Compare commits

...

71 Commits

Author SHA1 Message Date
Sebastián Ramírez
942fce394b 🔖 Release version 0.118.2 2025-10-08 16:49:59 +02:00
github-actions[bot]
13b067c9b6 📝 Update release notes
[skip ci]
2025-10-08 14:48:57 +00:00
François Voron
185cecd891 🐛 Fix tagged discriminated union not recognized as body field (#12942)
Co-authored-by: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com>
Co-authored-by: Patrick Arminio <patrick.arminio@gmail.com>
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2025-10-08 14:48:30 +00:00
github-actions[bot]
27c0f7e75f 📝 Update release notes
[skip ci]
2025-10-08 14:37:16 +00:00
dependabot[bot]
05dbfebce5 ⬆ Bump astral-sh/setup-uv from 6 to 7 (#14167)
Bumps [astral-sh/setup-uv](https://github.com/astral-sh/setup-uv) from 6 to 7.
- [Release notes](https://github.com/astral-sh/setup-uv/releases)
- [Commits](https://github.com/astral-sh/setup-uv/compare/v6...v7)

---
updated-dependencies:
- dependency-name: astral-sh/setup-uv
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-08 16:36:25 +02:00
Sebastián Ramírez
01be148429 🔖 Release version 0.118.1 2025-10-08 11:05:44 +02:00
github-actions[bot]
fca8564ea0 📝 Update release notes
[skip ci]
2025-10-08 09:03:50 +00:00
Sebastián Ramírez
485bfedf5d 🔨 Move local coverage logic to its own script (#14166) 2025-10-08 09:03:21 +00:00
github-actions[bot]
32b93b53fc 📝 Update release notes
[skip ci]
2025-10-08 08:58:49 +00:00
Colin Watson
c970d8a735 👽️ Ensure compatibility with Pydantic 2.12.0 (#14036)
Co-authored-by: Sofie Van Landeghem <svlandeg@users.noreply.github.com>
Co-authored-by: Victorien <65306057+Viicos@users.noreply.github.com>
Co-authored-by: svlandeg <svlandeg@github.com>
Co-authored-by: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com>
Co-authored-by: Patrick Arminio <patrick.arminio@gmail.com>
2025-10-08 10:57:37 +02:00
github-actions[bot]
22b38099ce 📝 Update release notes
[skip ci]
2025-10-07 15:05:44 +00:00
pre-commit-ci[bot]
bc5e877c9c ⬆ [pre-commit.ci] pre-commit autoupdate (#14161)
updates:
- [github.com/astral-sh/ruff-pre-commit: v0.13.2 → v0.13.3](https://github.com/astral-sh/ruff-pre-commit/compare/v0.13.2...v0.13.3)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2025-10-07 17:05:17 +02:00
github-actions[bot]
1cd8717818 📝 Update release notes
[skip ci]
2025-10-06 19:08:44 +00:00
Simon Gurcke
6df0358b80 📝 Add External Link: Getting started with logging in FastAPI (#14152)
Add logging article to External links
2025-10-06 21:08:20 +02:00
github-actions[bot]
56c0632f86 📝 Update release notes
[skip ci]
2025-10-06 11:10:19 +00:00
Sebastián Ramírez
61596ebe5b 🔨 Add Russian translations LLM prompt (#13936)
* 🔨 Add Russian translations LLM prompt

* 🔨 Tweak prompt with input from Yurii

* 📝 Update LLM prompt

* Update llm-prompt.md

* Update llm-prompt.md

* Update llm-prompt.md

* 🎨 [pre-commit.ci] Auto format from pre-commit.com hooks

* Update llm-prompt.md

* Update llm-prompt.md

* Update llm-prompt.md

* Update ru `llm-prompt.md`

---------

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 <yurii.motov.monte@gmail.com>
2025-10-06 13:09:58 +02:00
github-actions[bot]
e820049caa 📝 Update release notes
[skip ci]
2025-10-02 06:56:51 +00:00
dependabot[bot]
3e97c96b60 ⬆ Bump griffe-typingdoc from 0.2.8 to 0.2.9 (#14144)
Bumps [griffe-typingdoc](https://github.com/mkdocstrings/griffe-typingdoc) from 0.2.8 to 0.2.9.
- [Release notes](https://github.com/mkdocstrings/griffe-typingdoc/releases)
- [Changelog](https://github.com/mkdocstrings/griffe-typingdoc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/mkdocstrings/griffe-typingdoc/compare/0.2.8...0.2.9)

---
updated-dependencies:
- dependency-name: griffe-typingdoc
  dependency-version: 0.2.9
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-02 08:56:32 +02:00
github-actions[bot]
beef83d871 📝 Update release notes
[skip ci]
2025-10-02 06:46:36 +00:00
dependabot[bot]
d421feadf2 ⬆ Bump mkdocs-macros-plugin from 1.3.9 to 1.4.0 (#14145)
Bumps [mkdocs-macros-plugin](https://github.com/fralau/mkdocs_macros_plugin) from 1.3.9 to 1.4.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.3.9...v1.4.0)

---
updated-dependencies:
- dependency-name: mkdocs-macros-plugin
  dependency-version: 1.4.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-02 08:46:14 +02:00
github-actions[bot]
407a6a4a7c 📝 Update release notes
[skip ci]
2025-10-02 06:27:51 +00:00
dependabot[bot]
ece783d217 ⬆ Bump markdown-include-variants from 0.0.4 to 0.0.5 (#14146)
Bumps [markdown-include-variants](https://github.com/tiangolo/markdown-include-variants) from 0.0.4 to 0.0.5.
- [Release notes](https://github.com/tiangolo/markdown-include-variants/releases)
- [Changelog](https://github.com/tiangolo/markdown-include-variants/blob/main/release-notes.md)
- [Commits](https://github.com/tiangolo/markdown-include-variants/compare/0.0.4...0.0.5)

---
updated-dependencies:
- dependency-name: markdown-include-variants
  dependency-version: 0.0.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-02 08:27:21 +02:00
github-actions[bot]
45bfb89ea2 📝 Update release notes
[skip ci]
2025-10-01 16:44:12 +00:00
github-actions[bot]
6046849249 📝 Update release notes
[skip ci]
2025-10-01 16:43:50 +00:00
pre-commit-ci[bot]
597c2f42c6 ⬆ [pre-commit.ci] pre-commit autoupdate (#14126)
updates:
- [github.com/astral-sh/ruff-pre-commit: v0.13.1 → v0.13.2](https://github.com/astral-sh/ruff-pre-commit/compare/v0.13.1...v0.13.2)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2025-10-01 18:43:21 +02:00
Sebastián Ramírez
975e7190e4 👥 Update FastAPI GitHub topic repositories (#14150)
Co-authored-by: github-actions <github-actions@github.com>
2025-10-01 18:43:11 +02:00
github-actions[bot]
65b9bc24ef 📝 Update release notes
[skip ci]
2025-10-01 16:43:01 +00:00
github-actions[bot]
46b7bfc478 📝 Update release notes
[skip ci]
2025-10-01 16:42:56 +00:00
Sebastián Ramírez
28f910a10b 👥 Update FastAPI People - Sponsors (#14139)
Co-authored-by: github-actions <github-actions@github.com>
2025-10-01 18:42:38 +02:00
Sebastián Ramírez
9d920d616f 👥 Update FastAPI People - Contributors and Translators (#14138)
Co-authored-by: github-actions <github-actions@github.com>
2025-10-01 18:42:31 +02:00
github-actions[bot]
a2bde2b297 📝 Update release notes
[skip ci]
2025-10-01 15:50:23 +00:00
dependabot[bot]
69a69cc828 ⬆ Bump ruff from 0.12.7 to 0.13.2 (#14147)
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.12.7 to 0.13.2.
- [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.12.7...0.13.2)

---
updated-dependencies:
- dependency-name: ruff
  dependency-version: 0.13.2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-01 17:50:01 +02:00
github-actions[bot]
4f0d9d0cf1 📝 Update release notes
[skip ci]
2025-10-01 15:48:14 +00:00
dependabot[bot]
796601bddb ⬆ Bump sqlmodel from 0.0.24 to 0.0.25 (#14143)
Bumps [sqlmodel](https://github.com/fastapi/sqlmodel) from 0.0.24 to 0.0.25.
- [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.24...0.0.25)

---
updated-dependencies:
- dependency-name: sqlmodel
  dependency-version: 0.0.25
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-01 17:47:48 +02:00
github-actions[bot]
ef24ee4c39 📝 Update release notes
[skip ci]
2025-10-01 15:20:18 +00:00
Nils-Hero Lindemann
c623291929 🌐 Sync German docs (#14149)
* Sync German docs with #13917

Plus a typo fix in tutorial/security/oauth2-jwt.md line 89.

* Sync german docs with #14099

---------

Co-authored-by: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com>
2025-10-01 17:19:54 +02:00
github-actions[bot]
3a18a6d620 📝 Update release notes
[skip ci]
2025-10-01 13:26:33 +00:00
dependabot[bot]
90e567a6d9 ⬆ Bump tiangolo/issue-manager from 0.5.1 to 0.6.0 (#14148)
Bumps [tiangolo/issue-manager](https://github.com/tiangolo/issue-manager) from 0.5.1 to 0.6.0.
- [Release notes](https://github.com/tiangolo/issue-manager/releases)
- [Commits](https://github.com/tiangolo/issue-manager/compare/0.5.1...0.6.0)

---
updated-dependencies:
- dependency-name: tiangolo/issue-manager
  dependency-version: 0.6.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-01 15:26:11 +02:00
github-actions[bot]
a83a8e7a45 📝 Update release notes
[skip ci]
2025-09-30 11:37:34 +00:00
Motov Yurii
04d5e659bc 🌐 Add Russian translations for missing pages (LLM-generated) (#14135)
* Copy En pages

* Translate pages (reviewed and corrected)

* Apply changes from latest PRs: 13917 and 14099
2025-09-30 13:37:11 +02:00
github-actions[bot]
88a5554a44 📝 Update release notes
[skip ci]
2025-09-30 11:25:02 +00:00
Motov Yurii
977abe2396 🌐 Update Russian translations for existing pages (LLM-generated) (#14123)
* Update Russian translations for modified pages

* docs: fix translation for multiprocessing

* Update Russian translations for other existing pages

* Apply changes from latest PRs: 13917 and 14099

---------

Co-authored-by: vldmrdev <70532790+vldmrdev@users.noreply.github.com>
2025-09-30 13:24:39 +02:00
github-actions[bot]
3d70b26788 📝 Update release notes
[skip ci]
2025-09-30 06:26:25 +00:00
Sebastián Ramírez
e7fc394e15 🌐 Remove configuration files for inactive translations (#14130) 2025-09-30 08:25:57 +02:00
github-actions[bot]
3481aad827 📝 Update release notes
[skip ci]
2025-09-30 05:57:45 +00:00
Sebastián Ramírez
2f6fb12258 👷 Update docs previews comment, single comment, add failure status (#14129)
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2025-09-30 07:56:53 +02:00
github-actions[bot]
36a3830ba2 📝 Update release notes
[skip ci]
2025-09-30 04:07:18 +00:00
Motov Yurii
06367347e6 🔨 Modify mkdocs_hooks.py to add title to page's metadata (remove permalinks in social cards) (#14125) 2025-09-30 06:06:57 +02:00
Sebastián Ramírez
333f1ba737 🔖 Release version 0.118.0 2025-09-29 05:34:21 +02:00
Sebastián Ramírez
1d5168a4a1 📝 Update release notes 2025-09-29 05:33:39 +02:00
github-actions[bot]
bfa54b406d 📝 Update release notes
[skip ci]
2025-09-29 03:31:17 +00:00
Sebastián Ramírez
e329d78f86 🐛 Fix support for StreamingResponses with dependencies with yield or UploadFiles, close after the response is done (#14099)
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2025-09-29 05:29:38 +02:00
github-actions[bot]
861b22c408 📝 Update release notes
[skip ci]
2025-09-29 02:58:20 +00:00
Neizvestnyj
efdafa4361 📝 Update tutorial/security/oauth2-jwt/ to use pwdlib with Argon2 instead of passlib (#13917)
Co-authored-by: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com>
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2025-09-29 04:57:38 +02:00
github-actions[bot]
450a334253 📝 Update release notes
[skip ci]
2025-09-25 06:45:53 +00:00
alv2017
3eb2ee7510 ✏️ Fix typos in OAuth2 password request forms (#14112)
Fixed typos in OAuth2PasswordRequestForm and in OAuth2PasswordRequestFormStrict
2025-09-25 08:45:24 +02:00
github-actions[bot]
287eb316df 📝 Update release notes
[skip ci]
2025-09-24 08:10:57 +00:00
Nils-Hero Lindemann
cca3341cb9 🌐 Sync German docs (#14098)
* Sync German docs with #13510

* Sync German docs with #14059

---------

Co-authored-by: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com>
2025-09-24 10:10:28 +02:00
github-actions[bot]
f235502234 📝 Update release notes
[skip ci]
2025-09-22 19:30:48 +00:00
pre-commit-ci[bot]
b40da4f0d5 ⬆ [pre-commit.ci] pre-commit autoupdate (#14103)
updates:
- [github.com/astral-sh/ruff-pre-commit: v0.13.0 → v0.13.1](https://github.com/astral-sh/ruff-pre-commit/compare/v0.13.0...v0.13.1)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2025-09-22 21:30:27 +02:00
github-actions[bot]
9aa25fd682 📝 Update release notes
[skip ci]
2025-09-22 15:12:21 +00:00
Alejandra
8170860322 ♻️ Refactor sponsor image handling (#14102)
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2025-09-22 17:11:52 +02:00
github-actions[bot]
f0da082dd3 📝 Update release notes
[skip ci]
2025-09-21 14:11:44 +00:00
Alejandra
f97524429d 🐛 Fix sponsor display issue by hiding element on image error (#14097) 2025-09-21 14:11:11 +00:00
github-actions[bot]
6b1e6c5efd 📝 Update release notes
[skip ci]
2025-09-21 12:54:37 +00:00
Alejandra
40f3ab18e0 🐛 Hide sponsor badge when sponsor image is not displayed (#14096) 2025-09-21 14:54:15 +02:00
github-actions[bot]
8dfc651e1a 📝 Update release notes
[skip ci]
2025-09-21 11:29:24 +00:00
Alejandra
2eca83fbda 📝 Update contributing guidelines for installing requirements (#14095) 2025-09-21 13:29:04 +02:00
Sebastián Ramírez
784f06cb9b 🔖 Release version 0.117.1 2025-09-20 22:15:41 +02:00
github-actions[bot]
b5c05893b4 📝 Update release notes
[skip ci]
2025-09-20 19:56:30 +00:00
Thomas LÉVEIL
44fc67632b 🐛 Fix validation error when File is declared after Form parameter (#11194)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2025-09-20 21:55:59 +02:00
221 changed files with 10745 additions and 12503 deletions

View File

@@ -40,6 +40,7 @@ jobs:
- mkdocs.no-insiders.yml
- .github/workflows/build-docs.yml
- .github/workflows/deploy-docs.yml
- scripts/mkdocs_hooks.py
langs:
needs:
- changes
@@ -53,7 +54,7 @@ jobs:
with:
python-version: "3.11"
- name: Setup uv
uses: astral-sh/setup-uv@v6
uses: astral-sh/setup-uv@v7
with:
version: "0.4.15"
enable-cache: true
@@ -95,7 +96,7 @@ jobs:
with:
python-version: "3.11"
- name: Setup uv
uses: astral-sh/setup-uv@v6
uses: astral-sh/setup-uv@v7
with:
version: "0.4.15"
enable-cache: true

View File

@@ -30,7 +30,7 @@ jobs:
with:
python-version: "3.11"
- name: Setup uv
uses: astral-sh/setup-uv@v6
uses: astral-sh/setup-uv@v7
with:
version: "0.4.15"
enable-cache: true

View File

@@ -29,7 +29,7 @@ jobs:
with:
python-version: "3.11"
- name: Setup uv
uses: astral-sh/setup-uv@v6
uses: astral-sh/setup-uv@v7
with:
version: "0.4.15"
enable-cache: true
@@ -44,6 +44,7 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
COMMIT_SHA: ${{ github.event.workflow_run.head_sha }}
RUN_ID: ${{ github.run_id }}
STATE: "pending"
- name: Clean site
run: |
rm -rf ./site
@@ -67,6 +68,14 @@ jobs:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
command: pages deploy ./site --project-name=${{ env.PROJECT_NAME }} --branch=${{ env.BRANCH }}
- name: Deploy Docs Status Error
if: failure()
run: python ./scripts/deploy_docs_status.py
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
COMMIT_SHA: ${{ github.event.workflow_run.head_sha }}
RUN_ID: ${{ github.run_id }}
STATE: "error"
- name: Comment Deploy
run: python ./scripts/deploy_docs_status.py
env:
@@ -74,4 +83,4 @@ jobs:
DEPLOY_URL: ${{ steps.deploy.outputs.deployment-url }}
COMMIT_SHA: ${{ github.event.workflow_run.head_sha }}
RUN_ID: ${{ github.run_id }}
IS_DONE: "true"
STATE: "success"

View File

@@ -27,7 +27,7 @@ jobs:
env:
GITHUB_CONTEXT: ${{ toJson(github) }}
run: echo "$GITHUB_CONTEXT"
- uses: tiangolo/issue-manager@0.5.1
- uses: tiangolo/issue-manager@0.6.0
with:
token: ${{ secrets.GITHUB_TOKEN }}
config: >

View File

@@ -26,7 +26,7 @@ jobs:
with:
python-version: "3.11"
- name: Setup uv
uses: astral-sh/setup-uv@v6
uses: astral-sh/setup-uv@v7
with:
version: "0.4.15"
enable-cache: true

View File

@@ -34,7 +34,7 @@ jobs:
with:
python-version: "3.11"
- name: Setup uv
uses: astral-sh/setup-uv@v6
uses: astral-sh/setup-uv@v7
with:
version: "0.4.15"
enable-cache: true

View File

@@ -30,7 +30,7 @@ jobs:
with:
python-version: "3.11"
- name: Setup uv
uses: astral-sh/setup-uv@v6
uses: astral-sh/setup-uv@v7
with:
version: "0.4.15"
enable-cache: true

View File

@@ -26,7 +26,7 @@ jobs:
with:
python-version: '3.9'
- name: Setup uv
uses: astral-sh/setup-uv@v6
uses: astral-sh/setup-uv@v7
with:
version: "0.4.15"
enable-cache: true

View File

@@ -30,7 +30,7 @@ jobs:
with:
python-version: "3.11"
- name: Setup uv
uses: astral-sh/setup-uv@v6
uses: astral-sh/setup-uv@v7
with:
version: "0.4.15"
enable-cache: true

View File

@@ -29,7 +29,7 @@ jobs:
with:
python-version: "3.11"
- name: Setup uv
uses: astral-sh/setup-uv@v6
uses: astral-sh/setup-uv@v7
with:
version: "0.4.15"
enable-cache: true
@@ -67,7 +67,7 @@ jobs:
with:
python-version: ${{ matrix.python-version }}
- name: Setup uv
uses: astral-sh/setup-uv@v6
uses: astral-sh/setup-uv@v7
with:
version: "0.4.15"
enable-cache: true
@@ -112,7 +112,7 @@ jobs:
with:
python-version: '3.8'
- name: Setup uv
uses: astral-sh/setup-uv@v6
uses: astral-sh/setup-uv@v7
with:
version: "0.4.15"
enable-cache: true

View File

@@ -25,7 +25,7 @@ jobs:
with:
python-version: "3.11"
- name: Setup uv
uses: astral-sh/setup-uv@v6
uses: astral-sh/setup-uv@v7
with:
version: "0.4.15"
enable-cache: true

View File

@@ -48,7 +48,7 @@ jobs:
with:
python-version: "3.11"
- name: Setup uv
uses: astral-sh/setup-uv@v6
uses: astral-sh/setup-uv@v7
with:
version: "0.4.15"
enable-cache: true

View File

@@ -14,7 +14,7 @@ repos:
- id: end-of-file-fixer
- id: trailing-whitespace
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.13.0
rev: v0.13.3
hooks:
- id: ruff
args:

View File

@@ -1,467 +0,0 @@
<p align="center">
<a href="https://fastapi.tiangolo.com"><img src="https://fastapi.tiangolo.com/img/logo-margin/logo-teal.png" alt="FastAPI"></a>
</p>
<p align="center">
<em>FastAPI framework, yüksək məshuldarlı, öyrənməsi asan, çevik kodlama, istifadəyə hazırdır</em>
</p>
<p align="center">
<a href="https://github.com/fastapi/fastapi/actions?query=workflow%3ATest+event%3Apush+branch%3Amaster" target="_blank">
<img src="https://github.com/fastapi/fastapi/actions/workflows/test.yml/badge.svg?event=push&branch=master" alt="Test">
</a>
<a href="https://coverage-badge.samuelcolvin.workers.dev/redirect/fastapi/fastapi" target="_blank">
<img src="https://coverage-badge.samuelcolvin.workers.dev/fastapi/fastapi.svg" alt="Əhatə">
</a>
<a href="https://pypi.org/project/fastapi" target="_blank">
<img src="https://img.shields.io/pypi/v/fastapi?color=%2334D058&label=pypi%20package" alt="Paket versiyası">
</a>
<a href="https://pypi.org/project/fastapi" target="_blank">
<img src="https://img.shields.io/pypi/pyversions/fastapi.svg?color=%2334D058" alt="Dəstəklənən Python versiyaları">
</a>
</p>
---
**Sənədlər**: <a href="https://fastapi.tiangolo.com" target="_blank">https://fastapi.tiangolo.com</a>
**Qaynaq Kodu**: <a href="https://github.com/fastapi/fastapi" target="_blank">https://github.com/fastapi/fastapi</a>
---
FastAPI Python ilə API yaratmaq üçün standart Python <abbr title="Tip Məsləhətləri: Type Hints">tip məsləhətlərinə</abbr> əsaslanan, müasir, sürətli (yüksək performanslı) framework-dür.
Əsas xüsusiyyətləri bunlardır:
* **Sürətli**: Çox yüksək performans, **NodeJS****Go** səviyyəsində (Starlette və Pydantic-ə təşəkkürlər). [Ən sürətli Python frameworklərindən biridir](#performans).
* **Çevik kodlama**: Funksiyanallıqları inkişaf etdirmək sürətini təxminən 200%-dən 300%-ə qədər artırın. *
* **Daha az xəta**: İnsan (developer) tərəfindən törədilən səhvlərin təxminən 40% -ni azaldın. *
* **İntuitiv**: Əla redaktor dəstəyi. Hər yerdə <abbr title="auto-complete, autocompletion, IntelliSense olaraq da bilinir">otomatik tamamlama</abbr>. Xətaları müəyyənləşdirməyə daha az vaxt sərf edəcəksiniz.
* **Asan**: İstifadəsi və öyrənilməsi asan olması üçün nəzərdə tutulmuşdur. Sənədləri oxumaq üçün daha az vaxt ayıracaqsınız.
* **Qısa**: Kod təkrarlanmasını minimuma endirin. Hər bir parametr tərifində birdən çox xüsusiyyət ilə və daha az səhvlə qarşılaşacaqsınız.
* **Güclü**: Avtomatik və interaktiv sənədlərlə birlikdə istifadəyə hazır kod əldə edə bilərsiniz.
* **Standartlara əsaslanan**: API-lar üçün açıq standartlara əsaslanır (və tam uyğun gəlir): <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank">OpenAPI</a> (əvvəlki adı ilə Swagger) və <a href="https://json-schema.org/" class="external-link" target="_blank">JSON Schema</a>.
<small>* Bu fikirlər daxili development komandasının hazırladıqları məhsulların sınaqlarına əsaslanır.</small>
## Sponsorlar
<!-- sponsors -->
{% if sponsors %}
{% for sponsor in sponsors.gold -%}
<a href="{{ sponsor.url }}" target="_blank" title="{{ sponsor.title }}"><img src="{{ sponsor.img }}" style="border-radius:15px"></a>
{% endfor -%}`
{%- for sponsor in sponsors.silver -%}
<a href="{{ sponsor.url }}" target="_blank" title="{{ sponsor.title }}"><img src="{{ sponsor.img }}" style="border-radius:15px"></a>
{% endfor %}
{% endif %}
<!-- /sponsors -->
<a href="https://fastapi.tiangolo.com/az/fastapi-people/#sponsors" class="external-link" target="_blank">Digər sponsorlar</a>
## Rəylər
"_[...] Son günlərdə **FastAPI**-ı çox istifadə edirəm. [...] Əslində onu komandamın bütün **Microsoftda ML sevislərində** istifadə etməyi planlayıram. Onların bəziləri **windows**-un əsas məhsuluna və bəzi **Office** məhsullarına inteqrasiya olunurlar._"
<div style="text-align: right; margin-right: 10%;">Kabir Khan - <strong>Microsoft</strong> <a href="https://github.com/fastapi/fastapi/pull/26" target="_blank"><small>(ref)</small></a></div>
---
"_**FastAPI** kitabxanasını **Proqnozlar** əldə etmək üçün sorğulana bilən **REST** serverini yaratmaqda istifadə etdik._"
<div style="text-align: right; margin-right: 10%;">Piero Molino, Yaroslav Dudin, and Sai Sumanth Miryala - <strong>Uber</strong> <a href="https://eng.uber.com/ludwig-v0-2/" target="_blank"><small>(ref)</small></a></div>
---
"_**Netflix** **böhran idarəçiliyi** orkestrləşmə framework-nün açıq qaynaqlı buraxılışını elan etməkdən məmnundur: **Dispatch**! [**FastAPI** ilə quruldu]_"
<div style="text-align: right; margin-right: 10%;">Kevin Glisson, Marc Vilanova, Forest Monsen - <strong>Netflix</strong> <a href="https://netflixtechblog.com/introducing-dispatch-da4b8a2a8072" target="_blank"><small>(ref)</small></a></div>
---
"_**FastAPI** üçün həyəcanlıyam. Çox əyləncəlidir!_"
<div style="text-align: right; margin-right: 10%;">Brian Okken - <strong><a href="https://pythonbytes.fm/episodes/show/123/time-to-right-the-py-wrongs?time_in_sec=855" target="_blank">Python Bytes</a> podcast host</strong> <a href="https://x.com/brianokken/status/1112220079972728832" target="_blank"><small>(ref)</small></a></div>
---
"_Düzünü desəm, sizin qurduğunuz şey həqiqətən möhkəm və peşəkar görünür. Bir çox cəhətdən **Hug**-un olmasını istədiyim kimdir - kiminsə belə bir şey qurduğunu görmək həqiqətən ruhlandırıcıdır._"
<div style="text-align: right; margin-right: 10%;">Timothy Crosley - <strong><a href="https://github.com/hugapi/hug" target="_blank">Hug</a> creator</strong> <a href="https://news.ycombinator.com/item?id=19455465" target="_blank"><small>(ref)</small></a></div>
---
"_Əgər REST API-lər yaratmaq üçün **müasir framework** öyrənmək istəyirsinizsə, **FastAPI**-a baxın [...] Sürətli, istifadəsi və öyrənməsi asandır. [...]_"
"_**API** xidmətlərimizi **FastAPI**-a köçürdük [...] Sizin də bəyənəcəyinizi düşünürük._"
<div style="text-align: right; margin-right: 10%;">Ines Montani - Matthew Honnibal - <strong><a href="https://explosion.ai" target="_blank">Explosion AI</a> founders - <a href="https://spacy.io" target="_blank">spaCy</a> creators</strong> <a href="https://x.com/_inesmontani/status/1144173225322143744" target="_blank"><small>(ref)</small></a> - <a href="https://x.com/honnibal/status/1144031421859655680" target="_blank"><small>(ref)</small></a></div>
---
"_Python ilə istifadəyə hazır API qurmaq istəyən hər kəsə **FastAPI**-ı tövsiyə edirəm. **Möhtəşəm şəkildə dizayn edilmiş**, **istifadəsi asan** və **yüksək dərəcədə genişlənə bilən**-dir, API əsaslı inkişaf strategiyamızın **əsas komponentinə** çevrilib və Virtual TAC Engineer kimi bir çox avtomatlaşdırma və servisləri idarə edir._"
<div style="text-align: right; margin-right: 10%;">Deon Pillsbury - <strong>Cisco</strong> <a href="https://www.linkedin.com/posts/deonpillsbury_cisco-cx-python-activity-6963242628536487936-trAp/" target="_blank"><small>(ref)</small></a></div>
---
## **Typer**, CLI-ların FastAPI-ı
<a href="https://typer.tiangolo.com" target="_blank"><img src="https://typer.tiangolo.com/img/logo-margin/logo-margin-vector.svg" style="width: 20%;"></a>
Əgər siz veb API əvəzinə terminalda istifadə ediləcək <abbr title="Command Line Interface">CLI</abbr> proqramı qurursunuzsa, <a href="https://typer.tiangolo.com/" class="external-link" target="_blank">**Typer**</a>-a baxa bilərsiniz.
**Typer** FastAPI-ın kiçik qardaşıdır. Və o, CLI-lərin **FastAPI**-ı olmaq üçün nəzərdə tutulub. ⌨️ 🚀
## Tələblər
FastAPI nəhənglərin çiyinlərində dayanır:
* Web tərəfi üçün <a href="https://www.starlette.io/" class="external-link" target="_blank">Starlette</a>.
* Data tərəfi üçün <a href="https://docs.pydantic.dev/" class="external-link" target="_blank">Pydantic</a>.
## Quraşdırma
<div class="termy">
```console
$ pip install fastapi
---> 100%
```
</div>
Tətbiqimizi əlçatan etmək üçün bizə <a href="https://www.uvicorn.org" class="external-link" target="_blank">Uvicorn</a> və ya <a href="https://github.com/pgjones/hypercorn" class="external-link" target="_blank">Hypercorn</a> kimi ASGI server lazımdır.
<div class="termy">
```console
$ pip install "uvicorn[standard]"
---> 100%
```
</div>
## Nümunə
### Kodu yaradaq
* `main.py` adlı fayl yaradaq və ona aşağıdakı kodu yerləşdirək:
```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}
```
<details markdown="1">
<summary>Və ya <code>async def</code>...</summary>
Əgər kodunuzda `async` və ya `await` vardırsa `async def` istifadə edə bilərik:
```Python hl_lines="9 14"
from typing import Union
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
async def read_root():
return {"Hello": "World"}
@app.get("/items/{item_id}")
async def read_item(item_id: int, q: Union[str, None] = None):
return {"item_id": item_id, "q": q}
```
**Qeyd**:
Əgər bu mövzu haqqında məlumatınız yoxdursa <a href="https://fastapi.tiangolo.com/az/async/#in-a-hurry" target="_blank">`async` və `await` sənədindəki</a> _"Tələsirsən?"_ bölməsinə baxa bilərsiniz.
</details>
### Kodu işə salaq
Serveri aşağıdakı əmr ilə işə salaq:
<div class="termy">
```console
$ uvicorn main:app --reload
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.
```
</div>
<details markdown="1">
<summary><code>uvicorn main:app --reload</code> əmri haqqında...</summary>
`uvicorn main:app` əmri aşağıdakılara instinad edir:
* `main`: `main.py` faylı (yəni Python "modulu").
* `app`: `main.py` faylında `app = FastAPI()` sətrində yaratdığımız `FastAPI` obyektidir.
* `--reload`: kod dəyişikliyindən sonra avtomatik olaraq serveri yenidən işə salır. Bu parametrdən yalnız development mərhələsində istifadə etməliyik.
</details>
### İndi yoxlayaq
Bu linki brauzerimizdə açaq <a href="http://127.0.0.1:8000/items/5?q=somequery" class="external-link" target="_blank">http://127.0.0.1:8000/items/5?q=somequery</a>.
Aşağıdakı kimi bir JSON cavabı görəcəksiniz:
```JSON
{"item_id": 5, "q": "somequery"}
```
Siz artıq bir API yaratmısınız, hansı ki:
* `/` və `/items/{item_id}` <abbr title="Yol: Path ">_yollarında_</abbr> HTTP sorğularını qəbul edir.
* Hər iki _yolda_ `GET` <em>əməliyyatlarını</em> (həmçinin HTTP _metodları_ kimi bilinir) aparır.
* `/items/{item_id}` _yolu_ `item_id` adlı `int` qiyməti almalı olan _yol parametrinə_ sahibdir.
* `/items/{item_id}` _yolunun_ `q` adlı yol parametri var və bu parametr istəyə bağlı olsa da, `str` qiymətini almalıdır.
### İnteraktiv API Sənədləri
İndi <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a> ünvanına daxil olun.
Avtomatik interaktiv API sənədlərini görəcəksiniz (<a href="https://github.com/swagger-api/swagger-ui" class="external-link" target="_blank">Swagger UI</a> tərəfindən təmin edilir):
![Swagger UI](https://fastapi.tiangolo.com/img/index/index-01-swagger-ui-simple.png)
### Alternativ API sənədləri
İndi isə <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a> ünvanına daxil olun.
<a href="https://github.com/Rebilly/ReDoc" class="external-link" target="_blank">ReDoc</a> tərəfindən təqdim edilən avtomatik sənədləri görəcəksiniz:
![ReDoc](https://fastapi.tiangolo.com/img/index/index-02-redoc-simple.png)
## Nümunəni Yeniləyək
İndi gəlin `main.py` faylını `PUT` sorğusu ilə birlikdə <abbr title="Gövdə: Body ">gövdə</abbr> qəbul edəcək şəkildə dəyişdirək.
Pydantic sayəsində standart Python tiplərindən istifadə edərək <abbr title="Gövdə: Body ">gövdə</abbr>ni müəyyən edək.
```Python hl_lines="4 9-12 25-27"
from typing import Union
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
price: float
is_offer: Union[bool, None] = None
@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}
@app.put("/items/{item_id}")
def update_item(item_id: int, item: Item):
return {"item_name": item.name, "item_id": item_id}
```
Server avtomatik olaraq yenidən işə salınmalı idi (çünki biz yuxarıda `uvicorn` əmri ilə `--reload` parametrindən istifadə etmişik).
### İnteraktiv API sənədlərindəki dəyişikliyə baxaq
Yenidən <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a> ünvanına daxil olun.
* İnteraktiv API sənədləri yeni gövdə də daxil olmaq ilə avtomatik olaraq yenilənəcək:
![Swagger UI](https://fastapi.tiangolo.com/img/index/index-03-swagger-02.png)
* "Try it out" düyməsini klikləyin, bu, parametrləri doldurmağa və API ilə birbaşa əlaqə saxlamağa imkan verir:
![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-04-swagger-03.png)
* Sonra "Execute" düyməsini klikləyin, istifadəçi interfeysi API ilə əlaqə quracaq, parametrləri göndərəcək, nəticələri əldə edəcək və onları ekranda göstərəcək:
![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-05-swagger-04.png)
### Alternativ API Sənədlərindəki Dəyişikliyə Baxaq
İndi isə yenidən <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a> ünvanına daxil olun.
* Alternativ sənədlər həm də yeni sorğu parametri və gövdəsini əks etdirəcək:
![ReDoc](https://fastapi.tiangolo.com/img/index/index-06-redoc-02.png)
### Xülasə
Ümumiləşdirsək, parametrlər, gövdə və s. Biz məlumat növlərini **bir dəfə** funksiya parametrləri kimi təyin edirik.
Bunu standart müasir Python tipləri ilə edirsiniz.
Yeni sintaksis, müəyyən bir kitabxananın metodlarını və ya siniflərini və s. öyrənmək məcburiyyətində deyilsiniz.
Sadəcə standart **Python**.
Məsələn, `int` üçün:
```Python
item_id: int
```
və ya daha mürəkkəb `Item` modeli üçün:
```Python
item: Item
```
...və yalnız parametr tipini təyin etməklə bunları əldə edirsiniz:
* Redaktor dəstəyi ilə:
* Avtomatik tamamlama.
* Tip yoxlanması.
* Məlumatların Təsdiqlənməsi:
* Məlumat etibarsız olduqda avtomatik olaraq aydın xətalar göstərir.
* Hətta çox dərin JSON obyektlərində belə doğrulama aparır.
* Daxil olan məlumatları <abbr title="Çevrilmə: serialization, parsing, marshalling olaraq da bilinir">çevirmək</abbr> üçün aşağıdakı məlumat növlərindən istifadə edilir:
* JSON.
* <abbr title="Yol: Path">Yol</abbr> parametrləri.
* <abbr title="Sorğu: Query">Sorğu</abbr> parametrləri.
* <abbr title="Çərəz: Cookie">Çərəzlər</abbr>.
* <abbr title="Başlıq: Header">Başlıqlaq</abbr>.
* <abbr title="Forma: Form">Formalar</abbr>.
* Fayllar.
* Daxil olan məlumatları <abbr title="Çevrilmə: serialization, parsing, marshalling olaraq da bilinir">çevirmək</abbr> üçün aşağıdakı məlumat növlərindən istifadə edilir (JSON olaraq):
* Python tiplərinin (`str`, `int`, `float`, `bool`, `list`, və s) çevrilməsi.
* `datetime` obyektləri.
* `UUID` obyektləri.
* Verilənlər bazası modelləri.
* və daha çoxu...
* 2 alternativ istifadəçi interfeysi daxil olmaqla avtomatik interaktiv API sənədlərini təmin edir:
* Swagger UI.
* ReDoc.
---
Gəlin əvvəlki nümunəyə qayıdaq və **FastAPI**-nin nələr edəcəyinə nəzər salaq:
* `GET` və `PUT` sorğuları üçün `item_id`-nin <abbr title="Yol: Path">yolda</abbr> olub-olmadığını yoxlayacaq.
* `item_id`-nin `GET` və `PUT` sorğuları üçün növünün `int` olduğunu yoxlayacaq.
* Əgər `int` deyilsə, səbəbini göstərən bir xəta mesajı göstərəcəkdir.
* <abbr title="Məcburi olmayan: Optional">məcburi olmayan</abbr> `q` parametrinin `GET` (`http://127.0.0.1:8000/items/foo?q=somequery` burdakı kimi) sorğusu içərisində olub olmadığını yoxlayacaq.
* `q` parametrini `= None` ilə yaratdığımız üçün, <abbr title="Məcburi olmayan: Optional">məcburi olmayan</abbr> parametr olacaq.
* Əgər `None` olmasaydı, bu məcburi parametr olardı (`PUT` metodunun gövdəsində olduğu kimi).
* `PUT` sorğusu üçün, `/items/{item_id}` gövdəsini JSON olaraq oxuyacaq:
* `name` adında məcburi bir parametr olub olmadığını və əgər varsa, tipinin `str` olub olmadığını yoxlayacaq.
* `price` adında məcburi bir parametr olub olmadığını və əgər varsa, tipinin `float` olub olmadığını yoxlayacaq.
* `is_offer` adında <abbr title="Məcburi olmayan: Optional">məcburi olmayan</abbr> bir parametr olub olmadığını və əgər varsa, tipinin `float` olub olmadığını yoxlayacaq.
* Bütün bunlar ən dərin JSON obyektlərində belə işləyəcək.
* Məlumatların JSON-a və JSON-un Python obyektinə çevrilməsi avtomatik həyata keçiriləcək.
* Hər şeyi OpenAPI ilə uyğun olacaq şəkildə avtomatik olaraq sənədləşdirəcək və onları aşağıdakı kimi istifadə edə biləcək:
* İnteraktiv sənədləşmə sistemləri.
* Bir çox proqramlaşdırma dilləri üçün avtomatlaşdırılmış <abbr title="Müştəri: Client">müştəri</abbr> kodu yaratma sistemləri.
* 2 interaktiv sənədləşmə veb interfeysini birbaşa təmin edəcək.
---
Yeni başlamışıq, amma siz artıq işin məntiqini başa düşmüsünüz.
İndi aşağıdakı sətri dəyişdirməyə çalışın:
```Python
return {"item_name": item.name, "item_id": item_id}
```
...bundan:
```Python
... "item_name": item.name ...
```
...buna:
```Python
... "item_price": item.price ...
```
...və redaktorun məlumat tiplərini bildiyini və avtomatik tamaladığını görəcəksiniz:
![editor support](https://fastapi.tiangolo.com/img/vscode-completion.png)
Daha çox funksiyaya malik daha dolğun nümunə üçün <a href="https://fastapi.tiangolo.com/az/tutorial/">Öyrədici - İstifadəçi Təlimatı</a> səhifəsinə baxa bilərsiniz.
**Spoiler xəbərdarlığı**: Öyrədici - istifadəçi təlimatına bunlar daxildir:
* **Parametrlərin**, <abbr title="Başlıq: Header">**başlıqlar**</abbr>, <abbr title="Çərəz: Cookie">çərəzlər</abbr>, **forma sahələri** və **fayllar** olaraq müəyyən edilməsi.
* `maximum_length` və ya `regex` kimi **doğrulama məhdudiyyətlərinin** necə təyin ediləcəyi.
* Çox güclü və istifadəsi asan **<abbr title="components, resources, providers, services, injectables olaraq da bilinir">Dependency Injection</abbr>** sistemi.
* Təhlükəsizlik və autentifikasiya, **JWT tokenləri** ilə **OAuth2** dəstəyi və **HTTP Basic** autentifikasiyası.
* **çox dərin JSON modellərini** müəyyən etmək üçün daha irəli səviyyə (lakin eyni dərəcədə asan) üsullar (Pydantic sayəsində).
* <a href="https://strawberry.rocks" class="external-link" target="_blank">Strawberry</a> və digər kitabxanalar ilə **GraphQL** inteqrasiyası.
* Digər əlavə xüsusiyyətlər (Starlette sayəsində):
* **WebSockets**
* HTTPX və `pytest` sayəsində çox asan testlər
* **CORS**
* **Cookie Sessions**
* ...və daha çoxu.
## Performans
Müstəqil TechEmpower meyarları göstərir ki, Uvicorn üzərində işləyən **FastAPI** proqramları <a href="https://www.techempower.com/benchmarks/#section=test&runid=7464e520-0dc2-473d-bd34-dbdfd7e85911&hw=ph&test=query&l=zijzen-7" class="external-link" target="_blank">ən sürətli Python kitabxanalarından biridir</a>, yalnız Starlette və Uvicorn-un özündən yavaşdır, ki FastAPI bunların üzərinə qurulmuş bir framework-dür. (*)
Ətraflı məlumat üçün bu bölməyə nəzər salın <a href="https://fastapi.tiangolo.com/az/benchmarks/" class="internal-link" target="_blank"><abbr title="Müqayisələr: Benchmarks">Müqayisələr</abbr></a>.
## Məcburi Olmayan Tələblər
Pydantic tərəfindən istifadə olunanlar:
* <a href="https://github.com/JoshData/python-email-validator" target="_blank"><code>email-validator</code></a> - e-poçtun yoxlanılması üçün.
* <a href="https://docs.pydantic.dev/latest/usage/pydantic_settings/" target="_blank"><code>pydantic-settings</code></a> - parametrlərin idarə edilməsi üçün.
* <a href="https://docs.pydantic.dev/latest/usage/types/extra_types/extra_types/" target="_blank"><code>pydantic-extra-types</code></a> - Pydantic ilə istifadə edilə bilən əlavə tiplər üçün.
Starlette tərəfindən istifadə olunanlar:
* <a href="https://www.python-httpx.org" target="_blank"><code>httpx</code></a> - Əgər `TestClient` strukturundan istifadə edəcəksinizsə, tələb olunur.
* <a href="https://jinja.palletsprojects.com" target="_blank"><code>jinja2</code></a> - Standart <abbr title="Şablon: Template">şablon</abbr> konfiqurasiyasından istifadə etmək istəyirsinizsə, tələb olunur.
* <a href="https://github.com/Kludex/python-multipart" target="_blank"><code>python-multipart</code></a> - `request.form()` ilə forma <abbr title="HTTP sorğusu ilə alınan string məlumatın Python obyektinə çevrilməsi">"çevirmə"</abbr> dəstəyindən istifadə etmək istəyirsinizsə, tələb olunur.
* <a href="https://pythonhosted.org/itsdangerous/" target="_blank"><code>itsdangerous</code></a> - `SessionMiddleware` dəstəyi üçün tələb olunur.
* <a href="https://pyyaml.org/wiki/PyYAMLDocumentation" target="_blank"><code>pyyaml</code></a> - `SchemaGenerator` dəstəyi üçün tələb olunur (Çox güman ki, FastAPI istifadə edərkən buna ehtiyacınız olmayacaq).
* <a href="https://github.com/esnme/ultrajson" target="_blank"><code>ujson</code></a> - `UJSONResponse` istifadə etmək istəyirsinizsə, tələb olunur.
Həm FastAPI, həm də Starlette tərəfindən istifadə olunur:
* <a href="https://www.uvicorn.org" target="_blank"><code>uvicorn</code></a> - Yaratdığımız proqramı servis edəcək veb server kimi fəaliyyət göstərir.
* <a href="https://github.com/ijl/orjson" target="_blank"><code>orjson</code></a> - `ORJSONResponse` istifadə edəcəksinizsə tələb olunur.
Bütün bunları `pip install fastapi[all]` ilə quraşdıra bilərsiniz.
## Lisenziya
Bu layihə MIT lisenziyasının şərtlərinə əsasən lisenziyalaşdırılıb.

View File

@@ -1,5 +0,0 @@
# Öyrən
Burada **FastAPI** öyrənmək üçün giriş bölmələri və dərsliklər yer alır.
Siz bunu kitab, kurs, FastAPI öyrənmək üçün rəsmi və tövsiyə olunan üsul hesab edə bilərsiniz. 😎

View File

@@ -1 +0,0 @@
INHERIT: ../en/mkdocs.yml

View File

@@ -1,3 +0,0 @@
# সম্পর্কে
**FastAPI** সম্পর্কে বিস্তারিত — এর ডিজাইন, অনুপ্রেরণা ও আরও অনেক কিছু। 🤓

View File

@@ -1,298 +0,0 @@
# এনভায়রনমেন্ট ভেরিয়েবলস
/// tip
আপনি যদি "এনভায়রনমেন্ট ভেরিয়েবলস" কী এবং সেগুলো কীভাবে ব্যবহার করতে হয় সেটা জানেন, তাহলে এই অংশটি স্কিপ করে যেতে পারেন।
///
এনভায়রনমেন্ট ভেরিয়েবল (সংক্ষেপে "**env var**" নামেও পরিচিত) হলো এমন একটি ভেরিয়েবল যা পাইথন কোডের **বাইরে**, **অপারেটিং সিস্টেমে** থাকে এবং আপনার পাইথন কোড (বা অন্যান্য প্রোগ্রাম) দ্বারা যাকে রিড করা যায়।
এনভায়রনমেন্ট ভেরিয়েবলস অ্যাপ্লিকেশনের **সেটিংস** পরিচালনা করতে, পাইথনের **ইনস্টলেশন** প্রক্রিয়ার অংশ হিসেবে, ইত্যাদি কাজে উপযোগী হতে পারে।
## Env Vars তৈরী এবং ব্যবহার
আপনি **শেল (টার্মিনাল)**-এ, পাইথনের প্রয়োজন ছাড়াই, এনভায়রনমেন্ট ভেরিয়েবলস **তৈরি** এবং ব্যবহার করতে পারবেনঃ
//// tab | লিনাক্স, ম্যাকওএস, উইন্ডোজ Bash
<div class="termy">
```console
// আপনি চাইলে MY_NAME নামে একটি env var তৈরি করতে পারেন
$ export MY_NAME="Wade Wilson"
// তারপরে এটিকে চাইলে অন্যান্য প্রোগ্রামে ব্যবহার করতে পারেন
$ echo "Hello $MY_NAME"
Hello Wade Wilson
```
</div>
////
//// tab | উইন্ডোজ পাওয়ারশেল
<div class="termy">
```console
// MY_NAME নামে env var তৈরি
$ $Env:MY_NAME = "Wade Wilson"
// অন্যান্য প্রোগ্রামে এটিকে ব্যবহার
$ echo "Hello $Env:MY_NAME"
Hello Wade Wilson
```
</div>
////
## পাইথনে env vars রিড করা
আপনি চাইলে পাইথনের **বাইরে**, টার্মিনালে (বা অন্য কোনো উপায়ে) এনভায়রনমেন্ট ভেরিয়েবলস তৈরি করতে পারেন, এবং পরে সেগুলো **পাইথনে রিড** (অ্যাক্সেস করতে) পারেন।
উদাহরণস্বরূপ, আপনার `main.py` নামে একটি ফাইল থাকতে পারেঃ
```Python hl_lines="3"
import os
name = os.getenv("MY_NAME", "World")
print(f"Hello {name} from Python")
```
/// tip
<a href="https://docs.python.org/3.8/library/os.html#os.getenv" class="external-link" target="_blank">`os.getenv()`</a> এর দ্বিতীয় আর্গুমেন্টটি হলো এর ডিফল্ট ভ্যালু যা রিটার্ন করা হবে।
যদি এটি দেওয়া না হয়, ডিফল্টভাবে `None` ব্যবহৃত হবে, এখানে আমরা ডিফল্ট ভ্যালু হিসেবে `"World"` ব্যবহার করেছি।
///
তারপরে পাইথন প্রোগ্রামটিকে নিম্নোক্তভাবে কল করা যাবেঃ
//// tab | লিনাক্স, ম্যাকওএস, উইন্ডোজ Bash
<div class="termy">
```console
// এখনো আমরা এনভায়রনমেন্ট ভেরিয়েবল সেট করিনি
$ python main.py
// যেহেতু env var সেট করা হয়নি, তাই আমরা ডিফল্ট ভ্যালু পাচ্ছি
Hello World from Python
// কিন্তু আমরা প্রথমে যদি একটা এনভায়রনমেন্ট ভারিয়েবল তৈরি করে নেই
$ export MY_NAME="Wade Wilson"
// এবং তারপর আবার প্রোগ্রাটিকে কল করি
$ python main.py
// এখন এটি এনভায়রনমেন্ট ভেরিয়েবল রিড করতে পারবে
Hello Wade Wilson from Python
```
</div>
////
//// tab | উইন্ডোজ পাওয়ারশেল
<div class="termy">
```console
// এখনো আমরা এনভায়রনমেন্ট ভেরিয়েবল সেট করিনি
$ python main.py
// যেহেতু env var সেট করা হয়নি, তাই আমরা ডিফল্ট ভ্যালু পাচ্ছি
Hello World from Python
// কিন্তু আমরা প্রথমে যদি একটা এনভায়রনমেন্ট ভারিয়েবল তৈরি করে নেই
$ $Env:MY_NAME = "Wade Wilson"
// এবং তারপর আবার প্রোগ্রাটিকে কল করি
$ python main.py
// এখন এটি এনভায়রনমেন্ট ভেরিয়েবল রিড করতে পারবে
Hello Wade Wilson from Python
```
</div>
////
যেহেতু এনভায়রনমেন্ট ভেরিয়েবলস কোডের বাইরে সেট করা যায়, কিন্তু পরবর্তীতে কোড দ্বারা রিড করা যায়, এবং বাকি ফাইলগুলোর সাথে রাখতে (`git` এ কমিট) হয় না, তাই কনফিগারেশনস বা **সেটিংস** এর জন্য এগুলো সাধারণত ব্যবহৃত হয়ে থাকে।
আপনি একটি এনভায়রনমেন্ট ভেরিয়েবল শুধুমাত্র একটি **নির্দিষ্ট প্রোগ্রাম ইনভোকেশনের** জন্যও তৈরি করতে পারেন, যা শুধুমাত্র সেই প্রোগ্রামের জন্যই এভেইলেবল থাকবে এবং শুধুমাত্র তার চলাকালীন সময় পর্যন্তই সক্রিয় থাকবে।
এটি করতে, প্রোগ্রামটি রান করার ঠিক আগেই, একই লাইনে এনভায়রনমেন্ট ভেরিয়েবল তৈরি করুন:
<div class="termy">
```console
// প্রোগ্রামটি কল করার সময় একই লাইনে MY_NAME এনভায়রনমেন্ট ভেরিয়েবল তৈরি করুন
$ MY_NAME="Wade Wilson" python main.py
// এখন এটি এনভায়রনমেন্ট ভ্যরিয়েবলটিকে রিড করতে পারবে
Hello Wade Wilson from Python
// পরবর্তীতে এনভায়রনমেন্ট ভেরিয়েবলটিকে আর ব্যবহার করা যাচ্ছে না
$ python main.py
Hello World from Python
```
</div>
/// tip
এটি নিয়ে আরো বিস্তারিত পড়তে পারেন এখানে <a href="https://12factor.net/config" class="external-link" target="_blank">The Twelve-Factor App: Config</a>।
///
## টাইপস এবং ভ্যালিডেশন
এই এনভায়রনমেন্ট ভেরিয়েবলগুলো শুধুমাত্র **টেক্সট স্ট্রিংস** হ্যান্ডেল করতে পারে, যেহেতু এগুলো পাইথনের বাইরে অবস্থিত এবং অন্যান্য প্রোগ্রাম এবং সিস্টেমের বাকি অংশের (এমনকি বিভিন্ন অপারেটিং সিস্টেম যেমন লিনাক্স, উইন্ডোজ, ম্যাকওএস) সাথে সামঞ্জস্যপূর্ণ হতে হয়।
এর অর্থ হচ্ছে পাইথনে এনভায়রনমেন্ট ভেরিয়েবল থেকে রিড করা **যেকোনো ভ্যালু** একটি `str` হবে, এবং অন্য কোনো টাইপে কনভার্সন বা যেকোনো ভেলিডেশন কোডে আলাদাভাবে করতে হবে।
এনভায়রনমেন্ট ভেরিয়েবল ব্যবহার করে **এপ্লিকেশন সেটিংস** হ্যান্ডেল করা নিয়ে আরো বিস্তারিত জানা যাবে [Advanced User Guide - Settings and Environment Variables](./advanced/settings.md){.internal-link target=_blank}.
## `PATH` এনভায়রনমেন্ট ভেরিয়েবল
**`PATH`** নামে একটি **বিশেষ** এনভায়রনমেন্ট ভেরিয়েবল রয়েছে, যেটি প্রোগ্রাম রান করার জন্য অপারেটিং সিস্টেমস (লিনাক্স, ম্যাকওএস, উইন্ডোজ) দ্বারা ব্যবহৃত হয়।
`PATH` ভেরিয়েবল এর ভ্যালু হচ্ছে একটি বিশাল স্ট্রিং যা ডিরেক্টরিকে কোলন `:` দিয়ে আলাদা করার মাধ্যমে লিনাক্সে ও ম্যাকওএস এ, এবং সেমিকোলন `;` এর মাধ্যমে উইন্ডোজ এ তৈরি করা থাকে।
উদাহরণস্বরূপ, `PATH` ভেরিয়েবল নিচের মতো দেখতে হতে পারেঃ
//// tab | লিনাক্স, ম্যাকওএস
```plaintext
/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
```
তারমানে হলো সিস্টেম প্রোগ্রামগুলোকে নিচের ডিরেক্টরিগুলোতে খুঁজবেঃ
* `/usr/local/bin`
* `/usr/bin`
* `/bin`
* `/usr/sbin`
* `/sbin`
////
//// tab | উইন্ডোজ
```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` নামের একটি প্রোগ্রাম খুঁজবে।
যদি এটি খুঁজে পায়, তাহলে এটি প্রোগ্রামটিকে ব্যবহার করবে। অন্যথায় এটি **অন্যান্য ডিরেক্টরিগুলোতে** এটিকে খুঁজতে থাকবে।
### পাইথন ইনস্টল এবং `PATH` আপডেট
যখন আপনি পাইথন ইনস্টল করেন, আপনি `PATH` এনভায়রনমেন্ট ভেরিয়েবল আপডেট করতে চান কিনা সেটা জিজ্ঞেস করা হতে পারে।
//// tab | লিনাক্স, ম্যাকওএস
ধরা যাক আপনি পাইথন ইনস্টল করলেন এবং এটি `/opt/custompython/bin` ডিরেক্টরিতে ইনস্টল হচ্ছে।
যদি আপনি "Yes" সিলেক্ট করে `PATH` এনভায়রনমেন্ট ভেরিয়েবল আপডেট করতে চান, তাহলে ইনস্টলার `/opt/custompython/bin` কে `PATH` এনভায়রনমেন্ট ভেরিয়েবল এ এড করে দিবে।
এটা দেখতে এমনটা হতে পারেঃ
```plaintext
/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/custompython/bin
```
এইভাবে, আপনি যখন টার্মিনালে `python` টাইপ করেন, সিস্টেম পাইথন প্রোগ্রামটিকে `/opt/custompython/bin` (সর্বশেষ ডিরেক্টরি) তে খুঁজে পাবে এবং এটাকে ব্যবহার করবে।
////
//// tab | উইন্ডোজ
ধরা যাক আপনি পাইথন ইনস্টল করলেন এবং এটি `C:\opt\custompython\bin` ডিরেক্টরিতে ইনস্টল হচ্ছে।
যদি আপনি "Yes" সিলেক্ট করে `PATH` এনভায়রনমেন্ট ভেরিয়েবল আপডেট করতে চান, তাহলে ইনস্টলার `C:\opt\custompython\bin` কে `PATH` এনভায়রনমেন্ট ভেরিয়েবল এ এড করে দিবে।
```plaintext
C:\Program Files\Python312\Scripts;C:\Program Files\Python312;C:\Windows\System32;C:\opt\custompython\bin
```
এইভাবে, আপনি যখন টার্মিনালে `python` টাইপ করেন, সিস্টেম পাইথন প্রোগ্রামটিকে `C:\opt\custompython\bin` (সর্বশেষ ডিরেক্টরি) তে খুঁজে পাবে এবং এটাকে ব্যবহার করবে।
////
তাই, আপনি যদি টাইপ করেনঃ
<div class="termy">
```console
$ python
```
</div>
//// tab | লিনাক্স, ম্যাকওএস
সিস্টেম `python` প্রোগ্রামকে `/opt/custompython/bin` এ **খুঁজে পাবে** এবং এটাকে রান করবে।
এটা মোটামুটিভাবে নিচের মতো করে লেখার সমান হবেঃ
<div class="termy">
```console
$ /opt/custompython/bin/python
```
</div>
////
//// tab | উইন্ডোজ
সিস্টেম `python` প্রোগ্রামকে `C:\opt\custompython\bin\python` এ **খুঁজে পাবে** এবং এটাকে রান করবে।
এটা মোটামুটিভাবে নিচের মতো করে লেখার সমান হবেঃ
<div class="termy">
```console
$ C:\opt\custompython\bin\python
```
</div>
////
এই তথ্যগুলো [ভার্চুয়াল এনভায়রনমেন্টস](virtual-environments.md){.internal-link target=_blank} শেখার ক্ষেত্রে সহায়ক হবে।
## উপসংহার
এর মাধ্যমে আপনি **এনভায়রনমেন্ট ভেরিয়েবলস** কি এবং এটিকে পাইথনে কিভাবে ব্যবহার করতে হয় তার সম্পর্কে বেসিক ধারনা পেলেন।
চাইলে এই সম্পর্কে আরো বিস্তারিত পড়তে পারেন <a href="https://en.wikipedia.org/wiki/Environment_variable" class="external-link" target="_blank">Wikipedia for Environment Variable</a> এ।
অনেক ক্ষেত্রে, দেখা মাত্রই এনভায়রনমেন্ট ভেরিয়েবল কীভাবে প্রয়োজন হবে তা স্পষ্ট হয় না। কিন্তু ডেভেলপমেন্টের সময় আপনি নানা রকম পরিস্থিতিতে এগুলোর সম্মুখীন হবেন, তাই এগুলো সম্পর্কে জেনে রাখা ভালো।
উদাহরণস্বরূপ, আপনার এই ইনফরমেশনটি পরবর্তী, [ভার্চুয়াল এনভায়রনমেন্টস](virtual-environments.md) অংশে দরকার হবে।

View File

@@ -1,466 +0,0 @@
<p align="center">
<a href="https://fastapi.tiangolo.com"><img src="https://fastapi.tiangolo.com/img/logo-margin/logo-teal.png" alt="FastAPI"></a>
</p>
<p align="center">
<em>FastAPI উচ্চক্ষমতা সম্পন্ন, সহজে শেখার এবং দ্রুত কোড করে প্রোডাকশনের জন্য ফ্রামওয়ার্ক।</em>
</p>
<p align="center">
<a href="https://github.com/fastapi/fastapi/actions?query=workflow%3ATest+event%3Apush+branch%3Amaster" target="_blank">
<img src="https://github.com/fastapi/fastapi/actions/workflows/test.yml/badge.svg?event=push&branch=master" alt="Test">
</a>
<a href="https://coverage-badge.samuelcolvin.workers.dev/redirect/fastapi/fastapi" target="_blank">
<img src="https://coverage-badge.samuelcolvin.workers.dev/fastapi/fastapi.svg" alt="Coverage">
</a>
<a href="https://pypi.org/project/fastapi" target="_blank">
<img src="https://img.shields.io/pypi/v/fastapi?color=%2334D058&label=pypi%20package" alt="Package version">
</a>
<a href="https://pypi.org/project/fastapi" target="_blank">
<img src="https://img.shields.io/pypi/pyversions/fastapi.svg?color=%2334D058" alt="Supported Python versions">
</a>
</p>
---
**নির্দেশিকা নথি**: <a href="https://fastapi.tiangolo.com" target="_blank">https://fastapi.tiangolo.com</a>
**সোর্স কোড**: <a href="https://github.com/fastapi/fastapi" target="_blank">https://github.com/fastapi/fastapi</a>
---
FastAPI একটি আধুনিক, দ্রুত ( বেশি ক্ষমতা ) সম্পন্ন, Python 3.6+ দিয়ে API তৈরির জন্য স্ট্যান্ডার্ড পাইথন টাইপ ইঙ্গিত ভিত্তিক ওয়েব ফ্রেমওয়ার্ক।
এর মূল বৈশিষ্ট্য গুলো হলঃ
- **গতি**: এটি **NodeJS** এবং **Go** এর মত কার্যক্ষমতা সম্পন্ন (Starlette এবং Pydantic এর সাহায্যে)। [পাইথন এর দ্রুততম ফ্রেমওয়ার্ক গুলোর মধ্যে এটি একটি](#_11)।
- **দ্রুত কোড করা**:বৈশিষ্ট্য তৈরির গতি ২০০% থেকে ৩০০% বৃদ্ধি করে৷ \*
- **স্বল্প bugs**: মানুব (ডেভেলপার) সৃষ্ট ত্রুটির প্রায় % হ্রাস করে। \*
- **স্বজ্ঞাত**: দুর্দান্ত এডিটর সাহায্য <abbr title="also known as auto-complete, autocompletion, IntelliSense">Completion</abbr> নামেও পরিচিত। দ্রুত ডিবাগ করা যায়।
- **সহজ**: এটি এমন ভাবে সজানো হয়েছে যেন নির্দেশিকা নথি পড়ে সহজে শেখা এবং ব্যবহার করা যায়।
- **সংক্ষিপ্ত**: কোড পুনরাবৃত্তি কমানোর পাশাপাশি, bug কমায় এবং প্রতিটি প্যারামিটার ঘোষণা থেকে একাধিক ফিচার পাওয়া যায় ।
- **জোরালো**: স্বয়ংক্রিয় ভাবে তৈরি ক্রিয়াশীল নির্দেশনা নথি (documentation) সহ উৎপাদন উপযোগি (Production-ready) কোড পাওয়া যায়।
- **মান-ভিত্তিক**: এর ভিত্তি <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank">OpenAPI</a> (যা পুর্বে Swagger নামে পরিচিত ছিল) এবং <a href="https://json-schema.org/" class="external-link" target="_blank">JSON Schema</a> এর আদর্শের মানের ওপর
<small>\* উৎপাদনমুখি এপ্লিকেশন বানানোর এক দল ডেভেলপার এর মতামত ভিত্তিক ফলাফল।</small>
## স্পনসর গণ
<!-- sponsors -->
{% if sponsors %}
{% for sponsor in sponsors.gold -%}
<a href="{{ sponsor.url }}" target="_blank" title="{{ sponsor.title }}"><img src="{{ sponsor.img }}" style="border-radius:15px"></a>
{% endfor -%}
{%- for sponsor in sponsors.silver -%}
<a href="{{ sponsor.url }}" target="_blank" title="{{ sponsor.title }}"><img src="{{ sponsor.img }}" style="border-radius:15px"></a>
{% endfor %}
{% endif %}
<!-- /sponsors -->
<a href="https://fastapi.tiangolo.com/fastapi-people/#sponsors" class="external-link" target="_blank">অন্যান্য স্পনসর গণ</a>
## মতামত সমূহ
"_আমি আজকাল **FastAPI** ব্যবহার করছি। [...] আমরা ভাবছি মাইক্রোসফ্টে **ML সার্ভিস** এ সকল দলের জন্য এটি ব্যবহার করব। যার মধ্যে কিছু পণ্য **Windows** এ সংযোযন হয় এবং কিছু **Office** এর সাথে সংযোযন হচ্ছে।_"
<div style="text-align: right; margin-right: 10%;">কবির খান - <strong>মাইক্রোসফ্টে</strong> <a href="https://github.com/fastapi/fastapi/pull/26" target="_blank"><small>(ref)</small></a></div>
---
"_আমরা **FastAPI** লাইব্রেরি গ্রহণ করেছি একটি **REST** সার্ভার তৈরি করতে, যা **ভবিষ্যদ্বাণী** পাওয়ার জন্য কুয়েরি করা যেতে পারে। [লুডউইগের জন্য]_"
<div style="text-align: right; margin-right: 10%;">পিয়েরো মোলিনো, ইয়ারোস্লাভ দুদিন, এবং সাই সুমন্থ মিরিয়ালা - <strong>উবার</strong> <a href="https://eng.uber.com/ludwig-v0-2/" target="_blank"><small>(ref)</small></a></div>
---
"_**Netflix** আমাদের **ক্রাইসিস ম্যানেজমেন্ট** অর্কেস্ট্রেশন ফ্রেমওয়ার্ক: **ডিসপ্যাচ** এর ওপেন সোর্স রিলিজ ঘোষণা করতে পেরে আনন্দিত! [যাকিনা **FastAPI** দিয়ে নির্মিত]_"
<div style="text-align: right; margin-right: 10%;">কেভিন গ্লিসন, মার্ক ভিলানোভা, ফরেস্ট মনসেন - <strong>নেটফ্লিক্স</strong> <a href="https://netflixtechblog.com/introducing-dispatch-da4b8a2a8072" target="_blank"><small>(ref)</small></a></div>
---
"_আমি **FastAPI** নিয়ে চাঁদের সমান উৎসাহিত। এটি খুবই মজার!_"
<div style="text-align: right; margin-right: 10%;">ব্রায়ান ওকেন - <strong><a href="https://pythonbytes.fm/episodes/show/123/time-to-right-the-py-wrongs?time_in_sec=855" target="_blank">পাইথন বাইটস</a> পডকাস্ট হোস্ট</strong> <a href="https://x.com/brianokken/status/1112220079972728832" target="_blank"><small>(ref)</small></a></div>
---
"\_সত্যিই, আপনি যা তৈরি করেছেন তা খুব মজবুত এবং পরিপূর্ন৷ অনেক উপায়ে, আমি যা **Hug** এ করতে চেয়েছিলাম - তা কাউকে তৈরি করতে দেখে আমি সত্যিই অনুপ্রানিত৷\_"
<div style="text-align: right; margin-right: 10%;">টিমোথি ক্রসলে - <strong><a href="https://github.com/hugapi/hug" target="_blank">Hug</a> স্রষ্টা</strong> <a href="https://news.ycombinator.com/item?id=19455465" target="_blank"><small>(ref)</small></a></div>
---
"আপনি যদি REST API তৈরির জন্য একটি **আধুনিক ফ্রেমওয়ার্ক** শিখতে চান, তাহলে **FastAPI** দেখুন [...] এটি দ্রুত, ব্যবহার করা সহজ এবং শিখতেও সহজ [...]\_"
"_আমরা আমাদের **APIs** [...] এর জন্য **FastAPI**- তে এসেছি [...] আমি মনে করি আপনিও এটি পছন্দ করবেন [...]_"
<div style="text-align: right; margin-right: 10%;">ইনেস মন্টানি - ম্যাথিউ হোনিবাল - <strong><a href="https://explosion.ai" target="_blank">Explosion AI</a> প্রতিষ্ঠাতা - <a href="https://spacy.io" target="_blank">spaCy</a> স্রষ্টা</strong> <a href="https://x.com/_inesmontani/status/1144173225322143744" target="_blank"><small>(ref)</small></a> - <a href="https://x.com/honnibal/status/1144031421859655680" target="_blank"><small>(ref)</small></a></div>
---
## **Typer**, CLI এর জন্য FastAPI
<a href="https://typer.tiangolo.com" target="_blank"><img src="https://typer.tiangolo.com/img/logo-margin/logo-margin-vector.svg" style="width: 20%;"></a>
আপনি যদি <abbr title="Command Line Interface">CLI</abbr> অ্যাপ বানাতে চান, যা কিনা ওয়েব API এর পরিবর্তে টার্মিনালে ব্যবহার হবে, তাহলে দেখুন<a href="https://typer.tiangolo.com/" class="external-link" target="_blank">**Typer**</a>.
**টাইপার** হল FastAPI এর ছোট ভাইয়ের মত। এবং এটির উদ্দেশ্য ছিল **CLIs এর FastAPI** হওয়া। ⌨️ 🚀
## প্রয়োজনীয়তা গুলো
Python 3.7+
FastAPI কিছু দানবেদের কাঁধে দাঁড়িয়ে আছে:
- <a href="https://www.starlette.io/" class="external-link" target="_blank">Starlette</a> ওয়েব অংশের জন্য.
- <a href="https://docs.pydantic.dev/" class="external-link" target="_blank">Pydantic</a> ডেটা অংশগুলির জন্য.
## ইনস্টলেশন প্রক্রিয়া
<div class="termy">
```console
$ pip install fastapi
---> 100%
```
</div>
আপনার একটি ASGI সার্ভারেরও প্রয়োজন হবে, প্রোডাকশনের জন্য <a href="https://www.uvicorn.org" class="external-link" target="_blank">Uvicorn</a> অথবা <a href="https://github.com/pgjones/hypercorn" class="external-link" target="_blank">Hypercorn</a>.
<div class="termy">
```console
$ pip install "uvicorn[standard]"
---> 100%
```
</div>
## উদাহরণ
### তৈরি
- `main.py` নামে একটি ফাইল তৈরি করুন:
```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}
```
<details markdown="1">
<summary>অথবা ব্যবহার করুন <code>async def</code>...</summary>
যদি আপনার কোড `async` / `await`, ব্যবহার করে তাহলে `async def` ব্যবহার করুন:
```Python hl_lines="9 14"
from typing import Union
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
async def read_root():
return {"Hello": "World"}
@app.get("/items/{item_id}")
async def read_item(item_id: int, q: Union[str, None] = None):
return {"item_id": item_id, "q": q}
```
**টীকা**:
আপনি যদি না জানেন, _"তাড়াহুড়ো?"_ বিভাগটি দেখুন <a href="https://fastapi.tiangolo.com/async/#in-a-hurry" target="_blank">`async` এবং `await` নথির মধ্যে দেখুন </a>.
</details>
### এটি চালান
সার্ভার চালু করুন:
<div class="termy">
```console
$ uvicorn main:app --reload
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.
```
</div>
<details markdown="1">
<summary>নির্দেশনা সম্পর্কে <code>uvicorn main:app --reload</code>...</summary>
`uvicorn main:app` নির্দেশনাটি দ্বারা বোঝায়:
- `main`: ফাইল `main.py` (পাইথন "মডিউল")।
- `app`: `app = FastAPI()` লাইন দিয়ে `main.py` এর ভিতরে তৈরি করা অবজেক্ট।
- `--reload`: কোড পরিবর্তনের পরে সার্ভার পুনরায় চালু করুন। এটি শুধুমাত্র ডেভেলপমেন্ট এর সময় ব্যবহার করুন।
</details>
### এটা চেক করুন
আপনার ব্রাউজার খুলুন <a href="http://127.0.0.1:8000/items/5?q=somequery" class="external-link" target="_blank">http://127.0.0.1:8000/items/5?q=somequery</a> এ।
আপনি JSON রেসপন্স দেখতে পাবেন:
```JSON
{"item_id": 5, "q": "somequery"}
```
আপনি ইতিমধ্যে একটি API তৈরি করেছেন যা:
- `/` এবং `/items/{item_id}` _paths_ এ HTTP অনুরোধ গ্রহণ করে।
- উভয় *path*ই `GET` <em>অপারেশন</em> নেয় ( যা HTTP _methods_ নামেও পরিচিত)।
- _path_ `/items/{item_id}`-এ একটি _path প্যারামিটার_ `item_id` আছে যা কিনা `int` হতে হবে।
- _path_ `/items/{item_id}`-এর একটি ঐচ্ছিক `str` _query প্যারামিটার_ `q` আছে।
### ক্রিয়াশীল API নির্দেশিকা নথি
এখন যান <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
আপনি স্বয়ংক্রিয় ভাবে প্রস্তুত ক্রিয়াশীল API নির্দেশিকা নথি দেখতে পাবেন (<a href="https://github.com/swagger-api/swagger-ui" class="external-link" target="_blank">Swagger UI</a> প্রদত্ত):
![Swagger UI](https://fastapi.tiangolo.com/img/index/index-01-swagger-ui-simple.png)
### বিকল্প API নির্দেশিকা নথি
এবং এখন <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a> এ যান.
আপনি স্বয়ংক্রিয় ভাবে প্রস্তুত বিকল্প নির্দেশিকা নথি দেখতে পাবেন (<a href="https://github.com/Rebilly/ReDoc" class="external-link" target="_blank">ReDoc</a> প্রদত্ত):
![ReDoc](https://fastapi.tiangolo.com/img/index/index-02-redoc-simple.png)
## উদাহরণস্বরূপ আপগ্রেড
এখন `main.py` ফাইলটি পরিবর্তন করুন যেন এটি `PUT` রিকুয়েস্ট থেকে বডি পেতে পারে।
Python স্ট্যান্ডার্ড লাইব্রেরি, Pydantic এর সাহায্যে বডি ঘোষণা করুন।
```Python hl_lines="4 9-12 25-27"
from typing import Union
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
price: float
is_offer: Union[bool, None] = None
@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}
@app.put("/items/{item_id}")
def update_item(item_id: int, item: Item):
return {"item_name": item.name, "item_id": item_id}
```
সার্ভারটি স্বয়ংক্রিয়ভাবে পুনরায় লোড হওয়া উচিত (কারণ আপনি উপরের `uvicorn` কমান্ডে `--reload` যোগ করেছেন)।
### ক্রিয়াশীল API নির্দেশিকা নথি উন্নীতকরণ
এখন <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a> এডড্রেসে যান.
- ক্রিয়াশীল API নির্দেশিকা নথিটি স্বয়ংক্রিয়ভাবে উন্নীত হযে যাবে, নতুন বডি সহ:
![Swagger UI](https://fastapi.tiangolo.com/img/index/index-03-swagger-02.png)
- "Try it out" বাটনে চাপুন, এটি আপনাকে পেরামিটারগুলো পূরণ করতে এবং API এর সাথে সরাসরি ক্রিয়া-কলাপ করতে দিবে:
![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-04-swagger-03.png)
- তারপরে "Execute" বাটনে চাপুন, ব্যবহারকারীর ইন্টারফেস আপনার API এর সাথে যোগাযোগ করবে, পেরামিটার পাঠাবে, ফলাফলগুলি পাবে এবং সেগুলি পর্রদায় দেখাবে:
![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-05-swagger-04.png)
### বিকল্প API নির্দেশিকা নথি আপগ্রেড
এবং এখন <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a> এ যান।
- বিকল্প নির্দেশিকা নথিতেও নতুন কুয়েরি প্যারামিটার এবং বডি প্রতিফলিত হবে:
![ReDoc](https://fastapi.tiangolo.com/img/index/index-06-redoc-02.png)
### সংক্ষিপ্তকরণ
সংক্ষেপে, আপনি **শুধু একবার** প্যারামিটারের ধরন, বডি ইত্যাদি ফাংশন প্যারামিটার হিসেবে ঘোষণা করেন।
আপনি সেটি আধুনিক পাইথনের সাথে করেন।
আপনাকে নতুন করে নির্দিষ্ট কোন লাইব্রেরির বাক্য গঠন, ফাংশন বা ক্লাস কিছুই শিখতে হচ্ছে না।
শুধুই আধুনিক **Python 3.6+**
উদাহরণস্বরূপ, `int` এর জন্য:
```Python
item_id: int
```
অথবা আরও জটিল `Item` মডেলের জন্য:
```Python
item: Item
```
...এবং সেই একই ঘোষণার সাথে আপনি পাবেন:
- এডিটর সাহায্য, যেমন
- সমাপ্তি।
- ধরণ যাচাই
- তথ্য যাচাইকরণ:
- ডেটা অবৈধ হলে স্বয়ংক্রিয় এবং পরিষ্কার ত্রুটির নির্দেশনা।
- এমনকি গভীরভাবে নেস্ট করা JSON অবজেক্টের জন্য বৈধতা।
- প্রেরিত তথ্য <abbr title="যা পরিচিত: serialization, parsing, marshalling">রূপান্তর</abbr>: যা নেটওয়ার্ক থেকে পাইথনের তথ্য এবং ধরনে আসে, এবং সেখান থেকে পড়া:
- JSON।
- পাথ প্যারামিটার।
- কুয়েরি প্যারামিটার।
- কুকিজ
- হেডার
- ফর্ম
- ফাইল
- আউটপুট ডেটার <abbr title="যা পরিচিত: serialization, parsing, marshalling">রূপান্তর</abbr>: পাইথন ডেটা এবং টাইপ থেকে নেটওয়ার্ক ডেটাতে রূপান্তর করা (JSON হিসাবে):
-পাইথন টাইপে রূপান্তর করুন (`str`, `int`, `float`, `bool`, `list`, ইত্যাদি)।
- `datetime` অবজেক্ট।
- `UUID` objeঅবজেক্টcts।
- ডাটাবেস মডেল।
- ...এবং আরো অনেক।
- স্বয়ংক্রিয় ক্রিয়াশীল 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` এর ক্ষেত্রে হয়েছে)।
- `/items/{item_id}` এর জন্য `PUT` অনুরোধের বডি JSON হিসাবে পড়ুন:
- লক্ষ করুন, `name` একটি প্রয়োজনীয় অ্যাট্রিবিউট হিসাবে বিবেচনা করেছে এবং এটি `str` হতে হবে।
- লক্ষ করুন এখানে, `price` অ্যাট্রিবিউটটি আবশ্যক এবং এটি `float` হতে হবে।
- লক্ষ করুন `is_offer` একটি ঐচ্ছিক অ্যাট্রিবিউট এবং এটি `bool` হতে হবে যদি উপস্থিত থাকে।
- এই সবটি গভীরভাবে অবস্থানরত JSON অবজেক্টগুলিতেও কাজ করবে।
- স্বয়ংক্রিয়ভাবে JSON হতে এবং JSON থেকে কনভার্ট করুন।
- OpenAPI দিয়ে সবকিছু ডকুমেন্ট করুন, যা ব্যবহার করা যেতে পারে:
- ক্রিয়াশীল নির্দেশিকা নথি।
- অনেক ভাষার জন্য স্বয়ংক্রিয় ক্লায়েন্ট কোড তৈরির ব্যবস্থা।
- সরাসরি 2টি ক্রিয়াশীল নির্দেশিকা নথি ওয়েব পৃষ্ঠ প্রদান করা হয়েছে।
---
আমরা এতক্ষন শুধু এর পৃষ্ঠ তৈরি করেছি, কিন্তু আপনি ইতমধ্যেই এটি কিভাবে কাজ করে তার ধারণাও পেয়ে গিয়েছেন।
নিম্নোক্ত লাইন গুলো পরিবর্তন করার চেষ্টা করুন:
```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)
আরও বৈশিষ্ট্য সম্পন্ন উদাহরণের জন্য, দেখুন <a href="https://fastapi.tiangolo.com/tutorial/">টিউটোরিয়াল - ব্যবহারকারীর গাইড</a>.
**স্পয়লার সতর্কতা**: টিউটোরিয়াল - ব্যবহারকারীর গাইড নিম্নোক্ত বিষয়গুলি অন্তর্ভুক্ত করে:
- **হেডার**, **কুকিজ**, **ফর্ম ফিল্ড** এবং **ফাইলগুলি** এমন অন্যান্য জায়গা থেকে প্যারামিটার ঘোষণা করা।
- `maximum_length` বা `regex` এর মতো **যাচাইকরণ বাধামুক্তি** সেট করা হয় কিভাবে, তা নিয়ে আলোচনা করা হবে।
- একটি খুব শক্তিশালী এবং ব্যবহার করা সহজ <abbr title="also known as components, resources, providers, services, injectables">ডিপেন্ডেন্সি ইনজেকশন</abbr> পদ্ধতি
- **OAuth2** এবং **JWT টোকেন** এবং **HTTP Basic** auth সহ নিরাপত্তা এবং অনুমোদনপ্রাপ্তি সম্পর্কিত বিষয়সমূহের উপর।
- **গভীরভাবে অবস্থানরত JSON মডেল** ঘোষণা করার জন্য আরও উন্নত (কিন্তু সমান সহজ) কৌশল (Pydantic কে ধন্যবাদ)।
- আরো অতিরিক্ত বৈশিষ্ট্য (স্টারলেটকে ধন্যবাদ) হিসাবে:
- **WebSockets**
- **GraphQL**
- HTTPX এবং `pytest` ভিত্তিক অত্যন্ত সহজ পরীক্ষা
- **CORS**
- **Cookie Sessions**
- ...এবং আরো।
## কর্মক্ষমতা
স্বাধীন TechEmpower Benchmarks দেখায় যে **FastAPI** অ্যাপ্লিকেশনগুলি Uvicorn-এর অধীনে চলমান দ্রুততম<a href="https://www.techempower.com/benchmarks/#section=test&runid=7464e520-0dc2-473d-bd34-dbdfd7e85911&hw=ph&test=query&l=zijzen-7" class="external-link" target="_blank">পাইথন ফ্রেমওয়ার্কগুলির মধ্যে একটি,</a> শুধুমাত্র Starlette এবং Uvicorn-এর পর (FastAPI দ্বারা অভ্যন্তরীণভাবে ব্যবহৃত)। (\*)
এটি সম্পর্কে আরও বুঝতে, দেখুন <a href="https://fastapi.tiangolo.com/benchmarks/" class="internal-link" target="_blank">Benchmarks</a>.
## ঐচ্ছিক নির্ভরশীলতা
Pydantic দ্বারা ব্যবহৃত:
- <a href="https://github.com/JoshData/python-email-validator" target="_blank"><code>email-validator</code></a> - ইমেল যাচাইকরণের জন্য।
স্টারলেট দ্বারা ব্যবহৃত:
- <a href="https://www.python-httpx.org" target="_blank"><code>httpx</code></a> - আপনি যদি `TestClient` ব্যবহার করতে চান তাহলে আবশ্যক।
- <a href="https://jinja.palletsprojects.com" target="_blank"><code>jinja2</code></a> - আপনি যদি প্রদত্ত টেমপ্লেট রূপরেখা ব্যবহার করতে চান তাহলে প্রয়োজন।
- <a href="https://github.com/Kludex/python-multipart" target="_blank"><code>python-multipart</code></a> - আপনি যদি ফর্ম সহায়তা করতে চান তাহলে প্রয়োজন <abbr title="converting the string that comes from an HTTP request into Python data">"parsing"</abbr>, `request.form()` সহ।
- <a href="https://pythonhosted.org/itsdangerous/" target="_blank"><code>itsdangerous</code></a> - `SessionMiddleware` সহায়তার জন্য প্রয়োজন।
- <a href="https://pyyaml.org/wiki/PyYAMLDocumentation" target="_blank"><code>pyyaml</code></a> - স্টারলেটের SchemaGenerator সাপোর্ট এর জন্য প্রয়োজন (আপনার সম্ভাবত FastAPI প্রয়োজন নেই)।
- <a href="https://graphene-python.org/" target="_blank"><code>graphene</code></a> - `GraphQLApp` সহায়তার জন্য প্রয়োজন।
FastAPI / Starlette দ্বারা ব্যবহৃত:
- <a href="https://www.uvicorn.org" target="_blank"><code>uvicorn</code></a> - সার্ভারের জন্য যা আপনার অ্যাপ্লিকেশন লোড করে এবং পরিবেশন করে।
- <a href="https://github.com/ijl/orjson" target="_blank"><code>orjson</code></a> - আপনি `ORJSONResponse` ব্যবহার করতে চাইলে প্রয়োজন।
- <a href="https://github.com/esnme/ultrajson" target="_blank"><code>ujson</code></a> - আপনি `UJSONResponse` ব্যবহার করতে চাইলে প্রয়োজন।
আপনি এই সব ইনস্টল করতে পারেন `pip install fastapi[all]` দিয়ে.
## লাইসেন্স
এই প্রজেক্ট MIT লাইসেন্স নীতিমালার অধীনে শর্তায়িত।

View File

@@ -1,5 +0,0 @@
# শিখুন
এখানে **FastAPI** শিখার জন্য প্রাথমিক বিভাগগুলি এবং টিউটোরিয়ালগুলি রয়েছে।
আপনি এটিকে একটি **বই**, একটি **কোর্স**, এবং FastAPI শিখার **অফিসিয়াল** এবং প্রস্তাবিত উপায় বিবেচনা করতে পারেন। 😎

View File

@@ -1,586 +0,0 @@
# পাইথন এর <abbr title="একটি ভেরিয়েবল কি ধরনের ডেটা ধারণ করতে পারে।">টাইপ্স</abbr> পরিচিতি
Python-এ ঐচ্ছিক "টাইপ হিন্ট" (যা "টাইপ অ্যানোটেশন" নামেও পরিচিত) এর জন্য সাপোর্ট রয়েছে।
এই **"টাইপ হিন্ট"** বা অ্যানোটেশনগুলি এক ধরণের বিশেষ <abbr title="সিনট্যাক্স হল প্রোগ্রামিং ভাষায় কোড লেখার নিয়ম ও গঠন।">সিনট্যাক্স</abbr> যা একটি ভেরিয়েবলের <abbr title="যেমন: str, int, float, bool">টাইপ</abbr> ঘোষণা করতে দেয়।
ভেরিয়েবলগুলির জন্য টাইপ ঘোষণা করলে, এডিটর এবং টুলগুলি আপনাকে আরও ভালো সাপোর্ট দিতে পারে।
এটি পাইথন টাইপ হিন্ট সম্পর্কে একটি দ্রুত **টিউটোরিয়াল / রিফ্রেশার** মাত্র। এটি **FastAPI** এর সাথে ব্যবহার করার জন্য শুধুমাত্র ন্যূনতম প্রয়োজনীয়তা কভার করে... যা আসলে খুব একটা বেশি না।
**FastAPI** এই টাইপ হিন্টগুলির উপর ভিত্তি করে নির্মিত, যা এটিকে অনেক সুবিধা এবং লাভ প্রদান করে।
তবে, আপনি যদি কখনো **FastAPI** ব্যবহার নাও করেন, তবুও এগুলি সম্পর্কে একটু শেখা আপনার উপকারে আসবে।
/// note
যদি আপনি একজন Python বিশেষজ্ঞ হন, এবং টাইপ হিন্ট সম্পর্কে সবকিছু জানেন, তাহলে পরবর্তী অধ্যায়ে চলে যান।
///
## প্রেরণা
চলুন একটি সাধারণ উদাহরণ দিয়ে শুরু করি:
{* ../../docs_src/python_types/tutorial001.py *}
এই প্রোগ্রামটি কল করলে আউটপুট হয়:
```
John Doe
```
ফাংশনটি নিম্নলিখিত কাজ করে:
* `first_name` এবং `last_name` নেয়।
* প্রতিটির প্রথম অক্ষরকে `title()` ব্যবহার করে বড় হাতের অক্ষরে রূপান্তর করে।
* তাদেরকে মাঝখানে একটি স্পেস দিয়ে <abbr title="একটার পরে একটা একত্রিত করা">concatenate</abbr> করে।
{* ../../docs_src/python_types/tutorial001.py hl[2] *}
### এটি সম্পাদনা করুন
এটি একটি খুব সাধারণ প্রোগ্রাম।
কিন্তু এখন কল্পনা করুন যে আপনি এটি শুরু থেকে লিখছিলেন।
এক পর্যায়ে আপনি ফাংশনের সংজ্ঞা শুরু করেছিলেন, আপনার প্যারামিটারগুলি প্রস্তুত ছিল...
কিন্তু তারপর আপনাকে "সেই method কল করতে হবে যা প্রথম অক্ষরকে বড় হাতের অক্ষরে রূপান্তর করে"।
এটা কি `upper` ছিল? নাকি `uppercase`? `first_uppercase`? `capitalize`?
তারপর, আপনি পুরোনো প্রোগ্রামারের বন্ধু, এডিটর অটোকমপ্লিশনের সাহায্যে নেওয়ার চেষ্টা করেন।
আপনি ফাংশনের প্রথম প্যারামিটার `first_name` টাইপ করেন, তারপর একটি ডট (`.`) টাইপ করেন এবং `Ctrl+Space` চাপেন অটোকমপ্লিশন ট্রিগার করার জন্য।
কিন্তু, দুর্ভাগ্যবশত, আপনি কিছুই উপযোগী পান না:
<img src="/img/python-types/image01.png">
### টাইপ যোগ করুন
আসুন আগের সংস্করণ থেকে একটি লাইন পরিবর্তন করি।
আমরা ঠিক এই অংশটি পরিবর্তন করব অর্থাৎ ফাংশনের প্যারামিটারগুলি, এইগুলি:
```Python
first_name, last_name
```
থেকে এইগুলি:
```Python
first_name: str, last_name: str
```
ব্যাস।
এগুলিই "টাইপ হিন্ট":
{* ../../docs_src/python_types/tutorial002.py hl[1] *}
এটি ডিফল্ট ভ্যালু ঘোষণা করার মত নয় যেমন:
```Python
first_name="john", last_name="doe"
```
এটি একটি ভিন্ন জিনিস।
আমরা সমান (`=`) নয়, কোলন (`:`) ব্যবহার করছি।
এবং টাইপ হিন্ট যোগ করা সাধারণত তেমন কিছু পরিবর্তন করে না যা টাইপ হিন্ট ছাড়াই ঘটত।
কিন্তু এখন, কল্পনা করুন আপনি আবার সেই ফাংশন তৈরির মাঝখানে আছেন, কিন্তু টাইপ হিন্ট সহ।
একই পর্যায়ে, আপনি অটোকমপ্লিট ট্রিগার করতে `Ctrl+Space` চাপেন এবং আপনি দেখতে পান:
<img src="/img/python-types/image02.png">
এর সাথে, আপনি অপশনগুলি দেখে, স্ক্রল করতে পারেন, যতক্ষণ না আপনি এমন একটি অপশন খুঁজে পান যা কিছু মনে পরিয়ে দেয়:
<img src="/img/python-types/image03.png">
## আরও প্রেরণা
এই ফাংশনটি দেখুন, এটিতে ইতিমধ্যে টাইপ হিন্ট রয়েছে:
{* ../../docs_src/python_types/tutorial003.py hl[1] *}
এডিটর ভেরিয়েবলগুলির টাইপ জানার কারণে, আপনি শুধুমাত্র অটোকমপ্লিশনই পান না, আপনি এরর চেকও পান:
<img src="/img/python-types/image04.png">
এখন আপনি জানেন যে আপনাকে এটি ঠিক করতে হবে, `age`-কে একটি স্ট্রিং হিসেবে রূপান্তর করতে `str(age)` ব্যবহার করতে হবে:
{* ../../docs_src/python_types/tutorial004.py hl[2] *}
## টাইপ ঘোষণা
আপনি এতক্ষন টাইপ হিন্ট ঘোষণা করার মূল স্থানটি দেখে ফেলেছেন-- ফাংশন প্যারামিটার হিসেবে।
সাধারণত এটি **FastAPI** এর ক্ষেত্রেও একই।
### সিম্পল টাইপ
আপনি `str` ছাড়াও সমস্ত স্ট্যান্ডার্ড পাইথন টাইপ ঘোষণা করতে পারেন।
উদাহরণস্বরূপ, আপনি এগুলো ব্যবহার করতে পারেন:
* `int`
* `float`
* `bool`
* `bytes`
{* ../../docs_src/python_types/tutorial005.py hl[1] *}
### টাইপ প্যারামিটার সহ জেনেরিক টাইপ
কিছু ডাটা স্ট্রাকচার অন্যান্য মান ধারণ করতে পারে, যেমন `dict`, `list`, `set` এবং `tuple`। এবং অভ্যন্তরীণ মানগুলোরও নিজেদের টাইপ থাকতে পারে।
এই ধরনের টাইপগুলিকে বলা হয় "**জেনেরিক**" টাইপ এবং এগুলিকে তাদের অভ্যন্তরীণ টাইপগুলি সহ ঘোষণা করা সম্ভব।
এই টাইপগুলি এবং অভ্যন্তরীণ টাইপগুলি ঘোষণা করতে, আপনি Python মডিউল `typing` ব্যবহার করতে পারেন। এটি বিশেষভাবে এই টাইপ হিন্টগুলি সমর্থন করার জন্য রয়েছে।
#### Python এর নতুন সংস্করণ
`typing` ব্যবহার করা সিনট্যাক্সটি Python 3.6 থেকে সর্বশেষ সংস্করণগুলি পর্যন্ত, অর্থাৎ Python 3.9, Python 3.10 ইত্যাদি সহ সকল সংস্করণের সাথে **সামঞ্জস্যপূর্ণ**
Python যত এগিয়ে যাচ্ছে, **নতুন সংস্করণগুলি** এই টাইপ অ্যানোটেশনগুলির জন্য তত উন্নত সাপোর্ট নিয়ে আসছে এবং অনেক ক্ষেত্রে আপনাকে টাইপ অ্যানোটেশন ঘোষণা করতে `typing` মডিউল ইম্পোর্ট এবং ব্যবহার করার প্রয়োজন হবে না।
যদি আপনি আপনার প্রজেক্টের জন্য Python-এর আরও সাম্প্রতিক সংস্করণ নির্বাচন করতে পারেন, তাহলে আপনি সেই অতিরিক্ত সরলতা থেকে সুবিধা নিতে পারবেন।
ডক্সে রয়েছে 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+**"।
#### লিস্ট
উদাহরণস্বরূপ, একটি ভেরিয়েবলকে `str`-এর একটি `list` হিসেবে সংজ্ঞায়িত করা যাক।
//// tab | Python 3.9+
ভেরিয়েবলটি ঘোষণা করুন, একই কোলন (`:`) সিনট্যাক্স ব্যবহার করে।
টাইপ হিসেবে, `list` ব্যবহার করুন।
যেহেতু লিস্ট এমন একটি টাইপ যা অভ্যন্তরীণ টাইপগুলি ধারণ করে, আপনি তাদের স্কোয়ার ব্রাকেটের ভিতরে ব্যবহার করুন:
```Python hl_lines="1"
{!> ../../docs_src/python_types/tutorial006_py39.py!}
```
////
//// tab | Python 3.8+
`typing` থেকে `List` (বড় হাতের `L` দিয়ে) ইমপোর্ট করুন:
``` Python hl_lines="1"
{!> ../../docs_src/python_types/tutorial006.py!}
```
ভেরিয়েবলটি ঘোষণা করুন, একই কোলন (`:`) সিনট্যাক্স ব্যবহার করে।
টাইপ হিসেবে, `typing` থেকে আপনার ইম্পোর্ট করা `List` ব্যবহার করুন।
যেহেতু লিস্ট এমন একটি টাইপ যা অভ্যন্তরীণ টাইপগুলি ধারণ করে, আপনি তাদের স্কোয়ার ব্রাকেটের ভিতরে করুন:
```Python hl_lines="4"
{!> ../../docs_src/python_types/tutorial006.py!}
```
////
/// info
স্কোয়ার ব্রাকেট এর ভিতরে ব্যবহৃত এইসব অভন্তরীন টাইপগুলোকে "ইন্টারনাল টাইপ" বলে।
এই উদাহরণে, এটি হচ্ছে `List`(অথবা পাইথন ৩.৯ বা তার উপরের সংস্করণের ক্ষেত্রে `list`) এ পাস করা টাইপ প্যারামিটার।
///
এর অর্থ হচ্ছে: "ভেরিয়েবল `items` একটি `list`, এবং এই লিস্টের প্রতিটি আইটেম একটি `str`।"
/// tip
যদি আপনি Python 3.9 বা তার উপরে ব্যবহার করেন, আপনার `typing` থেকে `List` আমদানি করতে হবে না, আপনি সাধারণ `list` ওই টাইপের পরিবর্তে ব্যবহার করতে পারেন।
///
এর মাধ্যমে, আপনার এডিটর লিস্ট থেকে আইটেম প্রসেস করার সময় সাপোর্ট প্রদান করতে পারবে:
<img src="/img/python-types/image05.png">
টাইপগুলি ছাড়া, এটি করা প্রায় অসম্ভব।
লক্ষ্য করুন যে ভেরিয়েবল `item` হল `items` লিস্টের একটি এলিমেন্ট।
তবুও, এডিটর জানে যে এটি একটি `str`, এবং তার জন্য সাপোর্ট প্রদান করে।
#### টাপল এবং সেট
আপনি `tuple` এবং `set` ঘোষণা করার জন্য একই প্রক্রিয়া অনুসরণ করবেন:
//// tab | Python 3.9+
```Python hl_lines="1"
{!> ../../docs_src/python_types/tutorial007_py39.py!}
```
////
//// tab | Python 3.8+
```Python hl_lines="1 4"
{!> ../../docs_src/python_types/tutorial007.py!}
```
////
এর মানে হল:
* ভেরিয়েবল `items_t` হল একটি `tuple` যা ৩টি আইটেম ধারণ করে, একটি `int`, অন্য একটি `int`, এবং একটি `str`।
* ভেরিয়েবল `items_s` হল একটি `set`, এবং এর প্রতিটি আইটেম হল `bytes` টাইপের।
#### ডিক্ট
একটি `dict` সংজ্ঞায়িত করতে, আপনি ২টি টাইপ প্যারামিটার কমা দ্বারা পৃথক করে দেবেন।
প্রথম টাইপ প্যারামিটারটি হল `dict`-এর কীগুলির জন্য।
দ্বিতীয় টাইপ প্যারামিটারটি হল `dict`-এর মানগুলির জন্য:
//// tab | Python 3.9+
```Python hl_lines="1"
{!> ../../docs_src/python_types/tutorial008_py39.py!}
```
////
//// tab | Python 3.8+
```Python hl_lines="1 4"
{!> ../../docs_src/python_types/tutorial008.py!}
```
////
এর মানে হল:
* ভেরিয়েবল `prices` হল একটি `dict`:
* এই `dict`-এর কীগুলি হল `str` টাইপের (ধরা যাক, প্রতিটি আইটেমের নাম)।
* এই `dict`-এর মানগুলি হল `float` টাইপের (ধরা যাক, প্রতিটি আইটেমের দাম)।
#### ইউনিয়ন
আপনি একটি ভেরিয়েবলকে এমনভাবে ঘোষণা করতে পারেন যেন তা **একাধিক টাইপের** হয়, উদাহরণস্বরূপ, একটি `int` অথবা `str`।
Python 3.6 এবং তার উপরের সংস্করণগুলিতে (Python 3.10 অন্তর্ভুক্ত) আপনি `typing` থেকে `Union` টাইপ ব্যবহার করতে পারেন এবং স্কোয়ার ব্র্যাকেটের মধ্যে গ্রহণযোগ্য টাইপগুলি রাখতে পারেন।
Python 3.10-এ একটি **নতুন সিনট্যাক্স** আছে যেখানে আপনি সম্ভাব্য টাইপগুলিকে একটি <abbr title="উল্লম্ব বারালকে 'বিটওয়াইজ বা অপারেটর' বলা হয়, কিন্তু সেই অর্থ এখানে প্রাসঙ্গিক নয়">ভার্টিকাল বার (`|`)</abbr> দ্বারা পৃথক করতে পারেন।
//// tab | Python 3.10+
```Python hl_lines="1"
{!> ../../docs_src/python_types/tutorial008b_py310.py!}
```
////
//// tab | Python 3.8+
```Python hl_lines="1 4"
{!> ../../docs_src/python_types/tutorial008b.py!}
```
////
উভয় ক্ষেত্রেই এর মানে হল যে `item` হতে পারে একটি `int` অথবা `str`।
#### সম্ভবত `None`
আপনি এমনভাবে ঘোষণা করতে পারেন যে একটি মান হতে পারে এক টাইপের, যেমন `str`, আবার এটি `None`-ও হতে পারে।
Python 3.6 এবং তার উপরের সংস্করণগুলিতে (Python 3.10 অনতর্ভুক্ত) আপনি `typing` মডিউল থেকে `Optional` ইমপোর্ট করে এটি ঘোষণা এবং ব্যবহার করতে পারেন।
```Python hl_lines="1 4"
{!../../docs_src/python_types/tutorial009.py!}
```
`Optional[str]` ব্যবহার করা মানে হল শুধু `str` নয়, এটি হতে পারে `None`-ও, যা আপনার এডিটরকে সেই ত্রুটিগুলি শনাক্ত করতে সাহায্য করবে যেখানে আপনি ধরে নিচ্ছেন যে একটি মান সবসময় `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.8+
```Python hl_lines="1 4"
{!> ../../docs_src/python_types/tutorial009.py!}
```
////
//// tab | Python 3.8+ বিকল্প
```Python hl_lines="1 4"
{!> ../../docs_src/python_types/tutorial009b.py!}
```
////
#### `Union` বা `Optional` ব্যবহার
যদি আপনি Python 3.10-এর নীচের সংস্করণ ব্যবহার করেন, তবে এখানে আমার খুবই **ব্যক্তিগত** দৃষ্টিভঙ্গি থেকে একটি টিপস:
* 🚨 `Optional[SomeType]` ব্যবহার এড়িয়ে চলুন।
* এর পরিবর্তে ✨ **`Union[SomeType, None]` ব্যবহার করুন** ✨।
উভয়ই সমতুল্য এবং মূলে একই, কিন্তু আমি `Union`-এর পক্ষে সুপারিশ করব কারণ "**অপশনাল**" শব্দটি মনে হতে পারে যে মানটি ঐচ্ছিক,অথচ এটি আসলে মানে "এটি হতে পারে `None`", এমনকি যদি এটি ঐচ্ছিক না হয়েও আবশ্যিক হয়।
আমি মনে করি `Union[SomeType, None]` এর অর্থ আরও স্পষ্টভাবে প্রকাশ করে।
এটি কেবল শব্দ এবং নামের ব্যাপার। কিন্তু সেই শব্দগুলি আপনি এবং আপনার সহকর্মীরা কোড সম্পর্কে কীভাবে চিন্তা করেন তা প্রভাবিত করতে পারে।
একটি উদাহরণ হিসেবে, এই ফাংশনটি নিন:
{* ../../docs_src/python_types/tutorial009c.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` নিয়ে আর চিন্তা করতে হবে না। 😎
#### জেনেরিক টাইপস
স্কোয়ার ব্র্যাকেটে টাইপ প্যারামিটার নেওয়া এই টাইপগুলিকে **জেনেরিক টাইপ** বা **জেনেরিকস** বলা হয়, যেমন:
//// tab | Python 3.10+
আপনি সেই একই বিল্টইন টাইপ জেনেরিক্স হিসেবে ব্যবহার করতে পারবেন(ভিতরে টাইপ সহ স্কয়ারে ব্রাকেট দিয়ে):
* `list`
* `tuple`
* `set`
* `dict`
এবং Python 3.8 এর মতোই, `typing` মডিউল থেকে:
* `Union`
* `Optional` (Python 3.8 এর মতোই)
* ...এবং অন্যান্য।
Python 3.10-এ, `Union` এবং `Optional` জেনেরিকস ব্যবহার করার বিকল্প হিসেবে, আপনি টাইপগুলির ইউনিয়ন ঘোষণা করতে <abbr title="উল্লম্ব বারালকে 'বিটওয়াইজ বা অপারেটর' বলা হয়, কিন্তু সেই অর্থ এখানে প্রাসঙ্গিক নয়">ভার্টিকাল বার (`|`)</abbr> ব্যবহার করতে পারেন, যা ওদের থেকে অনেক ভালো এবং সহজ।
////
//// tab | Python 3.9+
আপনি সেই একই বিল্টইন টাইপ জেনেরিক্স হিসেবে ব্যবহার করতে পারবেন(ভিতরে টাইপ সহ স্কয়ারে ব্রাকেট দিয়ে):
* `list`
* `tuple`
* `set`
* `dict`
এবং Python 3.8 এর মতোই, `typing` মডিউল থেকে:
* `Union`
* `Optional`
* ...এবং অন্যান্য।
////
//// tab | Python 3.8+
* `List`
* `Tuple`
* `Set`
* `Dict`
* `Union`
* `Optional`
* ...এবং অন্যান্য।
////
### ক্লাস হিসেবে টাইপস
আপনি একটি ভেরিয়েবলের টাইপ হিসেবে একটি ক্লাস ঘোষণা করতে পারেন।
ধরুন আপনার কাছে `Person` নামে একটি ক্লাস আছে, যার একটি নাম আছে:
{* ../../docs_src/python_types/tutorial010.py hl[1:3] *}
তারপর আপনি একটি ভেরিয়েবলকে `Person` টাইপের হিসেবে ঘোষণা করতে পারেন:
{* ../../docs_src/python_types/tutorial010.py hl[6] *}
এবং তারপর, আবার, আপনি এডিটর সাপোর্ট পেয়ে যাবেন:
<img src="/img/python-types/image06.png">
লক্ষ্য করুন যে এর মানে হল "`one_person` হল ক্লাস `Person`-এর একটি **ইন্সট্যান্স**।"
এর মানে এটি নয় যে "`one_person` হল **ক্লাস** যাকে বলা হয় `Person`।"
## Pydantic মডেল
[Pydantic](https://docs.pydantic.dev/) হল একটি Python লাইব্রেরি যা ডাটা ভ্যালিডেশন সম্পাদন করে।
আপনি ডাটার "আকার" এট্রিবিউট সহ ক্লাস হিসেবে ঘোষণা করেন।
এবং প্রতিটি এট্রিবিউট এর একটি টাইপ থাকে।
তারপর আপনি যদি কিছু মান দিয়ে সেই ক্লাসের একটি ইন্সট্যান্স তৈরি করেন-- এটি মানগুলিকে ভ্যালিডেট করবে, প্রয়োজন অনুযায়ী তাদেরকে উপযুক্ত টাইপে রূপান্তর করবে এবং আপনাকে সমস্ত ডাটা সহ একটি অবজেক্ট প্রদান করবে।
এবং আপনি সেই ফলাফল অবজেক্টের সাথে এডিটর সাপোর্ট পাবেন।
অফিসিয়াল Pydantic ডক্স থেকে একটি উদাহরণ:
//// tab | Python 3.10+
```Python
{!> ../../docs_src/python_types/tutorial011_py310.py!}
```
////
//// tab | Python 3.9+
```Python
{!> ../../docs_src/python_types/tutorial011_py39.py!}
```
////
//// tab | Python 3.8+
```Python
{!> ../../docs_src/python_types/tutorial011.py!}
```
////
/// info
[Pydantic সম্পর্কে আরও জানতে, এর ডকুমেন্টেশন দেখুন](https://docs.pydantic.dev/)।
///
**FastAPI** মূলত Pydantic-এর উপর নির্মিত।
আপনি এই সমস্ত কিছুর অনেক বাস্তবসম্মত উদাহরণ পাবেন [টিউটোরিয়াল - ইউজার গাইডে](https://fastapi.tiangolo.com/tutorial/)।
/// tip
যখন আপনি `Optional` বা `Union[Something, None]` ব্যবহার করেন এবং কোনো ডিফল্ট মান না থাকে, Pydantic-এর একটি বিশেষ আচরণ রয়েছে, আপনি Pydantic ডকুমেন্টেশনে [Required Optional fields](https://docs.pydantic.dev/latest/concepts/models/#required-optional-fields) সম্পর্কে আরও পড়তে পারেন।
///
## মেটাডাটা অ্যানোটেশন সহ টাইপ হিন্টস
Python-এ এমন একটি ফিচার আছে যা `Annotated` ব্যবহার করে এই টাইপ হিন্টগুলিতে **অতিরিক্ত মেটাডাটা** রাখতে দেয়।
//// tab | Python 3.9+
Python 3.9-এ, `Annotated` স্ট্যান্ডার্ড লাইব্রেরিতে অন্তর্ভুক্ত, তাই আপনি এটি `typing` থেকে ইমপোর্ট করতে পারেন।
```Python hl_lines="1 4"
{!> ../../docs_src/python_types/tutorial013_py39.py!}
```
////
//// tab | Python 3.8+
Python 3.9-এর নীচের সংস্করণগুলিতে, আপনি `Annotated`-কে `typing_extensions` থেকে ইমপোর্ট করেন।
এটি **FastAPI** এর সাথে ইতিমদ্ধে ইনস্টল হয়ে থাকবে।
```Python hl_lines="1 4"
{!> ../../docs_src/python_types/tutorial013.py!}
```
////
Python নিজে এই `Annotated` দিয়ে কিছুই করে না। এবং এডিটর এবং অন্যান্য টুলগুলির জন্য, টাইপটি এখনও `str`।
কিন্তু আপনি এই `Annotated` এর মধ্যকার জায়গাটির মধ্যে **FastAPI**-এ কীভাবে আপনার অ্যাপ্লিকেশন আচরণ করুক তা সম্পর্কে অতিরিক্ত মেটাডাটা প্রদান করার জন্য ব্যবহার করতে পারেন।
মনে রাখার গুরুত্বপূর্ণ বিষয় হল যে **প্রথম *টাইপ প্যারামিটার*** আপনি `Annotated`-এ পাস করেন সেটি হল **আসল টাইপ**। বাকি শুধুমাত্র অন্যান্য টুলগুলির জন্য মেটাডাটা।
এখন আপনার কেবল জানা প্রয়োজন যে `Annotated` বিদ্যমান, এবং এটি স্ট্যান্ডার্ড Python। 😎
পরবর্তীতে আপনি দেখবেন এটি কতটা **শক্তিশালী** হতে পারে।
/// tip
এটি **স্ট্যান্ডার্ড Python** হওয়ার মানে হল আপনি আপনার এডিটরে, আপনি যে টুলগুলি কোড বিশ্লেষণ এবং রিফ্যাক্টর করার জন্য ব্যবহার করেন তাতে **সেরা সম্ভাব্য ডেভেলপার এক্সপেরিয়েন্স** পাবেন। ✨
এবং এছাড়াও আপনার কোড অন্যান্য অনেক Python টুল এবং লাইব্রেরিগুলির সাথে খুব সামঞ্জস্যপূর্ণ হবে। 🚀
///
## **FastAPI**-এ টাইপ হিন্টস
**FastAPI** এই টাইপ হিন্টগুলি ব্যবহার করে বেশ কিছু জিনিস করে।
**FastAPI**-এ আপনি টাইপ হিন্টগুলি সহ প্যারামিটার ঘোষণা করেন এবং আপনি পান:
* **এডিটর সাপোর্ট**।
* **টাইপচেক**।
...এবং **FastAPI** একই ঘোষণাগুলি ব্যবহার করে:
* **রিকুইরেমেন্টস সংজ্ঞায়িত করে**: রিকোয়েস্ট পাথ প্যারামিটার, কুয়েরি প্যারামিটার, হেডার, বডি, ডিপেন্ডেন্সিস, ইত্যাদি থেকে।
* **ডেটা রূপান্তর করে**: রিকোয়েস্ট থেকে প্রয়োজনীয় টাইপে ডেটা।
* **ডেটা যাচাই করে**: প্রতিটি রিকোয়েস্ট থেকে আসা ডেটা:
* যখন ডেটা অবৈধ হয় তখন **স্বয়ংক্রিয় ত্রুটি** গ্রাহকের কাছে ফেরত পাঠানো।
* **API ডকুমেন্টেশন তৈরি করে**: OpenAPI ব্যবহার করে:
* যা স্বয়ংক্রিয় ইন্টার‌্যাক্টিভ ডকুমেন্টেশন ইউজার ইন্টারফেস দ্বারা ব্যবহৃত হয়।
এই সব কিছু আপনার কাছে অস্পষ্ট মনে হতে পারে। চিন্তা করবেন না। আপনি [টিউটোরিয়াল - ইউজার গাইড](https://fastapi.tiangolo.com/tutorial/) এ এই সব কিছু প্র্যাকটিসে দেখতে পাবেন।
গুরুত্বপূর্ণ বিষয় হল, আপনি যদি স্ট্যান্ডার্ড Python টাইপগুলি ব্যবহার করেন, তবে আরও বেশি ক্লাস, ডেকোরেটর ইত্যাদি যোগ না করেই একই স্থানে **FastAPI** আপনার অনেক কাজ করে দিবে।
/// info
যদি আপনি টিউটোরিয়ালের সমস্ত বিষয় পড়ে ফেলে থাকেন এবং টাইপ সম্পর্কে আরও জানতে চান, তবে একটি ভালো রিসোর্স হল [mypy এর "cheat sheet"](https://mypy.readthedocs.io/en/latest/cheat_sheet_py3.html)। এই "cheat sheet" এ আপনি Python টাইপ হিন্ট সম্পর্কে বেসিক থেকে উন্নত লেভেলের ধারণা পেতে পারেন, যা আপনার কোডে টাইপ সেফটি এবং স্পষ্টতা বাড়াতে সাহায্য করবে।
///

View File

@@ -1 +0,0 @@
INHERIT: ../en/mkdocs.yml

View File

@@ -63,3 +63,91 @@ In den Kapiteln zum Thema Sicherheit gibt es Hilfsfunktionen, die auf die gleich
Wenn Sie das hier alles verstanden haben, wissen Sie bereits, wie diese Sicherheits-Hilfswerkzeuge unter der Haube funktionieren.
///
## Abhängigkeiten mit `yield`, `HTTPException`, `except` und Hintergrundtasks { #dependencies-with-yield-httpexception-except-and-background-tasks }
/// warning | Achtung
Sie benötigen diese technischen Details höchstwahrscheinlich nicht.
Diese Details sind hauptsächlich nützlich, wenn Sie eine FastAPI-Anwendung haben, die älter als 0.118.0 ist, und Sie auf Probleme mit Abhängigkeiten mit `yield` stoßen.
///
Abhängigkeiten mit `yield` haben sich im Laufe der Zeit weiterentwickelt, um verschiedene Anwendungsfälle abzudecken und einige Probleme zu beheben, hier ist eine Zusammenfassung der Änderungen.
### Abhängigkeiten mit `yield` und `StreamingResponse`, Technische Details { #dependencies-with-yield-and-streamingresponse-technical-details }
Vor FastAPI 0.118.0 wurde bei Verwendung einer Abhängigkeit mit `yield` der Exit-Code nach der *Pfadoperation-Funktion* ausgeführt, aber unmittelbar bevor die Response gesendet wurde.
Die Absicht war, Ressourcen nicht länger als nötig zu halten, während darauf gewartet wird, dass die Response durchs Netzwerk reist.
Diese Änderung bedeutete auch, dass bei Rückgabe einer `StreamingResponse` der Exit-Code der Abhängigkeit mit `yield` bereits ausgeführt worden wäre.
Wenn Sie beispielsweise eine Datenbanksession in einer Abhängigkeit mit `yield` hatten, konnte die `StreamingResponse` diese Session während des Streamens von Daten nicht verwenden, weil die Session im Exit-Code nach `yield` bereits geschlossen worden wäre.
Dieses Verhalten wurde in 0.118.0 zurückgenommen, sodass der Exit-Code nach `yield` ausgeführt wird, nachdem die Response gesendet wurde.
/// info | Info
Wie Sie unten sehen werden, ähnelt dies sehr dem Verhalten vor Version 0.106.0, jedoch mit mehreren Verbesserungen und Bugfixes für Sonderfälle.
///
#### Anwendungsfälle mit frühem Exit-Code { #use-cases-with-early-exit-code }
Es gibt einige Anwendungsfälle mit spezifischen Bedingungen, die vom alten Verhalten profitieren könnten, den Exit-Code von Abhängigkeiten mit `yield` vor dem Senden der Response auszuführen.
Stellen Sie sich zum Beispiel vor, Sie haben Code, der in einer Abhängigkeit mit `yield` eine Datenbanksession verwendet, nur um einen Benutzer zu verifizieren, die Datenbanksession wird aber in der *Pfadoperation-Funktion* nie wieder verwendet, sondern nur in der Abhängigkeit, und die Response benötigt lange, um gesendet zu werden, wie eine `StreamingResponse`, die Daten langsam sendet, aus irgendeinem Grund aber die Datenbank nicht verwendet.
In diesem Fall würde die Datenbanksession gehalten, bis das Senden der Response abgeschlossen ist, aber wenn Sie sie nicht verwenden, wäre es nicht notwendig, sie zu halten.
So könnte es aussehen:
{* ../../docs_src/dependencies/tutorial013_an_py310.py *}
Der Exit-Code, das automatische Schließen der `Session` in:
{* ../../docs_src/dependencies/tutorial013_an_py310.py ln[19:21] *}
... würde ausgeführt, nachdem die Response das langsame Senden der Daten beendet:
{* ../../docs_src/dependencies/tutorial013_an_py310.py ln[30:38] hl[31:33] *}
Da `generate_stream()` die Datenbanksession jedoch nicht verwendet, ist es nicht wirklich notwendig, die Session während des Sendens der Response offen zu halten.
Wenn Sie diesen spezifischen Anwendungsfall mit SQLModel (oder SQLAlchemy) haben, könnten Sie die Session explizit schließen, nachdem Sie sie nicht mehr benötigen:
{* ../../docs_src/dependencies/tutorial014_an_py310.py ln[24:28] hl[28] *}
Auf diese Weise würde die Session die Datenbankverbindung freigeben, sodass andere Requests sie verwenden könnten.
Wenn Sie einen anderen Anwendungsfall haben, der ein frühes Beenden aus einer Abhängigkeit mit `yield` benötigt, erstellen Sie bitte eine <a href="https://github.com/fastapi/fastapi/discussions/new?category=questions" class="external-link" target="_blank">GitHub-Diskussion-Frage</a> mit Ihrem spezifischen Anwendungsfall und warum Sie von einem frühen Schließen für Abhängigkeiten mit `yield` profitieren würden.
Wenn es überzeugende Anwendungsfälle für ein frühes Schließen bei Abhängigkeiten mit `yield` gibt, würde ich erwägen, eine neue Möglichkeit hinzuzufügen, um ein frühes Schließen optional zu aktivieren.
### Abhängigkeiten mit `yield` und `except`, Technische Details { #dependencies-with-yield-and-except-technical-details }
Vor FastAPI 0.110.0 war es so, dass wenn Sie eine Abhängigkeit mit `yield` verwendet und dann in dieser Abhängigkeit mit `except` eine Exception abgefangen haben und die Exception nicht erneut geworfen haben, die Exception automatisch an beliebige Exceptionhandler oder den Handler für interne Serverfehler weitergereicht/weitergeworfen wurde.
Dies wurde in Version 0.110.0 geändert, um unbehandelten Speicherverbrauch durch weitergeleitete Exceptions ohne Handler (interne Serverfehler) zu beheben und um es mit dem Verhalten von normalem Python-Code konsistent zu machen.
### Hintergrundtasks und Abhängigkeiten mit `yield`, Technische Details { #background-tasks-and-dependencies-with-yield-technical-details }
Vor FastAPI 0.106.0 war das Werfen von Exceptions nach `yield` nicht möglich, der Exit-Code in Abhängigkeiten mit `yield` wurde ausgeführt, nachdem die Response gesendet wurde, sodass [Exceptionhandler](../handling-errors.md#install-custom-exception-handlers){.internal-link target=_blank} bereits ausgeführt worden wären.
Dies war so designt, hauptsächlich um die Verwendung derselben von Abhängigkeiten „geyieldeten“ Objekte in Hintergrundtasks zu ermöglichen, da der Exit-Code erst ausgeführt wurde, nachdem die Hintergrundtasks abgeschlossen waren.
Dies wurde in FastAPI 0.106.0 geändert mit der Absicht, keine Ressourcen zu halten, während darauf gewartet wird, dass die Response durchs Netzwerk reist.
/// tip | Tipp
Zusätzlich ist ein Hintergrundtask normalerweise ein unabhängiger Logikblock, der separat gehandhabt werden sollte, mit eigenen Ressourcen (z. B. eigener Datenbankverbindung).
So haben Sie wahrscheinlich saubereren Code.
///
Wenn Sie sich bisher auf dieses Verhalten verlassen haben, sollten Sie jetzt die Ressourcen für Hintergrundtasks innerhalb des Hintergrundtasks selbst erstellen und intern nur Daten verwenden, die nicht von den Ressourcen von Abhängigkeiten mit `yield` abhängen.
Anstatt beispielsweise dieselbe Datenbanksession zu verwenden, würden Sie innerhalb des Hintergrundtasks eine neue Datenbanksession erstellen und die Objekte aus der Datenbank mithilfe dieser neuen Session beziehen. Und anstatt das Objekt aus der Datenbank als Parameter an die Hintergrundtask-Funktion zu übergeben, würden Sie die ID dieses Objekts übergeben und das Objekt dann innerhalb der Hintergrundtask-Funktion erneut beziehen.

View File

@@ -17,7 +17,7 @@ Wenn Sie Ihre API sichern möchten, gibt es mehrere bessere Dinge, die Sie tun k
* Stellen Sie sicher, dass Sie über gut definierte Pydantic-Modelle für Ihre <abbr title="Anfragekörper">Requestbodys</abbr> und <abbr title="Response Antwort: Daten, die der Server zum anfragenden Client zurücksendet">Responses</abbr> verfügen.
* Konfigurieren Sie alle erforderlichen Berechtigungen und Rollen mithilfe von Abhängigkeiten.
* Speichern Sie niemals Klartext-Passwörter, sondern nur Passwort-Hashes.
* Implementieren und verwenden Sie gängige kryptografische Tools wie Passlib und JWT-Tokens, usw.
* Implementieren und verwenden Sie gängige kryptografische Tools wie pwdlib und JWT-Tokens, usw.
* Fügen Sie bei Bedarf detailliertere Berechtigungskontrollen mit OAuth2-Scopes hinzu.
* ... usw.

View File

@@ -30,6 +30,16 @@ Um Cookies zu deklarieren, müssen Sie `Cookie` verwenden, da die Parameter sons
///
/// info | Info
Beachten Sie, dass **Browser Cookies auf besondere Weise und hinter den Kulissen handhaben** und **JavaScript** **nicht** ohne Weiteres erlauben, auf sie zuzugreifen.
Wenn Sie zur **API-Dokumentations-UI** unter `/docs` gehen, können Sie die **Dokumentation** zu Cookies für Ihre *Pfadoperationen* sehen.
Aber selbst wenn Sie die **Daten ausfüllen** und auf „Execute“ klicken, da die Dokumentations-UI mit **JavaScript** arbeitet, werden die Cookies nicht gesendet, und Sie sehen eine **Fehler**-Meldung, als hätten Sie keine Werte eingegeben.
///
## Zusammenfassung { #recap }
Deklarieren Sie Cookies mit `Cookie` und verwenden Sie dabei das gleiche allgemeine Muster wie bei `Query` und `Path`.

View File

@@ -1,6 +1,6 @@
# Abhängigkeiten mit `yield` { #dependencies-with-yield }
FastAPI unterstützt Abhängigkeiten, die nach Abschluss einige <abbr title="Manchmal auch genannt „Exit Code“, „Cleanup Code“, „Teardown Code“, „Closing Code“, „Kontext Manager Exit Code“, usw.">zusätzliche Schritte ausführen</abbr>.
FastAPI unterstützt Abhängigkeiten, die nach Abschluss einige <abbr title="Manchmal auch genannt „Exit Code“, „Cleanup Code“, „Teardown Code“, „Closing Code“, „Kontextmanager Exit Code“, usw.">zusätzliche Schritte ausführen</abbr>.
Verwenden Sie dazu `yield` statt `return` und schreiben Sie die zusätzlichen Schritte / den zusätzlichen Code danach.
@@ -35,7 +35,7 @@ Der ge`yield`ete Wert ist das, was in *Pfadoperationen* und andere Abhängigkeit
{* ../../docs_src/dependencies/tutorial007.py hl[4] *}
Der auf die `yield`-Anweisung folgende Code wird ausgeführt, nachdem die Response erstellt wurde, aber bevor sie gesendet wird:
Der auf die `yield`-Anweisung folgende Code wird nach der Response ausgeführt:
{* ../../docs_src/dependencies/tutorial007.py hl[5:6] *}
@@ -51,7 +51,7 @@ Sie können `async`- oder reguläre Funktionen verwenden.
Wenn Sie einen `try`-Block in einer Abhängigkeit mit `yield` verwenden, empfangen Sie alle Exceptions, die bei Verwendung der Abhängigkeit geworfen wurden.
Wenn beispielsweise ein Code irgendwann in der Mitte, in einer anderen Abhängigkeit oder in einer *Pfadoperation*, ein „Rollback“ einer Datenbanktransaktion oder einen anderen Fehler verursacht, empfangen Sie die resultierende Exception in Ihrer Abhängigkeit.
Wenn beispielsweise ein Code irgendwann in der Mitte, in einer anderen Abhängigkeit oder in einer *Pfadoperation*, ein „Rollback“ einer Datenbanktransaktion macht oder eine andere Exception verursacht, empfangen Sie die Exception in Ihrer Abhängigkeit.
Sie können also mit `except SomeException` diese bestimmte Exception innerhalb der Abhängigkeit handhaben.
@@ -95,9 +95,11 @@ Dieses funktioniert dank Pythons <a href="https://docs.python.org/3/library/cont
## Abhängigkeiten mit `yield` und `HTTPException` { #dependencies-with-yield-and-httpexception }
Sie haben gesehen, dass Ihre Abhängigkeiten `yield` verwenden können und `try`-Blöcke haben können, die Exceptions abfangen.
Sie haben gesehen, dass Sie Abhängigkeiten mit `yield` verwenden und `try`-Blöcke haben können, die versuchen, irgendeinen Code auszuführen und dann, nach `finally`, Exit-Code ausführen.
Auf die gleiche Weise könnten Sie im Exit-Code nach dem `yield` eine `HTTPException` oder ähnliches auslösen.
Sie können auch `except` verwenden, um die geworfene Exception abzufangen und damit etwas zu tun.
Zum Beispiel können Sie eine andere Exception auslösen, wie `HTTPException`.
/// tip | Tipp
@@ -109,7 +111,7 @@ Aber es ist für Sie da, wenn Sie es brauchen. 🤓
{* ../../docs_src/dependencies/tutorial008b_an_py39.py hl[18:22,31] *}
Eine Alternative zum Abfangen von Exceptions (und möglicherweise auch zum Auslösen einer weiteren `HTTPException`) besteht darin, einen [benutzerdefinierten Exceptionhandler](../handling-errors.md#install-custom-exception-handlers){.internal-link target=_blank} zu erstellen.
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}.
## Abhängigkeiten mit `yield` und `except` { #dependencies-with-yield-and-except }
@@ -121,7 +123,7 @@ In diesem Fall sieht der Client eine *HTTP 500 Internal Server Error*-Response,
### In Abhängigkeiten mit `yield` und `except` immer `raise` verwenden { #always-raise-in-dependencies-with-yield-and-except }
Wenn Sie eine Exception in einer Abhängigkeit mit `yield` abfangen, sollten Sie sofern Sie nicht eine andere `HTTPException` oder Ähnliches auslösen die ursprüngliche Exception erneut auslösen.
Wenn Sie eine Exception in einer Abhängigkeit mit `yield` abfangen, sollten Sie sofern Sie nicht eine andere `HTTPException` oder Ähnliches auslösen **die ursprüngliche Exception erneut auslösen**.
Sie können dieselbe Exception mit `raise` erneut auslösen:
@@ -178,48 +180,15 @@ Nachdem eine dieser Responses gesendet wurde, kann keine weitere Response gesend
/// tip | Tipp
Obiges Diagramm verwendet `HTTPException`, aber Sie können auch jede andere Exception auslösen, die Sie in einer Abhängigkeit mit `yield` abfangen, oder mit einem [benutzerdefinierten Exceptionhandler](../handling-errors.md#install-custom-exception-handlers){.internal-link target=_blank} erstellt haben.
Wenn Sie eine Exception auslösen, wird sie an die Abhängigkeiten mit `yield` weitergegeben, einschließlich `HTTPException`. In den meisten Fällen sollten Sie dieselbe Exception oder eine neue aus der Abhängigkeit mit `yield` erneut auslösen, um sicherzustellen, dass sie korrekt gehandhabt wird.
Wenn Sie in dem Code der *Pfadoperation-Funktion* irgendeine Exception auslösen, wird sie an die Abhängigkeiten mit `yield` weitergegeben, einschließlich `HTTPException`. In den meisten Fällen sollten Sie dieselbe Exception oder eine neue aus der Abhängigkeit mit `yield` erneut auslösen, um sicherzustellen, dass sie korrekt gehandhabt wird.
///
## Abhängigkeiten mit `yield`, `HTTPException`, `except` und Hintergrundtasks { #dependencies-with-yield-httpexception-except-and-background-tasks }
/// warning | Achtung
Sie benötigen diese technischen Details höchstwahrscheinlich nicht, Sie können diesen Abschnitt überspringen und weiter unten fortfahren.
Diese Details sind vor allem dann nützlich, wenn Sie eine Version von FastAPI vor 0.106.0 verwendet haben und Ressourcen aus Abhängigkeiten mit `yield` in Hintergrundtasks verwendet haben.
///
### Abhängigkeiten mit `yield` und `except`, technische Details { #dependencies-with-yield-and-except-technical-details }
Vor FastAPI 0.110.0 war es so, dass wenn Sie eine Abhängigkeit mit `yield` verwendeten und dort eine Exception mit `except` abfingen und die Exception nicht erneut auslösten, diese Exception automatisch an Exceptionhandler oder den internen Serverfehler-Handler weitergereicht/ausgelöst wurde.
Dies wurde in Version 0.110.0 geändert, um unbehandelte Speichernutzung durch weitergereichte Exceptions ohne Handler (interne Serverfehler) zu beheben und um das Verhalten an regulären Python-Code anzugleichen.
### Hintergrundtasks und Abhängigkeiten mit `yield`, technische Details { #background-tasks-and-dependencies-with-yield-technical-details }
Vor FastAPI 0.106.0 war das Auslösen von Exceptions nach `yield` nicht möglich, der Exit-Code in Abhängigkeiten mit `yield` wurde ausgeführt, *nachdem* die Response gesendet wurde, die [Exceptionhandler](../handling-errors.md#install-custom-exception-handlers){.internal-link target=_blank} wären also bereits ausgeführt worden.
Dies wurde hauptsächlich so konzipiert, damit die gleichen Objekte, die durch Abhängigkeiten ge`yield`et werden, innerhalb von Hintergrundtasks verwendet werden können, da der Exit-Code ausgeführt wird, nachdem die Hintergrundtasks abgeschlossen sind.
Da dies jedoch bedeuten würde, darauf zu warten, dass die Response durch das Netzwerk reist, während eine Ressource unnötigerweise in einer Abhängigkeit mit yield gehalten wird (z. B. eine Datenbankverbindung), wurde dies in FastAPI 0.106.0 geändert.
/// tip | Tipp
Darüber hinaus handelt es sich bei einem Hintergrundtask normalerweise um einen unabhängigen Satz von Logik, der separat behandelt werden sollte, mit eigenen Ressourcen (z. B. einer eigenen Datenbankverbindung).
Auf diese Weise erhalten Sie wahrscheinlich saubereren Code.
///
Wenn Sie sich früher auf dieses Verhalten verlassen haben, sollten Sie jetzt die Ressourcen für Hintergrundtasks innerhalb des Hintergrundtasks selbst erstellen und intern nur Daten verwenden, die nicht von den Ressourcen von Abhängigkeiten mit `yield` abhängen.
Anstatt beispielsweise dieselbe Datenbanksitzung zu verwenden, würden Sie eine neue Datenbanksitzung innerhalb des Hintergrundtasks erstellen und die Objekte mithilfe dieser neuen Sitzung aus der Datenbank abrufen. Und anstatt das Objekt aus der Datenbank als Parameter an die Hintergrundtask-Funktion zu übergeben, würden Sie die ID dieses Objekts übergeben und das Objekt dann innerhalb der Hintergrundtask-Funktion erneut laden.
Abhängigkeiten mit `yield` haben sich im Laufe der Zeit weiterentwickelt, um verschiedene Anwendungsfälle abzudecken und einige Probleme zu beheben.
Wenn Sie sehen möchten, was sich in verschiedenen Versionen von FastAPI geändert hat, lesen Sie mehr dazu im fortgeschrittenen Teil, unter [Fortgeschrittene Abhängigkeiten Abhängigkeiten mit `yield`, `HTTPException`, `except` und Hintergrundtasks](../../advanced/advanced-dependencies.md#dependencies-with-yield-httpexception-except-and-background-tasks){.internal-link target=_blank}.
## Kontextmanager { #context-managers }
### Was sind „Kontextmanager“ { #what-are-context-managers }

View File

@@ -54,18 +54,8 @@ Für **FastAPI** spielt es keine Rolle. Es erkennt die Parameter anhand ihrer Na
Sie können Ihre Funktion also so deklarieren:
//// tab | Python 3.8 nicht annotiert
/// tip | Tipp
Bevorzugen Sie die `Annotated`-Version, falls möglich.
///
{* ../../docs_src/path_params_numeric_validations/tutorial002.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 *}

View File

@@ -64,20 +64,20 @@ Wenn Ihre Datenbank gestohlen wird, hat der Dieb nicht die Klartext-Passwörter
Der Dieb kann also nicht versuchen, die gleichen Passwörter in einem anderen System zu verwenden (da viele Benutzer überall das gleiche Passwort verwenden, wäre dies gefährlich).
## `passlib` installieren { #install-passlib }
## `pwdlib` installieren { #install-pwdlib }
PassLib ist ein großartiges Python-Package, um Passwort-Hashes zu handhaben.
pwdlib ist ein großartiges Python-Package, um Passwort-Hashes zu handhaben.
Es unterstützt viele sichere Hashing-Algorithmen und Werkzeuge, um mit diesen zu arbeiten.
Der empfohlene Algorithmus ist „Bcrypt“.
Der empfohlene Algorithmus ist „Argon2“.
Stellen Sie sicher, dass Sie eine [virtuelle Umgebung](../../virtual-environments.md){.internal-link target=_blank} erstellen, sie aktivieren, und installieren Sie dann PassLib mit Bcrypt:
Stellen Sie sicher, dass Sie eine [virtuelle Umgebung](../../virtual-environments.md){.internal-link target=_blank} erstellen, sie aktivieren, und installieren Sie dann pwdlib mit Argon2:
<div class="termy">
```console
$ pip install "passlib[bcrypt]"
$ pip install "pwdlib[argon2]"
---> 100%
```
@@ -86,7 +86,7 @@ $ pip install "passlib[bcrypt]"
/// tip | Tipp
Mit `passlib` können Sie sogar konfigurieren, Passwörter zu lesen, die von **Django**, einem **Flask**-Sicherheit-Plugin, oder vielen anderen erstellt wurden.
Mit `pwdlib` können Sie sogar konfigurieren, Passwörter zu lesen, die von **Django**, einem **Flask**-Sicherheits-Plugin, oder vielen anderen erstellt wurden.
So könnten Sie beispielsweise die gleichen Daten aus einer Django-Anwendung in einer Datenbank mit einer FastAPI-Anwendung teilen. Oder schrittweise eine Django-Anwendung migrieren, während Sie dieselbe Datenbank verwenden.
@@ -96,15 +96,15 @@ Und Ihre Benutzer könnten sich gleichzeitig über Ihre Django-Anwendung oder Ih
## Die Passwörter hashen und überprüfen { #hash-and-verify-the-passwords }
Importieren Sie die benötigten Tools aus `passlib`.
Importieren Sie die benötigten Tools aus `pwdlib`.
Erstellen Sie einen PassLib-„Kontext“. Der wird für das Hashen und Verifizieren von Passwörtern verwendet.
Erstellen Sie eine PasswordHash-Instanz mit empfohlenen Einstellungen sie wird für das Hashen und Verifizieren von Passwörtern verwendet.
/// tip | Tipp
Der PassLib-Kontext kann auch andere Hashing-Algorithmen verwenden, einschließlich <abbr title="veraltet, obsolet: Es soll nicht mehr verwendet werden">deprecateter</abbr> Alter, um etwa nur eine Verifizierung usw. zu ermöglichen.
pwdlib unterstützt auch den bcrypt-Hashing-Algorithmus, enthält jedoch keine Legacy-Algorithmen für die Arbeit mit veralteten Hashes wird die Verwendung der Bibliothek passlib empfohlen.
Sie könnten ihn beispielsweise verwenden, um von einem anderen System (wie Django) generierte Passwörter zu lesen und zu verifizieren, aber alle neuen Passwörter mit einem anderen Algorithmus wie Bcrypt zu hashen.
Sie könnten sie beispielsweise verwenden, um von einem anderen System (wie Django) generierte Passwörter zu lesen und zu verifizieren, aber alle neuen Passwörter mit einem anderen Algorithmus wie Argon2 oder Bcrypt zu hashen.
Und mit allen gleichzeitig kompatibel sein.
@@ -120,7 +120,7 @@ Und noch eine, um einen Benutzer zu authentifizieren und zurückzugeben.
/// note | Hinweis
Wenn Sie sich die neue (gefakte) Datenbank `fake_users_db` anschauen, sehen Sie, wie das gehashte Passwort jetzt aussieht: `"$2b$12$EixZaYVK1fsbw1ZfbX3OXePaWxn96p36WQoeG6Lruj3vjPGga31lW"`.
Wenn Sie sich die neue (gefakte) Datenbank `fake_users_db` anschauen, sehen Sie, wie das gehashte Passwort jetzt aussieht: `"$argon2id$v=19$m=65536,t=3,p=4$wagCPXjifgvUFBzq4hqe3w$CYaIb8sB+wtD+Vu/P4uod1+Qof8h+1g7bbDlBID48Rc"`.
///
@@ -264,7 +264,7 @@ Viele Packages, die es stark vereinfachen, müssen viele Kompromisse beim Datenm
Es gibt Ihnen die volle Flexibilität, diejenigen auszuwählen, die am besten zu Ihrem Projekt passen.
Und Sie können viele gut gepflegte und weit verbreitete Packages wie `passlib` und `PyJWT` direkt verwenden, da **FastAPI** keine komplexen Mechanismen zur Integration externer Pakete erfordert.
Und Sie können viele gut gepflegte und weit verbreitete Packages wie `pwdlib` und `PyJWT` direkt verwenden, da **FastAPI** keine komplexen Mechanismen zur Integration externer Pakete erfordert.
Aber es bietet Ihnen die Werkzeuge, um den Prozess so weit wie möglich zu vereinfachen, ohne Kompromisse bei Flexibilität, Robustheit oder Sicherheit einzugehen.

View File

@@ -1,21 +1,21 @@
tiangolo:
login: tiangolo
count: 776
count: 782
avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4
url: https://github.com/tiangolo
dependabot:
login: dependabot
count: 113
count: 117
avatarUrl: https://avatars.githubusercontent.com/in/29110?v=4
url: https://github.com/apps/dependabot
alejsdev:
login: alejsdev
count: 48
avatarUrl: https://avatars.githubusercontent.com/u/90076947?u=638c65283ac9e9e2c3a0f9d1e3370db4b8a2c58d&v=4
count: 52
avatarUrl: https://avatars.githubusercontent.com/u/90076947?u=447d12a1b347f466b35378bee4c7104cc9b2c571&v=4
url: https://github.com/alejsdev
pre-commit-ci:
login: pre-commit-ci
count: 41
count: 45
avatarUrl: https://avatars.githubusercontent.com/in/68672?v=4
url: https://github.com/apps/pre-commit-ci
github-actions:
@@ -25,7 +25,7 @@ github-actions:
url: https://github.com/apps/github-actions
Kludex:
login: Kludex
count: 23
count: 24
avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=df8a3f06ba8f55ae1967a3e2d5ed882903a4e330&v=4
url: https://github.com/Kludex
dmontagu:
@@ -38,21 +38,31 @@ euri10:
count: 13
avatarUrl: https://avatars.githubusercontent.com/u/1104190?u=321a2e953e6645a7d09b732786c7a8061e0f8a8b&v=4
url: https://github.com/euri10
nilslindemann:
login: nilslindemann
count: 13
avatarUrl: https://avatars.githubusercontent.com/u/6892179?u=1dca6a22195d6cd1ab20737c0e19a4c55d639472&v=4
url: https://github.com/nilslindemann
kantandane:
login: kantandane
count: 13
avatarUrl: https://avatars.githubusercontent.com/u/3978368?u=cccc199291f991a73b1ebba5abc735a948e0bd16&v=4
url: https://github.com/kantandane
nilslindemann:
login: nilslindemann
svlandeg:
login: svlandeg
count: 11
avatarUrl: https://avatars.githubusercontent.com/u/6892179?u=1dca6a22195d6cd1ab20737c0e19a4c55d639472&v=4
url: https://github.com/nilslindemann
avatarUrl: https://avatars.githubusercontent.com/u/8796347?u=556c97650c27021911b0b9447ec55e75987b0e8a&v=4
url: https://github.com/svlandeg
zhaohan-dong:
login: zhaohan-dong
count: 11
avatarUrl: https://avatars.githubusercontent.com/u/65422392?u=8260f8781f50248410ebfa4c9bf70e143fe5c9f2&v=4
url: https://github.com/zhaohan-dong
YuriiMotov:
login: YuriiMotov
count: 10
avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=b9b13d598dddfab529a52d264df80a900bfe7060&v=4
url: https://github.com/YuriiMotov
mariacamilagl:
login: mariacamilagl
count: 9
@@ -68,21 +78,16 @@ vishnuvskvkl:
count: 8
avatarUrl: https://avatars.githubusercontent.com/u/84698110?u=8af5de0520dd4fa195f53c2850a26f57c0f6bc64&v=4
url: https://github.com/vishnuvskvkl
svlandeg:
login: svlandeg
count: 7
avatarUrl: https://avatars.githubusercontent.com/u/8796347?u=556c97650c27021911b0b9447ec55e75987b0e8a&v=4
url: https://github.com/svlandeg
alissadb:
login: alissadb
count: 6
avatarUrl: https://avatars.githubusercontent.com/u/96190409?u=be42d85938c241be781505a5a872575be28b2906&v=4
url: https://github.com/alissadb
YuriiMotov:
login: YuriiMotov
alv2017:
login: alv2017
count: 6
avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=b9b13d598dddfab529a52d264df80a900bfe7060&v=4
url: https://github.com/YuriiMotov
avatarUrl: https://avatars.githubusercontent.com/u/31544722?v=4
url: https://github.com/alv2017
wshayes:
login: wshayes
count: 5
@@ -103,11 +108,6 @@ krishnamadhavan:
count: 5
avatarUrl: https://avatars.githubusercontent.com/u/31798870?u=950693b28f3ae01105fd545c046e46ca3d31ab06&v=4
url: https://github.com/krishnamadhavan
alv2017:
login: alv2017
count: 5
avatarUrl: https://avatars.githubusercontent.com/u/31544722?v=4
url: https://github.com/alv2017
jekirl:
login: jekirl
count: 4
@@ -133,6 +133,11 @@ iudeen:
count: 4
avatarUrl: https://avatars.githubusercontent.com/u/10519440?u=f09cdd745e5bf16138f29b42732dd57c7f02bee1&v=4
url: https://github.com/iudeen
musicinmybrain:
login: musicinmybrain
count: 4
avatarUrl: https://avatars.githubusercontent.com/u/6898909?u=9010312053e7141383b9bdf538036c7f37fbaba0&v=4
url: https://github.com/musicinmybrain
philipokiokio:
login: philipokiokio
count: 4
@@ -186,7 +191,7 @@ Serrones:
uriyyo:
login: uriyyo
count: 3
avatarUrl: https://avatars.githubusercontent.com/u/32038156?u=a27b65a9ec3420586a827a0facccbb8b6df1ffb3&v=4
avatarUrl: https://avatars.githubusercontent.com/u/32038156?u=0c68019beb28381ce5205a838937c61e0fe3fee2&v=4
url: https://github.com/uriyyo
andrew222651:
login: andrew222651
@@ -243,16 +248,11 @@ papb:
count: 3
avatarUrl: https://avatars.githubusercontent.com/u/20914054?u=890511fae7ea90d887e2a65ce44a1775abba38d5&v=4
url: https://github.com/papb
musicinmybrain:
login: musicinmybrain
tamird:
login: tamird
count: 3
avatarUrl: https://avatars.githubusercontent.com/u/6898909?u=9010312053e7141383b9bdf538036c7f37fbaba0&v=4
url: https://github.com/musicinmybrain
gitworkflows:
login: gitworkflows
count: 3
avatarUrl: https://avatars.githubusercontent.com/u/118260833?v=4
url: https://github.com/gitworkflows
avatarUrl: https://avatars.githubusercontent.com/u/1535036?v=4
url: https://github.com/tamird
Nimitha-jagadeesha:
login: Nimitha-jagadeesha
count: 3
@@ -296,7 +296,7 @@ kabirkhan:
zamiramir:
login: zamiramir
count: 2
avatarUrl: https://avatars.githubusercontent.com/u/40475662?u=e58ef61034e8d0d6a312cc956fb09b9c3332b449&v=4
avatarUrl: https://avatars.githubusercontent.com/u/40475662?v=4
url: https://github.com/zamiramir
trim21:
login: trim21
@@ -331,7 +331,7 @@ svalouch:
frankie567:
login: frankie567
count: 2
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
marier-nico:
login: marier-nico
@@ -486,7 +486,7 @@ nzig:
yezz123:
login: yezz123
count: 2
avatarUrl: https://avatars.githubusercontent.com/u/52716203?u=d7062cbc6eb7671d5dc9cc0e32a24ae335e0f225&v=4
avatarUrl: https://avatars.githubusercontent.com/u/52716203?u=21b53ce4115062b1e20cb513e64ca0000c2ef127&v=4
url: https://github.com/yezz123
softwarebloat:
login: softwarebloat
@@ -518,11 +518,6 @@ estebanx64:
count: 2
avatarUrl: https://avatars.githubusercontent.com/u/10840422?u=1900887aeed268699e5ea6f3fb7db614f7b77cd3&v=4
url: https://github.com/estebanx64
tamird:
login: tamird
count: 2
avatarUrl: https://avatars.githubusercontent.com/u/1535036?v=4
url: https://github.com/tamird
ndimares:
login: ndimares
count: 2

View File

@@ -1,5 +1,9 @@
Articles:
English:
- author: Apitally
author_link: https://apitally.io
link: https://apitally.io/blog/getting-started-with-logging-in-fastapi
title: Getting started with logging in FastAPI
- author: Balthazar Rouberol
author_link: https://balthazar-rouberol.com
link: https://blog.balthazar-rouberol.com/how-to-profile-a-fastapi-asynchronous-request

View File

@@ -80,18 +80,18 @@ sponsors:
- - login: primer-io
avatarUrl: https://avatars.githubusercontent.com/u/62146168?v=4
url: https://github.com/primer-io
- - login: upciti
- - login: nilslindemann
avatarUrl: https://avatars.githubusercontent.com/u/6892179?u=1dca6a22195d6cd1ab20737c0e19a4c55d639472&v=4
url: https://github.com/nilslindemann
- login: upciti
avatarUrl: https://avatars.githubusercontent.com/u/43346262?v=4
url: https://github.com/upciti
- login: giunio-prc
avatarUrl: https://avatars.githubusercontent.com/u/59511892?u=b37c1f1e177a4ee0212d24fb1f15edc9b23fd132&v=4
url: https://github.com/giunio-prc
- login: thisisfixer
avatarUrl: https://avatars.githubusercontent.com/u/14433035?u=076d52a5b7891c764904af9f462bfb45428e25df&v=4
url: https://github.com/thisisfixer
- - login: samuelcolvin
avatarUrl: https://avatars.githubusercontent.com/u/4039449?u=42eb3b833047c8c4b4f647a031eaef148c16d93f&v=4
url: https://github.com/samuelcolvin
- login: vincentkoc
avatarUrl: https://avatars.githubusercontent.com/u/25068?u=fbd5b2d51142daa4bdbc21e21953a3b8b8188a4a&v=4
url: https://github.com/vincentkoc
- login: otosky
avatarUrl: https://avatars.githubusercontent.com/u/42260747?u=69d089387c743d89427aa4ad8740cfb34045a9e0&v=4
url: https://github.com/otosky
@@ -101,9 +101,6 @@ sponsors:
- login: roboflow
avatarUrl: https://avatars.githubusercontent.com/u/53104118?v=4
url: https://github.com/roboflow
- login: RaamEEIL
avatarUrl: https://avatars.githubusercontent.com/u/20320552?v=4
url: https://github.com/RaamEEIL
- login: ehaca
avatarUrl: https://avatars.githubusercontent.com/u/25950317?u=cec1a3e0643b785288ae8260cc295a85ab344995&v=4
url: https://github.com/ehaca
@@ -116,9 +113,6 @@ sponsors:
- login: Leay15
avatarUrl: https://avatars.githubusercontent.com/u/32212558?u=c4aa9c1737e515959382a5515381757b1fd86c53&v=4
url: https://github.com/Leay15
- login: chickenandstats
avatarUrl: https://avatars.githubusercontent.com/u/79477966?u=ae2b894aa954070db1d7830dab99b49eba4e4567&v=4
url: https://github.com/chickenandstats
- login: kaoru0310
avatarUrl: https://avatars.githubusercontent.com/u/80977929?u=1b61d10142b490e56af932ddf08a390fae8ee94f&v=4
url: https://github.com/kaoru0310
@@ -137,15 +131,15 @@ sponsors:
- login: patsatsia
avatarUrl: https://avatars.githubusercontent.com/u/61111267?u=3271b85f7a37b479c8d0ae0a235182e83c166edf&v=4
url: https://github.com/patsatsia
- login: secrett2633
avatarUrl: https://avatars.githubusercontent.com/u/65999962?v=4
url: https://github.com/secrett2633
- login: anthonycepeda
avatarUrl: https://avatars.githubusercontent.com/u/72019805?u=60bdf46240cff8fca482ff0fc07d963fd5e1a27c&v=4
url: https://github.com/anthonycepeda
- login: patricioperezv
avatarUrl: https://avatars.githubusercontent.com/u/73832292?u=5f471f156e19ee7920e62ae0f4a47b95580e61cf&v=4
url: https://github.com/patricioperezv
- login: chickenandstats
avatarUrl: https://avatars.githubusercontent.com/u/79477966?u=ae2b894aa954070db1d7830dab99b49eba4e4567&v=4
url: https://github.com/chickenandstats
- login: dodo5522
avatarUrl: https://avatars.githubusercontent.com/u/1362607?u=9bf1e0e520cccc547c046610c468ce6115bbcf9f&v=4
url: https://github.com/dodo5522
@@ -176,18 +170,15 @@ sponsors:
- login: Ryandaydev
avatarUrl: https://avatars.githubusercontent.com/u/4292423?u=679ff84cb7b988c5795a5fa583857f574a055763&v=4
url: https://github.com/Ryandaydev
- login: jaredtrog
avatarUrl: https://avatars.githubusercontent.com/u/4381365?v=4
url: https://github.com/jaredtrog
- login: vincentkoc
avatarUrl: https://avatars.githubusercontent.com/u/25068?u=fbd5b2d51142daa4bdbc21e21953a3b8b8188a4a&v=4
url: https://github.com/vincentkoc
- login: jstanden
avatarUrl: https://avatars.githubusercontent.com/u/63288?u=c3658d57d2862c607a0e19c2101c3c51876e36ad&v=4
url: https://github.com/jstanden
- login: paulcwatts
avatarUrl: https://avatars.githubusercontent.com/u/150269?u=1819e145d573b44f0ad74b87206d21cd60331d4e&v=4
url: https://github.com/paulcwatts
- login: andreaso
avatarUrl: https://avatars.githubusercontent.com/u/285964?u=837265cc7562c0685f25b2d81cd9de0434fe107c&v=4
url: https://github.com/andreaso
- login: robintw
avatarUrl: https://avatars.githubusercontent.com/u/296686?v=4
url: https://github.com/robintw
@@ -212,9 +203,6 @@ sponsors:
- login: jsoques
avatarUrl: https://avatars.githubusercontent.com/u/12414216?u=620921d94196546cc8b9eae2cc4cbc3f95bab42f&v=4
url: https://github.com/jsoques
- login: joeds13
avatarUrl: https://avatars.githubusercontent.com/u/13631604?u=628eb122e08bef43767b3738752b883e8e7f6259&v=4
url: https://github.com/joeds13
- login: dannywade
avatarUrl: https://avatars.githubusercontent.com/u/13680237?u=418ee985bd41577b20fde81417fb2d901e875e8a&v=4
url: https://github.com/dannywade
@@ -227,6 +215,12 @@ sponsors:
- login: ashi-agrawal
avatarUrl: https://avatars.githubusercontent.com/u/17105294?u=99c7a854035e5398d8e7b674f2d42baae6c957f8&v=4
url: https://github.com/ashi-agrawal
- login: RaamEEIL
avatarUrl: https://avatars.githubusercontent.com/u/20320552?v=4
url: https://github.com/RaamEEIL
- login: jaredtrog
avatarUrl: https://avatars.githubusercontent.com/u/4381365?v=4
url: https://github.com/jaredtrog
- login: oliverxchen
avatarUrl: https://avatars.githubusercontent.com/u/4471774?u=534191f25e32eeaadda22dfab4b0a428733d5489&v=4
url: https://github.com/oliverxchen
@@ -251,9 +245,6 @@ sponsors:
- - login: pawamoy
avatarUrl: https://avatars.githubusercontent.com/u/3999221?u=b030e4c89df2f3a36bc4710b925bdeb6745c9856&v=4
url: https://github.com/pawamoy
- login: petercool
avatarUrl: https://avatars.githubusercontent.com/u/37613029?u=75aa8c6729e6e8f85a300561c4dbeef9d65c8797&v=4
url: https://github.com/petercool
- login: siavashyj
avatarUrl: https://avatars.githubusercontent.com/u/43583410?u=562005ddc7901cd27a1219a118a2363817b14977&v=4
url: https://github.com/siavashyj
@@ -264,14 +255,11 @@ sponsors:
avatarUrl: https://avatars.githubusercontent.com/u/44609997?v=4
url: https://github.com/ArtyomVancyan
- login: caviri
avatarUrl: https://avatars.githubusercontent.com/u/45425937?u=4e14bd64282bad8f385eafbdb004b5a279366d6e&v=4
avatarUrl: https://avatars.githubusercontent.com/u/45425937?u=5f3d66ea5edea94c028c51ebf1c0f3b37e6c3db5&v=4
url: https://github.com/caviri
- login: hgalytoby
avatarUrl: https://avatars.githubusercontent.com/u/50397689?u=6cc9028f3db63f8f60ad21c17b1ce4b88c4e2e60&v=4
url: https://github.com/hgalytoby
- login: joshuatz
avatarUrl: https://avatars.githubusercontent.com/u/17817563?u=f1bf05b690d1fc164218f0b420cdd3acb7913e21&v=4
url: https://github.com/joshuatz
- login: nisutec
avatarUrl: https://avatars.githubusercontent.com/u/25281462?u=e562484c451fdfc59053163f64405f8eb262b8b0&v=4
url: https://github.com/nisutec
@@ -287,6 +275,12 @@ sponsors:
- login: bnkc
avatarUrl: https://avatars.githubusercontent.com/u/34930566?u=db5e6f4f87836cad26c2aa90ce390ce49041c5a9&v=4
url: https://github.com/bnkc
- login: petercool
avatarUrl: https://avatars.githubusercontent.com/u/37613029?u=75aa8c6729e6e8f85a300561c4dbeef9d65c8797&v=4
url: https://github.com/petercool
- login: JulioPeixoto
avatarUrl: https://avatars.githubusercontent.com/u/96303574?u=27d4614350cae33653f1be35cb47c92a12627ac9&v=4
url: https://github.com/JulioPeixoto
- login: johnl28
avatarUrl: https://avatars.githubusercontent.com/u/54412955?u=47dd06082d1c39caa90c752eb55566e4f3813957&v=4
url: https://github.com/johnl28
@@ -308,6 +302,9 @@ sponsors:
- login: Alisa-lisa
avatarUrl: https://avatars.githubusercontent.com/u/4137964?u=e7e393504f554f4ff15863a1e01a5746863ef9ce&v=4
url: https://github.com/Alisa-lisa
- login: moonape1226
avatarUrl: https://avatars.githubusercontent.com/u/8532038?u=d9f8b855a429fff9397c3833c2ff83849ebf989d&v=4
url: https://github.com/moonape1226
- login: ddanier
avatarUrl: https://avatars.githubusercontent.com/u/113563?u=ed1dc79de72f93bd78581f88ebc6952b62f472da&v=4
url: https://github.com/ddanier
@@ -323,9 +320,6 @@ sponsors:
- login: tochikuji
avatarUrl: https://avatars.githubusercontent.com/u/851759?v=4
url: https://github.com/tochikuji
- login: moonape1226
avatarUrl: https://avatars.githubusercontent.com/u/8532038?u=d9f8b855a429fff9397c3833c2ff83849ebf989d&v=4
url: https://github.com/moonape1226
- login: xncbf
avatarUrl: https://avatars.githubusercontent.com/u/9462045?u=a80a7bb349555b277645632ed66639ff43400614&v=4
url: https://github.com/xncbf
@@ -341,15 +335,15 @@ sponsors:
- login: mntolia
avatarUrl: https://avatars.githubusercontent.com/u/10390224?v=4
url: https://github.com/mntolia
- login: pheanex
avatarUrl: https://avatars.githubusercontent.com/u/10408624?u=5b6bab6ee174aa6e991333e06eb29f628741013d&v=4
url: https://github.com/pheanex
- login: Zuzah
avatarUrl: https://avatars.githubusercontent.com/u/10934846?u=1ef43e075ddc87bd1178372bf4d95ee6175cae27&v=4
url: https://github.com/Zuzah
- login: TheR1D
avatarUrl: https://avatars.githubusercontent.com/u/16740832?u=b0dfdbdb27b79729430c71c6128962f77b7b53f7&v=4
url: https://github.com/TheR1D
- login: joshuatz
avatarUrl: https://avatars.githubusercontent.com/u/17817563?u=f1bf05b690d1fc164218f0b420cdd3acb7913e21&v=4
url: https://github.com/joshuatz
- login: danielunderwood
avatarUrl: https://avatars.githubusercontent.com/u/4472301?v=4
url: https://github.com/danielunderwood
@@ -359,9 +353,6 @@ sponsors:
- login: sdevkota
avatarUrl: https://avatars.githubusercontent.com/u/5250987?u=4ed9a120c89805a8aefda1cbdc0cf6512e64d1b4&v=4
url: https://github.com/sdevkota
- login: brizzbuzz
avatarUrl: https://avatars.githubusercontent.com/u/5607577?u=58d5aae33bc97e52f11f334d2702e8710314b5c1&v=4
url: https://github.com/brizzbuzz
- login: Baghdady92
avatarUrl: https://avatars.githubusercontent.com/u/5708590?v=4
url: https://github.com/Baghdady92
@@ -374,10 +365,7 @@ sponsors:
- login: harsh183
avatarUrl: https://avatars.githubusercontent.com/u/7780198?v=4
url: https://github.com/harsh183
- - login: andrecorumba
avatarUrl: https://avatars.githubusercontent.com/u/37807517?u=9b9be3b41da9bda60957da9ef37b50dbf65baa61&v=4
url: https://github.com/andrecorumba
- login: KOZ39
- - login: KOZ39
avatarUrl: https://avatars.githubusercontent.com/u/38822500?u=9dfc0a697df1c9628f08e20dc3fb17b1afc4e5a7&v=4
url: https://github.com/KOZ39
- login: rwxd
@@ -386,18 +374,27 @@ sponsors:
- login: morzan1001
avatarUrl: https://avatars.githubusercontent.com/u/47593005?u=c30ab7230f82a12a9b938dcb54f84a996931409a&v=4
url: https://github.com/morzan1001
- login: azharthegeek
avatarUrl: https://avatars.githubusercontent.com/u/51288109?u=0987b2a9f39c21ccb071b6bdce0fc60d8492f8e8&v=4
url: https://github.com/azharthegeek
- login: Olegt0rr
avatarUrl: https://avatars.githubusercontent.com/u/25399456?u=3e87b5239a2f4600975ba13be73054f8567c6060&v=4
url: https://github.com/Olegt0rr
- login: larsyngvelundin
avatarUrl: https://avatars.githubusercontent.com/u/34173819?u=74958599695bf83ac9f1addd935a51548a10c6b0&v=4
url: https://github.com/larsyngvelundin
- login: henriquesebastiao
avatarUrl: https://avatars.githubusercontent.com/u/85202803?u=1b31ff01127bd267a87c97ff6319c77d91be606f&v=4
url: https://github.com/henriquesebastiao
- login: olexkram
avatarUrl: https://avatars.githubusercontent.com/u/148793576?v=4
url: https://github.com/olexkram
- login: andrecorumba
avatarUrl: https://avatars.githubusercontent.com/u/37807517?u=9b9be3b41da9bda60957da9ef37b50dbf65baa61&v=4
url: https://github.com/andrecorumba
- login: ChenPu2002
avatarUrl: https://avatars.githubusercontent.com/u/113831763?v=4
url: https://github.com/ChenPu2002
- login: CoderDeltaLAN
avatarUrl: https://avatars.githubusercontent.com/u/152043745?u=4ff541efffb7d134e60c5fcf2dd1e343f90bb782&v=4
url: https://github.com/CoderDeltaLAN
- login: aghents
avatarUrl: https://avatars.githubusercontent.com/u/60949885?u=d8616ddf22cf998a712cdceefd6a0256a178fe9d&v=4
url: https://github.com/aghents
- login: 0ne-stone
avatarUrl: https://avatars.githubusercontent.com/u/62360849?u=746dd21c34e7e06eefb11b03e8bb01aaae3c2a4f&v=4
url: https://github.com/0ne-stone
@@ -410,9 +407,6 @@ sponsors:
- login: andreagrandi
avatarUrl: https://avatars.githubusercontent.com/u/636391?u=13d90cb8ec313593a5b71fbd4e33b78d6da736f5&v=4
url: https://github.com/andreagrandi
- login: roboman-tech
avatarUrl: https://avatars.githubusercontent.com/u/8183070?u=fdeaa2ed29f598eb7901693884c0ad32b16982e3&v=4
url: https://github.com/roboman-tech
- login: msserpa
avatarUrl: https://avatars.githubusercontent.com/u/6334934?u=82c4489eb1559d88d2990d60001901b14f722bbb&v=4
url: https://github.com/msserpa

View File

@@ -1,495 +1,495 @@
- name: full-stack-fastapi-template
html_url: https://github.com/fastapi/full-stack-fastapi-template
stars: 37341
stars: 38085
owner_login: fastapi
owner_html_url: https://github.com/fastapi
- name: Hello-Python
html_url: https://github.com/mouredev/Hello-Python
stars: 31799
stars: 32243
owner_login: mouredev
owner_html_url: https://github.com/mouredev
- name: serve
html_url: https://github.com/jina-ai/serve
stars: 21721
stars: 21754
owner_login: jina-ai
owner_html_url: https://github.com/jina-ai
- name: HivisionIDPhotos
html_url: https://github.com/Zeyi-Lin/HivisionIDPhotos
stars: 19114
stars: 19400
owner_login: Zeyi-Lin
owner_html_url: https://github.com/Zeyi-Lin
- name: sqlmodel
html_url: https://github.com/fastapi/sqlmodel
stars: 16678
stars: 16859
owner_login: fastapi
owner_html_url: https://github.com/fastapi
- name: Douyin_TikTok_Download_API
html_url: https://github.com/Evil0ctal/Douyin_TikTok_Download_API
stars: 14126
stars: 14452
owner_login: Evil0ctal
owner_html_url: https://github.com/Evil0ctal
- name: fastapi-best-practices
html_url: https://github.com/zhanymkanov/fastapi-best-practices
stars: 13189
stars: 13613
owner_login: zhanymkanov
owner_html_url: https://github.com/zhanymkanov
- name: awesome-fastapi
html_url: https://github.com/mjhea0/awesome-fastapi
stars: 10264
owner_login: mjhea0
owner_html_url: https://github.com/mjhea0
- name: fastapi_mcp
html_url: https://github.com/tadata-org/fastapi_mcp
stars: 9964
stars: 10624
owner_login: tadata-org
owner_html_url: https://github.com/tadata-org
- name: awesome-fastapi
html_url: https://github.com/mjhea0/awesome-fastapi
stars: 10415
owner_login: mjhea0
owner_html_url: https://github.com/mjhea0
- name: FastUI
html_url: https://github.com/pydantic/FastUI
stars: 8861
stars: 8879
owner_login: pydantic
owner_html_url: https://github.com/pydantic
- name: XHS-Downloader
html_url: https://github.com/JoeanAmier/XHS-Downloader
stars: 8576
stars: 8824
owner_login: JoeanAmier
owner_html_url: https://github.com/JoeanAmier
- name: SurfSense
html_url: https://github.com/MODSetter/SurfSense
stars: 7421
stars: 8257
owner_login: MODSetter
owner_html_url: https://github.com/MODSetter
- name: FileCodeBox
html_url: https://github.com/vastsa/FileCodeBox
stars: 7179
stars: 7367
owner_login: vastsa
owner_html_url: https://github.com/vastsa
- name: polar
html_url: https://github.com/polarsource/polar
stars: 7106
stars: 7291
owner_login: polarsource
owner_html_url: https://github.com/polarsource
- name: nonebot2
html_url: https://github.com/nonebot/nonebot2
stars: 6998
stars: 7065
owner_login: nonebot
owner_html_url: https://github.com/nonebot
- name: hatchet
html_url: https://github.com/hatchet-dev/hatchet
stars: 5978
stars: 6070
owner_login: hatchet-dev
owner_html_url: https://github.com/hatchet-dev
- name: serge
html_url: https://github.com/serge-chat/serge
stars: 5751
stars: 5754
owner_login: serge-chat
owner_html_url: https://github.com/serge-chat
- name: fastapi-users
html_url: https://github.com/fastapi-users/fastapi-users
stars: 5517
stars: 5599
owner_login: fastapi-users
owner_html_url: https://github.com/fastapi-users
- name: strawberry
html_url: https://github.com/strawberry-graphql/strawberry
stars: 4392
stars: 4422
owner_login: strawberry-graphql
owner_html_url: https://github.com/strawberry-graphql
- name: chatgpt-web-share
html_url: https://github.com/chatpire/chatgpt-web-share
stars: 4305
stars: 4301
owner_login: chatpire
owner_html_url: https://github.com/chatpire
- name: poem
html_url: https://github.com/poem-web/poem
stars: 4157
stars: 4197
owner_login: poem-web
owner_html_url: https://github.com/poem-web
- name: dynaconf
html_url: https://github.com/dynaconf/dynaconf
stars: 4112
stars: 4144
owner_login: dynaconf
owner_html_url: https://github.com/dynaconf
- name: atrilabs-engine
html_url: https://github.com/Atri-Labs/atrilabs-engine
stars: 4104
stars: 4094
owner_login: Atri-Labs
owner_html_url: https://github.com/Atri-Labs
- name: Kokoro-FastAPI
html_url: https://github.com/remsky/Kokoro-FastAPI
stars: 3569
stars: 3739
owner_login: remsky
owner_html_url: https://github.com/remsky
- name: LitServe
html_url: https://github.com/Lightning-AI/LitServe
stars: 3531
owner_login: Lightning-AI
owner_html_url: https://github.com/Lightning-AI
- name: logfire
html_url: https://github.com/pydantic/logfire
stars: 3510
stars: 3614
owner_login: pydantic
owner_html_url: https://github.com/pydantic
- name: LitServe
html_url: https://github.com/Lightning-AI/LitServe
stars: 3578
owner_login: Lightning-AI
owner_html_url: https://github.com/Lightning-AI
- name: datamodel-code-generator
html_url: https://github.com/koxudaxi/datamodel-code-generator
stars: 3425
stars: 3496
owner_login: koxudaxi
owner_html_url: https://github.com/koxudaxi
- name: farfalle
html_url: https://github.com/rashadphz/farfalle
stars: 3420
stars: 3459
owner_login: rashadphz
owner_html_url: https://github.com/rashadphz
- name: fastapi-admin
html_url: https://github.com/fastapi-admin/fastapi-admin
stars: 3417
stars: 3456
owner_login: fastapi-admin
owner_html_url: https://github.com/fastapi-admin
- name: huma
html_url: https://github.com/danielgtaylor/huma
stars: 3351
stars: 3447
owner_login: danielgtaylor
owner_html_url: https://github.com/danielgtaylor
- name: tracecat
html_url: https://github.com/TracecatHQ/tracecat
stars: 3213
stars: 3254
owner_login: TracecatHQ
owner_html_url: https://github.com/TracecatHQ
- name: opyrator
html_url: https://github.com/ml-tooling/opyrator
stars: 3131
stars: 3134
owner_login: ml-tooling
owner_html_url: https://github.com/ml-tooling
- name: docarray
html_url: https://github.com/docarray/docarray
stars: 3098
stars: 3107
owner_login: docarray
owner_html_url: https://github.com/docarray
- name: fastapi-realworld-example-app
html_url: https://github.com/nsidnev/fastapi-realworld-example-app
stars: 2925
stars: 2936
owner_login: nsidnev
owner_html_url: https://github.com/nsidnev
- name: uvicorn-gunicorn-fastapi-docker
html_url: https://github.com/tiangolo/uvicorn-gunicorn-fastapi-docker
stars: 2796
stars: 2804
owner_login: tiangolo
owner_html_url: https://github.com/tiangolo
- name: best-of-web-python
html_url: https://github.com/ml-tooling/best-of-web-python
stars: 2583
stars: 2610
owner_login: ml-tooling
owner_html_url: https://github.com/ml-tooling
- name: RasaGPT
html_url: https://github.com/paulpierre/RasaGPT
stars: 2438
owner_login: paulpierre
owner_html_url: https://github.com/paulpierre
- name: mcp-context-forge
html_url: https://github.com/IBM/mcp-context-forge
stars: 2572
owner_login: IBM
owner_html_url: https://github.com/IBM
- name: fastapi-react
html_url: https://github.com/Buuntu/fastapi-react
stars: 2432
stars: 2451
owner_login: Buuntu
owner_html_url: https://github.com/Buuntu
- name: RasaGPT
html_url: https://github.com/paulpierre/RasaGPT
stars: 2441
owner_login: paulpierre
owner_html_url: https://github.com/paulpierre
- name: FastAPI-template
html_url: https://github.com/s3rius/FastAPI-template
stars: 2388
stars: 2424
owner_login: s3rius
owner_html_url: https://github.com/s3rius
- name: sqladmin
html_url: https://github.com/aminalaee/sqladmin
stars: 2323
stars: 2357
owner_login: aminalaee
owner_html_url: https://github.com/aminalaee
- name: nextpy
html_url: https://github.com/dot-agent/nextpy
stars: 2314
stars: 2324
owner_login: dot-agent
owner_html_url: https://github.com/dot-agent
- name: mcp-context-forge
html_url: https://github.com/IBM/mcp-context-forge
stars: 2236
owner_login: IBM
owner_html_url: https://github.com/IBM
- name: 30-Days-of-Python
html_url: https://github.com/codingforentrepreneurs/30-Days-of-Python
stars: 2196
owner_login: codingforentrepreneurs
owner_html_url: https://github.com/codingforentrepreneurs
- name: supabase-py
html_url: https://github.com/supabase/supabase-py
stars: 2194
stars: 2236
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: 2210
owner_login: codingforentrepreneurs
owner_html_url: https://github.com/codingforentrepreneurs
- name: langserve
html_url: https://github.com/langchain-ai/langserve
stars: 2157
stars: 2171
owner_login: langchain-ai
owner_html_url: https://github.com/langchain-ai
- name: fastapi-utils
html_url: https://github.com/fastapiutils/fastapi-utils
stars: 2155
stars: 2164
owner_login: fastapiutils
owner_html_url: https://github.com/fastapiutils
- name: solara
html_url: https://github.com/widgetti/solara
stars: 2083
stars: 2102
owner_login: widgetti
owner_html_url: https://github.com/widgetti
- name: mangum
html_url: https://github.com/Kludex/mangum
stars: 1969
owner_login: Kludex
owner_html_url: https://github.com/Kludex
- name: Yuxi-Know
html_url: https://github.com/xerrors/Yuxi-Know
stars: 1849
stars: 1995
owner_login: xerrors
owner_html_url: https://github.com/xerrors
- name: mangum
html_url: https://github.com/Kludex/mangum
stars: 1989
owner_login: Kludex
owner_html_url: https://github.com/Kludex
- name: python-week-2022
html_url: https://github.com/rochacbruno/python-week-2022
stars: 1817
stars: 1816
owner_login: rochacbruno
owner_html_url: https://github.com/rochacbruno
- name: agentkit
html_url: https://github.com/BCG-X-Official/agentkit
stars: 1779
stars: 1789
owner_login: BCG-X-Official
owner_html_url: https://github.com/BCG-X-Official
- name: manage-fastapi
html_url: https://github.com/ycd/manage-fastapi
stars: 1770
stars: 1780
owner_login: ycd
owner_html_url: https://github.com/ycd
- name: ormar
html_url: https://github.com/collerek/ormar
stars: 1766
stars: 1777
owner_login: collerek
owner_html_url: https://github.com/collerek
- name: piccolo
html_url: https://github.com/piccolo-orm/piccolo
stars: 1673
owner_login: piccolo-orm
owner_html_url: https://github.com/piccolo-orm
- name: openapi-python-client
html_url: https://github.com/openapi-generators/openapi-python-client
stars: 1667
stars: 1707
owner_login: openapi-generators
owner_html_url: https://github.com/openapi-generators
- name: langchain-serve
html_url: https://github.com/jina-ai/langchain-serve
stars: 1632
owner_login: jina-ai
owner_html_url: https://github.com/jina-ai
- name: fastapi-cache
html_url: https://github.com/long2ice/fastapi-cache
stars: 1628
owner_login: long2ice
owner_html_url: https://github.com/long2ice
- name: termpair
html_url: https://github.com/cs01/termpair
stars: 1622
owner_login: cs01
owner_html_url: https://github.com/cs01
- name: piccolo
html_url: https://github.com/piccolo-orm/piccolo
stars: 1695
owner_login: piccolo-orm
owner_html_url: https://github.com/piccolo-orm
- name: vue-fastapi-admin
html_url: https://github.com/mizhexiaoxiao/vue-fastapi-admin
stars: 1591
stars: 1695
owner_login: mizhexiaoxiao
owner_html_url: https://github.com/mizhexiaoxiao
- name: fastapi-cache
html_url: https://github.com/long2ice/fastapi-cache
stars: 1653
owner_login: long2ice
owner_html_url: https://github.com/long2ice
- name: langchain-serve
html_url: https://github.com/jina-ai/langchain-serve
stars: 1635
owner_login: jina-ai
owner_html_url: https://github.com/jina-ai
- name: termpair
html_url: https://github.com/cs01/termpair
stars: 1624
owner_login: cs01
owner_html_url: https://github.com/cs01
- name: slowapi
html_url: https://github.com/laurentS/slowapi
stars: 1580
stars: 1620
owner_login: laurentS
owner_html_url: https://github.com/laurentS
- name: coronavirus-tracker-api
html_url: https://github.com/ExpDev07/coronavirus-tracker-api
stars: 1578
stars: 1576
owner_login: ExpDev07
owner_html_url: https://github.com/ExpDev07
- name: fastapi-crudrouter
html_url: https://github.com/awtkns/fastapi-crudrouter
stars: 1531
stars: 1546
owner_login: awtkns
owner_html_url: https://github.com/awtkns
- name: awesome-fastapi-projects
html_url: https://github.com/Kludex/awesome-fastapi-projects
stars: 1473
owner_login: Kludex
owner_html_url: https://github.com/Kludex
- name: FastAPI-boilerplate
html_url: https://github.com/benavlabs/FastAPI-boilerplate
stars: 1432
stars: 1516
owner_login: benavlabs
owner_html_url: https://github.com/benavlabs
- name: awesome-fastapi-projects
html_url: https://github.com/Kludex/awesome-fastapi-projects
stars: 1481
owner_login: Kludex
owner_html_url: https://github.com/Kludex
- name: fastapi-pagination
html_url: https://github.com/uriyyo/fastapi-pagination
stars: 1428
stars: 1453
owner_login: uriyyo
owner_html_url: https://github.com/uriyyo
- name: bracket
html_url: https://github.com/evroon/bracket
stars: 1415
owner_login: evroon
owner_html_url: https://github.com/evroon
- name: awesome-python-resources
html_url: https://github.com/DjangoEx/awesome-python-resources
stars: 1413
owner_login: DjangoEx
owner_html_url: https://github.com/DjangoEx
- name: bracket
html_url: https://github.com/evroon/bracket
stars: 1393
owner_login: evroon
owner_html_url: https://github.com/evroon
- name: fastapi-boilerplate
html_url: https://github.com/teamhide/fastapi-boilerplate
stars: 1385
stars: 1406
owner_login: teamhide
owner_html_url: https://github.com/teamhide
- name: budgetml
html_url: https://github.com/ebhy/budgetml
stars: 1345
stars: 1346
owner_login: ebhy
owner_html_url: https://github.com/ebhy
- name: fastapi-amis-admin
html_url: https://github.com/amisadmin/fastapi-amis-admin
stars: 1327
stars: 1342
owner_login: amisadmin
owner_html_url: https://github.com/amisadmin
- name: fastapi-langgraph-agent-production-ready-template
html_url: https://github.com/wassim249/fastapi-langgraph-agent-production-ready-template
stars: 1334
owner_login: wassim249
owner_html_url: https://github.com/wassim249
- name: fastapi-tutorial
html_url: https://github.com/liaogx/fastapi-tutorial
stars: 1297
stars: 1303
owner_login: liaogx
owner_html_url: https://github.com/liaogx
- name: fastapi_best_architecture
html_url: https://github.com/fastapi-practices/fastapi_best_architecture
stars: 1242
stars: 1276
owner_login: fastapi-practices
owner_html_url: https://github.com/fastapi-practices
- name: fastapi-code-generator
html_url: https://github.com/koxudaxi/fastapi-code-generator
stars: 1241
owner_login: koxudaxi
owner_html_url: https://github.com/koxudaxi
- name: fastcrud
html_url: https://github.com/benavlabs/fastcrud
stars: 1236
stars: 1272
owner_login: benavlabs
owner_html_url: https://github.com/benavlabs
- name: fastapi-code-generator
html_url: https://github.com/koxudaxi/fastapi-code-generator
stars: 1253
owner_login: koxudaxi
owner_html_url: https://github.com/koxudaxi
- name: prometheus-fastapi-instrumentator
html_url: https://github.com/trallnag/prometheus-fastapi-instrumentator
stars: 1217
stars: 1246
owner_login: trallnag
owner_html_url: https://github.com/trallnag
- name: bolt-python
html_url: https://github.com/slackapi/bolt-python
stars: 1209
stars: 1221
owner_login: slackapi
owner_html_url: https://github.com/slackapi
- name: bedrock-chat
html_url: https://github.com/aws-samples/bedrock-chat
stars: 1199
stars: 1220
owner_login: aws-samples
owner_html_url: https://github.com/aws-samples
- name: fastapi_production_template
html_url: https://github.com/zhanymkanov/fastapi_production_template
stars: 1182
stars: 1202
owner_login: zhanymkanov
owner_html_url: https://github.com/zhanymkanov
- name: fastapi-scaff
html_url: https://github.com/atpuxiner/fastapi-scaff
stars: 1193
owner_login: atpuxiner
owner_html_url: https://github.com/atpuxiner
- name: langchain-extract
html_url: https://github.com/langchain-ai/langchain-extract
stars: 1162
stars: 1164
owner_login: langchain-ai
owner_html_url: https://github.com/langchain-ai
- name: fastapi-langgraph-agent-production-ready-template
html_url: https://github.com/wassim249/fastapi-langgraph-agent-production-ready-template
stars: 1150
owner_login: wassim249
owner_html_url: https://github.com/wassim249
- name: fastapi-alembic-sqlmodel-async
html_url: https://github.com/jonra1993/fastapi-alembic-sqlmodel-async
stars: 1145
stars: 1149
owner_login: jonra1993
owner_html_url: https://github.com/jonra1993
- name: odmantic
html_url: https://github.com/art049/odmantic
stars: 1130
stars: 1133
owner_login: art049
owner_html_url: https://github.com/art049
- name: restish
html_url: https://github.com/rest-sh/restish
stars: 1107
stars: 1122
owner_login: rest-sh
owner_html_url: https://github.com/rest-sh
- name: fastapi-scaff
html_url: https://github.com/atpuxiner/fastapi-scaff
stars: 1052
owner_login: atpuxiner
owner_html_url: https://github.com/atpuxiner
- name: runhouse
html_url: https://github.com/run-house/runhouse
stars: 1043
stars: 1047
owner_login: run-house
owner_html_url: https://github.com/run-house
- name: flock
html_url: https://github.com/Onelevenvy/flock
stars: 1010
stars: 1027
owner_login: Onelevenvy
owner_html_url: https://github.com/Onelevenvy
- name: authx
html_url: https://github.com/yezz123/authx
stars: 999
owner_login: yezz123
owner_html_url: https://github.com/yezz123
- name: autollm
html_url: https://github.com/viddexa/autollm
stars: 995
stars: 999
owner_login: viddexa
owner_html_url: https://github.com/viddexa
- name: lanarky
html_url: https://github.com/ajndkr/lanarky
stars: 994
stars: 995
owner_login: ajndkr
owner_html_url: https://github.com/ajndkr
- name: authx
html_url: https://github.com/yezz123/authx
stars: 978
owner_login: yezz123
owner_html_url: https://github.com/yezz123
- name: secure
html_url: https://github.com/TypeError/secure
stars: 942
owner_login: TypeError
owner_html_url: https://github.com/TypeError
- name: titiler
html_url: https://github.com/developmentseed/titiler
stars: 940
stars: 952
owner_login: developmentseed
owner_html_url: https://github.com/developmentseed
- name: energy-forecasting
html_url: https://github.com/iusztinpaul/energy-forecasting
stars: 937
stars: 946
owner_login: iusztinpaul
owner_html_url: https://github.com/iusztinpaul
- name: secure
html_url: https://github.com/TypeError/secure
stars: 944
owner_login: TypeError
owner_html_url: https://github.com/TypeError
- name: langcorn
html_url: https://github.com/msoedov/langcorn
stars: 933
stars: 934
owner_login: msoedov
owner_html_url: https://github.com/msoedov
- name: fastapi-do-zero
html_url: https://github.com/dunossauro/fastapi-do-zero
stars: 892
owner_login: dunossauro
owner_html_url: https://github.com/dunossauro
- name: marker-api
html_url: https://github.com/adithya-s-k/marker-api
stars: 890
owner_login: adithya-s-k
owner_html_url: https://github.com/adithya-s-k
- name: RuoYi-Vue3-FastAPI
html_url: https://github.com/insistence/RuoYi-Vue3-FastAPI
stars: 884
stars: 930
owner_login: insistence
owner_html_url: https://github.com/insistence
- name: aktools
html_url: https://github.com/akfamily/aktools
stars: 880
stars: 916
owner_login: akfamily
owner_html_url: https://github.com/akfamily
- name: every-pdf
html_url: https://github.com/DDULDDUCK/every-pdf
stars: 907
owner_login: DDULDDUCK
owner_html_url: https://github.com/DDULDDUCK
- name: marker-api
html_url: https://github.com/adithya-s-k/marker-api
stars: 903
owner_login: adithya-s-k
owner_html_url: https://github.com/adithya-s-k
- name: fastapi-observability
html_url: https://github.com/blueswen/fastapi-observability
stars: 880
stars: 902
owner_login: blueswen
owner_html_url: https://github.com/blueswen
- name: httpdbg
html_url: https://github.com/cle-b/httpdbg
stars: 876
owner_login: cle-b
owner_html_url: https://github.com/cle-b
- name: fastapi-do-zero
html_url: https://github.com/dunossauro/fastapi-do-zero
stars: 900
owner_login: dunossauro
owner_html_url: https://github.com/dunossauro

View File

@@ -63,6 +63,11 @@ cassiobotaro:
count: 62
avatarUrl: https://avatars.githubusercontent.com/u/3127847?u=a08022b191ddbd0a6159b2981d9d878b6d5bb71f&v=4
url: https://github.com/cassiobotaro
nilslindemann:
login: nilslindemann
count: 59
avatarUrl: https://avatars.githubusercontent.com/u/6892179?u=1dca6a22195d6cd1ab20737c0e19a4c55d639472&v=4
url: https://github.com/nilslindemann
mattwang44:
login: mattwang44
count: 59
@@ -70,7 +75,7 @@ mattwang44:
url: https://github.com/mattwang44
tiangolo:
login: tiangolo
count: 53
count: 55
avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4
url: https://github.com/tiangolo
Laineyzhang55:
@@ -108,16 +113,16 @@ Rishat-F:
count: 42
avatarUrl: https://avatars.githubusercontent.com/u/66554797?v=4
url: https://github.com/Rishat-F
nilslindemann:
login: nilslindemann
count: 41
avatarUrl: https://avatars.githubusercontent.com/u/6892179?u=1dca6a22195d6cd1ab20737c0e19a4c55d639472&v=4
url: https://github.com/nilslindemann
Winand:
login: Winand
count: 40
avatarUrl: https://avatars.githubusercontent.com/u/53390?u=bb0e71a2fc3910a8e0ee66da67c33de40ea695f8&v=4
url: https://github.com/Winand
YuriiMotov:
login: YuriiMotov
count: 40
avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=b9b13d598dddfab529a52d264df80a900bfe7060&v=4
url: https://github.com/YuriiMotov
solomein-sv:
login: solomein-sv
count: 38
@@ -131,7 +136,7 @@ JavierSanchezCastro:
alejsdev:
login: alejsdev
count: 37
avatarUrl: https://avatars.githubusercontent.com/u/90076947?u=638c65283ac9e9e2c3a0f9d1e3370db4b8a2c58d&v=4
avatarUrl: https://avatars.githubusercontent.com/u/90076947?u=447d12a1b347f466b35378bee4c7104cc9b2c571&v=4
url: https://github.com/alejsdev
stlucasgarcia:
login: stlucasgarcia
@@ -173,11 +178,6 @@ romashevchenko:
count: 32
avatarUrl: https://avatars.githubusercontent.com/u/132477732?v=4
url: https://github.com/romashevchenko
YuriiMotov:
login: YuriiMotov
count: 31
avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=b9b13d598dddfab529a52d264df80a900bfe7060&v=4
url: https://github.com/YuriiMotov
LorhanSohaky:
login: LorhanSohaky
count: 30
@@ -606,7 +606,7 @@ socket-socket:
nick-cjyx9:
login: nick-cjyx9
count: 10
avatarUrl: https://avatars.githubusercontent.com/u/119087246?u=c35aab03f082430be8a1edd80f5625b44819a0d8&v=4
avatarUrl: https://avatars.githubusercontent.com/u/119087246?u=7227a2de948c68fb8396d5beff1ee5b0e057c42e&v=4
url: https://github.com/nick-cjyx9
lucasbalieiro:
login: lucasbalieiro
@@ -986,7 +986,7 @@ esrefzeki:
dtleal:
login: dtleal
count: 5
avatarUrl: https://avatars.githubusercontent.com/u/31096951?v=4
avatarUrl: https://avatars.githubusercontent.com/u/31096951?u=704664ec74ab655485e5c909b25de3fa09a922ba&v=4
url: https://github.com/dtleal
art3xa:
login: art3xa
@@ -1023,11 +1023,6 @@ devluisrodrigues:
count: 5
avatarUrl: https://avatars.githubusercontent.com/u/21125286?v=4
url: https://github.com/11kkw
soroushgh1:
login: soroushgh1
count: 5
avatarUrl: https://avatars.githubusercontent.com/u/178516095?u=5e26f6a5f66cdb32d7b56e6ab362bf18ba7858b9&v=4
url: https://github.com/soroushgh1
lpdswing:
login: lpdswing
count: 4
@@ -1166,7 +1161,7 @@ cookie-byte217:
AbolfazlKameli:
login: AbolfazlKameli
count: 4
avatarUrl: https://avatars.githubusercontent.com/u/120686133?u=ad99cb0adb4a2091f552f9d7281ced334150f9c2&v=4
avatarUrl: https://avatars.githubusercontent.com/u/120686133?u=e41743da3c1820efafc59c5870cacd4f4425334c&v=4
url: https://github.com/AbolfazlKameli
tyronedamasceno:
login: tyronedamasceno

View File

@@ -1,6 +1,6 @@
nilslindemann:
login: nilslindemann
count: 120
count: 122
avatarUrl: https://avatars.githubusercontent.com/u/6892179?u=1dca6a22195d6cd1ab20737c0e19a4c55d639472&v=4
url: https://github.com/nilslindemann
jaystone776:
@@ -118,6 +118,11 @@ batlopes:
count: 6
avatarUrl: https://avatars.githubusercontent.com/u/33462923?u=0fb3d7acb316764616f11e4947faf080e49ad8d9&v=4
url: https://github.com/batlopes
tiangolo:
login: tiangolo
count: 6
avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4
url: https://github.com/tiangolo
lucasbalieiro:
login: lucasbalieiro
count: 6
@@ -143,11 +148,6 @@ Attsun1031:
count: 5
avatarUrl: https://avatars.githubusercontent.com/u/1175560?v=4
url: https://github.com/Attsun1031
tiangolo:
login: tiangolo
count: 5
avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4
url: https://github.com/tiangolo
rostik1410:
login: rostik1410
count: 5
@@ -286,7 +286,7 @@ hsuanchi:
alejsdev:
login: alejsdev
count: 3
avatarUrl: https://avatars.githubusercontent.com/u/90076947?u=638c65283ac9e9e2c3a0f9d1e3370db4b8a2c58d&v=4
avatarUrl: https://avatars.githubusercontent.com/u/90076947?u=447d12a1b347f466b35378bee4c7104cc9b2c571&v=4
url: https://github.com/alejsdev
riroan:
login: riroan
@@ -471,7 +471,7 @@ emrhnsyts:
vusallyv:
login: vusallyv
count: 2
avatarUrl: https://avatars.githubusercontent.com/u/85983771?u=53a7b755cb338d9313966dbf2e4e68b512565186&v=4
avatarUrl: https://avatars.githubusercontent.com/u/85983771?u=6fb8e2f876bca06e9f846606423c8f18fb46ad06&v=4
url: https://github.com/vusallyv
jackleeio:
login: jackleeio
@@ -543,3 +543,8 @@ EdmilsonRodrigues:
count: 2
avatarUrl: https://avatars.githubusercontent.com/u/62777025?u=217d6f3cd6cc750bb8818a3af7726c8d74eb7c2d&v=4
url: https://github.com/EdmilsonRodrigues
YuriiMotov:
login: YuriiMotov
count: 2
avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=b9b13d598dddfab529a52d264df80a900bfe7060&v=4
url: https://github.com/YuriiMotov

View File

@@ -63,3 +63,91 @@ In the chapters about security, there are utility functions that are implemented
If you understood all this, you already know how those utility tools for security work underneath.
///
## Dependencies with `yield`, `HTTPException`, `except` and Background Tasks { #dependencies-with-yield-httpexception-except-and-background-tasks }
/// warning
You most probably don't need these technical details.
These details are useful mainly if you had a FastAPI application older than 0.118.0 and you are facing issues with dependencies with `yield`.
///
Dependencies with `yield` have evolved over time to account for the different use cases and to fix some issues, here's a summary of what has changed.
### Dependencies with `yield` and `StreamingResponse`, Technical Details { #dependencies-with-yield-and-streamingresponse-technical-details }
Before FastAPI 0.118.0, if you used a dependency with `yield`, it would run the exit code after the *path operation function* returned but right before sending the response.
The intention was to avoid holding resources for longer than necessary, waiting for the response to travel through the network.
This change also meant that if you returned a `StreamingResponse`, the exit code of the dependency with `yield` would have been already run.
For example, if you had a database session in a dependency with `yield`, the `StreamingResponse` would not be able to use that session while streaming data because the session would have already been closed in the exit code after `yield`.
This behavior was reverted in 0.118.0, to make the exit code after `yield` be executed after the response is sent.
/// info
As you will see below, this is very similar to the behavior before version 0.106.0, but with several improvements and bug fixes for corner cases.
///
#### Use Cases with Early Exit Code { #use-cases-with-early-exit-code }
There are some use cases with specific conditions that could benefit from the old behavior of running the exit code of dependencies with `yield` before sending the response.
For example, imagine you have code that uses a database session in a dependency with `yield` only to verify a user, but the database session is never used again in the *path operation function*, only in the dependency, **and** the response takes a long time to be sent, like a `StreamingResponse` that sends data slowly, but for some reason doesn't use the database.
In this case, the database session would be held until the response is finished being sent, but if you don't use it, then it wouldn't be necessary to hold it.
Here's how it could look like:
{* ../../docs_src/dependencies/tutorial013_an_py310.py *}
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:
{* ../../docs_src/dependencies/tutorial013_an_py310.py ln[30:38] hl[31:33] *}
But as `generate_stream()` doesn't use the database session, it is not really necessary to keep the session open while sending the response.
If you have this specific use case using SQLModel (or SQLAlchemy), you could explicitly close the session after you don't need it anymore:
{* ../../docs_src/dependencies/tutorial014_an_py310.py ln[24:28] hl[28] *}
That way the session would release the database connection, so other requests could use it.
If you have a different use case that needs to exit early from a dependency with `yield`, please create a <a href="https://github.com/fastapi/fastapi/discussions/new?category=questions" class="external-link" target="_blank">GitHub Discussion Question</a> with your specific use case and why you would benefit from having early closing for dependencies with `yield`.
If there are compelling use cases for early closing in dependencies with `yield`, I would consider adding a new way to opt in to early closing.
### Dependencies with `yield` and `except`, Technical Details { #dependencies-with-yield-and-except-technical-details }
Before FastAPI 0.110.0, if you used a dependency with `yield`, and then you captured an exception with `except` in that dependency, and you didn't raise the exception again, the exception would be automatically raised/forwarded to any exception handlers or the internal server error handler.
This was changed in version 0.110.0 to fix unhandled memory consumption from forwarded exceptions without a handler (internal server errors), and to make it consistent with the behavior of regular Python code.
### Background Tasks and Dependencies with `yield`, Technical Details { #background-tasks-and-dependencies-with-yield-technical-details }
Before FastAPI 0.106.0, raising exceptions after `yield` was not possible, the exit code in dependencies with `yield` was executed *after* the response was sent, so [Exception Handlers](../handling-errors.md#install-custom-exception-handlers){.internal-link target=_blank} would have already run.
This was designed this way mainly to allow using the same objects "yielded" by dependencies inside of background tasks, because the exit code would be executed after the background tasks were finished.
This was changed in FastAPI 0.106.0 with the intention to not hold resources while waiting for the response to travel through the network.
/// tip
Additionally, a background task is normally an independent set of logic that should be handled separately, with its own resources (e.g. its own database connection).
So, this way you will probably have cleaner code.
///
If you used to rely on this behavior, now you should create the resources for background tasks inside the background task itself, and use internally only data that doesn't depend on the resources of dependencies with `yield`.
For example, instead of using the same database session, you would create a new database session inside of the background task, and you would obtain the objects from the database using this new session. And then instead of passing the object from the database as a parameter to the background task function, you would pass the ID of that object and then obtain the object again inside the background task function.

View File

@@ -10,10 +10,12 @@ If you already cloned the <a href="https://github.com/fastapi/fastapi" class="ex
Follow the instructions to create and activate a [virtual environment](virtual-environments.md){.internal-link target=_blank} for the internal code of `fastapi`.
### Install requirements using pip
### Install requirements
After activating the environment, install the required packages:
//// tab | `pip`
<div class="termy">
```console
@@ -24,6 +26,24 @@ $ pip install -r requirements.txt
</div>
////
//// tab | `uv`
If you have <a href="https://github.com/astral-sh/uv" class="external-link" target="_blank">`uv`</a>:
<div class="termy">
```console
$ uv pip install -r requirements.txt
---> 100%
```
</div>
////
It will install all the dependencies and your local FastAPI in your local environment.
### Using your local FastAPI

View File

@@ -102,7 +102,15 @@ a.announce-link:hover {
align-items: center;
}
.announce-wrapper div.item {
.announce-wrapper #announce-left div.item {
display: none;
}
.announce-wrapper #announce-right {
display: none;
}
.announce-wrapper #announce-right div.item {
display: none;
}
@@ -112,7 +120,7 @@ a.announce-link:hover {
top: -10px;
right: 0;
font-size: 0.5rem;
color: #999;
color: #e6e6e6;
background-color: #666;
border-radius: 10px;
padding: 0 10px;

View File

@@ -17,7 +17,7 @@ If you want to secure your API, there are several better things you can do, for
* Make sure you have well defined Pydantic models for your request bodies and responses.
* Configure any required permissions and roles using dependencies.
* Never store plaintext passwords, only password hashes.
* Implement and use well-known cryptographic tools, like Passlib and JWT tokens, etc.
* Implement and use well-known cryptographic tools, like pwdlib and JWT tokens, etc.
* Add more granular permission controls with OAuth2 scopes where needed.
* ...etc.

View File

@@ -135,10 +135,43 @@ async function showRandomAnnouncement(groupId, timeInterval) {
}
}
function handleSponsorImages() {
const announceRight = document.getElementById('announce-right');
if(!announceRight) return;
const sponsorImages = document.querySelectorAll('.sponsor-image');
const imagePromises = Array.from(sponsorImages).map(img => {
return new Promise((resolve, reject) => {
if (img.complete && img.naturalHeight !== 0) {
resolve();
} else {
img.addEventListener('load', () => {
if (img.naturalHeight !== 0) {
resolve();
} else {
reject();
}
});
img.addEventListener('error', reject);
}
});
});
Promise.all(imagePromises)
.then(() => {
announceRight.style.display = 'block';
showRandomAnnouncement('announce-right', 10000);
})
.catch(() => {
// do nothing
});
}
async function main() {
setupTermynal();
showRandomAnnouncement('announce-left', 5000)
showRandomAnnouncement('announce-right', 10000)
handleSponsorImages();
}
document$.subscribe(() => {
main()

View File

@@ -7,6 +7,90 @@ hide:
## Latest Changes
## 0.118.2
### Fixes
* 🐛 Fix tagged discriminated union not recognized as body field. PR [#12942](https://github.com/fastapi/fastapi/pull/12942) by [@frankie567](https://github.com/frankie567).
### Internal
* ⬆ Bump astral-sh/setup-uv from 6 to 7. PR [#14167](https://github.com/fastapi/fastapi/pull/14167) by [@dependabot[bot]](https://github.com/apps/dependabot).
## 0.118.1
### Upgrades
* 👽️ Ensure compatibility with Pydantic 2.12.0. PR [#14036](https://github.com/fastapi/fastapi/pull/14036) by [@cjwatson](https://github.com/cjwatson).
### Docs
* 📝 Add External Link: Getting started with logging in FastAPI. PR [#14152](https://github.com/fastapi/fastapi/pull/14152) by [@itssimon](https://github.com/itssimon).
### Translations
* 🔨 Add Russian translations LLM prompt. PR [#13936](https://github.com/fastapi/fastapi/pull/13936) by [@tiangolo](https://github.com/tiangolo).
* 🌐 Sync German docs. PR [#14149](https://github.com/fastapi/fastapi/pull/14149) by [@nilslindemann](https://github.com/nilslindemann).
* 🌐 Add Russian translations for missing pages (LLM-generated). PR [#14135](https://github.com/fastapi/fastapi/pull/14135) by [@YuriiMotov](https://github.com/YuriiMotov).
* 🌐 Update Russian translations for existing pages (LLM-generated). PR [#14123](https://github.com/fastapi/fastapi/pull/14123) by [@YuriiMotov](https://github.com/YuriiMotov).
* 🌐 Remove configuration files for inactive translations. PR [#14130](https://github.com/fastapi/fastapi/pull/14130) by [@tiangolo](https://github.com/tiangolo).
### Internal
* 🔨 Move local coverage logic to its own script. PR [#14166](https://github.com/fastapi/fastapi/pull/14166) by [@tiangolo](https://github.com/tiangolo).
* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#14161](https://github.com/fastapi/fastapi/pull/14161) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci).
* ⬆ Bump griffe-typingdoc from 0.2.8 to 0.2.9. PR [#14144](https://github.com/fastapi/fastapi/pull/14144) by [@dependabot[bot]](https://github.com/apps/dependabot).
* ⬆ Bump mkdocs-macros-plugin from 1.3.9 to 1.4.0. PR [#14145](https://github.com/fastapi/fastapi/pull/14145) by [@dependabot[bot]](https://github.com/apps/dependabot).
* ⬆ Bump markdown-include-variants from 0.0.4 to 0.0.5. PR [#14146](https://github.com/fastapi/fastapi/pull/14146) by [@dependabot[bot]](https://github.com/apps/dependabot).
* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#14126](https://github.com/fastapi/fastapi/pull/14126) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci).
* 👥 Update FastAPI GitHub topic repositories. PR [#14150](https://github.com/fastapi/fastapi/pull/14150) by [@tiangolo](https://github.com/tiangolo).
* 👥 Update FastAPI People - Sponsors. PR [#14139](https://github.com/fastapi/fastapi/pull/14139) by [@tiangolo](https://github.com/tiangolo).
* 👥 Update FastAPI People - Contributors and Translators. PR [#14138](https://github.com/fastapi/fastapi/pull/14138) by [@tiangolo](https://github.com/tiangolo).
* ⬆ Bump ruff from 0.12.7 to 0.13.2. PR [#14147](https://github.com/fastapi/fastapi/pull/14147) by [@dependabot[bot]](https://github.com/apps/dependabot).
* ⬆ Bump sqlmodel from 0.0.24 to 0.0.25. PR [#14143](https://github.com/fastapi/fastapi/pull/14143) by [@dependabot[bot]](https://github.com/apps/dependabot).
* ⬆ Bump tiangolo/issue-manager from 0.5.1 to 0.6.0. PR [#14148](https://github.com/fastapi/fastapi/pull/14148) by [@dependabot[bot]](https://github.com/apps/dependabot).
* 👷 Update docs previews comment, single comment, add failure status. PR [#14129](https://github.com/fastapi/fastapi/pull/14129) by [@tiangolo](https://github.com/tiangolo).
* 🔨 Modify `mkdocs_hooks.py` to add `title` to page's metadata (remove permalinks in social cards). PR [#14125](https://github.com/fastapi/fastapi/pull/14125) by [@YuriiMotov](https://github.com/YuriiMotov).
## 0.118.0
### Fixes
* 🐛 Fix support for `StreamingResponse`s with dependencies with `yield` or `UploadFile`s, close after the response is done. PR [#14099](https://github.com/fastapi/fastapi/pull/14099) by [@tiangolo](https://github.com/tiangolo).
Before FastAPI 0.118.0, if you used a dependency with `yield`, it would run the exit code after the *path operation function* returned but right before sending the response.
This change also meant that if you returned a `StreamingResponse`, the exit code of the dependency with `yield` would have been already run.
For example, if you had a database session in a dependency with `yield`, the `StreamingResponse` would not be able to use that session while streaming data because the session would have already been closed in the exit code after `yield`.
This behavior was reverted in 0.118.0, to make the exit code after `yield` be executed after the response is sent.
You can read more about it in the docs for [Advanced Dependencies - Dependencies with `yield`, `HTTPException`, `except` and Background Tasks](https://fastapi.tiangolo.com/advanced/advanced-dependencies#dependencies-with-yield-httpexception-except-and-background-tasks). Including what you could do if you wanted to close a database session earlier, before returning the response to the client.
### Docs
* 📝 Update `tutorial/security/oauth2-jwt/` to use `pwdlib` with Argon2 instead of `passlib`. PR [#13917](https://github.com/fastapi/fastapi/pull/13917) by [@Neizvestnyj](https://github.com/Neizvestnyj).
* ✏️ Fix typos in OAuth2 password request forms. PR [#14112](https://github.com/fastapi/fastapi/pull/14112) by [@alv2017](https://github.com/alv2017).
* 📝 Update contributing guidelines for installing requirements. PR [#14095](https://github.com/fastapi/fastapi/pull/14095) by [@alejsdev](https://github.com/alejsdev).
### Translations
* 🌐 Sync German docs. PR [#14098](https://github.com/fastapi/fastapi/pull/14098) by [@nilslindemann](https://github.com/nilslindemann).
### Internal
* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#14103](https://github.com/fastapi/fastapi/pull/14103) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci).
* ♻️ Refactor sponsor image handling. PR [#14102](https://github.com/fastapi/fastapi/pull/14102) by [@alejsdev](https://github.com/alejsdev).
* 🐛 Fix sponsor display issue by hiding element on image error. PR [#14097](https://github.com/fastapi/fastapi/pull/14097) by [@alejsdev](https://github.com/alejsdev).
* 🐛 Hide sponsor badge when sponsor image is not displayed. PR [#14096](https://github.com/fastapi/fastapi/pull/14096) by [@alejsdev](https://github.com/alejsdev).
## 0.117.1
### Fixes
* 🐛 Fix validation error when `File` is declared after `Form` parameter. PR [#11194](https://github.com/fastapi/fastapi/pull/11194) by [@thomasleveil](https://github.com/thomasleveil).
## 0.117.0
### Features

View File

@@ -35,7 +35,7 @@ The yielded value is what is injected into *path operations* and other dependenc
{* ../../docs_src/dependencies/tutorial007.py hl[4] *}
The code following the `yield` statement is executed after creating the response but before sending it:
The code following the `yield` statement is executed after the response:
{* ../../docs_src/dependencies/tutorial007.py hl[5:6] *}
@@ -51,7 +51,7 @@ You can use `async` or regular functions.
If you use a `try` block in a dependency with `yield`, you'll receive any exception that was thrown when using the dependency.
For example, if some code at some point in the middle, in another dependency or in a *path operation*, made a database transaction "rollback" or create any other error, you will receive the exception in your dependency.
For example, if some code at some point in the middle, in another dependency or in a *path operation*, made a database transaction "rollback" or created any other exception, you would receive the exception in your dependency.
So, you can look for that specific exception inside the dependency with `except SomeException`.
@@ -95,9 +95,11 @@ This works thanks to Python's <a href="https://docs.python.org/3/library/context
## Dependencies with `yield` and `HTTPException` { #dependencies-with-yield-and-httpexception }
You saw that you can use dependencies with `yield` and have `try` blocks that catch exceptions.
You saw that you can use dependencies with `yield` and have `try` blocks that try to execute some code and then run some exit code after `finally`.
The same way, you could raise an `HTTPException` or similar in the exit code, after the `yield`.
You can also use `except` to catch the exception that was raised and do something with it.
For example, you can raise a different exception, like `HTTPException`.
/// tip
@@ -109,7 +111,7 @@ But it's there for you if you need it. 🤓
{* ../../docs_src/dependencies/tutorial008b_an_py39.py hl[18:22,31] *}
An alternative you could use to catch exceptions (and possibly also raise another `HTTPException`) is to create a [Custom Exception Handler](../handling-errors.md#install-custom-exception-handlers){.internal-link target=_blank}.
If you want to catch exceptions and create a custom response based on that, create a [Custom Exception Handler](../handling-errors.md#install-custom-exception-handlers){.internal-link target=_blank}.
## Dependencies with `yield` and `except` { #dependencies-with-yield-and-except }
@@ -121,7 +123,7 @@ In this case, the client will see an *HTTP 500 Internal Server Error* response a
### Always `raise` in Dependencies with `yield` and `except` { #always-raise-in-dependencies-with-yield-and-except }
If you catch an exception in a dependency with `yield`, unless you are raising another `HTTPException` or similar, you should re-raise the original exception.
If you catch an exception in a dependency with `yield`, unless you are raising another `HTTPException` or similar, **you should re-raise the original exception**.
You can re-raise the same exception using `raise`:
@@ -178,48 +180,15 @@ After one of those responses is sent, no other response can be sent.
/// tip
This diagram shows `HTTPException`, but you could also raise any other exception that you catch in a dependency with `yield` or with a [Custom Exception Handler](../handling-errors.md#install-custom-exception-handlers){.internal-link target=_blank}.
If you raise any exception, it will be passed to the dependencies with yield, including `HTTPException`. In most cases you will want to re-raise that same exception or a new one from the dependency with `yield` to make sure it's properly handled.
If you raise any exception in the code from the *path operation function*, it will be passed to the dependencies with yield, including `HTTPException`. In most cases you will want to re-raise that same exception or a new one from the dependency with `yield` to make sure it's properly handled.
///
## Dependencies with `yield`, `HTTPException`, `except` and Background Tasks { #dependencies-with-yield-httpexception-except-and-background-tasks }
/// warning
You most probably don't need these technical details, you can skip this section and continue below.
These details are useful mainly if you were using a version of FastAPI prior to 0.106.0 and used resources from dependencies with `yield` in background tasks.
///
### Dependencies with `yield` and `except`, Technical Details { #dependencies-with-yield-and-except-technical-details }
Before FastAPI 0.110.0, if you used a dependency with `yield`, and then you captured an exception with `except` in that dependency, and you didn't raise the exception again, the exception would be automatically raised/forwarded to any exception handlers or the internal server error handler.
This was changed in version 0.110.0 to fix unhandled memory consumption from forwarded exceptions without a handler (internal server errors), and to make it consistent with the behavior of regular Python code.
### Background Tasks and Dependencies with `yield`, Technical Details { #background-tasks-and-dependencies-with-yield-technical-details }
Before FastAPI 0.106.0, raising exceptions after `yield` was not possible, the exit code in dependencies with `yield` was executed *after* the response was sent, so [Exception Handlers](../handling-errors.md#install-custom-exception-handlers){.internal-link target=_blank} would have already run.
This was designed this way mainly to allow using the same objects "yielded" by dependencies inside of background tasks, because the exit code would be executed after the background tasks were finished.
Nevertheless, as this would mean waiting for the response to travel through the network while unnecessarily holding a resource in a dependency with yield (for example a database connection), this was changed in FastAPI 0.106.0.
/// tip
Additionally, a background task is normally an independent set of logic that should be handled separately, with its own resources (e.g. its own database connection).
So, this way you will probably have cleaner code.
///
If you used to rely on this behavior, now you should create the resources for background tasks inside the background task itself, and use internally only data that doesn't depend on the resources of dependencies with `yield`.
For example, instead of using the same database session, you would create a new database session inside of the background task, and you would obtain the objects from the database using this new session. And then instead of passing the object from the database as a parameter to the background task function, you would pass the ID of that object and then obtain the object again inside the background task function.
Dependencies with `yield` have evolved over time to cover different use cases and fix some issues.
If you want to see what has changed in different versions of FastAPI, you can read more about it in the advanced guide, in [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 }
### What are "Context Managers" { #what-are-context-managers }

View File

@@ -64,20 +64,20 @@ If your database is stolen, the thief won't have your users' plaintext passwords
So, the thief won't be able to try to use that password in another system (as many users use the same password everywhere, this would be dangerous).
## Install `passlib` { #install-passlib }
## Install `pwdlib` { #install-pwdlib }
PassLib is a great Python package to handle password hashes.
pwdlib is a great Python package to handle password hashes.
It supports many secure hashing algorithms and utilities to work with them.
The recommended algorithm is "Bcrypt".
The recommended algorithm is "Argon2".
Make sure you create a [virtual environment](../../virtual-environments.md){.internal-link target=_blank}, activate it, and then install PassLib with Bcrypt:
Make sure you create a [virtual environment](../../virtual-environments.md){.internal-link target=_blank}, activate it, and then install pwdlib with Argon2:
<div class="termy">
```console
$ pip install "passlib[bcrypt]"
$ pip install "pwdlib[argon2]"
---> 100%
```
@@ -86,7 +86,7 @@ $ pip install "passlib[bcrypt]"
/// tip
With `passlib`, you could even configure it to be able to read passwords created by **Django**, a **Flask** security plug-in or many others.
With `pwdlib`, you could even configure it to be able to read passwords created by **Django**, a **Flask** security plug-in or many others.
So, you would be able to, for example, share the same data from a Django application in a database with a FastAPI application. Or gradually migrate a Django application using the same database.
@@ -96,15 +96,15 @@ And your users would be able to login from your Django app or from your **FastAP
## Hash and verify the passwords { #hash-and-verify-the-passwords }
Import the tools we need from `passlib`.
Import the tools we need from `pwdlib`.
Create a PassLib "context". This is what will be used to hash and verify passwords.
Create a PasswordHash instance with recommended settings - it will be used for hashing and verifying passwords.
/// tip
The PassLib context also has functionality to use different hashing algorithms, including deprecated old ones only to allow verifying them, etc.
pwdlib also supports the bcrypt hashing algorithm but does not include legacy algorithms - for working with outdated hashes, it is recommended to use the passlib library.
For example, you could use it to read and verify passwords generated by another system (like Django) but hash any new passwords with a different algorithm like Bcrypt.
For example, you could use it to read and verify passwords generated by another system (like Django) but hash any new passwords with a different algorithm like Argon2 or Bcrypt.
And be compatible with all of them at the same time.
@@ -120,7 +120,7 @@ And another one to authenticate and return a user.
/// note
If you check the new (fake) database `fake_users_db`, you will see how the hashed password looks like now: `"$2b$12$EixZaYVK1fsbw1ZfbX3OXePaWxn96p36WQoeG6Lruj3vjPGga31lW"`.
If you check the new (fake) database `fake_users_db`, you will see how the hashed password looks like now: `"$argon2id$v=19$m=65536,t=3,p=4$wagCPXjifgvUFBzq4hqe3w$CYaIb8sB+wtD+Vu/P4uod1+Qof8h+1g7bbDlBID48Rc"`.
///
@@ -264,7 +264,7 @@ Many packages that simplify it a lot have to make many compromises with the data
It gives you all the flexibility to choose the ones that fit your project the best.
And you can use directly many well maintained and widely used packages like `passlib` and `PyJWT`, because **FastAPI** doesn't require any complex mechanisms to integrate external packages.
And you can use directly many well maintained and widely used packages like `pwdlib` and `PyJWT`, because **FastAPI** doesn't require any complex mechanisms to integrate external packages.
But it provides you the tools to simplify the process as much as possible without compromising flexibility, robustness, or security.

View File

@@ -303,10 +303,6 @@ extra:
alternate:
- link: /
name: en - English
- link: /az/
name: az - azərbaycan dili
- link: /bn/
name: bn - বাংলা
- link: /de/
name: de - Deutsch
- link: /es/
@@ -315,22 +311,10 @@ extra:
name: fa - فارسی
- link: /fr/
name: fr - français
- link: /he/
name: he - עברית
- link: /hu/
name: hu - magyar
- link: /id/
name: id - Bahasa Indonesia
- link: /it/
name: it - italiano
- link: /ja/
name: ja - 日本語
- link: /ko/
name: ko - 한국어
- link: /nl/
name: nl - Nederlands
- link: /pl/
name: pl - Polski
- link: /pt/
name: pt - português
- link: /ru/
@@ -339,12 +323,8 @@ extra:
name: tr - Türkçe
- link: /uk/
name: uk - українська мова
- link: /ur/
name: ur - اردو
- link: /vi/
name: vi - Tiếng Việt
- link: /yo/
name: yo - Yorùbá
- link: /zh/
name: zh - 简体中文
- link: /zh-hant/

View File

@@ -1,469 +0,0 @@
# FastAPI
<style>
.md-content .md-typeset h1 { display: none; }
</style>
<p align="center">
<a href="https://fastapi.tiangolo.com"><img src="https://fastapi.tiangolo.com/img/logo-margin/logo-teal.png" alt="FastAPI"></a>
</p>
<p align="center">
<em>תשתית FastAPI, ביצועים גבוהים, קלה ללמידה, מהירה לתכנות, מוכנה לסביבת ייצור</em>
</p>
<p align="center">
<a href="https://github.com/fastapi/fastapi/actions?query=workflow%3ATest+event%3Apush+branch%3Amaster" target="_blank">
<img src="https://github.com/fastapi/fastapi/actions/workflows/test.yml/badge.svg?event=push&branch=master" alt="Test">
</a>
<a href="https://coverage-badge.samuelcolvin.workers.dev/redirect/fastapi/fastapi" target="_blank">
<img src="https://coverage-badge.samuelcolvin.workers.dev/fastapi/fastapi.svg" alt="Coverage">
</a>
<a href="https://pypi.org/project/fastapi" target="_blank">
<img src="https://img.shields.io/pypi/v/fastapi?color=%2334D058&label=pypi%20package" alt="Package version">
</a>
<a href="https://pypi.org/project/fastapi" target="_blank">
<img src="https://img.shields.io/pypi/pyversions/fastapi.svg?color=%2334D058" alt="Supported Python versions">
</a>
</p>
---
**תיעוד**: <a href="https://fastapi.tiangolo.com" target="_blank">https://fastapi.tiangolo.com</a>
**קוד**: <a href="https://github.com/fastapi/fastapi" target="_blank">https://github.com/fastapi/fastapi</a>
---
FastAPI היא תשתית רשת מודרנית ומהירה (ביצועים גבוהים) לבניית ממשקי תכנות יישומים (API) עם פייתון 3.6+ בהתבסס על רמזי טיפוסים סטנדרטיים.
תכונות המפתח הן:
- **מהירה**: ביצועים גבוהים מאוד, בקנה אחד עם NodeJS ו - Go (תודות ל - Starlette ו - Pydantic). [אחת מתשתיות הפייתון המהירות ביותר](#_14).
- **מהירה לתכנות**: הגבירו את מהירות פיתוח התכונות החדשות בכ - %200 עד %300. \*
- **פחות שגיאות**: מנעו כ - %40 משגיאות אנוש (מפתחים). \*
- **אינטואיטיבית**: תמיכת עורך מעולה. <abbr title="ידועה גם כהשלמה אוטומטית או IntelliSense">השלמה</abbr> בכל מקום. פחות זמן ניפוי שגיאות.
- **קלה**: מתוכננת להיות קלה לשימוש וללמידה. פחות זמן קריאת תיעוד.
- **קצרה**: מזערו שכפול קוד. מספר תכונות מכל הכרזת פרמטר. פחות שגיאות.
- **חסונה**: קבלו קוד מוכן לסביבת ייצור. עם תיעוד אינטרקטיבי אוטומטי.
- **מבוססת סטנדרטים**: מבוססת על (ותואמת לחלוטין ל -) הסטדנרטים הפתוחים לממשקי תכנות יישומים: <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank">OpenAPI</a> (ידועים לשעבר כ - Swagger) ו - <a href="https://json-schema.org/" class="external-link" target="_blank">JSON Schema</a>.
<small>\* הערכה מבוססת על בדיקות של צוות פיתוח פנימי שבונה אפליקציות בסביבת ייצור.</small>
## נותני חסות
<!-- sponsors -->
{% if sponsors %}
{% for sponsor in sponsors.gold -%}
<a href="{{ sponsor.url }}" target="_blank" title="{{ sponsor.title }}"><img src="{{ sponsor.img }}" style="border-radius:15px"></a>
{% endfor -%}
{%- for sponsor in sponsors.silver -%}
<a href="{{ sponsor.url }}" target="_blank" title="{{ sponsor.title }}"><img src="{{ sponsor.img }}" style="border-radius:15px"></a>
{% endfor %}
{% endif %}
<!-- /sponsors -->
<a href="https://fastapi.tiangolo.com/fastapi-people/#sponsors" class="external-link" target="_blank">נותני חסות אחרים</a>
## דעות
"_[...] I'm using **FastAPI** a ton these days. [...] I'm actually planning to use it for all of my team's **ML services at Microsoft**. Some of them are getting integrated into the core **Windows** product and some **Office** products._"
<div style="text-align: right; margin-right: 10%;">Kabir Khan - <strong>Microsoft</strong> <a href="https://github.com/fastapi/fastapi/pull/26" target="_blank"><small>(ref)</small></a></div>
---
"_We adopted the **FastAPI** library to spawn a **REST** server that can be queried to obtain **predictions**. [for Ludwig]_"
<div style="text-align: right; margin-right: 10%;">Piero Molino, Yaroslav Dudin, and Sai Sumanth Miryala - <strong>Uber</strong> <a href="https://eng.uber.com/ludwig-v0-2/" target="_blank"><small>(ref)</small></a></div>
---
"_**Netflix** is pleased to announce the open-source release of our **crisis management** orchestration framework: **Dispatch**! [built with **FastAPI**]_"
<div style="text-align: right; margin-right: 10%;">Kevin Glisson, Marc Vilanova, Forest Monsen - <strong>Netflix</strong> <a href="https://netflixtechblog.com/introducing-dispatch-da4b8a2a8072" target="_blank"><small>(ref)</small></a></div>
---
"_Im over the moon excited about **FastAPI**. Its so fun!_"
<div style="text-align: right; margin-right: 10%;">Brian Okken - <strong><a href="https://pythonbytes.fm/episodes/show/123/time-to-right-the-py-wrongs?time_in_sec=855" target="_blank">Python Bytes</a> podcast host</strong> <a href="https://x.com/brianokken/status/1112220079972728832" target="_blank"><small>(ref)</small></a></div>
---
"_Honestly, what you've built looks super solid and polished. In many ways, it's what I wanted **Hug** to be - it's really inspiring to see someone build that._"
<div style="text-align: right; margin-right: 10%;">Timothy Crosley - <strong><a href="https://github.com/hugapi/hug" target="_blank">Hug</a> creator</strong> <a href="https://news.ycombinator.com/item?id=19455465" target="_blank"><small>(ref)</small></a></div>
---
"_If you're looking to learn one **modern framework** for building REST APIs, check out **FastAPI** [...] It's fast, easy to use and easy to learn [...]_"
"_We've switched over to **FastAPI** for our **APIs** [...] I think you'll like it [...]_"
<div style="text-align: right; margin-right: 10%;">Ines Montani - Matthew Honnibal - <strong><a href="https://explosion.ai" target="_blank">Explosion AI</a> founders - <a href="https://spacy.io" target="_blank">spaCy</a> creators</strong> <a href="https://x.com/_inesmontani/status/1144173225322143744" target="_blank"><small>(ref)</small></a> - <a href="https://x.com/honnibal/status/1144031421859655680" target="_blank"><small>(ref)</small></a></div>
---
## **Typer**, ה - FastAPI של ממשקי שורת פקודה (CLI).
<a href="https://typer.tiangolo.com" target="_blank"><img src="https://typer.tiangolo.com/img/logo-margin/logo-margin-vector.svg" style="width: 20%;"></a>
אם אתם בונים אפליקציית <abbr title="ממשק שורת פקודה">CLI</abbr> לשימוש במסוף במקום ממשק רשת, העיפו מבט על <a href="https://typer.tiangolo.com/" class="external-link" target="_blank">**Typer**</a>.
**Typer** היא אחותה הקטנה של FastAPI. ומטרתה היא להיות ה - **FastAPI של ממשקי שורת פקודה**. ⌨️ 🚀
## תלויות
פייתון 3.6+
FastAPI עומדת על כתפי ענקיות:
- <a href="https://www.starlette.io/" class="external-link" target="_blank">Starlette</a> לחלקי הרשת.
- <a href="https://docs.pydantic.dev/" class="external-link" target="_blank">Pydantic</a> לחלקי המידע.
## התקנה
<div dir="ltr" class="termy">
```console
$ pip install fastapi
---> 100%
```
</div>
תצטרכו גם שרת ASGI כגון <a href="https://www.uvicorn.org" class="external-link" target="_blank">Uvicorn</a> או <a href="https://github.com/pgjones/hypercorn" class="external-link" target="_blank">Hypercorn</a>.
<div dir="ltr" class="termy">
```console
$ pip install "uvicorn[standard]"
---> 100%
```
</div>
## דוגמא
### צרו אותה
- צרו קובץ בשם `main.py` עם:
```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}
```
<details markdown="1">
<summary>או השתמשו ב - <code>async def</code>...</summary>
אם הקוד שלכם משתמש ב - `async` / `await`, השתמשו ב - `async def`:
```Python hl_lines="9 14"
from typing import Union
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
async def read_root():
return {"Hello": "World"}
@app.get("/items/{item_id}")
async def read_item(item_id: int, q: Union[str, None] = None):
return {"item_id": item_id, "q": q}
```
**שימו לב**:
אם אינכם יודעים, בדקו את פרק "ממהרים?" על <a href="https://fastapi.tiangolo.com/async/#in-a-hurry" target="_blank">`async` ו - `await` בתיעוד</a>.
</details>
### הריצו אותה
התחילו את השרת עם:
<div dir="ltr" class="termy">
```console
$ uvicorn main:app --reload
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.
```
</div>
<details markdown="1">
<summary>על הפקודה <code>uvicorn main:app --reload</code>...</summary>
הפקודה `uvicorn main:app` מתייחסת ל:
- `main`: הקובץ `main.py` (מודול פייתון).
- `app`: האובייקט שנוצר בתוך `main.py` עם השורה <code dir="ltr">app = FastAPI()</code>.
- <code dir="ltr">--reload</code>: גרמו לשרת להתאתחל לאחר שינויים בקוד. עשו זאת רק בסביבת פיתוח.
</details>
### בדקו אותה
פתחו את הדפדפן שלכם בכתובת <a href="http://127.0.0.1:8000/items/5?q=somequery" class="external-link" target="_blank">http://127.0.0.1:8000/items/5?q=somequery</a>.
אתם תראו תגובת JSON:
```JSON
{"item_id": 5, "q": "somequery"}
```
כבר יצרתם API ש:
- מקבל בקשות HTTP בנתיבים `/` ו - <code dir="ltr">/items/{item_id}</code>.
- שני ה _נתיבים_ מקבלים _בקשות_ `GET` (ידועות גם כ*מתודות* HTTP).
- ה _נתיב_ <code dir="ltr">/items/{item_id}</code> כולל \*פרמטר נתיב\_ `item_id` שאמור להיות `int`.
- ה _נתיב_ <code dir="ltr">/items/{item_id}</code> \*פרמטר שאילתא\_ אופציונלי `q`.
### תיעוד API אינטרקטיבי
כעת פנו לכתובת <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
אתם תראו את התיעוד האוטומטי (מסופק על ידי <a href="https://github.com/swagger-api/swagger-ui" class="external-link" target="_blank">Swagger UI</a>):
![Swagger UI](https://fastapi.tiangolo.com/img/index/index-01-swagger-ui-simple.png)
### תיעוד אלטרנטיבי
כעת פנו לכתובת <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a>.
אתם תראו תיעוד אלטרנטיבי (מסופק על ידי <a href="https://github.com/Rebilly/ReDoc" class="external-link" target="_blank">ReDoc</a>):
![ReDoc](https://fastapi.tiangolo.com/img/index/index-02-redoc-simple.png)
## שדרוג לדוגמא
כעת ערכו את הקובץ `main.py` כך שיוכל לקבל גוף מבקשת `PUT`.
הגדירו את הגוף בעזרת רמזי טיפוסים סטנדרטיים, הודות ל - `Pydantic`.
```Python hl_lines="4 9-12 25-27"
from typing import Union
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
price: float
is_offer: Union[bool, None] = None
@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}
@app.put("/items/{item_id}")
def update_item(item_id: int, item: Item):
return {"item_name": item.name, "item_id": item_id}
```
השרת אמול להתאתחל אוטומטית (מאחר והוספתם <code dir="ltr">--reload</code> לפקודת `uvicorn` שלמעלה).
### שדרוג התיעוד האינטרקטיבי
כעת פנו לכתובת <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
- התיעוד האוטומטי יתעדכן, כולל הגוף החדש:
![Swagger UI](https://fastapi.tiangolo.com/img/index/index-03-swagger-02.png)
- לחצו על הכפתור "Try it out", הוא יאפשר לכם למלא את הפרמטרים ולעבוד ישירות מול ה - API.
![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-04-swagger-03.png)
- אחר כך לחצו על הכפתור "Execute", האתר יתקשר עם ה - API שלכם, ישלח את הפרמטרים, ישיג את התוצאות ואז יראה אותן על המסך:
![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-05-swagger-04.png)
### שדרוג התיעוד האלטרנטיבי
כעת פנו לכתובת <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a>.
- התיעוד האלטרנטיבי גם יראה את פרמטר השאילתא והגוף החדשים.
![ReDoc](https://fastapi.tiangolo.com/img/index/index-06-redoc-02.png)
### סיכום
לסיכום, אתם מכריזים ** פעם אחת** על טיפוסי הפרמטרים, גוף וכו' כפרמטרים לפונקציה.
אתם עושים את זה עם טיפוסי פייתון מודרניים.
אתם לא צריכים ללמוד תחביר חדש, מתודות או מחלקות של ספרייה ספיציפית, וכו'
רק **פייתון 3.6+** סטנדרטי.
לדוגמא, ל - `int`:
```Python
item_id: int
```
או למודל `Item` מורכב יותר:
```Python
item: Item
```
...ועם הכרזת הטיפוס האחת הזו אתם מקבלים:
- תמיכת עורך, כולל:
- השלמות.
- בדיקת טיפוסים.
- אימות מידע:
- שגיאות ברורות ואטומטיות כאשר מוכנס מידע לא חוקי .
- אימות אפילו לאובייקטי JSON מקוננים.
- <abbr title="ידועה גם כ: פרסור, סיריאליזציה">המרה</abbr> של מידע קלט: המרה של מידע שמגיע מהרשת למידע וטיפוסים של פייתון. קורא מ:
- JSON.
- פרמטרי נתיב.
- פרמטרי שאילתא.
- עוגיות.
- כותרות.
- טפסים.
- קבצים.
- <abbr title="ידועה גם כ: פרסור, סיריאליזציה">המרה</abbr> של מידע פלט: המרה של מידע וטיפוסים מפייתון למידע רשת (כ - JSON):
- המירו טיפוסי פייתון (`str`, `int`, `float`, `bool`, `list`, etc).
- עצמי `datetime`.
- עצמי `UUID`.
- מודלי בסיסי נתונים.
- ...ורבים אחרים.
- תיעוד API אוטומטי ואינטרקטיבית כולל שתי אלטרנטיבות לממשק המשתמש:
- Swagger UI.
- ReDoc.
---
בחזרה לדוגמאת הקוד הקודמת, **FastAPI** ידאג:
- לאמת שיש `item_id` בנתיב בבקשות `GET` ו - `PUT`.
- לאמת שה - `item_id` הוא מטיפוס `int` בבקשות `GET` ו - `PUT`.
- אם הוא לא, הלקוח יראה שגיאה ברורה ושימושית.
- לבדוק האם קיים פרמטר שאילתא בשם `q` (קרי `http://127.0.0.1:8000/items/foo?q=somequery`) לבקשות `GET`.
- מאחר והפרמטר `q` מוגדר עם <code dir="ltr"> = None</code>, הוא אופציונלי.
- לולא ה - `None` הוא היה חובה (כמו הגוף במקרה של `PUT`).
- לבקשות `PUT` לנתיב <code dir="ltr">/items/{item_id}</code>, לקרוא את גוף הבקשה כ - JSON:
- לאמת שהוא כולל את מאפיין החובה `name` שאמור להיות מטיפוס `str`.
- לאמת שהוא כולל את מאפיין החובה `price` שחייב להיות מטיפוס `float`.
- לבדוק האם הוא כולל את מאפיין הרשות `is_offer` שאמור להיות מטיפוס `bool`, אם הוא נמצא.
- כל זה יעבוד גם לאובייקט JSON מקונן.
- להמיר מ - JSON ול- JSON אוטומטית.
- לתעד הכל באמצעות 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)
לדוגמא יותר שלמה שכוללת עוד תכונות, ראו את ה<a href="https://fastapi.tiangolo.com/tutorial/">מדריך - למשתמש</a>.
**התראת ספוילרים**: המדריך - למשתמש כולל:
- הכרזה על **פרמטרים** ממקורות אחרים ושונים כגון: **כותרות**, **עוגיות**, **טפסים** ו - **קבצים**.
- איך לקבוע **מגבלות אימות** בעזרת `maximum_length` או `regex`.
- דרך חזקה וקלה להשתמש ב**<abbr title="ידועה גם כרכיבים, משאבים, ספקים, שירותים, מוזרקים">הזרקת תלויות</abbr>**.
- אבטחה והתאמתות, כולל תמיכה ב - **OAuth2** עם **JWT** והתאמתות **HTTP Basic**.
- טכניקות מתקדמות (אבל קלות באותה מידה) להכרזת אובייקטי JSON מקוננים (תודות ל - Pydantic).
- אינטרקציה עם **GraphQL** דרך <a href="https://strawberry.rocks" class="external-link" target="_blank">Strawberry</a> וספריות אחרות.
- תכונות נוספות רבות (תודות ל - Starlette) כגון:
- **WebSockets**
- בדיקות קלות במיוחד מבוססות על `requests` ו - `pytest`
- **CORS**
- **Cookie Sessions**
- ...ועוד.
## ביצועים
בדיקות עצמאיות של TechEmpower הראו שאפליקציות **FastAPI** שרצות תחת Uvicorn הן <a href="https://www.techempower.com/benchmarks/#section=test&runid=7464e520-0dc2-473d-bd34-dbdfd7e85911&hw=ph&test=query&l=zijzen-7" class="external-link" target="_blank">מתשתיות הפייתון המהירות ביותר</a>, רק מתחת ל - Starlette ו - Uvicorn עצמן (ש - FastAPI מבוססת עליהן). (\*)
כדי להבין עוד על הנושא, ראו את הפרק <a href="https://fastapi.tiangolo.com/benchmarks/" class="internal-link" target="_blank">Benchmarks</a>.
## תלויות אופציונליות
בשימוש Pydantic:
- <a href="https://github.com/JoshData/python-email-validator" target="_blank"><code>email-validator</code></a> - לאימות כתובות אימייל.
בשימוש Starlette:
- <a href="https://www.python-httpx.org" target="_blank"><code>httpx</code></a> - דרוש אם ברצונכם להשתמש ב - `TestClient`.
- <a href="https://jinja.palletsprojects.com" target="_blank"><code>jinja2</code></a> - דרוש אם ברצונכם להשתמש בברירת המחדל של תצורת הטמפלייטים.
- <a href="https://github.com/Kludex/python-multipart" target="_blank"><code>python-multipart</code></a> - דרוש אם ברצונכם לתמוך ב <abbr title="המרת המחרוזת שמגיעה מבקשת HTTP למידע פייתון">"פרסור"</abbr> טפסים, באצמעות <code dir="ltr">request.form()</code>.
- <a href="https://pythonhosted.org/itsdangerous/" target="_blank"><code>itsdangerous</code></a> - דרוש אם ברצונכם להשתמש ב - `SessionMiddleware`.
- <a href="https://pyyaml.org/wiki/PyYAMLDocumentation" target="_blank"><code>pyyaml</code></a> - דרוש אם ברצונכם להשתמש ב - `SchemaGenerator` של Starlette (כנראה שאתם לא צריכים את זה עם FastAPI).
בשימוש FastAPI / Starlette:
- <a href="https://www.uvicorn.org" target="_blank"><code>uvicorn</code></a> - לשרת שטוען ומגיש את האפליקציה שלכם.
- <a href="https://github.com/ijl/orjson" target="_blank"><code>orjson</code></a> - דרוש אם ברצונכם להשתמש ב - `ORJSONResponse`.
- <a href="https://github.com/esnme/ultrajson" target="_blank"><code>ujson</code></a> - דרוש אם ברצונכם להשתמש ב - `UJSONResponse`.
תוכלו להתקין את כל אלו באמצעות <code dir="ltr">pip install "fastapi[all]"</code>.
## רשיון
הפרויקט הזה הוא תחת התנאים של רשיון MIT.

View File

@@ -1 +0,0 @@
INHERIT: ../en/mkdocs.yml

View File

@@ -1,467 +0,0 @@
<p align="center">
<a href="https://fastapi.tiangolo.com"><img src="https://fastapi.tiangolo.com/img/logo-margin/logo-teal.png" alt="FastAPI"></a>
</p>
<p align="center">
<em>FastAPI keretrendszer, nagy teljesítmény, könnyen tanulható, gyorsan kódolható, productionre kész</em>
</p>
<p align="center">
<a href="https://github.com/fastapi/fastapi/actions?query=workflow%3ATest+event%3Apush+branch%3Amaster" target="_blank">
<img src="https://github.com/fastapi/fastapi/actions/workflows/test.yml/badge.svg?event=push&branch=master" alt="Test">
</a>
<a href="https://coverage-badge.samuelcolvin.workers.dev/redirect/fastapi/fastapi" target="_blank">
<img src="https://coverage-badge.samuelcolvin.workers.dev/fastapi/fastapi.svg" alt="Coverage">
</a>
<a href="https://pypi.org/project/fastapi" target="_blank">
<img src="https://img.shields.io/pypi/v/fastapi?color=%2334D058&label=pypi%20package" alt="Package version">
</a>
<a href="https://pypi.org/project/fastapi" target="_blank">
<img src="https://img.shields.io/pypi/pyversions/fastapi.svg?color=%2334D058" alt="Supported Python versions">
</a>
</p>
---
**Dokumentáció**: <a href="https://fastapi.tiangolo.com" target="_blank">https://fastapi.tiangolo.com</a>
**Forrás kód**: <a href="https://github.com/fastapi/fastapi" target="_blank">https://github.com/fastapi/fastapi</a>
---
A FastAPI egy modern, gyors (nagy teljesítményű), webes keretrendszer API-ok építéséhez Python -al, a Python szabványos típusjelöléseire építve.
Kulcs funkciók:
* **Gyors**: Nagyon nagy teljesítmény, a **NodeJS**-el és a **Go**-val egyenrangú (a Starlettenek és a Pydantic-nek köszönhetően). [Az egyik leggyorsabb Python keretrendszer](#performance).
* **Gyorsan kódolható**: A funkciók fejlesztési sebességét 200-300 százalékkal megnöveli. *
* **Kevesebb hiba**: Körülbelül 40%-al csökkenti az emberi (fejlesztői) hibák számát. *
* **Intuitív**: Kiváló szerkesztő támogatás. <abbr title="más néven auto-complete, autocompletion, IntelliSense">Kiegészítés</abbr> mindenhol. Kevesebb hibakereséssel töltött idő.
* **Egyszerű**: Egyszerű tanulásra és használatra tervezve. Kevesebb dokumentáció olvasással töltött idő.
* **Rövid**: Kód duplikáció minimalizálása. Több funkció minden paraméter deklarálásával. Kevesebb hiba.
* **Robosztus**: Production ready kód. Automatikus interaktív dokumentáció val.
* **Szabvány alapú**: Az API-ok nyílt szabványaira alapuló (és azokkal teljesen kompatibilis): <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank">OpenAPI</a> (korábban Swagger néven ismert) és a <a href="https://json-schema.org/" class="external-link" target="_blank">JSON Schema</a>.
<small>* Egy production alkalmazásokat építő belső fejlesztői csapat tesztjein alapuló becslés. </small>
## Szponzorok
<!-- sponsors -->
{% if sponsors %}
{% for sponsor in sponsors.gold -%}
<a href="{{ sponsor.url }}" target="_blank" title="{{ sponsor.title }}"><img src="{{ sponsor.img }}" style="border-radius:15px"></a>
{% endfor -%}
{%- for sponsor in sponsors.silver -%}
<a href="{{ sponsor.url }}" target="_blank" title="{{ sponsor.title }}"><img src="{{ sponsor.img }}" style="border-radius:15px"></a>
{% endfor %}
{% endif %}
<!-- /sponsors -->
<a href="https://fastapi.tiangolo.com/fastapi-people/#sponsors" class="external-link" target="_blank">További szponzorok</a>
## Vélemények
"_[...] I'm using **FastAPI** a ton these days. [...] I'm actually planning to use it for all of my team's **ML services at Microsoft**. Some of them are getting integrated into the core **Windows** product and some **Office** products._"
<div style="text-align: right; margin-right: 10%;">Kabir Khan - <strong>Microsoft</strong> <a href="https://github.com/fastapi/fastapi/pull/26" target="_blank"><small>(ref)</small></a></div>
---
"_We adopted the **FastAPI** library to spawn a **REST** server that can be queried to obtain **predictions**. [for Ludwig]_"
<div style="text-align: right; margin-right: 10%;">Piero Molino, Yaroslav Dudin, and Sai Sumanth Miryala - <strong>Uber</strong> <a href="https://eng.uber.com/ludwig-v0-2/" target="_blank"><small>(ref)</small></a></div>
---
"_**Netflix** is pleased to announce the open-source release of our **crisis management** orchestration framework: **Dispatch**! [built with **FastAPI**]_"
<div style="text-align: right; margin-right: 10%;">Kevin Glisson, Marc Vilanova, Forest Monsen - <strong>Netflix</strong> <a href="https://netflixtechblog.com/introducing-dispatch-da4b8a2a8072" target="_blank"><small>(ref)</small></a></div>
---
"_Im over the moon excited about **FastAPI**. Its so fun!_"
<div style="text-align: right; margin-right: 10%;">Brian Okken - <strong><a href="https://pythonbytes.fm/episodes/show/123/time-to-right-the-py-wrongs?time_in_sec=855" target="_blank">Python Bytes</a> podcast host</strong> <a href="https://x.com/brianokken/status/1112220079972728832" target="_blank"><small>(ref)</small></a></div>
---
"_Honestly, what you've built looks super solid and polished. In many ways, it's what I wanted **Hug** to be - it's really inspiring to see someone build that._"
<div style="text-align: right; margin-right: 10%;">Timothy Crosley - <strong><a href="https://github.com/hugapi/hug" target="_blank">Hug</a> creator</strong> <a href="https://news.ycombinator.com/item?id=19455465" target="_blank"><small>(ref)</small></a></div>
---
"_If you're looking to learn one **modern framework** for building REST APIs, check out **FastAPI** [...] It's fast, easy to use and easy to learn [...]_"
"_We've switched over to **FastAPI** for our **APIs** [...] I think you'll like it [...]_"
<div style="text-align: right; margin-right: 10%;">Ines Montani - Matthew Honnibal - <strong><a href="https://explosion.ai" target="_blank">Explosion AI</a> founders - <a href="https://spacy.io" target="_blank">spaCy</a> creators</strong> <a href="https://x.com/_inesmontani/status/1144173225322143744" target="_blank"><small>(ref)</small></a> - <a href="https://x.com/honnibal/status/1144031421859655680" target="_blank"><small>(ref)</small></a></div>
---
"_If anyone is looking to build a production Python API, I would highly recommend **FastAPI**. It is **beautifully designed**, **simple to use** and **highly scalable**, it has become a **key component** in our API first development strategy and is driving many automations and services such as our Virtual TAC Engineer._"
<div style="text-align: right; margin-right: 10%;">Deon Pillsbury - <strong>Cisco</strong> <a href="https://www.linkedin.com/posts/deonpillsbury_cisco-cx-python-activity-6963242628536487936-trAp/" target="_blank"><small>(ref)</small></a></div>
---
## **Typer**, a CLI-ok FastAPI-ja
<a href="https://typer.tiangolo.com" target="_blank"><img src="https://typer.tiangolo.com/img/logo-margin/logo-margin-vector.svg" style="width: 20%;"></a>
Ha egy olyan CLI alkalmazást fejlesztesz amit a parancssorban kell használni webes API helyett, tekintsd meg: <a href="https://typer.tiangolo.com/" class="external-link" target="_blank">**Typer**</a>.
**Typer** a FastAPI kistestvére. A **CLI-k FastAPI-ja**. ⌨️ 🚀
## Követelmények
A FastAPI óriások vállán áll:
* <a href="https://www.starlette.io/" class="external-link" target="_blank">Starlette</a> a webes részekhez.
* <a href="https://docs.pydantic.dev/" class="external-link" target="_blank">Pydantic</a> az adat részekhez.
## Telepítés
<div class="termy">
```console
$ pip install fastapi
---> 100%
```
</div>
A production-höz egy ASGI szerverre is szükség lesz, mint például az <a href="https://www.uvicorn.org" class="external-link" target="_blank">Uvicorn</a> vagy a <a href="https://github.com/pgjones/hypercorn" class="external-link" target="_blank">Hypercorn</a>.
<div class="termy">
```console
$ pip install "uvicorn[standard]"
---> 100%
```
</div>
## Példa
### Hozd létre
* Hozz létre a `main.py` fájlt a következő tartalommal:
```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}
```
<details markdown="1">
<summary>Vagy használd az <code>async def</code>-et...</summary>
Ha a kódod `async` / `await`-et, használ `async def`:
```Python hl_lines="9 14"
from typing import Union
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
async def read_root():
return {"Hello": "World"}
@app.get("/items/{item_id}")
async def read_item(item_id: int, q: Union[str, None] = None):
return {"item_id": item_id, "q": q}
```
**Megjegyzés**:
Ha nem tudod, tekintsd meg a _"Sietsz?"_ szekciót <a href="https://fastapi.tiangolo.com/async/#in-a-hurry" target="_blank">`async` és `await`-ről dokumentációba</a>.
</details>
### Futtasd le
Indítsd el a szervert a következő paranccsal:
<div class="termy">
```console
$ uvicorn main:app --reload
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.
```
</div>
<details markdown="1">
<summary>A parancsról <code>uvicorn main:app --reload</code>...</summary>
A `uvicorn main:app` parancs a következőre utal:
* `main`: fájl `main.py` (a Python "modul").
* `app`: a `main.py`-ban a `app = FastAPI()` sorral létrehozott objektum.
* `--reload`: kód változtatás esetén újra indítja a szervert. Csak fejlesztés közben használandó.
</details>
### Ellenőrizd
Nyisd meg a böngésződ a következő címen: <a href="http://127.0.0.1:8000/items/5?q=somequery" class="external-link" target="_blank">http://127.0.0.1:8000/items/5?q=somequery</a>.
A következő JSON választ fogod látni:
```JSON
{"item_id": 5, "q": "somequery"}
```
Máris létrehoztál egy API-t ami:
* HTTP kéréseket fogad a `/` és `/items/{item_id}` _útvonalakon_.
* Mindkét _útvonal_ a `GET` <em>műveletet</em> használja (másik elnevezés: HTTP _metódus_).
* A `/items/{item_id}` _útvonalnak_ van egy _path paramétere_, az `item_id`, aminek `int` típusúnak kell lennie.
* A `/items/{item_id}` _útvonalnak_ még van egy opcionális, `str` típusú _query paramétere_ is, a `q`.
### Interaktív API dokumentáció
Most nyisd meg a <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a> címet.
Az automatikus interaktív API dokumentációt fogod látni (amit a <a href="https://github.com/swagger-api/swagger-ui" class="external-link" target="_blank">Swagger UI</a>-al hozunk létre):
![Swagger UI](https://fastapi.tiangolo.com/img/index/index-01-swagger-ui-simple.png)
### Alternatív API dokumentáció
És most menj el a <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a> címre.
Az alternatív automatikus dokumentációt fogod látni. (lásd <a href="https://github.com/Rebilly/ReDoc" class="external-link" target="_blank">ReDoc</a>):
![ReDoc](https://fastapi.tiangolo.com/img/index/index-02-redoc-simple.png)
## Példa frissítése
Módosítsuk a `main.py` fájlt, hogy `PUT` kérések esetén tudjon body-t fogadni.
Deklaráld a body-t standard Python típusokkal, a Pydantic-nak köszönhetően.
```Python hl_lines="4 9-12 25-27"
from typing import Union
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
price: float
is_offer: Union[bool, None] = None
@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}
@app.put("/items/{item_id}")
def update_item(item_id: int, item: Item):
return {"item_name": item.name, "item_id": item_id}
```
A szerver automatikusan újraindul (mert hozzáadtuk a --reload paramétert a fenti `uvicorn` parancshoz).
### Interaktív API dokumentáció frissítése
Most menj el a <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a> címre.
* Az interaktív API dokumentáció automatikusan frissült így már benne van az új body.
![Swagger UI](https://fastapi.tiangolo.com/img/index/index-03-swagger-02.png)
* Kattints rá a "Try it out" gombra, ennek segítségével kitöltheted a paramétereket és közvetlen használhatod az API-t:
![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-04-swagger-03.png)
* Ezután kattints az "Execute" gompra, a felhasználói felület kommunikálni fog az API-oddal. Elküldi a paramétereket és a visszakapott választ megmutatja a képernyődön.
![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-05-swagger-04.png)
### Alternatív API dokumentáció frissítés
Most menj el a <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a> címre.
* Az alternatív dokumentáció szintúgy tükrözni fogja az új kérési paraméter és body-t.
![ReDoc](https://fastapi.tiangolo.com/img/index/index-06-redoc-02.png)
### Összefoglalás
Összegzésül, deklarálod **egyszer** a paraméterek, body, stb típusát funkciós paraméterekként.
Ezt standard modern Python típusokkal csinálod.
Nem kell új szintaxist, vagy specifikus könyvtár mert metódósait, stb. megtanulnod.
Csak standard **Python**.
Például egy `int`-nek:
```Python
item_id: int
```
Egy komplexebb `Item` modellnek:
```Python
item: Item
```
... És csupán egy deklarációval megkapod a:
* Szerkesztő támogatást, beleértve:
* Szövegkiegészítés.
* Típus ellenőrzés.
* Adatok validációja:
* Automatikus és érthető hibák amikor az adatok hibásak.
* Validáció mélyen ágyazott objektumok esetén is.
* Bemeneti adatok<abbr title="also known as: serialization, parsing, marshalling"> átváltása</abbr> : a hálózatról érkező Python adatokká és típusokká. Adatok olvasása következő forrásokból:
* JSON.
* Cím paraméterek.
* Query paraméterek.
* Cookie-k.
* Header-ök.
* Formok.
* Fájlok.
* Kimeneti adatok <abbr title=" más néven: serialization, parsing, marshalling">átváltása</abbr>: Python adatok is típusokról hálózati adatokká:
* válts át Python típusokat (`str`, `int`, `float`, `bool`, `list`, etc).
* `datetime` csak objektumokat.
* `UUID` objektumokat.
* Adatbázis modelleket.
* ...És sok mást.
* Automatikus interaktív dokumentáció, beleértve két alternatív dokumentációt is:
* Swagger UI.
* ReDoc.
---
Visszatérve az előző kód példához. A **FastAPI**:
* Validálja hogy van egy `item_id` mező a `GET` és `PUT` kérésekben.
* Validálja hogy az `item_id` `int` típusú a `GET` és `PUT` kérésekben.
* Ha nem akkor látni fogunk egy tiszta hibát ezzel kapcsolatban.
* ellenőrzi hogyha van egy opcionális query paraméter `q` névvel (azaz `http://127.0.0.1:8000/items/foo?q=somequery`) `GET` kérések esetén.
* Mivel a `q` paraméter `= None`-al van deklarálva, ezért opcionális.
* `None` nélkül ez a mező kötelező lenne (mint például a body `PUT` kérések esetén).
* a `/items/{item_id}` címre érkező `PUT` kérések esetén, a JSON-t a következőképpen olvassa be:
* Ellenőrzi hogy létezik a kötelező `name` nevű attribútum és `string`.
* Ellenőrzi hogy létezik a kötelező `price` nevű attribútum és `float`.
* Ellenőrzi hogy létezik a `is_offer` nevű opcionális paraméter, ami ha létezik akkor `bool`
* Ez ágyazott JSON objektumokkal is működik
* JSONről való automatikus konvertálás.
* dokumentáljuk mindent OpenAPI-al amit használható:
* Interaktív dokumentációs rendszerekkel.
* Automatikus kliens kód generáló a rendszerekkel, több nyelven.
* Hozzá tartozik kettő interaktív dokumentációs web felület.
---
Eddig csak a felszínt kapargattuk, de a lényeg hogy most már könnyebben érthető hogyan működik.
Próbáld kicserélni a következő sorban:
```Python
return {"item_name": item.name, "item_id": item_id}
```
...ezt:
```Python
... "item_name": item.name ...
```
...erre:
```Python
... "item_price": item.price ...
```
... És figyeld meg hogy a szerkesztő automatikusan tudni fogja a típusokat és kiegészíti azokat:
![editor support](https://fastapi.tiangolo.com/img/vscode-completion.png)
Teljesebb példákért és funkciókért tekintsd meg a <a href="https://fastapi.tiangolo.com/tutorial/">Tutorial - User Guide</a> -t.
**Spoiler veszély**: a Tutorial - User Guidehoz tartozik:
* **Paraméterek** deklarációja különböző helyekről: **header-ök**, **cookie-k**, **form mezők** és **fájlok**.
* Hogyan állíts be **validációs feltételeket** mint a `maximum_length` vagy a `regex`.
* Nagyon hatékony és erős **<abbr title="also known as components, resources, providers, services, injectables">Függőség Injekció</abbr>** rendszerek.
* Biztonság és autentikáció beleértve, **OAuth2**, **JWT tokens** és **HTTP Basic** támogatást.
* Több haladó (de ugyanannyira könnyű) technika **mélyen ágyazott JSON modellek deklarációjára** (Pydantic-nek köszönhetően).
* **GraphQL** integráció <a href="https://strawberry.rocks" class="external-link" target="_blank">Strawberry</a>-vel és más könyvtárakkal.
* több extra funkció (Starlette-nek köszönhetően) pl.:
* **WebSockets**
* rendkívül könnyű tesztek HTTPX és `pytest` alapokra építve
* **CORS**
* **Cookie Sessions**
* ...és több.
## Teljesítmény
A független TechEmpower benchmarkok szerint az Uvicorn alatt futó **FastAPI** alkalmazások az <a href="https://www.techempower.com/benchmarks/#section=test&runid=7464e520-0dc2-473d-bd34-dbdfd7e85911&hw=ph&test=query&l=zijzen-7" class="external-link" target="_blank">egyik leggyorsabb Python keretrendszerek közé tartoznak</a>, éppen lemaradva a Starlette és az Uvicorn (melyeket a FastAPI belsőleg használ) mögött.(*)
Ezeknek a további megértéséhez: <a href="https://fastapi.tiangolo.com/benchmarks/" class="internal-link" target="_blank">Benchmarks</a>.
## Opcionális követelmények
Pydantic által használt:
* <a href="https://github.com/JoshData/python-email-validator" target="_blank"><code>email-validator</code></a> - e-mail validációkra.
* <a href="https://docs.pydantic.dev/latest/usage/pydantic_settings/" target="_blank"><code>pydantic-settings</code></a> - Beállítások követésére.
* <a href="https://docs.pydantic.dev/latest/usage/types/extra_types/extra_types/" target="_blank"><code>pydantic-extra-types</code></a> - Extra típusok Pydantic-hoz.
Starlette által használt:
* <a href="https://www.python-httpx.org" target="_blank"><code>httpx</code></a> - Követelmény ha a `TestClient`-et akarod használni.
* <a href="https://jinja.palletsprojects.com" target="_blank"><code>jinja2</code></a> - Követelmény ha az alap template konfigurációt akarod használni.
* <a href="https://github.com/Kludex/python-multipart" target="_blank"><code>python-multipart</code></a> - Követelmény ha <abbr title="converting the string that comes from an HTTP request into Python data">"parsing"</abbr>-ot akarsz támogatni, `request.form()`-al.
* <a href="https://pythonhosted.org/itsdangerous/" target="_blank"><code>itsdangerous</code></a> - Követelmény `SessionMiddleware` támogatáshoz.
* <a href="https://pyyaml.org/wiki/PyYAMLDocumentation" target="_blank"><code>pyyaml</code></a> - Követelmény a Starlette `SchemaGenerator`-ának támogatásához (valószínűleg erre nincs szükség FastAPI használása esetén).
FastAPI / Starlette által használt
* <a href="https://www.uvicorn.org" target="_blank"><code>uvicorn</code></a> - Szerverekhez amíg betöltik és szolgáltatják az applikációdat.
* <a href="https://github.com/ijl/orjson" target="_blank"><code>orjson</code></a> - Követelmény ha `ORJSONResponse`-t akarsz használni.
* <a href="https://github.com/esnme/ultrajson" target="_blank"><code>ujson</code></a> - Követelmény ha `UJSONResponse`-t akarsz használni.
Ezeket mind telepítheted a `pip install "fastapi[all]"` paranccsal.
## Licensz
Ez a projekt az MIT license, licensz alatt fut

View File

@@ -1 +0,0 @@
INHERIT: ../en/mkdocs.yml

View File

@@ -1,495 +0,0 @@
# FastAPI
<style>
.md-content .md-typeset h1 { display: none; }
</style>
<p align="center">
<a href="https://fastapi.tiangolo.com"><img src="https://fastapi.tiangolo.com/img/logo-margin/logo-teal.png" alt="FastAPI"></a>
</p>
<p align="center">
<em>FastAPI, framework performa tinggi, mudah dipelajari, cepat untuk coding, siap untuk pengembangan</em>
</p>
<p align="center">
<a href="https://github.com/fastapi/fastapi/actions?query=workflow%3ATest+event%3Apush+branch%3Amaster" target="_blank">
<img src="https://github.com/fastapi/fastapi/actions/workflows/test.yml/badge.svg?event=push&branch=master" alt="Test">
</a>
<a href="https://coverage-badge.samuelcolvin.workers.dev/redirect/fastapi/fastapi" target="_blank">
<img src="https://coverage-badge.samuelcolvin.workers.dev/fastapi/fastapi.svg" alt="Coverage">
</a>
<a href="https://pypi.org/project/fastapi" target="_blank">
<img src="https://img.shields.io/pypi/v/fastapi?color=%2334D058&label=pypi%20package" alt="Package version">
</a>
<a href="https://pypi.org/project/fastapi" target="_blank">
<img src="https://img.shields.io/pypi/pyversions/fastapi.svg?color=%2334D058" alt="Supported Python versions">
</a>
</p>
---
**Dokumentasi**: <a href="https://fastapi.tiangolo.com" target="_blank">https://fastapi.tiangolo.com</a>
**Kode Sumber**: <a href="https://github.com/fastapi/fastapi" target="_blank">https://github.com/fastapi/fastapi</a>
---
FastAPI adalah *framework* *web* moderen, cepat (performa-tinggi) untuk membangun API dengan Python berdasarkan tipe petunjuk Python.
Fitur utama FastAPI:
* **Cepat**: Performa sangat tinggi, setara **NodeJS** dan **Go** (berkat Starlette dan Pydantic). [Salah satu *framework* Python tercepat yang ada](#performa).
* **Cepat untuk coding**: Meningkatkan kecepatan pengembangan fitur dari 200% sampai 300%. *
* **Sedikit bug**: Mengurangi hingga 40% kesalahan dari manusia (pemrogram). *
* **Intuitif**: Dukungan editor hebat. <abbr title="juga dikenal otomatis-lengkap, pelengkapan otomatis, kecerdasan">Penyelesaian</abbr> di mana pun. Lebih sedikit *debugging*.
* **Mudah**: Dibuat mudah digunakan dan dipelajari. Sedikit waktu membaca dokumentasi.
* **Ringkas**: Mengurasi duplikasi kode. Beragam fitur dari setiap deklarasi parameter. Lebih sedikit *bug*.
* **Handal**: Dapatkan kode siap-digunakan. Dengan dokumentasi otomatis interaktif.
* **Standar-resmi**: Berdasarkan (kompatibel dengan ) standar umum untuk API: <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank">OpenAPI</a> (sebelumnya disebut Swagger) dan <a href="https://json-schema.org/" class="external-link" target="_blank">JSON Schema</a>.
<small>* estimasi berdasarkan pengujian tim internal pengembangan applikasi siap pakai.</small>
## Sponsor
<!-- sponsors -->
{% if sponsors %}
{% for sponsor in sponsors.gold -%}
<a href="{{ sponsor.url }}" target="_blank" title="{{ sponsor.title }}"><img src="{{ sponsor.img }}" style="border-radius:15px"></a>
{% endfor -%}
{%- for sponsor in sponsors.silver -%}
<a href="{{ sponsor.url }}" target="_blank" title="{{ sponsor.title }}"><img src="{{ sponsor.img }}" style="border-radius:15px"></a>
{% endfor %}
{% endif %}
<!-- /sponsors -->
<a href="https://fastapi.tiangolo.com/fastapi-people/#sponsors" class="external-link" target="_blank">Sponsor lainnya</a>
## Opini
"_[...] Saya banyak menggunakan **FastAPI** sekarang ini. [...] Saya berencana menggunakannya di semua tim servis ML Microsoft. Beberapa dari mereka sudah mengintegrasikan dengan produk inti *Windows** dan sebagian produk **Office**._"
<div style="text-align: right; margin-right: 10%;">Kabir Khan - <strong>Microsoft</strong> <a href="https://github.com/fastapi/fastapi/pull/26" target="_blank"><small>(ref)</small></a></div>
---
"_Kami adopsi library **FastAPI** untuk membuat server **REST** yang melakukan kueri untuk menghasilkan **prediksi**. [untuk Ludwig]_"
<div style="text-align: right; margin-right: 10%;">Piero Molino, Yaroslav Dudin, and Sai Sumanth Miryala - <strong>Uber</strong> <a href="https://eng.uber.com/ludwig-v0-2/" target="_blank"><small>(ref)</small></a></div>
---
"_**Netflix** dengan bangga mengumumkan rilis open-source orkestrasi framework **manajemen krisis** : **Dispatch**! [dibuat dengan **FastAPI**]_"
<div style="text-align: right; margin-right: 10%;">Kevin Glisson, Marc Vilanova, Forest Monsen - <strong>Netflix</strong> <a href="https://netflixtechblog.com/introducing-dispatch-da4b8a2a8072" target="_blank"><small>(ref)</small></a></div>
---
"_Saya sangat senang dengan **FastAPI**. Sangat menyenangkan!_"
<div style="text-align: right; margin-right: 10%;">Brian Okken - <strong><a href="https://pythonbytes.fm/episodes/show/123/time-to-right-the-py-wrongs?time_in_sec=855" target="_blank">Python Bytes</a> podcast host</strong> <a href="https://x.com/brianokken/status/1112220079972728832" target="_blank"><small>(ref)</small></a></div>
---
"_Jujur, apa yang anda buat sangat solid dan berkualitas. Ini adalah yang saya inginkan di **Hug** - sangat menginspirasi melihat seseorang membuat ini._"
<div style="text-align: right; margin-right: 10%;">Timothy Crosley - <strong><a href="https://github.com/hugapi/hug" target="_blank">Hug</a> creator</strong> <a href="https://news.ycombinator.com/item?id=19455465" target="_blank"><small>(ref)</small></a></div>
---
"_Jika anda ingin mempelajari **framework moderen** untuk membangun REST API, coba **FastAPI** [...] cepat, mudah digunakan dan dipelajari [...]_"
"_Kami sudah pindah ke **FastAPI** untuk **API** kami [...] Saya pikir kamu juga akan suka [...]_"
<div style="text-align: right; margin-right: 10%;">Ines Montani - Matthew Honnibal - <strong><a href="https://explosion.ai" target="_blank">Explosion AI</a> founders - <a href="https://spacy.io" target="_blank">spaCy</a> creators</strong> <a href="https://x.com/_inesmontani/status/1144173225322143744" target="_blank"><small>(ref)</small></a> - <a href="https://x.com/honnibal/status/1144031421859655680" target="_blank"><small>(ref)</small></a></div>
---
"_Jika anda ingin membuat API Python siap pakai, saya merekomendasikan **FastAPI**. FastAPI **didesain indah**, **mudah digunakan** dan **sangat scalable**, FastAPI adalah **komponen kunci** di strategi pengembangan API pertama kami dan mengatur banyak otomatisasi dan service seperti TAC Engineer kami._"
<div style="text-align: right; margin-right: 10%;">Deon Pillsbury - <strong>Cisco</strong> <a href="https://www.linkedin.com/posts/deonpillsbury_cisco-cx-python-activity-6963242628536487936-trAp/" target="_blank"><small>(ref)</small></a></div>
---
## **Typer**, CLI FastAPI
<a href="https://typer.tiangolo.com" target="_blank"><img src="https://typer.tiangolo.com/img/logo-margin/logo-margin-vector.svg" style="width: 20%;"></a>
Jika anda mengembangkan app <abbr title="Command Line Interface">CLI</abbr> yang digunakan di terminal bukan sebagai API web, kunjungi <a href="https://typer.tiangolo.com/" class="external-link" target="_blank">**Typer**</a>.
**Typer** adalah saudara kecil FastAPI. Dan ditujukan sebagai **CLI FastAPI**. ⌨️ 🚀
## Prayarat
FastAPI berdiri di pundak raksasa:
* <a href="https://www.starlette.io/" class="external-link" target="_blank">Starlette</a> untuk bagian web.
* <a href="https://docs.pydantic.dev/" class="external-link" target="_blank">Pydantic</a> untuk bagian data.
## Instalasi
Buat dan aktifkan <a href="https://fastapi.tiangolo.com/virtual-environments/" class="external-link" target="_blank">virtual environment</a> kemudian *install* FastAPI:
<div class="termy">
```console
$ pip install "fastapi[standard]"
---> 100%
```
</div>
**Catatan**: Pastikan anda menulis `"fastapi[standard]"` dengan tanda petik untuk memastikan bisa digunakan di semua *terminal*.
## Contoh
### Buat app
* Buat file `main.py` dengan:
```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}
```
<details markdown="1">
<summary>Atau gunakan <code>async def</code>...</summary>
Jika kode anda menggunakan `async` / `await`, gunakan `async def`:
```Python hl_lines="9 14"
from typing import Union
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
async def read_root():
return {"Hello": "World"}
@app.get("/items/{item_id}")
async def read_item(item_id: int, q: Union[str, None] = None):
return {"item_id": item_id, "q": q}
```
**Catatan**:
Jika anda tidak paham, kunjungi _"Panduan cepat"_ bagian <a href="https://fastapi.tiangolo.com/async/#in-a-hurry" target="_blank">`async` dan `await` di dokumentasi</a>.
</details>
### Jalankan
Jalankan *server* dengan:
<div class="termy">
```console
$ 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 [2248755] using WatchFiles
INFO: Started server process [2248757]
INFO: Waiting for application startup.
INFO: Application startup complete.
```
</div>
<details markdown="1">
<summary>Mengenai perintah <code>fastapi dev main.py</code>...</summary>
Perintah `fastapi dev` membaca file `main.py`, memeriksa app **FastAPI** di dalamnya, dan menjalan server dengan <a href="https://www.uvicorn.org" class="external-link" target="_blank">Uvicorn</a>.
Secara otomatis, `fastapi dev` akan mengaktifkan *auto-reload* untuk pengembangan lokal.
Informasi lebih lanjut kunjungi <a href="https://fastapi.tiangolo.com/fastapi-cli/" target="_blank">Dokumen FastAPI CLI</a>.
</details>
### Periksa
Buka *browser* di <a href="http://127.0.0.1:8000/items/5?q=somequery" class="external-link" target="_blank">http://127.0.0.1:8000/items/5?q=somequery</a>.
Anda akan melihat respon JSON berikut:
```JSON
{"item_id": 5, "q": "somequery"}
```
Anda telah membuat API:
* Menerima permintaan HTTP di _path_ `/` dan `/items/{item_id}`.
* Kedua _paths_ menerima <em>operasi</em> `GET` (juga disebut _metode_ HTTP).
* _path_ `/items/{item_id}` memiliki _parameter path_ `item_id` yang harus berjenis `int`.
* _path_ `/items/{item_id}` memiliki _query parameter_ `q` berjenis `str`.
### Dokumentasi API interaktif
Sekarang kunjungi <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
Anda akan melihat dokumentasi API interaktif otomatis (dibuat oleh <a href="https://github.com/swagger-api/swagger-ui" class="external-link" target="_blank">Swagger UI</a>):
![Swagger UI](https://fastapi.tiangolo.com/img/index/index-01-swagger-ui-simple.png)
### Dokumentasi API alternatif
Kemudian kunjungi <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a>.
Anda akan melihat dokumentasi alternatif otomatis (dibuat oleh <a href="https://github.com/Rebilly/ReDoc" class="external-link" target="_blank">ReDoc</a>):
![ReDoc](https://fastapi.tiangolo.com/img/index/index-02-redoc-simple.png)
## Contoh upgrade
Sekarang ubah `main.py` untuk menerima struktur permintaan `PUT`.
Deklarasikan struktur menggunakan tipe standar Python, berkat Pydantic.
```Python hl_lines="4 9-12 25-27"
from typing import Union
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
price: float
is_offer: Union[bool, None] = None
@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}
@app.put("/items/{item_id}")
def update_item(item_id: int, item: Item):
return {"item_name": item.name, "item_id": item_id}
```
Server `fastapi dev` akan otomatis memuat kembali.
### Upgrade dokumentasi API interaktif
Kunjungi <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
* Dokumentasi API interaktif akan otomatis diperbarui, termasuk kode yang baru:
![Swagger UI](https://fastapi.tiangolo.com/img/index/index-03-swagger-02.png)
* Klik tombol "Try it out", anda dapat mengisi parameter dan langsung berinteraksi dengan API:
![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-04-swagger-03.png)
* Kemudian klik tombol "Execute", tampilan pengguna akan berkomunikasi dengan API, mengirim parameter, mendapatkan dan menampilkan hasil ke layar:
![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-05-swagger-04.png)
### Upgrade dokumentasi API alternatif
Kunjungi <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a>.
* Dokumentasi alternatif akan menampilkan parameter *query* dan struktur *request*:
![ReDoc](https://fastapi.tiangolo.com/img/index/index-06-redoc-02.png)
### Ringkasan
Singkatnya, anda mendeklarasikan **sekali** jenis parameter, struktur, dll. sebagai parameter fungsi.
Anda melakukannya dengan tipe standar moderen Python.
Anda tidak perlu belajar sintaksis, metode, *classs* baru dari *library* tertentu, dll.
Cukup **Python** standar.
Sebagai contoh untuk `int`:
```Python
item_id: int
```
atau untuk model lebih rumit `Item`:
```Python
item: Item
```
...dengan sekali deklarasi anda mendapatkan:
* Dukungan editor, termasuk:
* Pelengkapan kode.
* Pengecekan tipe.
* Validasi data:
* Kesalahan otomatis dan jelas ketika data tidak sesuai.
* Validasi hingga untuk object JSON bercabang mendalam.
* <abbr title="juga disebut: serialization, parsing, marshalling">Konversi</abbr> input data: berasal dari jaringan ke data dan tipe Python. Membaca dari:
* JSON.
* Parameter path.
* Parameter query.
* Cookie.
* Header.
* Form.
* File.
* <abbr title="juga disebut: serialization, parsing, marshalling">Konversi</abbr> output data: konversi data Python ke tipe jaringan data (seperti JSON):
* Konversi tipe Python (`str`, `int`, `float`, `bool`, `list`, dll).
* Objek `datetime`.
* Objek `UUID`.
* Model database.
* ...dan banyak lagi.
* Dokumentasi interaktif otomatis, termasuk 2 alternatif tampilan pengguna:
* Swagger UI.
* ReDoc.
---
Kembali ke kode contoh sebelumnya, **FastAPI** akan:
* Validasi apakah terdapat `item_id` di *path* untuk permintaan `GET` dan `PUT` requests.
* Validasi apakah `item_id` berjenit `int` untuk permintaan `GET` dan `PUT`.
* Jika tidak, klien akan melihat pesan kesalahan jelas.
* Periksa jika ada parameter *query* opsional bernama `q` (seperti `http://127.0.0.1:8000/items/foo?q=somequery`) untuk permintaan `GET`.
* Karena parameter `q` dideklarasikan dengan `= None`, maka bersifat opsional.
* Tanpa `None` maka akan menjadi wajib ada (seperti struktur di kondisi dengan `PUT`).
* Untuk permintaan `PUT` `/items/{item_id}`, membaca struktur sebagai JSON:
* Memeriksa terdapat atribut wajib `name` harus berjenis `str`.
* Memeriksa terdapat atribut wajib`price` harus berjenis `float`.
* Memeriksa atribut opsional `is_offer`, harus berjenis `bool`, jika ada.
* Semua ini juga sama untuk objek json yang bersarang mendalam.
* Konversi dari dan ke JSON secara otomatis.
* Dokumentasi segalanya dengan OpenAPI, dengan menggunakan:
* Sistem dokumentasi interaktif.
* Sistem otomatis penghasil kode, untuk banyak bahasa.
* Menyediakan 2 tampilan dokumentasi web interaktif dengan langsung.
---
Kita baru menyentuh permukaannya saja, tetapi anda sudah mulai paham gambaran besar cara kerjanya.
Coba ubah baris:
```Python
return {"item_name": item.name, "item_id": item_id}
```
...dari:
```Python
... "item_name": item.name ...
```
...menjadi:
```Python
... "item_price": item.price ...
```
...anda akan melihat kode editor secara otomatis melengkapi atributnya dan tahu tipe nya:
![editor support](https://fastapi.tiangolo.com/img/vscode-completion.png)
Untuk contoh lengkap termasuk fitur lainnya, kunjungi <a href="https://fastapi.tiangolo.com/tutorial/">Tutorial - Panduan Pengguna</a>.
**Peringatan spoiler**: tutorial - panduan pengguna termasuk:
* Deklarasi **parameter** dari tempat berbeda seperti: **header**, **cookie**, **form field** and **file**.
* Bagaimana mengatur **batasan validasi** seperti `maximum_length`atau `regex`.
* Sistem **<abbr title="also known as components, resources, providers, services, injectables">Dependency Injection</abbr>** yang hebat dan mudah digunakan.
* Keamanan dan autentikasi, termasuk dukungan ke **OAuth2** dengan **JWT token** dan autentikasi **HTTP Basic**.
* Teknik lebih aju (tetapi mudah dipakai untuk deklarasi **model JSON bersarang ke dalam** (berkat Pydantic).
* Integrasi **GraphQL** dengan <a href="https://strawberry.rocks" class="external-link" target="_blank">Strawberry</a> dan library lainnya.
* Fitur lainnya (berkat Starlette) seperti:
* **WebSocket**
* Test yang sangat mudah berdasarkan HTTPX dan `pytest`
* **CORS**
* **Cookie Session**
* ...dan lainnya.
## Performa
Tolok ukur Independent TechEmpower mendapati aplikasi **FastAPI** berjalan menggunakan Uvicorn sebagai <a href="https://www.techempower.com/benchmarks/#section=test&runid=7464e520-0dc2-473d-bd34-dbdfd7e85911&hw=ph&test=query&l=zijzen-7" class="external-link" target="_blank">salah satu framework Python tercepat yang ada</a>, hanya di bawah Starlette dan Uvicorn itu sendiri (digunakan di internal FastAPI). (*)
Penjelasan lebih lanjut, lihat bagian <a href="https://fastapi.tiangolo.com/benchmarks/" class="internal-link" target="_blank">Tolok ukur</a>.
## Dependensi
FastAPI bergantung pada Pydantic dan Starlette.
### Dependensi `standar`
Ketika anda meng-*install* FastAPI dengan `pip install "fastapi[standard]"`, maka FastAPI akan menggunakan sekumpulan dependensi opsional `standar`:
Digunakan oleh Pydantic:
* <a href="https://github.com/JoshData/python-email-validator" target="_blank"><code>email-validator</code></a> - untuk validasi email.
Digunakan oleh Starlette:
* <a href="https://www.python-httpx.org" target="_blank"><code>httpx</code></a> - Dibutuhkan jika anda menggunakan `TestClient`.
* <a href="https://jinja.palletsprojects.com" target="_blank"><code>jinja2</code></a> - Dibutuhkan jika anda menggunakan konfigurasi template bawaan.
* <a href="https://github.com/Kludex/python-multipart" target="_blank"><code>python-multipart</code></a> - Dibutuhkan jika anda menggunakan form dukungan <abbr title="converting the string that comes from an HTTP request into Python data">"parsing"</abbr>, dengan `request.form()`.
Digunakan oleh FastAPI / Starlette:
* <a href="https://www.uvicorn.org" target="_blank"><code>uvicorn</code></a> - untuk server yang memuat dan melayani aplikasi anda. Termasuk `uvicorn[standard]`, yang memasukan sejumlah dependensi (misal `uvloop`) untuk needed melayani dengan performa tinggi.
* `fastapi-cli` - untuk menyediakan perintah `fastapi`.
### Tanpda dependensi `standard`
Jika anda tidak ingin menambahkan dependensi opsional `standard`, anda dapat menggunakan `pip install fastapi` daripada `pip install "fastapi[standard]"`.
### Dependensi Opsional Tambahan
Ada beberapa dependensi opsional yang bisa anda install.
Dependensi opsional tambahan Pydantic:
* <a href="https://docs.pydantic.dev/latest/usage/pydantic_settings/" target="_blank"><code>pydantic-settings</code></a> - untuk manajemen setting.
* <a href="https://docs.pydantic.dev/latest/usage/types/extra_types/extra_types/" target="_blank"><code>pydantic-extra-types</code></a> - untuk tipe tambahan yang digunakan dengan Pydantic.
Dependensi tambahan opsional FastAPI:
* <a href="https://github.com/ijl/orjson" target="_blank"><code>orjson</code></a> - Diperlukan jika anda akan menggunakan`ORJSONResponse`.
* <a href="https://github.com/esnme/ultrajson" target="_blank"><code>ujson</code></a> - Diperlukan jika anda akan menggunakan `UJSONResponse`.
## Lisensi
Project terlisensi dengan lisensi MIT.

View File

@@ -1,332 +0,0 @@
# Langkah Pertama
File FastAPI yang paling sederhana bisa seperti berikut:
{* ../../docs_src/first_steps/tutorial001.py *}
Salin file tersebut ke `main.py`.
Jalankan di server:
<div class="termy">
```console
$ <font color="#4E9A06">fastapi</font> dev <u style="text-decoration-style:single">main.py</u>
<font color="#3465A4">INFO </font> Using path <font color="#3465A4">main.py</font>
<font color="#3465A4">INFO </font> Resolved absolute path <font color="#75507B">/home/user/code/awesomeapp/</font><font color="#AD7FA8">main.py</font>
<font color="#3465A4">INFO </font> Searching for package file structure from directories with <font color="#3465A4">__init__.py</font> files
<font color="#3465A4">INFO </font> Importing from <font color="#75507B">/home/user/code/</font><font color="#AD7FA8">awesomeapp</font>
╭─ <font color="#8AE234"><b>Python module file</b></font> ─╮
│ │
│ 🐍 main.py │
│ │
╰──────────────────────╯
<font color="#3465A4">INFO </font> Importing module <font color="#4E9A06">main</font>
<font color="#3465A4">INFO </font> Found importable FastAPI app
╭─ <font color="#8AE234"><b>Importable FastAPI app</b></font> ─╮
│ │
│ <span style="background-color:#272822"><font color="#FF4689">from</font></span><span style="background-color:#272822"><font color="#F8F8F2"> main </font></span><span style="background-color:#272822"><font color="#FF4689">import</font></span><span style="background-color:#272822"><font color="#F8F8F2"> app</font></span><span style="background-color:#272822"> </span> │
│ │
╰──────────────────────────╯
<font color="#3465A4">INFO </font> Using import string <font color="#8AE234"><b>main:app</b></font>
<span style="background-color:#C4A000"><font color="#2E3436">╭────────── FastAPI CLI - Development mode ───────────╮</font></span>
<span style="background-color:#C4A000"><font color="#2E3436">│ │</font></span>
<span style="background-color:#C4A000"><font color="#2E3436">│ Serving at: http://127.0.0.1:8000 │</font></span>
<span style="background-color:#C4A000"><font color="#2E3436">│ │</font></span>
<span style="background-color:#C4A000"><font color="#2E3436">│ API docs: http://127.0.0.1:8000/docs │</font></span>
<span style="background-color:#C4A000"><font color="#2E3436">│ │</font></span>
<span style="background-color:#C4A000"><font color="#2E3436">│ Running in development mode, for production use: │</font></span>
<span style="background-color:#C4A000"><font color="#2E3436">│ │</font></span>
<span style="background-color:#C4A000"><font color="#2E3436">│ </font></span><span style="background-color:#C4A000"><font color="#555753"><b>fastapi run</b></font></span><span style="background-color:#C4A000"><font color="#2E3436"> │</font></span>
<span style="background-color:#C4A000"><font color="#2E3436">│ │</font></span>
<span style="background-color:#C4A000"><font color="#2E3436">╰─────────────────────────────────────────────────────╯</font></span>
<font color="#4E9A06">INFO</font>: Will watch for changes in these directories: [&apos;/home/user/code/awesomeapp&apos;]
<font color="#4E9A06">INFO</font>: Uvicorn running on <b>http://127.0.0.1:8000</b> (Press CTRL+C to quit)
<font color="#4E9A06">INFO</font>: Started reloader process [<font color="#34E2E2"><b>2265862</b></font>] using <font color="#34E2E2"><b>WatchFiles</b></font>
<font color="#4E9A06">INFO</font>: Started server process [<font color="#06989A">2265873</font>]
<font color="#4E9A06">INFO</font>: Waiting for application startup.
<font color="#4E9A06">INFO</font>: Application startup complete.
```
</div>
Di output, terdapat sebaris pesan:
```hl_lines="4"
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
```
Baris tersebut menunjukan URL dimana app aktif di komputer anda.
### Mencoba aplikasi
Buka browser di <a href="http://127.0.0.1:8000" class="external-link" target="_blank">http://127.0.0.1:8000</a>.
Anda akan melihat response JSON sebagai berikut:
```JSON
{"message": "Hello World"}
```
### Dokumen API interaktif
Sekarang kunjungi <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
Anda akan melihat dokumentasi API interaktif otomatis (dibuat oleh <a href="https://github.com/swagger-api/swagger-ui" class="external-link" target="_blank">Swagger UI</a>):
![Swagger UI](https://fastapi.tiangolo.com/img/index/index-01-swagger-ui-simple.png)
### Dokumen API alternatif
Dan sekarang, kunjungi <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a>.
Anda akan melihat dokumentasi alternatif otomatis (dibuat oleh <a href="https://github.com/Rebilly/ReDoc" class="external-link" target="_blank">ReDoc</a>):
![ReDoc](https://fastapi.tiangolo.com/img/index/index-02-redoc-simple.png)
### OpenAPI
**FastAPI** membuat sebuah "schema" dimana semua API anda menggunakan standar **OpenAPI** untuk mendefinisikan API.
#### "Schema"
"schema" adalah suatu definisi atau deskripsi dari sesuatu. Bukan kode yang mengimplementasi definisi tersebut. Ini hanyalah sebuah deskripsi abstrak.
#### "schema" API
Dalam hal ini, <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank">OpenAPI</a> adalah spesifikasi yang menunjukan bagaimana untuk mendefinisikan sebuah skema di API anda.
Definisi skema ini termasuk jalur API anda, parameter yang bisa diterima, dll.
#### "schema" Data
Istilah "schema" bisa juga merujuk ke struktur data, seperti konten JSON.
Dalam kondisi ini, ini berarti attribut JSON dan tipe data yang dimiliki, dll.
#### Schema OpenAPI and JSON
"schema" OpenAPI mendefinisikan skema API dari API yang anda buat. Skema tersebut termasuk definisi (atau "schema") dari data yang dikirim atau diterima oleh API dari **JSON Schema**, skema data standar JSON.
#### Lihat `openapi.json`
Jika anda penasaran bagaimana skema OpenAPI polos seperti apa, FastAPI secara otomatis membuat JSON (schema) dengan deksripsi API anda.
anda bisa melihatnya di: <a href="http://127.0.0.1:8000/openapi.json" class="external-link" target="_blank">http://127.0.0.1:8000/openapi.json</a>.
Anda akan melihat JSON yang dimulai seperti:
```JSON
{
"openapi": "3.1.0",
"info": {
"title": "FastAPI",
"version": "0.1.0"
},
"paths": {
"/items/": {
"get": {
"responses": {
"200": {
"description": "Successful Response",
"content": {
"application/json": {
...
```
#### Kegunaan OpenAPI
Skema OpenAPI adalah tulang punggung dua sistem dokumentasi API interaktif yang ada di FastAPI.
Ada banyak alternatif sistem dokumentasi lainnya yang semuanya berdasarkan OpenAPI. Anda bisa menambahkannya ke aplikasi **FastAPI** anda.
Anda juga bisa menggunakan OpenAPI untuk membuat kode secara otomatis, untuk klien yang menggunakan API anda. Sebagai contoh, frontend, aplikasi mobile atau IoT.
## Ringkasan, secara bertahap
### Langkah 1: impor `FastAPI`
{* ../../docs_src/first_steps/tutorial001.py hl[1] *}
`FastAPI` adalah class Python yang menyediakan semua fungsionalitas API anda.
/// note | Detail Teknis
`FastAPI` adalah class turunan langsung dari `Starlette`.
Anda bisa menggunakan semua fungsionalitas <a href="https://www.starlette.io/" class="external-link" target="_blank">Starlette</a> dengan `FastAPI` juga.
///
### Langkah 2: buat "instance" dari `FastAPI`
{* ../../docs_src/first_steps/tutorial001.py hl[3] *}
Di sini variabel `app` akan menjadi sebuah "instance" dari class `FastAPI`.
Ini akan menjadi gerbang utama untuk membuat semua API anda.
### Langkah 3: Buat *operasi path*
#### Path
"Path" atau jalur di sini merujuk ke bagian URL terakhir dimulai dari `/` pertama.
Sehingga, URL seperti:
```
https://example.com/items/foo
```
...path-nya adalah:
```
/items/foo
```
/// info
"path" juga biasa disebut "endpoint" atau "route".
///
ketika membuat API, "path" adalah jalan utama untuk memisahkan "concern" dan "resources".
#### Operasi
"Operasi" di sini merujuk ke salah satu dari metode HTTP berikut.
Salah satu dari:
* `POST`
* `GET`
* `PUT`
* `DELETE`
...dan operasi lainnya yang unik:
* `OPTIONS`
* `HEAD`
* `PATCH`
* `TRACE`
Dalam protokol HTTP, anda bisa berkomunikasi ke setiap path menggunakan satu (atau lebih) metode di atas.
---
Ketika membuat API, anda umumnya menggunakan metode HTTP tertentu untuk proses tertentu.
Umumnya menggunakan:
* `POST`: untuk membuat data.
* `GET`: untuk membaca data.
* `PUT`: untuk memperbarui data.
* `DELETE`: untuk menghapus data.
Sehingga, di OpanAPI, setiap metode HTTP ini disebut sebuah "operasi".
Kita akan menyebut mereka juga "**operasi**".
#### Mendefinisikan *dekorator operasi path*
{* ../../docs_src/first_steps/tutorial001.py hl[6] *}
`@app.get("/")` memberitahu **FastAPI** bahwa fungsi di bawahnya mengurusi request yang menuju ke:
* path `/`
* menggunakan <abbr title="an HTTP GET method">operasi <code>get</code></abbr>
/// info | `@decorator` Info
Sintaksis `@sesuatu` di Python disebut "dekorator".
Dekorator ditempatkan di atas fungsi. Seperti sebuah topi cantik (Saya pikir istilah ini berasal dari situ).
"dekorator" memanggil dan bekerja dengan fungsi yang ada di bawahnya
Pada kondisi ini, dekorator ini memberi tahu **FastAPI** bahwa fungsi di bawah nya berhubungan dengan **path** `/` dengan **operasi** `get`.
Sehingga disebut **dekorator operasi path**.
///
Operasi lainnya yang bisa digunakan:
* `@app.post()`
* `@app.put()`
* `@app.delete()`
Dan operasi unik lainnya:
* `@app.options()`
* `@app.head()`
* `@app.patch()`
* `@app.trace()`
/// tip | Tips
Jika anda bisa menggunakan operasi apa saja (metode HTTP).
**FastAPI** tidak mengharuskan anda menggunakan operasi tertentu.
Informasi di sini hanyalah sebagai panduan, bukan keharusan.
Sebagai contoh, ketika menggunakan GraphQL, semua operasi umumnya hanya menggunakan `POST`.
///
### Langkah 4: mendefinisikan **fungsi operasi path**
Ini "**fungsi operasi path**" kita:
* **path**: adalah `/`.
* **operasi**: adalah `get`.
* **fungsi**: adalah fungsi yang ada di bawah dekorator (di bawah `@app.get("/")`).
{* ../../docs_src/first_steps/tutorial001.py hl[7] *}
Ini adalah fungsi Python.
Fungsi ini dipanggil **FastAPI** setiap kali menerima request ke URL "`/`" dengan operasi `GET`.
Di kondisi ini, ini adalah sebuah fungsi `async`.
---
Anda bisa mendefinisikan fungsi ini sebagai fungsi normal daripada `async def`:
{* ../../docs_src/first_steps/tutorial003.py hl[7] *}
/// note | Catatan
Jika anda tidak tahu perbedaannya, kunjungi [Async: *"Panduan cepat"*](../async.md#in-a-hurry){.internal-link target=_blank}.
///
### Langkah 5: hasilkan konten
{* ../../docs_src/first_steps/tutorial001.py hl[8] *}
Anda bisa menghasilkan `dict`, `list`, nilai singular seperti `str`, `int`, dll.
Anda juga bisa menghasilkan model Pydantic (anda akan belajar mengenai ini nanti).
Ada banyak objek dan model yang secara otomatis dikonversi ke JSON (termasuk ORM, dll). Anda bisa menggunakan yang anda suka, kemungkinan sudah didukung.
## Ringkasan
* Impor `FastAPI`.
* Buat sebuah instance `app`.
* Tulis **dekorator operasi path** menggunakan dekorator seperti `@app.get("/")`.
* Definisikan **fungsi operasi path**; sebagai contoh, `def root(): ...`.
* Jalankan server development dengan perintah `fastapi dev`.

View File

@@ -1,83 +0,0 @@
# Tutorial - Pedoman Pengguna - Pengenalan
Tutorial ini menunjukan cara menggunakan ***FastAPI*** dengan semua fitur-fiturnya, tahap demi tahap.
Setiap bagian dibangun secara bertahap dari bagian sebelumnya, tetapi terstruktur untuk memisahkan banyak topik, sehingga kamu bisa secara langsung menuju ke topik spesifik untuk menyelesaikan kebutuhan API tertentu.
Ini juga dibangun untuk digunakan sebagai referensi yang akan datang.
Sehingga kamu dapat kembali lagi dan mencari apa yang kamu butuhkan dengan tepat.
## Jalankan kode
Semua blok-blok kode dapat disalin dan digunakan langsung (Mereka semua sebenarnya adalah file python yang sudah teruji).
Untuk menjalankan setiap contoh, salin kode ke file `main.py`, dan jalankan `uvicorn` dengan:
<div class="termy">
```console
$ uvicorn main:app --reload
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
<span style="color: green;">INFO</span>: Started reloader process [28720]
<span style="color: green;">INFO</span>: Started server process [28722]
<span style="color: green;">INFO</span>: Waiting for application startup.
<span style="color: green;">INFO</span>: Application startup complete.
```
</div>
**SANGAT disarankan** agar kamu menulis atau menyalin kode, mengubahnya dan menjalankannya secara lokal.
Dengan menggunakannya di dalam editor, benar-benar memperlihatkan manfaat dari FastAPI, melihat bagaimana sedikitnya kode yang harus kamu tulis, semua pengecekan tipe, pelengkapan otomatis, dll.
---
## Install FastAPI
Langkah pertama adalah dengan meng-install FastAPI.
Untuk tutorial, kamu mungkin hendak meng-installnya dengan semua pilihan fitur dan dependensinya:
<div class="termy">
```console
$ pip install "fastapi[all]"
---> 100%
```
</div>
...yang juga termasuk `uvicorn`, yang dapat kamu gunakan sebagai server yang menjalankan kodemu.
/// note | Catatan
Kamu juga dapat meng-installnya bagian demi bagian.
Hal ini mungkin yang akan kamu lakukan ketika kamu hendak menyebarkan (men-deploy) aplikasimu ke tahap produksi:
```
pip install fastapi
```
Juga install `uvicorn` untuk menjalankan server"
```
pip install "uvicorn[standard]"
```
Dan demikian juga untuk pilihan dependensi yang hendak kamu gunakan.
///
## Pedoman Pengguna Lanjutan
Tersedia juga **Pedoman Pengguna Lanjutan** yang dapat kamu baca nanti setelah **Tutorial - Pedoman Pengguna** ini.
**Pedoman Pengguna Lanjutan**, dibangun atas hal ini, menggunakan konsep yang sama, dan mengajarkan kepadamu beberapa fitur tambahan.
Tetapi kamu harus membaca terlebih dahulu **Tutorial - Pedoman Pengguna** (apa yang sedang kamu baca sekarang).
Hal ini dirancang supaya kamu dapat membangun aplikasi lengkap dengan hanya **Tutorial - Pedoman Pengguna**, dan kemudian mengembangkannya ke banyak cara yang berbeda, tergantung dari kebutuhanmu, menggunakan beberapa ide-ide tambahan dari **Pedoman Pengguna Lanjutan**.

View File

@@ -1,257 +0,0 @@
# Parameter Path
"parameter" atau "variabel" path didefinisikan dengan sintaksis Python format string:
{* ../../docs_src/path_params/tutorial001.py hl[6:7] *}
Nilai parameter path `item_id` akan dikirim ke fungsi sebagai argument `item_id`:
Jika anda menjalankan contoh berikut dan kunjungi <a href="http://127.0.0.1:8000/items/foo" class="external-link" target="_blank">http://127.0.0.1:8000/items/foo</a>, anda akan melihat respon:
```JSON
{"item_id":"foo"}
```
## Parameter path dengan tipe data
Tipe data parameter path bisa didefinisikan di dalam fungsi, menggunakan anotasi tipe data standar Python:
{* ../../docs_src/path_params/tutorial002.py hl[7] *}
Dalam hal ini `item_id` didefinisikan sebagai `int`.
/// check | Periksa
Penyunting kode anda bisa membantu periksa di dalam fungsi seperti pemeriksaan kesalahan, kelengkapan kode, dll.
///
## <abbr title="juga disebut: serialization, parsing, marshalling">Konversi</abbr> data
Jika contoh berikut dijalankan dan diakses browser melalui <a href="http://127.0.0.1:8000/items/3" class="external-link" target="_blank">http://127.0.0.1:8000/items/3</a>, anda akan melihat respon:
```JSON
{"item_id":3}
```
/// check | Periksa
Perhatikan nilai fungsi yang diterima (dan dihasilkan) adalah `3`, sebagai `int` di Python, dan bukan string `"3"`.
Sehingga dengan deklarasi tipe data **FastAPI** memberikan request otomatis <abbr title="konversi string dari request HTTP menjadi data Python">"parsing"</abbr>.
///
## Validasi Data
Tetapi jika di browser anda akses <a href="http://127.0.0.1:8000/items/foo" class="external-link" target="_blank">http://127.0.0.1:8000/items/foo</a>, anda akan melihat pesan kesalahan 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"
}
]
}
```
Karena parameter path `item_id` bernilai `"foo"` yang bukan tipe data `int`.
Kesalahan yang sama akan muncul jika menggunakan `float` daripada `int`, seperti di: <a href="http://127.0.0.1:8000/items/4.2" class="external-link" target="_blank">http://127.0.0.1:8000/items/4.2</a>
/// check | Periksa
Dengan deklarasi tipe data Python, **FastAPI** melakukan validasi data.
Perhatikan kesalahan tersebut juga menjelaskan validasi apa yang tidak sesuai.
Validasi ini sangat membantu ketika mengembangkan dan men-*debug* kode yang berhubungan dengan API anda.
///
## Dokumentasi
Ketika anda membuka browser di <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>, anda melihat dokumentasi API interaktif otomatis berikut:
<img src="/img/tutorial/path-params/image01.png">
/// check | Periksa
Dengan deklarasi tipe data Python yang sama, **FastAPI** membuat dokumentasi interaktif otomatis (terintegrasi Swagger UI).
Perhatikan parameter path dideklarasikan sebagai integer.
///
## Keuntungan basis-standar, dokumentasi alternatif
Karena skema yang dibuat berasal dari standar <a href="https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md" class="external-link" target="_blank">OpenAPI</a>, maka banyak alat lain yang kompatibel.
Sehingga **FastAPI** menyediakan dokumentasi alternatif (menggunakan ReDoc), yang bisa diakses di <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a>:
<img src="/img/tutorial/path-params/image02.png">
Cara yang sama untuk menggunakan tools kompatibel lainnya. Termasuk alat membuat kode otomatis untuk banyak bahasa.
## Pydantic
Semua validasi data dikerjakan di belakang layar oleh <a href="https://docs.pydantic.dev/" class="external-link" target="_blank">Pydantic</a>, sehingga anda mendapatkan banyak kemudahan. Anda juga tahu proses ini akan ditangani dengan baik.
Anda bisa mendeklarasikan tipe data dengan `str`, `float`, `bool` dan banyak tipe data kompleks lainnya.
Beberapa tipe di atas akan dibahas pada bab berikutnya tutorial ini.
## Urutan berpengaruh
Ketika membuat *operasi path*, anda bisa menghadapi kondisi dimana *path* nya sudah tetap.
Seperti `/users/me`, untuk mendapatkan data user yang sedang aktif.
Kemudian anda bisa memiliki path `/users/{user_id}` untuk mendapatkan data user tertentu melalui user ID.
karena *operasi path* dievaluasi melalui urutan, anda harus memastikan path untuk `/users/me` dideklarasikan sebelum `/user/{user_id}`:
{* ../../docs_src/path_params/tutorial003.py hl[6,11] *}
Sebaliknya, path `/users/{user_id}` juga akan sesuai dengan `/users/me`, "menganggap" menerima parameter `user_id` dengan nilai `"me"`.
Serupa, anda juga tidak bisa mendefinisikan operasi path:
{* ../../docs_src/path_params/tutorial003b.py hl[6,11] *}
Path pertama akan selalu digunakan karena path sesuai dengan yang pertama.
## Nilai terdefinisi
Jika ada *operasi path* yang menerima *parameter path*, tetapi anda ingin nilai valid *parameter path* sudah terdefinisi, anda bisa menggunakan standar Python <abbr title="Enumeration">`Enum`</abbr>.
### Membuat class `Enum`
Import `Enum` dan buat *sub-class* warisan dari `str` dan `Enum`.
Dengan warisan dari `str` dokumen API mengetahui nilai nya harus berjenis `string` supaya bisa digunakan dengan benar.
Kemudian buat atribut *class* dengan nilai tetap *string* yang benar:
{* ../../docs_src/path_params/tutorial005.py hl[1,6:9] *}
/// info
<a href="https://docs.python.org/3/library/enum.html" class="external-link" target="_blank">Enumerasi (atau enum) tersedia di Python</a> sejak versi 3.4.
///
/// tip | Tips
"AlxexNet", "ResNet", dan "LeNet" adalah nama <abbr title="Secara teknis, arsitektur model Deep Learning">model</abbr> *Machine Learning*.
///
### Mendeklarasikan *parameter path*
Kemudian buat *parameter path* dengan tipe anotasi menggunakan *class* enum dari (`ModelName`)
{* ../../docs_src/path_params/tutorial005.py hl[16] *}
### Periksa dokumentasi
Karena nilai yang tersedia untuk *parameter path* telah terdefinisi, dokumen interatik bisa memunculkan:
<img src="/img/tutorial/path-params/image03.png">
### Bekerja dengan *enumarasi* Python
Nilai *parameter path* akan menjadi *anggota enumerasi*.
#### Membandingkan *anggota enumerasi*
Anda bisa membandingkan parameter *path* dengan *anggota enumerasi* di enum `ModelName` yang anda buat:
{* ../../docs_src/path_params/tutorial005.py hl[17] *}
#### Mendapatkan *nilai enumerasi*
Anda bisa mendapatkan nilai (`str` dalam kasus ini) menggunakan `model_name.value`, atau secara umum `anggota_enum_anda.value`:
{* ../../docs_src/path_params/tutorial005.py hl[20] *}
/// tip | Tips
Anda bisa mengakses nilai `"lenet"` dnegan `ModelName.lenet.value`.
///
#### Menghasilkan *anggota enumerasi*
Anda bisa menghasilkan *anggota enumerasi* dari *operasi path* bahkan di body JSON bersarang (contoh `dict`).
They will be converted to their corresponding values (strings in this case) before returning them to the client:
{* ../../docs_src/path_params/tutorial005.py hl[18,21,23] *}
Klien akan mendapatkan respon JSON seperti berikut:
```JSON
{
"model_name": "alexnet",
"message": "Deep Learning FTW!"
}
```
## Parameter path berisi path
Misalkan terdapat *operasi path* dengan path `/files/{file_path}`.
Tetapi anda memerlukan `file_path` itu berisi *path*, seperti like `home/johndoe/myfile.txt`.
Sehingga URL untuk file tersebut akan seperti: `/files/home/johndoe/myfile.txt`.
### Dukungan OpenAPI
OpenAPI tidak bisa mendeklarasikan *parameter path* berisi *path* di dalamnya, karena menyebabkan kondisi yang sulit di*test* dan didefinisikan.
Tetapi, di **FastAPI** anda tetap bisa melakukannya dengan menggunakan *tools* internal dari Starlette.
Dan dokumentasi tetap berfungsi walaupun tidak menambahkan keterangan bahwa parameter harus berisi *path*.
### Konverter path
Melalui Starlette anda bisa mendeklarasikan *parameter path* berisi *path* dengan URL seperti:
```
/files/{file_path:path}
```
Dikondisi ini nama parameter adalah `file_path` dan bagian terakhir `:path` menginformasikan parameter harus sesuai dengan setiap *path*.
Sehingga anda bisa menggunakan:
{* ../../docs_src/path_params/tutorial004.py hl[6] *}
/// tip | Tips
Anda mungkin perlu parameter berisi `/home/johndoe/myfile.txt` di awali garis belakang (`/`).
Di kondisi ini, URL nya menjadi: `/files//home/johndoe/myfile.txt`, dengan dua garis belakang (`//`) di antara `files` dan `home`.
///
## Ringkasan
Di **FastAPI** dengan menggunakan deklarasi tipe Python standar, pendek, intuitif, anda mendapatkan:
* Dukungan editor: pemeriksaan kesalahan, autocompletion, dll.
* "<abbr title="konversi string dari request HTTP menjadi data Python">Parsing</abbr>" data.
* Validasi data.
* Annotasi API dan dokumentasi otomatis.
Semua itu anda hanya perlu mendeklarasikan sekali saja.
Ini adalah salah satu keunggulan **FastAPI** dibandingkan dengan *framework* lainnya (selain dari performa Python *native*c)

View File

@@ -1,40 +0,0 @@
# Berkas Statis
Anda dapat menyajikan berkas statis secara otomatis dari sebuah direktori menggunakan `StaticFiles`.
## Penggunaan `StaticFiles`
* Mengimpor `StaticFiles`.
* "Mount" representatif `StaticFiles()` di jalur spesifik.
{* ../../docs_src/static_files/tutorial001.py hl[2,6] *}
/// note | Detail Teknis
Anda dapat pula menggunakan `from starlette.staticfiles import StaticFiles`.
**FastAPI** menyediakan `starlette.staticfiles` sama seperti `fastapi.staticfiles` sebagai kemudahan pada Anda, yaitu para pengembang. Tetapi ini asli berasal langsung dari Starlette.
///
### Apa itu "Mounting"
"Mounting" dimaksud menambah aplikasi "independen" secara lengkap di jalur spesifik, kemudian menangani seluruh sub-jalur.
Hal ini berbeda dari menggunakan `APIRouter` karena aplikasi yang dimount benar-benar independen. OpenAPI dan dokumentasi dari aplikasi utama Anda tak akan menyertakan apa pun dari aplikasi yang dimount, dst.
Anda dapat mempelajari mengenai ini dalam [Panduan Pengguna Lanjutan](../advanced/index.md){.internal-link target=_blank}.
## Detail
Terhadap `"/static"` pertama mengacu pada sub-jalur yang akan menjadi tempat "sub-aplikasi" ini akan "dimount". Maka, jalur apa pun yang dimulai dengan `"/static"` akan ditangani oleh sub-jalur tersebut.
Terhadap `directory="static"` mengacu pada nama direktori yang berisi berkas statis Anda.
Terhadap `name="static"` ialah nama yang dapat digunakan secara internal oleh **FastAPI**.
Seluruh parameter ini dapat berbeda dari sekadar "`static`", sesuaikan parameter dengan keperluan dan detail spesifik akan aplikasi Anda.
## Info lanjutan
Sebagai detail dan opsi tambahan lihat <a href="https://www.starlette.io/staticfiles/" class="external-link" target="_blank">dokumentasi Starlette perihal Berkas Statis</a>.

View File

@@ -1 +0,0 @@
INHERIT: ../en/mkdocs.yml

View File

@@ -1,463 +0,0 @@
<p align="center">
<a href="https://fastapi.tiangolo.com"><img src="https://fastapi.tiangolo.com/img/logo-margin/logo-teal.png" alt="FastAPI"></a>
</p>
<p align="center">
<em>FastAPI framework, alte prestazioni, facile da imparare, rapido da implementare, pronto per il rilascio in produzione</em>
</p>
<p align="center">
<a href="https://github.com/fastapi/fastapi/actions?query=workflow%3ATest+event%3Apush+branch%3Amaster" target="_blank">
<img src="https://github.com/fastapi/fastapi/actions/workflows/test.yml/badge.svg?event=push&branch=master" alt="Test">
</a>
<a href="https://coverage-badge.samuelcolvin.workers.dev/redirect/fastapi/fastapi" target="_blank">
<img src="https://coverage-badge.samuelcolvin.workers.dev/fastapi/fastapi.svg" alt="Coverage">
</a>
<a href="https://pypi.org/project/fastapi" target="_blank">
<img src="https://img.shields.io/pypi/v/fastapi?color=%2334D058&label=pypi%20package" alt="Package version">
</a>
<a href="https://pypi.org/project/fastapi" target="_blank">
<img src="https://img.shields.io/pypi/pyversions/fastapi.svg?color=%2334D058" alt="Supported Python versions">
</a>
</p>
---
**Documentazione**: <a href="https://fastapi.tiangolo.com" target="_blank">https://fastapi.tiangolo.com</a>
**Codice Sorgente**: <a href="https://github.com/fastapi/fastapi" target="_blank">https://github.com/fastapi/fastapi</a>
---
FastAPI è un web framework moderno e veloce (a prestazioni elevate) che serve a creare API con Python 3.6+ basato sulle annotazioni di tipo di Python.
Le sue caratteristiche principali sono:
* **Velocità**: Prestazioni molto elevate, alla pari di **NodeJS** e **Go** (grazie a Starlette e Pydantic). [Uno dei framework Python più veloci in circolazione](#performance).
* **Veloce da programmare**: Velocizza il lavoro consentendo il rilascio di nuove funzionalità tra il 200% e il 300% più rapidamente. *
* **Meno bug**: Riduce di circa il 40% gli errori che commettono gli sviluppatori durante la scrittura del codice. *
* **Intuitivo**: Grande supporto per gli editor di testo con <abbr title="anche conosciuto come auto-completamento, autocompletion, IntelliSense">autocompletamento</abbr> in ogni dove. In questo modo si può dedicare meno tempo al debugging.
* **Facile**: Progettato per essere facile da usare e imparare. Si riduce il tempo da dedicare alla lettura della documentazione.
* **Sintentico**: Minimizza la duplicazione di codice. Molteplici funzionalità, ognuna con la propria dichiarazione dei parametri. Meno errori.
* **Robusto**: Crea codice pronto per la produzione con documentazione automatica interattiva.
* **Basato sugli standard**: Basato su (e completamente compatibile con) gli open standard per le API: <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank">OpenAPI</a> (precedentemente Swagger) e <a href="https://json-schema.org/" class="external-link" target="_blank">JSON Schema</a>.
<small>* Stima basata sull'esito di test eseguiti su codice sorgente di applicazioni rilasciate in produzione da un team interno di sviluppatori.</small>
## Sponsor
<!-- sponsors -->
{% if sponsors %}
{% for sponsor in sponsors.gold -%}
<a href="{{ sponsor.url }}" target="_blank" title="{{ sponsor.title }}"><img src="{{ sponsor.img }}" style="border-radius:15px"></a>
{% endfor -%}
{%- for sponsor in sponsors.silver -%}
<a href="{{ sponsor.url }}" target="_blank" title="{{ sponsor.title }}"><img src="{{ sponsor.img }}" style="border-radius:15px"></a>
{% endfor %}
{% endif %}
<!-- /sponsors -->
<a href="https://fastapi.tiangolo.com/fastapi-people/#sponsors" class="external-link" target="_blank">Altri sponsor</a>
## Recensioni
"_[...] I'm using **FastAPI** a ton these days. [...] I'm actually planning to use it for all of my team's **ML services at Microsoft**. Some of them are getting integrated into the core **Windows** product and some **Office** products._"
<div style="text-align: right; margin-right: 10%;">Kabir Khan - <strong>Microsoft</strong> <a href="https://github.com/fastapi/fastapi/pull/26" target="_blank"><small>(ref)</small></a></div>
---
"_We adopted the **FastAPI** library to spawn a **REST** server that can be queried to obtain **predictions**. [for Ludwig]_"
<div style="text-align: right; margin-right: 10%;">Piero Molino, Yaroslav Dudin, e Sai Sumanth Miryala - <strong>Uber</strong> <a href="https://eng.uber.com/ludwig-v0-2/" target="_blank"><small>(ref)</small></a></div>
---
"_**Netflix** is pleased to announce the open-source release of our **crisis management** orchestration framework: **Dispatch**! [built with **FastAPI**]_"
<div style="text-align: right; margin-right: 10%;">Kevin Glisson, Marc Vilanova, Forest Monsen - <strong>Netflix</strong> <a href="https://netflixtechblog.com/introducing-dispatch-da4b8a2a8072" target="_blank"><small>(ref)</small></a></div>
---
"_Im over the moon excited about **FastAPI**. Its so fun!_"
<div style="text-align: right; margin-right: 10%;">Brian Okken - <strong><a href="https://pythonbytes.fm/episodes/show/123/time-to-right-the-py-wrongs?time_in_sec=855" target="_blank">Python Bytes</a> podcast host</strong> <a href="https://x.com/brianokken/status/1112220079972728832" target="_blank"><small>(ref)</small></a></div>
---
"_Honestly, what you've built looks super solid and polished. In many ways, it's what I wanted **Hug** to be - it's really inspiring to see someone build that._"
<div style="text-align: right; margin-right: 10%;">Timothy Crosley - <strong><a href="https://github.com/hugapi/hug" target="_blank">Hug</a> creator</strong> <a href="https://news.ycombinator.com/item?id=19455465" target="_blank"><small>(ref)</small></a></div>
---
"_If you're looking to learn one **modern framework** for building REST APIs, check out **FastAPI** [...] It's fast, easy to use and easy to learn [...]_"
"_We've switched over to **FastAPI** for our **APIs** [...] I think you'll like it [...]_"
<div style="text-align: right; margin-right: 10%;">Ines Montani - Matthew Honnibal - <strong><a href="https://explosion.ai" target="_blank">Explosion AI</a> founders - <a href="https://spacy.io" target="_blank">spaCy</a> creators</strong> <a href="https://x.com/_inesmontani/status/1144173225322143744" target="_blank"><small>(ref)</small></a> - <a href="https://x.com/honnibal/status/1144031421859655680" target="_blank"><small>(ref)</small></a></div>
---
## **Typer**, la FastAPI delle CLI
<a href="https://typer.tiangolo.com" target="_blank"><img src="https://typer.tiangolo.com/img/logo-margin/logo-margin-vector.svg" style="width: 20%;"></a>
Se stai sviluppando un'app <abbr title="Command Line Interface (interfaccia della riga di comando)">CLI</abbr> da usare nel terminale invece che una web API, ti consigliamo <a href="https://typer.tiangolo.com/" class="external-link" target="_blank">**Typer**</a>.
**Typer** è il fratello minore di FastAPI. Ed è stato ideato per essere la **FastAPI delle CLI**. ⌨️ 🚀
## Requisiti
Python 3.6+
FastAPI è basata su importanti librerie:
* <a href="https://www.starlette.io/" class="external-link" target="_blank">Starlette</a> per le parti web.
* <a href="https://docs.pydantic.dev/" class="external-link" target="_blank">Pydantic</a> per le parti dei dati.
## Installazione
<div class="termy">
```console
$ pip install fastapi
---> 100%
```
</div>
Per il rilascio in produzione, sarà necessario un server ASGI come <a href="http://www.uvicorn.org" class="external-link" target="_blank">Uvicorn</a> oppure <a href="https://github.com/pgjones/hypercorn" class="external-link" target="_blank">Hypercorn</a>.
<div class="termy">
```console
$ pip install uvicorn[standard]
---> 100%
```
</div>
## Esempio
### Crea un file
* Crea un file `main.py` con:
```Python
from fastapi import FastAPI
from typing import Optional
app = FastAPI()
@app.get("/")
def read_root():
return {"Hello": "World"}
@app.get("/items/{item_id}")
def read_item(item_id: int, q: str = Optional[None]):
return {"item_id": item_id, "q": q}
```
<details markdown="1">
<summary>Oppure usa <code>async def</code>...</summary>
Se il tuo codice usa `async` / `await`, allora usa `async def`:
```Python hl_lines="7 12"
from fastapi import FastAPI
from typing import Optional
app = FastAPI()
@app.get("/")
async def read_root():
return {"Hello": "World"}
@app.get("/items/{item_id}")
async def read_item(item_id: int, q: Optional[str] = None):
return {"item_id": item_id, "q": q}
```
**Nota**:
e vuoi approfondire, consulta la sezione _"In a hurry?"_ su <a href="https://fastapi.tiangolo.com/async/#in-a-hurry" target="_blank">`async` e `await` nella documentazione</a>.
</details>
### Esegui il server
Puoi far partire il server così:
<div class="termy">
```console
$ uvicorn main:app --reload
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.
```
</div>
<details markdown="1">
<summary>Informazioni sul comando <code>uvicorn main:app --reload</code>...</summary>
Vediamo il comando `uvicorn main:app` in dettaglio:
* `main`: il file `main.py` (il "modulo" Python).
* `app`: l'oggetto creato dentro `main.py` con la riga di codice `app = FastAPI()`.
* `--reload`: ricarica il server se vengono rilevati cambiamenti del codice. Usalo solo durante la fase di sviluppo.
</details>
### Testa l'API
Apri il browser all'indirizzo <a href="http://127.0.0.1:8000/items/5?q=somequery" class="external-link" target="_blank">http://127.0.0.1:8000/items/5?q=somequery</a>.
Vedrai la seguente risposta JSON:
```JSON
{"item_id": 5, "q": "somequery"}
```
Hai appena creato un'API che:
* Riceve richieste HTTP sui _paths_ `/` and `/items/{item_id}`.
* Entrambi i _paths_ accettano`GET` <em>operations</em> (conosciuti anche come <abbr title="metodi HTTP">HTTP _methods_</abbr>).
* Il _path_ `/items/{item_id}` ha un _path parameter_ `item_id` che deve essere un `int`.
* Il _path_ `/items/{item_id}` ha una `str` _query parameter_ `q`.
### Documentazione interattiva dell'API
Adesso vai all'indirizzo <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
Vedrai la documentazione interattiva dell'API (offerta da <a href="https://github.com/swagger-api/swagger-ui" class="external-link" target="_blank">Swagger UI</a>):
![Swagger UI](https://fastapi.tiangolo.com/img/index/index-01-swagger-ui-simple.png)
### Documentazione interattiva alternativa
Adesso accedi all'url <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a>.
Vedrai la documentazione interattiva dell'API (offerta da <a href="https://github.com/Rebilly/ReDoc" class="external-link" target="_blank">ReDoc</a>):
![ReDoc](https://fastapi.tiangolo.com/img/index/index-02-redoc-simple.png)
## Esempio più avanzato
Adesso modifica il file `main.py` per ricevere un _body_ da una richiesta `PUT`.
Dichiara il _body_ usando le annotazioni di tipo standard di Python, grazie a Pydantic.
```Python hl_lines="2 7-10 23-25"
from fastapi import FastAPI
from pydantic import BaseModel
from typing import Optional
app = FastAPI()
class Item(BaseModel):
name: str
price: float
is_offer: bool = Optional[None]
@app.get("/")
def read_root():
return {"Hello": "World"}
@app.get("/items/{item_id}")
def read_item(item_id: int, q: Optional[str] = None):
return {"item_id": item_id, "q": q}
@app.put("/items/{item_id}")
def update_item(item_id: int, item: Item):
return {"item_name": item.name, "item_id": item_id}
```
Il server dovrebbe ricaricarsi in automatico (perché hai specificato `--reload` al comando `uvicorn` lanciato precedentemente).
### Aggiornamento della documentazione interattiva
Adesso vai su <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
* La documentazione interattiva dell'API verrà automaticamente aggiornata, includendo il nuovo _body_:
![Swagger UI](https://fastapi.tiangolo.com/img/index/index-03-swagger-02.png)
* Fai click sul pulsante "Try it out", che ti permette di inserire i parametri per interagire direttamente con l'API:
![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-04-swagger-03.png)
* Successivamente, premi sul pulsante "Execute". L'interfaccia utente comunicherà con la tua API, invierà i parametri, riceverà i risultati della richiesta, e li mostrerà sullo schermo:
![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-05-swagger-04.png)
### Aggiornamento della documentazione alternativa
Ora vai su <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a>.
* Anche la documentazione alternativa dell'API mostrerà il nuovo parametro della query e il _body_:
![ReDoc](https://fastapi.tiangolo.com/img/index/index-06-redoc-02.png)
### Riepilogo
Ricapitolando, è sufficiente dichiarare **una sola volta** i tipi dei parametri, del body, ecc. come parametri di funzioni.
Questo con le annotazioni per i tipi standard di Python.
Non c'è bisogno di imparare una nuova sintassi, metodi o classi specifici a una libreria, ecc.
È normalissimo **Python 3.6+**.
Per esempio, per un `int`:
```Python
item_id: int
```
o per un modello `Item` più complesso:
```Python
item: Item
```
...e con quella singola dichiarazione hai in cambio:
* Supporto per gli editor di testo, incluso:
* Autocompletamento.
* Controllo sulle annotazioni di tipo.
* Validazione dei dati:
* Errori chiari e automatici quando i dati sono invalidi.
* Validazione anche per gli oggetti JSON più complessi.
* <abbr title="anche noto come: serializzazione, parsing, marshalling">Conversione</abbr> dei dati di input: da risorse esterne a dati e tipi di Python. È possibile leggere da:
* JSON.
* Path parameters.
* Query parameters.
* Cookies.
* Headers.
* Form.
* File.
* <abbr title="detta anche: serialization, parsing, marshalling">Conversione</abbr> dei dati di output: converte dati e tipi di Python a dati per la rete (come JSON):
* Converte i tipi di Python (`str`, `int`, `float`, `bool`, `list`, ecc).
* Oggetti `datetime`.
* Oggetti `UUID`.
* Modelli del database.
* ...e molto di più.
* Generazione di una documentazione dell'API interattiva, con scelta dell'interfaccia grafica:
* Swagger UI.
* ReDoc.
---
Tornando al precedente esempio, **FastAPI**:
* Validerà che esiste un `item_id` nel percorso delle richieste `GET` e `PUT`.
* Validerà che `item_id` sia di tipo `int` per le richieste `GET` e `PUT`.
* Se non lo è, il client vedrà un errore chiaro e utile.
* Controllerà se ci sia un parametro opzionale chiamato `q` (per esempio `http://127.0.0.1:8000/items/foo?q=somequery`) per le richieste `GET`.
* Siccome il parametro `q` è dichiarato con `= None`, è opzionale.
* Senza il `None` sarebbe stato obbligatorio (come per il body della richiesta `PUT`).
* Per le richieste `PUT` su `/items/{item_id}`, leggerà il body come JSON, questo comprende:
* verifica che la richiesta abbia un attributo obbligatorio `name` e che sia di tipo `str`.
* verifica che la richiesta abbia un attributo obbligatorio `price` e che sia di tipo `float`.
* verifica che la richiesta abbia un attributo opzionale `is_offer` e che sia di tipo `bool`, se presente.
* Tutto questo funzionerebbe anche con oggetti JSON più complessi.
* Convertirà *da* e *a* JSON automaticamente.
* Documenterà tutto con OpenAPI, che può essere usato per:
* Sistemi di documentazione interattivi.
* Sistemi di generazione di codice dal lato client, per molti linguaggi.
* Fornirà 2 interfacce di documentazione dell'API interattive.
---
Questa è solo la punta dell'iceberg, ma dovresti avere già un'idea di come il tutto funzioni.
Prova a cambiare questa riga di codice:
```Python
return {"item_name": item.name, "item_id": item_id}
```
...da:
```Python
... "item_name": item.name ...
```
...a:
```Python
... "item_price": item.price ...
```
...e osserva come il tuo editor di testo autocompleterà gli attributi e sarà in grado di riconoscere i loro tipi:
![editor support](https://fastapi.tiangolo.com/img/vscode-completion.png)
Per un esempio più completo che mostra più funzionalità del framework, consulta <a href="https://fastapi.tiangolo.com/tutorial/">Tutorial - Guida Utente</a>.
**Spoiler alert**: il tutorial - Guida Utente include:
* Dichiarazione di **parameters** da altri posti diversi come: **headers**, **cookies**, **form fields** e **files**.
* Come stabilire **vincoli di validazione** come `maximum_length` o `regex`.
* Un sistema di **<abbr title="detto anche components, resources, providers, services, injectables">Dependency Injection</abbr>** facile da usare e molto potente.
e potente.
* Sicurezza e autenticazione, incluso il supporto per **OAuth2** con **token JWT** e autenticazione **HTTP Basic**.
* Tecniche più avanzate (ma ugualmente semplici) per dichiarare **modelli JSON altamente nidificati** (grazie a Pydantic).
* E altre funzionalità (grazie a Starlette) come:
* **WebSockets**
* **GraphQL**
* test molto facili basati su `requests` e `pytest`
* **CORS**
* **Cookie Sessions**
* ...e altro ancora.
## Prestazioni
Benchmark indipendenti di TechEmpower mostrano che **FastAPI** basato su Uvicorn è <a href="https://www.techempower.com/benchmarks/#section=test&runid=7464e520-0dc2-473d-bd34-dbdfd7e85911&hw=ph&test=query&l=zijzen-7" class="external-link" target="_blank">uno dei framework Python più veloci in circolazione</a>, solamente dietro a Starlette e Uvicorn (usate internamente da FastAPI). (*)
Per approfondire, consulta la sezione <a href="https://fastapi.tiangolo.com/benchmarks/" class="internal-link" target="_blank">Benchmarks</a>.
## Dipendenze opzionali
Usate da Pydantic:
* <a href="https://github.com/JoshData/python-email-validator" target="_blank"><code>email-validator</code></a> - per la validazione di email.
Usate da Starlette:
* <a href="http://docs.python-requests.org" target="_blank"><code>requests</code></a> - Richiesto se vuoi usare il `TestClient`.
* <a href="https://github.com/Tinche/aiofiles" target="_blank"><code>aiofiles</code></a> - Richiesto se vuoi usare `FileResponse` o `StaticFiles`.
* <a href="http://jinja.pocoo.org" target="_blank"><code>jinja2</code></a> - Richiesto se vuoi usare la configurazione template di default.
* <a href="https://github.com/Kludex/python-multipart" target="_blank"><code>python-multipart</code></a> - Richiesto se vuoi supportare il <abbr title="convertire la stringa che proviene da una richiesta HTTP in dati Python">"parsing"</abbr> con `request.form()`.
* <a href="https://pythonhosted.org/itsdangerous/" target="_blank"><code>itsdangerous</code></a> - Richiesto per usare `SessionMiddleware`.
* <a href="https://pyyaml.org/wiki/PyYAMLDocumentation" target="_blank"><code>pyyaml</code></a> - Richiesto per il supporto dello `SchemaGenerator` di Starlette (probabilmente non ti serve con FastAPI).
* <a href="https://graphene-python.org/" target="_blank"><code>graphene</code></a> - Richiesto per il supporto di `GraphQLApp`.
Usate da FastAPI / Starlette:
* <a href="https://www.uvicorn.org" target="_blank"><code>uvicorn</code></a> - per il server che carica e serve la tua applicazione.
* <a href="https://github.com/ijl/orjson" target="_blank"><code>orjson</code></a> - ichiesto se vuoi usare `ORJSONResponse`.
* <a href="https://github.com/esnme/ultrajson" target="_blank"><code>ujson</code></a> - Richiesto se vuoi usare `UJSONResponse`.
Puoi installarle tutte con `pip install fastapi[all]`.
## Licenza
Questo progetto è concesso in licenza in base ai termini della licenza MIT.

View File

@@ -1 +0,0 @@
INHERIT: ../en/mkdocs.yml

View File

@@ -1,298 +0,0 @@
# Omgevingsvariabelen
/// tip
Als je al weet wat "omgevingsvariabelen" zijn en hoe je ze kunt gebruiken, kun je deze stap gerust overslaan.
///
Een omgevingsvariabele (ook bekend als "**env var**") is een variabele die **buiten** de Python-code leeft, in het **besturingssysteem** en die door je Python-code (of door andere programma's) kan worden gelezen.
Omgevingsvariabelen kunnen nuttig zijn voor het bijhouden van applicatie **instellingen**, als onderdeel van de **installatie** van Python, enz.
## Omgevingsvariabelen maken en gebruiken
Je kunt omgevingsvariabelen **maken** en gebruiken in de **shell (terminal)**, zonder dat je Python nodig hebt:
//// tab | Linux, macOS, Windows Bash
<div class="termy">
```console
// Je zou een omgevingsvariabele MY_NAME kunnen maken met
$ export MY_NAME="Wade Wilson"
// Dan zou je deze met andere programma's kunnen gebruiken, zoals
$ echo "Hello $MY_NAME"
Hello Wade Wilson
```
</div>
////
//// tab | Windows PowerShell
<div class="termy">
```console
// Maak een omgevingsvariabel MY_NAME
$ $Env:MY_NAME = "Wade Wilson"
// Gebruik het met andere programma's, zoals
$ echo "Hello $Env:MY_NAME"
Hello Wade Wilson
```
</div>
////
## Omgevingsvariabelen uitlezen in Python
Je kunt omgevingsvariabelen **buiten** Python aanmaken, in de terminal (of met een andere methode) en ze vervolgens **in Python uitlezen**.
Je kunt bijvoorbeeld een bestand `main.py` hebben met:
```Python hl_lines="3"
import os
name = os.getenv("MY_NAME", "World")
print(f"Hello {name} from Python")
```
/// tip
Het tweede argument van <a href="https://docs.python.org/3.8/library/os.html#os.getenv" class="external-link" target="_blank">`os.getenv()`</a> is de standaardwaarde die wordt geretourneerd.
Als je dit niet meegeeft, is de standaardwaarde `None`. In dit geval gebruiken we standaard `"World"`.
///
Dan zou je dat Python-programma kunnen aanroepen:
//// tab | Linux, macOS, Windows Bash
<div class="termy">
```console
// Hier stellen we de omgevingsvariabelen nog niet in
$ python main.py
// Omdat we de omgevingsvariabelen niet hebben ingesteld, krijgen we de standaardwaarde
Hello World from Python
// Maar als we eerst een omgevingsvariabele aanmaken
$ export MY_NAME="Wade Wilson"
// en het programma dan opnieuw aanroepen
$ python main.py
// kan het de omgevingsvariabele nu wel uitlezen
Hello Wade Wilson from Python
```
</div>
////
//// tab | Windows PowerShell
<div class="termy">
```console
// Hier stellen we de omgevingsvariabelen nog niet in
$ python main.py
// Omdat we de omgevingsvariabelen niet hebben ingesteld, krijgen we de standaardwaarde
Hello World from Python
// Maar als we eerst een omgevingsvariabele aanmaken
$ $Env:MY_NAME = "Wade Wilson"
// en het programma dan opnieuw aanroepen
$ python main.py
// kan het de omgevingsvariabele nu wel uitlezen
Hello Wade Wilson from Python
```
</div>
////
Omdat omgevingsvariabelen buiten de code kunnen worden ingesteld, maar wel door de code kunnen worden gelezen en niet hoeven te worden opgeslagen (gecommit naar `git`) met de rest van de bestanden, worden ze vaak gebruikt voor configuraties of **instellingen**.
Je kunt ook een omgevingsvariabele maken die alleen voor een **specifieke programma-aanroep** beschikbaar is, die alleen voor dat programma beschikbaar is en alleen voor de duur van dat programma.
Om dat te doen, maak je het vlak voor het programma zelf aan, op dezelfde regel:
<div class="termy">
```console
// Maak een omgevingsvariabele MY_NAME in de regel voor deze programma-aanroep
$ MY_NAME="Wade Wilson" python main.py
// Nu kan het de omgevingsvariabele lezen
Hello Wade Wilson from Python
// De omgevingsvariabelen bestaan daarna niet meer
$ python main.py
Hello World from Python
```
</div>
/// tip
Je kunt er meer over lezen op <a href="https://12factor.net/config" class="external-link" target="_blank">The Twelve-Factor App: Config</a>.
///
## Types en Validatie
Deze omgevingsvariabelen kunnen alleen **tekstuele gegevens** verwerken, omdat ze extern zijn aan Python, compatibel moeten zijn met andere programma's en de rest van het systeem (zelfs met verschillende besturingssystemen, zoals Linux, Windows en macOS).
Dat betekent dat **elke waarde** die in Python uit een omgevingsvariabele wordt gelezen **een `str` zal zijn** en dat elke conversie naar een ander type of elke validatie in de code moet worden uitgevoerd.
Meer informatie over het gebruik van omgevingsvariabelen voor het verwerken van **applicatie instellingen** vind je in de [Geavanceerde gebruikershandleiding - Instellingen en Omgevingsvariabelen](./advanced/settings.md){.internal-link target=_blank}.
## `PATH` Omgevingsvariabele
Er is een **speciale** omgevingsvariabele met de naam **`PATH`**, die door de besturingssystemen (Linux, macOS, Windows) wordt gebruikt om programma's te vinden die uitgevoerd kunnen worden.
De waarde van de variabele `PATH` is een lange string die bestaat uit mappen die gescheiden worden door een dubbele punt `:` op Linux en macOS en door een puntkomma `;` op Windows.
De omgevingsvariabele `PATH` zou er bijvoorbeeld zo uit kunnen zien:
//// tab | Linux, macOS
```plaintext
/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
```
Dit betekent dat het systeem naar programma's zoekt in de mappen:
* `/usr/local/bin`
* `/usr/bin`
* `/bin`
* `/usr/sbin`
* `/sbin`
////
//// tab | Windows
```plaintext
C:\Program Files\Python312\Scripts;C:\Program Files\Python312;C:\Windows\System32
```
Dit betekent dat het systeem naar programma's zoekt in de mappen:
* `C:\Program Files\Python312\Scripts`
* `C:\Program Files\Python312`
* `C:\Windows\System32`
////
Wanneer je een **opdracht** in de terminal typt, **zoekt** het besturingssysteem naar het programma in **elk van de mappen** die vermeld staan in de omgevingsvariabele `PATH`.
Wanneer je bijvoorbeeld `python` in de terminal typt, zoekt het besturingssysteem naar een programma met de naam `python` in de **eerste map** in die lijst.
Zodra het gevonden wordt, zal het dat programma **gebruiken**. Anders blijft het in de **andere mappen** zoeken.
### Python installeren en `PATH` bijwerken
Wanneer je Python installeert, word je mogelijk gevraagd of je de omgevingsvariabele `PATH` wilt bijwerken.
//// tab | Linux, macOS
Stel dat je Python installeert en het komt terecht in de map `/opt/custompython/bin`.
Als je kiest om de `PATH` omgevingsvariabele bij te werken, zal het installatieprogramma `/opt/custompython/bin` toevoegen aan de `PATH` omgevingsvariabele.
Dit zou er zo uit kunnen zien:
```plaintext
/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/custompython/bin
```
Op deze manier zal het systeem, wanneer je `python` in de terminal typt, het Python-programma in `/opt/custompython/bin` (de laatste map) vinden en dat gebruiken.
////
//// tab | Windows
Stel dat je Python installeert en het komt terecht in de map `C:\opt\custompython\bin`.
Als je kiest om de `PATH` omgevingsvariabele bij te werken, zal het installatieprogramma `C:\opt\custompython\bin` toevoegen aan de `PATH` omgevingsvariabele.
```plaintext
C:\Program Files\Python312\Scripts;C:\Program Files\Python312;C:\Windows\System32;C:\opt\custompython\bin
```
Op deze manier zal het systeem, wanneer je `python` in de terminal typt, het Python-programma in `C:\opt\custompython\bin` (de laatste map) vinden en dat gebruiken.
////
Dus als je typt:
<div class="termy">
```console
$ python
```
</div>
//// tab | Linux, macOS
Zal het systeem het `python`-programma in `/opt/custompython/bin` **vinden** en uitvoeren.
Het zou ongeveer hetzelfde zijn als het typen van:
<div class="termy">
```console
$ /opt/custompython/bin/python
```
</div>
////
//// tab | Windows
Zal het systeem het `python`-programma in `C:\opt\custompython\bin\python` **vinden** en uitvoeren.
Het zou ongeveer hetzelfde zijn als het typen van:
<div class="termy">
```console
$ C:\opt\custompython\bin\python
```
</div>
////
Deze informatie is handig wanneer je meer wilt weten over [virtuele omgevingen](virtual-environments.md){.internal-link target=_blank}.
## Conclusion
Hiermee heb je basiskennis van wat **omgevingsvariabelen** zijn en hoe je ze in Python kunt gebruiken.
Je kunt er ook meer over lezen op de <a href="https://en.wikipedia.org/wiki/Environment_variable" class="external-link" target="_blank">Wikipedia over omgevingsvariabelen</a>.
In veel gevallen is het niet direct duidelijk hoe omgevingsvariabelen nuttig zijn en hoe je ze moet toepassen. Maar ze blijven in veel verschillende scenario's opduiken als je aan het ontwikkelen bent, dus het is goed om er meer over te weten.
Je hebt deze informatie bijvoorbeeld nodig in de volgende sectie, over [Virtuele Omgevingen](virtual-environments.md).

View File

@@ -1,201 +0,0 @@
# Functionaliteit
## FastAPI functionaliteit
**FastAPI** biedt je het volgende:
### Gebaseerd op open standaarden
* <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank"><strong>OpenAPI</strong></a> voor het maken van API's, inclusief declaraties van <abbr title="ook bekend als: endpoints, routess">pad</abbr><abbr title="ook bekend als HTTP-methoden, zoals POST, GET, PUT, DELETE">bewerkingen</abbr>, parameters, request bodies, beveiliging, enz.
* Automatische datamodel documentatie met <a href="https://json-schema.org/" class="external-link" target="_blank"><strong>JSON Schema</strong></a> (aangezien OpenAPI zelf is gebaseerd op JSON Schema).
* Ontworpen op basis van deze standaarden, na zorgvuldig onderzoek. In plaats van achteraf deze laag er bovenop te bouwen.
* Dit maakt het ook mogelijk om automatisch **clientcode te genereren** in verschillende programmeertalen.
### Automatische documentatie
Interactieve API-documentatie en verkenning van webgebruikersinterfaces. Aangezien dit framework is gebaseerd op OpenAPI, zijn er meerdere documentatie opties mogelijk, waarvan er standaard 2 zijn inbegrepen.
* <a href="https://github.com/swagger-api/swagger-ui" class="external-link" target="_blank"><strong>Swagger UI</strong></a>, met interactieve interface, maakt het mogelijk je API rechtstreeks vanuit de browser aan te roepen en te testen.
![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-03-swagger-02.png)
* Alternatieve API-documentatie met <a href="https://github.com/Rebilly/ReDoc" class="external-link" target="_blank"><strong>ReDoc</strong></a>.
![ReDoc](https://fastapi.tiangolo.com/img/index/index-06-redoc-02.png)
### Gewoon Moderne Python
Het is allemaal gebaseerd op standaard **Python type** declaraties (dankzij Pydantic). Je hoeft dus geen nieuwe syntax te leren. Het is gewoon standaard moderne Python.
Als je een opfriscursus van 2 minuten nodig hebt over het gebruik van Python types (zelfs als je FastAPI niet gebruikt), bekijk dan deze korte tutorial: [Python Types](python-types.md){.internal-link target=_blank}.
Je schrijft gewoon standaard Python met types:
```Python
from datetime import date
from pydantic import BaseModel
# Declareer een variabele als een str
# en krijg editorondersteuning in de functie
def main(user_id: str):
return user_id
# Een Pydantic model
class User(BaseModel):
id: int
name: str
joined: date
```
Vervolgens kan je het op deze manier gebruiken:
```Python
my_user: User = User(id=3, name="John Doe", joined="2018-07-19")
second_user_data = {
"id": 4,
"name": "Mary",
"joined": "2018-11-30",
}
my_second_user: User = User(**second_user_data)
```
/// info
`**second_user_data` betekent:
Geef de sleutels (keys) en waarden (values) van de `second_user_data` dict direct door als sleutel-waarden argumenten, gelijk aan: `User(id=4, name=“Mary”, joined=“2018-11-30”)`
///
### Editor-ondersteuning
Het gehele framework is ontworpen om eenvoudig en intuïtief te zijn in gebruik. Alle beslissingen zijn getest op meerdere code-editors nog voordat het daadwerkelijke ontwikkelen begon, om zo de beste ontwikkelervaring te garanderen.
Uit enquêtes onder Python ontwikkelaars blijkt maar al te duidelijk dat "(automatische) code aanvulling" <a href="https://www.jetbrains.com/research/python-developers-survey-2017/#tools-and-features" class="external-link" target="_blank">een van de meest gebruikte functionaliteiten is</a>.
Het hele **FastAPI** framework is daarop gebaseerd. Automatische code aanvulling werkt overal.
Je hoeft zelden terug te vallen op de documentatie.
Zo kan je editor je helpen:
* in <a href="https://code.visualstudio.com/" class="external-link" target="_blank">Visual Studio Code</a>:
![editor ondersteuning](https://fastapi.tiangolo.com/img/vscode-completion.png)
* in <a href="https://www.jetbrains.com/pycharm/" class="external-link" target="_blank">PyCharm</a>:
![editor ondersteuning](https://fastapi.tiangolo.com/img/pycharm-completion.png)
Je krijgt autocomletion die je voorheen misschien zelfs voor onmogelijk had gehouden. Zoals bijvoorbeeld de `price` key in een JSON body (die genest had kunnen zijn) die afkomstig is van een request.
Je hoeft niet langer de verkeerde keys in te typen, op en neer te gaan tussen de documentatie, of heen en weer te scrollen om te checken of je `username` of toch `user_name` had gebruikt.
### Kort
Dit framework heeft voor alles verstandige **standaardinstellingen**, met overal optionele configuraties. Alle parameters kunnen worden verfijnd zodat het past bij wat je nodig hebt, om zo de API te kunnen definiëren die jij nodig hebt.
Maar standaard werkt alles **“gewoon”**.
### Validatie
* Validatie voor de meeste (of misschien wel alle?) Python **datatypes**, inclusief:
* JSON objecten (`dict`).
* JSON array (`list`) die itemtypes definiëren.
* String (`str`) velden, die min en max lengtes hebben.
* Getallen (`int`, `float`) met min en max waarden, enz.
* Validatie voor meer exotische typen, zoals:
* URL.
* E-mail.
* UUID.
* ...en anderen.
Alle validatie wordt uitgevoerd door het beproefde en robuuste **Pydantic**.
### Beveiliging en authenticatie
Beveiliging en authenticatie is geïntegreerd. Zonder compromissen te doen naar databases of datamodellen.
Alle beveiligingsschema's gedefinieerd in OpenAPI, inclusief:
* HTTP Basic.
* **OAuth2** (ook met **JWT tokens**). Bekijk de tutorial over [OAuth2 with JWT](tutorial/security/oauth2-jwt.md){.internal-link target=_blank}.
* API keys in:
* Headers.
* Query parameters.
* Cookies, enz.
Plus alle beveiligingsfuncties van Starlette (inclusief **sessiecookies**).
Gebouwd als een herbruikbare tool met componenten die makkelijk te integreren zijn in en met je systemen, datastores, relationele en NoSQL databases, enz.
### Dependency Injection
FastAPI bevat een uiterst eenvoudig, maar uiterst krachtig <abbr title='ook bekend als "componenten", "bronnen", "diensten", "aanbieders"'><strong>Dependency Injection</strong></abbr> systeem.
* Zelfs dependencies kunnen dependencies hebben, waardoor een hiërarchie of **“graph” van dependencies** ontstaat.
* Allemaal **automatisch afgehandeld** door het framework.
* Alle dependencies kunnen data nodig hebben van request, de vereiste **padoperaties veranderen** en automatische documentatie verstrekken.
* **Automatische validatie** zelfs voor *padoperatie* parameters gedefinieerd in dependencies.
* Ondersteuning voor complexe gebruikersauthenticatiesystemen, **databaseverbindingen**, enz.
* **Geen compromisen** met databases, gebruikersinterfaces, enz. Maar eenvoudige integratie met ze allemaal.
### Ongelimiteerde "plug-ins"
Of anders gezegd, je hebt ze niet nodig, importeer en gebruik de code die je nodig hebt.
Elke integratie is ontworpen om eenvoudig te gebruiken (met afhankelijkheden), zodat je een “plug-in" kunt maken in 2 regels code, met dezelfde structuur en syntax die wordt gebruikt voor je *padbewerkingen*.
### Getest
* 100% <abbr title="De hoeveelheid code die automatisch wordt getest">van de code is getest</abbr>.
* 100% <abbr title="Python type annotaties, hiermee kunnen je editor en externe tools je beter ondersteunen">type geannoteerde</abbr> codebase.
* Wordt gebruikt in productietoepassingen.
## Starlette functies
**FastAPI** is volledig verenigbaar met (en gebaseerd op) <a href="https://www.starlette.io/" class="external-link" target="_blank"><strong>Starlette</strong></a>.
`FastAPI` is eigenlijk een subklasse van `Starlette`. Dus als je Starlette al kent of gebruikt, zal de meeste functionaliteit op dezelfde manier werken.
Met **FastAPI** krijg je alle functies van **Starlette** (FastAPI is gewoon Starlette op steroïden):
* Zeer indrukwekkende prestaties. Het is <a href="https://github.com/encode/starlette#performance" class="external-link" target="_blank">een van de snelste Python frameworks, vergelijkbaar met **NodeJS** en **Go**</a>.
* **WebSocket** ondersteuning.
* Taken in de achtergrond tijdens het proces.
* Opstart- en afsluit events.
* Test client gebouwd op HTTPX.
* **CORS**, GZip, Statische bestanden, Streaming reacties.
* **Sessie en Cookie** ondersteuning.
* 100% van de code is getest.
* 100% type geannoteerde codebase.
## Pydantic functionaliteit
**FastAPI** is volledig verenigbaar met (en gebaseerd op) Pydantic. Dus alle extra <a href="https://docs.pydantic.dev/" class="external-link" target="_blank"><strong>Pydantic</strong></a> code die je nog hebt werkt ook.
Inclusief externe pakketten die ook gebaseerd zijn op Pydantic, zoals <abbr title="Object-Relational Mapper">ORM</abbr>s, <abbr title="Object-Document Mapper">ODM</abbr>s voor databases.
Dit betekent ook dat je in veel gevallen het object dat je van een request krijgt **direct naar je database** kunt sturen, omdat alles automatisch wordt gevalideerd.
Hetzelfde geldt ook andersom, in veel gevallen kun je dus het object dat je krijgt van de database **direct doorgeven aan de client**.
Met **FastAPI** krijg je alle functionaliteit van **Pydantic** (omdat FastAPI is gebaseerd op Pydantic voor alle dataverwerking):
* **Geen brainfucks**:
* Je hoeft geen nieuwe microtaal voor schemadefinities te leren.
* Als je bekend bent Python types, weet je hoe je Pydantic moet gebruiken.
* Werkt goed samen met je **<abbr title=“Integrated Development Environment, vergelijkbaar met een code editor”>IDE</abbr>/<abbr title=“Een programma dat controleert op fouten in de code”>linter</abbr>/hersenen**:
* Doordat pydantic's datastructuren enkel instanties zijn van klassen, die je definieert, werkt automatische aanvulling, linting, mypy en je intuïtie allemaal goed met je gevalideerde data.
* Valideer **complexe structuren**:
* Gebruik van hiërarchische Pydantic modellen, Python `typing`'s `List` en `Dict`, enz.
* Met validators kunnen complexe dataschema's duidelijk en eenvoudig worden gedefinieerd, gecontroleerd en gedocumenteerd als JSON Schema.
* Je kunt diep **geneste JSON** objecten laten valideren en annoteren.
* **Uitbreidbaar**:
* Met Pydantic kunnen op maat gemaakte datatypen worden gedefinieerd of je kunt validatie uitbreiden met methoden op een model dat is ingericht met de decorator validator.
* 100% van de code is getest.

View File

@@ -1,494 +0,0 @@
# FastAPI
<style>
.md-content .md-typeset h1 { display: none; }
</style>
<p align="center">
<a href="https://fastapi.tiangolo.com"><img src="https://fastapi.tiangolo.com/img/logo-margin/logo-teal.png" alt="FastAPI"></a>
</p>
<p align="center">
<em>FastAPI framework, zeer goede prestaties, eenvoudig te leren, snel te programmeren, klaar voor productie</em>
</p>
<p align="center">
<a href="https://github.com/fastapi/fastapi/actions?query=workflow%3ATest+event%3Apush+branch%3Amaster" target="_blank">
<img src="https://github.com/fastapi/fastapi/actions/workflows/test.yml/badge.svg?event=push&branch=master" alt="Test">
</a>
<a href="https://coverage-badge.samuelcolvin.workers.dev/redirect/fastapi/fastapi" target="_blank">
<img src="https://coverage-badge.samuelcolvin.workers.dev/fastapi/fastapi.svg" alt="Coverage">
</a>
<a href="https://pypi.org/project/fastapi" target="_blank">
<img src="https://img.shields.io/pypi/v/fastapi?color=%2334D058&label=pypi%20package" alt="Package version">
</a>
<a href="https://pypi.org/project/fastapi" target="_blank">
<img src="https://img.shields.io/pypi/pyversions/fastapi.svg?color=%2334D058" alt="Supported Python versions">
</a>
</p>
---
**Documentatie**: <a href="https://fastapi.tiangolo.com" target="_blank">https://fastapi.tiangolo.com</a>
**Broncode**: <a href="https://github.com/fastapi/fastapi" target="_blank">https://github.com/tiangolo/fastapi</a>
---
FastAPI is een modern, snel (zeer goede prestaties), web framework voor het bouwen van API's in Python, gebruikmakend van standaard Python type-hints.
De belangrijkste kenmerken zijn:
* **Snel**: Zeer goede prestaties, vergelijkbaar met **NodeJS** en **Go** (dankzij Starlette en Pydantic). [Een van de snelste beschikbare Python frameworks](#prestaties).
* **Snel te programmeren**: Verhoog de snelheid om functionaliteit te ontwikkelen met ongeveer 200% tot 300%. *
* **Minder bugs**: Verminder ongeveer 40% van de door mensen (ontwikkelaars) veroorzaakte fouten. *
* **Intuïtief**: Buitengewoon goede ondersteuning voor editors. <abbr title="ook bekend als automatisch aanvullen, automatisch aanvullen, IntelliSense">Overal automische code aanvulling</abbr>. Minder tijd kwijt aan debuggen.
* **Eenvoudig**: Ontworpen om gemakkelijk te gebruiken en te leren. Minder tijd nodig om documentatie te lezen.
* **Kort**: Minimaliseer codeduplicatie. Elke parameterdeclaratie ondersteunt meerdere functionaliteiten. Minder bugs.
* **Robust**: Code gereed voor productie. Met automatische interactieve documentatie.
* **Standards-based**: Gebaseerd op (en volledig verenigbaar met) open standaarden voor API's: <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank">OpenAPI</a> (voorheen bekend als Swagger) en <a href="https://json-schema.org/" class="external-link" target="_blank">JSON Schema</a>.
<small>* schatting op basis van testen met een intern ontwikkelteam en bouwen van productieapplicaties.</small>
## Sponsors
<!-- sponsors -->
{% if sponsors %}
{% for sponsor in sponsors.gold -%}
<a href="{{ sponsor.url }}" target="_blank" title="{{ sponsor.title }}"><img src="{{ sponsor.img }}" style="border-radius:15px"></a>
{% endfor -%}
{%- for sponsor in sponsors.silver -%}
<a href="{{ sponsor.url }}" target="_blank" title="{{ sponsor.title }}"><img src="{{ sponsor.img }}" style="border-radius:15px"></a>
{% endfor %}
{% endif %}
<!-- /sponsors -->
<a href="https://fastapi.tiangolo.com/fastapi-people/#sponsors" class="external-link" target="_blank">Overige sponsoren</a>
## Meningen
"_[...] Ik gebruik **FastAPI** heel vaak tegenwoordig. [...] Ik ben van plan om het te gebruiken voor alle **ML-services van mijn team bij Microsoft**. Sommige van deze worden geïntegreerd in het kernproduct van **Windows** en sommige **Office**-producten._"
<div style="text-align: right; margin-right: 10%;">Kabir Khan - <strong>Microsoft</strong> <a href="https://github.com/fastapi/fastapi/pull/26" target="_blank"><small>(ref)</small></a></div>
---
"_We hebben de **FastAPI** library gebruikt om een **REST** server te maken die bevraagd kan worden om **voorspellingen** te maken. [voor Ludwig]_"
<div style="text-align: right; margin-right: 10%;">Piero Molino, Yaroslav Dudin en Sai Sumanth Miryala - <strong>Uber</strong> <a href="https://eng.uber.com/ludwig-v0-2/" target="_blank"><small>(ref)</small></a></div>
---
"_**Netflix** is verheugd om een open-source release aan te kondigen van ons **crisismanagement**-orkestratieframework: **Dispatch**! [gebouwd met **FastAPI**]_"
<div style="text-align: right; margin-right: 10%;">Kevin Glisson, Marc Vilanova, Forest Monsen - <strong>Netflix</strong> <a href="https://netflixtechblog.com/introducing-dispatch-da4b8a2a8072" target="_blank"><small>(ref)</small></a></div>
---
"_Ik ben super enthousiast over **FastAPI**. Het is zo leuk!_"
<div style="text-align: right; margin-right: 10%;">Brian Okken - <strong><a href="https://pythonbytes.fm/episodes/show/123/time-to-right-the-py-wrongs?time_in_sec=855" target="_blank">Python Bytes</a> podcast presentator</strong> <a href="https://x.com/brianokken/status/1112220079972728832" target="_blank"><small>(ref)</small></a></div>
---
"_Wat je hebt gebouwd ziet er echt super solide en gepolijst uit. In veel opzichten is het wat ik wilde dat **Hug** kon zijn - het is echt inspirerend om iemand dit te zien bouwen._"
<div style="text-align: right; margin-right: 10%;">Timothy Crosley - <strong><a href="https://github.com/hugapi/hug" target="_blank">Hug</a> creator</strong> <a href="https://news.ycombinator.com/item?id=19455465" target="_blank"><small>(ref)</small></a></div>
---
"Wie geïnteresseerd is in een **modern framework** voor het bouwen van REST API's, bekijkt best eens **FastAPI** [...] Het is snel, gebruiksvriendelijk en gemakkelijk te leren [...]_"
"_We zijn overgestapt naar **FastAPI** voor onze **API's** [...] Het gaat jou vast ook bevallen [...]_"
<div style="text-align: right; margin-right: 10%;">Ines Montani - Matthew Honnibal - <strong><a href="https://explosion.ai" target="_blank">Explosion AI</a> oprichters - <a href="https://spacy.io" target="_blank">spaCy</a> ontwikkelaars</strong> <a href="https://x.com/_inesmontani/status/1144173225322143744" target="_blank"><small>(ref)</small></a> - <a href="https://x.com/honnibal/status/1144031421859655680" target="_blank"><small>(ref)</small></a></div>
---
"_Wie een Python API wil bouwen voor productie, kan ik ten stelligste **FastAPI** aanraden. Het is **prachtig ontworpen**, **eenvoudig te gebruiken** en **gemakkelijk schaalbaar**, het is een **cruciale component** geworden in onze strategie om API's centraal te zetten, en het vereenvoudigt automatisering en diensten zoals onze Virtual TAC Engineer._"
<div style="text-align: right; margin-right: 10%;">Deon Pillsbury - <strong>Cisco</strong> <a href="https://www.linkedin.com/posts/deonpillsbury_cisco-cx-python-activity-6963242628536487936-trAp/" target="_blank"><small>(ref)</small></a></div>
---
## **Typer**, de FastAPI van CLIs
<a href="https://typer.tiangolo.com" target="_blank"><img src="https://typer.tiangolo.com/img/logo-margin/logo-margin-vector.svg" style="width: 20%;"></a>
Als je een <abbr title="Command Line Interface">CLI</abbr>-app bouwt die in de terminal moet worden gebruikt in plaats van een web-API, gebruik dan <a href="https://typer.tiangolo.com/ " class="external-link" target="_blank">**Typer**</a>.
**Typer** is het kleine broertje van FastAPI. En het is bedoeld als de **FastAPI van CLI's**.
## Vereisten
FastAPI staat op de schouders van reuzen:
* <a href="https://www.starlette.io/" class="external-link" target="_blank">Starlette</a> voor de webonderdelen.
* <a href="https://docs.pydantic.dev/" class="external-link" target="_blank">Pydantic</a> voor de datadelen.
## Installatie
<div class="termy">
```console
$ pip install "fastapi[standard]"
---> 100%
```
</div>
**Opmerking**: Zet `"fastapi[standard]"` tussen aanhalingstekens om ervoor te zorgen dat het werkt in alle terminals.
## Voorbeeld
### Creëer het
* Maak het bestand `main.py` aan met daarin:
```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}
```
<details markdown="1">
<summary>Of maak gebruik van <code>async def</code>...</summary>
Als je code gebruik maakt van `async` / `await`, gebruik dan `async def`:
```Python hl_lines="9 14"
from typing import Union
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
async def read_root():
return {"Hello": "World"}
@app.get("/items/{item_id}")
async def read_item(item_id: int, q: Union[str, None] = None):
return {"item_id": item_id, "q": q}
```
**Opmerking**:
Als je het niet weet, kijk dan in het gedeelte _"Heb je haast?"_ over <a href="https://fastapi.tiangolo.com/async/#in-a-hurry" target="_blank">`async` en `await` in de documentatie</a>.
</details>
### Voer het uit
Run de server met:
<div class="termy">
```console
$ 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 [2248755] using WatchFiles
INFO: Started server process [2248757]
INFO: Waiting for application startup.
INFO: Application startup complete.
```
</div>
<details markdown="1">
<summary>Over het commando <code>fastapi dev main.py</code>...</summary>
Het commando `fastapi dev` leest het `main.py` bestand, detecteert de **FastAPI** app, en start een server met <a href="https://www.uvicorn.org" class="external-link" target="_blank">Uvicorn</a>.
Standaard zal dit commando `fastapi dev` starten met "auto-reload" geactiveerd voor ontwikkeling op het lokale systeem.
Je kan hier meer over lezen in de <a href="https://fastapi.tiangolo.com/fastapi-cli/" target="_blank">FastAPI CLI documentatie</a>.
</details>
### Controleer het
Open je browser op <a href="http://127.0.0.1:8000/items/5?q=somequery" class="external-link" target="_blank">http://127.0.0.1:8000/items/5?q=somequery</a>.
Je zult een JSON response zien:
```JSON
{"item_id": 5, "q": "somequery"}
```
Je hebt een API gemaakt die:
* HTTP verzoeken kan ontvangen op de _paden_ `/` en `/items/{item_id}`.
* Beide _paden_ hebben `GET` <em>operaties</em> (ook bekend als HTTP _methoden_).
* Het _pad_ `/items/{item_id}` heeft een _pad parameter_ `item_id` dat een `int` moet zijn.
* Het _pad_ `/items/{item_id}` heeft een optionele `str` _query parameter_ `q`.
### Interactieve API documentatie
Ga naar <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
Je ziet de automatische interactieve API documentatie (verstrekt door <a href="https://github.com/swagger-api/swagger-ui" class="external-link" target="_blank">Swagger UI</a>):
![Swagger UI](https://fastapi.tiangolo.com/img/index/index-01-swagger-ui-simple.png)
### Alternatieve API documentatie
Ga vervolgens naar <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a>.
Je ziet de automatische interactieve API documentatie (verstrekt door <a href="https://github.com/Rebilly/ReDoc" class="external-link" target="_blank">ReDoc</a>):
![ReDoc](https://fastapi.tiangolo.com/img/index/index-02-redoc-simple.png)
## Voorbeeld upgrade
Pas nu het bestand `main.py` aan om de body van een `PUT` request te ontvangen.
Dankzij Pydantic kunnen we de body declareren met standaard Python types.
```Python hl_lines="4 9-12 25-27"
from typing import Union
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
price: float
is_offer: Union[bool, None] = None
@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}
@app.put("/items/{item_id}")
def update_item(item_id: int, item: Item):
return {"item_name": item.name, "item_id": item_id}
```
De `fastapi dev` server zou automatisch moeten herladen.
### Interactieve API documentatie upgrade
Ga nu naar <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
* De interactieve API-documentatie wordt automatisch bijgewerkt, inclusief de nieuwe body:
![Swagger UI](https://fastapi.tiangolo.com/img/index/index-03-swagger-02.png)
* Klik op de knop "Try it out", hiermee kan je de parameters invullen en direct met de API interacteren:
![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-04-swagger-03.png)
* Klik vervolgens op de knop "Execute", de gebruikersinterface zal communiceren met jouw API, de parameters verzenden, de resultaten ophalen en deze op het scherm tonen:
![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-05-swagger-04.png)
### Alternatieve API documentatie upgrade
Ga vervolgens naar <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a>.
* De alternatieve documentatie zal ook de nieuwe queryparameter en body weergeven:
![ReDoc](https://fastapi.tiangolo.com/img/index/index-06-redoc-02.png)
### Samenvatting
Samengevat declareer je **eenmalig** de types van parameters, body, etc. als functieparameters.
Dat doe je met standaard moderne Python types.
Je hoeft geen nieuwe syntax te leren, de methods of klassen van een specifieke bibliotheek, etc.
Gewoon standaard **Python**.
Bijvoorbeeld, voor een `int`:
```Python
item_id: int
```
of voor een complexer `Item` model:
```Python
item: Item
```
...en met die ene verklaring krijg je:
* Editor ondersteuning, inclusief:
* Code aanvulling.
* Type validatie.
* Validatie van data:
* Automatische en duidelijke foutboodschappen wanneer de data ongeldig is.
* Validatie zelfs voor diep geneste JSON objecten.
* <abbr title="ook bekend als: serialisatie, parsing, marshalling">Conversie</abbr> van invoergegevens: afkomstig van het netwerk naar Python-data en -types. Zoals:
* JSON.
* Pad parameters.
* Query parameters.
* Cookies.
* Headers.
* Formulieren.
* Bestanden.
* <abbr title="ook bekend als: serialisatie, parsing, marshalling">Conversie</abbr> van uitvoergegevens: converstie van Python-data en -types naar netwerkgegevens (zoals JSON):
* Converteer Python types (`str`, `int`, `float`, `bool`, `list`, etc).
* `datetime` objecten.
* `UUID` objecten.
* Database modellen.
* ...en nog veel meer.
* Automatische interactieve API-documentatie, inclusief 2 alternatieve gebruikersinterfaces:
* Swagger UI.
* ReDoc.
---
Terugkomend op het vorige code voorbeeld, **FastAPI** zal:
* Valideren dat er een `item_id` bestaat in het pad voor `GET` en `PUT` verzoeken.
* Valideren dat het `item_id` van het type `int` is voor `GET` en `PUT` verzoeken.
* Wanneer dat niet het geval is, krijgt de cliënt een nuttige, duidelijke foutmelding.
* Controleren of er een optionele query parameter is met de naam `q` (zoals in `http://127.0.0.1:8000/items/foo?q=somequery`) voor `GET` verzoeken.
* Aangezien de `q` parameter werd gedeclareerd met `= None`, is deze optioneel.
* Zonder de `None` declaratie zou deze verplicht zijn (net als bij de body in het geval met `PUT`).
* Voor `PUT` verzoeken naar `/items/{item_id}`, lees de body als JSON:
* Controleer of het een verplicht attribuut `naam` heeft en dat dat een `str` is.
* Controleer of het een verplicht attribuut `price` heeft en dat dat een`float` is.
* Controleer of het een optioneel attribuut `is_offer` heeft, dat een `bool` is wanneer het aanwezig is.
* Dit alles werkt ook voor diep geneste JSON objecten.
* Converteer automatisch van en naar JSON.
* Documenteer alles met OpenAPI, dat gebruikt kan worden door:
* Interactieve documentatiesystemen.
* Automatische client code generatie systemen, voor vele talen.
* Biedt 2 interactieve documentatie-webinterfaces aan.
---
Dit was nog maar een snel overzicht, maar je zou nu toch al een idee moeten hebben over hoe het allemaal werkt.
Probeer deze regel te veranderen:
```Python
return {"item_name": item.name, "item_id": item_id}
```
...van:
```Python
... "item_name": item.name ...
```
...naar:
```Python
... "item_price": item.price ...
```
...en zie hoe je editor de attributen automatisch invult en hun types herkent:
![editor support](https://fastapi.tiangolo.com/img/vscode-completion.png)
Voor een vollediger voorbeeld met meer mogelijkheden, zie de <a href="https://fastapi.tiangolo.com/tutorial/">Tutorial - Gebruikershandleiding</a>.
**Spoiler alert**: de tutorial - gebruikershandleiding bevat:
* Declaratie van **parameters** op andere plaatsen zoals: **headers**, **cookies**, **formuliervelden** en **bestanden**.
* Hoe stel je **validatie restricties** in zoals `maximum_length` of een `regex`.
* Een zeer krachtig en eenvoudig te gebruiken **<abbr title="ook bekend als componenten, middelen, verstrekkers, diensten, injectables">Dependency Injection</abbr>** systeem.
* Beveiliging en authenticatie, inclusief ondersteuning voor **OAuth2** met **JWT-tokens** en **HTTP Basic** auth.
* Meer geavanceerde (maar even eenvoudige) technieken voor het declareren van **diep geneste JSON modellen** (dankzij Pydantic).
* **GraphQL** integratie met <a href="https://strawberry.rocks" class="external-link" target="_blank">Strawberry</a> en andere packages.
* Veel extra functies (dankzij Starlette) zoals:
* **WebSockets**
* uiterst gemakkelijke tests gebaseerd op HTTPX en `pytest`
* **CORS**
* **Cookie Sessions**
* ...en meer.
## Prestaties
Onafhankelijke TechEmpower benchmarks tonen **FastAPI** applicaties draaiend onder Uvicorn aan als <a href="https://www.techempower.com/benchmarks/#section=test&runid=7464e520-0dc2-473d-bd34-dbdfd7e85911&hw=ph&test=query&l=zijzen-7" class="external-link" target="_blank">een van de snelste Python frameworks beschikbaar</a>, alleen onder Starlette en Uvicorn zelf (intern gebruikt door FastAPI). (*)
Zie de sectie <a href="https://fastapi.tiangolo.com/benchmarks/" class="internal-link" target="_blank">Benchmarks</a> om hier meer over te lezen.
## Afhankelijkheden
FastAPI maakt gebruik van Pydantic en Starlette.
### `standard` Afhankelijkheden
Wanneer je FastAPI installeert met `pip install "fastapi[standard]"`, worden de volgende `standard` optionele afhankelijkheden geïnstalleerd:
Gebruikt door Pydantic:
* <a href="https://github.com/JoshData/python-email-validator" target="_blank"><code>email_validator</code></a> - voor email validatie.
Gebruikt door Starlette:
* <a href="https://www.python-httpx.org" target="_blank"><code>httpx</code></a> - Vereist indien je de `TestClient` wil gebruiken.
* <a href="https://jinja.palletsprojects.com" target="_blank"><code>jinja2</code></a> - Vereist als je de standaard templateconfiguratie wil gebruiken.
* <a href="https://github.com/Kludex/python-multipart" target="_blank"><code>python-multipart</code></a> - Vereist indien je <abbr title="het omzetten van de string die uit een HTTP verzoek komt in Python data">"parsen"</abbr> van formulieren wil ondersteunen met `requests.form()`.
Gebruikt door FastAPI / Starlette:
* <a href="https://www.uvicorn.org" target="_blank"><code>uvicorn</code></a> - voor de server die jouw applicatie laadt en bedient.
* `fastapi-cli` - om het `fastapi` commando te voorzien.
### Zonder `standard` Afhankelijkheden
Indien je de optionele `standard` afhankelijkheden niet wenst te installeren, kan je installeren met `pip install fastapi` in plaats van `pip install "fastapi[standard]"`.
### Bijkomende Optionele Afhankelijkheden
Er zijn nog een aantal bijkomende afhankelijkheden die je eventueel kan installeren.
Bijkomende optionele afhankelijkheden voor Pydantic:
* <a href="https://docs.pydantic.dev/latest/usage/pydantic_settings/" target="_blank"><code>pydantic-settings</code></a> - voor het beheren van settings.
* <a href="https://docs.pydantic.dev/latest/usage/types/extra_types/extra_types/" target="_blank"><code>pydantic-extra-types</code></a> - voor extra data types die gebruikt kunnen worden met Pydantic.
Bijkomende optionele afhankelijkheden voor FastAPI:
* <a href="https://github.com/ijl/orjson" target="_blank"><code>orjson</code></a> - Vereist indien je `ORJSONResponse` wil gebruiken.
* <a href="https://github.com/esnme/ultrajson" target="_blank"><code>ujson</code></a> - Vereist indien je `UJSONResponse` wil gebruiken.
## Licentie
Dit project is gelicenseerd onder de voorwaarden van de MIT licentie.

View File

@@ -1,587 +0,0 @@
# Introductie tot Python Types
Python biedt ondersteuning voor optionele "type hints" (ook wel "type annotaties" genoemd).
Deze **"type hints"** of annotaties zijn een speciale syntax waarmee het <abbr title="bijvoorbeeld: str, int, float, bool">type</abbr> van een variabele kan worden gedeclareerd.
Door types voor je variabelen te declareren, kunnen editors en hulpmiddelen je beter ondersteunen.
Dit is slechts een **korte tutorial/opfrisser** over Python type hints. Het behandelt enkel het minimum dat nodig is om ze te gebruiken met **FastAPI**... en dat is relatief weinig.
**FastAPI** is helemaal gebaseerd op deze type hints, ze geven veel voordelen.
Maar zelfs als je **FastAPI** nooit gebruikt, heb je er baat bij om er iets over te leren.
/// note
Als je een Python expert bent en alles al weet over type hints, sla dan dit hoofdstuk over.
///
## Motivatie
Laten we beginnen met een eenvoudig voorbeeld:
{* ../../docs_src/python_types/tutorial001.py *}
Het aanroepen van dit programma leidt tot het volgende resultaat:
```
John Doe
```
De functie voert het volgende uit:
* Neem een `first_name` en een `last_name`
* Converteer de eerste letter van elk naar een hoofdletter met `title()`.
``
* <abbr title="Voegt ze samen, als één. Met de inhoud van de een na de ander.">Voeg samen</abbr> met een spatie in het midden.
{* ../../docs_src/python_types/tutorial001.py hl[2] *}
### Bewerk het
Dit is een heel eenvoudig programma.
Maar stel je nu voor dat je het vanaf nul zou moeten maken.
Op een gegeven moment zou je aan de definitie van de functie zijn begonnen, je had de parameters klaar...
Maar dan moet je “die methode die de eerste letter naar hoofdletters converteert” aanroepen.
Was het `upper`? Was het `uppercase`? `first_uppercase`? `capitalize`?
Dan roep je de hulp in van je oude programmeursvriend, (automatische) code aanvulling in je editor.
Je typt de eerste parameter van de functie, `first_name`, dan een punt (`.`) en drukt dan op `Ctrl+Spatie` om de aanvulling te activeren.
Maar helaas krijg je niets bruikbaars:
<img src="/img/python-types/image01.png">
### Types toevoegen
Laten we een enkele regel uit de vorige versie aanpassen.
We zullen precies dit fragment, de parameters van de functie, wijzigen van:
```Python
first_name, last_name
```
naar:
```Python
first_name: str, last_name: str
```
Dat is alles.
Dat zijn de "type hints":
{* ../../docs_src/python_types/tutorial002.py hl[1] *}
Dit is niet hetzelfde als het declareren van standaardwaarden zoals bij:
```Python
first_name="john", last_name="doe"
```
Het is iets anders.
We gebruiken dubbele punten (`:`), geen gelijkheidstekens (`=`).
Het toevoegen van type hints verandert normaal gesproken niet wat er gebeurt in je programma t.o.v. wat er zonder type hints zou gebeuren.
Maar stel je voor dat je weer bezig bent met het maken van een functie, maar deze keer met type hints.
Op hetzelfde moment probeer je de automatische aanvulling te activeren met `Ctrl+Spatie` en je ziet:
<img src="/img/python-types/image02.png">
Nu kun je de opties bekijken en er doorheen scrollen totdat je de optie vindt die “een belletje doet rinkelen”:
<img src="/img/python-types/image03.png">
### Meer motivatie
Bekijk deze functie, deze heeft al type hints:
{* ../../docs_src/python_types/tutorial003.py hl[1] *}
Omdat de editor de types van de variabelen kent, krijgt u niet alleen aanvulling, maar ook controles op fouten:
<img src="/img/python-types/image04.png">
Nu weet je hoe je het moet oplossen, converteer `age` naar een string met `str(age)`:
{* ../../docs_src/python_types/tutorial004.py hl[2] *}
## Types declareren
Je hebt net de belangrijkste plek om type hints te declareren gezien. Namelijk als functieparameters.
Dit is ook de belangrijkste plek waar je ze gebruikt met **FastAPI**.
### Eenvoudige types
Je kunt alle standaard Python types declareren, niet alleen `str`.
Je kunt bijvoorbeeld het volgende gebruiken:
* `int`
* `float`
* `bool`
* `bytes`
{* ../../docs_src/python_types/tutorial005.py hl[1] *}
### Generieke types met typeparameters
Er zijn enkele datastructuren die andere waarden kunnen bevatten, zoals `dict`, `list`, `set` en `tuple` en waar ook de interne waarden hun eigen type kunnen hebben.
Deze types die interne types hebben worden “**generieke**” types genoemd. Het is mogelijk om ze te declareren, zelfs met hun interne types.
Om deze types en de interne types te declareren, kun je de standaard Python module `typing` gebruiken. Deze module is speciaal gemaakt om deze type hints te ondersteunen.
#### Nieuwere versies van Python
De syntax met `typing` is **verenigbaar** met alle versies, van Python 3.6 tot aan de nieuwste, inclusief Python 3.9, Python 3.10, enz.
Naarmate Python zich ontwikkelt, worden **nieuwere versies**, met verbeterde ondersteuning voor deze type annotaties, beschikbaar. In veel gevallen hoef je niet eens de `typing` module te importeren en te gebruiken om de type annotaties te declareren.
Als je een recentere versie van Python kunt kiezen voor je project, kun je profiteren van die extra eenvoud.
In alle documentatie staan voorbeelden die compatibel zijn met elke versie van Python (als er een verschil is).
Bijvoorbeeld “**Python 3.6+**” betekent dat het compatibel is met Python 3.6 of hoger (inclusief 3.7, 3.8, 3.9, 3.10, etc). En “**Python 3.9+**” betekent dat het compatibel is met Python 3.9 of hoger (inclusief 3.10, etc).
Als je de **laatste versies van Python** kunt gebruiken, gebruik dan de voorbeelden voor de laatste versie, die hebben de **beste en eenvoudigste syntax**, bijvoorbeeld “**Python 3.10+**”.
#### List
Laten we bijvoorbeeld een variabele definiëren als een `list` van `str`.
//// tab | Python 3.9+
Declareer de variabele met dezelfde dubbele punt (`:`) syntax.
Als type, vul `list` in.
Doordat de list een type is dat enkele interne types bevat, zet je ze tussen vierkante haakjes:
```Python hl_lines="1"
{!> ../../docs_src/python_types/tutorial006_py39.py!}
```
////
//// tab | Python 3.8+
Van `typing`, importeer `List` (met een hoofdletter `L`):
```Python hl_lines="1"
{!> ../../docs_src/python_types/tutorial006.py!}
```
Declareer de variabele met dezelfde dubbele punt (`:`) syntax.
Zet als type de `List` die je hebt geïmporteerd uit `typing`.
Doordat de list een type is dat enkele interne types bevat, zet je ze tussen vierkante haakjes:
```Python hl_lines="4"
{!> ../../docs_src/python_types/tutorial006.py!}
```
////
/// info
De interne types tussen vierkante haakjes worden “typeparameters” genoemd.
In dit geval is `str` de typeparameter die wordt doorgegeven aan `List` (of `list` in Python 3.9 en hoger).
///
Dat betekent: “de variabele `items` is een `list`, en elk van de items in deze list is een `str`”.
/// tip
Als je Python 3.9 of hoger gebruikt, hoef je `List` niet te importeren uit `typing`, je kunt in plaats daarvan hetzelfde reguliere `list` type gebruiken.
///
Door dat te doen, kan je editor ondersteuning bieden, zelfs tijdens het verwerken van items uit de list:
<img src="/img/python-types/image05.png">
Zonder types is dat bijna onmogelijk om te bereiken.
Merk op dat de variabele `item` een van de elementen is in de lijst `items`.
Toch weet de editor dat het een `str` is, en biedt daar vervolgens ondersteuning voor aan.
#### Tuple en Set
Je kunt hetzelfde doen om `tuple`s en `set`s te declareren:
//// tab | Python 3.9+
```Python hl_lines="1"
{!> ../../docs_src/python_types/tutorial007_py39.py!}
```
////
//// tab | Python 3.8+
```Python hl_lines="1 4"
{!> ../../docs_src/python_types/tutorial007.py!}
```
////
Dit betekent:
* De variabele `items_t` is een `tuple` met 3 items, een `int`, nog een `int`, en een `str`.
* De variabele `items_s` is een `set`, en elk van de items is van het type `bytes`.
#### Dict
Om een `dict` te definiëren, geef je 2 typeparameters door, gescheiden door komma's.
De eerste typeparameter is voor de sleutels (keys) van de `dict`.
De tweede typeparameter is voor de waarden (values) van het `dict`:
//// tab | Python 3.9+
```Python hl_lines="1"
{!> ../../docs_src/python_types/tutorial008_py39.py!}
```
////
//// tab | Python 3.8+
```Python hl_lines="1 4"
{!> ../../docs_src/python_types/tutorial008.py!}
```
////
Dit betekent:
* De variabele `prices` is een `dict`:
* De sleutels van dit `dict` zijn van het type `str` (bijvoorbeeld de naam van elk item).
* De waarden van dit `dict` zijn van het type `float` (bijvoorbeeld de prijs van elk item).
#### Union
Je kunt een variable declareren die van **verschillende types** kan zijn, bijvoorbeeld een `int` of een `str`.
In Python 3.6 en hoger (inclusief Python 3.10) kun je het `Union`-type van `typing` gebruiken en de mogelijke types die je wilt accepteren, tussen de vierkante haakjes zetten.
In Python 3.10 is er ook een **nieuwe syntax** waarin je de mogelijke types kunt scheiden door een <abbr title='ook wel "bitwise of operator" genoemd, maar die betekenis is hier niet relevant'>verticale balk (`|`)</abbr>.
//// tab | Python 3.10+
```Python hl_lines="1"
{!> ../../docs_src/python_types/tutorial008b_py310.py!}
```
////
//// tab | Python 3.8+
```Python hl_lines="1 4"
{!> ../../docs_src/python_types/tutorial008b.py!}
```
////
In beide gevallen betekent dit dat `item` een `int` of een `str` kan zijn.
#### Mogelijk `None`
Je kunt declareren dat een waarde een type kan hebben, zoals `str`, maar dat het ook `None` kan zijn.
In Python 3.6 en hoger (inclusief Python 3.10) kun je het declareren door `Optional` te importeren en te gebruiken vanuit de `typing`-module.
```Python hl_lines="1 4"
{!../../docs_src/python_types/tutorial009.py!}
```
Door `Optional[str]` te gebruiken in plaats van alleen `str`, kan de editor je helpen fouten te detecteren waarbij je ervan uit zou kunnen gaan dat een waarde altijd een `str` is, terwijl het in werkelijkheid ook `None` zou kunnen zijn.
`Optional[EenType]` is eigenlijk een snelkoppeling voor `Union[EenType, None]`, ze zijn equivalent.
Dit betekent ook dat je in Python 3.10 `EenType | None` kunt gebruiken:
//// tab | Python 3.10+
```Python hl_lines="1"
{!> ../../docs_src/python_types/tutorial009_py310.py!}
```
////
//// tab | Python 3.8+
```Python hl_lines="1 4"
{!> ../../docs_src/python_types/tutorial009.py!}
```
////
//// tab | Python 3.8+ alternative
```Python hl_lines="1 4"
{!> ../../docs_src/python_types/tutorial009b.py!}
```
////
#### Gebruik van `Union` of `Optional`
Als je een Python versie lager dan 3.10 gebruikt, is dit een tip vanuit mijn **subjectieve** standpunt:
* 🚨 Vermijd het gebruik van `Optional[EenType]`.
* Gebruik in plaats daarvan **`Union[EenType, None]`** ✨.
Beide zijn gelijkwaardig en onderliggend zijn ze hetzelfde, maar ik zou `Union` aanraden in plaats van `Optional` omdat het woord “**optional**” lijkt te impliceren dat de waarde optioneel is, en het eigenlijk betekent “het kan `None` zijn”, zelfs als het niet optioneel is en nog steeds vereist is.
Ik denk dat `Union[SomeType, None]` explicieter is over wat het betekent.
Het gaat alleen om de woorden en naamgeving. Maar die naamgeving kan invloed hebben op hoe jij en je teamgenoten over de code denken.
Laten we als voorbeeld deze functie nemen:
{* ../../docs_src/python_types/tutorial009c.py hl[1,4] *}
De parameter `name` is gedefinieerd als `Optional[str]`, maar is **niet optioneel**, je kunt de functie niet aanroepen zonder de parameter:
```Python
say_hi() # Oh, nee, dit geeft een foutmelding! 😱
```
De `name` parameter is **nog steeds vereist** (niet *optioneel*) omdat het geen standaardwaarde heeft. Toch accepteert `name` `None` als waarde:
```Python
say_hi(name=None) # Dit werkt, None is geldig 🎉
```
Het goede nieuws is dat als je eenmaal Python 3.10 gebruikt, je je daar geen zorgen meer over hoeft te maken, omdat je dan gewoon `|` kunt gebruiken om unions van types te definiëren:
{* ../../docs_src/python_types/tutorial009c_py310.py hl[1,4] *}
Dan hoef je je geen zorgen te maken over namen als `Optional` en `Union`. 😎
#### Generieke typen
De types die typeparameters in vierkante haakjes gebruiken, worden **Generieke types** of **Generics** genoemd, bijvoorbeeld:
//// tab | Python 3.10+
Je kunt dezelfde ingebouwde types gebruiken als generics (met vierkante haakjes en types erin):
* `list`
* `tuple`
* `set`
* `dict`
Hetzelfde als bij Python 3.8, uit de `typing`-module:
* `Union`
* `Optional` (hetzelfde als bij Python 3.8)
* ...en anderen.
In Python 3.10 kun je , als alternatief voor de generieke `Union` en `Optional`, de <abbr title='ook wel "bitwise or operator" genoemd, maar die betekenis is hier niet relevant'>verticale lijn (`|`)</abbr> gebruiken om unions van typen te voorzien, dat is veel beter en eenvoudiger.
////
//// tab | Python 3.9+
Je kunt dezelfde ingebouwde types gebruiken als generieke types (met vierkante haakjes en types erin):
* `list`
* `tuple`
* `set`
* `dict`
En hetzelfde als met Python 3.8, vanuit de `typing`-module:
* `Union`
* `Optional`
* ...en anderen.
////
//// tab | Python 3.8+
* `List`
* `Tuple`
* `Set`
* `Dict`
* `Union`
* `Optional`
* ...en anderen.
////
### Klassen als types
Je kunt een klasse ook declareren als het type van een variabele.
Stel dat je een klasse `Person` hebt, met een naam:
{* ../../docs_src/python_types/tutorial010.py hl[1:3] *}
Vervolgens kun je een variabele van het type `Persoon` declareren:
{* ../../docs_src/python_types/tutorial010.py hl[6] *}
Dan krijg je ook nog eens volledige editorondersteuning:
<img src="/img/python-types/image06.png">
Merk op dat dit betekent dat "`one_person` een **instantie** is van de klasse `Person`".
Dit betekent niet dat `one_person` de **klasse** is met de naam `Person`.
## Pydantic modellen
<a href="https://docs.pydantic.dev/" class="external-link" target="_blank">Pydantic</a> is een Python-pakket voor het uitvoeren van datavalidatie.
Je declareert de "vorm" van de data als klassen met attributen.
Elk attribuut heeft een type.
Vervolgens maak je een instantie van die klasse met een aantal waarden en het valideert de waarden, converteert ze naar het juiste type (als dat het geval is) en geeft je een object met alle data terug.
Daarnaast krijg je volledige editorondersteuning met dat resulterende object.
Een voorbeeld uit de officiële Pydantic-documentatie:
//// tab | Python 3.10+
```Python
{!> ../../docs_src/python_types/tutorial011_py310.py!}
```
////
//// tab | Python 3.9+
```Python
{!> ../../docs_src/python_types/tutorial011_py39.py!}
```
////
//// tab | Python 3.8+
```Python
{!> ../../docs_src/python_types/tutorial011.py!}
```
////
/// info
Om meer te leren over <a href="https://docs.pydantic.dev/" class="external-link" target="_blank">Pydantic, bekijk de documentatie</a>.
///
**FastAPI** is volledig gebaseerd op Pydantic.
Je zult veel meer van dit alles in de praktijk zien in de [Tutorial - Gebruikershandleiding](tutorial/index.md){.internal-link target=_blank}.
/// tip
Pydantic heeft een speciaal gedrag wanneer je `Optional` of `Union[EenType, None]` gebruikt zonder een standaardwaarde, je kunt er meer over lezen in de Pydantic-documentatie over <a href="https://docs.pydantic.dev/2.3/usage/models/#required-fields" class="external-link" target="_blank">Verplichte optionele velden</a>.
///
## Type Hints met Metadata Annotaties
Python heeft ook een functie waarmee je **extra <abbr title="Data over de data, in dit geval informatie over het type, bijvoorbeeld een beschrijving.">metadata</abbr>** in deze type hints kunt toevoegen met behulp van `Annotated`.
//// tab | Python 3.9+
In Python 3.9 is `Annotated` onderdeel van de standaardpakket, dus je kunt het importeren vanuit `typing`.
```Python hl_lines="1 4"
{!> ../../docs_src/python_types/tutorial013_py39.py!}
```
////
//// tab | Python 3.8+
In versies lager dan Python 3.9 importeer je `Annotated` vanuit `typing_extensions`.
Het wordt al geïnstalleerd met **FastAPI**.
```Python hl_lines="1 4"
{!> ../../docs_src/python_types/tutorial013.py!}
```
////
Python zelf doet niets met deze `Annotated` en voor editors en andere hulpmiddelen is het type nog steeds een `str`.
Maar je kunt deze ruimte in `Annotated` gebruiken om **FastAPI** te voorzien van extra metadata over hoe je wilt dat je applicatie zich gedraagt.
Het belangrijkste om te onthouden is dat **de eerste *typeparameter*** die je doorgeeft aan `Annotated` het **werkelijke type** is. De rest is gewoon metadata voor andere hulpmiddelen.
Voor nu hoef je alleen te weten dat `Annotated` bestaat en dat het standaard Python is. 😎
Later zul je zien hoe **krachtig** het kan zijn.
/// tip
Het feit dat dit **standaard Python** is, betekent dat je nog steeds de **best mogelijke ontwikkelaarservaring** krijgt in je editor, met de hulpmiddelen die je gebruikt om je code te analyseren en te refactoren, enz. ✨
Daarnaast betekent het ook dat je code zeer verenigbaar zal zijn met veel andere Python-hulpmiddelen en -pakketten. 🚀
///
## Type hints in **FastAPI**
**FastAPI** maakt gebruik van type hints om verschillende dingen te doen.
Met **FastAPI** declareer je parameters met type hints en krijg je:
* **Editor ondersteuning**.
* **Type checks**.
...en **FastAPI** gebruikt dezelfde declaraties om:
* **Vereisten te definïeren **: van request pad parameters, query parameters, headers, bodies, dependencies, enz.
* **Data te converteren**: van de request naar het vereiste type.
* **Data te valideren**: afkomstig van elke request:
* **Automatische foutmeldingen** te genereren die naar de client worden geretourneerd wanneer de data ongeldig is.
* De API met OpenAPI te **documenteren**:
* die vervolgens wordt gebruikt door de automatische interactieve documentatie gebruikersinterfaces.
Dit klinkt misschien allemaal abstract. Maak je geen zorgen. Je ziet dit allemaal in actie in de [Tutorial - Gebruikershandleiding](tutorial/index.md){.internal-link target=_blank}.
Het belangrijkste is dat door standaard Python types te gebruiken, op één plek (in plaats van meer klassen, decorators, enz. toe te voegen), **FastAPI** een groot deel van het werk voor je doet.
/// info
Als je de hele tutorial al hebt doorgenomen en terug bent gekomen om meer te weten te komen over types, is een goede bron <a href="https://mypy.readthedocs.io/en/latest/cheat_sheet_py3.html" class="external-link" target="_blank">het "cheat sheet" van `mypy`</a>.
///

View File

@@ -1 +0,0 @@
INHERIT: ../en/mkdocs.yml

View File

@@ -1,201 +0,0 @@
# Cechy
## Cechy FastAPI
**FastAPI** zapewnia Ci następujące korzyści:
### Oparcie o standardy open
* <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank"><strong>OpenAPI</strong></a> do tworzenia API, w tym deklaracji <abbr title="znane również jako: paths, endpoints, routes">ścieżek</abbr> <abbr title="znane również jako metody HTTP, takie jak POST, GET, PUT, DELETE">operacji</abbr>, parametrów, <abbr title="po angielsku: body requests">ciał zapytań</abbr>, bezpieczeństwa, itp.
* Automatyczna dokumentacja modelu danych za pomocą <a href="https://json-schema.org/" class="external-link" target="_blank"><strong>JSON Schema</strong></a> (ponieważ OpenAPI bazuje na JSON Schema).
* Zaprojektowane z myślą o zgodności z powyższymi standardami zamiast dodawania ich obsługi po fakcie.
* Możliwość automatycznego **generowania kodu klienta** w wielu językach.
### Automatyczna dokumentacja
Interaktywna dokumentacja i webowe interfejsy do eksploracji API. Z racji tego, że framework bazuje na OpenAPI, istnieje wiele opcji, z czego 2 są domyślnie dołączone.
* <a href="https://github.com/swagger-api/swagger-ui" class="external-link" target="_blank"><strong>Swagger UI</strong></a>, z interaktywnym interfejsem - odpytuj i testuj swoje API bezpośrednio z przeglądarki.
![Swagger UI interakcja](https://fastapi.tiangolo.com/img/index/index-03-swagger-02.png)
* Alternatywna dokumentacja API z <a href="https://github.com/Rebilly/ReDoc" class="external-link" target="_blank"><strong>ReDoc</strong></a>.
![ReDoc](https://fastapi.tiangolo.com/img/index/index-06-redoc-02.png)
### Nowoczesny Python
Wszystko opiera się na standardowych deklaracjach typu **Python 3.8** (dzięki Pydantic). Brak nowej składni do uczenia. Po prostu standardowy, współczesny Python.
Jeśli potrzebujesz szybkiego przypomnienia jak używać deklaracji typów w Pythonie (nawet jeśli nie używasz FastAPI), sprawdź krótki samouczek: [Python Types](python-types.md){.internal-link target=_blank}.
Wystarczy, że napiszesz standardowe deklaracje typów Pythona:
```Python
from datetime import date
from pydantic import BaseModel
# Zadeklaruj parametr jako str
# i uzyskaj wsparcie edytora wewnątrz funkcji
def main(user_id: str):
return user_id
# Model Pydantic
class User(BaseModel):
id: int
name: str
joined: date
```
A one będą mogły zostać później użyte w następujący sposób:
```Python
my_user: User = User(id=3, name="John Doe", joined="2018-07-19")
second_user_data = {
"id": 4,
"name": "Mary",
"joined": "2018-11-30",
}
my_second_user: User = User(**second_user_data)
```
/// info
`**second_user_data` oznacza:
Przekaż klucze i wartości słownika `second_user_data` bezpośrednio jako argumenty klucz-wartość, co jest równoznaczne z: `User(id=4, name="Mary", joined="2018-11-30")`
///
### Wsparcie edytora
Cały framework został zaprojektowany tak, aby był łatwy i intuicyjny w użyciu. Wszystkie pomysły zostały przetestowane na wielu edytorach jeszcze przed rozpoczęciem procesu tworzenia, aby zapewnić najlepsze wrażenia programistyczne.
Ostatnia ankieta <abbr title="coroczna ankieta przeprowadza w środowisku programistów języka Python">Python developer survey</abbr> jasno wskazuje, że <a href="https://www.jetbrains.com/research/python-developers-survey-2017/#tools-and-features" class="external-link" target="_blank">najczęściej używaną funkcjonalnością jest autouzupełnianie w edytorze</a>.
Cała struktura frameworku **FastAPI** jest na tym oparta. Autouzupełnianie działa wszędzie.
Rzadko będziesz musiał wracać do dokumentacji.
Oto, jak twój edytor może Ci pomóc:
* <a href="https://code.visualstudio.com/" class="external-link" target="_blank">Visual Studio Code</a>:
![wsparcie edytora](https://fastapi.tiangolo.com/img/vscode-completion.png)
* <a href="https://www.jetbrains.com/pycharm/" class="external-link" target="_blank">PyCharm</a>:
![wsparcie edytora](https://fastapi.tiangolo.com/img/pycharm-completion.png)
Otrzymasz uzupełnienie nawet w miejscach, w których normalnie uzupełnienia nie ma. Na przykład klucz "price" w treści JSON (który mógł być zagnieżdżony), który pochodzi z zapytania.
Koniec z wpisywaniem błędnych nazw kluczy, przechodzeniem tam i z powrotem w dokumentacji lub przewijaniem w górę i w dół, aby sprawdzić, czy w końcu użyłeś nazwy `username` czy `user_name`.
### Zwięzłość
Wszystko posiada sensowne **domyślne wartości**. Wszędzie znajdziesz opcjonalne konfiguracje. Wszystkie parametry możesz dostroić, aby zrobić to co potrzebujesz do zdefiniowania API.
Ale domyślnie wszystko **"po prostu działa"**.
### Walidacja
* Walidacja większości (lub wszystkich?) **typów danych** Pythona, w tym:
* Obiektów JSON (`dict`).
* Tablic JSON (`list`) ze zdefiniowanym typem elementów.
* Pól tekstowych (`str`) z określeniem minimalnej i maksymalnej długości.
* Liczb (`int`, `float`) z wartościami minimalnymi, maksymalnymi, itp.
* Walidacja bardziej egzotycznych typów danych, takich jak:
* URL.
* Email.
* UUID.
* ...i inne.
Cała walidacja jest obsługiwana przez ugruntowaną i solidną bibliotekę **Pydantic**.
### Bezpieczeństwo i uwierzytelnianie
Bezpieczeństwo i uwierzytelnianie jest zintegrowane. Bez żadnych kompromisów z bazami czy modelami danych.
Wszystkie schematy bezpieczeństwa zdefiniowane w OpenAPI, w tym:
* Podstawowy protokół HTTP.
* **OAuth2** (również z **tokenami JWT**). Sprawdź samouczek [OAuth2 with JWT](tutorial/security/oauth2-jwt.md){.internal-link target=_blank}.
* Klucze API w:
* Nagłówkach.
* Parametrach zapytań.
* Ciasteczkach, itp.
Plus wszystkie funkcje bezpieczeństwa Starlette (włączając w to **<abbr title="po angielsku: session cookies">ciasteczka sesyjne</abbr>**).
Wszystko zbudowane jako narzędzia i komponenty wielokrotnego użytku, które można łatwo zintegrować z systemami, magazynami oraz bazami danych - relacyjnymi, NoSQL, itp.
### Wstrzykiwanie Zależności
FastAPI zawiera niezwykle łatwy w użyciu, ale niezwykle potężny system <abbr title='Po angielsku: Dependency Injection. Znane również jako "components", "resources", "services", "providers"'><strong>Wstrzykiwania Zależności</strong></abbr>.
* Nawet zależności mogą mieć zależności, tworząc hierarchię lub **"graf" zależności**.
* Wszystko jest **obsługiwane automatycznie** przez framework.
* Wszystkie zależności mogą wymagać danych w żądaniach oraz rozszerzać ograniczenia i automatyczną dokumentację **<abbr title="po angielsku: path operations">operacji na ścieżce</abbr>**.
* **Automatyczna walidacja** parametrów *operacji na ścieżce* zdefiniowanych w zależnościach.
* Obsługa złożonych systemów uwierzytelniania użytkowników, **połączeń z bazami danych**, itp.
* Bazy danych, front end, itp. **bez kompromisów**, ale wciąż łatwe do integracji.
### Nieograniczone "wtyczki"
Lub ujmując to inaczej - brak potrzeby wtyczek. Importuj i używaj kod, który potrzebujesz.
Każda integracja została zaprojektowana tak, aby była tak prosta w użyciu (z zależnościami), że możesz utworzyć "wtyczkę" dla swojej aplikacji w 2 liniach kodu, używając tej samej struktury i składni, które są używane w *operacjach na ścieżce*.
### Testy
* 100% <abbr title="Ilość kodu, który jest automatycznie testowany">pokrycia kodu testami</abbr>.
* 100% <abbr title="Deklaracje typów Python - dzięki nim twój edytor i zewnętrzne narzędzia mogą zapewnić Ci lepsze wsparcie ">adnotacji typów</abbr>.
* Używany w aplikacjach produkcyjnych.
## Cechy Starlette
**FastAPI** jest w pełni kompatybilny z (oraz bazuje na) <a href="https://www.starlette.io/" class="external-link" target="_blank"><strong>Starlette</strong></a>. Tak więc każdy dodatkowy kod Starlette, który posiadasz, również będzie działał.
`FastAPI` jest w rzeczywistości podklasą `Starlette`, więc jeśli już znasz lub używasz Starlette, większość funkcji będzie działać w ten sam sposób.
Dzięki **FastAPI** otrzymujesz wszystkie funkcje **Starlette** (ponieważ FastAPI to po prostu Starlette na sterydach):
* Bardzo imponująca wydajność. Jest to <a href="https://github.com/encode/starlette#performance" class="external-link" target="_blank">jeden z najszybszych dostępnych frameworków Pythona, na równi z **NodeJS** i **Go**</a>.
* Wsparcie dla **WebSocket**.
* <abbr title='Zadania wykonywane w tle, bez zatrzymywania żądań, w tym samym procesie. Po angielsku: In-process background tasks'>Zadania w tle</abbr>.
* Eventy startup i shutdown.
* Klient testowy zbudowany na bazie biblioteki `requests`.
* **CORS**, GZip, pliki statyczne, streamy.
* Obsługa **sesji i ciasteczek**.
* 100% pokrycie testami.
* 100% adnotacji typów.
## Cechy Pydantic
**FastAPI** jest w pełni kompatybilny z (oraz bazuje na) <a href="https://docs.pydantic.dev/" class="external-link" target="_blank"><strong>Pydantic</strong></a>. Tak więc każdy dodatkowy kod Pydantic, który posiadasz, również będzie działał.
Wliczając w to zewnętrzne biblioteki, również oparte o Pydantic, takie jak <abbr title="Mapowanie obiektowo-relacyjne. Po angielsku: Object-Relational Mapper">ORM</abbr>, <abbr title="Object-Document Mapper">ODM</abbr> dla baz danych.
Oznacza to, że w wielu przypadkach możesz przekazać ten sam obiekt, który otrzymasz z żądania **bezpośrednio do bazy danych**, ponieważ wszystko jest walidowane automatycznie.
Działa to również w drugą stronę, w wielu przypadkach możesz po prostu przekazać obiekt otrzymany z bazy danych **bezpośrednio do klienta**.
Dzięki **FastAPI** otrzymujesz wszystkie funkcje **Pydantic** (ponieważ FastAPI bazuje na Pydantic do obsługi wszystkich danych):
* **Bez prania mózgu**:
* Brak nowego mikrojęzyka do definiowania schematu, którego trzeba się nauczyć.
* Jeśli znasz adnotacje typów Pythona to wiesz jak używać Pydantic.
* Dobrze współpracuje z Twoim **<abbr title='Skrót od "Integrated Development Environment", podobne do edytora kodu'>IDE</abbr>/<abbr title="Program, który sprawdza Twój kod pod kątem błędów">linterem</abbr>/mózgiem**:
* Ponieważ struktury danych Pydantic to po prostu instancje klas, które definiujesz; autouzupełnianie, linting, mypy i twoja intuicja powinny działać poprawnie z Twoimi zwalidowanymi danymi.
* Walidacja **złożonych struktur**:
* Wykorzystanie hierarchicznych modeli Pydantic, Pythonowego modułu `typing` zawierającego `List`, `Dict`, itp.
* Walidatory umożliwiają jasne i łatwe definiowanie, sprawdzanie złożonych struktur danych oraz dokumentowanie ich jako JSON Schema.
* Możesz mieć głęboko **zagnieżdżone obiekty JSON** i wszystkie je poddać walidacji i adnotować.
* **Rozszerzalność**:
* Pydantic umożliwia zdefiniowanie niestandardowych typów danych lub rozszerzenie walidacji o metody na modelu, na których użyty jest dekorator walidatora.
* 100% pokrycie testami.

View File

@@ -1,269 +0,0 @@
# Pomóż FastAPI - Uzyskaj pomoc
Czy podoba Ci się **FastAPI**?
Czy chciałbyś pomóc FastAPI, jego użytkownikom i autorowi?
Może napotkałeś na trudności z **FastAPI** i potrzebujesz pomocy?
Istnieje kilka bardzo łatwych sposobów, aby pomóc (czasami wystarczy jedno lub dwa kliknięcia).
Istnieje również kilka sposobów uzyskania pomocy.
## Zapisz się do newslettera
Możesz zapisać się do rzadkiego [newslettera o **FastAPI i jego przyjaciołach**](newsletter.md){.internal-link target=_blank}, aby być na bieżąco z:
* Aktualnościami o FastAPI i przyjaciołach 🚀
* Przewodnikami 📝
* Funkcjami ✨
* Przełomowymi zmianami 🚨
* Poradami i sztuczkami ✅
## Śledź FastAPI na X (Twitter)
<a href="https://x.com/fastapi" class="external-link" target="_blank">Śledź @fastapi na **X (Twitter)**</a> aby być na bieżąco z najnowszymi wiadomościami o **FastAPI**. 🐦
## Dodaj gwiazdkę **FastAPI** na GitHubie
Możesz "dodać gwiazdkę" FastAPI na GitHubie (klikając przycisk gwiazdki w prawym górnym rogu): <a href="https://github.com/fastapi/fastapi" class="external-link" target="_blank">https://github.com/fastapi/fastapi</a>. ⭐️
Dodając gwiazdkę, inni użytkownicy będą mogli łatwiej znaleźć projekt i zobaczyć, że był już przydatny dla innych.
## Obserwuj repozytorium GitHub w poszukiwaniu nowych wydań
Możesz "obserwować" FastAPI na GitHubie (klikając przycisk "obserwuj" w prawym górnym rogu): <a href="https://github.com/fastapi/fastapi" class="external-link" target="_blank">https://github.com/fastapi/fastapi</a>. 👀
Wybierz opcję "Tylko wydania".
Dzięki temu będziesz otrzymywać powiadomienia (na swój adres e-mail) za każdym razem, gdy pojawi się nowe wydanie (nowa wersja) **FastAPI** z poprawkami błędów i nowymi funkcjami.
## Skontaktuj się z autorem
Możesz skontaktować się <a href="https://tiangolo.com" class="external-link" target="_blank">ze mną (Sebastián Ramírez / `tiangolo`)</a>, autorem.
Możesz:
* <a href="https://github.com/tiangolo" class="external-link" target="_blank">Śledzić mnie na **GitHubie**</a>.
* Zobacz inne projekty open source, które stworzyłem, a mogą być dla Ciebie pomocne.
* Śledź mnie, aby dostać powiadomienie, gdy utworzę nowy projekt open source.
* <a href="https://x.com/tiangolo" class="external-link" target="_blank">Śledzić mnie na **X (Twitter)**</a> lub na <a href="https://fosstodon.org/@tiangolo" class="external-link" target="_blank">Mastodonie</a>.
* Napisz mi, w jaki sposób korzystasz z FastAPI (uwielbiam o tym czytać).
* Dowiedz się, gdy ogłoszę coś nowego lub wypuszczę nowe narzędzia.
* Możesz także <a href="https://x.com/fastapi" class="external-link" target="_blank">śledzić @fastapi na X (Twitter)</a> (to oddzielne konto).
* <a href="https://www.linkedin.com/in/tiangolo/" class="external-link" target="_blank">Nawiąż ze mną kontakt na **Linkedinie**</a>.
* Dowiedz się, gdy ogłoszę coś nowego lub wypuszczę nowe narzędzia (chociaż częściej korzystam z Twittera 🤷‍♂).
* Czytaj moje posty (lub śledź mnie) na <a href="https://dev.to/tiangolo" class="external-link" target="_blank">**Dev.to**</a> lub na <a href="https://medium.com/@tiangolo" class="external-link" target="_blank">**Medium**</a>.
* Czytaj o innych pomysłach, artykułach i dowiedz się o narzędziach, które stworzyłem.
* Śledź mnie, by wiedzieć gdy opublikuję coś nowego.
## Napisz tweeta o **FastAPI**
<a href="https://x.com/compose/tweet?text=I'm loving @fastapi because... https://github.com/fastapi/fastapi" class="external-link" target="_blank">Napisz tweeta o **FastAPI**</a> i powiedz czemu Ci się podoba. 🎉
Uwielbiam czytać w jaki sposób **FastAPI** jest używane, co Ci się w nim podobało, w jakim projekcie/firmie go używasz itp.
## Głosuj na FastAPI
* <a href="https://www.slant.co/options/34241/~fastapi-review" class="external-link" target="_blank">Głosuj na **FastAPI** w Slant</a>.
* <a href="https://alternativeto.net/software/fastapi/" class="external-link" target="_blank">Głosuj na **FastAPI** w AlternativeTo</a>.
* <a href="https://stackshare.io/pypi-fastapi" class="external-link" target="_blank">Powiedz, że używasz **FastAPI** na StackShare</a>.
## Pomagaj innym, odpowiadając na ich pytania na GitHubie
Możesz spróbować pomóc innym, odpowiadając w:
* <a href="https://github.com/fastapi/fastapi/discussions/categories/questions?discussions_q=category%3AQuestions+is%3Aunanswered" class="external-link" target="_blank">Dyskusjach na GitHubie</a>
* <a href="https://github.com/fastapi/fastapi/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc+label%3Aquestion+-label%3Aanswered+" class="external-link" target="_blank">Problemach na GitHubie</a>
W wielu przypadkach możesz już znać odpowiedź na te pytania. 🤓
Jeśli pomożesz wielu ludziom, możesz zostać oficjalnym [Ekspertem FastAPI](fastapi-people.md#fastapi-experts){.internal-link target=_blank}. 🎉
Pamiętaj tylko o najważniejszym: bądź życzliwy. Ludzie przychodzą sfrustrowani i w wielu przypadkach nie zadają pytań w najlepszy sposób, ale mimo to postaraj się być dla nich jak najbardziej życzliwy. 🤗
Chciałbym, by społeczność **FastAPI** była życzliwa i przyjazna. Nie akceptuj prześladowania ani braku szacunku wobec innych. Dbajmy o siebie nawzajem.
---
Oto, jak pomóc innym z pytaniami (w dyskusjach lub problemach):
### Zrozum pytanie
* Upewnij się, czy rozumiesz **cel** i przypadek użycia osoby pytającej.
* Następnie sprawdź, czy pytanie (większość to pytania) jest **jasne**.
* W wielu przypadkach zadane pytanie dotyczy rozwiązania wymyślonego przez użytkownika, ale może istnieć **lepsze** rozwiązanie. Jeśli dokładnie zrozumiesz problem i przypadek użycia, być może będziesz mógł zaproponować lepsze **alternatywne rozwiązanie**.
* Jeśli nie rozumiesz pytania, poproś o więcej **szczegółów**.
### Odtwórz problem
W większości przypadków problem wynika z **autorskiego kodu** osoby pytającej.
Często pytający umieszczają tylko fragment kodu, niewystarczający do **odtworzenia problemu**.
* Możesz poprosić ich o dostarczenie <a href="https://stackoverflow.com/help/minimal-reproducible-example" class="external-link" target="_blank">minimalnego, odtwarzalnego przykładu</a>, który możesz **skopiować i wkleić** i uruchomić lokalnie, aby zobaczyć ten sam błąd lub zachowanie, które widzą, lub lepiej zrozumieć ich przypadki użycia.
* Jeśli jesteś wyjątkowo pomocny, możesz spróbować **stworzyć taki przykład** samodzielnie, opierając się tylko na opisie problemu. Miej na uwadze, że może to zająć dużo czasu i lepiej może być najpierw poprosić ich o wyjaśnienie problemu.
### Proponuj rozwiązania
* Po zrozumieniu pytania możesz podać im możliwą **odpowiedź**.
* W wielu przypadkach lepiej zrozumieć ich **podstawowy problem lub przypadek użycia**, ponieważ może istnieć lepszy sposób rozwiązania niż to, co próbują zrobić.
### Poproś o zamknięcie
Jeśli odpowiedzą, jest duża szansa, że rozwiązałeś ich problem, gratulacje, **jesteś bohaterem**! 🦸
* Jeśli Twoja odpowiedź rozwiązała problem, możesz poprosić o:
* W Dyskusjach na GitHubie: oznaczenie komentarza jako **odpowiedź**.
* W Problemach na GitHubie: **zamknięcie** problemu.
## Obserwuj repozytorium na GitHubie
Możesz "obserwować" FastAPI na GitHubie (klikając przycisk "obserwuj" w prawym górnym rogu): <a href="https://github.com/fastapi/fastapi" class="external-link" target="_blank">https://github.com/fastapi/fastapi</a>. 👀
Jeśli wybierzesz "Obserwuj" zamiast "Tylko wydania", otrzymasz powiadomienia, gdy ktoś utworzy nowy problem lub pytanie. Możesz również określić, że chcesz być powiadamiany tylko o nowych problemach, dyskusjach, PR-ach itp.
Następnie możesz spróbować pomóc rozwiązać te problemy.
## Zadawaj pytania
Możesz <a href="https://github.com/fastapi/fastapi/discussions/new?category=questions" class="external-link" target="_blank">utworzyć nowe pytanie</a> w repozytorium na GitHubie, na przykład aby:
* Zadać **pytanie** lub zapytać o **problem**.
* Zaproponować nową **funkcję**.
**Uwaga**: jeśli to zrobisz, poproszę Cię również o pomoc innym. 😉
## Przeglądaj Pull Requesty
Możesz pomóc mi w przeglądaniu pull requestów autorstwa innych osób.
Jak wcześniej wspomniałem, postaraj się być jak najbardziej życzliwy. 🤗
---
Oto, co warto mieć na uwadze podczas oceny pull requestu:
### Zrozum problem
* Najpierw upewnij się, że **rozumiesz problem**, który próbuje rozwiązać pull request. Może być osadzony w większym kontekście w GitHubowej dyskusji lub problemie.
* Jest też duża szansa, że pull request nie jest konieczny, ponieważ problem można rozwiązać w **inny sposób**. Wtedy możesz to zasugerować lub o to zapytać.
### Nie martw się stylem
* Nie przejmuj się zbytnio rzeczami takimi jak style wiadomości commitów, przy wcielaniu pull requesta łączę commity i modyfikuję opis sumarycznego commita ręcznie.
* Nie przejmuj się również stylem kodu, automatyczne narzędzia w repozytorium sprawdzają to samodzielnie.
A jeśli istnieje jakaś konkretna potrzeba dotycząca stylu lub spójności, sam poproszę o zmiany lub dodam commity z takimi zmianami.
### Sprawdź kod
* Przeczytaj kod, zastanów się czy ma sens, **uruchom go lokalnie** i potwierdź czy faktycznie rozwiązuje problem.
* Następnie dodaj **komentarz** z informacją o tym, że sprawdziłeś kod, dzięki temu będę miał pewność, że faktycznie go sprawdziłeś.
/// info
Niestety, nie mogę ślepo ufać PR-om, nawet jeśli mają kilka zatwierdzeń.
Kilka razy zdarzyło się, że PR-y miały 3, 5 lub więcej zatwierdzeń (prawdopodobnie dlatego, że opis obiecuje rozwiązanie ważnego problemu), ale gdy sam sprawdziłem danego PR-a, okazał się być zbugowany lub nie rozwiązywał problemu, który rzekomo miał rozwiązywać. 😅
Dlatego tak ważne jest, abyś faktycznie przeczytał i uruchomił kod oraz napisał w komentarzu, że to zrobiłeś. 🤓
///
* Jeśli PR można uprościć w jakiś sposób, możesz o to poprosić, ale nie ma potrzeby być zbyt wybrednym, może być wiele subiektywnych punktów widzenia (a ja też będę miał swój 🙈), więc lepiej żebyś skupił się na kluczowych rzeczach.
### Testy
* Pomóż mi sprawdzić, czy PR ma **testy**.
* Sprawdź, czy testy **nie przechodzą** przed PR. 🚨
* Następnie sprawdź, czy testy **przechodzą** po PR. ✅
* Wiele PR-ów nie ma testów, możesz **przypomnieć** im o dodaniu testów, a nawet **zaproponować** samemu jakieś testy. To jedna z rzeczy, które pochłaniają najwięcej czasu i możesz w tym bardzo pomóc.
* Następnie skomentuj również to, czego spróbowałeś, wtedy będę wiedział, że to sprawdziłeś. 🤓
## Utwórz Pull Request
Możesz [wnieść wkład](contributing.md){.internal-link target=_blank} do kodu źródłowego za pomocą Pull Requestu, na przykład:
* Naprawić literówkę, którą znalazłeś w dokumentacji.
* Podzielić się artykułem, filmem lub podcastem, który stworzyłeś lub znalazłeś na temat FastAPI, <a href="https://github.com/fastapi/fastapi/edit/master/docs/en/data/external_links.yml" class="external-link" target="_blank">edytując ten plik</a>.
* Upewnij się, że dodajesz swój link na początku odpowiedniej sekcji.
* Pomóc w [tłumaczeniu dokumentacji](contributing.md#translations){.internal-link target=_blank} na Twój język.
* Możesz również pomóc w weryfikacji tłumaczeń stworzonych przez innych.
* Zaproponować nowe sekcje dokumentacji.
* Naprawić istniejący problem/błąd.
* Upewnij się, że dodajesz testy.
* Dodać nową funkcję.
* Upewnij się, że dodajesz testy.
* Upewnij się, że dodajesz dokumentację, jeśli jest to istotne.
## Pomóż w utrzymaniu FastAPI
Pomóż mi utrzymać **FastAPI**! 🤓
Jest wiele pracy do zrobienia, a w większości przypadków **TY** możesz to zrobić.
Główne zadania, które możesz wykonać teraz to:
* [Pomóc innym z pytaniami na GitHubie](#pomagaj-innym-odpowiadajac-na-ich-pytania-na-githubie){.internal-link target=_blank} (zobacz sekcję powyżej).
* [Oceniać Pull Requesty](#przegladaj-pull-requesty){.internal-link target=_blank} (zobacz sekcję powyżej).
Te dwie czynności **zajmują najwięcej czasu**. To główna praca związana z utrzymaniem FastAPI.
Jeśli możesz mi w tym pomóc, **pomożesz mi utrzymać FastAPI** i zapewnisz że będzie **rozwijać się szybciej i lepiej**. 🚀
## Dołącz do czatu
Dołącz do 👥 <a href="https://discord.gg/VQjSZaeJmf" class="external-link" target="_blank">serwera czatu na Discordzie</a> 👥 i spędzaj czas z innymi w społeczności FastAPI.
/// tip | Wskazówka
Jeśli masz pytania, zadaj je w <a href="https://github.com/fastapi/fastapi/discussions/new?category=questions" class="external-link" target="_blank">Dyskusjach na GitHubie</a>, jest dużo większa szansa, że otrzymasz pomoc od [Ekspertów FastAPI](fastapi-people.md#fastapi-experts){.internal-link target=_blank}.
Używaj czatu tylko do innych ogólnych rozmów.
///
### Nie zadawaj pytań na czacie
Miej na uwadze, że ponieważ czaty pozwalają na bardziej "swobodną rozmowę", łatwo jest zadawać pytania, które są zbyt ogólne i trudniejsze do odpowiedzi, więc możesz nie otrzymać odpowiedzi.
Na GitHubie szablon poprowadzi Cię do napisania odpowiedniego pytania, dzięki czemu łatwiej uzyskasz dobrą odpowiedź, a nawet rozwiążesz problem samodzielnie, zanim zapytasz. Ponadto na GitHubie mogę się upewnić, że zawsze odpowiadam na wszystko, nawet jeśli zajmuje to trochę czasu. Osobiście nie mogę tego zrobić z systemami czatu. 😅
Rozmów w systemach czatu nie można tak łatwo przeszukiwać, jak na GitHubie, więc pytania i odpowiedzi mogą zaginąć w rozmowie. A tylko te na GitHubie liczą się do zostania [Ekspertem FastAPI](fastapi-people.md#fastapi-experts){.internal-link target=_blank}, więc najprawdopodobniej otrzymasz więcej uwagi na GitHubie.
Z drugiej strony w systemach czatu są tysiące użytkowników, więc jest duża szansa, że znajdziesz tam kogoś do rozmowy, prawie w każdej chwili. 😄
## Wspieraj autora
Możesz również finansowo wesprzeć autora (mnie) poprzez <a href="https://github.com/sponsors/tiangolo" class="external-link" target="_blank">sponsoring na GitHubie</a>.
Tam możesz postawić mi kawę ☕️ aby podziękować. 😄
Możesz także zostać srebrnym lub złotym sponsorem FastAPI. 🏅🎉
## Wspieraj narzędzia, które napędzają FastAPI
Jak widziałeś w dokumentacji, FastAPI stoi na ramionach gigantów, Starlette i Pydantic.
Możesz również wesprzeć:
* <a href="https://github.com/sponsors/samuelcolvin" class="external-link" target="_blank">Samuel Colvin (Pydantic)</a>
* <a href="https://github.com/sponsors/encode" class="external-link" target="_blank">Encode (Starlette, Uvicorn)</a>
---
Dziękuję! 🚀

View File

@@ -1,467 +0,0 @@
# FastAPI
<style>
.md-content .md-typeset h1 { display: none; }
</style>
<p align="center">
<a href="https://fastapi.tiangolo.com"><img src="https://fastapi.tiangolo.com/img/logo-margin/logo-teal.png" alt="FastAPI"></a>
</p>
<p align="center">
<em>FastAPI to szybki, prosty w nauce i gotowy do użycia w produkcji framework</em>
</p>
<p align="center">
<a href="https://github.com/fastapi/fastapi/actions?query=workflow%3ATest+event%3Apush+branch%3Amaster" target="_blank">
<img src="https://github.com/fastapi/fastapi/actions/workflows/test.yml/badge.svg?event=push&branch=master" alt="Test">
</a>
<a href="https://coverage-badge.samuelcolvin.workers.dev/redirect/fastapi/fastapi" target="_blank">
<img src="https://coverage-badge.samuelcolvin.workers.dev/fastapi/fastapi.svg" alt="Coverage">
</a>
<a href="https://pypi.org/project/fastapi" target="_blank">
<img src="https://img.shields.io/pypi/v/fastapi?color=%2334D058&label=pypi%20package" alt="Package version">
</a>
<a href="https://pypi.org/project/fastapi" target="_blank">
<img src="https://img.shields.io/pypi/pyversions/fastapi.svg?color=%2334D058" alt="Supported Python versions">
</a>
</p>
---
**Dokumentacja**: <a href="https://fastapi.tiangolo.com" target="_blank">https://fastapi.tiangolo.com</a>
**Kod żródłowy**: <a href="https://github.com/fastapi/fastapi" target="_blank">https://github.com/fastapi/fastapi</a>
---
FastAPI to nowoczesny, wydajny framework webowy do budowania API z użyciem Pythona bazujący na standardowym typowaniu Pythona.
Kluczowe cechy:
* **Wydajność**: FastAPI jest bardzo wydajny, na równi z **NodeJS** oraz **Go** (dzięki Starlette i Pydantic). [Jeden z najszybszych dostępnych frameworków Pythonowych](#wydajnosc).
* **Szybkość kodowania**: Przyśpiesza szybkość pisania nowych funkcjonalności o około 200% do 300%. *
* **Mniejsza ilość błędów**: Zmniejsza ilość ludzkich (dewelopera) błędy o około 40%. *
* **Intuicyjność**: Wspaniałe wsparcie dla edytorów kodu. Dostępne wszędzie <abbr title="znane jako auto-complete, autocompletion, IntelliSense">automatyczne uzupełnianie</abbr> kodu. Krótszy czas debugowania.
* **Łatwość**: Zaprojektowany by być prosty i łatwy do nauczenia. Mniej czasu spędzonego na czytanie dokumentacji.
* **Kompaktowość**: Minimalizacja powtarzającego się kodu. Wiele funkcjonalności dla każdej deklaracji parametru. Mniej błędów.
* **Solidność**: Kod gotowy dla środowiska produkcyjnego. Wraz z automatyczną interaktywną dokumentacją.
* **Bazujący na standardach**: Oparty na (i w pełni kompatybilny z) otwartych standardach API: <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank">OpenAPI</a> (wcześniej znane jako Swagger) oraz <a href="https://json-schema.org/" class="external-link" target="_blank">JSON Schema</a>.
<small>* oszacowania bazowane na testach wykonanych przez wewnętrzny zespół deweloperów, budujących aplikacie używane na środowisku produkcyjnym.</small>
## Sponsorzy
<!-- sponsors -->
{% if sponsors %}
{% for sponsor in sponsors.gold -%}
<a href="{{ sponsor.url }}" target="_blank" title="{{ sponsor.title }}"><img src="{{ sponsor.img }}" style="border-radius:15px"></a>
{% endfor -%}
{%- for sponsor in sponsors.silver -%}
<a href="{{ sponsor.url }}" target="_blank" title="{{ sponsor.title }}"><img src="{{ sponsor.img }}" style="border-radius:15px"></a>
{% endfor %}
{% endif %}
<!-- /sponsors -->
<a href="https://fastapi.tiangolo.com/fastapi-people/#sponsors" class="external-link" target="_blank">Inni sponsorzy</a>
## Opinie
"_[...] I'm using **FastAPI** a ton these days. [...] I'm actually planning to use it for all of my team's **ML services at Microsoft**. Some of them are getting integrated into the core **Windows** product and some **Office** products._"
<div style="text-align: right; margin-right: 10%;">Kabir Khan - <strong>Microsoft</strong> <a href="https://github.com/fastapi/fastapi/pull/26" target="_blank"><small>(ref)</small></a></div>
---
"_We adopted the **FastAPI** library to spawn a **REST** server that can be queried to obtain **predictions**. [for Ludwig]_"
<div style="text-align: right; margin-right: 10%;">Piero Molino, Yaroslav Dudin, and Sai Sumanth Miryala - <strong>Uber</strong> <a href="https://eng.uber.com/ludwig-v0-2/" target="_blank"><small>(ref)</small></a></div>
---
"_**Netflix** is pleased to announce the open-source release of our **crisis management** orchestration framework: **Dispatch**! [built with **FastAPI**]_"
<div style="text-align: right; margin-right: 10%;">Kevin Glisson, Marc Vilanova, Forest Monsen - <strong>Netflix</strong> <a href="https://netflixtechblog.com/introducing-dispatch-da4b8a2a8072" target="_blank"><small>(ref)</small></a></div>
---
"_Im over the moon excited about **FastAPI**. Its so fun!_"
<div style="text-align: right; margin-right: 10%;">Brian Okken - <strong><a href="https://pythonbytes.fm/episodes/show/123/time-to-right-the-py-wrongs?time_in_sec=855" target="_blank">Python Bytes</a> podcast host</strong> <a href="https://x.com/brianokken/status/1112220079972728832" target="_blank"><small>(ref)</small></a></div>
---
"_Honestly, what you've built looks super solid and polished. In many ways, it's what I wanted **Hug** to be - it's really inspiring to see someone build that._"
<div style="text-align: right; margin-right: 10%;">Timothy Crosley - <strong><a href="https://github.com/hugapi/hug" target="_blank">Hug</a> creator</strong> <a href="https://news.ycombinator.com/item?id=19455465" target="_blank"><small>(ref)</small></a></div>
---
"_If you're looking to learn one **modern framework** for building REST APIs, check out **FastAPI** [...] It's fast, easy to use and easy to learn [...]_"
"_We've switched over to **FastAPI** for our **APIs** [...] I think you'll like it [...]_"
<div style="text-align: right; margin-right: 10%;">Ines Montani - Matthew Honnibal - <strong><a href="https://explosion.ai" target="_blank">Explosion AI</a> founders - <a href="https://spacy.io" target="_blank">spaCy</a> creators</strong> <a href="https://x.com/_inesmontani/status/1144173225322143744" target="_blank"><small>(ref)</small></a> - <a href="https://x.com/honnibal/status/1144031421859655680" target="_blank"><small>(ref)</small></a></div>
---
## **Typer**, FastAPI aplikacji konsolowych
<a href="https://typer.tiangolo.com" target="_blank"><img src="https://typer.tiangolo.com/img/logo-margin/logo-margin-vector.svg" style="width: 20%;"></a>
Jeżeli tworzysz aplikacje <abbr title="aplikacja z interfejsem konsolowym">CLI</abbr>, która ma być używana w terminalu zamiast API, sprawdź <a href="https://typer.tiangolo.com/" class="external-link" target="_blank">**Typer**</a>.
**Typer** to młodsze rodzeństwo FastAPI. Jego celem jest pozostanie **FastAPI aplikacji konsolowych** . ⌨️ 🚀
## Wymagania
FastAPI oparty jest na:
* <a href="https://www.starlette.io/" class="external-link" target="_blank">Starlette</a> dla części webowej.
* <a href="https://docs.pydantic.dev/" class="external-link" target="_blank">Pydantic</a> dla części obsługujących dane.
## Instalacja
<div class="termy">
```console
$ pip install fastapi
---> 100%
```
</div>
Na serwerze produkcyjnym będziesz także potrzebował serwera ASGI, np. <a href="https://www.uvicorn.org" class="external-link" target="_blank">Uvicorn</a> lub <a href="https://github.com/pgjones/hypercorn" class="external-link" target="_blank">Hypercorn</a>.
<div class="termy">
```console
$ pip install "uvicorn[standard]"
---> 100%
```
</div>
## Przykład
### Stwórz
* Utwórz plik o nazwie `main.py` z:
```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}
```
<details markdown="1">
<summary>Albo użyj <code>async def</code>...</summary>
Jeżeli twój kod korzysta z `async` / `await`, użyj `async def`:
```Python hl_lines="9 14"
from typing import Union
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
async def read_root():
return {"Hello": "World"}
@app.get("/items/{item_id}")
async def read_item(item_id: int, q: Union[str, None] = None):
return {"item_id": item_id, "q": q}
```
**Przypis**:
Jeżeli nie znasz, sprawdź sekcję _"In a hurry?"_ o <a href="https://fastapi.tiangolo.com/async/#in-a-hurry" target="_blank">`async` i `await` w dokumentacji</a>.
</details>
### Uruchom
Uruchom serwer używając:
<div class="termy">
```console
$ uvicorn main:app --reload
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.
```
</div>
<details markdown="1">
<summary>O komendzie <code>uvicorn main:app --reload</code>...</summary>
Komenda `uvicorn main:app` odnosi się do:
* `main`: plik `main.py` ("moduł" w Pythonie).
* `app`: obiekt stworzony w `main.py` w lini `app = FastAPI()`.
* `--reload`: spraw by serwer resetował się po każdej zmianie w kodzie. Używaj tego tylko w środowisku deweloperskim.
</details>
### Wypróbuj
Otwórz link <a href="http://127.0.0.1:8000/items/5?q=somequery" class="external-link" target="_blank">http://127.0.0.1:8000/items/5?q=somequery</a> w przeglądarce.
Zobaczysz następującą odpowiedź JSON:
```JSON
{"item_id": 5, "q": "somequery"}
```
Właśnie stworzyłeś API które:
* Otrzymuje żądania HTTP w _ścieżce_ `/` i `/items/{item_id}`.
* Obie _ścieżki_ używają <em>operacji</em> `GET` (znane także jako _metody_ HTTP).
* _Ścieżka_ `/items/{item_id}` ma _parametr ścieżki_ `item_id` który powinien być obiektem typu `int`.
* _Ścieżka_ `/items/{item_id}` ma opcjonalny _parametr zapytania_ typu `str` o nazwie `q`.
### Interaktywna dokumentacja API
Otwórz teraz stronę <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
Zobaczysz automatyczną interaktywną dokumentację API (dostarczoną z pomocą <a href="https://github.com/swagger-api/swagger-ui" class="external-link" target="_blank">Swagger UI</a>):
![Swagger UI](https://fastapi.tiangolo.com/img/index/index-01-swagger-ui-simple.png)
### Alternatywna dokumentacja API
Otwórz teraz <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a>.
Zobaczysz alternatywną, lecz wciąż automatyczną dokumentację (wygenerowaną z pomocą <a href="https://github.com/Rebilly/ReDoc" class="external-link" target="_blank">ReDoc</a>):
![ReDoc](https://fastapi.tiangolo.com/img/index/index-02-redoc-simple.png)
## Aktualizacja przykładu
Zmodyfikuj teraz plik `main.py`, aby otrzmywał treść (body) żądania `PUT`.
Zadeklaruj treść żądania, używając standardowych typów w Pythonie dzięki Pydantic.
```Python hl_lines="4 9-12 25-27"
from typing import Union
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
price: float
is_offer: Union[bool, None] = None
@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}
@app.put("/items/{item_id}")
def update_item(item_id: int, item: Item):
return {"item_name": item.name, "item_id": item_id}
```
Serwer powinien przeładować się automatycznie (ponieważ dodałeś `--reload` do komendy `uvicorn` powyżej).
### Zaktualizowana interaktywna dokumentacja API
Wejdź teraz na <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
* Interaktywna dokumentacja API zaktualizuje sie automatycznie, także z nową treścią żądania (body):
![Swagger UI](https://fastapi.tiangolo.com/img/index/index-03-swagger-02.png)
* Kliknij przycisk "Try it out" (wypróbuj), pozwoli Ci to wypełnić parametry i bezpośrednio użyć API:
![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-04-swagger-03.png)
* Kliknij potem przycisk "Execute" (wykonaj), interfejs użytkownika połączy się z API, wyśle parametry, otrzyma odpowiedź i wyświetli ją na ekranie:
![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-05-swagger-04.png)
### Zaktualizowana alternatywna dokumentacja API
Otwórz teraz <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a>.
* Alternatywna dokumentacja również pokaże zaktualizowane parametry i treść żądania (body):
![ReDoc](https://fastapi.tiangolo.com/img/index/index-06-redoc-02.png)
### Podsumowanie
Podsumowując, musiałeś zadeklarować typy parametrów, treści żądania (body) itp. tylko **raz**, i są one dostępne jako parametry funkcji.
Robisz to tak samo jak ze standardowymi typami w Pythonie.
Nie musisz sie uczyć żadnej nowej składni, metod lub klas ze specyficznych bibliotek itp.
Po prostu standardowy **Python**.
Na przykład, dla danych typu `int`:
```Python
item_id: int
```
albo dla bardziej złożonego obiektu `Item`:
```Python
item: Item
```
...i z pojedyńczą deklaracją otrzymujesz:
* Wsparcie edytorów kodu, wliczając:
* Auto-uzupełnianie.
* Sprawdzanie typów.
* Walidacja danych:
* Automatyczne i przejrzyste błędy gdy dane są niepoprawne.
* Walidacja nawet dla głęboko zagnieżdżonych obiektów JSON.
* <abbr title="znane również jako: serializacja, przetwarzanie, marshalling">Konwersja</abbr> danych wejściowych: przychodzących z sieci na Pythonowe typy. Pozwala na przetwarzanie danych:
* JSON.
* Parametrów ścieżki.
* Parametrów zapytania.
* Dane cookies.
* Dane nagłówków (headers).
* Formularze.
* Pliki.
* <abbr title="znane również jako: serializacja, przetwarzanie, marshalling">Konwersja</abbr> danych wyjściowych: wychodzących z Pythona do sieci (jako JSON):
* Przetwarzanie Pythonowych typów (`str`, `int`, `float`, `bool`, `list`, itp).
* Obiekty `datetime`.
* Obiekty `UUID`.
* Modele baz danych.
* ...i wiele więcej.
* Automatyczne interaktywne dokumentacje API, wliczając 2 alternatywne interfejsy użytkownika:
* Swagger UI.
* ReDoc.
---
Wracając do poprzedniego przykładu, **FastAPI** :
* Potwierdzi, że w ścieżce jest `item_id` dla żądań `GET` i `PUT`.
* Potwierdzi, że `item_id` jest typu `int` dla żądań `GET` i `PUT`.
* Jeżeli nie jest, odbiorca zobaczy przydatną, przejrzystą wiadomość z błędem.
* Sprawdzi czy w ścieżce jest opcjonalny parametr zapytania `q` (np. `http://127.0.0.1:8000/items/foo?q=somequery`) dla żądania `GET`.
* Jako że parametr `q` jest zadeklarowany jako `= None`, jest on opcjonalny.
* Gdyby tego `None` nie było, parametr ten byłby wymagany (tak jak treść żądania w żądaniu `PUT`).
* Dla żądania `PUT` z ścieżką `/items/{item_id}`, odczyta treść żądania jako JSON:
* Sprawdzi czy posiada wymagany atrybut `name`, który powinien być typu `str`.
* Sprawdzi czy posiada wymagany atrybut `price`, który musi być typu `float`.
* Sprawdzi czy posiada opcjonalny atrybut `is_offer`, który (jeżeli obecny) powinien być typu `bool`.
* To wszystko będzie również działać dla głęboko zagnieżdżonych obiektów JSON.
* Automatycznie konwertuje z i do JSON.
* Dokumentuje wszystko w OpenAPI, które może być używane przez:
* Interaktywne systemy dokumentacji.
* Systemy automatycznego generowania kodu klienckiego, dla wielu języków.
* Dostarczy bezpośrednio 2 interaktywne dokumentacje webowe.
---
To dopiero początek, ale już masz mniej-więcej pojęcie jak to wszystko działa.
Spróbuj zmienić linijkę:
```Python
return {"item_name": item.name, "item_id": item_id}
```
...z:
```Python
... "item_name": item.name ...
```
...na:
```Python
... "item_price": item.price ...
```
...i zobacz jak edytor kodu automatycznie uzupełni atrybuty i będzie znał ich typy:
![editor support](https://fastapi.tiangolo.com/img/vscode-completion.png)
Dla bardziej kompletnych przykładów posiadających więcej funkcjonalności, zobacz <a href="https://fastapi.tiangolo.com/tutorial/">Tutorial - User Guide</a>.
**Uwaga Spoiler**: tutorial - user guide zawiera:
* Deklaracje **parametrów** z innych miejsc takich jak: **nagłówki**, **pliki cookies**, **formularze** i **pliki**.
* Jak ustawić **ograniczenia walidacyjne** takie jak `maksymalna długość` lub `regex`.
* Potężny i łatwy w użyciu system **<abbr title="znane jako komponenty, resources, providers, services, injectables">Dependency Injection</abbr>**.
* Zabezpieczenia i autentykacja, wliczając wsparcie dla **OAuth2** z **tokenami JWT** oraz autoryzacją **HTTP Basic**.
* Bardziej zaawansowane (ale równie proste) techniki deklarowania **głęboko zagnieżdżonych modeli JSON** (dzięki Pydantic).
* Wiele dodatkowych funkcji (dzięki Starlette) takie jak:
* **WebSockety**
* **GraphQL**
* bardzo proste testy bazujące na HTTPX oraz `pytest`
* **CORS**
* **Sesje cookie**
* ...i więcej.
## Wydajność
Niezależne benchmarki TechEmpower pokazują, że **FastAPI** (uruchomiony na serwerze Uvicorn) <a href="https://www.techempower.com/benchmarks/#section=test&runid=7464e520-0dc2-473d-bd34-dbdfd7e85911&hw=ph&test=query&l=zijzen-7" class="external-link" target="_blank">jest jednym z najszybszych dostępnych Pythonowych frameworków</a>, zaraz po Starlette i Uvicorn (używanymi wewnątrznie przez FastAPI). (*)
Aby dowiedzieć się o tym więcej, zobacz sekcję <a href="https://fastapi.tiangolo.com/benchmarks/" class="internal-link" target="_blank">Benchmarks</a>.
## Opcjonalne zależności
Używane przez Pydantic:
* <a href="https://github.com/JoshData/python-email-validator" target="_blank"><code>email-validator</code></a> - dla walidacji adresów email.
Używane przez Starlette:
* <a href="https://www.python-httpx.org" target="_blank"><code>httpx</code></a> - Wymagane jeżeli chcesz korzystać z `TestClient`.
* <a href="https://github.com/Tinche/aiofiles" target="_blank"><code>aiofiles</code></a> - Wymagane jeżeli chcesz korzystać z `FileResponse` albo `StaticFiles`.
* <a href="https://jinja.palletsprojects.com" target="_blank"><code>jinja2</code></a> - Wymagane jeżeli chcesz używać domyślnej konfiguracji szablonów.
* <a href="https://github.com/Kludex/python-multipart" target="_blank"><code>python-multipart</code></a> - Wymagane jeżelich chcesz wsparcie <abbr title="przetwarzania stringa którzy przychodzi z żądaniem HTTP na dane używane przez Pythona">"parsowania"</abbr> formularzy, używając `request.form()`.
* <a href="https://pythonhosted.org/itsdangerous/" target="_blank"><code>itsdangerous</code></a> - Wymagany dla wsparcia `SessionMiddleware`.
* <a href="https://pyyaml.org/wiki/PyYAMLDocumentation" target="_blank"><code>pyyaml</code></a> - Wymagane dla wsparcia `SchemaGenerator` z Starlette (z FastAPI prawdopodobnie tego nie potrzebujesz).
* <a href="https://graphene-python.org/" target="_blank"><code>graphene</code></a> - Wymagane dla wsparcia `GraphQLApp`.
Używane przez FastAPI / Starlette:
* <a href="https://www.uvicorn.org" target="_blank"><code>uvicorn</code></a> - jako serwer, który ładuje i obsługuje Twoją aplikację.
* <a href="https://github.com/ijl/orjson" target="_blank"><code>orjson</code></a> - Wymagane jeżeli chcesz używać `ORJSONResponse`.
* <a href="https://github.com/esnme/ultrajson" target="_blank"><code>ujson</code></a> - Wymagane jeżeli chcesz korzystać z `UJSONResponse`.
Możesz zainstalować wszystkie te aplikacje przy pomocy `pip install fastapi[all]`.
## Licencja
Ten projekt jest na licencji MIT.

View File

@@ -1,335 +0,0 @@
# Pierwsze kroki
Najprostszy plik FastAPI może wyglądać tak:
{* ../../docs_src/first_steps/tutorial001.py *}
Skopiuj to do pliku `main.py`.
Uruchom serwer:
<div class="termy">
```console
$ uvicorn main:app --reload
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
<span style="color: green;">INFO</span>: Started reloader process [28720]
<span style="color: green;">INFO</span>: Started server process [28722]
<span style="color: green;">INFO</span>: Waiting for application startup.
<span style="color: green;">INFO</span>: Application startup complete.
```
</div>
/// note
Polecenie `uvicorn main:app` odnosi się do:
* `main`: plik `main.py` ("moduł" Python).
* `app`: obiekt utworzony w pliku `main.py` w lini `app = FastAPI()`.
* `--reload`: sprawia, że serwer uruchamia się ponownie po zmianie kodu. Używany tylko w trakcie tworzenia oprogramowania.
///
Na wyjściu znajduje się linia z czymś w rodzaju:
```hl_lines="4"
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
```
Ta linia pokazuje adres URL, pod którym Twoja aplikacja jest obsługiwana, na Twoim lokalnym komputerze.
### Sprawdź to
Otwórz w swojej przeglądarce <a href="http://127.0.0.1:8000" class="external-link" target="_blank">http://127.0.0.1:8000</a>.
Zobaczysz odpowiedź w formacie JSON:
```JSON
{"message": "Hello World"}
```
### Interaktywna dokumentacja API
Przejdź teraz do <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
Zobaczysz automatyczną i interaktywną dokumentację API (dostarczoną przez <a href="https://github.com/swagger-api/swagger-ui" class="external-link" target="_blank">Swagger UI</a>):
![Swagger UI](https://fastapi.tiangolo.com/img/index/index-01-swagger-ui-simple.png)
### Alternatywna dokumentacja API
Teraz przejdź do <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a>.
Zobaczysz alternatywną automatycznie wygenerowaną dokumentację API (dostarczoną przez <a href="https://github.com/Rebilly/ReDoc" class="external-link" target="_blank">ReDoc</a>):
![ReDoc](https://fastapi.tiangolo.com/img/index/index-02-redoc-simple.png)
### OpenAPI
**FastAPI** generuje "schemat" z całym Twoim API przy użyciu standardu **OpenAPI** służącego do definiowania API.
#### Schema
"Schema" jest definicją lub opisem czegoś. Nie jest to kod, który go implementuje, ale po prostu abstrakcyjny opis.
#### API "Schema"
W typ przypadku, <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank">OpenAPI</a> to specyfikacja, która dyktuje sposób definiowania schematu interfejsu API.
Definicja schematu zawiera ścieżki API, możliwe parametry, które są przyjmowane przez endpointy, itp.
#### "Schemat" danych
Termin "schemat" może również odnosić się do wyglądu niektórych danych, takich jak zawartość JSON.
W takim przypadku będzie to oznaczać atrybuty JSON, ich typy danych itp.
#### OpenAPI i JSON Schema
OpenAPI definiuje API Schema dla Twojego API, który zawiera definicje (lub "schematy") danych wysyłanych i odbieranych przez Twój interfejs API przy użyciu **JSON Schema**, standardu dla schematów danych w formacie JSON.
#### Sprawdź `openapi.json`
Jeśli jesteś ciekawy, jak wygląda surowy schemat OpenAPI, FastAPI automatycznie generuje JSON Schema z opisami wszystkich Twoich API.
Możesz to zobaczyć bezpośrednio pod adresem: <a href="http://127.0.0.1:8000/openapi.json" class="external-link" target="_blank">http://127.0.0.1:8000/openapi.json</a>.
Zobaczysz JSON zaczynający się od czegoś takiego:
```JSON
{
"openapi": "3.0.2",
"info": {
"title": "FastAPI",
"version": "0.1.0"
},
"paths": {
"/items/": {
"get": {
"responses": {
"200": {
"description": "Successful Response",
"content": {
"application/json": {
...
```
#### Do czego służy OpenAPI
Schemat OpenAPI jest tym, co zasila dwa dołączone interaktywne systemy dokumentacji.
Istnieją dziesiątki alternatyw, wszystkie oparte na OpenAPI. Możesz łatwo dodać dowolną z nich do swojej aplikacji zbudowanej za pomocą **FastAPI**.
Możesz go również użyć do automatycznego generowania kodu dla klientów, którzy komunikują się z Twoim API. Na przykład aplikacje frontendowe, mobilne lub IoT.
## Przypomnijmy, krok po kroku
### Krok 1: zaimportuj `FastAPI`
{* ../../docs_src/first_steps/tutorial001.py hl[1] *}
`FastAPI` jest klasą, która zapewnia wszystkie funkcjonalności Twojego API.
/// note | Szczegóły techniczne
`FastAPI` jest klasą, która dziedziczy bezpośrednio z `Starlette`.
Oznacza to, że możesz korzystać ze wszystkich funkcjonalności <a href="https://www.starlette.io/" class="external-link" target="_blank">Starlette</a> również w `FastAPI`.
///
### Krok 2: utwórz instancję `FastAPI`
{*../../docs_src/first_steps/tutorial001.py hl[3] *}
Zmienna `app` będzie tutaj "instancją" klasy `FastAPI`.
Będzie to główny punkt interakcji przy tworzeniu całego interfejsu API.
Ta zmienna `app` jest tą samą zmienną, do której odnosi się `uvicorn` w poleceniu:
<div class="termy">
```console
$ uvicorn main:app --reload
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
```
</div>
Jeśli stworzysz swoją aplikację, np.:
{* ../../docs_src/first_steps/tutorial002.py hl[3] *}
I umieścisz to w pliku `main.py`, to będziesz mógł tak wywołać `uvicorn`:
<div class="termy">
```console
$ uvicorn main:my_awesome_api --reload
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
```
</div>
### Krok 3: wykonaj *operację na ścieżce*
#### Ścieżka
"Ścieżka" tutaj odnosi się do ostatniej części adresu URL, zaczynając od pierwszego `/`.
Więc, w adresie URL takim jak:
```
https://example.com/items/foo
```
...ścieżką będzie:
```
/items/foo
```
/// info
"Ścieżka" jest zazwyczaj nazywana "path", "endpoint" lub "route'.
///
Podczas budowania API, "ścieżka" jest głównym sposobem na oddzielenie "odpowiedzialności" i „zasobów”.
#### Operacje
"Operacje" tutaj odnoszą się do jednej z "metod" HTTP.
Jedna z:
* `POST`
* `GET`
* `PUT`
* `DELETE`
...i te bardziej egzotyczne:
* `OPTIONS`
* `HEAD`
* `PATCH`
* `TRACE`
W protokole HTTP można komunikować się z każdą ścieżką za pomocą jednej (lub więcej) "metod".
---
Podczas tworzenia API zwykle używasz tych metod HTTP do wykonania określonej akcji.
Zazwyczaj używasz:
* `POST`: do tworzenia danych.
* `GET`: do odczytywania danych.
* `PUT`: do aktualizacji danych.
* `DELETE`: do usuwania danych.
Tak więc w OpenAPI każda z metod HTTP nazywana jest "operacją".
Będziemy je również nazywali "**operacjami**".
#### Zdefiniuj *dekorator operacji na ścieżce*
{* ../../docs_src/first_steps/tutorial001.py hl[6] *}
`@app.get("/")` mówi **FastAPI** że funkcja poniżej odpowiada za obsługę żądań, które trafiają do:
* ścieżki `/`
* używając <abbr title="metoda HTTP GET">operacji <code>get</code></abbr>
/// info | `@decorator` Info
Składnia `@something` jest w Pythonie nazywana "dekoratorem".
Umieszczasz to na szczycie funkcji. Jak ładną ozdobną czapkę (chyba stąd wzięła się nazwa).
"Dekorator" przyjmuje funkcję znajdującą się poniżej jego i coś z nią robi.
W naszym przypadku dekorator mówi **FastAPI**, że poniższa funkcja odpowiada **ścieżce** `/` z **operacją** `get`.
Jest to "**dekorator operacji na ścieżce**".
///
Możesz również użyć innej operacji:
* `@app.post()`
* `@app.put()`
* `@app.delete()`
Oraz tych bardziej egzotycznych:
* `@app.options()`
* `@app.head()`
* `@app.patch()`
* `@app.trace()`
/// tip
Możesz dowolnie używać każdej operacji (metody HTTP).
**FastAPI** nie narzuca żadnego konkretnego znaczenia.
Informacje tutaj są przedstawione jako wskazówka, a nie wymóg.
Na przykład, używając GraphQL, normalnie wykonujesz wszystkie akcje używając tylko operacji `POST`.
///
### Krok 4: zdefiniuj **funkcję obsługującą ścieżkę**
To jest nasza "**funkcja obsługująca ścieżkę**":
* **ścieżka**: to `/`.
* **operacja**: to `get`.
* **funkcja**: to funkcja poniżej "dekoratora" (poniżej `@app.get("/")`).
{* ../../docs_src/first_steps/tutorial001.py hl[7] *}
Jest to funkcja Python.
Zostanie ona wywołana przez **FastAPI** za każdym razem, gdy otrzyma żądanie do adresu URL "`/`" przy użyciu operacji `GET`.
W tym przypadku jest to funkcja "asynchroniczna".
---
Możesz również zdefiniować to jako normalną funkcję zamiast `async def`:
{* ../../docs_src/first_steps/tutorial003.py hl[7] *}
/// note
Jeśli nie znasz różnicy, sprawdź [Async: *"In a hurry?"*](../async.md#in-a-hurry){.internal-link target=_blank}.
///
### Krok 5: zwróć zawartość
{* ../../docs_src/first_steps/tutorial001.py hl[8] *}
Możesz zwrócić `dict`, `list`, pojedynczą wartość jako `str`, `int`, itp.
Możesz również zwrócić modele Pydantic (więcej o tym później).
Istnieje wiele innych obiektów i modeli, które zostaną automatycznie skonwertowane do formatu JSON (w tym ORM itp.). Spróbuj użyć swoich ulubionych, jest bardzo prawdopodobne, że są już obsługiwane.
## Podsumowanie
* Zaimportuj `FastAPI`.
* Stwórz instancję `app`.
* Dodaj **dekorator operacji na ścieżce** (taki jak `@app.get("/")`).
* Napisz **funkcję obsługującą ścieżkę** (taką jak `def root(): ...` powyżej).
* Uruchom serwer deweloperski (`uvicorn main:app --reload`).

View File

@@ -1,83 +0,0 @@
# Samouczek
Ten samouczek pokaże Ci, krok po kroku, jak używać większości funkcji **FastAPI**.
Każda część korzysta z poprzednich, ale jest jednocześnie osobnym tematem. Możesz przejść bezpośrednio do każdego rozdziału, jeśli szukasz rozwiązania konkretnego problemu.
Samouczek jest tak zbudowany, żeby służył jako punkt odniesienia w przyszłości.
Możesz wracać i sprawdzać dokładnie to czego potrzebujesz.
## Wykonywanie kodu
Wszystkie fragmenty kodu mogą być skopiowane bezpośrednio i użyte (są poprawnymi i przetestowanymi plikami).
Żeby wykonać każdy przykład skopiuj kod to pliku `main.py` i uruchom `uvicorn` za pomocą:
<div class="termy">
```console
$ uvicorn main:app --reload
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
<span style="color: green;">INFO</span>: Started reloader process [28720]
<span style="color: green;">INFO</span>: Started server process [28722]
<span style="color: green;">INFO</span>: Waiting for application startup.
<span style="color: green;">INFO</span>: Application startup complete.
```
</div>
**BARDZO zalecamy** pisanie bądź kopiowanie kodu, edycję, a następnie wykonywanie go lokalnie.
Użycie w Twoim edytorze jest tym, co pokazuje prawdziwe korzyści z FastAPI, pozwala zobaczyć jak mało kodu musisz napisać, wszystkie funkcje, takie jak kontrola typów, <abbr title="auto-complete, autocompletion, IntelliSense">automatyczne uzupełnianie</abbr>, itd.
---
## Instalacja FastAPI
Jako pierwszy krok zainstaluj FastAPI.
Na potrzeby samouczka możesz zainstalować również wszystkie opcjonalne biblioteki:
<div class="termy">
```console
$ pip install "fastapi[all]"
---> 100%
```
</div>
...wliczając w to `uvicorn`, który będzie służył jako serwer wykonujacy Twój kod.
/// note
Możesz również wykonać instalację "krok po kroku".
Prawdopodobnie zechcesz to zrobić, kiedy będziesz wdrażać swoją aplikację w środowisku produkcyjnym:
```
pip install fastapi
```
Zainstaluj też `uvicorn`, który będzie służył jako serwer:
```
pip install "uvicorn[standard]"
```
Tak samo możesz zainstalować wszystkie dodatkowe biblioteki, których chcesz użyć.
///
## Zaawansowany poradnik
Jest też **Zaawansowany poradnik**, który możesz przeczytać po lekturze tego **Samouczka**.
**Zaawansowany poradnik** opiera się na tym samouczku, używa tych samych pojęć, żeby pokazać Ci kilka dodatkowych funkcji.
Najpierw jednak powinieneś przeczytać **Samouczek** (czytasz go teraz).
Ten rozdział jest zaprojektowany tak, że możesz stworzyć kompletną aplikację używając tylko informacji tutaj zawartych, a następnie rozszerzać ją na różne sposoby, w zależności od potrzeb, używając kilku dodatkowych pomysłów z **Zaawansowanego poradnika**.

View File

@@ -1 +0,0 @@
INHERIT: ../en/mkdocs.yml

503
docs/ru/docs/_llm-test.md Normal file
View File

@@ -0,0 +1,503 @@
# Тестовый файл LLM { #llm-test-file }
Этот документ проверяет, понимает ли <abbr title="Large Language Model Большая языковая модель">LLM</abbr>, переводящая документацию, `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 больше не вносит изменений в перевод. Это означает, что общий промпт и ваш языковой специфичный промпт максимально хороши (иногда он будет делать несколько, казалось бы, случайных изменений, причина в том, что <a href="https://doublespeak.chat/#/handbook#deterministic-output" class="external-link" target="_blank">LLM — недетерминированные алгоритмы</a>).
Тесты:
## Фрагменты кода { #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
$ <font color="#4E9A06">fastapi</font> run <u style="text-decoration-style:solid">main.py</u>
<span style="background-color:#009485"><font color="#D3D7CF"> FastAPI </font></span> 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 | Информация
Некоторый текст
///
/// note | Примечание
Некоторый текст
///
/// note | Технические подробности
Некоторый текст
///
/// check | Проверка
Некоторый текст
///
/// tip | Совет
Некоторый текст
///
/// warning | Предупреждение
Некоторый текст
///
/// danger | Опасность
Некоторый текст
///
////
//// 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}
* <a href="https://sqlmodel.tiangolo.com/" class="external-link" target="_blank">Внешняя ссылка</a>
* <a href="https://fastapi.tiangolo.com/css/styles.css" class="external-link" target="_blank">Ссылка на стиль</a>
* <a href="https://fastapi.tiangolo.com/js/logic.js" class="external-link" target="_blank">Ссылка на скрипт</a>
* <a href="https://fastapi.tiangolo.com/img/foo.jpg" class="external-link" target="_blank">Ссылка на изображение</a>
Текст ссылок должен переводиться, адрес ссылки должен указывать на перевод:
* <a href="https://fastapi.tiangolo.com/ru/" class="external-link" target="_blank">Ссылка на FastAPI</a>
////
//// tab | Информация
Ссылки должны переводиться, но их адреса не должны изменяться. Исключение — абсолютные ссылки на страницы документации FastAPI. В этом случае ссылка должна вести на перевод.
См. раздел `### Links` в общем промпте в `scripts/translate.py`.
////
## HTML-элементы "abbr" { #html-abbr-elements }
//// tab | Тест
Вот некоторые элементы, обёрнутые в HTML-элементы "abbr" (часть выдумана):
### abbr даёт полную расшифровку { #the-abbr-gives-a-full-phrase }
* <abbr title="Getting Things Done Как привести дела в порядок">GTD</abbr>
* <abbr title="less than меньше чем"><code>lt</code></abbr>
* <abbr title="XML Web Token XML веб‑токен">XWT</abbr>
* <abbr title="Parallel Server Gateway Interface Параллельный серверный интерфейс шлюза">PSGI</abbr>
### abbr даёт объяснение { #the-abbr-gives-an-explanation }
* <abbr title="Группа машин, которые настроены на соединение и совместную работу определённым образом.">кластер</abbr>
* <abbr title="Метод машинного обучения, который использует искусственные нейронные сети с многочисленными скрытыми слоями между входным и выходным слоями, тем самым формируя сложную внутреннюю структуру">Глубокое обучение</abbr>
### abbr даёт полную расшифровку и объяснение { #the-abbr-gives-a-full-phrase-and-an-explanation }
* <abbr title="Mozilla Developer Network Сеть разработчиков Mozilla: документация для разработчиков, созданная командой Firefox">MDN</abbr>
* <abbr title="Input/Output Ввод/Вывод: чтение или запись на диск, сетевое взаимодействие.">I/O</abbr>.
////
//// tab | Информация
Атрибуты "title" элементов "abbr" переводятся по определённым правилам.
Переводы могут добавлять свои собственные элементы "abbr", которые LLM не должна удалять. Например, чтобы объяснить английские слова.
См. раздел `### HTML abbr elements` в общем промпте в `scripts/translate.py`.
////
## Заголовки { #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 Basic
* HTTP Digest
* формат ISO
* стандарт JSON Schema
* JSON-схема
* определение схемы
* password flow
* Мобильный
* устаревший
* спроектированный
* некорректный
* на лету
* стандарт
* по умолчанию
* чувствительный к регистру
* нечувствительный к регистру
* обслуживать приложение
* отдавать страницу
* приложение
* приложение
* HTTP-запрос
* HTTP-ответ
* ответ с ошибкой
* операция пути
* декоратор операции пути
* функция-обработчик пути
* тело
* тело запроса
* тело ответа
* JSON-тело
* тело формы
* тело файла
* тело функции
* параметр
* body-параметр
* path-параметр
* query-параметр
* cookie-параметр
* параметр заголовка
* параметр формы
* параметр функции
* событие
* событие запуска
* запуск сервера
* событие остановки
* событие lifespan
* обработчик
* обработчик события
* обработчик исключений
* обрабатывать
* модель
* Pydantic-модель
* модель данных
* модель базы данных
* модель формы
* объект модели
* класс
* базовый класс
* родительский класс
* подкласс
* дочерний класс
* родственный класс
* метод класса
* заголовок
* HTTP-заголовки
* заголовок авторизации
* заголовок `Authorization`
* заголовок `Forwarded`
* система внедрения зависимостей
* зависимость
* зависимый объект
* зависимый
* ограниченный вводом/выводом
* ограниченный процессором
* конкурентность
* параллелизм
* многопроцессность
* переменная окружения
* переменная окружения
* `PATH`
* переменная `PATH`
* аутентификация
* провайдер аутентификации
* авторизация
* форма авторизации
* провайдер авторизации
* пользователь аутентифицируется
* система аутентифицирует пользователя
* CLI
* интерфейс командной строки
* сервер
* клиент
* облачный провайдер
* облачный сервис
* разработка
* этапы разработки
* dict
* словарь
* перечисление
* enum
* член перечисления
* кодировщик
* декодировщик
* кодировать
* декодировать
* исключение
* вызвать
* выражение
* оператор
* фронтенд
* бэкенд
* обсуждение на GitHub
* Issue на GitHub (тикет/обращение)
* производительность
* оптимизация производительности
* тип возвращаемого значения
* возвращаемое значение
* безопасность
* схема безопасности
* задача
* фоновая задача
* функция задачи
* шаблон
* шаблонизатор
* аннотация типов
* аннотация типов
* воркер сервера
* воркер Uvicorn
* воркер Gunicorn
* воркер-процесс
* класс воркера
* рабочая нагрузка
* деплой
* развернуть
* SDK
* набор средств разработки ПО
* `APIRouter`
* `requirements.txt`
* токен Bearer
* несовместимое изменение
* баг
* кнопка
* вызываемый объект
* код
* коммит
* менеджер контекста
* корутина
* сессия базы данных
* диск
* домен
* движок
* фиктивный X
* метод HTTP GET
* элемент
* библиотека
* lifespan
* блокировка
* middleware (Промежуточный слой)
* мобильное приложение
* модуль
* монтирование
* сеть
* origin (источник)
* переопределение
* полезная нагрузка
* процессор
* свойство
* прокси
* пулл-реквест (запрос на изменение)
* запрос
* ОЗУ
* удалённая машина
* статус-код
* строка
* тег
* веб‑фреймворк
* подстановочный знак
* вернуть
* валидировать
////
//// tab | Информация
Это неполный и ненормативный список (в основном) технических терминов, встречающихся в документации. Он может помочь автору промпта понять, по каким терминам LLM нужна подсказка. Например, когда она продолжает возвращать действительно хороший перевод к неоптимальному. Или когда у неё возникают проблемы со склонением/спряжением термина на вашем языке.
См., например, раздел `### List of English terms and their preferred German translations` в `docs/de/llm-prompt.md`.
////

View File

@@ -1,3 +1,3 @@
# О проекте
# О проекте { #about }
FastAPI: внутреннее устройство, повлиявшие технологии и всё такое прочее. 🤓
О FastAPI, его дизайне, источниках вдохновения и многом другом. 🤓

View File

@@ -0,0 +1,247 @@
# Дополнительные ответы в OpenAPI { #additional-responses-in-openapi }
/// warning | Предупреждение
Это довольно продвинутая тема.
Если вы только начинаете работать с **FastAPI**, возможно, вам это пока не нужно.
///
Вы можете объявлять дополнительные ответы с дополнительными статус-кодами, типами содержимого, описаниями и т.д.
Эти дополнительные ответы будут включены в схему OpenAPI, и поэтому появятся в документации API.
Но для таких дополнительных ответов убедитесь, что вы возвращаете `Response`, например `JSONResponse`, напрямую, со своим статус-кодом и содержимым.
## Дополнительный ответ с `model` { #additional-response-with-model }
Вы можете передать вашим декораторам операции пути параметр `responses`.
Он принимает `dict`: ключи — это статус-коды для каждого ответа (например, `200`), а значения — другие `dict` с информацией для каждого из них.
Каждый из этих `dict` для ответа может иметь ключ `model`, содержащий Pydantic-модель, аналогично `response_model`.
**FastAPI** возьмёт эту модель, сгенерирует для неё JSONсхему и включит её в нужное место в OpenAPI.
Например, чтобы объявить ещё один ответ со статус-кодом `404` и Pydantic-моделью `Message`, можно написать:
{* ../../docs_src/additional_responses/tutorial001.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.py hl[19:24,28] *}
/// 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.py hl[20:31] *}
Всё это будет объединено и включено в ваш OpenAPI и отображено в документации API:
<img src="/img/tutorial/additional-responses/image01.png">
## Комбинирование предопределённых и пользовательских ответов { #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.py hl[13:17,26] *}
## Дополнительная информация об ответах OpenAPI { #more-information-about-openapi-responses }
Чтобы увидеть, что именно можно включать в ответы, посмотрите эти разделы спецификации OpenAPI:
* <a href="https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#responses-object" class="external-link" target="_blank">Объект Responses OpenAPI</a>, он включает `Response Object`.
* <a href="https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#response-object" class="external-link" target="_blank">Объект Response OpenAPI</a>, вы можете включить всё из этого объекта напрямую в каждый ответ внутри вашего параметра `responses`. Включая `description`, `headers`, `content` (внутри него вы объявляете разные типы содержимого и JSONсхемы) и `links`.

View File

@@ -1,28 +1,28 @@
# Дополнительные статус коды
# Дополнительные статус-коды { #additional-status-codes }
По умолчанию **FastAPI** возвращает ответы, используя `JSONResponse`, помещая содержимое, которое вы возвращаете из вашей *операции пути*, внутрь этого `JSONResponse`.
По умолчанию **FastAPI** будет возвращать ответы, используя `JSONResponse`, помещая содержимое, которое вы возвращаете из вашей *операции пути*, внутрь этого `JSONResponse`.
Он будет использовать код статуса по умолчанию или тот, который вы укажете в вашей *операции пути*.
Он будет использовать статус-код по умолчанию или тот, который вы укажете в вашей *операции пути*.
## Дополнительные статус коды
## Дополнительные статус-коды { #additional-status-codes_1 }
Если вы хотите возвращать дополнительный статус код помимо основного, вы можете сделать это, возвращая объект `Response` напрямую, как `JSONResponse`, и устанавливая нужный статус код напрямую.
Если вы хотите возвращать дополнительные статус-коды помимо основного, вы можете сделать это, возвращая `Response` напрямую, например `JSONResponse`, и устанавливая дополнительный статус-код напрямую.
Например, скажем, вы хотите создать *операцию пути*, которая позволяет обновлять элементы и возвращает HTTP-код 200 "OK" при успешном выполнении.
Например, предположим, что вы хотите иметь *операцию пути*, которая позволяет обновлять элементы и возвращает HTTP статус-код 200 «OK» при успешном выполнении.
Но вы также хотите, чтобы она принимала новые элементы. И если элемент ранее не существовал, он создаётся, и возвращался HTTP-код 201 "Created".
Но вы также хотите, чтобы она принимала новые элементы. И если элементы ранее не существовали, она создаёт их и возвращает HTTP статус-код 201 «Created».
Чтобы реализовать это, импортируйте `JSONResponse` и возвращайте ваш контент напрямую, устанавливая нужный `status_code`:
Чтобы добиться этого, импортируйте `JSONResponse` и верните туда свой контент напрямую, установив нужный вам `status_code`:
{* ../../docs_src/additional_status_codes/tutorial001_an_py310.py hl[4,25] *}
/// warning | Внимание
Когда вы возвращаете объект `Response` напрямую, как в примере выше, он будет возвращён как есть.
Когда вы возвращаете `Response` напрямую, как в примере выше, он будет возвращён как есть.
Он не будет сериализован при помощи модели и т.д.
Он не будет сериализован с помощью модели и т.п.
Убедитесь, что в нём содержатся именно те данные, которые вы хотите, и что значения являются валидным JSON (если вы используете `JSONResponse`).
Убедитесь, что в нём именно те данные, которые вы хотите, и что значения являются валидным JSON (если вы используете `JSONResponse`).
///
@@ -30,12 +30,12 @@
Вы также можете использовать `from starlette.responses import JSONResponse`.
**FastAPI** предоставляет тот же `starlette.responses` через `fastapi.responses` просто для вашего удобства, как разработчика. Но большинство доступных Response-классов поступают напрямую из Starlette. То же самое касается и `status`.
**FastAPI** предоставляет тот же `starlette.responses` через `fastapi.responses` просто для вашего удобства как разработчика. Но большинство доступных Response-классов приходят напрямую из Starlette. То же самое со `status`.
///
## OpenAPI и документация API
## OpenAPI и документация API { #openapi-and-api-docs }
Если вы возвращаете дополнительные коды статусов и ответы напрямую, они не будут включены в схему OpenAPI (документацию API), потому что FastAPI не может заранее знать, что вы собираетесь вернуть.
Если вы возвращаете дополнительные статус-коды и ответы напрямую, они не будут включены в схему OpenAPI (документацию API), потому что у FastAPI нет способа заранее знать, что вы собираетесь вернуть.
Но вы можете задокументировать это в вашем коде, используя: [Дополнительные ответы в OpenAPI](additional-responses.md){.internal-link target=_blank}.
Но вы можете задокументировать это в своём коде, используя: [Дополнительные ответы](additional-responses.md){.internal-link target=_blank}.

View File

@@ -0,0 +1,153 @@
# Продвинутые зависимости { #advanced-dependencies }
## Параметризованные зависимости { #parameterized-dependencies }
Все зависимости, которые мы видели, — это конкретная функция или класс.
Но бывают случаи, когда нужно задавать параметры зависимости, не объявляя много разных функций или классов.
Представим, что нам нужна зависимость, которая проверяет, содержит ли query-параметр `q` некоторое фиксированное содержимое.
Но при этом мы хотим иметь возможность параметризовать это фиксированное содержимое.
## «Вызываемый» экземпляр { #a-callable-instance }
В Python есть способ сделать экземпляр класса «вызываемым» объектом.
Не сам класс (он уже является вызываемым), а экземпляр этого класса.
Для этого объявляем метод `__call__`:
{* ../../docs_src/dependencies/tutorial011_an_py39.py hl[12] *}
В этом случае именно `__call__` **FastAPI** использует для проверки дополнительных параметров и подзависимостей, и именно он будет вызван, чтобы позже передать значение параметру в вашей *функции-обработчике пути*.
## Параметризуем экземпляр { #parameterize-the-instance }
Теперь мы можем использовать `__init__`, чтобы объявить параметры экземпляра, с помощью которых будем «параметризовать» зависимость:
{* ../../docs_src/dependencies/tutorial011_an_py39.py hl[9] *}
В этом случае **FastAPI** вовсе не трогает `__init__` и не зависит от него — мы используем его напрямую в нашем коде.
## Создаём экземпляр { #create-an-instance }
Мы можем создать экземпляр этого класса так:
{* ../../docs_src/dependencies/tutorial011_an_py39.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_py39.py hl[22] *}
/// tip | Совет
Все это может показаться притянутым за уши. И пока может быть не совсем понятно, чем это полезно.
Эти примеры намеренно простые, но они показывают, как всё устроено.
В главах про безопасность есть вспомогательные функции, реализованные тем же способом.
Если вы поняли всё выше, вы уже знаете, как «под капотом» работают эти утилиты для безопасности.
///
## Зависимости с `yield`, `HTTPException`, `except` и фоновыми задачами { #dependencies-with-yield-httpexception-except-and-background-tasks }
/// warning | Предупреждение
Скорее всего, вам не понадобятся эти технические детали.
Они полезны главным образом, если у вас было приложение FastAPI версии ниже 0.118.0 и вы столкнулись с проблемами зависимостей с `yield`.
///
Зависимости с `yield` со временем изменялись, чтобы учитывать разные случаи применения и исправлять проблемы. Ниже — краткое резюме изменений.
### Зависимости с `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, но с несколькими улучшениями и исправлениями краевых случаев.
///
#### Сценарии с ранним выполнением кода после `yield` { #use-cases-with-early-exit-code }
Есть некоторые сценарии со специфическими условиями, которым могло бы помочь старое поведение — выполнение кода после `yield` перед отправкой ответа.
Например, представьте, что вы используете сессию базы данных в зависимости с `yield` только для проверки пользователя, а в самой *функции-обработчике пути* эта сессия больше не используется, и при этом ответ отправляется долго, например, это `StreamingResponse`, который медленно отправляет данные и по какой-то причине не использует базу данных.
В таком случае сессия базы данных будет удерживаться до завершения отправки ответа, хотя если вы её не используете, удерживать её не требуется.
Это могло бы выглядеть так:
{* ../../docs_src/dependencies/tutorial013_an_py310.py *}
Код после `yield`, автоматическое закрытие `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`, пожалуйста, создайте <a href="https://github.com/fastapi/fastapi/discussions/new?category=questions" class="external-link" target="_blank">вопрос в GitHub Discussions</a> с описанием конкретного кейса и почему вам было бы полезно иметь раннее закрытие для зависимостей с `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` в зависимостях выполнялся уже после отправки ответа, поэтому [Обработчики исключений](../handling-errors.md#install-custom-exception-handlers){.internal-link target=_blank} к тому моменту уже отработали.
Так было сделано в основном для того, чтобы можно было использовать те же объекты, «отданные» зависимостями через `yield`, внутри фоновых задач, потому что код после `yield` выполнялся после завершения фоновых задач.
В FastAPI 0.106.0 это изменили, чтобы не удерживать ресурсы, пока ответ передаётся по сети.
/// tip | Совет
Кроме того, фоновая задача обычно — это самостоятельный фрагмент логики, который следует обрабатывать отдельно, со своими ресурсами (например, со своим подключением к базе данных).
Так код, скорее всего, будет чище.
///
Если вы полагались на прежнее поведение, теперь ресурсы для фоновых задач следует создавать внутри самой фоновой задачи и использовать внутри неё только данные, которые не зависят от ресурсов зависимостей с `yield`.
Например, вместо использования той же сессии базы данных, создайте новую сессию в фоновой задаче и получите объекты из базы данных с помощью этой новой сессии. И затем, вместо передачи объекта из базы данных параметром в функцию фоновой задачи, передавайте идентификатор этого объекта и заново получайте объект внутри функции фоновой задачи.

View File

@@ -1,4 +1,4 @@
# Асинхронное тестирование
# Асинхронное тестирование { #async-tests }
Вы уже видели как тестировать **FastAPI** приложение, используя имеющийся класс `TestClient`. К этому моменту вы видели только как писать тесты в синхронном стиле без использования `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` основан на <a href="https://www.python-httpx.org" class="external-link" target="_blank">HTTPX</a>, и, к счастью, мы можем использовать его (`HTTPX`) напрямую для тестирования API.
## Пример
## Пример { #example }
В качестве простого примера, давайте рассмотрим файловую структуру, схожую с описанной в [Большие приложения](../tutorial/bigger-applications.md){.internal-link target=_blank} и [Тестирование](../tutorial/testing.md){.internal-link target=_blank}:
@@ -38,7 +38,7 @@
{* ../../docs_src/async_tests/test_main.py *}
## Запуск тестов
## Запуск тестов { #run-it }
Вы можете запустить свои тесты как обычно:
@@ -52,7 +52,7 @@ $ pytest
</div>
## Подробнее
## Подробнее { #in-detail }
Маркер `@pytest.mark.anyio` говорит pytest, что тестовая функция должна быть вызвана асинхронно:
@@ -88,7 +88,7 @@ response = client.get('/')
///
## Вызов других асинхронных функций
## Вызов других асинхронных функций { #other-asynchronous-function-calls }
Теперь тестовая функция стала асинхронной, поэтому внутри нее вы можете вызывать также и другие `async` функции, не связанные с отправлением запросов в ваше FastAPI приложение. Как если бы вы вызывали их в любом другом месте вашего кода.

View File

@@ -0,0 +1,458 @@
# За прокси‑сервером { #behind-a-proxy }
Во многих случаях перед приложением FastAPI используется прокси‑сервер, например Traefik или Nginx.
Такие прокси могут обрабатывать HTTPSсертификаты и многое другое.
## Пересылаемые заголовки прокси { #proxy-forwarded-headers }
Прокси перед вашим приложением обычно на лету добавляет некоторые HTTPзаголовки перед отправкой запроса на ваш сервер, чтобы сообщить ему, что запрос был переслан прокси, а также передать исходный (публичный) URL (включая домен), информацию об использовании HTTPS и т.д.
Программа сервера (например, Uvicorn, запущенный через FastAPI CLI) умеет интерпретировать эти заголовки и передавать соответствующую информацию вашему приложению.
Но из соображений безопасности, пока сервер не уверен, что находится за доверенным прокси, он не будет интерпретировать эти заголовки.
/// note | Технические детали
Заголовки прокси:
* <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Forwarded-For" class="external-link" target="_blank">X-Forwarded-For</a>
* <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Forwarded-Proto" class="external-link" target="_blank">X-Forwarded-Proto</a>
* <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Forwarded-Host" class="external-link" target="_blank">X-Forwarded-Host</a>
///
### Включить пересылаемые заголовки прокси { #enable-proxy-forwarded-headers }
Вы можете запустить FastAPI CLI с опцией командной строки `--forwarded-allow-ips` и передать IPадреса, которым следует доверять при чтении этих пересылаемых заголовков.
Если указать `--forwarded-allow-ips="*"`, приложение будет доверять всем входящим IP.
Если ваш сервер находится за доверенным прокси и только прокси обращается к нему, этого достаточно, чтобы он принимал IP этого прокси.
<div class="termy">
```console
$ fastapi run --forwarded-allow-ips="*"
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
```
</div>
### Редиректы с HTTPS { #redirects-with-https }
Например, вы объявили операцию пути `/items/`:
{* ../../docs_src/behind_a_proxy/tutorial001_01.py hl[6] *}
Если клиент обратится к `/items`, по умолчанию произойдёт редирект на `/items/`.
Но до установки опции `--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}.
///
### Как работают пересылаемые заголовки прокси
Ниже показано, как прокси добавляет пересылаемые заголовки между клиентом и сервером приложения:
```mermaid
sequenceDiagram
participant Client as Клиент
participant Proxy as Прокси/Балансировщик нагрузки
participant Server as FastAPI-сервер
Client->>Proxy: HTTPS-запрос<br/>Host: mysuperapp.com<br/>Path: /items
Note over Proxy: Прокси-сервер добавляет пересылаемые заголовки
Proxy->>Server: HTTP-запрос<br/>X-Forwarded-For: [client IP]<br/>X-Forwarded-Proto: https<br/>X-Forwarded-Host: mysuperapp.com<br/>Path: /items
Note over Server: Server интерпретирует HTTP-заголовки<br/>(если --forwarded-allow-ips установлен)
Server->>Proxy: HTTP-ответ<br/>с верными HTTPS URLs
Proxy->>Client: HTTPS-ответ
```
Прокси перехватывает исходный клиентский запрос и добавляет специальные пересылаемые заголовки (`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.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, в которой будет указано, что этот API `server` находится по пути `/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`, например так:
<div class="termy">
```console
$ fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
```
</div>
Если вы используете 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.py hl[8] *}
Затем, если вы запустите Uvicorn так:
<div class="termy">
```console
$ fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
```
</div>
Ответ будет примерно таким:
```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.py hl[3] *}
Передача `root_path` в `FastAPI` эквивалентна опции командной строки `--root-path` для Uvicorn или Hypercorn.
### О `root_path` { #about-root-path }
Учтите, что сервер (Uvicorn) не использует `root_path` ни для чего, кроме как передать его в приложение.
Если вы откроете в браузере <a href="http://127.0.0.1:8000/app" class="external-link" target="_blank">http://127.0.0.1:8000/app</a>, вы увидите обычный ответ:
```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`, то прокси (без урезанного префикса) обратится к Uvicorn по тому же пути: `http://127.0.0.1:8000/api/v1/app`.
## Локальное тестирование с Traefik { #testing-locally-with-traefik }
Вы можете легко поэкспериментировать локально с урезанным префиксом пути, используя <a href="https://docs.traefik.io/" class="external-link" target="_blank">Traefik</a>.
<a href="https://github.com/containous/traefik/releases" class="external-link" target="_blank">Скачайте Traefik</a> — это один бинарный файл; распакуйте архив и запустите его прямо из терминала.
Затем создайте файл `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:
<div class="termy">
```console
$ ./traefik --configFile=traefik.toml
INFO[0000] Configuration loaded from file: /home/user/awesomeapi/traefik.toml
```
</div>
И запустите приложение с опцией `--root-path`:
<div class="termy">
```console
$ fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
```
</div>
### Проверьте ответы { #check-the-responses }
Теперь, если вы перейдёте на URL с портом Uvicorn: <a href="http://127.0.0.1:8000/app" class="external-link" target="_blank">http://127.0.0.1:8000/app</a>, вы увидите обычный ответ:
```JSON
{
"message": "Hello World",
"root_path": "/api/v1"
}
```
/// tip | Совет
Обратите внимание, что хотя вы обращаетесь по `http://127.0.0.1:8000/app`, в ответе указан `root_path` равный `/api/v1`, взятый из опции `--root-path`.
///
А теперь откройте URL с портом Traefik и префиксом пути: <a href="http://127.0.0.1:9999/api/v1/app" class="external-link" target="_blank">http://127.0.0.1:9999/api/v1/app</a>.
Мы получим тот же ответ:
```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, он не будет работать, так как предполагается доступ через прокси.
Проверьте по адресу <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>:
<img src="/img/tutorial/behind-a-proxy/image01.png">
А вот если открыть интерфейс документации по «официальному» URL через прокси на порту `9999`, по `/api/v1/docs`, всё работает корректно! 🎉
Проверьте по адресу <a href="http://127.0.0.1:9999/api/v1/docs" class="external-link" target="_blank">http://127.0.0.1:9999/api/v1/docs</a>:
<img src="/img/tutorial/behind-a-proxy/image02.png">
Именно как и хотелось. ✔️
Это потому, что FastAPI использует `root_path`, чтобы создать в OpenAPI сервер по умолчанию с URL из `root_path`.
## Дополнительные серверы { #additional-servers }
/// warning | Предупреждение
Это более продвинутый сценарий. Можно пропустить.
///
По умолчанию FastAPI создаёт в схеме OpenAPI `server` с URL из `root_path`.
Но вы также можете указать дополнительные `servers`, например, если хотите, чтобы один и тот же интерфейс документации работал и со <abbr title="«промежуточное» или «предпродакшн» окружение">стейджингом</abbr>, и с продакшн.
Если вы передадите свой список `servers` и при этом задан `root_path` (потому что ваш API работает за прокси), FastAPI вставит «server» с этим `root_path` в начало списка.
Например:
{* ../../docs_src/behind_a_proxy/tutorial003.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`.
///
В интерфейсе документации по адресу <a href="http://127.0.0.1:9999/api/v1/docs" class="external-link" target="_blank">http://127.0.0.1:9999/api/v1/docs</a> это будет выглядеть так:
<img src="/img/tutorial/behind-a-proxy/image03.png">
/// tip | Совет
Интерфейс документации будет взаимодействовать с сервером, который вы выберете.
///
### Отключить автоматическое добавление сервера из `root_path` { #disable-automatic-server-from-root-path }
Если вы не хотите, чтобы FastAPI добавлял автоматический сервер, используя `root_path`, укажите параметр `root_path_in_servers=False`:
{* ../../docs_src/behind_a_proxy/tutorial004.py hl[9] *}
и тогда этот сервер не будет добавлен в схему OpenAPI.
## Монтирование вложенного приложения { #mounting-a-sub-application }
Если вам нужно смонтировать вложенное приложение (как описано в [Вложенные приложения — монтирование](sub-applications.md){.internal-link target=_blank}), и при этом вы используете прокси с `root_path`, делайте это обычным образом — всё будет работать, как ожидается.
FastAPI умно использует `root_path` внутри, так что всё просто работает. ✨

View File

@@ -0,0 +1,312 @@
# Кастомные ответы — HTML, поток, файл и другие { #custom-response-html-stream-file-others }
По умолчанию **FastAPI** возвращает ответы с помощью `JSONResponse`.
Вы можете переопределить это, вернув `Response` напрямую, как показано в разделе [Вернуть 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 }
Например, если вы выжимаете максимум производительности, вы можете установить и использовать <a href="https://github.com/ijl/orjson" class="external-link" target="_blank">`orjson`</a> и задать ответ как `ORJSONResponse`.
Импортируйте класс (подкласс) `Response`, который вы хотите использовать, и объявите его в декораторе операции пути.
Для больших ответов возвращать `Response` напрямую значительно быстрее, чем возвращать словарь.
Это потому, что по умолчанию FastAPI проверяет каждый элемент внутри и убеждается, что он сериализуем в JSON, используя тот же [JSON Compatible Encoder](../tutorial/encoder.md){.internal-link target=_blank}, объяснённый в руководстве. Это позволяет возвращать **произвольные объекты**, например модели из базы данных.
Но если вы уверены, что содержимое, которое вы возвращаете, **сериализуемо в JSON**, вы можете передать его напрямую в класс ответа и избежать дополнительных накладных расходов, которые FastAPI понёс бы, пропуская возвращаемое содержимое через `jsonable_encoder` перед передачей в класс ответа.
{* ../../docs_src/custom_response/tutorial001b.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.py hl[2,7] *}
/// info | Информация
Параметр `response_class` также используется для указания «типа содержимого» ответа.
В этом случае HTTP-заголовок `Content-Type` будет установлен в `text/html`.
И это будет задокументировано как таковое в OpenAPI.
///
### Вернуть `Response` { #return-a-response }
Как показано в разделе [Вернуть Response напрямую](response-directly.md){.internal-link target=_blank}, вы также можете переопределить ответ прямо в своей операции пути, просто вернув его.
Тот же пример сверху, возвращающий `HTMLResponse`, может выглядеть так:
{* ../../docs_src/custom_response/tutorial003.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.py hl[7,21,23] *}
В этом примере функция `generate_html_response()` уже генерирует и возвращает `Response` вместо возврата HTML в `str`.
Возвращая результат вызова `generate_html_response()`, вы уже возвращаете `Response`, который переопределит поведение **FastAPI** по умолчанию.
Но поскольку вы также передали `HTMLResponse` в `response_class`, **FastAPI** будет знать, как задокументировать это в OpenAPI и интерактивной документации как HTML с `text/html`:
<img src="/img/tutorial/custom-response/image01.png">
## Доступные ответы { #available-responses }
Ниже перечислены некоторые доступные классы ответов.
Учтите, что вы можете использовать `Response`, чтобы вернуть что угодно ещё, или даже создать собственный подкласс.
/// note | Технические детали
Вы также могли бы использовать `from starlette.responses import HTMLResponse`.
**FastAPI** предоставляет те же `starlette.responses` как `fastapi.responses` для вашего удобства как разработчика. Но большинство доступных классов ответов приходят непосредственно из Starlette.
///
### `Response` { #response }
Базовый класс `Response`, от него наследуются все остальные ответы.
Его можно возвращать напрямую.
Он принимает следующие параметры:
- `content``str` или `bytes`.
- `status_code` — целое число, HTTP статус-код.
- `headers` — словарь строк.
- `media_type` — строка, задающая тип содержимого. Например, `"text/html"`.
FastAPI (фактически Starlette) автоматически добавит заголовок Content-Length. Также будет добавлен заголовок Content-Type, основанный на `media_type` и с добавлением charset для текстовых типов.
{* ../../docs_src/response_directly/tutorial002.py hl[1,18] *}
### `HTMLResponse` { #htmlresponse }
Принимает текст или байты и возвращает HTML-ответ, как описано выше.
### `PlainTextResponse` { #plaintextresponse }
Принимает текст или байты и возвращает ответ в виде простого текста.
{* ../../docs_src/custom_response/tutorial005.py hl[2,7,9] *}
### `JSONResponse` { #jsonresponse }
Принимает данные и возвращает ответ, кодированный как `application/json`.
Это ответ по умолчанию, используемый в **FastAPI**, как было сказано выше.
### `ORJSONResponse` { #orjsonresponse }
Быстрая альтернативная реализация JSON-ответа с использованием <a href="https://github.com/ijl/orjson" class="external-link" target="_blank">`orjson`</a>, как было сказано выше.
/// info | Информация
Требуется установка `orjson`, например командой `pip install orjson`.
///
### `UJSONResponse` { #ujsonresponse }
Альтернативная реализация JSON-ответа с использованием <a href="https://github.com/ultrajson/ultrajson" class="external-link" target="_blank">`ujson`</a>.
/// info | Информация
Требуется установка `ujson`, например командой `pip install ujson`.
///
/// warning | Предупреждение
`ujson` менее аккуратен, чем встроенная реализация Python, в обработке некоторых крайних случаев.
///
{* ../../docs_src/custom_response/tutorial001.py hl[2,7] *}
/// tip | Совет
Возможно, `ORJSONResponse` окажется более быстрым вариантом.
///
### `RedirectResponse` { #redirectresponse }
Возвращает HTTP-редирект. По умолчанию использует статус-код 307 (Temporary Redirect — временное перенаправление).
Вы можете вернуть `RedirectResponse` напрямую:
{* ../../docs_src/custom_response/tutorial006.py hl[2,9] *}
---
Или можно использовать его в параметре `response_class`:
{* ../../docs_src/custom_response/tutorial006b.py hl[2,7,9] *}
Если вы сделаете так, то сможете возвращать URL напрямую из своей функции-обработчика пути.
В этом случае будет использован статус-код по умолчанию для `RedirectResponse`, то есть `307`.
---
Также вы можете использовать параметр `status_code` в сочетании с параметром `response_class`:
{* ../../docs_src/custom_response/tutorial006c.py hl[2,7,9] *}
### `StreamingResponse` { #streamingresponse }
Принимает асинхронный генератор или обычный генератор/итератор и отправляет тело ответа потоково.
{* ../../docs_src/custom_response/tutorial007.py hl[2,14] *}
#### Использование `StreamingResponse` с файлоподобными объектами { #using-streamingresponse-with-file-like-objects }
Если у вас есть <a href="https://docs.python.org/3/glossary.html#term-file-like-object" class="external-link" target="_blank">файлоподобный</a> объект (например, объект, возвращаемый `open()`), вы можете создать функцию-генератор для итерации по этому файлоподобному объекту.
Таким образом, вам не нужно сначала читать всё в память, вы можете передать эту функцию-генератор в `StreamingResponse` и вернуть его.
Это включает многие библиотеки для работы с облачным хранилищем, обработки видео и т.д.
{* ../../docs_src/custom_response/tutorial008.py hl[2,10:12,14] *}
1. Это функция-генератор. Она является «функцией-генератором», потому что содержит оператор(ы) `yield` внутри.
2. Используя блок `with`, мы гарантируем, что файлоподобный объект будет закрыт после завершения работы функции-генератора. То есть после того, как она закончит отправку ответа.
3. Этот `yield from` говорит функции итерироваться по объекту с именем `file_like`. И затем, для каждой итерации, отдавать эту часть как исходящую из этой функции-генератора (`iterfile`).
Таким образом, это функция-генератор, которая внутренне передаёт работу по «генерации» чему-то другому.
Делая это таким образом, мы можем поместить её в блок `with` и тем самым гарантировать, что файлоподобный объект будет закрыт после завершения.
/// tip | Совет
Заметьте, что здесь мы используем стандартный `open()`, который не поддерживает `async` и `await`, поэтому объявляем операцию пути обычной `def`.
///
### `FileResponse` { #fileresponse }
Асинхронно отправляет файл как ответ.
Для создания экземпляра принимает иной набор аргументов, чем другие типы ответов:
- `path` — путь к файлу, который будет отправлен.
- `headers` — любые дополнительные заголовки для включения, в виде словаря.
- `media_type` — строка, задающая тип содержимого. Если не задан, для определения типа содержимого будет использовано имя файла или путь.
- `filename` — если задан, будет включён в заголовок ответа `Content-Disposition`.
Файловые ответы будут содержать соответствующие заголовки `Content-Length`, `Last-Modified` и `ETag`.
{* ../../docs_src/custom_response/tutorial009.py hl[2,10] *}
Вы также можете использовать параметр `response_class`:
{* ../../docs_src/custom_response/tutorial009b.py hl[2,8,10] *}
В этом случае вы можете возвращать путь к файлу напрямую из своей функции-обработчика пути.
## Пользовательский класс ответа { #custom-response-class }
Вы можете создать собственный класс ответа, унаследовавшись от `Response`, и использовать его.
Например, предположим, что вы хотите использовать <a href="https://github.com/ijl/orjson" class="external-link" target="_blank">`orjson`</a>, но с некоторыми пользовательскими настройками, которые не используются во встроенном классе `ORJSONResponse`.
Скажем, вы хотите, чтобы возвращался отформатированный JSON с отступами, то есть хотите использовать опцию orjson `orjson.OPT_INDENT_2`.
Вы могли бы создать `CustomORJSONResponse`. Главное, что вам нужно сделать — реализовать метод `Response.render(content)`, который возвращает содержимое как `bytes`:
{* ../../docs_src/custom_response/tutorial009c.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.py hl[2,4] *}
/// tip | Совет
Вы по-прежнему можете переопределять `response_class` в операциях пути, как и раньше.
///
## Дополнительная документация { #additional-documentation }
Вы также можете объявить тип содержимого и многие другие детали в OpenAPI с помощью `responses`: [Дополнительные ответы в OpenAPI](additional-responses.md){.internal-link target=_blank}.

View File

@@ -0,0 +1,95 @@
# Использование dataclasses { #using-dataclasses }
FastAPI построен поверх **Pydantic**, и я показывал вам, как использовать Pydantic-модели для объявления HTTP-запросов и HTTP-ответов.
Но FastAPI также поддерживает использование <a href="https://docs.python.org/3/library/dataclasses.html" class="external-link" target="_blank">`dataclasses`</a> тем же способом:
{* ../../docs_src/dataclasses/tutorial001.py hl[1,7:12,19:20] *}
Это по-прежнему поддерживается благодаря **Pydantic**, так как в нём есть <a href="https://docs.pydantic.dev/latest/concepts/dataclasses/#use-of-stdlib-dataclasses-with-basemodel" class="external-link" target="_blank">встроенная поддержка `dataclasses`</a>.
Так что даже если в коде выше 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.py hl[1,7:13,19] *}
Этот dataclass будет автоматически преобразован в Pydantic dataclass.
Таким образом, его схема появится в интерфейсе документации API:
<img src="/img/tutorial/dataclasses/image01.png">
## Dataclasses во вложенных структурах данных { #dataclasses-in-nested-data-structures }
Вы также можете комбинировать `dataclasses` с другими аннотациями типов, чтобы создавать вложенные структуры данных.
В некоторых случаях вам всё же может понадобиться использовать версию `dataclasses` из Pydantic. Например, если у вас возникают ошибки с автоматически генерируемой документацией API.
В таком случае вы можете просто заменить стандартные `dataclasses` на `pydantic.dataclasses`, которая является полностью совместимой заменой (drop-in replacement):
{* ../../docs_src/dataclasses/tutorial003.py hl[1,5,8:11,14:17,23:25,28] *}
1. Мы по-прежнему импортируем `field` из стандартных `dataclasses`.
2. `pydantic.dataclasses` — полностью совместимая замена (drop-in replacement) для `dataclasses`.
3. Dataclass `Author` содержит список dataclass `Item`.
4. Dataclass `Author` используется в параметре `response_model`.
5. Вы можете использовать и другие стандартные аннотации типов вместе с dataclasses в качестве тела запроса.
В этом случае это список dataclass `Item`.
6. Здесь мы возвращаем словарь, содержащий `items`, который является списком dataclass.
FastAPI по-прежнему способен <abbr title="преобразование данных в формат, который можно передавать">сериализовать</abbr> данные в 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), чтобы преобразовать HTTP-ответ.
Вы можете комбинировать `dataclasses` с другими аннотациями типов множеством способов, чтобы формировать сложные структуры данных.
Смотрите подсказки в коде выше, чтобы увидеть более конкретные детали.
## Узнать больше { #learn-more }
Вы также можете комбинировать `dataclasses` с другими Pydantic-моделями, наследоваться от них, включать их в свои модели и т.д.
Чтобы узнать больше, посмотрите <a href="https://docs.pydantic.dev/latest/concepts/dataclasses/" class="external-link" target="_blank">документацию Pydantic о dataclasses</a>.
## Версия { #version }
Доступно начиная с версии FastAPI `0.67.0`. 🔖

View File

@@ -0,0 +1,165 @@
# События lifespan { #lifespan-events }
Вы можете определить логику (код), которую нужно выполнить перед тем, как приложение начнет запускаться. Это означает, что этот код будет выполнен один раз, перед тем как приложение начнет получать HTTP-запросы.
Аналогично, вы можете определить логику (код), которую нужно выполнить, когда приложение завершает работу. В этом случае код будет выполнен один раз, после обработки, возможно, многих запросов.
Поскольку этот код выполняется до того, как приложение начинает принимать запросы, и сразу после того, как оно заканчивает их обрабатывать, он охватывает весь lifespan (жизненный цикл) приложения (слово «lifespan» станет важным через секунду 😉).
Это может быть очень полезно для настройки ресурсов, которые нужны для всего приложения, которые разделяются между запросами и/или которые нужно затем очистить. Например, пул подключений к базе данных или загрузка общей модели Машинного обучения.
## Вариант использования { #use-case }
Начнем с примера варианта использования, а затем посмотрим, как это решить.
Представим, что у вас есть несколько моделей Машинного обучения, которые вы хотите использовать для обработки запросов. 🤖
Эти же модели разделяются между запросами, то есть это не одна модель на запрос, не одна на пользователя и т.п.
Представим, что загрузка модели может занимать довольно много времени, потому что ей нужно прочитать много данных с диска. Поэтому вы не хотите делать это для каждого запроса.
Вы могли бы загрузить её на верхнем уровне модуля/файла, но это означало бы, что модель загружается даже если вы просто запускаете простой автоматический тест; тогда этот тест будет медленным, так как ему придется ждать загрузки модели перед запуском независимой части кода.
Именно это мы и решим: давайте загружать модель перед тем, как начнётся обработка запросов, но только непосредственно перед тем, как приложение начнет принимать запросы, а не во время загрузки кода.
## Lifespan { #lifespan }
Вы можете определить логику для startup и shutdown, используя параметр `lifespan` приложения `FastAPI` и «менеджер контекста» (через секунду покажу что это).
Начнем с примера, а затем разберём его подробнее.
Мы создаём асинхронную функцию `lifespan()` с `yield` примерно так:
{* ../../docs_src/events/tutorial003.py hl[16,19] *}
Здесь мы симулируем дорогую операцию startup по загрузке модели, помещая (фиктивную) функцию модели в словарь с моделями Машинного обучения до `yield`. Этот код будет выполнен до того, как приложение начнет принимать запросы, во время startup.
А затем сразу после `yield` мы выгружаем модель. Этот код будет выполнен после того, как приложение закончит обрабатывать запросы, непосредственно перед shutdown. Это может, например, освободить ресурсы, такие как память или GPU.
/// tip | Совет
`shutdown` произойдёт, когда вы останавливаете приложение.
Возможно, вам нужно запустить новую версию, или вы просто устали от него. 🤷
///
### Функция lifespan { #lifespan-function }
Первое, на что стоит обратить внимание, — мы определяем асинхронную функцию с `yield`. Это очень похоже на Зависимости с `yield`.
{* ../../docs_src/events/tutorial003.py hl[14:19] *}
Первая часть функции, до `yield`, будет выполнена до запуска приложения.
А часть после `yield` будет выполнена после завершения работы приложения.
### Асинхронный менеджер контекста { #async-context-manager }
Если присмотреться, функция декорирована `@asynccontextmanager`.
Это превращает функцию в «асинхронный менеджер контекста».
{* ../../docs_src/events/tutorial003.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.py hl[22] *}
## Альтернативные события (устаревшие) { #alternative-events-deprecated }
/// warning | Предупреждение
Рекомендуемый способ обрабатывать startup и shutdown — использовать параметр `lifespan` приложения `FastAPI`, как описано выше. Если вы укажете параметр `lifespan`, обработчики событий `startup` и `shutdown` больше вызываться не будут. Либо всё через `lifespan`, либо всё через события — не одновременно.
Эту часть, скорее всего, можно пропустить.
///
Есть альтернативный способ определить логику, которую нужно выполнить во время startup и во время shutdown.
Вы можете определить обработчики событий (функции), которые нужно выполнить до старта приложения или при его завершении.
Эти функции можно объявить с `async def` или обычным `def`.
### Событие `startup` { #startup-event }
Чтобы добавить функцию, которую нужно запустить до старта приложения, объявите её как обработчик события `"startup"`:
{* ../../docs_src/events/tutorial001.py hl[8] *}
В этом случае функция-обработчик события `startup` инициализирует «базу данных» items (это просто `dict`) некоторыми значениями.
Вы можете добавить более одного обработчика события.
И ваше приложение не начнет принимать запросы, пока все обработчики события `startup` не завершатся.
### Событие `shutdown` { #shutdown-event }
Чтобы добавить функцию, которую нужно запустить при завершении работы приложения, объявите её как обработчик события `"shutdown"`:
{* ../../docs_src/events/tutorial002.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-технической спецификации, это часть <a href="https://asgi.readthedocs.io/en/latest/specs/lifespan.html" class="external-link" target="_blank">Протокола Lifespan</a>, и он определяет события `startup` и `shutdown`.
/// info | Информация
Вы можете прочитать больше про обработчики `lifespan` в Starlette в <a href="https://www.starlette.io/lifespan/" class="external-link" target="_blank">документации Starlette по Lifespan</a>.
Включая то, как работать с состоянием lifespan, которое можно использовать в других частях вашего кода.
///
## Подприложения { #sub-applications }
🚨 Имейте в виду, что эти события lifespan (startup и shutdown) будут выполнены только для основного приложения, а не для [Подприложения — Mounts](sub-applications.md){.internal-link target=_blank}.

View File

@@ -0,0 +1,208 @@
# Генерация SDK { #generating-sdks }
Поскольку **FastAPI** основан на спецификации **OpenAPI**, его API можно описать в стандартном формате, понятном множеству инструментов.
Это упрощает генерацию актуальной **документации**, клиентских библиотек (<abbr title="Software Development Kits Наборы средств разработки">**SDKs**</abbr>) на разных языках, а также **тестирования** или **воркфлоу автоматизации**, которые остаются синхронизированными с вашим кодом.
В этом руководстве вы узнаете, как сгенерировать **TypeScript SDK** для вашего бэкенда на FastAPI.
## Генераторы SDK с открытым исходным кодом { #open-source-sdk-generators }
Гибкий вариант — <a href="https://openapi-generator.tech/" class="external-link" target="_blank">OpenAPI Generator</a>, который поддерживает **многие языки программирования** и умеет генерировать SDK из вашей спецификации OpenAPI.
Для **TypeScriptклиентов** <a href="https://heyapi.dev/" class="external-link" target="_blank">Hey API</a> — специализированное решение, обеспечивающее оптимальный опыт для экосистемы TypeScript.
Больше генераторов SDK можно найти на <a href="https://openapi.tools/#sdk" class="external-link" target="_blank">OpenAPI.Tools</a>.
/// 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. 🙇
Например, вы можете попробовать:
* <a href="https://speakeasy.com/editor?utm_source=fastapi+repo&utm_medium=github+sponsorship" class="external-link" target="_blank">Speakeasy</a>
* <a href="https://www.stainless.com/?utm_source=fastapi&utm_medium=referral" class="external-link" target="_blank">Stainless</a>
* <a href="https://developers.liblab.com/tutorials/sdk-for-fastapi?utm_source=fastapi" class="external-link" target="_blank">liblab</a>
Некоторые из этих решений также могут быть open source или иметь бесплатные тарифы, так что вы сможете попробовать их без финансовых затрат. Другие коммерческие генераторы SDK доступны и их можно найти онлайн. 🤓
## Создать TypeScript SDK { #create-a-typescript-sdk }
Начнём с простого приложения FastAPI:
{* ../../docs_src/generate_clients/tutorial001_py39.py hl[7:9,12:13,16:17,21] *}
Обратите внимание, что *операции пути (обработчики пути)* определяют модели, которые они используют для полезной нагрузки запроса и полезной нагрузки ответа, с помощью моделей `Item` и `ResponseMessage`.
### Документация API { #api-docs }
Если перейти на `/docs`, вы увидите **схемы** данных, отправляемых в запросах и принимаемых в ответах:
<img src="/img/tutorial/generate-clients/image01.png">
Вы видите эти схемы, потому что они были объявлены с моделями в приложении.
Эта информация доступна в **схеме 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`.
Вы можете узнать, как <a href="https://heyapi.dev/openapi-ts/get-started" class="external-link" target="_blank">установить `@hey-api/openapi-ts`</a> и почитать о <a href="https://heyapi.dev/openapi-ts/output" class="external-link" target="_blank">сгенерированном результате</a> на их сайте.
### Использование SDK { #using-the-sdk }
Теперь вы можете импортировать и использовать клиентский код. Это может выглядеть так, обратите внимание, что вы получаете автозавершение для методoв:
<img src="/img/tutorial/generate-clients/image02.png">
Вы также получите автозавершение для отправляемой полезной нагрузки:
<img src="/img/tutorial/generate-clients/image03.png">
/// tip | Совет
Обратите внимание на автозавершение для `name` и `price`, это было определено в приложении FastAPI, в модели `Item`.
///
Вы получите ошибки прямо в редакторе для отправляемых данных:
<img src="/img/tutorial/generate-clients/image04.png">
Объект ответа также будет иметь автозавершение:
<img src="/img/tutorial/generate-clients/image05.png">
## Приложение FastAPI с тегами { #fastapi-app-with-tags }
Во многих случаях ваше приложение FastAPI будет больше, и вы, вероятно, будете использовать теги, чтобы разделять разные группы *операций пути*.
Например, у вас может быть раздел для **items** и другой раздел для **users**, и они могут быть разделены тегами:
{* ../../docs_src/generate_clients/tutorial002_py39.py hl[21,26,34] *}
### Генерация TypeScriptклиента с тегами { #generate-a-typescript-client-with-tags }
Если вы генерируете клиент для приложения FastAPI с использованием тегов, обычно клиентский код также будет разделён по тегам.
Таким образом вы сможете иметь всё правильно упорядоченным и сгруппированным в клиентском коде:
<img src="/img/tutorial/generate-clients/image06.png">
В этом случае у вас есть:
* `ItemsService`
* `UsersService`
### Имена методов клиента { #client-method-names }
Сейчас сгенерированные имена методов вроде `createItemItemsPost` выглядят не очень аккуратно:
```TypeScript
ItemsService.createItemItemsPost({name: "Plumbus", price: 5})
```
...это потому, что генератор клиента использует внутренний **ID операции** OpenAPI для каждой *операции пути*.
OpenAPI требует, чтобы каждый ID операции был уникален среди всех *операций пути*, поэтому FastAPI использует **имя функции**, **путь** и **HTTPметод/операцию** для генерации этого ID операции, так как таким образом можно гарантировать уникальность ID операций.
Но далее я покажу, как это улучшить. 🤓
## Пользовательские ID операций и лучшие имена методов { #custom-operation-ids-and-better-method-names }
Вы можете **изменить** способ **генерации** этих ID операций, чтобы сделать их проще, а имена методов в клиентах — **более простыми**.
В этом случае вам нужно будет обеспечить, чтобы каждый ID операции был **уникальным** другим способом.
Например, вы можете гарантировать, что у каждой *операции пути* есть тег, и затем генерировать ID операции на основе **тега** и **имени** *операции пути* (имени функции).
### Пользовательская функция генерации уникального ID { #custom-generate-unique-id-function }
FastAPI использует **уникальный ID** для каждой *операции пути*, который применяется для **ID операции**, а также для имён любых необходимых пользовательских моделей запросов или ответов.
Вы можете кастомизировать эту функцию. Она принимает `APIRoute` и возвращает строку.
Например, здесь берётся первый тег (скорее всего у вас один тег) и имя *операции пути* (имя функции).
Затем вы можете передать эту пользовательскую функцию в **FastAPI** через параметр `generate_unique_id_function`:
{* ../../docs_src/generate_clients/tutorial003_py39.py hl[6:7,10] *}
### Генерация TypeScriptклиента с пользовательскими ID операций { #generate-a-typescript-client-with-custom-operation-ids }
Теперь, если снова сгенерировать клиент, вы увидите, что имена методов улучшились:
<img src="/img/tutorial/generate-clients/image07.png">
Как видите, теперь имена методов содержат тег, а затем имя функции; больше они не включают информацию из URLпути и HTTPоперации.
### Предобработка спецификации OpenAPI для генератора клиента { #preprocess-the-openapi-specification-for-the-client-generator }
Сгенерированном коде всё ещё есть **дублирующаяся информация**.
Мы уже знаем, что этот метод относится к **items**, потому что это слово есть в `ItemsService` (взято из тега), но при этом имя тега всё ещё добавлено префиксом к имени метода. 😕
Скорее всего мы захотим оставить это в OpenAPI в целом, так как это гарантирует, что ID операций будут **уникальны**.
Но для сгенерированного клиента мы можем **модифицировать** ID операций OpenAPI непосредственно перед генерацией клиентов, чтобы сделать имена методов более приятными и **чистыми**.
Мы можем скачать OpenAPI JSON в файл `openapi.json`, а затем **убрать этот префикс‑тег** таким скриптом:
{* ../../docs_src/generate_clients/tutorial004.py *}
//// tab | Node.js
```Javascript
{!> ../../docs_src/generate_clients/tutorial004.js!}
```
////
После этого 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
```
После генерации нового клиента у вас будут **чистые имена методов**, со всем **автозавершением**, **ошибками прямо в редакторе** и т.д.:
<img src="/img/tutorial/generate-clients/image08.png">
## Преимущества { #benefits }
При использовании автоматически сгенерированных клиентов вы получите **автозавершение** для:
* Методов.
* Данных запроса — в теле запроса, queryпараметрах и т.д.
* Данных ответа.
У вас также будут **ошибки прямо в редакторе** для всего.
И каждый раз, когда вы обновляете код бэкенда и **перегенерируете** фронтенд, в нём появятся новые *операции пути* как методы, старые будут удалены, а любые другие изменения отразятся в сгенерированном коде. 🤓
Это также означает, что если что‑то изменилось, это будет **отражено** в клиентском коде автоматически. И если вы **соберёте** клиент, он завершится с ошибкой, если где‑то есть **несоответствие** в используемых данных.
Таким образом, вы **обнаружите многие ошибки** очень рано в цикле разработки, вместо того чтобы ждать, когда ошибки проявятся у конечных пользователей в продакшн, и затем пытаться отладить, в чём проблема. ✨

View File

@@ -1,12 +1,12 @@
# Расширенное руководство пользователя
# Расширенное руководство пользователя { #advanced-user-guide }
## Дополнительные возможности
## Дополнительные возможности { #additional-features }
Основное [Учебник - Руководство пользователя](../tutorial/index.md){.internal-link target=_blank} должно быть достаточно, чтобы познакомить вас со всеми основными функциями **FastAPI**.
В следующих разделах вы увидите другие варианты, конфигурации и дополнительные возможности.
/// tip
/// tip | Совет
Следующие разделы **не обязательно являются "продвинутыми"**.
@@ -14,7 +14,7 @@
///
## Сначала прочитайте Учебник - Руководство пользователя
## Сначала прочитайте Учебник - Руководство пользователя { #read-the-tutorial-first }
Вы все еще можете использовать большинство функций **FastAPI** со знаниями из [Учебник - Руководство пользователя](../tutorial/index.md){.internal-link target=_blank}.

View File

@@ -0,0 +1,97 @@
# Расширенное использование middleware { #advanced-middleware }
В основном руководстве вы читали, как добавить [пользовательское middleware](../tutorial/middleware.md){.internal-link target=_blank} в ваше приложение.
А затем — как работать с [CORS с помощью `CORSMiddleware`](../tutorial/cors.md){.internal-link target=_blank}.
В этом разделе посмотрим, как использовать другие middleware.
## Добавление ASGI middleware { #adding-asgi-middlewares }
Так как **FastAPI** основан на Starlette и реализует спецификацию <abbr title="Asynchronous Server Gateway Interface Асинхронный шлюзовой интерфейс сервера">ASGI</abbr>, вы можете использовать любое ASGI middleware.
Middleware не обязательно должно быть сделано специально для FastAPI или Starlette — достаточно, чтобы оно соответствовало спецификации ASGI.
В общем случае ASGI middleware — это классы, которые ожидают получить ASGIприложение первым аргументом.
Поэтому в документации к сторонним ASGI middleware, скорее всего, вы увидите что‑то вроде:
```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()` принимает класс 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.py hl[2,6] *}
## `TrustedHostMiddleware` { #trustedhostmiddleware }
Гарантирует, что во всех входящих запросах корректно установлен `Host`‑заголовок, чтобы защититься от атак на HTTPзаголовок Host.
{* ../../docs_src/advanced_middleware/tutorial002.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.py hl[2,6] *}
Поддерживаются следующие аргументы:
- `minimum_size` — не сжимать GZipом ответы, размер которых меньше этого минимального значения в байтах. По умолчанию — `500`.
- `compresslevel` — уровень GZipсжатия. Целое число от 1 до 9. По умолчанию — `9`. Более низкое значение — быстреее сжатие, но больший размер файла; более высокое значение — более медленное сжатие, но меньший размер файла.
## Другие middleware { #other-middlewares }
Существует много других ASGI middleware.
Например:
- <a href="https://github.com/encode/uvicorn/blob/master/uvicorn/middleware/proxy_headers.py" class="external-link" target="_blank">`ProxyHeadersMiddleware` от Uvicorn</a>
- <a href="https://github.com/florimondmanca/msgpack-asgi" class="external-link" target="_blank">MessagePack</a>
Чтобы увидеть другие доступные middleware, посмотрите <a href="https://www.starlette.io/middleware/" class="external-link" target="_blank">документацию по middleware в Starlette</a> и <a href="https://github.com/florimondmanca/awesome-asgi" class="external-link" target="_blank">список ASGI Awesome</a>.

View File

@@ -0,0 +1,186 @@
# Обратные вызовы в OpenAPI { #openapi-callbacks }
Вы можете создать API с *операцией пути* (обработчиком пути), которая будет инициировать HTTP-запрос к *внешнему API*, созданному кем-то другим (скорее всего тем же разработчиком, который будет использовать ваш API).
Процесс, происходящий, когда ваше приложение API обращается к *внешнему API*, называется «callback» (обратный вызов). Программное обеспечение, написанное внешним разработчиком, отправляет HTTP-запрос вашему API, а затем ваш API выполняет обратный вызов, отправляя HTTP-запрос во *внешний API* (который, вероятно, тоже создал тот же разработчик).
В этом случае вам может понадобиться задокументировать, как должно выглядеть это внешнее API: какую *операцию пути* оно должно иметь, какое тело запроса ожидать, какой ответ возвращать и т.д.
## Приложение с обратными вызовами { #an-app-with-callbacks }
Давайте рассмотрим это на примере.
Представьте, что вы разрабатываете приложение, позволяющее создавать счета.
Эти счета будут иметь `id`, `title` (необязательный), `customer` и `total`.
Пользователь вашего API (внешний разработчик) создаст счет в вашем API с помощью POST-запроса.
Затем ваш API (предположим) сделает следующее:
* Отправит счет клиенту внешнего разработчика.
* Получит оплату.
* Отправит уведомление обратно пользователю API (внешнему разработчику).
* Это будет сделано отправкой POST-запроса (из *вашего API*) в *внешний API*, предоставленный этим внешним разработчиком (это и есть «callback»).
## Обычное приложение **FastAPI** { #the-normal-fastapi-app }
Сначала посмотрим, как будет выглядеть обычное приложение API до добавления обратного вызова.
В нём будет *операция пути*, которая получит тело запроса `Invoice`, и query-параметр `callback_url`, содержащий URL для обратного вызова.
Эта часть вполне обычна, большая часть кода вам уже знакома:
{* ../../docs_src/openapi_callbacks/tutorial001.py hl[9:13,36:53] *}
/// tip | Совет
Query-параметр `callback_url` использует тип Pydantic <a href="https://docs.pydantic.dev/latest/api/networks/" class="external-link" target="_blank">Url</a>.
///
Единственное новое — это `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-запрос.
Реализуя обратный вызов, вы можете использовать, например, <a href="https://www.python-httpx.org" class="external-link" target="_blank">HTTPX</a> или <a href="https://requests.readthedocs.io/" class="external-link" target="_blank">Requests</a>.
///
## Напишите код документации обратного вызова { #write-the-callback-documentation-code }
Этот код не будет выполняться в вашем приложении, он нужен только для *документирования* того, как должен выглядеть *внешний API*.
Но вы уже знаете, как легко получить автоматическую документацию для API с **FastAPI**.
Мы используем те же знания, чтобы задокументировать, как должен выглядеть *внешний API*... создав *операции пути*, которые внешний API должен реализовать (те, которые ваш API будет вызывать).
/// tip | Совет
Когда вы пишете код для документирования обратного вызова, полезно представить, что вы — тот самый *внешний разработчик*. И что вы сейчас реализуете *внешний API*, а не *свой API*.
Временное принятие этой точки зрения (внешнего разработчика) поможет интуитивно понять, куда поместить параметры, какую Pydantic-модель использовать для тела запроса, для ответа и т.д. во *внешнем API*.
///
### Создайте `APIRouter` для обратного вызова { #create-a-callback-apirouter }
Сначала создайте новый `APIRouter`, который будет содержать один или несколько обратных вызовов.
{* ../../docs_src/openapi_callbacks/tutorial001.py hl[3,25] *}
### Создайте *операцию пути* для обратного вызова { #create-the-callback-path-operation }
Чтобы создать *операцию пути* для обратного вызова, используйте тот же `APIRouter`, который вы создали выше.
Она должна выглядеть как обычная *операция пути* FastAPI:
* Вероятно, в ней должно быть объявление тела запроса, например `body: InvoiceEvent`.
* А также может быть объявление модели ответа, например `response_model=InvoiceEventReceived`.
{* ../../docs_src/openapi_callbacks/tutorial001.py hl[16:18,21:22,28:32] *}
Есть 2 основных отличия от обычной *операции пути*:
* Ей не нужен реальный код, потому что ваше приложение никогда не будет вызывать эту функцию. Она используется только для документирования *внешнего API*. Поэтому в функции может быть просто `pass`.
* *Путь* может содержать <a href="https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#key-expression" class="external-link" target="_blank">выражение OpenAPI 3</a> (подробнее ниже), где можно использовать переменные с параметрами и части исходного HTTP-запроса, отправленного *вашему API*.
### Выражение пути для обратного вызова { #the-callback-path-expression }
*Путь* обратного вызова может содержать <a href="https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#key-expression" class="external-link" target="_blank">выражение OpenAPI 3</a>, которое может включать части исходного запроса, отправленного *вашему API*.
В нашем случае это `str`:
```Python
"{$callback_url}/invoices/{$request.body.id}"
```
Итак, если пользователь вашего API (внешний разработчик) отправляет HTTP-запрос вашему 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, полученный как query-параметр в `callback_url` (`https://www.external.org/events`), а также `id` счёта из тела JSON (`2expen51ve`).
///
### Подключите маршрутизатор обратного вызова { #add-the-callback-router }
К этому моменту у вас есть необходимые *операции пути* обратного вызова (те, которые *внешний разработчик* должен реализовать во *внешнем API*) в созданном выше маршрутизаторе обратных вызовов.
Теперь используйте параметр `callbacks` в *декораторе операции пути вашего API*, чтобы передать атрибут `.routes` (это, по сути, просто `list` маршрутов/*операций пути*) из этого маршрутизатора обратных вызовов:
{* ../../docs_src/openapi_callbacks/tutorial001.py hl[35] *}
/// tip | Совет
Обратите внимание, что вы передаёте не сам маршрутизатор (`invoices_callback_router`) в `callback=`, а его атрибут `.routes`, то есть `invoices_callback_router.routes`.
///
### Проверьте документацию { #check-the-docs }
Теперь вы можете запустить приложение и перейти по адресу <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
Вы увидите документацию, включающую раздел «Callbacks» для вашей *операции пути*, который показывает, как должен выглядеть *внешний API*:
<img src="/img/tutorial/openapi-callbacks/image01.png">

View File

@@ -0,0 +1,55 @@
# Вебхуки OpenAPI { #openapi-webhooks }
Бывают случаи, когда вы хотите сообщить пользователям вашего API, что ваше приложение может вызвать их приложение (отправив HTTP-запрос) с некоторыми данными, обычно чтобы уведомить о каком-то событии.
Это означает, что вместо обычного процесса, когда пользователи отправляют запросы вашему 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.py hl[9:13,36:53] *}
Определенные вами вебхуки попадут в схему **OpenAPI** и в автоматический **интерфейс документации**.
/// info | Информация
Объект `app.webhooks` на самом деле — это обычный `APIRouter`, тот же тип, который вы используете при структурировании приложения по нескольким файлам.
///
Обратите внимание: в случае с вебхуками вы на самом деле не объявляете путь (например, `/items/`), передаваемый туда текст — это лишь идентификатор вебхука (имя события). Например, в `@app.webhooks.post("new-subscription")` имя вебхука — `new-subscription`.
Это связано с тем, что предполагается: фактический URLпуть, по которому они хотят получать запрос вебхука, ваши пользователи укажут каким-то другим образом (например, в веб‑панели).
### Посмотрите документацию { #check-the-docs }
Теперь вы можете запустить приложение и перейти по ссылке <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
Вы увидите, что в документации есть обычные операции пути, а также появились вебхуки:
<img src="/img/tutorial/openapi-webhooks/image01.png">

View File

@@ -0,0 +1,204 @@
# Расширенная конфигурация операций пути { #path-operation-advanced-configuration }
## OpenAPI operationId { #openapi-operationid }
/// warning | Предупреждение
Если вы не «эксперт» по OpenAPI, скорее всего, это вам не нужно.
///
Вы можете задать OpenAPI `operationId`, который будет использоваться в вашей *операции пути*, с помощью параметра `operation_id`.
Нужно убедиться, что он уникален для каждой операции.
{* ../../docs_src/path_operation_advanced_configuration/tutorial001.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.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.py hl[6] *}
## Расширенное описание из docstring { #advanced-description-from-docstring }
Вы можете ограничить количество строк из docstring *функции-обработчика пути*, используемых для OpenAPI.
Добавление `\f` (экранированного символа «form feed») заставит **FastAPI** обрезать текст, используемый для OpenAPI, в этой точке.
Эта часть не попадёт в документацию, но другие инструменты (например, Sphinx) смогут использовать остальное.
{* ../../docs_src/path_operation_advanced_configuration/tutorial004.py hl[19:29] *}
## Дополнительные ответы { #additional-responses }
Вы, вероятно, уже видели, как объявлять `response_model` и `status_code` для *операции пути*.
Это определяет метаданные об основном ответе *операции пути*.
Также можно объявлять дополнительные ответы с их моделями, статус-кодами и т.д.
В документации есть целая глава об этом — [Дополнительные ответы в OpenAPI](additional-responses.md){.internal-link target=_blank}.
## Дополнительные данные OpenAPI { #openapi-extra }
Когда вы объявляете *операцию пути* в своём приложении, **FastAPI** автоматически генерирует соответствующие метаданные об этой *операции пути* для включения в схему OpenAPI.
/// note | Технические детали
В спецификации OpenAPI это называется <a href="https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#operation-object" class="external-link" target="_blank">Объект операции</a>.
///
Он содержит всю информацию об *операции пути* и используется для генерации автоматической документации.
Там есть `tags`, `parameters`, `requestBody`, `responses` и т.д.
Эта спецификация OpenAPI, специфичная для *операции пути*, обычно генерируется автоматически **FastAPI**, но вы также можете её расширить.
/// tip | Совет
Это низкоуровневая возможность расширения.
Если вам нужно лишь объявить дополнительные ответы, удобнее сделать это через [Дополнительные ответы в OpenAPI](additional-responses.md){.internal-link target=_blank}.
///
Вы можете расширить схему OpenAPI для *операции пути* с помощью параметра `openapi_extra`.
### Расширения 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.py hl[6] *}
Если вы откроете автоматическую документацию API, ваше расширение появится внизу страницы конкретной *операции пути*.
<img src="/img/tutorial/path-operation-advanced-configuration/image01.png">
И если вы посмотрите на итоговый 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.py hl[19:36, 39:40] *}
В этом примере мы не объявляли никакую Pydantic-модель. Фактически тело запроса даже не <abbr title="преобразовано из простого формата, например байтов, в объекты Python">распарсено</abbr> как JSON, оно читается напрямую как `bytes`, а функция `magic_data_reader()` будет отвечать за его парсинг каким-то способом.
Тем не менее, мы можем объявить ожидаемую схему для тела запроса.
### Пользовательский тип содержимого в OpenAPI { #custom-openapi-content-type }
Используя тот же приём, вы можете воспользоваться Pydantic-моделью, чтобы определить JSON Schema, которая затем будет включена в пользовательский раздел схемы OpenAPI для *операции пути*.
И вы можете сделать это, даже если тип данных в запросе — не JSON.
Например, в этом приложении мы не используем встроенную функциональность FastAPI для извлечения JSON Schema из моделей Pydantic, равно как и автоматическую валидацию JSON. Мы объявляем тип содержимого запроса как YAML, а не JSON:
//// tab | Pydantic v2
{* ../../docs_src/path_operation_advanced_configuration/tutorial007.py hl[17:22, 24] *}
////
//// tab | Pydantic v1
{* ../../docs_src/path_operation_advanced_configuration/tutorial007_pv1.py hl[17:22, 24] *}
////
/// info | Информация
В Pydantic версии 1 метод для получения JSON Schema модели назывался `Item.schema()`, в Pydantic версии 2 метод называется `Item.model_json_schema()`.
///
Тем не менее, хотя мы не используем встроенную функциональность по умолчанию, мы всё равно используем Pydantic-модель, чтобы вручную сгенерировать JSON Schema для данных, которые мы хотим получить в YAML.
Затем мы работаем с запросом напрямую и извлекаем тело как `bytes`. Это означает, что FastAPI даже не попытается распарсить полезную нагрузку запроса как JSON.
А затем в нашем коде мы напрямую парсим этот YAML и снова используем ту же Pydantic-модель для валидации YAML-содержимого:
//// tab | Pydantic v2
{* ../../docs_src/path_operation_advanced_configuration/tutorial007.py hl[26:33] *}
////
//// tab | Pydantic v1
{* ../../docs_src/path_operation_advanced_configuration/tutorial007_pv1.py hl[26:33] *}
////
/// info | Информация
В Pydantic версии 1 метод для парсинга и валидации объекта назывался `Item.parse_obj()`, в Pydantic версии 2 метод называется `Item.model_validate()`.
///
/// tip | Совет
Здесь мы переиспользуем ту же Pydantic-модель.
Но аналогично мы могли бы валидировать данные и каким-то другим способом.
///

View File

@@ -1,22 +1,22 @@
# Response - Изменение cтатус кода
# Response - Изменение статус-кода { #response-change-status-code }
Вы, вероятно, уже читали о том, что можно установить [Состояние ответа по умолчанию](../tutorial/response-status-code.md){.internal-link target=_blank}.
Вы, вероятно, уже читали о том, что можно установить [статус-код ответа по умолчанию](../tutorial/response-status-code.md){.internal-link target=_blank}.
Но в некоторых случаях вам нужно вернуть код состояния, отличный от установленного по умолчанию.
Но в некоторых случаях нужно вернуть другой статус-код, отличный от значения по умолчанию.
## Пример использования
## Пример использования { #use-case }
Например, представьте, что вы хотите возвращать HTTP код состояния "OK" `200` по умолчанию.
Например, представьте, что вы хотите по умолчанию возвращать HTTP статус-код «OK» `200`.
Но если данные не существовали, вы хотите создать их и вернуть HTTP код состояния "CREATED" `201`.
Но если данные не существовали, вы хотите создать их и вернуть HTTP статус-код «CREATED» `201`.
При этом вы всё ещё хотите иметь возможность фильтровать и преобразовывать возвращаемые данные с помощью `response_model`.
Для таких случаев вы можете использовать параметр `Response`.
## Использование параметра `Response`
## Использование параметра `Response` { #use-a-response-parameter }
Вы можете объявить параметр типа `Response` в вашей *функции обработки пути* (так же как для cookies и headers).
Вы можете объявить параметр типа `Response` в вашей *функции обработки пути* (как и для cookies и HTTP-заголовков).
И затем вы можете установить `status_code` в этом *временном* объекте ответа.
@@ -26,6 +26,6 @@
И если вы объявили `response_model`, он всё равно будет использоваться для фильтрации и преобразования возвращаемого объекта.
**FastAPI** будет использовать этот *временный* ответ для извлечения кода состояния (а также cookies и headers) и поместит их в финальный ответ, который содержит возвращаемое вами значение, отфильтрованное любым `response_model`.
**FastAPI** будет использовать этот *временный* ответ для извлечения статус-кода (а также cookies и HTTP-заголовков) и поместит их в финальный ответ, который содержит возвращаемое вами значение, отфильтрованное любым `response_model`.
Вы также можете объявить параметр `Response` в зависимостях и установить код состояния в них. Но помните, что последнее установленное значение будет иметь приоритет.
Вы также можете объявить параметр `Response` в зависимостях и установить в них статус-код. Но помните, что последнее установленное значение будет иметь приоритет.

View File

@@ -1,9 +1,8 @@
# Cookies в ответе { #response-cookies }
# Cookies в ответе
## Использование параметра `Response` { #use-a-response-parameter }
## Использование параметра `Response`
Вы можете объявить параметр типа `Response` в вашей функции эндпоинта.
Вы можете объявить параметр типа `Response` в вашей функции-обработчике пути.
Затем установить cookies в этом временном объекте ответа.
@@ -13,36 +12,40 @@
Если вы указали `response_model`, он всё равно будет использоваться для фильтрации и преобразования возвращаемого объекта.
**FastAPI** извлечет cookies (а также заголовки и коды состояния) из временного ответа и включит их в окончательный ответ, содержащий ваше возвращаемое значение, отфильтрованное через `response_model`.
**FastAPI** извлечет cookies (а также HTTP-заголовки и статус-код) из временного ответа и включит их в окончательный ответ, содержащий ваше возвращаемое значение, отфильтрованное через `response_model`.
Вы также можете объявить параметр типа Response в зависимостях и устанавливать cookies (и заголовки) там.
Вы также можете объявить параметр типа `Response` в зависимостях и устанавливать cookies (и HTTP-заголовки) там.
## Возвращение `Response` напрямую
## Возвращение `Response` напрямую { #return-a-response-directly }
Вы также можете установить cookies, если возвращаете `Response` напрямую в вашем коде.
Вы также можете установить Cookies, если возвращаете `Response` напрямую в вашем коде.
Для этого создайте объект `Response`, как описано в разделе [Возвращение ответа напрямую](response-directly.md){.target=_blank}.
Для этого создайте объект `Response`, как описано в разделе [Возвращение ответа напрямую](response-directly.md){.internal-link target=_blank}.
Затем установите cookies и верните этот объект:
{* ../../docs_src/response_cookies/tutorial001.py hl[10:12] *}
/// tip | Примечание
Имейте в виду, что если вы возвращаете ответ напрямую, вместо использования параметра `Response`, **FastAPI** отправит его без дополнительной обработки.
/// tip | Совет
Убедитесь, что ваши данные имеют корректный тип. Например, они должны быть совместимы с JSON, если вы используете `JSONResponse`.
Имейте в виду, что если вы возвращаете ответ напрямую, вместо использования параметра `Response`, FastAPI вернёт его напрямую.
Убедитесь, что ваши данные имеют корректный тип. Например, они должны быть совместимы с JSON, если вы возвращаете `JSONResponse`.
Также убедитесь, что вы не отправляете данные, которые должны были быть отфильтрованы через `response_model`.
///
### Дополнительная информация
### Дополнительная информация { #more-info }
/// note | Технические детали
Вы также можете использовать `from starlette.responses import Response` или `from starlette.responses import JSONResponse`.
**FastAPI** предоставляет `fastapi.responses`, которые являются теми же объектами, что и `starlette.responses`, просто для удобства. Однако большинство доступных типов ответов поступает непосредственно из **Starlette**.
Для установки заголовков и cookies `Response` используется часто, поэтому **FastAPI** также предоставляет его через `fastapi.responses`.
И так как `Response` часто используется для установки HTTP-заголовков и cookies, **FastAPI** также предоставляет его как `fastapi.Response`.
///
Чтобы увидеть все доступные параметры и настройки, ознакомьтесь с <a href="https://www.starlette.io/responses/#set-cookie" class="external-link" target="_blank">документацией Starlette</a>.

View File

@@ -1,4 +1,4 @@
# Возврат ответа напрямую
# Возврат ответа напрямую { #return-a-response-directly }
Когда вы создаёте **FastAPI** *операцию пути*, вы можете возвращать из неё любые данные: `dict`, `list`, Pydantic-модель, модель базы данных и т.д.
@@ -8,9 +8,9 @@
Но вы можете возвращать `JSONResponse` напрямую из ваших *операций пути*.
Это может быть полезно, например, если нужно вернуть пользовательские заголовки или куки.
Это может быть полезно, например, если нужно вернуть пользовательские HTTP-заголовки или 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`, который вы возвращаете, вы должны убедиться, что его содержимое готово к отправке.
@@ -44,7 +44,7 @@
///
## Возврат пользовательского `Response`
## Возврат пользовательского `Response` { #returning-a-custom-response }
Пример выше показывает все необходимые части, но он пока не очень полезен, так как вы могли бы просто вернуть `item` напрямую, и **FastAPI** поместил бы его в `JSONResponse`, преобразовав в `dict` и т.д. Всё это происходит по умолчанию.
@@ -56,7 +56,7 @@
{* ../../docs_src/response_directly/tutorial002.py hl[1,18] *}
## Примечания
## Примечания { #notes }
Когда вы возвращаете объект `Response` напрямую, его данные не валидируются, не преобразуются (не сериализуются) и не документируются автоматически.

View File

@@ -0,0 +1,41 @@
# HTTP-заголовки ответа { #response-headers }
## Использовать параметр `Response` { #use-a-response-parameter }
Вы можете объявить параметр типа `Response` в вашей функции-обработчике пути (как можно сделать и для cookie).
А затем вы можете устанавливать HTTP-заголовки в этом *временном* объекте ответа.
{* ../../docs_src/response_headers/tutorial002.py hl[1, 7:8] *}
После этого вы можете вернуть любой нужный объект, как обычно (например, `dict`, модель из базы данных и т.д.).
И, если вы объявили `response_model`, он всё равно будет использован для фильтрации и преобразования возвращённого объекта.
**FastAPI** использует этот *временный* ответ, чтобы извлечь HTTP-заголовки (а также cookie и статус-код) и поместит их в финальный HTTP-ответ, который содержит возвращённое вами значение, отфильтрованное согласно `response_model`.
Вы также можете объявлять параметр `Response` в зависимостях и устанавливать в них заголовки (и cookie).
## Вернуть `Response` напрямую { #return-a-response-directly }
Вы также можете добавить HTTP-заголовки, когда возвращаете `Response` напрямую.
Создайте ответ, как описано в [Вернуть Response напрямую](response-directly.md){.internal-link target=_blank}, и передайте заголовки как дополнительный параметр:
{* ../../docs_src/response_headers/tutorial001.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`.
///
## Пользовательские HTTP-заголовки { #custom-headers }
Помните, что собственные проприетарные заголовки можно добавлять, <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers" class="external-link" target="_blank">используя префикс `X-`</a>.
Но если у вас есть пользовательские заголовки, которые вы хотите показывать клиенту в браузере, вам нужно добавить их в настройки CORS (подробнее см. в [CORS (Cross-Origin Resource Sharing)](../tutorial/cors.md){.internal-link target=_blank}), используя параметр `expose_headers`, описанный в <a href="https://www.starlette.io/middleware/#corsmiddleware" class="external-link" target="_blank">документации Starlette по CORS</a>.

View File

@@ -0,0 +1,107 @@
# HTTP Basic Auth { #http-basic-auth }
Для самых простых случаев можно использовать HTTP Basic Auth.
При HTTP Basic Auth приложение ожидает HTTP-заголовок, который содержит имя пользователя и пароль.
Если его нет, возвращается ошибка HTTP 401 «Unauthorized».
Также возвращается заголовок `WWW-Authenticate` со значением `Basic` и необязательным параметром `realm`.
Это говорит браузеру показать встроенное окно запроса имени пользователя и пароля.
Затем, когда вы вводите эти данные, браузер автоматически отправляет их в заголовке.
## Простой HTTP Basic Auth { #simple-http-basic-auth }
* Импортируйте `HTTPBasic` и `HTTPBasicCredentials`.
* Создайте «схему» `security` с помощью `HTTPBasic`.
* Используйте эту `security` как зависимость в вашей *операции пути*.
* Она возвращает объект типа `HTTPBasicCredentials`:
* Он содержит отправленные `username` и `password`.
{* ../../docs_src/security/tutorial006_an_py39.py hl[4,8,12] *}
Когда вы впервые откроете URL (или нажмёте кнопку «Execute» в документации), браузер попросит ввести имя пользователя и пароль:
<img src="/img/tutorial/security/image12.png">
## Проверка имени пользователя { #check-the-username }
Вот более полный пример.
Используйте зависимость, чтобы проверить, корректны ли имя пользователя и пароль.
Для этого используйте стандартный модуль Python <a href="https://docs.python.org/3/library/secrets.html" class="external-link" target="_blank">`secrets`</a> для проверки имени пользователя и пароля.
`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_py39.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 сравнит первую `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 (тем же, что и при отсутствии учётных данных) и добавьте HTTP-заголовок `WWW-Authenticate`, чтобы браузер снова показал окно входа:
{* ../../docs_src/security/tutorial007_an_py39.py hl[26:30] *}

View File

@@ -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}.
Все они основаны на тех же концепциях, но предоставляют дополнительные возможности.

View File

@@ -0,0 +1,274 @@
# OAuth2 scopes { #oauth2-scopes }
Вы можете использовать OAuth2 scopes (scope - область, рамки) напрямую с **FastAPI** — они интегрированы и работают бесшовно.
Это позволит вам иметь более детальную систему разрешений по стандарту OAuth2, интегрированную в ваше OpenAPIприложение (и документацию API).
OAuth2 со scopes — это механизм, который используют многие крупные провайдеры аутентификации: Facebook, Google, GitHub, Microsoft, X (Twitter) и т.д. Они применяют его, чтобы предоставлять конкретные разрешения пользователям и приложениям.
Каждый раз, когда вы «входите через» 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) можно определить «схемы безопасности» (security schemes).
Когда одна из таких схем безопасности использует 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 и т.д.:
<img src="/img/tutorial/security/image11.png">
## 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` (их также могло быть больше одного).
/// note | Примечание
Вам не обязательно добавлять разные scopes в разных местах.
Мы делаем это здесь, чтобы показать, как **FastAPI** обрабатывает scopes, объявленные на разных уровнях.
///
{* ../../docs_src/security/tutorial005_an_py310.py hl[5,141,172] *}
/// info | Технические детали
`Security` на самом деле является подклассом `Depends` и имеет всего один дополнительный параметр, который мы рассмотрим позже.
Но используя `Security` вместо `Depends`, **FastAPI** будет знать, что можно объявлять security scopes, использовать их внутри и документировать API в OpenAPI.
Однако когда вы импортируете `Query`, `Path`, `Depends`, `Security` и другие из `fastapi`, это на самом деле функции, возвращающие специальные классы.
///
## Использование `SecurityScopes` { #use-securityscopes }
Теперь обновим зависимость `get_current_user`.
Именно её используют зависимости выше.
Здесь мы используем ту же схему OAuth2, созданную ранее, объявляя её как зависимость: `oauth2_scheme`.
Поскольку у этой функции‑зависимости нет собственных требований по scopes, мы можем использовать `Depends` с `oauth2_scheme` — нам не нужно использовать `Security`, если не требуется указывать 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 мы помещаем в HTTPзаголовок `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` или что‑то ещё — ведь это могло бы где‑то позже сломать приложение и создать риск для безопасности.
Мы также проверяем, что существует пользователь с таким именем, и если нет — вызываем то же исключение, созданное ранее.
{* ../../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` в любой точке и в нескольких местах — необязательно в «корневой» зависимости.
Он всегда будет содержать security scopes, объявленные в текущих зависимостях `Security`, и всеми зависящими — для этой конкретной операции пути и этого конкретного дерева зависимостей.
Поскольку `SecurityScopes` будет содержать все scopes, объявленные зависящими, вы можете использовать его, чтобы централизованно проверять наличие требуемых scopes в токене в одной функции‑зависимости, а затем объявлять разные требования по scopes в разных операциях пути.
Они будут проверяться независимо для каждой операции пути.
## Проверим это { #check-it }
Откройте документацию API — вы сможете аутентифицироваться и указать, какие scopes вы хотите авторизовать.
<img src="/img/tutorial/security/image11.png">
Если вы не выберете ни один scope, вы будете «аутентифицированы», но при попытке доступа к `/users/me/` или `/users/me/items/` получите ошибку о недостаточных разрешениях. При этом доступ к `/status/` будет возможен.
Если вы выберете scope `me`, но не `items`, вы сможете получить доступ к `/users/me/`, но не к `/users/me/items/`.
Так и будет происходить со сторонним приложением, которое попытается обратиться к одной из этих операций пути с токеном, предоставленным пользователем, — в зависимости от того, сколько разрешений пользователь дал приложению.
## О сторонних интеграциях { #about-third-party-integrations }
В этом примере мы используем OAuth2 «password flow» (аутентификация по паролю).
Это уместно, когда мы входим в наше собственное приложение, вероятно, с нашим собственным фронтендом.
Мы можем ему доверять при получении `username` и `password`, потому что он под нашим контролем.
Но если вы создаёте OAuth2приложение, к которому будут подключаться другие (т.е. вы строите провайдера аутентификации наподобие Facebook, Google, GitHub и т.п.), вам следует использовать один из других «flows».
Самый распространённый — «implicit flow».
Самый безопасный — «code flow», но он сложнее в реализации, так как требует больше шагов. Из‑за сложности многие провайдеры в итоге рекомендуют «implicit flow».
/// note | Примечание
Часто каждый провайдер аутентификации называет свои «flows» по‑разному — как часть бренда.
Но в итоге они реализуют один и тот же стандарт OAuth2.
///
FastAPI включает утилиты для всех этих OAuth2flows в `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`.

View File

@@ -0,0 +1,346 @@
# Настройки и переменные окружения { #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 предоставляет отличную утилиту для работы с этими настройками, поступающими из переменных окружения, — <a href="https://docs.pydantic.dev/latest/concepts/pydantic_settings/" class="external-link" target="_blank">Pydantic: управление настройками</a>.
### Установка `pydantic-settings` { #install-pydantic-settings }
Сначала убедитесь, что вы создали [виртуальное окружение](../virtual-environments.md){.internal-link target=_blank}, активировали его, а затем установили пакет `pydantic-settings`:
<div class="termy">
```console
$ pip install pydantic-settings
---> 100%
```
</div>
Он также включен при установке набора `all` с:
<div class="termy">
```console
$ pip install "fastapi[all]"
---> 100%
```
</div>
/// info | Информация
В Pydantic v1 он входил в основной пакет. Теперь он распространяется как отдельный пакет, чтобы вы могли установить его только при необходимости.
///
### Создание объекта `Settings` { #create-the-settings-object }
Импортируйте `BaseSettings` из Pydantic и создайте подкласс, очень похожий на Pydanticмодель.
Аналогично Pydanticмоделям, вы объявляете атрибуты класса с аннотациями типов и, при необходимости, значениями по умолчанию.
Вы можете использовать все те же возможности валидации и инструменты, что и для Pydanticмоделей, например разные типы данных и дополнительную валидацию через `Field()`.
//// tab | Pydantic v2
{* ../../docs_src/settings/tutorial001.py hl[2,5:8,11] *}
////
//// tab | Pydantic v1
/// info | Информация
В Pydantic v1 вы бы импортировали `BaseSettings` напрямую из `pydantic`, а не из `pydantic_settings`.
///
{* ../../docs_src/settings/tutorial001_pv1.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.py hl[18:20] *}
### Запуск сервера { #run-the-server }
Далее вы можете запустить сервер, передав конфигурации через переменные окружения. Например, можно задать `ADMIN_EMAIL` и `APP_NAME` так:
<div class="termy">
```console
$ ADMIN_EMAIL="deadpool@example.com" APP_NAME="ChimichangApp" fastapi run main.py
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
```
</div>
/// 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/config.py *}
А затем использовать его в файле `main.py`:
{* ../../docs_src/settings/app01/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/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`:
{* ../../docs_src/settings/app02/test_main.py hl[9:10,13,21] *}
В переопределении зависимости мы задаем новое значение `admin_email` при создании нового объекта `Settings`, а затем возвращаем этот новый объект.
После этого можно протестировать, что он используется.
## Чтение файла `.env` { #reading-a-env-file }
Если у вас много настроек, которые могут часто меняться, возможно в разных окружениях, может быть удобно поместить их в файл и читать оттуда как переменные окружения.
Эта практика достаточно распространена и имеет название: такие переменные окружения обычно размещают в файле `.env`, а сам файл называют «dotenv».
/// tip | Совет
Файл, начинающийся с точки (`.`), является скрытым в системах, подобных Unix, таких как Linux и macOS.
Но файл dotenv не обязательно должен иметь именно такое имя.
///
Pydantic поддерживает чтение таких файлов с помощью внешней библиотеки. Подробнее вы можете прочитать здесь: <a href="https://docs.pydantic.dev/latest/concepts/pydantic_settings/#dotenv-env-support" class="external-link" target="_blank">Pydantic Settings: поддержка Dotenv (.env)</a>.
/// 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` так:
//// tab | Pydantic v2
{* ../../docs_src/settings/app03_an/config.py hl[9] *}
/// tip | Совет
Атрибут `model_config` используется только для конфигурации Pydantic. Подробнее см. <a href="https://docs.pydantic.dev/latest/concepts/config/" class="external-link" target="_blank">Pydantic: Concepts: Configuration</a>.
///
////
//// tab | Pydantic v1
{* ../../docs_src/settings/app03_an/config_pv1.py hl[9:10] *}
/// tip | Совет
Класс `Config` используется только для конфигурации Pydantic. Подробнее см. <a href="https://docs.pydantic.dev/1.10/usage/model_config/" class="external-link" target="_blank">Pydantic Model Config</a>.
///
////
/// 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 }
Чтение файла с диска обычно затратная (медленная) операция, поэтому, вероятно, вы захотите сделать это один раз и затем переиспользовать один и тот же объект настроек, а не читать файл при каждом запросе.
Но каждый раз, когда мы делаем:
```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` { #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. Подробнее можно прочитать в <a href="https://docs.python.org/3/library/functools.html#functools.lru_cache" class="external-link" target="_blank">документации Python по `@lru_cache`</a>.
## Итоги { #recap }
Вы можете использовать Pydantic Settings для управления настройками и конфигурациями вашего приложения с полной мощью Pydanticмоделей.
* Используя зависимость, вы упрощаете тестирование.
* Можно использовать файлы `.env`.
* `@lru_cache` позволяет не читать файл dotenv снова и снова для каждого запроса, при этом давая возможность переопределять его во время тестирования.

View File

@@ -0,0 +1,67 @@
# Подприложения — Mounts (монтирование) { #sub-applications-mounts }
Если вам нужны два независимых приложения FastAPI, каждое со своим собственным OpenAPI и собственными интерфейсами документации, вы можете иметь основное приложение и «смонтировать» одно (или несколько) подприложений.
## Монтирование приложения **FastAPI** { #mounting-a-fastapi-application }
«Монтирование» означает добавление полностью независимого приложения по конкретному пути; далее оно будет обрабатывать всё под этим путём, используя объявленные в подприложении _операции пути_.
### Приложение верхнего уровня { #top-level-application }
Сначала создайте основное, верхнего уровня, приложение **FastAPI** и его *операции пути*:
{* ../../docs_src/sub_applications/tutorial001.py hl[3, 6:8] *}
### Подприложение { #sub-application }
Затем создайте подприложение и его *операции пути*.
Это подприложение — обычное стандартное приложение FastAPI, но именно оно будет «смонтировано»:
{* ../../docs_src/sub_applications/tutorial001.py hl[11, 14:16] *}
### Смонтируйте подприложение { #mount-the-sub-application }
В вашем приложении верхнего уровня, `app`, смонтируйте подприложение `subapi`.
В этом случае оно будет смонтировано по пути `/subapi`:
{* ../../docs_src/sub_applications/tutorial001.py hl[11, 19] *}
### Проверьте автоматическую документацию API { #check-the-automatic-api-docs }
Теперь запустите команду `fastapi` с вашим файлом:
<div class="termy">
```console
$ fastapi dev main.py
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
```
</div>
И откройте документацию по адресу <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
Вы увидите автоматическую документацию API для основного приложения, включающую только его собственные _операции пути_:
<img src="/img/tutorial/sub-applications/image01.png">
Затем откройте документацию для подприложения по адресу <a href="http://127.0.0.1:8000/subapi/docs" class="external-link" target="_blank">http://127.0.0.1:8000/subapi/docs</a>.
Вы увидите автоматическую документацию API для подприложения, включающую только его собственные _операции пути_, все под корректным префиксом подпути `/subapi`:
<img src="/img/tutorial/sub-applications/image02.png">
Если вы попробуете взаимодействовать с любым из двух интерфейсов, всё будет работать корректно, потому что браузер сможет обращаться к каждому конкретному приложению и подприложению.
### Технические подробности: `root_path` { #technical-details-root-path }
Когда вы монтируете подприложение, как описано выше, FastAPI позаботится о передаче пути монтирования для подприложения, используя механизм из спецификации ASGI под названием `root_path`.
Таким образом подприложение будет знать, что для интерфейса документации нужно использовать этот префикс пути.
У подприложения также могут быть свои собственные смонтированные подприложения, и всё будет работать корректно, потому что FastAPI автоматически обрабатывает все эти `root_path`.
Вы узнаете больше о `root_path` и о том, как использовать его явно, в разделе [За прокси](behind-a-proxy.md){.internal-link target=_blank}.

View File

@@ -0,0 +1,126 @@
# Шаблоны { #templates }
Вы можете использовать любой шаблонизатор вместе с **FastAPI**.
Часто выбирают Jinja2 — тот же, что используется во Flask и других инструментах.
Есть утилиты для простой настройки, которые вы можете использовать прямо в своем приложении **FastAPI** (предоставляются Starlette).
## Установка зависимостей { #install-dependencies }
Убедитесь, что вы создали [виртуальное окружение](../virtual-environments.md){.internal-link target=_blank}, активировали его и установили `jinja2`:
<div class="termy">
```console
$ pip install jinja2
---> 100%
```
</div>
## Использование `Jinja2Templates` { #using-jinja2templates }
- Импортируйте `Jinja2Templates`.
- Создайте объект `templates`, который сможете переиспользовать позже.
- Объявите параметр `Request` в *операции пути*, которая будет возвращать шаблон.
- Используйте созданный `templates`, чтобы отрендерить и вернуть `TemplateResponse`; передайте имя шаблона, объект `request` и словарь «context» с парами ключ-значение для использования внутри шаблона Jinja2.
{* ../../docs_src/templates/tutorial001.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`, взятый из переданного вами «context» `dict`:
```Python
{"id": id}
```
Например, для ID `42` это отрендерится как:
```html
Item ID: 42
```
### Аргументы `url_for` в шаблоне { #template-url-for-arguments }
Вы также можете использовать `url_for()` внутри шаблона — он принимает те же аргументы, что использовались бы вашей *функцией-обработчиком пути*.
Таким образом, фрагмент:
{% raw %}
```jinja
<a href="{{ url_for('read_item', id=id) }}">
```
{% endraw %}
...сгенерирует ссылку на тот же URL, который обрабатывается *функцией-обработчиком пути* `read_item(id=id)`.
Например, для ID `42` это отрендерится как:
```html
<a href="/items/42">
```
## Шаблоны и статические файлы { #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 }
Больше подробностей, включая то, как тестировать шаблоны, смотрите в <a href="https://www.starlette.io/templates/" class="external-link" target="_blank">документации Starlette по шаблонам</a>.

View File

@@ -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 | Совет
Если вы хотите переопределять зависимость только во время некоторых тестов, задайте переопределение в начале теста (внутри функции теста) и сбросьте его в конце (в конце функции теста).
///

View File

@@ -0,0 +1,12 @@
# Тестирование событий: lifespan и startup - shutdown { #testing-events-lifespan-and-startup-shutdown }
Если вам нужно, чтобы `lifespan` выполнялся в ваших тестах, вы можете использовать `TestClient` вместе с оператором `with`:
{* ../../docs_src/app_testing/tutorial004.py hl[9:15,18,27:28,30:32,41:43] *}
Вы можете узнать больше подробностей в статье [Запуск lifespan в тестах на официальном сайте документации Starlette.](https://www.starlette.io/lifespan/#running-lifespan-in-tests)
Для устаревших событий `startup` и `shutdown` вы можете использовать `TestClient` следующим образом:
{* ../../docs_src/app_testing/tutorial003.py hl[9:12,20:24] *}

View File

@@ -0,0 +1,13 @@
# Тестирование WebSocket { #testing-websockets }
Вы можете использовать тот же `TestClient` для тестирования WebSocket.
Для этого используйте `TestClient` с менеджером контекста `with`, подключаясь к WebSocket:
{* ../../docs_src/app_testing/tutorial002.py hl[27:31] *}
/// note | Примечание
Подробности смотрите в документации Starlette по <a href="https://www.starlette.io/testclient/#testing-websocket-sessions" class="external-link" target="_blank">тестированию WebSocket</a>.
///

View File

@@ -0,0 +1,56 @@
# Прямое использование Request { #using-the-request-directly }
До этого вы объявляли нужные части HTTP-запроса вместе с их типами.
Извлекая данные из:
* пути (как параметров),
* HTTP-заголовков,
* Cookie,
* и т.д.
Тем самым **FastAPI** валидирует эти данные, преобразует их и автоматически генерирует документацию для вашего API.
Но бывают ситуации, когда нужно обратиться к объекту `Request` напрямую.
## Подробности об объекте `Request` { #details-about-the-request-object }
Так как под капотом **FastAPI** — это **Starlette** с дополнительным слоем инструментов, вы можете при необходимости напрямую использовать объект <a href="https://www.starlette.io/requests/" class="external-link" target="_blank">`Request`</a> из Starlette.
Это также означает, что если вы получаете данные напрямую из объекта `Request` (например, читаете тело запроса), то они не будут валидироваться, конвертироваться или документироваться (с OpenAPI, для автоматического пользовательского интерфейса API) средствами FastAPI.
При этом любой другой параметр, объявленный обычным образом (например, тело запроса с Pydantic-моделью), по-прежнему будет валидироваться, конвертироваться, аннотироваться и т.д.
Но есть конкретные случаи, когда полезно получить объект `Request`.
## Используйте объект `Request` напрямую { #use-the-request-object-directly }
Представим, что вы хотите получить IP-адрес/хост клиента внутри вашей *функции-обработчика пути*.
Для этого нужно обратиться к запросу напрямую.
{* ../../docs_src/using_request_directly/tutorial001.py hl[1,7:8] *}
Если объявить параметр *функции-обработчика пути* с типом `Request`, **FastAPI** поймёт, что нужно передать объект `Request` в этот параметр.
/// tip | Совет
Обратите внимание, что в этом примере мы объявляем path-параметр вместе с параметром `Request`.
Таким образом, path-параметр будет извлечён, валидирован, преобразован к указанному типу и задокументирован в OpenAPI.
Точно так же вы можете объявлять любые другие параметры как обычно и, дополнительно, получать `Request`.
///
## Документация по `Request` { #request-documentation }
Подробнее об <a href="https://www.starlette.io/requests/" class="external-link" target="_blank">объекте `Request` на официальном сайте документации Starlette</a>.
/// note | Технические детали
Вы также можете использовать `from starlette.requests import Request`.
**FastAPI** предоставляет его напрямую для удобства разработчика, но сам объект приходит из Starlette.
///

View File

@@ -1,10 +1,10 @@
# Веб-сокеты
# Веб-сокеты { #websockets }
Вы можете использовать <a href="https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API" class="external-link" target="_blank">веб-сокеты</a> в **FastAPI**.
## Установка `WebSockets`
## Установка `websockets` { #install-websockets }
Убедитесь, что [виртуальная среда](../virtual-environments.md){.internal-link target=_blank} создана, активируйте её и установите `websockets`:
Убедитесь, что вы создали [виртуальное окружение](../virtual-environments.md){.internal-link target=_blank}, активировали его и установили `websockets` (библиотека Python, упрощающая работу с протоколом "WebSocket"):
<div class="termy">
@@ -16,31 +16,31 @@ $ pip install websockets
</div>
## Клиент WebSockets
## Клиент WebSockets { #websockets-client }
### Рабочее приложение
### В продакшн { #in-production }
Скорее всего, в вашей реальной продуктовой системе есть фронтенд, реализованный при помощи современных фреймворков React, Vue.js или Angular.
В продакшн у вас, вероятно, есть фронтенд, созданный с помощью современного фреймворка вроде React, Vue.js или Angular.
И наверняка для взаимодействия с бекендом через веб-сокеты вы будете использовать средства фронтенда.
И для взаимодействия с бекендом по WebSocket вы, скорее всего, будете использовать инструменты вашего фронтенда.
Также у вас может быть нативное мобильное приложение, коммуницирующее непосредственно с веб-сокетами на бекенд-сервере.
Также у вас может быть нативное мобильное приложение, которое напрямую, нативным кодом, взаимодействует с вашим WebSocket-бекендом.
Либо вы можете сделать какой-либо другой способ взаимодействия с веб-сокетами.
Либо у вас может быть любой другой способ взаимодействия с WebSocket-эндпоинтом.
---
Но для этого примера мы воспользуемся очень простым HTML документом с небольшими вставками JavaScript кода.
Но для этого примера мы воспользуемся очень простым HTMLдокументом с небольшим JavaScript, всё внутри одной длинной строки.
Конечно же это неоптимально, и на практике так делать не стоит.
Конечно же, это неоптимально, и вы бы не использовали это в продакшн.
В реальных приложениях стоит воспользоваться одним из вышеупомянутых способов.
В продакшн у вас был бы один из вариантов выше.
Для примера нам нужен наиболее простой способ, который позволит сосредоточиться на серверной части веб-сокетов и получить рабочий код:
Для примера нам нужен наиболее простой способ, который позволит сосредоточиться на серверной части вебсокетов и получить рабочий код:
{* ../../docs_src/websockets/tutorial001.py hl[2,6:38,41:43] *}
## Создание `websocket`
## Создание `websocket` { #create-a-websocket }
Создайте `websocket` в своем **FastAPI** приложении:
@@ -54,7 +54,7 @@ $ pip install websockets
///
## Ожидание и отправка сообщений
## Ожидание и отправка сообщений { #await-for-messages-and-send-messages }
Через эндпоинт веб-сокета вы можете получать и отправлять сообщения.
@@ -62,7 +62,7 @@ $ pip install websockets
Вы можете получать и отправлять двоичные, текстовые и JSON данные.
## Проверка в действии
## Проверка в действии { #try-it }
Если ваш файл называется `main.py`, то запустите приложение командой:
@@ -96,7 +96,7 @@ $ fastapi dev main.py
И все они будут использовать одно и то же веб-сокет соединение.
## Использование `Depends` и не только
## Использование `Depends` и не только { #using-depends-and-others }
Вы можете импортировать из `fastapi` и использовать в эндпоинте вебсокета:
@@ -119,7 +119,7 @@ $ fastapi dev main.py
///
### Веб-сокеты с зависимостями: проверка в действии
### Веб-сокеты с зависимостями: проверка в действии { #try-the-websockets-with-dependencies }
Если ваш файл называется `main.py`, то запустите приложение командой:
@@ -150,7 +150,7 @@ $ fastapi dev main.py
<img src="/img/tutorial/websockets/image05.png">
## Обработка отключений и работа с несколькими клиентами
## Обработка отключений и работа с несколькими клиентами { #handling-disconnections-and-multiple-clients }
Если веб-сокет соединение закрыто, то `await websocket.receive_text()` вызовет исключение `WebSocketDisconnect`, которое можно поймать и обработать как в этом примере:
@@ -168,7 +168,7 @@ $ fastapi dev main.py
Client #1596980209979 left the chat
```
/// tip | Примечание
/// tip | Подсказка
Приложение выше - это всего лишь простой минимальный пример, демонстрирующий обработку и передачу сообщений нескольким веб-сокет соединениям.
@@ -178,7 +178,7 @@ Client #1596980209979 left the chat
///
## Дополнительная информация
## Дополнительная информация { #more-info }
Для более глубокого изучения темы воспользуйтесь документацией Starlette:

View File

@@ -0,0 +1,35 @@
# Подключение WSGI — Flask, Django и другие { #including-wsgi-flask-django-others }
Вы можете монтировать WSGIприложения, как вы видели в [Подприложения — Mounts](sub-applications.md){.internal-link target=_blank}, [За прокси‑сервером](behind-a-proxy.md){.internal-link target=_blank}.
Для этого вы можете использовать `WSGIMiddleware` и обернуть им ваше WSGIприложение, например Flask, Django и т.д.
## Использование `WSGIMiddleware` { #using-wsgimiddleware }
Нужно импортировать `WSGIMiddleware`.
Затем оберните WSGIприложение (например, Flask) в middleware (Промежуточный слой).
После этого смонтируйте его на путь.
{* ../../docs_src/wsgi/tutorial001.py hl[2:3,3] *}
## Проверьте { #check-it }
Теперь каждый HTTPзапрос по пути `/v1/` будет обрабатываться приложением Flask.
А всё остальное будет обрабатываться **FastAPI**.
Если вы запустите это и перейдёте по <a href="http://localhost:8000/v1/" class="external-link" target="_blank">http://localhost:8000/v1/</a>, вы увидите HTTPответ от Flask:
```txt
Hello, World from Flask!
```
А если вы перейдёте по <a href="http://localhost:8000/v2" class="external-link" target="_blank">http://localhost:8000/v2</a>, вы увидите HTTPответ от FastAPI:
```JSON
{
"message": "Hello World"
}
```

View File

@@ -1,104 +1,94 @@
# Альтернативы, источники вдохновения и сравнения
# Альтернативы, источники вдохновения и сравнения { #alternatives-inspiration-and-comparisons }
Что вдохновило на создание **FastAPI**, сравнение его с альтернативами и чему он научился у них.
Что вдохновило **FastAPI**, сравнение с альтернативами и чему он у них научился.
## Введение
## Введение { #intro }
**FastAPI** не существовал бы, если б не было более ранних работ других людей.
**FastAPI** не существовал бы без предыдущих работ других людей.
Они создали большое количество инструментов, которые вдохновили меня на создание **FastAPI**.
Было создано множество инструментов, которые вдохновили на его появление.
Я всячески избегал создания нового фреймворка в течение нескольких лет.
Сначала я пытался собрать все нужные функции, которые ныне есть в **FastAPI**, используя множество различных фреймворков, плагинов и инструментов.
Я несколько лет избегал создания нового фреймворка. Сначала пытался закрыть все возможности, которые сейчас предоставляет **FastAPI**, с помощью множества разных фреймворков, плагинов и инструментов.
Но в какой-то момент не осталось другого выбора, кроме как создать что-то, что предоставляло бы все эти функции сразу.
Взять самые лучшие идеи из предыдущих инструментов и, используя новые возможности Python (которых не было до версии 3.6, то есть подсказки типов), объединить их.
Но в какой-то момент не осталось другого варианта, кроме как создать что-то, что включает все эти возможности, взяв лучшие идеи из прежних инструментов и совместив их максимально удачным образом, используя возможности языка, которых прежде не было (аннотации типов в Python 3.6+).
## Предшествующие инструменты
## Предшествующие инструменты { #previous-tools }
### <a href="https://www.djangoproject.com/" class="external-link" target="_blank">Django</a>
### <a href="https://www.djangoproject.com/" class="external-link" target="_blank">Django</a> { #django }
Это самый популярный Python-фреймворк, и он пользуется доверием.
Он используется для создания проектов типа Instagram.
Это самый популярный Python-фреймворк, ему широко доверяют. Он используется для построения систем вроде Instagram.
Django довольно тесно связан с реляционными базами данных (такими как MySQL или PostgreSQL), потому использовать NoSQL базы данных (например, Couchbase, MongoDB, Cassandra и т.п.) в качестве основного хранилища данных - непросто.
Он относительно тесно связан с реляционными базами данных (например, MySQL или PostgreSQL), поэтому использовать NoSQL-базу данных (например, Couchbase, MongoDB, Cassandra и т. п.) в качестве основного хранилища не очень просто.
Он был создан для генерации HTML-страниц на сервере, а не для создания API, используемых современными веб-интерфейсами (React, Vue.js, Angular и т.п.) или другими системами (например, <abbr title="Интернет вещей">IoT</abbr>) взаимодействующими с сервером.
Он был создан для генерации HTML на бэкенде, а не для создания API, используемых современным фронтендом (например, React, Vue.js и Angular) или другими системами (например, устройствами <abbr title="Internet of Things Интернет вещей">IoT</abbr>), которые с ним общаются.
### <a href="https://www.django-rest-framework.org/" class="external-link" target="_blank">Django REST Framework</a>
### <a href="https://www.django-rest-framework.org/" class="external-link" target="_blank">Django REST Framework</a> { #django-rest-framework }
Фреймворк Django REST был создан, как гибкий инструментарий для создания веб-API на основе Django.
Django REST Framework был создан как гибкий набор инструментов для построения веб-API поверх Django, чтобы улучшить его возможности в части API.
DRF использовался многими компаниями, включая Mozilla, Red Hat и Eventbrite.
Он используется многими компаниями, включая Mozilla, Red Hat и Eventbrite.
Это был один из первых примеров **автоматического документирования API** и это была одна из первых идей, вдохновивших на создание **FastAPI**.
Это был один из первых примеров **автоматической документации API**, и именно эта идея одной из первых вдохновила на «поиск» **FastAPI**.
/// note | Заметка
Django REST Framework был создан Tom Christie.
Он же создал Starlette и Uvicorn, на которых основан **FastAPI**.
Django REST Framework был создан Томом Кристи. Он же создал Starlette и Uvicorn, на которых основан **FastAPI**.
///
/// check | Идея для **FastAPI**
/// check | Вдохновило **FastAPI** на
Должно быть автоматическое создание документации API с пользовательским веб-интерфейсом.
Наличие пользовательского веб-интерфейса с автоматической документацией API.
///
### <a href="https://flask.palletsprojects.com" class="external-link" target="_blank">Flask</a>
### <a href="https://flask.palletsprojects.com" class="external-link" target="_blank">Flask</a> { #flask }
Flask - это "микрофреймворк", в нём нет интеграции с базами данных и многих других вещей, которые предустановлены в Django.
Flask это «микрофреймворк», он не включает интеграции с базами данных и многие другие вещи, которые в Django идут «из коробки».
Его простота и гибкость дают широкие возможности, такие как использование баз данных NoSQL в качестве основной системы хранения данных.
Эта простота и гибкость позволяет, например, использовать NoSQL-базы в качестве основной системы хранения данных.
Он очень прост, его изучение интуитивно понятно, хотя в некоторых местах документация довольно техническая.
Он очень прост, его относительно легко интуитивно освоить, хотя местами документация довольно техническая.
Flask часто используется и для приложений, которым не нужна база данных, настройки прав доступа для пользователей и прочие из множества функций, предварительно встроенных в Django.
Хотя многие из этих функций могут быть добавлены с помощью плагинов.
Его также часто используют для приложений, которым не нужна база данных, управление пользователями или многие другие функции, предварительно встроенные в Django. Хотя многие из этих возможностей можно добавить плагинами.
Такое разделение на части и то, что это "микрофреймворк", который можно расширить, добавляя необходимые возможности, было ключевой особенностью, которую я хотел сохранить.
Такое разбиение на части и то, что это «микрофреймворк», который можно расширять ровно под нужды, — ключевая особенность, которую хотелось сохранить.
Простота Flask, показалась мне подходящей для создания API.
Но ещё нужно было найти "Django REST Framework" для Flask.
С учётом простоты Flask он казался хорошим вариантом для создания API. Следующим было найти «Django REST Framework» для Flask.
/// check | Идеи для **FastAPI**
/// check | Вдохновило **FastAPI** на
Это будет микрофреймворк. К нему легко будет добавить необходимые инструменты и части.
Быть микро-фреймворком. Облегчить комбинирование необходимых инструментов и компонентов.
Должна быть простая и лёгкая в использовании система маршрутизации запросов.
Иметь простую и удобную систему маршрутизации.
///
### <a href="https://requests.readthedocs.io" class="external-link" target="_blank">Requests</a>
### <a href="https://requests.readthedocs.io" class="external-link" target="_blank">Requests</a> { #requests }
На самом деле **FastAPI** не является альтернативой **Requests**.
Их область применения очень разная.
**FastAPI** на самом деле не альтернатива **Requests**. Их области применения очень различны.
В принципе, можно использовать Requests *внутри* приложения FastAPI.
Обычно Requests используют даже внутри приложения FastAPI.
Но всё же я использовал в FastAPI некоторые идеи из Requests.
И всё же **FastAPI** во многом вдохновлялся Requests.
**Requests** - это библиотека для взаимодействия с API в качестве клиента,
в то время как **FastAPI** - это библиотека для *создания* API (то есть сервера).
**Requests** это библиотека для взаимодействия с API (как клиент), а **FastAPI** — библиотека для создания API (как сервер).
Они, так или иначе, диаметрально противоположны и дополняют друг друга.
Они, в каком-то смысле, находятся на противоположных концах и дополняют друг друга.
Requests имеет очень простой и понятный дизайн, очень прост в использовании и имеет разумные значения по умолчанию.
И в то же время он очень мощный и настраиваемый.
Requests имеет очень простой и понятный дизайн, им очень легко пользоваться, есть разумные значения по умолчанию. И при этом он очень мощный и настраиваемый.
Вот почему на официальном сайте написано:
Именно поэтому на официальном сайте сказано:
> Requests - один из самых загружаемых пакетов Python всех времен
> Requests один из самых загружаемых Python-пакетов всех времён
Использовать его очень просто. Например, чтобы выполнить запрос `GET`, Вы бы написали:
Пользоваться им очень просто. Например, чтобы сделать запрос `GET`, вы бы написали:
```Python
response = requests.get("http://example.com/some/url")
```
Противоположная *операция пути* в FastAPI может выглядеть следующим образом:
Соответствующая в FastAPI API-операция пути могла бы выглядеть так:
```Python hl_lines="1"
@app.get("/some/url")
@@ -106,428 +96,390 @@ def read_url():
return {"message": "Hello World"}
```
Глядите, как похоже `requests.get(...)` и `@app.get(...)`.
Посмотрите, насколько похожи `requests.get(...)` и `@app.get(...)`.
/// check | Идеи для **FastAPI**
/// check | Вдохновило **FastAPI** на
* Должен быть простой и понятный API.
* Нужно использовать названия HTTP-методов (операций) для упрощения понимания происходящего.
* Должны быть разумные настройки по умолчанию и широкие возможности их кастомизации.
* Иметь простой и понятный API.
* Использовать названия HTTP-методов (операций) напрямую, простым и интуитивным образом.
* Иметь разумные значения по умолчанию, но и мощные настройки.
///
### <a href="https://swagger.io/" class="external-link" target="_blank">Swagger</a> / <a href="https://github.com/OAI/OpenAPI-Specification/" class="external-link" target="_blank">OpenAPI</a>
### <a href="https://swagger.io/" class="external-link" target="_blank">Swagger</a> / <a href="https://github.com/OAI/OpenAPI-Specification/" class="external-link" target="_blank">OpenAPI</a> { #swagger-openapi }
Главной функцией, которую я хотел унаследовать от Django REST Framework, была автоматическая документация API.
Главной возможностью, которую хотелось взять из Django REST Framework, была автоматическая документация API.
Но потом я обнаружил, что существует стандарт документирования API, использующий JSON (или YAML, расширение JSON) под названием Swagger.
Затем я обнаружил, что есть стандарт для документирования API с использованием JSON (или YAML расширения JSON), под названием Swagger.
И к нему уже был создан пользовательский веб-интерфейс.
Таким образом, возможность генерировать документацию Swagger для API позволила бы использовать этот интерфейс.
И уже существовал веб-интерфейс для Swagger API. Поэтому возможность генерировать документацию Swagger для API позволила бы автоматически использовать этот веб-интерфейс.
В какой-то момент Swagger был передан Linux Foundation и переименован в OpenAPI.
Вот почему, когда говорят о версии 2.0, обычно говорят "Swagger", а для версии 3+ "OpenAPI".
Вот почему, говоря о версии 2.0, обычно говорят «Swagger», а о версии 3+ — «OpenAPI».
/// check | Идеи для **FastAPI**
/// check | Вдохновило **FastAPI** на
Использовать открытые стандарты для спецификаций API вместо самодельных схем.
Использовать открытый стандарт для спецификаций API вместо самодельной схемы.
Совместимость с основанными на стандартах пользовательскими интерфейсами:
И интегрировать основанные на стандартах инструменты пользовательского интерфейса:
* <a href="https://github.com/swagger-api/swagger-ui" class="external-link" target="_blank">Swagger UI</a>
* <a href="https://github.com/Rebilly/ReDoc" class="external-link" target="_blank">ReDoc</a>
Они были выбраны за популярность и стабильность.
Но сделав беглый поиск, Вы можете найти десятки альтернативных пользовательских интерфейсов для OpenAPI, которые Вы можете использовать с **FastAPI**.
Эти два инструмента выбраны за популярность и стабильность, но даже при беглом поиске можно найти десятки альтернативных интерфейсов для OpenAPI (которые можно использовать с **FastAPI**).
///
### REST фреймворки для Flask
### REST-фреймворки для Flask { #flask-rest-frameworks }
Существует несколько REST фреймворков для Flask, но потратив время и усилия на их изучение, я обнаружил, что многие из них не обновляются или заброшены и имеют нерешённые проблемы из-за которых они непригодны к использованию.
Существует несколько REST-фреймворков для Flask, но, вложив время и усилия в исследование, я обнаружил, что многие из них прекращены или заброшены, с несколькими нерешёнными Issue (тикет\обращение), из-за которых они непригодны.
### <a href="https://marshmallow.readthedocs.io/en/stable/" class="external-link" target="_blank">Marshmallow</a>
### <a href="https://marshmallow.readthedocs.io/en/stable/" class="external-link" target="_blank">Marshmallow</a> { #marshmallow }
Одной из основных функций, необходимых системам API, является "<abbr title="также называют маршаллингом или преобразованием">сериализация</abbr>" данных, то есть преобразование данных из кода (Python) во что-то, что может быть отправлено по сети.
Например, превращение объекта содержащего данные из базы данных в объект JSON, конвертация объекта `datetime` в строку и т.п.
Одна из основных возможностей, нужных системам API, — «<abbr title="также называемая маршаллингом или преобразованием">сериализация</abbr>» данных, то есть преобразование данных из кода (Python) во что-то, что можно отправить по сети. Например, преобразование объекта с данными из базы в JSON-объект. Преобразование объектов `datetime` в строки и т. п.
Еще одна важная функция, необходимая API — проверка данных, позволяющая убедиться, что данные действительны и соответствуют заданным параметрам.
Как пример, можно указать, что ожидаются данные типа `int`, а не какая-то произвольная строка.
Это особенно полезно для входящих данных.
Ещё одна важная возможность, востребованная API,валидация данных: убеждаться, что данные валидны с учётом заданных параметров. Например, что какое-то поле — `int`, а не произвольная строка. Это особенно полезно для входящих данных.
Без системы проверки данных Вам пришлось бы прописывать все проверки вручную.
Без системы валидации данных вам пришлось бы выполнять все проверки вручную в коде.
Именно для обеспечения этих функций и была создана Marshmallow.
Это отличная библиотека и я много раз пользовался ею раньше.
Именно для этих возможностей и был создан Marshmallow. Это отличная библиотека, я много ей пользовался раньше.
Но она была создана до того, как появились подсказки типов Python.
Итак, чтобы определить каждую <abbr title="Формат данных">схему</abbr>,
Вам нужно использовать определенные утилиты и классы, предоставляемые Marshmallow.
Но она появилась до того, как в Python появились аннотации типов. Поэтому для определения каждой <abbr title="описание того, как данные должны быть сформированы">схемы</abbr> нужно использовать специальные утилиты и классы, предоставляемые Marshmallow.
/// check | Идея для **FastAPI**
/// check | Вдохновило **FastAPI** на
Использовать код программы для автоматического создания "схем", определяющих типы данных и их проверку.
Использовать код для автоматического определения «схем», задающих типы данных и их валидацию.
///
### <a href="https://webargs.readthedocs.io/en/latest/" class="external-link" target="_blank">Webargs</a>
### <a href="https://webargs.readthedocs.io/en/latest/" class="external-link" target="_blank">Webargs</a> { #webargs }
Другая немаловажная функция API - <abbr title="чтение и преобразование данных в объекты Python">парсинг</abbr> данных из входящих запросов.
Ещё одна важная возможность для API <abbr title="чтение и преобразование данных в объекты Python">парсинг</abbr> данных из входящих HTTP-запросов.
Webargs - это инструмент, который был создан для этого и поддерживает несколько фреймворков, включая Flask.
Webargs это инструмент, созданный для этого поверх нескольких фреймворков, включая Flask.
Для проверки данных он использует Marshmallow и создан теми же авторами.
Он использует Marshmallow для валидации данных. И создан теми же разработчиками.
Это превосходный инструмент и я тоже часто пользовался им до **FastAPI**.
Это отличный инструмент, и я тоже много им пользовался до появления **FastAPI**.
/// info | Информация
Webargs бы создан разработчиками Marshmallow.
Webargs был создан теми же разработчиками, что и Marshmallow.
///
/// check | Идея для **FastAPI**
/// check | Вдохновило **FastAPI** на
Должна быть автоматическая проверка входных данных.
Автоматическую валидацию входящих данных HTTP-запроса.
///
### <a href="https://apispec.readthedocs.io/en/stable/" class="external-link" target="_blank">APISpec</a>
### <a href="https://apispec.readthedocs.io/en/stable/" class="external-link" target="_blank">APISpec</a> { #apispec }
Marshmallow и Webargs осуществляют проверку, анализ и сериализацию данных как плагины.
Marshmallow и Webargs предоставляют валидацию, парсинг и сериализацию как плагины.
Но документации API всё ещё не было. Тогда был создан APISpec.
Но документации всё ещё не было. Тогда появился APISpec.
Это плагин для множества фреймворков, в том числе и для Starlette.
Это плагин для многих фреймворков (есть плагин и для Starlette).
Он работает так - Вы записываете определение схем, используя формат YAML, внутри докстринга каждой функции, обрабатывающей маршрут.
Он работает так: вы пишете определение схемы в формате YAML внутри докстринга каждой функции, обрабатывающей маршрут.
Используя эти докстринги, он генерирует схему OpenAPI.
И он генерирует схемы OpenAPI.
Так это работает для Flask, Starlette, Responder и т.п.
Так это работает во Flask, Starlette, Responder и т. д.
Но теперь у нас возникает новая проблема - наличие постороннего микро-синтаксиса внутри кода Python (большие YAML).
Но у нас снова возникает проблема: появляется микро-синтаксис внутри строки Python (большой YAML).
Редактор кода не особо может помочь в такой парадигме.
А изменив какие-то параметры или схемы для Marshmallow можно забыть отредактировать докстринг с YAML и сгенерированная схема становится недействительной.
Редактор кода мало чем может помочь. И если мы изменим параметры или схемы Marshmallow и забудем также изменить YAML в докстринге, сгенерированная схема устареет.
/// info | Информация
APISpec тоже был создан авторами Marshmallow.
APISpec был создан теми же разработчиками, что и Marshmallow.
///
/// check | Идея для **FastAPI**
/// check | Вдохновило **FastAPI** на
Необходима поддержка открытого стандарта для API - OpenAPI.
Поддержку открытого стандарта для API OpenAPI.
///
### <a href="https://flask-apispec.readthedocs.io/en/latest/" class="external-link" target="_blank">Flask-apispec</a>
### <a href="https://flask-apispec.readthedocs.io/en/latest/" class="external-link" target="_blank">Flask-apispec</a> { #flask-apispec }
Это плагин для Flask, который связан с Webargs, Marshmallow и APISpec.
Это плагин для Flask, который связывает Webargs, Marshmallow и APISpec.
Он получает информацию от Webargs и Marshmallow, а затем использует APISpec для автоматического создания схемы OpenAPI.
Он использует информацию из Webargs и Marshmallow, чтобы автоматически генерировать схемы OpenAPI с помощью APISpec.
Это отличный, но крайне недооценённый инструмент.
Он должен быть более популярен, чем многие плагины для Flask.
Возможно, это связано с тем, что его документация слишком скудна и абстрактна.
Отличный и недооценённый инструмент. Он заслуживает большей популярности, чем многие плагины для Flask. Возможно, из-за слишком краткой и абстрактной документации.
Он избавил от необходимости писать чужеродный синтаксис YAML внутри докстрингов.
Это решило проблему необходимости писать YAML (ещё один синтаксис) в докстрингах Python.
Такое сочетание Flask, Flask-apispec, Marshmallow и Webargs было моим любимым стеком при построении бэкенда до появления **FastAPI**.
Комбинация Flask, Flask-apispec с Marshmallow и Webargs была моим любимым бэкенд-стеком до создания **FastAPI**.
Использование этого стека привело к созданию нескольких генераторов проектов. Я и некоторые другие команды до сих пор используем их:
Его использование привело к созданию нескольких full-stack генераторов на Flask. Это основные стеки, которые я (и несколько внешних команд) использовали до сих пор:
* <a href="https://github.com/tiangolo/full-stack" class="external-link" target="_blank">https://github.com/tiangolo/full-stack</a>
* <a href="https://github.com/tiangolo/full-stack-flask-couchbase" class="external-link" target="_blank">https://github.com/tiangolo/full-stack-flask-couchbase</a>
* <a href="https://github.com/tiangolo/full-stack-flask-couchdb" class="external-link" target="_blank">https://github.com/tiangolo/full-stack-flask-couchdb</a>
Эти генераторы проектов также стали основой для [Генераторов проектов с **FastAPI**](project-generation.md){.internal-link target=_blank}.
И эти же full-stack генераторы стали основой для [Генераторов проектов **FastAPI**](project-generation.md){.internal-link target=_blank}.
/// info | Информация
Как ни странно, но Flask-apispec тоже создан авторами Marshmallow.
Flask-apispec был создан теми же разработчиками, что и Marshmallow.
///
/// check | Идея для **FastAPI**
/// check | Вдохновило **FastAPI** на
Схема OpenAPI должна создаваться автоматически и использовать тот же код, который осуществляет сериализацию и проверку данных.
Автоматическую генерацию схемы OpenAPI из того же кода, который определяет сериализацию и валидацию.
///
### <a href="https://nestjs.com/" class="external-link" target="_blank">NestJS</a> (и <a href="https://angular.io/" class="external-link" target="_blank">Angular</a>)
### <a href="https://nestjs.com/" class="external-link" target="_blank">NestJS</a> (и <a href="https://angular.io/" class="external-link" target="_blank">Angular</a>) { #nestjs-and-angular }
Здесь даже не используется Python. NestJS - этот фреймворк написанный на JavaScript (TypeScript), основанный на NodeJS и вдохновлённый Angular.
Это даже не Python. NestJS это JavaScript/TypeScript-фреймворк на NodeJS, вдохновлённый Angular.
Он позволяет получить нечто похожее на то, что можно сделать с помощью Flask-apispec.
Он достигает чего-то отчасти похожего на то, что можно сделать с Flask-apispec.
В него встроена система внедрения зависимостей, ещё одна идея взятая от Angular.
Однако требуется предварительная регистрация "внедрений" (как и во всех других известных мне системах внедрения зависимостей), что увеличивает количество и повторяемость кода.
В нём встроена система внедрения зависимостей, вдохновлённая Angular 2. Требуется предварительная регистрация «инжектируемых» компонентов (как и во всех известных мне системах внедрения зависимостей), что добавляет многословности и повторяемости кода.
Так как параметры в нём описываются с помощью типов TypeScript (аналогично подсказкам типов в Python), поддержка редактора работает довольно хорошо.
Поскольку параметры описываются с помощью типов TypeScript (аналог аннотаций типов в Python), поддержка редактора весьма хороша.
Но поскольку данные из TypeScript не сохраняются после компиляции в JavaScript, он не может полагаться на подсказки типов для определения проверки данных, сериализации и документации.
Из-за этого и некоторых дизайнерских решений, для валидации, сериализации и автоматической генерации схем, приходится во многих местах добавлять декораторы.
Таким образом, это становится довольно многословным.
Но так как данные о типах TypeScript не сохраняются после компиляции в JavaScript, он не может полагаться на типы для одновременного определения валидации, сериализации и документации. Из‑за этого и некоторых проектных решений для получения валидации, сериализации и автоматической генерации схем приходится добавлять декораторы во многих местах. В итоге это становится довольно многословным.
Кроме того, он не очень хорошо справляется с вложенными моделями.
Если в запросе имеется объект JSON, внутренние поля которого, в свою очередь, являются вложенными объектами JSON, это не может быть должным образом задокументировано и проверено.
Он плохо справляется с вложенными моделями. Если JSON-тело запроса — это объект JSON, содержащий внутренние поля, которые сами являются вложенными объектами JSON, это нельзя как следует задокументировать и провалидировать.
/// check | Идеи для **FastAPI**
/// check | Вдохновило **FastAPI** на
Нужно использовать подсказки типов, чтоб воспользоваться поддержкой редактора кода.
Использовать типы Python для отличной поддержки в редакторе кода.
Нужна мощная система внедрения зависимостей. Необходим способ для уменьшения повторов кода.
Иметь мощную систему внедрения зависимостей. Найти способ минимизировать повторение кода.
///
### <a href="https://sanic.readthedocs.io/en/latest/" class="external-link" target="_blank">Sanic</a>
### <a href="https://sanic.readthedocs.io/en/latest/" class="external-link" target="_blank">Sanic</a> { #sanic }
Sanic был одним из первых чрезвычайно быстрых Python-фреймворков основанных на `asyncio`.
Он был сделан очень похожим на Flask.
Это был один из первых чрезвычайно быстрых Python-фреймворков на основе `asyncio`. Он был сделан очень похожим на Flask.
/// note | Технические детали
В нём использован <a href="https://github.com/MagicStack/uvloop" class="external-link" target="_blank">`uvloop`</a> вместо стандартного цикла событий `asyncio`, что и сделало его таким быстрым.
Он использовал <a href="https://github.com/MagicStack/uvloop" class="external-link" target="_blank">`uvloop`</a> вместо стандартного цикла `asyncio` в Python. Это и сделало его таким быстрым.
Он явно вдохновил создателей Uvicorn и Starlette, которые в настоящее время быстрее Sanic в открытых бенчмарках.
Он явно вдохновил Uvicorn и Starlette, которые сейчас быстрее Sanic в открытых бенчмарках.
///
/// check | Идеи для **FastAPI**
/// check | Вдохновило **FastAPI** на
Должна быть сумасшедшая производительность.
Поиск способа достичь сумасшедшей производительности.
Для этого **FastAPI** основан на Starlette, самом быстром из доступных фреймворков (по замерам незаинтересованных лиц).
Именно поэтому **FastAPI** основан на Starlette, так как это самый быстрый доступный фреймворк (по данным сторонних бенчмарков).
///
### <a href="https://falconframework.org/" class="external-link" target="_blank">Falcon</a>
### <a href="https://falconframework.org/" class="external-link" target="_blank">Falcon</a> { #falcon }
Falcon - ещё один высокопроизводительный Python-фреймворк.
В нём минимум функций и он создан, чтоб быть основой для других фреймворков, например, Hug.
Falcon ещё один высокопроизводительный Python-фреймворк, он минималистичен и служит основой для других фреймворков, таких как Hug.
Функции в нём получают два параметра - "запрос к серверу" и "ответ сервера".
Затем Вы "читаете" часть запроса и "пишите" часть ответа.
Из-за такой конструкции невозможно объявить параметры запроса и тела сообщения со стандартными подсказками типов Python в качестве параметров функции.
Он спроектирован так, что функции получают два параметра: «request» и «response». Затем вы «читаете» части из запроса и «пишете» части в ответ. Из‑за такого дизайна невозможно объявить параметры запроса и тело запроса стандартными аннотациями типов Python как параметры функции.
Таким образом, и валидацию данных, и их сериализацию, и документацию нужно прописывать вручную.
Либо эти функции должны быть встроены во фреймворк, сконструированный поверх Falcon, как в Hug.
Такая же особенность присутствует и в других фреймворках, вдохновлённых идеей Falcon, использовать только один объект запроса и один объект ответа.
Поэтому валидация данных, сериализация и документация должны выполняться в коде вручную, не автоматически. Либо должны быть реализованы во фреймворке поверх Falcon, как в Hug. Та же особенность есть и в других фреймворках, вдохновлённых дизайном Falcon — с одним объектом запроса и одним объектом ответа в параметрах.
/// check | Идея для **FastAPI**
/// check | Вдохновило **FastAPI** на
Найдите способы добиться отличной производительности.
Поиск способов получить отличную производительность.
Объявлять параметры `ответа сервера` в функциях, как в Hug.
Вместе с Hug (так как Hug основан на Falcon) вдохновило **FastAPI** объявлять параметр `response` в функциях.
Хотя в FastAPI это необязательно и используется в основном для установки заголовков, куки и альтернативных кодов состояния.
Хотя в FastAPI это необязательно, и используется в основном для установки HTTP-заголовков, cookie и альтернативных статус-кодов.
///
### <a href="https://moltenframework.com/" class="external-link" target="_blank">Molten</a>
### <a href="https://moltenframework.com/" class="external-link" target="_blank">Molten</a> { #molten }
Molten мне попался на начальной стадии написания **FastAPI**. В нём были похожие идеи:
Я обнаружил Molten на ранних этапах создания **FastAPI**. И у него были очень похожие идеи:
* Использование подсказок типов.
* Валидация и документация исходя из этих подсказок.
* Основан на аннотациях типов Python.
* Валидация и документация из этих типов.
* Система внедрения зависимостей.
В нём не используются сторонние библиотеки (такие, как Pydantic) для валидации, сериализации и документации.
Поэтому переиспользовать эти определения типов непросто.
Он не использует стороннюю библиотеку для валидации, сериализации и документации, такую как Pydantic, — у него своя. Поэтому такие определения типов данных будет сложнее переиспользовать.
Также требуется более подробная конфигурация и используется стандарт WSGI, который не предназначен для использования с высокопроизводительными инструментами, такими как Uvicorn, Starlette и Sanic, в отличие от ASGI.
Требуются более многословные конфигурации. И так как он основан на WSGI (вместо ASGI), он не предназначен для использования преимуществ высокой производительности инструментов вроде Uvicorn, Starlette и Sanic.
Его система внедрения зависимостей требует предварительной регистрации, и зависимости определяются, как объявления типов.
Из-за этого невозможно объявить более одного "компонента" (зависимости), который предоставляет определенный тип.
Система внедрения зависимостей требует предварительной регистрации зависимостей, а зависимости разрешаются по объявленным типам. Поэтому невозможно объявить более одного «компонента», предоставляющего определённый тип.
Маршруты объявляются в единственном месте с использованием функций, объявленных в других местах (вместо использования декораторов, в которые могут быть обёрнуты функции, обрабатывающие конкретные ресурсы).
Это больше похоже на Django, чем на Flask и Starlette.
Он разделяет в коде вещи, которые довольно тесно связаны.
Маршруты объявляются в одном месте, используя функции, объявленные в других местах (вместо декораторов, которые можно разместить прямо над функцией, обрабатывающей эндпоинт). Это ближе к тому, как это делает Django, чем Flask (и Starlette). Это разделяет в коде вещи, которые довольно тесно связаны.
/// check | Идея для **FastAPI**
/// check | Вдохновило **FastAPI** на
Определить дополнительные проверки типов данных, используя значения атрибутов модели "по умолчанию".
Это улучшает помощь редактора и раньше это не было доступно в Pydantic.
Определять дополнительные проверки типов данных, используя значение «по умолчанию» атрибутов модели. Это улучшает поддержку в редакторе кода, и раньше этого не было в Pydantic.
Фактически это подтолкнуло на обновление Pydantic для поддержки одинакового стиля проверок (теперь этот функционал уже доступен в Pydantic).
Фактически это вдохновило на обновление частей Pydantic, чтобы поддерживать такой же стиль объявления валидации (вся эта функциональность теперь уже есть в Pydantic).
///
### <a href="https://github.com/hugapi/hug" class="external-link" target="_blank">Hug</a>
### <a href="https://github.com/hugapi/hug" class="external-link" target="_blank">Hug</a> { #hug }
Hug был одним из первых фреймворков, реализовавших объявление параметров API с использованием подсказок типов Python.
Эта отличная идея была использована и другими инструментами.
Hug был одним из первых фреймворков, реализовавших объявление типов параметров API с использованием аннотаций типов Python. Это была отличная идея, которая вдохновила и другие инструменты.
При объявлении параметров вместо стандартных типов Python использовались собственные типы, но всё же это был огромный шаг вперед.
Он использовал собственные типы в объявлениях вместо стандартных типов Python, но это всё равно был огромный шаг вперёд.
Это также был один из первых фреймворков, генерировавших полную API-схему в формате JSON.
Он также был одним из первых фреймворков, генерировавших собственную схему, описывающую весь API в JSON.
Данная схема не придерживалась стандартов вроде OpenAPI и JSON Schema.
Поэтому было бы непросто совместить её с другими инструментами, такими как Swagger UI.
Но опять же, это была очень инновационная идея.
Он не был основан на стандартах вроде OpenAPI и JSON Schema. Поэтому интегрировать его с другими инструментами, такими как Swagger UI, было бы непросто. Но, опять же, это была очень инновационная идея.
Ещё у него есть интересная и необычная функция: используя один и тот же фреймворк можно создавать и API, и <abbr title="Интерфейс командной строки">CLI</abbr>.
У него есть интересная и необычная особенность: с помощью одного и того же фреймворка можно создавать и API, и CLI.
Поскольку он основан на WSGI, старом стандарте для синхронных веб-фреймворков, он не может работать с веб-сокетами и другими модными штуками, но всё равно обладает высокой производительностью.
Так как он основан на предыдущем стандарте для синхронных веб-фреймворков Python (WSGI), он не может работать с WebSocket и прочим, хотя также демонстрирует высокую производительность.
/// info | Информация
Hug создан Timothy Crosley, автором <a href="https://github.com/timothycrosley/isort" class="external-link" target="_blank">`isort`</a>, отличного инструмента для автоматической сортировки импортов в Python-файлах.
Hug был создан Тимоти Кросли, тем же автором <a href="https://github.com/timothycrosley/isort" class="external-link" target="_blank">`isort`</a>, отличного инструмента для автоматической сортировки импортов в файлах Python.
///
/// check | Идеи для **FastAPI**
/// check | Идеи, вдохновившие **FastAPI**
Hug повлиял на создание некоторых частей APIStar и был одним из инструментов, которые я счел наиболее многообещающими, наряду с APIStar.
Hug вдохновил части APIStar и был одним из наиболее многообещающих инструментов, которые я нашёл, наряду с APIStar.
Hug натолкнул на мысли использовать в **FastAPI** подсказки типов Python для автоматического создания схемы, определяющей API и его параметры.
Hug помог вдохновить **FastAPI** использовать аннотации типов Python для объявления параметров и автоматически генерировать схему, определяющую API.
Hug вдохновил **FastAPI** объявить параметр `ответа` в функциях для установки заголовков и куки.
Hug вдохновил **FastAPI** объявлять параметр `response` в функциях для установки HTTP-заголовков и cookie.
///
### <a href="https://github.com/encode/apistar" class="external-link" target="_blank">APIStar</a> (<= 0.5)
### <a href="https://github.com/encode/apistar" class="external-link" target="_blank">APIStar</a> (<= 0.5) { #apistar-0-5 }
Непосредственно перед тем, как принять решение о создании **FastAPI**, я обнаружил **APIStar**.
В нем было почти все, что я искал и у него был отличный дизайн.
Прямо перед решением строить **FastAPI** я нашёл сервер **APIStar**. В нём было почти всё, что я искал, и отличный дизайн.
Это была одна из первых реализаций фреймворка, использующего подсказки типов для объявления параметров и запросов, которые я когда-либо видел (до NestJS и Molten).
Я нашёл его примерно в то же время, что и Hug, но APIStar использовал стандарт OpenAPI.
Это была одна из первых реализаций фреймворка, использующего аннотации типов Python для объявления параметров и запросов (до NestJS и Molten), которые я видел. Я обнаружил его примерно в то же время, что и Hug. Но APIStar использовал стандарт OpenAPI.
В нём были автоматические проверка и сериализация данных и генерация схемы OpenAPI основанные на подсказках типов в нескольких местах.
В нём были автоматические валидация данных, сериализация данных и генерация схемы OpenAPI на основе тех же аннотаций типов в нескольких местах.
При определении схемы тела сообщения не использовались подсказки типов, как в Pydantic, это больше похоже на Marshmallow, поэтому помощь редактора была недостаточно хорошей, но всё же APIStar был лучшим доступным вариантом.
Определение схемы тела запроса не использовало те же аннотации типов Python, как в Pydantic, это было ближе к Marshmallow, поэтому поддержка редактора была бы хуже, но всё равно APIStar оставался лучшим доступным вариантом.
На тот момент у него были лучшие показатели производительности (проигрывающие только Starlette).
На тот момент у него были лучшие показатели в бенчмарках (его превосходил только Starlette).
Изначально у него не было автоматической документации API для веб-интерфейса, но я знал, что могу добавить к нему Swagger UI.
Сначала у него не было вебUI для автоматической документации API, но я знал, что могу добавить к нему Swagger UI.
В APIStar была система внедрения зависимостей, которая тоже требовала предварительную регистрацию компонентов, как и ранее описанные инструменты.
Но, тем не менее, это была отличная штука.
У него была система внедрения зависимостей. Она требовала предварительной регистрации компонентов, как и другие инструменты, обсуждавшиеся выше. Но всё же это была отличная возможность.
Я не смог использовать его в полноценном проекте, так как были проблемы со встраиванием <abbr title="Авторизация и соответствующие допуски к операциям пути (эндпоинтам)">функций безопасности</abbr> в схему OpenAPI, из-за которых невозможно было встроить все функции, применяемые в генераторах проектов на основе Flask-apispec.
Я добавил в свой список задач создание пул-реквеста, добавляющего эту функциональность.
Мне так и не удалось использовать его в полном проекте, поскольку не было интеграции с системой безопасности, поэтому я не мог заменить все возможности, которые имел с full-stack генераторами на основе Flask-apispec. В моём бэклоге было создать пулл-реквест (запрос на изменение), добавляющий эту функциональность.
В дальнейшем фокус проекта сместился.
Затем фокус проекта сместился.
Это больше не был API-фреймворк, так как автор сосредоточился на Starlette.
Это перестал быть веб-фреймворк для API, так как автору нужно было сосредоточиться на Starlette.
Ныне APIStar - это набор инструментов для проверки спецификаций OpenAPI.
Сейчас APIStar это набор инструментов для валидации спецификаций OpenAPI, а не веб-фреймворк.
/// info | Информация
APIStar был создан Tom Christie. Тот самый парень, который создал:
APIStar был создан Томом Кристи. Тем самым человеком, который создал:
* Django REST Framework
* Starlette (на котором основан **FastAPI**)
* Uvicorn (используемый в Starlette и **FastAPI**)
* Uvicorn (используется Starlette и **FastAPI**)
///
/// check | Идеи для **FastAPI**
/// check | Вдохновило **FastAPI** на
Воплощение.
Существование.
Мне казалось блестящей идеей объявлять множество функций (проверка данных, сериализация, документация) с помощью одних и тех же типов Python, которые при этом обеспечивают ещё и помощь редактора кода.
Идея объявлять сразу несколько вещей (валидацию данных, сериализацию и документацию) с помощью одних и тех же типов Python, которые одновременно обеспечивают отличную поддержку в редакторе кода, показалась мне блестящей.
После долгих поисков среди похожих друг на друга фреймворков и сравнения их различий, APIStar стал самым лучшим выбором.
После долгих поисков похожего фреймворка и тестирования множества альтернатив APIStar был лучшим доступным вариантом.
Но APIStar перестал быть фреймворком для создания веб-сервера, зато появился Starlette, новая и лучшая основа для построения подобных систем.
Это была последняя капля, сподвигнувшая на создание **FastAPI**.
Затем APIStar перестал существовать как сервер, а был создан Starlette новая и лучшая основа для такой системы. Это стало окончательным вдохновением для создания **FastAPI**.
Я считаю **FastAPI** "духовным преемником" APIStar, улучившим его возможности благодаря урокам, извлечённым из всех упомянутых выше инструментов.
Я считаю **FastAPI** «духовным преемником» APIStar, который улучшает и расширяет возможности, систему типов и другие части, опираясь на уроки от всех этих предыдущих инструментов.
///
## Что используется в **FastAPI**
## Что используется в **FastAPI** { #used-by-fastapi }
### <a href="https://docs.pydantic.dev/" class="external-link" target="_blank">Pydantic</a>
### <a href="https://docs.pydantic.dev/" class="external-link" target="_blank">Pydantic</a> { #pydantic }
Pydantic - это библиотека для валидации данных, сериализации и документирования (используя JSON Schema), основываясь на подсказках типов Python, что делает его чрезвычайно интуитивным.
Pydantic это библиотека для определения валидации данных, сериализации и документации (с использованием JSON Schema) на основе аннотаций типов Python.
Его можно сравнить с Marshmallow, хотя в бенчмарках Pydantic быстрее, чем Marshmallow.
И он основан на тех же подсказках типов, которые отлично поддерживаются редакторами кода.
Благодаря этому он чрезвычайно интуитивен.
/// check | **FastAPI** использует Pydantic
Его можно сравнить с Marshmallow. Хотя в бенчмарках он быстрее Marshmallow. И поскольку он основан на тех же аннотациях типов Python, поддержка в редакторе кода отличная.
Для проверки данных, сериализации данных и автоматической документации моделей (на основе JSON Schema).
/// check | **FastAPI** использует его для
Затем **FastAPI** берёт эти схемы JSON и помещает их в схему OpenAPI, не касаясь других вещей, которые он делает.
Обработки всей валидации данных, сериализации данных и автоматической документации моделей (на основе JSON Schema).
Затем **FastAPI** берёт эти данные JSON Schema и помещает их в OpenAPI, помимо всех прочих функций.
///
### <a href="https://www.starlette.io/" class="external-link" target="_blank">Starlette</a>
### <a href="https://www.starlette.io/" class="external-link" target="_blank">Starlette</a> { #starlette }
Starlette - это легковесный <abbr title="Новый стандарт построения асинхронных веб-сервисов Python">ASGI</abbr> фреймворк/набор инструментов, который идеален для построения высокопроизводительных асинхронных сервисов.
Starlette это лёгкий <abbr title="Новый стандарт построения асинхронных веб-сервисов Python">ASGI</abbr> фреймворк/набор инструментов, идеально подходящий для создания высокопроизводительных asyncioсервисов.
Starlette очень простой и интуитивный.
Он разработан таким образом, чтобы быть легко расширяемым и иметь модульные компоненты.
Он очень простой и интуитивный. Спроектирован так, чтобы его было легко расширять, и чтобы компоненты были модульными.
В нём есть:
* Впечатляющая производительность.
* Поддержка веб-сокетов.
* Фоновые задачи.
* Обработка событий при старте и финише приложения.
* Тестовый клиент на основе HTTPX.
* Поддержка CORS, сжатие GZip, статические файлы, потоковая передача данных.
* Поддержка сессий и куки.
* Поддержка WebSocket.
* Фоновые задачи, выполняемые в том же процессе.
* События запуска и завершения.
* Тестовый клиент на базе HTTPX.
* CORS, GZip, статические файлы, потоковые ответы.
* Поддержка сессий и cookie.
* 100% покрытие тестами.
* 100% аннотированный код.
* Несколько жёстких зависимостей.
* 100% кодовой базы с аннотациями типов.
* Мало жёстких зависимостей.
В настоящее время Starlette показывает самую высокую скорость среди Python-фреймворков в тестовых замерах.
Быстрее только Uvicorn, который является сервером, а не фреймворком.
В настоящее время Starlette — самый быстрый из протестированных Python-фреймворков. Его превосходит только Uvicorn, который не фреймворк, а сервер.
Starlette обеспечивает весь функционал микрофреймворка, но не предоставляет автоматическую валидацию данных, сериализацию и документацию.
Starlette предоставляет весь базовый функционал веб-микрофреймворка.
**FastAPI** добавляет эти функции используя подсказки типов Python и Pydantic.
Ещё **FastAPI** добавляет систему внедрения зависимостей, утилиты безопасности, генерацию схемы OpenAPI и т.д.
Но он не предоставляет автоматическую валидацию данных, сериализацию или документацию.
Это одна из главных вещей, которые **FastAPI** добавляет поверх, всё на основе аннотаций типов Python (с использованием Pydantic). Плюс система внедрения зависимостей, утилиты безопасности, генерация схемы OpenAPI и т. д.
/// note | Технические детали
ASGI - это новый "стандарт" разработанный участниками команды Django.
Он пока что не является "стандартом в Python" (то есть принятым PEP), но процесс принятия запущен.
ASGI это новый «стандарт», разрабатываемый участниками core-команды Django. Он всё ещё не является «стандартом Python» (PEP), хотя процесс идёт.
Тем не менее он уже используется в качестве "стандарта" несколькими инструментами.
Это значительно улучшает совместимость, поскольку Вы можете переключиться с Uvicorn на любой другой ASGI-сервер (например, Daphne или Hypercorn) или Вы можете добавить ASGI-совместимые инструменты, такие как `python-socketio`.
Тем не менее его уже используют как «стандарт» несколько инструментов. Это сильно улучшает совместимость: вы можете заменить Uvicorn на любой другой ASGI-сервер (например, Daphne или Hypercorn) или добавить совместимые с ASGI инструменты, такие как `python-socketio`.
///
/// check | **FastAPI** использует Starlette
/// check | **FastAPI** использует его для
В качестве ядра веб-сервиса для обработки запросов, добавив некоторые функции сверху.
Обработки всех основных веб-частей. Добавляя возможности поверх.
Класс `FastAPI` наследуется напрямую от класса `Starlette`.
Класс `FastAPI` напрямую наследуется от класса `Starlette`.
Таким образом, всё что Вы могли делать со Starlette, Вы можете делать с **FastAPI**, по сути это прокачанный Starlette.
Так что всё, что вы можете сделать со Starlette, вы можете сделать напрямую с **FastAPI**, по сути это «Starlette на стероидах».
///
### <a href="https://www.uvicorn.org/" class="external-link" target="_blank">Uvicorn</a>
### <a href="https://www.uvicorn.org/" class="external-link" target="_blank">Uvicorn</a> { #uvicorn }
Uvicorn - это молниеносный ASGI-сервер, построенный на uvloop и httptools.
Uvicorn молниеносный ASGI-сервер, построенный на uvloop и httptools.
Uvicorn является сервером, а не фреймворком.
Например, он не предоставляет инструментов для маршрутизации запросов по ресурсам.
Для этого нужна надстройка, такая как Starlette (или **FastAPI**).
Это не веб-фреймворк, а сервер. Например, он не предоставляет инструменты для маршрутизации по путям. Это предоставляет сверху фреймворк, такой как Starlette (или **FastAPI**).
Он рекомендуется в качестве сервера для Starlette и **FastAPI**.
Это рекомендуемый сервер для Starlette и **FastAPI**.
/// check | **FastAPI** рекомендует его
/// check | **FastAPI** рекомендует его как
Как основной сервер для запуска приложения **FastAPI**.
Основной веб-сервер для запуска приложений **FastAPI**.
Вы можете объединить его с Gunicorn, чтобы иметь асинхронный многопроцессный сервер.
Также вы можете использовать опцию командной строки `--workers`, чтобы получить асинхронный многопроцессный сервер.
Узнать больше деталей можно в разделе [Развёртывание](deployment/index.md){.internal-link target=_blank}.
Подробнее см. раздел [Развёртывание](deployment/index.md){.internal-link target=_blank}.
///
## Тестовые замеры и скорость
## Бенчмарки и скорость { #benchmarks-and-speed }
Чтобы понять, сравнить и увидеть разницу между Uvicorn, Starlette и FastAPI, ознакомьтесь с разделом [Тестовые замеры](benchmarks.md){.internal-link target=_blank}.
Чтобы понять, сравнить и увидеть разницу между Uvicorn, Starlette и FastAPI, см. раздел о [Бенчмарках](benchmarks.md){.internal-link target=_blank}.

View File

@@ -1,18 +1,18 @@
# Конкурентность и async / await
# Конкурентность и async / await { #concurrency-and-async-await }
Здесь приведена подробная информация об использовании синтаксиса `async def` при написании *функций обработки пути*, а также рассмотрены основы асинхронного программирования, конкурентности и параллелизма.
Подробности о синтаксисе `async def` для *функций-обработчиков пути* и немного фона об асинхронном коде, конкурентности и параллелизме.
## Нет времени?<a name="in-a-hurry"></a>
## Нет времени? { #in-a-hurry }
<abbr title="too long; didn't read (основная мысль)"><strong>TL;DR:</strong></abbr>
<abbr title="too long; didn't read слишком длинно; не читал"><strong>TL;DR:</strong></abbr>
Допустим, вы используете сторонюю библиотеку, которая требует вызова с ключевым словом `await`:
Если вы используете сторонние библиотеки, которые нужно вызывать с `await`, например:
```Python
results = await some_library()
```
В этом случае *функции обработки пути* необходимо объявлять с использованием синтаксиса `async def`:
Тогда объявляйте *функции-обработчики пути* с `async def`, например:
```Python hl_lines="2"
@app.get('/')
@@ -21,18 +21,15 @@ async def read_results():
return results
```
/// note
/// note | Примечание
`await` можно использовать только внутри функций, объявленных с использованием `async def`.
`await` можно использовать только внутри функций, объявленных с `async def`.
///
---
Если вы обращаетесь к сторонней библиотеке, которая с чем-то взаимодействует
(с базой данных, API, файловой системой и т. д.), и не имеет поддержки синтаксиса `await`
(что относится сейчас к большинству библиотек для работы с базами данных), то
объявляйте *функции обработки пути* обычным образом с помощью `def`, например:
Если вы используете стороннюю библиотеку, которая взаимодействует с чем-то (база данных, API, файловая система и т.д.) и не поддерживает использование `await` (сейчас это относится к большинству библиотек для БД), тогда объявляйте *функции-обработчики пути* как обычно, просто с `def`, например:
```Python hl_lines="2"
@app.get('/')
@@ -43,310 +40,283 @@ def results():
---
Если вашему приложению (странным образом) не нужно ни с чем взаимодействовать и, соответственно,
ожидать ответа, используйте `async def`.
Если вашему приложению (по какой-то причине) не нужно ни с чем взаимодействовать и ждать ответа, используйте `async def`, даже если внутри не нужен `await`.
---
Если вы не уверены, используйте обычный синтаксис `def`.
Если вы просто не уверены, используйте обычный `def`.
---
**Примечание**: при необходимости можно смешивать `def` и `async def` в *функциях обработки пути*
и использовать в каждом случае наиболее подходящий синтаксис. А FastAPI сделает с этим всё, что нужно.
**Примечание**: вы можете смешивать `def` и `async def` в *функциях-обработчиках пути* столько, сколько нужно, и объявлять каждую так, как лучше для вашего случая. FastAPI сделает с ними всё как надо.
В любом из описанных случаев FastAPI работает асинхронно и очень быстро.
В любом из случаев выше FastAPI всё равно работает асинхронно и очень быстро.
Однако придерживаясь указанных советов, можно получить дополнительную оптимизацию производительности.
Но следуя этим шагам, он сможет выполнить некоторые оптимизации производительности.
## Технические подробности
## Технические подробности { #technical-details }
Современные версии Python поддерживают разработку так называемого **"асинхронного кода"** посредством написания **"сопрограмм"** с использованием синтаксиса **`async` и `await`**.
Современные версии Python поддерживают **«асинхронный код»** с помощью **«сопрограмм»** (coroutines) и синтаксиса **`async` и `await`**.
Ниже разберём эту фразу по частям:
Разберём эту фразу по частям в разделах ниже:
* **Асинхронный код**
* **`async` и `await`**
* **Сопрограммы**
## Асинхронный код
## Асинхронный код { #asynchronous-code }
Асинхронный код означает, что в языке 💬 есть возможность сообщить машине / программе 🤖,
что в определённой точке кода ей 🤖 нужно будет ожидать завершения выполнения *чего-то ещё* в другом месте. Допустим это *что-то ещё* называется "медленный файл" 📝.
Асинхронный код значит, что в языке 💬 есть способ сказать компьютеру/программе 🤖, что в некоторый момент кода ему 🤖 придётся подождать, пока *что-то ещё* где-то в другом месте завершится. Назовём это *что-то ещё* «медленный файл» 📝.
И пока мы ждём завершения работы с "медленным файлом" 📝, компьютер может переключиться для выполнения других задач.
И пока мы ждём завершения работы с «медленныи файлом» 📝, компьютер может заняться другой работой.
Но при каждой возможности компьютер / программа 🤖 будет возвращаться обратно. Например, если он 🤖 опять окажется в режиме ожидания, или когда закончит всю работу. В этом случае компьютер 🤖 проверяет, не завершена ли какая-нибудь из текущих задач.
Затем компьютер/программа 🤖 будет возвращаться каждый раз, когда появится возможность (пока снова где-то идёт ожидание), или когда 🤖 завершит всю текущую работу. И он 🤖 проверит, не завершилась ли какая-либо из задач, которых он ждал, и сделает то, что нужно.
Потом он 🤖 берёт первую выполненную задачу (допустим, наш "медленный файл" 📝) и продолжает работу, производя с ней необходимые действия.
Далее он 🤖 возьмёт первую завершившуюся задачу (скажем, наш «медленный файл» 📝) и продолжит делать с ней то, что требуется.
Вышеупомянутое "что-то ещё", завершения которого приходится ожидать, обычно относится к достаточно "медленным" операциям <abbr title="Ввода-вывода">I/O</abbr> (по сравнению со скоростью работы процессора и оперативной памяти), например:
Это «ожидание чего-то ещё» обычно относится к операциям <abbr title="Input and Output Ввод/вывод">I/O</abbr>, которые относительно «медленные» (по сравнению со скоростью процессора и оперативной памяти), например ожидание:
* отправка данных от клиента по сети
* получение клиентом данных, отправленных вашей программой по сети
* чтение системой содержимого файла с диска и передача этих данных программе
* запись на диск данных, которые программа передала системе
* обращение к удалённому API
* ожидание завершения операции с базой данных
* получение результатов запроса к базе данных
* и т. д.
* отправки данных клиентом по сети
* получения клиентом данных, отправленных вашей программой по сети
* чтения системой содержимого файла на диске и передачи этих данных вашей программе
* записи на диск содержимого, которое ваша программа передала системе
* операции удалённого API
* завершения операции базы данных
* возврата результатов запроса к базе данных
* и т.д.
Поскольку в основном время тратится на ожидание выполнения операций <abbr title="Ввода-вывода">I/O</abbr>,
их обычно называют операциями, <abbr title="I/O bound">ограниченными скоростью ввода-вывода</abbr>.
Поскольку основное время выполнения уходит на ожидание операций <abbr title="Input and Output Ввод/вывод">I/O</abbr>, их называют операциями, «ограниченными вводом-выводом» (I/O bound).
Код называют "асинхронным", потому что компьютеру / программе не требуется "синхронизироваться" с медленной задачей и,
будучи в простое, ожидать момента её завершения, с тем чтобы забрать результат и продолжить работу.
Это называется «асинхронным», потому что компьютеру/программе не нужно «синхронизироваться» с медленной задачей, простаивая и выжидая точный момент её завершения, чтобы забрать результат и продолжить работу.
Вместо этого в "асинхронной" системе завершённая задача может немного подождать (буквально несколько микросекунд),
пока компьютер / программа занимается другими важными вещами, с тем чтобы потом вернуться,
забрать результаты выполнения и начать их обрабатывать.
Вместо этого, в «асинхронной» системе, уже завершившаяся задача может немного подождать (несколько микросекунд) в очереди, пока компьютер/программа завершит то, чем занимался, и затем вернётся, чтобы забрать результаты и продолжить работу с ними.
"Синхронное" исполнение (в противовес "асинхронному") также называют <abbr title="sequential">"последовательным"</abbr>,
потому что компьютер / программа последовательно выполняет все требуемые шаги перед тем, как перейти к следующей задаче,
даже если в процессе приходится ждать.
Для «синхронного» (в противоположность «асинхронному») исполнения часто используют термин «последовательный», потому что компьютер/программа выполняет все шаги по порядку, прежде чем переключиться на другую задачу, даже если эти шаги включают ожидание.
### Конкурентность и бургеры
### Конкурентность и бургеры { #concurrency-and-burgers }
Тот **асинхронный** код, о котором идёт речь выше, иногда называют **"конкурентностью"**. Она отличается от **"параллелизма"**.
Та идея **асинхронного** кода, описанная выше, иногда также называется **«конкурентностью»**. Она отличается от **«параллелизма»**.
Да, **конкурентность** и **параллелизм** подразумевают, что разные вещи происходят примерно в одно время.
И **конкурентность**, и **параллелизм** относятся к «разным вещам, происходящим примерно одновременно».
Но внутреннее устройство **конкурентности** и **параллелизма** довольно разное.
Но различия между *конкурентностью* и *параллелизмом* довольно существенные.
Чтобы это понять, представьте такую картину:
Чтобы их увидеть, представьте следующую историю про бургеры:
### Конкурентные бургеры
### Конкурентные бургеры { #concurrent-burgers }
<!-- The gender neutral cook emoji "🧑‍🍳" does not render well in browsers. In the meantime, I'm using a mix of male "👨‍🍳" and female "👩‍🍳" cooks. -->
Вы идёте со своей возлюбленной за фастфудом, вы стоите в очереди, пока кассир принимает заказы у людей перед вами. 😍
Вы идёте со своей возлюбленной 😍 в фастфуд 🍔 и становитесь в очередь, в это время кассир 💁 принимает заказы у посетителей перед вами.
<img src="/img/async/concurrent-burgers/concurrent-burgers-01.png" class="illustration">
Когда наконец подходит очередь, вы заказываете парочку самых вкусных и навороченных бургеров 🍔, один для своей возлюбленной 😍, а другой себе.
Наконец ваша очередь: вы заказываете 2 очень «навороченных» бургера для вашей возлюбленной и для себя. 🍔🍔
Отдаёте деньги 💸.
<img src="/img/async/concurrent-burgers/concurrent-burgers-02.png" class="illustration">
Кассир 💁 что-то говорит поварам на кухне 👨‍🍳, теперь они знают, какие бургеры нужно будет приготовить 🍔
(но пока они заняты бургерами предыдущих клиентов).
Кассир говорит что-то повару на кухне, чтобы они знали, что нужно приготовить ваши бургеры (хотя сейчас они готовят бургеры для предыдущих клиентов).
Кассир 💁 отдаёт вам чек с номером заказа.
<img src="/img/async/concurrent-burgers/concurrent-burgers-03.png" class="illustration">
В ожидании еды вы идёте со своей возлюбленной 😍 выбрать столик, садитесь и довольно продолжительное время общаетесь 😍
(поскольку ваши бургеры самые навороченные, готовятся они не так быстро ✨🍔✨).
Вы платите. 💸
Сидя за столиком с возлюбленной 😍 в ожидании бургеров 🍔, вы отлично проводите время,
восхищаясь её великолепием, красотой и умом ✨😍✨.
Кассир выдаёт вам номер вашей очереди.
Всё ещё ожидая заказ и болтая со своей возлюбленной 😍, время от времени вы проверяете,
какой номер горит над прилавком, и не подошла ли уже ваша очередь.
<img src="/img/async/concurrent-burgers/concurrent-burgers-04.png" class="illustration">
И вот наконец настаёт этот момент, и вы идёте к стойке, чтобы забрать бургеры 🍔 и вернуться за столик.
Пока вы ждёте, вы вместе со своей возлюбленной идёте и выбираете столик, садитесь и долго болтаете (ваши бургеры очень «навороченные», поэтому им нужно время на приготовление).
Вы со своей возлюбленной 😍 едите бургеры 🍔 и отлично проводите время ✨.
Сидя за столиком со своей возлюбленной в ожидании бургеров, вы можете провести это время, восхищаясь тем, какая она классная, милая и умная ✨😍✨.
<img src="/img/async/concurrent-burgers/concurrent-burgers-05.png" class="illustration">
Пока вы ждёте и разговариваете, время от времени вы поглядываете на номер на табло, чтобы понять, не подошла ли уже ваша очередь.
И вот в какой-то момент ваша очередь наступает. Вы подходите к стойке, забираете свои бургеры и возвращаетесь к столику.
<img src="/img/async/concurrent-burgers/concurrent-burgers-06.png" class="illustration">
Вы со своей возлюбленной едите бургеры и отлично проводите время. ✨
<img src="/img/async/concurrent-burgers/concurrent-burgers-07.png" class="illustration">
/// info | Информация
Прекрасные иллюстрации от <a href="https://www.instagram.com/ketrinadrawsalot" class="external-link" target="_blank">Ketrina Thompson</a>. 🎨
///
---
А теперь представьте, что в этой небольшой истории вы компьютер / программа 🤖.
Представьте, что в этой истории вы компьютер/программа 🤖.
В очереди вы просто глазеете по сторонам 😴, ждёте и ничего особо "продуктивного" не делаете.
Но очередь движется довольно быстро, поскольку кассир 💁 только принимает заказы (а не занимается приготовлением еды), так что ничего страшного.
Пока вы стоите в очереди, вы просто бездействуете 😴, ждёте своей очереди и не делаете ничего особо «продуктивного». Но очередь движется быстро, потому что кассир только принимает заказы (а не готовит их), так что это нормально.
Когда подходит очередь вы наконец предпринимаете "продуктивные" действия 🤓: просматриваете меню, выбираете в нём что-то, узнаёте, что хочет ваша возлюбленная 😍, собираетесь оплатить 💸, смотрите, какую достали карту, проверяете, чтобы с вас списали верную сумму, и что в заказе всё верно и т. д.
Когда приходит ваша очередь, вы выполняете действительно «продуктивную» работу: просматриваете меню, решаете, чего хотите, учитываете выбор своей возлюбленной, платите, проверяете, что дали правильную купюру/карту, что сумма списана корректно, что в заказе верные позиции и т.д.
И хотя вы всё ещё не получили бургеры 🍔, ваша работа с кассиром 💁 ставится "на паузу" ⏸,
поскольку теперь нужно ждать 🕙, когда заказ приготовят.
Но затем, хотя у вас ещё нет бургеров, ваша «работа» с кассиром поставлена «на паузу» ⏸, потому что нужно подождать 🕙, пока бургеры будут готовы.
Но отойдя с номерком от прилавка, вы садитесь за столик и можете переключить 🔀 внимание
на свою возлюбленную 😍 и "работать" ⏯ 🤓 уже над этим. И вот вы снова очень
"продуктивны" 🤓, мило болтаете вдвоём и всё такое 😍.
Но, отойдя от стойки и сев за столик с номерком, вы можете переключить 🔀 внимание на свою возлюбленную и «поработать» ⏯ 🤓 над этим. Снова очень «продуктивно» — флирт с вашей возлюбленной 😍.
В какой-то момент кассир 💁 поместит на табло ваш номер, подразумевая, что бургеры готовы 🍔, но вы не станете подскакивать как умалишённый, лишь только увидев на экране свою очередь. Вы уверены, что ваши бургеры 🍔 никто не утащит, ведь у вас свой номерок, а у других свой.
Потом кассир 💁 «говорит»: «Я закончил делать бургеры», — выводя ваш номер на табло, но вы не подпрыгиваете как сумасшедший в ту же секунду, как только номер сменился на ваш. Вы знаете, что ваши бургеры никто не украдёт, потому что у вас есть номер вашей очереди, а у других — их.
Поэтому вы подождёте, пока возлюбленная 😍 закончит рассказывать историю (закончите текущую работу ⏯ / задачу в обработке 🤓),
и мило улыбнувшись, скажете, что идёте забирать заказ ⏸.
Поэтому вы дожидаетесь, пока ваша возлюбленная закончит историю (завершится текущая работа ⏯ / выполняемая задача 🤓), мягко улыбаетесь и говорите, что идёте за бургерами ⏸.
И вот вы подходите к стойке 🔀, к первоначальной задаче, которая уже завершена ⏯, берёте бургеры 🍔, говорите спасибо и относите заказ за столик. На этом заканчивается этап / задача взаимодействия с кассой ⏹.
В свою очередь порождается задача "поедание бургеров" 🔀 ⏯, но предыдущая ("получение бургеров") завершена ⏹.
Затем вы идёте к стойке 🔀, к исходной задаче, которая теперь завершена ⏯, забираете бургеры, благодарите и несёте их к столику. На этом шаг/задача взаимодействия со стойкой завершён ⏹. Это, в свою очередь, создаёт новую задачу — «есть бургеры» 🔀 ⏯, но предыдущая «получить бургеры» — завершена ⏹.
### Параллельные бургеры
### Параллельные бургеры { #parallel-burgers }
Теперь представим, что вместо бургерной "Конкурентные бургеры" вы решили сходить в "Параллельные бургеры".
Теперь представим, что это не «Конкурентные бургеры», а «Параллельные бургеры».
И вот вы идёте со своей возлюбленной 😍 отведать параллельного фастфуда 🍔.
Вы идёте со своей возлюбленной за параллельным фастфудом.
Вы становитесь в очередь пока несколько (пусть будет 8) кассиров, которые по совместительству ещё и повары 👩‍🍳👨‍🍳👩‍🍳👨‍🍳👩‍🍳👨‍🍳👩‍🍳👨‍🍳, принимают заказы у посетителей перед вами.
Вы стоите в очереди, пока несколько (скажем, 8) кассиров, которые одновременно являются поварами, принимают заказы у людей перед вами.
При этом клиенты не отходят от стойки и ждут 🕙 получения еды, поскольку каждый
из 8 кассиров идёт на кухню готовить бургеры 🍔, а только потом принимает следующий заказ.
Все перед вами ждут, пока их бургеры будут готовы, не отходя от стойки, потому что каждый из 8 кассиров сразу идёт готовить бургер перед тем, как принять следующий заказ.
Наконец настаёт ваша очередь, и вы просите два самых навороченных бургера 🍔, один для дамы сердца 😍, а другой себе.
<img src="/img/async/parallel-burgers/parallel-burgers-01.png" class="illustration">
Ни о чём не жалея, расплачиваетесь 💸.
Наконец ваша очередь: вы заказываете 2 очень «навороченных» бургера — для вашей возлюбленной и для себя.
И кассир уходит на кухню 👨‍🍳.
Вы платите 💸.
Вам приходится ждать перед стойкой 🕙, чтобы никто по случайности не забрал ваши бургеры 🍔, ведь никаких номерков у вас нет.
<img src="/img/async/parallel-burgers/parallel-burgers-02.png" class="illustration">
Поскольку вы с возлюбленной 😍 хотите получить заказ вовремя 🕙, и следите за тем, чтобы никто не вклинился в очередь,
у вас не получается уделять должного внимание своей даме сердца 😞.
Кассир уходит на кухню.
Это "синхронная" работа, вы "синхронизированы" с кассиром/поваром 👨‍🍳. Приходится ждать 🕙 у стойки,
когда кассир/повар 👨‍🍳 закончит делать бургеры 🍔 и вручит вам заказ, иначе его случайно может забрать кто-то другой.
Вы ждёте, стоя у стойки 🕙, чтобы никто не забрал ваши бургеры раньше вас, так как никаких номерков нет.
Наконец кассир/повар 👨‍🍳 возвращается с бургерами 🍔 после невыносимо долгого ожидания 🕙 за стойкой.
<img src="/img/async/parallel-burgers/parallel-burgers-03.png" class="illustration">
Вы скорее забираете заказ 🍔 и идёте с возлюбленной 😍 за столик.
Так как вы со своей возлюбленной заняты тем, чтобы никто не встал перед вами и не забрал ваши бургеры, как только они появятся, вы не можете уделить внимание своей возлюбленной. 😞
Там вы просто едите эти бургеры, и на этом всё 🍔 ⏹.
Это «синхронная» работа, вы «синхронизированы» с кассиром/поваром 👨‍🍳. Вам нужно ждать 🕙 и находиться там в точный момент, когда кассир/повар 👨‍🍳 закончит бургеры и вручит их вам, иначе их может забрать кто-то другой.
Вам не особо удалось пообщаться, потому что большую часть времени 🕙 пришлось провести у кассы 😞.
<img src="/img/async/parallel-burgers/parallel-burgers-04.png" class="illustration">
Затем ваш кассир/повар 👨‍🍳 наконец возвращается с вашими бургерами, после долгого ожидания 🕙 у стойки.
<img src="/img/async/parallel-burgers/parallel-burgers-05.png" class="illustration">
Вы берёте бургеры и идёте со своей возлюбленной к столику.
Вы просто их съедаете — и всё. ⏹
<img src="/img/async/parallel-burgers/parallel-burgers-06.png" class="illustration">
Разговоров и флирта было немного, потому что большую часть времени вы ждали 🕙 у стойки. 😞
/// info | Информация
Прекрасные иллюстрации от <a href="https://www.instagram.com/ketrinadrawsalot" class="external-link" target="_blank">Ketrina Thompson</a>. 🎨
///
---
В описанном сценарии вы компьютер / программа 🤖 с двумя исполнителями (вы и ваша возлюбленная 😍),
на протяжении долгого времени 🕙 вы оба уделяете всё внимание ⏯ задаче "ждать на кассе".
В этом сценарии «параллельных бургеров» вы компьютер/программа 🤖 с двумя процессорами (вы и ваша возлюбленная), оба ждут 🕙 и уделяют внимание ⏯ тому, чтобы «ждать у стойки» 🕙 долгое время.
В этом ресторане быстрого питания 8 исполнителей (кассиров/поваров) 👩‍🍳👨‍🍳👩‍🍳👨‍🍳👩‍🍳👨‍🍳👩‍🍳👨‍🍳.
Хотя в бургерной конкурентного типа было всего два (один кассир и один повар) 💁 👨‍🍳.
В ресторане 8 процессоров (кассиров/поваров). Тогда как в «конкурентных бургерах» могло быть только 2 (один кассир и один повар).
Несмотря на обилие работников, опыт в итоге получился не из лучших 😞.
И всё же финальный опыт — не самый лучший. 😞
---
Так бы выглядел аналог истории про бургерную 🍔 в "параллельном" мире.
Это была параллельная версия истории про бургеры. 🍔
Вот более реалистичный пример. Представьте себе банк.
Для более «жизненного» примера представьте банк.
До недавних пор в большинстве банков было несколько кассиров 👨‍💼👨‍💼👨‍💼👨‍💼 и длинные очереди 🕙🕙🕙🕙🕙🕙🕙🕙.
До недавнего времени в большинстве банков было несколько кассиров 👨‍💼👨‍💼👨‍💼👨‍💼 и длинная очередь 🕙🕙🕙🕙🕙🕙🕙🕙.
Каждый кассир обслуживал одного клиента, потом следующего 👨‍💼⏯.
Все кассиры делают всю работу с одним клиентом за другим 👨‍💼⏯.
Нужно было долгое время 🕙 стоять перед окошком вместе со всеми, иначе пропустишь свою очередь.
И вам приходится долго 🕙 стоять в очереди, иначе вы потеряете свою очередь.
Сомневаюсь, что у вас бы возникло желание прийти с возлюбленной 😍 в банк 🏦 оплачивать налоги.
Вы вряд ли захотите взять свою возлюбленную 😍 с собой, чтобы заняться делами в банке 🏦.
### Выводы о бургерах
### Вывод про бургеры { #burger-conclusion }
В нашей истории про поход в фастфуд за бургерами приходится много ждать 🕙,
поэтому имеет смысл организовать конкурентную систему ⏸🔀⏯.
В этом сценарии «фастфуда с вашей возлюбленной», так как много ожидания 🕙, гораздо логичнее иметь конкурентную систему ⏸🔀⏯.
И то же самое с большинством веб-приложений.
Так обстоит дело и с большинством веб-приложений.
Пользователей очень много, но ваш сервер всё равно вынужден ждать 🕙 запросы по их слабому интернет-соединению.
Очень много пользователей, но ваш сервер ждёт 🕙, пока их не самое хорошее соединение отправит их запросы.
Потом снова ждать 🕙, пока вернётся ответ.
А затем снова ждёт 🕙, пока отправятся ответы.
<!--https://forum.wordreference.com/threads/%D0%9D%D0%BE-%D0%B5%D1%81%D0%BB%D0%B8.3258695/-->
Это ожидание 🕙 измеряется микросекундами, но если всё сложить, то набегает довольно много времени.
Это «ожидание» 🕙 измеряется микросекундами, но если всё сложить, то в сумме получается много ожидания.
Вот почему есть смысл использовать асинхронное ⏸🔀⏯ программирование при построении веб-API.
Вот почему асинхронный ⏸🔀⏯ код очень уместен для веб-API.
Большинство популярных фреймворков (включая Flask и Django) создавались
до появления в Python новых возможностей асинхронного программирования. Поэтому
их можно разворачивать с поддержкой параллельного исполнения или асинхронного
программирования старого типа, которое не настолько эффективно.
Именно такая асинхронность сделала NodeJS популярным (хотя NodeJS — не параллельный), и это сильная сторона Go как языка программирования.
При том, что основная спецификация асинхронного взаимодействия Python с веб-сервером
(<a href="https://asgi.readthedocs.io" class="external-link" target="_blank">ASGI</a>)
была разработана командой Django для внедрения поддержки веб-сокетов.
Того же уровня производительности вы получаете с **FastAPI**.
Именно асинхронность сделала NodeJS таким популярным (несмотря на то, что он не параллельный),
и в этом преимущество Go как языка программирования.
А так как можно одновременно использовать параллелизм и асинхронность, вы получаете производительность выше, чем у большинства протестированных фреймворков на NodeJS и на уровне Go, который — компилируемый язык, ближе к C <a href="https://www.techempower.com/benchmarks/#section=data-r17&hw=ph&test=query&l=zijmkf-1" class="external-link" target="_blank">(всё благодаря Starlette)</a>.
И тот же уровень производительности даёт **FastAPI**.
### Конкурентность лучше параллелизма? { #is-concurrency-better-than-parallelism }
Поскольку можно использовать преимущества параллелизма и асинхронности вместе,
вы получаете производительность лучше, чем у большинства протестированных NodeJS фреймворков
и на уровне с Go, который является компилируемым языком близким к C <a href="https://www.techempower.com/benchmarks/#section=data-r17&hw=ph&test=query&l=zijmkf-1" class="external-link" target="_blank">(всё благодаря Starlette)</a>.
Нет! Мораль истории не в этом.
### Получается, конкурентность лучше параллелизма?
Конкурентность отличается от параллелизма. И она лучше в **конкретных** сценариях, где много ожидания. Поэтому при разработке веб-приложений она обычно намного лучше параллелизма. Но не во всём.
Нет! Мораль истории совсем не в этом.
Чтобы уравновесить это, представьте такую короткую историю:
Конкурентность отличается от параллелизма. Она лучше в **конкретных** случаях, где много времени приходится на ожидание.
Вот почему она зачастую лучше параллелизма при разработке веб-приложений. Но это не значит, что конкурентность лучше в любых сценариях.
Давайте посмотрим с другой стороны, представьте такую картину:
> Вам нужно убраться в большом грязном доме.
> Вам нужно убрать большой грязный дом.
*Да, это вся история*.
---
Тут не нужно нигде ждать 🕙, просто есть куча работы в разных частях дома.
Здесь нигде нет ожидания 🕙, просто очень много работы в разных местах дома.
Можно организовать очередь как в примере с бургерами, сначала гостиная, потом кухня,
но это ни на что не повлияет, поскольку вы нигде не ждёте 🕙, а просто трёте да моете.
Можно организовать «очереди» как в примере с бургерами сначала гостиная, потом кухня, — но так как вы ничего не ждёте 🕙, а просто убираете и убираете, очереди ни на что не повлияют.
И понадобится одинаковое количество времени с очередью (конкурентностью) и без неё,
и работы будет сделано тоже одинаковое количество.
На завершение уйдёт одинаковое время — с очередями (конкурентностью) и без них — и объём выполненной работы будет одинаковым.
Однако в случае, если бы вы могли привести 8 бывших кассиров/поваров, а ныне уборщиков 👩‍🍳👨‍🍳👩‍🍳👨‍🍳👩‍🍳👨‍🍳👩‍🍳👨‍🍳,
и каждый из них (вместе с вами) взялся бы за свой участок дома,
с такой помощью вы бы закончили намного быстрее, делая всю работу **параллельно**.
Но в этом случае, если бы вы могли привести 8 бывших кассиров/поваров, а теперь — уборщиков, и каждый из них (плюс вы) взял бы свою зону дома для уборки, вы могли бы сделать всю работу **параллельно**, с дополнительной помощью, и завершить гораздо быстрее.
В описанном сценарии каждый уборщик (включая вас) был бы исполнителем, занятым на своём участке работы.
В этом сценарии каждый уборщик (включая вас) был бы процессором, выполняющим свою часть работы.
И поскольку большую часть времени выполнения занимает реальная работа (а не ожидание),
а работу в компьютере делает <abbr title="Центральный процессор (CPU)">ЦП</abbr>,
такие задачи называют <abbr title="CPU bound">ограниченными производительностью процессора</abbr>.
И так как основное время выполнения уходит на реальную работу (а не ожидание), а работу в компьютере выполняет <abbr title="Central Processing Unit Центральный процессор">CPU</abbr>, такие задачи называют «ограниченными процессором» (CPU bound).
---
Ограничение по процессору проявляется в операциях, где требуется выполнять сложные математические вычисления.
Типичные примеры CPU-bound операций — те, которые требуют сложной математической обработки.
Например:
* Обработка **звука** или **изображений**.
* **Компьютерное зрение**: изображение состоит из миллионов пикселей, в каждом пикселе 3 составляющих цвета,
обработка обычно требует проведения расчётов по всем пикселям сразу.
* **Машинное обучение**: здесь обычно требуется умножение "матриц" и "векторов".
Представьте гигантскую таблицу с числами в Экселе, и все их надо одновременно перемножить.
* **Глубокое обучение**: это область *машинного обучения*, поэтому сюда подходит то же описание.
Просто у вас будет не одна таблица в Экселе, а множество. В ряде случаев используется
специальный процессор для создания и / или использования построенных таким образом моделей.
* Обработка **аудио** или **изображений**.
* **Компьютерное зрение**: изображение состоит из миллионов пикселей, каждый пиксель имеет 3 значения/цвета; обычно требуется вычислить что-то для всех этих пикселей одновременно.
* **Машинное обучение**: обычно требует множества умножений «матриц» и «векторов». Представьте огромную таблицу с числами и умножение всех этих чисел «одновременно».
* **Глубокое обучение**: это подполе Машинного обучения, так что всё вышесказанное применимо. Просто это не одна таблица чисел, а их огромный набор, и во многих случаях вы используете специальный процессор, чтобы строить и/или использовать такие модели.
### Конкурентность + параллелизм: Веб + машинное обучение
### Конкурентность + параллелизм: Веб + Машинное обучение { #concurrency-parallelism-web-machine-learning }
**FastAPI** предоставляет возможности конкуретного программирования,
которое очень распространено в веб-разработке (именно этим славится NodeJS).
С **FastAPI** вы можете использовать преимущества конкурентности, что очень распространено в веб-разработке (это та же основная «фишка» NodeJS).
Кроме того вы сможете использовать все преимущества параллелизма и
<abbr title="multiprocessing">многопроцессорности</abbr> (когда несколько процессов работают параллельно),
если рабочая нагрузка предполагает **ограничение по процессору**,
как, например, в системах машинного обучения. <!--http://new.gramota.ru/spravka/punctum?layout=item&id=58_329-->
Но вы также можете использовать выгоды параллелизма и многопроцессности (когда несколько процессов работают параллельно) для рабочих нагрузок, **ограниченных процессором** (CPU bound), как в системах Машинного обучения.
Необходимо также отметить, что Python является главным языком в области
<abbr title="наука о данных (data science)">**дата-сайенс**</abbr>,
машинного обучения и, особенно, глубокого обучения. Всё это делает FastAPI
отличным вариантом (среди многих других) для разработки веб-API и приложений
в области дата-сайенс / машинного обучения.
Плюс к этому простой факт, что Python — основной язык для **Data Science**, Машинного обучения и особенно Глубокого обучения, делает FastAPI очень хорошим выбором для веб-API и приложений в области Data Science / Машинного обучения (среди многих других).
Как добиться такого параллелизма в эксплуатации описано в разделе [Развёртывание](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`. Оно сообщает интерпретатору, что необходимо дождаться ⏸
пока `get_burgers(2)` закончит свои дела 🕙, и только после этого сохранить результат в `burgers`.
Зная это, Python может пока переключиться на выполнение других задач 🔀 ⏯
(например получение следующего запроса).<!--http://new.gramota.ru/spravka/buro/search-answer?s=296614-->
Ключ здесь `await`. Он говорит Python, что нужно подождать ⏸, пока `get_burgers(2)` закончит своё дело 🕙, прежде чем сохранять результат в `burgers`. Благодаря этому Python будет знать, что за это время можно заняться чем-то ещё 🔀 ⏯ (например, принять другой запрос).
Чтобы ключевое слово `await` сработало, оно должно находиться внутри функции,
которая поддерживает асинхронность. Для этого вам просто нужно объявить её как `async def`:
Чтобы `await` работал, он должен находиться внутри функции, которая поддерживает такую асинхронность. Для этого просто объявите её с `async def`:
```Python hl_lines="1"
async def get_burgers(number: int):
# Готовим бургеры по специальному асинхронному рецепту
# Сделать что-то асинхронное, чтобы приготовить бургеры
return burgers
```
@@ -355,26 +325,22 @@ async def get_burgers(number: int):
```Python hl_lines="2"
# Это не асинхронный код
def get_sequential_burgers(number: int):
# Готовим бургеры последовательно по шагам
# Сделать что-то последовательное, чтобы приготовить бургеры
return burgers
```
Объявление `async def` указывает интерпретатору, что внутри этой функции
следует ожидать выражений `await`, и что можно поставить выполнение такой функции на "паузу" ⏸ и
переключиться на другие задачи 🔀, с тем чтобы вернуться сюда позже.
С `async def` Python знает, что внутри этой функции нужно учитывать выражения `await` и что выполнение такой функции можно «приостанавливать» ⏸ и идти делать что-то ещё 🔀, чтобы потом вернуться.
Если вы хотите вызвать функцию с `async def`, вам нужно <abbr title="await">"ожидать"</abbr> её.
Поэтому такое не сработает:
Когда вы хотите вызвать функцию, объявленную с `async def`, нужно её «ожидать». Поэтому вот так не сработает:
```Python
# Это не заработает, поскольку get_burgers объявлена с использованием async def
# Это не сработает, потому что get_burgers определена с: async def
burgers = get_burgers(2)
```
---
Если сторонняя библиотека требует вызывать её с ключевым словом `await`,
необходимо писать *функции обработки пути* с использованием `async def`, например:
Итак, если вы используете библиотеку, которую можно вызывать с `await`, вам нужно создать *функцию-обработчик пути*, которая её использует, с `async def`, например:
```Python hl_lines="2-3"
@app.get('/burgers')
@@ -383,129 +349,96 @@ async def read_burgers():
return burgers
```
### Технические подробности
### Более технические подробности { #more-technical-details }
Как вы могли заметить, `await` может применяться только в функциях, объявленных с использованием `async def`.
Вы могли заметить, что `await` можно использовать только внутри функций, определённых с `async def`.
<!--http://new.gramota.ru/spravka/punctum?layout=item&id=58_128-->
Но выполнение такой функции необходимо "ожидать" с помощью `await`.
Это означает, что её можно вызвать только из другой функции, которая тоже объявлена с `async def`.
Но при этом функции, определённые с `async def`, нужно «ожидать». Значит, функции с `async def` тоже можно вызывать только из функций, определённых с `async def`.
Но как же тогда появилась первая <abbr title="или яйцо?🤔">курица</abbr>? В смысле... как нам вызвать первую асинхронную функцию?
Так что же с «яйцом и курицей» — как вызвать первую `async` функцию?
При работе с **FastAPI** просто не думайте об этом, потому что "первой" функцией является ваша *функция обработки пути*,
и дальше с этим разберётся FastAPI.
Если вы работаете с **FastAPI**, вам не о чем беспокоиться, потому что этой «первой» функцией будет ваша *функция-обработчик пути*, а FastAPI знает, как сделать всё правильно.
Кроме того, если хотите, вы можете использовать синтаксис `async` / `await` и без FastAPI.
Но если вы хотите использовать `async` / `await` без FastAPI, вы тоже можете это сделать.
### Пишите свой асинхронный код
### Пишите свой асинхронный код { #write-your-own-async-code }
Starlette (и **FastAPI**) основаны на <a href="https://anyio.readthedocs.io/en/stable/" class="external-link" target="_blank">AnyIO</a>, что делает их совместимыми как со стандартной библиотекой <a href="https://docs.python.org/3/library/asyncio-task.html" class="external-link" target="_blank">asyncio</a> в Python, так и с <a href="https://trio.readthedocs.io/en/stable/" class="external-link" target="_blank">Trio</a>.<!--http://new.gramota.ru/spravka/buro/search-answer?s=285295-->
Starlette (и **FastAPI**) основаны на <a href="https://anyio.readthedocs.io/en/stable/" class="external-link" target="_blank">AnyIO</a>, что делает их совместимыми и со стандартной библиотекой Python <a href="https://docs.python.org/3/library/asyncio-task.html" class="external-link" target="_blank">asyncio</a>, и с <a href="https://trio.readthedocs.io/en/stable/" class="external-link" target="_blank">Trio</a>.
В частности, вы можете напрямую использовать <a href="https://anyio.readthedocs.io/en/stable/" class="external-link" target="_blank">AnyIO</a> в тех проектах, где требуется более сложная логика работы с конкурентностью.
В частности, вы можете напрямую использовать <a href="https://anyio.readthedocs.io/en/stable/" class="external-link" target="_blank">AnyIO</a> для продвинутых сценариев конкурентности, где в вашем коде нужны более сложные паттерны.
Даже если вы не используете FastAPI, вы можете писать асинхронные приложения с помощью <a href="https://anyio.readthedocs.io/en/stable/" class="external-link" target="_blank">AnyIO</a>, чтобы они были максимально совместимыми и получали его преимущества (например *структурную конкурентность*).
И даже если вы не используете FastAPI, вы можете писать свои асинхронные приложения с <a href="https://anyio.readthedocs.io/en/stable/" class="external-link" target="_blank">AnyIO</a>, чтобы они были максимально совместимыми и получали его преимущества (например, *структурную конкурентность*).
### Другие виды асинхронного программирования
Я создал ещё одну библиотеку поверх AnyIO, тонкий слой, чтобы немного улучшить аннотации типов и получить более качественное **автозавершение**, **ошибки прямо в редакторе** и т.д. Там также есть дружелюбное введение и руководство, чтобы помочь вам **понять** и писать **свой собственный асинхронный код**: <a href="https://asyncer.tiangolo.com/" class="external-link" target="_blank">Asyncer</a>. Она особенно полезна, если вам нужно **комбинировать асинхронный код с обычным** (блокирующим/синхронным) кодом.
Стиль написания кода с `async` и `await` появился в языке Python относительно недавно.
### Другие формы асинхронного кода { #other-forms-of-asynchronous-code }
Но он сильно облегчает работу с асинхронным кодом.
Такой стиль использования `async` и `await` относительно новый в языке.
Ровно такой же синтаксис (ну или почти такой же) недавно был включён в современные версии JavaScript (в браузере и NodeJS).
Но он сильно упрощает работу с асинхронным кодом.
До этого поддержка асинхронного кода была реализована намного сложнее, и его было труднее воспринимать.
Такой же (или почти такой же) синтаксис недавно появился в современных версиях JavaScript (в браузере и NodeJS).
В предыдущих версиях Python для этого использовались потоки или <a href="https://www.gevent.org/" class="external-link" target="_blank">Gevent</a>. Но такой код намного сложнее понимать, отлаживать и мысленно представлять.
До этого работа с асинхронным кодом была заметно сложнее и труднее для понимания.
Что касается JavaScript (в браузере и NodeJS), раньше там использовали для этой цели
<abbr title="callback">"обратные вызовы"</abbr>. Что выливалось в
"ад обратных вызовов".
В предыдущих версиях Python можно было использовать потоки или <a href="https://www.gevent.org/" class="external-link" target="_blank">Gevent</a>. Но такой код гораздо сложнее понимать, отлаживать и держать в голове.
## Сопрограммы
В прежних версиях NodeJS/браузерного JavaScript вы бы использовали «callbacks» (обратные вызовы), что приводит к «callback hell» (ад обратных вызовов).
<abbr title="coroutine">**Корути́на**</abbr> (или же сопрограмма) — это крутое словечко для именования той сущности,
которую возвращает функция `async def`. Python знает, что её можно запустить, как и обычную функцию,
но кроме того сопрограмму можно поставить на паузу ⏸ в том месте, где встретится слово `await`.
## Сопрограммы { #coroutines }
Всю функциональность асинхронного программирования с использованием `async` и `await`
часто обобщают словом "корутины". Они аналогичны <abbr title="Goroutines">"горутинам"</abbr>, ключевой особенности
языка Go.
**Сопрограмма** (coroutine) — это просто «навороченное» слово для того, что возвращает функция `async def`. Python знает, что это похоже на функцию: её можно запустить, она когда-нибудь завершится, но её выполнение может приостанавливаться ⏸ внутри, когда встречается `await`.
## Заключение
Часто всю функциональность использования асинхронного кода с `async` и `await` кратко называют «сопрограммами». Это сопоставимо с ключевой особенностью Go — «goroutines».
В самом начале была такая фраза:
## Заключение { #conclusion }
> Современные версии Python поддерживают разработку так называемого
**"асинхронного кода"** посредством написания **"сопрограмм"** с использованием
синтаксиса **`async` и `await`**.
Вернёмся к той же фразе:
Теперь всё должно звучать понятнее. ✨
> Современные версии Python поддерживают **«асинхронный код»** с помощью **«сопрограмм»** (coroutines) и синтаксиса **`async` и `await`**.
На этом основана работа FastAPI (посредством Starlette), и именно это
обеспечивает его высокую производительность.
Теперь это должно звучать понятнее. ✨
## Очень технические подробности
Именно это «движет» FastAPI (через Starlette) и обеспечивает столь впечатляющую производительность.
/// warning
## Очень технические подробности { #very-technical-details }
Этот раздел читать не обязательно.
/// warning | Предупреждение
Здесь приводятся подробности внутреннего устройства **FastAPI**.
Скорее всего, этот раздел можно пропустить.
Но если вы обладаете техническими знаниями (корутины, потоки, блокировка и т. д.)
и вам интересно, как FastAPI обрабатывает `async def` в отличие от обычных `def`,
читайте дальше.
Здесь — очень технические подробности о том, как **FastAPI** работает «под капотом».
Если у вас есть достаточно технических знаний (сопрограммы, потоки, блокировки и т.д.) и вам интересно, как FastAPI обрабатывает `async def` по сравнению с обычным `def`, — вперёд.
///
### Функции обработки пути
### Функции-обработчики пути { #path-operation-functions }
Когда вы объявляете *функцию обработки пути* обычным образом с ключевым словом `def`
вместо `async def`, FastAPI ожидает её выполнения, запустив функцию во внешнем
<abbr title="threadpool">пуле потоков</abbr>, а не напрямую (это бы заблокировало сервер).
Когда вы объявляете *функцию-обработчик пути* обычным `def` вместо `async def`, она запускается во внешнем пуле потоков, который затем «ожидается», вместо прямого вызова (прямой вызов заблокировал бы сервер).
Если ранее вы использовали другой асинхронный фреймворк, который работает иначе,
и привыкли объявлять простые вычислительные *функции* через `def` ради
незначительного прироста скорости (порядка 100 наносекунд), обратите внимание,
что с **FastAPI** вы получите противоположный эффект. В таком случае больше подходит
`async def`, если только *функция обработки пути* не использует код, приводящий
к блокировке <abbr title="Ввод/вывод: чтение и запись на диск, сетевые соединения.">I/O</abbr>.
<!--Уточнить: Не использовать async def, если код приводит к блокировке IO?-->
Если вы пришли из другого async-фреймворка, который работает иначе, и привыкли объявлять тривиальные *функции-обработчики пути*, выполняющие только вычисления, через простой `def` ради крошечной выгоды в производительности (около 100 наносекунд), обратите внимание: в **FastAPI** эффект будет противоположным. В таких случаях лучше использовать `async def`, если только ваши *функции-обработчики пути* не используют код, выполняющий блокирующий <abbr title="Input/Output Ввод/вывод: чтение или запись на диск, сетевые соединения.">I/O</abbr>.
<!--http://new.gramota.ru/spravka/punctum?layout=item&id=58_285-->
Но в любом случае велика вероятность, что **FastAPI** [окажется быстрее](index.md#_11){.internal-link target=_blank}
другого фреймворка (или хотя бы на уровне с ним).
Тем не менее, в обоих случаях велика вероятность, что **FastAPI** [всё равно будет быстрее](index.md#performance){.internal-link target=_blank} (или как минимум сопоставим) с вашим предыдущим фреймворком.
### Зависимости
### Зависимости { #dependencies }
То же относится к зависимостям. Если это обычная функция `def`, а не `async def`,
она запускается во внешнем пуле потоков.
То же относится к [зависимостям](tutorial/dependencies/index.md){.internal-link target=_blank}. Если зависимость — это обычная функция `def`, а не `async def`, она запускается во внешнем пуле потоков.
### Подзависимости
### Подзависимости { #sub-dependencies }
Вы можете объявить множество ссылающихся друг на друга зависимостей и подзависимостей
(в виде параметров при определении функции). Какие-то будут созданы с помощью `async def`,
другие обычным образом через `def`, и такая схема вполне работоспособна. Функции,
объявленные с помощью `def` будут запускаться на внешнем потоке (из пула),
а не с помощью `await`.
У вас может быть несколько зависимостей и [подзависимостей](tutorial/dependencies/sub-dependencies.md){.internal-link target=_blank}, которые требуют друг друга (в виде параметров определений функций): часть из них может быть объявлена с `async def`, а часть — обычным `def`. Всё будет работать, а те, что объявлены обычным `def`, будут вызываться во внешнем потоке (из пула), а не «ожидаться».
### Другие служебные функции
### Другие служебные функции { #other-utility-functions }
Любые другие служебные функции, которые вы вызываете напрямую, можно объявлять
с использованием `def` или `async def`. FastAPI не будет влиять на то, как вы
их запускаете.
Любые другие служебные функции, которые вы вызываете напрямую, можно объявлять обычным `def` или `async def`, и FastAPI не будет влиять на то, как вы их вызываете.
Этим они отличаются от функций, которые FastAPI вызывает самостоятельно:
*функции обработки пути* и зависимости.
В отличие от функций, которые FastAPI вызывает за вас: *функции-обработчики пути* и зависимости.
Если служебная функция объявлена с помощью `def`, она будет вызвана напрямую
(как вы и написали в коде), а не в отдельном потоке. Если же она объявлена с
помощью `async def`, её вызов должен осуществляться с ожиданием через `await`.
Если служебная функция — обычная функция с `def`, она будет вызвана напрямую (как вы и пишете в коде), не в пуле потоков; если функция объявлена с `async def`, тогда при её вызове в вашем коде вы должны использовать `await`.
---
<!--http://new.gramota.ru/spravka/buro/search-answer?s=299749-->
Ещё раз повторим, что все эти технические подробности полезны, только если вы специально их искали.
Снова: это очень технические подробности, полезные, вероятно, только если вы целенаправленно их ищете.
В противном случае просто ознакомьтесь с основными принципами в разделе выше: <a href="#_1">Нет времени?</a>.
Иначе вам достаточно руководствоваться рекомендациями из раздела выше: <a href="#in-a-hurry">Нет времени?</a>.

Some files were not shown because too many files have changed in this diff Show More