diff --git a/.github/DISCUSSION_TEMPLATE/translations.yml b/.github/DISCUSSION_TEMPLATE/translations.yml new file mode 100644 index 000000000..16e304d99 --- /dev/null +++ b/.github/DISCUSSION_TEMPLATE/translations.yml @@ -0,0 +1,45 @@ +labels: [lang-all] +body: + - type: markdown + attributes: + value: | + Thanks for your interest in helping translate the FastAPI docs! 🌍 + + Please follow these instructions carefully to propose a new language translation. 🙏 + + This structured process helps ensure translations can be properly maintained long-term. + - type: checkboxes + id: checks + attributes: + label: Initial Checks + description: Please confirm and check all the following options. + options: + - label: I checked that this language is not already being translated in FastAPI docs. + required: true + - label: I searched existing discussions to ensure no one else proposed this language. + required: true + - label: I am a native speaker of the language I want to help translate. + required: true + - type: input + id: language + attributes: + label: Target Language + description: What language do you want to translate the FastAPI docs into? + placeholder: e.g. Latin + validations: + required: true + - type: textarea + id: additional_info + attributes: + label: Additional Information + description: Any other relevant information about your translation proposal + - type: markdown + attributes: + value: | + Translations are automatized with AI and then reviewed by native speakers. 🤖 🙋 + + This allows us to keep them consistent and up-to-date. + + If there are several native speakers commenting on this discussion and + committing to help review new translations, the FastAPI team will review it + and potentially make it an official translation. 😎 diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml index 6ecdf487c..e84e4e4ab 100644 --- a/.github/workflows/build-docs.yml +++ b/.github/workflows/build-docs.yml @@ -53,7 +53,7 @@ jobs: with: python-version: "3.11" - name: Setup uv - uses: astral-sh/setup-uv@v5 + uses: astral-sh/setup-uv@v6 with: version: "0.4.15" enable-cache: true @@ -95,7 +95,7 @@ jobs: with: python-version: "3.11" - name: Setup uv - uses: astral-sh/setup-uv@v5 + uses: astral-sh/setup-uv@v6 with: version: "0.4.15" enable-cache: true diff --git a/.github/workflows/contributors.yml b/.github/workflows/contributors.yml index 87abfe3a1..34b54b452 100644 --- a/.github/workflows/contributors.yml +++ b/.github/workflows/contributors.yml @@ -30,7 +30,7 @@ jobs: with: python-version: "3.11" - name: Setup uv - uses: astral-sh/setup-uv@v5 + uses: astral-sh/setup-uv@v6 with: version: "0.4.15" enable-cache: true diff --git a/.github/workflows/deploy-docs.yml b/.github/workflows/deploy-docs.yml index d9ed61910..9ca69b208 100644 --- a/.github/workflows/deploy-docs.yml +++ b/.github/workflows/deploy-docs.yml @@ -29,7 +29,7 @@ jobs: with: python-version: "3.11" - name: Setup uv - uses: astral-sh/setup-uv@v5 + uses: astral-sh/setup-uv@v6 with: version: "0.4.15" enable-cache: true @@ -62,10 +62,7 @@ jobs: env: PROJECT_NAME: fastapitiangolo BRANCH: ${{ ( github.event.workflow_run.head_repository.full_name == github.repository && github.event.workflow_run.head_branch == 'master' && 'main' ) || ( github.event.workflow_run.head_sha ) }} - # TODO: Use v3 when it's fixed, probably in v3.11 - # https://github.com/cloudflare/wrangler-action/issues/307 - uses: cloudflare/wrangler-action@v3.13 - # uses: cloudflare/wrangler-action@v3 + uses: cloudflare/wrangler-action@v3 with: apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }} accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} diff --git a/.github/workflows/label-approved.yml b/.github/workflows/label-approved.yml index 02070146c..908a9453d 100644 --- a/.github/workflows/label-approved.yml +++ b/.github/workflows/label-approved.yml @@ -26,7 +26,7 @@ jobs: with: python-version: "3.11" - name: Setup uv - uses: astral-sh/setup-uv@v5 + uses: astral-sh/setup-uv@v6 with: version: "0.4.15" enable-cache: true diff --git a/.github/workflows/latest-changes.yml b/.github/workflows/latest-changes.yml index b8b5c42ee..208ab0c65 100644 --- a/.github/workflows/latest-changes.yml +++ b/.github/workflows/latest-changes.yml @@ -34,7 +34,7 @@ jobs: if: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.debug_enabled == 'true' }} with: limit-access-to-actor: true - - uses: tiangolo/latest-changes@0.3.2 + - uses: tiangolo/latest-changes@0.4.0 with: token: ${{ secrets.GITHUB_TOKEN }} latest_changes_file: docs/en/docs/release-notes.md diff --git a/.github/workflows/notify-translations.yml b/.github/workflows/notify-translations.yml index c96992689..621d1253a 100644 --- a/.github/workflows/notify-translations.yml +++ b/.github/workflows/notify-translations.yml @@ -34,7 +34,7 @@ jobs: with: python-version: "3.11" - name: Setup uv - uses: astral-sh/setup-uv@v5 + uses: astral-sh/setup-uv@v6 with: version: "0.4.15" enable-cache: true diff --git a/.github/workflows/people.yml b/.github/workflows/people.yml index 6ec3c1ad2..c1df3455e 100644 --- a/.github/workflows/people.yml +++ b/.github/workflows/people.yml @@ -30,7 +30,7 @@ jobs: with: python-version: "3.11" - name: Setup uv - uses: astral-sh/setup-uv@v5 + uses: astral-sh/setup-uv@v6 with: version: "0.4.15" enable-cache: true @@ -51,3 +51,4 @@ jobs: run: python ./scripts/people.py env: GITHUB_TOKEN: ${{ secrets.FASTAPI_PEOPLE }} + SLEEP_INTERVAL: ${{ vars.PEOPLE_SLEEP_INTERVAL }} diff --git a/.github/workflows/smokeshow.yml b/.github/workflows/smokeshow.yml index a0ffd55e6..d8a5dfb30 100644 --- a/.github/workflows/smokeshow.yml +++ b/.github/workflows/smokeshow.yml @@ -26,7 +26,7 @@ jobs: with: python-version: '3.9' - name: Setup uv - uses: astral-sh/setup-uv@v5 + uses: astral-sh/setup-uv@v6 with: version: "0.4.15" enable-cache: true diff --git a/.github/workflows/sponsors.yml b/.github/workflows/sponsors.yml index a5230c834..6da4d90e1 100644 --- a/.github/workflows/sponsors.yml +++ b/.github/workflows/sponsors.yml @@ -30,7 +30,7 @@ jobs: with: python-version: "3.11" - name: Setup uv - uses: astral-sh/setup-uv@v5 + uses: astral-sh/setup-uv@v6 with: version: "0.4.15" enable-cache: true diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 793e789e2..c3940be01 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -29,7 +29,7 @@ jobs: with: python-version: "3.11" - name: Setup uv - uses: astral-sh/setup-uv@v5 + uses: astral-sh/setup-uv@v6 with: version: "0.4.15" enable-cache: true @@ -48,6 +48,7 @@ jobs: strategy: matrix: python-version: + - "3.13" - "3.12" - "3.11" - "3.10" @@ -66,7 +67,7 @@ jobs: with: python-version: ${{ matrix.python-version }} - name: Setup uv - uses: astral-sh/setup-uv@v5 + uses: astral-sh/setup-uv@v6 with: version: "0.4.15" enable-cache: true @@ -111,7 +112,7 @@ jobs: with: python-version: '3.8' - name: Setup uv - uses: astral-sh/setup-uv@v5 + uses: astral-sh/setup-uv@v6 with: version: "0.4.15" enable-cache: true diff --git a/.github/workflows/topic-repos.yml b/.github/workflows/topic-repos.yml index 3c5c881f1..433aeb00b 100644 --- a/.github/workflows/topic-repos.yml +++ b/.github/workflows/topic-repos.yml @@ -25,7 +25,7 @@ jobs: with: python-version: "3.11" - name: Setup uv - uses: astral-sh/setup-uv@v5 + uses: astral-sh/setup-uv@v6 with: version: "0.4.15" enable-cache: true diff --git a/.github/workflows/translate.yml b/.github/workflows/translate.yml new file mode 100644 index 000000000..fc6b4d730 --- /dev/null +++ b/.github/workflows/translate.yml @@ -0,0 +1,77 @@ +name: Translate + +on: + workflow_dispatch: + inputs: + debug_enabled: + description: Run with tmate debugging enabled (https://github.com/marketplace/actions/debugging-with-tmate) + required: false + default: "false" + command: + description: Command to run + type: choice + options: + - translate-page + - translate-lang + - update-outdated + - add-missing + - update-and-add + - remove-all-removable + language: + description: Language to translate to as a letter code (e.g. "es" for Spanish) + type: string + required: false + default: "" + en_path: + description: File path in English to translate (e.g. docs/en/docs/index.md) + type: string + required: false + default: "" + +env: + UV_SYSTEM_PYTHON: 1 + +jobs: + job: + if: github.repository_owner == 'fastapi' + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - name: Dump GitHub context + env: + GITHUB_CONTEXT: ${{ toJson(github) }} + run: echo "$GITHUB_CONTEXT" + - uses: actions/checkout@v4 + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: "3.11" + - name: Setup uv + uses: astral-sh/setup-uv@v6 + with: + version: "0.4.15" + enable-cache: true + cache-dependency-glob: | + requirements**.txt + pyproject.toml + - name: Install Dependencies + run: uv pip install -r requirements-github-actions.txt -r requirements-translations.txt + # Allow debugging with tmate + - name: Setup tmate session + uses: mxschmitt/action-tmate@v3 + if: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.debug_enabled == 'true' }} + with: + limit-access-to-actor: true + env: + GITHUB_TOKEN: ${{ secrets.FASTAPI_TRANSLATIONS }} + OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} + - name: FastAPI Translate + run: | + python ./scripts/translate.py ${{ github.event.inputs.command }} + python ./scripts/translate.py make-pr + env: + GITHUB_TOKEN: ${{ secrets.FASTAPI_TRANSLATIONS }} + OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} + LANGUAGE: ${{ github.event.inputs.language }} + EN_PATH: ${{ github.event.inputs.en_path }} diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 767ef8d9e..0f882b221 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -14,7 +14,7 @@ repos: - id: end-of-file-fixer - id: trailing-whitespace - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.7.4 + rev: v0.12.5 hooks: - id: ruff args: diff --git a/README.md b/README.md index 6492ad745..0e421c347 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@

- Test + Test Coverage @@ -48,20 +48,22 @@ The key features are: - - - - - + - - - + + + + + + + + + @@ -148,7 +150,7 @@ $ pip install "fastapi[standard]" ### Create it -* Create a file `main.py` with: +Create a file `main.py` with: ```Python from typing import Union @@ -470,15 +472,20 @@ Used by Starlette: * jinja2 - Required if you want to use the default template configuration. * python-multipart - Required if you want to support form "parsing", with `request.form()`. -Used by FastAPI / Starlette: +Used by FastAPI: * uvicorn - for the server that loads and serves your application. This includes `uvicorn[standard]`, which includes some dependencies (e.g. `uvloop`) needed for high performance serving. -* `fastapi-cli` - to provide the `fastapi` command. +* `fastapi-cli[standard]` - to provide the `fastapi` command. + * This includes `fastapi-cloud-cli`, which allows you to deploy your FastAPI application to FastAPI Cloud. ### Without `standard` Dependencies If you don't want to include the `standard` optional dependencies, you can install with `pip install fastapi` instead of `pip install "fastapi[standard]"`. +### Without `fastapi-cloud-cli` + +If you want to install FastAPI with the standard dependencies but without the `fastapi-cloud-cli`, you can install with `pip install "fastapi[standard-no-fastapi-cloud-cli]"`. + ### Additional Optional Dependencies There are some additional dependencies you might want to install. diff --git a/docs/az/docs/index.md b/docs/az/docs/index.md index ad78d7d06..fbbbce130 100644 --- a/docs/az/docs/index.md +++ b/docs/az/docs/index.md @@ -6,7 +6,7 @@

- Test + Test Əhatə diff --git a/docs/bn/docs/about/index.md b/docs/bn/docs/about/index.md new file mode 100644 index 000000000..b6d611ae9 --- /dev/null +++ b/docs/bn/docs/about/index.md @@ -0,0 +1,3 @@ +# āϏāĻŽā§āĻĒāĻ°ā§āϕ⧇ + +**FastAPI** āϏāĻŽā§āĻĒāĻ°ā§āϕ⧇ āĻŦāĻŋāĻ¸ā§āϤāĻžāϰāĻŋāϤ — āĻāϰ āĻĄāĻŋāϜāĻžāχāύ, āĻ…āύ⧁āĻĒā§āϰ⧇āϰāĻŖāĻž āĻ“ āφāϰāĻ“ āĻ…āύ⧇āĻ• āĻ•āĻŋāϛ⧁āĨ¤ 🤓 diff --git a/docs/bn/docs/environment-variables.md b/docs/bn/docs/environment-variables.md new file mode 100644 index 000000000..9122ca5bf --- /dev/null +++ b/docs/bn/docs/environment-variables.md @@ -0,0 +1,298 @@ +# āĻāύāĻ­āĻžāϝāĻŧāϰāύāĻŽā§‡āĻ¨ā§āϟ āϭ⧇āϰāĻŋāϝāĻŧ⧇āĻŦāϞāϏ + +/// tip + +āφāĻĒāύāĻŋ āϝāĻĻāĻŋ "āĻāύāĻ­āĻžāϝāĻŧāϰāύāĻŽā§‡āĻ¨ā§āϟ āϭ⧇āϰāĻŋāϝāĻŧ⧇āĻŦāϞāϏ" āϕ⧀ āĻāĻŦāĻ‚ āϏ⧇āϗ⧁āϞ⧋ āϕ⧀āĻ­āĻžāĻŦ⧇ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāϤ⧇ āĻšāϝāĻŧ āϏ⧇āϟāĻž āϜāĻžāύ⧇āύ, āϤāĻžāĻšāϞ⧇ āĻāχ āĻ…āĻ‚āĻļāϟāĻŋ āĻ¸ā§āĻ•āĻŋāĻĒ āĻ•āϰ⧇ āϝ⧇āϤ⧇ āĻĒāĻžāϰ⧇āύāĨ¤ + +/// + +āĻāύāĻ­āĻžāϝāĻŧāϰāύāĻŽā§‡āĻ¨ā§āϟ āϭ⧇āϰāĻŋāϝāĻŧ⧇āĻŦāϞ (āϏāĻ‚āĻ•ā§āώ⧇āĻĒ⧇ "**env var**" āύāĻžāĻŽā§‡āĻ“ āĻĒāϰāĻŋāϚāĻŋāϤ) āĻšāϞ⧋ āĻāĻŽāύ āĻāĻ•āϟāĻŋ āϭ⧇āϰāĻŋāϝāĻŧ⧇āĻŦāϞ āϝāĻž āĻĒāĻžāχāĻĨāύ āϕ⧋āĻĄā§‡āϰ **āĻŦāĻžāχāϰ⧇**, **āĻ…āĻĒāĻžāϰ⧇āϟāĻŋāĻ‚ āϏāĻŋāĻ¸ā§āĻŸā§‡āĻŽā§‡** āĻĨāĻžāϕ⧇ āĻāĻŦāĻ‚ āφāĻĒāύāĻžāϰ āĻĒāĻžāχāĻĨāύ āϕ⧋āĻĄ (āĻŦāĻž āĻ…āĻ¨ā§āϝāĻžāĻ¨ā§āϝ āĻĒā§āϰ⧋āĻ—ā§āϰāĻžāĻŽ) āĻĻā§āĻŦāĻžāϰāĻž āϝāĻžāϕ⧇ āϰāĻŋāĻĄ āĻ•āϰāĻž āϝāĻžāϝāĻŧāĨ¤ + +āĻāύāĻ­āĻžāϝāĻŧāϰāύāĻŽā§‡āĻ¨ā§āϟ āϭ⧇āϰāĻŋāϝāĻŧ⧇āĻŦāϞāϏ āĻ…ā§āϝāĻžāĻĒā§āϞāĻŋāϕ⧇āĻļāύ⧇āϰ **āϏ⧇āϟāĻŋāĻ‚āϏ** āĻĒāϰāĻŋāϚāĻžāϞāύāĻž āĻ•āϰāϤ⧇, āĻĒāĻžāχāĻĨāύ⧇āϰ **āχāύāĻ¸ā§āϟāϞ⧇āĻļāύ** āĻĒā§āϰāĻ•ā§āϰāĻŋāϝāĻŧāĻžāϰ āĻ…āĻ‚āĻļ āĻšāĻŋāϏ⧇āĻŦ⧇, āχāĻ¤ā§āϝāĻžāĻĻāĻŋ āĻ•āĻžāĻœā§‡ āωāĻĒāϝ⧋āĻ—ā§€ āĻšāϤ⧇ āĻĒāĻžāϰ⧇āĨ¤ + +## Env Vars āϤ⧈āϰ⧀ āĻāĻŦāĻ‚ āĻŦā§āϝāĻŦāĻšāĻžāϰ + +āφāĻĒāύāĻŋ **āĻļ⧇āϞ (āϟāĻžāĻ°ā§āĻŽāĻŋāύāĻžāϞ)**-āĻ, āĻĒāĻžāχāĻĨāύ⧇āϰ āĻĒā§āϰāϝāĻŧā§‹āϜāύ āĻ›āĻžāĻĄāĻŧāĻžāχ, āĻāύāĻ­āĻžāϝāĻŧāϰāύāĻŽā§‡āĻ¨ā§āϟ āϭ⧇āϰāĻŋāϝāĻŧ⧇āĻŦāϞāϏ **āϤ⧈āϰāĻŋ** āĻāĻŦāĻ‚ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāϤ⧇ āĻĒāĻžāϰāĻŦ⧇āύāσ + +//// tab | āϞāĻŋāύāĻžāĻ•ā§āϏ, āĻŽā§āϝāĻžāĻ•āĻ“āĻāϏ, āωāχāĻ¨ā§āĻĄā§‹āϜ Bash + +

+ +```console +// āφāĻĒāύāĻŋ āϚāĻžāχāϞ⧇ MY_NAME āύāĻžāĻŽā§‡ āĻāĻ•āϟāĻŋ env var āϤ⧈āϰāĻŋ āĻ•āϰāϤ⧇ āĻĒāĻžāϰ⧇āύ +$ export MY_NAME="Wade Wilson" + +// āϤāĻžāϰāĻĒāϰ⧇ āĻāϟāĻŋāϕ⧇ āϚāĻžāχāϞ⧇ āĻ…āĻ¨ā§āϝāĻžāĻ¨ā§āϝ āĻĒā§āϰ⧋āĻ—ā§āϰāĻžāĻŽā§‡ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāϤ⧇ āĻĒāĻžāϰ⧇āύ +$ echo "Hello $MY_NAME" + +Hello Wade Wilson +``` + +
+ +//// + +//// tab | āωāχāĻ¨ā§āĻĄā§‹āϜ āĻĒāĻžāĻ“ā§ŸāĻžāϰāĻļ⧇āϞ + +
+ +```console +// MY_NAME āύāĻžāĻŽā§‡ env var āϤ⧈āϰāĻŋ +$ $Env:MY_NAME = "Wade Wilson" + +// āĻ…āĻ¨ā§āϝāĻžāĻ¨ā§āϝ āĻĒā§āϰ⧋āĻ—ā§āϰāĻžāĻŽā§‡ āĻāϟāĻŋāϕ⧇ āĻŦā§āϝāĻŦāĻšāĻžāϰ +$ echo "Hello $Env:MY_NAME" + +Hello Wade Wilson +``` + +
+ +//// + +## āĻĒāĻžāχāĻĨāύ⧇ env vars āϰāĻŋāĻĄ āĻ•āϰāĻž + +āφāĻĒāύāĻŋ āϚāĻžāχāϞ⧇ āĻĒāĻžāχāĻĨāύ⧇āϰ **āĻŦāĻžāχāϰ⧇**, āϟāĻžāĻ°ā§āĻŽāĻŋāύāĻžāϞ⧇ (āĻŦāĻž āĻ…āĻ¨ā§āϝ āϕ⧋āύ⧋ āωāĻĒāĻžāϝāĻŧ⧇) āĻāύāĻ­āĻžāϝāĻŧāϰāύāĻŽā§‡āĻ¨ā§āϟ āϭ⧇āϰāĻŋāϝāĻŧ⧇āĻŦāϞāϏ āϤ⧈āϰāĻŋ āĻ•āϰāϤ⧇ āĻĒāĻžāϰ⧇āύ, āĻāĻŦāĻ‚ āĻĒāϰ⧇ āϏ⧇āϗ⧁āϞ⧋ **āĻĒāĻžāχāĻĨāύ⧇ āϰāĻŋāĻĄ** (āĻ…ā§āϝāĻžāĻ•ā§āϏ⧇āϏ āĻ•āϰāϤ⧇) āĻĒāĻžāϰ⧇āύāĨ¤ + +āωāĻĻāĻžāĻšāϰāĻŖāĻ¸ā§āĻŦāϰ⧂āĻĒ, āφāĻĒāύāĻžāϰ `main.py` āύāĻžāĻŽā§‡ āĻāĻ•āϟāĻŋ āĻĢāĻžāχāϞ āĻĨāĻžāĻ•āϤ⧇ āĻĒāĻžāϰ⧇āσ + +```Python hl_lines="3" +import os + +name = os.getenv("MY_NAME", "World") +print(f"Hello {name} from Python") +``` + +/// tip + +
`os.getenv()` āĻāϰ āĻĻā§āĻŦāĻŋāĻ¤ā§€ā§Ÿ āφāĻ°ā§āϗ⧁āĻŽā§‡āĻ¨ā§āϟāϟāĻŋ āĻšāϞ⧋ āĻāϰ āĻĄāĻŋāĻĢāĻ˛ā§āϟ āĻ­ā§āϝāĻžāϞ⧁ āϝāĻž āϰāĻŋāϟāĻžāĻ°ā§āύ āĻ•āϰāĻž āĻšāĻŦ⧇āĨ¤ + +āϝāĻĻāĻŋ āĻāϟāĻŋ āĻĻ⧇āĻ“ā§ŸāĻž āύāĻž āĻšā§Ÿ, āĻĄāĻŋāĻĢāĻ˛ā§āϟāĻ­āĻžāĻŦ⧇ `None` āĻŦā§āϝāĻŦāĻšā§ƒāϤ āĻšāĻŦ⧇, āĻāĻ–āĻžāύ⧇ āφāĻŽāϰāĻž āĻĄāĻŋāĻĢāĻ˛ā§āϟ āĻ­ā§āϝāĻžāϞ⧁ āĻšāĻŋāϏ⧇āĻŦ⧇ `"World"` āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰ⧇āĻ›āĻŋāĨ¤ + +/// + +āϤāĻžāϰāĻĒāϰ⧇ āĻĒāĻžāχāĻĨāύ āĻĒā§āϰ⧋āĻ—ā§āϰāĻžāĻŽāϟāĻŋāϕ⧇ āύāĻŋāĻŽā§āύ⧋āĻ•ā§āϤāĻ­āĻžāĻŦ⧇ āĻ•āϞ āĻ•āϰāĻž āϝāĻžāĻŦ⧇āσ + +//// tab | āϞāĻŋāύāĻžāĻ•ā§āϏ, āĻŽā§āϝāĻžāĻ•āĻ“āĻāϏ, āωāχāĻ¨ā§āĻĄā§‹āϜ Bash + +
+ +```console +// āĻāĻ–āύ⧋ āφāĻŽāϰāĻž āĻāύāĻ­āĻžā§ŸāϰāύāĻŽā§‡āĻ¨ā§āϟ āϭ⧇āϰāĻŋāϝāĻŧ⧇āĻŦāϞ āϏ⧇āϟ āĻ•āϰāĻŋāύāĻŋ +$ python main.py + +// āϝ⧇āĻšā§‡āϤ⧁ env var āϏ⧇āϟ āĻ•āϰāĻž āĻšā§ŸāύāĻŋ, āϤāĻžāχ āφāĻŽāϰāĻž āĻĄāĻŋāĻĢāĻ˛ā§āϟ āĻ­ā§āϝāĻžāϞ⧁ āĻĒāĻžāĻšā§āĻ›āĻŋ + +Hello World from Python + +// āĻ•āĻŋāĻ¨ā§āϤ⧁ āφāĻŽāϰāĻž āĻĒā§āϰāĻĨāĻŽā§‡ āϝāĻĻāĻŋ āĻāĻ•āϟāĻž āĻāύāĻ­āĻžā§ŸāϰāύāĻŽā§‡āĻ¨ā§āϟ āĻ­āĻžāϰāĻŋā§Ÿā§‡āĻŦāϞ āϤ⧈āϰāĻŋ āĻ•āϰ⧇ āύ⧇āχ +$ export MY_NAME="Wade Wilson" + +// āĻāĻŦāĻ‚ āϤāĻžāϰāĻĒāϰ āφāĻŦāĻžāϰ āĻĒā§āϰ⧋āĻ—ā§āϰāĻžāϟāĻŋāϕ⧇ āĻ•āϞ āĻ•āϰāĻŋ +$ python main.py + +// āĻāĻ–āύ āĻāϟāĻŋ āĻāύāĻ­āĻžā§ŸāϰāύāĻŽā§‡āĻ¨ā§āϟ āϭ⧇āϰāĻŋāϝāĻŧ⧇āĻŦāϞ āϰāĻŋāĻĄ āĻ•āϰāϤ⧇ āĻĒāĻžāϰāĻŦ⧇ + +Hello Wade Wilson from Python +``` + +
+ +//// + +//// tab | āωāχāĻ¨ā§āĻĄā§‹āϜ āĻĒāĻžāĻ“ā§ŸāĻžāϰāĻļ⧇āϞ + +
+ +```console +// āĻāĻ–āύ⧋ āφāĻŽāϰāĻž āĻāύāĻ­āĻžā§ŸāϰāύāĻŽā§‡āĻ¨ā§āϟ āϭ⧇āϰāĻŋāϝāĻŧ⧇āĻŦāϞ āϏ⧇āϟ āĻ•āϰāĻŋāύāĻŋ +$ python main.py + +// āϝ⧇āĻšā§‡āϤ⧁ env var āϏ⧇āϟ āĻ•āϰāĻž āĻšā§ŸāύāĻŋ, āϤāĻžāχ āφāĻŽāϰāĻž āĻĄāĻŋāĻĢāĻ˛ā§āϟ āĻ­ā§āϝāĻžāϞ⧁ āĻĒāĻžāĻšā§āĻ›āĻŋ + +Hello World from Python + +// āĻ•āĻŋāĻ¨ā§āϤ⧁ āφāĻŽāϰāĻž āĻĒā§āϰāĻĨāĻŽā§‡ āϝāĻĻāĻŋ āĻāĻ•āϟāĻž āĻāύāĻ­āĻžā§ŸāϰāύāĻŽā§‡āĻ¨ā§āϟ āĻ­āĻžāϰāĻŋā§Ÿā§‡āĻŦāϞ āϤ⧈āϰāĻŋ āĻ•āϰ⧇ āύ⧇āχ +$ $Env:MY_NAME = "Wade Wilson" + +// āĻāĻŦāĻ‚ āϤāĻžāϰāĻĒāϰ āφāĻŦāĻžāϰ āĻĒā§āϰ⧋āĻ—ā§āϰāĻžāϟāĻŋāϕ⧇ āĻ•āϞ āĻ•āϰāĻŋ +$ python main.py + +// āĻāĻ–āύ āĻāϟāĻŋ āĻāύāĻ­āĻžā§ŸāϰāύāĻŽā§‡āĻ¨ā§āϟ āϭ⧇āϰāĻŋāϝāĻŧ⧇āĻŦāϞ āϰāĻŋāĻĄ āĻ•āϰāϤ⧇ āĻĒāĻžāϰāĻŦ⧇ + +Hello Wade Wilson from Python +``` + +
+ +//// + +āϝ⧇āĻšā§‡āϤ⧁ āĻāύāĻ­āĻžāϝāĻŧāϰāύāĻŽā§‡āĻ¨ā§āϟ āϭ⧇āϰāĻŋāϝāĻŧ⧇āĻŦāϞāϏ āϕ⧋āĻĄā§‡āϰ āĻŦāĻžāχāϰ⧇ āϏ⧇āϟ āĻ•āϰāĻž āϝāĻžāϝāĻŧ, āĻ•āĻŋāĻ¨ā§āϤ⧁ āĻĒāϰāĻŦāĻ°ā§āϤ⧀āϤ⧇ āϕ⧋āĻĄ āĻĻā§āĻŦāĻžāϰāĻž āϰāĻŋāĻĄ āĻ•āϰāĻž āϝāĻžāϝāĻŧ, āĻāĻŦāĻ‚ āĻŦāĻžāĻ•āĻŋ āĻĢāĻžāχāϞāϗ⧁āϞ⧋āϰ āϏāĻžāĻĨ⧇ āϰāĻžāĻ–āϤ⧇ (`git` āĻ āĻ•āĻŽāĻŋāϟ) āĻšā§Ÿ āύāĻž, āϤāĻžāχ āĻ•āύāĻĢāĻŋāĻ—āĻžāϰ⧇āĻļāύāϏ āĻŦāĻž **āϏ⧇āϟāĻŋāĻ‚āϏ** āĻāϰ āϜāĻ¨ā§āϝ āĻāϗ⧁āϞ⧋ āϏāĻžāϧāĻžāϰāĻŖāϤ āĻŦā§āϝāĻŦāĻšā§ƒāϤ āĻšā§Ÿā§‡ āĻĨāĻžāϕ⧇āĨ¤ + +āφāĻĒāύāĻŋ āĻāĻ•āϟāĻŋ āĻāύāĻ­āĻžāϝāĻŧāϰāύāĻŽā§‡āĻ¨ā§āϟ āϭ⧇āϰāĻŋāϝāĻŧ⧇āĻŦāϞ āĻļ⧁āϧ⧁āĻŽāĻžāĻ¤ā§āϰ āĻāĻ•āϟāĻŋ **āύāĻŋāĻ°ā§āĻĻāĻŋāĻˇā§āϟ āĻĒā§āϰ⧋āĻ—ā§āϰāĻžāĻŽ āχāύāĻ­ā§‹āϕ⧇āĻļāύ⧇āϰ** āϜāĻ¨ā§āϝāĻ“ āϤ⧈āϰāĻŋ āĻ•āϰāϤ⧇ āĻĒāĻžāϰ⧇āύ, āϝāĻž āĻļ⧁āϧ⧁āĻŽāĻžāĻ¤ā§āϰ āϏ⧇āχ āĻĒā§āϰ⧋āĻ—ā§āϰāĻžāĻŽā§‡āϰ āϜāĻ¨ā§āϝāχ āĻāϭ⧇āχāϞ⧇āĻŦāϞ āĻĨāĻžāĻ•āĻŦ⧇ āĻāĻŦāĻ‚ āĻļ⧁āϧ⧁āĻŽāĻžāĻ¤ā§āϰ āϤāĻžāϰ āϚāϞāĻžāĻ•āĻžāϞ⧀āύ āϏāĻŽāϝāĻŧ āĻĒāĻ°ā§āϝāĻ¨ā§āϤāχ āϏāĻ•ā§āϰāĻŋāϝāĻŧ āĻĨāĻžāĻ•āĻŦ⧇āĨ¤ + +āĻāϟāĻŋ āĻ•āϰāϤ⧇, āĻĒā§āϰ⧋āĻ—ā§āϰāĻžāĻŽāϟāĻŋ āϰāĻžāύ āĻ•āϰāĻžāϰ āĻ āĻŋāĻ• āφāϗ⧇āχ, āĻāĻ•āχ āϞāĻžāχāύ⧇ āĻāύāĻ­āĻžāϝāĻŧāϰāύāĻŽā§‡āĻ¨ā§āϟ āϭ⧇āϰāĻŋāϝāĻŧ⧇āĻŦāϞ āϤ⧈āϰāĻŋ āĻ•āϰ⧁āύ: + +
+ +```console +// āĻĒā§āϰ⧋āĻ—ā§āϰāĻžāĻŽāϟāĻŋ āĻ•āϞ āĻ•āϰāĻžāϰ āϏāĻŽā§Ÿ āĻāĻ•āχ āϞāĻžāχāύ⧇ MY_NAME āĻāύāĻ­āĻžā§ŸāϰāύāĻŽā§‡āĻ¨ā§āϟ āϭ⧇āϰāĻŋā§Ÿā§‡āĻŦāϞ āϤ⧈āϰāĻŋ āĻ•āϰ⧁āύ +$ MY_NAME="Wade Wilson" python main.py + +// āĻāĻ–āύ āĻāϟāĻŋ āĻāύāĻ­āĻžā§ŸāϰāύāĻŽā§‡āĻ¨ā§āϟ āĻ­ā§āϝāϰāĻŋā§Ÿā§‡āĻŦāϞāϟāĻŋāϕ⧇ āϰāĻŋāĻĄ āĻ•āϰāϤ⧇ āĻĒāĻžāϰāĻŦ⧇ + +Hello Wade Wilson from Python + +// āĻĒāϰāĻŦāĻ°ā§āϤ⧀āϤ⧇ āĻāύāĻ­āĻžā§ŸāϰāύāĻŽā§‡āĻ¨ā§āϟ āϭ⧇āϰāĻŋāϝāĻŧ⧇āĻŦāϞāϟāĻŋāϕ⧇ āφāϰ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāĻž āϝāĻžāĻšā§āϛ⧇ āύāĻž +$ python main.py + +Hello World from Python +``` + +
+ +/// tip + +āĻāϟāĻŋ āύāĻŋā§Ÿā§‡ āφāϰ⧋ āĻŦāĻŋāĻ¸ā§āϤāĻžāϰāĻŋāϤ āĻĒ⧜āϤ⧇ āĻĒāĻžāϰ⧇āύ āĻāĻ–āĻžāύ⧇ The Twelve-Factor App: ConfigāĨ¤ + +/// + +## āϟāĻžāχāĻĒāϏ āĻāĻŦāĻ‚ āĻ­ā§āϝāĻžāϞāĻŋāĻĄā§‡āĻļāύ + +āĻāχ āĻāύāĻ­āĻžā§ŸāϰāύāĻŽā§‡āĻ¨ā§āϟ āϭ⧇āϰāĻŋāϝāĻŧ⧇āĻŦāϞāϗ⧁āϞ⧋ āĻļ⧁āϧ⧁āĻŽāĻžāĻ¤ā§āϰ **āĻŸā§‡āĻ•ā§āϏāϟ āĻ¸ā§āĻŸā§āϰāĻŋāĻ‚āϏ** āĻšā§āϝāĻžāĻ¨ā§āĻĄā§‡āϞ āĻ•āϰāϤ⧇ āĻĒāĻžāϰ⧇, āϝ⧇āĻšā§‡āϤ⧁ āĻāϗ⧁āϞ⧋ āĻĒāĻžāχāĻĨāύ⧇āϰ āĻŦāĻžāχāϰ⧇ āĻ…āĻŦāĻ¸ā§āĻĨāĻŋāϤ āĻāĻŦāĻ‚ āĻ…āĻ¨ā§āϝāĻžāĻ¨ā§āϝ āĻĒā§āϰ⧋āĻ—ā§āϰāĻžāĻŽ āĻāĻŦāĻ‚ āϏāĻŋāĻ¸ā§āĻŸā§‡āĻŽā§‡āϰ āĻŦāĻžāĻ•āĻŋ āĻ…āĻ‚āĻļ⧇āϰ (āĻāĻŽāύāĻ•āĻŋ āĻŦāĻŋāĻ­āĻŋāĻ¨ā§āύ āĻ…āĻĒāĻžāϰ⧇āϟāĻŋāĻ‚ āϏāĻŋāĻ¸ā§āĻŸā§‡āĻŽ āϝ⧇āĻŽāύ āϞāĻŋāύāĻžāĻ•ā§āϏ, āωāχāĻ¨ā§āĻĄā§‹āϜ, āĻŽā§āϝāĻžāĻ•āĻ“āĻāϏ) āϏāĻžāĻĨ⧇ āϏāĻžāĻŽāĻžā§āϜāĻ¸ā§āϝāĻĒā§‚āĻ°ā§āĻŖ āĻšāϤ⧇ āĻšāϝāĻŧāĨ¤ + +āĻāϰ āĻ…āĻ°ā§āĻĨ āĻšāĻšā§āϛ⧇ āĻĒāĻžāχāĻĨāύ⧇ āĻāύāĻ­āĻžā§ŸāϰāύāĻŽā§‡āĻ¨ā§āϟ āϭ⧇āϰāĻŋāϝāĻŧ⧇āĻŦāϞ āĻĨ⧇āϕ⧇ āϰāĻŋāĻĄ āĻ•āϰāĻž **āϝ⧇āϕ⧋āύ⧋ āĻ­ā§āϝāĻžāϞ⧁** āĻāĻ•āϟāĻŋ `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` (āϏāĻ°ā§āĻŦāĻļ⧇āώ āĻĄāĻŋāϰ⧇āĻ•ā§āϟāϰāĻŋ) āϤ⧇ āϖ⧁āρāĻœā§‡ āĻĒāĻžāĻŦ⧇ āĻāĻŦāĻ‚ āĻāϟāĻžāϕ⧇ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāĻŦ⧇āĨ¤ + +//// + +āϤāĻžāχ, āφāĻĒāύāĻŋ āϝāĻĻāĻŋ āϟāĻžāχāĻĒ āĻ•āϰ⧇āύāσ + +
+ +```console +$ python +``` + +
+ +//// tab | āϞāĻŋāύāĻžāĻ•ā§āϏ, āĻŽā§āϝāĻžāĻ•āĻ“āĻāϏ + +āϏāĻŋāĻ¸ā§āĻŸā§‡āĻŽ `python` āĻĒā§āϰ⧋āĻ—ā§āϰāĻžāĻŽāϕ⧇ `/opt/custompython/bin` āĻ **āϖ⧁āρāĻœā§‡ āĻĒāĻžāĻŦ⧇** āĻāĻŦāĻ‚ āĻāϟāĻžāϕ⧇ āϰāĻžāύ āĻ•āϰāĻŦ⧇āĨ¤ + +āĻāϟāĻž āĻŽā§‹āϟāĻžāĻŽā§āϟāĻŋāĻ­āĻžāĻŦ⧇ āύāĻŋāĻšā§‡āϰ āĻŽāϤ⧋ āĻ•āϰ⧇ āϞ⧇āĻ–āĻžāϰ āϏāĻŽāĻžāύ āĻšāĻŦ⧇āσ + +
+ +```console +$ /opt/custompython/bin/python +``` + +
+ +//// + +//// tab | āωāχāĻ¨ā§āĻĄā§‹āϜ + +āϏāĻŋāĻ¸ā§āĻŸā§‡āĻŽ `python` āĻĒā§āϰ⧋āĻ—ā§āϰāĻžāĻŽāϕ⧇ `C:\opt\custompython\bin\python` āĻ **āϖ⧁āρāĻœā§‡ āĻĒāĻžāĻŦ⧇** āĻāĻŦāĻ‚ āĻāϟāĻžāϕ⧇ āϰāĻžāύ āĻ•āϰāĻŦ⧇āĨ¤ + +āĻāϟāĻž āĻŽā§‹āϟāĻžāĻŽā§āϟāĻŋāĻ­āĻžāĻŦ⧇ āύāĻŋāĻšā§‡āϰ āĻŽāϤ⧋ āĻ•āϰ⧇ āϞ⧇āĻ–āĻžāϰ āϏāĻŽāĻžāύ āĻšāĻŦ⧇āσ + +
+ +```console +$ C:\opt\custompython\bin\python +``` + +
+ +//// + +āĻāχ āϤāĻĨā§āϝāϗ⧁āϞ⧋ [āĻ­āĻžāĻ°ā§āϚ⧁⧟āĻžāϞ āĻāύāĻ­āĻžā§ŸāϰāύāĻŽā§‡āĻ¨ā§āϟāϏ](virtual-environments.md){.internal-link target=_blank} āĻļ⧇āĻ–āĻžāϰ āĻ•ā§āώ⧇āĻ¤ā§āϰ⧇ āϏāĻšāĻžā§ŸāĻ• āĻšāĻŦ⧇āĨ¤ + +## āωāĻĒāϏāĻ‚āĻšāĻžāϰ + +āĻāϰ āĻŽāĻžāĻ§ā§āϝāĻŽā§‡ āφāĻĒāύāĻŋ **āĻāύāĻ­āĻžā§ŸāϰāύāĻŽā§‡āĻ¨ā§āϟ āϭ⧇āϰāĻŋā§Ÿā§‡āĻŦāϞāϏ** āĻ•āĻŋ āĻāĻŦāĻ‚ āĻāϟāĻŋāϕ⧇ āĻĒāĻžāχāĻĨāύ⧇ āĻ•āĻŋāĻ­āĻžāĻŦ⧇ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāϤ⧇ āĻšā§Ÿ āϤāĻžāϰ āϏāĻŽā§āĻĒāĻ°ā§āϕ⧇ āĻŦ⧇āϏāĻŋāĻ• āϧāĻžāϰāύāĻž āĻĒ⧇āϞ⧇āύāĨ¤ + +āϚāĻžāχāϞ⧇ āĻāχ āϏāĻŽā§āĻĒāĻ°ā§āϕ⧇ āφāϰ⧋ āĻŦāĻŋāĻ¸ā§āϤāĻžāϰāĻŋāϤ āĻĒ⧜āϤ⧇ āĻĒāĻžāϰ⧇āύ Wikipedia for Environment Variable āĻāĨ¤ + +āĻ…āύ⧇āĻ• āĻ•ā§āώ⧇āĻ¤ā§āϰ⧇, āĻĻ⧇āĻ–āĻž āĻŽāĻžāĻ¤ā§āϰāχ āĻāύāĻ­āĻžāϝāĻŧāϰāύāĻŽā§‡āĻ¨ā§āϟ āϭ⧇āϰāĻŋāϝāĻŧ⧇āĻŦāϞ āϕ⧀āĻ­āĻžāĻŦ⧇ āĻĒā§āĻ°ā§Ÿā§‹āϜāύ āĻšāĻŦ⧇ āϤāĻž āĻ¸ā§āĻĒāĻˇā§āϟ āĻšā§Ÿ āύāĻžāĨ¤ āĻ•āĻŋāĻ¨ā§āϤ⧁ āĻĄā§‡āϭ⧇āϞāĻĒāĻŽā§‡āĻ¨ā§āĻŸā§‡āϰ āϏāĻŽāϝāĻŧ āφāĻĒāύāĻŋ āύāĻžāύāĻž āϰāĻ•āĻŽ āĻĒāϰāĻŋāĻ¸ā§āĻĨāĻŋāϤāĻŋāϤ⧇ āĻāϗ⧁āϞ⧋āϰ āϏāĻŽā§āĻŽā§āĻ–ā§€āύ āĻšāĻŦ⧇āύ, āϤāĻžāχ āĻāϗ⧁āϞ⧋ āϏāĻŽā§āĻĒāĻ°ā§āϕ⧇ āĻœā§‡āύ⧇ āϰāĻžāĻ–āĻž āĻ­āĻžāϞ⧋āĨ¤ + +āωāĻĻāĻžāĻšāϰāĻŖāĻ¸ā§āĻŦāϰ⧂āĻĒ, āφāĻĒāύāĻžāϰ āĻāχ āχāύāĻĢāϰāĻŽā§‡āĻļāύāϟāĻŋ āĻĒāϰāĻŦāĻ°ā§āϤ⧀, [āĻ­āĻžāĻ°ā§āϚ⧁⧟āĻžāϞ āĻāύāĻ­āĻžā§ŸāϰāύāĻŽā§‡āĻ¨ā§āϟāϏ](virtual-environments.md) āĻ…āĻ‚āĻļ⧇ āĻĻāϰāĻ•āĻžāϰ āĻšāĻŦ⧇āĨ¤ diff --git a/docs/bn/docs/index.md b/docs/bn/docs/index.md index 678ac9ca9..74ee230a1 100644 --- a/docs/bn/docs/index.md +++ b/docs/bn/docs/index.md @@ -5,15 +5,18 @@ FastAPI āωāĻšā§āϚāĻ•ā§āώāĻŽāϤāĻž āϏāĻŽā§āĻĒāĻ¨ā§āύ, āϏāĻšāĻœā§‡ āĻļ⧇āĻ–āĻžāϰ āĻāĻŦāĻ‚ āĻĻā§āϰ⧁āϤ āϕ⧋āĻĄ āĻ•āϰ⧇ āĻĒā§āϰ⧋āĻĄāĻžāĻ•āĻļāύ⧇āϰ āϜāĻ¨ā§āϝ āĻĢā§āϰāĻžāĻŽāĻ“ā§ŸāĻžāĻ°ā§āĻ•āĨ¤

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

--- diff --git a/docs/de/docs/advanced/generate-clients.md b/docs/de/docs/advanced/generate-clients.md index 38a69031c..f491d29af 100644 --- a/docs/de/docs/advanced/generate-clients.md +++ b/docs/de/docs/advanced/generate-clients.md @@ -20,7 +20,7 @@ Einige von diesen ✨ [**sponsern FastAPI**](../help-fastapi.md#den-autor-sponse Und es zeigt deren wahres Engagement fÃŧr FastAPI und seine **Community** (Sie), da diese Ihnen nicht nur einen **guten Service** bieten mÃļchten, sondern auch sicherstellen mÃļchten, dass Sie Ãŧber ein **gutes und gesundes Framework** verfÃŧgen, FastAPI. 🙇 -Beispielsweise kÃļnnten Sie Speakeasy ausprobieren. +Beispielsweise kÃļnnten Sie Speakeasy ausprobieren. Es gibt auch mehrere andere Unternehmen, welche ähnliche Dienste anbieten und die Sie online suchen und finden kÃļnnen. 🤓 diff --git a/docs/de/docs/deployment/concepts.md b/docs/de/docs/deployment/concepts.md index 97ad854e2..907598e54 100644 --- a/docs/de/docs/deployment/concepts.md +++ b/docs/de/docs/deployment/concepts.md @@ -216,7 +216,7 @@ Dieser Manager-Prozess wäre wahrscheinlich derjenige, welcher der IP am **Port* Diese Workerprozesse wÃŧrden Ihre Anwendung ausfÃŧhren, sie wÃŧrden die Hauptberechnungen durchfÃŧhren, um einen **Request** entgegenzunehmen und eine **Response** zurÃŧckzugeben, und sie wÃŧrden alles, was Sie in Variablen einfÃŧgen, in den RAM laden. - + Und natÃŧrlich wÃŧrden auf derselben Maschine neben Ihrer Anwendung wahrscheinlich auch **andere Prozesse** laufen. diff --git a/docs/de/docs/deployment/https.md b/docs/de/docs/deployment/https.md index 630582995..a216f44af 100644 --- a/docs/de/docs/deployment/https.md +++ b/docs/de/docs/deployment/https.md @@ -85,7 +85,7 @@ Zuerst wÃŧrde der Browser mithilfe der **DNS-Server** herausfinden, welches die Die DNS-Server geben dem Browser eine bestimmte **IP-Adresse** zurÃŧck. Das wäre die von Ihrem Server verwendete Ãļffentliche IP-Adresse, die Sie in den DNS-Servern konfiguriert haben. - + ### TLS-Handshake-Start @@ -93,7 +93,7 @@ Der Browser kommuniziert dann mit dieser IP-Adresse Ãŧber **Port 443** (den HTTP Der erste Teil der Kommunikation besteht lediglich darin, die Verbindung zwischen dem Client und dem Server herzustellen und die zu verwendenden kryptografischen SchlÃŧssel usw. zu vereinbaren. - + Diese Interaktion zwischen dem Client und dem Server zum Aufbau der TLS-Verbindung wird als **TLS-Handshake** bezeichnet. @@ -111,7 +111,7 @@ Mithilfe der oben beschriebenen **SNI-Erweiterung** wÃŧrde der TLS-Terminierungs In diesem Fall wÃŧrde er das Zertifikat fÃŧr `someapp.example.com` verwenden. - + Der Client **vertraut** bereits der Entität, die das TLS-Zertifikat generiert hat (in diesem Fall Let's Encrypt, aber wir werden später mehr darÃŧber erfahren), sodass er **verifizieren** kann, dass das Zertifikat gÃŧltig ist. @@ -133,19 +133,19 @@ Da Client und Server (sprich, der Browser und der TLS-Terminierungsproxy) nun Ãŧ Der Client sendet also einen **HTTPS-Request**. Das ist einfach ein HTTP-Request Ãŧber eine verschlÃŧsselte TLS-Verbindung. - + ### Den Request entschlÃŧsseln Der TLS-Terminierungsproxy wÃŧrde die vereinbarte VerschlÃŧsselung zum **EntschlÃŧsseln des Requests** verwenden und den **einfachen (entschlÃŧsselten) HTTP-Request** an den Prozess weiterleiten, der die Anwendung ausfÃŧhrt (z. B. einen Prozess, bei dem Uvicorn die FastAPI-Anwendung ausfÃŧhrt). - + ### HTTP-Response Die Anwendung wÃŧrde den Request verarbeiten und eine **einfache (unverschlÃŧsselte) HTTP-Response** an den TLS-Terminierungsproxy senden. - + ### HTTPS-Response @@ -153,7 +153,7 @@ Der TLS-Terminierungsproxy wÃŧrde dann die Response mithilfe der zuvor vereinbar Als Nächstes ÃŧberprÃŧft der Browser, ob die Response gÃŧltig und mit dem richtigen kryptografischen SchlÃŧssel usw. verschlÃŧsselt ist. Anschließend **entschlÃŧsselt er die Response** und verarbeitet sie. - + Der Client (Browser) weiß, dass die Response vom richtigen Server kommt, da dieser die Kryptografie verwendet, die zuvor mit dem **HTTPS-Zertifikat** vereinbart wurde. @@ -163,7 +163,7 @@ Auf demselben Server (oder denselben Servern) kÃļnnten sich **mehrere Anwendunge Nur ein Prozess kann diese spezifische IP und den Port verarbeiten (in unserem Beispiel der TLS-Terminierungsproxy), aber die anderen Anwendungen/Prozesse kÃļnnen auch auf dem/den Server(n) ausgefÃŧhrt werden, solange sie nicht versuchen, dieselbe **Kombination aus Ãļffentlicher IP und Port** zu verwenden. - + Auf diese Weise kÃļnnte der TLS-Terminierungsproxy HTTPS und Zertifikate fÃŧr **mehrere Domains**, fÃŧr mehrere Anwendungen, verarbeiten und die Requests dann jeweils an die richtige Anwendung weiterleiten. @@ -173,7 +173,7 @@ Irgendwann in der Zukunft wÃŧrde jedes Zertifikat **ablaufen** (etwa 3 Monate na Und dann gäbe es ein anderes Programm (in manchen Fällen ist es ein anderes Programm, in manchen Fällen ist es derselbe TLS-Terminierungsproxy), das mit Let's Encrypt kommuniziert und das/die Zertifikat(e) erneuert. - + Die **TLS-Zertifikate** sind **einem Domainnamen zugeordnet**, nicht einer IP-Adresse. diff --git a/docs/de/docs/how-to/custom-docs-ui-assets.md b/docs/de/docs/how-to/custom-docs-ui-assets.md index ab8cd9f6b..f68902b99 100644 --- a/docs/de/docs/how-to/custom-docs-ui-assets.md +++ b/docs/de/docs/how-to/custom-docs-ui-assets.md @@ -98,7 +98,7 @@ Sie kÃļnnen wahrscheinlich mit der rechten Maustaste auf jeden Link klicken und Und **ReDoc** verwendet diese Datei: -* `redoc.standalone.js` +* `redoc.standalone.js` Danach kÃļnnte Ihre Dateistruktur wie folgt aussehen: @@ -129,14 +129,8 @@ Sie sollten eine sehr lange JavaScript-Datei fÃŧr **ReDoc** sehen. Sie kÃļnnte beginnen mit etwas wie: ```JavaScript -/*! - * ReDoc - OpenAPI/Swagger-generated API Reference Documentation - * ------------------------------------------------------------- - * Version: "2.0.0-rc.18" - * Repo: https://github.com/Redocly/redoc - */ -!function(e,t){"object"==typeof exports&&"object"==typeof m - +/*! For license information please see redoc.standalone.js.LICENSE.txt */ +!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("null")): ... ``` diff --git a/docs/de/docs/index.md b/docs/de/docs/index.md index 411c8e969..d239f0815 100644 --- a/docs/de/docs/index.md +++ b/docs/de/docs/index.md @@ -12,7 +12,7 @@

- Test + Test Coverage diff --git a/docs/de/docs/tutorial/bigger-applications.md b/docs/de/docs/tutorial/bigger-applications.md index 59e91bdcc..514e3fd3a 100644 --- a/docs/de/docs/tutorial/bigger-applications.md +++ b/docs/de/docs/tutorial/bigger-applications.md @@ -52,7 +52,7 @@ from app.routers import items * Es gibt auch ein Unterverzeichnis `app/internal/` mit einer weiteren Datei `__init__.py`, es handelt sich also um ein weiteres „Python-Subpackage“: `app.internal`. * Und die Datei `app/internal/admin.py` ist ein weiteres Submodul: `app.internal.admin`. - + Die gleiche Dateistruktur mit Kommentaren: @@ -270,7 +270,7 @@ Aber diese Datei existiert nicht, unsere Abhängigkeiten befinden sich in einer Erinnern Sie sich, wie unsere Anwendungs-/Dateistruktur aussieht: - + --- diff --git a/docs/de/docs/tutorial/query-params-str-validations.md b/docs/de/docs/tutorial/query-params-str-validations.md index f181d501c..de8879ce8 100644 --- a/docs/de/docs/tutorial/query-params-str-validations.md +++ b/docs/de/docs/tutorial/query-params-str-validations.md @@ -315,22 +315,6 @@ Wenn Sie einen Parameter erforderlich machen wollen, während Sie `Query` verwen {* ../../docs_src/query_params_str_validations/tutorial006_an_py39.py hl[9] *} -### Erforderlich mit Ellipse (`...`) - -Es gibt eine Alternative, die explizit deklariert, dass ein Wert erforderlich ist. Sie kÃļnnen als Default das Literal `...` setzen: - -{* ../../docs_src/query_params_str_validations/tutorial006b_an_py39.py hl[9] *} - -/// info - -Falls Sie das `...` bisher noch nicht gesehen haben: Es ist ein spezieller einzelner Wert, Teil von Python und wird „Ellipsis“ genannt (Deutsch: Ellipse). - -Es wird von Pydantic und FastAPI verwendet, um explizit zu deklarieren, dass ein Wert erforderlich ist. - -/// - -Dies wird **FastAPI** wissen lassen, dass dieser Parameter erforderlich ist. - ### Erforderlich, kann `None` sein Sie kÃļnnen deklarieren, dass ein Parameter `None` akzeptiert, aber dennoch erforderlich ist. Das zwingt Clients, den Wert zu senden, selbst wenn er `None` ist. diff --git a/docs/em/docs/deployment/concepts.md b/docs/em/docs/deployment/concepts.md index 019703296..bbb017277 100644 --- a/docs/em/docs/deployment/concepts.md +++ b/docs/em/docs/deployment/concepts.md @@ -216,7 +216,7 @@ 👈 👨‍🏭 đŸ› ī¸ 🔜 🕐 🏃‍♂ 👆 🈸, đŸ‘Ģ 🔜 🎭 👑 📊 📨 **📨** & 📨 **📨**, & đŸ‘Ģ 🔜 📐 đŸ•ŗ 👆 🚮 đŸ”ĸ 💾. - + & â†—ī¸, 🎏 🎰 🔜 🎲 âœ”ī¸ **🎏 đŸ› ī¸** 🏃 👍, â†–ī¸ âšĒī¸âžĄī¸ 👆 🈸. diff --git a/docs/em/docs/deployment/https.md b/docs/em/docs/deployment/https.md index 31cf99001..6d2641a92 100644 --- a/docs/em/docs/deployment/https.md +++ b/docs/em/docs/deployment/https.md @@ -85,7 +85,7 @@ 🏓 đŸ’Ŋ 🔜 đŸ’Ŧ đŸ–Ĩ âš™ī¸ đŸŽ¯ **đŸ“ĸ đŸ“ĸ**. 👈 🔜 đŸ“ĸ đŸ“ĸ đŸ“ĸ âš™ī¸ 👆 đŸ’Ŋ, 👈 👆 🔗 🏓 đŸ’Ŋ. - + ### 🤝 🤝 â–ļī¸ @@ -93,7 +93,7 @@ đŸĨ‡ 🍕 đŸ“ģ đŸ› ī¸ 🔗 🖖 👩‍đŸ’ģ & đŸ’Ŋ & 💭 🔐 🔑 đŸ‘Ģ 🔜 âš™ī¸, â™’ī¸. - + 👉 🔗 🖖 👩‍đŸ’ģ & đŸ’Ŋ đŸ› ī¸ 🤝 🔗 🤙 **🤝 🤝**. @@ -111,7 +111,7 @@ 👉 đŸ’ŧ, âšĢī¸ 🔜 âš™ī¸ 📄 `someapp.example.com`. - + 👩‍đŸ’ģ âĒ **💙** 👨‍đŸ’ŧ 👈 🏗 👈 🤝 📄 (👉 đŸ’ŧ âžĄī¸ 🗜, âœ‹ī¸ đŸ‘Ĩ 🔜 👀 🔃 👈 âĒ), âšĢī¸ đŸ’Ē **✔** 👈 📄 ☑. @@ -133,19 +133,19 @@ , 👩‍đŸ’ģ 📨 **đŸ‡ē🇸🔍 📨**. 👉 đŸ‡ē🇸🔍 📨 🔘 🗜 🤝 🔗. - + ### 🗜 📨 🤝 ❎ đŸ—ŗ 🔜 âš™ī¸ 🔐 ✔ **🗜 📨**, & 🔜 đŸ“ļ **✅ (🗜) đŸ‡ē🇸🔍 📨** đŸ› ī¸ 🏃 🈸 (đŸ–ŧ đŸ› ī¸ âŽī¸ Uvicorn 🏃‍♂ FastAPI 🈸). - + ### đŸ‡ē🇸🔍 📨 🈸 🔜 đŸ› ī¸ 📨 & 📨 **✅ (đŸ’Ŋ) đŸ‡ē🇸🔍 📨** 🤝 ❎ đŸ—ŗ. - + ### đŸ‡ē🇸🔍 📨 @@ -153,7 +153,7 @@ ⏭, đŸ–Ĩ 🔜 ✔ 👈 📨 ☑ & 🗜 âŽī¸ â–ļī¸ī¸ 🔐 🔑, â™’ī¸. âšĢī¸ 🔜 â¤´ī¸ **🗜 📨** & đŸ› ī¸ âšĢī¸. - + 👩‍đŸ’ģ (đŸ–Ĩ) 🔜 💭 👈 📨 👟 âšĒī¸âžĄī¸ ☑ đŸ’Ŋ â†Šī¸ âšĢī¸ âš™ī¸ ⚛ đŸ‘Ģ ✔ âš™ī¸ **đŸ‡ē🇸🔍 📄** ⏭. @@ -163,7 +163,7 @@ 🕴 1ī¸âƒŖ đŸ› ī¸ đŸ’Ē 🚚 đŸŽ¯ đŸ“ĸ & ⛴ (🤝 ❎ đŸ—ŗ 👆 đŸ–ŧ) âœ‹ī¸ 🎏 🈸/đŸ› ī¸ đŸ’Ē 🏃 🔛 đŸ’Ŋ(Ⓜ) đŸ’â€â™‚ī¸, 📏 đŸ‘Ģ đŸšĢ 🔄 âš™ī¸ 🎏 **🌀 đŸ“ĸ đŸ“ĸ & ⛴**. - + 👈 🌌, 🤝 ❎ đŸ—ŗ đŸ’Ē đŸĩ đŸ‡ē🇸🔍 & 📄 **💗 🆔**, 💗 🈸, & â¤´ī¸ đŸ“ļ 📨 â–ļī¸ī¸ 🈸 🔠 đŸ’ŧ. @@ -173,7 +173,7 @@ & â¤´ī¸, 📤 🔜 ➕1ī¸âƒŖ 📋 (đŸ’ŧ âšĢī¸ ➕1ī¸âƒŖ 📋, đŸ’ŧ âšĢī¸ đŸ’Ē 🎏 🤝 ❎ đŸ—ŗ) 👈 🔜 đŸ’Ŧ âžĄī¸ 🗜, & â™ģ 📄(Ⓜ). - + **🤝 📄** **🔗 âŽī¸ 🆔 📛**, đŸšĢ âŽī¸ đŸ“ĸ đŸ“ĸ. diff --git a/docs/em/docs/index.md b/docs/em/docs/index.md index 16b2019d3..57be59b07 100644 --- a/docs/em/docs/index.md +++ b/docs/em/docs/index.md @@ -12,7 +12,7 @@

- Test + Test Coverage diff --git a/docs/em/docs/tutorial/bigger-applications.md b/docs/em/docs/tutorial/bigger-applications.md index 68f506f27..78a321ae6 100644 --- a/docs/em/docs/tutorial/bigger-applications.md +++ b/docs/em/docs/tutorial/bigger-applications.md @@ -52,7 +52,7 @@ from app.routers import items * 📤 📁 `app/internal/` âŽī¸ ➕1ī¸âƒŖ 📁 `__init__.py`, âšĢī¸ ➕1ī¸âƒŖ "🐍 đŸ“Ļ": `app.internal`. * & 📁 `app/internal/admin.py` ➕1ī¸âƒŖ 🔁: `app.internal.admin`. - + 🎏 📁 📊 âŽī¸ 🏤: @@ -244,7 +244,7 @@ from .dependencies import get_token_header 💭 ❔ 👆 📱/📁 📊 👀 💖: - + --- diff --git a/docs/em/docs/tutorial/query-params-str-validations.md b/docs/em/docs/tutorial/query-params-str-validations.md index dbaab5735..fd077bf8f 100644 --- a/docs/em/docs/tutorial/query-params-str-validations.md +++ b/docs/em/docs/tutorial/query-params-str-validations.md @@ -148,22 +148,6 @@ q: Union[str, None] = Query(default=None, min_length=3) {* ../../docs_src/query_params_str_validations/tutorial006.py hl[7] *} -### ✔ âŽī¸ ❕ (`...`) - -📤 🎛 🌌 đŸŽ¯ đŸ“Ŗ 👈 💲 ✔. 👆 đŸ’Ē ⚒ `default` đŸ”ĸ 🔑 💲 `...`: - -{* ../../docs_src/query_params_str_validations/tutorial006b.py hl[7] *} - -/// info - -đŸšĨ 👆 đŸšĢ 👀 👈 `...` ⏭: âšĢī¸ 🎁 👁 💲, âšĢī¸ 🍕 🐍 & 🤙 "❕". - -âšĢī¸ âš™ī¸ Pydantic & FastAPI đŸŽ¯ đŸ“Ŗ 👈 💲 ✔. - -/// - -👉 🔜 âžĄī¸ **FastAPI** 💭 👈 👉 đŸ”ĸ ✔. - ### ✔ âŽī¸ `None` 👆 đŸ’Ē đŸ“Ŗ 👈 đŸ”ĸ đŸ’Ē đŸšĢ `None`, âœ‹ī¸ 👈 âšĢī¸ ✔. 👉 🔜 ⚡ 👩‍đŸ’ģ 📨 💲, đŸšĨ 💲 `None`. @@ -178,18 +162,6 @@ Pydantic, ❔ âšĢī¸â” đŸ‹ī¸ 🌐 đŸ’Ŋ đŸ”Ŧ & đŸ› ī¸ FastAPI, âœ”ī¸ /// -### âš™ī¸ Pydantic `Required` â†Šī¸ ❕ (`...`) - -đŸšĨ 👆 💭 đŸ˜Ŧ âš™ī¸ `...`, 👆 đŸ’Ē 🗄 & âš™ī¸ `Required` âšĒī¸âžĄī¸ Pydantic: - -{* ../../docs_src/query_params_str_validations/tutorial006d.py hl[2,8] *} - -/// tip - -💭 👈 🌅 đŸ’ŧ, 🕐❔ đŸ•ŗ 🚚, 👆 đŸ’Ē đŸŽ¯ đŸšĢ `default` đŸ”ĸ, 👆 🛎 đŸšĢ âœ”ī¸ âš™ī¸ `...` đŸšĢ `Required`. - -/// - ## đŸ”ĸ đŸ”ĸ 📇 / 💗 💲 🕐❔ 👆 đŸ”Ŧ đŸ”ĸ đŸ”ĸ đŸŽ¯ âŽī¸ `Query` 👆 đŸ’Ē đŸ“Ŗ âšĢī¸ 📨 📇 💲, âš–ī¸ 🙆‍♀ 🎏 🌌, 📨 💗 💲. diff --git a/docs/en/data/contributors.yml b/docs/en/data/contributors.yml index f679d7286..05ff0c7d4 100644 --- a/docs/en/data/contributors.yml +++ b/docs/en/data/contributors.yml @@ -1,13 +1,23 @@ tiangolo: login: tiangolo - count: 697 + count: 768 avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 url: https://github.com/tiangolo dependabot: login: dependabot - count: 89 + count: 106 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 + url: https://github.com/alejsdev +pre-commit-ci: + login: pre-commit-ci + count: 37 + avatarUrl: https://avatars.githubusercontent.com/in/68672?v=4 + url: https://github.com/apps/pre-commit-ci github-actions: login: github-actions count: 26 @@ -15,19 +25,9 @@ github-actions: url: https://github.com/apps/github-actions Kludex: login: Kludex - count: 22 + count: 23 avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=df8a3f06ba8f55ae1967a3e2d5ed882903a4e330&v=4 url: https://github.com/Kludex -pre-commit-ci: - login: pre-commit-ci - count: 22 - avatarUrl: https://avatars.githubusercontent.com/in/68672?v=4 - url: https://github.com/apps/pre-commit-ci -alejsdev: - login: alejsdev - count: 21 - avatarUrl: https://avatars.githubusercontent.com/u/90076947?u=356f39ff3f0211c720b06d3dbb060e98884085e3&v=4 - url: https://github.com/alejsdev dmontagu: login: dmontagu count: 17 @@ -68,6 +68,11 @@ 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 @@ -88,16 +93,16 @@ waynerv: count: 5 avatarUrl: https://avatars.githubusercontent.com/u/39515546?u=ec35139777597cdbbbddda29bf8b9d4396b429a9&v=4 url: https://github.com/waynerv -svlandeg: - login: svlandeg - count: 5 - avatarUrl: https://avatars.githubusercontent.com/u/8796347?u=556c97650c27021911b0b9447ec55e75987b0e8a&v=4 - url: https://github.com/svlandeg krishnamadhavan: login: 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 @@ -108,6 +113,11 @@ hitrust: count: 4 avatarUrl: https://avatars.githubusercontent.com/u/3360631?u=5fa1f475ad784d64eb9666bdd43cc4d285dcc773&v=4 url: https://github.com/hitrust +ShahriyarR: + login: ShahriyarR + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/3852029?u=631b2ae59360ab380c524b32bc3d245aff1165af&v=4 + url: https://github.com/ShahriyarR adriangb: login: adriangb count: 4 @@ -116,7 +126,7 @@ adriangb: iudeen: login: iudeen count: 4 - avatarUrl: https://avatars.githubusercontent.com/u/10519440?u=2843b3303282bff8b212dcd4d9d6689452e4470c&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/10519440?u=f09cdd745e5bf16138f29b42732dd57c7f02bee1&v=4 url: https://github.com/iudeen philipokiokio: login: philipokiokio @@ -128,6 +138,11 @@ AlexWendland: count: 4 avatarUrl: https://avatars.githubusercontent.com/u/3949212?u=c4c0c615e0ea33d00bfe16b779cf6ebc0f58071c&v=4 url: https://github.com/AlexWendland +YuriiMotov: + login: YuriiMotov + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=b9b13d598dddfab529a52d264df80a900bfe7060&v=4 + url: https://github.com/YuriiMotov divums: login: divums count: 3 @@ -161,7 +176,7 @@ hukkin: marcosmmb: login: marcosmmb count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/6181089?u=b8567a842b38c5570c315b2b7ca766fa7be6721e&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/6181089?u=03c50eec631857d84df5232890780d00a3f76903&v=4 url: https://github.com/marcosmmb Serrones: login: Serrones @@ -173,11 +188,11 @@ uriyyo: count: 3 avatarUrl: https://avatars.githubusercontent.com/u/32038156?u=a27b65a9ec3420586a827a0facccbb8b6df1ffb3&v=4 url: https://github.com/uriyyo -amacfie: - login: amacfie +andrew222651: + login: andrew222651 count: 3 avatarUrl: https://avatars.githubusercontent.com/u/889657?u=d70187989940b085bcbfa3bedad8dbc5f3ab1fe7&v=4 - url: https://github.com/amacfie + url: https://github.com/andrew222651 rkbeatss: login: rkbeatss count: 3 @@ -206,13 +221,8 @@ TeoZosa: graingert: login: graingert count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/413772?u=64b77b6aa405c68a9c6bcf45f84257c66eea5f32&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/413772?v=4 url: https://github.com/graingert -ShahriyarR: - login: ShahriyarR - count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/3852029?u=c9a1691e5ebdc94cbf543086099a6ed705cdb873&v=4 - url: https://github.com/ShahriyarR jaystone776: login: jaystone776 count: 3 @@ -233,6 +243,11 @@ papb: count: 3 avatarUrl: https://avatars.githubusercontent.com/u/20914054?u=890511fae7ea90d887e2a65ce44a1775abba38d5&v=4 url: https://github.com/papb +musicinmybrain: + login: musicinmybrain + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/6898909?u=9010312053e7141383b9bdf538036c7f37fbaba0&v=4 + url: https://github.com/musicinmybrain gitworkflows: login: gitworkflows count: 3 @@ -301,7 +316,7 @@ dconathan: Jamim: login: Jamim count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/5607572?u=0cf3027bec78ba4f0b89802430c136bc69847d7a&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/5607572?u=9ce0b6a6d1a5124e28b3c04d8d26827ca328713a&v=4 url: https://github.com/Jamim svalouch: login: svalouch @@ -356,7 +371,7 @@ sattosan: michaeloliverx: login: michaeloliverx count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/55017335?u=e606eb5cc397c07523be47637b1ee796904fbb59&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/55017335?u=efb0cb6e261ff64d862fafb91ee80fc2e1f8a2ed&v=4 url: https://github.com/michaeloliverx voegtlel: login: voegtlel @@ -411,7 +426,7 @@ davidefiocco: adriencaccia: login: adriencaccia count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/19605940?u=980b0b366a02791a5600b2e9f9ac2037679acaa8&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/19605940?u=9a59081f46bfc9d839886a49d5092cf572879049&v=4 url: https://github.com/adriencaccia jamescurtin: login: jamescurtin @@ -433,6 +448,11 @@ imba-tjd: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/24759802?u=01e901a4fe004b4b126549d3ff1c4000fe3720b5&v=4 url: https://github.com/imba-tjd +johnthagen: + login: johnthagen + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/10340167?u=47147fc4e4db1f573bee3fe428deeacb3197bc5f&v=4 + url: https://github.com/johnthagen paxcodes: login: paxcodes count: 2 @@ -443,6 +463,11 @@ kaustubhgupta: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/43691873?u=8dd738718ac7ffad4ef31e86b5d780a1141c695d&v=4 url: https://github.com/kaustubhgupta +kinuax: + login: kinuax + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/13321374?u=22dc9873d6d9f2c7e4fc44c6480c3505efb1531f&v=4 + url: https://github.com/kinuax wakabame: login: wakabame count: 2 @@ -458,11 +483,6 @@ yezz123: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/52716203?u=d7062cbc6eb7671d5dc9cc0e32a24ae335e0f225&v=4 url: https://github.com/yezz123 -musicinmybrain: - login: musicinmybrain - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/6898909?u=9010312053e7141383b9bdf538036c7f37fbaba0&v=4 - url: https://github.com/musicinmybrain softwarebloat: login: softwarebloat count: 2 @@ -473,6 +493,11 @@ Lancetnik: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/44573917?u=f9a18be7324333daf9cc314c35c3051f0a20a7a6&v=4 url: https://github.com/Lancetnik +joakimnordling: + login: joakimnordling + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/6637576?u=df5d99db9b899b399effd429f4358baaa6f7199c&v=4 + url: https://github.com/joakimnordling yogabonito: login: yogabonito count: 2 @@ -493,6 +518,11 @@ tamird: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/1535036?v=4 url: https://github.com/tamird +ndimares: + login: ndimares + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/6267663?u=cfb27efde7a7212be8142abb6c058a1aeadb41b1&v=4 + url: https://github.com/ndimares rabinlamadong: login: rabinlamadong count: 2 @@ -503,3 +533,28 @@ AyushSinghal1794: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/89984761?v=4 url: https://github.com/AyushSinghal1794 +gsheni: + login: gsheni + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/8726321?u=ee3bd9ff6320f4715d1dd9671a3d55cccb65b984&v=4 + url: https://github.com/gsheni +DanielKusyDev: + login: DanielKusyDev + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/36250676?u=2ea6114ff751fc48b55f231987a0e2582c6b1bd2&v=4 + url: https://github.com/DanielKusyDev +DanielYang59: + login: DanielYang59 + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/80093591?u=63873f701c7c74aac83c906800a1dddc0bc8c92f&v=4 + url: https://github.com/DanielYang59 +valentinDruzhinin: + login: valentinDruzhinin + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/12831905?u=aae1ebc675c91e8fa582df4fcc4fc4128106344d&v=4 + url: https://github.com/valentinDruzhinin +blueswen: + login: blueswen + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/1564148?u=6d6b8cc8f2b5cef715e68d6175154a8a94d518ee&v=4 + url: https://github.com/blueswen diff --git a/docs/en/data/external_links.yml b/docs/en/data/external_links.yml index 9e411a631..50f84ecbf 100644 --- a/docs/en/data/external_links.yml +++ b/docs/en/data/external_links.yml @@ -411,3 +411,8 @@ Talks: author_link: https://twitter.com/chriswithers13 link: https://www.youtube.com/watch?v=3DLwPcrE5mA title: 'PyCon UK 2019: FastAPI from the ground up' + Taiwanese: + - author: Blueswen + author_link: https://github.com/blueswen + link: https://www.youtube.com/watch?v=y3sumuoDq4w + title: 'PyCon TW 2024: 全斚äŊåŧˇåŒ– Python æœå‹™å¯č§€æ¸Ŧ性īŧšäģĨ FastAPI 和 Grafana Stack į‚ē例' diff --git a/docs/en/data/github_sponsors.yml b/docs/en/data/github_sponsors.yml index 55fe3dda9..778ec6a95 100644 --- a/docs/en/data/github_sponsors.yml +++ b/docs/en/data/github_sponsors.yml @@ -1,38 +1,38 @@ sponsors: -- - login: bump-sh - avatarUrl: https://avatars.githubusercontent.com/u/33217836?v=4 - url: https://github.com/bump-sh - - login: Nixtla - avatarUrl: https://avatars.githubusercontent.com/u/79945230?v=4 - url: https://github.com/Nixtla +- - login: renderinc + avatarUrl: https://avatars.githubusercontent.com/u/36424661?v=4 + url: https://github.com/renderinc - login: andrew-propelauth - avatarUrl: https://avatars.githubusercontent.com/u/89474256?u=1188c27cb744bbec36447a2cfd4453126b2ddb5c&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/89474256?u=c98993dec8553c09d424ede67bbe86e5c35f48c9&v=4 url: https://github.com/andrew-propelauth - - login: liblaber - avatarUrl: https://avatars.githubusercontent.com/u/100821118?v=4 - url: https://github.com/liblaber - - login: zanfaruqui - avatarUrl: https://avatars.githubusercontent.com/u/104461687?v=4 - url: https://github.com/zanfaruqui - login: blockbee-io avatarUrl: https://avatars.githubusercontent.com/u/115143449?u=1b8620c2d6567c4df2111a371b85a51f448f9b85&v=4 url: https://github.com/blockbee-io - login: zuplo avatarUrl: https://avatars.githubusercontent.com/u/85497839?v=4 url: https://github.com/zuplo - - login: render-sponsorships - avatarUrl: https://avatars.githubusercontent.com/u/189296666?v=4 - url: https://github.com/render-sponsorships - - login: porter-dev - avatarUrl: https://avatars.githubusercontent.com/u/62078005?v=4 - url: https://github.com/porter-dev + - login: coderabbitai + avatarUrl: https://avatars.githubusercontent.com/u/132028505?v=4 + url: https://github.com/coderabbitai + - login: madisonredtfeldt + avatarUrl: https://avatars.githubusercontent.com/u/152656511?v=4 + url: https://github.com/madisonredtfeldt + - login: subtotal + avatarUrl: https://avatars.githubusercontent.com/u/176449348?v=4 + url: https://github.com/subtotal + - login: railwayapp + avatarUrl: https://avatars.githubusercontent.com/u/66716858?v=4 + url: https://github.com/railwayapp + - login: Nixtla + avatarUrl: https://avatars.githubusercontent.com/u/79945230?v=4 + url: https://github.com/Nixtla - login: scalar avatarUrl: https://avatars.githubusercontent.com/u/301879?v=4 url: https://github.com/scalar -- - login: ObliviousAI - avatarUrl: https://avatars.githubusercontent.com/u/65656077?v=4 - url: https://github.com/ObliviousAI -- - login: svix +- - login: dribia + avatarUrl: https://avatars.githubusercontent.com/u/41189616?v=4 + url: https://github.com/dribia + - login: svix avatarUrl: https://avatars.githubusercontent.com/u/80175132?v=4 url: https://github.com/svix - login: stainless-api @@ -44,18 +44,21 @@ sponsors: - login: databento avatarUrl: https://avatars.githubusercontent.com/u/64141749?v=4 url: https://github.com/databento -- - login: mercedes-benz - avatarUrl: https://avatars.githubusercontent.com/u/34240465?v=4 - url: https://github.com/mercedes-benz - - login: xoflare - avatarUrl: https://avatars.githubusercontent.com/u/74335107?v=4 - url: https://github.com/xoflare - - login: marvin-robot + - login: permitio + avatarUrl: https://avatars.githubusercontent.com/u/71775833?v=4 + url: https://github.com/permitio +- - login: marvin-robot avatarUrl: https://avatars.githubusercontent.com/u/41086007?u=b9fcab402d0cd0aec738b6574fe60855cb0cd36d&v=4 url: https://github.com/marvin-robot + - login: mercedes-benz + avatarUrl: https://avatars.githubusercontent.com/u/34240465?v=4 + url: https://github.com/mercedes-benz - login: Ponte-Energy-Partners avatarUrl: https://avatars.githubusercontent.com/u/114745848?v=4 url: https://github.com/Ponte-Energy-Partners + - login: LambdaTest-Inc + avatarUrl: https://avatars.githubusercontent.com/u/171592363?u=96606606a45fa170427206199014f2a5a2a4920b&v=4 + url: https://github.com/LambdaTest-Inc - login: BoostryJP avatarUrl: https://avatars.githubusercontent.com/u/57932412?v=4 url: https://github.com/BoostryJP @@ -68,68 +71,44 @@ sponsors: - - login: takashi-yoneya avatarUrl: https://avatars.githubusercontent.com/u/33813153?u=2d0522bceba0b8b69adf1f2db866503bd96f944e&v=4 url: https://github.com/takashi-yoneya + - login: Doist + avatarUrl: https://avatars.githubusercontent.com/u/2565372?v=4 + url: https://github.com/Doist - - login: mainframeindustries avatarUrl: https://avatars.githubusercontent.com/u/55092103?v=4 url: https://github.com/mainframeindustries - - login: CanoaPBC - avatarUrl: https://avatars.githubusercontent.com/u/64223768?v=4 - url: https://github.com/CanoaPBC - login: yasyf avatarUrl: https://avatars.githubusercontent.com/u/709645?u=f36736b3c6a85f578886ecc42a740e7b436e7a01&v=4 url: https://github.com/yasyf -- - login: genzou9201 - avatarUrl: https://avatars.githubusercontent.com/u/42960762?u=1ca6c18c59e8b327ae584c545b72de31ebc05275&v=4 - url: https://github.com/genzou9201 +- - login: alixlahuec + avatarUrl: https://avatars.githubusercontent.com/u/29543316?u=44357eb2a93bccf30fb9d389b8befe94a3d00985&v=4 + url: https://github.com/alixlahuec - - login: primer-io avatarUrl: https://avatars.githubusercontent.com/u/62146168?v=4 url: https://github.com/primer-io - - login: povilasb - avatarUrl: https://avatars.githubusercontent.com/u/1213442?u=b11f58ed6ceea6e8297c9b310030478ebdac894d&v=4 - url: https://github.com/povilasb - - login: upciti avatarUrl: https://avatars.githubusercontent.com/u/43346262?v=4 url: https://github.com/upciti - - login: freddiev4 - avatarUrl: https://avatars.githubusercontent.com/u/8339018?u=1aad5b4f5a04cb750852b843d5e1d8f4ce339c2e&v=4 - url: https://github.com/freddiev4 - - 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=cbf098fc04c0473523d373b0dd2145b4ec99ef93&v=4 - url: https://github.com/vincentkoc - - login: ProteinQure - avatarUrl: https://avatars.githubusercontent.com/u/33707203?v=4 - url: https://github.com/ProteinQure - - login: ddilidili - avatarUrl: https://avatars.githubusercontent.com/u/42176885?u=c0a849dde06987434653197b5f638d3deb55fc6c&v=4 - url: https://github.com/ddilidili - login: otosky avatarUrl: https://avatars.githubusercontent.com/u/42260747?u=69d089387c743d89427aa4ad8740cfb34045a9e0&v=4 url: https://github.com/otosky - - login: mjohnsey - avatarUrl: https://avatars.githubusercontent.com/u/16784016?u=38fad2e6b411244560b3af99c5f5a4751bc81865&v=4 - url: https://github.com/mjohnsey - - login: ashi-agrawal - avatarUrl: https://avatars.githubusercontent.com/u/17105294?u=99c7a854035e5398d8e7b674f2d42baae6c957f8&v=4 - url: https://github.com/ashi-agrawal - - login: sepsi77 - avatarUrl: https://avatars.githubusercontent.com/u/18682303?v=4 - url: https://github.com/sepsi77 - - login: RaamEEIL - avatarUrl: https://avatars.githubusercontent.com/u/20320552?v=4 - url: https://github.com/RaamEEIL - - login: jhundman - avatarUrl: https://avatars.githubusercontent.com/u/24263908?v=4 - url: https://github.com/jhundman - - login: b-rad-c - avatarUrl: https://avatars.githubusercontent.com/u/25362581?u=5bb10629f4015b62bec1f9a366675d5085551af9&v=4 - url: https://github.com/b-rad-c + - login: ramonalmeidam + avatarUrl: https://avatars.githubusercontent.com/u/45269580?u=3358750b3a5854d7c3ed77aaca7dd20a0f529d32&v=4 + url: https://github.com/ramonalmeidam + - login: roboflow + avatarUrl: https://avatars.githubusercontent.com/u/53104118?v=4 + url: https://github.com/roboflow + - login: dudikbender + avatarUrl: https://avatars.githubusercontent.com/u/53487583?u=3a57542938ebfd57579a0111db2b297e606d9681&v=4 + url: https://github.com/dudikbender - login: ehaca avatarUrl: https://avatars.githubusercontent.com/u/25950317?u=cec1a3e0643b785288ae8260cc295a85ab344995&v=4 url: https://github.com/ehaca - login: raphaellaude - avatarUrl: https://avatars.githubusercontent.com/u/28026311?u=28faad3e62250ef91a0c3c5d0faba39592d9ab39&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/28026311?u=91e1c00d9ac4f8045527e13de8050d504531cbc0&v=4 url: https://github.com/raphaellaude - login: timlrx avatarUrl: https://avatars.githubusercontent.com/u/28362229?u=9a745ca31372ee324af682715ae88ce8522f9094&v=4 @@ -137,12 +116,9 @@ sponsors: - login: Leay15 avatarUrl: https://avatars.githubusercontent.com/u/32212558?u=c4aa9c1737e515959382a5515381757b1fd86c53&v=4 url: https://github.com/Leay15 - - login: ygorpontelo - avatarUrl: https://avatars.githubusercontent.com/u/32963605?u=35f7103f9c4c4c2589ae5737ee882e9375ef072e&v=4 - url: https://github.com/ygorpontelo - - login: chickenandstats - avatarUrl: https://avatars.githubusercontent.com/u/79477966?v=4 - url: https://github.com/chickenandstats + - login: ProteinQure + avatarUrl: https://avatars.githubusercontent.com/u/33707203?v=4 + url: https://github.com/ProteinQure - login: kaoru0310 avatarUrl: https://avatars.githubusercontent.com/u/80977929?u=1b61d10142b490e56af932ddf08a390fae8ee94f&v=4 url: https://github.com/kaoru0310 @@ -152,27 +128,12 @@ sponsors: - login: Karine-Bauch avatarUrl: https://avatars.githubusercontent.com/u/90465103?u=7feb1018abb1a5631cfd9a91fea723d1ceb5f49b&v=4 url: https://github.com/Karine-Bauch - - login: eruditis - avatarUrl: https://avatars.githubusercontent.com/u/95244703?v=4 - url: https://github.com/eruditis - login: jugeeem avatarUrl: https://avatars.githubusercontent.com/u/116043716?u=ae590d79c38ac79c91b9c5caa6887d061e865a3d&v=4 url: https://github.com/jugeeem - login: logic-automation avatarUrl: https://avatars.githubusercontent.com/u/144732884?v=4 url: https://github.com/logic-automation - - login: Torqsight-Labs - avatarUrl: https://avatars.githubusercontent.com/u/169598176?v=4 - url: https://github.com/Torqsight-Labs - - login: ramonalmeidam - avatarUrl: https://avatars.githubusercontent.com/u/45269580?u=3358750b3a5854d7c3ed77aaca7dd20a0f529d32&v=4 - url: https://github.com/ramonalmeidam - - login: roboflow - avatarUrl: https://avatars.githubusercontent.com/u/53104118?v=4 - url: https://github.com/roboflow - - login: dudikbender - avatarUrl: https://avatars.githubusercontent.com/u/53487583?u=3a57542938ebfd57579a0111db2b297e606d9681&v=4 - url: https://github.com/dudikbender - login: patsatsia avatarUrl: https://avatars.githubusercontent.com/u/61111267?u=3271b85f7a37b479c8d0ae0a235182e83c166edf&v=4 url: https://github.com/patsatsia @@ -182,12 +143,9 @@ sponsors: - login: patricioperezv avatarUrl: https://avatars.githubusercontent.com/u/73832292?u=5f471f156e19ee7920e62ae0f4a47b95580e61cf&v=4 url: https://github.com/patricioperezv - - login: mintuhouse - avatarUrl: https://avatars.githubusercontent.com/u/769950?u=ecfbd79a97d33177e0d093ddb088283cf7fe8444&v=4 - url: https://github.com/mintuhouse - - login: tcsmith - avatarUrl: https://avatars.githubusercontent.com/u/989034?u=7d8d741552b3279e8f4d3878679823a705a46f8f&v=4 - url: https://github.com/tcsmith + - 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 @@ -197,9 +155,6 @@ sponsors: - login: knallgelb avatarUrl: https://avatars.githubusercontent.com/u/2358812?u=c48cb6362b309d74cbf144bd6ad3aed3eb443e82&v=4 url: https://github.com/knallgelb - - login: Shark009 - avatarUrl: https://avatars.githubusercontent.com/u/3163309?u=0c6f4091b0eda05c44c390466199826e6dc6e431&v=4 - url: https://github.com/Shark009 - login: dblackrun avatarUrl: https://avatars.githubusercontent.com/u/3528486?v=4 url: https://github.com/dblackrun @@ -215,6 +170,21 @@ sponsors: - login: anomaly avatarUrl: https://avatars.githubusercontent.com/u/3654837?v=4 url: https://github.com/anomaly + - login: mj0331 + avatarUrl: https://avatars.githubusercontent.com/u/3890353?u=1c627ac1a024515b4871de5c3ebbfaa1a57f65d4&v=4 + url: https://github.com/mj0331 + - login: gorhack + avatarUrl: https://avatars.githubusercontent.com/u/4141690?u=ec119ebc4bdf00a7bc84657a71aa17834f4f27f3&v=4 + url: https://github.com/gorhack + - 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 @@ -230,30 +200,21 @@ sponsors: - login: pamelafox avatarUrl: https://avatars.githubusercontent.com/u/297042?v=4 url: https://github.com/pamelafox - - login: ericof - avatarUrl: https://avatars.githubusercontent.com/u/306014?u=cf7c8733620397e6584a451505581c01c5d842d7&v=4 - url: https://github.com/ericof - login: wshayes avatarUrl: https://avatars.githubusercontent.com/u/365303?u=07ca03c5ee811eb0920e633cc3c3db73dbec1aa5&v=4 url: https://github.com/wshayes - - login: gaetanBloch - avatarUrl: https://avatars.githubusercontent.com/u/583199?u=50c49e83d6b4feb78a091901ea02ead1462f442b&v=4 - url: https://github.com/gaetanBloch - login: koxudaxi avatarUrl: https://avatars.githubusercontent.com/u/630670?u=507d8577b4b3670546b449c4c2ccbc5af40d72f7&v=4 url: https://github.com/koxudaxi - login: falkben avatarUrl: https://avatars.githubusercontent.com/u/653031?u=ad9838e089058c9e5a0bab94c0eec7cc181e0cd0&v=4 url: https://github.com/falkben - - login: TrevorBenson - avatarUrl: https://avatars.githubusercontent.com/u/9167887?u=dccbea3327a57750923333d8ebf1a0b3f1948949&v=4 - url: https://github.com/TrevorBenson + - login: mintuhouse + avatarUrl: https://avatars.githubusercontent.com/u/769950?u=ecfbd79a97d33177e0d093ddb088283cf7fe8444&v=4 + url: https://github.com/mintuhouse - login: wdwinslow - avatarUrl: https://avatars.githubusercontent.com/u/11562137?u=dc01daafb354135603a263729e3d26d939c0c452&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/11562137?u=371272f2c69e680e0559a7b0a57385e83a5dc728&v=4 url: https://github.com/wdwinslow - - login: catherinenelson1 - avatarUrl: https://avatars.githubusercontent.com/u/11951946?u=fe11bc35d36b6038cd46a946e4e46ef8aa5688ab&v=4 - url: https://github.com/catherinenelson1 - login: jsoques avatarUrl: https://avatars.githubusercontent.com/u/12414216?u=620921d94196546cc8b9eae2cc4cbc3f95bab42f&v=4 url: https://github.com/jsoques @@ -266,18 +227,18 @@ sponsors: - login: khadrawy avatarUrl: https://avatars.githubusercontent.com/u/13686061?u=59f25ef42ecf04c22657aac4238ce0e2d3d30304&v=4 url: https://github.com/khadrawy - - login: Ryandaydev - avatarUrl: https://avatars.githubusercontent.com/u/4292423?u=48f68868db8886fce31a1d802c1003914c6cd7c6&v=4 - url: https://github.com/Ryandaydev - - login: jaredtrog - avatarUrl: https://avatars.githubusercontent.com/u/4381365?v=4 - url: https://github.com/jaredtrog + - login: mjohnsey + avatarUrl: https://avatars.githubusercontent.com/u/16784016?u=38fad2e6b411244560b3af99c5f5a4751bc81865&v=4 + url: https://github.com/mjohnsey + - 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: oliverxchen avatarUrl: https://avatars.githubusercontent.com/u/4471774?u=534191f25e32eeaadda22dfab4b0a428733d5489&v=4 url: https://github.com/oliverxchen - - login: ennui93 - avatarUrl: https://avatars.githubusercontent.com/u/5300907?u=5b5452725ddb391b2caaebf34e05aba873591c3a&v=4 - url: https://github.com/ennui93 - login: ternaus avatarUrl: https://avatars.githubusercontent.com/u/5481618?u=513a26b02a39e7a28d587cd37c6cc877ea368e6e&v=4 url: https://github.com/ternaus @@ -285,26 +246,20 @@ sponsors: avatarUrl: https://avatars.githubusercontent.com/u/5920492?u=208d419cf667b8ac594c82a8db01932c7e50d057&v=4 url: https://github.com/eseglem - login: FernandoCelmer - avatarUrl: https://avatars.githubusercontent.com/u/6262214?u=d29fff3fd862fda4ca752079f13f32e84c762ea4&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/6262214?u=58ba6d5888fa7f355934e52db19f950e20b38162&v=4 url: https://github.com/FernandoCelmer - - login: simw - avatarUrl: https://avatars.githubusercontent.com/u/6322526?v=4 - url: https://github.com/simw - login: Rehket avatarUrl: https://avatars.githubusercontent.com/u/7015688?u=3afb0ba200feebbc7f958950e92db34df2a3c172&v=4 url: https://github.com/Rehket - login: hiancdtrsnm avatarUrl: https://avatars.githubusercontent.com/u/7343177?v=4 url: https://github.com/hiancdtrsnm +- - login: manoelpqueiroz + avatarUrl: https://avatars.githubusercontent.com/u/23669137?u=b12e84b28a84369ab5b30bd5a79e5788df5a0756&v=4 + url: https://github.com/manoelpqueiroz - - login: pawamoy avatarUrl: https://avatars.githubusercontent.com/u/3999221?u=b030e4c89df2f3a36bc4710b925bdeb6745c9856&v=4 url: https://github.com/pawamoy - - login: engineerjoe440 - avatarUrl: https://avatars.githubusercontent.com/u/33275230?u=eb223cad27017bb1e936ee9b429b450d092d0236&v=4 - url: https://github.com/engineerjoe440 - - 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=81c525232bb35780945a68e88afd96bb2cdad9c4&v=4 url: https://github.com/petercool @@ -317,12 +272,12 @@ sponsors: - login: ArtyomVancyan avatarUrl: https://avatars.githubusercontent.com/u/44609997?v=4 url: https://github.com/ArtyomVancyan - - 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: caviri + avatarUrl: https://avatars.githubusercontent.com/u/45425937?u=4e14bd64282bad8f385eafbdb004b5a279366d6e&v=4 + url: https://github.com/caviri + - login: hgalytoby + avatarUrl: https://avatars.githubusercontent.com/u/50397689?u=62c7ff3519858423579676cd0efbd7e3f1ffe63a&v=4 + url: https://github.com/hgalytoby - login: SebTota avatarUrl: https://avatars.githubusercontent.com/u/25122511?v=4 url: https://github.com/SebTota @@ -338,51 +293,33 @@ sponsors: - login: rlnchow avatarUrl: https://avatars.githubusercontent.com/u/28018479?u=a93ca9cf1422b9ece155784a72d5f2fdbce7adff&v=4 url: https://github.com/rlnchow - - login: dvlpjrs - avatarUrl: https://avatars.githubusercontent.com/u/32254642?u=fbd6ad0324d4f1eb6231cf775be1c7bd4404e961&v=4 - url: https://github.com/dvlpjrs - - login: caviri - avatarUrl: https://avatars.githubusercontent.com/u/45425937?u=4e14bd64282bad8f385eafbdb004b5a279366d6e&v=4 - url: https://github.com/caviri - - login: hgalytoby - avatarUrl: https://avatars.githubusercontent.com/u/50397689?u=62c7ff3519858423579676cd0efbd7e3f1ffe63a&v=4 - url: https://github.com/hgalytoby - - login: conservative-dude - avatarUrl: https://avatars.githubusercontent.com/u/55538308?u=f250c44942ea6e73a6bd90739b381c470c192c11&v=4 - url: https://github.com/conservative-dude - - login: CR1337 - avatarUrl: https://avatars.githubusercontent.com/u/62649536?u=57a6aab10d2421a497306da8bcded01b826c54ae&v=4 - url: https://github.com/CR1337 + - login: engineerjoe440 + avatarUrl: https://avatars.githubusercontent.com/u/33275230?u=eb223cad27017bb1e936ee9b429b450d092d0236&v=4 + url: https://github.com/engineerjoe440 + - login: bnkc + avatarUrl: https://avatars.githubusercontent.com/u/34930566?u=db5e6f4f87836cad26c2aa90ce390ce49041c5a9&v=4 + url: https://github.com/bnkc + - login: johnl28 + avatarUrl: https://avatars.githubusercontent.com/u/54412955?u=47dd06082d1c39caa90c752eb55566e4f3813957&v=4 + url: https://github.com/johnl28 - login: PunRabbit avatarUrl: https://avatars.githubusercontent.com/u/70463212?u=1a835cfbc99295a60c8282f6aa6199d1b42241a5&v=4 url: https://github.com/PunRabbit - login: PelicanQ avatarUrl: https://avatars.githubusercontent.com/u/77930606?v=4 url: https://github.com/PelicanQ - - login: tochikuji - avatarUrl: https://avatars.githubusercontent.com/u/851759?v=4 - url: https://github.com/tochikuji - - login: browniebroke - avatarUrl: https://avatars.githubusercontent.com/u/861044?u=5abfca5588f3e906b31583d7ee62f6de4b68aa24&v=4 - url: https://github.com/browniebroke - login: miguelgr avatarUrl: https://avatars.githubusercontent.com/u/1484589?u=54556072b8136efa12ae3b6902032ea2a39ace4b&v=4 url: https://github.com/miguelgr - login: WillHogan - avatarUrl: https://avatars.githubusercontent.com/u/1661551?u=7036c064cf29781470573865264ec8e60b6b809f&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/1661551?u=8a80356e3e7d5a417157aba7ea565dabc8678327&v=4 url: https://github.com/WillHogan - login: my3 avatarUrl: https://avatars.githubusercontent.com/u/1825270?v=4 url: https://github.com/my3 - - login: leobiscassi - avatarUrl: https://avatars.githubusercontent.com/u/1977418?u=f9f82445a847ab479bd7223debd677fcac6c49a0&v=4 - url: https://github.com/leobiscassi - login: Alisa-lisa avatarUrl: https://avatars.githubusercontent.com/u/4137964?u=e7e393504f554f4ff15863a1e01a5746863ef9ce&v=4 url: https://github.com/Alisa-lisa - - login: Graeme22 - avatarUrl: https://avatars.githubusercontent.com/u/4185684?u=498182a42300d7bcd4de1215190cb17eb501136c&v=4 - url: https://github.com/Graeme22 - login: ddanier avatarUrl: https://avatars.githubusercontent.com/u/113563?u=ed1dc79de72f93bd78581f88ebc6952b62f472da&v=4 url: https://github.com/ddanier @@ -395,23 +332,14 @@ sponsors: - login: ceb10n avatarUrl: https://avatars.githubusercontent.com/u/235213?u=edcce471814a1eba9f0cdaa4cd0de18921a940a6&v=4 url: https://github.com/ceb10n - - login: eteq - avatarUrl: https://avatars.githubusercontent.com/u/346587?v=4 - url: https://github.com/eteq - - login: securancy - avatarUrl: https://avatars.githubusercontent.com/u/606673?v=4 - url: https://github.com/securancy - - login: moonape1226 - avatarUrl: https://avatars.githubusercontent.com/u/8532038?u=d9f8b855a429fff9397c3833c2ff83849ebf989d&v=4 - url: https://github.com/moonape1226 - - login: msehnout - avatarUrl: https://avatars.githubusercontent.com/u/9369632?u=8c988f1b008a3f601385a3616f9327820f66e3a5&v=4 - url: https://github.com/msehnout + - login: tochikuji + avatarUrl: https://avatars.githubusercontent.com/u/851759?v=4 + url: https://github.com/tochikuji - login: xncbf avatarUrl: https://avatars.githubusercontent.com/u/9462045?u=a80a7bb349555b277645632ed66639ff43400614&v=4 url: https://github.com/xncbf - login: DMantis - avatarUrl: https://avatars.githubusercontent.com/u/9536869?v=4 + avatarUrl: https://avatars.githubusercontent.com/u/9536869?u=652dd0d49717803c0cbcbf44f7740e53cf2d4892&v=4 url: https://github.com/DMantis - login: hard-coders avatarUrl: https://avatars.githubusercontent.com/u/9651103?u=95db33927bbff1ed1c07efddeb97ac2ff33068ed&v=4 @@ -425,15 +353,15 @@ sponsors: - login: pheanex avatarUrl: https://avatars.githubusercontent.com/u/10408624?u=5b6bab6ee174aa6e991333e06eb29f628741013d&v=4 url: https://github.com/pheanex - - login: dzoladz - avatarUrl: https://avatars.githubusercontent.com/u/10561752?u=5ee314d54aa79592c18566827ad8914debd5630d&v=4 - url: https://github.com/dzoladz - login: Zuzah avatarUrl: https://avatars.githubusercontent.com/u/10934846?u=1ef43e075ddc87bd1178372bf4d95ee6175cae27&v=4 url: https://github.com/Zuzah - - login: artempronevskiy - avatarUrl: https://avatars.githubusercontent.com/u/12235104?u=03df6e1e55c9c6fe5d230adabb8dd7d43d8bbe8f&v=4 - url: https://github.com/artempronevskiy + - 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 @@ -458,33 +386,54 @@ sponsors: - login: harsh183 avatarUrl: https://avatars.githubusercontent.com/u/7780198?v=4 url: https://github.com/harsh183 - - login: hcristea - avatarUrl: https://avatars.githubusercontent.com/u/7814406?u=61d7a4fcf846983a4606788eac25e1c6c1209ba8&v=4 - url: https://github.com/hcristea -- - login: larsyngvelundin - avatarUrl: https://avatars.githubusercontent.com/u/34173819?u=74958599695bf83ac9f1addd935a51548a10c6b0&v=4 - url: https://github.com/larsyngvelundin - - login: andrecorumba + - login: moonape1226 + avatarUrl: https://avatars.githubusercontent.com/u/8532038?u=d9f8b855a429fff9397c3833c2ff83849ebf989d&v=4 + url: https://github.com/moonape1226 +- - login: andrecorumba avatarUrl: https://avatars.githubusercontent.com/u/37807517?u=9b9be3b41da9bda60957da9ef37b50dbf65baa61&v=4 url: https://github.com/andrecorumba + - login: KOZ39 + avatarUrl: https://avatars.githubusercontent.com/u/38822500?u=9dfc0a697df1c9628f08e20dc3fb17b1afc4e5a7&v=4 + url: https://github.com/KOZ39 - login: rwxd avatarUrl: https://avatars.githubusercontent.com/u/40308458?u=cd04a39e3655923be4f25c2ba8a5a07b3da3230a&v=4 url: https://github.com/rwxd - - login: sadikkuzu - avatarUrl: https://avatars.githubusercontent.com/u/23168063?u=d179c06bb9f65c4167fcab118526819f8e0dac17&v=4 - url: https://github.com/sadikkuzu + - login: morzan1001 + avatarUrl: https://avatars.githubusercontent.com/u/47593005?u=c30ab7230f82a12a9b938dcb54f84a996931409a&v=4 + url: https://github.com/morzan1001 - login: Olegt0rr avatarUrl: https://avatars.githubusercontent.com/u/25399456?u=3e87b5239a2f4600975ba13be73054f8567c6060&v=4 url: https://github.com/Olegt0rr - - login: FabulousCodingFox - avatarUrl: https://avatars.githubusercontent.com/u/78906517?u=924a27cbee3db7e0ece5cc1509921402e1445e74&v=4 - url: https://github.com/FabulousCodingFox - - login: anqorithm - avatarUrl: https://avatars.githubusercontent.com/u/61029571?u=468256fa4e2d9ce2870b608299724bebb7a33f18&v=4 - url: https://github.com/anqorithm - - login: ssbarnea - avatarUrl: https://avatars.githubusercontent.com/u/102495?u=c7bd9ddf127785286fc939dd18cb02db0a453bce&v=4 - url: https://github.com/ssbarnea + - login: larsyngvelundin + avatarUrl: https://avatars.githubusercontent.com/u/34173819?u=74958599695bf83ac9f1addd935a51548a10c6b0&v=4 + url: https://github.com/larsyngvelundin + - login: v4lerdon + avatarUrl: https://avatars.githubusercontent.com/u/98405746?u=10969728d51e8f08e203f5d65fda948c21545c73&v=4 + url: https://github.com/v4lerdon + - login: hauanitech + avatarUrl: https://avatars.githubusercontent.com/u/211940501?u=48f70c3ef9b89c598d2dde528cda2d4f6468a135&v=4 + url: https://github.com/hauanitech + - login: igor-kan + avatarUrl: https://avatars.githubusercontent.com/u/61065863?u=3bade33799d183510fd381e2e4f5e1b61af8631a&v=4 + url: https://github.com/igor-kan + - login: 0ne-stone + avatarUrl: https://avatars.githubusercontent.com/u/62360849?u=746dd21c34e7e06eefb11b03e8bb01aaae3c2a4f&v=4 + url: https://github.com/0ne-stone + - login: t3llscode + avatarUrl: https://avatars.githubusercontent.com/u/65864434?u=35df974cec16993343bf6494d60a14e71f66c5af&v=4 + url: https://github.com/t3llscode + - login: nayasinghania + avatarUrl: https://avatars.githubusercontent.com/u/74111380?u=752e99a5e139389fdc0a0677122adc08438eb076&v=4 + url: https://github.com/nayasinghania + - login: Toothwitch + avatarUrl: https://avatars.githubusercontent.com/u/1710406?u=5eebb23b46cd26e48643b9e5179536cad491c17a&v=4 + url: https://github.com/Toothwitch - login: andreagrandi avatarUrl: https://avatars.githubusercontent.com/u/636391?u=13d90cb8ec313593a5b71fbd4e33b78d6da736f5&v=4 url: https://github.com/andreagrandi + - login: sadikkuzu + avatarUrl: https://avatars.githubusercontent.com/u/23168063?u=d179c06bb9f65c4167fcab118526819f8e0dac17&v=4 + url: https://github.com/sadikkuzu + - login: roboman-tech + avatarUrl: https://avatars.githubusercontent.com/u/8183070?u=fdeaa2ed29f598eb7901693884c0ad32b16982e3&v=4 + url: https://github.com/roboman-tech diff --git a/docs/en/data/members.yml b/docs/en/data/members.yml index cf016eae1..7ec16e917 100644 --- a/docs/en/data/members.yml +++ b/docs/en/data/members.yml @@ -17,3 +17,6 @@ members: - login: patrick91 avatar_url: https://avatars.githubusercontent.com/u/667029 url: https://github.com/patrick91 +- login: luzzodev + avatar_url: https://avatars.githubusercontent.com/u/27291415 + url: https://github.com/luzzodev diff --git a/docs/en/data/people.yml b/docs/en/data/people.yml index 112567778..714d2eac7 100644 --- a/docs/en/data/people.yml +++ b/docs/en/data/people.yml @@ -1,43 +1,43 @@ maintainers: - login: tiangolo - answers: 1894 + answers: 1898 avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 url: https://github.com/tiangolo experts: - login: tiangolo - count: 1894 + count: 1898 avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 url: https://github.com/tiangolo +- login: YuriiMotov + count: 952 + avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=b9b13d598dddfab529a52d264df80a900bfe7060&v=4 + url: https://github.com/YuriiMotov - login: github-actions - count: 770 + count: 769 avatarUrl: https://avatars.githubusercontent.com/in/15368?v=4 url: https://github.com/apps/github-actions - login: Kludex - count: 644 + count: 654 avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=df8a3f06ba8f55ae1967a3e2d5ed882903a4e330&v=4 url: https://github.com/Kludex - login: jgould22 - count: 250 + count: 263 avatarUrl: https://avatars.githubusercontent.com/u/4335847?u=ed77f67e0bb069084639b24d812dbb2a2b1dc554&v=4 url: https://github.com/jgould22 - login: dmontagu count: 240 avatarUrl: https://avatars.githubusercontent.com/u/35119617?u=540f30c937a6450812628b9592a1dfe91bbe148e&v=4 url: https://github.com/dmontagu -- login: YuriiMotov - count: 223 - avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=e83a39697a2d33ab2ec9bfbced794ee48bc29cec&v=4 - url: https://github.com/YuriiMotov - login: Mause count: 219 avatarUrl: https://avatars.githubusercontent.com/u/1405026?v=4 url: https://github.com/Mause - login: ycd - count: 217 - avatarUrl: https://avatars.githubusercontent.com/u/62724709?u=29682e4b6ac7d5293742ccf818188394b9a82972&v=4 + count: 216 + avatarUrl: https://avatars.githubusercontent.com/u/62724709?u=f1e7bae394a315da950912c92dc861a8eaf95d4c&v=4 url: https://github.com/ycd - login: JarroVGIT - count: 192 + count: 190 avatarUrl: https://avatars.githubusercontent.com/u/13659033?u=e8bea32d07a5ef72f7dde3b2079ceb714923ca05&v=4 url: https://github.com/JarroVGIT - login: euri10 @@ -46,48 +46,52 @@ experts: url: https://github.com/euri10 - login: iudeen count: 128 - avatarUrl: https://avatars.githubusercontent.com/u/10519440?u=2843b3303282bff8b212dcd4d9d6689452e4470c&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/10519440?u=f09cdd745e5bf16138f29b42732dd57c7f02bee1&v=4 url: https://github.com/iudeen - login: phy25 count: 126 avatarUrl: https://avatars.githubusercontent.com/u/331403?v=4 url: https://github.com/phy25 - login: JavierSanchezCastro - count: 85 + count: 94 avatarUrl: https://avatars.githubusercontent.com/u/72013291?u=ae5679e6bd971d9d98cd5e76e8683f83642ba950&v=4 url: https://github.com/JavierSanchezCastro +- login: luzzodev + count: 87 + avatarUrl: https://avatars.githubusercontent.com/u/27291415?u=5607ae1ce75c5f54f09500ca854227f7bfd2033b&v=4 + url: https://github.com/luzzodev - login: raphaelauv count: 83 avatarUrl: https://avatars.githubusercontent.com/u/10202690?u=e6f86f5c0c3026a15d6b51792fa3e532b12f1371&v=4 url: https://github.com/raphaelauv -- login: ghandic - count: 71 - avatarUrl: https://avatars.githubusercontent.com/u/23500353?u=e2e1d736f924d9be81e8bfc565b6d8836ba99773&v=4 - url: https://github.com/ghandic - login: ArcLightSlavik count: 71 avatarUrl: https://avatars.githubusercontent.com/u/31127044?u=b0f2c37142f4b762e41ad65dc49581813422bd71&v=4 url: https://github.com/ArcLightSlavik +- login: ghandic + count: 71 + avatarUrl: https://avatars.githubusercontent.com/u/23500353?u=e2e1d736f924d9be81e8bfc565b6d8836ba99773&v=4 + url: https://github.com/ghandic - login: n8sty - count: 66 + count: 67 avatarUrl: https://avatars.githubusercontent.com/u/2964996?v=4 url: https://github.com/n8sty - login: falkben count: 59 avatarUrl: https://avatars.githubusercontent.com/u/653031?u=ad9838e089058c9e5a0bab94c0eec7cc181e0cd0&v=4 url: https://github.com/falkben -- login: acidjunk +- login: yinziyan1206 count: 50 - avatarUrl: https://avatars.githubusercontent.com/u/685002?u=b5094ab4527fc84b006c0ac9ff54367bdebb2267&v=4 - url: https://github.com/acidjunk + avatarUrl: https://avatars.githubusercontent.com/u/37829370?u=da44ca53aefd5c23f346fab8e9fd2e108294c179&v=4 + url: https://github.com/yinziyan1206 - login: sm-Fifteen count: 49 avatarUrl: https://avatars.githubusercontent.com/u/516999?u=437c0c5038558c67e887ccd863c1ba0f846c03da&v=4 url: https://github.com/sm-Fifteen -- login: yinziyan1206 +- login: acidjunk count: 49 - avatarUrl: https://avatars.githubusercontent.com/u/37829370?u=da44ca53aefd5c23f346fab8e9fd2e108294c179&v=4 - url: https://github.com/yinziyan1206 + avatarUrl: https://avatars.githubusercontent.com/u/685002?u=b5094ab4527fc84b006c0ac9ff54367bdebb2267&v=4 + url: https://github.com/acidjunk - login: adriangb count: 46 avatarUrl: https://avatars.githubusercontent.com/u/1755071?u=612704256e38d6ac9cbed24f10e4b6ac2da74ecb&v=4 @@ -100,34 +104,30 @@ experts: count: 45 avatarUrl: https://avatars.githubusercontent.com/u/16958893?u=f8be7088d5076d963984a21f95f44e559192d912&v=4 url: https://github.com/insomnes -- login: odiseo0 - count: 43 - avatarUrl: https://avatars.githubusercontent.com/u/87550035?u=241a71f6b7068738b81af3e57f45ffd723538401&v=4 - url: https://github.com/odiseo0 - login: frankie567 count: 43 avatarUrl: https://avatars.githubusercontent.com/u/1144727?u=c159fe047727aedecbbeeaa96a1b03ceb9d39add&v=4 url: https://github.com/frankie567 +- login: odiseo0 + count: 43 + avatarUrl: https://avatars.githubusercontent.com/u/87550035?u=241a71f6b7068738b81af3e57f45ffd723538401&v=4 + url: https://github.com/odiseo0 +- login: sinisaos + count: 41 + avatarUrl: https://avatars.githubusercontent.com/u/30960668?v=4 + url: https://github.com/sinisaos - login: includeamin count: 40 avatarUrl: https://avatars.githubusercontent.com/u/11836741?u=8bd5ef7e62fe6a82055e33c4c0e0a7879ff8cfb6&v=4 url: https://github.com/includeamin -- login: sinisaos - count: 39 - avatarUrl: https://avatars.githubusercontent.com/u/30960668?v=4 - url: https://github.com/sinisaos -- login: chbndrhnns - count: 37 - avatarUrl: https://avatars.githubusercontent.com/u/7534547?v=4 - url: https://github.com/chbndrhnns - login: STeveShary count: 37 avatarUrl: https://avatars.githubusercontent.com/u/5167622?u=de8f597c81d6336fcebc37b32dfd61a3f877160c&v=4 url: https://github.com/STeveShary -- login: luzzodev - count: 36 - avatarUrl: https://avatars.githubusercontent.com/u/27291415?v=4 - url: https://github.com/luzzodev +- login: chbndrhnns + count: 37 + avatarUrl: https://avatars.githubusercontent.com/u/7534547?v=4 + url: https://github.com/chbndrhnns - login: krishnardt count: 35 avatarUrl: https://avatars.githubusercontent.com/u/31960541?u=47f4829c77f4962ab437ffb7995951e41eeebe9b&v=4 @@ -144,9 +144,13 @@ experts: count: 27 avatarUrl: https://avatars.githubusercontent.com/u/13135006?u=99f0b0f0fc47e88e8abb337b4447357939ef93e7&v=4 url: https://github.com/hasansezertasan +- login: alv2017 + count: 26 + avatarUrl: https://avatars.githubusercontent.com/u/31544722?v=4 + url: https://github.com/alv2017 - login: dbanty count: 26 - avatarUrl: https://avatars.githubusercontent.com/u/43723790?u=9bcce836bbce55835291c5b2ac93a4e311f4b3c3&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/43723790?u=9d726785d08e50b1e1cd96505800c8ea8405bce2&v=4 url: https://github.com/dbanty - login: wshayes count: 25 @@ -156,14 +160,14 @@ experts: count: 23 avatarUrl: https://avatars.githubusercontent.com/u/9435877?u=719327b7d2c4c62212456d771bfa7c6b8dbb9eac&v=4 url: https://github.com/SirTelemak +- login: connebs + count: 22 + avatarUrl: https://avatars.githubusercontent.com/u/9054108?u=e151d5f545a3395136d711c227c22032fda67cfa&v=4 + url: https://github.com/connebs - login: nymous count: 22 avatarUrl: https://avatars.githubusercontent.com/u/4216559?u=360a36fb602cded27273cbfc0afc296eece90662&v=4 url: https://github.com/nymous -- login: acnebs - count: 22 - avatarUrl: https://avatars.githubusercontent.com/u/9054108?v=4 - url: https://github.com/acnebs - login: chrisK824 count: 22 avatarUrl: https://avatars.githubusercontent.com/u/79946379?u=03d85b22d696a58a9603e55fbbbe2de6b0f4face&v=4 @@ -172,10 +176,6 @@ experts: count: 21 avatarUrl: https://avatars.githubusercontent.com/u/51059348?u=5fe59a56e1f2f9ccd8005d71752a8276f133ae1a&v=4 url: https://github.com/rafsaf -- login: ebottos94 - count: 20 - avatarUrl: https://avatars.githubusercontent.com/u/100039558?u=8b91053b3abe4a9209375e3651e1c1ef192d884b&v=4 - url: https://github.com/ebottos94 - login: nsidnev count: 20 avatarUrl: https://avatars.githubusercontent.com/u/22559461?u=a9cc3238217e21dc8796a1a500f01b722adb082c&v=4 @@ -184,26 +184,30 @@ experts: count: 20 avatarUrl: https://avatars.githubusercontent.com/u/565544?v=4 url: https://github.com/chris-allnutt +- login: ebottos94 + count: 20 + avatarUrl: https://avatars.githubusercontent.com/u/100039558?u=8b91053b3abe4a9209375e3651e1c1ef192d884b&v=4 + url: https://github.com/ebottos94 - login: estebanx64 count: 19 avatarUrl: https://avatars.githubusercontent.com/u/10840422?u=45f015f95e1c0f06df602be4ab688d4b854cc8a8&v=4 url: https://github.com/estebanx64 -- login: zoliknemet +- login: valentinDruzhinin + count: 19 + avatarUrl: https://avatars.githubusercontent.com/u/12831905?u=aae1ebc675c91e8fa582df4fcc4fc4128106344d&v=4 + url: https://github.com/valentinDruzhinin +- login: sehraramiz count: 18 - avatarUrl: https://avatars.githubusercontent.com/u/22326718?u=31ba446ac290e23e56eea8e4f0c558aaf0b40779&v=4 - url: https://github.com/zoliknemet + avatarUrl: https://avatars.githubusercontent.com/u/14166324?u=8fac65e84dfff24245d304a5b5b09f7b5bd69dc9&v=4 + url: https://github.com/sehraramiz - login: retnikt count: 18 avatarUrl: https://avatars.githubusercontent.com/u/24581770?v=4 url: https://github.com/retnikt -- login: sehraramiz - count: 17 - avatarUrl: https://avatars.githubusercontent.com/u/14166324?u=8fac65e84dfff24245d304a5b5b09f7b5bd69dc9&v=4 - url: https://github.com/sehraramiz -- login: caeser1996 - count: 17 - avatarUrl: https://avatars.githubusercontent.com/u/16540232?u=05d2beb8e034d584d0a374b99d8826327bd7f614&v=4 - url: https://github.com/caeser1996 +- login: zoliknemet + count: 18 + avatarUrl: https://avatars.githubusercontent.com/u/22326718?u=31ba446ac290e23e56eea8e4f0c558aaf0b40779&v=4 + url: https://github.com/zoliknemet - login: Hultner count: 17 avatarUrl: https://avatars.githubusercontent.com/u/2669034?u=115e53df959309898ad8dc9443fbb35fee71df07&v=4 @@ -212,207 +216,304 @@ experts: count: 17 avatarUrl: https://avatars.githubusercontent.com/u/1765494?u=5b1ab7c582db4b4016fa31affe977d10af108ad4&v=4 url: https://github.com/harunyasar +- login: caeser1996 + count: 17 + avatarUrl: https://avatars.githubusercontent.com/u/16540232?u=05d2beb8e034d584d0a374b99d8826327bd7f614&v=4 + url: https://github.com/caeser1996 - login: nkhitrov count: 17 avatarUrl: https://avatars.githubusercontent.com/u/28262306?u=e19427d8dc296d6950e9c424adacc92d37496fe9&v=4 url: https://github.com/nkhitrov -- login: jonatasoli - count: 16 - avatarUrl: https://avatars.githubusercontent.com/u/26334101?u=071c062d2861d3dd127f6b4a5258cd8ef55d4c50&v=4 - url: https://github.com/jonatasoli - login: dstlny count: 16 avatarUrl: https://avatars.githubusercontent.com/u/41964673?u=9f2174f9d61c15c6e3a4c9e3aeee66f711ce311f&v=4 url: https://github.com/dstlny -- login: jorgerpo - count: 15 - avatarUrl: https://avatars.githubusercontent.com/u/12537771?u=7444d20019198e34911082780cc7ad73f2b97cb3&v=4 - url: https://github.com/jorgerpo -- login: simondale00 +- login: jonatasoli + count: 16 + avatarUrl: https://avatars.githubusercontent.com/u/26334101?u=f601c3f111f2148bd9244c2cb3ebbd57b592e674&v=4 + url: https://github.com/jonatasoli +- login: abhint count: 15 - avatarUrl: https://avatars.githubusercontent.com/u/33907262?u=2721fb37014d50daf473267c808aa678ecaefe09&v=4 - url: https://github.com/simondale00 + avatarUrl: https://avatars.githubusercontent.com/u/25699289?u=b5d219277b4d001ac26fb8be357fddd88c29d51b&v=4 + url: https://github.com/abhint - login: ghost count: 15 avatarUrl: https://avatars.githubusercontent.com/u/10137?u=b1951d34a583cf12ec0d3b0781ba19be97726318&v=4 url: https://github.com/ghost -- login: abhint +- login: jorgerpo count: 15 - avatarUrl: https://avatars.githubusercontent.com/u/25699289?u=b5d219277b4d001ac26fb8be357fddd88c29d51b&v=4 - url: https://github.com/abhint -- login: pythonweb2 - count: 14 - avatarUrl: https://avatars.githubusercontent.com/u/32141163?v=4 - url: https://github.com/pythonweb2 + avatarUrl: https://avatars.githubusercontent.com/u/12537771?u=7444d20019198e34911082780cc7ad73f2b97cb3&v=4 + url: https://github.com/jorgerpo last_month_experts: -- login: Kludex - count: 15 - avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=df8a3f06ba8f55ae1967a3e2d5ed882903a4e330&v=4 - url: https://github.com/Kludex - login: YuriiMotov - count: 10 - avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=e83a39697a2d33ab2ec9bfbced794ee48bc29cec&v=4 + count: 69 + avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=b9b13d598dddfab529a52d264df80a900bfe7060&v=4 url: https://github.com/YuriiMotov -- login: sehraramiz - count: 8 - avatarUrl: https://avatars.githubusercontent.com/u/14166324?u=8fac65e84dfff24245d304a5b5b09f7b5bd69dc9&v=4 - url: https://github.com/sehraramiz - login: luzzodev + count: 8 + avatarUrl: https://avatars.githubusercontent.com/u/27291415?u=5607ae1ce75c5f54f09500ca854227f7bfd2033b&v=4 + url: https://github.com/luzzodev +- login: valentinDruzhinin + count: 7 + avatarUrl: https://avatars.githubusercontent.com/u/12831905?u=aae1ebc675c91e8fa582df4fcc4fc4128106344d&v=4 + url: https://github.com/valentinDruzhinin +- login: eqsdxr count: 4 - avatarUrl: https://avatars.githubusercontent.com/u/27291415?v=4 + avatarUrl: https://avatars.githubusercontent.com/u/157279130?u=58fddf77ed76966eaa8c73eea9bea4bb0c53b673&v=4 + url: https://github.com/eqsdxr +- login: Jelle-tenB + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/210023470?u=c25d66addf36a747bd9fab773c4a6e7b238f45d4&v=4 + url: https://github.com/Jelle-tenB +- login: Garrett-R + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/6614695?u=c128fd775002882f6e391bda5a89d1bdc5bdf45f&v=4 + url: https://github.com/Garrett-R +three_months_experts: +- login: YuriiMotov + count: 736 + avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=b9b13d598dddfab529a52d264df80a900bfe7060&v=4 + url: https://github.com/YuriiMotov +- login: luzzodev + count: 27 + avatarUrl: https://avatars.githubusercontent.com/u/27291415?u=5607ae1ce75c5f54f09500ca854227f7bfd2033b&v=4 url: https://github.com/luzzodev -- login: yokwejuste +- login: valentinDruzhinin + count: 19 + avatarUrl: https://avatars.githubusercontent.com/u/12831905?u=aae1ebc675c91e8fa582df4fcc4fc4128106344d&v=4 + url: https://github.com/valentinDruzhinin +- login: raceychan + count: 6 + avatarUrl: https://avatars.githubusercontent.com/u/75417963?u=060c62870ec5a791765e63ac20d8885d11143786&v=4 + url: https://github.com/raceychan +- login: sachinh35 + count: 6 + avatarUrl: https://avatars.githubusercontent.com/u/21972708?u=8560b97b8b41e175f476270b56de8a493b84f302&v=4 + url: https://github.com/sachinh35 +- login: DoctorJohn + count: 5 + avatarUrl: https://avatars.githubusercontent.com/u/14076775?u=2913e70a6142772847e91e2aaa5b9152391715e9&v=4 + url: https://github.com/DoctorJohn +- login: eqsdxr count: 4 - avatarUrl: https://avatars.githubusercontent.com/u/71908316?u=592c1e42aa0ee5cb94890e0b863e2acc78cc3bbc&v=4 - url: https://github.com/yokwejuste -- login: alv2017 + avatarUrl: https://avatars.githubusercontent.com/u/157279130?u=58fddf77ed76966eaa8c73eea9bea4bb0c53b673&v=4 + url: https://github.com/eqsdxr +- login: Jelle-tenB count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/31544722?v=4 - url: https://github.com/alv2017 -- login: PREPONDERANCE + avatarUrl: https://avatars.githubusercontent.com/u/210023470?u=c25d66addf36a747bd9fab773c4a6e7b238f45d4&v=4 + url: https://github.com/Jelle-tenB +- login: JavierSanchezCastro + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/72013291?u=ae5679e6bd971d9d98cd5e76e8683f83642ba950&v=4 + url: https://github.com/JavierSanchezCastro +- login: purepani + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/7587353?v=4 + url: https://github.com/purepani +- login: tiangolo count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/112809059?u=30ab12dc9ddba2f94ab90e6ad4ad8bc5cfa7fccd&v=4 - url: https://github.com/PREPONDERANCE -- login: nbx3 + avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 + url: https://github.com/tiangolo +- login: TaigoFr count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/34649527?u=943812f69e0d40adbd3fa1c9b8ef50dd971a2a45&v=4 - url: https://github.com/nbx3 -- login: XiaoXinYo + avatarUrl: https://avatars.githubusercontent.com/u/17792131?u=372b27056ec82f1ae03d8b3f37ef55b04a7cfdd1&v=4 + url: https://github.com/TaigoFr +- login: Garrett-R count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/56395004?u=b3b7cb758997f283c271a581833e407229dab82c&v=4 - url: https://github.com/XiaoXinYo -- login: iloveitaly + avatarUrl: https://avatars.githubusercontent.com/u/6614695?u=c128fd775002882f6e391bda5a89d1bdc5bdf45f&v=4 + url: https://github.com/Garrett-R +- login: henrymcl count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/150855?v=4 - url: https://github.com/iloveitaly -three_months_experts: -- login: luzzodev - count: 34 - avatarUrl: https://avatars.githubusercontent.com/u/27291415?v=4 - url: https://github.com/luzzodev + avatarUrl: https://avatars.githubusercontent.com/u/26480299?v=4 + url: https://github.com/henrymcl +- login: jymchng + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/27895426?u=fb88c47775147d62a395fdb895d1af4148c7b566&v=4 + url: https://github.com/jymchng +- login: Brikas + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/80290187?v=4 + url: https://github.com/Brikas +- login: davidhuser + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/4357648?u=6ed702f8f6d49a8b2a0ed33cbd8ab59c2d7db7f7&v=4 + url: https://github.com/davidhuser +- login: Kludex + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=df8a3f06ba8f55ae1967a3e2d5ed882903a4e330&v=4 + url: https://github.com/Kludex +six_months_experts: - login: YuriiMotov - count: 33 - avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=e83a39697a2d33ab2ec9bfbced794ee48bc29cec&v=4 + count: 754 + avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=b9b13d598dddfab529a52d264df80a900bfe7060&v=4 url: https://github.com/YuriiMotov -- login: Kludex +- login: luzzodev + count: 51 + avatarUrl: https://avatars.githubusercontent.com/u/27291415?u=5607ae1ce75c5f54f09500ca854227f7bfd2033b&v=4 + url: https://github.com/luzzodev +- login: alv2017 count: 23 + avatarUrl: https://avatars.githubusercontent.com/u/31544722?v=4 + url: https://github.com/alv2017 +- login: valentinDruzhinin + count: 19 + avatarUrl: https://avatars.githubusercontent.com/u/12831905?u=aae1ebc675c91e8fa582df4fcc4fc4128106344d&v=4 + url: https://github.com/valentinDruzhinin +- login: jgould22 + count: 13 + avatarUrl: https://avatars.githubusercontent.com/u/4335847?u=ed77f67e0bb069084639b24d812dbb2a2b1dc554&v=4 + url: https://github.com/jgould22 +- login: Kludex + count: 11 avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=df8a3f06ba8f55ae1967a3e2d5ed882903a4e330&v=4 url: https://github.com/Kludex -- login: sehraramiz +- login: JavierSanchezCastro count: 10 - avatarUrl: https://avatars.githubusercontent.com/u/14166324?u=8fac65e84dfff24245d304a5b5b09f7b5bd69dc9&v=4 - url: https://github.com/sehraramiz -- login: estebanx64 - count: 7 - avatarUrl: https://avatars.githubusercontent.com/u/10840422?u=45f015f95e1c0f06df602be4ab688d4b854cc8a8&v=4 - url: https://github.com/estebanx64 -- login: yvallois + avatarUrl: https://avatars.githubusercontent.com/u/72013291?u=ae5679e6bd971d9d98cd5e76e8683f83642ba950&v=4 + url: https://github.com/JavierSanchezCastro +- login: sachinh35 + count: 9 + avatarUrl: https://avatars.githubusercontent.com/u/21972708?u=8560b97b8b41e175f476270b56de8a493b84f302&v=4 + url: https://github.com/sachinh35 +- login: yauhen-sobaleu + count: 9 + avatarUrl: https://avatars.githubusercontent.com/u/51629535?u=fc1817060daf2df438bfca86c44f33da5cd667db&v=4 + url: https://github.com/yauhen-sobaleu +- login: tiangolo + count: 8 + avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 + url: https://github.com/tiangolo +- login: raceychan count: 6 - avatarUrl: https://avatars.githubusercontent.com/u/36999744?v=4 - url: https://github.com/yvallois -- login: yokwejuste - count: 4 - avatarUrl: https://avatars.githubusercontent.com/u/71908316?u=592c1e42aa0ee5cb94890e0b863e2acc78cc3bbc&v=4 - url: https://github.com/yokwejuste -- login: jgould22 + avatarUrl: https://avatars.githubusercontent.com/u/75417963?u=060c62870ec5a791765e63ac20d8885d11143786&v=4 + url: https://github.com/raceychan +- login: DoctorJohn + count: 5 + avatarUrl: https://avatars.githubusercontent.com/u/14076775?u=2913e70a6142772847e91e2aaa5b9152391715e9&v=4 + url: https://github.com/DoctorJohn +- login: eqsdxr count: 4 - avatarUrl: https://avatars.githubusercontent.com/u/4335847?u=ed77f67e0bb069084639b24d812dbb2a2b1dc554&v=4 - url: https://github.com/jgould22 -- login: alv2017 + avatarUrl: https://avatars.githubusercontent.com/u/157279130?u=58fddf77ed76966eaa8c73eea9bea4bb0c53b673&v=4 + url: https://github.com/eqsdxr +- login: Jelle-tenB count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/31544722?v=4 - url: https://github.com/alv2017 -- login: viniciusCalcantara + avatarUrl: https://avatars.githubusercontent.com/u/210023470?u=c25d66addf36a747bd9fab773c4a6e7b238f45d4&v=4 + url: https://github.com/Jelle-tenB +- login: SobikXexe count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/108818737?u=3d7ffe5808843ee4372f9cc5a559ff1674cf1792&v=4 - url: https://github.com/viniciusCalcantara -- login: PREPONDERANCE + avatarUrl: https://avatars.githubusercontent.com/u/87701130?v=4 + url: https://github.com/SobikXexe +- login: purepani count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/112809059?u=30ab12dc9ddba2f94ab90e6ad4ad8bc5cfa7fccd&v=4 - url: https://github.com/PREPONDERANCE -- login: nbx3 + avatarUrl: https://avatars.githubusercontent.com/u/7587353?v=4 + url: https://github.com/purepani +- login: WilliamDEdwards count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/34649527?u=943812f69e0d40adbd3fa1c9b8ef50dd971a2a45&v=4 - url: https://github.com/nbx3 -- login: XiaoXinYo + avatarUrl: https://avatars.githubusercontent.com/u/12184311?u=9b29d5d1d71f5f1a7ef9e439963ad3529e3b33a4&v=4 + url: https://github.com/WilliamDEdwards +- login: TaigoFr count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/56395004?u=b3b7cb758997f283c271a581833e407229dab82c&v=4 - url: https://github.com/XiaoXinYo -- login: JavierSanchezCastro + avatarUrl: https://avatars.githubusercontent.com/u/17792131?u=372b27056ec82f1ae03d8b3f37ef55b04a7cfdd1&v=4 + url: https://github.com/TaigoFr +- login: Garrett-R count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/72013291?u=ae5679e6bd971d9d98cd5e76e8683f83642ba950&v=4 - url: https://github.com/JavierSanchezCastro -- login: iloveitaly + avatarUrl: https://avatars.githubusercontent.com/u/6614695?u=c128fd775002882f6e391bda5a89d1bdc5bdf45f&v=4 + url: https://github.com/Garrett-R +- login: EverStarck count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/150855?v=4 - url: https://github.com/iloveitaly -- login: LincolnPuzey + avatarUrl: https://avatars.githubusercontent.com/u/51029456?u=343409b7cb6b3ea6a59359f4e8370d9c3f140ecd&v=4 + url: https://github.com/EverStarck +- login: henrymcl count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/18750802?v=4 - url: https://github.com/LincolnPuzey -- login: Knighthawk-Leo + avatarUrl: https://avatars.githubusercontent.com/u/26480299?v=4 + url: https://github.com/henrymcl +- login: jymchng count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/72437494?u=27c68db94a3107b605e603cc136f4ba83f0106d5&v=4 - url: https://github.com/Knighthawk-Leo -- login: gelezo43 + avatarUrl: https://avatars.githubusercontent.com/u/27895426?u=fb88c47775147d62a395fdb895d1af4148c7b566&v=4 + url: https://github.com/jymchng +- login: adsouza count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/40732698?u=611f39d3c1d2f4207a590937a78c1f10eed6232c&v=4 - url: https://github.com/gelezo43 -- login: dbfreem + avatarUrl: https://avatars.githubusercontent.com/u/275832?v=4 + url: https://github.com/adsouza +- login: Brikas count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/9778569?u=f2f1e9135b5e4f1b0c6821a548b17f97572720fc&v=4 - url: https://github.com/dbfreem -- login: AliYmn + avatarUrl: https://avatars.githubusercontent.com/u/80290187?v=4 + url: https://github.com/Brikas +- login: JacobHayes count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/18416653?u=98c1fca46c7e4dabe8c39d17b5e55d1511d41cf9&v=4 - url: https://github.com/AliYmn -- login: RichieB2B + avatarUrl: https://avatars.githubusercontent.com/u/2555532?u=354a525847a276bbb4426b0c95791a8ba5970f9b&v=4 + url: https://github.com/JacobHayes +- login: davidhuser count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/1461970?u=edaa57d1077705244ea5c9244f4783d94ff11f12&v=4 - url: https://github.com/RichieB2B -- login: Synrom + avatarUrl: https://avatars.githubusercontent.com/u/4357648?u=6ed702f8f6d49a8b2a0ed33cbd8ab59c2d7db7f7&v=4 + url: https://github.com/davidhuser +- login: PidgeyBE count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/30272537?v=4 - url: https://github.com/Synrom -- login: iiotsrc + avatarUrl: https://avatars.githubusercontent.com/u/19860056?u=47b584eb1c1ab45e31c1b474109a962d7e82be49&v=4 + url: https://github.com/PidgeyBE +- login: KianAnbarestani count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/131771119?u=bcaf2559ef6266af70b151b7fda31a1ee3dbecb3&v=4 - url: https://github.com/iiotsrc -- login: Kfir-G + avatarUrl: https://avatars.githubusercontent.com/u/145364424?u=dcc3d8fb4ca07d36fb52a17f38b6650565de40be&v=4 + url: https://github.com/KianAnbarestani +- login: sinisaos count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/57500876?u=0cd29db046a17f12f382d398141319fca7ff230a&v=4 - url: https://github.com/Kfir-G -six_months_experts: + avatarUrl: https://avatars.githubusercontent.com/u/30960668?v=4 + url: https://github.com/sinisaos +- login: Ale-Cas + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/64859146?u=d52a6ecf8d83d2927e2ae270bdfcc83495dba8c9&v=4 + url: https://github.com/Ale-Cas +- login: marsboy02 + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/86903678?u=04cc319d6605f8d1ba3a0bed9f4f55a582719ae6&v=4 + url: https://github.com/marsboy02 +- login: vtgn + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/112889052?v=4 + url: https://github.com/vtgn +one_year_experts: - login: YuriiMotov - count: 72 - avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=e83a39697a2d33ab2ec9bfbced794ee48bc29cec&v=4 + count: 820 + avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=b9b13d598dddfab529a52d264df80a900bfe7060&v=4 url: https://github.com/YuriiMotov +- login: luzzodev + count: 87 + avatarUrl: https://avatars.githubusercontent.com/u/27291415?u=5607ae1ce75c5f54f09500ca854227f7bfd2033b&v=4 + url: https://github.com/luzzodev - login: Kludex - count: 39 + count: 51 avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=df8a3f06ba8f55ae1967a3e2d5ed882903a4e330&v=4 url: https://github.com/Kludex - login: sinisaos - count: 37 + count: 39 avatarUrl: https://avatars.githubusercontent.com/u/30960668?v=4 url: https://github.com/sinisaos -- login: luzzodev - count: 36 - avatarUrl: https://avatars.githubusercontent.com/u/27291415?v=4 - url: https://github.com/luzzodev - login: JavierSanchezCastro - count: 16 + count: 26 avatarUrl: https://avatars.githubusercontent.com/u/72013291?u=ae5679e6bd971d9d98cd5e76e8683f83642ba950&v=4 url: https://github.com/JavierSanchezCastro +- login: alv2017 + count: 26 + avatarUrl: https://avatars.githubusercontent.com/u/31544722?v=4 + url: https://github.com/alv2017 - login: tiangolo - count: 13 + count: 21 avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 url: https://github.com/tiangolo +- login: valentinDruzhinin + count: 19 + avatarUrl: https://avatars.githubusercontent.com/u/12831905?u=aae1ebc675c91e8fa582df4fcc4fc4128106344d&v=4 + url: https://github.com/valentinDruzhinin +- login: jgould22 + count: 17 + avatarUrl: https://avatars.githubusercontent.com/u/4335847?u=ed77f67e0bb069084639b24d812dbb2a2b1dc554&v=4 + url: https://github.com/jgould22 - login: Kfir-G count: 13 avatarUrl: https://avatars.githubusercontent.com/u/57500876?u=0cd29db046a17f12f382d398141319fca7ff230a&v=4 url: https://github.com/Kfir-G - login: sehraramiz - count: 10 + count: 11 avatarUrl: https://avatars.githubusercontent.com/u/14166324?u=8fac65e84dfff24245d304a5b5b09f7b5bd69dc9&v=4 url: https://github.com/sehraramiz - login: estebanx64 @@ -420,57 +521,93 @@ six_months_experts: avatarUrl: https://avatars.githubusercontent.com/u/10840422?u=45f015f95e1c0f06df602be4ab688d4b854cc8a8&v=4 url: https://github.com/estebanx64 - login: ceb10n - count: 9 + count: 10 avatarUrl: https://avatars.githubusercontent.com/u/235213?u=edcce471814a1eba9f0cdaa4cd0de18921a940a6&v=4 url: https://github.com/ceb10n -- login: yvallois - count: 6 - avatarUrl: https://avatars.githubusercontent.com/u/36999744?v=4 - url: https://github.com/yvallois +- login: sachinh35 + count: 9 + avatarUrl: https://avatars.githubusercontent.com/u/21972708?u=8560b97b8b41e175f476270b56de8a493b84f302&v=4 + url: https://github.com/sachinh35 +- login: yauhen-sobaleu + count: 9 + avatarUrl: https://avatars.githubusercontent.com/u/51629535?u=fc1817060daf2df438bfca86c44f33da5cd667db&v=4 + url: https://github.com/yauhen-sobaleu - login: n8sty - count: 6 + count: 7 avatarUrl: https://avatars.githubusercontent.com/u/2964996?v=4 url: https://github.com/n8sty +- login: yvallois + count: 7 + avatarUrl: https://avatars.githubusercontent.com/u/36999744?v=4 + url: https://github.com/yvallois +- login: raceychan + count: 6 + avatarUrl: https://avatars.githubusercontent.com/u/75417963?u=060c62870ec5a791765e63ac20d8885d11143786&v=4 + url: https://github.com/raceychan +- login: DoctorJohn + count: 5 + avatarUrl: https://avatars.githubusercontent.com/u/14076775?u=2913e70a6142772847e91e2aaa5b9152391715e9&v=4 + url: https://github.com/DoctorJohn +- login: eqsdxr + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/157279130?u=58fddf77ed76966eaa8c73eea9bea4bb0c53b673&v=4 + url: https://github.com/eqsdxr - login: TomFaulkner count: 4 avatarUrl: https://avatars.githubusercontent.com/u/14956620?v=4 url: https://github.com/TomFaulkner - login: yokwejuste count: 4 - avatarUrl: https://avatars.githubusercontent.com/u/71908316?u=592c1e42aa0ee5cb94890e0b863e2acc78cc3bbc&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/71908316?u=4ba43bd63c169b5c015137d8916752a44001445a&v=4 url: https://github.com/yokwejuste -- login: jgould22 +- login: svlandeg count: 4 - avatarUrl: https://avatars.githubusercontent.com/u/4335847?u=ed77f67e0bb069084639b24d812dbb2a2b1dc554&v=4 - url: https://github.com/jgould22 -- login: alv2017 + avatarUrl: https://avatars.githubusercontent.com/u/8796347?u=556c97650c27021911b0b9447ec55e75987b0e8a&v=4 + url: https://github.com/svlandeg +- login: mattmess1221 count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/31544722?v=4 - url: https://github.com/alv2017 -- login: viniciusCalcantara + avatarUrl: https://avatars.githubusercontent.com/u/3409962?u=d22ea18aa8ea688af25a45df306134d593621a44&v=4 + url: https://github.com/mattmess1221 +- login: Jelle-tenB count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/108818737?u=3d7ffe5808843ee4372f9cc5a559ff1674cf1792&v=4 - url: https://github.com/viniciusCalcantara -- login: pawelad + avatarUrl: https://avatars.githubusercontent.com/u/210023470?u=c25d66addf36a747bd9fab773c4a6e7b238f45d4&v=4 + url: https://github.com/Jelle-tenB +- login: pythonweb2 count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/7062874?u=d27dc220545a8401ad21840590a97d474d7101e6&v=4 - url: https://github.com/pawelad -- login: dbfreem + avatarUrl: https://avatars.githubusercontent.com/u/32141163?v=4 + url: https://github.com/pythonweb2 +- login: viniciusCalcantara count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/9778569?u=f2f1e9135b5e4f1b0c6821a548b17f97572720fc&v=4 - url: https://github.com/dbfreem -- login: Isuxiz + avatarUrl: https://avatars.githubusercontent.com/u/108818737?u=80f3ec7427fa6a41d5896984d0c526432f2299fa&v=4 + url: https://github.com/viniciusCalcantara +- login: davidhuser count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/48672727?u=34d7b4ade252687d22a27cf53037b735b244bfc1&v=4 - url: https://github.com/Isuxiz + avatarUrl: https://avatars.githubusercontent.com/u/4357648?u=6ed702f8f6d49a8b2a0ed33cbd8ab59c2d7db7f7&v=4 + url: https://github.com/davidhuser - login: bertomaniac count: 3 avatarUrl: https://avatars.githubusercontent.com/u/10235051?u=14484a96833228a7b29fee4a7916d411c242c4f6&v=4 url: https://github.com/bertomaniac +- login: dbfreem + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/9778569?u=f2f1e9135b5e4f1b0c6821a548b17f97572720fc&v=4 + url: https://github.com/dbfreem - login: PhysicallyActive count: 3 avatarUrl: https://avatars.githubusercontent.com/u/160476156?u=7a8e44f4a43d3bba636f795bb7d9476c9233b4d8&v=4 url: https://github.com/PhysicallyActive +- login: SobikXexe + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/87701130?v=4 + url: https://github.com/SobikXexe +- login: pawelad + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/7062874?u=d27dc220545a8401ad21840590a97d474d7101e6&v=4 + url: https://github.com/pawelad +- login: Isuxiz + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/48672727?u=34d7b4ade252687d22a27cf53037b735b244bfc1&v=4 + url: https://github.com/Isuxiz - login: Minibrams count: 3 avatarUrl: https://avatars.githubusercontent.com/u/8108085?u=b028dbc308fa8485e0e2e9402b3d03d8deb22bf9&v=4 @@ -479,388 +616,99 @@ six_months_experts: count: 3 avatarUrl: https://avatars.githubusercontent.com/u/88404339?u=2a80d80b054e9228391e32fb9bb39571509dab6a&v=4 url: https://github.com/AIdjis -- login: svlandeg - count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/8796347?u=556c97650c27021911b0b9447ec55e75987b0e8a&v=4 - url: https://github.com/svlandeg -- login: PREPONDERANCE - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/112809059?u=30ab12dc9ddba2f94ab90e6ad4ad8bc5cfa7fccd&v=4 - url: https://github.com/PREPONDERANCE -- login: nbx3 - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/34649527?u=943812f69e0d40adbd3fa1c9b8ef50dd971a2a45&v=4 - url: https://github.com/nbx3 -- login: yanggeorge - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/2434407?v=4 - url: https://github.com/yanggeorge -- login: XiaoXinYo +- login: dolfinus count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/56395004?u=b3b7cb758997f283c271a581833e407229dab82c&v=4 - url: https://github.com/XiaoXinYo -- login: pythonweb2 - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/32141163?v=4 - url: https://github.com/pythonweb2 + avatarUrl: https://avatars.githubusercontent.com/u/4661021?u=ed5ddadcf36d9b943ebe61febe0b96ee34e5425d&v=4 + url: https://github.com/dolfinus - login: slafs count: 2 avatarUrl: https://avatars.githubusercontent.com/u/210173?v=4 url: https://github.com/slafs -- login: AmirHmZz - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/38752106?u=07f80e451bda00a9492bbc764e49d24ad3ada8cc&v=4 - url: https://github.com/AmirHmZz -- login: iloveitaly - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/150855?v=4 - url: https://github.com/iloveitaly -- login: LincolnPuzey - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/18750802?v=4 - url: https://github.com/LincolnPuzey -- login: alejsdev - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/90076947?u=356f39ff3f0211c720b06d3dbb060e98884085e3&v=4 - url: https://github.com/alejsdev -- login: Knighthawk-Leo - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/72437494?u=27c68db94a3107b605e603cc136f4ba83f0106d5&v=4 - url: https://github.com/Knighthawk-Leo -- login: gelezo43 - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/40732698?u=611f39d3c1d2f4207a590937a78c1f10eed6232c&v=4 - url: https://github.com/gelezo43 -- login: christiansicari - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/29756552?v=4 - url: https://github.com/christiansicari -- login: 1001pepi - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/82064861?u=8c6ffdf2275d6970a07294752c545cd2702c57d3&v=4 - url: https://github.com/1001pepi -- login: AliYmn - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/18416653?u=98c1fca46c7e4dabe8c39d17b5e55d1511d41cf9&v=4 - url: https://github.com/AliYmn -- login: RichieB2B - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/1461970?u=edaa57d1077705244ea5c9244f4783d94ff11f12&v=4 - url: https://github.com/RichieB2B -- login: Synrom - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/30272537?v=4 - url: https://github.com/Synrom -- login: ecly - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/8410422?v=4 - url: https://github.com/ecly -- login: iiotsrc - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/131771119?u=bcaf2559ef6266af70b151b7fda31a1ee3dbecb3&v=4 - url: https://github.com/iiotsrc -- login: simondale00 - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/33907262?u=2721fb37014d50daf473267c808aa678ecaefe09&v=4 - url: https://github.com/simondale00 -- login: jd-solanki - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/47495003?u=6e225cb42c688d0cd70e65c6baedb9f5922b1178&v=4 - url: https://github.com/jd-solanki -- login: AumGupta - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/86357151?u=7d05aa606c0611a18f4db16cf26361ce10a6e195&v=4 - url: https://github.com/AumGupta -- login: DeoLeung +- login: purepani count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/3764720?u=4c222ef513814de4c7fb3736d0a7adf11d953d43&v=4 - url: https://github.com/DeoLeung -- login: Reemyos - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/44867003?v=4 - url: https://github.com/Reemyos -- login: deight93 - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/37678115?u=a608798b5bd0034183a9c430ebb42fb266db86ce&v=4 - url: https://github.com/deight93 -- login: Jkrox - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/83181939?u=d6a922d97129f7f3916d6a1c166bc011b3a72b7f&v=4 - url: https://github.com/Jkrox -- login: mmzeynalli - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/33568903?u=19efd0c0722730b83a70b7c86c36e5b7d83e07d2&v=4 - url: https://github.com/mmzeynalli + avatarUrl: https://avatars.githubusercontent.com/u/7587353?v=4 + url: https://github.com/purepani - login: ddahan count: 2 avatarUrl: https://avatars.githubusercontent.com/u/1933516?u=1d200a620e8d6841df017e9f2bb7efb58b580f40&v=4 url: https://github.com/ddahan -- login: jfeaver - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/1091338?u=0bcba366447d8fadad63f6705a52d128da4c7ec2&v=4 - url: https://github.com/jfeaver -- login: Wurstnase - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/8709415?u=f479af475a97aee9a1dab302cfc35d07e9ea245f&v=4 - url: https://github.com/Wurstnase -- login: tristan - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/1412?u=aab8aaa4cc0f1210ac45fc93873a5909d314c965&v=4 - url: https://github.com/tristan -- login: chandanch +- login: yanggeorge count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/8663552?u=afc484bc0a952c83f1fb6a1583cda443f807cd66&v=4 - url: https://github.com/chandanch -- login: rvishruth + avatarUrl: https://avatars.githubusercontent.com/u/2434407?v=4 + url: https://github.com/yanggeorge +- login: WilliamDEdwards count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/79176273?v=4 - url: https://github.com/rvishruth -- login: mattmess1221 + avatarUrl: https://avatars.githubusercontent.com/u/12184311?u=9b29d5d1d71f5f1a7ef9e439963ad3529e3b33a4&v=4 + url: https://github.com/WilliamDEdwards +- login: TaigoFr count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/3409962?u=723662989f2027755e67d200137c13c53ae154ac&v=4 - url: https://github.com/mattmess1221 -- login: meower1 + avatarUrl: https://avatars.githubusercontent.com/u/17792131?u=372b27056ec82f1ae03d8b3f37ef55b04a7cfdd1&v=4 + url: https://github.com/TaigoFr +- login: Garrett-R count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/109747197?u=0a5cc2a6ae74e558f0afc2874da85132e5953d8b&v=4 - url: https://github.com/meower1 -one_year_experts: -- login: YuriiMotov - count: 223 - avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=e83a39697a2d33ab2ec9bfbced794ee48bc29cec&v=4 - url: https://github.com/YuriiMotov -- login: Kludex - count: 83 - avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=df8a3f06ba8f55ae1967a3e2d5ed882903a4e330&v=4 - url: https://github.com/Kludex -- login: JavierSanchezCastro - count: 47 - avatarUrl: https://avatars.githubusercontent.com/u/72013291?u=ae5679e6bd971d9d98cd5e76e8683f83642ba950&v=4 - url: https://github.com/JavierSanchezCastro -- login: jgould22 - count: 42 - avatarUrl: https://avatars.githubusercontent.com/u/4335847?u=ed77f67e0bb069084639b24d812dbb2a2b1dc554&v=4 - url: https://github.com/jgould22 -- login: sinisaos - count: 39 - avatarUrl: https://avatars.githubusercontent.com/u/30960668?v=4 - url: https://github.com/sinisaos -- login: luzzodev - count: 36 - avatarUrl: https://avatars.githubusercontent.com/u/27291415?v=4 - url: https://github.com/luzzodev -- login: tiangolo - count: 24 - avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 - url: https://github.com/tiangolo -- login: n8sty - count: 23 - avatarUrl: https://avatars.githubusercontent.com/u/2964996?v=4 - url: https://github.com/n8sty -- login: estebanx64 - count: 19 - avatarUrl: https://avatars.githubusercontent.com/u/10840422?u=45f015f95e1c0f06df602be4ab688d4b854cc8a8&v=4 - url: https://github.com/estebanx64 -- login: sehraramiz - count: 14 - avatarUrl: https://avatars.githubusercontent.com/u/14166324?u=8fac65e84dfff24245d304a5b5b09f7b5bd69dc9&v=4 - url: https://github.com/sehraramiz -- login: PhysicallyActive - count: 14 - avatarUrl: https://avatars.githubusercontent.com/u/160476156?u=7a8e44f4a43d3bba636f795bb7d9476c9233b4d8&v=4 - url: https://github.com/PhysicallyActive -- login: ceb10n - count: 14 - avatarUrl: https://avatars.githubusercontent.com/u/235213?u=edcce471814a1eba9f0cdaa4cd0de18921a940a6&v=4 - url: https://github.com/ceb10n -- login: Kfir-G - count: 13 - avatarUrl: https://avatars.githubusercontent.com/u/57500876?u=0cd29db046a17f12f382d398141319fca7ff230a&v=4 - url: https://github.com/Kfir-G -- login: mattmess1221 - count: 11 - avatarUrl: https://avatars.githubusercontent.com/u/3409962?u=723662989f2027755e67d200137c13c53ae154ac&v=4 - url: https://github.com/mattmess1221 -- login: hasansezertasan - count: 10 - avatarUrl: https://avatars.githubusercontent.com/u/13135006?u=99f0b0f0fc47e88e8abb337b4447357939ef93e7&v=4 - url: https://github.com/hasansezertasan -- login: AIdjis - count: 8 - avatarUrl: https://avatars.githubusercontent.com/u/88404339?u=2a80d80b054e9228391e32fb9bb39571509dab6a&v=4 - url: https://github.com/AIdjis -- login: yvallois - count: 6 - avatarUrl: https://avatars.githubusercontent.com/u/36999744?v=4 - url: https://github.com/yvallois -- login: PREPONDERANCE - count: 5 - avatarUrl: https://avatars.githubusercontent.com/u/112809059?u=30ab12dc9ddba2f94ab90e6ad4ad8bc5cfa7fccd&v=4 - url: https://github.com/PREPONDERANCE -- login: pythonweb2 - count: 5 - avatarUrl: https://avatars.githubusercontent.com/u/32141163?v=4 - url: https://github.com/pythonweb2 -- login: acidjunk - count: 5 - avatarUrl: https://avatars.githubusercontent.com/u/685002?u=b5094ab4527fc84b006c0ac9ff54367bdebb2267&v=4 - url: https://github.com/acidjunk -- login: gustavosett - count: 5 - avatarUrl: https://avatars.githubusercontent.com/u/99373133?u=1739ca547c3d200f1b72450520bce46a97aab184&v=4 - url: https://github.com/gustavosett -- login: binbjz - count: 5 - avatarUrl: https://avatars.githubusercontent.com/u/8213913?u=22b68b7a0d5bf5e09c02084c0f5f53d7503114cd&v=4 - url: https://github.com/binbjz -- login: chyok - count: 5 - avatarUrl: https://avatars.githubusercontent.com/u/32629225?u=3b7c30e8a09426a1b9284f6e8a0ae53a525596bf&v=4 - url: https://github.com/chyok -- login: TomFaulkner - count: 4 - avatarUrl: https://avatars.githubusercontent.com/u/14956620?v=4 - url: https://github.com/TomFaulkner -- login: yokwejuste - count: 4 - avatarUrl: https://avatars.githubusercontent.com/u/71908316?u=592c1e42aa0ee5cb94890e0b863e2acc78cc3bbc&v=4 - url: https://github.com/yokwejuste -- login: DeoLeung - count: 4 - avatarUrl: https://avatars.githubusercontent.com/u/3764720?u=4c222ef513814de4c7fb3736d0a7adf11d953d43&v=4 - url: https://github.com/DeoLeung -- login: flo-at - count: 4 - avatarUrl: https://avatars.githubusercontent.com/u/564288?v=4 - url: https://github.com/flo-at -- login: GodMoonGoodman - count: 4 - avatarUrl: https://avatars.githubusercontent.com/u/29688727?u=7b251da620d999644c37c1feeb292d033eed7ad6&v=4 - url: https://github.com/GodMoonGoodman -- login: bertomaniac - count: 4 - avatarUrl: https://avatars.githubusercontent.com/u/10235051?u=14484a96833228a7b29fee4a7916d411c242c4f6&v=4 - url: https://github.com/bertomaniac -- login: alv2017 - count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/31544722?v=4 - url: https://github.com/alv2017 -- login: msehnout - count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/9369632?u=8c988f1b008a3f601385a3616f9327820f66e3a5&v=4 - url: https://github.com/msehnout -- login: viniciusCalcantara - count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/108818737?u=3d7ffe5808843ee4372f9cc5a559ff1674cf1792&v=4 - url: https://github.com/viniciusCalcantara -- login: pawelad - count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/7062874?u=d27dc220545a8401ad21840590a97d474d7101e6&v=4 - url: https://github.com/pawelad -- login: ThirVondukr - count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/50728601?u=167c0bd655e52817082e50979a86d2f98f95b1a3&v=4 - url: https://github.com/ThirVondukr -- login: dbfreem - count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/9778569?u=f2f1e9135b5e4f1b0c6821a548b17f97572720fc&v=4 - url: https://github.com/dbfreem -- login: Isuxiz - count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/48672727?u=34d7b4ade252687d22a27cf53037b735b244bfc1&v=4 - url: https://github.com/Isuxiz -- login: angely-dev - count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/4362224?v=4 - url: https://github.com/angely-dev -- login: deight93 - count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/37678115?u=a608798b5bd0034183a9c430ebb42fb266db86ce&v=4 - url: https://github.com/deight93 + avatarUrl: https://avatars.githubusercontent.com/u/6614695?u=c128fd775002882f6e391bda5a89d1bdc5bdf45f&v=4 + url: https://github.com/Garrett-R - login: mmzeynalli - count: 3 + count: 2 avatarUrl: https://avatars.githubusercontent.com/u/33568903?u=19efd0c0722730b83a70b7c86c36e5b7d83e07d2&v=4 url: https://github.com/mmzeynalli -- login: Minibrams - count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/8108085?u=b028dbc308fa8485e0e2e9402b3d03d8deb22bf9&v=4 - url: https://github.com/Minibrams -- login: ryanisn - count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/53449841?v=4 - url: https://github.com/ryanisn -- login: svlandeg - count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/8796347?u=556c97650c27021911b0b9447ec55e75987b0e8a&v=4 - url: https://github.com/svlandeg -- login: alexandercronin - count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/8014288?u=69580504c51a0cdd756fc47b23bb7f404bd694e7&v=4 - url: https://github.com/alexandercronin -- login: aanchlia - count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/2835374?u=3c3ed29aa8b09ccaf8d66def0ce82bc2f7e5aab6&v=4 - url: https://github.com/aanchlia -- login: chrisK824 - count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/79946379?u=03d85b22d696a58a9603e55fbbbe2de6b0f4face&v=4 - url: https://github.com/chrisK824 -- login: omarcruzpantoja - count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/15116058?u=4b64c643fad49225d854e1aaecd1ffc6f9071a1b&v=4 - url: https://github.com/omarcruzpantoja -- login: ahmedabdou14 - count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/104530599?u=d87b866e7c1db970d6f8e8031643818349b046d5&v=4 - url: https://github.com/ahmedabdou14 -- login: nbx3 +- login: jd-solanki count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/34649527?u=943812f69e0d40adbd3fa1c9b8ef50dd971a2a45&v=4 - url: https://github.com/nbx3 -- login: yanggeorge + avatarUrl: https://avatars.githubusercontent.com/u/47495003?u=6e225cb42c688d0cd70e65c6baedb9f5922b1178&v=4 + url: https://github.com/jd-solanki +- login: EverStarck count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/2434407?v=4 - url: https://github.com/yanggeorge -- login: XiaoXinYo + avatarUrl: https://avatars.githubusercontent.com/u/51029456?u=343409b7cb6b3ea6a59359f4e8370d9c3f140ecd&v=4 + url: https://github.com/EverStarck +- login: henrymcl count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/56395004?u=b3b7cb758997f283c271a581833e407229dab82c&v=4 - url: https://github.com/XiaoXinYo -- login: anantgupta129 + avatarUrl: https://avatars.githubusercontent.com/u/26480299?v=4 + url: https://github.com/henrymcl +- login: jymchng count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/66518357?u=6e25dcd84638f17d2c6df5dc26f07fd7c6dc118e&v=4 - url: https://github.com/anantgupta129 -- login: slafs + avatarUrl: https://avatars.githubusercontent.com/u/27895426?u=fb88c47775147d62a395fdb895d1af4148c7b566&v=4 + url: https://github.com/jymchng +- login: adsouza count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/210173?v=4 - url: https://github.com/slafs -- login: CarlosOliveira-23 + avatarUrl: https://avatars.githubusercontent.com/u/275832?v=4 + url: https://github.com/adsouza +- login: Synrom count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/102637302?u=cf350a4db956f30cbb2c27d3be0d15c282e32b14&v=4 - url: https://github.com/CarlosOliveira-23 -- login: monchin + avatarUrl: https://avatars.githubusercontent.com/u/30272537?v=4 + url: https://github.com/Synrom +- login: gaby count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/18521800?v=4 - url: https://github.com/monchin -- login: AmirHmZz + avatarUrl: https://avatars.githubusercontent.com/u/835733?u=8c72dec16fa560bdc81113354f2ffd79ad062bde&v=4 + url: https://github.com/gaby +- login: christiansicari count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/38752106?u=07f80e451bda00a9492bbc764e49d24ad3ada8cc&v=4 - url: https://github.com/AmirHmZz -- login: Leon0824 + avatarUrl: https://avatars.githubusercontent.com/u/29756552?v=4 + url: https://github.com/christiansicari +- login: Brikas count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/1922026?v=4 - url: https://github.com/Leon0824 + avatarUrl: https://avatars.githubusercontent.com/u/80290187?v=4 + url: https://github.com/Brikas +- login: JacobHayes + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/2555532?u=354a525847a276bbb4426b0c95791a8ba5970f9b&v=4 + url: https://github.com/JacobHayes +- login: rlimberger + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/4841242?u=6a13252caf3cedceb07b6e2775b6592445d13b70&v=4 + url: https://github.com/rlimberger - login: iloveitaly count: 2 avatarUrl: https://avatars.githubusercontent.com/u/150855?v=4 url: https://github.com/iloveitaly -- login: msukmanowsky +- login: iiotsrc count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/362755?u=782e6bf5b9f0356c3f74b4d894fda9f179252086&v=4 - url: https://github.com/msukmanowsky -- login: shurshilov + avatarUrl: https://avatars.githubusercontent.com/u/131771119?u=bcaf2559ef6266af70b151b7fda31a1ee3dbecb3&v=4 + url: https://github.com/iiotsrc +- login: AmirHmZz count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/11828278?u=6bcadc5ce4f2f56a514331c9f68eb987d4afe29a&v=4 - url: https://github.com/shurshilov -- login: LincolnPuzey + avatarUrl: https://avatars.githubusercontent.com/u/38752106?u=07f80e451bda00a9492bbc764e49d24ad3ada8cc&v=4 + url: https://github.com/AmirHmZz +- login: PidgeyBE count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/18750802?v=4 - url: https://github.com/LincolnPuzey + avatarUrl: https://avatars.githubusercontent.com/u/19860056?u=47b584eb1c1ab45e31c1b474109a962d7e82be49&v=4 + url: https://github.com/PidgeyBE diff --git a/docs/en/data/sponsors.yml b/docs/en/data/sponsors.yml index 4231452e4..2b3cd282d 100644 --- a/docs/en/data/sponsors.yml +++ b/docs/en/data/sponsors.yml @@ -5,26 +5,14 @@ gold: - url: https://platform.sh/try-it-now/?utm_source=fastapi-signup&utm_medium=banner&utm_campaign=FastAPI-signup-June-2023 title: "Build, run and scale your apps on a modern, reliable, and secure PaaS." img: https://fastapi.tiangolo.com/img/sponsors/platform-sh.png - - url: https://www.porter.run - title: Deploy FastAPI on AWS with a few clicks - img: https://fastapi.tiangolo.com/img/sponsors/porter.png - - url: https://bump.sh/fastapi?utm_source=fastapi&utm_medium=referral&utm_campaign=sponsor - title: Automate FastAPI documentation generation with Bump.sh - img: https://fastapi.tiangolo.com/img/sponsors/bump-sh.svg - url: https://github.com/scalar/scalar/?utm_source=fastapi&utm_medium=website&utm_campaign=main-badge title: "Scalar: Beautiful Open-Source API References from Swagger/OpenAPI files" img: https://fastapi.tiangolo.com/img/sponsors/scalar.svg - url: https://www.propelauth.com/?utm_source=fastapi&utm_campaign=1223&utm_medium=mainbadge title: Auth, user management and more for your B2B product img: https://fastapi.tiangolo.com/img/sponsors/propelauth.png - - url: https://www.withcoherence.com/?utm_medium=advertising&utm_source=fastapi&utm_campaign=website - title: Coherence - img: https://fastapi.tiangolo.com/img/sponsors/coherence.png - - url: https://www.mongodb.com/developer/languages/python/python-quickstart-fastapi/?utm_campaign=fastapi_framework&utm_source=fastapi_sponsorship&utm_medium=web_referral - title: Simplify Full Stack Development with FastAPI & MongoDB - img: https://fastapi.tiangolo.com/img/sponsors/mongodb.png - url: https://zuplo.link/fastapi-gh - title: 'Zuplo: Scale, Protect, Document, and Monetize your FastAPI' + title: 'Zuplo: Deploy, Secure, Document, and Monetize your FastAPI' img: https://fastapi.tiangolo.com/img/sponsors/zuplo.png - url: https://liblab.com?utm_source=fastapi title: liblab - Generate SDKs from FastAPI @@ -32,14 +20,23 @@ gold: - url: https://docs.render.com/deploy-fastapi?utm_source=deploydoc&utm_medium=referral&utm_campaign=fastapi title: Deploy & scale any full-stack web app on Render. Focus on building apps, not infra. img: https://fastapi.tiangolo.com/img/sponsors/render.svg + - url: https://www.coderabbit.ai/?utm_source=fastapi&utm_medium=badge&utm_campaign=fastapi + title: Cut Code Review Time & Bugs in Half with CodeRabbit + img: https://fastapi.tiangolo.com/img/sponsors/coderabbit.png + - url: https://subtotal.com/?utm_source=fastapi&utm_medium=sponsorship&utm_campaign=open-source + title: The Gold Standard in Retail Account Linking + img: https://fastapi.tiangolo.com/img/sponsors/subtotal.svg + - url: https://vibe.mobb.ai/?utm_source=Fast+APi&utm_medium=Image&utm_campaign=MVS + title: Secure Your AI-Generated Code to Unlock Dev Productivity + img: https://fastapi.tiangolo.com/img/sponsors/mobbai.png + - url: https://docs.railway.com/guides/fastapi?utm_medium=integration&utm_source=docs&utm_campaign=fastapi + title: Deploy enterprise applications at startup speed + img: https://fastapi.tiangolo.com/img/sponsors/railway.png silver: - - url: https://github.com/deepset-ai/haystack/ - title: Build powerful search from composable, open source building blocks - img: https://fastapi.tiangolo.com/img/sponsors/haystack-fastapi.svg - - url: https://databento.com/ + - url: https://databento.com/?utm_source=fastapi&utm_medium=sponsor&utm_content=display title: Pay as you go for market data img: https://fastapi.tiangolo.com/img/sponsors/databento.svg - - url: https://speakeasy.com?utm_source=fastapi+repo&utm_medium=github+sponsorship + - url: https://speakeasy.com/editor?utm_source=fastapi+repo&utm_medium=github+sponsorship title: SDKs for your API | Speakeasy img: https://fastapi.tiangolo.com/img/sponsors/speakeasy.png - url: https://www.svix.com/ @@ -48,10 +45,22 @@ silver: - url: https://www.stainlessapi.com/?utm_source=fastapi&utm_medium=referral title: Stainless | Generate best-in-class SDKs img: https://fastapi.tiangolo.com/img/sponsors/stainless.png + - url: https://www.permit.io/blog/implement-authorization-in-fastapi?utm_source=github&utm_medium=referral&utm_campaign=fastapi + title: Fine-Grained Authorization for FastAPI + img: https://fastapi.tiangolo.com/img/sponsors/permit.png + - url: https://www.interviewpal.com/?utm_source=fastapi&utm_medium=open-source&utm_campaign=dev-hiring + title: InterviewPal - AI Interview Coach for Engineers and Devs + img: https://fastapi.tiangolo.com/img/sponsors/interviewpal.png + - url: https://dribia.com/en/ + title: Dribia - Data Science within your reach + img: https://fastapi.tiangolo.com/img/sponsors/dribia.png bronze: - url: https://www.exoflare.com/open-source/?utm_source=FastAPI&utm_campaign=open_source title: Biosecurity risk assessments made easy. img: https://fastapi.tiangolo.com/img/sponsors/exoflare.png - - url: https://testdriven.io/courses/tdd-fastapi/ - title: Learn to build high-quality web apps with best practices - img: https://fastapi.tiangolo.com/img/sponsors/testdriven.svg + # - url: https://testdriven.io/courses/tdd-fastapi/ + # title: Learn to build high-quality web apps with best practices + # img: https://fastapi.tiangolo.com/img/sponsors/testdriven.svg + - url: https://lambdatest.com/?utm_source=fastapi&utm_medium=partner&utm_campaign=sponsor&utm_term=opensource&utm_content=webpage + title: LambdaTest, AI-Powered Cloud-based Test Orchestration Platform + img: https://fastapi.tiangolo.com/img/sponsors/lambdatest.png diff --git a/docs/en/data/sponsors_badge.yml b/docs/en/data/sponsors_badge.yml index d507a500f..62ba6a84c 100644 --- a/docs/en/data/sponsors_badge.yml +++ b/docs/en/data/sponsors_badge.yml @@ -38,3 +38,11 @@ logins: - render-sponsorships - renderinc - stainless-api + - snapit-cypher + - coderabbitai + - permitio + - LambdaTest-Inc + - dribia + - madisonredtfeldt + - railwayapp + - subtotal diff --git a/docs/en/data/topic_repos.yml b/docs/en/data/topic_repos.yml index c1176e55c..631edbb77 100644 --- a/docs/en/data/topic_repos.yml +++ b/docs/en/data/topic_repos.yml @@ -1,495 +1,495 @@ - name: full-stack-fastapi-template html_url: https://github.com/fastapi/full-stack-fastapi-template - stars: 28796 + stars: 35002 owner_login: fastapi owner_html_url: https://github.com/fastapi - name: Hello-Python html_url: https://github.com/mouredev/Hello-Python - stars: 27554 + stars: 31317 owner_login: mouredev owner_html_url: https://github.com/mouredev - name: serve html_url: https://github.com/jina-ai/serve - stars: 21225 + stars: 21680 owner_login: jina-ai owner_html_url: https://github.com/jina-ai -- name: sqlmodel - html_url: https://github.com/fastapi/sqlmodel - stars: 14921 - owner_login: fastapi - owner_html_url: https://github.com/fastapi - name: HivisionIDPhotos html_url: https://github.com/Zeyi-Lin/HivisionIDPhotos - stars: 14025 + stars: 18700 owner_login: Zeyi-Lin owner_html_url: https://github.com/Zeyi-Lin +- name: sqlmodel + html_url: https://github.com/fastapi/sqlmodel + stars: 16469 + 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: 10001 + stars: 13663 owner_login: Evil0ctal owner_html_url: https://github.com/Evil0ctal - name: fastapi-best-practices html_url: https://github.com/zhanymkanov/fastapi-best-practices - stars: 9820 + stars: 12716 owner_login: zhanymkanov owner_html_url: https://github.com/zhanymkanov - name: awesome-fastapi html_url: https://github.com/mjhea0/awesome-fastapi - stars: 8899 + stars: 10099 owner_login: mjhea0 owner_html_url: https://github.com/mjhea0 - name: FastUI html_url: https://github.com/pydantic/FastUI - stars: 8400 + stars: 8850 owner_login: pydantic owner_html_url: https://github.com/pydantic +- name: XHS-Downloader + html_url: https://github.com/JoeanAmier/XHS-Downloader + stars: 8305 + owner_login: JoeanAmier + owner_html_url: https://github.com/JoeanAmier +- name: FileCodeBox + html_url: https://github.com/vastsa/FileCodeBox + stars: 6936 + owner_login: vastsa + owner_html_url: https://github.com/vastsa - name: nonebot2 html_url: https://github.com/nonebot/nonebot2 - stars: 6235 + stars: 6911 owner_login: nonebot owner_html_url: https://github.com/nonebot +- name: fastapi_mcp + html_url: https://github.com/tadata-org/fastapi_mcp + stars: 6767 + owner_login: tadata-org + owner_html_url: https://github.com/tadata-org +- name: SurfSense + html_url: https://github.com/MODSetter/SurfSense + stars: 6202 + owner_login: MODSetter + owner_html_url: https://github.com/MODSetter +- name: hatchet + html_url: https://github.com/hatchet-dev/hatchet + stars: 5878 + owner_login: hatchet-dev + owner_html_url: https://github.com/hatchet-dev +- name: polar + html_url: https://github.com/polarsource/polar + stars: 5872 + owner_login: polarsource + owner_html_url: https://github.com/polarsource - name: serge html_url: https://github.com/serge-chat/serge - stars: 5685 + stars: 5740 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: 4787 + stars: 5429 owner_login: fastapi-users owner_html_url: https://github.com/fastapi-users -- name: FileCodeBox - html_url: https://github.com/vastsa/FileCodeBox - stars: 4479 - owner_login: vastsa - owner_html_url: https://github.com/vastsa -- name: hatchet - html_url: https://github.com/hatchet-dev/hatchet - stars: 4413 - owner_login: hatchet-dev - owner_html_url: https://github.com/hatchet-dev +- name: strawberry + html_url: https://github.com/strawberry-graphql/strawberry + stars: 4345 + 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: 4322 + stars: 4301 owner_login: chatpire owner_html_url: https://github.com/chatpire +- name: poem + html_url: https://github.com/poem-web/poem + stars: 4107 + owner_login: poem-web + owner_html_url: https://github.com/poem-web - name: atrilabs-engine html_url: https://github.com/Atri-Labs/atrilabs-engine - stars: 4115 + stars: 4103 owner_login: Atri-Labs owner_html_url: https://github.com/Atri-Labs -- name: strawberry - html_url: https://github.com/strawberry-graphql/strawberry - stars: 4084 - owner_login: strawberry-graphql - owner_html_url: https://github.com/strawberry-graphql - name: dynaconf html_url: https://github.com/dynaconf/dynaconf - stars: 3844 + stars: 4079 owner_login: dynaconf owner_html_url: https://github.com/dynaconf -- name: poem - html_url: https://github.com/poem-web/poem - stars: 3698 - owner_login: poem-web - owner_html_url: https://github.com/poem-web -- name: polar - html_url: https://github.com/polarsource/polar - stars: 3355 - owner_login: polarsource - owner_html_url: https://github.com/polarsource -- name: opyrator - html_url: https://github.com/ml-tooling/opyrator - stars: 3114 - owner_login: ml-tooling - owner_html_url: https://github.com/ml-tooling +- name: LitServe + html_url: https://github.com/Lightning-AI/LitServe + stars: 3430 + owner_login: Lightning-AI + owner_html_url: https://github.com/Lightning-AI +- name: logfire + html_url: https://github.com/pydantic/logfire + stars: 3420 + owner_login: pydantic + owner_html_url: https://github.com/pydantic - name: farfalle html_url: https://github.com/rashadphz/farfalle - stars: 3022 + stars: 3391 owner_login: rashadphz owner_html_url: https://github.com/rashadphz +- name: Kokoro-FastAPI + html_url: https://github.com/remsky/Kokoro-FastAPI + stars: 3375 + owner_login: remsky + owner_html_url: https://github.com/remsky +- name: datamodel-code-generator + html_url: https://github.com/koxudaxi/datamodel-code-generator + stars: 3354 + owner_login: koxudaxi + owner_html_url: https://github.com/koxudaxi - name: fastapi-admin html_url: https://github.com/fastapi-admin/fastapi-admin - stars: 3002 + stars: 3353 owner_login: fastapi-admin owner_html_url: https://github.com/fastapi-admin +- name: huma + html_url: https://github.com/danielgtaylor/huma + stars: 3277 + owner_login: danielgtaylor + owner_html_url: https://github.com/danielgtaylor +- name: opyrator + html_url: https://github.com/ml-tooling/opyrator + stars: 3131 + owner_login: ml-tooling + owner_html_url: https://github.com/ml-tooling - name: docarray html_url: https://github.com/docarray/docarray - stars: 2998 + stars: 3085 owner_login: docarray owner_html_url: https://github.com/docarray -- name: datamodel-code-generator - html_url: https://github.com/koxudaxi/datamodel-code-generator - stars: 2845 - owner_login: koxudaxi - owner_html_url: https://github.com/koxudaxi +- name: tracecat + html_url: https://github.com/TracecatHQ/tracecat + stars: 2921 + owner_login: TracecatHQ + owner_html_url: https://github.com/TracecatHQ - name: fastapi-realworld-example-app html_url: https://github.com/nsidnev/fastapi-realworld-example-app - stars: 2832 + stars: 2919 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: 2727 + stars: 2789 owner_login: tiangolo owner_html_url: https://github.com/tiangolo -- name: WrenAI - html_url: https://github.com/Canner/WrenAI - stars: 2699 - owner_login: Canner - owner_html_url: https://github.com/Canner -- name: LitServe - html_url: https://github.com/Lightning-AI/LitServe - stars: 2664 - owner_login: Lightning-AI - owner_html_url: https://github.com/Lightning-AI -- name: logfire - html_url: https://github.com/pydantic/logfire - stars: 2495 - owner_login: pydantic - owner_html_url: https://github.com/pydantic -- name: huma - html_url: https://github.com/danielgtaylor/huma - stars: 2479 - owner_login: danielgtaylor - owner_html_url: https://github.com/danielgtaylor -- name: tracecat - html_url: https://github.com/TracecatHQ/tracecat - stars: 2446 - owner_login: TracecatHQ - owner_html_url: https://github.com/TracecatHQ -- name: RasaGPT - html_url: https://github.com/paulpierre/RasaGPT - stars: 2378 - owner_login: paulpierre - owner_html_url: https://github.com/paulpierre - name: best-of-web-python html_url: https://github.com/ml-tooling/best-of-web-python - stars: 2374 + stars: 2560 owner_login: ml-tooling owner_html_url: https://github.com/ml-tooling +- name: RasaGPT + html_url: https://github.com/paulpierre/RasaGPT + stars: 2434 + owner_login: paulpierre + owner_html_url: https://github.com/paulpierre - name: fastapi-react html_url: https://github.com/Buuntu/fastapi-react - stars: 2274 + stars: 2419 owner_login: Buuntu owner_html_url: https://github.com/Buuntu +- name: FastAPI-template + html_url: https://github.com/s3rius/FastAPI-template + stars: 2369 + owner_login: s3rius + owner_html_url: https://github.com/s3rius - name: nextpy html_url: https://github.com/dot-agent/nextpy - stars: 2244 + stars: 2304 owner_login: dot-agent owner_html_url: https://github.com/dot-agent +- name: sqladmin + html_url: https://github.com/aminalaee/sqladmin + stars: 2272 + owner_login: aminalaee + owner_html_url: https://github.com/aminalaee - name: 30-Days-of-Python html_url: https://github.com/codingforentrepreneurs/30-Days-of-Python - stars: 2154 + stars: 2192 owner_login: codingforentrepreneurs owner_html_url: https://github.com/codingforentrepreneurs -- name: FastAPI-template - html_url: https://github.com/s3rius/FastAPI-template - stars: 2067 - owner_login: s3rius - owner_html_url: https://github.com/s3rius +- name: supabase-py + html_url: https://github.com/supabase/supabase-py + stars: 2141 + owner_login: supabase + owner_html_url: https://github.com/supabase - name: langserve html_url: https://github.com/langchain-ai/langserve - stars: 1980 + stars: 2140 owner_login: langchain-ai owner_html_url: https://github.com/langchain-ai -- name: sqladmin - html_url: https://github.com/aminalaee/sqladmin - stars: 1980 - owner_login: aminalaee - owner_html_url: https://github.com/aminalaee - name: fastapi-utils html_url: https://github.com/fastapiutils/fastapi-utils - stars: 1970 + stars: 2107 owner_login: fastapiutils owner_html_url: https://github.com/fastapiutils - name: solara html_url: https://github.com/widgetti/solara - stars: 1950 + stars: 2063 owner_login: widgetti owner_html_url: https://github.com/widgetti -- name: python-week-2022 - html_url: https://github.com/rochacbruno/python-week-2022 - stars: 1836 - owner_login: rochacbruno - owner_html_url: https://github.com/rochacbruno -- name: supabase-py - html_url: https://github.com/supabase/supabase-py - stars: 1803 - owner_login: supabase - owner_html_url: https://github.com/supabase - name: mangum html_url: https://github.com/Kludex/mangum - stars: 1760 + stars: 1943 owner_login: Kludex owner_html_url: https://github.com/Kludex +- name: python-week-2022 + html_url: https://github.com/rochacbruno/python-week-2022 + stars: 1819 + owner_login: rochacbruno + owner_html_url: https://github.com/rochacbruno +- name: agentkit + html_url: https://github.com/BCG-X-Official/agentkit + stars: 1774 + 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: 1704 + stars: 1769 owner_login: ycd owner_html_url: https://github.com/ycd - name: ormar html_url: https://github.com/collerek/ormar - stars: 1688 + stars: 1761 owner_login: collerek owner_html_url: https://github.com/collerek -- name: agentkit - html_url: https://github.com/BCG-X-Official/agentkit - stars: 1615 - owner_login: BCG-X-Official - owner_html_url: https://github.com/BCG-X-Official +- name: piccolo + html_url: https://github.com/piccolo-orm/piccolo + stars: 1658 + owner_login: piccolo-orm + owner_html_url: https://github.com/piccolo-orm - name: langchain-serve html_url: https://github.com/jina-ai/langchain-serve - stars: 1615 + stars: 1632 owner_login: jina-ai owner_html_url: https://github.com/jina-ai +- name: openapi-python-client + html_url: https://github.com/openapi-generators/openapi-python-client + stars: 1628 + owner_login: openapi-generators + owner_html_url: https://github.com/openapi-generators - name: termpair html_url: https://github.com/cs01/termpair - stars: 1613 + stars: 1617 owner_login: cs01 owner_html_url: https://github.com/cs01 +- name: fastapi-cache + html_url: https://github.com/long2ice/fastapi-cache + stars: 1607 + owner_login: long2ice + owner_html_url: https://github.com/long2ice - name: coronavirus-tracker-api html_url: https://github.com/ExpDev07/coronavirus-tracker-api - stars: 1591 + stars: 1580 owner_login: ExpDev07 owner_html_url: https://github.com/ExpDev07 -- name: piccolo - html_url: https://github.com/piccolo-orm/piccolo - stars: 1477 - owner_login: piccolo-orm - owner_html_url: https://github.com/piccolo-orm +- name: slowapi + html_url: https://github.com/laurentS/slowapi + stars: 1551 + owner_login: laurentS + owner_html_url: https://github.com/laurentS - name: fastapi-crudrouter html_url: https://github.com/awtkns/fastapi-crudrouter - stars: 1435 + stars: 1522 owner_login: awtkns owner_html_url: https://github.com/awtkns -- name: fastapi-cache - html_url: https://github.com/long2ice/fastapi-cache - stars: 1412 - owner_login: long2ice - owner_html_url: https://github.com/long2ice -- name: openapi-python-client - html_url: https://github.com/openapi-generators/openapi-python-client - stars: 1398 - owner_login: openapi-generators - owner_html_url: https://github.com/openapi-generators +- name: vue-fastapi-admin + html_url: https://github.com/mizhexiaoxiao/vue-fastapi-admin + stars: 1505 + owner_login: mizhexiaoxiao + owner_html_url: https://github.com/mizhexiaoxiao - name: awesome-fastapi-projects html_url: https://github.com/Kludex/awesome-fastapi-projects - stars: 1386 + stars: 1468 owner_login: Kludex owner_html_url: https://github.com/Kludex - name: awesome-python-resources html_url: https://github.com/DjangoEx/awesome-python-resources - stars: 1371 + stars: 1403 owner_login: DjangoEx owner_html_url: https://github.com/DjangoEx -- name: budgetml - html_url: https://github.com/ebhy/budgetml - stars: 1342 - owner_login: ebhy - owner_html_url: https://github.com/ebhy -- name: slowapi - html_url: https://github.com/laurentS/slowapi - stars: 1289 - owner_login: laurentS - owner_html_url: https://github.com/laurentS - name: fastapi-pagination html_url: https://github.com/uriyyo/fastapi-pagination - stars: 1240 + stars: 1396 owner_login: uriyyo owner_html_url: https://github.com/uriyyo +- name: FastAPI-boilerplate + html_url: https://github.com/benavlabs/FastAPI-boilerplate + stars: 1378 + owner_login: benavlabs + owner_html_url: https://github.com/benavlabs - name: fastapi-boilerplate html_url: https://github.com/teamhide/fastapi-boilerplate - stars: 1173 + stars: 1373 owner_login: teamhide owner_html_url: https://github.com/teamhide -- name: fastapi-tutorial - html_url: https://github.com/liaogx/fastapi-tutorial - stars: 1162 - owner_login: liaogx - owner_html_url: https://github.com/liaogx +- name: bracket + html_url: https://github.com/evroon/bracket + stars: 1367 + owner_login: evroon + owner_html_url: https://github.com/evroon +- name: budgetml + html_url: https://github.com/ebhy/budgetml + stars: 1345 + owner_login: ebhy + owner_html_url: https://github.com/ebhy - name: fastapi-amis-admin html_url: https://github.com/amisadmin/fastapi-amis-admin - stars: 1118 + stars: 1300 owner_login: amisadmin owner_html_url: https://github.com/amisadmin +- name: fastapi-tutorial + html_url: https://github.com/liaogx/fastapi-tutorial + stars: 1284 + owner_login: liaogx + owner_html_url: https://github.com/liaogx - name: fastapi-code-generator html_url: https://github.com/koxudaxi/fastapi-code-generator - stars: 1095 + stars: 1232 owner_login: koxudaxi owner_html_url: https://github.com/koxudaxi +- name: fastcrud + html_url: https://github.com/benavlabs/fastcrud + stars: 1208 + owner_login: benavlabs + owner_html_url: https://github.com/benavlabs +- name: prometheus-fastapi-instrumentator + html_url: https://github.com/trallnag/prometheus-fastapi-instrumentator + stars: 1200 + owner_login: trallnag + owner_html_url: https://github.com/trallnag - name: bolt-python html_url: https://github.com/slackapi/bolt-python - stars: 1086 + stars: 1197 owner_login: slackapi owner_html_url: https://github.com/slackapi -- name: odmantic - html_url: https://github.com/art049/odmantic - stars: 1085 - owner_login: art049 - owner_html_url: https://github.com/art049 -- name: langchain-extract - html_url: https://github.com/langchain-ai/langchain-extract - stars: 1068 - owner_login: langchain-ai - owner_html_url: https://github.com/langchain-ai +- name: bedrock-chat + html_url: https://github.com/aws-samples/bedrock-chat + stars: 1188 + owner_login: aws-samples + owner_html_url: https://github.com/aws-samples +- name: fastapi_best_architecture + html_url: https://github.com/fastapi-practices/fastapi_best_architecture + stars: 1178 + owner_login: fastapi-practices + owner_html_url: https://github.com/fastapi-practices - name: fastapi_production_template html_url: https://github.com/zhanymkanov/fastapi_production_template - stars: 1059 + stars: 1173 owner_login: zhanymkanov owner_html_url: https://github.com/zhanymkanov +- name: langchain-extract + html_url: https://github.com/langchain-ai/langchain-extract + stars: 1148 + owner_login: langchain-ai + owner_html_url: https://github.com/langchain-ai - name: fastapi-alembic-sqlmodel-async html_url: https://github.com/jonra1993/fastapi-alembic-sqlmodel-async - stars: 1031 + stars: 1134 owner_login: jonra1993 owner_html_url: https://github.com/jonra1993 -- name: prometheus-fastapi-instrumentator - html_url: https://github.com/trallnag/prometheus-fastapi-instrumentator - stars: 1013 - owner_login: trallnag - owner_html_url: https://github.com/trallnag +- name: odmantic + html_url: https://github.com/art049/odmantic + stars: 1122 + owner_login: art049 + owner_html_url: https://github.com/art049 +- name: restish + html_url: https://github.com/rest-sh/restish + stars: 1088 + owner_login: rest-sh + owner_html_url: https://github.com/rest-sh +- name: fastapi-scaf + html_url: https://github.com/atpuxiner/fastapi-scaf + stars: 1061 + owner_login: atpuxiner + owner_html_url: https://github.com/atpuxiner - name: runhouse html_url: https://github.com/run-house/runhouse - stars: 988 + stars: 1041 owner_login: run-house owner_html_url: https://github.com/run-house +- name: fastapi-langgraph-agent-production-ready-template + html_url: https://github.com/wassim249/fastapi-langgraph-agent-production-ready-template + stars: 1037 + owner_login: wassim249 + owner_html_url: https://github.com/wassim249 +- name: autollm + html_url: https://github.com/viddexa/autollm + stars: 997 + owner_login: viddexa + owner_html_url: https://github.com/viddexa - name: lanarky html_url: https://github.com/ajndkr/lanarky - stars: 982 + stars: 994 owner_login: ajndkr owner_html_url: https://github.com/ajndkr -- name: autollm - html_url: https://github.com/viddexa/autollm +- name: mcp-context-forge + html_url: https://github.com/IBM/mcp-context-forge stars: 981 - owner_login: viddexa - owner_html_url: https://github.com/viddexa -- name: bedrock-claude-chat - html_url: https://github.com/aws-samples/bedrock-claude-chat - stars: 977 - owner_login: aws-samples - owner_html_url: https://github.com/aws-samples -- name: SurfSense - html_url: https://github.com/MODSetter/SurfSense - stars: 971 - owner_login: MODSetter - owner_html_url: https://github.com/MODSetter -- name: restish - html_url: https://github.com/danielgtaylor/restish - stars: 954 - owner_login: danielgtaylor - owner_html_url: https://github.com/danielgtaylor + owner_login: IBM + owner_html_url: https://github.com/IBM +- name: authx + html_url: https://github.com/yezz123/authx + stars: 967 + owner_login: yezz123 + owner_html_url: https://github.com/yezz123 - name: secure html_url: https://github.com/TypeError/secure - stars: 911 + stars: 941 owner_login: TypeError owner_html_url: https://github.com/TypeError -- name: langcorn - html_url: https://github.com/msoedov/langcorn - stars: 909 - owner_login: msoedov - owner_html_url: https://github.com/msoedov +- name: flock + html_url: https://github.com/Onelevenvy/flock + stars: 937 + owner_login: Onelevenvy + owner_html_url: https://github.com/Onelevenvy - name: energy-forecasting html_url: https://github.com/iusztinpaul/energy-forecasting - stars: 884 + stars: 934 owner_login: iusztinpaul owner_html_url: https://github.com/iusztinpaul -- name: vue-fastapi-admin - html_url: https://github.com/mizhexiaoxiao/vue-fastapi-admin - stars: 863 - owner_login: mizhexiaoxiao - owner_html_url: https://github.com/mizhexiaoxiao -- name: authx - html_url: https://github.com/yezz123/authx - stars: 850 - owner_login: yezz123 - owner_html_url: https://github.com/yezz123 +- name: langcorn + html_url: https://github.com/msoedov/langcorn + stars: 932 + owner_login: msoedov + owner_html_url: https://github.com/msoedov - name: titiler html_url: https://github.com/developmentseed/titiler - stars: 809 + stars: 917 owner_login: developmentseed owner_html_url: https://github.com/developmentseed - name: marker-api html_url: https://github.com/adithya-s-k/marker-api - stars: 792 + stars: 880 owner_login: adithya-s-k owner_html_url: https://github.com/adithya-s-k -- name: fastapi_best_architecture - html_url: https://github.com/fastapi-practices/fastapi_best_architecture - stars: 742 - owner_login: fastapi-practices - owner_html_url: https://github.com/fastapi-practices -- name: fastapi-mail - html_url: https://github.com/sabuhish/fastapi-mail - stars: 728 - owner_login: sabuhish - owner_html_url: https://github.com/sabuhish -- name: fastcrud - html_url: https://github.com/igorbenav/fastcrud - stars: 727 - owner_login: igorbenav - owner_html_url: https://github.com/igorbenav -- name: annotated-py-projects - html_url: https://github.com/hhstore/annotated-py-projects - stars: 722 - owner_login: hhstore - owner_html_url: https://github.com/hhstore -- name: FastAPI-boilerplate - html_url: https://github.com/igorbenav/FastAPI-boilerplate - stars: 716 - owner_login: igorbenav - owner_html_url: https://github.com/igorbenav -- name: lccn_predictor - html_url: https://github.com/baoliay2008/lccn_predictor - stars: 707 - owner_login: baoliay2008 - owner_html_url: https://github.com/baoliay2008 -- name: chatGPT-web - html_url: https://github.com/mic1on/chatGPT-web - stars: 706 - owner_login: mic1on - owner_html_url: https://github.com/mic1on +- name: httpdbg + html_url: https://github.com/cle-b/httpdbg + stars: 875 + 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: 702 + stars: 873 owner_login: dunossauro owner_html_url: https://github.com/dunossauro -- name: linbing - html_url: https://github.com/taomujian/linbing - stars: 699 - owner_login: taomujian - owner_html_url: https://github.com/taomujian - name: fastapi-observability html_url: https://github.com/blueswen/fastapi-observability - stars: 698 + stars: 861 owner_login: blueswen owner_html_url: https://github.com/blueswen -- name: FastAPI-Backend-Template - html_url: https://github.com/Aeternalis-Ingenium/FastAPI-Backend-Template - stars: 682 - owner_login: Aeternalis-Ingenium - owner_html_url: https://github.com/Aeternalis-Ingenium -- name: learn-generative-ai - html_url: https://github.com/panaverse/learn-generative-ai - stars: 673 - owner_login: panaverse - owner_html_url: https://github.com/panaverse -- name: fastapi-jwt-auth - html_url: https://github.com/IndominusByte/fastapi-jwt-auth - stars: 668 - owner_login: IndominusByte - owner_html_url: https://github.com/IndominusByte -- name: pity - html_url: https://github.com/wuranxu/pity - stars: 660 - owner_login: wuranxu - owner_html_url: https://github.com/wuranxu -- name: starlette-admin - html_url: https://github.com/jowilf/starlette-admin - stars: 653 - owner_login: jowilf - owner_html_url: https://github.com/jowilf -- name: fastapi_login - html_url: https://github.com/MushroomMaula/fastapi_login - stars: 650 - owner_login: MushroomMaula - owner_html_url: https://github.com/MushroomMaula +- name: ludic + html_url: https://github.com/getludic/ludic + stars: 854 + owner_login: getludic + owner_html_url: https://github.com/getludic +- name: aktools + html_url: https://github.com/akfamily/aktools + stars: 839 + owner_login: akfamily + owner_html_url: https://github.com/akfamily +- name: RuoYi-Vue3-FastAPI + html_url: https://github.com/insistence/RuoYi-Vue3-FastAPI + stars: 836 + owner_login: insistence + owner_html_url: https://github.com/insistence diff --git a/docs/en/data/translation_reviewers.yml b/docs/en/data/translation_reviewers.yml index 6cc09a7c1..8eaf93d9c 100644 --- a/docs/en/data/translation_reviewers.yml +++ b/docs/en/data/translation_reviewers.yml @@ -5,12 +5,17 @@ s111d: url: https://github.com/s111d Xewus: login: Xewus - count: 139 + count: 140 avatarUrl: https://avatars.githubusercontent.com/u/85196001?u=f8e2dc7e5104f109cef944af79050ea8d1b8f914&v=4 url: https://github.com/Xewus +sodaMelon: + login: sodaMelon + count: 127 + avatarUrl: https://avatars.githubusercontent.com/u/66295123?u=be939db90f1119efee9e6110cc05066ff1f40f00&v=4 + url: https://github.com/sodaMelon ceb10n: login: ceb10n - count: 108 + count: 116 avatarUrl: https://avatars.githubusercontent.com/u/235213?u=edcce471814a1eba9f0cdaa4cd0de18921a940a6&v=4 url: https://github.com/ceb10n tokusumi: @@ -25,24 +30,24 @@ hasansezertasan: url: https://github.com/hasansezertasan hard-coders: login: hard-coders - count: 92 + count: 93 avatarUrl: https://avatars.githubusercontent.com/u/9651103?u=95db33927bbff1ed1c07efddeb97ac2ff33068ed&v=4 url: https://github.com/hard-coders +alv2017: + login: alv2017 + count: 88 + avatarUrl: https://avatars.githubusercontent.com/u/31544722?v=4 + url: https://github.com/alv2017 +nazarepiedady: + login: nazarepiedady + count: 86 + avatarUrl: https://avatars.githubusercontent.com/u/31008635?u=f69ddc4ea8bda3bdfac7aa0e2ea38de282e6ee2d&v=4 + url: https://github.com/nazarepiedady AlertRED: login: AlertRED count: 81 avatarUrl: https://avatars.githubusercontent.com/u/15695000?u=f5a4944c6df443030409c88da7d7fa0b7ead985c&v=4 url: https://github.com/AlertRED -sodaMelon: - login: sodaMelon - count: 81 - avatarUrl: https://avatars.githubusercontent.com/u/66295123?u=be939db90f1119efee9e6110cc05066ff1f40f00&v=4 - url: https://github.com/sodaMelon -nazarepiedady: - login: nazarepiedady - count: 78 - avatarUrl: https://avatars.githubusercontent.com/u/31008635?u=8dc25777dc9cb51fb0dbba2f137988953d330b78&v=4 - url: https://github.com/nazarepiedady Alexandrhub: login: Alexandrhub count: 68 @@ -55,14 +60,19 @@ waynerv: url: https://github.com/waynerv cassiobotaro: login: cassiobotaro - count: 61 + count: 62 avatarUrl: https://avatars.githubusercontent.com/u/3127847?u=a08022b191ddbd0a6159b2981d9d878b6d5bb71f&v=4 url: https://github.com/cassiobotaro mattwang44: login: mattwang44 - count: 58 + count: 59 avatarUrl: https://avatars.githubusercontent.com/u/24987826?u=58e37fb3927b9124b458945ac4c97aa0f1062d85&v=4 url: https://github.com/mattwang44 +tiangolo: + login: tiangolo + count: 53 + avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 + url: https://github.com/tiangolo Laineyzhang55: login: Laineyzhang55 count: 48 @@ -78,16 +88,26 @@ komtaki: count: 45 avatarUrl: https://avatars.githubusercontent.com/u/39375566?u=260ad6b1a4b34c07dbfa728da5e586f16f6d1824&v=4 url: https://github.com/komtaki +rostik1410: + login: rostik1410 + count: 42 + avatarUrl: https://avatars.githubusercontent.com/u/11443899?u=e26a635c2ba220467b308a326a579b8ccf4a8701&v=4 + url: https://github.com/rostik1410 +svlandeg: + login: svlandeg + count: 42 + avatarUrl: https://avatars.githubusercontent.com/u/8796347?u=556c97650c27021911b0b9447ec55e75987b0e8a&v=4 + url: https://github.com/svlandeg alperiox: login: alperiox count: 42 avatarUrl: https://avatars.githubusercontent.com/u/34214152?u=2c5acad3461d4dbc2d48371ba86cac56ae9b25cc&v=4 url: https://github.com/alperiox -tiangolo: - login: tiangolo - count: 40 - avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 - url: https://github.com/tiangolo +Rishat-F: + login: Rishat-F + count: 42 + avatarUrl: https://avatars.githubusercontent.com/u/66554797?v=4 + url: https://github.com/Rishat-F Winand: login: Winand count: 40 @@ -103,6 +123,11 @@ JavierSanchezCastro: count: 38 avatarUrl: https://avatars.githubusercontent.com/u/72013291?u=ae5679e6bd971d9d98cd5e76e8683f83642ba950&v=4 url: https://github.com/JavierSanchezCastro +alejsdev: + login: alejsdev + count: 37 + avatarUrl: https://avatars.githubusercontent.com/u/90076947?u=638c65283ac9e9e2c3a0f9d1e3370db4b8a2c58d&v=4 + url: https://github.com/alejsdev stlucasgarcia: login: stlucasgarcia count: 36 @@ -113,11 +138,21 @@ SwftAlpc: count: 36 avatarUrl: https://avatars.githubusercontent.com/u/52768429?u=6a3aa15277406520ad37f6236e89466ed44bc5b8&v=4 url: https://github.com/SwftAlpc +timothy-jeong: + login: timothy-jeong + count: 36 + avatarUrl: https://avatars.githubusercontent.com/u/53824764?u=db3d0cea2f5fab64d810113c5039a369699a2774&v=4 + url: https://github.com/timothy-jeong nilslindemann: login: nilslindemann count: 35 avatarUrl: https://avatars.githubusercontent.com/u/6892179?u=1dca6a22195d6cd1ab20737c0e19a4c55d639472&v=4 url: https://github.com/nilslindemann +mezgoodle: + login: mezgoodle + count: 35 + avatarUrl: https://avatars.githubusercontent.com/u/41520940?u=4a9c765af688389d54296845d18b8f6cd6ddf09a&v=4 + url: https://github.com/mezgoodle rjNemo: login: rjNemo count: 34 @@ -138,26 +173,21 @@ romashevchenko: count: 32 avatarUrl: https://avatars.githubusercontent.com/u/132477732?v=4 url: https://github.com/romashevchenko -wdh99: - login: wdh99 - count: 31 - avatarUrl: https://avatars.githubusercontent.com/u/108172295?u=8a8fb95d5afe3e0fa33257b2aecae88d436249eb&v=4 - url: https://github.com/wdh99 -alv2017: - login: alv2017 - count: 31 - avatarUrl: https://avatars.githubusercontent.com/u/31544722?v=4 - url: https://github.com/alv2017 LorhanSohaky: login: LorhanSohaky count: 30 avatarUrl: https://avatars.githubusercontent.com/u/16273730?u=095b66f243a2cd6a0aadba9a095009f8aaf18393&v=4 url: https://github.com/LorhanSohaky -alejsdev: - login: alejsdev +YuriiMotov: + login: YuriiMotov count: 30 - avatarUrl: https://avatars.githubusercontent.com/u/90076947?u=356f39ff3f0211c720b06d3dbb060e98884085e3&v=4 - url: https://github.com/alejsdev + avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=b9b13d598dddfab529a52d264df80a900bfe7060&v=4 + url: https://github.com/YuriiMotov +Vincy1230: + login: Vincy1230 + count: 30 + avatarUrl: https://avatars.githubusercontent.com/u/81342412?u=ab5e256a4077a4a91f3f9cd2115ba80780454cbe&v=4 + url: https://github.com/Vincy1230 black-redoc: login: black-redoc count: 29 @@ -181,7 +211,7 @@ dedkot01: hsuanchi: login: hsuanchi count: 28 - avatarUrl: https://avatars.githubusercontent.com/u/24913710?u=0b094ae292292fee093818e37ceb645c114d2bff&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/24913710?u=7d25a398e478b6e63503bf6f26c54efa9e0da07b&v=4 url: https://github.com/hsuanchi dpinezich: login: dpinezich @@ -208,11 +238,6 @@ junah201: count: 26 avatarUrl: https://avatars.githubusercontent.com/u/75025529?u=2451c256e888fa2a06bcfc0646d09b87ddb6a945&v=4 url: https://github.com/junah201 -Vincy1230: - login: Vincy1230 - count: 26 - avatarUrl: https://avatars.githubusercontent.com/u/81342412?u=ab5e256a4077a4a91f3f9cd2115ba80780454cbe&v=4 - url: https://github.com/Vincy1230 zy7y: login: zy7y count: 25 @@ -228,6 +253,11 @@ Aruelius: count: 24 avatarUrl: https://avatars.githubusercontent.com/u/25380989?u=574f8cfcda3ea77a3f81884f6b26a97068e36a9d&v=4 url: https://github.com/Aruelius +wisderfin: + login: wisderfin + count: 24 + avatarUrl: https://avatars.githubusercontent.com/u/77553770?u=9a23740d520d65dc0051cdc1ecd87f31cb900313&v=4 + url: https://github.com/wisderfin OzgunCaglarArslan: login: OzgunCaglarArslan count: 24 @@ -243,16 +273,11 @@ axel584: count: 23 avatarUrl: https://avatars.githubusercontent.com/u/1334088?u=9667041f5b15dc002b6f9665fda8c0412933ac04&v=4 url: https://github.com/axel584 -wisderfin: - login: wisderfin +DianaTrufanova: + login: DianaTrufanova count: 23 - avatarUrl: https://avatars.githubusercontent.com/u/77553770?u=94478d3e1ef7d36d70479c5bd35d8de28b071c10&v=4 - url: https://github.com/wisderfin -rostik1410: - login: rostik1410 - count: 22 - avatarUrl: https://avatars.githubusercontent.com/u/11443899?u=e26a635c2ba220467b308a326a579b8ccf4a8701&v=4 - url: https://github.com/rostik1410 + avatarUrl: https://avatars.githubusercontent.com/u/119067607?u=1cd55f841b68b4a187fa6d06a7dafa5f070195aa&v=4 + url: https://github.com/DianaTrufanova AGolicyn: login: AGolicyn count: 21 @@ -266,7 +291,7 @@ Attsun1031: ycd: login: ycd count: 20 - avatarUrl: https://avatars.githubusercontent.com/u/62724709?u=29682e4b6ac7d5293742ccf818188394b9a82972&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/62724709?u=f1e7bae394a315da950912c92dc861a8eaf95d4c&v=4 url: https://github.com/ycd delhi09: login: delhi09 @@ -283,26 +308,21 @@ DevDae: count: 20 avatarUrl: https://avatars.githubusercontent.com/u/87962045?u=08e10fa516e844934f4b3fc7c38b33c61697e4a1&v=4 url: https://github.com/DevDae -svlandeg: - login: svlandeg - count: 20 - avatarUrl: https://avatars.githubusercontent.com/u/8796347?u=556c97650c27021911b0b9447ec55e75987b0e8a&v=4 - url: https://github.com/svlandeg sattosan: login: sattosan count: 19 avatarUrl: https://avatars.githubusercontent.com/u/20574756?u=b0d8474d2938189c6954423ae8d81d91013f80a8&v=4 url: https://github.com/sattosan +yes0ng: + login: yes0ng + count: 19 + avatarUrl: https://avatars.githubusercontent.com/u/25501794?u=3aed18b0d491e0220a167a1e9e58bea3638c6707&v=4 + url: https://github.com/yes0ng ComicShrimp: login: ComicShrimp count: 18 avatarUrl: https://avatars.githubusercontent.com/u/43503750?u=d2fbf412e7730183ce91686ca48d4147e1b7dc74&v=4 url: https://github.com/ComicShrimp -mezgoodle: - login: mezgoodle - count: 18 - avatarUrl: https://avatars.githubusercontent.com/u/41520940?u=e871bc26734eb2436d98c19c3fb57a4773e13c24&v=4 - url: https://github.com/mezgoodle simatheone: login: simatheone count: 18 @@ -313,6 +333,16 @@ ivan-abc: count: 18 avatarUrl: https://avatars.githubusercontent.com/u/36765187?u=c6e0ba571c1ccb6db9d94e62e4b8b5eda811a870&v=4 url: https://github.com/ivan-abc +Limsunoh: + login: Limsunoh + count: 18 + avatarUrl: https://avatars.githubusercontent.com/u/90311848?u=f456e0c5709fd50c8cd2898b551558eda14e5f21&v=4 + url: https://github.com/Limsunoh +SofiiaTrufanova: + login: SofiiaTrufanova + count: 18 + avatarUrl: https://avatars.githubusercontent.com/u/63260929?u=483e0b64fabc76343b3be39b7e1dcb930a95e1bb&v=4 + url: https://github.com/SofiiaTrufanova bezaca: login: bezaca count: 17 @@ -338,11 +368,6 @@ jeison-araya: count: 17 avatarUrl: https://avatars.githubusercontent.com/u/57369279?u=17001e68af7d8e5b8c343e5e9df4050f419998d5&v=4 url: https://github.com/jeison-araya -Limsunoh: - login: Limsunoh - count: 17 - avatarUrl: https://avatars.githubusercontent.com/u/90311848?u=f456e0c5709fd50c8cd2898b551558eda14e5f21&v=4 - url: https://github.com/Limsunoh yanever: login: yanever count: 16 @@ -353,21 +378,21 @@ mastizada: count: 16 avatarUrl: https://avatars.githubusercontent.com/u/1975818?u=0751a06d7271c8bf17cb73b1b845644ab4d2c6dc&v=4 url: https://github.com/mastizada +Joao-Pedro-P-Holanda: + login: Joao-Pedro-P-Holanda + count: 16 + avatarUrl: https://avatars.githubusercontent.com/u/110267046?u=331bd016326dac4cf3df4848f6db2dbbf8b5f978&v=4 + url: https://github.com/Joao-Pedro-P-Holanda JaeHyuckSa: login: JaeHyuckSa count: 16 - avatarUrl: https://avatars.githubusercontent.com/u/104830931?v=4 + avatarUrl: https://avatars.githubusercontent.com/u/104830931?u=6e352201714a05154e5d0ccf91b4715a951c622e&v=4 url: https://github.com/JaeHyuckSa Jedore: login: Jedore count: 15 avatarUrl: https://avatars.githubusercontent.com/u/17944025?u=81d503e1c800eb666b3861ca47a3a773bbc3f539&v=4 url: https://github.com/Jedore -Joao-Pedro-P-Holanda: - login: Joao-Pedro-P-Holanda - count: 15 - avatarUrl: https://avatars.githubusercontent.com/u/110267046?u=331bd016326dac4cf3df4848f6db2dbbf8b5f978&v=4 - url: https://github.com/Joao-Pedro-P-Holanda kim-sangah: login: kim-sangah count: 15 @@ -383,11 +408,6 @@ dukkee: count: 14 avatarUrl: https://avatars.githubusercontent.com/u/36825394?u=ccfd86e6a4f2d093dad6f7544cc875af67fa2df8&v=4 url: https://github.com/dukkee -mkdir700: - login: mkdir700 - count: 14 - avatarUrl: https://avatars.githubusercontent.com/u/56359329?u=0ba13427420e7f6e4c83947736de247326f2c292&v=4 - url: https://github.com/mkdir700 BORA040126: login: BORA040126 count: 14 @@ -396,7 +416,7 @@ BORA040126: mattkoehne: login: mattkoehne count: 14 - avatarUrl: https://avatars.githubusercontent.com/u/80362153?u=6e1439582715693407b86182eb66263bb578a761&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/80362153?v=4 url: https://github.com/mattkoehne jovicon: login: jovicon @@ -438,16 +458,16 @@ oandersonmagalhaes: count: 12 avatarUrl: https://avatars.githubusercontent.com/u/83456692?v=4 url: https://github.com/oandersonmagalhaes +mkdir700: + login: mkdir700 + count: 12 + avatarUrl: https://avatars.githubusercontent.com/u/56359329?u=3d6ea8714f5000829b60dcf7b13a75b1e73aaf47&v=4 + url: https://github.com/mkdir700 batlopes: login: batlopes count: 12 avatarUrl: https://avatars.githubusercontent.com/u/33462923?u=0fb3d7acb316764616f11e4947faf080e49ad8d9&v=4 url: https://github.com/batlopes -Lenclove: - login: Lenclove - count: 12 - avatarUrl: https://avatars.githubusercontent.com/u/32355298?u=d0065e01650c63c2b2413f42d983634b2ea85481&v=4 - url: https://github.com/Lenclove joonas-yoon: login: joonas-yoon count: 12 @@ -468,6 +488,11 @@ andersonrocha0: count: 12 avatarUrl: https://avatars.githubusercontent.com/u/22346169?u=93a1359c8c5461d894802c0cc65bcd09217e7a02&v=4 url: https://github.com/andersonrocha0 +gitgernit: + login: gitgernit + count: 12 + avatarUrl: https://avatars.githubusercontent.com/u/129539613?u=d04f10143ab32c93f563ea14bf242d1d2bc991b0&v=4 + url: https://github.com/gitgernit kwang1215: login: kwang1215 count: 12 @@ -493,6 +518,11 @@ glsglsgls: count: 11 avatarUrl: https://avatars.githubusercontent.com/u/76133879?v=4 url: https://github.com/glsglsgls +k94-ishi: + login: k94-ishi + count: 11 + avatarUrl: https://avatars.githubusercontent.com/u/32672580?u=bc7c5c07af0656be9fe4f1784a444af8d81ded89&v=4 + url: https://github.com/k94-ishi codespearhead: login: codespearhead count: 11 @@ -508,11 +538,21 @@ Lufa1u: count: 11 avatarUrl: https://avatars.githubusercontent.com/u/112495876?u=087658920ed9e74311597bdd921d8d2de939d276&v=4 url: https://github.com/Lufa1u +waketzheng: + login: waketzheng + count: 11 + avatarUrl: https://avatars.githubusercontent.com/u/35413830?u=df19e4fd5bb928e7d086e053ef26a46aad23bf84&v=4 + url: https://github.com/waketzheng KNChiu: login: KNChiu count: 11 avatarUrl: https://avatars.githubusercontent.com/u/36751646?v=4 url: https://github.com/KNChiu +maru0123-2004: + login: maru0123-2004 + count: 11 + avatarUrl: https://avatars.githubusercontent.com/u/43961566?u=16ed8603a4d6a4665cb6c53a7aece6f31379b769&v=4 + url: https://github.com/maru0123-2004 mariacamilagl: login: mariacamilagl count: 10 @@ -538,6 +578,11 @@ RobotToI: count: 10 avatarUrl: https://avatars.githubusercontent.com/u/44951382?u=e41dbc19191ce7abed86694b1a44ea0523e1c60e&v=4 url: https://github.com/RobotToI +vitumenezes: + login: vitumenezes + count: 10 + avatarUrl: https://avatars.githubusercontent.com/u/9680878?u=05fd25cfafdc09382bf8907c37293a696c205754&v=4 + url: https://github.com/vitumenezes fcrozetta: login: fcrozetta count: 10 @@ -563,16 +608,16 @@ nick-cjyx9: count: 10 avatarUrl: https://avatars.githubusercontent.com/u/119087246?u=c35aab03f082430be8a1edd80f5625b44819a0d8&v=4 url: https://github.com/nick-cjyx9 -waketzheng: - login: waketzheng - count: 10 - avatarUrl: https://avatars.githubusercontent.com/u/35413830?u=df19e4fd5bb928e7d086e053ef26a46aad23bf84&v=4 - url: https://github.com/waketzheng lucasbalieiro: login: lucasbalieiro count: 10 - avatarUrl: https://avatars.githubusercontent.com/u/37416577?u=5a395a69384e7fa0f9840ea32ef963d3f1cd9da4&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/37416577?u=dad91601ee4f40458d691774ec439aff308344d7&v=4 url: https://github.com/lucasbalieiro +Zhongheng-Cheng: + login: Zhongheng-Cheng + count: 10 + avatarUrl: https://avatars.githubusercontent.com/u/95612344?u=a0f7730a3cc7486827965e01a119ad610bda4b0a&v=4 + url: https://github.com/Zhongheng-Cheng RunningIkkyu: login: RunningIkkyu count: 9 @@ -586,18 +631,18 @@ JulianMaurin: JeongHyeongKim: login: JeongHyeongKim count: 9 - avatarUrl: https://avatars.githubusercontent.com/u/26577800?u=fe653349051c0acf62cd984e74c4ff60ca8d2cb6&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/26577800?u=77f060f4686f32c248907b81b16ee2b3177ca44c&v=4 url: https://github.com/JeongHyeongKim arthurio: login: arthurio count: 9 avatarUrl: https://avatars.githubusercontent.com/u/950449?u=76b997138273ce5e1990b971c4f27c9aff979fd5&v=4 url: https://github.com/arthurio -mahone3297: - login: mahone3297 +Lenclove: + login: Lenclove count: 9 - avatarUrl: https://avatars.githubusercontent.com/u/1701379?u=20588ff0e456d13e8017333eb237595d11410234&v=4 - url: https://github.com/mahone3297 + avatarUrl: https://avatars.githubusercontent.com/u/32355298?u=d0065e01650c63c2b2413f42d983634b2ea85481&v=4 + url: https://github.com/Lenclove eVery1337: login: eVery1337 count: 9 @@ -613,6 +658,11 @@ riroan: count: 9 avatarUrl: https://avatars.githubusercontent.com/u/33053284?u=2d18e3771506ee874b66d6aa2b3b1107fd95c38f&v=4 url: https://github.com/riroan +MinLee0210: + login: MinLee0210 + count: 9 + avatarUrl: https://avatars.githubusercontent.com/u/57653278?u=8ca05a7efbc76048183da00da87d148b755a3ba8&v=4 + url: https://github.com/MinLee0210 yodai-yodai: login: yodai-yodai count: 9 @@ -626,13 +676,13 @@ marcelomarkus: JoaoGustavoRogel: login: JoaoGustavoRogel count: 9 - avatarUrl: https://avatars.githubusercontent.com/u/29525510?u=1dd3096c6c2be2576fd5e818b1be15b2c9768aa5&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/29525510?u=a0a91251f5e43e132608d55d28ccb8645c5ea405&v=4 url: https://github.com/JoaoGustavoRogel -Zhongheng-Cheng: - login: Zhongheng-Cheng +Yarous: + login: Yarous count: 9 - avatarUrl: https://avatars.githubusercontent.com/u/95612344?u=a0f7730a3cc7486827965e01a119ad610bda4b0a&v=4 - url: https://github.com/Zhongheng-Cheng + avatarUrl: https://avatars.githubusercontent.com/u/61277193?u=5b462347458a373b2d599c6f416d2b75eddbffad&v=4 + url: https://github.com/Yarous dimaqq: login: dimaqq count: 8 @@ -648,11 +698,6 @@ bnzone: count: 8 avatarUrl: https://avatars.githubusercontent.com/u/39371503?u=c16f00c41d88479fa2d57b0d7d233b758eacce2d&v=4 url: https://github.com/bnzone -ChuyuChoyeon: - login: ChuyuChoyeon - count: 8 - avatarUrl: https://avatars.githubusercontent.com/u/129537877?u=f0c76f3327817a8b86b422d62e04a34bf2827f2b&v=4 - url: https://github.com/ChuyuChoyeon shamosishen: login: shamosishen count: 8 @@ -663,6 +708,11 @@ mertssmnoglu: count: 8 avatarUrl: https://avatars.githubusercontent.com/u/61623638?u=59dd885b68ff1832f9ab3b4a4446896358c23442&v=4 url: https://github.com/mertssmnoglu +mahone3297: + login: mahone3297 + count: 8 + avatarUrl: https://avatars.githubusercontent.com/u/1701379?u=20588ff0e456d13e8017333eb237595d11410234&v=4 + url: https://github.com/mahone3297 KimJoonSeo: login: KimJoonSeo count: 8 @@ -673,11 +723,16 @@ camigomezdev: count: 8 avatarUrl: https://avatars.githubusercontent.com/u/16061815?u=25b5ebc042fff53fa03dc107ded10e36b1b7a5b9&v=4 url: https://github.com/camigomezdev -gitgernit: - login: gitgernit +minaton-ru: + login: minaton-ru count: 8 - avatarUrl: https://avatars.githubusercontent.com/u/129539613?u=d04f10143ab32c93f563ea14bf242d1d2bc991b0&v=4 - url: https://github.com/gitgernit + avatarUrl: https://avatars.githubusercontent.com/u/53541518?u=67336ca11a85493f75031508aade588dad3b9910&v=4 + url: https://github.com/minaton-ru +sungchan1: + login: sungchan1 + count: 8 + avatarUrl: https://avatars.githubusercontent.com/u/28076127?u=a816d86ef3e60450a7225f128caf9a394c9320f9&v=4 + url: https://github.com/sungchan1 Serrones: login: Serrones count: 7 @@ -698,11 +753,6 @@ anthonycepeda: count: 7 avatarUrl: https://avatars.githubusercontent.com/u/72019805?u=60bdf46240cff8fca482ff0fc07d963fd5e1a27c&v=4 url: https://github.com/anthonycepeda -vitumenezes: - login: vitumenezes - count: 7 - avatarUrl: https://avatars.githubusercontent.com/u/9680878?u=e7c6865aec49c3c94b8c8edc1198d1eac3e50b26&v=4 - url: https://github.com/vitumenezes fabioueno: login: fabioueno count: 7 @@ -728,10 +778,20 @@ d2a-raudenaerde: count: 7 avatarUrl: https://avatars.githubusercontent.com/u/5213150?v=4 url: https://github.com/d2a-raudenaerde +valentinDruzhinin: + login: valentinDruzhinin + count: 7 + avatarUrl: https://avatars.githubusercontent.com/u/12831905?u=aae1ebc675c91e8fa582df4fcc4fc4128106344d&v=4 + url: https://github.com/valentinDruzhinin +Zerohertz: + login: Zerohertz + count: 7 + avatarUrl: https://avatars.githubusercontent.com/u/42334717?u=5ebf4d33e73b1ad373154f6cdee44f7cab4d05ba&v=4 + url: https://github.com/Zerohertz deniscapeto: login: deniscapeto count: 6 - avatarUrl: https://avatars.githubusercontent.com/u/12864353?u=dbc20c5c1171feab5df4db46488b675d53cb5b07&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/12864353?u=20c5b2300b264a585a8381acf3cef44bcfcc1ead&v=4 url: https://github.com/deniscapeto bsab: login: bsab @@ -803,11 +863,6 @@ Kirilex: count: 6 avatarUrl: https://avatars.githubusercontent.com/u/100281552?v=4 url: https://github.com/Kirilex -Mordson: - login: Mordson - count: 6 - avatarUrl: https://avatars.githubusercontent.com/u/39025897?u=b94ea96ef35bbe43bc85359cfb31d28ac16d470c&v=4 - url: https://github.com/Mordson arunppsg: login: arunppsg count: 6 @@ -818,11 +873,6 @@ dimastbk: count: 6 avatarUrl: https://avatars.githubusercontent.com/u/3132181?u=66587398d43466a1dc75c238df5f048e0afc77ed&v=4 url: https://github.com/dimastbk -lordqyxz: - login: lordqyxz - count: 6 - avatarUrl: https://avatars.githubusercontent.com/u/31722468?u=974553c0ba53526d9be7e9876544283291be3b0d&v=4 - url: https://github.com/lordqyxz dudyaosuplayer: login: dudyaosuplayer count: 6 @@ -838,6 +888,11 @@ bankofsardine: count: 6 avatarUrl: https://avatars.githubusercontent.com/u/44944207?u=0368e1b698ffab6bf29e202f9fd2dddd352429f1&v=4 url: https://github.com/bankofsardine +Rekl0w: + login: Rekl0w + count: 6 + avatarUrl: https://avatars.githubusercontent.com/u/91488737?u=3b62b04a3e6699eab9b1eea4e88c09a39b753a17&v=4 + url: https://github.com/Rekl0w rsip22: login: rsip22 count: 5 @@ -851,7 +906,7 @@ jessicapaz: mohsen-mahmoodi: login: mohsen-mahmoodi count: 5 - avatarUrl: https://avatars.githubusercontent.com/u/2872586?u=9274b3b13d8a992dba29b162fee48473a0fa142d&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/2872586?u=3a9fc1aa16a3a0ab93a1f8550de82a940592857d&v=4 url: https://github.com/mohsen-mahmoodi jeesang7: login: jeesang7 @@ -866,7 +921,7 @@ TemaSpb: BugLight: login: BugLight count: 5 - avatarUrl: https://avatars.githubusercontent.com/u/13618366?u=57572e544e40c2a491db5bf7255bd24886d2cb09&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/13618366?u=7d733749f80e5f7e66a434cf42aedcfc60340f43&v=4 url: https://github.com/BugLight 0x4Dark: login: 0x4Dark @@ -881,13 +936,18 @@ Wuerike: jvmazagao: login: jvmazagao count: 5 - avatarUrl: https://avatars.githubusercontent.com/u/22477816?u=f3b2d503b53e6ec8c808f0601b756a063a07f06e&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/22477816?u=2b57addf5830906bf6ae5f25cd4c8c2fa5c2d68e&v=4 url: https://github.com/jvmazagao cun3yt: login: cun3yt count: 5 - avatarUrl: https://avatars.githubusercontent.com/u/24409240?u=39f651cdcc4991fb9fef5bbd9e9503db2174ac13&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/24409240?u=06abfd77786db859b0602d5369d2ae18c932c17c&v=4 url: https://github.com/cun3yt +Mordson: + login: Mordson + count: 5 + avatarUrl: https://avatars.githubusercontent.com/u/39025897?u=b94ea96ef35bbe43bc85359cfb31d28ac16d470c&v=4 + url: https://github.com/Mordson aminkhani: login: aminkhani count: 5 @@ -908,10 +968,15 @@ Chushine: count: 5 avatarUrl: https://avatars.githubusercontent.com/u/135534400?v=4 url: https://github.com/Chushine +ChuyuChoyeon: + login: ChuyuChoyeon + count: 5 + avatarUrl: https://avatars.githubusercontent.com/u/129537877?u=f0c76f3327817a8b86b422d62e04a34bf2827f2b&v=4 + url: https://github.com/ChuyuChoyeon frwl404: login: frwl404 count: 5 - avatarUrl: https://avatars.githubusercontent.com/u/42642656?u=572a5a33762e07eaa6ebd58d9d773abdb1de41c3&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/42642656?u=8395a3d991d9fac86901277d76f0f70857b56ec5&v=4 url: https://github.com/frwl404 esrefzeki: login: esrefzeki @@ -953,11 +1018,16 @@ devluisrodrigues: count: 5 avatarUrl: https://avatars.githubusercontent.com/u/103431660?u=d9674a3249edc4601d2c712cdebf899918503c3a&v=4 url: https://github.com/devluisrodrigues -timothy-jeong: - login: timothy-jeong +11kkw: + login: 11kkw count: 5 - avatarUrl: https://avatars.githubusercontent.com/u/53824764?u=659311b6f6aeb0fbb8b527723fd4c83642f04327&v=4 - url: https://github.com/timothy-jeong + 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 @@ -971,7 +1041,7 @@ SepehrRasouli: Zxilly: login: Zxilly count: 4 - avatarUrl: https://avatars.githubusercontent.com/u/31370133?u=122e23d6e974614736be606e4ea816f45e7745f8&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/31370133?u=c5359b8d9d80a7cdc23d5295d179ed90174996c8&v=4 url: https://github.com/Zxilly eavv: login: eavv @@ -988,6 +1058,11 @@ FelipeSilva93: count: 4 avatarUrl: https://avatars.githubusercontent.com/u/66804965?u=e7cb4b580e46f2e04ecb4cd4d7a12acdddd3c6c1&v=4 url: https://github.com/FelipeSilva93 +peacekimjapan: + login: peacekimjapan + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/33534175?u=e4219bcebc3773a7068cc34c3eb268ef77cec31b&v=4 + url: https://github.com/peacekimjapan bas-baskara: login: bas-baskara count: 4 @@ -1011,18 +1086,23 @@ personage-hub: aminalaee: login: aminalaee count: 4 - avatarUrl: https://avatars.githubusercontent.com/u/19784933?u=2f45a312b73e7fb29f3b6f8676e5be6f7220da25&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/19784933?v=4 url: https://github.com/aminalaee erfan-rfmhr: login: erfan-rfmhr count: 4 - avatarUrl: https://avatars.githubusercontent.com/u/98986056?u=6c4f9218fe5bb04780dd92bfced360c55e2009f0&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/98986056?u=0acda1ff1df0989f3f3eb79977baa35da4cb6c8c&v=4 url: https://github.com/erfan-rfmhr Scorpionchiques: login: Scorpionchiques count: 4 avatarUrl: https://avatars.githubusercontent.com/u/15703294?v=4 url: https://github.com/Scorpionchiques +lordqyxz: + login: lordqyxz + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/31722468?u=974553c0ba53526d9be7e9876544283291be3b0d&v=4 + url: https://github.com/lordqyxz heysaeid: login: heysaeid count: 4 @@ -1053,6 +1133,11 @@ matiasbertani: count: 4 avatarUrl: https://avatars.githubusercontent.com/u/65260383?u=d5edd86a6e2ab4fb1aab7751931fe045a963afd7&v=4 url: https://github.com/matiasbertani +thiennc254: + login: thiennc254 + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/97406628?u=1b2860679694b9a552764d0fa81dbd7a016322ec&v=4 + url: https://github.com/thiennc254 javillegasna: login: javillegasna count: 4 @@ -1063,6 +1148,26 @@ javillegasna: count: 4 avatarUrl: https://avatars.githubusercontent.com/u/174453744?v=4 url: https://github.com/9zimin9 +ilhamfadillah: + login: ilhamfadillah + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/20577838?u=c56192cf99b55affcaad408b240259c62e633450&v=4 + url: https://github.com/ilhamfadillah +gerry-sabar: + login: gerry-sabar + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/1120123?v=4 + url: https://github.com/gerry-sabar +cookie-byte217: + login: cookie-byte217 + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/57880178?v=4 + url: https://github.com/cookie-byte217 +AbolfazlKameli: + login: AbolfazlKameli + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/120686133?u=05d405115fc834d46260ec24ec7b28e23a13477e&v=4 + url: https://github.com/AbolfazlKameli tyronedamasceno: login: tyronedamasceno count: 3 @@ -1141,7 +1246,7 @@ RuslanTer: FedorGN: login: FedorGN count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/66411909?u=1c6734e92f50c7d66f130ef7d394e72b53770fe6&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/66411909?u=22382380e7d66ee57ffbfc2ae6bd5efd0cdb672e&v=4 url: https://github.com/FedorGN rafsaf: login: rafsaf @@ -1151,7 +1256,7 @@ rafsaf: frnsimoes: login: frnsimoes count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/66239468?u=771c4b0c403a42ccf2676ac987ac4999e5ad09bc&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/66239468?u=fd8d408946633acc4bea057c207e6c0833871527&v=4 url: https://github.com/frnsimoes lieryan: login: lieryan @@ -1243,6 +1348,11 @@ Sion99: count: 3 avatarUrl: https://avatars.githubusercontent.com/u/82511301?v=4 url: https://github.com/Sion99 +nymous: + login: nymous + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/4216559?u=360a36fb602cded27273cbfc0afc296eece90662&v=4 + url: https://github.com/nymous EpsilonRationes: login: EpsilonRationes count: 3 @@ -1263,6 +1373,11 @@ kohiry: count: 3 avatarUrl: https://avatars.githubusercontent.com/u/57669492?u=f6ab0a062740261e882879269a41a47788c84043&v=4 url: https://github.com/kohiry +ptt3199: + login: ptt3199 + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/51350651?u=2c3d947a80283e32bf616d4c3af139a6be69680f&v=4 + url: https://github.com/ptt3199 arynoot: login: arynoot count: 3 @@ -1276,18 +1391,38 @@ GDemay: maxscheijen: login: maxscheijen count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/47034840?u=eb98f37882528ea349ca4e5255fa64ac3fef0294&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/47034840?v=4 url: https://github.com/maxscheijen celestywang: login: celestywang count: 3 avatarUrl: https://avatars.githubusercontent.com/u/184830753?v=4 url: https://github.com/celestywang -ilhamfadillah: - login: ilhamfadillah +RyaWcksn: + login: RyaWcksn count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/20577838?u=c56192cf99b55affcaad408b240259c62e633450&v=4 - url: https://github.com/ilhamfadillah + avatarUrl: https://avatars.githubusercontent.com/u/42831964?u=0cb4265faf3e3425a89e59b6fddd3eb2de180af0&v=4 + url: https://github.com/RyaWcksn +tienduong-21: + login: tienduong-21 + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/80129618?v=4 + url: https://github.com/tienduong-21 +zbellos: + login: zbellos + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/204500646?v=4 + url: https://github.com/zbellos +Mohammad222PR: + login: Mohammad222PR + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/116789737?u=25810a5fe049d2f1618e2e7417cea011cc353ce4&v=4 + url: https://github.com/Mohammad222PR +EdmilsonRodrigues: + login: EdmilsonRodrigues + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/62777025?u=217d6f3cd6cc750bb8818a3af7726c8d74eb7c2d&v=4 + url: https://github.com/EdmilsonRodrigues blaisep: login: blaisep count: 2 @@ -1361,7 +1496,7 @@ TimorChow: ataberkciftlikli: login: ataberkciftlikli count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/64265169?v=4 + avatarUrl: https://avatars.githubusercontent.com/u/64265169?u=ca7c1348242559f70bc1dc027a4be277c464676f&v=4 url: https://github.com/ataberkciftlikli leandrodesouzadev: login: leandrodesouzadev @@ -1383,36 +1518,31 @@ its0x08: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/15280042?u=d7c2058f29d4e8fbdae09b194e04c5e410350211&v=4 url: https://github.com/its0x08 -lindsayzhou: - login: lindsayzhou +linsein: + login: linsein count: 2 avatarUrl: https://avatars.githubusercontent.com/u/23748021?u=4db169ce262b69aa7292f82b785436544f69fb88&v=4 - url: https://github.com/lindsayzhou + url: https://github.com/linsein 0xflotus: login: 0xflotus count: 2 avatarUrl: https://avatars.githubusercontent.com/u/26602940?u=3c52ce6393bb547c97e6380ccdee03e0c64152c6&v=4 url: https://github.com/0xflotus -peacekimjapan: - login: peacekimjapan - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/33534175?u=e4219bcebc3773a7068cc34c3eb268ef77cec31b&v=4 - url: https://github.com/peacekimjapan jonatasoli: login: jonatasoli count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/26334101?u=071c062d2861d3dd127f6b4a5258cd8ef55d4c50&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/26334101?u=f601c3f111f2148bd9244c2cb3ebbd57b592e674&v=4 url: https://github.com/jonatasoli tyzh-dev: login: tyzh-dev count: 2 avatarUrl: https://avatars.githubusercontent.com/u/51972581?u=ba3882da7c009918a8e2d6b9ead31c89f09c922d&v=4 url: https://github.com/tyzh-dev -WaFeeAL: - login: WaFeeAL +yurkevich-dev: + login: yurkevich-dev count: 2 avatarUrl: https://avatars.githubusercontent.com/u/45145188?u=db2de8c186073d95693279dcf085fcebffab57d0&v=4 - url: https://github.com/WaFeeAL + url: https://github.com/yurkevich-dev emp7yhead: login: emp7yhead count: 2 @@ -1446,7 +1576,7 @@ felipebpl: iudeen: login: iudeen count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/10519440?u=2843b3303282bff8b212dcd4d9d6689452e4470c&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/10519440?u=f09cdd745e5bf16138f29b42732dd57c7f02bee1&v=4 url: https://github.com/iudeen dwisulfahnur: login: dwisulfahnur @@ -1466,7 +1596,7 @@ raphaelauv: Fahad-Md-Kamal: login: Fahad-Md-Kamal count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/34704464?u=84abea85e59c30b2e3bc700ae42424f3fe704332&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/34704464?u=141086368c5557d5a1a533fe291f21f9fc584458&v=4 url: https://github.com/Fahad-Md-Kamal zxcq544: login: zxcq544 @@ -1548,6 +1678,11 @@ siavashyj: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/43583410?u=562005ddc7901cd27a1219a118a2363817b14977&v=4 url: https://github.com/siavashyj +Ramin-RX7: + login: Ramin-RX7 + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/52785580?u=b3678f779ad0ee9cd9dca9e50ccb804b5eb990a5&v=4 + url: https://github.com/Ramin-RX7 DevSpace88: login: DevSpace88 count: 2 @@ -1581,7 +1716,7 @@ zhiquanchi: Jamim: login: Jamim count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/5607572?u=0cf3027bec78ba4f0b89802430c136bc69847d7a&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/5607572?u=9ce0b6a6d1a5124e28b3c04d8d26827ca328713a&v=4 url: https://github.com/Jamim alvinkhalil: login: alvinkhalil @@ -1591,13 +1726,18 @@ alvinkhalil: leylaeminova: login: leylaeminova count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/100516839?u=35a9ce14bb86d7d7faa25d432f61dec2984cb818&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/100516839?u=0b0dab9e31742076b22812b14a39b4e6d8f6de4a&v=4 url: https://github.com/leylaeminova UN-9BOT: login: UN-9BOT count: 2 avatarUrl: https://avatars.githubusercontent.com/u/111110804?u=39e158937ed795972c2d0400fc521c50e9bfb9e7&v=4 url: https://github.com/UN-9BOT +flasonme: + login: flasonme + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/30571019?v=4 + url: https://github.com/flasonme gustavoprezoto: login: gustavoprezoto count: 2 @@ -1621,25 +1761,95 @@ ZhibangYue: saeye: login: saeye count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/62229734?v=4 + avatarUrl: https://avatars.githubusercontent.com/u/62229734?u=312d619db2588b60d5d5bde65260a2f44fdc6c76&v=4 url: https://github.com/saeye Heumhub: login: Heumhub count: 2 avatarUrl: https://avatars.githubusercontent.com/u/173761521?v=4 url: https://github.com/Heumhub +manumolina: + login: manumolina + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/2404208?u=fdc5502910f8dec814b2477f89587b9e45fac846&v=4 + url: https://github.com/manumolina logan2d5: login: logan2d5 count: 2 avatarUrl: https://avatars.githubusercontent.com/u/146642263?u=dbd6621f8b0330d6919f6a7131277b92e26fbe87&v=4 url: https://github.com/logan2d5 -RyaWcksn: - login: RyaWcksn - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/42831964?u=0cb4265faf3e3425a89e59b6fddd3eb2de180af0&v=4 - url: https://github.com/RyaWcksn -gerry-sabar: - login: gerry-sabar - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/1120123?v=4 - url: https://github.com/gerry-sabar +guspan-tanadi: + login: guspan-tanadi + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/36249910?v=4 + url: https://github.com/guspan-tanadi +tiaggo16: + login: tiaggo16 + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/62227573?u=359f4e2c51a4b13c8553ac5af405d635b07bb61f&v=4 + url: https://github.com/tiaggo16 +kiharito: + login: kiharito + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/38311245?v=4 + url: https://github.com/kiharito +t4f1d: + login: t4f1d + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/4054172?u=463d5ce0ec8ad8582f6e9351bb8c9a5105b39bb7&v=4 + url: https://github.com/t4f1d +J-Fuji: + login: J-Fuji + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/101452903?v=4 + url: https://github.com/J-Fuji +MrL8199: + login: MrL8199 + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/39489075?u=3fc4f89c86973e40b5970d838c801bdbc13ac828&v=4 + url: https://github.com/MrL8199 +ivintoiu: + login: ivintoiu + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/1853336?u=5e3d0977f44661fb9712fa297cc8f7608ea6ce48&v=4 + url: https://github.com/ivintoiu +TechnoService2: + login: TechnoService2 + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/142113388?v=4 + url: https://github.com/TechnoService2 +EgorOnishchuk: + login: EgorOnishchuk + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/120256301?v=4 + url: https://github.com/EgorOnishchuk +iamantonreznik: + login: iamantonreznik + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/112612414?u=bf6de9a1ab17326fe14de0709719fff3826526d0&v=4 + url: https://github.com/iamantonreznik +Azazul123: + login: Azazul123 + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/102759111?u=b48ce6e30a81a23467cc30e0c011bcc57f0326ab&v=4 + url: https://github.com/Azazul123 +ykertytsky: + login: ykertytsky + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/83857001?u=1172902656ee604cf37f5e36abe938cd34a97a32&v=4 + url: https://github.com/ykertytsky +NavesSapnis: + login: NavesSapnis + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/79222417?u=b5b10291b8e9130ca84fd20f0a641e04ed94b6b1&v=4 + url: https://github.com/NavesSapnis +eqsdxr: + login: eqsdxr + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/157279130?u=58fddf77ed76966eaa8c73eea9bea4bb0c53b673&v=4 + url: https://github.com/eqsdxr +syedasamina56: + login: syedasamina56 + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/183273097?v=4 + url: https://github.com/syedasamina56 diff --git a/docs/en/data/translators.yml b/docs/en/data/translators.yml index 7b199dc08..410c9c826 100644 --- a/docs/en/data/translators.yml +++ b/docs/en/data/translators.yml @@ -8,6 +8,16 @@ jaystone776: count: 46 avatarUrl: https://avatars.githubusercontent.com/u/11191137?u=299205a95e9b6817a43144a48b643346a5aac5cc&v=4 url: https://github.com/jaystone776 +valentinDruzhinin: + login: valentinDruzhinin + count: 29 + avatarUrl: https://avatars.githubusercontent.com/u/12831905?u=aae1ebc675c91e8fa582df4fcc4fc4128106344d&v=4 + url: https://github.com/valentinDruzhinin +ceb10n: + login: ceb10n + count: 27 + avatarUrl: https://avatars.githubusercontent.com/u/235213?u=edcce471814a1eba9f0cdaa4cd0de18921a940a6&v=4 + url: https://github.com/ceb10n tokusumi: login: tokusumi count: 23 @@ -23,11 +33,6 @@ hasansezertasan: count: 22 avatarUrl: https://avatars.githubusercontent.com/u/13135006?u=99f0b0f0fc47e88e8abb337b4447357939ef93e7&v=4 url: https://github.com/hasansezertasan -ceb10n: - login: ceb10n - count: 22 - avatarUrl: https://avatars.githubusercontent.com/u/235213?u=edcce471814a1eba9f0cdaa4cd0de18921a940a6&v=4 - url: https://github.com/ceb10n waynerv: login: waynerv count: 20 @@ -43,6 +48,11 @@ hard-coders: count: 15 avatarUrl: https://avatars.githubusercontent.com/u/9651103?u=95db33927bbff1ed1c07efddeb97ac2ff33068ed&v=4 url: https://github.com/hard-coders +Joao-Pedro-P-Holanda: + login: Joao-Pedro-P-Holanda + count: 14 + avatarUrl: https://avatars.githubusercontent.com/u/110267046?u=331bd016326dac4cf3df4848f6db2dbbf8b5f978&v=4 + url: https://github.com/Joao-Pedro-P-Holanda codingjenny: login: codingjenny count: 14 @@ -53,11 +63,11 @@ Xewus: count: 13 avatarUrl: https://avatars.githubusercontent.com/u/85196001?u=f8e2dc7e5104f109cef944af79050ea8d1b8f914&v=4 url: https://github.com/Xewus -Joao-Pedro-P-Holanda: - login: Joao-Pedro-P-Holanda - count: 12 - avatarUrl: https://avatars.githubusercontent.com/u/110267046?u=331bd016326dac4cf3df4848f6db2dbbf8b5f978&v=4 - url: https://github.com/Joao-Pedro-P-Holanda +Zhongheng-Cheng: + login: Zhongheng-Cheng + count: 13 + avatarUrl: https://avatars.githubusercontent.com/u/95612344?u=a0f7730a3cc7486827965e01a119ad610bda4b0a&v=4 + url: https://github.com/Zhongheng-Cheng Smlep: login: Smlep count: 11 @@ -93,11 +103,16 @@ pablocm83: count: 8 avatarUrl: https://avatars.githubusercontent.com/u/28315068?u=3310fbb05bb8bfc50d2c48b6cb64ac9ee4a14549&v=4 url: https://github.com/pablocm83 -Zhongheng-Cheng: - login: Zhongheng-Cheng - count: 8 - avatarUrl: https://avatars.githubusercontent.com/u/95612344?u=a0f7730a3cc7486827965e01a119ad610bda4b0a&v=4 - url: https://github.com/Zhongheng-Cheng +ptt3199: + login: ptt3199 + count: 7 + avatarUrl: https://avatars.githubusercontent.com/u/51350651?u=2c3d947a80283e32bf616d4c3af139a6be69680f&v=4 + url: https://github.com/ptt3199 +NinaHwang: + login: NinaHwang + count: 6 + avatarUrl: https://avatars.githubusercontent.com/u/79563565?u=241f2cb6d38a2d379536608a8ea5a22ed4b1a3ea&v=4 + url: https://github.com/NinaHwang batlopes: login: batlopes count: 6 @@ -106,7 +121,7 @@ batlopes: lucasbalieiro: login: lucasbalieiro count: 6 - avatarUrl: https://avatars.githubusercontent.com/u/37416577?u=5a395a69384e7fa0f9840ea32ef963d3f1cd9da4&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/37416577?u=dad91601ee4f40458d691774ec439aff308344d7&v=4 url: https://github.com/lucasbalieiro Alexandrhub: login: Alexandrhub @@ -128,11 +143,6 @@ Attsun1031: count: 5 avatarUrl: https://avatars.githubusercontent.com/u/1175560?v=4 url: https://github.com/Attsun1031 -NinaHwang: - login: NinaHwang - count: 5 - avatarUrl: https://avatars.githubusercontent.com/u/79563565?u=241f2cb6d38a2d379536608a8ea5a22ed4b1a3ea&v=4 - url: https://github.com/NinaHwang tiangolo: login: tiangolo count: 5 @@ -143,6 +153,11 @@ rostik1410: count: 5 avatarUrl: https://avatars.githubusercontent.com/u/11443899?u=e26a635c2ba220467b308a326a579b8ccf4a8701&v=4 url: https://github.com/rostik1410 +alv2017: + login: alv2017 + count: 5 + avatarUrl: https://avatars.githubusercontent.com/u/31544722?v=4 + url: https://github.com/alv2017 komtaki: login: komtaki count: 4 @@ -188,6 +203,21 @@ kwang1215: count: 4 avatarUrl: https://avatars.githubusercontent.com/u/74170199?u=2a63ff6692119dde3f5e5693365b9fcd6f977b08&v=4 url: https://github.com/kwang1215 +k94-ishi: + login: k94-ishi + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/32672580?u=bc7c5c07af0656be9fe4f1784a444af8d81ded89&v=4 + url: https://github.com/k94-ishi +Mohammad222PR: + login: Mohammad222PR + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/116789737?u=25810a5fe049d2f1618e2e7417cea011cc353ce4&v=4 + url: https://github.com/Mohammad222PR +NavesSapnis: + login: NavesSapnis + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/79222417?u=b5b10291b8e9130ca84fd20f0a641e04ed94b6b1&v=4 + url: https://github.com/NavesSapnis jfunez: login: jfunez count: 3 @@ -196,7 +226,7 @@ jfunez: ycd: login: ycd count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/62724709?u=29682e4b6ac7d5293742ccf818188394b9a82972&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/62724709?u=f1e7bae394a315da950912c92dc861a8eaf95d4c&v=4 url: https://github.com/ycd mariacamilagl: login: mariacamilagl @@ -233,11 +263,6 @@ Zssaer: count: 3 avatarUrl: https://avatars.githubusercontent.com/u/45691504?u=4c0c195f25cb5ac6af32acfb0ab35427682938d2&v=4 url: https://github.com/Zssaer -wdh99: - login: wdh99 - count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/108172295?u=8a8fb95d5afe3e0fa33257b2aecae88d436249eb&v=4 - url: https://github.com/wdh99 ChuyuChoyeon: login: ChuyuChoyeon count: 3 @@ -256,12 +281,12 @@ mojtabapaso: hsuanchi: login: hsuanchi count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/24913710?u=0b094ae292292fee093818e37ceb645c114d2bff&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/24913710?u=7d25a398e478b6e63503bf6f26c54efa9e0da07b&v=4 url: https://github.com/hsuanchi alejsdev: login: alejsdev count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/90076947?u=356f39ff3f0211c720b06d3dbb060e98884085e3&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/90076947?u=638c65283ac9e9e2c3a0f9d1e3370db4b8a2c58d&v=4 url: https://github.com/alejsdev riroan: login: riroan @@ -281,7 +306,7 @@ pe-brian: maxscheijen: login: maxscheijen count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/47034840?u=eb98f37882528ea349ca4e5255fa64ac3fef0294&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/47034840?v=4 url: https://github.com/maxscheijen ilacftemp: login: ilacftemp @@ -313,11 +338,26 @@ nahyunkeem: count: 3 avatarUrl: https://avatars.githubusercontent.com/u/174440096?u=e12401d492eee58570f8914d0872b52e421a776e&v=4 url: https://github.com/nahyunkeem -alv2017: - login: alv2017 +timothy-jeong: + login: timothy-jeong count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/31544722?v=4 - url: https://github.com/alv2017 + avatarUrl: https://avatars.githubusercontent.com/u/53824764?u=db3d0cea2f5fab64d810113c5039a369699a2774&v=4 + url: https://github.com/timothy-jeong +gerry-sabar: + login: gerry-sabar + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/1120123?v=4 + url: https://github.com/gerry-sabar +Rishat-F: + login: Rishat-F + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/66554797?v=4 + url: https://github.com/Rishat-F +ruzia: + login: ruzia + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/24503?v=4 + url: https://github.com/ruzia izaguerreiro: login: izaguerreiro count: 2 @@ -446,8 +486,13 @@ choi-haram: imtiaz101325: login: imtiaz101325 count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/54007087?u=7a210ee38a0a30b7536226419b3b799620ad57d9&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/54007087?u=194d972b501b9ea9d2ddeaed757c492936e0121a&v=4 url: https://github.com/imtiaz101325 +fabianfalon: + login: fabianfalon + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/3700760?u=95f69e31280b17ac22299cdcd345323b142fe0af&v=4 + url: https://github.com/fabianfalon waketzheng: login: waketzheng count: 2 @@ -476,15 +521,25 @@ andersonrocha0: saeye: login: saeye count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/62229734?v=4 + avatarUrl: https://avatars.githubusercontent.com/u/62229734?u=312d619db2588b60d5d5bde65260a2f44fdc6c76&v=4 url: https://github.com/saeye -timothy-jeong: - login: timothy-jeong - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/53824764?u=659311b6f6aeb0fbb8b527723fd4c83642f04327&v=4 - url: https://github.com/timothy-jeong -gerry-sabar: - login: gerry-sabar - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/1120123?v=4 - url: https://github.com/gerry-sabar +11kkw: + login: 11kkw + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/21125286?v=4 + url: https://github.com/11kkw +yes0ng: + login: yes0ng + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/25501794?u=3aed18b0d491e0220a167a1e9e58bea3638c6707&v=4 + url: https://github.com/yes0ng +EgorOnishchuk: + login: EgorOnishchuk + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/120256301?v=4 + url: https://github.com/EgorOnishchuk +EdmilsonRodrigues: + login: EdmilsonRodrigues + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/62777025?u=217d6f3cd6cc750bb8818a3af7726c8d74eb7c2d&v=4 + url: https://github.com/EdmilsonRodrigues diff --git a/docs/en/docs/advanced/generate-clients.md b/docs/en/docs/advanced/generate-clients.md index 3b9dc83f0..55e6a08b1 100644 --- a/docs/en/docs/advanced/generate-clients.md +++ b/docs/en/docs/advanced/generate-clients.md @@ -22,9 +22,9 @@ And it shows their true commitment to FastAPI and its **community** (you), as th For example, you might want to try: -* Speakeasy +* Speakeasy * Stainless -* liblab +* liblab There are also several other companies offering similar services that you can search and find online. 🤓 diff --git a/docs/en/docs/advanced/index.md b/docs/en/docs/advanced/index.md index 36f0720c0..47385e2c6 100644 --- a/docs/en/docs/advanced/index.md +++ b/docs/en/docs/advanced/index.md @@ -19,18 +19,3 @@ And it's possible that for your use case, the solution is in one of them. You could still use most of the features in **FastAPI** with the knowledge from the main [Tutorial - User Guide](../tutorial/index.md){.internal-link target=_blank}. And the next sections assume you already read it, and assume that you know those main ideas. - -## External Courses - -Although the [Tutorial - User Guide](../tutorial/index.md){.internal-link target=_blank} and this **Advanced User Guide** are written as a guided tutorial (like a book) and should be enough for you to **learn FastAPI**, you might want to complement it with additional courses. - -Or it might be the case that you just prefer to take other courses because they adapt better to your learning style. - -Some course providers ✨ [**sponsor FastAPI**](../help-fastapi.md#sponsor-the-author){.internal-link target=_blank} ✨, this ensures the continued and healthy **development** of FastAPI and its **ecosystem**. - -And it shows their true commitment to FastAPI and its **community** (you), as they not only want to provide you a **good learning experience** but also want to make sure you have a **good and healthy framework**, FastAPI. 🙇 - -You might want to try their courses: - -* Talk Python Training -* Test-Driven Development diff --git a/docs/en/docs/advanced/response-directly.md b/docs/en/docs/advanced/response-directly.md index 691b1e7cd..759b762b5 100644 --- a/docs/en/docs/advanced/response-directly.md +++ b/docs/en/docs/advanced/response-directly.md @@ -58,7 +58,7 @@ You could put your XML content in a string, put that in a `Response`, and return ## Notes -When you return a `Response` directly its data is not validated, converted (serialized), nor documented automatically. +When you return a `Response` directly its data is not validated, converted (serialized), or documented automatically. But you can still document it as described in [Additional Responses in OpenAPI](additional-responses.md){.internal-link target=_blank}. diff --git a/docs/en/docs/async.md b/docs/en/docs/async.md index 63bd8ca68..8207ec480 100644 --- a/docs/en/docs/async.md +++ b/docs/en/docs/async.md @@ -40,7 +40,7 @@ def results(): --- -If your application (somehow) doesn't have to communicate with anything else and wait for it to respond, use `async def`. +If your application (somehow) doesn't have to communicate with anything else and wait for it to respond, use `async def`, even if you don't need to use `await` inside. --- diff --git a/docs/en/docs/contributing.md b/docs/en/docs/contributing.md index 1b70a0ea9..2583fd1fb 100644 --- a/docs/en/docs/contributing.md +++ b/docs/en/docs/contributing.md @@ -181,6 +181,28 @@ as Uvicorn by default will use the port `8000`, the documentation on port `8008` ### Translations +/// warning | Attention + +**Update on Translations** + +We're updating the way we handle documentation translations. + +Until now, we invited community members to translate pages via pull requests, which were then reviewed by at least two native speakers. While this has helped bring FastAPI to many more users, we’ve also run into several challenges - some languages have only a few translated pages, others are outdated and hard to maintain over time. +To improve this, we’re working on automation tools 🤖 to manage translations more efficiently. Once ready, documentation will be machine-translated and still reviewed by at least two native speakers ✅ before publishing. This will allow us to keep translations up-to-date while reducing the review burden on maintainers. + +What’s changing now: + +* đŸšĢ We’re no longer accepting new community-submitted translation PRs. + +* âŗ Existing open PRs will be reviewed and can still be merged if completed within the next 3 weeks (since July 11 2025). + +* 🌐 In the future, we will only support languages where at least three active native speakers are available to review and maintain translations. + +This transition will help us keep translations more consistent and timely while better supporting our contributors 🙌. Thank you to everyone who has contributed so far — your help has been invaluable! 💖 + +/// + + Help with translations is VERY MUCH appreciated! And it can't be done without the help from the community. 🌎 🚀 Here are the steps to help with translations. @@ -293,30 +315,47 @@ Now you can translate it all and see how it looks as you save the file. Some of these files are updated very frequently and a translation would always be behind, or they include the main content from English source files, etc. +#### Request a New Language + +Let's say that you want to request translations for a language that is not yet translated, not even some pages. For example, Latin. + +If there is no discussion for that language, you can start by requesting the new language. For that, you can follow these steps: + +* Create a new discussion following the template. +* Get a few native speakers to comment on the discussion and commit to help review translations for that language. + +Once there are several people in the discussion, the FastAPI team can evaluate it and can make it an official translation. + +Then the docs will be automatically translated using AI, and the team of native speakers can review the translation, and help tweak the AI prompts. + +Once there's a new translation, for example if docs are updated or there's a new section, there will be a comment in the same discussion with the link to the new translation to review. + #### New Language -Let's say that you want to add translations for a language that is not yet translated, not even some pages. +/// note -Let's say you want to add translations for Creole, and it's not yet there in the docs. +These steps will be performed by the FastAPI team. + +/// -Checking the link from above, the code for "Creole" is `ht`. +Checking the link from above (List of ISO 639-1 codes), you can see that the 2-letter code for Latin is `la`. -The next step is to run the script to generate a new translation directory: +Now you can create a new directory for the new language, running the following script:

```console // Use the command new-lang, pass the language code as a CLI argument -$ python ./scripts/docs.py new-lang ht +$ python ./scripts/docs.py new-lang la -Successfully initialized: docs/ht +Successfully initialized: docs/la ```
-Now you can check in your code editor the newly created directory `docs/ht/`. +Now you can check in your code editor the newly created directory `docs/la/`. -That command created a file `docs/ht/mkdocs.yml` with a simple config that inherits everything from the `en` version: +That command created a file `docs/la/mkdocs.yml` with a simple config that inherits everything from the `en` version: ```yaml INHERIT: ../en/mkdocs.yml @@ -328,11 +367,11 @@ You could also simply create that file with those contents manually. /// -That command also created a dummy file `docs/ht/index.md` for the main page, you can start by translating that one. +That command also created a dummy file `docs/la/index.md` for the main page, you can start by translating that one. You can continue with the previous instructions for an "Existing Language" for that process. -You can make the first pull request with those two files, `docs/ht/mkdocs.yml` and `docs/ht/index.md`. 🎉 +You can make the first pull request with those two files, `docs/la/mkdocs.yml` and `docs/la/index.md`. 🎉 #### Preview the result diff --git a/docs/en/docs/deployment/cloud.md b/docs/en/docs/deployment/cloud.md index 471808851..c6d408f8c 100644 --- a/docs/en/docs/deployment/cloud.md +++ b/docs/en/docs/deployment/cloud.md @@ -14,5 +14,5 @@ You might want to try their services and follow their guides: * Platform.sh * Porter -* Coherence * Render +* Railway diff --git a/docs/en/docs/deployment/concepts.md b/docs/en/docs/deployment/concepts.md index e71a7487a..ed635a920 100644 --- a/docs/en/docs/deployment/concepts.md +++ b/docs/en/docs/deployment/concepts.md @@ -65,7 +65,7 @@ The word **program** is commonly used to describe many things: * The **code** that you write, the **Python files**. * The **file** that can be **executed** by the operating system, for example: `python`, `python.exe` or `uvicorn`. -* A particular program while it is **running** on the operating system, using the CPU, and storing things on memory. This is also called a **process**. +* A particular program while it is **running** on the operating system, using the CPU, and storing things in memory. This is also called a **process**. ### What is a Process @@ -216,7 +216,7 @@ This Manager Process would probably be the one listening on the **port** in the Those worker processes would be the ones running your application, they would perform the main computations to receive a **request** and return a **response**, and they would load anything you put in variables in RAM. - + And of course, the same machine would probably have **other processes** running as well, apart from your application. diff --git a/docs/en/docs/deployment/https.md b/docs/en/docs/deployment/https.md index 46eda791e..8b4a08dbe 100644 --- a/docs/en/docs/deployment/https.md +++ b/docs/en/docs/deployment/https.md @@ -85,7 +85,7 @@ First, the browser would check with the **DNS servers** what is the **IP for the The DNS servers would tell the browser to use some specific **IP address**. That would be the public IP address used by your server, that you configured in the DNS servers. - + ### TLS Handshake Start @@ -93,7 +93,7 @@ The browser would then communicate with that IP address on **port 443** (the HTT The first part of the communication is just to establish the connection between the client and the server and to decide the cryptographic keys they will use, etc. - + This interaction between the client and the server to establish the TLS connection is called the **TLS handshake**. @@ -111,7 +111,7 @@ Using the **SNI extension** discussed above, the TLS Termination Proxy would che In this case, it would use the certificate for `someapp.example.com`. - + The client already **trusts** the entity that generated that TLS certificate (in this case Let's Encrypt, but we'll see about that later), so it can **verify** that the certificate is valid. @@ -133,19 +133,19 @@ Now that the client and server (specifically the browser and the TLS Termination So, the client sends an **HTTPS request**. This is just an HTTP request through an encrypted TLS connection. - + ### Decrypt the Request The TLS Termination Proxy would use the encryption agreed to **decrypt the request**, and would transmit the **plain (decrypted) HTTP request** to the process running the application (for example a process with Uvicorn running the FastAPI application). - + ### HTTP Response The application would process the request and send a **plain (unencrypted) HTTP response** to the TLS Termination Proxy. - + ### HTTPS Response @@ -153,7 +153,7 @@ The TLS Termination Proxy would then **encrypt the response** using the cryptogr Next, the browser would verify that the response is valid and encrypted with the right cryptographic key, etc. It would then **decrypt the response** and process it. - + The client (browser) will know that the response comes from the correct server because it is using the cryptography they agreed using the **HTTPS certificate** before. @@ -163,7 +163,7 @@ In the same server (or servers), there could be **multiple applications**, for e Only one process can be handling the specific IP and port (the TLS Termination Proxy in our example) but the other applications/processes can be running on the server(s) too, as long as they don't try to use the same **combination of public IP and port**. - + That way, the TLS Termination Proxy could handle HTTPS and certificates for **multiple domains**, for multiple applications, and then transmit the requests to the right application in each case. @@ -173,7 +173,7 @@ At some point in the future, each certificate would **expire** (about 3 months a And then, there would be another program (in some cases it's another program, in some cases it could be the same TLS Termination Proxy) that would talk to Let's Encrypt, and renew the certificate(s). - + The **TLS certificates** are **associated with a domain name**, not with an IP address. diff --git a/docs/en/docs/help-fastapi.md b/docs/en/docs/help-fastapi.md index 81151032f..35d2e7b84 100644 --- a/docs/en/docs/help-fastapi.md +++ b/docs/en/docs/help-fastapi.md @@ -249,20 +249,7 @@ On the other side, there are thousands of users in the chat systems, so there's ## Sponsor the author -You can also financially support the author (me) through GitHub sponsors. - -There you could buy me a coffee â˜•ī¸ to say thanks. 😄 - -And you can also become a Silver or Gold sponsor for FastAPI. 🏅🎉 - -## Sponsor the tools that power FastAPI - -As you have seen in the documentation, FastAPI stands on the shoulders of giants, Starlette and Pydantic. - -You can also sponsor: - -* Samuel Colvin (Pydantic) -* Encode (Starlette, Uvicorn) +If your **product/company** depends on or is related to **FastAPI** and you want to reach its users, you can sponsor the author (me) through GitHub sponsors. Depending on the tier, you could get some extra benefits, like a badge in the docs. 🎁 --- diff --git a/docs/en/docs/how-to/custom-docs-ui-assets.md b/docs/en/docs/how-to/custom-docs-ui-assets.md index f717c98fa..9d2238e4f 100644 --- a/docs/en/docs/how-to/custom-docs-ui-assets.md +++ b/docs/en/docs/how-to/custom-docs-ui-assets.md @@ -98,7 +98,7 @@ You can probably right-click each link and select an option similar to `Save lin And **ReDoc** uses the file: -* `redoc.standalone.js` +* `redoc.standalone.js` After that, your file structure could look like: @@ -129,14 +129,8 @@ You should see a very long JavaScript file for **ReDoc**. It could start with something like: ```JavaScript -/*! - * ReDoc - OpenAPI/Swagger-generated API Reference Documentation - * ------------------------------------------------------------- - * Version: "2.0.0-rc.18" - * Repo: https://github.com/Redocly/redoc - */ -!function(e,t){"object"==typeof exports&&"object"==typeof m - +/*! For license information please see redoc.standalone.js.LICENSE.txt */ +!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("null")): ... ``` diff --git a/docs/en/docs/img/deployment/concepts/process-ram.drawio b/docs/en/docs/img/deployment/concepts/process-ram.drawio deleted file mode 100644 index b29c8a342..000000000 --- a/docs/en/docs/img/deployment/concepts/process-ram.drawio +++ /dev/null @@ -1,106 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/en/docs/img/deployment/concepts/process-ram.drawio.svg b/docs/en/docs/img/deployment/concepts/process-ram.drawio.svg new file mode 100644 index 000000000..a6a5c81d0 --- /dev/null +++ b/docs/en/docs/img/deployment/concepts/process-ram.drawio.svg @@ -0,0 +1,297 @@ + + + + + + + + + + + + + +
+
+
+ + + Server + + +
+
+
+
+ + Server + +
+
+
+ + + + + + + + + + +
+
+
+ + + RAM + +
+
+
+
+
+
+ + RAM + +
+
+
+ + + + + + + + + + +
+
+
+ + + CPU + +
+
+
+
+
+
+ + CPU + +
+
+
+ + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + + Process + + + + Manager + + +
+
+
+
+ + Process Manager + +
+
+
+ + + + + + + + + + +
+
+
+ + + Worker Process + + +
+
+
+
+ + Worker Process + +
+
+
+ + + + + + + + + + + + + +
+
+
+ + + Worker Process + + +
+
+
+
+ + Worker Process + +
+
+
+ + + + + + + + + + + + + +
+
+
+ + + Another Process + + +
+
+
+
+ + Another Process + +
+
+
+ + + + + + + + + + + + + + + + + + + +
+
+
+ + 1 GB + +
+
+
+
+ + 1 GB + +
+
+
+ + + + + + + +
+
+
+ + 1 GB + +
+
+
+
+ + 1 GB + +
+
+
+ + + + + + +
+ + + + + Text is not SVG - cannot display + + + +
diff --git a/docs/en/docs/img/deployment/concepts/process-ram.svg b/docs/en/docs/img/deployment/concepts/process-ram.svg deleted file mode 100644 index c1bf0d589..000000000 --- a/docs/en/docs/img/deployment/concepts/process-ram.svg +++ /dev/null @@ -1,59 +0,0 @@ -
Server
Server
RAM
RAM -
CPU
CPU -
Process Manager
Process Manager
Worker Process
Worker Process
Worker Process
Worker Process
Another Process
Another Process
1 GB
1 GB
1 GB
1 GB
Viewer does not support full SVG 1.1
diff --git a/docs/en/docs/img/deployment/https/https.drawio b/docs/en/docs/img/deployment/https/https.drawio deleted file mode 100644 index c4c8a3628..000000000 --- a/docs/en/docs/img/deployment/https/https.drawio +++ /dev/null @@ -1,277 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/en/docs/img/deployment/https/https.drawio.svg b/docs/en/docs/img/deployment/https/https.drawio.svg new file mode 100644 index 000000000..c2a65b69f --- /dev/null +++ b/docs/en/docs/img/deployment/https/https.drawio.svg @@ -0,0 +1,907 @@ + + + + + + + + + + + + + + + + + + + +
+
+
+ + + Server(s) + + +
+
+
+
+ + Server(s) + +
+
+
+ + + + + + + + + + + +
+
+
+ + DNS Servers + +
+
+
+
+ + DNS Servers + +
+
+
+ + + + + + + + + + +
+
+
+ + + TLS Termination Proxy + +
+
+
+
+
+
+ + TLS Termination Proxy + +
+
+
+ + + + + + + + + + + + + + + +
+
+
+ + Cert Renovation Program + +
+
+
+
+ + Cert Renovation Program + +
+
+
+ + + + + + + + + + + +
+
+
+ + Let's Encrypt + +
+
+
+
+ + Let's Encrypt + +
+
+
+ + + + + + + + + + + + + + + +
+
+
+ + + FastAPI + + + app for: someapp.example.com + + +
+
+
+
+ + FastAPI app for: someapp.example.com + +
+
+
+ + + + + + + +
+
+
+ + + Another app + + + : another.example.com + + +
+
+
+
+ + Another app: another.example.com + +
+
+
+ + + + + + + +
+
+
+ + + One more app + + + : onemore.example.com + + +
+
+
+
+ + One more app: onemore.example.com + +
+
+
+ + + + + + + +
+
+
+ + + A Database + + +
+
+
+
+ + A Database + +
+
+
+ + + + + + + + + + + + + +
+
+
+ + + Plain response from: someapp.example.com + + +
+
+
+
+ + Plain response from: someapp.example.com + +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ + Port 443 (HTTPS) + +
+
+
+
+ + Port 443 (HTTPS) + +
+
+
+ + + + + + + + + + + + + + +
+
+
+ + + Encrypted request for: someapp.example.com + + +
+
+
+
+ + Encrypted request for: someapp.example.com + +
+
+
+ + + + + + + +
+
+
+ + + Who is: someapp.example.com + + +
+
+
+
+ + Who is: someapp.example.com + +
+
+
+ + + + + + + +
+
+
+ + + IP: + +
+ + 123.124.125.126 + +
+
+
+
+
+ + IP:... + +
+
+
+ + + + + + + +
+
+
+ + + Renew HTTPS cert for: someapp.example.com + + +
+
+
+
+ + Renew HTTPS cert for: someapp.example.com + +
+
+
+ + + + + + + +
+
+
+ + + New HTTPS cert for: someapp.example.com + + +
+
+
+
+ + New HTTPS cert for: someapp.example.com + +
+
+
+ + + + + + + + + + +
+
+
+ + + TLS Handshake + + +
+
+
+
+ + TLS Handshake + +
+
+
+ + + + + + + + + + +
+
+
+ + + Encrypted response from: someapp.example.com + + +
+
+
+
+ + Encrypted response from: someapp.example.com + +
+
+
+ + + + + + + + + + + + + +
+
+
+ + + HTTPS certificates + +
+
+
+
+
+
+ + HTTPS certificates + +
+
+
+ + + + + + + +
+
+
+ + + + someapp.example.com + + +
+
+
+
+
+
+ + someapp.example.com + +
+
+
+ + + + + + + +
+
+
+ + + + another.example.net + + +
+
+
+
+
+
+ + another.example.net + +
+
+
+ + + + + + + +
+
+
+ + + + onemore.example.org + + +
+
+
+
+
+
+ + onemore.example.org + +
+
+
+ + + + + + + +
+
+
+ + + + IP: + +
+ + 123.124.125.126 + +
+
+
+
+
+
+
+ + IP:... + +
+
+
+ + + + + + + +
+
+
+ + + Decrypted request for: someapp.example.com + + +
+
+
+
+ + Decrypted request for: someapp.example.com + +
+
+
+ + + + + + + + + + +
+
+
+ + https://someapp.example.com + +
+
+
+
+ + https://someapp.example.com + +
+
+
+
+ + + + + Text is not SVG - cannot display + + + +
diff --git a/docs/en/docs/img/deployment/https/https.svg b/docs/en/docs/img/deployment/https/https.svg deleted file mode 100644 index 69497518a..000000000 --- a/docs/en/docs/img/deployment/https/https.svg +++ /dev/null @@ -1,62 +0,0 @@ -
Server(s)
Server(s)
https://someapp.example.com
https://someapp.example.com
DNS Servers
DNS Servers
TLS Termination Proxy
TLS Termination Proxy -
Cert Renovation Program
Cert Renovation Program
Let's Encrypt
Let's Encrypt
FastAPI app for: someapp.example.com
FastAPI app for: someapp.example.com
Another app: another.example.com
Another app: another.example.com
One more app: onemore.example.com
One more app: onemore.example.com
A Database
A Database
Plain response from: someapp.example.com
Plain response from: someapp.example.com
Port 443 (HTTPS)
Port 443 (HTTPS)
Encrypted request for: someapp.example.com
Encrypted request for: someapp.example.com
Who is: someapp.example.com
Who is: someapp.example.com
IP:
123.124.125.126
IP:...
Renew HTTPS cert for: someapp.example.com
Renew HTTPS cert for: someapp.example.com
New HTTPS cert for: someapp.example.com
New HTTPS cert for: someapp.example.com
TLS Handshake
TLS Handshake
Encrypted response from: someapp.example.com
Encrypted response from: someapp.example.com
HTTPS certificates
HTTPS certificates -
someapp.example.com
someapp.example.com -
another.example.net
another.example.net -
onemore.example.org
onemore.example.org -
IP:
123.124.125.126
IP:...
Decrypted request for: someapp.example.com
Decrypted request for: someapp.example.com
Viewer does not support full SVG 1.1
diff --git a/docs/en/docs/img/deployment/https/https01.drawio b/docs/en/docs/img/deployment/https/https01.drawio deleted file mode 100644 index 181582f9b..000000000 --- a/docs/en/docs/img/deployment/https/https01.drawio +++ /dev/null @@ -1,78 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/en/docs/img/deployment/https/https01.drawio.svg b/docs/en/docs/img/deployment/https/https01.drawio.svg new file mode 100644 index 000000000..ea128daf8 --- /dev/null +++ b/docs/en/docs/img/deployment/https/https01.drawio.svg @@ -0,0 +1,131 @@ + + + + + + + + + + + + + + + + + + +
+
+
+ + DNS Servers + +
+
+
+
+ + DNS Servers + +
+
+
+ + + + + + + + + + + + + + + + + +
+
+
+ + + Who is: someapp.example.com + + +
+
+
+
+ + Who is: someapp.example.com + +
+
+
+ + + + + + + +
+
+
+ + + IP: + +
+ + 123.124.125.126 + +
+
+
+
+
+ + IP:... + +
+
+
+ + + + + + + +
+
+
+ + https://someapp.example.com + +
+
+
+
+ + https://someapp.example.com + +
+
+
+
+ + + + + Text is not SVG - cannot display + + + +
diff --git a/docs/en/docs/img/deployment/https/https01.svg b/docs/en/docs/img/deployment/https/https01.svg deleted file mode 100644 index 2edbd0623..000000000 --- a/docs/en/docs/img/deployment/https/https01.svg +++ /dev/null @@ -1,57 +0,0 @@ -
https://someapp.example.com
https://someapp.example.com
DNS Servers
DNS Servers
Who is: someapp.example.com
Who is: someapp.example.com
IP:
123.124.125.126
IP:...
Viewer does not support full SVG 1.1
diff --git a/docs/en/docs/img/deployment/https/https02.drawio b/docs/en/docs/img/deployment/https/https02.drawio deleted file mode 100644 index 650c06d1e..000000000 --- a/docs/en/docs/img/deployment/https/https02.drawio +++ /dev/null @@ -1,110 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/en/docs/img/deployment/https/https02.drawio.svg b/docs/en/docs/img/deployment/https/https02.drawio.svg new file mode 100644 index 000000000..c29d59356 --- /dev/null +++ b/docs/en/docs/img/deployment/https/https02.drawio.svg @@ -0,0 +1,245 @@ + + + + + + + + + + + + + + + + + +
+
+
+ + + Server(s) + + +
+
+
+
+ + Server(s) + +
+
+
+ + + + + + + + + + + +
+
+
+ + DNS Servers + +
+
+
+
+ + DNS Servers + +
+
+
+ + + + + + + + + + + + + + + + + +
+
+
+ + Port 443 (HTTPS) + +
+
+
+
+ + Port 443 (HTTPS) + +
+
+
+ + + + + + + +
+
+
+ + + + IP: + +
+ + 123.124.125.126 + +
+
+
+
+
+
+
+ + IP:... + +
+
+
+ + + + + + + +
+
+
+ + + Who is: someapp.example.com + + +
+
+
+
+ + Who is: someapp.example.com + +
+
+
+ + + + + + + +
+
+
+ + + IP: + +
+ + 123.124.125.126 + +
+
+
+
+
+ + IP:... + +
+
+
+ + + + + + + + + + +
+
+
+ + + TLS Handshake + + +
+
+
+
+ + TLS Handshake + +
+
+
+ + + + + + + + + + +
+
+
+ + https://someapp.example.com + +
+
+
+
+ + https://someapp.example.com + +
+
+
+
+ + + + + Text is not SVG - cannot display + + + +
diff --git a/docs/en/docs/img/deployment/https/https02.svg b/docs/en/docs/img/deployment/https/https02.svg deleted file mode 100644 index e16b7e94a..000000000 --- a/docs/en/docs/img/deployment/https/https02.svg +++ /dev/null @@ -1,57 +0,0 @@ -
Server(s)
Server(s)
https://someapp.example.com
https://someapp.example.com
DNS Servers
DNS Servers
Port 443 (HTTPS)
Port 443 (HTTPS)
IP:
123.124.125.126
IP:...
Who is: someapp.example.com
Who is: someapp.example.com
IP:
123.124.125.126
IP:...
TLS Handshake
TLS Handshake
Viewer does not support full SVG 1.1
diff --git a/docs/en/docs/img/deployment/https/https03.drawio b/docs/en/docs/img/deployment/https/https03.drawio deleted file mode 100644 index c178fd363..000000000 --- a/docs/en/docs/img/deployment/https/https03.drawio +++ /dev/null @@ -1,131 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/en/docs/img/deployment/https/https03.drawio.svg b/docs/en/docs/img/deployment/https/https03.drawio.svg new file mode 100644 index 000000000..6971e4c9c --- /dev/null +++ b/docs/en/docs/img/deployment/https/https03.drawio.svg @@ -0,0 +1,715 @@ + + + + + + + + + + + + + + + + + + + +
+
+
+ + + Server(s) + + +
+
+
+
+ + Server(s) + +
+
+
+ + + + + + + + + + + +
+
+
+ + DNS Servers + +
+
+
+
+ + DNS Servers + +
+
+
+ + + + + + + + + + +
+
+
+ + + TLS Termination Proxy + +
+
+
+
+
+
+ + TLS Termination Proxy + +
+
+
+ + + + + + + + + + + + + + + + + +
+
+
+ + Port 443 (HTTPS) + +
+
+
+
+ + Port 443 (HTTPS) + +
+
+
+ + + + + + + +
+
+
+ + + Who is: someapp.example.com + + +
+
+
+
+ + Who is: someapp.example.com + +
+
+
+ + + + + + + +
+
+
+ + + IP: + +
+ + 123.124.125.126 + +
+
+
+
+
+ + IP:... + +
+
+
+ + + + + + + + + + +
+
+
+ + + TLS Handshake + + +
+
+
+
+ + TLS Handshake + +
+
+
+ + + + + + + + + + + + + +
+
+
+ + + HTTPS certificates + +
+
+
+
+
+
+ + HTTPS certificates + +
+
+
+ + + + + + + +
+
+
+ + + + someapp.example.com + + +
+
+
+
+
+
+ + someapp.example.com + +
+
+
+ + + + + + + +
+
+
+ + + + another.example.net + + +
+
+
+
+
+
+ + another.example.net + +
+
+
+ + + + + + + +
+
+
+ + + + onemore.example.org + + +
+
+
+
+
+
+ + onemore.example.org + +
+
+
+ + + + + + + +
+
+
+ + + + IP: + +
+ + 123.124.125.126 + +
+
+
+
+
+
+
+ + IP:... + +
+
+
+ + + + + + + +
+
+
+ + https://someapp.example.com + +
+
+
+
+ + https://someapp.example.com + +
+
+
+
+ + + + + Text is not SVG - cannot display + + + +
diff --git a/docs/en/docs/img/deployment/https/https03.svg b/docs/en/docs/img/deployment/https/https03.svg deleted file mode 100644 index 2badd1c7d..000000000 --- a/docs/en/docs/img/deployment/https/https03.svg +++ /dev/null @@ -1,62 +0,0 @@ -
Server(s)
Server(s)
https://someapp.example.com
https://someapp.example.com
DNS Servers
DNS Servers
TLS Termination Proxy
TLS Termination Proxy -
Port 443 (HTTPS)
Port 443 (HTTPS)
Who is: someapp.example.com
Who is: someapp.example.com
IP:
123.124.125.126
IP:...
TLS Handshake
TLS Handshake
HTTPS certificates
HTTPS certificates -
someapp.example.com
someapp.example.com -
another.example.net
another.example.net -
onemore.example.org
onemore.example.org -
IP:
123.124.125.126
IP:...
Viewer does not support full SVG 1.1
diff --git a/docs/en/docs/img/deployment/https/https04.drawio b/docs/en/docs/img/deployment/https/https04.drawio deleted file mode 100644 index 78a6e919a..000000000 --- a/docs/en/docs/img/deployment/https/https04.drawio +++ /dev/null @@ -1,152 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/en/docs/img/deployment/https/https04.drawio.svg b/docs/en/docs/img/deployment/https/https04.drawio.svg new file mode 100644 index 000000000..7e32bcdfe --- /dev/null +++ b/docs/en/docs/img/deployment/https/https04.drawio.svg @@ -0,0 +1,419 @@ + + + + + + + + + + + + + + + + + +
+
+
+ + + Server(s) + + +
+
+
+
+ + Server(s) + +
+
+
+ + + + + + + + + + + +
+
+
+ + DNS Servers + +
+
+
+
+ + DNS Servers + +
+
+
+ + + + + + + + + + +
+
+
+ + + TLS Termination Proxy + +
+
+
+
+
+
+ + TLS Termination Proxy + +
+
+
+ + + + + + + + + + + + + + + + + +
+
+
+ + Port 443 (HTTPS) + +
+
+
+
+ + Port 443 (HTTPS) + +
+
+
+ + + + + + + + + + + + + + +
+
+
+ + + Encrypted request for: someapp.example.com + + +
+
+
+
+ + Encrypted request for: someapp.example.com + +
+
+
+ + + + + + + +
+
+
+ + + Who is: someapp.example.com + + +
+
+
+
+ + Who is: someapp.example.com + +
+
+
+ + + + + + + +
+
+
+ + + IP: + +
+ + 123.124.125.126 + +
+
+
+
+
+ + IP:... + +
+
+
+ + + + + + + + + + +
+
+
+ + + TLS Handshake + + +
+
+
+
+ + TLS Handshake + +
+
+
+ + + + + + + + + + + + + +
+
+
+ + + HTTPS certificates + +
+
+
+
+
+
+ + HTTPS certificates + +
+
+
+ + + + + + + +
+
+
+ + + + someapp.example.com + + +
+
+
+
+
+
+ + someapp.example.com + +
+
+
+ + + + + + + +
+
+
+ + + + another.example.net + + +
+
+
+
+
+
+ + another.example.net + +
+
+
+ + + + + + + +
+
+
+ + + + onemore.example.org + + +
+
+
+
+
+
+ + onemore.example.org + +
+
+
+ + + + + + + +
+
+
+ + + + IP: + +
+ + 123.124.125.126 + +
+
+
+
+
+
+
+ + IP:... + +
+
+
+ + + + + + + +
+
+
+ + https://someapp.example.com + +
+
+
+
+ + https://someapp.example.com + +
+
+
+
+ + + + + Text is not SVG - cannot display + + + +
diff --git a/docs/en/docs/img/deployment/https/https04.svg b/docs/en/docs/img/deployment/https/https04.svg deleted file mode 100644 index 4513ac76b..000000000 --- a/docs/en/docs/img/deployment/https/https04.svg +++ /dev/null @@ -1,62 +0,0 @@ -
Server(s)
Server(s)
https://someapp.example.com
https://someapp.example.com
DNS Servers
DNS Servers
TLS Termination Proxy
TLS Termination Proxy -
Port 443 (HTTPS)
Port 443 (HTTPS)
Encrypted request for: someapp.example.com
Encrypted request for: someapp.example.com
Who is: someapp.example.com
Who is: someapp.example.com
IP:
123.124.125.126
IP:...
TLS Handshake
TLS Handshake
HTTPS certificates
HTTPS certificates -
someapp.example.com
someapp.example.com -
another.example.net
another.example.net -
onemore.example.org
onemore.example.org -
IP:
123.124.125.126
IP:...
Viewer does not support full SVG 1.1
diff --git a/docs/en/docs/img/deployment/https/https05.drawio b/docs/en/docs/img/deployment/https/https05.drawio deleted file mode 100644 index 236ecd841..000000000 --- a/docs/en/docs/img/deployment/https/https05.drawio +++ /dev/null @@ -1,166 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/en/docs/img/deployment/https/https05.drawio.svg b/docs/en/docs/img/deployment/https/https05.drawio.svg new file mode 100644 index 000000000..fed2fad16 --- /dev/null +++ b/docs/en/docs/img/deployment/https/https05.drawio.svg @@ -0,0 +1,641 @@ + + + + + + + + + + + + + + + + + + + +
+
+
+ + + Server(s) + + +
+
+
+
+ + Server(s) + +
+
+
+ + + + + + + + + + + +
+
+
+ + DNS Servers + +
+
+
+
+ + DNS Servers + +
+
+
+ + + + + + + + + + +
+
+
+ + + TLS Termination Proxy + +
+
+
+
+
+
+ + TLS Termination Proxy + +
+
+
+ + + + + + + +
+
+
+ + + FastAPI + + + app for: someapp.example.com + + +
+
+
+
+ + FastAPI app for: someapp.example.com + +
+
+
+ + + + + + + + + + + +
+
+
+ + + Decrypted request for: someapp.example.com + + +
+
+
+
+ + Decrypted request for: someapp.example.com + +
+
+
+ + + + + + + + + + + + + + + + + +
+
+
+ + Port 443 (HTTPS) + +
+
+
+
+ + Port 443 (HTTPS) + +
+
+
+ + + + + + + + + + + + + + +
+
+
+ + + Encrypted request for: someapp.example.com + + +
+
+
+
+ + Encrypted request for: someapp.example.com + +
+
+
+ + + + + + + +
+
+
+ + + Who is: someapp.example.com + + +
+
+
+
+ + Who is: someapp.example.com + +
+
+
+ + + + + + + +
+
+
+ + + IP: + +
+ + 123.124.125.126 + +
+
+
+
+
+ + IP:... + +
+
+
+ + + + + + + + + + +
+
+
+ + + TLS Handshake + + +
+
+
+
+ + TLS Handshake + +
+
+
+ + + + + + + + + + + + + +
+
+
+ + + HTTPS certificates + +
+
+
+
+
+
+ + HTTPS certificates + +
+
+
+ + + + + + + +
+
+
+ + + + someapp.example.com + + +
+
+
+
+
+
+ + someapp.example.com + +
+
+
+ + + + + + + +
+
+
+ + + + another.example.net + + +
+
+
+
+
+
+ + another.example.net + +
+
+
+ + + + + + + +
+
+
+ + + + onemore.example.org + + +
+
+
+
+
+
+ + onemore.example.org + +
+
+
+ + + + + + + +
+
+
+ + + + IP: + +
+ + 123.124.125.126 + +
+
+
+
+
+
+
+ + IP:... + +
+
+
+ + + + + + + +
+
+
+ + https://someapp.example.com + +
+
+
+
+ + https://someapp.example.com + +
+
+
+
+ + + + + Text is not SVG - cannot display + + + +
diff --git a/docs/en/docs/img/deployment/https/https05.svg b/docs/en/docs/img/deployment/https/https05.svg deleted file mode 100644 index ddcd2760a..000000000 --- a/docs/en/docs/img/deployment/https/https05.svg +++ /dev/null @@ -1,62 +0,0 @@ -
Server(s)
Server(s)
https://someapp.example.com
https://someapp.example.com
DNS Servers
DNS Servers
TLS Termination Proxy
TLS Termination Proxy -
FastAPI app for: someapp.example.com
FastAPI app for: someapp.example.com
Decrypted request for: someapp.example.com
Decrypted request for: someapp.example.com
Port 443 (HTTPS)
Port 443 (HTTPS)
Encrypted request for: someapp.example.com
Encrypted request for: someapp.example.com
Who is: someapp.example.com
Who is: someapp.example.com
IP:
123.124.125.126
IP:...
TLS Handshake
TLS Handshake
HTTPS certificates
HTTPS certificates -
someapp.example.com
someapp.example.com -
another.example.net
another.example.net -
onemore.example.org
onemore.example.org -
IP:
123.124.125.126
IP:...
Viewer does not support full SVG 1.1
diff --git a/docs/en/docs/img/deployment/https/https06.drawio b/docs/en/docs/img/deployment/https/https06.drawio deleted file mode 100644 index 9dec13184..000000000 --- a/docs/en/docs/img/deployment/https/https06.drawio +++ /dev/null @@ -1,183 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/en/docs/img/deployment/https/https06.drawio.svg b/docs/en/docs/img/deployment/https/https06.drawio.svg new file mode 100644 index 000000000..e0bd9bc6e --- /dev/null +++ b/docs/en/docs/img/deployment/https/https06.drawio.svg @@ -0,0 +1,673 @@ + + + + + + + + + + + + + + + + + + + +
+
+
+ + + Server(s) + + +
+
+
+
+ + Server(s) + +
+
+
+ + + + + + + + + + + +
+
+
+ + DNS Servers + +
+
+
+
+ + DNS Servers + +
+
+
+ + + + + + + + + + +
+
+
+ + + TLS Termination Proxy + +
+
+
+
+
+
+ + TLS Termination Proxy + +
+
+
+ + + + + + + + + + + +
+
+
+ + + FastAPI + + + app for: someapp.example.com + + +
+
+
+
+ + FastAPI app for: someapp.example.com + +
+
+
+ + + + + + + +
+
+
+ + + Plain response from: someapp.example.com + + +
+
+
+
+ + Plain response from: someapp.example.com + +
+
+
+ + + + + + + + + + + + + + +
+
+
+ + + Decrypted request for: someapp.example.com + + +
+
+
+
+ + Decrypted request for: someapp.example.com + +
+
+
+ + + + + + + + + + + + + + + + + +
+
+
+ + Port 443 (HTTPS) + +
+
+
+
+ + Port 443 (HTTPS) + +
+
+
+ + + + + + + + + + + + + + +
+
+
+ + + Encrypted request for: someapp.example.com + + +
+
+
+
+ + Encrypted request for: someapp.example.com + +
+
+
+ + + + + + + +
+
+
+ + + Who is: someapp.example.com + + +
+
+
+
+ + Who is: someapp.example.com + +
+
+
+ + + + + + + +
+
+
+ + + IP: + +
+ + 123.124.125.126 + +
+
+
+
+
+ + IP:... + +
+
+
+ + + + + + + + + + +
+
+
+ + + TLS Handshake + + +
+
+
+
+ + TLS Handshake + +
+
+
+ + + + + + + + + + + + + +
+
+
+ + + HTTPS certificates + +
+
+
+
+
+
+ + HTTPS certificates + +
+
+
+ + + + + + + +
+
+
+ + + + someapp.example.com + + +
+
+
+
+
+
+ + someapp.example.com + +
+
+
+ + + + + + + +
+
+
+ + + + another.example.net + + +
+
+
+
+
+
+ + another.example.net + +
+
+
+ + + + + + + +
+
+
+ + + + onemore.example.org + + +
+
+
+
+
+
+ + onemore.example.org + +
+
+
+ + + + + + + +
+
+
+ + + + IP: + +
+ + 123.124.125.126 + +
+
+
+
+
+
+
+ + IP:... + +
+
+
+ + + + + + + +
+
+
+ + https://someapp.example.com + +
+
+
+
+ + https://someapp.example.com + +
+
+
+
+ + + + + Text is not SVG - cannot display + + + +
diff --git a/docs/en/docs/img/deployment/https/https06.svg b/docs/en/docs/img/deployment/https/https06.svg deleted file mode 100644 index 3695de40c..000000000 --- a/docs/en/docs/img/deployment/https/https06.svg +++ /dev/null @@ -1,62 +0,0 @@ -
Server(s)
Server(s)
https://someapp.example.com
https://someapp.example.com
DNS Servers
DNS Servers
TLS Termination Proxy
TLS Termination Proxy -
FastAPI app for: someapp.example.com
FastAPI app for: someapp.example.com
Plain response from: someapp.example.com
Plain response from: someapp.example.com
Decrypted request for: someapp.example.com
Decrypted request for: someapp.example.com
Port 443 (HTTPS)
Port 443 (HTTPS)
Encrypted request for: someapp.example.com
Encrypted request for: someapp.example.com
Who is: someapp.example.com
Who is: someapp.example.com
IP:
123.124.125.126
IP:...
TLS Handshake
TLS Handshake
HTTPS certificates
HTTPS certificates -
someapp.example.com
someapp.example.com -
another.example.net
another.example.net -
onemore.example.org
onemore.example.org -
IP:
123.124.125.126
IP:...
Viewer does not support full SVG 1.1
diff --git a/docs/en/docs/img/deployment/https/https07.drawio b/docs/en/docs/img/deployment/https/https07.drawio deleted file mode 100644 index aa8f4d6be..000000000 --- a/docs/en/docs/img/deployment/https/https07.drawio +++ /dev/null @@ -1,203 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/en/docs/img/deployment/https/https07.drawio.svg b/docs/en/docs/img/deployment/https/https07.drawio.svg new file mode 100644 index 000000000..b74b33807 --- /dev/null +++ b/docs/en/docs/img/deployment/https/https07.drawio.svg @@ -0,0 +1,540 @@ + + + + + + + + + + + + + + + + + +
+
+
+ + + Server(s) + + +
+
+
+
+ + Server(s) + +
+
+
+ + + + + + + + + + + +
+
+
+ + DNS Servers + +
+
+
+
+ + DNS Servers + +
+
+
+ + + + + + + + + + +
+
+
+ + + TLS Termination Proxy + +
+
+
+
+
+
+ + TLS Termination Proxy + +
+
+
+ + + + + + + + + + + +
+
+
+ + + FastAPI + + + app for: someapp.example.com + + +
+
+
+
+ + FastAPI app for: someapp.example.com + +
+
+
+ + + + + + + +
+
+
+ + + Plain response from: someapp.example.com + + +
+
+
+
+ + Plain response from: someapp.example.com + +
+
+
+ + + + + + + + + + + + + + +
+
+
+ + + Decrypted request for: someapp.example.com + + +
+
+
+
+ + Decrypted request for: someapp.example.com + +
+
+
+ + + + + + + + + + + + + + + + + + + + + +
+
+
+ + Port 443 (HTTPS) + +
+
+
+
+ + Port 443 (HTTPS) + +
+
+
+ + + + + + + + + + + + + + +
+
+
+ + + Encrypted request for: someapp.example.com + + +
+
+
+
+ + Encrypted request for: someapp.example.com + +
+
+
+ + + + + + + +
+
+
+ + + Who is: someapp.example.com + + +
+
+
+
+ + Who is: someapp.example.com + +
+
+
+ + + + + + + +
+
+
+ + + IP: + +
+ + 123.124.125.126 + +
+
+
+
+
+ + IP:... + +
+
+
+ + + + + + + + + + +
+
+
+ + + TLS Handshake + + +
+
+
+
+ + TLS Handshake + +
+
+
+ + + + + + + + + + +
+
+
+ + + Encrypted response from: someapp.example.com + + +
+
+
+
+ + Encrypted response from: someapp.example.com + +
+
+
+ + + + + + + + + + + + + +
+
+
+ + + HTTPS certificates + +
+
+
+
+
+
+ + HTTPS certificates + +
+
+
+ + + + + + + +
+
+
+ + + + someapp.example.com + + +
+
+
+
+
+
+ + someapp.example.com + +
+
+
+ + + + + + + +
+
+
+ + + + another.example.net + + +
+
+
+
+
+
+ + another.example.net + +
+
+
+ + + + + + + +
+
+
+ + + + onemore.example.org + + +
+
+
+
+
+
+ + onemore.example.org + +
+
+
+ + + + + + + +
+
+
+ + + + IP: + +
+ + 123.124.125.126 + +
+
+
+
+
+
+
+ + IP:... + +
+
+
+ + + + + + + +
+
+
+ + https://someapp.example.com + +
+
+
+
+ + https://someapp.example.com + +
+
+
+
+ + + + + Text is not SVG - cannot display + + + +
diff --git a/docs/en/docs/img/deployment/https/https07.svg b/docs/en/docs/img/deployment/https/https07.svg deleted file mode 100644 index 551354cef..000000000 --- a/docs/en/docs/img/deployment/https/https07.svg +++ /dev/null @@ -1,62 +0,0 @@ -
Server(s)
Server(s)
https://someapp.example.com
https://someapp.example.com
DNS Servers
DNS Servers
TLS Termination Proxy
TLS Termination Proxy -
FastAPI app for: someapp.example.com
FastAPI app for: someapp.example.com
Plain response from: someapp.example.com
Plain response from: someapp.example.com
Decrypted request for: someapp.example.com
Decrypted request for: someapp.example.com
Port 443 (HTTPS)
Port 443 (HTTPS)
Encrypted request for: someapp.example.com
Encrypted request for: someapp.example.com
Who is: someapp.example.com
Who is: someapp.example.com
IP:
123.124.125.126
IP:...
TLS Handshake
TLS Handshake
Encrypted response from: someapp.example.com
Encrypted response from: someapp.example.com
HTTPS certificates
HTTPS certificates -
someapp.example.com
someapp.example.com -
another.example.net
another.example.net -
onemore.example.org
onemore.example.org -
IP:
123.124.125.126
IP:...
Viewer does not support full SVG 1.1
diff --git a/docs/en/docs/img/deployment/https/https08.drawio b/docs/en/docs/img/deployment/https/https08.drawio deleted file mode 100644 index 794b192df..000000000 --- a/docs/en/docs/img/deployment/https/https08.drawio +++ /dev/null @@ -1,217 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/en/docs/img/deployment/https/https08.drawio.svg b/docs/en/docs/img/deployment/https/https08.drawio.svg new file mode 100644 index 000000000..8fc0b31ec --- /dev/null +++ b/docs/en/docs/img/deployment/https/https08.drawio.svg @@ -0,0 +1,625 @@ + + + + + + + + + + + + + + + + + +
+
+
+ + + Server(s) + + +
+
+
+
+ + Server(s) + +
+
+
+ + + + + + + + + + + +
+
+
+ + DNS Servers + +
+
+
+
+ + DNS Servers + +
+
+
+ + + + + + + + + + +
+
+
+ + + TLS Termination Proxy + +
+
+
+
+
+
+ + TLS Termination Proxy + +
+
+
+ + + + + + + + + + + + + + + +
+
+
+ + + FastAPI + + + app for: someapp.example.com + + +
+
+
+
+ + FastAPI app for: someapp.example.com + +
+
+
+ + + + + + + +
+
+
+ + + Another app + + + : another.example.com + + +
+
+
+
+ + Another app: another.example.com + +
+
+
+ + + + + + + +
+
+
+ + + One more app + + + : onemore.example.com + + +
+
+
+
+ + One more app: onemore.example.com + +
+
+
+ + + + + + + +
+
+
+ + + A Database + + +
+
+
+
+ + A Database + +
+
+
+ + + + + + + +
+
+
+ + + Plain response from: someapp.example.com + + +
+
+
+
+ + Plain response from: someapp.example.com + +
+
+
+ + + + + + + + + + + + + + +
+
+
+ + + Decrypted request for: someapp.example.com + + +
+
+
+
+ + Decrypted request for: someapp.example.com + +
+
+
+ + + + + + + + + + + + + + + + + + + + + +
+
+
+ + Port 443 (HTTPS) + +
+
+
+
+ + Port 443 (HTTPS) + +
+
+
+ + + + + + + + + + + + + + +
+
+
+ + + Encrypted request for: someapp.example.com + + +
+
+
+
+ + Encrypted request for: someapp.example.com + +
+
+
+ + + + + + + +
+
+
+ + + Who is: someapp.example.com + + +
+
+
+
+ + Who is: someapp.example.com + +
+
+
+ + + + + + + +
+
+
+ + + IP: + +
+ + 123.124.125.126 + +
+
+
+
+
+ + IP:... + +
+
+
+ + + + + + + + + + +
+
+
+ + + TLS Handshake + + +
+
+
+
+ + TLS Handshake + +
+
+
+ + + + + + + + + + +
+
+
+ + + Encrypted response from: someapp.example.com + + +
+
+
+
+ + Encrypted response from: someapp.example.com + +
+
+
+ + + + + + + + + + + + + +
+
+
+ + + HTTPS certificates + +
+
+
+
+
+
+ + HTTPS certificates + +
+
+
+ + + + + + + +
+
+
+ + + + someapp.example.com + + +
+
+
+
+
+
+ + someapp.example.com + +
+
+
+ + + + + + + +
+
+
+ + + + another.example.net + + +
+
+
+
+
+
+ + another.example.net + +
+
+
+ + + + + + + +
+
+
+ + + + onemore.example.org + + +
+
+
+
+
+
+ + onemore.example.org + +
+
+
+ + + + + + + +
+
+
+ + + + IP: + +
+ + 123.124.125.126 + +
+
+
+
+
+
+
+ + IP:... + +
+
+
+ + + + + + + +
+
+
+ + https://someapp.example.com + +
+
+
+
+ + https://someapp.example.com + +
+
+
+
+ + + + + Text is not SVG - cannot display + + + +
diff --git a/docs/en/docs/img/deployment/https/https08.svg b/docs/en/docs/img/deployment/https/https08.svg deleted file mode 100644 index 2d4680dcc..000000000 --- a/docs/en/docs/img/deployment/https/https08.svg +++ /dev/null @@ -1,62 +0,0 @@ -
Server(s)
Server(s)
https://someapp.example.com
https://someapp.example.com
DNS Servers
DNS Servers
TLS Termination Proxy
TLS Termination Proxy -
FastAPI app for: someapp.example.com
FastAPI app for: someapp.example.com
Another app: another.example.com
Another app: another.example.com
One more app: onemore.example.com
One more app: onemore.example.com
A Database
A Database
Plain response from: someapp.example.com
Plain response from: someapp.example.com
Decrypted request for: someapp.example.com
Decrypted request for: someapp.example.com
Port 443 (HTTPS)
Port 443 (HTTPS)
Encrypted request for: someapp.example.com
Encrypted request for: someapp.example.com
Who is: someapp.example.com
Who is: someapp.example.com
IP:
123.124.125.126
IP:...
TLS Handshake
TLS Handshake
Encrypted response from: someapp.example.com
Encrypted response from: someapp.example.com
HTTPS certificates
HTTPS certificates -
someapp.example.com
someapp.example.com -
another.example.net
another.example.net -
onemore.example.org
onemore.example.org -
IP:
123.124.125.126
IP:...
Viewer does not support full SVG 1.1
diff --git a/docs/en/docs/img/sponsors/coderabbit-banner.png b/docs/en/docs/img/sponsors/coderabbit-banner.png new file mode 100644 index 000000000..da3bb3482 Binary files /dev/null and b/docs/en/docs/img/sponsors/coderabbit-banner.png differ diff --git a/docs/en/docs/img/sponsors/coderabbit.png b/docs/en/docs/img/sponsors/coderabbit.png new file mode 100644 index 000000000..1fb74569b Binary files /dev/null and b/docs/en/docs/img/sponsors/coderabbit.png differ diff --git a/docs/en/docs/img/sponsors/dribia.png b/docs/en/docs/img/sponsors/dribia.png new file mode 100644 index 000000000..f40e14086 Binary files /dev/null and b/docs/en/docs/img/sponsors/dribia.png differ diff --git a/docs/en/docs/img/sponsors/interviewpal.png b/docs/en/docs/img/sponsors/interviewpal.png new file mode 100644 index 000000000..e40ed01fd Binary files /dev/null and b/docs/en/docs/img/sponsors/interviewpal.png differ diff --git a/docs/en/docs/img/sponsors/lambdatest.png b/docs/en/docs/img/sponsors/lambdatest.png new file mode 100644 index 000000000..674cbcb89 Binary files /dev/null and b/docs/en/docs/img/sponsors/lambdatest.png differ diff --git a/docs/en/docs/img/sponsors/mobbai-banner.png b/docs/en/docs/img/sponsors/mobbai-banner.png new file mode 100644 index 000000000..1f59294ab Binary files /dev/null and b/docs/en/docs/img/sponsors/mobbai-banner.png differ diff --git a/docs/en/docs/img/sponsors/mobbai.png b/docs/en/docs/img/sponsors/mobbai.png new file mode 100644 index 000000000..b519fd885 Binary files /dev/null and b/docs/en/docs/img/sponsors/mobbai.png differ diff --git a/docs/en/docs/img/sponsors/permit.png b/docs/en/docs/img/sponsors/permit.png new file mode 100644 index 000000000..4f07f22e2 Binary files /dev/null and b/docs/en/docs/img/sponsors/permit.png differ diff --git a/docs/en/docs/img/sponsors/railway-banner.png b/docs/en/docs/img/sponsors/railway-banner.png new file mode 100644 index 000000000..f6146a7c1 Binary files /dev/null and b/docs/en/docs/img/sponsors/railway-banner.png differ diff --git a/docs/en/docs/img/sponsors/railway.png b/docs/en/docs/img/sponsors/railway.png new file mode 100644 index 000000000..dc6ccacc4 Binary files /dev/null and b/docs/en/docs/img/sponsors/railway.png differ diff --git a/docs/en/docs/img/sponsors/subtotal-banner.svg b/docs/en/docs/img/sponsors/subtotal-banner.svg new file mode 100644 index 000000000..3d6c98dfc --- /dev/null +++ b/docs/en/docs/img/sponsors/subtotal-banner.svg @@ -0,0 +1,133 @@ + + + + + sponsorship-banner + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/en/docs/img/sponsors/subtotal.svg b/docs/en/docs/img/sponsors/subtotal.svg new file mode 100644 index 000000000..b944c1b2c --- /dev/null +++ b/docs/en/docs/img/sponsors/subtotal.svg @@ -0,0 +1,31 @@ + + + sponsorship-badge + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/en/docs/img/sponsors/zuplo.png b/docs/en/docs/img/sponsors/zuplo.png index 7a7c16862..6a4ed233e 100644 Binary files a/docs/en/docs/img/sponsors/zuplo.png and b/docs/en/docs/img/sponsors/zuplo.png differ diff --git a/docs/en/docs/img/tutorial/bigger-applications/package.drawio b/docs/en/docs/img/tutorial/bigger-applications/package.drawio deleted file mode 100644 index cab3de2ca..000000000 --- a/docs/en/docs/img/tutorial/bigger-applications/package.drawio +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/en/docs/img/tutorial/bigger-applications/package.drawio.svg b/docs/en/docs/img/tutorial/bigger-applications/package.drawio.svg new file mode 100644 index 000000000..7e28f4a68 --- /dev/null +++ b/docs/en/docs/img/tutorial/bigger-applications/package.drawio.svg @@ -0,0 +1,420 @@ + + + + + + + + + + + + + + + + +
+
+
+ + Package app +
+ app/__init__.py +
+
+
+
+
+ + Package app... + +
+
+
+ + + + + + + +
+
+
+ + + Module app.main + +
+ + app/main.py + +
+
+
+
+
+ + Module app.main... + +
+
+
+ + + + + + + +
+
+
+ + + Module app.dependencies + +
+ + app/dependencies.py + +
+
+
+
+
+ + Module app.dependencies... + +
+
+
+ + + + + + + + + + +
+
+
+ + + Subpackage app.internal +
+
+ + app/internal/__init__.py + +
+ +
+
+
+
+
+
+ + Subpackage app.internal... + +
+
+
+ + + + + + + +
+
+
+ + + Module app.internal.admin + +
+ + app/internal/admin.py + +
+
+
+
+
+ + Module app.internal.admin... + +
+
+
+ + + + + + + + + + +
+
+
+ + + Subpackage app.routers +
+ app/routers/__init__.py +
+
+
+
+
+
+
+ + Subpackage app.routers... + +
+
+
+ + + + + + + +
+
+
+ + + Module app.routers.items + +
+ + app/routers/items.py + +
+
+
+
+
+ + Module app.routers.items... + +
+
+
+ + + + + + + +
+
+
+ + + Module app.routers.users + +
+ + app/routers/users.py + +
+
+
+
+
+ + Module app.routers.users... + +
+
+
+
+ + + + + Text is not SVG - cannot display + + + +
diff --git a/docs/en/docs/img/tutorial/bigger-applications/package.svg b/docs/en/docs/img/tutorial/bigger-applications/package.svg deleted file mode 100644 index 44da1dc30..000000000 --- a/docs/en/docs/img/tutorial/bigger-applications/package.svg +++ /dev/null @@ -1 +0,0 @@ -
Package app
app/__init__.py
Package app...
Module app.main
app/main.py
Module app.main...
Module app.dependencies
app/dependencies.py
Module app.dependencies...
Subpackage app.internal
app/internal/__init__.py
Subpackage app.internal...
Module app.internal.admin
app/internal/admin.py
Module app.internal.admin...
Subpackage app.routers
app/routers/__init__.py
Subpackage app.routers...
Module app.routers.items
app/routers/items.py
Module app.routers.items...
Module app.routers.users
app/routers/users.py
Module app.routers.users...
Viewer does not support full SVG 1.1
diff --git a/docs/en/docs/index.md b/docs/en/docs/index.md index cbe71c87d..938882d7d 100644 --- a/docs/en/docs/index.md +++ b/docs/en/docs/index.md @@ -12,7 +12,7 @@

- Test + Test Coverage @@ -146,7 +146,7 @@ $ pip install "fastapi[standard]" ### Create it -* Create a file `main.py` with: +Create a file `main.py` with: ```Python from typing import Union @@ -468,15 +468,20 @@ Used by Starlette: * jinja2 - Required if you want to use the default template configuration. * python-multipart - Required if you want to support form "parsing", with `request.form()`. -Used by FastAPI / Starlette: +Used by FastAPI: * uvicorn - for the server that loads and serves your application. This includes `uvicorn[standard]`, which includes some dependencies (e.g. `uvloop`) needed for high performance serving. -* `fastapi-cli` - to provide the `fastapi` command. +* `fastapi-cli[standard]` - to provide the `fastapi` command. + * This includes `fastapi-cloud-cli`, which allows you to deploy your FastAPI application to FastAPI Cloud. ### Without `standard` Dependencies If you don't want to include the `standard` optional dependencies, you can install with `pip install fastapi` instead of `pip install "fastapi[standard]"`. +### Without `fastapi-cloud-cli` + +If you want to install FastAPI with the standard dependencies but without the `fastapi-cloud-cli`, you can install with `pip install "fastapi[standard-no-fastapi-cloud-cli]"`. + ### Additional Optional Dependencies There are some additional dependencies you might want to install. diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index ad8b85d0e..b57ff80f0 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -9,6 +9,363 @@ hide: ### Docs +* 📝 Add discussion template for new language translation requests. PR [#13535](https://github.com/fastapi/fastapi/pull/13535) by [@alejsdev](https://github.com/alejsdev). + +### Translations + +* 🌐 Update Portuguese Translation for `docs/pt/docs/async.md`. PR [#13863](https://github.com/fastapi/fastapi/pull/13863) by [@EdmilsonRodrigues](https://github.com/EdmilsonRodrigues). +* 📝 Fix highlight line in `docs/ja/docs/tutorial/body.md`. PR [#13927](https://github.com/fastapi/fastapi/pull/13927) by [@KoyoMiyazaki](https://github.com/KoyoMiyazaki). +* 🌐 Add Persian translation for `docs/fa/docs/environment-variables.md`. PR [#13923](https://github.com/fastapi/fastapi/pull/13923) by [@Mohammad222PR](https://github.com/Mohammad222PR). +* 🌐 Add Persian translation for `docs/fa/docs/python-types.md`. PR [#13524](https://github.com/fastapi/fastapi/pull/13524) by [@Mohammad222PR](https://github.com/Mohammad222PR). +* 🌐 Update Portuguese Translation for `docs/pt/docs/project-generation.md`. PR [#13875](https://github.com/fastapi/fastapi/pull/13875) by [@EdmilsonRodrigues](https://github.com/EdmilsonRodrigues). +* 🌐 Add Persian translation for `docs/fa/docs/async.md`. PR [#13541](https://github.com/fastapi/fastapi/pull/13541) by [@Mohammad222PR](https://github.com/Mohammad222PR). +* 🌐 Add Bangali translation for `docs/bn/about/index.md`. PR [#13882](https://github.com/fastapi/fastapi/pull/13882) by [@sajjadrahman56](https://github.com/sajjadrahman56). + +### Internal + +* đŸ‘Ĩ Update FastAPI People - Experts. PR [#13963](https://github.com/fastapi/fastapi/pull/13963) by [@tiangolo](https://github.com/tiangolo). +* âŦ† Bump ruff from 0.11.2 to 0.12.7. PR [#13957](https://github.com/fastapi/fastapi/pull/13957) by [@dependabot[bot]](https://github.com/apps/dependabot). +* âŦ† Bump cairosvg from 2.7.1 to 2.8.2. PR [#13959](https://github.com/fastapi/fastapi/pull/13959) by [@dependabot[bot]](https://github.com/apps/dependabot). +* âŦ† Bump pydantic-ai from 0.0.30 to 0.4.10. PR [#13958](https://github.com/fastapi/fastapi/pull/13958) by [@dependabot[bot]](https://github.com/apps/dependabot). +* đŸ‘Ĩ Update FastAPI GitHub topic repositories. PR [#13962](https://github.com/fastapi/fastapi/pull/13962) by [@tiangolo](https://github.com/tiangolo). +* âŦ† Bump mkdocs-material from 9.6.15 to 9.6.16. PR [#13961](https://github.com/fastapi/fastapi/pull/13961) by [@dependabot[bot]](https://github.com/apps/dependabot). +* âŦ† Bump tiangolo/latest-changes from 0.3.2 to 0.4.0. PR [#13952](https://github.com/fastapi/fastapi/pull/13952) by [@dependabot[bot]](https://github.com/apps/dependabot). +* đŸ‘Ĩ Update FastAPI People - Sponsors. PR [#13956](https://github.com/fastapi/fastapi/pull/13956) by [@tiangolo](https://github.com/tiangolo). +* đŸ‘Ĩ Update FastAPI People - Contributors and Translators. PR [#13955](https://github.com/fastapi/fastapi/pull/13955) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Update sponsors: Databento link and sponsors_badge data. PR [#13954](https://github.com/fastapi/fastapi/pull/13954) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Update sponsors: Add Railway. PR [#13953](https://github.com/fastapi/fastapi/pull/13953) by [@tiangolo](https://github.com/tiangolo). +* âš’ī¸ Update translate script, update prompt to minimize generated diff. PR [#13947](https://github.com/fastapi/fastapi/pull/13947) by [@YuriiMotov](https://github.com/YuriiMotov). +* âŦ† [pre-commit.ci] pre-commit autoupdate. PR [#13943](https://github.com/fastapi/fastapi/pull/13943) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). +* âš’ī¸ Tweak translate script and CI. PR [#13939](https://github.com/fastapi/fastapi/pull/13939) by [@tiangolo](https://github.com/tiangolo). +* 👷 Add CI to translate with LLMs. PR [#13937](https://github.com/fastapi/fastapi/pull/13937) by [@tiangolo](https://github.com/tiangolo). +* âš’ī¸ Update translate script, show and update outdated translations. PR [#13933](https://github.com/fastapi/fastapi/pull/13933) by [@tiangolo](https://github.com/tiangolo). +* 🔨 Refactor translate script with extra feedback (prints). PR [#13932](https://github.com/fastapi/fastapi/pull/13932) by [@tiangolo](https://github.com/tiangolo). +* 🔨 Update translations script to remove old (removed) files. PR [#13928](https://github.com/fastapi/fastapi/pull/13928) by [@tiangolo](https://github.com/tiangolo). +* âŦ† [pre-commit.ci] pre-commit autoupdate. PR [#13894](https://github.com/fastapi/fastapi/pull/13894) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). +* âŦ† Update httpx requirement to >=0.23.0,<0.29.0. PR [#13114](https://github.com/fastapi/fastapi/pull/13114) by [@yan12125](https://github.com/yan12125). +* 🔧 Update sponsors: Add Mobb. PR [#13916](https://github.com/fastapi/fastapi/pull/13916) by [@tiangolo](https://github.com/tiangolo). +* đŸ‘Ĩ Update FastAPI People - Experts. PR [#13889](https://github.com/fastapi/fastapi/pull/13889) by [@tiangolo](https://github.com/tiangolo). +* 🔨 Update FastAPI People sleep interval, use external settings. PR [#13888](https://github.com/fastapi/fastapi/pull/13888) by [@tiangolo](https://github.com/tiangolo). + +## 0.116.1 + +### Upgrades + +* âŦ†ī¸ Upgrade Starlette supported version range to `>=0.40.0,<0.48.0`. PR [#13884](https://github.com/fastapi/fastapi/pull/13884) by [@tiangolo](https://github.com/tiangolo). + +### Docs + +* 📝 Add notification about impending changes in Translations to `docs/en/docs/contributing.md`. PR [#13886](https://github.com/fastapi/fastapi/pull/13886) by [@YuriiMotov](https://github.com/YuriiMotov). + +### Internal + +* âŦ† [pre-commit.ci] pre-commit autoupdate. PR [#13871](https://github.com/fastapi/fastapi/pull/13871) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). + +## 0.116.0 + +### Features + +* ✨ Add support for deploying to FastAPI Cloud with `fastapi deploy`. PR [#13870](https://github.com/fastapi/fastapi/pull/13870) by [@tiangolo](https://github.com/tiangolo). + +Installing `fastapi[standard]` now includes `fastapi-cloud-cli`. + +This will allow you to deploy to [FastAPI Cloud](https://fastapicloud.com) with the `fastapi deploy` command. + +If you want to install `fastapi` with the standard dependencies but without `fastapi-cloud-cli`, you can install instead `fastapi[standard-no-fastapi-cloud-cli]`. + +### Translations + +* 🌐 Add Russian translation for `docs/ru/docs/advanced/response-directly.md`. PR [#13801](https://github.com/fastapi/fastapi/pull/13801) by [@NavesSapnis](https://github.com/NavesSapnis). +* 🌐 Add Russian translation for `docs/ru/docs/advanced/additional-status-codes.md`. PR [#13799](https://github.com/fastapi/fastapi/pull/13799) by [@NavesSapnis](https://github.com/NavesSapnis). +* 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/body-updates.md`. PR [#13804](https://github.com/fastapi/fastapi/pull/13804) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). + +### Internal + +* âŦ† Bump pillow from 11.1.0 to 11.3.0. PR [#13852](https://github.com/fastapi/fastapi/pull/13852) by [@dependabot[bot]](https://github.com/apps/dependabot). +* đŸ‘Ĩ Update FastAPI People - Sponsors. PR [#13846](https://github.com/fastapi/fastapi/pull/13846) by [@tiangolo](https://github.com/tiangolo). +* đŸ‘Ĩ Update FastAPI GitHub topic repositories. PR [#13848](https://github.com/fastapi/fastapi/pull/13848) by [@tiangolo](https://github.com/tiangolo). +* âŦ† Bump mkdocs-material from 9.6.1 to 9.6.15. PR [#13849](https://github.com/fastapi/fastapi/pull/13849) by [@dependabot[bot]](https://github.com/apps/dependabot). +* âŦ† [pre-commit.ci] pre-commit autoupdate. PR [#13843](https://github.com/fastapi/fastapi/pull/13843) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). +* đŸ‘Ĩ Update FastAPI People - Contributors and Translators. PR [#13845](https://github.com/fastapi/fastapi/pull/13845) by [@tiangolo](https://github.com/tiangolo). + +## 0.115.14 + +### Fixes + +* 🐛 Fix support for unions when using `Form`. PR [#13827](https://github.com/fastapi/fastapi/pull/13827) by [@patrick91](https://github.com/patrick91). + +### Docs + +* âœī¸ Fix grammar mistake in `docs/en/docs/advanced/response-directly.md`. PR [#13800](https://github.com/fastapi/fastapi/pull/13800) by [@NavesSapnis](https://github.com/NavesSapnis). +* 📝 Update Speakeasy URL to Speakeasy Sandbox. PR [#13697](https://github.com/fastapi/fastapi/pull/13697) by [@ndimares](https://github.com/ndimares). + +### Translations + +* 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/response-model.md`. PR [#13792](https://github.com/fastapi/fastapi/pull/13792) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). +* 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/security/index.md`. PR [#13805](https://github.com/fastapi/fastapi/pull/13805) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). +* âœī¸ Fix typo in `docs/ja/docs/tutorial/encoder.md`. PR [#13815](https://github.com/fastapi/fastapi/pull/13815) by [@ruzia](https://github.com/ruzia). +* âœī¸ Fix typo in `docs/ja/docs/tutorial/handling-errors.md`. PR [#13814](https://github.com/fastapi/fastapi/pull/13814) by [@ruzia](https://github.com/ruzia). +* âœī¸ Fix typo in `docs/ja/docs/tutorial/body-fields.md`. PR [#13802](https://github.com/fastapi/fastapi/pull/13802) by [@ruzia](https://github.com/ruzia). +* 🌐 Add Russian translation for `docs/ru/docs/advanced/index.md`. PR [#13797](https://github.com/fastapi/fastapi/pull/13797) by [@NavesSapnis](https://github.com/NavesSapnis). + +### Internal + +* âŦ† [pre-commit.ci] pre-commit autoupdate. PR [#13823](https://github.com/fastapi/fastapi/pull/13823) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). + +## 0.115.13 + +### Fixes + +* 🐛 Fix truncating the model's description with form feed (`\f`) character for Pydantic V2. PR [#13698](https://github.com/fastapi/fastapi/pull/13698) by [@YuriiMotov](https://github.com/YuriiMotov). + +### Refactors + +* ✨ Add `refreshUrl` parameter in `OAuth2PasswordBearer`. PR [#11460](https://github.com/fastapi/fastapi/pull/11460) by [@snosratiershad](https://github.com/snosratiershad). +* 🚸 Set format to password for fields `password` and `client_secret` in `OAuth2PasswordRequestForm`, make docs show password fields for passwords. PR [#11032](https://github.com/fastapi/fastapi/pull/11032) by [@Thodoris1999](https://github.com/Thodoris1999). +* ✅ Simplify tests for `settings`. PR [#13505](https://github.com/fastapi/fastapi/pull/13505) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). +* ✅ Simplify tests for `validate_response_recursive`. PR [#13507](https://github.com/fastapi/fastapi/pull/13507) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). + +### Upgrades + +* âŦ†ī¸ Update ReDoc to version 2.x. PR [#9700](https://github.com/fastapi/fastapi/pull/9700) by [@joakimnordling](https://github.com/joakimnordling). + +### Docs + +* 📝 Add annotations to HTTP middleware example. PR [#11530](https://github.com/fastapi/fastapi/pull/11530) by [@Kilo59](https://github.com/Kilo59). +* 📝 Clarify in CORS docs that wildcards and credentials are mutually exclusive. PR [#9829](https://github.com/fastapi/fastapi/pull/9829) by [@dfioravanti](https://github.com/dfioravanti). +* âœī¸ Fix typo in docstring. PR [#13532](https://github.com/fastapi/fastapi/pull/13532) by [@comp64](https://github.com/comp64). +* 📝 Clarify guidance on using `async def` without `await`. PR [#13642](https://github.com/fastapi/fastapi/pull/13642) by [@swastikpradhan1999](https://github.com/swastikpradhan1999). +* 📝 Update exclude-parameters-from-openapi documentation links. PR [#13600](https://github.com/fastapi/fastapi/pull/13600) by [@timonrieger](https://github.com/timonrieger). +* 📝 Clarify the middleware execution order in docs. PR [#13699](https://github.com/fastapi/fastapi/pull/13699) by [@YuriiMotov](https://github.com/YuriiMotov). +* 🍱 Update Drawio diagrams SVGs, single file per diagram, sans-serif font. PR [#13706](https://github.com/fastapi/fastapi/pull/13706) by [@tiangolo](https://github.com/tiangolo). +* 📝 Update docs for "Help FastAPI", simplify and reduce "sponsor" section. PR [#13670](https://github.com/fastapi/fastapi/pull/13670) by [@tiangolo](https://github.com/tiangolo). +* 📝 Remove unnecessary bullet from docs. PR [#13641](https://github.com/fastapi/fastapi/pull/13641) by [@Adamowoc](https://github.com/Adamowoc). +* âœī¸ Fix syntax error in `docs/en/docs/tutorial/handling-errors.md`. PR [#13623](https://github.com/fastapi/fastapi/pull/13623) by [@gsheni](https://github.com/gsheni). +* 📝 Fix typo in documentation. PR [#13599](https://github.com/fastapi/fastapi/pull/13599) by [@Taoup](https://github.com/Taoup). +* 📝 Fix liblab client generation doc link. PR [#13571](https://github.com/fastapi/fastapi/pull/13571) by [@EFord36](https://github.com/EFord36). +* âœī¸ Fix talk information typo. PR [#13544](https://github.com/fastapi/fastapi/pull/13544) by [@blueswen](https://github.com/blueswen). +* 📝 Add External Link: Taiwanese talk on FastAPI with observability . PR [#13527](https://github.com/fastapi/fastapi/pull/13527) by [@blueswen](https://github.com/blueswen). + +### Translations + +* 🌐 Add Russian Translation for `docs/ru/docs/advanced/response-change-status-code.md`. PR [#13791](https://github.com/fastapi/fastapi/pull/13791) by [@NavesSapnis](https://github.com/NavesSapnis). +* 🌐 Add Persian translation for `docs/fa/docs/learn/index.md`. PR [#13518](https://github.com/fastapi/fastapi/pull/13518) by [@Mohammad222PR](https://github.com/Mohammad222PR). +* 🌐 Add Korean translation for `docs/ko/docs/advanced/sub-applications.md`. PR [#4543](https://github.com/fastapi/fastapi/pull/4543) by [@NinaHwang](https://github.com/NinaHwang). +* 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/schema-extra-example.md`. PR [#13769](https://github.com/fastapi/fastapi/pull/13769) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). +* âœī¸ Remove redundant words in docs/zh/docs/python-types.md. PR [#13774](https://github.com/fastapi/fastapi/pull/13774) by [@CharleeWa](https://github.com/CharleeWa). +* 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/query-param-models.md`. PR [#13748](https://github.com/fastapi/fastapi/pull/13748) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). +* 🌐 Add Bengali translation for `docs/bn/docs/environment-variables.md`. PR [#13629](https://github.com/fastapi/fastapi/pull/13629) by [@SakibSibly](https://github.com/SakibSibly). +* 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/query-params-str-validations.md` page. PR [#13546](https://github.com/fastapi/fastapi/pull/13546) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). +* 🌐 Add Russian translation for `docs/ru/docs/tutorial/cookie-param-models.md`. PR [#13616](https://github.com/fastapi/fastapi/pull/13616) by [@EgorOnishchuk](https://github.com/EgorOnishchuk). +* 🌐 Add Korean translation for `docs/ko/docs/tutorial/extra-models.md`. PR [#13063](https://github.com/fastapi/fastapi/pull/13063) by [@timothy-jeong](https://github.com/timothy-jeong). +* 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/path-params-numeric-validations.md` page. PR [#13548](https://github.com/fastapi/fastapi/pull/13548) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). +* 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/middleware.md` page. PR [#13520](https://github.com/fastapi/fastapi/pull/13520) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). +* 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/background-tasks.md` page. PR [#13502](https://github.com/fastapi/fastapi/pull/13502) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). +* 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/cors.md` page. PR [#13519](https://github.com/fastapi/fastapi/pull/13519) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). +* 🌐 Update Korean translation for `docs/ko/docs/advanced/events.md`. PR [#13487](https://github.com/fastapi/fastapi/pull/13487) by [@bom1215](https://github.com/bom1215). +* 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/handling-errors.md` page. PR [#13420](https://github.com/fastapi/fastapi/pull/13420) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). +* 🌐 Add Russian translation for `docs/ru/docs/tutorial/request-form-models.md`. PR [#13552](https://github.com/fastapi/fastapi/pull/13552) by [@EgorOnishchuk](https://github.com/EgorOnishchuk). +* 📝 Fix internal anchor link in Spanish deployment docs. PR [#13737](https://github.com/fastapi/fastapi/pull/13737) by [@fabianfalon](https://github.com/fabianfalon). +* 🌐 Update Korean translation for `docs/ko/docs/virtual-environments.md`. PR [#13630](https://github.com/fastapi/fastapi/pull/13630) by [@sungchan1](https://github.com/sungchan1). +* 🌐 Add Russian translation for `docs/ru/docs/tutorial/header-param-models.md`. PR [#13526](https://github.com/fastapi/fastapi/pull/13526) by [@minaton-ru](https://github.com/minaton-ru). +* 🌐 Update Chinese translation for `docs/zh/docs/tutorial/index.md`. PR [#13374](https://github.com/fastapi/fastapi/pull/13374) by [@Zhongheng-Cheng](https://github.com/Zhongheng-Cheng). +* 🌐 Update Chinese translation for `docs/zh/docs/deployment/manually.md`. PR [#13324](https://github.com/fastapi/fastapi/pull/13324) by [@Zhongheng-Cheng](https://github.com/Zhongheng-Cheng). +* 🌐 Update Chinese translation for `docs/zh/docs/deployment/server-workers.md`. PR [#13292](https://github.com/fastapi/fastapi/pull/13292) by [@Zhongheng-Cheng](https://github.com/Zhongheng-Cheng). +* 🌐 Update Chinese translation for `docs/zh/docs/tutorial/first-steps.md`. PR [#13348](https://github.com/fastapi/fastapi/pull/13348) by [@Zhongheng-Cheng](https://github.com/Zhongheng-Cheng). + +### Internal + +* 🔨 Resolve Pydantic deprecation warnings in internal script. PR [#13696](https://github.com/fastapi/fastapi/pull/13696) by [@emmanuel-ferdman](https://github.com/emmanuel-ferdman). +* 🔧 Update sponsors: remove Porter. PR [#13783](https://github.com/fastapi/fastapi/pull/13783) by [@tiangolo](https://github.com/tiangolo). +* âŦ† [pre-commit.ci] pre-commit autoupdate. PR [#13781](https://github.com/fastapi/fastapi/pull/13781) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). +* âŦ† [pre-commit.ci] pre-commit autoupdate. PR [#13757](https://github.com/fastapi/fastapi/pull/13757) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). +* âŦ† Bump griffe-typingdoc from 0.2.7 to 0.2.8. PR [#13751](https://github.com/fastapi/fastapi/pull/13751) by [@dependabot[bot]](https://github.com/apps/dependabot). +* 🍱 Update sponsors: Dribia badge size. PR [#13773](https://github.com/fastapi/fastapi/pull/13773) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Update sponsors: add Dribia. PR [#13771](https://github.com/fastapi/fastapi/pull/13771) by [@tiangolo](https://github.com/tiangolo). +* âŦ† Bump typer from 0.15.3 to 0.16.0. PR [#13752](https://github.com/fastapi/fastapi/pull/13752) by [@dependabot[bot]](https://github.com/apps/dependabot). +* đŸ‘Ĩ Update FastAPI GitHub topic repositories. PR [#13754](https://github.com/fastapi/fastapi/pull/13754) by [@tiangolo](https://github.com/tiangolo). +* đŸ‘Ĩ Update FastAPI People - Sponsors. PR [#13750](https://github.com/fastapi/fastapi/pull/13750) by [@tiangolo](https://github.com/tiangolo). +* đŸ‘Ĩ Update FastAPI People - Contributors and Translators. PR [#13749](https://github.com/fastapi/fastapi/pull/13749) by [@tiangolo](https://github.com/tiangolo). +* âŦ† [pre-commit.ci] pre-commit autoupdate. PR [#13736](https://github.com/fastapi/fastapi/pull/13736) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). +* 🔧 Update sponsors: Add InterviewPal. PR [#13728](https://github.com/fastapi/fastapi/pull/13728) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Remove Google Analytics. PR [#13727](https://github.com/fastapi/fastapi/pull/13727) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Update sponsors: remove MongoDB. PR [#13725](https://github.com/fastapi/fastapi/pull/13725) by [@tiangolo](https://github.com/tiangolo). +* âŦ† [pre-commit.ci] pre-commit autoupdate. PR [#13711](https://github.com/fastapi/fastapi/pull/13711) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). +* 🔧 Update sponsors: add Subtotal. PR [#13701](https://github.com/fastapi/fastapi/pull/13701) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Update sponsors: remove deepset / Haystack. PR [#13700](https://github.com/fastapi/fastapi/pull/13700) by [@tiangolo](https://github.com/tiangolo). +* âŦ† [pre-commit.ci] pre-commit autoupdate. PR [#13688](https://github.com/fastapi/fastapi/pull/13688) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). +* đŸ‘Ĩ Update FastAPI People - Experts. PR [#13671](https://github.com/fastapi/fastapi/pull/13671) by [@tiangolo](https://github.com/tiangolo). +* âŦ† Bump typer from 0.12.5 to 0.15.3. PR [#13666](https://github.com/fastapi/fastapi/pull/13666) by [@dependabot[bot]](https://github.com/apps/dependabot). +* âŦ† Bump sqlmodel from 0.0.23 to 0.0.24. PR [#13665](https://github.com/fastapi/fastapi/pull/13665) by [@dependabot[bot]](https://github.com/apps/dependabot). +* 🔧 Update Sponsors: Zuplo logo and alt text. PR [#13645](https://github.com/fastapi/fastapi/pull/13645) by [@martyndavies](https://github.com/martyndavies). +* đŸ‘Ĩ Update FastAPI GitHub topic repositories. PR [#13667](https://github.com/fastapi/fastapi/pull/13667) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Update links for LinkedIn and bottom. PR [#13669](https://github.com/fastapi/fastapi/pull/13669) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Update sponsors: remove Bump.sh and Coherence. PR [#13668](https://github.com/fastapi/fastapi/pull/13668) by [@tiangolo](https://github.com/tiangolo). +* đŸ‘Ĩ Update FastAPI People - Sponsors. PR [#13664](https://github.com/fastapi/fastapi/pull/13664) by [@tiangolo](https://github.com/tiangolo). +* đŸ‘Ĩ Update FastAPI People - Contributors and Translators. PR [#13662](https://github.com/fastapi/fastapi/pull/13662) by [@tiangolo](https://github.com/tiangolo). +* âŦ† [pre-commit.ci] pre-commit autoupdate. PR [#13656](https://github.com/fastapi/fastapi/pull/13656) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). +* ✅ Use `inline-snapshot` to support different Pydantic versions in the test suite. PR [#12534](https://github.com/fastapi/fastapi/pull/12534) by [@15r10nk](https://github.com/15r10nk). +* âŦ† Bump astral-sh/setup-uv from 5 to 6. PR [#13648](https://github.com/fastapi/fastapi/pull/13648) by [@dependabot[bot]](https://github.com/apps/dependabot). +* âŦ† [pre-commit.ci] pre-commit autoupdate. PR [#13634](https://github.com/fastapi/fastapi/pull/13634) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). +* âŦ† [pre-commit.ci] pre-commit autoupdate. PR [#13619](https://github.com/fastapi/fastapi/pull/13619) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). +* âŦ† [pre-commit.ci] pre-commit autoupdate. PR [#13594](https://github.com/fastapi/fastapi/pull/13594) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). +* đŸ‘Ĩ Update FastAPI People - Experts. PR [#13568](https://github.com/fastapi/fastapi/pull/13568) by [@tiangolo](https://github.com/tiangolo). +* đŸ‘Ĩ Update FastAPI GitHub topic repositories. PR [#13565](https://github.com/fastapi/fastapi/pull/13565) by [@tiangolo](https://github.com/tiangolo). +* đŸ‘Ĩ Update FastAPI People - Sponsors. PR [#13559](https://github.com/fastapi/fastapi/pull/13559) by [@tiangolo](https://github.com/tiangolo). +* đŸ‘Ĩ Update FastAPI People - Contributors and Translators. PR [#13558](https://github.com/fastapi/fastapi/pull/13558) by [@tiangolo](https://github.com/tiangolo). +* âŦ† Bump dirty-equals from 0.8.0 to 0.9.0. PR [#13561](https://github.com/fastapi/fastapi/pull/13561) by [@dependabot[bot]](https://github.com/apps/dependabot). +* 🔧 Clean up `docs/en/mkdocs.yml` configuration file. PR [#13542](https://github.com/fastapi/fastapi/pull/13542) by [@svlandeg](https://github.com/svlandeg). +* âŦ† [pre-commit.ci] pre-commit autoupdate. PR [#12986](https://github.com/fastapi/fastapi/pull/12986) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). + +## 0.115.12 + +### Fixes + +* 🐛 Fix `convert_underscores=False` for header Pydantic models. PR [#13515](https://github.com/fastapi/fastapi/pull/13515) by [@tiangolo](https://github.com/tiangolo). + +### Docs + +* 📝 Update `docs/en/docs/tutorial/middleware.md`. PR [#13444](https://github.com/fastapi/fastapi/pull/13444) by [@Rishat-F](https://github.com/Rishat-F). +* đŸ‘Ĩ Update FastAPI People - Experts. PR [#13493](https://github.com/fastapi/fastapi/pull/13493) by [@tiangolo](https://github.com/tiangolo). + +### Translations + +* 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/metadata.md` page. PR [#13459](https://github.com/fastapi/fastapi/pull/13459) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). +* 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/response-status-code.md` page. PR [#13462](https://github.com/fastapi/fastapi/pull/13462) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). +* 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/cookie-param-models.md` page. PR [#13460](https://github.com/fastapi/fastapi/pull/13460) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). +* 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/header-param-models.md` page. PR [#13461](https://github.com/fastapi/fastapi/pull/13461) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). +* 🌐 Add Japanese translation for `docs/ja/docs/virtual-environments.md`. PR [#13304](https://github.com/fastapi/fastapi/pull/13304) by [@k94-ishi](https://github.com/k94-ishi). +* 🌐 Add Korean translation for `docs/ko/docs/tutorial/security/oauth2-jwt.md`. PR [#13333](https://github.com/fastapi/fastapi/pull/13333) by [@yes0ng](https://github.com/yes0ng). +* 🌐 Add Vietnamese translation for `docs/vi/docs/deployment/cloud.md`. PR [#13407](https://github.com/fastapi/fastapi/pull/13407) by [@ptt3199](https://github.com/ptt3199). + +### Internal + +* âŦ† Bump pydantic-ai from 0.0.15 to 0.0.30. PR [#13438](https://github.com/fastapi/fastapi/pull/13438) by [@dependabot[bot]](https://github.com/apps/dependabot). +* âŦ† Bump sqlmodel from 0.0.22 to 0.0.23. PR [#13437](https://github.com/fastapi/fastapi/pull/13437) by [@dependabot[bot]](https://github.com/apps/dependabot). +* âŦ† Bump black from 24.10.0 to 25.1.0. PR [#13436](https://github.com/fastapi/fastapi/pull/13436) by [@dependabot[bot]](https://github.com/apps/dependabot). +* âŦ† Bump ruff to 0.9.4. PR [#13299](https://github.com/fastapi/fastapi/pull/13299) by [@dependabot[bot]](https://github.com/apps/dependabot). +* 🔧 Update sponsors: pause TestDriven. PR [#13446](https://github.com/fastapi/fastapi/pull/13446) by [@tiangolo](https://github.com/tiangolo). + +## 0.115.11 + +### Fixes + +* 🐛 Add docs examples and tests (support) for `Annotated` custom validations, like `AfterValidator`, revert [#13440](https://github.com/fastapi/fastapi/pull/13440). PR [#13442](https://github.com/fastapi/fastapi/pull/13442) by [@tiangolo](https://github.com/tiangolo). + * New docs: [Query Parameters and String Validations - Custom Validation](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#custom-validation). + +### Translations + +* 🌐 Add Russian translation for `docs/ru/docs/tutorial/middleware.md`. PR [#13412](https://github.com/fastapi/fastapi/pull/13412) by [@alv2017](https://github.com/alv2017). + +### Internal + +* đŸ‘Ĩ Update FastAPI GitHub topic repositories. PR [#13439](https://github.com/fastapi/fastapi/pull/13439) by [@tiangolo](https://github.com/tiangolo). +* đŸ‘Ĩ Update FastAPI People - Contributors and Translators. PR [#13432](https://github.com/fastapi/fastapi/pull/13432) by [@tiangolo](https://github.com/tiangolo). +* đŸ‘Ĩ Update FastAPI People - Sponsors. PR [#13433](https://github.com/fastapi/fastapi/pull/13433) by [@tiangolo](https://github.com/tiangolo). + +## 0.115.10 + +### Fixes + +* â™ģī¸ Update internal annotation usage for compatibility with Pydantic 2.11. PR [#13314](https://github.com/fastapi/fastapi/pull/13314) by [@Viicos](https://github.com/Viicos). + +### Upgrades + +* âŦ†ī¸ Bump Starlette to allow up to 0.46.0: `>=0.40.0,<0.47.0`. PR [#13426](https://github.com/fastapi/fastapi/pull/13426) by [@musicinmybrain](https://github.com/musicinmybrain). + +### Translations + +* 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/debugging.md`. PR [#13370](https://github.com/fastapi/fastapi/pull/13370) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). +* 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/query-params.md`. PR [#13362](https://github.com/fastapi/fastapi/pull/13362) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). +* 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/path-params.md`. PR [#13354](https://github.com/fastapi/fastapi/pull/13354) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). +* 🌐 Add Japanese translation for `docs/ja/docs/tutorial/cookie-param-models.md`. PR [#13330](https://github.com/fastapi/fastapi/pull/13330) by [@k94-ishi](https://github.com/k94-ishi). +* 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/body-multiple-params.md`. PR [#13408](https://github.com/fastapi/fastapi/pull/13408) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). +* 🌐 Add Japanese translation for `docs/ja/docs/tutorial/query-param-models.md`. PR [#13323](https://github.com/fastapi/fastapi/pull/13323) by [@k94-ishi](https://github.com/k94-ishi). +* 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/body-nested-models.md`. PR [#13409](https://github.com/fastapi/fastapi/pull/13409) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). +* 🌐 Add Vietnamese translation for `docs/vi/docs/deployment/versions.md`. PR [#13406](https://github.com/fastapi/fastapi/pull/13406) by [@ptt3199](https://github.com/ptt3199). +* 🌐 Add Vietnamese translation for `docs/vi/docs/deployment/index.md`. PR [#13405](https://github.com/fastapi/fastapi/pull/13405) by [@ptt3199](https://github.com/ptt3199). +* 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/request-forms.md`. PR [#13383](https://github.com/fastapi/fastapi/pull/13383) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). +* 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/testing.md`. PR [#13371](https://github.com/fastapi/fastapi/pull/13371) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). + +## 0.115.9 + +### Fixes + +* 🐛 Ensure that `HTTPDigest` only raises an exception when `auto_error is True`. PR [#2939](https://github.com/fastapi/fastapi/pull/2939) by [@arthurio](https://github.com/arthurio). + +### Refactors + +* ✅ Simplify tests for `query_params_str_validations`. PR [#13218](https://github.com/fastapi/fastapi/pull/13218) by [@alv2017](https://github.com/alv2017). +* ✅ Simplify tests for `app_testing`. PR [#13220](https://github.com/fastapi/fastapi/pull/13220) by [@alv2017](https://github.com/alv2017). +* ✅ Simplify tests for `dependency_testing`. PR [#13223](https://github.com/fastapi/fastapi/pull/13223) by [@alv2017](https://github.com/alv2017). + +### Docs + +* 🍱 Update sponsors: CodeRabbit logo. PR [#13424](https://github.com/fastapi/fastapi/pull/13424) by [@tiangolo](https://github.com/tiangolo). +* đŸŠē Unify the badges across all tutorial translations. PR [#13329](https://github.com/fastapi/fastapi/pull/13329) by [@svlandeg](https://github.com/svlandeg). +* 📝 Fix typos in virtual environments documentation. PR [#13396](https://github.com/fastapi/fastapi/pull/13396) by [@bullet-ant](https://github.com/bullet-ant). +* 🐛 Fix issue with Swagger theme change example in the official tutorial. PR [#13289](https://github.com/fastapi/fastapi/pull/13289) by [@Zerohertz](https://github.com/Zerohertz). +* 📝 Add more precise description of HTTP status code range in docs. PR [#13347](https://github.com/fastapi/fastapi/pull/13347) by [@DanielYang59](https://github.com/DanielYang59). +* đŸ”Ĩ Remove manual type annotations in JWT tutorial to avoid typing expectations (JWT doesn't provide more types). PR [#13378](https://github.com/fastapi/fastapi/pull/13378) by [@tiangolo](https://github.com/tiangolo). +* 📝 Update docs for Query Params and String Validations, remove obsolete Ellipsis docs (`...`). PR [#13377](https://github.com/fastapi/fastapi/pull/13377) by [@tiangolo](https://github.com/tiangolo). +* âœī¸ Remove duplicate title in docs `body-multiple-params`. PR [#13345](https://github.com/fastapi/fastapi/pull/13345) by [@DanielYang59](https://github.com/DanielYang59). +* 📝 Fix test badge. PR [#13313](https://github.com/fastapi/fastapi/pull/13313) by [@esadek](https://github.com/esadek). + +### Translations + +* 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/header-params.md`. PR [#13381](https://github.com/fastapi/fastapi/pull/13381) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). +* 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/request-files.md`. PR [#13395](https://github.com/fastapi/fastapi/pull/13395) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). +* 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/request-form-models.md`. PR [#13384](https://github.com/fastapi/fastapi/pull/13384) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). +* 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/request-forms-and-files.md`. PR [#13386](https://github.com/fastapi/fastapi/pull/13386) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). +* 🌐 Update Korean translation for `docs/ko/docs/help-fastapi.md`. PR [#13262](https://github.com/fastapi/fastapi/pull/13262) by [@Zerohertz](https://github.com/Zerohertz). +* 🌐 Add Korean translation for `docs/ko/docs/advanced/custom-response.md`. PR [#13265](https://github.com/fastapi/fastapi/pull/13265) by [@11kkw](https://github.com/11kkw). +* 🌐 Update Korean translation for `docs/ko/docs/tutorial/security/simple-oauth2.md`. PR [#13335](https://github.com/fastapi/fastapi/pull/13335) by [@yes0ng](https://github.com/yes0ng). +* 🌐 Add Russian translation for `docs/ru/docs/advanced/response-cookies.md`. PR [#13327](https://github.com/fastapi/fastapi/pull/13327) by [@Stepakinoyan](https://github.com/Stepakinoyan). +* 🌐 Add Vietnamese translation for `docs/vi/docs/tutorial/static-files.md`. PR [#11291](https://github.com/fastapi/fastapi/pull/11291) by [@ptt3199](https://github.com/ptt3199). +* 🌐 Add Korean translation for `docs/ko/docs/tutorial/dependencies/dependencies-with-yield.md`. PR [#13257](https://github.com/fastapi/fastapi/pull/13257) by [@11kkw](https://github.com/11kkw). +* 🌐 Add Vietnamese translation for `docs/vi/docs/virtual-environments.md`. PR [#13282](https://github.com/fastapi/fastapi/pull/13282) by [@ptt3199](https://github.com/ptt3199). +* 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/static-files.md`. PR [#13285](https://github.com/fastapi/fastapi/pull/13285) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). +* 🌐 Add Vietnamese translation for `docs/vi/docs/environment-variables.md`. PR [#13287](https://github.com/fastapi/fastapi/pull/13287) by [@ptt3199](https://github.com/ptt3199). +* 🌐 Add Vietnamese translation for `docs/vi/docs/fastapi-cli.md`. PR [#13294](https://github.com/fastapi/fastapi/pull/13294) by [@ptt3199](https://github.com/ptt3199). +* 🌐 Add Ukrainian translation for `docs/uk/docs/features.md`. PR [#13308](https://github.com/fastapi/fastapi/pull/13308) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). +* 🌐 Add Ukrainian translation for `docs/uk/docs/learn/index.md`. PR [#13306](https://github.com/fastapi/fastapi/pull/13306) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). +* 🌐 Update Portuguese Translation for `docs/pt/docs/deployment/https.md`. PR [#13317](https://github.com/fastapi/fastapi/pull/13317) by [@Joao-Pedro-P-Holanda](https://github.com/Joao-Pedro-P-Holanda). +* 🌐 Update Portuguese Translation for `docs/pt/docs/index.md`. PR [#13328](https://github.com/fastapi/fastapi/pull/13328) by [@ceb10n](https://github.com/ceb10n). +* 🌐 Add Russian translation for `docs/ru/docs/advanced/websockets.md`. PR [#13279](https://github.com/fastapi/fastapi/pull/13279) by [@Rishat-F](https://github.com/Rishat-F). + +### Internal + +* ✅ Fix a minor bug in the test `tests/test_modules_same_name_body/test_main.py`. PR [#13411](https://github.com/fastapi/fastapi/pull/13411) by [@alv2017](https://github.com/alv2017). +* 👷 Use `wrangler-action` v3. PR [#13415](https://github.com/fastapi/fastapi/pull/13415) by [@joakimnordling](https://github.com/joakimnordling). +* 🔧 Update sponsors: add CodeRabbit. PR [#13402](https://github.com/fastapi/fastapi/pull/13402) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Update team: Add Ludovico. PR [#13390](https://github.com/fastapi/fastapi/pull/13390) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Update sponsors: Add LambdaTest. PR [#13389](https://github.com/fastapi/fastapi/pull/13389) by [@tiangolo](https://github.com/tiangolo). +* âŦ† Bump cloudflare/wrangler-action from 3.13 to 3.14. PR [#13350](https://github.com/fastapi/fastapi/pull/13350) by [@dependabot[bot]](https://github.com/apps/dependabot). +* âŦ† Bump mkdocs-material from 9.5.18 to 9.6.1. PR [#13301](https://github.com/fastapi/fastapi/pull/13301) by [@dependabot[bot]](https://github.com/apps/dependabot). +* âŦ† Bump pillow from 11.0.0 to 11.1.0. PR [#13300](https://github.com/fastapi/fastapi/pull/13300) by [@dependabot[bot]](https://github.com/apps/dependabot). +* đŸ‘Ĩ Update FastAPI People - Sponsors. PR [#13295](https://github.com/fastapi/fastapi/pull/13295) by [@tiangolo](https://github.com/tiangolo). +* đŸ‘Ĩ Update FastAPI People - Experts. PR [#13303](https://github.com/fastapi/fastapi/pull/13303) by [@tiangolo](https://github.com/tiangolo). +* đŸ‘Ĩ Update FastAPI GitHub topic repositories. PR [#13302](https://github.com/fastapi/fastapi/pull/13302) by [@tiangolo](https://github.com/tiangolo). +* đŸ‘Ĩ Update FastAPI People - Contributors and Translators. PR [#13293](https://github.com/fastapi/fastapi/pull/13293) by [@tiangolo](https://github.com/tiangolo). +* âŦ† Bump inline-snapshot from 0.18.1 to 0.19.3. PR [#13298](https://github.com/fastapi/fastapi/pull/13298) by [@dependabot[bot]](https://github.com/apps/dependabot). +* 🔧 Update sponsors, add Permit. PR [#13288](https://github.com/fastapi/fastapi/pull/13288) by [@tiangolo](https://github.com/tiangolo). + +## 0.115.8 + +### Fixes + +* 🐛 Fix `OAuth2PasswordRequestForm` and `OAuth2PasswordRequestFormStrict` fixed `grant_type` "password" RegEx. PR [#9783](https://github.com/fastapi/fastapi/pull/9783) by [@skarfie123](https://github.com/skarfie123). + +### Refactors + +* ✅ Simplify tests for body_multiple_params . PR [#13237](https://github.com/fastapi/fastapi/pull/13237) by [@alejsdev](https://github.com/alejsdev). +* â™ģī¸ Move duplicated code portion to a static method in the `APIKeyBase` super class. PR [#3142](https://github.com/fastapi/fastapi/pull/3142) by [@ShahriyarR](https://github.com/ShahriyarR). +* ✅ Simplify tests for request_files. PR [#13182](https://github.com/fastapi/fastapi/pull/13182) by [@alejsdev](https://github.com/alejsdev). + +### Docs + +* 📝 Change the word "unwrap" to "unpack" in `docs/en/docs/tutorial/extra-models.md`. PR [#13061](https://github.com/fastapi/fastapi/pull/13061) by [@timothy-jeong](https://github.com/timothy-jeong). +* 📝 Update Request Body's `tutorial002` to deal with `tax=0` case. PR [#13230](https://github.com/fastapi/fastapi/pull/13230) by [@togogh](https://github.com/togogh). * đŸ‘Ĩ Update FastAPI People - Experts. PR [#13269](https://github.com/fastapi/fastapi/pull/13269) by [@tiangolo](https://github.com/tiangolo). ### Translations @@ -20,6 +377,7 @@ hide: ### Internal +* âŦ†ī¸ Add support for Python 3.13. PR [#13274](https://github.com/fastapi/fastapi/pull/13274) by [@tiangolo](https://github.com/tiangolo). * âŦ†ī¸ Upgrade AnyIO max version for tests, new range: `>=3.2.1,<5.0.0`. PR [#13273](https://github.com/fastapi/fastapi/pull/13273) by [@tiangolo](https://github.com/tiangolo). * 🔧 Update Sponsors badges. PR [#13271](https://github.com/fastapi/fastapi/pull/13271) by [@tiangolo](https://github.com/tiangolo). * â™ģī¸ Fix `notify_translations.py` empty env var handling for PR label events vs workflow_dispatch. PR [#13272](https://github.com/fastapi/fastapi/pull/13272) by [@tiangolo](https://github.com/tiangolo). diff --git a/docs/en/docs/tutorial/bigger-applications.md b/docs/en/docs/tutorial/bigger-applications.md index 605ced0d3..f5f29a173 100644 --- a/docs/en/docs/tutorial/bigger-applications.md +++ b/docs/en/docs/tutorial/bigger-applications.md @@ -52,7 +52,7 @@ from app.routers import items * There's also a subdirectory `app/internal/` with another file `__init__.py`, so it's another "Python subpackage": `app.internal`. * And the file `app/internal/admin.py` is another submodule: `app.internal.admin`. - + The same file structure with comments: @@ -270,7 +270,7 @@ But that file doesn't exist, our dependencies are in a file at `app/dependencies Remember how our app/file structure looks like: - + --- diff --git a/docs/en/docs/tutorial/body-multiple-params.md b/docs/en/docs/tutorial/body-multiple-params.md index 9fced9652..71b308bb4 100644 --- a/docs/en/docs/tutorial/body-multiple-params.md +++ b/docs/en/docs/tutorial/body-multiple-params.md @@ -10,8 +10,6 @@ And you can also declare body parameters as optional, by setting the default to {* ../../docs_src/body_multiple_params/tutorial001_an_py310.py hl[18:20] *} -## Multiple body parameters - /// note Notice that, in this case, the `item` that would be taken from the body is optional. As it has a `None` default value. diff --git a/docs/en/docs/tutorial/cors.md b/docs/en/docs/tutorial/cors.md index cf31cfcf5..5ca4437b3 100644 --- a/docs/en/docs/tutorial/cors.md +++ b/docs/en/docs/tutorial/cors.md @@ -57,7 +57,10 @@ The following arguments are supported: * `allow_origin_regex` - A regex string to match against origins that should be permitted to make cross-origin requests. e.g. `'https://.*\.example\.org'`. * `allow_methods` - A list of HTTP methods that should be allowed for cross-origin requests. Defaults to `['GET']`. You can use `['*']` to allow all standard methods. * `allow_headers` - A list of HTTP request headers that should be supported for cross-origin requests. Defaults to `[]`. You can use `['*']` to allow all headers. The `Accept`, `Accept-Language`, `Content-Language` and `Content-Type` headers are always allowed for simple CORS requests. -* `allow_credentials` - Indicate that cookies should be supported for cross-origin requests. Defaults to `False`. Also, `allow_origins` cannot be set to `['*']` for credentials to be allowed, origins must be specified. +* `allow_credentials` - Indicate that cookies should be supported for cross-origin requests. Defaults to `False`. + + None of `allow_origins`, `allow_methods` and `allow_headers` can be set to `['*']` if `allow_credentials` is set to `True`. All of them must be explicitly specified. + * `expose_headers` - Indicate any response headers that should be made accessible to the browser. Defaults to `[]`. * `max_age` - Sets a maximum time in seconds for browsers to cache CORS responses. Defaults to `600`. diff --git a/docs/en/docs/tutorial/extra-models.md b/docs/en/docs/tutorial/extra-models.md index 5fac3f69e..ed1590ece 100644 --- a/docs/en/docs/tutorial/extra-models.md +++ b/docs/en/docs/tutorial/extra-models.md @@ -70,9 +70,9 @@ we would get a Python `dict` with: } ``` -#### Unwrapping a `dict` +#### Unpacking a `dict` -If we take a `dict` like `user_dict` and pass it to a function (or class) with `**user_dict`, Python will "unwrap" it. It will pass the keys and values of the `user_dict` directly as key-value arguments. +If we take a `dict` like `user_dict` and pass it to a function (or class) with `**user_dict`, Python will "unpack" it. It will pass the keys and values of the `user_dict` directly as key-value arguments. So, continuing with the `user_dict` from above, writing: @@ -117,11 +117,11 @@ would be equivalent to: UserInDB(**user_in.dict()) ``` -...because `user_in.dict()` is a `dict`, and then we make Python "unwrap" it by passing it to `UserInDB` prefixed with `**`. +...because `user_in.dict()` is a `dict`, and then we make Python "unpack" it by passing it to `UserInDB` prefixed with `**`. So, we get a Pydantic model from the data in another Pydantic model. -#### Unwrapping a `dict` and extra keywords +#### Unpacking a `dict` and extra keywords And then adding the extra keyword argument `hashed_password=hashed_password`, like in: diff --git a/docs/en/docs/tutorial/handling-errors.md b/docs/en/docs/tutorial/handling-errors.md index 4d969747f..5b8e677e4 100644 --- a/docs/en/docs/tutorial/handling-errors.md +++ b/docs/en/docs/tutorial/handling-errors.md @@ -35,7 +35,7 @@ Because it's a Python exception, you don't `return` it, you `raise` it. This also means that if you are inside a utility function that you are calling inside of your *path operation function*, and you raise the `HTTPException` from inside of that utility function, it won't run the rest of the code in the *path operation function*, it will terminate that request right away and send the HTTP error from the `HTTPException` to the client. -The benefit of raising an exception over `return`ing a value will be more evident in the section about Dependencies and Security. +The benefit of raising an exception over returning a value will be more evident in the section about Dependencies and Security. In this example, when the client requests an item by an ID that doesn't exist, raise an exception with a status code of `404`: @@ -252,4 +252,4 @@ If you want to use the exception along with the same default exception handlers {* ../../docs_src/handling_errors/tutorial006.py hl[2:5,15,21] *} -In this example you are just `print`ing the error with a very expressive message, but you get the idea. You can use the exception and then just reuse the default exception handlers. +In this example you are just printing the error with a very expressive message, but you get the idea. You can use the exception and then just reuse the default exception handlers. diff --git a/docs/en/docs/tutorial/header-param-models.md b/docs/en/docs/tutorial/header-param-models.md index 73950a668..4cdf09705 100644 --- a/docs/en/docs/tutorial/header-param-models.md +++ b/docs/en/docs/tutorial/header-param-models.md @@ -51,6 +51,22 @@ For example, if the client tries to send a `tool` header with a value of `plumbu } ``` +## Disable Convert Underscores + +The same way as with regular header parameters, when you have underscore characters in the parameter names, they are **automatically converted to hyphens**. + +For example, if you have a header parameter `save_data` in the code, the expected HTTP header will be `save-data`, and it will show up like that in the docs. + +If for some reason you need to disable this automatic conversion, you can do it as well for Pydantic models for header parameters. + +{* ../../docs_src/header_param_models/tutorial003_an_py310.py hl[19] *} + +/// warning + +Before setting `convert_underscores` to `False`, bear in mind that some HTTP proxies and servers disallow the usage of headers with underscores. + +/// + ## Summary You can use **Pydantic models** to declare **headers** in **FastAPI**. 😎 diff --git a/docs/en/docs/tutorial/index.md b/docs/en/docs/tutorial/index.md index 4fe38256c..17f6fb685 100644 --- a/docs/en/docs/tutorial/index.md +++ b/docs/en/docs/tutorial/index.md @@ -76,10 +76,12 @@ $ pip install "fastapi[standard]" /// note -When you install with `pip install "fastapi[standard]"` it comes with some default optional standard dependencies. +When you install with `pip install "fastapi[standard]"` it comes with some default optional standard dependencies, including `fastapi-cloud-cli`, which allows you to deploy to FastAPI Cloud. If you don't want to have those optional dependencies, you can instead install `pip install fastapi`. +If you want to install the standard dependencies but without the `fastapi-cloud-cli`, you can install with `pip install "fastapi[standard-no-fastapi-cloud-cli]"`. + /// ## Advanced User Guide diff --git a/docs/en/docs/tutorial/middleware.md b/docs/en/docs/tutorial/middleware.md index 53c47a085..b7c03a319 100644 --- a/docs/en/docs/tutorial/middleware.md +++ b/docs/en/docs/tutorial/middleware.md @@ -15,7 +15,7 @@ A "middleware" is a function that works with every **request** before it is proc If you have dependencies with `yield`, the exit code will run *after* the middleware. -If there were any background tasks (documented later), they will run *after* all the middleware. +If there were any background tasks (covered in the [Background Tasks](background-tasks.md){.internal-link target=_blank} section, you will see it later), they will run *after* all the middleware. /// @@ -65,6 +65,29 @@ Here we use ../../docs_src/query_params_str_validations/tutorial002_an_py310.py!} -``` - -//// - -//// tab | Python 3.8+ - -In versions of Python below Python 3.9 you import `Annotated` from `typing_extensions`. - -It will already be installed with FastAPI. - -```Python hl_lines="3-4" -{!> ../../docs_src/query_params_str_validations/tutorial002_an.py!} -``` - -//// +{* ../../docs_src/query_params_str_validations/tutorial002_an_py310.py hl[1,3] *} /// info @@ -145,54 +125,23 @@ As in this case (without using `Annotated`) we have to replace the default value So: -```Python -q: Union[str, None] = Query(default=None) -``` - -...makes the parameter optional, with a default value of `None`, the same as: - -```Python -q: Union[str, None] = None -``` - -And in Python 3.10 and above: - ```Python q: str | None = Query(default=None) ``` ...makes the parameter optional, with a default value of `None`, the same as: -```Python -q: str | None = None -``` - -But the `Query` versions declare it explicitly as being a query parameter. - -/// info - -Keep in mind that the most important part to make a parameter optional is the part: ```Python -= None -``` - -or the: - -```Python -= Query(default=None) +q: str | None = None ``` -as it will use that `None` as the default value, and that way make the parameter **not required**. - -The `Union[str, None]` part allows your editor to provide better support, but it is not what tells FastAPI that this parameter is not required. - -/// +But the `Query` version declares it explicitly as being a query parameter. Then, we can pass more parameters to `Query`. In this case, the `max_length` parameter that applies to strings: ```Python -q: Union[str, None] = Query(default=None, max_length=50) +q: str | None = Query(default=None, max_length=50) ``` This will validate the data, show a clear error when the data is not valid, and document the parameter in the OpenAPI schema *path operation*. @@ -201,7 +150,7 @@ This will validate the data, show a clear error when the data is not valid, and Keep in mind that when using `Query` inside of `Annotated` you cannot use the `default` parameter for `Query`. -Instead use the actual default value of the function parameter. Otherwise, it would be inconsistent. +Instead, use the actual default value of the function parameter. Otherwise, it would be inconsistent. For example, this is not allowed: @@ -255,7 +204,7 @@ This specific regular expression pattern checks that the received parameter valu If you feel lost with all these **"regular expression"** ideas, don't worry. They are a hard topic for many people. You can still do a lot of stuff without needing regular expressions yet. -But whenever you need them and go and learn them, know that you can already use them directly in **FastAPI**. +Now you know that whenever you need them you can use them in **FastAPI**. ### Pydantic v1 `regex` instead of `pattern` @@ -296,7 +245,7 @@ q: str instead of: ```Python -q: Union[str, None] = None +q: str | None = None ``` But we are now declaring it with `Query`, for example like: @@ -304,15 +253,7 @@ But we are now declaring it with `Query`, for example like: //// tab | Annotated ```Python -q: Annotated[Union[str, None], Query(min_length=3)] = None -``` - -//// - -//// tab | non-Annotated - -```Python -q: Union[str, None] = Query(default=None, min_length=3) +q: Annotated[str | None, Query(min_length=3)] = None ``` //// @@ -321,42 +262,14 @@ So, when you need to declare a value as required while using `Query`, you can si {* ../../docs_src/query_params_str_validations/tutorial006_an_py39.py hl[9] *} -### Required with Ellipsis (`...`) - -There's an alternative way to explicitly declare that a value is required. You can set the default to the literal value `...`: - -{* ../../docs_src/query_params_str_validations/tutorial006b_an_py39.py hl[9] *} - -/// info - -If you hadn't seen that `...` before: it is a special single value, it is part of Python and is called "Ellipsis". - -It is used by Pydantic and FastAPI to explicitly declare that a value is required. - -/// - -This will let **FastAPI** know that this parameter is required. - ### Required, can be `None` You can declare that a parameter can accept `None`, but that it's still required. This would force clients to send a value, even if the value is `None`. -To do that, you can declare that `None` is a valid type but still use `...` as the default: +To do that, you can declare that `None` is a valid type but simply do not declare a default value: {* ../../docs_src/query_params_str_validations/tutorial006c_an_py310.py hl[9] *} -/// tip - -Pydantic, which is what powers all the data validation and serialization in FastAPI, has a special behavior when you use `Optional` or `Union[Something, None]` without a default value, you can read more about it in the Pydantic docs about Required fields. - -/// - -/// tip - -Remember that in most of the cases, when something is required, you can simply omit the default, so you normally don't have to use `...`. - -/// - ## Query parameter list / multiple values When you define a query parameter explicitly with `Query` you can also declare it to receive a list of values, or said in another way, to receive multiple values. @@ -396,7 +309,7 @@ The interactive API docs will update accordingly, to allow multiple values: ### Query parameter list / multiple values with defaults -And you can also define a default `list` of values if none are provided: +You can also define a default `list` of values if none are provided: {* ../../docs_src/query_params_str_validations/tutorial012_an_py39.py hl[9] *} @@ -419,7 +332,7 @@ the default of `q` will be: `["foo", "bar"]` and your response will be: #### Using just `list` -You can also use `list` directly instead of `List[str]` (or `list[str]` in Python 3.9+): +You can also use `list` directly instead of `list[str]`: {* ../../docs_src/query_params_str_validations/tutorial013_an_py39.py hl[9] *} @@ -427,7 +340,7 @@ You can also use `list` directly instead of `List[str]` (or `list[str]` in Pytho Keep in mind that in this case, FastAPI won't check the contents of the list. -For example, `List[int]` would check (and document) that the contents of the list are integers. But `list` alone wouldn't. +For example, `list[int]` would check (and document) that the contents of the list are integers. But `list` alone wouldn't. /// @@ -493,6 +406,68 @@ To exclude a query parameter from the generated OpenAPI schema (and thus, from t {* ../../docs_src/query_params_str_validations/tutorial014_an_py310.py hl[10] *} +## Custom Validation + +There could be cases where you need to do some **custom validation** that can't be done with the parameters shown above. + +In those cases, you can use a **custom validator function** that is applied after the normal validation (e.g. after validating that the value is a `str`). + +You can achieve that using Pydantic's `AfterValidator` inside of `Annotated`. + +/// tip + +Pydantic also has `BeforeValidator` and others. 🤓 + +/// + +For example, this custom validator checks that the item ID starts with `isbn-` for an ISBN book number or with `imdb-` for an IMDB movie URL ID: + +{* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py hl[5,16:19,24] *} + +/// info + +This is available with Pydantic version 2 or above. 😎 + +/// + +/// tip + +If you need to do any type of validation that requires communicating with any **external component**, like a database or another API, you should instead use **FastAPI Dependencies**, you will learn about them later. + +These custom validators are for things that can be checked with **only** the **same data** provided in the request. + +/// + +### Understand that Code + +The important point is just using **`AfterValidator` with a function inside `Annotated`**. Feel free to skip this part. 🤸 + +--- + +But if you're curious about this specific code example and you're still entertained, here are some extra details. + +#### String with `value.startswith()` + +Did you notice? a string using `value.startswith()` can take a tuple, and it will check each value in the tuple: + +{* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py ln[16:19] hl[17] *} + +#### A Random Item + +With `data.items()` we get an iterable object with tuples containing the key and value for each dictionary item. + +We convert this iterable object into a proper `list` with `list(data.items())`. + +Then with `random.choice()` we can get a **random value** from the list, so, we get a tuple with `(id, name)`. It will be something like `("imdb-tt0371724", "The Hitchhiker's Guide to the Galaxy")`. + +Then we **assign those two values** of the tuple to the variables `id` and `name`. + +So, if the user didn't provide an item ID, they will still receive a random suggestion. + +...we do all this in a **single simple line**. đŸ¤¯ Don't you love Python? 🐍 + +{* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py ln[22:30] hl[29] *} + ## Recap You can declare additional validations and metadata for your parameters. @@ -510,6 +485,8 @@ Validations specific for strings: * `max_length` * `pattern` +Custom validations using `AfterValidator`. + In these examples you saw how to declare validations for `str` values. See the next chapters to learn how to declare validations for other types, like numbers. diff --git a/docs/en/docs/tutorial/response-status-code.md b/docs/en/docs/tutorial/response-status-code.md index 711042a46..41bf02a8f 100644 --- a/docs/en/docs/tutorial/response-status-code.md +++ b/docs/en/docs/tutorial/response-status-code.md @@ -53,16 +53,16 @@ These status codes have a name associated to recognize them, but the important p In short: -* `100` and above are for "Information". You rarely use them directly. Responses with these status codes cannot have a body. -* **`200`** and above are for "Successful" responses. These are the ones you would use the most. +* `100 - 199` are for "Information". You rarely use them directly. Responses with these status codes cannot have a body. +* **`200 - 299`** are for "Successful" responses. These are the ones you would use the most. * `200` is the default status code, which means everything was "OK". * Another example would be `201`, "Created". It is commonly used after creating a new record in the database. * A special case is `204`, "No Content". This response is used when there is no content to return to the client, and so the response must not have a body. -* **`300`** and above are for "Redirection". Responses with these status codes may or may not have a body, except for `304`, "Not Modified", which must not have one. -* **`400`** and above are for "Client error" responses. These are the second type you would probably use the most. +* **`300 - 399`** are for "Redirection". Responses with these status codes may or may not have a body, except for `304`, "Not Modified", which must not have one. +* **`400 - 499`** are for "Client error" responses. These are the second type you would probably use the most. * An example is `404`, for a "Not Found" response. * For generic errors from the client, you can just use `400`. -* `500` and above are for server errors. You almost never use them directly. When something goes wrong at some part in your application code, or server, it will automatically return one of these status codes. +* `500 - 599` are for server errors. You almost never use them directly. When something goes wrong at some part in your application code, or server, it will automatically return one of these status codes. /// tip diff --git a/docs/en/docs/virtual-environments.md b/docs/en/docs/virtual-environments.md index b75be18c3..4f65b3b80 100644 --- a/docs/en/docs/virtual-environments.md +++ b/docs/en/docs/virtual-environments.md @@ -668,7 +668,7 @@ After activating the virtual environment, the `PATH` variable would look somethi /home/user/code/awesome-project/.venv/bin:/usr/bin:/bin:/usr/sbin:/sbin ``` -That means that the system will now start looking first look for programs in: +That means that the system will now start looking first for programs in: ```plaintext /home/user/code/awesome-project/.venv/bin @@ -692,7 +692,7 @@ and use that one. C:\Users\user\code\awesome-project\.venv\Scripts;C:\Windows\System32 ``` -That means that the system will now start looking first look for programs in: +That means that the system will now start looking first for programs in: ```plaintext C:\Users\user\code\awesome-project\.venv\Scripts diff --git a/docs/en/mkdocs.yml b/docs/en/mkdocs.yml index e9a639d0b..8a5ea13e0 100644 --- a/docs/en/mkdocs.yml +++ b/docs/en/mkdocs.yml @@ -6,7 +6,7 @@ theme: name: material custom_dir: ../en/overrides palette: - - media: "(prefers-color-scheme)" + - media: (prefers-color-scheme) toggle: icon: material/lightbulb-auto name: Switch to light mode @@ -27,7 +27,6 @@ theme: features: - content.code.annotate - content.code.copy - # - content.code.select - content.footnote.tooltips - content.tabs.link - content.tooltips @@ -35,7 +34,6 @@ theme: - navigation.indexes - navigation.instant - navigation.instant.prefetch - # - navigation.instant.preview - navigation.instant.progress - navigation.path - navigation.tabs @@ -46,7 +44,6 @@ theme: - search.share - search.suggest - toc.follow - icon: repo: fontawesome/brands/github-alt logo: img/icon-white.svg @@ -55,11 +52,7 @@ theme: repo_name: fastapi/fastapi repo_url: https://github.com/fastapi/fastapi plugins: - # Material for MkDocs - search: - # Configured in mkdocs.insiders.yml - # social: - # Other plugins + search: null macros: include_yaml: - external_links: ../en/data/external_links.yml @@ -103,7 +96,6 @@ plugins: signature_crossrefs: true show_symbol_type_heading: true show_symbol_type_toc: true - nav: - FastAPI: index.md - features.md @@ -258,33 +250,27 @@ nav: - benchmarks.md - management.md - release-notes.md - markdown_extensions: - # Python Markdown - abbr: - attr_list: - footnotes: - md_in_html: - tables: + abbr: null + attr_list: null + footnotes: null + md_in_html: null + tables: null toc: permalink: true - - # Python Markdown Extensions - pymdownx.betterem: - pymdownx.caret: + pymdownx.betterem: null + pymdownx.caret: null pymdownx.highlight: line_spans: __span - pymdownx.inlinehilite: - pymdownx.keys: - pymdownx.mark: + pymdownx.inlinehilite: null + pymdownx.keys: null + pymdownx.mark: null pymdownx.superfences: custom_fences: - name: mermaid class: mermaid - format: !!python/name:pymdownx.superfences.fence_code_format - pymdownx.tilde: - - # pymdownx blocks + format: !!python/name:pymdownx.superfences.fence_code_format '' + pymdownx.tilde: null pymdownx.blocks.admonition: types: - note @@ -295,34 +281,14 @@ markdown_extensions: - tip - hint - warning - # Custom types - info - check - pymdownx.blocks.details: + pymdownx.blocks.details: null pymdownx.blocks.tab: - alternate_style: True - - # Other extensions - mdx_include: - markdown_include_variants: - + alternate_style: true + mdx_include: null + markdown_include_variants: null extra: - analytics: - provider: google - property: G-YNEVN69SC3 - feedback: - title: Was this page helpful? - ratings: - - icon: material/emoticon-happy-outline - name: This page was helpful - data: 1 - note: >- - Thanks for your feedback! - - icon: material/emoticon-sad-outline - name: This page could be improved - data: 0 - note: >- - Thanks for your feedback! social: - icon: fontawesome/brands/github-alt link: https://github.com/fastapi/fastapi @@ -331,14 +297,9 @@ extra: - icon: fontawesome/brands/twitter link: https://twitter.com/fastapi - icon: fontawesome/brands/linkedin - link: https://www.linkedin.com/in/tiangolo - - icon: fontawesome/brands/dev - link: https://dev.to/tiangolo - - icon: fontawesome/brands/medium - link: https://medium.com/@tiangolo + link: https://www.linkedin.com/company/fastapi - icon: fontawesome/solid/globe link: https://tiangolo.com - alternate: - link: / name: en - English @@ -390,14 +351,11 @@ extra: name: zh-hant - įšéĢ”ä¸­æ–‡ - link: /em/ name: 😉 - extra_css: - css/termynal.css - css/custom.css - extra_javascript: - js/termynal.js - js/custom.js - hooks: - ../../scripts/mkdocs_hooks.py diff --git a/docs/en/overrides/main.html b/docs/en/overrides/main.html index b58ed8818..12585507d 100644 --- a/docs/en/overrides/main.html +++ b/docs/en/overrides/main.html @@ -10,6 +10,13 @@ Follow @fastapi on Twitter to stay updated +

+ + + {% include ".icons/fontawesome/brands/linkedin.svg" %} + Follow FastAPI on LinkedIn to stay updated + +
@@ -17,9 +24,6 @@ Subscribe to the FastAPI and friends newsletter 🎉
-
- You can now sponsor FastAPI 🍰 -
@@ -35,57 +39,57 @@
- + - +
- + - +
- + - +
- + - +
- + - +
- + - +
- + - +
- + - +
- + - +
diff --git a/docs/es/docs/advanced/generate-clients.md b/docs/es/docs/advanced/generate-clients.md index bf2e5cb4f..b664bceac 100644 --- a/docs/es/docs/advanced/generate-clients.md +++ b/docs/es/docs/advanced/generate-clients.md @@ -22,7 +22,7 @@ Y muestra su verdadero compromiso con FastAPI y su **comunidad** (tÃē), ya que n Por ejemplo, podrías querer probar: -* Speakeasy +* Speakeasy * Stainless * liblab diff --git a/docs/es/docs/deployment/concepts.md b/docs/es/docs/deployment/concepts.md index f5725c5dc..bcc7948bc 100644 --- a/docs/es/docs/deployment/concepts.md +++ b/docs/es/docs/deployment/concepts.md @@ -216,7 +216,7 @@ Este Proceso Administrador probablemente sería el que escuche en el **puerto** Esos worker processes serían los que ejecutan tu aplicaciÃŗn, realizarían los cÃĄlculos principales para recibir un **request** y devolver un **response**, y cargarían cualquier cosa que pongas en variables en RAM. - + Y por supuesto, la misma mÃĄquina probablemente tendría **otros procesos** ejecutÃĄndose tambiÊn, aparte de tu aplicaciÃŗn. diff --git a/docs/es/docs/deployment/docker.md b/docs/es/docs/deployment/docker.md index ff204f078..3a39d3661 100644 --- a/docs/es/docs/deployment/docker.md +++ b/docs/es/docs/deployment/docker.md @@ -6,7 +6,7 @@ Usar contenedores de Linux tiene varias ventajas, incluyendo **seguridad**, **re /// tip | Consejo -ÂŋTienes prisa y ya conoces esto? Salta al [`Dockerfile` mÃĄs abajo 👇](#build-a-docker-image-for-fastapi). +ÂŋTienes prisa y ya conoces esto? Salta al [`Dockerfile` mÃĄs abajo 👇](#construir-una-imagen-de-docker-para-fastapi). /// diff --git a/docs/es/docs/deployment/https.md b/docs/es/docs/deployment/https.md index f2871ac03..3ccb5dc47 100644 --- a/docs/es/docs/deployment/https.md +++ b/docs/es/docs/deployment/https.md @@ -85,7 +85,7 @@ Primero, el navegador consultaría con los **servidores DNS** cuÃĄl es la **IP d Los servidores DNS le dirían al navegador que use una **direcciÃŗn IP** específica. Esa sería la direcciÃŗn IP pÃēblica utilizada por tu servidor, que configuraste en los servidores DNS. - + ### Inicio del Handshake TLS @@ -93,7 +93,7 @@ El navegador luego se comunicaría con esa direcciÃŗn IP en el **puerto 443** (e La primera parte de la comunicaciÃŗn es solo para establecer la conexiÃŗn entre el cliente y el servidor y decidir las claves criptogrÃĄficas que usarÃĄn, etc. - + Esta interacciÃŗn entre el cliente y el servidor para establecer la conexiÃŗn TLS se llama **handshake TLS**. @@ -111,7 +111,7 @@ Usando la **extensiÃŗn SNI** discutida anteriormente, el TLS Termination Proxy v En este caso, usaría el certificado para `someapp.example.com`. - + El cliente ya **confía** en la entidad que generÃŗ ese certificado TLS (en este caso Let's Encrypt, pero lo veremos mÃĄs adelante), por lo que puede **verificar** que el certificado sea vÃĄlido. @@ -133,19 +133,19 @@ Ahora que el cliente y el servidor (específicamente el navegador y el TLS Termi Así que, el cliente envía un **request HTTPS**. Esto es simplemente un request HTTP a travÊs de una conexiÃŗn TLS encriptada. - + ### Desencriptar el Request El TLS Termination Proxy usaría la encriptaciÃŗn acordada para **desencriptar el request**, y transmitiría el **request HTTP simple (desencriptado)** al proceso que ejecuta la aplicaciÃŗn (por ejemplo, un proceso con Uvicorn ejecutando la aplicaciÃŗn FastAPI). - + ### Response HTTP La aplicaciÃŗn procesaría el request y enviaría un **response HTTP simple (sin encriptar)** al TLS Termination Proxy. - + ### Response HTTPS @@ -153,7 +153,7 @@ El TLS Termination Proxy entonces **encriptaría el response** usando la criptog Luego, el navegador verificaría que el response sea vÃĄlido y encriptado con la clave criptogrÃĄfica correcta, etc. Entonces **desencriptaría el response** y lo procesaría. - + El cliente (navegador) sabrÃĄ que el response proviene del servidor correcto porque estÃĄ utilizando la criptografía que acordaron usando el **certificado HTTPS** anteriormente. @@ -163,7 +163,7 @@ En el mismo servidor (o servidores), podrían haber **mÃēltiples aplicaciones**, Solo un proceso puede estar gestionando la IP y puerto específica (el TLS Termination Proxy en nuestro ejemplo) pero las otras aplicaciones/procesos pueden estar ejecutÃĄndose en el/los servidor(es) tambiÊn, siempre y cuando no intenten usar la misma **combinaciÃŗn de IP pÃēblica y puerto**. - + De esa manera, el TLS Termination Proxy podría gestionar HTTPS y certificados para **mÃēltiples dominios**, para mÃēltiples aplicaciones, y luego transmitir los requests a la aplicaciÃŗn correcta en cada caso. @@ -173,7 +173,7 @@ En algÃēn momento en el futuro, cada certificado **expiraría** (alrededor de 3 Y entonces, habría otro programa (en algunos casos es otro programa, en algunos casos podría ser el mismo TLS Termination Proxy) que hablaría con Let's Encrypt y renovaría el/los certificado(s). - + Los **certificados TLS** estÃĄn **asociados con un nombre de dominio**, no con una direcciÃŗn IP. diff --git a/docs/es/docs/how-to/custom-docs-ui-assets.md b/docs/es/docs/how-to/custom-docs-ui-assets.md index 444cf167e..0a03ff330 100644 --- a/docs/es/docs/how-to/custom-docs-ui-assets.md +++ b/docs/es/docs/how-to/custom-docs-ui-assets.md @@ -98,7 +98,7 @@ Probablemente puedas hacer clic derecho en cada enlace y seleccionar una opciÃŗn Y **ReDoc** utiliza el archivo: -* `redoc.standalone.js` +* `redoc.standalone.js` DespuÊs de eso, tu estructura de archivos podría verse así: @@ -129,14 +129,8 @@ Deberías ver un archivo JavaScript muy largo de **ReDoc**. Podría comenzar con algo como: ```JavaScript -/*! - * ReDoc - OpenAPI/Swagger-generated API Reference Documentation - * ------------------------------------------------------------- - * Version: "2.0.0-rc.18" - * Repo: https://github.com/Redocly/redoc - */ -!function(e,t){"object"==typeof exports&&"object"==typeof m - +/*! For license information please see redoc.standalone.js.LICENSE.txt */ +!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("null")): ... ``` diff --git a/docs/es/docs/index.md b/docs/es/docs/index.md index db8da6933..c1da5d633 100644 --- a/docs/es/docs/index.md +++ b/docs/es/docs/index.md @@ -12,7 +12,7 @@

- Test + Test Coverage diff --git a/docs/es/docs/tutorial/bigger-applications.md b/docs/es/docs/tutorial/bigger-applications.md index 78165ef05..c3d8f0686 100644 --- a/docs/es/docs/tutorial/bigger-applications.md +++ b/docs/es/docs/tutorial/bigger-applications.md @@ -52,7 +52,7 @@ from app.routers import items * TambiÊn hay un subdirectorio `app/internal/` con otro archivo `__init__.py`, por lo que es otro "subpaquete de Python": `app.internal`. * Y el archivo `app/internal/admin.py` es otro submÃŗdulo: `app.internal.admin`. - + La misma estructura de archivos con comentarios: @@ -270,7 +270,7 @@ Pero ese archivo no existe, nuestras dependencias estÃĄn en un archivo en `app/d Recuerda cÃŗmo se ve nuestra estructura de aplicaciÃŗn/archivo: - + --- diff --git a/docs/es/docs/tutorial/query-params-str-validations.md b/docs/es/docs/tutorial/query-params-str-validations.md index f378b9dce..9cb76156f 100644 --- a/docs/es/docs/tutorial/query-params-str-validations.md +++ b/docs/es/docs/tutorial/query-params-str-validations.md @@ -321,22 +321,6 @@ Así que, cuando necesites declarar un valor como requerido mientras usas `Query {* ../../docs_src/query_params_str_validations/tutorial006_an_py39.py hl[9] *} -### Requerido con Puntos suspensivos (`...`) - -Hay una manera alternativa de declarar explícitamente que un valor es requerido. Puedes establecer el valor por defecto al valor literal `...`: - -{* ../../docs_src/query_params_str_validations/tutorial006b_an_py39.py hl[9] *} - -/// info | InformaciÃŗn - -Si no habías visto eso `...` antes: es un valor especial Ãēnico, es parte de Python y se llama "Ellipsis". - -Se usa por Pydantic y FastAPI para declarar explícitamente que un valor es requerido. - -/// - -Esto le permitirÃĄ a **FastAPI** saber que este parÃĄmetro es requerido. - ### Requerido, puede ser `None` Puedes declarar que un parÃĄmetro puede aceptar `None`, pero que aÃēn así es requerido. Esto obligaría a los clientes a enviar un valor, incluso si el valor es `None`. diff --git a/docs/es/llm-prompt.md b/docs/es/llm-prompt.md index 3340dbc99..936ed9bba 100644 --- a/docs/es/llm-prompt.md +++ b/docs/es/llm-prompt.md @@ -4,56 +4,6 @@ Use the informal grammar (use "tÃē" instead of "usted"). For instructions or titles in imperative, keep them in imperative, for example "Edit it" to "Edítalo". -There are special blocks of notes, tips and others that look like: - -/// note - -To translate it, keep the same line and add the translation after a vertical bar: - -/// note | Nota - -Some examples: - -Source: - -/// tip - -Result: - -/// tip | Consejo - -Source: - -/// details | Preview - -Result: - -/// details | Vista previa - -Source: - -/// warning - -Result: - -/// warning | Advertencia - -Source: - -/// info - -Result: - -/// info | InformaciÃŗn - -Source: - -/// note | Technical Details - -Result: - -/// note | Detalles TÊcnicos - --- For the next terms, use the following translations: diff --git a/docs/fa/docs/async.md b/docs/fa/docs/async.md new file mode 100644 index 000000000..e07374862 --- /dev/null +++ b/docs/fa/docs/async.md @@ -0,0 +1,444 @@ +# Ų‡Ų…â€ŒØ˛Ų…Ø§Ų†ÛŒ ؈ async / await + +ØŦØ˛ØĻیاØĒ Ø¯Øą Ų…ŲˆØąØ¯ ØŗÛŒŲ†ØĒÚŠØŗ `async def` Ø¨ØąØ§ÛŒ *ØĒŲˆØ§Ø¨Øš ØšŲ…Ų„ÛŒØ§ØĒ Ų…ØŗÛŒØą* ؈ ÛŒŲ‡ ÚŠŲ… ŲžÛŒØ´â€ŒØ˛Ų…ÛŒŲ†Ų‡ Ø¯Øą Ų…ŲˆØąØ¯ ڊد Ų†Ø§Ų‡Ų…â€ŒØ˛Ų…Ø§Ų†ØŒ Ų‡Ų…â€ŒØ˛Ų…Ø§Ų†ÛŒ ؈ Ų…ŲˆØ§Ø˛ÛŒâ€ŒØŗØ§Ø˛ÛŒ. + +## ØšØŦŲ„Ų‡ Ø¯Ø§ØąÛŒØŸ + +TL;DR: + +Ø§Ú¯Ų‡ Ø§Ø˛ ÚŠØĒØ§Ø¨ØŽŲˆŲ†Ų‡â€ŒŲ‡Ø§ÛŒ ØŗŲˆŲ…â€ŒØ´ØŽØĩی Ø§ØŗØĒŲØ§Ø¯Ų‡ Ų…ÛŒâ€ŒÚŠŲ†ÛŒ ÚŠŲ‡ Ø¨Ų‡ØĒ Ų…ÛŒâ€ŒÚ¯Ų† با `await` ØĩØ¯Ø§Ø´ŲˆŲ† ÚŠŲ†ÛŒØŒ Ų…ØĢŲ„: + +```Python +results = await some_library() +``` + +Ø§ŲˆŲ† ŲˆŲ‚ØĒ، *ØĒŲˆØ§Ø¨Øš ØšŲ…Ų„ÛŒØ§ØĒ Ų…ØŗÛŒØąØĒ* ØąŲˆ با `async def` ØĒØšØąÛŒŲ ÚŠŲ†ØŒ Ø§ÛŒŲ†ØŦŲˆØąÛŒ: + +```Python hl_lines="2" +@app.get('/') +async def read_results(): + results = await some_library() + return results +``` + +/// note + +ŲŲ‚Øˇ ØĒŲˆÛŒ ØĒŲˆØ§Ø¨ØšÛŒ ÚŠŲ‡ با `async def` ØŗØ§ØŽØĒŲ‡ Ø´Ø¯Ų† Ų…ÛŒâ€ŒØĒŲˆŲ†ÛŒ Ø§Ø˛ `await` Ø§ØŗØĒŲØ§Ø¯Ų‡ ÚŠŲ†ÛŒ. + +/// + +--- + +Ø§Ú¯Ų‡ Ø§Ø˛ ÛŒŲ‡ ÚŠØĒØ§Ø¨ØŽŲˆŲ†Ų‡ ØŗŲˆŲ…â€ŒØ´ØŽØĩ Ø§ØŗØĒŲØ§Ø¯Ų‡ Ų…ÛŒâ€ŒÚŠŲ†ÛŒ ÚŠŲ‡ با ÛŒŲ‡ Ú†ÛŒØ˛ÛŒ (Ų…ØĢŲ„ دیØĒØ§Ø¨ÛŒØŗØŒ API، ØŗÛŒØŗØĒŲ… ŲØ§ÛŒŲ„ ؈ ØēÛŒØąŲ‡) Ø§ØąØĒØ¨Ø§Øˇ Ø¯Ø§ØąŲ‡ ؈ Ø§Ø˛ `await` ŲžØ´ØĒÛŒØ¨Ø§Ų†ÛŒ Ų†Ų…ÛŒâ€ŒÚŠŲ†Ų‡ (ÚŠŲ‡ Ø§Ų„Ø§Ų† Ø¨ØąØ§ÛŒ بیشØĒØą ÚŠØĒØ§Ø¨ØŽŲˆŲ†Ų‡â€ŒŲ‡Ø§ÛŒ دیØĒØ§Ø¨ÛŒØŗ Ø§ÛŒŲ†ØŦŲˆØąÛŒŲ‡)، Ø§ŲˆŲ† ŲˆŲ‚ØĒ *ØĒŲˆØ§Ø¨Øš ØšŲ…Ų„ÛŒØ§ØĒ Ų…ØŗÛŒØąØĒ* ØąŲˆ ؚادی، ŲŲ‚Øˇ با `def` ØĒØšØąÛŒŲ ÚŠŲ†ØŒ Ø§ÛŒŲ†ØŦŲˆØąÛŒ: + +```Python hl_lines="2" +@app.get('/') +def results(): + results = some_library() + return results +``` + +--- + +Ø§Ú¯Ų‡ Ø¨ØąŲ†Ø§Ų…Ų‡â€ŒØ§ØĒ (Ø¨Ų‡ Ų‡Øą Ø¯Ų„ÛŒŲ„ÛŒ) Ų„Ø§Ø˛Ų… Ų†ÛŒØŗØĒ با Ú†ÛŒØ˛ Ø¯ÛŒÚ¯Ų‡â€ŒØ§ÛŒ Ø§ØąØĒØ¨Ø§Øˇ Ø¨ØąŲ‚ØąØ§Øą ÚŠŲ†Ų‡ ؈ Ų…Ų†ØĒØ¸Øą ØŦŲˆØ§Ø¨Ø´ Ø¨Ų…ŲˆŲ†Ų‡ØŒ Ø§Ø˛ `async def` Ø§ØŗØĒŲØ§Ø¯Ų‡ ÚŠŲ†. + +--- + +Ø§Ú¯Ų‡ Ų†Ų…ÛŒâ€ŒØ¯ŲˆŲ†ÛŒ Ú†ÛŒÚŠØ§Øą ÚŠŲ†ÛŒØŒ Ø§Ø˛ `def` Ų…ØšŲ…ŲˆŲ„ÛŒ Ø§ØŗØĒŲØ§Ø¯Ų‡ ÚŠŲ†. + +--- + +**ØĒ؈ØŦŲ‡**: Ų…ÛŒâ€ŒØĒŲˆŲ†ÛŒ ØĒŲˆÛŒ *ØĒŲˆØ§Ø¨Øš ØšŲ…Ų„ÛŒØ§ØĒ Ų…ØŗÛŒØąØĒ* Ų‡Øą Ú†Ų‚Ø¯Øą ÚŠŲ‡ Ų„Ø§Ø˛Ų… Ø¯Ø§ØąÛŒ `def` ؈ `async def` ØąŲˆ Ų‚Ø§ØˇÛŒ ÚŠŲ†ÛŒ ؈ Ų‡Øą ÚŠØ¯ŲˆŲ… ØąŲˆ با Ø¨Ų‡ØĒØąÛŒŲ† Ú¯Ø˛ÛŒŲ†Ų‡ Ø¨ØąØ§ØĒ ØĒØšØąÛŒŲ ÚŠŲ†ÛŒ. FastAPI ØŽŲˆØ¯Ø´ ÚŠØ§Øą Ø¯ØąØŗØĒ ØąŲˆ Ø¨Ø§Ų‡Ø§Ø´ŲˆŲ† Ø§Ų†ØŦØ§Ų… Ų…ÛŒâ€ŒØ¯Ų‡. + +Ø¨Ų‡ Ų‡Øą Ø­Ø§Ų„ØŒ ØĒŲˆÛŒ Ų‡Øą ÚŠØ¯ŲˆŲ… Ø§Ø˛ Ų…ŲˆŲ‚ØšÛŒØĒâ€ŒŲ‡Ø§ÛŒ Ø¨Ø§Ų„Ø§ØŒ FastAPI Ų‡Ų†ŲˆØ˛ Ų†Ø§Ų‡Ų…â€ŒØ˛Ų…Ø§Ų† ÚŠØ§Øą Ų…ÛŒâ€ŒÚŠŲ†Ų‡ ؈ ØŽÛŒŲ„ÛŒ ØŽÛŒŲ„ÛŒ ØŗØąÛŒØš Ų‡ØŗØĒ. + +ŲˆŲ„ÛŒ با Ø¯Ų†Ø¨Ø§Ų„ ÚŠØąØ¯Ų† Ų…ØąØ§Ø­Ų„ Ø¨Ø§Ų„Ø§ØŒ Ų…ÛŒâ€ŒØĒŲˆŲ†Ų‡ ÛŒŲ‡ ØŗØąÛŒ Ø¨Ų‡ÛŒŲ†Ų‡â€ŒØŗØ§Ø˛ÛŒ ØšŲ…Ų„ÚŠØąØ¯ Ų‡Ų… Ø¨ÚŠŲ†Ų‡. + +## ØŦØ˛ØĻیاØĒ ŲŲ†ÛŒ + +Ų†ØŗØŽŲ‡â€ŒŲ‡Ø§ÛŒ Ų…Ø¯ØąŲ† ŲžØ§ÛŒØĒŲˆŲ† Ø§Ø˛ **"ڊد Ų†Ø§Ų‡Ų…â€ŒØ˛Ų…Ø§Ų†"** با Ú†ÛŒØ˛ÛŒ ÚŠŲ‡ Ø¨Ų‡Ø´ **"ÚŠØąŲˆØĒÛŒŲ†"** Ų…ÛŒâ€ŒÚ¯Ų† ŲžØ´ØĒÛŒØ¨Ø§Ų†ÛŒ Ų…ÛŒâ€ŒÚŠŲ†Ų†ØŒ با ØŗÛŒŲ†ØĒÚŠØŗ **`async` ؈ `await`**. + +بیاید Ø§ÛŒŲ† ØŦŲ…Ų„Ų‡ ØąŲˆ ØĒÚŠŲ‡â€ŒØĒÚŠŲ‡ ØĒŲˆÛŒ Ø¨ØŽØ´â€ŒŲ‡Ø§ÛŒ Ø˛ÛŒØą Ø¨Ø¨ÛŒŲ†ÛŒŲ…: + +* **ڊد Ų†Ø§Ų‡Ų…â€ŒØ˛Ų…Ø§Ų†** +* **`async` ؈ `await`** +* **ÚŠØąŲˆØĒÛŒŲ†â€ŒŲ‡Ø§** + +## ڊد Ų†Ø§Ų‡Ų…â€ŒØ˛Ų…Ø§Ų† + +ڊد Ų†Ø§Ų‡Ų…â€ŒØ˛Ų…Ø§Ų† ÛŒØšŲ†ÛŒ Ø˛Ø¨ŲˆŲ† đŸ’Ŧ ÛŒŲ‡ ØąØ§Ų‡ÛŒ Ø¯Ø§ØąŲ‡ ÚŠŲ‡ Ø¨Ų‡ ÚŠØ§Ų…ŲžÛŒŲˆØĒØą / Ø¨ØąŲ†Ø§Ų…Ų‡ 🤖 Ø¨Ú¯Ų‡ ØĒŲˆÛŒ ÛŒŲ‡ ØŦای ڊد، باید Ų…Ų†ØĒØ¸Øą Ø¨Ų…ŲˆŲ†Ų‡ ØĒا *ÛŒŲ‡ Ú†ÛŒØ˛ Ø¯ÛŒÚ¯Ų‡* ÛŒŲ‡ ØŦای Ø¯ÛŒÚ¯Ų‡ ØĒŲ…ŲˆŲ… Ø¨Ø´Ų‡. ŲØąØļ ÚŠŲ† Ø§ŲˆŲ† *ÛŒŲ‡ Ú†ÛŒØ˛ Ø¯ÛŒÚ¯Ų‡* Ø§ØŗŲ…Ø´ "ŲØ§ÛŒŲ„-ØĸØąŲˆŲ…" 📝 Ø¨Ø§Ø´Ų‡. + +ŲžØŗØŒ ØĒŲˆÛŒ Ø§ŲˆŲ† Ų…Ø¯ØĒ، ÚŠØ§Ų…ŲžÛŒŲˆØĒØą Ų…ÛŒâ€ŒØĒŲˆŲ†Ų‡ Ø¨ØąŲ‡ ÛŒŲ‡ ÚŠØ§Øą Ø¯ÛŒÚ¯Ų‡ Ø¨ÚŠŲ†Ų‡ØŒ ØĒا ŲˆŲ‚ØĒی "ŲØ§ÛŒŲ„-ØĸØąŲˆŲ…" 📝 ØĒŲ…ŲˆŲ… Ø¨Ø´Ų‡. + +بؚدش ÚŠØ§Ų…ŲžÛŒŲˆØĒØą / Ø¨ØąŲ†Ø§Ų…Ų‡ 🤖 Ų‡Øą ŲˆŲ‚ØĒ ŲØąØĩØĒی داشØĒŲ‡ Ø¨Ø§Ø´Ų‡ Ø¨ØąŲ…ÛŒâ€ŒÚ¯ØąØ¯Ų‡ØŒ Ú†ŲˆŲ† Ø¯ŲˆØ¨Ø§ØąŲ‡ Ų…Ų†ØĒØ¸ØąŲ‡ØŒ یا Ų‡Øą ŲˆŲ‚ØĒ Ų‡Ų…Ų‡ ÚŠØ§ØąÛŒ ÚŠŲ‡ Ø§ŲˆŲ† Ų„Ø­Ø¸Ų‡ داشØĒŲ‡ ØĒŲ…ŲˆŲ… ÚŠØąØ¯Ų‡. ؈ Ų…ÛŒâ€ŒØ¨ÛŒŲ†Ų‡ Øĸیا ÚŠØ§ØąØ§ÛŒÛŒ ÚŠŲ‡ Ų…Ų†ØĒØ¸ØąØ´ŲˆŲ† Ø¨ŲˆØ¯Ų‡ ØĒŲ…ŲˆŲ… Ø´Ø¯Ų† یا Ų†Ų‡ØŒ ؈ Ų‡Øą ÚŠØ§ØąÛŒ ÚŠŲ‡ باید Ø¨ÚŠŲ†Ų‡ ØąŲˆ Ø§Ų†ØŦØ§Ų… Ų…ÛŒâ€ŒØ¯Ų‡. + +بؚد، Ø§ŲˆŲ† 🤖 Ø§ŲˆŲ„ÛŒŲ† ÚŠØ§ØąÛŒ ÚŠŲ‡ ØĒŲ…ŲˆŲ… Ø´Ø¯Ų‡ (Ų…ØĢŲ„Ø§Ų‹ "ŲØ§ÛŒŲ„-ØĸØąŲˆŲ…" 📝 Ų…Ø§) ØąŲˆ Ø¨ØąŲ…ÛŒâ€ŒØ¯Ø§ØąŲ‡ ؈ Ų‡Øą ÚŠØ§ØąÛŒ ÚŠŲ‡ باید Ø¨Ø§Ų‡Ø§Ø´ Ø¨ÚŠŲ†Ų‡ ØąŲˆ Ø§Ø¯Ø§Ų…Ų‡ Ų…ÛŒâ€ŒØ¯Ų‡. + +Ø§ÛŒŲ† "Ų…Ų†ØĒØ¸Øą ÛŒŲ‡ Ú†ÛŒØ˛ Ø¯ÛŒÚ¯Ų‡ Ø¨ŲˆØ¯Ų†" Ų…ØšŲ…ŲˆŲ„Ø§Ų‹ Ø¨Ų‡ ØšŲ…Ų„ÛŒØ§ØĒ I/O Ø§Ø´Ø§ØąŲ‡ Ø¯Ø§ØąŲ‡ ÚŠŲ‡ Ų†ØŗØ¨ØĒØ§Ų‹ "ØĸØąŲˆŲ…" Ų‡ØŗØĒŲ† (Ų†ØŗØ¨ØĒ Ø¨Ų‡ ØŗØąØšØĒ ŲžØąØ¯Ø§Ø˛Ų†Ø¯Ų‡ ؈ Ø­Ø§ŲØ¸Ų‡ RAM)، Ų…ØĢŲ„ Ų…Ų†ØĒØ¸Øą Ų…ŲˆŲ†Ø¯Ų† Ø¨ØąØ§ÛŒ: + +* Ø¯Ø§Ø¯Ų‡â€ŒŲ‡Ø§ÛŒÛŒ ÚŠŲ‡ Ø§Ø˛ ÚŠŲ„Ø§ÛŒŲ†ØĒ Ø§Ø˛ ØˇØąÛŒŲ‚ Ø´Ø¨ÚŠŲ‡ ŲØąØŗØĒØ§Ø¯Ų‡ Ų…ÛŒâ€ŒØ´Ų† +* Ø¯Ø§Ø¯Ų‡â€ŒŲ‡Ø§ÛŒÛŒ ÚŠŲ‡ Ø¨ØąŲ†Ø§Ų…Ų‡â€ŒØ§ØĒ ŲØąØŗØĒØ§Ø¯Ų‡ ØĒا Ø§Ø˛ ØˇØąÛŒŲ‚ Ø´Ø¨ÚŠŲ‡ Ø¨Ų‡ ÚŠŲ„Ø§ÛŒŲ†ØĒ Ø¨ØąØŗŲ‡ +* Ų…Ø­ØĒŲˆØ§ÛŒ ÛŒŲ‡ ŲØ§ÛŒŲ„ ØĒŲˆÛŒ Ø¯ÛŒØŗÚŠ ÚŠŲ‡ ØŗÛŒØŗØĒŲ… Ø¨ØŽŲˆŲ†Ø¯Ø´ ؈ Ø¨Ų‡ Ø¨ØąŲ†Ø§Ų…Ų‡â€ŒØ§ØĒ Ø¨Ø¯Ų‡ +* Ų…Ø­ØĒŲˆØ§ÛŒÛŒ ÚŠŲ‡ Ø¨ØąŲ†Ø§Ų…Ų‡â€ŒØ§ØĒ Ø¨Ų‡ ØŗÛŒØŗØĒŲ… Ø¯Ø§Ø¯Ų‡ ØĒا ØĒŲˆÛŒ Ø¯ÛŒØŗÚŠ Ø¨Ų†ŲˆÛŒØŗŲ‡ +* ÛŒŲ‡ ØšŲ…Ų„ÛŒØ§ØĒ API Ø§Ø˛ ØąØ§Ų‡ Ø¯ŲˆØą +* ÛŒŲ‡ ØšŲ…Ų„ÛŒØ§ØĒ دیØĒØ§Ø¨ÛŒØŗ ÚŠŲ‡ ØĒŲ…ŲˆŲ… Ø¨Ø´Ų‡ +* ÛŒŲ‡ ÚŠŲˆØĻØąÛŒ دیØĒØ§Ø¨ÛŒØŗ ÚŠŲ‡ Ų†ØĒایØŦØ´ Ø¨ØąÚ¯ØąØ¯Ų‡ +* ؈ ØēÛŒØąŲ‡. + +Ú†ŲˆŲ† Ø˛Ų…Ø§Ų† اØŦØąØ§ بیشØĒØą ØĩØąŲ Ø§Ų†ØĒØ¸Ø§Øą Ø¨ØąØ§ÛŒ ØšŲ…Ų„ÛŒØ§ØĒ I/O Ų…ÛŒâ€ŒØ´Ų‡ØŒ Ø¨Ų‡Ø´ŲˆŲ† Ų…ÛŒâ€ŒÚ¯Ų† ØšŲ…Ų„ÛŒØ§ØĒ "I/O bound". + +Ø¨Ų‡Ø´ "Ų†Ø§Ų‡Ų…â€ŒØ˛Ų…Ø§Ų†" Ų…ÛŒâ€ŒÚ¯Ų† Ú†ŲˆŲ† ÚŠØ§Ų…ŲžÛŒŲˆØĒØą / Ø¨ØąŲ†Ø§Ų…Ų‡ Ų„Ø§Ø˛Ų… Ų†ÛŒØŗØĒ با ÚŠØ§Øą ØĸØąŲˆŲ… "Ų‡Ų…â€ŒØ˛Ų…Ø§Ų†" Ø¨Ø§Ø´Ų‡ØŒ Ų…Ų†ØĒØ¸Øą Ų„Ø­Ø¸Ų‡ Ø¯Ų‚ÛŒŲ‚ ØĒŲ…ŲˆŲ… Ø´Ø¯Ų† ÚŠØ§Øą Ø¨Ų…ŲˆŲ†Ų‡ØŒ Ø¯Øą Ø­Ø§Ų„ÛŒ ÚŠŲ‡ Ų‡ÛŒÚ† ÚŠØ§ØąÛŒ Ų†Ų…ÛŒâ€ŒÚŠŲ†Ų‡ØŒ ØĒا Ų†ØĒیØŦŲ‡ ØąŲˆ Ø¨Ú¯ÛŒØąŲ‡ ؈ ÚŠØ§ØąØ´ ØąŲˆ Ø§Ø¯Ø§Ų…Ų‡ Ø¨Ø¯Ų‡. + +Ø¨Ų‡ ØŦاش، Ú†ŲˆŲ† ÛŒŲ‡ ØŗÛŒØŗØĒŲ… "Ų†Ø§Ų‡Ų…â€ŒØ˛Ų…Ø§Ų†" Ų‡ØŗØĒ، ŲˆŲ‚ØĒی ÚŠØ§Øą ØĒŲ…ŲˆŲ… شد، Ų…ÛŒâ€ŒØĒŲˆŲ†Ų‡ ÛŒŲ‡ ÚŠŲ… ØĒŲˆÛŒ Øĩ؁ Ų…Ų†ØĒØ¸Øą Ø¨Ų…ŲˆŲ†Ų‡ (Ú†Ų†Ø¯ Ų…ÛŒÚŠØąŲˆØĢØ§Ų†ÛŒŲ‡) ØĒا ÚŠØ§Ų…ŲžÛŒŲˆØĒØą / Ø¨ØąŲ†Ø§Ų…Ų‡ Ų‡Øą ÚŠØ§ØąÛŒ ÚŠŲ‡ ØąŲØĒŲ‡ Ø¨ÚŠŲ†Ų‡ ØąŲˆ ØĒŲ…ŲˆŲ… ÚŠŲ†Ų‡ØŒ ؈ بؚد Ø¨ØąÚ¯ØąØ¯Ų‡ Ų†ØĒیØŦŲ‡ ØąŲˆ Ø¨Ú¯ÛŒØąŲ‡ ؈ Ø¨Ø§Ų‡Ø§Ø´ ÚŠØ§Øą ÚŠŲ†Ų‡. + +Ø¨ØąØ§ÛŒ "Ų‡Ų…â€ŒØ˛Ų…Ø§Ų†" (Ø¨ØąØŽŲ„Ø§Ų "Ų†Ø§Ų‡Ų…â€ŒØ˛Ų…Ø§Ų†") Ų…ØšŲ…ŲˆŲ„Ø§Ų‹ Ø§Ø˛ اØĩØˇŲ„Ø§Ø­ "ØĒØąØĒیبی" Ų‡Ų… Ø§ØŗØĒŲØ§Ø¯Ų‡ Ų…ÛŒâ€ŒÚŠŲ†Ų†ØŒ Ú†ŲˆŲ† ÚŠØ§Ų…ŲžÛŒŲˆØĒØą / Ø¨ØąŲ†Ø§Ų…Ų‡ Ų‡Ų…Ų‡ Ų…ØąØ§Ø­Ų„ ØąŲˆ Ø¨Ų‡ ØĒØąØĒیب Ø¯Ų†Ø¨Ø§Ų„ Ų…ÛŒâ€ŒÚŠŲ†Ų‡ Ų‚Ø¨Ų„ Ø§Ø˛ Ø§ÛŒŲ†ÚŠŲ‡ Ø¨ØąŲ‡ ØŗØąØ§Øē ÛŒŲ‡ ÚŠØ§Øą Ø¯ÛŒÚ¯Ų‡ØŒ Ø­ØĒی Ø§Ú¯Ų‡ Ø§ŲˆŲ† Ų…ØąØ§Ø­Ų„ Ø´Ø§Ų…Ų„ Ø§Ų†ØĒØ¸Ø§Øą Ø¨Ø§Ø´Ų†. + +### Ų‡Ų…â€ŒØ˛Ų…Ø§Ų†ÛŒ ؈ Ø¨ØąÚ¯ØąŲ‡Ø§ + +Ø§ÛŒŲ† Ø§ÛŒØ¯Ų‡ **Ų†Ø§Ų‡Ų…â€ŒØ˛Ų…Ø§Ų†** ÚŠŲ‡ Ø¨Ø§Ų„Ø§ ØĒ؈Øļیح Ø¯Ø§Ø¯Ų… Ú¯Ø§Ų‡ÛŒ Ø¨Ų‡Ø´ **"Ų‡Ų…â€ŒØ˛Ų…Ø§Ų†ÛŒ"** Ų‡Ų… Ų…ÛŒâ€ŒÚ¯Ų†. با **"Ų…ŲˆØ§Ø˛ÛŒâ€ŒØŗØ§Ø˛ÛŒ"** ŲØąŲ‚ Ø¯Ø§ØąŲ‡. + +**Ų‡Ų…â€ŒØ˛Ų…Ø§Ų†ÛŒ** ؈ **Ų…ŲˆØ§Ø˛ÛŒâ€ŒØŗØ§Ø˛ÛŒ** Ų‡Øą Ø¯Ųˆ Ø¨Ų‡ "اØĒŲØ§Ų‚ Ø§ŲØĒØ§Ø¯Ų† Ú†ÛŒØ˛Ø§ÛŒ Ų…ØŽØĒ؄؁ ÚŠŲ…â€ŒŲˆØ¨ÛŒØ´ Ų‡Ų…Ø˛Ų…Ø§Ų†" ØąØ¨Øˇ Ø¯Ø§ØąŲ†. + +ŲˆŲ„ÛŒ ØŦØ˛ØĻیاØĒ Ø¨ÛŒŲ† *Ų‡Ų…â€ŒØ˛Ų…Ø§Ų†ÛŒ* ؈ *Ų…ŲˆØ§Ø˛ÛŒâ€ŒØŗØ§Ø˛ÛŒ* ØŽÛŒŲ„ÛŒ Ų…ØĒŲØ§ŲˆØĒŲ‡. + +Ø¨ØąØ§ÛŒ Ø¯ÛŒØ¯Ų† ŲØąŲ‚Ø´ØŒ Ø§ÛŒŲ† Ø¯Ø§ØŗØĒØ§Ų† Ø¯Øą Ų…ŲˆØąØ¯ Ø¨ØąÚ¯ØąŲ‡Ø§ ØąŲˆ ØĒØĩŲˆØą ÚŠŲ†: + +### Ø¨ØąÚ¯ØąŲ‡Ø§ÛŒ Ų‡Ų…â€ŒØ˛Ų…Ø§Ų† + +با ØšØ´Ų‚ØĒ Ų…ÛŒâ€ŒØąÛŒ ŲØŗØĒâ€ŒŲŲˆØ¯ Ø¨Ú¯ÛŒØąÛŒŲ†ØŒ ØĒŲˆÛŒ Øĩ؁ ŲˆØ§ÛŒŲ…ÛŒØŗØĒی Ø¯Øą Ø­Ø§Ų„ÛŒ ÚŠŲ‡ ØĩŲ†Ø¯ŲˆŲ‚Ø¯Ø§Øą ØŗŲØ§ØąØ´ ØĸØ¯Ų…Ø§ÛŒ ØŦŲ„ŲˆÛŒ ØĒ؈ ØąŲˆ Ų…ÛŒâ€ŒÚ¯ÛŒØąŲ‡. 😍 + + + +بؚد Ų†ŲˆØ¨ØĒ ØĒ؈ Ų…ÛŒâ€ŒØ´Ų‡ØŒ ØŗŲØ§ØąØ´ Ø¯Ųˆ ØĒا Ø¨ØąÚ¯Øą ØŽÛŒŲ„ÛŒ شیڊ Ø¨ØąØ§ÛŒ ØŽŲˆØ¯ØĒ ؈ ØšØ´Ų‚ØĒ Ų…ÛŒâ€ŒØ¯ÛŒ. 🍔🍔 + + + +ØĩŲ†Ø¯ŲˆŲ‚Ø¯Ø§Øą ÛŒŲ‡ Ú†ÛŒØ˛ÛŒ Ø¨Ų‡ ØĸØ´ŲžØ˛ ØĒŲˆÛŒ ØĸØ´ŲžØ˛ØŽŲˆŲ†Ų‡ Ų…ÛŒâ€ŒÚ¯Ų‡ ØĒا Ø¨Ø¯ŲˆŲ†Ų† باید Ø¨ØąÚ¯ØąŲ‡Ø§ÛŒ ØĒ؈ ØąŲˆ ØĸŲ…Ø§Ø¯Ų‡ ÚŠŲ†Ų† (Ú¯ØąÚ†Ų‡ Ø§Ų„Ø§Ų† Ø¯Ø§ØąŲ† Ø¨ØąÚ¯ØąŲ‡Ø§ÛŒ Ų…Ø´ØĒØąÛŒØ§ÛŒ Ų‚Ø¨Ų„ÛŒ ØąŲˆ Ø¯ØąØŗØĒ Ų…ÛŒâ€ŒÚŠŲ†Ų†). + + + +ŲžŲˆŲ„ ØąŲˆ Ų…ÛŒâ€ŒØ¯ÛŒ. 💸 + +ØĩŲ†Ø¯ŲˆŲ‚Ø¯Ø§Øą Ø´Ų…Ø§ØąŲ‡ Ų†ŲˆØ¨ØĒØĒ ØąŲˆ Ø¨Ų‡ØĒ Ų…ÛŒâ€ŒØ¯Ų‡. + + + +ŲˆŲ‚ØĒی Ų…Ų†ØĒØ¸ØąÛŒØŒ با ØšØ´Ų‚ØĒ Ų…ÛŒâ€ŒØąÛŒ ÛŒŲ‡ Ų…ÛŒØ˛ Ø§Ų†ØĒ؎اب Ų…ÛŒâ€ŒÚŠŲ†ÛŒØŒ Ų…ÛŒâ€ŒØ´ÛŒŲ†ÛŒ ؈ ÚŠŲ„ÛŒ با ØšØ´Ų‚ØĒ Ø­ØąŲ Ų…ÛŒâ€ŒØ˛Ų†ÛŒ (Ú†ŲˆŲ† Ø¨ØąÚ¯ØąŲ‡Ø§ØĒ ØŽÛŒŲ„ÛŒ Ø´ÛŒÚŠŲ† ؈ ØĸŲ…Ø§Ø¯Ų‡ ÚŠØąØ¯Ų†Ø´ŲˆŲ† ÛŒŲ‡ ÚŠŲ… ØˇŲˆŲ„ Ų…ÛŒâ€ŒÚŠØ´Ų‡). + +ŲˆŲ‚ØĒی ŲžØ´ØĒ Ų…ÛŒØ˛ با ØšØ´Ų‚ØĒ Ų†Ø´ØŗØĒی، Ø¯Øą Ø­Ø§Ų„ÛŒ ÚŠŲ‡ Ų…Ų†ØĒØ¸Øą Ø¨ØąÚ¯ØąŲ‡Ø§ÛŒÛŒØŒ Ų…ÛŒâ€ŒØĒŲˆŲ†ÛŒ Ø§ŲˆŲ† Ø˛Ų…Ø§Ų† ØąŲˆ ØĩØąŲ ØĒØ­ØŗÛŒŲ† Ø§ÛŒŲ† ÚŠŲ†ÛŒ ÚŠŲ‡ ØšØ´Ų‚ØĒ Ú†Ų‚Ø¯Øą Ø¨Ø§Ø­Ø§Ų„ØŒ Ų†Ø§Ø˛ ؈ Ø¨Ø§Ų‡ŲˆØ´Ų‡ ✨😍✨. + + + +ŲˆŲ‚ØĒی Ų…Ų†ØĒØ¸ØąÛŒ ؈ با ØšØ´Ų‚ØĒ Ø­ØąŲ Ų…ÛŒâ€ŒØ˛Ų†ÛŒØŒ Ų‡Øą Ø§Ø˛ Ú¯Ø§Ų‡ÛŒ Ø´Ų…Ø§ØąŲ‡â€ŒØ§ÛŒ ÚŠŲ‡ ØąŲˆ ŲžÛŒØ´ØŽŲˆŲ† Ų†Ø´ŲˆŲ† Ø¯Ø§Ø¯Ų‡ Ų…ÛŒâ€ŒØ´Ų‡ ØąŲˆ چک Ų…ÛŒâ€ŒÚŠŲ†ÛŒ ÚŠŲ‡ Ø¨Ø¨ÛŒŲ†ÛŒ Ų†ŲˆØ¨ØĒØĒ Ø´Ø¯Ų‡ یا Ų†Ų‡. + +بؚد ÛŒŲ‡ ØŦایی Ø¨Ø§Ų„Ø§ØŽØąŲ‡ Ų†ŲˆØ¨ØĒØĒ Ų…ÛŒâ€ŒØ´Ų‡. Ų…ÛŒâ€ŒØąÛŒ ŲžÛŒØ´ØŽŲˆŲ†ØŒ Ø¨ØąÚ¯ØąŲ‡Ø§ØĒ ØąŲˆ Ų…ÛŒâ€ŒÚ¯ÛŒØąÛŒ ؈ Ø¨ØąŲ…ÛŒâ€ŒÚ¯ØąØ¯ÛŒ ØŗØą Ų…ÛŒØ˛. + + + +ØĒ؈ ؈ ØšØ´Ų‚ØĒ Ø¨ØąÚ¯ØąŲ‡Ø§ ØąŲˆ Ų…ÛŒâ€ŒØŽŲˆØąÛŒŲ† ؈ ÛŒŲ‡ ŲˆŲ‚ØĒ ØŽŲˆØ¨ Ø¨Ø§Ų‡Ų… Ø¯Ø§ØąÛŒŲ†. ✨ + + + +/// info + +ØĒØĩØ§ŲˆÛŒØą Ų‚Ø´Ų†Ú¯ Ø§Ø˛ ÚŠØĒØąÛŒŲ†Ø§ ØĒØ§Ų…ŲžØŗŲˆŲ†. 🎨 + +/// + +--- + +ØĒØĩŲˆØą ÚŠŲ† ØĒ؈ ØĒŲˆÛŒ Ø§ÛŒŲ† Ø¯Ø§ØŗØĒØ§Ų† ÚŠØ§Ų…ŲžÛŒŲˆØĒØą / Ø¨ØąŲ†Ø§Ų…Ų‡ 🤖 Ų‡ØŗØĒی. + +ŲˆŲ‚ØĒی ØĒŲˆÛŒ Øĩ؁ Ų‡ØŗØĒی، ŲŲ‚Øˇ Ø¨ÛŒÚŠØ§ØąÛŒ đŸ˜´ØŒ Ų…Ų†ØĒØ¸Øą Ų†ŲˆØ¨ØĒØĒ Ų‡ØŗØĒی، ÚŠØ§Øą ØŽÛŒŲ„ÛŒ "Ų…ŲÛŒØ¯ÛŒ" Ų†Ų…ÛŒâ€ŒÚŠŲ†ÛŒ. ŲˆŲ„ÛŒ Øĩ؁ ØŗØąÛŒØš ŲžÛŒØ´ Ų…ÛŒâ€ŒØąŲ‡ Ú†ŲˆŲ† ØĩŲ†Ø¯ŲˆŲ‚Ø¯Ø§Øą ŲŲ‚Øˇ ØŗŲØ§ØąØ´ Ų…ÛŒâ€ŒÚ¯ÛŒØąŲ‡ (ØĸŲ…Ø§Ø¯Ø´ŲˆŲ† Ų†Ų…ÛŒâ€ŒÚŠŲ†Ų‡)، ŲžØŗ Ø§ÛŒŲ† ØŽŲˆØ¨Ų‡. + +بؚد، ŲˆŲ‚ØĒی Ų†ŲˆØ¨ØĒØĒ Ų…ÛŒâ€ŒØ´Ų‡ØŒ ÚŠØ§Øą "Ų…ŲÛŒØ¯" ŲˆØ§Ų‚ØšÛŒ Ų…ÛŒâ€ŒÚŠŲ†ÛŒØŒ Ų…Ų†Ųˆ ØąŲˆ ŲžØąØ¯Ø§Ø˛Ø´ Ų…ÛŒâ€ŒÚŠŲ†ÛŒØŒ ØĒØĩŲ…ÛŒŲ… Ų…ÛŒâ€ŒÚ¯ÛŒØąÛŒ چی Ų…ÛŒâ€ŒØŽŲˆØ§ÛŒØŒ Ø§Ų†ØĒ؎اب ØšØ´Ų‚ØĒ ØąŲˆ Ų…ÛŒâ€ŒÚ¯ÛŒØąÛŒØŒ ŲžŲˆŲ„ Ų…ÛŒâ€ŒØ¯ÛŒØŒ چک Ų…ÛŒâ€ŒÚŠŲ†ÛŒ Ø§ØŗÚŠŲ†Ø§Øŗ یا ÚŠØ§ØąØĒ Ø¯ØąØŗØĒ ØąŲˆ دادی، چک Ų…ÛŒâ€ŒÚŠŲ†ÛŒ Ø¯ØąØŗØĒ Ø­ØŗØ§Ø¨ Ø´Ø¯Ų‡ØŒ چک Ų…ÛŒâ€ŒÚŠŲ†ÛŒ ØŗŲØ§ØąØ´ ØĸیØĒŲ…Ø§ÛŒ Ø¯ØąØŗØĒ ØąŲˆ Ø¯Ø§ØąŲ‡ ؈ ØēÛŒØąŲ‡. + +ŲˆŲ„ÛŒ بؚد، Ú¯ØąÚ†Ų‡ Ų‡Ų†ŲˆØ˛ Ø¨ØąÚ¯ØąŲ‡Ø§ØĒ ØąŲˆ Ų†Ø¯Ø§ØąÛŒØŒ ÚŠØ§ØąØĒ با ØĩŲ†Ø¯ŲˆŲ‚Ø¯Ø§Øą "Ų…ŲˆŲ‚ØĒØ§Ų‹ Ų…ØĒŲˆŲ‚Ų" ⏸ Ų…ÛŒâ€ŒØ´Ų‡ØŒ Ú†ŲˆŲ† باید Ų…Ų†ØĒØ¸Øą Ø¨Ų…ŲˆŲ†ÛŒ 🕙 ØĒا Ø¨ØąÚ¯ØąŲ‡Ø§ØĒ ØĸŲ…Ø§Ø¯Ų‡ Ø¨Ø´Ų†. + +ŲˆŲ„ÛŒ ŲˆŲ‚ØĒی Ø§Ø˛ ŲžÛŒØ´ØŽŲˆŲ† Ø¯ŲˆØą Ų…ÛŒâ€ŒØ´ÛŒ ؈ با Ø´Ų…Ø§ØąŲ‡ Ų†ŲˆØ¨ØĒØĒ ØŗØą Ų…ÛŒØ˛ Ų…ÛŒâ€ŒØ´ÛŒŲ†ÛŒØŒ Ų…ÛŒâ€ŒØĒŲˆŲ†ÛŒ ØĒ؈ØŦŲ‡ØĒ ØąŲˆ 🔀 Ø¨Ų‡ ØšØ´Ų‚ØĒ بدی ؈ "ÚŠØ§Øą" ⏯ 🤓 ØąŲˆ Ø§ŲˆŲ† Ø¨ÚŠŲ†ÛŒ. بؚدش Ø¯ŲˆØ¨Ø§ØąŲ‡ Ø¯Ø§ØąÛŒ ÛŒŲ‡ Ú†ÛŒØ˛ ØŽÛŒŲ„ÛŒ "Ų…ŲÛŒØ¯" Ø§Ų†ØŦØ§Ų… Ų…ÛŒâ€ŒØ¯ÛŒØŒ Ų…ØĢŲ„ Ų„Ø§Øŗ Ø˛Ø¯Ų† با ØšØ´Ų‚ØĒ 😍. + +بؚد ØĩŲ†Ø¯ŲˆŲ‚Ø¯Ø§Øą 💁 با گذاشØĒŲ† Ø´Ų…Ø§ØąŲ‡â€ŒØ§ØĒ ØąŲˆ Ų†Ų…Ø§ÛŒØ´Ú¯Øą ŲžÛŒØ´ØŽŲˆŲ† Ų…ÛŒâ€ŒÚ¯Ų‡ "Ų…Ų† با Ø¯ØąØŗØĒ ÚŠØąØ¯Ų† Ø¨ØąÚ¯ØąŲ‡Ø§ ØĒŲ…ŲˆŲ… ÚŠØąØ¯Ų…"، ŲˆŲ„ÛŒ ØĒ؈ Ų…ØĢŲ„ Ø¯ÛŒŲˆŲˆŲ†Ų‡â€ŒŲ‡Ø§ ŲˆŲ‚ØĒی Ø´Ų…Ø§ØąŲ‡â€ŒØ§ØĒ ØąŲˆ Ų†Ų…Ø§ÛŒØ´Ú¯Øą Ų…ÛŒØ§Ø¯ ŲŲˆØąÛŒ Ų†Ų…ÛŒâ€ŒŲžØąÛŒ. Ų…ÛŒâ€ŒØ¯ŲˆŲ†ÛŒ ÚŠØŗÛŒ Ø¨ØąÚ¯ØąŲ‡Ø§ØĒ ØąŲˆ Ų†Ų…ÛŒâ€ŒØ¯Ø˛Ø¯Ų‡ Ú†ŲˆŲ† Ø´Ų…Ø§ØąŲ‡ Ų†ŲˆØ¨ØĒØĒ ØąŲˆ Ø¯Ø§ØąÛŒØŒ ؈ Ø§ŲˆŲ†Ø§ Ų‡Ų… Ų…Ø§Ų„ ØŽŲˆØ¯Ø´ŲˆŲ† ØąŲˆ Ø¯Ø§ØąŲ†. + +ŲžØŗ Ų…Ų†ØĒØ¸Øą Ų…ÛŒâ€ŒŲ…ŲˆŲ†ÛŒ ØĒا ØšØ´Ų‚ØĒ Ø¯Ø§ØŗØĒØ§Ų†Ø´ ØąŲˆ ØĒŲ…ŲˆŲ… ÚŠŲ†Ų‡ (ÚŠØ§Øą ŲØšŲ„ÛŒ ⏯ / ŲˆØ¸ÛŒŲŲ‡â€ŒØ§ÛŒ ÚŠŲ‡ Ø¯Ø§ØąŲ‡ ŲžØąØ¯Ø§Ø˛Ø´ Ų…ÛŒâ€ŒØ´Ų‡ 🤓)، ØĸØąŲˆŲ… Ų„Ø¨ØŽŲ†Ø¯ Ų…ÛŒâ€ŒØ˛Ų†ÛŒ ؈ Ų…ÛŒâ€ŒÚ¯ÛŒ ÚŠŲ‡ Ų…ÛŒâ€ŒØąÛŒ Ø¨ØąÚ¯ØąŲ‡Ø§ ØąŲˆ Ø¨ÛŒØ§ØąÛŒ ⏸. + +بؚد Ų…ÛŒâ€ŒØąÛŒ ŲžÛŒØ´ØŽŲˆŲ† đŸ”€ØŒ Ø¨Ų‡ ÚŠØ§Øą Ø§ŲˆŲ„ÛŒŲ‡ ÚŠŲ‡ Ø­Ø§Ų„Ø§ ØĒŲ…ŲˆŲ… Ø´Ø¯Ų‡ ⏯، Ø¨ØąÚ¯ØąŲ‡Ø§ ØąŲˆ Ų…ÛŒâ€ŒÚ¯ÛŒØąÛŒØŒ ØĒØ´ÚŠØą Ų…ÛŒâ€ŒÚŠŲ†ÛŒ ؈ Ų…ÛŒâ€ŒØ¨ØąØ´ŲˆŲ† ØŗØą Ų…ÛŒØ˛. Ø§ÛŒŲ† Ų…ØąØ­Ų„Ų‡ / ŲˆØ¸ÛŒŲŲ‡ ØĒØšØ§Ų…Ų„ با ŲžÛŒØ´ØŽŲˆŲ† ØąŲˆ ØĒŲ…ŲˆŲ… Ų…ÛŒâ€ŒÚŠŲ†Ų‡ ⏚. Ø§ÛŒŲ† Ø¨Ų‡ Ų†ŲˆØ¨Ų‡ ØŽŲˆØ¯Ø´ ÛŒŲ‡ ŲˆØ¸ÛŒŲŲ‡ ØŦدید، "ØŽŲˆØąØ¯Ų† Ø¨ØąÚ¯ØąŲ‡Ø§" 🔀 ⏯، Ų…ÛŒâ€ŒØŗØ§Ø˛Ų‡ØŒ ŲˆŲ„ÛŒ Ø§ŲˆŲ† Ų‚Ø¨Ų„ÛŒ ÚŠŲ‡ "Ú¯ØąŲØĒŲ† Ø¨ØąÚ¯ØąŲ‡Ø§" Ø¨ŲˆØ¯ ØĒŲ…ŲˆŲ… Ø´Ø¯Ų‡ ⏚. + +### Ø¨ØąÚ¯ØąŲ‡Ø§ÛŒ Ų…ŲˆØ§Ø˛ÛŒ + +Ø­Ø§Ų„Ø§ ŲØąØļ ÚŠŲ† Ø§ÛŒŲ†Ø§ "Ø¨ØąÚ¯ØąŲ‡Ø§ÛŒ Ų‡Ų…â€ŒØ˛Ų…Ø§Ų†" Ų†ÛŒØŗØĒŲ†ØŒ Ø¨Ų„ÚŠŲ‡ "Ø¨ØąÚ¯ØąŲ‡Ø§ÛŒ Ų…ŲˆØ§Ø˛ÛŒ" Ų‡ØŗØĒŲ†. + +با ØšØ´Ų‚ØĒ Ų…ÛŒâ€ŒØąÛŒ ŲØŗØĒâ€ŒŲŲˆØ¯ Ų…ŲˆØ§Ø˛ÛŒ Ø¨Ú¯ÛŒØąÛŒ. + +ØĒŲˆÛŒ Øĩ؁ ŲˆØ§ÛŒŲ…ÛŒØŗØĒی Ø¯Øą Ø­Ø§Ų„ÛŒ ÚŠŲ‡ Ú†Ų†Ø¯ ØĒا (Ų…ØĢŲ„Ø§Ų‹ 8 ØĒا) ØĩŲ†Ø¯ŲˆŲ‚Ø¯Ø§Øą ÚŠŲ‡ Ų‡Ų…Ø˛Ų…Ø§Ų† ØĸØ´ŲžØ˛ Ų‡Ų… Ų‡ØŗØĒŲ† ØŗŲØ§ØąØ´ ØĸØ¯Ų…Ø§ÛŒ ØŦŲ„ŲˆÛŒ ØĒ؈ ØąŲˆ Ų…ÛŒâ€ŒÚ¯ÛŒØąŲ†. + +Ų‡Ų…Ų‡ Ų‚Ø¨Ų„ ØĒ؈ Ų…Ų†ØĒØ¸ØąŲ† Ø¨ØąÚ¯ØąŲ‡Ø§Ø´ŲˆŲ† ØĸŲ…Ø§Ø¯Ų‡ Ø¨Ø´Ų‡ Ų‚Ø¨Ų„ Ø§Ø˛ Ø§ÛŒŲ†ÚŠŲ‡ ŲžÛŒØ´ØŽŲˆŲ† ØąŲˆ ØĒØąÚŠ ÚŠŲ†Ų†ØŒ Ú†ŲˆŲ† Ų‡Øą ÚŠØ¯ŲˆŲ… Ø§Ø˛ 8 ØĒا ØĩŲ†Ø¯ŲˆŲ‚Ø¯Ø§Øą Ų…ÛŒâ€ŒØąŲ‡ ؈ Ø¨ØąÚ¯Øą ØąŲˆ Ų‡Ų…ŲˆŲ† Ų…ŲˆŲ‚Øš Ø¯ØąØŗØĒ Ų…ÛŒâ€ŒÚŠŲ†Ų‡ Ų‚Ø¨Ų„ Ø§Ø˛ Ø§ÛŒŲ†ÚŠŲ‡ ØŗŲØ§ØąØ´ بؚدی ØąŲˆ Ø¨Ú¯ÛŒØąŲ‡. + + + +Ø¨Ø§Ų„Ø§ØŽØąŲ‡ Ų†ŲˆØ¨ØĒ ØĒ؈ Ų…ÛŒâ€ŒØ´Ų‡ØŒ ØŗŲØ§ØąØ´ Ø¯Ųˆ ØĒا Ø¨ØąÚ¯Øą ØŽÛŒŲ„ÛŒ شیڊ Ø¨ØąØ§ÛŒ ØŽŲˆØ¯ØĒ ؈ ØšØ´Ų‚ØĒ Ų…ÛŒâ€ŒØ¯ÛŒ. + +ŲžŲˆŲ„ ØąŲˆ Ų…ÛŒâ€ŒØ¯ÛŒ 💸. + + + +ØĩŲ†Ø¯ŲˆŲ‚Ø¯Ø§Øą Ų…ÛŒâ€ŒØąŲ‡ ØĸØ´ŲžØ˛ØŽŲˆŲ†Ų‡. + +Ų…Ų†ØĒØ¸Øą Ų…ÛŒâ€ŒŲ…ŲˆŲ†ÛŒØŒ ØŦŲ„ŲˆÛŒ ŲžÛŒØ´ØŽŲˆŲ† ŲˆØ§ÛŒØŗØĒادی đŸ•™ØŒ ÚŠŲ‡ ÚŠØŗÛŒ Ų‚Ø¨Ų„ Ø§Ø˛ ØĒ؈ Ø¨ØąÚ¯ØąŲ‡Ø§ØĒ ØąŲˆ Ų†Ú¯ÛŒØąŲ‡ØŒ Ú†ŲˆŲ† Ø´Ų…Ø§ØąŲ‡ Ų†ŲˆØ¨ØĒ Ų†ÛŒØŗØĒ. + + + +Ú†ŲˆŲ† ØĒ؈ ؈ ØšØ´Ų‚ØĒ Ų…Ø´ØēŲˆŲ„ Ø§ÛŒŲ† Ų‡ØŗØĒÛŒŲ† ÚŠŲ‡ Ų†Ø°Ø§ØąÛŒŲ† ÚŠØŗÛŒ ØŦŲ„ŲˆØĒŲˆŲ† بیاد ؈ Ų‡Øą ŲˆŲ‚ØĒ Ø¨ØąÚ¯ØąŲ‡Ø§ ØąØŗÛŒØ¯Ų† Ø§ŲˆŲ†Ø§ ØąŲˆ Ø¨Ú¯ÛŒØąŲ‡ØŒ Ų†Ų…ÛŒâ€ŒØĒŲˆŲ†ÛŒ Ø¨Ų‡ ØšØ´Ų‚ØĒ ØĒ؈ØŦŲ‡ ÚŠŲ†ÛŒ. 😞 + +Ø§ÛŒŲ† ÚŠØ§Øą "Ų‡Ų…â€ŒØ˛Ų…Ø§Ų†" Ų‡ØŗØĒ، ØĒ؈ با ØĩŲ†Ø¯ŲˆŲ‚Ø¯Ø§Øą/ØĸØ´ŲžØ˛ đŸ‘¨â€đŸŗ "Ų‡Ų…â€ŒØ˛Ų…Ø§Ų†" Ų‡ØŗØĒی. باید Ų…Ų†ØĒØ¸Øą Ø¨Ų…ŲˆŲ†ÛŒ 🕙 ؈ Ø¯ØąØŗØĒ Ų‡Ų…ŲˆŲ† Ų„Ø­Ø¸Ų‡ ÚŠŲ‡ ØĩŲ†Ø¯ŲˆŲ‚Ø¯Ø§Øą/ØĸØ´ŲžØ˛ đŸ‘¨â€đŸŗ Ø¨ØąÚ¯ØąŲ‡Ø§ ØąŲˆ ØĒŲ…ŲˆŲ… Ų…ÛŒâ€ŒÚŠŲ†Ų‡ ؈ Ø¨Ų‡ØĒ Ų…ÛŒâ€ŒØ¯Ų‡ Ø§ŲˆŲ†ØŦا باشی، ŲˆÚ¯ØąŲ†Ų‡ Ų…Ų…ÚŠŲ†Ų‡ یڊی Ø¯ÛŒÚ¯Ų‡ Ø§ŲˆŲ†Ø§ ØąŲˆ Ø¨Ú¯ÛŒØąŲ‡. + + + +بؚد ØĩŲ†Ø¯ŲˆŲ‚Ø¯Ø§Øą/ØĸØ´ŲžØ˛ØĒ đŸ‘¨â€đŸŗ Ø¨Ø§Ų„Ø§ØŽØąŲ‡ بؚد Ø§Ø˛ ÛŒŲ‡ Ų…Ø¯ØĒ ØˇŲˆŲ„Ø§Ų†ÛŒ Ø§Ų†ØĒØ¸Ø§Øą 🕙 ØŦŲ„ŲˆÛŒ ŲžÛŒØ´ØŽŲˆŲ† با Ø¨ØąÚ¯ØąŲ‡Ø§ØĒ Ø¨ØąŲ…ÛŒâ€ŒÚ¯ØąØ¯Ų‡. + + + +Ø¨ØąÚ¯ØąŲ‡Ø§ØĒ ØąŲˆ Ų…ÛŒâ€ŒÚ¯ÛŒØąÛŒ ؈ با ØšØ´Ų‚ØĒ Ų…ÛŒâ€ŒØąÛŒ ØŗØą Ų…ÛŒØ˛. + +ŲŲ‚Øˇ Ų…ÛŒâ€ŒØŽŲˆØąÛŒŲ†Ø´ŲˆŲ†ØŒ ؈ ØĒŲ…ŲˆŲ…Ų‡. ⏚ + + + +Ø­ØąŲ Ø˛Ø¯Ų† یا Ų„Ø§Øŗ Ø˛Ø¯Ų† Ø˛ÛŒØ§Ø¯ Ų†Ø¨ŲˆØ¯ Ú†ŲˆŲ† بیشØĒØą ŲˆŲ‚ØĒ ØĩØąŲ Ø§Ų†ØĒØ¸Ø§Øą 🕙 ØŦŲ„ŲˆÛŒ ŲžÛŒØ´ØŽŲˆŲ† شد. 😞 + +/// info + +ØĒØĩØ§ŲˆÛŒØą Ų‚Ø´Ų†Ú¯ Ø§Ø˛ ÚŠØĒØąÛŒŲ†Ø§ ØĒØ§Ų…ŲžØŗŲˆŲ†. 🎨 + +/// + +--- + +ØĒŲˆÛŒ Ø§ÛŒŲ† ØŗŲ†Ø§ØąÛŒŲˆÛŒ Ø¨ØąÚ¯ØąŲ‡Ø§ÛŒ Ų…ŲˆØ§Ø˛ÛŒØŒ ØĒ؈ ÛŒŲ‡ ÚŠØ§Ų…ŲžÛŒŲˆØĒØą / Ø¨ØąŲ†Ø§Ų…Ų‡ 🤖 با Ø¯Ųˆ ØĒا ŲžØąØ¯Ø§Ø˛Ų†Ø¯Ų‡ (ØĒ؈ ؈ ØšØ´Ų‚ØĒ) Ų‡ØŗØĒی، Ų‡Øą Ø¯Ųˆ Ų…Ų†ØĒØ¸Øą 🕙 ؈ ØĒ؈ØŦŲ‡Ø´ŲˆŲ† ⏯ ØąŲˆ Ø¨ØąØ§ÛŒ Ų…Ø¯ØĒ ØˇŲˆŲ„Ø§Ų†ÛŒ "Ø§Ų†ØĒØ¸Ø§Øą ØŦŲ„ŲˆÛŒ ŲžÛŒØ´ØŽŲˆŲ†" 🕙 گذاشØĒŲ†. + +ŲØŗØĒâ€ŒŲŲˆØ¯ 8 ØĒا ŲžØąØ¯Ø§Ø˛Ų†Ø¯Ų‡ (ØĩŲ†Ø¯ŲˆŲ‚Ø¯Ø§Øą/ØĸØ´ŲžØ˛) Ø¯Ø§ØąŲ‡. Ø¯Øą Ø­Ø§Ų„ÛŒ ÚŠŲ‡ ŲØŗØĒâ€ŒŲŲˆØ¯ Ø¨ØąÚ¯ØąŲ‡Ø§ÛŒ Ų‡Ų…â€ŒØ˛Ų…Ø§Ų† شاید ŲŲ‚Øˇ 2 ØĒا داشØĒŲ‡ (ÛŒŲ‡ ØĩŲ†Ø¯ŲˆŲ‚Ø¯Ø§Øą ؈ ÛŒŲ‡ ØĸØ´ŲžØ˛). + +ŲˆŲ„ÛŒ با Ø§ÛŒŲ† Ø­Ø§Ų„ØŒ ØĒØŦØąØ¨Ų‡ Ų†Ų‡Ø§ÛŒÛŒ Ø¨Ų‡ØĒØąÛŒŲ† Ų†ÛŒØŗØĒ. 😞 + +--- + +Ø§ÛŒŲ† Ų…ØšØ§Ø¯Ų„ Ų…ŲˆØ§Ø˛ÛŒ Ø¯Ø§ØŗØĒØ§Ų† Ø¨ØąÚ¯ØąŲ‡Ø§ Ø¨ŲˆØ¯. 🍔 + +Ø¨ØąØ§ÛŒ ÛŒŲ‡ Ų…ØĢØ§Ų„ "ŲˆØ§Ų‚ØšÛŒâ€ŒØĒØą" Ø§Ø˛ Ø˛Ų†Ø¯Ú¯ÛŒØŒ ÛŒŲ‡ Ø¨Ø§Ų†ÚŠ ØąŲˆ ØĒØĩŲˆØą ÚŠŲ†. + +ØĒا Ų‡Ų…ÛŒŲ† Ú†Ų†Ø¯ ŲˆŲ‚ØĒ ŲžÛŒØ´ØŒ بیشØĒØą Ø¨Ø§Ų†ÚŠâ€ŒŲ‡Ø§ Ú†Ų†Ø¯ ØĒا ØĩŲ†Ø¯ŲˆŲ‚Ø¯Ø§Øą 👨‍đŸ’ŧ👨‍đŸ’ŧ👨‍đŸ’ŧ👨‍đŸ’ŧ داشØĒŲ† ؈ ÛŒŲ‡ Øĩ؁ Ø¨Ø˛ØąÚ¯ 🕙🕙🕙🕙🕙🕙🕙🕙. + +Ų‡Ų…Ų‡ ØĩŲ†Ø¯ŲˆŲ‚Ø¯Ø§ØąŲ‡Ø§ ÚŠØ§Øą ØąŲˆ با ÛŒŲ‡ Ų…Ø´ØĒØąÛŒ بؚد Ø§Ø˛ Ø§ŲˆŲ† یڊی 👨‍đŸ’ŧ⏯ Ø§Ų†ØŦØ§Ų… Ų…ÛŒâ€ŒØ¯Ø§Ø¯Ų†. + +؈ باید ØĒŲˆÛŒ Øĩ؁ 🕙 Ų…Ø¯ØĒ Ø˛ÛŒØ§Ø¯ÛŒ Ų…Ų†ØĒØ¸Øą Ø¨Ų…ŲˆŲ†ÛŒ ŲˆÚ¯ØąŲ†Ų‡ Ų†ŲˆØ¨ØĒØĒ ØąŲˆ Ø§Ø˛ Ø¯ØŗØĒ Ų…ÛŒâ€ŒØ¯ÛŒ. + +احØĒŲ…Ø§Ų„Ø§Ų‹ Ų†Ų…ÛŒâ€ŒØŽŲˆØ§ÛŒ ØšØ´Ų‚ØĒ 😍 ØąŲˆ با ØŽŲˆØ¯ØĒ Ø¨Ø¨ØąÛŒ Ø¨Ø§Ų†ÚŠ đŸĻ Ø¨ØąØ§ÛŒ ÚŠØ§ØąØ§ÛŒ ØąŲˆØ˛Ų…ØąŲ‡. + +### Ų†ØĒیØŦŲ‡â€ŒÚ¯ÛŒØąÛŒ Ø¨ØąÚ¯ØąŲ‡Ø§ + +ØĒŲˆÛŒ Ø§ÛŒŲ† ØŗŲ†Ø§ØąÛŒŲˆÛŒ "Ø¨ØąÚ¯ØąŲ‡Ø§ÛŒ ŲØŗØĒâ€ŒŲŲˆØ¯ با ØšØ´Ų‚ØĒ"، Ú†ŲˆŲ† ÚŠŲ„ÛŒ Ø§Ų†ØĒØ¸Ø§Øą 🕙 Ų‡ØŗØĒ، ØŽÛŒŲ„ÛŒ Ų…Ų†ØˇŲ‚ÛŒâ€ŒØĒØąŲ‡ ÚŠŲ‡ ÛŒŲ‡ ØŗÛŒØŗØĒŲ… Ų‡Ų…â€ŒØ˛Ų…Ø§Ų† â¸đŸ”€â¯ داشØĒŲ‡ باشی. + +Ø§ÛŒŲ† Ø¨ØąØ§ÛŒ بیشØĒØą Ø¨ØąŲ†Ø§Ų…Ų‡â€ŒŲ‡Ø§ÛŒ ŲˆØ¨ Ų‡Ų… ØĩØ¯Ų‚ Ų…ÛŒâ€ŒÚŠŲ†Ų‡. + +ØŽÛŒŲ„ÛŒ ØŽÛŒŲ„ÛŒ ÚŠØ§ØąØ¨ØąØŒ ŲˆŲ„ÛŒ ØŗØąŲˆØąØĒ Ų…Ų†ØĒØ¸Øą 🕙 اØĒØĩØ§Ų„ Ų†Ų‡â€ŒÚ†Ų†Ø¯Ø§Ų† ØŽŲˆØ¨Ø´ŲˆŲ† Ų‡ØŗØĒ ØĒا Ø¯ØąØŽŲˆØ§ØŗØĒâ€ŒŲ‡Ø§Ø´ŲˆŲ† ØąŲˆ Ø¨ŲØąØŗØĒŲ†. + +؈ بؚد Ø¯ŲˆØ¨Ø§ØąŲ‡ Ų…Ų†ØĒØ¸Øą 🕙 ÚŠŲ‡ ØŦŲˆØ§Ø¨â€ŒŲ‡Ø§ Ø¨ØąÚ¯ØąØ¯Ų†. + +Ø§ÛŒŲ† "Ø§Ų†ØĒØ¸Ø§Øą" 🕙 ØĒŲˆÛŒ Ų…ÛŒÚŠØąŲˆØĢØ§Ų†ÛŒŲ‡â€ŒŲ‡Ø§ Ø§Ų†Ø¯Ø§Ø˛Ų‡â€ŒÚ¯ÛŒØąÛŒ Ų…ÛŒâ€ŒØ´Ų‡ØŒ ŲˆŲ„ÛŒ با Ø§ÛŒŲ† Ø­Ø§Ų„ØŒ ØŦŲ…ØšØ´ ÚŠŲ‡ Ø¨ÚŠŲ†ÛŒ ØĸØŽØąØ´ ÚŠŲ„ÛŒ Ø§Ų†ØĒØ¸Ø§Øą Ų…ÛŒâ€ŒØ´Ų‡. + +Ø¨ØąØ§ÛŒ Ų‡Ų…ÛŒŲ† Ø§ØŗØĒŲØ§Ø¯Ų‡ Ø§Ø˛ ڊد Ų†Ø§Ų‡Ų…â€ŒØ˛Ų…Ø§Ų† â¸đŸ”€â¯ Ø¨ØąØ§ÛŒ APIŲ‡Ø§ÛŒ ŲˆØ¨ ØŽÛŒŲ„ÛŒ Ų…Ų†ØˇŲ‚ÛŒŲ‡. + +Ø§ÛŒŲ† Ų†ŲˆØš Ų†Ø§Ų‡Ų…â€ŒØ˛Ų…Ø§Ų†ÛŒ Ú†ÛŒØ˛ÛŒŲ‡ ÚŠŲ‡ NodeJS ØąŲˆ Ų…Ø­Ø¨ŲˆØ¨ ÚŠØąØ¯ (Ú¯ØąÚ†Ų‡ NodeJS Ų…ŲˆØ§Ø˛ÛŒ Ų†ÛŒØŗØĒ) ؈ Ų†Ų‚ØˇŲ‡ Ų‚ŲˆØĒ Go Ø¨Ų‡â€ŒØšŲ†ŲˆØ§Ų† ÛŒŲ‡ Ø˛Ø¨ŲˆŲ† Ø¨ØąŲ†Ø§Ų…Ų‡â€ŒŲ†ŲˆÛŒØŗÛŒŲ‡. + +؈ Ų‡Ų…ŲˆŲ† ØŗØˇØ­ ØšŲ…Ų„ÚŠØąØ¯ÛŒ Ų‡ØŗØĒ ÚŠŲ‡ با **FastAPI** Ų…ÛŒâ€ŒÚ¯ÛŒØąÛŒ. + +؈ Ú†ŲˆŲ† Ų…ÛŒâ€ŒØĒŲˆŲ†ÛŒ Ų‡Ų…â€ŒØ˛Ų…Ø§Ų†ÛŒ ؈ Ų…ŲˆØ§Ø˛ÛŒâ€ŒØŗØ§Ø˛ÛŒ ØąŲˆ Ų‡Ų…Ø˛Ų…Ø§Ų† داشØĒŲ‡ باشی، ØšŲ…Ų„ÚŠØąØ¯ Ø¨Ø§Ų„Ø§ØĒØąÛŒ Ø§Ø˛ بیشØĒØą ŲØąÛŒŲ…â€ŒŲˆØąÚŠâ€ŒŲ‡Ø§ÛŒ ØĒØŗØĒâ€ŒØ´Ø¯Ų‡ NodeJS Ų…ÛŒâ€ŒÚ¯ÛŒØąÛŒ ؈ Ų‡Ų…â€ŒØĒØąØ§Ø˛ با Go، ÚŠŲ‡ ÛŒŲ‡ Ø˛Ø¨ŲˆŲ† ÚŠØ§Ų…ŲžØ§ÛŒŲ„â€ŒØ´Ø¯Ų‡ Ų†Ø˛Ø¯ÛŒÚŠ Ø¨Ų‡ C Ų‡ØŗØĒ (Ų‡Ų…Ų‡ Ø§ÛŒŲ†Ø§ Ø¨Ų‡ Ų„ØˇŲ Starlette). + +### Øĸیا Ų‡Ų…â€ŒØ˛Ų…Ø§Ų†ÛŒ Ø§Ø˛ Ų…ŲˆØ§Ø˛ÛŒâ€ŒØŗØ§Ø˛ÛŒ Ø¨Ų‡ØĒØąŲ‡ØŸ + +Ų†Ų‡! Ø§ÛŒŲ† Ų†ØĒیØŦŲ‡ Ø¯Ø§ØŗØĒØ§Ų† Ų†ÛŒØŗØĒ. + +Ų‡Ų…â€ŒØ˛Ų…Ø§Ų†ÛŒ با Ų…ŲˆØ§Ø˛ÛŒâ€ŒØŗØ§Ø˛ÛŒ ŲØąŲ‚ Ø¯Ø§ØąŲ‡. ؈ ØĒŲˆÛŒ **ØŗŲ†Ø§ØąÛŒŲˆŲ‡Ø§ÛŒ ؎اØĩ** ÚŠŲ‡ ÚŠŲ„ÛŒ Ø§Ų†ØĒØ¸Ø§Øą Ø¯Ø§ØąŲ† Ø¨Ų‡ØĒØąŲ‡. Ø¨Ų‡ Ų‡Ų…ÛŒŲ† ØŽØ§ØˇØąØŒ Ų…ØšŲ…ŲˆŲ„Ø§Ų‹ Ø¨ØąØ§ÛŒ ØĒŲˆØŗØšŲ‡ Ø¨ØąŲ†Ø§Ų…Ų‡â€ŒŲ‡Ø§ÛŒ ŲˆØ¨ ØŽÛŒŲ„ÛŒ Ø§Ø˛ Ų…ŲˆØ§Ø˛ÛŒâ€ŒØŗØ§Ø˛ÛŒ Ø¨Ų‡ØĒØąŲ‡. ŲˆŲ„ÛŒ Ų†Ų‡ Ø¨ØąØ§ÛŒ Ų‡Ų…Ų‡â€ŒÚ†ÛŒØ˛. + +Ø¨ØąØ§ÛŒ Ø§ÛŒŲ†ÚŠŲ‡ ÛŒŲ‡ ØĒØšØ§Ø¯Ų„ Ø¨Ø°Ø§ØąÛŒŲ…ØŒ Ø§ÛŒŲ† Ø¯Ø§ØŗØĒØ§Ų† ÚŠŲˆØĒØ§Ų‡ ØąŲˆ ØĒØĩŲˆØą ÚŠŲ†: + +> باید ÛŒŲ‡ ØŽŲˆŲ†Ų‡ Ø¨Ø˛ØąÚ¯ ؈ ÚŠØĢÛŒŲ ØąŲˆ ØĒŲ…ÛŒØ˛ ÚŠŲ†ÛŒ. + +*ØĸØąŲ‡ØŒ ÚŠŲ„ Ø¯Ø§ØŗØĒØ§Ų† Ų‡Ų…ÛŒŲ†Ų‡*. + +--- + +Ų‡ÛŒÚ† Ø§Ų†ØĒØ¸Ø§ØąÛŒ 🕙 Ø§ŲˆŲ†ØŦا Ų†ÛŒØŗØĒ، ŲŲ‚Øˇ ÚŠŲ„ÛŒ ÚŠØ§Øą Ø¨ØąØ§ÛŒ Ø§Ų†ØŦØ§Ų… Ø¯Ø§Ø¯Ų† ØĒŲˆÛŒ ØŦØ§Ų‡Ø§ÛŒ Ų…ØŽØĒ؄؁ ØŽŲˆŲ†Ų‡. + +Ų…ÛŒâ€ŒØĒŲˆŲ†ÛŒ Ų…ØĢŲ„ Ų…ØĢØ§Ų„ Ø¨ØąÚ¯ØąŲ‡Ø§ Ų†ŲˆØ¨ØĒ Ø¨Ø°Ø§ØąÛŒØŒ Ø§ŲˆŲ„ ŲžØ°ÛŒØąØ§ÛŒÛŒØŒ بؚد ØĸØ´ŲžØ˛ØŽŲˆŲ†Ų‡ØŒ ŲˆŲ„ÛŒ Ú†ŲˆŲ† Ų…Ų†ØĒØ¸Øą Ú†ÛŒØ˛ÛŒ Ų†ÛŒØŗØĒی đŸ•™ØŒ ŲŲ‚Øˇ Ø¯Ø§ØąÛŒ ØĒŲ…ÛŒØ˛ Ų…ÛŒâ€ŒÚŠŲ†ÛŒ ؈ ØĒŲ…ÛŒØ˛ Ų…ÛŒâ€ŒÚŠŲ†ÛŒØŒ Ų†ŲˆØ¨ØĒâ€ŒŲ‡Ø§ Ų‡ÛŒÚ† ØĒØŖØĢÛŒØąÛŒ Ų†Ø¯Ø§ØąŲ‡. + +با Ų†ŲˆØ¨ØĒ یا Ø¨Ø¯ŲˆŲ† Ų†ŲˆØ¨ØĒ (Ų‡Ų…â€ŒØ˛Ų…Ø§Ų†ÛŒ) Ų‡Ų…ŲˆŲ† Ų‚Ø¯Øą ØˇŲˆŲ„ Ų…ÛŒâ€ŒÚŠØ´Ų‡ ØĒا ØĒŲ…ŲˆŲ…Ø´ ÚŠŲ†ÛŒ ؈ Ų‡Ų…ŲˆŲ† Ų…Ų‚Ø¯Ø§Øą ÚŠØ§Øą ØąŲˆ ÚŠØąØ¯ÛŒ. + +ŲˆŲ„ÛŒ ØĒŲˆÛŒ Ø§ÛŒŲ† Ų…ŲˆŲ‚ØšÛŒØĒ، Ø§Ú¯Ų‡ بØĒŲˆŲ†ÛŒ Ø§ŲˆŲ† 8 ØĒا ØĩŲ†Ø¯ŲˆŲ‚Ø¯Ø§Øą/ØĸØ´ŲžØ˛/Ø­Ø§Ų„Ø§-ØĒŲ…ÛŒØ˛ÚŠØ§Øą ØąŲˆ Ø¨ÛŒØ§ØąÛŒØŒ ؈ Ų‡Øą ÚŠØ¯ŲˆŲ…Ø´ŲˆŲ† (Ø¨Ų‡â€ŒØšŲ„Ø§ŲˆŲ‡ ØŽŲˆØ¯ØĒ) ÛŒŲ‡ Ų‚ØŗŲ…ØĒ Ø§Ø˛ ØŽŲˆŲ†Ų‡ ØąŲˆ ØĒŲ…ÛŒØ˛ ÚŠŲ†Ų†ØŒ Ų…ÛŒâ€ŒØĒŲˆŲ†ÛŒ Ų‡Ų…Ų‡ ÚŠØ§Øą ØąŲˆ **Ų…ŲˆØ§Ø˛ÛŒ** Ø§Ų†ØŦØ§Ų… بدی، با ÚŠŲ…ÚŠ اØļØ§ŲÛŒØŒ ؈ ØŽÛŒŲ„ÛŒ Ø˛ŲˆØ¯ØĒØą ØĒŲ…ŲˆŲ…Ø´ ÚŠŲ†ÛŒ. + +ØĒŲˆÛŒ Ø§ÛŒŲ† ØŗŲ†Ø§ØąÛŒŲˆØŒ Ų‡Øą ÚŠØ¯ŲˆŲ… Ø§Ø˛ ØĒŲ…ÛŒØ˛ÚŠØ§ØąŲ‡Ø§ (Ø§Ø˛ ØŦŲ…Ų„Ų‡ ØŽŲˆØ¯ØĒ) ÛŒŲ‡ ŲžØąØ¯Ø§Ø˛Ų†Ø¯Ų‡â€ŒØŗØĒ ÚŠŲ‡ ÚŠØ§Øą ØŽŲˆØ¯Ø´ ØąŲˆ Ų…ÛŒâ€ŒÚŠŲ†Ų‡. + +؈ Ú†ŲˆŲ† بیشØĒØą Ø˛Ų…Ø§Ų† اØŦØąØ§ ØĩØąŲ ÚŠØ§Øą ŲˆØ§Ų‚ØšÛŒ Ų…ÛŒâ€ŒØ´Ų‡ (Ø¨Ų‡ ØŦای Ø§Ų†ØĒØ¸Ø§Øą)، ؈ ÚŠØ§Øą ØĒŲˆÛŒ ÚŠØ§Ų…ŲžÛŒŲˆØĒØą با CPU Ø§Ų†ØŦØ§Ų… Ų…ÛŒâ€ŒØ´Ų‡ØŒ Ø¨Ų‡ Ø§ÛŒŲ† Ų…Ø´ÚŠŲ„Ø§ØĒ Ų…ÛŒâ€ŒÚ¯Ų† "CPU bound". + +--- + +Ų…ØĢØ§Ų„â€ŒŲ‡Ø§ÛŒ ØąØ§ÛŒØŦ ØšŲ…Ų„ÛŒØ§ØĒ CPU bound Ú†ÛŒØ˛Ø§ÛŒÛŒ Ų‡ØŗØĒŲ† ÚŠŲ‡ Ų†ÛŒØ§Ø˛ Ø¨Ų‡ ŲžØąØ¯Ø§Ø˛Ø´ ØąÛŒØ§Øļی ŲžÛŒÚ†ÛŒØ¯Ų‡ Ø¯Ø§ØąŲ†. + +Ų…ØĢŲ„Ø§Ų‹: + +* ŲžØąØ¯Ø§Ø˛Ø´ **Øĩدا** یا **ØĒØĩŲˆÛŒØą**. +* **Ø¨ÛŒŲ†Ø§ÛŒÛŒ ÚŠØ§Ų…ŲžÛŒŲˆØĒØąÛŒ**: ÛŒŲ‡ ØĒØĩŲˆÛŒØą Ø§Ø˛ Ų…ÛŒŲ„ÛŒŲˆŲ†â€ŒŲ‡Ø§ ŲžÛŒÚŠØŗŲ„ ØĒØ´ÚŠÛŒŲ„ Ø´Ø¯Ų‡ØŒ Ų‡Øą ŲžÛŒÚŠØŗŲ„ 3 ØĒا Ų…Ų‚Ø¯Ø§Øą / ØąŲ†Ú¯ Ø¯Ø§ØąŲ‡ØŒ ŲžØąØ¯Ø§Ø˛Ø´Ø´ Ų…ØšŲ…ŲˆŲ„Ø§Ų‹ Ų†ÛŒØ§Ø˛ Ø¯Ø§ØąŲ‡ Ú†ÛŒØ˛ÛŒ ØąŲˆ ØąŲˆ Ø§ŲˆŲ† ŲžÛŒÚŠØŗŲ„â€ŒŲ‡Ø§ Ų‡Ų…Ø˛Ų…Ø§Ų† Ø­ØŗØ§Ø¨ ÚŠŲ†ÛŒ. +* **ÛŒØ§Ø¯Ú¯ÛŒØąÛŒ Ų…Ø§Ø´ÛŒŲ†**: Ų…ØšŲ…ŲˆŲ„Ø§Ų‹ ÚŠŲ„ÛŒ ØļØąØ¨ "Ų…Ø§ØĒØąÛŒØŗ" ؈ "Ø¨ØąØ¯Ø§Øą" Ų„Ø§Ø˛Ų… Ø¯Ø§ØąŲ‡. ÛŒŲ‡ ØŦØ¯ŲˆŲ„ Ø¨Ø˛ØąÚ¯ ŲžØą Ø§Ø˛ ؚدد ØąŲˆ ØĒØĩŲˆØą ÚŠŲ† ÚŠŲ‡ Ų‡Ų…Ų‡â€ŒØ´ŲˆŲ† ØąŲˆ Ų‡Ų…Ø˛Ų…Ø§Ų† ØļØąØ¨ Ų…ÛŒâ€ŒÚŠŲ†ÛŒ. +* **ÛŒØ§Ø¯Ú¯ÛŒØąÛŒ ØšŲ…ÛŒŲ‚**: Ø§ÛŒŲ† ÛŒŲ‡ Ø˛ÛŒØąØ´Ø§ØŽŲ‡ Ø§Ø˛ ÛŒØ§Ø¯Ú¯ÛŒØąÛŒ Ų…Ø§Ø´ÛŒŲ†Ų‡ØŒ ŲžØŗ Ų‡Ų…ŲˆŲ† Ų‚ØļÛŒŲ‡ ØĩØ¯Ų‚ Ų…ÛŒâ€ŒÚŠŲ†Ų‡. ŲŲ‚Øˇ Ø§ÛŒŲ† ÚŠŲ‡ ÛŒŲ‡ ØŦØ¯ŲˆŲ„ ؚدد Ø¨ØąØ§ÛŒ ØļØąØ¨ ÚŠØąØ¯Ų† Ų†ÛŒØŗØĒ، Ø¨Ų„ÚŠŲ‡ ÛŒŲ‡ Ų…ØŦŲ…ŲˆØšŲ‡ Ø¨Ø˛ØąÚ¯ Ø§Ø˛ Ø§ŲˆŲ†Ø§ Ų‡ØŗØĒ، ؈ ØĒŲˆÛŒ ØŽÛŒŲ„ÛŒ Ų…ŲˆØ§ØąØ¯ Ø§Ø˛ ÛŒŲ‡ ŲžØąØ¯Ø§Ø˛Ų†Ø¯Ų‡ ؎اØĩ Ø¨ØąØ§ÛŒ ØŗØ§ØŽØĒ ؈ / یا Ø§ØŗØĒŲØ§Ø¯Ų‡ Ø§Ø˛ Ø§ÛŒŲ† Ų…Ø¯Ų„â€ŒŲ‡Ø§ Ø§ØŗØĒŲØ§Ø¯Ų‡ Ų…ÛŒâ€ŒÚŠŲ†ÛŒ. + +### Ų‡Ų…â€ŒØ˛Ų…Ø§Ų†ÛŒ + Ų…ŲˆØ§Ø˛ÛŒâ€ŒØŗØ§Ø˛ÛŒ: ŲˆØ¨ + ÛŒØ§Ø¯Ú¯ÛŒØąÛŒ Ų…Ø§Ø´ÛŒŲ† + +با **FastAPI** Ų…ÛŒâ€ŒØĒŲˆŲ†ÛŒ Ø§Ø˛ Ų‡Ų…â€ŒØ˛Ų…Ø§Ų†ÛŒ ÚŠŲ‡ Ø¨ØąØ§ÛŒ ØĒŲˆØŗØšŲ‡ ŲˆØ¨ ØŽÛŒŲ„ÛŒ ØąØ§ÛŒØŦŲ‡ (Ų‡Ų…ŲˆŲ† ØŦذابیØĒ اØĩŲ„ÛŒ NodeJS) Ø§ØŗØĒŲØ§Ø¯Ų‡ ÚŠŲ†ÛŒ. + +ŲˆŲ„ÛŒ Ų…ÛŒâ€ŒØĒŲˆŲ†ÛŒ Ø§Ø˛ ŲŲˆØ§ÛŒØ¯ Ų…ŲˆØ§Ø˛ÛŒâ€ŒØŗØ§Ø˛ÛŒ ؈ Ú†Ų†Ø¯ŲžØąØ¯Ø§Ø˛Ø´ÛŒ (اØŦØąØ§ÛŒ Ú†Ų†Ø¯ ŲžØąŲˆØŗŲ‡ Ø¨Ų‡â€ŒØĩŲˆØąØĒ Ų…ŲˆØ§Ø˛ÛŒ) Ø¨ØąØ§ÛŒ ÚŠØ§ØąØ§ÛŒ **CPU bound** Ų…ØĢŲ„ ØŗÛŒØŗØĒŲ…â€ŒŲ‡Ø§ÛŒ ÛŒØ§Ø¯Ú¯ÛŒØąÛŒ Ų…Ø§Ø´ÛŒŲ† Ų‡Ų… Ø¨Ų‡ØąŲ‡ Ø¨Ø¨ØąÛŒ. + +Ø§ÛŒŲ†ØŒ Ø¨Ų‡â€ŒØšŲ„Ø§ŲˆŲ‡ Ø§ÛŒŲ† ŲˆØ§Ų‚ØšÛŒØĒ ØŗØ§Ø¯Ų‡ ÚŠŲ‡ ŲžØ§ÛŒØĒŲˆŲ† Ø˛Ø¨ŲˆŲ† اØĩŲ„ÛŒ Ø¨ØąØ§ÛŒ **ØšŲ„Ų… Ø¯Ø§Ø¯Ų‡**، ÛŒØ§Ø¯Ú¯ÛŒØąÛŒ Ų…Ø§Ø´ÛŒŲ† ؈ Ø¨Ų‡â€ŒØŽØĩ؈Øĩ ÛŒØ§Ø¯Ú¯ÛŒØąÛŒ ØšŲ…ÛŒŲ‚Ų‡ØŒ باؚØĢ Ų…ÛŒâ€ŒØ´Ų‡ FastAPI ÛŒŲ‡ Ø§Ų†ØĒ؎اب ØŽÛŒŲ„ÛŒ ØŽŲˆØ¨ Ø¨ØąØ§ÛŒ APIŲ‡Ø§ ؈ Ø¨ØąŲ†Ø§Ų…Ų‡â€ŒŲ‡Ø§ÛŒ ŲˆØ¨ ØšŲ„Ų… Ø¯Ø§Ø¯Ų‡ / ÛŒØ§Ø¯Ú¯ÛŒØąÛŒ Ų…Ø§Ø´ÛŒŲ† Ø¨Ø§Ø´Ų‡ (Ø¨ÛŒŲ† ØŽÛŒŲ„ÛŒ Ú†ÛŒØ˛Ø§ÛŒ Ø¯ÛŒÚ¯Ų‡). + +Ø¨ØąØ§ÛŒ Ø¯ÛŒØ¯Ų† Ø§ÛŒŲ†ÚŠŲ‡ Ú†ØˇŲˆØą ØĒŲˆÛŒ Ų…Ø­ÛŒØˇ ŲˆØ§Ų‚ØšÛŒ Ø¨Ų‡ Ø§ÛŒŲ† Ų…ŲˆØ§Ø˛ÛŒâ€ŒØŗØ§Ø˛ÛŒ Ø¨ØąØŗÛŒØŒ ب؎ش [Ø§ØŗØĒŲ‚ØąØ§Øą](deployment/index.md){.internal-link target=_blank} ØąŲˆ Ø¨Ø¨ÛŒŲ†. + +## `async` ؈ `await` + +Ų†ØŗØŽŲ‡â€ŒŲ‡Ø§ÛŒ Ų…Ø¯ØąŲ† ŲžØ§ÛŒØĒŲˆŲ† ÛŒŲ‡ ØąØ§Ų‡ ØŽÛŒŲ„ÛŒ ØŗØ§Ø¯Ų‡ ؈ Ų‚Ø§Ø¨Ų„â€ŒŲŲ‡Ų… Ø¨ØąØ§ÛŒ ØĒØšØąÛŒŲ ڊد Ų†Ø§Ų‡Ų…â€ŒØ˛Ų…Ø§Ų† Ø¯Ø§ØąŲ†. Ø§ÛŒŲ† باؚØĢ Ų…ÛŒâ€ŒØ´Ų‡ Ų…ØĢŲ„ ڊد "ØĒØąØĒیبی" Ų…ØšŲ…ŲˆŲ„ÛŒ Ø¨Ų‡ Ų†Ø¸Øą بیاد ؈ ØĒŲˆÛŒ Ų„Ø­Ø¸Ų‡â€ŒŲ‡Ø§ÛŒ Ø¯ØąØŗØĒ "Ø§Ų†ØĒØ¸Ø§Øą" ØąŲˆ Ø¨ØąØ§ØĒ Ø§Ų†ØŦØ§Ų… Ø¨Ø¯Ų‡. + +ŲˆŲ‚ØĒی ÛŒŲ‡ ØšŲ…Ų„ÛŒØ§ØĒی Ų‡ØŗØĒ ÚŠŲ‡ Ų‚Ø¨Ų„ Ø§Ø˛ Ø¯Ø§Ø¯Ų† Ų†ØĒیØŦŲ‡â€ŒŲ‡Ø§ Ų†ÛŒØ§Ø˛ Ø¨Ų‡ Ø§Ų†ØĒØ¸Ø§Øą Ø¯Ø§ØąŲ‡ ؈ Ø§Ø˛ Ø§ÛŒŲ† Ų‚Ø§Ø¨Ų„ÛŒØĒâ€ŒŲ‡Ø§ÛŒ ØŦدید ŲžØ§ÛŒØĒŲˆŲ† ŲžØ´ØĒÛŒØ¨Ø§Ų†ÛŒ Ų…ÛŒâ€ŒÚŠŲ†Ų‡ØŒ Ų…ÛŒâ€ŒØĒŲˆŲ†ÛŒ Ø§ÛŒŲ†ØŦŲˆØąÛŒ ÚŠØ¯Ų†ŲˆÛŒØŗÛŒØ´ ÚŠŲ†ÛŒ: + +```Python +burgers = await get_burgers(2) +``` + +Ų†ÚŠØĒŲ‡ ÚŠŲ„ÛŒØ¯ÛŒ Ø§ÛŒŲ†ØŦا `await` Ų‡ØŗØĒ. Ø¨Ų‡ ŲžØ§ÛŒØĒŲˆŲ† Ų…ÛŒâ€ŒÚ¯Ų‡ ÚŠŲ‡ باید ⏸ Ų…Ų†ØĒØ¸Øą Ø¨Ų…ŲˆŲ†Ų‡ ØĒا `get_burgers(2)` ÚŠØ§ØąØ´ 🕙 ØĒŲ…ŲˆŲ… Ø¨Ø´Ų‡ Ų‚Ø¨Ų„ Ø§Ø˛ Ø§ÛŒŲ†ÚŠŲ‡ Ų†ØĒیØŦŲ‡â€ŒŲ‡Ø§ ØąŲˆ ØĒŲˆÛŒ `burgers` Ø°ØŽÛŒØąŲ‡ ÚŠŲ†Ų‡. با Ø§ÛŒŲ†ØŒ ŲžØ§ÛŒØĒŲˆŲ† Ų…ÛŒâ€ŒØ¯ŲˆŲ†Ų‡ ÚŠŲ‡ Ų…ÛŒâ€ŒØĒŲˆŲ†Ų‡ Ø¨ØąŲ‡ ÛŒŲ‡ ÚŠØ§Øą Ø¯ÛŒÚ¯Ų‡ 🔀 ⏯ ØĒŲˆÛŒ Ø§ÛŒŲ† Ų…Ø¯ØĒ Ø¨ÚŠŲ†Ų‡ (Ų…ØĢŲ„ Ú¯ØąŲØĒŲ† ÛŒŲ‡ Ø¯ØąØŽŲˆØ§ØŗØĒ Ø¯ÛŒÚ¯Ų‡). + +Ø¨ØąØ§ÛŒ Ø§ÛŒŲ†ÚŠŲ‡ `await` ÚŠØ§Øą ÚŠŲ†Ų‡ØŒ باید ØĒŲˆÛŒ ÛŒŲ‡ ØĒابؚ Ø¨Ø§Ø´Ų‡ ÚŠŲ‡ Ø§Ø˛ Ø§ÛŒŲ† Ų†Ø§Ų‡Ų…â€ŒØ˛Ų…Ø§Ų†ÛŒ ŲžØ´ØĒÛŒØ¨Ø§Ų†ÛŒ ÚŠŲ†Ų‡. Ø¨ØąØ§ÛŒ Ø§ÛŒŲ† ÚŠØ§ØąØŒ ŲŲ‚Øˇ با `async def` ØĒØšØąÛŒŲØ´ Ų…ÛŒâ€ŒÚŠŲ†ÛŒ: + +```Python hl_lines="1" +async def get_burgers(number: int): + # ÛŒŲ‡ ØŗØąÛŒ ÚŠØ§Øą Ų†Ø§Ų‡Ų…â€ŒØ˛Ų…Ø§Ų† Ø¨ØąØ§ÛŒ ØŗØ§ØŽØĒŲ† Ø¨ØąÚ¯ØąŲ‡Ø§ Ø§Ų†ØŦØ§Ų… Ø¨Ø¯Ų‡ + return burgers +``` + +...Ø¨Ų‡ ØŦای `def`: + +```Python hl_lines="2" +# Ø§ÛŒŲ† Ų†Ø§Ų‡Ų…â€ŒØ˛Ų…Ø§Ų† Ų†ÛŒØŗØĒ +def get_sequential_burgers(number: int): + # ÛŒŲ‡ ØŗØąÛŒ ÚŠØ§Øą ØĒØąØĒیبی Ø¨ØąØ§ÛŒ ØŗØ§ØŽØĒŲ† Ø¨ØąÚ¯ØąŲ‡Ø§ Ø§Ų†ØŦØ§Ų… Ø¨Ø¯Ų‡ + return burgers +``` + +با `async def`، ŲžØ§ÛŒØĒŲˆŲ† Ų…ÛŒâ€ŒØ¯ŲˆŲ†Ų‡ ÚŠŲ‡ ØĒŲˆÛŒ Ø§ŲˆŲ† ØĒابؚ باید Ø­ŲˆØ§ØŗØ´ Ø¨Ų‡ ØšØ¨Ø§ØąØĒâ€ŒŲ‡Ø§ÛŒ `await` Ø¨Ø§Ø´Ų‡ØŒ ؈ Ų…ÛŒâ€ŒØĒŲˆŲ†Ų‡ اØŦØąØ§ÛŒ Ø§ŲˆŲ† ØĒابؚ ØąŲˆ "Ų…ŲˆŲ‚ØĒØ§Ų‹ Ų…ØĒŲˆŲ‚Ų" ⏸ ÚŠŲ†Ų‡ ؈ Ø¨ØąŲ‡ ÛŒŲ‡ ÚŠØ§Øą Ø¯ÛŒÚ¯Ų‡ 🔀 Ų‚Ø¨Ų„ Ø§Ø˛ Ø¨ØąÚ¯Ø´ØĒŲ† Ø¨ÚŠŲ†Ų‡. + +ŲˆŲ‚ØĒی Ų…ÛŒâ€ŒØŽŲˆØ§ÛŒ ÛŒŲ‡ ØĒابؚ `async def` ØąŲˆ Øĩدا ÚŠŲ†ÛŒØŒ باید "Ų…Ų†ØĒØ¸ØąØ´" Ø¨Ų…ŲˆŲ†ÛŒ. ŲžØŗ Ø§ÛŒŲ† ÚŠØ§Øą Ų†Ų…ÛŒâ€ŒÚŠŲ†Ų‡: + +```Python +# Ø§ÛŒŲ† ÚŠØ§Øą Ų†Ų…ÛŒâ€ŒÚŠŲ†Ų‡ØŒ Ú†ŲˆŲ† get_burgers با async def ØĒØšØąÛŒŲ Ø´Ø¯Ų‡ +burgers = get_burgers(2) +``` + +--- + +ŲžØŗØŒ Ø§Ú¯Ų‡ Ø§Ø˛ ÛŒŲ‡ ÚŠØĒØ§Ø¨ØŽŲˆŲ†Ų‡ Ø§ØŗØĒŲØ§Ø¯Ų‡ Ų…ÛŒâ€ŒÚŠŲ†ÛŒ ÚŠŲ‡ Ø¨Ų‡ØĒ Ų…ÛŒâ€ŒÚ¯Ų‡ Ų…ÛŒâ€ŒØĒŲˆŲ†ÛŒ با `await` Øĩداش ÚŠŲ†ÛŒØŒ باید *ØĒŲˆØ§Ø¨Øš ØšŲ…Ų„ÛŒØ§ØĒ Ų…ØŗÛŒØąØĒ* ÚŠŲ‡ Ø§Ø˛Ø´ Ø§ØŗØĒŲØ§Ø¯Ų‡ Ų…ÛŒâ€ŒÚŠŲ†Ų† ØąŲˆ با `async def` Ø¨ØŗØ§Ø˛ÛŒØŒ Ų…ØĢŲ„: + +```Python hl_lines="2-3" +@app.get('/burgers') +async def read_burgers(): + burgers = await get_burgers(2) + return burgers +``` + +### ØŦØ˛ØĻیاØĒ ŲŲ†ÛŒâ€ŒØĒØą + +شاید Ų…ØĒ؈ØŦŲ‡ Ø´Ø¯Ų‡ باشی ÚŠŲ‡ `await` ŲŲ‚Øˇ ØĒŲˆÛŒ ØĒŲˆØ§Ø¨ØšÛŒ ÚŠŲ‡ با `async def` ØĒØšØąÛŒŲ Ø´Ø¯Ų† Ų…ÛŒâ€ŒØĒŲˆŲ†Ų‡ Ø§ØŗØĒŲØ§Ø¯Ų‡ Ø¨Ø´Ų‡. + +ŲˆŲ„ÛŒ Ø¯Øą ØšÛŒŲ† Ø­Ø§Ų„ØŒ ØĒŲˆØ§Ø¨ØšÛŒ ÚŠŲ‡ با `async def` ØĒØšØąÛŒŲ Ø´Ø¯Ų† باید "Ų…Ų†ØĒØ¸Øą"Ø´ŲˆŲ† Ø¨Ų…ŲˆŲ†ÛŒ. ŲžØŗ ØĒŲˆØ§Ø¨Øš با `async def` ŲŲ‚Øˇ ØĒŲˆÛŒ ØĒŲˆØ§Ø¨ØšÛŒ ÚŠŲ‡ با `async def` ØĒØšØąÛŒŲ Ø´Ø¯Ų† Ų…ÛŒâ€ŒØĒŲˆŲ†Ų† Øĩدا Ø˛Ø¯Ų‡ Ø¨Ø´Ų†. + +Ø­Ø§Ų„Ø§ØŒ Ų‚ØļÛŒŲ‡ Ų…ØąØē ؈ ØĒØŽŲ…â€ŒŲ…ØąØē Ú†ÛŒŲ‡ØŒ Ú†ØˇŲˆØą Ø§ŲˆŲ„ÛŒŲ† ØĒابؚ `async` ØąŲˆ Øĩدا Ų…ÛŒâ€ŒÚŠŲ†ÛŒØŸ + +Ø§Ú¯Ų‡ با **FastAPI** ÚŠØ§Øą Ų…ÛŒâ€ŒÚŠŲ†ÛŒØŒ Ų„Ø§Ø˛Ų… Ų†ÛŒØŗØĒ Ų†Ú¯ØąØ§Ų† Ø§ÛŒŲ† باشی، Ú†ŲˆŲ† Ø§ŲˆŲ† "Ø§ŲˆŲ„ÛŒŲ†" ØĒابؚ، *ØĒابؚ ØšŲ…Ų„ÛŒØ§ØĒ Ų…ØŗÛŒØąØĒ* Ų‡ØŗØĒ، ؈ FastAPI Ų…ÛŒâ€ŒØ¯ŲˆŲ†Ų‡ Ú†ØˇŲˆØą ÚŠØ§Øą Ø¯ØąØŗØĒ ØąŲˆ Ø¨ÚŠŲ†Ų‡. + +ŲˆŲ„ÛŒ Ø§Ú¯Ų‡ Ø¨ØŽŲˆØ§ÛŒ Ø¨Ø¯ŲˆŲ† FastAPI Ø§Ø˛ `async` / `await` Ø§ØŗØĒŲØ§Ø¯Ų‡ ÚŠŲ†ÛŒØŒ Ø§ÛŒŲ†Ų… Ų…Ų…ÚŠŲ†Ų‡. + +### ڊد Ų†Ø§Ų‡Ų…â€ŒØ˛Ų…Ø§Ų† ØŽŲˆØ¯ØĒ ØąŲˆ Ø¨Ų†ŲˆÛŒØŗ + +Starlette (؈ **FastAPI**) Ø¨Øą ŲžØ§ÛŒŲ‡ AnyIO Ų‡ØŗØĒŲ†ØŒ ÚŠŲ‡ باؚØĢ Ų…ÛŒâ€ŒØ´Ų‡ با ÚŠØĒØ§Ø¨ØŽŲˆŲ†Ų‡ Ø§ØŗØĒØ§Ų†Ø¯Ø§ØąØ¯ ŲžØ§ÛŒØĒŲˆŲ† asyncio ؈ Trio ØŗØ§Ø˛Ú¯Ø§Øą Ø¨Ø§Ø´Ų‡. + +Ø¨Ų‡â€ŒØŽØĩ؈Øĩ، Ų…ÛŒâ€ŒØĒŲˆŲ†ÛŒ Ų…ØŗØĒŲ‚ÛŒŲ…Ø§Ų‹ Ø§Ø˛ AnyIO Ø¨ØąØ§ÛŒ Ų…ŲˆØ§ØąØ¯ Ø§ØŗØĒŲØ§Ø¯Ų‡ ŲžÛŒØ´ØąŲØĒŲ‡ Ų‡Ų…â€ŒØ˛Ų…Ø§Ų†ÛŒ ÚŠŲ‡ Ų†ÛŒØ§Ø˛ Ø¨Ų‡ Ø§Ų„Ú¯ŲˆŲ‡Ø§ÛŒ ŲžÛŒÚ†ÛŒØ¯Ų‡â€ŒØĒØą ØĒŲˆÛŒ ڊد ØŽŲˆØ¯ØĒ Ø¯Ø§ØąŲ† Ø§ØŗØĒŲØ§Ø¯Ų‡ ÚŠŲ†ÛŒ. + +؈ Ø­ØĒی Ø§Ú¯Ų‡ Ø§Ø˛ FastAPI Ø§ØŗØĒŲØ§Ø¯Ų‡ Ų†ÚŠŲ†ÛŒØŒ Ų…ÛŒâ€ŒØĒŲˆŲ†ÛŒ Ø¨ØąŲ†Ø§Ų…Ų‡â€ŒŲ‡Ø§ÛŒ Ų†Ø§Ų‡Ų…â€ŒØ˛Ų…Ø§Ų† ØŽŲˆØ¯ØĒ ØąŲˆ با AnyIO Ø¨Ų†ŲˆÛŒØŗÛŒ ØĒا ØŽÛŒŲ„ÛŒ ØŗØ§Ø˛Ú¯Ø§Øą Ø¨Ø§Ø´Ų‡ ؈ ŲŲˆØ§ÛŒØ¯Ø´ ØąŲˆ Ø¨Ú¯ÛŒØąÛŒ (Ų…ØĢŲ„ *Ų‡Ų…â€ŒØ˛Ų…Ø§Ų†ÛŒ ØŗØ§ØŽØĒØ§ØąÛŒØ§ŲØĒŲ‡*). + +Ų…Ų† ÛŒŲ‡ ÚŠØĒØ§Ø¨ØŽŲˆŲ†Ų‡ Ø¯ÛŒÚ¯Ų‡ ØąŲˆÛŒ AnyIO ØŗØ§ØŽØĒŲ…ØŒ ÛŒŲ‡ Ų„Ø§ÛŒŲ‡ Ų†Ø§Ø˛ÚŠ ØąŲˆØ´ØŒ ØĒا ÛŒŲ‡ ÚŠŲ… annotationŲ‡Ø§ÛŒ Ų†ŲˆØš ØąŲˆ Ø¨Ų‡ØĒØą ÚŠŲ†Ų… ؈ **ØĒÚŠŲ…ÛŒŲ„ ØŽŲˆØ¯ÚŠØ§Øą** Ø¨Ų‡ØĒØąØŒ **ØŽØˇØ§Ų‡Ø§ÛŒ Ø¯ØąŲˆŲ†â€ŒØŽØˇÛŒ** ؈ ØēÛŒØąŲ‡ Ø¨Ú¯ÛŒØąŲ…. ÛŒŲ‡ Ų…Ų‚Ø¯Ų…Ų‡ ؈ ØĸŲ…ŲˆØ˛Ø´ ØŗØ§Ø¯Ų‡ Ų‡Ų… Ø¯Ø§ØąŲ‡ ÚŠŲ‡ Ø¨Ų‡ØĒ ÚŠŲ…ÚŠ Ų…ÛŒâ€ŒÚŠŲ†Ų‡ **Ø¨ŲŲ‡Ų…ÛŒ** ؈ **ڊد Ų†Ø§Ų‡Ų…â€ŒØ˛Ų…Ø§Ų† ØŽŲˆØ¯ØĒ ØąŲˆ Ø¨Ų†ŲˆÛŒØŗÛŒ**: Asyncer. Ø§Ú¯Ų‡ Ø¨ØŽŲˆØ§ÛŒ **ڊد Ų†Ø§Ų‡Ų…â€ŒØ˛Ų…Ø§Ų† ØąŲˆ با ڊد Ų…ØšŲ…ŲˆŲ„ÛŒ** (Ø¨Ų„Ø§ÚŠâ€ŒÚŠŲ†Ų†Ø¯Ų‡/Ų‡Ų…â€ŒØ˛Ų…Ø§Ų†) ØĒØąÚŠÛŒØ¨ ÚŠŲ†ÛŒ ØŽÛŒŲ„ÛŒ Ø¨Ų‡â€ŒØ¯ØąØ¯ØĒ Ų…ÛŒâ€ŒØŽŲˆØąŲ‡. + +### Ø´ÚŠŲ„â€ŒŲ‡Ø§ÛŒ Ø¯ÛŒÚ¯Ų‡ ڊد Ų†Ø§Ų‡Ų…â€ŒØ˛Ų…Ø§Ų† + +Ø§ÛŒŲ† ØŗØ¨ÚŠ Ø§ØŗØĒŲØ§Ø¯Ų‡ Ø§Ø˛ `async` ؈ `await` ØĒŲˆÛŒ Ø˛Ø¨ŲˆŲ† Ų†ØŗØ¨ØĒØ§Ų‹ ØŦØ¯ÛŒØ¯Ų‡. + +ŲˆŲ„ÛŒ ÚŠØ§Øą با ڊد Ų†Ø§Ų‡Ų…â€ŒØ˛Ų…Ø§Ų† ØąŲˆ ØŽÛŒŲ„ÛŒ ØŗØ§Ø¯Ų‡â€ŒØĒØą Ų…ÛŒâ€ŒÚŠŲ†Ų‡. + +Ų‡Ų…ÛŒŲ† ØŗÛŒŲ†ØĒÚŠØŗ (یا ØĒŲ‚ØąÛŒØ¨Ø§Ų‹ ÛŒÚŠØŗØ§Ų†) Ø§ØŽÛŒØąØ§Ų‹ ØĒŲˆÛŒ Ų†ØŗØŽŲ‡â€ŒŲ‡Ø§ÛŒ Ų…Ø¯ØąŲ† ØŦØ§ŲˆØ§Ø§ØŗÚŠØąÛŒŲžØĒ (ØĒŲˆÛŒ Ų…ØąŲˆØąÚ¯Øą ؈ NodeJS) Ų‡Ų… اØļØ§ŲŲ‡ Ø´Ø¯Ų‡. + +ŲˆŲ„ÛŒ Ų‚Ø¨Ų„ Ø§Ø˛ Ø§ŲˆŲ†ØŒ Ų…Ø¯ÛŒØąÛŒØĒ ڊد Ų†Ø§Ų‡Ų…â€ŒØ˛Ų…Ø§Ų† ØŽÛŒŲ„ÛŒ ŲžÛŒÚ†ÛŒØ¯Ų‡â€ŒØĒØą ؈ ØŗØŽØĒ‌ØĒØą Ø¨ŲˆØ¯. + +ØĒŲˆÛŒ Ų†ØŗØŽŲ‡â€ŒŲ‡Ø§ÛŒ Ų‚Ø¨Ų„ÛŒ ŲžØ§ÛŒØĒŲˆŲ†ØŒ Ų…ÛŒâ€ŒØĒŲˆŲ†ØŗØĒی Ø§Ø˛ Ų†ØŽâ€ŒŲ‡Ø§ یا Gevent Ø§ØŗØĒŲØ§Ø¯Ų‡ ÚŠŲ†ÛŒ. ŲˆŲ„ÛŒ ڊد ØŽÛŒŲ„ÛŒ ŲžÛŒÚ†ÛŒØ¯Ų‡â€ŒØĒØą Ų…ÛŒâ€ŒØ´Ų‡ Ø¨ØąØ§ÛŒ ŲŲ‡Ų…ÛŒØ¯Ų†ØŒ دیباگ ÚŠØąØ¯Ų† ؈ ŲÚŠØą ÚŠØąØ¯Ų† Ø¨Ų‡Ø´. + +ØĒŲˆÛŒ Ų†ØŗØŽŲ‡â€ŒŲ‡Ø§ÛŒ Ų‚Ø¨Ų„ÛŒ NodeJS / ØŦØ§ŲˆØ§Ø§ØŗÚŠØąÛŒŲžØĒ Ų…ØąŲˆØąÚ¯ØąØŒ Ø§Ø˛ "ÚŠØ§Ų„â€ŒØ¨ÚŠâ€ŒŲ‡Ø§" Ø§ØŗØĒŲØ§Ø¯Ų‡ Ų…ÛŒâ€ŒÚŠØąØ¯ÛŒ. ÚŠŲ‡ Ų…ÛŒâ€ŒØąØŗÛŒØ¯ Ø¨Ų‡ ØŦŲ‡Ø§Ų† ÚŠØ§Ų„â€ŒØ¨ÚŠâ€ŒŲ‡Ø§. + +## ÚŠØąŲˆØĒÛŒŲ†â€ŒŲ‡Ø§ + +**ÚŠØąŲˆØĒÛŒŲ†** ŲŲ‚Øˇ ÛŒŲ‡ اØĩØˇŲ„Ø§Ø­ ØŽÛŒŲ„ÛŒ شیڊ Ø¨ØąØ§ÛŒ Ú†ÛŒØ˛ÛŒŲ‡ ÚŠŲ‡ ÛŒŲ‡ ØĒابؚ `async def` Ø¨ØąŲ…ÛŒâ€ŒÚ¯ØąØ¯ŲˆŲ†Ų‡. ŲžØ§ÛŒØĒŲˆŲ† Ų…ÛŒâ€ŒØ¯ŲˆŲ†Ų‡ ÚŠŲ‡ Ø§ÛŒŲ† ÛŒŲ‡ Ú†ÛŒØ˛ÛŒ Ų…ØĢŲ„ ØĒابؚ Ų‡ØŗØĒ، Ų…ÛŒâ€ŒØĒŲˆŲ†Ų‡ Ø´ØąŲˆØš Ø¨Ø´Ų‡ ؈ ÛŒŲ‡ ØŦایی ØĒŲ…ŲˆŲ… Ø¨Ø´Ų‡ØŒ ŲˆŲ„ÛŒ Ų…Ų…ÚŠŲ†Ų‡ Ø¯Ø§ØŽŲ„Ø´ Ų‡Ų… Ų…ŲˆŲ‚Ų ⏸ Ø¨Ø´Ų‡ØŒ Ų‡Øą ŲˆŲ‚ØĒ ÛŒŲ‡ `await` ØĒŲˆØ´ Ø¨Ø§Ø´Ų‡. + +ŲˆŲ„ÛŒ Ų‡Ų…Ų‡ Ø§ÛŒŲ† Ų‚Ø§Ø¨Ų„ÛŒØĒ Ø§ØŗØĒŲØ§Ø¯Ų‡ Ø§Ø˛ ڊد Ų†Ø§Ų‡Ų…â€ŒØ˛Ų…Ø§Ų† با `async` ؈ `await` ØŽÛŒŲ„ÛŒ ŲˆŲ‚ØĒا ØŽŲ„Ø§ØĩŲ‡ Ų…ÛŒâ€ŒØ´Ų‡ Ø¨Ų‡ Ø§ØŗØĒŲØ§Ø¯Ų‡ Ø§Ø˛ "ÚŠØąŲˆØĒÛŒŲ†â€ŒŲ‡Ø§". Ø§ÛŒŲ† Ų‚Ø§Ø¨Ų„ Ų…Ų‚Ø§ÛŒØŗŲ‡ با ŲˆÛŒÚ˜Ú¯ÛŒ اØĩŲ„ÛŒ Go، ÛŒØšŲ†ÛŒ "GoroutineŲ‡Ø§" Ų‡ØŗØĒ. + +## Ų†ØĒیØŦŲ‡â€ŒÚ¯ÛŒØąÛŒ + +بیاید Ų‡Ų…ŲˆŲ† ØŦŲ…Ų„Ų‡ Ø§Ø˛ Ø¨Ø§Ų„Ø§ ØąŲˆ Ø¨Ø¨ÛŒŲ†ÛŒŲ…: + +> Ų†ØŗØŽŲ‡â€ŒŲ‡Ø§ÛŒ Ų…Ø¯ØąŲ† ŲžØ§ÛŒØĒŲˆŲ† Ø§Ø˛ **"ڊد Ų†Ø§Ų‡Ų…â€ŒØ˛Ų…Ø§Ų†"** با Ú†ÛŒØ˛ÛŒ ÚŠŲ‡ Ø¨Ų‡Ø´ **"ÚŠØąŲˆØĒÛŒŲ†"** Ų…ÛŒâ€ŒÚ¯Ų† ŲžØ´ØĒÛŒØ¨Ø§Ų†ÛŒ Ų…ÛŒâ€ŒÚŠŲ†Ų†ØŒ با ØŗÛŒŲ†ØĒÚŠØŗ **`async` ؈ `await`**. + +Ø­Ø§Ų„Ø§ باید بیشØĒØą Ø¨ØąØ§ØĒ Ų…ØšŲ†ÛŒ Ø¨Ø¯Ų‡. ✨ + +Ų‡Ų…Ų‡ Ø§ÛŒŲ†Ø§ Ú†ÛŒØ˛ÛŒŲ‡ ÚŠŲ‡ Ø¨Ų‡ FastAPI (Ø§Ø˛ ØˇØąÛŒŲ‚ Starlette) Ų‚Ø¯ØąØĒ Ų…ÛŒâ€ŒØ¯Ų‡ ؈ باؚØĢ Ų…ÛŒâ€ŒØ´Ų‡ ØšŲ…Ų„ÚŠØąØ¯ Ú†Ø´Ų…Ú¯ÛŒØąÛŒ داشØĒŲ‡ Ø¨Ø§Ø´Ų‡. + +## ØŦØ˛ØĻیاØĒ ØŽÛŒŲ„ÛŒ ŲŲ†ÛŒ + +/// warning + +احØĒŲ…Ø§Ų„Ø§Ų‹ Ų…ÛŒâ€ŒØĒŲˆŲ†ÛŒ Ø§ÛŒŲ†Ųˆ ØąØ¯ ÚŠŲ†ÛŒ. + +Ø§ÛŒŲ†Ø§ ØŦØ˛ØĻیاØĒ ØŽÛŒŲ„ÛŒ ŲŲ†ÛŒ Ø§Ø˛ Ų†Ø­ŲˆŲ‡ ÚŠØ§Øą **FastAPI** Ø˛ÛŒØą ŲžŲˆØŗØĒŲ‡â€ŒØŗØĒ. + +Ø§Ú¯Ų‡ ÛŒŲ‡ ÚŠŲ… Ø¯Ø§Ų†Ø´ ŲŲ†ÛŒ (ÚŠØąŲˆØĒÛŒŲ†â€ŒŲ‡Ø§ØŒ Ų†ØŽâ€ŒŲ‡Ø§ØŒ Ø¨Ų„Ø§ÚŠ ÚŠØąØ¯Ų† ؈ ØēÛŒØąŲ‡) Ø¯Ø§ØąÛŒ ؈ ÚŠŲ†ØŦÚŠØ§ŲˆÛŒ ÚŠŲ‡ FastAPI Ú†ØˇŲˆØą `async def` ØąŲˆ Ø¯Øą Ų…Ų‚Ø§Ø¨Ų„ `def` Ų…ØšŲ…ŲˆŲ„ÛŒ Ų…Ø¯ÛŒØąÛŒØĒ Ų…ÛŒâ€ŒÚŠŲ†Ų‡ØŒ Ø§Ø¯Ø§Ų…Ų‡ Ø¨Ø¯Ų‡. + +/// + +### ØĒŲˆØ§Ø¨Øš ØšŲ…Ų„ÛŒØ§ØĒ Ų…ØŗÛŒØą + +ŲˆŲ‚ØĒی ÛŒŲ‡ *ØĒابؚ ØšŲ…Ų„ÛŒØ§ØĒ Ų…ØŗÛŒØą* ØąŲˆ با `def` Ų…ØšŲ…ŲˆŲ„ÛŒ Ø¨Ų‡ ØŦای `async def` ØĒØšØąÛŒŲ Ų…ÛŒâ€ŒÚŠŲ†ÛŒØŒ ØĒŲˆÛŒ ÛŒŲ‡ Ø§ØŗØĒØŽØą Ų†ØŽ ØŽØ§ØąØŦی اØŦØąØ§ Ų…ÛŒâ€ŒØ´Ų‡ ÚŠŲ‡ بؚدش Ų…Ų†ØĒØ¸ØąØ´ Ų…ÛŒâ€ŒŲ…ŲˆŲ†Ų†ØŒ Ø¨Ų‡ ØŦای Ø§ÛŒŲ†ÚŠŲ‡ Ų…ØŗØĒŲ‚ÛŒŲ… Øĩداش ÚŠŲ†Ų† (Ú†ŲˆŲ† ØŗØąŲˆØą ØąŲˆ Ø¨Ų„Ø§ÚŠ Ų…ÛŒâ€ŒÚŠŲ†Ų‡). + +Ø§Ú¯Ų‡ Ø§Ø˛ ÛŒŲ‡ ŲØąÛŒŲ…â€ŒŲˆØąÚŠ Ų†Ø§Ų‡Ų…â€ŒØ˛Ų…Ø§Ų† Ø¯ÛŒÚ¯Ų‡ Ų…ÛŒØ§ÛŒ ÚŠŲ‡ Ø¨Ų‡ ØąŲˆØ´ Ø¨Ø§Ų„Ø§ ÚŠØ§Øą Ų†Ų…ÛŒâ€ŒÚŠŲ†Ų‡ ؈ ؚادØĒ Ø¯Ø§ØąÛŒ *ØĒŲˆØ§Ø¨Øš ØšŲ…Ų„ÛŒØ§ØĒ Ų…ØŗÛŒØą* ØŗØ§Ø¯Ų‡ ŲŲ‚Øˇ Ų…Ø­Ø§ØŗØ¨Ø§ØĒی ØąŲˆ با `def` Ų…ØšŲ…ŲˆŲ„ÛŒ Ø¨ØąØ§ÛŒ ÛŒŲ‡ ØŗŲˆØ¯ ÚŠŲˆÚ†ÛŒÚŠ ØšŲ…Ų„ÚŠØąØ¯ (Ø­Ø¯ŲˆØ¯ 100 Ų†Ø§Ų†ŲˆØĢØ§Ų†ÛŒŲ‡) ØĒØšØąÛŒŲ ÚŠŲ†ÛŒØŒ ØĒ؈ØŦŲ‡ ÚŠŲ† ÚŠŲ‡ ØĒŲˆÛŒ **FastAPI** اØĢØąØ´ ÚŠØ§Ų…Ų„Ø§Ų‹ Ø¨ØąØšÚŠØŗŲ‡. ØĒŲˆÛŒ Ø§ÛŒŲ† Ų…ŲˆØ§ØąØ¯ØŒ Ø¨Ų‡ØĒØąŲ‡ Ø§Ø˛ `async def` Ø§ØŗØĒŲØ§Ø¯Ų‡ ÚŠŲ†ÛŒ Ų…Ú¯Ų‡ Ø§ÛŒŲ†ÚŠŲ‡ *ØĒŲˆØ§Ø¨Øš ØšŲ…Ų„ÛŒØ§ØĒ Ų…ØŗÛŒØąØĒ* ڊدی داشØĒŲ‡ Ø¨Ø§Ø´Ų† ÚŠŲ‡ ØšŲ…Ų„ÛŒØ§ØĒ I/O Ø¨Ų„Ø§ÚŠâ€ŒÚŠŲ†Ų†Ø¯Ų‡ Ø§Ų†ØŦØ§Ų… Ø¨Ø¯Ų‡. + +با Ø§ÛŒŲ† Ø­Ø§Ų„ØŒ ØĒŲˆÛŒ Ų‡Øą Ø¯Ųˆ Ų…ŲˆŲ‚ØšÛŒØĒ، احØĒŲ…Ø§Ų„Ø´ Ø˛ÛŒØ§Ø¯Ų‡ ÚŠŲ‡ **FastAPI** Ų‡Ų†ŲˆØ˛ [ØŗØąÛŒØšâ€ŒØĒØą](index.md#performance){.internal-link target=_blank} Ø§Ø˛ ŲØąÛŒŲ…â€ŒŲˆØąÚŠ Ų‚Ø¨Ų„ÛŒâ€ŒØ§ØĒ Ø¨Ø§Ø´Ų‡ (یا Ø­Ø¯Ø§Ų‚Ų„ Ų‚Ø§Ø¨Ų„ Ų…Ų‚Ø§ÛŒØŗŲ‡ Ø¨Ø§Ų‡Ø§Ø´). + +### ŲˆØ§Ø¨ØŗØĒÚ¯ÛŒâ€ŒŲ‡Ø§ + +Ų‡Ų…ÛŒŲ† Ø¨ØąØ§ÛŒ [ŲˆØ§Ø¨ØŗØĒÚ¯ÛŒâ€ŒŲ‡Ø§](tutorial/dependencies/index.md){.internal-link target=_blank} Ų‡Ų… ØĩØ¯Ų‚ Ų…ÛŒâ€ŒÚŠŲ†Ų‡. Ø§Ú¯Ų‡ ÛŒŲ‡ ŲˆØ§Ø¨ØŗØĒگی ÛŒŲ‡ ØĒابؚ `def` Ų…ØšŲ…ŲˆŲ„ÛŒ Ø¨Ų‡ ØŦای `async def` Ø¨Ø§Ø´Ų‡ØŒ ØĒŲˆÛŒ Ø§ØŗØĒØŽØą Ų†ØŽ ØŽØ§ØąØŦی اØŦØąØ§ Ų…ÛŒâ€ŒØ´Ų‡. + +### Ø˛ÛŒØąŲˆØ§Ø¨ØŗØĒÚ¯ÛŒâ€ŒŲ‡Ø§ + +Ų…ÛŒâ€ŒØĒŲˆŲ†ÛŒ Ú†Ų†Ø¯ ØĒا ŲˆØ§Ø¨ØŗØĒگی ؈ [Ø˛ÛŒØąŲˆØ§Ø¨ØŗØĒگی](tutorial/dependencies/sub-dependencies.md){.internal-link target=_blank} داشØĒŲ‡ باشی ÚŠŲ‡ Ų‡Ų…Ø¯ÛŒÚ¯Ų‡ ØąŲˆ Ų†ÛŒØ§Ø˛ Ø¯Ø§ØąŲ† (Ø¨Ų‡â€ŒØšŲ†ŲˆØ§Ų† ŲžØ§ØąØ§Ų…ØĒØąŲ‡Ø§ÛŒ ØĒØšØąÛŒŲ ØĒابؚ)، بؚØļÛŒâ€ŒŲ‡Ø§Ø´ŲˆŲ† Ų…Ų…ÚŠŲ†Ų‡ با `async def` ØŗØ§ØŽØĒŲ‡ Ø¨Ø´Ų† ؈ بؚØļÛŒâ€ŒŲ‡Ø§ با `def` Ų…ØšŲ…ŲˆŲ„ÛŒ. Ø¨Ø§Ø˛Ų… ÚŠØ§Øą Ų…ÛŒâ€ŒÚŠŲ†Ų‡ØŒ ؈ Ø§ŲˆŲ†Ø§ÛŒÛŒ ÚŠŲ‡ با `def` Ų…ØšŲ…ŲˆŲ„ÛŒ ØŗØ§ØŽØĒŲ‡ Ø´Ø¯Ų† ØĒŲˆÛŒ ÛŒŲ‡ Ų†ØŽ ØŽØ§ØąØŦی (Ø§Ø˛ Ø§ØŗØĒØŽØą Ų†ØŽ) Øĩدا Ø˛Ø¯Ų‡ Ų…ÛŒâ€ŒØ´Ų† Ø¨Ų‡ ØŦای Ø§ÛŒŲ†ÚŠŲ‡ "Ų…Ų†ØĒØ¸ØąØ´ŲˆŲ†" Ø¨Ų…ŲˆŲ†Ų†. + +### ØĒŲˆØ§Ø¨Øš ÚŠØ§ØąØ¨ØąØ¯ÛŒ Ø¯ÛŒÚ¯Ų‡ + +Ų‡Øą ØĒابؚ ÚŠØ§ØąØ¨ØąØ¯ÛŒ Ø¯ÛŒÚ¯Ų‡â€ŒØ§ÛŒ ÚŠŲ‡ Ų…ØŗØĒŲ‚ÛŒŲ… ØŽŲˆØ¯ØĒ Øĩداش Ų…ÛŒâ€ŒÚŠŲ†ÛŒ Ų…ÛŒâ€ŒØĒŲˆŲ†Ų‡ با `def` Ų…ØšŲ…ŲˆŲ„ÛŒ یا `async def` ØŗØ§ØŽØĒŲ‡ Ø¨Ø´Ų‡ ؈ FastAPI ØąŲˆ Ų†Ø­ŲˆŲ‡ ØĩØ¯Ø§Ø˛Ø¯Ų†Ø´ ØĒØŖØĢÛŒØą Ų†Ų…ÛŒâ€ŒØ°Ø§ØąŲ‡. + +Ø§ÛŒŲ† Ø¨ØąØŽŲ„Ø§Ų ØĒŲˆØ§Ø¨ØšÛŒ Ų‡ØŗØĒ ÚŠŲ‡ FastAPI Ø¨ØąØ§ØĒ ØĩØ¯Ø§Ø´ŲˆŲ† Ų…ÛŒâ€ŒÚŠŲ†Ų‡: *ØĒŲˆØ§Ø¨Øš ØšŲ…Ų„ÛŒØ§ØĒ Ų…ØŗÛŒØą* ؈ ŲˆØ§Ø¨ØŗØĒÚ¯ÛŒâ€ŒŲ‡Ø§. + +Ø§Ú¯Ų‡ ØĒابؚ ÚŠØ§ØąØ¨ØąØ¯ÛŒØĒ ÛŒŲ‡ ØĒابؚ Ų…ØšŲ…ŲˆŲ„ÛŒ با `def` Ø¨Ø§Ø´Ų‡ØŒ Ų…ØŗØĒŲ‚ÛŒŲ… Øĩداش Ų…ÛŒâ€ŒÚŠŲ†Ų† (Ų‡Ų…ŲˆŲ†â€ŒØˇŲˆØą ÚŠŲ‡ ØĒŲˆÛŒ ڊدØĒ Ų†ŲˆØ´ØĒی)، Ų†Ų‡ ØĒŲˆÛŒ Ø§ØŗØĒØŽØą Ų†ØŽØŒ Ø§Ú¯Ų‡ ØĒابؚ با `async def` ØŗØ§ØŽØĒŲ‡ Ø´Ø¯Ų‡ Ø¨Ø§Ø´Ų‡ØŒ باید ŲˆŲ‚ØĒی ØĒŲˆÛŒ ڊدØĒ Øĩداش Ų…ÛŒâ€ŒÚŠŲ†ÛŒ `await`Ø´ ÚŠŲ†ÛŒ. + +--- + +Ø¯ŲˆØ¨Ø§ØąŲ‡ØŒ Ø§ÛŒŲ†Ø§ ØŦØ˛ØĻیاØĒ ØŽÛŒŲ„ÛŒ ŲŲ†ÛŒ Ų‡ØŗØĒŲ† ÚŠŲ‡ احØĒŲ…Ø§Ų„Ø§Ų‹ Ø§Ú¯Ų‡ Ø¯Ų†Ø¨Ø§Ų„Ø´ŲˆŲ† Ø§ŲˆŲ…Ø¯Ų‡ باشی Ø¨ØąØ§ØĒ Ų…ŲÛŒØ¯ Ø¨Ø§Ø´Ų†. + +ŲˆÚ¯ØąŲ†Ų‡ØŒ با ØąØ§Ų‡Ų†Ų…Ø§ÛŒÛŒâ€ŒŲ‡Ø§ÛŒ ب؎ش Ø¨Ø§Ų„Ø§ باید ØŽŲˆØ¨ باشی: ØšØŦŲ„Ų‡ Ø¯Ø§ØąÛŒØŸ. diff --git a/docs/fa/docs/environment-variables.md b/docs/fa/docs/environment-variables.md new file mode 100644 index 000000000..75309ce1f --- /dev/null +++ b/docs/fa/docs/environment-variables.md @@ -0,0 +1,298 @@ +# Ų…ØĒØēÛŒØąŲ‡Ø§ÛŒ Ų…Ø­ÛŒØˇÛŒ + +/// tip + +Ø§Ú¯Ų‡ Ø§Ø˛ Ų‚Ø¨Ų„ Ų…ÛŒâ€ŒØ¯ŲˆŲ†ÛŒ Ų…ØĒØēÛŒØąŲ‡Ø§ÛŒ Ų…Ø­ÛŒØˇÛŒ چی Ų‡ØŗØĒŲ† ؈ Ú†ØˇŲˆØą Ø§Ø˛Ø´ŲˆŲ† Ø§ØŗØĒŲØ§Ø¯Ų‡ Ų…ÛŒâ€ŒØ´Ų‡ØŒ Ų…ÛŒâ€ŒØĒŲˆŲ†ÛŒ Ø§ÛŒŲ† ب؎ش ØąŲˆ ØąØ¯ ÚŠŲ†ÛŒ. + +/// + +ÛŒŲ‡ Ų…ØĒØēÛŒØą Ų…Ø­ÛŒØˇÛŒ (ÚŠŲ‡ Ø¨Ų‡Ø´ "**env var**" Ų‡Ų… Ų…ÛŒâ€ŒÚ¯Ų†) ÛŒŲ‡ Ų…ØĒØēÛŒØąÛŒŲ‡ ÚŠŲ‡ **ØŽØ§ØąØŦ** Ø§Ø˛ ڊد ŲžØ§ÛŒØĒŲˆŲ†ØŒ ØĒŲˆÛŒ **ØŗÛŒØŗØĒŲ…â€ŒØšØ§Ų…Ų„** Ø˛Ų†Ø¯Ú¯ÛŒ Ų…ÛŒâ€ŒÚŠŲ†Ų‡ ؈ Ų…ÛŒâ€ŒØĒŲˆŲ†Ų‡ ØĒŲˆØŗØˇ ڊد ŲžØ§ÛŒØĒŲˆŲ†ØĒ (یا Ø¨ØąŲ†Ø§Ų…Ų‡â€ŒŲ‡Ø§ÛŒ Ø¯ÛŒÚ¯Ų‡) ØŽŲˆŲ†Ø¯Ų‡ Ø¨Ø´Ų‡. + +Ų…ØĒØēÛŒØąŲ‡Ø§ÛŒ Ų…Ø­ÛŒØˇÛŒ Ų…ÛŒâ€ŒØĒŲˆŲ†Ų† Ø¨ØąØ§ÛŒ Ų…Ø¯ÛŒØąÛŒØĒ **ØĒŲ†Ø¸ÛŒŲ…Ø§ØĒ** Ø¨ØąŲ†Ø§Ų…Ų‡ØŒ Ø¨Ų‡â€ŒØšŲ†ŲˆØ§Ų† ب؎شی Ø§Ø˛ **Ų†Øĩب** ŲžØ§ÛŒØĒŲˆŲ† ؈ ØēÛŒØąŲ‡ Ų…ŲÛŒØ¯ Ø¨Ø§Ø´Ų†. + +## ØŗØ§ØŽØĒ ؈ Ø§ØŗØĒŲØ§Ø¯Ų‡ Ø§Ø˛ Ų…ØĒØēÛŒØąŲ‡Ø§ÛŒ Ų…Ø­ÛŒØˇÛŒ + +Ų…ÛŒâ€ŒØĒŲˆŲ†ÛŒ Ų…ØĒØēÛŒØąŲ‡Ø§ÛŒ Ų…Ø­ÛŒØˇÛŒ ØąŲˆ ØĒŲˆÛŒ **Ø´Ų„ (ØĒØąŲ…ÛŒŲ†Ø§Ų„)** **Ø¨ØŗØ§Ø˛ÛŒ** ؈ Ø§Ø˛Ø´ŲˆŲ† Ø§ØŗØĒŲØ§Ø¯Ų‡ ÚŠŲ†ÛŒØŒ Ø¨Ø¯ŲˆŲ† Ø§ÛŒŲ†ÚŠŲ‡ Ø¨Ų‡ ŲžØ§ÛŒØĒŲˆŲ† Ų†ÛŒØ§Ø˛ داشØĒŲ‡ باشی: + +//// tab | Ų„ÛŒŲ†ŲˆÚŠØŗØŒ Ų…ÚŠâ€ŒØ§ŲˆØ§ØŗØŒ ŲˆÛŒŲ†Ø¯ŲˆØ˛ بش + +

+ +```console +// Ų…ÛŒâ€ŒØĒŲˆŲ†ÛŒ ÛŒŲ‡ Ų…ØĒØēÛŒØą Ų…Ø­ÛŒØˇÛŒ Ø¨Ų‡ Ø§ØŗŲ… MY_NAME Ø¨ØŗØ§Ø˛ÛŒ با +$ export MY_NAME="Wade Wilson" + +// بؚد Ų…ÛŒâ€ŒØĒŲˆŲ†ÛŒ با Ø¨ØąŲ†Ø§Ų…Ų‡â€ŒŲ‡Ø§ÛŒ Ø¯ÛŒÚ¯Ų‡ Ø§Ø˛Ø´ Ø§ØŗØĒŲØ§Ø¯Ų‡ ÚŠŲ†ÛŒØŒ Ų…ØĢŲ„ +$ echo "Hello $MY_NAME" + +Hello Wade Wilson +``` + +
+ +//// + +//// tab | ŲˆÛŒŲ†Ø¯ŲˆØ˛ ŲžØ§ŲˆØąØ´Ų„ + +
+ +```console +// ÛŒŲ‡ Ų…ØĒØēÛŒØą Ų…Ø­ÛŒØˇÛŒ Ø¨Ų‡ Ø§ØŗŲ… MY_NAME Ø¨ØŗØ§Ø˛ +$ $Env:MY_NAME = "Wade Wilson" + +// با Ø¨ØąŲ†Ø§Ų…Ų‡â€ŒŲ‡Ø§ÛŒ Ø¯ÛŒÚ¯Ų‡ Ø§Ø˛Ø´ Ø§ØŗØĒŲØ§Ø¯Ų‡ ÚŠŲ†ØŒ Ų…ØĢŲ„ +$ echo "Hello $Env:MY_NAME" + +Hello Wade Wilson +``` + +
+ +//// + +## ØŽŲˆŲ†Ø¯Ų† Ų…ØĒØēÛŒØąŲ‡Ø§ÛŒ Ų…Ø­ÛŒØˇÛŒ ØĒŲˆÛŒ ŲžØ§ÛŒØĒŲˆŲ† + +Ų…ÛŒâ€ŒØĒŲˆŲ†ÛŒ Ų…ØĒØēÛŒØąŲ‡Ø§ÛŒ Ų…Ø­ÛŒØˇÛŒ ØąŲˆ **ØŽØ§ØąØŦ** Ø§Ø˛ ŲžØ§ÛŒØĒŲˆŲ†ØŒ ØĒŲˆÛŒ ØĒØąŲ…ÛŒŲ†Ø§Ų„ (یا با Ų‡Øą ØąŲˆØ´ Ø¯ÛŒÚ¯Ų‡) Ø¨ØŗØ§Ø˛ÛŒØŒ ؈ بؚد ØĒŲˆÛŒ **ŲžØ§ÛŒØĒŲˆŲ†** Ø§ŲˆŲ†Ø§ ØąŲˆ Ø¨ØŽŲˆŲ†ÛŒ. + +Ų…ØĢŲ„Ø§Ų‹ Ų…ÛŒâ€ŒØĒŲˆŲ†ÛŒ ÛŒŲ‡ ŲØ§ÛŒŲ„ `main.py` داشØĒŲ‡ باشی با: + +```Python hl_lines="3" +import os + +name = os.getenv("MY_NAME", "World") +print(f"Hello {name} from Python") +``` + +/// tip + +ØĸØąÚ¯ŲˆŲ…Ø§Ų† Ø¯ŲˆŲ… `os.getenv()` Ų…Ų‚Ø¯Ø§Øą ŲžÛŒØ´â€ŒŲØąØļÛŒŲ‡ ÚŠŲ‡ Ø¨ØąŲ…ÛŒâ€ŒÚ¯ØąØ¯ŲˆŲ†Ų‡. + +Ø§Ú¯Ų‡ Ų†Ø¯ÛŒØŒ Ø¨Ų‡â€ŒØĩŲˆØąØĒ ŲžÛŒØ´â€ŒŲØąØļ `None` Ų‡ØŗØĒ، Ø§ÛŒŲ†ØŦا Ų…Ø§ `"World"` ØąŲˆ Ø¨Ų‡â€ŒØšŲ†ŲˆØ§Ų† Ų…Ų‚Ø¯Ø§Øą ŲžÛŒØ´â€ŒŲØąØļ گذاشØĒÛŒŲ…. + +/// + +بؚد Ų…ÛŒâ€ŒØĒŲˆŲ†ÛŒ Ø§ŲˆŲ† Ø¨ØąŲ†Ø§Ų…Ų‡ ŲžØ§ÛŒØĒŲˆŲ† ØąŲˆ Øĩدا ÚŠŲ†ÛŒ: + +//// tab | Ų„ÛŒŲ†ŲˆÚŠØŗØŒ Ų…ÚŠâ€ŒØ§ŲˆØ§ØŗØŒ ŲˆÛŒŲ†Ø¯ŲˆØ˛ بش + +
+ +```console +// Ø§ÛŒŲ†ØŦا Ų‡Ų†ŲˆØ˛ Ų…ØĒØēÛŒØą Ų…Ø­ÛŒØˇÛŒ ØąŲˆ ØĒŲ†Ø¸ÛŒŲ… Ų†ÚŠØąØ¯ÛŒŲ… +$ python main.py + +// Ú†ŲˆŲ† Ų…ØĒØēÛŒØą Ų…Ø­ÛŒØˇÛŒ ØąŲˆ ØĒŲ†Ø¸ÛŒŲ… Ų†ÚŠØąØ¯ÛŒŲ…ØŒ Ų…Ų‚Ø¯Ø§Øą ŲžÛŒØ´â€ŒŲØąØļ ØąŲˆ Ų…ÛŒâ€ŒÚ¯ÛŒØąÛŒŲ… + +Hello World from Python + +// ŲˆŲ„ÛŒ Ø§Ú¯Ų‡ Ø§ŲˆŲ„ ÛŒŲ‡ Ų…ØĒØēÛŒØą Ų…Ø­ÛŒØˇÛŒ Ø¨ØŗØ§Ø˛ÛŒŲ… +$ export MY_NAME="Wade Wilson" + +// ؈ بؚد Ø¯ŲˆØ¨Ø§ØąŲ‡ Ø¨ØąŲ†Ø§Ų…Ų‡ ØąŲˆ Øĩدا ÚŠŲ†ÛŒŲ… +$ python main.py + +// Ø­Ø§Ų„Ø§ Ų…ÛŒâ€ŒØĒŲˆŲ†Ų‡ Ų…ØĒØēÛŒØą Ų…Ø­ÛŒØˇÛŒ ØąŲˆ Ø¨ØŽŲˆŲ†Ų‡ + +Hello Wade Wilson from Python +``` + +
+ +//// + +//// tab | ŲˆÛŒŲ†Ø¯ŲˆØ˛ ŲžØ§ŲˆØąØ´Ų„ + +
+ +```console +// Ø§ÛŒŲ†ØŦا Ų‡Ų†ŲˆØ˛ Ų…ØĒØēÛŒØą Ų…Ø­ÛŒØˇÛŒ ØąŲˆ ØĒŲ†Ø¸ÛŒŲ… Ų†ÚŠØąØ¯ÛŒŲ… +$ python main.py + +// Ú†ŲˆŲ† Ų…ØĒØēÛŒØą Ų…Ø­ÛŒØˇÛŒ ØąŲˆ ØĒŲ†Ø¸ÛŒŲ… Ų†ÚŠØąØ¯ÛŒŲ…ØŒ Ų…Ų‚Ø¯Ø§Øą ŲžÛŒØ´â€ŒŲØąØļ ØąŲˆ Ų…ÛŒâ€ŒÚ¯ÛŒØąÛŒŲ… + +Hello World from Python + +// ŲˆŲ„ÛŒ Ø§Ú¯Ų‡ Ø§ŲˆŲ„ ÛŒŲ‡ Ų…ØĒØēÛŒØą Ų…Ø­ÛŒØˇÛŒ Ø¨ØŗØ§Ø˛ÛŒŲ… +$ $Env:MY_NAME = "Wade Wilson" + +// ؈ بؚد Ø¯ŲˆØ¨Ø§ØąŲ‡ Ø¨ØąŲ†Ø§Ų…Ų‡ ØąŲˆ Øĩدا ÚŠŲ†ÛŒŲ… +$ python main.py + +// Ø­Ø§Ų„Ø§ Ų…ÛŒâ€ŒØĒŲˆŲ†Ų‡ Ų…ØĒØēÛŒØą Ų…Ø­ÛŒØˇÛŒ ØąŲˆ Ø¨ØŽŲˆŲ†Ų‡ + +Hello Wade Wilson from Python +``` + +
+ +//// + +Ú†ŲˆŲ† Ų…ØĒØēÛŒØąŲ‡Ø§ÛŒ Ų…Ø­ÛŒØˇÛŒ Ų…ÛŒâ€ŒØĒŲˆŲ†Ų† ØŽØ§ØąØŦ Ø§Ø˛ ڊد ØĒŲ†Ø¸ÛŒŲ… Ø¨Ø´Ų†ØŒ ŲˆŲ„ÛŒ ڊد Ų…ÛŒâ€ŒØĒŲˆŲ†Ų‡ Ø§ŲˆŲ†Ø§ ØąŲˆ Ø¨ØŽŲˆŲ†Ų‡ØŒ ؈ Ų„Ø§Ø˛Ų… Ų†ÛŒØŗØĒ با Ø¨Ų‚ÛŒŲ‡ ŲØ§ÛŒŲ„â€ŒŲ‡Ø§ Ø°ØŽÛŒØąŲ‡ (ÚŠŲ…ÛŒØĒی Ø¨Ų‡ `git`) Ø¨Ø´Ų†ØŒ Ų…ØšŲ…ŲˆŲ„Ø§Ų‹ Ø¨ØąØ§ÛŒ ŲžÛŒÚŠØąØ¨Ų†Ø¯ÛŒ یا **ØĒŲ†Ø¸ÛŒŲ…Ø§ØĒ** Ø§ØŗØĒŲØ§Ø¯Ų‡ Ų…ÛŒâ€ŒØ´Ų†. + +Ų‡Ų…Ú†Ų†ÛŒŲ† Ų…ÛŒâ€ŒØĒŲˆŲ†ÛŒ ÛŒŲ‡ Ų…ØĒØēÛŒØą Ų…Ø­ÛŒØˇÛŒ ØąŲˆ ŲŲ‚Øˇ Ø¨ØąØ§ÛŒ **ÛŒŲ‡ اØŦØąØ§ÛŒ ؎اØĩ Ø¨ØąŲ†Ø§Ų…Ų‡** Ø¨ØŗØ§Ø˛ÛŒØŒ ÚŠŲ‡ ŲŲ‚Øˇ Ø¨ØąØ§ÛŒ Ø§ŲˆŲ† Ø¨ØąŲ†Ø§Ų…Ų‡ ؈ ŲŲ‚Øˇ Ø¨ØąØ§ÛŒ Ų…Ø¯ØĒ Ø˛Ų…Ø§Ų† اØŦØąØ§Ø´ Ø¯Øą Ø¯ØŗØĒØąØŗŲ‡. + +Ø¨ØąØ§ÛŒ Ø§ÛŒŲ† ÚŠØ§ØąØŒ Ø¯ØąØŗØĒ Ų‚Ø¨Ų„ Ø§Ø˛ ØŽŲˆØ¯ Ø¨ØąŲ†Ø§Ų…Ų‡ØŒ ØĒŲˆÛŒ Ų‡Ų…ŲˆŲ† ØŽØˇ Ø¨ØŗØ§Ø˛Ø´: + +
+ +```console +// ÛŒŲ‡ Ų…ØĒØēÛŒØą Ų…Ø­ÛŒØˇÛŒ MY_NAME ØąŲˆ ØĒŲˆÛŒ ØŽØˇ Ø¨ØąØ§ÛŒ Ø§ÛŒŲ† اØŦØąØ§ÛŒ Ø¨ØąŲ†Ø§Ų…Ų‡ Ø¨ØŗØ§Ø˛ +$ MY_NAME="Wade Wilson" python main.py + +// Ø­Ø§Ų„Ø§ Ų…ÛŒâ€ŒØĒŲˆŲ†Ų‡ Ų…ØĒØēÛŒØą Ų…Ø­ÛŒØˇÛŒ ØąŲˆ Ø¨ØŽŲˆŲ†Ų‡ + +Hello Wade Wilson from Python + +// Ų…ØĒØēÛŒØą Ų…Ø­ÛŒØˇÛŒ بؚدش Ø¯ÛŒÚ¯Ų‡ ؈ØŦŲˆØ¯ Ų†Ø¯Ø§ØąŲ‡ +$ python main.py + +Hello World from Python +``` + +
+ +/// tip + +Ų…ÛŒâ€ŒØĒŲˆŲ†ÛŒ بیشØĒØą Ø¯Øą Ų…ŲˆØąØ¯Ø´ ØĒŲˆÛŒ Ø¨ØąŲ†Ø§Ų…Ų‡ Ø¯ŲˆØ§Ø˛Ø¯Ų‡â€ŒŲØ§ÚŠØĒŲˆØąÛŒ: ŲžÛŒÚŠØąØ¨Ų†Ø¯ÛŒ Ø¨ØŽŲˆŲ†ÛŒ. + +/// + +## Ų†ŲˆØšâ€ŒŲ‡Ø§ ؈ اؚØĒØ¨Ø§ØąØŗŲ†ØŦی + +Ø§ÛŒŲ† Ų…ØĒØēÛŒØąŲ‡Ø§ÛŒ Ų…Ø­ÛŒØˇÛŒ ŲŲ‚Øˇ Ų…ÛŒâ€ŒØĒŲˆŲ†Ų† **ØąØ´ØĒŲ‡â€ŒŲ‡Ø§ÛŒ Ų…ØĒŲ†ÛŒ** ØąŲˆ Ų†Ú¯Ų‡ Ø¯Ø§ØąŲ†ØŒ Ú†ŲˆŲ† ØŽØ§ØąØŦ Ø§Ø˛ ŲžØ§ÛŒØĒŲˆŲ† Ų‡ØŗØĒŲ† ؈ باید با Ø¨ØąŲ†Ø§Ų…Ų‡â€ŒŲ‡Ø§ÛŒ Ø¯ÛŒÚ¯Ų‡ ؈ Ø¨Ų‚ÛŒŲ‡ ØŗÛŒØŗØĒŲ… (؈ Ø­ØĒی ØŗÛŒØŗØĒŲ…â€ŒØšØ§Ų…Ų„â€ŒŲ‡Ø§ÛŒ Ų…ØŽØĒ؄؁ Ų…ØĢŲ„ Ų„ÛŒŲ†ŲˆÚŠØŗØŒ ŲˆÛŒŲ†Ø¯ŲˆØ˛ØŒ Ų…ÚŠâ€ŒØ§ŲˆØ§Øŗ) ØŗØ§Ø˛Ú¯Ø§Øą Ø¨Ø§Ø´Ų†. + +ÛŒØšŲ†ÛŒ **Ų‡Øą Ų…Ų‚Ø¯Ø§ØąÛŒ** ÚŠŲ‡ ØĒŲˆÛŒ ŲžØ§ÛŒØĒŲˆŲ† Ø§Ø˛ ÛŒŲ‡ Ų…ØĒØēÛŒØą Ų…Ø­ÛŒØˇÛŒ ØŽŲˆŲ†Ø¯Ų‡ Ų…ÛŒâ€ŒØ´Ų‡ ÛŒŲ‡ `str` Ų‡ØŗØĒ، ؈ Ų‡Øą ØĒØ¨Ø¯ÛŒŲ„ Ø¨Ų‡ Ų†ŲˆØš Ø¯ÛŒÚ¯Ų‡ یا Ų‡Øą اؚØĒØ¨Ø§ØąØŗŲ†ØŦی باید ØĒŲˆÛŒ ڊد Ø§Ų†ØŦØ§Ų… Ø¨Ø´Ų‡. + +ØĒŲˆÛŒ [ØąØ§Ų‡Ų†Ų…Ø§ÛŒ ÚŠØ§ØąØ¨Øą ŲžÛŒØ´ØąŲØĒŲ‡ - ØĒŲ†Ø¸ÛŒŲ…Ø§ØĒ ؈ Ų…ØĒØēÛŒØąŲ‡Ø§ÛŒ Ų…Ø­ÛŒØˇÛŒ](./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` Ų‚ØąØ§Øą Ú¯ØąŲØĒŲ‡. + +Ø§Ú¯Ų‡ بگی Ø¨Ų„Ų‡ Ø¨ØąØ§ÛŒ Ø¨Ų‡â€ŒØąŲˆØ˛ØąØŗØ§Ų†ÛŒ Ų…ØĒØēÛŒØą Ų…Ø­ÛŒØˇÛŒ `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` Ų‚ØąØ§Øą Ú¯ØąŲØĒŲ‡. + +Ø§Ú¯Ų‡ بگی Ø¨Ų„Ų‡ Ø¨ØąØ§ÛŒ Ø¨Ų‡â€ŒØąŲˆØ˛ØąØŗØ§Ų†ÛŒ Ų…ØĒØēÛŒØą Ų…Ø­ÛŒØˇÛŒ `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` (ØĸØŽØąÛŒŲ† ŲžŲˆØ´Ų‡) ŲžÛŒØ¯Ø§ Ų…ÛŒâ€ŒÚŠŲ†Ų‡ ؈ Ø§Ø˛ Ø§ŲˆŲ† Ø§ØŗØĒŲØ§Ø¯Ų‡ Ų…ÛŒâ€ŒÚŠŲ†Ų‡. + +//// + +ŲžØŗØŒ Ø§Ú¯Ų‡ ØĒØ§ÛŒŲž ÚŠŲ†ÛŒ: + +
+ +```console +$ python +``` + +
+ +//// tab | Ų„ÛŒŲ†ŲˆÚŠØŗØŒ Ų…ÚŠâ€ŒØ§ŲˆØ§Øŗ + +ØŗÛŒØŗØĒŲ… Ø¨ØąŲ†Ø§Ų…Ų‡ `python` ØąŲˆ ØĒŲˆÛŒ `/opt/custompython/bin` **ŲžÛŒØ¯Ø§** Ų…ÛŒâ€ŒÚŠŲ†Ų‡ ؈ اØŦØąØ§Ø´ Ų…ÛŒâ€ŒÚŠŲ†Ų‡. + +ØĒŲ‚ØąÛŒØ¨Ø§Ų‹ Ų…ØšØ§Ø¯Ų„ Ø§ÛŒŲ†Ų‡ ÚŠŲ‡ ØĒØ§ÛŒŲž ÚŠŲ†ÛŒ: + +
+ +```console +$ /opt/custompython/bin/python +``` + +
+ +//// + +//// tab | ŲˆÛŒŲ†Ø¯ŲˆØ˛ + +ØŗÛŒØŗØĒŲ… Ø¨ØąŲ†Ø§Ų…Ų‡ `python` ØąŲˆ ØĒŲˆÛŒ `C:\opt\custompython\bin\python` **ŲžÛŒØ¯Ø§** Ų…ÛŒâ€ŒÚŠŲ†Ų‡ ؈ اØŦØąØ§Ø´ Ų…ÛŒâ€ŒÚŠŲ†Ų‡. + +ØĒŲ‚ØąÛŒØ¨Ø§Ų‹ Ų…ØšØ§Ø¯Ų„ Ø§ÛŒŲ†Ų‡ ÚŠŲ‡ ØĒØ§ÛŒŲž ÚŠŲ†ÛŒ: + +
+ +```console +$ C:\opt\custompython\bin\python +``` + +
+ +//// + +Ø§ÛŒŲ† Ø§ØˇŲ„Ø§ØšØ§ØĒ ŲˆŲ‚ØĒی Ø¯Øą Ų…ŲˆØąØ¯ [Ų…Ø­ÛŒØˇâ€ŒŲ‡Ø§ÛŒ Ų…ØŦØ§Ø˛ÛŒ](virtual-environments.md){.internal-link target=_blank} یاد Ų…ÛŒâ€ŒÚ¯ÛŒØąÛŒ Ø¨Ų‡â€ŒØ¯ØąØ¯ØĒ Ų…ÛŒâ€ŒØŽŲˆØąŲ‡. + +## Ų†ØĒیØŦŲ‡â€ŒÚ¯ÛŒØąÛŒ + +با Ø§ÛŒŲ† باید ÛŒŲ‡ Ø¯ØąÚŠ ŲžØ§ÛŒŲ‡â€ŒØ§ÛŒ Ø§Ø˛ **Ų…ØĒØēÛŒØąŲ‡Ø§ÛŒ Ų…Ø­ÛŒØˇÛŒ** ؈ Ų†Ø­ŲˆŲ‡ Ø§ØŗØĒŲØ§Ø¯Ų‡â€ŒØ´ŲˆŲ† ØĒŲˆÛŒ ŲžØ§ÛŒØĒŲˆŲ† داشØĒŲ‡ باشی. + +Ų…ÛŒâ€ŒØĒŲˆŲ†ÛŒ بیشØĒØą Ø¯Øą Ų…ŲˆØąØ¯Ø´ŲˆŲ† ØĒŲˆÛŒ ŲˆÛŒÚŠÛŒâ€ŒŲžØ¯ÛŒØ§ Ø¨ØąØ§ÛŒ Ų…ØĒØēÛŒØą Ų…Ø­ÛŒØˇÛŒ Ø¨ØŽŲˆŲ†ÛŒ. + +ØĒŲˆÛŒ ØŽÛŒŲ„ÛŒ Ų…ŲˆØ§ØąØ¯ Ų…Ø´ØŽØĩ Ų†ÛŒØŗØĒ ÚŠŲ‡ Ų…ØĒØēÛŒØąŲ‡Ø§ÛŒ Ų…Ø­ÛŒØˇÛŒ Ú†ØˇŲˆØą Ų…ÛŒâ€ŒØĒŲˆŲ†Ų† ŲŲˆØąÛŒ Ų…ŲÛŒØ¯ ؈ ÚŠØ§ØąØ¨ØąØ¯ÛŒ Ø¨Ø§Ø´Ų†. ŲˆŲ„ÛŒ ØĒŲˆÛŒ Ų…ŲˆŲ‚ØšÛŒØĒâ€ŒŲ‡Ø§ÛŒ Ų…ØŽØĒ؄؁ ØĒŲˆØŗØšŲ‡ Ų…Ø¯Ø§Ų… ŲžÛŒØ¯Ø§Ø´ŲˆŲ† Ų…ÛŒâ€ŒØ´Ų‡ØŒ ŲžØŗ ØŽŲˆØ¨Ų‡ ÚŠŲ‡ Ø¯Øą Ų…ŲˆØąØ¯Ø´ŲˆŲ† Ø¨Ø¯ŲˆŲ†ÛŒ. + +Ų…ØĢŲ„Ø§Ų‹ØŒ ØĒŲˆÛŒ ب؎ش بؚدی Ø¯Øą Ų…ŲˆØąØ¯ [Ų…Ø­ÛŒØˇâ€ŒŲ‡Ø§ÛŒ Ų…ØŦØ§Ø˛ÛŒ](virtual-environments.md) Ø¨Ų‡ Ø§ÛŒŲ† Ø§ØˇŲ„Ø§ØšØ§ØĒ Ų†ÛŒØ§Ø˛ Ø¯Ø§ØąÛŒ. diff --git a/docs/fa/docs/index.md b/docs/fa/docs/index.md index 6addce763..0aa0bec36 100644 --- a/docs/fa/docs/index.md +++ b/docs/fa/docs/index.md @@ -11,11 +11,11 @@ ŲØąÛŒŲ…â€ŒŲˆØąÚŠ FastAPI، ÚŠØ§ØąØ§ÛŒÛŒ Ø¨Ø§Ų„Ø§ØŒ ÛŒØ§Ø¯Ú¯ÛŒØąÛŒ ØĸØŗØ§Ų†ØŒ ÚŠØ¯Ų†ŲˆÛŒØŗÛŒ ØŗØąÛŒØšØŒ ØĸŲ…Ø§Ø¯Ų‡ Ø¨ØąØ§ÛŒ Ø§ØŗØĒŲØ§Ø¯Ų‡ Ø¯Øą Ų…Ø­ÛŒØˇ ŲžØąŲˆØ¯Ø§ÚŠØ´Ų†

- - Test + + Test - - Coverage + + Coverage Package version diff --git a/docs/fa/docs/learn/index.md b/docs/fa/docs/learn/index.md new file mode 100644 index 000000000..06aa7f00e --- /dev/null +++ b/docs/fa/docs/learn/index.md @@ -0,0 +1,5 @@ +# ÛŒØ§Ø¯Ú¯ÛŒØąÛŒ + +Ø§ÛŒŲ†ØŦا Ø¨ØŽØ´â€ŒŲ‡Ø§ÛŒ Ų…Ų‚Ø¯Ų…Ø§ØĒی ؈ ØĸŲ…ŲˆØ˛Ø´â€ŒŲ‡Ø§ÛŒÛŒ Ų‡ØŗØĒŲ† ÚŠŲ‡ Ø¨ØąØ§ÛŒ ÛŒØ§Ø¯Ú¯ÛŒØąÛŒ **FastAPI** Ø¨Ų‡ØĒ ÚŠŲ…ÚŠ Ų…ÛŒâ€ŒÚŠŲ†Ų†. + +Ų…ÛŒâ€ŒØĒŲˆŲ†ÛŒ Ø§ÛŒŲ†Ųˆ ÛŒŲ‡ **ÚŠØĒاب**، ÛŒŲ‡ **Ø¯ŲˆØąŲ‡ ØĸŲ…ŲˆØ˛Ø´ÛŒ**، یا ØąØ§Ų‡ **ØąØŗŲ…ÛŒ** ؈ ŲžÛŒØ´Ų†Ų‡Ø§Ø¯ÛŒ Ø¨ØąØ§ÛŒ ÛŒØ§Ø¯Ú¯ÛŒØąÛŒ FastAPI Ø¯Øą Ų†Ø¸Øą Ø¨Ú¯ÛŒØąÛŒ. 😎 diff --git a/docs/fa/docs/python-types.md b/docs/fa/docs/python-types.md new file mode 100644 index 000000000..c428acbf7 --- /dev/null +++ b/docs/fa/docs/python-types.md @@ -0,0 +1,578 @@ +# Ų…Ų‚Ø¯Ų…Ų‡â€ŒØ§ÛŒ Ø¨Øą Ø§Ų†ŲˆØ§Øš Ų†ŲˆØš Ø¯Øą ŲžØ§ÛŒØĒŲˆŲ† + +ŲžØ§ÛŒØĒŲˆŲ† Ø§Ø˛ "Ų†ŲˆØšâ€ŒŲ†Ų…Ø§"Ų‡Ø§ÛŒ ا؎ØĒÛŒØ§ØąÛŒ (ÚŠŲ‡ Ø¨Ų‡Ø´ŲˆŲ† "type hints" یا "type annotations" Ų‡Ų… Ų…ÛŒâ€ŒÚ¯Ų†) ŲžØ´ØĒÛŒØ¨Ø§Ų†ÛŒ Ų…ÛŒâ€ŒÚŠŲ†Ų‡. + +Ø§ÛŒŲ† **"Ų†ŲˆØšâ€ŒŲ†Ų…Ø§Ų‡Ø§"** یا annotationŲ‡Ø§ ÛŒŲ‡ ØŗÛŒŲ†ØĒÚŠØŗ ؎اØĩ Ų‡ØŗØĒŲ† ÚŠŲ‡ Ø¨Ų‡ØĒ اØŦØ§Ø˛Ų‡ Ų…ÛŒâ€ŒØ¯Ų† Ų†ŲˆØš ÛŒŲ‡ Ų…ØĒØēÛŒØą ØąŲˆ Ų…Ø´ØŽØĩ ÚŠŲ†ÛŒ. + +با Ų…Ø´ØŽØĩ ÚŠØąØ¯Ų† Ų†ŲˆØš Ų…ØĒØēÛŒØąŲ‡Ø§ØŒ ŲˆÛŒØąØ§ÛŒØ´Ú¯ØąŲ‡Ø§ ؈ Ø§Ø¨Ø˛Ø§ØąŲ‡Ø§ Ų…ÛŒâ€ŒØĒŲˆŲ†Ų† ŲžØ´ØĒÛŒØ¨Ø§Ų†ÛŒ Ø¨Ų‡ØĒØąÛŒ Ø¨Ų‡ØĒ Ø¨Ø¯Ų†. + +Ø§ÛŒŲ† ŲŲ‚Øˇ ÛŒŲ‡ **ØĸŲ…ŲˆØ˛Ø´ ØŗØąÛŒØš / یادØĸŲˆØąÛŒ** Ø¯Øą Ų…ŲˆØąØ¯ Ų†ŲˆØšâ€ŒŲ†Ų…Ø§Ų‡Ø§ÛŒ ŲžØ§ÛŒØĒŲˆŲ†Ų‡. ŲŲ‚Øˇ Ø­Ø¯Ø§Ų‚Ų„ Ú†ÛŒØ˛Ø§ÛŒÛŒ ÚŠŲ‡ Ø¨ØąØ§ÛŒ Ø§ØŗØĒŲØ§Ø¯Ų‡ Ø§Ø˛Ø´ŲˆŲ† با **FastAPI** Ų„Ø§Ø˛Ų…Ų‡ ØąŲˆ ŲžŲˆØ´Ø´ Ų…ÛŒâ€ŒØ¯Ų‡... ÚŠŲ‡ Ø¯Øą ŲˆØ§Ų‚Øš ØŽÛŒŲ„ÛŒ ÚŠŲ…Ų‡. + +**FastAPI** ÚŠØ§Ų…Ų„Ø§Ų‹ Ø¨Øą ŲžØ§ÛŒŲ‡ Ø§ÛŒŲ† Ų†ŲˆØšâ€ŒŲ†Ų…Ø§Ų‡Ø§ØŗØĒ ؈ Ø§ÛŒŲ† Ø¨Ų‡Ø´ ÚŠŲ„ÛŒ Ų…Ø˛ÛŒØĒ ؈ ŲØ§ÛŒØ¯Ų‡ Ų…ÛŒâ€ŒØ¯Ų‡. + +ŲˆŲ„ÛŒ Ø­ØĒی Ø§Ú¯Ų‡ Ų‡ÛŒÚ†â€ŒŲˆŲ‚ØĒ Ø§Ø˛ **FastAPI** Ø§ØŗØĒŲØ§Ø¯Ų‡ Ų†ÚŠŲ†ÛŒØŒ Ø¨Ø§Ø˛Ų… ÛŒØ§Ø¯Ú¯ÛŒØąÛŒ ÛŒŲ‡ ÚŠŲ… Ø¯Øą Ų…ŲˆØąØ¯Ø´ŲˆŲ† Ø¨Ų‡ Ų†ŲØšØĒŲ‡. + +/// note + +Ø§Ú¯Ų‡ Ø­ØąŲŲ‡â€ŒØ§ÛŒ ŲžØ§ÛŒØĒŲˆŲ†ÛŒ ؈ Ų‡Ų…Ų‡â€ŒÚ†ÛŒØ˛ ØąŲˆ Ø¯Øą Ų…ŲˆØąØ¯ Ų†ŲˆØšâ€ŒŲ†Ų…Ø§Ų‡Ø§ Ų…ÛŒâ€ŒØ¯ŲˆŲ†ÛŒØŒ Ø¨ØąŲˆ ØŗØąØ§Øē ؁ØĩŲ„ بؚدی. + +/// + +## Ø§Ų†Ú¯ÛŒØ˛Ų‡ + +بیاید با ÛŒŲ‡ Ų…ØĢØ§Ų„ ØŗØ§Ø¯Ų‡ Ø´ØąŲˆØš ÚŠŲ†ÛŒŲ…: + +{* ../../docs_src/python_types/tutorial001.py *} + +ŲˆŲ‚ØĒی Ø§ÛŒŲ† Ø¨ØąŲ†Ø§Ų…Ų‡ ØąŲˆ اØŦØąØ§ ÚŠŲ†ÛŒØŒ ØŽØąŲˆØŦی Ø§ÛŒŲ†Ų‡: + +``` +John Doe +``` + +Ø§ÛŒŲ† ØĒابؚ Ø§ÛŒŲ† ÚŠØ§ØąØ§ ØąŲˆ Ų…ÛŒâ€ŒÚŠŲ†Ų‡: + +* ÛŒŲ‡ `first_name` ؈ `last_name` Ų…ÛŒâ€ŒÚ¯ÛŒØąŲ‡. +* Ø­ØąŲ Ø§ŲˆŲ„ Ų‡Øą ÚŠØ¯ŲˆŲ… ØąŲˆ با `title()` Ø¨Ø˛ØąÚ¯ Ų…ÛŒâ€ŒÚŠŲ†Ų‡. +* ØĒØąÚŠÛŒØ¨Ø´ŲˆŲ† Ų…ÛŒâ€ŒÚŠŲ†Ų‡ با ÛŒŲ‡ ŲØ§ØĩŲ„Ų‡ ŲˆØŗØˇØ´ŲˆŲ†. + +{* ../../docs_src/python_types/tutorial001.py hl[2] *} + +### ŲˆÛŒØąØ§ÛŒØ´Ø´ ÚŠŲ† + +Ø§ÛŒŲ† ÛŒŲ‡ Ø¨ØąŲ†Ø§Ų…Ų‡ ØŽÛŒŲ„ÛŒ ØŗØ§Ø¯Ų‡â€ŒØŗØĒ. + +ŲˆŲ„ÛŒ Ø­Ø§Ų„Ø§ ØĒØĩŲˆØą ÚŠŲ† Ø¯Ø§ØąÛŒ Ø§Ø˛ ØĩŲØą Ų…ÛŒâ€ŒŲ†ŲˆÛŒØŗÛŒØ´. + +ÛŒŲ‡ ØŦایی Ø´ØąŲˆØš ÚŠØąØ¯ÛŒ Ø¨Ų‡ ØĒØšØąÛŒŲ ØĒابؚ، ŲžØ§ØąØ§Ų…ØĒØąŲ‡Ø§ØĒ ØĸŲ…Ø§Ø¯Ų‡â€ŒØŗØĒ... + +ŲˆŲ„ÛŒ بؚد باید "Ø§ŲˆŲ† Ų…ØĒدی ÚŠŲ‡ Ø­ØąŲ Ø§ŲˆŲ„ ØąŲˆ Ø¨Ø˛ØąÚ¯ Ų…ÛŒâ€ŒÚŠŲ†Ų‡" ØąŲˆ Øĩدا ÚŠŲ†ÛŒ. + +Øĸیا Ø§ØŗŲ…Ø´ `upper` Ø¨ŲˆØ¯ØŸ یا `uppercase`؟ شاید `first_uppercase`؟ یا `capitalize`؟ + +بؚد، با Ø¯ŲˆØŗØĒ Ų‚Ø¯ÛŒŲ…ÛŒ Ø¨ØąŲ†Ø§Ų…Ų‡â€ŒŲ†ŲˆÛŒØŗØ§ØŒ ØĒÚŠŲ…ÛŒŲ„ ØŽŲˆØ¯ÚŠØ§Øą ŲˆÛŒØąØ§ÛŒØ´Ú¯ØąØŒ Ø§Ų…ØĒØ­Ø§Ų† Ų…ÛŒâ€ŒÚŠŲ†ÛŒ. + +ŲžØ§ØąØ§Ų…ØĒØą Ø§ŲˆŲ„ ØĒابؚ، `first_name` ØąŲˆ ØĒØ§ÛŒŲž Ų…ÛŒâ€ŒÚŠŲ†ÛŒØŒ بؚد ÛŒŲ‡ Ų†Ų‚ØˇŲ‡ (`.`) Ų…ÛŒâ€ŒØ°Ø§ØąÛŒ ؈ `Ctrl+Space` ØąŲˆ Ų…ÛŒâ€ŒØ˛Ų†ÛŒ ØĒا ØĒÚŠŲ…ÛŒŲ„ ØŽŲˆØ¯ÚŠØ§Øą بیاد. + +ŲˆŲ„ÛŒ Ų…ØĒØŖØŗŲØ§Ų†Ų‡ØŒ Ú†ÛŒØ˛ Ų…ŲÛŒØ¯ÛŒ Ų†Ų…ÛŒâ€ŒÚ¯ÛŒØąÛŒ: + + + +### Ų†ŲˆØš اØļØ§ŲŲ‡ ÚŠŲ† + +بیا ŲŲ‚Øˇ ÛŒŲ‡ ØŽØˇ Ø§Ø˛ Ų†ØŗØŽŲ‡ Ų‚Ø¨Ų„ÛŒ ØąŲˆ ØĒØēÛŒÛŒØą Ø¨Ø¯ÛŒŲ…. + +Ø¯Ų‚ÛŒŲ‚Ø§Ų‹ Ø§ÛŒŲ† ب؎ش، ŲžØ§ØąØ§Ų…ØĒØąŲ‡Ø§ÛŒ ØĒابؚ ØąŲˆØŒ Ø§Ø˛: + +```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` ŲØšØ§Ų„ ÚŠŲ†ÛŒ ؈ Ø§ÛŒŲ†Ųˆ Ų…ÛŒâ€ŒØ¨ÛŒŲ†ÛŒ: + + + +با Ø§ÛŒŲ†ØŒ Ų…ÛŒâ€ŒØĒŲˆŲ†ÛŒ Ø§ØŗÚŠØąŲˆŲ„ ÚŠŲ†ÛŒØŒ Ú¯Ø˛ÛŒŲ†Ų‡â€ŒŲ‡Ø§ ØąŲˆ Ø¨Ø¨ÛŒŲ†ÛŒØŒ ØĒا ŲˆŲ‚ØĒی ÚŠŲ‡ Ø§ŲˆŲ† Ú†ÛŒØ˛ÛŒ ÚŠŲ‡ "Ø¨Ų‡ Ų†Ø¸ØąØĒ ØĸØ´Ų†Ø§ Ų…ÛŒØ§Ø¯" ØąŲˆ ŲžÛŒØ¯Ø§ ÚŠŲ†ÛŒ: + + + +## Ø§Ų†Ú¯ÛŒØ˛Ų‡ بیشØĒØą + +Ø§ÛŒŲ† ØĒابؚ ØąŲˆ چک ÚŠŲ†ØŒ Ø§Ų„Ø§Ų† Ų†ŲˆØšâ€ŒŲ†Ų…Ø§ Ø¯Ø§ØąŲ‡: + +{* ../../docs_src/python_types/tutorial003.py hl[1] *} + +Ú†ŲˆŲ† ŲˆÛŒØąØ§ÛŒØ´Ú¯Øą Ų†ŲˆØš Ų…ØĒØēÛŒØąŲ‡Ø§ ØąŲˆ Ų…ÛŒâ€ŒØ¯ŲˆŲ†Ų‡ØŒ ŲŲ‚Øˇ ØĒÚŠŲ…ÛŒŲ„ ØŽŲˆØ¯ÚŠØ§Øą Ų†Ų…ÛŒâ€ŒÚ¯ÛŒØąÛŒØŒ Ø¨Ų„ÚŠŲ‡ چک ØŽØˇØ§Ų‡Ø§ Ų‡Ų… Ø¯Ø§ØąÛŒ: + + + +Ø­Ø§Ų„Ø§ Ų…ÛŒâ€ŒØ¯ŲˆŲ†ÛŒ ÚŠŲ‡ باید Ø¯ØąØŗØĒØ´ ÚŠŲ†ÛŒØŒ `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`. ؈ Ų…Ų‚Ø¯Ø§ØąŲ‡Ø§ÛŒ Ø¯Ø§ØŽŲ„ÛŒØ´ŲˆŲ† Ų‡Ų… Ų…ÛŒâ€ŒØĒŲˆŲ†Ų† Ų†ŲˆØš ØŽŲˆØ¯Ø´ŲˆŲ† ØąŲˆ داشØĒŲ‡ Ø¨Ø§Ø´Ų†. + +Ø¨Ų‡ Ø§ÛŒŲ† Ų†ŲˆØšâ€ŒŲ‡Ø§ ÚŠŲ‡ Ų†ŲˆØšâ€ŒŲ‡Ø§ÛŒ Ø¯Ø§ØŽŲ„ÛŒ Ø¯Ø§ØąŲ† Ų…ÛŒâ€ŒÚ¯Ų† "**ØšŲ…ŲˆŲ…ÛŒ**" یا "generic". ؈ Ų…ÛŒâ€ŒØ´Ų‡ Ø§ŲˆŲ†Ø§ ØąŲˆ ØĒØšØąÛŒŲ ÚŠØąØ¯ØŒ Ø­ØĒی با Ų†ŲˆØšâ€ŒŲ‡Ø§ÛŒ Ø¯Ø§ØŽŲ„ÛŒØ´ŲˆŲ†. + +Ø¨ØąØ§ÛŒ ØĒØšØąÛŒŲ Ø§ÛŒŲ† Ų†ŲˆØšâ€ŒŲ‡Ø§ ؈ Ų†ŲˆØšâ€ŒŲ‡Ø§ÛŒ Ø¯Ø§ØŽŲ„ÛŒØ´ŲˆŲ†ØŒ Ų…ÛŒâ€ŒØĒŲˆŲ†ÛŒ Ø§Ø˛ Ų…Ø§Ú˜ŲˆŲ„ Ø§ØŗØĒØ§Ų†Ø¯Ø§ØąØ¯ ŲžØ§ÛŒØĒŲˆŲ† `typing` Ø§ØŗØĒŲØ§Ø¯Ų‡ ÚŠŲ†ÛŒ. Ø§ÛŒŲ† Ų…Ø§Ú˜ŲˆŲ„ Ų…ØŽØĩ؈Øĩ ŲžØ´ØĒÛŒØ¨Ø§Ų†ÛŒ Ø§Ø˛ Ų†ŲˆØšâ€ŒŲ†Ų…Ø§Ų‡Ø§ØŗØĒ. + +#### Ų†ØŗØŽŲ‡â€ŒŲ‡Ø§ÛŒ ØŦدیدØĒØą ŲžØ§ÛŒØĒŲˆŲ† + +ØŗÛŒŲ†ØĒÚŠØŗ با Ø§ØŗØĒŲØ§Ø¯Ų‡ Ø§Ø˛ `typing` با Ų‡Ų…Ų‡ Ų†ØŗØŽŲ‡â€ŒŲ‡Ø§ØŒ Ø§Ø˛ ŲžØ§ÛŒØĒŲˆŲ† 3.6 ØĒا ØŦدیدØĒØąÛŒŲ†â€ŒŲ‡Ø§ØŒ Ø§Ø˛ ØŦŲ…Ų„Ų‡ ŲžØ§ÛŒØĒŲˆŲ† 3.9، 3.10 ؈ ØēÛŒØąŲ‡ **ØŗØ§Ø˛Ú¯Ø§ØąŲ‡**. + +با ŲžÛŒØ´ØąŲØĒ ŲžØ§ÛŒØĒŲˆŲ†ØŒ **Ų†ØŗØŽŲ‡â€ŒŲ‡Ø§ÛŒ ØŦدیدØĒØą** ŲžØ´ØĒÛŒØ¨Ø§Ų†ÛŒ Ø¨Ų‡ØĒØąÛŒ Ø¨ØąØ§ÛŒ Ø§ÛŒŲ† Ų†ŲˆØšâ€ŒŲ†Ų…Ø§Ų‡Ø§ Ø¯Ø§ØąŲ† ؈ ØĒŲˆÛŒ ØŽÛŒŲ„ÛŒ Ų…ŲˆØ§ØąØ¯ Ø­ØĒی Ų„Ø§Ø˛Ų… Ų†ÛŒØŗØĒ Ų…Ø§Ú˜ŲˆŲ„ `typing` ØąŲˆ ŲˆØ§ØąØ¯ ÚŠŲ†ÛŒ ؈ Ø§Ø˛Ø´ Ø¨ØąØ§ÛŒ ØĒØšØąÛŒŲ Ų†ŲˆØšâ€ŒŲ†Ų…Ø§Ų‡Ø§ Ø§ØŗØĒŲØ§Ø¯Ų‡ ÚŠŲ†ÛŒ. + +Ø§Ú¯Ų‡ بØĒŲˆŲ†ÛŒ Ø¨ØąØ§ÛŒ ŲžØąŲˆÚ˜Ų‡â€ŒØ§ØĒ Ø§Ø˛ ÛŒŲ‡ Ų†ØŗØŽŲ‡ ØŦدیدØĒØą ŲžØ§ÛŒØĒŲˆŲ† Ø§ØŗØĒŲØ§Ø¯Ų‡ ÚŠŲ†ÛŒØŒ Ų…ÛŒâ€ŒØĒŲˆŲ†ÛŒ Ø§Ø˛ Ø§ÛŒŲ† ØŗØ§Ø¯Ú¯ÛŒ اØļØ§ŲŲ‡ Ø¨Ų‡ØąŲ‡ Ø¨Ø¨ØąÛŒ. + +ØĒŲˆÛŒ Ų‡Ų…Ų‡ Ų…ØŗØĒŲ†Ø¯Ø§ØĒ، Ų…ØĢØ§Ų„â€ŒŲ‡Ø§ÛŒÛŒ Ų‡ØŗØĒŲ† ÚŠŲ‡ با Ų‡Øą Ų†ØŗØŽŲ‡ ŲžØ§ÛŒØĒŲˆŲ† ØŗØ§Ø˛Ú¯Ø§ØąŲ† (ŲˆŲ‚ØĒی ØĒŲØ§ŲˆØĒی Ų‡ØŗØĒ). + +Ų…ØĢŲ„Ø§Ų‹ "**Python 3.6+**" ÛŒØšŲ†ÛŒ با ŲžØ§ÛŒØĒŲˆŲ† 3.6 یا Ø¨Ø§Ų„Ø§ØĒØą (Ų…ØĢŲ„ 3.7، 3.8، 3.9، 3.10 ؈ ØēÛŒØąŲ‡) ØŗØ§Ø˛Ú¯Ø§ØąŲ‡. ؈ "**Python 3.9+**" ÛŒØšŲ†ÛŒ با ŲžØ§ÛŒØĒŲˆŲ† 3.9 یا Ø¨Ø§Ų„Ø§ØĒØą (Ų…ØĢŲ„ 3.10 ؈ ØēÛŒØąŲ‡) ØŗØ§Ø˛Ú¯Ø§ØąŲ‡. + +Ø§Ú¯Ų‡ بØĒŲˆŲ†ÛŒ Ø§Ø˛ **ØŦدیدØĒØąÛŒŲ† Ų†ØŗØŽŲ‡â€ŒŲ‡Ø§ÛŒ ŲžØ§ÛŒØĒŲˆŲ†** Ø§ØŗØĒŲØ§Ø¯Ų‡ ÚŠŲ†ÛŒØŒ Ø§Ø˛ Ų…ØĢØ§Ų„â€ŒŲ‡Ø§ÛŒ Ų†ØŗØŽŲ‡ ØĸØŽØą Ø§ØŗØĒŲØ§Ø¯Ų‡ ÚŠŲ†ØŒ Ú†ŲˆŲ† Ø§ŲˆŲ†Ø§ **Ø¨Ų‡ØĒØąÛŒŲ† ؈ ØŗØ§Ø¯Ų‡â€ŒØĒØąÛŒŲ† ØŗÛŒŲ†ØĒÚŠØŗ** ØąŲˆ Ø¯Ø§ØąŲ†ØŒ Ų…ØĢŲ„Ø§Ų‹ "**Python 3.10+**". + +#### Ų„ÛŒØŗØĒ + +Ų…ØĢŲ„Ø§Ų‹ØŒ Ø¨ÛŒØ§ÛŒŲ… ÛŒŲ‡ Ų…ØĒØēÛŒØą ØĒØšØąÛŒŲ ÚŠŲ†ÛŒŲ… ÚŠŲ‡ ÛŒŲ‡ `list` Ø§Ø˛ `str` Ø¨Ø§Ø´Ų‡. + +//// 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!} +``` + +Ų…ØĒØēÛŒØą ØąŲˆ با Ų‡Ų…ŲˆŲ† ØŗÛŒŲ†ØĒÚŠØŗ Ø¯ŲˆŲ†Ų‚ØˇŲ‡ (`:`) ØĒØšØąÛŒŲ ÚŠŲ†. + +Ø¨Ų‡â€ŒØšŲ†ŲˆØ§Ų† Ų†ŲˆØšØŒ `List` ØąŲˆ ÚŠŲ‡ Ø§Ø˛ `typing` ŲˆØ§ØąØ¯ ÚŠØąØ¯ÛŒ Ø¨Ø°Ø§Øą. + +Ú†ŲˆŲ† Ų„ÛŒØŗØĒ ÛŒŲ‡ Ų†ŲˆØšŲ‡ ÚŠŲ‡ Ų†ŲˆØšâ€ŒŲ‡Ø§ÛŒ Ø¯Ø§ØŽŲ„ÛŒ Ø¯Ø§ØąŲ‡ØŒ Ø§ŲˆŲ†Ø§ ØąŲˆ ØĒŲˆÛŒ ÚŠØąŲˆØ´Ų‡â€ŒŲ‡Ø§ Ų…ÛŒâ€ŒØ°Ø§ØąÛŒ: + +```Python hl_lines="4" +{!> ../../docs_src/python_types/tutorial006.py!} +``` + +//// + +/// info + +Ø§ŲˆŲ† Ų†ŲˆØšâ€ŒŲ‡Ø§ÛŒ Ø¯Ø§ØŽŲ„ÛŒ ØĒŲˆÛŒ ÚŠØąŲˆØ´Ų‡â€ŒŲ‡Ø§ Ø¨Ų‡Ø´ŲˆŲ† "ŲžØ§ØąØ§Ų…ØĒØąŲ‡Ø§ÛŒ Ų†ŲˆØš" Ų…ÛŒâ€ŒÚ¯Ų†. + +ØĒŲˆÛŒ Ø§ÛŒŲ† Ų…ŲˆØąØ¯ØŒ `str` ŲžØ§ØąØ§Ų…ØĒØą Ų†ŲˆØšÛŒŲ‡ ÚŠŲ‡ Ø¨Ų‡ `List` (یا `list` ØĒŲˆÛŒ ŲžØ§ÛŒØĒŲˆŲ† 3.9 ؈ Ø¨Ø§Ų„Ø§ØĒØą) ŲžØ§Øŗ Ø¯Ø§Ø¯Ų‡ Ø´Ø¯Ų‡. + +/// + +ÛŒØšŲ†ÛŒ: "Ų…ØĒØēÛŒØą `items` ÛŒŲ‡ `list` Ų‡ØŗØĒ، ؈ Ų‡Øą ÚŠØ¯ŲˆŲ… Ø§Ø˛ ØĸیØĒŲ…â€ŒŲ‡Ø§ÛŒ Ø§ÛŒŲ† Ų„ÛŒØŗØĒ ÛŒŲ‡ `str` Ų‡ØŗØĒŲ†". + +/// tip + +Ø§Ú¯Ų‡ Ø§Ø˛ ŲžØ§ÛŒØĒŲˆŲ† 3.9 یا Ø¨Ø§Ų„Ø§ØĒØą Ø§ØŗØĒŲØ§Ø¯Ų‡ Ų…ÛŒâ€ŒÚŠŲ†ÛŒØŒ Ų„Ø§Ø˛Ų… Ų†ÛŒØŗØĒ `List` ØąŲˆ Ø§Ø˛ `typing` ŲˆØ§ØąØ¯ ÚŠŲ†ÛŒØŒ Ų…ÛŒâ€ŒØĒŲˆŲ†ÛŒ Ų‡Ų…ŲˆŲ† Ų†ŲˆØš Ų…ØšŲ…ŲˆŲ„ÛŒ `list` ØąŲˆ Ø¨Ų‡ ØŦاش Ø§ØŗØĒŲØ§Ø¯Ų‡ ÚŠŲ†ÛŒ. + +/// + +با Ø§ÛŒŲ† ÚŠØ§ØąØŒ ŲˆÛŒØąØ§ÛŒØ´Ú¯ØąØĒ Ø­ØĒی ŲˆŲ‚ØĒی Ø¯Ø§ØąÛŒ ØĸیØĒŲ…â€ŒŲ‡Ø§ÛŒ Ų„ÛŒØŗØĒ ØąŲˆ ŲžØąØ¯Ø§Ø˛Ø´ Ų…ÛŒâ€ŒÚŠŲ†ÛŒ Ø¨Ų‡ØĒ ÚŠŲ…ÚŠ Ų…ÛŒâ€ŒÚŠŲ†Ų‡: + + + +Ø¨Ø¯ŲˆŲ† Ų†ŲˆØšâ€ŒŲ‡Ø§ØŒ ØąØŗÛŒØ¯Ų† Ø¨Ų‡ Ø§ÛŒŲ† ØĒŲ‚ØąÛŒØ¨Ø§Ų‹ ØēÛŒØąŲ…Ų…ÚŠŲ†Ų‡. + +ØĒ؈ØŦŲ‡ ÚŠŲ† ÚŠŲ‡ Ų…ØĒØēÛŒØą `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` با 3 ØĒا ØĸیØĒŲ…Ų‡ØŒ ÛŒŲ‡ `int`، ÛŒŲ‡ `int` Ø¯ÛŒÚ¯Ų‡ØŒ ؈ ÛŒŲ‡ `str`. +* Ų…ØĒØēÛŒØą `items_s` ÛŒŲ‡ `set` Ų‡ØŗØĒ، ؈ Ų‡Øą ÚŠØ¯ŲˆŲ… Ø§Ø˛ ØĸیØĒŲ…â€ŒŲ‡Ø§Ø´ Ø§Ø˛ Ų†ŲˆØš `bytes` Ų‡ØŗØĒŲ†. + +#### Ø¯ÛŒÚŠØ´Ų†ØąÛŒ + +Ø¨ØąØ§ÛŒ ØĒØšØąÛŒŲ ÛŒŲ‡ `dict`، 2 ØĒا ŲžØ§ØąØ§Ų…ØĒØą Ų†ŲˆØš Ų…ÛŒâ€ŒØ¯ÛŒØŒ ÚŠŲ‡ با ÚŠØ§Ų…Ø§ Ø§Ø˛ Ų‡Ų… ØŦدا Ø´Ø¯Ų†. + +ŲžØ§ØąØ§Ų…ØĒØą Ų†ŲˆØš Ø§ŲˆŲ„ Ø¨ØąØ§ÛŒ ÚŠŲ„ÛŒØ¯Ų‡Ø§ÛŒ `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`. + +ØĒŲˆÛŒ ŲžØ§ÛŒØĒŲˆŲ† 3.6 ؈ Ø¨Ø§Ų„Ø§ØĒØą (Ø§Ø˛ ØŦŲ…Ų„Ų‡ ŲžØ§ÛŒØĒŲˆŲ† 3.10) Ų…ÛŒâ€ŒØĒŲˆŲ†ÛŒ Ø§Ø˛ Ų†ŲˆØš `Union` ØĒŲˆÛŒ `typing` Ø§ØŗØĒŲØ§Ø¯Ų‡ ÚŠŲ†ÛŒ ؈ Ų†ŲˆØšâ€ŒŲ‡Ø§ÛŒ Ų…Ų…ÚŠŲ† ØąŲˆ ØĒŲˆÛŒ ÚŠØąŲˆØ´Ų‡â€ŒŲ‡Ø§ Ø¨Ø°Ø§ØąÛŒ. + +ØĒŲˆÛŒ ŲžØ§ÛŒØĒŲˆŲ† 3.10 ÛŒŲ‡ **ØŗÛŒŲ†ØĒÚŠØŗ ØŦدید** Ų‡Ų… Ų‡ØŗØĒ ÚŠŲ‡ Ų…ÛŒâ€ŒØĒŲˆŲ†ÛŒ Ų†ŲˆØšâ€ŒŲ‡Ø§ÛŒ Ų…Ų…ÚŠŲ† ØąŲˆ با ÛŒŲ‡ ØŽØˇ ØšŲ…ŲˆØ¯ÛŒ (`|`) ØŦدا ÚŠŲ†ÛŒ. + +//// 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` Ų‡Ų… Ø¨Ø§Ø´Ų‡. + +ØĒŲˆÛŒ ŲžØ§ÛŒØĒŲˆŲ† 3.6 ؈ Ø¨Ø§Ų„Ø§ØĒØą (Ø§Ø˛ ØŦŲ…Ų„Ų‡ ŲžØ§ÛŒØĒŲˆŲ† 3.10) Ų…ÛŒâ€ŒØĒŲˆŲ†ÛŒ با ŲˆØ§ØąØ¯ ÚŠØąØ¯Ų† ؈ Ø§ØŗØĒŲØ§Ø¯Ų‡ Ø§Ø˛ `Optional` Ø§Ø˛ Ų…Ø§Ú˜ŲˆŲ„ `typing` Ø§ÛŒŲ†Ųˆ ØĒØšØąÛŒŲ ÚŠŲ†ÛŒ. + +```Python hl_lines="1 4" +{!../../docs_src/python_types/tutorial009.py!} +``` + +Ø§ØŗØĒŲØ§Ø¯Ų‡ Ø§Ø˛ `Optional[str]` Ø¨Ų‡ ØŦای ŲŲ‚Øˇ `str` Ø¨Ų‡ ŲˆÛŒØąØ§ÛŒØ´Ú¯Øą ÚŠŲ…ÚŠ Ų…ÛŒâ€ŒÚŠŲ†Ų‡ ØŽØˇØ§Ų‡Ø§ÛŒÛŒ ÚŠŲ‡ Ų…Ų…ÚŠŲ†Ų‡ ŲÚŠØą ÚŠŲ†ÛŒ ÛŒŲ‡ Ų…Ų‚Ø¯Ø§Øą Ų‡Ų…ÛŒØ´Ų‡ `str` Ų‡ØŗØĒ ØąŲˆ ŲžÛŒØ¯Ø§ ÚŠŲ†Ų‡ØŒ Ø¯Øą Ø­Ø§Ų„ÛŒ ÚŠŲ‡ Ų…ÛŒâ€ŒØĒŲˆŲ†Ų‡ `None` Ų‡Ų… Ø¨Ø§Ø´Ų‡. + +`Optional[Something]` Ø¯Øą ŲˆØ§Ų‚Øš Ų…ÛŒØ§Ų†â€ŒØ¨Øą Ø¨ØąØ§ÛŒ `Union[Something, None]` Ų‡ØŗØĒ، Ø§ÛŒŲ† Ø¯Ųˆ ØĒا Ų…ØšØ§Ø¯Ų„Ų†. + +ÛŒØšŲ†ÛŒ ØĒŲˆÛŒ ŲžØ§ÛŒØĒŲˆŲ† 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` + +Ø§Ú¯Ų‡ Ø§Ø˛ Ų†ØŗØŽŲ‡ ŲžØ§ÛŒØĒŲˆŲ† Ø˛ÛŒØą 3.10 Ø§ØŗØĒŲØ§Ø¯Ų‡ Ų…ÛŒâ€ŒÚŠŲ†ÛŒØŒ ÛŒŲ‡ Ų†ÚŠØĒŲ‡ Ø§Ø˛ دید ØŽÛŒŲ„ÛŒ **Ø´ØŽØĩی** ØŽŲˆØ¯Ų…: + +* 🚨 Ø§Ø˛ `Optional[SomeType]` Ø§ØŗØĒŲØ§Ø¯Ų‡ Ų†ÚŠŲ† +* Ø¨Ų‡ ØŦاش ✨ **Ø§Ø˛ `Union[SomeType, None]` Ø§ØŗØĒŲØ§Ø¯Ų‡ ÚŠŲ†** ✨. + +Ų‡Øą Ø¯Ųˆ Ų…ØšØ§Ø¯Ų„Ų† ؈ Ø˛ÛŒØą ŲžŲˆØŗØĒŲ‡ ÛŒÚŠÛŒâ€ŒØ§Ų†ØŒ ŲˆŲ„ÛŒ Ų…Ų† `Union` ØąŲˆ Ø¨Ų‡ `Optional` ØĒØąØŦیح Ų…ÛŒâ€ŒØ¯Ų… Ú†ŲˆŲ† ÚŠŲ„Ų…Ų‡ "**ا؎ØĒÛŒØ§ØąÛŒ**" Ø§Ų†Ú¯Ø§Øąæš—į¤ē Ų…ÛŒâ€ŒÚŠŲ†Ų‡ ÚŠŲ‡ Ų…Ų‚Ø¯Ø§Øą ا؎ØĒÛŒØ§ØąÛŒŲ‡ØŒ Ø¯Øą Ø­Ø§Ų„ÛŒ ÚŠŲ‡ Ø¯Øą ŲˆØ§Ų‚Øš ÛŒØšŲ†ÛŒ "Ų…ÛŒâ€ŒØĒŲˆŲ†Ų‡ `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 Ų…ØšØĒØ¨ØąŲ‡ 🎉 +``` + +ØŽØ¨Øą ØŽŲˆØ¨ Ø§ÛŒŲ†Ų‡ ÚŠŲ‡ ŲˆŲ‚ØĒی ØąŲˆ ŲžØ§ÛŒØĒŲˆŲ† 3.10 باشی، Ų„Ø§Ø˛Ų… Ų†ÛŒØŗØĒ Ų†Ú¯ØąØ§Ų† Ø§ÛŒŲ† باشی، Ú†ŲˆŲ† Ų…ÛŒâ€ŒØĒŲˆŲ†ÛŒ Ø¨Ų‡â€ŒØŗØ§Ø¯Ú¯ÛŒ Ø§Ø˛ `|` Ø¨ØąØ§ÛŒ ØĒØšØąÛŒŲ اØĒØ­Ø§Ø¯ÛŒŲ‡ Ų†ŲˆØšâ€ŒŲ‡Ø§ Ø§ØŗØĒŲØ§Ø¯Ų‡ ÚŠŲ†ÛŒ: + +{* ../../docs_src/python_types/tutorial009c_py310.py hl[1,4] *} + +Ø§ŲˆŲ† Ų…ŲˆŲ‚Øš Ø¯ÛŒÚ¯Ų‡ Ų„Ø§Ø˛Ų… Ų†ÛŒØŗØĒ Ų†Ú¯ØąØ§Ų† Ø§ØŗŲ…â€ŒŲ‡Ø§ÛŒÛŒ Ų…ØĢŲ„ `Optional` ؈ `Union` باشی. 😎 + +#### Ų†ŲˆØšâ€ŒŲ‡Ø§ÛŒ ØšŲ…ŲˆŲ…ÛŒ + +Ø§ÛŒŲ† Ų†ŲˆØšâ€ŒŲ‡Ø§ÛŒÛŒ ÚŠŲ‡ ŲžØ§ØąØ§Ų…ØĒØąŲ‡Ø§ÛŒ Ų†ŲˆØš ØąŲˆ ØĒŲˆÛŒ ÚŠØąŲˆØ´Ų‡â€ŒŲ‡Ø§ Ų…ÛŒâ€ŒÚ¯ÛŒØąŲ† Ø¨Ų‡Ø´ŲˆŲ† **Ų†ŲˆØšâ€ŒŲ‡Ø§ÛŒ ØšŲ…ŲˆŲ…ÛŒ** یا **Generics** Ų…ÛŒâ€ŒÚ¯Ų†ØŒ Ų…ØĢŲ„Ø§Ų‹: + +//// tab | Python 3.10+ + +Ų…ÛŒâ€ŒØĒŲˆŲ†ÛŒ Ø§Ø˛ Ų‡Ų…ŲˆŲ† Ų†ŲˆØšâ€ŒŲ‡Ø§ÛŒ Ø¯Ø§ØŽŲ„ÛŒ Ø¨Ų‡â€ŒØšŲ†ŲˆØ§Ų† Ų†ŲˆØšâ€ŒŲ‡Ø§ÛŒ ØšŲ…ŲˆŲ…ÛŒ Ø§ØŗØĒŲØ§Ø¯Ų‡ ÚŠŲ†ÛŒ (با ÚŠØąŲˆØ´Ų‡â€ŒŲ‡Ø§ ؈ Ų†ŲˆØšâ€ŒŲ‡Ø§ Ø¯Ø§ØŽŲ„Ø´ŲˆŲ†): + +* `list` +* `tuple` +* `set` +* `dict` + +؈ Ų‡Ų…ŲˆŲ†â€ŒØˇŲˆØą ÚŠŲ‡ ØĒŲˆÛŒ ŲžØ§ÛŒØĒŲˆŲ† 3.8 Ø¨ŲˆØ¯ØŒ Ø§Ø˛ Ų…Ø§Ú˜ŲˆŲ„ `typing`: + +* `Union` +* `Optional` (Ų‡Ų…ŲˆŲ†â€ŒØˇŲˆØą ÚŠŲ‡ ØĒŲˆÛŒ ŲžØ§ÛŒØĒŲˆŲ† 3.8 Ø¨ŲˆØ¯) +* ...؈ Ø¨Ų‚ÛŒŲ‡. + +ØĒŲˆÛŒ ŲžØ§ÛŒØĒŲˆŲ† 3.10، Ø¨Ų‡â€ŒØšŲ†ŲˆØ§Ų† ØŦØ§ÛŒÚ¯Ø˛ÛŒŲ† Ø¨ØąØ§ÛŒ Ø§ØŗØĒŲØ§Ø¯Ų‡ Ø§Ø˛ Ų†ŲˆØšâ€ŒŲ‡Ø§ÛŒ ØšŲ…ŲˆŲ…ÛŒ `Union` ؈ `Optional`، Ų…ÛŒâ€ŒØĒŲˆŲ†ÛŒ Ø§Ø˛ ØŽØˇ ØšŲ…ŲˆØ¯ÛŒ (`|`) Ø¨ØąØ§ÛŒ ØĒØšØąÛŒŲ اØĒØ­Ø§Ø¯ÛŒŲ‡ Ų†ŲˆØšâ€ŒŲ‡Ø§ Ø§ØŗØĒŲØ§Ø¯Ų‡ ÚŠŲ†ÛŒØŒ ÚŠŲ‡ ØŽÛŒŲ„ÛŒ Ø¨Ų‡ØĒØą ؈ ØŗØ§Ø¯Ų‡â€ŒØĒØąŲ‡. + +//// + +//// tab | Python 3.9+ + +Ų…ÛŒâ€ŒØĒŲˆŲ†ÛŒ Ø§Ø˛ Ų‡Ų…ŲˆŲ† Ų†ŲˆØšâ€ŒŲ‡Ø§ÛŒ Ø¯Ø§ØŽŲ„ÛŒ Ø¨Ų‡â€ŒØšŲ†ŲˆØ§Ų† Ų†ŲˆØšâ€ŒŲ‡Ø§ÛŒ ØšŲ…ŲˆŲ…ÛŒ Ø§ØŗØĒŲØ§Ø¯Ų‡ ÚŠŲ†ÛŒ (با ÚŠØąŲˆØ´Ų‡â€ŒŲ‡Ø§ ؈ Ų†ŲˆØšâ€ŒŲ‡Ø§ Ø¯Ø§ØŽŲ„Ø´ŲˆŲ†): + +* `list` +* `tuple` +* `set` +* `dict` + +؈ Ų‡Ų…ŲˆŲ†â€ŒØˇŲˆØą ÚŠŲ‡ ØĒŲˆÛŒ ŲžØ§ÛŒØĒŲˆŲ† 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] *} + +؈ بؚد، Ø¯ŲˆØ¨Ø§ØąŲ‡ØŒ Ų‡Ų…Ų‡ ŲžØ´ØĒÛŒØ¨Ø§Ų†ÛŒ ŲˆÛŒØąØ§ÛŒØ´Ú¯Øą ØąŲˆ Ø¯Ø§ØąÛŒ: + + + +ØĒ؈ØŦŲ‡ ÚŠŲ† ÚŠŲ‡ Ø§ÛŒŲ† ÛŒØšŲ†ÛŒ "`one_person` ÛŒŲ‡ **Ų†Ų…ŲˆŲ†Ų‡** Ø§Ø˛ ÚŠŲ„Ø§Øŗ `Person` Ų‡ØŗØĒ". + +ÛŒØšŲ†ÛŒ "`one_person` ØŽŲˆØ¯ **ÚŠŲ„Ø§Øŗ** Ø¨Ų‡ Ø§ØŗŲ… `Person` Ų†ÛŒØŗØĒ". + +## Ų…Ø¯Ų„â€ŒŲ‡Ø§ÛŒ Pydantic + +Pydantic ÛŒŲ‡ ÚŠØĒØ§Ø¨ØŽŲˆŲ†Ų‡ ŲžØ§ÛŒØĒŲˆŲ†Ų‡ Ø¨ØąØ§ÛŒ اؚØĒØ¨Ø§ØąØŗŲ†ØŦی Ø¯Ø§Ø¯Ų‡â€ŒŲ‡Ø§. + +"Ø´ÚŠŲ„" Ø¯Ø§Ø¯Ų‡â€ŒŲ‡Ø§ ØąŲˆ Ø¨Ų‡â€ŒØšŲ†ŲˆØ§Ų† ÚŠŲ„Ø§Øŗâ€ŒŲ‡Ø§ÛŒÛŒ با ŲˆÛŒÚ˜Ú¯ÛŒâ€ŒŲ‡Ø§ ØĒØšØąÛŒŲ Ų…ÛŒâ€ŒÚŠŲ†ÛŒ. + +؈ Ų‡Øą ŲˆÛŒÚ˜Ú¯ÛŒ ÛŒŲ‡ Ų†ŲˆØš Ø¯Ø§ØąŲ‡. + +بؚد ÛŒŲ‡ Ų†Ų…ŲˆŲ†Ų‡ Ø§Ø˛ Ø§ŲˆŲ† ÚŠŲ„Ø§Øŗ ØąŲˆ با ÛŒŲ‡ ØŗØąÛŒ Ų…Ų‚Ø¯Ø§Øą Ų…ÛŒâ€ŒØŗØ§Ø˛ÛŒ ؈ Ø§ŲˆŲ† Ų…Ų‚Ø¯Ø§ØąŲ‡Ø§ ØąŲˆ اؚØĒØ¨Ø§ØąØŗŲ†ØŦی Ų…ÛŒâ€ŒÚŠŲ†Ų‡ØŒ Ø¨Ų‡ Ų†ŲˆØš Ų…Ų†Ø§ØŗØ¨ ØĒØ¨Ø¯ÛŒŲ„Ø´ŲˆŲ† Ų…ÛŒâ€ŒÚŠŲ†Ų‡ (Ø§Ú¯Ų‡ Ų„Ø§Ø˛Ų… Ø¨Ø§Ø´Ų‡) ؈ ÛŒŲ‡ Ø´ÛŒØĄ با Ų‡Ų…Ų‡ Ø¯Ø§Ø¯Ų‡â€ŒŲ‡Ø§ Ø¨Ų‡ØĒ Ų…ÛŒâ€ŒØ¯Ų‡. + +؈ با Ø§ŲˆŲ† Ø´ÛŒØĄ Ų†Ų‡Ø§ÛŒÛŒ Ų‡Ų…Ų‡ ŲžØ´ØĒÛŒØ¨Ø§Ų†ÛŒ ŲˆÛŒØąØ§ÛŒØ´Ú¯Øą ØąŲˆ Ų…ÛŒâ€ŒÚ¯ÛŒØąÛŒ. + +ÛŒŲ‡ Ų…ØĢØ§Ų„ Ø§Ø˛ Ų…ØŗØĒŲ†Ø¯Ø§ØĒ ØąØŗŲ…ÛŒ 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، Ų…ØŗØĒŲ†Ø¯Ø§ØĒØ´ ØąŲˆ چک ÚŠŲ†. + +/// + +**FastAPI** ÚŠØ§Ų…Ų„Ø§Ų‹ Ø¨Øą ŲžØ§ÛŒŲ‡ Pydantic Ų‡ØŗØĒ. + +ØĒŲˆÛŒ [ØĸŲ…ŲˆØ˛Ø´ - ØąØ§Ų‡Ų†Ų…Ø§ÛŒ ÚŠØ§ØąØ¨Øą](tutorial/index.md){.internal-link target=_blank} ØŽÛŒŲ„ÛŒ بیشØĒØą Ø§Ø˛ Ø§ÛŒŲ†Ø§ ØąŲˆ ØĒŲˆÛŒ ØšŲ…Ų„ Ų…ÛŒâ€ŒØ¨ÛŒŲ†ÛŒ. + +/// tip + +Pydantic ÛŒŲ‡ ØąŲØĒØ§Øą ؎اØĩ Ø¯Ø§ØąŲ‡ ŲˆŲ‚ØĒی Ø§Ø˛ `Optional` یا `Union[Something, None]` Ø¨Ø¯ŲˆŲ† Ų…Ų‚Ø¯Ø§Øą ŲžÛŒØ´â€ŒŲØąØļ Ø§ØŗØĒŲØ§Ø¯Ų‡ Ų…ÛŒâ€ŒÚŠŲ†ÛŒØŒ Ų…ÛŒâ€ŒØĒŲˆŲ†ÛŒ ØĒŲˆÛŒ Ų…ØŗØĒŲ†Ø¯Ø§ØĒ Pydantic Ø¯Øą Ų…ŲˆØąØ¯ ŲÛŒŲ„Ø¯Ų‡Ø§ÛŒ ا؎ØĒÛŒØ§ØąÛŒ Ų„Ø§Ø˛Ų… بیشØĒØą Ø¨ØŽŲˆŲ†ÛŒ. + +/// + +## Ų†ŲˆØšâ€ŒŲ†Ų…Ø§Ų‡Ø§ با AnnotationŲ‡Ø§ÛŒ Ų…ØĒادیØĒا + +ŲžØ§ÛŒØĒŲˆŲ† ÛŒŲ‡ Ų‚Ø§Ø¨Ų„ÛŒØĒ Ų‡Ų… Ø¯Ø§ØąŲ‡ ÚŠŲ‡ Ø¨Ų‡ØĒ اØŦØ§Ø˛Ų‡ Ų…ÛŒâ€ŒØ¯Ų‡ **Ų…ØĒادیØĒا اØļØ§ŲÛŒ** ØąŲˆ ØĒŲˆÛŒ Ø§ÛŒŲ† Ų†ŲˆØšâ€ŒŲ†Ų…Ø§Ų‡Ø§ Ø¨Ø°Ø§ØąÛŒ با Ø§ØŗØĒŲØ§Ø¯Ų‡ Ø§Ø˛ `Annotated`. + +//// tab | Python 3.9+ + +ØĒŲˆÛŒ ŲžØ§ÛŒØĒŲˆŲ† 3.9، `Annotated` ب؎شی Ø§Ø˛ ÚŠØĒØ§Ø¨ØŽŲˆŲ†Ų‡ Ø§ØŗØĒØ§Ų†Ø¯Ø§ØąØ¯Ų‡ØŒ ŲžØŗ Ų…ÛŒâ€ŒØĒŲˆŲ†ÛŒ Ø§Ø˛ `typing` ŲˆØ§ØąØ¯Ø´ ÚŠŲ†ÛŒ. + +```Python hl_lines="1 4" +{!> ../../docs_src/python_types/tutorial013_py39.py!} +``` + +//// + +//// tab | Python 3.8+ + +ØĒŲˆÛŒ Ų†ØŗØŽŲ‡â€ŒŲ‡Ø§ÛŒ Ø˛ÛŒØą ŲžØ§ÛŒØĒŲˆŲ† 3.9، `Annotated` ØąŲˆ Ø§Ø˛ `typing_extensions` ŲˆØ§ØąØ¯ Ų…ÛŒâ€ŒÚŠŲ†ÛŒ. + +با **FastAPI** Ø§Ø˛ Ų‚Ø¨Ų„ Ų†Øĩب Ø´Ø¯Ų‡. + +```Python hl_lines="1 4" +{!> ../../docs_src/python_types/tutorial013.py!} +``` + +//// + +ØŽŲˆØ¯ ŲžØ§ÛŒØĒŲˆŲ† با Ø§ÛŒŲ† `Annotated` ÚŠØ§ØąÛŒ Ų†Ų…ÛŒâ€ŒÚŠŲ†Ų‡. ؈ Ø¨ØąØ§ÛŒ ŲˆÛŒØąØ§ÛŒØ´Ú¯ØąŲ‡Ø§ ؈ Ø§Ø¨Ø˛Ø§ØąŲ‡Ø§ÛŒ Ø¯ÛŒÚ¯Ų‡ØŒ Ų†ŲˆØš Ų‡Ų†ŲˆØ˛ `str` Ų‡ØŗØĒ. + +ŲˆŲ„ÛŒ Ų…ÛŒâ€ŒØĒŲˆŲ†ÛŒ Ø§Ø˛ Ø§ÛŒŲ† ؁Øļا ØĒŲˆÛŒ `Annotated` Ø§ØŗØĒŲØ§Ø¯Ų‡ ÚŠŲ†ÛŒ ØĒا Ø¨Ų‡ **FastAPI** Ų…ØĒادیØĒای اØļØ§ŲÛŒ Ø¯Øą Ų…ŲˆØąØ¯ Ø§ÛŒŲ†ÚŠŲ‡ Ú†ØˇŲˆØą Ų…ÛŒâ€ŒØŽŲˆØ§ÛŒ Ø¨ØąŲ†Ø§Ų…Ų‡â€ŒØ§ØĒ ØąŲØĒØ§Øą ÚŠŲ†Ų‡ بدی. + +Ų†ÚŠØĒŲ‡ Ų…Ų‡Ų… Ø§ÛŒŲ†Ų‡ ÚŠŲ‡ **Ø§ŲˆŲ„ÛŒŲ† *ŲžØ§ØąØ§Ų…ØĒØą Ų†ŲˆØš*** ÚŠŲ‡ Ø¨Ų‡ `Annotated` Ų…ÛŒâ€ŒØ¯ÛŒØŒ **Ų†ŲˆØš ŲˆØ§Ų‚ØšÛŒ** Ų‡ØŗØĒ. Ø¨Ų‚ÛŒØ´ ŲŲ‚Øˇ Ų…ØĒادیØĒا Ø¨ØąØ§ÛŒ Ø§Ø¨Ø˛Ø§ØąŲ‡Ø§ÛŒ Ø¯ÛŒÚ¯Ų‡â€ŒØŗØĒ. + +Ø§Ų„Ø§Ų† ŲŲ‚Øˇ باید Ø¨Ø¯ŲˆŲ†ÛŒ ÚŠŲ‡ `Annotated` ؈ØŦŲˆØ¯ Ø¯Ø§ØąŲ‡ØŒ ؈ Ø§ÛŒŲ†ÚŠŲ‡ ŲžØ§ÛŒØĒŲˆŲ† Ø§ØŗØĒØ§Ų†Ø¯Ø§ØąØ¯Ų‡. 😎 + +Ø¨ØšØ¯Ø§Ų‹ Ų…ÛŒâ€ŒØ¨ÛŒŲ†ÛŒ ÚŠŲ‡ Ú†Ų‚Ø¯Øą **Ų‚ŲˆÛŒ** Ų…ÛŒâ€ŒØĒŲˆŲ†Ų‡ Ø¨Ø§Ø´Ų‡. + +/// tip + +Ø§ÛŒŲ†ÚŠŲ‡ Ø§ÛŒŲ† **ŲžØ§ÛŒØĒŲˆŲ† Ø§ØŗØĒØ§Ų†Ø¯Ø§ØąØ¯Ų‡** ÛŒØšŲ†ÛŒ Ų‡Ų†ŲˆØ˛ **Ø¨Ų‡ØĒØąÛŒŲ† ØĒØŦØąØ¨Ų‡ ØĒŲˆØŗØšŲ‡â€ŒØ¯Ų‡Ų†Ø¯Ų‡** ØąŲˆ ØĒŲˆÛŒ ŲˆÛŒØąØ§ÛŒØ´Ú¯ØąØĒ، با Ø§Ø¨Ø˛Ø§ØąŲ‡Ø§ÛŒÛŒ ÚŠŲ‡ Ø¨ØąØ§ÛŒ ØĒØ­Ų„ÛŒŲ„ ؈ Ø¨Ø§Ø˛ØŗØ§Ø˛ÛŒ ڊدØĒ Ø§ØŗØĒŲØ§Ø¯Ų‡ Ų…ÛŒâ€ŒÚŠŲ†ÛŒ ؈ ØēÛŒØąŲ‡ Ų…ÛŒâ€ŒÚ¯ÛŒØąÛŒ. ✨ + +؈ Ų‡Ų…ÛŒŲ†â€ŒØˇŲˆØą ڊدØĒ با ØŽÛŒŲ„ÛŒ Ø§Ø˛ Ø§Ø¨Ø˛Ø§ØąŲ‡Ø§ ؈ ÚŠØĒØ§Ø¨ØŽŲˆŲ†Ų‡â€ŒŲ‡Ø§ÛŒ Ø¯ÛŒÚ¯Ų‡ ŲžØ§ÛŒØĒŲˆŲ† ØŽÛŒŲ„ÛŒ ØŗØ§Ø˛Ú¯Ø§Øą Ų…ÛŒâ€ŒŲ…ŲˆŲ†Ų‡. 🚀 + +/// + +## Ų†ŲˆØšâ€ŒŲ†Ų…Ø§Ų‡Ø§ ØĒŲˆÛŒ **FastAPI** + +**FastAPI** Ø§Ø˛ Ø§ÛŒŲ† Ų†ŲˆØšâ€ŒŲ†Ų…Ø§Ų‡Ø§ Ø§ØŗØĒŲØ§Ø¯Ų‡ Ų…ÛŒâ€ŒÚŠŲ†Ų‡ ØĒا Ú†Ų†Ø¯ ØĒا ÚŠØ§Øą Ø¨ÚŠŲ†Ų‡. + +با **FastAPI** ŲžØ§ØąØ§Ų…ØĒØąŲ‡Ø§ ØąŲˆ با Ų†ŲˆØšâ€ŒŲ†Ų…Ø§Ų‡Ø§ ØĒØšØąÛŒŲ Ų…ÛŒâ€ŒÚŠŲ†ÛŒ ؈ Ø§ÛŒŲ†Ø§ ØąŲˆ Ų…ÛŒâ€ŒÚ¯ÛŒØąÛŒ: + +* **ŲžØ´ØĒÛŒØ¨Ø§Ų†ÛŒ ŲˆÛŒØąØ§ÛŒØ´Ú¯Øą**. +* **چک Ų†ŲˆØšâ€ŒŲ‡Ø§**. + +...؈ **FastAPI** Ø§Ø˛ Ų‡Ų…ŲˆŲ† ØĒØšØąÛŒŲâ€ŒŲ‡Ø§ Ø¨ØąØ§ÛŒ Ø§ÛŒŲ†Ø§ Ø§ØŗØĒŲØ§Ø¯Ų‡ Ų…ÛŒâ€ŒÚŠŲ†Ų‡: + +* **ØĒØšØąÛŒŲ Ų†ÛŒØ§Ø˛Ų‡Ø§**: Ø§Ø˛ ŲžØ§ØąØ§Ų…ØĒØąŲ‡Ø§ÛŒ Ų…ØŗÛŒØą Ø¯ØąØŽŲˆØ§ØŗØĒ، ŲžØ§ØąØ§Ų…ØĒØąŲ‡Ø§ÛŒ ÚŠŲˆØĻØąÛŒØŒ Ų‡Ø¯ØąŲ‡Ø§ØŒ Ø¨Ø¯Ų†Ų‡â€ŒŲ‡Ø§ØŒ ŲˆØ§Ø¨ØŗØĒÚ¯ÛŒâ€ŒŲ‡Ø§ ؈ ØēÛŒØąŲ‡. +* **ØĒØ¨Ø¯ÛŒŲ„ Ø¯Ø§Ø¯Ų‡**: Ø§Ø˛ Ø¯ØąØŽŲˆØ§ØŗØĒ Ø¨Ų‡ Ų†ŲˆØš Ų…ŲˆØąØ¯ Ų†ÛŒØ§Ø˛. +* **اؚØĒØ¨Ø§ØąØŗŲ†ØŦی Ø¯Ø§Ø¯Ų‡**: ÚŠŲ‡ Ø§Ø˛ Ų‡Øą Ø¯ØąØŽŲˆØ§ØŗØĒ Ų…ÛŒØ§Ø¯: + * ØĒŲˆŲ„ÛŒØ¯ **ØŽØˇØ§Ų‡Ø§ÛŒ ØŽŲˆØ¯ÚŠØ§Øą** ÚŠŲ‡ Ø¨Ų‡ ÚŠŲ„Ø§ÛŒŲ†ØĒ Ø¨ØąŲ…ÛŒâ€ŒÚ¯ØąØ¯Ų‡ ŲˆŲ‚ØĒی Ø¯Ø§Ø¯Ų‡ Ų†Ø§Ų…ØšØĒØ¨ØąŲ‡. +* **Ų…ØŗØĒŲ†Ø¯ØŗØ§Ø˛ÛŒ** API با Ø§ØŗØĒŲØ§Ø¯Ų‡ Ø§Ø˛ OpenAPI: + * ÚŠŲ‡ بؚدش ØĒŲˆØŗØˇ ØąØ§Ø¨Øˇâ€ŒŲ‡Ø§ÛŒ ÚŠØ§ØąØ¨ØąÛŒ Ų…ØŗØĒŲ†Ø¯Ø§ØĒ ØĒØšØ§Ų…Ų„ÛŒ ØŽŲˆØ¯ÚŠØ§Øą Ø§ØŗØĒŲØ§Ø¯Ų‡ Ų…ÛŒâ€ŒØ´Ų‡. + +Ø§ÛŒŲ†Ø§ شاید Ų‡Ų…Ų‡â€ŒØ´ Ø§Ų†ØĒØ˛Ø§ØšÛŒ Ø¨Ų‡ Ų†Ø¸Øą بیاد. Ų†Ú¯ØąØ§Ų† Ų†Ø¨Ø§Ø´. Ų‡Ų…Ų‡ Ø§ÛŒŲ†Ø§ ØąŲˆ ØĒŲˆÛŒ ØšŲ…Ų„ ØĒŲˆÛŒ [ØĸŲ…ŲˆØ˛Ø´ - ØąØ§Ų‡Ų†Ų…Ø§ÛŒ ÚŠØ§ØąØ¨Øą](tutorial/index.md){.internal-link target=_blank} Ų…ÛŒâ€ŒØ¨ÛŒŲ†ÛŒ. + +Ų†ÚŠØĒŲ‡ Ų…Ų‡Ų… Ø§ÛŒŲ†Ų‡ ÚŠŲ‡ با Ø§ØŗØĒŲØ§Ø¯Ų‡ Ø§Ø˛ Ų†ŲˆØšâ€ŒŲ‡Ø§ÛŒ Ø§ØŗØĒØ§Ų†Ø¯Ø§ØąØ¯ ŲžØ§ÛŒØĒŲˆŲ†ØŒ ØĒŲˆÛŒ ÛŒŲ‡ ØŦا (Ø¨Ų‡ ØŦای اØļØ§ŲŲ‡ ÚŠØąØ¯Ų† ÚŠŲ„Ø§Øŗâ€ŒŲ‡Ø§ÛŒ بیشØĒØąØŒ Ø¯ÚŠŲˆØąØ§ØĒŲˆØąŲ‡Ø§ ؈ ØēÛŒØąŲ‡)، **FastAPI** ÚŠŲ„ÛŒ Ø§Ø˛ ÚŠØ§Øą ØąŲˆ Ø¨ØąØ§ØĒ Ø§Ų†ØŦØ§Ų… Ų…ÛŒâ€ŒØ¯Ų‡. + +/// info + +Ø§Ú¯Ų‡ Ų‡Ų…Ų‡ ØĸŲ…ŲˆØ˛Ø´ ØąŲˆ Ú¯Ø°ØąŲˆŲ†Ø¯ÛŒ ؈ Ø¨ØąÚ¯Ø´ØĒی ÚŠŲ‡ بیشØĒØą Ø¯Øą Ų…ŲˆØąØ¯ Ų†ŲˆØšâ€ŒŲ‡Ø§ Ø¨Ø¨ÛŒŲ†ÛŒØŒ ÛŒŲ‡ Ų…Ų†Ø¨Øš ØŽŲˆØ¨ "ØĒŲ‚Ų„Ø¨â€ŒŲ†Ø§Ų…Ų‡" Ø§Ø˛ `mypy` Ų‡ØŗØĒ. + +/// diff --git a/docs/fr/docs/index.md b/docs/fr/docs/index.md index 695429008..d25f7a939 100644 --- a/docs/fr/docs/index.md +++ b/docs/fr/docs/index.md @@ -12,7 +12,7 @@

- Test + Test Coverage diff --git a/docs/he/docs/index.md b/docs/he/docs/index.md index 6498d15e1..bd166f205 100644 --- a/docs/he/docs/index.md +++ b/docs/he/docs/index.md @@ -12,10 +12,10 @@

- Test + Test - - Coverage + + Coverage Package version diff --git a/docs/hu/docs/index.md b/docs/hu/docs/index.md index c6f596650..45ff49c3b 100644 --- a/docs/hu/docs/index.md +++ b/docs/hu/docs/index.md @@ -6,7 +6,7 @@

- Test + Test Coverage diff --git a/docs/id/docs/index.md b/docs/id/docs/index.md index 7fdd1cc7a..5fb0c4c9c 100644 --- a/docs/id/docs/index.md +++ b/docs/id/docs/index.md @@ -12,7 +12,7 @@

- Test + Test Coverage diff --git a/docs/it/docs/index.md b/docs/it/docs/index.md index 8a1039bc5..dc8f5b846 100644 --- a/docs/it/docs/index.md +++ b/docs/it/docs/index.md @@ -4,15 +4,19 @@

FastAPI framework, alte prestazioni, facile da imparare, rapido da implementare, pronto per il rilascio in produzione

+

- - Build Status + + Test + + + Coverage - - Coverage + + Package version - Package version + Supported Python versions

diff --git a/docs/ja/docs/deployment/concepts.md b/docs/ja/docs/deployment/concepts.md index c6b21fd1b..a0d4fb35b 100644 --- a/docs/ja/docs/deployment/concepts.md +++ b/docs/ja/docs/deployment/concepts.md @@ -219,7 +219,7 @@ FastAPI ã‚ĸプãƒĒã‚ąãƒŧã‚ˇãƒ§ãƒŗã§ã¯ã€Uvicorn ぎようãĒã‚ĩãƒŧバãƒŧプロ これらぎワãƒŧã‚Ģãƒŧãƒģプロã‚ģ゚は、ã‚ĸプãƒĒã‚ąãƒŧã‚ˇãƒ§ãƒŗã‚’åŽŸčĄŒã™ã‚‹ã‚‚ãŽã§ã‚ã‚Šã€**ãƒĒクエ゚ト**を受けãĻ**ãƒŦã‚šãƒãƒŗã‚š**をčŋ”すためぎä¸ģčρãĒč¨ˆįŽ—ã‚’čĄŒã„ã€ã‚ãĒたが変数ãĢå…ĨれたもぎはäŊ•でもRAMãĢロãƒŧドしぞす。 - + そしãĻã‚‚ãĄã‚ã‚“ã€åŒã˜ãƒžã‚ˇãƒŗã§ã¯ã€ã‚ãĒたぎã‚ĸプãƒĒã‚ąãƒŧã‚ˇãƒ§ãƒŗã¨ã¯åˆĨãĢ、**äģ–ぎプロã‚ģ゚**ã‚‚åŽŸčĄŒã•ã‚ŒãĻいるでしょう。 diff --git a/docs/ja/docs/deployment/https.md b/docs/ja/docs/deployment/https.md index ac40b0982..7b0f567aa 100644 --- a/docs/ja/docs/deployment/https.md +++ b/docs/ja/docs/deployment/https.md @@ -92,7 +92,7 @@ DNSã‚ĩãƒŧバãƒŧでは、**å–åž—ã—ãŸãƒ‰ãƒĄã‚¤ãƒŗ**をあãĒたぎã‚ĩãƒŧバãƒŧ DNSã‚ĩãƒŧバãƒŧは、ブナã‚Ļã‚ļãĢį‰šåŽšãŽ**IPã‚ĸドãƒŦ゚**をäŊŋį”¨ã™ã‚‹ã‚ˆã†ãĢ指į¤ēしぞす。こぎIPã‚ĸドãƒŦ゚は、DNSã‚ĩãƒŧバãƒŧã§č¨­åŽšã—ãŸã€ã‚ãĒたぎã‚ĩãƒŧバãƒŧがäŊŋį”¨ã™ã‚‹ãƒ‘ãƒ–ãƒĒックIPã‚ĸドãƒŦ゚ãĢãĒりぞす。 - + ### TLS Handshake ぎ開始 @@ -100,7 +100,7 @@ DNSã‚ĩãƒŧバãƒŧは、ブナã‚Ļã‚ļãĢį‰šåŽšãŽ**IPã‚ĸドãƒŦ゚**をäŊŋį”¨ã™ã‚‹ 通äŋĄãŽæœ€åˆãŽéƒ¨åˆ†ã¯ã€ã‚¯ãƒŠã‚¤ã‚ĸãƒŗãƒˆã¨ã‚ĩãƒŧバãƒŧ間ぎæŽĨįļšã‚’įĸēįĢ‹ã—ã€äŊŋį”¨ã™ã‚‹æš—åˇéĩãĒおをæąēめるだけです。 - + TLSæŽĨįļšã‚’įĸēįĢ‹ã™ã‚‹ãŸã‚ãŽã‚¯ãƒŠã‚¤ã‚ĸãƒŗãƒˆã¨ã‚ĩãƒŧバãƒŧ間ぎこぎやりとりは、**TLSãƒãƒŗãƒ‰ã‚ˇã‚§ã‚¤ã‚¯**とå‘ŧばれぞす。 @@ -120,7 +120,7 @@ TLS Termination Proxyは、1つäģĨ上ぎ**TLSč¨ŧ明書**īŧˆHTTPSč¨ŧ明書īŧ‰ãĢ äģŠå›žã¯ã€`someapp.example.com`ぎč¨ŧ明書をäŊŋうことãĢãĒりぞす。 - + クナイã‚ĸãƒŗãƒˆã¯ã€ããŽTLSč¨ŧæ˜Žæ›¸ã‚’į”Ÿæˆã—ãŸã‚¨ãƒŗãƒ†ã‚Ŗãƒ†ã‚Ŗīŧˆã“ぎ場合はLet's Encryptですが、これãĢついãĻは垌čŋ°ã—ぞすīŧ‰ã‚’すでãĢ**äŋĄé ŧ**しãĻいるため、そぎč¨ŧ明書が有劚であることを**検č¨ŧ**することができぞす。 @@ -142,19 +142,19 @@ TLS Termination Proxyは、1つäģĨ上ぎ**TLSč¨ŧ明書**īŧˆHTTPSč¨ŧ明書īŧ‰ãĢ そこで、クナイã‚ĸãƒŗãƒˆã¯**HTTPSãƒĒクエ゚ト**を送äŋĄã—ãžã™ã€‚ã“ã‚Œã¯ã€æš—åˇåŒ–ã•ã‚ŒãŸTLSã‚ŗãƒã‚¯ã‚ˇãƒ§ãƒŗã‚’äģ‹ã—た単ãĒるHTTPãƒĒクエ゚トです。 - + ### ãƒĒã‚¯ã‚¨ã‚šãƒˆãŽåžŠåˇåŒ– TLS Termination Proxy は、合意が取れãĻã„ã‚‹æš—åˇåŒ–ã‚’äŊŋį”¨ã—ãĻ、**ãƒĒã‚¯ã‚¨ã‚šãƒˆã‚’åžŠåˇåŒ–**し、**プãƒŦãƒŧãƒŗ (åžŠåˇåŒ–ã•ã‚ŒãŸ) HTTP ãƒĒクエ゚ト** をã‚ĸプãƒĒã‚ąãƒŧã‚ˇãƒ§ãƒŗã‚’åŽŸčĄŒã—ãĻいるプロã‚ģ゚ (䞋えば、FastAPI ã‚ĸプãƒĒã‚ąãƒŧã‚ˇãƒ§ãƒŗã‚’åŽŸčĄŒã—ãĻいる Uvicorn を持つプロã‚ģ゚) ãĢ送äŋĄã—ぞす。 - + ### HTTP ãƒŦã‚šãƒãƒŗã‚š ã‚ĸプãƒĒã‚ąãƒŧã‚ˇãƒ§ãƒŗã¯ãƒĒクエ゚トをå‡Ļį†ã—ã€**プãƒŦãƒŧãƒŗ(æš—åˇåŒ–ã•ã‚ŒãĻいãĒい)HTTPãƒŦã‚šãƒãƒŗã‚š** をTLS Termination ProxyãĢ送äŋĄã—ぞす。 - + ### HTTPS ãƒŦã‚šãƒãƒŗã‚š @@ -162,7 +162,7 @@ TLS Termination ProxyはæŦĄãĢ、äē‹å‰ãĢ合意が取れãĻã„ã‚‹æš—åˇ(`someap そぎ垌ブナã‚Ļã‚ļでは、ãƒŦã‚šãƒãƒŗã‚šãŒæœ‰åŠšã§æ­Ŗã—ã„æš—åˇã‚­ãƒŧã§æš—åˇåŒ–ã•ã‚ŒãĻいることãĒおを検č¨ŧしぞす。そしãĻ、ブナã‚Ļã‚ļはãƒŦã‚šãƒãƒŗã‚šã‚’**åžŠåˇåŒ–**しãĻå‡Ļį†ã—ãžã™ã€‚ - + クナイã‚ĸãƒŗãƒˆīŧˆãƒ–ナã‚Ļã‚ļīŧ‰ã¯ã€ãƒŦã‚šãƒãƒŗã‚šãŒæ­Ŗã—ã„ã‚ĩãƒŧバãƒŧからæĨたことをįŸĨることができぞす。 ãĒぜãĒら、そぎã‚ĩãƒŧバãƒŧは、äģĨ前ãĢ**HTTPSč¨ŧ明書**をäŊŋãŖãĻåˆæ„ã—ãŸæš—åˇã‚’äŊŋãŖãĻいるからです。 @@ -172,7 +172,7 @@ TLS Termination ProxyはæŦĄãĢ、äē‹å‰ãĢ合意が取れãĻã„ã‚‹æš—åˇ(`someap į‰šåŽšãŽIPとポãƒŧトīŧˆã“ぎ䞋ではTLS Termination Proxyīŧ‰ã‚’æ‰ąã†ã“ã¨ãŒã§ãã‚‹ãŽã¯1つぎプロã‚ģ゚だけですが、äģ–ぎã‚ĸプãƒĒã‚ąãƒŧã‚ˇãƒ§ãƒŗ/プロã‚ģ゚も、同じ**パブãƒĒックIPとポãƒŧト**ぎįĩ„ãŋ合わせをäŊŋį”¨ã—ã‚ˆã†ã¨ã—ãĒい限り、ã‚ĩãƒŧバãƒŧä¸Šã§åŽŸčĄŒã™ã‚‹ã“ã¨ãŒã§ããžã™ã€‚ - + そうすれば、TLS Termination Proxy は、**č¤‡æ•°ãŽãƒ‰ãƒĄã‚¤ãƒŗ**ã‚„č¤‡æ•°ãŽã‚ĸプãƒĒã‚ąãƒŧã‚ˇãƒ§ãƒŗãŽHTTPSとč¨ŧ明書をå‡Ļį†ã—ã€ãã‚Œãžã‚ŒãŽã‚ąãƒŧ゚で遊切ãĒã‚ĸプãƒĒã‚ąãƒŧã‚ˇãƒ§ãƒŗãĢãƒĒクエ゚トを送äŋĄã™ã‚‹ã“とができぞす。 @@ -182,7 +182,7 @@ TLS Termination ProxyはæŦĄãĢ、äē‹å‰ãĢ合意が取れãĻã„ã‚‹æš—åˇ(`someap そぎ垌、Let's Encryptと通äŋĄã™ã‚‹åˆĨぎプログナムīŧˆåˆĨぎプログナムである場合もあれば、同じTLS Termination Proxyである場合もあるīŧ‰ãĢã‚ˆãŖãĻ、č¨ŧ明書を更新しぞす。 - + **TLSč¨ŧ明書**は、IPã‚ĸドãƒŦ゚ではãĒく、**ãƒ‰ãƒĄã‚¤ãƒŗåãĢé–ĸ逪äģ˜ã‘られãĻ**いぞす。 diff --git a/docs/ja/docs/index.md b/docs/ja/docs/index.md index 682c94e83..1ba85f8e0 100644 --- a/docs/ja/docs/index.md +++ b/docs/ja/docs/index.md @@ -11,14 +11,17 @@ FastAPI framework, high performance, easy to learn, fast to code, ready for production

- - Build Status + + Test - - Coverage + + Coverage - Package version + Package version + + + Supported Python versions

diff --git a/docs/ja/docs/tutorial/body-fields.md b/docs/ja/docs/tutorial/body-fields.md index 0466320f1..ce5630351 100644 --- a/docs/ja/docs/tutorial/body-fields.md +++ b/docs/ja/docs/tutorial/body-fields.md @@ -44,7 +44,7 @@ čŋŊåŠ æƒ…å ąã¯`Field`や`Query`、`Body`ãĒãŠã§åŽŖč¨€ã™ã‚‹ã“ã¨ãŒã§ããžã™ã€‚ãã—ãĻãã‚Œã¯į”Ÿæˆã•ã‚ŒãŸJSON゚キãƒŧマãĢåĢぞれぞす。 -垌ãĢäž‹ã‚’į”¨ã„ãĻåŽŖč¨€ã‚’å­Ļãļ際ãĢ、čŋŊåŠ æƒ…å ąã‚’åĨæ‚Ēæ–šæŗ•ã‚’å­Ļずぞす。 +垌ãĢäž‹ã‚’į”¨ã„ãĻåŽŖč¨€ã‚’å­Ļãļ際ãĢ、čŋŊåŠ æƒ…å ąã‚’čŋŊåŠ ã™ã‚‹æ–šæŗ•ã‚’å­Ļずぞす。 ## ぞとめ diff --git a/docs/ja/docs/tutorial/body.md b/docs/ja/docs/tutorial/body.md index 8376959d5..1298eec7e 100644 --- a/docs/ja/docs/tutorial/body.md +++ b/docs/ja/docs/tutorial/body.md @@ -22,7 +22,7 @@ GET ãƒĒã‚¯ã‚¨ã‚šãƒˆã§ãƒœãƒ‡ã‚Ŗã‚’é€äŋĄã™ã‚‹ã“とは、ä앿§˜ã§ã¯æœĒåŽšįžŠ ぞす初めãĢ、 `pydantic` から `BaseModel` ã‚’ã‚¤ãƒŗãƒãƒŧトするåŋ…čĻãŒã‚ã‚Šãžã™: -{* ../../docs_src/body/tutorial001.py hl[2] *} +{* ../../docs_src/body/tutorial001.py hl[4] *} ## デãƒŧã‚ŋãƒĸデãƒĢぎäŊœæˆ @@ -30,7 +30,7 @@ GET ãƒĒã‚¯ã‚¨ã‚šãƒˆã§ãƒœãƒ‡ã‚Ŗã‚’é€äŋĄã™ã‚‹ã“とは、ä앿§˜ã§ã¯æœĒåŽšįžŠ すずãĻãŽåąžæ€§ãĢpython標æē–ぎ型をäŊŋį”¨ã—ãžã™: -{* ../../docs_src/body/tutorial001.py hl[5:9] *} +{* ../../docs_src/body/tutorial001.py hl[7:11] *} クエãƒĒãƒ‘ãƒŠãƒĄãƒŧã‚ŋãŽåŽŖč¨€ã¨åŒæ§˜ãĢ、ãƒĸデãƒĢåąžæ€§ãŒãƒ‡ãƒ•ã‚ŠãƒĢト値をもつとき、åŋ…é ˆãĒåąžæ€§ã§ã¯ãĒくãĒりぞす。それäģĨ外はåŋ…é ˆãĢãĒりぞす。ã‚Ēãƒ—ã‚ˇãƒ§ãƒŠãƒĢãĒåąžæ€§ãĢしたい場合は `None` をäŊŋį”¨ã—ãĻください。 @@ -58,7 +58,7 @@ GET ãƒĒã‚¯ã‚¨ã‚šãƒˆã§ãƒœãƒ‡ã‚Ŗã‚’é€äŋĄã™ã‚‹ã“とは、ä앿§˜ã§ã¯æœĒåŽšįžŠ *パ゚ã‚ĒペãƒŦãƒŧã‚ˇãƒ§ãƒŗ* ãĢ加えるためãĢã€ãƒ‘ã‚šãƒ‘ãƒŠãƒĄãƒŧã‚ŋやクエãƒĒãƒ‘ãƒŠãƒĄãƒŧã‚ŋと同じ様ãĢåŽŖč¨€ã—ãžã™: -{* ../../docs_src/body/tutorial001.py hl[16] *} +{* ../../docs_src/body/tutorial001.py hl[18] *} ...そしãĻ、äŊœæˆã—たãƒĸデãƒĢ `Item` ã§åž‹ã‚’åŽŖč¨€ã—ãžã™ã€‚ @@ -125,7 +125,7 @@ GET ãƒĒã‚¯ã‚¨ã‚šãƒˆã§ãƒœãƒ‡ã‚Ŗã‚’é€äŋĄã™ã‚‹ã“とは、ä앿§˜ã§ã¯æœĒåŽšįžŠ é–ĸ数内部で、ãƒĸデãƒĢぎ全ãĻãŽåąžæ€§ãĢį›´æŽĨã‚ĸクã‚ģ゚できぞす: -{* ../../docs_src/body/tutorial002.py hl[19] *} +{* ../../docs_src/body/tutorial002.py hl[21] *} ## ãƒĒã‚¯ã‚¨ã‚šãƒˆãƒœãƒ‡ã‚Ŗ + ãƒ‘ã‚šãƒ‘ãƒŠãƒĄãƒŧã‚ŋ @@ -133,7 +133,7 @@ GET ãƒĒã‚¯ã‚¨ã‚šãƒˆã§ãƒœãƒ‡ã‚Ŗã‚’é€äŋĄã™ã‚‹ã“とは、ä앿§˜ã§ã¯æœĒåŽšįžŠ **FastAPI** ã¯ãƒ‘ã‚šãƒ‘ãƒŠãƒĄãƒŧã‚ŋであるé–ĸæ•°ãƒ‘ãƒŠãƒĄãƒŧã‚ŋは**パ゚から受け取り**、PydanticãƒĸデãƒĢãĢã‚ˆãŖãĻåŽŖč¨€ã•ã‚ŒãŸé–ĸæ•°ãƒ‘ãƒŠãƒĄãƒŧã‚ŋは**ãƒĒã‚¯ã‚¨ã‚šãƒˆãƒœãƒ‡ã‚Ŗã‹ã‚‰å—ã‘å–ã‚‹**ということをčĒč­˜ã—ãžã™ã€‚ -{* ../../docs_src/body/tutorial003.py hl[15:16] *} +{* ../../docs_src/body/tutorial003.py hl[17:18] *} ## ãƒĒã‚¯ã‚¨ã‚šãƒˆãƒœãƒ‡ã‚Ŗ + ãƒ‘ã‚šãƒ‘ãƒŠãƒĄãƒŧã‚ŋ + クエãƒĒãƒ‘ãƒŠãƒĄãƒŧã‚ŋ @@ -141,7 +141,7 @@ GET ãƒĒã‚¯ã‚¨ã‚šãƒˆã§ãƒœãƒ‡ã‚Ŗã‚’é€äŋĄã™ã‚‹ã“とは、ä앿§˜ã§ã¯æœĒåŽšįžŠ **FastAPI** はそれぞれをčĒč­˜ã—ã€éŠåˆ‡ãĒ場所からデãƒŧã‚ŋを取垗しぞす。 -{* ../../docs_src/body/tutorial004.py hl[16] *} +{* ../../docs_src/body/tutorial004.py hl[18] *} é–ĸæ•°ãƒ‘ãƒŠãƒĄãƒŧã‚ŋはäģĨ下ぎ様ãĢčĒč­˜ã•ã‚Œãžã™: diff --git a/docs/ja/docs/tutorial/cookie-param-models.md b/docs/ja/docs/tutorial/cookie-param-models.md new file mode 100644 index 000000000..8285f44ef --- /dev/null +++ b/docs/ja/docs/tutorial/cookie-param-models.md @@ -0,0 +1,77 @@ +# クッキãƒŧãƒ‘ãƒŠãƒĄãƒŧã‚ŋãƒĸデãƒĢ + +もしé–ĸé€Ŗã™ã‚‹**č¤‡æ•°ãŽã‚¯ãƒƒã‚­ãƒŧ**から成るグãƒĢãƒŧプがあるãĒã‚‰ã€ãã‚Œã‚‰ã‚’åŽŖč¨€ã™ã‚‹ãŸã‚ãĢ、**PydanticãƒĸデãƒĢ**をäŊœæˆã§ããžã™ã€‚đŸĒ + +こうすることで、**č¤‡æ•°ãŽå ´æ‰€**で**そぎPydanticãƒĸデãƒĢã‚’å†åˆŠį”¨**でき、バãƒĒデãƒŧã‚ˇãƒ§ãƒŗã‚„ãƒĄã‚ŋデãƒŧã‚ŋを、すずãĻぎクッキãƒŧãƒ‘ãƒŠãƒĄãƒŧã‚ŋãĢ寞しãĻ一åēĻãĢåŽŖč¨€ã§ããžã™ã€‚đŸ˜Ž + +/// note | å‚™č€ƒ + +こぎ抟čƒŊは、FastAPIぎバãƒŧã‚¸ãƒ§ãƒŗ `0.115.0` からã‚ĩポãƒŧトされãĻã„ãžã™ã€‚đŸ¤“ + +/// + +/// tip | 豆įŸĨ識 + +これと同じテクニックは `Query` 、 `Cookie` 、 `Header` ãĢã‚‚éŠį”¨ã§ããžã™ã€‚ 😎 + +/// + +## クッキãƒŧãĢPydanticãƒĸデãƒĢをäŊŋį”¨ã™ã‚‹ + +åŋ…čρãĒč¤‡æ•°ãŽ**クッキãƒŧ**ãƒ‘ãƒŠãƒĄãƒŧã‚ŋを**PydanticãƒĸデãƒĢ**ã§åŽŖč¨€ã—ã€ã•ã‚‰ãĢ、それを `Cookie` としãĻåŽŖč¨€ã—ãžã—ã‚‡ã†: + +{* ../../docs_src/cookie_param_models/tutorial001_an_py310.py hl[9:12,16] *} + +**FastAPI**は、ãƒĒクエ゚トぎ**クッキãƒŧ**から**ãã‚Œãžã‚ŒãŽãƒ•ã‚ŖãƒŧãƒĢド**ぎデãƒŧã‚ŋを**æŠŊå‡ē**ã—ã€åŽšįžŠã•ã‚ŒãŸ**PydanticãƒĸデãƒĢ**を提䞛しぞす。 + +## ドキãƒĨãƒĄãƒŗãƒˆãŽįĸēčĒ + +å¯žčŠąįš„APIドキãƒĨãƒĄãƒŗãƒˆUI `/docs` ã§ã€åŽšįžŠã•ã‚ŒãĻいるクッキãƒŧをįĸēčĒã§ããžã™: + +
+ +
+ +/// info | å‚™č€ƒ + + +**ブナã‚Ļã‚ļがクッキãƒŧをå‡Ļį†ã—**ãĻã„ãžã™ãŒã€į‰šåˆĨãĒæ–šæŗ•ã§å†…éƒ¨įš„ãĢå‡Ļį†ã‚’čĄŒãŖãĻいるためãĢ、**JavaScript**ã‹ã‚‰ã¯į°Ąå˜ãĢ操äŊœ**できãĒい**ことãĢį•™æ„ã—ãĻください。 + +**å¯žčŠąįš„APIドキãƒĨãƒĄãƒŗãƒˆUI** `/docs` ãĢã‚ĸクã‚ģ゚すれば、*パ゚ã‚ĒペãƒŦãƒŧã‚ˇãƒ§ãƒŗ*ãĢé–ĸするクッキãƒŧぎ**ドキãƒĨãƒĄãƒŗãƒ†ãƒŧã‚ˇãƒ§ãƒŗ**をįĸēčĒã§ããžã™ã€‚ + +しかし、たとえ**クッキãƒŧデãƒŧã‚ŋをå…Ĩ力しãĻ**「Execute」をクãƒĒックしãĻã‚‚ã€å¯žčŠąįš„APIドキãƒĨãƒĄãƒŗãƒˆUIは**JavaScript**で動äŊœã—ãĻいるためクッキãƒŧは送äŋĄã•れず、ぞるで値をå…Ĩ力しãĒã‹ãŖãŸã‹ãŽã‚ˆã†ãĒ**エナãƒŧ**ãƒĄãƒƒã‚ģãƒŧã‚¸ãŒčĄ¨į¤ēされぞす。 + +/// + +## äŊ™åˆ†ãĒクッキãƒŧをįρæ­ĸする + +į‰šåŽšãŽīŧˆã‚ぞり一čˆŦįš„ã§ã¯ãĒいかもしれãĒいīŧ‰ã‚ąãƒŧ゚で、受けäģ˜ã‘るクッキãƒŧを**åˆļ限**するåŋ…čĻãŒã‚ã‚‹ã‹ã‚‚ã—ã‚Œãžã›ã‚“ã€‚ + +あãĒたぎAPIはį‹Ŧč‡Ēぎ クッキãƒŧ同意 ã‚’įŽĄį†ã™ã‚‹čƒŊåŠ›ã‚’æŒãŖãĻいぞす。 đŸ¤ĒđŸĒ + +PydanticぎãƒĸデãƒĢぎ Configuration ã‚’åˆŠį”¨ã—ãĻ、 `extra` ãƒ•ã‚ŖãƒŧãƒĢドを `forbid` とすることができぞす。 + +{* ../../docs_src/cookie_param_models/tutorial002_an_py39.py hl[10] *} + +もしクナイã‚ĸãƒŗãƒˆãŒ**äŊ™åˆ†ãĒクッキãƒŧ**を送ろうとすると、**エナãƒŧ**ãƒŦã‚šãƒãƒŗã‚šãŒčŋ”されぞす。 + +おうせAPIãĢ拒åĻされるぎãĢあãĒãŸãŽåŒæ„ã‚’åž—ã‚ˆã†ã¨į˛žä¸€æ¯åŠĒåŠ›ã™ã‚‹å¯å“€æƒŗãĒクッキãƒŧバナãƒŧãŸãĄ... đŸĒ + +䞋えば、クナイã‚ĸãƒŗãƒˆãŒã‚¯ãƒƒã‚­ãƒŧ `santa_tracker` を `good-list-please` という値で送ろうとすると、`santa_tracker` という クッキãƒŧãŒč¨ąå¯ã•ã‚ŒãĻいãĒい ことを通įŸĨする**エナãƒŧ**ãƒŦã‚šãƒãƒŗã‚šãŒčŋ”されぞす: + +```json +{ + "detail": [ + { + "type": "extra_forbidden", + "loc": ["cookie", "santa_tracker"], + "msg": "Extra inputs are not permitted", + "input": "good-list-please", + } + ] +} +``` + +## ぞとめ + +**FastAPI**では、**クッキãƒŧ**ã‚’åŽŖč¨€ã™ã‚‹ãŸã‚ãĢ、**PydanticãƒĸデãƒĢ**をäŊŋį”¨ã§ããžã™ã€‚đŸ˜Ž diff --git a/docs/ja/docs/tutorial/encoder.md b/docs/ja/docs/tutorial/encoder.md index 409ebeec6..309cf8857 100644 --- a/docs/ja/docs/tutorial/encoder.md +++ b/docs/ja/docs/tutorial/encoder.md @@ -8,7 +8,7 @@ ## `jsonable_encoder`ぎäŊŋᔍ -JSONäē’æ›ãŽãƒ‡ãƒŧã‚ŋぎãŋを受äŋĄã™ã‚‹ãƒ‡ãƒŧã‚ŋベãƒŧ゚`fase_db`があるとしぞしょう。 +JSONäē’æ›ãŽãƒ‡ãƒŧã‚ŋぎãŋを受äŋĄã™ã‚‹ãƒ‡ãƒŧã‚ŋベãƒŧ゚`fake_db`があるとしぞしょう。 䞋えば、`datetime`ã‚ĒブジェクトはJSONとäē’æ›æ€§ãŒãĒいぎで、こぎデãƒŧã‚ŋãƒŧベãƒŧ゚ãĢは受け取られぞせん。 diff --git a/docs/ja/docs/tutorial/handling-errors.md b/docs/ja/docs/tutorial/handling-errors.md index 9a46cc738..37315b087 100644 --- a/docs/ja/docs/tutorial/handling-errors.md +++ b/docs/ja/docs/tutorial/handling-errors.md @@ -63,7 +63,7 @@ Pythonぎ䞋外ãĒぎで、`return`ではãĒく、`raise`です。 `HTTPException`をį™ēį”Ÿã•ã›ã‚‹éš›ãĢは、`str`だけでãĒく、JSONãĢ変換できるäģģæ„ãŽå€¤ã‚’`detail`ãƒ‘ãƒŠãƒĄãƒŧã‚ŋとしãĻæ¸Ąã™ã“ã¨ãŒã§ããžã™ã€‚ -`dist`や`list`ãĒãŠã‚’æ¸Ąã™ã“ã¨ãŒã§ããžã™ã€‚ +`dict`や`list`ãĒãŠã‚’æ¸Ąã™ã“ã¨ãŒã§ããžã™ã€‚ これらは **FastAPI** ãĢã‚ˆãŖãĻč‡Ēå‹•įš„ãĢå‡Ļį†ã•ã‚Œã€JSONãĢ変換されぞす。 diff --git a/docs/ja/docs/tutorial/query-param-models.md b/docs/ja/docs/tutorial/query-param-models.md new file mode 100644 index 000000000..053d0740b --- /dev/null +++ b/docs/ja/docs/tutorial/query-param-models.md @@ -0,0 +1,68 @@ +# クエãƒĒãƒ‘ãƒŠãƒĄãƒŧã‚ŋãƒĸデãƒĢ + +もしé–ĸé€Ŗã™ã‚‹**č¤‡æ•°ãŽã‚¯ã‚¨ãƒĒãƒ‘ãƒŠãƒĄãƒŧã‚ŋ**から成るグãƒĢãƒŧプがあるãĒã‚‰ã€ãã‚Œã‚‰ã‚’åŽŖč¨€ã™ã‚‹ãŸã‚ãĢ、**PydanticãƒĸデãƒĢ**をäŊœæˆã§ããžã™ã€‚ + +こうすることで、**č¤‡æ•°ãŽå ´æ‰€**で**そぎPydanticãƒĸデãƒĢã‚’å†åˆŠį”¨**でき、バãƒĒデãƒŧã‚ˇãƒ§ãƒŗã‚„ãƒĄã‚ŋデãƒŧã‚ŋを、すずãĻぎクエãƒĒãƒ‘ãƒŠãƒĄãƒŧã‚ŋãĢ寞しãĻ一åēĻãĢåŽŖč¨€ã§ããžã™ã€‚đŸ˜Ž + +/// note | å‚™č€ƒ + +こぎ抟čƒŊは、FastAPIぎバãƒŧã‚¸ãƒ§ãƒŗ `0.115.0` からã‚ĩポãƒŧトされãĻã„ãžã™ã€‚đŸ¤“ + +/// + +## クエãƒĒãƒ‘ãƒŠãƒĄãƒŧã‚ŋãĢPydanticãƒĸデãƒĢをäŊŋį”¨ã™ã‚‹ + +åŋ…čρãĒ**č¤‡æ•°ãŽã‚¯ã‚¨ãƒĒãƒ‘ãƒŠãƒĄãƒŧã‚ŋ**を**PydanticãƒĸデãƒĢ**ã§åŽŖč¨€ã—ã€ã•ã‚‰ãĢ、それを `Query` としãĻåŽŖč¨€ã—ãžã—ã‚‡ã†: + +{* ../../docs_src/query_param_models/tutorial001_an_py310.py hl[9:13,17] *} + +**FastAPI**は、ãƒĒクエ゚トぎ**クエãƒĒãƒ‘ãƒŠãƒĄãƒŧã‚ŋ**からそれぞれぎ**ãƒ•ã‚ŖãƒŧãƒĢド**ぎデãƒŧã‚ŋを**æŠŊå‡ē**ã—ã€åŽšįžŠã•ã‚ŒãŸ**PydanticãƒĸデãƒĢ**を提䞛しぞす。 + +## ドキãƒĨãƒĄãƒŗãƒˆãŽįĸēčĒ + +å¯žčŠąįš„APIドキãƒĨãƒĄãƒŗãƒˆ `/docs` でクエãƒĒãƒ‘ãƒŠãƒĄãƒŧã‚ŋをįĸēčĒã§ããžã™: + +
+ +
+ +## äŊ™åˆ†ãĒクエãƒĒãƒ‘ãƒŠãƒĄãƒŧã‚ŋをįρæ­ĸする + +į‰šåŽšãŽīŧˆã‚ぞり一čˆŦįš„ã§ã¯ãĒいかもしれãĒいīŧ‰ã‚ąãƒŧ゚で、受けäģ˜ã‘るクエãƒĒãƒ‘ãƒŠãƒĄãƒŧã‚ŋを**åˆļ限**するåŋ…čĻãŒã‚ã‚‹ã‹ã‚‚ã—ã‚Œãžã›ã‚“ã€‚ + +PydanticぎãƒĸデãƒĢぎ Configuration ã‚’åˆŠį”¨ã—ãĻ、 `extra` ãƒ•ã‚ŖãƒŧãƒĢドを `forbid` とすることができぞす。 + +{* ../../docs_src/query_param_models/tutorial002_an_py310.py hl[10] *} + +もしクナイã‚ĸãƒŗãƒˆãŒ**クエãƒĒãƒ‘ãƒŠãƒĄãƒŧã‚ŋ**としãĻ**äŊ™åˆ†ãĒ**デãƒŧã‚ŋを送ろうとすると、**エナãƒŧ**ãƒŦã‚šãƒãƒŗã‚šãŒčŋ”されぞす。 + +䞋えば、クナイã‚ĸãƒŗãƒˆãŒã‚¯ã‚¨ãƒĒãƒ‘ãƒŠãƒĄãƒŧã‚ŋ `tool` ãĢ、値 `plumbus` ã‚’č¨­åŽšã—ãĻ送ろうとすると: + +```http +https://example.com/items/?limit=10&tool=plumbus +``` + +クエãƒĒãƒ‘ãƒŠãƒĄãƒŧã‚ŋ `tool` ãŒč¨ąå¯ã•ã‚ŒãĻいãĒいことを通įŸĨする**エナãƒŧ**ãƒŦã‚šãƒãƒŗã‚šãŒčŋ”されぞす。 + +```json +{ + "detail": [ + { + "type": "extra_forbidden", + "loc": ["query", "tool"], + "msg": "Extra inputs are not permitted", + "input": "plumbus" + } + ] +} +``` + +## ぞとめ + +**FastAPI**では、**クエãƒĒãƒ‘ãƒŠãƒĄãƒŧã‚ŋ**ã‚’åŽŖč¨€ã™ã‚‹ãŸã‚ãĢ、**PydanticãƒĸデãƒĢ**をäŊŋį”¨ã§ããžã™ã€‚đŸ˜Ž + +/// tip | 豆įŸĨ識 + +ネã‚ŋバãƒŦæŗ¨æ„: PydanticãƒĸデãƒĢはクッキãƒŧやヘッダãƒŧãŽåŽŖč¨€ãĢもäŊŋį”¨ã§ããžã™ãŒã€ããŽå†…åŽšãĢついãĻは垌ぎチãƒĨãƒŧトãƒĒã‚ĸãƒĢでå­Ļãŗãžã™ã€‚đŸ¤Ģ + +/// diff --git a/docs/ja/docs/virtual-environments.md b/docs/ja/docs/virtual-environments.md new file mode 100644 index 000000000..791cf64a8 --- /dev/null +++ b/docs/ja/docs/virtual-environments.md @@ -0,0 +1,831 @@ +# äģŽæƒŗį’°åĸƒ + +PythonプロジェクトぎäŊœæĨ­ã§ã¯ã€**äģŽæƒŗį’°åĸƒ**īŧˆãžãŸã¯éĄžäŧŧぎäģ•įĩ„ãŋīŧ‰ã‚’äŊŋį”¨ã—ã€ãƒ—ãƒ­ã‚¸ã‚§ã‚¯ãƒˆã”ã¨ãĢã‚¤ãƒŗã‚šãƒˆãƒŧãƒĢã™ã‚‹ãƒ‘ãƒƒã‚ąãƒŧジを分é›ĸするずきでしょう。 + +/// info | æƒ…å ą + +もし、äģŽæƒŗį’°åĸƒãŽæĻ‚čĻã‚„äŊœæˆæ–šæŗ•ã€äŊŋį”¨æ–šæŗ•ãĢついãĻæ—ĸãĢご存įŸĨãĒら、こぎã‚ģã‚¯ã‚ˇãƒ§ãƒŗã‚’ã‚šã‚­ãƒƒãƒ—ã™ã‚‹ã“ã¨ãŒã§ããžã™ã€‚đŸ¤“ + +/// + +/// tip | 豆įŸĨ識 + +**äģŽæƒŗį’°åĸƒ**は、**į’°åĸƒå¤‰æ•°**ã¨ã¯į•°ãĒりぞす。 + +**į’°åĸƒå¤‰æ•°**は、プログナムがäŊŋį”¨ã§ãã‚‹ã‚ˇã‚šãƒ†ãƒ å†…ãŽå¤‰æ•°ã§ã™ã€‚ + +**äģŽæƒŗį’°åĸƒ**ã¯ã€ãƒ•ã‚Ąã‚¤ãƒĢã‚’ãžã¨ã‚ãŸãƒ‡ã‚ŖãƒŦクトãƒĒぎことです。 + +/// + +/// info | æƒ…å ą +こぎペãƒŧジでは、**äģŽæƒŗį’°åĸƒ**ぎäŊŋį”¨æ–šæŗ•ã¨ã€ããŽã¯ãŸã‚‰ããĢついãĻčĒŦ明しぞす。 + +もし**すずãĻã‚’įŽĄį†ã™ã‚‹ãƒ„ãƒŧãƒĢ**īŧˆPythonãŽã‚¤ãƒŗã‚šãƒˆãƒŧãƒĢもåĢむīŧ‰ã‚’å°Žå…Ĩするæē–備ができãĻいるãĒら、uv をおčŠĻしください。 + +/// + +## プロジェクトぎäŊœæˆ + +ãžãšã€ãƒ—ãƒ­ã‚¸ã‚§ã‚¯ãƒˆį”¨ãŽãƒ‡ã‚ŖãƒŦクトãƒĒをäŊœæˆã—ぞす。 + +į§ã¯é€šå¸¸ home/user ãƒ‡ã‚ŖãƒŦクトãƒĒぎ中ãĢ `code` ã¨ã„ã†ãƒ‡ã‚ŖãƒŦクトãƒĒã‚’į”¨æ„ã—ãĻいãĻ、プロジェクトごとãĢ1ã¤ãŽãƒ‡ã‚ŖãƒŦクトãƒĒをそぎ中ãĢäŊœæˆã—ãĻいぞす。 + +
+ +```console +// Go to the home directory +$ cd +// Create a directory for all your code projects +$ mkdir code +// Enter into that code directory +$ cd code +// Create a directory for this project +$ mkdir awesome-project +// Enter into that project directory +$ cd awesome-project +``` + +
+ +## äģŽæƒŗį’°åĸƒãŽäŊœæˆ + +Pythonプロジェクトでぎ**初めãĻぎ**äŊœæĨ­ã‚’開始する際ãĢは、**プロジェクト内**ãĢäģŽæƒŗį’°åĸƒã‚’äŊœæˆã—ãĻください。 + +/// tip | 豆įŸĨ識 + +ã“ã‚Œã‚’čĄŒã†ãŽã¯ã€**プロジェクトごとãĢ1回だけ**です。äŊœæĨ­ãŽãŸãŗãĢčĄŒã†åŋ…čĻã¯ã‚ã‚Šãžã›ã‚“ã€‚ + +/// + +//// tab | `venv` + +äģŽæƒŗį’°åĸƒã‚’äŊœæˆã™ã‚‹ãĢは、PythonãĢäģ˜åąžã—ãĻいる `venv` ãƒĸジãƒĨãƒŧãƒĢをäŊŋį”¨ã§ããžã™ã€‚ + +
+ +```console +$ python -m venv .venv +``` + +
+ +/// details | ã“ãŽã‚ŗãƒžãƒŗãƒ‰ãŽæ„å‘ŗ + +- `python` : `python` というプログナムをå‘ŧãŗå‡ēしぞす +- `-m` : ãƒĸジãƒĨãƒŧãƒĢを゚クãƒĒプトとしãĻå‘ŧãŗå‡ēしぞす。おぎãƒĸジãƒĨãƒŧãƒĢをå‘ŧãŗå‡ēすぎか、こぎæŦĄãĢ指厚しぞす +- `venv` : 通常PythonãĢäģ˜éšã—ãĻã‚¤ãƒŗã‚šãƒˆãƒŧãƒĢされる `venv`ãƒĸジãƒĨãƒŧãƒĢをäŊŋį”¨ã—ãžã™ +- `.venv` : äģŽæƒŗį’°åĸƒã‚’`.venv`ã¨ã„ã†æ–°ã—ã„ãƒ‡ã‚ŖãƒŦクトãƒĒãĢäŊœæˆã—ぞす + +/// + +//// + +//// tab | `uv` + +もし `uv` ã‚’ã‚¤ãƒŗã‚šãƒˆãƒŧãƒĢ済ãŋãĒら、äģŽæƒŗį’°åĸƒã‚’äŊœæˆã™ã‚‹ãŸã‚ãĢ `uv` をäŊŋうこともできぞす。 + +
+ +```console +$ uv venv +``` + +
+ +/// tip | 豆įŸĨ識 + +デフりãƒĢトでは、 `uv` は `.venv` ã¨ã„ã†ãƒ‡ã‚ŖãƒŦクトãƒĒãĢäģŽæƒŗį’°åĸƒã‚’äŊœæˆã—ぞす。 + +ただし、čŋŊ加ぎåŧ•æ•°ãĢãƒ‡ã‚ŖãƒŦクトãƒĒ名を与えãĻã‚Ģ゚ã‚ŋマイã‚ēすることもできぞす。 + +/// + +//// + +ã“ãŽã‚ŗãƒžãƒŗãƒ‰ã¯ `.venv` ã¨ã„ã†ãƒ‡ã‚ŖãƒŦクトãƒĒãĢ新しいäģŽæƒŗį’°åĸƒã‚’äŊœæˆã—ぞす。 + +/// details | `.venv` ぞたはそぎäģ–ぎ名前 + +äģŽæƒŗį’°åĸƒã‚’åˆĨãŽãƒ‡ã‚ŖãƒŦクトãƒĒãĢäŊœæˆã™ã‚‹ã“とも可čƒŊですが、 `.venv` と名äģ˜ã‘るぎが一čˆŦįš„ãĒæ…Ŗįŋ’です。 + +/// + +## äģŽæƒŗį’°åĸƒãŽæœ‰åŠšåŒ– + +åŽŸčĄŒã•ã‚Œã‚‹Pythonã‚ŗãƒžãƒŗãƒ‰ã‚„ã‚¤ãƒŗã‚šãƒˆãƒŧãƒĢã•ã‚Œã‚‹ãƒ‘ãƒƒã‚ąãƒŧジが新しくäŊœæˆã—たäģŽæƒŗį’°åĸƒã‚’äŊŋį”¨ã™ã‚‹ã‚ˆã†ã€ããŽäģŽæƒŗį’°åĸƒã‚’有劚化しぞしょう。 + +/// tip | 豆įŸĨ識 + +そぎプロジェクトぎäŊœæĨ­ã§**新しいã‚ŋãƒŧミナãƒĢã‚ģãƒƒã‚ˇãƒ§ãƒŗ**を開始する際ãĢは、**毎回**有劚化がåŋ…čĻã§ã™ã€‚ + +/// + +//// tab | Linux, macOS + +
+ +```console +$ source .venv/bin/activate +``` + +
+ +//// + +//// tab | Windows PowerShell + +
+ +```console +$ .venv\Scripts\Activate.ps1 +``` + +
+ +//// + +//// tab | Windows Bash + +もしWindowsでBashをäŊŋį”¨ã—ãĻいる場合 (Git BashãĒお): + +
+ +```console +$ source .venv/Scripts/activate +``` + +
+ +//// + +/// tip | 豆įŸĨ識 + +**æ–°ã—ã„ãƒ‘ãƒƒã‚ąãƒŧジ**をäģŽæƒŗį’°åĸƒãĢã‚¤ãƒŗã‚šãƒˆãƒŧãƒĢするときãĢは、再åēĻ**有劚化**しãĻください。 + +ã“ã†ã™ã‚‹ã“ã¨ã§ã€ããŽãƒ‘ãƒƒã‚ąãƒŧã‚¸ãŒã‚¤ãƒŗã‚šãƒˆãƒŧãƒĢした**ã‚ŋãƒŧミナãƒĢīŧˆCLIīŧ‰ãƒ—ログナム**をäŊŋį”¨ã™ã‚‹å ´åˆãĢ、äģŽæƒŗį’°åĸƒå†…ぎもぎがįĸē原ãĢäŊŋわれ、グロãƒŧバãƒĢį’°åĸƒãĢã‚¤ãƒŗã‚šãƒˆãƒŧãƒĢされãĻいるåˆĨぎもぎīŧˆãŠãã‚‰ãåŋ…čρãĒã‚‚ãŽã¨ã¯į•°ãĒるバãƒŧã‚¸ãƒ§ãƒŗīŧ‰ã‚’čĒ¤ãŖãĻäŊŋį”¨ã™ã‚‹ã“ã¨ã‚’é˜˛ãŽãžã™ã€‚ + +/// + +## äģŽæƒŗį’°åĸƒãŒæœ‰åŠšã§ã‚ã‚‹ã“ã¨ã‚’įĸēčĒã™ã‚‹ + +äģŽæƒŗį’°åĸƒãŒæœ‰åŠšã§ã‚ã‚‹īŧˆå‰ãŽã‚ŗãƒžãƒŗãƒ‰ãŒæ­Ŗå¸¸ãĢ抟čƒŊしたīŧ‰ã“とをįĸēčĒã—ãžã™ã€‚ + +/// tip | 豆įŸĨ識 + +これは**äģģæ„**ですが、すずãĻが期垅通りãĢ抟čƒŊã—ã€æ„å›ŗã—ãŸäģŽæƒŗį’°åĸƒã‚’äŊŋį”¨ã—ãĻいることを**įĸēčĒã™ã‚‹**č‰¯ã„æ–šæŗ•ã§ã™ã€‚ + +/// + +//// tab | Linux, macOS, Windows Bash + +
+ +```console +$ which python + +/home/user/code/awesome-project/.venv/bin/python +``` + +
+ +`.venv/bin/python` ãĢある `python` バイナãƒĒが、プロジェクトīŧˆã“ぎ場合は `awesome-project` īŧ‰å†…ãĢ襨į¤ēされãĻã„ã‚Œã°ã€æ­Ŗå¸¸ãĢ動äŊœã—ãĻいぞす đŸŽ‰ã€‚ + +//// + +//// tab | Windows PowerShell + +
+ +``` console +$ Get-Command python + +C:\Users\user\code\awesome-project\.venv\Scripts\python +``` + +
+ +`.venv\Scripts\python` ãĢある `python` バイナãƒĒが、プロジェクトīŧˆã“ぎ場合は `awesome-project` īŧ‰å†…ãĢ襨į¤ēされãĻã„ã‚Œã°ã€æ­Ŗå¸¸ãĢ動äŊœã—ãĻいぞす đŸŽ‰ã€‚ + +//// + +## `pip` をã‚ĸップグãƒŦãƒŧドする + +/// tip | 豆įŸĨ識 + +もし `uv` をäŊŋį”¨ã—ãĻいる場合は、 `pip` ぎäģŖã‚ã‚ŠãĢ `uv` をäŊŋãŖãĻã‚¤ãƒŗã‚šãƒˆãƒŧãƒĢã‚’čĄŒã†ãŸã‚ã€ `pip` をã‚ĸップグãƒŦãƒŧドするåŋ…čĻã¯ã‚ã‚Šãžã›ã‚“ đŸ˜Žã€‚ + +/// + +ã‚‚ã—ãƒ‘ãƒƒã‚ąãƒŧã‚¸ãŽã‚¤ãƒŗã‚šãƒˆãƒŧãƒĢãĢ `pip`īŧˆPythonãĢ標æē–でäģ˜åąžã—ãĻいぞすīŧ‰ã‚’äŊŋį”¨ã—ãĻいるãĒら、 `pip` を最新バãƒŧã‚¸ãƒ§ãƒŗãĢ**ã‚ĸップグãƒŦãƒŧド**しぞしょう。 + +ãƒ‘ãƒƒã‚ąãƒŧã‚¸ãŽã‚¤ãƒŗã‚šãƒˆãƒŧãƒĢ中ãĢį™ēį”Ÿã™ã‚‹æƒŗåŽšå¤–ãŽã‚¨ãƒŠãƒŧぎ多くは、最初ãĢ `pip` をã‚ĸップグãƒŦãƒŧドしãĻãŠãã ã‘ã§č§Ŗæąēされぞす。 + +/// tip | 豆įŸĨ識 + +通常、これはäģŽæƒŗį’°åĸƒã‚’äŊœæˆã—ãŸį›´åžŒãĢ**一åēĻだけ**åŽŸčĄŒã—ãžã™ã€‚ + +/// + +äģŽæƒŗį’°åĸƒãŒæœ‰åŠšã§ã‚ã‚‹ã“ã¨ã‚’īŧˆä¸Šã§čĒŦæ˜Žã—ãŸã‚ŗãƒžãƒŗãƒ‰ã§īŧ‰įĸēčĒã—ã€ã‚ĸップグãƒŦãƒŧãƒ‰ã‚’åŽŸčĄŒã—ãžã—ã‚‡ã†īŧš + +
+ +```console +$ python -m pip install --upgrade pip + +---> 100% +``` + +
+ +## `.gitignore` をčŋŊ加する + +**Git**をäŊŋį”¨ã—ãĻいる場合īŧˆäŊŋį”¨ã™ã‚‹ãšãã§ã—ã‚‡ã†īŧ‰ã€ `.gitignore` ãƒ•ã‚Ąã‚¤ãƒĢをčŋŊ加しãĻ、 `.venv` å†…ãŽã‚ã‚‰ã‚†ã‚‹ãƒ•ã‚Ąã‚¤ãƒĢをGitãŽįŽĄį†å¯žčąĄã‹ã‚‰é™¤å¤–ã—ãžã™ã€‚ + +/// tip | 豆įŸĨ識 + +もし `uv` をäŊŋį”¨ã—ãĻäģŽæƒŗį’°åĸƒã‚’äŊœæˆã—た場合、すでãĢこぎäŊœæĨ­ã¯æ¸ˆã‚“でいるぎで、こぎ手順を゚キップできぞす đŸ˜Žã€‚ + +/// + +/// tip | 豆įŸĨ識 + +これも、äģŽæƒŗį’°åĸƒã‚’äŊœæˆã—ãŸį›´åžŒãĢ**一åēĻだけ**åŽŸčĄŒã—ãžã™ã€‚ + +/// + +
+ +```console +$ echo "*" > .venv/.gitignore +``` + +
+ +/// details | ã“ãŽã‚ŗãƒžãƒŗãƒ‰ãŽæ„å‘ŗ + +- `echo "*"` : ã‚ŋãƒŧミナãƒĢãĢ `*` ã¨ã„ã†ãƒ†ã‚­ã‚šãƒˆã‚’ã€ŒčĄ¨į¤ē」しようとしぞす。īŧˆæŦĄãŽéƒ¨åˆ†ãĢã‚ˆãŖãĻそぎ動äŊœãŒå°‘し変わりぞすīŧ‰ +- `>` : `>` ぎåˇĻå´ãŽã‚ŗãƒžãƒŗãƒ‰ãŒã‚ŋãƒŧミナãƒĢãĢ襨į¤ēしようとする内厚を、ã‚ŋãƒŧミナãƒĢãĢã¯čĄ¨į¤ēせず、 `>` ãŽåŗå´ãŽãƒ•ã‚Ąã‚¤ãƒĢãĢ書きčžŧãŋぞす。 +- `.gitignore` : `*` を書きčžŧã‚€ãƒ•ã‚Ąã‚¤ãƒĢ名。 + +ここで、GitãĢおける `*` は「すずãĻã€ã‚’æ„å‘ŗã™ã‚‹ãŽã§ã€ã“ãŽã‚ŗãƒžãƒŗãƒ‰ãĢã‚ˆãŖãĻ `.venv` ãƒ‡ã‚ŖãƒŦクトãƒĒ内ぎすずãĻがGitãĢį„ĄčĻ–ã•ã‚Œã‚‹ã‚ˆã†ãĢãĒりぞす。 + +ã“ãŽã‚ŗãƒžãƒŗãƒ‰ã¯äģĨ下ぎテキ゚トを持つ `.gitignore` ãƒ•ã‚Ąã‚¤ãƒĢをäŊœæˆã—ぞすīŧš + +```gitignore +* +``` + +/// + +## ãƒ‘ãƒƒã‚ąãƒŧã‚¸ãŽã‚¤ãƒŗã‚šãƒˆãƒŧãƒĢ + +äģŽæƒŗį’°åĸƒã‚’æœ‰åŠšåŒ–ã—ãŸåžŒã€ããŽä¸­ã§ãƒ‘ãƒƒã‚ąãƒŧã‚¸ã‚’ã‚¤ãƒŗã‚šãƒˆãƒŧãƒĢできぞす。 + +/// tip | 豆įŸĨ識 + +プロジェクトãĢåŋ…čρãĒãƒ‘ãƒƒã‚ąãƒŧã‚¸ã‚’ã‚¤ãƒŗã‚šãƒˆãƒŧãƒĢぞたはã‚ĸップグãƒŦãƒŧドする場合、これを**一åēĻ**åŽŸčĄŒã—ãžã™ã€‚ + +ã‚‚ã—æ–°ã—ã„ãƒ‘ãƒƒã‚ąãƒŧジをčŋŊ加したり、バãƒŧã‚¸ãƒ§ãƒŗã‚’ã‚ĸップグãƒŦãƒŧドするåŋ…čĻãŒã‚ã‚‹å ´åˆã¯ã€ã‚‚ã†**一åēĻã“ãŽæ‰‹é †ã‚’įš°ã‚Ščŋ”し**ぞす。 + +/// + +### ãƒ‘ãƒƒã‚ąãƒŧã‚¸ã‚’į›´æŽĨã‚¤ãƒŗã‚šãƒˆãƒŧãƒĢする + +æ€ĨいでいãĻã€ãƒ—ãƒ­ã‚¸ã‚§ã‚¯ãƒˆãŽãƒ‘ãƒƒã‚ąãƒŧジčρäģļã‚’åŽŖč¨€ã™ã‚‹ãƒ•ã‚Ąã‚¤ãƒĢをäŊŋいたくãĒã„å ´åˆã€ãƒ‘ãƒƒã‚ąãƒŧã‚¸ã‚’į›´æŽĨã‚¤ãƒŗã‚šãƒˆãƒŧãƒĢできぞす。 + +/// tip | 豆įŸĨ識 + +プログナムがåŋ…čĻã¨ã™ã‚‹ãƒ‘ãƒƒã‚ąãƒŧジとバãƒŧã‚¸ãƒ§ãƒŗã‚’ãƒ•ã‚Ąã‚¤ãƒĢīŧˆäž‹ãˆã° `requirements.txt` や `pyproject.toml` īŧ‰ãĢ記čŧ‰ã—ãĻおくぎは、īŧˆã¨ãĻもīŧ‰č‰¯ã„č€ƒãˆã§ã™ã€‚ + +/// + +//// tab | `pip` + +
+ +```console +$ pip install "fastapi[standard]" + +---> 100% +``` + +
+ +//// + +//// tab | `uv` + +もし `uv` をäŊŋį”¨ã§ãã‚‹ãĒら: + +
+ +```console +$ uv pip install "fastapi[standard]" +---> 100% +``` + +
+ +//// + +### `requirements.txt` ã‹ã‚‰ã‚¤ãƒŗã‚šãƒˆãƒŧãƒĢする + +もし `requirements.txt` があるãĒã‚‰ã€ãƒ‘ãƒƒã‚ąãƒŧã‚¸ãŽã‚¤ãƒŗã‚šãƒˆãƒŧãƒĢãĢäŊŋį”¨ã§ããžã™ã€‚ + +//// tab | `pip` + +
+ +```console +$ pip install -r requirements.txt +---> 100% +``` + +
+ +//// + +//// tab | `uv` + +もし `uv` をäŊŋį”¨ã§ãã‚‹ãĒら: + +
+ +```console +$ uv pip install -r requirements.txt +---> 100% +``` + +
+ +//// + +/// details | `requirements.txt` + +ãƒ‘ãƒƒã‚ąãƒŧã‚¸ãŒč¨˜čŧ‰ã•れた `requirements.txt` はäģĨ下ぎようãĢãĒãŖãĻいぞす: + +```requirements.txt +fastapi[standard]==0.113.0 +pydantic==2.8.0 +``` + +/// + +## ãƒ—ãƒ­ã‚°ãƒŠãƒ ã‚’åŽŸčĄŒã™ã‚‹ + +äģŽæƒŗį’°åĸƒã‚’æœ‰åŠšåŒ–ã—ãŸåžŒã€ãƒ—ãƒ­ã‚°ãƒŠãƒ ã‚’åŽŸčĄŒã§ããžã™ã€‚ã“ãŽéš›ã€äģŽæƒŗį’°åĸƒå†…ぎPythonと、そこãĢã‚¤ãƒŗã‚šãƒˆãƒŧãƒĢã—ãŸãƒ‘ãƒƒã‚ąãƒŧジがäŊŋį”¨ã•ã‚Œãžã™ã€‚ + +
+ +```console +$ python main.py + +Hello World +``` + +
+ +## ã‚¨ãƒ‡ã‚Ŗã‚ŋãŽč¨­åŽš + +ãƒ—ãƒ­ã‚¸ã‚§ã‚¯ãƒˆã§ã¯ãŠãã‚‰ãã‚¨ãƒ‡ã‚Ŗã‚ŋをäŊŋį”¨ã™ã‚‹ã§ã—ã‚‡ã†ã€‚ã‚ŗãƒŧãƒ‰čŖœåŽŒã‚„ã‚¤ãƒŗãƒŠã‚¤ãƒŗã‚¨ãƒŠãƒŧãŽčĄ¨į¤ēができるようãĢ、äŊœæˆã—たäģŽæƒŗį’°åĸƒã‚’ã‚¨ãƒ‡ã‚Ŗã‚ŋでもäŊŋãˆã‚‹ã‚ˆã†č¨­åŽšã—ãĻください。īŧˆå¤šããŽå ´åˆã€č‡Ē動検å‡ēされぞすīŧ‰ + +č¨­åŽšäž‹: + +* VS Code +* PyCharm + +/// tip | 豆įŸĨ識 + +ã“ãŽč¨­åŽšã¯é€šå¸¸ã€äģŽæƒŗį’°åĸƒã‚’äŊœæˆã—た際ãĢ**一åēĻだけ**čĄŒã„ãžã™ã€‚ + +/// + +## äģŽæƒŗį’°åĸƒãŽį„ĄåŠšåŒ– + +プロジェクトぎäŊœæĨ­ãŒįĩ‚äē†ã—たら、そぎäģŽæƒŗį’°åĸƒã‚’**į„ĄåŠšåŒ–**できぞす。 + +
+ +```console +$ deactivate +``` + +
+ +これãĢより、 `python` ã‚ŗãƒžãƒŗãƒ‰ã‚’åŽŸčĄŒã—ãĻã‚‚ã€ããŽãƒ—ãƒ­ã‚¸ã‚§ã‚¯ãƒˆį”¨īŧˆãŽãƒ‘ãƒƒã‚ąãƒŧã‚¸ãŒã‚¤ãƒŗã‚šãƒˆãƒŧãƒĢされたīŧ‰äģŽæƒŗį’°åĸƒã‹ã‚‰ `python` プログナムをå‘ŧãŗå‡ēそうとはしãĒくãĒりぞす。 + +## äŊœæĨ­æē–å‚™åތäē† + +ここぞでで、プロジェクトぎäŊœæĨ­ã‚’始めるæē–備が整いぞした。 + +/// tip | 豆įŸĨ識 + +ä¸Šč¨˜ãŽå†…åŽšã‚’į†č§Ŗã—ãŸã„ã§ã™ã‹īŧŸ + +もしそうãĒら、äģĨ下をčĒ­ãŋé€˛ã‚ãĻãã ã•ã„ã€‚đŸ‘‡đŸ¤“ + +/// + +## ãĒぜäģŽæƒŗį’°åĸƒīŧŸ + +FastAPIをäŊŋãŖãŸäŊœæĨ­ã‚’するãĢは、 [Python](https://www.python.org/) ãŽã‚¤ãƒŗã‚šãƒˆãƒŧãƒĢがåŋ…čĻã§ã™ã€‚ + +それから、FastAPIや、äŊŋį”¨ã—ãŸã„ããŽäģ–ぎ**ãƒ‘ãƒƒã‚ąãƒŧジ**を**ã‚¤ãƒŗã‚šãƒˆãƒŧãƒĢ**するåŋ…čĻãŒã‚ã‚Šãžã™ã€‚ + +ãƒ‘ãƒƒã‚ąãƒŧã‚¸ã‚’ã‚¤ãƒŗã‚šãƒˆãƒŧãƒĢするãĢは、通常、Python ãĢäģ˜åąžã™ã‚‹ `pip` ã‚ŗãƒžãƒŗãƒ‰ (ぞたは同様ぎäģŖæ›ŋã‚ŗãƒžãƒŗãƒ‰) をäŊŋį”¨ã—ãžã™ã€‚ + +ただし、`pip` ã‚’į›´æŽĨäŊŋį”¨ã™ã‚‹ã¨ã€ãƒ‘ãƒƒã‚ąãƒŧジは**グロãƒŧバãƒĢãĒPythonį’°åĸƒ**īŧˆOS全äŊ“ãĢã‚¤ãƒŗã‚šãƒˆãƒŧãƒĢされたPythonį’°åĸƒīŧ‰ãĢã‚¤ãƒŗã‚šãƒˆãƒŧãƒĢされぞす。 + +### å•éĄŒį‚š + +では、グロãƒŧバãƒĢPythonį’°åĸƒãĢãƒ‘ãƒƒã‚ąãƒŧã‚¸ã‚’ã‚¤ãƒŗã‚šãƒˆãƒŧãƒĢã™ã‚‹ã“ã¨ãŽå•éĄŒį‚šã¯äŊ•でしょうかīŧŸ + +ã‚ã‚‹æ™‚į‚šã§ã€ã‚ãĒたは**į•°ãĒã‚‹ãƒ‘ãƒƒã‚ąãƒŧジ**ãĢ䞝存する多くぎプログナムを書くことãĢãĒるでしょう。そしãĻ、これらぎ中ãĢã¯åŒã˜ãƒ‘ãƒƒã‚ąãƒŧジぎ**į•°ãĒるバãƒŧã‚¸ãƒ§ãƒŗ**ãĢ䞝存するもぎもå‡ēãĻãã‚‹ã§ã—ã‚‡ã†ã€‚đŸ˜ą + +䞋えば、 `philosophers-stone` īŧˆčŗĸč€…ãŽįŸŗīŧ‰ã¨ã„うプロジェクトをäŊœæˆã™ã‚‹ã¨ã—ぞす。こぎプログナムは **`harry` īŧˆãƒãƒĒãƒŧīŧ‰ã¨ã„ã†ãƒ‘ãƒƒã‚ąãƒŧジぎバãƒŧã‚¸ãƒ§ãƒŗ `1`**ãĢ䞝存しãĻいぞす。そぎため、 `harry` īŧˆãƒãƒĒãƒŧīŧ‰ã‚’ã‚¤ãƒŗã‚šãƒˆãƒŧãƒĢするåŋ…čĻãŒã‚ã‚Šãžã™ã€‚ + +```mermaid +flowchart LR + stone(philosophers-stone) -->|requires| harry-1[harry v1] +``` + +それから、 `prisoner-of-azkaban` īŧˆã‚ĸã‚ēã‚ĢãƒãƒŗãŽå›šäēēīŧ‰ã¨ã„うåˆĨぎプロジェクトをäŊœæˆã—たとしぞす。こぎプロジェクトも `harry` īŧˆãƒãƒĒãƒŧīŧ‰ãĢ䞝存しãĻいぞすが、**`harry` īŧˆãƒãƒĒãƒŧīŧ‰ãŽãƒãƒŧã‚¸ãƒ§ãƒŗ `3`**がåŋ…čĻã§ã™ã€‚ + +```mermaid +flowchart LR + azkaban(prisoner-of-azkaban) --> |requires| harry-3[harry v3] +``` + +ã—ã‹ã—ã€ã“ã“ã§å•éĄŒãĢãĒるぎは、もしロãƒŧã‚ĢãƒĢぎ**äģŽæƒŗį’°åĸƒ**ではãĒくグロãƒŧバãƒĢīŧˆį’°åĸƒīŧ‰ãĢãƒ‘ãƒƒã‚ąãƒŧã‚¸ã‚’ã‚¤ãƒŗã‚šãƒˆãƒŧãƒĢするãĒら、 `harry` īŧˆãƒãƒĒãƒŧīŧ‰ãŽãŠãŽãƒãƒŧã‚¸ãƒ§ãƒŗã‚’ã‚¤ãƒŗã‚šãƒˆãƒŧãƒĢするか選ばãĒいといけãĒいことです。 + +䞋えば、 `philosophers-stone` īŧˆčŗĸč€…ãŽįŸŗīŧ‰ã‚’åŽŸčĄŒã™ã‚‹ãĢは、ぞず `harry` īŧˆãƒãƒĒãƒŧīŧ‰ãŽãƒãƒŧã‚¸ãƒ§ãƒŗ `1` ã‚’ã‚¤ãƒŗã‚šãƒˆãƒŧãƒĢするåŋ…čĻãŒã‚ã‚Šãžã™īŧš + +
+ +```console +$ pip install "harry==1" +``` + +
+ +これãĢより、`harry` īŧˆãƒãƒĒãƒŧīŧ‰ãƒãƒŧã‚¸ãƒ§ãƒŗ1がグロãƒŧバãƒĢãĒPythonį’°åĸƒãĢã‚¤ãƒŗã‚šãƒˆãƒŧãƒĢされぞす。 + +```mermaid +flowchart LR + subgraph global[global env] + harry-1[harry v1] + end + subgraph stone-project[philosophers-stone project] + stone(philosophers-stone) -->|requires| harry-1 + end +``` + +しかし、 `prisoner-of-azkaban` īŧˆã‚ĸã‚ēã‚ĢãƒãƒŗãŽå›šäēēīŧ‰ã‚’åŽŸčĄŒã—ãŸã„å ´åˆã¯ã€`harry` īŧˆãƒãƒĒãƒŧīŧ‰ãŽãƒãƒŧã‚¸ãƒ§ãƒŗ `1` をã‚ĸãƒŗã‚¤ãƒŗã‚šãƒˆãƒŧãƒĢし、`harry` īŧˆãƒãƒĒãƒŧīŧ‰ãŽãƒãƒŧã‚¸ãƒ§ãƒŗ `3` ã‚’ã‚¤ãƒŗã‚šãƒˆãƒŧãƒĢã—į›´ã™åŋ…čĻãŒã‚ã‚Šãžã™ã€‚īŧˆã‚るいは、単ãĢ`harry` īŧˆãƒãƒĒãƒŧīŧ‰ãŽãƒãƒŧã‚¸ãƒ§ãƒŗ `3` ã‚’ã‚¤ãƒŗã‚šãƒˆãƒŧãƒĢすることで、č‡Ēå‹•įš„ãĢバãƒŧã‚¸ãƒ§ãƒŗ `1` がã‚ĸãƒŗã‚¤ãƒŗã‚šãƒˆãƒŧãƒĢされぞすīŧ‰ + +
+ +```console +$ pip install "harry==3" +``` + +
+ +こぎようãĢしãĻ、グロãƒŧバãƒĢį’°åĸƒã¸ãŽ `harry` īŧˆãƒãƒĒãƒŧīŧ‰ãŽãƒãƒŧã‚¸ãƒ§ãƒŗ `3` ãŽã‚¤ãƒŗã‚šãƒˆãƒŧãƒĢが厌äē†ã—ぞす。 + +それから、 `philosophers-stone` īŧˆčŗĸč€…ãŽįŸŗīŧ‰ã‚’å†ãŗåŽŸčĄŒã—ã‚ˆã†ã¨ã™ã‚‹ã¨ã€ã“ãŽãƒ—ãƒ­ã‚°ãƒŠãƒ ã¯ `harry` īŧˆãƒãƒĒãƒŧīŧ‰ãŽãƒãƒŧã‚¸ãƒ§ãƒŗ `1` がåŋ…čρãĒため、**動äŊœã—ãĒくãĒる**可čƒŊ性がありぞす。 + +```mermaid +flowchart LR + subgraph global[global env] + harry-1[harry v1] + style harry-1 fill:#ccc,stroke-dasharray: 5 5 + harry-3[harry v3] + end + subgraph stone-project[philosophers-stone project] + stone(philosophers-stone) -.-x|â›”ī¸| harry-1 + end + subgraph azkaban-project[prisoner-of-azkaban project] + azkaban(prisoner-of-azkaban) --> |requires| harry-3 + end +``` + +/// tip | 豆įŸĨ識 + +PythonãŽãƒ‘ãƒƒã‚ąãƒŧジでは、**新しいバãƒŧã‚¸ãƒ§ãƒŗ**で**äē’æ›æ€§ã‚’損ãĒう変更をéŋける**ようåŠĒめるぎが一čˆŦįš„ã§ã™ãŒã€ãã‚Œã§ã‚‚æŗ¨æ„ãŒåŋ…čĻã§ã™ã€‚ã™ãšãĻãŒæ­Ŗå¸¸ãĢ動äŊœã™ã‚‹ã“とをテ゚トでįĸēčĒã—ãĻã‹ã‚‰ã€æ„å›ŗįš„ãĢ指厚しãĻ新しいバãƒŧã‚¸ãƒ§ãƒŗã‚’ã‚¤ãƒŗã‚šãƒˆãƒŧãƒĢã™ã‚‹ãŽãŒč‰¯ã„ã§ã—ã‚‡ã†ã€‚ + +/// + +あãĒたぎすずãĻぎ**プロジェクトが䞝存しãĻいる**、**多数ぎ**äģ–ぎ**ãƒ‘ãƒƒã‚ąãƒŧジ**ãŒä¸Šč¨˜ãŽå•éĄŒã‚’æŠąãˆãĻã„ã‚‹ã¨æƒŗåƒã—ãĻãã ã•ã„ã€‚ã“ã‚Œã¯įŽĄį†ãŒéžå¸¸ãĢå›°é›Ŗã§ã™ã€‚ãã—ãĻ、**äē’æ›æ€§ãŽãĒいバãƒŧã‚¸ãƒ§ãƒŗ**ãŽãƒ‘ãƒƒã‚ąãƒŧジをäŊŋãŖãĻãƒ—ãƒ­ã‚¸ã‚§ã‚¯ãƒˆã‚’åŽŸčĄŒã—ã€ãĒぜ動äŊœã—ãĒいぎか分からãĒくãĒるでしょう。 + +ぞた、äŊŋį”¨ã—ãĻいるOSīŧˆLinux、Windows、macOS ãĒおīŧ‰ãĢã‚ˆãŖãĻは、PythonがすでãĢã‚¤ãƒŗã‚šãƒˆãƒŧãƒĢされãĻã„ã‚‹ã“ã¨ãŒã‚ã‚Šãžã™ã€‚ã“ãŽå ´åˆã€į‰šåŽšãŽãƒãƒŧã‚¸ãƒ§ãƒŗãŽãƒ‘ãƒƒã‚ąãƒŧジが**OSぎ動äŊœãĢåŋ…čĻã§ã‚ã‚‹**ことがありぞす。グロãƒŧバãƒĢį’°åĸƒãĢãƒ‘ãƒƒã‚ąãƒŧã‚¸ã‚’ã‚¤ãƒŗã‚šãƒˆãƒŧãƒĢすると、OSãĢäģ˜åąžã™ã‚‹ãƒ—ログナムを**åŖŠã—ãĻしぞう**可čƒŊ性がありぞす。 + +## ãƒ‘ãƒƒã‚ąãƒŧã‚¸ãŽã‚¤ãƒŗã‚šãƒˆãƒŧãƒĢ先 + +Pythonã‚’ã‚¤ãƒŗã‚šãƒˆãƒŧãƒĢã—ãŸã¨ãã€ãƒ•ã‚Ąã‚¤ãƒĢをåĢã‚“ã ã„ãã¤ã‹ãŽãƒ‡ã‚ŖãƒŦクトãƒĒがäŊœæˆã•れぞす。 + +これらぎ中ãĢã¯ã€ã‚¤ãƒŗã‚šãƒˆãƒŧãƒĢã•ã‚ŒãŸãƒ‘ãƒƒã‚ąãƒŧジをäŋå­˜ã™ã‚‹ãŸã‚ãŽã‚‚ぎもありぞす。 + +äģĨä¸‹ãŽã‚ŗãƒžãƒŗãƒ‰ã‚’åŽŸčĄŒã—ãŸã¨ãīŧš + +
+ +```console +// Don't run this now, it's just an example 🤓 +$ pip install "fastapi[standard]" +---> 100% +``` + +
+ +FastAPIãŽã‚ŗãƒŧドをåĢã‚€åœ§į¸Žãƒ•ã‚Ąã‚¤ãƒĢが、通常は [PyPI](https://pypi.org/project/fastapi/) からダã‚Ļãƒŗãƒ­ãƒŧドされぞす。 + +ぞた、FastAPIが䞝存するäģ–ãŽãƒ‘ãƒƒã‚ąãƒŧジも**ダã‚Ļãƒŗãƒ­ãƒŧド**されぞす。 + +ãã‚Œã‹ã‚‰ã€ã“ã‚Œã‚‰ãŽãƒ•ã‚Ąã‚¤ãƒĢは**č§Ŗå‡**ã•ã‚Œã€ã‚ŗãƒŗãƒ”ãƒĨãƒŧã‚ŋãŽã‚ã‚‹ãƒ‡ã‚ŖãƒŦクトãƒĒãĢ配įŊŽã•れぞす。 + +デフりãƒĢãƒˆã§ã¯ã€ã“ã‚Œã‚‰ãŽãƒ•ã‚Ąã‚¤ãƒĢはPythonãŽã‚¤ãƒŗã‚šãƒˆãƒŧãƒĢ時ãĢäŊœæˆã•ã‚Œã‚‹ãƒ‡ã‚ŖãƒŦクトãƒĒ、つぞり**グロãƒŧバãƒĢį’°åĸƒ**ãĢ配įŊŽã•れぞす。 + +## äģŽæƒŗį’°åĸƒã¨ã¯ + +すずãĻãŽãƒ‘ãƒƒã‚ąãƒŧジをグロãƒŧバãƒĢį’°åĸƒãĢ配įŊŽã™ã‚‹ã“とãĢã‚ˆãŖãĻį”Ÿã˜ã‚‹å•éĄŒãŽč§Ŗæąēį­–ã¯ã€äŊœæĨ­ã™ã‚‹**プロジェクトごとぎäģŽæƒŗį’°åĸƒ**をäŊŋį”¨ã™ã‚‹ã“ã¨ã§ã™ã€‚ + +äģŽæƒŗį’°åĸƒã¯**ãƒ‡ã‚ŖãƒŦクトãƒĒ**であり、グロãƒŧバãƒĢį’°åĸƒã¨éžå¸¸ãĢäŧŧãĻいãĻ、一つぎプロジェクトでäŊŋã†į‰šåŽšãŽãƒ‘ãƒƒã‚ąãƒŧã‚¸įž¤ã‚’ã‚¤ãƒŗã‚šãƒˆãƒŧãƒĢできる場所です。 + +こぎようãĢしãĻ、それぞれぎプロジェクトがį‹Ŧč‡ĒぎäģŽæƒŗį’°åĸƒīŧˆ`.venv` ãƒ‡ã‚ŖãƒŦクトãƒĒīŧ‰ãĢį‹Ŧč‡ĒãŽãƒ‘ãƒƒã‚ąãƒŧã‚¸įž¤ã‚’æŒã¤ã“ã¨ãŒã§ããžã™ã€‚ + +```mermaid +flowchart TB + subgraph stone-project[philosophers-stone project] + stone(philosophers-stone) --->|requires| harry-1 + subgraph venv1[.venv] + harry-1[harry v1] + end + end + subgraph azkaban-project[prisoner-of-azkaban project] + azkaban(prisoner-of-azkaban) --->|requires| harry-3 + subgraph venv2[.venv] + harry-3[harry v3] + end + end + stone-project ~~~ azkaban-project +``` + +## äģŽæƒŗį’°åĸƒãŽæœ‰åŠšåŒ–ã¨ã¯ + +äģŽæƒŗį’°åĸƒã‚’有劚ãĢしたとき、䞋えばæŦĄãŽã‚ŗãƒžãƒŗãƒ‰ã‚’åŽŸčĄŒã—ãŸå ´åˆã‚’č€ƒãˆãžã™īŧš + +//// tab | Linux, macOS + +
+ +```console +$ source .venv/bin/activate +``` + +
+ +//// + +//// tab | Windows PowerShell + +
+ +```console +$ .venv\Scripts\Activate.ps1 +``` + +
+ +//// + +//// tab | Windows Bash + +あるいは、WindowsでBashをäŊŋį”¨ã—ãĻいる場合 (Git BashãĒお): + +
+ +```console +$ source .venv/Scripts/activate +``` + +
+ +//// + +これãĢã‚ˆãŖãĻ、いくつかぎ [į’°åĸƒå¤‰æ•°](environment-variables.md){.internal-link target=_blank} がäŊœæˆãƒģäŋŽæ­Ŗã•れ、æŦĄãĢåŽŸčĄŒã•ã‚Œã‚‹ã‚ŗãƒžãƒŗãƒ‰ã§äŊŋį”¨ã§ãã‚‹ã‚ˆã†ãĢãĒりぞす。 + +ã“ã‚Œã‚‰ãŽį’°åĸƒå¤‰æ•°ãŽã˛ã¨ã¤ãĢ、 `PATH` 変数がありぞす。 + +/// tip | 豆įŸĨ識 + +`PATH` 変数ãĢついãĻãŽčŠŗį´°ã¯ [į’°åĸƒå¤‰æ•°](environment-variables.md#pathį’°åĸƒå¤‰æ•°){.internal-link target=_blank} ã‚’å‚į…§ã—ãĻください。 + +/// + +äģŽæƒŗį’°åĸƒã‚’有劚ãĢすると、そぎäģŽæƒŗį’°åĸƒãŽãƒ‘゚ `.venv/bin` īŧˆLinuxとmacOSīŧ‰ã€ã‚るいは `.venv\Scripts` īŧˆWindowsīŧ‰ãŒ `PATH` 変数ãĢčŋŊ加されぞす。 + +ããŽį’°åĸƒã‚’有劚ãĢする前ぎ `PATH` 変数がæŦĄãŽã‚ˆã†ãĢãĒãŖãĻいるとしぞす。 + +//// tab | Linux, macOS + +```plaintext +/usr/bin:/bin:/usr/sbin:/sbin +``` + +これは、OSがäģĨä¸‹ãŽãƒ‡ã‚ŖãƒŦクトãƒĒ中でプログナムをæŽĸã™ã“ã¨ã‚’æ„å‘ŗã—ãžã™īŧš + +* `/usr/bin` +* `/bin` +* `/usr/sbin` +* `/sbin` + +//// + +//// tab | Windows + +```plaintext +C:\Windows\System32 +``` + +これは、OSがäģĨä¸‹ãŽãƒ‡ã‚ŖãƒŦクトãƒĒ中でプログナムをæŽĸã™ã“ã¨ã‚’æ„å‘ŗã—ãžã™īŧš + +* `C:\Windows\System32` + +//// + +äģŽæƒŗį’°åĸƒã‚’有劚ãĢすると、 `PATH` 変数はæŦĄãŽã‚ˆã†ãĢãĒりぞす。 + +//// tab | Linux, macOS + +```plaintext +/home/user/code/awesome-project/.venv/bin:/usr/bin:/bin:/usr/sbin:/sbin +``` + +これは、OSがäģ–ãŽãƒ‡ã‚ŖãƒŦクトãƒĒをæŽĸすより前ãĢ、最初ãĢäģĨä¸‹ãŽãƒ‡ã‚ŖãƒŦクトãƒĒ中でプログナムをæŽĸã—å§‹ã‚ã‚‹ã“ã¨ã‚’æ„å‘ŗã—ãžã™īŧš + +```plaintext +/home/user/code/awesome-project/.venv/bin +``` + +そぎため、ã‚ŋãƒŧミナãƒĢで `python` とå…Ĩ力した際ãĢ、OSはPythonプログナムをäģĨ下ぎパ゚でį™ēčĻ‹ã—ã€äŊŋį”¨ã—ãžã™ã€‚ + +```plaintext +/home/user/code/awesome-project/.venv/bin/python +``` + +//// + +//// tab | Windows + +```plaintext +C:\Users\user\code\awesome-project\.venv\Scripts;C:\Windows\System32 +``` + +これは、OSがäģ–ãŽãƒ‡ã‚ŖãƒŦクトãƒĒをæŽĸすより前ãĢ、最初ãĢäģĨä¸‹ãŽãƒ‡ã‚ŖãƒŦクトãƒĒ中でプログナムをæŽĸã—å§‹ã‚ã‚‹ã“ã¨ã‚’æ„å‘ŗã—ãžã™īŧš + +```plaintext +C:\Users\user\code\awesome-project\.venv\Scripts +``` + +そぎため、ã‚ŋãƒŧミナãƒĢで `python` とå…Ĩ力した際ãĢ、OSはPythonプログナムをäģĨ下ぎパ゚でį™ēčĻ‹ã—ã€äŊŋį”¨ã—ãžã™ã€‚ + +```plaintext +C:\Users\user\code\awesome-project\.venv\Scripts\python +``` + +//// + +重čρãĒį‚šã¯ã€äģŽæƒŗį’°åĸƒãŽãƒ‘゚を `PATH` 変数ぎ**先頭**ãĢ配įŊŽã™ã‚‹ã“とです。OSã¯åˆŠį”¨å¯čƒŊãĒäģ–ぎPythonをčĻ‹ã¤ã‘ã‚‹ã‚ˆã‚Š**前ãĢ**、こぎäģŽæƒŗį’°åĸƒãŽPythonをčĻ‹ã¤ã‘ã‚‹ã‚ˆã†ãĢãĒりぞす。こぎようãĢしãĻ、 `python` ã‚’åŽŸčĄŒã—ãŸã¨ããĢ、äģ–ぎ `python` īŧˆäž‹ãˆã°ã‚°ãƒ­ãƒŧバãƒĢį’°åĸƒãŽ `python` īŧ‰ã§ã¯ãĒく、**そぎäģŽæƒŗį’°åĸƒãŽ**PythonをäŊŋį”¨ã™ã‚‹ã‚ˆã†ãĢãĒりぞす。 + +äģŽæƒŗį’°åĸƒã‚’有劚ãĢしãĻ変更されることはäģ–ãĢもありぞすが、これが最も重čρãĒå¤‰æ›´ãŽã˛ã¨ã¤ã§ã™ã€‚ + +## äģŽæƒŗį’°åĸƒãŽįĸēčĒ + +äģŽæƒŗį’°åĸƒãŒæœ‰åŠšã‹ãŠã†ã‹ã€äž‹ãˆã°æŦĄãŽã‚ˆã†ãĢįĸēčĒã§ããžã™ã€‚īŧš + +//// tab | Linux, macOS, Windows Bash + +
+ +```console +$ which python + +/home/user/code/awesome-project/.venv/bin/python +``` + +
+ +//// + +//// tab | Windows PowerShell + +
+ +```console +$ Get-Command python + +C:\Users\user\code\awesome-project\.venv\Scripts\python +``` + +
+ +//// + +これは、äŊŋį”¨ã•ã‚Œã‚‹ `python` プログナムが**そぎäģŽæƒŗį’°åĸƒãŽ**ã‚‚ãŽã§ã‚ã‚‹ã“ã¨ã‚’æ„å‘ŗã—ãžã™ã€‚ + +LinuxやmacOSでは `which` を、Windows PowerShellでは `Get-Command` をäŊŋį”¨ã—ãžã™ã€‚ + +ã“ãŽã‚ŗãƒžãƒŗãƒ‰ãŽå‹•äŊœã¯ã€ `PATH`変数ãĢč¨­åŽšã•ã‚ŒãŸ**それぞれぎパ゚を順ãĢ**įĸēčĒã—ãĻいき、å‘ŧばれãĻいる `python` プログナムをæŽĸしぞす。そしãĻ、čĻ‹ã¤ã‹ã‚ŠæŦĄįŦŦそぎプログナムへぎ**ãƒ‘ã‚šã‚’čĄ¨į¤ēしぞす**。 + +最も重čρãĒことは、 `python` がå‘ŧばれたときãĢ、ぞさãĢã“ãŽã‚ŗãƒžãƒŗãƒ‰ã§įĸēčĒã—ãŸ "`python`" ãŒåŽŸčĄŒã•ã‚Œã‚‹ã“ã¨ã§ã™ã€‚ + +こうしãĻ、č‡Ēåˆ†ãŒæƒŗåŽšé€šã‚ŠãŽäģŽæƒŗį’°åĸƒãĢいるかをįĸēčĒã§ããžã™ã€‚ + +/// tip | 豆įŸĨ識 + +あるäģŽæƒŗį’°åĸƒã‚’有劚ãĢし、そぎPythonをäŊŋį”¨ã—ãŸãžãž**äģ–ぎプロジェクトãĢį§ģ動しãĻ**ã—ãžã†ã“ã¨ã¯į°Ąå˜ãĢčĩˇã“り垗ぞす。 + +そしãĻ、そぎįŦŦäēŒãŽãƒ—ロジェクトは動äŊœã—ãĒいでしょう。ãĒぜãĒらåˆĨぎプロジェクトぎäģŽæƒŗį’°åĸƒãŽ**čĒ¤ãŖãŸPython**をäŊŋį”¨ã—ãĻいるからです。 + +そぎため、おぎ `python` がäŊŋį”¨ã•ã‚ŒãĻいるぎかįĸēčĒã§ãã‚‹ã“ã¨ã¯åŊšįĢ‹ãĄãžã™ã€‚đŸ¤“ + +/// + +## ãĒぜäģŽæƒŗį’°åĸƒã‚’į„ĄåŠšåŒ–ã™ã‚‹ãŽã‹ + +䞋えば、`philosophers-stone` īŧˆčŗĸč€…ãŽįŸŗīŧ‰ã¨ã„うプロジェクトでäŊœæĨ­ã‚’しãĻいãĻ、**そぎäģŽæƒŗį’°åĸƒã‚’有劚ãĢし**、åŋ…čρãĒãƒ‘ãƒƒã‚ąãƒŧã‚¸ã‚’ã‚¤ãƒŗã‚šãƒˆãƒŧãƒĢしãĻããŽį’°åĸƒå†…でäŊœæĨ­ã‚’é€˛ã‚ãĻいるとしぞす。 + +それから、**åˆĨぎプロジェクト**、 `prisoner-of-azkaban` īŧˆã‚ĸã‚ēã‚ĢãƒãƒŗãŽå›šäēēīŧ‰ãĢ取り掛かろうとしぞす。 + +ããŽãƒ—ãƒ­ã‚¸ã‚§ã‚¯ãƒˆãƒ‡ã‚ŖãƒŦクトãƒĒへį§ģ動しぞすīŧš + +
+ +```console +$ cd ~/code/prisoner-of-azkaban +``` + +
+ +もし `philosophers-stone` īŧˆčŗĸč€…ãŽįŸŗīŧ‰ãŽäģŽæƒŗį’°åĸƒã‚’į„ĄåŠšåŒ–ã—ãĻいãĒいと、`python` ã‚’åŽŸčĄŒã—ãŸã¨ãã€ ã‚ŋãƒŧミナãƒĢは `philosophers-stone` īŧˆčŗĸč€…ãŽįŸŗīŧ‰ãŽPythonをäŊŋį”¨ã—ã‚ˆã†ã¨ã—ãžã™ã€‚ + +
+ +```console +$ cd ~/code/prisoner-of-azkaban + +$ python main.py + +// Error importing sirius, it's not installed 😱 +Traceback (most recent call last): + File "main.py", line 1, in + import sirius +``` + +
+ +しかし、そぎäģŽæƒŗį’°åĸƒã‚’į„ĄåŠšåŒ–ã—ã€ `prisoner-of-azkaban` īŧˆã‚ĸã‚ēã‚ĢãƒãƒŗãŽå›šäēēīŧ‰ãŽãŸã‚ãŽæ–°ã—いäģŽæƒŗį’°åĸƒã‚’有劚ãĢすれば、 `python` ã‚’åŽŸčĄŒã—ãŸã¨ããĢ `prisoner-of-azkaban` īŧˆã‚ĸã‚ēã‚ĢãƒãƒŗãŽå›šäēēīŧ‰ãŽäģŽæƒŗį’°åĸƒãŽ Python がäŊŋį”¨ã•ã‚Œã‚‹ã‚ˆã†ãĢãĒりぞす。 + +
+ +```console +$ cd ~/code/prisoner-of-azkaban + +// You don't need to be in the old directory to deactivate, you can do it wherever you are, even after going to the other project 😎 +$ deactivate + +// Activate the virtual environment in prisoner-of-azkaban/.venv 🚀 +$ source .venv/bin/activate + +// Now when you run python, it will find the package sirius installed in this virtual environment ✨ +$ python main.py + +I solemnly swear đŸē +``` + +
+ +## äģŖæ›ŋ手æŽĩ + +これは、あらゆるäģ•įĩ„ãŋを**æ šæœŦから**å­ĻãļãŸã‚ãŽã‚ˇãƒŗãƒ—ãƒĢãĒå…Ĩ門ã‚Ŧイドです。 + +äģŽæƒŗį’°åĸƒã€ãƒ‘ãƒƒã‚ąãƒŧジぎ䞝存é–ĸäŋ‚īŧˆrequirementsīŧ‰ã€ãƒ—ãƒ­ã‚¸ã‚§ã‚¯ãƒˆãŽįŽĄį†ãĢは、多くぎ**äģŖæ›ŋ手æŽĩ**がありぞす。 + +æē–å‚™ãŒæ•´ã„ã€ãƒ‘ãƒƒã‚ąãƒŧジぎ䞝存é–ĸäŋ‚、äģŽæƒŗį’°åĸƒãĒお**プロジェクト全äŊ“ãŽįŽĄį†**ツãƒŧãƒĢをäŊŋã„ãŸã„ã¨č€ƒãˆãŸã‚‰ã€uv をčŠĻしãĻãŋることをおすすめしぞす。 + +`uv` ではäģĨ下ぎようãĒ多くぎことができぞすīŧš + +* į•°ãĒるバãƒŧã‚¸ãƒ§ãƒŗã‚‚åĢめた**Python ãŽã‚¤ãƒŗã‚šãƒˆãƒŧãƒĢ** +* プロジェクトごとぎ**äģŽæƒŗį’°åĸƒ**ãŽįŽĄį† +* **ãƒ‘ãƒƒã‚ąãƒŧジ**ãŽã‚¤ãƒŗã‚šãƒˆãƒŧãƒĢ +* ãƒ—ãƒ­ã‚¸ã‚§ã‚¯ãƒˆãŽãƒ‘ãƒƒã‚ąãƒŧジぎ**䞝存é–ĸäŋ‚やバãƒŧã‚¸ãƒ§ãƒŗ**ãŽįŽĄį† +* ãƒ‘ãƒƒã‚ąãƒŧジとそぎバãƒŧã‚¸ãƒ§ãƒŗãŽã€äžå­˜é–ĸäŋ‚ã‚’åĢめた**åŽŗå¯†ãĒ**įĩ„ãŋ合わせをäŋæŒã—、これãĢã‚ˆãŖãĻ、æœŦį•Ēį’°åĸƒã§ã€é–‹į™ēį’°åĸƒã¨å…¨ãåŒã˜ã‚ˆã†ãĢãƒ—ãƒ­ã‚¸ã‚§ã‚¯ãƒˆã‚’åŽŸčĄŒã§ãã‚‹īŧˆã“れは**locking**とå‘ŧばれぞすīŧ‰ +* そぎäģ–ぎさぞざぞãĒ抟čƒŊ + +## ぞとめ + +ここぞでčĒ­ãŋすずãĻį†č§Ŗã—ãŸãĒら、世間ぎ多くぎ開į™ēč€…ã¨æ¯”ãšãĻ、äģŽæƒŗį’°åĸƒãĢついãĻ**あãĒたはより多くぎことをįŸĨãŖãĻいぞす**ã€‚đŸ¤“ + +ã“ã‚Œã‚‰ãŽčŠŗį´°ã‚’įŸĨることは、将æĨã€č¤‡é›‘ãĢčĻ‹ãˆã‚‹äŊ•かぎデバッグãĢããŖã¨åŊšįĢ‹ã¤ã§ã—ã‚‡ã†ã€‚ã—ã‹ã—ã€ããŽé ƒãĢは、あãĒたは**そぎすずãĻぎ動äŊœã‚’æ šæœŦから**į†č§Ŗã—ãĻã„ã‚‹ã§ã—ã‚‡ã†ã€‚đŸ˜Ž diff --git a/docs/ko/docs/advanced/custom-response.md b/docs/ko/docs/advanced/custom-response.md new file mode 100644 index 000000000..2001956fa --- /dev/null +++ b/docs/ko/docs/advanced/custom-response.md @@ -0,0 +1,313 @@ +# ė‚ŦėšŠėž ė •ė˜ ė‘ë‹ĩ - HTML, Stream, 파ėŧ, 기타 + +ę¸°ëŗ¸ė ėœŧ로, **FastAPI** ė‘ë‹ĩė„ `JSONResponse`ëĨŧ ė‚ŦėšŠí•˜ė—Ŧ 반환합니다. + +ė´ëĨŧ ėžŦė •ė˜ 하려면 [ė‘ë‹ĩė„ 링렑 반환하기](response-directly.md){.internal-link target=_blank}ė—ė„œ ëŗ¸ 枃래ëŸŧ `Response`ëĨŧ 링렑 반환하면 됩니다. + +꡸ëŸŦ나 `Response` (또는 `JSONResponse`뙀 ę°™ė€ í•˜ėœ„ í´ëž˜ėŠ¤)ëĨŧ 링렑 반환하면, ë°ė´í„°ę°€ ėžë™ėœŧ로 ëŗ€í™˜ë˜ė§€ ė•Šėœŧ늰 (ė‹Ŧ맀떴 `response_model`ė„ ė„ ė–¸í–ˆë”ëŧ도), ëŦ¸ė„œí™”ę°€ ėžë™ėœŧ로 ėƒė„ąë˜ė§€ ė•ŠėŠĩ니다(똈ëĨŧ ë“¤ė–´, ėƒė„ąëœ OpenAPIė˜ ėŧëļ€ëĄœ HTTP 헤더 `Content-Type`뗐 íŠšė • "ë¯¸ë””ė–´ íƒ€ėž…"ė„ íŦ함하는 ę˛Ŋ뚰). + +í•˜ė§€ë§Œ *ę˛Ŋ로 ėž‘ė—… 데ėŊ”ë ˆė´í„°*ė—ė„œ `response_class` ë§¤ę°œëŗ€ėˆ˜ëĨŧ ė‚ŦėšŠí•˜ė—Ŧ ė›í•˜ëŠ” `Response`(똈: ëĒ¨ë“  `Response` í•˜ėœ„ í´ëž˜ėŠ¤)ëĨŧ ė„ ė–¸í•  ėˆ˜ë„ ėžˆėŠĩ니다. + +*ę˛Ŋ로 ėž‘ė—… í•¨ėˆ˜*ė—ė„œ 반환하는 ë‚´ėšŠė€ 해당 `Response`ė•ˆė— íŦ함됩니다. + +꡸ëĻŦęŗ  만ė•Ŋ ꡸ `Response`가 `JSONResponse`뙀 `UJSONResponse`ė˜ ę˛Ŋ뚰 래ëŸŧ JSON ë¯¸ë””ė–´ íƒ€ėž…(`application/json`)ė„ 氀맀溠 ėžˆë‹¤ëŠ´, *ę˛Ŋ로 ėž‘ė—… 데ėŊ”ë ˆė´í„°*ė—ė„œ ė„ ė–¸í•œ Pydanticė˜ `response_model`ė„ ė‚ŦėšŠí•´ ėžë™ėœŧ로 ëŗ€í™˜(및 필터링) 됩니다. + +/// note | 및溠 + +ë¯¸ë””ė–´ íƒ€ėž…ė´ ė—†ëŠ” ė‘ë‹ĩ í´ëž˜ėŠ¤ëĨŧ ė‚ŦėšŠí•˜ëŠ” ę˛Ŋ뚰, FastAPI는 ė‘ë‹ĩ뗐 ë‚´ėšŠė´ ė—†ė„ 것ėœŧ로 ė˜ˆėƒí•˜ë¯€ëĄœ ėƒė„ąëœ OpenAPI ëŦ¸ė„œė—ė„œ ė‘ë‹ĩ í˜•ė‹ė„ ëŦ¸ė„œí™”í•˜ė§€ ė•ŠėŠĩ니다. + +/// + +## `ORJSONResponse` ė‚ŦėšŠí•˜ę¸° + +똈ëĨŧ ë“¤ė–´, ė„ąëŠĨė„ 극대화하려는 ę˛Ŋ뚰, orjsonė„ ė„¤ėš˜í•˜ė—Ŧ ė‚ŦėšŠí•˜ęŗ  ė‘ë‹ĩė„ `ORJSONResponse`로 ė„¤ė •í•  눘 ėžˆėŠĩ니다. + +ė‚ŦėšŠí•˜ęŗ ėž 하는 `Response` í´ëž˜ėŠ¤(í•˜ėœ„ í´ëž˜ėŠ¤)ëĨŧ ėž„íŦ트한 후, **ę˛Ŋ로 ėž‘ė—… 데ėŊ”ë ˆė´í„°*ė—ė„œ ė„ ė–¸í•˜ė„¸ėš”. + +대규ëǍ ė‘ë‹ĩė˜ ę˛Ŋ뚰, ë”•ė…”ë„ˆëĻŦëĨŧ 반환하는 ę˛ƒëŗ´ë‹¤ `Response`ëĨŧ 반환하는 ę˛ƒė´ 훨ė”Ŧ ëš ëĻ…ë‹ˆë‹¤. + +ė´ėœ ëŠ” ę¸°ëŗ¸ė ėœŧ로, FastAPI가 내ëļ€ė˜ ëĒ¨ë“  항ëĒŠė„ 검ė‚Ŧí•˜ęŗ  JSONėœŧ로 링ë Ŧ화할 눘 ėžˆëŠ”ė§€ í™•ė¸í•˜ę¸° 때ëŦ¸ėž…니다. ė´ëŠ” ė‚ŦėšŠėž ė•ˆë‚´ė„œė—ė„œ 네ëĒ…ëœ [JSON 호환 가ëŠĨ ė¸ėŊ”더](../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 ė‘ë‹ĩ + +**FastAPI**ė—ė„œ HTML ė‘ë‹ĩė„ 링렑 반환하려면 `HTMLResponse`ëĨŧ ė‚ŦėšŠí•˜ė„¸ėš”. + +* `HTMLResponse`ëĨŧ ėž„íŦ트 합니다. +* *ę˛Ŋ로 ėž‘ė—… 데ėŊ”ë ˆė´í„°*ė˜ `response_class` ë§¤ę°œëŗ€ėˆ˜ëĄœ `HTMLResponse`ëĨŧ ė „ë‹Ŧ합니다. + +{* ../../docs_src/custom_response/tutorial002.py hl[2,7] *} + +/// info | ė •ëŗ´ + +`response_class` ë§¤ę°œëŗ€ėˆ˜ëŠ” ė‘ë‹ĩė˜ "ë¯¸ë””ė–´ íƒ€ėž…"ė„ ė •ė˜í•˜ëŠ” ë°ė—ë„ ė‚ŦėšŠëŠë‹ˆë‹¤. + +ė´ ę˛Ŋ뚰, HTTP 헤더 `Content-Type`ė€ `text/html`로 ė„¤ė •ëŠë‹ˆë‹¤. + +꡸ëĻŦęŗ  ė´ëŠ” OpenAPI뗐 그대로 ëŦ¸ė„œí™” 됩니다. + +/// + +### `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` ėžŦė •ė˜ 하기 + +í•¨ėˆ˜ 내ëļ€ė—ė„œ ė‘ë‹ĩė„ ėžŦė •ė˜í•˜ëŠ´ė„œ ë™ė‹œė— OpenAPIė—ė„œ "ë¯¸ë””ė–´ íƒ€ėž…"ė„ ëŦ¸ė„œí™”í•˜ęŗ  ė‹ļ다면, `response_class` ë§¤ę˛Œëŗ€ėˆ˜ëĨŧ ė‚ŦėšŠí•˜ëŠ´ė„œ `Response` ę°ė˛´ëĨŧ 반환할 눘 ėžˆėŠĩ니다. + +ė´ ę˛Ŋ뚰 `response_class`는 OpenAPI *ę˛Ŋ로 ėž‘ė—…*ė„ ëŦ¸ė„œí™”하는 데만 ė‚ŦėšŠë˜ęŗ , ė‹¤ė œëĄœëŠ” ė—ŦëŸŦëļ„ė´ 반환한 `Response`가 그대로 ė‚ŦėšŠëŠë‹ˆë‹¤. + +### `HTMLResponse`링렑 반환하기 + +똈ëĨŧ ë“¤ė–´, ë‹¤ėŒęŗŧ ę°™ė´ ėž‘ė„ąí•  눘 ėžˆėŠĩ니다: + +{* ../../docs_src/custom_response/tutorial004.py hl[7,21,23] *} + +ė´ ė˜ˆė œė—ė„œ, `generate_html_response()` í•¨ėˆ˜ëŠ” HTMLė„ `str`로 반환하는 ëŒ€ė‹  ė´ë¯¸ `Response`ëĨŧ ėƒė„ąí•˜ęŗ  반환합니다. + +`generate_html_response()`ëĨŧ 호ėļœí•œ 결ęŗŧëĨŧ 반환함ėœŧëĄœė¨, ę¸°ëŗ¸ė ė¸ **FastAPI** ę¸°ëŗ¸ ë™ėž‘ė„ ėžŦė •ė˜ 하는 `Response`ëĨŧ ė´ë¯¸ ë°˜í™˜í•˜ęŗ  ėžˆėŠĩ니다. + +í•˜ė§€ë§Œ `response_class`뗐 `HTMLResponse`ëĨŧ 함ęģ˜ ė „ë‹Ŧ했기 때ëŦ¸ė—, FastAPI는 ė´ëĨŧ OpenAPI 및 대화형 ëŦ¸ė„œė—ė„œ `text/html`로 HTMLė„ ëŦ¸ė„œí™” 하는 ë°Šë˛•ė„ ė•Œ 눘 ėžˆėŠĩ니다. + + + +## ė‚ŦėšŠ 가ëŠĨ한 ė‘ë‹ĩ들 + +ë‹¤ėŒė€ ė‚ŦėšŠí•  눘 ėžˆëŠ” ëLJ氀맀 ė‘ë‹ĩ들 ėž…ë‹ˆë‹¤. + +`Response`ëĨŧ ė‚ŦėšŠí•˜ė—Ŧ 다ëĨ¸ ė–´ë–¤ 것도 반환 í• ėˆ˜ ėžˆėœŧ늰, 링렑 í•˜ėœ„ í´ëž˜ėŠ¤ëĨŧ 만들 ėˆ˜ë„ ėžˆėŠĩ니다. + +/// note | 揰눠 넏ëļ€ė‚Ŧ항 + +`from starlette.responses import HTMLResponse`ëĨŧ ė‚ŦėšŠí•  ėˆ˜ë„ ėžˆėŠĩ니다. + +**FastAPI**는 ę°œë°œėžė¸ ė—ŦëŸŦëļ„ė˜ íŽ¸ė˜ëĨŧ ėœ„í•´ `starlette.responses`ëĨŧ `fastapi.responses`로 렜ęŗĩ í•˜ė§€ë§Œ, 대ëļ€ëļ„ė˜ ė‚ŦėšŠ 가ëŠĨ한 ė‘ë‹ĩė€ Starletteė—ė„œ 링렑 氀렏ė˜ĩ니다. + +/// + +### `Response` + +ę¸°ëŗ¸ `Response` í´ëž˜ėŠ¤ëŠ” 다ëĨ¸ ëĒ¨ë“  ė‘ë‹ĩ í´ëž˜ėŠ¤ė˜ ëļ€ëǍ í´ëž˜ėŠ¤ ėž…ë‹ˆë‹¤. + +ė´ í´ëž˜ėŠ¤ëĨŧ 링렑 반환할 눘 ėžˆėŠĩ니다. + +ë‹¤ėŒ ë§¤ę°œëŗ€ėˆ˜ëĨŧ ë°›ė„ 눘 ėžˆėŠĩ니다: + +* `content` - `str` 또는 `bytes`. +* `status_code` - HTTP ėƒíƒœėŊ”드ëĨŧ 나타내는 `int`. +* `headers` - ëŦ¸ėžė—´ëĄœ ė´ëŖ¨ė–´ė§„ `dict`. +* `media_type` - ë¯¸ë””ė–´ íƒ€ėž…ė„ 나타내는 `str` 똈: `"text/html"`. + +FastAPI (ė‹¤ė œëĄœëŠ” Starlette)가 ėžë™ėœŧ로 `Content-Length` 헤더ëĨŧ íŦí•¨ė‹œí‚ĩ니다. 또한 `media_type`뗐 기반하ė—Ŧ `Content-Type` 헤더ëĨŧ íŦ함하며, í…ėŠ¤íŠ¸ íƒ€ėž…ė˜ ę˛Ŋ뚰 ëŦ¸ėž ė§‘í•Šė„ ėļ”ę°€ 합니다. + +{* ../../docs_src/response_directly/tutorial002.py hl[1,18] *} + +### `HTMLResponse` + +í…ėŠ¤íŠ¸ 또는 ë°”ė´íŠ¸ëĨŧ ë°›ė•„ HTML ė‘ë‹ĩė„ 반환합니다. ėœ„ė—ė„œ 네ëĒ…í•œ ë‚´ėšŠęŗŧ 같ėŠĩ니다. + +### `PlainTextResponse` + +í…ėŠ¤íŠ¸ 또는 ë°”ė´íŠ¸ëĨŧ ë°›ė•„ ėŧ반 í…ėŠ¤íŠ¸ ė‘ë‹ĩė„ 반환합니다. + +{* ../../docs_src/custom_response/tutorial005.py hl[2,7,9] *} + +### `JSONResponse` + +ë°ė´í„°ëĨŧ ë°›ė•„ `application/json`ėœŧ로 ė¸ėŊ”딊된 ė‘ë‹ĩė„ 반환합니다. + +ė´ëŠ” ėœ„ė—ė„œ 네ëĒ…í–ˆë“¯ė´ **FastAPI**ė—ė„œ ę¸°ëŗ¸ė ėœŧ로 ė‚ŦėšŠë˜ëŠ” ė‘ë‹ĩ í˜•ė‹ėž…ë‹ˆë‹¤. + +### `ORJSONResponse` + + `orjson`ė„ ė‚ŦėšŠí•˜ė—Ŧ ëš ëĨ¸ JSON ė‘ë‹ĩė„ 렜ęŗĩ하는 ëŒ€ė•ˆėž…ë‹ˆë‹¤. ėœ„ė—ė„œ 네ëĒ…í•œ ë‚´ėšŠęŗŧ 같ėŠĩ니다. + +/// info | ė •ëŗ´ + +ė´ëĨŧ ė‚ŦėšŠí•˜ë ¤ëŠ´ `orjson`ė„ ė„¤ėš˜í•´ė•ŧ합니다. 똈: `pip install orjson`. + +/// + +### `UJSONResponse` + +`ujson`ė„ ė‚ŦėšŠí•œ 또 다ëĨ¸ JSON ė‘ë‹ĩ í˜•ė‹ėž…ë‹ˆë‹¤. + +/// info | ė •ëŗ´ + +ė´ ė‘ë‹ĩė„ ė‚ŦėšŠí•˜ë ¤ëŠ´ `ujson`ė„ ė„¤ėš˜í•´ė•ŧ합니다. 똈: 'pip install ujson`. + +/// + +/// warning | ę˛Ŋęŗ  + +`ujson` ė€ ėŧëļ€ ė˜ˆė™¸ ę˛Ŋ뚰ëĨŧ 래ëĻŦ하는 데 ėžˆė–´ Python 내ėžĨ ęĩŦí˜„ëŗ´ë‹¤ 덜 ė—„ę˛Ší•Šë‹ˆë‹¤. + +/// + +{* ../../docs_src/custom_response/tutorial001.py hl[2,7] *} + +/// tip | 팁 + +`ORJSONResponse`가 더 ëš ëĨ¸ ëŒ€ė•ˆėŧ 가ëŠĨė„ąė´ ėžˆėŠĩ니다. + +/// + +### `RedirectResponse` + +HTTP ëĻŦë””ë ‰ė…˜ ė‘ë‹ĩė„ 반환합니다. ę¸°ëŗ¸ė ėœŧ로 ėƒíƒœ ėŊ”드는 307(ėž„ė‹œ ëĻŦë””ë ‰ė…˜)ėœŧ로 ė„¤ė •ëŠë‹ˆë‹¤. + +`RedirectResponse`ëĨŧ 링렑 반환할 눘 ėžˆėŠĩ니다. + +{* ../../docs_src/custom_response/tutorial006.py hl[2,9] *} + +--- + +또는 `response_class` ë§¤ę°œëŗ€ėˆ˜ė—ė„œ ė‚ŦėšŠí•  ėˆ˜ë„ ėžˆėŠĩ니다: + + +{* ../../docs_src/custom_response/tutorial006b.py hl[2,7,9] *} + +ė´ ę˛Ŋ뚰, *ę˛Ŋ로 ėž‘ė—…* í•¨ėˆ˜ė—ė„œ URLė„ 링렑 반환할 눘 ėžˆėŠĩ니다. + +ė´ ę˛Ŋ뚰, ė‚ŦėšŠë˜ëŠ” `status_code`는 `RedirectResponse`ė˜ ę¸°ëŗ¸ę°’ė¸ `307` ėž…ë‹ˆë‹¤. + +--- + +`status_code` ë§¤ę°œëŗ€ėˆ˜ëĨŧ `response_class` ë§¤ę°œëŗ€ėˆ˜ė™€ 함ęģ˜ ė‚ŦėšŠí•  ėˆ˜ë„ ėžˆėŠĩ니다: + +{* ../../docs_src/custom_response/tutorial006c.py hl[2,7,9] *} + +### `StreamingResponse` + +비동기 ė œë„ˆë ˆė´í„° 또는 ėŧ반 ė œë„ˆë ˆė´í„°/ė´í„°ë ˆė´í„°ëĨŧ ë°›ė•„ ė‘ë‹ĩ ëŗ¸ëŦ¸ė„ ėŠ¤íŠ¸ëĻŦ밍 합니다. + +{* ../../docs_src/custom_response/tutorial007.py hl[2,14] *} + +#### 파ėŧęŗŧ ę°™ė€ ę°ė˛´ëĨŧ ė‚ŦėšŠí•œ `StreamingResponse` + +파ėŧęŗŧ ę°™ė€ ę°ė˛´(똈: `open()`ėœŧ로 반환된 ę°ė˛´)가 ėžˆëŠ” ę˛Ŋ뚰, 해당 파ėŧęŗŧ ę°™ė€ ę°ė˛´ëĨŧ 반ëŗĩ(iterate)하는 ė œë„ˆë ˆė´í„° í•¨ėˆ˜ëĨŧ 만들 눘 ėžˆėŠĩ니다. + +ė´ ë°Šė‹ėœŧ로, 파ėŧ 렄랴ëĨŧ 메ëǍëĻŦ뗐 ë¨ŧė € ėŊė–´ë“¤ėŧ í•„ėš” ė—†ė´, ė œë„ˆë ˆė´í„° í•¨ėˆ˜ëĨŧ `StreamingResponse`뗐 ė „ë‹Ŧ하ė—Ŧ 반환할 눘 ėžˆėŠĩ니다. + +ė´ ë°Šė‹ė€ 클ëŧėš°ë“œ ėŠ¤í† ëĻŦė§€, ëš„ë””ė˜¤ 래ëĻŦ ë“ąė˜ ë‹¤ė–‘í•œ ëŧė´ë¸ŒëŸŦëĻŦ뙀 함ęģ˜ ė‚ŦėšŠí•  눘 ėžˆėŠĩ니다. + +{* ../../docs_src/custom_response/tutorial008.py hl[2,10:12,14] *} + +1. ė´ę˛ƒė´ ė œë„ˆë ˆė´í„° í•¨ėˆ˜ėž…ë‹ˆë‹¤. `yield` ëŦ¸ė„ íŦí•¨í•˜ęŗ  ėžˆėœŧë¯€ëĄœ "ė œë„ˆë ˆė´í„° í•¨ėˆ˜"ėž…ë‹ˆë‹¤. +2. `with` ë¸”ëĄė„ ė‚ŦėšŠí•¨ėœŧëĄœė¨, ė œë„ˆë ˆė´í„° í•¨ėˆ˜ę°€ ė™„ëŖŒëœ 후 파ėŧęŗŧ ę°™ė€ ę°ė˛´ę°€ ë‹Ģ히도록 합니다. ėω, ė‘ë‹ĩ ė „ė†Ąė´ 끝난 후 ë‹Ģ힙니다. +3. ė´ `yield from`ė€ í•¨ėˆ˜ę°€ `file_like`ëŧ는 ę°ė˛´ëĨŧ 반ëŗĩ(iterate)하도록 합니다. 반ëŗĩ된 각 ëļ€ëļ„ė€ ė´ ė œë„ˆë ˆė´í„° í•¨ėˆ˜(`iterfile`)ė—ė„œ ėƒė„ąëœ 枃래ëŸŧ `yield` 됩니다. + + ė´ë ‡ę˛Œ 하면 "ėƒė„ą(generating)" ėž‘ė—…ė„ 내ëļ€ė ėœŧ로 다ëĨ¸ ëŦ´ė–¸ę°€ė— ėœ„ėž„í•˜ëŠ” ė œë„ˆë ˆė´í„° í•¨ėˆ˜ę°€ 됩니다. + + ė´ ë°Šė‹ė„ ė‚ŦėšŠí•˜ëŠ´ `with` 블록 ė•ˆė—ė„œ 파ėŧė„ ė—´ 눘 ėžˆė–´, ėž‘ė—…ė´ ė™„ëŖŒëœ 후 파ėŧęŗŧ ę°™ė€ ę°ė˛´ę°€ ë‹Ģ히는 ę˛ƒė„ ëŗ´ėžĨ할 눘 ėžˆėŠĩ니다. + +/// tip | 팁 + +ė—Ŧę¸°ė„œ í‘œė¤€ `open()`ė„ ė‚ŦėšŠí•˜ęŗ  ėžˆę¸° 때ëŦ¸ė— `async`뙀 `await`ëĨŧ ė§€ė›í•˜ė§€ ė•ŠėŠĩ니다. 따ëŧė„œ ę˛Ŋ로 ėž‘ė—…ė€ ėŧ반 `def`로 ė„ ė–¸í•Šë‹ˆë‹¤. + +/// + +### `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] *} + +ė´ ę˛Ŋ뚰, ę˛Ŋ로 ėž‘ė—… í•¨ėˆ˜ė—ė„œ 파ėŧ ę˛Ŋ로ëĨŧ 링렑 반환할 눘 ėžˆėŠĩ니다. + +## ė‚ŦėšŠėž ė •ė˜ ė‘ë‹ĩ í´ëž˜ėŠ¤ + +`Response`ëĨŧ ėƒė†ë°›ė•„ ė‚ŦėšŠėž ė •ė˜ ė‘ë‹ĩ í´ëž˜ėŠ¤ëĨŧ ėƒė„ąí•˜ęŗ  ė‚ŦėšŠí•  눘 ėžˆėŠĩ니다. + +똈ëĨŧ ë“¤ė–´, íŦ함된 `ORJSONResponse` í´ëž˜ėŠ¤ė—ė„œ ė‚ŦėšŠë˜ė§€ ė•ŠëŠ” 네렕ėœŧ로 orjsonė„ ė‚ŦėšŠí•˜ęŗ  ė‹ļë‹¤ęŗ  ę°€ė •í•´ë´…ė‹œë‹¤. + +만ė•Ŋ 들ė—Ŧ듰揰 및 íŦ맷된 JSONė„ ë°˜í™˜í•˜ęŗ  ė‹ļ다면, `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 íŦë§ˇíŒ…ëŗ´ë‹¤ 더 ėœ ėšŠí•˜ę˛Œ í™œėšŠí•  ë°Šë˛•ė„ ė°žė„ 눘 ėžˆė„ ę˛ƒėž…ë‹ˆë‹¤. 😉 + +## ę¸°ëŗ¸ ė‘ë‹ĩ í´ëž˜ėŠ¤ + +**FastAPI** í´ëž˜ėŠ¤ ę°ė˛´ 또는 `APIRouter`ëĨŧ ėƒė„ąí•  때 ę¸°ëŗ¸ė ėœŧ로 ė‚ŦėšŠí•  ė‘ë‹ĩ í´ëž˜ėŠ¤ëĨŧ ė§€ė •í•  눘 ėžˆėŠĩ니다. + +ė´ëĨŧ ė •ė˜í•˜ëŠ” ë§¤ę°œëŗ€ėˆ˜ëŠ” `default_response_class`ėž…ë‹ˆë‹¤. + +ė•„ëž˜ ė˜ˆė œė—ė„œ **FastAPI**는 ëĒ¨ë“  ę˛Ŋ로 ėž‘ė—…ė—ė„œ ę¸°ëŗ¸ė ėœŧ로 `JSONResponse` ëŒ€ė‹  `ORJSONResponse`ëĨŧ ė‚ŦėšŠí•Šë‹ˆë‹¤. + +{* ../../docs_src/custom_response/tutorial010.py hl[2,4] *} + +/// tip | 팁 + +ė—Ŧė „ížˆ ė´ė „ė˛˜ëŸŧ *ę˛Ŋ로 ėž‘ė—…*ė—ė„œ `response_class`ëĨŧ ėžŦė •ė˜í•  눘 ėžˆėŠĩ니다. + +/// + +## ėļ”ę°€ ëŦ¸ė„œí™” + +OpenAPIė—ė„œ `responses`ëĨŧ ė‚ŦėšŠí•˜ė—Ŧ ë¯¸ë””ė–´ íƒ€ėž… 및 기타 넏ëļ€ ė •ëŗ´ëĨŧ ė„ ė–¸í•  ėˆ˜ë„ ėžˆėŠĩ니다: [OpenAPIė—ė„œ ėļ”ę°€ ė‘ë‹ĩ](additional-responses.md){.internal-link target=_blank}. diff --git a/docs/ko/docs/advanced/events.md b/docs/ko/docs/advanced/events.md index ae349e7be..5f8fe0f1e 100644 --- a/docs/ko/docs/advanced/events.md +++ b/docs/ko/docs/advanced/events.md @@ -1,53 +1,165 @@ -# ė´ë˛¤íŠ¸: startupęŗŧ shutdown +# Lifespan ė´ë˛¤íŠ¸ -í•„ėš”ė— 따ëŧ ė‘ėšŠ í”„ëĄœęˇ¸ëž¨ė´ ė‹œėž‘ë˜ę¸° ė „ė´ë‚˜ ėĸ…ëŖŒë  때 ė‹¤í–‰ë˜ëŠ” ė´ë˛¤íŠ¸ 핸들ëŸŦ(í•¨ėˆ˜)ëĨŧ ė •ė˜í•  눘 ėžˆėŠĩ니다. +ė• í”ŒëĻŦėŧ€ė´ė…˜ **ė‹œėž‘ ė „**뗐 ė‹¤í–‰ë˜ė–´ė•ŧ 하는 ëĄœė§(ėŊ”드)ė„ ė •ė˜í•  눘 ėžˆėŠĩ니다. ė´ëŠ” ė´ ėŊ”ë“œę°€ **한 번**만 ė‹¤í–‰ë˜ëŠ°, **ė• í”ŒëĻŦėŧ€ė´ė…˜ė´ ėš”ė˛­ė„ 받기 ė‹œėž‘í•˜ę¸° ė „**뗐 ė‹¤í–‰ëœë‹¤ëŠ” ė˜ë¯¸ėž…ë‹ˆë‹¤. -ė´ í•¨ėˆ˜ë“¤ė€ `async def` 또는 평범하게 `def`ėœŧ로 ė„ ė–¸í•  눘 ėžˆėŠĩ니다. +마ė°Ŧę°€ė§€ëĄœ, ė• í”ŒëĻŦėŧ€ė´ė…˜ė´ **ėĸ…ëŖŒë  때** ė‹¤í–‰ë˜ė–´ė•ŧ 하는 ëĄœė§(ėŊ”드)ė„ ė •ė˜í•  눘 ėžˆėŠĩ니다. ė´ ę˛Ŋ뚰, ė´ ėŊ”드는 **한 번**만 ė‹¤í–‰ë˜ëŠ°, **ė—ŦëŸŦ ėš”ė˛­ė„ 래ëĻŦ한 후**뗐 ė‹¤í–‰ëŠë‹ˆë‹¤. + +ė´ ėŊ”ë“œę°€ ė• í”ŒëĻŦėŧ€ė´ė…˜ė´ **ėš”ė˛­ė„ 받기 ė‹œėž‘í•˜ę¸° 렄뗐** ė‹¤í–‰ë˜ęŗ , ėš”ė˛­ 래ëĻŦ가 끝난 후 **ėĸ…ëŖŒ 링렄뗐** ė‹¤í–‰ë˜ę¸° 때ëŦ¸ė— 렄랴 ė• í”ŒëĻŦėŧ€ė´ė…˜ė˜ **눘ëĒ…(Lifespan)**ė„ ë‹¤ëŖšë‹ˆë‹¤. (ėž ė‹œ 후 "눘ëĒ…"ė´ëŧ는 ë‹¨ė–´ę°€ ė¤‘ėš”í•´ė§‘ë‹ˆë‹¤ 😉) + +ė´ ë°Šë˛•ė€ 렄랴 ė• í”ŒëĻŦėŧ€ė´ė…˜ė—ė„œ ė‚ŦėšŠí•´ė•ŧ 하는 **ėžė›**ė„ ė„¤ė •í•˜ęą°ë‚˜ ėš”ė˛­ 氄뗐 **ęŗĩėœ ë˜ëŠ”** ėžė›ė„ ė„¤ė •í•˜ęŗ , 또는 ꡸ í›„ė— **ė •ëĻŦ**하는 데 ë§¤ėš° ėœ ėšŠí•  눘 ėžˆėŠĩ니다. 똈ëĨŧ ë“¤ė–´, ë°ė´í„°ë˛ ė´ėŠ¤ 뗰枰 풀 또는 ęŗĩėœ ë˜ëŠ” ë¨¸ė‹ ëŸŦ닝 ëĒ¨ë¸ė„ 로드하는 ę˛Ŋėš°ėž…ë‹ˆë‹¤. + + +## ė‚ŦėšŠ ė‚Ŧ례 + +ë¨ŧė € **ė‚ŦėšŠ ė‚Ŧ례**ëĨŧ ė˜ˆëĄœ ë“¤ė–´ëŗ´ęŗ , ė´ëĨŧ ė–´ë–ģ枌 해결할 눘 ėžˆëŠ”ė§€ ė‚´íŽ´ëŗ´ę˛ ėŠĩ니다. + +뚰ëĻŦ가 ėš”ė˛­ė„ 래ëĻŦ하기 ėœ„í•´ ė‚ŦėšŠí•˜ęŗ  ė‹ļė€ **ë¨¸ė‹ ëŸŦ닝 ëĒ¨ë¸**ė´ ėžˆë‹¤ęŗ  ėƒėƒí•´ ë´…ė‹œë‹¤. 🤖 + +ė´ ëĒ¨ë¸ë“¤ė€ ėš”ė˛­ 氄뗐 ęŗĩėœ ë˜ë¯€ëĄœ, ėš”ė˛­ë§ˆë‹¤ ëĒ¨ë¸ė´ í•˜ë‚˜ė”Š ėžˆëŠ” ę˛ƒė´ ė•„ë‹ˆëŧ, ė—ŦëŸŦ ėš”ė˛­ė—ė„œ 동ėŧ한 ëĒ¨ë¸ė„ ė‚ŦėšŠí•Šë‹ˆë‹¤. + +ëĒ¨ë¸ė„ 로드하는 데 **ėƒë‹ší•œ ė‹œę°„ė´ 깸ëĻ°ë‹¤ęŗ  ėƒėƒí•´ ë´…ė‹œë‹¤**, ė™œëƒí•˜ëŠ´ ëĒ¨ë¸ė´ **ë””ėŠ¤íŦė—ė„œ ë§Žė€ ë°ė´í„°ëĨŧ ėŊė–´ė•ŧ** 하기 때ëŦ¸ėž…니다. 따ëŧė„œ ëĒ¨ë“  ėš”ė˛­ė— 대해 ëĒ¨ë¸ė„ 매번 ëĄœë“œí•˜ęŗ  ė‹ļė§€ ė•ŠėŠĩ니다. + +ëĒ¨ë“ˆ/파ėŧė˜ ėĩœėƒėœ„ė—ė„œ ëĒ¨ë¸ė„ 로드할 ėˆ˜ë„ ėžˆė§€ë§Œ, ꡸ëŸŦ늴 **ëĒ¨ë¸ė„ 로드하는데** ė‹œę°„ė´ 깸ëĻŦ기 때ëŦ¸ė—, ë‹¨ėˆœí•œ ėžë™í™”ëœ í…ŒėŠ¤íŠ¸ëĨŧ ė‹¤í–‰í•  때도 ëĒ¨ë¸ė´ 로드될 ë•ŒęšŒė§€ 기다려ė•ŧ í•´ė„œ **í…ŒėŠ¤íŠ¸ ė†ë„ę°€ ëŠë ¤ė§‘ë‹ˆë‹¤**. + +ė´ ëŦ¸ė œëĨŧ í•´ę˛°í•˜ë ¤ęŗ  하는 ę˛ƒėž…ë‹ˆë‹¤. ėš”ė˛­ė„ 래ëĻŦ하기 렄뗐 ëĒ¨ë¸ė„ 로드하되, ė• í”ŒëĻŦėŧ€ė´ė…˜ė´ ėš”ė˛­ė„ 받기 ė‹œėž‘í•˜ę¸° ė§ė „ė—ë§Œ ëĄœë“œí•˜ęŗ , ėŊ”ë“œę°€ 로드되는 ë™ė•ˆė€ ëĄœë“œí•˜ė§€ ė•Šë„ëĄ 하겠ėŠĩ니다. + +## Lifespan + +`FastAPI` ė• í”ŒëĻŦėŧ€ė´ė…˜ė˜ `lifespan` ë§¤ę°œëŗ€ėˆ˜ė™€ "ėģ¨í…ėŠ¤íŠ¸ ë§¤ë‹ˆė €"ëĨŧ ė‚ŦėšŠí•˜ė—Ŧ *ė‹œėž‘*ęŗŧ *ėĸ…ëŖŒ* ëĄœė§ė„ ė •ė˜í•  눘 ėžˆėŠĩ니다. (ėģ¨í…ėŠ¤íŠ¸ ë§¤ë‹ˆė €ę°€ ëŦ´ė—‡ė¸ė§€ ėž ė‹œ í›„ė— 네ëĒ…ë“œëĻŦ겠ėŠĩ니다.) + +똈렜ëĨŧ í†ĩ해 ė‹œėž‘í•˜ęŗ , ꡸ í›„ė— ėžė„¸ížˆ ė‚´íŽ´ëŗ´ę˛ ėŠĩ니다. + +뚰ëĻŦ는 `yield`ëĨŧ ė‚ŦėšŠí•˜ė—Ŧ 비동기 í•¨ėˆ˜ `lifespan()`ė„ ë‹¤ėŒęŗŧ ę°™ė´ ėƒė„ąí•Šë‹ˆë‹¤: + +{* ../../docs_src/events/tutorial003.py hl[16,19] *} + +ė—Ŧę¸°ė„œ 뚰ëĻŦ는 ëĒ¨ë¸ė„ 로드하는 비ė‹ŧ *ė‹œėž‘* ėž‘ė—…ė„ ė‹œëŽŦë ˆė´ė…˜í•˜ęŗ  ėžˆėŠĩ니다. `yield` ė•žė—ė„œ (ę°€ė§œ) ëĒ¨ë¸ í•¨ėˆ˜ëĨŧ ë¨¸ė‹ ëŸŦ닝 ëĒ¨ë¸ė´ 담긴 ë”•ė…”ë„ˆëĻŦ뗐 ë„ŖėŠĩ니다. ė´ ėŊ”드는 **ė• í”ŒëĻŦėŧ€ė´ė…˜ė´ ėš”ė˛­ė„ 받기 ė‹œėž‘í•˜ę¸° ė „**, *ė‹œėž‘* ë™ė•ˆė— ė‹¤í–‰ëŠë‹ˆë‹¤. + +꡸ëĻŦęŗ  `yield` ė§í›„ė—ëŠ” ëĒ¨ë¸ė„ ė–¸ëĄœë“œí•Šë‹ˆë‹¤. ė´ ėŊ”드는 **ė• í”ŒëĻŦėŧ€ė´ė…˜ė´ ėš”ė˛­ 래ëĻŦ ė™„ëŖŒ 후**, *ėĸ…ëŖŒ* 링렄뗐 ė‹¤í–‰ëŠë‹ˆë‹¤. 똈ëĨŧ ë“¤ė–´, 메ëǍëĻŦ나 GPU뙀 ę°™ė€ ėžė›ė„ í•´ė œí•˜ëŠ” ėž‘ė—…ė„ 할 눘 ėžˆėŠĩ니다. + +/// tip | 팁 + +`shutdown`ė€ ė• í”ŒëĻŦėŧ€ė´ė…˜ė„ **ėĸ…ëŖŒ**할 때 ë°œėƒí•Šë‹ˆë‹¤. + +ėƒˆëĄœėš´ ë˛„ė „ė„ ė‹œėž‘í•´ė•ŧ 하거나, ꡸ëƒĨ ė‹¤í–‰ė„ 늈ėļ”ęŗ  ė‹ļė„ ėˆ˜ë„ ėžˆėŠĩ니다. 🤷 + +/// + +### Lifespan í•¨ėˆ˜ + +ë¨ŧė € ėŖŧëĒŠí•  ė ė€, `yield`ëĨŧ ė‚ŦėšŠí•˜ė—Ŧ 비동기 í•¨ėˆ˜(async function)ëĨŧ ė •ė˜í•˜ęŗ  ėžˆë‹¤ëŠ” ę˛ƒėž…ë‹ˆë‹¤. ė´ëŠ” `yield`ëĨŧ ė‚ŦėšŠí•œ ė˜ėĄ´ė„ąęŗŧ ë§¤ėš° 뜠ė‚Ŧ합니다. + +{* ../../docs_src/events/tutorial003.py hl[14:19] *} + +í•¨ėˆ˜ė˜ ė˛Ģ ë˛ˆė§¸ ëļ€ëļ„, ėω `yield` ė´ė „ė˜ ėŊ”드는 ė• í”ŒëĻŦėŧ€ė´ė…˜ė´ ė‹œėž‘ë˜ę¸° **렄뗐** ė‹¤í–‰ëŠë‹ˆë‹¤. + +꡸ëĻŦęŗ  `yield` ė´í›„ė˜ ëļ€ëļ„ė€ ė• í”ŒëĻŦėŧ€ė´ė…˜ė´ ė™„ëŖŒëœ 후 **ë‚˜ė¤‘ė—** ė‹¤í–‰ëŠë‹ˆë‹¤. + +### 비동기 ėģ¨í…ėŠ¤íŠ¸ ë§¤ë‹ˆė € + +í•¨ėˆ˜ëĨŧ í™•ė¸í•´ëŗ´ëŠ´, `@asynccontextmanager`로 ėžĨė‹ë˜ė–´ ėžˆėŠĩ니다. + +ė´ę˛ƒė€ í•¨ėˆ˜ëĨŧ "**비동기 ėģ¨í…ėŠ¤íŠ¸ ë§¤ë‹ˆė €**"ëŧęŗ  ëļˆëĻŦ는 것ėœŧ로 ëŗ€í™˜ė‹œí‚ĩ니다. + +{* ../../docs_src/events/tutorial003.py hl[1,13] *} + +íŒŒė´ėŦė—ė„œ **ėģ¨í…ėŠ¤íŠ¸ ë§¤ë‹ˆė €**는 `with` ëŦ¸ė—ė„œ ė‚ŦėšŠí•  눘 ėžˆëŠ” ę˛ƒėž…ë‹ˆë‹¤. 똈ëĨŧ ë“¤ė–´, `open()`ė€ ėģ¨í…ėŠ¤íŠ¸ ë§¤ë‹ˆė €ëĄœ ė‚ŦėšŠí•  눘 ėžˆėŠĩ니다: + +```Python +with open("file.txt") as file: + file.read() +``` +ėĩœęˇŧ ë˛„ė „ė˜ íŒŒė´ėŦė—ė„œëŠ” **비동기 ėģ¨í…ėŠ¤íŠ¸ ë§¤ë‹ˆė €**도 ėžˆėŠĩ니다. ė´ëĨŧ `async with`뙀 함ęģ˜ ė‚ŦėšŠí•Šë‹ˆë‹¤: + +```Python +async with lifespan(app): + await do_stuff() +``` + +ėģ¨í…ėŠ¤íŠ¸ ë§¤ë‹ˆė €ë‚˜ ėœ„ė™€ ę°™ė€ 비동기 ėģ¨í…ėŠ¤íŠ¸ ë§¤ë‹ˆė €ëĨŧ 만들면, `with` ë¸”ëĄė— ë“¤ė–´ę°€ę¸° 렄뗐 `yield` ė´ė „ė˜ ėŊ”ë“œę°€ ė‹¤í–‰ë˜ęŗ , `with` ë¸”ëĄė„ ë˛—ė–´ë‚œ í›„ė—ëŠ” `yield` ė´í›„ė˜ ėŊ”ë“œę°€ ė‹¤í–‰ëŠë‹ˆë‹¤. + +ėœ„ė˜ ėŊ”드 ė˜ˆė œė—ė„œëŠ” 링렑 ė‚ŦėšŠí•˜ė§€ ė•Šęŗ , FastAPI뗐 ė „ë‹Ŧ하ė—Ŧ ė‚ŦėšŠí•˜ë„ëĄ 합니다. + +`FastAPI` ė• í”ŒëĻŦėŧ€ė´ė…˜ė˜ `lifespan` ë§¤ę°œëŗ€ėˆ˜ëŠ” **비동기 ėģ¨í…ėŠ¤íŠ¸ ë§¤ë‹ˆė €**ëĨŧ 받기 때ëŦ¸ė—, ėƒˆëĄœėš´ `lifespan` 비동기 ėģ¨í…ėŠ¤íŠ¸ ë§¤ë‹ˆė €ëĨŧ FastAPI뗐 ė „ë‹Ŧ할 눘 ėžˆėŠĩ니다. + +{* ../../docs_src/events/tutorial003.py hl[22] *} + +## ëŒ€ė˛´ ė´ë˛¤íŠ¸ (ė‚ŦėšŠ ė¤‘ë‹¨) /// warning | ę˛Ŋęŗ  -ė´ë˛¤íŠ¸ 핸들ëŸŦ는 ėŖŧ ė‘ėšŠ í”„ëĄœęˇ¸ëž¨ė—ė„œë§Œ ėž‘ë™í•Šë‹ˆë‹¤. [í•˜ėœ„ ė‘ėšŠ 프로그램 - ë§ˆėš´íŠ¸](./sub-applications.md){.internal-link target=_blank}ė—ė„œëŠ” ėž‘ë™í•˜ė§€ ė•ŠėŠĩ니다. +*ė‹œėž‘*ęŗŧ *ėĸ…ëŖŒ*ëĨŧ 래ëĻŦ하는 ęļŒėžĨ ë°Šë˛•ė€ ėœ„ė—ė„œ 네ëĒ…í•œ 대로 `FastAPI` ė• í”ŒëĻŦėŧ€ė´ė…˜ė˜ `lifespan` ë§¤ę°œëŗ€ėˆ˜ëĨŧ ė‚ŦėšŠí•˜ëŠ” ę˛ƒėž…ë‹ˆë‹¤. `lifespan` ë§¤ę°œëŗ€ėˆ˜ëĨŧ 렜ęŗĩ하면 `startup`ęŗŧ `shutdown` ė´ë˛¤íŠ¸ 핸들ëŸŦ는 더 ė´ėƒ 호ėļœë˜ė§€ ė•ŠėŠĩ니다. `lifespan`ė„ ė‚ŦėšŠí• ė§€, ëĒ¨ë“  ė´ë˛¤íŠ¸ëĨŧ ė‚ŦėšŠí• ė§€ ė„ íƒí•´ė•ŧ 하며 둘 다 ė‚ŦėšŠí•  ėˆ˜ëŠ” ė—†ėŠĩ니다. + +ė´ ëļ€ëļ„ė€ ęą´ë„ˆë›°ė…”ë„ ėĸ‹ėŠĩ니다. /// -## `startup` ė´ë˛¤íŠ¸ +*ė‹œėž‘*ęŗŧ *ėĸ…ëŖŒ* ë™ė•ˆ ė‹¤í–‰ë  ė´ ëĄœė§ė„ ė •ė˜í•˜ëŠ” ëŒ€ė˛´ ë°Šë˛•ė´ ėžˆėŠĩ니다. + +ė• í”ŒëĻŦėŧ€ė´ė…˜ė´ ė‹œėž‘ë˜ę¸° 렄뗐 또는 ėĸ…ëŖŒë  때 ė‹¤í–‰í•´ė•ŧ 하는 ė´ë˛¤íŠ¸ 핸들ëŸŦ(í•¨ėˆ˜)ëĨŧ ė •ė˜í•  눘 ėžˆėŠĩ니다. -ė‘ėšŠ í”„ëĄœęˇ¸ëž¨ė„ ė‹œėž‘í•˜ę¸° 렄뗐 ė‹¤í–‰í•˜ë ¤ëŠ” í•¨ėˆ˜ëĨŧ "startup" ė´ë˛¤íŠ¸ëĄœ ė„ ė–¸í•Šë‹ˆë‹¤: +ė´ í•¨ėˆ˜ë“¤ė€ `async def` 또는 ėŧ반 `def`로 ė„ ė–¸í•  눘 ėžˆėŠĩ니다. + +### `startup` ė´ë˛¤íŠ¸ + +ė• í”ŒëĻŦėŧ€ė´ė…˜ė´ ė‹œėž‘ë˜ę¸° 렄뗐 ė‹¤í–‰ë˜ė–´ė•ŧ 하는 í•¨ėˆ˜ëĨŧ ėļ”ę°€í•˜ë ¤ëŠ´, `"startup"` ė´ë˛¤íŠ¸ëĄœ ė„ ė–¸í•Šë‹ˆë‹¤: {* ../../docs_src/events/tutorial001.py hl[8] *} -ė´ ę˛Ŋ뚰 `startup` ė´ë˛¤íŠ¸ 핸들ëŸŦ í•¨ėˆ˜ëŠ” ë‹¨ėˆœížˆ ëLJ 氀맀 값ėœŧ로 ęĩŦė„ąëœ `dict` í˜•ė‹ė˜ "ë°ė´í„°ë˛ ė´ėŠ¤"ëĨŧ ė´ˆę¸°í™”í•Šë‹ˆë‹¤. +ė´ ę˛Ŋ뚰, `startup` ė´ë˛¤íŠ¸ 핸들ëŸŦ í•¨ėˆ˜ëŠ” "database"ëŧ는 항ëĒŠ(ë‹¨ė§€ `dict`)ė„ ėŧëļ€ ę°’ėœŧ로 ė´ˆę¸°í™”í•Šë‹ˆë‹¤. -하나 ė´ėƒė˜ ė´ë˛¤íŠ¸ 핸들ëŸŦ í•¨ėˆ˜ëĨŧ ėļ”가할 ėˆ˜ë„ ėžˆėŠĩ니다. +ė—ŦëŸŦ ę°œė˜ ė´ë˛¤íŠ¸ 핸들ëŸŦ í•¨ėˆ˜ëĨŧ ėļ”가할 눘 ėžˆėŠĩ니다. -꡸ëĻŦęŗ  ė‘ėšŠ í”„ëĄœęˇ¸ëž¨ė€ ëĒ¨ë“  `startup` ė´ë˛¤íŠ¸ 핸들ëŸŦ가 ė™„ëŖŒë  ë•ŒęšŒė§€ ėš”ė˛­ė„ ë°›ė§€ ė•ŠėŠĩ니다. +ė• í”ŒëĻŦėŧ€ė´ė…˜ė€ ëĒ¨ë“  `startup` ė´ë˛¤íŠ¸ 핸들ëŸŦ가 ė™„ëŖŒë  ë•ŒęšŒė§€ ėš”ė˛­ė„ 받기 ė‹œėž‘í•˜ė§€ ė•ŠėŠĩ니다. -## `shutdown` ė´ë˛¤íŠ¸ +### `shutdown` ė´ë˛¤íŠ¸ -ė‘ėšŠ í”„ëĄœęˇ¸ëž¨ė´ ėĸ…ëŖŒë  때 ė‹¤í–‰í•˜ë ¤ëŠ” í•¨ėˆ˜ëĨŧ ėļ”ę°€í•˜ë ¤ëŠ´ `"shutdown"` ė´ë˛¤íŠ¸ëĄœ ė„ ė–¸í•Šë‹ˆë‹¤: +ė• í”ŒëĻŦėŧ€ė´ė…˜ė´ ėĸ…ëŖŒë  때 ė‹¤í–‰ë˜ė–´ė•ŧ 하는 í•¨ėˆ˜ëĨŧ ėļ”ę°€í•˜ë ¤ëŠ´, `"shutdown"` ė´ë˛¤íŠ¸ëĄœ ė„ ė–¸í•Šë‹ˆë‹¤: {* ../../docs_src/events/tutorial002.py hl[6] *} -ė´ ė˜ˆė œė—ė„œ `shutdown` ė´ë˛¤íŠ¸ 핸들ëŸŦ í•¨ėˆ˜ëŠ” `"Application shutdown"`ė´ëŧ는 í…ėŠ¤íŠ¸ę°€ ė ížŒ `log.txt` 파ėŧė„ ėļ”가할 ę˛ƒėž…ë‹ˆë‹¤. +ė—Ŧę¸°ė„œ, `shutdown` ė´ë˛¤íŠ¸ 핸들ëŸŦ í•¨ėˆ˜ëŠ” `"Application shutdown"`ė´ëŧ는 í…ėŠ¤íŠ¸ëĨŧ `log.txt` 파ėŧ뗐 기록합니다. /// info | ė •ëŗ´ -`open()` í•¨ėˆ˜ė—ė„œ `mode="a"`는 "ėļ”ę°€"ëĨŧ ė˜ë¯¸í•Šë‹ˆë‹¤. 따ëŧė„œ ė´ë¯¸ ėĄ´ėžŦ하는 파ėŧė˜ ë‚´ėšŠė„ ëŽė–´ė“°ė§€ ė•Šęŗ  ėƒˆëĄœėš´ ė¤„ė„ ėļ”ę°€í•Šë‹ˆë‹¤. +`open()` í•¨ėˆ˜ė—ė„œ `mode="a"`는 "ėļ”ę°€"ëĨŧ ė˜ë¯¸í•˜ë¯€ëĄœ, 파ėŧ뗐 ėžˆëŠ” ę¸°ėĄ´ ë‚´ėšŠė€ ëŽė–´ė“°ė§€ ė•Šęŗ  ėƒˆëĄœėš´ ė¤„ė´ ėļ”ę°€ëŠë‹ˆë‹¤. /// /// tip | 팁 -ė´ ė˜ˆė œė—ė„œëŠ” 파ėŧęŗŧ ėƒí˜¸ėž‘ėšŠ 하기 ėœ„í•´ íŒŒė´ėŦ í‘œė¤€ í•¨ėˆ˜ė¸ `open()`ė„ ė‚ŦėšŠí•˜ęŗ  ėžˆėŠĩ니다. +ė´ ę˛Ŋ뚰, 뚰ëĻŦ는 í‘œė¤€ íŒŒė´ėŦ `open()` í•¨ėˆ˜ëĨŧ ė‚ŦėšŠí•˜ė—Ŧ 파ėŧęŗŧ ėƒí˜¸ėž‘ėšŠí•˜ęŗ  ėžˆėŠĩ니다. -따ëŧė„œ ë””ėŠ¤íŦ뗐 ë°ė´í„°ëĨŧ 듰揰 ėœ„í•´ "대기"가 í•„ėš”í•œ I/O (ėž…ë Ĩ/ėļœë Ĩ) ėž‘ė—…ė„ ėˆ˜í–‰í•Šë‹ˆë‹¤. +따ëŧė„œ I/O(ėž…ėļœë Ĩ) ėž‘ė—…ė´ íŦí•¨ë˜ė–´ ėžˆė–´ ë””ėŠ¤íŦ뗐 기록되는 ę˛ƒė„ "기다ëĻŦ는" ęŗŧė •ė´ í•„ėš”í•Šë‹ˆë‹¤. -꡸ëŸŦ나 `open()`ė€ `async`뙀 `await`ė„ ė‚ŦėšŠí•˜ė§€ ė•Šę¸° 때ëŦ¸ė— ė´ë˛¤íŠ¸ 핸들ëŸŦ í•¨ėˆ˜ëŠ” `async def`가 ė•„ë‹Œ í‘œė¤€ `def`로 ė„ ė–¸í•˜ęŗ  ėžˆėŠĩ니다. +í•˜ė§€ë§Œ `open()`ė€ `async`뙀 `await`ëĨŧ ė‚ŦėšŠí•˜ė§€ ė•ŠėŠĩ니다. + +ęˇ¸ëž˜ė„œ 뚰ëĻŦ는 ė´ë˛¤íŠ¸ 핸들ëŸŦ í•¨ėˆ˜ëĨŧ `async def` ëŒ€ė‹  ėŧ반 `def`로 ė„ ė–¸í•Šë‹ˆë‹¤. /// +### `startup`ęŗŧ `shutdown`ė„ 함ęģ˜ ė‚ŦėšŠ + +*ė‹œėž‘*ęŗŧ *ėĸ…ëŖŒ* ëĄœė§ė´ ė—°ę˛°ë  가ëŠĨė„ąė´ 높ėŠĩ니다. 똈ëĨŧ ë“¤ė–´, ëŦ´ė–¸ę°€ëĨŧ ė‹œėž‘í•œ 후 끝내거나, ėžė›ė„ 획득한 후 í•´ė œí•˜ëŠ” ë“ąė˜ ėž‘ė—…ė„ 할 눘 ėžˆėŠĩ니다. + +ė´ëŸŦ한 ėž‘ė—…ė„ ëŗ„ë„ė˜ í•¨ėˆ˜ëĄœ 래ëĻŦ하면 ė„œëĄœ ëĄœė§ė´ë‚˜ ëŗ€ėˆ˜ëĨŧ ęŗĩėœ í•˜ė§€ ė•Šę¸° 때ëŦ¸ė— 더 ė–´ë ¤ė›Œė§‘ë‹ˆë‹¤. ę°’ë“¤ė„ ė „ė—­ ëŗ€ėˆ˜ė— ė €ėžĨ하거나 ëš„ėŠˇí•œ 트ëĻ­ė„ ė‚ŦėšŠí•´ė•ŧ 할 눘 ėžˆėŠĩ니다. + +그렇기 때ëŦ¸ė— ėœ„ė—ė„œ 네ëĒ…í•œ 대로 `lifespan`ė„ ė‚ŦėšŠí•˜ëŠ” ę˛ƒė´ ęļŒėžĨ됩니다. + +## 揰눠렁 넏ëļ€ė‚Ŧ항 + +호기ė‹Ŧ ë§Žė€ ëļ„ë“¤ė„ ėœ„í•œ ę¸°ėˆ ė ė¸ 넏ëļ€ė‚Ŧí•­ėž…ë‹ˆë‹¤. 🤓 + +ASGI 揰눠 ė‚Ŧ떑뗐 따ëĨ´ëŠ´, ė´ëŠ” Lifespan Protocolė˜ ėŧëļ€ė´ëа, `startup`ęŗŧ `shutdown`ė´ëŧ는 ė´ë˛¤íŠ¸ëĨŧ ė •ė˜í•Šë‹ˆë‹¤. + /// info | ė •ëŗ´ -ė´ë˛¤íŠ¸ 핸들ëŸŦ뗐 관한 ë‚´ėšŠė€ Starlette ė´ë˛¤íŠ¸ ëŦ¸ė„œė—ė„œ ėļ”ę°€ëĄœ í™•ė¸í•  눘 ėžˆėŠĩ니다. +Starletteė˜ `lifespan` 핸들ëŸŦ뗐 대해 더 ėŊęŗ  ė‹ļ다면 Starletteė˜ Lifespan ëŦ¸ė„œė—ė„œ í™•ė¸í•  눘 ėžˆėŠĩ니다. + +ė´ ëŦ¸ė„œė—ëŠ” ėŊ”ë“œė˜ 다ëĨ¸ ė˜ė—­ė—ė„œ ė‚ŦėšŠí•  눘 ėžˆëŠ” lifespan ėƒíƒœëĨŧ 래ëĻŦ하는 방법도 íŦí•¨ë˜ė–´ ėžˆėŠĩ니다. /// + +## ė„œë¸Œ ė• í”ŒëĻŦėŧ€ė´ė…˜ + +🚨 ė´ lifespan ė´ë˛¤íŠ¸(`startup`ęŗŧ `shutdown`)는 ëŠ”ė¸ ė• í”ŒëĻŦėŧ€ė´ė…˜ė— ëŒ€í•´ė„œë§Œ ė‹¤í–‰ë˜ëŠ°, [ė„œë¸Œ ė• í”ŒëĻŦėŧ€ė´ė…˜ - Mounts](sub-applications.md){.internal-link target=_blank}ė—ëŠ” ė‹¤í–‰ë˜ė§€ ė•ŠėŒė„ ėœ ė˜í•˜ė„¸ėš”. diff --git a/docs/ko/docs/advanced/sub-applications.md b/docs/ko/docs/advanced/sub-applications.md new file mode 100644 index 000000000..c5835de15 --- /dev/null +++ b/docs/ko/docs/advanced/sub-applications.md @@ -0,0 +1,67 @@ +# í•˜ėœ„ ė‘ėšŠí”„ëĄœęˇ¸ëž¨ - ë§ˆėš´íŠ¸ + +만ė•Ŋ ę°ę°ė˜ 독ëĻŊė ė¸ OpenAPI뙀 ëŦ¸ė„œ UIëĨŧ 갖는 두 ę°œė˜ 독ëĻŊė ė¸ FastAPI ė‘ėšŠí”„ëĄœęˇ¸ëž¨ė´ í•„ėš”í•˜ë‹¤ëŠ´, ëŠ”ė¸ ė–´í”ŒëĻŦėŧ€ė´ė…˜ė— 하나 (또는 ꡸ ė´ėƒė˜) í•˜ėœ„-ė‘ėšŠí”„ëĄœęˇ¸ëž¨(들)ė„ â€œë§ˆėš´íŠ¸"í•´ė„œ ė‚ŦėšŠí•  눘 ėžˆėŠĩ니다. + +## **FastAPI** ė‘ėšŠí”„ëĄœęˇ¸ëž¨ ë§ˆėš´íŠ¸ + +â€œë§ˆėš´íŠ¸"ė´ëž€ ė™„ė „ížˆ “독ëĻŊė ė¸" ė‘ėšŠí”„ëĄœęˇ¸ëž¨ė„ íŠšė • ę˛ŊëĄœė— ėļ”ę°€í•˜ė—Ŧ 해당 í•˜ėœ„ ė‘ėšŠí”„ëĄœęˇ¸ëž¨ė—ė„œ ė„ ė–¸ëœ *ę˛Ŋ로 ë™ėž‘*ė„ í†ĩ해 해당 ę˛Ŋ로 ė•„ëž˜ė— ėžˆëŠ” ëĒ¨ë“  ėž‘ė—…ë“¤ė„ 래ëĻŦ할 눘 ėžˆë„ëĄ 하는 ę˛ƒė„ ė˜ë¯¸í•Šë‹ˆë‹¤. + +### ėĩœėƒë‹¨ ė‘ėšŠí”„ëĄœęˇ¸ëž¨ + +ë¨ŧė €, ëŠ”ė¸, ėĩœėƒë‹¨ė˜ **FastAPI** ė‘ėšŠí”„ëĄœęˇ¸ëž¨ęŗŧ ė´ę˛ƒė˜ *ę˛Ŋ로 ë™ėž‘*ė„ ėƒė„ąí•Šë‹ˆë‹¤: + +{* ../../docs_src/sub_applications/tutorial001.py hl[3, 6:8] *} + +### í•˜ėœ„ ė‘ėšŠí”„ëĄœęˇ¸ëž¨ + +ë‹¤ėŒėœŧ로, í•˜ėœ„ ė‘ėšŠí”„ëĄœęˇ¸ëž¨ęŗŧ ė´ę˛ƒė˜ *ę˛Ŋ로 ë™ėž‘*ė„ ėƒė„ąí•Šë‹ˆë‹¤: + +ė´ í•˜ėœ„ ė‘ėšŠí”„ëĄœęˇ¸ëž¨ė€ 또 다ëĨ¸ í‘œė¤€ FastAPI ė‘ėšŠí”„ëĄœęˇ¸ëž¨ėž…ë‹ˆë‹¤. 다만 ė´ę˛ƒė€ â€œë§ˆėš´íŠ¸â€ë  ę˛ƒėž…ë‹ˆë‹¤: + +{* ../../docs_src/sub_applications/tutorial001.py hl[11, 14:16] *} + +### í•˜ėœ„ ė‘ėšŠí”„ëĄœęˇ¸ëž¨ ë§ˆėš´íŠ¸ + +ėĩœėƒë‹¨ ė‘ėšŠí”„ëĄœęˇ¸ëž¨, `app`뗐 í•˜ėœ„ ė‘ėšŠí”„ëĄœęˇ¸ëž¨, `subapi`ëĨŧ ë§ˆėš´íŠ¸í•Šë‹ˆë‹¤. + +ė´ ė˜ˆė‹œė—ė„œ, í•˜ėœ„ ė‘ėšŠí”„ëĄœęˇ¸ëž¨ė…˜ė€ `/subapi` ę˛ŊëĄœė— ë§ˆėš´íŠ¸ 될 ę˛ƒėž…ë‹ˆë‹¤: + +{* ../../docs_src/sub_applications/tutorial001.py hl[11, 19] *} + +### ėžë™ėœŧ로 ėƒė„ąëœ API ëŦ¸ė„œ í™•ė¸ + +ė´ė œ, `uvicorn`ėœŧ로 ëŠ”ė¸ ė‘ėšŠí”„ëĄœęˇ¸ëž¨ė„ ė‹¤í–‰í•˜ė‹­ė‹œė˜¤. ë‹šė‹ ė˜ 파ėŧė´ `main.py`ëŧ늴, ė´ë ‡ę˛Œ ė‹¤í–‰í•Šë‹ˆë‹¤: + +
+ +```console +$ uvicorn main:app --reload + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +꡸ëĻŦęŗ  http://127.0.0.1:8000/docsė—ė„œ ëŦ¸ė„œëĨŧ ė—Ŧė‹­ė‹œė˜¤. + +ëŠ”ė¸ ė‘ėšŠí”„ëĄœęˇ¸ëž¨ė˜ *ę˛Ŋ로 ë™ėž‘*ë§Œė„ íŦ함하는, ëŠ”ė¸ ė‘ėšŠí”„ëĄœęˇ¸ëž¨ė— 대한 ėžë™ API ëŦ¸ė„œëĨŧ í™•ė¸í•  눘 ėžˆėŠĩ니다: + + + +ë‹¤ėŒėœŧ로, http://127.0.0.1:8000/subapi/docsė—ė„œ í•˜ėœ„ ė‘ėšŠí”„ëĄœęˇ¸ëž¨ė˜ ëŦ¸ė„œëĨŧ ė—Ŧė‹­ė‹œė˜¤. + +í•˜ėœ„ ę˛Ŋ로 ė ‘ë‘ė‚Ŧ `/subapi` ė•„ëž˜ė— ė„ ė–¸ëœ *ę˛Ŋ로 ë™ėž‘* ė„ íŦ함하는, í•˜ėœ„ ė‘ėšŠí”„ëĄœęˇ¸ëž¨ė— 대한 ėžë™ API ëŦ¸ė„œëĨŧ í™•ė¸í•  눘 ėžˆėŠĩ니다: + + + +두 ė‚ŦėšŠėž ė¸í„°íŽ˜ė´ėŠ¤ 뤑 ė–´ëŠ 하나ëĨŧ ė‚ŦėšŠí•´ė•ŧ하는 ę˛Ŋ뚰, 브ëŧėš°ė €ëŠ” íŠšė • ė‘ėšŠí”„ëĄœęˇ¸ëž¨ 또는 í•˜ėœ„ ė‘ėšŠí”„ëĄœęˇ¸ëž¨ęŗŧ 각각 í†ĩė‹ í•  눘 ėžˆę¸° 때ëŦ¸ė— ė˜Ŧ바ëĨ´ę˛Œ ë™ėž‘í•  ę˛ƒėž…ë‹ˆë‹¤. + +### 揰눠렁 넏ëļ€ė‚Ŧ항: `root_path` + +ėœ„ė— 네ëĒ…ëœ 것ęŗŧ ę°™ė´ í•˜ėœ„ ė‘ėšŠí”„ëĄœęˇ¸ëž¨ė„ ë§ˆėš´íŠ¸í•˜ëŠ” ę˛Ŋ뚰, FastAPI는 `root_path`ëŧęŗ  하는 ASGI ëĒ…ė„¸ė˜ 매ėģ¤ë‹ˆėĻ˜ė„ ė‚ŦėšŠí•˜ė—Ŧ í•˜ėœ„ ė‘ėšŠí”„ëĄœęˇ¸ëž¨ė— 대한 ë§ˆėš´íŠ¸ ę˛Ŋ로 í†ĩė‹ ė„ 래ëĻŦ합니다. + +ė´ëĨŧ í†ĩ해, í•˜ėœ„ ė‘ėšŠí”„ëĄœęˇ¸ëž¨ė€ ëŦ¸ė„œ UIëĨŧ ėœ„í•´ ę˛Ŋ로 ė ‘ë‘ė‚ŦëĨŧ ė‚ŦėšŠí•´ė•ŧ 한다는 ė‚Ŧė‹¤ė„ ė¸ė§€í•Šë‹ˆë‹¤. + +í•˜ėœ„ ė‘ėšŠí”„ëĄœęˇ¸ëž¨ė—ë„ ė—­ė‹œ 다ëĨ¸ í•˜ėœ„ ė‘ėšŠí”„ëĄœęˇ¸ëž¨ė„ ë§ˆėš´íŠ¸í•˜ëŠ” ę˛ƒė´ 가ëŠĨ하며 FastAPI가 ëĒ¨ë“  `root_path` ë“¤ė„ ėžë™ė ėœŧ로 래ëĻŦ하기 때ëŦ¸ė— ëĒ¨ë“  ę˛ƒė€ ė˜Ŧ바ëĨ´ę˛Œ ë™ėž‘í•  ę˛ƒėž…ë‹ˆë‹¤. + +`root_path`뙀 ė´ę˛ƒė„ ė‚ŦėšŠí•˜ëŠ” ë°Šë˛•ė— ëŒ€í•´ė„œëŠ” [í”„ëĄė‹œė˜ 뒷단](./behind-a-proxy.md){.internal-link target=_blank} ė„šė…˜ė—ė„œ ë°°ėš¸ 눘 ėžˆėŠĩ니다. diff --git a/docs/ko/docs/help-fastapi.md b/docs/ko/docs/help-fastapi.md index 932952b4a..06435d4bb 100644 --- a/docs/ko/docs/help-fastapi.md +++ b/docs/ko/docs/help-fastapi.md @@ -1,162 +1,269 @@ -* # FastAPI 맀뛐 - ë„ė›€ë§ 받기 +# FastAPI 맀뛐 - ë„ė›€ 받기 - **FastAPI** 가 ë§ˆėŒė— ë“œė‹œë‚˜ėš”? +**FastAPI** 가 ë§ˆėŒė— ë“œė‹œë‚˜ėš”? - FastAPI, 다ëĨ¸ ė‚ŦėšŠėž, ę°œë°œėžëĨŧ ė‘ė›í•˜ęŗ  ė‹ļėœŧė‹ ę°€ėš”? +FastAPI, 다ëĨ¸ ė‚ŦėšŠėž, ę°œë°œėžëĨŧ ė‘ė›í•˜ęŗ  ė‹ļėœŧė‹ ę°€ėš”? - í˜šė€ **FastAPI** 뗐 대해 ë„ė›€ė´ í•„ėš”í•˜ė‹ ę°€ėš”? +í˜šė€ **FastAPI** 뗐 대해 ë„ė›€ė´ í•„ėš”í•˜ė‹ ę°€ėš”? - ė•„ėŖŧ 간단하게 ė‘ė›í•  눘 ėžˆėŠĩ니다 (ëLJ ë˛ˆė˜ 클ëĻ­ë§Œėœŧ로). +ė•„ėŖŧ 간단하게 ė‘ė›í•  눘 ėžˆėŠĩ니다 (ëLJ ë˛ˆė˜ 클ëĻ­ë§Œėœŧ로). - 또한 ë„ė›€ė„ ë°›ė„ 눘 ėžˆëŠ” 방법도 ëLJ 氀맀 ėžˆėŠĩ니다. +또한 ë„ė›€ė„ ë°›ė„ 눘 ėžˆëŠ” 방법도 ëLJ 氀맀 ėžˆėŠĩ니다. - ## ë‰´ėŠ¤ë ˆí„° ęĩŦ독 +## ë‰´ėŠ¤ë ˆí„° ęĩŦ독 - [**FastAPI뙀 ėšœęĩŦ** ë‰´ėŠ¤ë ˆí„°](https://github.com/fastapi/fastapi/blob/master/newsletter)ëĨŧ ęĩŦ독하ė—Ŧ ėĩœė‹  ė •ëŗ´ëĨŧ ėœ ė§€í•  눘 ėžˆėŠĩ니다{.internal-link target=_blank}: +[**FastAPI and friends** ë‰´ėŠ¤ë ˆí„°](newsletter.md){.internal-link target=\_blank}ëĨŧ ęĩŦ독하ė—Ŧ ėĩœė‹  ė •ëŗ´ëĨŧ ėœ ė§€í•  눘 ėžˆėŠĩ니다: - - FastAPI 뙀 ꡸ ėšœęĩŦë“¤ė— 대한 ë‰´ėŠ¤ 🚀 - - ę°€ė´ë“œ 📝 - - íŠšė§• ✨ - - íšę¸°ė ė¸ ëŗ€í™” 🚨 - - 팁ęŗŧ ėš”ë š ✅ +* FastAPI and friends뗐 대한 ë‰´ėŠ¤ 🚀 +* ę°€ė´ë“œ 📝 +* 기ëŠĨ ✨ +* íšę¸°ė ė¸ ëŗ€í™” 🚨 +* 팁ęŗŧ ėš”ë š ✅ - ## íŠ¸ėœ„í„°ė—ė„œ FastAPI íŒ”ëĄœėš°í•˜ę¸° +## íŠ¸ėœ„í„°ė—ė„œ FastAPI íŒ”ëĄœėš°í•˜ę¸° - [Follow @fastapi on **Twitter**](https://twitter.com/fastapi) ëĨŧ íŒ”ëĄœėš°í•˜ė—Ŧ **FastAPI** 뗐 대한 ėĩœė‹  ë‰´ėŠ¤ëĨŧ ė–ģė„ 눘 ėžˆėŠĩ니다. đŸĻ +**Twitter**ė˜ @fastapiëĨŧ íŒ”ëĄœėš°í•˜ė—Ŧ **FastAPI** 뗐 대한 ėĩœė‹  ë‰´ėŠ¤ëĨŧ ė–ģė„ 눘 ėžˆėŠĩ니다. đŸĻ - ## Star **FastAPI** in GitHub +## Star **FastAPI** in GitHub - GitHubė—ė„œ FastAPI뗐 "star"ëĨŧ ëļ™ėŧ 눘 ėžˆėŠĩ니다(똤ëĨ¸ėĒŊ ėƒë‹¨ė˜ star 버íŠŧė„ 클ëĻ­): https://github.com/fastapi/fastapi. â­ī¸ +GitHubė—ė„œ FastAPI뗐 "star"ëĨŧ ëļ™ėŧ 눘 ėžˆėŠĩ니다 (똤ëĨ¸ėĒŊ ėƒë‹¨ė˜ star 버íŠŧė„ 클ëĻ­): https://github.com/fastapi/fastapi. â­ī¸ - ėŠ¤íƒ€ëĨŧ 늘ëĻŧėœŧëĄœė¨, 다ëĨ¸ ė‚ŦėšŠėžë“¤ė´ ėĸ€ 더 ė‰Ŋ枌 ė°žė„ 눘 ėžˆęŗ , ë§Žė€ ė‚ŦëžŒë“¤ė—ę˛Œ ėœ ėšŠí•œ ę˛ƒėž„ė„ 나타ë‚ŧ 눘 ėžˆėŠĩ니다. +ėŠ¤íƒ€ëĨŧ 늘ëĻŧėœŧëĄœė¨, 다ëĨ¸ ė‚ŦėšŠėžë“¤ė´ ėĸ€ 더 ė‰Ŋ枌 ė°žė„ 눘 ėžˆęŗ , ë§Žė€ ė‚ŦëžŒë“¤ė—ę˛Œ ėœ ėšŠí•œ ę˛ƒėž„ė„ 나타ë‚ŧ 눘 ėžˆėŠĩ니다. - ## GitHub ė €ėžĨė†Œė—ė„œ ëĻ´ëĻŦėψ í™•ė¸ +## GitHub ė €ėžĨė†Œė—ė„œ ëĻ´ëĻŦėψ í™•ė¸ - GitHubė—ė„œ FastAPIëĨŧ "watch"할 눘 ėžˆėŠĩ니다 (똤ëĨ¸ėĒŊ ėƒë‹¨ watch 버íŠŧė„ 클ëĻ­): https://github.com/fastapi/fastapi. 👀 +GitHubė—ė„œ FastAPIëĨŧ "watch"할 눘 ėžˆėŠĩ니다 (똤ëĨ¸ėĒŊ ėƒë‹¨ watch 버íŠŧė„ 클ëĻ­): https://github.com/fastapi/fastapi. 👀 - ė—Ŧę¸°ė„œ "Releases only"ė„ ė„ íƒí•  눘 ėžˆėŠĩ니다. +ė—Ŧę¸°ė„œ "Releases only"ė„ ė„ íƒí•  눘 ėžˆėŠĩ니다. - ė´ë ‡ę˛Œí•˜ëŠ´, **FastAPI** ė˜ 버그 ėˆ˜ė • 및 ėƒˆëĄœėš´ 기ëŠĨė˜ ęĩŦ현 ë“ąė˜ ėƒˆëĄœėš´ ėžëŖŒ (ėĩœė‹  ë˛„ė „)ė´ ėžˆė„ 때마다 (ė´ëŠ”ėŧ) í†ĩė§€ëĨŧ ë°›ė„ 눘 ėžˆėŠĩ니다. +ė´ë ‡ę˛Œí•˜ëŠ´, **FastAPI** ė˜ 버그 ėˆ˜ė • 및 ėƒˆëĄœėš´ 기ëŠĨė˜ ęĩŦ현 ë“ąė˜ ėƒˆëĄœėš´ ėžëŖŒ (ėĩœė‹  ë˛„ė „)ė´ ėžˆė„ 때마다 (ė´ëŠ”ėŧ) í†ĩė§€ëĨŧ ë°›ė„ 눘 ėžˆėŠĩ니다. - ## ę°œë°œėžė™€ė˜ 뗰枰 +## ę°œë°œėžė™€ė˜ 뗰枰 - ę°œë°œėžė¸ [me (SebastiÃĄn Ramírez / `tiangolo`)](https://tiangolo.com/) 뙀 ė—°ëŊė„ ėˇ¨í•  눘 ėžˆėŠĩ니다. +ę°œë°œėž(SebastiÃĄn Ramírez / `tiangolo`)뙀 ė—°ëŊė„ ėˇ¨í•  눘 ėžˆėŠĩ니다. - ė—ŦëŸŦëļ„ė€ 할 눘 ėžˆėŠĩ니다: +ė—ŦëŸŦëļ„ė€ 할 눘 ėžˆėŠĩ니다: - - [**GitHub**ė—ė„œ íŒ”ëĄœėš°í•˜ę¸°](https://github.com/tiangolo). - - ë‹šė‹ ė—ę˛Œ ë„ė›€ė´ 될 ė €ė˜ 다ëĨ¸ ė˜¤í”ˆė†ŒėŠ¤ í”„ëĄœė íŠ¸ëĨŧ í™•ė¸í•˜ė‹­ė‹œė˜¤. - - ėƒˆëĄœėš´ ė˜¤í”ˆė†ŒėŠ¤ í”„ëĄœė íŠ¸ëĨŧ ë§Œë“¤ė—ˆė„ 때 í™•ė¸í•˜ë ¤ëŠ´ íŒ”ëĄœėš° í•˜ė‹­ė‹œė˜¤. +* **GitHub**ė—ė„œ íŒ”ëĄœėš°í•˜ę¸°.. + * ë‹šė‹ ė—ę˛Œ ë„ė›€ė´ 될 ė €ė˜ 다ëĨ¸ ė˜¤í”ˆė†ŒėŠ¤ í”„ëĄœė íŠ¸ëĨŧ í™•ė¸í•˜ė‹­ė‹œė˜¤. + * ėƒˆëĄœėš´ ė˜¤í”ˆė†ŒėŠ¤ í”„ëĄœė íŠ¸ëĨŧ ë§Œë“¤ė—ˆė„ 때 í™•ė¸í•˜ë ¤ëŠ´ íŒ”ëĄœėš° í•˜ė‹­ė‹œė˜¤. +* **Twitter** 또는 Mastodonė—ė„œ íŒ”ëĄœėš°í•˜ę¸°. + * FastAPIė˜ ė‚ŦėšŠ ėšŠë„ëĨŧ ė•Œë ¤ėŖŧė„¸ėš” (ęˇ¸ę˛ƒė„ ë“ŖëŠ” ę˛ƒė„ ėĸ‹ė•„핊니다). + * 발표나 ėƒˆëĄœėš´ 툴 ėļœė‹œ ė†Œė‹ė„ ë°›ė•„ëŗ´ė‹­ė‹œė˜¤. + * **Twitter**ė˜ @fastapiëĨŧ íŒ”ëĄœėš° (ëŗ„ë„ ęŗ„ė •ė—ė„œ) 할 눘 ėžˆėŠĩ니다. +* **LinkedIn**ė—ė„œ íŒ”ëĄœėš°í•˜ę¸°.. + * ėƒˆëĄœėš´ íˆ´ė˜ 발표나 ėļœė‹œ ė†Œė‹ė„ ë°›ė•„ëŗ´ė‹­ė‹œė˜¤. (단, TwitterëĨŧ 더 ėžėŖŧ ė‚ŦėšŠí•Šë‹ˆë‹¤ 🤷‍♂). +* **Dev.to** 또는 **Medium**ė—ė„œ ė œę°€ ėž‘ė„ąí•œ ë‚´ėšŠė„ ėŊė–´ ëŗ´ė‹­ė‹œė˜¤ (또는 íŒ”ëĄœėš°). + * 다ëĨ¸ 기ė‚Ŧ나 ė•„ė´ë””ė–´ë“¤ė„ ėŊęŗ , ė œę°€ ë§Œë“¤ė–´ė™”ë˜ íˆ´ė— ëŒ€í•´ė„œë„ ėŊėœŧė‹­ė‹œė˜¤. + * ėƒˆëĄœėš´ 기ė‚ŦëĨŧ ėŊ기 ėœ„í•´ íŒ”ëĄœėš° í•˜ė‹­ė‹œė˜¤. - - [**Twitter**ė—ė„œ íŒ”ëĄœėš°í•˜ę¸°](https://twitter.com/tiangolo). - - FastAPIė˜ ė‚ŦėšŠ ėšŠë„ëĨŧ ė•Œë ¤ėŖŧė„¸ėš” (ęˇ¸ę˛ƒė„ ë“ŖëŠ” ę˛ƒė„ ėĸ‹ė•„핊니다). - - 발표 또는 ėƒˆëĄœėš´ 툴 ėļœė‹œí•  때 들ėœŧė‹­ė‹œė˜¤. - - [follow @fastapi on Twitter](https://twitter.com/fastapi) (ëŗ„ë„ ęŗ„ė •ė—ė„œ) 할 눘 ėžˆėŠĩ니다. +## **FastAPI**뗐 대한 íŠ¸ėœ— - - [**Linkedin**ė—ė„œė˜ 뗰枰](https://www.linkedin.com/in/tiangolo/). - - ėƒˆëĄœėš´ íˆ´ė˜ 발표나 ëĻ´ëĻŦ늤ëĨŧ ë“¤ė„ 눘 ėžˆėŠĩ니다 (단, TwitterëĨŧ 더 ėžėŖŧ ė‚ŦėšŠí•Šë‹ˆë‹¤ 🤷‍♂). +**FastAPI**뗐 대해 íŠ¸ėœ— í•˜ęŗ  FastAPI가 ë§ˆėŒė— 드는 ė´ėœ ëĨŧ ė•Œë ¤ėŖŧė„¸ėš”. 🎉 - - [**Dev.to**](https://dev.to/tiangolo) 또는 [**Medium**](https://medium.com/@tiangolo)ė—ė„œ ė œę°€ ėž‘ė„ąí•œ ë‚´ėšŠė„ ėŊė–´ ëŗ´ė‹­ė‹œė˜¤(또는 íŒ”ëĄœėš°). - - 다ëĨ¸ 기ė‚Ŧ나 ė•„ė´ë””ė–´ë“¤ė„ ėŊęŗ , ė œę°€ ë§Œë“¤ė–´ė™”ë˜ íˆ´ė— ëŒ€í•´ė„œë„ ėŊėœŧė‹­ė‹œė˜¤. - - ėƒˆëĄœėš´ 기ė‚ŦëĨŧ ėŊ기 ėœ„í•´ íŒ”ëĄœėš° í•˜ė‹­ė‹œė˜¤. +**FastAPI**가 ė–´ë–ģ枌 ė‚ŦėšŠë˜ęŗ  ėžˆëŠ”ė§€, ė–´ë–¤ ė ė´ ë§ˆėŒė— ë“¤ė—ˆëŠ”ė§€, ė–´ë–¤ í”„ëĄœė íŠ¸/회ė‚Ŧė—ė„œ ė‚ŦėšŠí•˜ęŗ  ėžˆëŠ”ė§€ ë“ąė— 대해 ë“Ŗęŗ  ė‹ļėŠĩ니다. - ## **FastAPI**뗐 대한 íŠ¸ėœ— +## FastAPI뗐 íˆŦ표하기 - [**FastAPI**뗐 대해 íŠ¸ėœ—](https://twitter.com/compose/tweet?text=I'm loving @fastapi because... https://github.com/fastapi/fastapi) í•˜ęŗ  FastAPI가 ë§ˆėŒė— 드는 ė´ėœ ëĨŧ ė•Œë ¤ėŖŧė„¸ėš”. 🎉 +* Slantė—ė„œ **FastAPI** 뗐 대해 íˆŦí‘œí•˜ė‹­ė‹œė˜¤. +* AlternativeToė—ė„œ **FastAPI** 뗐 대해 íˆŦí‘œí•˜ė‹­ė‹œė˜¤. +* StackShareė—ė„œ **FastAPI** 뗐 대해 íˆŦí‘œí•˜ė‹­ė‹œė˜¤. - **FastAPI**가 ė–´ë–ģ枌 ė‚ŦėšŠë˜ęŗ  ėžˆëŠ”ė§€, ė–´ë–¤ ė ė´ ë§ˆėŒė— ë“¤ė—ˆëŠ”ė§€, ė–´ë–¤ í”„ëĄœė íŠ¸/회ė‚Ŧė—ė„œ ė‚ŦėšŠí•˜ęŗ  ėžˆëŠ”ė§€ ë“ąė— 대해 ë“Ŗęŗ  ė‹ļėŠĩ니다. +## GitHubė˜ ė´ėŠˆëĄœ 다ëĨ¸ė‚Ŧ람 돕기 - ## FastAPI뗐 íˆŦ표하기 +다ëĨ¸ ė‚ŦëžŒë“¤ė˜ 마ëŦ¸ė— ë„ė›€ė„ 뤄 눘 ėžˆėŠĩ니다: - - [Slantė—ė„œ **FastAPI** 뗐 대해 íˆŦí‘œí•˜ė‹­ė‹œė˜¤](https://www.slant.co/options/34241/~fastapi-review). - - [AlternativeTo**FastAPI** 뗐 대해 íˆŦí‘œí•˜ė‹­ė‹œė˜¤](https://alternativeto.net/software/fastapi/). +* GitHub ë””ėŠ¤ėģ¤ė…˜ +* GitHub ė´ėŠˆ - ## GitHubė˜ ė´ėŠˆëĄœ 다ëĨ¸ė‚Ŧ람 돕기 +ë§Žė€ ę˛Ŋ뚰, ė—ŦëŸŦëļ„ė€ ė´ë¯¸ ꡸ 마ëŦ¸ė— 대한 ë‹ĩė„ ė•Œęŗ  ėžˆė„ ėˆ˜ë„ ėžˆėŠĩ니다. 🤓 - [ėĄ´ėžŦ하는 ė´ėŠˆ](https://github.com/fastapi/fastapi/issues)ëĨŧ í™•ė¸í•˜ęŗ  ęˇ¸ę˛ƒė„ ė‹œë„í•˜ęŗ  ë„ė™€ė¤„ 눘 ėžˆėŠĩ니다. 대ëļ€ëļ„ė˜ ę˛Ŋ뚰 ė´ë¯¸ ë‹ĩė„ ė•Œęŗ  ėžˆëŠ” 마ëŦ¸ėž…니다. 🤓 +만ė•Ŋ ë§Žė€ ė‚ŦëžŒë“¤ė˜ ëŦ¸ė œëĨŧ ë„ė™€ė¤€ë‹¤ëŠ´, ęŗĩė‹ė ė¸ [FastAPI ė „ëŦ¸ę°€](fastapi-people.md#fastapi-experts){.internal-link target=\_blank} 가 될 ę˛ƒėž…ë‹ˆë‹¤. 🎉 - ë§Žė€ ė‚ŦëžŒë“¤ė˜ ëŦ¸ė œëĨŧ ë„ė™€ė¤€ë‹¤ëŠ´, ęŗĩė‹ė ė¸ [FastAPI ė „ëŦ¸ę°€](https://github.com/fastapi/fastapi/blob/master/docs/en/docs/fastapi-people.md#experts) 가 될 눘 ėžˆėŠĩ니다{.internal-link target=_blank}. 🎉 +가ėžĨ ė¤‘ėš”í•œ ė ė€: ėšœė ˆí•˜ë ¤ęŗ  노ë Ĩ하는 ę˛ƒėž…ë‹ˆë‹¤. ė‚ŦëžŒë“¤ė€ ėĸŒė ˆę°ė„ ė•ˆęŗ  ė˜¤ëŠ°, ë§Žė€ ę˛Ŋ뚰 ėĩœė„ ė˜ ë°Šė‹ėœŧ로 마ëŦ¸í•˜ė§€ ė•Šė„ ėˆ˜ë„ ėžˆėŠĩ니다. í•˜ė§€ë§Œ ėĩœëŒ€í•œ ėšœė ˆí•˜ę˛Œ ëŒ€í•˜ë ¤ęŗ  노ë Ĩí•˜ė„¸ėš”. 🤗 - ## GitHub ė €ėžĨė†Œ ëŗ´ę¸° +**FastAPI** ėģ¤ëŽ¤ë‹ˆí‹°ė˜ ëĒŠí‘œëŠ” ėšœė ˆí•˜ęŗ  í™˜ė˜í•˜ëŠ” ę˛ƒėž…ë‹ˆë‹¤. ë™ė‹œė—, ę´´ëĄ­íž˜ė´ë‚˜ ëŦ´ëĄ€í•œ í–‰ë™ė„ ë°›ė•„ë“¤ė´ė§€ ë§ˆė„¸ėš”. 뚰ëĻŦ는 ė„œëĄœëĨŧ 돌봐ė•ŧ 합니다. - GitHubė—ė„œ FastAPIëĨŧ "watch"할 눘 ėžˆėŠĩ니다 (똤ëĨ¸ėĒŊ ėƒë‹¨ watch 버íŠŧė„ 클ëĻ­): https://github.com/fastapi/fastapi. 👀 +--- - "Releases only" ëŒ€ė‹  "Watching"ė„ ė„ íƒí•˜ëŠ´ 다ëĨ¸ ė‚ŦėšŠėžę°€ ėƒˆëĄœėš´ issueëĨŧ ėƒė„ąí•  때 ė•ŒëĻŧė´ ėˆ˜ė‹ ëŠë‹ˆë‹¤. +다ëĨ¸ ė‚ŦëžŒë“¤ė˜ 마ëŦ¸ (ë””ėŠ¤ėģ¤ė…˜ 또는 ė´ėŠˆė—ė„œ) í•´ę˛°ė„ ë„ėš¸ 눘 ėžˆëŠ” ë°Šë˛•ė€ ë‹¤ėŒęŗŧ 같ėŠĩ니다. - 그런 ë‹¤ėŒ ė´ëŸ° issuesëĨŧ 해결 할 눘 ėžˆë„ëĄ ë„ė›€ė„ 뤄 눘 ėžˆėŠĩ니다. +### 마ëŦ¸ ė´í•´í•˜ę¸° - ## ė´ėŠˆ ėƒė„ąí•˜ę¸° +* 마ëŦ¸í•˜ëŠ” ė‚ŦëžŒė´ 氀맄 **ëĒŠė **ęŗŧ ė‚ŦėšŠ ė‚Ŧ례ëĨŧ ė´í•´í•  눘 ėžˆëŠ”ė§€ í™•ė¸í•˜ė„¸ėš”. - GitHub ė €ėžĨė†Œė— [ėƒˆëĄœėš´ ė´ėŠˆ ėƒė„ą](https://github.com/fastapi/fastapi/issues/new/choose) ė„ 할 눘 ėžˆėŠĩ니다, 똈ëĨŧ들면 ë‹¤ėŒęŗŧ 같ėŠĩ니다: +* 마ëŦ¸ (대ëļ€ëļ„ė€ 마ëŦ¸ėž…니다)ė´ **ëĒ…í™•**í•œė§€ í™•ė¸í•˜ė„¸ėš”. - - **마ëŦ¸**ė„ 하거나 **ëŦ¸ė œ**뗐 대해 마ëŦ¸í•Šë‹ˆë‹¤. - - ėƒˆëĄœėš´ **기ëŠĨ**ė„ ė œė•ˆ 합니다. +* ë§Žė€ ę˛Ŋ뚰, ė‚ŦėšŠėžę°€ ę°€ė •í•œ í•´ę˛°ėą…ė— 대한 마ëŦ¸ė„ í•˜ė§€ë§Œ, 더 **ėĸ‹ė€** í•´ę˛°ėą…ė´ ėžˆė„ 눘 ėžˆėŠĩ니다. ëŦ¸ė œė™€ ė‚ŦėšŠ ė‚Ŧ례ëĨŧ 더 ėž˜ ė´í•´í•˜ëŠ´ 더 ë‚˜ė€ **ëŒ€ė•ˆė ė¸ í•´ę˛°ėą…**ė„ ė œė•ˆí•  눘 ėžˆėŠĩ니다. - **및溠**: 만ė•Ŋ ė´ėŠˆëĨŧ ėƒė„ąí•œë‹¤ëŠ´, ė €ëŠ” ė—ŦëŸŦëļ„ė—ę˛Œ 다ëĨ¸ ė‚ŦëžŒë“¤ė„ ë„ė™€ë‹Ŧëŧęŗ  ëļ€íƒí•  ę˛ƒėž…ë‹ˆë‹¤. 😉 +* 마ëŦ¸ė„ ė´í•´í•  눘 ė—†ë‹¤ëŠ´, 더 **ėžė„¸í•œ ė •ëŗ´**ëĨŧ ėš”ė˛­í•˜ė„¸ėš”. - ## Pull RequestëĨŧ ë§Œë“œė‹­ė‹œė˜¤ +### ëŦ¸ė œ ėžŦ현하기 - Pull RequestsëĨŧ ė´ėšŠí•˜ė—Ŧ ė†ŒėŠ¤ėŊ”ë“œė— [ėģ¨íЏëĻŦ뷰트](https://github.com/fastapi/fastapi/blob/master/docs/en/docs/contributing.md){.internal-link target=_blank} 할 눘 ėžˆėŠĩ니다. 똈ëĨŧ 들면 ë‹¤ėŒęŗŧ 같ėŠĩ니다: +대ëļ€ëļ„ė˜ ę˛Ŋ뚰, 마ëŦ¸ė€ 마ëŦ¸ėžė˜ **ė›ëŗ¸ ėŊ”드**뙀 ę´€ë ¨ė´ ėžˆėŠĩ니다. - - ëŦ¸ė„œė—ė„œ ė°žė€ ė˜¤íƒ€ëĨŧ ėˆ˜ė •í•  때. +ë§Žė€ ę˛Ŋ뚰, ėŊ”ë“œė˜ ėŧëļ€ë§Œ ëŗĩė‚Ŧí•´ė„œ ė˜ŦëĻŦė§€ë§Œ, 그것만ėœŧ로는 **ëŦ¸ė œëĨŧ ėžŦ현**í•˜ę¸°ė— ėļŠëļ„í•˜ė§€ ė•ŠėŠĩ니다. - - FastAPIëĨŧ [íŽ¸ė§‘í•˜ė—Ŧ](https://github.com/fastapi/fastapi/edit/master/docs/en/data/external_links.yml) ėž‘ė„ąí–ˆęą°ë‚˜ ė°žė€ ëŦ¸ė„œ, ëš„ë””ė˜¤ 또는 팟ėēėŠ¤íŠ¸ëĨŧ ęŗĩėœ í•  때. +* 마ëŦ¸ėžė—ę˛Œ ėĩœė†Œí•œė˜ ėžŦ현 가ëŠĨ한 똈렜ëĨŧ 렜ęŗĩ해ë‹Ŧëŧęŗ  ėš”ė˛­í•˜ė„¸ėš”. ė´ë ‡ę˛Œ 하면 ėŊ”드ëĨŧ **ëŗĩė‚Ŧ-ëļ™ė—Ŧë„Ŗę¸°**하ė—Ŧ 링렑 ė‹¤í–‰í•˜ęŗ , 동ėŧ한 똤ëĨ˜ë‚˜ ë™ėž‘ė„ í™•ė¸í•˜ęą°ë‚˜ ė‚ŦėšŠ ė‚Ŧ례ëĨŧ 더 ėž˜ ė´í•´í•  눘 ėžˆėŠĩ니다. - - 해당 ė„šė…˜ė˜ ė‹œėž‘ ëļ€ëļ„뗐 링íŦëĨŧ ėļ”ę°€í–ˆëŠ”ė§€ í™•ė¸í•˜ė‹­ė‹œė˜¤. +* 너그ëŸŦ뚴 ë§ˆėŒė´ 든다면, ëŦ¸ė œ 네ëĒ…ë§Œė„ 기반ėœŧ로 링렑 **똈렜ëĨŧ ë§Œë“¤ė–´**ëŗŧ ėˆ˜ë„ ėžˆėŠĩ니다. í•˜ė§€ë§Œ, ė´ëŠ” ė‹œę°„ė´ ë§Žė´ 깸ëĻ´ 눘 ėžˆėœŧë¯€ëĄœ, ë¨ŧė € 마ëŦ¸ė„ ëĒ…í™•ížˆ 해ë‹Ŧëŧęŗ  ėš”ė˛­í•˜ëŠ” ę˛ƒė´ ėĸ‹ėŠĩ니다. - - ë‹šė‹ ė˜ ė–¸ė–´ëĄœ [ëŦ¸ė„œ ë˛ˆė—­í•˜ëŠ”ë°](https://github.com/fastapi/fastapi/blob/master/docs/en/docs/contributing.md#translations){.internal-link target=_blank} 기ė—Ŧ할 때. +### í•´ę˛°ėą… ė œė•ˆí•˜ę¸° - - 또한 다ëĨ¸ ė‚ŦėšŠėžę°€ 만든 ë˛ˆė—­ė„ 검토하는데 ë„ė›€ė„ 뤄 ėˆ˜ë„ ėžˆėŠĩ니다. +* 마ëŦ¸ė„ ėļŠëļ„히 ė´í•´í•œ í›„ė—ëŠ” 가ëŠĨ한 **ë‹ĩëŗ€**ė„ 렜ęŗĩ할 눘 ėžˆėŠĩ니다. - - ėƒˆëĄœėš´ ëŦ¸ė„œė˜ ė„šė…˜ė„ ė œė•ˆí•  때. +* ë§Žė€ ę˛Ŋ뚰, 마ëŦ¸ėžė˜ **ęˇŧëŗ¸ė ė¸ ëŦ¸ė œë‚˜ ė‚ŦėšŠ ė‚Ŧ례**ëĨŧ ė´í•´í•˜ëŠ” ę˛ƒė´ ė¤‘ėš”í•Šë‹ˆë‹¤. ęˇ¸ë“¤ė´ ė‹œë„í•˜ëŠ” ë°Šë˛•ëŗ´ë‹¤ 더 ë‚˜ė€ í•´ę˛°ėą…ė´ ėžˆė„ 눘 ėžˆę¸° 때ëŦ¸ėž…니다. - - ę¸°ėĄ´ ëŦ¸ė œ/버그ëĨŧ ėˆ˜ė •í•  때. +### 해결 ėš”ė˛­í•˜ę¸° - - ėƒˆëĄœėš´ featureëĨŧ ėļ”가할 때. +마ëŦ¸ėžę°€ ë‹ĩëŗ€ė„ í™•ė¸í•˜ęŗ  나면, ë‹šė‹ ė´ ëŦ¸ė œëĨŧ í•´ę˛°í–ˆė„ 가ëŠĨė„ąė´ 높ėŠĩ니다. ėļ•하핊니다, **ë‹šė‹ ė€ ė˜ė›…ėž…ë‹ˆë‹¤**! đŸĻ¸ - ## ėą„íŒ…ė— ė°¸ė—Ŧí•˜ė‹­ė‹œė˜¤ +* ė´ė œ ëŦ¸ė œëĨŧ 해결했다면, 마ëŦ¸ėžė—ę˛Œ ë‹¤ėŒė„ ėš”ė˛­í•  눘 ėžˆėŠĩ니다. - đŸ‘Ĩ [ë””ėŠ¤ėŊ”드 ėą„íŒ… ė„œë˛„](https://discord.gg/VQjSZaeJmf) đŸ‘Ĩ 뗐 ę°€ėž…í•˜ęŗ  FastAPI ėģ¤ëŽ¤ë‹ˆí‹°ė—ė„œ 다ëĨ¸ ė‚Ŧ람들ęŗŧ ė–´ėš¸ëĻŦė„¸ėš”. + * GitHub ë””ėŠ¤ėģ¤ė…˜ė—ė„œ: ëŒ“ę¸€ė„ **ë‹ĩëŗ€**ėœŧ로 í‘œė‹œí•˜ë„ëĄ ėš”ė˛­í•˜ė„¸ėš”. + * GitHub ė´ėŠˆė—ė„œ: ė´ėŠˆëĨŧ **ë‹Ģė•„ë‹Ŧëŧęŗ ** ėš”ė˛­í•˜ė„¸ėš”. - /// tip +## GitHub ė €ėžĨė†Œ ëŗ´ę¸° - 마ëŦ¸ė´ ėžˆëŠ” ę˛Ŋ뚰, [GitHub ė´ėŠˆ ](https://github.com/fastapi/fastapi/issues/new/choose) ė—ė„œ 마ëŦ¸í•˜ė‹­ė‹œė˜¤, [FastAPI ė „ëŦ¸ę°€](https://github.com/fastapi/fastapi/blob/master/docs/en/docs/fastapi-people.md#experts) ė˜ ë„ė›€ė„ ë°›ė„ 가ëŠĨė„ąė´ 높ėŠĩ니다{.internal-link target=_blank} . +GitHubė—ė„œ FastAPIëĨŧ "watch"할 눘 ėžˆėŠĩ니다 (똤ëĨ¸ėĒŊ ėƒë‹¨ watch 버íŠŧė„ 클ëĻ­): https://github.com/fastapi/fastapi. 👀 - /// +"Releases only" ëŒ€ė‹  "Watching"ė„ ė„ íƒí•˜ëŠ´, ėƒˆëĄœėš´ ė´ėŠˆë‚˜ 마ëŦ¸ė´ ėƒė„ąë  때 ė•ŒëĻŧė„ ë°›ė„ 눘 ėžˆėŠĩ니다. 또한, íŠšė •í•˜ę˛Œ ėƒˆëĄœėš´ ė´ėŠˆ, ë””ėŠ¤ėģ¤ė…˜, PR 등만 ė•ŒëĻŧ 받도록 ė„¤ė •í•  ėˆ˜ë„ ėžˆėŠĩ니다. - ``` - 다ëĨ¸ ėŧë°˜ė ė¸ ëŒ€í™”ė—ė„œë§Œ ėą„íŒ…ė„ ė‚ŦėšŠí•˜ė‹­ė‹œė˜¤. - ``` +그런 ë‹¤ėŒ ė´ëŸ° ė´ėŠˆë“¤ė„ 해결 할 눘 ėžˆë„ëĄ ë„ė›€ė„ 뤄 눘 ėžˆėŠĩ니다. - ę¸°ėĄ´ [ė§€í„° ėą„íŒ…](https://gitter.im/fastapi/fastapi) ė´ ėžˆė§€ë§Œ ėą„ë„ęŗŧ 溠揉揰ëŠĨė´ ė—†ė–´ė„œ 대화ëĨŧ 하기가 ėĄ°ę¸ˆ ė–´ë ĩ기 때ëŦ¸ė— ė§€ę¸ˆė€ ë””ėŠ¤ėŊ”ë“œę°€ ęļŒėžĨ되는 ė‹œėŠ¤í…œėž…ë‹ˆë‹¤. +## ė´ėŠˆ ėƒė„ąí•˜ę¸° - ### 마ëŦ¸ė„ ėœ„í•´ ėą„íŒ…ė„ ė‚ŦėšŠí•˜ė§€ ë§ˆė‹­ė‹œė˜¤ +GitHub ė €ėžĨė†Œė— ėƒˆëĄœėš´ ė´ėŠˆ ėƒė„ąė„ 할 눘 ėžˆėŠĩ니다, 똈ëĨŧ들면 ë‹¤ėŒęŗŧ 같ėŠĩ니다: - ėą„íŒ…ė€ 더 ë§Žė€ "ėžėœ ëĄœėš´ 대화"ëĨŧ í—ˆėšŠí•˜ę¸° 때ëŦ¸ė—, 너ëŦ´ ėŧë°˜ė ė¸ 마ëŦ¸ė´ë‚˜ 대ë‹ĩ하기 ė–´ë ¤ėš´ 마ëŦ¸ė„ ė‰Ŋ枌 마ëŦ¸ė„ 할 눘 ėžˆėœŧë¯€ëĄœ, ë‹ĩëŗ€ė„ ë°›ė§€ ëĒģ할 눘 ėžˆėŠĩ니다. +* **마ëŦ¸**ė„ 하거나 **ëŦ¸ė œ**뗐 대해 마ëŦ¸í•Šë‹ˆë‹¤. +* ėƒˆëĄœėš´ **기ëŠĨ**ė„ ė œė•ˆ 합니다. - GitHub ė´ėŠˆė—ė„œė˜ 템플ëĻŋė€ ė˜Ŧ바ëĨ¸ 마ëŦ¸ė„ ėž‘ė„ąí•˜ë„ëĄ ė•ˆë‚´í•˜ė—Ŧ 더 ė‰Ŋ枌 ėĸ‹ė€ ë‹ĩëŗ€ė„ ė–ģ거나 마ëŦ¸í•˜ę¸° 렄뗐 ėŠ¤ėŠ¤ëĄœ ëŦ¸ė œëĨŧ 해결할 ėˆ˜ë„ ėžˆėŠĩ니다. ꡸ëĻŦęŗ  GitHubė—ė„œëŠ” ė‹œę°„ė´ ėĄ°ę¸ˆ 깸ëĻŦ더ëŧ도 í•­ėƒ ëĒ¨ë“  ę˛ƒė— ë‹ĩ할 눘 ėžˆėŠĩ니다. ėą„íŒ… ė‹œėŠ¤í…œė—ė„œëŠ” ę°œė¸ė ėœŧ로 그렇게 할 눘 ė—†ėŠĩ니다. 😅 +**및溠**: 만ė•Ŋ ė´ėŠˆëĨŧ ėƒė„ąí•œë‹¤ëŠ´, ė €ëŠ” ė—ŦëŸŦëļ„ė—ę˛Œ 다ëĨ¸ ė‚ŦëžŒë“¤ė„ ë„ė™€ë‹Ŧëŧęŗ  ëļ€íƒí•  ę˛ƒėž…ë‹ˆë‹¤. 😉 - ėą„íŒ… ė‹œėŠ¤í…œė—ė„œė˜ 대화 또한 GitHubė—ė„œ 래ëŸŧ ė‰Ŋ枌 ę˛€ėƒ‰í•  눘 뗆揰 때ëŦ¸ė— 대화 뤑뗐 마ëŦ¸ęŗŧ ë‹ĩëŗ€ė´ ė†ė‹¤ë  눘 ėžˆėŠĩ니다. ꡸ëĻŦęŗ  GitHub ė´ėŠˆė— ėžˆëŠ” 것만 [FastAPI ė „ëŦ¸ę°€](https://github.com/fastapi/fastapi/blob/master/docs/en/docs/fastapi-people.md#experts)가 되는 것ėœŧ로 간ėŖŧë˜ë¯€ëĄœ{.internal-link target=_blank} , GitHub ė´ėŠˆė—ė„œ 더 ë§Žė€ 관ė‹Ŧė„ ë°›ė„ ę˛ƒėž…ë‹ˆë‹¤. +## Pull Requests ëĻŦ뷰하기 - 반늴, ėą„íŒ… ė‹œėŠ¤í…œė—ëŠ” 눘랜 ëĒ…ė˜ ė‚ŦėšŠėžę°€ ėžˆę¸° 때ëŦ¸ė—, ęą°ė˜ í•­ėƒ 대화 ėƒëŒ€ëĨŧ ė°žė„ 가ëŠĨė„ąė´ 높ėŠĩ니다. 😄 +다ëĨ¸ ė‚ŦëžŒë“¤ė˜ pull requestëĨŧ ëĻŦ뷰하는 데 ë„ė›€ė„ 뤄 눘 ėžˆėŠĩ니다. - ## ę°œë°œėž ėŠ¤í°ė„œę°€ ë˜ė‹­ė‹œė˜¤ +ë‹¤ė‹œ 한번 ë§í•˜ė§€ë§Œ, ėĩœëŒ€í•œ ėšœė ˆí•˜ę˛Œ ëĻŦ뷰해 ėŖŧė„¸ėš”. 🤗 - [GitHub ėŠ¤í°ė„œ](https://github.com/sponsors/tiangolo) ëĨŧ í†ĩ해 ę°œë°œėžëĨŧ ę˛Ŋ렜렁ėœŧ로 ė§€ė›í•  눘 ėžˆėŠĩ니다. +--- - 감ė‚Ŧ하다는 말로 ėģ¤í”ŧëĨŧ â˜•ī¸ í•œėž” ė‚Ŧ뤄 눘 ėžˆėŠĩ니다. 😄 +Pull RrquestëĨŧ ëĻŦ뷰할 때 ęŗ ë ¤í•´ė•ŧ 할 ė‚Ŧ항ęŗŧ ë°Šë˛•ė€ ë‹¤ėŒęŗŧ 같ėŠĩ니다: - 또한 FastAPIė˜ ė‹¤ë˛„ 또는 ęŗ¨ë“œ ėŠ¤í°ė„œę°€ 될 눘 ėžˆėŠĩ니다. 🏅🎉 +### ëŦ¸ė œ ė´í•´í•˜ę¸° - ## FastAPIëĨŧ 강화하는 도ęĩŦė˜ ėŠ¤í°ė„œę°€ ë˜ė‹­ė‹œė˜¤ +* ë¨ŧė €, 해당 pull request가 해결하려는 **ëŦ¸ė œëĨŧ ė´í•´í•˜ëŠ”ė§€** í™•ė¸í•˜ė„¸ėš”. GitHub ë””ėŠ¤ėģ¤ė…˜ 또는 ė´ėŠˆė—ė„œ 더 긴 ë…ŧė˜ę°€ ėžˆė—ˆė„ ėˆ˜ë„ ėžˆėŠĩ니다. - ëŦ¸ė„œė—ė„œ ëŗ´ė•˜ë“¯ė´, FastAPI는 Starletteęŗŧ Pydantic ëŧ는 ęą°ė¸ė˜ ė–´ęš¨ė— íƒ€ęŗ  ėžˆėŠĩ니다. +* Pull request가 í•„ėš”í•˜ė§€ ė•Šė„ 가ëŠĨė„ąë„ ėžˆėŠĩ니다. **다ëĨ¸ ë°Šė‹**ėœŧ로 ëŦ¸ė œëĨŧ 해결할 눘 ėžˆë‹¤ëŠ´, ꡸ ë°Šë˛•ė„ ė œė•ˆí•˜ęą°ë‚˜ 마ëŦ¸í•  눘 ėžˆėŠĩ니다. - ë‹¤ėŒė˜ ėŠ¤í°ė„œę°€ 될 눘 ėžˆėŠĩ니다 +### ėŠ¤íƒ€ėŧ뗐 너ëŦ´ ė‹ ę˛Ŋ ė“°ė§€ ė•Šę¸° - - [Samuel Colvin (Pydantic)](https://github.com/sponsors/samuelcolvin) - - [Encode (Starlette, Uvicorn)](https://github.com/sponsors/encode) +* ėģ¤ë°‹ ëŠ”ė‹œė§€ ėŠ¤íƒ€ėŧ ę°™ė€ ę˛ƒė— 너ëŦ´ ė‹ ę˛Ŋ ė“°ė§€ ė•Šė•„ë„ 됩니다. ė €ëŠ” 링렑 ėģ¤ë°‹ė„ ėˆ˜ė •í•˜ė—Ŧ squash and mergeëĨŧ ėˆ˜í–‰í•  ę˛ƒėž…ë‹ˆë‹¤. - ------ +* ėŊ”드 ėŠ¤íƒ€ėŧ ęˇœėš™ë„ ęąąė •í•  í•„ėš” ė—†ėŠĩ니다. ė´ë¯¸ ėžë™í™”ëœ 도ęĩŦë“¤ė´ ė´ëĨŧ 검ė‚Ŧí•˜ęŗ  ėžˆėŠĩ니다. - 감ė‚Ŧ합니다! 🚀 +ėŠ¤íƒ€ėŧė´ë‚˜ ėŧę´€ė„ą 관련 ėš”ė˛­ė´ í•„ėš”í•œ ę˛Ŋ뚰, ė œę°€ 링렑 ėš”ė˛­í•˜ęą°ë‚˜ í•„ėš”í•œ ëŗ€ę˛Ŋ ė‚Ŧí•­ė„ ėļ”ę°€ ėģ¤ë°‹ėœŧ로 ėˆ˜ė •í•  ę˛ƒėž…ë‹ˆë‹¤. + +### ėŊ”드 í™•ė¸í•˜ę¸° + +* ėŊ”드ëĨŧ ėŊęŗ , **ë…ŧëĻŦ렁ėœŧ로 타당**í•œė§€ í™•ė¸í•œ 후 로ėģŦė—ė„œ ė‹¤í–‰í•˜ė—Ŧ ëŦ¸ė œę°€ í•´ę˛°ë˜ëŠ”ė§€ í™•ė¸í•˜ė„¸ėš”. + +* 그런 ë‹¤ėŒ, í™•ė¸í–ˆë‹¤ęŗ  **댓글**ė„ 남겨 ėŖŧė„¸ėš”. 그래ė•ŧ ė œę°€ ę˛€í† í–ˆėŒė„ ė•Œ 눘 ėžˆėŠĩ니다. + +/// info + +ëļˆí–‰ížˆë„, ė œę°€ ë‹¨ėˆœížˆ ė—ŦëŸŦ ę°œė˜ ėŠšė¸ë§Œėœŧ로 PRė„ ė‹ ëĸ°í•  ėˆ˜ëŠ” ė—†ėŠĩ니다. + +3氜, 5氜 ė´ėƒė˜ ėŠšė¸ė´ ë‹Ŧëϰ PRė´ ė‹¤ė œëĄœëŠ” ęš¨ė ¸ ėžˆęą°ë‚˜, 버그가 ėžˆęą°ë‚˜, ėŖŧėžĨ하는 ëŦ¸ė œëĨŧ í•´ę˛°í•˜ė§€ ëĒģ하는 ę˛Ŋėš°ę°€ ė—ŦëŸŦ 번 ėžˆė—ˆėŠĩ니다. 😅 + +따ëŧė„œ, ė •ë§ëĄœ ėŊ”드ëĨŧ ėŊęŗ  ė‹¤í–‰í•œ 뒤, 댓글로 í™•ė¸ ë‚´ėšŠė„ 남겨 ėŖŧ는 ę˛ƒė´ ë§¤ėš° ė¤‘ėš”í•Šë‹ˆë‹¤. 🤓 + +/// + +* PRė„ 더 ë‹¨ėˆœí•˜ę˛Œ 만들 눘 ėžˆë‹¤ëŠ´ 그렇게 ėš”ė˛­í•  눘 ėžˆė§€ë§Œ, 너ëŦ´ ęšŒë‹¤ëĄœėš¸ í•„ėš”ëŠ” ė—†ėŠĩ니다. ėŖŧę´€ė ė¸ ę˛Ŧ해가 ë§Žė´ ėžˆė„ 눘 ėžˆę¸° 때ëŦ¸ėž…니다 (꡸ëĻŦęŗ  ė €ë„ 렜 ę˛Ŧ해가 ėžˆė„ ęą°ė˜ˆėš” 🙈). 따ëŧė„œ í•ĩė‹Ŧė ė¸ ëļ€ëļ„뗐 ė§‘ė¤‘í•˜ëŠ” ę˛ƒė´ ėĸ‹ėŠĩ니다. + +### í…ŒėŠ¤íŠ¸ + +* PR뗐 **í…ŒėŠ¤íŠ¸**가 íŦí•¨ë˜ė–´ ėžˆëŠ”ė§€ í™•ė¸í•˜ëŠ” 데 ë„ė›€ė„ ėŖŧė„¸ėš”. + +* PRė„ ė ėšŠí•˜ę¸° 렄뗐 í…ŒėŠ¤íŠ¸ę°€ **ė‹¤íŒ¨**í•˜ëŠ”ė§€ í™•ė¸í•˜ė„¸ėš”. 🚨 + +* PRė„ ė ėšŠí•œ 후 í…ŒėŠ¤íŠ¸ę°€ **í†ĩęŗŧ**í•˜ëŠ”ė§€ í™•ė¸í•˜ė„¸ėš”. ✅ + +* ë§Žė€ PRė—ëŠ” í…ŒėŠ¤íŠ¸ę°€ ė—†ėŠĩ니다. í…ŒėŠ¤íŠ¸ëĨŧ ėļ”ę°€í•˜ë„ëĄ **냁揰**ė‹œėŧœė¤„ ėˆ˜ë„ ėžˆęŗ , 링렑 í…ŒėŠ¤íŠ¸ëĨŧ **ė œė•ˆ**할 ėˆ˜ë„ ėžˆėŠĩ니다. ė´ëŠ” ė‹œę°„ė´ ë§Žė´ ė†Œėš”ë˜ëŠ” ëļ€ëļ„ ė¤‘ í•˜ë‚˜ė´ëŠ°, ꡸ ëļ€ëļ„ė„ ë§Žė´ ë„ė™€ė¤„ 눘 ėžˆėŠĩ니다. + +* ꡸ëĻŦęŗ  ė‹œë„í•œ ë‚´ėšŠė„ 댓글로 남겨ėŖŧė„¸ėš”. ꡸ëŸŦ늴 ė œę°€ í™•ė¸í–ˆë‹¤ëŠ” 깸 ė•Œ 눘 ėžˆėŠĩ니다. 🤓 + +## Pull RequestëĨŧ ë§Œë“œė‹­ė‹œė˜¤ + +Pull RequestsëĨŧ ė´ėšŠí•˜ė—Ŧ ė†ŒėŠ¤ėŊ”ë“œė— [ėģ¨íЏëĻŦ뷰트](contributing.md){.internal-link target=\_blank} 할 눘 ėžˆėŠĩ니다. 똈ëĨŧ 들면 ë‹¤ėŒęŗŧ 같ėŠĩ니다: + +* ëŦ¸ė„œė—ė„œ 발ę˛Ŧ한 ė˜¤íƒ€ëĨŧ ėˆ˜ė •í•  때. +* FastAPI 관련 ëŦ¸ė„œ, ëš„ë””ė˜¤ 또는 팟ėēėŠ¤íŠ¸ëĨŧ ėž‘ė„ąí–ˆęą°ë‚˜ 발ę˛Ŧ하ė—Ŧ ė´ 파ėŧė„ íŽ¸ė§‘í•˜ė—Ŧ ęŗĩėœ í•  때. + * 해당 ė„šė…˜ė˜ ė‹œėž‘ ëļ€ëļ„뗐 링íŦëĨŧ ėļ”가해ė•ŧ 합니다. +* ë‹šė‹ ė˜ ė–¸ė–´ëĄœ [ëŦ¸ė„œ ë˛ˆė—­í•˜ëŠ”ë°](contributing.md#translations){.internal-link target=\_blank} 기ė—Ŧ할 때. + * 다ëĨ¸ ė‚ŦëžŒė´ ėž‘ė„ąí•œ ë˛ˆė—­ė„ 검토하는 것도 ë„ėš¸ 눘 ėžˆėŠĩ니다. +* ėƒˆëĄœėš´ ëŦ¸ė„œė˜ ė„šė…˜ė„ ė œė•ˆí•  때. +* ę¸°ėĄ´ ëŦ¸ė œ/버그ëĨŧ ėˆ˜ė •í•  때. + * í…ŒėŠ¤íŠ¸ëĨŧ ë°˜ë“œė‹œ ėļ”가해ė•ŧ 합니다. +* ėƒˆëĄœėš´ featureëĨŧ ėļ”가할 때. + * í…ŒėŠ¤íŠ¸ëĨŧ ë°˜ë“œė‹œ ėļ”가해ė•ŧ 합니다. + * 관련 ëŦ¸ė„œę°€ í•„ėš”í•˜ë‹¤ëŠ´ ë°˜ë“œė‹œ ėļ”가해ė•ŧ 합니다. + +## FastAPI ėœ ė§€ 관ëĻŦ뗐 ë„ė›€ ėŖŧ기 + +**FastAPI**ė˜ ėœ ė§€ 관ëĻŦëĨŧ ë„ė™€ėŖŧė„¸ėš”! 🤓 + +할 ėŧė´ ë§Žęŗ , ꡸ 뤑 대ëļ€ëļ„ė€ **ė—ŦëŸŦëļ„**ė´ 할 눘 ėžˆėŠĩ니다. + +ė§€ę¸ˆ 할 눘 ėžˆëŠ” ėŖŧėš” ėž‘ė—…ė€: + +* [GitHubė—ė„œ 다ëĨ¸ ė‚ŦëžŒë“¤ė˜ 마ëŦ¸ė— ë„ė›€ ėŖŧ기](#github_1){.internal-link target=_blank} (ėœ„ė˜ ė„šė…˜ė„ ė°¸ėĄ°í•˜ė„¸ėš”). +* [Pull Request ëĻŦ뷰하기](#pull-requests){.internal-link target=_blank} (ėœ„ė˜ ė„šė…˜ė„ ė°¸ėĄ°í•˜ė„¸ėš”). + +ė´ 두 ėž‘ė—…ė´ **가ėžĨ ë§Žė€ ė‹œę°„ė„ ė†ŒëǍ**하는 ėŧėž…ë‹ˆë‹¤. ęˇ¸ę˛ƒė´ FastAPI ėœ ė§€ 관ëĻŦė˜ ėŖŧėš” ėž‘ė—…ėž…ë‹ˆë‹¤. + +ė´ ėž‘ė—…ė„ ë„ė™€ėŖŧė‹ ë‹¤ëŠ´, **FastAPI ėœ ė§€ 관ëĻŦ뗐 ë„ė›€ė„ ėŖŧ는 것**ė´ëŠ° ęˇ¸ę˛ƒė´ **더 ëš ëĨ´ęŗ  더 ėž˜ ë°œė „í•˜ëŠ” 것**ė„ ëŗ´ėžĨ하는 ę˛ƒėž…ë‹ˆë‹¤. 🚀 + +## ėą„íŒ…ė— ė°¸ė—Ŧí•˜ė‹­ė‹œė˜¤ + +đŸ‘Ĩ ë””ėŠ¤ėŊ”드 ėą„íŒ… ė„œë˛„ đŸ‘Ĩ 뗐 ę°€ėž…í•˜ęŗ  FastAPI ėģ¤ëŽ¤ë‹ˆí‹°ė—ė„œ 다ëĨ¸ ė‚Ŧ람들ęŗŧ ė–´ėš¸ëĻŦė„¸ėš”. + +/// tip + +마ëŦ¸ė´ ėžˆëŠ” ę˛Ŋ뚰, GitHub ë””ėŠ¤ėģ¤ė…˜ ė—ė„œ 마ëŦ¸í•˜ė‹­ė‹œė˜¤, [FastAPI Experts](fastapi-people.md#fastapi-experts){.internal-link target=_blank} ė˜ ë„ė›€ė„ ë°›ė„ 가ëŠĨė„ąė´ 높ėŠĩ니다. + +다ëĨ¸ ėŧë°˜ė ė¸ ëŒ€í™”ė—ė„œë§Œ ėą„íŒ…ė„ ė‚ŦėšŠí•˜ė‹­ė‹œė˜¤. + +/// + +### 마ëŦ¸ė„ ėœ„í•´ ėą„íŒ…ė„ ė‚ŦėšŠí•˜ė§€ ë§ˆė‹­ė‹œė˜¤ + +ėą„íŒ…ė€ 더 ë§Žė€ "ėžėœ ëĄœėš´ 대화"ëĨŧ í—ˆėšŠí•˜ę¸° 때ëŦ¸ė—, 너ëŦ´ ėŧë°˜ė ė¸ 마ëŦ¸ė´ë‚˜ 대ë‹ĩ하기 ė–´ë ¤ėš´ 마ëŦ¸ė„ ė‰Ŋ枌 마ëŦ¸ė„ 할 눘 ėžˆėœŧë¯€ëĄœ, ë‹ĩëŗ€ė„ ë°›ė§€ ëĒģ할 눘 ėžˆėŠĩ니다. + +GitHub ė´ėŠˆė—ė„œė˜ 템플ëĻŋė€ ė˜Ŧ바ëĨ¸ 마ëŦ¸ė„ ėž‘ė„ąí•˜ë„ëĄ ė•ˆë‚´í•˜ė—Ŧ 더 ė‰Ŋ枌 ėĸ‹ė€ ë‹ĩëŗ€ė„ ė–ģ거나 마ëŦ¸í•˜ę¸° 렄뗐 ėŠ¤ėŠ¤ëĄœ ëŦ¸ė œëĨŧ 해결할 ėˆ˜ë„ ėžˆėŠĩ니다. ꡸ëĻŦęŗ  GitHubė—ė„œëŠ” ė‹œę°„ė´ ėĄ°ę¸ˆ 깸ëĻŦ더ëŧ도 í•­ėƒ ëĒ¨ë“  ę˛ƒė— ë‹ĩ할 눘 ėžˆėŠĩ니다. ėą„íŒ… ė‹œėŠ¤í…œė—ė„œëŠ” ę°œė¸ė ėœŧ로 그렇게 할 눘 ė—†ėŠĩ니다. 😅 + +ėą„íŒ… ė‹œėŠ¤í…œė—ė„œė˜ 대화 또한 GitHubė—ė„œ 래ëŸŧ ė‰Ŋ枌 ę˛€ėƒ‰í•  눘 뗆揰 때ëŦ¸ė— 대화 뤑뗐 마ëŦ¸ęŗŧ ë‹ĩëŗ€ė´ ė†ė‹¤ë  눘 ėžˆėŠĩ니다. ꡸ëĻŦęŗ  GitHub ė´ėŠˆė— ėžˆëŠ” 것만 [FastAPI Expert](fastapi-people.md#fastapi-experts){.internal-link target=_blank}가 되는 것ėœŧ로 간ėŖŧë˜ë¯€ëĄœ, GitHub ė´ėŠˆė—ė„œ 더 ë§Žė€ 관ė‹Ŧė„ ë°›ė„ ę˛ƒėž…ë‹ˆë‹¤. + +반늴, ėą„íŒ… ė‹œėŠ¤í…œė—ëŠ” 눘랜 ëĒ…ė˜ ė‚ŦėšŠėžę°€ ėžˆę¸° 때ëŦ¸ė—, ęą°ė˜ í•­ėƒ 대화 ėƒëŒ€ëĨŧ ė°žė„ 가ëŠĨė„ąė´ 높ėŠĩ니다. 😄 + +## ę°œë°œėž ėŠ¤í°ė„œę°€ ë˜ė‹­ė‹œė˜¤ + +GitHub ėŠ¤í°ė„œ ëĨŧ í†ĩ해 ę°œë°œėžëĨŧ ę˛Ŋ렜렁ėœŧ로 ė§€ė›í•  눘 ėžˆėŠĩ니다. + +감ė‚Ŧ하다는 말로 ėģ¤í”ŧëĨŧ â˜•ī¸ í•œėž” ė‚Ŧ뤄 눘 ėžˆėŠĩ니다. 😄 + +또한 FastAPIė˜ ė‹¤ë˛„ 또는 ęŗ¨ë“œ ėŠ¤í°ė„œę°€ 될 눘 ėžˆėŠĩ니다. 🏅🎉 + +## FastAPIëĨŧ 강화하는 도ęĩŦė˜ ėŠ¤í°ė„œę°€ ë˜ė‹­ė‹œė˜¤ + +ëŦ¸ė„œė—ė„œ ëŗ´ė•˜ë“¯ė´, FastAPI는 Starletteęŗŧ Pydantic ëŧ는 ęą°ė¸ė˜ ė–´ęš¨ė— íƒ€ęŗ  ėžˆėŠĩ니다. + +ë‹¤ėŒė˜ ėŠ¤í°ė„œę°€ 될 눘 ėžˆėŠĩ니다 + +* Samuel Colvin (Pydantic) +* Encode (Starlette, Uvicorn) + +--- + +감ė‚Ŧ합니다! 🚀 diff --git a/docs/ko/docs/index.md b/docs/ko/docs/index.md index 8b00d90bc..0df2000fa 100644 --- a/docs/ko/docs/index.md +++ b/docs/ko/docs/index.md @@ -11,15 +11,18 @@ FastAPI í”„ë ˆėž„ė›ŒíŦ, ęŗ ė„ąëŠĨ, 간편한 학ėŠĩ, ëš ëĨ¸ ėŊ”드 ėž‘ė„ą, ė¤€ëš„ëœ í”„ëĄœë•ė…˜

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

--- diff --git a/docs/ko/docs/tutorial/dependencies/dependencies-with-yield.md b/docs/ko/docs/tutorial/dependencies/dependencies-with-yield.md new file mode 100644 index 000000000..ff174937d --- /dev/null +++ b/docs/ko/docs/tutorial/dependencies/dependencies-with-yield.md @@ -0,0 +1,275 @@ +# yieldëĨŧ ė‚ŦėšŠí•˜ëŠ” ė˜ėĄ´ė„ą + +FastAPI는 ėž‘ė—… ė™„ëŖŒ 후 ėļ”ę°€ ë‹¨ęŗ„ëĨŧ ėˆ˜í–‰í•˜ëŠ” ė˜ėĄ´ė„ąė„ ė§€ė›í•Šë‹ˆë‹¤. + +ė´ëĨŧ ęĩŦ현하려면 `return` ëŒ€ė‹  `yield`ëĨŧ ė‚ŦėšŠí•˜ęŗ , ėļ”ę°€ëĄœ ė‹¤í–‰í•  ë‹¨ęŗ„ (ėŊ”드)ëĨŧ ꡸ ë’¤ė— ėž‘ė„ąí•˜ė„¸ėš”. + +/// tip | 팁 + +각 ė˜ėĄ´ė„ąë§ˆë‹¤ `yield`는 한 번만 ė‚ŦėšŠí•´ė•ŧ 합니다. + +/// + +/// note | 揰눠 넏ëļ€ė‚Ŧ항 + +ë‹¤ėŒęŗŧ 함ęģ˜ ė‚ŦėšŠí•  눘 ėžˆëŠ” ëĒ¨ë“  í•¨ėˆ˜: + +* `@contextlib.contextmanager` 또는 +* `@contextlib.asynccontextmanager` + +는 **FastAPI**ė˜ ė˜ėĄ´ė„ąėœŧ로 ė‚ŦėšŠí•  눘 ėžˆėŠĩ니다. + +ė‚Ŧ다, FastAPI는 내ëļ€ė ėœŧ로 ė´ 두 데ėŊ”ë ˆė´í„°ëĨŧ ė‚ŦėšŠí•Šë‹ˆë‹¤. + +/// + +## `yield`ëĨŧ ė‚ŦėšŠí•˜ëŠ” ë°ė´í„°ë˛ ė´ėŠ¤ ė˜ėĄ´ė„ą + +똈ëĨŧ ë“¤ė–´, ė´ 기ëŠĨė„ ė‚ŦėšŠí•˜ëŠ´ ë°ė´í„°ë˛ ė´ėŠ¤ ė„¸ė…˜ė„ ėƒė„ąí•˜ęŗ  ėž‘ė—…ė´ 끝난 í›„ė— ė„¸ė…˜ė„ ėĸ…ëŖŒí•  눘 ėžˆėŠĩ니다. + +ė‘ë‹ĩė„ ėƒė„ąí•˜ę¸° ė „ė—ëŠ” `yield`ëŦ¸ė„ íŦ함하ė—Ŧ ꡸ ė´ė „ė˜ ėŊ”ë“œë§Œė´ ė‹¤í–‰ëŠë‹ˆë‹¤: + +{* ../../docs_src/dependencies/tutorial007.py hl[2:4] *} + +yield된 ę°’ė€ *ę˛Ŋ로 ėž‘ė—…* 및 다ëĨ¸ ė˜ėĄ´ė„ąë“¤ė— ėŖŧėž…ë˜ëŠ” 값 ėž…ë‹ˆë‹¤: + +{* ../../docs_src/dependencies/tutorial007.py hl[4] *} + +`yield`ëŦ¸ ë‹¤ėŒė˜ ėŊ”드는 ė‘ë‹ĩė„ ėƒė„ąí•œ 후 ëŗ´ë‚´ę¸° 렄뗐 ė‹¤í–‰ëŠë‹ˆë‹¤: + +{* ../../docs_src/dependencies/tutorial007.py hl[5:6] *} + +/// tip | 팁 + +`async` í•¨ėˆ˜ė™€ ėŧ반 í•¨ėˆ˜ ëĒ¨ë‘ ė‚ŦėšŠí•  눘 ėžˆėŠĩ니다. + +**FastAPI**는 ėŧ반 ė˜ėĄ´ė„ąęŗŧ 마ė°Ŧę°€ė§€ëĄœ ę°ę°ė˜ í•¨ėˆ˜ëĨŧ ė˜Ŧ바ëĨ´ę˛Œ 래ëĻŦ할 ę˛ƒėž…ë‹ˆë‹¤. + +/// + +## `yield`뙀 `try`ëĨŧ ė‚ŦėšŠí•˜ëŠ” ė˜ėĄ´ė„ą + +`yield`ëĨŧ ė‚ŦėšŠí•˜ëŠ” ė˜ėĄ´ė„ąė—ė„œ `try` ë¸”ëĄė„ ė‚ŦėšŠí•œë‹¤ëŠ´, ė˜ėĄ´ė„ąė„ ė‚ŦėšŠí•˜ëŠ” ë„ė¤‘ ë°œėƒí•œ ëĒ¨ë“  ė˜ˆė™¸ëĨŧ ë°›ė„ 눘 ėžˆėŠĩ니다. + +똈ëĨŧ ë“¤ė–´, 다ëĨ¸ ė˜ėĄ´ė„ąė´ë‚˜ *ę˛Ŋ로 ėž‘ė—…*ė˜ 뤑氄뗐 ë°ė´í„°ë˛ ė´ėŠ¤ íŠ¸ëžœėž­ė…˜ "륤밹"ė´ ë°œėƒí•˜ęą°ë‚˜ 다ëĨ¸ 똤ëĨ˜ę°€ ë°œėƒí•œë‹¤ëŠ´, 해당 ė˜ˆė™¸ëĨŧ ė˜ėĄ´ė„ąė—ė„œ ë°›ė„ 눘 ėžˆėŠĩ니다. + +따ëŧė„œ, ė˜ėĄ´ė„ą ë‚´ė—ė„œ `except SomeException`ė„ ė‚ŦėšŠí•˜ė—Ŧ íŠšė • ė˜ˆė™¸ëĨŧ 래ëĻŦ할 눘 ėžˆėŠĩ니다. + +마ė°Ŧę°€ė§€ëĄœ, `finally`ëĨŧ ė‚ŦėšŠí•˜ė—Ŧ ė˜ˆė™¸ ë°œėƒ ė—Ŧëļ€ė™€ 洀溄 ė—†ė´ ėĸ…ëŖŒ ë‹¨ęŗ„ęšŒ ė‹¤í–‰ë˜ë„ëĄ 할 눘 ėžˆėŠĩ니다. + +{* ../../docs_src/dependencies/tutorial007.py hl[3,5] *} + +## `yield`ëĨŧ ė‚ŦėšŠí•˜ëŠ” í•˜ėœ„ ė˜ėĄ´ė„ą + +ëĒ¨ë“  íŦ揰뙀 í˜•íƒœė˜ í•˜ėœ„ ė˜ėĄ´ė„ąęŗŧ í•˜ėœ„ ė˜ėĄ´ė„ąė˜ "트ëĻŦ"도 ę°€ė§ˆ 눘 ėžˆėœŧ늰, ė´ë“¤ ëĒ¨ë‘ę°€ `yield`ëĨŧ ė‚ŦėšŠí•  눘 ėžˆėŠĩ니다. + +**FastAPI**는 `yield`ëĨŧ ė‚ŦėšŠí•˜ëŠ” 각 ė˜ėĄ´ė„ąė˜ "ėĸ…ëŖŒ ėŊ”드"가 ė˜Ŧ바ëĨ¸ ėˆœė„œëĄœ ė‹¤í–‰ë˜ë„ëĄ ëŗ´ėžĨ합니다. + +똈ëĨŧ ë“¤ė–´, `dependency_c`는 `dependency_b`뗐 ė˜ėĄ´í•  눘 ėžˆęŗ , `dependency_b`는 `dependency_a`뗐 ė˜ėĄ´í•  눘 ėžˆėŠĩ니다. + +{* ../../docs_src/dependencies/tutorial008_an_py39.py hl[6,14,22] *} + +ė´ë“¤ ëĒ¨ë‘ëŠ” `yield`ëĨŧ ė‚ŦėšŠí•  눘 ėžˆėŠĩ니다. + +ė´ ę˛Ŋ뚰 `dependency_c`는 ėĸ…ëŖŒ ėŊ”드ëĨŧ ė‹¤í–‰í•˜ę¸° ėœ„í•´, `dependency_b`ė˜ 값 (ė—Ŧę¸°ė„œëŠ” `dep_b`로 ëĒ…ëĒ…)ė´ ė—Ŧė „ížˆ ė‚ŦėšŠ 가ëŠĨ해ė•ŧ 합니다. + +꡸ëĻŦęŗ , `dependency_b`는 ėĸ…ëŖŒ ėŊ”드ëĨŧ ėœ„í•´ `dependency_a`ė˜ 값 (ė—Ŧę¸°ė„œëŠ” `dep_a`로 ëĒ…ëĒ…) ė´ ė‚ŦėšŠ 가ëŠĨ해ė•ŧ 합니다. + +{* ../../docs_src/dependencies/tutorial008_an_py39.py hl[18:19,26:27] *} + +ę°™ė€ ë°Šė‹ėœŧ로, `yield`ëĨŧ ė‚ŦėšŠí•˜ëŠ” ė˜ėĄ´ė„ąęŗŧ `return`ė„ ė‚ŦėšŠí•˜ëŠ” ė˜ėĄ´ė„ąė„ 함ęģ˜ ė‚ŦėšŠí•  눘 ėžˆėœŧ늰, ė´ë“¤ 뤑 ėŧëļ€ę°€ 다ëĨ¸ ę˛ƒë“¤ė— ė˜ėĄ´í•  눘 ėžˆėŠĩ니다. + +꡸ëĻŦęŗ  `yield`ëĨŧ ė‚ŦėšŠí•˜ëŠ” 다ëĨ¸ ė—ŦëŸŦ ė˜ėĄ´ė„ąė„ í•„ėš”ëĄœ 하는 단ėŧ ė˜ėĄ´ė„ąė„ ę°€ė§ˆ ėˆ˜ë„ ėžˆėŠĩ니다. + +ė›í•˜ëŠ” ė˜ėĄ´ė„ąė„ ė›í•˜ëŠ” 대로 ėĄ°í•Ší•  눘 ėžˆėŠĩ니다. + +**FastAPI**는 ëĒ¨ë“  ę˛ƒė´ ė˜Ŧ바ëĨ¸ ėˆœė„œëĄœ ė‹¤í–‰ë˜ë„ëĄ ëŗ´ėžĨ합니다. + +/// note | 揰눠 넏ëļ€ė‚Ŧ항 + +íŒŒė´ėŦė˜ Context Managers 덕ëļ„뗐 ė´ 기ëŠĨė´ ėž‘ë™í•Šë‹ˆë‹¤. + +**FastAPI**는 ė´ëĨŧ 내ëļ€ė ėœŧ로 ėģ¨í…ėŠ¤íŠ¸ 관ëĻŦėžëĨŧ ė‚ŦėšŠí•˜ė—Ŧ ęĩŦ현합니다. + +/// + +## `yield`뙀 `HTTPException`ëĨŧ ė‚ŦėšŠí•˜ëŠ” ė˜ėĄ´ė„ą + +`yield`뙀 `try` ë¸”ëĄė´ ėžˆëŠ” ė˜ėĄ´ė„ąė„ ė‚ŦėšŠí•˜ė—Ŧ ė˜ˆė™¸ëĨŧ 래ëĻŦ할 눘 ėžˆë‹¤ëŠ” ę˛ƒė„ ė•Œę˛Œ ë˜ė—ˆėŠĩ니다. + +ę°™ė€ ë°Šė‹ėœŧ로, `yield` ė´í›„ė˜ ėĸ…ëŖŒ ėŊ”ë“œė—ė„œ `HTTPException`ė´ë‚˜ 뜠ė‚Ŧ한 ė˜ˆė™¸ëĨŧ ë°œėƒė‹œí‚Ŧ 눘 ėžˆėŠĩ니다. + +/// tip | 팁 + +ė´ëŠ” ë‹¤ė†Œ 溠揉 ę¸°ėˆ ė´ëŠ°, 대ëļ€ëļ„ė˜ ę˛Ŋ뚰 ę˛Ŋ로 ė—°ė‚° í•¨ėˆ˜ 등 ë‚˜ë¨¸ė§€ ė• í”ŒëĻŦėŧ€ė´ė…˜ ėŊ”드 내ëļ€ė—ė„œ ė˜ˆė™¸ (`HTTPException` íŦ함)ëĨŧ ë°œėƒė‹œí‚Ŧ 눘 ėžˆėœŧë¯€ëĄœ ė‹¤ė œëĄœëŠ” í•„ėš”í•˜ė§€ ė•Šė„ ę˛ƒėž…ë‹ˆë‹¤. + +í•˜ė§€ë§Œ í•„ėš”í•œ ę˛Ŋ뚰 ė‚ŦėšŠí•  눘 ėžˆėŠĩ니다. 🤓 + +/// + +{* ../../docs_src/dependencies/tutorial008b_an_py39.py hl[18:22,31] *} + +ė˜ˆė™¸ëĨŧ 래ëĻŦí•˜ęŗ (또는 ėļ”ę°€ëĄœ 다ëĨ¸ `HTTPException`ė„ ë°œėƒė‹œí‚¤ę¸° ėœ„í•´) ė‚ŦėšŠí•  눘 ėžˆëŠ” 또 다ëĨ¸ ë°Šë˛•ė€ [ė‚ŦėšŠėž ė •ė˜ ė˜ˆė™¸ 래ëĻŦ기](../handling-errors.md#install-custom-exception-handlers){.internal-link target=_blank}ëĨŧ ėƒė„ąí•˜ëŠ” 것 ėž…ë‹ˆë‹¤. + +## `yield`뙀 `except`ëĨŧ ė‚ŦėšŠí•˜ëŠ” ė˜ėĄ´ė„ą + +`yield`ëĨŧ ė‚ŦėšŠí•˜ëŠ” ė˜ėĄ´ė„ąė—ė„œ `except`ëĨŧ ė‚ŦėšŠí•˜ė—Ŧ ė˜ˆė™¸ëĨŧ íŦė°Ší•˜ęŗ  ė˜ˆė™¸ëĨŧ ë‹¤ė‹œ ë°œėƒė‹œí‚¤ė§€ ė•Šęą°ë‚˜ (또는 냈 ė˜ˆė™¸ëĨŧ ë°œėƒė‹œí‚¤ė§€ ė•Šėœŧ늴), FastAPI는 해당 ė˜ˆė™¸ę°€ ë°œėƒí–ˆëŠ”ė§€ ė•Œ 눘 ė—†ėŠĩ니다. ė´ëŠ” ėŧë°˜ė ė¸ Python ë°Šė‹ęŗŧ 동ėŧ합니다: + +{* ../../docs_src/dependencies/tutorial008c_an_py39.py hl[15:16] *} + +ė´ ę˛Ŋ뚰, `HTTPException`ė´ë‚˜ 뜠ė‚Ŧ한 ė˜ˆė™¸ëĨŧ ë°œėƒė‹œí‚¤ė§€ ė•Šę¸° 때ëŦ¸ė— 클ëŧė´ė–¸íŠ¸ëŠ” HTTP 500 Internal Server Error ė‘ë‹ĩė„ ëŗ´ę˛Œ ë˜ė§€ë§Œ, ė„œë˛„ëŠ” ė–´ë–¤ 똤ëĨ˜ę°€ ë°œėƒí–ˆëŠ”ė§€ė— 대한 **로그**나 다ëĨ¸ í‘œė‹œëĨŧ ė „í˜€ 氀맀맀 ė•Šę˛Œ 됩니다. 😱 + +### `yield`뙀 `except`ëĨŧ ė‚ŦėšŠí•˜ëŠ” ė˜ėĄ´ė„ąė—ė„œ í•­ėƒ `raise` 하기 + +`yield`가 ėžˆëŠ” ė˜ėĄ´ė„ąė—ė„œ ė˜ˆė™¸ëĨŧ ėžĄė•˜ė„ 때는 `HTTPException`ė´ë‚˜ 뜠ė‚Ŧ한 ė˜ˆė™¸ëĨŧ ėƒˆëĄœ ë°œėƒė‹œí‚¤ė§€ ė•ŠëŠ” 한, ë°˜ë“œė‹œ ė›ëž˜ė˜ ė˜ˆė™¸ëĨŧ ë‹¤ė‹œ ë°œėƒė‹œėŧœė•ŧ 합니다. + +`raise`ëĨŧ ė‚ŦėšŠí•˜ė—Ŧ 동ėŧ한 ė˜ˆė™¸ëĨŧ ë‹¤ė‹œ ë°œėƒė‹œí‚Ŧ 눘 ėžˆėŠĩ니다: + +{* ../../docs_src/dependencies/tutorial008d_an_py39.py hl[17] *} + +ė´ė œ 클ëŧė´ė–¸íŠ¸ëŠ” 동ėŧ한 *HTTP 500 Internal Server Error* 똤ëĨ˜ ė‘ë‹ĩė„ 받게 ë˜ė§€ë§Œ, ė„œë˛„ ëĄœęˇ¸ė—ëŠ” ė‚ŦėšŠėž ė •ė˜ ė˜ˆė™¸ė¸ `InternalError"가 기록됩니다. 😎 + +## `yield`ëĨŧ ė‚ŦėšŠí•˜ëŠ” ė˜ėĄ´ė„ąė˜ ė‹¤í–‰ ėˆœė„œ + +ė‹¤í–‰ ėˆœė„œëŠ” ė•„ëž˜ ë‹¤ė´ė–´ęˇ¸ëž¨ęŗŧ ęą°ė˜ ëš„ėŠˇí•Šë‹ˆë‹¤. ė‹œę°„ė€ ėœ„ė—ė„œ ė•„ëž˜ëĄœ 흐ëĻ…ë‹ˆë‹¤. ꡸ëĻŦęŗ  각 ė—´ė€ ėƒí˜¸ ėž‘ėšŠí•˜ęą°ë‚˜ ėŊ”드ëĨŧ ė‹¤í–‰í•˜ëŠ” ëļ€ëļ„ ė¤‘ í•˜ë‚˜ėž…ë‹ˆë‹¤. + +```mermaid +sequenceDiagram + +participant client as Client +participant handler as Exception handler +participant dep as Dep with yield +participant operation as Path Operation +participant tasks as Background tasks + + Note over client,operation: Can raise exceptions, including HTTPException + client ->> dep: Start request + Note over dep: Run code up to yield + opt raise Exception + dep -->> handler: Raise Exception + handler -->> client: HTTP error response + end + dep ->> operation: Run dependency, e.g. DB session + opt raise + operation -->> dep: Raise Exception (e.g. HTTPException) + opt handle + dep -->> dep: Can catch exception, raise a new HTTPException, raise other exception + end + handler -->> client: HTTP error response + end + + operation ->> client: Return response to client + Note over client,operation: Response is already sent, can't change it anymore + opt Tasks + operation -->> tasks: Send background tasks + end + opt Raise other exception + tasks -->> tasks: Handle exceptions in the background task code + end +``` + +/// info | ė •ëŗ´ + +클ëŧė´ė–¸íŠ¸ė— **í•˜ë‚˜ė˜ ė‘ë‹ĩ** 만 ė „ė†ĄëŠë‹ˆë‹¤. ė´ëŠ” 똤ëĨ˜ ė‘ë‹ĩ 뤑 하나ėŧ ėˆ˜ë„ ėžˆęŗ ,*ę˛Ŋ로 ėž‘ė—…*ė—ė„œ ėƒė„ąëœ ė‘ë‹ĩėŧ ėˆ˜ë„ ėžˆėŠĩ니다. + +ė´ëŸŦ한 ė‘ë‹ĩ 뤑 하나가 ė „ė†Ąëœ í›„ė—ëŠ” 다ëĨ¸ ė‘ë‹ĩė„ ëŗ´ë‚ŧ 눘 ė—†ėŠĩ니다. + +/// + +/// tip | 팁 + +ė´ ë‹¤ė´ė–´ęˇ¸ëž¨ė€ `HTTPException`ė„ ëŗ´ė—ŦėŖŧė§€ë§Œ, `yield`ëĨŧ ė‚ŦėšŠí•˜ëŠ” ė˜ėĄ´ė„ąė—ė„œ 래ëĻŦ한 ė˜ˆė™¸ë‚˜ [ė‚ŦėšŠėž ė •ė˜ ė˜ˆė™¸ė˛˜ëĻŦ기](../handling-errors.md#install-custom-exception-handlers){.internal-link target=_blank}.ëĨŧ ė‚ŦėšŠí•˜ė—Ŧ 래ëĻŦ한 다ëĨ¸ ė˜ˆė™¸ë„ ë°œėƒė‹œí‚Ŧ 눘 ėžˆėŠĩ니다. + +ė–´ë–¤ ė˜ˆė™¸ę°€ ë°œėƒí•˜ë“ , `HTTPException`ė„ íŦ함하ė—Ŧ yieldëĨŧ ė‚ŦėšŠí•˜ëŠ” ė˜ėĄ´ė„ąėœŧ로 ė „ë‹Ŧ됩니다. 대ëļ€ëļ„ė˜ ę˛Ŋ뚰 ė˜ˆė™¸ëĨŧ ë‹¤ė‹œ ë°œėƒė‹œí‚¤ęą°ë‚˜ ėƒˆëĄœėš´ ė˜ˆė™¸ëĨŧ ë°œėƒė‹œėŧœė•ŧ 합니다. + +/// + +## `yield`, `HTTPException`, `except` 및 밹꡸ëŧėš´ë“œ ėž‘ė—…ė„ ė‚ŦėšŠí•˜ëŠ” ė˜ėĄ´ė„ą + +/// warning | ę˛Ŋęŗ  + +ė´ëŸŦ한 揰눠렁 넏ëļ€ ė‚Ŧí•­ė€ 대ëļ€ëļ„ í•„ėš”í•˜ė§€ ė•Šėœŧë¯€ëĄœ ė´ ė„šė…˜ė„ ęą´ë„ˆë›°ęŗ  ė•„ëž˜ė—ė„œ ęŗ„ė† ė§„í–‰í•´ë„ 됩니다. + +ė´ëŸŦ한 넏ëļ€ ė •ëŗ´ëŠ” ėŖŧ로 FastAPI 0.106.0 ė´ė „ ë˛„ė „ė—ė„œ `yield`가 ėžˆëŠ” ė˜ėĄ´ė„ąė˜ ëĻŦė†ŒėŠ¤ëĨŧ 밹꡸ëŧėš´ë“œ ėž‘ė—…ė—ė„œ ė‚ŦėšŠí–ˆë˜ ę˛Ŋėš°ëŠ” ėœ ėšŠí•Šë‹ˆë‹¤. + +/// + +### `yield`뙀 `except`ëĨŧ ė‚ŦėšŠí•˜ëŠ” ė˜ėĄ´ė„ą, 揰눠 넏ëļ€ė‚Ŧ항 + +FastAPI 0.110.0 ė´ė „ė—ëŠ” `yield`가 íŦ함된 ė˜ėĄ´ė„ąė„ ė‚ŦėšŠí•œ 후 해당 ė˜ėĄ´ė„ąė—ė„œ `except`가 íŦ함된 ė˜ˆė™¸ëĨŧ ėēĄė˛˜í•˜ęŗ  ë‹¤ė‹œ ė˜ˆė™¸ëĨŧ ë°œėƒė‹œí‚¤ė§€ ė•Šėœŧ늴 ė˜ˆė™¸ę°€ ėžë™ėœŧ로 ė˜ˆė™¸ 핸들ëŸŦ 또는 내ëļ€ ė„œë˛„ 똤ëĨ˜ 핸들ëŸŦ로 ë°œėƒ/ė „ë‹Ŧë˜ė—ˆėŠĩ니다. + +ė´ëŠ” 래ëĻŦ기 ė—†ė´ ė „ë‹Ŧ된 ė˜ˆė™¸(내ëļ€ ė„œë˛„ 똤ëĨ˜)ė—ė„œ 래ëĻŦë˜ė§€ ė•Šė€ 메ëǍëĻŦ ė†Œëš„ëĨŧ ėˆ˜ė •í•˜ęŗ  ėŧ반 íŒŒė´ėŦ ėŊ”ë“œė˜ ë™ėž‘ęŗŧ ėŧėš˜í•˜ë„ëĄ 하기 ėœ„í•´ 0.110.0 ë˛„ė „ė—ė„œ ëŗ€ę˛Ŋë˜ė—ˆėŠĩ니다. + +### 밹꡸ëŧėš´ë“œ ėž‘ė—…ęŗŧ `yield`ëĨŧ ė‚ŦėšŠí•˜ëŠ” ė˜ėĄ´ė„ą, 揰눠 넏ëļ€ė‚Ŧ항 + +FastAPI 0.106.0 ė´ė „ė—ëŠ” `yield` ė´í›„ė— ė˜ˆė™¸ëĨŧ ë°œėƒė‹œí‚¤ëŠ” ę˛ƒė´ ëļˆę°€ëŠĨ했ėŠĩ니다. `yield`가 ėžˆëŠ” ė˜ėĄ´ė„ą ėĸ…ëŖŒ ėŊ”드는 ė‘ë‹ĩė´ ė „ė†Ąëœ ė´í›„ė— ė‹¤í–‰ë˜ė—ˆę¸° 때ëŦ¸ė—, [ė˜ˆė™¸ 래ëĻŦ기](../handling-errors.md#install-custom-exception-handlers){.internal-link target=_blank}가 ė´ë¯¸ ė‹¤í–‰ëœ ėƒíƒœė˜€ėŠĩ니다. + +ė´ëŠ” ėŖŧ로 밹꡸ëŧėš´ë“œ ėž‘ė—… ë‚´ė—ė„œ ė˜ėĄ´ė„ąė—ė„œ "yield된" 동ėŧ한 ę°ė˛´ëĨŧ ė‚ŦėšŠí•  눘 ėžˆë„ëĄ 하기 ėœ„í•´ ė´ëŸ° ë°Šė‹ėœŧ로 ė„¤ęŗ„ë˜ė—ˆėŠĩ니다. ėĸ…ëŖŒ ėŊ”드는 밹꡸ëŧėš´ë“œ ėž‘ė—…ė´ ė™„ëŖŒëœ í›„ė— ė‹¤í–‰ë˜ė—ˆę¸° 때ëŦ¸ėž…니다 + +í•˜ė§€ë§Œ ė´ë ‡ę˛Œ 하면 ëĻŦė†ŒėŠ¤ëĨŧ ëļˆí•„ėš”í•˜ę˛Œ ė–‘ëŗ´í•œ ė˜ėĄ´ė„ą(똈: ë°ė´í„°ë˛ ė´ėŠ¤ 뗰枰)ė—ė„œ ëŗ´ėœ í•˜ëŠ´ė„œ ė‘ë‹ĩė´ ë„¤íŠ¸ė›ŒíŦëĨŧ í†ĩ해 ė´ë™í•  ë•ŒęšŒė§€ 기다ëĻŦ는 ę˛ƒė„ ė˜ë¯¸í•˜ę¸° 때ëŦ¸ė— FastAPI 0.106.0ė—ė„œ ëŗ€ę˛Ŋë˜ė—ˆėŠĩ니다. + +/// tip | 팁 + +또한 밹꡸ëŧėš´ë“œ ėž‘ė—…ė€ ėŧë°˜ė ėœŧ로 ėžė˛´ ëĻŦė†ŒėŠ¤(똈: ėžė˛´ ë°ė´í„°ë˛ ė´ėŠ¤ 뗰枰)ëĨŧ ė‚ŦėšŠí•˜ė—Ŧ ëŗ„ë„ëĄœ 래ëĻŦ해ė•ŧ 하는 독ëĻŊė ė¸ ëĄœė§ ė§‘í•Šėž…ë‹ˆë‹¤. + +따ëŧė„œ ė´ë ‡ę˛Œ 하면 ėŊ”ë“œę°€ 더 ęš”ë”í•´ė§‘ë‹ˆë‹¤. + +/// + +만ė•Ŋ ė´ė „ė— ė´ëŸŦ한 ë™ėž‘ė— ė˜ėĄ´í–ˆë‹¤ëŠ´, ė´ė œëŠ” 밹꡸ëŧėš´ë“œ ėž‘ė—… 내ëļ€ė—ė„œ 밹꡸ëŧėš´ë“œ ėž‘ė—…ė„ ėœ„í•œ ëĻŦė†ŒėŠ¤ëĨŧ ėƒė„ąí•˜ęŗ , `yield`가 ėžˆëŠ” ė˜ėĄ´ė„ąė˜ ëĻŦė†ŒėŠ¤ė— ė˜ėĄ´í•˜ė§€ ė•ŠëŠ” ë°ė´í„°ë§Œ 내ëļ€ė ėœŧ로 ė‚ŦėšŠí•´ė•ŧ합니다. + +똈ëĨŧ ë“¤ė–´, 동ėŧ한 ë°ė´í„°ë˛ ė´ėŠ¤ ė„¸ė…˜ė„ ė‚ŦėšŠí•˜ëŠ” ëŒ€ė‹ , 밹꡸ëŧėš´ë“œ ėž‘ė—… 내ëļ€ė—ė„œ ėƒˆëĄœėš´ ë°ė´í„°ë˛ ė´ėŠ¤ ė„¸ė…˜ė„ ėƒė„ąí•˜ęŗ  ė´ ėƒˆëĄœėš´ ė„¸ė…˜ė„ ė‚ŦėšŠí•˜ė—Ŧ ë°ė´í„°ë˛ ė´ėŠ¤ė—ė„œ ę°ė˛´ëĨŧ 氀렏뙀ė•ŧ 합니다. ꡸ëĻŦęŗ  ë°ė´í„°ë˛ ė´ėŠ¤ ę°ė˛´ëĨŧ 밹꡸ëŧėš´ë“œ ėž‘ė—… í•¨ėˆ˜ė˜ ë§¤ę°œëŗ€ėˆ˜ëĄœ 링렑 ė „ë‹Ŧ하는 ëŒ€ė‹ , 해당 ę°ė˛´ė˜ IDëĨŧ ė „ë‹Ŧ한 ë‹¤ėŒ 밹꡸ëŧėš´ë“œ ėž‘ė—… í•¨ėˆ˜ 내ëļ€ė—ė„œ ę°ė˛´ëĨŧ ë‹¤ė‹œ 氀렏뙀ė•ŧ 합니다 + +## ėģ¨í…ėŠ¤íŠ¸ 관ëĻŦėž + +### "ėģ¨í…ėŠ¤íŠ¸ 관ëĻŦėž"란? + +"ėģ¨í…ėŠ¤íŠ¸ 관ëĻŦėž"는 Pythonė—ė„œ `with` ëŦ¸ė—ė„œ ė‚ŦėšŠí•  눘 ėžˆëŠ” ëĒ¨ë“  ę°ė˛´ëĨŧ ė˜ë¯¸í•Šë‹ˆë‹¤. + +똈ëĨŧ ë“¤ė–´, `with`ëĨŧ ė‚ŦėšŠí•˜ė—Ŧ 파ėŧė„ ėŊė„ 눘 ėžˆėŠĩ니다: + +```Python +with open("./somefile.txt") as f: + contents = f.read() + print(contents) +``` + +내ëļ€ė ėœŧ로 `open("./somefile.txt")` 는 "ėģ¨í…ėŠ¤íŠ¸ 관ëĻŦėž(Context Manager)"ëŧęŗ  ëļˆëĻŦ는 ę°ė˛´ëĨŧ ėƒė„ąí•Šë‹ˆë‹¤. + +`with` ë¸”ëĄė´ 끝나면, ė˜ˆė™¸ę°€ ë°œėƒí–ˆë”ëŧ도 파ėŧė„ ë‹Ģ도록 ëŗ´ėžĨ합니다. + +`yield`가 ėžˆëŠ” ė˜ėĄ´ė„ąė„ ėƒė„ąí•˜ëŠ´ **FastAPI**는 내ëļ€ė ėœŧ로 ė´ëĨŧ ėœ„í•œ ėģ¨í…ėŠ¤íŠ¸ ë§¤ë‹ˆė €ëĨŧ ėƒė„ąí•˜ęŗ  다ëĨ¸ 관련 도ęĩŦ들ęŗŧ 결합합니다. + +### `yield`ëĨŧ ė‚ŦėšŠí•˜ëŠ” ė˜ėĄ´ė„ąė—ė„œ ėģ¨í…ėŠ¤íŠ¸ 관ëĻŦėž ė‚ŦėšŠí•˜ę¸° + +/// warning | ę˛Ŋęŗ  + +ė´ę˛ƒė€ ė–´ëŠ ė •ë„ "溠揉" ę°œë…ėž…ë‹ˆë‹¤. + +**FastAPI**ëĨŧ ė˛˜ėŒ ė‹œėž‘í•˜ëŠ” ę˛Ŋ뚰 ė§€ę¸ˆė€ ė´ ëļ€ëļ„ė„ ęą´ë„ˆë›°ė–´ë„ ėĸ‹ėŠĩ니다. + +/// + +Pythonė—ė„œëŠ” ë‹¤ėŒė„ í†ĩ해 ėģ¨í…ėŠ¤íŠ¸ 관ëĻŦėžëĨŧ ėƒė„ąí•  눘 ėžˆėŠĩ니다. 두 氀맀 ëŠ”ė„œë“œę°€ ėžˆëŠ” í´ëž˜ėŠ¤ëĨŧ ėƒė„ąí•Šë‹ˆë‹¤: `__enter__()` and `__exit__()`. + +**FastAPI**ė˜ `yield`가 ėžˆëŠ” ė˜ėĄ´ė„ą ë‚´ė—ė„œ +`with` 또는 `async with`ëŦ¸ė„ ė‚ŦėšŠí•˜ė—Ŧ ė´ë“¤ė„ í™œėšŠí•  눘 ėžˆėŠĩ니다: + +{* ../../docs_src/dependencies/tutorial010.py hl[1:9,13] *} + +/// tip | 팁 + +ėģ¨í…ėŠ¤íŠ¸ 관ëĻŦėžëĨŧ ėƒė„ąí•˜ëŠ” 또 다ëĨ¸ ë°Šë˛•ė€ ë‹¤ėŒęŗŧ 같ėŠĩ니다: + +* `@contextlib.contextmanager` 또는 +* `@contextlib.asynccontextmanager` + +ė´ë“¤ė€ 단ėŧ `yield`가 ėžˆëŠ” í•¨ėˆ˜ëĨŧ ęž¸ë¯¸ëŠ” 데 ė‚ŦėšŠí•Šë‹ˆë‹¤. + +ė´ę˛ƒė´ **FastAPI**가 `yield`가 ėžˆëŠ” ė˜ėĄ´ė„ąė„ ėœ„í•´ 내ëļ€ė ėœŧ로 ė‚ŦėšŠí•˜ëŠ” ë°Šė‹ėž…ë‹ˆë‹¤. + +í•˜ė§€ë§Œ FastAPI ė˜ėĄ´ė„ąė—ëŠ” ė´ëŸŦ한 데ėŊ”ë ˆė´í„°ëĨŧ ė‚ŦėšŠí•  í•„ėš”ę°€ ė—†ėŠĩ니다(꡸ëĻŦęŗ  ė‚ŦėšŠí•´ė„œë„ ė•ˆëŠë‹ˆë‹¤). + +FastAPI가 내ëļ€ė ėœŧ로 ė´ëĨŧ 래ëĻŦ해 뤄 ę˛ƒėž…ë‹ˆë‹¤. + +/// diff --git a/docs/ko/docs/tutorial/extra-models.md b/docs/ko/docs/tutorial/extra-models.md new file mode 100644 index 000000000..8e4559061 --- /dev/null +++ b/docs/ko/docs/tutorial/extra-models.md @@ -0,0 +1,223 @@ +# ėļ”ę°€ ëĒ¨ë¸ + +ė§€ë‚œ ė˜ˆė œė— ė´ė–´ė„œ, ė—°ę´€ëœ ëĒ¨ë¸ė„ ė—ŦëŸŦ氜 갖는 ę˛ƒė€ 흔한 ėŧėž…ë‹ˆë‹¤. + +특히 ė‚ŦėšŠėž ëĒ¨ë¸ė˜ ę˛Ŋėš°ė— ꡸ëŸŦ한데, ė™œëƒí•˜ëŠ´: + +* **ėž…ë Ĩ ëĒ¨ë¸** ė€ 비밀번호ëĨŧ 氀렏ė•ŧ 합니다. +* **ėļœë Ĩ ëĒ¨ë¸** ė€ 비밀번호ëĨŧ ę°€ė§€ëŠ´ ė•ˆëŠë‹ˆë‹¤. +* **ë°ė´í„°ë˛ ė´ėŠ¤ ëĒ¨ë¸** ė€ í•´ė‹œė˛˜ëĻŦ된 비밀번호ëĨŧ ę°€ė§ˆ ę˛ƒėž…ë‹ˆë‹¤. + +/// danger | ėœ„í—˜ + +ė ˆëŒ€ ė‚ŦėšŠėžė˜ 비밀번호ëĨŧ 평ëŦ¸ėœŧ로 ė €ėžĨí•˜ė§€ ë§ˆė„¸ėš”. í•­ėƒ ė´í›„ė— 검ėĻ 가ëŠĨ한 "ė•ˆė „í•œ í•´ė‹œ(secure hash)"로 ė €ėžĨí•˜ė„¸ėš”. + +만ė•Ŋ ė´ę˛Œ ëŦ´ė—‡ė¸ė§€ ëǍëĨ´ę˛ ë‹¤ëŠ´, [security chapters](security/simple-oauth2.md#password-hashing){.internal-link target=_blank}.ė—ė„œ 비밀번호 í•´ė‹œė— 대해 ë°°ėš¸ 눘 ėžˆėŠĩ니다. + +/// + +## ë‹¤ė¤‘ ëĒ¨ë¸ + +ė•„ëž˜ëŠ” 비밀번호 í•„ë“œė™€ 해당 필드가 ė‚ŦėšŠë˜ëŠ” ėœ„ėš˜ëĨŧ íŦ함하ė—Ŧ, 각 ëĒ¨ë¸ë“¤ė´ ė–´ë–¤ 형태ëĨŧ ę°€ė§ˆ 눘 ėžˆëŠ”ė§€ ė „ë°˜ė ė¸ ė˜ˆė‹œėž…ë‹ˆë‹¤: + +{* ../../docs_src/extra_models/tutorial001_py310.py hl[7,9,14,20,22,27:28,31:33,38:39] *} + + +/// info | ė •ëŗ´ + +Pydantic v1ė—ė„œëŠ” 해당 ëŠ”ė„œë“œę°€ `.dict()`로 ëļˆë ¸ėœŧ늰, Pydantic v2ė—ė„œëŠ” `.model_dump()`로 ė´ëĻ„ė´ ëŗ€ę˛Ŋë˜ė—ˆėŠĩ니다. `.dict()`는 ė—Ŧė „ížˆ ė§€ė›ë˜ė§€ë§Œ 더 ė´ėƒ ęļŒėžĨë˜ė§€ ė•ŠėŠĩ니다. + +ė—Ŧę¸°ė—ė„œ ė‚ŦėšŠí•˜ëŠ” ė˜ˆė œëŠ” Pydantic v1ęŗŧė˜ í˜¸í™˜ė„ąė„ ėœ„í•´ `.dict()`ëĨŧ ė‚ŦėšŠí•˜ė§€ë§Œ, Pydantic v2ëĨŧ ė‚ŦėšŠí•  눘 ėžˆë‹¤ëŠ´ `.model_dump()`ëĨŧ ė‚ŦėšŠí•˜ëŠ” ę˛ƒė´ ėĸ‹ėŠĩ니다. + +/// + +### `**user_in.dict()` 뗐 대하ė—Ŧ + +#### Pydanticė˜ `.dict()` + +`user_in`ė€ Pydantic ëĒ¨ë¸ í´ëž˜ėŠ¤ė¸ `UserIn`ėž…ë‹ˆë‹¤. + +Pydantic ëĒ¨ë¸ė€ ëĒ¨ë¸ ë°ė´í„°ëĨŧ íŦ함한 `dict`ëĨŧ 반환하는 `.dict()` ëŠ”ė„œë“œëĨŧ 렜ęŗĩ합니다. + +따ëŧė„œ, ë‹¤ėŒęŗŧ ę°™ė´ Pydantic ę°ė˛´ `user_in`ė„ ėƒė„ąí•  눘 ėžˆėŠĩ니다: + +```Python +user_in = UserIn(username="john", password="secret", email="john.doe@example.com") +``` + +꡸ ë‹¤ėŒ, ë‹¤ėŒęŗŧ ę°™ė´ 호ėļœí•Šë‹ˆë‹¤: + +```Python +user_dict = user_in.dict() +``` + +ė´ė œ ëŗ€ėˆ˜ `user_dict`뗐 ë°ė´í„°ę°€ íŦ함된 `dict`ëĨŧ ę°€ė§€ę˛Œ 됩니다(ė´ëŠ” Pydantic ëĒ¨ë¸ ę°ė˛´ę°€ ė•„ë‹Œ `dict`ėž…ë‹ˆë‹¤). + +꡸ëĻŦęŗ  ë‹¤ėŒęŗŧ ę°™ė´ 호ėļœí•˜ëŠ´: + +```Python +print(user_dict) +``` + +Pythonė˜ `dict`가 ë‹¤ėŒęŗŧ ę°™ė´ ėļœë Ĩ됩니다: + +```Python +{ + 'username': 'john', + 'password': 'secret', + 'email': 'john.doe@example.com', + 'full_name': None, +} +``` + +#### `dict` ė–¸íŒ¨í‚š(Unpacking) + +`user_dict`뙀 ę°™ė€ `dict`ëĨŧ í•¨ėˆ˜(또는 í´ëž˜ėŠ¤)뗐 `**user_dict`로 ė „ë‹Ŧ하면, Pythonė€ ė´ëĨŧ "ė–¸íŒŠ(unpack)"합니다. ė´ ęŗŧė •ė—ė„œ `user_dict`ė˜ í‚¤ė™€ ę°’ė„ 각각 키-값 ė¸ėžëĄœ 링렑 ė „ë‹Ŧ합니다. + +따ëŧė„œ, ėœ„ė—ė„œ ėƒė„ąí•œ `user_dict`ëĨŧ ė‚ŦėšŠí•˜ė—Ŧ ë‹¤ėŒęŗŧ ę°™ė´ ėž‘ė„ąí•˜ëŠ´: + +```Python +UserInDB(**user_dict) +``` + +ë‹¤ėŒęŗŧ ę°™ė€ 결ęŗŧëĨŧ ėƒė„ąí•Šë‹ˆë‹¤: + +```Python +UserInDB( + username="john", + password="secret", + email="john.doe@example.com", + full_name=None, +) +``` + +í˜šė€ 더 ė •í™•ížˆ ë§í•˜ėžëŠ´, `user_dict`ëĨŧ 링렑 ė‚ŦėšŠí•˜ëŠ” ę˛ƒė€, ë‚˜ė¤‘ė— ė–´ë–¤ ę°’ė´ ėļ”ę°€ë˜ë”ëŧ도 ė•„ëž˜ė™€ 동ėŧ한 효ęŗŧëĨŧ 냅니다: + +```Python +UserInDB( + username = user_dict["username"], + password = user_dict["password"], + email = user_dict["email"], + full_name = user_dict["full_name"], +) +``` + +#### 다ëĨ¸ ëĒ¨ë¸ ë°ė´í„°ëĄœ 냈 Pydantic ëĒ¨ë¸ ėƒė„ą + +ėœ„ė˜ ė˜ˆė œė—ė„œ `user_in.dict()`로ëļ€í„° `user_dict`ëĨŧ ėƒė„ąí•œ 枃래ëŸŧ, ė•„ëž˜ ėŊ”드는: + +```Python +user_dict = user_in.dict() +UserInDB(**user_dict) +``` + +ë‹¤ėŒęŗŧ 동ėŧ합니다: + +```Python +UserInDB(**user_in.dict()) +``` + +...ė™œëƒí•˜ëŠ´ `user_in.dict()`는 `dict`ė´ëŠ°, ė´ëĨŧ `**`로 Pythonė´ "ė–¸íŒŠ(unpack)"하도록 하ė—Ŧ `UserInDB`뗐 ė „ë‹Ŧ하기 때ëŦ¸ėž…니다. + +따ëŧė„œ, 다ëĨ¸ Pydantic ëĒ¨ë¸ė˜ ë°ė´í„°ëĨŧ ė‚ŦėšŠí•˜ė—Ŧ ėƒˆëĄœėš´ Pydantic ëĒ¨ë¸ė„ ėƒė„ąí•  눘 ėžˆėŠĩ니다. + +#### `dict` ė–¸íŒ¨í‚š(Unpacking)ęŗŧ ėļ”ę°€ í‚¤ė›Œë“œ + +꡸ëĻŦęŗ  ë‹¤ėŒęŗŧ ę°™ė´ ėļ”ę°€ í‚¤ė›Œë“œ ė¸ėž `hashed_password=hashed_password`ëĨŧ ėļ”ę°€í•˜ëŠ´: + +```Python +UserInDB(**user_in.dict(), hashed_password=hashed_password) +``` + +ë‹¤ėŒęŗŧ ę°™ė€ 결ęŗŧëĨŧ ėƒė„ąí•Šë‹ˆë‹¤: + +```Python +UserInDB( + username = user_dict["username"], + password = user_dict["password"], + email = user_dict["email"], + full_name = user_dict["full_name"], + hashed_password = hashed_password, +) +``` + +/// warning | ę˛Ŋęŗ  + +ėļ”氀렁ėœŧ로 렜ęŗĩ된 í•¨ėˆ˜ `fake_password_hasher`뙀 `fake_save_user`는 ë°ė´í„° 흐ëĻ„ė„ ė‹œė—°í•˜ę¸° ėœ„í•œ 똈렜ėŧ ëŋė´ëа, ė‹¤ė œ ëŗ´ė•ˆė„ 렜ęŗĩí•˜ė§€ ė•ŠėŠĩ니다. + +/// + +## 뤑ëŗĩ ė¤„ė´ę¸° + +ėŊ”드 뤑ëŗĩė„ ė¤„ė´ëŠ” ę˛ƒė€ **FastAPI**ė˜ í•ĩė‹Ŧ ė•„ė´ë””ė–´ 뤑 í•˜ë‚˜ėž…ë‹ˆë‹¤. + +ėŊ”드 뤑ëŗĩė€ 버그, ëŗ´ė•ˆ ëŦ¸ė œ, ėŊ”드 비동기화 ëŦ¸ė œ(한 ęŗŗė€ ė—…ë°ė´íŠ¸ë˜ė—ˆė§€ë§Œ 다ëĨ¸ ęŗŗė€ ė—…ë°ė´íŠ¸ë˜ė§€ ė•ŠëŠ” ëŦ¸ė œ) ë“ąė˜ 가ëŠĨė„ąė„ ėĻę°€ė‹œí‚ĩ니다. + +꡸ëĻŦęŗ  ė´ ëĒ¨ë¸ë“¤ė€ ë§Žė€ ë°ė´í„°ëĨŧ ęŗĩėœ í•˜ëŠ´ė„œ ė†ė„ą ė´ëĻ„ęŗŧ íƒ€ėž…ė„ 뤑ëŗĩí•˜ęŗ  ėžˆėŠĩ니다. + +더 ë‚˜ė€ ë°Šë˛•ė´ ėžˆėŠĩ니다. + +`UserBase` ëĒ¨ë¸ė„ ė„ ė–¸í•˜ė—Ŧ 다ëĨ¸ ëĒ¨ë¸ë“¤ė˜ ę¸°ëŗ¸(base)ėœŧ로 ė‚ŦėšŠí•  눘 ėžˆėŠĩ니다. 그런 ë‹¤ėŒ ė´ ëĒ¨ë¸ė„ ėƒė†ë°›ė•„ ė†ė„ąęŗŧ íƒ€ėž… ė„ ė–¸(ėœ í˜• ė„ ė–¸, 검ėĻ 등)ė„ ėƒė†í•˜ëŠ” ė„œë¸Œí´ëž˜ėŠ¤ëĨŧ 만들 눘 ėžˆėŠĩ니다. + +ëĒ¨ë“  ë°ė´í„° ëŗ€í™˜, 검ėĻ, ëŦ¸ė„œí™” ë“ąė€ ė •ėƒė ėœŧ로 ėž‘ë™í•  ę˛ƒėž…ë‹ˆë‹¤. + +ė´ë ‡ę˛Œ 하면 각 ëĒ¨ë¸ ę°„ė˜ ė°¨ė´ė ë§Œ ė„ ė–¸í•  눘 ėžˆėŠĩ니다(평ëŦ¸ `password`가 ėžˆëŠ” ę˛Ŋ뚰, `hashed_password`만 ėžˆëŠ” ę˛Ŋ뚰, í˜šė€ 비밀번호가 ė—†ëŠ” ę˛Ŋ뚰): + +{* ../../docs_src/extra_models/tutorial002_py310.py hl[7,13:14,17:18,21:22] *} + +## `Union` 또는 `anyOf` + +두 氀맀 ė´ėƒė˜ íƒ€ėž…ė„ íŦ함하는 `Union`ėœŧ로 ė‘ë‹ĩė„ ė„ ė–¸í•  눘 ėžˆėŠĩ니다. ė´ëŠ” ė‘ë‹ĩė´ ꡸ 뤑 í•˜ë‚˜ė˜ íƒ€ėž…ėŧ 눘 ėžˆėŒė„ ė˜ë¯¸í•Šë‹ˆë‹¤. + +OpenAPIė—ė„œëŠ” ė´ëĨŧ `anyOf`로 ė •ė˜í•Šë‹ˆë‹¤. + +ė´ëĨŧ ėœ„í•´ í‘œė¤€ Python íƒ€ėž… ížŒíŠ¸ė¸ `typing.Union`ė„ ė‚ŦėšŠí•  눘 ėžˆėŠĩ니다: + +/// note | 및溠 + +`Union`ė„ ė •ė˜í• ë•ŒëŠ” 더 ęĩŦė˛´ė ė¸ íƒ€ėž…ė„ ë¨ŧė € íŦí•¨í•˜ęŗ , 덜 ęĩŦė˛´ė ė¸ íƒ€ėž…ė„ ꡸ ë’¤ė— ë‚˜ė—´í•´ė•ŧ합니다. ė•„ëž˜ ė˜ˆė œė—ė„œëŠ” `Union[PlaneItem, CarItem]` ëĨŧ ëŗ´ëŠ´, 더 ęĩŦė˛´ė ė¸ `PlaneItem`ė´ `CarItem`ëŗ´ë‹¤ ė•žė— ėœ„ėš˜í•Šë‹ˆë‹¤. + +/// + +{* ../../docs_src/extra_models/tutorial003_py310.py hl[1,14:15,18:20,33] *} + + +### Python 3.10ė—ė„œ `Union` + +ėœ„ė˜ ė˜ˆė œė—ė„œëŠ” `response_model` ė¸ėž 값ėœŧ로 `Union[PlaneItem, CarItem]`ė„ ė „ë‹Ŧ합니다. + +ė´ ę˛Ŋ뚰, ė´ëĨŧ **íƒ€ėž… ė–´ë…¸í…Œė´ė…˜(type annotation)** ė´ ė•„ë‹Œ **ė¸ėž 값(argument value)** ėœŧ로 ė „ë‹Ŧí•˜ęŗ  ėžˆę¸° 때ëŦ¸ė— Python 3.10ė—ė„œë„ `Union`ė„ ė‚ŦėšŠí•´ė•ŧ 합니다. + +만ė•Ŋ íƒ€ėž… ė–´ë…¸í…Œė´ė…˜ė— ė‚ŦėšŠí•œë‹¤ëŠ´, ë‹¤ėŒęŗŧ ę°™ė´ 눘링 막대(|)ëĨŧ ė‚ŦėšŠí•  눘 ėžˆėŠĩ니다: + +```Python +some_variable: PlaneItem | CarItem +``` + +í•˜ė§€ë§Œ ė´ëĨŧ `response_model=PlaneItem | CarItem`ęŗŧ ę°™ė´ 할당하면 뗐ëŸŦ가 ë°œėƒí•Šë‹ˆë‹¤. ė´ëŠ” Pythonė´ ė´ëĨŧ íƒ€ėž… ė–´ë…¸í…Œė´ė…˜ėœŧ로 í•´ė„í•˜ė§€ ė•Šęŗ , `PlaneItem`ęŗŧ `CarItem` ė‚Ŧė´ė˜ **ėž˜ëĒģ된 ė—°ė‚°(invalid operation)**ė„ ė‹œë„í•˜ę¸° 때ëŦ¸ėž…니다 + +## ëĒ¨ë¸ ëĻŦėŠ¤íŠ¸ + +마ė°Ŧę°€ė§€ëĄœ, ę°ė˛´ ëĻŦėŠ¤íŠ¸ í˜•íƒœė˜ ė‘ë‹ĩė„ ė„ ė–¸í•  ėˆ˜ë„ ėžˆėŠĩ니다. + +ė´ëĨŧ ėœ„í•´ í‘œė¤€ Pythonė˜ `typing.List`ëĨŧ ė‚ŦėšŠí•˜ė„¸ėš”(또는 Python 3.9 ė´ėƒė—ė„œëŠ” ë‹¨ėˆœížˆ `list`ëĨŧ ė‚ŦėšŠí•  눘 ėžˆėŠĩ니다): + +{* ../../docs_src/extra_models/tutorial004_py39.py hl[18] *} + + +## ėž„ė˜ė˜ `dict` ė‘ë‹ĩ + +Pydantic ëĒ¨ë¸ė„ ė‚ŦėšŠí•˜ė§€ ė•Šęŗ , í‚¤ė™€ ę°’ė˜ íƒ€ėž…ë§Œ ė„ ė–¸í•˜ė—Ŧ 평범한 ėž„ė˜ė˜ `dict`로 ė‘ë‹ĩė„ ė„ ė–¸í•  ėˆ˜ë„ ėžˆėŠĩ니다. + +ė´ëŠ” Pydantic ëĒ¨ë¸ė— í•„ėš”í•œ ėœ íš¨í•œ 필드/ė†ė„ą ė´ëĻ„ė„ ė‚Ŧ렄뗐 ė•Œ 눘 ė—†ëŠ” ę˛Ŋėš°ė— ėœ ėšŠí•Šë‹ˆë‹¤. + +ė´ ę˛Ŋ뚰, `typing.Dict`ëĨŧ ė‚ŦėšŠí•  눘 ėžˆėŠĩ니다(또는 Python 3.9 ė´ėƒė—ė„œëŠ” ë‹¨ėˆœížˆ `dict`ëĨŧ ė‚ŦėšŠí•  눘 ėžˆėŠĩ니다): + +{* ../../docs_src/extra_models/tutorial005_py39.py hl[6] *} + + +## ėš”ė•Ŋ + +ė—ŦëŸŦ Pydantic ëĒ¨ë¸ė„ ė‚ŦėšŠí•˜ęŗ , 각 ę˛Ŋėš°ė— 맞게 ėžėœ ëĄ­ę˛Œ ėƒė†í•˜ė„¸ėš”. + +ė—”í„°í‹°ę°€ ė„œëĄœ 다ëĨ¸ "ėƒíƒœ"ëĨŧ 氀렏ė•ŧ 하는 ę˛Ŋ뚰, ė—”í„°í‹°ë‹š 단ėŧ ë°ė´í„° ëĒ¨ë¸ė„ ė‚ŦėšŠí•  í•„ėš”ëŠ” ė—†ėŠĩ니다. 똈ëĨŧ ë“¤ė–´, ė‚ŦėšŠėž "ė—”í„°í‹°"가 `password`, `password_hash`, 또는 비밀번호가 ė—†ëŠ” ėƒíƒœëĨŧ íŦ함할 눘 ėžˆëŠ” ę˛Ŋ뚰래ëŸŧ ë§ėž…ë‹ˆë‹¤. diff --git a/docs/ko/docs/tutorial/security/oauth2-jwt.md b/docs/ko/docs/tutorial/security/oauth2-jwt.md new file mode 100644 index 000000000..d8bac8346 --- /dev/null +++ b/docs/ko/docs/tutorial/security/oauth2-jwt.md @@ -0,0 +1,273 @@ +# íŒ¨ėŠ¤ė›Œë“œ í•´ė‹ąė„ ė´ėšŠí•œ OAuth2, JWT í† í°ė„ ė‚ŦėšŠí•˜ëŠ” Bearer ė¸ėĻ + +ëĒ¨ë“  ëŗ´ė•ˆ 흐ëĻ„ė„ ęĩŦė„ąí–ˆėœŧë¯€ëĄœ, ė´ė œ JWT 토큰ęŗŧ íŒ¨ėŠ¤ė›Œë“œ í•´ė‹ąė„ ė‚ŦėšŠí•´ ė• í”ŒëĻŦėŧ€ė´ė…˜ė„ ė•ˆė „í•˜ę˛Œ 만들 ę˛ƒėž…ë‹ˆë‹¤. + +ė´ ėŊ”드는 ė‹¤ė œëĄœ ė• í”ŒëĻŦėŧ€ė´ė…˜ė—ė„œ íŒ¨ėŠ¤ė›Œë“œëĨŧ í•´ė‹ąí•˜ė—Ŧ DB뗐 ė €ėžĨ하는 ë“ąė˜ ėž‘ė—…ė— í™œėšŠí•  눘 ėžˆėŠĩ니다. + +ė´ė „ ėžĨ뗐 ė´ė–´ė„œ ė‹œėž‘í•´ ë´…ė‹œë‹¤. + +## JWT + +JWT 는 "JSON Web Tokens" ė„ ė˜ë¯¸í•Šë‹ˆë‹¤. + +JSON ę°ė˛´ëĨŧ ęŗĩë°ąė´ ė—†ëŠ” 긴 ëŦ¸ėžė—´ëĄœ ė¸ėŊ”딊하는 í‘œė¤€ė´ëŠ°, ë‹¤ėŒęŗŧ ę°™ė€ í˜•íƒœėž…ë‹ˆë‹¤: + +``` +eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c +``` + +JWT는 ė•”í˜¸í™”ë˜ė§€ ė•Šė•„ 누ęĩŦë“ ė§€ í† í°ė—ė„œ ė •ëŗ´ëĨŧ ëŗĩė›í•  눘 ėžˆėŠĩ니다. + +í•˜ė§€ë§Œ JWT는 ė„œëĒ…ë˜ė–´ ėžˆėŠĩ니다. ęˇ¸ëž˜ė„œ ėžė‹ ė´ 발급한 í† í°ė„ ë°›ė•˜ė„ 때, ė‹¤ė œëĄœ ėžė‹ ė´ 발급한게 ë§žëŠ”ė§€ 검ėĻí•  눘 ėžˆėŠĩ니다. + +ë§ŒëŖŒ ę¸°ę°„ė´ ėŧėŖŧėŧė¸ í† í°ė„ ë°œí–‰í–ˆë‹¤ęŗ  ę°€ė •í•´ ë´…ė‹œë‹¤. ë‹¤ėŒ 날 ė‚ŦėšŠėžę°€ í† í°ė„ ę°€ė ¸ė™”ė„ 때, ꡸ ė‚ŦėšŠėžę°€ ė‹œėŠ¤í…œė— ė—Ŧė „ížˆ ëĄœęˇ¸ė¸ë˜ė–´ ėžˆë‹¤ëŠ” ę˛ƒė„ ė•Œ 눘 ėžˆėŠĩ니다. + +ėŧėŖŧėŧ ë’¤ė—ëŠ” í† í°ė´ ë§ŒëŖŒë  ę˛ƒė´ęŗ , ė‚ŦėšŠėžëŠ” ė¸ę°€ë˜ė§€ ė•Šė•„ 냈 í† í°ė„ 받기 ėœ„í•´ ë‹¤ė‹œ ëĄœęˇ¸ė¸í•´ė•ŧ 할 ę˛ƒėž…ë‹ˆë‹¤. 만ė•Ŋ ė‚ŦėšŠėž(또는 렜3ėž)가 í† í°ė„ ėˆ˜ė •í•˜ęą°ë‚˜ ë§ŒëŖŒėŧė„ ëŗ€ę˛Ŋ하면, ė„œëĒ…ė´ ėŧėš˜í•˜ė§€ ė•Šę¸° 때ëŦ¸ė— ė•Œė•„ėąŒ 눘 ėžˆė„ ę˛ƒėž…ë‹ˆë‹¤. + +만ė•Ŋ JWT í† í°ė„ ë‹¤ë¤„ëŗ´ęŗ , ėž‘ë™ ë°Šė‹ë„ ė•Œė•„ëŗ´ęŗ  ė‹ļ다면 https://jwt.io ė„ í™•ė¸í•˜ė‹­ė‹œė˜¤. + +## `PyJWT` ė„¤ėš˜ + +íŒŒė´ėŦėœŧ로 JWT í† í°ė„ ėƒė„ąí•˜ęŗ  검ėĻí•˜ë ¤ëŠ´ `PyJWT` ëĨŧ ė„¤ėš˜í•´ė•ŧ 합니다. + +[ę°€ėƒí™˜ę˛Ŋ](../../virtual-environments.md){.internal-link target=_blank} ė„ ë§Œë“¤ęŗ  í™œė„ąí™”í•œ ë‹¤ėŒ `pyjwt` ëĨŧ ė„¤ėš˜í•˜ė‹­ė‹œė˜¤: + +
+ +```console +$ pip install pyjwt + +---> 100% +``` + +
+ +/// info | 및溠 + +RSA나 ECDSA ę°™ė€ ė „ėž ė„œëĒ… ė•Œęŗ ëĻŦėĻ˜ė„ ė‚ŦėšŠí•˜ë ¤ëŠ´, `pyjwt[crypto]`ëŧ는 ė•”í˜¸í™” ëŧė´ë¸ŒëŸŦëĻŦ ė˜ėĄ´ė„ąė„ ė„¤ėš˜í•´ė•ŧ 합니다. + +더 ėžė„¸í•œ ë‚´ėšŠė€ PyJWT ė„¤ėš˜ ė—ė„œ í™•ė¸í•  눘 ėžˆėŠĩ니다. + +/// + +## íŒ¨ėŠ¤ė›Œë“œ í•´ė‹ą + +"í•´ė‹ą(Hashing)"ė€ ė–´ë–¤ ë‚´ėšŠ(ė—Ŧę¸°ė„œëŠ” íŒ¨ėŠ¤ė›Œë“œ)ė„ í•´ė„í•  눘 ė—†ëŠ” ėŧë ¨ė˜ ë°”ė´íŠ¸ ė§‘í•Š(ë‹¨ėˆœ ëŦ¸ėžė—´)ėœŧ로 ëŗ€í™˜í•˜ëŠ” ę˛ƒė„ ė˜ë¯¸í•Šë‹ˆë‹¤. + +동ėŧ한 ë‚´ėšŠ(ë˜‘ę°™ė€ íŒ¨ėŠ¤ė›Œë“œ)ė„ í•´ė‹ąí•˜ëŠ´ 동ėŧ한 ëŦ¸ėžė—´ė„ ė–ģėŠĩ니다. + +í•˜ė§€ë§Œ ꡸ ëŦ¸ėžė—´ė„ ë‹¤ė‹œ íŒ¨ėŠ¤ė›Œë“œëĄœ 되돌ëĻ´ ėˆ˜ëŠ” ė—†ėŠĩ니다. + +### íŒ¨ėŠ¤ė›Œë“œëĨŧ í•´ė‹ąí•˜ëŠ” ė´ėœ  + +ë°ė´í„°ë˛ ė´ėŠ¤ëĨŧ íƒˆėˇ¨ë‹ší•˜ë”ëŧ도, ėš¨ėž…ėžëŠ” ė‚ŦėšŠėžė˜ 평ëŦ¸ íŒ¨ėŠ¤ė›Œë“œ ëŒ€ė‹  í•´ė‹œ 값만 ė–ģė„ 눘 ėžˆėŠĩ니다. + +따ëŧė„œ ėš¨ėž…ėžëŠ” í›”ėšœ ė‚ŦėšŠėž íŒ¨ėŠ¤ė›Œë“œëĨŧ 다ëĨ¸ ė‹œėŠ¤í…œė—ė„œ í™œėšŠí•  눘 ė—†ėŠĩ니다. (ëŒ€ë‹¤ėˆ˜ ė‚ŦėšŠėžę°€ ė—ŦëŸŦ ė‹œėŠ¤í…œė—ė„œ 동ėŧ한 íŒ¨ėŠ¤ė›Œë“œëĨŧ ė‚ŦėšŠí•˜ę¸° 때ëŦ¸ė— 평ëŦ¸ íŒ¨ėŠ¤ė›Œë“œę°€ 뜠ėļœë˜ëŠ´ ėœ„í—˜í•Šë‹ˆë‹¤.) + +## `passlib` ė„¤ėš˜ + +PassLib는 íŒ¨ėŠ¤ė›Œë“œ í•´ė‹œëĨŧ ë‹¤ëŖ¨ëŠ” 훌ëĨ­í•œ íŒŒė´ėŦ íŒ¨í‚¤ė§€ėž…ë‹ˆë‹¤. + +ë§Žė€ ė•ˆė „í•œ í•´ė‹œ ė•Œęŗ ëĻŦėϘęŗŧ 도ęĩŦë“¤ė„ ė§€ė›í•Šë‹ˆë‹¤. + +ėļ”ė˛œí•˜ëŠ” ė•Œęŗ ëĻŦėĻ˜ė€ "Bcrypt"ėž…ë‹ˆë‹¤. + +[ę°€ėƒí™˜ę˛Ŋ](../../virtual-environments.md){.internal-link target=_blank} ė„ ë§Œë“¤ęŗ  í™œė„ąí™”í•œ ë‹¤ėŒ PassLib뙀 BcryptëĨŧ ė„¤ėš˜í•˜ė‹­ė‹œė˜¤: + +
+ +```console +$ pip install "passlib[bcrypt]" + +---> 100% +``` + +
+ +/// tip | 팁 + +`passlib`ëĨŧ ė‚ŦėšŠí•˜ė—Ŧ, **Django**, **Flask** ė˜ ëŗ´ė•ˆ 플ëŸŦęˇ¸ė¸ė´ë‚˜ 다ëĨ¸ 도ęĩŦ로 ėƒė„ąí•œ íŒ¨ėŠ¤ė›Œë“œëĨŧ ėŊė„ 눘 ėžˆë„ëĄ ė„¤ė •í•  ėˆ˜ë„ ėžˆėŠĩ니다. + +똈ëĨŧ ë“¤ėžëŠ´, FastAPI ė• í”ŒëĻŦėŧ€ė´ė…˜ęŗŧ Django ė• í”ŒëĻŦėŧ€ė´ė…˜ė´ ę°™ė€ ë°ė´í„°ë˛ ė´ėŠ¤ė—ė„œ ë°ė´í„°ëĨŧ ęŗĩėœ í•  눘 ėžˆėŠĩ니다. 또는 ę°™ė€ ë°ė´í„°ë˛ ė´ėŠ¤ëĨŧ ė‚ŦėšŠí•˜ė—Ŧ Django ė• í”ŒëĻŦėŧ€ė´ė…˜ė„ 렐맄렁ėœŧ로 ë§ˆė´ęˇ¸ë ˆė´ė…˜ 할 ėˆ˜ë„ ėžˆėŠĩ니다. + +꡸ëĻŦęŗ  ė‚ŦėšŠėžëŠ” FastAPI ė• í”ŒëĻŦėŧ€ė´ė…˜ęŗŧ Django ė• í”ŒëĻŦėŧ€ė´ė…˜ė— ë™ė‹œė— ëĄœęˇ¸ė¸í•  눘 ėžˆėŠĩ니다. + +/// + +## íŒ¨ėŠ¤ė›Œë“œė˜ í•´ė‹œė™€ 검ėĻ + +í•„ėš”í•œ 도ęĩŦëĨŧ `passlib`ė—ė„œ ėž„íŦ트합니다. + +PassLib "ėģ¨í…ėŠ¤íŠ¸(context)"ëĨŧ ėƒė„ąí•Šë‹ˆë‹¤. ė´ę˛ƒė€ íŒ¨ėŠ¤ė›Œë“œëĨŧ í•´ė‹ąí•˜ęŗ  검ėĻí•˜ëŠ”ë° ė‚ŦėšŠí•Šë‹ˆë‹¤. + +/// tip | 팁 + +PassLib ėģ¨í…ėŠ¤íŠ¸ëŠ” ë‹¤ė–‘í•œ í•´ė‹ą ė•Œęŗ ëĻŦėĻ˜ė„ ė‚ŦėšŠí•  눘 ėžˆëŠ” 기ëŠĨė„ 렜ęŗĩ하며, 더 ė´ėƒ ė‚ŦėšŠė´ ęļŒėžĨë˜ė§€ ė•ŠëŠ” ė˜¤ëž˜ëœ í•´ė‹ą ė•Œęŗ ëĻŦėĻ˜ė„ 검ėĻí•˜ëŠ” 기ëŠĨ도 íŦí•¨ë˜ė–´ ėžˆėŠĩ니다. + +똈ëĨŧ ë“¤ė–´, 다ëĨ¸ ė‹œėŠ¤í…œ(Django ę°™ė€)ė—ė„œ ėƒė„ąí•œ íŒ¨ėŠ¤ė›Œë“œëĨŧ ėŊęŗ  검ėĻí•  눘 ėžˆėœŧ늰, ėƒˆëĄœėš´ íŒ¨ėŠ¤ė›Œë“œëĨŧ Bcrypt ę°™ė€ 다ëĨ¸ ė•Œęŗ ëĻŦėϘėœŧ로 í•´ė‹ąí•  ėˆ˜ë„ ėžˆėŠĩ니다. + +꡸ëĻŦęŗ  ë™ė‹œė— 그런 ëĒ¨ë“  ė•Œęŗ ëĻŦėϘęŗŧ í˜¸í™˜ė„ąė„ ėœ ė§€í•Šë‹ˆë‹¤. + +/// + +ė‚ŦėšŠėžëĄœëļ€í„° ë°›ė€ íŒ¨ėŠ¤ė›Œë“œëĨŧ í•´ė‹ąí•˜ëŠ” ėœ í‹¸ëĻŦ티 í•¨ėˆ˜ëĨŧ ėƒė„ąí•Šë‹ˆë‹¤. + +꡸ëĻŦęŗ  ë°›ė€ íŒ¨ėŠ¤ė›Œë“œę°€ ė €ėžĨ된 í•´ė‹œė™€ ėŧėš˜í•˜ëŠ”ė§€ 검ėĻí•˜ëŠ” 또 다ëĨ¸ ėœ í‹¸ëĻŦ티 í•¨ėˆ˜ë„ ėƒė„ąí•Šë‹ˆë‹¤. + +꡸ëĻŦęŗ  ė‚ŦėšŠėžëĨŧ ė¸ėĻí•˜ęŗ  반환하는 또 다ëĨ¸ í•¨ėˆ˜ë„ ėƒė„ąí•Šë‹ˆë‹¤. + +{* ../../docs_src/security/tutorial004_an_py310.py hl[8,49,56:57,60:61,70:76] *} + +/// note + +ėƒˆëĄœėš´ (ę°€ė§œ) ë°ė´í„°ë˛ ė´ėŠ¤ `fake_users_db`ëĨŧ í™•ė¸í•˜ëŠ´, í•´ė‹œ 래ëĻŦ된 íŒ¨ėŠ¤ė›Œë“œę°€ ė–´ë–ģ枌 ėƒę˛ŧëŠ”ė§€ ëŗŧ 눘 ėžˆėŠĩ니다: `"$2b$12$EixZaYVK1fsbw1ZfbX3OXePaWxn96p36WQoeG6Lruj3vjPGga31lW"`. + +/// + +## JWT 토큰 래ëĻŦ + +ė„¤ėš˜ëœ ëĒ¨ë“ˆė„ ėž„íŦ트 합니다. + +JWT 토큰 ė„œëDž뗐 ė‚ŦėšŠë  ėž„ė˜ė˜ 비밀키ëĨŧ ėƒė„ąí•Šë‹ˆë‹¤. + +ė•ˆė „í•œ ėž„ė˜ė˜ 비밀키ëĨŧ ėƒė„ąí•˜ë ¤ëŠ´ ë‹¤ėŒ ëĒ…ë šė–´ëĨŧ ė‚ŦėšŠí•˜ė‹­ė‹œė˜¤: + +
+ +```console +$ openssl rand -hex 32 + +09d25e094faa6ca2556c818166b7a9563b93f7099f6f0f4caa6cf63b88e8d3e7 +``` + +
+ +꡸ëĻŦęŗ  ėƒė„ąí•œ 비밀키ëĨŧ ëŗĩė‚Ŧ해 ëŗ€ėˆ˜ `SECRET_KEY`뗐 ëŒ€ėž…í•Šë‹ˆë‹¤. (ė´ ė˜ˆė œė˜ ëŗ€ėˆ˜ ę°’ė„ 그대로 ė‚ŦėšŠí•˜ė§€ ë§ˆė‹­ė‹œė˜¤.) + +JWT í† í°ė„ ė„œëĒ…í•˜ëŠ” 데 ė‚ŦėšŠë  ė•Œęŗ ëĻŦėĻ˜ė„ ėœ„í•œ ëŗ€ėˆ˜ `ALGORITHM` ė„ ėƒė„ąí•˜ęŗ  `"HS256"` ėœŧ로 ė„¤ė •í•Šë‹ˆë‹¤. + +토큰 ë§ŒëŖŒ ę¸°ę°„ė„ ėœ„í•œ ëŗ€ėˆ˜ëĨŧ ėƒė„ąí•Šë‹ˆë‹¤. + +ė‘ë‹ĩė„ ėœ„í•œ 토큰 ė—”ë“œíŦė¸íŠ¸ė— ė‚ŦėšŠë  Pydantic ëĒ¨ë¸ė„ ė •ė˜í•Šë‹ˆë‹¤. + +냈 ė•Ąė„¸ėŠ¤ í† í°ė„ ėƒė„ąí•˜ę¸° ėœ„í•œ ėœ í‹¸ëĻŦ티 í•¨ėˆ˜ëĨŧ ėƒė„ąí•Šë‹ˆë‹¤. + +{* ../../docs_src/security/tutorial004_an_py310.py hl[4,7,13:15,29:31,79:87] *} + +## ė˜ėĄ´ė„ą ėˆ˜ė • + +`get_current_user` í•¨ėˆ˜ëĨŧ ė´ė „ęŗŧ 동ėŧ한 í† í°ė„ 받도록 ėˆ˜ė •í•˜ë˜, ė´ë˛ˆė—ëŠ” JWT í† í°ė„ ė‚ŦėšŠí•˜ë„ëĄ 합니다. + +ë°›ė€ í† í°ė„ 디ėŊ”딊하ė—Ŧ 검ėĻí•œ 후 현ėžŦ ė‚ŦėšŠėžëĨŧ 반환합니다. + +í† í°ė´ ėœ íš¨í•˜ė§€ ė•Šë‹¤ëŠ´ HTTP 똤ëĨ˜ëĨŧ 반환합니다. + +{* ../../docs_src/security/tutorial004_an_py310.py hl[90:107] *} + +## `/token` ę˛Ŋ로 ėž‘ė—… ėˆ˜ė • + +í† í°ė˜ ë§ŒëŖŒ ė‹œę°ė„ ė„¤ė •í•˜ę¸° ėœ„í•´ `timedelta` ëĨŧ ėƒė„ąí•Šë‹ˆë‹¤. + +ė‹¤ė œ JWT ė•Ąė„¸ėŠ¤ í† í°ė„ ėƒė„ąí•˜ė—Ŧ 반환합니다. + +{* ../../docs_src/security/tutorial004_an_py310.py hl[118:133] *} + +### JWT "ėŖŧ랴(subject)" `sub`뗐 대한 揰눠 넏ëļ€ ė‚Ŧ항 + +JWT ëDž넏뗐 따ëĨ´ëŠ´ í† í°ė˜ ėŖŧ랴ëĨŧ íŦ함하는 `sub`ëŧ는 키가 ėžˆėŠĩ니다. + +ė‚ŦėšŠ ė—Ŧëļ€ëŠ” ė„ íƒė‚Ŧí•­ė´ė§€ë§Œ, ė‚ŦėšŠėžė˜ ė‹ëŗ„ ė •ëŗ´ëĨŧ ė €ėžĨ할 눘 ėžˆėœŧë¯€ëĄœ ė—Ŧę¸°ė„œëŠ” ė´ëĨŧ ė‚ŦėšŠí•Šë‹ˆë‹¤. + +JWT는 ė‚ŦėšŠėžëĨŧ ė‹ëŗ„í•˜ęŗ  ė‚ŦėšŠėžę°€ APIëĨŧ 링렑 ė‚ŦėšŠí•  눘 ėžˆë„ëĄ í—ˆėšŠí•˜ëŠ” 것 ė™¸ė—ë„ 다ëĨ¸ ėšŠë„ëĄœ ė‚ŦėšŠë  ėˆ˜ë„ ėžˆėŠĩ니다. + +똈ëĨŧ ë“¤ė–´ "ėžë™ė°¨"나 "블로그 ę˛Œė‹œëŦŧ"ė„ ė‹ëŗ„í•˜ëŠ” 데 ė‚ŦėšŠí•  눘 ėžˆėŠĩ니다. + +꡸ëĻŦęŗ  "ėžë™ė°¨ëĨŧ ėš´ė „í•˜ë‹¤"나 "블로그 ę˛Œė‹œëŦŧė„ ėˆ˜ė •í•˜ë‹¤"래ëŸŧ 해당 ė—”í„°í‹°ė— 대한 ęļŒí•œė„ ėļ”가할 눘 ėžˆėŠĩ니다. + +꡸ 후 ė´ JWT í† í°ė„ ė‚ŦėšŠėž(또는 봇)ė—ę˛Œ 렜ęŗĩ하면, ęˇ¸ë“¤ė€ ęŗ„ė •ė„ 따로 만들 í•„ėš” ė—†ė´ API가 ėƒė„ąí•œ JWT 토큰만ėœŧ로 ėž‘ė—…(ėžë™ė°¨ ėš´ė „ 또는 블로그 ę˛Œė‹œëŦŧ íŽ¸ė§‘)ė„ ėˆ˜í–‰í•  눘 ėžˆėŠĩ니다. + +ė´ëŸŦ한 ę°œë…ė„ í™œėšŠí•˜ëŠ´ JWT는 훨ė”Ŧ 더 ëŗĩėžĄí•œ ė‹œë‚˜ëĻŦė˜¤ė—ë„ ė‚ŦėšŠí•  눘 ėžˆėŠĩ니다. + +ė´ ę˛Ŋ뚰 ė—ŦëŸŦ ė—”í„°í‹°ę°€ 동ėŧ한 IDëĨŧ ę°€ė§ˆ 눘 ėžˆėŠĩ니다. 똈ëĨŧ ë“¤ė–´ fooëŧ는 IDëĨŧ 氀맄 ė‚ŦėšŠėž, ėžë™ė°¨, 블로그 ę˛Œė‹œëŦŧė´ ėžˆė„ 눘 ėžˆėŠĩ니다. + +ęˇ¸ëž˜ė„œ ID ėļŠëŒė„ ë°Šė§€í•˜ę¸° ėœ„í•´, ė‚ŦėšŠėžė˜ JWT í† í°ė„ ėƒė„ąí•  때 ė ‘ë‘ė‚Ŧ로 `sub` 키ëĨŧ ėļ”가할 눘 ėžˆėŠĩ니다. 똈ëĨŧ ë“¤ė–´ `username:` ė„ ëļ™ė´ëŠ” ë°Šė‹ėž…ë‹ˆë‹¤. ė´ ė˜ˆė œė—ė„œëŠ” `sub` ę°’ė´ `username:johndoe`ė´ 될 눘 ėžˆėŠĩ니다. + +가ėžĨ ė¤‘ėš”í•œ ė ė€ `sub` 키는 렄랴 ė• í”ŒëĻŦėŧ€ė´ė…˜ė—ė„œ ęŗ ėœ í•œ ė‹ëŗ„ėžę°€ ë˜ė–´ė•ŧ 하며 ëŦ¸ėžė—´ė´ė–´ė•ŧ 한다는 ė ėž…ë‹ˆë‹¤. + +## í™•ė¸í•´ë´…ė‹œë‹¤ + +ė„œë˛„ëĨŧ ė‹¤í–‰í•˜ęŗ  ëŦ¸ė„œëĄœ ė´ë™í•˜ė‹­ė‹œė˜¤: http://127.0.0.1:8000/docs. + +ë‹¤ėŒęŗŧ ę°™ė€ ė‚ŦėšŠėž ė¸í„°íŽ˜ė´ėŠ¤ëĨŧ ëŗŧ 눘 ėžˆėŠĩ니다: + + + +ė´ė „ęŗŧ ę°™ė€ 방법ėœŧ로 ė• í”ŒëĻŦėŧ€ė´ė…˜ė— ė¸ėĻí•˜ė‹­ė‹œė˜¤. + +ë‹¤ėŒ ė¸ėĻ ė •ëŗ´ëĨŧ ė‚ŦėšŠí•˜ė‹­ė‹œė˜¤: + +Username: `johndoe` +Password: `secret` + +/// check + +ėŊ”드 ė–´ë””ė—ë„ 평ëŦ¸ íŒ¨ėŠ¤ė›Œë“œ "`secret`" ė´ ė—†ë‹¤ëŠ” 렐뗐 ėœ ė˜í•˜ė‹­ė‹œė˜¤. í•´ė‹œëœ ë˛„ė „ë§Œ ėžˆėŠĩ니다. + +/// + + + +`/users/me/` ëĨŧ 호ėļœí•˜ëŠ´ ë‹¤ėŒęŗŧ ę°™ė€ ė‘ë‹ĩė„ ė–ģė„ 눘 ėžˆėŠĩ니다: + +```JSON +{ + "username": "johndoe", + "email": "johndoe@example.com", + "full_name": "John Doe", + "disabled": false +} +``` + + + +ę°œë°œėž 도ęĩŦëĨŧ ė—´ė–´ëŗ´ëŠ´ ė „ė†Ąëœ ë°ė´í„°ė— 토큰만 íŦ함된 ę˛ƒė„ í™•ė¸í•  눘 ėžˆėŠĩ니다. íŒ¨ėŠ¤ė›Œë“œëŠ” ė‚ŦėšŠėžëĨŧ ė¸ėĻí•˜ęŗ  ė•Ąė„¸ėŠ¤ í† í°ė„ 받기 ėœ„í•œ ė˛Ģ ë˛ˆė§¸ ėš”ė˛­ė—ë§Œ ė „ė†Ąë˜ëŠ°, ė´í›„ė—ëŠ” ė „ė†Ąë˜ė§€ ė•ŠėŠĩ니다: + + + +/// note + +`Bearer `로 ė‹œėž‘í•˜ëŠ” `Authorization` í—¤ë”ė— ėŖŧëĒŠí•˜ė‹­ė‹œė˜¤. + +/// + +## `scopes` ė˜ 溠揉 ė‚ŦėšŠë˛• + +OAuth2는 "늤ėŊ”프(scopes)" ëŧ는 ę°œë…ė„ ę°–ęŗ  ėžˆėŠĩ니다. + +ė´ëĨŧ ė‚ŦėšŠí•˜ė—Ŧ JWT í† í°ė— íŠšė • ęļŒí•œ ė§‘í•Šė„ ėļ”가할 눘 ėžˆėŠĩ니다. + +꡸ 후 ė´ í† í°ė„ ė‚ŦėšŠėžė—ę˛Œ 링렑 렜ęŗĩ하거나 렜3ėžė—ę˛Œ 렜ęŗĩ하ė—Ŧ, íŠšė • ė œí•œė‚Ŧ항 í•˜ė—ėžˆëŠ” API뙀 í†ĩė‹ í•˜ë„ëĄ 할 눘 ėžˆėŠĩ니다. + +**FastAPI** ė—ė„œė˜ ė‚ŦėšŠ 방법ęŗŧ í†ĩ합 ë°Šė‹ė€ **ė‹Ŧ화 ė‚ŦėšŠėž ė•ˆë‚´ė„œ** ė—ė„œ ėžė„¸ížˆ ë°°ėš¸ 눘 ėžˆėŠĩ니다. + +## ėš”ė•Ŋ + +ė§€ę¸ˆęšŒė§€ ė‚´íŽ´ëŗ¸ ë‚´ėšŠė„ 바탕ėœŧ로, OAuth2뙀 JWT ę°™ė€ í‘œė¤€ė„ ė‚ŦėšŠí•˜ė—Ŧ ė•ˆė „í•œ **FastAPI** ė• í”ŒëĻŦėŧ€ė´ė…˜ė„ 만들 눘 ėžˆėŠĩ니다. + +ęą°ė˜ ëĒ¨ë“  í”„ë ˆėž„ė›ŒíŦė—ė„œ ëŗ´ė•ˆ 래ëĻŦ는 ėƒë‹šížˆ ëŗĩėžĄí•œ ėŖŧė œėž…ë‹ˆë‹¤. + +ė´ëĨŧ ë‹¨ėˆœí™”í•˜ëŠ” ë§Žė€ íŒ¨í‚¤ė§€ëŠ” ë°ė´í„° ëĒ¨ë¸, ë°ė´í„°ë˛ ė´ėŠ¤, ė‚ŦėšŠ 가ëŠĨ한 기ëŠĨë“¤ė— 대해 ė—ŦëŸŦ 렜ė•Ŋė´ ėžˆėŠĩ니다. ꡸ëĻŦęŗ  ė§€ë‚˜ėš˜ę˛Œ ë‹¨ėˆœí™”í•˜ëŠ” ėŧëļ€ íŒ¨í‚¤ė§€ë“¤ė€ ė‹Ŧ각한 ëŗ´ė•ˆ ę˛°í•¨ė„ ę°€ė§ˆ ėˆ˜ë„ ėžˆėŠĩ니다. + +--- + +**FastAPI** 는 ė–´ë–¤ ë°ė´í„°ë˛ ė´ėŠ¤, ë°ė´í„° ëĒ¨ë¸, 도ęĩŦ도 ę°•ėš”í•˜ė§€ ė•ŠėŠĩ니다. + +í”„ëĄœė íŠ¸ė— 가ėžĨ ė í•Ší•œ ę˛ƒė„ ė„ íƒí•  눘 ėžˆëŠ” ėœ ė—°ė„ąė„ 렜ęŗĩ합니다. + +꡸ëĻŦęŗ  `passlib` 뙀 `PyJWT` 래ëŸŧ ėž˜ 관ëĻŦë˜ęŗ  널ëĻŦ ė‚ŦėšŠë˜ëŠ” íŒ¨í‚¤ė§€ë“¤ė„ 바로 ė‚ŦėšŠí•  눘 ėžˆėŠĩ니다. **FastAPI** 는 뙏ëļ€ íŒ¨í‚¤ė§€ í†ĩí•Šė„ ėœ„í•´ ëŗĩėžĄí•œ 메ėģ¤ë‹ˆėĻ˜ė´ í•„ėš”í•˜ė§€ ė•Šę¸° 때ëŦ¸ėž…니다. + +꡸ëŸŦ나 ėœ ė—°ė„ą, ę˛Ŧęŗ ė„ą, ëŗ´ė•ˆė„ąė„ í•´ėš˜ė§€ ė•ŠėœŧëŠ´ė„œ ęŗŧė •ė„ ë‹¨ėˆœí™”í•  눘 ėžˆëŠ” 도ęĩŦë“¤ė„ 렜ęŗĩ합니다. + +꡸ëĻŦęŗ  OAuth2뙀 ę°™ė€ í‘œė¤€ 프로토ėŊœė„ 비ęĩė  간단한 방법ėœŧ로 ęĩŦí˜„í•˜ęŗ  ė‚ŦėšŠí•  눘 ėžˆėŠĩ니다. + +더 넏ëļ„화된 ęļŒí•œ 랴溄ëĨŧ ėœ„í•´ OAuth2ė˜ "늤ėŊ”프"ëĨŧ ė‚ŦėšŠí•˜ëŠ” ë°Šë˛•ė€ **ė‹Ŧ화 ė‚ŦėšŠėž ė•ˆë‚´ė„œ**ė—ė„œ 더 ėžė„¸ížˆ ë°°ėš¸ 눘 ėžˆėŠĩ니다. OAuth2ė˜ 늤ėŊ”프는 렜3ėž ė• í”ŒëĻŦėŧ€ė´ė…˜ė´ ė‚ŦėšŠėžëĨŧ ëŒ€ė‹ í•´ ęˇ¸ë“¤ė˜ API뙀 ėƒí˜¸ėž‘ėšŠí•˜ë„ëĄ ęļŒí•œė„ ëļ€ė—Ŧ하기 ėœ„í•´, Facebook, Google, GitHub, Microsoft, Twitter ë“ąė˜ ë§Žė€ 대형 ė¸ėĻ 렜ęŗĩė—…ė˛´ë“¤ė´ ė‚ŦėšŠí•˜ëŠ” 메ėģ¤ë‹ˆėĻ˜ėž…ë‹ˆë‹¤. diff --git a/docs/ko/docs/tutorial/security/simple-oauth2.md b/docs/ko/docs/tutorial/security/simple-oauth2.md index ddc7430af..f10c4f588 100644 --- a/docs/ko/docs/tutorial/security/simple-oauth2.md +++ b/docs/ko/docs/tutorial/security/simple-oauth2.md @@ -32,7 +32,7 @@ OAuth2는 (뚰ëĻŦ가 ė‚ŦėšŠí•˜ęŗ  ėžˆëŠ”) "íŒ¨ėŠ¤ė›Œë“œ í”ŒëĄœėš°"ė„ ė‚ŦėšŠí•  * `instagram_basic`ė€ íŽ˜ė´ėŠ¤ëļ/ė¸ėŠ¤íƒ€ęˇ¸ëž¨ė—ė„œ ė‚ŦėšŠí•Šë‹ˆë‹¤. * `https://www.googleapis.com/auth/drive`는 Googleė—ė„œ ė‚ŦėšŠí•Šë‹ˆë‹¤. -/// ė •ëŗ´ +/// info | ė •ëŗ´ OAuth2ė—ė„œ "ë˛”ėœ„"는 í•„ėš”í•œ íŠšė • ęļŒí•œė„ ė„ ė–¸í•˜ëŠ” ëŦ¸ėžė—´ėž…니다. @@ -61,7 +61,7 @@ OAuth2ė˜ ę˛Ŋ뚰 ëŦ¸ėžė—´ėŧ ëŋėž…니다. * `scope`는 ė„ íƒė ė¸ 필드로 ęŗĩë°ąėœŧ로 ęĩŦëļ„된 ëŦ¸ėžė—´ëĄœ ęĩŦė„ąëœ 큰 ëŦ¸ėžė—´ėž…니다. * `grant_type`(ė„ íƒė ėœŧ로 ė‚ŦėšŠ). -/// 팁 +/// tip | 팁 OAuth2 ė‚Ŧė–‘ė€ ė‹¤ė œëĄœ `password`ëŧ는 ęŗ ė • ę°’ė´ ėžˆëŠ” `grant_type` 필드ëĨŧ *ėš”ęĩŦ*í•˜ė§€ë§Œ `OAuth2PasswordRequestForm`ė€ ė´ëĨŧ ę°•ėš”í•˜ė§€ ė•ŠėŠĩ니다. @@ -72,7 +72,7 @@ OAuth2 ė‚Ŧė–‘ė€ ė‹¤ė œëĄœ `password`ëŧ는 ęŗ ė • ę°’ė´ ėžˆëŠ” `grant_type` * `client_id`(ė„ íƒė ėœŧ로 ė‚ŦėšŠ) (ė˜ˆė œė—ė„œëŠ” í•„ėš”í•˜ė§€ ė•ŠėŠĩ니다). * `client_secret`(ė„ íƒė ėœŧ로 ė‚ŦėšŠ) (ė˜ˆė œė—ė„œëŠ” í•„ėš”í•˜ė§€ ė•ŠėŠĩ니다). -/// ė •ëŗ´ +/// info | ė •ëŗ´ `OAuth2PasswordRequestForm`ė€ `OAuth2PasswordBearer`뙀 ę°™ė´ **FastAPI**뗐 대한 íŠšėˆ˜ í´ëž˜ėŠ¤ę°€ ė•„ë‹™ë‹ˆë‹¤. @@ -86,7 +86,7 @@ OAuth2 ė‚Ŧė–‘ė€ ė‹¤ė œëĄœ `password`ëŧ는 ęŗ ė • ę°’ė´ ėžˆëŠ” `grant_type` ### íŧ ë°ė´í„° ė‚ŦėšŠí•˜ę¸° -/// 팁 +/// tip | 팁 ėĸ…ė†ė„ą í´ëž˜ėŠ¤ `OAuth2PasswordRequestForm`ė˜ ė¸ėŠ¤í„´ėŠ¤ė—ëŠ” ęŗĩë°ąėœŧ로 ęĩŦëļ„된 긴 ëŦ¸ėžė—´ė´ ėžˆëŠ” `scope` ė†ė„ąė´ 뗆溠 ëŒ€ė‹  ė „ė†Ąëœ 각 ë˛”ėœ„ė— 대한 ė‹¤ė œ ëŦ¸ėžė—´ ëĒŠëĄė´ ėžˆëŠ” `scopes` ė†ė„ąė´ ėžˆėŠĩ니다. @@ -126,7 +126,7 @@ OAuth2 ė‚Ŧė–‘ė€ ė‹¤ė œëĄœ `password`ëŧ는 ęŗ ė • ę°’ė´ ėžˆëŠ” `grant_type` 따ëŧė„œ 해ėģ¤ëŠ” 다ëĨ¸ ė‹œėŠ¤í…œė—ė„œ 동ėŧ한 ė•”í˜¸ëĨŧ ė‚ŦėšŠí•˜ë ¤ęŗ  ė‹œë„í•  눘 ė—†ėŠĩ니다(ë§Žė€ ė‚ŦėšŠėžę°€ ëĒ¨ë“  ęŗŗė—ė„œ 동ėŧ한 ė•”í˜¸ëĨŧ ė‚ŦėšŠí•˜ë¯€ëĄœ ė´ëŠ” ėœ„í—˜í•  눘 ėžˆėŠĩ니다). -//// tab | PíŒŒė´ėŦ 3.7 ė´ėƒ +//// tab | íŒŒė´ėŦ 3.7 ė´ėƒ {* ../../docs_src/security/tutorial003.py hl[80:83] *} @@ -150,7 +150,7 @@ UserInDB( ) ``` -/// ė •ëŗ´ +/// info | ė •ëŗ´ `**user_dict`뗐 대한 ėžė„¸í•œ 네ëĒ…ė€ [**ėļ”ę°€ ëĒ¨ë¸** ëŦ¸ė„œ](../extra-models.md#about-user_indict){.internal-link target=_blank}ëĨŧ ë‹¤ė‹œ ėŊė–´ë´…ė‹œë‹¤. @@ -166,7 +166,7 @@ UserInDB( ė´ 간단한 ė˜ˆė œė—ė„œëŠ” ė™„ė „ížˆ ė•ˆė „í•˜ė§€ ė•Šęŗ , 동ėŧ한 `username`ė„ 토큰ėœŧ로 반환합니다. -/// 팁 +/// tip | 팁 ë‹¤ėŒ ėžĨė—ė„œëŠ” íŒ¨ėŠ¤ė›Œë“œ í•´ė‹ą 및 JWT í† í°ė„ ė‚ŦėšŠí•˜ė—Ŧ ė‹¤ė œ ëŗ´ė•ˆ ęĩŦí˜„ė„ ëŗŧ 눘 ėžˆėŠĩ니다. @@ -176,7 +176,7 @@ UserInDB( {* ../../docs_src/security/tutorial003.py hl[85] *} -/// 팁 +/// tip | 팁 ė‚Ŧ떑뗐 따ëŧ ė´ ė˜ˆė œė™€ 동ėŧ하게 `access_token` 및 `token_type`ė´ íŦ함된 JSONė„ 반환해ė•ŧ 합니다. @@ -202,7 +202,7 @@ UserInDB( {* ../../docs_src/security/tutorial003.py hl[58:66,69:72,90] *} -/// ė •ëŗ´ +/// info | ė •ëŗ´ ė—Ŧę¸°ė„œ 반환하는 ę°’ė´ `Bearer`ė¸ ėļ”ę°€ 헤더 `WWW-Authenticate`도 ė‚Ŧė–‘ė˜ ėŧëļ€ėž…니다. diff --git a/docs/ko/docs/virtual-environments.md b/docs/ko/docs/virtual-environments.md new file mode 100644 index 000000000..0d10c3200 --- /dev/null +++ b/docs/ko/docs/virtual-environments.md @@ -0,0 +1,846 @@ +# ę°€ėƒ 환ę˛Ŋ + +Python í”„ëĄœė íŠ¸ëĨŧ ėž‘ė—…í•  때는 **ę°€ėƒ 환ę˛Ŋ** (또는 ė´ė™€ 뜠ė‚Ŧ한 도ęĩŦ)ė„ ė‚ŦėšŠí•˜ëŠ” ę˛ƒė´ ėĸ‹ėŠĩ니다. 각 í”„ëĄœė íŠ¸ 마다 ė„¤ėš˜í•˜ëŠ” íŒ¨í‚¤ė§€ëĨŧ ëļ„ëĻŦ하ė—Ŧ 관ëĻŦ할 눘 ėžˆėŠĩ니다. + +/// info | ė •ëŗ´ + +ė´ë¯¸ ę°€ėƒ 환ę˛Ŋ뗐 대해 ėž˜ ė•Œęŗ  ėžˆë‹¤ëŠ´, ė´ ė„šė…˜ė€ 건너 ë›°ė–´ë„ ę´œė°ŽėŠĩ니다. 🤓 + +/// + +/// tip | 팁 + +**ę°€ėƒ 환ę˛Ŋ(Virtual Environment)** ė€ **환ę˛Ŋ ëŗ€ėˆ˜(Environment Variable)** 뙀 다ëĻ…ë‹ˆë‹¤. + +**환ę˛Ŋ ëŗ€ėˆ˜**는 ė‹œėŠ¤í…œė— ėĄ´ėžŦ하며, í”„ëĄœęˇ¸ëž¨ė´ ė‚ŦėšŠí•  눘 ėžˆëŠ” ëŗ€ėˆ˜ėž…ë‹ˆë‹¤. + +**ę°€ėƒ 환ę˛Ŋ**ė€ ëLJëLJ 파ėŧ로 ęĩŦė„ąëœ í•˜ë‚˜ė˜ 디렉터ëĻŦėž…ë‹ˆë‹¤. + +/// + +/// info | ė •ëŗ´ + +ė´ íŽ˜ė´ė§€ė—ė„œëŠ” **ę°€ėƒ 환ę˛Ŋ**ė˜ ė‚ŦėšŠ 방법ęŗŧ ėž‘ë™ ë°Šė‹ė„ 네ëĒ…í•Šë‹ˆë‹¤. + +만ė•Ŋ **ëĒ¨ë“  ę˛ƒė„ 관ëĻŦ해ėŖŧ는 도ęĩŦ** (Python ė„¤ėš˜ęšŒė§€ íŦ함)ëĨŧ ė‚ŦėšŠí•˜ęŗ  ė‹ļ다면 uvëĨŧ ė‚ŦėšŠí•´ëŗ´ė„¸ėš”. + +/// + +## í”„ëĄœė íŠ¸ ėƒė„ą + +ë¨ŧė €, í”„ëĄœė íŠ¸ëĨŧ ėœ„í•œ 디렉터ëĻŦëĨŧ 하나 ėƒė„ąí•Šë‹ˆë‹¤. + +ëŗ´í†ĩ ė‚ŦėšŠėž 홈 디렉터ëĻŦ ė•ˆė— `code`ëŧ는 디렉터ëĻŦëĨŧ ë§Œë“¤ęŗ , ꡸ ė•ˆė— í”„ëĄœė íŠ¸ë§ˆë‹¤ í•˜ë‚˜ė”Š 디렉터ëĻŦëĨŧ ë§Œë“¤ė–´ 관ëĻŦ합니다. + +
+ +```console +// 홈 디렉터ëĻŦ로 ė´ë™ +$ cd +// ëĒ¨ë“  ėŊ”드 í”„ëĄœė íŠ¸ëĨŧ ėœ„í•œ 디렉터ëĻŦ ėƒė„ą +$ mkdir code +// code 디렉터ëĻŦ로 ė´ë™ +$ cd code +// ė´ë˛ˆ í”„ëĄœė íŠ¸ëĨŧ ėœ„í•œ 디렉터ëĻŦ ėƒė„ą +$ mkdir awesome-project +// 해당 í”„ëĄœė íŠ¸ 디렉터ëĻŦ로 ė´ë™ +$ cd awesome-project +``` + +
+ +## ę°€ėƒ 환ę˛Ŋ ėƒė„ą + +Python í”„ëĄœė íŠ¸ëĨŧ **ė˛˜ėŒ ė‹œėž‘í•  때**, ę°€ėƒ 환ę˛Ŋė„ **í”„ëĄœė íŠ¸ 내ëļ€**뗐 ėƒė„ąí•Šë‹ˆë‹¤. + +/// tip | 팁 + +ė´ ėž‘ė—…ė€ **í”„ëĄœė íŠ¸ëĨŧ ė˛˜ėŒ ė„¤ė •í•  때 한번만** 해ėŖŧ늴 됩니다. ė´í›„ ėž‘ė—…í•  때 반ëŗĩ할 í•„ėš”ëŠ” ė—†ėŠĩ니다. + +/// + +//// tab | `venv` + +Python í‘œė¤€ ëŧė´ë¸ŒëŸŦëĻŦ뗐 íŦ함된 venv ëĒ¨ë“ˆė„ ė‚ŦėšŠí•´ ę°€ėƒ 환ę˛Ŋė„ ėƒė„ąí•  눘 ėžˆėŠĩ니다. + +
+ +```console +$ python -m venv .venv +``` + +
+ +/// details | ëĒ…ë šė–´ ėƒė„¸ 네ëĒ… + +* `python`: `python` í”„ëĄœęˇ¸ëž¨ė„ ė‹¤í–‰í•Šë‹ˆë‹¤. +* `-m`: íŠšė • ëĒ¨ë“ˆė„ 늤íŦëĻŊíŠ¸ė˛˜ëŸŧ ė‹¤í–‰í•Šë‹ˆë‹¤. ëŒ€ėƒ ëĒ¨ë“ˆė„ 바로 ë’¤ė— ė§€ė •í•Šë‹ˆë‹¤. +* `venv`: Python í‘œė¤€ ëŧė´ë¸ŒëŸŦëĻŦ뗐 íŦ함된 `venv` ëĒ¨ë“ˆė„ ė‹¤í–‰í•Šë‹ˆë‹¤. +* `.venv`: ę°€ėƒ 환ę˛Ŋė„ `.venv` 디렉터ëĻŦ뗐 ėƒė„ąí•Šë‹ˆë‹¤. + +/// + +//// + +//// tab | `uv` + +`uv`가 ė„¤ėš˜ë˜ė–´ ėžˆë‹¤ëŠ´, uvëĨŧ í†ĩ해 ę°€ėƒ 환ę˛Ŋė„ ėƒė„ąí•  눘 ėžˆėŠĩ니다. + +
+ +```console +$ uv venv +``` + +
+ +/// tip | 팁 + +`uv`는 ę¸°ëŗ¸ė ėœŧ로 `.venv` 디렉터ëĻŦ뗐 ę°€ėƒ 환ę˛Ŋė„ ėƒė„ąí•Šë‹ˆë‹¤. + +ëŗ„ë„ëĄœ 디렉터ëĻŦ ė´ëĻ„ė„ ėļ”ę°€ ė¸ėžëĄœ 넘겨 ėŖŧ늴 ę˛Ŋ로ëĨŧ 맀렕 할 눘 ėžˆėŠĩ니다. + +/// + +//// + +해당 ëĒ…ë šė–´ëŠ” `.venv` 디렉터ëĻŦ뗐 ėƒˆëĄœėš´ ę°€ėƒ 환ę˛Ŋė„ ėƒė„ąí•Šë‹ˆë‹¤. + +/// details | `.venv` 또는 다ëĨ¸ ė´ëĻ„ + +ę°€ėƒ 환ę˛Ŋė„ 다ëĨ¸ 디렉터ëĻŦ뗐 ėƒė„ąí•  ėˆ˜ë„ ėžˆė§€ë§Œ, ę´€ëĄ€ė ėœŧ로 `.venv` 디렉터ëĻŦ ė´ëĻ„ė„ ė‚ŦėšŠí•Šë‹ˆë‹¤. + +/// + +## ę°€ėƒ 환ę˛Ŋ í™œė„ąí™” + +ė´í›„ ė‹¤í–‰í•˜ëŠ” Python ëĒ…ë šė–´ė™€ íŒ¨í‚¤ė§€ ė„¤ėš˜ę°€ ę°€ėƒ 환ę˛Ŋė„ 따ëĨ´ë„록, ę°€ėƒ 환ę˛Ŋė„ í™œė„ąí™”í•˜ė„¸ėš”. + +/// tip | 팁 + +**í„°ë¯¸ë„ė„ ėƒˆëĄœ ė—´ęŗ ** í”„ëĄœė íŠ¸ ėž‘ė—…ė„ ė‹œėž‘í•  때는, **í•­ėƒ ė´ ėž‘ė—…ė„** 해ėŖŧė„¸ėš”. + +/// + +//// tab | Linux, macOS + +
+ +```console +$ source .venv/bin/activate +``` + +
+ +//// + +//// tab | Windows PowerShell + +
+ +```console +$ .venv\Scripts\Activate.ps1 +``` + +
+ +//// + +//// tab | Windows Bash + +Windowsė—ė„œ Bash(똈: Git Bash)ëĨŧ ė‚ŦėšŠí•˜ëŠ” ę˛Ŋ뚰: + +
+ +```console +$ source .venv/Scripts/activate +``` + +
+ +//// + +/// tip | 팁 + +ę°€ėƒ 환ę˛Ŋ뗐 ėƒˆëĄœėš´ íŒ¨í‚¤ė§€ëĨŧ ė„¤ėš˜í•  때마다, 해당 환ę˛Ŋė„ ë‹¤ė‹œ í™œė„ąí™”í•˜ė„¸ėš”. + +ė´ë ‡ę˛Œ 하면 해당 íŒ¨í‚¤ė§€ëĄœ ė„¤ėš˜ëœ **터미널(CLI) 프로그램**ė„ ė‚ŦėšŠí•  때, 렄뗭뗐 ė„¤ėš˜ëœ 다ëĨ¸ ë˛„ė „ė´ ė•„ë‹ˆëŧ, ę°€ėƒ 환ę˛Ŋ ė•ˆė— ė„¤ėš˜ëœ ė •í™•í•œ ë˛„ė „ė„ ė‚ŦėšŠí•Šë‹ˆë‹¤. + +/// + +## ę°€ėƒ 환ę˛Ŋė´ í™œė„ąí™” ė—Ŧëļ€ í™•ė¸ + +ę°€ėƒ 환ę˛Ŋė´ í™œė„ąí™”ë˜ė—ˆëŠ”ė§€ í™•ė¸í•Šë‹ˆë‹¤. (ė´ė „ ëĒ…ë šė–´ę°€ ė œëŒ€ëĄœ ėž‘ë™í–ˆëŠ”ė§€ í™•ė¸í•Šë‹ˆë‹¤). + +/// tip | 팁 + +ė´ ë‹¨ęŗ„ëŠ” **ė„ íƒ ė‚Ŧ항**ė´ė§€ë§Œ, ëĒ¨ë“  ę˛ƒė´ ė˜ˆėƒëŒ€ëĄœ ėž‘ë™í•˜ęŗ  ėžˆëŠ”ė§€, ꡸ëĻŦęŗ  ė˜ë„í•œ ę°€ėƒ 환ę˛Ŋė´ í™œė„ąí™” ë˜ė—ˆëŠ” ė§€ **í™•ė¸**하는 ėĸ‹ė€ ë°Šë˛•ėž…ë‹ˆë‹¤. + +/// + +//// tab | Linux, macOS, Windows Bash + +
+ +```console +$ which python + +/home/user/code/awesome-project/.venv/bin/python +``` + +
+ +`python` ėœ„ėš˜ę°€ í”„ëĄœė íŠ¸ 내ëļ€(ė´ ė˜ˆė‹œė—ė„œëŠ” `awesome-project`)ė˜ `.venv/bin/python` ę˛Ŋ로로 í‘œė‹œëœë‹¤ëŠ´ ė„ąęŗĩėž…ë‹ˆë‹¤. 🎉 + +//// + +//// tab | Windows PowerShell + +
+ +```console +$ Get-Command python + +C:\Users\user\code\awesome-project\.venv\Scripts\python +``` + +
+ +`python` ėœ„ėš˜ę°€ í”„ëĄœė íŠ¸ 내ëļ€(ė´ ė˜ˆė‹œė—ė„œëŠ” `awesome-project`)ė˜ `.venv\bin\python` ę˛Ŋ로로 í‘œė‹œëœë‹¤ëŠ´ ė„ąęŗĩėž…ë‹ˆë‹¤. 🎉 + +//// + +## pip ė—…ęˇ¸ë ˆė´ë“œ + +/// tip | 팁 + +`uv`ëĨŧ ė‚ŦėšŠí•œë‹¤ëŠ´, `pip` ëŒ€ė‹  `uv`로 íŒ¨í‚¤ė§€ëĨŧ ė„¤ėš˜í•˜ę˛Œ ë˜ë¯€ëĄœ `pip`ė„ ė—…ęˇ¸ë ˆė´ë“œí•  í•„ėš”ę°€ ė—†ėŠĩ니다. 😎 + +/// + +`pip`ė„ ė‚ŦėšŠí•˜ė—Ŧ íŒ¨í‚¤ė§€ëĨŧ ė„¤ėš˜í•˜ëŠ” ę˛Ŋ뚰 (Python í‘œė¤€ ëŧė´ë¸ŒëŸŦëĻŦ뗐 íŦí•¨ë˜ė–´ ėžˆėŠĩ니다), **ėĩœė‹  ë˛„ė „ėœŧ로 ė—…ęˇ¸ë ˆė´ë“œ**하는 ę˛ƒė´ ėĸ‹ėŠĩ니다. + +íŒ¨í‚¤ė§€ ė„¤ėš˜ 뤑 ë°œėƒí•˜ëŠ” ë‹¤ė–‘í•˜ęŗ  íŠšė´í•œ 뗐ëŸŦë“¤ė€ `pip` ė—…ęˇ¸ë ˆė´ë“œëĄœ ė‰Ŋ枌 해결되는 ę˛Ŋėš°ę°€ 많ėŠĩ니다. + +/// tip | 팁 + +ė´ ėž‘ė—…ė€ ëŗ´í†ĩ ę°€ėƒ 환ę˛Ŋė„ ėƒė„ąí•œ **ė§í›„ 한 번만** 하면 됩니다. + +/// + +ę°€ėƒ 환ę˛Ŋė´ í™œė„ąí™”ëœ ėƒíƒœė¸ė§€ í™•ė¸í•œ 후(ė•žė„œ 네ëĒ…í•œ ëĒ…ë šė–´ ė‚ŦėšŠ), ė•„ëž˜ ëĒ…ë šė–´ëĨŧ ė‹¤í–‰í•˜ė„¸ėš”: + +
+ +```console +$ python -m pip install --upgrade pip + +---> 100% +``` + +
+ +## `.gitignore` ėļ”ę°€í•˜ę¸° + +**Git**ė„ ė‚ŦėšŠí•˜ęŗ  ėžˆë‹¤ëŠ´ (ė‚ŦėšŠí•˜ëŠ” ę˛ƒė´ ėĸ‹ėŠĩ니다), `.gitignore` 파ėŧė„ ėļ”ę°€í•´ė„œ `.venv` 디렉터ëĻŦ 렄랴ëĨŧ Gitė—ė„œ ė œė™¸í•˜ė„¸ėš”. + +/// tip | 팁 + +`uv`ëĨŧ ė‚ŦėšŠí•´ ę°€ėƒ 환ę˛Ŋė„ ėƒė„ąí–ˆë‹¤ëŠ´, ė´ë¯¸ ė´ ėž‘ė—…ė´ ėžë™ėœŧ로 래ëĻŦë˜ė–´ ėžˆėœŧë¯€ëĄœ ė´ ë‹¨ęŗ„ëŠ” ęą´ë„ˆë›°ė–´ë„ 됩니다. 😎 + +/// + +/// tip | 팁 + +ė´ ėž‘ė—…ë„ 마ė°Ŧę°€ė§€ëĄœ, ę°€ėƒ 환ę˛Ŋė„ ėƒė„ąí•œ **ė§í›„ 한 번만** 하면 됩니다. + +/// + +
+ +```console +$ echo "*" > .venv/.gitignore +``` + +
+ +/// details | ëĒ…ë šė–´ ėƒė„¸ 네ëĒ… + +* `echo "*"`: í„°ë¯¸ë„ė— `*` í…ėŠ¤íŠ¸ëĨŧ "ėļœë Ĩ"합니다 (ë‹¤ėŒ 네ëĒ…ė—ė„œ ėĄ°ę¸ˆ 바뀝니다) +* `>`: ė™ŧėĒŊ ëĒ…ë šė–´ė˜ ėļœë Ĩ ë‚´ėšŠė„ í„°ë¯¸ë„ė— ėļœë Ĩí•˜ė§€ ė•Šęŗ , 똤ëĨ¸ėĒŊ뗐 ė§€ė •ëœ 파ėŧ로 **기록(write)** 하ëŧ는 ė˜ë¯¸ėž…ë‹ˆë‹¤. +* `.gitignore`: ėļœë Ĩ된 í…ėŠ¤íŠ¸ę°€ 기록될 파ėŧ ė´ëĻ„ėž…ë‹ˆë‹¤. + +꡸ëĻŦęŗ  Gitė—ė„œ `*`는 "ëĒ¨ë“  것"ė„ ė˜ë¯¸í•Šë‹ˆë‹¤. 따ëŧė„œ `.venv` 디렉터ëĻŦ ė•ˆė˜ ëĒ¨ë“  ę˛ƒė„ ëŦ´ė‹œí•˜ę˛Œ 됩니다. + +ė´ ëĒ…ë šė–´ëŠ” ë‹¤ėŒęŗŧ ę°™ė€ ë‚´ėšŠė„ 氀맄 `.gitignore` 파ėŧė„ ėƒė„ąí•Šë‹ˆë‹¤: + + +```gitignore +* +``` + +/// + +## íŒ¨í‚¤ė§€ ė„¤ėš˜ + +ę°€ėƒ 환ę˛Ŋė„ í™œė„ąí™”í•œ 후, ꡸ ė•ˆė— í•„ėš”í•œ íŒ¨í‚¤ė§€ë“¤ė„ ė„¤ėš˜í•  눘 ėžˆėŠĩ니다. + +/// tip | 팁 + +í”„ëĄœė íŠ¸ė—ė„œ í•„ėš”í•œ íŒ¨í‚¤ė§€ëĨŧ ė„¤ėš˜í•˜ęą°ë‚˜ ė—…ęˇ¸ë ˆė´ë“œí•  때는 ė´ ėž‘ė—…ė„ **한 번만** 하면 됩니다. + +만ė•Ŋ íŠšė • íŒ¨í‚¤ė§€ė˜ ë˛„ė „ė„ ė—…ęˇ¸ë ˆė´ë“œí•˜ęą°ë‚˜, ėƒˆëĄœėš´ íŒ¨í‚¤ė§€ëĨŧ ėļ”가할 í•„ėš”ę°€ ėƒę¸°ëŠ´ **ë‹¤ė‹œ ė´ ėž‘ė—…ė„ 반ëŗĩ**하면 됩니다. + +/// + +### íŒ¨í‚¤ė§€ 링렑 ė„¤ėš˜ + +급하게 ėž‘ė—…í•˜ęą°ë‚˜, í”„ëĄœė íŠ¸ė— í•„ėš”í•œ íŒ¨í‚¤ė§€ ëĒŠëĄė„ 따로 파ėŧ로 관ëĻŦí•˜ęŗ  ė‹ļė§€ ė•Šė€ ę˛Ŋ뚰, íŒ¨í‚¤ė§€ëĨŧ 링렑 ė„¤ėš˜í•  ėˆ˜ë„ ėžˆėŠĩ니다. + +/// tip | 팁 + +íŒ¨í‚¤ė§€ ė´ëĻ„ęŗŧ ë˛„ė „ ė •ëŗ´ëĨŧ 파ėŧ뗐 ė •ëĻŦ해두는 것(똈: `requirements.txt` 또는 `pyproject.toml`)ė€ (ë§¤ėš°) ėĸ‹ė€ ėƒę°ėž…ë‹ˆë‹¤. + +/// + +//// tab | `pip` + +
+ +```console +$ pip install "fastapi[standard]" + +---> 100% +``` + +
+ +//// + +//// tab | `uv` + +`uv`ëĨŧ ė‚ŦėšŠí•˜ëŠ” ę˛Ŋ뚰: + +
+ +```console +$ uv pip install "fastapi[standard]" +---> 100% +``` + +
+ +//// + +### `requirements.txt`ė—ė„œ ė„¤ėš˜ + +`requirements.txt` 파ėŧė´ ėžˆë‹¤ëŠ´, ꡸ ė•ˆė— ëĒ…ė‹œëœ íŒ¨í‚¤ė§€ë“¤ė„ 한 ë˛ˆė— ė„¤ėš˜í•  눘 ėžˆėŠĩ니다. + +//// tab | `pip` + +
+ +```console +$ pip install -r requirements.txt +---> 100% +``` + +
+ +//// + +//// tab | `uv` + +`uv`ëĨŧ ė‚ŦėšŠí•˜ëŠ” ę˛Ŋ뚰: + +
+ +```console +$ uv pip install -r requirements.txt +---> 100% +``` + +
+ +//// + +/// details | `requirements.txt` + +ë‹¤ėŒė€ ëLJ 氀맀 íŒ¨í‚¤ė§€ëĨŧ íŦ함한 `requirements.txt`ė˜ ė˜ˆė‹œėž…ë‹ˆë‹¤: + +```requirements.txt +fastapi[standard]==0.113.0 +pydantic==2.8.0 +``` + +/// + +## 프로그램 ė‹¤í–‰ + +ę°€ėƒ 환ę˛Ŋė„ í™œė„ąí™”í•œ í›„ė—ëŠ” í”„ëĄœęˇ¸ëž¨ė„ ė‹¤í–‰í•  눘 ėžˆėŠĩ니다. ė´ë•Œ 해당 ę°€ėƒ 환ę˛Ŋ뗐 ė„¤ėš˜ëœ Pythonęŗŧ íŒ¨í‚¤ė§€ë“¤ė´ ė‚ŦėšŠëŠë‹ˆë‹¤. + +
+ +```console +$ python main.py + +Hello World +``` + +
+ +## ė—ë””í„° 네렕 + +ė—ë””í„°ëĨŧ ė‚ŦėšŠí•  ę˛Ŋ뚰, ė•žė„œ 만든 ę°€ėƒ 환ę˛Ŋė„ ė‚ŦėšŠí•˜ë„ëĄ ė„¤ė •í•˜ëŠ” ę˛ƒė´ ėĸ‹ėŠĩ니다. (대ëļ€ëļ„ė˜ ė—ë””í„°ëŠ” ėžë™ėœŧ로 ę°ė§€í•˜ę¸°ë„ 합니다.) +ė´ë ‡ę˛Œ 하면 ėžë™ ė™„ė„ą 기ëŠĨė´ë‚˜ ėŊ”드 내 똤ëĨ˜ í‘œė‹œ 기ëŠĨė„ ė œëŒ€ëĄœ ė‚ŦėšŠí•  눘 ėžˆėŠĩ니다. + +ė˜ˆė‹œ: + +* VS Code +* PyCharm + +/// tip | 팁 + +ė´ ė„¤ė •ė€ ëŗ´í†ĩ ę°€ėƒ 환ę˛Ŋė„ **ė˛˜ėŒ ë§Œë“¤ė—ˆė„ 때 한 번만** 해ėŖŧ늴 됩니다. + +/// + +## ę°€ėƒ 환ę˛Ŋ ëš„í™œė„ąí™” + +í”„ëĄœė íŠ¸ ėž‘ė—…ė´ 끝ë‚Ŧ다면, ę°€ėƒ 환ę˛Ŋė„ **ëš„í™œė„ąí™”**할 눘 ėžˆėŠĩ니다. + +
+ +```console +$ deactivate +``` + +
+ +ė´ë ‡ę˛Œ 하면 ė´í›„ė— `python` ëĒ…ë šė–´ëĨŧ ė‹¤í–‰í–ˆė„ 때, ę°€ėƒ 환ę˛Ŋė˜ Pythonė´ë‚˜ ꡸ ė•ˆė— ė„¤ėš˜ëœ íŒ¨í‚¤ė§€ë“¤ė„ ė‚ŦėšŠí•˜ė§€ ė•Šę˛Œ 됩니다. + +## ė´ė œ ėž‘ė—…í•  ė¤€ëš„ę°€ ë˜ė—ˆėŠĩ니다 + +ė´ė œ í”„ëĄœė íŠ¸ ėž‘ė—…ė„ ė‹œėž‘í•  ė¤€ëš„ę°€ ė™„ëŖŒë˜ė—ˆėŠĩ니다. + + +/// tip | 팁 + +ėœ„ ë‚´ėšŠė„ 더 ęšŠė´ ė´í•´í•˜ęŗ  ė‹ļėœŧė‹ ę°€ėš”? + +그렇다면 ęŗ„ė† ėŊė–´ ėŖŧė„¸ėš”. 👇🤓 + +/// + +## ę°€ėƒ 환ę˛Ŋė„ ė™œ ė‚ŦėšŠí•˜ëŠ”ę°€ + +FastAPIëĨŧ ė‚ŦėšŠí•˜ë ¤ëŠ´ ë¨ŧė € Pythonė„ ė„¤ėš˜í•´ė•ŧ 합니다. + +꡸ í›„ė—ëŠ” FastAPI뙀 함ęģ˜ ė‚ŦėšŠí•  **기타 íŒ¨í‚¤ė§€ë“¤**ė„ **ė„¤ėš˜**해ė•ŧ 합니다. + +íŒ¨í‚¤ė§€ëĨŧ ė„¤ėš˜í•  때 ëŗ´í†ĩ Python뗐 ę¸°ëŗ¸ íŦ함된 `pip` ëĒ…ë šė–´(또는 뜠ė‚Ŧ한 도ęĩŦ)ëĨŧ ė‚ŦėšŠí•Šë‹ˆë‹¤. + +í•˜ė§€ë§Œ `pip`ė„ ꡸ëƒĨ 링렑 ė‚ŦėšŠí•˜ëŠ´, 해당 íŒ¨í‚¤ė§€ë“¤ė€ **ė „ė—­ Python 환ę˛Ŋ**(ė‹œėŠ¤í…œ 렄랴뗐 ė„¤ėš˜ëœ Python)뗐 ė„¤ėš˜ëŠë‹ˆë‹¤. + +### ëŦ¸ė œė  + +그렇다면, ė „ė—­ Python 환ę˛Ŋ뗐 íŒ¨í‚¤ė§€ëĨŧ ė„¤ėš˜í•˜ëŠ´ ė–´ë–¤ ëŦ¸ė œę°€ ë°œėƒí• ęšŒėš”? + +ė–´ëŠ ė‹œė ė´ 되늴, **ė„œëĄœ 다ëĨ¸ íŒ¨í‚¤ė§€ë“¤**뗐 ė˜ėĄ´í•˜ëŠ” ė—ŦëŸŦ ę°œė˜ í”„ëĄœęˇ¸ëž¨ė„ ėž‘ė„ąí•˜ę˛Œ 될 ę˛ƒėž…ë‹ˆë‹¤. ꡸ëĻŦęŗ  ė´ë“¤ 뤑 ėŧëļ€ëŠ” **ę°™ė€ íŒ¨í‚¤ė§€ė˜ ė„œëĄœ 다ëĨ¸ ë˛„ė „**ė„ í•„ėš”ëĄœ 할 눘 ėžˆėŠĩ니다. 😱 + +똈ëĨŧ ë“¤ė–´, `마법ė‚Ŧė˜ 돌(philosophers-stone)` í”„ëĄœė íŠ¸ëĨŧ ë§Œë“¤ė—ˆë‹¤ęŗ  ę°€ė •í•´ë´…ė‹œë‹¤. ė´ í”„ëĄœęˇ¸ëž¨ė€ `해ëĻŦ íŦ터(harry)`ëŧ는 íŒ¨í‚¤ė§€ė˜ `v1` ë˛„ė „ė„ **ė˜ėĄ´**합니다. 따ëŧė„œ `harry`ëĨŧ ė„¤ėš˜í•´ė•ŧ 합니다. + +```mermaid +flowchart LR + stone(philosophers-stone) -->|requires| harry-1[harry v1] +``` + +그런데 ë‚˜ė¤‘ė— `ė•„ėĻˆėš´ë°˜ė˜ ėŖ„ėˆ˜(prisoner-of-azkaban)`ė´ëŧ는 또 다ëĨ¸ í”„ëĄœė íŠ¸ëĨŧ 만들게 ë˜ė—ˆęŗ , ė´ í”„ëĄœė íŠ¸ë„ ė—­ė‹œ `harry` íŒ¨í‚¤ė§€ëĨŧ ė‚ŦėšŠí•Šë‹ˆë‹¤. 그런데 ė´ í”„ëĄœė íŠ¸ëŠ” `harry`ė˜ `v3` ë˛„ė „ė´ í•„ėš”í•Šë‹ˆë‹¤. + +```mermaid +flowchart LR + azkaban(prisoner-of-azkaban) --> |requires| harry-3[harry v3] +``` + +í•˜ė§€ë§Œ ė´ė œ ëŦ¸ė œę°€ ėƒęšë‹ˆë‹¤. 로ėģŦ ę°€ėƒ 환ę˛Ŋ ëŒ€ė‹ ė— ė „ė—­ 환ę˛Ŋ뗐 íŒ¨í‚¤ė§€ëĨŧ ė„¤ėš˜í•˜ę˛Œ 되늴, ė–´ë–¤ ë˛„ė „ė˜ `harry`ëĨŧ ė„¤ėš˜í• ė§€ëĨŧ ė„ íƒí•´ė•ŧ 하기 때ëŦ¸ėž…니다. + +똈ëĨŧ ë“¤ė–´, `마법ė‚Ŧė˜ 돌(philosophers-stone)`ė„ ė‹¤í–‰í•˜ęŗ  ė‹ļ다면 ë¨ŧė € `harry` `v1` ë˛„ė „ė„ ë‹¤ėŒęŗŧ ę°™ė´ ė„¤ėš˜ 해ė•ŧ 합니다: + +
+ +```console +$ pip install "harry==1" +``` + +
+ +꡸ëŸŦ늴 결ęĩ­ ė „ė—­ Python 환ę˛Ŋė—ëŠ” `harry` `v1`ë˛„ė „ė´ ė„¤ėš˜ëœ ėƒíƒœę°€ 됩니다. + +```mermaid +flowchart LR + subgraph global[global env] + harry-1[harry v1] + end + subgraph stone-project[philosophers-stone project] + stone(philosophers-stone) -->|requires| harry-1 + end +``` + +í•˜ė§€ë§Œ ė´ė œ `ė•„ėĻˆėš´ë°˜ė˜ ėŖ„ėˆ˜(prisoner-of-azkaban)`ė„ ė‹¤í–‰í•˜ęŗ  ė‹ļ다면, `harry` `v1`ë˛„ė „ė„ ė œęą°í•˜ęŗ  `harry` `v3`ë˛„ė „ė„ ė„¤ėš˜í•´ė•ŧ 합니다. (또는 ë‹¨ėˆœížˆ `v3`ë˛„ė „ė„ ė„¤ėš˜í•˜ëŠ” 것만ėœŧ로도 ę¸°ėĄ´ė˜ `v1`ë˛„ė „ė´ ėžë™ėœŧ로 ė œęą°ëŠë‹ˆë‹¤.) + +
+ +```console +$ pip install "harry==3" +``` + +
+ +그렇게 하면 ė´ė œ ė „ė—­ Python 환ę˛Ŋė—ëŠ” `harry` `v3`ë˛„ė „ė´ ė„¤ėš˜ëœ ėƒíƒœę°€ 됩니다. + +꡸ëĻŦęŗ  ë‹¤ė‹œ `마법ė‚Ŧė˜ 돌(philosophers-stone)`ė„ ė‹¤í–‰í•˜ë ¤ęŗ  하면, **ėž‘ë™í•˜ė§€** ė•Šė„ 눘 ėžˆėŠĩ니다. ė™œëƒí•˜ëŠ´ ė´ í”„ëĄœęˇ¸ëž¨ė€ `harry` `v1`ë˛„ė „ė„ í•„ėš”ëĄœ 하기 때ëŦ¸ėž…니다. + +```mermaid +flowchart LR + subgraph global[global env] + harry-1[harry v1] + style harry-1 fill:#ccc,stroke-dasharray: 5 5 + harry-3[harry v3] + end + subgraph stone-project[philosophers-stone project] + stone(philosophers-stone) -.-x|â›”ī¸| harry-1 + end + subgraph azkaban-project[prisoner-of-azkaban project] + azkaban(prisoner-of-azkaban) --> |requires| harry-3 + end +``` + +/// tip | 팁 + +Python íŒ¨í‚¤ė§€ë“¤ė€ **냈 ë˛„ė „**ė—ė„œ **í˜¸í™˜ė„ą ëŦ¸ė œ(breaking changes)**가 ë°œėƒí•˜ė§€ ė•Šë„ëĄ ėĩœëŒ€í•œ 노ë Ĩ하는 ę˛ƒė´ ėŧë°˜ė ėž…ë‹ˆë‹¤. í•˜ė§€ë§Œ 그래도 ė•ˆė „í•˜ę˛Œ ėž‘ė—…í•˜ë ¤ëŠ´, í…ŒėŠ¤íŠ¸ëĨŧ ė‹¤í–‰í•´ëŗ´ëŠ´ė„œ 냈 ë˛„ė „ė„ ė˜ë„ė ėœŧ로 ė„¤ėš˜í•˜ëŠ” ę˛ƒė´ ėĸ‹ėŠĩ니다. + +/// + +ė´ė œ, ė´ëŸ° ėŧė´ ė—ŦëŸŦëļ„ė˜ **ëĒ¨ë“  í”„ëĄœė íŠ¸**가 ė‚ŦėšŠí•˜ëŠ” **ėˆ˜ë§Žė€ íŒ¨í‚¤ė§€ë“¤**ė—ė„œ ë™ė‹œė— ë°œėƒí•œë‹¤ęŗ  ėƒėƒí•´ëŗ´ė„¸ėš”. ė´ëŠ” ë§¤ėš° 관ëĻŦ하기 ė–´ë ¤ėš°ëŠ°, 결ęĩ­ **ė„œëĄœ í˜¸í™˜ë˜ė§€ ė•ŠëŠ” ë˛„ė „**ė˜ íŒ¨í‚¤ė§€ëĄœ í”„ëĄœė íŠ¸ëĨŧ ė‹¤í–‰í•˜ę˛Œ 될 가ëŠĨė„ąė´ ë†’ęŗ , 그로 ė¸í•´ ė–´ë–¤ ëŦ¸ė œę°€ ė™œ ë°œėƒí•˜ëŠ”ė§€ ė•Œ 눘 ė—†ę˛Œ 될 눘 ėžˆėŠĩ니다. + +또한 ė‚ŦėšŠí•˜ëŠ” 뚴똁랴렜(Linux, Windows, macOS 등)뗐 따ëŧ Pythonė´ **미ëĻŦ ė„¤ėš˜ë˜ė–´ ėžˆė„ ėˆ˜ë„** ėžˆėŠĩ니다. ė´ëŸ° ę˛Ŋėš°ė—ëŠ” ėš´ė˜ė˛´ė œė˜ ë™ėž‘ė— í•„ėš”í•œ íŠšė • ë˛„ė „ė˜ íŒ¨í‚¤ė§€ë“¤ė´ 함ęģ˜ ė„¤ėš˜ë˜ė–´ ėžˆė„ 눘 ėžˆėŠĩ니다. ė´ ėƒíƒœė—ė„œ ė „ė—­ Python 환ę˛Ŋ뗐 ėž„ė˜ė˜ íŒ¨í‚¤ė§€ëĨŧ ė„¤ėš˜í•˜ëŠ´, ėš´ė˜ė˛´ė œė— íŦ함된 프로그램 ėŧëļ€ę°€ **ęš¨ė§ˆ ėœ„í—˜**도 ėžˆėŠĩ니다. + +## íŒ¨í‚¤ė§€ë“¤ė€ ė–´ë””ė— ė„¤ėš˜ë˜ëŠ”ę°€ + +Pythonė„ ė„¤ėš˜í•˜ëŠ´, ėģ´í“¨í„°ė— ė—ŦëŸŦ 디렉터ëĻŦ뙀 파ėŧë“¤ė´ ėƒė„ąëŠë‹ˆë‹¤. + +ė´ 뤑 ėŧëļ€ ë””ë ‰í„°ëĻŦ는 ė‚ŦėšŠėžę°€ ė„¤ėš˜í•œ íŒ¨í‚¤ė§€ë“¤ė„ ëŗ´ę´€í•˜ëŠ” ė—­í• ė„ 합니다. + +똈ëĨŧ ë“¤ė–´, ė•„ëž˜ ëĒ…ë šė–´ëĨŧ ė‹¤í–‰í•˜ëŠ´: + +
+ +```console +// ė§€ę¸ˆ ė‹¤í–‰í•˜ė§€ ė•Šė•„ë„ 됩니다, ꡸ëƒĨ 똈렜ėŧ ëŋė´ė—ėš” 🤓 +$ pip install "fastapi[standard]" +---> 100% +``` + +
+ +해당 ëĒ…ë šė–´ëŠ” FastAPI ėŊ”드ëĨŧ íŦ함한 ė••ėļ• íŒŒėŧė„ ë‹¤ėš´ëĄœë“œí•Šë‹ˆë‹¤. ė´ 파ėŧė€ ëŗ´í†ĩ PyPIė—ė„œ ë°›ė•„ė˜ĩ니다. + +또한 FastAPI가 ė˜ėĄ´í•˜ëŠ” 다ëĨ¸ íŒ¨í‚¤ė§€ë“¤ë„ 함ęģ˜ **ë‹¤ėš´ëĄœë“œ**됩니다. + +꡸ëĻŦęŗ  ꡸ ëĒ¨ë“  파ėŧë“¤ė„ **ė••ėļ• í•´ė œ**한 뒤, ėģ´í“¨í„°ė˜ íŠšė • 디렉터ëĻŦ뗐 ė €ėžĨ합니다. + +ę¸°ëŗ¸ė ėœŧ로 ė´ 파ėŧë“¤ė€ Pythonė´ ė„¤ėš˜ëœ 디렉터ëĻŦ ė•ˆ, ėω **ė „ė—­ 환ę˛Ŋ**뗐 ë‚´ė˜ 디렉터ëĻŦ뗐 ė €ėžĨ됩니다. + +## ę°€ėƒ 환ę˛Ŋė´ëž€ + +ė „ė—­ 환ę˛Ŋ뗐 ëĒ¨ë“  íŒ¨í‚¤ė§€ëĨŧ ė„¤ėš˜í•˜ëŠ´ė„œ ë°œėƒí•˜ëŠ” ëŦ¸ė œė— 대한 í•´ę˛°ėą…ė€, ėž‘ė—…í•˜ëŠ” **각 í”„ëĄœė íŠ¸ë§ˆë‹¤ ę°€ėƒ 환ę˛Ŋ**ė„ ė‚ŦėšŠí•˜ëŠ” ę˛ƒėž…ë‹ˆë‹¤. + +ę°€ėƒ 환ę˛Ŋė€ ė „ė—­ 환ę˛Ŋęŗŧ ë§¤ėš° 뜠ė‚Ŧ한 í•˜ë‚˜ė˜ **디렉터ëĻŦ**ė´ëŠ°, ꡸ ė•ˆė— 해당 í”„ëĄœė íŠ¸ëĨŧ ėœ„í•œ íŒ¨í‚¤ė§€ë“¤ė„ ė„¤ėš˜í•  눘 ėžˆėŠĩ니다. + +ė´ë ‡ę˛Œ 하면 각 í”„ëĄœė íŠ¸ëŠ” ėžė˛´ė ė¸ ę°€ėƒ 환ę˛Ŋ(`.venv` 디렉터ëĻŦ)ė„ ę°€ė§€ę˛Œ 되늰, ꡸ ė•ˆė— 해당 í”„ëĄœė íŠ¸ ė „ėšŠ íŒ¨í‚¤ė§€ë“¤ė„ ëŗ´ėœ í•˜ę˛Œ 됩니다. + + +```mermaid +flowchart TB + subgraph stone-project[philosophers-stone project] + stone(philosophers-stone) --->|requires| harry-1 + subgraph venv1[.venv] + harry-1[harry v1] + end + end + subgraph azkaban-project[prisoner-of-azkaban project] + azkaban(prisoner-of-azkaban) --->|requires| harry-3 + subgraph venv2[.venv] + harry-3[harry v3] + end + end + stone-project ~~~ azkaban-project +``` + +## ę°€ėƒ 환ę˛Ŋ í™œė„ąí™” ė˜ë¯¸ + +ę°€ėƒ 환ę˛Ŋė„ í™œė„ąí™”í•œë‹¤ëŠ” ę˛ƒė€, 똈ëĨŧ ë“¤ė–´ ë‹¤ėŒęŗŧ ę°™ė€ ëĒ…ë šė–´ëĨŧ ė‹¤í–‰í•˜ëŠ” ę˛ƒė„ ė˜ë¯¸í•Šë‹ˆë‹¤: + +//// tab | Linux, macOS + +
+ +```console +$ source .venv/bin/activate +``` + +
+ +//// + +//// tab | Windows PowerShell + +
+ +```console +$ .venv\Scripts\Activate.ps1 +``` + +
+ +//// + +//// tab | Windows Bash + +Windowsė—ė„œ Bash(똈: Git Bash)ëĨŧ ė‚ŦėšŠí•˜ëŠ” ę˛Ŋ뚰: + +
+ +```console +$ source .venv/Scripts/activate +``` + +
+ +//// + +ė´ ëĒ…ë šė–´ëŠ” ė´í›„ė— ė‹¤í–‰ë  ëĒ…ë šė–´ė—ė„œ ė‚ŦėšŠë  [환ę˛Ŋ ëŗ€ėˆ˜](environment-variables.md){.internal-link target=_blank} ëLJ 氜ëĨŧ ėƒė„ąí•˜ęą°ë‚˜ ėˆ˜ė •í•Šë‹ˆë‹¤. + +ė´ ëŗ€ėˆ˜ë“¤ 뤑 하나가 바로 `PATH` ëŗ€ėˆ˜ėž…ë‹ˆë‹¤. + +/// tip | 팁 + +`PATH` 환ę˛Ŋ ëŗ€ėˆ˜ė— 대해 더 ė•Œęŗ  ė‹ļ다면 [환ę˛Ŋ ëŗ€ėˆ˜ ëŦ¸ė„œė˜ PATH 환ę˛Ŋ ëŗ€ėˆ˜ ė„šė…˜](environment-variables.md#path-environment-variable){.internal-link target=_blank}ė„ ė°¸ęŗ í•˜ė„¸ėš”. + +/// + +ę°€ėƒ 환ę˛Ŋė„ í™œė„ąí™”í•˜ëŠ´, ę°€ėƒ 환ę˛Ŋė˜ ę˛ŊëĄœė¸ `.venv/bin` (Linux뙀 macOS) 또는 `.venv\Scripts`(Windows)ëĨŧ `PATH` 환ę˛Ŋ ëŗ€ėˆ˜ė— ėļ”ę°€ëŠë‹ˆë‹¤. + +똈ëĨŧ ë“¤ė–´, ę°€ėƒ 환ę˛Ŋė„ í™œė„ąí™”í•˜ę¸° ė „ė˜ `PATH` ëŗ€ėˆ˜ëŠ” ë‹¤ėŒęŗŧ ę°™ė•˜ë‹¤ęŗ  ę°€ė •í•´ë´…ė‹œë‹¤: + +//// tab | Linux, macOS + +```plaintext +/usr/bin:/bin:/usr/sbin:/sbin +``` + +ė‹œėŠ¤í…œė€ ë‹¤ėŒ ę˛ŊëĄœë“¤ė—ė„œ í”„ëĄœęˇ¸ëž¨ė„ ė°žę˛Œ 됩니다: + +* `/usr/bin` +* `/bin` +* `/usr/sbin` +* `/sbin` + +//// + +//// tab | Windows + +```plaintext +C:\Windows\System32 +``` + +ė‹œėŠ¤í…œė€ ë‹¤ėŒ ę˛ŊëĄœë“¤ė—ė„œ í”„ëĄœęˇ¸ëž¨ė„ ė°žę˛Œ 됩니다: + +* `C:\Windows\System32` + +//// + +ę°€ėƒ 환ę˛Ŋė„ í™œė„ąí™”í•œ í›„ė—ëŠ”, `PATH` ëŗ€ėˆ˜ëŠ” ë‹¤ėŒęŗŧ ę°™ė€ 형태가 됩니다: + +//// tab | Linux, macOS + +```plaintext +/home/user/code/awesome-project/.venv/bin:/usr/bin:/bin:/usr/sbin:/sbin +``` + +ė‹œėŠ¤í…œė€ 가ėžĨ ë¨ŧė € ë‹¤ėŒ ę˛ŊëĄœė—ė„œ í”„ëĄœęˇ¸ëž¨ė„ ė°žę¸° ė‹œėž‘í•Šë‹ˆë‹¤: + +```plaintext +/home/user/code/awesome-project/.venv/bin +``` + +꡸ í›„ė— 다ëĨ¸ 디렉터ëĻŦë“¤ė„ íƒėƒ‰í•Šë‹ˆë‹¤. + +따ëŧė„œ í„°ë¯¸ë„ė— `python`ė„ ėž…ë Ĩ하면, ė‹œėŠ¤í…œė€ ë‹¤ėŒ ėœ„ėš˜ė— ėžˆëŠ” Python í”„ëĄœęˇ¸ëž¨ė„ ė°žę˛Œ 됩니다: + +```plaintext +/home/user/code/awesome-project/.venv/bin/python +``` + +꡸ëĻŦęŗ  해당 Pythonė„ ė‚ŦėšŠí•˜ę˛Œ 됩니다. + +//// + +//// tab | Windows + +```plaintext +C:\Users\user\code\awesome-project\.venv\Scripts;C:\Windows\System32 +``` + +ė‹œėŠ¤í…œė€ 가ėžĨ ë¨ŧė € ë‹¤ėŒ ę˛ŊëĄœė—ė„œ í”„ëĄœęˇ¸ëž¨ė„ ė°žę¸° ė‹œėž‘í•Šë‹ˆë‹¤: + +```plaintext +C:\Users\user\code\awesome-project\.venv\Scripts +``` + +꡸ í›„ė— 다ëĨ¸ 디렉터ëĻŦë“¤ė„ íƒėƒ‰í•Šë‹ˆë‹¤. + +따ëŧė„œ í„°ë¯¸ë„ė— `python`ė„ ėž…ë Ĩ하면, ė‹œėŠ¤í…œė€ ë‹¤ėŒ ę˛ŊëĄœė— ėžˆëŠ” Python í”„ëĄœęˇ¸ëž¨ė„ ė°žę˛Œ 됩니다: + +```plaintext +C:\Users\user\code\awesome-project\.venv\Scripts\python +``` + +꡸ëĻŦęŗ  해당 Pythonė„ ė‚ŦėšŠí•˜ę˛Œ 됩니다. + +//// + +ė¤‘ėš”í•œ 넏ëļ€ ė‚Ŧ항 뤑 하나는, ę°€ėƒ 환ę˛Ŋė˜ ę˛Ŋ로가 `PATH` ëŗ€ėˆ˜ė˜ 가ėžĨ **ė•ž**뗐 ėļ”ę°€ëœë‹¤ëŠ” ė ėž…ë‹ˆë‹¤. ė‹œėŠ¤í…œė€ ė‚ŦėšŠ 가ëŠĨ한 다ëĨ¸ Pythonë“¤ëŗ´ë‹¤ **ë¨ŧė €** ė´ ę˛Ŋ로ëĨŧ ė°žėŠĩ니다. ęˇ¸ëž˜ė„œ í„°ë¯¸ë„ė—ė„œ `python`ė„ ė‹¤í–‰í•˜ëŠ´, ė „ė—­ 환ę˛Ŋė˜ Pythonė´ ė•„ë‹Œ **ę°€ėƒ 환ę˛Ŋ뗐 ėžˆëŠ”** Pythonė´ ė‚ŦėšŠëŠë‹ˆë‹¤. (똈: ė „ė—­ 환ę˛Ŋ뗐 ė„¤ėš˜ëœ `python`ė´ ėžˆë”ëŧ도 ęˇ¸ëŗ´ë‹¤ ėš°ė„ í•Šë‹ˆë‹¤.) + +ę°€ėƒ 환ę˛Ŋė„ í™œė„ąí™”í•˜ëŠ´ ė´ ė™¸ė—ë„ ëLJ 氀맀 다ëĨ¸ ę˛ƒë“¤ė´ ëŗ€ę˛Ŋë˜ė§€ë§Œ, ė´ëŠ” ęˇ¸ė¤‘ė—ė„œë„ 가ėžĨ ė¤‘ėš”í•œ ëŗ€í™” 뤑 í•˜ë‚˜ėž…ë‹ˆë‹¤. + +## ę°€ėƒ 환ę˛Ŋ í™•ė¸í•˜ę¸° + +ę°€ėƒ 환ę˛Ŋė´ í™œė„ąí™” ë˜ė—ˆëŠ”ė§€ í™•ė¸í•˜ë ¤ëŠ´, ė•„ëž˜ ëĒ…ë šė–´ëĨŧ ė‚ŦėšŠí•  눘 ėžˆėŠĩ니다: + +//// tab | Linux, macOS, Windows Bash + +
+ +```console +$ which python + +/home/user/code/awesome-project/.venv/bin/python +``` + +
+ +//// + +//// tab | Windows PowerShell + +
+ +```console +$ Get-Command python + +C:\Users\user\code\awesome-project\.venv\Scripts\python +``` + +
+ +//// + +ėω, 현ėžŦ ė‚ŦėšŠë˜ëŠ” `python` í”„ëĄœęˇ¸ëž¨ė€ **ę°€ėƒ 환ę˛Ŋ 내ëļ€ė— ėžˆëŠ” 것**ėž…ë‹ˆë‹¤. + +Linux뙀 macOSė—ė„œëŠ” `which`, Windows PowerShellė—ė„œëŠ” `Get-Command` ëĒ…ë šė–´ëĨŧ ė‚ŦėšŠí•Šë‹ˆë‹¤. + +ė´ ëĒ…ë šė–´ëŠ” `PATH` 환ę˛Ŋ ëŗ€ėˆ˜ė— ė§€ė •ëœ ę˛ŊëĄœë“¤ė„ **ėˆœė„œëŒ€ëĄœ íƒėƒ‰**í•˜ëŠ´ė„œ `python`ė´ëŧ는 ė´ëĻ„ė˜ í”„ëĄœęˇ¸ëž¨ė„ ė°žėŠĩ니다. +ė°žëŠ” ėĻ‰ė‹œ, 해당 í”„ëĄœęˇ¸ëž¨ė˜ **ę˛Ŋ로ëĨŧ ėļœë Ĩ**합니다. + +ė¤‘ėš”í•œ ė ė€ í„°ë¯¸ë„ė—ė„œ `python`ė„ ė‹¤í–‰í–ˆė„ 때, ė‹¤ė œëĄœ ė‹¤í–‰ë˜ëŠ” "`python`"ė´ ė–´ë–¤ ę˛ƒė¸ė§€ ė •í™•ížˆ ė•Œ 눘 ėžˆë‹¤ëŠ” ę˛ƒėž…ë‹ˆë‹¤. + +따ëŧė„œ 현ėžŦ ė˜Ŧ바ëĨ¸ ę°€ėƒ 환ę˛Ŋ뗐 ėžˆëŠ”ė§€ í™•ė¸í•  눘 ėžˆėŠĩ니다. + +/// tip | 팁 + +í•˜ë‚˜ė˜ ę°€ėƒ 환ę˛Ŋė„ í™œė„ąí™”í•œ 뒤, 해당 Pythonė„ 氀맄 ėƒíƒœė—ė„œ **또 다ëĨ¸ í”„ëĄœė íŠ¸**로 ė´ë™í•˜ëŠ” ę˛ƒė€ 흔히 ë°œėƒí•Šë‹ˆë‹¤. + +í•˜ė§€ë§Œ ė´ë•Œ ė´ė „ í”„ëĄœė íŠ¸ė˜ ę°€ėƒ 환ę˛Ŋ뗐 ėžˆëŠ” **ėž˜ëĒģ된 Python ė‹¤í–‰ 파ėŧ**ė„ ė‚ŦėšŠí•˜ę˛Œ ë˜ė–´ 냈 í”„ëĄœė íŠ¸ę°€ **ė •ėƒ ėž‘ë™í•˜ė§€ ė•Šė„ 눘 ėžˆėŠĩ니다.** + +ęˇ¸ëž˜ė„œ 현ėžŦ ė–´ë–¤ `python`ė´ ė‚ŦėšŠë˜ęŗ  ėžˆëŠ”ė§€ í™•ė¸í•  눘 ėžˆëŠ” ëŠĨë Ĩė€ ë§¤ėš° ėœ ėšŠí•Šë‹ˆë‹¤. 🤓 + +/// + +## ę°€ėƒ 환ę˛Ŋė„ ëš„í™œė„ąí™”í•˜ëŠ” ė´ėœ  + +똈ëĨŧ ë“¤ė–´ `마법ė‚Ŧė˜ 돌(philosophers-stone)`ė´ëŧ는 í”„ëĄœė íŠ¸ė—ė„œ ėž‘ė—… ė¤‘ė´ëŧęŗ  í•´ëŗ´ę˛ ėŠĩ니다. ė´ë•Œ 해당 **ę°€ėƒ 환ę˛Ŋė„ í™œė„ąí™”**í•˜ęŗ , í•„ėš”í•œ íŒ¨í‚¤ė§€ëĨŧ ė„¤ėš˜í•˜ëŠ° ėž‘ė—…ė„ ė§„í–‰í•Šë‹ˆë‹¤. + +그런데 ė´ė œëŠ” **다ëĨ¸ í”„ëĄœė íŠ¸**ė¸ `ė•„ėĻˆėš´ë°˜ė˜ ėŖ„ėˆ˜(prisoner-of-azkaban)`ė„ ėž‘ė—…í•˜ęŗ  ė‹ļė–´ėĄŒėŠĩ니다. + +ęˇ¸ëž˜ė„œ ꡸ í”„ëĄœė íŠ¸ 디렉터ëĻŦ로 ė´ë™í•Šë‹ˆë‹¤: + +
+ +```console +$ cd ~/code/prisoner-of-azkaban +``` + +
+ +만ė•Ŋ `마법ė‚Ŧė˜ 돌(philosophers-stone)`ė˜ ę°€ėƒ 환ę˛Ŋė„ ëš„í™œė„ąí™”í•˜ė§€ ė•Šė•˜ë‹¤ëŠ´, í„°ë¯¸ë„ė—ė„œ `python`ė„ ė‹¤í–‰í•  때 ė—Ŧė „ížˆ `마법ė‚Ŧė˜ 돌(philosophers-stone)` ę°€ėƒ 환ę˛Ŋė˜ Pythonė„ ė‚ŦėšŠí•˜ę˛Œ 됩니다. + +
+ +```console +$ cd ~/code/prisoner-of-azkaban + +$ python main.py + +// siriusëĨŧ ėž„íŦ트하는 데 ė‹¤íŒ¨í–ˆėŠĩ니다. ė„¤ėš˜ë˜ė–´ ėžˆė§€ ė•Šė•„ėš” 😱 +Traceback (most recent call last): + File "main.py", line 1, in + import sirius +``` + +
+ +í•˜ė§€ë§Œ `마법ė‚Ŧė˜ 돌(philosophers-stone)`ė˜ ę°€ėƒ 환ę˛Ŋė„ ëš„í™œė„ąí™”í•œ ë‹¤ėŒ, `ė•„ėĻˆėš´ë°˜ė˜ ėŖ„ėˆ˜(prisoner-of-azkaban)` í”„ëĄœė íŠ¸ė˜ ę°€ėƒ 환ę˛Ŋė„ í™œė„ąí™”í•˜ëŠ´, ė´ė œ `python` ëĒ…ë šė–´ëŠ” `ė•„ėĻˆėš´ë°˜ė˜ ėŖ„ėˆ˜(prisoner-of-azkaban)` ę°€ėƒ 환ę˛Ŋė˜ Pythonė„ ė‚ŦėšŠí•˜ę˛Œ 됩니다. + +
+ +```console +$ cd ~/code/prisoner-of-azkaban + +// ė´ė „ 디렉터ëĻŦ뗐 ėžˆė„ í•„ėš” ė—†ė´, ė–´ë””ė„œë“  ę°€ėƒ 환ę˛Ŋė„ ëš„í™œė„ąí™”í•  눘 ėžˆėŠĩ니다. 다ëĨ¸ í”„ëĄœė íŠ¸ 디렉터ëĻŦ로 ė´ë™í•œ í›„ė—ë„ ę´œė°Žė•„ėš” 😎 +$ deactivate + +// prisoner-of-azkaban/.venv ę°€ėƒ 환ę˛Ŋė„ í™œė„ąí™”í•Šë‹ˆë‹¤ 🚀 +$ source .venv/bin/activate + +// ė´ė œ pythonė„ ė‹¤í–‰í•˜ëŠ´, ė´ ę°€ėƒ 환ę˛Ŋ뗐 ė„¤ėš˜ëœ sirius íŒ¨í‚¤ė§€ëĨŧ ė°žę˛Œ 됩니다 ✨ +$ python main.py + +ëĒģ된 ė§“ė„ ęž¸ë¯¸ęŗ  ėžˆėŒė„ ė—„ėˆ™ížˆ ë§šė„¸í•Šë‹ˆë‹¤.🧙 +ImportError는 ė´ė œ ė—†ėŠĩ니다. đŸē +``` + +
+ +## ëŒ€ė•ˆë“¤ + +ė´ ëŦ¸ė„œëŠ” ė—ŦëŸŦëļ„ė´ Python í”„ëĄœė íŠ¸ëĨŧ ė‹œėž‘í•˜ęŗ , **꡸ 내ëļ€ė—ė„œ** ė–´ë–ģ枌 ëŒė•„ę°€ëŠ”ė§€ ė•Œë ¤ėŖŧ는 간단한 ę°€ė´ë“œėž…ë‹ˆë‹¤. + +ę°€ėƒ 환ę˛Ŋ, íŒ¨í‚¤ė§€ ė˜ėĄ´ė„ą(Requirements), í”„ëĄœė íŠ¸ëĨŧ 관ëĻŦ하는 ë°Šë˛•ė—ëŠ” ė´ ė™¸ė—ë„ ë‹¤ė–‘í•œ **ëŒ€ė•ˆ**ë“¤ė´ ėĄ´ėžŦ합니다. + +만ė•Ŋ ė¤€ëš„ę°€ ë˜ė—ˆë‹¤ëŠ´, **í”„ëĄœė íŠ¸ 렄랴**, íŒ¨í‚¤ė§€ ė˜ėĄ´ė„ą, ę°€ėƒ 환ę˛Ŋ ë“ąė„ í†ĩí•Šė ėœŧ로 **관ëĻŦ**할 눘 ėžˆëŠ” 도ęĩŦëĨŧ ė¨ëŗ´ëŠ” 것도 ėĸ‹ėŠĩ니다. 그럴 때 ėļ”ė˛œí•˜ëŠ” 도ęĩŦ가 바로 uvėž…ë‹ˆë‹¤. + +`uv`는 ë‹¤ė–‘í•œ 기ëŠĨė„ ė§€ė›í•Šë‹ˆë‹¤: + +* ë‹¤ė–‘í•œ ë˛„ė „ė˜ **Python ė„¤ėš˜** +* 각 í”„ëĄœė íŠ¸ ëŗ„ **ę°€ėƒ 환ę˛Ŋ 관ëĻŦ** +* **íŒ¨í‚¤ė§€ ė„¤ėš˜** +* í”„ëĄœė íŠ¸ė˜ **ė˜ėĄ´ė„ąęŗŧ ë˛„ė „** 관ëĻŦ +* ė„¤ėš˜ëœ íŒ¨í‚¤ė§€ë“¤ęŗŧ ꡸ ë˛„ė „ė„ **ė •í™•ížˆ ęŗ ė •(lock)**í•´ė„œ,개발 환ę˛Ŋęŗŧ 뚴똁 환ę˛Ŋė´ ė™„ė „ížˆ 동ėŧ하게 ėž‘ë™í•  눘 ėžˆë„ëĄ ëŗ´ėžĨ +* ė´ ė™¸ė—ë„ ë‹¤ė–‘í•œ 기ëŠĨė„ 맀뛐 + +## 결률 + +ė—Ŧę¸°ęšŒė§€ ëĒ¨ë‘ ėŊęŗ  ė´í•´í–ˆë‹¤ëŠ´, ė´ė œ ë§Žė€ ę°œë°œėžë“¤ëŗ´ë‹¤ ę°€ėƒ 환ę˛Ŋė„ **훨ė”Ŧ 더 ęšŠė´ ėžˆę˛Œ ė´í•´**하게 ë˜ė…¨ėŠĩ니다. 🤓 + +ė´ëŸ° 넏ëļ€ė ė¸ ë‚´ėšŠė„ ė•Œęŗ  ėžˆėœŧ늴, 떏렠氀 ëŗĩėžĄí•´ ëŗ´ė´ëŠ” ëŦ¸ė œëĨŧ 디버깅할 때 ëļ„ëĒ…ížˆ 큰 ë„ė›€ė´ 될 ę˛ƒėž…ë‹ˆë‹¤. ė´ė œëŠ” **ė´ ëĒ¨ë“  ę˛ƒë“¤ė´ 내ëļ€ė—ė„œ ė–´ë–ģ枌 ėž‘ë™í•˜ëŠ”ė§€** ė•Œęŗ  ėžˆę¸° 때ëŦ¸ėž…니다. 😎 diff --git a/docs/nl/docs/index.md b/docs/nl/docs/index.md index d88bb7771..32b20e31e 100644 --- a/docs/nl/docs/index.md +++ b/docs/nl/docs/index.md @@ -12,7 +12,7 @@

- Test + Test Coverage diff --git a/docs/pl/docs/index.md b/docs/pl/docs/index.md index 9a96c6553..0e13d2631 100644 --- a/docs/pl/docs/index.md +++ b/docs/pl/docs/index.md @@ -11,15 +11,18 @@ FastAPI to szybki, prosty w nauce i gotowy do uÅŧycia w produkcji framework

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

--- diff --git a/docs/pt/docs/advanced/generate-clients.md b/docs/pt/docs/advanced/generate-clients.md index 04d7c0071..dc6b29511 100644 --- a/docs/pt/docs/advanced/generate-clients.md +++ b/docs/pt/docs/advanced/generate-clients.md @@ -22,7 +22,7 @@ E isso mostra o verdadeiro compromisso deles com o FastAPI e sua **comunidade** Por exemplo, vocÃĒ pode querer experimentar: -* Speakeasy +* Speakeasy * Stainless * liblab diff --git a/docs/pt/docs/async.md b/docs/pt/docs/async.md index 0d6bdbf0e..4425eba77 100644 --- a/docs/pt/docs/async.md +++ b/docs/pt/docs/async.md @@ -40,7 +40,7 @@ def results(): --- -Se sua aplicaÃ§ÃŖo (de alguma forma) nÃŖo tem que se comunicar com nada mais e tem que esperar que o respondam, use `async def`. +Se sua aplicaÃ§ÃŖo (de alguma forma) nÃŖo tem que se comunicar com nada mais e esperar que o respondam, use `async def`. --- @@ -52,7 +52,7 @@ Se vocÃĒ simplesmente nÃŖo sabe, use apenas `def`. De qualquer forma, em ambos os casos acima, FastAPI irÃĄ trabalhar assincronamente e ser extremamente rÃĄpido. -Seguindo os passos acima, ele serÃĄ capaz de fazer algumas otimizaçÃĩes de performance. +Mas, seguindo os passos acima, ele serÃĄ capaz de fazer algumas otimizaçÃĩes de performance. ## Detalhes TÊcnicos @@ -66,36 +66,36 @@ Vamos ver aquela frase por partes na seÃ§ÃŖo abaixo: ## CÃŗdigo assíncrono -CÃŗdigo assíncrono apenas significa que a linguagem đŸ’Ŧ tem um jeito de dizer para o computador / programa 🤖 que em certo ponto, ele 🤖 terÃĄ que esperar por *algo* para finalizar em outro lugar. Vamos dizer que esse *algo* seja chamado "arquivo lento" 📝. +CÃŗdigo assíncrono apenas significa que a linguagem đŸ’Ŧ tem um jeito de dizer para o computador / programa 🤖 que em certo ponto do cÃŗdigo, ele 🤖 terÃĄ que esperar *algo* finalizar em outro lugar. Vamos dizer que esse *algo* seja chamado "arquivo lento" 📝. -EntÃŖo, durante esse tempo, o computador pode ir e fazer outro trabalho, enquanto o "arquivo lento" 📝 termine. +EntÃŖo, durante esse tempo, o computador pode ir e fazer outro trabalho, enquanto o "arquivo lento" 📝 termina. -EntÃŖo o computador / programa 🤖 irÃĄ voltar toda hora que tiver uma chance porquÃĒ ele ainda estÃĄ esperando o "arquivo lento", ou ele 🤖 nunca irÃĄ terminar todo o trabalho que tem atÊ esse ponto. E ele 🤖 irÃĄ ver se alguma das tarefas que estava esperando jÃĄ terminaram, fazendo o que quer que tinham que fazer. +EntÃŖo o computador / programa 🤖 irÃĄ voltar sempre que tiver uma chance, seja porque ele estÃĄ esperando novamente, ou quando ele 🤖 terminar todo o trabalho que tem atÊ esse ponto. E ele 🤖 irÃĄ ver se alguma das tarefas que estava esperando jÃĄ terminaram de fazer o que quer que tinham que fazer. -Depois, ele 🤖 pega a primeira tarefa para finalizar (vamos dizer, nosso "arquivo lento" 📝) e continua o que ele tem que fazer com isso. +Depois, ele 🤖 pega a primeira tarefa para finalizar (vamos dizer, nosso "arquivo lento" 📝) e continua o que tem que fazer com ela. -Esse "esperar por algo" normalmente se refere a operaçÃĩes I/O que sÃŖo relativamente "lentas" (comparadas a velocidade do processador e da memÃŗria RAM), como esperar por: +Esse "esperar por algo" normalmente se refere a operaçÃĩes I/O que sÃŖo relativamente "lentas" (comparadas à velocidade do processador e da memÃŗria RAM), como esperar por: * dados do cliente para serem enviados atravÊs da rede -* dados enviados pelo seu programa para serem recebidos pelo clente atravÊs da rede -* conteÃēdo de um arquivo no disco pra ser lido pelo sistema e entregar ao seu programa +* dados enviados pelo seu programa serem recebidos pelo clente atravÊs da rede +* conteÃēdo de um arquivo no disco ser lido pelo sistema e entregue ao seu programa * conteÃēdo que seu programa deu ao sistema para ser escrito no disco -* uma operaÃ§ÃŖo remota API -* uma operaÃ§ÃŖo no banco de dados para finalizar -* uma solicitaÃ§ÃŖo no banco de dados esperando o retorno do resultado +* uma operaÃ§ÃŖo em uma API remota +* uma operaÃ§ÃŖo no banco de dados finalizar +* uma solicitaÃ§ÃŖo no banco de dados retornar o resultado * etc. -Enquanto o tempo de execuÃ§ÃŖo Ê consumido mais pela espera das operaçÃĩes I/O, essas operaçÃĩes sÃŖo chamadas de operaçÃĩes "limitadas por I/O". +Quanto o tempo de execuÃ§ÃŖo Ê consumido majoritariamente pela espera de operaçÃĩes I/O, essas operaçÃĩes sÃŖo chamadas operaçÃĩes "limitadas por I/O". -Isso Ê chamado de "assíncrono" porquÃĒ o computador / programa nÃŖo tem que ser "sincronizado" com a tarefa lenta, esperando pelo exato momento que a tarefa finalize, enquanto nÃŖo faz nada, para ser capaz de pegar o resultado da tarefa e dar continuidade ao trabalho. +Isso Ê chamado de "assíncrono" porque o computador / programa nÃŖo tem que ser "sincronizado" com a tarefa lenta, esperando pelo momento exato em que a tarefa finaliza, enquanto nÃŖo faz nada, para ser capaz de pegar o resultado da tarefa e dar continuidade ao trabalho. -Ao invÊs disso, sendo um sistema "assíncrono", uma vez finalizada, a tarefa pode esperar um pouco (alguns microssegundos) para que o computador / programa finalize o que quer que esteja fazendo,e entÃŖo volte para pegar o resultado e continue trabalhando com ele. +Ao invÊs disso, sendo um sistema "assíncrono", uma vez finalizada, a tarefa pode esperar na fila um pouco (alguns microssegundos) para que o computador / programa finalize o que quer que esteja fazendo, e entÃŖo volte para pegar o resultado e continue trabalhando com ele. -Para "síncrono" (contrÃĄrio de "assíncrono") tambÊm Ê utilizado o termo "sequencial", porquÃĒ o computador / programa segue todos os passos, na sequÃĒncia, antes de trocar para uma tarefa diferente, mesmo se alguns passos envolvam esperar. +Para "síncrono" (contrÃĄrio de "assíncrono") tambÊm Ê utilizado o termo "sequencial", porquÃĒ o computador / programa segue todos os passos, em sequÃĒncia, antes de trocar para uma tarefa diferente, mesmo se alguns passos envolvam esperar. ### ConcorrÃĒncia e hambÃērgueres -Essa idÊia de cÃŗdigo **assíncrono** descrito acima Ê algo às vezes chamado de **"concorrÃĒncia"**. E Ê diferente de **"paralelismo"**. +Essa idÊia de cÃŗdigo **assíncrono** descrita acima Ê às vezes chamado de **"concorrÃĒncia"**. Isso Ê diferente de **"paralelismo"**. **ConcorrÃĒncia** e **paralelismo** ambos sÃŖo relacionados a "diferentes coisas acontecendo mais ou menos ao mesmo tempo". @@ -105,117 +105,115 @@ Para ver essa diferença, imagine a seguinte histÃŗria sobre hambÃērgueres: ### HambÃērgueres concorrentes -VocÃĒ vai com seu _crush_ :heart_eyes: na lanchonete, fica na fila enquanto o caixa pega os pedidos das pessoas na sua frente. +VocÃĒ vai com seu _crush_ na lanchonete, e fica na fila enquanto o caixa pega os pedidos das pessoas na sua frente. 😍 -EntÃŖo chega a sua vez, vocÃĒ pede dois saborosos hambÃērgueres para vocÃĒ e seu _crush_ :heart_eyes:. +EntÃŖo chega a sua vez, vocÃĒ pede dois saborosos hambÃērgueres para vocÃĒ e seu _crush_. 🍔🍔 -VocÃĒ paga. +O caixa diz alguma coisa para o cozinheiro na cozinha para que eles saivam que tÃĒm que preparar seus hambÃērgueres (mesmo que ele esteja atualmente preparando os lanches dos outros clientes). -O caixa diz alguma coisa para o cara na cozinha para que ele tenha que preparar seus hambÃērgueres (mesmo embora ele esteja preparando os lanches dos outros clientes). +VocÃĒ paga. 💸 O caixa te entrega seu nÃēmero de chamada. -Enquanto vocÃĒ espera, vocÃĒ vai com seu _crush_ :heart_eyes: e pega uma mesa, senta e conversa com seu _crush_ :heart_eyes: por um bom tempo (como seus hambÃērgueres sÃŖo muito saborosos, leva um tempo para serem preparados). +Enquanto vocÃĒ espera, vocÃĒ vai com seu _crush_ e pega uma mesa, senta e conversa com seu _crush_ por um bom tempo (jÃĄ que seus hambÃērgueres sÃŖo muito saborosos, e leva um tempo para serem preparados). -Enquanto vocÃĒ estÃĄ sentado na mesa com seu _crush_ :heart_eyes:, esperando os hambÃērgueres, vocÃĒ pode gastar o tempo admirando como lindo, maravilhoso e esperto Ê seu _crush_ :heart_eyes:. +JÃĄ que vocÃĒ estÃĄ sentado na mesa com seu _crush_, esperando os hambÃērgueres, vocÃĒ pode passar esse tempo admirando o quÃŖo lindo, maravilhoso e esperto Ê seu _crush_ ✨😍✨. -Enquanto espera e conversa com seu _crush_ :heart_eyes:, de tempos em tempos, vocÃĒ verifica o nÃēmero de chamada exibido no balcÃŖo para ver se jÃĄ Ê sua vez. +Enquanto espera e conversa com seu _crush_, de tempos em tempos, vocÃĒ verifica o nÃēmero da chamada exibido no balcÃŖo para ver se jÃĄ Ê sua vez. -EntÃŖo a certo ponto, Ê finalmente sua vez. VocÃĒ vai no balcÃŖo, pega seus hambÃērgueres e volta para a mesa. +EntÃŖo em algum momento, Ê finalmente sua vez. VocÃĒ vai ao balcÃŖo, pega seus hambÃērgueres e volta para a mesa. -VocÃĒ e seu _crush_ :heart_eyes: comem os hambÃērgueres e aproveitam o tempo. +VocÃĒ e seu _crush_ comem os hambÃērgueres e aproveitam o tempo. ✨ --- -Imagine que vocÃĒ seja o computador / programa nessa histÃŗria. +Imagine que vocÃĒ seja o computador / programa nessa histÃŗria. -Enquanto vocÃĒ estÃĄ na fila, tranquilo, esperando por sua vez, nÃŖo estÃĄ fazendo nada "produtivo". Mas a fila Ê rÃĄpida porquÃĒ o caixa sÃŗ estÃĄ pegando os pedidos, entÃŖo estÃĄ tudo bem. +Enquanto vocÃĒ estÃĄ na fila, vocÃĒ estÃĄ somente ocioso 😴, esperando por sua vez, sem fazer nada muito "produtivo". Mas a fila Ê rÃĄpida porque o caixa sÃŗ estÃĄ pegando os pedidos (nÃŖo os preparando), entÃŖo estÃĄ tudo bem. -EntÃŖo, quando Ê sua vez, vocÃĒ faz o trabalho "produtivo" de verdade, vocÃĒ processa o menu, decide o que quer, pega a escolha de seu _crush_ :heart_eyes:, paga, verifica se entregou o valor correto em dinheiro ou cartÃŖo de crÊdito, verifica se foi cobrado corretamente, verifica se seu pedido estÃĄ correto etc. +EntÃŖo, quando Ê sua vez, vocÃĒ faz trabalho realmente "produtivo", vocÃĒ processa o menu, decide o que quer, pega a escolha de seu _crush_, paga, verifica se entregou o cartÃŖo ou a cÊdula correta, verifica se foi cobrado corretamente, verifica se seu pedido estÃĄ correto etc. -Mas entÃŖo, embora vocÃĒ ainda nÃŖo tenha os hambÃērgueres, seu trabalho no caixa estÃĄ "pausado", porquÃĒ vocÃĒ tem que esperar seus hambÃērgueres estarem prontos. +Mas entÃŖo, embora vocÃĒ ainda nÃŖo tenha os hambÃērgueres, seu trabalho no caixa estÃĄ "pausado" ⏸, porque vocÃĒ tem que esperar 🕙 seus hambÃērgueres ficarem prontos. -Mas enquanto vocÃĒ se afasta do balcÃŖo e senta na mesa com o nÃēmero da sua chamada, vocÃĒ pode trocar sua atenÃ§ÃŖo para seu _crush_ :heart_eyes:, e "trabalhar" nisso. EntÃŖo vocÃĒ estÃĄ novamente fazendo algo muito "produtivo", como flertar com seu _crush_ :heart_eyes:. +Contudo, à medida que vocÃĒ se afasta do balcÃŖo e senta na mesa, com um nÃēmero para sua chamada, vocÃĒ pode trocar 🔀 sua atenÃ§ÃŖo para seu _crush_, e "trabalhar" ⏯ 🤓 nisso. EntÃŖo vocÃĒ estÃĄ novamente fazendo algo muito "produtivo", como flertar com seu _crush_ 😍. -EntÃŖo o caixa diz que "seus hambÃērgueres estÃŖo prontos" colocando seu nÃēmero no balcÃŖo, mas vocÃĒ nÃŖo corre que nem um maluco imediatamente quando o nÃēmero exibido Ê o seu. VocÃĒ sabe que ninguÊm irÃĄ roubar seus hambÃērgueres porquÃĒ vocÃĒ tem o nÃēmero de chamada, e os outros tem os nÃēmeros deles. +EntÃŖo o caixa 💁 diz que "seus hambÃērgueres estÃŖo prontos" colocando seu nÃēmero no balcÃŖo, mas vocÃĒ nÃŖo corre que nem um maluco imediatamente quando o nÃēmero exibido Ê o seu. VocÃĒ sabe que ninguÊm irÃĄ roubar seus hambÃērgueres porque vocÃĒ tem o seu nÃēmero da chamada, e os outros tÃĒm os deles. -EntÃŖo vocÃĒ espera que seu _crush_ :heart_eyes: termine a histÃŗria que estava contando (terminar o trabalho atual / tarefa sendo processada), sorri gentilmente e diz que vocÃĒ estÃĄ indo buscar os hambÃērgueres. +EntÃŖo vocÃĒ espera seu _crush_ terminar a histÃŗria que estava contando (terminar o trabalho atual ⏯ / tarefa sendo processada 🤓), sorri gentilmente e diz que vocÃĒ estÃĄ indo buscar os hambÃērgueres. -EntÃŖo vocÃĒ vai no balcÃŖo, para a tarefa inicial que agora estÃĄ finalizada, pega os hambÃērgueres, e leva para a mesa. Isso finaliza esse passo / tarefa da interaÃ§ÃŖo com o balcÃŖo. Agora Ê criada uma nova tarefa, "comer hambÃērgueres", mas a tarefa anterior, "pegar os hambÃērgueres" jÃĄ estÃĄ finalizada. +EntÃŖo vocÃĒ vai ao balcÃŖo 🔀, para a tarefa inicial que agora estÃĄ finalizada⏯, pega os hambÃērgueres, agradece, e leva-os para a mesa. Isso finaliza esse passo / tarefa da interaÃ§ÃŖo com o balcÃŖo ⏚. Isso, por sua vez, cria uma nova tarefa, a de "comer hambÃērgueres" 🔀 ⏯, mas a tarefa anterior de "pegar os hambÃērgueres" jÃĄ estÃĄ finalizada ⏚. ### HambÃērgueres paralelos -VocÃĒ vai com seu _crush_ :heart_eyes: em uma lanchonete paralela. +Agora vamos imaginar que esses nÃŖo sÃŖo "HambÃērgueres Concorrentes", e sim "HambÃērgueres Paralelos" -VocÃĒ fica na fila enquanto alguns (vamos dizer 8) caixas pegam os pedidos das pessoas na sua frente. +VocÃĒ vai com seu _crush_ na lanchonete paralela. -Todo mundo antes de vocÃĒ estÃĄ esperando pelos hambÃērgueres estarem prontos antes de deixar o caixa porquÃĒ cada um dos 8 caixas vai e prepara o hambÃērguer antes de pegar o prÃŗximo pedido. +VocÃĒ fica na fila enquanto vÃĄrios (vamos dizer 8) caixas que tambÊm sÃŖo cozinheiros pegam os pedidos das pessoas na sua frente. -EntÃŖo Ê finalmente sua vez, e pede 2 hambÃērgueres muito saborosos para vocÃĒ e seu _crush_ :heart_eyes:. +Todo mundo na sua frente estÃĄ esperando seus hambÃērgueres ficarem prontos antes de deixar o caixa porque cada um dos 8 caixas vai e prepara o hambÃērguer logo apÃŗs receber o pedido, antes de pegar o prÃŗximo pedido. -VocÃĒ paga. +EntÃŖo Ê finalmente sua vez, vocÃĒ pede 2 hambÃērgueres muito saborosos para vocÃĒ e seu _crush_. + +VocÃĒ paga 💸. O caixa vai para a cozinha. -VocÃĒ espera, na frente do balcÃŖo, para que ninguÊm pegue seus hambÃērgueres antes de vocÃĒ, jÃĄ que nÃŖo tem nÃēmeros de chamadas. +VocÃĒ espera, na frente do balcÃŖo 🕙, para que ninguÊm pegue seus hambÃērgueres antes de vocÃĒ, jÃĄ que nÃŖo tem nÃēmeros de chamadas. -Enquanto vocÃĒ e seu _crush_ :heart_eyes: estÃŖo ocupados nÃŖo permitindo que ninguÊm passe a frente e pegue seus hambÃērgueres assim que estiverem prontos, vocÃĒ nÃŖo pode dar atenÃ§ÃŖo ao seu _crush_ :heart_eyes:. +Como vocÃĒ e seu _crush_ estÃŖo ocupados nÃŖo permitindo que ninguÊm passe na frente e pegue seus hambÃērgueres assim que estiverem prontos, vocÃĒ nÃŖo pode dar atenÃ§ÃŖo ao seu _crush_. 😞 -Isso Ê trabalho "síncrono", vocÃĒ estÃĄ "sincronizado" com o caixa / cozinheiro. VocÃĒ tem que esperar e estar lÃĄ no exato momento que o caixa / cozinheiro terminar os hambÃērgueres e dÃĄ-los a vocÃĒ, ou entÃŖo, outro alguÊm pode pegÃĄ-los. +Isso Ê trabalho "síncrono", vocÃĒ estÃĄ "sincronizado" com o caixa / cozinheirođŸ‘¨â€đŸŗ. VocÃĒ tem que esperar 🕙 e estar lÃĄ no exato momento que o caixa / cozinheiro đŸ‘¨â€đŸŗ terminar os hambÃērgueres e os der a vocÃĒ, ou entÃŖo, outro alguÊm pode pegÃĄ-los. -EntÃŖo seu caixa / cozinheiro finalmente volta com seus hambÃērgueres, depois de um longo tempo esperando por eles em frente ao balcÃŖo. +EntÃŖo seu caixa / cozinheiro đŸ‘¨â€đŸŗ finalmente volta com seus hambÃērgueres, depois de um longo tempo esperando 🕙 por eles em frente ao balcÃŖo. -VocÃĒ pega seus hambÃērgueres e vai para a mesa com seu _crush_ :heart_eyes:. +VocÃĒ pega seus hambÃērgueres e vai para a mesa com seu _crush_. -VocÃĒs comem os hambÃērgueres, e o trabalho estÃĄ terminado. +VocÃĒs comem os hambÃērgueres, e o trabalho estÃĄ terminado. ⏚ -NÃŖo houve muita conversa ou flerte jÃĄ que a maior parte do tempo foi gasto esperando os lanches na frente do balcÃŖo. +NÃŖo houve muita conversa ou flerte jÃĄ que a maior parte do tempo foi gasto esperando 🕙 na frente do balcÃŖo. 😞 --- -Nesse cenÃĄrio dos hambÃērgueres paralelos, vocÃĒ ÃŠ um computador / programa com dois processadores (vocÃĒ e seu _crush_ :heart_eyes:), ambos esperando e dedicando a atenÃ§ÃŖo de estar "esperando no balcÃŖo" por um bom tempo. +Nesse cenÃĄrio dos hambÃērgueres paralelos, vocÃĒ ÃŠ um computador / programa com dois processadores (vocÃĒ e seu _crush_), ambos esperando 🕙 e dedicando sua atenÃ§ÃŖo ⏯ "esperando no balcÃŖo" 🕙 por um bom tempo. -A lanchonete paralela tem 8 processadores (caixas / cozinheiros). Enquanto a lanchonete dos hambÃērgueres concorrentes tinham apenas 2 (um caixa e um cozinheiro). +A lanchonete paralela tem 8 processadores (caixas / cozinheiros), enquanto a lanchonete dos hambÃērgueres concorrentes tinha apenas 2 (um caixa e um cozinheiro). -Ainda assim, a Ãēltima experiÃĒncia nÃŖo foi a melhor. +Ainda assim, a experiÃĒncia final nÃŖo foi a melhor. 😞 --- -Essa poderia ser a histÃŗria paralela equivalente aos hambÃērgueres. +Essa seria o equivalente paralelo à histÃŗrio dos hambÃērgueres. 🍔 Para um exemplo "mais real", imagine um banco. -AtÊ recentemente, a maioria dos bancos tinha muitos caixas e uma grande fila. +AtÊ recentemente, a maioria dos bancos tinham muitos caixas 👨‍đŸ’ŧ👨‍đŸ’ŧ👨‍đŸ’ŧ👨‍đŸ’ŧ e uma grande fila 🕙🕙🕙🕙🕙🕙🕙🕙. -Todos os caixas fazendo todo o trabalho, um cliente apÃŗs o outro. +Todos os caixas fazendo todo o trabalho, um cliente apÃŗs o outro 👨‍đŸ’ŧ⏯. -E vocÃĒ tinha que esperar na fila por um longo tempo ou poderia perder a vez. +E vocÃĒ tinha que esperar 🕙 na fila por um longo tempo ou poderia perder a vez. -VocÃĒ provavelmente nÃŖo gostaria de levar seu _crush_ :heart_eyes: com vocÃĒ para um rolezinho no banco. +VocÃĒ provavelmente nÃŖo gostaria de levar seu _crush_ 😍 com vocÃĒ para um rolezinho no banco đŸĻ. ### ConclusÃŖo dos hambÃērgueres -Nesse cenÃĄrio dos "hambÃērgueres com seu _crush_ :heart_eyes:", como tem muita espera, faz mais sentido ter um sistema concorrente. +Nesse cenÃĄrio dos "hambÃērgueres com seu _crush_", como tem muita espera, faz mais sentido ter um sistema concorrente â¸đŸ”€â¯. Esse Ê o caso da maioria das aplicaçÃĩes web. -Geralmente sÃŖo muitos usuÃĄrios, e seu servidor estÃĄ esperando pelas suas conexÃĩes nÃŖo tÃŖo boas para enviar as requisiçÃĩes. - -E entÃŖo esperando novamente pelas respostas voltarem. - -Essa "espera" Ê medida em microssegundos, e ainda assim, somando tudo, Ê um monte de espera no final. +Muitos, muitos usuÃĄrios, mas seu servidor estÃĄ esperando 🕙 pela sua conexÃŖo nÃŖo tÃŖo boa enviar suas requisiçÃĩes. -Por isso que faz muito mais sentido utilizar cÃŗdigo assíncrono para APIs web. +E entÃŖo esperando 🕙 novamente as respostas voltarem. -A maioria dos frameworks Python existentes mais populares (incluindo Flask e Django) foram criados antes que os novos recursos assíncronos existissem em Python. EntÃŖo, os meios que eles podem ser colocados em produÃ§ÃŖo para suportar execuÃ§ÃŖo paralela mais a forma antiga de execuÃ§ÃŖo assíncrona nÃŖo sÃŖo tÃŖo poderosos quanto as novas capacidades. +Essa "espera" 🕙 Ê medida em microssegundos, mas ainda assim, somando tudo, Ê um monte de espera no final. -Mesmo embora a especificaÃ§ÃŖo principal para web assíncrono em Python (ASGI) foi desenvolvida no Django, para adicionar suporte para WebSockets. +Por isso que faz bastante sentido utilizar cÃŗdigo assíncrono â¸đŸ”€â¯ para APIs web. -Esse tipo de assincronicidade Ê o que fez NodeJS popular (embora NodeJS nÃŖo seja paralelo) e que essa seja a força do Go como uma linguagem de programa. +Esse tipo de assincronicidade Ê o que fez NodeJS popular (embora NodeJS nÃŖo seja paralelo) e essa Ê a força do Go como uma linguagem de programaÃ§ÃŖo. E esse Ê o mesmo nível de performance que vocÃĒ tem com o **FastAPI**. -E como vocÃĒ pode ter paralelismo e sincronicidade ao mesmo tempo, vocÃĒ tem uma maior performance do que a maioria dos frameworks NodeJS testados e lado a lado com Go, que Ê uma linguagem compilada prÃŗxima ao C (tudo graças ao Starlette). +E como vocÃĒ pode ter paralelismo e assincronicidade ao mesmo tempo, vocÃĒ tem uma maior performance do que a maioria dos frameworks NodeJS testados e lado a lado com Go, que Ê uma linguagem compilada, mais prÃŗxima ao C (tudo graças ao Starlette). ### ConcorrÃĒncia Ê melhor que paralelismo? @@ -225,64 +223,64 @@ ConcorrÃĒncia Ê diferente de paralelismo. E Ê melhor em cenÃĄrios **específic EntÃŖo, para equilibrar tudo, imagine a seguinte historinha: -> VocÃĒ tem que limpar uma grande casa suja. +> VocÃĒ tem que limpar uma casa grande e suja. *Sim, essa Ê toda a histÃŗria*. --- -NÃŖo hÃĄ espera em lugar algum, apenas um monte de trabalho para ser feito, em mÃēltiplos cômodos da casa. +NÃŖo hÃĄ espera 🕙 em lugar algum, apenas um monte de trabalho para ser feito, em mÃēltiplos cômodos da casa. -VocÃĒ poderia ter chamadas como no exemplo dos hambÃērgueres, primeiro a sala de estar, entÃŖo a cozinha, mas vocÃĒ nÃŖo estÃĄ esperando por nada, apenas limpar e limpar, as chamadas nÃŖo afetariam em nada. +VocÃĒ poderia ter turnos como no exemplo dos hambÃērgueres, primeiro a sala de estar, entÃŖo a cozinha, mas como vocÃĒ nÃŖo estÃĄ esperando por nada, apenas limpando e limpando, as chamadas nÃŖo afetariam em nada. -Levaria o mesmo tempo para finalizar com ou sem chamadas (concorrÃĒncia) e vocÃĒ teria feito o mesmo tanto de trabalho. +Levaria o mesmo tempo para finalizar com ou sem turnos (concorrÃĒncia) e vocÃĒ teria feito o mesmo tanto de trabalho. Mas nesse caso, se vocÃĒ trouxesse os 8 ex-caixas / cozinheiros / agora-faxineiros, e cada um deles (mais vocÃĒ) pudessem dividir a casa para limpÃĄ-la, vocÃĒs fariam toda a limpeza em **paralelo**, com a ajuda extra, e terminariam muito mais cedo. Nesse cenÃĄrio, cada um dos faxineiros (incluindo vocÃĒ) poderia ser um processador, fazendo a sua parte do trabalho. -E a maior parte do tempo de execuÃ§ÃŖo Ê tomada por trabalho (ao invÊs de ficar esperando), e o trabalho em um computador Ê feito pela CPU, que podem gerar problemas que sÃŖo chamados de "limite de CPU". +E a maior parte do tempo de execuÃ§ÃŖo Ê tomada por trabalho real (ao invÊs de ficar esperando), e o trabalho em um computador Ê feito pela CPU. Eles chamam esses problemas de "limitados por CPU". --- -Exemplos comuns de limite de CPU sÃŖo coisas que exigem processamento matemÃĄtico complexo. +Exemplos comuns de operaçÃĩes limitadas por CPU sÃŖo coisas que exigem processamento matemÃĄtico complexo. Por exemplo: * **Processamento de ÃĄudio** ou **imagem** -* **VisÃŖo do Computador**: uma imagem Ê composta por milhÃĩes de pixels, cada pixel tem 3 valores (cores, processamento que normalmente exige alguma computaÃ§ÃŖo em todos esses pixels ao mesmo tempo) +* **VisÃŖo Computacional**: uma imagem Ê composta por milhÃĩes de pixels, cada pixel tem 3 valores / cores, processar isso normalmente exige alguma computaÃ§ÃŖo em todos esses pixels ao mesmo tempo -* **Machine Learning**: Normalmente exige muita multiplicaÃ§ÃŖo de matrizes e vetores. Pense numa grande folha de papel com nÃēmeros e multiplicando todos eles juntos e ao mesmo tempo. +* **Machine Learning**: Normalmente exige muita multiplicaÃ§ÃŖo de matrizes e vetores. Pense numa grande planilha com nÃēmeros e em multiplicar todos eles juntos e ao mesmo tempo. -* **Deep Learning**: Esse Ê um subcampo do Machine Learning, entÃŖo o mesmo se aplica. A diferença Ê que nÃŖo hÃĄ apenas uma grande folha de papel com nÃēmeros para multiplicar, mas um grande conjunto de folhas de papel, e em muitos casos, vocÃĒ utiliza um processador especial para construir e/ou usar modelos. +* **Deep Learning**: Esse Ê um subcampo do Machine Learning, entÃŖo, o mesmo se aplica. A diferença Ê que nÃŖo hÃĄ apenas uma grande planilha com nÃēmeros para multiplicar, mas um grande conjunto delas, e em muitos casos, vocÃĒ utiliza um processador especial para construir e/ou usar esses modelos. ### ConcorrÃĒncia + Paralelismo: Web + Machine learning Com **FastAPI** vocÃĒ pode levar a vantagem da concorrÃĒncia que Ê muito comum para desenvolvimento web (o mesmo atrativo de NodeJS). -Mas vocÃĒ tambÊm pode explorar os benefícios do paralelismo e multiprocessamento (tendo mÃēltiplos processadores rodando em paralelo) para trabalhos pesados que geram **limite de CPU** como aqueles em sistemas de Machine Learning. +Mas vocÃĒ tambÊm pode explorar os benefícios do paralelismo e multiprocessamento (tendo mÃēltiplos processadores rodando em paralelo) para trabalhos **limitados por CPU** como aqueles em sistemas de Machine Learning. -Isso, mais o simples fato que Python Ê a principal linguagem para **Data Science**, Machine Learning e especialmente Deep Learning, faz do FastAPI uma Ãŗtima escolha para APIs web e aplicaçÃĩes com Data Science / Machine Learning (entre muitas outras). +Isso, somado ao simples fato que Python Ê a principal linguagem para **Data Science**, Machine Learning e especialmente Deep Learning, faz do FastAPI uma Ãŗtima escolha para APIs web e aplicaçÃĩes com Data Science / Machine Learning (entre muitas outras). Para ver como alcançar esse paralelismo em produÃ§ÃŖo veja a seÃ§ÃŖo sobre [Deployment](deployment/index.md){.internal-link target=_blank}. ## `async` e `await` -VersÃĩes modernas do Python tem um modo muito intuitivo para definir cÃŗdigo assíncrono. Isso faz parecer normal o cÃŗdigo "sequencial" e fazer o "esperar" para vocÃĒ nos momentos certos. +VersÃĩes modernas do Python tÃĒm um modo muito intuitivo para definir cÃŗdigo assíncrono. Isso faz parecer do mesmo jeito do cÃŗdigo normal "sequencial" e fazer a "espera" para vocÃĒ nos momentos certos. -Quando tem uma operaÃ§ÃŖo que exigirÃĄ espera antes de dar os resultados e tem suporte para esses recursos Python, vocÃĒ pode escrever assim: +Quando tem uma operaÃ§ÃŖo que exigirÃĄ espera antes de dar os resultados e tem suporte para esses novos recursos do Python, vocÃĒ pode escrever assim: ```Python burgers = await get_burgers(2) ``` -A chave aqui Ê o `await`. Ele diz ao Python que ele tem que esperar por `get_burgers(2)` para finalizar suas coisas antes de armazenar os resultados em `burgers`. Com isso, o Python saberÃĄ que ele pode ir e fazer outras coisas nesse meio tempo (como receber outra requisiÃ§ÃŖo). +A chave aqui Ê o `await`. Ele diz ao Python que ele tem que esperar por `get_burgers(2)` finalizar suas coisas 🕙 antes de armazenar os resultados em `burgers`. Com isso, o Python saberÃĄ que ele pode ir e fazer outras coisas 🔀 ⏯ nesse meio tempo (como receber outra requisiÃ§ÃŖo). Para o `await` funcionar, tem que estar dentro de uma funÃ§ÃŖo que suporte essa assincronicidade. Para fazer isso, apenas declare a funÃ§ÃŖo com `async def`: ```Python hl_lines="1" async def get_burgers(number: int): - # Fazer alguma coisa assíncrona para criar os hambÃērgueres + # Faz alguma coisa assíncrona para criar os hambÃērgueres return burgers ``` @@ -295,9 +293,9 @@ def get_sequential_burgers(number: int): return burgers ``` -Com `async def`, o Python sabe que, dentro dessa funÃ§ÃŖo, tem que estar ciente das expressÃĩes `await`, e que isso pode "pausar" a execuÃ§ÃŖo dessa funÃ§ÃŖo, e poderÃĄ fazer outra coisa antes de voltar. +Com `async def`, o Python sabe que, dentro dessa funÃ§ÃŖo, ele deve estar ciente das expressÃĩes `await`, e que isso poderÃĄ "pausar" ⏸ a execuÃ§ÃŖo dessa funÃ§ÃŖo, e ir fazer outra coisa 🔀 antes de voltar. -Quando vocÃĒ quiser chamar uma funÃ§ÃŖo `async def`, vocÃĒ tem que "esperar". EntÃŖo, isso nÃŖo funcionarÃĄ: +Quando vocÃĒ quiser chamar uma funÃ§ÃŖo `async def`, vocÃĒ tem que "esperar" ela. EntÃŖo, isso nÃŖo funcionarÃĄ: ```Python # Isso nÃŖo irÃĄ funcionar, porquÃĒ get_burgers foi definido com: async def @@ -319,13 +317,24 @@ async def read_burgers(): VocÃĒ deve ter observado que `await` pode ser usado somente dentro de funçÃĩes definidas com `async def`. -Mas ao mesmo tempo, funçÃĩes definidas com `async def` tem que ser aguardadas. EntÃŖo, funçÃĩes com `async def` pdem ser chamadas somente dentro de funçÃĩes definidas com `async def` tambÊm. +Mas ao mesmo tempo, funçÃĩes definidas com `async def` tÃĒm que ser "aguardadas". EntÃŖo, funçÃĩes com `async def` pdem ser chamadas somente dentro de funçÃĩes definidas com `async def` tambÊm. EntÃŖo, sobre o ovo e a galinha, como vocÃĒ chama a primeira funÃ§ÃŖo async? Se vocÃĒ estivar trabalhando com **FastAPI** nÃŖo terÃĄ que se preocupar com isso, porquÃĒ essa "primeira" funÃ§ÃŖo serÃĄ a sua *funÃ§ÃŖo de operaÃ§ÃŖo de rota*, e o FastAPI saberÃĄ como fazer a coisa certa. -Mas se vocÃĒ quiser usar `async` / `await` sem FastAPI, verifique a documentaÃ§ÃŖo oficial Python. +Mas se vocÃĒ quiser usar `async` / `await` sem FastAPI, vocÃĒ tambÊm pode fazÃĒ-lo. + +### Escreva seu prÃŗprio cÃŗdigo assíncrono + +Starlette (e **FastAPI**) sÃŖo baseados no AnyIO, o que o torna compatível com ambos o asyncio da biblioteca padrÃŖo do Python, e o Trio. + +Em particular, vocÃĒ pode usar diretamente o AnyIO para seus casos de uso avançados de concorrÃĒncia que requerem padrÃĩes mais avançados no seu prÃŗprio cÃŗdigo. + +E atÊ se vocÃĒ nÃŖo estiver utilizando FastAPI, vocÃĒ tambÊm pode escrever suas prÃŗprias aplicaçÃĩes assíncronas com o AnyIO por ser altamente compatível e ganhar seus benefícios (e.g. *concorrÃĒncia estruturada*). + +Eu criei outra biblioteca em cima do AnyIO, como uma fina camada acima, para melhorar um pouco as anotaçÃĩes de tipo e obter melhor **autocompletar**, **erros de linha**, etc. Ela tambÊm possui uma introduÃ§ÃŖo amigÃĄvel e um tutorial para ajudar vocÃĒ a **entender** e escrever **seu prÃŗprio cÃŗdigo async**: Asyncer. Seria particularmente Ãētil se vocÃĒ precisar **combinar cÃŗdigo async com cÃŗdigo regular** (bloqueador/síncrono). + ### Outras formas de cÃŗdigo assíncrono @@ -337,25 +346,25 @@ Essa mesma sintaxe (ou quase a mesma) foi tambÊm incluída recentemente em vers Mas antes disso, controlar cÃŗdigo assíncrono era bem mais complexo e difícil. -Nas versÃĩes anteriores do Python, vocÃĒ poderia utilizar threads ou Gevent. Mas o cÃŗdigo Ê um pouco mais complexo de entender, debugar, e pensar sobre. +Nas versÃĩes anteriores do Python, vocÃĒ poderia utilizar threads ou Gevent. Mas o cÃŗdigo Ê bem mais complexo de entender, debugar, e pensar sobre. -Nas versÃĩes anteriores do NodeJS / Navegador JavaScript, vocÃĒ poderia utilizar "callbacks". O que leva ao inferno do callback. +Nas versÃĩes anteriores do NodeJS / Navegador JavaScript, vocÃĒ utilizaria "callbacks". O que leva ao inferno do callback. ## Corrotinas -**Corrotina** Ê apenas um jeito bonitinho para a coisa que Ê retornada de uma funÃ§ÃŖo `async def`. O Python sabe que Ê uma funÃ§ÃŖo que pode começar e terminar em algum ponto, mas que pode ser pausada internamente tambÊm, sempre que tiver um `await` dentro dela. +**Corrotina** Ê apenas um jeito bonitinho para a coisa que Ê retornada de uma funÃ§ÃŖo `async def`. O Python sabe que Ê algo como uma funÃ§ÃŖo, que pode começar e que vai terminar em algum ponto, mas que pode ser pausada ⏸ internamente tambÊm, sempre que tiver um `await` dentro dela. -Mas toda essa funcionalidade de cÃŗdigo assíncrono com `async` e `await` Ê muitas vezes resumida como "corrotina". É comparÃĄvel ao principal recurso chave do Go, a "Gorotina". +Mas toda essa funcionalidade de cÃŗdigo assíncrono com `async` e `await` Ê muitas vezes resumida como usando "corrotinas". É comparÃĄvel ao principal recurso chave do Go, a "Gorrotina". ## ConclusÃŖo -Vamos ver a mesma frase com o conteÃēdo cima: +Vamos ver a mesma frase de cima: -> VersÃĩes modernas do Python tem suporte para **"cÃŗdigo assíncrono"** usando algo chamado **"corrotinas"**, com sintaxe **`async` e `await`**. +> VersÃĩes modernas do Python tÃĒm suporte para **"cÃŗdigo assíncrono"** usando algo chamado **"corrotinas"**, com sintaxe **`async` e `await`**. -Isso pode fazer mais sentido agora. +Isso pode fazer mais sentido agora. ✨ -Tudo isso Ê o que deixa o FastAPI poderoso (atravÊs do Starlette) e que o faz ter uma performance impressionante. +Tudo isso Ê o que empodera o FastAPI (atravÊs do Starlette) e que o faz ter uma performance tÃŖo impressionante. ## Detalhes muito tÊcnicos @@ -365,25 +374,25 @@ VocÃĒ pode provavelmente pular isso. Esses sÃŖo detalhes muito tÊcnicos de como **FastAPI** funciona por baixo do capô. -Se vocÃĒ tem algum conhecimento tÊcnico (corrotinas, threads, blocking etc) e estÃĄ curioso sobre como o FastAPI controla o `async def` vs normal `def`, vÃĄ em frente. +Se vocÃĒ tem certo conhecimento tÊcnico (corrotinas, threads, blocking etc) e estÃĄ curioso sobre como o FastAPI controla o `async def` vs normal `def`, vÃĄ em frente. /// ### FunçÃĩes de operaÃ§ÃŖo de rota -Quando vocÃĒ declara uma *funÃ§ÃŖo de operaÃ§ÃŖo de rota* com `def` normal ao invÊs de `async def`, ela Ê rodada em uma threadpool externa que entÃŖo Ê aguardada, ao invÊs de ser chamada diretamente (ela poderia bloquear o servidor). +Quando vocÃĒ declara uma *funÃ§ÃŖo de operaÃ§ÃŖo de rota* com `def` normal ao invÊs de `async def`, ela Ê rodada em uma threadpool externa que Ê entÃŖo aguardada, ao invÊs de ser chamada diretamente (jÃĄ que ela bloquearia o servidor). -Se vocÃĒ estÃĄ chegando de outro framework assíncrono que nÃŖo faz o trabalho descrito acima e vocÃĒ estÃĄ acostumado a definir triviais *funçÃĩes de operaÃ§ÃŖo de rota* com simples `def` para ter um mínimo ganho de performance (cerca de 100 nanosegundos), por favor observe que no **FastAPI** o efeito pode ser bem o oposto. Nesses casos, Ê melhor usar `async def` a menos que suas *funçÃĩes de operaÃ§ÃŖo de rota* utilizem cÃŗdigo que performem bloqueamento IO. +Se vocÃĒ estÃĄ chegando de outro framework assíncrono que nÃŖo funciona como descrito acima e vocÃĒ estÃĄ acostumado a definir *funçÃĩes de operaÃ§ÃŖo de rota* triviais somente de computaÃ§ÃŖo com simples `def` para ter um mínimo ganho de performance (cerca de 100 nanosegundos), por favor observe que no **FastAPI** o efeito pode ser bem o oposto. Nesses casos, Ê melhor usar `async def` a menos que suas *funçÃĩes de operaÃ§ÃŖo de rota* utilizem cÃŗdigo que performe bloqueamento IO. -Ainda, em ambas as situaçÃĩes, as chances sÃŖo que o **FastAPI** serÃĄ [ainda mais rÃĄpido](index.md#performance){.internal-link target=_blank} do que (ou ao menos comparÃĄvel a) seus frameworks antecessores. +Ainda, em ambas as situaçÃĩes, as chances sÃŖo que o **FastAPI** [ainda serÃĄ mais rÃĄpido](index.md#performance){.internal-link target=_blank} do que (ou ao menos comparÃĄvel a) seu framework anterior. ### DependÃĒncias -O mesmo se aplica para as dependÃĒncias. Se uma dependÃĒncia tem as funçÃĩes com padrÃŖo `def` ao invÊs de `async def`, ela Ê rodada no threadpool externo. +O mesmo se aplica para as [dependÃĒncias](tutorial/dependencies/index.md){.internal-link target=_blank}. Se uma dependÃĒncia tem as funçÃĩes com padrÃŖo `def` ao invÊs de `async def`, ela Ê rodada no threadpool externo. ### Sub-dependÃĒncias -VocÃĒ pode ter mÃēltiplas dependÃĒncias e sub-dependÃĒncias exigindo uma a outra (como parÃĸmetros de definiçÃĩes de funçÃĩes), algumas delas podem ser criadas com `async def` e algumas com `def` normal. Isso ainda poderia funcionar, e aquelas criadas com `def` podem ser chamadas em uma thread externa ao invÊs de serem "aguardadas". +VocÃĒ pode ter mÃēltiplas dependÃĒncias e [sub-dependÃĒncias](tutorial/dependencies/sub-dependencies.md){.internal-link target=_blank} requisitando uma à outra (como parÃĸmetros de definiçÃĩes de funçÃĩes), algumas delas podem ser criadas com `async def` e algumas com `def` normal. Isso ainda funcionaria, e aquelas criadas com `def` normal seriam chamadas em uma thread externa (do threadpool) ao invÊs de serem "aguardadas". ### Outras funçÃĩes de utilidade @@ -395,6 +404,6 @@ Se sua funÃ§ÃŖo de utilidade Ê uma funÃ§ÃŖo normal com `def`, ela serÃĄ chamada --- -Novamente, esses sÃŖo detalhes muito tÊcnicos que provavelmente possam ser Ãēteis caso vocÃĒ esteja procurando por eles. +Novamente, esses sÃŖo detalhes muito tÊcnicos que provavelmente seriam Ãēteis caso vocÃĒ esteja procurando por eles. Caso contrÃĄrio, vocÃĒ deve ficar bem com as dicas da seÃ§ÃŖo acima: Com pressa?. diff --git a/docs/pt/docs/deployment/concepts.md b/docs/pt/docs/deployment/concepts.md index 8cf70d0b4..014ca3797 100644 --- a/docs/pt/docs/deployment/concepts.md +++ b/docs/pt/docs/deployment/concepts.md @@ -216,7 +216,7 @@ Este Processo de Gerenciador provavelmente seria o que escutaria na **porta** no Esses processos de trabalho seriam aqueles que executariam seu aplicativo, eles executariam os cÃĄlculos principais para receber uma **solicitaÃ§ÃŖo** e retornar uma **resposta**, e carregariam qualquer coisa que vocÃĒ colocasse em variÃĄveis ​​na RAM. - + E, claro, a mesma mÃĄquina provavelmente teria **outros processos** em execuÃ§ÃŖo, alÊm do seu aplicativo. diff --git a/docs/pt/docs/deployment/https.md b/docs/pt/docs/deployment/https.md index 9a13977ec..904d04eaa 100644 --- a/docs/pt/docs/deployment/https.md +++ b/docs/pt/docs/deployment/https.md @@ -14,38 +14,186 @@ Para aprender o bÃĄsico de HTTPS de uma perspectiva do usuÃĄrio, verifique SNI. - * Esta extensÃŖo SNI permite que um Ãēnico servidor (com um Ãēnico endereço IP) tenha vÃĄrios certificados HTTPS e atenda a vÃĄrios domínios / aplicativos HTTPS. - * Para que isso funcione, um Ãēnico componente (programa) em execuÃ§ÃŖo no servidor, ouvindo no endereço IP pÃēblico, deve ter todos os certificados HTTPS no servidor. -* Depois de obter uma conexÃŖo segura, o protocolo de comunicaÃ§ÃŖo ainda Ê HTTP. - * Os conteÃēdos sÃŖo criptografados, embora sejam enviados com o protocolo HTTP. + * No entanto, existe uma **soluÃ§ÃŖo** para isso. +* HÃĄ uma **extensÃŖo** para o protocolo **TLS** (aquele que lida com a criptografia no nível TCP, antes do HTTP) chamado **SNI**. + * Esta extensÃŖo SNI permite que um Ãēnico servidor (com um **Ãēnico endereço IP**) tenha **vÃĄrios certificados HTTPS** e atenda a **vÃĄrios domínios / aplicativos HTTPS**. + * Para que isso funcione, um **Ãēnico** componente (programa) em execuÃ§ÃŖo no servidor, ouvindo no **endereço IP pÃēblico**, deve ter **todos os certificados HTTPS** no servidor. +* **Depois** de obter uma conexÃŖo segura, o protocolo de comunicaÃ§ÃŖo **ainda Ê HTTP**. + * Os conteÃēdos sÃŖo **criptografados**, embora sejam enviados com o **protocolo HTTP**. -É uma prÃĄtica comum ter um programa/servidor HTTP em execuÃ§ÃŖo no servidor (mÃĄquina, host, etc.) e gerenciar todas as partes HTTPS: enviando as solicitaçÃĩes HTTP descriptografadas para o aplicativo HTTP real em execuÃ§ÃŖo no mesmo servidor (a aplicaÃ§ÃŖo **FastAPI**, neste caso), pegue a resposta HTTP do aplicativo, criptografe-a usando o certificado apropriado e envie-a de volta ao cliente usando HTTPS. Este servidor Ê frequentemente chamado de TLS Termination Proxy. +É uma prÃĄtica comum ter um **programa/servidor HTTP** em execuÃ§ÃŖo no servidor (mÃĄquina, host, etc.) e **gerenciar todas as partes HTTPS**: **recebendo as requisiçÃĩes encriptadas**, enviando as **solicitaçÃĩes HTTP descriptografadas** para o aplicativo HTTP real em execuÃ§ÃŖo no mesmo servidor (a aplicaÃ§ÃŖo **FastAPI**, neste caso), pegue a **resposta HTTP** do aplicativo, **criptografe-a** usando o **certificado HTTPS** apropriado e envie-a de volta ao cliente usando **HTTPS**. Este servidor Ê frequentemente chamado de **Proxy de TerminaÃ§ÃŖo TLS**. + +Algumas das opçÃĩes que vocÃĒ pode usar como Proxy de TerminaÃ§ÃŖo TLS sÃŖo: + +* Traefik (que tambÊm pode gerenciar a renovaÃ§ÃŖo de certificados) +* Caddy (que tambÊm pode gerenciar a renovaÃ§ÃŖo de certificados) +* Nginx +* HAProxy ## Let's Encrypt -Antes de Let's Encrypt, esses certificados HTTPS eram vendidos por terceiros confiÃĄveis. +Antes de Let's Encrypt, esses **certificados HTTPS** eram vendidos por terceiros confiÃĄveis. O processo de aquisiÃ§ÃŖo de um desses certificados costumava ser complicado, exigia bastante papelada e os certificados eram bastante caros. -Mas entÃŖo Let's Encrypt foi criado. +Mas entÃŖo o **Let's Encrypt** foi criado. -Ele Ê um projeto da Linux Foundation que fornece certificados HTTPS gratuitamente. De forma automatizada. Esses certificados usam toda a segurança criptogrÃĄfica padrÃŖo e tÃĒm vida curta (cerca de 3 meses), entÃŖo a segurança Ê realmente melhor por causa de sua vida Ãētil reduzida. +Ele Ê um projeto da Linux Foundation que fornece **certificados HTTPS gratuitamente** . De forma automatizada. Esses certificados usam toda a segurança criptogrÃĄfica padrÃŖo e tÃĒm vida curta (cerca de 3 meses), entÃŖo a **segurança Ê, na verdade, melhor** por causa de sua vida Ãētil reduzida. Os domínios sÃŖo verificados com segurança e os certificados sÃŖo gerados automaticamente. Isso tambÊm permite automatizar a renovaÃ§ÃŖo desses certificados. -A ideia Ê automatizar a aquisiÃ§ÃŖo e renovaÃ§ÃŖo desses certificados, para que vocÃĒ tenha HTTPS seguro, de graça e para sempre. +A ideia Ê automatizar a aquisiÃ§ÃŖo e renovaÃ§ÃŖo desses certificados, para que vocÃĒ tenha **HTTPS seguro, de graça e para sempre**. + +## HTTPS para Desenvolvedores + +Aqui estÃĄ um exemplo de como uma API HTTPS poderia ser estruturada, passo a passo, com foco principal nas ideias relevantes para desenvolvedores. + +### Nome do domínio + +A etapa inicial provavelmente seria **adquirir** algum **nome de domínio**. EntÃŖo, vocÃĒ iria configurÃĄ-lo em um servidor DNS (possivelmente no mesmo provedor em nuvem). + +VocÃĒ provavelmente usaria um servidor em nuvem (mÃĄquina virtual) ou algo parecido, e ele teria fixed **Endereço IP pÃēblico**. + +No(s) servidor(es) DNS, vocÃĒ configuraria um registro (`registro A`) para apontar **seu domínio** para o **endereço IP pÃēblico do seu servidor**. + +VocÃĒ provavelmente farÃĄ isso apenas uma vez, na primeira vez em que tudo estiver sendo configurado. + +/// tip | Dica + +Essa parte do Nome do Domínio se dÃĄ muito antes do HTTPS, mas como tudo depende do domínio e endereço IP pÃēblico, vale a pena mencionÃĄ-la aqui. + +/// + +### DNS + +Agora vamos focar em todas as partes que realmente fazem parte do HTTPS. + +Primeiro, o navegador iria verificar com os **servidores DNS** qual o **IP do domínio**, nesse caso, `someapp.example.com`. + +Os servidores DNS iriam informar o navegador para utilizar algum **endereço IP** específico. Esse seria o endereço IP pÃēblico em uso no seu servidor, que vocÃĒ configurou nos servidores DNS. + + + +### Início do Handshake TLS + +O navegador entÃŖo irÃĄ comunicar-se com esse endereço IP na **porta 443** (a porta HTTPS). + +A primeira parte dessa comunicaÃ§ÃŖo Ê apenas para estabelecer a conexÃŖo entre o cliente e o servidor e para decidir as chaves criptogrÃĄficas a serem utilizadas, etc. + + + +Esse interaÃ§ÃŖo entre o cliente e o servidor para estabelecer uma conexÃŖo TLS Ê chamada de **Handshake TLS**. + +### TLS com a ExtensÃŖo SNI + +**Apenas um processo** no servidor pode se conectar a uma **porta** em um **endereço IP**. Poderiam existir outros processos conectados em outras portas desse mesmo endereço IP, mas apenas um para cada combinaÃ§ÃŖo de endereço IP e porta. + +TLS (HTTPS) usa a porta `443` por padrÃŖo. EntÃŖo essa Ê a porta que precisamos. + +Como apenas um Ãēnico processo pode se comunicar com essa porta, o processo que faria isso seria o **Proxy de TerminaÃ§ÃŖo TLS**. + +O Proxy de TerminaÃ§ÃŖo TLS teria acesso a um ou mais **certificados TLS** (certificados HTTPS). + +Utilizando a **extensÃŖo SNI** discutida acima, o Proxy de TerminaÃ§ÃŖo TLS iria checar qual dos certificados TLS (HTTPS) disponíveis deve ser usado para essa conexÃŖo, utilizando o que corresponda ao domínio esperado pelo cliente. + +Nesse caso, ele usaria o certificado para `someapp.example.com`. + + + +O cliente jÃĄ **confia** na entidade que gerou o certificado TLS (nesse caso, o Let's Encrypt, mas veremos sobre isso mais tarde), entÃŖo ele pode **verificar** que o certificado Ê vÃĄlido. + +EntÃŖo, utilizando o certificado, o cliente e o Proxy de TerminaÃ§ÃŖo TLS **decidem como encriptar** o resto da **comunicaÃ§ÃŖo TCP**. Isso completa a parte do **Handshake TLS**. + +ApÃŗs isso, o cliente e o servidor possuem uma **conexÃŖo TCP encriptada**, que Ê provida pelo TLS. E entÃŖo eles podem usar essa conexÃŖo para começar a **comunicaÃ§ÃŖo HTTP** propriamente dita. + +E isso resume o que Ê **HTTPS**, apenas **HTTP** simples dentro de uma **conexÃŖo TLS segura** em vez de uma conexÃŖo TCP pura (nÃŖo encriptada). + +/// tip | Dica + +Percebe que a encriptaÃ§ÃŖo da comunicaÃ§ÃŖo acontece no **nível do TCP**, nÃŖo no nível do HTTP. + +/// + +### SolicitaÃ§ÃŖo HTTPS + +Agora que o cliente e servidor (especialmente o navegador e o Proxy de TerminaÃ§ÃŖo TLS) possuem uma **conexÃŖo TCP encriptada**, eles podem iniciar a **comunicaÃ§ÃŖo HTTP**. + +EntÃŖo, o cliente envia uma **solicitaÃ§ÃŖo HTTPS**. Que Ê apenas uma solicitaÃ§ÃŖo HTTP sobre uma conexÃŖo TLS encriptada. + + + +### Desencriptando a SolicitaÃ§ÃŖo + +O Proxy de TerminaÃ§ÃŖo TLS entÃŖo usaria a encriptaÃ§ÃŖo combinada para **desencriptar a solicitaÃ§ÃŖo**, e transmitiria a **solicitaÃ§ÃŖo bÃĄsica (desencriptada)** para o processo executando a aplicaÃ§ÃŖo (por exemplo, um processo com Uvicorn executando a aplicaÃ§ÃŖo FastAPI). + + + +### Resposta HTTP + +A aplicaÃ§ÃŖo processaria a solicitaÃ§ÃŖo e retornaria uma **resposta HTTP bÃĄsica (nÃŖo encriptada)** para o Proxy de TerminaÃ§ÃŖo TLS. + + + +### Resposta HTTPS + +O Proxy de TerminaÃ§ÃŖo TLS iria **encriptar a resposta** utilizando a criptografia combinada anteriormente (que foi definida com o certificado para `someapp.example.com`), e devolveria para o navegador. + +No prÃŗximo passo, o navegador verifica que a resposta Ê vÃĄlida e encriptada com a chave criptogrÃĄfica correta, etc. E depois **desencripta a resposta** e a processa. + + + +O cliente (navegador) saberÃĄ que a resposta vem do servidor correto por que ela usa a criptografia que foi combinada entre eles usando o **certificado HTTPS** anterior. + +### MÃēltiplas AplicaçÃĩes + +Podem existir **mÃēltiplas aplicaçÃĩes** em execuÃ§ÃŖo no mesmo servidor (ou servidores), por exemplo: outras APIs ou um banco de dados. + +Apenas um processo pode estar vinculado a um IP e porta (o Proxy de TerminaÃ§ÃŖo TLS, por exemplo), mas outras aplicaçÃĩes/processos tambÊm podem estar em execuÃ§ÃŖo no(s) servidor(es), desde que nÃŖo tentem usar a mesma **combinaÃ§ÃŖo de IP pÃēblico e porta**. + + + +Dessa forma, o Proxy de TerminaÃ§ÃŖo TLS pode gerenciar o HTTPS e os certificados de **mÃēltiplos domínios**, para mÃēltiplas aplicaçÃĩes, e entÃŖo transmitir as requisiçÃĩes para a aplicaÃ§ÃŖo correta em cada caso. + +### RenovaÃ§ÃŖo de Certificados + +Em algum momento futuro, cada certificado irÃĄ **expirar** (aproximadamente 3 meses apÃŗs a aquisiÃ§ÃŖo). + +E entÃŖo, haverÃĄ outro programa (em alguns casos pode ser o prÃŗprio Proxy de TerminaÃ§ÃŖo TLS) que irÃĄ interagir com o Let's Encrypt e renovar o(s) certificado(s). + + + +Os **certificados TLS** sÃŖo **associados com um nome de domínio**, e nÃŖo a um endereço IP. + +EntÃŖo para renovar os certificados, o programa de renovaÃ§ÃŖo precisa **provar** para a autoridade (Let's Encrypt) que ele realmente **possui e controla esse domínio**> + +Para fazer isso, e acomodar as necessidades de diferentes aplicaçÃĩes, existem diferentes opçÃĩes para esse programa. Algumas escolhas populares sÃŖo: + +* **Modificar alguns registros DNS** + * Para isso, o programa de renovaÃ§ÃŖo precisa ter suporte as APIs do provedor DNS, entÃŖo, dependendo do provedor DNS que vocÃĒ utilize, isso pode ou nÃŖo ser uma opÃ§ÃŖo viÃĄvel. +* **Executar como um servidor** (ao menos durante o processo de aquisiÃ§ÃŖo do certificado) no endereço IP pÃēblico associado com o domínio. + * Como dito anteriormente, apenas um processo pode estar ligado a uma porta e IP específicos. + * Essa Ê uma dos motivos que fazem utilizar o mesmo Proxy de TerminaÃ§ÃŖo TLS para gerenciar a renovaÃ§ÃŖo de certificados ser tÃŖo Ãētil. + * Caso contrÃĄrio, vocÃĒ pode ter que parar a execuÃ§ÃŖo do Proxy de TerminaÃ§ÃŖo TLS momentaneamente, inicializar o programa de renovaÃ§ÃŖo para renovar os certificados, e entÃŖo reiniciar o Proxy de TerminaÃ§ÃŖo TLS. Isso nÃŖo Ê o ideal, jÃĄ que sua(s) aplicaÃ§ÃŖo(Ãĩes) nÃŖo vÃŖo estar disponíveis enquanto o Proxy de TerminaÃ§ÃŖo TLS estiver desligado. + +Todo esse processo de renovaÃ§ÃŖo, enquanto o aplicativo ainda funciona, Ê uma das principais razÃĩes para preferir um **sistema separado para gerenciar HTTPS** com um Proxy de TerminaÃ§ÃŖo TLS em vez de usar os certificados TLS no servidor da aplicaÃ§ÃŖo diretamente (e.g. com o Uvicorn). + +## Recapitulando + +Possuir **HTTPS** habilitado na sua aplicaÃ§ÃŖo Ê bastante importante, e atÊ **crítico** na maioria dos casos. A maior parte do esforço que vocÃĒ tem que colocar sobre o HTTPS como desenvolvedor estÃĄ em **entender esses conceitos** e como eles funcionam. + +Mas uma vez que vocÃĒ saiba o bÃĄsico de **HTTPS para desenvolvedores**, vocÃĒ pode combinar e configurar diferentes ferramentas facilmente para gerenciar tudo de uma forma simples. + +Em alguns dos prÃŗximos capítulos, eu mostrarei para vocÃĒ vÃĄrios exemplos concretos de como configurar o **HTTPS** para aplicaçÃĩes **FastAPI**. 🔒 diff --git a/docs/pt/docs/how-to/custom-docs-ui-assets.md b/docs/pt/docs/how-to/custom-docs-ui-assets.md index 3adc7529e..b7de6c8bd 100644 --- a/docs/pt/docs/how-to/custom-docs-ui-assets.md +++ b/docs/pt/docs/how-to/custom-docs-ui-assets.md @@ -98,7 +98,7 @@ VocÃĒ provavelmente pode clicar com o botÃŖo direito em cada link e selecionar u E o **ReDoc** usa os arquivos: -* `redoc.standalone.js` +* `redoc.standalone.js` Depois disso, sua estrutura de arquivos deve se parecer com: @@ -129,14 +129,8 @@ VocÃĒ deverÃĄ ver um arquivo JavaScript muito longo para o **ReDoc**. Esse arquivo pode começar com algo como: ```JavaScript -/*! - * ReDoc - OpenAPI/Swagger-generated API Reference Documentation - * ------------------------------------------------------------- - * Version: "2.0.0-rc.18" - * Repo: https://github.com/Redocly/redoc - */ -!function(e,t){"object"==typeof exports&&"object"==typeof m - +/*! For license information please see redoc.standalone.js.LICENSE.txt */ +!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("null")): ... ``` diff --git a/docs/pt/docs/index.md b/docs/pt/docs/index.md index bc23114dc..9f08d5224 100644 --- a/docs/pt/docs/index.md +++ b/docs/pt/docs/index.md @@ -11,15 +11,18 @@ Framework FastAPI, alta performance, fÃĄcil de aprender, fÃĄcil de codar, pronto para produÃ§ÃŖo

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

--- @@ -60,7 +63,7 @@ Os recursos chave sÃŖo: -Outros patrocinadores +Outros patrocinadores ## OpiniÃĩes @@ -70,6 +73,18 @@ Os recursos chave sÃŖo: --- +"_NÃŗs adotamos a biblioteca **FastAPI** para iniciar um servidor **REST** que pode ser consultado para obter **previsÃĩes**. [para o Ludwig]_" + +
Piero Molino, Yaroslav Dudin, e Sai Sumanth Miryala - Uber (ref)
+ +--- + +"_A **Netflix** tem o prazer de anunciar o lançamento open-source do nosso framework de orquestraÃ§ÃŖo de **gerenciamento de crises**: **Dispatch**! [criado com **FastAPI**]_" + +
Kevin Glisson, Marc Vilanova, Forest Monsen - Netflix (ref)
+ +--- + "*Estou extremamente entusiasmado com o **FastAPI**. É tÃŖo divertido!*"
Brian Okken - Python Bytes podcaster (ref)
@@ -90,9 +105,9 @@ Os recursos chave sÃŖo: --- -"*NÃŗs adotamos a biblioteca **FastAPI** para criar um servidor **REST** que possa ser chamado para obter **prediçÃĩes**. [para o Ludwig]*" +"_Se alguÊm estiver procurando construir uma API Python para produÃ§ÃŖo, eu recomendaria fortemente o **FastAPI**. Ele Ê **lindamente projetado**, **simples de usar** e **altamente escalÃĄvel**. Ele se tornou um **componente chave** para a nossa estratÊgia API first de desenvolvimento e estÃĄ impulsionando diversas automaçÃĩes e serviços, como o nosso Virtual TAC Engineer._" -
Piero Molino, Yaroslav Dudin e Sai Sumanth Miryala - Uber (ref)
+
Deon Pillsbury - Cisco (ref)
--- @@ -113,28 +128,20 @@ FastAPI estÃĄ nos ombros de gigantes: ## InstalaÃ§ÃŖo -
- -```console -$ pip install fastapi - ----> 100% -``` - -
- -VocÃĒ tambÊm precisarÃĄ de um servidor ASGI para produÃ§ÃŖo, tal como Uvicorn ou Hypercorn. +Crie e ative um ambiente virtual, e entÃŖo instale o FastAPI:
```console -$ pip install "uvicorn[standard]" +$ pip install "fastapi[standard]" ---> 100% ```
+**Nota**: Certifique-se de que vocÃĒ colocou `"fastapi[standard]"` com aspas, para garantir que funcione em todos os terminais. + ## Exemplo ### Crie @@ -184,7 +191,7 @@ async def read_item(item_id: int, q: Union[str, None] = None): **Nota**: -Se vocÃĒ nÃŖo sabe, verifique a seÃ§ÃŖo _"In a hurry?"_ sobre `async` e `await` nas docs. +Se vocÃĒ nÃŖo sabe, verifique a seÃ§ÃŖo _"Com pressa?"_ sobre `async` e `await` nas docs. @@ -195,11 +202,24 @@ Rode o servidor com:
```console -$ uvicorn main:app --reload - +$ fastapi dev main.py + + ╭────────── FastAPI CLI - Development mode ───────────╮ + │ │ + │ Serving at: http://127.0.0.1:8000 │ + │ │ + │ API docs: http://127.0.0.1:8000/docs │ + │ │ + │ Running in development mode, for production use: │ + │ │ + │ fastapi run │ + │ │ + ╰─────────────────────────────────────────────────────╯ + +INFO: Will watch for changes in these directories: ['/home/user/code/awesomeapp'] INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) -INFO: Started reloader process [28720] -INFO: Started server process [28722] +INFO: Started reloader process [2248755] using WatchFiles +INFO: Started server process [2248757] INFO: Waiting for application startup. INFO: Application startup complete. ``` @@ -207,13 +227,13 @@ INFO: Application startup complete.
-Sobre o comando uvicorn main:app --reload... +Sobre o comando fastapi dev main.py... -O comando `uvicorn main:app` se refere a: +O comando `fastapi dev` lÃĒ o seu arquivo `main.py`, identifica o aplicativo **FastAPI** nele, e inicia um servidor usando o Uvicorn. -* `main`: o arquivo `main.py` (o "mÃŗdulo" Python). -* `app`: o objeto criado dentro de `main.py` com a linha `app = FastAPI()`. -* `--reload`: faz o servidor recarregar apÃŗs mudanças de cÃŗdigo. Somente faça isso para desenvolvimento. +Por padrÃŖo, o `fastapi dev` iniciarÃĄ com *auto-reload* habilitado para desenvolvimento local. + +VocÃĒ pode ler mais sobre isso na documentaÃ§ÃŖo do FastAPI CLI.
@@ -268,7 +288,7 @@ app = FastAPI() class Item(BaseModel): name: str price: float - is_offer: Union[bool] = None + is_offer: Union[bool, None] = None @app.get("/") @@ -286,7 +306,7 @@ def update_item(item_id: int, item: Item): return {"item_name": item.name, "item_id": item_id} ``` -O servidor deverÃĄ recarregar automaticamente (porquÃĒ vocÃĒ adicionou `--reload` ao comando `uvicorn` acima). +O servidor `fastapi dev` deverÃĄ recarregar automaticamente. ### Evoluindo a DocumentaÃ§ÃŖo Interativa da API @@ -316,7 +336,7 @@ E agora, vÃĄ para Tutorial - Guia do UsuÃĄrio. +Para um exemplo mais completo incluindo mais recursos, veja Tutorial - Guia do UsuÃĄrio. **Alerta de Spoiler**: o tutorial - guia do usuÃĄrio inclui: @@ -416,9 +436,9 @@ Para um exemplo mais completo incluindo mais recursos, veja InjeÃ§ÃŖo de DependÃĒncia**. * Segurança e autenticaÃ§ÃŖo, incluindo suporte para **OAuth2** com autenticaÃ§ÃŖo **JWT tokens** e **HTTP Basic**. * TÊcnicas mais avançadas (mas igualmente fÃĄceis) para declaraÃ§ÃŖo de **modelos JSON profundamente aninhados** (graças ao Pydantic). +* IntegraçÃĩes **GraphQL** com o Strawberry e outras bibliotecas. * Muitos recursos extras (graças ao Starlette) como: * **WebSockets** - * **GraphQL** * testes extrememamente fÃĄceis baseados em HTTPX e `pytest` * **CORS** * **Cookie Sessions** @@ -428,30 +448,49 @@ Para um exemplo mais completo incluindo mais recursos, veja um dos _frameworks_ Python mais rÃĄpidos disponíveis, somente atrÃĄs de Starlette e Uvicorn (utilizados internamente pelo FastAPI). (*) -Para entender mais sobre performance, veja a seÃ§ÃŖo Benchmarks. +Para entender mais sobre performance, veja a seÃ§ÃŖo ComparaçÃĩes. + +## DependÃĒncias + +O FastAPI depende do Pydantic e do Starlette. + -## DependÃĒncias opcionais +### DependÃĒncias `standard` -Usados por Pydantic: +Quando vocÃĒ instala o FastAPI com `pip install "fastapi[standard]"`, ele vÃĒm com o grupo `standard` (padrÃŖo) de dependÃĒncias opcionais: + +Utilizado pelo Pydantic: * email-validator - para validaÃ§ÃŖo de email. -Usados por Starlette: +Utilizado pelo Starlette: + +* httpx - ObrigatÃŗrio caso vocÃĒ queira utilizar o `TestClient`. +* jinja2 - ObrigatÃŗrio se vocÃĒ quer utilizar a configuraÃ§ÃŖo padrÃŖo de templates. +* python-multipart - ObrigatÃŗrio se vocÃĒ deseja suporte a "parsing" de formulÃĄrio, com `request.form()`. + +Utilizado pelo FastAPI / Starlette: + +* uvicorn - para o servidor que carrega e serve a sua aplicaÃ§ÃŖo. Isto inclui `uvicorn[standard]`, que inclui algumas dependÃĒncias (e.g. `uvloop`) necessÃĄrias para servir em alta performance. +* `fastapi-cli` - que disponibiliza o comando `fastapi`. + +### Sem as dependÃĒncias `standard` + +Se vocÃĒ nÃŖo deseja incluir as dependÃĒncias opcionais `standard`, vocÃĒ pode instalar utilizando `pip install fastapi` ao invÊs de `pip install "fastapi[standard]"`. + +### DpendÃĒncias opcionais adicionais + +Existem algumas dependÃĒncias adicionais que vocÃĒ pode querer instalar. -* httpx - NecessÃĄrio se vocÃĒ quiser utilizar o `TestClient`. -* jinja2 - NecessÃĄrio se vocÃĒ quiser utilizar a configuraÃ§ÃŖo padrÃŖo de templates. -* python-multipart - NecessÃĄrio se vocÃĒ quiser suporte com "parsing" de formulÃĄrio, com `request.form()`. -* itsdangerous - NecessÃĄrio para suporte a `SessionMiddleware`. -* pyyaml - NecessÃĄrio para suporte a `SchemaGenerator` da Starlette (vocÃĒ provavelmente nÃŖo precisarÃĄ disso com o FastAPI). -* graphene - NecessÃĄrio para suporte a `GraphQLApp`. +DependÃĒncias opcionais adicionais do Pydantic: -Usados por FastAPI / Starlette: +* pydantic-settings - para gerenciamento de configuraçÃĩes. +* pydantic-extra-types - tipos extras para serem utilizados com o Pydantic. -* uvicorn - para o servidor que carrega e serve sua aplicaÃ§ÃŖo. -* orjson - NecessÃĄrio se vocÃĒ quer utilizar `ORJSONResponse`. -* ujson - NecessÃĄrio se vocÃĒ quer utilizar `UJSONResponse`. +DependÃĒncias opcionais adicionais do FastAPI: -VocÃĒ pode instalar todas essas dependÃĒncias com `pip install fastapi[all]`. +* orjson - ObrigatÃŗrio se vocÃĒ deseja utilizar o `ORJSONResponse`. +* ujson - ObrigatÃŗrio se vocÃĒ deseja utilizar o `UJSONResponse`. ## Licença diff --git a/docs/pt/docs/project-generation.md b/docs/pt/docs/project-generation.md index e5c935fd2..e337ad762 100644 --- a/docs/pt/docs/project-generation.md +++ b/docs/pt/docs/project-generation.md @@ -1,84 +1,28 @@ -# GeraÃ§ÃŖo de Projetos - Modelo - -VocÃĒ pode usar um gerador de projetos para começar, por jÃĄ incluir configuraçÃĩes iniciais, segurança, banco de dados e os primeiros _endpoints_ API jÃĄ feitos para vocÃĒ. - -Um gerador de projetos sempre terÃĄ uma prÊ-configuraÃ§ÃŖo que vocÃĒ pode atualizar e adaptar para suas prÃŗprias necessidades, mas pode ser um bom ponto de partida para seu projeto. - -## Full Stack FastAPI PostgreSQL - -GitHub: https://github.com/tiangolo/full-stack-fastapi-postgresql - -### Full Stack FastAPI PostgreSQL - Recursos - -* IntegraÃ§ÃŖo completa **Docker**. -* Modo de implantaÃ§ÃŖo Docker Swarm. -* IntegraÃ§ÃŖo e otimizaÃ§ÃŖo **Docker Compose** para desenvolvimento local. -* **Pronto para ProduÃ§ÃŖo** com servidor _web_ usando Uvicorn e Gunicorn. -* _Backend_ **FastAPI** Python: - * **RÃĄpido**: Alta performance, no nível de **NodeJS** e **Go** (graças ao Starlette e Pydantic). - * **Intuitivo**: Ótimo suporte de editor. _Auto-Complete_ em todo lugar. Menos tempo _debugando_. - * **FÃĄcil**: Projetado para ser fÃĄcil de usar e aprender. Menos tempo lendo documentaçÃĩes. - * **Curto**: Minimize duplicaÃ§ÃŖo de cÃŗdigo. MÃēltiplos recursos para cada declaraÃ§ÃŖo de parÃĸmetro. - * **Robusto**: Tenha cÃŗdigo pronto para produÃ§ÃŖo. Com documentaÃ§ÃŖo interativa automÃĄtica. - * **Baseado em PadrÃĩes**: Baseado em (e completamente compatível com) padrÃĩes abertos para APIs: OpenAPI e JSON Schema. - * **Muitos outros recursos** incluindo validaÃ§ÃŖo automÃĄtica, serializaÃ§ÃŖo, documentaÃ§ÃŖo interativa, autenticaÃ§ÃŖo com _tokens_ OAuth2 JWT etc. -* **Senha segura** _hashing_ por padrÃŖo. -* AutenticaÃ§ÃŖo **Token JWT**. -* Modelos **SQLAlchemy** (independente de extensÃĩes Flask, para que eles possam ser usados com _workers_ Celery diretamente). -* Modelos bÃĄsicos para usuÃĄrios (modifique e remova conforme suas necessidades). -* MigraçÃĩes **Alembic**. -* **CORS** (_Cross Origin Resource Sharing_ - Compartilhamento de Recursos Entre Origens). -* _Worker_ **Celery** que pode importar e usar modelos e cÃŗdigos do resto do _backend_ seletivamente. -* Testes _backend_ _REST_ baseados no **Pytest**, integrados com Docker, entÃŖo vocÃĒ pode testar a interaÃ§ÃŖo completa da API, independente do banco de dados. Como roda no Docker, ele pode construir um novo repositÃŗrio de dados do zero toda vez (assim vocÃĒ pode usar ElasticSearch, MongoDB, CouchDB, ou o que quiser, e apenas testar que a API esteja funcionando). -* FÃĄcil integraÃ§ÃŖo com Python atravÊs dos **Kernels Jupyter** para desenvolvimento remoto ou no Docker com extensÃĩes como Atom Hydrogen ou Visual Studio Code Jupyter. -* _Frontend_ **Vue**: - * Gerado com Vue CLI. - * Controle de **AutenticaÃ§ÃŖo JWT**. - * VisualizaÃ§ÃŖo de _login_. - * ApÃŗs o _login_, visualizaÃ§ÃŖo do painel de controle principal. - * Painel de controle principal com criaÃ§ÃŖo e ediÃ§ÃŖo de usuÃĄrio. - * EdiÃ§ÃŖo do prÃŗprio usuÃĄrio. - * **Vuex**. - * **Vue-router**. - * **Vuetify** para belos componentes _material design_. - * **TypeScript**. - * Servidor Docker baseado em **Nginx** (configurado para rodar "lindamente" com Vue-router). - * ConstruÃ§ÃŖo multi-estÃĄgio Docker, entÃŖo vocÃĒ nÃŖo precisa salvar ou _commitar_ cÃŗdigo compilado. - * Testes _frontend_ rodados na hora da construÃ§ÃŖo (pode ser desabilitado tambÊm). - * Feito tÃŖo modular quanto possível, entÃŖo ele funciona fora da caixa, mas vocÃĒ pode gerar novamente com Vue CLI ou criar conforme vocÃĒ queira, e reutilizar o que quiser. -* **PGAdmin** para banco de dados PostgreSQL, vocÃĒ pode modificar para usar PHPMyAdmin e MySQL facilmente. -* **Flower** para monitoraÃ§ÃŖo de tarefas Celery. -* Balanceamento de carga entre _frontend_ e _backend_ com **Traefik**, entÃŖo vocÃĒ pode ter ambos sob o mesmo domínio, separados por rota, mas servidos por diferentes containers. -* IntegraÃ§ÃŖo Traefik, incluindo geraÃ§ÃŖo automÃĄtica de certificados **HTTPS** Let's Encrypt. -* GitLab **CI** (integraÃ§ÃŖo contínua), incluindo testes _frontend_ e _backend_. - -## Full Stack FastAPI Couchbase - -GitHub: https://github.com/tiangolo/full-stack-fastapi-couchbase - -âš ī¸ **WARNING** âš ī¸ - -Se vocÃĒ estÃĄ iniciando um novo projeto do zero, verifique as alternativas aqui. - -Por exemplo, o gerador de projetos Full Stack FastAPI PostgreSQL pode ser uma alternativa melhor, como ele Ê ativamente mantido e utilizado. E ele inclui todos os novos recursos e melhorias. - -VocÃĒ ainda Ê livre para utilizar o gerador baseado em Couchbase se quiser, ele provavelmente ainda funciona bem, e vocÃĒ jÃĄ tem um projeto gerado com ele que roda bem tambÊm (e vocÃĒ provavelmente jÃĄ atualizou ele para encaixar nas suas necessidades). - -VocÃĒ pode ler mais sobre nas documentaÃ§ÃŖoes do repositÃŗrio. - -## Full Stack FastAPI MongoDB - -...pode demorar, dependendo do meu tempo disponível e outros fatores. 😅 🎉 - -## Modelos de Aprendizado de MÃĄquina com spaCy e FastAPI - -GitHub: https://github.com/microsoft/cookiecutter-spacy-fastapi - -### Modelos de Aprendizado de MÃĄquina com spaCy e FastAPI - Recursos - -* IntegraÃ§ÃŖo com modelo NER **spaCy**. -* Formato de requisiÃ§ÃŖo **Busca Cognitiva Azure** acoplado. -* Servidor Python _web_ **Pronto para ProduÃ§ÃŖo** usando Uvicorn e Gunicorn. -* ImplantaÃ§ÃŖo **Azure DevOps** Kubernetes (AKS) CI/CD acoplada. -* **Multilingual** facilmente escolhido como uma das linguagens spaCy acopladas durante a configuraÃ§ÃŖo do projeto. -* **Facilmente extensível** para outros modelos de _frameworks_ (Pytorch, Tensorflow), nÃŖo apenas spaCy. +# Full Stack FastAPI Template + +_Templates_, embora tipicamente venham com alguma configuraÃ§ÃŖo específica, sÃŖo desenhados para serem flexíveis e customizÃĄveis. Isso permite que vocÃĒ os modifique e adapte para as especificaçÃĩes do seu projeto, fazendo-os um excelente ponto de partida. 🏁 + +VocÃĒ pode usar esse _template_ para começar, jÃĄ que ele inclui vÃĄrias configuraçÃĩes iniciais, segurança, banco de dados, e alguns _endpoints_ de API jÃĄ feitos para vocÃĒ. + +RepositÃŗrio GitHub: Full Stack FastAPI Template + +## Full Stack FastAPI Template - Pilha de Tecnologias e Recursos + +- ⚡ [**FastAPI**](https://fastapi.tiangolo.com) para a API do backend em Python. + - 🧰 [SQLModel](https://sqlmodel.tiangolo.com) para as interaçÃĩes do Python com bancos de dados SQL (ORM). + - 🔍 [Pydantic](https://docs.pydantic.dev), usado pelo FastAPI, para validaÃ§ÃŖo de dados e gerenciamento de configuraçÃĩes. + - 💾 [PostgreSQL](https://www.postgresql.org) como banco de dados SQL. +- 🚀 [React](https://react.dev) para o frontend. + - 💃 Usando TypeScript, hooks, [Vite](https://vitejs.dev), e outras partes de uma _stack_ frontend moderna. + - 🎨 [Chakra UI](https://chakra-ui.com) para os componentes de frontend. + - 🤖 Um cliente frontend automaticamente gerado. + - đŸ§Ē [Playwright](https://playwright.dev) para testes Ponta-a-Ponta. + - đŸĻ‡ Suporte para modo escuro. +- 🐋 [Docker Compose](https://www.docker.com) para desenvolvimento e produÃ§ÃŖo. +- 🔒 _Hash_ seguro de senhas por padrÃŖo. +- 🔑 AutenticaÃ§ÃŖo por token JWT. +- đŸ“Ģ RecuperaÃ§ÃŖo de senhas baseada em email. +- ✅ Testes com [Pytest](https://pytest.org). +- 📞 [Traefik](https://traefik.io) como proxy reverso / balanceador de carga. +- đŸšĸ InstruçÃĩes de _deployment_ usando Docker Compose, incluindo como configurar um proxy frontend com Traefik para gerenciar automaticamente certificados HTTPS. +- 🏭 CI (IntegraÃ§ÃŖo Contínua) e CD (_Deploy_ Contínuo) baseado em GitHub Actions. diff --git a/docs/pt/docs/tutorial/bigger-applications.md b/docs/pt/docs/tutorial/bigger-applications.md index a094005fd..b621f3c72 100644 --- a/docs/pt/docs/tutorial/bigger-applications.md +++ b/docs/pt/docs/tutorial/bigger-applications.md @@ -52,7 +52,7 @@ from app.routers import items * HÃĄ tambÊm um subdiretÃŗrio `app/internal/` com outro arquivo `__init__.py`, entÃŖo ele Ê outro "subpacote Python":`app.internal`. * E o arquivo `app/internal/admin.py` Ê outro submÃŗdulo: `app.internal.admin`. - + A mesma estrutura de arquivos com comentÃĄrios: @@ -270,7 +270,7 @@ Mas esse arquivo nÃŖo existe, nossas dependÃĒncias estÃŖo em um arquivo em `app/ Lembre-se de como nossa estrutura app/file se parece: - + --- diff --git a/docs/ru/docs/advanced/additional-status-codes.md b/docs/ru/docs/advanced/additional-status-codes.md new file mode 100644 index 000000000..aab1f8ee3 --- /dev/null +++ b/docs/ru/docs/advanced/additional-status-codes.md @@ -0,0 +1,41 @@ +# ДоĐŋĐžĐģĐŊĐ¸Ņ‚ĐĩĐģҌĐŊŅ‹Đĩ ŅŅ‚Đ°Ņ‚ŅƒŅ ĐēĐžĐ´Ņ‹ + +По ҃ĐŧĐžĐģŅ‡Đ°ĐŊĐ¸ŅŽ **FastAPI** Đ˛ĐžĐˇĐ˛Ņ€Đ°Ņ‰Đ°ĐĩŅ‚ ĐžŅ‚Đ˛Đĩ҂ҋ, Đ¸ŅĐŋĐžĐģŅŒĐˇŅƒŅ `JSONResponse`, ĐŋĐžĐŧĐĩŅ‰Đ°Ņ ŅĐžĐ´ĐĩŅ€ĐļиĐŧĐžĐĩ, ĐēĐžŅ‚ĐžŅ€ĐžĐĩ Đ˛Ņ‹ Đ˛ĐžĐˇĐ˛Ņ€Đ°Ņ‰Đ°ĐĩŅ‚Đĩ иС Đ˛Đ°ŅˆĐĩĐš *ĐžĐŋĐĩŅ€Đ°Ņ†Đ¸Đ¸ ĐŋŅƒŅ‚Đ¸*, вĐŊŅƒŅ‚Ņ€ŅŒ ŅŅ‚ĐžĐŗĐž `JSONResponse`. + +ОĐŊ ĐąŅƒĐ´ĐĩŅ‚ Đ¸ŅĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ŅŒ ĐēОд ŅŅ‚Đ°Ņ‚ŅƒŅĐ° ĐŋĐž ҃ĐŧĐžĐģŅ‡Đ°ĐŊĐ¸ŅŽ иĐģи Ņ‚ĐžŅ‚, ĐēĐžŅ‚ĐžŅ€Ņ‹Đš Đ˛Ņ‹ ҃ĐēаĐļĐĩŅ‚Đĩ в Đ˛Đ°ŅˆĐĩĐš *ĐžĐŋĐĩŅ€Đ°Ņ†Đ¸Đ¸ ĐŋŅƒŅ‚Đ¸*. + +## ДоĐŋĐžĐģĐŊĐ¸Ņ‚ĐĩĐģҌĐŊŅ‹Đĩ ŅŅ‚Đ°Ņ‚ŅƒŅ ĐēĐžĐ´Ņ‹ + +Đ•ŅĐģи Đ˛Ņ‹ Ņ…ĐžŅ‚Đ¸Ņ‚Đĩ Đ˛ĐžĐˇĐ˛Ņ€Đ°Ņ‰Đ°Ņ‚ŅŒ Đ´ĐžĐŋĐžĐģĐŊĐ¸Ņ‚ĐĩĐģҌĐŊŅ‹Đš ŅŅ‚Đ°Ņ‚ŅƒŅ ĐēОд ĐŋĐžĐŧиĐŧĐž ĐžŅĐŊОвĐŊĐžĐŗĐž, Đ˛Ņ‹ ĐŧĐžĐļĐĩŅ‚Đĩ ŅĐ´ĐĩĐģĐ°Ņ‚ŅŒ ŅŅ‚Đž, Đ˛ĐžĐˇĐ˛Ņ€Đ°Ņ‰Đ°Ņ ĐžĐąŅŠĐĩĐēŅ‚ `Response` ĐŊаĐŋŅ€ŅĐŧŅƒŅŽ, ĐēаĐē `JSONResponse`, и ŅƒŅŅ‚Đ°ĐŊавĐģĐ¸Đ˛Đ°Ņ ĐŊ҃ĐļĐŊŅ‹Đš ŅŅ‚Đ°Ņ‚ŅƒŅ ĐēОд ĐŊаĐŋŅ€ŅĐŧŅƒŅŽ. + +НаĐŋŅ€Đ¸ĐŧĐĩŅ€, ҁĐēаĐļĐĩĐŧ, Đ˛Ņ‹ Ņ…ĐžŅ‚Đ¸Ņ‚Đĩ ŅĐžĐˇĐ´Đ°Ņ‚ŅŒ *ĐžĐŋĐĩŅ€Đ°Ņ†Đ¸ŅŽ ĐŋŅƒŅ‚Đ¸*, ĐēĐžŅ‚ĐžŅ€Đ°Ņ ĐŋОСвОĐģŅĐĩŅ‚ ОйĐŊОвĐģŅŅ‚ŅŒ ŅĐģĐĩĐŧĐĩĐŊ҂ҋ и Đ˛ĐžĐˇĐ˛Ņ€Đ°Ņ‰Đ°ĐĩŅ‚ HTTP-ĐēОд 200 "OK" ĐŋŅ€Đ¸ ҃ҁĐŋĐĩ҈ĐŊĐžĐŧ Đ˛Ņ‹ĐŋĐžĐģĐŊĐĩĐŊии. + +Но Đ˛Ņ‹ Ņ‚Đ°ĐēĐļĐĩ Ņ…ĐžŅ‚Đ¸Ņ‚Đĩ, Ņ‡Ņ‚ĐžĐąŅ‹ ĐžĐŊа ĐŋŅ€Đ¸ĐŊиĐŧаĐģа ĐŊĐžĐ˛Ņ‹Đĩ ŅĐģĐĩĐŧĐĩĐŊ҂ҋ. И ĐĩҁĐģи ŅĐģĐĩĐŧĐĩĐŊŅ‚ Ņ€Đ°ĐŊĐĩĐĩ ĐŊĐĩ ŅŅƒŅ‰ĐĩŅŅ‚Đ˛ĐžĐ˛Đ°Đģ, ĐžĐŊ ŅĐžĐˇĐ´Đ°Ņ‘Ņ‚ŅŅ, и Đ˛ĐžĐˇĐ˛Ņ€Đ°Ņ‰Đ°ĐģŅŅ HTTP-ĐēОд 201 "Created". + +Đ§Ņ‚ĐžĐąŅ‹ Ņ€ĐĩаĐģĐ¸ĐˇĐžĐ˛Đ°Ņ‚ŅŒ ŅŅ‚Đž, иĐŧĐŋĐžŅ€Ņ‚Đ¸Ņ€ŅƒĐšŅ‚Đĩ `JSONResponse` и Đ˛ĐžĐˇĐ˛Ņ€Đ°Ņ‰Đ°ĐšŅ‚Đĩ Đ˛Đ°Ņˆ ĐēĐžĐŊŅ‚ĐĩĐŊŅ‚ ĐŊаĐŋŅ€ŅĐŧŅƒŅŽ, ŅƒŅŅ‚Đ°ĐŊавĐģĐ¸Đ˛Đ°Ņ ĐŊ҃ĐļĐŊŅ‹Đš `status_code`: + +{* ../../docs_src/additional_status_codes/tutorial001_an_py310.py hl[4,25] *} + +/// warning | ВĐŊиĐŧаĐŊиĐĩ + +ĐšĐžĐŗĐ´Đ° Đ˛Ņ‹ Đ˛ĐžĐˇĐ˛Ņ€Đ°Ņ‰Đ°ĐĩŅ‚Đĩ ĐžĐąŅŠĐĩĐēŅ‚ `Response` ĐŊаĐŋŅ€ŅĐŧŅƒŅŽ, ĐēаĐē в ĐŋŅ€Đ¸ĐŧĐĩŅ€Đĩ Đ˛Ņ‹ŅˆĐĩ, ĐžĐŊ ĐąŅƒĐ´ĐĩŅ‚ Đ˛ĐžĐˇĐ˛Ņ€Đ°Ņ‰Ņ‘ĐŊ ĐēаĐē ĐĩŅŅ‚ŅŒ. + +ОĐŊ ĐŊĐĩ ĐąŅƒĐ´ĐĩŅ‚ ҁĐĩŅ€Đ¸Đ°ĐģиСОваĐŊ ĐŋŅ€Đ¸ ĐŋĐžĐŧĐžŅ‰Đ¸ ĐŧОдĐĩĐģи и Ņ‚.Đ´. + +ĐŖĐąĐĩĐ´Đ¸Ņ‚ĐĩҁҌ, Ņ‡Ņ‚Đž в ĐŊŅ‘Đŧ ŅĐžĐ´ĐĩŅ€ĐļĐ°Ņ‚ŅŅ иĐŧĐĩĐŊĐŊĐž Ņ‚Đĩ даĐŊĐŊŅ‹Đĩ, ĐēĐžŅ‚ĐžŅ€Ņ‹Đĩ Đ˛Ņ‹ Ņ…ĐžŅ‚Đ¸Ņ‚Đĩ, и Ņ‡Ņ‚Đž СĐŊĐ°Ņ‡ĐĩĐŊĐ¸Ņ ŅĐ˛ĐģŅŅŽŅ‚ŅŅ ваĐģидĐŊŅ‹Đŧ JSON (ĐĩҁĐģи Đ˛Ņ‹ Đ¸ŅĐŋĐžĐģŅŒĐˇŅƒĐĩŅ‚Đĩ `JSONResponse`). + +/// + +/// note | ĐĸĐĩŅ…ĐŊĐ¸Ņ‡ĐĩҁĐēиĐĩ Đ´ĐĩŅ‚Đ°Đģи + +Đ’Ņ‹ Ņ‚Đ°ĐēĐļĐĩ ĐŧĐžĐļĐĩŅ‚Đĩ Đ¸ŅĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ŅŒ `from starlette.responses import JSONResponse`. + +**FastAPI** ĐŋŅ€ĐĩĐ´ĐžŅŅ‚Đ°Đ˛ĐģŅĐĩŅ‚ Ņ‚ĐžŅ‚ ĐļĐĩ `starlette.responses` ҇ĐĩŅ€ĐĩС `fastapi.responses` ĐŋŅ€ĐžŅŅ‚Đž Đ´ĐģŅ Đ˛Đ°ŅˆĐĩĐŗĐž ŅƒĐ´ĐžĐąŅŅ‚Đ˛Đ°, ĐēаĐē Ņ€Đ°ĐˇŅ€Đ°ĐąĐžŅ‚Ņ‡Đ¸Đēа. Но йОĐģŅŒŅˆĐ¸ĐŊŅŅ‚Đ˛Đž Đ´ĐžŅŅ‚ŅƒĐŋĐŊҋ҅ Response-ĐēĐģĐ°ŅŅĐžĐ˛ ĐŋĐžŅŅ‚ŅƒĐŋĐ°ŅŽŅ‚ ĐŊаĐŋŅ€ŅĐŧŅƒŅŽ иС Starlette. ĐĸĐž ĐļĐĩ ŅĐ°ĐŧĐžĐĩ ĐēĐ°ŅĐ°ĐĩŅ‚ŅŅ и `status`. + +/// + +## OpenAPI и Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Đ¸Ņ API + +Đ•ŅĐģи Đ˛Ņ‹ Đ˛ĐžĐˇĐ˛Ņ€Đ°Ņ‰Đ°ĐĩŅ‚Đĩ Đ´ĐžĐŋĐžĐģĐŊĐ¸Ņ‚ĐĩĐģҌĐŊŅ‹Đĩ ĐēĐžĐ´Ņ‹ ŅŅ‚Đ°Ņ‚ŅƒŅĐžĐ˛ и ĐžŅ‚Đ˛Đĩ҂ҋ ĐŊаĐŋŅ€ŅĐŧŅƒŅŽ, ĐžĐŊи ĐŊĐĩ ĐąŅƒĐ´ŅƒŅ‚ вĐēĐģŅŽŅ‡ĐĩĐŊŅ‹ в ҁ҅ĐĩĐŧ҃ OpenAPI (Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Đ¸ŅŽ API), ĐŋĐžŅ‚ĐžĐŧ҃ Ņ‡Ņ‚Đž FastAPI ĐŊĐĩ ĐŧĐžĐļĐĩŅ‚ ĐˇĐ°Ņ€Đ°ĐŊĐĩĐĩ СĐŊĐ°Ņ‚ŅŒ, Ņ‡Ņ‚Đž Đ˛Ņ‹ ŅĐžĐąĐ¸Ņ€Đ°ĐĩŅ‚ĐĩҁҌ вĐĩŅ€ĐŊŅƒŅ‚ŅŒ. + +Но Đ˛Ņ‹ ĐŧĐžĐļĐĩŅ‚Đĩ СадОĐē҃ĐŧĐĩĐŊŅ‚Đ¸Ņ€ĐžĐ˛Đ°Ņ‚ŅŒ ŅŅ‚Đž в Đ˛Đ°ŅˆĐĩĐŧ ĐēОдĐĩ, Đ¸ŅĐŋĐžĐģŅŒĐˇŅƒŅ: [ДоĐŋĐžĐģĐŊĐ¸Ņ‚ĐĩĐģҌĐŊŅ‹Đĩ ĐžŅ‚Đ˛Đĩ҂ҋ в OpenAPI](additional-responses.md){.internal-link target=_blank}. diff --git a/docs/ru/docs/advanced/index.md b/docs/ru/docs/advanced/index.md new file mode 100644 index 000000000..b5cb733e7 --- /dev/null +++ b/docs/ru/docs/advanced/index.md @@ -0,0 +1,21 @@ +# Đ Đ°ŅŅˆĐ¸Ņ€ĐĩĐŊĐŊĐžĐĩ Ņ€ŅƒĐēĐžĐ˛ĐžĐ´ŅŅ‚Đ˛Đž ĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ĐĩĐģŅ + +## ДоĐŋĐžĐģĐŊĐ¸Ņ‚ĐĩĐģҌĐŊŅ‹Đĩ вОСĐŧĐžĐļĐŊĐžŅŅ‚Đ¸ + +ĐžŅĐŊОвĐŊĐžĐĩ [ĐŖŅ‡ĐĩĐąĐŊиĐē - Đ ŅƒĐēĐžĐ˛ĐžĐ´ŅŅ‚Đ˛Đž ĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ĐĩĐģŅ](../tutorial/index.md){.internal-link target=_blank} Đ´ĐžĐģĐļĐŊĐž ĐąŅ‹Ņ‚ŅŒ Đ´ĐžŅŅ‚Đ°Ņ‚ĐžŅ‡ĐŊĐž, Ņ‡Ņ‚ĐžĐąŅ‹ ĐŋОСĐŊаĐēĐžĐŧĐ¸Ņ‚ŅŒ Đ˛Đ°Ņ ŅĐž Đ˛ŅĐĩĐŧи ĐžŅĐŊОвĐŊŅ‹Đŧи Ņ„ŅƒĐŊĐēŅ†Đ¸ŅĐŧи **FastAPI**. + +В ҁĐģĐĩĐ´ŅƒŅŽŅ‰Đ¸Ņ… Ņ€Đ°ĐˇĐ´ĐĩĐģĐ°Ņ… Đ˛Ņ‹ ŅƒĐ˛Đ¸Đ´Đ¸Ņ‚Đĩ Đ´Ņ€ŅƒĐŗĐ¸Đĩ Đ˛Đ°Ņ€Đ¸Đ°ĐŊ҂ҋ, ĐēĐžĐŊŅ„Đ¸ĐŗŅƒŅ€Đ°Ņ†Đ¸Đ¸ и Đ´ĐžĐŋĐžĐģĐŊĐ¸Ņ‚ĐĩĐģҌĐŊŅ‹Đĩ вОСĐŧĐžĐļĐŊĐžŅŅ‚Đ¸. + +/// tip + +ĐĄĐģĐĩĐ´ŅƒŅŽŅ‰Đ¸Đĩ Ņ€Đ°ĐˇĐ´ĐĩĐģŅ‹ **ĐŊĐĩ ĐžĐąŅĐˇĐ°Ņ‚ĐĩĐģҌĐŊĐž ŅĐ˛ĐģŅŅŽŅ‚ŅŅ "ĐŋŅ€ĐžĐ´Đ˛Đ¸ĐŊŅƒŅ‚Ņ‹Đŧи"**. + +И вĐŋĐžĐģĐŊĐĩ вОСĐŧĐžĐļĐŊĐž, Ņ‡Ņ‚Đž Đ´ĐģŅ Đ˛Đ°ŅˆĐĩĐŗĐž ҁĐģŅƒŅ‡Đ°Ņ Đ¸ŅĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°ĐŊĐ¸Ņ Ņ€Đĩ҈ĐĩĐŊиĐĩ ĐŊĐ°Ņ…ĐžĐ´Đ¸Ņ‚ŅŅ в ОдĐŊĐžĐŧ иС ĐŊĐ¸Ņ…. + +/// + +## ĐĄĐŊĐ°Ņ‡Đ°Đģа ĐŋŅ€ĐžŅ‡Đ¸Ņ‚Đ°ĐšŅ‚Đĩ ĐŖŅ‡ĐĩĐąĐŊиĐē - Đ ŅƒĐēĐžĐ˛ĐžĐ´ŅŅ‚Đ˛Đž ĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ĐĩĐģŅ + +Đ’Ņ‹ Đ˛ŅĐĩ Đĩ҉Đĩ ĐŧĐžĐļĐĩŅ‚Đĩ Đ¸ŅĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ŅŒ йОĐģŅŒŅˆĐ¸ĐŊŅŅ‚Đ˛Đž Ņ„ŅƒĐŊĐēŅ†Đ¸Đš **FastAPI** ŅĐž СĐŊаĐŊĐ¸ŅĐŧи иС [ĐŖŅ‡ĐĩĐąĐŊиĐē - Đ ŅƒĐēĐžĐ˛ĐžĐ´ŅŅ‚Đ˛Đž ĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ĐĩĐģŅ](../tutorial/index.md){.internal-link target=_blank}. + +И ҁĐģĐĩĐ´ŅƒŅŽŅ‰Đ¸Đĩ Ņ€Đ°ĐˇĐ´ĐĩĐģŅ‹ ĐŋŅ€ĐĩĐ´ĐŋĐžĐģĐ°ĐŗĐ°ŅŽŅ‚, Ņ‡Ņ‚Đž Đ˛Ņ‹ ҃ĐļĐĩ ĐŋŅ€ĐžŅ‡Đ¸Ņ‚Đ°Đģи ĐĩĐŗĐž, и ĐŋŅ€ĐĩĐ´ĐŋĐžĐģĐ°ĐŗĐ°ŅŽŅ‚, Ņ‡Ņ‚Đž Đ˛Ņ‹ СĐŊаĐĩŅ‚Đĩ ŅŅ‚Đ¸ ĐžŅĐŊОвĐŊŅ‹Đĩ идĐĩи. diff --git a/docs/ru/docs/advanced/response-change-status-code.md b/docs/ru/docs/advanced/response-change-status-code.md new file mode 100644 index 000000000..37dade99f --- /dev/null +++ b/docs/ru/docs/advanced/response-change-status-code.md @@ -0,0 +1,31 @@ +# Response - ИСĐŧĐĩĐŊĐĩĐŊиĐĩ cŅ‚Đ°Ņ‚ŅƒŅ ĐēОда + +Đ’Ņ‹, вĐĩŅ€ĐžŅŅ‚ĐŊĐž, ҃ĐļĐĩ Ņ‡Đ¸Ņ‚Đ°Đģи Đž Ņ‚ĐžĐŧ, Ņ‡Ņ‚Đž ĐŧĐžĐļĐŊĐž ŅƒŅŅ‚Đ°ĐŊĐžĐ˛Đ¸Ņ‚ŅŒ [ĐĄĐžŅŅ‚ĐžŅĐŊиĐĩ ĐžŅ‚Đ˛ĐĩŅ‚Đ° ĐŋĐž ҃ĐŧĐžĐģŅ‡Đ°ĐŊĐ¸ŅŽ](../tutorial/response-status-code.md){.internal-link target=_blank}. + +Но в ĐŊĐĩĐēĐžŅ‚ĐžŅ€Ņ‹Ņ… ҁĐģŅƒŅ‡Đ°ŅŅ… ваĐŧ ĐŊ҃ĐļĐŊĐž вĐĩŅ€ĐŊŅƒŅ‚ŅŒ ĐēОд ŅĐžŅŅ‚ĐžŅĐŊĐ¸Ņ, ĐžŅ‚ĐģĐ¸Ņ‡ĐŊŅ‹Đš ĐžŅ‚ ŅƒŅŅ‚Đ°ĐŊОвĐģĐĩĐŊĐŊĐžĐŗĐž ĐŋĐž ҃ĐŧĐžĐģŅ‡Đ°ĐŊĐ¸ŅŽ. + +## ĐŸŅ€Đ¸ĐŧĐĩŅ€ Đ¸ŅĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°ĐŊĐ¸Ņ + +НаĐŋŅ€Đ¸ĐŧĐĩŅ€, ĐŋŅ€ĐĩĐ´ŅŅ‚Đ°Đ˛ŅŒŅ‚Đĩ, Ņ‡Ņ‚Đž Đ˛Ņ‹ Ņ…ĐžŅ‚Đ¸Ņ‚Đĩ Đ˛ĐžĐˇĐ˛Ņ€Đ°Ņ‰Đ°Ņ‚ŅŒ HTTP ĐēОд ŅĐžŅŅ‚ĐžŅĐŊĐ¸Ņ "OK" `200` ĐŋĐž ҃ĐŧĐžĐģŅ‡Đ°ĐŊĐ¸ŅŽ. + +Но ĐĩҁĐģи даĐŊĐŊŅ‹Đĩ ĐŊĐĩ ŅŅƒŅ‰ĐĩŅŅ‚Đ˛ĐžĐ˛Đ°Đģи, Đ˛Ņ‹ Ņ…ĐžŅ‚Đ¸Ņ‚Đĩ ŅĐžĐˇĐ´Đ°Ņ‚ŅŒ Đ¸Ņ… и вĐĩŅ€ĐŊŅƒŅ‚ŅŒ HTTP ĐēОд ŅĐžŅŅ‚ĐžŅĐŊĐ¸Ņ "CREATED" `201`. + +ĐŸŅ€Đ¸ ŅŅ‚ĐžĐŧ Đ˛Ņ‹ Đ˛ŅŅ‘ Đĩ҉ґ Ņ…ĐžŅ‚Đ¸Ņ‚Đĩ иĐŧĐĩŅ‚ŅŒ вОСĐŧĐžĐļĐŊĐžŅŅ‚ŅŒ Ņ„Đ¸ĐģŅŒŅ‚Ņ€ĐžĐ˛Đ°Ņ‚ŅŒ и ĐŋŅ€ĐĩĐžĐąŅ€Đ°ĐˇĐžĐ˛Ņ‹Đ˛Đ°Ņ‚ŅŒ Đ˛ĐžĐˇĐ˛Ņ€Đ°Ņ‰Đ°ĐĩĐŧŅ‹Đĩ даĐŊĐŊŅ‹Đĩ ҁ ĐŋĐžĐŧĐžŅ‰ŅŒŅŽ `response_model`. + +ДĐģŅ Ņ‚Đ°ĐēĐ¸Ņ… ҁĐģŅƒŅ‡Đ°Đĩв Đ˛Ņ‹ ĐŧĐžĐļĐĩŅ‚Đĩ Đ¸ŅĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ŅŒ ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ `Response`. + +## Đ˜ŅĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°ĐŊиĐĩ ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ° `Response` + +Đ’Ņ‹ ĐŧĐžĐļĐĩŅ‚Đĩ ĐžĐąŅŠŅĐ˛Đ¸Ņ‚ŅŒ ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ Ņ‚Đ¸Đŋа `Response` в Đ˛Đ°ŅˆĐĩĐš *Ņ„ŅƒĐŊĐēŅ†Đ¸Đ¸ ĐžĐąŅ€Đ°ĐąĐžŅ‚Đēи ĐŋŅƒŅ‚Đ¸* (Ņ‚Đ°Đē ĐļĐĩ ĐēаĐē Đ´ĐģŅ cookies и headers). + +И ĐˇĐ°Ņ‚ĐĩĐŧ Đ˛Ņ‹ ĐŧĐžĐļĐĩŅ‚Đĩ ŅƒŅŅ‚Đ°ĐŊĐžĐ˛Đ¸Ņ‚ŅŒ `status_code` в ŅŅ‚ĐžĐŧ *Đ˛Ņ€ĐĩĐŧĐĩĐŊĐŊĐžĐŧ* ĐžĐąŅŠĐĩĐēŅ‚Đĩ ĐžŅ‚Đ˛ĐĩŅ‚Đ°. + +{* ../../docs_src/response_change_status_code/tutorial001.py hl[1,9,12] *} + +ĐŸĐžŅĐģĐĩ ŅŅ‚ĐžĐŗĐž Đ˛Ņ‹ ĐŧĐžĐļĐĩŅ‚Đĩ вĐĩŅ€ĐŊŅƒŅ‚ŅŒ ĐģŅŽĐąĐžĐš ĐžĐąŅŠĐĩĐēŅ‚, ĐēĐžŅ‚ĐžŅ€Ņ‹Đš ваĐŧ ĐŊ҃ĐļĐĩĐŊ, ĐēаĐē ĐžĐąŅ‹Ņ‡ĐŊĐž (`dict`, ĐŧОдĐĩĐģҌ ĐąĐ°ĐˇŅ‹ даĐŊĐŊҋ҅ и Ņ‚.Đ´.). + +И ĐĩҁĐģи Đ˛Ņ‹ ĐžĐąŅŠŅĐ˛Đ¸Đģи `response_model`, ĐžĐŊ Đ˛ŅŅ‘ Ņ€Đ°Đ˛ĐŊĐž ĐąŅƒĐ´ĐĩŅ‚ Đ¸ŅĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ŅŒŅŅ Đ´ĐģŅ Ņ„Đ¸ĐģŅŒŅ‚Ņ€Đ°Ņ†Đ¸Đ¸ и ĐŋŅ€ĐĩĐžĐąŅ€Đ°ĐˇĐžĐ˛Đ°ĐŊĐ¸Ņ Đ˛ĐžĐˇĐ˛Ņ€Đ°Ņ‰Đ°ĐĩĐŧĐžĐŗĐž ĐžĐąŅŠĐĩĐēŅ‚Đ°. + +**FastAPI** ĐąŅƒĐ´ĐĩŅ‚ Đ¸ŅĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ŅŒ ŅŅ‚ĐžŅ‚ *Đ˛Ņ€ĐĩĐŧĐĩĐŊĐŊŅ‹Đš* ĐžŅ‚Đ˛ĐĩŅ‚ Đ´ĐģŅ иСвĐģĐĩ҇ĐĩĐŊĐ¸Ņ ĐēОда ŅĐžŅŅ‚ĐžŅĐŊĐ¸Ņ (а Ņ‚Đ°ĐēĐļĐĩ cookies и headers) и ĐŋĐžĐŧĐĩŅŅ‚Đ¸Ņ‚ Đ¸Ņ… в Ņ„Đ¸ĐŊаĐģҌĐŊŅ‹Đš ĐžŅ‚Đ˛ĐĩŅ‚, ĐēĐžŅ‚ĐžŅ€Ņ‹Đš ŅĐžĐ´ĐĩŅ€ĐļĐ¸Ņ‚ Đ˛ĐžĐˇĐ˛Ņ€Đ°Ņ‰Đ°ĐĩĐŧĐžĐĩ ваĐŧи СĐŊĐ°Ņ‡ĐĩĐŊиĐĩ, ĐžŅ‚Ņ„Đ¸ĐģŅŒŅ‚Ņ€ĐžĐ˛Đ°ĐŊĐŊĐžĐĩ ĐģŅŽĐąŅ‹Đŧ `response_model`. + +Đ’Ņ‹ Ņ‚Đ°ĐēĐļĐĩ ĐŧĐžĐļĐĩŅ‚Đĩ ĐžĐąŅŠŅĐ˛Đ¸Ņ‚ŅŒ ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ `Response` в ĐˇĐ°Đ˛Đ¸ŅĐ¸ĐŧĐžŅŅ‚ŅŅ… и ŅƒŅŅ‚Đ°ĐŊĐžĐ˛Đ¸Ņ‚ŅŒ ĐēОд ŅĐžŅŅ‚ĐžŅĐŊĐ¸Ņ в ĐŊĐ¸Ņ…. Но ĐŋĐžĐŧĐŊĐ¸Ņ‚Đĩ, Ņ‡Ņ‚Đž ĐŋĐžŅĐģĐĩĐ´ĐŊĐĩĐĩ ŅƒŅŅ‚Đ°ĐŊОвĐģĐĩĐŊĐŊĐžĐĩ СĐŊĐ°Ņ‡ĐĩĐŊиĐĩ ĐąŅƒĐ´ĐĩŅ‚ иĐŧĐĩŅ‚ŅŒ ĐŋŅ€Đ¸ĐžŅ€Đ¸Ņ‚ĐĩŅ‚. diff --git a/docs/ru/docs/advanced/response-cookies.md b/docs/ru/docs/advanced/response-cookies.md new file mode 100644 index 000000000..e04ff577c --- /dev/null +++ b/docs/ru/docs/advanced/response-cookies.md @@ -0,0 +1,48 @@ + +# Cookies в ĐžŅ‚Đ˛ĐĩŅ‚Đĩ + +## Đ˜ŅĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°ĐŊиĐĩ ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ° `Response` + +Đ’Ņ‹ ĐŧĐžĐļĐĩŅ‚Đĩ ĐžĐąŅŠŅĐ˛Đ¸Ņ‚ŅŒ ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ Ņ‚Đ¸Đŋа `Response` в Đ˛Đ°ŅˆĐĩĐš Ņ„ŅƒĐŊĐēŅ†Đ¸Đ¸ ŅĐŊĐ´ĐŋОиĐŊŅ‚Đ°. + +Đ—Đ°Ņ‚ĐĩĐŧ ŅƒŅŅ‚Đ°ĐŊĐžĐ˛Đ¸Ņ‚ŅŒ cookies в ŅŅ‚ĐžĐŧ Đ˛Ņ€ĐĩĐŧĐĩĐŊĐŊĐžĐŧ ĐžĐąŅŠĐĩĐēŅ‚Đĩ ĐžŅ‚Đ˛ĐĩŅ‚Đ°. + +{* ../../docs_src/response_cookies/tutorial002.py hl[1, 8:9] *} + +ĐŸĐžŅĐģĐĩ ŅŅ‚ĐžĐŗĐž ĐŧĐžĐļĐŊĐž вĐĩŅ€ĐŊŅƒŅ‚ŅŒ ĐģŅŽĐąĐžĐš ĐžĐąŅŠĐĩĐēŅ‚, ĐēаĐē и Ņ€Đ°ĐŊҌ҈Đĩ (ĐŊаĐŋŅ€Đ¸ĐŧĐĩŅ€, `dict`, ĐžĐąŅŠĐĩĐēŅ‚ ĐŧОдĐĩĐģи ĐąĐ°ĐˇŅ‹ даĐŊĐŊҋ҅ и Ņ‚Đ°Đē даĐģĐĩĐĩ). + +Đ•ŅĐģи Đ˛Ņ‹ ҃ĐēаСаĐģи `response_model`, ĐžĐŊ Đ˛ŅŅ‘ Ņ€Đ°Đ˛ĐŊĐž ĐąŅƒĐ´ĐĩŅ‚ Đ¸ŅĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ŅŒŅŅ Đ´ĐģŅ Ņ„Đ¸ĐģŅŒŅ‚Ņ€Đ°Ņ†Đ¸Đ¸ и ĐŋŅ€ĐĩĐžĐąŅ€Đ°ĐˇĐžĐ˛Đ°ĐŊĐ¸Ņ Đ˛ĐžĐˇĐ˛Ņ€Đ°Ņ‰Đ°ĐĩĐŧĐžĐŗĐž ĐžĐąŅŠĐĩĐēŅ‚Đ°. + +**FastAPI** иСвĐģĐĩ҇ĐĩŅ‚ cookies (а Ņ‚Đ°ĐēĐļĐĩ ĐˇĐ°ĐŗĐžĐģОвĐēи и ĐēĐžĐ´Ņ‹ ŅĐžŅŅ‚ĐžŅĐŊĐ¸Ņ) иС Đ˛Ņ€ĐĩĐŧĐĩĐŊĐŊĐžĐŗĐž ĐžŅ‚Đ˛ĐĩŅ‚Đ° и вĐēĐģŅŽŅ‡Đ¸Ņ‚ Đ¸Ņ… в ĐžĐēĐžĐŊŅ‡Đ°Ņ‚ĐĩĐģҌĐŊŅ‹Đš ĐžŅ‚Đ˛ĐĩŅ‚, ŅĐžĐ´ĐĩŅ€ĐļĐ°Ņ‰Đ¸Đš Đ˛Đ°ŅˆĐĩ Đ˛ĐžĐˇĐ˛Ņ€Đ°Ņ‰Đ°ĐĩĐŧĐžĐĩ СĐŊĐ°Ņ‡ĐĩĐŊиĐĩ, ĐžŅ‚Ņ„Đ¸ĐģŅŒŅ‚Ņ€ĐžĐ˛Đ°ĐŊĐŊĐžĐĩ ҇ĐĩŅ€ĐĩС `response_model`. + +Đ’Ņ‹ Ņ‚Đ°ĐēĐļĐĩ ĐŧĐžĐļĐĩŅ‚Đĩ ĐžĐąŅŠŅĐ˛Đ¸Ņ‚ŅŒ ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ Ņ‚Đ¸Đŋа Response в ĐˇĐ°Đ˛Đ¸ŅĐ¸ĐŧĐžŅŅ‚ŅŅ… и ŅƒŅŅ‚Đ°ĐŊавĐģĐ¸Đ˛Đ°Ņ‚ŅŒ cookies (и ĐˇĐ°ĐŗĐžĐģОвĐēи) Ņ‚Đ°Đŧ. + +## Đ’ĐžĐˇĐ˛Ņ€Đ°Ņ‰ĐĩĐŊиĐĩ `Response` ĐŊаĐŋŅ€ŅĐŧŅƒŅŽ + +Đ’Ņ‹ Ņ‚Đ°ĐēĐļĐĩ ĐŧĐžĐļĐĩŅ‚Đĩ ŅƒŅŅ‚Đ°ĐŊĐžĐ˛Đ¸Ņ‚ŅŒ cookies, ĐĩҁĐģи Đ˛ĐžĐˇĐ˛Ņ€Đ°Ņ‰Đ°ĐĩŅ‚Đĩ `Response` ĐŊаĐŋŅ€ŅĐŧŅƒŅŽ в Đ˛Đ°ŅˆĐĩĐŧ ĐēОдĐĩ. + +ДĐģŅ ŅŅ‚ĐžĐŗĐž ŅĐžĐˇĐ´Đ°ĐšŅ‚Đĩ ĐžĐąŅŠĐĩĐēŅ‚ `Response`, ĐēаĐē ĐžĐŋĐ¸ŅĐ°ĐŊĐž в Ņ€Đ°ĐˇĐ´ĐĩĐģĐĩ [Đ’ĐžĐˇĐ˛Ņ€Đ°Ņ‰ĐĩĐŊиĐĩ ĐžŅ‚Đ˛ĐĩŅ‚Đ° ĐŊаĐŋŅ€ŅĐŧŅƒŅŽ](response-directly.md){.target=_blank}. + +Đ—Đ°Ņ‚ĐĩĐŧ ŅƒŅŅ‚Đ°ĐŊĐžĐ˛Đ¸Ņ‚Đĩ cookies и вĐĩŅ€ĐŊĐ¸Ņ‚Đĩ ŅŅ‚ĐžŅ‚ ĐžĐąŅŠĐĩĐēŅ‚: + +{* ../../docs_src/response_cookies/tutorial001.py hl[10:12] *} + +/// tip | ĐŸŅ€Đ¸ĐŧĐĩŅ‡Đ°ĐŊиĐĩ +ИĐŧĐĩĐšŅ‚Đĩ в Đ˛Đ¸Đ´Ņƒ, Ņ‡Ņ‚Đž ĐĩҁĐģи Đ˛Ņ‹ Đ˛ĐžĐˇĐ˛Ņ€Đ°Ņ‰Đ°ĐĩŅ‚Đĩ ĐžŅ‚Đ˛ĐĩŅ‚ ĐŊаĐŋŅ€ŅĐŧŅƒŅŽ, вĐŧĐĩŅŅ‚Đž Đ¸ŅĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°ĐŊĐ¸Ņ ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ° `Response`, **FastAPI** ĐžŅ‚ĐŋŅ€Đ°Đ˛Đ¸Ņ‚ ĐĩĐŗĐž ĐąĐĩС Đ´ĐžĐŋĐžĐģĐŊĐ¸Ņ‚ĐĩĐģҌĐŊОК ĐžĐąŅ€Đ°ĐąĐžŅ‚Đēи. + +ĐŖĐąĐĩĐ´Đ¸Ņ‚ĐĩҁҌ, Ņ‡Ņ‚Đž Đ˛Đ°ŅˆĐ¸ даĐŊĐŊŅ‹Đĩ иĐŧĐĩŅŽŅ‚ ĐēĐžŅ€Ņ€ĐĩĐēŅ‚ĐŊŅ‹Đš Ņ‚Đ¸Đŋ. НаĐŋŅ€Đ¸ĐŧĐĩŅ€, ĐžĐŊи Đ´ĐžĐģĐļĐŊŅ‹ ĐąŅ‹Ņ‚ŅŒ ŅĐžĐ˛ĐŧĐĩŅŅ‚Đ¸ĐŧŅ‹ ҁ JSON, ĐĩҁĐģи Đ˛Ņ‹ Đ¸ŅĐŋĐžĐģŅŒĐˇŅƒĐĩŅ‚Đĩ `JSONResponse`. + +ĐĸаĐēĐļĐĩ ŅƒĐąĐĩĐ´Đ¸Ņ‚ĐĩҁҌ, Ņ‡Ņ‚Đž Đ˛Ņ‹ ĐŊĐĩ ĐžŅ‚ĐŋŅ€Đ°Đ˛ĐģŅĐĩŅ‚Đĩ даĐŊĐŊŅ‹Đĩ, ĐēĐžŅ‚ĐžŅ€Ņ‹Đĩ Đ´ĐžĐģĐļĐŊŅ‹ ĐąŅ‹Đģи ĐąŅ‹Ņ‚ŅŒ ĐžŅ‚Ņ„Đ¸ĐģŅŒŅ‚Ņ€ĐžĐ˛Đ°ĐŊŅ‹ ҇ĐĩŅ€ĐĩС `response_model`. +/// + +### ДоĐŋĐžĐģĐŊĐ¸Ņ‚ĐĩĐģҌĐŊĐ°Ņ иĐŊŅ„ĐžŅ€ĐŧĐ°Ņ†Đ¸Ņ + +/// note | ĐĸĐĩŅ…ĐŊĐ¸Ņ‡ĐĩҁĐēиĐĩ Đ´ĐĩŅ‚Đ°Đģи +Đ’Ņ‹ Ņ‚Đ°ĐēĐļĐĩ ĐŧĐžĐļĐĩŅ‚Đĩ Đ¸ŅĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ŅŒ `from starlette.responses import Response` иĐģи `from starlette.responses import JSONResponse`. + +**FastAPI** ĐŋŅ€ĐĩĐ´ĐžŅŅ‚Đ°Đ˛ĐģŅĐĩŅ‚ `fastapi.responses`, ĐēĐžŅ‚ĐžŅ€Ņ‹Đĩ ŅĐ˛ĐģŅŅŽŅ‚ŅŅ Ņ‚ĐĩĐŧи ĐļĐĩ ĐžĐąŅŠĐĩĐēŅ‚Đ°Đŧи, Ņ‡Ņ‚Đž и `starlette.responses`, ĐŋŅ€ĐžŅŅ‚Đž Đ´ĐģŅ ŅƒĐ´ĐžĐąŅŅ‚Đ˛Đ°. ОдĐŊаĐēĐž йОĐģŅŒŅˆĐ¸ĐŊŅŅ‚Đ˛Đž Đ´ĐžŅŅ‚ŅƒĐŋĐŊҋ҅ Ņ‚Đ¸ĐŋОв ĐžŅ‚Đ˛ĐĩŅ‚ĐžĐ˛ ĐŋĐžŅŅ‚ŅƒĐŋаĐĩŅ‚ ĐŊĐĩĐŋĐžŅŅ€ĐĩĐ´ŅŅ‚Đ˛ĐĩĐŊĐŊĐž иС **Starlette**. + +ДĐģŅ ŅƒŅŅ‚Đ°ĐŊОвĐēи ĐˇĐ°ĐŗĐžĐģОвĐēОв и cookies `Response` Đ¸ŅĐŋĐžĐģŅŒĐˇŅƒĐĩŅ‚ŅŅ Ņ‡Đ°ŅŅ‚Đž, ĐŋĐžŅŅ‚ĐžĐŧ҃ **FastAPI** Ņ‚Đ°ĐēĐļĐĩ ĐŋŅ€ĐĩĐ´ĐžŅŅ‚Đ°Đ˛ĐģŅĐĩŅ‚ ĐĩĐŗĐž ҇ĐĩŅ€ĐĩС `fastapi.responses`. +/// + +Đ§Ņ‚ĐžĐąŅ‹ ŅƒĐ˛Đ¸Đ´ĐĩŅ‚ŅŒ Đ˛ŅĐĩ Đ´ĐžŅŅ‚ŅƒĐŋĐŊŅ‹Đĩ ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁҋ и ĐŊĐ°ŅŅ‚Ņ€ĐžĐšĐēи, ОСĐŊаĐēĐžĐŧŅŒŅ‚ĐĩҁҌ ҁ Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Đ¸ĐĩĐš Starlette. diff --git a/docs/ru/docs/advanced/response-directly.md b/docs/ru/docs/advanced/response-directly.md new file mode 100644 index 000000000..ee83d22b1 --- /dev/null +++ b/docs/ru/docs/advanced/response-directly.md @@ -0,0 +1,65 @@ +# Đ’ĐžĐˇĐ˛Ņ€Đ°Ņ‚ ĐžŅ‚Đ˛ĐĩŅ‚Đ° ĐŊаĐŋŅ€ŅĐŧŅƒŅŽ + +ĐšĐžĐŗĐ´Đ° Đ˛Ņ‹ ŅĐžĐˇĐ´Đ°Ņ‘Ņ‚Đĩ **FastAPI** *ĐžĐŋĐĩŅ€Đ°Ņ†Đ¸ŅŽ ĐŋŅƒŅ‚Đ¸*, Đ˛Ņ‹ ĐŧĐžĐļĐĩŅ‚Đĩ Đ˛ĐžĐˇĐ˛Ņ€Đ°Ņ‰Đ°Ņ‚ŅŒ иС ĐŊĐĩŅ‘ ĐģŅŽĐąŅ‹Đĩ даĐŊĐŊŅ‹Đĩ: `dict`, `list`, Pydantic-ĐŧОдĐĩĐģҌ, ĐŧОдĐĩĐģҌ ĐąĐ°ĐˇŅ‹ даĐŊĐŊҋ҅ и Ņ‚.Đ´. + +По ҃ĐŧĐžĐģŅ‡Đ°ĐŊĐ¸ŅŽ **FastAPI** Đ°Đ˛Ņ‚ĐžĐŧĐ°Ņ‚Đ¸Ņ‡ĐĩҁĐēи ĐŋŅ€ĐĩĐžĐąŅ€Đ°ĐˇŅƒĐĩŅ‚ Đ˛ĐžĐˇĐ˛Ņ€Đ°Ņ‰Đ°ĐĩĐŧĐžĐĩ СĐŊĐ°Ņ‡ĐĩĐŊиĐĩ в JSON ҁ ĐŋĐžĐŧĐžŅ‰ŅŒŅŽ `jsonable_encoder`, ĐēаĐē ĐžĐŋĐ¸ŅĐ°ĐŊĐž в [JSON ĐēĐžĐ´Đ¸Ņ€ĐžĐ˛Ņ‰Đ¸Đē](../tutorial/encoder.md){.internal-link target=_blank}. + +Đ—Đ°Ņ‚ĐĩĐŧ "ĐŋОд ĐēаĐŋĐžŅ‚ĐžĐŧ" ŅŅ‚Đ¸ даĐŊĐŊŅ‹Đĩ, ŅĐžĐ˛ĐŧĐĩŅŅ‚Đ¸ĐŧŅ‹Đĩ ҁ JSON (ĐŊаĐŋŅ€Đ¸ĐŧĐĩŅ€ `dict`), ĐŋĐžĐŧĐĩŅ‰Đ°ŅŽŅ‚ŅŅ в `JSONResponse`, ĐēĐžŅ‚ĐžŅ€Ņ‹Đš Đ¸ŅĐŋĐžĐģŅŒĐˇŅƒĐĩŅ‚ŅŅ Đ´ĐģŅ ĐžŅ‚ĐŋŅ€Đ°Đ˛Đēи ĐžŅ‚Đ˛ĐĩŅ‚Đ° ĐēĐģиĐĩĐŊŅ‚Ņƒ. + +Но Đ˛Ņ‹ ĐŧĐžĐļĐĩŅ‚Đĩ Đ˛ĐžĐˇĐ˛Ņ€Đ°Ņ‰Đ°Ņ‚ŅŒ `JSONResponse` ĐŊаĐŋŅ€ŅĐŧŅƒŅŽ иС Đ˛Đ°ŅˆĐ¸Ņ… *ĐžĐŋĐĩŅ€Đ°Ņ†Đ¸Đš ĐŋŅƒŅ‚Đ¸*. + +Đ­Ņ‚Đž ĐŧĐžĐļĐĩŅ‚ ĐąŅ‹Ņ‚ŅŒ ĐŋĐžĐģĐĩСĐŊĐž, ĐŊаĐŋŅ€Đ¸ĐŧĐĩŅ€, ĐĩҁĐģи ĐŊ҃ĐļĐŊĐž вĐĩŅ€ĐŊŅƒŅ‚ŅŒ ĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ĐĩĐģҌҁĐēиĐĩ ĐˇĐ°ĐŗĐžĐģОвĐēи иĐģи Đē҃Đēи. + +## Đ’ĐžĐˇĐ˛Ņ€Đ°Ņ‚ `Response` + +На ŅĐ°ĐŧĐžĐŧ Đ´ĐĩĐģĐĩ, Đ˛Ņ‹ ĐŧĐžĐļĐĩŅ‚Đĩ Đ˛ĐžĐˇĐ˛Ņ€Đ°Ņ‰Đ°Ņ‚ŅŒ ĐģŅŽĐąĐžĐš ĐžĐąŅŠĐĩĐēŅ‚ `Response` иĐģи ĐĩĐŗĐž ĐŋОдĐēĐģĐ°ŅŅ. + +/// tip | ĐŸĐžĐ´ŅĐēаСĐēа + +`JSONResponse` ŅĐ°Đŧ ĐŋĐž ҁĐĩĐąĐĩ ŅĐ˛ĐģŅĐĩŅ‚ŅŅ ĐŋОдĐēĐģĐ°ŅŅĐžĐŧ `Response`. + +/// + +И ĐēĐžĐŗĐ´Đ° Đ˛Ņ‹ Đ˛ĐžĐˇĐ˛Ņ€Đ°Ņ‰Đ°ĐĩŅ‚Đĩ `Response`, **FastAPI** ĐŋĐĩŅ€ĐĩĐ´Đ°ŅŅ‚ ĐĩĐŗĐž ĐŊаĐŋŅ€ŅĐŧŅƒŅŽ. + +Đ­Ņ‚Đž ĐŊĐĩ ĐŋŅ€Đ¸Đ˛ĐĩĐ´ĐĩŅ‚ Đē ĐŋŅ€ĐĩĐžĐąŅ€Đ°ĐˇĐžĐ˛Đ°ĐŊĐ¸ŅŽ даĐŊĐŊҋ҅ ҁ ĐŋĐžĐŧĐžŅ‰ŅŒŅŽ Pydantic-ĐŧОдĐĩĐģĐĩĐš, ŅĐžĐ´ĐĩŅ€ĐļиĐŧĐžĐĩ ĐŊĐĩ ĐąŅƒĐ´ĐĩŅ‚ ĐŋŅ€ĐĩĐžĐąŅ€Đ°ĐˇĐžĐ˛Đ°ĐŊĐž в ĐēаĐēОК-ĐģийО Ņ‚Đ¸Đŋ и Ņ‚.Đ´. + +Đ­Ņ‚Đž Đ´Đ°Ņ‘Ņ‚ ваĐŧ йОĐģŅŒŅˆŅƒŅŽ ĐŗĐ¸ĐąĐēĐžŅŅ‚ŅŒ. Đ’Ņ‹ ĐŧĐžĐļĐĩŅ‚Đĩ Đ˛ĐžĐˇĐ˛Ņ€Đ°Ņ‰Đ°Ņ‚ŅŒ ĐģŅŽĐąŅ‹Đĩ Ņ‚Đ¸ĐŋŅ‹ даĐŊĐŊҋ҅, ĐŋĐĩŅ€ĐĩĐžĐŋŅ€ĐĩĐ´ĐĩĐģŅŅ‚ŅŒ ĐģŅŽĐąŅ‹Đĩ ĐžĐąŅŠŅĐ˛ĐģĐĩĐŊĐ¸Ņ иĐģи ваĐģĐ¸Đ´Đ°Ņ†Đ¸ŅŽ даĐŊĐŊҋ҅ и Ņ‚.Đ´. + +## Đ˜ŅĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°ĐŊиĐĩ `jsonable_encoder` в `Response` + +ĐŸĐžŅĐēĐžĐģҌĐē҃ **FastAPI** ĐŊĐĩ иСĐŧĐĩĐŊŅĐĩŅ‚ ĐžĐąŅŠĐĩĐēŅ‚ `Response`, ĐēĐžŅ‚ĐžŅ€Ņ‹Đš Đ˛Ņ‹ Đ˛ĐžĐˇĐ˛Ņ€Đ°Ņ‰Đ°ĐĩŅ‚Đĩ, Đ˛Ņ‹ Đ´ĐžĐģĐļĐŊŅ‹ ŅƒĐąĐĩĐ´Đ¸Ņ‚ŅŒŅŅ, Ņ‡Ņ‚Đž ĐĩĐŗĐž ŅĐžĐ´ĐĩŅ€ĐļиĐŧĐžĐĩ ĐŗĐžŅ‚ĐžĐ˛Đž Đē ĐžŅ‚ĐŋŅ€Đ°Đ˛ĐēĐĩ. + +НаĐŋŅ€Đ¸ĐŧĐĩŅ€, Đ˛Ņ‹ ĐŊĐĩ ĐŧĐžĐļĐĩŅ‚Đĩ ĐŋĐžĐŧĐĩŅŅ‚Đ¸Ņ‚ŅŒ Pydantic-ĐŧОдĐĩĐģҌ в `JSONResponse`, ĐŊĐĩ ĐŋŅ€ĐĩĐžĐąŅ€Đ°ĐˇĐžĐ˛Đ°Đ˛ ĐĩŅ‘ ҁĐŊĐ°Ņ‡Đ°Đģа в `dict` ҁ ĐŋĐžĐŧĐžŅ‰ŅŒŅŽ ĐŋŅ€ĐĩĐžĐąŅ€Đ°ĐˇĐžĐ˛Đ°ĐŊĐ¸Ņ Đ˛ŅĐĩŅ… Ņ‚Đ¸ĐŋОв даĐŊĐŊҋ҅ (Ņ‚Đ°ĐēĐ¸Ņ… ĐēаĐē `datetime`, `UUID` и Ņ‚.Đ´.) в ŅĐžĐ˛ĐŧĐĩŅŅ‚Đ¸ĐŧŅ‹Đĩ ҁ JSON Ņ‚Đ¸ĐŋŅ‹. + +В Ņ‚Đ°ĐēĐ¸Ņ… ҁĐģŅƒŅ‡Đ°ŅŅ… Đ˛Ņ‹ ĐŧĐžĐļĐĩŅ‚Đĩ Đ¸ŅĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ŅŒ `jsonable_encoder` Đ´ĐģŅ ĐŋŅ€ĐĩĐžĐąŅ€Đ°ĐˇĐžĐ˛Đ°ĐŊĐ¸Ņ даĐŊĐŊҋ҅ ĐŋĐĩŅ€ĐĩĐ´ ĐŋĐĩŅ€ĐĩĐ´Đ°Ņ‡ĐĩĐš Đ¸Ņ… в ĐžŅ‚Đ˛ĐĩŅ‚: + +{* ../../docs_src/response_directly/tutorial001.py hl[6:7,21:22] *} + +/// note | ĐĸĐĩŅ…ĐŊĐ¸Ņ‡ĐĩҁĐēиĐĩ Đ´ĐĩŅ‚Đ°Đģи + +Đ’Ņ‹ Ņ‚Đ°ĐēĐļĐĩ ĐŧĐžĐļĐĩŅ‚Đĩ Đ¸ŅĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ŅŒ `from starlette.responses import JSONResponse`. + +**FastAPI** ĐŋŅ€ĐĩĐ´ĐžŅŅ‚Đ°Đ˛ĐģŅĐĩŅ‚ `starlette.responses` ҇ĐĩŅ€ĐĩС `fastapi.responses` ĐŋŅ€ĐžŅŅ‚Đž Đ´ĐģŅ Đ˛Đ°ŅˆĐĩĐŗĐž ŅƒĐ´ĐžĐąŅŅ‚Đ˛Đ°, ĐēаĐē Ņ€Đ°ĐˇŅ€Đ°ĐąĐžŅ‚Ņ‡Đ¸Đēа. Но йОĐģŅŒŅˆĐ¸ĐŊŅŅ‚Đ˛Đž Đ´ĐžŅŅ‚ŅƒĐŋĐŊҋ҅ Response-ĐēĐģĐ°ŅŅĐžĐ˛ ĐŋĐžŅŅ‚ŅƒĐŋĐ°ŅŽŅ‚ ĐŊаĐŋŅ€ŅĐŧŅƒŅŽ иС Starlette. + +/// + +## Đ’ĐžĐˇĐ˛Ņ€Đ°Ņ‚ ĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ĐĩĐģҌҁĐēĐžĐŗĐž `Response` + +ĐŸŅ€Đ¸ĐŧĐĩŅ€ Đ˛Ņ‹ŅˆĐĩ ĐŋĐžĐēĐ°ĐˇŅ‹Đ˛Đ°ĐĩŅ‚ Đ˛ŅĐĩ ĐŊĐĩĐžĐąŅ…ĐžĐ´Đ¸ĐŧŅ‹Đĩ Ņ‡Đ°ŅŅ‚Đ¸, ĐŊĐž ĐžĐŊ ĐŋĐžĐēа ĐŊĐĩ ĐžŅ‡ĐĩĐŊҌ ĐŋĐžĐģĐĩСĐĩĐŊ, Ņ‚Đ°Đē ĐēаĐē Đ˛Ņ‹ ĐŧĐžĐŗĐģи ĐąŅ‹ ĐŋŅ€ĐžŅŅ‚Đž вĐĩŅ€ĐŊŅƒŅ‚ŅŒ `item` ĐŊаĐŋŅ€ŅĐŧŅƒŅŽ, и **FastAPI** ĐŋĐžĐŧĐĩŅŅ‚Đ¸Đģ ĐąŅ‹ ĐĩĐŗĐž в `JSONResponse`, ĐŋŅ€ĐĩĐžĐąŅ€Đ°ĐˇĐžĐ˛Đ°Đ˛ в `dict` и Ņ‚.Đ´. Đ’ŅŅ‘ ŅŅ‚Đž ĐŋŅ€ĐžĐ¸ŅŅ…ĐžĐ´Đ¸Ņ‚ ĐŋĐž ҃ĐŧĐžĐģŅ‡Đ°ĐŊĐ¸ŅŽ. + +ĐĸĐĩĐŋĐĩŅ€ŅŒ Đ´Đ°Đ˛Đ°ĐšŅ‚Đĩ ĐŋĐžŅĐŧĐžŅ‚Ņ€Đ¸Đŧ, ĐēаĐē ĐŧĐžĐļĐŊĐž Đ¸ŅĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ŅŒ ŅŅ‚Đž Đ´ĐģŅ Đ˛ĐžĐˇĐ˛Ņ€Đ°Ņ‚Đ° ĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ĐĩĐģҌҁĐēĐžĐŗĐž ĐžŅ‚Đ˛ĐĩŅ‚Đ°. + +ДоĐŋŅƒŅŅ‚Đ¸Đŧ, Đ˛Ņ‹ Ņ…ĐžŅ‚Đ¸Ņ‚Đĩ вĐĩŅ€ĐŊŅƒŅ‚ŅŒ ĐžŅ‚Đ˛ĐĩŅ‚ в Ņ„ĐžŅ€ĐŧĐ°Ņ‚Đĩ XML. + +Đ’Ņ‹ ĐŧĐžĐļĐĩŅ‚Đĩ ĐŋĐžĐŧĐĩŅŅ‚Đ¸Ņ‚ŅŒ Đ˛Đ°Ņˆ XML-ĐēĐžĐŊŅ‚ĐĩĐŊŅ‚ в ŅŅ‚Ņ€ĐžĐē҃, ĐŋĐžĐŧĐĩŅŅ‚Đ¸Ņ‚ŅŒ ĐĩŅ‘ в `Response` и вĐĩŅ€ĐŊŅƒŅ‚ŅŒ: + +{* ../../docs_src/response_directly/tutorial002.py hl[1,18] *} + +## ĐŸŅ€Đ¸ĐŧĐĩŅ‡Đ°ĐŊĐ¸Ņ + +ĐšĐžĐŗĐ´Đ° Đ˛Ņ‹ Đ˛ĐžĐˇĐ˛Ņ€Đ°Ņ‰Đ°ĐĩŅ‚Đĩ ĐžĐąŅŠĐĩĐēŅ‚ `Response` ĐŊаĐŋŅ€ŅĐŧŅƒŅŽ, ĐĩĐŗĐž даĐŊĐŊŅ‹Đĩ ĐŊĐĩ ваĐģĐ¸Đ´Đ¸Ņ€ŅƒŅŽŅ‚ŅŅ, ĐŊĐĩ ĐŋŅ€ĐĩĐžĐąŅ€Đ°ĐˇŅƒŅŽŅ‚ŅŅ (ĐŊĐĩ ҁĐĩŅ€Đ¸Đ°ĐģĐ¸ĐˇŅƒŅŽŅ‚ŅŅ) и ĐŊĐĩ Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ¸Ņ€ŅƒŅŽŅ‚ŅŅ Đ°Đ˛Ņ‚ĐžĐŧĐ°Ņ‚Đ¸Ņ‡ĐĩҁĐēи. + +Но Đ˛Ņ‹ Đ˛ŅŅ‘ Ņ€Đ°Đ˛ĐŊĐž ĐŧĐžĐļĐĩŅ‚Đĩ СадОĐē҃ĐŧĐĩĐŊŅ‚Đ¸Ņ€ĐžĐ˛Đ°Ņ‚ŅŒ ŅŅ‚Đž, ĐēаĐē ĐžĐŋĐ¸ŅĐ°ĐŊĐž в [ДоĐŋĐžĐģĐŊĐ¸Ņ‚ĐĩĐģҌĐŊŅ‹Đĩ ĐžŅ‚Đ˛Đĩ҂ҋ в OpenAPI](additional-responses.md){.internal-link target=_blank}. + +В ҁĐģĐĩĐ´ŅƒŅŽŅ‰Đ¸Ņ… Ņ€Đ°ĐˇĐ´ĐĩĐģĐ°Ņ… Đ˛Ņ‹ ŅƒĐ˛Đ¸Đ´Đ¸Ņ‚Đĩ, ĐēаĐē Đ¸ŅĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ŅŒ/ĐžĐąŅŠŅĐ˛ĐģŅŅ‚ŅŒ Ņ‚Đ°ĐēиĐĩ ĐēĐ°ŅŅ‚ĐžĐŧĐŊŅ‹Đĩ `Response`, ĐŋŅ€Đ¸ ŅŅ‚ĐžĐŧ ŅĐžŅ…Ņ€Đ°ĐŊŅŅ Đ°Đ˛Ņ‚ĐžĐŧĐ°Ņ‚Đ¸Ņ‡ĐĩҁĐēĐžĐĩ ĐŋŅ€ĐĩĐžĐąŅ€Đ°ĐˇĐžĐ˛Đ°ĐŊиĐĩ даĐŊĐŊҋ҅, Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Đ¸ŅŽ и Ņ‚.Đ´. diff --git a/docs/ru/docs/advanced/websockets.md b/docs/ru/docs/advanced/websockets.md new file mode 100644 index 000000000..bc9dfcbff --- /dev/null +++ b/docs/ru/docs/advanced/websockets.md @@ -0,0 +1,186 @@ +# ВĐĩĐą-ŅĐžĐēĐĩ҂ҋ + +Đ’Ņ‹ ĐŧĐžĐļĐĩŅ‚Đĩ Đ¸ŅĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ŅŒ вĐĩĐą-ŅĐžĐēĐĩ҂ҋ в **FastAPI**. + +## ĐŖŅŅ‚Đ°ĐŊОвĐēа `WebSockets` + +ĐŖĐąĐĩĐ´Đ¸Ņ‚ĐĩҁҌ, Ņ‡Ņ‚Đž [Đ˛Đ¸Ņ€Ņ‚ŅƒĐ°ĐģҌĐŊĐ°Ņ ҁҀĐĩда](../virtual-environments.md){.internal-link target=_blank} ŅĐžĐˇĐ´Đ°ĐŊа, аĐēŅ‚Đ¸Đ˛Đ¸Ņ€ŅƒĐšŅ‚Đĩ ĐĩŅ‘ и ŅƒŅŅ‚Đ°ĐŊĐžĐ˛Đ¸Ņ‚Đĩ `websockets`: + +
+ +```console +$ pip install websockets + +---> 100% +``` + +
+ +## КĐģиĐĩĐŊŅ‚ WebSockets + +### Đ Đ°ĐąĐžŅ‡ĐĩĐĩ ĐŋŅ€Đ¸ĐģĐžĐļĐĩĐŊиĐĩ + +ĐĄĐēĐžŅ€ĐĩĐĩ Đ˛ŅĐĩĐŗĐž, в Đ˛Đ°ŅˆĐĩĐš Ņ€ĐĩаĐģҌĐŊОК ĐŋŅ€ĐžĐ´ŅƒĐēŅ‚ĐžĐ˛ĐžĐš ŅĐ¸ŅŅ‚ĐĩĐŧĐĩ ĐĩŅŅ‚ŅŒ Ņ„Ņ€ĐžĐŊŅ‚ĐĩĐŊĐ´, Ņ€ĐĩаĐģиСОваĐŊĐŊŅ‹Đš ĐŋŅ€Đ¸ ĐŋĐžĐŧĐžŅ‰Đ¸ ŅĐžĐ˛Ņ€ĐĩĐŧĐĩĐŊĐŊҋ҅ ҄ҀĐĩĐšĐŧĐ˛ĐžŅ€ĐēОв React, Vue.js иĐģи Angular. + +И ĐŊавĐĩŅ€ĐŊŅĐēа Đ´ĐģŅ вСаиĐŧОдĐĩĐšŅŅ‚Đ˛Đ¸Ņ ҁ ĐąĐĩĐēĐĩĐŊĐ´ĐžĐŧ ҇ĐĩŅ€ĐĩС вĐĩĐą-ŅĐžĐēĐĩ҂ҋ Đ˛Ņ‹ ĐąŅƒĐ´ĐĩŅ‚Đĩ Đ¸ŅĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ŅŒ ҁҀĐĩĐ´ŅŅ‚Đ˛Đ° Ņ„Ņ€ĐžĐŊŅ‚ĐĩĐŊда. + +ĐĸаĐēĐļĐĩ ҃ Đ˛Đ°Ņ ĐŧĐžĐļĐĩŅ‚ ĐąŅ‹Ņ‚ŅŒ ĐŊĐ°Ņ‚Đ¸Đ˛ĐŊĐžĐĩ ĐŧОйиĐģҌĐŊĐžĐĩ ĐŋŅ€Đ¸ĐģĐžĐļĐĩĐŊиĐĩ, ĐēĐžĐŧĐŧ҃ĐŊĐ¸Ņ†Đ¸Ņ€ŅƒŅŽŅ‰ĐĩĐĩ ĐŊĐĩĐŋĐžŅŅ€ĐĩĐ´ŅŅ‚Đ˛ĐĩĐŊĐŊĐž ҁ вĐĩĐą-ŅĐžĐēĐĩŅ‚Đ°Đŧи ĐŊа ĐąĐĩĐēĐĩĐŊĐ´-ҁĐĩŅ€Đ˛ĐĩŅ€Đĩ. + +Либо Đ˛Ņ‹ ĐŧĐžĐļĐĩŅ‚Đĩ ŅĐ´ĐĩĐģĐ°Ņ‚ŅŒ ĐēаĐēОК-ĐģийО Đ´Ņ€ŅƒĐŗĐžĐš ҁĐŋĐžŅĐžĐą вСаиĐŧОдĐĩĐšŅŅ‚Đ˛Đ¸Ņ ҁ вĐĩĐą-ŅĐžĐēĐĩŅ‚Đ°Đŧи. + +--- + +Но Đ´ĐģŅ ŅŅ‚ĐžĐŗĐž ĐŋŅ€Đ¸ĐŧĐĩŅ€Đ° ĐŧŅ‹ Đ˛ĐžŅĐŋĐžĐģŅŒĐˇŅƒĐĩĐŧŅŅ ĐžŅ‡ĐĩĐŊҌ ĐŋŅ€ĐžŅŅ‚Ņ‹Đŧ HTML Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚ĐžĐŧ ҁ ĐŊĐĩйОĐģŅŒŅˆĐ¸Đŧи Đ˛ŅŅ‚Đ°Đ˛ĐēаĐŧи JavaScript ĐēОда. + +КоĐŊĐĩ҇ĐŊĐž ĐļĐĩ ŅŅ‚Đž ĐŊĐĩĐžĐŋŅ‚Đ¸ĐŧаĐģҌĐŊĐž, и ĐŊа ĐŋŅ€Đ°ĐēŅ‚Đ¸ĐēĐĩ Ņ‚Đ°Đē Đ´ĐĩĐģĐ°Ņ‚ŅŒ ĐŊĐĩ ŅŅ‚ĐžĐ¸Ņ‚. + +В Ņ€ĐĩаĐģҌĐŊҋ҅ ĐŋŅ€Đ¸ĐģĐžĐļĐĩĐŊĐ¸ŅŅ… ŅŅ‚ĐžĐ¸Ņ‚ Đ˛ĐžŅĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ŅŒŅŅ ОдĐŊиĐŧ иС Đ˛Ņ‹ŅˆĐĩ҃ĐŋĐžĐŧŅĐŊŅƒŅ‚Ņ‹Ņ… ҁĐŋĐžŅĐžĐąĐžĐ˛. + +ДĐģŅ ĐŋŅ€Đ¸ĐŧĐĩŅ€Đ° ĐŊаĐŧ ĐŊ҃ĐļĐĩĐŊ ĐŊаийОĐģĐĩĐĩ ĐŋŅ€ĐžŅŅ‚ĐžĐš ҁĐŋĐžŅĐžĐą, ĐēĐžŅ‚ĐžŅ€Ņ‹Đš ĐŋОСвОĐģĐ¸Ņ‚ ŅĐžŅŅ€ĐĩĐ´ĐžŅ‚ĐžŅ‡Đ¸Ņ‚ŅŒŅŅ ĐŊа ҁĐĩŅ€Đ˛ĐĩŅ€ĐŊОК Ņ‡Đ°ŅŅ‚Đ¸ вĐĩĐą-ŅĐžĐēĐĩŅ‚ĐžĐ˛ и ĐŋĐžĐģŅƒŅ‡Đ¸Ņ‚ŅŒ Ņ€Đ°ĐąĐžŅ‡Đ¸Đš ĐēОд: + +{* ../../docs_src/websockets/tutorial001.py hl[2,6:38,41:43] *} + +## ХОСдаĐŊиĐĩ `websocket` + +ĐĄĐžĐˇĐ´Đ°ĐšŅ‚Đĩ `websocket` в ŅĐ˛ĐžĐĩĐŧ **FastAPI** ĐŋŅ€Đ¸ĐģĐžĐļĐĩĐŊии: + +{* ../../docs_src/websockets/tutorial001.py hl[1,46:47] *} + +/// note | ĐĸĐĩŅ…ĐŊĐ¸Ņ‡ĐĩҁĐēиĐĩ Đ´ĐĩŅ‚Đ°Đģи + +Đ’Ņ‹ Ņ‚Đ°ĐēĐļĐĩ ĐŧĐžĐļĐĩŅ‚Đĩ Đ¸ŅĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ŅŒ `from starlette.websockets import WebSocket`. + +**FastAPI** ĐŊаĐŋŅ€ŅĐŧŅƒŅŽ ĐŋŅ€ĐĩĐ´ĐžŅŅ‚Đ°Đ˛ĐģŅĐĩŅ‚ Ņ‚ĐžŅ‚ ĐļĐĩ ŅĐ°ĐŧŅ‹Đš `WebSocket` ĐŋŅ€ĐžŅŅ‚Đž Đ´ĐģŅ ŅƒĐ´ĐžĐąŅŅ‚Đ˛Đ°. На ŅĐ°ĐŧĐžĐŧ Đ´ĐĩĐģĐĩ ŅŅ‚Đž `WebSocket` иС Starlette. + +/// + +## ОĐļидаĐŊиĐĩ и ĐžŅ‚ĐŋŅ€Đ°Đ˛Đēа ŅĐžĐžĐąŅ‰ĐĩĐŊиК + +ЧĐĩŅ€ĐĩС ŅĐŊĐ´ĐŋОиĐŊŅ‚ вĐĩĐą-ŅĐžĐēĐĩŅ‚Đ° Đ˛Ņ‹ ĐŧĐžĐļĐĩŅ‚Đĩ ĐŋĐžĐģŅƒŅ‡Đ°Ņ‚ŅŒ и ĐžŅ‚ĐŋŅ€Đ°Đ˛ĐģŅŅ‚ŅŒ ŅĐžĐžĐąŅ‰ĐĩĐŊĐ¸Ņ. + +{* ../../docs_src/websockets/tutorial001.py hl[48:52] *} + +Đ’Ņ‹ ĐŧĐžĐļĐĩŅ‚Đĩ ĐŋĐžĐģŅƒŅ‡Đ°Ņ‚ŅŒ и ĐžŅ‚ĐŋŅ€Đ°Đ˛ĐģŅŅ‚ŅŒ Đ´Đ˛ĐžĐ¸Ņ‡ĐŊŅ‹Đĩ, Ņ‚ĐĩĐēŅŅ‚ĐžĐ˛Ņ‹Đĩ и JSON даĐŊĐŊŅ‹Đĩ. + +## ĐŸŅ€ĐžĐ˛ĐĩŅ€Đēа в Đ´ĐĩĐšŅŅ‚Đ˛Đ¸Đ¸ + +Đ•ŅĐģи Đ˛Đ°Ņˆ Ņ„Đ°ĐšĐģ ĐŊĐ°ĐˇŅ‹Đ˛Đ°ĐĩŅ‚ŅŅ `main.py`, Ņ‚Đž СаĐŋŅƒŅŅ‚Đ¸Ņ‚Đĩ ĐŋŅ€Đ¸ĐģĐžĐļĐĩĐŊиĐĩ ĐēĐžĐŧаĐŊдОК: + +
+ +```console +$ fastapi dev main.py + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +ĐžŅ‚ĐēŅ€ĐžĐšŅ‚Đĩ ĐąŅ€Đ°ŅƒĐˇĐĩŅ€ ĐŋĐž Đ°Đ´Ņ€Đĩҁ҃ http://127.0.0.1:8000. + +Đ’Ņ‹ ŅƒĐ˛Đ¸Đ´Đ¸Ņ‚Đĩ ҁĐģĐĩĐ´ŅƒŅŽŅ‰ŅƒŅŽ ĐŋŅ€ĐžŅŅ‚ĐĩĐŊҌĐēŅƒŅŽ ŅŅ‚Ņ€Đ°ĐŊĐ¸Ņ†Ņƒ: + + + +Đ’Ņ‹ ĐŧĐžĐļĐĩŅ‚Đĩ ĐŊĐ°ĐąĐ¸Ņ€Đ°Ņ‚ŅŒ ŅĐžĐžĐąŅ‰ĐĩĐŊĐ¸Ņ в ĐŋĐžĐģĐĩ ввОда и ĐžŅ‚ĐŋŅ€Đ°Đ˛ĐģŅŅ‚ŅŒ Đ¸Ņ…: + + + +И Đ˛Đ°ŅˆĐĩ **FastAPI** ĐŋŅ€Đ¸ĐģĐžĐļĐĩĐŊиĐĩ ҁ вĐĩĐą-ŅĐžĐēĐĩŅ‚Đ°Đŧи ĐžŅ‚Đ˛ĐĩŅ‚Đ¸Ņ‚: + + + +Đ’Ņ‹ ĐŧĐžĐļĐĩŅ‚Đĩ ĐžŅ‚ĐŋŅ€Đ°Đ˛ĐģŅŅ‚ŅŒ и ĐŋĐžĐģŅƒŅ‡Đ°Ņ‚ŅŒ ĐŧĐŊĐžĐļĐĩŅŅ‚Đ˛Đž ŅĐžĐžĐąŅ‰ĐĩĐŊиК: + + + +И Đ˛ŅĐĩ ĐžĐŊи ĐąŅƒĐ´ŅƒŅ‚ Đ¸ŅĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ŅŒ ОдĐŊĐž и Ņ‚Đž ĐļĐĩ вĐĩĐą-ŅĐžĐēĐĩŅ‚ ŅĐžĐĩдиĐŊĐĩĐŊиĐĩ. + +## Đ˜ŅĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°ĐŊиĐĩ `Depends` и ĐŊĐĩ Ņ‚ĐžĐģҌĐēĐž + +Đ’Ņ‹ ĐŧĐžĐļĐĩŅ‚Đĩ иĐŧĐŋĐžŅ€Ņ‚Đ¸Ņ€ĐžĐ˛Đ°Ņ‚ŅŒ иС `fastapi` и Đ¸ŅĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ŅŒ в ŅĐŊĐ´ĐŋОиĐŊŅ‚Đĩ вĐĩĐąŅĐžĐēĐĩŅ‚Đ°: + +* `Depends` +* `Security` +* `Cookie` +* `Header` +* `Path` +* `Query` + +ОĐŊи Ņ€Đ°ĐąĐžŅ‚Đ°ŅŽŅ‚ Ņ‚Đ°Đē ĐļĐĩ, ĐēаĐē и в Đ´Ņ€ŅƒĐŗĐ¸Ņ… FastAPI ŅĐŊĐ´ĐŋОиĐŊŅ‚Đ°Ņ…/*ĐžĐŋĐĩŅ€Đ°Ņ†Đ¸ŅŅ… ĐŋŅƒŅ‚Đ¸*: + +{* ../../docs_src/websockets/tutorial002_an_py310.py hl[68:69,82] *} + +/// info | ĐŸŅ€Đ¸ĐŧĐĩŅ‡Đ°ĐŊиĐĩ + +В вĐĩĐą-ŅĐžĐēĐĩŅ‚Đĩ Đ˛Ņ‹ĐˇŅ‹Đ˛Đ°Ņ‚ŅŒ `HTTPException` ĐŊĐĩ иĐŧĐĩĐĩŅ‚ ҁĐŧҋҁĐģа. ВĐŧĐĩŅŅ‚Đž ŅŅ‚ĐžĐŗĐž ĐŊ҃ĐļĐŊĐž Đ¸ŅĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ŅŒ `WebSocketException`. + +ЗаĐēŅ€Ņ‹Đ˛Đ°ŅŽŅ‰Đ¸Đš ŅŅ‚Đ°Ņ‚ŅƒŅ ĐēОд ĐŧĐžĐļĐŊĐž Đ¸ŅĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ŅŒ иС valid codes defined in the specification. + +/// + +### ВĐĩĐą-ŅĐžĐēĐĩ҂ҋ ҁ ĐˇĐ°Đ˛Đ¸ŅĐ¸ĐŧĐžŅŅ‚ŅĐŧи: ĐŋŅ€ĐžĐ˛ĐĩŅ€Đēа в Đ´ĐĩĐšŅŅ‚Đ˛Đ¸Đ¸ + +Đ•ŅĐģи Đ˛Đ°Ņˆ Ņ„Đ°ĐšĐģ ĐŊĐ°ĐˇŅ‹Đ˛Đ°ĐĩŅ‚ŅŅ `main.py`, Ņ‚Đž СаĐŋŅƒŅŅ‚Đ¸Ņ‚Đĩ ĐŋŅ€Đ¸ĐģĐžĐļĐĩĐŊиĐĩ ĐēĐžĐŧаĐŊдОК: + +
+ +```console +$ fastapi dev main.py + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +ĐžŅ‚ĐēŅ€ĐžĐšŅ‚Đĩ ĐąŅ€Đ°ŅƒĐˇĐĩŅ€ ĐŋĐž Đ°Đ´Ņ€Đĩҁ҃ http://127.0.0.1:8000. + +ĐĸаĐŧ Đ˛Ņ‹ ĐŧĐžĐļĐĩŅ‚Đĩ ĐˇĐ°Đ´Đ°Ņ‚ŅŒ: + +* "Item ID", Đ¸ŅĐŋĐžĐģŅŒĐˇŅƒĐĩĐŧŅ‹Đš в ĐŋŅƒŅ‚Đ¸. +* "Token", Đ¸ŅĐŋĐžĐģŅŒĐˇŅƒĐĩĐŧŅ‹Đš ĐēаĐē query-ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ. + +/// tip | ĐŸĐžĐ´ŅĐēаСĐēа + +ĐžĐąŅ€Đ°Ņ‚Đ¸Ņ‚Đĩ вĐŊиĐŧаĐŊиĐĩ, Ņ‡Ņ‚Đž query-ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ `token` ĐąŅƒĐ´ĐĩŅ‚ ĐžĐąŅ€Đ°ĐąĐžŅ‚Đ°ĐŊ в ĐˇĐ°Đ˛Đ¸ŅĐ¸ĐŧĐžŅŅ‚Đ¸. + +/// + +ĐĸĐĩĐŋĐĩŅ€ŅŒ Đ˛Ņ‹ ĐŧĐžĐļĐĩŅ‚Đĩ ĐŋОдĐēĐģŅŽŅ‡Đ¸Ņ‚ŅŒŅŅ Đē вĐĩĐą-ŅĐžĐēĐĩŅ‚Ņƒ и ĐŊĐ°Ņ‡Đ¸ĐŊĐ°Ņ‚ŅŒ ĐžŅ‚ĐŋŅ€Đ°Đ˛Đē҃ и ĐŋĐžĐģŅƒŅ‡ĐĩĐŊиĐĩ ŅĐžĐžĐąŅ‰ĐĩĐŊиК: + + + +## ĐžĐąŅ€Đ°ĐąĐžŅ‚Đēа ĐžŅ‚ĐēĐģŅŽŅ‡ĐĩĐŊиК и Ņ€Đ°ĐąĐžŅ‚Đ° ҁ ĐŊĐĩҁĐēĐžĐģҌĐēиĐŧи ĐēĐģиĐĩĐŊŅ‚Đ°Đŧи + +Đ•ŅĐģи вĐĩĐą-ŅĐžĐēĐĩŅ‚ ŅĐžĐĩдиĐŊĐĩĐŊиĐĩ СаĐēŅ€Ņ‹Ņ‚Đž, Ņ‚Đž `await websocket.receive_text()` Đ˛Ņ‹ĐˇĐžĐ˛ĐĩŅ‚ Đ¸ŅĐēĐģŅŽŅ‡ĐĩĐŊиĐĩ `WebSocketDisconnect`, ĐēĐžŅ‚ĐžŅ€ĐžĐĩ ĐŧĐžĐļĐŊĐž ĐŋОКĐŧĐ°Ņ‚ŅŒ и ĐžĐąŅ€Đ°ĐąĐžŅ‚Đ°Ņ‚ŅŒ ĐēаĐē в ŅŅ‚ĐžĐŧ ĐŋŅ€Đ¸ĐŧĐĩŅ€Đĩ: + +{* ../../docs_src/websockets/tutorial003_py39.py hl[79:81] *} + +Đ§Ņ‚ĐžĐąŅ‹ Đ˛ĐžŅĐŋŅ€ĐžĐ¸ĐˇĐ˛ĐĩŅŅ‚Đ¸ ĐŋŅ€Đ¸ĐŧĐĩŅ€: + +* ĐžŅ‚ĐēŅ€ĐžĐšŅ‚Đĩ ĐŋŅ€Đ¸ĐģĐžĐļĐĩĐŊиĐĩ в ĐŊĐĩҁĐēĐžĐģҌĐēĐ¸Ņ… вĐēĐģадĐēĐ°Ņ… ĐąŅ€Đ°ŅƒĐˇĐĩŅ€Đ°. +* ĐžŅ‚ĐŋŅ€Đ°Đ˛ŅŒŅ‚Đĩ иС ĐŊĐ¸Ņ… ŅĐžĐžĐąŅ‰ĐĩĐŊĐ¸Ņ. +* Đ—Đ°Ņ‚ĐĩĐŧ СаĐēŅ€ĐžĐšŅ‚Đĩ ОдĐŊ҃ иС вĐēĐģадОĐē. + +Đ­Ņ‚Đž Đ˛Ņ‹ĐˇĐžĐ˛ĐĩŅ‚ Đ¸ŅĐēĐģŅŽŅ‡ĐĩĐŊиĐĩ `WebSocketDisconnect`, и Đ˛ŅĐĩ ĐžŅŅ‚Đ°ĐģҌĐŊŅ‹Đĩ ĐēĐģиĐĩĐŊ҂ҋ ĐŋĐžĐģŅƒŅ‡Đ°Ņ‚ ҁĐģĐĩĐ´ŅƒŅŽŅ‰ĐĩĐĩ ŅĐžĐžĐąŅ‰ĐĩĐŊиĐĩ: + +``` +Client #1596980209979 left the chat +``` + +/// tip | ĐŸŅ€Đ¸ĐŧĐĩŅ‡Đ°ĐŊиĐĩ + +ĐŸŅ€Đ¸ĐģĐžĐļĐĩĐŊиĐĩ Đ˛Ņ‹ŅˆĐĩ - ŅŅ‚Đž Đ˛ŅĐĩĐŗĐž ĐģĐ¸ŅˆŅŒ ĐŋŅ€ĐžŅŅ‚ĐžĐš ĐŧиĐŊиĐŧаĐģҌĐŊŅ‹Đš ĐŋŅ€Đ¸ĐŧĐĩŅ€, Đ´ĐĩĐŧĐžĐŊŅŅ‚Ņ€Đ¸Ņ€ŅƒŅŽŅ‰Đ¸Đš ĐžĐąŅ€Đ°ĐąĐžŅ‚Đē҃ и ĐŋĐĩŅ€ĐĩĐ´Đ°Ņ‡Ņƒ ŅĐžĐžĐąŅ‰ĐĩĐŊиК ĐŊĐĩҁĐēĐžĐģҌĐēиĐŧ вĐĩĐą-ŅĐžĐēĐĩŅ‚ ŅĐžĐĩдиĐŊĐĩĐŊĐ¸ŅĐŧ. + +Но иĐŧĐĩĐšŅ‚Đĩ в Đ˛Đ¸Đ´Ņƒ, Ņ‡Ņ‚Đž ŅŅ‚Đž ĐąŅƒĐ´ĐĩŅ‚ Ņ€Đ°ĐąĐžŅ‚Đ°Ņ‚ŅŒ Ņ‚ĐžĐģҌĐēĐž в ОдĐŊĐžĐŧ ĐŋŅ€ĐžŅ†ĐĩҁҁĐĩ и Ņ‚ĐžĐģҌĐēĐž ĐŋĐžĐēа ĐžĐŊ аĐēŅ‚Đ¸Đ˛ĐĩĐŊ, Ņ‚Đ°Đē ĐēаĐē Đ˛ŅŅ‘ ĐžĐąŅ€Đ°ĐąĐ°Ņ‚Ņ‹Đ˛Đ°ĐĩŅ‚ŅŅ в ĐŋŅ€ĐžŅŅ‚ĐžĐŧ ҁĐŋĐ¸ŅĐēĐĩ в ĐžĐŋĐĩŅ€Đ°Ņ‚Đ¸Đ˛ĐŊОК ĐŋаĐŧŅŅ‚Đ¸. + +Đ•ŅĐģи ĐŊ҃ĐļĐŊĐž Ņ‡Ņ‚Đž-Ņ‚Đž ĐģĐĩĐŗĐēĐž иĐŊŅ‚ĐĩĐŗŅ€Đ¸Ņ€ŅƒĐĩĐŧĐžĐĩ ҁ FastAPI, ĐŊĐž йОĐģĐĩĐĩ ĐŊадĐĩĐļĐŊĐžĐĩ и ҁ ĐŋОддĐĩŅ€ĐļĐēОК Redis, PostgreSQL иĐģи Đ´Ņ€ŅƒĐŗĐžĐŗĐž, Ņ‚Đž ĐŧĐžĐļĐŊĐž Đ˛ĐžŅĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ŅŒŅŅ encode/broadcaster. + +/// + +## ДоĐŋĐžĐģĐŊĐ¸Ņ‚ĐĩĐģҌĐŊĐ°Ņ иĐŊŅ„ĐžŅ€ĐŧĐ°Ņ†Đ¸Ņ + +ДĐģŅ йОĐģĐĩĐĩ ĐŗĐģŅƒĐąĐžĐēĐžĐŗĐž Đ¸ĐˇŅƒŅ‡ĐĩĐŊĐ¸Ņ Ņ‚ĐĩĐŧŅ‹ Đ˛ĐžŅĐŋĐžĐģŅŒĐˇŅƒĐšŅ‚ĐĩҁҌ Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Đ¸ĐĩĐš Starlette: + +* The `WebSocket` class. +* Class-based WebSocket handling. diff --git a/docs/ru/docs/deployment/concepts.md b/docs/ru/docs/deployment/concepts.md index 7cdc29526..acfa1f4fe 100644 --- a/docs/ru/docs/deployment/concepts.md +++ b/docs/ru/docs/deployment/concepts.md @@ -216,7 +216,7 @@ КаĐļĐ´Ņ‹Đš иС ŅŅ‚Đ¸Ņ… ĐŋŅ€ĐžŅ†ĐĩŅŅĐžĐ˛ ĐąŅƒĐ´ĐĩŅ‚ СаĐŋ҃ҁĐēĐ°Ņ‚ŅŒ Đ˛Đ°ŅˆĐĩ ĐŋŅ€Đ¸ĐģĐžĐļĐĩĐŊиĐĩ Đ´ĐģŅ ĐžĐąŅ€Đ°ĐąĐžŅ‚Đēи ĐŋĐžĐģŅƒŅ‡ĐĩĐŊĐŊĐžĐŗĐž **СаĐŋŅ€ĐžŅĐ°** и Đ˛ĐžĐˇĐ˛Ņ€Đ°Ņ‰ĐĩĐŊĐ¸Ņ Đ˛Ņ‹Ņ‡Đ¸ŅĐģĐĩĐŊĐŊĐžĐŗĐž **ĐžŅ‚Đ˛ĐĩŅ‚Đ°** и ĐžĐŊи ĐąŅƒĐ´ŅƒŅ‚ Đ¸ŅĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ŅŒ ĐžĐŋĐĩŅ€Đ°Ņ‚Đ¸Đ˛ĐŊŅƒŅŽ ĐŋаĐŧŅŅ‚ŅŒ. - + БĐĩĐˇŅƒŅĐģОвĐŊĐž, ĐŊа ŅŅ‚ĐžĐŧ ĐļĐĩ ҁĐĩŅ€Đ˛ĐĩŅ€Đĩ ĐąŅƒĐ´ŅƒŅ‚ Ņ€Đ°ĐąĐžŅ‚Đ°Ņ‚ŅŒ и **Đ´Ņ€ŅƒĐŗĐ¸Đĩ ĐŋŅ€ĐžŅ†Đĩҁҁҋ**, ĐēĐžŅ‚ĐžŅ€Ņ‹Đĩ ĐŊĐĩ ĐžŅ‚ĐŊĐžŅŅŅ‚ŅŅ Đē Đ˛Đ°ŅˆĐĩĐŧ҃ ĐŋŅ€Đ¸ĐģĐžĐļĐĩĐŊĐ¸ŅŽ. diff --git a/docs/ru/docs/deployment/https.md b/docs/ru/docs/deployment/https.md index 85c4cce60..d8877a9a1 100644 --- a/docs/ru/docs/deployment/https.md +++ b/docs/ru/docs/deployment/https.md @@ -92,7 +92,7 @@ DNS-ҁĐĩŅ€Đ˛ĐĩŅ€Đ° ĐŋŅ€Đ¸ŅŅ‹ĐģĐ°ŅŽŅ‚ ĐąŅ€Đ°ŅƒĐˇĐĩŅ€Ņƒ ĐžĐŋŅ€ĐĩĐ´ĐĩĐģŅ‘ĐŊĐŊŅ‹Đš **IP-Đ°Đ´Ņ€Đĩҁ**, Ņ‚ĐžŅ‚ ŅĐ°ĐŧŅ‹Đš ĐŋŅƒĐąĐģĐ¸Ņ‡ĐŊŅ‹Đš IP-Đ°Đ´Ņ€Đĩҁ Đ˛Đ°ŅˆĐĩĐŗĐž ҁĐĩŅ€Đ˛ĐĩŅ€Đ°, ĐēĐžŅ‚ĐžŅ€Ņ‹Đš Đ˛Ņ‹ ҃ĐēаСаĐģи в Ņ€ĐĩŅŅƒŅ€ŅĐŊОК "СаĐŋĐ¸ŅĐ¸ А" ĐŋŅ€Đ¸ ĐŊĐ°ŅŅ‚Ņ€ĐžĐšĐēĐĩ. - + ### Đ ŅƒĐēĐžĐŋĐžĐļĐ°Ņ‚Đ¸Đĩ TLS @@ -100,7 +100,7 @@ DNS-ҁĐĩŅ€Đ˛ĐĩŅ€Đ° ĐŋŅ€Đ¸ŅŅ‹ĐģĐ°ŅŽŅ‚ ĐąŅ€Đ°ŅƒĐˇĐĩŅ€Ņƒ ĐžĐŋŅ€ĐĩĐ´ĐĩĐģŅ‘ĐŊĐŊŅ‹Đš ПĐĩŅ€Đ˛Ņ‹Đŧ ŅˆĐ°ĐŗĐžĐŧ ĐąŅƒĐ´ĐĩŅ‚ ŅƒŅŅ‚Đ°ĐŊОвĐģĐĩĐŊиĐĩ ŅĐžĐĩдиĐŊĐĩĐŊĐ¸Ņ ĐŧĐĩĐļĐ´Ņƒ ĐēĐģиĐĩĐŊŅ‚ĐžĐŧ (ĐąŅ€Đ°ŅƒĐˇĐĩŅ€ĐžĐŧ) и ҁĐĩŅ€Đ˛ĐĩŅ€ĐžĐŧ и Đ˛Ņ‹ĐąĐžŅ€ ĐēŅ€Đ¸ĐŋŅ‚ĐžĐŗŅ€Đ°Ņ„Đ¸Ņ‡ĐĩҁĐēĐžĐŗĐž ĐēĐģŅŽŅ‡Đ° (Đ´ĐģŅ ŅˆĐ¸Ņ„Ņ€ĐžĐ˛Đ°ĐŊĐ¸Ņ). - + Đ­Ņ‚Đ° Ņ‡Đ°ŅŅ‚ŅŒ ĐēĐģиĐĩĐŊŅ‚-ҁĐĩŅ€Đ˛ĐĩŅ€ĐŊĐžĐŗĐž вСаиĐŧОдĐĩĐšŅŅ‚Đ˛Đ¸Ņ ŅƒŅŅ‚Đ°ĐŊавĐģиваĐĩŅ‚ TLS-ŅĐžĐĩдиĐŊĐĩĐŊиĐĩ и ĐŊĐ°ĐˇŅ‹Đ˛Đ°ĐĩŅ‚ŅŅ **TLS-Ņ€ŅƒĐēĐžĐŋĐžĐļĐ°Ņ‚Đ¸ĐĩĐŧ**. @@ -118,7 +118,7 @@ DNS-ҁĐĩŅ€Đ˛ĐĩŅ€Đ° ĐŋŅ€Đ¸ŅŅ‹ĐģĐ°ŅŽŅ‚ ĐąŅ€Đ°ŅƒĐˇĐĩŅ€Ņƒ ĐžĐŋŅ€ĐĩĐ´ĐĩĐģŅ‘ĐŊĐŊŅ‹Đš ĐĸĐž ĐĩŅŅ‚ŅŒ ĐąŅƒĐ´ĐĩŅ‚ Đ˛Ņ‹ĐąŅ€Đ°ĐŊ ҁĐĩŅ€Ņ‚Đ¸Ņ„Đ¸ĐēĐ°Ņ‚ Đ´ĐģŅ Đ´ĐžĐŧĐĩĐŊа `someapp.example.com`. - + КĐģиĐĩĐŊŅ‚ ҃ĐļĐĩ **дОвĐĩŅ€ŅĐĩŅ‚** Ņ‚ĐžĐŧ҃, ĐēŅ‚Đž Đ˛Ņ‹Đ´Đ°Đģ ŅŅ‚ĐžŅ‚ TLS-ҁĐĩŅ€Ņ‚Đ¸Ņ„Đ¸ĐēĐ°Ņ‚ (в ĐŊĐ°ŅˆĐĩĐŧ ҁĐģŅƒŅ‡Đ°Đĩ - Let's Encrypt, ĐŊĐž ĐŧŅ‹ Đĩ҉ґ ĐžĐąŅŅƒĐ´Đ¸Đŧ ŅŅ‚Đž), ĐŋĐžŅ‚ĐžĐŧ҃ ĐŧĐžĐļĐĩŅ‚ **ĐŋŅ€ĐžĐ˛ĐĩŅ€Đ¸Ņ‚ŅŒ**, Đ´ĐĩĐšŅŅ‚Đ˛Đ¸Ņ‚ĐĩĐģĐĩĐŊ Đģи ĐŋĐžĐģŅƒŅ‡ĐĩĐŊĐŊŅ‹Đš ĐžŅ‚ ҁĐĩŅ€Đ˛ĐĩŅ€Đ° ҁĐĩŅ€Ņ‚Đ¸Ņ„Đ¸ĐēĐ°Ņ‚. @@ -140,19 +140,19 @@ DNS-ҁĐĩŅ€Đ˛ĐĩŅ€Đ° ĐŋŅ€Đ¸ŅŅ‹ĐģĐ°ŅŽŅ‚ ĐąŅ€Đ°ŅƒĐˇĐĩŅ€Ņƒ ĐžĐŋŅ€ĐĩĐ´ĐĩĐģŅ‘ĐŊĐŊŅ‹Đš ĐĸаĐē ĐēĐģиĐĩĐŊŅ‚ ĐžŅ‚ĐŋŅ€Đ°Đ˛ĐģŅĐĩŅ‚ **HTTPS-СаĐŋŅ€ĐžŅ**. ĐĸĐž ĐĩŅŅ‚ŅŒ ĐžĐąŅ‹Ņ‡ĐŊŅ‹Đš HTTP-СаĐŋŅ€ĐžŅ, ĐŊĐž ҇ĐĩŅ€ĐĩС ĐˇĐ°ŅˆĐ¸Ņ„Ņ€ĐžĐ˛Đ°ĐŊĐŊĐžĐĩ TLS-ŅĐžĐ´Đ¸ĐŊĐĩĐŊиĐĩ. - + ### Đ Đ°ŅŅˆĐ¸Ņ„Ņ€ĐžĐ˛Đēа СаĐŋŅ€ĐžŅĐ° ĐŸŅ€ĐžĐēŅĐ¸-ҁĐĩŅ€Đ˛ĐĩŅ€, Đ¸ŅĐŋĐžĐģŅŒĐˇŅƒŅ ŅĐžĐŗĐģĐ°ŅĐžĐ˛Đ°ĐŊĐŊŅ‹Đš ҁ ĐēĐģиĐĩĐŊŅ‚ĐžĐŧ ĐēĐģŅŽŅ‡, Ņ€Đ°ŅŅˆĐ¸Ņ„Ņ€ŅƒĐĩŅ‚ ĐŋĐžĐģŅƒŅ‡ĐĩĐŊĐŊŅ‹Đš **ĐˇĐ°ŅˆĐ¸Ņ„Ņ€ĐžĐ˛Đ°ĐŊĐŊŅ‹Đš СаĐŋŅ€ĐžŅ** и ĐŋĐĩŅ€ĐĩĐ´Đ°ŅŅ‚ **ĐžĐąŅ‹Ņ‡ĐŊŅ‹Đš (ĐŊĐĩĐˇĐ°ŅˆĐ¸Ņ„Ņ€ĐžĐ˛Đ°ĐŊĐŊŅ‹Đš) HTTP-СаĐŋŅ€ĐžŅ** ĐŋŅ€ĐžŅ†Đĩҁҁ҃, СаĐŋ҃ҁĐēĐ°ŅŽŅ‰ĐĩĐŧ҃ ĐŋŅ€Đ¸ĐģĐžĐļĐĩĐŊиĐĩ (ĐŊаĐŋŅ€Đ¸ĐŧĐĩŅ€, ĐŋŅ€ĐžŅ†Đĩҁҁ҃ Uvicorn СаĐŋ҃ҁĐēĐ°ŅŽŅ‰ĐĩĐŧ҃ ĐŋŅ€Đ¸ĐģĐžĐļĐĩĐŊиĐĩ FastAPI). - + ### HTTP-ĐžŅ‚Đ˛ĐĩŅ‚ ĐŸŅ€Đ¸ĐģĐžĐļĐĩĐŊиĐĩ ĐžĐąŅ€Đ°ĐąĐžŅ‚Đ°ĐĩŅ‚ СаĐŋŅ€ĐžŅ и вĐĩŅ€ĐŊґ҂ **ĐžĐąŅ‹Ņ‡ĐŊŅ‹Đš (ĐŊĐĩĐˇĐ°ŅˆĐ¸Ņ„Ņ€ĐžĐ˛Đ°ĐŊĐŊŅ‹Đš) HTTP-ĐžŅ‚Đ˛ĐĩŅ‚** ĐŋŅ€ĐžĐēŅĐ¸-ҁĐĩŅ€Đ˛ĐĩŅ€Ņƒ. - + ### HTTPS-ĐžŅ‚Đ˛ĐĩŅ‚ @@ -160,7 +160,7 @@ DNS-ҁĐĩŅ€Đ˛ĐĩŅ€Đ° ĐŋŅ€Đ¸ŅŅ‹ĐģĐ°ŅŽŅ‚ ĐąŅ€Đ°ŅƒĐˇĐĩŅ€Ņƒ ĐžĐŋŅ€ĐĩĐ´ĐĩĐģŅ‘ĐŊĐŊŅ‹Đš НаĐēĐžĐŊĐĩ҆, ĐąŅ€Đ°ŅƒĐˇĐĩŅ€ ĐŋŅ€ĐžĐ˛ĐĩŅ€Đ¸Ņ‚ ĐžŅ‚Đ˛ĐĩŅ‚, в Ņ‚ĐžĐŧ Ņ‡Đ¸ŅĐģĐĩ, Ņ‡Ņ‚Đž Ņ‚ĐžŅ‚ ĐˇĐ°ŅˆĐ¸Ņ„Ņ€ĐžĐ˛Đ°ĐŊ ҁ ĐŊ҃ĐļĐŊŅ‹Đŧ ĐēĐģŅŽŅ‡ĐžĐŧ, **Ņ€Đ°ŅŅˆĐ¸Ņ„Ņ€ŅƒĐĩŅ‚ ĐĩĐŗĐž** и ĐžĐąŅ€Đ°ĐąĐžŅ‚Đ°ĐĩŅ‚. - + КĐģиĐĩĐŊŅ‚ (ĐąŅ€Đ°ŅƒĐˇĐĩŅ€) СĐŊаĐĩŅ‚, Ņ‡Ņ‚Đž ĐžŅ‚Đ˛ĐĩŅ‚ ĐŋŅ€Đ¸ŅˆŅ‘Đģ ĐžŅ‚ ĐŋŅ€Đ°Đ˛Đ¸ĐģҌĐŊĐžĐŗĐž ҁĐĩŅ€Đ˛ĐĩŅ€Đ°, Ņ‚Đ°Đē ĐēаĐē Đ¸ŅĐŋĐžĐģŅŒĐˇŅƒĐĩŅ‚ ĐŧĐĩŅ‚ĐžĐ´Ņ‹ ŅˆĐ¸Ņ„Ņ€ĐžĐ˛Đ°ĐŊĐ¸Ņ, ŅĐžĐŗĐģĐ°ŅĐžĐ˛Đ°ĐŊĐŊŅ‹Đĩ иĐŧи Ņ€Đ°ĐŊĐŊĐĩĐĩ ҇ĐĩŅ€ĐĩС **HTTPS-ҁĐĩŅ€Ņ‚Đ¸Ņ„Đ¸ĐēĐ°Ņ‚**. @@ -171,7 +171,7 @@ DNS-ҁĐĩŅ€Đ˛ĐĩŅ€Đ° ĐŋŅ€Đ¸ŅŅ‹ĐģĐ°ŅŽŅ‚ ĐąŅ€Đ°ŅƒĐˇĐĩŅ€Ņƒ ĐžĐŋŅ€ĐĩĐ´ĐĩĐģŅ‘ĐŊĐŊŅ‹Đš НаĐŋĐžĐŧĐŊŅŽ, Ņ‡Ņ‚Đž Ņ‚ĐžĐģҌĐēĐž ОдиĐŊ ĐŋŅ€ĐžŅ†Đĩҁҁ (ĐŊаĐŋŅ€Đ¸ĐŧĐĩŅ€, ĐŋŅ€ĐžĐēŅĐ¸-ҁĐĩŅ€Đ˛ĐĩŅ€) ĐŧĐžĐļĐĩŅ‚ ĐŋŅ€ĐžŅĐģŅƒŅˆĐ¸Đ˛Đ°Ņ‚ŅŒ ĐžĐŋŅ€ĐĩĐ´ĐĩĐģŅ‘ĐŊĐŊŅ‹Đš ĐŋĐžŅ€Ņ‚ ĐžĐŋŅ€ĐĩĐ´ĐĩĐģŅ‘ĐŊĐŊĐžĐŗĐž IP-Đ°Đ´Ņ€ĐĩŅĐ°. Но Đ´Ņ€ŅƒĐŗĐ¸Đĩ ĐŋŅ€ĐžŅ†Đĩҁҁҋ и ĐŋŅ€Đ¸ĐģĐžĐļĐĩĐŊĐ¸Ņ Ņ‚ĐžĐļĐĩ ĐŧĐžĐŗŅƒŅ‚ Ņ€Đ°ĐąĐžŅ‚Đ°Ņ‚ŅŒ ĐŊа ŅŅ‚ĐžĐŧ ĐļĐĩ ҁĐĩŅ€Đ˛ĐĩŅ€Đĩ (ҁĐĩŅ€Đ˛ĐĩŅ€Đ°Ņ…), ĐĩҁĐģи ĐžĐŊи ĐŊĐĩ ĐŋŅ‹Ņ‚Đ°ŅŽŅ‚ŅŅ Đ¸ŅĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ŅŒ ҃ĐļĐĩ СаĐŊŅŅ‚ŅƒŅŽ **ĐēĐžĐŧйиĐŊĐ°Ņ†Đ¸ŅŽ IP-Đ°Đ´Ņ€ĐĩŅĐ° и ĐŋĐžŅ€Ņ‚Đ°** (ŅĐžĐēĐĩŅ‚). - + ĐĸаĐēиĐŧ ĐžĐąŅ€Đ°ĐˇĐžĐŧ, ҁĐĩŅ€Đ˛ĐĩŅ€ СавĐĩŅ€ŅˆĐĩĐŊĐ¸Ņ TLS ĐŧĐžĐļĐĩŅ‚ ĐžĐąŅ€Đ°ĐąĐ°Ņ‚Ņ‹Đ˛Đ°Ņ‚ŅŒ HTTPS-СаĐŋŅ€ĐžŅŅ‹ и Đ¸ŅĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ŅŒ ҁĐĩŅ€Ņ‚Đ¸Ņ„Đ¸ĐēĐ°Ņ‚Ņ‹ Đ´ĐģŅ **ĐŧĐŊĐžĐļĐĩŅŅ‚Đ˛Đ° Đ´ĐžĐŧĐĩĐŊОв** иĐģи ĐŋŅ€Đ¸ĐģĐžĐļĐĩĐŊиК и ĐŋĐĩŅ€ĐĩĐ´Đ°Đ˛Đ°Ņ‚ŅŒ СаĐŋŅ€ĐžŅŅ‹ ĐŋŅ€Đ°Đ˛Đ¸ĐģҌĐŊŅ‹Đŧ Đ°Đ´Ņ€ĐĩŅĐ°Ņ‚Đ°Đŧ (Đ´Ņ€ŅƒĐŗĐ¸Đŧ ĐŋŅ€Đ¸ĐģĐžĐļĐĩĐŊĐ¸ŅĐŧ). @@ -181,7 +181,7 @@ DNS-ҁĐĩŅ€Đ˛ĐĩŅ€Đ° ĐŋŅ€Đ¸ŅŅ‹ĐģĐ°ŅŽŅ‚ ĐąŅ€Đ°ŅƒĐˇĐĩŅ€Ņƒ ĐžĐŋŅ€ĐĩĐ´ĐĩĐģŅ‘ĐŊĐŊŅ‹Đš ĐšĐžĐŗĐ´Đ° ŅŅ‚Đž ĐŋŅ€ĐžĐ¸ĐˇĐžĐšĐ´Ņ‘Ņ‚, ĐŧĐžĐļĐŊĐž СаĐŋŅƒŅŅ‚Đ¸Ņ‚ŅŒ Đ´Ņ€ŅƒĐŗŅƒŅŽ ĐŋŅ€ĐžĐŗŅ€Đ°ĐŧĐŧ҃, ĐēĐžŅ‚ĐžŅ€Đ°Ņ ĐŋОдĐēĐģŅŽŅ‡Đ¸Ņ‚ŅŅ Đē Let's Encrypt и ОйĐŊĐžĐ˛Đ¸Ņ‚ ҁĐĩŅ€Ņ‚Đ¸Ņ„Đ¸ĐēĐ°Ņ‚(Ņ‹). ĐĄŅƒŅ‰ĐĩŅŅ‚Đ˛ŅƒŅŽŅ‚ ĐŋŅ€ĐžĐēŅĐ¸-ҁĐĩŅ€Đ˛ĐĩҀҋ, ĐēĐžŅ‚ĐžŅ€Ņ‹Đĩ ĐŧĐžĐŗŅƒŅ‚ ŅĐ´ĐĩĐģĐ°Ņ‚ŅŒ ŅŅ‚Đž Đ´ĐĩĐšŅŅ‚Đ˛Đ¸Đĩ ŅĐ°ĐŧĐžŅŅ‚ĐžŅŅ‚ĐĩĐģҌĐŊĐž. - + **TLS-ҁĐĩŅ€Ņ‚Đ¸Ņ„Đ¸ĐēĐ°Ņ‚Ņ‹** ĐŊĐĩ ĐŋŅ€Đ¸Đ˛ŅĐˇĐ°ĐŊŅ‹ Đē IP-Đ°Đ´Ņ€Đĩҁ҃, ĐŊĐž **ŅĐ˛ŅĐˇĐ°ĐŊŅ‹ ҁ иĐŧĐĩĐŊĐĩĐŧ Đ´ĐžĐŧĐĩĐŊа**. diff --git a/docs/ru/docs/index.md b/docs/ru/docs/index.md index 5ebe1494b..a9546cf1e 100644 --- a/docs/ru/docs/index.md +++ b/docs/ru/docs/index.md @@ -12,10 +12,10 @@

- Test + Test - - Coverage + + Coverage Package version diff --git a/docs/ru/docs/tutorial/bigger-applications.md b/docs/ru/docs/tutorial/bigger-applications.md index 7c3dc288f..8b9080d39 100644 --- a/docs/ru/docs/tutorial/bigger-applications.md +++ b/docs/ru/docs/tutorial/bigger-applications.md @@ -52,7 +52,7 @@ from app.routers import items * ПодĐēĐ°Ņ‚Đ°ĐģĐžĐŗ `app/internal/`, ŅĐžĐ´ĐĩŅ€ĐļĐ°Ņ‰Đ¸Đš Ņ„Đ°ĐšĐģ `__init__.py`, ŅĐ˛ĐģŅĐĩŅ‚ŅŅ Đĩ҉ґ ОдĐŊиĐŧ ŅŅƒĐą-ĐŋаĐēĐĩŅ‚ĐžĐŧ: `app.internal`. * А Ņ„Đ°ĐšĐģ `app/internal/admin.py` ŅĐ˛ĐģŅĐĩŅ‚ŅŅ Đĩ҉ґ ОдĐŊиĐŧ ŅŅƒĐą-ĐŧĐžĐ´ŅƒĐģĐĩĐŧ: `app.internal.admin`. - + Đĸа ĐļĐĩ ŅĐ°ĐŧĐ°Ņ Ņ„Đ°ĐšĐģĐžĐ˛Đ°Ņ ŅŅ‚Ņ€ŅƒĐēŅ‚ŅƒŅ€Đ° ĐŋŅ€Đ¸ĐģĐžĐļĐĩĐŊĐ¸Ņ, ĐŊĐž ҁ ĐēĐžĐŧĐŧĐĩĐŊŅ‚Đ°Ņ€Đ¸ŅĐŧи: @@ -269,7 +269,7 @@ from .dependencies import get_token_header Đ’ŅĐŋĐžĐŧĐŊĐ¸Ņ‚Đĩ, ĐēаĐē Đ˛Ņ‹ĐŗĐģŅĐ´Đ¸Ņ‚ Ņ„Đ°ĐšĐģĐžĐ˛Đ°Ņ ŅŅ‚Ņ€ŅƒĐēŅ‚ŅƒŅ€Đ° ĐŊĐ°ŅˆĐĩĐŗĐž ĐŋŅ€Đ¸ĐģĐžĐļĐĩĐŊĐ¸Ņ: - + --- diff --git a/docs/ru/docs/tutorial/cookie-param-models.md b/docs/ru/docs/tutorial/cookie-param-models.md new file mode 100644 index 000000000..3a57443bb --- /dev/null +++ b/docs/ru/docs/tutorial/cookie-param-models.md @@ -0,0 +1,76 @@ +# МодĐĩĐģи ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€ĐžĐ˛ cookie + +Đ•ŅĐģи ҃ Đ˛Đ°Ņ ĐĩŅŅ‚ŅŒ ĐŗŅ€ŅƒĐŋĐŋа **cookies**, ĐēĐžŅ‚ĐžŅ€Ņ‹Đĩ ŅĐ˛ŅĐˇĐ°ĐŊŅ‹ ĐŧĐĩĐļĐ´Ņƒ ŅĐžĐąĐžĐš, Đ˛Ņ‹ ĐŧĐžĐļĐĩŅ‚Đĩ ŅĐžĐˇĐ´Đ°Ņ‚ŅŒ **Pydantic-ĐŧОдĐĩĐģҌ** Đ´ĐģŅ Đ¸Ņ… ĐžĐąŅŠŅĐ˛ĐģĐĩĐŊĐ¸Ņ. đŸĒ + +Đ­Ņ‚Đž ĐŋОСвОĐģĐ¸Ņ‚ ваĐŧ **ĐŋĐĩŅ€ĐĩĐ¸ŅĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ŅŒ ĐŧОдĐĩĐģҌ** в **Ņ€Đ°ĐˇĐŊҋ҅ ĐŧĐĩŅŅ‚Đ°Ņ…**, а Ņ‚Đ°ĐēĐļĐĩ ĐžĐąŅŠŅĐ˛Đ¸Ņ‚ŅŒ ĐŋŅ€ĐžĐ˛ĐĩŅ€Đēи и ĐŧĐĩŅ‚Đ°Đ´Đ°ĐŊĐŊŅ‹Đĩ ŅŅ€Đ°ĐˇŅƒ Đ´ĐģŅ Đ˛ŅĐĩŅ… ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€ĐžĐ˛. 😎 + +/// note | ЗаĐŧĐĩŅ‚Đēа + +Đ­Ņ‚ĐžŅ‚ Ņ„ŅƒĐŊĐēŅ†Đ¸ĐžĐŊаĐģ Đ´ĐžŅŅ‚ŅƒĐŋĐĩĐŊ ҁ вĐĩŅ€ŅĐ¸Đ¸ `0.115.0`. 🤓 + +/// + +/// tip | ХОвĐĩŅ‚ + +ĐĸаĐēОК ĐļĐĩ ĐŋĐžĐ´Ņ…ĐžĐ´ ĐŋŅ€Đ¸ĐŧĐĩĐŊŅĐĩŅ‚ŅŅ Đ´ĐģŅ `Query`, `Cookie`, и `Header`. 😎 + +/// + +## Pydantic-ĐŧОдĐĩĐģҌ Đ´ĐģŅ cookies + +ĐžĐąŅŠŅĐ˛Đ¸Ņ‚Đĩ ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁҋ **cookie**, ĐēĐžŅ‚ĐžŅ€Ņ‹Đĩ ваĐŧ ĐŊ҃ĐļĐŊŅ‹, в **Pydantic-ĐŧОдĐĩĐģи**, а ĐˇĐ°Ņ‚ĐĩĐŧ ĐžĐąŅŠŅĐ˛Đ¸Ņ‚Đĩ ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ ĐēаĐē `Cookie`: + +{* ../../docs_src/cookie_param_models/tutorial001_an_py310.py hl[9:12,16] *} + +**FastAPI** **иСвĐģĐĩ҇ґ҂** даĐŊĐŊŅ‹Đĩ Đ´ĐģŅ **ĐēаĐļĐ´ĐžĐŗĐž ĐŋĐžĐģŅ** иС **cookies**, ĐŋĐžĐģŅƒŅ‡ĐĩĐŊĐŊҋ҅ в СаĐŋŅ€ĐžŅĐĩ, и Đ˛Ņ‹Đ´Đ°ŅŅ‚ ваĐŧ ĐžĐąŅŠŅĐ˛ĐģĐĩĐŊĐŊŅƒŅŽ Pydantic-ĐŧОдĐĩĐģҌ. + +## ĐŸŅ€ĐžĐ˛ĐĩŅ€Đēа ŅĐŗĐĩĐŊĐĩŅ€Đ¸Ņ€ĐžĐ˛Đ°ĐŊĐŊОК Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Đ¸Đ¸ + +Đ’Ņ‹ ĐŧĐžĐļĐĩŅ‚Đĩ ĐŋĐžŅĐŧĐžŅ‚Ņ€ĐĩŅ‚ŅŒ ĐžĐąŅŠŅĐ˛ĐģĐĩĐŊĐŊŅ‹Đĩ cookies в ĐŗŅ€Đ°Ņ„Đ¸Ņ‡ĐĩҁĐēĐžĐŧ иĐŊŅ‚ĐĩҀ҄ĐĩĐšŅĐĩ ДоĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Đ¸Đ¸ ĐŋĐž ĐŋŅƒŅ‚Đ¸ `/docs`: + +

+ +
+ +/// info | ДоĐŋĐžĐģĐŊĐ¸Ņ‚ĐĩĐģҌĐŊĐ°Ņ иĐŊŅ„ĐžŅ€ĐŧĐ°Ņ†Đ¸Ņ + +ИĐŧĐĩĐšŅ‚Đĩ в Đ˛Đ¸Đ´Ņƒ, Ņ‡Ņ‚Đž, ĐŋĐžŅĐēĐžĐģҌĐē҃ **ĐąŅ€Đ°ŅƒĐˇĐĩҀҋ ĐžĐąŅ€Đ°ĐąĐ°Ņ‚Ņ‹Đ˛Đ°ŅŽŅ‚ cookies** ĐžŅĐžĐąŅ‹Đŧ ĐžĐąŅ€Đ°ĐˇĐžĐŧ и ĐŋОд ĐēаĐŋĐžŅ‚ĐžĐŧ, ĐžĐŊи **ĐŊĐĩ** ĐŋОСвОĐģŅŅ‚ **JavaScript** ĐģĐĩĐŗĐēĐž ĐŋĐžĐģŅƒŅ‡Đ¸Ņ‚ŅŒ Đ´ĐžŅŅ‚ŅƒĐŋ Đē ĐŊиĐŧ. + +Đ•ŅĐģи Đ˛Ņ‹ ĐŋĐĩŅ€ĐĩĐšĐ´Ņ‘Ņ‚Đĩ Đē **ĐŗŅ€Đ°Ņ„Đ¸Ņ‡ĐĩҁĐēĐžĐŧ҃ иĐŊŅ‚ĐĩҀ҄ĐĩĐšŅŅƒ Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Đ¸Đ¸ API** ĐŋĐž ĐŋŅƒŅ‚Đ¸ `/docs`, Ņ‚Đž ҁĐŧĐžĐļĐĩŅ‚Đĩ ŅƒĐ˛Đ¸Đ´ĐĩŅ‚ŅŒ **Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Đ¸ŅŽ** ĐŋĐž cookies Đ´ĐģŅ Đ˛Đ°ŅˆĐ¸Ņ… *ĐžĐŋĐĩŅ€Đ°Ņ†Đ¸Đš ĐŋŅƒŅ‚ĐĩĐš*. + +Но даĐļĐĩ ĐĩҁĐģи Đ˛Ņ‹ **СаĐŋĐžĐģĐŊĐ¸Ņ‚Đĩ даĐŊĐŊŅ‹Đĩ** и ĐŊаĐļĐŧґ҂Đĩ "Execute", ĐŋĐžŅĐēĐžĐģҌĐē҃ ĐŗŅ€Đ°Ņ„Đ¸Ņ‡ĐĩҁĐēиК иĐŊŅ‚ĐĩҀ҄ĐĩĐšŅ ДоĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Đ¸Đ¸ Ņ€Đ°ĐąĐžŅ‚Đ°ĐĩŅ‚ ҁ **JavaScript**, cookies ĐŊĐĩ ĐąŅƒĐ´ŅƒŅ‚ ĐžŅ‚ĐŋŅ€Đ°Đ˛ĐģĐĩĐŊŅ‹, и Đ˛Ņ‹ ŅƒĐ˛Đ¸Đ´Đ¸Ņ‚Đĩ ŅĐžĐžĐąŅ‰ĐĩĐŊиĐĩ Ой **ĐžŅˆĐ¸ĐąĐēĐĩ** ĐēаĐē ĐąŅƒĐ´Ņ‚Đž ĐŊĐĩ ҃ĐēĐ°ĐˇŅ‹Đ˛Đ°Đģи ĐŊиĐēаĐēĐ¸Ņ… СĐŊĐ°Ņ‡ĐĩĐŊиК. + +/// + +## ЗаĐŋŅ€ĐĩŅ‚ Đ´ĐžĐŋĐžĐģĐŊĐ¸Ņ‚ĐĩĐģҌĐŊҋ҅ cookies + +В ĐŊĐĩĐēĐžŅ‚ĐžŅ€Ņ‹Ņ… ҁĐģŅƒŅ‡Đ°ŅŅ… (ĐŊĐĩ ĐžŅĐžĐąĐž Ņ‡Đ°ŅŅ‚Đž Đ˛ŅŅ‚Ņ€ĐĩŅ‡Đ°ŅŽŅ‰Đ¸Ņ…ŅŅ) ваĐŧ ĐŧĐžĐļĐĩŅ‚ ĐŋĐžĐŊĐ°Đ´ĐžĐąĐ¸Ņ‚ŅŒŅŅ **ĐžĐŗŅ€Đ°ĐŊĐ¸Ņ‡Đ¸Ņ‚ŅŒ** cookies, ĐēĐžŅ‚ĐžŅ€Ņ‹Đĩ Đ˛Ņ‹ Ņ…ĐžŅ‚Đ¸Ņ‚Đĩ ĐŋĐžĐģŅƒŅ‡Đ°Ņ‚ŅŒ. + +ĐĸĐĩĐŋĐĩŅ€ŅŒ Đ˛Đ°Ņˆ API ŅĐ°Đŧ Ņ€ĐĩŅˆĐ°ĐĩŅ‚, ĐŋŅ€Đ¸ĐŊиĐŧĐ°Ņ‚ŅŒ Đģи cookies. đŸ¤ĒđŸĒ + +Đ’Ņ‹ ĐŧĐžĐļĐĩŅ‚Đĩ ҁĐēĐžĐŊŅ„Đ¸ĐŗŅƒŅ€Đ¸Ņ€ĐžĐ˛Đ°Ņ‚ŅŒ Pydantic-ĐŧОдĐĩĐģҌ Ņ‚Đ°Đē, Ņ‡Ņ‚ĐžĐąŅ‹ СаĐŋŅ€ĐĩŅ‚Đ¸Ņ‚ŅŒ (`forbid`) ĐģŅŽĐąŅ‹Đĩ Đ´ĐžĐŋĐžĐģĐŊĐ¸Ņ‚ĐĩĐģҌĐŊŅ‹Đĩ (`extra`) ĐŋĐžĐģŅ: + +{* ../../docs_src/cookie_param_models/tutorial002_an_py39.py hl[10] *} + +Đ•ŅĐģи ĐēĐģиĐĩĐŊŅ‚ ĐŋĐžĐŋŅ€ĐžĐąŅƒĐĩŅ‚ ĐžŅ‚ĐŋŅ€Đ°Đ˛Đ¸Ņ‚ŅŒ **Đ´ĐžĐŋĐžĐģĐŊĐ¸Ņ‚ĐĩĐģҌĐŊŅ‹Đĩ cookies**, Ņ‚Đž в ĐžŅ‚Đ˛ĐĩŅ‚ ĐžĐŊ ĐŋĐžĐģŅƒŅ‡Đ¸Ņ‚ **ĐžŅˆĐ¸ĐąĐē҃**. + +БĐĩĐ´ĐŊŅ‹Đĩ йаĐŊĐŊĐĩҀҋ cookies, ĐžĐŊи Đ˛ŅĐĩĐŧи ŅĐ¸ĐģаĐŧи ĐŋŅ‹Ņ‚Đ°ŅŽŅ‚ŅŅ ĐŋĐžĐģŅƒŅ‡Đ¸Ņ‚ŅŒ Đ˛Đ°ŅˆĐĩ ŅĐžĐŗĐģĐ°ŅĐ¸Đĩ — и Đ˛ŅŅ‘ Ņ€Đ°Đ´Đ¸ Ņ‚ĐžĐŗĐž, Ņ‡Ņ‚ĐžĐąŅ‹ API ĐĩĐŗĐž ĐžŅ‚ĐēĐģĐžĐŊиĐģ. đŸĒ + +НаĐŋŅ€Đ¸ĐŧĐĩŅ€, ĐĩҁĐģи ĐēĐģиĐĩĐŊŅ‚ ĐŋĐžĐŋŅ‹Ņ‚Đ°ĐĩŅ‚ŅŅ ĐžŅ‚ĐŋŅ€Đ°Đ˛Đ¸Ņ‚ŅŒ cookie `santa_tracker` ŅĐž СĐŊĐ°Ņ‡ĐĩĐŊиĐĩĐŧ `good-list-please`, Ņ‚Đž в ĐžŅ‚Đ˛ĐĩŅ‚ ĐžĐŊ ĐŋĐžĐģŅƒŅ‡Đ¸Ņ‚ **ĐžŅˆĐ¸ĐąĐē҃**, ŅĐžĐžĐąŅ‰Đ°ŅŽŅ‰ŅƒŅŽ ĐĩĐŧ҃, Ņ‡Ņ‚Đž cookie `santa_tracker` ĐŊĐĩ Ņ€Đ°ĐˇŅ€ĐĩŅˆŅ‘ĐŊ: + +```json +{ + "detail": [ + { + "type": "extra_forbidden", + "loc": ["cookie", "santa_tracker"], + "msg": "Extra inputs are not permitted", + "input": "good-list-please" + } + ] +} +``` + +## ЗаĐēĐģŅŽŅ‡ĐĩĐŊиĐĩ + +Đ’Ņ‹ ĐŧĐžĐļĐĩŅ‚Đĩ Đ¸ŅĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ŅŒ **Pydantic-ĐŧОдĐĩĐģи** Đ´ĐģŅ ĐžĐąŅŠŅĐ˛ĐģĐĩĐŊĐ¸Ņ **cookies** в **FastAPI**. 😎 diff --git a/docs/ru/docs/tutorial/header-param-models.md b/docs/ru/docs/tutorial/header-param-models.md new file mode 100644 index 000000000..4f54e3e15 --- /dev/null +++ b/docs/ru/docs/tutorial/header-param-models.md @@ -0,0 +1,72 @@ +# МодĐĩĐģи Header-ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€ĐžĐ˛ + +Đ•ŅĐģи ҃ Đ˛Đ°Ņ ĐĩŅŅ‚ŅŒ ĐŗŅ€ŅƒĐŋĐŋа ŅĐ˛ŅĐˇĐ°ĐŊĐŊҋ҅ **header-ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€ĐžĐ˛**, Ņ‚Đž Đ˛Ņ‹ ĐŧĐžĐļĐĩŅ‚Đĩ ĐžĐąŅŠĐĩдиĐŊĐ¸Ņ‚ŅŒ Đ¸Ņ… в ОдĐŊ҃ **Pydantic-ĐŧОдĐĩĐģҌ**. + +Đ­Ņ‚Đž ĐŋОСвОĐģĐ¸Ņ‚ ваĐŧ **ĐŋĐĩŅ€ĐĩĐ¸ŅĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ŅŒ ĐŧОдĐĩĐģҌ** в **Ņ€Đ°ĐˇĐŊҋ҅ ĐŧĐĩŅŅ‚Đ°Ņ…**, а Ņ‚Đ°ĐēĐļĐĩ ĐˇĐ°Đ´Đ°Ņ‚ŅŒ ваĐģĐ¸Đ´Đ°Ņ†Đ¸ŅŽ и ĐŧĐĩŅ‚Đ°Đ´Đ°ĐŊĐŊŅ‹Đĩ ŅŅ€Đ°ĐˇŅƒ Đ´ĐģŅ Đ˛ŅĐĩŅ… ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€ĐžĐ˛. 😎 + +/// note | ЗаĐŧĐĩŅ‚Đēа + +Đ­Ņ‚ĐžŅ‚ Ņ„ŅƒĐŊĐēŅ†Đ¸ĐžĐŊаĐģ Đ´ĐžŅŅ‚ŅƒĐŋĐĩĐŊ в FastAPI ĐŊĐ°Ņ‡Đ¸ĐŊĐ°Ņ ҁ вĐĩŅ€ŅĐ¸Đ¸ `0.115.0`. 🤓 + +/// + +## Header-ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁҋ в видĐĩ Pydantic-ĐŧОдĐĩĐģи + +ĐžĐąŅŠŅĐ˛Đ¸Ņ‚Đĩ ĐŊ҃ĐļĐŊŅ‹Đĩ **header-ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁҋ** в **Pydantic-ĐŧОдĐĩĐģи** и ĐˇĐ°Ņ‚ĐĩĐŧ аĐŊĐŊĐžŅ‚Đ¸Ņ€ŅƒĐšŅ‚Đĩ ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ ĐēаĐē `Header`: + +{* ../../docs_src/header_param_models/tutorial001_an_py310.py hl[9:14,18] *} + +**FastAPI** **иСвĐģĐĩ҇ґ҂** даĐŊĐŊŅ‹Đĩ Đ´ĐģŅ **ĐēаĐļĐ´ĐžĐŗĐž ĐŋĐžĐģŅ** иС **ĐˇĐ°ĐŗĐžĐģОвĐēОв** СаĐŋŅ€ĐžŅĐ° и Đ˛Ņ‹Đ´Đ°ŅŅ‚ СадаĐŊĐŊŅƒŅŽ ваĐŧи Pydantic-ĐŧОдĐĩĐģҌ. + +## ĐŸŅ€ĐžĐ˛ĐĩŅ€ŅŒŅ‚Đĩ Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Đ¸ŅŽ + +Đ’Ņ‹ ĐŧĐžĐļĐĩŅ‚Đĩ ĐŋĐžŅĐŧĐžŅ‚Ņ€ĐĩŅ‚ŅŒ ĐŊ҃ĐļĐŊŅ‹Đĩ header-ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁҋ в ĐŗŅ€Đ°Ņ„Đ¸Ņ‡ĐĩҁĐēĐžĐŧ иĐŊŅ‚ĐĩҀ҄ĐĩĐšŅĐĩ ŅĐŗĐĩĐŊĐĩŅ€Đ¸Ņ€ĐžĐ˛Đ°ĐŊĐŊОК Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Đ¸Đ¸ ĐŋĐž ĐŋŅƒŅ‚Đ¸ `/docs`: + +
+ +
+ +## КаĐē СаĐŋŅ€ĐĩŅ‚Đ¸Ņ‚ŅŒ Đ´ĐžĐŋĐžĐģĐŊĐ¸Ņ‚ĐĩĐģҌĐŊŅ‹Đĩ ĐˇĐ°ĐŗĐžĐģОвĐēи + +В ĐŊĐĩĐēĐžŅ‚ĐžŅ€Ņ‹Ņ… ҁĐģŅƒŅ‡Đ°ŅŅ… (ĐŊĐĩ ĐžŅĐžĐąĐž Ņ‡Đ°ŅŅ‚Đž Đ˛ŅŅ‚Ņ€ĐĩŅ‡Đ°ŅŽŅ‰Đ¸Ņ…ŅŅ) ваĐŧ ĐŧĐžĐļĐĩŅ‚ ĐŋĐžĐŊĐ°Đ´ĐžĐąĐ¸Ņ‚ŅŒŅŅ **ĐžĐŗŅ€Đ°ĐŊĐ¸Ņ‡Đ¸Ņ‚ŅŒ** ĐˇĐ°ĐŗĐžĐģОвĐēи, ĐēĐžŅ‚ĐžŅ€Ņ‹Đĩ Đ˛Ņ‹ Ņ…ĐžŅ‚Đ¸Ņ‚Đĩ ĐŋĐžĐģŅƒŅ‡Đ°Ņ‚ŅŒ. + +Đ’Ņ‹ ĐŧĐžĐļĐĩŅ‚Đĩ Đ¸ŅĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ŅŒ вОСĐŧĐžĐļĐŊĐžŅŅ‚Đ¸ ĐēĐžĐŊŅ„Đ¸ĐŗŅƒŅ€Đ°Ņ†Đ¸Đ¸ Pydantic-ĐŧОдĐĩĐģи Đ´ĐģŅ Ņ‚ĐžĐŗĐž, Ņ‡Ņ‚ĐžĐąŅ‹ СаĐŋŅ€ĐĩŅ‚Đ¸Ņ‚ŅŒ (`forbid`) ĐģŅŽĐąŅ‹Đĩ Đ´ĐžĐŋĐžĐģĐŊĐ¸Ņ‚ĐĩĐģҌĐŊŅ‹Đĩ (`extra`) ĐŋĐžĐģŅ: + +{* ../../docs_src/header_param_models/tutorial002_an_py310.py hl[10] *} + +Đ•ŅĐģи ĐēĐģиĐĩĐŊŅ‚ ĐŋĐžĐŋŅ€ĐžĐąŅƒĐĩŅ‚ ĐžŅ‚ĐŋŅ€Đ°Đ˛Đ¸Ņ‚ŅŒ **Đ´ĐžĐŋĐžĐģĐŊĐ¸Ņ‚ĐĩĐģҌĐŊŅ‹Đĩ ĐˇĐ°ĐŗĐžĐģОвĐēи**, Ņ‚Đž в ĐžŅ‚Đ˛ĐĩŅ‚ ĐžĐŊ ĐŋĐžĐģŅƒŅ‡Đ¸Ņ‚ **ĐžŅˆĐ¸ĐąĐē҃**. + +НаĐŋŅ€Đ¸ĐŧĐĩŅ€, ĐĩҁĐģи ĐēĐģиĐĩĐŊŅ‚ ĐŋĐžĐŋŅ‹Ņ‚Đ°ĐĩŅ‚ŅŅ ĐžŅ‚ĐŋŅ€Đ°Đ˛Đ¸Ņ‚ŅŒ ĐˇĐ°ĐŗĐžĐģОвОĐē `tool` ŅĐž СĐŊĐ°Ņ‡ĐĩĐŊиĐĩĐŧ `plumbus`, Ņ‚Đž в ĐžŅ‚Đ˛ĐĩŅ‚ ĐžĐŊ ĐŋĐžĐģŅƒŅ‡Đ¸Ņ‚ ĐžŅˆĐ¸ĐąĐē҃, ŅĐžĐžĐąŅ‰Đ°ŅŽŅ‰ŅƒŅŽ ĐĩĐŧ҃, Ņ‡Ņ‚Đž header-ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ `tool` ĐŊĐĩ Ņ€Đ°ĐˇŅ€Đĩ҈ĐĩĐŊ: + +```json +{ + "detail": [ + { + "type": "extra_forbidden", + "loc": ["header", "tool"], + "msg": "Extra inputs are not permitted", + "input": "plumbus", + } + ] +} +``` + +## КаĐē ĐžŅ‚ĐēĐģŅŽŅ‡Đ¸Ņ‚ŅŒ Đ°Đ˛Ņ‚ĐžĐŧĐ°Ņ‚Đ¸Ņ‡ĐĩҁĐēĐžĐĩ ĐŋŅ€ĐĩĐžĐąŅ€Đ°ĐˇĐžĐ˛Đ°ĐŊиĐĩ ĐŋĐžĐ´Ņ‡ĐĩŅ€ĐēиваĐŊиК + +КаĐē и в ҁĐģŅƒŅ‡Đ°Đĩ ҁ ĐžĐąŅ‹Ņ‡ĐŊŅ‹Đŧи ĐˇĐ°ĐŗĐžĐģОвĐēаĐŧи, ĐĩҁĐģи ҃ Đ˛Đ°Ņ в иĐŧĐĩĐŊĐ°Ņ… ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€ĐžĐ˛ иĐŧĐĩŅŽŅ‚ŅŅ ŅĐ¸ĐŧвОĐģŅ‹ ĐŋĐžĐ´Ņ‡ĐĩŅ€ĐēиваĐŊĐ¸Ņ, ĐžĐŊи **Đ°Đ˛Ņ‚ĐžĐŧĐ°Ņ‚Đ¸Ņ‡ĐĩҁĐēи ĐŋŅ€ĐĩĐžĐąŅ€Đ°ĐˇĐžĐ˛Ņ‹Đ˛Đ°ŅŽŅ‚ŅŅ в Đ´ĐĩŅ„Đ¸Ņ**. + +НаĐŋŅ€Đ¸ĐŧĐĩŅ€, ĐĩҁĐģи в ĐēОдĐĩ ĐĩŅŅ‚ŅŒ header-ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ `save_data`, Ņ‚Đž ĐžĐļидаĐĩĐŧŅ‹Đš HTTP-ĐˇĐ°ĐŗĐžĐģОвОĐē ĐąŅƒĐ´ĐĩŅ‚ `save-data` и иĐŧĐĩĐŊĐŊĐž Ņ‚Đ°Đē ĐžĐŊ ĐąŅƒĐ´ĐĩŅ‚ ĐžŅ‚ĐžĐąŅ€Đ°ĐļĐ°Ņ‚ŅŒŅŅ в Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Đ¸Đ¸. + +Đ•ŅĐģи ĐŋĐž ĐēаĐēиĐŧ-Ņ‚Đž ĐŋŅ€Đ¸Ņ‡Đ¸ĐŊаĐŧ ваĐŧ ĐŊ҃ĐļĐŊĐž ĐžŅ‚ĐēĐģŅŽŅ‡Đ¸Ņ‚ŅŒ даĐŊĐŊĐžĐĩ Đ°Đ˛Ņ‚ĐžĐŧĐ°Ņ‚Đ¸Ņ‡ĐĩҁĐēĐžĐĩ ĐŋŅ€ĐĩĐžĐąŅ€Đ°ĐˇĐžĐ˛Đ°ĐŊиĐĩ, ŅŅ‚Đž ĐŧĐžĐļĐŊĐž ŅĐ´ĐĩĐģĐ°Ņ‚ŅŒ и Đ´ĐģŅ Pydantic-ĐŧОдĐĩĐģĐĩĐš Đ´ĐģŅ header-ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€ĐžĐ˛. + +{* ../../docs_src/header_param_models/tutorial003_an_py310.py hl[19] *} + +/// warning | ВĐŊиĐŧаĐŊиĐĩ + +ПĐĩŅ€ĐĩĐ´ Ņ‚ĐĩĐŧ ĐēаĐē ŅƒŅŅ‚Đ°ĐŊавĐģĐ¸Đ˛Đ°Ņ‚ŅŒ Đ´ĐģŅ ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ° `convert_underscores` СĐŊĐ°Ņ‡ĐĩĐŊиĐĩ `False`, иĐŧĐĩĐšŅ‚Đĩ в Đ˛Đ¸Đ´Ņƒ, Ņ‡Ņ‚Đž ĐŊĐĩĐēĐžŅ‚ĐžŅ€Ņ‹Đĩ HTTP-ĐŋŅ€ĐžĐēŅĐ¸ и ҁĐĩŅ€Đ˛ĐĩҀҋ ĐŊĐĩ Ņ€Đ°ĐˇŅ€ĐĩŅˆĐ°ŅŽŅ‚ Đ¸ŅĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ŅŒ ĐˇĐ°ĐŗĐžĐģОвĐēи ҁ ŅĐ¸ĐŧвОĐģаĐŧи ĐŋĐžĐ´Ņ‡ĐĩŅ€ĐēиваĐŊĐ¸Ņ. + +/// + +## Đ ĐĩĐˇŅŽĐŧĐĩ + +Đ’Ņ‹ ĐŧĐžĐļĐĩŅ‚Đĩ Đ¸ŅĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ŅŒ **Pydantic-ĐŧОдĐĩĐģи** Đ´ĐģŅ ĐžĐąŅŠŅĐ˛ĐģĐĩĐŊĐ¸Ņ **header-ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€ĐžĐ˛** в **FastAPI**. 😎 diff --git a/docs/ru/docs/tutorial/middleware.md b/docs/ru/docs/tutorial/middleware.md new file mode 100644 index 000000000..845e881e1 --- /dev/null +++ b/docs/ru/docs/tutorial/middleware.md @@ -0,0 +1,74 @@ +# Middleware (ĐŸŅ€ĐžĐŧĐĩĐļŅƒŅ‚ĐžŅ‡ĐŊŅ‹Đš ҁĐģОК) + +Đ’Ņ‹ ĐŧĐžĐļĐĩŅ‚Đĩ Đ´ĐžĐąĐ°Đ˛Đ¸Ņ‚ŅŒ ĐŋŅ€ĐžĐŧĐĩĐļŅƒŅ‚ĐžŅ‡ĐŊŅ‹Đš ҁĐģОК (middleware) в **FastAPI** ĐŋŅ€Đ¸ĐģĐžĐļĐĩĐŊиĐĩ. + +"Middleware" ŅŅ‚Đž Ņ„ŅƒĐŊĐēŅ†Đ¸Ņ, ĐēĐžŅ‚ĐžŅ€Đ°Ņ Đ˛Ņ‹ĐŋĐžĐģĐŊŅĐĩŅ‚ŅŅ ҁ ĐēаĐļĐ´Ņ‹Đŧ СаĐŋŅ€ĐžŅĐžĐŧ Đ´Đž ĐĩĐŗĐž ĐžĐąŅ€Đ°ĐąĐžŅ‚Đēи ĐēаĐēОК-ĐģийО ĐēĐžĐŊĐēŅ€ĐĩŅ‚ĐŊОК *ĐžĐŋĐĩŅ€Đ°Ņ†Đ¸ĐĩĐš ĐŋŅƒŅ‚Đ¸*. +А Ņ‚Đ°ĐēĐļĐĩ ҁ ĐēаĐļĐ´Ņ‹Đŧ ĐžŅ‚Đ˛ĐĩŅ‚ĐžĐŧ ĐŋĐĩŅ€ĐĩĐ´ ĐĩĐŗĐž Đ˛ĐžĐˇĐ˛Ņ€Đ°Ņ‰ĐĩĐŊиĐĩĐŧ. + + +* ОĐŊа ĐŋŅ€Đ¸ĐŊиĐŧаĐĩŅ‚ ĐēаĐļĐ´Ņ‹Đš ĐŋĐžŅŅ‚ŅƒĐŋĐ°ŅŽŅ‰Đ¸Đš **СаĐŋŅ€ĐžŅ**. +* МоĐļĐĩŅ‚ Ņ‡Ņ‚Đž-Ņ‚Đž ŅĐ´ĐĩĐģĐ°Ņ‚ŅŒ ҁ ŅŅ‚Đ¸Đŧ **СаĐŋŅ€ĐžŅĐžĐŧ** иĐģи Đ˛Ņ‹ĐŋĐžĐģĐŊĐ¸Ņ‚ŅŒ ĐģŅŽĐąĐžĐš ĐŊ҃ĐļĐŊŅ‹Đš ĐēОд. +* Đ—Đ°Ņ‚ĐĩĐŧ ĐŋĐĩŅ€ĐĩдаĐĩŅ‚ **СаĐŋŅ€ĐžŅ** Đ´ĐģŅ ĐŋĐžŅĐģĐĩĐ´ŅƒŅŽŅ‰ĐĩĐš ĐžĐąŅ€Đ°ĐąĐžŅ‚Đēи (ĐēаĐēОК-ĐģийО *ĐžĐŋĐĩŅ€Đ°Ņ†Đ¸ĐĩĐš ĐŋŅƒŅ‚Đ¸*). +* ПоĐģŅƒŅ‡Đ°ĐĩŅ‚ **ĐžŅ‚Đ˛ĐĩŅ‚** (ĐžŅ‚ *ĐžĐŋĐĩŅ€Đ°Ņ†Đ¸Đ¸ ĐŋŅƒŅ‚Đ¸*). +* МоĐļĐĩŅ‚ Ņ‡Ņ‚Đž-Ņ‚Đž ŅĐ´ĐĩĐģĐ°Ņ‚ŅŒ ҁ ŅŅ‚Đ¸Đŧ **ĐžŅ‚Đ˛ĐĩŅ‚ĐžĐŧ** иĐģи Đ˛Ņ‹ĐŋĐžĐģĐŊĐ¸Ņ‚ŅŒ ĐģŅŽĐąĐžĐš ĐŊ҃ĐļĐŊŅ‹Đš ĐēОд. +* И Đ˛ĐžĐˇĐ˛Ņ€Đ°Ņ‰Đ°ĐĩŅ‚ **ĐžŅ‚Đ˛ĐĩŅ‚**. + +/// note | ĐĸĐĩŅ…ĐŊĐ¸Ņ‡ĐĩҁĐēиĐĩ Đ´ĐĩŅ‚Đ°Đģи + +Đ•ŅĐģи ҃ Đ˛Đ°Ņ ĐĩŅŅ‚ŅŒ ĐˇĐ°Đ˛Đ¸ŅĐ¸ĐŧĐžŅŅ‚Đ¸ ҁ `yield`, Ņ‚Đž ĐēОд Đ˛Ņ‹Ņ…ĐžĐ´Đ° (ĐēОд ĐŋĐžŅĐģĐĩ `yield`) ĐąŅƒĐ´ĐĩŅ‚ Đ˛Ņ‹ĐŋĐžĐģĐŊŅŅ‚ŅŒŅŅ *ĐŋĐžŅĐģĐĩ* middleware. + +Đ•ŅĐģи ҃ Đ˛Đ°Ņ иĐŧĐĩŅŽŅ‚ŅŅ ĐŊĐĩĐēиĐĩ Ņ„ĐžĐŊĐžĐ˛Ņ‹Đĩ ĐˇĐ°Đ´Đ°Ņ‡Đ¸ (ҁĐŧ. Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Đ¸ŅŽ), Ņ‚Đž ĐžĐŊи ĐąŅƒĐ´ŅƒŅ‚ СаĐŋŅƒŅ‰ĐĩĐŊŅ‹ ĐŋĐžŅĐģĐĩ middleware. + +/// + +## ХОСдаĐŊиĐĩ middleware + +ДĐģŅ ŅĐžĐˇĐ´Đ°ĐŊĐ¸Ņ middleware Đ¸ŅĐŋĐžĐģŅŒĐˇŅƒĐšŅ‚Đĩ Đ´ĐĩĐēĐžŅ€Đ°Ņ‚ĐžŅ€ `@app.middleware("http")`. + +Đ¤ŅƒĐŊĐēŅ†Đ¸Ņ middleware ĐŋĐžĐģŅƒŅ‡Đ°ĐĩŅ‚: + +* `request` (ĐžĐąŅŠĐĩĐēŅ‚ СаĐŋŅ€ĐžŅĐ°). +* Đ¤ŅƒĐŊĐēŅ†Đ¸ŅŽ `call_next`, ĐēĐžŅ‚ĐžŅ€Đ°Ņ ĐŋĐžĐģŅƒŅ‡Đ°ĐĩŅ‚ `request` в ĐēĐ°Ņ‡ĐĩŅŅ‚Đ˛Đĩ ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ°. + * Đ­Ņ‚Đ° Ņ„ŅƒĐŊĐēŅ†Đ¸Ņ ĐŋĐĩŅ€ĐĩĐ´Đ°Ņ‘Ņ‚ `request` ŅĐžĐžŅ‚Đ˛ĐĩŅ‚ŅŅ‚Đ˛ŅƒŅŽŅ‰ĐĩĐš *ĐžĐŋĐĩŅ€Đ°Ņ†Đ¸Đ¸ ĐŋŅƒŅ‚Đ¸*. + * Đ—Đ°Ņ‚ĐĩĐŧ ĐžĐŊа Đ˛ĐžĐˇĐ˛Ņ€Đ°Ņ‰Đ°ĐĩŅ‚ ĐžŅ‚Đ˛ĐĩŅ‚ `response`, ŅĐŗĐĩĐŊĐĩŅ€Đ¸Ņ€ĐžĐ˛Đ°ĐŊĐŊŅ‹Đš *ĐžĐŋĐĩŅ€Đ°Ņ†Đ¸ĐĩĐš ĐŋŅƒŅ‚Đ¸*. +* ĐĸаĐēĐļĐĩ иĐŧĐĩĐĩŅ‚ŅŅ вОСĐŧĐžĐļĐŊĐžŅŅ‚ŅŒ видОиСĐŧĐĩĐŊĐ¸Ņ‚ŅŒ `response`, ĐŋĐĩŅ€ĐĩĐ´ Ņ‚ĐĩĐŧ ĐēаĐē ĐĩĐŗĐž вĐĩŅ€ĐŊŅƒŅ‚ŅŒ. + +{* ../../docs_src/middleware/tutorial001.py hl[8:9,11,14] *} + +/// tip | ĐŸŅ€Đ¸ĐŧĐĩŅ‡Đ°ĐŊиĐĩ + +ИĐŧĐĩĐšŅ‚Đĩ в Đ˛Đ¸Đ´Ņƒ, Ņ‡Ņ‚Đž ĐŧĐžĐļĐŊĐž дОйавĐģŅŅ‚ŅŒ ŅĐ˛ĐžĐ¸ ŅĐžĐąŅŅ‚Đ˛ĐĩĐŊĐŊŅ‹Đĩ ĐˇĐ°ĐŗĐžĐģОвĐēи
ĐŋŅ€Đ¸ ĐŋĐžĐŧĐžŅ‰Đ¸ ĐŋŅ€ĐĩŅ„Đ¸ĐēŅĐ° 'X-'. + +Đ•ŅĐģи ĐļĐĩ Đ˛Ņ‹ Ņ…ĐžŅ‚Đ¸Ņ‚Đĩ Đ´ĐžĐąĐ°Đ˛Đ¸Ņ‚ŅŒ ŅĐžĐąŅŅ‚Đ˛ĐĩĐŊĐŊŅ‹Đĩ ĐˇĐ°ĐŗĐžĐģОвĐēи, ĐēĐžŅ‚ĐžŅ€Ņ‹Đĩ ĐēĐģиĐĩĐŊŅ‚ ҁĐŧĐžĐļĐĩŅ‚ ŅƒĐ˛Đ¸Đ´ĐĩŅ‚ŅŒ в ĐąŅ€Đ°ŅƒĐˇĐĩŅ€Đĩ, Ņ‚Đž ваĐŧ ĐŋĐžŅ‚Ņ€ĐĩĐąŅƒĐĩŅ‚ŅŅ Đ´ĐžĐąĐ°Đ˛Đ¸Ņ‚ŅŒ Đ¸Ņ… в ĐŊĐ°ŅŅ‚Ņ€ĐžĐšĐēи CORS ([CORS (Cross-Origin Resource Sharing)](cors.md){.internal-link target=_blank}), Đ¸ŅĐŋĐžĐģŅŒĐˇŅƒŅ ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ `expose_headers`, ҁĐŧ. Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Đ¸ŅŽ Starlette's CORS docs. + +/// + +/// note | ĐĸĐĩŅ…ĐŊĐ¸Ņ‡ĐĩҁĐēиĐĩ Đ´ĐĩŅ‚Đ°Đģи + +Đ’Ņ‹ Ņ‚Đ°ĐēĐļĐĩ ĐŧĐžĐļĐĩŅ‚Đĩ Đ¸ŅĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ŅŒ `from starlette.requests import Request`. + +**FastAPI** ĐŋŅ€ĐĩĐ´ĐžŅŅ‚Đ°Đ˛ĐģŅĐĩŅ‚ Ņ‚Đ°ĐēОК Đ´ĐžŅŅ‚ŅƒĐŋ Đ´ĐģŅ ŅƒĐ´ĐžĐąŅŅ‚Đ˛Đ° Ņ€Đ°ĐˇŅ€Đ°ĐąĐžŅ‚Ņ‡Đ¸ĐēОв. Но, ĐŊа ŅĐ°ĐŧĐžĐŧ Đ´ĐĩĐģĐĩ, ŅŅ‚Đž `Request` иС Starlette. + +/// + +### До и ĐŋĐžŅĐģĐĩ `response` + +Đ’Ņ‹ ĐŧĐžĐļĐĩŅ‚Đĩ Đ´ĐžĐąĐ°Đ˛Đ¸Ņ‚ŅŒ ĐēОд, Đ¸ŅĐŋĐžĐģŅŒĐˇŅƒŅŽŅ‰Đ¸Đš `request` Đ´Đž ĐŋĐĩŅ€ĐĩĐ´Đ°Ņ‡Đ¸ ĐĩĐŗĐž ĐēаĐēОК-ĐģийО *ĐžĐŋĐĩŅ€Đ°Ņ†Đ¸Đ¸ ĐŋŅƒŅ‚Đ¸*. + +А Ņ‚Đ°ĐēĐļĐĩ ĐŋĐžŅĐģĐĩ Ņ„ĐžŅ€ĐŧĐ¸Ņ€ĐžĐ˛Đ°ĐŊĐ¸Ņ `response`, Đ´Đž Ņ‚ĐžĐŗĐž, ĐēаĐē Đ˛Ņ‹ ĐĩĐŗĐž вĐĩŅ€ĐŊґ҂Đĩ. + +НаĐŋŅ€Đ¸ĐŧĐĩŅ€, Đ˛Ņ‹ ĐŧĐžĐļĐĩŅ‚Đĩ Đ´ĐžĐąĐ°Đ˛Đ¸Ņ‚ŅŒ ŅĐžĐąŅŅ‚Đ˛ĐĩĐŊĐŊŅ‹Đš ĐˇĐ°ĐŗĐžĐģОвОĐē `X-Process-Time`, ŅĐžĐ´ĐĩŅ€ĐļĐ°Ņ‰Đ¸Đš Đ˛Ņ€ĐĩĐŧŅ в ҁĐĩĐē҃ĐŊĐ´Đ°Ņ…, ĐŊĐĩĐžĐąŅ…ĐžĐ´Đ¸ĐŧĐžĐĩ Đ´ĐģŅ ĐžĐąŅ€Đ°ĐąĐžŅ‚Đēи СаĐŋŅ€ĐžŅĐ° и ĐŗĐĩĐŊĐĩŅ€Đ°Ņ†Đ¸Đ¸ ĐžŅ‚Đ˛ĐĩŅ‚Đ°: + +{* ../../docs_src/middleware/tutorial001.py hl[10,12:13] *} + +/// tip | ĐŸŅ€Đ¸ĐŧĐĩŅ‡Đ°ĐŊиĐĩ + +ĐœŅ‹ Đ¸ŅĐŋĐžĐģŅŒĐˇŅƒĐĩĐŧ `time.perf_counter()` вĐŧĐĩŅŅ‚Đž `time.time()` Đ´ĐģŅ ОйĐĩҁĐŋĐĩ҇ĐĩĐŊĐ¸Ņ йОĐģҌ҈ĐĩĐš Ņ‚ĐžŅ‡ĐŊĐžŅŅ‚Đ¸ ĐŊĐ°ŅˆĐ¸Ņ… ĐŋŅ€Đ¸ĐŧĐĩŅ€ĐžĐ˛. 🤓 + +/// + +## Đ”Ņ€ŅƒĐŗĐ¸Đĩ middleware + +О Đ´Ņ€ŅƒĐŗĐ¸Ņ… middleware Đ˛Ņ‹ ĐŧĐžĐļĐĩŅ‚Đĩ ŅƒĐˇĐŊĐ°Ņ‚ŅŒ йОĐģҌ҈Đĩ в Ņ€Đ°ĐˇĐ´ĐĩĐģĐĩ [Advanced User Guide: Advanced Middleware](../advanced/middleware.md){.internal-link target=_blank}. + +В ҁĐģĐĩĐ´ŅƒŅŽŅ‰ĐĩĐŧ Ņ€Đ°ĐˇĐ´ĐĩĐģĐĩ Đ˛Ņ‹ ĐŧĐžĐļĐĩŅ‚Đĩ ĐŋŅ€ĐžŅ‡Đ¸Ņ‚Đ°Ņ‚ŅŒ, ĐēаĐē ĐŊĐ°ŅŅ‚Ņ€ĐžĐ¸Ņ‚ŅŒ CORS ҁ ĐŋĐžĐŧĐžŅ‰ŅŒŅŽ middleware. diff --git a/docs/ru/docs/tutorial/query-params-str-validations.md b/docs/ru/docs/tutorial/query-params-str-validations.md index 32a98ff22..13b7015db 100644 --- a/docs/ru/docs/tutorial/query-params-str-validations.md +++ b/docs/ru/docs/tutorial/query-params-str-validations.md @@ -291,22 +291,6 @@ q: Union[str, None] = Query(default=None, min_length=3) {* ../../docs_src/query_params_str_validations/tutorial006_an_py39.py hl[9] *} -### ĐžĐąŅĐˇĐ°Ņ‚ĐĩĐģҌĐŊŅ‹Đš ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ ҁ Ellipsis (`...`) - -АĐģŅŒŅ‚ĐĩŅ€ĐŊĐ°Ņ‚Đ¸Đ˛ĐŊŅ‹Đš ҁĐŋĐžŅĐžĐą ҃ĐēĐ°ĐˇĐ°Ņ‚ŅŒ ĐžĐąŅĐˇĐ°Ņ‚ĐĩĐģҌĐŊĐžŅŅ‚ŅŒ ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ° СаĐŋŅ€ĐžŅĐ° - ŅŅ‚Đž ҃ĐēĐ°ĐˇĐ°Ņ‚ŅŒ ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ `default` ҇ĐĩŅ€ĐĩС ĐŧĐŊĐžĐŗĐžŅ‚ĐžŅ‡Đ¸Đĩ `...`: - -{* ../../docs_src/query_params_str_validations/tutorial006b_an_py39.py hl[9] *} - -/// info | ДоĐŋĐžĐģĐŊĐ¸Ņ‚ĐĩĐģҌĐŊĐ°Ņ иĐŊŅ„ĐžŅ€ĐŧĐ°Ņ†Đ¸Ņ - -Đ•ŅĐģи Đ˛Ņ‹ Ņ€Đ°ĐŊĐĩĐĩ ĐŊĐĩ ŅŅ‚Đ°ĐģĐēиваĐģĐ¸ŅŅŒ ҁ `...`: ŅŅ‚Đž ҁĐŋĐĩŅ†Đ¸Đ°ĐģҌĐŊĐžĐĩ СĐŊĐ°Ņ‡ĐĩĐŊиĐĩ, Ņ‡Đ°ŅŅ‚ŅŒ ŅĐˇŅ‹Đēа Python и ĐŊĐ°ĐˇŅ‹Đ˛Đ°ĐĩŅ‚ŅŅ "Ellipsis". - -Đ˜ŅĐŋĐžĐģŅŒĐˇŅƒĐĩŅ‚ŅŅ в Pydantic и FastAPI Đ´ĐģŅ ĐžĐŋŅ€ĐĩĐ´ĐĩĐģĐĩĐŊĐ¸Ņ, Ņ‡Ņ‚Đž СĐŊĐ°Ņ‡ĐĩĐŊиĐĩ ҂ҀĐĩĐąŅƒĐĩŅ‚ŅŅ ĐžĐąŅĐˇĐ°Ņ‚ĐĩĐģҌĐŊĐž. - -/// - -ĐĸаĐēиĐŧ ĐžĐąŅ€Đ°ĐˇĐžĐŧ, **FastAPI** ĐžĐŋŅ€ĐĩĐ´ĐĩĐģŅĐĩŅ‚, Ņ‡Ņ‚Đž ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ ŅĐ˛ĐģŅĐĩŅ‚ŅŅ ĐžĐąŅĐˇĐ°Ņ‚ĐĩĐģҌĐŊŅ‹Đŧ. - ### ĐžĐąŅĐˇĐ°Ņ‚ĐĩĐģҌĐŊŅ‹Đš ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ ҁ `None` Đ’Ņ‹ ĐŧĐžĐļĐĩŅ‚Đĩ ĐžĐŋŅ€ĐĩĐ´ĐĩĐģĐ¸Ņ‚ŅŒ, Ņ‡Ņ‚Đž ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ ĐŧĐžĐļĐĩŅ‚ ĐŋŅ€Đ¸ĐŊиĐŧĐ°Ņ‚ŅŒ `None`, ĐŊĐž Đ˛ŅŅ‘ Đĩ҉ґ ŅĐ˛ĐģŅĐĩŅ‚ŅŅ ĐžĐąŅĐˇĐ°Ņ‚ĐĩĐģҌĐŊŅ‹Đŧ. Đ­Ņ‚Đž ĐŧĐžĐļĐĩŅ‚ ĐŋĐžŅ‚Ņ€ĐĩĐąĐžĐ˛Đ°Ņ‚ŅŒŅŅ Đ´ĐģŅ Ņ‚ĐžĐŗĐž, Ņ‡Ņ‚ĐžĐąŅ‹ ĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ĐĩĐģи ŅĐ˛ĐŊĐž ҃ĐēаСаĐģи ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ, даĐļĐĩ ĐĩҁĐģи ĐĩĐŗĐž СĐŊĐ°Ņ‡ĐĩĐŊиĐĩ ĐąŅƒĐ´ĐĩŅ‚ `None`. @@ -321,18 +305,6 @@ Pydantic, ĐŧĐžŅ‰ŅŒ ĐēĐžŅ‚ĐžŅ€ĐžĐŗĐž Đ¸ŅĐŋĐžĐģŅŒĐˇŅƒĐĩŅ‚ŅŅ в FastAPI Đ´ĐģŅ /// -### Đ˜ŅĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°ĐŊиĐĩ Pydantic's `Required` вĐŧĐĩŅŅ‚Đž Ellipsis (`...`) - -Đ•ŅĐģи Đ˛Đ°Ņ ҁĐŧŅƒŅ‰Đ°ĐĩŅ‚ `...`, Đ˛Ņ‹ ĐŧĐžĐļĐĩŅ‚Đĩ Đ¸ŅĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ŅŒ `Required` иС Pydantic: - -{* ../../docs_src/query_params_str_validations/tutorial006d_an_py39.py hl[4,10] *} - -/// tip | ĐŸĐžĐ´ŅĐēаСĐēа - -ЗаĐŋĐžĐŧĐŊĐ¸Ņ‚Đĩ, ĐēĐžĐŗĐ´Đ° ваĐŧ ĐŊĐĩĐžĐąŅ…ĐžĐ´Đ¸ĐŧĐž ĐžĐąŅŠŅĐ˛Đ¸Ņ‚ŅŒ query-ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ ĐžĐąŅĐˇĐ°Ņ‚ĐĩĐģҌĐŊŅ‹Đŧ, Đ˛Ņ‹ ĐŧĐžĐļĐĩŅ‚Đĩ ĐŋŅ€ĐžŅŅ‚Đž ĐŊĐĩ ҃ĐēĐ°ĐˇŅ‹Đ˛Đ°Ņ‚ŅŒ ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ `default`. ĐĸаĐēиĐŧ ĐžĐąŅ€Đ°ĐˇĐžĐŧ, ваĐŧ Ņ€ĐĩĐ´ĐēĐž ĐŋŅ€Đ¸Đ´Ņ‘Ņ‚ŅŅ Đ¸ŅĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ŅŒ `...` иĐģи `Required`. - -/// - ## МĐŊĐžĐļĐĩŅŅ‚Đ˛Đž СĐŊĐ°Ņ‡ĐĩĐŊиК Đ´ĐģŅ query-ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ° ДĐģŅ query-ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ° `Query` ĐŧĐžĐļĐŊĐž ҃ĐēĐ°ĐˇĐ°Ņ‚ŅŒ, Ņ‡Ņ‚Đž ĐžĐŊ ĐŋŅ€Đ¸ĐŊиĐŧаĐĩŅ‚ ҁĐŋĐ¸ŅĐžĐē СĐŊĐ°Ņ‡ĐĩĐŊиК (ĐŧĐŊĐžĐļĐĩŅŅ‚Đ˛Đž СĐŊĐ°Ņ‡ĐĩĐŊиК). diff --git a/docs/ru/docs/tutorial/request-form-models.md b/docs/ru/docs/tutorial/request-form-models.md new file mode 100644 index 000000000..1034ed27f --- /dev/null +++ b/docs/ru/docs/tutorial/request-form-models.md @@ -0,0 +1,78 @@ +# МодĐĩĐģи Ņ„ĐžŅ€Đŧ + +Đ’Ņ‹ ĐŧĐžĐļĐĩŅ‚Đĩ Đ¸ŅĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ŅŒ **Pydantic-ĐŧОдĐĩĐģи** Đ´ĐģŅ ĐžĐąŅŠŅĐ˛ĐģĐĩĐŊĐ¸Ņ **ĐŋĐžĐģĐĩĐš Ņ„ĐžŅ€Đŧ** в FastAPI. + +/// info | ДоĐŋĐžĐģĐŊĐ¸Ņ‚ĐĩĐģҌĐŊĐ°Ņ иĐŊŅ„ĐžŅ€ĐŧĐ°Ņ†Đ¸Ņ + +Đ§Ņ‚ĐžĐąŅ‹ Đ¸ŅĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ŅŒ Ņ„ĐžŅ€ĐŧŅ‹, ҁĐŊĐ°Ņ‡Đ°Đģа ŅƒŅŅ‚Đ°ĐŊĐžĐ˛Đ¸Ņ‚Đĩ `python-multipart`. + +ĐŖĐąĐĩĐ´Đ¸Ņ‚ĐĩҁҌ, Ņ‡Ņ‚Đž Đ˛Ņ‹ ŅĐžĐˇĐ´Đ°Đģи и аĐēŅ‚Đ¸Đ˛Đ¸Ņ€ĐžĐ˛Đ°Đģи [Đ˛Đ¸Ņ€Ņ‚ŅƒĐ°ĐģҌĐŊĐžĐĩ ĐžĐēŅ€ŅƒĐļĐĩĐŊиĐĩ](../virtual-environments.md){.internal-link target=_blank}, а ĐˇĐ°Ņ‚ĐĩĐŧ ŅƒŅŅ‚Đ°ĐŊĐžĐ˛Đ¸Ņ‚Đĩ ĐŋаĐēĐĩŅ‚, ĐŊаĐŋŅ€Đ¸ĐŧĐĩŅ€: + +```console +$ pip install python-multipart +``` + +/// + +/// note | ЗаĐŧĐĩŅ‚Đēа + +Đ­Ņ‚ĐžŅ‚ Ņ„ŅƒĐŊĐēŅ†Đ¸ĐžĐŊаĐģ Đ´ĐžŅŅ‚ŅƒĐŋĐĩĐŊ ҁ вĐĩŅ€ŅĐ¸Đ¸ `0.113.0`. 🤓 + +/// + +## Pydantic-ĐŧОдĐĩĐģҌ Đ´ĐģŅ Ņ„ĐžŅ€ĐŧŅ‹ + +ВаĐŧ ĐŋŅ€ĐžŅŅ‚Đž ĐŊ҃ĐļĐŊĐž ĐžĐąŅŠŅĐ˛Đ¸Ņ‚ŅŒ **Pydantic-ĐŧОдĐĩĐģҌ** ҁ ĐŋĐžĐģŅĐŧи, ĐēĐžŅ‚ĐžŅ€Ņ‹Đĩ Đ˛Ņ‹ Ņ…ĐžŅ‚Đ¸Ņ‚Đĩ ĐŋĐžĐģŅƒŅ‡Đ¸Ņ‚ŅŒ ĐēаĐē **ĐŋĐžĐģŅ Ņ„ĐžŅ€ĐŧŅ‹**, а ĐˇĐ°Ņ‚ĐĩĐŧ ĐžĐąŅŠŅĐ˛Đ¸Ņ‚ŅŒ ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ ĐēаĐē `Form`: + +{* ../../docs_src/request_form_models/tutorial001_an_py39.py hl[9:11,15] *} + +**FastAPI** **иСвĐģĐĩ҇ґ҂** даĐŊĐŊŅ‹Đĩ Đ´ĐģŅ **ĐēаĐļĐ´ĐžĐŗĐž ĐŋĐžĐģŅ** иС **даĐŊĐŊҋ҅ Ņ„ĐžŅ€ĐŧŅ‹** в СаĐŋŅ€ĐžŅĐĩ и Đ˛Ņ‹Đ´Đ°ŅŅ‚ ваĐŧ ĐžĐąŅŠŅĐ˛ĐģĐĩĐŊĐŊŅƒŅŽ Pydantic-ĐŧОдĐĩĐģҌ. + +## ĐŸŅ€ĐžĐ˛ĐĩŅ€Đēа ŅĐŗĐĩĐŊĐĩŅ€Đ¸Ņ€ĐžĐ˛Đ°ĐŊĐŊОК Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Đ¸Đ¸ + +Đ’Ņ‹ ĐŧĐžĐļĐĩŅ‚Đĩ ĐŋĐžŅĐŧĐžŅ‚Ņ€ĐĩŅ‚ŅŒ ĐŋĐžĐģŅ Ņ„ĐžŅ€ĐŧŅ‹ в ĐŗŅ€Đ°Ņ„Đ¸Ņ‡ĐĩҁĐēĐžĐŧ иĐŊŅ‚ĐĩҀ҄ĐĩĐšŅĐĩ ДоĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Đ¸Đ¸ ĐŋĐž ĐŋŅƒŅ‚Đ¸ `/docs`: + +
+ +
+ +## ЗаĐŋŅ€ĐĩŅ‚ Đ´ĐžĐŋĐžĐģĐŊĐ¸Ņ‚ĐĩĐģҌĐŊҋ҅ ĐŋĐžĐģĐĩĐš Ņ„ĐžŅ€ĐŧŅ‹ + +В ĐŊĐĩĐēĐžŅ‚ĐžŅ€Ņ‹Ņ… ҁĐģŅƒŅ‡Đ°ŅŅ… (ĐŊĐĩ ĐžŅĐžĐąĐž Ņ‡Đ°ŅŅ‚Đž Đ˛ŅŅ‚Ņ€ĐĩŅ‡Đ°ŅŽŅ‰Đ¸Ņ…ŅŅ) ваĐŧ ĐŧĐžĐļĐĩŅ‚ ĐŋĐžĐŊĐ°Đ´ĐžĐąĐ¸Ņ‚ŅŒŅŅ **ĐžĐŗŅ€Đ°ĐŊĐ¸Ņ‡Đ¸Ņ‚ŅŒ** ĐŋĐžĐģŅ Ņ„ĐžŅ€ĐŧŅ‹ Ņ‚ĐžĐģҌĐēĐž Ņ‚ĐĩĐŧи, ĐēĐžŅ‚ĐžŅ€Ņ‹Đĩ ĐžĐąŅŠŅĐ˛ĐģĐĩĐŊŅ‹ в Pydantic-ĐŧОдĐĩĐģи. И **СаĐŋŅ€ĐĩŅ‚Đ¸Ņ‚ŅŒ** ĐģŅŽĐąŅ‹Đĩ **Đ´ĐžĐŋĐžĐģĐŊĐ¸Ņ‚ĐĩĐģҌĐŊŅ‹Đĩ** ĐŋĐžĐģŅ. + +/// note | ЗаĐŧĐĩŅ‚Đēа + +Đ­Ņ‚ĐžŅ‚ Ņ„ŅƒĐŊĐēŅ†Đ¸ĐžĐŊаĐģ Đ´ĐžŅŅ‚ŅƒĐŋĐĩĐŊ ҁ вĐĩŅ€ŅĐ¸Đ¸ `0.114.0`. 🤓 + +/// + +Đ’Ņ‹ ĐŧĐžĐļĐĩŅ‚Đĩ ҁĐēĐžĐŊŅ„Đ¸ĐŗŅƒŅ€Đ¸Ņ€ĐžĐ˛Đ°Ņ‚ŅŒ Pydantic-ĐŧОдĐĩĐģҌ Ņ‚Đ°Đē, Ņ‡Ņ‚ĐžĐąŅ‹ СаĐŋŅ€ĐĩŅ‚Đ¸Ņ‚ŅŒ (`forbid`) Đ˛ŅĐĩ Đ´ĐžĐŋĐžĐģĐŊĐ¸Ņ‚ĐĩĐģҌĐŊŅ‹Đĩ (`extra`) ĐŋĐžĐģŅ: + +{* ../../docs_src/request_form_models/tutorial002_an_py39.py hl[12] *} + +Đ•ŅĐģи ĐēĐģиĐĩĐŊŅ‚ ĐŋĐžĐŋŅ€ĐžĐąŅƒĐĩŅ‚ ĐžŅ‚ĐŋŅ€Đ°Đ˛Đ¸Ņ‚ŅŒ Đ´ĐžĐŋĐžĐģĐŊĐ¸Ņ‚ĐĩĐģҌĐŊŅ‹Đĩ даĐŊĐŊŅ‹Đĩ, Ņ‚Đž в ĐžŅ‚Đ˛ĐĩŅ‚ ĐžĐŊ ĐŋĐžĐģŅƒŅ‡Đ¸Ņ‚ **ĐžŅˆĐ¸ĐąĐē҃**. + +НаĐŋŅ€Đ¸ĐŧĐĩŅ€, ĐĩҁĐģи ĐēĐģиĐĩĐŊŅ‚ ĐŋĐžĐŋŅ‹Ņ‚Đ°ĐĩŅ‚ŅŅ ĐžŅ‚ĐŋŅ€Đ°Đ˛Đ¸Ņ‚ŅŒ ĐŋĐžĐģŅ Ņ„ĐžŅ€ĐŧŅ‹: + +* `username`: `Rick` +* `password`: `Portal Gun` +* `extra`: `Mr. Poopybutthole` + +ĐĸĐž в ĐžŅ‚Đ˛ĐĩŅ‚ ĐžĐŊ ĐŋĐžĐģŅƒŅ‡Đ¸Ņ‚ **ĐžŅˆĐ¸ĐąĐē҃**, ŅĐžĐžĐąŅ‰Đ°ŅŽŅ‰ŅƒŅŽ ĐĩĐŧ҃, Ņ‡Ņ‚Đž ĐŋĐžĐģĐĩ `extra` ĐŊĐĩ Ņ€Đ°ĐˇŅ€Đĩ҈ĐĩĐŊĐž: + +```json +{ + "detail": [ + { + "type": "extra_forbidden", + "loc": ["body", "extra"], + "msg": "Extra inputs are not permitted", + "input": "Mr. Poopybutthole" + } + ] +} +``` + +## ЗаĐēĐģŅŽŅ‡ĐĩĐŊиĐĩ + +Đ’Ņ‹ ĐŧĐžĐļĐĩŅ‚Đĩ Đ¸ŅĐŋĐžĐģŅŒĐˇĐžĐ˛Đ°Ņ‚ŅŒ Pydantic-ĐŧОдĐĩĐģи Đ´ĐģŅ ĐžĐąŅŠŅĐ˛ĐģĐĩĐŊĐ¸Ņ ĐŋĐžĐģĐĩĐš Ņ„ĐžŅ€Đŧ в FastAPI. 😎 diff --git a/docs/tr/docs/index.md b/docs/tr/docs/index.md index 7ecaf1ba3..f666e2d06 100644 --- a/docs/tr/docs/index.md +++ b/docs/tr/docs/index.md @@ -12,7 +12,7 @@

- Test + Test Coverage diff --git a/docs/uk/docs/features.md b/docs/uk/docs/features.md new file mode 100644 index 000000000..7d679d8ee --- /dev/null +++ b/docs/uk/docs/features.md @@ -0,0 +1,189 @@ +# Đ¤ŅƒĐŊĐēŅ†Ņ–ĐžĐŊаĐģҌĐŊŅ– ĐŧĐžĐļĐģĐ¸Đ˛ĐžŅŅ‚Ņ– + +## Đ¤ŅƒĐŊĐēŅ†Ņ–ĐžĐŊаĐģҌĐŊŅ– ĐŧĐžĐļĐģĐ¸Đ˛ĐžŅŅ‚Ņ– FastAPI + +**FastAPI** ĐŊĐ°Đ´Đ°Ņ” ваĐŧ Ņ‚Đ°ĐēŅ– ĐŧĐžĐļĐģĐ¸Đ˛ĐžŅŅ‚Ņ–: + +### ВиĐēĐžŅ€Đ¸ŅŅ‚Đ°ĐŊĐŊŅ Đ˛Ņ–Đ´ĐēŅ€Đ¸Ņ‚Đ¸Ņ… ŅŅ‚Đ°ĐŊĐ´Đ°Ņ€Ņ‚Ņ–Đ˛ + +* OpenAPI Đ´ĐģŅ ŅŅ‚Đ˛ĐžŅ€ĐĩĐŊĐŊŅ API, вĐēĐģŅŽŅ‡Đ°ŅŽŅ‡Đ¸ ĐžĐŗĐžĐģĐžŅˆĐĩĐŊĐŊŅ ҈ĐģŅŅ…Ņ–Đ˛, ĐžĐŋĐĩŅ€Đ°Ņ†Ņ–Đš, ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Ņ–Đ˛, ҂ҖĐģ СаĐŋĐ¸Ņ‚Ņ–Đ˛, ĐąĐĩСĐŋĐĩĐēи Ņ‚ĐžŅ‰Đž. +* ĐĐ˛Ņ‚ĐžĐŧĐ°Ņ‚Đ¸Ņ‡ĐŊа Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Ņ–Ņ ĐŧОдĐĩĐģĐĩĐš даĐŊĐ¸Ņ… Са Đ´ĐžĐŋĐžĐŧĐžĐŗĐžŅŽ JSON Schema (ĐžŅĐēŅ–ĐģҌĐēи OpenAPI ĐąĐ°ĐˇŅƒŅ”Ņ‚ŅŒŅŅ ŅĐ°ĐŧĐĩ ĐŊа JSON Schema). +* Đ ĐžĐˇŅ€ĐžĐąĐģĐĩĐŊĐž ĐŊа ĐžŅĐŊĐžĐ˛Ņ– Ņ†Đ¸Ņ… ŅŅ‚Đ°ĐŊĐ´Đ°Ņ€Ņ‚Ņ–Đ˛ ĐŋҖҁĐģŅ Ņ€ĐĩŅ‚ĐĩĐģҌĐŊĐžĐŗĐž аĐŊаĐģŅ–ĐˇŅƒ, а ĐŊĐĩ ŅĐē Đ´ĐžĐ´Đ°Ņ‚ĐēОвиК Ņ€Ņ–Đ˛ĐĩĐŊҌ ĐŋОвĐĩҀ҅ ĐžŅĐŊОвĐŊĐžŅ— Đ°Ņ€Ņ…Ņ–Ņ‚ĐĩĐēŅ‚ŅƒŅ€Đ¸. +* ĐĻĐĩ Ņ‚Đ°ĐēĐžĐļ Đ´Đ°Ņ” СĐŧĐžĐŗŅƒ Đ°Đ˛Ņ‚ĐžĐŧĐ°Ņ‚Đ¸Ņ‡ĐŊĐž **ĐŗĐĩĐŊĐĩŅ€ŅƒĐ˛Đ°Ņ‚Đ¸ ĐēОд ĐēĐģŅ–Ņ”ĐŊŅ‚Đ°** ĐąĐ°ĐŗĐ°Ņ‚ŅŒĐŧа ĐŧОваĐŧи. + +### ĐĐ˛Ņ‚ĐžĐŧĐ°Ņ‚Đ¸Ņ‡ĐŊа ĐŗĐĩĐŊĐĩŅ€Đ°Ņ†Ņ–Ņ Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Ņ–Ņ— + +ІĐŊŅ‚ĐĩŅ€Đ°ĐēŅ‚Đ¸Đ˛ĐŊа Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Ņ–Ņ API Ņ‚Đ° вĐĩĐąŅ–ĐŊŅ‚ĐĩҀ҄ĐĩĐšŅ Đ´ĐģŅ ĐšĐžĐŗĐž Đ´ĐžŅĐģŅ–Đ´ĐļĐĩĐŊĐŊŅ. ĐžŅĐēŅ–ĐģҌĐēи ҄ҀĐĩĐšĐŧĐ˛ĐžŅ€Đē ĐąĐ°ĐˇŅƒŅ”Ņ‚ŅŒŅŅ ĐŊа OpenAPI, Ņ” ĐēŅ–ĐģҌĐēа Đ˛Đ°Ņ€Ņ–Đ°ĐŊŅ‚Ņ–Đ˛, два С ŅĐēĐ¸Ņ… вĐēĐģŅŽŅ‡ĐĩĐŊŅ– Са СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ. + +* Swagger UI — дОСвОĐģŅŅ” Ņ–ĐŊŅ‚ĐĩŅ€Đ°ĐēŅ‚Đ¸Đ˛ĐŊĐž ĐŋĐĩŅ€ĐĩĐŗĐģŅĐ´Đ°Ņ‚Đ¸ API, виĐēĐģиĐēĐ°Ņ‚Đ¸ Ņ‚Đ° Ņ‚ĐĩŅŅ‚ŅƒĐ˛Đ°Ņ‚Đ¸ ĐšĐžĐŗĐž ĐŋŅ€ŅĐŧĐž ҃ ĐąŅ€Đ°ŅƒĐˇĐĩҀҖ. + +![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-03-swagger-02.png) + +* АĐģŅŒŅ‚ĐĩŅ€ĐŊĐ°Ņ‚Đ¸Đ˛ĐŊа Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Ņ–Ņ API Са Đ´ĐžĐŋĐžĐŧĐžĐŗĐžŅŽ ReDoc. + +![ReDoc](https://fastapi.tiangolo.com/img/index/index-06-redoc-02.png) + +### ĐĸŅ–ĐģҌĐēи ŅŅƒŅ‡Đ°ŅĐŊиК Python + +FastAPI виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅ” ŅŅ‚Đ°ĐŊĐ´Đ°Ņ€Ņ‚ĐŊŅ– **Ņ‚Đ¸Đŋи Python** (ĐˇĐ°Đ˛Đ´ŅĐēи Pydantic). ВаĐŧ ĐŊĐĩ ĐŋĐžŅ‚Ņ€Ņ–ĐąĐŊĐž Đ˛Đ¸Đ˛Ņ‡Đ°Ņ‚Đ¸ ĐŊОвиК ŅĐ¸ĐŊŅ‚Đ°ĐēŅĐ¸Ņ — ĐģĐ¸ŅˆĐĩ ŅŅ‚Đ°ĐŊĐ´Đ°Ņ€Ņ‚ĐŊиК ŅŅƒŅ‡Đ°ŅĐŊиК Python. + +Đ¯ĐēŅ‰Đž ваĐŧ ĐŋĐžŅ‚Ņ€Ņ–ĐąĐŊĐĩ ĐēĐžŅ€ĐžŅ‚ĐēĐĩ ĐŊĐ°ĐŗĐ°Đ´ŅƒĐ˛Đ°ĐŊĐŊŅ ĐŋŅ€Đž виĐēĐžŅ€Đ¸ŅŅ‚Đ°ĐŊĐŊŅ Ņ‚Đ¸ĐŋŅ–Đ˛ ҃ Python (ĐŊĐ°Đ˛Ņ–Ņ‚ŅŒ ŅĐēŅ‰Đž ви ĐŊĐĩ виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅ”Ņ‚Đĩ FastAPI), ĐŋĐĩŅ€ĐĩĐŗĐģŅĐŊŅŒŅ‚Đĩ ĐēĐžŅ€ĐžŅ‚ĐēиК ĐŋŅ–Đ´Ņ€ŅƒŅ‡ĐŊиĐē: [Đ’ŅŅ‚ŅƒĐŋ Đ´Đž Ņ‚Đ¸ĐŋŅ–Đ˛ Python](python-types.md){.internal-link target=_blank}. + +ĐžŅŅŒ ĐŋŅ€Đ¸ĐēĐģад ŅŅ‚Đ°ĐŊĐ´Đ°Ņ€Ņ‚ĐŊĐžĐŗĐž Python-ĐēĐžĐ´Ņƒ С Ņ‚Đ¸ĐŋаĐŧи: + +```Python +from datetime import date +from pydantic import BaseModel + +# ĐžĐŗĐžĐģĐžŅˆĐĩĐŊĐŊŅ СĐŧŅ–ĐŊĐŊĐžŅ— ŅĐē str +# С ĐŋŅ–Đ´Ņ‚Ņ€Đ¸ĐŧĐēĐžŅŽ Đ°Đ˛Ņ‚ĐžĐ´ĐžĐŋОвĐŊĐĩĐŊĐŊŅ ҃ Ņ€ĐĩдаĐēŅ‚ĐžŅ€Ņ– +def main(user_id: str): + return user_id + +# МодĐĩĐģҌ Pydantic +class User(BaseModel): + id: int + name: str + joined: date +``` + +ĐŸŅ€Đ¸ĐēĐģад виĐēĐžŅ€Đ¸ŅŅ‚Đ°ĐŊĐŊŅ ҆ҖҔҗ ĐŧОдĐĩĐģŅ–: + +```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` ОСĐŊĐ°Ņ‡Đ°Ņ”: + +ПĐĩŅ€ĐĩĐ´Đ°Ņ‚Đ¸ ĐēĐģŅŽŅ‡Ņ– Ņ‚Đ° СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ ҁĐģОвĐŊиĐēа `second_user_data` ŅĐē Đ°Ņ€ĐŗŅƒĐŧĐĩĐŊŅ‚Đ¸ ҃ Đ˛Đ¸ĐŗĐģŅĐ´Ņ– "ĐēĐģŅŽŅ‡-СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ", ĐĩĐēĐ˛Ņ–Đ˛Đ°ĐģĐĩĐŊŅ‚ĐŊĐž `User(id=4, name="Mary", joined="2018-11-30")`. + +/// + +### ĐŸŅ–Đ´Ņ‚Ņ€Đ¸ĐŧĐēа Ņ€ĐĩдаĐēŅ‚ĐžŅ€Ņ–Đ˛ (IDE) + +Đ¤Ņ€ĐĩĐšĐŧĐ˛ĐžŅ€Đē ҁĐŋŅ€ĐžŅ”ĐēŅ‚ĐžĐ˛Đ°ĐŊиК Ņ‚Đ°Đē, Ņ‰ĐžĐą ĐąŅƒŅ‚Đ¸ ĐģĐĩĐŗĐēиĐŧ Ņ– Ņ–ĐŊŅ‚ŅƒŅ—Ņ‚Đ¸Đ˛ĐŊĐž ĐˇŅ€ĐžĐˇŅƒĐŧŅ–ĐģиĐŧ. ĐŖŅŅ– Ņ€Ņ–ŅˆĐĩĐŊĐŊŅ Ņ‚ĐĩŅŅ‚ŅƒĐ˛Đ°ĐģĐ¸ŅŅ ҃ Ņ€Ņ–ĐˇĐŊĐ¸Ņ… Ņ€ĐĩдаĐēŅ‚ĐžŅ€Đ°Ņ… ҉Đĩ Đ´Đž ĐŋĐžŅ‡Đ°Ņ‚Đē҃ Ņ€ĐžĐˇŅ€ĐžĐąĐēи, Ņ‰ĐžĐą СайĐĩСĐŋĐĩŅ‡Đ¸Ņ‚Đ¸ ĐŊаКĐēŅ€Đ°Ņ‰Đ¸Đš Đ´ĐžŅĐ˛Ņ–Đ´ ĐŋŅ€ĐžĐŗŅ€Đ°ĐŧŅƒĐ˛Đ°ĐŊĐŊŅ. + +За Ņ€ĐĩĐˇŅƒĐģŅŒŅ‚Đ°Ņ‚Đ°Đŧи ĐžĐŋĐ¸Ņ‚ŅƒĐ˛Đ°ĐŊҌ Ņ€ĐžĐˇŅ€ĐžĐąĐŊиĐēŅ–Đ˛ Python ОдĐŊŅ–Ņ”ŅŽ С ĐŊаКĐŋĐžĐŋ҃ĐģŅŅ€ĐŊŅ–ŅˆĐ¸Ņ… Ņ„ŅƒĐŊĐēŅ†Ņ–Đš Ņ” "Đ°Đ˛Ņ‚ĐžĐ´ĐžĐŋОвĐŊĐĩĐŊĐŊŅ". + +**FastAPI** ĐŋОвĐŊŅ–ŅŅ‚ŅŽ ĐŋŅ–Đ´Ņ‚Ņ€Đ¸ĐŧŅƒŅ” Đ°Đ˛Ņ‚ĐžĐ´ĐžĐŋОвĐŊĐĩĐŊĐŊŅ ҃ Đ˛ŅŅ–Ņ… ĐŧŅ–ŅŅ†ŅŅ…, Ņ‚ĐžĐŧ҃ ваĐŧ Ņ€Ņ–Đ´ĐēĐž дОвĐĩĐ´ĐĩŅ‚ŅŒŅŅ ĐŋОвĐĩŅ€Ņ‚Đ°Ņ‚Đ¸ŅŅ Đ´Đž Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Ņ–Ņ—. + +ĐŸŅ€Đ¸ĐēĐģад Đ°Đ˛Ņ‚ĐžĐ´ĐžĐŋОвĐŊĐĩĐŊĐŊŅ ҃ Ņ€ĐĩдаĐēŅ‚ĐžŅ€Đ°Ņ…: + +* ҃ Visual Studio Code: + +![editor support](https://fastapi.tiangolo.com/img/vscode-completion.png) + +* ҃ PyCharm: + +![editor support](https://fastapi.tiangolo.com/img/pycharm-completion.png) + +### ĐšĐžŅ€ĐžŅ‚ĐēиК ĐēОд +FastAPI ĐŧĐ°Ņ” Ņ€ĐžĐˇŅƒĐŧĐŊŅ– ĐŊаĐģĐ°ŅˆŅ‚ŅƒĐ˛Đ°ĐŊĐŊŅ **Са СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ**, аĐģĐĩ Đ˛ŅŅ– ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ¸ ĐŧĐžĐļĐŊа ĐŊаĐģĐ°ŅˆŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´ĐŊĐž Đ´Đž Đ˛Đ°ŅˆĐ¸Ņ… ĐŋĐžŅ‚Ņ€ĐĩĐą. ОдĐŊаĐē Са СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ Đ˛ŅĐĩ "ĐŋŅ€ĐžŅŅ‚Đž ĐŋŅ€Đ°Ņ†ŅŽŅ”". + +### ВаĐģŅ–Đ´Đ°Ņ†Ņ–Ņ +* ĐŸŅ–Đ´Ņ‚Ņ€Đ¸ĐŧĐēа ваĐģŅ–Đ´Đ°Ņ†Ņ–Ņ— Đ´ĐģŅ ĐąŅ–ĐģŅŒŅˆĐžŅŅ‚Ņ– (айО Đ˛ŅŅ–Ņ…?) **Ņ‚Đ¸ĐŋŅ–Đ˛ даĐŊĐ¸Ņ… Python**, СОĐēŅ€ĐĩĐŧа: + * JSON-Ой'Ņ”ĐēŅ‚Ņ–Đ˛ (`dict`). + * JSON-ҁĐŋĐ¸ŅĐēŅ–Đ˛ (`list`) С виСĐŊĐ°Ņ‡ĐĩĐŊĐŊŅĐŧ Ņ‚Đ¸ĐŋŅ–Đ˛ ĐĩĐģĐĩĐŧĐĩĐŊŅ‚Ņ–Đ˛. + * Đ ŅĐ´ĐēŅ–Đ˛ (`str`) Ņ–Đˇ ĐŧŅ–ĐŊŅ–ĐŧаĐģҌĐŊĐžŅŽ Ņ‚Đ° ĐŧаĐēŅĐ¸ĐŧаĐģҌĐŊĐžŅŽ дОвĐļиĐŊĐžŅŽ. + * Đ§Đ¸ŅĐĩĐģ (`int`, `float`) С ОйĐŧĐĩĐļĐĩĐŊĐŊŅĐŧи ĐŧŅ–ĐŊŅ–ĐŧаĐģҌĐŊĐ¸Ņ… Ņ‚Đ° ĐŧаĐēŅĐ¸ĐŧаĐģҌĐŊĐ¸Ņ… СĐŊĐ°Ņ‡ĐĩĐŊҌ Ņ‚ĐžŅ‰Đž. + +* ВаĐģŅ–Đ´Đ°Ņ†Ņ–Ņ ҁĐēĐģадĐŊŅ–ŅˆĐ¸Ņ… Ņ‚Đ¸ĐŋŅ–Đ˛, Ņ‚Đ°ĐēĐ¸Ņ… ŅĐē: + * URL. + * Email. + * UUID. + * ...Ņ‚Đ° Ņ–ĐŊŅˆŅ–. + +ĐŖŅŅ ваĐģŅ–Đ´Đ°Ņ†Ņ–Ņ виĐēĐžĐŊŅƒŅ”Ņ‚ŅŒŅŅ ҇ĐĩŅ€ĐĩС ĐŊĐ°Đ´Ņ–ĐšĐŊиК Ņ‚Đ° ĐŋĐĩŅ€ĐĩĐ˛Ņ–Ņ€ĐĩĐŊиК **Pydantic**. + +### БĐĩСĐŋĐĩĐēа Ņ‚Đ° Đ°Đ˛Ņ‚ĐĩĐŊŅ‚Đ¸Ņ„Ņ–ĐēĐ°Ņ†Ņ–Ņ + +**FastAPI** ĐŋŅ–Đ´Ņ‚Ņ€Đ¸ĐŧŅƒŅ” Đ˛ĐąŅƒĐ´ĐžĐ˛Đ°ĐŊ҃ Đ°Đ˛Ņ‚ĐĩĐŊŅ‚Đ¸Ņ„Ņ–ĐēĐ°Ņ†Ņ–ŅŽ Ņ‚Đ° Đ°Đ˛Ņ‚ĐžŅ€Đ¸ĐˇĐ°Ņ†Ņ–ŅŽ, ĐąĐĩС ĐŋŅ€Đ¸Đ˛â€™ŅĐˇĐēи Đ´Đž ĐēĐžĐŊĐēŅ€ĐĩŅ‚ĐŊĐ¸Ņ… йаС даĐŊĐ¸Ņ… Ņ‡Đ¸ ĐŧОдĐĩĐģĐĩĐš даĐŊĐ¸Ņ…. + +ĐŸŅ–Đ´Ņ‚Ņ€Đ¸ĐŧŅƒŅŽŅ‚ŅŒŅŅ Đ˛ŅŅ– ҁ҅ĐĩĐŧи ĐąĐĩСĐŋĐĩĐēи OpenAPI, вĐēĐģŅŽŅ‡Đ°ŅŽŅ‡Đ¸: + +* HTTP Basic. +* **OAuth2** (Ņ‚Đ°ĐēĐžĐļ Ņ–Đˇ ĐŋŅ–Đ´Ņ‚Ņ€Đ¸ĐŧĐēĐžŅŽ **JWT-Ņ‚ĐžĐēĐĩĐŊŅ–Đ˛**). Див. ĐŋŅ–Đ´Ņ€ŅƒŅ‡ĐŊиĐē: [OAuth2 Ņ–Đˇ JWT](tutorial/security/oauth2-jwt.md){.internal-link target=_blank}. +* КĐģŅŽŅ‡Ņ– API в: + * Đ—Đ°ĐŗĐžĐģОвĐēĐ°Ņ…. + * ĐŸĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ°Ņ… СаĐŋĐ¸Ņ‚Ņƒ. + * Cookies Ņ‚ĐžŅ‰Đž. + +А Ņ‚Đ°ĐēĐžĐļ ŅƒŅŅ– ĐŧĐžĐļĐģĐ¸Đ˛ĐžŅŅ‚Ņ– ĐąĐĩСĐŋĐĩĐēи Đ˛Ņ–Đ´ Starlette (СОĐēŅ€ĐĩĐŧа **ҁĐĩŅŅ–ĐšĐŊŅ– cookies**). + +ĐŖŅŅ– вОĐŊи ŅŅ‚Đ˛ĐžŅ€ĐĩĐŊŅ– ŅĐē ĐąĐ°ĐŗĐ°Ņ‚ĐžŅ€Đ°ĐˇĐžĐ˛Ņ– Ņ–ĐŊŅŅ‚Ņ€ŅƒĐŧĐĩĐŊŅ‚Đ¸ Ņ‚Đ° ĐēĐžĐŧĐŋĐžĐŊĐĩĐŊŅ‚Đ¸, ŅĐēŅ– ĐģĐĩĐŗĐēĐž Ņ–ĐŊŅ‚ĐĩĐŗŅ€ŅƒŅŽŅ‚ŅŒŅŅ С Đ˛Đ°ŅˆĐ¸Đŧи ŅĐ¸ŅŅ‚ĐĩĐŧаĐŧи, ŅŅ…ĐžĐ˛Đ¸Ņ‰Đ°Đŧи даĐŊĐ¸Ņ…, Ņ€ĐĩĐģŅŅ†Ņ–ĐšĐŊиĐŧи Ņ‚Đ° NoSQL йаСаĐŧи даĐŊĐ¸Ņ… Ņ‚ĐžŅ‰Đž. + +### ВĐŋŅ€ĐžĐ˛Đ°Đ´ĐļĐĩĐŊĐŊŅ СаĐģĐĩĐļĐŊĐžŅŅ‚ĐĩĐš + +**FastAPI** ĐŧŅ–ŅŅ‚Đ¸Ņ‚ŅŒ ĐŊĐ°Đ´ĐˇĐ˛Đ¸Ņ‡Đ°ĐšĐŊĐž ĐŋŅ€ĐžŅŅ‚Ņƒ ҃ виĐēĐžŅ€Đ¸ŅŅ‚Đ°ĐŊĐŊŅ–, аĐģĐĩ ĐŋĐžŅ‚ŅƒĐļĐŊ҃ ŅĐ¸ŅŅ‚ĐĩĐŧ҃ вĐŋŅ€ĐžĐ˛Đ°Đ´ĐļĐĩĐŊĐŊŅ СаĐģĐĩĐļĐŊĐžŅŅ‚ĐĩĐš. + +* ЗаĐģĐĩĐļĐŊĐžŅŅ‚Ņ– ĐŧĐžĐļŅƒŅ‚ŅŒ ĐŧĐ°Ņ‚Đ¸ вĐģĐ°ŅĐŊŅ– СаĐģĐĩĐļĐŊĐžŅŅ‚Ņ–, ŅƒŅ‚Đ˛ĐžŅ€ŅŽŅŽŅ‡Đ¸ Ņ–Ņ”Ņ€Đ°Ņ€Ņ…Ņ–ŅŽ айО **"ĐŗŅ€Đ°Ņ„ СаĐģĐĩĐļĐŊĐžŅŅ‚ĐĩĐš"**. +* ĐŖŅŅ– СаĐģĐĩĐļĐŊĐžŅŅ‚Ņ– Đ°Đ˛Ņ‚ĐžĐŧĐ°Ņ‚Đ¸Ņ‡ĐŊĐž ĐēĐĩŅ€ŅƒŅŽŅ‚ŅŒŅŅ ҄ҀĐĩĐšĐŧĐ˛ĐžŅ€ĐēĐžĐŧ. +* ĐŖŅŅ– СаĐģĐĩĐļĐŊĐžŅŅ‚Ņ– ĐŧĐžĐļŅƒŅ‚ŅŒ ĐžŅ‚Ņ€Đ¸ĐŧŅƒĐ˛Đ°Ņ‚Đ¸ даĐŊŅ– С СаĐŋĐ¸Ņ‚Ņ–Đ˛ Ņ– Ņ€ĐžĐˇŅˆĐ¸Ņ€ŅŽĐ˛Đ°Ņ‚Đ¸ **ОйĐŧĐĩĐļĐĩĐŊĐŊŅ ĐžĐŋĐĩŅ€Đ°Ņ†Ņ–Ņ— Са ҈ĐģŅŅ…ĐžĐŧ** Ņ‚Đ° Đ°Đ˛Ņ‚ĐžĐŧĐ°Ņ‚Đ¸Ņ‡ĐŊ҃ Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Ņ–ŅŽ. +* **ĐĐ˛Ņ‚ĐžĐŧĐ°Ņ‚Đ¸Ņ‡ĐŊа ваĐģŅ–Đ´Đ°Ņ†Ņ–Ņ** ĐŊĐ°Đ˛Ņ–Ņ‚ŅŒ Đ´ĐģŅ ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Ņ–Đ˛ *ĐžĐŋĐĩŅ€Đ°Ņ†Ņ–Đš ҈ĐģŅŅ…Ņƒ*, виСĐŊĐ°Ņ‡ĐĩĐŊĐ¸Ņ… ҃ СаĐģĐĩĐļĐŊĐžŅŅ‚ŅŅ…. +* ĐŸŅ–Đ´Ņ‚Ņ€Đ¸ĐŧĐēа ҁĐēĐģадĐŊĐ¸Ņ… ŅĐ¸ŅŅ‚ĐĩĐŧ Đ°Đ˛Ņ‚ĐĩĐŊŅ‚Đ¸Ņ„Ņ–ĐēĐ°Ņ†Ņ–Ņ— ĐēĐžŅ€Đ¸ŅŅ‚ŅƒĐ˛Đ°Ņ‡Ņ–Đ˛, **С'Ņ”Đ´ĐŊаĐŊҌ Ņ–Đˇ йаСаĐŧи даĐŊĐ¸Ņ…** Ņ‚ĐžŅ‰Đž. +* **ЖодĐŊĐ¸Ņ… ОйĐŧĐĩĐļĐĩĐŊҌ** Ņ‰ĐžĐ´Đž виĐēĐžŅ€Đ¸ŅŅ‚Đ°ĐŊĐŊŅ йаС даĐŊĐ¸Ņ…, Ņ„Ņ€ĐžĐŊŅ‚ĐĩĐŊĐ´Ņ–Đ˛ Ņ‚ĐžŅ‰Đž, аĐģĐĩ вОдĐŊĐžŅ‡Đ°Ņ ĐŋŅ€ĐžŅŅ‚Đ° Ņ–ĐŊŅ‚ĐĩĐŗŅ€Đ°Ņ†Ņ–Ņ С ŅƒŅŅ–Đŧа ĐŊиĐŧи. + +### НĐĩĐŧĐ°Ņ” ОйĐŧĐĩĐļĐĩĐŊҌ ĐŊа "ĐŋĐģĐ°ĐŗŅ–ĐŊи" + +АйО Ņ–ĐŊŅˆĐ¸Đŧи ҁĐģОваĐŧи, вОĐŊи ĐŊĐĩ ĐŋĐžŅ‚Ņ€Ņ–ĐąĐŊŅ– – ĐŋŅ€ĐžŅŅ‚Đž Ņ–ĐŧĐŋĐžŅ€Ņ‚ŅƒĐšŅ‚Đĩ Ņ‚Đ° виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐšŅ‚Đĩ ĐŊĐĩĐžĐąŅ…Ņ–Đ´ĐŊиК ĐēОд. + +Đ‘ŅƒĐ´ŅŒ-ŅĐēа Ņ–ĐŊŅ‚ĐĩĐŗŅ€Đ°Ņ†Ņ–Ņ ҁĐŋŅ€ĐžŅ”ĐēŅ‚ĐžĐ˛Đ°ĐŊа ĐŊĐ°ŅŅ‚Ņ–ĐģҌĐēи ĐŋŅ€ĐžŅŅ‚Đž (С виĐēĐžŅ€Đ¸ŅŅ‚Đ°ĐŊĐŊŅĐŧ СаĐģĐĩĐļĐŊĐžŅŅ‚ĐĩĐš), Ņ‰Đž ви ĐŧĐžĐļĐĩŅ‚Đĩ ŅŅ‚Đ˛ĐžŅ€Đ¸Ņ‚Đ¸ "ĐŋĐģĐ°ĐŗŅ–ĐŊ" Đ´ĐģŅ ŅĐ˛ĐžĐŗĐž ĐˇĐ°ŅŅ‚ĐžŅŅƒĐŊĐē҃ Đ˛ŅŅŒĐžĐŗĐž ҃ 2 Ņ€ŅĐ´ĐēĐ°Ņ… ĐēĐžĐ´Ņƒ, виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅŽŅ‡Đ¸ Ņ‚Ņƒ ŅĐ°Đŧ҃ ŅŅ‚Ņ€ŅƒĐēŅ‚ŅƒŅ€Ņƒ Ņ‚Đ° ŅĐ¸ĐŊŅ‚Đ°ĐēŅĐ¸Ņ, Ņ‰Đž Đš Đ´ĐģŅ Đ˛Đ°ŅˆĐ¸Ņ… *ĐžĐŋĐĩŅ€Đ°Ņ†Ņ–Đš ҈ĐģŅŅ…Ņƒ*. + +### ĐŸŅ€ĐžŅ‚ĐĩŅŅ‚ĐžĐ˛Đ°ĐŊĐž + +* 100% ĐŋĐžĐēŅ€Đ¸Ņ‚Ņ‚Ņ Ņ‚ĐĩŅŅ‚Đ°Đŧи. +* 100% аĐŊĐžŅ‚ĐžĐ˛Đ°ĐŊа Ņ‚Đ¸ĐŋаĐŧи ĐēОдОва йаСа. +* ВиĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅ”Ņ‚ŅŒŅŅ ҃ Ņ€ĐžĐąĐžŅ‡Đ¸Ņ… ҁĐĩŅ€ĐĩĐ´ĐžĐ˛Đ¸Ņ‰Đ°Ņ…. + +## МоĐļĐģĐ¸Đ˛ĐžŅŅ‚Ņ– Starlette + +**FastAPI** ĐŋОвĐŊŅ–ŅŅ‚ŅŽ ҁ҃ĐŧҖҁĐŊиК Ņ–Đˇ (Ņ‚Đ° ĐŋĐžĐąŅƒĐ´ĐžĐ˛Đ°ĐŊиК ĐŊа ĐžŅĐŊĐžĐ˛Ņ–) Starlette. ĐĸĐžĐŧ҃ ĐąŅƒĐ´ŅŒ-ŅĐēиК Đ´ĐžĐ´Đ°Ņ‚ĐēОвиК ĐēОд Starlette, ŅĐēиК ви ĐŧĐ°Ņ”Ņ‚Đĩ, Ņ‚Đ°ĐēĐžĐļ ĐŋŅ€Đ°Ņ†ŅŽĐ˛Đ°Ņ‚Đ¸ĐŧĐĩ. + +**FastAPI** Ņ„Đ°ĐēŅ‚Đ¸Ņ‡ĐŊĐž Ņ” ĐŋŅ–Đ´ĐēĐģĐ°ŅĐžĐŧ **Starlette**. ĐĸĐžĐŧ҃, ŅĐēŅ‰Đž ви вĐļĐĩ СĐŊаКОĐŧŅ– ĐˇŅ– Starlette айО виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅ”Ņ‚Đĩ ĐšĐžĐŗĐž, ĐąŅ–ĐģŅŒŅˆŅ–ŅŅ‚ŅŒ Ņ„ŅƒĐŊĐēŅ†Ņ–ĐžĐŊаĐģҌĐŊĐžŅŅ‚Ņ– ĐŋŅ€Đ°Ņ†ŅŽĐ˛Đ°Ņ‚Đ¸ĐŧĐĩ Ņ‚Đ°Đē ŅĐ°ĐŧĐž. + +З **FastAPI** ви ĐžŅ‚Ņ€Đ¸ĐŧŅƒŅ”Ņ‚Đĩ Đ˛ŅŅ– ĐŧĐžĐļĐģĐ¸Đ˛ĐžŅŅ‚Ņ– **Starlette** (адĐļĐĩ FastAPI — ҆Đĩ, ĐŋĐž ŅŅƒŅ‚Ņ–, Starlette ĐŊа ҁ҂ĐĩŅ€ĐžŅ—Đ´Đ°Ņ…): + +* Đ Đ°ĐˇŅŽŅ‡Đ° ĐŋŅ€ĐžĐ´ŅƒĐēŅ‚Đ¸Đ˛ĐŊŅ–ŅŅ‚ŅŒ. ĐĻĐĩ ОдиĐŊ Ņ–Đˇ ĐŊĐ°ĐšŅˆĐ˛Đ¸Đ´ŅˆĐ¸Ņ… ҄ҀĐĩĐšĐŧĐ˛ĐžŅ€ĐēŅ–Đ˛ ĐŊа Python, ĐŊа Ņ€Ņ–Đ˛ĐŊŅ– С **NodeJS** Ņ– **Go**. +* ĐŸŅ–Đ´Ņ‚Ņ€Đ¸ĐŧĐēа **WebSocket**. +* ФОĐŊĐžĐ˛Ņ– ĐˇĐ°Đ´Đ°Ņ‡Ņ– ҃ ĐŋŅ€ĐžŅ†ĐĩҁҖ. +* ĐŸĐžĐ´Ņ–Ņ— СаĐŋ҃ҁĐē҃ Ņ‚Đ° СавĐĩŅ€ŅˆĐĩĐŊĐŊŅ Ņ€ĐžĐąĐžŅ‚Đ¸. +* КĐģŅ–Ņ”ĐŊŅ‚ Đ´ĐģŅ Ņ‚ĐĩŅŅ‚ŅƒĐ˛Đ°ĐŊĐŊŅ, ĐŋĐžĐąŅƒĐ´ĐžĐ˛Đ°ĐŊиК ĐŊа HTTPX. +* ĐŸŅ–Đ´Ņ‚Ņ€Đ¸ĐŧĐēа **CORS**, **GZip**, ŅŅ‚Đ°Ņ‚Đ¸Ņ‡ĐŊĐ¸Ņ… Ņ„Đ°ĐšĐģŅ–Đ˛, ĐŋĐžŅ‚ĐžĐēĐžĐ˛Đ¸Ņ… Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´ĐĩĐš. +* ĐŸŅ–Đ´Ņ‚Ņ€Đ¸ĐŧĐēа **ҁĐĩŅŅ–Đš** Ņ– **cookie**. +* 100% ĐŋĐžĐēŅ€Đ¸Ņ‚Ņ‚Ņ Ņ‚ĐĩŅŅ‚Đ°Đŧи. +* 100% аĐŊĐžŅ‚ĐžĐ˛Đ°ĐŊа Ņ‚Đ¸ĐŋаĐŧи ĐēОдОва йаСа. + +## МоĐļĐģĐ¸Đ˛ĐžŅŅ‚Ņ– Pydantic + +**FastAPI** ĐŋОвĐŊŅ–ŅŅ‚ŅŽ ҁ҃ĐŧҖҁĐŊиК Ņ–Đˇ (Ņ‚Đ° ĐŋĐžĐąŅƒĐ´ĐžĐ˛Đ°ĐŊиК ĐŊа ĐžŅĐŊĐžĐ˛Ņ–) Pydantic. ĐĸĐžĐŧ҃ ĐąŅƒĐ´ŅŒ-ŅĐēиК Đ´ĐžĐ´Đ°Ņ‚ĐēОвиК ĐēОд Pydantic, ŅĐēиК ви ĐŧĐ°Ņ”Ņ‚Đĩ, Ņ‚Đ°ĐēĐžĐļ ĐŋŅ€Đ°Ņ†ŅŽĐ˛Đ°Ņ‚Đ¸ĐŧĐĩ. + +ВĐēĐģŅŽŅ‡Đ°ŅŽŅ‡Đ¸ СОвĐŊŅ–ŅˆĐŊŅ– ĐąŅ–ĐąĐģŅ–ĐžŅ‚ĐĩĐēи, ĐŋĐžĐąŅƒĐ´ĐžĐ˛Đ°ĐŊŅ– Ņ‚Đ°ĐēĐžĐļ ĐŊа Pydantic, Ņ‚Đ°ĐēŅ– ŅĐē ORM, ODM Đ´ĐģŅ йаС даĐŊĐ¸Ņ…. + +ĐĻĐĩ Ņ‚Đ°ĐēĐžĐļ ОСĐŊĐ°Ņ‡Đ°Ņ”, Ņ‰Đž в ĐąĐ°ĐŗĐ°Ņ‚ŅŒĐžŅ… виĐŋадĐēĐ°Ņ… ви ĐŧĐžĐļĐĩŅ‚Đĩ ĐŋĐĩŅ€ĐĩĐ´Đ°Ņ‚Đ¸ Ņ‚ĐžĐš ŅĐ°ĐŧиК Ой'Ņ”ĐēŅ‚, ŅĐēиК ĐžŅ‚Ņ€Đ¸ĐŧŅƒŅ”Ņ‚Đĩ С СаĐŋĐ¸Ņ‚Ņƒ, **ĐąĐĩСĐŋĐžŅĐĩŅ€ĐĩĐ´ĐŊŅŒĐž в ĐąĐ°ĐˇŅƒ даĐŊĐ¸Ņ…**, ĐžŅĐēŅ–ĐģҌĐēи Đ˛ŅĐĩ Đ°Đ˛Ņ‚ĐžĐŧĐ°Ņ‚Đ¸Ņ‡ĐŊĐž ĐŋĐĩŅ€ĐĩĐ˛Ņ–Ņ€ŅŅ”Ņ‚ŅŒŅŅ. + +ĐĸĐĩ Đļ ŅĐ°ĐŧĐĩ Đ˛Ņ–Đ´ĐąŅƒĐ˛Đ°Ņ”Ņ‚ŅŒŅŅ Đš ҃ ĐˇĐ˛ĐžŅ€ĐžŅ‚ĐŊĐžĐŧ҃ ĐŊаĐŋŅ€ŅĐŧĐē҃ — ҃ ĐąĐ°ĐŗĐ°Ņ‚ŅŒĐžŅ… виĐŋадĐēĐ°Ņ… ви ĐŧĐžĐļĐĩŅ‚Đĩ ĐŋŅ€ĐžŅŅ‚Đž ĐŋĐĩŅ€ĐĩĐ´Đ°Ņ‚Đ¸ Ой'Ņ”ĐēŅ‚, ŅĐēиК ĐžŅ‚Ņ€Đ¸ĐŧŅƒŅ”Ņ‚Đĩ С йаСи даĐŊĐ¸Ņ…, **ĐąĐĩСĐŋĐžŅĐĩŅ€ĐĩĐ´ĐŊŅŒĐž ĐēĐģŅ–Ņ”ĐŊŅ‚Ņƒ**. + +З **FastAPI** ви ĐžŅ‚Ņ€Đ¸ĐŧŅƒŅ”Ņ‚Đĩ Đ˛ŅŅ– ĐŧĐžĐļĐģĐ¸Đ˛ĐžŅŅ‚Ņ– **Pydantic** (адĐļĐĩ FastAPI ĐąĐ°ĐˇŅƒŅ”Ņ‚ŅŒŅŅ ĐŊа Pydantic Đ´ĐģŅ ĐžĐąŅ€ĐžĐąĐēи Đ˛ŅŅ–Ņ… даĐŊĐ¸Ņ…): + +* **ĐŅ–ŅĐēĐžŅ— ĐŋĐģŅƒŅ‚Đ°ĐŊиĐŊи** : + * НĐĩ ĐŋĐžŅ‚Ņ€Ņ–ĐąĐŊĐž Đ˛Ņ‡Đ¸Ņ‚Đ¸ ĐŊĐžĐ˛Ņƒ ĐŧĐžĐ˛Ņƒ Đ´ĐģŅ виСĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ ҁ҅ĐĩĐŧ. + * Đ¯ĐēŅ‰Đž ви СĐŊĐ°Ņ”Ņ‚Đĩ Ņ‚Đ¸Đŋи Python, ви СĐŊĐ°Ņ”Ņ‚Đĩ, ŅĐē виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ Pydantic. +* ЛĐĩĐŗĐēĐž ĐŋŅ€Đ°Ņ†ŅŽŅ” С Đ˛Đ°ŅˆĐ¸Đŧ **IDE/ĐģŅ–ĐŊŅ‚ĐĩŅ€ĐžĐŧ/ĐŧОСĐēĐžĐŧ**: + * ĐžŅĐēŅ–ĐģҌĐēи ŅŅ‚Ņ€ŅƒĐēŅ‚ŅƒŅ€Đ¸ даĐŊĐ¸Ņ… Pydantic Ņ” ĐŋŅ€ĐžŅŅ‚Đž ĐĩĐēСĐĩĐŧĐŋĐģŅŅ€Đ°Đŧи ĐēĐģĐ°ŅŅ–Đ˛, ŅĐēŅ– ви виСĐŊĐ°Ņ‡Đ°Ņ”Ņ‚Đĩ; Đ°Đ˛Ņ‚ĐžĐ´ĐžĐŋОвĐŊĐĩĐŊĐŊŅ, ĐģŅ–ĐŊŅ‚Đ¸ĐŊĐŗ, mypy Ņ– Đ˛Đ°ŅˆĐ° Ņ–ĐŊŅ‚ŅƒŅ—Ņ†Ņ–Ņ ĐŋОвиĐŊĐŊŅ– Đ´ĐžĐąŅ€Đĩ ĐŋŅ€Đ°Ņ†ŅŽĐ˛Đ°Ņ‚Đ¸ С Đ˛Đ°ŅˆĐ¸Đŧи ĐŋĐĩŅ€ĐĩĐ˛Ņ–Ņ€ĐĩĐŊиĐŧи даĐŊиĐŧи. +* ВаĐģŅ–Đ´Đ°Ņ†Ņ–Ņ **ҁĐēĐģадĐŊĐ¸Ņ… ŅŅ‚Ņ€ŅƒĐēŅ‚ŅƒŅ€**: + * ВиĐēĐžŅ€Đ¸ŅŅ‚Đ°ĐŊĐŊŅ Ņ–Ņ”Ņ€Đ°Ņ€Ņ…Ņ–Ņ‡ĐŊĐ¸Ņ… ĐŧОдĐĩĐģĐĩĐš Pydantic. Python `typing`, `List` Ņ– `Dict` Ņ‚ĐžŅ‰Đž. + * ВаĐģŅ–Đ´Đ°Ņ‚ĐžŅ€Đ¸ дОСвОĐģŅŅŽŅ‚ŅŒ ҇Җ҂ĐēĐž Ņ– ĐŋŅ€ĐžŅŅ‚Đž виСĐŊĐ°Ņ‡Đ°Ņ‚Đ¸, ĐŋĐĩŅ€ĐĩĐ˛Ņ–Ņ€ŅŅ‚Đ¸ Đš Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚ŅƒĐ˛Đ°Ņ‚Đ¸ ҁĐēĐģадĐŊŅ– ҁ҅ĐĩĐŧи даĐŊĐ¸Ņ… ҃ Đ˛Đ¸ĐŗĐģŅĐ´Ņ– JSON-ҁ҅ĐĩĐŧи. + * Ви ĐŧĐžĐļĐĩŅ‚Đĩ ĐŧĐ°Ņ‚Đ¸ ĐŗĐģийОĐēĐž **вĐēĐģадĐĩĐŊŅ– JSON Ой'Ņ”ĐēŅ‚Đ¸** Ņ‚Đ° ĐŋĐĩŅ€ĐĩĐ˛Ņ–Ņ€Đ¸Ņ‚Đ¸ Ņ‚Đ° аĐŊĐžŅ‚ŅƒĐ˛Đ°Ņ‚Đ¸ Ņ—Ņ… Đ˛ŅŅ–. +* **Đ ĐžĐˇŅˆĐ¸Ņ€ŅŽĐ˛Đ°ĐŊŅ–ŅŅ‚ŅŒ**: + * Pydantic дОСвОĐģŅŅ” виСĐŊĐ°Ņ‡Đ°Ņ‚Đ¸ ĐēĐžŅ€Đ¸ŅŅ‚ŅƒĐ˛Đ°Ņ†ŅŒĐēŅ– Ņ‚Đ¸Đŋи даĐŊĐ¸Ņ… айО Ņ€ĐžĐˇŅˆĐ¸Ņ€ŅŽĐ˛Đ°Ņ‚Đ¸ ваĐģŅ–Đ´Đ°Ņ†Ņ–ŅŽ ĐŧĐĩŅ‚ĐžĐ´Đ°Đŧи в ĐŧОдĐĩĐģŅ– Đ´ĐĩĐēĐžŅ€Đ°Ņ‚ĐžŅ€ĐžĐŧ `validator`. +* 100% ĐŋĐžĐēŅ€Đ¸Ņ‚Ņ‚Ņ Ņ‚ĐĩŅŅ‚Đ°Đŧи. diff --git a/docs/uk/docs/index.md b/docs/uk/docs/index.md index 012bac2e2..b573ee259 100644 --- a/docs/uk/docs/index.md +++ b/docs/uk/docs/index.md @@ -6,7 +6,7 @@

- Test + Test Coverage diff --git a/docs/uk/docs/learn/index.md b/docs/uk/docs/learn/index.md new file mode 100644 index 000000000..7f9f21e57 --- /dev/null +++ b/docs/uk/docs/learn/index.md @@ -0,0 +1,5 @@ +# ĐĐ°Đ˛Ņ‡Đ°ĐŊĐŊŅ + +ĐŖ Ņ†ŅŒĐžĐŧ҃ Ņ€ĐžĐˇĐ´Ņ–ĐģŅ– ĐŊадаĐŊŅ– Đ˛ŅŅ‚ŅƒĐŋĐŊŅ– Ņ‚Đ° ĐŊĐ°Đ˛Ņ‡Đ°ĐģҌĐŊŅ– ĐŧĐ°Ņ‚ĐĩŅ€Ņ–Đ°Đģи Đ´ĐģŅ Đ˛Đ¸Đ˛Ņ‡ĐĩĐŊĐŊŅ FastAPI. + +ĐĻĐĩ ĐŧĐžĐļĐŊа Ņ€ĐžĐˇĐŗĐģŅĐ´Đ°Ņ‚Đ¸ ŅĐē **ĐēĐŊĐ¸ĐŗŅƒ**, **ĐēŅƒŅ€Ņ**, айО **ĐžŅ„Ņ–Ņ†Ņ–ĐšĐŊиК** Ņ‚Đ° Ņ€ĐĩĐēĐžĐŧĐĩĐŊдОваĐŊиК ҁĐŋĐžŅŅ–Đą ĐžŅĐ˛ĐžŅ—Ņ‚Đ¸ FastAPI. 😎 diff --git a/docs/uk/docs/tutorial/background-tasks.md b/docs/uk/docs/tutorial/background-tasks.md new file mode 100644 index 000000000..912ba8c2a --- /dev/null +++ b/docs/uk/docs/tutorial/background-tasks.md @@ -0,0 +1,85 @@ +# ФОĐŊĐžĐ˛Ņ– ĐˇĐ°Đ´Đ°Ņ‡Ņ– + +Ви ĐŧĐžĐļĐĩŅ‚Đĩ ŅŅ‚Đ˛ĐžŅ€ŅŽĐ˛Đ°Ņ‚Đ¸ Ņ„ĐžĐŊĐžĐ˛Ņ– ĐˇĐ°Đ´Đ°Ņ‡Ņ–, ŅĐēŅ– ĐąŅƒĐ´ŅƒŅ‚ŅŒ виĐēĐžĐŊŅƒĐ˛Đ°Ņ‚Đ¸ŅŅ *ĐŋҖҁĐģŅ* ĐŋОвĐĩŅ€ĐŊĐĩĐŊĐŊŅ Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´Ņ–. + +ĐĻĐĩ ĐēĐžŅ€Đ¸ŅĐŊĐž Đ´ĐģŅ ĐžĐŋĐĩŅ€Đ°Ņ†Ņ–Đš, ŅĐēŅ– ĐŋĐžŅ‚Ņ€Ņ–ĐąĐŊĐž виĐēĐžĐŊĐ°Ņ‚Đ¸ ĐŋҖҁĐģŅ ĐžĐąŅ€ĐžĐąĐēи СаĐŋĐ¸Ņ‚Ņƒ, аĐģĐĩ ĐēĐģŅ–Ņ”ĐŊŅ‚Ņƒ ĐŊĐĩ ĐžĐąĐžĐ˛â€™ŅĐˇĐēОвО ҇ĐĩĐēĐ°Ņ‚Đ¸ СавĐĩŅ€ŅˆĐĩĐŊĐŊŅ ҆ҖҔҗ ĐžĐŋĐĩŅ€Đ°Ņ†Ņ–Ņ— ĐŋĐĩŅ€ĐĩĐ´ ĐžŅ‚Ņ€Đ¸ĐŧаĐŊĐŊŅĐŧ Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´Ņ–. + +ĐŸŅ€Đ¸ĐēĐģади виĐēĐžŅ€Đ¸ŅŅ‚Đ°ĐŊĐŊŅ: + +* ĐĐ°Đ´ŅĐ¸ĐģаĐŊĐŊŅ email-ҁĐŋĐžĐ˛Ņ–Ņ‰ĐĩĐŊҌ ĐŋҖҁĐģŅ виĐēĐžĐŊаĐŊĐŊŅ ĐŋĐĩвĐŊĐžŅ— Đ´Ņ–Ņ—: + * ĐŸŅ–Đ´ĐēĐģŅŽŅ‡ĐĩĐŊĐŊŅ Đ´Đž ĐŋĐžŅˆŅ‚ĐžĐ˛ĐžĐŗĐž ҁĐĩŅ€Đ˛ĐĩŅ€Đ° Ņ‚Đ° ĐŊĐ°Đ´ŅĐ¸ĐģаĐŊĐŊŅ ĐģĐ¸ŅŅ‚Đ° ĐŧĐžĐļĐĩ СаКĐŧĐ°Ņ‚Đ¸ ĐēŅ–ĐģҌĐēа ҁĐĩĐē҃ĐŊĐ´. Ви ĐŧĐžĐļĐĩŅ‚Đĩ Đ˛Ņ–Đ´Ņ€Đ°ĐˇŅƒ ĐŋОвĐĩŅ€ĐŊŅƒŅ‚Đ¸ Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´ŅŒ, а email Đ˛Ņ–Đ´ĐŋŅ€Đ°Đ˛Đ¸Ņ‚Đ¸ ҃ Ņ„ĐžĐŊŅ–. +* ĐžĐąŅ€ĐžĐąĐēа даĐŊĐ¸Ņ…: + * НаĐŋŅ€Đ¸ĐēĐģад, ŅĐēŅ‰Đž ĐžŅ‚Ņ€Đ¸ĐŧаĐŊĐž Ņ„Đ°ĐšĐģ, ŅĐēиК ĐŋĐžŅ‚Ņ€Ņ–ĐąĐŊĐž ĐžĐąŅ€ĐžĐąĐ¸Ņ‚Đ¸ Đ´ĐžĐ˛ĐŗĐžŅ‚Ņ€Đ¸Đ˛Đ°ĐģиĐŧ ĐŋŅ€ĐžŅ†ĐĩŅĐžĐŧ, ĐŧĐžĐļĐŊа ĐŋОвĐĩŅ€ĐŊŅƒŅ‚Đ¸ Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´ŅŒ "Accepted" ("ĐŸŅ€Đ¸ĐšĐŊŅŅ‚Đž", HTTP 202) Ņ– виĐēĐžĐŊĐ°Ņ‚Đ¸ ĐžĐąŅ€ĐžĐąĐē҃ Ņ„Đ°ĐšĐģ҃ ҃ Ņ„ĐžĐŊŅ–. + +## ВиĐēĐžŅ€Đ¸ŅŅ‚Đ°ĐŊĐŊŅ `BackgroundTasks` + +ĐĄĐŋĐžŅ‡Đ°Ņ‚Đē҃ Ņ–ĐŧĐŋĐžŅ€Ņ‚ŅƒĐšŅ‚Đĩ `BackgroundTasks` Ņ– Đ´ĐžĐ´Đ°ĐšŅ‚Đĩ ĐšĐžĐŗĐž ŅĐē ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ ҃ Đ’Đ°ŅˆŅƒ *Ņ„ŅƒĐŊĐēŅ†Ņ–ŅŽ ĐžĐŋĐĩŅ€Đ°Ņ†Ņ–Ņ— ҈ĐģŅŅ…Ņƒ* (path operation function) Đ´Đž `BackgroundTasks`: + +{* ../../docs_src/background_tasks/tutorial001.py hl[1,13] *} + +**FastAPI** Đ°Đ˛Ņ‚ĐžĐŧĐ°Ņ‚Đ¸Ņ‡ĐŊĐž ŅŅ‚Đ˛ĐžŅ€Đ¸Ņ‚ŅŒ Ой'Ņ”ĐēŅ‚ `BackgroundTasks` Ņ– ĐŋĐĩŅ€ĐĩĐ´Đ°ŅŅ‚ŅŒ ĐšĐžĐŗĐž ҃ ҆ĐĩĐš ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ. + + +## ĐĄŅ‚Đ˛ĐžŅ€ĐĩĐŊĐŊŅ Ņ„ŅƒĐŊĐē҆Җҗ ĐˇĐ°Đ´Đ°Ņ‡Ņ– + +ĐĄŅ‚Đ˛ĐžŅ€Ņ–Ņ‚ŅŒ Ņ„ŅƒĐŊĐēŅ†Ņ–ŅŽ, ŅĐēа ĐąŅƒĐ´Đĩ виĐēĐžĐŊŅƒĐ˛Đ°Ņ‚Đ¸ Ņ„ĐžĐŊĐžĐ˛Ņƒ ĐˇĐ°Đ´Đ°Ņ‡Ņƒ. + +ĐĻĐĩ ĐˇĐ˛Đ¸Ņ‡Đ°ĐšĐŊа Ņ„ŅƒĐŊĐēŅ†Ņ–Ņ, ŅĐēа ĐŧĐžĐļĐĩ ĐžŅ‚Ņ€Đ¸ĐŧŅƒĐ˛Đ°Ņ‚Đ¸ ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ¸. + +ВоĐŊа ĐŧĐžĐļĐĩ ĐąŅƒŅ‚Đ¸ Đ°ŅĐ¸ĐŊŅ…Ņ€ĐžĐŊĐŊĐžŅŽ `async def` айО ĐˇĐ˛Đ¸Ņ‡Đ°ĐšĐŊĐžŅŽ `def` Ņ„ŅƒĐŊĐēŅ†Ņ–Ņ”ŅŽ – **FastAPI** ĐžĐąŅ€ĐžĐąĐ¸Ņ‚ŅŒ Ņ—Ņ— ĐŋŅ€Đ°Đ˛Đ¸ĐģҌĐŊĐž. + +ĐŖ ĐŊĐ°ŅˆĐžĐŧ҃ виĐŋадĐē҃ Ņ„ŅƒĐŊĐēŅ†Ņ–Ņ СаĐŋĐ¸ŅŅƒŅ” ҃ Ņ„Đ°ĐšĐģ (Ņ–ĐŧŅ–Ņ‚ŅƒŅŽŅ‡Đ¸ ĐŊĐ°Đ´ŅĐ¸ĐģаĐŊĐŊŅ email). + +І ĐžŅĐēŅ–ĐģҌĐēи ĐžĐŋĐĩŅ€Đ°Ņ†Ņ–Ņ СаĐŋĐ¸ŅŅƒ ĐŊĐĩ виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅ” `async` Ņ‚Đ° `await`, Đŧи виСĐŊĐ°Ņ‡Đ°Ņ”ĐŧĐž Ņ„ŅƒĐŊĐēŅ†Ņ–ŅŽ ŅĐē ĐˇĐ˛Đ¸Ņ‡Đ°ĐšĐŊ҃ `def`: + +{* ../../docs_src/background_tasks/tutorial001.py hl[6:9] *} + +## ДодаваĐŊĐŊŅ Ņ„ĐžĐŊĐžĐ˛ĐžŅ— ĐˇĐ°Đ´Đ°Ņ‡Ņ– + +ĐŖŅĐĩŅ€ĐĩдиĐŊŅ– Đ’Đ°ŅˆĐžŅ— *Ņ„ŅƒĐŊĐē҆Җҗ ĐžĐąŅ€ĐžĐąĐēи ҈ĐģŅŅ…Ņƒ*, ĐŋĐĩŅ€ĐĩĐ´Đ°ĐšŅ‚Đĩ Ņ„ŅƒĐŊĐēŅ†Ņ–ŅŽ ĐˇĐ°Đ´Đ°Ņ‡Ņ– в Ой'Ņ”ĐēŅ‚ *background tasks*, виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅŽŅ‡Đ¸ ĐŧĐĩŅ‚ĐžĐ´ `.add_task()`: + +{* ../../docs_src/background_tasks/tutorial001.py hl[14] *} + +`.add_task()` ĐŋŅ€Đ¸ĐšĐŧĐ°Ņ” Đ°Ņ€ĐŗŅƒĐŧĐĩĐŊŅ‚Đ¸: + +* Đ¤ŅƒĐŊĐēŅ†Ņ–Ņ ĐˇĐ°Đ´Đ°Ņ‡Đ°, ŅĐēа ĐąŅƒĐ´Đĩ виĐēĐžĐŊŅƒĐ˛Đ°Ņ‚Đ¸ŅŅ ҃ Ņ„ĐžĐŊОвОĐŧ҃ Ņ€ĐĩĐļиĐŧŅ– (`write_notification`). ЗвĐĩŅ€ĐŊŅ–Ņ‚ŅŒ ŅƒĐ˛Đ°ĐŗŅƒ, Ņ‰Đž ĐŋĐĩŅ€ĐĩĐ´Đ°Ņ”Ņ‚ŅŒŅŅ ОйĘŧŅ”ĐēŅ‚ ĐąĐĩС Đ´ŅƒĐļĐžĐē. +* Đ‘ŅƒĐ´ŅŒ-ŅĐēа ĐŋĐžŅĐģŅ–Đ´ĐžĐ˛ĐŊŅ–ŅŅ‚ŅŒ Đ°Ņ€ĐŗŅƒĐŧĐĩĐŊŅ‚Ņ–Đ˛, ŅĐēŅ– ĐŋĐžŅ‚Ņ€Ņ–ĐąĐŊĐž ĐŋĐĩŅ€ĐĩĐ´Đ°Ņ‚Đ¸ ҃ Ņ„ŅƒĐŊĐēŅ†Ņ–ŅŽ СавдаĐŊĐŊŅ ҃ Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´ĐŊĐžĐŧ҃ ĐŋĐžŅ€ŅĐ´Đē҃ (`email`). +* Đ‘ŅƒĐ´ŅŒ-ŅĐēŅ– Ņ–ĐŧĐĩĐŊОваĐŊŅ– Đ°Ņ€ĐŗŅƒĐŧĐĩĐŊŅ‚Đ¸, ŅĐēŅ– ĐŋĐžŅ‚Ņ€Ņ–ĐąĐŊĐž ĐŋĐĩŅ€ĐĩĐ´Đ°Ņ‚Đ¸ ҃ Ņ„ŅƒĐŊĐēŅ†Ņ–ŅŽ ĐˇĐ°Đ´Đ°Ņ‡Ņƒ (`message="some notification"`). + +## ВĐŋŅ€ĐžĐ˛Đ°Đ´ĐļĐĩĐŊĐŊŅ СаĐģĐĩĐļĐŊĐžŅŅ‚ĐĩĐš + +ВиĐēĐžŅ€Đ¸ŅŅ‚Đ°ĐŊĐŊŅ `BackgroundTasks` Ņ‚Đ°ĐēĐžĐļ ĐŋŅ€Đ°Ņ†ŅŽŅ” С ŅĐ¸ŅŅ‚ĐĩĐŧĐžŅŽ вĐŋŅ€ĐžĐ˛Đ°Đ´ĐļĐĩĐŊĐŊŅ СаĐģĐĩĐļĐŊĐžŅŅ‚ĐĩĐš. Ви ĐŧĐžĐļĐĩŅ‚Đĩ ĐžĐŗĐžĐģĐžŅĐ¸Ņ‚Đ¸ ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ Ņ‚Đ¸Đŋ҃ `BackgroundTasks` ĐŊа Ņ€Ņ–ĐˇĐŊĐ¸Ņ… Ņ€Ņ–Đ˛ĐŊŅŅ…: ҃ *Ņ„ŅƒĐŊĐē҆Җҗ ĐžĐŋĐĩŅ€Đ°Ņ†Ņ–Ņ— ҈ĐģŅŅ…Ņƒ*, ҃ СаĐģĐĩĐļĐŊĐžŅŅ‚Ņ– (dependable), ҃ ĐŋŅ–Đ´ СаĐģĐĩĐļĐŊĐžŅŅ‚Ņ– Ņ‚ĐžŅ‰Đž. + +**FastAPI** СĐŊĐ°Ņ”, ŅĐē Đ´Ņ–ŅŅ‚Đ¸ в ĐēĐžĐļĐŊĐžĐŧ҃ виĐŋадĐē҃ Ņ– ŅĐē ĐŋĐžĐ˛Ņ‚ĐžŅ€ĐŊĐž виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ ОдиĐŊ Ņ– Ņ‚ĐžĐš ŅĐ°ĐŧиК Ой'Ņ”ĐēŅ‚, Ņ‰ĐžĐą ŅƒŅŅ– Ņ„ĐžĐŊĐžĐ˛Ņ– ĐˇĐ°Đ´Đ°Ņ‡Ņ– ĐąŅƒĐģи ĐžĐąâ€™Ņ”Đ´ĐŊаĐŊŅ– Ņ‚Đ° виĐēĐžĐŊŅƒĐ˛Đ°ĐģĐ¸ŅŅ ҃ Ņ„ĐžĐŊОвОĐŧ҃ Ņ€ĐĩĐļиĐŧŅ– ĐŋҖҁĐģŅ СавĐĩŅ€ŅˆĐĩĐŊĐŊŅ ĐžŅĐŊОвĐŊĐžĐŗĐž СаĐŋĐ¸Ņ‚Ņƒ. + +{* ../../docs_src/background_tasks/tutorial002_an_py310.py hl[13,15,22,25] *} + +ĐŖ Ņ†ŅŒĐžĐŧ҃ ĐŋŅ€Đ¸ĐēĐģĐ°Đ´Ņ– ĐŋĐžĐ˛Ņ–Đ´ĐžĐŧĐģĐĩĐŊĐŊŅ ĐąŅƒĐ´ŅƒŅ‚ŅŒ СаĐŋĐ¸ŅĐ°ĐŊŅ– ҃ Ņ„Đ°ĐšĐģ `log.txt` *ĐŋҖҁĐģŅ* Ņ‚ĐžĐŗĐž, ŅĐē Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´ŅŒ ĐąŅƒĐ´Đĩ ĐŊĐ°Đ´Ņ–ŅĐģаĐŊа. + +Đ¯ĐēŅ‰Đž ҃ СаĐŋĐ¸Ņ‚Ņ– ĐąŅƒĐ˛ ĐŋĐĩŅ€ĐĩдаĐŊиК query-ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ, Đ˛Ņ–ĐŊ ĐąŅƒĐ´Đĩ СаĐŋĐ¸ŅĐ°ĐŊиК ҃ ĐģĐžĐŗ ҃ Ņ„ĐžĐŊĐžĐ˛Ņ–Đš ĐˇĐ°Đ´Đ°Ņ‡Ņ–. + +А ĐŋĐžŅ‚Ņ–Đŧ Ņ–ĐŊŅˆĐ° Ņ„ĐžĐŊОва ĐˇĐ°Đ´Đ°Ņ‡Đ°, ŅĐēа ŅŅ‚Đ˛ĐžŅ€ŅŽŅ”Ņ‚ŅŒŅŅ ҃ *Ņ„ŅƒĐŊĐē҆Җҗ ĐžĐŋĐĩŅ€Đ°Ņ†Ņ–Ņ— ҈ĐģŅŅ…Ņƒ*, СаĐŋĐ¸ŅˆĐĩ ĐŋĐžĐ˛Ņ–Đ´ĐžĐŧĐģĐĩĐŊĐŊŅ С виĐēĐžŅ€Đ¸ŅŅ‚Đ°ĐŊĐŊŅĐŧ path ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ° `email`. + +## ĐĸĐĩŅ…ĐŊҖ҇ĐŊŅ– Đ´ĐĩŅ‚Đ°ĐģŅ– + +КĐģĐ°Ņ `BackgroundTasks` ĐŋĐžŅ…ĐžĐ´Đ¸Ņ‚ŅŒ ĐąĐĩСĐŋĐžŅĐĩŅ€ĐĩĐ´ĐŊŅŒĐž С `starlette.background`. + +Đ’Ņ–ĐŊ Ņ–ĐŧĐŋĐžŅ€Ņ‚ŅƒŅ”Ņ‚ŅŒŅŅ ĐąĐĩСĐŋĐžŅĐĩŅ€ĐĩĐ´ĐŊŅŒĐž ҃ FastAPI, Ņ‰ĐžĐą Ви ĐŧĐžĐŗĐģи виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ ĐšĐžĐŗĐž С `fastapi` Ņ– виĐŋадĐēОвО ĐŊĐĩ Ņ–ĐŧĐŋĐžŅ€Ņ‚ŅƒĐ˛Đ°Đģи `BackgroundTask` (ĐąĐĩС s в ĐēŅ–ĐŊ҆Җ) С `starlette.background`. + +Đ¯ĐēŅ‰Đž виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ ĐģĐ¸ŅˆĐĩ `BackgroundTasks` (а ĐŊĐĩ `BackgroundTask`), Ņ‚Đž ĐšĐžĐŗĐž ĐŧĐžĐļĐŊа ĐŋĐĩŅ€ĐĩĐ´Đ°Đ˛Đ°Ņ‚Đ¸ ŅĐē ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ ҃ *Ņ„ŅƒĐŊĐē҆Җҗ ĐžĐŋĐĩŅ€Đ°Ņ†Ņ–Ņ— ҈ĐģŅŅ…Ņƒ*, Ņ– **FastAPI** ĐŋĐžĐ´ĐąĐ°Ņ” ĐŋŅ€Đž Đ˛ŅĐĩ Ņ–ĐŊ҈Đĩ, Ņ‚Đ°Đē ŅĐ°ĐŧĐž ŅĐē Ņ– ĐŋŅ€Đž виĐēĐžŅ€Đ¸ŅŅ‚Đ°ĐŊĐŊŅ Ой'Ņ”ĐēŅ‚Đ° `Request`. + +ĐĸаĐēĐžĐļ ĐŧĐžĐļĐŊа виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ `BackgroundTask` ĐžĐēŅ€ĐĩĐŧĐž в FastAPI, аĐģĐĩ Đ´ĐģŅ Ņ†ŅŒĐžĐŗĐž ВаĐŧ дОвĐĩĐ´ĐĩŅ‚ŅŒŅŅ ŅŅ‚Đ˛ĐžŅ€Đ¸Ņ‚Đ¸ Ой'Ņ”ĐēŅ‚ ҃ ĐēĐžĐ´Ņ– Ņ‚Đ° ĐŋОвĐĩŅ€ĐŊŅƒŅ‚Đ¸ Starlette `Response`, вĐēĐģŅŽŅ‡Đ°ŅŽŅ‡Đ¸ ĐšĐžĐŗĐž. + +ДĐĩŅ‚Đ°ĐģҌĐŊŅ–ŅˆĐĩ ĐŧĐžĐļĐŊа ĐŋĐžŅ‡Đ¸Ņ‚Đ°Ņ‚Đ¸ в ĐžŅ„Ņ–Ņ†Ņ–ĐšĐŊŅ–Đš Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Ņ–Ņ— Starlette ĐŋŅ€Đž Ņ„ĐžĐŊĐžĐ˛Ņ– ĐˇĐ°Đ´Đ°Ņ‡Ņ– . + +## Đ—Đ°ŅŅ‚ĐĩŅ€ĐĩĐļĐĩĐŊĐŊŅ + +Đ¯ĐēŅ‰Đž ВаĐŧ ĐŋĐžŅ‚Ņ€Ņ–ĐąĐŊĐž виĐēĐžĐŊŅƒĐ˛Đ°Ņ‚Đ¸ ҁĐēĐģадĐŊŅ– Ņ„ĐžĐŊĐžĐ˛Ņ– ĐžĐąŅ‡Đ¸ŅĐģĐĩĐŊĐŊŅ, Ņ– ĐŋŅ€Đ¸ Ņ†ŅŒĐžĐŧ҃ ĐŊĐĩĐŧа ĐŋĐžŅ‚Ņ€Đĩйи СаĐŋ҃ҁĐēĐ°Ņ‚Đ¸ Ņ—Ņ… ҃ Ņ‚ĐžĐŧ҃ Đļ ĐŋŅ€ĐžŅ†ĐĩҁҖ (ĐŊаĐŋŅ€Đ¸ĐēĐģад, ĐŊĐĩ ĐŋĐžŅ‚Ņ€Ņ–ĐąĐŊĐž ҁĐŋŅ–ĐģҌĐŊĐžĐŗĐž Đ´ĐžŅŅ‚ŅƒĐŋ҃ Đ´Đž ĐŋаĐŧâ€™ŅŅ‚Ņ– Ņ‡Đ¸ СĐŧŅ–ĐŊĐŊĐ¸Ņ…), ĐŧĐžĐļĐģивО, Đ˛Đ°Ņ€Ņ‚Đž ҁĐēĐžŅ€Đ¸ŅŅ‚Đ°Ņ‚Đ¸ŅŅ ĐąŅ–ĐģҌ҈ ĐŋĐžŅ‚ŅƒĐļĐŊиĐŧи Ņ–ĐŊŅŅ‚Ņ€ŅƒĐŧĐĩĐŊŅ‚Đ°Đŧи, Ņ‚Đ°ĐēиĐŧи ŅĐē Celery. + +ĐĸаĐēŅ– Ņ–ĐŊŅŅ‚Ņ€ŅƒĐŧĐĩĐŊŅ‚Đ¸ ĐˇĐ°ĐˇĐ˛Đ¸Ņ‡Đ°Đš ĐŋĐžŅ‚Ņ€ĐĩĐąŅƒŅŽŅ‚ŅŒ ҁĐēĐģадĐŊŅ–ŅˆĐžŅ— ĐēĐžĐŊŅ„Ņ–ĐŗŅƒŅ€Đ°Ņ†Ņ–Ņ— Ņ‚Đ° ĐŧĐĩĐŊĐĩĐ´ĐļĐĩŅ€Đ° ҇ĐĩŅ€ĐŗĐ¸ ĐŋĐžĐ˛Ņ–Đ´ĐžĐŧĐģĐĩĐŊҌ/СавдаĐŊҌ, ĐŊаĐŋŅ€Đ¸ĐēĐģад, RabbitMQ айО Redis. ОдĐŊаĐē вОĐŊи дОСвОĐģŅŅŽŅ‚ŅŒ виĐēĐžĐŊŅƒĐ˛Đ°Ņ‚Đ¸ Ņ„ĐžĐŊĐžĐ˛Ņ– ĐˇĐ°Đ´Đ°Ņ‡Ņ– в ĐēŅ–ĐģҌĐēĐžŅ… ĐŋŅ€ĐžŅ†ĐĩŅĐ°Ņ… Ņ– ĐŊĐ°Đ˛Ņ–Ņ‚ŅŒ ĐŊа ĐēŅ–ĐģҌĐēĐžŅ… ҁĐĩŅ€Đ˛ĐĩŅ€Đ°Ņ…. + +Đ¯ĐēŅ‰Đž Đļ ВаĐŧ ĐŋĐžŅ‚Ņ€Ņ–ĐąĐŊĐž ĐžŅ‚Ņ€Đ¸ĐŧĐ°Ņ‚Đ¸ Đ´ĐžŅŅ‚ŅƒĐŋ Đ´Đž СĐŧŅ–ĐŊĐŊĐ¸Ņ… Ņ– ĐžĐąâ€™Ņ”ĐēŅ‚Ņ–Đ˛ Ņ–Đˇ ҂ҖҔҗ Đļ **FastAPI** - ĐŋŅ€ĐžĐŗŅ€Đ°Đŧи айО виĐēĐžĐŊŅƒĐ˛Đ°Ņ‚Đ¸ ĐŊĐĩвĐĩĐģиĐēŅ– Ņ„ĐžĐŊĐžĐ˛Ņ– СавдаĐŊĐŊŅ (ĐŊаĐŋŅ€Đ¸ĐēĐģад, ĐŊĐ°Đ´ŅĐ¸ĐģĐ°Ņ‚Đ¸ ҁĐŋĐžĐ˛Ņ–Ņ‰ĐĩĐŊĐŊŅ ĐĩĐģĐĩĐēŅ‚Ņ€ĐžĐŊĐŊĐžŅŽ ĐŋĐžŅˆŅ‚ĐžŅŽ), Đ´ĐžŅŅ‚Đ°Ņ‚ĐŊŅŒĐž ĐŋŅ€ĐžŅŅ‚Đž виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ `BackgroundTasks`. + +## ĐŸŅ–Đ´ŅŅƒĐŧĐžĐē + +ІĐŧĐŋĐžŅ€Ņ‚ŅƒĐšŅ‚Đĩ Ņ‚Đ° виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐšŅ‚Đĩ `BackgroundTasks` ŅĐē ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ ҃ *Ņ„ŅƒĐŊĐēŅ†Ņ–ŅŅ… ĐžĐŋĐĩŅ€Đ°Ņ†Ņ–Ņ— ҈ĐģŅŅ…Ņƒ* Ņ‚Đ° СаĐģĐĩĐļĐŊĐžŅŅ‚ŅŅ…, Ņ‰ĐžĐą Đ´ĐžĐ´Đ°Đ˛Đ°Ņ‚Đ¸ Ņ„ĐžĐŊĐžĐ˛Ņ– ĐˇĐ°Đ´Đ°Ņ‡Ņ–. diff --git a/docs/uk/docs/tutorial/body-multiple-params.md b/docs/uk/docs/tutorial/body-multiple-params.md new file mode 100644 index 000000000..e2acf8a70 --- /dev/null +++ b/docs/uk/docs/tutorial/body-multiple-params.md @@ -0,0 +1,170 @@ +# ĐĸŅ–ĐģĐž СаĐŋĐ¸Ņ‚Ņƒ - ДĐĩĐēŅ–ĐģҌĐēа ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Ņ–Đ˛ + +ĐĸĐĩĐŋĐĩŅ€, ĐēĐžĐģи Đŧи Ņ€ĐžĐˇĐŗĐģŅĐŊ҃Đģи виĐēĐžŅ€Đ¸ŅŅ‚Đ°ĐŊĐŊŅ `Path` Ņ‚Đ° `Query`, Ņ€ĐžĐˇĐŗĐģŅĐŊҌĐŧĐž ĐąŅ–ĐģҌ҈ ĐŋŅ€ĐžŅŅƒĐŊŅƒŅ‚Ņ– ҁĐŋĐžŅĐžĐąĐ¸ ĐžĐŗĐžĐģĐžŅˆĐĩĐŊĐŊŅ ҂ҖĐģа СаĐŋĐ¸Ņ‚Ņƒ в **FastAPI**. + +## ЗĐŧŅ–ŅˆŅƒĐ˛Đ°ĐŊĐŊŅ `Path`, `Query` Ņ‚Đ° ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Ņ–Đ˛ ҂ҖĐģа СаĐŋĐ¸Ņ‚Ņƒ + +По-ĐŋĐĩŅ€ŅˆĐĩ, ĐˇĐ˛Ņ–ŅĐŊĐž, Ви ĐŧĐžĐļĐĩŅ‚Đĩ Đ˛Ņ–ĐģҌĐŊĐž СĐŧŅ–ŅˆŅƒĐ˛Đ°Ņ‚Đ¸ ĐžĐŗĐžĐģĐžŅˆĐĩĐŊĐŊŅ ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Ņ–Đ˛ `Path`, `Query` Ņ‚Đ° ҂ҖĐģа СаĐŋĐ¸Ņ‚Ņƒ, Ņ– **FastAPI** ĐŋŅ€Đ°Đ˛Đ¸ĐģҌĐŊĐž Ņ—Ņ… ĐžĐąŅ€ĐžĐąĐ¸Ņ‚ŅŒ. + +ĐĸаĐēĐžĐļ Ви ĐŧĐžĐļĐĩŅ‚Đĩ ĐžĐŗĐžĐģĐžŅĐ¸Ņ‚Đ¸ ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ¸ ҂ҖĐģа ŅĐē ĐŊĐĩĐžĐąĐžĐ˛â€™ŅĐˇĐēĐžĐ˛Ņ–, Đ˛ŅŅ‚Đ°ĐŊĐžĐ˛Đ¸Đ˛ŅˆĐ¸ Đ´ĐģŅ ĐŊĐ¸Ņ… СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ Са СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ `None`: + +{* ../../docs_src/body_multiple_params/tutorial001_an_py310.py hl[18:20] *} + +/// note | ĐŸŅ€Đ¸ĐŧŅ–Ņ‚Đēа + +ЗвĐĩŅ€ĐŊŅ–Ņ‚ŅŒ ŅƒĐ˛Đ°ĐŗŅƒ, Ņ‰Đž в Ņ†ŅŒĐžĐŧ҃ виĐŋадĐē҃ ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ `item`, ŅĐēиК ĐąĐĩŅ€ĐĩŅ‚ŅŒŅŅ С ҂ҖĐģа СаĐŋĐ¸Ņ‚Ņƒ, Ņ” ĐŊĐĩОйОв'ŅĐˇĐēОвиĐŧ, ĐžŅĐēŅ–ĐģҌĐēи ĐŧĐ°Ņ” СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ Са СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ `None`. + +/// + +## ДĐĩĐēŅ–ĐģҌĐēа ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Ņ–Đ˛ ҂ҖĐģа СаĐŋĐ¸Ņ‚Ņƒ + +ĐŖ ĐŋĐžĐŋĐĩŅ€ĐĩĐ´ĐŊŅŒĐžĐŧ҃ ĐŋŅ€Đ¸ĐēĐģĐ°Đ´Ņ– *ĐžĐŋĐĩŅ€Đ°Ņ†Ņ–Ņ ҈ĐģŅŅ…Ņƒ* ĐžŅ‡Ņ–ĐēŅƒĐ˛Đ°Đģа JSON С Đ°Ņ‚Ņ€Đ¸ĐąŅƒŅ‚Đ°Đŧи `Item`, ĐŊаĐŋŅ€Đ¸ĐēĐģад: + +```JSON +{ + "name": "Foo", + "description": "The pretender", + "price": 42.0, + "tax": 3.2 +} +``` +АĐģĐĩ Ви Ņ‚Đ°ĐēĐžĐļ ĐŧĐžĐļĐĩŅ‚Đĩ ĐžĐŗĐžĐģĐžŅĐ¸Ņ‚Đ¸ Đ´ĐĩĐēŅ–ĐģҌĐēа ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Ņ–Đ˛ ҂ҖĐģа, ĐŊаĐŋŅ€Đ¸ĐēĐģад `item` Ņ‚Đ° `user`: + +{* ../../docs_src/body_multiple_params/tutorial002_py310.py hl[20] *} + +ĐŖ Ņ†ŅŒĐžĐŧ҃ виĐŋадĐē҃ **FastAPI** Ņ€ĐžĐˇĐŋŅ–ĐˇĐŊĐ°Ņ”, Ņ‰Đž Ņ” ĐēŅ–ĐģҌĐēа ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Ņ–Đ˛ ҂ҖĐģа (два ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ¸ Ņ” ĐŧОдĐĩĐģŅĐŧи Pydantic). + +ĐĸĐžĐŧ҃ Đ˛Ņ–ĐŊ виĐēĐžŅ€Đ¸ŅŅ‚Đ°Ņ” ĐŊаСви ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Ņ–Đ˛ ŅĐē ĐēĐģŅŽŅ‡Ņ– (ĐŊаСви ĐŋĐžĐģŅ–Đ˛) ҃ ҂ҖĐģŅ– СаĐŋĐ¸Ņ‚Ņƒ, ĐžŅ‡Ņ–ĐēŅƒŅŽŅ‡Đ¸: + +```JSON +{ + "item": { + "name": "Foo", + "description": "The pretender", + "price": 42.0, + "tax": 3.2 + }, + "user": { + "username": "dave", + "full_name": "Dave Grohl" + } +} +``` + +/// note | ĐŸŅ€Đ¸ĐŧŅ–Ņ‚Đēа + +ЗвĐĩŅ€ĐŊŅ–Ņ‚ŅŒ ŅƒĐ˛Đ°ĐŗŅƒ, Ņ‰Đž Ņ…ĐžŅ‡Đ° `item` ĐžĐŗĐžĐģĐžŅˆĐĩĐŊĐž, Ņ‚Đ°Đē ŅĐ°ĐŧĐž ŅĐē Ņ– Ņ€Đ°ĐŊŅ–ŅˆĐĩ, Ņ‚ĐĩĐŋĐĩŅ€ Đ˛Ņ–ĐŊ ĐžŅ‡Ņ–ĐēŅƒŅ”Ņ‚ŅŒŅŅ в ҂ҖĐģŅ– ĐŋŅ–Đ´ ĐēĐģŅŽŅ‡ĐĩĐŧ `item`. + +/// + +**FastAPI** Đ°Đ˛Ņ‚ĐžĐŧĐ°Ņ‚Đ¸Ņ‡ĐŊĐž ĐēĐžĐŊвĐĩŅ€Ņ‚ŅƒŅ” даĐŊŅ– Ņ–Đˇ СаĐŋĐ¸Ņ‚Ņƒ Ņ‚Đ°ĐēиĐŧ Ņ‡Đ¸ĐŊĐžĐŧ, Ņ‰ĐžĐą ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ `item` ĐžŅ‚Ņ€Đ¸Đŧав ŅĐ˛Ņ–Đš вĐŧҖҁ҂, Ņ– Ņ‚Đĩ Đļ ŅĐ°ĐŧĐĩ ŅŅ‚ĐžŅŅƒŅ”Ņ‚ŅŒŅŅ `user`. + +Đ’Ņ–ĐŊ виĐēĐžĐŊĐ°Ņ” ваĐģŅ–Đ´Đ°Ņ†Ņ–ŅŽ ҁĐēĐģадĐĩĐŊĐ¸Ņ… даĐŊĐ¸Ņ… Ņ– СадОĐē҃ĐŧĐĩĐŊŅ‚ŅƒŅ” Ņ—Ņ… Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´ĐŊиĐŧ Ņ‡Đ¸ĐŊĐžĐŧ ҃ ҁ҅ĐĩĐŧŅ– OpenAPI Ņ‚Đ° в Đ°Đ˛Ņ‚ĐžĐŧĐ°Ņ‚Đ¸Ņ‡ĐŊŅ–Đš Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Ņ–Ņ—. + +## ОдиĐŊĐ¸Ņ‡ĐŊŅ– СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ в ҂ҖĐģŅ– СаĐŋĐ¸Ņ‚Ņƒ + +ĐĸаĐē ŅĐ°ĐŧĐž ŅĐē Ņ” `Query` Ņ– `Path` Đ´ĐģŅ виСĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ Đ´ĐžĐ´Đ°Ņ‚ĐēĐžĐ˛Đ¸Ņ… даĐŊĐ¸Ņ… Đ´ĐģŅ ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Ņ–Đ˛ СаĐŋĐ¸Ņ‚Ņƒ Ņ‚Đ° ҈ĐģŅŅ…Ņƒ, **FastAPI** ĐŊĐ°Đ´Đ°Ņ” ĐĩĐēĐ˛Ņ–Đ˛Đ°ĐģĐĩĐŊŅ‚ĐŊиК `Body`. + +НаĐŋŅ€Đ¸ĐēĐģад, Ņ€ĐžĐˇŅˆĐ¸Ņ€ŅŽŅŽŅ‡Đ¸ ĐŋĐžĐŋĐĩŅ€ĐĩĐ´ĐŊŅŽ ĐŧОдĐĩĐģҌ, Ви ĐŧĐžĐļĐĩŅ‚Đĩ Đ˛Đ¸Ņ€Ņ–ŅˆĐ¸Ņ‚Đ¸ Đ´ĐžĐ´Đ°Ņ‚Đ¸ ҉Đĩ ОдиĐŊ ĐēĐģŅŽŅ‡ `importance` в Ņ‚Đĩ Đļ ŅĐ°ĐŧĐĩ ҂ҖĐģĐž СаĐŋĐ¸Ņ‚Ņƒ Ņ€Đ°ĐˇĐžĐŧ Ņ–Đˇ `item` Ņ– `user`. + +Đ¯ĐēŅ‰Đž Ви ĐžĐŗĐžĐģĐžŅĐ¸Ņ‚Đĩ ĐšĐžĐŗĐž ŅĐē Ņ”, Ņ‚Đž, ĐžŅĐēŅ–ĐģҌĐēи ҆Đĩ ОдиĐŊĐ¸Ņ‡ĐŊĐĩ СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ, **FastAPI** ĐŋŅ€Đ¸Đŋ҃ҁĐēĐ°Ņ‚Đ¸ĐŧĐĩ, Ņ‰Đž ҆Đĩ ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ СаĐŋĐ¸Ņ‚Ņƒ (query parameter). + +АĐģĐĩ Ви ĐŧĐžĐļĐĩŅ‚Đĩ вĐēĐ°ĐˇĐ°Ņ‚Đ¸ **FastAPI** ĐžĐąŅ€ĐžĐąĐģŅŅ‚Đ¸ ĐšĐžĐŗĐž ŅĐē Ņ–ĐŊŅˆĐ¸Đš ĐēĐģŅŽŅ‡ ҂ҖĐģа (body key), виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅŽŅ‡Đ¸ `Body`: + +{* ../../docs_src/body_multiple_params/tutorial003_an_py310.py hl[23] *} + +ĐŖ Ņ†ŅŒĐžĐŧ҃ виĐŋадĐē҃ **FastAPI** ĐžŅ‡Ņ–ĐēŅƒĐ˛Đ°Ņ‚Đ¸ĐŧĐĩ ҂ҖĐģĐž СаĐŋĐ¸Ņ‚Ņƒ ҃ Ņ‚Đ°ĐēĐžĐŧ҃ Đ˛Đ¸ĐŗĐģŅĐ´Ņ–: + +```JSON +{ + "item": { + "name": "Foo", + "description": "The pretender", + "price": 42.0, + "tax": 3.2 + }, + "user": { + "username": "dave", + "full_name": "Dave Grohl" + }, + "importance": 5 +} +``` +ЗĐŊĐžĐ˛Ņƒ Đļ Ņ‚Đ°Đēи, **FastAPI** ĐēĐžĐŊвĐĩŅ€Ņ‚ŅƒĐ˛Đ°Ņ‚Đ¸ĐŧĐĩ Ņ‚Đ¸Đŋи даĐŊĐ¸Ņ…, ĐŋĐĩŅ€ĐĩĐ˛Ņ–Ņ€ŅŅ‚Đ¸ĐŧĐĩ Ņ—Ņ…, ŅŅ‚Đ˛ĐžŅ€ŅŽĐ˛Đ°Ņ‚Đ¸ĐŧĐĩ Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Ņ–ŅŽ Ņ‚ĐžŅ‰Đž. + +## ДĐĩĐēŅ–ĐģҌĐēа body Ņ‚Đ° query ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Ņ–Đ˛ + +Đ—Đ˛Ņ–ŅĐŊĐž, Ви ĐŧĐžĐļĐĩŅ‚Đĩ ĐžĐŗĐžĐģĐžŅˆŅƒĐ˛Đ°Ņ‚Đ¸ Đ´ĐžĐ´Đ°Ņ‚ĐēĐžĐ˛Ņ– query ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ¸ СаĐŋĐ¸Ņ‚Ņƒ, ĐēĐžĐģи ҆Đĩ ĐŊĐĩĐžĐąŅ…Ņ–Đ´ĐŊĐž, ĐŊа Đ´ĐžĐ´Đ°Ņ‚ĐžĐē Đ´Đž ĐąŅƒĐ´ŅŒ-ŅĐēĐ¸Ņ… ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Ņ–Đ˛ ҂ҖĐģа СаĐŋĐ¸Ņ‚Ņƒ. + +ĐžŅĐēŅ–ĐģҌĐēи Са СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ ĐžĐēŅ€ĐĩĐŧŅ– СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ Ņ–ĐŊŅ‚ĐĩŅ€ĐŋŅ€ĐĩŅ‚ŅƒŅŽŅ‚ŅŒŅŅ ŅĐē ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ¸ СаĐŋĐ¸Ņ‚Ņƒ, ВаĐŧ ĐŊĐĩ ĐŋĐžŅ‚Ņ€Ņ–ĐąĐŊĐž ŅĐ˛ĐŊĐž Đ´ĐžĐ´Đ°Đ˛Đ°Ņ‚Đ¸ `Query`, ĐŧĐžĐļĐŊа ĐŋŅ€ĐžŅŅ‚Đž виĐēĐžŅ€Đ¸ŅŅ‚Đ°Ņ‚Đ¸: + +```Python +q: Union[str, None] = None +``` + +АйО в Python 3.10 Ņ‚Đ° Đ˛Đ¸Ņ‰Đĩ: + +```Python +q: str | None = None +``` + +НаĐŋŅ€Đ¸ĐēĐģад: + +{* ../../docs_src/body_multiple_params/tutorial004_an_py310.py hl[28] *} + + +/// info | ІĐŊŅ„ĐžŅ€ĐŧĐ°Ņ†Ņ–Ņ + +`Body` Ņ‚Đ°ĐēĐžĐļ ĐŧĐ°Ņ” ҂Җ ŅĐ°ĐŧŅ– Đ´ĐžĐ´Đ°Ņ‚ĐēĐžĐ˛Ņ– ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ¸ ваĐģŅ–Đ´Đ°Ņ†Ņ–Ņ— Ņ‚Đ° ĐŧĐĩŅ‚Đ°Đ´Đ°ĐŊĐ¸Ņ…, Ņ‰Đž Đš `Query`, `Path` Ņ‚Đ° Ņ–ĐŊŅˆŅ–, ŅĐēŅ– Ви ĐŋĐžĐąĐ°Ņ‡Đ¸Ņ‚Đĩ ĐŋŅ–ĐˇĐŊŅ–ŅˆĐĩ. + +/// + +## ВĐēĐģадĐĩĐŊиК ĐŋООдиĐŊĐžĐēиК ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ ҂ҖĐģа СаĐŋĐ¸Ņ‚Ņƒ + +ĐŸŅ€Đ¸ĐŋŅƒŅŅ‚Đ¸ĐŧĐž, ҃ Đ˛Đ°Ņ Ņ” ĐģĐ¸ŅˆĐĩ ОдиĐŊ ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ ҂ҖĐģа СаĐŋĐ¸Ņ‚Ņƒ `item` С ĐŧОдĐĩĐģŅ– Pydantic `Item`. + +За СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ **FastAPI** ĐžŅ‡Ņ–ĐēŅƒĐ˛Đ°Ņ‚Đ¸ĐŧĐĩ, Ņ‰Đž ҂ҖĐģĐž СаĐŋĐ¸Ņ‚Ņƒ ĐŧŅ–ŅŅ‚Đ¸Ņ‚Đ¸ĐŧĐĩ вĐŧҖҁ҂ ĐąĐĩСĐŋĐžŅĐĩŅ€ĐĩĐ´ĐŊŅŒĐž. + +АĐģĐĩ ŅĐēŅ‰Đž Ви Ņ…ĐžŅ‡ĐĩŅ‚Đĩ, Ņ‰ĐžĐą Đ˛Ņ–ĐŊ ĐžŅ‡Ņ–ĐēŅƒĐ˛Đ°Đ˛ JSON С ĐēĐģŅŽŅ‡ĐĩĐŧ `item`, а Đ˛ŅĐĩŅ€ĐĩдиĐŊŅ– — вĐŧҖҁ҂ ĐŧОдĐĩĐģŅ– (Ņ‚Đ°Đē, ŅĐē ҆Đĩ Đ˛Ņ–Đ´ĐąŅƒĐ˛Đ°Ņ”Ņ‚ŅŒŅŅ ĐŋŅ€Đ¸ ĐžĐŗĐžĐģĐžŅˆĐĩĐŊĐŊŅ– Đ´ĐžĐ´Đ°Ņ‚ĐēĐžĐ˛Đ¸Ņ… ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Ņ–Đ˛ ҂ҖĐģа), Ви ĐŧĐžĐļĐĩŅ‚Đĩ виĐēĐžŅ€Đ¸ŅŅ‚Đ°Ņ‚Đ¸ ҁĐŋĐĩŅ†Ņ–Đ°ĐģҌĐŊиК ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ `Body` — `embed`: + +```Python +item: Item = Body(embed=True) +``` + +ŅĐē ҃ ĐŋŅ€Đ¸ĐēĐģĐ°Đ´Ņ–: + +{* ../../docs_src/body_multiple_params/tutorial005_an_py310.py hl[17] *} + +ĐŖ Ņ†ŅŒĐžĐŧ҃ виĐŋадĐē҃ **FastAPI** ĐžŅ‡Ņ–ĐēŅƒĐ˛Đ°Ņ‚Đ¸ĐŧĐĩ ҂ҖĐģĐž СаĐŋĐ¸Ņ‚Ņƒ Ņ‚Đ°ĐēĐžĐŗĐž Đ˛Đ¸ĐŗĐģŅĐ´Ņƒ: + +```JSON hl_lines="2" +{ + "item": { + "name": "Foo", + "description": "The pretender", + "price": 42.0, + "tax": 3.2 + } +} +``` + +СаĐŧŅ–ŅŅ‚ŅŒ: + +```JSON +{ + "name": "Foo", + "description": "The pretender", + "price": 42.0, + "tax": 3.2 +} +``` + +## ĐŸŅ–Đ´ŅŅƒĐŧĐžĐē + +Ви ĐŧĐžĐļĐĩŅ‚Đĩ Đ´ĐžĐ´Đ°Đ˛Đ°Ņ‚Đ¸ ĐēŅ–ĐģҌĐēа ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Ņ–Đ˛ ҂ҖĐģа Đ´Đž Đ’Đ°ŅˆĐžŅ— *Ņ„ŅƒĐŊĐē҆Җҗ ĐžĐŋĐĩŅ€Đ°Ņ†Ņ–Ņ— ҈ĐģŅŅ…Ņƒ* (*path operation function*), ĐŊĐ°Đ˛Ņ–Ņ‚ŅŒ ŅĐēŅ‰Đž СаĐŋĐ¸Ņ‚ ĐŧĐžĐļĐĩ ĐŧĐ°Ņ‚Đ¸ ĐģĐ¸ŅˆĐĩ ОдĐŊĐĩ ҂ҖĐģĐž. + +АĐģĐĩ **FastAPI** ĐžĐąŅ€ĐžĐąĐ¸Ņ‚ŅŒ ҆Đĩ, ĐŊĐ°Đ´Đ°ŅŅ‚ŅŒ ВаĐŧ ĐŋĐžŅ‚Ņ€Ņ–ĐąĐŊŅ– даĐŊŅ– ҃ Ņ„ŅƒĐŊĐē҆Җҗ, ĐŋĐĩŅ€ĐĩĐ˛Ņ–Ņ€Đ¸Ņ‚ŅŒ Ņ—Ņ… Ņ‚Đ° СадОĐē҃ĐŧĐĩĐŊŅ‚ŅƒŅ” ĐēĐžŅ€ĐĩĐēŅ‚ĐŊ҃ ҁ҅ĐĩĐŧ҃ в *ĐžĐŋĐĩŅ€Đ°Ņ†Ņ–Ņ— ҈ĐģŅŅ…Ņƒ*. + +ĐĸаĐēĐžĐļ Ви ĐŧĐžĐļĐĩŅ‚Đĩ ĐžĐŗĐžĐģĐžŅˆŅƒĐ˛Đ°Ņ‚Đ¸ ĐžĐēŅ€ĐĩĐŧŅ– СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ, ŅĐēŅ– ĐąŅƒĐ´ŅƒŅ‚ŅŒ ĐžŅ‚Ņ€Đ¸ĐŧаĐŊŅ– ŅĐē Ņ‡Đ°ŅŅ‚Đ¸ĐŊа ҂ҖĐģа СаĐŋĐ¸Ņ‚Ņƒ. + +ĐšŅ€Ņ–Đŧ Ņ‚ĐžĐŗĐž, Ви ĐŧĐžĐļĐĩŅ‚Đĩ вĐēĐ°ĐˇĐ°Ņ‚Đ¸ **FastAPI** Đ˛ĐąŅƒĐ´ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ ҂ҖĐģĐž в ĐēĐģŅŽŅ‡, ĐŊĐ°Đ˛Ņ–Ņ‚ŅŒ ŅĐēŅ‰Đž ĐžĐŗĐžĐģĐžŅˆĐĩĐŊĐž ĐģĐ¸ŅˆĐĩ ОдиĐŊ ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ. diff --git a/docs/uk/docs/tutorial/body-nested-models.md b/docs/uk/docs/tutorial/body-nested-models.md new file mode 100644 index 000000000..abc33f2eb --- /dev/null +++ b/docs/uk/docs/tutorial/body-nested-models.md @@ -0,0 +1,245 @@ +# ĐĸŅ–ĐģĐž СаĐŋĐ¸Ņ‚Ņƒ - ВĐēĐģадĐĩĐŊŅ– ĐŧОдĐĩĐģŅ– + +З **FastAPI** Ви ĐŧĐžĐļĐĩŅ‚Đĩ виСĐŊĐ°Ņ‡Đ°Ņ‚Đ¸, ĐŋĐĩŅ€ĐĩĐ˛Ņ–Ņ€ŅŅ‚Đ¸, Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚ŅƒĐ˛Đ°Ņ‚Đ¸ Ņ‚Đ° виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ ĐŧОдĐĩĐģŅ–, ŅĐēŅ– ĐŧĐžĐļŅƒŅ‚ŅŒ ĐąŅƒŅ‚Đ¸ вĐēĐģадĐĩĐŊŅ– ĐŊа ĐąŅƒĐ´ŅŒ-ŅĐē҃ ĐŗĐģийиĐŊ҃ (ĐˇĐ°Đ˛Đ´ŅĐēи Pydantic). + +## ПоĐģŅ ҁĐŋĐ¸ŅĐē҃ + +Ви ĐŧĐžĐļĐĩŅ‚Đĩ виСĐŊĐ°Ņ‡Đ¸Ņ‚Đ¸ Đ°Ņ‚Ņ€Đ¸ĐąŅƒŅ‚ ŅĐē ĐŋŅ–Đ´Ņ‚Đ¸Đŋ. НаĐŋŅ€Đ¸ĐēĐģад, Python-ҁĐŋĐ¸ŅĐžĐē (`list`): + +{* ../../docs_src/body_nested_models/tutorial001_py310.py hl[12] *} + +ĐĻĐĩ ĐˇŅ€ĐžĐąĐ¸Ņ‚ŅŒ `tags` ҁĐŋĐ¸ŅĐēĐžĐŧ, Ņ…ĐžŅ‡Đ° ĐŊĐĩ виСĐŊĐ°Ņ‡Đ°Ņ”Ņ‚ŅŒŅŅ Ņ‚Đ¸Đŋ ĐĩĐģĐĩĐŧĐĩĐŊŅ‚Ņ–Đ˛ ҁĐŋĐ¸ŅĐē҃. + +## ПоĐģŅ ҁĐŋĐ¸ŅĐē҃ С ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€ĐžĐŧ Ņ‚Đ¸Đŋ҃ + +АĐģĐĩ Python ĐŧĐ°Ņ” ҁĐŋĐĩŅ†Đ¸Ņ„Ņ–Ņ‡ĐŊиК ҁĐŋĐžŅŅ–Đą ĐžĐŗĐžĐģĐžŅˆĐĩĐŊĐŊŅ ҁĐŋĐ¸ŅĐēŅ–Đ˛ С вĐŊŅƒŅ‚Ņ€Ņ–ŅˆĐŊŅ–Đŧи Ņ‚Đ¸ĐŋаĐŧи айО "ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ°Đŧи Ņ‚Đ¸Đŋ҃": +### ІĐŧĐŋĐžŅ€Ņ‚ŅƒŅ”ĐŧĐž `List` С ĐŧĐžĐ´ŅƒĐģŅ typing + +ĐŖ Python 3.9 Ņ– Đ˛Đ¸Ņ‰Đĩ ĐŧĐžĐļĐŊа виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ ŅŅ‚Đ°ĐŊĐ´Đ°Ņ€Ņ‚ĐŊиК `list` Đ´ĐģŅ ĐžĐŗĐžĐģĐžŅˆĐĩĐŊĐŊŅ Ņ‚Đ°ĐēĐ¸Ņ… Ņ‚Đ¸ĐŋŅ–Đ˛, ŅĐē Đŧи ĐŋĐžĐąĐ°Ņ‡Đ¸ĐŧĐž ĐŊиĐļ҇Đĩ. 💡 + +АĐģĐĩ в Python вĐĩҀҁҖҗ Đ´Đž 3.9 (Đ˛Ņ–Đ´ 3.6 Ņ– Đ˛Đ¸Ņ‰Đĩ) ҁĐŋĐžŅ‡Đ°Ņ‚Đē҃ ĐŋĐžŅ‚Ņ€Ņ–ĐąĐŊĐž Ņ–ĐŧĐŋĐžŅ€Ņ‚ŅƒĐ˛Đ°Ņ‚Đ¸ `List` С ĐŧĐžĐ´ŅƒĐģŅ ŅŅ‚Đ°ĐŊĐ´Đ°Ņ€Ņ‚ĐŊĐžŅ— ĐąŅ–ĐąĐģŅ–ĐžŅ‚ĐĩĐēи Python `typing`: + +{* ../../docs_src/body_nested_models/tutorial002.py hl[1] *} + +### ĐžĐŗĐžĐģĐžŅˆĐĩĐŊĐŊŅ `list` С ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€ĐžĐŧ Ņ‚Đ¸Đŋ҃ + +ЊОй ĐžĐŗĐžĐģĐžŅĐ¸Ņ‚Đ¸ Ņ‚Đ¸Đŋи С ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ°Đŧи Ņ‚Đ¸Đŋ҃ (вĐŊŅƒŅ‚Ņ€Ņ–ŅˆĐŊŅ–Đŧи Ņ‚Đ¸ĐŋаĐŧи), Ņ‚Đ°ĐēиĐŧи ŅĐē `list`, `dict`, `tuple`: + +* Đ¯ĐēŅ‰Đž Ви виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅ”Ņ‚Đĩ вĐĩŅ€ŅŅ–ŅŽ Python Đ´Đž 3.9, Ņ–ĐŧĐŋĐžŅ€Ņ‚ŅƒĐšŅ‚Đĩ Ņ—Ņ… Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´ĐŊ҃ вĐĩŅ€ŅŅ–ŅŽ С ĐŧĐžĐ´ŅƒĐģŅ `typing`. +* ПĐĩŅ€ĐĩĐ´Đ°ĐšŅ‚Đĩ вĐŊŅƒŅ‚Ņ€Ņ–ŅˆĐŊŅ– Ņ‚Đ¸Đŋи ŅĐē "ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ¸ Ņ‚Đ¸Đŋ҃", виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅŽŅ‡Đ¸ ĐēĐ˛Đ°Đ´Ņ€Đ°Ņ‚ĐŊŅ– Đ´ŅƒĐļĐēи: `[` and `]`. + +ĐŖ Python 3.9 ҆Đĩ ĐąŅƒĐ´Đĩ Đ˛Đ¸ĐŗĐģŅĐ´Đ°Ņ‚Đ¸ Ņ‚Đ°Đē: + +```Python +my_list: list[str] +``` + +ĐŖ вĐĩŅ€ŅŅ–ŅŅ… Python Đ´Đž 3.9 ҆Đĩ Đ˛Đ¸ĐŗĐģŅĐ´Đ°Ņ” Ņ‚Đ°Đē: + +```Python +from typing import List + +my_list: List[str] +``` + +ĐĻĐĩ ŅŅ‚Đ°ĐŊĐ´Đ°Ņ€Ņ‚ĐŊиК ŅĐ¸ĐŊŅ‚Đ°ĐēŅĐ¸Ņ Python Đ´ĐģŅ ĐžĐŗĐžĐģĐžŅˆĐĩĐŊĐŊŅ Ņ‚Đ¸ĐŋŅ–Đ˛. + +ВиĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐšŅ‚Đĩ Ņ‚ĐžĐš ŅĐ°ĐŧиК ŅŅ‚Đ°ĐŊĐ´Đ°Ņ€Ņ‚ĐŊиК ŅĐ¸ĐŊŅ‚Đ°ĐēŅĐ¸Ņ Đ´ĐģŅ Đ°Ņ‚Ņ€Đ¸ĐąŅƒŅ‚Ņ–Đ˛ ĐŧОдĐĩĐģĐĩĐš С вĐŊŅƒŅ‚Ņ€Ņ–ŅˆĐŊŅ–Đŧи Ņ‚Đ¸ĐŋаĐŧи. + +ĐžŅ‚ĐļĐĩ, ҃ ĐŊĐ°ŅˆĐžĐŧ҃ ĐŋŅ€Đ¸ĐēĐģĐ°Đ´Ņ–, Đŧи ĐŧĐžĐļĐĩĐŧĐž ĐˇŅ€ĐžĐąĐ¸Ņ‚Đ¸ `tags` ŅĐ°ĐŧĐĩ "ҁĐŋĐ¸ŅĐēĐžĐŧ Ņ€ŅĐ´ĐēŅ–Đ˛": + +{* ../../docs_src/body_nested_models/tutorial002_py310.py hl[12] *} + +## ĐĸиĐŋи ĐŧĐŊĐžĐļиĐŊ + +АĐģĐĩ ĐŋĐžŅ‚Ņ–Đŧ Đŧи ĐŋĐžĐ´ŅƒĐŧаĐģи, Ņ‰Đž Ņ‚ĐĩĐŗĐ¸ ĐŊĐĩ ĐŋОвиĐŊĐŊŅ– ĐŋĐžĐ˛Ņ‚ĐžŅ€ŅŽĐ˛Đ°Ņ‚Đ¸ŅŅ, вОĐŊи, ĐšĐŧĐžĐ˛Ņ–Ņ€ĐŊĐž, ĐŋОвиĐŊĐŊŅ– ĐąŅƒŅ‚Đ¸ ҃ĐŊŅ–ĐēаĐģҌĐŊиĐŧи Ņ€ŅĐ´ĐēаĐŧи. + +І Python ĐŧĐ°Ņ” ҁĐŋĐĩŅ†Ņ–Đ°ĐģҌĐŊиК Ņ‚Đ¸Đŋ даĐŊĐ¸Ņ… Đ´ĐģŅ ĐŧĐŊĐžĐļиĐŊ ҃ĐŊŅ–ĐēаĐģҌĐŊĐ¸Ņ… ĐĩĐģĐĩĐŧĐĩĐŊŅ‚Ņ–Đ˛ — ҆Đĩ `set`. + +ĐĸĐžĐŧ҃ Đŧи ĐŧĐžĐļĐĩĐŧĐž ĐžĐŗĐžĐģĐžŅĐ¸Ņ‚Đ¸ `tags` ŅĐē ĐŧĐŊĐžĐļиĐŊ҃ Ņ€ŅĐ´ĐēŅ–Đ˛: + +{* ../../docs_src/body_nested_models/tutorial003_py310.py hl[12] *} + +ĐĐ°Đ˛Ņ–Ņ‚ŅŒ ŅĐēŅ‰Đž Ви ĐžŅ‚Ņ€Đ¸ĐŧĐ°Ņ”Ņ‚Đĩ СаĐŋĐ¸Ņ‚ С Đ´ŅƒĐąĐģŅŒĐžĐ˛Đ°ĐŊиĐŧи даĐŊиĐŧи, Đ˛Ņ–ĐŊ ĐąŅƒĐ´Đĩ ĐŋĐĩŅ€ĐĩŅ‚Đ˛ĐžŅ€ĐĩĐŊиК ҃ ĐŧĐŊĐžĐļиĐŊ҃ ҃ĐŊŅ–ĐēаĐģҌĐŊĐ¸Ņ… ĐĩĐģĐĩĐŧĐĩĐŊŅ‚Ņ–Đ˛. + +І ĐēĐžĐģи Ви ĐąŅƒĐ´ĐĩŅ‚Đĩ Đ˛Đ¸Đ˛ĐžĐ´Đ¸Ņ‚Đ¸ ҆Җ даĐŊŅ–, ĐŊĐ°Đ˛Ņ–Ņ‚ŅŒ ŅĐēŅ‰Đž Đ´ĐļĐĩŅ€ĐĩĐģĐž ĐŧŅ–ŅŅ‚Đ¸Ņ‚ŅŒ Đ´ŅƒĐąĐģŅ–ĐēĐ°Ņ‚Đ¸, вОĐŊи ĐąŅƒĐ´ŅƒŅ‚ŅŒ вивĐĩĐ´ĐĩĐŊŅ– ŅĐē ĐŧĐŊĐžĐļиĐŊа ҃ĐŊŅ–ĐēаĐģҌĐŊĐ¸Ņ… ĐĩĐģĐĩĐŧĐĩĐŊŅ‚Ņ–Đ˛. + +І ҆Đĩ ĐąŅƒĐ´Đĩ аĐŊĐžŅ‚ĐžĐ˛Đ°ĐŊĐž/Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚ĐžĐ˛Đ°ĐŊĐž Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´ĐŊĐž. + +## ВĐēĐģадĐĩĐŊŅ– ĐŧОдĐĩĐģŅ– + +КоĐļĐĩĐŊ Đ°Ņ‚Ņ€Đ¸ĐąŅƒŅ‚ ĐŧОдĐĩĐģŅ– Pydantic ĐŧĐ°Ņ” Ņ‚Đ¸Đŋ. + +АĐģĐĩ ҆ĐĩĐš Ņ‚Đ¸Đŋ ŅĐ°Đŧ ĐŧĐžĐļĐĩ ĐąŅƒŅ‚Đ¸ Ņ–ĐŊŅˆĐžŅŽ ĐŧОдĐĩĐģĐģŅŽ Pydantic. + +ĐžŅ‚ĐļĐĩ, Ви ĐŧĐžĐļĐĩŅ‚Đĩ ĐžĐŗĐžĐģĐžŅĐ¸Ņ‚Đ¸ ĐŗĐģийОĐēĐž вĐēĐģадĐĩĐŊŅ– JSON "Ой'Ņ”ĐēŅ‚Đ¸" С ĐēĐžĐŊĐēŅ€ĐĩŅ‚ĐŊиĐŧи Ņ–ĐŧĐĩĐŊаĐŧи Đ°Ņ‚Ņ€Đ¸ĐąŅƒŅ‚Ņ–Đ˛, Ņ‚Đ¸ĐŋаĐŧи Ņ‚Đ° ĐŋĐĩŅ€ĐĩĐ˛Ņ–Ņ€ĐēаĐŧи. + +ĐŖŅĐĩ ҆Đĩ, вĐēĐģадĐĩĐŊĐĩ ĐąĐĩС ОйĐŧĐĩĐļĐĩĐŊҌ. + +### ВизĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ ĐŋŅ–Đ´ĐŧОдĐĩĐģŅ– + +НаĐŋŅ€Đ¸ĐēĐģад, Đŧи ĐŧĐžĐļĐĩĐŧĐž виСĐŊĐ°Ņ‡Đ¸Ņ‚Đ¸ ĐŧОдĐĩĐģҌ `Image`: + +{* ../../docs_src/body_nested_models/tutorial004_py310.py hl[7:9] *} + +### ВиĐēĐžŅ€Đ¸ŅŅ‚Đ°ĐŊĐŊŅ ĐŋŅ–Đ´ĐŧОдĐĩĐģŅ– ŅĐē Ņ‚Đ¸Đŋ҃ + +А ĐŋĐžŅ‚Ņ–Đŧ Đŧи ĐŧĐžĐļĐĩĐŧĐž виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ Ņ—Ņ— ŅĐē Ņ‚Đ¸Đŋ Đ°Ņ‚Ņ€Đ¸ĐąŅƒŅ‚Đ°: + +{* ../../docs_src/body_nested_models/tutorial004_py310.py hl[18] *} + +ĐĻĐĩ ОСĐŊĐ°Ņ‡Đ°Ņ‚Đ¸ĐŧĐĩ, Ņ‰Đž **FastAPI** ĐžŅ‡Ņ–ĐēŅƒĐ˛Đ°Ņ‚Đ¸ĐŧĐĩ ҂ҖĐģĐž СаĐŋĐ¸Ņ‚Ņƒ Ņ‚Đ°ĐēĐžĐŗĐž Đ˛Đ¸ĐŗĐģŅĐ´Ņƒ: + +```JSON +{ + "name": "Foo", + "description": "The pretender", + "price": 42.0, + "tax": 3.2, + "tags": ["rock", "metal", "bar"], + "image": { + "url": "http://example.com/baz.jpg", + "name": "The Foo live" + } +} +``` + +Đ—Đ°Đ˛Đ´ŅĐēи Ņ‚Đ°ĐēŅ–Đš Đ´ĐĩĐēĐģĐ°Ņ€Đ°Ņ†Ņ–Ņ— ҃ **FastAPI** Ви ĐžŅ‚Ņ€Đ¸ĐŧŅƒŅ”Ņ‚Đĩ: + +* ĐŸŅ–Đ´Ņ‚Ņ€Đ¸ĐŧĐē҃ в Ņ€ĐĩдаĐēŅ‚ĐžŅ€Ņ– (Đ°Đ˛Ņ‚ĐžĐˇĐ°Đ˛ĐĩŅ€ŅˆĐĩĐŊĐŊŅ Ņ‚ĐžŅ‰Đž), ĐŊĐ°Đ˛Ņ–Ņ‚ŅŒ Đ´ĐģŅ вĐēĐģадĐĩĐŊĐ¸Ņ… ĐŧОдĐĩĐģĐĩĐš +* КоĐŊвĐĩŅ€Ņ‚Đ°Ņ†Ņ–ŅŽ даĐŊĐ¸Ņ… +* ВаĐģŅ–Đ´Đ°Ņ†Ņ–ŅŽ даĐŊĐ¸Ņ… +* ĐĐ˛Ņ‚ĐžĐŧĐ°Ņ‚Đ¸Ņ‡ĐŊ҃ Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Ņ–ŅŽ + +## ĐĄĐŋĐĩŅ†Ņ–Đ°ĐģҌĐŊŅ– Ņ‚Đ¸Đŋи Ņ‚Đ° ваĐģŅ–Đ´Đ°Ņ†Ņ–Ņ + +ОĐēҀҖĐŧ ĐˇĐ˛Đ¸Ņ‡Đ°ĐšĐŊĐ¸Ņ… Ņ‚Đ¸ĐŋŅ–Đ˛, Ņ‚Đ°ĐēĐ¸Ņ… ŅĐē `str`, `int`, `float`, Ņ‚Đ° Ņ–ĐŊ. Ви ĐŧĐžĐļĐĩŅ‚Đĩ виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ ҁĐēĐģадĐŊŅ–ŅˆŅ– Ņ‚Đ¸Đŋи, ŅĐēŅ– ĐŊĐ°ŅĐģŅ–Đ´ŅƒŅŽŅ‚ŅŒ `str`. + +ЊОй ĐŋĐžĐąĐ°Ņ‡Đ¸Ņ‚Đ¸ Đ˛ŅŅ– Đ´ĐžŅŅ‚ŅƒĐŋĐŊŅ– Đ˛Đ°Ņ€Ņ–Đ°ĐŊŅ‚Đ¸, ОСĐŊаКОĐŧŅ‚ĐĩŅŅ С ĐžĐŗĐģŅĐ´ĐžĐŧ Ņ‚Đ¸ĐŋŅ–Đ˛ ҃ Pydantic. ДĐĩŅĐēŅ– ĐŋŅ€Đ¸ĐēĐģади ĐąŅƒĐ´ŅƒŅ‚ŅŒ ҃ ĐŊĐ°ŅŅ‚ŅƒĐŋĐŊĐ¸Ņ… Ņ€ĐžĐˇĐ´Ņ–ĐģĐ°Ņ…. + +НаĐŋŅ€Đ¸ĐēĐģад, ҃ ĐŧОдĐĩĐģŅ– `Image` Ņ” ĐŋĐžĐģĐĩ `url`, Ņ‚ĐžĐŧ҃ Đŧи ĐŧĐžĐļĐĩĐŧĐž ĐžĐŗĐžĐģĐžŅĐ¸Ņ‚Đ¸ ĐšĐžĐŗĐž ŅĐē `HttpUrl` Đ˛Ņ–Đ´ Pydantic СаĐŧŅ–ŅŅ‚ŅŒ `str`: + +{* ../../docs_src/body_nested_models/tutorial005_py310.py hl[2,8] *} + +Đ ŅĐ´ĐžĐē ĐąŅƒĐ´Đĩ ĐŋĐĩŅ€ĐĩĐ˛Ņ–Ņ€ĐĩĐŊĐž ŅĐē Đ´Ņ–ĐšŅĐŊ҃ URL-Đ°Đ´Ņ€Đĩҁ҃ Ņ– СадОĐē҃ĐŧĐĩĐŊŅ‚ĐžĐ˛Đ°ĐŊĐž в JSON Schema / OpenAPI ŅĐē URL. + +## ĐŅ‚Ņ€Đ¸ĐąŅƒŅ‚Đ¸ ĐˇŅ– ҁĐŋĐ¸ŅĐēаĐŧи ĐŋŅ–Đ´ĐŧОдĐĩĐģĐĩĐš + +ĐŖ Pydantic Ви ĐŧĐžĐļĐĩŅ‚Đĩ виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ ĐŧОдĐĩĐģŅ– ŅĐē ĐŋŅ–Đ´Ņ‚Đ¸Đŋи Đ´ĐģŅ `list`, `set` Ņ‚ĐžŅ‰Đž: + +{* ../../docs_src/body_nested_models/tutorial006_py310.py hl[18] *} + +ĐĻĐĩ ОСĐŊĐ°Ņ‡Đ°Ņ”, Ņ‰Đž **FastAPI** ĐąŅƒĐ´Đĩ ĐžŅ‡Ņ–ĐēŅƒĐ˛Đ°Ņ‚Đ¸ (ĐēĐžĐŊвĐĩŅ€Ņ‚ŅƒĐ˛Đ°Ņ‚Đ¸, ваĐģŅ–Đ´ŅƒĐ˛Đ°Ņ‚Đ¸, Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚ŅƒĐ˛Đ°Ņ‚Đ¸ Ņ‚ĐžŅ‰Đž) JSON ҂ҖĐģĐž СаĐŋĐ¸Ņ‚Ņƒ ҃ Đ˛Đ¸ĐŗĐģŅĐ´Ņ–: + +```JSON hl_lines="11" +{ + "name": "Foo", + "description": "The pretender", + "price": 42.0, + "tax": 3.2, + "tags": [ + "rock", + "metal", + "bar" + ], + "images": [ + { + "url": "http://example.com/baz.jpg", + "name": "The Foo live" + }, + { + "url": "http://example.com/dave.jpg", + "name": "The Baz" + } + ] +} +``` + +/// info | ІĐŊŅ„ĐžŅ€ĐŧĐ°Ņ†Ņ–Ņ + +ЗвĐĩŅ€ĐŊŅ–Ņ‚ŅŒ ŅƒĐ˛Đ°ĐŗŅƒ, Ņ‰Đž Ņ‚ĐĩĐŋĐĩŅ€ ĐēĐģŅŽŅ‡ `images` ĐŧŅ–ŅŅ‚Đ¸Ņ‚ŅŒ ҁĐŋĐ¸ŅĐžĐē Ой'Ņ”ĐēŅ‚Ņ–Đ˛ ĐˇĐžĐąŅ€Đ°ĐļĐĩĐŊҌ. + +/// + +## ГĐģийОĐēĐž вĐēĐģадĐĩĐŊŅ– ĐŧОдĐĩĐģŅ– + +Ви ĐŧĐžĐļĐĩŅ‚Đĩ виСĐŊĐ°Ņ‡Đ°Ņ‚Đ¸ вĐēĐģадĐĩĐŊŅ– ĐŧОдĐĩĐģŅ– Đ´ĐžĐ˛Ņ–ĐģҌĐŊĐžŅ— ĐŗĐģийиĐŊи: + +{* ../../docs_src/body_nested_models/tutorial007_py310.py hl[7,12,18,21,25] *} + +/// info | ІĐŊŅ„ĐžŅ€ĐŧĐ°Ņ†Ņ–Ņ + +ЗвĐĩŅ€ĐŊŅ–Ņ‚ŅŒ ŅƒĐ˛Đ°ĐŗŅƒ, Ņ‰Đž в ĐŧОдĐĩĐģŅ– `Offer` Ņ” ҁĐŋĐ¸ŅĐžĐē `Item`Ņ–Đ˛, ŅĐēŅ–, ŅĐ˛ĐžŅ”ŅŽ ҇ĐĩŅ€ĐŗĐžŅŽ, ĐŧĐžĐļŅƒŅ‚ŅŒ ĐŧĐ°Ņ‚Đ¸ ĐŊĐĩОйОв'ŅĐˇĐēОвиК ҁĐŋĐ¸ŅĐžĐē `Image`Ņ–Đ˛. + +/// + +## ĐĸŅ–Đģа СаĐŋĐ¸Ņ‚Ņ–Đ˛, Ņ‰Đž ҁĐēĐģĐ°Đ´Đ°ŅŽŅ‚ŅŒŅŅ ĐˇŅ– ҁĐŋĐ¸ŅĐēŅ–Đ˛ + +Đ¯ĐēŅ‰Đž вĐĩҀ҅ĐŊŅ–Đš Ņ€Ņ–Đ˛ĐĩĐŊҌ JSON ҂ҖĐģа, ŅĐēĐĩ Ви ĐžŅ‡Ņ–ĐēŅƒŅ”Ņ‚Đĩ, Ņ” JSON `ĐŧĐ°ŅĐ¸Đ˛ĐžĐŧ` (҃ Python — `list`), Ви ĐŧĐžĐļĐĩŅ‚Đĩ ĐžĐŗĐžĐģĐžŅĐ¸Ņ‚Đ¸ Ņ‚Đ¸Đŋ ҃ ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂ҀҖ Ņ„ŅƒĐŊĐē҆Җҗ, ŅĐē Ņ– в ĐŧОдĐĩĐģŅŅ… Pydantic: + +```Python +images: List[Image] +``` +айО в Python 3.9 Ņ– Đ˛Đ¸Ņ‰Đĩ: + +```Python +images: list[Image] +``` + +ĐŊаĐŋŅ€Đ¸ĐēĐģад: + +{* ../../docs_src/body_nested_models/tutorial008_py39.py hl[13] *} + +## ĐŸŅ–Đ´Ņ‚Ņ€Đ¸ĐŧĐēа в Ņ€ĐĩдаĐēŅ‚ĐžŅ€Ņ– Đ˛ŅŅŽĐ´Đ¸ + +Ви ĐžŅ‚Ņ€Đ¸ĐŧĐ°Ņ”Ņ‚Đĩ ĐŋŅ–Đ´Ņ‚Ņ€Đ¸ĐŧĐē҃ в Ņ€ĐĩдаĐēŅ‚ĐžŅ€Ņ– Đ˛ŅŅŽĐ´Đ¸. + +ĐĐ°Đ˛Ņ–Ņ‚ŅŒ Đ´ĐģŅ ĐĩĐģĐĩĐŧĐĩĐŊŅ‚Ņ–Đ˛ ҃ ҁĐŋĐ¸ŅĐēĐ°Ņ…: + + + +Ви ĐŊĐĩ СĐŧĐžĐŗĐģи Đą ĐžŅ‚Ņ€Đ¸ĐŧĐ°Ņ‚Đ¸ Ņ‚Đ°Đē҃ ĐŋŅ–Đ´Ņ‚Ņ€Đ¸ĐŧĐē҃ в Ņ€ĐĩдаĐēŅ‚ĐžŅ€Ņ–, ŅĐēйи ĐŋŅ€Đ°Ņ†ŅŽĐ˛Đ°Đģи ĐŊаĐŋŅ€ŅĐŧ҃ ĐˇŅ– `dict`, а ĐŊĐĩ С ĐŧОдĐĩĐģŅĐŧи Pydantic. + +АĐģĐĩ ВаĐŧ ĐŊĐĩ ĐŋĐžŅ‚Ņ€Ņ–ĐąĐŊĐž Ņ‚ŅƒŅ€ĐąŅƒĐ˛Đ°Ņ‚Đ¸ŅŅ ĐŋŅ€Đž ҆Đĩ: Đ˛Ņ…Ņ–Đ´ĐŊŅ– dict'и Đ°Đ˛Ņ‚ĐžĐŧĐ°Ņ‚Đ¸Ņ‡ĐŊĐž ĐēĐžĐŊвĐĩŅ€Ņ‚ŅƒŅŽŅ‚ŅŒŅŅ, а Đ˛Đ¸Ņ…Ņ–Đ´ĐŊŅ– даĐŊŅ– Đ°Đ˛Ņ‚ĐžĐŧĐ°Ņ‚Đ¸Ņ‡ĐŊĐž ĐŋĐĩŅ€ĐĩŅ‚Đ˛ĐžŅ€ŅŽŅŽŅ‚ŅŒŅŅ в JSON. + +## ĐĸŅ–Đģа С Đ´ĐžĐ˛Ņ–ĐģҌĐŊиĐŧи `dict` + +Ви Ņ‚Đ°ĐēĐžĐļ ĐŧĐžĐļĐĩŅ‚Đĩ ĐžĐŗĐžĐģĐžŅĐ¸Ņ‚Đ¸ ҂ҖĐģĐž ŅĐē `dict` С ĐēĐģŅŽŅ‡Đ°Đŧи ОдĐŊĐžĐŗĐž Ņ‚Đ¸Đŋ҃ Ņ‚Đ° СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅĐŧи Ņ–ĐŊŅˆĐžĐŗĐž Ņ‚Đ¸Đŋ҃. + +ĐĻĐĩ ĐēĐžŅ€Đ¸ŅĐŊĐž, ŅĐēŅ‰Đž Ви ĐŊĐĩ СĐŊĐ°Ņ”Ņ‚Đĩ ĐŊаĐŋĐĩŅ€ĐĩĐ´, ŅĐēŅ– Ņ–ĐŧĐĩĐŊа ĐŋĐžĐģŅ–Đ˛ ĐąŅƒĐ´ŅƒŅ‚ŅŒ Đ´Ņ–ĐšŅĐŊиĐŧи (ŅĐē ҃ виĐŋадĐē҃ С ĐŧОдĐĩĐģŅĐŧи Pydantic). + +ĐĻĐĩ ĐąŅƒĐ´Đĩ ĐēĐžŅ€Đ¸ŅĐŊĐž, ŅĐēŅ‰Đž Ви Ņ…ĐžŅ‡ĐĩŅ‚Đĩ ĐŋŅ€Đ¸ĐšĐŧĐ°Ņ‚Đ¸ ĐēĐģŅŽŅ‡Ņ–, ŅĐēŅ– СаСдаĐģĐĩĐŗŅ–Đ´ŅŒ ĐŊĐĩĐ˛Ņ–Đ´ĐžĐŧŅ–. + +--- + +ĐĻĐĩ Ņ‚Đ°ĐēĐžĐļ ĐˇŅ€ŅƒŅ‡ĐŊĐž, ŅĐēŅ‰Đž Ви Ņ…ĐžŅ‡ĐĩŅ‚Đĩ ĐŧĐ°Ņ‚Đ¸ ĐēĐģŅŽŅ‡Ņ– Ņ–ĐŊŅˆĐžĐŗĐž Ņ‚Đ¸Đŋ҃ (ĐŊаĐŋŅ€Đ¸ĐēĐģад, `int`). + +ĐžŅŅŒ Ņ‰Đž Đŧи Ņ€ĐžĐˇĐŗĐģŅĐŊĐĩĐŧĐž даĐģŅ–. + +ĐŖ Ņ†ŅŒĐžĐŧ҃ виĐŋадĐē҃ Ви ĐŧĐžĐļĐĩŅ‚Đĩ ĐŋŅ€Đ¸ĐšĐŧĐ°Ņ‚Đ¸ ĐąŅƒĐ´ŅŒ-ŅĐēиК `dict`, ŅĐēŅ‰Đž ĐšĐžĐŗĐž ĐēĐģŅŽŅ‡Ņ– — ҆Đĩ `int`, а СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ — `float`: + +{* ../../docs_src/body_nested_models/tutorial009_py39.py hl[7] *} + +/// tip | ĐŸĐžŅ€Đ°Đ´Đ° + +ĐœĐ°ĐšŅ‚Đĩ ĐŊа ŅƒĐ˛Đ°ĐˇŅ–, Ņ‰Đž в JSON ҂ҖĐģŅ– ĐēĐģŅŽŅ‡Ņ– ĐŧĐžĐļŅƒŅ‚ŅŒ ĐąŅƒŅ‚Đ¸ ĐģĐ¸ŅˆĐĩ Ņ€ŅĐ´ĐēаĐŧи (`str`). + +АĐģĐĩ Pydantic Đ°Đ˛Ņ‚ĐžĐŧĐ°Ņ‚Đ¸Ņ‡ĐŊĐž ĐēĐžĐŊвĐĩŅ€Ņ‚ŅƒŅ” даĐŊŅ–. + +ĐĻĐĩ ОСĐŊĐ°Ņ‡Đ°Ņ”, Ņ‰Đž ĐŊĐ°Đ˛Ņ–Ņ‚ŅŒ ŅĐēŅ‰Đž ĐēĐģŅ–Ņ”ĐŊŅ‚Đ¸ Đ˛Đ°ŅˆĐžĐŗĐž API ĐŊĐ°Đ´ŅĐ¸ĐģĐ°Ņ‚Đ¸ĐŧŅƒŅ‚ŅŒ ĐēĐģŅŽŅ‡Ņ– ҃ Đ˛Đ¸ĐŗĐģŅĐ´Ņ– Ņ€ŅĐ´ĐēŅ–Đ˛, ŅĐēŅ‰Đž вОĐŊи ĐŧŅ–ŅŅ‚ŅŅ‚ŅŒ ҆ҖĐģŅ– Ņ‡Đ¸ŅĐģа, Pydantic ĐēĐžĐŊвĐĩŅ€Ņ‚ŅƒŅ” Ņ—Ņ… Ņ– ĐŋŅ€ĐžĐ˛ĐĩĐ´Đĩ ваĐģŅ–Đ´Đ°Ņ†Ņ–ŅŽ. + +ĐĸĐžĐąŅ‚Đž `dict`, ŅĐēиК Ви ĐžŅ‚Ņ€Đ¸ĐŧĐ°Ņ”Ņ‚Đĩ ŅĐē `weights`, ĐŧĐ°Ņ‚Đ¸ĐŧĐĩ ĐēĐģŅŽŅ‡Ņ– Ņ‚Đ¸Đŋ҃ `int` Ņ‚Đ° СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ Ņ‚Đ¸Đŋ҃ `float`. + +/// + +## ĐŸŅ–Đ´ŅŅƒĐŧĐžĐē + +З **FastAPI** Ви ĐŧĐ°Ņ”Ņ‚Đĩ ĐŧаĐēŅĐ¸ĐŧаĐģҌĐŊ҃ ĐŗĐŊŅƒŅ‡ĐēŅ–ŅŅ‚ŅŒ ĐˇĐ°Đ˛Đ´ŅĐēи ĐŧОдĐĩĐģŅĐŧ Pydantic, СйĐĩŅ€Ņ–ĐŗĐ°ŅŽŅ‡Đ¸ ĐŋŅ€Đ¸ Ņ†ŅŒĐžĐŧ҃ ĐēОд ĐŋŅ€ĐžŅŅ‚Đ¸Đŧ, ĐēĐžŅ€ĐžŅ‚ĐēиĐŧ Ņ‚Đ° ĐĩĐģĐĩĐŗĐ°ĐŊŅ‚ĐŊиĐŧ. + +А Ņ‚Đ°ĐēĐžĐļ ĐžŅ‚Ņ€Đ¸ĐŧŅƒŅ”Ņ‚Đĩ Đ˛ŅŅ– ĐŋĐĩŅ€ĐĩĐ˛Đ°ĐŗĐ¸: + +* ĐŸŅ–Đ´Ņ‚Ņ€Đ¸ĐŧĐēа в Ņ€ĐĩдаĐēŅ‚ĐžŅ€Ņ– (Đ°Đ˛Ņ‚ĐžĐ´ĐžĐŋОвĐŊĐĩĐŊĐŊŅ Đ˛ŅŅŽĐ´Đ¸!) +* КоĐŊвĐĩŅ€Ņ‚Đ°Ņ†Ņ–Ņ даĐŊĐ¸Ņ… (ĐŋĐ°Ņ€ŅĐ¸ĐŊĐŗ/ҁĐĩŅ€Đ¸Đ°ĐģŅ–ĐˇĐ°Ņ†Ņ–Ņ) +* ВаĐģŅ–Đ´Đ°Ņ†Ņ–Ņ даĐŊĐ¸Ņ… +* ДоĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Ņ–Ņ ҁ҅ĐĩĐŧ +* ĐĐ˛Ņ‚ĐžĐŧĐ°Ņ‚Đ¸Ņ‡ĐŊĐĩ ŅŅ‚Đ˛ĐžŅ€ĐĩĐŊĐŊŅ Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Ņ–Ņ— diff --git a/docs/uk/docs/tutorial/body-updates.md b/docs/uk/docs/tutorial/body-updates.md new file mode 100644 index 000000000..e78b5a5bf --- /dev/null +++ b/docs/uk/docs/tutorial/body-updates.md @@ -0,0 +1,116 @@ +# ĐĸŅ–ĐģĐž – ОĐŊОвĐģĐĩĐŊĐŊŅ + +## ОĐŊОвĐģĐĩĐŊĐŊŅ С виĐēĐžŅ€Đ¸ŅŅ‚Đ°ĐŊĐŊŅĐŧ `PUT` + +ЊОй ĐžĐŊĐžĐ˛Đ¸Ņ‚Đ¸ ĐĩĐģĐĩĐŧĐĩĐŊŅ‚, Ви ĐŧĐžĐļĐĩŅ‚Đĩ виĐēĐžŅ€Đ¸ŅŅ‚Đ°Ņ‚Đ¸ HTTP `PUT` ĐžĐŋĐĩŅ€Đ°Ņ†Ņ–ŅŽ. + +Ви ĐŧĐžĐļĐĩŅ‚Đĩ виĐēĐžŅ€Đ¸ŅŅ‚Đ°Ņ‚Đ¸ `jsonable_encoder`, Ņ‰ĐžĐą ĐŋĐĩŅ€ĐĩŅ‚Đ˛ĐžŅ€Đ¸Ņ‚Đ¸ Đ˛Ņ…Ņ–Đ´ĐŊŅ– даĐŊŅ– ĐŊа Ņ‚Đ°ĐēŅ–, ŅĐēŅ– ĐŧĐžĐļĐŊа СйĐĩŅ€Ņ–ĐŗĐ°Ņ‚Đ¸ ŅĐē JSON (ĐŊаĐŋŅ€Đ¸ĐēĐģад, ҃ NoSQL ĐąĐ°ĐˇŅ– даĐŊĐ¸Ņ…). НаĐŋŅ€Đ¸ĐēĐģад, ĐŋĐĩŅ€ĐĩŅ‚Đ˛ĐžŅ€ŅŽŅŽŅ‡Đ¸ `datetime` ҃ `str`. + +{* ../../docs_src/body_updates/tutorial001_py310.py hl[28:33] *} + +`PUT` виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅ”Ņ‚ŅŒŅŅ Đ´ĐģŅ ĐžŅ‚Ņ€Đ¸ĐŧаĐŊĐŊŅ даĐŊĐ¸Ņ…, ŅĐēŅ– ĐŧĐ°ŅŽŅ‚ŅŒ СаĐŧŅ–ĐŊĐ¸Ņ‚Đ¸ Ņ‡Đ¸ĐŊĐŊŅ– даĐŊŅ–. + +### ПоĐŋĐĩŅ€ĐĩĐ´ĐļĐĩĐŊĐŊŅ ĐŋŅ€Đž СаĐŧŅ–ĐŊ҃ + +ĐĻĐĩ ОСĐŊĐ°Ņ‡Đ°Ņ”, Ņ‰Đž ŅĐēŅ‰Đž Ви Ņ…ĐžŅ‡ĐĩŅ‚Đĩ ĐžĐŊĐžĐ˛Đ¸Ņ‚Đ¸ ĐĩĐģĐĩĐŧĐĩĐŊŅ‚ `bar`, виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅŽŅ‡Đ¸ `PUT` С ҂ҖĐģĐžĐŧ: + +```Python +{ + "name": "Barz", + "price": 3, + "description": None, +} +``` + +ĐžŅĐēŅ–ĐģҌĐēи Đ˛Ņ–ĐŊ ĐŊĐĩ ĐŧŅ–ŅŅ‚Đ¸Ņ‚ŅŒ вĐļĐĩ СйĐĩŅ€ĐĩĐļĐĩĐŊĐžĐŗĐž Đ°Ņ‚Ņ€Đ¸ĐąŅƒŅ‚Đ° `"tax": 20.2`, ĐŧОдĐĩĐģҌ ввĐĩĐ´ĐĩĐŊĐŊŅ ĐŋŅ€Đ¸ĐšĐŧĐĩ СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ Са СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ `"tax": 10.5`. + +І даĐŊŅ– ĐąŅƒĐ´ŅƒŅ‚ŅŒ СйĐĩŅ€ĐĩĐļĐĩĐŊŅ– С Ņ†Đ¸Đŧ "ĐŊОвиĐŧ" СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅĐŧ `tax` = `10.5`. + +## Đ§Đ°ŅŅ‚ĐēĐžĐ˛Ņ– ĐžĐŊОвĐģĐĩĐŊĐŊŅ С `PATCH` + +Ви Ņ‚Đ°ĐēĐžĐļ ĐŧĐžĐļĐĩŅ‚Đĩ виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ ĐžĐŋĐĩŅ€Đ°Ņ†Ņ–ŅŽ HTTP `PATCH` Đ´ĐģŅ *Ņ‡Đ°ŅŅ‚ĐēĐžĐ˛ĐžĐŗĐž* ĐžĐŊОвĐģĐĩĐŊĐŊŅ даĐŊĐ¸Ņ…. + +ĐĻĐĩ ОСĐŊĐ°Ņ‡Đ°Ņ”, Ņ‰Đž Ви ĐŧĐžĐļĐĩŅ‚Đĩ ĐŊĐ°Đ´Ņ–ŅĐģĐ°Ņ‚Đ¸ ĐģĐ¸ŅˆĐĩ ҂Җ даĐŊŅ–, ŅĐēŅ– Ņ…ĐžŅ‡ĐĩŅ‚Đĩ ĐžĐŊĐžĐ˛Đ¸Ņ‚Đ¸, СаĐģĐ¸ŅˆĐ°ŅŽŅ‡Đ¸ Ņ–ĐŊŅˆŅ– ĐąĐĩС СĐŧŅ–ĐŊ. + +/// note | ĐŸŅ€Đ¸ĐŧŅ–Ņ‚Đēа + +`PATCH` ĐŧĐĩĐŊ҈ Đ˛Ņ–Đ´ĐžĐŧиК Ņ– Ņ€Ņ–Đ´ŅˆĐĩ виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅ”Ņ‚ŅŒŅŅ, ĐŊŅ–Đļ `PUT`. + +І ĐąĐ°ĐŗĐ°Ņ‚Đž ĐēĐžĐŧаĐŊĐ´ виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅŽŅ‚ŅŒ ĐģĐ¸ŅˆĐĩ `PUT`, ĐŊĐ°Đ˛Ņ–Ņ‚ŅŒ Đ´ĐģŅ Ņ‡Đ°ŅŅ‚ĐēĐžĐ˛Đ¸Ņ… ĐžĐŊОвĐģĐĩĐŊҌ. + +Ви **Đ˛Ņ–ĐģҌĐŊŅ–** виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ Ņ—Ņ… Ņ‚Đ°Đē, ŅĐē Ņ…ĐžŅ‡ĐĩŅ‚Đĩ, **FastAPI** ĐŊĐĩ ĐŊаĐēĐģĐ°Đ´Đ°Ņ” ОйĐŧĐĩĐļĐĩĐŊҌ. + +АĐģĐĩ ҆ĐĩĐš ĐŋĐžŅŅ–ĐąĐŊиĐē ĐŋĐžĐēĐ°ĐˇŅƒŅ” ВаĐŧ ĐąŅ–ĐģҌ҈-ĐŧĐĩĐŊ҈ ŅĐē Ņ—Ņ… ĐˇĐ°Đ´ŅƒĐŧаĐŊĐž виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸. + +/// + +### ВиĐēĐžŅ€Đ¸ŅŅ‚Đ°ĐŊĐŊŅ ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ° `exclude_unset` ҃ Pydantic + +Đ¯ĐēŅ‰Đž Ви Ņ…ĐžŅ‡ĐĩŅ‚Đĩ ĐžŅ‚Ņ€Đ¸ĐŧĐ°Ņ‚Đ¸ Ņ‡Đ°ŅŅ‚ĐēĐžĐ˛Ņ– ĐžĐŊОвĐģĐĩĐŊĐŊŅ, Đ´ŅƒĐļĐĩ ĐˇŅ€ŅƒŅ‡ĐŊĐž виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ `exclude_unset` ҃ ĐŧĐĩŅ‚ĐžĐ´Ņ– `.model_dump()` ĐŧОдĐĩĐģŅ– Pydantic. + +НаĐŋŅ€Đ¸ĐēĐģад: `item.model_dump(exclude_unset=True)`. + +/// info | ІĐŊŅ„ĐžŅ€ĐŧĐ°Ņ†Ņ–Ņ + +ĐŖ Pydantic v1 ҆ĐĩĐš ĐŧĐĩŅ‚ĐžĐ´ ĐŊĐ°ĐˇĐ¸Đ˛Đ°Đ˛ŅŅ `.dict()`, Đ˛Ņ–ĐŊ ĐąŅƒĐ˛ ĐˇĐ°ŅŅ‚Đ°Ņ€Ņ–ĐģиК (аĐģĐĩ Đ˛ŅĐĩ ҉Đĩ ĐŋŅ–Đ´Ņ‚Ņ€Đ¸ĐŧŅƒŅ”Ņ‚ŅŒŅŅ) ҃ Pydantic v2, Ņ– ĐąŅƒĐ˛ ĐŋĐĩŅ€ĐĩĐšĐŧĐĩĐŊОваĐŊиК ҃ `.model_dump()`. + +ĐŸŅ€Đ¸ĐēĐģади Ņ‚ŅƒŅ‚ виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅŽŅ‚ŅŒ `.dict()` Đ´ĐģŅ ҁ҃ĐŧҖҁĐŊĐžŅŅ‚Ņ– С Pydantic v1, аĐģĐĩ ВаĐŧ ҁĐģŅ–Đ´ виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ `.model_dump()`, ŅĐēŅ‰Đž ĐŧĐžĐļĐĩŅ‚Đĩ виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ Pydantic v2. + +/// + +ĐĻĐĩ ŅŅ‚Đ˛ĐžŅ€Đ¸Ņ‚ŅŒ `dict` ĐģĐ¸ŅˆĐĩ С Ņ‚Đ¸Đŧи даĐŊиĐŧи, ŅĐēŅ– ĐąŅƒĐģи ŅĐ˛ĐŊĐž Đ˛ŅŅ‚Đ°ĐŊОвĐģĐĩĐŊŅ– ĐŋŅ–Đ´ Ņ‡Đ°Ņ ŅŅ‚Đ˛ĐžŅ€ĐĩĐŊĐŊŅ ĐŧОдĐĩĐģŅ– `item`, виĐēĐģŅŽŅ‡Đ°ŅŽŅ‡Đ¸ СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ Са СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ. + +ĐĸĐžĐ´Ņ– Ви ĐŧĐžĐļĐĩŅ‚Đĩ виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ ҆Đĩ, Ņ‰ĐžĐą ŅŅ‚Đ˛ĐžŅ€Đ¸Ņ‚Đ¸ `dict` ĐģĐ¸ŅˆĐĩ С даĐŊиĐŧи, ŅĐēŅ– ĐąŅƒĐģи Đ˛ŅŅ‚Đ°ĐŊОвĐģĐĩĐŊŅ– (ĐŊĐ°Đ´Ņ–ŅĐģаĐŊŅ– ҃ СаĐŋĐ¸Ņ‚Ņ–), ĐŋŅ€ĐžĐŋ҃ҁĐēĐ°ŅŽŅ‡Đ¸ СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ Са СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ: + +{* ../../docs_src/body_updates/tutorial002_py310.py hl[32] *} + +### ВиĐēĐžŅ€Đ¸ŅŅ‚Đ°ĐŊĐŊŅ ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ° `update` ҃ Pydantic + +ĐĸĐĩĐŋĐĩŅ€ Ви ĐŧĐžĐļĐĩŅ‚Đĩ ŅŅ‚Đ˛ĐžŅ€Đ¸Ņ‚Đ¸ ĐēĐžĐŋŅ–ŅŽ ĐŊĐ°ŅĐ˛ĐŊĐžŅ— ĐŧОдĐĩĐģŅ– Са Đ´ĐžĐŋĐžĐŧĐžĐŗĐžŅŽ `.model_copy()`, Ņ– ĐŋĐĩŅ€ĐĩĐ´Đ°Ņ‚Đ¸ ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ `update` С `dict` , ŅĐēиК ĐŧŅ–ŅŅ‚Đ¸Ņ‚ŅŒ даĐŊŅ– Đ´ĐģŅ ĐžĐŊОвĐģĐĩĐŊĐŊŅ. + +/// info | ІĐŊŅ„ĐžŅ€ĐŧĐ°Ņ†Ņ–Ņ + +ĐŖ Pydantic v1 ĐŧĐĩŅ‚ĐžĐ´ ĐŊĐ°ĐˇĐ¸Đ˛Đ°Đ˛ŅŅ `.copy()`, Đ˛Ņ–ĐŊ ĐąŅƒĐ˛ ĐˇĐ°ŅŅ‚Đ°Ņ€Ņ–ĐģиК (аĐģĐĩ Đ˛ŅĐĩ ҉Đĩ ĐŋŅ–Đ´Ņ‚Ņ€Đ¸ĐŧŅƒŅ”Ņ‚ŅŒŅŅ) ҃ Pydantic v2, Ņ– ĐąŅƒĐ˛ ĐŋĐĩŅ€ĐĩĐšĐŧĐĩĐŊОваĐŊиК ҃ `.model_copy()`. + +ĐŸŅ€Đ¸ĐēĐģади Ņ‚ŅƒŅ‚ виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅŽŅ‚ŅŒ `.copy()` Đ´ĐģŅ ҁ҃ĐŧҖҁĐŊĐžŅŅ‚Ņ– С Pydantic v1, аĐģĐĩ ŅĐēŅ‰Đž Ви ĐŧĐžĐļĐĩŅ‚Đĩ виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ Pydantic v2 — ВаĐŧ ҁĐģŅ–Đ´ виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ `.model_copy()` СаĐŧŅ–ŅŅ‚ŅŒ Ņ†ŅŒĐžĐŗĐž. + +/// + +НаĐŋŅ€Đ¸ĐēĐģад: `stored_item_model.model_copy(update=update_data)`: + +{* ../../docs_src/body_updates/tutorial002_py310.py hl[33] *} + +### ĐŸŅ–Đ´ŅŅƒĐŧĐžĐē Ņ‡Đ°ŅŅ‚ĐēĐžĐ˛Đ¸Ņ… ĐžĐŊОвĐģĐĩĐŊҌ + +ĐŖ ĐŋŅ–Đ´ŅŅƒĐŧĐē҃, Ņ‰ĐžĐą ĐˇĐ°ŅŅ‚ĐžŅŅƒĐ˛Đ°Ņ‚Đ¸ Ņ‡Đ°ŅŅ‚ĐēĐžĐ˛Ņ– ĐžĐŊОвĐģĐĩĐŊĐŊŅ, Ви: + +* (ОĐŋŅ†Ņ–ĐžĐŊаĐģҌĐŊĐž) виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅ”Ņ‚Đĩ `PATCH` СаĐŧŅ–ŅŅ‚ŅŒ `PUT`. +* ĐžŅ‚Ņ€Đ¸ĐŧŅƒŅ”Ņ‚Đĩ СйĐĩŅ€ĐĩĐļĐĩĐŊŅ– даĐŊŅ–. +* ПоĐŧŅ–Ņ‰Đ°Ņ”Ņ‚Đĩ ҆Җ даĐŊŅ– в ĐŧОдĐĩĐģҌ Pydantic. +* ГĐĩĐŊĐĩŅ€ŅƒŅ”Ņ‚Đĩ `dict` ĐąĐĩС СĐŊĐ°Ņ‡ĐĩĐŊҌ Са СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ С ĐŧОдĐĩĐģŅ– ввĐĩĐ´ĐĩĐŊĐŊŅ (виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅŽŅ‡Đ¸ `exclude_unset`). + * ĐĸаĐēиĐŧ Ņ‡Đ¸ĐŊĐžĐŧ Ви ĐžĐŊĐžĐ˛Đ¸Ņ‚Đĩ ĐģĐ¸ŅˆĐĩ ҂Җ СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ, ŅĐēŅ– ĐąŅƒĐģи ŅĐ˛ĐŊĐž СадаĐŊŅ– ĐēĐžŅ€Đ¸ŅŅ‚ŅƒĐ˛Đ°Ņ‡ĐĩĐŧ, СаĐŧŅ–ŅŅ‚ŅŒ Ņ‚ĐžĐŗĐž, Ņ‰ĐžĐą ĐŋĐĩŅ€ĐĩСаĐŋĐ¸ŅŅƒĐ˛Đ°Ņ‚Đ¸ вĐļĐĩ СйĐĩŅ€ĐĩĐļĐĩĐŊŅ– СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅĐŧи Са СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ С Đ˛Đ°ŅˆĐžŅ— ĐŧОдĐĩĐģŅ–. +* ĐĄŅ‚Đ˛ĐžŅ€ŅŽŅ”Ņ‚Đĩ ĐēĐžĐŋŅ–ŅŽ СйĐĩŅ€ĐĩĐļĐĩĐŊĐžŅ— ĐŧОдĐĩĐģŅ–, ĐžĐŊОвĐģŅŽŅŽŅ‡Đ¸ Ņ—Ņ— Đ°Ņ‚Ņ€Đ¸ĐąŅƒŅ‚Đ¸ ĐžŅ‚Ņ€Đ¸ĐŧаĐŊиĐŧи Ņ‡Đ°ŅŅ‚ĐēОвиĐŧи ĐžĐŊОвĐģĐĩĐŊĐŊŅĐŧи (виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅŽŅ‡Đ¸ ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ `update`). +* ПĐĩŅ€ĐĩŅ‚Đ˛ĐžŅ€ŅŽŅ”Ņ‚Đĩ ҁĐēĐžĐŋŅ–ĐšĐžĐ˛Đ°ĐŊ҃ ĐŧОдĐĩĐģҌ ĐŊа Ņ‰ĐžŅŅŒ, Ņ‰Đž ĐŧĐžĐļĐŊа СйĐĩŅ€ĐĩĐŗŅ‚Đ¸ ҃ Đ˛Đ°ŅˆŅƒ БД (ĐŊаĐŋŅ€Đ¸ĐēĐģад, виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅŽŅ‡Đ¸ `jsonable_encoder`). + * ĐĻĐĩ ĐŧĐžĐļĐŊа ĐŋĐžŅ€Ņ–Đ˛ĐŊŅŅ‚Đ¸ С ĐŋĐžĐ˛Ņ‚ĐžŅ€ĐŊиĐŧ виĐēĐžŅ€Đ¸ŅŅ‚Đ°ĐŊĐŊŅĐŧ ĐŧĐĩŅ‚ĐžĐ´Ņƒ `.model_dump()` ĐŧОдĐĩĐģŅ–, аĐģĐĩ ҆Đĩ ĐŗĐ°Ņ€Đ°ĐŊŅ‚ŅƒŅ” (Ņ– ĐŋĐĩŅ€ĐĩŅ‚Đ˛ĐžŅ€ŅŽŅ”) СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ ҃ Ņ‚Đ¸Đŋи даĐŊĐ¸Ņ…, ŅĐēŅ– ĐŧĐžĐļĐŊа ĐŋĐĩŅ€ĐĩŅ‚Đ˛ĐžŅ€Đ¸Ņ‚Đ¸ ĐŊа JSON, ĐŊаĐŋŅ€Đ¸ĐēĐģад, `datetime` ĐŊа `str`. +* ЗбĐĩŅ€Ņ–ĐŗĐ°Ņ”Ņ‚Đĩ даĐŊŅ– ҃ Đ˛Đ°ŅˆŅƒ БД. +* ПовĐĩŅ€Ņ‚Đ°Ņ”Ņ‚Đĩ ĐžĐŊОвĐģĐĩĐŊ҃ ĐŧОдĐĩĐģҌ. + +{* ../../docs_src/body_updates/tutorial002_py310.py hl[28:35] *} + +/// tip | ĐŸĐžŅ€Đ°Đ´Đ° + +ĐĐ°ŅĐŋŅ€Đ°Đ˛Đ´Ņ– Ви ĐŧĐžĐļĐĩŅ‚Đĩ виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ Ņ†ŅŽ ŅĐ°Đŧ҃ Ņ‚ĐĩŅ…ĐŊŅ–Đē҃ Ņ– С ĐžĐŋĐĩŅ€Đ°Ņ†Ņ–Ņ”ŅŽ HTTP `PUT`. + +АĐģĐĩ ĐŋŅ€Đ¸ĐēĐģад Ņ‚ŅƒŅ‚ виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅ” `PATCH`, Ņ‚ĐžĐŧ҃ Ņ‰Đž Đ˛Ņ–ĐŊ ĐąŅƒĐ˛ ŅŅ‚Đ˛ĐžŅ€ĐĩĐŊиК ŅĐ°ĐŧĐĩ Đ´ĐģŅ Ņ‚Đ°ĐēĐ¸Ņ… виĐŋадĐēŅ–Đ˛. + +/// + +/// note | ĐŸŅ€Đ¸ĐŧŅ–Ņ‚Đēа + +ЗвĐĩŅ€ĐŊŅ–Ņ‚ŅŒ ŅƒĐ˛Đ°ĐŗŅƒ, Ņ‰Đž ĐŧОдĐĩĐģҌ СаĐŋĐ¸Ņ‚Ņƒ Đ˛ŅĐĩ ҉Đĩ ĐŋŅ€ĐžŅ…ĐžĐ´Đ¸Ņ‚ŅŒ ваĐģŅ–Đ´Đ°Ņ†Ņ–ŅŽ. + +ĐĸĐžĐļ, ŅĐēŅ‰Đž Ви Ņ…ĐžŅ‡ĐĩŅ‚Đĩ ĐžŅ‚Ņ€Đ¸ĐŧŅƒĐ˛Đ°Ņ‚Đ¸ Ņ‡Đ°ŅŅ‚ĐēĐžĐ˛Ņ– ĐžĐŊОвĐģĐĩĐŊĐŊŅ, ŅĐēŅ– ĐŧĐžĐļŅƒŅ‚ŅŒ ĐŊĐĩ ĐŧŅ–ŅŅ‚Đ¸Ņ‚Đ¸ ĐļОдĐŊĐžĐŗĐž Đ°Ņ‚Ņ€Đ¸ĐąŅƒŅ‚Đ°, ВаĐŧ ĐŋĐžŅ‚Ņ€Ņ–ĐąĐŊĐž ĐŧĐ°Ņ‚Đ¸ ĐŧОдĐĩĐģҌ, Đ´Đĩ Đ˛ŅŅ– Đ°Ņ‚Ņ€Đ¸ĐąŅƒŅ‚Đ¸ ĐŋОСĐŊĐ°Ņ‡ĐĩĐŊŅ– ŅĐē ĐŊĐĩĐžĐąĐžĐ˛â€™ŅĐˇĐēĐžĐ˛Ņ– (ĐˇŅ– СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅĐŧи Са СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ айО `None`). + +ЊОй Ņ€ĐžĐˇŅ€Ņ–ĐˇĐŊŅŅ‚Đ¸ ĐŧОдĐĩĐģŅ– С ŅƒŅŅ–Đŧа ĐŊĐĩĐžĐąĐžĐ˛â€™ŅĐˇĐēОвиĐŧи СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅĐŧи Đ´ĐģŅ **ĐžĐŊОвĐģĐĩĐŊĐŊŅ** Ņ– ĐŧОдĐĩĐģŅ– С ĐžĐąĐžĐ˛â€™ŅĐˇĐēОвиĐŧи СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅĐŧи Đ´ĐģŅ **ŅŅ‚Đ˛ĐžŅ€ĐĩĐŊĐŊŅ**, Ви ĐŧĐžĐļĐĩŅ‚Đĩ ҁĐēĐžŅ€Đ¸ŅŅ‚Đ°Ņ‚Đ¸ŅŅŒ Ņ–Đ´ĐĩŅĐŧи, ĐžĐŋĐ¸ŅĐ°ĐŊиĐŧи ҃ [Đ”ĐžĐ´Đ°Ņ‚ĐēĐžĐ˛Ņ– ĐŧОдĐĩĐģŅ–](extra-models.md){.internal-link target=_blank}. + +/// diff --git a/docs/uk/docs/tutorial/cookie-param-models.md b/docs/uk/docs/tutorial/cookie-param-models.md new file mode 100644 index 000000000..f070b6ac8 --- /dev/null +++ b/docs/uk/docs/tutorial/cookie-param-models.md @@ -0,0 +1,76 @@ +# МодĐĩĐģŅ– Đ´ĐģŅ Cookie-ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Ņ–Đ˛ + +Đ¯ĐēŅ‰Đž ҃ Đ’Đ°Ņ Ņ” ĐŗŅ€ŅƒĐŋа **cookies** ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Ņ–Đ˛, ŅĐēŅ– ĐŋОв'ŅĐˇĐ°ĐŊŅ– ĐŧŅ–Đļ ŅĐžĐąĐžŅŽ, Ви ĐŧĐžĐļĐĩŅ‚Đĩ ŅŅ‚Đ˛ĐžŅ€Đ¸Ņ‚Đ¸ **Pydantic-ĐŧОдĐĩĐģҌ**, Ņ‰ĐžĐą ĐžĐŗĐžĐģĐžŅĐ¸Ņ‚Đ¸ Ņ—Ņ…. đŸĒ + +ĐĻĐĩ дОСвОĐģĐ¸Ņ‚ŅŒ ВаĐŧ ĐŋĐžĐ˛Ņ‚ĐžŅ€ĐŊĐž **виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ ĐŧОдĐĩĐģҌ** ҃ **Ņ€Ņ–ĐˇĐŊĐ¸Ņ… ĐŧŅ–ŅŅ†ŅŅ…**, а Ņ‚Đ°ĐēĐžĐļ ĐžĐŗĐžĐģĐžŅĐ¸Ņ‚Đ¸ ваĐģŅ–Đ´Đ°Ņ†Ņ–ŅŽ Ņ‚Đ° ĐŧĐĩŅ‚Đ°Đ´Đ°ĐŊŅ– Đ´ĐģŅ Đ˛ŅŅ–Ņ… ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Ņ–Đ˛ ОдĐŊĐžŅ‡Đ°ŅĐŊĐž. 😎 + +/// note | ĐĐžŅ‚Đ°Ņ‚Đēи + +ĐĻĐĩ ĐŋŅ–Đ´Ņ‚Ņ€Đ¸ĐŧŅƒŅ”Ņ‚ŅŒŅŅ С вĐĩҀҁҖҗ FastAPI `0.115.0`. 🤓 + +/// + +/// tip | ĐŸĐžŅ€Đ°Đ´Đ° + +ĐĻŅ Đļ Ņ‚ĐĩŅ…ĐŊŅ–Đēа ĐˇĐ°ŅŅ‚ĐžŅĐžĐ˛ŅƒŅ”Ņ‚ŅŒŅŅ Đ´Đž `Query`, `Cookie`, Ņ‚Đ° `Header`. 😎 + +/// + +## Cookie С Pydantic-ĐŧОдĐĩĐģĐģŅŽ + +ĐžĐŗĐžĐģĐžŅŅ–Ņ‚ŅŒ **cookie-ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ¸**, ŅĐēŅ– ВаĐŧ ĐŋĐžŅ‚Ņ€Ņ–ĐąĐŊŅ–, ҃ **Pydantic-ĐŧОдĐĩĐģŅ–**, а ĐŋĐžŅ‚Ņ–Đŧ ĐžĐŗĐžĐģĐžŅŅ–Ņ‚ŅŒ ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ ŅĐē `Cookie`: + +{* ../../docs_src/cookie_param_models/tutorial001_an_py310.py hl[9:12,16] *} + +**FastAPI** ĐąŅƒĐ´Đĩ **Đ˛Đ¸Ņ‚ŅĐŗŅƒĐ˛Đ°Ņ‚Đ¸** даĐŊŅ– Đ´ĐģŅ **ĐēĐžĐļĐŊĐžĐŗĐž ĐŋĐžĐģŅ** С **cookie** ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Ņ–Đ˛, ĐžŅ‚Ņ€Đ¸ĐŧаĐŊĐ¸Ņ… ҃ СаĐŋĐ¸Ņ‚Ņ–, Ņ– ĐŋĐĩŅ€ĐĩĐ´Đ°Đ˛Đ°Ņ‚Đ¸ ВаĐŧ Pydantic-ĐŧОдĐĩĐģҌ, ŅĐē҃ Ви виСĐŊĐ°Ņ‡Đ¸Đģи. + +## ПĐĩŅ€ĐĩĐ˛Ņ–Ņ€Đēа ҃ Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Ņ–Ņ— + +Ви ĐŧĐžĐļĐĩŅ‚Đĩ ĐŋĐžĐąĐ°Ņ‡Đ¸Ņ‚Đ¸ виСĐŊĐ°Ņ‡ĐĩĐŊŅ– cookie в Ņ–ĐŊŅ‚ĐĩҀ҄ĐĩĐšŅŅ– Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Ņ–Ņ— Са Đ°Đ´Ņ€ĐĩŅĐžŅŽ `/docs`: + +

+ +
+ +/// info | ІĐŊŅ„ĐžŅ€ĐŧĐ°Ņ†Ņ–Ņ + +ĐœĐ°ĐšŅ‚Đĩ ĐŊа ŅƒĐ˛Đ°ĐˇŅ–, Ņ‰Đž ĐžŅĐēŅ–ĐģҌĐēи **ĐąŅ€Đ°ŅƒĐˇĐĩŅ€Đ¸ ĐžĐąŅ€ĐžĐąĐģŅŅŽŅ‚ŅŒ cookie** ĐžŅĐžĐąĐģивиĐŧ Ņ‡Đ¸ĐŊĐžĐŧ Ņ– "Са ĐģĐ°ŅˆŅ‚ŅƒĐŊĐēаĐŧи", вОĐŊи **ĐŊĐĩ** дОСвОĐģŅŅŽŅ‚ŅŒ **JavaScript** ĐģĐĩĐŗĐēĐž С ĐŊиĐŧи ĐŋŅ€Đ°Ņ†ŅŽĐ˛Đ°Ņ‚Đ¸. + +Đ¯ĐēŅ‰Đž Ви СаКдĐĩŅ‚Đĩ Đ´Đž **Ņ–ĐŊŅ‚ĐĩҀ҄ĐĩĐšŅŅƒ Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Ņ–Ņ— API** Са Đ°Đ´Ņ€ĐĩŅĐžŅŽ `/docs`, Ви СĐŧĐžĐļĐĩŅ‚Đĩ ĐŋĐžĐąĐ°Ņ‡Đ¸Ņ‚Đ¸ **Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Ņ–ŅŽ** Đ´ĐģŅ cookie ҃ Đ’Đ°ŅˆĐ¸Ņ… **ĐžĐŋĐĩŅ€Đ°Ņ†Ņ–ŅŅ… ҈ĐģŅŅ…Ņƒ**. + +АĐģĐĩ ĐŊĐ°Đ˛Ņ–Ņ‚ŅŒ ŅĐēŅ‰Đž Ви СаĐŋОвĐŊĐ¸Ņ‚Đĩ даĐŊŅ– Đš ĐŊĐ°Ņ‚Đ¸ŅĐŊĐĩŅ‚Đĩ "Execute", ĐžŅĐēŅ–ĐģҌĐēи Ņ–ĐŊŅ‚ĐĩҀ҄ĐĩĐšŅ Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Ņ–Ņ— ĐŋŅ€Đ°Ņ†ŅŽŅ” С **JavaScript**, cookie ĐŊĐĩ ĐąŅƒĐ´ŅƒŅ‚ŅŒ Đ˛Ņ–Đ´ĐŋŅ€Đ°Đ˛ĐģĐĩĐŊŅ–, Ņ– Ви ĐŋĐžĐąĐ°Ņ‡Đ¸Ņ‚Đĩ **ĐŋĐžĐŧиĐģĐē҃**, ĐŊŅ–ĐąĐ¸ Ви ĐŊĐĩ ввĐĩĐģи ĐļОдĐŊĐ¸Ņ… СĐŊĐ°Ņ‡ĐĩĐŊҌ. + +/// + +## Đ—Đ°ĐąĐžŅ€ĐžĐŊа Đ´ĐžĐ´Đ°Ņ‚ĐēĐžĐ˛Đ¸Ņ… cookie + +ĐŖ Đ´ĐĩŅĐēĐ¸Ņ… ҁĐŋĐĩŅ†Ņ–Đ°ĐģҌĐŊĐ¸Ņ… виĐŋадĐēĐ°Ņ… (ĐšĐŧĐžĐ˛Ņ–Ņ€ĐŊĐž, ĐŊĐĩ Đ´ŅƒĐļĐĩ ĐŋĐžŅˆĐ¸Ņ€ĐĩĐŊĐ¸Ņ…) Ви ĐŧĐžĐļĐĩŅ‚Đĩ ĐˇĐ°Ņ…ĐžŅ‚Ņ–Ņ‚Đ¸ **ОйĐŧĐĩĐļĐ¸Ņ‚Đ¸** ҁĐŋĐ¸ŅĐžĐē cookie, ŅĐēŅ– Ņ…ĐžŅ‡ĐĩŅ‚Đĩ ĐžŅ‚Ņ€Đ¸ĐŧŅƒĐ˛Đ°Ņ‚Đ¸. + +Đ’Đ°ŅˆĐ° API Ņ‚ĐĩĐŋĐĩŅ€ ĐŧĐ°Ņ” ĐŧĐžĐļĐģĐ¸Đ˛Ņ–ŅŅ‚ŅŒ ĐēĐžĐŊŅ‚Ņ€ĐžĐģŅŽĐ˛Đ°Ņ‚Đ¸ вĐģĐ°ŅĐŊ҃ ĐˇĐŗĐžĐ´Ņƒ ĐŊа cookie. đŸ¤ĒđŸĒ + +Ви ĐŧĐžĐļĐĩŅ‚Đĩ виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ ĐŊаĐģĐ°ŅˆŅ‚ŅƒĐ˛Đ°ĐŊĐŊŅ ĐŧОдĐĩĐģŅ– Pydantic, Ņ‰ĐžĐą `ĐˇĐ°ĐąĐžŅ€ĐžĐŊĐ¸Ņ‚Đ¸` ĐąŅƒĐ´ŅŒ-ŅĐēŅ– `Đ´ĐžĐ´Đ°Ņ‚ĐēĐžĐ˛Ņ–` ĐŋĐžĐģŅ: + +{* ../../docs_src/cookie_param_models/tutorial002_an_py39.py hl[10] *} + +Đ¯ĐēŅ‰Đž ĐēĐģŅ–Ņ”ĐŊŅ‚ ҁĐŋŅ€ĐžĐąŅƒŅ” ĐŊĐ°Đ´Ņ–ŅĐģĐ°Ņ‚Đ¸ ŅĐēŅ–ŅŅŒ **Đ´ĐžĐ´Đ°Ņ‚ĐēĐžĐ˛Ņ– cookie**, Đ˛Ņ–ĐŊ ĐžŅ‚Ņ€Đ¸ĐŧĐ°Ņ” Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´ŅŒ С **ĐŋĐžĐŧиĐģĐēĐžŅŽ**. + +Đ‘Ņ–Đ´ĐŊŅ– йаĐŊĐĩŅ€Đ¸ cookie, ŅĐēŅ– Ņ‚Đ°Đē ŅŅ‚Đ°Ņ€Đ°ĐŊĐŊĐž ĐŊаĐŧĐ°ĐŗĐ°ŅŽŅ‚ŅŒŅŅ ĐžŅ‚Ņ€Đ¸ĐŧĐ°Ņ‚Đ¸ Đ’Đ°ŅˆŅƒ ĐˇĐŗĐžĐ´Ņƒ, Ņ‰ĐžĐą API Ņ—Ņ— Đ˛Ņ–Đ´Ņ…Đ¸ĐģиĐģа. đŸĒ + +НаĐŋŅ€Đ¸ĐēĐģад, ŅĐēŅ‰Đž ĐēĐģŅ–Ņ”ĐŊŅ‚ ҁĐŋŅ€ĐžĐąŅƒŅ” ĐŊĐ°Đ´Ņ–ŅĐģĐ°Ņ‚Đ¸ cookie `santa_tracker` ĐˇŅ– СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅĐŧ `good-list-please`, Đ˛Ņ–ĐŊ ĐžŅ‚Ņ€Đ¸ĐŧĐ°Ņ” Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´ŅŒ С ĐŋĐžĐŧиĐģĐēĐžŅŽ, ŅĐēа ĐŋĐžĐ˛Ņ–Đ´ĐžĐŧĐ¸Ņ‚ŅŒ, Ņ‰Đž cookie `santa_tracker` ĐŊĐĩ дОСвОĐģĐĩĐŊĐž: + +```json +{ + "detail": [ + { + "type": "extra_forbidden", + "loc": ["cookie", "santa_tracker"], + "msg": "Extra inputs are not permitted", + "input": "good-list-please", + } + ] +} +``` + +## ĐŸŅ–Đ´ŅŅƒĐŧĐžĐē + +Ви ĐŧĐžĐļĐĩŅ‚Đĩ виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ **Pydantic-ĐŧОдĐĩĐģŅ–** Đ´ĐģŅ ĐžĐŗĐžĐģĐžŅˆĐĩĐŊĐŊŅ cookie ҃ FastAPI. 😎 diff --git a/docs/uk/docs/tutorial/cors.md b/docs/uk/docs/tutorial/cors.md new file mode 100644 index 000000000..95b204d0f --- /dev/null +++ b/docs/uk/docs/tutorial/cors.md @@ -0,0 +1,89 @@ +# CORS (ОбĐŧŅ–ĐŊ Ņ€ĐĩŅŅƒŅ€ŅĐ°Đŧи ĐŧŅ–Đļ Ņ€Ņ–ĐˇĐŊиĐŧи Đ´ĐļĐĩŅ€ĐĩĐģаĐŧи) + +CORS айО "ОбĐŧŅ–ĐŊ Ņ€ĐĩŅŅƒŅ€ŅĐ°Đŧи ĐŧŅ–Đļ Ņ€Ņ–ĐˇĐŊиĐŧи Đ´ĐļĐĩŅ€ĐĩĐģаĐŧи" Ņ” ŅĐ¸Ņ‚ŅƒĐ°Ņ†Ņ–Ņ, ĐēĐžĐģи Ņ„Ņ€ĐžĐŊŅ‚ĐĩĐŊĐ´, Ņ‰Đž ĐŋŅ€Đ°Ņ†ŅŽŅ” в ĐąŅ€Đ°ŅƒĐˇĐĩҀҖ, ĐŧŅ–ŅŅ‚Đ¸Ņ‚ŅŒ JavaScript-ĐēОд, ŅĐēиК Đ˛ĐˇĐ°Ņ”ĐŧĐžĐ´Ņ–Ņ” С ĐąĐĩĐēĐĩĐŊĐ´ĐžĐŧ, Ņ€ĐžĐˇŅ‚Đ°ŅˆĐžĐ˛Đ°ĐŊиĐŧ в Ņ–ĐŊŅˆĐžĐŧ҃ "Đ´ĐļĐĩŅ€ĐĩĐģŅ–" (origin). + +## ДĐļĐĩŅ€ĐĩĐģĐž (Origin) + +ДĐļĐĩŅ€ĐĩĐģĐž виСĐŊĐ°Ņ‡Đ°Ņ”Ņ‚ŅŒŅŅ ĐēĐžĐŧĐąŅ–ĐŊĐ°Ņ†Ņ–Ņ”ŅŽ ĐŋŅ€ĐžŅ‚ĐžĐēĐžĐģ҃ (`http`, `https`), Đ´ĐžĐŧĐĩĐŊ҃ (`myapp.com`, `localhost`, `localhost.tiangolo.com`), ĐŋĐžŅ€Ņ‚Ņƒ (`80`, `443`, `8080`). + + +НаĐŋŅ€Đ¸ĐēĐģад, Ņ‚Đ°ĐēŅ– Đ°Đ´Ņ€ĐĩŅĐ¸ вваĐļĐ°ŅŽŅ‚ŅŒŅŅ Ņ€Ņ–ĐˇĐŊиĐŧи Đ´ĐļĐĩŅ€ĐĩĐģаĐŧи: + +* `http://localhost` +* `https://localhost` +* `http://localhost:8080` + +ĐĐ°Đ˛Ņ–Ņ‚ŅŒ ŅĐēŅ‰Đž вОĐŊи Đ˛ŅŅ– ĐŧŅ–ŅŅ‚ŅŅ‚ŅŒ `localhost`, вОĐŊи ĐŧĐ°ŅŽŅ‚ŅŒ Ņ€Ņ–ĐˇĐŊŅ– ĐŋŅ€ĐžŅ‚ĐžĐēĐžĐģи айО ĐŋĐžŅ€Ņ‚Đ¸, Ņ‰Đž Ņ€ĐžĐąĐ¸Ņ‚ŅŒ Ņ—Ņ… ĐžĐēŅ€ĐĩĐŧиĐŧи "Đ´ĐļĐĩŅ€ĐĩĐģаĐŧи". + +## ĐšŅ€ĐžĐēи + +ĐŸŅ€Đ¸ĐŋŅƒŅŅ‚Đ¸ĐŧĐž, Ņ‰Đž Đ’Đ°Ņˆ Ņ„Ņ€ĐžĐŊŅ‚ĐĩĐŊĐ´ ĐŋŅ€Đ°Ņ†ŅŽŅ” в ĐąŅ€Đ°ŅƒĐˇĐĩҀҖ ĐŊа `http://localhost:8080`, а ĐšĐžĐŗĐž JavaScript ĐŊаĐŧĐ°ĐŗĐ°Ņ”Ņ‚ŅŒŅŅ Đ˛Ņ–Đ´ĐŋŅ€Đ°Đ˛Đ¸Ņ‚Đ¸ СаĐŋĐ¸Ņ‚ Đ´Đž ĐąĐĩĐēĐĩĐŊĐ´Ņƒ, ŅĐēиК ĐŋŅ€Đ°Ņ†ŅŽŅ” ĐŊа `http://localhost` (ĐžŅĐēŅ–ĐģҌĐēи Đŧи ĐŊĐĩ вĐēĐ°ĐˇŅƒŅ”ĐŧĐž ĐŋĐžŅ€Ņ‚, ĐąŅ€Đ°ŅƒĐˇĐĩŅ€ Са СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ ĐŋŅ€Đ¸Đŋ҃ҁĐēĐ°Ņ” ĐŋĐžŅ€Ņ‚ `80`). + +ĐŸĐžŅ‚Ņ–Đŧ ĐąŅ€Đ°ŅƒĐˇĐĩŅ€ ĐŊĐ°Đ´Ņ–ŅˆĐģĐĩ HTTP-СаĐŋĐ¸Ņ‚ `OPTIONS` Đ´Đž ĐąĐĩĐēĐĩĐŊĐ´Ņƒ ĐŊа ĐŋĐžŅ€Ņ‚Ņƒ `:80`, Ņ– ŅĐēŅ‰Đž ĐąĐĩĐēĐĩĐŊĐ´ ĐŊĐ°Đ´Ņ–ŅˆĐģĐĩ Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´ĐŊŅ– ĐˇĐ°ĐŗĐžĐģОвĐēи, Ņ‰Đž дОСвОĐģŅŅŽŅ‚ŅŒ ĐēĐžĐŧ҃ĐŊŅ–ĐēĐ°Ņ†Ņ–ŅŽ С Ņ†ŅŒĐžĐŗĐž Ņ–ĐŊŅˆĐžĐŗĐž Đ´ĐļĐĩŅ€ĐĩĐģа (`http://localhost:8080`), Ņ‚ĐžĐ´Ņ– ĐąŅ€Đ°ŅƒĐˇĐĩŅ€ ĐŊа ĐŋĐžŅ€Ņ‚Ņƒ `:8080` дОСвОĐģĐ¸Ņ‚ŅŒ JavaScript ҃ Ņ„Ņ€ĐžĐŊŅ‚ĐĩĐŊĐ´Ņ– ĐŊĐ°Đ´Ņ–ŅĐģĐ°Ņ‚Đ¸ ŅĐ˛Ņ–Đš СаĐŋĐ¸Ņ‚ Đ´Đž ĐąĐĩĐēĐĩĐŊĐ´Ņƒ ĐŊа ĐŋĐžŅ€Ņ‚Ņƒ `:80`. + +ЊОй Đ´ĐžŅŅĐŗŅ‚Đ¸ Ņ†ŅŒĐžĐŗĐž, ĐąĐĩĐēĐĩĐŊĐ´ ĐŊа ĐŋĐžŅ€Ņ‚Ņƒ `:80` ĐŋОвиĐŊĐĩĐŊ ĐŧĐ°Ņ‚Đ¸ ҁĐŋĐ¸ŅĐžĐē "дОСвОĐģĐĩĐŊĐ¸Ņ… Đ´ĐļĐĩŅ€ĐĩĐģ". + +ĐŖ Ņ†ŅŒĐžĐŧ҃ виĐŋадĐē҃ ҁĐŋĐ¸ŅĐžĐē ĐŧĐ°Ņ” ĐŧŅ–ŅŅ‚Đ¸Ņ‚Đ¸ `http://localhost:8080`, Ņ‰ĐžĐą Ņ„Ņ€ĐžĐŊŅ‚ĐĩĐŊĐ´ ĐŊа ĐŋĐžŅ€Ņ‚Ņƒ `:8080` ĐŋŅ€Đ°Ņ†ŅŽĐ˛Đ°Đ˛ ĐēĐžŅ€ĐĩĐēŅ‚ĐŊĐž. + +## ХиĐŧвОĐģҌĐŊĐĩ ĐŋŅ–Đ´ŅŅ‚Đ°Đ˛ĐģŅĐŊĐŊŅ + +МоĐļĐŊа Ņ‚Đ°ĐēĐžĐļ ĐžĐŗĐžĐģĐžŅĐ¸Ņ‚Đ¸ ҁĐŋĐ¸ŅĐžĐē ŅĐē `"*"` ("ŅĐ¸ĐŧвОĐģҌĐŊĐĩ ĐŋŅ–Đ´ŅŅ‚Đ°Đ˛ĐģŅĐŊĐŊŅ"), Ņ‰Đž ОСĐŊĐ°Ņ‡Đ°Ņ” Đ´ĐžĐˇĐ˛Ņ–Đģ Đ´ĐģŅ Đ˛ŅŅ–Ņ… Đ´ĐļĐĩŅ€ĐĩĐģ. + +ОдĐŊаĐē ҆Đĩ дОСвОĐģĐ¸Ņ‚ŅŒ ĐģĐ¸ŅˆĐĩ ĐŋĐĩвĐŊŅ– Ņ‚Đ¸Đŋи ĐēĐžĐŧ҃ĐŊŅ–ĐēĐ°Ņ†Ņ–Ņ—, виĐēĐģŅŽŅ‡Đ°ŅŽŅ‡Đ¸ Đ˛ŅĐĩ, Ņ‰Đž ĐŋОв'ŅĐˇĐ°ĐŊĐĩ С ОйĐģŅ–ĐēОвиĐŧи даĐŊиĐŧи: Cookies, ĐˇĐ°ĐŗĐžĐģОвĐēи Đ°Đ˛Ņ‚ĐžŅ€Đ¸ĐˇĐ°Ņ†Ņ–Ņ—, Ņ‚Đ°ĐēŅ– ŅĐē ҂Җ, Ņ‰Đž виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅŽŅ‚ŅŒŅŅ С Bearer Ņ‚ĐžĐēĐĩĐŊаĐŧи Ņ‚ĐžŅ‰Đž. + +ĐĸĐžĐŧ҃ Đ´ĐģŅ ĐēĐžŅ€ĐĩĐēŅ‚ĐŊĐžŅ— Ņ€ĐžĐąĐžŅ‚Đ¸ ĐēŅ€Đ°Ņ‰Đĩ ŅĐ˛ĐŊĐž вĐēĐ°ĐˇŅƒĐ˛Đ°Ņ‚Đ¸ дОСвОĐģĐĩĐŊŅ– Đ´ĐļĐĩŅ€ĐĩĐģа. + +## ВиĐēĐžŅ€Đ¸ŅŅ‚Đ°ĐŊĐŊŅ `CORSMiddleware` + +Ви ĐŧĐžĐļĐĩŅ‚Đĩ ĐŊаĐģĐ°ŅˆŅ‚ŅƒĐ˛Đ°Ņ‚Đ¸ ҆Đĩ ҃ Đ’Đ°ŅˆĐžĐŧ҃ Đ´ĐžĐ´Đ°Ņ‚Đē҃ **FastAPI** Са Đ´ĐžĐŋĐžĐŧĐžĐŗĐžŅŽ `CORSMiddleware`. + +* ІĐŧĐŋĐžŅ€Ņ‚ŅƒĐšŅ‚Đĩ `CORSMiddleware`. +* ĐĄŅ‚Đ˛ĐžŅ€Ņ–Ņ‚ŅŒ ҁĐŋĐ¸ŅĐžĐē дОСвОĐģĐĩĐŊĐ¸Ņ… Đ´ĐļĐĩŅ€ĐĩĐģ (҃ Đ˛Đ¸ĐŗĐģŅĐ´Ņ– Ņ€ŅĐ´ĐēŅ–Đ˛). +* Đ”ĐžĐ´Đ°ĐšŅ‚Đĩ ĐšĐžĐŗĐž ŅĐē "middleware" ҃ Đ’Đ°Ņˆ Đ´ĐžĐ´Đ°Ņ‚ĐžĐē **FastAPI**. + + +ĐĸаĐēĐžĐļ ĐŧĐžĐļĐŊа вĐēĐ°ĐˇĐ°Ņ‚Đ¸, Ņ‡Đ¸ дОСвОĐģŅŅ” Đ’Đ°Ņˆ ĐąĐĩĐēĐĩĐŊĐ´: + +* ОбĐģŅ–ĐēĐžĐ˛Ņ– даĐŊŅ– (ĐˇĐ°ĐŗĐžĐģОвĐēи Đ°Đ˛Ņ‚ĐžŅ€Đ¸ĐˇĐ°Ņ†Ņ–Ņ—, ҁookies, Ņ‚ĐžŅ‰Đž). +* КоĐŊĐēŅ€ĐĩŅ‚ĐŊŅ– HTTP-ĐŧĐĩŅ‚ĐžĐ´Đ¸ (`POST`, `PUT`) айО Đ˛ŅŅ– Са Đ´ĐžĐŋĐžĐŧĐžĐŗĐžŅŽ `"*"` +* КоĐŊĐēŅ€ĐĩŅ‚ĐŊŅ– HTTP-ĐˇĐ°ĐŗĐžĐģОвĐēи айО Đ˛ŅŅ– Са Đ´ĐžĐŋĐžĐŧĐžĐŗĐžŅŽ `"*"`. + + +{* ../../docs_src/cors/tutorial001.py hl[2,6:11,13:19] *} + +ĐŸĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ¸ Са СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ ҃ `CORSMiddleware` Ņ” Đ´ĐžŅĐ¸Ņ‚ŅŒ ОйĐŧĐĩĐļĐĩĐŊиĐŧи, Ņ‚ĐžĐŧ҃ ВаĐŧ ĐŋĐžŅ‚Ņ€Ņ–ĐąĐŊĐž ŅĐ˛ĐŊĐž вĐēĐ°ĐˇĐ°Ņ‚Đ¸ ĐēĐžĐŊĐēŅ€ĐĩŅ‚ĐŊŅ– Đ´ĐļĐĩŅ€ĐĩĐģа, ĐŧĐĩŅ‚ĐžĐ´Đ¸ айО ĐˇĐ°ĐŗĐžĐģОвĐēи, Ņ‰ĐžĐą ĐąŅ€Đ°ŅƒĐˇĐĩŅ€Đ¸ ĐŧĐžĐŗĐģи виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ Ņ—Ņ… ҃ ĐēĐžĐŊŅ‚ĐĩĐēҁ҂Җ СаĐŋĐ¸Ņ‚Ņ–Đ˛ ĐŧŅ–Đļ Ņ€Ņ–ĐˇĐŊиĐŧи Đ´ĐžĐŧĐĩĐŊаĐŧи. + + +ĐŸŅ–Đ´Ņ‚Ņ€Đ¸ĐŧŅƒŅŽŅ‚ŅŒŅŅ Ņ‚Đ°ĐēŅ– Đ°Ņ€ĐŗŅƒĐŧĐĩĐŊŅ‚Đ¸: + +* `allow_origins` - ĐĄĐŋĐ¸ŅĐžĐē Đ´ĐļĐĩŅ€ĐĩĐģ, ŅĐēиĐŧ дОСвОĐģĐĩĐŊĐž ĐˇĐ´Ņ–ĐšŅĐŊŅŽĐ˛Đ°Ņ‚Đ¸ ĐŧŅ–ĐļĐ´ĐžĐŧĐĩĐŊĐŊŅ– СаĐŋĐ¸Ņ‚Đ¸. НаĐŋŅ€Đ¸ĐēĐģад `['https://example.org', 'https://www.example.org']`. Ви ĐŧĐžĐļĐĩŅ‚Đĩ виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ ['*'], Ņ‰ĐžĐą дОСвОĐģĐ¸Ņ‚Đ¸ Đ˛ŅŅ– Đ´ĐļĐĩŅ€ĐĩĐģа. +* `allow_origin_regex` - Đ ŅĐ´ĐžĐē Ņ€ĐĩĐŗŅƒĐģŅŅ€ĐŊĐžĐŗĐž Đ˛Đ¸Ņ€Đ°ĐˇŅƒ Đ´ĐģŅ Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´ĐŊĐžŅŅ‚Ņ– Đ´ĐļĐĩŅ€ĐĩĐģаĐŧ, ŅĐēиĐŧ дОСвОĐģĐĩĐŊĐž ĐˇĐ´Ņ–ĐšŅĐŊŅŽĐ˛Đ°Ņ‚Đ¸ ĐŧŅ–ĐļĐ´ĐžĐŧĐĩĐŊĐŊŅ– СаĐŋĐ¸Ņ‚Đ¸. НаĐŋŅ€Đ¸ĐēĐģад, `'https://.*\.example\.org'`. +* `allow_methods` - ĐĄĐŋĐ¸ŅĐžĐē HTTP-ĐŧĐĩŅ‚ĐžĐ´Ņ–Đ˛, дОСвОĐģĐĩĐŊĐ¸Ņ… Đ´ĐģŅ ĐŧŅ–ĐļĐ´ĐžĐŧĐĩĐŊĐŊĐ¸Ņ… СаĐŋĐ¸Ņ‚Ņ–Đ˛. За СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ `['GET']`. Ви ĐŧĐžĐļĐĩŅ‚Đĩ виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ `['*']`, Ņ‰ĐžĐą дОСвОĐģĐ¸Ņ‚Đ¸ Đ˛ŅŅ– ŅŅ‚Đ°ĐŊĐ´Đ°Ņ€Ņ‚ĐŊŅ– ĐŧĐĩŅ‚ĐžĐ´Đ¸. +* `allow_headers` - ĐĄĐŋĐ¸ŅĐžĐē HTTP-ĐˇĐ°ĐŗĐžĐģОвĐēŅ–Đ˛, ŅĐēŅ– ĐŋŅ–Đ´Ņ‚Ņ€Đ¸ĐŧŅƒŅŽŅ‚ŅŒŅŅ Đ´ĐģŅ ĐŧŅ–ĐļĐ´ĐžĐŧĐĩĐŊĐŊĐ¸Ņ… СаĐŋĐ¸Ņ‚Ņ–Đ˛. За СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ `[]`. Ви ĐŧĐžĐļĐĩŅ‚Đĩ виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ `['*']`, Ņ‰ĐžĐą дОСвОĐģĐ¸Ņ‚Đ¸ Đ˛ŅŅ– ĐˇĐ°ĐŗĐžĐģОвĐēи. Đ—Đ°ĐŗĐžĐģОвĐēи `Accept`, `Accept-Language`, `Content-Language` Ņ– `Content-Type` СавĐļди дОСвОĐģĐĩĐŊŅ– Đ´ĐģŅ ĐŋŅ€ĐžŅŅ‚Đ¸Ņ… CORS-СаĐŋĐ¸Ņ‚Ņ–Đ˛. +* `allow_credentials` - ВизĐŊĐ°Ņ‡Đ°Ņ”, Ņ‡Đ¸ ĐŋŅ–Đ´Ņ‚Ņ€Đ¸ĐŧŅƒŅŽŅ‚ŅŒŅŅ Ņ„Đ°ĐšĐģи cookie Đ´ĐģŅ ĐŧŅ–ĐļĐ´ĐžĐŧĐĩĐŊĐŊĐ¸Ņ… СаĐŋĐ¸Ņ‚Ņ–Đ˛. За СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ `False`. ĐĸаĐēĐžĐļ, ŅĐēŅ‰Đž ĐŋĐžŅ‚Ņ€Ņ–ĐąĐŊĐž дОСвОĐģĐ¸Ņ‚Đ¸ ОйĐŧŅ–ĐŊ ОйĐģŅ–ĐēОвиĐŧи даĐŊиĐŧи (`allow_credentials = True`), ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ `allow_origins` ĐŊĐĩ ĐŧĐžĐļĐĩ ĐąŅƒŅ‚Đ¸ Đ˛ŅŅ‚Đ°ĐŊОвĐģĐĩĐŊиК ŅĐē `['*']`, ĐŊĐĩĐžĐąŅ…Ņ–Đ´ĐŊĐž вĐēĐ°ĐˇĐ°Ņ‚Đ¸ ĐēĐžĐŊĐēŅ€ĐĩŅ‚ĐŊŅ– Đ´ĐļĐĩŅ€ĐĩĐģа. +* `expose_headers` - ВĐēĐ°ĐˇŅƒŅ”, ŅĐēŅ– ĐˇĐ°ĐŗĐžĐģОвĐēи Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´Ņ– ĐŋОвиĐŊĐŊŅ– ĐąŅƒŅ‚Đ¸ Đ´ĐžŅŅ‚ŅƒĐŋĐŊŅ– Đ´ĐģŅ ĐąŅ€Đ°ŅƒĐˇĐĩŅ€Đ°. За СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ `[]`. +* `max_age` - Đ’ŅŅ‚Đ°ĐŊОвĐģŅŽŅ” ĐŧаĐēŅĐ¸ĐŧаĐģҌĐŊиК Ņ‡Đ°Ņ (҃ ҁĐĩĐē҃ĐŊĐ´Đ°Ņ…) Đ´ĐģŅ ĐēĐĩŅˆŅƒĐ˛Đ°ĐŊĐŊŅ CORS-Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´ĐĩĐš ҃ ĐąŅ€Đ°ŅƒĐˇĐĩŅ€Đ°Ņ…. За СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ `600`. + +ĐĻĐĩĐš middleware ĐžĐąŅ€ĐžĐąĐģŅŅ” два Ņ‚Đ¸Đŋи HTTP-СаĐŋĐ¸Ņ‚Ņ–Đ˛... + +### ПоĐŋĐĩŅ€ĐĩĐ´ĐŊŅ– CORS-СаĐŋĐ¸Ņ‚Đ¸ (preflight requests) + +ĐĻĐĩ ĐąŅƒĐ´ŅŒ-ŅĐēŅ– `OPTIONS` - СаĐŋĐ¸Ņ‚Đ¸, Ņ‰Đž ĐŧŅ–ŅŅ‚ŅŅ‚ŅŒ ĐˇĐ°ĐŗĐžĐģОвĐēи `Origin` Ņ‚Đ° `Access-Control-Request-Method`. + +ĐŖ Ņ‚Đ°ĐēĐžĐŧ҃ виĐŋадĐē҃ middleware ĐŋĐĩŅ€ĐĩŅ…ĐžĐŋĐ¸Ņ‚ŅŒ Đ˛Ņ…Ņ–Đ´ĐŊиК СаĐŋĐ¸Ņ‚ Ņ– Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–ŅŅ‚ŅŒ Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´ĐŊиĐŧи CORS-ĐˇĐ°ĐŗĐžĐģОвĐēаĐŧи, ĐŋОвĐĩŅ€Ņ‚Đ°ŅŽŅ‡Đ¸ айО `200`, айО `400` Đ´ĐģŅ Ņ–ĐŊŅ„ĐžŅ€ĐŧĐ°Ņ†Ņ–ĐšĐŊĐ¸Ņ… ҆ҖĐģĐĩĐš. + +### ĐŸŅ€ĐžŅŅ‚Ņ– СаĐŋĐ¸Ņ‚Đ¸ + +Đ‘ŅƒĐ´ŅŒ-ŅĐēŅ– СаĐŋĐ¸Ņ‚Đ¸ Ņ–Đˇ ĐˇĐ°ĐŗĐžĐģОвĐēĐžĐŧ `Origin`. ĐŖ Ņ†ŅŒĐžĐŧ҃ виĐŋадĐē҃ middleware ĐŋŅ€ĐžĐŋŅƒŅŅ‚Đ¸Ņ‚ŅŒ СаĐŋĐ¸Ņ‚ ŅĐē ĐˇĐ˛Đ¸Ņ‡Đ°ĐšĐŊиК, аĐģĐĩ Đ´ĐžĐ´Đ°ŅŅ‚ŅŒ Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´ĐŊŅ– CORS-ĐˇĐ°ĐŗĐžĐģОвĐēи ҃ Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´ŅŒ. + +## Đ”ĐžĐ´Đ°Ņ‚ĐēОва Ņ–ĐŊŅ„ĐžŅ€ĐŧĐ°Ņ†Ņ–Ņ + +Đ‘Ņ–ĐģҌ҈Đĩ ĐŋŅ€Đž CORS ĐŧĐžĐļĐŊа Đ´Ņ–ĐˇĐŊĐ°Ņ‚Đ¸ŅŅ в Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Ņ–Ņ— Mozilla. + +/// note | ĐĸĐĩŅ…ĐŊҖ҇ĐŊŅ– Đ´ĐĩŅ‚Đ°ĐģŅ– + +ĐĸаĐēĐžĐļ ĐŧĐžĐļĐŊа виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ `from starlette.middleware.cors import CORSMiddleware`. + +**FastAPI** ĐŊĐ°Đ´Đ°Ņ” ĐēŅ–ĐģҌĐēа middleware ҃ `fastapi.middleware` Đ´ĐģŅ ĐˇŅ€ŅƒŅ‡ĐŊĐžŅŅ‚Ņ– Ņ€ĐžĐˇŅ€ĐžĐąĐŊиĐēŅ–Đ˛. АĐģĐĩ ĐąŅ–ĐģŅŒŅˆŅ–ŅŅ‚ŅŒ Đ´ĐžŅŅ‚ŅƒĐŋĐŊĐ¸Ņ… middleware ĐŋĐžŅ…ĐžĐ´ŅŅ‚ŅŒ ĐąĐĩСĐŋĐžŅĐĩŅ€ĐĩĐ´ĐŊŅŒĐž ĐˇŅ– Starlette. + +/// diff --git a/docs/uk/docs/tutorial/debugging.md b/docs/uk/docs/tutorial/debugging.md new file mode 100644 index 000000000..b0e5344f8 --- /dev/null +++ b/docs/uk/docs/tutorial/debugging.md @@ -0,0 +1,112 @@ +# НаĐģĐ°ĐŗĐžĐ´ĐļĐĩĐŊĐŊŅ (Debugging) + +Ви ĐŧĐžĐļĐĩŅ‚Đĩ ĐŋŅ–Đ´'Ņ”Đ´ĐŊĐ°Ņ‚Đ¸ Đ´ĐĩĐąĐ°ĐŗĐĩŅ€ ҃ Đ’Đ°ŅˆĐžĐŧ҃ Ņ€ĐĩдаĐēŅ‚ĐžŅ€Ņ– ĐēĐžĐ´Ņƒ, ĐŊаĐŋŅ€Đ¸ĐēĐģад, ҃ Visual Studio Code айО PyCharm. + +## ВиĐēĐģиĐē `uvicorn` + +ĐŖ Đ’Đ°ŅˆĐžĐŧ҃ FastAPI-Đ´ĐžĐ´Đ°Ņ‚Đē҃ Ņ–ĐŧĐŋĐžŅ€Ņ‚ŅƒĐšŅ‚Đĩ Ņ‚Đ° СаĐŋŅƒŅŅ‚Ņ–Ņ‚ŅŒ `uvicorn` ĐąĐĩСĐŋĐžŅĐĩŅ€ĐĩĐ´ĐŊŅŒĐž: + +{* ../../docs_src/debugging/tutorial001.py hl[1,15] *} + +### ĐŸŅ€Đž `__name__ == "__main__"` + +ГоĐģОвĐŊа ĐŧĐĩŅ‚Đ° виĐēĐžŅ€Đ¸ŅŅ‚Đ°ĐŊĐŊŅ `__name__ == "__main__"` — ҆Đĩ СайĐĩСĐŋĐĩ҇ĐĩĐŊĐŊŅ виĐēĐžĐŊаĐŊĐŊŅ ĐŋĐĩвĐŊĐžĐŗĐž ĐēĐžĐ´Ņƒ ҂ҖĐģҌĐēи Ņ‚ĐžĐ´Ņ–, ĐēĐžĐģи Ņ„Đ°ĐšĐģ СаĐŋ҃ҁĐēĐ°Ņ”Ņ‚ŅŒŅŅ ĐąĐĩСĐŋĐžŅĐĩŅ€ĐĩĐ´ĐŊŅŒĐž: + +
+ +```console +$ python myapp.py +``` + +
+ +аĐģĐĩ ĐŊĐĩ виĐēĐžĐŊŅƒŅ”Ņ‚ŅŒŅŅ ĐŋŅ€Đ¸ ĐšĐžĐŗĐž Ņ–ĐŧĐŋĐžŅ€Ņ‚Ņ– в Ņ–ĐŊŅˆĐ¸Đš Ņ„Đ°ĐšĐģ, ĐŊаĐŋŅ€Đ¸ĐēĐģад: + +```Python +from myapp import app +``` + +#### ДĐĩŅ‚Đ°ĐģҌĐŊŅ–ŅˆĐĩ + +ĐŸŅ€Đ¸ĐŋŅƒŅŅ‚Đ¸ĐŧĐž, Đ’Đ°Ņˆ Ņ„Đ°ĐšĐģ ĐŊĐ°ĐˇĐ¸Đ˛Đ°Ņ”Ņ‚ŅŒŅŅ `myapp.py`. + +Đ¯ĐēŅ‰Đž Ви СаĐŋŅƒŅŅ‚Đ¸Ņ‚Đĩ ĐšĐžĐŗĐž Ņ‚Đ°Đē: + +
+ +```console +$ python myapp.py +``` + +
+ +Ņ‚ĐžĐ´Ņ– вĐŊŅƒŅ‚Ņ€Ņ–ŅˆĐŊŅ СĐŧŅ–ĐŊĐŊа `__name__`, ŅĐēа ŅŅ‚Đ˛ĐžŅ€ŅŽŅ”Ņ‚ŅŒŅŅ Đ°Đ˛Ņ‚ĐžĐŧĐ°Ņ‚Đ¸Ņ‡ĐŊĐž Python, ĐŧĐ°Ņ‚Đ¸ĐŧĐĩ СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ `"__main__"`. + +ĐžŅ‚ĐļĐĩ, ҆ĐĩĐš ĐąĐģĐžĐē ĐēĐžĐ´Ņƒ: + +```Python + uvicorn.run(app, host="0.0.0.0", port=8000) +``` + +ĐąŅƒĐ´Đĩ виĐēĐžĐŊаĐŊиК. + +--- + +ĐĻĐĩ ĐŊĐĩ ŅŅ‚Đ°ĐŊĐĩŅ‚ŅŒŅŅ, ŅĐēŅ‰Đž Ви Ņ–ĐŧĐŋĐžŅ€Ņ‚ŅƒŅ”Ņ‚Đĩ ҆ĐĩĐš ĐŧĐžĐ´ŅƒĐģҌ (Ņ„Đ°ĐšĐģ). + +Đ¯ĐēŅ‰Đž ҃ Đ’Đ°Ņ Ņ” Ņ–ĐŊŅˆĐ¸Đš Ņ„Đ°ĐšĐģ, ĐŊаĐŋŅ€Đ¸ĐēĐģад `importer.py`, С ĐŊĐ°ŅŅ‚ŅƒĐŋĐŊиĐŧ ĐēОдОĐŧ: + +```Python +from myapp import app + +# Đ”ĐžĐ´Đ°Ņ‚ĐēОвиК ĐēОд +``` + +ĐŖ Ņ†ŅŒĐžĐŧ҃ виĐŋадĐē҃ Đ°Đ˛Ņ‚ĐžĐŧĐ°Ņ‚Đ¸Ņ‡ĐŊĐž ŅŅ‚Đ˛ĐžŅ€ĐĩĐŊа СĐŧŅ–ĐŊĐŊа ҃ Ņ„Đ°ĐšĐģŅ– `myapp.py` ĐŊĐĩ ĐŧĐ°Ņ‚Đ¸ĐŧĐĩ СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ СĐŧŅ–ĐŊĐŊĐžŅ— `__name__` ŅĐē `"__main__"`. + +ĐžŅ‚ĐļĐĩ, Ņ€ŅĐ´ĐžĐē: + +```Python + uvicorn.run(app, host="0.0.0.0", port=8000) +``` + +ĐŊĐĩ ĐąŅƒĐ´Đĩ виĐēĐžĐŊаĐŊĐž. + +/// info | ІĐŊŅ„ĐžŅ€ĐŧĐ°Ņ†Ņ–Ņ + +Đ‘Ņ–ĐģҌ҈ Đ´ĐĩŅ‚Đ°ĐģҌĐŊ҃ Ņ–ĐŊŅ„ĐžŅ€ĐŧĐ°Ņ†Ņ–ŅŽ ĐŧĐžĐļĐŊа СĐŊĐ°ĐšŅ‚Đ¸ в ĐžŅ„Ņ–Ņ†Ņ–ĐšĐŊŅ–Đš Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Ņ–Ņ— Python. + +/// + +## ЗаĐŋ҃ҁĐē ĐēĐžĐ´Ņƒ С Đ˛Đ°ŅˆĐ¸Đŧ Đ´ĐĩĐąĐ°ĐŗĐĩŅ€ĐžĐŧ + +ĐžŅĐēŅ–ĐģҌĐēи Ви СаĐŋ҃ҁĐēĐ°Ņ”Ņ‚Đĩ ҁĐĩŅ€Đ˛ĐĩŅ€ Uvicorn ĐąĐĩСĐŋĐžŅĐĩŅ€ĐĩĐ´ĐŊŅŒĐž С Đ’Đ°ŅˆĐžĐŗĐž ĐēĐžĐ´Ņƒ, Ви ĐŧĐžĐļĐĩŅ‚Đĩ СаĐŋŅƒŅŅ‚Đ¸Ņ‚Đ¸ Đ˛Đ°ŅˆŅƒ Python ĐŋŅ€ĐžĐŗŅ€Đ°Đŧ҃ (Đ˛Đ°Ņˆ FastAPI Đ´ĐžĐ´Đ°Ņ‚ĐžĐē) ĐąĐĩСĐŋĐžŅĐĩŅ€ĐĩĐ´ĐŊŅŒĐž С Đ´ĐĩĐąĐ°ĐŗĐĩŅ€Đ°. + +--- + +НаĐŋŅ€Đ¸ĐēĐģад, ҃ Visual Studio Code Ви ĐŧĐžĐļĐĩŅ‚Đĩ: + +* ПĐĩŅ€ĐĩĐšĐ´Ņ–Ņ‚ŅŒ ĐŊа вĐēĐģадĐē҃ "Debug". +* ĐĐ°Ņ‚Đ¸ŅĐŊŅ–Ņ‚ŅŒ "Add configuration...". +* ВибĐĩŅ€Ņ–Ņ‚ŅŒ "Python" +* ЗаĐŋŅƒŅŅ‚Ņ–Ņ‚ŅŒ Đ´ĐĩĐąĐ°ĐŗĐĩŅ€ С ĐžĐŋŅ†Ņ–Ņ”ŅŽ "`Python: Current File (Integrated Terminal)`". + +ĐĻĐĩ СаĐŋŅƒŅŅ‚Đ¸Ņ‚ŅŒ ҁĐĩŅ€Đ˛ĐĩŅ€ С Đ’Đ°ŅˆĐ¸Đŧ **FastAPI** ĐēОдОĐŧ, ĐˇŅƒĐŋиĐŊĐ¸Ņ‚ŅŒŅŅ ĐŊа Ņ‚ĐžŅ‡ĐēĐ°Ņ… ĐˇŅƒĐŋиĐŊ҃ Ņ‚ĐžŅ‰Đž. + +ĐžŅŅŒ ŅĐē ҆Đĩ ĐŧĐžĐļĐĩ Đ˛Đ¸ĐŗĐģŅĐ´Đ°Ņ‚Đ¸: + + + +--- +Đ¯ĐēŅ‰Đž Ви виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅ”Ņ‚Đĩ PyCharm, ви ĐŧĐžĐļĐĩŅ‚Đĩ: + +* Đ’Ņ–Đ´ĐēŅ€Đ¸Ņ‚Đ¸ ĐŧĐĩĐŊŅŽ "Run". +* Đ’Đ¸ĐąŅ€Đ°Ņ‚Đ¸ ĐžĐŋŅ†Ņ–ŅŽ "Debug...". +* ĐŸĐžŅ‚Ņ–Đŧ С'ŅĐ˛Đ¸Ņ‚ŅŒŅŅ ĐēĐžĐŊŅ‚ĐĩĐēҁ҂ĐŊĐĩ ĐŧĐĩĐŊŅŽ. +* Đ’Đ¸ĐąŅ€Đ°Ņ‚Đ¸ Ņ„Đ°ĐšĐģ Đ´ĐģŅ ĐŊаĐģĐ°ĐŗĐžĐ´ĐļĐĩĐŊĐŊŅ (҃ Ņ†ŅŒĐžĐŧ҃ виĐŋадĐē҃, `main.py`). + +ĐĻĐĩ СаĐŋŅƒŅŅ‚Đ¸Ņ‚ŅŒ ҁĐĩŅ€Đ˛ĐĩŅ€ С Đ’Đ°ŅˆĐ¸Đŧ **FastAPI** ĐēОдОĐŧ, ĐˇŅƒĐŋиĐŊĐ¸Ņ‚ŅŒŅŅ ĐŊа Ņ‚ĐžŅ‡ĐēĐ°Ņ… ĐˇŅƒĐŋиĐŊ҃ Ņ‚ĐžŅ‰Đž. + +ĐžŅŅŒ ŅĐē ҆Đĩ ĐŧĐžĐļĐĩ Đ˛Đ¸ĐŗĐģŅĐ´Đ°Ņ‚Đ¸: + + diff --git a/docs/uk/docs/tutorial/handling-errors.md b/docs/uk/docs/tutorial/handling-errors.md new file mode 100644 index 000000000..12a356cd0 --- /dev/null +++ b/docs/uk/docs/tutorial/handling-errors.md @@ -0,0 +1,255 @@ +# ĐžĐąŅ€ĐžĐąĐēа ПоĐŧиĐģĐžĐē + +Є ĐąĐ°ĐŗĐ°Ņ‚Đž ŅĐ¸Ņ‚ŅƒĐ°Ņ†Ņ–Đš, ĐēĐžĐģи ĐŋĐžŅ‚Ņ€Ņ–ĐąĐŊĐž ĐŋĐžĐ˛Ņ–Đ´ĐžĐŧĐ¸Ņ‚Đ¸ ĐēĐģŅ–Ņ”ĐŊŅ‚Đ°, ŅĐēиК виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅ” Đ’Đ°Ņˆ API, ĐŋŅ€Đž ĐŋĐžĐŧиĐģĐē҃. + +ĐĻиĐŧ ĐēĐģŅ–Ņ”ĐŊŅ‚ĐžĐŧ ĐŧĐžĐļĐĩ ĐąŅƒŅ‚Đ¸ ĐąŅ€Đ°ŅƒĐˇĐĩŅ€ Ņ–Đˇ Ņ„Ņ€ĐžĐŊŅ‚ĐĩĐŊĐ´ĐžĐŧ, ĐēОд Ņ–ĐŊŅˆĐžĐŗĐž Ņ€ĐžĐˇŅ€ĐžĐąĐŊиĐēа, IoT-ĐŋŅ€Đ¸ŅŅ‚Ņ€Ņ–Đš Ņ‚ĐžŅ‰Đž. + +МоĐļĐģивО, ВаĐŧ ĐŋĐžŅ‚Ņ€Ņ–ĐąĐŊĐž ĐŋĐžĐ˛Ņ–Đ´ĐžĐŧĐ¸Ņ‚Đ¸ ĐēĐģŅ–Ņ”ĐŊŅ‚Đ°, Ņ‰Đž: + +* ĐŖ ĐŊŅŒĐžĐŗĐž ĐŊĐĩĐ´ĐžŅŅ‚Đ°Ņ‚ĐŊŅŒĐž ĐŋŅ€Đ°Đ˛ Đ´ĐģŅ виĐēĐžĐŊаĐŊĐŊŅ ҆ҖҔҗ ĐžĐŋĐĩŅ€Đ°Ņ†Ņ–Ņ—. +* Đ’Ņ–ĐŊ ĐŊĐĩ ĐŧĐ°Ņ” Đ´ĐžŅŅ‚ŅƒĐŋ҃ Đ´Đž Ņ†ŅŒĐžĐŗĐž Ņ€ĐĩŅŅƒŅ€ŅŅƒ. +* ЕĐģĐĩĐŧĐĩĐŊŅ‚, Đ´Đž ŅĐēĐžĐŗĐž Đ˛Ņ–ĐŊ ĐŊаĐŧĐ°ĐŗĐ°Ņ”Ņ‚ŅŒŅŅ ĐžŅ‚Ņ€Đ¸ĐŧĐ°Ņ‚Đ¸ Đ´ĐžŅŅ‚ŅƒĐŋ, ĐŊĐĩ ҖҁĐŊŅƒŅ”. +* Ņ‚ĐžŅ‰Đž. + +ĐŖ Ņ‚Đ°ĐēĐ¸Ņ… виĐŋадĐēĐ°Ņ… ĐˇĐ°ĐˇĐ˛Đ¸Ņ‡Đ°Đš ĐŋОвĐĩŅ€Ņ‚Đ°Ņ”Ņ‚ŅŒŅŅ **HTTP ŅŅ‚Đ°Ņ‚ŅƒŅ-ĐēОд** в Đ´Ņ–Đ°ĐŋаСОĐŊŅ– **400** (Đ˛Ņ–Đ´ 400 Đ´Đž 499). + +ĐĻĐĩ ŅŅ…ĐžĐļĐĩ ĐŊа HTTP ŅŅ‚Đ°Ņ‚ŅƒŅ-ĐēОди 200 (Đ˛Ņ–Đ´ 200 Đ´Đž 299). ĐĻŅ– "200" ŅŅ‚Đ°Ņ‚ŅƒŅ-ĐēОди ОСĐŊĐ°Ņ‡Đ°ŅŽŅ‚ŅŒ, Ņ‰Đž СаĐŋĐ¸Ņ‚ ĐŋŅ€ĐžĐšŅˆĐžĐ˛ ҃ҁĐŋŅ–ŅˆĐŊĐž. + +ĐĄŅ‚Đ°Ņ‚ŅƒŅ-ĐēОди в Đ´Ņ–Đ°ĐŋаСОĐŊŅ– 400 ОСĐŊĐ°Ņ‡Đ°ŅŽŅ‚ŅŒ, Ņ‰Đž ŅŅ‚Đ°ĐģĐ°ŅŅ ĐŋĐžĐŧиĐģĐēа С йОĐē҃ ĐēĐģŅ–Ņ”ĐŊŅ‚Đ°. + +ПаĐŧ'ŅŅ‚Đ°Ņ”Ņ‚Đĩ Đ˛ŅŅ– ҆Җ ĐŋĐžĐŧиĐģĐēи **404 Not Found** (Ņ– ĐļĐ°Ņ€Ņ‚Đ¸ ĐŋŅ€Đž ĐŊĐ¸Ņ…)? + +## ВиĐēĐžŅ€Đ¸ŅŅ‚Đ°ĐŊĐŊŅ `HTTPException` + +ЊОй ĐŋОвĐĩŅ€ĐŊŅƒŅ‚Đ¸ HTTP-Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´Ņ– С ĐŋĐžĐŧиĐģĐēаĐŧи ĐēĐģŅ–Ņ”ĐŊŅ‚Ņƒ, виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐšŅ‚Đĩ `HTTPException`. + +### ІĐŧĐŋĐžŅ€Ņ‚ `HTTPException` + +{* ../../docs_src/handling_errors/tutorial001.py hl[1] *} + +### ВиĐēĐžŅ€Đ¸ŅŅ‚Đ°ĐŊĐŊŅ `HTTPException` ҃ ĐēĐžĐ´Ņ– + +`HTTPException` — ҆Đĩ ĐˇĐ˛Đ¸Ņ‡Đ°ĐšĐŊа ĐŋĐžĐŧиĐģĐēа Python Ņ–Đˇ Đ´ĐžĐ´Đ°Ņ‚ĐēОвиĐŧи даĐŊиĐŧи, ŅĐēŅ– ŅŅ‚ĐžŅŅƒŅŽŅ‚ŅŒŅŅ API. + +ĐžŅĐēŅ–ĐģҌĐēи ҆Đĩ ĐŋĐžĐŧиĐģĐēа Python, Ви ĐŊĐĩ `ĐŋОвĐĩŅ€Ņ‚Đ°Ņ”Ņ‚Đĩ` ĐšĐžĐŗĐž, а `ĐŗĐĩĐŊĐĩŅ€ŅƒŅ”Ņ‚Đĩ` (ĐŗĐĩĐŊĐĩŅ€ŅƒŅ”Ņ‚Đĩ ĐŋĐžĐŧиĐģĐē҃). + +ĐĻĐĩ Ņ‚Đ°ĐēĐžĐļ ОСĐŊĐ°Ņ‡Đ°Ņ”, Ņ‰Đž ŅĐēŅ‰Đž Ви ĐŋĐĩŅ€ĐĩĐąŅƒĐ˛Đ°Ņ”Ņ‚Đĩ Đ˛ŅĐĩŅ€ĐĩдиĐŊŅ– Đ´ĐžĐŋĐžĐŧŅ–ĐļĐŊĐžŅ— Ņ„ŅƒĐŊĐē҆Җҗ, ŅĐē҃ виĐēĐģиĐēĐ°Ņ”Ņ‚Đĩ Đ˛ŅĐĩŅ€ĐĩдиĐŊŅ– ŅĐ˛ĐžŅ”Ņ— *Ņ„ŅƒĐŊĐē҆Җҗ ĐžĐŋĐĩŅ€Đ°Ņ†Ņ–Ņ— ҈ĐģŅŅ…Ņƒ*, Ņ– Ņ‚Đ°Đŧ ĐŗĐĩĐŊĐĩŅ€ŅƒŅ”Ņ‚Đĩ `HTTPException`, Đ˛ŅĐĩŅ€ĐĩдиĐŊŅ– ҆ҖҔҗ Đ´ĐžĐŋĐžĐŧŅ–ĐļĐŊĐžŅ— Ņ„ŅƒĐŊĐē҆Җҗ, Ņ‚Đž Ņ€ĐĩŅˆŅ‚Đ° ĐēĐžĐ´Ņƒ в *Ņ„ŅƒĐŊĐē҆Җҗ ĐžĐŋĐĩŅ€Đ°Ņ†Ņ–Ņ— ҈ĐģŅŅ…Ņƒ* ĐŊĐĩ ĐąŅƒĐ´Đĩ виĐēĐžĐŊаĐŊа. ЗаĐŋĐ¸Ņ‚ ĐžĐ´Ņ€Đ°ĐˇŅƒ СавĐĩŅ€ŅˆĐ¸Ņ‚ŅŒŅŅ, Ņ– HTTP-ĐŋĐžĐŧиĐģĐēа С `HTTPException` ĐąŅƒĐ´Đĩ ĐŊĐ°Đ´Ņ–ŅĐģаĐŊа ĐēĐģŅ–Ņ”ĐŊŅ‚Ņƒ. + +ПĐĩŅ€ĐĩĐ˛Đ°ĐŗĐ° виĐēĐžŅ€Đ¸ŅŅ‚Đ°ĐŊĐŊŅ `ĐŗĐĩĐŊĐĩŅ€Đ°Ņ†Ņ–Ņ—` (raise) ĐŋĐžĐŧиĐģĐēи СаĐŧŅ–ŅŅ‚ŅŒ `ĐŋОвĐĩŅ€ĐŊĐĩĐŊĐŊŅ` СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ (return) ŅŅ‚Đ°ĐŊĐĩ ĐąŅ–ĐģҌ҈ ĐžŅ‡ĐĩвидĐŊиĐŧ в Ņ€ĐžĐˇĐ´Ņ–ĐģŅ– ĐŋŅ€Đž ЗаĐģĐĩĐļĐŊĐžŅŅ‚Ņ– Ņ‚Đ° БĐĩСĐŋĐĩĐē҃. + +ĐŖ Ņ†ŅŒĐžĐŧ҃ ĐŋŅ€Đ¸ĐēĐģĐ°Đ´Ņ–, ŅĐēŅ‰Đž ĐēĐģŅ–Ņ”ĐŊŅ‚ СаĐŋĐ¸Ņ‚ŅƒŅ” ĐĩĐģĐĩĐŧĐĩĐŊŅ‚ Са ID, ŅĐēĐžĐŗĐž ĐŊĐĩ ҖҁĐŊŅƒŅ”, ĐąŅƒĐ´Đĩ ĐˇĐŗĐĩĐŊĐĩŅ€ĐžĐ˛Đ°ĐŊĐž ĐŋĐžĐŧиĐģĐē҃ ĐˇŅ– ŅŅ‚Đ°Ņ‚ŅƒŅ-ĐēОдОĐŧ `404`: + +{* ../../docs_src/handling_errors/tutorial001.py hl[11] *} + +### ĐžŅ‚Ņ€Đ¸ĐŧаĐŊа Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´ŅŒ + +Đ¯ĐēŅ‰Đž ĐēĐģŅ–Ņ”ĐŊŅ‚ Ņ€ĐžĐąĐ¸Ņ‚ŅŒ СаĐŋĐ¸Ņ‚ Са ҈ĐģŅŅ…ĐžĐŧ `http://example.com/items/foo` (Đ´Đĩ `item_id` `"foo"`), Đ˛Ņ–ĐŊ ĐžŅ‚Ņ€Đ¸ĐŧĐ°Ņ” ŅŅ‚Đ°Ņ‚ŅƒŅ-ĐēОд 200 Ņ– JSON Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´ŅŒ: + +```JSON +{ + "item": "The Foo Wrestlers" +} +``` + +АĐģĐĩ ŅĐēŅ‰Đž ĐēĐģŅ–Ņ”ĐŊŅ‚ Ņ€ĐžĐąĐ¸Ņ‚ŅŒ СаĐŋĐ¸Ņ‚ ĐŊа `http://example.com/items/bar` (Đ´Đĩ `item_id` ĐŧĐ°Ņ” ĐŊĐĩ ҖҁĐŊŅƒŅŽŅ‡Đĩ СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ `"bar"`), Ņ‚Đž ĐžŅ‚Ņ€Đ¸ĐŧĐ°Ņ” ŅŅ‚Đ°Ņ‚ŅƒŅ-ĐēОд 404 (ĐŋĐžĐŧиĐģĐēа "ĐŊĐĩ СĐŊаКдĐĩĐŊĐž") Ņ‚Đ° Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´ŅŒ: + +```JSON +{ + "detail": "Item not found" +} +``` + +/// tip | ĐŸĐžŅ€Đ°Đ´Đ° + +ĐŸŅ–Đ´ Ņ‡Đ°Ņ виĐēĐģиĐē҃ `HTTPException` Ви ĐŧĐžĐļĐĩŅ‚Đĩ ĐŋĐĩŅ€ĐĩĐ´Đ°Ņ‚Đ¸ ĐąŅƒĐ´ŅŒ-ŅĐēĐĩ СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ, ŅĐēĐĩ ĐŧĐžĐļĐĩ ĐąŅƒŅ‚Đ¸ ĐŋĐĩŅ€ĐĩŅ‚Đ˛ĐžŅ€ĐĩĐŊĐĩ в JSON, ŅĐē ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ `detail`, а ĐŊĐĩ ĐģĐ¸ŅˆĐĩ Ņ€ŅĐ´ĐžĐē (`str`). + +Ви ĐŧĐžĐļĐĩŅ‚Đĩ ĐŋĐĩŅ€ĐĩĐ´Đ°Ņ‚Đ¸ `dict`, `list` Ņ‚ĐžŅ‰Đž. + +ВоĐŊи ĐžĐąŅ€ĐžĐąĐģŅŅŽŅ‚ŅŒŅŅ Đ°Đ˛Ņ‚ĐžĐŧĐ°Ņ‚Đ¸Ņ‡ĐŊĐž Са Đ´ĐžĐŋĐžĐŧĐžĐŗĐžŅŽ **FastAPI** Ņ‚Đ° ĐŋĐĩŅ€ĐĩŅ‚Đ˛ĐžŅ€ŅŽŅŽŅ‚ŅŒŅŅ в JSON. + +/// + +## ДодаваĐŊĐŊŅ вĐģĐ°ŅĐŊĐ¸Ņ… ĐˇĐ°ĐŗĐžĐģОвĐēŅ–Đ˛ + +ІĐŊĐžĐ´Ņ– ĐŋĐžŅ‚Ņ€Ņ–ĐąĐŊĐž Đ´ĐžĐ´Đ°Ņ‚Đ¸ вĐģĐ°ŅĐŊŅ– ĐˇĐ°ĐŗĐžĐģОвĐēи Đ´Đž HTTP-ĐŋĐžĐŧиĐģĐēи, ĐŊаĐŋŅ€Đ¸ĐēĐģад, Đ´ĐģŅ ĐŋĐĩвĐŊĐ¸Ņ… Ņ‚Đ¸ĐŋŅ–Đ˛ ĐąĐĩСĐŋĐĩĐēи. + +ЙĐŧĐžĐ˛Ņ–Ņ€ĐŊĐž, ВаĐŧ ĐŊĐĩ дОвĐĩĐ´ĐĩŅ‚ŅŒŅŅ виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ ҆Đĩ ĐąĐĩСĐŋĐžŅĐĩŅ€ĐĩĐ´ĐŊŅŒĐž ҃ ŅĐ˛ĐžŅ”Đŧ҃ ĐēĐžĐ´Ņ–. + +АĐģĐĩ ŅĐēŅ‰Đž ВаĐŧ СĐŊĐ°Đ´ĐžĐąĐ¸Ņ‚ŅŒŅŅ ҆Đĩ Đ´ĐģŅ ҁĐēĐģадĐŊĐžĐŗĐž ҁ҆ĐĩĐŊĐ°Ņ€Ņ–ŅŽ, Ви ĐŧĐžĐļĐĩŅ‚Đĩ Đ´ĐžĐ´Đ°Ņ‚Đ¸ вĐģĐ°ŅĐŊŅ– ĐˇĐ°ĐŗĐžĐģОвĐēи: + +{* ../../docs_src/handling_errors/tutorial002.py hl[14] *} + +## Đ’ŅŅ‚Đ°ĐŊОвĐģĐĩĐŊĐŊŅ вĐģĐ°ŅĐŊĐ¸Ņ… ĐžĐąŅ€ĐžĐąĐŊиĐēŅ–Đ˛ ĐŋĐžĐŧиĐģĐžĐē + +Ви ĐŧĐžĐļĐĩŅ‚Đĩ Đ´ĐžĐ´Đ°Ņ‚Đ¸ вĐģĐ°ŅĐŊŅ– ĐžĐąŅ€ĐžĐąĐŊиĐēи ĐŋĐžĐŧиĐģĐžĐē Са Đ´ĐžĐŋĐžĐŧĐžĐŗĐžŅŽ Ņ‚Đ¸Ņ… ŅĐ°ĐŧĐ¸Ņ… ŅƒŅ‚Đ¸ĐģŅ–Ņ‚ ĐžĐąŅ€ĐžĐąĐēи ĐŋĐžĐŧиĐģĐžĐē ĐˇŅ– Starlette. + +ĐŸŅ€Đ¸ĐŋŅƒŅŅ‚Đ¸ĐŧĐž, ҃ Đ’Đ°Ņ Ņ” вĐģĐ°ŅĐŊиК ОйĘŧŅ”ĐēŅ‚ ĐŋĐžĐŧиĐģĐēи `UnicornException`, ŅĐēĐĩ Ви (айО ĐąŅ–ĐąĐģŅ–ĐžŅ‚ĐĩĐēа, ŅĐē҃ Ви виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅ”Ņ‚Đĩ) ĐŧĐžĐļĐĩ `ĐˇĐŗĐĩĐŊĐĩŅ€ŅƒĐ˛Đ°Ņ‚Đ¸` (`raise`). + +І Ви Ņ…ĐžŅ‡ĐĩŅ‚Đĩ ĐžĐąŅ€ĐžĐąĐģŅŅ‚Đ¸ ҆Đĩ виĐēĐģŅŽŅ‡ĐĩĐŊĐŊŅ ĐŗĐģОйаĐģҌĐŊĐž Са Đ´ĐžĐŋĐžĐŧĐžĐŗĐžŅŽ FastAPI. + +Ви ĐŧĐžĐļĐĩŅ‚Đĩ Đ´ĐžĐ´Đ°Ņ‚Đ¸ вĐģĐ°ŅĐŊиК ĐžĐąŅ€ĐžĐąĐŊиĐē виĐēĐģŅŽŅ‡ĐĩĐŊҌ Са Đ´ĐžĐŋĐžĐŧĐžĐŗĐžŅŽ `@app.exception_handler()`: + +{* ../../docs_src/handling_errors/tutorial003.py hl[5:7,13:18,24] *} + +ĐĸŅƒŅ‚, ŅĐēŅ‰Đž Ви СвĐĩŅ€ĐŊĐĩŅ‚ĐĩŅŅ Đ´Đž `/unicorns/yolo`, Ņ‚Đž ĐˇĐŗĐĩĐŊĐĩŅ€ŅƒŅ”Ņ‚ŅŒŅŅ ĐŋĐžĐŧиĐģĐēа `UnicornException`. + +АĐģĐĩ вОĐŊа ĐąŅƒĐ´Đĩ ĐžĐąŅ€ĐžĐąĐģĐĩĐŊа Ņ„ŅƒĐŊĐēŅ†Ņ–Ņ”ŅŽ-ĐžĐąŅ€ĐžĐąĐŊиĐēĐžĐŧ `unicorn_exception_handler`. + +ĐžŅ‚ĐļĐĩ, Ви ĐžŅ‚Ņ€Đ¸ĐŧĐ°Ņ”Ņ‚Đĩ ĐˇŅ€ĐžĐˇŅƒĐŧŅ–Đģ҃ ĐŋĐžĐŧиĐģĐē҃ ĐˇŅ– HTTP-ŅŅ‚Đ°Ņ‚ŅƒŅĐžĐŧ `418` Ņ– JSON-Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´Đ´ŅŽ: + +```JSON +{"message": "Oops! yolo did something. There goes a rainbow..."} +``` + +/// note | ĐĸĐĩŅ…ĐŊҖ҇ĐŊŅ– Đ´ĐĩŅ‚Đ°ĐģŅ– + +Ви Ņ‚Đ°ĐēĐžĐļ ĐŧĐžĐļĐĩŅ‚Đĩ виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ `from starlette.requests import Request` Ņ– `from starlette.responses import JSONResponse`. + +**FastAPI** ĐŊĐ°Đ´Đ°Ņ” ҂Җ ŅĐ°ĐŧŅ– `starlette.responses`, Ņ‰Đž Đš `fastapi.responses`, ĐŋŅ€ĐžŅŅ‚Đž Đ´ĐģŅ ĐˇŅ€ŅƒŅ‡ĐŊĐžŅŅ‚Ņ– Ņ€ĐžĐˇŅ€ĐžĐąĐŊиĐēа. АĐģĐĩ ĐąŅ–ĐģŅŒŅˆŅ–ŅŅ‚ŅŒ Đ´ĐžŅŅ‚ŅƒĐŋĐŊĐ¸Ņ… Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´ĐĩĐš ĐŊĐ°Đ´Ņ…ĐžĐ´ŅŅ‚ŅŒ ĐąĐĩСĐŋĐžŅĐĩŅ€ĐĩĐ´ĐŊŅŒĐž ĐˇŅ– Starlette. ĐĸĐĩ Đļ ŅĐ°ĐŧĐĩ ŅŅ‚ĐžŅŅƒŅ”Ņ‚ŅŒŅŅ Ņ– `Request`. + +/// + +## ПĐĩŅ€ĐĩвиСĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ ĐžĐąŅ€ĐžĐąĐŊиĐēŅ–Đ˛ ĐŋĐžĐŧиĐģĐžĐē Са СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ + +**FastAPI** ĐŧĐ°Ņ” ĐēŅ–ĐģҌĐēа ĐžĐąŅ€ĐžĐąĐŊиĐēŅ–Đ˛ ĐŋĐžĐŧиĐģĐžĐē Са СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ. + +ĐĻŅ– ĐžĐąŅ€ĐžĐąĐŊиĐēи Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´Đ°ŅŽŅ‚ŅŒ Са ĐŋОвĐĩŅ€ĐŊĐĩĐŊĐŊŅ ŅŅ‚Đ°ĐŊĐ´Đ°Ņ€Ņ‚ĐŊĐ¸Ņ… JSON-Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´ĐĩĐš, ĐēĐžĐģи Ви `ĐŗĐĩĐŊĐĩŅ€ŅƒŅ”Ņ‚Đĩ` (`raise`) `HTTPException`, а Ņ‚Đ°ĐēĐžĐļ ĐēĐžĐģи СаĐŋĐ¸Ņ‚ ĐŧŅ–ŅŅ‚Đ¸Ņ‚ŅŒ ĐŊĐĩĐēĐžŅ€ĐĩĐēŅ‚ĐŊŅ– даĐŊŅ–. + +Ви ĐŧĐžĐļĐĩŅ‚Đĩ ĐŋĐĩŅ€ĐĩвиСĐŊĐ°Ņ‡Đ¸Ņ‚Đ¸ ҆Җ ĐžĐąŅ€ĐžĐąĐŊиĐēи, ŅŅ‚Đ˛ĐžŅ€Đ¸Đ˛ŅˆĐ¸ вĐģĐ°ŅĐŊŅ–. + +### ПĐĩŅ€ĐĩвиСĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ ĐŋĐžĐŧиĐģĐžĐē ваĐģŅ–Đ´Đ°Ņ†Ņ–Ņ— СаĐŋĐ¸Ņ‚Ņƒ + +КоĐģи СаĐŋĐ¸Ņ‚ ĐŧŅ–ŅŅ‚Đ¸Ņ‚ŅŒ ĐŊĐĩĐēĐžŅ€ĐĩĐēŅ‚ĐŊŅ– даĐŊŅ–, **FastAPI** ĐŗĐĩĐŊĐĩŅ€ŅƒŅ” `RequestValidationError`. + +І Ņ‚Đ°ĐēĐžĐļ вĐēĐģŅŽŅ‡Đ°Ņ” ĐžĐąŅ€ĐžĐąĐŊиĐē ĐŋĐžĐŧиĐģĐžĐē Са СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ Đ´ĐģŅ ĐŊŅŒĐžĐŗĐž. + +ЊОй ĐŋĐĩŅ€ĐĩвиСĐŊĐ°Ņ‡Đ¸Ņ‚Đ¸ ĐšĐžĐŗĐž, Ņ–ĐŧĐŋĐžŅ€Ņ‚ŅƒĐšŅ‚Đĩ `RequestValidationError` Ņ– виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐšŅ‚Đĩ ĐšĐžĐŗĐž С `@app.exception_handler(RequestValidationError)` Đ´ĐģŅ Đ´ĐĩĐēĐžŅ€ŅƒĐ˛Đ°ĐŊĐŊŅ ĐžĐąŅ€ĐžĐąĐŊиĐēа ĐŋĐžĐŧиĐģĐžĐē. + +ĐžĐąŅ€ĐžĐąĐŊиĐē ĐŋĐžĐŧиĐģĐžĐē ĐžŅ‚Ņ€Đ¸ĐŧŅƒŅ” `Request` Ņ– ŅĐ°Đŧ҃ ĐŋĐžĐŧиĐģĐē҃. + +{* ../../docs_src/handling_errors/tutorial004.py hl[2,14:16] *} + +ĐĸĐĩĐŋĐĩŅ€, ŅĐēŅ‰Đž Ви ĐŋĐĩŅ€ĐĩКдĐĩŅ‚Đĩ Са ĐŋĐžŅĐ¸ĐģаĐŊĐŊŅĐŧ `/items/foo`, СаĐŧŅ–ŅŅ‚ŅŒ Ņ‚ĐžĐŗĐž, Ņ‰ĐžĐą ĐžŅ‚Ņ€Đ¸ĐŧĐ°Ņ‚Đ¸ ŅŅ‚Đ°ĐŊĐ´Đ°Ņ€Ņ‚ĐŊ҃ JSON-ĐŋĐžĐŧиĐģĐē҃: + +```JSON +{ + "detail": [ + { + "loc": [ + "path", + "item_id" + ], + "msg": "value is not a valid integer", + "type": "type_error.integer" + } + ] +} +``` + +Ви ĐžŅ‚Ņ€Đ¸ĐŧĐ°Ņ”Ņ‚Đĩ Ņ‚ĐĩĐēŅŅ‚ĐžĐ˛Ņƒ вĐĩŅ€ŅŅ–ŅŽ: + +``` +1 validation error +path -> item_id + value is not a valid integer (type=type_error.integer) +``` + +#### `RequestValidationError` ĐŋŅ€ĐžŅ‚Đ¸ `ValidationError` + +/// warning | ĐŖĐ˛Đ°ĐŗĐ° + +ĐĻĐĩ Ņ‚ĐĩŅ…ĐŊҖ҇ĐŊŅ– Đ´ĐĩŅ‚Đ°ĐģŅ–, ŅĐēŅ– Ви ĐŧĐžĐļĐĩŅ‚Đĩ ĐŋŅ€ĐžĐŋŅƒŅŅ‚Đ¸Ņ‚Đ¸, ŅĐēŅ‰Đž вОĐŊи ĐˇĐ°Ņ€Đ°Đˇ ĐŊĐĩ ваĐļĐģĐ¸Đ˛Ņ– Đ´ĐģŅ Đ’Đ°Ņ. + +/// + +`RequestValidationError` Ņ” ĐŋŅ–Đ´ĐēĐģĐ°ŅĐžĐŧ Pydantic `ValidationError`. + +**FastAPI** виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅ” ĐšĐžĐŗĐž Đ´ĐģŅ Ņ‚ĐžĐŗĐž, ŅĐēŅ‰Đž Ви виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅ”Ņ‚Đĩ ĐŧОдĐĩĐģҌ Pydantic ҃ `response_model` Ņ– ҃ Đ˛Đ°ŅˆĐ¸Ņ… даĐŊĐ¸Ņ… Ņ” ĐŋĐžĐŧиĐģĐēа, Ви ĐŋĐžĐąĐ°Ņ‡Đ¸Đģи ĐŋĐžĐŧиĐģĐē҃ ҃ ŅĐ˛ĐžŅ”Đŧ҃ ĐļŅƒŅ€ĐŊаĐģŅ–. + +АĐģĐĩ ĐēĐģŅ–Ņ”ĐŊŅ‚/ĐēĐžŅ€Đ¸ŅŅ‚ŅƒĐ˛Đ°Ņ‡ ĐŊĐĩ ĐŋĐžĐąĐ°Ņ‡Đ¸Ņ‚ŅŒ Ņ—Ņ—. ĐĐ°Ņ‚ĐžĐŧŅ–ŅŅ‚ŅŒ ĐēĐģŅ–Ņ”ĐŊŅ‚ ĐžŅ‚Ņ€Đ¸ĐŧĐ°Ņ” "Internal Server Error" ĐˇŅ– ŅŅ‚Đ°Ņ‚ŅƒŅĐžĐŧ HTTP `500`. + +ĐĸаĐē ĐŧĐ°Ņ” ĐąŅƒŅ‚Đ¸, ŅĐēŅ‰Đž ҃ Đ’Đ°Ņ виĐŊиĐēĐģа `ValidationError` Pydantic ҃ *Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´Ņ–* айО Đ´ĐĩŅ–ĐŊĐ´Đĩ ҃ Đ˛Đ°ŅˆĐžĐŧ҃ ĐēĐžĐ´Ņ– (ĐŊĐĩ ҃ *СаĐŋĐ¸Ņ‚Ņ–* ĐēĐģŅ–Ņ”ĐŊŅ‚Đ°), ҆Đĩ ĐŊĐ°ŅĐŋŅ€Đ°Đ˛Đ´Ņ– Ņ” ĐŋĐžĐŧиĐģĐēĐžŅŽ ҃ Đ’Đ°ŅˆĐžĐŧ҃ ĐēĐžĐ´Ņ–. + +І ĐŋĐžĐēи Ви Ņ—Ņ— виĐŋŅ€Đ°Đ˛ĐģŅŅ”Ņ‚Đĩ, ĐēĐģŅ–Ņ”ĐŊŅ‚Đ¸/ĐēĐžŅ€Đ¸ŅŅ‚ŅƒĐ˛Đ°Ņ‡Ņ– ĐŊĐĩ ĐŋОвиĐŊĐŊŅ– ĐŧĐ°Ņ‚Đ¸ Đ´ĐžŅŅ‚ŅƒĐŋ҃ Đ´Đž вĐŊŅƒŅ‚Ņ€Ņ–ŅˆĐŊŅŒĐžŅ— Ņ–ĐŊŅ„ĐžŅ€ĐŧĐ°Ņ†Ņ–Ņ— ĐŋŅ€Đž ĐŋĐžĐŧиĐģĐē҃, ĐžŅĐēŅ–ĐģҌĐēи ҆Đĩ ĐŧĐžĐļĐĩ ĐŋŅ€Đ¸ĐˇĐ˛ĐĩŅŅ‚Đ¸ Đ´Đž Đ˛Ņ€Đ°ĐˇĐģĐ¸Đ˛ĐžŅŅ‚Ņ– ĐąĐĩСĐŋĐĩĐēи. + +### ПĐĩŅ€ĐĩвиСĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ ĐžĐąŅ€ĐžĐąĐŊиĐēа ĐŋĐžĐŧиĐģĐžĐē `HTTPException` + +АĐŊаĐģĐžĐŗŅ–Ņ‡ĐŊĐž, Ви ĐŧĐžĐļĐĩŅ‚Đĩ ĐŋĐĩŅ€ĐĩвиСĐŊĐ°Ņ‡Đ¸Ņ‚Đ¸ ĐžĐąŅ€ĐžĐąĐŊиĐē `HTTPException`. + +НаĐŋŅ€Đ¸ĐēĐģад, Ви ĐŧĐžĐļĐĩŅ‚Đĩ ĐˇĐ°Ņ…ĐžŅ‚Ņ–Ņ‚Đ¸ ĐŋОвĐĩŅ€ĐŊŅƒŅ‚Đ¸ Ņ‚ĐĩĐēŅŅ‚ĐžĐ˛Ņƒ Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´ŅŒ СаĐŧŅ–ŅŅ‚ŅŒ JSON Đ´ĐģŅ Ņ†Đ¸Ņ… ĐŋĐžĐŧиĐģĐžĐē: + +{* ../../docs_src/handling_errors/tutorial004.py hl[3:4,9:11,22] *} + +/// note | ĐĸĐĩŅ…ĐŊҖ҇ĐŊŅ– Đ´ĐĩŅ‚Đ°ĐģŅ– + +Ви Ņ‚Đ°ĐēĐžĐļ ĐŧĐžĐļĐĩŅ‚Đĩ виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ `from starlette.responses import PlainTextResponse`. + +**FastAPI** ĐŊĐ°Đ´Đ°Ņ” ҂Җ ŅĐ°ĐŧŅ– `starlette.responses`, Ņ‰Đž Đš `fastapi.responses`, ĐŋŅ€ĐžŅŅ‚Đž Đ´ĐģŅ ĐˇŅ€ŅƒŅ‡ĐŊĐžŅŅ‚Ņ– Ņ€ĐžĐˇŅ€ĐžĐąĐŊиĐēа. АĐģĐĩ ĐąŅ–ĐģŅŒŅˆŅ–ŅŅ‚ŅŒ Đ´ĐžŅŅ‚ŅƒĐŋĐŊĐ¸Ņ… Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´ĐĩĐš ĐŊĐ°Đ´Ņ…ĐžĐ´ŅŅ‚ŅŒ ĐąĐĩСĐŋĐžŅĐĩŅ€ĐĩĐ´ĐŊŅŒĐž ĐˇŅ– Starlette. + +/// + +### ВиĐēĐžŅ€Đ¸ŅŅ‚Đ°ĐŊĐŊŅ ҂ҖĐģа `RequestValidationError` + +`RequestValidationError` ĐŧŅ–ŅŅ‚Đ¸Ņ‚ŅŒ `body`, ŅĐēиК Đ˛Ņ–ĐŊ ĐžŅ‚Ņ€Đ¸Đŧав Ņ–Đˇ ĐŊĐĩĐēĐžŅ€ĐĩĐēŅ‚ĐŊиĐŧи даĐŊиĐŧи. + +Ви ĐŧĐžĐļĐĩŅ‚Đĩ виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ ҆Đĩ ĐŋŅ–Đ´ Ņ‡Đ°Ņ Ņ€ĐžĐˇŅ€ĐžĐąĐēи ŅĐ˛ĐžĐŗĐž Đ´ĐžĐ´Đ°Ņ‚Đēа, Ņ‰ĐžĐą ĐģĐžĐŗŅƒĐ˛Đ°Ņ‚Đ¸ ҂ҖĐģĐž СаĐŋĐ¸Ņ‚Ņƒ Ņ‚Đ° ĐŊаĐģĐ°ĐŗĐžĐ´ĐļŅƒĐ˛Đ°Ņ‚Đ¸ ĐšĐžĐŗĐž, ĐŋОвĐĩŅ€Ņ‚Đ°Ņ‚Đ¸ ĐēĐžŅ€Đ¸ŅŅ‚ŅƒĐ˛Đ°Ņ‡ĐĩĐ˛Ņ– Ņ‚ĐžŅ‰Đž. + +{* ../../docs_src/handling_errors/tutorial005.py hl[14] *} + +ĐĸĐĩĐŋĐĩŅ€ ҁĐŋŅ€ĐžĐąŅƒĐšŅ‚Đĩ ĐŊĐ°Đ´Ņ–ŅĐģĐ°Ņ‚Đ¸ ĐŊĐĩĐēĐžŅ€ĐĩĐēŅ‚ĐŊиК ĐĩĐģĐĩĐŧĐĩĐŊŅ‚, ĐŊаĐŋŅ€Đ¸ĐēĐģад: + +```JSON +{ + "title": "towel", + "size": "XL" +} +``` +Ви ĐžŅ‚Ņ€Đ¸ĐŧĐ°Ņ”Ņ‚Đĩ Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´ŅŒ, ŅĐēа ĐŋĐžĐ˛Ņ–Đ´ĐžĐŧĐ¸Ņ‚ŅŒ ВаĐŧ, ŅĐēŅ– ŅĐ°ĐŧĐĩ даĐŊŅ– Ņ” ĐŊĐĩĐēĐžŅ€ĐĩĐēŅ‚ĐŊŅ– ҃ Đ˛Đ°ŅˆĐžĐŧ҃ ҂ҖĐģŅ– СаĐŋĐ¸Ņ‚Ņƒ: + + +```JSON hl_lines="12-15" +{ + "detail": [ + { + "loc": [ + "body", + "size" + ], + "msg": "value is not a valid integer", + "type": "type_error.integer" + } + ], + "body": { + "title": "towel", + "size": "XL" + } +} +``` + +#### `HTTPException` FastAPI ĐŋŅ€ĐžŅ‚Đ¸ `HTTPException` Starlette + +**FastAPI** ĐŧĐ°Ņ” вĐģĐ°ŅĐŊиК `HTTPException`. + +І ĐēĐģĐ°Ņ ĐŋĐžĐŧиĐģĐēи `HTTPException` в **FastAPI** ҃ҁĐŋадĐēĐžĐ˛ŅƒŅ”Ņ‚ŅŒŅŅ Đ˛Ņ–Đ´ ĐēĐģĐ°ŅŅƒ ĐŋĐžĐŧиĐģĐēи `HTTPException` в Starlette. + +ЄдиĐŊа Ņ€Ņ–ĐˇĐŊĐ¸Ņ†Ņ ĐŋĐžĐģŅĐŗĐ°Ņ” в Ņ‚ĐžĐŧ҃, Ņ‰Đž `HTTPException` в **FastAPI** ĐŋŅ€Đ¸ĐšĐŧĐ°Ņ” ĐąŅƒĐ´ŅŒ-ŅĐēŅ– даĐŊŅ–, ŅĐēŅ– ĐŧĐžĐļĐŊа ĐŋĐĩŅ€ĐĩŅ‚Đ˛ĐžŅ€Đ¸Ņ‚Đ¸ ĐŊа JSON, Đ´ĐģŅ ĐŋĐžĐģŅ `detail`, Ņ‚ĐžĐ´Ņ– ŅĐē `HTTPException` ҃ Starlette ĐŋŅ€Đ¸ĐšĐŧĐ°Ņ” ҂ҖĐģҌĐēи Ņ€ŅĐ´Đēи. + +ĐžŅ‚ĐļĐĩ, Ви ĐŧĐžĐļĐĩŅ‚Đĩ ĐŋŅ€ĐžĐ´ĐžĐ˛ĐļŅƒĐ˛Đ°Ņ‚Đ¸ виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ `HTTPException` в **FastAPI** ŅĐē ĐˇĐ°ĐˇĐ˛Đ¸Ņ‡Đ°Đš ҃ ŅĐ˛ĐžŅ”Đŧ҃ ĐēĐžĐ´Ņ–. + +АĐģĐĩ ĐēĐžĐģи Ви Ņ€ĐĩŅ”ŅŅ‚Ņ€ŅƒŅ”Ņ‚Đĩ ĐžĐąŅ€ĐžĐąĐŊиĐē виĐēĐģŅŽŅ‡ĐĩĐŊҌ, ҁĐģŅ–Đ´ Ņ€ĐĩŅ”ŅŅ‚Ņ€ŅƒĐ˛Đ°Ņ‚Đ¸ ĐšĐžĐŗĐž Đ´ĐģŅ `HTTPException` ĐˇŅ– Starlette. + +ĐĸаĐēиĐŧ Ņ‡Đ¸ĐŊĐžĐŧ, ŅĐēŅ‰Đž ĐąŅƒĐ´ŅŒ-ŅĐēа Ņ‡Đ°ŅŅ‚Đ¸ĐŊа вĐŊŅƒŅ‚Ņ€Ņ–ŅˆĐŊŅŒĐžĐŗĐž ĐēĐžĐ´Ņƒ Starlette айО Ņ€ĐžĐˇŅˆĐ¸Ņ€ĐĩĐŊĐŊŅ Ņ‡Đ¸ ĐŋĐģĐ°ĐŗŅ–ĐŊ Starlette ĐˇĐŗĐĩĐŊĐĩŅ€ŅƒŅ” (raise) `HTTPException`, Đ’Đ°Ņˆ ĐžĐąŅ€ĐžĐąĐŊиĐē СĐŧĐžĐļĐĩ ĐŋĐĩŅ€ĐĩŅ…ĐžĐŋĐ¸Ņ‚Đ¸ Ņ‚Đ° ĐžĐąŅ€ĐžĐąĐ¸Ņ‚Đ¸ Ņ—Ņ—. + +ĐŖ Ņ†ŅŒĐžĐŧ҃ ĐŋŅ€Đ¸ĐēĐģĐ°Đ´Ņ–, Ņ‰ĐžĐą ĐŧĐ°Ņ‚Đ¸ ĐŧĐžĐļĐģĐ¸Đ˛Ņ–ŅŅ‚ŅŒ виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ Ойидва `HTTPException` в ОдĐŊĐžĐŧ҃ ĐēĐžĐ´Ņ–, ĐŋĐžĐŧиĐģĐēа Starlette ĐŋĐĩŅ€ĐĩĐšĐŧĐĩĐŊĐžĐ˛ŅƒŅ”Ņ‚ŅŒŅŅ ĐŊа `StarletteHTTPException`: + +```Python +from starlette.exceptions import HTTPException as StarletteHTTPException +``` + +### ĐŸĐžĐ˛Ņ‚ĐžŅ€ĐŊĐĩ виĐēĐžŅ€Đ¸ŅŅ‚Đ°ĐŊĐŊŅ ĐžĐąŅ€ĐžĐąĐŊиĐēŅ–Đ˛ ĐŋĐžĐŧиĐģĐžĐē **FastAPI** + +Đ¯ĐēŅ‰Đž Ви Ņ…ĐžŅ‡ĐĩŅ‚Đĩ виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ ĐŋĐžĐŧиĐģĐēи Ņ€Đ°ĐˇĐžĐŧ Ņ–Đˇ Ņ‚Đ°ĐēиĐŧи Đļ ĐžĐąŅ€ĐžĐąĐŊиĐēаĐŧи ĐŋĐžĐŧиĐģĐžĐē Са СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ, ŅĐē ҃ **FastAPI**, Ви ĐŧĐžĐļĐĩŅ‚Đĩ Ņ–ĐŧĐŋĐžŅ€Ņ‚ŅƒĐ˛Đ°Ņ‚Đ¸ Ņ‚Đ° ĐŋĐžĐ˛Ņ‚ĐžŅ€ĐŊĐž виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ Ņ—Ņ… Ņ–Đˇ `fastapi.exception_handlers`: + +{* ../../docs_src/handling_errors/tutorial006.py hl[2:5,15,21] *} + +ĐŖ Ņ†ŅŒĐžĐŧ҃ ĐŋŅ€Đ¸ĐēĐģĐ°Đ´Ņ– Ви ĐŋŅ€ĐžŅŅ‚Đž виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅ”Ņ‚Đĩ `print` Đ´ĐģŅ вивĐĩĐ´ĐĩĐŊĐŊŅ Đ´ŅƒĐļĐĩ Ņ–ĐŊŅ„ĐžŅ€ĐŧĐ°Ņ‚Đ¸Đ˛ĐŊĐžĐŗĐž ĐŋĐžĐ˛Ņ–Đ´ĐžĐŧĐģĐĩĐŊĐŊŅ, аĐģĐĩ Ви ĐˇŅ€ĐžĐˇŅƒĐŧŅ–Đģи ĐžŅĐŊОвĐŊ҃ Ņ–Đ´ĐĩŅŽ. Ви ĐŧĐžĐļĐĩŅ‚Đĩ ĐžĐąŅ€ĐžĐąĐ¸Ņ‚Đ¸ ĐŋĐžĐŧиĐģĐē҃ Ņ‚Đ° ĐŋĐžĐ˛Ņ‚ĐžŅ€ĐŊĐž виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ ĐžĐąŅ€ĐžĐąĐŊиĐēи ĐŋĐžĐŧиĐģĐžĐē Са СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ. diff --git a/docs/uk/docs/tutorial/header-param-models.md b/docs/uk/docs/tutorial/header-param-models.md new file mode 100644 index 000000000..6f7b0bdae --- /dev/null +++ b/docs/uk/docs/tutorial/header-param-models.md @@ -0,0 +1,58 @@ +# МодĐĩĐģŅ– ĐŸĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Ņ–Đ˛ Đ—Đ°ĐŗĐžĐģОвĐēŅ–Đ˛ + +Đ¯ĐēŅ‰Đž ҃ Đ’Đ°Ņ Ņ” ĐŗŅ€ŅƒĐŋа ĐŋĐžĐ˛â€™ŅĐˇĐ°ĐŊĐ¸Ņ… ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Ņ–Đ˛ ĐˇĐ°ĐŗĐžĐģОвĐēŅ–Đ˛, Ви ĐŧĐžĐļĐĩŅ‚Đĩ ŅŅ‚Đ˛ĐžŅ€Đ¸Ņ‚Đ¸ **Pydantic ĐŧОдĐĩĐģҌ** Đ´ĐģŅ Ņ—Ņ… ĐžĐŗĐžĐģĐžŅˆĐĩĐŊĐŊŅ. + +ĐĻĐĩ дОСвОĐģĐ¸Ņ‚ŅŒ ВаĐŧ ĐŋĐžĐ˛Ņ‚ĐžŅ€ĐŊĐž **виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ ĐŧОдĐĩĐģҌ** в **Ņ€Ņ–ĐˇĐŊĐ¸Ņ… ĐŧŅ–ŅŅ†ŅŅ…**, а Ņ‚Đ°ĐēĐžĐļ ĐžĐŗĐžĐģĐžŅĐ¸Ņ‚Đ¸ ваĐģŅ–Đ´Đ°Ņ†Ņ–Ņ— Ņ‚Đ° ĐŧĐĩŅ‚Đ°Đ´Đ°ĐŊŅ– Đ´ĐģŅ Đ˛ŅŅ–Ņ… ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Ņ–Đ˛ ОдĐŊĐžŅ‡Đ°ŅĐŊĐž. 😎 + +/// note | ĐĐžŅ‚Đ°Ņ‚Đēи + +ĐĻŅ ĐŧĐžĐļĐģĐ¸Đ˛Ņ–ŅŅ‚ŅŒ ĐŋŅ–Đ´Ņ‚Ņ€Đ¸ĐŧŅƒŅ”Ņ‚ŅŒŅŅ ĐŋĐžŅ‡Đ¸ĐŊĐ°ŅŽŅ‡Đ¸ С вĐĩҀҁҖҗ FastAPI `0.115.0`. 🤓 + +/// + +## ĐŸĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ¸ Đ—Đ°ĐŗĐžĐģОвĐēŅ–Đ˛ С ВиĐēĐžŅ€Đ¸ŅŅ‚Đ°ĐŊĐŊŅĐŧ Pydantic Model + +ĐžĐŗĐžĐģĐžŅŅ–Ņ‚ŅŒ ĐŋĐžŅ‚Ņ€Ņ–ĐąĐŊŅ– **ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ¸ ĐˇĐ°ĐŗĐžĐģОвĐēŅ–Đ˛** ҃ **Pydantic ĐŧОдĐĩĐģŅ–**, а ĐŋĐžŅ‚Ņ–Đŧ ĐžĐŗĐžĐģĐžŅŅ–Ņ‚ŅŒ ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ ŅĐē `Header`: + +{* ../../docs_src/header_param_models/tutorial001_an_py310.py hl[9:14,18] *} + +FastAPI ĐąŅƒĐ´Đĩ Đ˛Đ¸Ņ‚ŅĐŗŅƒĐ˛Đ°Ņ‚Đ¸ даĐŊŅ– Đ´ĐģŅ ĐēĐžĐļĐŊĐžĐŗĐž ĐŋĐžĐģŅ С ĐˇĐ°ĐŗĐžĐģОвĐēŅ–Đ˛ ҃ СаĐŋĐ¸Ņ‚Ņ– Ņ‚Đ° ĐŋĐĩŅ€ĐĩĐ´Đ°Đ˛Đ°Ņ‚Đ¸ Ņ—Ņ… ҃ ŅŅ‚Đ˛ĐžŅ€ĐĩĐŊ҃ ВаĐŧи Pydantic ĐŧОдĐĩĐģҌ. + +**FastAPI** ĐąŅƒĐ´Đĩ **Đ˛Đ¸Ņ‚ŅĐŗŅƒĐ˛Đ°Ņ‚Đ¸** даĐŊŅ– Đ´ĐģŅ **ĐēĐžĐļĐŊĐžĐŗĐž ĐŋĐžĐģŅ** С **ĐˇĐ°ĐŗĐžĐģОвĐēŅ–Đ˛** ҃ СаĐŋĐ¸Ņ‚Ņ– Ņ‚Đ° ĐŋĐĩŅ€ĐĩĐ´Đ°Đ˛Đ°Ņ‚Đ¸ Ņ—Ņ… ҃ ŅŅ‚Đ˛ĐžŅ€ĐĩĐŊ҃ ВаĐŧи Pydantic ĐŧОдĐĩĐģҌ. + +## ПĐĩŅ€ĐĩĐ˛Ņ–Ņ€Đēа в ДоĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Ņ–Ņ— + +Ви ĐŧĐžĐļĐĩŅ‚Đĩ ĐŋĐžĐąĐ°Ņ‡Đ¸Ņ‚Đ¸ ĐŊĐĩĐžĐąŅ…Ņ–Đ´ĐŊŅ– ĐˇĐ°ĐŗĐžĐģОвĐēи в Ņ–ĐŊŅ‚ĐĩҀ҄ĐĩĐšŅŅ– Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Ņ–Ņ— Са Đ°Đ´Ņ€ĐĩŅĐžŅŽ `/docs`: + +
+ +
+ +## Đ—Đ°ĐąĐžŅ€ĐžĐŊа Đ”ĐžĐ´Đ°Ņ‚ĐēĐžĐ˛Đ¸Ņ… Đ—Đ°ĐŗĐžĐģОвĐēŅ–Đ˛ + +ĐŖ Đ´ĐĩŅĐēĐ¸Ņ… ĐžŅĐžĐąĐģĐ¸Đ˛Đ¸Ņ… виĐŋадĐēĐ°Ņ… (ĐšĐŧĐžĐ˛Ņ–Ņ€ĐŊĐž, ĐŊĐĩ Đ´ŅƒĐļĐĩ ĐŋĐžŅˆĐ¸Ņ€ĐĩĐŊĐ¸Ņ…) Ви ĐŧĐžĐļĐĩŅ‚Đĩ ĐˇĐ°Ņ…ĐžŅ‚Ņ–Ņ‚Đ¸ **ОйĐŧĐĩĐļĐ¸Ņ‚Đ¸** ĐˇĐ°ĐŗĐžĐģОвĐēи, ŅĐēŅ– Ņ…ĐžŅ‡ĐĩŅ‚Đĩ ĐžŅ‚Ņ€Đ¸ĐŧĐ°Ņ‚Đ¸. + +Ви ĐŧĐžĐļĐĩŅ‚Đĩ виĐēĐžŅ€Đ¸ŅŅ‚Đ°Ņ‚Đ¸ ĐēĐžĐŊŅ„Ņ–ĐŗŅƒŅ€Đ°Ņ†Ņ–ŅŽ ĐŧОдĐĩĐģŅ– Pydantic, Ņ‰ĐžĐą `ĐˇĐ°ĐąĐžŅ€ĐžĐŊĐ¸Ņ‚Đ¸` ĐąŅƒĐ´ŅŒ-ŅĐēŅ– `Đ´ĐžĐ´Đ°Ņ‚ĐēĐžĐ˛Ņ–` ĐŋĐžĐģŅ: + +{* ../../docs_src/header_param_models/tutorial002_an_py310.py hl[10] *} + +Đ¯ĐēŅ‰Đž ĐēĐģŅ–Ņ”ĐŊŅ‚ ҁĐŋŅ€ĐžĐąŅƒŅ” ĐŊĐ°Đ´Ņ–ŅĐģĐ°Ņ‚Đ¸ **Đ´ĐžĐ´Đ°Ņ‚ĐēĐžĐ˛Ņ– ĐˇĐ°ĐŗĐžĐģОвĐēи**, Đ˛Ņ–ĐŊ ĐžŅ‚Ņ€Đ¸ĐŧĐ°Ņ” **ĐŋĐžĐŧиĐģĐē҃** ҃ Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´Ņ–. + +НаĐŋŅ€Đ¸ĐēĐģад, ŅĐēŅ‰Đž ĐēĐģŅ–Ņ”ĐŊŅ‚ ҁĐŋŅ€ĐžĐąŅƒŅ” ĐŊĐ°Đ´Ņ–ŅĐģĐ°Ņ‚Đ¸ ĐˇĐ°ĐŗĐžĐģОвОĐē `tool` ĐˇŅ– СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅĐŧ `plumbus`, Đ˛Ņ–ĐŊ ĐžŅ‚Ņ€Đ¸ĐŧĐ°Ņ” **ĐŋĐžĐŧиĐģĐē҃** С ĐŋĐžĐ˛Ņ–Đ´ĐžĐŧĐģĐĩĐŊĐŊŅĐŧ ĐŋŅ€Đž Ņ‚Đĩ, Ņ‰Đž ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ ĐˇĐ°ĐŗĐžĐģОвĐēа `tool` ĐŊĐĩ дОСвОĐģĐĩĐŊиК: + +```json +{ + "detail": [ + { + "type": "extra_forbidden", + "loc": ["header", "tool"], + "msg": "Extra inputs are not permitted", + "input": "plumbus", + } + ] +} +``` + +## ĐŸŅ–Đ´ŅŅƒĐŧĐžĐē + +Ви ĐŧĐžĐļĐĩŅ‚Đĩ виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ **Pydantic ĐŧОдĐĩĐģŅ–** Đ´ĐģŅ ĐžĐŗĐžĐģĐžŅˆĐĩĐŊĐŊŅ **ĐˇĐ°ĐŗĐžĐģОвĐēŅ–Đ˛** ҃ **FastAPI**. 😎 diff --git a/docs/uk/docs/tutorial/header-params.md b/docs/uk/docs/tutorial/header-params.md new file mode 100644 index 000000000..09c70a4f6 --- /dev/null +++ b/docs/uk/docs/tutorial/header-params.md @@ -0,0 +1,91 @@ +# Header-ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ¸ + +Ви ĐŧĐžĐļĐĩŅ‚Đĩ виСĐŊĐ°Ņ‡Đ°Ņ‚Đ¸ ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ¸ ĐˇĐ°ĐŗĐžĐģОвĐēŅ–Đ˛, Ņ‚Đ°Đē ŅĐ°ĐŧĐž ŅĐē виСĐŊĐ°Ņ‡Đ°Ņ”Ņ‚Đĩ `Query`, `Path` Ņ– `Cookie` ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ¸. + +## ІĐŧĐŋĐžŅ€Ņ‚ `Header` + +ĐĄĐŋĐžŅ‡Đ°Ņ‚Đē҃ Ņ–ĐŧĐŋĐžŅ€Ņ‚ŅƒĐšŅ‚Đĩ `Header`: + +{* ../../docs_src/header_params/tutorial001_an_py310.py hl[3] *} + +## ĐžĐŗĐžĐģĐžŅˆĐĩĐŊĐŊŅ ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Ņ–Đ˛ `Header` + +ĐŸĐžŅ‚Ņ–Đŧ ĐžĐŗĐžĐģĐžŅŅ–Ņ‚ŅŒ ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ¸ ĐˇĐ°ĐŗĐžĐģОвĐēŅ–Đ˛, виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅŽŅ‡Đ¸ Ņ‚Ņƒ Đļ ŅŅ‚Ņ€ŅƒĐēŅ‚ŅƒŅ€Ņƒ, Ņ‰Đž Đš Đ´ĐģŅ `Path`, `Query` Ņ‚Đ° `Cookie`. + +Ви ĐŧĐžĐļĐĩŅ‚Đĩ виСĐŊĐ°Ņ‡Đ¸Ņ‚Đ¸ СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ Са СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ, а Ņ‚Đ°ĐēĐžĐļ ŅƒŅŅ– Đ´ĐžĐ´Đ°Ņ‚ĐēĐžĐ˛Ņ– ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ¸ ваĐģŅ–Đ´Đ°Ņ†Ņ–Ņ— айО аĐŊĐžŅ‚Đ°Ņ†Ņ–Ņ—: + +{* ../../docs_src/header_params/tutorial001_an_py310.py hl[9] *} + +/// note | ĐĸĐĩŅ…ĐŊҖ҇ĐŊŅ– Đ´ĐĩŅ‚Đ°ĐģŅ– + +`Header`Ņ” "ҁĐĩŅŅ‚Ņ€Đ¸ĐŊҁҌĐēиĐŧ" ĐēĐģĐ°ŅĐžĐŧ Đ´ĐģŅ `Path`, `Query` Ņ– `Cookie`. Đ’Ņ–ĐŊ Ņ‚Đ°ĐēĐžĐļ ҃ҁĐŋадĐēĐžĐ˛ŅƒŅ”Ņ‚ŅŒŅŅ Đ˛Ņ–Đ´ ĐˇĐ°ĐŗĐ°ĐģҌĐŊĐžĐŗĐž ĐēĐģĐ°ŅŅƒ `Param`. + +АĐģĐĩ ĐŋаĐŧâ€™ŅŅ‚Đ°ĐšŅ‚Đĩ, Ņ‰Đž ĐŋŅ€Đ¸ Ņ–ĐŧĐŋĐžŅ€Ņ‚Ņ– `Query`, `Path`, `Header` Ņ‚Đ° Ņ–ĐŊŅˆĐ¸Ņ… Ņ–Đˇ `fastapi`, Ņ‚Đž ĐŊĐ°ŅĐŋŅ€Đ°Đ˛Đ´Ņ– вОĐŊи Ņ” Ņ„ŅƒĐŊĐēŅ†Ņ–ŅĐŧи, ŅĐēŅ– ĐŋОвĐĩŅ€Ņ‚Đ°ŅŽŅ‚ŅŒ ҁĐŋĐĩŅ†Ņ–Đ°ĐģҌĐŊŅ– ĐēĐģĐ°ŅĐ¸. + +/// + +/// info | ІĐŊŅ„ĐžŅ€ĐŧĐ°Ņ†Ņ–Ņ + +ЊОй ĐžĐŗĐžĐģĐžŅĐ¸Ņ‚Đ¸ ĐˇĐ°ĐŗĐžĐģОвĐēи, ĐŋĐžŅ‚Ņ€Ņ–ĐąĐŊĐž виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ `Header`, Ņ–ĐŊаĐē҈Đĩ ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ¸ ĐąŅƒĐ´ŅƒŅ‚ŅŒ Ņ–ĐŊŅ‚ĐĩŅ€ĐŋŅ€ĐĩŅ‚ŅƒĐ˛Đ°Ņ‚Đ¸ŅŅ ŅĐē ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ¸ СаĐŋĐ¸Ņ‚Ņƒ. + +/// + +## ĐĐ˛Ņ‚ĐžĐŧĐ°Ņ‚Đ¸Ņ‡ĐŊĐĩ ĐŋĐĩŅ€ĐĩŅ‚Đ˛ĐžŅ€ĐĩĐŊĐŊŅ + +`Header` ĐŧĐ°Ņ” Đ´ĐžĐ´Đ°Ņ‚ĐēОвиК Ņ„ŅƒĐŊĐēŅ†Ņ–ĐžĐŊаĐģ ĐŋĐžŅ€Ņ–Đ˛ĐŊŅĐŊĐž С `Path`, `Query` Ņ‚Đ° `Cookie`. + +Đ‘Ņ–ĐģŅŒŅˆŅ–ŅŅ‚ŅŒ ŅŅ‚Đ°ĐŊĐ´Đ°Ņ€Ņ‚ĐŊĐ¸Ņ… ĐˇĐ°ĐŗĐžĐģОвĐēŅ–Đ˛ Ņ€ĐžĐˇĐ´Ņ–ĐģŅŅŽŅ‚ŅŒŅŅ ŅĐ¸ĐŧвОĐģĐžĐŧ ÂĢĐ´Đĩ҄ҖҁÂģ, Ņ‚Đ°ĐēĐžĐļ Đ˛Ņ–Đ´ĐžĐŧиĐŧ ŅĐē ÂĢĐŧŅ–ĐŊ҃ҁÂģ (`-`). + +АĐģĐĩ СĐŧŅ–ĐŊĐŊа, Ņ‚Đ°Đēа ŅĐē `user-agent`, Ņ” ĐŊĐĩĐ´Ņ–ĐšŅĐŊĐžŅŽ в Python. + +ĐĸĐžĐŧ҃, Са СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ, `Header` Đ°Đ˛Ņ‚ĐžĐŧĐ°Ņ‚Đ¸Ņ‡ĐŊĐž ĐŋĐĩŅ€ĐĩŅ‚Đ˛ĐžŅ€ŅŽŅ” ŅĐ¸ĐŧвОĐģи ĐŋŅ–Đ´ĐēŅ€ĐĩҁĐģĐĩĐŊĐŊŅ (`_`) ĐŊа Đ´ĐĩŅ„Ņ–ŅĐ¸ (`-`) Đ´ĐģŅ ĐžŅ‚Ņ€Đ¸ĐŧаĐŊĐŊŅ Ņ‚Đ° Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚ŅƒĐ˛Đ°ĐŊĐŊŅ ĐˇĐ°ĐŗĐžĐģОвĐēŅ–Đ˛. + +ĐžŅĐēŅ–ĐģҌĐēи ĐˇĐ°ĐŗĐžĐģОвĐēи HTTP ĐŊĐĩ Ņ‡ŅƒŅ‚ĐģĐ¸Đ˛Ņ– Đ´Đž Ņ€ĐĩĐŗŅ–ŅŅ‚Ņ€Ņƒ, Ви ĐŧĐžĐļĐĩŅ‚Đĩ виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ ŅŅ‚Đ°ĐŊĐ´Đ°Ņ€Ņ‚ĐŊиК ŅŅ‚Đ¸ĐģҌ Python ("snake_case"). + +ĐĸĐžĐŧ҃ Ви ĐŧĐžĐļĐĩŅ‚Đĩ виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ `user_agent`, ŅĐē ĐˇĐ°ĐˇĐ˛Đ¸Ņ‡Đ°Đš ҃ ĐēĐžĐ´Ņ– Python, СаĐŧŅ–ŅŅ‚ŅŒ Ņ‚ĐžĐŗĐž Ņ‰ĐžĐą ĐŋĐ¸ŅĐ°Ņ‚Đ¸ С вĐĩĐģиĐēĐžŅ— ĐģŅ–Ņ‚ĐĩŅ€Đ¸, ŅĐē `User_Agent` айО Ņ‰ĐžŅŅŒ ĐŋĐžĐ´Ņ–ĐąĐŊĐĩ. + +Đ¯ĐēŅ‰Đž ВаĐŧ ĐŋĐžŅ‚Ņ€Ņ–ĐąĐŊĐž виĐŧĐēĐŊŅƒŅ‚Đ¸ Đ°Đ˛Ņ‚ĐžĐŧĐ°Ņ‚Đ¸Ņ‡ĐŊĐĩ ĐŋĐĩŅ€ĐĩŅ‚Đ˛ĐžŅ€ĐĩĐŊĐŊŅ ĐŋŅ–Đ´ĐēŅ€ĐĩҁĐģĐĩĐŊҌ ҃ Đ´ĐĩŅ„Ņ–ŅĐ¸, Đ˛ŅŅ‚Đ°ĐŊĐžĐ˛Ņ–Ņ‚ŅŒ `convert_underscores` в `Header` СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ `False`: + +{* ../../docs_src/header_params/tutorial002_an_py310.py hl[10] *} + +/// warning | ĐŖĐ˛Đ°ĐŗĐ° + +ПĐĩŅ€ĐĩĐ´ Ņ‚Đ¸Đŧ ŅĐē Đ˛ŅŅ‚Đ°ĐŊĐžĐ˛Đ¸Ņ‚Đ¸ СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ `False` Đ´ĐģŅ `convert_underscores` ĐŋаĐŧâ€™ŅŅ‚Đ°ĐšŅ‚Đĩ, Ņ‰Đž Đ´ĐĩŅĐēŅ– HTTP-ĐŋŅ€ĐžĐēҁҖ Ņ‚Đ° ҁĐĩŅ€Đ˛ĐĩŅ€Đ¸ ĐŊĐĩ ĐŋŅ–Đ´Ņ‚Ņ€Đ¸ĐŧŅƒŅŽŅ‚ŅŒ ĐˇĐ°ĐŗĐžĐģОвĐēи С ĐŋŅ–Đ´ĐēŅ€ĐĩҁĐģĐĩĐŊĐŊŅĐŧи. + +/// + +## Đ”ŅƒĐąĐģŅŒĐžĐ˛Đ°ĐŊŅ– ĐˇĐ°ĐŗĐžĐģОвĐēи + +МоĐļĐģивО ĐžŅ‚Ņ€Đ¸ĐŧĐ°Ņ‚Đ¸ Đ´ŅƒĐąĐģŅŒĐžĐ˛Đ°ĐŊŅ– ĐˇĐ°ĐŗĐžĐģОвĐēи, Ņ‚ĐžĐąŅ‚Đž Ņ‚ĐžĐš ŅĐ°ĐŧиК ĐˇĐ°ĐŗĐžĐģОвОĐē Ņ–Đˇ ĐēŅ–ĐģҌĐēĐžĐŧа СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅĐŧи. + +ĐĻĐĩ ĐŧĐžĐļĐŊа виСĐŊĐ°Ņ‡Đ¸Ņ‚Đ¸, виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅŽŅ‡Đ¸ ҁĐŋĐ¸ŅĐžĐē ҃ Ņ‚Đ¸ĐŋŅ–ĐˇĐ°Ņ†Ņ–Ņ— ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ°. + +Ви ĐžŅ‚Ņ€Đ¸ĐŧĐ°Ņ”Ņ‚Đĩ Đ˛ŅŅ– СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ Đ´ŅƒĐąĐģŅŒĐžĐ˛Đ°ĐŊĐžĐŗĐž ĐˇĐ°ĐŗĐžĐģОвĐēа ҃ Đ˛Đ¸ĐŗĐģŅĐ´Ņ– `list` ҃ Python. + +НаĐŋŅ€Đ¸ĐēĐģад, Ņ‰ĐžĐą ĐžĐŗĐžĐģĐžŅĐ¸Ņ‚Đ¸ ĐˇĐ°ĐŗĐžĐģОвОĐē `X-Token`, ŅĐēиК ĐŧĐžĐļĐĩ Đˇâ€™ŅĐ˛ĐģŅŅ‚Đ¸ŅŅ ĐąŅ–ĐģҌ҈Đĩ ĐŊŅ–Đļ ОдиĐŊ Ņ€Đ°Đˇ: + +{* ../../docs_src/header_params/tutorial003_an_py310.py hl[9] *} + +Đ¯ĐēŅ‰Đž Ви Đ˛ĐˇĐ°Ņ”ĐŧĐžĐ´Ņ–Ņ”Ņ‚Đĩ С Ņ†Ņ–Ņ”ŅŽ ĐžĐŋĐĩŅ€Đ°Ņ†Ņ–Ņ”ŅŽ ҈ĐģŅŅ…Ņƒ, ĐŊĐ°Đ´ŅĐ¸ĐģĐ°ŅŽŅ‡Đ¸ два HTTP-ĐˇĐ°ĐŗĐžĐģОвĐēи, ĐŊаĐŋŅ€Đ¸ĐēĐģад: + +``` +X-Token: foo +X-Token: bar +``` + +Đ’Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´ŅŒ ĐąŅƒĐ´Đĩ Ņ‚Đ°Đēа: + +```JSON +{ + "X-Token values": [ + "bar", + "foo" + ] +} +``` + +## ĐŸŅ–Đ´ŅŅƒĐŧĐžĐē + +ĐžĐŗĐžĐģĐžŅˆŅƒĐšŅ‚Đĩ ĐˇĐ°ĐŗĐžĐģОвĐēи Са Đ´ĐžĐŋĐžĐŧĐžĐŗĐžŅŽ `Header`, виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅŽŅ‡Đ¸ Ņ‚ĐžĐš ŅĐ°ĐŧиК ĐŋŅ–Đ´Ņ…Ņ–Đ´, Ņ‰Đž Đš Đ´ĐģŅ `Query`, `Path` Ņ‚Đ° `Cookie`. + +НĐĩ Ņ…Đ˛Đ¸ĐģŅŽĐšŅ‚ĐĩŅŅ ĐŋŅ€Đž ĐŋŅ–Đ´ĐēŅ€ĐĩҁĐģĐĩĐŊĐŊŅ ҃ СĐŧŅ–ĐŊĐŊĐ¸Ņ… — **FastAPI** Đ°Đ˛Ņ‚ĐžĐŧĐ°Ņ‚Đ¸Ņ‡ĐŊĐž ĐēĐžĐŊвĐĩŅ€Ņ‚ŅƒŅ” Ņ—Ņ…. diff --git a/docs/uk/docs/tutorial/metadata.md b/docs/uk/docs/tutorial/metadata.md new file mode 100644 index 000000000..64e667ec6 --- /dev/null +++ b/docs/uk/docs/tutorial/metadata.md @@ -0,0 +1,120 @@ +# МĐĩŅ‚Đ°Đ´Đ°ĐŊŅ– Ņ‚Đ° URL-Đ°Đ´Ņ€ĐĩŅĐ¸ Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Ņ–Ņ— + +Ви ĐŧĐžĐļĐĩŅ‚Đĩ ĐŊаĐģĐ°ŅˆŅ‚ŅƒĐ˛Đ°Ņ‚Đ¸ ĐēŅ–ĐģҌĐēа ĐēĐžĐŊŅ„Ņ–ĐŗŅƒŅ€Đ°Ņ†Ņ–Đš ĐŧĐĩŅ‚Đ°Đ´Đ°ĐŊĐ¸Ņ… ҃ Đ’Đ°ŅˆĐžĐŧ҃ Đ´ĐžĐ´Đ°Ņ‚Đē҃ **FastAPI**. + +## МĐĩŅ‚Đ°Đ´Đ°ĐŊŅ– Đ´ĐģŅ API + +Ви ĐŧĐžĐļĐĩŅ‚Đĩ Đ˛ŅŅ‚Đ°ĐŊĐžĐ˛Đ¸Ņ‚Đ¸ Ņ‚Đ°ĐēŅ– ĐŋĐžĐģŅ, ŅĐēŅ– виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅŽŅ‚ŅŒŅŅ в ҁĐŋĐĩŅ†Đ¸Ņ„Ņ–ĐēĐ°Ņ†Ņ–Ņ— OpenAPI Ņ‚Đ° в Đ°Đ˛Ņ‚ĐžĐŧĐ°Ņ‚Đ¸Ņ‡ĐŊĐž ĐˇĐŗĐĩĐŊĐĩŅ€ĐžĐ˛Đ°ĐŊĐ¸Ņ… Ņ–ĐŊŅ‚ĐĩҀ҄ĐĩĐšŅĐ°Ņ… Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Ņ–Ņ— API: + +| ĐŸĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ | ĐĸиĐŋ | ОĐŋĐ¸Ņ | +|------------|------|-------------| +| `title` | `str` | Назва API. | +| `summary` | `str` | ĐšĐžŅ€ĐžŅ‚ĐēиК ĐžĐŋĐ¸Ņ API. Đ”ĐžŅŅ‚ŅƒĐŋĐŊĐž С OpenAPI 3.1.0, FastAPI 0.99.0. | +| `description` | `str` | Đ‘Ņ–ĐģҌ҈ Đ´ĐĩŅ‚Đ°ĐģҌĐŊиК ĐžĐŋĐ¸Ņ API. МоĐļĐĩ виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ Markdown. | +| `version` | `string` | ВĐĩŅ€ŅŅ–Ņ API. ĐĻĐĩ вĐĩŅ€ŅŅ–Ņ Đ’Đ°ŅˆĐžĐŗĐž Đ´ĐžĐ´Đ°Ņ‚Đēа, а ĐŊĐĩ OpenAPI. НаĐŋŅ€Đ¸ĐēĐģад, `2.5.0`. | +| `terms_of_service` | `str` | URL Đ´Đž ҃ĐŧОв виĐēĐžŅ€Đ¸ŅŅ‚Đ°ĐŊĐŊŅ API. Đ¯ĐēŅ‰Đž вĐēаСаĐŊĐž, ĐŧĐ°Ņ” ĐąŅƒŅ‚Đ¸ ҃ Ņ„ĐžŅ€ĐŧĐ°Ņ‚Ņ– URL. | +| `contact` | `dict` | ІĐŊŅ„ĐžŅ€ĐŧĐ°Ņ†Ņ–Ņ Đ´ĐģŅ ĐēĐžĐŊŅ‚Đ°ĐēŅ‚Ņƒ С API. МоĐļĐĩ ĐŧŅ–ŅŅ‚Đ¸Ņ‚Đ¸ ĐēŅ–ĐģҌĐēа ĐŋĐžĐģŅ–Đ˛.
contact ĐŋĐžĐģŅ
ĐŸĐ°Ņ€Đ°ĐŧĐĩ҂ҀĐĸиĐŋОĐŋĐ¸Ņ
namestrІĐŧ'Ņ ĐēĐžĐŊŅ‚Đ°ĐēŅ‚ĐŊĐžŅ— ĐžŅĐžĐąĐ¸ айО ĐžŅ€ĐŗĐ°ĐŊŅ–ĐˇĐ°Ņ†Ņ–Ņ—.
urlstrURL С Ņ–ĐŊŅ„ĐžŅ€ĐŧĐ°Ņ†Ņ–Ņ”ŅŽ Đ´ĐģŅ ĐēĐžĐŊŅ‚Đ°ĐēŅ‚Ņƒ. ПовиĐŊĐĩĐŊ ĐąŅƒŅ‚Đ¸ ҃ Ņ„ĐžŅ€ĐŧĐ°Ņ‚Ņ– URL.
emailstrEmail ĐēĐžĐŊŅ‚Đ°ĐēŅ‚ĐŊĐžŅ— ĐžŅĐžĐąĐ¸ айО ĐžŅ€ĐŗĐ°ĐŊŅ–ĐˇĐ°Ņ†Ņ–Ņ—. ПовиĐŊĐĩĐŊ ĐąŅƒŅ‚Đ¸ ҃ Ņ„ĐžŅ€ĐŧĐ°Ņ‚Ņ– ĐĩĐģĐĩĐēŅ‚Ņ€ĐžĐŊĐŊĐžŅ— ĐŋĐžŅˆŅ‚Đ¸.
| +| `license_info` | `dict` | ІĐŊŅ„ĐžŅ€ĐŧĐ°Ņ†Ņ–Ņ ĐŋŅ€Đž ĐģҖ҆ĐĩĐŊĐˇŅ–ŅŽ Đ´ĐģŅ API. МоĐļĐĩ ĐŧŅ–ŅŅ‚Đ¸Ņ‚Đ¸ ĐēŅ–ĐģҌĐēа ĐŋĐžĐģŅ–Đ˛.
license_info ĐŋĐžĐģŅ
ĐŸĐ°Ņ€Đ°ĐŧĐĩ҂ҀĐĸиĐŋОĐŋĐ¸Ņ
namestrОБОВ'Đ¯Đ—ĐšĐžĐ’Đž (ŅĐēŅ‰Đž Đ˛ŅŅ‚Đ°ĐŊОвĐģĐĩĐŊĐž license_info). Назва ĐģҖ҆ĐĩĐŊĐˇŅ–Ņ— Đ´ĐģŅ API.
identifierstrĐ›Ņ–Ņ†ĐĩĐŊĐˇŅ–ĐšĐŊиК Đ˛Đ¸Ņ€Đ°Đˇ Са SPDX Đ´ĐģŅ API. ПоĐģĐĩ identifier Đ˛ĐˇĐ°Ņ”ĐŧОвиĐēĐģŅŽŅ‡ĐŊĐĩ С ĐŋĐžĐģĐĩĐŧ url. Đ”ĐžŅŅ‚ŅƒĐŋĐŊĐž С OpenAPI 3.1.0, FastAPI 0.99.0.
urlstrURL Đ´Đž ĐģҖ҆ĐĩĐŊĐˇŅ–Ņ—, ŅĐēа виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅ”Ņ‚ŅŒŅŅ Đ´ĐģŅ API. ПовиĐŊĐĩĐŊ ĐąŅƒŅ‚Đ¸ ҃ Ņ„ĐžŅ€ĐŧĐ°Ņ‚Ņ– URL.
| + +Ви ĐŧĐžĐļĐĩŅ‚Đĩ ĐŊаĐģĐ°ŅˆŅ‚ŅƒĐ˛Đ°Ņ‚Đ¸ Ņ—Ņ… ĐŊĐ°ŅŅ‚ŅƒĐŋĐŊиĐŧ Ņ‡Đ¸ĐŊĐžĐŧ: + +{* ../../docs_src/metadata/tutorial001.py hl[3:16, 19:32] *} + +/// tip | ĐŸŅ–Đ´ĐēаСĐēа + +ĐŖ ĐŋĐžĐģŅ– `description` ĐŧĐžĐļĐŊа виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ Markdown, Ņ– Đ˛Ņ–ĐŊ ĐąŅƒĐ´Đĩ Đ˛Ņ–Đ´ĐžĐąŅ€Đ°ĐļĐ°Ņ‚Đ¸ŅŅ ҃ Ņ€ĐĩĐˇŅƒĐģŅŒŅ‚Đ°Ņ‚Ņ–. + +/// + +З Ņ†Ņ–Ņ”ŅŽ ĐēĐžĐŊŅ„Ņ–ĐŗŅƒŅ€Đ°Ņ†Ņ–Ņ”ŅŽ Đ°Đ˛Ņ‚ĐžĐŧĐ°Ņ‚Đ¸Ņ‡ĐŊа Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Ņ–Ņ API Đ˛Đ¸ĐŗĐģŅĐ´Đ°Ņ‚Đ¸ĐŧĐĩ Ņ‚Đ°Đē: + + + +## ІдĐĩĐŊŅ‚Đ¸Ņ„Ņ–ĐēĐ°Ņ‚ĐžŅ€ ĐģҖ҆ĐĩĐŊĐˇŅ–Ņ— + +З ĐŋĐžŅ‡Đ°Ņ‚Đē҃ виĐēĐžŅ€Đ¸ŅŅ‚Đ°ĐŊĐŊŅ OpenAPI 3.1.0 Ņ‚Đ° FastAPI 0.99.0 Ви Ņ‚Đ°ĐēĐžĐļ ĐŧĐžĐļĐĩŅ‚Đĩ ĐŊаĐģĐ°ŅˆŅ‚ŅƒĐ˛Đ°Ņ‚Đ¸ `license_info` Са Đ´ĐžĐŋĐžĐŧĐžĐŗĐžŅŽ `identifier` СаĐŧŅ–ŅŅ‚ŅŒ `url`. + +НаĐŋŅ€Đ¸ĐēĐģад: + +{* ../../docs_src/metadata/tutorial001_1.py hl[31] *} + +## МĐĩŅ‚Đ°Đ´Đ°ĐŊŅ– Đ´ĐģŅ Ņ‚ĐĩĐŗŅ–Đ˛ + +Ви Ņ‚Đ°ĐēĐžĐļ ĐŧĐžĐļĐĩŅ‚Đĩ Đ´ĐžĐ´Đ°Ņ‚Đ¸ Đ´ĐžĐ´Đ°Ņ‚ĐēĐžĐ˛Ņ– ĐŧĐĩŅ‚Đ°Đ´Đ°ĐŊŅ– Đ´ĐģŅ Ņ€Ņ–ĐˇĐŊĐ¸Ņ… Ņ‚ĐĩĐŗŅ–Đ˛, ŅĐēŅ– виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅŽŅ‚ŅŒŅŅ Đ´ĐģŅ ĐŗŅ€ŅƒĐŋŅƒĐ˛Đ°ĐŊĐŊŅ ĐžĐŋĐĩŅ€Đ°Ņ†Ņ–Đš ҈ĐģŅŅ…Ņ–Đ˛, Са Đ´ĐžĐŋĐžĐŧĐžĐŗĐžŅŽ ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ° `openapi_tags`. + +Đ’Ņ–ĐŊ ĐŋŅ€Đ¸ĐšĐŧĐ°Ņ” ҁĐŋĐ¸ŅĐžĐē, ŅĐēиК ĐŧŅ–ŅŅ‚Đ¸Ņ‚ŅŒ ОдиĐŊ ҁĐģОвĐŊиĐē Đ´ĐģŅ ĐēĐžĐļĐŊĐžĐŗĐž Ņ‚ĐĩĐŗĐ°. + +КоĐļĐĩĐŊ ҁĐģОвĐŊиĐē ĐŧĐžĐļĐĩ ĐŧŅ–ŅŅ‚Đ¸Ņ‚Đ¸: + +* `name` (**ОйОв'ŅĐˇĐēОвО**): `str` С Ņ‚Ņ–Ņ”ŅŽ Đļ ĐŊĐ°ĐˇĐ˛ĐžŅŽ Ņ‚ĐĩĐŗŅƒ, ŅĐē҃ Ви виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅ”Ņ‚Đĩ ҃ ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂ҀҖ `tags` ҃ Đ’Đ°ŅˆĐ¸Ņ… *ĐžĐŋĐĩŅ€Đ°Ņ†Ņ–ŅŅ… ҈ĐģŅŅ…Ņƒ* Ņ‚Đ° `APIRouter`s. +* `description`: `str` С ĐēĐžŅ€ĐžŅ‚ĐēиĐŧ ĐžĐŋĐ¸ŅĐžĐŧ Ņ‚ĐĩĐŗŅƒ. МоĐļĐĩ ĐŧŅ–ŅŅ‚Đ¸Ņ‚Đ¸ Markdown Ņ– ĐąŅƒĐ´Đĩ Đ˛Ņ–Đ´ĐžĐąŅ€Đ°ĐļĐĩĐŊĐž в Ņ–ĐŊŅ‚ĐĩҀ҄ĐĩĐšŅŅ– Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Ņ–Ņ—. +* `externalDocs`: `dict` ŅĐēиК ĐžĐŋĐ¸ŅŅƒŅ” СОвĐŊŅ–ŅˆĐŊŅŽ Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Ņ–ŅŽ С Ņ‚Đ°ĐēиĐŧи ĐŋĐžĐģŅĐŧи: + * `description`: `str` С ĐēĐžŅ€ĐžŅ‚ĐēиĐŧ ĐžĐŋĐ¸ŅĐžĐŧ СОвĐŊŅ–ŅˆĐŊŅŒĐžŅ— Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Ņ–Ņ—. + * `url` (**ОйОв'ŅĐˇĐēОвО**): `str`С URL-Đ°Đ´Ņ€ĐĩŅĐžŅŽ СОвĐŊŅ–ŅˆĐŊŅŒĐžŅ— Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Ņ–Ņ—. + +### ĐĄŅ‚Đ˛ĐžŅ€ĐĩĐŊĐŊŅ ĐŧĐĩŅ‚Đ°Đ´Đ°ĐŊĐ¸Ņ… Đ´ĐģŅ Ņ‚ĐĩĐŗŅ–Đ˛ + +ĐĄĐŋŅ€ĐžĐąŅƒĐšĐŧĐž ҆Đĩ ĐŊа ĐŋŅ€Đ¸ĐēĐģĐ°Đ´Ņ– С Ņ‚ĐĩĐŗĐ°Đŧи Đ´ĐģŅ `users` Ņ‚Đ° `items`. + +ĐĄŅ‚Đ˛ĐžŅ€Ņ–Ņ‚ŅŒ ĐŧĐĩŅ‚Đ°Đ´Đ°ĐŊŅ– Đ´ĐģŅ ŅĐ˛ĐžŅ—Ņ… Ņ‚ĐĩĐŗŅ–Đ˛ Ņ– ĐŋĐĩŅ€ĐĩĐ´Đ°ĐšŅ‚Đĩ Ņ—Ņ… ҃ ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ `openapi_tags`: + +{* ../../docs_src/metadata/tutorial004.py hl[3:16,18] *} + +ЗвĐĩŅ€ĐŊŅ–Ņ‚ŅŒ ŅƒĐ˛Đ°ĐŗŅƒ, Ņ‰Đž в ĐžĐŋĐ¸ŅĐ°Ņ… ĐŧĐžĐļĐŊа виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ Markdown, ĐŊаĐŋŅ€Đ¸ĐēĐģад, "login" ĐąŅƒĐ´Đĩ ĐŋĐžĐēаСаĐŊĐž ĐļĐ¸Ņ€ĐŊиĐŧ ŅˆŅ€Đ¸Ņ„Ņ‚ĐžĐŧ (**login**), а "fancy" ĐąŅƒĐ´Đĩ ĐŋĐžĐēаСаĐŊĐž ĐēŅƒŅ€ŅĐ¸Đ˛ĐžĐŧ (_fancy_). + +/// tip | ĐŸĐžŅ€Đ°Đ´Đ° + +НĐĩ ОйОв'ŅĐˇĐēОвО Đ´ĐžĐ´Đ°Đ˛Đ°Ņ‚Đ¸ ĐŧĐĩŅ‚Đ°Đ´Đ°ĐŊŅ– Đ´ĐģŅ Đ˛ŅŅ–Ņ… Ņ‚ĐĩĐŗŅ–Đ˛, ŅĐēŅ– Ви виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅ”Ņ‚Đĩ. + +/// + +### ВиĐēĐžŅ€Đ¸ŅŅ‚Đ°ĐŊĐŊŅ Ņ‚ĐĩĐŗŅ–Đ˛ + +ВиĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐšŅ‚Đĩ ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ `tags` ĐˇŅ– ŅĐ˛ĐžŅ—Đŧи *ĐžĐŋĐĩŅ€Đ°Ņ†Ņ–ŅĐŧи ҈ĐģŅŅ…Ņƒ* (Ņ– `APIRouter`) Đ´ĐģŅ ĐŋŅ€Đ¸ĐˇĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ Ņ—Ņ… Đ´Đž Ņ€Ņ–ĐˇĐŊĐ¸Ņ… Ņ‚ĐĩĐŗŅ–Đ˛: + +{* ../../docs_src/metadata/tutorial004.py hl[21,26] *} + +/// info | ІĐŊŅ„ĐžŅ€ĐŧĐ°Ņ†Ņ–Ņ + +ДĐĩŅ‚Đ°ĐģҌĐŊŅ–ŅˆĐĩ ĐŋŅ€Đž Ņ‚ĐĩĐŗĐ¸ Ņ‡Đ¸Ņ‚Đ°ĐšŅ‚Đĩ в Ņ€ĐžĐˇĐ´Ņ–ĐģŅ– [КоĐŊŅ„Ņ–ĐŗŅƒŅ€Đ°Ņ†Ņ–Ņ ҈ĐģŅŅ…Ņ–Đ˛ ĐžĐŋĐĩŅ€Đ°Ņ†Ņ–Đš](path-operation-configuration.md#tags){.internal-link target=_blank}. + +/// + +### ПĐĩŅ€ĐĩĐ˛Ņ–Ņ€Đēа Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Ņ–Ņ— + +Đ¯ĐēŅ‰Đž Ви ĐˇĐ°Ņ€Đ°Đˇ ĐŋĐĩŅ€ĐĩĐ˛Ņ–Ņ€Đ¸Ņ‚Đĩ Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Ņ–ŅŽ, вОĐŊа ĐŋĐžĐēаĐļĐĩ Đ˛ŅŅ– Đ´ĐžĐ´Đ°Ņ‚ĐēĐžĐ˛Ņ– ĐŧĐĩŅ‚Đ°Đ´Đ°ĐŊŅ–: + + + +### ĐŸĐžŅ€ŅĐ´ĐžĐē Ņ‚ĐĩĐŗŅ–Đ˛ + +ĐŸĐžŅ€ŅĐ´ĐžĐē ĐēĐžĐļĐŊĐžĐŗĐž ҁĐģОвĐŊиĐēа ĐŧĐĩŅ‚Đ°Đ´Đ°ĐŊĐ¸Ņ… Ņ‚ĐĩĐŗŅƒ Ņ‚Đ°ĐēĐžĐļ виСĐŊĐ°Ņ‡Đ°Ņ” ĐŋĐžŅ€ŅĐ´ĐžĐē Đ˛Ņ–Đ´ĐžĐąŅ€Đ°ĐļĐĩĐŊĐŊŅ в Ņ–ĐŊŅ‚ĐĩҀ҄ĐĩĐšŅŅ– Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Ņ–Ņ—. + +НаĐŋŅ€Đ¸ĐēĐģад, Ņ…ĐžŅ‡Đ° `users` Đŧав йи ĐšŅ‚Đ¸ ĐŋҖҁĐģŅ `items` в аĐģŅ„Đ°Đ˛Ņ–Ņ‚ĐŊĐžĐŧ҃ ĐŋĐžŅ€ŅĐ´Đē҃, Đ˛Ņ–ĐŊ Đ˛Ņ–Đ´ĐžĐąŅ€Đ°ĐļĐ°Ņ”Ņ‚ŅŒŅŅ ĐŋĐĩŅ€ĐĩĐ´ ĐŊиĐŧи, ĐžŅĐēŅ–ĐģҌĐēи Đŧи дОдаĐģи ĐšĐžĐŗĐž ĐŧĐĩŅ‚Đ°Đ´Đ°ĐŊŅ– ŅĐē ĐŋĐĩŅ€ŅˆĐ¸Đš ҁĐģОвĐŊиĐē ҃ ҁĐŋĐ¸ŅĐē҃. + +## URL Đ´ĐģŅ OpenAPI + +За СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ ҁ҅ĐĩĐŧа OpenAPI ĐŊĐ°Đ´Đ°Ņ”Ņ‚ŅŒŅŅ Са Đ°Đ´Ņ€ĐĩŅĐžŅŽ `/openapi.json`. + +АĐģĐĩ Ви ĐŧĐžĐļĐĩŅ‚Đĩ ĐŊаĐģĐ°ŅˆŅ‚ŅƒĐ˛Đ°Ņ‚Đ¸ ҆Đĩ Са Đ´ĐžĐŋĐžĐŧĐžĐŗĐžŅŽ ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ° `openapi_url`. + +НаĐŋŅ€Đ¸ĐēĐģад, Ņ‰ĐžĐą ĐŊаĐģĐ°ŅˆŅ‚ŅƒĐ˛Đ°Ņ‚Đ¸ ĐšĐžĐŗĐž ĐŊа `/api/v1/openapi.json`: + +{* ../../docs_src/metadata/tutorial002.py hl[3] *} + +Đ¯ĐēŅ‰Đž Ви Ņ…ĐžŅ‡ĐĩŅ‚Đĩ ĐŋОвĐŊŅ–ŅŅ‚ŅŽ виĐŧĐēĐŊŅƒŅ‚Đ¸ ҁ҅ĐĩĐŧ҃ OpenAPI, Ви ĐŧĐžĐļĐĩŅ‚Đĩ Đ˛ŅŅ‚Đ°ĐŊĐžĐ˛Đ¸Ņ‚Đ¸ `openapi_url=None`, ҆Đĩ Ņ‚Đ°ĐēĐžĐļ виĐŧĐēĐŊĐĩ Ņ–ĐŊŅ‚ĐĩҀ҄ĐĩĐšŅĐ¸ Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Ņ–Ņ—, ŅĐēŅ– Ņ—Ņ— виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅŽŅ‚ŅŒ. + +## URL-Đ°Đ´Ņ€ĐĩŅĐ¸ Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Ņ–Ņ— + +Ви ĐŧĐžĐļĐĩŅ‚Đĩ ĐŊаĐģĐ°ŅˆŅ‚ŅƒĐ˛Đ°Ņ‚Đ¸ два Ņ–ĐŊŅ‚ĐĩҀ҄ĐĩĐšŅĐ¸ ĐēĐžŅ€Đ¸ŅŅ‚ŅƒĐ˛Đ°Ņ‡Đ° Đ´ĐģŅ Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Ņ–Ņ—, ŅĐēŅ– вĐēĐģŅŽŅ‡ĐĩĐŊŅ–: + +* **Swagger UI**: Đ´ĐžŅŅ‚ŅƒĐŋĐŊиК Са Đ°Đ´Ņ€ĐĩŅĐžŅŽ `/docs`. + * Ви ĐŧĐžĐļĐĩŅ‚Đĩ СĐŧŅ–ĐŊĐ¸Ņ‚Đ¸ ĐšĐžĐŗĐž URL Са Đ´ĐžĐŋĐžĐŧĐžĐŗĐžŅŽ ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ° `docs_url`. + * Ви ĐŧĐžĐļĐĩŅ‚Đĩ виĐŧĐēĐŊŅƒŅ‚Đ¸ ĐšĐžĐŗĐž, Đ˛ŅŅ‚Đ°ĐŊĐžĐ˛Đ¸Đ˛ŅˆĐ¸ `docs_url=None`. +* **ReDoc**: Đ´ĐžŅŅ‚ŅƒĐŋĐŊиК Са Đ°Đ´Ņ€ĐĩŅĐžŅŽ `/redoc`. + * Ви ĐŧĐžĐļĐĩŅ‚Đĩ СĐŧŅ–ĐŊĐ¸Ņ‚Đ¸ ĐšĐžĐŗĐž URL Са Đ´ĐžĐŋĐžĐŧĐžĐŗĐžŅŽ ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ° `redoc_url`. + * Ви ĐŧĐžĐļĐĩŅ‚Đĩ виĐŧĐēĐŊŅƒŅ‚Đ¸ ĐšĐžĐŗĐž, Đ˛ŅŅ‚Đ°ĐŊĐžĐ˛Đ¸Đ˛ŅˆĐ¸ `redoc_url=None`. + +НаĐŋŅ€Đ¸ĐēĐģад, Ņ‰ĐžĐą ĐŊаĐģĐ°ŅˆŅ‚ŅƒĐ˛Đ°Ņ‚Đ¸ Swagger UI ĐŊа `/documentation` Ņ– виĐŧĐēĐŊŅƒŅ‚Đ¸ ReDoc: + +{* ../../docs_src/metadata/tutorial003.py hl[3] *} diff --git a/docs/uk/docs/tutorial/middleware.md b/docs/uk/docs/tutorial/middleware.md new file mode 100644 index 000000000..807be484a --- /dev/null +++ b/docs/uk/docs/tutorial/middleware.md @@ -0,0 +1,75 @@ +# Middleware (ĐŸŅ€ĐžĐŧŅ–ĐļĐŊиК ŅˆĐ°Ņ€) + +ĐŖ **FastAPI** ĐŧĐžĐļĐŊа Đ´ĐžĐ´Đ°Đ˛Đ°Ņ‚Đ¸ middleware (ĐŋŅ€ĐžĐŧŅ–ĐļĐŊиК ŅˆĐ°Ņ€). + +"Middleware" — ҆Đĩ Ņ„ŅƒĐŊĐēŅ†Ņ–Ņ, ŅĐēа ĐŋŅ€Đ°Ņ†ŅŽŅ” С ĐēĐžĐļĐŊиĐŧ **СаĐŋĐ¸Ņ‚ĐžĐŧ** ĐŋĐĩŅ€ĐĩĐ´ ĐšĐžĐŗĐž ĐžĐąŅ€ĐžĐąĐēĐžŅŽ ĐąŅƒĐ´ŅŒ-ŅĐēĐžŅŽ ĐēĐžĐŊĐēŅ€ĐĩŅ‚ĐŊĐžŅŽ *ĐžĐŋĐĩŅ€Đ°Ņ†Ņ–Ņ”ŅŽ ҈ĐģŅŅ…Ņƒ* (*path operation*), а Ņ‚Đ°ĐēĐžĐļ С ĐēĐžĐļĐŊĐžŅŽ **Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´Đ´ŅŽ** ĐŋĐĩŅ€ĐĩĐ´ Ņ—Ņ— ĐŋОвĐĩŅ€ĐŊĐĩĐŊĐŊŅĐŧ. + +* Middleware ĐžŅ‚Ņ€Đ¸ĐŧŅƒŅ” ĐēĐžĐļĐĩĐŊ **СаĐŋĐ¸Ņ‚**, Ņ‰Đž ĐŊĐ°Đ´Ņ…ĐžĐ´Đ¸Ņ‚ŅŒ Đ´Đž Đ’Đ°ŅˆĐžĐŗĐž ĐˇĐ°ŅŅ‚ĐžŅŅƒĐŊĐē҃. +* МоĐļĐĩ виĐēĐžĐŊĐ°Ņ‚Đ¸ ĐŋĐĩвĐŊŅ– Đ´Ņ–Ņ— Ņ–Đˇ Ņ†Đ¸Đŧ **СаĐŋĐ¸Ņ‚ĐžĐŧ** айО СаĐŋŅƒŅŅ‚Đ¸Ņ‚Đ¸ ĐŊĐĩĐžĐąŅ…Ņ–Đ´ĐŊиК ĐēОд. +* ДаĐģŅ– ĐŋĐĩŅ€ĐĩĐ´Đ°Ņ” **СаĐŋĐ¸Ņ‚** Đ´ĐģŅ ĐžĐąŅ€ĐžĐąĐēи ĐžŅĐŊОвĐŊиĐŧ ĐˇĐ°ŅŅ‚ĐžŅŅƒĐŊĐēĐžĐŧ (*ĐžĐŋĐĩŅ€Đ°Ņ†Ņ–Ņ”ŅŽ ҈ĐģŅŅ…Ņƒ*). +* ĐžŅ‚Ņ€Đ¸ĐŧŅƒŅ” **Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´ŅŒ**, ŅŅ„ĐžŅ€ĐŧОваĐŊ҃ ĐˇĐ°ŅŅ‚ĐžŅŅƒĐŊĐēĐžĐŧ (*ĐžĐŋĐĩŅ€Đ°Ņ†Ņ–Ņ”ŅŽ ҈ĐģŅŅ…Ņƒ*). +* МоĐļĐĩ СĐŧŅ–ĐŊĐ¸Ņ‚Đ¸ Ņ†ŅŽ **Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´ŅŒ** айО виĐēĐžĐŊĐ°Ņ‚Đ¸ Đ´ĐžĐ´Đ°Ņ‚ĐēОвиК ĐēОд. +* ПовĐĩŅ€Ņ‚Đ°Ņ” **Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´ŅŒ** ĐēĐģŅ–Ņ”ĐŊŅ‚Ņƒ. + +/// note | ĐĸĐĩŅ…ĐŊҖ҇ĐŊŅ– Đ´ĐĩŅ‚Đ°ĐģŅ– + +Đ¯ĐēŅ‰Đž ҃ Đ’Đ°Ņ Ņ” СаĐģĐĩĐļĐŊĐžŅŅ‚Ņ– С `yield`, ĐēОд Đ˛Đ¸Ņ…ĐžĐ´Ņƒ виĐēĐžĐŊĐ°Ņ”Ņ‚ŅŒŅŅ *ĐŋҖҁĐģŅ* middleware. + +Đ¯ĐēŅ‰Đž ĐąŅƒĐģи СаĐŋĐģаĐŊОваĐŊŅ– Ņ„ĐžĐŊĐžĐ˛Ņ– ĐˇĐ°Đ´Đ°Ņ‡Ņ– (background tasks - Ņ€ĐžĐˇĐŗĐģŅĐŊŅƒŅ‚Đž даĐģŅ–), вОĐŊи виĐēĐžĐŊĐ°ŅŽŅ‚ŅŒŅŅ *ĐŋҖҁĐģŅ* Đ˛ŅŅ–Ņ… middleware. + +/// + +## ĐĄŅ‚Đ˛ĐžŅ€ĐĩĐŊĐŊŅ middleware + +ЊОй ŅŅ‚Đ˛ĐžŅ€Đ¸Ņ‚Đ¸ middleware, Ви виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅ”Ņ‚Đĩ Đ´ĐĩĐēĐžŅ€Đ°Ņ‚ĐžŅ€ `@app.middleware("http")` ĐŊа Ņ„ŅƒĐŊĐē҆Җҗ. + +Đ¤ŅƒĐŊĐēŅ†Ņ–Ņ middleware ĐžŅ‚Ņ€Đ¸ĐŧŅƒŅ”: + +* `ЗаĐŋĐ¸Ņ‚`. +* Đ¤ŅƒĐŊĐēŅ†Ņ–ŅŽ `call_next`, ŅĐēа ĐŋŅ€Đ¸ĐšĐŧĐ°Ņ” `СаĐŋĐ¸Ņ‚` ŅĐē ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ. + * ĐĻŅ Ņ„ŅƒĐŊĐēŅ†Ņ–Ņ ĐŋĐĩŅ€ĐĩĐ´Đ°Ņ” `СаĐŋĐ¸Ņ‚` Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´ĐŊŅ–Đš *ĐžĐŋĐĩŅ€Đ°Ņ†Ņ–Ņ— ҈ĐģŅŅ…Ņƒ*. + * ĐŸĐžŅ‚Ņ–Đŧ вОĐŊа ĐŋОвĐĩŅ€Ņ‚Đ°Ņ” `Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´ŅŒ`, ĐˇĐŗĐĩĐŊĐĩŅ€ĐžĐ˛Đ°ĐŊ҃ Ņ†Ņ–Ņ”ŅŽ *ĐžĐŋĐĩŅ€Đ°Ņ†Ņ–Ņ”ŅŽ ҈ĐģŅŅ…Ņƒ*. + +* Ви ĐŧĐžĐļĐĩŅ‚Đĩ ҉Đĩ СĐŧŅ–ĐŊĐ¸Ņ‚Đ¸ `Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´ŅŒ` ĐŋĐĩŅ€ĐĩĐ´ Ņ‚Đ¸Đŧ, ŅĐē ĐŋОвĐĩŅ€ĐŊŅƒŅ‚Đ¸ Ņ—Ņ—. + + +{* ../../docs_src/middleware/tutorial001.py hl[8:9,11,14] *} + +/// tip | ĐŸĐžŅ€Đ°Đ´Đ° + +НĐĩ ĐˇĐ°ĐąŅƒĐ˛Đ°ĐšŅ‚Đĩ, Ņ‰Đž вĐģĐ°ŅĐŊŅ– ĐˇĐ°ĐŗĐžĐģОвĐēи ĐŧĐžĐļĐŊа Đ´ĐžĐ´Đ°Đ˛Đ°Ņ‚Đ¸, виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅŽŅ‡Đ¸ ĐŋŅ€Đĩ҄ҖĐēҁ 'X-'. + +АĐģĐĩ ŅĐēŅ‰Đž ҃ Đ’Đ°Ņ Ņ” вĐģĐ°ŅĐŊŅ– ĐˇĐ°ĐŗĐžĐģОвĐēи, ŅĐēŅ– Ви Ņ…ĐžŅ‡ĐĩŅ‚Đĩ, Ņ‰ĐžĐą ĐąŅ€Đ°ŅƒĐˇĐĩŅ€ĐŊиК ĐēĐģŅ–Ņ”ĐŊŅ‚ ĐŧŅ–Đŗ ĐŋĐžĐąĐ°Ņ‡Đ¸Ņ‚Đ¸, ĐŋĐžŅ‚Ņ€Ņ–ĐąĐŊĐž Đ´ĐžĐ´Đ°Ņ‚Đ¸ Ņ—Ņ… Đ´Đž Đ’Đ°ŅˆĐžŅ— ĐēĐžĐŊŅ„Ņ–ĐŗŅƒŅ€Đ°Ņ†Ņ–Ņ— CORS (див. [CORS (ОбĐŧŅ–ĐŊ Ņ€ĐĩŅŅƒŅ€ŅĐ°Đŧи ĐŧŅ–Đļ Ņ€Ņ–ĐˇĐŊиĐŧи Đ´ĐļĐĩŅ€ĐĩĐģаĐŧи)](cors.md){.internal-link target=_blank} Са Đ´ĐžĐŋĐžĐŧĐžĐŗĐžŅŽ ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ° `expose_headers`, ĐžĐŋĐ¸ŅĐ°ĐŊĐžĐŗĐž в Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Ņ–Ņ— Starlette ĐŋĐž CORS. + +/// + +/// note | ĐĸĐĩŅ…ĐŊҖ҇ĐŊŅ– Đ´ĐĩŅ‚Đ°ĐģŅ– + +Ви Ņ‚Đ°ĐēĐžĐļ ĐŧĐžĐļĐĩŅ‚Đĩ виĐēĐžŅ€Đ¸ŅŅ‚Đ°Ņ‚Đ¸ `from starlette.requests import Request`. + +**FastAPI** ĐŊĐ°Đ´Đ°Ņ” ҆Đĩ Đ´ĐģŅ Đ’Đ°ŅˆĐžŅ— ĐˇŅ€ŅƒŅ‡ĐŊĐžŅŅ‚Ņ– ŅĐē Ņ€ĐžĐˇŅ€ĐžĐąĐŊиĐēа. АĐģĐĩ Đ˛Ņ–ĐŊ ĐŋĐžŅ…ĐžĐ´Đ¸Ņ‚ŅŒ ĐąĐĩСĐŋĐžŅĐĩŅ€ĐĩĐ´ĐŊŅŒĐž ĐˇŅ– Starlette. + +/// + +### До Ņ– ĐŋҖҁĐģŅ `response`(`Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´Ņ–`) + +Ви ĐŧĐžĐļĐĩŅ‚Đĩ Đ´ĐžĐ´Đ°Ņ‚Đ¸ ĐēОд, ŅĐēиК ĐąŅƒĐ´Đĩ виĐēĐžĐŊŅƒĐ˛Đ°Ņ‚Đ¸ŅŅ С `СаĐŋĐ¸Ņ‚ĐžĐŧ` (`request`), Đ´Đž Ņ‚ĐžĐŗĐž, ŅĐē ĐšĐžĐŗĐž ĐžĐąŅ€ĐžĐąĐ¸Ņ‚ŅŒ ĐąŅƒĐ´ŅŒ-ŅĐēа *ĐžĐŋĐĩŅ€Đ°Ņ†Ņ–Ņ ҈ĐģŅŅ…Ņƒ* (*path operation*). + +ĐĸаĐēĐžĐļ Ви ĐŧĐžĐļĐĩŅ‚Đĩ Đ´ĐžĐ´Đ°Ņ‚Đ¸ ĐēОд, ŅĐēиК ĐąŅƒĐ´Đĩ виĐēĐžĐŊŅƒĐ˛Đ°Ņ‚Đ¸ŅŅ ĐŋҖҁĐģŅ Ņ‚ĐžĐŗĐž, ŅĐē `Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´ŅŒ` (`response`) ĐąŅƒĐ´Đĩ ĐˇĐŗĐĩĐŊĐĩŅ€ĐžĐ˛Đ°ĐŊĐž, ĐŋĐĩŅ€ĐĩĐ´ Ņ‚Đ¸Đŧ ŅĐē ĐšĐžĐŗĐž ĐŋОвĐĩŅ€ĐŊŅƒŅ‚Đ¸. + +НаĐŋŅ€Đ¸ĐēĐģад, Ви ĐŧĐžĐļĐĩŅ‚Đĩ Đ´ĐžĐ´Đ°Ņ‚Đ¸ вĐģĐ°ŅĐŊиК ĐˇĐ°ĐŗĐžĐģОвОĐē `X-Process-Time`, ŅĐēиК ĐŧŅ–ŅŅ‚Đ¸Ņ‚Đ¸ĐŧĐĩ Ņ‡Đ°Ņ ҃ ҁĐĩĐē҃ĐŊĐ´Đ°Ņ…, ŅĐēиК Đ˛Đ¸Ņ‚Ņ€Đ°Ņ‚Đ¸Đ˛ŅŅ ĐŊа ĐžĐąŅ€ĐžĐąĐē҃ СаĐŋĐ¸Ņ‚Ņƒ Ņ‚Đ° ĐŗĐĩĐŊĐĩŅ€Đ°Ņ†Ņ–ŅŽ Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´Ņ–: + +{* ../../docs_src/middleware/tutorial001.py hl[10,12:13] *} + + +/// tip | ĐŸŅ–Đ´ĐēаСĐēа + +ĐĸŅƒŅ‚ Đŧи виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅ”ĐŧĐž `time.perf_counter()` СаĐŧŅ–ŅŅ‚ŅŒ `time.time()` ĐžŅĐēŅ–ĐģҌĐēи Đ˛Ņ–ĐŊ ĐŧĐžĐļĐĩ ĐąŅƒŅ‚Đ¸ ĐąŅ–ĐģҌ҈ Ņ‚ĐžŅ‡ĐŊиĐŧ Đ´ĐģŅ Ņ‚Đ°ĐēĐ¸Ņ… виĐŋадĐēŅ–Đ˛. 🤓 + +/// + +## ІĐŊŅˆŅ– middlewares + +Ви ĐŧĐžĐļĐĩŅ‚Đĩ ĐŋŅ–ĐˇĐŊŅ–ŅˆĐĩ ĐŋŅ€ĐžŅ‡Đ¸Ņ‚Đ°Ņ‚Đ¸ ĐąŅ–ĐģҌ҈Đĩ ĐŋŅ€Đž Ņ–ĐŊŅˆŅ– middlewares в [Advanced User Guide: Advanced Middleware](../advanced/middleware.md){.internal-link target=_blank}. + +Ви Đ´Ņ–ĐˇĐŊĐ°Ņ”Ņ‚ĐĩҁҌ, ŅĐē ĐžĐąŅ€ĐžĐąĐģŅŅ‚Đ¸ CORS Са Đ´ĐžĐŋĐžĐŧĐžĐŗĐžŅŽ middleware в ĐŊĐ°ŅŅ‚ŅƒĐŋĐŊĐžĐŧ҃ Ņ€ĐžĐˇĐ´Ņ–ĐģŅ–. diff --git a/docs/uk/docs/tutorial/path-params-numeric-validations.md b/docs/uk/docs/tutorial/path-params-numeric-validations.md new file mode 100644 index 000000000..281ee183c --- /dev/null +++ b/docs/uk/docs/tutorial/path-params-numeric-validations.md @@ -0,0 +1,165 @@ +# Path ĐŸĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ¸ Ņ‚Đ° ваĐģŅ–Đ´Đ°Ņ†Ņ–Ņ Ņ‡Đ¸ŅĐģĐžĐ˛Đ¸Ņ… даĐŊĐ¸Ņ… + +ĐĸаĐē ŅĐ°ĐŧĐž ŅĐē Ви ĐŧĐžĐļĐĩŅ‚Đĩ ĐžĐŗĐžĐģĐžŅˆŅƒĐ˛Đ°Ņ‚Đ¸ Đ´ĐžĐ´Đ°Ņ‚ĐēĐžĐ˛Ņ– ĐŋĐĩŅ€ĐĩĐ˛Ņ–Ņ€Đēи Ņ‚Đ° ĐŧĐĩŅ‚Đ°Đ´Đ°ĐŊŅ– Đ´ĐģŅ query ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Ņ–Đ˛ Са Đ´ĐžĐŋĐžĐŧĐžĐŗĐžŅŽ `Query`, Ви ĐŧĐžĐļĐĩŅ‚Đĩ ĐžĐŗĐžĐģĐžŅˆŅƒĐ˛Đ°Ņ‚Đ¸ Ņ‚ĐžĐš ŅĐ°ĐŧиК Ņ‚Đ¸Đŋ ĐŋĐĩŅ€ĐĩĐ˛Ņ–Ņ€ĐžĐē Ņ– ĐŧĐĩŅ‚Đ°Đ´Đ°ĐŊĐ¸Ņ… Đ´ĐģŅ ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Ņ–Đ˛ ҈ĐģŅŅ…Ņƒ Са Đ´ĐžĐŋĐžĐŧĐžĐŗĐžŅŽ `Path`. + +## ІĐŧĐŋĐžŅ€Ņ‚ Path + +ĐĄĐŋĐžŅ‡Đ°Ņ‚Đē҃ Ņ–ĐŧĐŋĐžŅ€Ņ‚ŅƒĐšŅ‚Đĩ `Path` С `fastapi` Ņ– Ņ–ĐŧĐŋĐžŅ€Ņ‚ŅƒĐšŅ‚Đĩ `Annotated`: + +{* ../../docs_src/path_params_numeric_validations/tutorial001_an_py310.py hl[1,3] *} + +/// info | ІĐŊŅ„ĐžŅ€ĐŧĐ°Ņ†Ņ–Ņ + +FastAPI дОдав ĐŋŅ–Đ´Ņ‚Ņ€Đ¸ĐŧĐē҃ `Annotated` (Ņ– ĐŋĐžŅ‡Đ°Đ˛ Ņ€ĐĩĐēĐžĐŧĐĩĐŊĐ´ŅƒĐ˛Đ°Ņ‚Đ¸ ĐšĐžĐŗĐž виĐēĐžŅ€Đ¸ŅŅ‚Đ°ĐŊĐŊŅ) ҃ вĐĩҀҁҖҗ 0.95.0. + +Đ¯ĐēŅ‰Đž ҃ Đ’Đ°Ņ ŅŅ‚Đ°Ņ€Đ° вĐĩŅ€ŅŅ–Ņ, ĐŋŅ€Đ¸ ҁĐŋŅ€ĐžĐąŅ– виĐēĐžŅ€Đ¸ŅŅ‚Đ°Ņ‚Đ¸ `Annotated` ĐŧĐžĐļŅƒŅ‚ŅŒ виĐŊиĐēĐ°Ņ‚Đ¸ ĐŋĐžĐŧиĐģĐēи. + +ПĐĩŅ€ĐĩĐēĐžĐŊĐ°ĐšŅ‚ĐĩŅŅ, Ņ‰Đž Ви [ĐžĐŊОвиĐģи вĐĩŅ€ŅŅ–ŅŽ FastAPI](../deployment/versions.md#upgrading-the-fastapi-versions){.internal-link target=_blank} ĐŋŅ€Đ¸ĐŊаКĐŧĐŊŅ– Đ´Đž вĐĩҀҁҖҗ 0.95.1 ĐŋĐĩŅ€ĐĩĐ´ виĐēĐžŅ€Đ¸ŅŅ‚Đ°ĐŊĐŊŅĐŧ `Annotated`. + +/// + +## ĐžĐŗĐžĐģĐžŅˆĐĩĐŊĐŊŅ ĐŧĐĩŅ‚Đ°Đ´Đ°ĐŊĐ¸Ņ… + +Ви ĐŧĐžĐļĐĩŅ‚Đĩ ĐžĐŗĐžĐģĐžŅˆŅƒĐ˛Đ°Ņ‚Đ¸ Đ˛ŅŅ– ҂Җ Đļ ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ¸, Ņ‰Đž Ņ– Đ´ĐģŅ `Query`. + +НаĐŋŅ€Đ¸ĐēĐģад, Ņ‰ĐžĐą ĐžĐŗĐžĐģĐžŅĐ¸Ņ‚Đ¸ СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ ĐŧĐĩŅ‚Đ°Đ´Đ°ĐŊĐ¸Ņ… `title` Đ´ĐģŅ ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ° ҈ĐģŅŅ…Ņƒ `item_id`, Ви ĐŧĐžĐļĐĩŅ‚Đĩ ĐŊаĐŋĐ¸ŅĐ°Ņ‚Đ¸: + +{* ../../docs_src/path_params_numeric_validations/tutorial001_an_py310.py hl[10] *} + +/// note | ĐŸŅ€Đ¸ĐŧŅ–Ņ‚Đēа + +ĐŸĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ ҈ĐģŅŅ…Ņƒ СавĐļди Ņ” ĐžĐąĐžĐ˛â€™ŅĐˇĐēОвиĐŧ, ĐžŅĐēŅ–ĐģҌĐēи Đ˛Ņ–ĐŊ ĐŧĐ°Ņ” ĐąŅƒŅ‚Đ¸ Ņ‡Đ°ŅŅ‚Đ¸ĐŊĐžŅŽ ҈ĐģŅŅ…Ņƒ. ĐĐ°Đ˛Ņ–Ņ‚ŅŒ ŅĐēŅ‰Đž Ви ĐžĐŗĐžĐģĐžŅĐ¸Ņ‚Đĩ ĐšĐžĐŗĐž ĐˇŅ– СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅĐŧ `None` айО Đ˛ŅŅ‚Đ°ĐŊĐžĐ˛Đ¸Ņ‚Đĩ СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ Са СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ — Đ˛Ņ–ĐŊ Đ˛ŅĐĩ ОдĐŊĐž СаĐģĐ¸ŅˆĐ°Ņ‚Đ¸ĐŧĐĩŅ‚ŅŒŅŅ ĐžĐąĐžĐ˛â€™ŅĐˇĐēОвиĐŧ. + +/// + +## ĐŖĐŋĐžŅ€ŅĐ´ĐēĐžĐ˛ŅƒĐšŅ‚Đĩ ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ¸, ŅĐē ВаĐŧ ĐŋĐžŅ‚Ņ€Ņ–ĐąĐŊĐž + +/// tip | ĐŸŅ–Đ´ĐēаСĐēа + +ĐĻĐĩ, ĐŧĐ°ĐąŅƒŅ‚ŅŒ, ĐŊĐĩ ĐŊĐ°ŅŅ‚Ņ–ĐģҌĐēи ваĐļĐģивО айО ĐŊĐĩĐžĐąŅ…Ņ–Đ´ĐŊĐž, ŅĐēŅ‰Đž Ви виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅ”Ņ‚Đĩ `Annotated`. + +/// + +ĐŸŅ€Đ¸ĐŋŅƒŅŅ‚Đ¸ĐŧĐž, Ви Ņ…ĐžŅ‡ĐĩŅ‚Đĩ ĐžĐŗĐžĐģĐžŅĐ¸Ņ‚Đ¸ ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ СаĐŋĐ¸Ņ‚Ņƒ `q` ŅĐē ĐžĐąĐžĐ˛â€™ŅĐˇĐēОвиК `str`. + +І ВаĐŧ ĐŊĐĩ ĐŋĐžŅ‚Ņ€Ņ–ĐąĐŊĐž ĐžĐŗĐžĐģĐžŅˆŅƒĐ˛Đ°Ņ‚Đ¸ ĐŊŅ–Ņ‡ĐžĐŗĐž Ņ–ĐŊŅˆĐžĐŗĐž Đ´ĐģŅ Ņ†ŅŒĐžĐŗĐž ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ°, Ņ‚ĐžĐŧ҃ ĐŊĐĩĐŧĐ°Ņ” ĐŋĐžŅ‚Ņ€Đĩйи виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ `Query`. + +АĐģĐĩ ВаĐŧ Đ˛ŅĐĩ ОдĐŊĐž ĐŋĐžŅ‚Ņ€Ņ–ĐąĐŊĐž виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ `Path` Đ´ĐģŅ ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ° ҈ĐģŅŅ…Ņƒ `item_id`. І С ĐŋĐĩвĐŊĐ¸Ņ… ĐŋŅ€Đ¸Ņ‡Đ¸ĐŊ Ви ĐŊĐĩ Ņ…ĐžŅ‡ĐĩŅ‚Đĩ виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ `Annotated`. + +Python Đ˛Đ¸Đ´Đ°ŅŅ‚ŅŒ ĐŋĐžĐŧиĐģĐē҃, ŅĐēŅ‰Đž Ņ€ĐžĐˇĐŧŅ–ŅŅ‚Đ¸Ņ‚Đ¸ СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ С "default" ĐŋĐĩŅ€ĐĩĐ´ СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅĐŧ, ŅĐēĐĩ ĐŊĐĩ ĐŧĐ°Ņ” "default". + +АĐģĐĩ Ви ĐŧĐžĐļĐĩŅ‚Đĩ СĐŧŅ–ĐŊĐ¸Ņ‚Đ¸ ĐŋĐžŅ€ŅĐ´ĐžĐē Ņ– Ņ€ĐžĐˇĐŧŅ–ŅŅ‚Đ¸Ņ‚Đ¸ СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ ĐąĐĩС СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ Са СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ (ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ СаĐŋĐ¸Ņ‚Ņƒ `q`) ĐŋĐĩŅ€ŅˆĐ¸Đŧ. + + +ДĐģŅ **FastAPI** ĐŋĐžŅ€ŅĐ´ĐžĐē ĐŊĐĩ ĐŧĐ°Ņ” СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ. Đ’Ņ–ĐŊ виСĐŊĐ°Ņ‡Đ°Ņ” ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ¸ Са Ņ—Ņ… Ņ–ĐŧĐĩĐŊаĐŧи, Ņ‚Đ¸ĐŋаĐŧи Ņ‚Đ° СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅĐŧи Са СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ (`Query`, `Path` Ņ‚ĐžŅ‰Đž) Ņ– ĐŊĐĩ СвĐĩŅ€Ņ‚Đ°Ņ” ŅƒĐ˛Đ°ĐŗĐ¸ ĐŊа ĐŋĐžŅ€ŅĐ´ĐžĐē. + +ĐĸĐžĐŧ҃ Ви ĐŧĐžĐļĐĩŅ‚Đĩ ĐžĐŗĐžĐģĐžŅĐ¸Ņ‚Đ¸ Đ’Đ°ŅˆŅƒ Ņ„ŅƒĐŊĐēŅ†Ņ–ŅŽ Ņ‚Đ°Đē: + +//// tab | Python 3.8 non-Annotated + +/// tip | ĐŸŅ–Đ´ĐēаСĐēа + +За ĐŧĐžĐļĐģĐ¸Đ˛ĐžŅŅ‚Ņ– Đ˛Ņ–Đ´Đ´Đ°Đ˛Đ°ĐšŅ‚Đĩ ĐŋĐĩŅ€ĐĩĐ˛Đ°ĐŗŅƒ вĐĩҀҁҖҗ С виĐēĐžŅ€Đ¸ŅŅ‚Đ°ĐŊĐŊŅĐŧ `Annotated`. + +/// + +{* ../../docs_src/path_params_numeric_validations/tutorial002.py hl[7] *} + +//// + +АĐģĐĩ ĐŧĐ°ĐšŅ‚Đĩ ĐŊа ŅƒĐ˛Đ°ĐˇŅ–, Ņ‰Đž ŅĐēŅ‰Đž Ви виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅ”Ņ‚Đĩ `Annotated`, Ņ†Ņ ĐŋŅ€ĐžĐąĐģĐĩĐŧа ĐŊĐĩ виĐŊиĐēĐŊĐĩ, ĐžŅĐēŅ–ĐģҌĐēи Ви ĐŊĐĩ виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅ”Ņ‚Đĩ СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ Са СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ Đ´ĐģŅ ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Ņ–Đ˛ `Query()` айО `Path()`. + +{* ../../docs_src/path_params_numeric_validations/tutorial002_an_py39.py *} + +## ĐŖĐŋĐžŅ€ŅĐ´ĐēĐžĐ˛ŅƒĐšŅ‚Đĩ ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ¸ Са ĐŋĐžŅ‚Ņ€ĐĩĐąĐžŅŽ, Ņ…Đ¸Ņ‚Ņ€ĐžŅ‰Ņ– + +/// tip | ĐŸŅ–Đ´ĐēаСĐēа + +ĐĻĐĩ, ĐŧĐ°ĐąŅƒŅ‚ŅŒ, ĐŊĐĩ ĐŊĐ°ŅŅ‚Ņ–ĐģҌĐēи ваĐļĐģивО айО ĐŊĐĩĐžĐąŅ…Ņ–Đ´ĐŊĐž, ŅĐēŅ‰Đž Ви виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅ”Ņ‚Đĩ `Annotated`. + +/// + +ĐžŅŅŒ **ĐŊĐĩвĐĩĐģиĐēа Ņ…Đ¸Ņ‚Ņ€Ņ–ŅŅ‚ŅŒ**, ŅĐēа ĐŧĐžĐļĐĩ ŅŅ‚Đ°Ņ‚Đ¸ в ĐŋŅ€Đ¸ĐŗĐžĐ´Ņ–, Ņ…ĐžŅ‡Đ° вОĐŊа Ņ€Ņ–Đ´ĐēĐž СĐŊĐ°Đ´ĐžĐąĐ¸Ņ‚ŅŒŅŅ. + +Đ¯ĐēŅ‰Đž Ви Ņ…ĐžŅ‡ĐĩŅ‚Đĩ: + +* ĐžĐŗĐžĐģĐžŅĐ¸Ņ‚Đ¸ ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ СаĐŋĐ¸Ņ‚Ņƒ `q` ĐąĐĩС виĐēĐžŅ€Đ¸ŅŅ‚Đ°ĐŊĐŊŅ `Query` айО СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ Са СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ +* ĐžĐŗĐžĐģĐžŅĐ¸Ņ‚Đ¸ ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ ҈ĐģŅŅ…Ņƒ `item_id`, виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅŽŅ‡Đ¸ `Path` +* Ņ€ĐžĐˇĐŧŅ–ŅŅ‚Đ¸Ņ‚Đ¸ Ņ—Ņ… ҃ Ņ€Ņ–ĐˇĐŊĐžĐŧ҃ ĐŋĐžŅ€ŅĐ´Đē҃ +* ĐŊĐĩ виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ `Annotated` + +...҃ Python Ņ” ҁĐŋĐĩŅ†Ņ–Đ°ĐģҌĐŊиК ŅĐ¸ĐŊŅ‚Đ°ĐēŅĐ¸Ņ Đ´ĐģŅ Ņ†ŅŒĐžĐŗĐž. + +ПĐĩŅ€ĐĩĐ´Đ°ĐšŅ‚Đĩ `*` ŅĐē ĐŋĐĩŅ€ŅˆĐ¸Đš ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ Ņ„ŅƒĐŊĐē҆Җҗ. + +Python ĐŊŅ–Ņ‡ĐžĐŗĐž ĐŊĐĩ ĐˇŅ€ĐžĐąĐ¸Ņ‚ŅŒ Ņ–Đˇ Ņ†Ņ–Ņ”ŅŽ `*`, аĐģĐĩ Ņ€ĐžĐˇĐŋŅ–ĐˇĐŊĐ°Ņ”, Ņ‰Đž Đ˛ŅŅ– ĐŊĐ°ŅŅ‚ŅƒĐŋĐŊŅ– ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ¸ ҁĐģŅ–Đ´ виĐēĐģиĐēĐ°Ņ‚Đ¸ ŅĐē Đ°Ņ€ĐŗŅƒĐŧĐĩĐŊŅ‚Đ¸ Са ĐēĐģŅŽŅ‡ĐžĐ˛Đ¸Đŧ ҁĐģОвОĐŧ (ĐŋĐ°Ņ€Đ¸ ĐēĐģŅŽŅ‡-СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ), Ņ‚Đ°ĐēĐžĐļ Đ˛Ņ–Đ´ĐžĐŧŅ– ŅĐē kwargs. ĐĐ°Đ˛Ņ–Ņ‚ŅŒ ŅĐēŅ‰Đž вОĐŊи ĐŊĐĩ ĐŧĐ°ŅŽŅ‚ŅŒ СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ Са СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ. + +{* ../../docs_src/path_params_numeric_validations/tutorial003.py hl[7] *} + +### ĐšŅ€Đ°Ņ‰Đĩ С `Annotated` + +ĐœĐ°ĐšŅ‚Đĩ ĐŊа ŅƒĐ˛Đ°ĐˇŅ–, ŅĐēŅ‰Đž Ви виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅ”Ņ‚Đĩ `Annotated`, ĐžŅĐēŅ–ĐģҌĐēи Ви ĐŊĐĩ виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅ”Ņ‚Đĩ СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ Са СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ Đ´ĐģŅ ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Ņ–Đ˛ Ņ„ŅƒĐŊĐē҆Җҗ, ҆ҖҔҗ ĐŋŅ€ĐžĐąĐģĐĩĐŧи ĐŊĐĩ виĐŊиĐēĐŊĐĩ, Ņ–, ŅˆĐ˛Đ¸Đ´ŅˆĐĩ Са Đ˛ŅĐĩ, ВаĐŧ ĐŊĐĩ ĐŋĐžŅ‚Ņ€Ņ–ĐąĐŊĐž ĐąŅƒĐ´Đĩ виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ `*`. + +{* ../../docs_src/path_params_numeric_validations/tutorial003_an_py39.py hl[10] *} + +## ВаĐģŅ–Đ´Đ°Ņ†Ņ–Ņ Ņ‡Đ¸ŅĐģĐžĐ˛Đ¸Ņ… даĐŊĐ¸Ņ…: ĐąŅ–ĐģҌ҈Đĩ айО Đ´ĐžŅ€Ņ–Đ˛ĐŊŅŽŅ” + +За Đ´ĐžĐŋĐžĐŧĐžĐŗĐžŅŽ `Query` Ņ– `Path` (Ņ‚Đ° Ņ–ĐŊŅˆĐ¸Ņ…, ŅĐēŅ– Ви ĐŋĐžĐąĐ°Ņ‡Đ¸Ņ‚Đĩ ĐŋŅ–ĐˇĐŊŅ–ŅˆĐĩ) ĐŧĐžĐļĐŊа ĐžĐŗĐžĐģĐžŅˆŅƒĐ˛Đ°Ņ‚Đ¸ Ņ‡Đ¸ŅĐģĐžĐ˛Ņ– ОйĐŧĐĩĐļĐĩĐŊĐŊŅ. + +ĐĸŅƒŅ‚, ĐˇĐ°Đ˛Đ´ŅĐēи `ge=1`, `item_id` ĐŧĐ°Ņ” ĐąŅƒŅ‚Đ¸ ҆ҖĐģиĐŧ Ņ‡Đ¸ŅĐģĐžĐŧ, ŅĐēĐĩ "`g`reater than or `e`qual" (ĐąŅ–ĐģҌ҈Đĩ айО Đ´ĐžŅ€Ņ–Đ˛ĐŊŅŽŅ”) `1`. + +{* ../../docs_src/path_params_numeric_validations/tutorial004_an_py39.py hl[10] *} + +## ВаĐģŅ–Đ´Đ°Ņ†Ņ–Ņ Ņ‡Đ¸ŅĐģĐžĐ˛Đ¸Ņ… даĐŊĐ¸Ņ…: ĐąŅ–ĐģҌ҈Đĩ ĐŊŅ–Đļ Ņ– ĐŧĐĩĐŊ҈Đĩ айО Đ´ĐžŅ€Ņ–Đ˛ĐŊŅŽŅ” + +ĐĸĐĩ ŅĐ°ĐŧĐĩ ĐˇĐ°ŅŅ‚ĐžŅĐžĐ˛ŅƒŅ”Ņ‚ŅŒŅŅ Đ´Đž: + +* `gt`: `g`reater `t`han (ĐąŅ–ĐģҌ҈Đĩ ĐŊŅ–Đļ) +* `le`: `l`ess than or `e`qual (ĐŧĐĩĐŊ҈Đĩ айО Đ´ĐžŅ€Ņ–Đ˛ĐŊŅŽŅ”) + +{* ../../docs_src/path_params_numeric_validations/tutorial005_an_py39.py hl[10] *} + +## ВаĐģŅ–Đ´Đ°Ņ†Ņ–Ņ Ņ‡Đ¸ŅĐģĐžĐ˛Đ¸Ņ… даĐŊĐ¸Ņ…: float, ĐąŅ–ĐģҌ҈Đĩ ĐŊŅ–Đļ Ņ– ĐŧĐĩĐŊ҈Đĩ ĐŊŅ–Đļ + +ВаĐģŅ–Đ´Đ°Ņ†Ņ–Ņ Ņ‡Đ¸ŅĐĩĐģ Ņ‚Đ°ĐēĐžĐļ ĐŋŅ€Đ°Ņ†ŅŽŅ” Đ´ĐģŅ СĐŊĐ°Ņ‡ĐĩĐŊҌ Ņ‚Đ¸Đŋ҃ `float`. + +ĐžŅŅŒ Đ´Đĩ ŅŅ‚Đ°Ņ” ваĐļĐģивО ĐŧĐ°Ņ‚Đ¸ ĐŧĐžĐļĐģĐ¸Đ˛Ņ–ŅŅ‚ŅŒ ĐžĐŗĐžĐģĐžŅˆŅƒĐ˛Đ°Ņ‚Đ¸ gt, а ĐŊĐĩ ҂ҖĐģҌĐēи ge. ĐĻĐĩ дОСвОĐģŅŅ”, ĐŊаĐŋŅ€Đ¸ĐēĐģад, виĐŧĐ°ĐŗĐ°Ņ‚Đ¸, Ņ‰ĐžĐą СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ ĐąŅƒĐģĐž ĐąŅ–ĐģҌ҈Đĩ `0`, ĐŊĐ°Đ˛Ņ–Ņ‚ŅŒ ŅĐēŅ‰Đž вОĐŊĐž ĐŧĐĩĐŊ҈Đĩ `1`. + +ĐĸаĐēиĐŧ Ņ‡Đ¸ĐŊĐžĐŧ, СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ `0.5` ĐąŅƒĐ´Đĩ Đ´ĐžĐŋŅƒŅŅ‚Đ¸ĐŧиĐŧ. АĐģĐĩ `0.0` айО `0` — ĐŊŅ–. + +ĐĸĐĩ ŅĐ°ĐŧĐĩ ŅŅ‚ĐžŅŅƒŅ”Ņ‚ŅŒŅŅ lt. + +{* ../../docs_src/path_params_numeric_validations/tutorial006_an_py39.py hl[13] *} + +## ĐŸŅ–Đ´ŅŅƒĐŧĐžĐē + +За Đ´ĐžĐŋĐžĐŧĐžĐŗĐžŅŽ `Query`, `Path` (Ņ– Ņ–ĐŊŅˆĐ¸Ņ… ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Ņ–Đ˛, ŅĐēŅ– Ви ҉Đĩ ĐŊĐĩ ĐąĐ°Ņ‡Đ¸Đģи) ĐŧĐžĐļĐŊа ĐžĐŗĐžĐģĐžŅˆŅƒĐ˛Đ°Ņ‚Đ¸ ĐŧĐĩŅ‚Đ°Đ´Đ°ĐŊŅ– Ņ‚Đ° ĐŋĐĩŅ€ĐĩĐ˛Ņ–Ņ€Đēи Ņ€ŅĐ´ĐēŅ–Đ˛, Ņ‚Đ°Đē ŅĐ°ĐŧĐž ŅĐē ҃ [Query ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ¸ Ņ‚Đ° ваĐģŅ–Đ´Đ°Ņ†Ņ–Ņ Ņ€ŅĐ´ĐēŅ–Đ˛](query-params-str-validations.md){.internal-link target=_blank}. + +ĐĸаĐēĐžĐļ ĐŧĐžĐļĐŊа ĐžĐŗĐžĐģĐžŅˆŅƒĐ˛Đ°Ņ‚Đ¸ Ņ‡Đ¸ŅĐģĐžĐ˛Ņ– ĐŋĐĩŅ€ĐĩĐ˛Ņ–Ņ€Đēи: + +* `gt`: `g`reater `t`han (ĐąŅ–ĐģҌ҈Đĩ ĐŊŅ–Đļ) +* `ge`: `g`reater than or `e`qual (ĐąŅ–ĐģҌ҈Đĩ айО Đ´ĐžŅ€Ņ–Đ˛ĐŊŅŽŅ”) +* `lt`: `l`ess `t`han (ĐŧĐĩĐŊ҈Đĩ ĐŊŅ–Đļ) +* `le`: `l`ess than or `e`qual (ĐŧĐĩĐŊ҈Đĩ айО Đ´ĐžŅ€Ņ–Đ˛ĐŊŅŽŅ”) + +/// info | ІĐŊŅ„ĐžŅ€ĐŧĐ°Ņ†Ņ–Ņ + +`Query`, `Path` Ņ‚Đ° Ņ–ĐŊŅˆŅ– ĐēĐģĐ°ŅĐ¸, ŅĐēŅ– Ви ĐŋĐžĐąĐ°Ņ‡Đ¸Ņ‚Đĩ ĐŋŅ–ĐˇĐŊŅ–ŅˆĐĩ, Ņ” ĐŋŅ–Đ´ĐēĐģĐ°ŅĐ°Đŧи ҁĐŋŅ–ĐģҌĐŊĐžĐŗĐž ĐēĐģĐ°ŅŅƒ `Param`. + +Đ’ŅŅ– вОĐŊи ĐŧĐ°ŅŽŅ‚ŅŒ ОдĐŊаĐēĐžĐ˛Ņ– ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ¸ Đ´ĐģŅ Đ´ĐžĐ´Đ°Ņ‚ĐēĐžĐ˛Đ¸Ņ… ĐŋĐĩŅ€ĐĩĐ˛Ņ–Ņ€ĐžĐē Ņ– ĐŧĐĩŅ‚Đ°Đ´Đ°ĐŊĐ¸Ņ…, ŅĐēŅ– Ви вĐļĐĩ ĐąĐ°Ņ‡Đ¸Đģи. + +/// + +/// note | ĐĸĐĩŅ…ĐŊҖ҇ĐŊŅ– Đ´ĐĩŅ‚Đ°ĐģŅ– + +КоĐģи Ви Ņ–ĐŧĐŋĐžŅ€Ņ‚ŅƒŅ”Ņ‚Đĩ `Query`, `Path` Ņ‚Đ° Ņ–ĐŊŅˆŅ– С `fastapi`, ĐŊĐ°ŅĐŋŅ€Đ°Đ˛Đ´Ņ– ҆Đĩ Ņ„ŅƒĐŊĐē҆Җҗ. + +ĐŸŅ€Đ¸ виĐēĐģиĐē҃ вОĐŊи ĐŋОвĐĩŅ€Ņ‚Đ°ŅŽŅ‚ŅŒ ĐĩĐēСĐĩĐŧĐŋĐģŅŅ€Đ¸ ĐēĐģĐ°ŅŅ–Đ˛ С Ņ‚Đ°ĐēиĐŧи Đļ Ņ–ĐŧĐĩĐŊаĐŧи. + +ĐĸĐžĐąŅ‚Đž Ви Ņ–ĐŧĐŋĐžŅ€Ņ‚ŅƒŅ”Ņ‚Đĩ `Query`, ŅĐēа Ņ” Ņ„ŅƒĐŊĐēŅ†Ņ–Ņ”ŅŽ. А ĐēĐžĐģи Ви Ņ—Ņ— виĐēĐģиĐēĐ°Ņ”Ņ‚Đĩ, вОĐŊа ĐŋОвĐĩŅ€Ņ‚Đ°Ņ” ĐĩĐēСĐĩĐŧĐŋĐģŅŅ€ ĐēĐģĐ°ŅŅƒ, ŅĐēиК Ņ‚ĐĩĐļ ĐŊĐ°ĐˇĐ¸Đ˛Đ°Ņ”Ņ‚ŅŒŅŅ `Query`. + +ĐĻŅ– Ņ„ŅƒĐŊĐē҆Җҗ ŅŅ‚Đ˛ĐžŅ€ĐĩĐŊŅ– Ņ‚Đ°ĐēиĐŧ Ņ‡Đ¸ĐŊĐžĐŧ (СаĐŧŅ–ŅŅ‚ŅŒ виĐēĐžŅ€Đ¸ŅŅ‚Đ°ĐŊĐŊŅ ĐēĐģĐ°ŅŅ–Đ˛ ĐŊаĐŋŅ€ŅĐŧ҃), Ņ‰ĐžĐą Đ’Đ°Ņˆ Ņ€ĐĩдаĐēŅ‚ĐžŅ€ ĐŊĐĩ Đ˛Ņ–Đ´ĐˇĐŊĐ°Ņ‡Đ°Đ˛ Ņ—Ņ…ĐŊŅ– Ņ‚Đ¸Đŋи ŅĐē ĐŋĐžĐŧиĐģĐēи. + +ĐĸаĐēиĐŧ Ņ‡Đ¸ĐŊĐžĐŧ, Ви ĐŧĐžĐļĐĩŅ‚Đĩ ĐēĐžŅ€Đ¸ŅŅ‚ŅƒĐ˛Đ°Ņ‚Đ¸ŅŅ ŅĐ˛ĐžŅ—Đŧ ĐˇĐ˛Đ¸Ņ‡Đ°ĐšĐŊиĐŧ Ņ€ĐĩдаĐēŅ‚ĐžŅ€ĐžĐŧ Ņ– Ņ–ĐŊŅŅ‚Ņ€ŅƒĐŧĐĩĐŊŅ‚Đ°Đŧи Đ´ĐģŅ ĐŋŅ€ĐžĐŗŅ€Đ°ĐŧŅƒĐ˛Đ°ĐŊĐŊŅ ĐąĐĩС Đ´ĐžĐ´Đ°Ņ‚ĐēĐžĐ˛Đ¸Ņ… ĐŊаĐģĐ°ŅˆŅ‚ŅƒĐ˛Đ°ĐŊҌ Đ´ĐģŅ Ņ–ĐŗĐŊĐžŅ€ŅƒĐ˛Đ°ĐŊĐŊŅ Ņ‚Đ°ĐēĐ¸Ņ… ĐŋĐžĐŧиĐģĐžĐē. + +/// diff --git a/docs/uk/docs/tutorial/path-params.md b/docs/uk/docs/tutorial/path-params.md new file mode 100644 index 000000000..e7df1f19a --- /dev/null +++ b/docs/uk/docs/tutorial/path-params.md @@ -0,0 +1,261 @@ +# Path ĐŸĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ¸ + +Ви ĐŧĐžĐļĐĩŅ‚Đĩ виСĐŊĐ°Ņ‡Đ¸Ņ‚Đ¸ "ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ¸" айО "СĐŧŅ–ĐŊĐŊŅ–" ҈ĐģŅŅ…Ņƒ, виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅŽŅ‡Đ¸ ŅĐ¸ĐŊŅ‚Đ°ĐēŅĐ¸Ņ Ņ„ĐžŅ€ĐŧĐ°Ņ‚ĐžĐ˛Đ°ĐŊĐ¸Ņ… Ņ€ŅĐ´ĐēŅ–Đ˛: + +{* ../../docs_src/path_params/tutorial001.py hl[6:7] *} + +ЗĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ° ҈ĐģŅŅ…Ņƒ `item_id` ĐŋĐĩŅ€ĐĩĐ´Đ°Ņ”Ņ‚ŅŒŅŅ ҃ Ņ„ŅƒĐŊĐēŅ†Ņ–ŅŽ ŅĐē Đ°Ņ€ĐŗŅƒĐŧĐĩĐŊŅ‚ `item_id`. + +Đ¯ĐēŅ‰Đž СаĐŋŅƒŅŅ‚Đ¸Ņ‚Đ¸ ҆ĐĩĐš ĐŋŅ€Đ¸ĐēĐģад Ņ‚Đ° ĐŋĐĩŅ€ĐĩĐšŅ‚Đ¸ Са ĐŋĐžŅĐ¸ĐģаĐŊĐŊŅĐŧ http://127.0.0.1:8000/items/foo, Ņ‚Đž ĐžŅ‚Ņ€Đ¸ĐŧĐ°Ņ”ĐŧĐž Ņ‚Đ°Đē҃ Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´ŅŒ: + +```JSON +{"item_id":"foo"} +``` + +## Path ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ¸ С Ņ‚Đ¸ĐŋаĐŧи + +Ви ĐŧĐžĐļĐĩŅ‚Đĩ виСĐŊĐ°Ņ‡Đ¸Ņ‚Đ¸ Ņ‚Đ¸Đŋ ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ° ҈ĐģŅŅ…Ņƒ ҃ Ņ„ŅƒĐŊĐē҆Җҗ, виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅŽŅ‡Đ¸ ŅŅ‚Đ°ĐŊĐ´Đ°Ņ€Ņ‚ĐŊŅ– аĐŊĐžŅ‚Đ°Ņ†Ņ–Ņ— Ņ‚Đ¸ĐŋŅ–Đ˛ Python: + +{* ../../docs_src/path_params/tutorial002.py hl[7] *} + +ĐŖ Ņ‚Đ°ĐēĐžĐŧ҃ виĐŋадĐē҃ `item_id` виСĐŊĐ°Ņ‡Đ°Ņ”Ņ‚ŅŒŅŅ ŅĐē `int`. + +/// check | ĐŸŅ€Đ¸ĐŧŅ–Ņ‚Đēа + +ĐĻĐĩ Đ´Đ°ŅŅ‚ŅŒ ĐŧĐžĐļĐģĐ¸Đ˛Ņ–ŅŅ‚ŅŒ ĐŋŅ–Đ´Ņ‚Ņ€Đ¸ĐŧĐēи Ņ€ĐĩдаĐēŅ‚ĐžŅ€Đ° Đ˛ŅĐĩŅ€ĐĩдиĐŊŅ– Ņ„ŅƒĐŊĐē҆Җҗ С ĐŋĐĩŅ€ĐĩĐ˛Ņ–Ņ€ĐēаĐŧи ĐŋĐžĐŧиĐģĐžĐē, Đ°Đ˛Ņ‚ĐžĐ´ĐžĐŋОвĐŊĐĩĐŊĐŊŅ Ņ‚ĐžŅ‰Đž. + +/// + +## ПĐĩŅ€ĐĩŅ‚Đ˛ĐžŅ€ĐĩĐŊĐŊŅ даĐŊĐ¸Ņ… + +Đ¯ĐēŅ‰Đž СаĐŋŅƒŅŅ‚Đ¸Ņ‚Đ¸ ҆ĐĩĐš ĐŋŅ€Đ¸ĐēĐģад Ņ– ĐŋĐĩŅ€ĐĩĐšŅ‚Đ¸ Са ĐŋĐžŅĐ¸ĐģаĐŊĐŊŅĐŧ http://127.0.0.1:8000/items/3, Ņ‚Đž ĐžŅ‚Ņ€Đ¸ĐŧĐ°Ņ”Ņ‚Đĩ Ņ‚Đ°Đē҃ Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´ŅŒ: + +```JSON +{"item_id":3} +``` + +/// check | ĐŸŅ€Đ¸ĐŧŅ–Ņ‚Đēа + +ЗвĐĩŅ€ĐŊŅ–Ņ‚ŅŒ ŅƒĐ˛Đ°ĐŗŅƒ, Ņ‰Đž СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ, ŅĐēĐĩ ĐžŅ‚Ņ€Đ¸ĐŧаĐģа (Ņ– ĐŋОвĐĩŅ€ĐŊ҃Đģа) Đ˛Đ°ŅˆĐ° Ņ„ŅƒĐŊĐēŅ†Ņ–Ņ, — ҆Đĩ `3`. ĐĻĐĩ Python `int`, а ĐŊĐĩ Ņ€ŅĐ´ĐžĐē `"3"`. + +ĐžŅ‚ĐļĐĩ, С Ņ‚Đ°ĐēиĐŧ ĐžĐŗĐžĐģĐžŅˆĐĩĐŊĐŊŅĐŧ Ņ‚Đ¸Đŋ҃ **FastAPI** Đ°Đ˛Ņ‚ĐžĐŧĐ°Ņ‚Đ¸Ņ‡ĐŊĐž виĐēĐžĐŊŅƒŅ” "ĐŋĐ°Ņ€ŅĐ¸ĐŊĐŗ" СаĐŋĐ¸Ņ‚Ņ–Đ˛. + +/// + +## ПĐĩŅ€ĐĩĐ˛Ņ–Ņ€Đēа даĐŊĐ¸Ņ… + +Đ¯ĐēŅ‰Đž Đļ Đ˛Ņ–Đ´ĐēŅ€Đ¸Ņ‚Đ¸ ҃ ĐąŅ€Đ°ŅƒĐˇĐĩҀҖ ĐŋĐžŅĐ¸ĐģаĐŊĐŊŅ http://127.0.0.1:8000/items/foo, Ņ‚Đž ĐŋĐžĐąĐ°Ņ‡Đ¸ĐŧĐž ҆ҖĐēĐ°Đ˛Ņƒ HTTP-ĐŋĐžĐŧиĐģĐē҃: + +```JSON +{ + "detail": [ + { + "type": "int_parsing", + "loc": [ + "path", + "item_id" + ], + "msg": "Input should be a valid integer, unable to parse string as an integer", + "input": "foo", + "url": "https://errors.pydantic.dev/2.1/v/int_parsing" + } + ] +} +``` +Ņ‚ĐžĐŧ҃ Ņ‰Đž ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ ҈ĐģŅŅ…Ņƒ ĐŧĐ°Ņ” СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ `"foo"`, ŅĐēĐĩ ĐŊĐĩ Ņ” Ņ‚Đ¸ĐŋĐžĐŧ `int`. + +ĐĸаĐē҃ ŅĐ°Đŧ҃ ĐŋĐžĐŧиĐģĐē҃ ĐžŅ‚Ņ€Đ¸ĐŧĐ°Ņ”ĐŧĐž, ŅĐēŅ‰Đž ĐŋĐĩŅ€ĐĩĐ´Đ°Ņ‚Đ¸ `float` СаĐŧŅ–ŅŅ‚ŅŒ `int`, ŅĐē ĐąĐ°Ņ‡Đ¸ĐŧĐž, ҃ Ņ†ŅŒĐžĐŧ҃ ĐŋŅ€Đ¸ĐēĐģĐ°Đ´Ņ–: http://127.0.0.1:8000/items/4.2 + +/// check | ĐŸŅ€Đ¸ĐŧŅ–Ņ‚Đēа + +ĐžŅ‚ĐļĐĩ, **FastAPI** ĐŊĐ°Đ´Đ°Ņ” ĐŋĐĩŅ€ĐĩĐ˛Ņ–Ņ€Đē҃ Ņ‚Đ¸ĐŋŅ–Đ˛ С Ņ‚Đ°ĐēиĐŧ ŅĐ°ĐŧиĐŧ ĐžĐŗĐžĐģĐžŅˆĐĩĐŊĐŊŅĐŧ Ņ‚Đ¸Đŋ҃ в Python. + +ЗвĐĩŅ€ĐŊŅ–Ņ‚ŅŒ ŅƒĐ˛Đ°ĐŗŅƒ, Ņ‰Đž ĐŋĐžĐŧиĐģĐēа Ņ‚Đ°ĐēĐžĐļ ҇Җ҂ĐēĐž вĐēĐ°ĐˇŅƒŅ” ŅĐ°ĐŧĐĩ ĐŊа Ņ‚Đĩ ĐŧҖҁ҆Đĩ, Đ´Đĩ ваĐģŅ–Đ´Đ°Ņ†Ņ–Ņ ĐŊĐĩ ĐŋŅ€ĐžĐšŅˆĐģа. + +ĐĻĐĩ ĐŊĐĩĐšĐŧĐžĐ˛Ņ–Ņ€ĐŊĐž ĐēĐžŅ€Đ¸ŅĐŊĐž ĐŋŅ–Đ´ Ņ‡Đ°Ņ Ņ€ĐžĐˇŅ€ĐžĐąĐēи Ņ‚Đ° Đ´ĐĩĐąĐ°ĐŗŅ–ĐŊĐŗŅƒ ĐēĐžĐ´Ņƒ, Ņ‰Đž Đ˛ĐˇĐ°Ņ”ĐŧĐžĐ´Ņ–Ņ” С Đ˛Đ°ŅˆĐ¸Đŧ API. + +/// + +## ДоĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Ņ–Ņ + +ĐĸĐĩĐŋĐĩŅ€ ĐēĐžĐģи Đ˛Ņ–Đ´ĐēŅ€Đ¸Ņ”Ņ‚Đĩ ŅĐ˛Ņ–Đš ĐąŅ€Đ°ŅƒĐˇĐĩŅ€ Са ĐŋĐžŅĐ¸ĐģаĐŊĐŊŅĐŧ http://127.0.0.1:8000/docs, Ņ‚Đž ĐŋĐžĐąĐ°Ņ‡Đ¸Ņ‚Đĩ Đ°Đ˛Ņ‚ĐžĐŧĐ°Ņ‚Đ¸Ņ‡ĐŊĐž ĐˇĐŗĐĩĐŊĐĩŅ€ĐžĐ˛Đ°ĐŊ҃, Ņ–ĐŊŅ‚ĐĩŅ€Đ°ĐēŅ‚Đ¸Đ˛ĐŊ҃ API-Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Ņ–ŅŽ: + + + +/// check | ĐŸŅ€Đ¸ĐŧŅ–Ņ‚Đēа + +ЗĐŊĐžĐ˛Ņƒ Đļ Ņ‚Đ°Đēи, ĐģĐ¸ŅˆĐĩ С Ņ†Đ¸Đŧ ŅĐ°ĐŧиĐŧ ĐžĐŗĐžĐģĐžŅˆĐĩĐŊĐŊŅĐŧ Ņ‚Đ¸Đŋ҃ в Python, FastAPI ĐŊĐ°Đ´Đ°Ņ” ваĐŧ Đ°Đ˛Ņ‚ĐžĐŧĐ°Ņ‚Đ¸Ņ‡ĐŊ҃, Ņ–ĐŊŅ‚ĐĩŅ€Đ°ĐēŅ‚Đ¸Đ˛ĐŊ҃ Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Ņ–ŅŽ (С Ņ–ĐŊŅ‚ĐĩĐŗŅ€Đ°Ņ†Ņ–Ņ”ŅŽ Swagger UI). + +ЗвĐĩŅ€ĐŊŅ–Ņ‚ŅŒ ŅƒĐ˛Đ°ĐŗŅƒ, Ņ‰Đž ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ ҈ĐģŅŅ…Ņƒ ĐžĐŗĐžĐģĐžŅˆĐĩĐŊиК ŅĐē ҆ҖĐģĐĩ Ņ‡Đ¸ŅĐģĐž. + + +/// + +## ПĐĩŅ€ĐĩĐ˛Đ°ĐŗĐ¸ ŅŅ‚Đ°ĐŊĐ´Đ°Ņ€Ņ‚Đ¸ĐˇĐ°Ņ†Ņ–Ņ—, аĐģŅŒŅ‚ĐĩŅ€ĐŊĐ°Ņ‚Đ¸Đ˛ĐŊа Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Ņ–Ņ + +І ĐžŅĐēŅ–ĐģҌĐēи ĐˇĐŗĐĩĐŊĐĩŅ€ĐžĐ˛Đ°ĐŊа ҁ҅ĐĩĐŧа Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´Đ°Ņ” ŅŅ‚Đ°ĐŊĐ´Đ°Ņ€Ņ‚Ņƒ OpenAPI, ҖҁĐŊŅƒŅ” ĐąĐ°ĐŗĐ°Ņ‚Đž ҁ҃ĐŧҖҁĐŊĐ¸Ņ… Ņ–ĐŊŅŅ‚Ņ€ŅƒĐŧĐĩĐŊŅ‚Ņ–Đ˛. + +З ҆ҖҔҗ ĐŋŅ€Đ¸Ņ‡Đ¸ĐŊи FastAPI Ņ‚Đ°ĐēĐžĐļ ĐŊĐ°Đ´Đ°Ņ” аĐģŅŒŅ‚ĐĩŅ€ĐŊĐ°Ņ‚Đ¸Đ˛ĐŊ҃ Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Ņ–ŅŽ API (виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅŽŅ‡Đ¸ ReDoc), Đ´Đž ŅĐēĐžŅ— ĐŧĐžĐļĐŊа ĐžŅ‚Ņ€Đ¸ĐŧĐ°Ņ‚Đ¸ Đ´ĐžŅŅ‚ŅƒĐŋ Са ĐŋĐžŅĐ¸ĐģаĐŊĐŊŅĐŧ http://127.0.0.1:8000/redoc: + + + +ĐĸаĐēиĐŧ Ņ‡Đ¸ĐŊĐžĐŧ, ҖҁĐŊŅƒŅ” ĐąĐ°ĐŗĐ°Ņ‚Đž ҁ҃ĐŧҖҁĐŊĐ¸Ņ… Ņ–ĐŊŅŅ‚Ņ€ŅƒĐŧĐĩĐŊŅ‚Ņ–Đ˛, вĐēĐģŅŽŅ‡Đ°ŅŽŅ‡Đ¸ Ņ–ĐŊŅŅ‚Ņ€ŅƒĐŧĐĩĐŊŅ‚Đ¸ Đ´ĐģŅ ĐŗĐĩĐŊĐĩŅ€Đ°Ņ†Ņ–Ņ— ĐēĐžĐ´Ņƒ Đ´ĐģŅ ĐąĐ°ĐŗĐ°Ņ‚ŅŒĐžŅ… ĐŧОв. + + +## Pydantic + +Đ’ŅŅ ваĐģŅ–Đ´Đ°Ņ†Ņ–Ņ даĐŊĐ¸Ņ… виĐēĐžĐŊŅƒŅ”Ņ‚ŅŒŅŅ Са ĐģĐ°ŅˆŅ‚ŅƒĐŊĐēаĐŧи Са Đ´ĐžĐŋĐžĐŧĐžĐŗĐžŅŽ Pydantic, Ņ‚ĐžĐŧ҃ Ви ĐžŅ‚Ņ€Đ¸ĐŧŅƒŅ”Ņ‚Đĩ Đ˛ŅŅ– ĐŋĐĩŅ€ĐĩĐ˛Đ°ĐŗĐ¸ Đ˛Ņ–Đ´ ĐšĐžĐŗĐž виĐēĐžŅ€Đ¸ŅŅ‚Đ°ĐŊĐŊŅ. І ĐŧĐžĐļĐĩŅ‚Đĩ ĐąŅƒŅ‚Đ¸ вĐŋĐĩвĐŊĐĩĐŊŅ–, Ņ‰Đž Đ˛ŅĐĩ в ĐŊĐ°Đ´Ņ–ĐšĐŊĐ¸Ņ… Ņ€ŅƒĐēĐ°Ņ…. + +Ви ĐŧĐžĐļĐĩŅ‚Đĩ виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ ҂Җ ŅĐ°ĐŧŅ– ĐžĐŗĐžĐģĐžŅˆĐĩĐŊĐŊŅ Ņ‚Đ¸ĐŋŅ–Đ˛ С `str`, `float`, `bool` Ņ‚Đ° ĐąĐ°ĐŗĐ°Ņ‚ŅŒĐŧа Ņ–ĐŊŅˆĐ¸Đŧи ҁĐēĐģадĐŊиĐŧи Ņ‚Đ¸ĐŋаĐŧи даĐŊĐ¸Ņ…. + +ДĐĩĐēŅ–ĐģҌĐēа С ĐŊĐ¸Ņ… ĐąŅƒĐ´ŅƒŅ‚ŅŒ Ņ€ĐžĐˇĐŗĐģŅĐŊŅƒŅ‚Ņ– в ĐŊĐ°ŅŅ‚ŅƒĐŋĐŊĐ¸Ņ… Ņ€ĐžĐˇĐ´Ņ–ĐģĐ°Ņ… ĐŋĐžŅŅ–ĐąĐŊиĐēа. + +## ĐŸĐžŅ€ŅĐ´ĐžĐē ĐŧĐ°Ņ” СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ + +ĐŸŅ€Đ¸ ŅŅ‚Đ˛ĐžŅ€ĐĩĐŊĐŊŅ– *ĐžĐŋĐĩŅ€Đ°Ņ†Ņ–Đš ҈ĐģŅŅ…Ņƒ* ĐŧĐžĐļŅƒŅ‚ŅŒ виĐŊиĐēĐ°Ņ‚Đ¸ ŅĐ¸Ņ‚ŅƒĐ°Ņ†Ņ–Ņ—, ĐēĐžĐģи ҈ĐģŅŅ… ҄ҖĐēŅĐžĐ˛Đ°ĐŊиК. + +НаĐŋŅ€Đ¸ĐēĐģад, `/users/me`. ĐŸŅ€Đ¸ĐŋŅƒŅŅ‚Đ¸ĐŧĐž, Ņ‰Đž ҆Đĩ ҈ĐģŅŅ… Đ´ĐģŅ ĐžŅ‚Ņ€Đ¸ĐŧаĐŊĐŊŅ даĐŊĐ¸Ņ… ĐŋŅ€Đž ĐŋĐžŅ‚ĐžŅ‡ĐŊĐžĐŗĐž ĐēĐžŅ€Đ¸ŅŅ‚ŅƒĐ˛Đ°Ņ‡Đ°. + +А Ņ‚Đ°ĐēĐžĐļ ҃ Đ˛Đ°Ņ ĐŧĐžĐļĐĩ ĐąŅƒŅ‚Đ¸ ҈ĐģŅŅ… `/users/{user_id}`, Ņ‰ĐžĐą ĐžŅ‚Ņ€Đ¸ĐŧĐ°Ņ‚Đ¸ даĐŊŅ– ĐŋŅ€Đž ĐēĐžĐŊĐēŅ€ĐĩŅ‚ĐŊĐžĐŗĐž ĐēĐžŅ€Đ¸ŅŅ‚ŅƒĐ˛Đ°Ņ‡Đ° Са ĐšĐžĐŗĐž ID. + +ĐžŅĐēŅ–ĐģҌĐēи *ĐžĐŋĐĩŅ€Đ°Ņ†Ņ–Ņ— ҈ĐģŅŅ…Ņƒ* ĐžŅ†Ņ–ĐŊŅŽŅŽŅ‚ŅŒŅŅ ĐŋĐž ҇ĐĩŅ€ĐˇŅ–, Ви ĐŋОвиĐŊĐŊŅ– ĐŋĐĩŅ€ĐĩĐēĐžĐŊĐ°Ņ‚Đ¸ŅŅ, Ņ‰Đž ҈ĐģŅŅ… Đ´ĐģŅ `/users/me` ĐžĐŗĐžĐģĐžŅˆĐĩĐŊиК ĐŋĐĩŅ€ĐĩĐ´ ҈ĐģŅŅ…ĐžĐŧ Đ´ĐģŅ `/users/{user_id}`: + +{* ../../docs_src/path_params/tutorial003.py hl[6,11] *} + +ІĐŊаĐē҈Đĩ ҈ĐģŅŅ… Đ´ĐģŅ `/users/{user_id}` Ņ‚Đ°ĐēĐžĐļ ĐąŅƒĐ´Đĩ Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´Đ°Ņ‚Đ¸ Đ´ĐģŅ `/users/me`, "вваĐļĐ°ŅŽŅ‡Đ¸", Ņ‰Đž Đ˛Ņ–ĐŊ ĐžŅ‚Ņ€Đ¸ĐŧŅƒŅ” ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ `user_id` ĐˇŅ– СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅĐŧ `"me"`. + +АĐŊаĐģĐžĐŗŅ–Ņ‡ĐŊĐž, Ви ĐŊĐĩ ĐŧĐžĐļĐĩŅ‚Đĩ ĐžĐŗĐžĐģĐžŅĐ¸Ņ‚Đ¸ ĐžĐŋĐĩŅ€Đ°Ņ†Ņ–ŅŽ ҈ĐģŅŅ…Ņƒ: + +{* ../../docs_src/path_params/tutorial003b.py hl[6,11] *} + +ПĐĩŅ€ŅˆĐ° ĐžĐŋĐĩŅ€Đ°Ņ†Ņ–Ņ ĐąŅƒĐ´Đĩ СавĐļди виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ŅŅ, ĐžŅĐēŅ–ĐģҌĐēи ҈ĐģŅŅ… ĐˇĐąŅ–ĐŗĐ°Ņ”Ņ‚ŅŒŅŅ ĐŋĐĩŅ€ŅˆĐ¸Đŧ. +## ПоĐŋĐĩŅ€ĐĩĐ´ĐŊŅŒĐž виСĐŊĐ°Ņ‡ĐĩĐŊŅ– СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ + +Đ¯ĐēŅ‰Đž ҃ Đ˛Đ°Ņ Ņ” *ĐžĐŋĐĩŅ€Đ°Ņ†Ņ–Ņ ҈ĐģŅŅ…Ņƒ*, ŅĐēа ĐŋŅ€Đ¸ĐšĐŧĐ°Ņ” *ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ ҈ĐģŅŅ…Ņƒ*, аĐģĐĩ Ви Ņ…ĐžŅ‡ĐĩŅ‚Đĩ, Ņ‰ĐžĐą ĐŧĐžĐļĐģĐ¸Đ˛Ņ– Đ´ĐžĐŋŅƒŅŅ‚Đ¸ĐŧŅ– СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ *ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ° ҈ĐģŅŅ…Ņƒ* ĐąŅƒĐģи ĐŋĐžĐŋĐĩŅ€ĐĩĐ´ĐŊŅŒĐž виСĐŊĐ°Ņ‡ĐĩĐŊŅ–, Ви ĐŧĐžĐļĐĩŅ‚Đĩ виĐēĐžŅ€Đ¸ŅŅ‚Đ°Ņ‚Đ¸ ŅŅ‚Đ°ĐŊĐ´Đ°Ņ€Ņ‚ĐŊиК Python Enum. + +### ĐĄŅ‚Đ˛ĐžŅ€ĐĩĐŊĐŊŅ ĐēĐģĐ°ŅŅƒ `Enum` + +ІĐŧĐŋĐžŅ€Ņ‚ŅƒĐšŅ‚Đĩ `Enum` Ņ– ŅŅ‚Đ˛ĐžŅ€Ņ–Ņ‚ŅŒ ĐŋŅ–Đ´ĐēĐģĐ°Ņ, Ņ‰Đž ĐŊĐ°ŅĐģŅ–Đ´ŅƒŅ”Ņ‚ŅŒŅŅ Đ˛Ņ–Đ´ `str` Ņ‚Đ° `Enum`. + +ĐĐ°ŅĐģŅ–Đ´ŅƒŅŽŅ‡Đ¸ Đ˛Ņ–Đ´ `str`, Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Ņ–Ņ API СĐŧĐžĐļĐĩ виСĐŊĐ°Ņ‡Đ¸Ņ‚Đ¸, Ņ‰Đž СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ ĐŋОвиĐŊĐŊŅ– ĐąŅƒŅ‚Đ¸ Ņ‚Đ¸Đŋ҃ `string`, Ņ– ĐŋŅ€Đ°Đ˛Đ¸ĐģҌĐŊĐž Ņ—Ņ… Đ˛Ņ–Đ´ĐžĐąŅ€Đ°ĐˇĐ¸Ņ‚ŅŒ. + +ĐŸŅ–ŅĐģŅ Ņ†ŅŒĐžĐŗĐž ŅŅ‚Đ˛ĐžŅ€Ņ–Ņ‚ŅŒ Đ°Ņ‚Ņ€Đ¸ĐąŅƒŅ‚Đ¸ ĐēĐģĐ°ŅŅƒ С ҄ҖĐēŅĐžĐ˛Đ°ĐŊиĐŧи СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅĐŧи, ŅĐēŅ– ĐąŅƒĐ´ŅƒŅ‚ŅŒ Đ´ĐžŅŅ‚ŅƒĐŋĐŊиĐŧи Đ´ĐžĐŋŅƒŅŅ‚Đ¸ĐŧиĐŧи СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅĐŧи: + +{* ../../docs_src/path_params/tutorial005.py hl[1,6:9] *} + +/// info | Đ”ĐžĐ´Đ°Ņ‚ĐēОва Ņ–ĐŊŅ„ĐžŅ€ĐŧĐ°Ņ†Ņ–Ņ + +ПĐĩŅ€ĐĩĐģҖ҇ĐĩĐŊĐŊŅ (айО enums) Đ´ĐžŅŅ‚ŅƒĐŋĐŊŅ– в Python ĐŋĐžŅ‡Đ¸ĐŊĐ°ŅŽŅ‡Đ¸ С вĐĩҀҁҖҗ 3.4. + +/// + +/// tip | ĐŸĐžŅ€Đ°Đ´Đ° + +Đ¯ĐēŅ‰Đž ваĐŧ ҆ҖĐēавО, "AlexNet", "ResNet" Ņ‚Đ° "LeNet" — ҆Đĩ ĐŋŅ€ĐžŅŅ‚Đž ĐŊаСви ML ĐŧОдĐĩĐģĐĩĐš Machine Learning. + +/// + + +### ĐžĐŗĐžĐģĐžŅŅ–Ņ‚ŅŒ *ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ ҈ĐģŅŅ…Ņƒ* + +ĐŸĐžŅ‚Ņ–Đŧ ŅŅ‚Đ˛ĐžŅ€Ņ–Ņ‚ŅŒ *ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ ҈ĐģŅŅ…Ņƒ* С аĐŊĐžŅ‚Đ°Ņ†Ņ–Ņ”ŅŽ Ņ‚Đ¸Đŋ҃, виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅŽŅ‡Đ¸ ŅŅ‚Đ˛ĐžŅ€ĐĩĐŊиК ваĐŧи ĐēĐģĐ°Ņ enum (`ModelName`): + +{* ../../docs_src/path_params/tutorial005.py hl[16] *} + +### ПĐĩŅ€ĐĩĐ˛Ņ–Ņ€Đēа Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Ņ–Ņ— + +ĐžŅĐēŅ–ĐģҌĐēи Đ´ĐžŅŅ‚ŅƒĐŋĐŊŅ– СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ Đ´ĐģŅ *ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ° ҈ĐģŅŅ…Ņƒ* виСĐŊĐ°Ņ‡ĐĩĐŊŅ– СаСдаĐģĐĩĐŗŅ–Đ´ŅŒ, Ņ–ĐŊŅ‚ĐĩŅ€Đ°ĐēŅ‚Đ¸Đ˛ĐŊа Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Ņ–Ņ СĐŧĐžĐļĐĩ ĐēŅ€Đ°ŅĐ¸Đ˛Đž Ņ—Ņ… Đ˛Ņ–Đ´ĐžĐąŅ€Đ°ĐˇĐ¸Ņ‚Đ¸: + + + +### Đ ĐžĐąĐžŅ‚Đ° С *ĐŋĐĩŅ€ĐĩĐģŅ–Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧи* ҃ Python + +ЗĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ *ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ° ҈ĐģŅŅ…Ņƒ* ĐąŅƒĐ´Đĩ ĐĩĐģĐĩĐŧĐĩĐŊŅ‚ĐžĐŧ *ĐŋĐĩŅ€ĐĩĐģŅ–Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅ*. + +#### ĐŸĐžŅ€Ņ–Đ˛ĐŊŅĐŊĐŊŅ *ĐĩĐģĐĩĐŧĐĩĐŊŅ‚Ņ–Đ˛ ĐŋĐĩŅ€ĐĩĐģŅ–Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅ* + +Ви ĐŧĐžĐļĐĩŅ‚Đĩ ĐŋĐžŅ€Ņ–Đ˛ĐŊŅŽĐ˛Đ°Ņ‚Đ¸ ĐšĐžĐŗĐž С *ĐĩĐģĐĩĐŧĐĩĐŊŅ‚Đ°Đŧи ĐŋĐĩŅ€ĐĩĐģŅ–Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅ* ҃ ŅŅ‚Đ˛ĐžŅ€ĐĩĐŊĐžĐŧ҃ ваĐŧи enum `ModelName`: + +{* ../../docs_src/path_params/tutorial005.py hl[17] *} + +#### ĐžŅ‚Ņ€Đ¸ĐŧаĐŊĐŊŅ *СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ ĐŋĐĩŅ€ĐĩĐģŅ–Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅ* + +Ви ĐŧĐžĐļĐĩŅ‚Đĩ ĐžŅ‚Ņ€Đ¸ĐŧĐ°Ņ‚Đ¸ Ņ„Đ°ĐēŅ‚Đ¸Ņ‡ĐŊĐĩ СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ (҃ Ņ†ŅŒĐžĐŧ҃ виĐŋадĐē҃ ҆Đĩ `str`), виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅŽŅ‡Đ¸ `model_name.value`, айО ĐˇĐ°ĐŗĐ°ĐģĐžĐŧ `your_enum_member.value`: + +{* ../../docs_src/path_params/tutorial005.py hl[20] *} + +/// tip | ĐŸĐžŅ€Đ°Đ´Đ° + +Ви Ņ‚Đ°ĐēĐžĐļ ĐŧĐžĐļĐĩŅ‚Đĩ ĐžŅ‚Ņ€Đ¸ĐŧĐ°Ņ‚Đ¸ Đ´ĐžŅŅ‚ŅƒĐŋ Đ´Đž СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ `"lenet"`, виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅŽŅ‡Đ¸ `ModelName.lenet.value`. + +/// + + +#### ПовĐĩŅ€ĐŊĐĩĐŊĐŊŅ *ĐĩĐģĐĩĐŧĐĩĐŊŅ‚Ņ–Đ˛ ĐŋĐĩŅ€ĐĩĐģŅ–Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅ* + +Ви ĐŧĐžĐļĐĩŅ‚Đĩ ĐŋОвĐĩŅ€Ņ‚Đ°Ņ‚Đ¸ *ĐĩĐģĐĩĐŧĐĩĐŊŅ‚Đ¸ ĐŋĐĩŅ€ĐĩĐģŅ–Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅ* С Đ˛Đ°ŅˆĐžŅ— *ĐžĐŋĐĩŅ€Đ°Ņ†Ņ–Ņ— ҈ĐģŅŅ…Ņƒ*, ĐŊĐ°Đ˛Ņ–Ņ‚ŅŒ вĐēĐģадĐĩĐŊŅ– ҃ JSON-҂ҖĐģĐž (ĐŊаĐŋŅ€Đ¸ĐēĐģад, `dict`). + +ВоĐŊи ĐąŅƒĐ´ŅƒŅ‚ŅŒ ĐŋĐĩŅ€ĐĩŅ‚Đ˛ĐžŅ€ĐĩĐŊŅ– ĐŊа Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´ĐŊŅ– СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ (҃ Ņ†ŅŒĐžĐŧ҃ виĐŋадĐē҃ Ņ€ŅĐ´Đēи) ĐŋĐĩŅ€ĐĩĐ´ ĐŋОвĐĩŅ€ĐŊĐĩĐŊĐŊŅĐŧ ĐēĐģŅ–Ņ”ĐŊŅ‚Ņƒ: + +{* ../../docs_src/path_params/tutorial005.py hl[18,21,23] *} + +На ŅŅ‚ĐžŅ€ĐžĐŊŅ– ĐēĐģŅ–Ņ”ĐŊŅ‚Đ° Ви ĐžŅ‚Ņ€Đ¸ĐŧĐ°Ņ”Ņ‚Đĩ Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´ŅŒ ҃ Ņ„ĐžŅ€ĐŧĐ°Ņ‚Ņ– JSON, ĐŊаĐŋŅ€Đ¸ĐēĐģад: + +```JSON +{ + "model_name": "alexnet", + "message": "Deep Learning FTW!" +} +``` + +## Path-ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ¸, Ņ‰Đž ĐŧŅ–ŅŅ‚ŅŅ‚ŅŒ ҈ĐģŅŅ…Đ¸ + +ĐŸŅ€Đ¸ĐŋŅƒŅŅ‚Đ¸ĐŧĐž, ҃ Đ˛Đ°Ņ Ņ” *ĐžĐŋĐĩŅ€Đ°Ņ†Ņ–Ņ ҈ĐģŅŅ…Ņƒ* С ĐŧĐ°Ņ€ŅˆŅ€ŅƒŅ‚ĐžĐŧ `/files/{file_path}`. + +АĐģĐĩ ваĐŧ ĐŋĐžŅ‚Ņ€Ņ–ĐąĐŊĐž, Ņ‰ĐžĐą `file_path` ĐŧŅ–ŅŅ‚Đ¸Đ˛ *҈ĐģŅŅ…*, ĐŊаĐŋŅ€Đ¸ĐēĐģад `home/johndoe/myfile.txt`. + +ĐžŅ‚ĐļĐĩ, URL Đ´ĐģŅ Ņ†ŅŒĐžĐŗĐž Ņ„Đ°ĐšĐģ҃ Đ˛Đ¸ĐŗĐģŅĐ´Đ°Ņ‚Đ¸ĐŧĐĩ Ņ‚Đ°Đē: `/files/home/johndoe/myfile.txt`. + + + +### ĐŸŅ–Đ´Ņ‚Ņ€Đ¸ĐŧĐēа OpenAPI + +OpenAPI ĐŊĐĩ ĐŋŅ–Đ´Ņ‚Ņ€Đ¸ĐŧŅƒŅ” ҁĐŋĐžŅŅ–Đą ĐžĐŗĐžĐģĐžŅˆĐĩĐŊĐŊŅ *ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ° ҈ĐģŅŅ…Ņƒ*, Ņ‰Đž ĐŧŅ–ŅŅ‚Đ¸Ņ‚ŅŒ *҈ĐģŅŅ…* Đ˛ŅĐĩŅ€ĐĩдиĐŊŅ–, ĐžŅĐēŅ–ĐģҌĐēи ҆Đĩ ĐŧĐžĐļĐĩ ĐŋŅ€Đ¸ĐˇĐ˛ĐĩŅŅ‚Đ¸ Đ´Đž ҁ҆ĐĩĐŊĐ°Ņ€Ņ–Ņ—Đ˛, ŅĐēŅ– ҁĐēĐģадĐŊĐž Ņ‚ĐĩŅŅ‚ŅƒĐ˛Đ°Ņ‚Đ¸ Ņ‚Đ° виСĐŊĐ°Ņ‡Đ°Ņ‚Đ¸. + +ОдĐŊаĐē (ОдĐŊĐ°Ņ‡Đĩ), Ви Đ˛ŅĐĩ ОдĐŊĐž ĐŧĐžĐļĐĩŅ‚Đĩ ĐˇŅ€ĐžĐąĐ¸Ņ‚Đ¸ ҆Đĩ в **FastAPI**, виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅŽŅ‡Đ¸ ОдиĐŊ Ņ–Đˇ вĐŊŅƒŅ‚Ņ€Ņ–ŅˆĐŊŅ–Ņ… Ņ–ĐŊŅŅ‚Ņ€ŅƒĐŧĐĩĐŊŅ‚Ņ–Đ˛ Starlette. + +ДоĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Ņ–Ņ Đ˛ŅĐĩ ҉Đĩ ĐŋŅ€Đ°Ņ†ŅŽĐ˛Đ°Ņ‚Đ¸ĐŧĐĩ, Ņ…ĐžŅ‡Đ° Đš ĐŊĐĩ Đ´ĐžĐ´Đ°Đ˛Đ°Ņ‚Đ¸ĐŧĐĩ ĐžĐŋĐ¸ŅŅƒ ĐŋŅ€Đž Ņ‚Đĩ, Ņ‰Đž ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ ĐŋОвиĐŊĐĩĐŊ ĐŧŅ–ŅŅ‚Đ¸Ņ‚Đ¸ ҈ĐģŅŅ…. + +### КоĐŊвĐĩҀ҂ĐĩŅ€ ҈ĐģŅŅ…Ņƒ + +ВиĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅŽŅ‡Đ¸ ĐžĐŋŅ†Ņ–ŅŽ ĐąĐĩСĐŋĐžŅĐĩŅ€ĐĩĐ´ĐŊŅŒĐž ĐˇŅ– Starlette, Ви ĐŧĐžĐļĐĩŅ‚Đĩ ĐžĐŗĐžĐģĐžŅĐ¸Ņ‚Đ¸ *ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ ҈ĐģŅŅ…Ņƒ*, Ņ‰Đž ĐŧŅ–ŅŅ‚Đ¸Ņ‚ŅŒ *҈ĐģŅŅ…*, виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅŽŅ‡Đ¸ URL ĐŊа ĐēŅˆŅ‚Đ°ĐģŅ‚: + +``` +/files/{file_path:path} +``` +ĐŖ Ņ†ŅŒĐžĐŧ҃ виĐŋадĐē҃ Ņ–Đŧ'Ņ ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ° — `file_path`, а ĐžŅŅ‚Đ°ĐŊĐŊŅ Ņ‡Đ°ŅŅ‚Đ¸ĐŊа `:path` вĐēĐ°ĐˇŅƒŅ” ĐŊа Ņ‚Đĩ, Ņ‰Đž ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ ĐŋОвиĐŊĐĩĐŊ Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´Đ°Ņ‚Đ¸ ĐąŅƒĐ´ŅŒ-ŅĐēĐžĐŧ҃ *҈ĐģŅŅ…Ņƒ*. + +ĐžŅ‚ĐļĐĩ, Ви ĐŧĐžĐļĐĩŅ‚Đĩ виĐēĐžŅ€Đ¸ŅŅ‚Đ°Ņ‚Đ¸ ĐšĐžĐŗĐž Ņ‚Đ°Đē: + +{* ../../docs_src/path_params/tutorial004.py hl[6] *} + +/// tip | ĐŸĐžŅ€Đ°Đ´Đ° + +ВаĐŧ ĐŧĐžĐļĐĩ СĐŊĐ°Đ´ĐžĐąĐ¸Ņ‚Đ¸ŅŅ, Ņ‰ĐžĐą ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ ĐŧŅ–ŅŅ‚Đ¸Đ˛ `/home/johndoe/myfile.txt` Ņ–Đˇ ĐŋĐžŅ‡Đ°Ņ‚ĐēĐžĐ˛ĐžŅŽ ĐēĐžŅĐžŅŽ Ņ€Đ¸ŅĐēĐžŅŽ (`/`). + +ĐŖ Ņ‚Đ°ĐēĐžĐŧ҃ виĐŋадĐē҃ URL Đ˛Đ¸ĐŗĐģŅĐ´Đ°Ņ‚Đ¸ĐŧĐĩ Ņ‚Đ°Đē: `/files//home/johndoe/myfile.txt`, Ņ–Đˇ ĐŋĐžĐ´Đ˛Ņ–ĐšĐŊĐžŅŽ ĐēĐžŅĐžŅŽ Ņ€Đ¸ŅĐēĐžŅŽ (`//`) ĐŧŅ–Đļ `files` Ņ– `home`. + +/// + +## ĐŸŅ–Đ´ŅŅƒĐŧĐžĐē + +З **FastAPI**, виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅŽŅ‡Đ¸ ĐēĐžŅ€ĐžŅ‚ĐēŅ–, Ņ–ĐŊŅ‚ŅƒŅ—Ņ‚Đ¸Đ˛ĐŊĐž ĐˇŅ€ĐžĐˇŅƒĐŧŅ–ĐģŅ– Ņ‚Đ° ŅŅ‚Đ°ĐŊĐ´Đ°Ņ€Ņ‚ĐŊŅ– ĐžĐŗĐžĐģĐžŅˆĐĩĐŊĐŊŅ Ņ‚Đ¸ĐŋŅ–Đ˛ Python, Ви ĐžŅ‚Ņ€Đ¸ĐŧŅƒŅ”Ņ‚Đĩ: + +* ĐŸŅ–Đ´Ņ‚Ņ€Đ¸ĐŧĐē҃ в Ņ€ĐĩдаĐēŅ‚ĐžŅ€Ņ–: ĐŋĐĩŅ€ĐĩĐ˛Ņ–Ņ€Đēа ĐŋĐžĐŧиĐģĐžĐē, Đ°Đ˛Ņ‚ĐžĐ´ĐžĐŋОвĐŊĐĩĐŊĐŊŅ Ņ‚ĐžŅ‰Đž. +* "ĐŸĐ°Ņ€ŅĐ¸ĐŊĐŗ" даĐŊĐ¸Ņ… +* ВаĐģŅ–Đ´Đ°Ņ†Ņ–ŅŽ даĐŊĐ¸Ņ… +* АĐŊĐžŅ‚Đ°Ņ†Ņ–ŅŽ API Ņ‚Đ° Đ°Đ˛Ņ‚ĐžĐŧĐ°Ņ‚Đ¸Ņ‡ĐŊ҃ Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Ņ–ŅŽ + +І ваĐŧ ĐŋĐžŅ‚Ņ€Ņ–ĐąĐŊĐž ĐžĐŗĐžĐģĐžŅĐ¸Ņ‚Đ¸ Ņ—Ņ… ĐģĐ¸ŅˆĐĩ ОдиĐŊ Ņ€Đ°Đˇ. + +ĐĻĐĩ, ĐšĐŧĐžĐ˛Ņ–Ņ€ĐŊĐž, ĐžŅĐŊОвĐŊа видиĐŧа ĐŋĐĩŅ€ĐĩĐ˛Đ°ĐŗĐ° **FastAPI** ĐŋĐžŅ€Ņ–Đ˛ĐŊŅĐŊĐž С аĐģŅŒŅ‚ĐĩŅ€ĐŊĐ°Ņ‚Đ¸Đ˛ĐŊиĐŧи ҄ҀĐĩĐšĐŧĐ˛ĐžŅ€ĐēаĐŧи (ĐžĐēҀҖĐŧ Đ˛Đ¸ŅĐžĐēĐžŅ— ĐŋŅ€ĐžĐ´ŅƒĐēŅ‚Đ¸Đ˛ĐŊĐžŅŅ‚Ņ–). diff --git a/docs/uk/docs/tutorial/query-param-models.md b/docs/uk/docs/tutorial/query-param-models.md new file mode 100644 index 000000000..97eb82fa1 --- /dev/null +++ b/docs/uk/docs/tutorial/query-param-models.md @@ -0,0 +1,68 @@ +# МодĐĩĐģŅ– Query ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Ņ–Đ˛ + +Đ¯ĐēŅ‰Đž ҃ Đ’Đ°Ņ Ņ” ĐŗŅ€ŅƒĐŋа **query ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Ņ–Đ˛**, ŅĐēŅ– ĐŋĐžĐ˛â€™ŅĐˇĐ°ĐŊŅ– ĐŧŅ–Đļ ŅĐžĐąĐžŅŽ, Ви ĐŧĐžĐļĐĩŅ‚Đĩ ŅŅ‚Đ˛ĐžŅ€Đ¸Ņ‚Đ¸ **Pydantic-ĐŧОдĐĩĐģҌ** Đ´ĐģŅ Ņ—Ņ… ĐžĐŗĐžĐģĐžŅˆĐĩĐŊĐŊŅ. + +ĐĻĐĩ дОСвОĐģĐ¸Ņ‚ŅŒ ВаĐŧ **ĐŋĐžĐ˛Ņ‚ĐžŅ€ĐŊĐž виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ ĐŧОдĐĩĐģҌ** ҃ **Ņ€Ņ–ĐˇĐŊĐ¸Ņ… ĐŧŅ–ŅŅ†ŅŅ…**, а Ņ‚Đ°ĐēĐžĐļ ĐžĐŗĐžĐģĐžŅˆŅƒĐ˛Đ°Ņ‚Đ¸ ĐŋĐĩŅ€ĐĩĐ˛Ņ–Ņ€Đēи Ņ‚Đ° ĐŧĐĩŅ‚Đ°Đ´Đ°ĐŊŅ– Đ´ĐģŅ Đ˛ŅŅ–Ņ… ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Ņ–Đ˛ ОдĐŊĐžŅ‡Đ°ŅĐŊĐž. 😎 + +/// note | ĐŸŅ€Đ¸ĐŧŅ–Ņ‚Đēа + +ĐĻŅ ĐŧĐžĐļĐģĐ¸Đ˛Ņ–ŅŅ‚ŅŒ ĐŋŅ–Đ´Ņ‚Ņ€Đ¸ĐŧŅƒŅ”Ņ‚ŅŒŅŅ, ĐŋĐžŅ‡Đ¸ĐŊĐ°ŅŽŅ‡Đ¸ С вĐĩҀҁҖҗ FastAPI `0.115.0`. 🤓 + +/// + +## Query ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ¸ С Pydantic-ĐŧОдĐĩĐģĐģŅŽ + +ĐžĐŗĐžĐģĐžŅŅ–Ņ‚ŅŒ **query ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ¸**, ŅĐēŅ– ВаĐŧ ĐŋĐžŅ‚Ņ€Ņ–ĐąĐŊŅ–, ҃ **Pydantic-ĐŧОдĐĩĐģŅ–**, а ĐŋĐžŅ‚Ņ–Đŧ ĐžĐŗĐžĐģĐžŅŅ–Ņ‚ŅŒ ҆ĐĩĐš ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ ŅĐē `Query`: + +{* ../../docs_src/query_param_models/tutorial001_an_py310.py hl[9:13,17] *} + +**FastAPI** ĐąŅƒĐ´Đĩ **Đ˛Đ¸Ņ‚ŅĐŗŅƒĐ˛Đ°Ņ‚Đ¸** даĐŊŅ– Đ´ĐģŅ **ĐēĐžĐļĐŊĐžĐŗĐž ĐŋĐžĐģŅ** С **query ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Ņ–Đ˛** ҃ СаĐŋĐ¸Ņ‚Ņ– Ņ‚Đ° ĐŋĐĩŅ€ĐĩĐ´Đ°Đ˛Đ°Ņ‚Đ¸ Ņ—Ņ… ҃ виСĐŊĐ°Ņ‡ĐĩĐŊ҃ ваĐŧи Pydantic-ĐŧОдĐĩĐģҌ. + +## ПĐĩŅ€ĐĩĐ˛Ņ–Ņ€Ņ‚Đĩ Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Ņ–ŅŽ + +Ви ĐŧĐžĐļĐĩŅ‚Đĩ ĐŋĐžĐąĐ°Ņ‡Đ¸Ņ‚Đ¸ ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ¸ СаĐŋĐ¸Ņ‚Ņƒ в UI Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Ņ–Ņ— Са `/docs`: + +
+ +
+ +## Đ—Đ°ĐąĐžŅ€ĐžĐŊа ĐˇĐ°ĐšĐ˛Đ¸Ņ… Query ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Ņ–Đ˛ + +ĐŖ Đ´ĐĩŅĐēĐ¸Ņ… ĐžŅĐžĐąĐģĐ¸Đ˛Đ¸Ņ… виĐŋадĐēĐ°Ņ… (ĐšĐŧĐžĐ˛Ņ–Ņ€ĐŊĐž, ĐŊĐĩ Đ´ŅƒĐļĐĩ ĐŋĐžŅˆĐ¸Ņ€ĐĩĐŊĐ¸Ņ…) Ви ĐŧĐžĐļĐĩŅ‚Đĩ ĐˇĐ°Ņ…ĐžŅ‚Ņ–Ņ‚Đ¸ **ОйĐŧĐĩĐļĐ¸Ņ‚Đ¸** query ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ¸, ŅĐēŅ– дОСвОĐģĐĩĐŊĐž ĐžŅ‚Ņ€Đ¸ĐŧŅƒĐ˛Đ°Ņ‚Đ¸. + +Ви ĐŧĐžĐļĐĩŅ‚Đĩ виĐēĐžŅ€Đ¸ŅŅ‚Đ°Ņ‚Đ¸ ĐēĐžĐŊŅ„Ņ–ĐŗŅƒŅ€Đ°Ņ†Ņ–ŅŽ ĐŧОдĐĩĐģŅ– Pydantic, Ņ‰ĐžĐą ĐˇĐ°ĐąĐžŅ€ĐžĐŊĐ¸Ņ‚Đ¸ (`forbid`) ĐąŅƒĐ´ŅŒ-ŅĐēŅ– ĐˇĐ°ĐšĐ˛Ņ– (`extra`) ĐŋĐžĐģŅ: + +{* ../../docs_src/query_param_models/tutorial002_an_py310.py hl[10] *} + +Đ¯ĐēŅ‰Đž ĐēĐģŅ–Ņ”ĐŊŅ‚ ҁĐŋŅ€ĐžĐąŅƒŅ” ĐŊĐ°Đ´Ņ–ŅĐģĐ°Ņ‚Đ¸ **ĐˇĐ°ĐšĐ˛Ņ–** даĐŊŅ– ҃ **query ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ°Ņ…**, Đ˛Ņ–ĐŊ ĐžŅ‚Ņ€Đ¸ĐŧĐ°Ņ” **ĐŋĐžĐŧиĐģĐē҃**. + +НаĐŋŅ€Đ¸ĐēĐģад, ŅĐēŅ‰Đž ĐēĐģŅ–Ņ”ĐŊŅ‚ ҁĐŋŅ€ĐžĐąŅƒŅ” ĐŊĐ°Đ´Ņ–ŅĐģĐ°Ņ‚Đ¸ query ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ `tool` ĐˇŅ– СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅĐŧ `plumbus`, ŅĐē ҃ Ņ†ŅŒĐžĐŧ҃ СаĐŋĐ¸Ņ‚Ņ–: + +```http +https://example.com/items/?limit=10&tool=plumbus +``` + +Đ’Ņ–ĐŊ ĐžŅ‚Ņ€Đ¸ĐŧĐ°Ņ” Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´ŅŒ С **ĐŋĐžĐŧиĐģĐēĐžŅŽ**, ŅĐēа ĐŋĐžĐ˛Ņ–Đ´ĐžĐŧĐ¸Ņ‚ŅŒ, Ņ‰Đž query ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ `tool ` ĐŊĐĩ дОСвОĐģĐĩĐŊĐž: + +```json +{ + "detail": [ + { + "type": "extra_forbidden", + "loc": ["query", "tool"], + "msg": "Extra inputs are not permitted", + "input": "plumbus" + } + ] +} +``` + +## ĐŸŅ–Đ´ŅŅƒĐŧĐžĐē + +Ви ĐŧĐžĐļĐĩŅ‚Đĩ виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ **Pydantic-ĐŧОдĐĩĐģŅ–** Đ´ĐģŅ ĐžĐŗĐžĐģĐžŅˆĐĩĐŊĐŊŅ **query ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Ņ–Đ˛** ҃ **FastAPI**. 😎 + +/// tip | ĐŸŅ–Đ´ĐēаСĐēа + +ĐĄĐŋОКĐģĐĩŅ€: Ви Ņ‚Đ°ĐēĐžĐļ ĐŧĐžĐļĐĩŅ‚Đĩ виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ Pydantic-ĐŧОдĐĩĐģŅ– Đ´ĐģŅ ĐžĐŗĐžĐģĐžŅˆĐĩĐŊĐŊŅ cookie Ņ‚Đ° ĐˇĐ°ĐŗĐžĐģОвĐēŅ–Đ˛, аĐģĐĩ ĐŋŅ€Đž ҆Đĩ Ви Đ´Ņ–ĐˇĐŊĐ°Ņ”Ņ‚ĐĩŅŅ ĐŋŅ–ĐˇĐŊŅ–ŅˆĐĩ в Ņ†ŅŒĐžĐŧ҃ ĐŋĐžŅŅ–ĐąĐŊиĐē҃. đŸ¤Ģ + +/// diff --git a/docs/uk/docs/tutorial/query-params-str-validations.md b/docs/uk/docs/tutorial/query-params-str-validations.md new file mode 100644 index 000000000..cd3f4ad93 --- /dev/null +++ b/docs/uk/docs/tutorial/query-params-str-validations.md @@ -0,0 +1,491 @@ +# Query ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ¸ Ņ‚Đ° ваĐģŅ–Đ´Đ°Ņ†Ņ–Ņ Ņ€ŅĐ´ĐēŅ–Đ˛ + +**FastAPI** дОСвОĐģŅŅ” ĐžĐŗĐžĐģĐžŅˆŅƒĐ˛Đ°Ņ‚Đ¸ Đ´ĐžĐ´Đ°Ņ‚ĐēĐžĐ˛Ņƒ Ņ–ĐŊŅ„ĐžŅ€ĐŧĐ°Ņ†Ņ–ŅŽ Ņ‚Đ° виĐēĐžĐŊŅƒĐ˛Đ°Ņ‚Đ¸ ваĐģŅ–Đ´Đ°Ņ†Ņ–ŅŽ Đ´ĐģŅ Đ’Đ°ŅˆĐ¸Ņ… ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Ņ–Đ˛. + +Đ ĐžĐˇĐŗĐģŅĐŊĐĩĐŧĐž ҆ĐĩĐš Đ´ĐžĐ´Đ°Ņ‚ĐžĐē ŅĐē ĐŋŅ€Đ¸ĐēĐģад: + +{* ../../docs_src/query_params_str_validations/tutorial001_py310.py hl[7] *} + +Query ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ `q` ĐŧĐ°Ņ” Ņ‚Đ¸Đŋ `str | None`, Ņ‰Đž ОСĐŊĐ°Ņ‡Đ°Ņ”, Ņ‰Đž Đ˛Ņ–ĐŊ ĐŧĐžĐļĐĩ ĐąŅƒŅ‚Đ¸ ŅĐē `str`, Ņ‚Đ°Đē Ņ– `None`. За СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ Đ˛Ņ–ĐŊ ĐŧĐ°Ņ” СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ `None`, Ņ‚ĐžĐŧ҃ FastAPI Ņ€ĐžĐˇŅƒĐŧŅ–Ņ”, Ņ‰Đž ҆ĐĩĐš ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ ĐŊĐĩ Ņ” ОйОв'ŅĐˇĐēОвиĐŧ. + +/// note | ĐŸŅ€Đ¸ĐŧŅ–Ņ‚Đēа + +FastAPI СĐŊĐ°Ņ”, Ņ‰Đž `q` ĐŊĐĩ Ņ” ĐžĐąĐžĐ˛â€™ŅĐˇĐēОвиĐŧ, ĐˇĐ°Đ˛Đ´ŅĐēи СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅŽ Са СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ `= None`. + +ВиĐēĐžŅ€Đ¸ŅŅ‚Đ°ĐŊĐŊŅ `str | None` дОСвОĐģĐ¸Ņ‚ŅŒ Đ’Đ°ŅˆĐžĐŧ҃ Ņ€ĐĩдаĐēŅ‚ĐžŅ€Ņƒ ĐēĐžĐ´Ņƒ ĐŊĐ°Đ´Đ°Đ˛Đ°Ņ‚Đ¸ ĐēŅ€Đ°Ņ‰Ņƒ ĐŋŅ–Đ´Ņ‚Ņ€Đ¸ĐŧĐē҃ Ņ‚Đ° Đ˛Đ¸ŅĐ˛ĐģŅŅ‚Đ¸ ĐŋĐžĐŧиĐģĐēи. + +/// + +## Đ”ĐžĐ´Đ°Ņ‚ĐēОва ваĐģŅ–Đ´Đ°Ņ†Ņ–Ņ + +Ми Ņ…ĐžŅ‡ĐĩĐŧĐž, Ņ‰ĐžĐą ĐŊĐ°Đ˛Ņ–Ņ‚ŅŒ ŅĐēŅ‰Đž `q` Ņ” ĐŊĐĩĐžĐąĐžĐ˛â€™ŅĐˇĐēОвиĐŧ, **ĐšĐžĐŗĐž дОвĐļиĐŊа ĐŊĐĩ ĐŋĐĩŅ€ĐĩĐ˛Đ¸Ņ‰ŅƒĐ˛Đ°Đģа 50 ŅĐ¸ĐŧвОĐģŅ–Đ˛**, ŅĐēŅ‰Đž Đ˛Ņ–ĐŊ Đ˛ŅĐĩ Đļ ĐąŅƒĐ´Đĩ ĐŋĐĩŅ€ĐĩдаĐŊиК. + +### ІĐŧĐŋĐžŅ€Ņ‚ `Query` Ņ‚Đ° `Annotated` + +ЊОй ҆Đĩ ĐˇŅ€ĐžĐąĐ¸Ņ‚Đ¸, ҁĐŋĐžŅ‡Đ°Ņ‚Đē҃ Ņ–ĐŧĐŋĐžŅ€Ņ‚ŅƒŅ”ĐŧĐž: + +* `Query` С `fastapi` +* `Annotated` С `typing` + +{* ../../docs_src/query_params_str_validations/tutorial002_an_py310.py hl[1,3] *} + +/// info | ІĐŊŅ„ĐžŅ€ĐŧĐ°Ņ†Ņ–Ņ + +FastAPI дОдав ĐŋŅ–Đ´Ņ‚Ņ€Đ¸ĐŧĐē҃ `Annotated` (Ņ– ĐŋĐžŅ‡Đ°Đ˛ Ņ€ĐĩĐēĐžĐŧĐĩĐŊĐ´ŅƒĐ˛Đ°Ņ‚Đ¸ ĐšĐžĐŗĐž) ҃ вĐĩҀҁҖҗ 0.95.0. + +Đ¯ĐēŅ‰Đž ҃ Đ’Đ°Ņ ŅŅ‚Đ°Ņ€Ņ–ŅˆĐ° вĐĩŅ€ŅŅ–Ņ, ĐŋŅ–Đ´ Ņ‡Đ°Ņ виĐēĐžŅ€Đ¸ŅŅ‚Đ°ĐŊĐŊŅ `Annotated` ĐŧĐžĐļŅƒŅ‚ŅŒ виĐŊиĐēĐ°Ņ‚Đ¸ ĐŋĐžĐŧиĐģĐēи. + +ПĐĩŅ€ĐĩĐēĐžĐŊĐ°ĐšŅ‚ĐĩŅŅ, Ņ‰Đž Ви [ĐžĐŊОвиĐģи вĐĩŅ€ŅŅ–ŅŽ FastAPI](../deployment/versions.md#upgrading-the-fastapi-versions){.internal-link target=_blank} Đ´Đž ĐŋŅ€Đ¸ĐŊаКĐŧĐŊŅ– 0.95.1, ĐŋĐĩŅ€Ņˆ ĐŊŅ–Đļ виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ `Annotated`. + +/// + +## ВиĐēĐžŅ€Đ¸ŅŅ‚Đ°ĐŊĐŊŅ `Annotated` ҃ Ņ‚Đ¸ĐŋŅ– ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ° `q` + +ПаĐŧâ€™ŅŅ‚Đ°Ņ”Ņ‚Đĩ, ŅĐē Ņ Ņ€Đ°ĐŊŅ–ŅˆĐĩ Ņ€ĐžĐˇĐŋĐžĐ˛Ņ–Đ´Đ°Đ˛, Ņ‰Đž `Annotated` ĐŧĐžĐļĐŊа виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ Đ´ĐģŅ дОдаваĐŊĐŊŅ ĐŧĐĩŅ‚Đ°Đ´Đ°ĐŊĐ¸Ņ… Đ´Đž ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Ņ–Đ˛ ҃ [Đ’ŅŅ‚ŅƒĐŋŅ– Đ´Đž Ņ‚Đ¸ĐŋŅ–Đ˛ Python](../python-types.md#type-hints-with-metadata-annotations){.internal-link target=_blank}? + +Đ—Đ°Ņ€Đ°Đˇ ŅĐ°ĐŧĐĩ Ņ‡Đ°Ņ виĐēĐžŅ€Đ¸ŅŅ‚Đ°Ņ‚Đ¸ ĐšĐžĐŗĐž Ņ€Đ°ĐˇĐžĐŧ Ņ–Đˇ FastAPI. 🚀 + +РаĐŊŅ–ŅˆĐĩ Đŧи ĐŧаĐģи Ņ‚Đ°Đē҃ аĐŊĐžŅ‚Đ°Ņ†Ņ–ŅŽ Ņ‚Đ¸Đŋ҃: + +//// tab | Python 3.10+ + +```Python +q: str | None = None +``` + +//// + +//// tab | Python 3.8+ + +```Python +q: Union[str, None] = None +``` + +//// + +ĐĸĐĩĐŋĐĩŅ€ Đŧи ĐˇĐ°ĐŗĐžŅ€ĐŊĐĩĐŧĐž Ņ—Ņ— ҃ `Annotated`, Ņ– ĐžŅ‚Ņ€Đ¸ĐŧĐ°Ņ”ĐŧĐž: + +//// tab | Python 3.10+ + +```Python +q: Annotated[str | None] = None +``` + +//// + +//// tab | Python 3.8+ + +```Python +q: Annotated[Union[str, None]] = None +``` + +//// + +ĐžĐąĐ¸Đ´Đ˛Ņ– ҆Җ вĐĩҀҁҖҗ ОСĐŊĐ°Ņ‡Đ°ŅŽŅ‚ŅŒ ОдĐŊĐĩ Đš Ņ‚Đĩ ŅĐ°ĐŧĐĩ: `q` — ҆Đĩ ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ, ŅĐēиК ĐŧĐžĐļĐĩ ĐąŅƒŅ‚Đ¸ `str` айО `None`, Ņ– Са СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ ĐŧĐ°Ņ” СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ `None`. + +А Ņ‚ĐĩĐŋĐĩŅ€ ĐŋĐĩŅ€ĐĩŅ…ĐžĐ´Đ¸ĐŧĐž Đ´Đž ҆ҖĐēĐ°Đ˛ĐžĐŗĐž! 🎉 + +## ДодаваĐŊĐŊŅ `Query` Đ´Đž `Annotated` ҃ ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ `q` + +ĐĸĐĩĐŋĐĩŅ€, ĐēĐžĐģи ҃ ĐŊĐ°Ņ Ņ” `Annotated`, Đ´Đĩ Đŧи ĐŧĐžĐļĐĩĐŧĐž Đ´ĐžĐ´Đ°Đ˛Đ°Ņ‚Đ¸ Đ´ĐžĐ´Đ°Ņ‚ĐēĐžĐ˛Ņƒ Ņ–ĐŊŅ„ĐžŅ€ĐŧĐ°Ņ†Ņ–ŅŽ (СОĐēŅ€ĐĩĐŧа ваĐģŅ–Đ´Đ°Ņ†Ņ–ŅŽ), дОдаĐŧĐž `Query` Đ˛ŅĐĩŅ€ĐĩдиĐŊ҃ `Annotated` Ņ– Đ˛ŅŅ‚Đ°ĐŊОвиĐŧĐž ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ `max_length` ҃ `50`: + +{* ../../docs_src/query_params_str_validations/tutorial002_an_py310.py hl[9] *} + +ЗвĐĩŅ€ĐŊŅ–Ņ‚ŅŒ ŅƒĐ˛Đ°ĐŗŅƒ, Ņ‰Đž СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ Са СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ ҃ҁĐĩ ҉Đĩ `None`, Ņ‚ĐžĐŧ҃ ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ СаĐģĐ¸ŅˆĐ°Ņ”Ņ‚ŅŒŅŅ ĐŊĐĩОйОв'ŅĐˇĐēОвиĐŧ. + +АĐģĐĩ Ņ‚ĐĩĐŋĐĩŅ€, Đ´ĐžĐ´Đ°Đ˛ŅˆĐ¸ `Query(max_length=50)` Đ˛ŅĐĩŅ€ĐĩдиĐŊ҃ `Annotated`, Đŧи ĐŋĐžĐ˛Ņ–Đ´ĐžĐŧĐģŅŅ”ĐŧĐž FastAPI, Ņ‰Đž Ņ…ĐžŅ‡ĐĩĐŧĐž **Đ´ĐžĐ´Đ°Ņ‚ĐēĐžĐ˛Ņƒ ваĐģŅ–Đ´Đ°Ņ†Ņ–ŅŽ** Đ´ĐģŅ Ņ†ŅŒĐžĐŗĐž СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ — вОĐŊĐž ĐŧĐ°Ņ” ĐŧŅ–ŅŅ‚Đ¸Ņ‚Đ¸ ĐŧаĐēŅĐ¸Đŧ҃Đŧ 50 ŅĐ¸ĐŧвОĐģŅ–Đ˛. 😎 + +/// tip | ĐŸŅ–Đ´ĐēаСĐēа + +Ми виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅ”ĐŧĐž `Query()`, ĐžŅĐēŅ–ĐģҌĐēи ҆Đĩ **query ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ**. ДаĐģŅ– Đŧи Ņ€ĐžĐˇĐŗĐģŅĐŊĐĩĐŧĐž Ņ–ĐŊŅˆŅ– Đ˛Đ°Ņ€Ņ–Đ°ĐŊŅ‚Đ¸, ŅĐē-ĐžŅ‚ `Path()`, `Body()`, `Header()` Ņ‚Đ° `Cookie()`, ŅĐēŅ– ĐŋŅ€Đ¸ĐšĐŧĐ°ŅŽŅ‚ŅŒ ҂Җ ŅĐ°ĐŧŅ– Đ°Ņ€ĐŗŅƒĐŧĐĩĐŊŅ‚Đ¸, Ņ‰Đž Đš `Query()`. + +/// + +ĐĸĐĩĐŋĐĩŅ€ FastAPI: + +* **ПĐĩŅ€ĐĩĐ˛Ņ–Ņ€Đ¸Ņ‚ŅŒ** даĐŊŅ–, Ņ‰ĐžĐą ĐŋĐĩŅ€ĐĩĐēĐžĐŊĐ°Ņ‚Đ¸ŅŅ, Ņ‰Đž Ņ—Ņ…ĐŊŅ дОвĐļиĐŊа ĐŊĐĩ ĐŋĐĩŅ€ĐĩĐ˛Đ¸Ņ‰ŅƒŅ” 50 ŅĐ¸ĐŧвОĐģŅ–Đ˛ +* ПоĐēаĐļe **҇Җ҂Đē҃ ĐŋĐžĐŧиĐģĐē҃** ĐēĐģŅ–Ņ”ĐŊŅ‚Ņƒ, ŅĐēŅ‰Đž даĐŊŅ– ĐŊĐĩĐ´Ņ–ĐšŅĐŊŅ– +* **ЗадоĐē҃ĐŧĐĩĐŊŅ‚ŅƒŅ”** ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ в OpenAPI-ҁ҅ĐĩĐŧŅ– *ĐžĐŋĐĩŅ€Đ°Ņ†Ņ–Ņ— ҈ĐģŅŅ…Ņƒ* (Ņ‰Đž Đ˛Ņ–Đ´ĐžĐąŅ€Đ°ĐˇĐ¸Ņ‚ŅŒŅŅ в **Đ°Đ˛Ņ‚ĐžĐŧĐ°Ņ‚Đ¸Ņ‡ĐŊĐž ĐˇĐŗĐĩĐŊĐĩŅ€ĐžĐ˛Đ°ĐŊŅ–Đš Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Ņ–Ņ—**) + +## АĐģŅŒŅ‚ĐĩŅ€ĐŊĐ°Ņ‚Đ¸Đ˛ĐŊиК (ĐˇĐ°ŅŅ‚Đ°Ņ€Ņ–ĐģиК) ĐŧĐĩŅ‚ĐžĐ´: Query ŅĐē СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ Са СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ + +ĐŖ ĐŋĐžĐŋĐĩŅ€ĐĩĐ´ĐŊŅ–Ņ… вĐĩŅ€ŅŅ–ŅŅ… FastAPI (Đ´Đž 0.95.0) `Query` виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Đ˛ŅŅ ŅĐē СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ Са СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ Đ´ĐģŅ ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ°, а ĐŊĐĩ Đ˛ŅĐĩŅ€ĐĩдиĐŊŅ– `Annotated`. Ви, ĐšĐŧĐžĐ˛Ņ–Ņ€ĐŊĐž, ĐŋĐžĐąĐ°Ņ‡Đ¸Ņ‚Đĩ ĐēОд, ŅĐēиК виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅ” ҆ĐĩĐš ĐŋŅ–Đ´Ņ…Ņ–Đ´, Ņ‚ĐžĐŧ҃ Đ˛Đ°Ņ€Ņ‚Đž Ņ€ĐžĐˇĐŗĐģŅĐŊŅƒŅ‚Đ¸ ĐšĐžĐŗĐž. + +/// tip | ĐŸŅ–Đ´ĐēаСĐēа + +ДĐģŅ ĐŊĐžĐ˛ĐžĐŗĐž ĐēĐžĐ´Ņƒ Ņ‚Đ° ĐēĐžĐģи ҆Đĩ ĐŧĐžĐļĐģивО, виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐšŅ‚Đĩ `Annotated`, ŅĐē ĐŋĐžĐēаСаĐŊĐž Đ˛Đ¸Ņ‰Đĩ. ĐĻĐĩ ĐŧĐ°Ņ” ĐąĐ°ĐŗĐ°Ņ‚Đž ĐŋĐĩŅ€ĐĩĐ˛Đ°Đŗ (ĐŋĐžŅŅĐŊĐĩĐŊĐ¸Ņ… ĐŊиĐļ҇Đĩ) Ņ– ĐŊĐĩ ĐŧĐ°Ņ” ĐŊĐĩĐ´ĐžĐģŅ–ĐēŅ–Đ˛. 🍰 + +/// + +РаĐŊŅ–ŅˆĐĩ Đŧи ĐŋĐ¸ŅĐ°Đģи `Query()` ŅĐē СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ Са СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ Đ´ĐģŅ ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ° Ņ„ŅƒĐŊĐē҆Җҗ, Đ˛ŅŅ‚Đ°ĐŊОвĐģŅŽŅŽŅ‡Đ¸ `max_length` ҃ 50: + +{* ../../docs_src/query_params_str_validations/tutorial002_py310.py hl[7] *} + +ĐžŅĐēŅ–ĐģҌĐēи в Ņ†ŅŒĐžĐŧ҃ виĐŋадĐē҃ (ĐąĐĩС `Annotated`) ĐŊаĐŧ ĐŋĐžŅ‚Ņ€Ņ–ĐąĐŊĐž СаĐŧŅ–ĐŊĐ¸Ņ‚Đ¸ `None` ҃ Ņ„ŅƒĐŊĐē҆Җҗ ĐŊа `Query()`, Ņ‚ĐĩĐŋĐĩŅ€ Đŧи ĐŋОвиĐŊĐŊŅ– ŅĐ˛ĐŊĐž Đ˛ŅŅ‚Đ°ĐŊĐžĐ˛Đ¸Ņ‚Đ¸ СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ Са СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ ҇ĐĩŅ€ĐĩС ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ `Query(default=None)`. ĐĻĐĩ виĐēĐžĐŊŅƒŅ” Ņ‚Ņƒ ŅĐ°Đŧ҃ Ņ€ĐžĐģҌ виСĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ Са СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ (ĐŋŅ€Đ¸ĐŊаКĐŧĐŊŅ– Đ´ĐģŅ FastAPI). + +ĐĸаĐēиĐŧ Ņ‡Đ¸ĐŊĐžĐŧ: + +```Python +q: str | None = Query(default=None) +``` + +...Ņ€ĐžĐąĐ¸Ņ‚ŅŒ ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ ĐŊĐĩĐžĐąĐžĐ˛â€™ŅĐˇĐēОвиĐŧ ĐˇŅ– СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅĐŧ Са СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ `None`, Ņ‰Đž ĐĩĐēĐ˛Ņ–Đ˛Đ°ĐģĐĩĐŊŅ‚ĐŊĐž: + + +```Python +q: str | None = None +``` +АĐģĐĩ ҃ вĐĩҀҁҖҗ С `Query` Đŧи ŅĐ˛ĐŊĐž вĐēĐ°ĐˇŅƒŅ”ĐŧĐž, Ņ‰Đž ҆Đĩ query ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ. + +ДаĐģŅ– Đŧи ĐŧĐžĐļĐĩĐŧĐž ĐŋĐĩŅ€ĐĩĐ´Đ°Đ˛Đ°Ņ‚Đ¸ `Query` Đ´ĐžĐ´Đ°Ņ‚ĐēĐžĐ˛Ņ– ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ¸, СОĐēŅ€ĐĩĐŧа `max_length`, ŅĐēиК ĐˇĐ°ŅŅ‚ĐžŅĐžĐ˛ŅƒŅ”Ņ‚ŅŒŅŅ Đ´Đž Ņ€ŅĐ´ĐēŅ–Đ˛: + +```Python +q: str | None = Query(default=None, max_length=50) +``` + +ĐĻĐĩ СайĐĩСĐŋĐĩŅ‡Đ¸Ņ‚ŅŒ ваĐģŅ–Đ´Đ°Ņ†Ņ–ŅŽ даĐŊĐ¸Ņ…, вивĐĩĐ´Đĩ ĐˇŅ€ĐžĐˇŅƒĐŧŅ–Đģ҃ ĐŋĐžĐŧиĐģĐē҃ ҃ Ņ€Đ°ĐˇŅ– ĐŊĐĩĐ´Ņ–ĐšŅĐŊĐ¸Ņ… даĐŊĐ¸Ņ… Ņ– СадОĐē҃ĐŧĐĩĐŊŅ‚ŅƒŅ” ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ ҃ ҁ҅ĐĩĐŧŅ– OpenAPI *ĐžĐŋĐĩŅ€Đ°Ņ†Ņ–Ņ— ҈ĐģŅŅ…Ņƒ*. + +### `Query` ŅĐē СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ Са СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ айО Đ˛ŅĐĩŅ€ĐĩдиĐŊŅ– `Annotated` + +ВаĐļĐģивО ĐŋаĐŧâ€™ŅŅ‚Đ°Ņ‚Đ¸, ŅĐēŅ‰Đž виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ `Query` Đ˛ŅĐĩŅ€ĐĩдиĐŊŅ– `Annotated`, ĐŊĐĩ ĐŧĐžĐļĐŊа ĐˇĐ°Đ´Đ°Đ˛Đ°Ņ‚Đ¸ ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ `default` ҃ `Query`. + +ЗаĐŧŅ–ŅŅ‚ŅŒ Ņ†ŅŒĐžĐŗĐž виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐšŅ‚Đĩ СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ Са СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ ҃ ŅĐ°ĐŧŅ–Đš Ņ„ŅƒĐŊĐē҆Җҗ. ІĐŊаĐē҈Đĩ ҆Đĩ ĐąŅƒĐ´Đĩ ĐŊĐĩĐģĐžĐŗŅ–Ņ‡ĐŊĐž. + +НаĐŋŅ€Đ¸ĐēĐģад, ҆ĐĩĐš Đ˛Đ°Ņ€Ņ–Đ°ĐŊŅ‚ Ņ” ĐŊĐĩĐēĐžŅ€ĐĩĐēŅ‚ĐŊиĐŧ: + +```Python +q: Annotated[str, Query(default="rick")] = "morty" +``` + +...Ņ‚ĐžĐŧ҃, Ņ‰Đž ĐŊĐĩ ĐˇŅ€ĐžĐˇŅƒĐŧŅ–ĐģĐž, ŅĐēĐĩ СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ ĐŧĐ°Ņ” ĐąŅƒŅ‚Đ¸ СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅĐŧ Са СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ: `"rick"` Ņ‡Đ¸ `"morty"`. + +ĐšĐžŅ€ĐĩĐēŅ‚ĐŊŅ– Đ˛Đ°Ņ€Ņ–Đ°ĐŊŅ‚Đ¸: + +```Python +q: Annotated[str, Query()] = "rick" +``` + +...айО ҃ ŅŅ‚Đ°Ņ€Đ¸Ņ… ĐēĐžĐ´ĐžĐ˛Đ¸Ņ… ĐąĐ°ĐˇĐ°Ņ… Ви СĐŊаКдĐĩŅ‚Đĩ: + +```Python +q: str = Query(default="rick") +``` + +### ПĐĩŅ€ĐĩĐ˛Đ°ĐŗĐ¸ виĐēĐžŅ€Đ¸ŅŅ‚Đ°ĐŊĐŊŅ `Annotated` + +**ВиĐēĐžŅ€Đ¸ŅŅ‚Đ°ĐŊĐŊŅ `Annotated` Ņ” Ņ€ĐĩĐēĐžĐŧĐĩĐŊдОваĐŊиĐŧ** СаĐŧŅ–ŅŅ‚ŅŒ СадаĐŊĐŊŅ СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ Са СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ ҃ ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ°Ņ… Ņ„ŅƒĐŊĐē҆Җҗ, ĐžŅĐēŅ–ĐģҌĐēи вОĐŊĐž **ĐēŅ€Đ°Ņ‰Đĩ** С ĐēŅ–ĐģҌĐēĐžŅ… ĐŋŅ€Đ¸Ņ‡Đ¸ĐŊ. 🤓 + +ЗĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ **Са СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ** ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ° **Ņ„ŅƒĐŊĐē҆Җҗ** Ņ” ĐšĐžĐŗĐž **Ņ„Đ°ĐēŅ‚Đ¸Ņ‡ĐŊиĐŧ СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅĐŧ Са СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ**, Ņ‰Đž Ņ” ĐąŅ–ĐģҌ҈ Ņ–ĐŊŅ‚ŅƒŅ—Ņ‚Đ¸Đ˛ĐŊиĐŧ ҃ Python ĐˇĐ°ĐŗĐ°ĐģĐžĐŧ. 😌 + +Ви ĐŧĐžĐļĐĩŅ‚Đĩ **виĐēĐģиĐēĐ°Ņ‚Đ¸** Ņ‚Ņƒ ŅĐ°Đŧ҃ Ņ„ŅƒĐŊĐēŅ†Ņ–ŅŽ **в Ņ–ĐŊŅˆĐ¸Ņ… ĐŧŅ–ŅŅ†ŅŅ…** ĐąĐĩС FastAPI, Ņ– вОĐŊа **ĐŋŅ€Đ°Ņ†ŅŽĐ˛Đ°Ņ‚Đ¸ĐŧĐĩ ĐžŅ‡Ņ–ĐēŅƒĐ˛Đ°ĐŊĐž**. Đ¯ĐēŅ‰Đž ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ Ņ” **ĐžĐąĐžĐ˛â€™ŅĐˇĐēОвиĐŧ** (ĐąĐĩС СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ Са СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ), Đ’Đ°Ņˆ **Ņ€ĐĩдаĐēŅ‚ĐžŅ€** ĐŋĐžĐ˛Ņ–Đ´ĐžĐŧĐ¸Ņ‚ŅŒ ĐŋŅ€Đž ĐŋĐžĐŧиĐģĐē҃, а **Python** Ņ‚Đ°ĐēĐžĐļ Đ˛Đ¸Đ´Đ°ŅŅ‚ŅŒ ĐŋĐžĐŧиĐģĐē҃, ŅĐēŅ‰Đž Ви виĐēĐžĐŊĐ°Ņ”Ņ‚Đĩ Ņ„ŅƒĐŊĐēŅ†Ņ–ŅŽ ĐąĐĩС ĐŋĐĩŅ€ĐĩдаваĐŊĐŊŅ Ņ†ŅŒĐžĐŗĐž ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ°. + +Đ¯ĐēŅ‰Đž Ви ĐŊĐĩ виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅ”Ņ‚Đĩ `Annotated`, а виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅ”Ņ‚Đĩ **(ŅŅ‚Đ°Ņ€Đ¸Đš) ŅŅ‚Đ¸ĐģҌ СĐŊĐ°Ņ‡ĐĩĐŊҌ Са СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ**, Ņ‚Đž ĐŋŅ€Đ¸ виĐēĐģиĐē҃ ҆ҖҔҗ Ņ„ŅƒĐŊĐē҆Җҗ ĐąĐĩС FastAPI **в Ņ–ĐŊŅˆĐ¸Ņ… ĐŧŅ–ŅŅ†ŅŅ…**, ĐŋĐžŅ‚Ņ€Ņ–ĐąĐŊĐž **ĐŊĐĩ ĐˇĐ°ĐąŅƒŅ‚Đ¸** ĐŋĐĩŅ€ĐĩĐ´Đ°Ņ‚Đ¸ Ņ—Đš Đ°Ņ€ĐŗŅƒĐŧĐĩĐŊŅ‚Đ¸, Ņ–ĐŊаĐē҈Đĩ СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ ĐąŅƒĐ´ŅƒŅ‚ŅŒ Đ˛Ņ–Đ´Ņ€Ņ–ĐˇĐŊŅŅ‚Đ¸ŅŅ Đ˛Ņ–Đ´ ĐžŅ‡Ņ–ĐēŅƒĐ˛Đ°ĐŊĐ¸Ņ… (ĐŊаĐŋŅ€Đ¸ĐēĐģад, Ви ĐžŅ‚Ņ€Đ¸ĐŧĐ°Ņ”Ņ‚Đĩ `QueryInfo` айО ĐŋĐžĐ´Ņ–ĐąĐŊĐĩ СаĐŧŅ–ŅŅ‚ŅŒ `str`). Đ’Đ°Ņˆ Ņ€ĐĩдаĐēŅ‚ĐžŅ€ ĐŊĐĩ ĐŋĐžĐ˛Ņ–Đ´ĐžĐŧĐ¸Ņ‚ŅŒ ĐŋŅ€Đž ĐŋĐžĐŧиĐģĐē҃, Ņ– Python Ņ‚Đ°ĐēĐžĐļ ĐŊĐĩ Đ˛Đ¸Đ´Đ°ŅŅ‚ŅŒ ĐŋĐžĐŧиĐģĐē҃ ĐŋŅ€Đ¸ СаĐŋ҃ҁĐē҃ Ņ„ŅƒĐŊĐē҆Җҗ, ĐŋĐžĐēи ĐŊĐĩ виĐŊиĐēĐŊĐĩ ĐŋĐžĐŧиĐģĐēа ĐŋŅ–Đ´ Ņ‡Đ°Ņ виĐēĐžĐŊаĐŊĐŊŅ ĐžĐŋĐĩŅ€Đ°Ņ†Ņ–Đš ҃ҁĐĩŅ€ĐĩдиĐŊŅ–. + +ĐžŅĐēŅ–ĐģҌĐēи `Annotated` ĐŧĐžĐļĐĩ ĐŧŅ–ŅŅ‚Đ¸Ņ‚Đ¸ ĐēŅ–ĐģҌĐēа аĐŊĐžŅ‚Đ°Ņ†Ņ–Đš ĐŧĐĩŅ‚Đ°Đ´Đ°ĐŊĐ¸Ņ…, Ви ĐŊĐ°Đ˛Ņ–Ņ‚ŅŒ ĐŧĐžĐļĐĩŅ‚Đĩ виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ Ņ‚Ņƒ ŅĐ°Đŧ҃ Ņ„ŅƒĐŊĐēŅ†Ņ–ŅŽ С Ņ–ĐŊŅˆĐ¸Đŧи Ņ–ĐŊŅŅ‚Ņ€ŅƒĐŧĐĩĐŊŅ‚Đ°Đŧи, Ņ‚Đ°ĐēиĐŧи ŅĐē Typer. 🚀 + +## ДодаваĐŊĐŊŅ Đ´ĐžĐ´Đ°Ņ‚ĐēĐžĐ˛Đ¸Ņ… ваĐģŅ–Đ´Đ°Ņ†Ņ–Đš + +Ви Ņ‚Đ°ĐēĐžĐļ ĐŧĐžĐļĐĩŅ‚Đĩ Đ´ĐžĐ´Đ°Ņ‚Đ¸ ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ `min_length`: + +{* ../../docs_src/query_params_str_validations/tutorial003_an_py310.py hl[10] *} + +## ДодаваĐŊĐŊŅ Ņ€ĐĩĐŗŅƒĐģŅŅ€ĐŊĐ¸Ņ… Đ˛Đ¸Ņ€Đ°ĐˇŅ–Đ˛ + +Ви ĐŧĐžĐļĐĩŅ‚Đĩ виСĐŊĐ°Ņ‡Đ¸Ņ‚Đ¸ Ņ€ĐĩĐŗŅƒĐģŅŅ€ĐŊиК Đ˛Đ¸Ņ€Đ°Đˇ pattern, ŅĐēĐžĐŧ҃ ĐŧĐ°Ņ” Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´Đ°Ņ‚Đ¸ ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ: + +{* ../../docs_src/query_params_str_validations/tutorial004_an_py310.py hl[11] *} + +ĐĻĐĩĐš ĐēĐžĐŊĐēŅ€ĐĩŅ‚ĐŊиК ŅˆĐ°ĐąĐģĐžĐŊ Ņ€ĐĩĐŗŅƒĐģŅŅ€ĐŊĐžĐŗĐž Đ˛Đ¸Ņ€Đ°ĐˇŅƒ ĐŋĐĩŅ€ĐĩĐ˛Ņ–Ņ€ŅŅ”, Ņ‰Đž ĐžŅ‚Ņ€Đ¸ĐŧаĐŊĐĩ СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ°: + +* `^`: ĐŋĐžŅ‡Đ¸ĐŊĐ°Ņ”Ņ‚ŅŒŅŅ С ĐŊĐ°ŅŅ‚ŅƒĐŋĐŊĐ¸Ņ… ŅĐ¸ĐŧвОĐģŅ–Đ˛, ĐŋĐĩŅ€ĐĩĐ´ ŅĐēиĐŧи ĐŊĐĩĐŧĐ°Ņ” Ņ–ĐŊŅˆĐ¸Ņ… ŅĐ¸ĐŧвОĐģŅ–Đ˛. +* `fixedquery`: Ņ‚ĐžŅ‡ĐŊĐž Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´Đ°Ņ” СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅŽ `fixedquery`. +* `$`: СаĐēŅ–ĐŊŅ‡ŅƒŅ”Ņ‚ŅŒŅŅ Ņ‚ŅƒŅ‚, ĐŋҖҁĐģŅ `fixedquery` ĐŊĐĩĐŧĐ°Ņ” ĐļОдĐŊĐ¸Ņ… ŅĐ¸ĐŧвОĐģŅ–Đ˛. + +Đ¯ĐēŅ‰Đž Ви ĐŋĐžŅ‡ŅƒĐ˛Đ°Ņ”Ņ‚ĐĩŅŅ Ņ€ĐžĐˇĐŗŅƒĐąĐģĐĩĐŊĐž Ņ‰ĐžĐ´Đž **"Ņ€ĐĩĐŗŅƒĐģŅŅ€ĐŊĐ¸Ņ… Đ˛Đ¸Ņ€Đ°ĐˇŅ–Đ˛"**, ĐŊĐĩ Ņ…Đ˛Đ¸ĐģŅŽĐšŅ‚ĐĩŅŅ. ВоĐŊи Ņ” ҁĐēĐģадĐŊĐžŅŽ Ņ‚ĐĩĐŧĐžŅŽ Đ´ĐģŅ ĐąĐ°ĐŗĐ°Ņ‚ŅŒĐžŅ… ĐģŅŽĐ´ĐĩĐš. Ви Đ˛ŅĐĩ ОдĐŊĐž ĐŧĐžĐļĐĩŅ‚Đĩ ĐˇŅ€ĐžĐąĐ¸Ņ‚Đ¸ ĐąĐ°ĐŗĐ°Ņ‚Đž Ņ€Đĩ҇ĐĩĐš ĐąĐĩС Ņ—Ņ… виĐēĐžŅ€Đ¸ŅŅ‚Đ°ĐŊĐŊŅ. + +АĐģĐĩ Ņ‚ĐĩĐŋĐĩŅ€ Ви СĐŊĐ°Ņ”Ņ‚Đĩ, Ņ‰Đž ĐēĐžĐģи вОĐŊи СĐŊадОйĐģŅŅ‚ŅŒŅŅ, Ņ—Ņ… ĐŧĐžĐļĐŊа ĐˇĐ°ŅŅ‚ĐžŅĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ ҃ **FastAPI**. + +### Pydantic v1 `regex` СаĐŧŅ–ŅŅ‚ŅŒ `pattern` + +До вĐĩҀҁҖҗ Pydantic 2 Ņ– FastAPI 0.100.0 ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ ĐŊĐ°ĐˇĐ¸Đ˛Đ°Đ˛ŅŅ `regex` СаĐŧŅ–ŅŅ‚ŅŒ `pattern`, аĐģĐĩ Ņ‚ĐĩĐŋĐĩŅ€ Đ˛Ņ–ĐŊ ĐˇĐ°ŅŅ‚Đ°Ņ€Ņ–Đ˛. + +Ви Đ˛ŅĐĩ ҉Đĩ ĐŧĐžĐļĐĩŅ‚Đĩ ĐˇŅƒŅŅ‚Ņ€Ņ–Ņ‚Đ¸ ĐēОд, ŅĐēиК виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅ” ĐšĐžĐŗĐž: + +//// tab | Pydantic v1 + +{* ../../docs_src/query_params_str_validations/tutorial004_regex_an_py310.py hl[11] *} + +//// + +АĐģĐĩ ĐŧĐ°ĐšŅ‚Đĩ ĐŊа ŅƒĐ˛Đ°ĐˇŅ–, Ņ‰Đž Đ˛Ņ–ĐŊ Ņ” ĐˇĐ°ŅŅ‚Đ°Ņ€Ņ–ĐģиĐŧ Ņ– ĐšĐžĐŗĐž ҁĐģŅ–Đ´ ĐžĐŊĐžĐ˛Đ¸Ņ‚Đ¸ Đ´Đž ĐŊĐžĐ˛ĐžĐŗĐž ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ° `pattern`. 🤓 + +## ЗĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ Са СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ + +Ви ĐŧĐžĐļĐĩŅ‚Đĩ виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ Са СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ, Đ˛Ņ–Đ´ĐŧŅ–ĐŊĐŊŅ– Đ˛Ņ–Đ´ `None`. + +НаĐŋŅ€Đ¸ĐēĐģад, ŅĐēŅ‰Đž Ви Ņ…ĐžŅ‡ĐĩŅ‚Đĩ ĐžĐŗĐžĐģĐžŅĐ¸Ņ‚Đ¸ ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ СаĐŋĐ¸Ņ‚Ņƒ `q` С `min_length` `3` Ņ– СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅĐŧ Са СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ `"fixedquery"`: + +{* ../../docs_src/query_params_str_validations/tutorial005_an_py39.py hl[9] *} + +/// note | ĐĸĐĩŅ…ĐŊҖ҇ĐŊŅ– Đ´ĐĩŅ‚Đ°ĐģŅ– + +ĐĐ°ŅĐ˛ĐŊŅ–ŅŅ‚ŅŒ СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ Са СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ ĐąŅƒĐ´ŅŒ-ŅĐēĐžĐŗĐž Ņ‚Đ¸Đŋ҃, вĐēĐģŅŽŅ‡Đ°ŅŽŅ‡Đ¸ `None`, Ņ€ĐžĐąĐ¸Ņ‚ŅŒ ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ ĐŊĐĩĐžĐąĐžĐ˛â€™ŅĐˇĐēОвиĐŧ (not required). + +/// + +## ĐžĐąĐžĐ˛â€™ŅĐˇĐēĐžĐ˛Ņ– ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ¸ + +Đ¯ĐēŅ‰Đž ĐŊаĐŧ ĐŊĐĩ ĐŋĐžŅ‚Ņ€Ņ–ĐąĐŊĐž вĐēĐ°ĐˇŅƒĐ˛Đ°Ņ‚Đ¸ Đ´ĐžĐ´Đ°Ņ‚ĐēĐžĐ˛Ņ– ĐŋĐĩŅ€ĐĩĐ˛Ņ–Ņ€Đēи айО ĐŧĐĩŅ‚Đ°Đ´Đ°ĐŊŅ–, Đŧи ĐŧĐžĐļĐĩĐŧĐž ĐˇŅ€ĐžĐąĐ¸Ņ‚Đ¸ ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ `q` ĐžĐąĐžĐ˛â€™ŅĐˇĐēОвиĐŧ, ĐŋŅ€ĐžŅŅ‚Đž ĐŊĐĩ ĐžĐŗĐžĐģĐžŅˆŅƒŅŽŅ‡Đ¸ СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ Са СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ, ĐŊаĐŋŅ€Đ¸ĐēĐģад: + +```Python +q: str +``` + +СаĐŧŅ–ŅŅ‚ŅŒ: + +```Python +q: str | None = None +``` + +АĐģĐĩ Ņ‚ĐĩĐŋĐĩŅ€ Đŧи ĐžĐŗĐžĐģĐžŅˆŅƒŅ”ĐŧĐž ĐšĐžĐŗĐž С `Query`, ĐŊаĐŋŅ€Đ¸ĐēĐģад: + +//// tab | Annotated + +```Python +q: Annotated[str | None, Query(min_length=3)] = None +``` + +//// + +ĐĸĐžĐŧ҃, ŅĐēŅ‰Đž ВаĐŧ ĐŋĐžŅ‚Ņ€Ņ–ĐąĐŊĐž ĐˇŅ€ĐžĐąĐ¸Ņ‚Đ¸ СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ ĐžĐąĐžĐ˛â€™ŅĐˇĐēОвиĐŧ, виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅŽŅ‡Đ¸ `Query`, ĐŋŅ€ĐžŅŅ‚Đž ĐŊĐĩ вĐēĐ°ĐˇŅƒĐšŅ‚Đĩ СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ Са СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ: + +{* ../../docs_src/query_params_str_validations/tutorial006_an_py39.py hl[9] *} + +### ĐžĐąĐžĐ˛â€™ŅĐˇĐēОвĐĩ СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ, ŅĐēĐĩ ĐŧĐžĐļĐĩ ĐąŅƒŅ‚Đ¸ `None` + +Ви ĐŧĐžĐļĐĩŅ‚Đĩ вĐēĐ°ĐˇĐ°Ņ‚Đ¸, Ņ‰Đž ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ ĐŧĐžĐļĐĩ ĐŋŅ€Đ¸ĐšĐŧĐ°Ņ‚Đ¸ `None`, аĐģĐĩ ĐŋŅ€Đ¸ Ņ†ŅŒĐžĐŧ҃ СаĐģĐ¸ŅˆĐ°Ņ”Ņ‚ŅŒŅŅ ĐžĐąĐžĐ˛â€™ŅĐˇĐēОвиĐŧ. ĐĻĐĩ СĐŧŅƒŅĐ¸Ņ‚ŅŒ ĐēĐģŅ–Ņ”ĐŊŅ‚Ņ–Đ˛ ĐŊĐ°Đ´Ņ–ŅĐģĐ°Ņ‚Đ¸ СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ, ĐŊĐ°Đ˛Ņ–Ņ‚ŅŒ ŅĐēŅ‰Đž вОĐŊĐž Đ´ĐžŅ€Ņ–Đ˛ĐŊŅŽŅ” `None`. + +ЊОй ĐˇŅ€ĐžĐąĐ¸Ņ‚Đ¸ ҆Đĩ, ĐžĐŗĐžĐģĐžŅŅ–Ņ‚ŅŒ, Ņ‰Đž `None` Ņ” Đ´ĐžĐŋŅƒŅŅ‚Đ¸ĐŧиĐŧ Ņ‚Đ¸ĐŋĐžĐŧ, аĐģĐĩ ĐŊĐĩ вĐēĐ°ĐˇŅƒĐšŅ‚Đĩ СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ Са СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ: + +{* ../../docs_src/query_params_str_validations/tutorial006c_an_py310.py hl[9] *} + +## ĐĄĐŋĐ¸ŅĐžĐē ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Ņ–Đ˛ СаĐŋĐ¸Ņ‚Ņƒ / ĐēŅ–ĐģҌĐēа СĐŊĐ°Ņ‡ĐĩĐŊҌ + +Đ¯ĐēŅ‰Đž Ви виСĐŊĐ°Ņ‡Đ°Ņ”Ņ‚Đĩ ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ СаĐŋĐ¸Ņ‚Ņƒ Са Đ´ĐžĐŋĐžĐŧĐžĐŗĐžŅŽ `Query`, Ви Ņ‚Đ°ĐēĐžĐļ ĐŧĐžĐļĐĩŅ‚Đĩ дОСвОĐģĐ¸Ņ‚Đ¸ ĐžŅ‚Ņ€Đ¸ĐŧаĐŊĐŊŅ ҁĐŋĐ¸ŅĐē҃ СĐŊĐ°Ņ‡ĐĩĐŊҌ, Ņ‚ĐžĐąŅ‚Đž дОСвОĐģĐ¸Ņ‚Đ¸ ĐžŅ‚Ņ€Đ¸ĐŧаĐŊĐŊŅ ĐēŅ–ĐģҌĐēĐžŅ… СĐŊĐ°Ņ‡ĐĩĐŊҌ. + +НаĐŋŅ€Đ¸ĐēĐģад, Ņ‰ĐžĐą дОСвОĐģĐ¸Ņ‚Đ¸ ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Ņƒ СаĐŋĐ¸Ņ‚Ņƒ `q` С'ŅĐ˛ĐģŅŅ‚Đ¸ŅŅ ĐēŅ–ĐģҌĐēа Ņ€Đ°ĐˇŅ–Đ˛ в URL, ĐŧĐžĐļĐŊа ĐŊаĐŋĐ¸ŅĐ°Ņ‚Đ¸: + +{* ../../docs_src/query_params_str_validations/tutorial011_an_py310.py hl[9] *} + +ĐĸĐžĐ´Ņ–, ҃ виĐŋадĐē҃ СаĐŋĐ¸Ņ‚Ņƒ Са URL: + +``` +http://localhost:8000/items/?q=foo&q=bar +``` + +Ви ĐžŅ‚Ņ€Đ¸ĐŧĐ°Ņ”Ņ‚Đĩ ĐēŅ–ĐģҌĐēа СĐŊĐ°Ņ‡ĐĩĐŊҌ *query ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ°* `q` (`foo` Ņ– `bar`) ҃ Đ˛Đ¸ĐŗĐģŅĐ´Ņ– ҁĐŋĐ¸ŅĐē҃ `list` в Python ҃ Đ’Đ°ŅˆŅ–Đš *Ņ„ŅƒĐŊĐē҆Җҗ ĐžĐąŅ€ĐžĐąĐēи ҈ĐģŅŅ…Ņƒ*, ҃ *ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂ҀҖ Ņ„ŅƒĐŊĐē҆Җҗ* `q`. + +ĐžŅ‚ĐļĐĩ, Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´ŅŒ ĐŊа ҆ĐĩĐš URL ĐąŅƒĐ´Đĩ: + +```JSON +{ + "q": [ + "foo", + "bar" + ] +} +``` + +/// tip | ĐŸŅ–Đ´ĐēаСĐēа + +ЊОй ĐžĐŗĐžĐģĐžŅĐ¸Ņ‚Đ¸ ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ СаĐŋĐ¸Ņ‚Ņƒ С Ņ‚Đ¸ĐŋĐžĐŧ `list`, ŅĐē ҃ ĐŊавĐĩĐ´ĐĩĐŊĐžĐŧ҃ Đ˛Đ¸Ņ‰Đĩ ĐŋŅ€Đ¸ĐēĐģĐ°Đ´Ņ–, ĐŋĐžŅ‚Ņ€Ņ–ĐąĐŊĐž ŅĐ˛ĐŊĐž виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ `Query`, Ņ–ĐŊаĐē҈Đĩ Đ˛Ņ–ĐŊ ĐąŅƒĐ´Đĩ Ņ–ĐŊŅ‚ĐĩŅ€ĐŋŅ€ĐĩŅ‚ĐžĐ˛Đ°ĐŊиК ŅĐē ҂ҖĐģĐž СаĐŋĐ¸Ņ‚Ņƒ. + +/// + +ІĐŊŅ‚ĐĩŅ€Đ°ĐēŅ‚Đ¸Đ˛ĐŊа API-Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Ņ–Ņ ĐžĐŊĐžĐ˛Đ¸Ņ‚ŅŒŅŅ Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´ĐŊĐž, дОСвОĐģŅŅŽŅ‡Đ¸ ĐŋĐĩŅ€ĐĩĐ´Đ°Đ˛Đ°Ņ‚Đ¸ ĐēŅ–ĐģҌĐēа СĐŊĐ°Ņ‡ĐĩĐŊҌ: + + + +### ĐĄĐŋĐ¸ŅĐžĐē ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Ņ–Đ˛ СаĐŋĐ¸Ņ‚Ņƒ / ĐēŅ–ĐģҌĐēа СĐŊĐ°Ņ‡ĐĩĐŊҌ Са СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ + +Ви Ņ‚Đ°ĐēĐžĐļ ĐŧĐžĐļĐĩŅ‚Đĩ виСĐŊĐ°Ņ‡Đ¸Ņ‚Đ¸ СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ Са СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ Đ´ĐģŅ `list`, ŅĐēŅ‰Đž ĐļОдĐŊĐĩ СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ ĐŊĐĩ ĐąŅƒĐģĐž ĐŋĐĩŅ€ĐĩдаĐŊĐĩ: + +{* ../../docs_src/query_params_str_validations/tutorial012_an_py39.py hl[9] *} + +Đ¯ĐēŅ‰Đž Ви ĐŋĐĩŅ€ĐĩКдĐĩŅ‚Đĩ Са ĐŋĐžŅĐ¸ĐģаĐŊĐŊŅĐŧ: + +``` +http://localhost:8000/items/ +``` + +Ņ‚Đž СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ `q` Са СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ ĐąŅƒĐ´Đĩ: `["foo", "bar"]`, Ņ– Đ’Đ°ŅˆĐ° Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´ŅŒ Đ˛Đ¸ĐŗĐģŅĐ´Đ°Ņ‚Đ¸ĐŧĐĩ Ņ‚Đ°Đē: + +```JSON +{ + "q": [ + "foo", + "bar" + ] +} +``` + +#### ВиĐēĐžŅ€Đ¸ŅŅ‚Đ°ĐŊĐŊŅ ҂ҖĐģҌĐēи `list` + +Ви Ņ‚Đ°ĐēĐžĐļ ĐŧĐžĐļĐĩŅ‚Đĩ виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ `list` ĐąĐĩС ŅƒŅ‚ĐžŅ‡ĐŊĐĩĐŊĐŊŅ Ņ‚Đ¸Đŋ҃, СаĐŧŅ–ŅŅ‚ŅŒ `list[str]`: + +{* ../../docs_src/query_params_str_validations/tutorial013_an_py39.py hl[9] *} + +/// note | ĐĸĐĩŅ…ĐŊҖ҇ĐŊŅ– Đ´ĐĩŅ‚Đ°ĐģŅ– + +ĐœĐ°ĐšŅ‚Đĩ ĐŊа ŅƒĐ˛Đ°ĐˇŅ–, Ņ‰Đž в Ņ†ŅŒĐžĐŧ҃ виĐŋадĐē҃ FastAPI ĐŊĐĩ ĐŋĐĩŅ€ĐĩĐ˛Ņ–Ņ€ŅŅ‚Đ¸ĐŧĐĩ вĐŧҖҁ҂ ҁĐŋĐ¸ŅĐē҃. + +НаĐŋŅ€Đ¸ĐēĐģад, `list[int]` ĐŋĐĩŅ€ĐĩĐ˛Ņ–Ņ€ŅŅ‚Đ¸ĐŧĐĩ (Ņ– Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚ŅƒĐ˛Đ°Ņ‚Đ¸ĐŧĐĩ), Ņ‰Đž Đ˛ŅŅ– ĐĩĐģĐĩĐŧĐĩĐŊŅ‚Đ¸ ҁĐŋĐ¸ŅĐē҃ Ņ” ҆ҖĐģиĐŧи Ņ‡Đ¸ŅĐģаĐŧи. АĐģĐĩ `list` ĐąĐĩС ŅƒŅ‚ĐžŅ‡ĐŊĐĩĐŊĐŊŅ Ņ†ŅŒĐžĐŗĐž ĐŊĐĩ Ņ€ĐžĐąĐ¸Ņ‚Đ¸ĐŧĐĩ. + +/// + +## ДодаваĐŊĐŊŅ Đ´ĐžĐ´Đ°Ņ‚ĐēĐžĐ˛Đ¸Ņ… ĐŧĐĩŅ‚Đ°Đ´Đ°ĐŊĐ¸Ņ… + +Ви ĐŧĐžĐļĐĩŅ‚Đĩ Đ´ĐžĐ´Đ°Ņ‚Đ¸ ĐąŅ–ĐģҌ҈Đĩ Ņ–ĐŊŅ„ĐžŅ€ĐŧĐ°Ņ†Ņ–Ņ— ĐŋŅ€Đž ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ. + +ĐĻŅ Ņ–ĐŊŅ„ĐžŅ€ĐŧĐ°Ņ†Ņ–Ņ ĐąŅƒĐ´Đĩ вĐēĐģŅŽŅ‡ĐĩĐŊа ҃ ĐˇĐŗĐĩĐŊĐĩŅ€ĐžĐ˛Đ°ĐŊиК OpenAPI Ņ‚Đ° виĐēĐžŅ€Đ¸ŅŅ‚Đ°ĐŊа в Ņ–ĐŊŅ‚ĐĩҀ҄ĐĩĐšŅĐ°Ņ… Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Ņ–Ņ— Ņ‚Đ° СОвĐŊŅ–ŅˆĐŊŅ–Ņ… Ņ–ĐŊŅŅ‚Ņ€ŅƒĐŧĐĩĐŊŅ‚Đ°Ņ…. + +/// note | ĐĸĐĩŅ…ĐŊҖ҇ĐŊŅ– Đ´ĐĩŅ‚Đ°ĐģŅ– + +ĐœĐ°ĐšŅ‚Đĩ ĐŊа ŅƒĐ˛Đ°ĐˇŅ–, Ņ‰Đž Ņ€Ņ–ĐˇĐŊŅ– Ņ–ĐŊŅŅ‚Ņ€ŅƒĐŧĐĩĐŊŅ‚Đ¸ ĐŧĐžĐļŅƒŅ‚ŅŒ ĐŧĐ°Ņ‚Đ¸ Ņ€Ņ–ĐˇĐŊиК Ņ€Ņ–Đ˛ĐĩĐŊҌ ĐŋŅ–Đ´Ņ‚Ņ€Đ¸ĐŧĐēи OpenAPI. + +ДĐĩŅĐēŅ– С ĐŊĐ¸Ņ… ĐŧĐžĐļŅƒŅ‚ŅŒ ҉Đĩ ĐŊĐĩ Đ˛Ņ–Đ´ĐžĐąŅ€Đ°ĐļĐ°Ņ‚Đ¸ Đ˛ŅŅŽ Đ´ĐžĐ´Đ°Ņ‚ĐēĐžĐ˛Ņƒ Ņ–ĐŊŅ„ĐžŅ€ĐŧĐ°Ņ†Ņ–ŅŽ, Ņ…ĐžŅ‡Đ° в ĐąŅ–ĐģŅŒŅˆĐžŅŅ‚Ņ– виĐŋадĐēŅ–Đ˛ Ņ†Ņ Ņ„ŅƒĐŊĐēŅ†Ņ–Ņ вĐļĐĩ СаĐŋĐģаĐŊОваĐŊа Đ´ĐģŅ Ņ€ĐžĐˇŅ€ĐžĐąĐēи. + +/// + +Ви ĐŧĐžĐļĐĩŅ‚Đĩ Đ´ĐžĐ´Đ°Ņ‚Đ¸ `title` : + +{* ../../docs_src/query_params_str_validations/tutorial007_an_py310.py hl[10] *} + +А Ņ‚Đ°ĐēĐžĐļ `description`: + +{* ../../docs_src/query_params_str_validations/tutorial008_an_py310.py hl[14] *} + +## АĐģŅ–Đ°ŅĐ¸ ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Ņ–Đ˛ + +ĐŖŅĐ˛Ņ–Ņ‚ŅŒ, Ņ‰Đž Ви Ņ…ĐžŅ‡ĐĩŅ‚Đĩ, Ņ‰ĐžĐą ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ ĐŊĐ°ĐˇĐ¸Đ˛Đ°Đ˛ŅŅ `item-query`. + +НаĐŋŅ€Đ¸ĐēĐģад: + +``` +http://127.0.0.1:8000/items/?item-query=foobaritems +``` + +АĐģĐĩ `item-query` — ҆Đĩ ĐŊĐĩĐēĐžŅ€ĐĩĐēŅ‚ĐŊа ĐŊаСва СĐŧŅ–ĐŊĐŊĐžŅ— в Python. + +НайбĐģиĐļŅ‡Đ¸Đš Đ´ĐžĐŋŅƒŅŅ‚Đ¸ĐŧиК Đ˛Đ°Ņ€Ņ–Đ°ĐŊŅ‚ — `item_query`. + +ĐŸŅ€ĐžŅ‚Đĩ ВаĐŧ ĐŋĐžŅ‚Ņ€Ņ–ĐąĐŊĐž, Ņ‰ĐžĐą ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ СаĐģĐ¸ŅˆĐ°Đ˛ŅŅ ŅĐ°ĐŧĐĩ `item-query`... + +ĐŖ Ņ‚Đ°ĐēĐžĐŧ҃ виĐŋадĐē҃ ĐŧĐžĐļĐŊа ĐžĐŗĐžĐģĐžŅĐ¸Ņ‚Đ¸ `alias`, Ņ– ŅĐ°ĐŧĐĩ Đ˛Ņ–ĐŊ ĐąŅƒĐ´Đĩ виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ŅŅ Đ´ĐģŅ ĐžŅ‚Ņ€Đ¸ĐŧаĐŊĐŊŅ СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ°: + +{* ../../docs_src/query_params_str_validations/tutorial009_an_py310.py hl[9] *} + +## ВивĐĩĐ´ĐĩĐŊĐŊŅ ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Ņ–Đ˛ ŅĐē ĐˇĐ°ŅŅ‚Đ°Ņ€Ņ–ĐģĐ¸Ņ… + +ĐŸŅ€Đ¸ĐŋŅƒŅŅ‚Đ¸ĐŧĐž, Ņ‰Đž Ви ĐąŅ–ĐģҌ҈Đĩ ĐŊĐĩ Ņ…ĐžŅ‡ĐĩŅ‚Đĩ виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ ҆ĐĩĐš ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ. + +ВаĐŧ ĐŋĐžŅ‚Ņ€Ņ–ĐąĐŊĐž СаĐģĐ¸ŅˆĐ¸Ņ‚Đ¸ ĐšĐžĐŗĐž ĐŊа Đ´ĐĩŅĐēиК Ņ‡Đ°Ņ, ĐžŅĐēŅ–ĐģҌĐēи ĐŊиĐŧ ĐēĐžŅ€Đ¸ŅŅ‚ŅƒŅŽŅ‚ŅŒŅŅ ĐēĐģŅ–Ņ”ĐŊŅ‚Đ¸, аĐģĐĩ Ви Ņ…ĐžŅ‡ĐĩŅ‚Đĩ, Ņ‰ĐžĐą Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Ņ–Ņ ҇Җ҂ĐēĐž ĐŋĐžĐēĐ°ĐˇŅƒĐ˛Đ°Đģа, Ņ‰Đž Đ˛Ņ–ĐŊ Ņ” ĐˇĐ°ŅŅ‚Đ°Ņ€Ņ–ĐģиĐŧ. + +ĐĸĐžĐ´Ņ– Ви ĐŧĐžĐļĐĩŅ‚Đĩ ĐŋĐĩŅ€ĐĩĐ´Đ°Ņ‚Đ¸ ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ `deprecated=True` Đ´Đž `Query`: + +{* ../../docs_src/query_params_str_validations/tutorial010_an_py310.py hl[19] *} + +ДоĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Ņ–Ņ ĐąŅƒĐ´Đĩ ĐŋĐžĐēĐ°ĐˇŅƒĐ˛Đ°Ņ‚Đ¸ ҆Đĩ Ņ‚Đ°ĐēиĐŧ Ņ‡Đ¸ĐŊĐžĐŧ: + + + +## ВиĐŊŅŅ‚ĐžĐē ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Ņ–Đ˛ С OpenAPI + +ЊОй виĐēĐģŅŽŅ‡Đ¸Ņ‚Đ¸ ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ СаĐŋĐ¸Ņ‚Ņƒ ĐˇŅ– ĐˇĐŗĐĩĐŊĐĩŅ€ĐžĐ˛Đ°ĐŊĐžŅ— ҁ҅ĐĩĐŧи OpenAPI (Ņ–, Ņ‚Đ°ĐēиĐŧ Ņ‡Đ¸ĐŊĐžĐŧ, С Đ°Đ˛Ņ‚ĐžĐŧĐ°Ņ‚Đ¸Ņ‡ĐŊĐ¸Ņ… ŅĐ¸ŅŅ‚ĐĩĐŧ Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Ņ–Ņ—), Đ˛ŅŅ‚Đ°ĐŊĐžĐ˛Ņ–Ņ‚ŅŒ ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ `include_in_schema` Đ´ĐģŅ `Query` в `False`: + +{* ../../docs_src/query_params_str_validations/tutorial014_an_py310.py hl[10] *} + +## ĐšĐ°ŅŅ‚ĐžĐŧĐŊа ваĐģŅ–Đ´Đ°Ņ†Ņ–Ņ + +МоĐļŅƒŅ‚ŅŒ ĐąŅƒŅ‚Đ¸ виĐŋадĐēи, ĐēĐžĐģи ВаĐŧ ĐŋĐžŅ‚Ņ€Ņ–ĐąĐŊĐž ĐŋŅ€ĐžĐ˛ĐĩŅŅ‚Đ¸ **ĐēĐ°ŅŅ‚ĐžĐŧĐŊ҃ ваĐģŅ–Đ´Đ°Ņ†Ņ–ŅŽ**, ŅĐē҃ ĐŊĐĩ ĐŧĐžĐļĐŊа Ņ€ĐĩаĐģŅ–ĐˇŅƒĐ˛Đ°Ņ‚Đ¸ Са Đ´ĐžĐŋĐžĐŧĐžĐŗĐžŅŽ ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Ņ–Đ˛, ĐŋĐžĐēаСаĐŊĐ¸Ņ… Đ˛Đ¸Ņ‰Đĩ. + +ĐŖ Ņ‚Đ°ĐēĐ¸Ņ… виĐŋадĐēĐ°Ņ… ви ĐŧĐžĐļĐĩŅ‚Đĩ виĐēĐžŅ€Đ¸ŅŅ‚Đ°Ņ‚Đ¸ **ĐēĐ°ŅŅ‚ĐžĐŧĐŊ҃ Ņ„ŅƒĐŊĐēŅ†Ņ–ŅŽ ваĐģŅ–Đ´Đ°Ņ†Ņ–Ņ—**, ŅĐēа ĐąŅƒĐ´Đĩ ĐˇĐ°ŅŅ‚ĐžŅĐžĐ˛Đ°ĐŊа ĐŋҖҁĐģŅ ĐˇĐ˛Đ¸Ņ‡Đ°ĐšĐŊĐžŅ— ваĐģŅ–Đ´Đ°Ņ†Ņ–Ņ— (ĐŊаĐŋŅ€Đ¸ĐēĐģад, ĐŋҖҁĐģŅ ĐŋĐĩŅ€ĐĩĐ˛Ņ–Ņ€Đēи, Ņ‰Đž СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ Ņ” Ņ‚Đ¸ĐŋĐžĐŧ `str`). + +ĐĻĐĩ ĐŧĐžĐļĐŊа Đ´ĐžŅŅĐŗŅ‚Đ¸ Са Đ´ĐžĐŋĐžĐŧĐžĐŗĐžŅŽ Pydantic's `AfterValidator` в ҁĐĩŅ€ĐĩдиĐŊŅ– `Annotated`. + +/// tip | ĐŸŅ–Đ´ĐēаСĐēа + +Pydantic Ņ‚Đ°ĐēĐžĐļ ĐŧĐ°Ņ” `BeforeValidator` Ņ‚Đ° Ņ–ĐŊŅˆŅ–. 🤓 + +/// + +НаĐŋŅ€Đ¸ĐēĐģад, ҆ĐĩĐš ĐēĐ°ŅŅ‚ĐžĐŧĐŊиК ваĐģŅ–Đ´Đ°Ņ‚ĐžŅ€ ĐŋĐĩŅ€ĐĩĐ˛Ņ–Ņ€ŅŅ”, Ņ‡Đ¸ ĐŋĐžŅ‡Đ¸ĐŊĐ°Ņ”Ņ‚ŅŒŅŅ ID ĐĩĐģĐĩĐŧĐĩĐŊŅ‚Đ° С `isbn-` Đ´ĐģŅ ĐŊĐžĐŧĐĩŅ€Đ° ĐēĐŊĐ¸ĐŗĐ¸ ISBN айО С `imdb-` Đ´ĐģŅ ID URL ҄ҖĐģҌĐŧ҃ ĐŊа IMDB: + +{* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py hl[5,16:19,24] *} + +/// info | ІĐŊŅ„ĐžŅ€ĐŧĐ°Ņ†Ņ–Ņ + +ĐĻĐĩ Đ´ĐžŅŅ‚ŅƒĐŋĐŊĐž С вĐĩҀҁҖҗ Pydantic 2 айО Đ˛Đ¸Ņ‰Đĩ. 😎 + +/// + +/// tip | ĐŸŅ–Đ´ĐēаСĐēа + +Đ¯ĐēŅ‰Đž ВаĐŧ ĐŋĐžŅ‚Ņ€Ņ–ĐąĐŊĐž виĐēĐžĐŊĐ°Ņ‚Đ¸ ĐąŅƒĐ´ŅŒ-ŅĐē҃ ваĐģŅ–Đ´Đ°Ņ†Ņ–ŅŽ, ŅĐēа виĐŧĐ°ĐŗĐ°Ņ” Đ˛ĐˇĐ°Ņ”ĐŧĐžĐ´Ņ–Ņ— С ĐąŅƒĐ´ŅŒ-ŅĐēиĐŧ **СОвĐŊŅ–ŅˆĐŊŅ–Đŧ ĐēĐžĐŧĐŋĐžĐŊĐĩĐŊŅ‚ĐžĐŧ**, Ņ‚Đ°ĐēиĐŧ ŅĐē йаСа даĐŊĐ¸Ņ… Ņ‡Đ¸ Ņ–ĐŊŅˆĐ¸Đš API, ви ĐŋОвиĐŊĐŊŅ– СаĐŧŅ–ŅŅ‚ŅŒ Ņ†ŅŒĐžĐŗĐž виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ **FastAPI Dependencies**. Ви Đ´Ņ–ĐˇĐŊĐ°Ņ”Ņ‚ĐĩҁҌ ĐŋŅ€Đž ĐŊĐ¸Ņ… ĐŋŅ–ĐˇĐŊŅ–ŅˆĐĩ. + +ĐĻŅ– ĐēĐ°ŅŅ‚ĐžĐŧĐŊŅ– ваĐģŅ–Đ´Đ°Ņ‚ĐžŅ€Đ¸ виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅŽŅ‚ŅŒŅŅ Đ´ĐģŅ Ņ€Đĩ҇ĐĩĐš, ŅĐēŅ– ĐŧĐžĐļĐŊа ĐŋĐĩŅ€ĐĩĐ˛Ņ–Ņ€Đ¸Ņ‚Đ¸ ĐģĐ¸ŅˆĐĩ С **Ņ‚Đ¸Đŧи даĐŊиĐŧи**, Ņ‰Đž ĐŊадаĐŊŅ– в СаĐŋĐ¸Ņ‚Ņ–. + +/// + +### Đ—Ņ€ĐžĐˇŅƒĐŧŅ–ĐšŅ‚Đĩ ҆ĐĩĐš ĐēОд + +ГоĐģОвĐŊиК ĐŧĐžĐŧĐĩĐŊŅ‚ – ҆Đĩ виĐēĐžŅ€Đ¸ŅŅ‚Đ°ĐŊĐŊŅ **`AfterValidator` С Ņ„ŅƒĐŊĐēŅ†Ņ–Ņ”ŅŽ Đ˛ŅĐĩŅ€ĐĩдиĐŊŅ– `Annotated`**. МоĐļĐĩŅ‚Đĩ ĐŋŅ€ĐžĐŋŅƒŅŅ‚Đ¸Ņ‚Đ¸ Ņ†ŅŽ Ņ‡Đ°ŅŅ‚Đ¸ĐŊ҃, ŅĐēŅ‰Đž Ņ…ĐžŅ‡ĐĩŅ‚Đĩ. 🤸 + +--- + +АĐģĐĩ ŅĐēŅ‰Đž ВаĐŧ ҆ҖĐēавО Ņ€ĐžĐˇŅ–ĐąŅ€Đ°Ņ‚Đ¸ŅŅ в Ņ†ŅŒĐžĐŧ҃ ĐēĐžĐŊĐēŅ€ĐĩŅ‚ĐŊĐžĐŧ҃ ĐŋŅ€Đ¸ĐēĐģĐ°Đ´Ņ– ĐēĐžĐ´Ņƒ Ņ– ВаĐŧ ҉Đĩ ĐŊĐĩ ĐŊĐ°ĐąŅ€Đ¸Đ´ĐģĐž, ĐžŅŅŒ ĐēŅ–ĐģҌĐēа Đ´ĐžĐ´Đ°Ņ‚ĐēĐžĐ˛Đ¸Ņ… Đ´ĐĩŅ‚Đ°ĐģĐĩĐš. + +#### Đ ŅĐ´ĐžĐē Ņ–Đˇ `value.startswith()` + +ЗвĐĩŅ€ĐŊ҃Đģи ŅƒĐ˛Đ°ĐŗŅƒ? Đ ŅĐ´ĐžĐē Ņ–Đˇ `value.startswith()` ĐŧĐžĐļĐĩ ĐŋŅ€Đ¸ĐšĐŧĐ°Ņ‚Đ¸ ĐēĐžŅ€Ņ‚ĐĩĐļ, Ņ– Ņ‚ĐžĐ´Ņ– Đ˛Ņ–ĐŊ ĐŋĐĩŅ€ĐĩĐ˛Ņ–Ņ€ŅŅ‚Đ¸ĐŧĐĩ ĐēĐžĐļĐŊĐĩ СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ в ĐēĐžŅ€Ņ‚ĐĩĐļŅ–: + +{* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py ln[16:19] hl[17] *} + +#### ВиĐŋадĐēОвиК ĐĩĐģĐĩĐŧĐĩĐŊŅ‚ + +За Đ´ĐžĐŋĐžĐŧĐžĐŗĐžŅŽ `data.items()` Đŧи ĐžŅ‚Ņ€Đ¸ĐŧŅƒŅ”ĐŧĐž Ņ–Ņ‚ĐĩŅ€Đ°ĐąĐĩĐģҌĐŊиК Ой'Ņ”ĐēŅ‚ Ņ–Đˇ ĐēĐžŅ€Ņ‚ĐĩĐļаĐŧи, Ņ‰Đž ĐŧŅ–ŅŅ‚ŅŅ‚ŅŒ ĐēĐģŅŽŅ‡ Ņ– СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ Đ´ĐģŅ ĐēĐžĐļĐŊĐžĐŗĐž ĐĩĐģĐĩĐŧĐĩĐŊŅ‚Đ° ҁĐģОвĐŊиĐēа. + +Ми ĐŋĐĩŅ€ĐĩŅ‚Đ˛ĐžŅ€ŅŽŅ”ĐŧĐž ҆ĐĩĐš Ņ–Ņ‚ĐĩŅ€Đ°ĐąĐĩĐģҌĐŊиК Ой'Ņ”ĐēŅ‚ ҃ ĐˇĐ˛Đ¸Ņ‡Đ°ĐšĐŊиК `list` Са Đ´ĐžĐŋĐžĐŧĐžĐŗĐžŅŽ `list(data.items())`. + +ĐŸĐžŅ‚Ņ–Đŧ, виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅŽŅ‡Đ¸ `random.choice()`, Đŧи ĐŧĐžĐļĐĩĐŧĐž ĐžŅ‚Ņ€Đ¸ĐŧĐ°Ņ‚Đ¸ виĐŋадĐēОвĐĩ СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ ĐˇŅ– ҁĐŋĐ¸ŅĐē҃, Ņ‚ĐžĐąŅ‚Đž ĐžŅ‚Ņ€Đ¸ĐŧŅƒŅ”ĐŧĐž ĐēĐžŅ€Ņ‚ĐĩĐļ Ņ–Đˇ `(id, name)`. ĐĻĐĩ ĐŧĐžĐļĐĩ ĐąŅƒŅ‚Đ¸ Ņ‰ĐžŅŅŒ ĐŊа ĐˇŅ€Đ°ĐˇĐžĐē `("imdb-tt0371724", "The Hitchhiker's Guide to the Galaxy")`. + +ДаĐģŅ– Đŧи **ĐŋŅ€Đ¸ŅĐ˛ĐžŅŽŅ”ĐŧĐž ҆Җ два СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ** ĐēĐžŅ€Ņ‚ĐĩĐļ҃ СĐŧŅ–ĐŊĐŊиĐŧ `id` Ņ– `name`. + +ĐĸĐžĐļ, ŅĐēŅ‰Đž ĐēĐžŅ€Đ¸ŅŅ‚ŅƒĐ˛Đ°Ņ‡ ĐŊĐĩ вĐēаСав ID ĐĩĐģĐĩĐŧĐĩĐŊŅ‚Đ°, Đ˛Ņ–ĐŊ Đ˛ŅĐĩ ОдĐŊĐž ĐžŅ‚Ņ€Đ¸ĐŧĐ°Ņ” виĐŋадĐēĐžĐ˛Ņƒ Ņ€ĐĩĐēĐžĐŧĐĩĐŊĐ´Đ°Ņ†Ņ–ŅŽ. + +...Ņ– Đ˛ŅĐĩ ҆Đĩ Ņ€ĐĩаĐģŅ–ĐˇĐžĐ˛Đ°ĐŊĐž в **ОдĐŊĐžĐŧ҃ Ņ€ŅĐ´Đē҃ ĐēĐžĐ´Ņƒ**. đŸ¤¯ ĐĨŅ–ĐąĐ° ĐŊĐĩ ĐŋŅ€ĐĩĐēŅ€Đ°ŅĐŊиК Python? 🐍 + +{* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py ln[22:30] hl[29] *} + +## ĐŸŅ–Đ´ŅŅƒĐŧĐžĐē + +Ви ĐŧĐžĐļĐĩŅ‚Đĩ ĐžĐŗĐžĐģĐžŅˆŅƒĐ˛Đ°Ņ‚Đ¸ Đ´ĐžĐ´Đ°Ņ‚ĐēĐžĐ˛Ņ– ваĐģŅ–Đ´Đ°Ņ†Ņ–Ņ— Ņ‚Đ° ĐŧĐĩŅ‚Đ°Ņ–ĐŊŅ„ĐžŅ€ĐŧĐ°Ņ†Ņ–ŅŽ Đ´ĐģŅ ŅĐ˛ĐžŅ—Ņ… ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Ņ–Đ˛. + +Đ—Đ°ĐŗĐ°ĐģҌĐŊŅ– ваĐģŅ–Đ´Đ°Ņ†Ņ–Ņ— Ņ‚Đ° ĐŧĐĩŅ‚Đ°Ņ–ĐŊŅ„ĐžŅ€ĐŧĐ°Ņ†Ņ–Ņ: + +* `alias` +* `title` +* `description` +* `deprecated` + +ВаĐģŅ–Đ´Đ°Ņ†Ņ–Ņ—, ҁĐŋĐĩŅ†Đ¸Ņ„Ņ–Ņ‡ĐŊŅ– Đ´ĐģŅ Ņ€ŅĐ´ĐēŅ–Đ˛: + +* `min_length` +* `max_length` +* `pattern` + +ĐšĐ°ŅŅ‚ĐžĐŧĐŊŅ– ваĐģŅ–Đ´Đ°Ņ†Ņ–Ņ— Са Đ´ĐžĐŋĐžĐŧĐžĐŗĐžŅŽ `AfterValidator`. + +ĐŖ Ņ†Đ¸Ņ… ĐŋŅ€Đ¸ĐēĐģĐ°Đ´Đ°Ņ… Ви ĐŋĐžĐąĐ°Ņ‡Đ¸Đģи, ŅĐē ĐžĐŗĐžĐģĐžŅˆŅƒĐ˛Đ°Ņ‚Đ¸ ваĐģŅ–Đ´Đ°Ņ†Ņ–Ņ— Đ´ĐģŅ СĐŊĐ°Ņ‡ĐĩĐŊҌ `str`. + +Đ”Đ¸Đ˛Ņ–Ņ‚ŅŒŅŅ ĐŊĐ°ŅŅ‚ŅƒĐŋĐŊŅ– Ņ€ĐžĐˇĐ´Ņ–Đģи, Ņ‰ĐžĐą Đ´Ņ–ĐˇĐŊĐ°Ņ‚Đ¸ŅŅ, ŅĐē ĐžĐŗĐžĐģĐžŅˆŅƒĐ˛Đ°Ņ‚Đ¸ ваĐģŅ–Đ´Đ°Ņ†Ņ–Ņ— Đ´ĐģŅ Ņ–ĐŊŅˆĐ¸Ņ… Ņ‚Đ¸ĐŋŅ–Đ˛, ĐŊаĐŋŅ€Đ¸ĐēĐģад Ņ‡Đ¸ŅĐĩĐģ. diff --git a/docs/uk/docs/tutorial/query-params.md b/docs/uk/docs/tutorial/query-params.md new file mode 100644 index 000000000..16bb42af3 --- /dev/null +++ b/docs/uk/docs/tutorial/query-params.md @@ -0,0 +1,192 @@ +# Query ĐŸĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ¸ + +КоĐģи Ви ĐžĐŗĐžĐģĐžŅˆŅƒŅ”Ņ‚Đĩ Ņ–ĐŊŅˆŅ– ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ¸ Ņ„ŅƒĐŊĐē҆Җҗ, ŅĐēŅ– ĐŊĐĩ Ņ” Ņ‡Đ°ŅŅ‚Đ¸ĐŊĐžŅŽ ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Ņ–Đ˛ ҈ĐģŅŅ…Ņƒ, вОĐŊи Đ°Đ˛Ņ‚ĐžĐŧĐ°Ņ‚Đ¸Ņ‡ĐŊĐž Ņ–ĐŊŅ‚ĐĩŅ€ĐŋŅ€ĐĩŅ‚ŅƒŅŽŅ‚ŅŒŅŅ ŅĐē "query" ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ¸. + +{* ../../docs_src/query_params/tutorial001.py hl[9] *} + +Query ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ¸ — ҆Đĩ ĐŊĐ°ĐąŅ–Ņ€ ĐŋĐ°Ņ€ ĐēĐģŅŽŅ‡-СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ, Ņ‰Đž ĐšĐ´ŅƒŅ‚ŅŒ ĐŋҖҁĐģŅ ŅĐ¸ĐŧвОĐģ҃ `?` в URL, Ņ€ĐžĐˇĐ´Ņ–ĐģĐĩĐŊŅ– ŅĐ¸ĐŧвОĐģаĐŧи `&`. + +НаĐŋŅ€Đ¸ĐēĐģад, в URL: + +``` +http://127.0.0.1:8000/items/?skip=0&limit=10 +``` + +...query ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ°Đŧи Ņ”: + +* `skip`: ĐˇŅ– СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅĐŧ `0` +* `limit`: ĐˇŅ– СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅĐŧ `10` + +ĐžŅĐēŅ–ĐģҌĐēи вОĐŊи Ņ” Ņ‡Đ°ŅŅ‚Đ¸ĐŊĐžŅŽ URL, вОĐŊи "Са СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ" Ņ” Ņ€ŅĐ´ĐēаĐŧи. + +АĐģĐĩ ĐēĐžĐģи Ви ĐžĐŗĐžĐģĐžŅˆŅƒŅ”Ņ‚Đĩ Ņ—Ņ… Ņ–Đˇ Ņ‚Đ¸ĐŋаĐŧи Python (҃ ĐŊавĐĩĐ´ĐĩĐŊĐžĐŧ҃ ĐŋŅ€Đ¸ĐēĐģĐ°Đ´Ņ– ŅĐē `int`), вОĐŊи ĐŋĐĩŅ€ĐĩŅ‚Đ˛ĐžŅ€ŅŽŅŽŅ‚ŅŒŅŅ ĐŊа ҆ĐĩĐš Ņ‚Đ¸Đŋ Ņ– ĐŋŅ€ĐžŅ…ĐžĐ´ŅŅ‚ŅŒ ĐŋĐĩŅ€ĐĩĐ˛Ņ–Ņ€Đē҃ Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´ĐŊĐžŅŅ‚Ņ–. + +ĐŖĐ˛ĐĩҁҌ Ņ‚ĐžĐš ŅĐ°ĐŧиК ĐŋŅ€ĐžŅ†Đĩҁ, ŅĐēиК ĐˇĐ°ŅŅ‚ĐžŅĐžĐ˛ŅƒŅ”Ņ‚ŅŒŅŅ Đ´Đž ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Ņ–Đ˛ ҈ĐģŅŅ…Ņƒ, Ņ‚Đ°ĐēĐžĐļ ĐˇĐ°ŅŅ‚ĐžŅĐžĐ˛ŅƒŅ”Ņ‚ŅŒŅŅ Đ´Đž query ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Ņ–Đ˛: + +* ĐŸŅ–Đ´Ņ‚Ņ€Đ¸ĐŧĐēа в Ņ€ĐĩдаĐēŅ‚ĐžŅ€Ņ– (Đ°Đ˛Ņ‚ĐžĐ´ĐžĐŋОвĐŊĐĩĐŊĐŊŅ, ĐŋĐĩŅ€ĐĩĐ˛Ņ–Ņ€Đēа ĐŋĐžĐŧиĐģĐžĐē) +* "ĐŸĐ°Ņ€ŅĐ¸ĐŊĐŗ" даĐŊĐ¸Ņ… +* ВаĐģŅ–Đ´Đ°Ņ†Ņ–Ņ даĐŊĐ¸Ņ… +* ĐĐ˛Ņ‚ĐžĐŧĐ°Ņ‚Đ¸Ņ‡ĐŊа Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Ņ–Ņ + + +## ЗĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ Са СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ + +ĐžŅĐēŅ–ĐģҌĐēи query ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ¸ ĐŊĐĩ Ņ” ҄ҖĐēŅĐžĐ˛Đ°ĐŊĐžŅŽ Ņ‡Đ°ŅŅ‚Đ¸ĐŊĐžŅŽ ҈ĐģŅŅ…Ņƒ, вОĐŊи ĐŧĐžĐļŅƒŅ‚ŅŒ ĐąŅƒŅ‚Đ¸ ĐŊĐĩĐžĐąĐžĐ˛â€™ŅĐˇĐēОвиĐŧи Ņ‚Đ° ĐŧĐ°Ņ‚Đ¸ СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ Са СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ. + +ĐŖ ĐŊавĐĩĐ´ĐĩĐŊĐžĐŧ҃ Đ˛Đ¸Ņ‰Đĩ ĐŋŅ€Đ¸ĐēĐģĐ°Đ´Ņ– вОĐŊи ĐŧĐ°ŅŽŅ‚ŅŒ СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ Са СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ: `skip=0` Ņ– `limit=10`. + +ĐžŅ‚ĐļĐĩ, Ņ€ĐĩĐˇŅƒĐģŅŒŅ‚Đ°Ņ‚ ĐŋĐĩŅ€ĐĩŅ…ĐžĐ´Ņƒ Са URL: + +``` +http://127.0.0.1:8000/items/ +``` +ĐąŅƒĐ´Đĩ Ņ‚Đ°ĐēиĐŧ ŅĐ°ĐŧиĐŧ, ŅĐē Ņ– ĐŋĐĩŅ€ĐĩŅ…Ņ–Đ´ Са ĐŋĐžŅĐ¸ĐģаĐŊĐŊŅĐŧ: + +``` +http://127.0.0.1:8000/items/?skip=0&limit=10 +``` + +АĐģĐĩ ŅĐēŅ‰Đž Ви ĐŋĐĩŅ€ĐĩКдĐĩŅ‚Đĩ, ĐŊаĐŋŅ€Đ¸ĐēĐģад, Са ĐŋĐžŅĐ¸ĐģаĐŊĐŊŅĐŧ: + +``` +http://127.0.0.1:8000/items/?skip=20 +``` + +ЗĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Ņ–Đ˛ ҃ Đ˛Đ°ŅˆŅ–Đš Ņ„ŅƒĐŊĐē҆Җҗ ĐąŅƒĐ´ŅƒŅ‚ŅŒ Ņ‚Đ°ĐēиĐŧи: + +* `skip=20`: ĐžŅĐēŅ–ĐģҌĐēи Ви вĐēаСаĐģи ĐšĐžĐŗĐž в URL +* `limit=10`: ĐžŅĐēŅ–ĐģҌĐēи ҆Đĩ СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ Са СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ + +## НĐĩОйОв'ŅĐˇĐēĐžĐ˛Ņ– ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ¸ + +АĐŊаĐģĐžĐŗŅ–Ņ‡ĐŊĐž, Ви ĐŧĐžĐļĐĩŅ‚Đĩ ĐžĐŗĐžĐģĐžŅĐ¸Ņ‚Đ¸ ĐŊĐĩĐžĐąĐžĐ˛â€™ŅĐˇĐēĐžĐ˛Ņ– query ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ¸, Đ˛ŅŅ‚Đ°ĐŊĐžĐ˛Đ¸Đ˛ŅˆĐ¸ Đ´ĐģŅ ĐŊĐ¸Ņ… СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ Са СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ `None`: + +{* ../../docs_src/query_params/tutorial002_py310.py hl[7] *} + +ĐŖ Ņ†ŅŒĐžĐŧ҃ виĐŋадĐē҃ ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ Ņ„ŅƒĐŊĐē҆Җҗ `q` ĐąŅƒĐ´Đĩ ĐŊĐĩĐžĐąĐžĐ˛â€™ŅĐˇĐēОвиĐŧ Ņ– Са СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ ĐŧĐ°Ņ‚Đ¸ĐŧĐĩ СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ `None`. + +/// check | ĐŸŅ€Đ¸ĐŧŅ–Ņ‚Đēа + +ĐĸаĐēĐžĐļ СвĐĩŅ€ĐŊŅ–Ņ‚ŅŒ ŅƒĐ˛Đ°ĐŗŅƒ, Ņ‰Đž **FastAPI** Đ´ĐžŅŅ‚Đ°Ņ‚ĐŊŅŒĐž Ņ€ĐžĐˇŅƒĐŧĐŊиК, Ņ‰ĐžĐą виСĐŊĐ°Ņ‡Đ¸Ņ‚Đ¸, Ņ‰Đž ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ ҈ĐģŅŅ…Ņƒ `item_id` Ņ” ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€ĐžĐŧ ҈ĐģŅŅ…Ņƒ, а `q` — ĐŊŅ–, ĐžŅ‚ĐļĐĩ, ҆Đĩ query ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ. + +/// + +## ПĐĩŅ€ĐĩŅ‚Đ˛ĐžŅ€ĐĩĐŊĐŊŅ Ņ‚Đ¸Đŋ҃ Query ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ° + +Ви Ņ‚Đ°ĐēĐžĐļ ĐŧĐžĐļĐĩŅ‚Đĩ ĐžĐŗĐžĐģĐžŅˆŅƒĐ˛Đ°Ņ‚Đ¸ ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ¸ Ņ‚Đ¸Đŋ҃ `bool`, Ņ– вОĐŊи ĐąŅƒĐ´ŅƒŅ‚ŅŒ Đ°Đ˛Ņ‚ĐžĐŧĐ°Ņ‚Đ¸Ņ‡ĐŊĐž ĐēĐžĐŊвĐĩŅ€Ņ‚ĐžĐ˛Đ°ĐŊŅ–: + +{* ../../docs_src/query_params/tutorial003_py310.py hl[7] *} + +ĐŖ Ņ†ŅŒĐžĐŧ҃ виĐŋадĐē҃, ŅĐēŅ‰Đž Ви СвĐĩŅ€ĐŊĐĩŅ‚ĐĩҁҌ Đ´Đž: + + +``` +http://127.0.0.1:8000/items/foo?short=1 +``` + +айО + +``` +http://127.0.0.1:8000/items/foo?short=True +``` + +айО + +``` +http://127.0.0.1:8000/items/foo?short=true +``` + +айО + +``` +http://127.0.0.1:8000/items/foo?short=on +``` + +айО + +``` +http://127.0.0.1:8000/items/foo?short=yes +``` + +айО ĐąŅƒĐ´ŅŒ-ŅĐēиК Ņ–ĐŊŅˆĐ¸Đš Đ˛Đ°Ņ€Ņ–Đ°ĐŊŅ‚ ĐŊаĐŋĐ¸ŅĐ°ĐŊĐŊŅ (вĐĩĐģиĐēŅ– ĐģŅ–Ņ‚ĐĩŅ€Đ¸, ĐŋĐĩŅ€ŅˆĐ° ĐģŅ–Ņ‚ĐĩŅ€Đ° вĐĩĐģиĐēа Ņ‚ĐžŅ‰Đž), Đ˛Đ°ŅˆĐ° Ņ„ŅƒĐŊĐēŅ†Ņ–Ņ ĐŋĐžĐąĐ°Ņ‡Đ¸Ņ‚ŅŒ ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ `short` ĐˇŅ– СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅĐŧ `True` С Ņ‚Đ¸ĐŋĐžĐŧ даĐŊĐ¸Ņ… `bool`. В Ņ–ĐŊŅˆĐžĐŧ҃ виĐŋадĐē҃ – `False`. + +## ĐšŅ–ĐģҌĐēа path Ņ– query ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Ņ–Đ˛ + +Ви ĐŧĐžĐļĐĩŅ‚Đĩ ОдĐŊĐžŅ‡Đ°ŅĐŊĐž ĐžĐŗĐžĐģĐžŅˆŅƒĐ˛Đ°Ņ‚Đ¸ ĐēŅ–ĐģҌĐēа path Ņ– query ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Ņ–Đ˛, Ņ– **FastAPI** Đ°Đ˛Ņ‚ĐžĐŧĐ°Ņ‚Đ¸Ņ‡ĐŊĐž виСĐŊĐ°Ņ‡Đ¸Ņ‚ŅŒ, ŅĐēиК С ĐŊĐ¸Ņ… Đ´Đž Ņ‡ĐžĐŗĐž ĐŊаĐģĐĩĐļĐ¸Ņ‚ŅŒ. + + +НĐĩ ĐŋĐžŅ‚Ņ€Ņ–ĐąĐŊĐž Đ´ĐžŅ‚Ņ€Đ¸ĐŧŅƒĐ˛Đ°Ņ‚Đ¸ŅŅŒ ĐŋĐĩвĐŊĐžĐŗĐž ĐŋĐžŅ€ŅĐ´Đē҃ Ņ—Ņ… ĐžĐŗĐžĐģĐžŅˆĐĩĐŊĐŊŅ. + +ВоĐŊи виСĐŊĐ°Ņ‡Đ°ŅŽŅ‚ŅŒŅŅ Са ĐŊĐ°ĐˇĐ˛ĐžŅŽ: + +{* ../../docs_src/query_params/tutorial004_py310.py hl[6,8] *} + +## ĐžĐąĐžĐ˛â€™ŅĐˇĐēĐžĐ˛Ņ– Query ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ¸ + +Đ¯ĐēŅ‰Đž Ви ĐžĐŗĐžĐģĐžŅˆŅƒŅ”Ņ‚Đĩ СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ Са СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ Đ´ĐģŅ ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Ņ–Đ˛, ŅĐēŅ– ĐŊĐĩ Ņ” path-ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ°Đŧи (҃ Ņ†ŅŒĐžĐŧ҃ Ņ€ĐžĐˇĐ´Ņ–ĐģŅ– Đŧи ĐąĐ°Ņ‡Đ¸Đģи ĐŋĐžĐēи Ņ‰Đž ĐģĐ¸ŅˆĐĩ path ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ¸), Ņ‚ĐžĐ´Ņ– вОĐŊи ŅŅ‚Đ°ŅŽŅ‚ŅŒ ĐŊĐĩĐžĐąĐžĐ˛â€™ŅĐˇĐēОвиĐŧи. + +Đ¯ĐēŅ‰Đž Ви ĐŊĐĩ Ņ…ĐžŅ‡ĐĩŅ‚Đĩ вĐēĐ°ĐˇŅƒĐ˛Đ°Ņ‚Đ¸ ĐēĐžĐŊĐēŅ€ĐĩŅ‚ĐŊŅ– СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ, аĐģĐĩ Ņ…ĐžŅ‡ĐĩŅ‚Đĩ ĐˇŅ€ĐžĐąĐ¸Ņ‚Đ¸ ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ ĐžĐŋŅ†Ņ–ĐžĐŊаĐģҌĐŊиĐŧ, ĐˇĐ°Đ´Đ°ĐšŅ‚Đĩ `None` ŅĐē СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ Са СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ. + +АĐģĐĩ ŅĐēŅ‰Đž Ви Ņ…ĐžŅ‡ĐĩŅ‚Đĩ ĐˇŅ€ĐžĐąĐ¸Ņ‚Đ¸ query ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ ĐžĐąĐžĐ˛â€™ŅĐˇĐēОвиĐŧ, ĐŋŅ€ĐžŅŅ‚Đž ĐŊĐĩ вĐēĐ°ĐˇŅƒĐšŅ‚Đĩ Đ´ĐģŅ ĐŊŅŒĐžĐŗĐž СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ Са СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ: + +{* ../../docs_src/query_params/tutorial005.py hl[6:7] *} + +ĐĸŅƒŅ‚ `needy` – ĐžĐąĐžĐ˛â€™ŅĐˇĐēОвиК query ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ Ņ‚Đ¸Đŋ҃ `str`. + +Đ¯ĐēŅ‰Đž Ви Đ˛Ņ–Đ´ĐēŅ€Đ¸Ņ”Ņ‚Đĩ ҃ ĐąŅ€Đ°ŅƒĐˇĐĩҀҖ URL-Đ°Đ´Ņ€Đĩҁ҃: + +``` +http://127.0.0.1:8000/items/foo-item +``` + +...ĐąĐĩС дОдаваĐŊĐŊŅ ĐžĐąĐžĐ˛â€™ŅĐˇĐēĐžĐ˛ĐžĐŗĐž ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ° `needy`, Ви ĐŋĐžĐąĐ°Ņ‡Đ¸Ņ‚Đĩ ĐŋĐžĐŧиĐģĐē҃: + +```JSON +{ + "detail": [ + { + "type": "missing", + "loc": [ + "query", + "needy" + ], + "msg": "Field required", + "input": null, + "url": "https://errors.pydantic.dev/2.1/v/missing" + } + ] +} +``` + +ĐžŅĐēŅ–ĐģҌĐēи `needy` Ņ” ĐžĐąĐžĐ˛â€™ŅĐˇĐēОвиĐŧ ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€ĐžĐŧ, ваĐŧ ĐŋĐžŅ‚Ņ€Ņ–ĐąĐŊĐž вĐēĐ°ĐˇĐ°Ņ‚Đ¸ ĐšĐžĐŗĐž в URL: + +``` +http://127.0.0.1:8000/items/foo-item?needy=sooooneedy +``` + +...҆ĐĩĐš СаĐŋĐ¸Ņ‚ ĐŋОвĐĩŅ€ĐŊĐĩ: + +```JSON +{ + "item_id": "foo-item", + "needy": "sooooneedy" +} +``` + + +Đ—Đ˛Đ¸Ņ‡Đ°ĐšĐŊĐž, Ви ĐŧĐžĐļĐĩŅ‚Đĩ виСĐŊĐ°Ņ‡Đ¸Ņ‚Đ¸ Đ´ĐĩŅĐēŅ– ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ¸ ŅĐē ĐžĐąĐžĐ˛â€™ŅĐˇĐēĐžĐ˛Ņ–, Ņ–ĐŊŅˆŅ– ĐˇŅ– СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅĐŧ Са СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ, а ҉Đĩ Đ´ĐĩŅĐēŅ– — ĐŋОвĐŊŅ–ŅŅ‚ŅŽ ĐžĐŋŅ†Ņ–ĐžĐŊаĐģҌĐŊŅ–: + +{* ../../docs_src/query_params/tutorial006_py310.py hl[8] *} + +ĐŖ Ņ†ŅŒĐžĐŧ҃ виĐŋадĐē҃ Ņ” 3 query ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ¸: + +* `needy`, ĐžĐąĐžĐ˛â€™ŅĐˇĐēОвиК `str`. +* `skip`, `int` ĐˇŅ– СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅĐŧ Са СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ `0`. +* `limit`, ĐžĐŋŅ†Ņ–ĐžĐŊаĐģҌĐŊиК `int`. + + +/// tip | ĐŸŅ–Đ´ĐēаСĐēа + +Ви Ņ‚Đ°ĐēĐžĐļ ĐŧĐžĐļĐĩŅ‚Đĩ виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ `Enum`-и, Ņ‚Đ°Đē ŅĐ°ĐŧĐž ŅĐē Ņ– С [Path Parameters](path-params.md#predefined-values){.internal-link target=_blank}. + +/// diff --git a/docs/uk/docs/tutorial/request-files.md b/docs/uk/docs/tutorial/request-files.md new file mode 100644 index 000000000..18b7cc01c --- /dev/null +++ b/docs/uk/docs/tutorial/request-files.md @@ -0,0 +1,175 @@ +# ЗаĐŋĐ¸Ņ‚ Ņ„Đ°ĐšĐģŅ–Đ˛ + +Ви ĐŧĐžĐļĐĩŅ‚Đĩ виСĐŊĐ°Ņ‡Đ¸Ņ‚Đ¸ Ņ„Đ°ĐšĐģи, ŅĐēŅ– ĐąŅƒĐ´ŅƒŅ‚ŅŒ СаваĐŊŅ‚Đ°ĐļŅƒĐ˛Đ°Ņ‚Đ¸ŅŅ ĐēĐģŅ–Ņ”ĐŊŅ‚ĐžĐŧ, виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅŽŅ‡Đ¸ `File`. + +/// info | ІĐŊŅ„ĐžŅ€ĐŧĐ°Ņ†Ņ–Ņ + +ЊОй ĐžŅ‚Ņ€Đ¸ĐŧŅƒĐ˛Đ°Ņ‚Đ¸ СаваĐŊŅ‚Đ°ĐļĐĩĐŊŅ– Ņ„Đ°ĐšĐģи, ҁĐŋĐžŅ‡Đ°Ņ‚Đē҃ Đ˛ŅŅ‚Đ°ĐŊĐžĐ˛Ņ–Ņ‚ŅŒ python-multipart. + +ПĐĩŅ€ĐĩĐēĐžĐŊĐ°ĐšŅ‚ĐĩŅŅ, Ņ‰Đž Ви ŅŅ‚Đ˛ĐžŅ€Đ¸Đģи [Đ˛Ņ–Ņ€Ņ‚ŅƒĐ°ĐģҌĐŊĐĩ ҁĐĩŅ€ĐĩĐ´ĐžĐ˛Đ¸Ņ‰Đĩ](../virtual-environments.md){.internal-link target=_blank}, аĐēŅ‚Đ¸Đ˛ŅƒĐ˛Đ°Đģи ĐšĐžĐŗĐž Ņ‚Đ° Đ˛ŅŅ‚Đ°ĐŊОвиĐģи ĐŋаĐēĐĩŅ‚, ĐŊаĐŋŅ€Đ¸ĐēĐģад: + +```console +$ pip install python-multipart +``` + +ĐĻĐĩ ĐŊĐĩĐžĐąŅ…Ņ–Đ´ĐŊĐž, ĐžŅĐēŅ–ĐģҌĐēи СаваĐŊŅ‚Đ°ĐļĐĩĐŊŅ– Ņ„Đ°ĐšĐģи ĐŋĐĩŅ€ĐĩĐ´Đ°ŅŽŅ‚ŅŒŅŅ ҃ Đ˛Đ¸ĐŗĐģŅĐ´Ņ– "Ņ„ĐžŅ€ĐŧĐ°Ņ‚ĐžĐ˛Đ°ĐŊĐ¸Ņ… даĐŊĐ¸Ņ… Ņ„ĐžŅ€Đŧи". + +/// + +## ІĐŧĐŋĐžŅ€Ņ‚ `File` + +ІĐŧĐŋĐžŅ€Ņ‚ŅƒĐšŅ‚Đĩ `File` Ņ‚Đ° `UploadFile` С `fastapi`: + +{* ../../docs_src/request_files/tutorial001_an_py39.py hl[3] *} + +## ВизĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Ņ–Đ˛ `File` + +ĐĄŅ‚Đ˛ĐžŅ€Ņ–Ņ‚ŅŒ ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ¸ Ņ„Đ°ĐšĐģŅ–Đ˛ Ņ‚Đ°Đē ŅĐ°ĐŧĐž ŅĐē Ви Đą ŅŅ‚Đ˛ĐžŅ€ŅŽĐ˛Đ°Đģи `Body` айО `Form`: + +{* ../../docs_src/request_files/tutorial001_an_py39.py hl[9] *} + +/// info | ІĐŊŅ„ĐžŅ€ĐŧĐ°Ņ†Ņ–Ņ + +`File` — ҆Đĩ ĐēĐģĐ°Ņ, ŅĐēиК ĐąĐĩСĐŋĐžŅĐĩŅ€ĐĩĐ´ĐŊŅŒĐž ҃ҁĐŋадĐēĐžĐ˛ŅƒŅ” `Form`. + +АĐģĐĩ ĐŋаĐŧâ€™ŅŅ‚Đ°ĐšŅ‚Đĩ, Ņ‰Đž ĐēĐžĐģи Ви Ņ–ĐŧĐŋĐžŅ€Ņ‚ŅƒŅ”Ņ‚Đĩ `Query`, `Path`, `File` Ņ‚Đ° Ņ–ĐŊŅˆŅ– С `fastapi`, ҆Đĩ ĐŊĐ°ŅĐŋŅ€Đ°Đ˛Đ´Ņ– Ņ„ŅƒĐŊĐē҆Җҗ, ŅĐēŅ– ĐŋОвĐĩŅ€Ņ‚Đ°ŅŽŅ‚ŅŒ ҁĐŋĐĩŅ†Ņ–Đ°ĐģҌĐŊŅ– ĐēĐģĐ°ŅĐ¸. + +/// + +/// tip | ĐŸŅ–Đ´ĐēаСĐēа + +ЊОй ĐžĐŗĐžĐģĐžŅĐ¸Ņ‚Đ¸ ҂ҖĐģа Ņ„Đ°ĐšĐģŅ–Đ˛, ВаĐŧ ĐŋĐžŅ‚Ņ€Ņ–ĐąĐŊĐž виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ `File`, Ņ‚ĐžĐŧ҃ Ņ‰Đž Ņ–ĐŊаĐē҈Đĩ ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ¸ ĐąŅƒĐ´ŅƒŅ‚ŅŒ Ņ–ĐŊŅ‚ĐĩŅ€ĐŋŅ€ĐĩŅ‚ĐžĐ˛Đ°ĐŊŅ– ŅĐē ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ¸ СаĐŋĐ¸Ņ‚Ņƒ айО ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ¸ ҂ҖĐģа (JSON). + +/// + +ФаКĐģи ĐąŅƒĐ´ŅƒŅ‚ŅŒ СаваĐŊŅ‚Đ°ĐļĐĩĐŊŅ– ҃ Đ˛Đ¸ĐŗĐģŅĐ´Ņ– "Ņ„ĐžŅ€ĐŧĐ°Ņ‚ĐžĐ˛Đ°ĐŊĐ¸Ņ… даĐŊĐ¸Ņ… Ņ„ĐžŅ€Đŧи". + +Đ¯ĐēŅ‰Đž Ви ĐžĐŗĐžĐģĐžŅĐ¸Ņ‚Đĩ Ņ‚Đ¸Đŋ ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ° Ņ„ŅƒĐŊĐē҆Җҗ ĐžĐąŅ€ĐžĐąĐŊиĐēа ĐŧĐ°Ņ€ŅˆŅ€ŅƒŅ‚Ņƒ ŅĐē `bytes`, **FastAPI** ĐŋŅ€ĐžŅ‡Đ¸Ņ‚Đ°Ņ” Ņ„Đ°ĐšĐģ Са Đ’Đ°Ņ, Ņ– Ви ĐžŅ‚Ņ€Đ¸ĐŧĐ°Ņ”Ņ‚Đĩ ĐšĐžĐŗĐž вĐŧҖҁ҂ ҃ Đ˛Đ¸ĐŗĐģŅĐ´Ņ– `bytes`. + +ОдĐŊаĐē ĐŧĐ°ĐšŅ‚Đĩ ĐŊа ŅƒĐ˛Đ°ĐˇŅ–, Ņ‰Đž вĐĩҁҌ вĐŧҖҁ҂ ĐąŅƒĐ´Đĩ СйĐĩŅ€ĐĩĐļĐĩĐŊĐž в ĐŋаĐŧ'ŅŅ‚Ņ–. ĐĻĐĩ ĐŋŅ€Đ°Ņ†ŅŽĐ˛Đ°Ņ‚Đ¸ĐŧĐĩ Đ´ĐžĐąŅ€Đĩ Đ´ĐģŅ ĐŧаĐģĐ¸Ņ… Ņ„Đ°ĐšĐģŅ–Đ˛. + +АĐģĐĩ в Đ´ĐĩŅĐēĐ¸Ņ… виĐŋадĐēĐ°Ņ… ВаĐŧ ĐŧĐžĐļĐĩ СĐŊĐ°Đ´ĐžĐąĐ¸Ņ‚Đ¸ŅŅ `UploadFile`. + +## ĐŸĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ¸ Ņ„Đ°ĐšĐģ҃ С `UploadFile` + +ВизĐŊĐ°Ņ‡Ņ‚Đĩ ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ Ņ„Đ°ĐšĐģ҃ С Ņ‚Đ¸ĐŋĐžĐŧ `UploadFile`: + +{* ../../docs_src/request_files/tutorial001_an_py39.py hl[14] *} + +ВиĐēĐžŅ€Đ¸ŅŅ‚Đ°ĐŊĐŊŅ `UploadFile` ĐŧĐ°Ņ” ĐēŅ–ĐģҌĐēа ĐŋĐĩŅ€ĐĩĐ˛Đ°Đŗ ĐŋĐĩŅ€ĐĩĐ´ `bytes`: + +* ВаĐŧ ĐŊĐĩ ĐŋĐžŅ‚Ņ€Ņ–ĐąĐŊĐž виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ `File()` ҃ СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ– Са СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ°. +* ВиĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅ”Ņ‚ŅŒŅŅ "ĐąŅƒŅ„ĐĩŅ€Đ¸ĐˇĐžĐ˛Đ°ĐŊиК" Ņ„Đ°ĐšĐģ: + * ФаКĐģ СйĐĩŅ€Ņ–ĐŗĐ°Ņ”Ņ‚ŅŒŅŅ в ĐŋаĐŧ'ŅŅ‚Ņ– Đ´Đž Đ´ĐžŅŅĐŗĐŊĐĩĐŊĐŊŅ ĐŋĐĩвĐŊĐžĐŗĐž ОйĐŧĐĩĐļĐĩĐŊĐŊŅ, ĐŋҖҁĐģŅ Ņ‡ĐžĐŗĐž Đ˛Ņ–ĐŊ СаĐŋĐ¸ŅŅƒŅ”Ņ‚ŅŒŅŅ ĐŊа Đ´Đ¸ŅĐē. +* ĐĻĐĩ ОСĐŊĐ°Ņ‡Đ°Ņ”, Ņ‰Đž Đ˛Ņ–ĐŊ Đ´ĐžĐąŅ€Đĩ ĐŋŅ€Đ°Ņ†ŅŽŅ” Đ´ĐģŅ вĐĩĐģиĐēĐ¸Ņ… Ņ„Đ°ĐšĐģŅ–Đ˛, Ņ‚Đ°ĐēĐ¸Ņ… ŅĐē ĐˇĐžĐąŅ€Đ°ĐļĐĩĐŊĐŊŅ, Đ˛Ņ–Đ´ĐĩĐž, вĐĩĐģиĐēŅ– Đ´Đ˛Ņ–ĐšĐēĐžĐ˛Ņ– Ņ„Đ°ĐšĐģи Ņ‚ĐžŅ‰Đž, ĐŊĐĩ ҁĐŋĐžĐļĐ¸Đ˛Đ°ŅŽŅ‡Đ¸ Đ˛ŅŅŽ ĐŋаĐŧ'ŅŅ‚ŅŒ. +Ви ĐŧĐžĐļĐĩŅ‚Đĩ ĐžŅ‚Ņ€Đ¸ĐŧĐ°Ņ‚Đ¸ ĐŧĐĩŅ‚Đ°Đ´Đ°ĐŊŅ– ĐŋŅ€Đž СаваĐŊŅ‚Đ°ĐļĐĩĐŊиК Ņ„Đ°ĐšĐģ. +* Đ’Ņ–ĐŊ ĐŧĐ°Ņ” file-like `Đ°ŅĐ¸ĐŊŅ…Ņ€ĐžĐŊĐŊиК Ņ„Đ°ĐšĐģОвиК Ņ–ĐŊŅ‚ĐĩҀ҄ĐĩĐšŅ` interface. +* Đ’Ņ–ĐŊ ĐŊĐ°Đ´Đ°Ņ” Ņ„Đ°ĐēŅ‚Đ¸Ņ‡ĐŊиК Ой'Ņ”ĐēŅ‚ Python `SpooledTemporaryFile`, ŅĐēиК ĐŧĐžĐļĐŊа ĐŋĐĩŅ€ĐĩĐ´Đ°Đ˛Đ°Ņ‚Đ¸ ĐąĐĩСĐŋĐžŅĐĩŅ€ĐĩĐ´ĐŊŅŒĐž Ņ–ĐŊŅˆĐ¸Đŧ ĐąŅ–ĐąĐģŅ–ĐžŅ‚ĐĩĐēаĐŧ. + +### `UploadFile` + +`UploadFile` ĐŧĐ°Ņ” Ņ‚Đ°ĐēŅ– Đ°Ņ‚Ņ€Đ¸ĐąŅƒŅ‚Đ¸: + +* `filename`: Đ ŅĐ´ĐžĐē `str` С ĐžŅ€Đ¸ĐŗŅ–ĐŊаĐģҌĐŊĐžŅŽ ĐŊĐ°ĐˇĐ˛ĐžŅŽ Ņ„Đ°ĐšĐģ҃, ŅĐēиК ĐąŅƒĐ˛ СаваĐŊŅ‚Đ°ĐļĐĩĐŊиК (ĐŊаĐŋŅ€Đ¸ĐēĐģад, `myimage.jpg`). +* `content_type`: Đ ŅĐ´ĐžĐē `str` С MIME-Ņ‚Đ¸ĐŋĐžĐŧ (ĐŊаĐŋŅ€Đ¸ĐēĐģад, `image/jpeg`). +* `file`: Об'Ņ”ĐēŅ‚ SpooledTemporaryFile (Ņ„Đ°ĐšĐģĐžĐŋĐžĐ´Ņ–ĐąĐŊиК Ой'Ņ”ĐēŅ‚). ĐĻĐĩ Ņ„Đ°ĐēŅ‚Đ¸Ņ‡ĐŊиК Ņ„Đ°ĐšĐģОвиК Ой'Ņ”ĐēŅ‚ Python, ŅĐēиК ĐŧĐžĐļĐŊа ĐąĐĩСĐŋĐžŅĐĩŅ€ĐĩĐ´ĐŊŅŒĐž ĐŋĐĩŅ€ĐĩĐ´Đ°Đ˛Đ°Ņ‚Đ¸ Ņ–ĐŊŅˆĐ¸Đŧ Ņ„ŅƒĐŊĐēŅ†Ņ–ŅĐŧ айО ĐąŅ–ĐąĐģŅ–ĐžŅ‚ĐĩĐēаĐŧ, Ņ‰Đž ĐžŅ‡Ņ–ĐēŅƒŅŽŅ‚ŅŒ "Ņ„Đ°ĐšĐģĐžĐŋĐžĐ´Ņ–ĐąĐŊиК" Ой'Ņ”ĐēŅ‚. + +`UploadFile` ĐŧĐ°Ņ” Ņ‚Đ°ĐēŅ– Đ°ŅĐ¸ĐŊŅ…Ņ€ĐžĐŊĐŊŅ– `async` ĐŧĐĩŅ‚ĐžĐ´Đ¸. ВоĐŊи виĐēĐģиĐēĐ°ŅŽŅ‚ŅŒ Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´ĐŊŅ– ĐŧĐĩŅ‚ĐžĐ´Đ¸ Ņ„Đ°ĐšĐģ҃ ĐŋŅ–Đ´ ĐēаĐŋĐžŅ‚ĐžĐŧ (виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅŽŅ‡Đ¸ вĐŊŅƒŅ‚Ņ€Ņ–ŅˆĐŊŅ–Đš `SpooledTemporaryFile`). + +* `write(data)`: ЗаĐŋĐ¸ŅŅƒŅ” `data` (`str` айО `bytes`) ҃ Ņ„Đ°ĐšĐģ. +* `read(size)`: Đ§Đ¸Ņ‚Đ°Ņ” `size` (`int`) ĐąĐ°ĐšŅ‚Ņ–Đ˛/ŅĐ¸ĐŧвОĐģŅ–Đ˛ С Ņ„Đ°ĐšĐģ҃. +* `seek(offset)`: ПĐĩŅ€ĐĩĐŧŅ–Ņ‰ŅƒŅ”Ņ‚ŅŒŅŅ Đ´Đž ĐŋĐžĐˇĐ¸Ņ†Ņ–Ņ— `offset` (`int`) ҃ Ņ„Đ°ĐšĐģŅ–. + * НаĐŋŅ€Đ¸ĐēĐģад, `await myfile.seek(0)` ĐŋОвĐĩŅ€ĐŊĐĩ ĐēŅƒŅ€ŅĐžŅ€ ĐŊа ĐŋĐžŅ‡Đ°Ņ‚ĐžĐē Ņ„Đ°ĐšĐģ҃. + * This is especially useful if you run `await myfile.read()` once and then need to read the contents again. ĐĻĐĩ ĐžŅĐžĐąĐģивО ĐēĐžŅ€Đ¸ŅĐŊĐž, ŅĐēŅ‰Đž Ви виĐēĐžĐŊŅƒŅ”Ņ‚Đĩ await `await myfile.read()` ОдиĐŊ Ņ€Đ°Đˇ, а ĐŋĐžŅ‚Ņ–Đŧ ĐŋĐžŅ‚Ņ€Ņ–ĐąĐŊĐž СĐŊĐžĐ˛Ņƒ ĐŋŅ€ĐžŅ‡Đ¸Ņ‚Đ°Ņ‚Đ¸ вĐŧҖҁ҂. +* `close()`: ЗаĐēŅ€Đ¸Đ˛Đ°Ņ” Ņ„Đ°ĐšĐģ. + +ĐžŅĐēŅ–ĐģҌĐēи Đ˛ŅŅ– ҆Җ ĐŧĐĩŅ‚ĐžĐ´Đ¸ Ņ” Đ°ŅĐ¸ĐŊŅ…Ņ€ĐžĐŊĐŊиĐŧи `async`, ВаĐŧ ĐŋĐžŅ‚Ņ€Ņ–ĐąĐŊĐž виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ "await": + +НаĐŋŅ€Đ¸ĐēĐģад, Đ˛ŅĐĩŅ€ĐĩдиĐŊŅ– `async` *Ņ„ŅƒĐŊĐē҆Җҗ ĐžĐąŅ€ĐžĐąĐēи ҈ĐģŅŅ…Ņƒ* Ви ĐŧĐžĐļĐĩŅ‚Đĩ ĐžŅ‚Ņ€Đ¸ĐŧĐ°Ņ‚Đ¸ вĐŧҖҁ҂ Са Đ´ĐžĐŋĐžĐŧĐžĐŗĐžŅŽ: + +```Python +contents = await myfile.read() +``` +Đ¯ĐēŅ‰Đž Ви СĐŊĐ°Ņ…ĐžĐ´Đ¸Ņ‚ĐĩҁҌ ҃ ĐˇĐ˛Đ¸Ņ‡Đ°ĐšĐŊŅ–Đš `def` *Ņ„ŅƒĐŊĐē҆Җҗ ĐžĐąŅ€ĐžĐąĐēи ҈ĐģŅŅ…Ņƒ*, Ви ĐŧĐžĐļĐĩŅ‚Đĩ ĐžŅ‚Ņ€Đ¸ĐŧĐ°Ņ‚Đ¸ Đ´ĐžŅŅ‚ŅƒĐŋ Đ´Đž `UploadFile.file` ĐąĐĩСĐŋĐžŅĐĩŅ€ĐĩĐ´ĐŊŅŒĐž, ĐŊаĐŋŅ€Đ¸ĐēĐģад: + +```Python +contents = myfile.file.read() +``` + +/// note | ĐĸĐĩŅ…ĐŊҖ҇ĐŊŅ– Đ´ĐĩŅ‚Đ°ĐģŅ– `async` + +КоĐģи Ви виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅ”Ņ‚Đĩ `async` ĐŧĐĩŅ‚ĐžĐ´Đ¸, **FastAPI** виĐēĐžĐŊŅƒŅ” Ņ„Đ°ĐšĐģĐžĐ˛Ņ– ĐžĐŋĐĩŅ€Đ°Ņ†Ņ–Ņ— ҃ Đŋ҃ĐģŅ– ĐŋĐžŅ‚ĐžĐēŅ–Đ˛ Ņ‚Đ° ĐžŅ‡Ņ–ĐēŅƒŅ” Ņ—Ņ… СавĐĩŅ€ŅˆĐĩĐŊĐŊŅ. + +/// + +/// note | ĐĸĐĩŅ…ĐŊҖ҇ĐŊŅ– Đ´ĐĩŅ‚Đ°ĐģŅ– Starlette + +`UploadFile` ҃ **FastAPI** ҃ҁĐŋадĐēĐžĐ˛ŅƒŅ”Ņ‚ŅŒŅŅ ĐąĐĩСĐŋĐžŅĐĩŅ€ĐĩĐ´ĐŊŅŒĐž Đ˛Ņ–Đ´ `UploadFile` ҃ **Starlette**, аĐģĐĩ Đ´ĐžĐ´Đ°Ņ” Đ´ĐĩŅĐēŅ– ĐŊĐĩĐžĐąŅ…Ņ–Đ´ĐŊŅ– Ņ‡Đ°ŅŅ‚Đ¸ĐŊи, Ņ‰ĐžĐą ĐˇŅ€ĐžĐąĐ¸Ņ‚Đ¸ ĐšĐžĐŗĐž ҁ҃ĐŧҖҁĐŊиĐŧ Ņ–Đˇ **Pydantic** Ņ‚Đ° Ņ–ĐŊŅˆĐ¸Đŧи ĐēĐžĐŧĐŋĐžĐŊĐĩĐŊŅ‚Đ°Đŧи FastAPI. + +/// + +## ĐŠĐž Ņ‚Đ°ĐēĐĩ "Form Data" + +ĐĄĐŋĐžŅŅ–Đą, ҃ ŅĐēиК HTML-Ņ„ĐžŅ€Đŧи (`
`) ĐŊĐ°Đ´ŅĐ¸ĐģĐ°ŅŽŅ‚ŅŒ даĐŊŅ– ĐŊа ҁĐĩŅ€Đ˛ĐĩŅ€, ĐˇĐ°ĐˇĐ˛Đ¸Ņ‡Đ°Đš виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅ” "ҁĐŋĐĩŅ†Ņ–Đ°ĐģҌĐŊĐĩ" ĐēĐžĐ´ŅƒĐ˛Đ°ĐŊĐŊŅ, Đ˛Ņ–Đ´ĐŧŅ–ĐŊĐŊĐĩ Đ˛Ņ–Đ´ JSON. + +**FastAPI** СайĐĩСĐŋĐĩŅ‡ŅƒŅ” ĐŋŅ€Đ°Đ˛Đ¸ĐģҌĐŊĐĩ ĐˇŅ‡Đ¸Ņ‚ŅƒĐ˛Đ°ĐŊĐŊŅ Ņ†Đ¸Ņ… даĐŊĐ¸Ņ… С Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´ĐŊĐžŅ— Ņ‡Đ°ŅŅ‚Đ¸ĐŊи СаĐŋĐ¸Ņ‚Ņƒ, а ĐŊĐĩ С JSON. + +/// note | ĐĸĐĩŅ…ĐŊҖ҇ĐŊŅ– Đ´ĐĩŅ‚Đ°ĐģŅ– + +ДаĐŊŅ– С Ņ„ĐžŅ€Đŧ ĐˇĐ°ĐˇĐ˛Đ¸Ņ‡Đ°Đš ĐēĐžĐ´ŅƒŅŽŅ‚ŅŒŅŅ Са Đ´ĐžĐŋĐžĐŧĐžĐŗĐžŅŽ "media type" `application/x-www-form-urlencoded`, ŅĐēŅ‰Đž вОĐŊи ĐŊĐĩ ĐŧŅ–ŅŅ‚ŅŅ‚ŅŒ Ņ„Đ°ĐšĐģŅ–Đ˛. + +АĐģĐĩ ŅĐēŅ‰Đž Ņ„ĐžŅ€Đŧа ĐŧŅ–ŅŅ‚Đ¸Ņ‚ŅŒ Ņ„Đ°ĐšĐģи, вОĐŊа ĐēĐžĐ´ŅƒŅ”Ņ‚ŅŒŅŅ ҃ Ņ„ĐžŅ€ĐŧĐ°Ņ‚Ņ– `multipart/form-data`. Đ¯ĐēŅ‰Đž Ви виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅ”Ņ‚Đĩ `File`, **FastAPI** виСĐŊĐ°Ņ‡Đ¸Ņ‚ŅŒ, Ņ‰Đž ĐŋĐžŅ‚Ņ€Ņ–ĐąĐŊĐž ĐžŅ‚Ņ€Đ¸ĐŧĐ°Ņ‚Đ¸ Ņ„Đ°ĐšĐģи С Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´ĐŊĐžŅ— Ņ‡Đ°ŅŅ‚Đ¸ĐŊи ҂ҖĐģа СаĐŋĐ¸Ņ‚Ņƒ. + +ЊОй Đ´Ņ–ĐˇĐŊĐ°Ņ‚Đ¸ŅŅ ĐąŅ–ĐģҌ҈Đĩ ĐŋŅ€Đž ҆Җ Ņ‚Đ¸Đŋи ĐēĐžĐ´ŅƒĐ˛Đ°ĐŊĐŊŅ Ņ‚Đ° Ņ„ĐžŅ€ĐŧĐžĐ˛Ņ– ĐŋĐžĐģŅ, ОСĐŊаКОĐŧŅ‚ĐĩŅŅ С Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Ņ–Ņ”ŅŽ MDN Ņ‰ĐžĐ´Đž POST. + +/// + +/// warning | ĐŖĐ˛Đ°ĐŗĐ° + +Ви ĐŧĐžĐļĐĩŅ‚Đĩ ĐžĐŗĐžĐģĐžŅĐ¸Ņ‚Đ¸ ĐēŅ–ĐģҌĐēа ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Ņ–Đ˛ `File` Ņ– `Form` в *ĐžĐŋĐĩŅ€Đ°Ņ†Ņ–Ņ— ҈ĐģŅŅ…Ņƒ*, аĐģĐĩ Ви ĐŊĐĩ ĐŧĐžĐļĐĩŅ‚Đĩ ОдĐŊĐžŅ‡Đ°ŅĐŊĐž ĐžĐŗĐžĐģĐžŅˆŅƒĐ˛Đ°Ņ‚Đ¸ ĐŋĐžĐģŅ `Body`, ŅĐēŅ– ĐŧĐ°ŅŽŅ‚ŅŒ ĐŊĐ°Đ´Ņ…ĐžĐ´Đ¸Ņ‚Đ¸ ҃ Ņ„ĐžŅ€ĐŧĐ°Ņ‚Ņ– JSON, ĐžŅĐēŅ–ĐģҌĐēи ҂ҖĐģĐž СаĐŋĐ¸Ņ‚Ņƒ ĐąŅƒĐ´Đĩ СаĐēОдОваĐŊĐĩ ҃ Ņ„ĐžŅ€ĐŧĐ°Ņ‚Ņ– `multipart/form-data`, а ĐŊĐĩ `application/json`. + +ĐĻĐĩ ĐŊĐĩ ОйĐŧĐĩĐļĐĩĐŊĐŊŅ **FastAPI**, а ĐžŅĐžĐąĐģĐ¸Đ˛Ņ–ŅŅ‚ŅŒ ĐŋŅ€ĐžŅ‚ĐžĐēĐžĐģ҃ HTTP. + +/// + +## ОĐŋŅ†Ņ–ĐžĐŊаĐģҌĐŊĐĩ ЗаваĐŊŅ‚Đ°ĐļĐĩĐŊĐŊŅ ФаКĐģŅ–Đ˛ + +ФаКĐģ ĐŧĐžĐļĐŊа ĐˇŅ€ĐžĐąĐ¸Ņ‚Đ¸ ĐŊĐĩĐžĐąĐžĐ˛â€™ŅĐˇĐēОвиĐŧ, виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅŽŅ‡Đ¸ ŅŅ‚Đ°ĐŊĐ´Đ°Ņ€Ņ‚ĐŊŅ– аĐŊĐžŅ‚Đ°Ņ†Ņ–Ņ— Ņ‚Đ¸ĐŋŅ–Đ˛ Ņ– Đ˛ŅŅ‚Đ°ĐŊОвĐģŅŽŅŽŅ‡Đ¸ СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ Са СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ `None`: + +{* ../../docs_src/request_files/tutorial001_02_an_py310.py hl[9,17] *} + +## `UploadFile` Ņ–Đˇ Đ”ĐžĐ´Đ°Ņ‚ĐēОвиĐŧи МĐĩŅ‚Đ° ДаĐŊиĐŧи + +Ви Ņ‚Đ°ĐēĐžĐļ ĐŧĐžĐļĐĩŅ‚Đĩ виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ `File()` Ņ€Đ°ĐˇĐžĐŧ Ņ–Đˇ `UploadFile`, ĐŊаĐŋŅ€Đ¸ĐēĐģад, Đ´ĐģŅ Đ˛ŅŅ‚Đ°ĐŊОвĐģĐĩĐŊĐŊŅ Đ´ĐžĐ´Đ°Ņ‚ĐēĐžĐ˛Đ¸Ņ… ĐŧĐĩŅ‚Đ°Đ´Đ°ĐŊĐ¸Ņ…: + +{* ../../docs_src/request_files/tutorial001_03_an_py39.py hl[9,15] *} + +## ЗаваĐŊŅ‚Đ°ĐļĐĩĐŊĐŊŅ ĐšŅ–ĐģҌĐēĐžŅ… ФаКĐģŅ–Đ˛ + +МоĐļĐŊа СаваĐŊŅ‚Đ°ĐļŅƒĐ˛Đ°Ņ‚Đ¸ ĐēŅ–ĐģҌĐēа Ņ„Đ°ĐšĐģŅ–Đ˛ ОдĐŊĐžŅ‡Đ°ŅĐŊĐž. + +ВоĐŊи ĐąŅƒĐ´ŅƒŅ‚ŅŒ ĐŋĐžĐ˛â€™ŅĐˇĐ°ĐŊŅ– С ОдĐŊиĐŧ Ņ– Ņ‚Đ¸Đŧ ŅĐ°ĐŧиĐŧ "form field", ŅĐēиК ĐŋĐĩŅ€ĐĩĐ´Đ°Ņ”Ņ‚ŅŒŅŅ ҃ Đ˛Đ¸ĐŗĐģŅĐ´Ņ– "form data". + +ЊОй ҆Đĩ Ņ€ĐĩаĐģŅ–ĐˇŅƒĐ˛Đ°Ņ‚Đ¸, ĐŋĐžŅ‚Ņ€Ņ–ĐąĐŊĐž ĐžĐŗĐžĐģĐžŅĐ¸Ņ‚Đ¸ ҁĐŋĐ¸ŅĐžĐē `bytes` айО `UploadFile`: + +{* ../../docs_src/request_files/tutorial002_an_py39.py hl[10,15] *} + +Ви ĐžŅ‚Ņ€Đ¸ĐŧĐ°Ņ”Ņ‚Đĩ, ŅĐē Ņ– ĐąŅƒĐģĐž ĐžĐŗĐžĐģĐžŅˆĐĩĐŊĐž, `list` Ņ–Đˇ `bytes` айО `UploadFile`. + +/// note | ĐĸĐĩŅ…ĐŊҖ҇ĐŊŅ– Đ´ĐĩŅ‚Đ°ĐģŅ– + +Ви Ņ‚Đ°ĐēĐžĐļ ĐŧĐžĐļĐĩŅ‚Đĩ виĐēĐžŅ€Đ¸ŅŅ‚Đ°Ņ‚Đ¸ `from starlette.responses import HTMLResponse`. + +**FastAPI** ĐŊĐ°Đ´Đ°Ņ” ҂Җ Đļ ŅĐ°ĐŧŅ– `starlette.responses`, Ņ‰Đž Đš `fastapi.responses`, Đ´ĐģŅ ĐˇŅ€ŅƒŅ‡ĐŊĐžŅŅ‚Ņ– Ņ€ĐžĐˇŅ€ĐžĐąĐŊиĐēŅ–Đ˛. ОдĐŊаĐē ĐąŅ–ĐģŅŒŅˆŅ–ŅŅ‚ŅŒ Đ´ĐžŅŅ‚ŅƒĐŋĐŊĐ¸Ņ… Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´ĐĩĐš ĐŊĐ°Đ´Ņ…ĐžĐ´ŅŅ‚ŅŒ ĐąĐĩСĐŋĐžŅĐĩŅ€ĐĩĐ´ĐŊŅŒĐž Đ˛Ņ–Đ´ Starlette. + +/// + +### ЗаваĐŊŅ‚Đ°ĐļĐĩĐŊĐŊŅ Đ´ĐĩĐēŅ–ĐģҌĐēĐžŅ… Ņ„Đ°ĐšĐģŅ–Đ˛ Ņ–Đˇ Đ´ĐžĐ´Đ°Ņ‚ĐēОвиĐŧи ĐŧĐĩŅ‚Đ°Đ´Đ°ĐŊиĐŧи + +ĐĸаĐē ŅĐ°ĐŧĐž ŅĐē Ņ– Ņ€Đ°ĐŊŅ–ŅˆĐĩ, Ви ĐŧĐžĐļĐĩŅ‚Đĩ виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ `File()`, Ņ‰ĐžĐą Đ˛ŅŅ‚Đ°ĐŊĐžĐ˛Đ¸Ņ‚Đ¸ Đ´ĐžĐ´Đ°Ņ‚ĐēĐžĐ˛Ņ– ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ¸ ĐŊĐ°Đ˛Ņ–Ņ‚ŅŒ Đ´ĐģŅ `UploadFile`: + +{* ../../docs_src/request_files/tutorial003_an_py39.py hl[11,18:20] *} + +## ĐŸŅ–Đ´ŅŅƒĐŧĐžĐē + +ВиĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐšŅ‚Đĩ `File`, `bytes`Ņ‚Đ° `UploadFile`, Ņ‰ĐžĐą ĐžĐŗĐžĐģĐžŅˆŅƒĐ˛Đ°Ņ‚Đ¸ Ņ„Đ°ĐšĐģи Đ´ĐģŅ СаваĐŊŅ‚Đ°ĐļĐĩĐŊĐŊŅ ҃ СаĐŋĐ¸Ņ‚Đ°Ņ…, ŅĐēŅ– ĐŊĐ°Đ´ŅĐ¸ĐģĐ°ŅŽŅ‚ŅŒŅŅ ҃ Đ˛Đ¸ĐŗĐģŅĐ´Ņ– form data. diff --git a/docs/uk/docs/tutorial/request-form-models.md b/docs/uk/docs/tutorial/request-form-models.md new file mode 100644 index 000000000..7f5759e79 --- /dev/null +++ b/docs/uk/docs/tutorial/request-form-models.md @@ -0,0 +1,78 @@ +# МодĐĩĐģŅ– Ņ„ĐžŅ€Đŧ (Form Models) + +ĐŖ FastAPI Ви ĐŧĐžĐļĐĩŅ‚Đĩ виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ **Pydantic-ĐŧОдĐĩĐģŅ–** Đ´ĐģŅ ĐžĐŗĐžĐģĐžŅˆĐĩĐŊĐŊŅ **ĐŋĐžĐģŅ–Đ˛ Ņ„ĐžŅ€Đŧи**. + +/// info | ІĐŊŅ„ĐžŅ€ĐŧĐ°Ņ†Ņ–Ņ + +ЊОй виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ Ņ„ĐžŅ€Đŧи, ҁĐŋĐžŅ‡Đ°Ņ‚Đē҃ Đ˛ŅŅ‚Đ°ĐŊĐžĐ˛Ņ–Ņ‚ŅŒ python-multipart. + +ПĐĩŅ€ĐĩĐēĐžĐŊĐ°ĐšŅ‚ĐĩŅŅ, Ņ‰Đž Ви ŅŅ‚Đ˛ĐžŅ€Đ¸Đģи [Đ˛Ņ–Ņ€Ņ‚ŅƒĐ°ĐģҌĐŊĐĩ ҁĐĩŅ€ĐĩĐ´ĐžĐ˛Đ¸Ņ‰Đĩ](../virtual-environments.md){.internal-link target=_blank}, аĐēŅ‚Đ¸Đ˛ŅƒĐ˛Đ°Đģи ĐšĐžĐŗĐž, а ĐŋĐžŅ‚Ņ–Đŧ Đ˛ŅŅ‚Đ°ĐŊОвиĐģи ĐąŅ–ĐąĐģŅ–ĐžŅ‚ĐĩĐē҃, ĐŊаĐŋŅ€Đ¸ĐēĐģад: + +```console +$ pip install python-multipart +``` + +/// + +/// note | ĐŸŅ–Đ´ĐēаСĐēа + +ĐĻŅ Ņ„ŅƒĐŊĐēŅ†Ņ–Ņ ĐŋŅ–Đ´Ņ‚Ņ€Đ¸ĐŧŅƒŅ”Ņ‚ŅŒŅŅ, ĐŋĐžŅ‡Đ¸ĐŊĐ°ŅŽŅ‡Đ¸ С FastAPI вĐĩҀҁҖҗ `0.113.0`. 🤓 + +/// + +## ВиĐēĐžŅ€Đ¸ŅŅ‚Đ°ĐŊĐŊŅ Pydantic-ĐŧОдĐĩĐģĐĩĐš Đ´ĐģŅ Ņ„ĐžŅ€Đŧ + +ВаĐŧ ĐŋŅ€ĐžŅŅ‚Đž ĐŋĐžŅ‚Ņ€Ņ–ĐąĐŊĐž ĐžĐŗĐžĐģĐžŅĐ¸Ņ‚Đ¸ **Pydantic-ĐŧОдĐĩĐģҌ** С ĐŋĐžĐģŅĐŧи, ŅĐēŅ– Ви Ņ…ĐžŅ‡ĐĩŅ‚Đĩ ĐžŅ‚Ņ€Đ¸ĐŧĐ°Ņ‚Đ¸ ŅĐē **ĐŋĐžĐģŅ Ņ„ĐžŅ€Đŧи**, а ĐŋĐžŅ‚Ņ–Đŧ ĐžĐŗĐžĐģĐžŅĐ¸Ņ‚Đ¸ ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ ŅĐē `Form`: + +{* ../../docs_src/request_form_models/tutorial001_an_py39.py hl[9:11,15] *} + +**FastAPI** **Đ˛Đ¸Ņ‚ŅĐŗĐŊĐĩ** даĐŊŅ– Đ´ĐģŅ **ĐēĐžĐļĐŊĐžĐŗĐž ĐŋĐžĐģŅ** С **Ņ„ĐžŅ€ĐŧĐžĐ˛Đ¸Ņ… даĐŊĐ¸Ņ…** ҃ СаĐŋĐ¸Ņ‚Ņ– Ņ‚Đ° ĐŊĐ°Đ´Đ°ŅŅ‚ŅŒ ваĐŧ Pydantic-ĐŧОдĐĩĐģҌ, ŅĐē҃ Ви виСĐŊĐ°Ņ‡Đ¸Đģи. + +## ПĐĩŅ€ĐĩĐ˛Ņ–Ņ€Đēа Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Ņ–Ņ— + +Ви ĐŧĐžĐļĐĩŅ‚Đĩ ĐŋĐĩŅ€ĐĩĐ˛Ņ–Ņ€Đ¸Ņ‚Đ¸ ҆Đĩ в UI Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Ņ–Ņ— Са `/docs`: + +
+ +
+ +## Đ—Đ°ĐąĐžŅ€ĐžĐŊа Đ´ĐžĐ´Đ°Ņ‚ĐēĐžĐ˛Đ¸Ņ… ĐŋĐžĐģŅ–Đ˛ Ņ„ĐžŅ€Đŧи + +ĐŖ Đ´ĐĩŅĐēĐ¸Ņ… ĐžŅĐžĐąĐģĐ¸Đ˛Đ¸Ņ… виĐŋадĐēĐ°Ņ… (ĐšĐŧĐžĐ˛Ņ–Ņ€ĐŊĐž, Ņ€Ņ–Đ´ĐēĐž) Ви ĐŧĐžĐļĐĩŅ‚Đĩ **ОйĐŧĐĩĐļĐ¸Ņ‚Đ¸** Ņ„ĐžŅ€Đŧ҃ ĐģĐ¸ŅˆĐĩ Ņ‚Đ¸Đŧи ĐŋĐžĐģŅĐŧи, ŅĐēŅ– ĐąŅƒĐģи ĐžĐŗĐžĐģĐžŅˆĐĩĐŊŅ– в Pydantic-ĐŧОдĐĩĐģŅ–, Ņ– **ĐˇĐ°ĐąĐžŅ€ĐžĐŊĐ¸Ņ‚Đ¸** ĐąŅƒĐ´ŅŒ-ŅĐēŅ– **Đ´ĐžĐ´Đ°Ņ‚ĐēĐžĐ˛Ņ–** ĐŋĐžĐģŅ. + +/// note | ĐŸŅ–Đ´ĐēаСĐēа + +ĐĻŅ Ņ„ŅƒĐŊĐēŅ†Ņ–Ņ ĐŋŅ–Đ´Ņ‚Ņ€Đ¸ĐŧŅƒŅ”Ņ‚ŅŒŅŅ, ĐŋĐžŅ‡Đ¸ĐŊĐ°ŅŽŅ‡Đ¸ С FastAPI вĐĩҀҁҖҗ `0.114.0`. 🤓 + +/// + +Ви ĐŧĐžĐļĐĩŅ‚Đĩ виĐēĐžŅ€Đ¸ŅŅ‚Đ°Ņ‚Đ¸ ĐēĐžĐŊŅ„Ņ–ĐŗŅƒŅ€Đ°Ņ†Ņ–ŅŽ Pydantic-ĐŧОдĐĩĐģŅ–, Ņ‰ĐžĐą ĐˇĐ°ĐąĐžŅ€ĐžĐŊĐ¸Ņ‚Đ¸ `forbid` ĐąŅƒĐ´ŅŒ-ŅĐēŅ– Đ´ĐžĐ´Đ°Ņ‚ĐēĐžĐ˛Ņ– `extra` ĐŋĐžĐģŅ: + +{* ../../docs_src/request_form_models/tutorial002_an_py39.py hl[12] *} + +Đ¯ĐēŅ‰Đž ĐēĐģŅ–Ņ”ĐŊŅ‚ ҁĐŋŅ€ĐžĐąŅƒŅ” ĐŊĐ°Đ´Ņ–ŅĐģĐ°Ņ‚Đ¸ Đ´ĐžĐ´Đ°Ņ‚ĐēĐžĐ˛Ņ– даĐŊŅ–, Đ˛Ņ–ĐŊ ĐžŅ‚Ņ€Đ¸ĐŧĐ°Ņ” **Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´ŅŒ С ĐŋĐžĐŧиĐģĐēĐžŅŽ**. + +НаĐŋŅ€Đ¸ĐēĐģад, ŅĐēŅ‰Đž ĐēĐģŅ–Ņ”ĐŊŅ‚ ҁĐŋŅ€ĐžĐąŅƒŅ” ĐŊĐ°Đ´Ņ–ŅĐģĐ°Ņ‚Đ¸ ĐŊĐ°ŅŅ‚ŅƒĐŋĐŊŅ– ĐŋĐžĐģŅ Ņ„ĐžŅ€Đŧи: + +* `username`: `Rick` +* `password`: `Portal Gun` +* `extra`: `Mr. Poopybutthole` + +Đ’Ņ–ĐŊ ĐžŅ‚Ņ€Đ¸ĐŧĐ°Ņ” Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´ŅŒ Ņ–Đˇ ĐŋĐžĐŧиĐģĐēĐžŅŽ, ŅĐēа ĐŋĐžĐ˛Ņ–Đ´ĐžĐŧĐģŅŅ”, Ņ‰Đž ĐŋĐžĐģĐĩ `extra` ĐŊĐĩ дОСвОĐģĐĩĐŊĐž: + +```json +{ + "detail": [ + { + "type": "extra_forbidden", + "loc": ["body", "extra"], + "msg": "Extra inputs are not permitted", + "input": "Mr. Poopybutthole" + } + ] +} +``` + +## ĐŸŅ–Đ´ŅŅƒĐŧĐžĐē + +Ви ĐŧĐžĐļĐĩŅ‚Đĩ виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ Pydantic-ĐŧОдĐĩĐģŅ– Đ´ĐģŅ ĐžĐŗĐžĐģĐžŅˆĐĩĐŊĐŊŅ ĐŋĐžĐģŅ–Đ˛ Ņ„ĐžŅ€Đŧи ҃ FastAPI. 😎 diff --git a/docs/uk/docs/tutorial/request-forms-and-files.md b/docs/uk/docs/tutorial/request-forms-and-files.md new file mode 100644 index 000000000..a089ef945 --- /dev/null +++ b/docs/uk/docs/tutorial/request-forms-and-files.md @@ -0,0 +1,41 @@ +# ЗаĐŋĐ¸Ņ‚Đ¸ С Ņ„ĐžŅ€ĐŧаĐŧи Ņ‚Đ° Ņ„Đ°ĐšĐģаĐŧи + +ĐŖ FastAPI Ви ĐŧĐžĐļĐĩŅ‚Đĩ ОдĐŊĐžŅ‡Đ°ŅĐŊĐž ĐžŅ‚Ņ€Đ¸ĐŧŅƒĐ˛Đ°Ņ‚Đ¸ Ņ„Đ°ĐšĐģи Ņ‚Đ° ĐŋĐžĐģŅ Ņ„ĐžŅ€Đŧи, виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅŽŅ‡Đ¸ `File` Ņ– `Form`. + +/// info | ІĐŊŅ„ĐžŅ€ĐŧĐ°Ņ†Ņ–Ņ + +ЊОй ĐžŅ‚Ņ€Đ¸ĐŧŅƒĐ˛Đ°Ņ‚Đ¸ СаваĐŊŅ‚Đ°ĐļĐĩĐŊŅ– Ņ„Đ°ĐšĐģи Ņ‚Đ°/айО даĐŊŅ– Ņ„ĐžŅ€Đŧи, ҁĐŋĐžŅ‡Đ°Ņ‚Đē҃ Đ˛ŅŅ‚Đ°ĐŊĐžĐ˛Ņ–Ņ‚ŅŒ python-multipart. + +ПĐĩŅ€ĐĩĐēĐžĐŊĐ°ĐšŅ‚ĐĩŅŅ, Ņ‰Đž Ви ŅŅ‚Đ˛ĐžŅ€Đ¸Đģи [Đ˛Ņ–Ņ€Ņ‚ŅƒĐ°ĐģҌĐŊĐĩ ҁĐĩŅ€ĐĩĐ´ĐžĐ˛Đ¸Ņ‰Đĩ](../virtual-environments.md){.internal-link target=_blank}, аĐēŅ‚Đ¸Đ˛ŅƒĐ˛Đ°Đģи ĐšĐžĐŗĐž, а ĐŋĐžŅ‚Ņ–Đŧ Đ˛ŅŅ‚Đ°ĐŊОвиĐģи ĐąŅ–ĐąĐģŅ–ĐžŅ‚ĐĩĐē҃, ĐŊаĐŋŅ€Đ¸ĐēĐģад: + +```console +$ pip install python-multipart +``` + +/// + +## ІĐŧĐŋĐžŅ€Ņ‚ `File` Ņ‚Đ° `Form` + +{* ../../docs_src/request_forms_and_files/tutorial001_an_py39.py hl[3] *} + +## ĐžĐŗĐžĐģĐžŅˆĐĩĐŊĐŊŅ ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Ņ–Đ˛ `File` Ņ‚Đ° `Form` + +ĐĄŅ‚Đ˛ĐžŅ€Ņ–Ņ‚ŅŒ ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ¸ Ņ„Đ°ĐšĐģŅ–Đ˛ Ņ‚Đ° Ņ„ĐžŅ€Đŧи Ņ‚Đ°Đē ŅĐ°ĐŧĐž ŅĐē Ņ– Đ´ĐģŅ `Body` айО `Query`: + +{* ../../docs_src/request_forms_and_files/tutorial001_an_py39.py hl[10:12] *} + +ФаКĐģи Ņ‚Đ° ĐŋĐžĐģŅ Ņ„ĐžŅ€Đŧи ĐąŅƒĐ´ŅƒŅ‚ŅŒ СаваĐŊŅ‚Đ°ĐļĐĩĐŊŅ– ŅĐē Ņ„ĐžŅ€ĐŧĐžĐ˛Ņ– даĐŊŅ–, Ņ– Ви ĐžŅ‚Ņ€Đ¸ĐŧĐ°Ņ”Ņ‚Đĩ ŅĐē Ņ„Đ°ĐšĐģи, Ņ‚Đ°Đē Ņ– ввĐĩĐ´ĐĩĐŊŅ– ĐēĐžŅ€Đ¸ŅŅ‚ŅƒĐ˛Đ°Ņ‡ĐĩĐŧ ĐŋĐžĐģŅ. + +Ви Ņ‚Đ°ĐēĐžĐļ ĐŧĐžĐļĐĩŅ‚Đĩ ĐžĐŗĐžĐģĐžŅĐ¸Ņ‚Đ¸ Đ´ĐĩŅĐēŅ– Ņ„Đ°ĐšĐģи ŅĐē `bytes`, а Đ´ĐĩŅĐēŅ– ŅĐē `UploadFile`. + +/// warning | ĐŖĐ˛Đ°ĐŗĐ° + +Ви ĐŧĐžĐļĐĩŅ‚Đĩ ĐžĐŗĐžĐģĐžŅĐ¸Ņ‚Đ¸ ĐēŅ–ĐģҌĐēа ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Ņ–Đ˛ `File` Ņ– `Form` в ĐžĐŋĐĩŅ€Đ°Ņ†Ņ–Ņ— *҈ĐģŅŅ…Ņƒ*, аĐģĐĩ ĐŊĐĩ ĐŧĐžĐļĐĩŅ‚Đĩ ОдĐŊĐžŅ‡Đ°ŅĐŊĐž ĐžĐŗĐžĐģĐžŅˆŅƒĐ˛Đ°Ņ‚Đ¸ `Body`-ĐŋĐžĐģŅ, ŅĐēŅ– ĐžŅ‡Ņ–ĐēŅƒŅ”Ņ‚Đĩ ĐžŅ‚Ņ€Đ¸ĐŧĐ°Ņ‚Đ¸ ҃ Ņ„ĐžŅ€ĐŧĐ°Ņ‚Ņ– JSON, ĐžŅĐēŅ–ĐģҌĐēи СаĐŋĐ¸Ņ‚ ĐŧĐ°Ņ‚Đ¸ĐŧĐĩ ҂ҖĐģĐž, СаĐēОдОваĐŊĐĩ Са Đ´ĐžĐŋĐžĐŧĐžĐŗĐžŅŽ `multipart/form-data`, а ĐŊĐĩ `application/json`. + +ĐĻĐĩ ĐŊĐĩ ОйĐŧĐĩĐļĐĩĐŊĐŊŅ **FastAPI**, а Ņ‡Đ°ŅŅ‚Đ¸ĐŊа ĐŋŅ€ĐžŅ‚ĐžĐēĐžĐģ҃ HTTP. + +/// + +## ĐŸŅ–Đ´ŅŅƒĐŧĐžĐē + +ВиĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐšŅ‚Đĩ `File` Ņ‚Đ° `Form` Ņ€Đ°ĐˇĐžĐŧ, ĐēĐžĐģи ваĐŧ ĐŋĐžŅ‚Ņ€Ņ–ĐąĐŊĐž ĐžŅ‚Ņ€Đ¸ĐŧŅƒĐ˛Đ°Ņ‚Đ¸ даĐŊŅ– Ņ„ĐžŅ€Đŧи Ņ‚Đ° Ņ„Đ°ĐšĐģи в ОдĐŊĐžĐŧ҃ СаĐŋĐ¸Ņ‚Ņ–. diff --git a/docs/uk/docs/tutorial/request-forms.md b/docs/uk/docs/tutorial/request-forms.md new file mode 100644 index 000000000..10c58a73e --- /dev/null +++ b/docs/uk/docs/tutorial/request-forms.md @@ -0,0 +1,73 @@ +# ДаĐŊŅ– Ņ„ĐžŅ€Đŧи + +Đ¯ĐēŅ‰Đž ВаĐŧ ĐŋĐžŅ‚Ņ€Ņ–ĐąĐŊĐž ĐžŅ‚Ņ€Đ¸ĐŧŅƒĐ˛Đ°Ņ‚Đ¸ ĐŋĐžĐģŅ Ņ„ĐžŅ€Đŧи СаĐŧŅ–ŅŅ‚ŅŒ JSON, Ви ĐŧĐžĐļĐĩŅ‚Đĩ виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ `Form`. + +/// info | ІĐŊŅ„ĐžŅ€ĐŧĐ°Ņ†Ņ–Ņ + +ЊОй виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ Ņ„ĐžŅ€Đŧи, ҁĐŋĐžŅ‡Đ°Ņ‚Đē҃ Đ˛ŅŅ‚Đ°ĐŊĐžĐ˛Ņ–Ņ‚ŅŒ `python-multipart`. + +ПĐĩŅ€ĐĩĐēĐžĐŊĐ°ĐšŅ‚ĐĩŅŅ, Ņ‰Đž Ви ŅŅ‚Đ˛ĐžŅ€Đ¸Đģи [Đ˛Ņ–Ņ€Ņ‚ŅƒĐ°ĐģҌĐŊĐĩ ҁĐĩŅ€ĐĩĐ´ĐžĐ˛Đ¸Ņ‰Đĩ](../virtual-environments.md){.internal-link target=_blank}, аĐēŅ‚Đ¸Đ˛ŅƒĐ˛Đ°Đģи ĐšĐžĐŗĐž, Ņ– ĐŋĐžŅ‚Ņ–Đŧ Đ˛ŅŅ‚Đ°ĐŊОвиĐģи ĐąŅ–ĐąĐģŅ–ĐžŅ‚ĐĩĐē҃, ĐŊаĐŋŅ€Đ¸ĐēĐģад: + +```console +$ pip install python-multipart +``` + +/// + +## ІĐŧĐŋĐžŅ€Ņ‚ `Form` + +ІĐŧĐŋĐžŅ€Ņ‚ŅƒĐšŅ‚Đĩ `Form` С `fastapi`: + +{* ../../docs_src/request_forms/tutorial001_an_py39.py hl[3] *} + +## ĐžĐŗĐžĐģĐžŅˆĐĩĐŊĐŊŅ ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Ņ–Đ˛ `Form` + +ĐĄŅ‚Đ˛ĐžŅ€ŅŽĐšŅ‚Đĩ ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ¸ Ņ„ĐžŅ€Đŧи Ņ‚Đ°Đē ŅĐ°ĐŧĐž ŅĐē Ви Đą ŅŅ‚Đ˛ĐžŅ€ŅŽĐ˛Đ°Đģи `Body` айО `Query`: + +{* ../../docs_src/request_forms/tutorial001_an_py39.py hl[9] *} + +НаĐŋŅ€Đ¸ĐēĐģад, ОдиĐŊ ĐˇŅ– ҁĐŋĐžŅĐžĐąŅ–Đ˛ виĐēĐžŅ€Đ¸ŅŅ‚Đ°ĐŊĐŊŅ ҁĐŋĐĩŅ†Đ¸Ņ„Ņ–ĐēĐ°Ņ†Ņ–Ņ— OAuth2 (Ņ‚Đ°Đē СваĐŊиК "password flow") виĐŧĐ°ĐŗĐ°Ņ” ĐŊĐ°Đ´ŅĐ¸ĐģĐ°Ņ‚Đ¸ `username` Ņ‚Đ° `password` ŅĐē ĐŋĐžĐģŅ Ņ„ĐžŅ€Đŧи. + +spec виĐŧĐ°ĐŗĐ°Ņ”, Ņ‰ĐžĐą ҆Җ ĐŋĐžĐģŅ ĐŧаĐģи Ņ‚ĐžŅ‡ĐŊŅ– ĐŊаСви `username` Ņ– `password` Ņ‚Đ° ĐŊĐ°Đ´ŅĐ¸ĐģаĐģĐ¸ŅŅ ҃ Đ˛Đ¸ĐŗĐģŅĐ´Ņ– ĐŋĐžĐģŅ–Đ˛ Ņ„ĐžŅ€Đŧи, а ĐŊĐĩ JSON. + +З `Form` Ви ĐŧĐžĐļĐĩŅ‚Đĩ ĐžĐŗĐžĐģĐžŅˆŅƒĐ˛Đ°Ņ‚Đ¸ ҂Җ Đļ ĐēĐžĐŊŅ„Ņ–ĐŗŅƒŅ€Đ°Ņ†Ņ–Ņ—, Ņ‰Đž Ņ– С `Body` (Ņ‚Đ° `Query`, `Path`, `Cookie`), вĐēĐģŅŽŅ‡Đ°ŅŽŅ‡Đ¸ ваĐģŅ–Đ´Đ°Ņ†Ņ–ŅŽ, ĐŋŅ€Đ¸ĐēĐģади, ĐŋҁĐĩвдОĐŊŅ–Đŧи (ĐŊаĐŋŅ€Đ¸ĐēĐģад, `user-name` СаĐŧŅ–ŅŅ‚ŅŒ `username`) Ņ‚ĐžŅ‰Đž. + +/// info | ІĐŊŅ„ĐžŅ€ĐŧĐ°Ņ†Ņ–Ņ + +`Form` — ҆Đĩ ĐēĐģĐ°Ņ, ŅĐēиК ĐąĐĩСĐŋĐžŅĐĩŅ€ĐĩĐ´ĐŊŅŒĐž ĐŊĐ°ŅĐģŅ–Đ´ŅƒŅ”Ņ‚ŅŒŅŅ Đ˛Ņ–Đ´ `Body`. + +/// + +/// tip | ĐŸĐžŅ€Đ°Đ´Đ° + +ЊОй ĐžĐŗĐžĐģĐžŅĐ¸Ņ‚Đ¸ ҂ҖĐģĐž Ņ„ĐžŅ€Đŧи, ĐŋĐžŅ‚Ņ€Ņ–ĐąĐŊĐž ŅĐ˛ĐŊĐž виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ `Form`, ĐžŅĐēŅ–ĐģҌĐēи ĐąĐĩС ĐŊŅŒĐžĐŗĐž ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ¸ ĐąŅƒĐ´ŅƒŅ‚ŅŒ Ņ–ĐŊŅ‚ĐĩŅ€ĐŋŅ€ĐĩŅ‚ŅƒĐ˛Đ°Ņ‚Đ¸ŅŅ ŅĐē ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ¸ СаĐŋĐ¸Ņ‚Ņƒ айО ҂ҖĐģа (JSON). + +/// + +## ĐŸŅ€Đž "ĐŋĐžĐģŅ Ņ„ĐžŅ€Đŧи" + +HTML-Ņ„ĐžŅ€Đŧи (`
`) ĐŊĐ°Đ´ŅĐ¸ĐģĐ°ŅŽŅ‚ŅŒ даĐŊŅ– ĐŊа ҁĐĩŅ€Đ˛ĐĩŅ€ ҃ "ҁĐŋĐĩŅ†Ņ–Đ°ĐģҌĐŊĐžĐŧ҃" ĐēĐžĐ´ŅƒĐ˛Đ°ĐŊĐŊŅ–, ŅĐēĐĩ Đ˛Ņ–Đ´Ņ€Ņ–ĐˇĐŊŅŅ”Ņ‚ŅŒŅŅ Đ˛Ņ–Đ´ JSON. + +**FastAPI** ĐŋĐžĐ´ĐąĐ°Ņ” ĐŋŅ€Đž Ņ‚Đĩ, Ņ‰ĐžĐą ĐˇŅ‡Đ¸Ņ‚Đ°Ņ‚Đ¸ ҆Җ даĐŊŅ– С ĐŋŅ€Đ°Đ˛Đ¸ĐģҌĐŊĐžĐŗĐž ĐŧŅ–ŅŅ†Ņ, а ĐŊĐĩ С JSON. + +/// note | ĐĸĐĩŅ…ĐŊҖ҇ĐŊŅ– Đ´ĐĩŅ‚Đ°ĐģŅ– + +ДаĐŊŅ– С Ņ„ĐžŅ€Đŧ ĐˇĐ°ĐˇĐ˛Đ¸Ņ‡Đ°Đš ĐēĐžĐ´ŅƒŅŽŅ‚ŅŒŅŅ Са Đ´ĐžĐŋĐžĐŧĐžĐŗĐžŅŽ "Ņ‚Đ¸Đŋ҃ ĐŧĐĩĐ´Ņ–Đ°" `application/x-www-form-urlencoded`. + +АĐģĐĩ ŅĐēŅ‰Đž Ņ„ĐžŅ€Đŧа ĐŧŅ–ŅŅ‚Đ¸Ņ‚ŅŒ Ņ„Đ°ĐšĐģи, вОĐŊа ĐēĐžĐ´ŅƒŅ”Ņ‚ŅŒŅŅ ŅĐē `multipart/form-data`. Ви Đ´Ņ–ĐˇĐŊĐ°Ņ”Ņ‚ĐĩŅŅ ĐŋŅ€Đž ĐžĐąŅ€ĐžĐąĐē҃ Ņ„Đ°ĐšĐģŅ–Đ˛ ҃ ĐŊĐ°ŅŅ‚ŅƒĐŋĐŊĐžĐŧ҃ Ņ€ĐžĐˇĐ´Ņ–ĐģŅ–. + +Đ¯ĐēŅ‰Đž Ви Ņ…ĐžŅ‡ĐĩŅ‚Đĩ Đ´Ņ–ĐˇĐŊĐ°Ņ‚Đ¸ŅŅ ĐąŅ–ĐģҌ҈Đĩ ĐŋŅ€Đž ҆Җ ĐēĐžĐ´ŅƒĐ˛Đ°ĐŊĐŊŅ Ņ‚Đ° ĐŋĐžĐģŅ Ņ„ĐžŅ€Đŧ, СвĐĩŅ€ĐŊŅ–Ņ‚ŅŒŅŅ Đ´Đž MDN вĐĩйдОĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Ņ–Ņ— Đ´ĐģŅ POST. + +/// + +/// warning | ПоĐŋĐĩŅ€ĐĩĐ´ĐļĐĩĐŊĐŊŅ + +Ви ĐŧĐžĐļĐĩŅ‚Đĩ ĐžĐŗĐžĐģĐžŅĐ¸Ņ‚Đ¸ ĐēŅ–ĐģҌĐēа ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Ņ–Đ˛ `Form` в *ĐžĐŋĐĩŅ€Đ°Ņ†Ņ–Ņ— ҈ĐģŅŅ…Ņƒ*, аĐģĐĩ ĐŊĐĩ ĐŧĐžĐļĐĩŅ‚Đĩ ОдĐŊĐžŅ‡Đ°ŅĐŊĐž ĐžĐŗĐžĐģĐžŅĐ¸Ņ‚Đ¸ ĐŋĐžĐģŅ `Body`, ŅĐēŅ– Ви ĐžŅ‡Ņ–ĐēŅƒŅ”Ņ‚Đĩ ĐžŅ‚Ņ€Đ¸ĐŧĐ°Ņ‚Đ¸ ҃ Ņ„ĐžŅ€ĐŧĐ°Ņ‚Ņ– JSON, ĐžŅĐēŅ–ĐģҌĐēи ҂ҖĐģĐž СаĐŋĐ¸Ņ‚Ņƒ ĐąŅƒĐ´Đĩ СаĐēОдОваĐŊĐž ҃ Ņ„ĐžŅ€ĐŧĐ°Ņ‚Ņ– `application/x-www-form-urlencoded`, а ĐŊĐĩ `application/json`. + +ĐĻĐĩ ĐŊĐĩ ОйĐŧĐĩĐļĐĩĐŊĐŊŅ **FastAPI**, а Ņ‡Đ°ŅŅ‚Đ¸ĐŊа HTTP-ĐŋŅ€ĐžŅ‚ĐžĐēĐžĐģ҃. + +/// + +## ĐŸŅ–Đ´ŅŅƒĐŧĐžĐē + +ВиĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐšŅ‚Đĩ `Form` Đ´ĐģŅ ĐžĐŗĐžĐģĐžŅˆĐĩĐŊĐŊŅ Đ˛Ņ…Ņ–Đ´ĐŊĐ¸Ņ… ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Ņ–Đ˛ ҃ Đ˛Đ¸ĐŗĐģŅĐ´Ņ– даĐŊĐ¸Ņ… Ņ„ĐžŅ€Đŧи. diff --git a/docs/uk/docs/tutorial/response-model.md b/docs/uk/docs/tutorial/response-model.md new file mode 100644 index 000000000..def1f8a2d --- /dev/null +++ b/docs/uk/docs/tutorial/response-model.md @@ -0,0 +1,358 @@ +# МодĐĩĐģҌ Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´Ņ– — ĐĸиĐŋ, Ņ‰Đž ĐŋОвĐĩŅ€Ņ‚Đ°Ņ”Ņ‚ŅŒŅŅ + +Ви ĐŧĐžĐļĐĩŅ‚Đĩ ĐžĐŗĐžĐģĐžŅĐ¸Ņ‚Đ¸ Ņ‚Đ¸Đŋ, ŅĐēиК виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ĐŧĐĩŅ‚ŅŒŅŅ ҃ Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´Ņ–, Са Đ´ĐžĐŋĐžĐŧĐžĐŗĐžŅŽ *аĐŊĐžŅ‚Đ°Ņ†Ņ–Ņ— Ņ‚Đ¸Đŋ҃, Ņ‰Đž ĐŋОвĐĩŅ€Ņ‚Đ°Ņ”Ņ‚ŅŒŅŅ* *Ņ„ŅƒĐŊĐēŅ†Ņ–Ņ”ŅŽ ĐžĐŋĐĩŅ€Đ°Ņ†Ņ–Ņ”ŅŽ ҈ĐģŅŅ…Ņƒ* (path operation) + +**АĐŊĐžŅ‚Đ°Ņ†Ņ–ŅŽ Ņ‚Đ¸Đŋ҃** ĐŧĐžĐļĐŊа вĐēĐ°ĐˇĐ°Ņ‚Đ¸ Ņ‚Đ°Đē ŅĐ°ĐŧĐž ŅĐē Ņ– Đ´ĐģŅ Đ˛Ņ…Ņ–Đ´ĐŊĐ¸Ņ… **ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Ņ–Đ˛** Ņ„ŅƒĐŊĐē҆Җҗ: ҆Đĩ ĐŧĐžĐļŅƒŅ‚ŅŒ ĐąŅƒŅ‚Đ¸ ĐŧОдĐĩĐģŅ– Pydantic, ҁĐŋĐ¸ŅĐēи (lists), ҁĐģОвĐŊиĐēи (dictionaries), ҁĐēаĐģŅŅ€ĐŊŅ– СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ, ŅĐē-ĐžŅ‚ ҆ҖĐģŅ– Ņ‡Đ¸ŅĐģа (integers), ĐąŅƒĐģĐĩĐ˛Ņ– СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ (booleans) Ņ‚ĐžŅ‰Đž. + +{* ../../docs_src/response_model/tutorial001_01_py310.py hl[16,21] *} + +FastAPI виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ĐŧĐĩ ҆ĐĩĐš Ņ‚Đ¸Đŋ, Ņ‰ĐžĐą: + +* **ПĐĩŅ€ĐĩĐ˛Ņ–Ņ€Đ¸Ņ‚Đ¸ ĐŋŅ€Đ°Đ˛Đ¸ĐģҌĐŊŅ–ŅŅ‚ŅŒ** ĐŋОвĐĩŅ€ĐŊĐĩĐŊĐ¸Ņ… даĐŊĐ¸Ņ…. + * Đ¯ĐēŅ‰Đž даĐŊŅ– ĐŊĐĩ ваĐģŅ–Đ´ĐŊŅ– (ĐŊаĐŋŅ€Đ¸ĐēĐģад, Đ˛Ņ–Đ´ŅŅƒŅ‚ĐŊŅ” ĐŋĐžĐģĐĩ), ҆Đĩ ОСĐŊĐ°Ņ‡Đ°Ņ”, Ņ‰Đž Đ’Đ°Ņˆ ĐēОд Đ´ĐžĐ´Đ°Ņ‚Đē҃ ĐŋŅ€Đ°Ņ†ŅŽŅ” ĐŊĐĩĐēĐžŅ€ĐĩĐēŅ‚ĐŊĐž Ņ– ĐŊĐĩ ĐŋОвĐĩŅ€Ņ‚Đ°Ņ” Ņ‚Đĩ, Ņ‰Đž ĐŋОвиĐŊĐĩĐŊ. ĐŖ Ņ‚Đ°ĐēĐžĐŧ҃ виĐŋадĐē҃ FastAPI ĐŋОвĐĩŅ€ĐŊĐĩ ĐŋĐžĐŧиĐģĐē҃ ҁĐĩŅ€Đ˛ĐĩŅ€Đ°, СаĐŧŅ–ŅŅ‚ŅŒ Ņ‚ĐžĐŗĐž Ņ‰ĐžĐą Đ˛Ņ–Đ´Đ´Đ°Ņ‚Đ¸ ĐŊĐĩĐ´ĐžĐŋŅƒŅŅ‚Đ¸ĐŧŅ– даĐŊŅ–. ĐĸаĐē Ви Ņ‚Đ° Đ’Đ°ŅˆŅ– ĐēĐģŅ–Ņ”ĐŊŅ‚Đ¸ ĐąŅƒĐ´ĐĩŅ‚Đĩ вĐŋĐĩвĐŊĐĩĐŊŅ–, Ņ‰Đž ĐžŅ‚Ņ€Đ¸ĐŧŅƒŅ”Ņ‚Đĩ ĐžŅ‡Ņ–ĐēŅƒĐ˛Đ°ĐŊŅ– даĐŊŅ– ҃ ĐŋŅ€Đ°Đ˛Đ¸ĐģҌĐŊĐžĐŧ҃ Ņ„ĐžŅ€ĐŧĐ°Ņ‚Ņ–. + +* Đ”ĐžĐ´Đ°Ņ‚Đ¸ **JSON Schema** Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´Ņ– Đ´Đž ҁĐŋĐĩŅ†Đ¸Ņ„Ņ–ĐēĐ°Ņ†Ņ–Ņ— OpenAPI в *ĐžĐŋĐĩŅ€Đ°Ņ†Ņ–ŅŅ… ҈ĐģŅŅ…Ņƒ*. + * ĐĻĐĩ ĐąŅƒĐ´Đĩ виĐēĐžŅ€Đ¸ŅŅ‚Đ°ĐŊĐž в **Đ°Đ˛Ņ‚ĐžĐŧĐ°Ņ‚Đ¸Ņ‡ĐŊŅ–Đš Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Ņ–Ņ—**. + * А Ņ‚Đ°ĐēĐžĐļ Ņ–ĐŊŅŅ‚Ņ€ŅƒĐŧĐĩĐŊŅ‚Đ°Đŧи, ŅĐēŅ– Đ°Đ˛Ņ‚ĐžĐŧĐ°Ņ‚Đ¸Ņ‡ĐŊĐž ĐŗĐĩĐŊĐĩŅ€ŅƒŅŽŅ‚ŅŒ ĐēĐģŅ–Ņ”ĐŊŅ‚ŅŅŒĐēиК ĐēОд. + +АĐģĐĩ ĐŊĐ°ĐšĐŗĐžĐģОвĐŊŅ–ŅˆĐĩ: + +* FastAPI **ОйĐŧĐĩĐļĐ¸Ņ‚ŅŒ Ņ‚Đ° Đ˛Ņ–Đ´Ņ„Ņ–ĐģŅŒŅ‚Ņ€ŅƒŅ”** Đ˛Đ¸Ņ…Ņ–Đ´ĐŊŅ– даĐŊŅ– Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´ĐŊĐž Đ´Đž Ņ‚Đ¸Đŋ҃, вĐēаСаĐŊĐžĐŗĐž ҃ Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´Ņ–. + * ĐĻĐĩ ĐžŅĐžĐąĐģивО ваĐļĐģивО Đ´ĐģŅ **ĐąĐĩСĐŋĐĩĐēи**. ДĐĩŅ‚Đ°ĐģŅ– ĐŊиĐļ҇Đĩ. + +## ĐŸĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ `response_model` + +ІĐŊĐžĐ´Ņ– ВаĐŧ ĐŋĐžŅ‚Ņ€Ņ–ĐąĐŊĐž айО ĐˇŅ€ŅƒŅ‡ĐŊĐž ĐŋОвĐĩŅ€Ņ‚Đ°Ņ‚Đ¸ Ņ–ĐŊŅˆŅ– Ņ‚Đ¸Đŋи даĐŊĐ¸Ņ…, ĐŊŅ–Đļ ҂Җ, Ņ‰Đž СаСĐŊĐ°Ņ‡ĐĩĐŊŅ– ŅĐē Ņ‚Đ¸Đŋ Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´Ņ–. + +НаĐŋŅ€Đ¸ĐēĐģад, Ви ĐŧĐžĐļĐĩŅ‚Đĩ **ĐŋОвĐĩŅ€Ņ‚Đ°Ņ‚Đ¸ ҁĐģОвĐŊиĐē** айО ĐžĐąâ€™Ņ”ĐēŅ‚ йаСи даĐŊĐ¸Ņ…, аĐģĐĩ **ĐžĐŗĐžĐģĐžŅĐ¸Ņ‚Đ¸ ĐŧОдĐĩĐģҌ Pydantic** ŅĐē ĐŧОдĐĩĐģҌ Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´Ņ–. ĐĸĐžĐ´Ņ– ĐŧОдĐĩĐģҌ Pydantic Đ°Đ˛Ņ‚ĐžĐŧĐ°Ņ‚Đ¸Ņ‡ĐŊĐž ĐžĐąŅ€ĐžĐąĐģŅŅ‚Đ¸ĐŧĐĩ ваĐģŅ–Đ´Đ°Ņ†Ņ–ŅŽ, Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Ņ–ŅŽ Ņ‚ĐžŅ‰Đž. + +Đ¯ĐēŅ‰Đž Ви Đ´ĐžĐ´Đ°ŅŅ‚Đĩ аĐŊĐžŅ‚Đ°Ņ†Ņ–ŅŽ Ņ‚Đ¸Đŋ҃ Đ´ĐģŅ ĐŋОвĐĩŅ€ĐŊĐĩĐŊĐŊŅ, Ņ€ĐĩдаĐēŅ‚ĐžŅ€ ĐēĐžĐ´Ņƒ айО mypy ĐŧĐžĐļŅƒŅ‚ŅŒ ĐŋĐžŅĐēĐ°Ņ€ĐļĐ¸Ņ‚Đ¸ŅŅ, Ņ‰Đž Ņ„ŅƒĐŊĐēŅ†Ņ–Ņ ĐŋОвĐĩŅ€Ņ‚Đ°Ņ” Ņ–ĐŊŅˆĐ¸Đš Ņ‚Đ¸Đŋ (ĐŊаĐŋŅ€Đ¸ĐēĐģад, dict СаĐŧŅ–ŅŅ‚ŅŒ Item). + +ĐŖ Ņ‚Đ°ĐēĐ¸Ņ… виĐŋадĐēĐ°Ņ… ĐŧĐžĐļĐŊа ҁĐēĐžŅ€Đ¸ŅŅ‚Đ°Ņ‚Đ¸ŅŅ ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€ĐžĐŧ `response_model` в Đ´ĐĩĐēĐžŅ€Đ°Ņ‚ĐžŅ€Ņ– ĐŧĐ°Ņ€ŅˆŅ€ŅƒŅ‚Ņƒ (ĐŊаĐŋŅ€Đ¸ĐēĐģад, @app.get()). + +ĐŸĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ `response_model` ĐŋŅ€Đ°Ņ†ŅŽŅ” С ĐąŅƒĐ´ŅŒ-ŅĐēиĐŧ *ĐžĐŋĐĩŅ€Đ°Ņ‚ĐžŅ€ĐžĐŧ ҈ĐģŅŅ…Ņƒ*: + +* `@app.get()` +* `@app.post()` +* `@app.put()` +* `@app.delete()` +* Ņ‚ĐžŅ‰Đž. + +{* ../../docs_src/response_model/tutorial001_py310.py hl[17,22,24:27] *} + +/// note | ĐŸŅ€Đ¸ĐŧŅ–Ņ‚Đēа + +ЗвĐĩŅ€ĐŊŅ–Ņ‚ŅŒ ŅƒĐ˛Đ°ĐŗŅƒ, Ņ‰Đž `response_model` Ņ” ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€ĐžĐŧ ĐŧĐĩŅ‚ĐžĐ´Ņƒ-Đ´ĐĩĐēĐžŅ€Đ°Ņ‚ĐžŅ€Đ° (`get`, `post`, Ņ‚ĐžŅ‰Đž), а ĐŊĐĩ *Ņ„ŅƒĐŊĐēŅ†Ņ–Ņ”ŅŽ ĐžĐŋĐĩŅ€Đ°Ņ†Ņ–Ņ”ŅŽ ҈ĐģŅŅ…Ņƒ* (path operation function), ŅĐē ҆Đĩ Ņ€ĐžĐąĐ¸Ņ‚ŅŒŅŅ С ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ°Đŧи айО ҂ҖĐģĐžĐŧ СаĐŋĐ¸Ņ‚Ņƒ. + +/// + +`response_model` ĐŋŅ€Đ¸ĐšĐŧĐ°Ņ” Ņ‚Đ°ĐēиК ŅĐ°ĐŧиК Ņ‚Đ¸Đŋ, ŅĐēиК Ви Đą вĐēаСаĐģи Đ´ĐģŅ ĐŋĐžĐģŅ ĐŧОдĐĩĐģŅ– Pydantic. ĐĸĐžĐąŅ‚Đž ҆Đĩ ĐŧĐžĐļĐĩ ĐąŅƒŅ‚Đ¸ ŅĐē Pydantic-ĐŧОдĐĩĐģҌ, Ņ‚Đ°Đē Ņ–, ĐŊаĐŋŅ€Đ¸ĐēĐģад, `list` Ņ–Đˇ ĐŧОдĐĩĐģĐĩĐš Pydantic — `List[Item]`. + +FastAPI виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ĐŧĐĩ `response_model` Đ´ĐģŅ ŅŅ‚Đ˛ĐžŅ€ĐĩĐŊĐŊŅ Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Ņ–Ņ—, ваĐģŅ–Đ´Đ°Ņ†Ņ–Ņ— даĐŊĐ¸Ņ… Ņ‚Đ° — ĐŊаКваĐļĐģĐ¸Đ˛Ņ–ŅˆĐĩ — **ĐŋĐĩŅ€ĐĩŅ‚Đ˛ĐžŅ€ĐĩĐŊĐŊŅ Ņ‚Đ° ҄ҖĐģŅŒŅ‚Ņ€Đ°Ņ†Ņ–Ņ— Đ˛Đ¸Ņ…Ņ–Đ´ĐŊĐ¸Ņ… даĐŊĐ¸Ņ…** ĐˇĐŗŅ–Đ´ĐŊĐž С ĐžĐŗĐžĐģĐžŅˆĐĩĐŊиĐŧ Ņ‚Đ¸ĐŋĐžĐŧ. + +/// tip | ĐŸĐžŅ€Đ°Đ´Đ° + +Đ¯ĐēŅ‰Đž ҃ Đ’Đ°Ņ ŅƒĐ˛Ņ–ĐŧĐēĐŊĐĩĐŊĐž ŅŅƒĐ˛ĐžŅ€Ņƒ ĐŋĐĩŅ€ĐĩĐ˛Ņ–Ņ€Đē҃ Ņ‚Đ¸ĐŋŅ–Đ˛ ҃ Ņ€ĐĩдаĐēŅ‚ĐžŅ€Ņ–, mypy Ņ‚ĐžŅ‰Đž, Ви ĐŧĐžĐļĐĩŅ‚Đĩ ĐžĐŗĐžĐģĐžŅĐ¸Ņ‚Đ¸ Ņ‚Đ¸Đŋ ĐŋОвĐĩŅ€ĐŊĐĩĐŊĐŊŅ Ņ„ŅƒĐŊĐē҆Җҗ ŅĐē `Any`. + +ĐĸаĐēиĐŧ Ņ‡Đ¸ĐŊĐžĐŧ, Ви ĐŋĐžĐ˛Ņ–Đ´ĐžĐŧĐģŅŅ”Ņ‚Đĩ Ņ€ĐĩдаĐēŅ‚ĐžŅ€Ņƒ, Ņ‰Đž ŅĐ˛Ņ–Đ´ĐžĐŧĐž ĐŋОвĐĩŅ€Ņ‚Đ°Ņ”Ņ‚Đĩ ĐąŅƒĐ´ŅŒ-Ņ‰Đž. АĐģĐĩ FastAPI ҃ҁĐĩ ОдĐŊĐž виĐēĐžĐŊŅƒĐ˛Đ°Ņ‚Đ¸ĐŧĐĩ ŅŅ‚Đ˛ĐžŅ€ĐĩĐŊĐŊŅ Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Ņ–Ņ—, ваĐģŅ–Đ´Đ°Ņ†Ņ–ŅŽ, ҄ҖĐģŅŒŅ‚Ņ€Đ°Ņ†Ņ–ŅŽ Ņ‚ĐžŅ‰Đž Са Đ´ĐžĐŋĐžĐŧĐžĐŗĐžŅŽ ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ° `response_model`. + +/// + +### ĐŸŅ€Ņ–ĐžŅ€Đ¸Ņ‚ĐĩŅ‚ `response_model` + +Đ¯ĐēŅ‰Đž Ви вĐēĐ°ĐˇŅƒŅ”Ņ‚Đĩ Ņ– Ņ‚Đ¸Đŋ ĐŋОвĐĩŅ€ĐŊĐĩĐŊĐŊŅ, Ņ– `response_model`, Ņ‚Đž FastAPI виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ĐŧĐĩ `response_model` С ĐŋŅ€Ņ–ĐžŅ€Đ¸Ņ‚ĐĩŅ‚ĐžĐŧ. + +ĐĸаĐēиĐŧ Ņ‡Đ¸ĐŊĐžĐŧ, Ви ĐŧĐžĐļĐĩŅ‚Đĩ Đ´ĐžĐ´Đ°Ņ‚Đ¸ ĐŋŅ€Đ°Đ˛Đ¸ĐģҌĐŊŅ– аĐŊĐžŅ‚Đ°Ņ†Ņ–Ņ— Ņ‚Đ¸ĐŋŅ–Đ˛ Đ´Đž Đ˛Đ°ŅˆĐ¸Ņ… Ņ„ŅƒĐŊĐēŅ†Ņ–Đš, ĐŊĐ°Đ˛Ņ–Ņ‚ŅŒ ŅĐēŅ‰Đž вОĐŊи ĐŋОвĐĩŅ€Ņ‚Đ°ŅŽŅ‚ŅŒ Ņ‚Đ¸Đŋ, Đ˛Ņ–Đ´ĐŧŅ–ĐŊĐŊиК Đ˛Ņ–Đ´ `response_model`. ĐĻĐĩ ĐąŅƒĐ´Đĩ ĐēĐžŅ€Đ¸ŅĐŊĐž Đ´ĐģŅ Ņ€ĐĩдаĐēŅ‚ĐžŅ€Ņ–Đ˛ ĐēĐžĐ´Ņƒ Ņ‚Đ° Ņ–ĐŊŅŅ‚Ņ€ŅƒĐŧĐĩĐŊŅ‚Ņ–Đ˛, Ņ‚Đ°ĐēĐ¸Ņ… ŅĐē mypy. І ĐŋŅ€Đ¸ Ņ†ŅŒĐžĐŧ҃ FastAPI ĐŋŅ€ĐžĐ´ĐžĐ˛ĐļĐ¸Ņ‚ŅŒ виĐēĐžĐŊŅƒĐ˛Đ°Ņ‚Đ¸ ваĐģŅ–Đ´Đ°Ņ†Ņ–ŅŽ даĐŊĐ¸Ņ…, ĐŗĐĩĐŊĐĩŅ€ŅƒĐ˛Đ°Ņ‚Đ¸ Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Ņ–ŅŽ Ņ‚ĐžŅ‰Đž ĐŊа ĐžŅĐŊĐžĐ˛Ņ– `response_model`. + +Ви Ņ‚Đ°ĐēĐžĐļ ĐŧĐžĐļĐĩŅ‚Đĩ виĐēĐžŅ€Đ¸ŅŅ‚Đ°Ņ‚Đ¸ `response_model=None`, Ņ‰ĐžĐą виĐŧĐēĐŊŅƒŅ‚Đ¸ ŅŅ‚Đ˛ĐžŅ€ĐĩĐŊĐŊŅ ĐŧОдĐĩĐģŅ– Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´Ņ– Đ´ĐģŅ ҆ҖҔҗ *ĐžĐŋĐĩŅ€Đ°Ņ†Ņ–Ņ— ҈ĐģŅŅ…Ņƒ*. ĐĻĐĩ ĐŧĐžĐļĐĩ СĐŊĐ°Đ´ĐžĐąĐ¸Ņ‚Đ¸ŅŅ, ŅĐēŅ‰Đž Ви Đ´ĐžĐ´Đ°Ņ”Ņ‚Đĩ аĐŊĐžŅ‚Đ°Ņ†Ņ–Ņ— Ņ‚Đ¸ĐŋŅ–Đ˛ Đ´Đž Ой'Ņ”ĐēŅ‚Ņ–Đ˛, ŅĐēŅ– ĐŊĐĩ Ņ” Đ´ĐžĐŋŅƒŅŅ‚Đ¸ĐŧиĐŧи ĐŋĐžĐģŅĐŧи Pydantic — ĐŋŅ€Đ¸ĐēĐģад Ņ†ŅŒĐžĐŗĐž Ви ĐŋĐžĐąĐ°Ņ‡Đ¸Ņ‚Đĩ в ОдĐŊĐžĐŧ҃ С ĐŊĐ°ŅŅ‚ŅƒĐŋĐŊĐ¸Ņ… Ņ€ĐžĐˇĐ´Ņ–ĐģŅ–Đ˛. + +## ПовĐĩŅ€ĐŊŅƒŅ‚Đ¸ ҂Җ ŅĐ°ĐŧŅ– Đ˛Ņ…Ņ–Đ´ĐŊŅ– даĐŊŅ– + +ĐĸŅƒŅ‚ Đŧи ĐžĐŗĐžĐģĐžŅˆŅƒŅ”ĐŧĐž ĐŧОдĐĩĐģҌ `UserIn`, ŅĐēа ĐŧŅ–ŅŅ‚Đ¸Ņ‚ŅŒ ĐˇĐ˛Đ¸Ņ‡Đ°ĐšĐŊиК Ņ‚ĐĩĐēŅŅ‚ĐžĐ˛Đ¸Đš ĐŋĐ°Ņ€ĐžĐģҌ: + +{* ../../docs_src/response_model/tutorial002_py310.py hl[7,9] *} + +/// info | ІĐŊŅ„ĐžŅ€ĐŧĐ°Ņ†Ņ–Ņ + +ЊОй виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ `EmailStr`, ҁĐŋĐžŅ‡Đ°Ņ‚Đē҃ Đ˛ŅŅ‚Đ°ĐŊĐžĐ˛Ņ–Ņ‚ŅŒ `email-validator`. + +ПĐĩŅ€ĐĩĐēĐžĐŊĐ°ĐšŅ‚ĐĩҁҌ, Ņ‰Đž Ви ŅŅ‚Đ˛ĐžŅ€Đ¸Đģи [Đ˛Ņ–Ņ€Ņ‚ŅƒĐ°ĐģҌĐŊĐĩ ҁĐĩŅ€ĐĩĐ´ĐžĐ˛Đ¸Ņ‰Đĩ](../virtual-environments.md){.internal-link target=_blank}, аĐēŅ‚Đ¸Đ˛ŅƒĐ˛Đ°Đģи ĐšĐžĐŗĐž, а ĐŋĐžŅ‚Ņ–Đŧ Đ˛ŅŅ‚Đ°ĐŊОвиĐģи ĐŋаĐēĐĩŅ‚, ĐŊаĐŋŅ€Đ¸ĐēĐģад: + +```console +$ pip install email-validator +``` + +or with: + +```console +$ pip install "pydantic[email]" +``` + +/// + +І Đŧи виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅ”ĐŧĐž Ņ†ŅŽ ĐŧОдĐĩĐģҌ, Ņ‰ĐžĐą ĐžĐŗĐžĐģĐžŅĐ¸Ņ‚Đ¸ Ņ– Đ˛Ņ…Ņ–Đ´ĐŊŅ–, Ņ– Đ˛Đ¸Ņ…Ņ–Đ´ĐŊŅ– даĐŊŅ–: + +{* ../../docs_src/response_model/tutorial002_py310.py hl[16] *} + +ĐĸĐĩĐŋĐĩŅ€, ĐēĐžĐģи ĐąŅ€Đ°ŅƒĐˇĐĩŅ€ ŅŅ‚Đ˛ĐžŅ€ŅŽŅ” ĐēĐžŅ€Đ¸ŅŅ‚ŅƒĐ˛Đ°Ņ‡Đ° С ĐŋĐ°Ņ€ĐžĐģĐĩĐŧ, API ĐŋОвĐĩŅ€ĐŊĐĩ Ņ‚ĐžĐš ŅĐ°ĐŧиК ĐŋĐ°Ņ€ĐžĐģҌ ҃ Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´Ņ–. + +ĐŖ Ņ†ŅŒĐžĐŧ҃ виĐŋадĐē҃ ҆Đĩ ĐŧĐžĐļĐĩ ĐŊĐĩ ĐąŅƒŅ‚Đ¸ ĐŋŅ€ĐžĐąĐģĐĩĐŧĐžŅŽ, адĐļĐĩ ŅĐ°ĐŧĐĩ ĐēĐžŅ€Đ¸ŅŅ‚ŅƒĐ˛Đ°Ņ‡ ĐŊĐ°Đ´Ņ–ŅĐģав ĐŋĐ°Ņ€ĐžĐģҌ. + +АĐģĐĩ ŅĐēŅ‰Đž Đŧи виĐēĐžŅ€Đ¸ŅŅ‚Đ°Ņ”ĐŧĐž Ņ†ŅŽ Đļ ĐŧОдĐĩĐģҌ Đ´ĐģŅ Ņ–ĐŊŅˆĐžŅ— ĐžĐŋĐĩŅ€Đ°Ņ†Ņ–Ņ— ҈ĐģŅŅ…Ņƒ, Đŧи ĐŧĐžĐļĐĩĐŧĐž виĐŋадĐēОвО ĐŊĐ°Đ´Ņ–ŅĐģĐ°Ņ‚Đ¸ ĐŋĐ°Ņ€ĐžĐģŅ– ĐŊĐ°ŅˆĐ¸Ņ… ĐēĐžŅ€Đ¸ŅŅ‚ŅƒĐ˛Đ°Ņ‡Ņ–Đ˛ ĐēĐžĐļĐŊĐžĐŧ҃ ĐēĐģŅ–Ņ”ĐŊŅ‚Ņƒ. + +/// danger | ОбĐĩŅ€ĐĩĐļĐŊĐž + +ĐŅ–ĐēĐžĐģи ĐŊĐĩ СйĐĩŅ€Ņ–ĐŗĐ°ĐšŅ‚Đĩ ĐŋĐ°Ņ€ĐžĐģҌ ĐēĐžŅ€Đ¸ŅŅ‚ŅƒĐ˛Đ°Ņ‡Đ° ҃ Đ˛Ņ–Đ´ĐēŅ€Đ¸Ņ‚ĐžĐŧ҃ Đ˛Đ¸ĐŗĐģŅĐ´Ņ– Ņ‚Đ° ĐŊĐĩ ĐŊĐ°Đ´ŅĐ¸ĐģĐ°ĐšŅ‚Đĩ ĐšĐžĐŗĐž ҃ Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´Ņ–, ŅĐēŅ‰Đž ҂ҖĐģҌĐēи Ви ĐŊĐĩ СĐŊĐ°Ņ”Ņ‚Đĩ Đ˛ŅŅ– Ņ€Đ¸ĐˇĐ¸Đēи Ņ– Ņ‚ĐžŅ‡ĐŊĐž Ņ€ĐžĐˇŅƒĐŧҖҔ҂Đĩ, Ņ‰Đž Ņ€ĐžĐąĐ¸Ņ‚Đĩ. + +/// + +## Đ”ĐžĐ´Đ°ĐšŅ‚Đĩ ĐžĐēŅ€ĐĩĐŧ҃ Đ˛Đ¸Ņ…Ņ–Đ´ĐŊ҃ ĐŧОдĐĩĐģҌ + +ЗаĐŧŅ–ŅŅ‚ŅŒ Ņ†ŅŒĐžĐŗĐž Đŧи ĐŧĐžĐļĐĩĐŧĐž ŅŅ‚Đ˛ĐžŅ€Đ¸Ņ‚Đ¸ Đ˛Ņ…Ņ–Đ´ĐŊ҃ ĐŧОдĐĩĐģҌ С Đ˛Ņ–Đ´ĐēŅ€Đ¸Ņ‚Đ¸Đŧ ĐŋĐ°Ņ€ĐžĐģĐĩĐŧ Ņ– Đ˛Đ¸Ņ…Ņ–Đ´ĐŊ҃ ĐŧОдĐĩĐģҌ ĐąĐĩС ĐŊŅŒĐžĐŗĐž: + +{* ../../docs_src/response_model/tutorial003_py310.py hl[9,11,16] *} + +ĐĸŅƒŅ‚, ĐŊĐ°Đ˛Ņ–Ņ‚ŅŒ ŅĐēŅ‰Đž *Ņ„ŅƒĐŊĐēŅ†Ņ–Ņ ĐžĐŋĐĩŅ€Đ°Ņ†Ņ–Ņ— ҈ĐģŅŅ…Ņƒ* ĐŋОвĐĩŅ€Ņ‚Đ°Ņ” Ой'Ņ”ĐēŅ‚ ĐēĐžŅ€Đ¸ŅŅ‚ŅƒĐ˛Đ°Ņ‡Đ°, ŅĐēиК ĐŧŅ–ŅŅ‚Đ¸Ņ‚ŅŒ ĐŋĐ°Ņ€ĐžĐģҌ: + +{* ../../docs_src/response_model/tutorial003_py310.py hl[24] *} + +...Đŧи ĐžĐŗĐžĐģĐžŅĐ¸Đģи `response_model` ŅĐē ĐŊĐ°ŅˆŅƒ ĐŧОдĐĩĐģҌ `UserOut`, ŅĐēа ĐŊĐĩ ĐŧŅ–ŅŅ‚Đ¸Ņ‚ŅŒ ĐŋĐ°Ņ€ĐžĐģŅ: + +{* ../../docs_src/response_model/tutorial003_py310.py hl[22] *} + +ĐĸаĐēиĐŧ Ņ‡Đ¸ĐŊĐžĐŧ, **FastAPI** Đ°Đ˛Ņ‚ĐžĐŧĐ°Ņ‚Đ¸Ņ‡ĐŊĐž Đ˛Ņ–Đ´Ņ„Ņ–ĐģŅŒŅ‚Ņ€ŅƒŅ” Đ˛ŅŅ– даĐŊŅ–, ŅĐēŅ– ĐŊĐĩ вĐēаСаĐŊŅ– ҃ Đ˛Đ¸Ņ…Ņ–Đ´ĐŊŅ–Đš ĐŧОдĐĩĐģŅ– (Са Đ´ĐžĐŋĐžĐŧĐžĐŗĐžŅŽ Pydantic). + +### `response_model` айО Ņ‚Đ¸Đŋ ĐŋОвĐĩŅ€ĐŊĐĩĐŊĐŊŅ + +ĐŖ Ņ†ŅŒĐžĐŧ҃ виĐŋадĐē҃, ĐžŅĐēŅ–ĐģҌĐēи Đ´Đ˛Ņ– ĐŧОдĐĩĐģŅ– Ņ€Ņ–ĐˇĐŊŅ–, ŅĐēŅ‰Đž Đŧи аĐŊĐžŅ‚ŅƒŅ”ĐŧĐž Ņ‚Đ¸Đŋ ĐŋОвĐĩŅ€ĐŊĐĩĐŊĐŊŅ Ņ„ŅƒĐŊĐē҆Җҗ ŅĐē `UserOut`, Ņ€ĐĩдаĐēŅ‚ĐžŅ€ Ņ– Ņ‚Đ°ĐēŅ– Ņ–ĐŊŅŅ‚Ņ€ŅƒĐŧĐĩĐŊŅ‚Đ¸, ŅĐē mypy, Đ˛Đ¸Đ´Đ°Đ´ŅƒŅ‚ŅŒ ĐŋĐžĐŧиĐģĐē҃, йО Ņ„Đ°ĐēŅ‚Đ¸Ņ‡ĐŊĐž Đŧи ĐŋОвĐĩŅ€Ņ‚Đ°Ņ”ĐŧĐž Ņ–ĐŊŅˆĐ¸Đš Ņ‚Đ¸Đŋ. + +ĐĸĐžĐŧ҃ в Ņ†ŅŒĐžĐŧ҃ ĐŋŅ€Đ¸ĐēĐģĐ°Đ´Ņ– Đŧи виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅ”ĐŧĐž ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ `response_model`, а ĐŊĐĩ аĐŊĐžŅ‚Đ°Ņ†Ņ–ŅŽ Ņ‚Đ¸Đŋ҃ ĐŋОвĐĩŅ€ĐŊĐĩĐŊĐŊŅ. + +...аĐģĐĩ Ņ‡Đ¸Ņ‚Đ°ĐšŅ‚Đĩ даĐģŅ–, Ņ‰ĐžĐą Đ´Ņ–ĐˇĐŊĐ°Ņ‚Đ¸ŅŅ, ŅĐē ĐžĐąŅ–ĐšŅ‚Đ¸ ҆Đĩ ОйĐŧĐĩĐļĐĩĐŊĐŊŅ. + +## ĐĸиĐŋ ĐŋОвĐĩŅ€ĐŊĐĩĐŊĐŊŅ Ņ– ҄ҖĐģŅŒŅ‚Ņ€Đ°Ņ†Ņ–Ņ даĐŊĐ¸Ņ… + +ĐŸŅ€ĐžĐ´ĐžĐ˛ĐļиĐŧĐž С ĐŋĐžĐŋĐĩŅ€ĐĩĐ´ĐŊŅŒĐžĐŗĐž ĐŋŅ€Đ¸ĐēĐģĐ°Đ´Ņƒ. Ми Ņ…ĐžŅ‚Ņ–Đģи **аĐŊĐžŅ‚ŅƒĐ˛Đ°Ņ‚Đ¸ Ņ„ŅƒĐŊĐēŅ†Ņ–ŅŽ ОдĐŊиĐŧ Ņ‚Đ¸ĐŋĐžĐŧ**, аĐģĐĩ ĐŋŅ€Đ¸ Ņ†ŅŒĐžĐŧ҃ ĐŋОвĐĩŅ€Ņ‚Đ°Ņ‚Đ¸ С ĐŊĐĩŅ— ĐąŅ–ĐģҌ҈Đĩ даĐŊĐ¸Ņ…. + +Ми Ņ…ĐžŅ‡ĐĩĐŧĐž, Ņ‰ĐžĐą FastAPI ĐŋŅ€ĐžĐ´ĐžĐ˛ĐļŅƒĐ˛Đ°Đ˛ **҄ҖĐģŅŒŅ‚Ņ€ŅƒĐ˛Đ°Ņ‚Đ¸** ҆Җ даĐŊŅ– Са Đ´ĐžĐŋĐžĐŧĐžĐŗĐžŅŽ response_model. ĐĸĐžĐąŅ‚Đž ĐŊĐ°Đ˛Ņ–Ņ‚ŅŒ ŅĐēŅ‰Đž Ņ„ŅƒĐŊĐēŅ†Ņ–Ņ ĐŋОвĐĩŅ€Ņ‚Đ°Ņ” ĐąŅ–ĐģҌ҈Đĩ Ņ–ĐŊŅ„ĐžŅ€ĐŧĐ°Ņ†Ņ–Ņ—, ҃ Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´Ņ– ĐąŅƒĐ´ŅƒŅ‚ŅŒ ĐģĐ¸ŅˆĐĩ ҂Җ ĐŋĐžĐģŅ, ŅĐēŅ– вĐēаСаĐŊŅ– ҃ response_model. + +ĐŖ ĐŋĐžĐŋĐĩŅ€ĐĩĐ´ĐŊŅŒĐžĐŧ҃ ĐŋŅ€Đ¸ĐēĐģĐ°Đ´Ņ–, ĐžŅĐēŅ–ĐģҌĐēи ĐēĐģĐ°ŅĐ¸ ĐąŅƒĐģи Ņ€Ņ–ĐˇĐŊŅ–, ĐŊаĐŧ дОвĐĩĐģĐžŅŅ виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ `response_model`. АĐģĐĩ ҆Đĩ ОСĐŊĐ°Ņ‡Đ°Ņ”, Ņ‰Đž Đŧи ĐŊĐĩ ĐžŅ‚Ņ€Đ¸ĐŧŅƒŅ”ĐŧĐž ĐŋŅ–Đ´Ņ‚Ņ€Đ¸ĐŧĐēи С йОĐē҃ Ņ€ĐĩдаĐēŅ‚ĐžŅ€Đ° ĐēĐžĐ´Ņƒ Ņ‚Đ° Ņ–ĐŊŅŅ‚Ņ€ŅƒĐŧĐĩĐŊŅ‚Ņ–Đ˛ ĐŋĐĩŅ€ĐĩĐ˛Ņ–Ņ€Đēи Ņ‚Đ¸ĐŋŅ–Đ˛ Ņ‰ĐžĐ´Đž Ņ‚Đ¸Đŋ҃, ŅĐēиК ĐŋОвĐĩŅ€Ņ‚Đ°Ņ” Ņ„ŅƒĐŊĐēŅ†Ņ–Ņ. + +ĐŸŅ€ĐžŅ‚Đĩ в ĐąŅ–ĐģŅŒŅˆĐžŅŅ‚Ņ– виĐŋадĐēŅ–Đ˛, ĐēĐžĐģи ĐŊаĐŧ ĐŋĐžŅ‚Ņ€Ņ–ĐąĐŊĐž ĐˇŅ€ĐžĐąĐ¸Ņ‚Đ¸ Ņ‰ĐžŅŅŒ ĐŋĐžĐ´Ņ–ĐąĐŊĐĩ, Đŧи ĐŋŅ€ĐžŅŅ‚Đž Ņ…ĐžŅ‡ĐĩĐŧĐž, Ņ‰ĐžĐą ĐŧОдĐĩĐģҌ **Đ˛Ņ–Đ´Ņ„Ņ–ĐģŅŒŅ‚Ņ€ŅƒĐ˛Đ°Đģа айО ĐŋŅ€Đ¸ĐąŅ€Đ°Đģа** Ņ‡Đ°ŅŅ‚Đ¸ĐŊ҃ даĐŊĐ¸Ņ…, ŅĐē ҃ Ņ†ŅŒĐžĐŧ҃ ĐŋŅ€Đ¸ĐēĐģĐ°Đ´Ņ–. + +ĐŖ Ņ‚Đ°ĐēĐ¸Ņ… виĐŋадĐēĐ°Ņ… Đŧи ĐŧĐžĐļĐĩĐŧĐž виĐēĐžŅ€Đ¸ŅŅ‚Đ°Ņ‚Đ¸ ĐēĐģĐ°ŅĐ¸ Ņ‚Đ° ҁĐŋадĐēŅƒĐ˛Đ°ĐŊĐŊŅ, Ņ‰ĐžĐą ҁĐēĐžŅ€Đ¸ŅŅ‚Đ°Ņ‚Đ¸ŅŅ **аĐŊĐžŅ‚Đ°Ņ†Ņ–ŅĐŧи Ņ‚Đ¸ĐŋŅ–Đ˛** Ņ„ŅƒĐŊĐēŅ†Ņ–Đš — ҆Đĩ Đ´Đ°Ņ” ĐēŅ€Đ°Ņ‰Ņƒ ĐŋŅ–Đ´Ņ‚Ņ€Đ¸ĐŧĐē҃ С йОĐē҃ Ņ€ĐĩдаĐēŅ‚ĐžŅ€Đ° Ņ‚Đ° Ņ–ĐŊŅŅ‚Ņ€ŅƒĐŧĐĩĐŊŅ‚Ņ–Đ˛ Ņ‚Đ¸Đŋ҃ mypy, Ņ– ĐŋŅ€Đ¸ Ņ†ŅŒĐžĐŧ҃ FastAPI ĐŋŅ€ĐžĐ´ĐžĐ˛ĐļŅƒŅ” виĐēĐžĐŊŅƒĐ˛Đ°Ņ‚Đ¸ **҄ҖĐģŅŒŅ‚Ņ€Đ°Ņ†Ņ–ŅŽ даĐŊĐ¸Ņ…** ҃ Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´Ņ–. + +{* ../../docs_src/response_model/tutorial003_01_py310.py hl[7:10,13:14,18] *} + +Đ—Đ°Đ˛Đ´ŅĐēи Ņ†ŅŒĐžĐŧ҃ Đŧи ĐžŅ‚Ņ€Đ¸ĐŧŅƒŅ”ĐŧĐž ĐŋŅ–Đ´Ņ‚Ņ€Đ¸ĐŧĐē҃ Ņ–ĐŊŅŅ‚Ņ€ŅƒĐŧĐĩĐŊŅ‚Ņ–Đ˛ — Đ˛Ņ–Đ´ Ņ€ĐĩдаĐēŅ‚ĐžŅ€Ņ–Đ˛ Ņ– mypy, ĐžŅĐēŅ–ĐģҌĐēи ҆ĐĩĐš ĐēОд Ņ” ĐēĐžŅ€ĐĩĐēŅ‚ĐŊиĐŧ С Ņ‚ĐžŅ‡Đēи ĐˇĐžŅ€Ņƒ Ņ‚Đ¸ĐŋŅ–Đ˛, — аĐģĐĩ Đŧи Ņ‚Đ°ĐēĐžĐļ ĐžŅ‚Ņ€Đ¸ĐŧŅƒŅ”ĐŧĐž ҄ҖĐģŅŒŅ‚Ņ€Đ°Ņ†Ņ–ŅŽ даĐŊĐ¸Ņ… Đ˛Ņ–Đ´ FastAPI. + +Đ¯Đē ҆Đĩ ĐŋŅ€Đ°Ņ†ŅŽŅ”? Đ”Đ°Đ˛Đ°ĐšŅ‚Đĩ Ņ€ĐžĐˇĐąĐĩŅ€ĐĩĐŧĐžŅŅ. 🤓 + +### ĐĸиĐŋи Ņ‚Đ° ĐŋŅ–Đ´Ņ‚Ņ€Đ¸ĐŧĐēа Ņ–ĐŊŅŅ‚Ņ€ŅƒĐŧĐĩĐŊŅ‚Ņ–Đ˛ + +ĐĄĐŋĐĩŅ€ŅˆŅƒ ĐŋОдивиĐŧĐžŅŅŒ, ŅĐē ҆Đĩ ĐąĐ°Ņ‡Đ°Ņ‚ŅŒ Ņ€ĐĩдаĐēŅ‚ĐžŅ€Đ¸, mypy Ņ‚Đ° Ņ–ĐŊŅˆŅ– Ņ–ĐŊŅŅ‚Ņ€ŅƒĐŧĐĩĐŊŅ‚Đ¸. + +`BaseUser` ĐŧĐ°Ņ” ĐąĐ°ĐˇĐžĐ˛Ņ– ĐŋĐžĐģŅ. ĐŸĐžŅ‚Ņ–Đŧ `UserIn` ҃ҁĐŋадĐēĐžĐ˛ŅƒŅ” `BaseUser` Ņ– Đ´ĐžĐ´Đ°Ņ” ĐŋĐžĐģĐĩ `password`, ĐžŅ‚ĐļĐĩ, Đ˛Ņ–ĐŊ ĐŧĐ°Ņ‚Đ¸ĐŧĐĩ Đ˛ŅŅ– ĐŋĐžĐģŅ С ĐžĐąĐžŅ… ĐŧОдĐĩĐģĐĩĐš. + +Ми СаСĐŊĐ°Ņ‡Đ°Ņ”ĐŧĐž Ņ‚Đ¸Đŋ ĐŋОвĐĩŅ€ĐŊĐĩĐŊĐŊŅ Ņ„ŅƒĐŊĐē҆Җҗ ŅĐē `BaseUser`, аĐģĐĩ Ņ„Đ°ĐēŅ‚Đ¸Ņ‡ĐŊĐž ĐŋОвĐĩŅ€Ņ‚Đ°Ņ”ĐŧĐž ĐĩĐēСĐĩĐŧĐŋĐģŅŅ€ `UserIn`. + +Đ ĐĩдаĐēŅ‚ĐžŅ€, mypy Ņ‚Đ° Ņ–ĐŊŅˆŅ– Ņ–ĐŊŅŅ‚Ņ€ŅƒĐŧĐĩĐŊŅ‚Đ¸ ĐŊĐĩ ҁĐēĐ°Ņ€ĐļĐ¸Ņ‚Đ¸ĐŧŅƒŅ‚ŅŒŅŅ ĐŊа ҆Đĩ, Ņ‚ĐžĐŧ҃ Ņ‰Đž С Ņ‚ĐžŅ‡Đēи ĐˇĐžŅ€Ņƒ Ņ‚Đ¸ĐŋŅ–ĐˇĐ°Ņ†Ņ–Ņ— `UserIn` Ņ” ĐŋŅ–Đ´ĐēĐģĐ°ŅĐžĐŧ `BaseUser`, а ҆Đĩ ОСĐŊĐ°Ņ‡Đ°Ņ”, Ņ‰Đž Đ˛Ņ–ĐŊ Ņ” `ваĐģŅ–Đ´ĐŊиĐŧ` Ņ‚Đ¸ĐŋĐžĐŧ, ĐēĐžĐģи ĐžŅ‡Ņ–ĐēŅƒŅ”Ņ‚ŅŒŅŅ ĐąŅƒĐ´ŅŒ-Ņ‰Đž, Ņ‰Đž Ņ” `BaseUser`. + +### Đ¤Ņ–ĐģŅŒŅ‚Ņ€Đ°Ņ†Ņ–Ņ даĐŊĐ¸Ņ… ҃ FastAPI + +ĐĸĐĩĐŋĐĩŅ€ Đ´ĐģŅ FastAPI Đ˛Ņ–ĐŊ ĐąĐ°Ņ‡Đ¸Ņ‚ŅŒ Ņ‚Đ¸Đŋ ĐŋОвĐĩŅ€ĐŊĐĩĐŊĐŊŅ Ņ– ĐŋĐĩŅ€ĐĩĐēĐžĐŊŅƒŅ”Ņ‚ŅŒŅŅ, Ņ‰Đž Ņ‚Đĩ, Ņ‰Đž Ви ĐŋОвĐĩŅ€Ņ‚Đ°Ņ”Ņ‚Đĩ, ĐŧŅ–ŅŅ‚Đ¸Ņ‚ŅŒ **҂ҖĐģҌĐēи** ĐŋĐžĐģŅ, ŅĐēŅ– ĐžĐŗĐžĐģĐžŅˆĐĩĐŊŅ– ҃ Ņ†ŅŒĐžĐŧ҃ Ņ‚Đ¸ĐŋŅ–. + +FastAPI виĐēĐžĐŊŅƒŅ” ĐēŅ–ĐģҌĐēа вĐŊŅƒŅ‚Ņ€Ņ–ŅˆĐŊŅ–Ņ… ĐžĐŋĐĩŅ€Đ°Ņ†Ņ–Đš С Pydantic, Ņ‰ĐžĐą ĐŗĐ°Ņ€Đ°ĐŊŅ‚ŅƒĐ˛Đ°Ņ‚Đ¸, Ņ‰Đž ĐŋŅ€Đ°Đ˛Đ¸Đģа ĐŊĐ°ŅĐģŅ–Đ´ŅƒĐ˛Đ°ĐŊĐŊŅ ĐēĐģĐ°ŅŅ–Đ˛ ĐŊĐĩ ĐˇĐ°ŅŅ‚ĐžŅĐžĐ˛ŅƒŅŽŅ‚ŅŒŅŅ Đ´ĐģŅ ҄ҖĐģŅŒŅ‚Ņ€Đ°Ņ†Ņ–Ņ— ĐŋОвĐĩŅ€ĐŊĐĩĐŊĐ¸Ņ… даĐŊĐ¸Ņ…, Ņ–ĐŊаĐē҈Đĩ Ви ĐŧĐžĐŗĐģи Đą ĐŋОвĐĩŅ€ĐŊŅƒŅ‚Đ¸ СĐŊĐ°Ņ‡ĐŊĐž ĐąŅ–ĐģҌ҈Đĩ даĐŊĐ¸Ņ…, ĐŊŅ–Đļ ĐžŅ‡Ņ–ĐēŅƒĐ˛Đ°Đģи. + +ĐĸаĐēиĐŧ Ņ‡Đ¸ĐŊĐžĐŧ, Ви ĐžŅ‚Ņ€Đ¸ĐŧŅƒŅ”Ņ‚Đĩ ĐŊаКĐēŅ€Đ°Ņ‰Đĩ С Đ´Đ˛ĐžŅ… ŅĐ˛Ņ–Ņ‚Ņ–Đ˛: аĐŊĐžŅ‚Đ°Ņ†Ņ–Ņ— Ņ‚Đ¸ĐŋŅ–Đ˛ **С ĐŋŅ–Đ´Ņ‚Ņ€Đ¸ĐŧĐēĐžŅŽ Ņ–ĐŊŅŅ‚Ņ€ŅƒĐŧĐĩĐŊŅ‚Ņ–Đ˛** Ņ– **҄ҖĐģŅŒŅ‚Ņ€Đ°Ņ†Ņ–ŅŽ даĐŊĐ¸Ņ…**. + +## ĐŸĐžĐ´Đ¸Đ˛Đ¸Ņ‚Đ¸ŅŅŒ ҃ Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Ņ–Ņ— + +КоĐģи Ви Đ´Đ¸Đ˛Đ¸Ņ‚ĐĩҁҌ Đ°Đ˛Ņ‚ĐžĐŧĐ°Ņ‚Đ¸Ņ‡ĐŊ҃ Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Ņ–ŅŽ, Ви ĐŧĐžĐļĐĩŅ‚Đĩ ĐŋĐžĐąĐ°Ņ‡Đ¸Ņ‚Đ¸, Ņ‰Đž Đ˛Ņ…Ņ–Đ´ĐŊа ĐŧОдĐĩĐģҌ Ņ– Đ˛Đ¸Ņ…Ņ–Đ´ĐŊа ĐŧОдĐĩĐģҌ ĐŧĐ°ŅŽŅ‚ŅŒ вĐģĐ°ŅĐŊ҃ JSON-ҁ҅ĐĩĐŧ҃: + + + +І ĐžĐąĐ¸Đ´Đ˛Ņ– ĐŧОдĐĩĐģŅ– виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅŽŅ‚ŅŒŅŅ Đ´ĐģŅ Ņ–ĐŊŅ‚ĐĩŅ€Đ°ĐēŅ‚Đ¸Đ˛ĐŊĐžŅ— API-Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Ņ–Ņ—: + + + +## ІĐŊŅˆŅ– аĐŊĐžŅ‚Đ°Ņ†Ņ–Ņ— Ņ‚Đ¸ĐŋŅ–Đ˛ ĐŋОвĐĩŅ€ĐŊĐĩĐŊĐŊŅ + +Đ†ŅĐŊŅƒŅŽŅ‚ŅŒ виĐŋадĐēи, ĐēĐžĐģи Ви ĐŋОвĐĩŅ€Ņ‚Đ°Ņ”Ņ‚Đĩ Ņ‰ĐžŅŅŒ, Ņ‰Đž ĐŊĐĩ Ņ” Đ´ĐžĐŋŅƒŅŅ‚Đ¸ĐŧиĐŧ ĐŋĐžĐģĐĩĐŧ Pydantic, аĐģĐĩ аĐŊĐžŅ‚ŅƒŅ”Ņ‚Đĩ ҆Đĩ ҃ Ņ„ŅƒĐŊĐē҆Җҗ ĐģĐ¸ŅˆĐĩ Đ´ĐģŅ Ņ‚ĐžĐŗĐž, Ņ‰ĐžĐą ĐžŅ‚Ņ€Đ¸ĐŧĐ°Ņ‚Đ¸ ĐŋŅ–Đ´Ņ‚Ņ€Đ¸ĐŧĐē҃ Đ˛Ņ–Đ´ Ņ–ĐŊŅŅ‚Ņ€ŅƒĐŧĐĩĐŊŅ‚Ņ–Đ˛ (Ņ€ĐĩдаĐēŅ‚ĐžŅ€Đ°, mypy Ņ‚ĐžŅ‰Đž). + +### ПовĐĩŅ€ĐŊĐĩĐŊĐŊŅ Response ĐŊаĐŋŅ€ŅĐŧ҃ + +НайĐŋĐžŅˆĐ¸Ņ€ĐĩĐŊŅ–ŅˆĐ¸Đŧ виĐŋадĐēĐžĐŧ ĐąŅƒĐ´Đĩ [ĐŋОвĐĩŅ€ĐŊĐĩĐŊĐŊŅ Response ĐŊаĐŋŅ€ŅĐŧ҃, ŅĐē ĐŋĐžŅŅĐŊŅŽŅ”Ņ‚ŅŒŅŅ ĐŋŅ–ĐˇĐŊŅ–ŅˆĐĩ ҃ Ņ€ĐžĐˇŅˆĐ¸Ņ€ĐĩĐŊŅ–Đš Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Ņ–Ņ—](../advanced/response-directly.md){.internal-link target=_blank}. + +{* ../../docs_src/response_model/tutorial003_02.py hl[8,10:11] *} + +ĐĻĐĩĐš ĐŋŅ€ĐžŅŅ‚Đ¸Đš виĐŋадОĐē Đ°Đ˛Ņ‚ĐžĐŧĐ°Ņ‚Đ¸Ņ‡ĐŊĐž ĐžĐąŅ€ĐžĐąĐģŅŅ”Ņ‚ŅŒŅŅ FastAPI, Ņ‚ĐžĐŧ҃ Ņ‰Đž аĐŊĐžŅ‚Đ°Ņ†Ņ–Ņ Ņ‚Đ¸Đŋ҃ ĐŋОвĐĩŅ€ĐŊĐĩĐŊĐŊŅ — ҆Đĩ ĐēĐģĐ°Ņ (айО ĐŋŅ–Đ´ĐēĐģĐ°Ņ) `Response`. + +І Ņ–ĐŊŅŅ‚Ņ€ŅƒĐŧĐĩĐŊŅ‚Đ¸ Ņ‚Đ°ĐēĐžĐļ ĐąŅƒĐ´ŅƒŅ‚ŅŒ СадОвОĐģĐĩĐŊŅ–, йО Ņ– `RedirectResponse`, Ņ– `JSONResponse` Ņ” ĐŋŅ–Đ´ĐēĐģĐ°ŅĐ°Đŧи `Response`, ĐžŅ‚ĐļĐĩ аĐŊĐžŅ‚Đ°Ņ†Ņ–Ņ Ņ‚Đ¸Đŋ҃ ĐēĐžŅ€ĐĩĐēŅ‚ĐŊа. + +### АĐŊĐžŅ‚Đ°Ņ†Ņ–Ņ ĐŋŅ–Đ´ĐēĐģĐ°ŅŅƒ Response + +ĐĸаĐēĐžĐļ ĐŧĐžĐļĐŊа виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ ĐŋŅ–Đ´ĐēĐģĐ°Ņ `Response` ҃ аĐŊĐžŅ‚Đ°Ņ†Ņ–Ņ— Ņ‚Đ¸Đŋ҃: + +{* ../../docs_src/response_model/tutorial003_03.py hl[8:9] *} + +ĐĻĐĩ Ņ‚ĐĩĐļ ĐŋŅ€Đ°Ņ†ŅŽĐ˛Đ°Ņ‚Đ¸ĐŧĐĩ, йО `RedirectResponse` — ĐŋŅ–Đ´ĐēĐģĐ°Ņ `Response`, Ņ– FastAPI Đ°Đ˛Ņ‚ĐžĐŧĐ°Ņ‚Đ¸Ņ‡ĐŊĐž ĐžĐąŅ€ĐžĐąĐ¸Ņ‚ŅŒ ҆ĐĩĐš ĐŋŅ€ĐžŅŅ‚Đ¸Đš виĐŋадОĐē. + +### НĐĩĐēĐžŅ€ĐĩĐēŅ‚ĐŊŅ– аĐŊĐžŅ‚Đ°Ņ†Ņ–Ņ— Ņ‚Đ¸Đŋ҃ ĐŋОвĐĩŅ€ĐŊĐĩĐŊĐŊŅ + +АĐģĐĩ ĐēĐžĐģи Ви ĐŋОвĐĩŅ€Ņ‚Đ°Ņ”Ņ‚Đĩ ŅĐēĐ¸ĐšŅŅŒ Ņ–ĐŊŅˆĐ¸Đš Đ´ĐžĐ˛Ņ–ĐģҌĐŊиК ĐžĐąâ€™Ņ”ĐēŅ‚, Ņ‰Đž ĐŊĐĩ Ņ” ваĐģŅ–Đ´ĐŊиĐŧ Ņ‚Đ¸ĐŋĐžĐŧ Pydantic (ĐŊаĐŋŅ€Đ¸ĐēĐģад, ĐžĐąâ€™Ņ”ĐēŅ‚ йаСи даĐŊĐ¸Ņ…), Ņ– аĐŊĐžŅ‚ŅƒŅ”Ņ‚Đĩ ĐšĐžĐŗĐž Ņ‚Đ°Đē ҃ Ņ„ŅƒĐŊĐē҆Җҗ, FastAPI ҁĐŋŅ€ĐžĐąŅƒŅ” ŅŅ‚Đ˛ĐžŅ€Đ¸Ņ‚Đ¸ Pydantic ĐŧОдĐĩĐģҌ Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´Ņ– ĐŊа ĐžŅĐŊĐžĐ˛Ņ– ҆ҖҔҗ аĐŊĐžŅ‚Đ°Ņ†Ņ–Ņ— Ņ‚Đ¸Đŋ҃, Ņ– ҆Đĩ СавĐĩŅ€ŅˆĐ¸Ņ‚ŅŒŅŅ ĐŋĐžĐŧиĐģĐēĐžŅŽ. + +ĐĸĐĩ ŅĐ°ĐŧĐĩ ŅŅ‚Đ°ĐŊĐĩŅ‚ŅŒŅŅ, ŅĐēŅ‰Đž Ви виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅ”Ņ‚Đĩ union ĐŧŅ–Đļ Ņ€Ņ–ĐˇĐŊиĐŧи Ņ‚Đ¸ĐŋаĐŧи, Đ´Đĩ ОдиĐŊ айО ĐąŅ–ĐģҌ҈Đĩ ĐŊĐĩ Ņ” ваĐģŅ–Đ´ĐŊиĐŧи Ņ‚Đ¸ĐŋаĐŧи Pydantic, ĐŊаĐŋŅ€Đ¸ĐēĐģад, ҆Đĩ ҁĐŋŅ€Đ¸Ņ‡Đ¸ĐŊĐ¸Ņ‚ŅŒ ĐŋĐžĐŧиĐģĐē҃ đŸ’Ĩ: + +{* ../../docs_src/response_model/tutorial003_04_py310.py hl[8] *} + +...҆Đĩ ĐŊĐĩ ĐŋŅ€Đ°Ņ†ŅŽŅ”, Ņ‚ĐžĐŧ҃ Ņ‰Đž Ņ‚Đ¸Đŋ аĐŊĐžŅ‚Đ°Ņ†Ņ–Ņ— ĐŊĐĩ Ņ” Ņ‚Đ¸ĐŋĐžĐŧ Pydantic Ņ– ĐŊĐĩ Ņ” ĐŋŅ€ĐžŅŅ‚Đž ĐēĐģĐ°ŅĐžĐŧ `Response` айО ĐšĐžĐŗĐž ĐŋŅ–Đ´ĐēĐģĐ°ŅĐžĐŧ, а Ņ” ĐžĐąâ€™Ņ”Đ´ĐŊаĐŊĐŊŅĐŧ (union) — айО `Response`, айО `dict`. + +### Đ’Ņ–Đ´ĐēĐģŅŽŅ‡ĐĩĐŊĐŊŅ МодĐĩĐģŅ– Đ’Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´Ņ– + +ĐŸŅ€ĐžĐ´ĐžĐ˛ĐļŅƒŅŽŅ‡Đ¸ ĐŋŅ€Đ¸ĐēĐģад Đ˛Đ¸Ņ‰Đĩ, ĐŧĐžĐļĐģивО, Ви ĐŊĐĩ Ņ…ĐžŅ‡ĐĩŅ‚Đĩ виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ ŅŅ‚Đ°ĐŊĐ´Đ°Ņ€Ņ‚ĐŊ҃ ваĐģŅ–Đ´Đ°Ņ†Ņ–ŅŽ даĐŊĐ¸Ņ…, Đ°Đ˛Ņ‚ĐžĐŧĐ°Ņ‚Đ¸Ņ‡ĐŊ҃ Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Ņ–ŅŽ, ҄ҖĐģŅŒŅ‚Ņ€Đ°Ņ†Ņ–ŅŽ Ņ‚ĐžŅ‰Đž, ŅĐēŅ– FastAPI виĐēĐžĐŊŅƒŅ” Са СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ. + +АĐģĐĩ ви Đ˛ŅĐĩ ОдĐŊĐž ĐŧĐžĐļĐĩŅ‚Đĩ СаĐģĐ¸ŅˆĐ¸Ņ‚Đ¸ аĐŊĐžŅ‚Đ°Ņ†Ņ–ŅŽ Ņ‚Đ¸Đŋ҃ ҃ Ņ„ŅƒĐŊĐē҆Җҗ, Ņ‰ĐžĐą СйĐĩŅ€ĐĩĐŗŅ‚Đ¸ ĐŋŅ–Đ´Ņ‚Ņ€Đ¸ĐŧĐē҃ С йОĐē҃ Ņ–ĐŊŅŅ‚Ņ€ŅƒĐŧĐĩĐŊŅ‚Ņ–Đ˛, Ņ‚Đ°ĐēĐ¸Ņ… ŅĐē Ņ€ĐĩдаĐēŅ‚ĐžŅ€Đ¸ ĐēĐžĐ´Ņƒ айО ŅŅ‚Đ°Ņ‚Đ¸Ņ‡ĐŊŅ– ĐŋĐĩŅ€ĐĩĐ˛Ņ–Ņ€Đēи Ņ‚Đ¸ĐŋŅ–Đ˛ (ĐŊаĐŋŅ€Đ¸ĐēĐģад, mypy). + +ĐŖ Ņ‚Đ°ĐēĐžĐŧ҃ виĐŋадĐē҃ ви ĐŧĐžĐļĐĩŅ‚Đĩ виĐŧĐēĐŊŅƒŅ‚Đ¸ ĐŗĐĩĐŊĐĩŅ€Đ°Ņ†Ņ–ŅŽ ĐŧОдĐĩĐģŅ– Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´Ņ–, Đ˛ŅŅ‚Đ°ĐŊĐžĐ˛Đ¸Đ˛ŅˆĐ¸ `response_model=None`: + +{* ../../docs_src/response_model/tutorial003_05_py310.py hl[7] *} + +ĐĻĐĩ СĐŧŅƒŅĐ¸Ņ‚ŅŒ FastAPI ĐŋŅ€ĐžĐŋŅƒŅŅ‚Đ¸Ņ‚Đ¸ ĐŗĐĩĐŊĐĩŅ€Đ°Ņ†Ņ–ŅŽ ĐŧОдĐĩĐģŅ– Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´Ņ–, Ņ– Ņ‚Đ°ĐēиĐŧ Ņ‡Đ¸ĐŊĐžĐŧ Ви СĐŧĐžĐļĐĩŅ‚Đĩ виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ ĐąŅƒĐ´ŅŒ-ŅĐēŅ– аĐŊĐžŅ‚Đ°Ņ†Ņ–Ņ— Ņ‚Đ¸ĐŋŅ–Đ˛ ĐŋОвĐĩŅ€ĐŊĐĩĐŊĐŊŅ ĐąĐĩС вĐŋĐģĐ¸Đ˛Ņƒ ĐŊа Đ˛Đ°ŅˆŅƒ FastAPI аĐŋĐģŅ–ĐēĐ°Ņ†Ņ–ŅŽ. 🤓 + +## ĐŸĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ¸ ĐēĐžĐ´ŅƒĐ˛Đ°ĐŊĐŊŅ ĐŧОдĐĩĐģŅ– Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´Ņ– + +Đ’Đ°ŅˆĐ° ĐŧОдĐĩĐģҌ Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´Ņ– ĐŧĐžĐļĐĩ ĐŧĐ°Ņ‚Đ¸ СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ Са СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ, ĐŊаĐŋŅ€Đ¸ĐēĐģад: + +{* ../../docs_src/response_model/tutorial004_py310.py hl[9,11:12] *} + +* `description: Union[str, None] = None` (айО `str | None = None` ҃ Python 3.10) ĐŧĐ°Ņ” СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ Са СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ `None`. +* `tax: float = 10.5` ĐŧĐ°Ņ” СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ Са СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ `10.5`. +* `tags: List[str] = []` ĐŧĐ°Ņ” СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ Са СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ ĐŋĐžŅ€ĐžĐļĐŊŅ–Đš ҁĐŋĐ¸ŅĐžĐē: `[]`. + +АĐģĐĩ Ви ĐŧĐžĐļĐĩŅ‚Đĩ ĐˇĐ°Ņ…ĐžŅ‚Ņ–Ņ‚Đ¸ ĐŊĐĩ вĐēĐģŅŽŅ‡Đ°Ņ‚Đ¸ Ņ—Ņ… ҃ Ņ€ĐĩĐˇŅƒĐģŅŒŅ‚Đ°Ņ‚, ŅĐēŅ‰Đž вОĐŊи Ņ„Đ°ĐēŅ‚Đ¸Ņ‡ĐŊĐž ĐŊĐĩ ĐąŅƒĐģи СйĐĩŅ€ĐĩĐļĐĩĐŊŅ–. + +НаĐŋŅ€Đ¸ĐēĐģад, ŅĐēŅ‰Đž ҃ Đ’Đ°Ņ Ņ” ĐŧОдĐĩĐģŅ– С ĐąĐ°ĐŗĐ°Ņ‚ŅŒĐŧа ĐŊĐĩĐžĐąĐžĐ˛â€™ŅĐˇĐēОвиĐŧи Đ°Ņ‚Ņ€Đ¸ĐąŅƒŅ‚Đ°Đŧи ҃ NoSQL ĐąĐ°ĐˇŅ– даĐŊĐ¸Ņ…, аĐģĐĩ Ви ĐŊĐĩ Ņ…ĐžŅ‡ĐĩŅ‚Đĩ Đ˛Ņ–Đ´ĐŋŅ€Đ°Đ˛ĐģŅŅ‚Đ¸ Đ´ŅƒĐļĐĩ Đ´ĐžĐ˛ĐŗŅ– JSON-Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´Ņ–, ĐŋОвĐŊŅ– СĐŊĐ°Ņ‡ĐĩĐŊҌ Са СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ. + +### ВиĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐšŅ‚Đĩ ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ `response_model_exclude_unset` + +Ви ĐŧĐžĐļĐĩŅ‚Đĩ Đ˛ŅŅ‚Đ°ĐŊĐžĐ˛Đ¸Ņ‚Đ¸ ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ Đ´ĐĩĐēĐžŅ€Đ°Ņ‚ĐžŅ€Đ° ҈ĐģŅŅ…Ņƒ `response_model_exclude_unset=True`: + +{* ../../docs_src/response_model/tutorial004_py310.py hl[22] *} + +Ņ– ҆Җ СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ Са СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ ĐŊĐĩ ĐąŅƒĐ´ŅƒŅ‚ŅŒ вĐēĐģŅŽŅ‡ĐĩĐŊŅ– ҃ Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´ŅŒ, ҂ҖĐģҌĐēи Ņ„Đ°ĐēŅ‚Đ¸Ņ‡ĐŊĐž Đ˛ŅŅ‚Đ°ĐŊОвĐģĐĩĐŊŅ– СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ. + +ĐžŅ‚ĐļĐĩ, ŅĐēŅ‰Đž Ви ĐŊĐ°Đ´Ņ–ŅˆĐģĐĩŅ‚Đĩ СаĐŋĐ¸Ņ‚ Đ´Đž Ņ†ŅŒĐžĐŗĐž ĐžĐŋĐĩŅ€Đ°Ņ‚ĐžŅ€Đ° ҈ĐģŅŅ…Ņƒ Đ´ĐģŅ ĐĩĐģĐĩĐŧĐĩĐŊŅ‚Đ° С item_id `foo`, Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´ŅŒ (ĐąĐĩС вĐēĐģŅŽŅ‡ĐĩĐŊĐŊŅ СĐŊĐ°Ņ‡ĐĩĐŊҌ Са СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ) ĐąŅƒĐ´Đĩ: + +```JSON +{ + "name": "Foo", + "price": 50.2 +} +``` + +/// info | ІĐŊŅ„ĐžŅ€ĐŧĐ°Ņ†Ņ–Ņ + +ĐŖ Pydantic вĐĩҀҁҖҗ 1 ĐŧĐĩŅ‚ĐžĐ´ ĐŊĐ°ĐˇĐ¸Đ˛Đ°Đ˛ŅŅ `.dict()`, Đ˛Ņ–ĐŊ ĐąŅƒĐ˛ ĐˇĐ°ŅŅ‚Đ°Ņ€Ņ–ĐģиК (аĐģĐĩ ҉Đĩ ĐŋŅ–Đ´Ņ‚Ņ€Đ¸ĐŧŅƒŅ”Ņ‚ŅŒŅŅ) ҃ Pydantic вĐĩҀҁҖҗ 2 Ņ– ĐŋĐĩŅ€ĐĩĐšĐŧĐĩĐŊОваĐŊиК ҃ `.model_dump()`. + +ĐŸŅ€Đ¸ĐēĐģади Ņ‚ŅƒŅ‚ виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅŽŅ‚ŅŒ `.dict()` Đ´ĐģŅ ҁ҃ĐŧҖҁĐŊĐžŅŅ‚Ņ– С Pydantic v1, аĐģĐĩ ВаĐŧ ҁĐģŅ–Đ´ виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ `.model_dump()`, ŅĐēŅ‰Đž Ви ĐŧĐžĐļĐĩŅ‚Đĩ виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ Pydantic v2. + +/// + +/// info | ІĐŊŅ„ĐžŅ€ĐŧĐ°Ņ†Ņ–Ņ + +FastAPI виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅ” `.dict()` ĐŧОдĐĩĐģŅ– Pydantic С ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€ĐžĐŧ `exclude_unset`, Ņ‰ĐžĐą Đ´ĐžŅŅĐŗŅ‚Đ¸ Ņ†ŅŒĐžĐŗĐž. + +/// + +/// info | ІĐŊŅ„ĐžŅ€ĐŧĐ°Ņ†Ņ–Ņ + +Ви Ņ‚Đ°ĐēĐžĐļ ĐŧĐžĐļĐĩŅ‚Đĩ виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸: + +* `response_model_exclude_defaults=True` +* `response_model_exclude_none=True` + +ŅĐē ĐžĐŋĐ¸ŅĐ°ĐŊĐž в Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Ņ–Ņ— Pydantic for `exclude_defaults` Ņ‚Đ° `exclude_none`. + +/// + +#### ДаĐŊŅ– ĐˇŅ– СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅĐŧи Đ´ĐģŅ ĐŋĐžĐģŅ–Đ˛ Ņ–Đˇ Ņ‚Đ¸ĐŋОвиĐŧи СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅĐŧи + +АĐģĐĩ ŅĐēŅ‰Đž Đ’Đ°ŅˆŅ– даĐŊŅ– ĐŧĐ°ŅŽŅ‚ŅŒ СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ Đ´ĐģŅ ĐŋĐžĐģŅ–Đ˛ ĐŧОдĐĩĐģŅ– С Ņ‚Đ¸ĐŋОвиĐŧи СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅĐŧи, ŅĐē ҃ ĐĩĐģĐĩĐŧĐĩĐŊŅ‚Đ° С item_id `bar`: + +```Python hl_lines="3 5" +{ + "name": "Bar", + "description": "The bartenders", + "price": 62, + "tax": 20.2 +} +``` +вОĐŊи ĐąŅƒĐ´ŅƒŅ‚ŅŒ вĐēĐģŅŽŅ‡ĐĩĐŊŅ– ҃ Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´ŅŒ. + +#### ДаĐŊŅ– С Ņ‚Đ¸Đŧи ŅĐ°ĐŧиĐŧи СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅĐŧи, Ņ‰Đž Đš Ņ‚Đ¸ĐŋĐžĐ˛Ņ– + +Đ¯ĐēŅ‰Đž даĐŊŅ– ĐŧĐ°ŅŽŅ‚ŅŒ ҂Җ ŅĐ°ĐŧŅ– СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ, Ņ‰Đž Đš Ņ‚Đ¸ĐŋĐžĐ˛Ņ–, ŅĐē ҃ ĐĩĐģĐĩĐŧĐĩĐŊŅ‚Đ° С item_id `baz`: + +```Python hl_lines="3 5-6" +{ + "name": "Baz", + "description": None, + "price": 50.2, + "tax": 10.5, + "tags": [] +} +``` + +FastAPI Đ´ĐžŅŅ‚Đ°Ņ‚ĐŊŅŒĐž Ņ€ĐžĐˇŅƒĐŧĐŊиК (ĐŊĐ°ŅĐŋŅ€Đ°Đ˛Đ´Ņ–, Pydantic Đ´ĐžŅŅ‚Đ°Ņ‚ĐŊŅŒĐž Ņ€ĐžĐˇŅƒĐŧĐŊиК), Ņ‰ĐžĐą ĐˇŅ€ĐžĐˇŅƒĐŧŅ–Ņ‚Đ¸, Ņ‰Đž, Ņ…ĐžŅ‡Đ° `description`, `tax` Ņ– `tags` ĐŧĐ°ŅŽŅ‚ŅŒ ҂Җ ŅĐ°ĐŧŅ– СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ, Ņ‰Đž Đš Ņ‚Đ¸ĐŋĐžĐ˛Ņ–, вОĐŊи ĐąŅƒĐģи Đ˛ŅŅ‚Đ°ĐŊОвĐģĐĩĐŊŅ– ŅĐ˛ĐŊĐž (а ĐŊĐĩ Đ˛ĐˇŅŅ‚Ņ– ŅĐē СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ Са СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ). + +ĐžŅ‚ĐļĐĩ, вОĐŊи ĐąŅƒĐ´ŅƒŅ‚ŅŒ вĐēĐģŅŽŅ‡ĐĩĐŊŅ– ҃ JSON-Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´ŅŒ. + +/// tip | ĐŸĐžŅ€Đ°Đ´Đ° + +ЗвĐĩŅ€ĐŊŅ–Ņ‚ŅŒ ŅƒĐ˛Đ°ĐŗŅƒ, Ņ‰Đž Ņ‚Đ¸ĐŋĐžĐ˛Ņ– СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ ĐŧĐžĐļŅƒŅ‚ŅŒ ĐąŅƒŅ‚Đ¸ ĐąŅƒĐ´ŅŒ-ŅĐēиĐŧи, ĐŊĐĩ ĐģĐ¸ŅˆĐĩ `None`. + +ĐĻĐĩ ĐŧĐžĐļĐĩ ĐąŅƒŅ‚Đ¸ list (`[]`), `float` 10.5 Ņ‚ĐžŅ‰Đž. + +/// + +### `response_model_include` Ņ‚Đ° `response_model_exclude` + +Ви Ņ‚Đ°ĐēĐžĐļ ĐŧĐžĐļĐĩŅ‚Đĩ виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ¸ *Đ´ĐĩĐēĐžŅ€Đ°Ņ‚ĐžŅ€Đ° ĐžĐŋĐĩŅ€Đ°Ņ†Ņ–Ņ— ҈ĐģŅŅ…Ņƒ* `response_model_include` Ņ‚Đ° `response_model_exclude`. + +ВоĐŊи ĐŋŅ€Đ¸ĐšĐŧĐ°ŅŽŅ‚ŅŒ `set` (ĐŧĐŊĐžĐļиĐŊ҃) Ņ€ŅĐ´ĐēŅ–Đ˛ (`str`) С Ņ–ĐŧĐĩĐŊаĐŧи Đ°Ņ‚Ņ€Đ¸ĐąŅƒŅ‚Ņ–Đ˛, ŅĐēŅ– ĐŋĐžŅ‚Ņ€Ņ–ĐąĐŊĐž вĐēĐģŅŽŅ‡Đ¸Ņ‚Đ¸ (ĐŋŅ€ĐžĐŋ҃ҁĐēĐ°ŅŽŅ‡Đ¸ Ņ–ĐŊŅˆŅ–) айО виĐēĐģŅŽŅ‡Đ¸Ņ‚Đ¸ (вĐēĐģŅŽŅ‡Đ°ŅŽŅ‡Đ¸ Ņ–ĐŊŅˆŅ–). + +ĐĻĐĩ ĐŧĐžĐļĐŊа виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ ŅĐē ŅˆĐ˛Đ¸Đ´ĐēиК ҁĐŋĐžŅŅ–Đą, ŅĐēŅ‰Đž ҃ Đ’Đ°Ņ Ņ” ĐģĐ¸ŅˆĐĩ ОдĐŊа ĐŧОдĐĩĐģҌ Pydantic Ņ– Ви Ņ…ĐžŅ‡ĐĩŅ‚Đĩ видаĐģĐ¸Ņ‚Đ¸ Đ´ĐĩŅĐēŅ– даĐŊŅ– С Đ˛Đ¸Đ˛ĐžĐ´Ņƒ. + +/// tip | ĐŸĐžŅ€Đ°Đ´Đ° + +АĐģĐĩ Đ˛ŅĐĩ Đļ Ņ€ĐĩĐēĐžĐŧĐĩĐŊĐ´ŅƒŅ”Ņ‚ŅŒŅŅ виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ ĐžĐŋĐ¸ŅĐ°ĐŊŅ– Đ˛Đ¸Ņ‰Đĩ ĐŋŅ–Đ´Ņ…ĐžĐ´Đ¸, Ņ–Đˇ ĐˇĐ°ŅŅ‚ĐžŅŅƒĐ˛Đ°ĐŊĐŊŅĐŧ ĐēŅ–ĐģҌĐēĐžŅ… ĐēĐģĐ°ŅŅ–Đ˛, СаĐŧŅ–ŅŅ‚ŅŒ Ņ†Đ¸Ņ… ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Ņ–Đ˛. + + +ĐĻĐĩ Ņ‚ĐžĐŧ҃, Ņ‰Đž JSON Schema, ŅĐēиК ĐŗĐĩĐŊĐĩŅ€ŅƒŅ”Ņ‚ŅŒŅŅ ҃ Đ˛Đ°ŅˆĐžĐŧ҃ OpenAPI Đ´ĐžĐ´Đ°Ņ‚Đē҃ (Ņ– в Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Ņ–Ņ—), Đ˛ŅĐĩ ОдĐŊĐž ĐąŅƒĐ´Đĩ Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´Đ°Ņ‚Đ¸ ĐŋОвĐŊŅ–Đš ĐŧОдĐĩĐģŅ–, ĐŊĐ°Đ˛Ņ–Ņ‚ŅŒ ŅĐēŅ‰Đž Ви виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅ”Ņ‚Đĩ `response_model_include` айО `response_model_exclude` Đ´ĐģŅ виĐēĐģŅŽŅ‡ĐĩĐŊĐŊŅ Đ´ĐĩŅĐēĐ¸Ņ… Đ°Ņ‚Ņ€Đ¸ĐąŅƒŅ‚Ņ–Đ˛. + +ĐĻĐĩ Ņ‚Đ°ĐēĐžĐļ ŅŅ‚ĐžŅŅƒŅ”Ņ‚ŅŒŅŅ `response_model_by_alias`, ŅĐēиК ĐŋŅ€Đ°Ņ†ŅŽŅ” ĐŋĐžĐ´Ņ–ĐąĐŊиĐŧ Ņ‡Đ¸ĐŊĐžĐŧ. + +/// + +{* ../../docs_src/response_model/tutorial005_py310.py hl[29,35] *} + +/// tip | ĐŸĐžŅ€Đ°Đ´Đ° + +ХиĐŊŅ‚Đ°ĐēŅĐ¸Ņ `{"name", "description"}` ŅŅ‚Đ˛ĐžŅ€ŅŽŅ” `set` С Ņ†Đ¸Đŧи двОĐŧа СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅĐŧи. + +Đ’Ņ–ĐŊ ĐĩĐēĐ˛Ņ–Đ˛Đ°ĐģĐĩĐŊŅ‚ĐŊиК `set(["name", "description"])`. + +/// + +#### ВиĐēĐžŅ€Đ¸ŅŅ‚Đ°ĐŊĐŊŅ `list` СаĐŧŅ–ŅŅ‚ŅŒ `set` + +Đ¯ĐēŅ‰Đž Ви ĐˇĐ°ĐąŅƒĐ´ĐĩŅ‚Đĩ виĐēĐžŅ€Đ¸ŅŅ‚Đ°Ņ‚Đ¸ `set` Ņ– ĐŊĐ°Ņ‚ĐžĐŧŅ–ŅŅ‚ŅŒ ĐˇĐ°ŅŅ‚ĐžŅŅƒŅ”Ņ‚Đĩ `list` айО `tuple`, FastAPI Đ˛ŅĐĩ ОдĐŊĐž ĐŋĐĩŅ€ĐĩŅ‚Đ˛ĐžŅ€Đ¸Ņ‚ŅŒ ҆Đĩ ĐŊа `set`, Ņ– Đ˛ŅĐĩ ĐŋŅ€Đ°Ņ†ŅŽĐ˛Đ°Ņ‚Đ¸ĐŧĐĩ ĐŋŅ€Đ°Đ˛Đ¸ĐģҌĐŊĐž: + +{* ../../docs_src/response_model/tutorial006_py310.py hl[29,35] *} + +## ĐŸŅ–Đ´ŅŅƒĐŧĐžĐē + +ВиĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐšŅ‚Đĩ ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ `response_model` *Đ´ĐĩĐēĐžŅ€Đ°Ņ‚ĐžŅ€Đ° ĐžĐŋĐĩŅ€Đ°Ņ†Ņ–Ņ— ҈ĐģŅŅ…Ņƒ*, Ņ‰ĐžĐą виСĐŊĐ°Ņ‡Đ°Ņ‚Đ¸ ĐŧОдĐĩĐģŅ– Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´Ņ–, ĐžŅĐžĐąĐģивО Ņ‰ĐžĐą ĐŗĐ°Ņ€Đ°ĐŊŅ‚ŅƒĐ˛Đ°Ņ‚Đ¸ ҄ҖĐģŅŒŅ‚Ņ€Đ°Ņ†Ņ–ŅŽ ĐŋŅ€Đ¸Đ˛Đ°Ņ‚ĐŊĐ¸Ņ… даĐŊĐ¸Ņ…. + +ВиĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐšŅ‚Đĩ `response_model_exclude_unset`, Ņ‰ĐžĐą ĐŋОвĐĩŅ€Ņ‚Đ°Ņ‚Đ¸ ĐģĐ¸ŅˆĐĩ ŅĐ˛ĐŊĐž Đ˛ŅŅ‚Đ°ĐŊОвĐģĐĩĐŊŅ– СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ. diff --git a/docs/uk/docs/tutorial/response-status-code.md b/docs/uk/docs/tutorial/response-status-code.md new file mode 100644 index 000000000..1ed69d6f2 --- /dev/null +++ b/docs/uk/docs/tutorial/response-status-code.md @@ -0,0 +1,100 @@ +# ĐĄŅ‚Đ°Ņ‚ŅƒŅ ĐēОди Đ’Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´ĐĩĐš + +ĐĸаĐē ŅĐ°ĐŧĐž ŅĐē Ви ĐŧĐžĐļĐĩŅ‚Đĩ вĐēĐ°ĐˇĐ°Ņ‚Đ¸ ĐŧОдĐĩĐģҌ Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´Ņ–, Ви Ņ‚Đ°ĐēĐžĐļ ĐŧĐžĐļĐĩŅ‚Đĩ ĐžĐŗĐžĐģĐžŅĐ¸Ņ‚Đ¸ HTTP ĐēОд ŅŅ‚Đ°Ņ‚ŅƒŅŅƒ Đ´ĐģŅ Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´Ņ– Са Đ´ĐžĐŋĐžĐŧĐžĐŗĐžŅŽ ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ° `status_code` в ĐąŅƒĐ´ŅŒ-ŅĐēŅ–Đš С *ĐžĐŋĐĩŅ€Đ°Ņ†Ņ–Đš ҈ĐģŅŅ…Ņƒ*: + +* `@app.get()` +* `@app.post()` +* `@app.put()` +* `@app.delete()` +* Ņ‚ĐžŅ‰Đž. + +{* ../../docs_src/response_status_code/tutorial001.py hl[6] *} + +/// note | ĐĐžŅ‚Đ°Ņ‚Đēа + +ЗвĐĩŅ€ĐŊŅ–Ņ‚ŅŒ ŅƒĐ˛Đ°ĐŗŅƒ, Ņ‰Đž `status_code` Ņ” ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€ĐžĐŧ ĐŧĐĩŅ‚ĐžĐ´Ņƒ "Đ´ĐĩĐēĐžŅ€Đ°Ņ‚ĐžŅ€Đ°" (`get`, `post` Ņ– Ņ‚.Đ´.), а ĐŊĐĩ Đ’Đ°ŅˆĐžŅ— *Ņ„ŅƒĐŊĐē҆Җҗ ĐžĐŋĐĩŅ€Đ°Ņ†Ņ–Ņ— ҈ĐģŅŅ…Ņƒ*, ŅĐē ŅƒŅŅ– Ņ–ĐŊŅˆŅ– ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ¸ Ņ‚Đ° ҂ҖĐģĐž СаĐŋĐ¸Ņ‚Ņƒ. + +/// + +ĐŸĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ `status_code` ĐŋŅ€Đ¸ĐšĐŧĐ°Ņ” Ņ‡Đ¸ŅĐģĐž, ŅĐēĐĩ Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´Đ°Ņ” HTTP ĐēĐžĐ´Ņƒ ŅŅ‚Đ°Ņ‚ŅƒŅŅƒ. + +/// info | ІĐŊŅ„ĐžŅ€ĐŧĐ°Ņ†Ņ–Ņ +`status_code` Ņ‚Đ°ĐēĐžĐļ ĐŧĐžĐļĐĩ ĐžŅ‚Ņ€Đ¸ĐŧŅƒĐ˛Đ°Ņ‚Đ¸ СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ С `IntEnum`, ĐŊаĐŋŅ€Đ¸ĐēĐģад, С Python `http.HTTPStatus`. + +/// + +Đ’Ņ–ĐŊ ĐąŅƒĐ´Đĩ: + +* ПовĐĩŅ€Ņ‚Đ°Ņ‚Đ¸ вĐēаСаĐŊиК ĐēОд ŅŅ‚Đ°Ņ‚ŅƒŅŅƒ ҃ Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´Ņ–. +* ДоĐē҃ĐŧĐĩĐŊŅ‚ŅƒĐ˛Đ°Ņ‚Đ¸ ĐšĐžĐŗĐž ŅĐē Ņ‚Đ°ĐēиК ҃ ҁ҅ĐĩĐŧŅ– OpenAPI (Ņ–, Ņ‚Đ°ĐēиĐŧ Ņ‡Đ¸ĐŊĐžĐŧ, в Ņ–ĐŊŅ‚ĐĩҀ҄ĐĩĐšŅŅ– ĐēĐžŅ€Đ¸ŅŅ‚ŅƒĐ˛Đ°Ņ‡Đ°): + + + +/// note | ĐĐžŅ‚Đ°Ņ‚Đēа + +ДĐĩŅĐēŅ– ĐēОди Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´Ņ– (див. ĐŊĐ°ŅŅ‚ŅƒĐŋĐŊиК Ņ€ĐžĐˇĐ´Ņ–Đģ) вĐēĐ°ĐˇŅƒŅŽŅ‚ŅŒ, Ņ‰Đž Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´ŅŒ ĐŊĐĩ ĐŧĐ°Ņ” ҂ҖĐģа. + +FastAPI СĐŊĐ°Ņ” ĐŋŅ€Đž ҆Đĩ Ņ– ŅŅ‚Đ˛ĐžŅ€Đ¸Ņ‚ŅŒ OpenAPI Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Ņ–ŅŽ, ŅĐēа вĐēĐ°ĐˇŅƒŅ”, Ņ‰Đž ҂ҖĐģа Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´Ņ– ĐŊĐĩĐŧĐ°Ņ”. + +/// + +## ĐŸŅ€Đž HTTP ŅŅ‚Đ°Ņ‚ŅƒŅ ĐēОди + +/// note | ĐĐžŅ‚Đ°Ņ‚Đēа + +Đ¯ĐēŅ‰Đž Ви вĐļĐĩ СĐŊĐ°Ņ”Ņ‚Đĩ, Ņ‰Đž Ņ‚Đ°ĐēĐĩ HTTP ĐēОди ŅŅ‚Đ°Ņ‚ŅƒŅŅƒ, ĐŋĐĩŅ€ĐĩŅ…ĐžĐ´ŅŒŅ‚Đĩ Đ´Đž ĐŊĐ°ŅŅ‚ŅƒĐŋĐŊĐžĐŗĐž Ņ€ĐžĐˇĐ´Ņ–Đģ҃. + +/// + +В HTTP Ви ĐŊĐ°Đ´ŅĐ¸ĐģĐ°Ņ”Ņ‚Đĩ Ņ‡Đ¸ŅĐģОвиК ĐēОд ŅŅ‚Đ°Ņ‚ŅƒŅŅƒ С 3 Ņ†Đ¸Ņ„Ņ€ ŅĐē Ņ‡Đ°ŅŅ‚Đ¸ĐŊ҃ Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´Ņ–. + +ĐĻŅ– ĐēОди ŅŅ‚Đ°Ņ‚ŅƒŅŅƒ ĐŧĐ°ŅŽŅ‚ŅŒ ĐŋĐžĐ˛â€™ŅĐˇĐ°ĐŊ҃ ĐŊĐ°ĐˇĐ˛Ņƒ Đ´ĐģŅ Ņ—Ņ… Ņ€ĐžĐˇĐŋŅ–ĐˇĐŊаваĐŊĐŊŅ, аĐģĐĩ ĐŊаКваĐļĐģĐ¸Đ˛Ņ–ŅˆĐžŅŽ Ņ‡Đ°ŅŅ‚Đ¸ĐŊĐžŅŽ Ņ” ŅĐ°ĐŧĐĩ Ņ‡Đ¸ŅĐģĐž. + +ĐšĐžŅ€ĐžŅ‚ĐēĐž: + +* **`100 - 199`** "ІĐŊŅ„ĐžŅ€ĐŧĐ°Ņ†Ņ–ĐšĐŊŅ–" Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´Ņ–. Ви Ņ€Ņ–Đ´ĐēĐž виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅ”Ņ‚Đĩ Ņ—Ņ… ĐŊаĐŋŅ€ŅĐŧ҃. Đ’Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´Ņ– С Ņ‚Đ°ĐēиĐŧи ĐēОдаĐŧи ĐŊĐĩ ĐŧĐžĐļŅƒŅ‚ŅŒ ĐŧĐ°Ņ‚Đ¸ ҂ҖĐģа. +* **`200 - 299`** "ĐŖŅĐŋŅ–ŅˆĐŊŅ–" Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´Ņ–. ĐĻĐĩ ҂Җ, ŅĐēŅ– Ви виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ĐŧĐĩŅ‚Đĩ ĐŊĐ°ĐšŅ‡Đ°ŅŅ‚Ņ–ŅˆĐĩ. + * `200` - ĐēОд Са СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ, ŅĐēиК ОСĐŊĐ°Ņ‡Đ°Ņ”, Ņ‰Đž Đ˛ŅĐĩ ĐŋŅ€ĐžĐšŅˆĐģĐž "OK". + * ІĐŊŅˆĐ¸Đš ĐŋŅ€Đ¸ĐēĐģад – `201`, "Created" (ŅŅ‚Đ˛ĐžŅ€ĐĩĐŊĐž). Đ™ĐžĐŗĐž ĐˇĐ°ĐˇĐ˛Đ¸Ņ‡Đ°Đš виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅŽŅ‚ŅŒ ĐŋҖҁĐģŅ ŅŅ‚Đ˛ĐžŅ€ĐĩĐŊĐŊŅ ĐŊĐžĐ˛ĐžĐŗĐž СаĐŋĐ¸ŅŅƒ в ĐąĐ°ĐˇŅ– даĐŊĐ¸Ņ…. + * ĐžŅĐžĐąĐģивиК виĐŋадОĐē – `204`, "No Content" (ĐŊĐĩĐŧĐ°Ņ” вĐŧŅ–ŅŅ‚Ņƒ). ĐĻŅ Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´ŅŒ виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅ”Ņ‚ŅŒŅŅ, ĐēĐžĐģи ĐŊĐĩĐŧĐ°Ņ” даĐŊĐ¸Ņ… Đ´ĐģŅ ĐŋОвĐĩŅ€ĐŊĐĩĐŊĐŊŅ ĐēĐģŅ–Ņ”ĐŊŅ‚Ņƒ, Ņ‚ĐžĐŧ҃ Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´ŅŒ ĐŊĐĩ ĐŋОвиĐŊĐŊа ĐŧĐ°Ņ‚Đ¸ ҂ҖĐģа. +* **`300 - 399`** "ПĐĩŅ€ĐĩĐŊаĐŋŅ€Đ°Đ˛ĐģĐĩĐŊĐŊŅ". Đ’Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´Ņ– С Ņ†Đ¸Đŧи ĐēОдаĐŧи ĐŧĐžĐļŅƒŅ‚ŅŒ ĐŧĐ°Ņ‚Đ¸ айО ĐŊĐĩ ĐŧĐ°Ņ‚Đ¸ ҂ҖĐģа, Са виĐŊŅŅ‚ĐēĐžĐŧ `304`, "Not Modified" (ĐŊĐĩ СĐŧŅ–ĐŊĐĩĐŊĐž), ŅĐēа ĐŊĐĩ ĐŋОвиĐŊĐŊа ĐŧĐ°Ņ‚Đ¸ ҂ҖĐģа. +* **`400 - 499`** "ПоĐŧиĐģĐēа ĐēĐģŅ–Ņ”ĐŊŅ‚Đ°". ĐĻĐĩ Đ´Ņ€ŅƒĐŗĐ¸Đš Ņ‚Đ¸Đŋ, ŅĐēиК Ви, ĐšĐŧĐžĐ˛Ņ–Ņ€ĐŊĐž, ĐąŅƒĐ´ĐĩŅ‚Đĩ виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ ĐŊĐ°ĐšŅ‡Đ°ŅŅ‚Ņ–ŅˆĐĩ. + * ĐŸŅ€Đ¸ĐēĐģад `404`, "Not Found" (ĐŊĐĩ СĐŊаКдĐĩĐŊĐž). + * ДĐģŅ ĐˇĐ°ĐŗĐ°ĐģҌĐŊĐ¸Ņ… ĐŋĐžĐŧиĐģĐžĐē ĐēĐģŅ–Ņ”ĐŊŅ‚Đ° ĐŧĐžĐļĐŊа виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ `400`. +* `500 - 599` "ПоĐŧиĐģĐēи ҁĐĩŅ€Đ˛ĐĩŅ€Đ°". Ви ĐŧаКĐļĐĩ ĐŊŅ–ĐēĐžĐģи ĐŊĐĩ виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅ”Ņ‚Đĩ Ņ—Ņ… ĐŊаĐŋŅ€ŅĐŧ҃. Đ¯ĐēŅ‰Đž в ĐēĐžĐ´Ņ– Đ’Đ°ŅˆĐžĐŗĐž ĐˇĐ°ŅŅ‚ĐžŅŅƒĐŊĐē҃ айО ĐŊа ҁĐĩŅ€Đ˛ĐĩҀҖ Ņ‰ĐžŅŅŒ ĐŋŅ–ŅˆĐģĐž ĐŊĐĩ Ņ‚Đ°Đē, Đ°Đ˛Ņ‚ĐžĐŧĐ°Ņ‚Đ¸Ņ‡ĐŊĐž ĐąŅƒĐ´Đĩ ĐŋОвĐĩŅ€ĐŊĐĩĐŊĐž ОдиĐŊ Ņ–Đˇ Ņ†Đ¸Ņ… ĐēĐžĐ´Ņ–Đ˛ ŅŅ‚Đ°Ņ‚ŅƒŅŅƒ. + +/// tip | ĐŸĐžŅ€Đ°Đ´Đ° + +ЊОй Đ´Ņ–ĐˇĐŊĐ°Ņ‚Đ¸ŅŅ ĐąŅ–ĐģҌ҈Đĩ ĐŋŅ€Đž ĐēĐžĐļĐĩĐŊ ĐēОд ŅŅ‚Đ°Ņ‚ŅƒŅŅƒ Ņ– ĐŋŅ€Đ¸ĐˇĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ ĐēĐžĐļĐŊĐžĐŗĐž С ĐŊĐ¸Ņ…, ĐŋĐĩŅ€ĐĩĐŗĐģŅĐŊŅŒŅ‚Đĩ Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Ņ–ŅŽ MDN ĐŋŅ€Đž HTTP ĐēОди ŅŅ‚Đ°Ņ‚ŅƒŅŅƒ. + +/// + +## ЛĐĩĐŗĐēиК ҁĐŋĐžŅŅ–Đą СаĐŋаĐŧ'ŅŅ‚Đ°Ņ‚Đ¸ ĐŊаСви + +Đ ĐžĐˇĐŗĐģŅĐŊĐĩĐŧĐž ҉Đĩ Ņ€Đ°Đˇ ĐŋĐžĐŋĐĩŅ€ĐĩĐ´ĐŊŅ–Đš ĐŋŅ€Đ¸ĐēĐģад: + +{* ../../docs_src/response_status_code/tutorial001.py hl[6] *} + +`201` - ҆Đĩ ĐēОд ŅŅ‚Đ°Ņ‚ŅƒŅŅƒ Đ´ĐģŅ "Created" (ŅŅ‚Đ˛ĐžŅ€ĐĩĐŊĐž). + +АĐģĐĩ ВаĐŧ ĐŊĐĩ ĐŋĐžŅ‚Ņ€Ņ–ĐąĐŊĐž СаĐŋаĐŧ'ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸, Ņ‰Đž ОСĐŊĐ°Ņ‡Đ°Ņ” ĐēĐžĐļĐĩĐŊ Ņ–Đˇ Ņ†Đ¸Ņ… ĐēĐžĐ´Ņ–Đ˛. + +Ви ĐŧĐžĐļĐĩŅ‚Đĩ виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ ĐˇŅ€ŅƒŅ‡ĐŊŅ– СĐŧŅ–ĐŊĐŊŅ– С `fastapi.status` + +{* ../../docs_src/response_status_code/tutorial002.py hl[1,6] *} + +ĐĻŅ– СĐŧŅ–ĐŊĐŊŅ– ĐŋŅ€ĐžŅŅ‚Đž Đ´ĐģŅ ĐˇŅ€ŅƒŅ‡ĐŊĐžŅŅ‚Ņ–. ВоĐŊи ĐŧŅ–ŅŅ‚ŅŅ‚ŅŒ ҂Җ Đļ ŅĐ°ĐŧŅ– Ņ‡Đ¸ŅĐģа, аĐģĐĩ Ви ĐŧĐžĐļĐĩŅ‚Đĩ ҁĐēĐžŅ€Đ¸ŅŅ‚Đ°Ņ‚Đ¸ŅŅ Đ°Đ˛Ņ‚ĐžĐˇĐ°ĐŋОвĐŊĐĩĐŊĐŊŅĐŧ в Ņ€ĐĩдаĐēŅ‚ĐžŅ€Ņ–: + + + +/// note | ĐĸĐĩŅ…ĐŊҖ҇ĐŊŅ– Đ´ĐĩŅ‚Đ°ĐģŅ– + +Ви Ņ‚Đ°ĐēĐžĐļ ĐŧĐžĐļĐĩŅ‚Đĩ виĐēĐžŅ€Đ¸ŅŅ‚Đ°Ņ‚Đ¸ `from starlette import status`. + +**FastAPI** ĐŊĐ°Đ´Đ°Ņ” ҂Җ Đļ ŅĐ°ĐŧŅ– СĐŧŅ–ĐŊĐŊŅ– `starlette.status` ŅĐē `fastapi.status`, ĐŋŅ€ĐžŅŅ‚Đž Đ´ĐģŅ ĐˇŅ€ŅƒŅ‡ĐŊĐžŅŅ‚Ņ– Ņ€ĐžĐˇŅ€ĐžĐąĐŊиĐēа. ОдĐŊаĐē вОĐŊи ĐŋĐžŅ…ĐžĐ´ŅŅ‚ŅŒ ĐąĐĩСĐŋĐžŅĐĩŅ€ĐĩĐ´ĐŊŅŒĐž ĐˇŅ– Starlette. + +/// + +## ЗĐŧŅ–ĐŊа СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ Са СаĐŧĐžĐ˛Ņ‡ŅƒĐ˛Đ°ĐŊĐŊŅĐŧ + +ДаĐģŅ–, ҃ ĐŸĐžŅŅ–ĐąĐŊиĐē҃ Đ´ĐģŅ Đ´ĐžŅĐ˛Ņ–Đ´Ņ‡ĐĩĐŊĐ¸Ņ… ĐēĐžŅ€Đ¸ŅŅ‚ŅƒĐ˛Đ°Ņ‡Ņ–Đ˛{.internal-link target=_blank}, Ви Đ´Ņ–ĐˇĐŊĐ°Ņ”Ņ‚ĐĩҁҌ, ŅĐē ĐŋОвĐĩŅ€ĐŊŅƒŅ‚Đ¸ Ņ–ĐŊŅˆĐ¸Đš ĐēОд ŅŅ‚Đ°Ņ‚ŅƒŅŅƒ, ĐŊŅ–Đļ Ņ‚ĐžĐš, ŅĐēиК Ви ĐžĐŗĐžĐģĐžŅĐ¸Đģи Ņ‚ŅƒŅ‚. diff --git a/docs/uk/docs/tutorial/schema-extra-example.md b/docs/uk/docs/tutorial/schema-extra-example.md new file mode 100644 index 000000000..853fd5e65 --- /dev/null +++ b/docs/uk/docs/tutorial/schema-extra-example.md @@ -0,0 +1,222 @@ +# ДĐĩĐēĐģĐ°Ņ€ŅƒĐ˛Đ°ĐŊĐŊŅ ĐŋŅ€Đ¸ĐēĐģĐ°Đ´Ņ–Đ˛ Đ˛Ņ…Ņ–Đ´ĐŊĐ¸Ņ… даĐŊĐ¸Ņ… + +Ви ĐŧĐžĐļĐĩŅ‚Đĩ ĐˇĐ°Đ´Đ°Ņ‚Đ¸ ĐŋŅ€Đ¸ĐēĐģади даĐŊĐ¸Ņ…, ŅĐēŅ– Đ’Đ°Ņˆ ĐˇĐ°ŅŅ‚ĐžŅŅƒĐŊĐžĐē ĐŧĐžĐļĐĩ ĐžŅ‚Ņ€Đ¸ĐŧŅƒĐ˛Đ°Ņ‚Đ¸. + +ĐžŅŅŒ ĐēŅ–ĐģҌĐēа ҁĐŋĐžŅĐžĐąŅ–Đ˛, ŅĐē ҆Đĩ ĐˇŅ€ĐžĐąĐ¸Ņ‚Đ¸. + +## Đ”ĐžĐ´Đ°Ņ‚ĐēĐžĐ˛Ņ– даĐŊŅ– JSON-ҁ҅ĐĩĐŧи в ĐŧОдĐĩĐģŅŅ… Pydantic + +Ви ĐŧĐžĐļĐĩŅ‚Đĩ ĐˇĐ°Đ´Đ°Ņ‚Đ¸ `examples` Đ´ĐģŅ ĐŧОдĐĩĐģŅ– Pydantic, ŅĐēŅ– ĐąŅƒĐ´Đĩ дОдаĐŊĐž Đ´Đž ĐˇĐŗĐĩĐŊĐĩŅ€ĐžĐ˛Đ°ĐŊĐžŅ— JSON-ҁ҅ĐĩĐŧи. + +//// tab | Pydantic v2 + +{* ../../docs_src/schema_extra_example/tutorial001_py310.py hl[13:24] *} + +//// + +//// tab | Pydantic v1 + +{* ../../docs_src/schema_extra_example/tutorial001_pv1_py310.py hl[13:23] *} + +//// + +ĐĻŅ Đ´ĐžĐ´Đ°Ņ‚ĐēОва Ņ–ĐŊŅ„ĐžŅ€ĐŧĐ°Ņ†Ņ–Ņ ĐąŅƒĐ´Đĩ дОдаĐŊа ŅĐē Ņ” Đ´Đž **JSON-ҁ҅ĐĩĐŧи**, Ņ– вОĐŊа ĐąŅƒĐ´Đĩ виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ŅŅ в Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Ņ–Ņ— Đ´Đž API. + +//// tab | Pydantic v2 + +ĐŖ вĐĩҀҁҖҗ Pydantic 2 виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅ”Ņ‚ŅŒŅŅ Đ°Ņ‚Ņ€Đ¸ĐąŅƒŅ‚ `model_config`, ŅĐēиК ĐŋŅ€Đ¸ĐšĐŧĐ°Ņ” `dict`, ŅĐē ĐžĐŋĐ¸ŅĐ°ĐŊĐž в Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Ņ–Ņ— Pydantic: КоĐŊŅ„Ņ–ĐŗŅƒŅ€Đ°Ņ†Ņ–Ņ. + +Ви ĐŧĐžĐļĐĩŅ‚Đĩ Đ˛ŅŅ‚Đ°ĐŊĐžĐ˛Đ¸Ņ‚Đ¸ `"json_schema_extra"` ŅĐē `dict`, Ņ‰Đž ĐŧŅ–ŅŅ‚Đ¸Ņ‚ŅŒ ĐąŅƒĐ´ŅŒ-ŅĐēŅ– Đ´ĐžĐ´Đ°Ņ‚ĐēĐžĐ˛Ņ– даĐŊŅ–, ŅĐēŅ– Ви Ņ…ĐžŅ‡ĐĩŅ‚Đĩ Đ˛Ņ–Đ´ĐžĐąŅ€Đ°ĐˇĐ¸Ņ‚Đ¸ ҃ ĐˇĐŗĐĩĐŊĐĩŅ€ĐžĐ˛Đ°ĐŊŅ–Đš JSON-ҁ҅ĐĩĐŧŅ–, вĐēĐģŅŽŅ‡Đ°ŅŽŅ‡Đ¸ `examples`. + +//// + +//// tab | Pydantic v1 + +ĐŖ вĐĩҀҁҖҗ Pydantic 1 виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅ”Ņ‚ŅŒŅŅ вĐŊŅƒŅ‚Ņ€Ņ–ŅˆĐŊŅ–Đš ĐēĐģĐ°Ņ `Config` Ņ– ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ `schema_extra`, ŅĐē ĐžĐŋĐ¸ŅĐ°ĐŊĐž в Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Ņ–Ņ— Pydantic: НаĐģĐ°ŅˆŅ‚ŅƒĐ˛Đ°ĐŊĐŊŅ ҁ҅ĐĩĐŧи. + +Ви ĐŧĐžĐļĐĩŅ‚Đĩ ĐˇĐ°Đ´Đ°Ņ‚Đ¸ `schema_extra` ŅĐē `dict`, Ņ‰Đž ĐŧŅ–ŅŅ‚Đ¸Ņ‚ŅŒ ĐąŅƒĐ´ŅŒ-ŅĐēŅ– Đ´ĐžĐ´Đ°Ņ‚ĐēĐžĐ˛Ņ– даĐŊŅ–, ŅĐēŅ– Ви Ņ…ĐžŅ‡ĐĩŅ‚Đĩ ĐąĐ°Ņ‡Đ¸Ņ‚Đ¸ ҃ ĐˇĐŗĐĩĐŊĐĩŅ€ĐžĐ˛Đ°ĐŊŅ–Đš JSON-ҁ҅ĐĩĐŧŅ–, вĐēĐģŅŽŅ‡Đ°ŅŽŅ‡Đ¸ `examples`. + +//// + +/// tip | ĐŸŅ–Đ´ĐēаСĐēа + +Ви ĐŧĐžĐļĐĩŅ‚Đĩ виĐēĐžŅ€Đ¸ŅŅ‚Đ°Ņ‚Đ¸ Ņ‚Ņƒ Đļ Ņ‚ĐĩŅ…ĐŊŅ–Đē҃, Ņ‰ĐžĐą Ņ€ĐžĐˇŅˆĐ¸Ņ€Đ¸Ņ‚Đ¸ JSON-ҁ҅ĐĩĐŧ҃ Ņ– Đ´ĐžĐ´Đ°Ņ‚Đ¸ вĐģĐ°ŅĐŊ҃ Đ´ĐžĐ´Đ°Ņ‚ĐēĐžĐ˛Ņƒ Ņ–ĐŊŅ„ĐžŅ€ĐŧĐ°Ņ†Ņ–ŅŽ. + +НаĐŋŅ€Đ¸ĐēĐģад, Ви ĐŧĐžĐļĐĩŅ‚Đĩ виĐēĐžŅ€Đ¸ŅŅ‚Đ°Ņ‚Đ¸ Ņ—Ņ— Đ´ĐģŅ дОдаваĐŊĐŊŅ ĐŧĐĩŅ‚Đ°Đ´Đ°ĐŊĐ¸Ņ… Đ´ĐģŅ Ņ–ĐŊŅ‚ĐĩҀ҄ĐĩĐšŅŅƒ ĐēĐžŅ€Đ¸ŅŅ‚ŅƒĐ˛Đ°Ņ‡Đ° ĐŊа Ņ„Ņ€ĐžĐŊŅ‚ĐĩĐŊĐ´Ņ– Ņ‚ĐžŅ‰Đž. + +/// + +/// info | ІĐŊŅ„ĐžŅ€ĐŧĐ°Ņ†Ņ–Ņ + +OpenAPI 3.1.0 (ŅĐēиК виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅ”Ņ‚ŅŒŅŅ ĐŋĐžŅ‡Đ¸ĐŊĐ°ŅŽŅ‡Đ¸ С FastAPI 0.99.0) дОдав ĐŋŅ–Đ´Ņ‚Ņ€Đ¸ĐŧĐē҃ `examples`, Ņ‰Đž Ņ” Ņ‡Đ°ŅŅ‚Đ¸ĐŊĐžŅŽ ŅŅ‚Đ°ĐŊĐ´Đ°Ņ€Ņ‚Ņƒ **JSON-ҁ҅ĐĩĐŧи**. + +До Ņ†ŅŒĐžĐŗĐž ĐŋŅ–Đ´Ņ‚Ņ€Đ¸ĐŧŅƒĐ˛Đ°Đ˛ŅŅ ĐģĐ¸ŅˆĐĩ ĐēĐģŅŽŅ‡ `example` С ОдĐŊиĐŧ ĐŋŅ€Đ¸ĐēĐģадОĐŧ. Đ’Ņ–ĐŊ Đ˛ŅĐĩ ҉Đĩ ĐŋŅ–Đ´Ņ‚Ņ€Đ¸ĐŧŅƒŅ”Ņ‚ŅŒŅŅ в OpenAPI 3.1.0, аĐģĐĩ Ņ” ĐˇĐ°ŅŅ‚Đ°Ņ€Ņ–ĐģиĐŧ Ņ– ĐŊĐĩ Đ˛Ņ…ĐžĐ´Đ¸Ņ‚ŅŒ Đ´Đž ŅŅ‚Đ°ĐŊĐ´Đ°Ņ€Ņ‚Ņƒ JSON Schema. ĐĸĐžĐŧ҃ Ņ€ĐĩĐēĐžĐŧĐĩĐŊĐ´ŅƒŅ”Ņ‚ŅŒŅŅ ĐŋĐĩŅ€ĐĩĐšŅ‚Đ¸ С `example` ĐŊа `examples`. 🤓 + +Đ‘Ņ–ĐģҌ҈Đĩ ĐŋŅ€Đž ҆Đĩ ĐŧĐžĐļĐŊа ĐŋŅ€ĐžŅ‡Đ¸Ņ‚Đ°Ņ‚Đ¸ в ĐēŅ–ĐŊ҆Җ ҆ҖҔҗ ŅŅ‚ĐžŅ€Ņ–ĐŊĐēи. + +/// + +## Đ”ĐžĐ´Đ°Ņ‚ĐēĐžĐ˛Ņ– Đ°Ņ€ĐŗŅƒĐŧĐĩĐŊŅ‚Đ¸ `Field` + +КоĐģи ви виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅ”Ņ‚Đĩ `Field()` ҃ ĐŧОдĐĩĐģŅŅ… Pydantic, Ви Ņ‚Đ°ĐēĐžĐļ ĐŧĐžĐļĐĩŅ‚Đĩ вĐēĐ°ĐˇĐ°Ņ‚Đ¸ Đ´ĐžĐ´Đ°Ņ‚ĐēĐžĐ˛Ņ– `examples`: + +{* ../../docs_src/schema_extra_example/tutorial002_py310.py hl[2,8:11] *} + +## `examples` ҃ JSON-ҁ҅ĐĩĐŧŅ– — OpenAPI + +ĐŸŅ€Đ¸ виĐēĐžŅ€Đ¸ŅŅ‚Đ°ĐŊĐŊŅ– ĐąŅƒĐ´ŅŒ-ĐēĐžĐŗĐž С ĐŊĐ°ŅŅ‚ŅƒĐŋĐŊĐžĐŗĐž: + +* `Path()` +* `Query()` +* `Header()` +* `Cookie()` +* `Body()` +* `Form()` +* `File()` + +Ви Ņ‚Đ°ĐēĐžĐļ ĐŧĐžĐļĐĩŅ‚Đĩ ĐˇĐ°Đ´Đ°Ņ‚Đ¸ ĐŊĐ°ĐąŅ–Ņ€ `examples` С Đ´ĐžĐ´Đ°Ņ‚ĐēĐžĐ˛ĐžŅŽ Ņ–ĐŊŅ„ĐžŅ€ĐŧĐ°Ņ†Ņ–Ņ”ŅŽ, ŅĐēа ĐąŅƒĐ´Đĩ дОдаĐŊа Đ´Đž Ņ—Ņ…ĐŊŅ–Ņ… **JSON-ҁ҅ĐĩĐŧ** ҃ **OpenAPI**. + +### `Body` С `examples` + +ĐĸŅƒŅ‚ Đŧи ĐŋĐĩŅ€ĐĩĐ´Đ°Ņ”ĐŧĐž `examples`, ŅĐēŅ– ĐŧŅ–ŅŅ‚ŅŅ‚ŅŒ ОдиĐŊ ĐŋŅ€Đ¸ĐēĐģад ĐžŅ‡Ņ–ĐēŅƒĐ˛Đ°ĐŊĐ¸Ņ… даĐŊĐ¸Ņ… ҃ `Body()`: + +{* ../../docs_src/schema_extra_example/tutorial003_an_py310.py hl[22:29] *} + +### ĐŸŅ€Đ¸ĐēĐģад ҃ UI Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Ņ–Ņ— + +За Đ´ĐžĐŋĐžĐŧĐžĐŗĐžŅŽ ĐąŅƒĐ´ŅŒ-ŅĐēĐžĐŗĐž С ĐŊавĐĩĐ´ĐĩĐŊĐ¸Ņ… Đ˛Đ¸Ņ‰Đĩ ĐŧĐĩŅ‚ĐžĐ´Ņ–Đ˛ ҆Đĩ Đ˛Đ¸ĐŗĐģŅĐ´Đ°Ņ‚Đ¸ĐŧĐĩ Ņ‚Đ°Đē ҃ Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Ņ–Ņ— Са `/docs`: + + + +### `Body` С ĐēŅ–ĐģҌĐēĐžĐŧа `examples` + +Đ—Đ˛Đ¸Ņ‡Đ°ĐšĐŊĐž, Ви Ņ‚Đ°ĐēĐžĐļ ĐŧĐžĐļĐĩŅ‚Đĩ ĐŋĐĩŅ€ĐĩĐ´Đ°Ņ‚Đ¸ ĐēŅ–ĐģҌĐēа `examples`: + +{* ../../docs_src/schema_extra_example/tutorial004_an_py310.py hl[23:38] *} + +КоĐģи Ви ҆Đĩ Ņ€ĐžĐąĐ¸Ņ‚Đĩ, ĐŋŅ€Đ¸ĐēĐģади ĐąŅƒĐ´ŅƒŅ‚ŅŒ Ņ‡Đ°ŅŅ‚Đ¸ĐŊĐžŅŽ вĐŊŅƒŅ‚Ņ€Ņ–ŅˆĐŊŅŒĐžŅ— **JSON-ҁ҅ĐĩĐŧи** Đ´ĐģŅ Ņ†Đ¸Ņ… даĐŊĐ¸Ņ…. + +Đ’Ņ‚Ņ–Đŧ, ĐŊа ĐŧĐžĐŧĐĩĐŊŅ‚ ĐŊаĐŋĐ¸ŅĐ°ĐŊĐŊŅ Ņ†ŅŒĐžĐŗĐž (26 ҁĐĩŅ€ĐŋĐŊŅ 2023), Swagger UI — Ņ–ĐŊŅŅ‚Ņ€ŅƒĐŧĐĩĐŊŅ‚, ŅĐēиК Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´Đ°Ņ” Са Đ˛Ņ–Đ´ĐžĐąŅ€Đ°ĐļĐĩĐŊĐŊŅ UI Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Ņ–Ņ— — ĐŊĐĩ ĐŋŅ–Đ´Ņ‚Ņ€Đ¸ĐŧŅƒŅ” ĐŋĐžĐēаС ĐēŅ–ĐģҌĐēĐžŅ… ĐŋŅ€Đ¸ĐēĐģĐ°Đ´Ņ–Đ˛ ҃ **JSON-ҁ҅ĐĩĐŧи**. АĐģĐĩ ĐŊиĐļ҇Đĩ ĐŧĐžĐļĐŊа ĐŋŅ€ĐžŅ‡Đ¸Ņ‚Đ°Ņ‚Đ¸ ĐŋŅ€Đž ĐžĐąŅ…Ņ–Đ´ĐŊиК ҈ĐģŅŅ…. + +### ĐĄĐŋĐĩŅ†Đ¸Ņ„Ņ–Ņ‡ĐŊŅ– Đ´ĐģŅ OpenAPI `examples` + +ĐŠĐĩ Đ´Đž Ņ‚ĐžĐŗĐž, ŅĐē **JSON-ҁ҅ĐĩĐŧа** ĐŋĐžŅ‡Đ°Đģа ĐŋŅ–Đ´Ņ‚Ņ€Đ¸ĐŧŅƒĐ˛Đ°Ņ‚Đ¸ `examples`, OpenAPI вĐļĐĩ ĐŧаĐģа ĐŋŅ–Đ´Ņ‚Ņ€Đ¸ĐŧĐē҃ ĐŋĐžĐģŅ С Ņ‚Đ°ĐēĐžŅŽ Đļ ĐŊĐ°ĐˇĐ˛ĐžŅŽ — `examples`. + +ĐĻĐĩ **ҁĐŋĐĩŅ†Đ¸Ņ„Ņ–Ņ‡ĐŊĐĩ Đ´ĐģŅ OpenAPI** ĐŋĐžĐģĐĩ `examples` Ņ€ĐžĐˇĐŧŅ–Ņ‰ŅƒŅ”Ņ‚ŅŒŅŅ в Ņ–ĐŊŅˆŅ–Đš Ņ‡Đ°ŅŅ‚Đ¸ĐŊŅ– ҁĐŋĐĩŅ†Đ¸Ņ„Ņ–ĐēĐ°Ņ†Ņ–Ņ— OpenAPI — ҃ **Đ´ĐĩŅ‚Đ°ĐģŅŅ… ĐēĐžĐļĐŊĐžŅ— *ĐžĐŋĐĩŅ€Đ°Ņ†Ņ–Ņ— ҈ĐģŅŅ…Ņƒ***, а ĐŊĐĩ Đ˛ŅĐĩŅ€ĐĩдиĐŊŅ– ŅĐ°ĐŧĐžŅ— JSON-ҁ҅ĐĩĐŧи. + +Swagger UI вĐļĐĩ давĐŊĐž ĐŋŅ–Đ´Ņ‚Ņ€Đ¸ĐŧŅƒŅ” ҆Đĩ ĐŋĐžĐģĐĩ `examples`. ĐĸĐžĐŧ҃ Ви ĐŧĐžĐļĐĩŅ‚Đĩ виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ ĐšĐžĐŗĐž, Ņ‰ĐžĐą **Đ˛Ņ–Đ´ĐžĐąŅ€Đ°ĐļĐ°Ņ‚Đ¸** ĐēŅ–ĐģҌĐēа **ĐŋŅ€Đ¸ĐēĐģĐ°Đ´Ņ–Đ˛ ҃ Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Ņ–Ņ—**. + +ĐĻĐĩ ĐŋĐžĐģĐĩ `examples` ҃ ҁĐŋĐĩŅ†Đ¸Ņ„Ņ–ĐēĐ°Ņ†Ņ–Ņ— OpenAPI — ҆Đĩ `dict` (ҁĐģОвĐŊиĐē) С **ĐēŅ–ĐģҌĐēĐžĐŧа ĐŋŅ€Đ¸ĐēĐģадаĐŧи** (а ĐŊĐĩ ҁĐŋĐ¸ŅĐžĐē `list`), ĐēĐžĐļĐĩĐŊ Ņ–Đˇ ŅĐēĐ¸Ņ… ĐŧĐžĐļĐĩ ĐŧŅ–ŅŅ‚Đ¸Ņ‚Đ¸ Đ´ĐžĐ´Đ°Ņ‚ĐēĐžĐ˛Ņƒ Ņ–ĐŊŅ„ĐžŅ€ĐŧĐ°Ņ†Ņ–ŅŽ, Ņ‰Đž ĐąŅƒĐ´Đĩ дОдаĐŊа Đ´Đž **OpenAPI**. + +ВоĐŊĐž ĐŊĐĩ вĐēĐģŅŽŅ‡Đ°Ņ”Ņ‚ŅŒŅŅ Đ´Đž JSON Schema ĐēĐžĐļĐŊĐžĐŗĐž ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ°, а Ņ€ĐžĐˇĐŧŅ–Ņ‰ŅƒŅ”Ņ‚ŅŒŅŅ СОвĐŊŅ–, ĐąĐĩСĐŋĐžŅĐĩŅ€ĐĩĐ´ĐŊŅŒĐž в *ĐžĐŋĐĩŅ€Đ°Ņ†Ņ–Ņ— ҈ĐģŅŅ…Ņƒ*. + +### ВиĐēĐžŅ€Đ¸ŅŅ‚Đ°ĐŊĐŊŅ ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ° `openapi_examples` + +Ви ĐŧĐžĐļĐĩŅ‚Đĩ ĐžĐŗĐžĐģĐžŅĐ¸Ņ‚Đ¸ ҁĐŋĐĩŅ†Đ¸Ņ„Ņ–Ņ‡ĐŊŅ– Đ´ĐģŅ OpenAPI `examples` ҃ FastAPI Са Đ´ĐžĐŋĐžĐŧĐžĐŗĐžŅŽ ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ° `openapi_examples` Đ´ĐģŅ: + +* `Path()` +* `Query()` +* `Header()` +* `Cookie()` +* `Body()` +* `Form()` +* `File()` + +КĐģŅŽŅ‡Ņ– ҁĐģОвĐŊиĐēа (`dict`) Ņ–Đ´ĐĩĐŊŅ‚Đ¸Ņ„Ņ–ĐēŅƒŅŽŅ‚ŅŒ ĐēĐžĐļĐĩĐŊ ĐŋŅ€Đ¸ĐēĐģад, а ĐēĐžĐļĐŊĐĩ СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅ `dict` — ĐēĐžĐļĐĩĐŊ ҁĐŋĐĩŅ†Đ¸Ņ„Ņ–Ņ‡ĐŊиК ҁĐģОвĐŊиĐē `dict` в `examples` ĐŧĐžĐļĐĩ ĐŧŅ–ŅŅ‚Đ¸Ņ‚Đ¸: + +* `summary`: ĐēĐžŅ€ĐžŅ‚ĐēиК ĐžĐŋĐ¸Ņ ĐŋŅ€Đ¸ĐēĐģĐ°Đ´Ņƒ. +* `description`: Ņ€ĐžĐˇĐŗĐžŅ€ĐŊŅƒŅ‚Đ¸Đš ĐžĐŋĐ¸Ņ (ĐŧĐžĐļĐĩ ĐŧŅ–ŅŅ‚Đ¸Ņ‚Đ¸ Markdown). +* `value`: ŅĐ°Đŧ ĐŋŅ€Đ¸ĐēĐģад, ĐŊаĐŋŅ€Đ¸ĐēĐģад, ҁĐģОвĐŊиĐē (`dict`). +* `externalValue`: аĐģŅŒŅ‚ĐĩŅ€ĐŊĐ°Ņ‚Đ¸Đ˛Đ° `value`, URL-Đ°Đ´Ņ€ĐĩŅĐ°, Ņ‰Đž вĐēĐ°ĐˇŅƒŅ” ĐŊа ĐŋŅ€Đ¸ĐēĐģад. ĐŸŅ€ĐžŅ‚Đĩ Ņ†Ņ ĐžĐŋŅ†Ņ–Ņ ĐŧĐžĐļĐĩ ĐŊĐĩ ĐŋŅ–Đ´Ņ‚Ņ€Đ¸ĐŧŅƒĐ˛Đ°Ņ‚Đ¸ŅŅ ĐąŅ–ĐģŅŒŅˆŅ–ŅŅ‚ŅŽ Ņ–ĐŊŅŅ‚Ņ€ŅƒĐŧĐĩĐŊŅ‚Ņ–Đ˛, ĐŊа Đ˛Ņ–Đ´ĐŧŅ–ĐŊ҃ Đ˛Ņ–Đ´ `value`. + +ВиĐēĐžŅ€Đ¸ŅŅ‚Đ°ĐŊĐŊŅ Đ˛Đ¸ĐŗĐģŅĐ´Đ°Ņ” Ņ‚Đ°Đē: + +{* ../../docs_src/schema_extra_example/tutorial005_an_py310.py hl[23:49] *} + +### ĐŸŅ€Đ¸ĐēĐģади OpenAPI ҃ UI Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Ņ–Ņ— + +З ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€ĐžĐŧ `openapi_examples`, дОдаĐŊиĐŧ Đ´Đž `Body()`, Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Ņ–Ņ `/docs` Đ˛Đ¸ĐŗĐģŅĐ´Đ°Ņ‚Đ¸ĐŧĐĩ Ņ‚Đ°Đē: + + + +## ĐĸĐĩŅ…ĐŊҖ҇ĐŊŅ– Đ´ĐĩŅ‚Đ°ĐģŅ– + +/// tip | ĐŸŅ–Đ´ĐēаСĐēа + +Đ¯ĐēŅ‰Đž Ви вĐļĐĩ виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅ”Ņ‚Đĩ **FastAPI** вĐĩҀҁҖҗ **0.99.0 айО Đ˛Đ¸Ņ‰Đĩ**, Ви ĐŧĐžĐļĐĩŅ‚Đĩ **ĐŋŅ€ĐžĐŋŅƒŅŅ‚Đ¸Ņ‚Đ¸** ҆ĐĩĐš Ņ€ĐžĐˇĐ´Ņ–Đģ. + +Đ’Ņ–ĐŊ ĐąŅ–ĐģҌ҈ аĐēŅ‚ŅƒĐ°ĐģҌĐŊиК Đ´ĐģŅ ŅŅ‚Đ°Ņ€Đ¸Ņ… вĐĩŅ€ŅŅ–Đš, Đ´Đž ĐŋĐžŅĐ˛Đ¸ OpenAPI 3.1.0. + +МоĐļĐŊа вваĐļĐ°Ņ‚Đ¸ ҆Đĩ ĐēĐžŅ€ĐžŅ‚ĐēиĐŧ **Ņ–ŅŅ‚ĐžŅ€Đ¸Ņ‡ĐŊиĐŧ ĐĩĐēҁĐēŅƒŅ€ŅĐžĐŧ** ҃ OpenAPI Ņ‚Đ° JSON Schema. 🤓 + +/// + +/// warning | ПоĐŋĐĩŅ€ĐĩĐ´ĐļĐĩĐŊĐŊŅ + +ĐĻĐĩ Đ´ŅƒĐļĐĩ Ņ‚ĐĩŅ…ĐŊҖ҇ĐŊа Ņ–ĐŊŅ„ĐžŅ€ĐŧĐ°Ņ†Ņ–Ņ ĐŋŅ€Đž ŅŅ‚Đ°ĐŊĐ´Đ°Ņ€Ņ‚Đ¸ **JSON Schema** Ņ– **OpenAPI**. + +Đ¯ĐēŅ‰Đž Đ˛Đ¸Ņ‰ĐĩĐˇĐŗĐ°Đ´Đ°ĐŊŅ– Ņ–Đ´ĐĩŅ— вĐļĐĩ ĐŋŅ€Đ°Ņ†ŅŽŅŽŅ‚ŅŒ ҃ Đ’Đ°Ņ — ĐŧĐžĐļĐĩŅ‚Đĩ ĐŊĐĩ ĐˇĐ°ĐŗĐģийĐģŅŽĐ˛Đ°Ņ‚Đ¸ŅŅ в ҆Җ Đ´ĐĩŅ‚Đ°ĐģŅ–. + +/// + +До OpenAPI 3.1.0 ҁĐŋĐĩŅ†Đ¸Ņ„Ņ–ĐēĐ°Ņ†Ņ–Ņ виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Đģа ŅŅ‚Đ°Ņ€Ņƒ Ņ‚Đ° ĐŧĐžĐ´Đ¸Ņ„Ņ–ĐēОваĐŊ҃ вĐĩŅ€ŅŅ–ŅŽ **JSON Schema**. + +ĐžŅĐēŅ–ĐģҌĐēи JSON Schema Ņ€Đ°ĐŊŅ–ŅˆĐĩ ĐŊĐĩ ĐŋŅ–Đ´Ņ‚Ņ€Đ¸ĐŧŅƒĐ˛Đ°Đģа `examples`, OpenAPI дОдаĐģа вĐģĐ°ŅĐŊĐĩ ĐŋĐžĐģĐĩ `examples`. + +OpenAPI Ņ‚Đ°ĐēĐžĐļ дОдаĐģа `example` Ņ– `examples` Đ´Đž Ņ–ĐŊŅˆĐ¸Ņ… Ņ‡Đ°ŅŅ‚Đ¸ĐŊ ҁĐŋĐĩŅ†Đ¸Ņ„Ņ–ĐēĐ°Ņ†Ņ–Ņ—: + +* `Parameter Object` (в ҁĐŋĐĩŅ†Đ¸Ņ„Ņ–ĐēĐ°Ņ†Ņ–Ņ—) виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅ”Ņ‚ŅŒŅŅ FastAPI Đ´ĐģŅ: + * `Path()` + * `Query()` + * `Header()` + * `Cookie()` +* `Request Body Object`, в ĐŋĐžĐģŅ– `content`, в `Media Type Object` (в ҁĐŋĐĩŅ†Đ¸Ņ„Ņ–ĐēĐ°Ņ†Ņ–Ņ—) виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅ”Ņ‚ŅŒŅŅ FastAPI Đ´ĐģŅ: + * `Body()` + * `File()` + * `Form()` + +/// info | ІĐŊŅ„ĐžŅ€ĐŧĐ°Ņ†Ņ–Ņ + +ĐĻĐĩĐš ŅŅ‚Đ°Ņ€Đ¸Đš ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ `examples`, ҁĐŋĐĩŅ†Đ¸Ņ„Ņ–Ņ‡ĐŊиК Đ´ĐģŅ OpenAPI, Ņ‚ĐĩĐŋĐĩŅ€ ĐŊĐ°ĐˇĐ¸Đ˛Đ°Ņ”Ņ‚ŅŒŅŅ `openapi_examples`, ĐŋĐžŅ‡Đ¸ĐŊĐ°ŅŽŅ‡Đ¸ С FastAPI вĐĩҀҁҖҗ `0.103.0`. + +/// + +### ПоĐģĐĩ `examples` ҃ JSON Schema + +ĐŸŅ–ĐˇĐŊŅ–ŅˆĐĩ JSON Schema дОдаĐģа ĐŋĐžĐģĐĩ `examples` ҃ ĐŊĐžĐ˛Ņƒ вĐĩŅ€ŅŅ–ŅŽ ҁĐŋĐĩŅ†Đ¸Ņ„Ņ–ĐēĐ°Ņ†Ņ–Ņ—. + +І вĐļĐĩ OpenAPI 3.1.0 ĐąĐ°ĐˇŅƒŅ”Ņ‚ŅŒŅŅ ĐŊа Ņ†Ņ–Đš ĐŊĐžĐ˛Ņ–Đš вĐĩҀҁҖҗ (JSON Schema 2020-12), ŅĐēа вĐēĐģŅŽŅ‡Đ°Ņ” ĐŋĐžĐģĐĩ `examples`. + +ĐĸĐĩĐŋĐĩŅ€ ҆Đĩ ĐŋĐžĐģĐĩ `examples` Ņ” ĐŋŅ€Ņ–ĐžŅ€Đ¸Ņ‚ĐĩŅ‚ĐŊиĐŧ Ņ– СаĐŧŅ–ĐŊŅŽŅ” ŅŅ‚Đ°Ņ€Đĩ (Ņ– ĐēĐ°ŅŅ‚ĐžĐŧĐŊĐĩ) ĐŋĐžĐģĐĩ `example`, ŅĐēĐĩ ŅŅ‚Đ°ĐģĐž ĐˇĐ°ŅŅ‚Đ°Ņ€Ņ–ĐģиĐŧ. + +НовĐĩ ĐŋĐžĐģĐĩ `examples` ҃ JSON Schema — ҆Đĩ **ĐŋŅ€ĐžŅŅ‚Đž ҁĐŋĐ¸ŅĐžĐē (`list`)** ĐŋŅ€Đ¸ĐēĐģĐ°Đ´Ņ–Đ˛, ĐąĐĩС Đ´ĐžĐ´Đ°Ņ‚ĐēĐžĐ˛Đ¸Ņ… ĐŧĐĩŅ‚Đ°Đ´Đ°ĐŊĐ¸Ņ… (ĐŊа Đ˛Ņ–Đ´ĐŧŅ–ĐŊ҃ Đ˛Ņ–Đ´ OpenAPI). + +/// info | ІĐŊŅ„ĐžŅ€ĐŧĐ°Ņ†Ņ–Ņ + +ĐĐ°Đ˛Ņ–Ņ‚ŅŒ ĐŋҖҁĐģŅ Ņ‚ĐžĐŗĐž, ŅĐē С'ŅĐ˛Đ¸Đ˛ŅŅ OpenAPI 3.1.0, ŅĐēиК ĐŋŅ–Đ´Ņ‚Ņ€Đ¸ĐŧŅƒĐ˛Đ°Đ˛ examples ҃ JSON Schema, Ņ–ĐŊŅŅ‚Ņ€ŅƒĐŧĐĩĐŊŅ‚ Swagger UI ҉Đĩ Đ´ĐĩŅĐēиК Ņ‡Đ°Ņ ĐŊĐĩ ĐŋŅ–Đ´Ņ‚Ņ€Đ¸ĐŧŅƒĐ˛Đ°Đ˛ Ņ†ŅŽ вĐĩŅ€ŅŅ–ŅŽ (ĐŋŅ–Đ´Ņ‚Ņ€Đ¸ĐŧĐēа Đˇâ€™ŅĐ˛Đ¸ĐģĐ°ŅŅŒ С вĐĩҀҁҖҗ 5.0.0 🎉). + +ЧĐĩŅ€ĐĩС ҆Đĩ вĐĩҀҁҖҗ FastAPI Đ´Đž 0.99.0 Đ˛ŅĐĩ ҉Đĩ виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Đģи вĐĩҀҁҖҗ OpenAPI ĐŊиĐļ҇Җ Са 3.1.0. + +/// + +### `Examples` в Pydantic Ņ– FastAPI + +КоĐģи Ви Đ´ĐžĐ´Đ°Ņ”Ņ‚Đĩ `examples` ҃ ĐŧОдĐĩĐģҌ Pydantic ҇ĐĩŅ€ĐĩС `schema_extra` айО `Field(examples=["something"])`, ҆Җ ĐŋŅ€Đ¸ĐēĐģади Đ´ĐžĐ´Đ°ŅŽŅ‚ŅŒŅŅ Đ´Đž **JSON Schema** ҆ҖҔҗ ĐŧОдĐĩĐģŅ–. + +І Ņ†Ņ **JSON Schema** Pydantic-ĐŧОдĐĩĐģŅ– вĐēĐģŅŽŅ‡Đ°Ņ”Ņ‚ŅŒŅŅ Đ´Đž **OpenAPI** Đ’Đ°ŅˆĐžĐŗĐž API, а ĐŋĐžŅ‚Ņ–Đŧ виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅ”Ņ‚ŅŒŅŅ в UI Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Ņ–Ņ— (docs UI). + +ĐŖ вĐĩŅ€ŅŅ–ŅŅ… FastAPI Đ´Đž 0.99.0 (ĐŋĐžŅ‡Đ¸ĐŊĐ°ŅŽŅ‡Đ¸ С 0.99.0 виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅ”Ņ‚ŅŒŅŅ ĐŊĐžĐ˛Ņ–ŅˆĐ¸Đš OpenAPI 3.1.0), ĐēĐžĐģи Ви виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Đģи `example` айО `examples` С Ņ–ĐŊŅˆĐ¸Đŧи ŅƒŅ‚Đ¸ĐģŅ–Ņ‚Đ°Đŧи (`Query()`, `Body()` Ņ‚ĐžŅ‰Đž), ҆Җ ĐŋŅ€Đ¸ĐēĐģади ĐŊĐĩ дОдаваĐģĐ¸ŅŅ Đ´Đž JSON Schema, ŅĐēиК ĐžĐŋĐ¸ŅŅƒŅ” ҆Җ даĐŊŅ– (ĐŊĐ°Đ˛Ņ–Ņ‚ŅŒ ĐŊĐĩ Đ´Đž вĐģĐ°ŅĐŊĐžŅ— вĐĩҀҁҖҗ JSON Schema ҃ OpenAPI). ĐĐ°Ņ‚ĐžĐŧŅ–ŅŅ‚ŅŒ вОĐŊи дОдаваĐģĐ¸ŅŅ ĐąĐĩСĐŋĐžŅĐĩŅ€ĐĩĐ´ĐŊŅŒĐž Đ´Đž ĐžĐŋĐ¸ŅŅƒ *ĐžĐąŅ€ĐžĐąĐŊиĐēа ҈ĐģŅŅ…Ņƒ* *(path operation)* в OpenAPI (Ņ‚ĐžĐąŅ‚Đž ĐŋОСа ĐŧĐĩĐļаĐŧи Ņ‡Đ°ŅŅ‚Đ¸ĐŊ, ŅĐēŅ– виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅŽŅ‚ŅŒ JSON Schema). + +АĐģĐĩ Ņ‚ĐĩĐŋĐĩŅ€, ĐēĐžĐģи FastAPI 0.99.0 Ņ– Đ˛Đ¸Ņ‰Đĩ виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅŽŅ‚ŅŒ OpenAPI 3.1.0, а Ņ‚ĐžĐš — JSON Schema 2020-12, Ņ€Đ°ĐˇĐžĐŧ Ņ–Đˇ Swagger UI 5.0.0 Ņ– Đ˛Đ¸Ņ‰Đĩ — Đ˛ŅĐĩ ŅŅ‚Đ°ĐģĐž ĐąŅ–ĐģҌ҈ ŅƒĐˇĐŗĐžĐ´ĐļĐĩĐŊиĐŧ, Ņ– examples Ņ‚ĐĩĐŋĐĩŅ€ вĐēĐģŅŽŅ‡Đ°ŅŽŅ‚ŅŒŅŅ Đ´Đž JSON Schema. + +### Swagger UI Ņ‚Đ° ҁĐŋĐĩŅ†Đ¸Ņ„Ņ–Ņ‡ĐŊŅ– Đ´ĐģŅ OpenAPI `examples` + +РаĐŊŅ–ŅˆĐĩ (ŅŅ‚Đ°ĐŊĐžĐŧ ĐŊа 26 ҁĐĩŅ€ĐŋĐŊŅ 2023 Ņ€ĐžĐē҃) Swagger UI ĐŊĐĩ ĐŋŅ–Đ´Ņ‚Ņ€Đ¸ĐŧŅƒĐ˛Đ°Đ˛ ĐēŅ–ĐģҌĐēа ĐŋŅ€Đ¸ĐēĐģĐ°Đ´Ņ–Đ˛ ҃ JSON Schema, Ņ‚ĐžĐŧ҃ ĐēĐžŅ€Đ¸ŅŅ‚ŅƒĐ˛Đ°Ņ‡Ņ– ĐŊĐĩ ĐŧаĐģи ĐŧĐžĐļĐģĐ¸Đ˛ĐžŅŅ‚Ņ– ĐŋĐžĐēĐ°ĐˇĐ°Ņ‚Đ¸ Đ´ĐĩĐēŅ–ĐģҌĐēа ĐŋŅ€Đ¸ĐēĐģĐ°Đ´Ņ–Đ˛ ҃ Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Ņ–Ņ—. + +ЊОй Đ˛Đ¸Ņ€Ņ–ŅˆĐ¸Ņ‚Đ¸ ҆Đĩ, FastAPI ĐŋĐžŅ‡Đ¸ĐŊĐ°ŅŽŅ‡Đ¸ С вĐĩҀҁҖҗ 0.103.0 **дОдав ĐŋŅ–Đ´Ņ‚Ņ€Đ¸ĐŧĐē҃** ŅŅ‚Đ°Ņ€ĐžĐŗĐž **OpenAPI-ҁĐŋĐĩŅ†Đ¸Ņ„Ņ–Ņ‡ĐŊĐžĐŗĐž** ĐŋĐžĐģŅ `examples` ҇ĐĩŅ€ĐĩС ĐŊОвиК ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ `openapi_examples`. 🤓 + +### ĐŸŅ–Đ´ŅŅƒĐŧĐžĐē + +РаĐŊŅ–ŅˆĐĩ Ņ ĐēаСав, Ņ‰Đž ĐŊĐĩ ĐģŅŽĐąĐģŅŽ Ņ–ŅŅ‚ĐžŅ€Ņ–ŅŽ... а Ņ‚ĐĩĐŋĐĩŅ€ ĐžŅŅŒ Ņ — Ņ€ĐžĐˇĐŋĐžĐ˛Ņ–Đ´Đ°ŅŽ "Ņ‚ĐĩŅ…ĐŊҖ҇ĐŊŅ– Ņ–ŅŅ‚ĐžŅ€Đ¸Ņ‡ĐŊŅ–" ĐģĐĩĐē҆Җҗ. 😅 + +ĐšĐžŅ€ĐžŅ‚ĐēĐž: **ĐžĐŊĐžĐ˛Ņ–Ņ‚ŅŒŅŅ Đ´Đž FastAPI 0.99.0 айО Đ˛Đ¸Ņ‰Đĩ** — Ņ– Đ˛ŅĐĩ ŅŅ‚Đ°ĐŊĐĩ СĐŊĐ°Ņ‡ĐŊĐž **ĐŋŅ€ĐžŅŅ‚Ņ–ŅˆĐ¸Đŧ, ŅƒĐˇĐŗĐžĐ´ĐļĐĩĐŊиĐŧ Ņ‚Đ° Ņ–ĐŊŅ‚ŅƒŅ—Ņ‚Đ¸Đ˛ĐŊĐž ĐˇŅ€ĐžĐˇŅƒĐŧŅ–ĐģиĐŧ**, Ņ– ВаĐŧ ĐŊĐĩ дОвĐĩĐ´ĐĩŅ‚ŅŒŅŅ СĐŊĐ°Ņ‚Đ¸ Đ˛ŅŅ– ҆Җ Ņ–ŅŅ‚ĐžŅ€Đ¸Ņ‡ĐŊŅ– Đ´ĐĩŅ‚Đ°ĐģŅ–. 😎 diff --git a/docs/uk/docs/tutorial/security/index.md b/docs/uk/docs/tutorial/security/index.md new file mode 100644 index 000000000..c3d94be8d --- /dev/null +++ b/docs/uk/docs/tutorial/security/index.md @@ -0,0 +1,104 @@ +# БĐĩСĐŋĐĩĐēа + +Đ†ŅĐŊŅƒŅ” ĐąĐ°ĐŗĐ°Ņ‚Đž ҁĐŋĐžŅĐžĐąŅ–Đ˛ Ņ€ĐĩаĐģŅ–ĐˇŅƒĐ˛Đ°Ņ‚Đ¸ ĐąĐĩСĐŋĐĩĐē҃, Đ°Đ˛Ņ‚ĐĩĐŊŅ‚Đ¸Ņ„Ņ–ĐēĐ°Ņ†Ņ–ŅŽ Ņ‚Đ° Đ°Đ˛Ņ‚ĐžŅ€Đ¸ĐˇĐ°Ņ†Ņ–ŅŽ. + +ĐĻĐĩ ĐˇĐ°ĐˇĐ˛Đ¸Ņ‡Đ°Đš ҁĐēĐģадĐŊа Ņ– "ĐŊĐĩĐŋŅ€ĐžŅŅ‚Đ°" Ņ‚ĐĩĐŧа. + +ĐŖ ĐąĐ°ĐŗĐ°Ņ‚ŅŒĐžŅ… ҄ҀĐĩĐšĐŧĐ˛ĐžŅ€ĐēĐ°Ņ… Ņ– ŅĐ¸ŅŅ‚ĐĩĐŧĐ°Ņ… СайĐĩСĐŋĐĩ҇ĐĩĐŊĐŊŅ ĐąĐĩСĐŋĐĩĐēи Ņ‚Đ° Đ°Đ˛Ņ‚ĐĩĐŊŅ‚Đ¸Ņ„Ņ–ĐēĐ°Ņ†Ņ–Ņ— СаКĐŧĐ°Ņ” вĐĩĐģĐ¸Ņ‡ĐĩСĐŊ҃ Ņ‡Đ°ŅŅ‚Đ¸ĐŊ҃ ĐˇŅƒŅĐ¸ĐģҌ Ņ– ĐēĐžĐ´Ņƒ (Ņ–ĐŊĐžĐ´Ņ– — ĐŋĐžĐŊад 50% Đ˛ŅŅŒĐžĐŗĐž ĐŊаĐŋĐ¸ŅĐ°ĐŊĐžĐŗĐž ĐēĐžĐ´Ņƒ). + +**FastAPI** ĐŊĐ°Đ´Đ°Ņ” ĐēŅ–ĐģҌĐēа Ņ–ĐŊŅŅ‚Ņ€ŅƒĐŧĐĩĐŊŅ‚Ņ–Đ˛, ŅĐēŅ– Đ´ĐžĐŋĐžĐŧĐžĐļŅƒŅ‚ŅŒ ВаĐŧ вĐŋĐžŅ€Đ°Ņ‚Đ¸ŅŅ С **ĐąĐĩСĐŋĐĩĐēĐžŅŽ** ĐģĐĩĐŗĐēĐž, ŅˆĐ˛Đ¸Đ´ĐēĐž, ŅŅ‚Đ°ĐŊĐ´Đ°Ņ€Ņ‚ĐŊиĐŧ ҁĐŋĐžŅĐžĐąĐžĐŧ, ĐąĐĩС ĐŊĐĩĐžĐąŅ…Ņ–Đ´ĐŊĐžŅŅ‚Ņ– Đ˛Đ¸Đ˛Ņ‡Đ°Ņ‚Đ¸ Đ˛ŅŅ– ҁĐŋĐĩŅ†Đ¸Ņ„Ņ–ĐēĐ°Ņ†Ņ–Ņ— ĐąĐĩСĐŋĐĩĐēи. + +АĐģĐĩ ҁĐŋĐžŅ‡Đ°Ņ‚Đē҃ — ĐēŅ–ĐģҌĐēа ĐēĐžŅ€ĐžŅ‚ĐēĐ¸Ņ… ĐŋĐžĐŊŅŅ‚ŅŒ. + +## ĐŸĐžŅĐŋŅ–ŅˆĐ°Ņ”Ņ‚Đĩ? + +Đ¯ĐēŅ‰Đž ВаĐŧ ĐŊĐĩ ҆ҖĐēĐ°Đ˛Ņ– Đ˛ŅŅ– ҆Җ Ņ‚ĐĩŅ€ĐŧŅ–ĐŊи Đš ĐŋŅ€ĐžŅŅ‚Đž ĐŋĐžŅ‚Ņ€Ņ–ĐąĐŊĐž *ŅˆĐ˛Đ¸Đ´ĐēĐž* Đ´ĐžĐ´Đ°Ņ‚Đ¸ Đ°Đ˛Ņ‚ĐĩĐŊŅ‚Đ¸Ņ„Ņ–ĐēĐ°Ņ†Ņ–ŅŽ Са ĐģĐžĐŗŅ–ĐŊĐžĐŧ Ņ– ĐŋĐ°Ņ€ĐžĐģĐĩĐŧ — ĐŋĐĩŅ€ĐĩŅ…ĐžĐ´ŅŒŅ‚Đĩ Đ´Đž ĐŊĐ°ŅŅ‚ŅƒĐŋĐŊĐ¸Ņ… Ņ€ĐžĐˇĐ´Ņ–ĐģŅ–Đ˛. + +## OAuth2 + +OAuth2 — ҆Đĩ ҁĐŋĐĩŅ†Đ¸Ņ„Ņ–ĐēĐ°Ņ†Ņ–Ņ, Ņ‰Đž ĐžĐŋĐ¸ŅŅƒŅ” ĐēŅ–ĐģҌĐēа ҁĐŋĐžŅĐžĐąŅ–Đ˛ ĐžĐąŅ€ĐžĐąĐēи Đ°Đ˛Ņ‚ĐĩĐŊŅ‚Đ¸Ņ„Ņ–ĐēĐ°Ņ†Ņ–Ņ— Ņ‚Đ° Đ°Đ˛Ņ‚ĐžŅ€Đ¸ĐˇĐ°Ņ†Ņ–Ņ—. + +ĐĻĐĩ Đ´ĐžŅĐ¸Ņ‚ŅŒ Ой'Ņ”ĐŧĐŊа ҁĐŋĐĩŅ†Đ¸Ņ„Ņ–ĐēĐ°Ņ†Ņ–Ņ, ŅĐēа ĐžŅ…ĐžĐŋĐģŅŽŅ” ҁĐēĐģадĐŊŅ– виĐŋадĐēи виĐēĐžŅ€Đ¸ŅŅ‚Đ°ĐŊĐŊŅ. + +ВоĐŊа вĐēĐģŅŽŅ‡Đ°Ņ” ҁĐŋĐžŅĐžĐąĐ¸ Đ°Đ˛Ņ‚ĐĩĐŊŅ‚Đ¸Ņ„Ņ–ĐēĐ°Ņ†Ņ–Ņ— ҇ĐĩŅ€ĐĩС "҂ҀĐĩŅ‚ŅŽ ŅŅ‚ĐžŅ€ĐžĐŊ҃". + +ХаĐŧĐĩ ҆Đĩ ĐģĐĩĐļĐ¸Ņ‚ŅŒ в ĐžŅĐŊĐžĐ˛Ņ– "Đ˛Ņ…ĐžĐ´Ņƒ ҇ĐĩŅ€ĐĩС Google, Facebook, X (Twitter), GitHub" Ņ‚ĐžŅ‰Đž. + +### OAuth 1 + +РаĐŊŅ–ŅˆĐĩ ҖҁĐŊŅƒĐ˛Đ°Đ˛ OAuth 1, ŅĐēиК СĐŊĐ°Ņ‡ĐŊĐž Đ˛Ņ–Đ´Ņ€Ņ–ĐˇĐŊŅŅ”Ņ‚ŅŒŅŅ Đ˛Ņ–Đ´ OAuth2 Ņ– Ņ” ҁĐēĐģадĐŊŅ–ŅˆĐ¸Đŧ, ĐžŅĐēŅ–ĐģҌĐēи ĐŧŅ–ŅŅ‚Đ¸Đ˛ ҁĐŋĐĩŅ†Đ¸Ņ„Ņ–ĐēĐ°Ņ†Ņ–Ņ— Đ´ĐģŅ ŅˆĐ¸Ņ„Ņ€ŅƒĐ˛Đ°ĐŊĐŊŅ ĐēĐžĐŧ҃ĐŊŅ–ĐēĐ°Ņ†Ņ–Đš. + +Đ—Đ°Ņ€Đ°Đˇ ĐŧаКĐļĐĩ ĐŊĐĩ виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅ”Ņ‚ŅŒŅŅ. + +OAuth2 ĐŊĐĩ вĐēĐ°ĐˇŅƒŅ”, ŅĐē ŅĐ°ĐŧĐĩ ŅˆĐ¸Ņ„Ņ€ŅƒĐ˛Đ°Ņ‚Đ¸ С'Ņ”Đ´ĐŊаĐŊĐŊŅ — вОĐŊĐž ĐžŅ‡Ņ–ĐēŅƒŅ”, Ņ‰Đž Đ˛Đ°Ņˆ ĐˇĐ°ŅŅ‚ĐžŅŅƒĐŊĐžĐē ĐŋŅ€Đ°Ņ†ŅŽŅ” ҇ĐĩŅ€ĐĩС HTTPS. + +/// tip | ĐŸĐžŅ€Đ°Đ´Đ° + +ĐŖ Ņ€ĐžĐˇĐ´Ņ–ĐģŅ– ĐŋŅ€Đž **Đ´ĐĩĐŋĐģОК** Ви ĐŋĐžĐąĐ°Ņ‡Đ¸Ņ‚Đĩ, ŅĐē ĐŊаĐģĐ°ŅˆŅ‚ŅƒĐ˛Đ°Ņ‚Đ¸ HTTPS ĐąĐĩСĐēĐžŅˆŅ‚ĐžĐ˛ĐŊĐž С Traefik Ņ‚Đ° Let's Encrypt. + +/// + +## OpenID Connect + +OpenID Connect — ҉Đĩ ОдĐŊа ҁĐŋĐĩŅ†Đ¸Ņ„Ņ–ĐēĐ°Ņ†Ņ–Ņ, ĐŋĐžĐąŅƒĐ´ĐžĐ˛Đ°ĐŊа ĐŊа ĐžŅĐŊĐžĐ˛Ņ– **OAuth2**. + +ВоĐŊа Ņ€ĐžĐˇŅˆĐ¸Ņ€ŅŽŅ” OAuth2, ŅƒŅ‚ĐžŅ‡ĐŊŅŽŅŽŅ‡Đ¸ Đ´ĐĩŅĐēŅ– ĐŊĐĩОдĐŊОСĐŊĐ°Ņ‡ĐŊĐžŅŅ‚Ņ– Đ´ĐģŅ Đ´ĐžŅŅĐŗĐŊĐĩĐŊĐŊŅ ĐēŅ€Đ°Ņ‰ĐžŅ— ҁ҃ĐŧҖҁĐŊĐžŅŅ‚Ņ–. + +НаĐŋŅ€Đ¸ĐēĐģад, Đ˛Ņ…Ņ–Đ´ ҇ĐĩŅ€ĐĩС Google виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅ” OpenID Connect (ŅĐēиК ĐąĐ°ĐˇŅƒŅ”Ņ‚ŅŒŅŅ ĐŊа OAuth2). + +АĐģĐĩ Đ˛Ņ…Ņ–Đ´ ҇ĐĩŅ€ĐĩС Facebook — ĐŊŅ–. Đ’Ņ–ĐŊ ĐŧĐ°Ņ” вĐģĐ°ŅĐŊ҃ Ņ€ĐĩаĐģŅ–ĐˇĐ°Ņ†Ņ–ŅŽ ĐŊа ĐąĐ°ĐˇŅ– OAuth2. + +### OpenID (ĐŊĐĩ "OpenID Connect") + +Đ†ŅĐŊŅƒĐ˛Đ°Đģа Ņ‚Đ°ĐēĐžĐļ ҁĐŋĐĩŅ†Đ¸Ņ„Ņ–ĐēĐ°Ņ†Ņ–Ņ "OpenID", ŅĐēа ĐŊаĐŧĐ°ĐŗĐ°ĐģĐ°ŅŅ Ņ€ĐžĐˇĐ˛ĘŧŅĐˇĐ°Ņ‚Đ¸ ҂Җ ŅĐ°ĐŧŅ– ĐˇĐ°Đ´Đ°Ņ‡Ņ–, Ņ‰Đž Đš **OpenID Connect**, аĐģĐĩ ĐŊĐĩ ĐąĐ°ĐˇŅƒĐ˛Đ°ĐģĐ°ŅŅŒ ĐŊа OAuth2. + +ĐĻĐĩ ĐąŅƒĐģа ĐˇĐžĐ˛ŅŅ–Đŧ Ņ–ĐŊŅˆĐ° ŅĐ¸ŅŅ‚ĐĩĐŧа, Ņ– ŅŅŒĐžĐŗĐžĐ´ĐŊŅ– вОĐŊа ĐŧаКĐļĐĩ ĐŊĐĩ виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅ”Ņ‚ŅŒŅŅ. + +## OpenAPI + +OpenAPI (Ņ€Đ°ĐŊŅ–ŅˆĐĩ Swagger) — ҆Đĩ ҁĐŋĐĩŅ†Đ¸Ņ„Ņ–ĐēĐ°Ņ†Ņ–Ņ Đ´ĐģŅ ĐŋĐžĐąŅƒĐ´ĐžĐ˛Đ¸ API (Ņ‚ĐĩĐŋĐĩŅ€ ĐŋŅ–Đ´ ĐĩĐŗŅ–Đ´ĐžŅŽ Linux Foundation). + +**FastAPI** ĐąĐ°ĐˇŅƒŅ”Ņ‚ŅŒŅŅ ĐŊа **OpenAPI**. + +Đ—Đ°Đ˛Đ´ŅĐēи Ņ†ŅŒĐžĐŧ҃ Ви ĐžŅ‚Ņ€Đ¸ĐŧŅƒŅ”Ņ‚Đĩ Đ°Đ˛Ņ‚ĐžĐŧĐ°Ņ‚Đ¸Ņ‡ĐŊ҃ Ņ–ĐŊŅ‚ĐĩŅ€Đ°ĐēŅ‚Đ¸Đ˛ĐŊ҃ Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Ņ–ŅŽ, ĐŗĐĩĐŊĐĩŅ€Đ°Ņ†Ņ–ŅŽ ĐēĐžĐ´Ņƒ Ņ‚Đ° ĐąĐ°ĐŗĐ°Ņ‚Đž Ņ–ĐŊŅˆĐžĐŗĐž. + +OpenAPI дОСвОĐģŅŅ” ĐžĐŋĐ¸ŅŅƒĐ˛Đ°Ņ‚Đ¸ Ņ€Ņ–ĐˇĐŊŅ– "ҁ҅ĐĩĐŧи" ĐąĐĩСĐŋĐĩĐēи. + +ВиĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅŽŅ‡Đ¸ Ņ—Ņ…, Ви ĐŧĐžĐļĐĩŅ‚Đĩ ҁĐēĐžŅ€Đ¸ŅŅ‚Đ°Ņ‚Đ¸ŅŅ Đ˛ŅŅ–Đŧа Ņ†Đ¸Đŧи Ņ–ĐŊŅŅ‚Ņ€ŅƒĐŧĐĩĐŊŅ‚Đ°Đŧи, Ņ‰Đž ĐąĐ°ĐˇŅƒŅŽŅ‚ŅŒŅŅ ĐŊа ŅŅ‚Đ°ĐŊĐ´Đ°Ņ€Ņ‚Đ°Ņ…, СОĐēŅ€ĐĩĐŧа Ņ–ĐŊŅ‚ĐĩŅ€Đ°ĐēŅ‚Đ¸Đ˛ĐŊиĐŧи ŅĐ¸ŅŅ‚ĐĩĐŧаĐŧи Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Ņ–Ņ—. + +OpenAPI виСĐŊĐ°Ņ‡Đ°Ņ” Ņ‚Đ°ĐēŅ– ҁ҅ĐĩĐŧи ĐąĐĩСĐŋĐĩĐēи: + +* `apiKey`: ҁĐŋĐĩŅ†Đ¸Ņ„Ņ–Ņ‡ĐŊиК Đ´ĐģŅ ĐˇĐ°ŅŅ‚ĐžŅŅƒĐŊĐē҃ ĐēĐģŅŽŅ‡, ŅĐēиК ĐŧĐžĐļĐĩ ĐŋĐĩŅ€ĐĩĐ´Đ°Đ˛Đ°Ņ‚Đ¸ŅŅ ҇ĐĩŅ€ĐĩС: + * ĐŸĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ СаĐŋĐ¸Ņ‚Ņƒ. + * Đ—Đ°ĐŗĐžĐģОвОĐē. + * Cookie. +* `http`: ŅŅ‚Đ°ĐŊĐ´Đ°Ņ€Ņ‚ĐŊŅ– ĐŧĐĩŅ‚ĐžĐ´Đ¸ HTTP-Đ°Đ˛Ņ‚ĐĩĐŊŅ‚Đ¸Ņ„Ņ–ĐēĐ°Ņ†Ņ–Ņ—, вĐēĐģŅŽŅ‡Đ°ŅŽŅ‡Đ¸: + * `bearer`: ĐˇĐ°ĐŗĐžĐģОвОĐē `Authorization` ĐˇŅ– СĐŊĐ°Ņ‡ĐĩĐŊĐŊŅĐŧ `Bearer` Ņ‚Đ° Ņ‚ĐžĐēĐĩĐŊĐžĐŧ. ĐĻĐĩ ҃ҁĐŋадĐēОваĐŊĐž С OAuth2. + * HTTP Basic Đ°Đ˛Ņ‚ĐĩĐŊŅ‚Đ¸Ņ„Ņ–ĐēĐ°Ņ†Ņ–Ņ + * HTTP Digest, Ņ‚ĐžŅ‰Đž. +* `oauth2`: ŅƒŅŅ– ҁĐŋĐžŅĐžĐąĐ¸ ĐžĐąŅ€ĐžĐąĐēи ĐąĐĩСĐŋĐĩĐēи Са Đ´ĐžĐŋĐžĐŧĐžĐŗĐžŅŽ OAuth2 (Ņ‚Đ°Đē СваĐŊŅ– ÂĢĐŋĐžŅ‚ĐžĐēиÂģ). + * ДĐĩŅĐēŅ– С Ņ†Đ¸Ņ… ĐŋĐžŅ‚ĐžĐēŅ–Đ˛ ĐŋŅ–Đ´Ņ…ĐžĐ´ŅŅ‚ŅŒ Đ´ĐģŅ ŅŅ‚Đ˛ĐžŅ€ĐĩĐŊĐŊŅ вĐģĐ°ŅĐŊĐžĐŗĐž ĐŋŅ€ĐžĐ˛Đ°ĐšĐ´ĐĩŅ€Đ° Đ°Đ˛Ņ‚ĐĩĐŊŅ‚Đ¸Ņ„Ņ–ĐēĐ°Ņ†Ņ–Ņ— OAuth 2.0 (ĐŊаĐŋŅ€Đ¸ĐēĐģад, Google, Facebook, X (Twitter), GitHub Ņ‚ĐžŅ‰Đž): + * `implicit`— ĐŊĐĩŅĐ˛ĐŊиК + * `clientCredentials`— ОйĐģŅ–ĐēĐžĐ˛Ņ– даĐŊŅ– ĐēĐģŅ–Ņ”ĐŊŅ‚Đ° + * `authorizationCode` — ĐēОд Đ°Đ˛Ņ‚ĐžŅ€Đ¸ĐˇĐ°Ņ†Ņ–Ņ— + * АĐģĐĩ Ņ” ОдиĐŊ ĐžĐēŅ€ĐĩĐŧиК ÂĢĐŋĐžŅ‚Ņ–ĐēÂģ, ŅĐēиК Ņ–Đ´ĐĩаĐģҌĐŊĐž ĐŋŅ–Đ´Ņ…ĐžĐ´Đ¸Ņ‚ŅŒ Đ´ĐģŅ Ņ€ĐĩаĐģŅ–ĐˇĐ°Ņ†Ņ–Ņ— Đ°Đ˛Ņ‚ĐĩĐŊŅ‚Đ¸Ņ„Ņ–ĐēĐ°Ņ†Ņ–Ņ— Đ˛ŅĐĩŅ€ĐĩдиĐŊŅ– ОдĐŊĐžĐŗĐž Đ´ĐžĐ´Đ°Ņ‚Đē҃: + * `password`: ҃ ĐŊĐ°ŅŅ‚ŅƒĐŋĐŊĐ¸Ņ… Ņ€ĐžĐˇĐ´Ņ–ĐģĐ°Ņ… ĐąŅƒĐ´Đĩ ĐŋŅ€Đ¸ĐēĐģад виĐēĐžŅ€Đ¸ŅŅ‚Đ°ĐŊĐŊŅ Ņ†ŅŒĐžĐŗĐž ĐŋĐžŅ‚ĐžĐē҃. +* `openIdConnect`: дОСвОĐģŅŅ” Đ°Đ˛Ņ‚ĐžĐŧĐ°Ņ‚Đ¸Ņ‡ĐŊĐž Đ˛Đ¸ŅĐ˛ĐģŅŅ‚Đ¸ ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ¸ Đ°Đ˛Ņ‚ĐĩĐŊŅ‚Đ¸Ņ„Ņ–ĐēĐ°Ņ†Ņ–Ņ— OAuth2. + * ĐĻĐĩ Đ°Đ˛Ņ‚ĐžĐŧĐ°Ņ‚Đ¸Ņ‡ĐŊĐĩ Đ˛Đ¸ŅĐ˛ĐģĐĩĐŊĐŊŅ виСĐŊĐ°Ņ‡Đ°Ņ”Ņ‚ŅŒŅŅ ҃ ҁĐŋĐĩŅ†Đ¸Ņ„Ņ–ĐēĐ°Ņ†Ņ–Ņ— OpenID Connect. + + +/// tip | ĐŸĐžŅ€Đ°Đ´Đ° + +ІĐŊŅ‚ĐĩĐŗŅ€Đ°Ņ†Ņ–Ņ Ņ–ĐŊŅˆĐ¸Ņ… ĐŋŅ€ĐžĐ˛Đ°ĐšĐ´ĐĩŅ€Ņ–Đ˛ Đ°Đ˛Ņ‚ĐĩĐŊŅ‚Đ¸Ņ„Ņ–ĐēĐ°Ņ†Ņ–Ņ—/Đ°Đ˛Ņ‚ĐžŅ€Đ¸ĐˇĐ°Ņ†Ņ–Ņ—, Ņ‚Đ°ĐēĐ¸Ņ… ŅĐē Google, Facebook, X (Twitter), GitHub Ņ‚ĐžŅ‰Đž — Ņ‚Đ°ĐēĐžĐļ ĐŧĐžĐļĐģива Ņ– Đ˛Ņ–Đ´ĐŊĐžŅĐŊĐž ĐŋŅ€ĐžŅŅ‚Đ°. + +ĐĐ°ĐšŅĐēĐģадĐŊŅ–ŅˆĐĩ — ҆Đĩ ŅŅ‚Đ˛ĐžŅ€Đ¸Ņ‚Đ¸ вĐģĐ°ŅĐŊĐžĐŗĐž ĐŋŅ€ĐžĐ˛Đ°ĐšĐ´ĐĩŅ€Đ° Đ°Đ˛Ņ‚ĐĩĐŊŅ‚Đ¸Ņ„Ņ–ĐēĐ°Ņ†Ņ–Ņ—/Đ°Đ˛Ņ‚ĐžŅ€Đ¸ĐˇĐ°Ņ†Ņ–Ņ—, ŅĐē Google Ņ‡Đ¸ Facebook. АĐģĐĩ **FastAPI** ĐŊĐ°Đ´Đ°Ņ” ВаĐŧ Ņ–ĐŊŅŅ‚Ņ€ŅƒĐŧĐĩĐŊŅ‚Đ¸, Ņ‰ĐžĐą ĐˇŅ€ĐžĐąĐ¸Ņ‚Đ¸ ҆Đĩ ĐģĐĩĐŗĐēĐž, ĐąĐĩŅ€ŅƒŅ‡Đ¸ ĐŊа ҁĐĩĐąĐĩ ваĐļĐē҃ Ņ‡Đ°ŅŅ‚Đ¸ĐŊ҃ Ņ€ĐžĐąĐžŅ‚Đ¸. + +/// + +## ІĐŊŅŅ‚Ņ€ŅƒĐŧĐĩĐŊŅ‚Đ¸ **FastAPI** + +FastAPI ĐŊĐ°Đ´Đ°Ņ” ĐēŅ–ĐģҌĐēа Ņ–ĐŊŅŅ‚Ņ€ŅƒĐŧĐĩĐŊŅ‚Ņ–Đ˛ Đ´ĐģŅ ĐēĐžĐļĐŊĐžŅ— С ĐžĐŋĐ¸ŅĐ°ĐŊĐ¸Ņ… ҁ҅ĐĩĐŧ ĐąĐĩСĐŋĐĩĐēи в ĐŧĐžĐ´ŅƒĐģŅ– `fastapi.security`, ŅĐēŅ– ҁĐŋŅ€ĐžŅ‰ŅƒŅŽŅ‚ŅŒ виĐēĐžŅ€Đ¸ŅŅ‚Đ°ĐŊĐŊŅ Ņ†Đ¸Ņ… ĐŧĐĩŅ…Đ°ĐŊŅ–ĐˇĐŧŅ–Đ˛ ĐˇĐ°Ņ…Đ¸ŅŅ‚Ņƒ. + +ĐŖ ĐŊĐ°ŅŅ‚ŅƒĐŋĐŊĐ¸Ņ… Ņ€ĐžĐˇĐ´Ņ–ĐģĐ°Ņ… Ви ĐŋĐžĐąĐ°Ņ‡Đ¸Ņ‚Đĩ, ŅĐē Đ´ĐžĐ´Đ°Ņ‚Đ¸ ĐąĐĩСĐŋĐĩĐē҃ Đ´Đž ŅĐ˛ĐžĐŗĐž API Са Đ´ĐžĐŋĐžĐŧĐžĐŗĐžŅŽ Ņ†Đ¸Ņ… Ņ–ĐŊŅŅ‚Ņ€ŅƒĐŧĐĩĐŊŅ‚Ņ–Đ˛ **FastAPI**. + +А Ņ‚Đ°ĐēĐžĐļ ĐŋĐžĐąĐ°Ņ‡Đ¸Ņ‚Đĩ, ŅĐē вОĐŊа Đ°Đ˛Ņ‚ĐžĐŧĐ°Ņ‚Đ¸Ņ‡ĐŊĐž Ņ–ĐŊŅ‚ĐĩĐŗŅ€ŅƒŅ”Ņ‚ŅŒŅŅ в Ņ–ĐŊŅ‚ĐĩŅ€Đ°ĐēŅ‚Đ¸Đ˛ĐŊ҃ Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Ņ–ŅŽ Đ˛Đ°ŅˆĐžĐŗĐž API. diff --git a/docs/uk/docs/tutorial/static-files.md b/docs/uk/docs/tutorial/static-files.md new file mode 100644 index 000000000..a84782d8f --- /dev/null +++ b/docs/uk/docs/tutorial/static-files.md @@ -0,0 +1,40 @@ +# ĐĄŅ‚Đ°Ņ‚Đ¸Ņ‡ĐŊŅ– Ņ„Đ°ĐšĐģи + +Ви ĐŧĐžĐļĐĩŅ‚Đĩ Đ°Đ˛Ņ‚ĐžĐŧĐ°Ņ‚Đ¸Ņ‡ĐŊĐž ĐŊĐ°Đ´Đ°Đ˛Đ°Ņ‚Đ¸ ŅŅ‚Đ°Ņ‚Đ¸Ņ‡ĐŊŅ– Ņ„Đ°ĐšĐģи С ĐēĐ°Ņ‚Đ°ĐģĐžĐŗŅƒ, виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒŅŽŅ‡Đ¸ `StaticFiles`. + +## ВиĐēĐžŅ€Đ¸ŅŅ‚Đ°ĐŊĐŊŅ `StaticFiles` + +* ІĐŧĐŋĐžŅ€Ņ‚ŅƒĐšŅ‚Đĩ `StaticFiles`. +* "ĐŸŅ–Đ´'Ņ”Đ´ĐŊĐ°Ņ‚Đ¸" ĐĩĐēСĐĩĐŧĐŋĐģŅŅ€ `StaticFiles()` С вĐēаСаĐŊĐŊŅĐŧ ĐŊĐĩĐžĐąŅ…Ņ–Đ´ĐŊĐžĐŗĐž ҈ĐģŅŅ…Ņƒ. + +{* ../../docs_src/static_files/tutorial001.py hl[2,6] *} + +/// note | ĐĸĐĩŅ…ĐŊҖ҇ĐŊŅ– Đ´ĐĩŅ‚Đ°ĐģŅ– + +Ви Ņ‚Đ°ĐēĐžĐļ ĐŧĐžĐļĐĩŅ‚Đĩ виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ `from starlette.staticfiles import StaticFiles`. + +**FastAPI** ĐŊĐ°Đ´Đ°Ņ” Ņ‚ĐžĐš ŅĐ°ĐŧиК `starlette.staticfiles`, Ņ‰Đž Đš `fastapi.staticfiles` Đ´ĐģŅ ĐˇŅ€ŅƒŅ‡ĐŊĐžŅŅ‚Ņ– Ņ€ĐžĐˇŅ€ĐžĐąĐŊиĐēŅ–Đ˛. АĐģĐĩ Ņ„Đ°ĐēŅ‚Đ¸Ņ‡ĐŊĐž Đ˛Ņ–ĐŊ ĐąĐĩСĐŋĐžŅĐĩŅ€ĐĩĐ´ĐŊŅŒĐž ĐŋĐžŅ…ĐžĐ´Đ¸Ņ‚ŅŒ Ņ–Đˇ Starlette. + +/// + +### ĐŠĐž Ņ‚Đ°ĐēĐĩ "ĐŸŅ–Đ´'Ņ”Đ´ĐŊаĐŊĐŊŅ" + +"ĐŸŅ–Đ´'Ņ”Đ´ĐŊаĐŊĐŊŅ" ОСĐŊĐ°Ņ‡Đ°Ņ” дОдаваĐŊĐŊŅ ĐŋОвĐŊĐžŅ†Ņ–ĐŊĐŊĐžĐŗĐž "ĐŊĐĩСаĐģĐĩĐļĐŊĐžĐŗĐž" ĐˇĐ°ŅŅ‚ĐžŅŅƒĐŊĐē҃ Са ĐŋĐĩвĐŊиĐŧ ҈ĐģŅŅ…ĐžĐŧ, ŅĐēиК ĐŋĐžŅ‚Ņ–Đŧ ĐžĐąŅ€ĐžĐąĐģŅŅ” Đ˛ŅŅ– ĐŋŅ–Đ´ ҈ĐģŅŅ…Đ¸. + +ĐĻĐĩ Đ˛Ņ–Đ´Ņ€Ņ–ĐˇĐŊŅŅ”Ņ‚ŅŒŅŅ Đ˛Ņ–Đ´ виĐēĐžŅ€Đ¸ŅŅ‚Đ°ĐŊĐŊŅ `APIRouter`, ĐžŅĐēŅ–ĐģҌĐēи ĐŋŅ–Đ´'Ņ”Đ´ĐŊаĐŊиК ĐˇĐ°ŅŅ‚ĐžŅŅƒĐŊĐžĐē Ņ” ĐŋОвĐŊŅ–ŅŅ‚ŅŽ ĐŊĐĩСаĐģĐĩĐļĐŊиĐŧ. OpenAPI Ņ‚Đ° Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Ņ–Ņ Đ˛Đ°ŅˆĐžĐŗĐž ĐžŅĐŊОвĐŊĐžĐŗĐž ĐˇĐ°ŅŅ‚ĐžŅŅƒĐŊĐē҃ ĐŊĐĩ ĐąŅƒĐ´ŅƒŅ‚ŅŒ СĐŊĐ°Ņ‚Đ¸ ĐŊŅ–Ņ‡ĐžĐŗĐž ĐŋŅ€Đž Đ˛Đ°Ņˆ ĐŋŅ–Đ´'Ņ”Đ´ĐŊаĐŊиК ĐˇĐ°ŅŅ‚ĐžŅŅƒĐŊĐžĐē. + +Ви ĐŧĐžĐļĐĩŅ‚Đĩ Đ´Ņ–ĐˇĐŊĐ°Ņ‚Đ¸ŅŅ ĐąŅ–ĐģҌ҈Đĩ ĐŋŅ€Đž ҆Đĩ в [ĐŸĐžŅŅ–ĐąĐŊиĐē҃ Đ´ĐģŅ ĐŋŅ€ĐžŅŅƒĐŊŅƒŅ‚Đ¸Ņ… ĐēĐžŅ€Đ¸ŅŅ‚ŅƒĐ˛Đ°Ņ‡Ņ–Đ˛](../advanced/index.md){.internal-link target=_blank}. + +## ДĐĩŅ‚Đ°ĐģŅ– + +ПĐĩŅ€ŅˆĐĩ `"/static"` вĐēĐ°ĐˇŅƒŅ” ĐŊа ĐŋŅ–Đ´ ҈ĐģŅŅ…, Са ŅĐēиĐŧ ĐąŅƒĐ´Đĩ "ĐŋŅ–Đ´'Ņ”Đ´ĐŊаĐŊĐž" ҆ĐĩĐš ĐŊОвиК "ĐˇĐ°ŅŅ‚ĐžŅŅƒĐŊĐžĐē". ĐĸĐžĐŧ҃ ĐąŅƒĐ´ŅŒ-ŅĐēиК ҈ĐģŅŅ…, ŅĐēиК ĐŋĐžŅ‡Đ¸ĐŊĐ°Ņ”Ņ‚ŅŒŅŅ С `"/static"`, ĐąŅƒĐ´Đĩ ĐžĐąŅ€ĐžĐąĐģŅŅ‚Đ¸ŅŅ ĐŊиĐŧ. + +`directory="static"` виСĐŊĐ°Ņ‡Đ°Ņ” ĐēĐ°Ņ‚Đ°ĐģĐžĐŗ, Ņ‰Đž ĐŧŅ–ŅŅ‚Đ¸Ņ‚ŅŒ Đ˛Đ°ŅˆŅ– ŅŅ‚Đ°Ņ‚Đ¸Ņ‡ĐŊŅ– Ņ„Đ°ĐšĐģи. + +`name="static"` ҆Đĩ Ņ–Đŧ'Ņ, ŅĐēĐĩ ĐŧĐžĐļĐŊа виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ Đ˛ŅĐĩŅ€ĐĩдиĐŊŅ– **FastAPI**. + +ĐŖŅŅ– ҆Җ ĐŋĐ°Ņ€Đ°ĐŧĐĩŅ‚Ņ€Đ¸ ĐŧĐžĐļŅƒŅ‚ŅŒ ĐąŅƒŅ‚Đ¸ СĐŧŅ–ĐŊĐĩĐŊŅ– Đ˛Ņ–Đ´ĐŋĐžĐ˛Ņ–Đ´ĐŊĐž Đ´Đž ĐŋĐžŅ‚Ņ€ĐĩĐą Ņ– ĐžŅĐžĐąĐģĐ¸Đ˛ĐžŅŅ‚ĐĩĐš Đ˛Đ°ŅˆĐžĐŗĐž ĐˇĐ°ŅŅ‚ĐžŅŅƒĐŊĐē҃. + +## Đ”ĐžĐ´Đ°Ņ‚ĐēОва Ņ–ĐŊŅ„ĐžŅ€ĐŧĐ°Ņ†Ņ–Ņ + +ДĐĩŅ‚Đ°ĐģҌĐŊŅ–ŅˆĐĩ ĐŋŅ€Đž ĐŊаĐģĐ°ŅˆŅ‚ŅƒĐ˛Đ°ĐŊĐŊŅ Ņ‚Đ° ĐŧĐžĐļĐģĐ¸Đ˛ĐžŅŅ‚Ņ– ĐŧĐžĐļĐŊа Đ´Ņ–ĐˇĐŊĐ°Ņ‚Đ¸ŅŅ в Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Ņ–Ņ— Starlette ĐŋŅ€Đž ŅŅ‚Đ°Ņ‚Đ¸Ņ‡ĐŊŅ– Ņ„Đ°ĐšĐģи. diff --git a/docs/uk/docs/tutorial/testing.md b/docs/uk/docs/tutorial/testing.md new file mode 100644 index 000000000..25fc370d6 --- /dev/null +++ b/docs/uk/docs/tutorial/testing.md @@ -0,0 +1,240 @@ +# ĐĸĐĩŅŅ‚ŅƒĐ˛Đ°ĐŊĐŊŅ + +ĐĸĐĩŅŅ‚ŅƒĐ˛Đ°ĐŊĐŊŅ **FastAPI** Đ´ĐžĐ´Đ°Ņ‚ĐēŅ–Đ˛ Ņ” ĐŋŅ€ĐžŅŅ‚Đ¸Đŧ Ņ‚Đ° ĐĩŅ„ĐĩĐēŅ‚Đ¸Đ˛ĐŊиĐŧ ĐˇĐ°Đ˛Đ´ŅĐēи ĐąŅ–ĐąĐģŅ–ĐžŅ‚Đĩ҆Җ Starlette, ŅĐēа ĐąĐ°ĐˇŅƒŅ”Ņ‚ŅŒŅŅ ĐŊа HTTPX. +ĐžŅĐēŅ–ĐģҌĐēи HTTPX Ņ€ĐžĐˇŅ€ĐžĐąĐģĐĩĐŊиК ĐŊа ĐžŅĐŊĐžĐ˛Ņ– Requests, ĐšĐžĐŗĐž API Ņ” Ņ–ĐŊŅ‚ŅƒŅ—Ņ‚Đ¸Đ˛ĐŊĐž ĐˇŅ€ĐžĐˇŅƒĐŧŅ–ĐģиĐŧ Đ´ĐģŅ Ņ‚Đ¸Ņ…, Ņ…Ņ‚Đž вĐļĐĩ СĐŊаКОĐŧиК С Requests. + +З ĐšĐžĐŗĐž Đ´ĐžĐŋĐžĐŧĐžĐŗĐžŅŽ Ви ĐŧĐžĐļĐĩŅ‚Đĩ виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ pytest ĐąĐĩСĐŋĐžŅĐĩŅ€ĐĩĐ´ĐŊŅŒĐž С **FastAPI**. + +## ВиĐēĐžŅ€Đ¸ŅŅ‚Đ°ĐŊĐŊŅ `TestClient` + +/// info | ІĐŊŅ„ĐžŅ€ĐŧĐ°Ņ†Ņ–Ņ + +ЊОй виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ `TestClient`, ҁĐŋĐžŅ‡Đ°Ņ‚Đē҃ Đ˛ŅŅ‚Đ°ĐŊĐžĐ˛Ņ–Ņ‚ŅŒ `httpx`. + +ПĐĩŅ€ĐĩĐēĐžĐŊĐ°ĐšŅ‚ĐĩŅŅ, Ņ‰Đž Ви ŅŅ‚Đ˛ĐžŅ€Đ¸Đģи [Đ˛Ņ–Ņ€Ņ‚ŅƒĐ°ĐģҌĐŊĐĩ ҁĐĩŅ€ĐĩĐ´ĐžĐ˛Đ¸Ņ‰Đĩ](../virtual-environments.md){.internal-link target=_blank}, аĐēŅ‚Đ¸Đ˛ŅƒĐ˛Đ°Đģи ĐšĐžĐŗĐž, а ĐŋĐžŅ‚Ņ–Đŧ Đ˛ŅŅ‚Đ°ĐŊОвиĐģи ŅĐ°Đŧ҃ ĐąŅ–ĐąĐģŅ–ĐžŅ‚ĐĩĐē҃, ĐŊаĐŋŅ€Đ¸ĐēĐģад: + +```console +$ pip install httpx +``` + +/// + +ІĐŧĐŋĐžŅ€Ņ‚ŅƒĐšŅ‚Đĩ `TestClient`. + +ĐĄŅ‚Đ˛ĐžŅ€Ņ–Ņ‚ŅŒ `TestClient`, ĐŋĐĩŅ€ĐĩĐ´Đ°Đ˛ŅˆĐ¸ КОĐŧ҃ Đ’Đ°Ņˆ ĐˇĐ°ŅŅ‚ĐžŅŅƒĐŊĐžĐē **FastAPI**. + +ĐĄŅ‚Đ˛ĐžŅ€ŅŽĐšŅ‚Đĩ Ņ„ŅƒĐŊĐē҆Җҗ С Ņ–ĐŧĐĩĐŊаĐŧи, Ņ‰Đž ĐŋĐžŅ‡Đ¸ĐŊĐ°ŅŽŅ‚ŅŒŅŅ С `test_` (҆Đĩ ŅŅ‚Đ°ĐŊĐ´Đ°Ņ€Ņ‚ĐŊа ŅƒĐŗĐžĐ´Đ° Đ´ĐģŅ `pytest`). + +ВиĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐšŅ‚Đĩ Ой'Ņ”ĐēŅ‚ `TestClient` Ņ‚Đ°Đē ŅĐ°ĐŧĐž ŅĐē Ņ– `httpx`. + +ЗаĐŋĐ¸ŅŅƒĐšŅ‚Đĩ ĐŋŅ€ĐžŅŅ‚Ņ– `assert`-Đ˛Đ¸Ņ€Đ°ĐˇĐ¸ ĐˇŅ– ŅŅ‚Đ°ĐŊĐ´Đ°Ņ€Ņ‚ĐŊиĐŧи Đ˛Đ¸Ņ€Đ°ĐˇĐ°Đŧи Python, ŅĐēŅ– ĐŋĐžŅ‚Ņ€Ņ–ĐąĐŊĐž ĐŋĐĩŅ€ĐĩĐ˛Ņ–Ņ€Đ¸Ņ‚Đ¸ (҆Đĩ Ņ‚Đ°ĐēĐžĐļ ŅŅ‚Đ°ĐŊĐ´Đ°Ņ€Ņ‚ Đ´ĐģŅ `pytest`). + +{* ../../docs_src/app_testing/tutorial001.py hl[2,12,15:18] *} + + +/// tip | ĐŸĐžŅ€Đ°Đ´Đ° + +ЗвĐĩŅ€ĐŊŅ–Ņ‚ŅŒ ŅƒĐ˛Đ°ĐŗŅƒ, Ņ‰Đž Ņ‚ĐĩŅŅ‚ĐžĐ˛Ņ– Ņ„ŅƒĐŊĐē҆Җҗ — ҆Đĩ ĐˇĐ˛Đ¸Ņ‡Đ°ĐšĐŊŅ– `def`, а ĐŊĐĩ `async def`. + +ВиĐēĐģиĐēи ĐēĐģŅ–Ņ”ĐŊŅ‚Đ° Ņ‚Đ°ĐēĐžĐļ ĐˇĐ˛Đ¸Ņ‡Đ°ĐšĐŊŅ–, ĐąĐĩС виĐēĐžŅ€Đ¸ŅŅ‚Đ°ĐŊĐŊŅ `await`. + +ĐĻĐĩ дОСвОĐģŅŅ” виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ `pytest` ĐąĐĩС ĐˇĐ°ĐšĐ˛Đ¸Ņ… ҃ҁĐēĐģадĐŊĐĩĐŊҌ. + +/// + +/// note | ĐĸĐĩŅ…ĐŊҖ҇ĐŊŅ– Đ´ĐĩŅ‚Đ°ĐģŅ– + +Ви Ņ‚Đ°ĐēĐžĐļ ĐŧĐžĐļĐĩŅ‚Đĩ виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ `from starlette.testclient import TestClient`. + +**FastAPI** ĐŊĐ°Đ´Đ°Ņ” Ņ‚ĐžĐš ŅĐ°ĐŧиК `starlette.testclient` ĐŋŅ–Đ´ ĐŊĐ°ĐˇĐ˛ĐžŅŽ `fastapi.testclient` Đ´ĐģŅ ĐˇŅ€ŅƒŅ‡ĐŊĐžŅŅ‚Ņ– Ņ€ĐžĐˇŅ€ĐžĐąĐŊиĐēŅ–Đ˛, аĐģĐĩ Đ˛Ņ–ĐŊ ĐąĐĩСĐŋĐžŅĐĩŅ€ĐĩĐ´ĐŊŅŒĐž ĐŋĐžŅ…ĐžĐ´Đ¸Ņ‚ŅŒ Ņ–Đˇ Starlette. + +/// + +/// tip | ĐŸĐžŅ€Đ°Đ´Đ° + +Đ¯ĐēŅ‰Đž ВаĐŧ ĐŋĐžŅ‚Ņ€Ņ–ĐąĐŊĐž виĐēĐģиĐēĐ°Ņ‚Đ¸ `async`-Ņ„ŅƒĐŊĐē҆Җҗ ҃ Đ˛Đ°ŅˆĐ¸Ņ… Ņ‚ĐĩŅŅ‚Đ°Ņ…, ĐžĐēҀҖĐŧ Đ˛Ņ–Đ´ĐŋŅ€Đ°Đ˛ĐģĐĩĐŊĐŊŅ СаĐŋĐ¸Ņ‚Ņ–Đ˛ Đ´Đž FastAPI-ĐˇĐ°ŅŅ‚ĐžŅŅƒĐŊĐē҃ (ĐŊаĐŋŅ€Đ¸ĐēĐģад, Đ°ŅĐ¸ĐŊŅ…Ņ€ĐžĐŊĐŊŅ– Ņ„ŅƒĐŊĐē҆Җҗ Ņ€ĐžĐąĐžŅ‚Đ¸ С ĐąĐ°ĐˇĐžŅŽ даĐŊĐ¸Ņ…), ĐŋĐĩŅ€ĐĩĐŗĐģŅĐŊŅŒŅ‚Đĩ [ĐŅĐ¸ĐŊŅ…Ņ€ĐžĐŊĐŊŅ– Ņ‚ĐĩŅŅ‚Đ¸](../advanced/async-tests.md){.internal-link target=_blank} ҃ Ņ€ĐžĐˇŅˆĐ¸Ņ€ĐĩĐŊĐžĐŧ҃ ĐēĐĩŅ€Ņ–Đ˛ĐŊĐ¸Ņ†Ņ‚Đ˛Ņ–. + +/// + +## Đ ĐžĐˇĐ´Ņ–ĐģĐĩĐŊĐŊŅ Ņ‚ĐĩŅŅ‚Ņ–Đ˛ + +ĐŖ Ņ€ĐĩаĐģҌĐŊĐžĐŧ҃ ĐˇĐ°ŅŅ‚ĐžŅŅƒĐŊĐē҃ Đ’Đ°ŅˆŅ– Ņ‚ĐĩŅŅ‚Đ¸, ĐšĐŧĐžĐ˛Ņ–Ņ€ĐŊĐž, ĐąŅƒĐ´ŅƒŅ‚ŅŒ в ĐžĐēŅ€ĐĩĐŧĐžĐŧ҃ Ņ„Đ°ĐšĐģŅ–. + +ĐĸаĐēĐžĐļ Đ’Đ°Ņˆ **FastAPI**-ĐˇĐ°ŅŅ‚ĐžŅŅƒĐŊĐžĐē ĐŧĐžĐļĐĩ ҁĐēĐģĐ°Đ´Đ°Ņ‚Đ¸ŅŅ С ĐēŅ–ĐģҌĐēĐžŅ… Ņ„Đ°ĐšĐģŅ–Đ˛ айО ĐŧĐžĐ´ŅƒĐģŅ–Đ˛ Ņ‚ĐžŅ‰Đž. + +### ФаКĐģ ĐˇĐ°ŅŅ‚ĐžŅŅƒĐŊĐē҃ **FastAPI** + +ĐŸŅ€Đ¸ĐŋŅƒŅŅ‚Đ¸ĐŧĐž, ҃ Đ’Đ°Ņ Ņ” ŅŅ‚Ņ€ŅƒĐēŅ‚ŅƒŅ€Đ° Ņ„Đ°ĐšĐģŅ–Đ˛, ĐžĐŋĐ¸ŅĐ°ĐŊа в Ņ€ĐžĐˇĐ´Ņ–ĐģŅ– [Đ‘Ņ–ĐģŅŒŅˆŅ– ĐˇĐ°ŅŅ‚ĐžŅŅƒĐŊĐēи](bigger-applications.md){.internal-link target=_blank}: + +``` +. +├── app +│   ├── __init__.py +│   └── main.py +``` +ĐŖ Ņ„Đ°ĐšĐģŅ– `main.py` СĐŊĐ°Ņ…ĐžĐ´Đ¸Ņ‚ŅŒŅŅ Đ’Đ°Ņˆ ĐˇĐ°ŅŅ‚ĐžŅŅƒĐŊĐžĐē **FastAPI** : + +{* ../../docs_src/app_testing/main.py *} + +### ФаКĐģ Ņ‚ĐĩŅŅ‚ŅƒĐ˛Đ°ĐŊĐŊŅ + +Ви ĐŧĐžĐļĐĩŅ‚Đĩ ŅŅ‚Đ˛ĐžŅ€Đ¸Ņ‚Đ¸ Ņ„Đ°ĐšĐģ `test_main.py` С Đ’Đ°ŅˆĐ¸Đŧи Ņ‚ĐĩŅŅ‚Đ°Đŧи. Đ’Ņ–ĐŊ ĐŧĐžĐļĐĩ СĐŊĐ°Ņ…ĐžĐ´Đ¸Ņ‚Đ¸ŅŅ в Ņ‚ĐžĐŧ҃ Đļ ĐŋаĐēĐĩ҂Җ Python (҃ Ņ‚Ņ–Đš ŅĐ°ĐŧŅ–Đš Đ´Đ¸Ņ€ĐĩĐēŅ‚ĐžŅ€Ņ–Ņ— С Ņ„Đ°ĐšĐģĐžĐŧ `__init__.py`): + + +``` hl_lines="5" +. +├── app +│   ├── __init__.py +│   ├── main.py +│   └── test_main.py +``` + +ĐžŅĐēŅ–ĐģҌĐēи ҆ĐĩĐš Ņ„Đ°ĐšĐģ СĐŊĐ°Ņ…ĐžĐ´Đ¸Ņ‚ŅŒŅŅ в Ņ‚ĐžĐŧ҃ Đļ ĐŋаĐēĐĩ҂Җ, Ви ĐŧĐžĐļĐĩŅ‚Đĩ виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ Đ˛Ņ–Đ´ĐŊĐžŅĐŊиК Ņ–ĐŧĐŋĐžŅ€Ņ‚, Ņ‰ĐžĐą Ņ–ĐŧĐŋĐžŅ€Ņ‚ŅƒĐ˛Đ°Ņ‚Đ¸ Ой'Ņ”ĐēŅ‚ `app` Ņ–Đˇ ĐŧĐžĐ´ŅƒĐģŅ `main` (`main.py`): + +{* ../../docs_src/app_testing/test_main.py hl[3] *} + + +...Ņ– ĐŊаĐŋĐ¸ŅĐ°Ņ‚Đ¸ ĐēОд Đ´ĐģŅ Ņ‚ĐĩŅŅ‚Ņ–Đ˛ Ņ‚Đ°Đē ŅĐ°ĐŧĐž ŅĐē Ņ– Ņ€Đ°ĐŊŅ–ŅˆĐĩ. + +## ĐĸĐĩŅŅ‚ŅƒĐ˛Đ°ĐŊĐŊŅ: Ņ€ĐžĐˇŅˆĐ¸Ņ€ĐĩĐŊиК ĐŋŅ€Đ¸ĐēĐģад + +ĐĸĐĩĐŋĐĩŅ€ Ņ€ĐžĐˇŅˆĐ¸Ņ€Đ¸ĐŧĐž ҆ĐĩĐš ĐŋŅ€Đ¸ĐēĐģад Ņ– дОдаĐŧĐž ĐąŅ–ĐģҌ҈Đĩ Đ´ĐĩŅ‚Đ°ĐģĐĩĐš, Ņ‰ĐžĐą ĐŋĐžĐąĐ°Ņ‡Đ¸Ņ‚Đ¸, ŅĐē Ņ‚ĐĩŅŅ‚ŅƒĐ˛Đ°Ņ‚Đ¸ Ņ€Ņ–ĐˇĐŊŅ– Ņ‡Đ°ŅŅ‚Đ¸ĐŊи. + +### Đ ĐžĐˇŅˆĐ¸Ņ€ĐĩĐŊиК Ņ„Đ°ĐšĐģ ĐˇĐ°ŅŅ‚ĐžŅŅƒĐŊĐē҃ **FastAPI** + +ЗаĐģĐ¸ŅˆĐ¸ĐŧĐž Ņ‚Ņƒ ŅĐ°Đŧ҃ ŅŅ‚Ņ€ŅƒĐēŅ‚ŅƒŅ€Ņƒ Ņ„Đ°ĐšĐģŅ–Đ˛: + +``` +. +├── app +│   ├── __init__.py +│   ├── main.py +│   └── test_main.py +``` + +ĐŸŅ€Đ¸ĐŋŅƒŅŅ‚Đ¸ĐŧĐž, Ņ‰Đž Ņ‚ĐĩĐŋĐĩŅ€ Ņ„Đ°ĐšĐģ `main.py` Ņ–Đˇ Đ’Đ°ŅˆĐ¸Đŧ **FastAPI**-ĐˇĐ°ŅŅ‚ĐžŅŅƒĐŊĐēĐžĐŧ ĐŧŅ–ŅŅ‚Đ¸Ņ‚ŅŒ Đ´ĐžĐ´Đ°Ņ‚ĐēĐžĐ˛Ņ– ĐžĐŋĐĩŅ€Đ°Ņ†Ņ–Ņ— ҈ĐģŅŅ…Ņƒ (**path operations**). + +Đ’Ņ–ĐŊ ĐŧĐ°Ņ” `GET`-ĐžĐŋĐĩŅ€Đ°Ņ†Ņ–ŅŽ, ŅĐēа ĐŧĐžĐļĐĩ ĐŋОвĐĩŅ€Ņ‚Đ°Ņ‚Đ¸ ĐŋĐžĐŧиĐģĐē҃. + +Đ’Ņ–ĐŊ ĐŧĐ°Ņ” `POST`-ĐžĐŋĐĩŅ€Đ°Ņ†Ņ–ŅŽ, ŅĐēа ĐŧĐžĐļĐĩ ĐŋОвĐĩŅ€Ņ‚Đ°Ņ‚Đ¸ ĐēŅ–ĐģҌĐēа ĐŋĐžĐŧиĐģĐžĐē. + +ĐžĐąĐ¸Đ´Đ˛Ņ– ĐžĐŋĐĩŅ€Đ°Ņ†Ņ–Ņ— ҈ĐģŅŅ…Ņƒ виĐŧĐ°ĐŗĐ°ŅŽŅ‚ŅŒ ĐˇĐ°ĐŗĐžĐģОвОĐē `X-Token`. + +//// tab | Python 3.10+ + +```Python +{!> ../../docs_src/app_testing/app_b_an_py310/main.py!} +``` + +//// + +//// tab | Python 3.9+ + +```Python +{!> ../../docs_src/app_testing/app_b_an_py39/main.py!} +``` + +//// + +//// tab | Python 3.8+ + +```Python +{!> ../../docs_src/app_testing/app_b_an/main.py!} +``` + +//// + +//// tab | Python 3.10+ non-Annotated + +/// tip | ĐŸĐžŅ€Đ°Đ´Đ° + +БаĐļаĐŊĐž виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ вĐĩŅ€ŅŅ–ŅŽ С `Annotated`, ŅĐēŅ‰Đž ҆Đĩ ĐŧĐžĐļĐģивО + +/// + +```Python +{!> ../../docs_src/app_testing/app_b_py310/main.py!} +``` + +//// + +//// tab | Python 3.8+ non-Annotated + +/// tip | ĐŸĐžŅ€Đ°Đ´Đ° + +БаĐļаĐŊĐž виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐ˛Đ°Ņ‚Đ¸ вĐĩŅ€ŅŅ–ŅŽ С `Annotated`, ŅĐēŅ‰Đž ҆Đĩ ĐŧĐžĐļĐģивО + +/// + +```Python +{!> ../../docs_src/app_testing/app_b/main.py!} +``` + +//// + +### Đ ĐžĐˇŅˆĐ¸Ņ€ĐĩĐŊиК Ņ‚ĐĩŅŅ‚ĐžĐ˛Đ¸Đš Ņ„Đ°ĐšĐģ + +ĐŸĐžŅ‚Ņ–Đŧ Ви ĐŧĐžĐļĐĩŅ‚Đĩ ĐžĐŊĐžĐ˛Đ¸Ņ‚Đ¸ `test_main.py`, Đ´ĐžĐ´Đ°Đ˛ŅˆĐ¸ Ņ€ĐžĐˇŅˆĐ¸Ņ€ĐĩĐŊŅ– Ņ‚ĐĩŅŅ‚Đ¸: + +{* ../../docs_src/app_testing/app_b/test_main.py *} + +КоĐģи ВаĐŧ ĐŋĐžŅ‚Ņ€Ņ–ĐąĐŊĐž ĐŋĐĩŅ€ĐĩĐ´Đ°Ņ‚Đ¸ ĐēĐģŅ–Ņ”ĐŊŅ‚Ņƒ Ņ–ĐŊŅ„ĐžŅ€ĐŧĐ°Ņ†Ņ–ŅŽ в СаĐŋĐ¸Ņ‚Ņ–, аĐģĐĩ Ви ĐŊĐĩ СĐŊĐ°Ņ”Ņ‚Đĩ, ŅĐē ҆Đĩ ĐˇŅ€ĐžĐąĐ¸Ņ‚Đ¸, Ви ĐŧĐžĐļĐĩŅ‚Đĩ ĐŋĐžŅˆŅƒĐēĐ°Ņ‚Đ¸ (ĐŊаĐŋŅ€Đ¸ĐēĐģад, ҃ Google) ҁĐŋĐžŅŅ–Đą Ņ€ĐĩаĐģŅ–ĐˇĐ°Ņ†Ņ–Ņ— в `httpx`, айО ĐŊĐ°Đ˛Ņ–Ņ‚ŅŒ ҃ `requests`, ĐžŅĐēŅ–ĐģҌĐēи HTTPX Ņ€ĐžĐˇŅ€ĐžĐąĐģĐĩĐŊиК ĐŊа ĐžŅĐŊĐžĐ˛Ņ– диСаКĐŊ҃ Requests. + +ДаĐģŅ– Ви ĐŋŅ€ĐžŅŅ‚Đž ĐŋĐžĐ˛Ņ‚ĐžŅ€ŅŽŅ”Ņ‚Đĩ ҆Җ Đļ Đ´Ņ–Ņ— ҃ Đ˛Đ°ŅˆĐ¸Ņ… Ņ‚ĐĩŅŅ‚Đ°Ņ…. + +НаĐŋŅ€Đ¸ĐēĐģад: + +* ЊОй ĐŋĐĩŅ€ĐĩĐ´Đ°Ņ‚Đ¸ *path* айО *query* ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ, Đ´ĐžĐ´Đ°ĐšŅ‚Đĩ ĐšĐžĐŗĐž ĐąĐĩСĐŋĐžŅĐĩŅ€ĐĩĐ´ĐŊŅŒĐž Đ´Đž URL. +* ЊОй ĐŋĐĩŅ€ĐĩĐ´Đ°Ņ‚Đ¸ ҂ҖĐģĐž JSON, ĐŋĐĩŅ€ĐĩĐ´Đ°ĐšŅ‚Đĩ Python-Ой'Ņ”ĐēŅ‚ (ĐŊаĐŋŅ€Đ¸ĐēĐģад, `dict`) ҃ ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ `json`. +* Đ¯ĐēŅ‰Đž ĐŋĐžŅ‚Ņ€Ņ–ĐąĐŊĐž ĐŊĐ°Đ´Ņ–ŅĐģĐ°Ņ‚Đ¸ *Form Data* СаĐŧŅ–ŅŅ‚ŅŒ JSON, виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐšŅ‚Đĩ ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂Ҁ `data`. +* ЊОй ĐŋĐĩŅ€ĐĩĐ´Đ°Ņ‚Đ¸ ĐˇĐ°ĐŗĐžĐģОвĐēи *headers*, виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐšŅ‚Đĩ `dict` ҃ ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂ҀҖ `headers`. +* ДĐģŅ *cookies* виĐēĐžŅ€Đ¸ŅŅ‚ĐžĐ˛ŅƒĐšŅ‚Đĩ `dict` ҃ ĐŋĐ°Ņ€Đ°ĐŧĐĩ҂ҀҖ `cookies`. + +ДоĐēĐģадĐŊŅ–ŅˆĐĩ ĐŋŅ€Đž ĐŋĐĩŅ€ĐĩĐ´Đ°Ņ‡Ņƒ даĐŊĐ¸Ņ… ҃ ĐąĐĩĐēĐĩĐŊĐ´ (Са Đ´ĐžĐŋĐžĐŧĐžĐŗĐžŅŽ `httpx` айО `TestClient`) ĐŧĐžĐļĐŊа СĐŊĐ°ĐšŅ‚Đ¸ в Đ´ĐžĐē҃ĐŧĐĩĐŊŅ‚Đ°Ņ†Ņ–Ņ— HTTPX. + +/// info | ІĐŊŅ„ĐžŅ€ĐŧĐ°Ņ†Ņ–Ņ + +ЗвĐĩŅ€ĐŊŅ–Ņ‚ŅŒ ŅƒĐ˛Đ°ĐŗŅƒ, Ņ‰Đž `TestClient` ĐžŅ‚Ņ€Đ¸ĐŧŅƒŅ” даĐŊŅ–, ŅĐēŅ– ĐŧĐžĐļĐŊа ĐēĐžĐŊвĐĩŅ€Ņ‚ŅƒĐ˛Đ°Ņ‚Đ¸ в JSON, а ĐŊĐĩ Pydantic-ĐŧОдĐĩĐģŅ–. +Đ¯ĐēŅ‰Đž ҃ Đ’Đ°Ņ Ņ” Pydantic-ĐŧОдĐĩĐģҌ ҃ Ņ‚Đĩҁ҂Җ, Ņ– Ви Ņ…ĐžŅ‡ĐĩŅ‚Đĩ ĐŋĐĩŅ€ĐĩĐ´Đ°Ņ‚Đ¸ Ņ—Ņ— даĐŊŅ– в Đ´ĐžĐ´Đ°Ņ‚ĐžĐē ĐŋŅ–Đ´ Ņ‡Đ°Ņ Ņ‚ĐĩŅŅ‚ŅƒĐ˛Đ°ĐŊĐŊŅ, Ви ĐŧĐžĐļĐĩŅ‚Đĩ виĐēĐžŅ€Đ¸ŅŅ‚Đ°Ņ‚Đ¸ `jsonable_encoder`, ĐžĐŋĐ¸ŅĐ°ĐŊиК ҃ Ņ€ĐžĐˇĐ´Ņ–ĐģŅ– [JSON Compatible Encoder](encoder.md){.internal-link target=_blank}. + +/// + +## ЗаĐŋ҃ҁĐē Ņ‚ĐĩŅŅ‚Ņ–Đ˛ + +ĐŸŅ–ŅĐģŅ Ņ†ŅŒĐžĐŗĐž ваĐŧ ĐŋĐžŅ‚Ņ€Ņ–ĐąĐŊĐž Đ˛ŅŅ‚Đ°ĐŊĐžĐ˛Đ¸Ņ‚Đ¸ `pytest`. + +ПĐĩŅ€ĐĩĐēĐžĐŊĐ°ĐšŅ‚ĐĩŅŅ, Ņ‰Đž Ви ŅŅ‚Đ˛ĐžŅ€Đ¸Đģи [Đ˛Ņ–Ņ€Ņ‚ŅƒĐ°ĐģҌĐŊĐĩ ҁĐĩŅ€ĐĩĐ´ĐžĐ˛Đ¸Ņ‰Đĩ]{.internal-link target=_blank}, аĐēŅ‚Đ¸Đ˛ŅƒĐ˛Đ°Đģи ĐšĐžĐŗĐž Ņ– Đ˛ŅŅ‚Đ°ĐŊОвиĐģи ĐŊĐĩĐžĐąŅ…Ņ–Đ´ĐŊŅ– ĐŋаĐēĐĩŅ‚Đ¸, ĐŊаĐŋŅ€Đ¸ĐēĐģад: + +
+ +```console +$ pip install pytest + +---> 100% +``` + +
+ +`pytest` Đ°Đ˛Ņ‚ĐžĐŧĐ°Ņ‚Đ¸Ņ‡ĐŊĐž СĐŊаКдĐĩ Ņ„Đ°ĐšĐģи С Ņ‚ĐĩŅŅ‚Đ°Đŧи, виĐēĐžĐŊĐ°Ņ” Ņ—Ņ… Ņ– ĐŊĐ°Đ´Đ°ŅŅ‚ŅŒ ваĐŧ Ņ€ĐĩĐˇŅƒĐģŅŒŅ‚Đ°Ņ‚Đ¸. + +ЗаĐŋŅƒŅŅ‚Ņ–Ņ‚ŅŒ Ņ‚ĐĩŅŅ‚Đ¸ Са Đ´ĐžĐŋĐžĐŧĐžĐŗĐžŅŽ: + +
+ +```console +$ pytest + +================ test session starts ================ +platform linux -- Python 3.6.9, pytest-5.3.5, py-1.8.1, pluggy-0.13.1 +rootdir: /home/user/code/superawesome-cli/app +plugins: forked-1.1.3, xdist-1.31.0, cov-2.8.1 +collected 6 items + +---> 100% + +test_main.py ...... [100%] + +================= 1 passed in 0.03s ================= +``` + +
diff --git a/docs/vi/docs/deployment/cloud.md b/docs/vi/docs/deployment/cloud.md new file mode 100644 index 000000000..9ab72769d --- /dev/null +++ b/docs/vi/docs/deployment/cloud.md @@ -0,0 +1,17 @@ +# Triáģƒn khai FastAPI trÃĒn cÃĄc Dáģ‹ch váģĨ Cloud + +BáēĄn cÃŗ tháģƒ sáģ­ dáģĨng **báēĨt káģŗ nhà cung cáēĨp dáģ‹ch váģĨ cloud** nào đáģƒ triáģƒn khai áģŠng dáģĨng FastAPI cáģ§a mÃŦnh. + +Trong háē§u háēŋt cÃĄc trưáģng háģŖp, cÃĄc nhà cung cáēĨp dáģ‹ch váģĨ cloud láģ›n đáģu cÃŗ hưáģ›ng dáēĢn triáģƒn khai FastAPI váģ›i háģ. + +## Nhà cung cáēĨp dáģ‹ch váģĨ Cloud - Nhà tài tráģŖ +Máģ™t vài nhà cung cáēĨp dáģ‹ch váģĨ cloud ✨ [**tài tráģŖ cho FastAPI**](../help-fastapi.md#sponsor-the-author){.internal-link target=_blank} ✨, điáģu này giÃēp đáēŖm báēŖo sáģą phÃĄt triáģƒn liÃĒn táģĨc và kháģe máēĄnh cáģ§a FastAPI và háģ‡ sinh thÃĄi cáģ§a nÃŗ. + +ThÃĒm náģ¯a, điáģu này cÅŠng tháģƒ hiáģ‡n cam káēŋt tháģąc sáģą cáģ§a háģ Ä‘áģ‘i váģ›i FastAPI và **cáģ™ng đáģ“ng ngưáģi dÚng** (báēĄn), vÃŦ háģ không cháģ‰ muáģ‘n cung cáēĨp cho báēĄn máģ™t **dáģ‹ch váģĨ táģ‘t** mà cÃ˛n muáģ‘n đáēŖm báēŖo ráēąng báēĄn cÃŗ máģ™t **framework táģ‘t và báģn váģ¯ng**, Ä‘Ãŗ chính là FastAPI. 🙇 + +BáēĄn cÃŗ tháģƒ tháģ­ cÃĄc dáģ‹ch váģĨ cáģ§a háģ và làm theo hưáģ›ng dáēĢn cáģ§a háģ: + +* Platform.sh +* Porter +* Coherence +* Render diff --git a/docs/vi/docs/deployment/index.md b/docs/vi/docs/deployment/index.md new file mode 100644 index 000000000..24ffdc71b --- /dev/null +++ b/docs/vi/docs/deployment/index.md @@ -0,0 +1,21 @@ +# Triáģƒn khai + +Triáģƒn khai máģ™t áģŠng dáģĨng **FastAPI** khÃĄ dáģ… dàng. + +## Triáģƒn khai là gÃŦ + +Triáģƒn khai máģ™t áģŠng dáģĨng cÃŗ nghÄŠa là tháģąc hiáģ‡n cÃĄc bưáģ›c cáē§n thiáēŋt đáģƒ làm cho nÃŗ **sáēĩn sàng pháģĨc váģĨ ngưáģi dÚng**. + +Đáģ‘i váģ›i máģ™t **API web**, điáģu này cÃŗ nghÄŠa là đáēˇt nÃŗ trong máģ™t **mÃĄy cháģ§ táģĢ xa**, váģ›i máģ™t **chÆ°ÆĄng trÃŦnh mÃĄy cháģ§** cung cáēĨp hiáģ‡u suáēĨt táģ‘t, áģ•n đáģ‹nh, v.v., đáģƒ ngưáģi dÚng cáģ§a báēĄn cÃŗ tháģƒ truy cáē­p áģŠng dáģĨng cáģ§a báēĄn máģ™t cÃĄch hiáģ‡u quáēŖ và không báģ‹ giÃĄn đoáēĄn hoáēˇc gáēˇp váēĨn đáģ. + +Điáģu này trÃĄi ngưáģŖc váģ›i cÃĄc **giai đoáēĄn phÃĄt triáģƒn**, trong Ä‘Ãŗ báēĄn liÃĒn táģĨc thay đáģ•i mÃŖ, phÃĄ váģĄ nÃŗ và sáģ­a nÃŗ, ngáģĢng và kháģŸi đáģ™ng láēĄi mÃĄy cháģ§ phÃĄt triáģƒn, v.v. + +## CÃĄc Chiáēŋn lưáģŖc Triáģƒn khai + +CÃŗ nhiáģu cÃĄch đáģƒ triáģƒn khai áģŠng dáģĨng cáģ§a báēĄn tÚy thuáģ™c vào trưáģng háģŖp sáģ­ dáģĨng cáģ§a báēĄn và cÃĄc công cáģĨ mà báēĄn sáģ­ dáģĨng. + +BáēĄn cÃŗ tháģƒ **triáģƒn khai máģ™t mÃĄy cháģ§** cáģ§a riÃĒng báēĄn báēąng cÃĄch sáģ­ dáģĨng máģ™t sáģą káēŋt háģŖp cÃĄc công cáģĨ, hoáēˇc báēĄn cÃŗ tháģƒ sáģ­ dáģĨng máģ™t **dáģ‹ch váģĨ cloud** đáģƒ làm máģ™t sáģ‘ công viáģ‡c cho báēĄn, hoáēˇc cÃĄc tÚy cháģn khÃĄc. + +Tôi sáēŊ cháģ‰ ra máģ™t sáģ‘ khÃĄi niáģ‡m chính cáē§n thiáēŋt khi triáģƒn khai máģ™t áģŠng dáģĨng **FastAPI** (máēˇc dÚ háē§u háēŋt nÃŗ ÃĄp dáģĨng cho báēĨt káģŗ loáēĄi áģŠng dáģĨng web nào). + +BáēĄn sáēŊ tháēĨy nhiáģu chi tiáēŋt cáē§n thiáēŋt và máģ™t sáģ‘ káģš thuáē­t đáģƒ triáģƒn khai trong cÃĄc pháē§n tiáēŋp theo. ✨ diff --git a/docs/vi/docs/deployment/versions.md b/docs/vi/docs/deployment/versions.md new file mode 100644 index 000000000..04de393e7 --- /dev/null +++ b/docs/vi/docs/deployment/versions.md @@ -0,0 +1,93 @@ +# Váģ cÃĄc phiÃĒn báēŖn cáģ§a FastAPI + +**FastAPI** Ä‘ÃŖ đưáģŖc sáģ­ dáģĨng áģŸ quy mô tháģąc táēŋ (production) trong nhiáģu áģŠng dáģĨng và háģ‡ tháģ‘ng. Và pháēĄm vi kiáģƒm tháģ­ Ä‘Æ°áģŖc giáģ¯ áģŸ máģŠc 100%. Nhưng viáģ‡c phÃĄt triáģƒn cáģ§a nÃŗ váēĢn đang diáģ…n ra nhanh chÃŗng. + +CÃĄc tính năng máģ›i đưáģŖc báģ• sung thưáģng xuyÃĒn, láģ—i đưáģŖc sáģ­a đáģ‹nh káģŗ, và mÃŖ nguáģ“n váēĢn đang đưáģŖc cáēŖi thiáģ‡n liÃĒn táģĨc + +ÄÃŗ là lí do cÃĄc phiÃĒn báēŖn hiáģ‡n táēĄi váēĢn cÃ˛n là 0.x.x, điáģu này pháēŖn ÃĄnh ráēąng máģ—i phiÃĒn báēŖn cÃŗ tháģƒ cÃŗ cÃĄc thay đáģ•i gÃĸy máēĨt tÆ°ÆĄng thích. Điáģu này tuÃĸn theo cÃĄc quy ưáģ›c váģ Semantic Versioning. + +BáēĄn cÃŗ tháģƒ táēĄo ra sáēŖn pháēŠm tháģąc táēŋ váģ›i **FastAPI** ngay bÃĸy giáģ (và báēĄn cÃŗ tháģƒ Ä‘ÃŖ làm điáģu này trong máģ™t tháģi gian dài), báēĄn cháģ‰ cáē§n đáēŖm báēŖo ráēąng báēĄn sáģ­ dáģĨng máģ™t phiÃĒn báēŖn hoáēĄt đáģ™ng đÃēng váģ›i cÃĄc đoáēĄn mÃŖ cÃ˛n láēĄi cáģ§a báēĄn. + +## Cáģ‘ Ä‘áģ‹nh phiÃĒn báēŖn cáģ§a `fastapi` + +Điáģu đáē§u tiÃĒn báēĄn nÃĒn làm là "cáģ‘ Ä‘áģ‹nh" phiÃĒn báēŖn cáģ§a **FastAPI** báēĄn đang sáģ­ dáģĨng đáģƒ phiÃĒn báēŖn máģ›i nháēĨt mà báēĄn biáēŋt hoáēĄt đáģ™ng đÃēng váģ›i áģŠng dáģĨng cáģ§a báēĄn. + +Ví dáģĨ, giáēŖ sáģ­ báēĄn đang sáģ­ dáģĨng phiÃĒn báēŖn `0.112.0` trong áģŠng dáģĨng cáģ§a báēĄn. + +Náēŋu báēĄn sáģ­ dáģĨng máģ™t táģ‡p `requirements.txt` báēĄn cÃŗ tháģƒ cháģ‰ Ä‘áģ‹nh phiÃĒn báēŖn váģ›i: + +```txt +fastapi[standard]==0.112.0 +``` + +Như váē­y, báēĄn sáēŊ sáģ­ dáģĨng chính xÃĄc phiÃĒn báēŖn `0.112.0`. + +Hoáēˇc báēĄn cÅŠng cÃŗ tháģƒ cáģ‘ Ä‘áģ‹nh nÃŗ váģ›i: + +```txt +fastapi[standard]>=0.112.0,<0.113.0 +``` + +Như váē­y, báēĄn sáēŊ sáģ­ dáģĨng cÃĄc phiÃĒn báēŖn `0.112.0` tráģŸ lÃĒn, nhưng nháģ hÆĄn `0.113.0`, ví dáģĨ, máģ™t phiÃĒn báēŖn `0.112.2` váēĢn đưáģŖc cháēĨp nháē­n. + +Náēŋu báēĄn sáģ­ dáģĨng báēĨt káģŗ công cáģĨ nào đáģƒ quáēŖn lÃŊ cài đáēˇt cáģ§a báēĄn, như `uv`, Poetry, Pipenv, hoáēˇc báēĨt káģŗ công cáģĨ nào khÃĄc, chÃēng đáģu cÃŗ máģ™t cÃĄch đáģƒ báēĄn cÃŗ tháģƒ Ä‘áģ‹nh nghÄŠa cÃĄc phiÃĒn báēŖn cáģĨ tháģƒ cho cÃĄc gÃŗi cáģ§a báēĄn. + +## CÃĄc phiÃĒn báēŖn cÃŗ sáēĩn + +BáēĄn cÃŗ tháģƒ xem cÃĄc phiÃĒn báēŖn cÃŗ sáēĩn (ví dáģĨ đáģƒ kiáģƒm tra phiÃĒn báēŖn máģ›i nháēĨt) trong [Release Notes](../release-notes.md){.internal-link target=_blank}. + +## Váģ cÃĄc phiÃĒn báēŖn + +Theo quy ưáģ›c váģ Semantic Versioning, báēĨt káģŗ phiÃĒn báēŖn nào bÃĒn dưáģ›i `1.0.0` cÃŗ tháģƒ thÃĒm cÃĄc thay đáģ•i gÃĸy máēĨt tÆ°ÆĄng thích. + +**FastAPI** cÅŠng theo quy ưáģ›c ráēąng báēĨt káģŗ thay đáģ•i phiÃĒn báēŖn "PATCH" nào là cho cÃĄc láģ—i và cÃĄc thay đáģ•i không gÃĸy máēĨt tÆ°ÆĄng thích. + +/// tip + +"PATCH" là sáģ‘ cuáģ‘i cÚng, ví dáģĨ, trong `0.2.3`, phiÃĒn báēŖn PATCH là `3`. + +/// + +VÃŦ váē­y, báēĄn cÃŗ tháģƒ cáģ‘ Ä‘áģ‹nh đáēŋn máģ™t phiÃĒn báēŖn như: + +```txt +fastapi>=0.45.0,<0.46.0 +``` + +CÃĄc thay đáģ•i gÃĸy máēĨt tÆ°ÆĄng thích và cÃĄc tính năng máģ›i đưáģŖc thÃĒm vào trong cÃĄc phiÃĒn báēŖn "MINOR". + +/// tip + +"MINOR" là sáģ‘ áģŸ giáģ¯a, ví dáģĨ, trong `0.2.3`, phiÃĒn báēŖn MINOR là `2`. + +/// + +## NÃĸng cáēĨp cÃĄc phiÃĒn báēŖn cáģ§a FastAPI + +BáēĄn nÃĒn thÃĒm cÃĄc bài kiáģƒm tra (tests) cho áģŠng dáģĨng cáģ§a báēĄn. + +Váģ›i **FastAPI** điáģu này ráēĨt dáģ… dàng (nháģ vào Starlette), kiáģƒm tra tài liáģ‡u: [Testing](../tutorial/testing.md){.internal-link target=_blank} + +Sau khi báēĄn cÃŗ cÃĄc bài kiáģƒm tra, báēĄn cÃŗ tháģƒ nÃĸng cáēĨp phiÃĒn báēŖn **FastAPI** lÃĒn máģ™t phiÃĒn báēŖn máģ›i hÆĄn, và đáēŖm báēŖo ráēąng táēĨt cáēŖ mÃŖ cáģ§a báēĄn hoáēĄt đáģ™ng đÃēng báēąng cÃĄch cháēĄy cÃĄc bài kiáģƒm tra cáģ§a báēĄn. + +Náēŋu máģi tháģŠ Ä‘ang hoáēĄt đáģ™ng, hoáēˇc sau khi báēĄn tháģąc hiáģ‡n cÃĄc thay đáģ•i cáē§n thiáēŋt, và táēĨt cáēŖ cÃĄc bài kiáģƒm tra cáģ§a báēĄn đáģu đi qua, thÃŦ báēĄn cÃŗ tháģƒ cáģ‘ Ä‘áģ‹nh phiÃĒn báēŖn cáģ§a `fastapi` đáēŋn phiÃĒn báēŖn máģ›i hÆĄn. + +## Váģ Starlette + +BáēĄn không nÃĒn cáģ‘ Ä‘áģ‹nh phiÃĒn báēŖn cáģ§a `starlette`. + +CÃĄc phiÃĒn báēŖn khÃĄc nhau cáģ§a **FastAPI** sáēŊ sáģ­ dáģĨng máģ™t phiÃĒn báēŖn Starlette máģ›i hÆĄn. + +VÃŦ váē­y, báēĄn cÃŗ tháģƒ Ä‘áģƒ **FastAPI** sáģ­ dáģĨng phiÃĒn báēŖn Starlette phÚ háģŖp. + +## Váģ Pydantic + +Pydantic bao gáģ“m cÃĄc bài kiáģƒm tra cáģ§a riÃĒng nÃŗ cho **FastAPI**, vÃŦ váē­y cÃĄc phiÃĒn báēŖn máģ›i hÆĄn cáģ§a Pydantic (trÃĒn `1.0.0`) luôn tÆ°ÆĄng thích váģ›i **FastAPI**. + +BáēĄn cÃŗ tháģƒ cáģ‘ Ä‘áģ‹nh Pydantic đáēŋn báēĨt káģŗ phiÃĒn báēŖn nào trÃĒn `1.0.0` mà báēĄn muáģ‘n. + +Ví dáģĨ: + +```txt +pydantic>=2.7.0,<3.0.0 +``` diff --git a/docs/vi/docs/environment-variables.md b/docs/vi/docs/environment-variables.md new file mode 100644 index 000000000..dd06f8959 --- /dev/null +++ b/docs/vi/docs/environment-variables.md @@ -0,0 +1,300 @@ +# Biáēŋn môi trưáģng (Environment Variables) + +/// tip + +Náēŋu báēĄn Ä‘ÃŖ biáēŋt váģ "biáēŋn môi trưáģng" và cÃĄch sáģ­ dáģĨng chÃēng, báēĄn cÃŗ tháģƒ báģ qua pháē§n này. + +/// + +Máģ™t biáēŋn môi trưáģng (cÃ˛n đưáģŖc gáģi là "**env var**") là máģ™t biáēŋn mà táģ“n táēĄi **bÃĒn ngoài** đoáēĄn mÃŖ Python, áģŸ trong **háģ‡ Ä‘iáģu hành**, và cÃŗ tháģƒ Ä‘Æ°áģŖc đáģc báģŸi đoáēĄn mÃŖ Python cáģ§a báēĄn (hoáēˇc báģŸi cÃĄc chÆ°ÆĄng trÃŦnh khÃĄc). + +CÃĄc biáēŋn môi trưáģng cÃŗ tháģƒ Ä‘Æ°áģŖc sáģ­ dáģĨng đáģƒ xáģ­ lí **cÃĄc thiáēŋt láē­p** cáģ§a áģŠng dáģĨng, như máģ™t pháē§n cáģ§a **cÃĄc quÃĄ trÃŦnh cài đáēˇt** Python, v.v. + +## TáēĄo và Sáģ­ dáģĨng cÃĄc Biáēŋn Môi Trưáģng + +BáēĄn cÃŗ tháģƒ **táēĄo** và sáģ­ dáģĨng cÃĄc biáēŋn môi trưáģng trong **shell (terminal)**, mà không cáē§n sáģ­ dáģĨng Python: + +//// tab | Linux, macOS, Windows Bash + +
+ +```console +// BáēĄn cÃŗ tháģƒ táēĄo máģ™t biáēŋn môi trưáģng MY_NAME váģ›i +$ export MY_NAME="Wade Wilson" + +// Sau Ä‘Ãŗ báēĄn cÃŗ tháģƒ sáģ­ dáģĨng nÃŗ váģ›i cÃĄc chÆ°ÆĄng trÃŦnh khÃĄc, như +$ echo "Hello $MY_NAME" + +Hello Wade Wilson +``` + +
+ +//// + +//// tab | Windows PowerShell + +
+ +```console +// TáēĄo máģ™t biáēŋn môi trưáģng MY_NAME +$ $Env:MY_NAME = "Wade Wilson" + +// Sáģ­ dáģĨng nÃŗ váģ›i cÃĄc chÆ°ÆĄng trÃŦnh khÃĄc, như là +$ echo "Hello $Env:MY_NAME" + +Hello Wade Wilson +``` + +
+ +//// + +## Đáģc cÃĄc Biáēŋn Môi Trưáģng trong Python + +BáēĄn cÅŠng cÃŗ tháģƒ táēĄo cÃĄc biáēŋn môi trưáģng **bÃĒn ngoài** đoáēĄn mÃŖ Python, trong terminal (hoáēˇc báēąng báēĨt káģŗ phÆ°ÆĄng phÃĄp nào khÃĄc), và sau Ä‘Ãŗ **đáģc chÃēng trong Python**. + +Ví dáģĨ, báēĄn cÃŗ máģ™t file `main.py` váģ›i: + +```Python hl_lines="3" +import os + +name = os.getenv("MY_NAME", "World") +print(f"Hello {name} from Python") +``` + +/// tip + +Tham sáģ‘ tháģŠ hai cho `os.getenv()` là giÃĄ tráģ‹ máēˇc đáģ‹nh đáģƒ tráēŖ váģ. + +Náēŋu không đưáģŖc cung cáēĨp, nÃŗ máēˇc đáģ‹nh là `None`, áģŸ Ä‘Ãĸy chÃēng ta cung cáēĨp `"World"` là giÃĄ tráģ‹ máēˇc đáģ‹nh đáģƒ sáģ­ dáģĨng. + +/// + +Sau Ä‘Ãŗ báēĄn cÃŗ tháģƒ gáģi chÆ°ÆĄng trÃŦnh Python: + +//// tab | Linux, macOS, Windows Bash + +
+ +```console +// áģž Ä‘Ãĸy chÃēng ta chưa cài đáēˇt biáēŋn môi trưáģng +$ python main.py + +// VÃŦ chÃēng ta chưa cài đáēˇt biáēŋn môi trưáģng, chÃēng ta nháē­n đưáģŖc giÃĄ tráģ‹ máēˇc đáģ‹nh + +Hello World from Python + +// Nhưng náēŋu chÃēng ta táēĄo máģ™t biáēŋn môi trưáģng trưáģ›c Ä‘Ãŗ +$ export MY_NAME="Wade Wilson" + +// Và sau Ä‘Ãŗ gáģi chÆ°ÆĄng trÃŦnh láēĄi +$ python main.py + +// BÃĸy giáģ nÃŗ cÃŗ tháģƒ Ä‘áģc biáēŋn môi trưáģng + +Hello Wade Wilson from Python +``` + +
+ +//// + +//// tab | Windows PowerShell + +
+ +```console +// áģž Ä‘Ãĸy chÃēng ta chưa cài đáēˇt biáēŋn môi trưáģng +$ python main.py + +// VÃŦ chÃēng ta chưa cài đáēˇt biáēŋn môi trưáģng, chÃēng ta nháē­n đưáģŖc giÃĄ tráģ‹ máēˇc đáģ‹nh + +Hello World from Python + +// Nhưng náēŋu chÃēng ta táēĄo máģ™t biáēŋn môi trưáģng trưáģ›c Ä‘Ãŗ +$ $Env:MY_NAME = "Wade Wilson" + +// Và sau Ä‘Ãŗ gáģi chÆ°ÆĄng trÃŦnh láēĄi +$ python main.py + +// BÃĸy giáģ nÃŗ cÃŗ tháģƒ Ä‘áģc biáēŋn môi trưáģng + +Hello Wade Wilson from Python +``` + +
+ +//// + +VÃŦ cÃĄc biáēŋn môi trưáģng cÃŗ tháģƒ Ä‘Æ°áģŖc táēĄo bÃĒn ngoài đoáēĄn mÃŖ Python, nhưng cÃŗ tháģƒ Ä‘Æ°áģŖc đáģc báģŸi đoáēĄn mÃŖ Python, và không cáē§n đưáģŖc lưu tráģ¯ (commit vào `git`) cÚng váģ›i cÃĄc file khÃĄc, nÃĒn chÃēng thưáģng đưáģŖc sáģ­ dáģĨng đáģƒ lưu cÃĄc thiáēŋt láē­p hoáēˇc **cáēĨu hÃŦnh**. + +BáēĄn cÅŠng cÃŗ tháģƒ táēĄo ra máģ™t biáēŋn môi trưáģng dành riÃĒng cho máģ™t **láē§n gáģi chÆ°ÆĄng trÃŦnh**, cháģ‰ cÃŗ tháģƒ Ä‘Æ°áģŖc sáģ­ dáģĨng báģŸi chÆ°ÆĄng trÃŦnh Ä‘Ãŗ, và cháģ‰ trong tháģi gian cháēĄy cáģ§a chÆ°ÆĄng trÃŦnh. + +Đáģƒ làm điáģu này, táēĄo nÃŗ ngay trưáģ›c chÆ°ÆĄng trÃŦnh Ä‘Ãŗ, trÃĒn cÚng máģ™t dÃ˛ng: + +
+ +```console +// TáēĄo máģ™t biáēŋn môi trưáģng MY_NAME cho láē§n gáģi chÆ°ÆĄng trÃŦnh này +$ MY_NAME="Wade Wilson" python main.py + +// BÃĸy giáģ nÃŗ cÃŗ tháģƒ Ä‘áģc biáēŋn môi trưáģng + +Hello Wade Wilson from Python + +// Biáēŋn môi trưáģng không cÃ˛n táģ“n táēĄi sau Ä‘Ãŗ +$ python main.py + +Hello World from Python +``` + +
+ +/// tip + +BáēĄn cÃŗ tháģƒ Ä‘áģc thÃĒm váģ Ä‘iáģu này táēĄi The Twelve-Factor App: Config. + +/// + +## CÃĄc Kiáģƒu (Types) và Kiáģƒm tra (Validation) + +CÃĄc biáēŋn môi trưáģng cÃŗ tháģƒ cháģ‰ xáģ­ lí **chuáģ—i kÃŊ táģą**, vÃŦ chÃēng náēąm bÃĒn ngoài đoáēĄn mÃŖ Python và pháēŖi tÆ°ÆĄng thích váģ›i cÃĄc chÆ°ÆĄng trÃŦnh khÃĄc và pháē§n cÃ˛n láēĄi cáģ§a háģ‡ tháģ‘ng (và tháē­m chí váģ›i cÃĄc háģ‡ Ä‘iáģu hành khÃĄc, như Linux, Windows, macOS). + +Điáģu này cÃŗ nghÄŠa là **báēĨt káģŗ giÃĄ tráģ‹ nào** đưáģŖc đáģc trong Python táģĢ máģ™t biáēŋn môi trưáģng **sáēŊ là máģ™t `str`**, và báēĨt káģŗ hành đáģ™ng chuyáģƒn đáģ•i sang kiáģƒu dáģ¯ liáģ‡u khÃĄc hoáēˇc hành đáģ™ng kiáģƒm tra nào cÅŠng pháēŖi đưáģŖc tháģąc hiáģ‡n trong đoáēĄn mÃŖ. + +BáēĄn sáēŊ háģc thÃĒm váģ viáģ‡c sáģ­ dáģĨng biáēŋn môi trưáģng đáģƒ xáģ­ lí **cÃĄc thiáēŋt láē­p áģŠng dáģĨng** trong [Hưáģ›ng dáēĢn nÃĸng cao - CÃĄc thiáēŋt láē­p và biáēŋn môi trưáģng](./advanced/settings.md){.internal-link target=_blank}. + +## Biáēŋn môi trưáģng `PATH` + +CÃŗ máģ™t biáēŋn môi trưáģng **đáēˇc biáģ‡t** đưáģŖc gáģi là **`PATH`** đưáģŖc sáģ­ dáģĨng báģŸi cÃĄc háģ‡ Ä‘iáģu hành (Linux, macOS, Windows) nháēąm tÃŦm cÃĄc chÆ°ÆĄng trÃŦnh đáģƒ tháģąc thi. + +GiÃĄ tráģ‹ cáģ§a biáēŋn môi trưáģng `PATH` là máģ™t chuáģ—i dài đưáģŖc táēĄo báģŸi cÃĄc thư máģĨc đưáģŖc phÃĸn tÃĄch báģŸi dáēĨu hai cháēĨm `:` trÃĒn Linux và macOS, và báģŸi dáēĨu cháēĨm pháēŠy `;` trÃĒn Windows. + +Ví dáģĨ, biáēŋn môi trưáģng `PATH` cÃŗ tháģƒ cÃŗ dáēĄng như sau: + +//// tab | Linux, macOS + +```plaintext +/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin +``` + +Điáģu này cÃŗ nghÄŠa là háģ‡ tháģ‘ng sáēŊ tÃŦm kiáēŋm cÃĄc chÆ°ÆĄng trÃŦnh trong cÃĄc thư máģĨc: + +* `/usr/local/bin` +* `/usr/bin` +* `/bin` +* `/usr/sbin` +* `/sbin` + +//// + +//// tab | Windows + +```plaintext +C:\Program Files\Python312\Scripts;C:\Program Files\Python312;C:\Windows\System32 +``` + +Điáģu này cÃŗ nghÄŠa là háģ‡ tháģ‘ng sáēŊ tÃŦm kiáēŋm cÃĄc chÆ°ÆĄng trÃŦnh trong cÃĄc thư máģĨc: + +* `C:\Program Files\Python312\Scripts` +* `C:\Program Files\Python312` +* `C:\Windows\System32` + +//// + +Khi báēĄn gÃĩ máģ™t **láģ‡nh** trong terminal, háģ‡ Ä‘iáģu hành **tÃŦm kiáēŋm** chÆ°ÆĄng trÃŦnh trong **máģ—i thư máģĨc** đưáģŖc liáģ‡t kÃĒ trong biáēŋn môi trưáģng `PATH`. + +Ví dáģĨ, khi báēĄn gÃĩ `python` trong terminal, háģ‡ Ä‘iáģu hành tÃŦm kiáēŋm máģ™t chÆ°ÆĄng trÃŦnh đưáģŖc gáģi `python` trong **thư máģĨc đáē§u tiÃĒn** trong danh sÃĄch Ä‘Ãŗ. + +Náēŋu tÃŦm tháēĨy, nÃŗ sáēŊ **sáģ­ dáģĨng** nÃŗ. Náēŋu không tÃŦm tháēĨy, nÃŗ sáēŊ tiáēŋp táģĨc tÃŦm kiáēŋm trong **cÃĄc thư máģĨc khÃĄc**. + +### Cài đáēˇt Python và cáē­p nháē­t biáēŋn môi trưáģng `PATH` + +Khi báēĄn cài đáēˇt Python, báēĄn cÃŗ tháģƒ Ä‘Æ°áģŖc háģi náēŋu báēĄn muáģ‘n cáē­p nháē­t biáēŋn môi trưáģng `PATH`. + +//// tab | Linux, macOS + +GiáēŖ sáģ­ báēĄn cài đáēˇt Python vào thư máģĨc `/opt/custompython/bin`. + +Náēŋu báēĄn cháģn cáē­p nháē­t biáēŋn môi trưáģng `PATH`, thÃŦ cài đáēˇt sáēŊ thÃĒm `/opt/custompython/bin` vào biáēŋn môi trưáģng `PATH`. + +NÃŗ cÃŗ tháģƒ cÃŗ dáēĄng như sau: + +```plaintext +/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/custompython/bin +``` + +Như váē­y, khi báēĄn gÃĩ `python` trong terminal, háģ‡ tháģ‘ng sáēŊ tÃŦm tháēĨy chÆ°ÆĄng trÃŦnh Python trong `/opt/custompython/bin` (thư máģĨc cuáģ‘i) và sáģ­ dáģĨng nÃŗ. + +//// + +//// tab | Windows + +GiáēŖ sáģ­ báēĄn cài đáēˇt Python vào thư máģĨc `C:\opt\custompython\bin`. + +Náēŋu báēĄn cháģn cáē­p nháē­t biáēŋn môi trưáģng `PATH`, thÃŦ cài đáēˇt sáēŊ thÃĒm `C:\opt\custompython\bin` vào biáēŋn môi trưáģng `PATH`. + +NÃŗ cÃŗ tháģƒ cÃŗ dáēĄng như sau: + +```plaintext +C:\Program Files\Python312\Scripts;C:\Program Files\Python312;C:\Windows\System32;C:\opt\custompython\bin +``` + +Như váē­y, khi báēĄn gÃĩ `python` trong terminal, háģ‡ tháģ‘ng sáēŊ tÃŦm tháēĨy chÆ°ÆĄng trÃŦnh Python trong `C:\opt\custompython\bin` (thư máģĨc cuáģ‘i) và sáģ­ dáģĨng nÃŗ. + +//// + +Váē­y, náēŋu báēĄn gÃĩ: + +
+ +```console +$ python +``` + +
+ +//// tab | Linux, macOS + +Háģ‡ tháģ‘ng sáēŊ **tÃŦm kiáēŋm** chÆ°ÆĄng trÃŦnh `python` trong `/opt/custompython/bin` và tháģąc thi nÃŗ. + +NÃŗ tÆ°ÆĄng Ä‘Æ°ÆĄng váģ›i viáģ‡c báēĄn gÃĩ: + +
+ +```console +$ /opt/custompython/bin/python +``` + +
+ +//// + +//// tab | Windows + +Háģ‡ tháģ‘ng sáēŊ **tÃŦm kiáēŋm** chÆ°ÆĄng trÃŦnh `python` trong `C:\opt\custompython\bin\python` và tháģąc thi nÃŗ. + +NÃŗ tÆ°ÆĄng Ä‘Æ°ÆĄng váģ›i viáģ‡c báēĄn gÃĩ: + +
+ +```console +$ C:\opt\custompython\bin\python +``` + +
+ +//// + +Thông tin này sáēŊ háģ¯u ích khi báēĄn háģc váģ [Môi trưáģng áēŖo](virtual-environments.md){.internal-link target=_blank}. + +## Káēŋt luáē­n + +Váģ›i nháģ¯ng thông tin này, báēĄn cÃŗ tháģƒ hiáģƒu đưáģŖc **cÃĄc biáēŋn môi trưáģng là gÃŦ** và **cÃĄch sáģ­ dáģĨng chÃēng trong Python**. + +BáēĄn cÃŗ tháģƒ Ä‘áģc thÃĒm váģ chÃēng táēĄi Wikipedia cho Biáēŋn môi trưáģng. + +Trong nhiáģu trưáģng háģŖp, cÃĄch cÃĄc biáēŋn môi trưáģng tráģŸ nÃĒn háģ¯u ích và cÃŗ tháģƒ ÃĄp dáģĨng không tháģąc sáģą rÃĩ ràng ngay táģĢ Ä‘áē§u, nhưng chÃēng sáēŊ liÃĒn táģĨc xuáēĨt hiáģ‡n trong ráēĨt nhiáģu tÃŦnh huáģ‘ng khi báēĄn phÃĄt triáģƒn áģŠng dáģĨng, vÃŦ váē­y viáģ‡c hiáģƒu biáēŋt váģ chÃēng là háģ¯u ích. + +Cháēŗng háēĄn, báēĄn sáēŊ cáē§n nháģ¯ng thông tin này khi báēĄn háģc váģ [Môi trưáģng áēŖo](virtual-environments.md). diff --git a/docs/vi/docs/fastapi-cli.md b/docs/vi/docs/fastapi-cli.md new file mode 100644 index 000000000..d9e315ae4 --- /dev/null +++ b/docs/vi/docs/fastapi-cli.md @@ -0,0 +1,75 @@ +# FastAPI CLI + +**FastAPI CLI** là máģ™t chÆ°ÆĄng trÃŦnh dÃ˛ng láģ‡nh cÃŗ tháģƒ Ä‘Æ°áģŖc sáģ­ dáģĨng đáģƒ pháģĨc váģĨ áģŠng dáģĨng FastAPI cáģ§a báēĄn, quáēŖn lÃŊ dáģą ÃĄn FastAPI cáģ§a báēĄn và nhiáģu hoáēĄt đáģ™ng khÃĄc. + +Khi báēĄn cài đáēˇt FastAPI (vd váģ›i `pip install "fastapi[standard]"`), nÃŗ sáēŊ bao gáģ“m máģ™t gÃŗi đưáģŖc gáģi là `fastapi-cli`, gÃŗi này cung cáēĨp láģ‡nh `fastapi` trong terminal. + +Đáģƒ cháēĄy áģŠng dáģĨng FastAPI cáģ§a báēĄn cho quÃĄ trÃŦnh phÃĄt triáģƒn (development), báēĄn cÃŗ tháģƒ sáģ­ dáģĨng láģ‡nh `fastapi dev`: + +
+ +```console +$ fastapi dev main.py + + FastAPI Starting development server 🚀 + + Searching for package file structure from directories with + __init__.py files + Importing from /home/user/code/awesomeapp + + module 🐍 main.py + + code Importing the FastAPI app object from the module with the + following code: + + from main import app + + app Using import string: main:app + + server Server started at http://127.0.0.1:8000 + server Documentation at http://127.0.0.1:8000/docs + + tip Running in development mode, for production use: + fastapi run + + Logs: + + INFO Will watch for changes in these directories: + ['/home/user/code/awesomeapp'] + INFO Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to + quit) + INFO Started reloader process [383138] using WatchFiles + INFO Started server process [383153] + INFO Waiting for application startup. + INFO Application startup complete. +``` + +
+ +ChÆ°ÆĄng trÃŦnh dÃ˛ng láģ‡nh `fastapi` là **FastAPI CLI**. + +FastAPI CLI nháē­n đưáģng dáēĢn đáēŋn chÆ°ÆĄng trÃŦnh Python cáģ§a báēĄn (vd `main.py`) và táģą Ä‘áģ™ng phÃĄt hiáģ‡n đáģ‘i tưáģŖng `FastAPI` (thưáģng đưáģŖc gáģi là `app`), xÃĄc đáģ‹nh quÃĄ trÃŦnh nháē­p đÃēng, và sau Ä‘Ãŗ cháēĄy nÃŗ (serve). + +Đáģ‘i váģ›i váē­n hành tháģąc táēŋ (production), báēĄn sáēŊ sáģ­ dáģĨng `fastapi run` thay tháēŋ. 🚀 + +áģž bÃĒn trong, **FastAPI CLI** sáģ­ dáģĨng Uvicorn, máģ™t server ASGI cÃŗ hiáģ‡u suáēĨt cao, sáēĩn sàng cho váē­n hành tháģąc táēŋ (production). 😎 + +## `fastapi dev` + +CháēĄy `fastapi dev` sáēŊ kháģŸi đáģ™ng quÃĄ trÃŦnh phÃĄt triáģƒn. + +Máēˇc đáģ‹nh, **auto-reload** đưáģŖc báē­t, táģą Ä‘áģ™ng táēŖi láēĄi server khi báēĄn thay đáģ•i code cáģ§a báēĄn. Điáģu này táģ‘n nhiáģu tài nguyÃĒn và cÃŗ tháģƒ kÊm áģ•n đáģ‹nh hÆĄn khi nÃŗ báģ‹ táē¯t. BáēĄn nÃĒn sáģ­ dáģĨng nÃŗ cho quÃĄ trÃŦnh phÃĄt triáģƒn. NÃŗ cÅŠng láē¯ng nghe đáģ‹a cháģ‰ IP `127.0.0.1`, Ä‘Ãŗ là đáģ‹a cháģ‰ IP cáģ§a mÃĄy tính đáģƒ táģą giao tiáēŋp váģ›i chính nÃŗ (`localhost`). + +## `fastapi run` + +CháēĄy `fastapi run` máēˇc đáģ‹nh sáēŊ kháģŸi đáģ™ng FastAPI cho quÃĄ trÃŦnh váē­n hành tháģąc táēŋ. + +Máēˇc đáģ‹nh, **auto-reload** báģ‹ táē¯t. NÃŗ cÅŠng láē¯ng nghe đáģ‹a cháģ‰ IP `0.0.0.0`, Ä‘Ãŗ là táēĨt cáēŖ cÃĄc đáģ‹a cháģ‰ IP cÃŗ sáēĩn, như váē­y nÃŗ sáēŊ đưáģŖc truy cáē­p công khai báģŸi báēĨt káģŗ ai cÃŗ tháģƒ giao tiáēŋp váģ›i mÃĄy tính. ĐÃĸy là cÃĄch báēĄn thưáģng cháēĄy nÃŗ trong sáēŖn pháēŠm hoàn thiáģ‡n, ví dáģĨ trong máģ™t container. + +Trong háē§u háēŋt cÃĄc trưáģng háģŖp, báēĄn sáēŊ (và nÃĒn) cÃŗ máģ™t "proxy điáģƒm cuáģ‘i (termination proxy)" xáģ­ lÃŊ HTTPS cho báēĄn, điáģu này sáēŊ pháģĨ thuáģ™c vào cÃĄch báēĄn triáģƒn khai áģŠng dáģĨng cáģ§a báēĄn, nhà cung cáēĨp cÃŗ tháģƒ làm điáģu này cho báēĄn, hoáēˇc báēĄn cÃŗ tháģƒ cáē§n thiáēŋt láē­p nÃŗ. + +/// tip + +BáēĄn cÃŗ tháģƒ tÃŦm hiáģƒu thÃĒm váģ FastAPI CLI trong [tài liáģ‡u triáģƒn khai](deployment/index.md){.internal-link target=_blank}. + +/// diff --git a/docs/vi/docs/index.md b/docs/vi/docs/index.md index 5e346ded8..5c6b7e8a4 100644 --- a/docs/vi/docs/index.md +++ b/docs/vi/docs/index.md @@ -12,7 +12,7 @@

- Test + Test Coverage diff --git a/docs/vi/docs/tutorial/static-files.md b/docs/vi/docs/tutorial/static-files.md new file mode 100644 index 000000000..ecf8c2485 --- /dev/null +++ b/docs/vi/docs/tutorial/static-files.md @@ -0,0 +1,40 @@ +# Táģ‡p tÄŠnh (Static Files) + +BáēĄn cÃŗ tháģƒ triáģƒn khai táģ‡p tÄŠnh táģą Ä‘áģ™ng táģĢ máģ™t thư máģĨc báēąng cÃĄch sáģ­ dáģĨng StaticFiles. + +## Sáģ­ dáģĨng `Táģ‡p tÄŠnh` + +- Nháē­p `StaticFiles`. +- "Mount" a `StaticFiles()` instance in a specific path. + +{* ../../docs_src/static_files/tutorial001.py hl[2,6] *} + +/// note | Chi tiáēŋt káģš thuáē­t + +BáēĄn cÅŠng cÃŗ tháģƒ sáģ­ dáģĨng `from starlette.staticfiles import StaticFiles`. + +**FastAPI** cung cáēĨp cÚng `starlette.staticfiles` như `fastapi.staticfiles` giÃēp Ä‘ÆĄn giáēŖn hÃŗa viáģ‡c sáģ­ dáģĨng, nhưng nÃŗ tháģąc sáģą Ä‘áēŋn táģĢ Starlette. + +/// + +### "Mounting" là gÃŦ + +"Mounting" cÃŗ nghÄŠa là thÃĒm máģ™t áģŠng dáģĨng "đáģ™c láē­p" hoàn cháģ‰nh vào máģ™t đưáģng dáēĢn cáģĨ tháģƒ, sau Ä‘Ãŗ áģŠng dáģĨng Ä‘Ãŗ sáēŊ cháģ‹u trÃĄch nhiáģ‡m xáģ­ lÃŊ táēĨt cáēŖ cÃĄc đưáģng dáēĢn con. + +Điáģu này khÃĄc váģ›i viáģ‡c sáģ­ dáģĨng `APIRouter` vÃŦ máģ™t áģŠng dáģĨng đưáģŖc gáē¯n káēŋt là hoàn toàn đáģ™c láē­p. OpenAPI và tài liáģ‡u táģĢ áģŠng dáģĨng chính cáģ§a báēĄn sáēŊ không bao gáģ“m báēĨt káģŗ tháģŠ gÃŦ táģĢ áģŠng dáģĨng đưáģŖc gáē¯n káēŋt, v.v. + +BáēĄn cÃŗ tháģƒ Ä‘áģc thÃĒm váģ Ä‘iáģu này trong [Hưáģ›ng dáēĢn Ngưáģi dÚng NÃĸng cao](../advanced/index.md){.internal-link target=\_blank}. + +## Chi tiáēŋt + +Đưáģng dáēĢn đáē§u tiÃĒn `"/static"` là đưáģng dáēĢn con mà "áģŠng dáģĨng con" này sáēŊ đưáģŖc "gáē¯n" vào. VÃŦ váē­y, báēĨt káģŗ Ä‘Æ°áģng dáēĢn nào báē¯t đáē§u báēąng `"/static"` sáēŊ đưáģŖc xáģ­ lÃŊ báģŸi nÃŗ. + +Đưáģng dáēĢn `directory="static"` là tÃĒn cáģ§a thư máģĨc cháģŠa táģ‡p tÄŠnh cáģ§a báēĄn. + +Tham sáģ‘ `name="static"` đáēˇt tÃĒn cho nÃŗ đáģƒ cÃŗ tháģƒ Ä‘Æ°áģŖc sáģ­ dáģĨng bÃĒn trong **FastAPI**. + +TáēĨt cáēŖ cÃĄc tham sáģ‘ này cÃŗ tháģƒ khÃĄc váģ›i `static`, điáģu cháģ‰nh chÃēng váģ›i phÚ háģŖp váģ›i áģŠng dáģĨng cáģ§a báēĄn. + +## Thông tin thÃĒm + +Đáģƒ biáēŋt thÃĒm chi tiáēŋt và tÚy cháģn, hÃŖy xem Starlette's docs about Static Files. diff --git a/docs/vi/docs/virtual-environments.md b/docs/vi/docs/virtual-environments.md new file mode 100644 index 000000000..22d8e153e --- /dev/null +++ b/docs/vi/docs/virtual-environments.md @@ -0,0 +1,842 @@ +# Môi trưáģng áēŖo (Virtual Environments) + +Khi báēĄn làm viáģ‡c trong cÃĄc dáģą ÃĄn Python, báēĄn cÃŗ tháģƒ sáģ­ dáģĨng máģ™t **môi trưáģng áēŖo** (hoáēˇc máģ™t cÆĄ cháēŋ tÆ°ÆĄng táģą) đáģƒ cÃĄch ly cÃĄc gÃŗi báēĄn cài đáēˇt cho máģ—i dáģą ÃĄn. + +/// info +Náēŋu báēĄn Ä‘ÃŖ biáēŋt váģ cÃĄc môi trưáģng áēŖo, cÃĄch táēĄo chÃēng và sáģ­ dáģĨng chÃēng, báēĄn cÃŗ tháģƒ báģ qua pháē§n này. 🤓 + +/// + +/// tip + +Máģ™t **môi trưáģng áēŖo** khÃĄc váģ›i máģ™t **biáēŋn môi trưáģng (environment variable)**. + +Máģ™t **biáēŋn môi trưáģng** là máģ™t biáēŋn trong háģ‡ tháģ‘ng cÃŗ tháģƒ Ä‘Æ°áģŖc sáģ­ dáģĨng báģŸi cÃĄc chÆ°ÆĄng trÃŦnh. + +Máģ™t **môi trưáģng áēŖo** là máģ™t thư máģĨc váģ›i máģ™t sáģ‘ táģ‡p trong Ä‘Ãŗ. + +/// + +/// info + +Trang này sáēŊ hưáģ›ng dáēĢn báēĄn cÃĄch sáģ­ dáģĨng cÃĄc **môi trưáģng áēŖo** và cÃĄch chÃēng hoáēĄt đáģ™ng. + +Náēŋu báēĄn Ä‘ÃŖ sáēĩn sàng sáģ­ dáģĨng máģ™t **công cáģĨ cÃŗ tháģƒ quáēŖn lÃŊ táēĨt cáēŖ máģi tháģŠ** cho báēĄn (bao gáģ“m cáēŖ viáģ‡c cài đáēˇt Python), hÃŖy tháģ­ uv. + +/// + +## TáēĄo máģ™t Dáģą ÃĄn + +Đáē§u tiÃĒn, táēĄo máģ™t thư máģĨc cho dáģą ÃĄn cáģ§a báēĄn. + +CÃĄch tôi thưáģng làm là táēĄo máģ™t thư máģĨc cÃŗ tÃĒn `code` trong thư máģĨc `home/user`. + +Và trong thư máģĨc Ä‘Ãŗ, tôi táēĄo máģ™t thư máģĨc cho máģ—i dáģą ÃĄn. + +

+ +```console +// Đi đáēŋn thư máģĨc home +$ cd +// TáēĄo máģ™t thư máģĨc cho táēĨt cáēŖ cÃĄc dáģą ÃĄn cáģ§a báēĄn +$ mkdir code +// Vào thư máģĨc code +$ cd code +// TáēĄo máģ™t thư máģĨc cho dáģą ÃĄn này +$ mkdir awesome-project +// Vào thư máģĨc dáģą ÃĄn +$ cd awesome-project +``` + +
+ +## TáēĄo máģ™t Môi trưáģng áēŖo + +Khi báēĄn báē¯t đáē§u làm viáģ‡c váģ›i máģ™t dáģą ÃĄn Python **trong láē§n đáē§u**, hÃŖy táēĄo máģ™t môi trưáģng áēŖo **trong thư máģĨc dáģą ÃĄn cáģ§a báēĄn**. + +/// tip + +BáēĄn cáē§n làm điáģu này **máģ™t láē§n cho máģ—i dáģą ÃĄn**, không pháēŖi máģ—i khi báēĄn làm viáģ‡c. +/// + +//// tab | `venv` + +Đáģƒ táēĄo máģ™t môi trưáģng áēŖo, báēĄn cÃŗ tháģƒ sáģ­ dáģĨng module `venv` cÃŗ sáēĩn cáģ§a Python. + +
+ +```console +$ python -m venv .venv +``` + +
+ +/// details | CÃĄch cÃĄc láģ‡nh hoáēĄt đáģ™ng + +* `python`: sáģ­ dáģĨng chÆ°ÆĄng trÃŦnh `python` +* `-m`: gáģi máģ™t module như máģ™t script, chÃēng ta sáēŊ nÃŗi váģ module Ä‘Ãŗ sau +* `venv`: sáģ­ dáģĨng module `venv` đưáģŖc cài đáēˇt sáēĩn cáģ§a Python +* `.venv`: táēĄo môi trưáģng áēŖo trong thư máģĨc máģ›i `.venv` + +/// + +//// + +//// tab | `uv` + +Náēŋu báēĄn cÃŗ `uv` đưáģŖc cài đáēˇt, báēĄn cÃŗ tháģƒ sáģ­ dáģĨng nÃŗ đáģƒ táēĄo máģ™t môi trưáģng áēŖo. + +
+ +```console +$ uv venv +``` + +
+ +/// tip + +Máēˇc đáģ‹nh, `uv` sáēŊ táēĄo máģ™t môi trưáģng áēŖo trong máģ™t thư máģĨc cÃŗ tÃĒn `.venv`. + +Nhưng báēĄn cÃŗ tháģƒ tÚy cháģ‰nh nÃŗ báēąng cÃĄch thÃĒm máģ™t đáģ‘i sáģ‘ váģ›i tÃĒn thư máģĨc. + +/// + +//// + +Láģ‡nh này táēĄo máģ™t môi trưáģng áēŖo máģ›i trong máģ™t thư máģĨc cÃŗ tÃĒn `.venv`. + +/// details | `.venv` hoáēˇc tÃĒn khÃĄc + +BáēĄn cÃŗ tháģƒ táēĄo môi trưáģng áēŖo trong máģ™t thư máģĨc khÃĄc, nhưng thưáģng ngưáģi ta quy ưáģ›c đáēˇt nÃŗ là `.venv`. + +/// + +## Kích hoáēĄt Môi trưáģng áēŖo + +Kích hoáēĄt môi trưáģng áēŖo máģ›i đáģƒ báēĨt káģŗ láģ‡nh Python nào báēĄn cháēĄy hoáēˇc gÃŗi nào báēĄn cài đáēˇt sáēŊ sáģ­ dáģĨng nÃŗ. + +/// tip + +Làm điáģu này **máģ—i khi** báēĄn báē¯t đáē§u máģ™t **phiÃĒn terminal máģ›i** đáģƒ làm viáģ‡c trÃĒn dáģą ÃĄn. + +/// + +//// tab | Linux, macOS + +
+ +```console +$ source .venv/bin/activate +``` + +
+ +//// + +//// tab | Windows PowerShell + +
+ +```console +$ .venv\Scripts\Activate.ps1 +``` + +
+ +//// + +//// tab | Windows Bash + +Náēŋu báēĄn sáģ­ dáģĨng Bash cho Windows (ví dáģĨ: Git Bash): + +
+ +```console +$ source .venv/Scripts/activate +``` + +
+ +//// + +/// tip + +Máģ—i khi báēĄn cài đáēˇt thÃĒm máģ™t **package máģ›i** trong môi trưáģng Ä‘Ãŗ, hÃŖy **kích hoáēĄt** môi trưáģng Ä‘Ãŗ láēĄi. + +Điáģu này đáēŖm báēŖo ráēąng khi báēĄn sáģ­ dáģĨng máģ™t **chÆ°ÆĄng trÃŦnh dÃ˛ng láģ‡nh (CLI)** đưáģŖc cài đáēˇt táģĢ gÃŗi Ä‘Ãŗ, báēĄn sáēŊ dÚng báēŖn cài đáēˇt táģĢ môi trưáģng áēŖo cáģ§a mÃŦnh thay vÃŦ báēŖn đưáģŖc cài đáēˇt toàn cáģĨc khÃĄc cÃŗ tháģƒ cÃŗ phiÃĒn báēŖn khÃĄc váģ›i phiÃĒn báēŖn báēĄn cáē§n. + +/// + +## Kiáģƒm tra xem Môi trưáģng áēŖo Ä‘ÃŖ đưáģŖc Kích hoáēĄt chưa + +Kiáģƒm tra xem môi trưáģng áēŖo Ä‘ÃŖ đưáģŖc kích hoáēĄt chưa (láģ‡nh trưáģ›c Ä‘Ãŗ Ä‘ÃŖ hoáēĄt đáģ™ng). + +/// tip + +Điáģu này là **không báē¯t buáģ™c**, nhưng nÃŗ là máģ™t cÃĄch táģ‘t đáģƒ **kiáģƒm tra** ráēąng máģi tháģŠ Ä‘ang hoáēĄt đáģ™ng như mong đáģŖi và báēĄn đang sáģ­ dáģĨng đÃēng môi trưáģng áēŖo mà báēĄn Ä‘ÃŖ đáģ‹nh. + +/// + +//// tab | Linux, macOS, Windows Bash + +
+ +```console +$ which python + +/home/user/code/awesome-project/.venv/bin/python +``` + +
+ +Náēŋu nÃŗ hiáģƒn tháģ‹ `python` binary táēĄi `.venv/bin/python`, trong dáģą ÃĄn cáģ§a báēĄn (trong trưáģng háģŖp `awesome-project`), thÃŦ táģŠc là nÃŗ hoáēĄt đáģ™ng. 🎉 + +//// + +//// tab | Windows PowerShell + +
+ +```console +$ Get-Command python + +C:\Users\user\code\awesome-project\.venv\Scripts\python +``` + +
+ +Náēŋu nÃŗ hiáģƒn tháģ‹ `python` binary táēĄi `.venv\Scripts\python`, trong dáģą ÃĄn cáģ§a báēĄn (trong trưáģng háģŖp `awesome-project`), thÃŦ táģŠc là nÃŗ hoáēĄt đáģ™ng. 🎉 + +//// + +## NÃĸng cáēĨp `pip` + +/// tip + +Náēŋu báēĄn sáģ­ dáģĨng `uv` báēĄn sáģ­ dáģĨng nÃŗ đáģƒ cài đáēˇt thay vÃŦ `pip`, thÃŦ báēĄn không cáē§n cáē­p nháē­t `pip`. 😎 + +/// + +Náēŋu báēĄn sáģ­ dáģĨng `pip` đáģƒ cài đáēˇt gÃŗi (nÃŗ đưáģŖc cài đáēˇt máēˇc đáģ‹nh váģ›i Python), báēĄn nÃĒn **nÃĸng cáēĨp** nÃŗ lÃĒn phiÃĒn báēŖn máģ›i nháēĨt. + +Nhiáģu láģ—i khÃĄc nhau trong khi cài đáēˇt gÃŗi đưáģŖc giáēŖi quyáēŋt cháģ‰ báēąng cÃĄch nÃĸng cáēĨp `pip` trưáģ›c. + +/// tip + +BáēĄn thưáģng làm điáģu này **máģ™t láē§n**, ngay sau khi báēĄn táēĄo môi trưáģng áēŖo. + +/// + +ĐáēŖm báēŖo ráēąng môi trưáģng áēŖo Ä‘ÃŖ đưáģŖc kích hoáēĄt (váģ›i láģ‡nh trÃĒn) và sau Ä‘Ãŗ cháēĄy: + +
+ +```console +$ python -m pip install --upgrade pip + +---> 100% +``` + +
+ +## ThÃĒm `.gitignore` + +Náēŋu báēĄn sáģ­ dáģĨng **Git** (nÃĒn làm), hÃŖy thÃĒm máģ™t file `.gitignore` đáģƒ Git báģ qua máģi tháģŠ trong `.venv`. + +/// tip + +Náēŋu báēĄn sáģ­ dáģĨng `uv` đáģƒ táēĄo môi trưáģng áēŖo, nÃŗ Ä‘ÃŖ táģą Ä‘áģ™ng làm điáģu này cho báēĄn, báēĄn cÃŗ tháģƒ báģ qua bưáģ›c này. 😎 + +/// + +/// tip + +Làm điáģu này **máģ™t láē§n**, ngay sau khi báēĄn táēĄo môi trưáģng áēŖo. + +/// + +
+ +```console +$ echo "*" > .venv/.gitignore +``` + +
+ +/// details | CÃĄch láģ‡nh hoáēĄt đáģ™ng + +* `echo "*"`: sáēŊ "in" văn báēŖn `*` trong terminal (pháē§n tiáēŋp theo sáēŊ thay đáģ•i điáģu Ä‘Ãŗ máģ™t chÃēt) +* `>`: báēĨt káģŗ văn báēŖn nào đưáģŖc in ra terminal báģŸi láģ‡nh trưáģ›c `>` không đưáģŖc in ra mà thay vào Ä‘Ãŗ đưáģŖc viáēŋt vào file áģŸ phía bÃĒn pháēŖi cáģ§a `>` +* `.gitignore`: tÃĒn cáģ§a file mà văn báēŖn sáēŊ đưáģŖc viáēŋt vào + +Và `*` váģ›i Git cÃŗ nghÄŠa là "máģi tháģŠ". VÃŦ váē­y, nÃŗ sáēŊ báģ qua máģi tháģŠ trong thư máģĨc `.venv`. + +Láģ‡nh này sáēŊ táēĄo máģ™t file `.gitignore` váģ›i náģ™i dung: + +```gitignore +* +``` + +/// + +## Cài đáēˇt gÃŗi (packages) + +Sau khi kích hoáēĄt môi trưáģng, báēĄn cÃŗ tháģƒ cài đáēˇt cÃĄc gÃŗi trong Ä‘Ãŗ. + +/// tip + +Tháģąc hiáģ‡n điáģu này **máģ™t láē§n** khi cài đáēˇt hoáēˇc cáē­p nháē­t gÃŗi cáē§n thiáēŋt cho dáģą ÃĄn cáģ§a báēĄn. + +Náēŋu báēĄn cáē§n cáē­p nháē­t phiÃĒn báēŖn hoáēˇc thÃĒm máģ™t gÃŗi máģ›i, báēĄn sáēŊ **tháģąc hiáģ‡n điáģu này láēĄi**. + +/// + +### Cài đáēˇt gÃŗi tráģąc tiáēŋp + +Náēŋu báēĄn cáē§n cáē­p nháē­t phiÃĒn báēŖn hoáēˇc thÃĒm máģ™t gÃŗi máģ›i, báēĄn sáēŊ **tháģąc hiáģ‡n điáģu này láēĄi**. + +/// tip +Đáģƒ quáēŖn lÃŊ dáģą ÃĄn táģ‘t hÆĄn, hÃŖy liáģ‡t kÃĒ táēĨt cáēŖ cÃĄc gÃŗi và phiÃĒn báēŖn cáē§n thiáēŋt trong máģ™t file (ví dáģĨ `requirements.txt` hoáēˇc `pyproject.toml`). + +/// + +//// tab | `pip` + +
+ +```console +$ pip install "fastapi[standard]" + +---> 100% +``` + +
+ +//// + +//// tab | `uv` + +Náēŋu báēĄn cÃŗ `uv`: + +
+ +```console +$ uv pip install "fastapi[standard]" +---> 100% +``` + +
+ +//// + +### Cài đáēˇt táģĢ `requirements.txt` + +Náēŋu báēĄn cÃŗ máģ™t táģ‡p `requirements.txt`, báēĄn cÃŗ tháģƒ sáģ­ dáģĨng nÃŗ đáģƒ cài đáēˇt cÃĄc gÃŗi. + +//// tab | `pip` + +
+ +```console +$ pip install -r requirements.txt +---> 100% +``` + +
+ +//// + +//// tab | `uv` + +Náēŋu báēĄn cÃŗ `uv`: + +
+ +```console +$ uv pip install -r requirements.txt +---> 100% +``` + +
+ +//// + +/// details | `requirements.txt` + +Máģ™t táģ‡p `requirements.txt` váģ›i máģ™t sáģ‘ gÃŗi sáēŊ trông như tháēŋ này: + +```requirements.txt +fastapi[standard]==0.113.0 +pydantic==2.8.0 +``` + +/// + +## CháēĄy ChÆ°ÆĄng trÃŦnh cáģ§a báēĄn + +Sau khi kích hoáēĄt môi trưáģng áēŖo, báēĄn cÃŗ tháģƒ cháēĄy chÆ°ÆĄng trÃŦnh cáģ§a mÃŦnh, nÃŗ sáēŊ sáģ­ dáģĨng Python trong môi trưáģng áēŖo cáģ§a báēĄn váģ›i cÃĄc gÃŗi báēĄn Ä‘ÃŖ cài đáēˇt. + +
+ +```console +$ python main.py + +Hello World +``` + +
+ +## CáēĨu hÃŦnh TrÃŦnh soáēĄn tháēŖo cáģ§a báēĄn + +Náēŋu báēĄn sáģ­ dáģĨng máģ™t trÃŦnh soáēĄn tháēŖo, hÃŖy đáēŖm báēŖo báēĄn cáēĨu hÃŦnh nÃŗ đáģƒ sáģ­ dáģĨng cÚng môi trưáģng áēŖo mà báēĄn Ä‘ÃŖ táēĄo (trÃŦnh soáēĄn tháēŖo sáēŊ táģą Ä‘áģ™ng phÃĄt hiáģ‡n môi trưáģng áēŖo) đáģƒ báēĄn cÃŗ tháģƒ nháē­n đưáģŖc tính năng táģą Ä‘áģ™ng hoàn thành cÃĸu láģ‡nh (autocomplete) và in láģ—i tráģąc tiáēŋp trong trÃŦnh soáēĄn tháēŖo (inline errors). + +Ví dáģĨ: + +* VS Code +* PyCharm + +/// tip + +BáēĄn thưáģng cháģ‰ cáē§n làm điáģu này **máģ™t láē§n**, khi báēĄn táēĄo môi trưáģng áēŖo. + +/// + +## Huáģˇ kích hoáēĄt Môi trưáģng áēŖo + +Khi báēĄn hoàn táēĨt viáģ‡c làm trÃĒn dáģą ÃĄn cáģ§a báēĄn, báēĄn cÃŗ tháģƒ **huáģˇ kích hoáēĄt** môi trưáģng áēŖo. + +
+ +```console +$ deactivate +``` + +
+ +Như váē­y, khi báēĄn cháēĄy `python`, nÃŗ sáēŊ không cháēĄy táģĢ môi trưáģng áēŖo Ä‘Ãŗ váģ›i cÃĄc gÃŗi Ä‘ÃŖ cài đáēˇt. + +## Sáēĩn sàng đáģƒ Làm viáģ‡c + +BÃĸy giáģ báēĄn Ä‘ÃŖ sáēĩn sàng đáģƒ làm viáģ‡c trÃĒn dáģą ÃĄn cáģ§a mÃŦnh ráģ“i đáēĨy. + +/// tip + +BáēĄn muáģ‘n hiáģƒu táēĨt cáēŖ nháģ¯ng gÃŦ áģŸ trÃĒn? + +Tiáēŋp táģĨc đáģc. 👇🤓 + +/// + +## TáēĄi sao cáē§n Môi trưáģng áēŖo + +Đáģƒ làm viáģ‡c váģ›i FastAPI, báēĄn cáē§n cài đáēˇt Python. + +Sau Ä‘Ãŗ, báēĄn sáēŊ cáē§n **cài đáēˇt** FastAPI và báēĨt káģŗ **gÃŗi** nào mà báēĄn muáģ‘n sáģ­ dáģĨng. + +Đáģƒ cài đáēˇt gÃŗi, báēĄn thưáģng sáģ­ dáģĨng láģ‡nh `pip` cÃŗ sáēĩn váģ›i Python (hoáēˇc cÃĄc phiÃĒn báēŖn tÆ°ÆĄng táģą). + +Tuy nhiÃĒn, náēŋu báēĄn sáģ­ dáģĨng `pip` tráģąc tiáēŋp, cÃĄc gÃŗi sáēŊ đưáģŖc cài đáēˇt trong **môi trưáģng Python toàn cáģĨc** cáģ§a báēĄn (pháē§n cài đáēˇt toàn cáģĨc cáģ§a Python). + +### VáēĨn đáģ + +Váē­y, váēĨn đáģ gÃŦ khi cài đáēˇt gÃŗi trong môi trưáģng Python toàn cáģĨc? + +Trong máģ™t vài tháģi điáģƒm, báēĄn sáēŊ pháēŖi viáēŋt nhiáģu chÆ°ÆĄng trÃŦnh khÃĄc nhau pháģĨ thuáģ™c vào **cÃĄc gÃŗi khÃĄc nhau**. Và máģ™t sáģ‘ dáģą ÃĄn báēĄn tháģąc hiáģ‡n láēĄi pháģĨ thuáģ™c vào **cÃĄc phiÃĒn báēŖn khÃĄc nhau** cáģ§a cÚng máģ™t gÃŗi. 😱 + +Ví dáģĨ, báēĄn cÃŗ tháģƒ táēĄo máģ™t dáģą ÃĄn đưáģŖc gáģi là `philosophers-stone`, chÆ°ÆĄng trÃŦnh này pháģĨ thuáģ™c vào máģ™t gÃŗi khÃĄc đưáģŖc gáģi là **`harry`, sáģ­ dáģĨng phiÃĒn báēŖn `1`**. VÃŦ váē­y, báēĄn cáē§n cài đáēˇt `harry`. + +```mermaid +flowchart LR + stone(philosophers-stone) -->|pháģĨ thuáģ™c| harry-1[harry v1] +``` + +Sau Ä‘Ãŗ, vào máģ™t vài tháģi điáģƒm sau, báēĄn táēĄo máģ™t dáģą ÃĄn khÃĄc đưáģŖc gáģi là `prisoner-of-azkaban`, và dáģą ÃĄn này cÅŠng pháģĨ thuáģ™c vào `harry`, nhưng dáģą ÃĄn này cáē§n **`harry` phiÃĒn báēŖn `3`**. + +```mermaid +flowchart LR + azkaban(prisoner-of-azkaban) --> |pháģĨ thuáģ™c| harry-3[harry v3] +``` + +BÃĸy giáģ, váēĨn đáģ là, náēŋu báēĄn cài đáēˇt cÃĄc gÃŗi toàn cáģĨc (trong môi trưáģng toàn cáģĨc) thay vÃŦ trong máģ™t **môi trưáģng áēŖo cáģĨc báģ™**, báēĄn sáēŊ pháēŖi cháģn phiÃĒn báēŖn `harry` nào đáģƒ cài đáēˇt. + +Náēŋu báēĄn muáģ‘n cháēĄy `philosophers-stone` báēĄn sáēŊ cáē§n pháēŖi cài đáēˇt `harry` phiÃĒn báēŖn `1`, ví dáģĨ váģ›i: + +
+ +```console +$ pip install "harry==1" +``` + +
+ +Và sau Ä‘Ãŗ báēĄn sáēŊ cÃŗ `harry` phiÃĒn báēŖn `1` đưáģŖc cài đáēˇt trong môi trưáģng Python toàn cáģĨc cáģ§a báēĄn. + +```mermaid +flowchart LR + subgraph global[môi trưáģng toàn cáģĨc] + harry-1[harry v1] + end + subgraph stone-project[dáģą ÃĄn philosophers-stone ] + stone(philosophers-stone) -->|pháģĨ thuáģ™c| harry-1 + end +``` + +Nhưng sau Ä‘Ãŗ, náēŋu báēĄn muáģ‘n cháēĄy `prisoner-of-azkaban`, báēĄn sáēŊ cáē§n pháēŖi gáģĄ báģ `harry` phiÃĒn báēŖn `1` và cài đáēˇt `harry` phiÃĒn báēŖn `3` (hoáēˇc cháģ‰ cáē§n cài đáēˇt phiÃĒn báēŖn `3` sáēŊ táģą Ä‘áģ™ng gáģĄ báģ phiÃĒn báēŖn `1`). + +
+ +```console +$ pip install "harry==3" +``` + +
+ +Và sau Ä‘Ãŗ báēĄn sáēŊ cÃŗ `harry` phiÃĒn báēŖn `3` đưáģŖc cài đáēˇt trong môi trưáģng Python toàn cáģĨc cáģ§a báēĄn. + +Và náēŋu báēĄn cáģ‘ gáē¯ng cháēĄy `philosophers-stone` láēĄi, cÃŗ kháēŖ năng nÃŗ sáēŊ **không hoáēĄt đáģ™ng** vÃŦ nÃŗ cáē§n `harry` phiÃĒn báēŖn `1`. + +```mermaid +flowchart LR + subgraph global[môi trưáģng toàn cáģĨc] + harry-1[harry v1] + style harry-1 fill:#ccc,stroke-dasharray: 5 5 + harry-3[harry v3] + end + subgraph stone-project[dáģą ÃĄn philosophers-stone ] + stone(philosophers-stone) -.-x|â›”ī¸| harry-1 + end + subgraph azkaban-project[dáģą ÃĄn prisoner-of-azkaban ] + azkaban(prisoner-of-azkaban) --> |pháģĨ thuáģ™c| harry-3 + end +``` + +/// tip + +Máēˇc dÚ cÃĄc gÃŗi Python thưáģng cáģ‘ gáē¯ng **trÃĄnh cÃĄc thay đáģ•i làm háģng code** trong **phiÃĒn báēŖn máģ›i**, nhưng đáģƒ Ä‘áēŖm báēŖo an toàn, báēĄn nÃĒn cháģ§ Ä‘áģ™ng cài đáēˇt phiÃĒn báēŖn máģ›i và cháēĄy kiáģƒm tháģ­ Ä‘áģƒ xÃĄc nháē­n máģi tháģŠ váēĢn hoáēĄt đáģ™ng đÃēng. + +/// + +BÃĸy giáģ, hÃŖy hÃŦnh dung váģ **nhiáģu** gÃŗi khÃĄc nhau mà táēĨt cáēŖ cÃĄc dáģą ÃĄn cáģ§a báēĄn pháģĨ thuáģ™c vào. RÃĩ ràng ráēĨt khÃŗ đáģƒ quáēŖn lÃŊ. Điáģu này dáēĢn táģ›i viáģ‡c là báēĄn sáēŊ cÃŗ nhiáģu dáģą ÃĄn váģ›i **cÃĄc phiÃĒn báēŖn không tÆ°ÆĄng thích** cáģ§a cÃĄc gÃŗi, và báēĄn cÃŗ tháģƒ không biáēŋt táēĄi sao máģ™t sáģ‘ tháģŠ không hoáēĄt đáģ™ng. + +HÆĄn náģ¯a, tuáģŗ vào háģ‡ Ä‘iáģu hành cáģ§a báēĄn (vd Linux, Windows, macOS), cÃŗ tháģƒ Ä‘ÃŖ cÃŗ Python đưáģŖc cài đáēˇt sáēĩn. Trong trưáģng háģŖp áēĨy, máģ™t vài gÃŗi nhiáģu kháēŖ năng Ä‘ÃŖ đưáģŖc cài đáēˇt trưáģ›c váģ›i cÃĄc phiÃĒn báēŖn **cáē§n thiáēŋt cho háģ‡ tháģ‘ng cáģ§a báēĄn**. Náēŋu báēĄn cài đáēˇt cÃĄc gÃŗi trong môi trưáģng Python toàn cáģĨc, báēĄn cÃŗ tháģƒ sáēŊ **phÃĄ váģĄ** máģ™t sáģ‘ chÆ°ÆĄng trÃŦnh Ä‘ÃŖ đưáģŖc cài đáēˇt sáēĩn cÚng háģ‡ tháģ‘ng. + +## NÆĄi cÃĄc GÃŗi đưáģŖc Cài đáēˇt + +Khi báēĄn cài đáēˇt Python, nÃŗ sáēŊ táēĄo ra máģ™t vài thư máģĨc và táģ‡p trong mÃĄy tính cáģ§a báēĄn. + +Máģ™t vài thư máģĨc này là nháģ¯ng thư máģĨc cháģ‹u trÃĄch nhiáģ‡m cÃŗ táēĨt cáēŖ cÃĄc gÃŗi báēĄn cài đáēˇt. + +Khi báēĄn cháēĄy: + +
+ +```console +// ĐáģĢng cháēĄy láģ‡nh này ngay, đÃĸy cháģ‰ là máģ™t ví dáģĨ 🤓 +$ pip install "fastapi[standard]" +---> 100% +``` + +
+ +Láģ‡nh này sáēŊ táēŖi xuáģ‘ng máģ™t táģ‡p nÊn váģ›i mÃŖ nguáģ“n FastAPI, thưáģng là táģĢ PyPI. + +NÃŗ cÅŠng sáēŊ **táēŖi xuáģ‘ng** cÃĄc táģ‡p cho cÃĄc gÃŗi khÃĄc mà FastAPI pháģĨ thuáģ™c vào. + +Sau Ä‘Ãŗ, nÃŗ sáēŊ **giáēŖi nÊn** táēĨt cáēŖ cÃĄc táģ‡p Ä‘Ãŗ và đưa chÃēng vào máģ™t thư máģĨc trong mÃĄy tính cáģ§a báēĄn. + +Máēˇc đáģ‹nh, nÃŗ sáēŊ đưa cÃĄc táģ‡p Ä‘ÃŖ táēŖi xuáģ‘ng và giáēŖi nÊn vào thư máģĨc đưáģŖc cài đáēˇt cÚng Python cáģ§a báēĄn, Ä‘Ãŗ là **môi trưáģng toàn cáģĨc**. + +## Nháģ¯ng Môi trưáģng áēŖo là gÃŦ? + +CÃĄch giáēŖi quyáēŋt cho váēĨn đáģ cÃŗ táēĨt cáēŖ cÃĄc gÃŗi trong môi trưáģng toàn cáģĨc là sáģ­ dáģĨng máģ™t **môi trưáģng áēŖo cho máģ—i dáģą ÃĄn** báēĄn làm viáģ‡c. + +Máģ™t môi trưáģng áēŖo là máģ™t **thư máģĨc**, ráēĨt giáģ‘ng váģ›i môi trưáģng toàn cáģĨc, trong Ä‘Ãŗ báēĄn cÃŗ tháģƒ cài đáēˇt cÃĄc gÃŗi cho máģ™t dáģą ÃĄn. + +VÃŦ váē­y, máģ—i dáģą ÃĄn sáēŊ cÃŗ máģ™t môi trưáģng áēŖo riÃĒng cáģ§a nÃŗ (thư máģĨc `.venv`) váģ›i cÃĄc gÃŗi riÃĒng cáģ§a nÃŗ. + +```mermaid +flowchart TB + subgraph stone-project[dáģą ÃĄn philosophers-stone ] + stone(philosophers-stone) --->|pháģĨ thuáģ™c| harry-1 + subgraph venv1[.venv] + harry-1[harry v1] + end + end + subgraph azkaban-project[dáģą ÃĄn prisoner-of-azkaban ] + azkaban(prisoner-of-azkaban) --->|pháģĨ thuáģ™c| harry-3 + subgraph venv2[.venv] + harry-3[harry v3] + end + end + stone-project ~~~ azkaban-project +``` + +## Kích hoáēĄt Môi trưáģng áēŖo nghÄŠa là gÃŦ + +Khi báēĄn kích hoáēĄt máģ™t môi trưáģng áēŖo, ví dáģĨ váģ›i: + +//// tab | Linux, macOS + +
+ +```console +$ source .venv/bin/activate +``` + +
+ +//// + +//// tab | Windows PowerShell + +
+ +```console +$ .venv\Scripts\Activate.ps1 +``` + +
+ +//// + +//// tab | Windows Bash + +Náēŋu báēĄn sáģ­ dáģĨng Bash cho Windows (ví dáģĨ Git Bash): + +
+ +```console +$ source .venv/Scripts/activate +``` + +
+ +//// + +Láģ‡nh này sáēŊ táēĄo hoáēˇc sáģ­a đáģ•i máģ™t sáģ‘ [biáēŋn môi trưáģng](environment-variables.md){.internal-link target=_blank} mà sáēŊ đưáģŖc sáģ­ dáģĨng cho cÃĄc láģ‡nh tiáēŋp theo. + +Máģ™t trong sáģ‘ Ä‘Ãŗ là biáēŋn `PATH`. + +/// tip + +BáēĄn cÃŗ tháģƒ tÃŦm hiáģƒu thÃĒm váģ biáēŋn `PATH` trong [Biáēŋn môi trưáģng](environment-variables.md#path-environment-variable){.internal-link target=_blank} section. + +/// + +Kích hoáēĄt môi trưáģng áēŖo thÃĒm đưáģng dáēĢn `.venv/bin` (trÃĒn Linux và macOS) hoáēˇc `.venv\Scripts` (trÃĒn Windows) vào biáēŋn `PATH`. + +GiáēŖ sáģ­ ráēąng trưáģ›c khi kích hoáēĄt môi trưáģng, biáēŋn `PATH` như sau: + +//// tab | Linux, macOS + +```plaintext +/usr/bin:/bin:/usr/sbin:/sbin +``` + +NghÄŠa là háģ‡ tháģ‘ng sáēŊ tÃŦm kiáēŋm chÆ°ÆĄng trÃŦnh trong: + +* `/usr/bin` +* `/bin` +* `/usr/sbin` +* `/sbin` + +//// + +//// tab | Windows + +```plaintext +C:\Windows\System32 +``` + +NghÄŠa là háģ‡ tháģ‘ng sáēŊ tÃŦm kiáēŋm chÆ°ÆĄng trÃŦnh trong: + +* `C:\Windows\System32` + +//// + +Sau khi kích hoáēĄt môi trưáģng áēŖo, biáēŋn `PATH` sáēŊ như sau: + +//// tab | Linux, macOS + +```plaintext +/home/user/code/awesome-project/.venv/bin:/usr/bin:/bin:/usr/sbin:/sbin +``` + +NghÄŠa là háģ‡ tháģ‘ng sáēŊ báē¯t đáē§u tÃŦm kiáēŋm chÆ°ÆĄng trÃŦnh trong: + +```plaintext +/home/user/code/awesome-project/.venv/bin +``` + +trưáģ›c khi tÃŦm kiáēŋm trong cÃĄc thư máģĨc khÃĄc. + +VÃŦ váē­y, khi báēĄn gÃĩ `python` trong terminal, háģ‡ tháģ‘ng sáēŊ tÃŦm tháēĨy chÆ°ÆĄng trÃŦnh Python trong: + +```plaintext +/home/user/code/awesome-project/.venv/bin/python +``` + +và sáģ­ dáģĨng chÆ°ÆĄng trÃŦnh Ä‘Ãŗ. + +//// + +//// tab | Windows + +```plaintext +C:\Users\user\code\awesome-project\.venv\Scripts;C:\Windows\System32 +``` + +NghÄŠa là háģ‡ tháģ‘ng sáēŊ báē¯t đáē§u tÃŦm kiáēŋm chÆ°ÆĄng trÃŦnh trong: + +```plaintext +C:\Users\user\code\awesome-project\.venv\Scripts +``` + +trưáģ›c khi tÃŦm kiáēŋm trong cÃĄc thư máģĨc khÃĄc. + +VÃŦ váē­y, khi báēĄn gÃĩ `python` trong terminal, háģ‡ tháģ‘ng sáēŊ tÃŦm tháēĨy chÆ°ÆĄng trÃŦnh Python trong: + +```plaintext +C:\Users\user\code\awesome-project\.venv\Scripts\python +``` + +và sáģ­ dáģĨng chÆ°ÆĄng trÃŦnh Ä‘Ãŗ. + +//// + +Máģ™t chi tiáēŋt quan tráģng là nÃŗ sáēŊ đưa đáģ‹a cháģ‰ cáģ§a môi trưáģng áēŖo vào **đáē§u** cáģ§a biáēŋn `PATH`. Háģ‡ tháģ‘ng sáēŊ tÃŦm kiáēŋm nÃŗ **trưáģ›c** khi tÃŦm kiáēŋm báēĨt káģŗ Python nào khÃĄc cÃŗ sáēĩn. VÃŦ váē­y, khi báēĄn cháēĄy `python`, nÃŗ sáēŊ sáģ­ dáģĨng Python **táģĢ môi trưáģng áēŖo** thay vÃŦ báēĨt káģŗ Python nào khÃĄc (ví dáģĨ, Python táģĢ môi trưáģng toàn cáģĨc). + +Kích hoáēĄt máģ™t môi trưáģng áēŖo cÅŠng thay đáģ•i máģ™t vài tháģŠ khÃĄc, nhưng đÃĸy là máģ™t trong nháģ¯ng điáģu quan tráģng nháēĨt mà nÃŗ tháģąc hiáģ‡n. + +## Kiáģƒm tra máģ™t Môi trưáģng áēŖo + +Khi báēĄn kiáģƒm tra máģ™t môi trưáģng áēŖo Ä‘ÃŖ đưáģŖc kích hoáēĄt chưa, ví dáģĨ váģ›i: + +//// tab | Linux, macOS, Windows Bash + +
+ +```console +$ which python + +/home/user/code/awesome-project/.venv/bin/python +``` + +
+ +//// + +//// tab | Windows PowerShell + +
+ +```console +$ Get-Command python + +C:\Users\user\code\awesome-project\.venv\Scripts\python +``` + +
+ +//// + + +Điáģu Ä‘Ãŗ cÃŗ nghÄŠa là chÆ°ÆĄng trÃŦnh `python` sáēŊ đưáģŖc sáģ­ dáģĨng là chÆ°ÆĄng trÃŦnh **trong môi trưáģng áēŖo**. + +BáēĄn sáģ­ dáģĨng `which` trÃĒn Linux và macOS và `Get-Command` trÃĒn Windows PowerShell. + +CÃĄch hoáēĄt đáģ™ng cáģ§a láģ‡nh này là nÃŗ sáēŊ đi và kiáģƒm tra biáēŋn `PATH`, đi qua **máģ—i đưáģng dáēĢn theo tháģŠ táģą**, tÃŦm kiáēŋm chÆ°ÆĄng trÃŦnh đưáģŖc gáģi là `python`. Khi nÃŗ tÃŦm tháēĨy nÃŗ, nÃŗ sáēŊ **hiáģƒn tháģ‹ cho báēĄn đưáģng dáēĢn** đáēŋn chÆ°ÆĄng trÃŦnh Ä‘Ãŗ. + +Điáģu quan tráģng nháēĨt là khi báēĄn gáģi `python`, Ä‘Ãŗ chính là chÆ°ÆĄng trÃŦnh `python` đưáģŖc tháģąc thi. + +VÃŦ váē­y, báēĄn cÃŗ tháģƒ xÃĄc nháē­n náēŋu báēĄn đang áģŸ trong môi trưáģng áēŖo đÃēng. + +/// tip + +Dáģ… dàng kích hoáēĄt máģ™t môi trưáģng áēŖo, cài đáēˇt Python, và sau Ä‘Ãŗ **chuyáģƒn đáēŋn máģ™t dáģą ÃĄn khÃĄc**. + +Và dáģą ÃĄn tháģŠ hai **sáēŊ không hoáēĄt đáģ™ng** vÃŦ báēĄn đang sáģ­ dáģĨng **Python không đÃēng**, táģĢ máģ™t môi trưáģng áēŖo cho máģ™t dáģą ÃĄn khÃĄc. + +Tháē­t tiáģ‡n láģŖi khi cÃŗ tháģƒ kiáģƒm tra `python` nào đang đưáģŖc sáģ­ dáģĨng 🤓 + +/// + +## TáēĄi sao láēĄi Huáģˇ kích hoáēĄt máģ™t Môi trưáģng áēŖo + +Ví dáģĨ, báēĄn cÃŗ tháģƒ làm viáģ‡c trÃĒn máģ™t dáģą ÃĄn `philosophers-stone`, **kích hoáēĄt môi trưáģng áēŖo**, cài đáēˇt cÃĄc gÃŗi và làm viáģ‡c váģ›i môi trưáģng áēŖo Ä‘Ãŗ. + +Sau Ä‘Ãŗ, báēĄn muáģ‘n làm viáģ‡c trÃĒn **dáģą ÃĄn khÃĄc** `prisoner-of-azkaban`. + +BáēĄn đi đáēŋn dáģą ÃĄn Ä‘Ãŗ: + +
+ +```console +$ cd ~/code/prisoner-of-azkaban +``` + +
+ +Náēŋu báēĄn không táē¯t môi trưáģng áēŖo cho `philosophers-stone`, khi báēĄn cháēĄy `python` trong terminal, nÃŗ sáēŊ cáģ‘ gáē¯ng sáģ­ dáģĨng Python táģĢ `philosophers-stone`. + +
+ +```console +$ cd ~/code/prisoner-of-azkaban + +$ python main.py + +// Láģ—i khi import sirius, nÃŗ không đưáģŖc cài đáēˇt 😱 +Traceback (most recent call last): + File "main.py", line 1, in + import sirius +``` + +
+ +Náēŋu báēĄn huáģˇ kích hoáēĄt môi trưáģng áēŖo hiáģ‡n táēĄi và kích hoáēĄt môi trưáģng áēŖo máģ›i cho `prisoner-of-azkaban`, khi báēĄn cháēĄy `python`, nÃŗ sáēŊ sáģ­ dáģĨng Python táģĢ môi trưáģng áēŖo trong `prisoner-of-azkaban`. + +
+ +```console +$ cd ~/code/prisoner-of-azkaban + +// BáēĄn không cáē§n pháēŖi áģŸ trong thư máģĨc trưáģ›c đáģƒ huáģˇ kích hoáēĄt, báēĄn cÃŗ tháģƒ làm điáģu Ä‘Ãŗ áģŸ báēĨt káģŗ Ä‘Ãĸu, ngay cáēŖ sau khi đi đáēŋn dáģą ÃĄn khÃĄc 😎 +$ deactivate + +// Kích hoáēĄt môi trưáģng áēŖo trong prisoner-of-azkaban/.venv 🚀 +$ source .venv/bin/activate + +// BÃĸy giáģ khi báēĄn cháēĄy python, nÃŗ sáēŊ tÃŦm tháēĨy gÃŗi sirius đưáģŖc cài đáēˇt trong môi trưáģng áēŖo này ✨ +$ python main.py + +I solemnly swear đŸē + +(Tôi long tráģng tháģ đŸē - cÃĸu này đưáģŖc láēĨy táģĢ Harry Potter, chÃē thích cáģ§a ngưáģi dáģ‹ch) +``` + +
+ +## CÃĄc cÃĄch làm tÆ°ÆĄng táģą + +ĐÃĸy là máģ™t hưáģ›ng dáēĢn Ä‘ÆĄn giáēŖn đáģƒ báēĄn cÃŗ tháģƒ báē¯t đáē§u và hiáģƒu cÃĄch máģi tháģŠ hoáēĄt đáģ™ng **bÃĒn trong**. + +CÃŗ nhiáģu **cÃĄch khÃĄc nhau** đáģƒ quáēŖn lí cÃĄc môi trưáģng áēŖo, cÃĄc gÃŗi pháģĨ thuáģ™c (requirements), và cÃĄc dáģą ÃĄn. + +Máģ™t khi báēĄn Ä‘ÃŖ sáēĩn sàng và muáģ‘n sáģ­ dáģĨng máģ™t công cáģĨ đáģƒ **quáēŖn lí cáēŖ dáģą ÃĄn**, cÃĄc gÃŗi pháģĨ thuáģ™c, cÃĄc môi trưáģng áēŖo, v.v. Tôi sáēŊ khuyÃĒn báēĄn nÃĒn tháģ­ uv. + +`uv` cÃŗ tháģƒ làm nhiáģu tháģŠ, cháēŗng háēĄn: + +* **Cài đáēˇt Python** cho báēĄn, bao gáģ“m nhiáģu phiÃĒn báēŖn khÃĄc nhau +* QuáēŖn lí **cÃĄc môi trưáģng áēŖo** cho cÃĄc dáģą ÃĄn cáģ§a báēĄn +* Cài đáēˇt **cÃĄc gÃŗi (packages)** +* QuáēŖn lí **cÃĄc thành pháē§n pháģĨ thuáģ™c và phiÃĒn báēŖn** cáģ§a cÃĄc gÃŗi cho dáģą ÃĄn cáģ§a báēĄn +* ĐáēŖm báēŖo ráēąng báēĄn cÃŗ máģ™t **táē­p háģŖp chính xÃĄc** cÃĄc gÃŗi và phiÃĒn báēŖn đáģƒ cài đáēˇt, bao gáģ“m cÃĄc thành pháē§n pháģĨ thuáģ™c cáģ§a chÃēng, đáģƒ báēĄn cÃŗ tháģƒ Ä‘áēŖm báēŖo ráēąng báēĄn cÃŗ tháģƒ cháēĄy dáģą ÃĄn cáģ§a báēĄn trong sáēŖn xuáēĨt chính xÃĄc như trong mÃĄy tính cáģ§a báēĄn trong khi phÃĄt triáģƒn, điáģu này đưáģŖc gáģi là **locking** +* Và cÃ˛n nhiáģu tháģŠ khÃĄc náģ¯a + +## Káēŋt luáē­n + +Náēŋu báēĄn Ä‘ÃŖ đáģc và hiáģƒu háēŋt nháģ¯ng điáģu này, khÃĄ cháē¯c là bÃĸy giáģ báēĄn Ä‘ÃŖ **biáēŋt nhiáģu hÆĄn** váģ môi trưáģng áēŖo so váģ›i kha khÃĄ láē­p trÃŦnh viÃĒn khÃĄc đáēĨy. 🤓 + +Nháģ¯ng hiáģƒu biáēŋt chi tiáēŋt này cÃŗ tháģƒ sáēŊ háģ¯u ích váģ›i báēĄn trong tÆ°ÆĄng lai khi mà báēĄn cáē§n gáģĄ láģ—i máģ™t vài tháģŠ pháģŠc táēĄp, và báēĄn Ä‘ÃŖ cÃŗ nháģ¯ng hiáģƒu biáēŋt váģ **ngáģn ngành gáģ‘c ráģ… cÃĄch nÃŗ hoáēĄt đáģ™ng**. 😎 diff --git a/docs/yo/docs/index.md b/docs/yo/docs/index.md index 3ad1483de..d6aa78b3d 100644 --- a/docs/yo/docs/index.md +++ b/docs/yo/docs/index.md @@ -12,7 +12,7 @@

- Test + Test Coverage diff --git a/docs/zh-hant/docs/index.md b/docs/zh-hant/docs/index.md index 137a17284..81d99ede4 100644 --- a/docs/zh-hant/docs/index.md +++ b/docs/zh-hant/docs/index.md @@ -6,7 +6,7 @@

- Test + Test Coverage diff --git a/docs/zh/docs/deployment/concepts.md b/docs/zh/docs/deployment/concepts.md index 7a0b6c3d2..f7208da7c 100644 --- a/docs/zh/docs/deployment/concepts.md +++ b/docs/zh/docs/deployment/concepts.md @@ -220,7 +220,7 @@ čŋ™äē›åˇĨäŊœčŋ›į¨‹å°†æ˜¯čŋčĄŒæ‚¨įš„åē”ᔍፋåēįš„čŋ›į¨‹īŧŒåރäģŦå°†æ‰§čĄŒä¸ģčĻčŽĄįŽ—äģĨæŽĨæ”ļ **č¯ˇæą‚** åšļčŋ”回 **响åē”**īŧŒåšļ且厃äģŦ将加čŊŊ您攞å…Ĩ RAM ä¸­įš„å˜é‡ä¸­įš„äģģäŊ•内厚。 - + åŊ“į„ļīŧŒé™¤ä熿‚¨įš„åē”ᔍፋåēäš‹å¤–īŧŒåŒä¸€å°æœē器可čƒŊčŋ˜čŋčĄŒ**å…ļäģ–čŋ›į¨‹**。 diff --git a/docs/zh/docs/deployment/https.md b/docs/zh/docs/deployment/https.md index 9c963d587..d994c4add 100644 --- a/docs/zh/docs/deployment/https.md +++ b/docs/zh/docs/deployment/https.md @@ -86,7 +86,7 @@ DNS æœåŠĄå™¨äŧšå‘Šč¯‰æĩč§ˆå™¨äŊŋį”¨æŸä¸Ēį‰šåŽšįš„ **IP 地址**。 čŋ™å°†æ˜¯äŊ åœ¨ DNS æœåŠĄå™¨ä¸­ä¸ēäŊ įš„æœåŠĄå™¨é…įŊŽįš„å…Ŧå…ą IP 地址。 - + ### TLS æĄæ‰‹åŧ€å§‹ @@ -94,7 +94,7 @@ DNS æœåŠĄå™¨äŧšå‘Šč¯‰æĩč§ˆå™¨äŊŋį”¨æŸä¸Ēį‰šåŽšįš„ **IP 地址**。 čŋ™å°†æ˜¯ 通äŋĄįš„įŦŦ一部分åĒ是åģēįĢ‹åŽĸæˆˇįĢ¯å’ŒæœåŠĄå™¨äš‹é—´įš„čŋžæŽĨåšļå†ŗåŽšåŽƒäģŦ将äŊŋį”¨įš„åŠ å¯†å¯†é’Ĩį­‰ã€‚ - + åŽĸæˆˇįĢ¯å’ŒæœåŠĄå™¨äš‹é—´åģēįĢ‹ TLS čŋžæŽĨįš„čŋ‡į¨‹į§°ä¸ē **TLS æĄæ‰‹**。 @@ -112,7 +112,7 @@ TLS į숿­ĸäģŖį†å¯äģĨčŽŋ问一ä¸Ē或多ä¸Ē **TLS 蝁äšĻ**īŧˆHTTPS 蝁äšĻīŧ‰ã€‚ 在čŋ™į§æƒ…å†ĩ下īŧŒåŽƒå°†äŊŋᔍ`someapp.example.com`įš„č¯äšĻ。 - + åŽĸæˆˇį̝厞įģ**äŋĄäģģ**į”Ÿæˆč¯Ĩ TLS 蝁äšĻįš„åŽžäŊ“īŧˆåœ¨æœŦ例中ä¸ē Let's EncryptīŧŒäŊ†æˆ‘äģŦį¨åŽäŧšįœ‹åˆ°īŧ‰īŧŒå› æ­¤åŽƒå¯äģĨ**énj蝁**č¯Ĩ蝁äšĻ是åĻ有效。 @@ -134,19 +134,19 @@ TLS į숿­ĸäģŖį†å¯äģĨčŽŋ问一ä¸Ē或多ä¸Ē **TLS 蝁äšĻ**īŧˆHTTPS 蝁äšĻīŧ‰ã€‚ æŽĨ下æĨīŧŒåŽĸæˆˇįĢ¯å‘é€ä¸€ä¸Ē **HTTPS č¯ˇæą‚**。 čŋ™å…ļ厞åĒ是一ä¸Ē通čŋ‡ TLS 加密čŋžæŽĨįš„ HTTP č¯ˇæą‚ã€‚ - + ### č§Ŗå¯†č¯ˇæą‚ TLS į숿­ĸäģŖį†å°†äŊŋį”¨åå•†åĨŊįš„åŠ å¯†įŽ—æŗ•**č§Ŗå¯†č¯ˇæą‚**īŧŒåšļ将**īŧˆč§Ŗå¯†įš„īŧ‰HTTP č¯ˇæą‚**äŧ čž“到čŋčĄŒåē”ᔍፋåēįš„čŋ›į¨‹īŧˆäž‹åĻ‚čŋčĄŒ FastAPI åē”į”¨įš„ Uvicorn čŋ›į¨‹īŧ‰ã€‚ - + ### HTTP 响åē” åē”ᔍፋåēå°†å¤„į†č¯ˇæą‚åšļ向 TLS į숿­ĸäģŖį†å‘送**īŧˆæœĒ加密īŧ‰HTTP 响åē”**。 - + ### HTTPS 响åē” @@ -154,7 +154,7 @@ TLS į숿­ĸäģŖį†å°†äŊŋį”¨åå•†åĨŊįš„åŠ å¯†įŽ—æŗ•**č§Ŗå¯†č¯ˇæą‚**īŧŒåšļ将**īŧˆ æŽĨ下æĨīŧŒæĩč§ˆå™¨å°†éĒŒč¯å“å甿˜¯åĻ有效和是åĻäŊŋᔍä熿­ŖįĄŽįš„加密密é’Ĩį­‰ã€‚į„ļ后厃äŧš**č§Ŗå¯†å“åē”**åšļå¤„į†åŽƒã€‚ - + åŽĸæˆˇį̝īŧˆæĩč§ˆå™¨īŧ‰å°†įŸĨ道响å甿Ĩč‡Ēæ­ŖįĄŽįš„æœåŠĄå™¨īŧŒå› ä¸ē厃äŊŋᔍäē†äģ–äģŦ䚋前äŊŋᔍ **HTTPS 蝁äšĻ** 协商å‡ēįš„åŠ å¯†įŽ—æŗ•ã€‚ @@ -164,7 +164,7 @@ TLS į숿­ĸäģŖį†å°†äŊŋį”¨åå•†åĨŊįš„åŠ å¯†įŽ—æŗ•**č§Ŗå¯†č¯ˇæą‚**īŧŒåšļ将**īŧˆ åĒ有一ä¸Ēčŋ›į¨‹å¯äģĨå¤„į†į‰šåŽšįš„ IP 和įĢ¯åŖīŧˆåœ¨æˆ‘äģŦįš„į¤ē例中ä¸ē TLS į숿­ĸäģŖį†īŧ‰īŧŒäŊ†å…ļäģ–åē”ᔍፋåē/čŋ›į¨‹äšŸå¯äģĨåœ¨æœåŠĄå™¨ä¸ŠčŋčĄŒīŧŒåĒčĻåŽƒäģŦä¸å°č¯•äŊŋį”¨į›¸åŒįš„ **å…Ŧå…ą IP 和įĢ¯åŖįš„įģ„合**。 - + čŋ™æ ˇīŧŒTLS į숿­ĸäģŖį†å°ąå¯äģĨä¸ē多ä¸Ēåē”ᔍፋåēå¤„ᐆ**多ä¸Ē域名**įš„ HTTPS å’Œč¯äšĻīŧŒį„ļåŽåœ¨æ¯į§æƒ…å†ĩä¸‹å°†č¯ˇæą‚äŧ čž“åˆ°æ­ŖįĄŽįš„åē”ᔍፋåēã€‚ @@ -174,7 +174,7 @@ TLS į숿­ĸäģŖį†å°†äŊŋį”¨åå•†åĨŊįš„åŠ å¯†įŽ—æŗ•**č§Ŗå¯†č¯ˇæą‚**īŧŒåšļ将**īŧˆ į„ļ后īŧŒäŧšæœ‰åĻ一ä¸Ēፋåēīŧˆåœ¨æŸä盿ƒ…å†ĩ下是åĻ一ä¸ĒፋåēīŧŒåœ¨æŸä盿ƒ…å†ĩ下可čƒŊ是同一ä¸Ē TLS į숿­ĸäģŖį†īŧ‰ä¸Ž Let's Encrypt 通äŋĄåšļæ›´æ–°č¯äšĻ。 - + **TLS 蝁äšĻ** **ä¸ŽåŸŸåį›¸å…ŗč”**īŧŒč€Œä¸æ˜¯ä¸Ž IP åœ°å€į›¸å…ŗč”ã€‚ diff --git a/docs/zh/docs/deployment/manually.md b/docs/zh/docs/deployment/manually.md index 30ee7a1e9..3dc5942e3 100644 --- a/docs/zh/docs/deployment/manually.md +++ b/docs/zh/docs/deployment/manually.md @@ -1,159 +1,157 @@ -# 手动čŋčĄŒæœåŠĄå™¨ - Uvicorn +# 手动čŋčĄŒæœåŠĄå™¨ -在čŋœį¨‹æœåŠĄå™¨čŽĄįŽ—æœē上čŋčĄŒ **FastAPI** åē”ᔍፋåēæ‰€éœ€įš„ä¸ģčρ䏜čĨŋ是 ASGI æœåŠĄå™¨į¨‹åēīŧŒäž‹åĻ‚ **Uvicorn**。 +## äŊŋᔍ `fastapi run` å‘Ŋäģ¤ -有 3 ä¸Ēä¸ģčĻå¯é€‰æ–šæĄˆīŧš +įŽ€č€Œč¨€äš‹īŧŒäŊŋᔍ `fastapi run` æĨčŋčĄŒæ‚¨įš„ FastAPI åē”ᔍፋåēīŧš -* UvicornīŧšéĢ˜æ€§čƒŊ ASGI æœåŠĄå™¨ã€‚ -* Hypercornīŧšä¸Ž HTTP/2 和 Trio į­‰å…ŧåŽšįš„ ASGI æœåŠĄå™¨ã€‚ -* Daphneīŧšä¸ē Django Channels 构åģēįš„ ASGI æœåŠĄå™¨ã€‚ - -## æœåŠĄå™¨ä¸ģæœēå’ŒæœåŠĄå™¨į¨‹åē - -å…ŗäēŽåį§°īŧŒæœ‰ä¸€ä¸Ē小įģ†čŠ‚éœ€čĻčŽ°äŊã€‚ 💡 - -“**æœåŠĄå™¨**â€ä¸€č¯é€šå¸¸į”¨äēŽæŒ‡čŋœį¨‹/äē‘čŽĄįŽ—æœēīŧˆį‰Šį†æœēæˆ–č™šæ‹Ÿæœēīŧ‰äģĨ及在č¯ĨčŽĄįŽ—æœē上čŋčĄŒįš„ፋåēīŧˆäž‹åĻ‚ Uvicornīŧ‰ã€‚ +

-č¯ˇčŽ°äŊīŧŒåŊ“您一čˆŦč¯ģåˆ°â€œæœåŠĄå™¨â€čŋ™ä¸Ēåč¯æ—ļīŧŒåŽƒå¯čƒŊæŒ‡įš„æ˜¯čŋ™ä¸¤č€…䚋一。 +```console +$ fastapi run main.py -åŊ“提到čŋœį¨‹ä¸ģæœēæ—ļīŧŒé€šå¸¸å°†å…ļį§°ä¸ē**æœåŠĄå™¨**īŧŒäŊ†äšŸį§°ä¸ē**æœē器**(machine)、**VM**īŧˆč™šæ‹Ÿæœēīŧ‰ã€**čŠ‚į‚š**。 čŋ™äē›éƒŊæ˜¯æŒ‡æŸį§įąģåž‹įš„čŋœį¨‹čŽĄįŽ—æœēīŧŒé€šå¸¸čŋčĄŒ LinuxīŧŒæ‚¨å¯äģĨ在å…ļ中čŋčĄŒį¨‹åēã€‚ + FastAPI Starting production server 🚀 + Searching for package file structure from directories + with __init__.py files + Importing from /home/user/code/awesomeapp -## åŽ‰čŖ…æœåŠĄå™¨į¨‹åē + module 🐍 main.py -您可äģĨäŊŋᔍäģĨ下å‘Ŋäģ¤åމ誅 ASGI å…ŧåŽšæœåŠĄå™¨īŧš + code Importing the FastAPI app object from the module with + the following code: -//// tab | Uvicorn + from main import app -* UvicornīŧŒä¸€ä¸ĒåŋĢåĻ‚é—Ēį”ĩ ASGI æœåŠĄå™¨īŧŒåŸēäēŽ uvloop 和 httptools 构åģē。 + app Using import string: main:app -
+ server Server started at http://0.0.0.0:8000 + server Documentation at http://0.0.0.0:8000/docs -```console -$ pip install "uvicorn[standard]" + Logs: ----> 100% + INFO Started server process [2306215] + INFO Waiting for application startup. + INFO Application startup complete. + INFO Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C + to quit) ```
-/// tip +čŋ™åœ¨å¤§å¤šæ•°æƒ…å†ĩ下éƒŊčƒŊæ­Ŗå¸¸čŋčĄŒã€‚đŸ˜Ž -通čŋ‡æˇģ加`standard`īŧŒUvicorn å°†åŽ‰čŖ…åšļäŊŋᔍ䏀ä盿Ž¨čįš„éĸå¤–䞝čĩ–éĄšã€‚ +例åĻ‚īŧŒæ‚¨å¯äģĨäŊŋᔍč¯Ĩå‘Ŋäģ¤åœ¨åŽšå™¨ã€æœåŠĄå™¨į­‰įŽ¯åĸƒä¸­å¯åŠ¨æ‚¨įš„ **FastAPI** åē”į”¨ã€‚ -å…ļ中包æ‹Ŧ`uvloop`īŧŒåŽƒæ˜¯`asyncio`įš„éĢ˜æ€§čƒŊæ›ŋäģŖå“īŧŒåŽƒæäž›äē†åˇ¨å¤§įš„åšļ发性čƒŊ提升。 +## ASGI æœåŠĄå™¨ -/// +čŽŠæˆ‘äģŦæˇąå…Ĩäē†č§Ŗä¸€äē›įģ†čŠ‚ã€‚ -//// +FastAPI äŊŋᔍäē†ä¸€į§į”¨äēŽæž„åģē Python Web æĄ†æžļå’ŒæœåŠĄå™¨įš„æ ‡å‡†īŧŒį§°ä¸ē ASGI。FastAPI æœŦč´¨ä¸Šæ˜¯ä¸€ä¸Ē ASGI Web æĄ†æžļ。 -//// tab | Hypercorn +čρ圍čŋœį¨‹æœåŠĄå™¨ä¸ŠčŋčĄŒ **FastAPI** åē”ᔍīŧˆæˆ–äģģäŊ•å…ļäģ– ASGI åē”ᔍīŧ‰īŧŒæ‚¨éœ€čρ䏀ä¸Ē ASGI æœåŠĄå™¨į¨‹åēīŧŒäž‹åĻ‚ **Uvicorn**。厃是 `fastapi` å‘Ŋäģ¤éģ˜čޤäŊŋį”¨įš„ ASGI æœåŠĄå™¨ã€‚ -* HypercornīŧŒä¸€ä¸Ē也与 HTTP/2 å…ŧåŽšįš„ ASGI æœåŠĄå™¨ã€‚ - -
+除此䚋外īŧŒčŋ˜æœ‰å…ļäģ–一äē›å¯é€‰įš„ ASGI æœåŠĄå™¨īŧŒäž‹åĻ‚īŧš -```console -$ pip install hypercorn - ----> 100% -``` - -
+* UvicornīŧšéĢ˜æ€§čƒŊ ASGI æœåŠĄå™¨ã€‚ +* Hypercornīŧšä¸Ž HTTP/2 和 Trio į­‰å…ŧåŽšįš„ ASGI æœåŠĄå™¨ã€‚ +* Daphneīŧšä¸ē Django Channels 构åģēįš„ ASGI æœåŠĄå™¨ã€‚ +* GranianīŧšåŸēäēŽ Rust įš„ HTTP æœåŠĄå™¨īŧŒä¸“ä¸ē Python åē”į”¨čŽžčŽĄã€‚ +* NGINX UnitīŧšNGINX Unit 是一ä¸ĒčŊģ量įē§ä¸”įĩæ´ģįš„ Web åē”ᔍčŋčĄŒæ—ļįŽ¯åĸƒã€‚ -...或äģģäŊ•å…ļäģ– ASGI æœåŠĄå™¨ã€‚ +## æœåŠĄå™¨ä¸ģæœēå’ŒæœåŠĄå™¨į¨‹åē -//// +å…ŗäēŽåį§°īŧŒæœ‰ä¸€ä¸Ē小įģ†čŠ‚éœ€čĻčŽ°äŊã€‚ 💡 -## čŋčĄŒæœåŠĄå™¨į¨‹åē +“**æœåŠĄå™¨**â€ä¸€č¯é€šå¸¸į”¨äēŽæŒ‡čŋœį¨‹/äē‘čŽĄįŽ—æœēīŧˆį‰Šį†æœēæˆ–č™šæ‹Ÿæœēīŧ‰äģĨ及在č¯ĨčŽĄįŽ—æœē上čŋčĄŒįš„ፋåēīŧˆäž‹åĻ‚ Uvicornīŧ‰ã€‚ -您可äģĨæŒ‰į…§äš‹å‰æ•™į¨‹ä¸­įš„į›¸åŒæ–šåŧčŋčĄŒåē”ᔍፋåēīŧŒäŊ†ä¸äŊŋᔍ`--reload`选项īŧŒäž‹åĻ‚īŧš +č¯ˇčŽ°äŊīŧŒåŊ“您一čˆŦč¯ģåˆ°â€œæœåŠĄå™¨â€čŋ™ä¸Ēåč¯æ—ļīŧŒåŽƒå¯čƒŊæŒ‡įš„æ˜¯čŋ™ä¸¤č€…䚋一。 -//// tab | Uvicorn +åŊ“提到čŋœį¨‹ä¸ģæœēæ—ļīŧŒé€šå¸¸å°†å…ļį§°ä¸ē**æœåŠĄå™¨**īŧŒäŊ†äšŸį§°ä¸ē**æœē器**(machine)、**VM**īŧˆč™šæ‹Ÿæœēīŧ‰ã€**čŠ‚į‚š**。 čŋ™äē›éƒŊæ˜¯æŒ‡æŸį§įąģåž‹įš„čŋœį¨‹čŽĄįŽ—æœēīŧŒé€šå¸¸čŋčĄŒ LinuxīŧŒæ‚¨å¯äģĨ在å…ļ中čŋčĄŒį¨‹åēã€‚ -
-```console -$ uvicorn main:app --host 0.0.0.0 --port 80 +## åŽ‰čŖ…æœåŠĄå™¨į¨‹åē -INFO: Uvicorn running on http://0.0.0.0:80 (Press CTRL+C to quit) -``` +åŊ“您åމ誅 FastAPI æ—ļīŧŒåރč‡Ēå¸Ļ一ä¸Ēį”Ÿäē§įޝåĸƒæœåŠĄå™¨â€”â€”UvicornīŧŒåšļ且您可äģĨäŊŋᔍ `fastapi run` å‘Ŋä줿Ĩ启动厃。 -
+不čŋ‡īŧŒæ‚¨äšŸå¯äģĨæ‰‹åŠ¨åŽ‰čŖ… ASGI æœåŠĄå™¨ã€‚ -//// +č¯ˇįĄŽäŋæ‚¨åˆ›åģēåšļæŋ€æ´ģ一ä¸Ē[č™šæ‹ŸįŽ¯åĸƒ](../virtual-environments.md){.internal-link target=_blank}īŧŒį„ļåŽå†åŽ‰čŖ…æœåŠĄå™¨åē”ᔍፋåēã€‚ -//// tab | Hypercorn +例åĻ‚īŧŒčĻåŽ‰čŖ… UvicornīŧŒå¯äģĨčŋčĄŒäģĨ下å‘Ŋäģ¤īŧš
```console -$ hypercorn main:app --bind 0.0.0.0:80 +$ pip install "uvicorn[standard]" -Running on 0.0.0.0:8080 over http (CTRL + C to quit) +---> 100% ```
-//// +įąģäŧŧįš„æĩį¨‹äšŸé€‚ᔍäēŽäģģäŊ•å…ļäģ– ASGI æœåŠĄå™¨į¨‹åēã€‚ -/// warning +/// tip -åĻ‚æžœæ‚¨æ­Ŗåœ¨äŊŋᔍ`--reload`选项īŧŒč¯ˇčްäŊåˆ é™¤åŽƒã€‚ +通čŋ‡æˇģ加 `standard` 选项īŧŒUvicorn å°†åŽ‰čŖ…åšļäŊŋᔍ䏀ä盿Ž¨čįš„éĸå¤–䞝čĩ–éĄšã€‚ - `--reload` 选项æļˆč€—更多čĩ„æēīŧŒåšļä¸”æ›´ä¸į¨ŗåŽšã€‚ +å…ļ中包æ‹Ŧ `uvloop`īŧŒčŋ™æ˜¯ `asyncio` įš„éĢ˜æ€§čƒŊæ›ŋäģŖæ–šæĄˆīŧŒčƒŊå¤Ÿæ˜žč‘—æå‡åšļ发性čƒŊ。 - 厃在**åŧ€å‘**期间有垈大帎劊īŧŒäŊ†æ‚¨**不åē”č¯Ĩ**在**į”Ÿäē§įޝåĸƒ**中äŊŋį”¨åŽƒã€‚ +åŊ“您äŊŋᔍ `pip install "fastapi[standard]"` åŽ‰čŖ… FastAPI æ—ļīŧŒåŽžé™…ä¸ŠäšŸäŧšåމ誅 `uvicorn[standard]`。 /// -## Hypercorn with Trio - -Starlette 和 **FastAPI** åŸēäēŽ AnyIOīŧŒ 所äģĨ厃äģŦ才čƒŊ同æ—ļ与 Python įš„æ ‡å‡†åē“ asyncio 和Trio å…ŧ厚。 - -å°ŊįŽĄåĻ‚æ­¤īŧŒUvicorn į›Žå‰äģ…与 asyncio å…ŧ厚īŧŒåšļ且通常äŊŋᔍ `uvloop`, 厃是`asyncio`įš„éĢ˜æ€§čƒŊæ›ŋäģŖå“ã€‚ - -äŊ†åĻ‚æžœäŊ æƒŗį›´æŽĨäŊŋᔍ**Trio**īŧŒé‚ŖäšˆäŊ å¯äģĨäŊŋᔍ**Hypercorn**īŧŒå› ä¸ē厃支持厃。 ✨ - -### åŽ‰čŖ…å…ˇæœ‰ Trio įš„ Hypercorn +## čŋčĄŒæœåŠĄå™¨į¨‹åē -éĻ–å…ˆīŧŒæ‚¨éœ€čĻåŽ‰čŖ…å…ˇæœ‰ Trio æ”¯æŒįš„ Hypercornīŧš +åĻ‚æžœæ‚¨æ‰‹åŠ¨åŽ‰čŖ…äē† ASGI æœåŠĄå™¨īŧŒé€šå¸¸éœ€čρäģĨį‰šåŽšæ ŧåŧäŧ é€’一ä¸Ēå¯ŧå…Ĩ字įŦĻ串īŧŒäģĨäžŋæœåŠĄå™¨čƒŊå¤Ÿæ­ŖįĄŽå¯ŧå…Ĩæ‚¨įš„ FastAPI åē”ᔍīŧš
```console -$ pip install "hypercorn[trio]" ----> 100% +$ uvicorn main:app --host 0.0.0.0 --port 80 + +INFO: Uvicorn running on http://0.0.0.0:80 (Press CTRL+C to quit) ```
-### Run with Trio +/// note -į„ļ后äŊ å¯äģĨäŧ é€’å€ŧ`trio`įģ™å‘Ŋäģ¤čĄŒé€‰éĄš`--worker-class`: +å‘Ŋäģ¤ `uvicorn main:app` įš„åĢ义åς䏋īŧš -
+* `main`īŧšæŒ‡įš„æ˜¯ `main.py` 文äģļīŧˆåŗ Python â€œæ¨Ąå—â€īŧ‰ã€‚ +* `app`īŧšæŒ‡įš„æ˜¯ `main.py` 文äģļ中通čŋ‡ `app = FastAPI()` 创åģēįš„å¯ščąĄã€‚ -```console -$ hypercorn main:app --worker-class trio +åŽƒį­‰äģˇäēŽäģĨ下å¯ŧå…Ĩ蝭åĨīŧš + +```Python +from main import app ``` -
+/// + +æ¯į§ ASGI æœåŠĄå™¨į¨‹åēé€šå¸¸éƒŊäŧšæœ‰įąģäŧŧįš„å‘Ŋäģ¤īŧŒæ‚¨å¯äģĨ在厃äģŦįš„åŽ˜æ–šæ–‡æĄŖä¸­æ‰žåˆ°æ›´å¤šäŋĄæ¯ã€‚ + +/// warning + +Uvicorn 和å…ļäģ–æœåŠĄå™¨æ”¯æŒ `--reload` 选项īŧŒč¯Ĩé€‰éĄšåœ¨åŧ€å‘čŋ‡į¨‹ä¸­éžå¸¸æœ‰į”¨ã€‚ -čŋ™å°†é€ščŋ‡æ‚¨įš„åē”ᔍፋåēå¯åЍ HypercornīŧŒåšļäŊŋᔍ Trio äŊœä¸ē后įĢ¯ã€‚ +äŊ† `--reload` 选项äŧšæļˆč€—更多čĩ„æēīŧŒä¸”į›¸å¯šä¸į¨ŗåŽšã€‚ -įŽ°åœ¨æ‚¨å¯äģĨ在åē”ᔍፋåēå†…部äŊŋᔍ Trio。 æˆ–č€…æ›´åĨŊįš„æ˜¯īŧŒæ‚¨å¯äģĨäŊŋᔍ AnyIOīŧŒäŊŋæ‚¨įš„äģŖį ä¸Ž Trio 和 asyncio å…ŧ厚。 🎉 +厃寚äēŽ**åŧ€å‘é˜ļæŽĩ**非常有帎劊īŧŒäŊ†åœ¨**į”Ÿäē§įޝåĸƒ**中**不åē”č¯Ĩ**äŊŋį”¨ã€‚ + +/// ## 部įŊ˛æĻ‚åŋĩ -čŋ™äē›į¤ē例čŋčĄŒæœåŠĄå™¨į¨‹åēīŧˆäž‹åĻ‚ Uvicornīŧ‰īŧŒå¯åЍ**单ä¸Ēčŋ›į¨‹**īŧŒåœ¨æ‰€æœ‰ IPīŧˆ`0.0.0.0`)ä¸Šį›‘åŦéĸ„厚䚉įĢ¯åŖīŧˆäž‹åĻ‚`80`)。 +čŋ™äē›į¤ē例čŋčĄŒæœåŠĄå™¨į¨‹åēīŧˆäž‹åĻ‚ Uvicornīŧ‰īŧŒå¯åЍ**单ä¸Ēčŋ›į¨‹**īŧŒåœ¨æ‰€æœ‰ IPīŧˆ`0.0.0.0`īŧ‰ä¸Šį›‘åŦéĸ„厚䚉įĢ¯åŖīŧˆäž‹åĻ‚`80`īŧ‰ã€‚ čŋ™æ˜¯åŸēæœŦæ€čˇ¯ã€‚ äŊ†æ‚¨å¯čƒŊ需čρ处ᐆ䏀äē›å…ļäģ–ä狿ƒ…īŧŒäž‹åĻ‚īŧš * 厉全性 - HTTPS * 启动æ—ļčŋčĄŒ * 重新启动 -* ReplicationīŧˆčŋčĄŒįš„čŋ›į¨‹æ•°īŧ‰ +* 复åˆļīŧˆčŋčĄŒįš„čŋ›į¨‹æ•°īŧ‰ * 内存 * åŧ€å§‹å‰įš„æ­ĨéǤ diff --git a/docs/zh/docs/deployment/server-workers.md b/docs/zh/docs/deployment/server-workers.md index eb0252a5c..e46ba7a09 100644 --- a/docs/zh/docs/deployment/server-workers.md +++ b/docs/zh/docs/deployment/server-workers.md @@ -1,4 +1,4 @@ -# Server Workers - Gunicorn with Uvicorn +# æœåŠĄå™¨åˇĨäŊœčŋ›į¨‹īŧˆWorkersīŧ‰ - äŊŋᔍ Uvicorn įš„å¤šåˇĨäŊœčŋ›į¨‹æ¨Ąåŧ čŽŠæˆ‘äģŦå›žéĄžä¸€ä¸‹äš‹å‰įš„éƒ¨įŊ˛æĻ‚åŋĩīŧš @@ -9,125 +9,79 @@ * 内存 * å¯åŠ¨å‰įš„å…ˆå‰æ­ĨéǤ -åˆ°į›Žå‰ä¸ēæ­ĸīŧŒé€ščŋ‡æ–‡æĄŖä¸­įš„æ‰€æœ‰æ•™į¨‹īŧŒæ‚¨å¯čƒŊ厞įģåœ¨**单ä¸Ēčŋ›į¨‹**上čŋčĄŒäē†åƒ Uvicorn čŋ™æ ˇįš„**æœåŠĄå™¨į¨‹åē**。 +åˆ°į›Žå‰ä¸ēæ­ĸīŧŒåœ¨æ–‡æĄŖä¸­įš„æ‰€æœ‰æ•™į¨‹ä¸­īŧŒæ‚¨å¯čƒŊä¸€į›´æ˜¯åœ¨čŋčĄŒä¸€ä¸Ē**æœåŠĄå™¨į¨‹åē**īŧŒäž‹åĻ‚äŊŋᔍ `fastapi` å‘Ŋä줿Ĩ启动 UvicornīŧŒč€Œåރéģ˜čޤčŋčĄŒįš„æ˜¯**单čŋ›į¨‹æ¨Ąåŧ**。 -部įŊ˛åē”ᔍፋåēæ—ļīŧŒæ‚¨å¯čƒŊ希望čŋ›čĄŒä¸€äē›**čŋ›į¨‹å¤åˆļ**īŧŒäģĨåˆŠį”¨**多核**åšļčƒŊå¤Ÿå¤„į†æ›´å¤šč¯ˇæą‚ã€‚ +部įŊ˛åē”ᔍፋåēæ—ļīŧŒæ‚¨å¯čƒŊ希望čŋ›čĄŒä¸€äē›**čŋ›į¨‹å¤åˆļ**īŧŒäģĨåˆŠį”¨**多核** CPU åšļčƒŊå¤Ÿå¤„į†æ›´å¤šč¯ˇæą‚ã€‚ æ­ŖåĻ‚æ‚¨åœ¨ä¸Šä¸€įĢ æœ‰å…ŗ[部įŊ˛æĻ‚åŋĩ](concepts.md){.internal-link target=_blank}ä¸­įœ‹åˆ°įš„īŧŒæ‚¨å¯äģĨäŊŋį”¨å¤šį§į­–į•Ĩ。 -在čŋ™é‡Œæˆ‘å°†å‘æ‚¨åą•į¤ēåĻ‚äŊ•å°† **Gunicorn** 与 **Uvicorn worker čŋ›į¨‹** 一čĩˇäŊŋį”¨ã€‚ +在æœŦįĢ čŠ‚ä¸­īŧŒæˆ‘å°†å‘æ‚¨åą•į¤ēåĻ‚äŊ•äŊŋᔍ `fastapi` å‘Ŋä줿ˆ–į›´æŽĨäŊŋᔍ `uvicorn` å‘Ŋäģ¤äģĨ**多åˇĨäŊœčŋ›į¨‹æ¨Ąåŧ**čŋčĄŒ **Uvicorn**。 /// info åĻ‚æžœæ‚¨æ­Ŗåœ¨äŊŋį”¨åŽšå™¨īŧŒäž‹åĻ‚ Docker 或 KubernetesīŧŒæˆ‘将在下一įĢ ä¸­å‘Šč¯‰æ‚¨æ›´å¤šį›¸å…ŗäŋĄæ¯īŧš[åŽšå™¨ä¸­įš„ FastAPI - Docker](docker.md){.internal-link target=_blank}。 -į‰šåˆĢ是īŧŒåŊ“在 **Kubernetes** 上čŋčĄŒæ—ļīŧŒæ‚¨å¯čƒŊ**ä¸æƒŗ**äŊŋᔍ GunicornīŧŒč€Œæ˜¯čŋčĄŒ **每ä¸Ē厚器一ä¸Ē Uvicorn čŋ›į¨‹**īŧŒäŊ†æˆ‘将在æœŦįĢ åŽéĸå‘Šč¯‰æ‚¨čŋ™ä¸€į‚šã€‚ +æ¯”čžƒį‰šåˆĢįš„æ˜¯īŧŒåœ¨ **Kubernetes** įŽ¯åĸƒä¸­čŋčĄŒæ—ļīŧŒæ‚¨é€šå¸¸**不需čρ**äŊŋį”¨å¤šä¸ĒåˇĨäŊœčŋ›į¨‹īŧŒč€Œæ˜¯**每ä¸Ē厚器čŋčĄŒä¸€ä¸Ē Uvicorn čŋ›į¨‹**。不čŋ‡īŧŒæˆ‘äŧšåœ¨æœŦįĢ čŠ‚įš„åŽįģ­éƒ¨åˆ†č¯Ļįģ†äģ‹įģčŋ™ä¸€į‚šã€‚ /// -## Gunicorn with Uvicorn Workers +## 多ä¸ĒåˇĨäŊœčŋ›į¨‹ -**Gunicorn**ä¸ģčĻæ˜¯ä¸€ä¸ĒäŊŋᔍ**WSGI标准**įš„åē”į”¨æœåŠĄå™¨ã€‚ čŋ™æ„å‘ŗį€ Gunicorn 可äģĨä¸ē Flask 和 Django į­‰åē”ᔍፋåēæäž›æœåŠĄã€‚ Gunicorn æœŦčēĢ与 **FastAPI** 不å…ŧ厚īŧŒå› ä¸ē FastAPI äŊŋį”¨æœ€æ–°įš„ **ASGI 标准**。 +您可äģĨäŊŋᔍ `--workers` å‘Ŋäģ¤čĄŒé€‰éĄšæĨ启动多ä¸ĒåˇĨäŊœčŋ›į¨‹īŧš -äŊ† Gunicorn 支持充åŊ“ **čŋ›į¨‹įŽĄį†å™¨** åšļå…čŽ¸į”¨æˆˇå‘Šč¯‰åŽƒčρäŊŋᔍå“Ēä¸Ēį‰šåŽšįš„ **workerįąģ**。 į„ļ后 Gunicorn 将äŊŋᔍč¯Ĩįąģ启动一ä¸Ē或多ä¸Ē **workerčŋ›į¨‹**。 +//// tab | `fastapi` -**Uvicorn** 有一ä¸Ē Gunicorn å…ŧåŽšįš„workerįąģ。 - -äŊŋᔍčŋ™į§įģ„合īŧŒGunicorn 将充åŊ“ **čŋ›į¨‹įŽĄį†å™¨**īŧŒį›‘åŦ **įĢ¯åŖ** 和 **IP**。 厃äŧšå°†é€šäŋĄ**äŧ čž“**到čŋčĄŒ**Uvicornįąģ**įš„workerčŋ›į¨‹ã€‚ - -į„ļ后与Gunicornå…ŧåŽšįš„**Uvicorn worker**įąģå°†č´Ÿč´Ŗå°†Gunicornå‘é€įš„æ•°æŽčŊŦæĸä¸ēASGI标准äģĨ供FastAPIäŊŋį”¨ã€‚ - -## åŽ‰čŖ… Gunicorn 和 Uvicorn +åĻ‚æžœæ‚¨äŊŋᔍ `fastapi` å‘Ŋäģ¤īŧš
```console -$ pip install "uvicorn[standard]" gunicorn - ----> 100% -``` - -
+$ fastapi run --workers 4 main.py -čŋ™å°†åމ誅å¸Ļ有`standard`æ‰Šåą•åŒ…īŧˆäģĨčŽˇåž—éĢ˜æ€§čƒŊīŧ‰įš„ Uvicorn 和 Gunicorn。 + FastAPI Starting production server 🚀 -## Run Gunicorn with Uvicorn Workers + Searching for package file structure from directories with + __init__.py files + Importing from /home/user/code/awesomeapp -æŽĨ下æĨäŊ å¯äģĨ通čŋ‡äģĨ下å‘Ŋäģ¤čŋčĄŒGunicorn: - -
- -```console -$ gunicorn main:app --workers 4 --worker-class uvicorn.workers.UvicornWorker --bind 0.0.0.0:80 - -[19499] [INFO] Starting gunicorn 20.1.0 -[19499] [INFO] Listening at: http://0.0.0.0:80 (19499) -[19499] [INFO] Using worker: uvicorn.workers.UvicornWorker -[19511] [INFO] Booting worker with pid: 19511 -[19513] [INFO] Booting worker with pid: 19513 -[19514] [INFO] Booting worker with pid: 19514 -[19515] [INFO] Booting worker with pid: 19515 -[19511] [INFO] Started server process [19511] -[19511] [INFO] Waiting for application startup. -[19511] [INFO] Application startup complete. -[19513] [INFO] Started server process [19513] -[19513] [INFO] Waiting for application startup. -[19513] [INFO] Application startup complete. -[19514] [INFO] Started server process [19514] -[19514] [INFO] Waiting for application startup. -[19514] [INFO] Application startup complete. -[19515] [INFO] Started server process [19515] -[19515] [INFO] Waiting for application startup. -[19515] [INFO] Application startup complete. -``` - -
+ module 🐍 main.py + code Importing the FastAPI app object from the module with the + following code: -čŽŠæˆ‘äģŦįœ‹įœ‹æ¯ä¸Ēé€‰éĄšįš„åĢ义īŧš + from main import app -* `main:app`īŧščŋ™ä¸Ž Uvicorn äŊŋį”¨įš„č¯­æŗ•į›¸åŒīŧŒ`main` 襨į¤ē名ä¸ē"`main`"įš„ Python æ¨Ąå—īŧŒå› æ­¤æ˜¯æ–‡äģļ `main.py`。 `app` 是 **FastAPI** åē”ᔍፋåēįš„å˜é‡åį§°ã€‚ - * äŊ å¯äģĨæƒŗčąĄ `main:app` ᛏåŊ“äēŽä¸€ä¸Ē Python `import` 蝭åĨīŧŒäž‹åĻ‚īŧš + app Using import string: main:app - ```Python - from main import app - ``` + server Server started at http://0.0.0.0:8000 + server Documentation at http://0.0.0.0:8000/docs - * 因此īŧŒ`main:app` ä¸­įš„å†’åˇį›¸åŊ“äēŽ `from main import app` ä¸­įš„ Python `import` 部分。 + Logs: -* `--workers`īŧščρäŊŋį”¨įš„workerčŋ›į¨‹æ•°é‡īŧŒæ¯ä¸Ēčŋ›į¨‹å°†čŋčĄŒä¸€ä¸Ē Uvicorn workerčŋ›į¨‹īŧŒåœ¨æœŦ例中ä¸ē 4 ä¸Ēworkerčŋ›į¨‹ã€‚ - -* `--worker-class`īŧšåœ¨workerčŋ›į¨‹ä¸­äŊŋį”¨įš„ä¸Ž Gunicorn å…ŧåŽšįš„åˇĨäŊœįąģ。 - * čŋ™é‡Œæˆ‘äģŦäŧ é€’äē† Gunicorn 可äģĨå¯ŧå…Ĩ和äŊŋį”¨įš„įąģīŧš - - ```Python - import uvicorn.workers.UvicornWorker - ``` - -* `--bind`īŧščŋ™å‘Šč¯‰ Gunicorn čρᛑåŦįš„ IP 和įĢ¯åŖīŧŒäŊŋį”¨å†’åˇ (`:`) 分隔 IP 和įĢ¯åŖã€‚ - * åĻ‚æžœæ‚¨į›´æŽĨčŋčĄŒ UvicornīŧŒåˆ™å¯äģĨäŊŋᔍ`--host 0.0.0.0`和`--port 80`īŧŒč€Œä¸æ˜¯`--bind 0.0.0.0:80`īŧˆGunicorn 选项īŧ‰ã€‚ - - -åœ¨čž“å‡ē中īŧŒæ‚¨å¯äģĨįœ‹åˆ°åŽƒæ˜žį¤ēä熿¯ä¸Ēčŋ›į¨‹įš„ **PID**īŧˆčŋ›į¨‹ IDīŧ‰īŧˆåރåĒ是一ä¸Ē数字īŧ‰ã€‚ - -äŊ å¯äģĨįœ‹åˆ°īŧš - -* Gunicorn **čŋ›į¨‹įŽĄį†å™¨** äģĨ PID `19499` åŧ€å¤´īŧˆåœ¨æ‚¨įš„æƒ…å†ĩ下īŧŒåŽƒå°†æ˜¯ä¸€ä¸Ēä¸åŒįš„æ•°å­—īŧ‰ã€‚ -* į„ļ后厃åŧ€å§‹`Listening at: http://0.0.0.0:80`。 -* į„ļåŽåŽƒæŖ€æĩ‹åˆ°åރåŋ…éĄģäŊŋᔍ `uvicorn.workers.UvicornWorker` å¤„įš„workerįąģ。 -* į„ļ后厃启动**4ä¸Ēworker**īŧŒæ¯ä¸ĒéƒŊ有č‡Ēåˇąįš„PIDīŧš`19511`、`19513`、`19514`和`19515`。 - -Gunicorn čŋ˜å°†č´Ÿč´ŖįŽĄį†**æ­ģčŋ›į¨‹**和**重新启动**新čŋ›į¨‹īŧˆåĻ‚æžœéœ€čρäŋæŒworker数量īŧ‰ã€‚ 因此īŧŒčŋ™åœ¨ä¸€åŽšį¨‹åēĻ上有劊äēŽä¸Šéĸåˆ—čĄ¨ä¸­**重启**įš„æĻ‚åŋĩ。 - -å°ŊįŽĄåĻ‚æ­¤īŧŒæ‚¨å¯čƒŊčŋ˜å¸Œæœ›æœ‰ä¸€äē›å¤–éƒ¨įš„ä¸œčĨŋīŧŒäģĨįĄŽäŋåœ¨åŋ…čρæ—ļ**重新启动 Gunicorn**īŧŒåšļ且**在启动æ—ļčŋčĄŒåރ**į­‰ã€‚ + INFO Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to + quit) + INFO Started parent process [27365] + INFO Started server process [27368] + INFO Started server process [27369] + INFO Started server process [27370] + INFO Started server process [27367] + INFO Waiting for application startup. + INFO Waiting for application startup. + INFO Waiting for application startup. + INFO Waiting for application startup. + INFO Application startup complete. + INFO Application startup complete. + INFO Application startup complete. + INFO Application startup complete. +``` -## Uvicorn with Workers +
-Uvicorn 䚟有一ä¸Ēé€‰éĄšå¯äģĨ启动和čŋčĄŒå¤šä¸Ē **workerčŋ›į¨‹**。 +//// -į„ļ而īŧŒåˆ°į›Žå‰ä¸ēæ­ĸīŧŒUvicorn 处ᐆworkerčŋ›į¨‹įš„čƒŊ力比 Gunicorn 更有限。 因此īŧŒåĻ‚æžœæ‚¨æƒŗæ‹Ĩ有čŋ™ä¸Ēįē§åˆĢīŧˆPython įē§åˆĢīŧ‰įš„čŋ›į¨‹įŽĄį†å™¨īŧŒé‚Ŗäšˆæœ€åĨŊå°č¯•äŊŋᔍ Gunicorn äŊœä¸ēčŋ›į¨‹įŽĄį†å™¨ã€‚ +//// tab | `uvicorn` -无čŽēåĻ‚äŊ•īŧŒæ‚¨éƒŊ可äģĨ像čŋ™æ ˇčŋčĄŒåރīŧš +åĻ‚æžœæ‚¨æ›´æƒŗčρᛴæŽĨäŊŋᔍ `uvicorn` å‘Ŋäģ¤īŧš
@@ -151,13 +105,15 @@ $ uvicorn main:app --host 0.0.0.0 --port 8080 --workers 4
+//// + čŋ™é‡Œå”¯ä¸€įš„æ–°é€‰éĄšæ˜¯ `--workers` å‘Šč¯‰ Uvicorn 启动 4 ä¸ĒåˇĨäŊœčŋ›į¨‹ã€‚ -您čŋ˜å¯äģĨįœ‹åˆ°åŽƒæ˜žį¤ēä熿¯ä¸Ēčŋ›į¨‹įš„ **PID**īŧŒįˆļčŋ›į¨‹īŧˆčŋ™æ˜¯ **čŋ›į¨‹įŽĄį†å™¨**īŧ‰įš„ PID ä¸ē`27365`īŧŒæ¯ä¸ĒåˇĨäŊœčŋ›į¨‹įš„ PID ä¸ēīŧš`27368`、`27369`īŧŒ `27370`和`27367`。 +您čŋ˜å¯äģĨįœ‹åˆ°åŽƒæ˜žį¤ēä熿¯ä¸Ēčŋ›į¨‹įš„ **PID**īŧŒįˆļčŋ›į¨‹īŧˆčŋ™æ˜¯**čŋ›į¨‹įŽĄį†å™¨**īŧ‰įš„ PID ä¸ē`27365`īŧŒæ¯ä¸ĒåˇĨäŊœčŋ›į¨‹įš„ PID ä¸ēīŧš`27368`、`27369`īŧŒ `27370`和`27367`。 ## 部įŊ˛æĻ‚åŋĩ -在čŋ™é‡ŒīŧŒæ‚¨äē†č§Ŗäē†åĻ‚äŊ•äŊŋᔍ **Gunicorn**īŧˆæˆ– Uvicornīŧ‰įŽĄį† **Uvicorn åˇĨäŊœčŋ›į¨‹**æĨ**åšļ行**åē”ᔍፋåēįš„æ‰§čĄŒīŧŒåˆŠį”¨ CPU ä¸­įš„ **多核**īŧŒåšļ čƒŊ够æģĄčļŗ**æ›´å¤šč¯ˇæą‚**。 +在čŋ™é‡ŒīŧŒæ‚¨å­Ļäš äē†åĻ‚äŊ•äŊŋį”¨å¤šä¸Ē**åˇĨäŊœčŋ›į¨‹īŧˆworkersīŧ‰**æĨ莊åē”ᔍፋåēįš„æ‰§čĄŒ**åšļčĄŒåŒ–**īŧŒå……åˆ†åˆŠį”¨ CPU įš„**多核性čƒŊ**īŧŒåšļčƒŊå¤Ÿå¤„į†**æ›´å¤šįš„č¯ˇæą‚**。 äģŽä¸Šéĸįš„éƒ¨įŊ˛æĻ‚åŋĩåˆ—čĄ¨æĨįœ‹īŧŒäŊŋᔍworkerä¸ģčĻæœ‰åŠŠäēŽ**复åˆļ**部分īŧŒåšļ寚**重新启动**æœ‰ä¸€į‚šå¸ŽåŠŠīŧŒäŊ†æ‚¨äģį„ļ需čĻį…§éĄžå…ļäģ–部分īŧš @@ -170,15 +126,13 @@ $ uvicorn main:app --host 0.0.0.0 --port 8080 --workers 4 ## 厚器和 Docker -åœ¨å…ŗäēŽ [åŽšå™¨ä¸­įš„ FastAPI - Docker](docker.md){.internal-link target=_blank} įš„ä¸‹ä¸€į̠䏭īŧŒæˆ‘å°†äģ‹įģä¸€äē›å¯į”¨äēŽå¤„ᐆå…ļäģ– **部įŊ˛æĻ‚åŋĩ** įš„į­–į•Ĩ。 - -我čŋ˜å°†å‘æ‚¨åą•į¤ē **厘斚 Docker 镜像**īŧŒå…ļ中包æ‹Ŧ **Gunicorn 和 Uvicorn worker** äģĨ及一äē›å¯šįŽ€å•æƒ…å†ĩæœ‰į”¨įš„éģ˜čŽ¤é…įŊŽã€‚ +åœ¨å…ŗäēŽ [åŽšå™¨ä¸­įš„ FastAPI - Docker](docker.md){.internal-link target=_blank} įš„ä¸‹ä¸€į̠䏭īŧŒæˆ‘å°†äģ‹įģä¸€äē›å¯į”¨äēŽå¤„ᐆå…ļäģ–**部įŊ˛æĻ‚åŋĩ**įš„į­–į•Ĩ。 -åœ¨é‚Ŗé‡ŒīŧŒæˆ‘čŋ˜å°†å‘æ‚¨åą•į¤ēåĻ‚äŊ• **äģŽå¤´åŧ€å§‹æž„åģēč‡Ēåˇąįš„é•œåƒ** äģĨčŋčĄŒå•ä¸Ē Uvicorn čŋ›į¨‹īŧˆæ˛Ąæœ‰ Gunicornīŧ‰ã€‚ čŋ™æ˜¯ä¸€ä¸ĒįŽ€å•įš„čŋ‡į¨‹īŧŒåšļ且可čƒŊ是您在äŊŋį”¨åƒ **Kubernetes** čŋ™æ ˇįš„分布åŧåŽšå™¨įŽĄį†įŗģį쟿—ļæƒŗčĻåšįš„ä狿ƒ…。 +æˆ‘å°†å‘æ‚¨åą•į¤ēåĻ‚äŊ•**äģŽé›ļåŧ€å§‹æž„åģēč‡Ēåˇąįš„é•œåƒ**īŧŒäģĨčŋčĄŒä¸€ä¸Ē单į‹Ŧįš„ Uvicorn čŋ›į¨‹ã€‚čŋ™ä¸Ēčŋ‡į¨‹į›¸å¯šįŽ€å•īŧŒåšļ且在äŊŋᔍ **Kubernetes** į­‰åˆ†å¸ƒåŧåŽšå™¨įŽĄį†įŗģį쟿—ļīŧŒčŋ™é€šå¸¸æ˜¯æ‚¨éœ€čĻé‡‡å–įš„æ–šæŗ•ã€‚ ## å›žéĄž -您可äģĨäŊŋᔍ**Gunicorn**īŧˆæˆ–Uvicornīŧ‰äŊœä¸ēUvicornåˇĨäŊœčŋ›į¨‹įš„čŋ›į¨‹įŽĄį†å™¨īŧŒäģĨåˆŠį”¨**多核CPU**īŧŒ**åšļ行čŋčĄŒå¤šä¸Ēčŋ›į¨‹**。 +您可äģĨ在äŊŋᔍ `fastapi` 或 `uvicorn` å‘Ŋä줿—ļīŧŒé€ščŋ‡ `--workers` CLI é€‰éĄšå¯į”¨å¤šä¸ĒåˇĨäŊœčŋ›į¨‹īŧˆworkersīŧ‰īŧŒäģĨå……åˆ†åˆŠį”¨**多核 CPU**īŧŒäģĨ**åšļ行čŋčĄŒå¤šä¸Ēčŋ›į¨‹**。 åĻ‚æžœæ‚¨čĻčŽžįŊŽ**č‡Ēåˇąįš„éƒ¨įŊ˛įŗģįģŸ**īŧŒåŒæ—ļč‡Ēåˇąå¤„į†å…ļäģ–部įŊ˛æĻ‚åŋĩīŧŒåˆ™å¯äģĨäŊŋᔍčŋ™äē›åˇĨå…ˇå’Œæƒŗæŗ•ã€‚ diff --git a/docs/zh/docs/index.md b/docs/zh/docs/index.md index d3e9e3112..94cf8745c 100644 --- a/docs/zh/docs/index.md +++ b/docs/zh/docs/index.md @@ -11,11 +11,11 @@ FastAPI æĄ†æžļīŧŒéĢ˜æ€§čƒŊīŧŒæ˜“äēŽå­Ļäš īŧŒéĢ˜æ•ˆįŧ–᠁īŧŒį”Ÿäē§å¯į”¨

- - Test + + Test - - Coverage + + Coverage Package version diff --git a/docs/zh/docs/python-types.md b/docs/zh/docs/python-types.md index 5126cb847..ba767da87 100644 --- a/docs/zh/docs/python-types.md +++ b/docs/zh/docs/python-types.md @@ -228,7 +228,7 @@ John Doe ## Pydantic æ¨Ąåž‹ -Pydantic 是一ä¸ĒᔍæĨᔍæĨæ‰§čĄŒæ•°æŽæ ĄéĒŒįš„ Python åē“。 +Pydantic 是一ä¸ĒᔍæĨæ‰§čĄŒæ•°æŽæ ĄéĒŒįš„ Python åē“。 äŊ å¯äģĨå°†æ•°æŽįš„"į쓿ž„"åŖ°æ˜Žä¸ēå…ˇæœ‰åąžæ€§įš„įąģ。 diff --git a/docs/zh/docs/tutorial/bigger-applications.md b/docs/zh/docs/tutorial/bigger-applications.md index 318e10fd7..554bc654f 100644 --- a/docs/zh/docs/tutorial/bigger-applications.md +++ b/docs/zh/docs/tutorial/bigger-applications.md @@ -52,7 +52,7 @@ from app.routers import items * čŋ˜æœ‰ä¸€ä¸Ēå­į›ŽåŊ• `app/internal/` 包åĢåĻ一ä¸Ē `__init__.py` 文äģļīŧŒå› æ­¤åŽƒæ˜¯åˆä¸€ä¸Ē「Python 子包」īŧš`app.internal`。 * `app/internal/admin.py` 是åĻ一ä¸Ēå­æ¨Ąå—īŧš`app.internal.admin`。 - + å¸Ļæœ‰æŗ¨é‡Šįš„åŒä¸€æ–‡äģļį쓿ž„īŧš @@ -244,7 +244,7 @@ from .dependencies import get_token_header č¯ˇčŽ°äŊæˆ‘äģŦįš„į¨‹åē/文äģļį쓿ž„æ˜¯æ€Žæ ˇįš„īŧš - + --- diff --git a/docs/zh/docs/tutorial/first-steps.md b/docs/zh/docs/tutorial/first-steps.md index c4ff460e0..80a34116a 100644 --- a/docs/zh/docs/tutorial/first-steps.md +++ b/docs/zh/docs/tutorial/first-steps.md @@ -11,26 +11,42 @@

```console -$ uvicorn main:app --reload +$ fastapi dev main.py -INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) -INFO: Started reloader process [28720] -INFO: Started server process [28722] -INFO: Waiting for application startup. -INFO: Application startup complete. -``` + FastAPI Starting development server 🚀 -
+ Searching for package file structure from directories + with __init__.py files + Importing from /home/user/code/awesomeapp -/// note + module 🐍 main.py -`uvicorn main:app` å‘Ŋäģ¤åĢ义åς䏋: + code Importing the FastAPI app object from the module with + the following code: -* `main`īŧš`main.py` 文äģļīŧˆä¸€ä¸Ē Pythonã€Œæ¨Ąå—ã€īŧ‰ã€‚ -* `app`īŧšåœ¨ `main.py` 文äģļ中通čŋ‡ `app = FastAPI()` 创åģēįš„å¯ščąĄã€‚ -* `--reload`īŧščŽŠæœåŠĄå™¨åœ¨æ›´æ–°äģŖį åŽé‡æ–°å¯åŠ¨ã€‚äģ…在åŧ€å‘æ—ļäŊŋᔍč¯Ĩé€‰éĄšã€‚ + from main import app -/// + app Using import string: main:app + + server Server started at http://127.0.0.1:8000 + server Documentation at http://127.0.0.1:8000/docs + + tip Running in development mode, for production use: + fastapi run + + Logs: + + INFO Will watch for changes in these directories: + ['/home/user/code/awesomeapp'] + INFO Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C + to quit) + INFO Started reloader process [383138] using WatchFiles + INFO Started server process [383153] + INFO Waiting for application startup. + INFO Application startup complete. +``` + + åœ¨čž“å‡ē中īŧŒäŧšæœ‰ä¸€čĄŒäŋĄæ¯åƒä¸‹éĸčŋ™æ ˇīŧš @@ -38,7 +54,6 @@ $ uvicorn main:app --reload INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) ``` - č¯ĨčĄŒæ˜žį¤ēäē†äŊ įš„åē”į”¨åœ¨æœŦæœēæ‰€æäž›æœåŠĄįš„ URL 地址。 ### æŸĨįœ‹ @@ -63,7 +78,7 @@ INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) 前垀 http://127.0.0.1:8000/redoc。 -äŊ å°†äŧšįœ‹åˆ°å¯é€‰įš„č‡ĒåŠ¨į”Ÿæˆæ–‡æĄŖ īŧˆį”ą ReDoc 提䞛)īŧš +äŊ å°†äŧšįœ‹åˆ°å¯é€‰įš„č‡ĒåŠ¨į”Ÿæˆæ–‡æĄŖ īŧˆį”ą ReDoc 提䞛īŧ‰īŧš ![ReDoc](https://fastapi.tiangolo.com/img/index/index-02-redoc-simple.png) @@ -77,9 +92,9 @@ INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) #### APIã€Œæ¨Ąåŧã€ -在čŋ™į§åœē景下īŧŒOpenAPI æ˜¯ä¸€į§č§„åŽšåĻ‚äŊ•厚䚉 API æ¨Ąåŧįš„č§„čŒƒã€‚ +在čŋ™į§åœē景下īŧŒOpenAPI æ˜¯ä¸€į§č§„åŽšåĻ‚äŊ•厚䚉 API æ¨Ąåŧįš„č§„čŒƒã€‚ -åŽšäš‰įš„ OpenAPI æ¨Ąåŧå°†åŒ…æ‹ŦäŊ įš„ API čˇ¯åž„īŧŒäģĨ及厃äģŦ可čƒŊäŊŋį”¨įš„å‚æ•°į­‰į­‰ã€‚ +ã€Œæ¨Ąåŧã€įš„厚䚉包æ‹ŦäŊ įš„ API čˇ¯åž„īŧŒäģĨ及厃äģŦ可čƒŊäŊŋį”¨įš„å‚æ•°į­‰į­‰ã€‚ #### æ•°æŽã€Œæ¨Ąåŧã€ @@ -93,7 +108,7 @@ OpenAPI ä¸ēäŊ įš„ API 厚䚉 API æ¨Ąåŧã€‚č¯Ĩæ¨Ąåŧä¸­åŒ…åĢäē†äŊ įš„ API 发送 #### æŸĨįœ‹ `openapi.json` -åĻ‚æžœäŊ å¯šåŽŸå§‹įš„ OpenAPI æ¨Ąåŧé•ŋäģ€äšˆæ ˇå­æ„Ÿåˆ°åĨŊåĨ‡īŧŒå…ļ厞厃åĒ是一ä¸Ēč‡ĒåŠ¨į”Ÿæˆįš„åŒ…åĢä熿‰€æœ‰ API 描čŋ°įš„ JSON。 +åĻ‚æžœäŊ å¯šåŽŸå§‹įš„ OpenAPI æ¨Ąåŧé•ŋäģ€äšˆæ ˇå­æ„Ÿåˆ°åĨŊåĨ‡īŧŒFastAPI č‡ĒåŠ¨į”Ÿæˆäē†åŒ…åĢ所有 API 描čŋ°įš„ JSONīŧˆæ¨Ąåŧīŧ‰ã€‚ äŊ å¯äģĨį›´æŽĨ在īŧšhttp://127.0.0.1:8000/openapi.json įœ‹åˆ°åŽƒã€‚ @@ -101,7 +116,7 @@ OpenAPI ä¸ēäŊ įš„ API 厚䚉 API æ¨Ąåŧã€‚č¯Ĩæ¨Ąåŧä¸­åŒ…åĢäē†äŊ įš„ API 发送 ```JSON { - "openapi": "3.0.2", + "openapi": "3.1.0", "info": { "title": "FastAPI", "version": "0.1.0" @@ -140,7 +155,7 @@ OpenAPI ä¸ēäŊ įš„ API 厚䚉 API æ¨Ąåŧã€‚č¯Ĩæ¨Ąåŧä¸­åŒ…åĢäē†äŊ įš„ API 发送 `FastAPI` æ˜¯į›´æŽĨäģŽ `Starlette` įģ§æ‰ŋįš„įąģ。 -äŊ å¯äģĨ通čŋ‡ `FastAPI` äŊŋį”¨æ‰€æœ‰įš„ Starlette įš„åŠŸčƒŊ。 +äŊ å¯äģĨ通čŋ‡ `FastAPI` äŊŋį”¨æ‰€æœ‰įš„ Starlette įš„åŠŸčƒŊ。 /// @@ -152,34 +167,6 @@ OpenAPI ä¸ēäŊ įš„ API 厚䚉 API æ¨Ąåŧã€‚č¯Ĩæ¨Ąåŧä¸­åŒ…åĢäē†äŊ įš„ API 发送 čŋ™ä¸Ē厞䞋将是创åģēäŊ æ‰€æœ‰ API įš„ä¸ģčρäē¤äē’å¯ščąĄã€‚ -čŋ™ä¸Ē `app` åŒæ ˇåœ¨åς䏋å‘Ŋäģ¤ä¸­čĸĢ `uvicorn` 所åŧ•ᔍīŧš - -
- -```console -$ uvicorn main:app --reload - -INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) -``` - -
- -åĻ‚æžœäŊ åƒä¸‹éĸčŋ™æ ˇåˆ›åģēåē”ᔍīŧš - -{* ../../docs_src/first_steps/tutorial002.py hl[3] *} - -将äģŖį æ”žå…Ĩ `main.py` 文äģļ中īŧŒį„ļ后äŊ å¯äģĨ像下éĸčŋ™æ ˇčŋčĄŒ `uvicorn`īŧš - -
- -```console -$ uvicorn main:my_awesome_api --reload - -INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) -``` - -
- ### æ­ĨéǤ 3īŧšåˆ›åģē一ä¸Ē*čˇ¯åž„æ“äŊœ* #### čˇ¯åž„ @@ -279,13 +266,13 @@ https://example.com/items/foo /// tip -您可äģĨ随意äŊŋᔍäģģäŊ•一ä¸Ē操äŊœīŧˆHTTPæ–šæŗ•īŧ‰ã€‚ +äŊ å¯äģĨ随意äŊŋᔍäģģäŊ•一ä¸Ē操äŊœīŧˆHTTPæ–šæŗ•īŧ‰ã€‚ **FastAPI** æ˛Ąæœ‰åŧēåˆļčĻæą‚æ“äŊœæœ‰äģģäŊ•į‰šåŽšįš„åĢ䚉。 æ­¤å¤„æäž›įš„äŋĄæ¯äģ…äŊœä¸ē指å¯ŧīŧŒč€Œä¸æ˜¯čĻæą‚ã€‚ -比åĻ‚īŧŒåŊ“äŊŋᔍ GraphQL æ—ļ通常äŊ æ‰€æœ‰įš„动äŊœéƒŊ通čŋ‡ `post` ä¸€į§æ–šæŗ•æ‰§čĄŒã€‚ +比åĻ‚īŧŒåŊ“äŊŋᔍ GraphQL æ—ļ通常äŊ æ‰€æœ‰įš„动äŊœéƒŊ通čŋ‡ `POST` ä¸€į§æ–šæŗ•æ‰§čĄŒã€‚ /// @@ -331,6 +318,6 @@ https://example.com/items/foo * å¯ŧå…Ĩ `FastAPI`。 * 创åģē一ä¸Ē `app` 厞䞋。 -* įŧ–写一ä¸Ē**čˇ¯åž„æ“äŊœčŖ…éĨ°å™¨**īŧˆåĻ‚ `@app.get("/")`īŧ‰ã€‚ -* įŧ–写一ä¸Ē**čˇ¯åž„æ“äŊœå‡Ŋ数**īŧˆåĻ‚ä¸Šéĸįš„ `def root(): ...`īŧ‰ã€‚ -* čŋčĄŒåŧ€å‘æœåŠĄå™¨īŧˆåĻ‚ `uvicorn main:app --reload`īŧ‰ã€‚ +* įŧ–写一ä¸Ē**čˇ¯åž„æ“äŊœčŖ…éĨ°å™¨**īŧŒåĻ‚ `@app.get("/")`。 +* 厚䚉一ä¸Ē**čˇ¯åž„æ“äŊœå‡Ŋ数**īŧŒåĻ‚ `def root(): ...`。 +* äŊŋᔍå‘Ŋäģ¤ `fastapi dev` čŋčĄŒåŧ€å‘æœåŠĄå™¨ã€‚ diff --git a/docs/zh/docs/tutorial/index.md b/docs/zh/docs/tutorial/index.md index ab19f02c5..3ca927337 100644 --- a/docs/zh/docs/tutorial/index.md +++ b/docs/zh/docs/tutorial/index.md @@ -1,34 +1,58 @@ # æ•™į¨‹ - į”¨æˆˇæŒ‡å— -æœŦæ•™į¨‹å°†ä¸€æ­Ĩæ­Ĩ向äŊ åą•į¤ēåĻ‚äŊ•äŊŋᔍ **FastAPI** įš„įģå¤§éƒ¨åˆ†į‰šæ€§ã€‚ +æœŦæ•™į¨‹å°†ä¸€æ­Ĩæ­Ĩå‘æ‚¨åą•į¤ēåĻ‚äŊ•äŊŋᔍ **FastAPI** įš„įģå¤§éƒ¨åˆ†į‰šæ€§ã€‚ -各ä¸ĒįĢ čŠ‚įš„å†…åŽšåžĒåēæ¸čŋ›īŧŒäŊ†æ˜¯åˆå›´įģ•į€å•į‹Ŧįš„ä¸ģéĸ˜īŧŒæ‰€äģĨäŊ å¯äģĨį›´æŽĨ莺čŊŦ到某ä¸ĒįĢ čŠ‚äģĨ觪冺äŊ įš„į‰šåŽšéœ€æą‚ã€‚ +各ä¸ĒįĢ čŠ‚įš„å†…åŽšåžĒåēæ¸čŋ›īŧŒäŊ†æ˜¯åˆå›´įģ•į€å•į‹Ŧįš„ä¸ģéĸ˜īŧŒæ‰€äģĨ您可äģĨį›´æŽĨ莺čŊŦ到某ä¸ĒįĢ čŠ‚äģĨč§Ŗå†ŗæ‚¨įš„į‰šåŽšéœ€æą‚ã€‚ -æœŦæ•™į¨‹åŒæ ˇå¯äģĨäŊœä¸ē将æĨįš„å‚č€ƒæ‰‹å†Œã€‚ - -äŊ å¯äģĨ随æ—ļ回到æœŦæ•™į¨‹åšļæŸĨ阅äŊ éœ€čĻįš„å†…åŽšã€‚ +æœŦæ•™į¨‹åŒæ ˇå¯äģĨäŊœä¸ē将æĨįš„å‚č€ƒæ‰‹å†ŒīŧŒæ‰€äģĨ您可äģĨ随æ—ļ回到æœŦæ•™į¨‹åšļæŸĨ阅您需čĻįš„å†…åŽšã€‚ ## čŋčĄŒäģŖį  所有äģŖį į‰‡æŽĩéƒŊ可äģĨ复åˆļåŽį›´æŽĨäŊŋᔍīŧˆåރäģŦ厞际上是įģčŋ‡æĩ‹č¯•įš„ Python 文äģļīŧ‰ã€‚ -čρčŋčĄŒäģģäŊ•į¤ē例īŧŒč¯ˇå°†äģŖį å¤åˆļ到 `main.py` 文äģļ中īŧŒį„ļ后äŊŋᔍäģĨ下å‘Ŋäģ¤å¯åЍ `uvicorn`īŧš +čρčŋčĄŒäģģäŊ•į¤ē例īŧŒč¯ˇå°†äģŖį å¤åˆļ到 `main.py` 文äģļ中īŧŒį„ļ后äŊŋᔍäģĨ下å‘Ŋäģ¤å¯åЍ `fastapi dev`īŧš
```console -$ uvicorn main:app --reload +$ fastapi dev main.py + + FastAPI Starting development server 🚀 + + Searching for package file structure from directories + with __init__.py files + Importing from /home/user/code/awesomeapp + + module 🐍 main.py + + code Importing the FastAPI app object from the module with + the following code: + + from main import app + + app Using import string: main:app + + server Server started at http://127.0.0.1:8000 + server Documentation at http://127.0.0.1:8000/docs + + tip Running in development mode, for production use: + fastapi run + + Logs: -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. + INFO Will watch for changes in these directories: + ['/home/user/code/awesomeapp'] + INFO Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C + to quit) + INFO Started reloader process [383138] using WatchFiles + INFO Started server process [383153] + INFO Waiting for application startup. + INFO Application startup complete. ```
-åŧē჈åģē莎äŊ åœ¨æœŦ地įŧ–写或复åˆļäģŖį īŧŒå¯šå…ļčŋ›čĄŒįŧ–čž‘åšļčŋčĄŒã€‚ +**åŧē჈åģē莎**您在æœŦ地įŧ–写或复åˆļäģŖį īŧŒå¯šå…ļčŋ›čĄŒįŧ–čž‘åšļčŋčĄŒã€‚ 在įŧ–čž‘å™¨ä¸­äŊŋᔍ FastAPI äŧšįœŸæ­Ŗåœ°åą•įŽ°å‡ēåŽƒįš„äŧ˜åŠŋīŧšåĒ需čρįŧ–å†™åžˆå°‘įš„äģŖį īŧŒæ‰€æœ‰įš„įąģåž‹æŖ€æŸĨīŧŒäģŖį čĄĨå…¨į­‰į­‰ã€‚ @@ -36,48 +60,34 @@ $ uvicorn main:app --reload ## åŽ‰čŖ… FastAPI -įŦŦ一ä¸Ēæ­ĨéĒ¤æ˜¯åŽ‰čŖ… FastAPI。 +įŦŦ一ä¸Ēæ­ĨéĒ¤æ˜¯åŽ‰čŖ… FastAPI. -ä¸ēäē†äŊŋᔍæœŦæ•™į¨‹īŧŒäŊ å¯čƒŊ需čĻåŽ‰čŖ…æ‰€æœ‰įš„å¯é€‰äžčĩ–及寚åē”功čƒŊīŧš +č¯ˇįĄŽäŋæ‚¨åˆ›åģēåšļæŋ€æ´ģ一ä¸Ē[č™šæ‹ŸįŽ¯åĸƒ](../virtual-environments.md){.internal-link target=_blank}īŧŒį„ļ后**åŽ‰čŖ… FastAPI**īŧš
```console -$ pip install "fastapi[all]" +$ pip install "fastapi[standard]" ---> 100% ```
-......äģĨä¸ŠåŽ‰čŖ…čŋ˜åŒ…æ‹Ŧäē† `uvicorn`īŧŒäŊ å¯äģĨ将å…ļᔍäŊœčŋčĄŒäģŖį įš„æœåŠĄå™¨ã€‚ - /// note -äŊ äšŸå¯äģĨ分åŧ€æĨåŽ‰čŖ…ã€‚ - -假åĻ‚äŊ æƒŗå°†åē”ᔍፋåēéƒ¨įŊ˛åˆ°į”Ÿäē§įޝåĸƒīŧŒäŊ å¯čƒŊčĻæ‰§čĄŒäģĨ下操äŊœīŧš - -``` -pip install fastapi -``` - -åšļä¸”åŽ‰čŖ…`uvicorn`æĨäŊœä¸ēæœåŠĄå™¨īŧš - -``` -pip install "uvicorn[standard]" -``` +åŊ“您äŊŋᔍ `pip install "fastapi[standard]"` čŋ›čĄŒåމ誅æ—ļīŧŒåރäŧšé™„å¸Ļ一äē›éģ˜čŽ¤įš„å¯é€‰æ ‡å‡†äžčĩ–éĄšã€‚ -į„ļ后寚äŊ æƒŗäŊŋį”¨įš„æ¯ä¸Ē可选䞝čĩ–éĄšäšŸæ‰§čĄŒį›¸åŒįš„æ“äŊœã€‚ +åĻ‚æžœæ‚¨ä¸æƒŗåŽ‰čŖ…čŋ™äē›å¯é€‰äžčĩ–īŧŒå¯äģĨé€‰æ‹ŠåŽ‰čŖ… `pip install fastapi`。 /// ## čŋ›é˜ļį”¨æˆˇæŒ‡å— -在æœŦ**æ•™į¨‹-į”¨æˆˇæŒ‡å—**䚋后īŧŒäŊ å¯äģĨ阅č¯ģ**čŋ›é˜ļį”¨æˆˇæŒ‡å—**。 +在æœŦ**æ•™į¨‹-į”¨æˆˇæŒ‡å—**䚋后īŧŒæ‚¨å¯äģĨ阅č¯ģ**čŋ›é˜ļį”¨æˆˇæŒ‡å—**。 **čŋ›é˜ļį”¨æˆˇæŒ‡å—**äģĨæœŦæ•™į¨‹ä¸ēåŸēįĄ€īŧŒäŊŋį”¨į›¸åŒįš„æĻ‚åŋĩīŧŒåšļ教授一äē›éĸå¤–įš„į‰šæ€§ã€‚ -äŊ†æ˜¯äŊ åē”č¯Ĩ先阅č¯ģ**æ•™į¨‹-į”¨æˆˇæŒ‡å—**īŧˆåŗäŊ įŽ°åœ¨æ­Ŗåœ¨é˜…č¯ģįš„å†…åŽšīŧ‰ã€‚ +äŊ†æ˜¯æ‚¨åē”č¯Ĩ先阅č¯ģ**æ•™į¨‹-į”¨æˆˇæŒ‡å—**īŧˆåŗæ‚¨įŽ°åœ¨æ­Ŗåœ¨é˜…č¯ģįš„å†…åŽšīŧ‰ã€‚ -æ•™į¨‹įģčŋ‡į˛žåŋƒčŽžčŽĄīŧŒäŊŋäŊ å¯äģĨäģ…通čŋ‡**æ•™į¨‹-į”¨æˆˇæŒ‡å—**æĨåŧ€å‘一ä¸ĒåŽŒæ•´įš„åē”ᔍፋåēīŧŒį„ļ后栚捎äŊ įš„需čρīŧŒäŊŋᔍ**čŋ›é˜ļį”¨æˆˇæŒ‡å—**ä¸­įš„ä¸€äē›å…ļä얿ςåŋĩīŧŒäģĨä¸åŒįš„æ–šåŧæĨæ‰Šåą•åŽƒã€‚ +æ•™į¨‹įģčŋ‡į˛žåŋƒčŽžčŽĄīŧŒäŊŋ您可äģĨäģ…通čŋ‡**æ•™į¨‹-į”¨æˆˇæŒ‡å—**æĨåŧ€å‘一ä¸ĒåŽŒæ•´įš„åē”ᔍፋåēīŧŒį„ļåŽæ šæŽæ‚¨įš„éœ€čρīŧŒäŊŋᔍ**čŋ›é˜ļį”¨æˆˇæŒ‡å—**ä¸­įš„ä¸€äē›å…ļä얿ςåŋĩīŧŒäģĨä¸åŒįš„æ–šåŧæĨæ‰Šåą•åŽƒã€‚ diff --git a/docs/zh/docs/tutorial/query-params-str-validations.md b/docs/zh/docs/tutorial/query-params-str-validations.md index 2fba671f7..c2f9a7e9f 100644 --- a/docs/zh/docs/tutorial/query-params-str-validations.md +++ b/docs/zh/docs/tutorial/query-params-str-validations.md @@ -108,21 +108,6 @@ q: Union[str, None] = Query(default=None, min_length=3) {* ../../docs_src/query_params_str_validations/tutorial006.py hl[7] *} -### äŊŋį”¨įœį•Ĩåˇ(`...`)åŖ°æ˜Žåŋ…需参数 - -有åĻä¸€į§æ–šæŗ•å¯äģĨ昞åŧįš„åŖ°æ˜Žä¸€ä¸Ēå€ŧ是åŋ…éœ€įš„īŧŒåŗå°†éģ˜čŽ¤å‚æ•°įš„éģ˜čޤå€ŧ莞ä¸ē `...` īŧš - -{* ../../docs_src/query_params_str_validations/tutorial006b.py hl[7] *} - -/// info - -åĻ‚æžœäŊ äš‹å‰æ˛Ąč§čŋ‡ `...` čŋ™į§į”¨æŗ•īŧšåŽƒæ˜¯ä¸€ä¸Ēį‰šæŽŠįš„å•į‹Ŧå€ŧīŧŒåŽƒæ˜¯ Python įš„ä¸€éƒ¨åˆ†åšļ且čĸĢį§°ä¸ē“Ellipsis”īŧˆæ„ä¸ēᜁį•Ĩåˇ —— č¯‘č€…æŗ¨īŧ‰ã€‚ -Pydantic 和 FastAPI äŊŋį”¨åŽƒæĨ昞åŧįš„åŖ°æ˜Žéœ€čρ䏀ä¸Ēå€ŧ。 - -/// - -čŋ™å°†äŊŋ **FastAPI** įŸĨ道此æŸĨč¯ĸ参数是åŋ…éœ€įš„ã€‚ - ### äŊŋᔍ`None`åŖ°æ˜Žåŋ…需参数 äŊ å¯äģĨåŖ°æ˜Žä¸€ä¸Ē参数可äģĨæŽĨæ”ļ`None`å€ŧīŧŒäŊ†åރäģį„ļ是åŋ…éœ€įš„ã€‚čŋ™å°†åŧēåˆļåŽĸæˆˇįĢ¯å‘é€ä¸€ä¸Ēå€ŧīŧŒåŗäŊŋč¯Ĩå€ŧ是`None`。 @@ -137,18 +122,6 @@ Pydantic 是 FastAPI 中所有数捎éĒŒč¯å’Œåēåˆ—åŒ–įš„æ ¸åŋƒīŧŒåŊ“äŊ åœ¨æ˛Ą /// -### äŊŋᔍPydanticä¸­įš„`Required`äģŖæ›ŋᜁį•Ĩåˇ(`...`) - -åĻ‚æžœäŊ č§‰åž—äŊŋᔍ `...` ä¸čˆ’æœīŧŒäŊ äšŸå¯äģĨäģŽ Pydantic å¯ŧå…ĨåšļäŊŋᔍ `Required`īŧš - -{* ../../docs_src/query_params_str_validations/tutorial006d.py hl[2,8] *} - -/// tip - -č¯ˇčŽ°äŊīŧŒåœ¨å¤§å¤šæ•°æƒ…å†ĩ下īŧŒåŊ“äŊ éœ€čĻæŸäē›ä¸œčĨŋæ—ļīŧŒå¯äģĨįŽ€å•åœ°įœį•Ĩ `default` 参数īŧŒå› æ­¤äŊ é€šå¸¸ä¸åŋ…äŊŋᔍ `...` 或 `Required` - -/// - ## æŸĨč¯ĸå‚æ•°åˆ—čĄ¨ / 多ä¸Ēå€ŧ åŊ“äŊ äŊŋᔍ `Query` 昞åŧåœ°åŽšäš‰æŸĨč¯ĸ参数æ—ļīŧŒäŊ čŋ˜å¯äģĨåŖ°æ˜ŽåŽƒåŽģæŽĨæ”ļ一įģ„å€ŧīŧŒæˆ–æĸåĨč¯æĨ蝴īŧŒæŽĨæ”ļ多ä¸Ēå€ŧ。 diff --git a/docs_src/body/tutorial002.py b/docs_src/body/tutorial002.py index 7f5183908..5cd86216b 100644 --- a/docs_src/body/tutorial002.py +++ b/docs_src/body/tutorial002.py @@ -17,7 +17,7 @@ app = FastAPI() @app.post("/items/") async def create_item(item: Item): item_dict = item.dict() - if item.tax: + if item.tax is not None: price_with_tax = item.price + item.tax item_dict.update({"price_with_tax": price_with_tax}) return item_dict diff --git a/docs_src/body/tutorial002_py310.py b/docs_src/body/tutorial002_py310.py index 8928b72b8..454c45c88 100644 --- a/docs_src/body/tutorial002_py310.py +++ b/docs_src/body/tutorial002_py310.py @@ -15,7 +15,7 @@ app = FastAPI() @app.post("/items/") async def create_item(item: Item): item_dict = item.dict() - if item.tax: + if item.tax is not None: price_with_tax = item.price + item.tax item_dict.update({"price_with_tax": price_with_tax}) return item_dict diff --git a/docs_src/configure_swagger_ui/tutorial002.py b/docs_src/configure_swagger_ui/tutorial002.py index cc569ce45..cc75c2196 100644 --- a/docs_src/configure_swagger_ui/tutorial002.py +++ b/docs_src/configure_swagger_ui/tutorial002.py @@ -1,6 +1,6 @@ from fastapi import FastAPI -app = FastAPI(swagger_ui_parameters={"syntaxHighlight.theme": "obsidian"}) +app = FastAPI(swagger_ui_parameters={"syntaxHighlight": {"theme": "obsidian"}}) @app.get("/users/{username}") diff --git a/docs_src/custom_docs_ui/tutorial001.py b/docs_src/custom_docs_ui/tutorial001.py index f7ceb0c2f..1cfcce19a 100644 --- a/docs_src/custom_docs_ui/tutorial001.py +++ b/docs_src/custom_docs_ui/tutorial001.py @@ -29,7 +29,7 @@ async def redoc_html(): return get_redoc_html( openapi_url=app.openapi_url, title=app.title + " - ReDoc", - redoc_js_url="https://unpkg.com/redoc@next/bundles/redoc.standalone.js", + redoc_js_url="https://unpkg.com/redoc@2/bundles/redoc.standalone.js", ) diff --git a/docs_src/header_param_models/tutorial003.py b/docs_src/header_param_models/tutorial003.py new file mode 100644 index 000000000..dc2eb74bd --- /dev/null +++ b/docs_src/header_param_models/tutorial003.py @@ -0,0 +1,19 @@ +from typing import List, Union + +from fastapi import FastAPI, Header +from pydantic import BaseModel + +app = FastAPI() + + +class CommonHeaders(BaseModel): + host: str + save_data: bool + if_modified_since: Union[str, None] = None + traceparent: Union[str, None] = None + x_tag: List[str] = [] + + +@app.get("/items/") +async def read_items(headers: CommonHeaders = Header(convert_underscores=False)): + return headers diff --git a/docs_src/header_param_models/tutorial003_an.py b/docs_src/header_param_models/tutorial003_an.py new file mode 100644 index 000000000..e3edb1189 --- /dev/null +++ b/docs_src/header_param_models/tutorial003_an.py @@ -0,0 +1,22 @@ +from typing import List, Union + +from fastapi import FastAPI, Header +from pydantic import BaseModel +from typing_extensions import Annotated + +app = FastAPI() + + +class CommonHeaders(BaseModel): + host: str + save_data: bool + if_modified_since: Union[str, None] = None + traceparent: Union[str, None] = None + x_tag: List[str] = [] + + +@app.get("/items/") +async def read_items( + headers: Annotated[CommonHeaders, Header(convert_underscores=False)], +): + return headers diff --git a/docs_src/header_param_models/tutorial003_an_py310.py b/docs_src/header_param_models/tutorial003_an_py310.py new file mode 100644 index 000000000..07bfa83bf --- /dev/null +++ b/docs_src/header_param_models/tutorial003_an_py310.py @@ -0,0 +1,21 @@ +from typing import Annotated + +from fastapi import FastAPI, Header +from pydantic import BaseModel + +app = FastAPI() + + +class CommonHeaders(BaseModel): + host: str + save_data: bool + if_modified_since: str | None = None + traceparent: str | None = None + x_tag: list[str] = [] + + +@app.get("/items/") +async def read_items( + headers: Annotated[CommonHeaders, Header(convert_underscores=False)], +): + return headers diff --git a/docs_src/header_param_models/tutorial003_an_py39.py b/docs_src/header_param_models/tutorial003_an_py39.py new file mode 100644 index 000000000..8be6b01d0 --- /dev/null +++ b/docs_src/header_param_models/tutorial003_an_py39.py @@ -0,0 +1,21 @@ +from typing import Annotated, Union + +from fastapi import FastAPI, Header +from pydantic import BaseModel + +app = FastAPI() + + +class CommonHeaders(BaseModel): + host: str + save_data: bool + if_modified_since: Union[str, None] = None + traceparent: Union[str, None] = None + x_tag: list[str] = [] + + +@app.get("/items/") +async def read_items( + headers: Annotated[CommonHeaders, Header(convert_underscores=False)], +): + return headers diff --git a/docs_src/header_param_models/tutorial003_py310.py b/docs_src/header_param_models/tutorial003_py310.py new file mode 100644 index 000000000..65e92a28c --- /dev/null +++ b/docs_src/header_param_models/tutorial003_py310.py @@ -0,0 +1,17 @@ +from fastapi import FastAPI, Header +from pydantic import BaseModel + +app = FastAPI() + + +class CommonHeaders(BaseModel): + host: str + save_data: bool + if_modified_since: str | None = None + traceparent: str | None = None + x_tag: list[str] = [] + + +@app.get("/items/") +async def read_items(headers: CommonHeaders = Header(convert_underscores=False)): + return headers diff --git a/docs_src/header_param_models/tutorial003_py39.py b/docs_src/header_param_models/tutorial003_py39.py new file mode 100644 index 000000000..848c34111 --- /dev/null +++ b/docs_src/header_param_models/tutorial003_py39.py @@ -0,0 +1,19 @@ +from typing import Union + +from fastapi import FastAPI, Header +from pydantic import BaseModel + +app = FastAPI() + + +class CommonHeaders(BaseModel): + host: str + save_data: bool + if_modified_since: Union[str, None] = None + traceparent: Union[str, None] = None + x_tag: list[str] = [] + + +@app.get("/items/") +async def read_items(headers: CommonHeaders = Header(convert_underscores=False)): + return headers diff --git a/docs_src/query_params_str_validations/tutorial006b.py b/docs_src/query_params_str_validations/tutorial006b.py deleted file mode 100644 index a8d69c889..000000000 --- a/docs_src/query_params_str_validations/tutorial006b.py +++ /dev/null @@ -1,11 +0,0 @@ -from fastapi import FastAPI, Query - -app = FastAPI() - - -@app.get("/items/") -async def read_items(q: str = Query(default=..., min_length=3)): - results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]} - if q: - results.update({"q": q}) - return results diff --git a/docs_src/query_params_str_validations/tutorial006b_an.py b/docs_src/query_params_str_validations/tutorial006b_an.py deleted file mode 100644 index ea3b02583..000000000 --- a/docs_src/query_params_str_validations/tutorial006b_an.py +++ /dev/null @@ -1,12 +0,0 @@ -from fastapi import FastAPI, Query -from typing_extensions import Annotated - -app = FastAPI() - - -@app.get("/items/") -async def read_items(q: Annotated[str, Query(min_length=3)] = ...): - results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]} - if q: - results.update({"q": q}) - return results diff --git a/docs_src/query_params_str_validations/tutorial006b_an_py39.py b/docs_src/query_params_str_validations/tutorial006b_an_py39.py deleted file mode 100644 index 687a9f544..000000000 --- a/docs_src/query_params_str_validations/tutorial006b_an_py39.py +++ /dev/null @@ -1,13 +0,0 @@ -from typing import Annotated - -from fastapi import FastAPI, Query - -app = FastAPI() - - -@app.get("/items/") -async def read_items(q: Annotated[str, Query(min_length=3)] = ...): - results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]} - if q: - results.update({"q": q}) - return results diff --git a/docs_src/query_params_str_validations/tutorial006c.py b/docs_src/query_params_str_validations/tutorial006c.py index 2ac148c94..0a0e820da 100644 --- a/docs_src/query_params_str_validations/tutorial006c.py +++ b/docs_src/query_params_str_validations/tutorial006c.py @@ -6,7 +6,7 @@ app = FastAPI() @app.get("/items/") -async def read_items(q: Union[str, None] = Query(default=..., min_length=3)): +async def read_items(q: Union[str, None] = Query(min_length=3)): results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]} if q: results.update({"q": q}) diff --git a/docs_src/query_params_str_validations/tutorial006c_an.py b/docs_src/query_params_str_validations/tutorial006c_an.py index 10bf26a57..55c4f4adc 100644 --- a/docs_src/query_params_str_validations/tutorial006c_an.py +++ b/docs_src/query_params_str_validations/tutorial006c_an.py @@ -7,7 +7,7 @@ app = FastAPI() @app.get("/items/") -async def read_items(q: Annotated[Union[str, None], Query(min_length=3)] = ...): +async def read_items(q: Annotated[Union[str, None], Query(min_length=3)]): results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]} if q: results.update({"q": q}) diff --git a/docs_src/query_params_str_validations/tutorial006c_an_py310.py b/docs_src/query_params_str_validations/tutorial006c_an_py310.py index 1ab0a7d53..2995d9c97 100644 --- a/docs_src/query_params_str_validations/tutorial006c_an_py310.py +++ b/docs_src/query_params_str_validations/tutorial006c_an_py310.py @@ -6,7 +6,7 @@ app = FastAPI() @app.get("/items/") -async def read_items(q: Annotated[str | None, Query(min_length=3)] = ...): +async def read_items(q: Annotated[str | None, Query(min_length=3)]): results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]} if q: results.update({"q": q}) diff --git a/docs_src/query_params_str_validations/tutorial006c_an_py39.py b/docs_src/query_params_str_validations/tutorial006c_an_py39.py index ac1273331..76a1cd49a 100644 --- a/docs_src/query_params_str_validations/tutorial006c_an_py39.py +++ b/docs_src/query_params_str_validations/tutorial006c_an_py39.py @@ -6,7 +6,7 @@ app = FastAPI() @app.get("/items/") -async def read_items(q: Annotated[Union[str, None], Query(min_length=3)] = ...): +async def read_items(q: Annotated[Union[str, None], Query(min_length=3)]): results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]} if q: results.update({"q": q}) diff --git a/docs_src/query_params_str_validations/tutorial006c_py310.py b/docs_src/query_params_str_validations/tutorial006c_py310.py index 82dd9e5d7..88b499c7a 100644 --- a/docs_src/query_params_str_validations/tutorial006c_py310.py +++ b/docs_src/query_params_str_validations/tutorial006c_py310.py @@ -4,7 +4,7 @@ app = FastAPI() @app.get("/items/") -async def read_items(q: str | None = Query(default=..., min_length=3)): +async def read_items(q: str | None = Query(min_length=3)): results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]} if q: results.update({"q": q}) diff --git a/docs_src/query_params_str_validations/tutorial006d.py b/docs_src/query_params_str_validations/tutorial006d.py deleted file mode 100644 index a8d69c889..000000000 --- a/docs_src/query_params_str_validations/tutorial006d.py +++ /dev/null @@ -1,11 +0,0 @@ -from fastapi import FastAPI, Query - -app = FastAPI() - - -@app.get("/items/") -async def read_items(q: str = Query(default=..., min_length=3)): - results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]} - if q: - results.update({"q": q}) - return results diff --git a/docs_src/query_params_str_validations/tutorial006d_an.py b/docs_src/query_params_str_validations/tutorial006d_an.py deleted file mode 100644 index ea3b02583..000000000 --- a/docs_src/query_params_str_validations/tutorial006d_an.py +++ /dev/null @@ -1,12 +0,0 @@ -from fastapi import FastAPI, Query -from typing_extensions import Annotated - -app = FastAPI() - - -@app.get("/items/") -async def read_items(q: Annotated[str, Query(min_length=3)] = ...): - results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]} - if q: - results.update({"q": q}) - return results diff --git a/docs_src/query_params_str_validations/tutorial006d_an_py39.py b/docs_src/query_params_str_validations/tutorial006d_an_py39.py deleted file mode 100644 index 687a9f544..000000000 --- a/docs_src/query_params_str_validations/tutorial006d_an_py39.py +++ /dev/null @@ -1,13 +0,0 @@ -from typing import Annotated - -from fastapi import FastAPI, Query - -app = FastAPI() - - -@app.get("/items/") -async def read_items(q: Annotated[str, Query(min_length=3)] = ...): - results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]} - if q: - results.update({"q": q}) - return results diff --git a/docs_src/query_params_str_validations/tutorial015_an.py b/docs_src/query_params_str_validations/tutorial015_an.py new file mode 100644 index 000000000..f2ec6db12 --- /dev/null +++ b/docs_src/query_params_str_validations/tutorial015_an.py @@ -0,0 +1,31 @@ +import random +from typing import Union + +from fastapi import FastAPI +from pydantic import AfterValidator +from typing_extensions import Annotated + +app = FastAPI() + +data = { + "isbn-9781529046137": "The Hitchhiker's Guide to the Galaxy", + "imdb-tt0371724": "The Hitchhiker's Guide to the Galaxy", + "isbn-9781439512982": "Isaac Asimov: The Complete Stories, Vol. 2", +} + + +def check_valid_id(id: str): + if not id.startswith(("isbn-", "imdb-")): + raise ValueError('Invalid ID format, it must start with "isbn-" or "imdb-"') + return id + + +@app.get("/items/") +async def read_items( + id: Annotated[Union[str, None], AfterValidator(check_valid_id)] = None, +): + if id: + item = data.get(id) + else: + id, item = random.choice(list(data.items())) + return {"id": id, "name": item} diff --git a/docs_src/query_params_str_validations/tutorial015_an_py310.py b/docs_src/query_params_str_validations/tutorial015_an_py310.py new file mode 100644 index 000000000..35f368094 --- /dev/null +++ b/docs_src/query_params_str_validations/tutorial015_an_py310.py @@ -0,0 +1,30 @@ +import random +from typing import Annotated + +from fastapi import FastAPI +from pydantic import AfterValidator + +app = FastAPI() + +data = { + "isbn-9781529046137": "The Hitchhiker's Guide to the Galaxy", + "imdb-tt0371724": "The Hitchhiker's Guide to the Galaxy", + "isbn-9781439512982": "Isaac Asimov: The Complete Stories, Vol. 2", +} + + +def check_valid_id(id: str): + if not id.startswith(("isbn-", "imdb-")): + raise ValueError('Invalid ID format, it must start with "isbn-" or "imdb-"') + return id + + +@app.get("/items/") +async def read_items( + id: Annotated[str | None, AfterValidator(check_valid_id)] = None, +): + if id: + item = data.get(id) + else: + id, item = random.choice(list(data.items())) + return {"id": id, "name": item} diff --git a/docs_src/query_params_str_validations/tutorial015_an_py39.py b/docs_src/query_params_str_validations/tutorial015_an_py39.py new file mode 100644 index 000000000..989b6d2c2 --- /dev/null +++ b/docs_src/query_params_str_validations/tutorial015_an_py39.py @@ -0,0 +1,30 @@ +import random +from typing import Annotated, Union + +from fastapi import FastAPI +from pydantic import AfterValidator + +app = FastAPI() + +data = { + "isbn-9781529046137": "The Hitchhiker's Guide to the Galaxy", + "imdb-tt0371724": "The Hitchhiker's Guide to the Galaxy", + "isbn-9781439512982": "Isaac Asimov: The Complete Stories, Vol. 2", +} + + +def check_valid_id(id: str): + if not id.startswith(("isbn-", "imdb-")): + raise ValueError('Invalid ID format, it must start with "isbn-" or "imdb-"') + return id + + +@app.get("/items/") +async def read_items( + id: Annotated[Union[str, None], AfterValidator(check_valid_id)] = None, +): + if id: + item = data.get(id) + else: + id, item = random.choice(list(data.items())) + return {"id": id, "name": item} diff --git a/docs_src/security/tutorial004.py b/docs_src/security/tutorial004.py index 91d161b8a..222589618 100644 --- a/docs_src/security/tutorial004.py +++ b/docs_src/security/tutorial004.py @@ -95,7 +95,7 @@ async def get_current_user(token: str = Depends(oauth2_scheme)): ) try: payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM]) - username: str = payload.get("sub") + username = payload.get("sub") if username is None: raise credentials_exception token_data = TokenData(username=username) diff --git a/docs_src/security/tutorial004_an.py b/docs_src/security/tutorial004_an.py index df50754af..e2221cd39 100644 --- a/docs_src/security/tutorial004_an.py +++ b/docs_src/security/tutorial004_an.py @@ -96,7 +96,7 @@ async def get_current_user(token: Annotated[str, Depends(oauth2_scheme)]): ) try: payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM]) - username: str = payload.get("sub") + username = payload.get("sub") if username is None: raise credentials_exception token_data = TokenData(username=username) diff --git a/docs_src/security/tutorial004_an_py310.py b/docs_src/security/tutorial004_an_py310.py index eff54ef01..a3f74fc0e 100644 --- a/docs_src/security/tutorial004_an_py310.py +++ b/docs_src/security/tutorial004_an_py310.py @@ -95,7 +95,7 @@ async def get_current_user(token: Annotated[str, Depends(oauth2_scheme)]): ) try: payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM]) - username: str = payload.get("sub") + username = payload.get("sub") if username is None: raise credentials_exception token_data = TokenData(username=username) diff --git a/docs_src/security/tutorial004_an_py39.py b/docs_src/security/tutorial004_an_py39.py index 0455b500c..b33d677ed 100644 --- a/docs_src/security/tutorial004_an_py39.py +++ b/docs_src/security/tutorial004_an_py39.py @@ -95,7 +95,7 @@ async def get_current_user(token: Annotated[str, Depends(oauth2_scheme)]): ) try: payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM]) - username: str = payload.get("sub") + username = payload.get("sub") if username is None: raise credentials_exception token_data = TokenData(username=username) diff --git a/docs_src/security/tutorial004_py310.py b/docs_src/security/tutorial004_py310.py index 78bee22a3..d46ce26bf 100644 --- a/docs_src/security/tutorial004_py310.py +++ b/docs_src/security/tutorial004_py310.py @@ -94,7 +94,7 @@ async def get_current_user(token: str = Depends(oauth2_scheme)): ) try: payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM]) - username: str = payload.get("sub") + username = payload.get("sub") if username is None: raise credentials_exception token_data = TokenData(username=username) diff --git a/docs_src/security/tutorial005_an.py b/docs_src/security/tutorial005_an.py index 5b67cb145..2e8bb3bdb 100644 --- a/docs_src/security/tutorial005_an.py +++ b/docs_src/security/tutorial005_an.py @@ -117,7 +117,7 @@ async def get_current_user( ) try: payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM]) - username: str = payload.get("sub") + username = payload.get("sub") if username is None: raise credentials_exception token_scopes = payload.get("scopes", []) diff --git a/docs_src/security/tutorial005_an_py310.py b/docs_src/security/tutorial005_an_py310.py index 297193e35..90781587f 100644 --- a/docs_src/security/tutorial005_an_py310.py +++ b/docs_src/security/tutorial005_an_py310.py @@ -116,7 +116,7 @@ async def get_current_user( ) try: payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM]) - username: str = payload.get("sub") + username = payload.get("sub") if username is None: raise credentials_exception token_scopes = payload.get("scopes", []) diff --git a/docs_src/security/tutorial005_an_py39.py b/docs_src/security/tutorial005_an_py39.py index 1acf47bdc..a5192d8d6 100644 --- a/docs_src/security/tutorial005_an_py39.py +++ b/docs_src/security/tutorial005_an_py39.py @@ -1,5 +1,5 @@ from datetime import datetime, timedelta, timezone -from typing import Annotated, List, Union +from typing import Annotated, Union import jwt from fastapi import Depends, FastAPI, HTTPException, Security, status @@ -44,7 +44,7 @@ class Token(BaseModel): class TokenData(BaseModel): username: Union[str, None] = None - scopes: List[str] = [] + scopes: list[str] = [] class User(BaseModel): @@ -116,7 +116,7 @@ async def get_current_user( ) try: payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM]) - username: str = payload.get("sub") + username = payload.get("sub") if username is None: raise credentials_exception token_scopes = payload.get("scopes", []) diff --git a/fastapi/__init__.py b/fastapi/__init__.py index c92279cfd..b02bf8b4f 100644 --- a/fastapi/__init__.py +++ b/fastapi/__init__.py @@ -1,6 +1,6 @@ """FastAPI framework, high performance, easy to learn, fast to code, ready for production""" -__version__ = "0.115.7" +__version__ = "0.116.1" from starlette import status as status diff --git a/fastapi/_compat.py b/fastapi/_compat.py index c07e4a3b0..227ad837d 100644 --- a/fastapi/_compat.py +++ b/fastapi/_compat.py @@ -16,6 +16,7 @@ from typing import ( Tuple, Type, Union, + cast, ) from fastapi.exceptions import RequestErrorModel @@ -231,6 +232,10 @@ if PYDANTIC_V2: field_mapping, definitions = schema_generator.generate_definitions( inputs=inputs ) + for item_def in cast(Dict[str, Dict[str, Any]], definitions).values(): + if "description" in item_def: + item_description = cast(str, item_def["description"]).split("\f")[0] + item_def["description"] = item_description return field_mapping, definitions # type: ignore[return-value] def is_scalar_field(field: ModelField) -> bool: diff --git a/fastapi/applications.py b/fastapi/applications.py index 6d427cdc2..05c7bd2be 100644 --- a/fastapi/applications.py +++ b/fastapi/applications.py @@ -748,7 +748,7 @@ class FastAPI(Starlette): This affects the generated OpenAPI (e.g. visible at `/docs`). Read more about it in the - [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-from-openapi). + [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-parameters-from-openapi). """ ), ] = True, @@ -1720,7 +1720,7 @@ class FastAPI(Starlette): This affects the generated OpenAPI (e.g. visible at `/docs`). Read more about it in the - [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-from-openapi). + [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-parameters-from-openapi). """ ), ] = True, @@ -2093,7 +2093,7 @@ class FastAPI(Starlette): This affects the generated OpenAPI (e.g. visible at `/docs`). Read more about it in the - [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-from-openapi). + [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-parameters-from-openapi). """ ), ] = True, @@ -2471,7 +2471,7 @@ class FastAPI(Starlette): This affects the generated OpenAPI (e.g. visible at `/docs`). Read more about it in the - [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-from-openapi). + [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-parameters-from-openapi). """ ), ] = True, @@ -2849,7 +2849,7 @@ class FastAPI(Starlette): This affects the generated OpenAPI (e.g. visible at `/docs`). Read more about it in the - [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-from-openapi). + [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-parameters-from-openapi). """ ), ] = True, @@ -3222,7 +3222,7 @@ class FastAPI(Starlette): This affects the generated OpenAPI (e.g. visible at `/docs`). Read more about it in the - [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-from-openapi). + [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-parameters-from-openapi). """ ), ] = True, @@ -3595,7 +3595,7 @@ class FastAPI(Starlette): This affects the generated OpenAPI (e.g. visible at `/docs`). Read more about it in the - [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-from-openapi). + [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-parameters-from-openapi). """ ), ] = True, @@ -3968,7 +3968,7 @@ class FastAPI(Starlette): This affects the generated OpenAPI (e.g. visible at `/docs`). Read more about it in the - [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-from-openapi). + [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-parameters-from-openapi). """ ), ] = True, @@ -4346,7 +4346,7 @@ class FastAPI(Starlette): This affects the generated OpenAPI (e.g. visible at `/docs`). Read more about it in the - [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-from-openapi). + [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-parameters-from-openapi). """ ), ] = True, @@ -4425,7 +4425,7 @@ class FastAPI(Starlette): app = FastAPI() - @app.put("/items/{item_id}") + @app.trace("/items/{item_id}") def trace_item(item_id: str): return None ``` @@ -4515,14 +4515,17 @@ class FastAPI(Starlette): ```python import time + from typing import Awaitable, Callable - from fastapi import FastAPI, Request + from fastapi import FastAPI, Request, Response app = FastAPI() @app.middleware("http") - async def add_process_time_header(request: Request, call_next): + async def add_process_time_header( + request: Request, call_next: Callable[[Request], Awaitable[Response]] + ) -> Response: start_time = time.time() response = await call_next(request) process_time = time.time() - start_time diff --git a/fastapi/dependencies/utils.py b/fastapi/dependencies/utils.py index 38bc3eb4e..baf226b7a 100644 --- a/fastapi/dependencies/utils.py +++ b/fastapi/dependencies/utils.py @@ -133,9 +133,9 @@ def get_param_sub_dependant( def get_parameterless_sub_dependant(*, depends: params.Depends, path: str) -> Dependant: - assert callable( - depends.dependency - ), "A parameter-less dependency must have a callable dependency" + assert callable(depends.dependency), ( + "A parameter-less dependency must have a callable dependency" + ) return get_sub_dependant(depends=depends, dependency=depends.dependency, path=path) @@ -305,9 +305,9 @@ def get_dependant( type_annotation=param_details.type_annotation, dependant=dependant, ): - assert ( - param_details.field is None - ), f"Cannot specify multiple FastAPI annotations for {param_name!r}" + assert param_details.field is None, ( + f"Cannot specify multiple FastAPI annotations for {param_name!r}" + ) continue assert param_details.field is not None if isinstance(param_details.field.field_info, params.Body): @@ -442,9 +442,9 @@ def analyze_param( ), ): assert depends is None, f"Cannot specify `Depends` for type {type_annotation!r}" - assert ( - field_info is None - ), f"Cannot specify FastAPI annotation for type {type_annotation!r}" + assert field_info is None, ( + f"Cannot specify FastAPI annotation for type {type_annotation!r}" + ) # Handle default assignations, neither field_info nor depends was not found in Annotated nor default value elif field_info is None and depends is None: default_value = value if value is not inspect.Signature.empty else RequiredParam @@ -497,9 +497,9 @@ def analyze_param( field_info=field_info, ) if is_path_param: - assert is_scalar_field( - field=field - ), "Path params must be of one of the supported types" + assert is_scalar_field(field=field), ( + "Path params must be of one of the supported types" + ) elif isinstance(field_info, params.Query): assert ( is_scalar_field(field) @@ -524,9 +524,9 @@ def add_param_to_fields(*, field: ModelField, dependant: Dependant) -> None: elif field_info_in == params.ParamTypes.header: dependant.header_params.append(field) else: - assert ( - field_info_in == params.ParamTypes.cookie - ), f"non-body parameters must be in path, query, header or cookie: {field.name}" + assert field_info_in == params.ParamTypes.cookie, ( + f"non-body parameters must be in path, query, header or cookie: {field.name}" + ) dependant.cookie_params.append(field) @@ -751,6 +751,8 @@ def request_params_to_args( return values, errors fields_to_extract = fields + default_convert_underscores = True + params_to_process: Dict[str, Any] = {} model_fields = [ @@ -770,7 +772,9 @@ def request_params_to_args( if isinstance(received_params, Headers): # Handle fields extracted from a Pydantic Model for a header, each field # doesn't have a FieldInfo of type Header with the default convert_underscores=True - convert_underscores = getattr(field.field_info, "convert_underscores", True) + convert_underscores = getattr( + field.field_info, "convert_underscores", default_convert_underscores + ) if convert_underscores: alias = ( field.alias @@ -789,9 +793,9 @@ def request_params_to_args( for field in fields: field_info = field.field_info - assert isinstance( - field_info, params.Param - ), "Params must be subclasses of Param" + assert isinstance(field_info, params.Param), ( + "Params must be subclasses of Param" + ) if lenient_issubclass(field.type_, BaseModel): loc: Tuple[str, ...] = (field_info.in_.value,) @@ -812,6 +816,25 @@ def request_params_to_args( return values, errors +def is_union_of_base_models(field_type: Any) -> bool: + """Check if field type is a Union where all members are BaseModel subclasses.""" + from fastapi.types import UnionType + + origin = get_origin(field_type) + + # Check if it's a Union type (covers both typing.Union and types.UnionType in Python 3.10+) + if origin is not Union and origin is not UnionType: + return False + + union_args = get_args(field_type) + + for arg in union_args: + if not lenient_issubclass(arg, BaseModel): + return False + + return True + + def _should_embed_body_fields(fields: List[ModelField]) -> bool: if not fields: return False @@ -825,10 +848,12 @@ def _should_embed_body_fields(fields: List[ModelField]) -> bool: # If it explicitly specifies it is embedded, it has to be embedded if getattr(first_field.field_info, "embed", None): return True - # If it's a Form (or File) field, it has to be a BaseModel to be top level + # If it's a Form (or File) field, it has to be a BaseModel (or a union of BaseModels) to be top level # otherwise it has to be embedded, so that the key value pair can be extracted - if isinstance(first_field.field_info, params.Form) and not lenient_issubclass( - first_field.type_, BaseModel + if ( + isinstance(first_field.field_info, params.Form) + and not lenient_issubclass(first_field.type_, BaseModel) + and not is_union_of_base_models(first_field.type_) ): return True return False diff --git a/fastapi/openapi/docs.py b/fastapi/openapi/docs.py index c2ec358d2..f181b43c1 100644 --- a/fastapi/openapi/docs.py +++ b/fastapi/openapi/docs.py @@ -188,7 +188,7 @@ def get_redoc_html( It is normally set to a CDN URL. """ ), - ] = "https://cdn.jsdelivr.net/npm/redoc@next/bundles/redoc.standalone.js", + ] = "https://cdn.jsdelivr.net/npm/redoc@2/bundles/redoc.standalone.js", redoc_favicon_url: Annotated[ str, Doc( diff --git a/fastapi/openapi/utils.py b/fastapi/openapi/utils.py index 947eca948..808646cc2 100644 --- a/fastapi/openapi/utils.py +++ b/fastapi/openapi/utils.py @@ -32,6 +32,7 @@ from fastapi.utils import ( generate_operation_id_for_path, is_body_allowed_for_status_code, ) +from pydantic import BaseModel from starlette.responses import JSONResponse from starlette.routing import BaseRoute from starlette.status import HTTP_422_UNPROCESSABLE_ENTITY @@ -113,6 +114,13 @@ def _get_openapi_operation_parameters( (ParamTypes.header, header_params), (ParamTypes.cookie, cookie_params), ] + default_convert_underscores = True + if len(flat_dependant.header_params) == 1: + first_field = flat_dependant.header_params[0] + if lenient_issubclass(first_field.type_, BaseModel): + default_convert_underscores = getattr( + first_field.field_info, "convert_underscores", True + ) for param_type, param_group in parameter_groups: for param in param_group: field_info = param.field_info @@ -126,8 +134,21 @@ def _get_openapi_operation_parameters( field_mapping=field_mapping, separate_input_output_schemas=separate_input_output_schemas, ) + name = param.alias + convert_underscores = getattr( + param.field_info, + "convert_underscores", + default_convert_underscores, + ) + if ( + param_type == ParamTypes.header + and param.alias == param.name + and convert_underscores + ): + name = param.name.replace("_", "-") + parameter = { - "name": param.alias, + "name": name, "in": param_type.value, "required": param.required, "schema": param_schema, @@ -364,9 +385,9 @@ def get_openapi_path( openapi_response = operation_responses.setdefault( status_code_key, {} ) - assert isinstance( - process_response, dict - ), "An additional response must be a dict" + assert isinstance(process_response, dict), ( + "An additional response must be a dict" + ) field = route.response_fields.get(additional_status_code) additional_field_schema: Optional[Dict[str, Any]] = None if field: @@ -434,9 +455,9 @@ def get_fields_from_routes( route, routing.APIRoute ): if route.body_field: - assert isinstance( - route.body_field, ModelField - ), "A request body must be a Pydantic Field" + assert isinstance(route.body_field, ModelField), ( + "A request body must be a Pydantic Field" + ) body_fields_from_routes.append(route.body_field) if route.response_field: responses_from_routes.append(route.response_field) diff --git a/fastapi/routing.py b/fastapi/routing.py index 8ea4bb219..54c75a027 100644 --- a/fastapi/routing.py +++ b/fastapi/routing.py @@ -9,6 +9,7 @@ from typing import ( Any, AsyncIterator, Callable, + Collection, Coroutine, Dict, List, @@ -504,9 +505,9 @@ class APIRoute(routing.Route): status_code = int(status_code) self.status_code = status_code if self.response_model: - assert is_body_allowed_for_status_code( - status_code - ), f"Status code {status_code} must not have a response body" + assert is_body_allowed_for_status_code(status_code), ( + f"Status code {status_code} must not have a response body" + ) response_name = "Response_" + self.unique_id self.response_field = create_model_field( name=response_name, @@ -537,9 +538,9 @@ class APIRoute(routing.Route): assert isinstance(response, dict), "An additional response must be a dict" model = response.get("model") if model: - assert is_body_allowed_for_status_code( - additional_status_code - ), f"Status code {additional_status_code} must not have a response body" + assert is_body_allowed_for_status_code(additional_status_code), ( + f"Status code {additional_status_code} must not have a response body" + ) response_name = f"Response_{additional_status_code}_{self.unique_id}" response_field = create_model_field( name=response_name, type_=model, mode="serialization" @@ -814,7 +815,7 @@ class APIRouter(routing.Router): This affects the generated OpenAPI (e.g. visible at `/docs`). Read more about it in the - [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-from-openapi). + [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-parameters-from-openapi). """ ), ] = True, @@ -844,9 +845,9 @@ class APIRouter(routing.Router): ) if prefix: assert prefix.startswith("/"), "A path prefix must start with '/'" - assert not prefix.endswith( - "/" - ), "A path prefix must not end with '/', as the routes will start with '/'" + assert not prefix.endswith("/"), ( + "A path prefix must not end with '/', as the routes will start with '/'" + ) self.prefix = prefix self.tags: List[Union[str, Enum]] = tags or [] self.dependencies = list(dependencies or []) @@ -862,7 +863,7 @@ class APIRouter(routing.Router): def route( self, path: str, - methods: Optional[List[str]] = None, + methods: Optional[Collection[str]] = None, name: Optional[str] = None, include_in_schema: bool = True, ) -> Callable[[DecoratedCallable], DecoratedCallable]: @@ -1256,9 +1257,9 @@ class APIRouter(routing.Router): """ if prefix: assert prefix.startswith("/"), "A path prefix must start with '/'" - assert not prefix.endswith( - "/" - ), "A path prefix must not end with '/', as the routes will start with '/'" + assert not prefix.endswith("/"), ( + "A path prefix must not end with '/', as the routes will start with '/'" + ) else: for r in router.routes: path = getattr(r, "path") # noqa: B009 @@ -1626,7 +1627,7 @@ class APIRouter(routing.Router): This affects the generated OpenAPI (e.g. visible at `/docs`). Read more about it in the - [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-from-openapi). + [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-parameters-from-openapi). """ ), ] = True, @@ -2003,7 +2004,7 @@ class APIRouter(routing.Router): This affects the generated OpenAPI (e.g. visible at `/docs`). Read more about it in the - [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-from-openapi). + [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-parameters-from-openapi). """ ), ] = True, @@ -2385,7 +2386,7 @@ class APIRouter(routing.Router): This affects the generated OpenAPI (e.g. visible at `/docs`). Read more about it in the - [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-from-openapi). + [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-parameters-from-openapi). """ ), ] = True, @@ -2767,7 +2768,7 @@ class APIRouter(routing.Router): This affects the generated OpenAPI (e.g. visible at `/docs`). Read more about it in the - [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-from-openapi). + [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-parameters-from-openapi). """ ), ] = True, @@ -3144,7 +3145,7 @@ class APIRouter(routing.Router): This affects the generated OpenAPI (e.g. visible at `/docs`). Read more about it in the - [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-from-openapi). + [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-parameters-from-openapi). """ ), ] = True, @@ -3521,7 +3522,7 @@ class APIRouter(routing.Router): This affects the generated OpenAPI (e.g. visible at `/docs`). Read more about it in the - [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-from-openapi). + [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-parameters-from-openapi). """ ), ] = True, @@ -3903,7 +3904,7 @@ class APIRouter(routing.Router): This affects the generated OpenAPI (e.g. visible at `/docs`). Read more about it in the - [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-from-openapi). + [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-parameters-from-openapi). """ ), ] = True, @@ -4285,7 +4286,7 @@ class APIRouter(routing.Router): This affects the generated OpenAPI (e.g. visible at `/docs`). Read more about it in the - [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-from-openapi). + [FastAPI docs for Query Parameters and String Validations](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-parameters-from-openapi). """ ), ] = True, diff --git a/fastapi/security/api_key.py b/fastapi/security/api_key.py index d68bdb037..70c2dca8a 100644 --- a/fastapi/security/api_key.py +++ b/fastapi/security/api_key.py @@ -9,7 +9,15 @@ from typing_extensions import Annotated, Doc class APIKeyBase(SecurityBase): - pass + @staticmethod + def check_api_key(api_key: Optional[str], auto_error: bool) -> Optional[str]: + if not api_key: + if auto_error: + raise HTTPException( + status_code=HTTP_403_FORBIDDEN, detail="Not authenticated" + ) + return None + return api_key class APIKeyQuery(APIKeyBase): @@ -101,14 +109,7 @@ class APIKeyQuery(APIKeyBase): async def __call__(self, request: Request) -> Optional[str]: api_key = request.query_params.get(self.model.name) - if not api_key: - if self.auto_error: - raise HTTPException( - status_code=HTTP_403_FORBIDDEN, detail="Not authenticated" - ) - else: - return None - return api_key + return self.check_api_key(api_key, self.auto_error) class APIKeyHeader(APIKeyBase): @@ -196,14 +197,7 @@ class APIKeyHeader(APIKeyBase): async def __call__(self, request: Request) -> Optional[str]: api_key = request.headers.get(self.model.name) - if not api_key: - if self.auto_error: - raise HTTPException( - status_code=HTTP_403_FORBIDDEN, detail="Not authenticated" - ) - else: - return None - return api_key + return self.check_api_key(api_key, self.auto_error) class APIKeyCookie(APIKeyBase): @@ -291,11 +285,4 @@ class APIKeyCookie(APIKeyBase): async def __call__(self, request: Request) -> Optional[str]: api_key = request.cookies.get(self.model.name) - if not api_key: - if self.auto_error: - raise HTTPException( - status_code=HTTP_403_FORBIDDEN, detail="Not authenticated" - ) - else: - return None - return api_key + return self.check_api_key(api_key, self.auto_error) diff --git a/fastapi/security/http.py b/fastapi/security/http.py index e06f3d66d..9ab2df3c9 100644 --- a/fastapi/security/http.py +++ b/fastapi/security/http.py @@ -413,8 +413,11 @@ class HTTPDigest(HTTPBase): else: return None if scheme.lower() != "digest": - raise HTTPException( - status_code=HTTP_403_FORBIDDEN, - detail="Invalid authentication credentials", - ) + if self.auto_error: + raise HTTPException( + status_code=HTTP_403_FORBIDDEN, + detail="Invalid authentication credentials", + ) + else: + return None return HTTPAuthorizationCredentials(scheme=scheme, credentials=credentials) diff --git a/fastapi/security/oauth2.py b/fastapi/security/oauth2.py index 6adc55bfe..88e394db1 100644 --- a/fastapi/security/oauth2.py +++ b/fastapi/security/oauth2.py @@ -63,7 +63,7 @@ class OAuth2PasswordRequestForm: *, grant_type: Annotated[ Union[str, None], - Form(pattern="password"), + Form(pattern="^password$"), Doc( """ The OAuth2 spec says it is required and MUST be the fixed string @@ -85,7 +85,7 @@ class OAuth2PasswordRequestForm: ], password: Annotated[ str, - Form(), + Form(json_schema_extra={"format": "password"}), Doc( """ `password` string. The OAuth2 spec requires the exact field name @@ -130,7 +130,7 @@ class OAuth2PasswordRequestForm: ] = None, client_secret: Annotated[ Union[str, None], - Form(), + Form(json_schema_extra={"format": "password"}), Doc( """ If there's a `client_password` (and a `client_id`), they can be sent @@ -217,7 +217,7 @@ class OAuth2PasswordRequestFormStrict(OAuth2PasswordRequestForm): self, grant_type: Annotated[ str, - Form(pattern="password"), + Form(pattern="^password$"), Doc( """ The OAuth2 spec says it is required and MUST be the fixed string @@ -457,11 +457,26 @@ class OAuth2PasswordBearer(OAuth2): """ ), ] = True, + refreshUrl: Annotated[ + Optional[str], + Doc( + """ + The URL to refresh the token and obtain a new one. + """ + ), + ] = None, ): if not scopes: scopes = {} flows = OAuthFlowsModel( - password=cast(Any, {"tokenUrl": tokenUrl, "scopes": scopes}) + password=cast( + Any, + { + "tokenUrl": tokenUrl, + "refreshUrl": refreshUrl, + "scopes": scopes, + }, + ) ) super().__init__( flows=flows, diff --git a/pyproject.toml b/pyproject.toml index 381eb50bf..7709451ff 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -38,11 +38,12 @@ classifiers = [ "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", "Topic :: Internet :: WWW/HTTP :: HTTP Servers", "Topic :: Internet :: WWW/HTTP", ] dependencies = [ - "starlette>=0.40.0,<0.46.0", + "starlette>=0.40.0,<0.48.0", "pydantic>=1.7.4,!=1.8,!=1.8.1,!=2.0.0,!=2.0.1,!=2.1.0,<3.0.0", "typing-extensions>=4.8.0", ] @@ -57,7 +58,26 @@ Changelog = "https://fastapi.tiangolo.com/release-notes/" [project.optional-dependencies] standard = [ - "fastapi-cli[standard] >=0.0.5", + "fastapi-cli[standard] >=0.0.8", + # For the test client + "httpx >=0.23.0", + # For templates + "jinja2 >=3.1.5", + # For forms and file uploads + "python-multipart >=0.0.18", + # To validate email fields + "email-validator >=2.0.0", + # Uvicorn with uvloop + "uvicorn[standard] >=0.12.0", + # TODO: this should be part of some pydantic optional extra dependencies + # # Settings management + # "pydantic-settings >=2.0.0", + # # Extra Pydantic data types + # "pydantic-extra-types >=2.0.0", +] + +standard-no-fastapi-cloud-cli = [ + "fastapi-cli[standard-no-fastapi-cloud-cli] >=0.0.8", # For the test client "httpx >=0.23.0", # For templates @@ -76,7 +96,7 @@ standard = [ ] all = [ - "fastapi-cli[standard] >=0.0.5", + "fastapi-cli[standard] >=0.0.8", # # For the test client "httpx >=0.23.0", # For templates @@ -162,6 +182,8 @@ filterwarnings = [ # Ref: https://github.com/python-trio/trio/pull/3054 # Remove once there's a new version of Trio 'ignore:The `hash` argument is deprecated*:DeprecationWarning:trio', + # Ignore flaky coverage / pytest warning about SQLite connection, only applies to Python 3.13 and Pydantic v1 + 'ignore:Exception ignored in. =0.23.0,<0.28.0 +httpx >=0.23.0,<0.29.0 # For linting and generating docs versions -ruff ==0.6.4 +ruff ==0.12.7 diff --git a/requirements-docs.txt b/requirements-docs.txt index 6f391675a..eeb41b5ce 100644 --- a/requirements-docs.txt +++ b/requirements-docs.txt @@ -1,19 +1,19 @@ -e . -r requirements-docs-tests.txt -mkdocs-material==9.5.18 +mkdocs-material==9.6.16 mdx-include >=1.4.1,<2.0.0 mkdocs-redirects>=1.2.1,<1.3.0 -typer == 0.12.5 +typer == 0.16.0 pyyaml >=5.3.1,<7.0.0 # For Material for MkDocs, Chinese search jieba==0.42.1 # For image processing by Material for MkDocs -pillow==11.0.0 +pillow==11.3.0 # For image processing by Material for MkDocs -cairosvg==2.7.1 +cairosvg==2.8.2 mkdocstrings[python]==0.26.1 -griffe-typingdoc==0.2.7 +griffe-typingdoc==0.2.8 # For griffe, it formats with black -black==24.10.0 +black==25.1.0 mkdocs-macros-plugin==1.3.7 markdown-include-variants==0.0.4 diff --git a/requirements-github-actions.txt b/requirements-github-actions.txt index 920aefea6..f807d06a8 100644 --- a/requirements-github-actions.txt +++ b/requirements-github-actions.txt @@ -1,6 +1,6 @@ PyGithub>=2.3.0,<3.0.0 pydantic>=2.5.3,<3.0.0 pydantic-settings>=2.1.0,<3.0.0 -httpx>=0.27.0,<0.28.0 +httpx>=0.27.0,<0.29.0 pyyaml >=5.3.1,<7.0.0 smokeshow diff --git a/requirements-tests.txt b/requirements-tests.txt index 91e7fb7aa..b9f2b2b66 100644 --- a/requirements-tests.txt +++ b/requirements-tests.txt @@ -3,14 +3,14 @@ pytest >=7.1.3,<9.0.0 coverage[toml] >= 6.5.0,< 8.0 mypy ==1.8.0 -dirty-equals ==0.8.0 -sqlmodel==0.0.22 +dirty-equals ==0.9.0 +sqlmodel==0.0.24 flask >=1.1.2,<4.0.0 anyio[trio] >=3.2.1,<5.0.0 PyJWT==2.8.0 pyyaml >=5.3.1,<7.0.0 passlib[bcrypt] >=1.7.2,<2.0.0 -inline-snapshot==0.18.1 +inline-snapshot>=0.21.1 # types types-ujson ==5.10.0.20240515 types-orjson ==3.6.2 diff --git a/requirements-translations.txt b/requirements-translations.txt index a8f8a02d7..a62ba3ac1 100644 --- a/requirements-translations.txt +++ b/requirements-translations.txt @@ -1 +1,2 @@ -pydantic-ai==0.0.15 +pydantic-ai==0.4.10 +GitPython==3.1.45 diff --git a/scripts/label_approved.py b/scripts/label_approved.py index 271444504..81de92efb 100644 --- a/scripts/label_approved.py +++ b/scripts/label_approved.py @@ -27,7 +27,7 @@ if settings.debug: logging.basicConfig(level=logging.DEBUG) else: logging.basicConfig(level=logging.INFO) -logging.debug(f"Using config: {settings.json()}") +logging.debug(f"Using config: {settings.model_dump_json()}") g = Github(settings.token.get_secret_value()) repo = g.get_repo(settings.github_repository) for pr in repo.get_pulls(state="open"): @@ -48,7 +48,7 @@ for pr in repo.get_pulls(state="open"): ] config = settings.config or default_config for approved_label, conf in config.items(): - logging.debug(f"Processing config: {conf.json()}") + logging.debug(f"Processing config: {conf.model_dump_json()}") if conf.await_label is None or (conf.await_label in pr_label_by_name): logging.debug(f"Processable PR: {pr.number}") if len(approved_reviews) >= conf.number: diff --git a/scripts/people.py b/scripts/people.py index f61fd31c9..7418b4595 100644 --- a/scripts/people.py +++ b/scripts/people.py @@ -119,6 +119,7 @@ class Settings(BaseSettings): github_token: SecretStr github_repository: str httpx_timeout: int = 30 + sleep_interval: int = 5 def get_graphql_response( @@ -184,7 +185,7 @@ def get_discussion_nodes(settings: Settings) -> list[DiscussionsNode]: discussion_nodes.append(discussion_edge.node) last_edge = discussion_edges[-1] # Handle GitHub secondary rate limits, requests per minute - time.sleep(5) + time.sleep(settings.sleep_interval) discussion_edges = get_graphql_question_discussion_edges( settings=settings, after=last_edge.cursor ) diff --git a/scripts/translate.py b/scripts/translate.py index ce11b3877..2fdc18ca0 100644 --- a/scripts/translate.py +++ b/scripts/translate.py @@ -1,10 +1,15 @@ +import secrets +import subprocess from functools import lru_cache from pathlib import Path -from typing import Iterable +from typing import Annotated, Iterable +import git import typer import yaml +from github import Github from pydantic_ai import Agent +from rich import print non_translated_sections = ( "reference/", @@ -21,6 +26,8 @@ non_translated_sections = ( general_prompt = """ For technical terms in English that don't have a common translation term use the original term in English. +If you have instructions to translate specific terms or phrases in a specific way, please follow those instructions instead of keeping the old and outdated content. + For code snippets or fragments, surrounded by backticks (`), don't translate the content, keep the original in English. For example, `list`, `dict`, keep them as is. The content is written in markdown, write the translation in markdown as well. Don't add triple backticks (`) around the generated translation content. @@ -28,8 +35,38 @@ The content is written in markdown, write the translation in markdown as well. D When there's an example of code, the console or a terminal, normally surrounded by triple backticks and a keyword like "console" or "bash" (e.g. ```console), do not translate the content, keep the original in English. The original content will be surrounded by triple percentage signs (%) and you should translate it to the target language. Do not include the triple percentage signs in the translation. + +There are special blocks of notes, tips and others that look like: + +/// note + +To translate it, keep the same line and add the translation after a vertical bar. + +For example, if you were translating to Spanish, you would write: + +/// note | Nota + +Some examples in Spanish: + +Source: + +/// tip + +Result: + +/// tip | Consejo + +Source: + +/// details | Preview + +Result: + +/// details | Vista previa """ +app = typer.Typer() + @lru_cache def get_langs() -> dict[str, str]: @@ -38,64 +75,89 @@ def get_langs() -> dict[str, str]: def generate_lang_path(*, lang: str, path: Path) -> Path: en_docs_path = Path("docs/en/docs") - assert str(path).startswith( - str(en_docs_path) - ), f"Path must be inside {en_docs_path}" + assert str(path).startswith(str(en_docs_path)), ( + f"Path must be inside {en_docs_path}" + ) lang_docs_path = Path(f"docs/{lang}/docs") out_path = Path(str(path).replace(str(en_docs_path), str(lang_docs_path))) return out_path -def translate_page(*, lang: str, path: Path) -> None: +def generate_en_path(*, lang: str, path: Path) -> Path: + en_docs_path = Path("docs/en/docs") + assert not str(path).startswith(str(en_docs_path)), ( + f"Path must not be inside {en_docs_path}" + ) + lang_docs_path = Path(f"docs/{lang}/docs") + out_path = Path(str(path).replace(str(lang_docs_path), str(en_docs_path))) + return out_path + + +@app.command() +def translate_page( + *, + language: Annotated[str, typer.Option(envvar="LANGUAGE")], + en_path: Annotated[Path, typer.Option(envvar="EN_PATH")], +) -> None: langs = get_langs() - language = langs[lang] - lang_path = Path(f"docs/{lang}") + language_name = langs[language] + lang_path = Path(f"docs/{language}") lang_path.mkdir(exist_ok=True) lang_prompt_path = lang_path / "llm-prompt.md" assert lang_prompt_path.exists(), f"Prompt file not found: {lang_prompt_path}" lang_prompt_content = lang_prompt_path.read_text() en_docs_path = Path("docs/en/docs") - assert str(path).startswith( - str(en_docs_path) - ), f"Path must be inside {en_docs_path}" - out_path = generate_lang_path(lang=lang, path=path) + assert str(en_path).startswith(str(en_docs_path)), ( + f"Path must be inside {en_docs_path}" + ) + out_path = generate_lang_path(lang=language, path=en_path) out_path.parent.mkdir(parents=True, exist_ok=True) - original_content = path.read_text() + original_content = en_path.read_text() old_translation: str | None = None if out_path.exists(): + print(f"Found existing translation: {out_path}") old_translation = out_path.read_text() + print(f"Translating {en_path} to {language} ({language_name})") agent = Agent("openai:gpt-4o") prompt_segments = [ - lang_prompt_content, general_prompt, + lang_prompt_content, ] if old_translation: prompt_segments.extend( [ "There's an existing previous translation for this content that is probably outdated with old content or old instructions.", - "Update the translation given your current instructions and the original content.", - "If you have instructions to translate specific terms or phrases in a specific way, please follow those instructions instead of keeping the old and outdated content.", + "Update the translation only where necessary:", + "- If the original English content has changed, reflect that in the translation.", + "- If the previous translation violates current instructions, update it.", + "- Otherwise, preserve the original translation **line-by-line** as-is.", + "Do not:", + "- Rephrase or rewrite correct lines just to improve the style.", + "- Add or remove line breaks unless the English source changed.", + "- Change formatting or whitespace unless absolutely required.", + "Only change what must be changed. The goal is to minimize diffs for easier review.", "Previous translation:", f"%%%\n{old_translation}%%%", ] ) prompt_segments.extend( [ - f"Translate to {language} ({lang}).", + f"Translate to {language} ({language_name}).", "Original content:", f"%%%\n{original_content}%%%", ] ) prompt = "\n\n".join(prompt_segments) - + print(f"Running agent for {out_path}") result = agent.run_sync(prompt) out_content = f"{result.data.strip()}\n" + print(f"Saving translation to {out_path}") out_path.write_text(out_content) -def iter_paths_to_translate() -> Iterable[Path]: +def iter_all_en_paths() -> Iterable[Path]: """ Iterate on the markdown files to translate in order of priority. """ @@ -119,12 +181,16 @@ def iter_paths_to_translate() -> Iterable[Path]: yield path -def translate_all(lang: str) -> None: - paths_to_process: list[Path] = [] - for path in iter_paths_to_translate(): +def iter_en_paths_to_translate() -> Iterable[Path]: + for path in iter_all_en_paths(): if str(path).replace("docs/en/docs/", "").startswith(non_translated_sections): continue - paths_to_process.append(path) + yield path + + +@app.command() +def translate_lang(language: Annotated[str, typer.Option(envvar="LANGUAGE")]) -> None: + paths_to_process = list(iter_en_paths_to_translate()) print("Original paths:") for p in paths_to_process: print(f" - {p}") @@ -132,7 +198,7 @@ def translate_all(lang: str) -> None: missing_paths: list[Path] = [] skipped_paths: list[Path] = [] for p in paths_to_process: - lang_path = generate_lang_path(lang=lang, path=p) + lang_path = generate_lang_path(lang=language, path=p) if lang_path.exists(): skipped_paths.append(p) continue @@ -147,16 +213,158 @@ def translate_all(lang: str) -> None: print(f"Total paths to process: {len(missing_paths)}") for p in missing_paths: print(f"Translating: {p}") - translate_page(lang="es", path=p) + translate_page(language="es", en_path=p) print(f"Done translating: {p}") -def main(*, lang: str, path: Path = None) -> None: - if path: - translate_page(lang=lang, path=path) - else: - translate_all(lang=lang) +@app.command() +def list_removable(language: str) -> list[Path]: + removable_paths: list[Path] = [] + lang_paths = Path(f"docs/{language}").rglob("*.md") + for path in lang_paths: + en_path = generate_en_path(lang=language, path=path) + if not en_path.exists(): + removable_paths.append(path) + print(removable_paths) + return removable_paths + + +@app.command() +def list_all_removable() -> list[Path]: + all_removable_paths: list[Path] = [] + langs = get_langs() + for lang in langs: + if lang == "en": + continue + removable_paths = list_removable(lang) + all_removable_paths.extend(removable_paths) + print(all_removable_paths) + return all_removable_paths + + +@app.command() +def remove_removable(language: str) -> None: + removable_paths = list_removable(language) + for path in removable_paths: + path.unlink() + print(f"Removed: {path}") + print("Done removing all removable paths") + + +@app.command() +def remove_all_removable() -> None: + all_removable = list_all_removable() + for removable_path in all_removable: + removable_path.unlink() + print(f"Removed: {removable_path}") + print("Done removing all removable paths") + + +@app.command() +def list_missing(language: str) -> list[Path]: + missing_paths: list[Path] = [] + en_lang_paths = list(iter_en_paths_to_translate()) + for path in en_lang_paths: + lang_path = generate_lang_path(lang=language, path=path) + if not lang_path.exists(): + missing_paths.append(path) + print(missing_paths) + return missing_paths + + +@app.command() +def list_outdated(language: str) -> list[Path]: + dir_path = Path(__file__).absolute().parent.parent + repo = git.Repo(dir_path) + + outdated_paths: list[Path] = [] + en_lang_paths = list(iter_en_paths_to_translate()) + for path in en_lang_paths: + lang_path = generate_lang_path(lang=language, path=path) + if not lang_path.exists(): + continue + en_commit_datetime = list(repo.iter_commits(paths=path, max_count=1))[ + 0 + ].committed_datetime + lang_commit_datetime = list(repo.iter_commits(paths=lang_path, max_count=1))[ + 0 + ].committed_datetime + if lang_commit_datetime < en_commit_datetime: + outdated_paths.append(path) + print(outdated_paths) + return outdated_paths + + +@app.command() +def update_outdated(language: Annotated[str, typer.Option(envvar="LANGUAGE")]) -> None: + outdated_paths = list_outdated(language) + for path in outdated_paths: + print(f"Updating lang: {language} path: {path}") + translate_page(language=language, en_path=path) + print(f"Done updating: {path}") + print("Done updating all outdated paths") + + +@app.command() +def add_missing(language: Annotated[str, typer.Option(envvar="LANGUAGE")]) -> None: + missing_paths = list_missing(language) + for path in missing_paths: + print(f"Adding lang: {language} path: {path}") + translate_page(language=language, en_path=path) + print(f"Done adding: {path}") + print("Done adding all missing paths") + + +@app.command() +def update_and_add(language: Annotated[str, typer.Option(envvar="LANGUAGE")]) -> None: + print(f"Updating outdated translations for {language}") + update_outdated(language=language) + print(f"Adding missing translations for {language}") + add_missing(language=language) + print(f"Done updating and adding for {language}") + + +@app.command() +def make_pr( + *, + language: Annotated[str | None, typer.Option(envvar="LANGUAGE")] = None, + github_token: Annotated[str, typer.Option(envvar="GITHUB_TOKEN")], + github_repository: Annotated[str, typer.Option(envvar="GITHUB_REPOSITORY")], +) -> None: + print("Setting up GitHub Actions git user") + repo = git.Repo(Path(__file__).absolute().parent.parent) + if not repo.is_dirty(untracked_files=True): + print("Repository is clean, no changes to commit") + return + subprocess.run(["git", "config", "user.name", "github-actions"], check=True) + subprocess.run( + ["git", "config", "user.email", "github-actions@github.com"], check=True + ) + branch_name = "translate" + if language: + branch_name += f"-{language}" + branch_name += f"-{secrets.token_hex(4)}" + print(f"Creating a new branch {branch_name}") + subprocess.run(["git", "checkout", "-b", branch_name], check=True) + print("Adding updated files") + git_path = Path("docs") + subprocess.run(["git", "add", str(git_path)], check=True) + print("Committing updated file") + message = "🌐 Update translations" + if language: + message += f" for {language}" + subprocess.run(["git", "commit", "-m", message], check=True) + print("Pushing branch") + subprocess.run(["git", "push", "origin", branch_name], check=True) + print("Creating PR") + g = Github(github_token) + gh_repo = g.get_repo(github_repository) + pr = gh_repo.create_pull( + title=message, body=message, base="master", head=branch_name + ) + print(f"Created PR: {pr.number}") + print("Finished") if __name__ == "__main__": - typer.run(main) + app() diff --git a/tests/test_application.py b/tests/test_application.py index 5c62f5f6e..a7d50ea72 100644 --- a/tests/test_application.py +++ b/tests/test_application.py @@ -43,7 +43,7 @@ def test_redoc(): response = client.get("/redoc") assert response.status_code == 200, response.text assert response.headers["content-type"] == "text/html; charset=utf-8" - assert "redoc@next" in response.text + assert "redoc@2" in response.text def test_enum_status_code_response(): diff --git a/tests/test_enforce_once_required_parameter.py b/tests/test_enforce_once_required_parameter.py index b64f8341b..30329282f 100644 --- a/tests/test_enforce_once_required_parameter.py +++ b/tests/test_enforce_once_required_parameter.py @@ -48,7 +48,7 @@ expected_schema = { "type": "array", }, "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error " "Type", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, }, "required": ["loc", "msg", "type"], "title": "ValidationError", @@ -73,7 +73,7 @@ expected_schema = { "responses": { "200": { "content": {"application/json": {"schema": {}}}, - "description": "Successful " "Response", + "description": "Successful Response", }, "422": { "content": { @@ -83,7 +83,7 @@ expected_schema = { } } }, - "description": "Validation " "Error", + "description": "Validation Error", }, }, "summary": "Foo Handler", diff --git a/tests/test_generic_parameterless_depends.py b/tests/test_generic_parameterless_depends.py index fe13ff89b..5aa35320c 100644 --- a/tests/test_generic_parameterless_depends.py +++ b/tests/test_generic_parameterless_depends.py @@ -55,7 +55,7 @@ def test_openapi_schema(): "responses": { "200": { "content": {"application/json": {"schema": {}}}, - "description": "Successful " "Response", + "description": "Successful Response", } }, "summary": "A", @@ -67,7 +67,7 @@ def test_openapi_schema(): "responses": { "200": { "content": {"application/json": {"schema": {}}}, - "description": "Successful " "Response", + "description": "Successful Response", } }, "summary": "B", diff --git a/tests/test_modules_same_name_body/test_main.py b/tests/test_modules_same_name_body/test_main.py index cc165bdca..263d87df2 100644 --- a/tests/test_modules_same_name_body/test_main.py +++ b/tests/test_modules_same_name_body/test_main.py @@ -1,3 +1,4 @@ +import pytest from fastapi.testclient import TestClient from .app.main import app @@ -5,29 +6,22 @@ from .app.main import app client = TestClient(app) -def test_post_a(): +@pytest.mark.parametrize( + "path", ["/a/compute", "/a/compute/", "/b/compute", "/b/compute/"] +) +def test_post(path): data = {"a": 2, "b": "foo"} - response = client.post("/a/compute", json=data) + response = client.post(path, json=data) assert response.status_code == 200, response.text - data = response.json() + assert data == response.json() -def test_post_a_invalid(): +@pytest.mark.parametrize( + "path", ["/a/compute", "/a/compute/", "/b/compute", "/b/compute/"] +) +def test_post_invalid(path): data = {"a": "bar", "b": "foo"} - response = client.post("/a/compute", json=data) - assert response.status_code == 422, response.text - - -def test_post_b(): - data = {"a": 2, "b": "foo"} - response = client.post("/b/compute/", json=data) - assert response.status_code == 200, response.text - data = response.json() - - -def test_post_b_invalid(): - data = {"a": "bar", "b": "foo"} - response = client.post("/b/compute/", json=data) + response = client.post(path, json=data) assert response.status_code == 422, response.text diff --git a/tests/test_openapi_model_description_trim_on_formfeed.py b/tests/test_openapi_model_description_trim_on_formfeed.py new file mode 100644 index 000000000..e18d4f6b2 --- /dev/null +++ b/tests/test_openapi_model_description_trim_on_formfeed.py @@ -0,0 +1,31 @@ +from fastapi import FastAPI +from fastapi.testclient import TestClient +from pydantic import BaseModel + +app = FastAPI() + + +class MyModel(BaseModel): + """ + A model with a form feed character in the title. + \f + Text after form feed character. + """ + + +@app.get("/foo") +def foo(v: MyModel): # pragma: no cover + pass + + +client = TestClient(app) + + +def test_openapi(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + openapi_schema = response.json() + + assert openapi_schema["components"]["schemas"]["MyModel"]["description"] == ( + "A model with a form feed character in the title.\n" + ) diff --git a/tests/test_repeated_dependency_schema.py b/tests/test_repeated_dependency_schema.py index d7d0dfa05..c21829bd9 100644 --- a/tests/test_repeated_dependency_schema.py +++ b/tests/test_repeated_dependency_schema.py @@ -41,7 +41,7 @@ schema = { "type": "array", }, "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error " "Type", "type": "string"}, + "type": {"title": "Error Type", "type": "string"}, }, "required": ["loc", "msg", "type"], "title": "ValidationError", @@ -66,7 +66,7 @@ schema = { "responses": { "200": { "content": {"application/json": {"schema": {}}}, - "description": "Successful " "Response", + "description": "Successful Response", }, "422": { "content": { @@ -76,7 +76,7 @@ schema = { } } }, - "description": "Validation " "Error", + "description": "Validation Error", }, }, "summary": "Get Deps", diff --git a/tests/test_security_http_digest_optional.py b/tests/test_security_http_digest_optional.py index 1e6eb8bd7..0d66f9c72 100644 --- a/tests/test_security_http_digest_optional.py +++ b/tests/test_security_http_digest_optional.py @@ -37,8 +37,8 @@ def test_security_http_digest_incorrect_scheme_credentials(): response = client.get( "/users/me", headers={"Authorization": "Other invalidauthorization"} ) - assert response.status_code == 403, response.text - assert response.json() == {"detail": "Invalid authentication credentials"} + assert response.status_code == 200, response.text + assert response.json() == {"msg": "Create an account first"} def test_openapi_schema(): diff --git a/tests/test_security_oauth2.py b/tests/test_security_oauth2.py index 7d914d034..2b7e3457a 100644 --- a/tests/test_security_oauth2.py +++ b/tests/test_security_oauth2.py @@ -1,3 +1,4 @@ +import pytest from dirty_equals import IsDict from fastapi import Depends, FastAPI, Security from fastapi.security import OAuth2, OAuth2PasswordRequestFormStrict @@ -137,10 +138,18 @@ def test_strict_login_no_grant_type(): ) -def test_strict_login_incorrect_grant_type(): +@pytest.mark.parametrize( + argnames=["grant_type"], + argvalues=[ + pytest.param("incorrect", id="incorrect value"), + pytest.param("passwordblah", id="password with suffix"), + pytest.param("blahpassword", id="password with prefix"), + ], +) +def test_strict_login_incorrect_grant_type(grant_type: str): response = client.post( "/login", - data={"username": "johndoe", "password": "secret", "grant_type": "incorrect"}, + data={"username": "johndoe", "password": "secret", "grant_type": grant_type}, ) assert response.status_code == 422 assert response.json() == IsDict( @@ -149,9 +158,9 @@ def test_strict_login_incorrect_grant_type(): { "type": "string_pattern_mismatch", "loc": ["body", "grant_type"], - "msg": "String should match pattern 'password'", - "input": "incorrect", - "ctx": {"pattern": "password"}, + "msg": "String should match pattern '^password$'", + "input": grant_type, + "ctx": {"pattern": "^password$"}, } ] } @@ -161,9 +170,9 @@ def test_strict_login_incorrect_grant_type(): "detail": [ { "loc": ["body", "grant_type"], - "msg": 'string does not match regex "password"', + "msg": 'string does not match regex "^password$"', "type": "value_error.str.regex", - "ctx": {"pattern": "password"}, + "ctx": {"pattern": "^password$"}, } ] } @@ -248,7 +257,7 @@ def test_openapi_schema(): "properties": { "grant_type": { "title": "Grant Type", - "pattern": "password", + "pattern": "^password$", "type": "string", }, "username": {"title": "Username", "type": "string"}, diff --git a/tests/test_security_oauth2_optional.py b/tests/test_security_oauth2_optional.py index 0da3b911e..046ac5763 100644 --- a/tests/test_security_oauth2_optional.py +++ b/tests/test_security_oauth2_optional.py @@ -1,5 +1,6 @@ from typing import Optional +import pytest from dirty_equals import IsDict from fastapi import Depends, FastAPI, Security from fastapi.security import OAuth2, OAuth2PasswordRequestFormStrict @@ -141,10 +142,18 @@ def test_strict_login_no_grant_type(): ) -def test_strict_login_incorrect_grant_type(): +@pytest.mark.parametrize( + argnames=["grant_type"], + argvalues=[ + pytest.param("incorrect", id="incorrect value"), + pytest.param("passwordblah", id="password with suffix"), + pytest.param("blahpassword", id="password with prefix"), + ], +) +def test_strict_login_incorrect_grant_type(grant_type: str): response = client.post( "/login", - data={"username": "johndoe", "password": "secret", "grant_type": "incorrect"}, + data={"username": "johndoe", "password": "secret", "grant_type": grant_type}, ) assert response.status_code == 422 assert response.json() == IsDict( @@ -153,9 +162,9 @@ def test_strict_login_incorrect_grant_type(): { "type": "string_pattern_mismatch", "loc": ["body", "grant_type"], - "msg": "String should match pattern 'password'", - "input": "incorrect", - "ctx": {"pattern": "password"}, + "msg": "String should match pattern '^password$'", + "input": grant_type, + "ctx": {"pattern": "^password$"}, } ] } @@ -165,9 +174,9 @@ def test_strict_login_incorrect_grant_type(): "detail": [ { "loc": ["body", "grant_type"], - "msg": 'string does not match regex "password"', + "msg": 'string does not match regex "^password$"', "type": "value_error.str.regex", - "ctx": {"pattern": "password"}, + "ctx": {"pattern": "^password$"}, } ] } @@ -252,7 +261,7 @@ def test_openapi_schema(): "properties": { "grant_type": { "title": "Grant Type", - "pattern": "password", + "pattern": "^password$", "type": "string", }, "username": {"title": "Username", "type": "string"}, diff --git a/tests/test_security_oauth2_optional_description.py b/tests/test_security_oauth2_optional_description.py index 85a9f9b39..629cddca2 100644 --- a/tests/test_security_oauth2_optional_description.py +++ b/tests/test_security_oauth2_optional_description.py @@ -1,5 +1,6 @@ from typing import Optional +import pytest from dirty_equals import IsDict from fastapi import Depends, FastAPI, Security from fastapi.security import OAuth2, OAuth2PasswordRequestFormStrict @@ -142,10 +143,18 @@ def test_strict_login_no_grant_type(): ) -def test_strict_login_incorrect_grant_type(): +@pytest.mark.parametrize( + argnames=["grant_type"], + argvalues=[ + pytest.param("incorrect", id="incorrect value"), + pytest.param("passwordblah", id="password with suffix"), + pytest.param("blahpassword", id="password with prefix"), + ], +) +def test_strict_login_incorrect_grant_type(grant_type: str): response = client.post( "/login", - data={"username": "johndoe", "password": "secret", "grant_type": "incorrect"}, + data={"username": "johndoe", "password": "secret", "grant_type": grant_type}, ) assert response.status_code == 422 assert response.json() == IsDict( @@ -154,9 +163,9 @@ def test_strict_login_incorrect_grant_type(): { "type": "string_pattern_mismatch", "loc": ["body", "grant_type"], - "msg": "String should match pattern 'password'", - "input": "incorrect", - "ctx": {"pattern": "password"}, + "msg": "String should match pattern '^password$'", + "input": grant_type, + "ctx": {"pattern": "^password$"}, } ] } @@ -166,9 +175,9 @@ def test_strict_login_incorrect_grant_type(): "detail": [ { "loc": ["body", "grant_type"], - "msg": 'string does not match regex "password"', + "msg": 'string does not match regex "^password$"', "type": "value_error.str.regex", - "ctx": {"pattern": "password"}, + "ctx": {"pattern": "^password$"}, } ] } @@ -253,7 +262,7 @@ def test_openapi_schema(): "properties": { "grant_type": { "title": "Grant Type", - "pattern": "password", + "pattern": "^password$", "type": "string", }, "username": {"title": "Username", "type": "string"}, diff --git a/tests/test_tutorial/test_body_multiple_params/test_tutorial003.py b/tests/test_tutorial/test_body_multiple_params/test_tutorial003.py index c26f8b89b..d18ceae48 100644 --- a/tests/test_tutorial/test_body_multiple_params/test_tutorial003.py +++ b/tests/test_tutorial/test_body_multiple_params/test_tutorial003.py @@ -1,13 +1,26 @@ +import importlib + import pytest from dirty_equals import IsDict from fastapi.testclient import TestClient +from ...utils import needs_py39, needs_py310 + -@pytest.fixture(name="client") -def get_client(): - from docs_src.body_multiple_params.tutorial003 import app +@pytest.fixture( + name="client", + params=[ + "tutorial003", + pytest.param("tutorial003_py310", marks=needs_py310), + "tutorial003_an", + pytest.param("tutorial003_an_py39", marks=needs_py39), + pytest.param("tutorial003_an_py310", marks=needs_py310), + ], +) +def get_client(request: pytest.FixtureRequest): + mod = importlib.import_module(f"docs_src.body_multiple_params.{request.param}") - client = TestClient(app) + client = TestClient(mod.app) return client diff --git a/tests/test_tutorial/test_body_multiple_params/test_tutorial003_an.py b/tests/test_tutorial/test_body_multiple_params/test_tutorial003_an.py deleted file mode 100644 index 62c7e2fad..000000000 --- a/tests/test_tutorial/test_body_multiple_params/test_tutorial003_an.py +++ /dev/null @@ -1,273 +0,0 @@ -import pytest -from dirty_equals import IsDict -from fastapi.testclient import TestClient - - -@pytest.fixture(name="client") -def get_client(): - from docs_src.body_multiple_params.tutorial003_an import app - - client = TestClient(app) - return client - - -def test_post_body_valid(client: TestClient): - response = client.put( - "/items/5", - json={ - "importance": 2, - "item": {"name": "Foo", "price": 50.5}, - "user": {"username": "Dave"}, - }, - ) - assert response.status_code == 200 - assert response.json() == { - "item_id": 5, - "importance": 2, - "item": { - "name": "Foo", - "price": 50.5, - "description": None, - "tax": None, - }, - "user": {"username": "Dave", "full_name": None}, - } - - -def test_post_body_no_data(client: TestClient): - response = client.put("/items/5", json=None) - assert response.status_code == 422 - assert response.json() == IsDict( - { - "detail": [ - { - "type": "missing", - "loc": ["body", "item"], - "msg": "Field required", - "input": None, - }, - { - "type": "missing", - "loc": ["body", "user"], - "msg": "Field required", - "input": None, - }, - { - "type": "missing", - "loc": ["body", "importance"], - "msg": "Field required", - "input": None, - }, - ] - } - ) | IsDict( - # TODO: remove when deprecating Pydantic v1 - { - "detail": [ - { - "loc": ["body", "item"], - "msg": "field required", - "type": "value_error.missing", - }, - { - "loc": ["body", "user"], - "msg": "field required", - "type": "value_error.missing", - }, - { - "loc": ["body", "importance"], - "msg": "field required", - "type": "value_error.missing", - }, - ] - } - ) - - -def test_post_body_empty_list(client: TestClient): - response = client.put("/items/5", json=[]) - assert response.status_code == 422 - assert response.json() == IsDict( - { - "detail": [ - { - "type": "missing", - "loc": ["body", "item"], - "msg": "Field required", - "input": None, - }, - { - "type": "missing", - "loc": ["body", "user"], - "msg": "Field required", - "input": None, - }, - { - "type": "missing", - "loc": ["body", "importance"], - "msg": "Field required", - "input": None, - }, - ] - } - ) | IsDict( - # TODO: remove when deprecating Pydantic v1 - { - "detail": [ - { - "loc": ["body", "item"], - "msg": "field required", - "type": "value_error.missing", - }, - { - "loc": ["body", "user"], - "msg": "field required", - "type": "value_error.missing", - }, - { - "loc": ["body", "importance"], - "msg": "field required", - "type": "value_error.missing", - }, - ] - } - ) - - -def test_openapi_schema(client: TestClient): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/{item_id}": { - "put": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Update Item", - "operationId": "update_item_items__item_id__put", - "parameters": [ - { - "required": True, - "schema": {"title": "Item Id", "type": "integer"}, - "name": "item_id", - "in": "path", - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Body_update_item_items__item_id__put" - } - } - }, - "required": True, - }, - } - } - }, - "components": { - "schemas": { - "Item": { - "title": "Item", - "required": ["name", "price"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "description": IsDict( - { - "title": "Description", - "anyOf": [{"type": "string"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Description", "type": "string"} - ), - "price": {"title": "Price", "type": "number"}, - "tax": IsDict( - { - "title": "Tax", - "anyOf": [{"type": "number"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Tax", "type": "number"} - ), - }, - }, - "User": { - "title": "User", - "required": ["username"], - "type": "object", - "properties": { - "username": {"title": "Username", "type": "string"}, - "full_name": IsDict( - { - "title": "Full Name", - "anyOf": [{"type": "string"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Full Name", "type": "string"} - ), - }, - }, - "Body_update_item_items__item_id__put": { - "title": "Body_update_item_items__item_id__put", - "required": ["item", "user", "importance"], - "type": "object", - "properties": { - "item": {"$ref": "#/components/schemas/Item"}, - "user": {"$ref": "#/components/schemas/User"}, - "importance": {"title": "Importance", "type": "integer"}, - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] - }, - }, - "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"}, - } - }, - }, - } - }, - } diff --git a/tests/test_tutorial/test_body_multiple_params/test_tutorial003_an_py310.py b/tests/test_tutorial/test_body_multiple_params/test_tutorial003_an_py310.py deleted file mode 100644 index f46430fb5..000000000 --- a/tests/test_tutorial/test_body_multiple_params/test_tutorial003_an_py310.py +++ /dev/null @@ -1,279 +0,0 @@ -import pytest -from dirty_equals import IsDict -from fastapi.testclient import TestClient - -from ...utils import needs_py310 - - -@pytest.fixture(name="client") -def get_client(): - from docs_src.body_multiple_params.tutorial003_an_py310 import app - - client = TestClient(app) - return client - - -@needs_py310 -def test_post_body_valid(client: TestClient): - response = client.put( - "/items/5", - json={ - "importance": 2, - "item": {"name": "Foo", "price": 50.5}, - "user": {"username": "Dave"}, - }, - ) - assert response.status_code == 200 - assert response.json() == { - "item_id": 5, - "importance": 2, - "item": { - "name": "Foo", - "price": 50.5, - "description": None, - "tax": None, - }, - "user": {"username": "Dave", "full_name": None}, - } - - -@needs_py310 -def test_post_body_no_data(client: TestClient): - response = client.put("/items/5", json=None) - assert response.status_code == 422 - assert response.json() == IsDict( - { - "detail": [ - { - "type": "missing", - "loc": ["body", "item"], - "msg": "Field required", - "input": None, - }, - { - "type": "missing", - "loc": ["body", "user"], - "msg": "Field required", - "input": None, - }, - { - "type": "missing", - "loc": ["body", "importance"], - "msg": "Field required", - "input": None, - }, - ] - } - ) | IsDict( - # TODO: remove when deprecating Pydantic v1 - { - "detail": [ - { - "loc": ["body", "item"], - "msg": "field required", - "type": "value_error.missing", - }, - { - "loc": ["body", "user"], - "msg": "field required", - "type": "value_error.missing", - }, - { - "loc": ["body", "importance"], - "msg": "field required", - "type": "value_error.missing", - }, - ] - } - ) - - -@needs_py310 -def test_post_body_empty_list(client: TestClient): - response = client.put("/items/5", json=[]) - assert response.status_code == 422 - assert response.json() == IsDict( - { - "detail": [ - { - "type": "missing", - "loc": ["body", "item"], - "msg": "Field required", - "input": None, - }, - { - "type": "missing", - "loc": ["body", "user"], - "msg": "Field required", - "input": None, - }, - { - "type": "missing", - "loc": ["body", "importance"], - "msg": "Field required", - "input": None, - }, - ] - } - ) | IsDict( - # TODO: remove when deprecating Pydantic v1 - { - "detail": [ - { - "loc": ["body", "item"], - "msg": "field required", - "type": "value_error.missing", - }, - { - "loc": ["body", "user"], - "msg": "field required", - "type": "value_error.missing", - }, - { - "loc": ["body", "importance"], - "msg": "field required", - "type": "value_error.missing", - }, - ] - } - ) - - -@needs_py310 -def test_openapi_schema(client: TestClient): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/{item_id}": { - "put": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Update Item", - "operationId": "update_item_items__item_id__put", - "parameters": [ - { - "required": True, - "schema": {"title": "Item Id", "type": "integer"}, - "name": "item_id", - "in": "path", - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Body_update_item_items__item_id__put" - } - } - }, - "required": True, - }, - } - } - }, - "components": { - "schemas": { - "Item": { - "title": "Item", - "required": ["name", "price"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "description": IsDict( - { - "title": "Description", - "anyOf": [{"type": "string"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Description", "type": "string"} - ), - "price": {"title": "Price", "type": "number"}, - "tax": IsDict( - { - "title": "Tax", - "anyOf": [{"type": "number"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Tax", "type": "number"} - ), - }, - }, - "User": { - "title": "User", - "required": ["username"], - "type": "object", - "properties": { - "username": {"title": "Username", "type": "string"}, - "full_name": IsDict( - { - "title": "Full Name", - "anyOf": [{"type": "string"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Full Name", "type": "string"} - ), - }, - }, - "Body_update_item_items__item_id__put": { - "title": "Body_update_item_items__item_id__put", - "required": ["item", "user", "importance"], - "type": "object", - "properties": { - "item": {"$ref": "#/components/schemas/Item"}, - "user": {"$ref": "#/components/schemas/User"}, - "importance": {"title": "Importance", "type": "integer"}, - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] - }, - }, - "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"}, - } - }, - }, - } - }, - } diff --git a/tests/test_tutorial/test_body_multiple_params/test_tutorial003_an_py39.py b/tests/test_tutorial/test_body_multiple_params/test_tutorial003_an_py39.py deleted file mode 100644 index 29071cddc..000000000 --- a/tests/test_tutorial/test_body_multiple_params/test_tutorial003_an_py39.py +++ /dev/null @@ -1,279 +0,0 @@ -import pytest -from dirty_equals import IsDict -from fastapi.testclient import TestClient - -from ...utils import needs_py39 - - -@pytest.fixture(name="client") -def get_client(): - from docs_src.body_multiple_params.tutorial003_an_py39 import app - - client = TestClient(app) - return client - - -@needs_py39 -def test_post_body_valid(client: TestClient): - response = client.put( - "/items/5", - json={ - "importance": 2, - "item": {"name": "Foo", "price": 50.5}, - "user": {"username": "Dave"}, - }, - ) - assert response.status_code == 200 - assert response.json() == { - "item_id": 5, - "importance": 2, - "item": { - "name": "Foo", - "price": 50.5, - "description": None, - "tax": None, - }, - "user": {"username": "Dave", "full_name": None}, - } - - -@needs_py39 -def test_post_body_no_data(client: TestClient): - response = client.put("/items/5", json=None) - assert response.status_code == 422 - assert response.json() == IsDict( - { - "detail": [ - { - "type": "missing", - "loc": ["body", "item"], - "msg": "Field required", - "input": None, - }, - { - "type": "missing", - "loc": ["body", "user"], - "msg": "Field required", - "input": None, - }, - { - "type": "missing", - "loc": ["body", "importance"], - "msg": "Field required", - "input": None, - }, - ] - } - ) | IsDict( - # TODO: remove when deprecating Pydantic v1 - { - "detail": [ - { - "loc": ["body", "item"], - "msg": "field required", - "type": "value_error.missing", - }, - { - "loc": ["body", "user"], - "msg": "field required", - "type": "value_error.missing", - }, - { - "loc": ["body", "importance"], - "msg": "field required", - "type": "value_error.missing", - }, - ] - } - ) - - -@needs_py39 -def test_post_body_empty_list(client: TestClient): - response = client.put("/items/5", json=[]) - assert response.status_code == 422 - assert response.json() == IsDict( - { - "detail": [ - { - "type": "missing", - "loc": ["body", "item"], - "msg": "Field required", - "input": None, - }, - { - "type": "missing", - "loc": ["body", "user"], - "msg": "Field required", - "input": None, - }, - { - "type": "missing", - "loc": ["body", "importance"], - "msg": "Field required", - "input": None, - }, - ] - } - ) | IsDict( - # TODO: remove when deprecating Pydantic v1 - { - "detail": [ - { - "loc": ["body", "item"], - "msg": "field required", - "type": "value_error.missing", - }, - { - "loc": ["body", "user"], - "msg": "field required", - "type": "value_error.missing", - }, - { - "loc": ["body", "importance"], - "msg": "field required", - "type": "value_error.missing", - }, - ] - } - ) - - -@needs_py39 -def test_openapi_schema(client: TestClient): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/{item_id}": { - "put": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Update Item", - "operationId": "update_item_items__item_id__put", - "parameters": [ - { - "required": True, - "schema": {"title": "Item Id", "type": "integer"}, - "name": "item_id", - "in": "path", - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Body_update_item_items__item_id__put" - } - } - }, - "required": True, - }, - } - } - }, - "components": { - "schemas": { - "Item": { - "title": "Item", - "required": ["name", "price"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "description": IsDict( - { - "title": "Description", - "anyOf": [{"type": "string"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Description", "type": "string"} - ), - "price": {"title": "Price", "type": "number"}, - "tax": IsDict( - { - "title": "Tax", - "anyOf": [{"type": "number"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Tax", "type": "number"} - ), - }, - }, - "User": { - "title": "User", - "required": ["username"], - "type": "object", - "properties": { - "username": {"title": "Username", "type": "string"}, - "full_name": IsDict( - { - "title": "Full Name", - "anyOf": [{"type": "string"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Full Name", "type": "string"} - ), - }, - }, - "Body_update_item_items__item_id__put": { - "title": "Body_update_item_items__item_id__put", - "required": ["item", "user", "importance"], - "type": "object", - "properties": { - "item": {"$ref": "#/components/schemas/Item"}, - "user": {"$ref": "#/components/schemas/User"}, - "importance": {"title": "Importance", "type": "integer"}, - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] - }, - }, - "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"}, - } - }, - }, - } - }, - } diff --git a/tests/test_tutorial/test_body_multiple_params/test_tutorial003_py310.py b/tests/test_tutorial/test_body_multiple_params/test_tutorial003_py310.py deleted file mode 100644 index 133afe9b5..000000000 --- a/tests/test_tutorial/test_body_multiple_params/test_tutorial003_py310.py +++ /dev/null @@ -1,279 +0,0 @@ -import pytest -from dirty_equals import IsDict -from fastapi.testclient import TestClient - -from ...utils import needs_py310 - - -@pytest.fixture(name="client") -def get_client(): - from docs_src.body_multiple_params.tutorial003_py310 import app - - client = TestClient(app) - return client - - -@needs_py310 -def test_post_body_valid(client: TestClient): - response = client.put( - "/items/5", - json={ - "importance": 2, - "item": {"name": "Foo", "price": 50.5}, - "user": {"username": "Dave"}, - }, - ) - assert response.status_code == 200 - assert response.json() == { - "item_id": 5, - "importance": 2, - "item": { - "name": "Foo", - "price": 50.5, - "description": None, - "tax": None, - }, - "user": {"username": "Dave", "full_name": None}, - } - - -@needs_py310 -def test_post_body_no_data(client: TestClient): - response = client.put("/items/5", json=None) - assert response.status_code == 422 - assert response.json() == IsDict( - { - "detail": [ - { - "type": "missing", - "loc": ["body", "item"], - "msg": "Field required", - "input": None, - }, - { - "type": "missing", - "loc": ["body", "user"], - "msg": "Field required", - "input": None, - }, - { - "type": "missing", - "loc": ["body", "importance"], - "msg": "Field required", - "input": None, - }, - ] - } - ) | IsDict( - # TODO: remove when deprecating Pydantic v1 - { - "detail": [ - { - "loc": ["body", "item"], - "msg": "field required", - "type": "value_error.missing", - }, - { - "loc": ["body", "user"], - "msg": "field required", - "type": "value_error.missing", - }, - { - "loc": ["body", "importance"], - "msg": "field required", - "type": "value_error.missing", - }, - ] - } - ) - - -@needs_py310 -def test_post_body_empty_list(client: TestClient): - response = client.put("/items/5", json=[]) - assert response.status_code == 422 - assert response.json() == IsDict( - { - "detail": [ - { - "type": "missing", - "loc": ["body", "item"], - "msg": "Field required", - "input": None, - }, - { - "type": "missing", - "loc": ["body", "user"], - "msg": "Field required", - "input": None, - }, - { - "type": "missing", - "loc": ["body", "importance"], - "msg": "Field required", - "input": None, - }, - ] - } - ) | IsDict( - # TODO: remove when deprecating Pydantic v1 - { - "detail": [ - { - "loc": ["body", "item"], - "msg": "field required", - "type": "value_error.missing", - }, - { - "loc": ["body", "user"], - "msg": "field required", - "type": "value_error.missing", - }, - { - "loc": ["body", "importance"], - "msg": "field required", - "type": "value_error.missing", - }, - ] - } - ) - - -@needs_py310 -def test_openapi_schema(client: TestClient): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/{item_id}": { - "put": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Update Item", - "operationId": "update_item_items__item_id__put", - "parameters": [ - { - "required": True, - "schema": {"title": "Item Id", "type": "integer"}, - "name": "item_id", - "in": "path", - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Body_update_item_items__item_id__put" - } - } - }, - "required": True, - }, - } - } - }, - "components": { - "schemas": { - "Item": { - "title": "Item", - "required": ["name", "price"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "description": IsDict( - { - "title": "Description", - "anyOf": [{"type": "string"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Description", "type": "string"} - ), - "price": {"title": "Price", "type": "number"}, - "tax": IsDict( - { - "title": "Tax", - "anyOf": [{"type": "number"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Tax", "type": "number"} - ), - }, - }, - "User": { - "title": "User", - "required": ["username"], - "type": "object", - "properties": { - "username": {"title": "Username", "type": "string"}, - "full_name": IsDict( - { - "title": "Full Name", - "anyOf": [{"type": "string"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Full Name", "type": "string"} - ), - }, - }, - "Body_update_item_items__item_id__put": { - "title": "Body_update_item_items__item_id__put", - "required": ["item", "user", "importance"], - "type": "object", - "properties": { - "item": {"$ref": "#/components/schemas/Item"}, - "user": {"$ref": "#/components/schemas/User"}, - "importance": {"title": "Importance", "type": "integer"}, - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] - }, - }, - "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"}, - } - }, - }, - } - }, - } diff --git a/tests/test_tutorial/test_configure_swagger_ui/test_tutorial001.py b/tests/test_tutorial/test_configure_swagger_ui/test_tutorial001.py index 72db54bd2..a04dba219 100644 --- a/tests/test_tutorial/test_configure_swagger_ui/test_tutorial001.py +++ b/tests/test_tutorial/test_configure_swagger_ui/test_tutorial001.py @@ -8,31 +8,31 @@ client = TestClient(app) def test_swagger_ui(): response = client.get("/docs") assert response.status_code == 200, response.text - assert ( - '"syntaxHighlight": false' in response.text - ), "syntaxHighlight should be included and converted to JSON" - assert ( - '"dom_id": "#swagger-ui"' in response.text - ), "default configs should be preserved" + assert '"syntaxHighlight": false' in response.text, ( + "syntaxHighlight should be included and converted to JSON" + ) + assert '"dom_id": "#swagger-ui"' in response.text, ( + "default configs should be preserved" + ) assert "presets: [" in response.text, "default configs should be preserved" - assert ( - "SwaggerUIBundle.presets.apis," in response.text - ), "default configs should be preserved" - assert ( - "SwaggerUIBundle.SwaggerUIStandalonePreset" in response.text - ), "default configs should be preserved" - assert ( - '"layout": "BaseLayout",' in response.text - ), "default configs should be preserved" - assert ( - '"deepLinking": true,' in response.text - ), "default configs should be preserved" - assert ( - '"showExtensions": true,' in response.text - ), "default configs should be preserved" - assert ( - '"showCommonExtensions": true,' in response.text - ), "default configs should be preserved" + assert "SwaggerUIBundle.presets.apis," in response.text, ( + "default configs should be preserved" + ) + assert "SwaggerUIBundle.SwaggerUIStandalonePreset" in response.text, ( + "default configs should be preserved" + ) + assert '"layout": "BaseLayout",' in response.text, ( + "default configs should be preserved" + ) + assert '"deepLinking": true,' in response.text, ( + "default configs should be preserved" + ) + assert '"showExtensions": true,' in response.text, ( + "default configs should be preserved" + ) + assert '"showCommonExtensions": true,' in response.text, ( + "default configs should be preserved" + ) def test_get_users(): diff --git a/tests/test_tutorial/test_configure_swagger_ui/test_tutorial002.py b/tests/test_tutorial/test_configure_swagger_ui/test_tutorial002.py index 166901188..ea56b6f21 100644 --- a/tests/test_tutorial/test_configure_swagger_ui/test_tutorial002.py +++ b/tests/test_tutorial/test_configure_swagger_ui/test_tutorial002.py @@ -8,34 +8,34 @@ client = TestClient(app) def test_swagger_ui(): response = client.get("/docs") assert response.status_code == 200, response.text - assert ( - '"syntaxHighlight": false' not in response.text - ), "not used parameters should not be included" - assert ( - '"syntaxHighlight.theme": "obsidian"' in response.text - ), "parameters with middle dots should be included in a JSON compatible way" - assert ( - '"dom_id": "#swagger-ui"' in response.text - ), "default configs should be preserved" + assert '"syntaxHighlight": false' not in response.text, ( + "not used parameters should not be included" + ) + assert '"syntaxHighlight": {"theme": "obsidian"}' in response.text, ( + "parameters with middle dots should be included in a JSON compatible way" + ) + assert '"dom_id": "#swagger-ui"' in response.text, ( + "default configs should be preserved" + ) assert "presets: [" in response.text, "default configs should be preserved" - assert ( - "SwaggerUIBundle.presets.apis," in response.text - ), "default configs should be preserved" - assert ( - "SwaggerUIBundle.SwaggerUIStandalonePreset" in response.text - ), "default configs should be preserved" - assert ( - '"layout": "BaseLayout",' in response.text - ), "default configs should be preserved" - assert ( - '"deepLinking": true,' in response.text - ), "default configs should be preserved" - assert ( - '"showExtensions": true,' in response.text - ), "default configs should be preserved" - assert ( - '"showCommonExtensions": true,' in response.text - ), "default configs should be preserved" + assert "SwaggerUIBundle.presets.apis," in response.text, ( + "default configs should be preserved" + ) + assert "SwaggerUIBundle.SwaggerUIStandalonePreset" in response.text, ( + "default configs should be preserved" + ) + assert '"layout": "BaseLayout",' in response.text, ( + "default configs should be preserved" + ) + assert '"deepLinking": true,' in response.text, ( + "default configs should be preserved" + ) + assert '"showExtensions": true,' in response.text, ( + "default configs should be preserved" + ) + assert '"showCommonExtensions": true,' in response.text, ( + "default configs should be preserved" + ) def test_get_users(): diff --git a/tests/test_tutorial/test_configure_swagger_ui/test_tutorial003.py b/tests/test_tutorial/test_configure_swagger_ui/test_tutorial003.py index 187e89ace..926bbb14f 100644 --- a/tests/test_tutorial/test_configure_swagger_ui/test_tutorial003.py +++ b/tests/test_tutorial/test_configure_swagger_ui/test_tutorial003.py @@ -8,34 +8,34 @@ client = TestClient(app) def test_swagger_ui(): response = client.get("/docs") assert response.status_code == 200, response.text - assert ( - '"deepLinking": false,' in response.text - ), "overridden configs should be preserved" - assert ( - '"deepLinking": true' not in response.text - ), "overridden configs should not include the old value" - assert ( - '"syntaxHighlight": false' not in response.text - ), "not used parameters should not be included" - assert ( - '"dom_id": "#swagger-ui"' in response.text - ), "default configs should be preserved" + assert '"deepLinking": false,' in response.text, ( + "overridden configs should be preserved" + ) + assert '"deepLinking": true' not in response.text, ( + "overridden configs should not include the old value" + ) + assert '"syntaxHighlight": false' not in response.text, ( + "not used parameters should not be included" + ) + assert '"dom_id": "#swagger-ui"' in response.text, ( + "default configs should be preserved" + ) assert "presets: [" in response.text, "default configs should be preserved" - assert ( - "SwaggerUIBundle.presets.apis," in response.text - ), "default configs should be preserved" - assert ( - "SwaggerUIBundle.SwaggerUIStandalonePreset" in response.text - ), "default configs should be preserved" - assert ( - '"layout": "BaseLayout",' in response.text - ), "default configs should be preserved" - assert ( - '"showExtensions": true,' in response.text - ), "default configs should be preserved" - assert ( - '"showCommonExtensions": true,' in response.text - ), "default configs should be preserved" + assert "SwaggerUIBundle.presets.apis," in response.text, ( + "default configs should be preserved" + ) + assert "SwaggerUIBundle.SwaggerUIStandalonePreset" in response.text, ( + "default configs should be preserved" + ) + assert '"layout": "BaseLayout",' in response.text, ( + "default configs should be preserved" + ) + assert '"showExtensions": true,' in response.text, ( + "default configs should be preserved" + ) + assert '"showCommonExtensions": true,' in response.text, ( + "default configs should be preserved" + ) def test_get_users(): diff --git a/tests/test_tutorial/test_cookie_param_models/test_tutorial002.py b/tests/test_tutorial/test_cookie_param_models/test_tutorial002.py index 30adadc8a..cef6f6630 100644 --- a/tests/test_tutorial/test_cookie_param_models/test_tutorial002.py +++ b/tests/test_tutorial/test_cookie_param_models/test_tutorial002.py @@ -5,7 +5,13 @@ from dirty_equals import IsDict from fastapi.testclient import TestClient from inline_snapshot import snapshot -from tests.utils import needs_py39, needs_py310, needs_pydanticv1, needs_pydanticv2 +from tests.utils import ( + needs_py39, + needs_py310, + needs_pydanticv1, + needs_pydanticv2, + pydantic_snapshot, +) @pytest.fixture( @@ -59,8 +65,8 @@ def test_cookie_param_model_defaults(client: TestClient): def test_cookie_param_model_invalid(client: TestClient): response = client.get("/items/") assert response.status_code == 422 - assert response.json() == snapshot( - IsDict( + assert response.json() == pydantic_snapshot( + v2=snapshot( { "detail": [ { @@ -71,9 +77,8 @@ def test_cookie_param_model_invalid(client: TestClient): } ] } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 + ), + v1=snapshot( { "detail": [ { @@ -83,7 +88,7 @@ def test_cookie_param_model_invalid(client: TestClient): } ] } - ) + ), ) @@ -144,18 +149,23 @@ def test_openapi_schema(client: TestClient): "name": "fatebook_tracker", "in": "cookie", "required": False, - "schema": IsDict( - { - "anyOf": [{"type": "string"}, {"type": "null"}], - "title": "Fatebook Tracker", - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - { - "type": "string", - "title": "Fatebook Tracker", - } + "schema": pydantic_snapshot( + v2=snapshot( + { + "anyOf": [ + {"type": "string"}, + {"type": "null"}, + ], + "title": "Fatebook Tracker", + } + ), + v1=snapshot( + # TODO: remove when deprecating Pydantic v1 + { + "type": "string", + "title": "Fatebook Tracker", + } + ), ), }, { diff --git a/tests/test_tutorial/test_custom_docs_ui/test_tutorial001.py b/tests/test_tutorial/test_custom_docs_ui/test_tutorial001.py index aff070d74..cb8e8c224 100644 --- a/tests/test_tutorial/test_custom_docs_ui/test_tutorial001.py +++ b/tests/test_tutorial/test_custom_docs_ui/test_tutorial001.py @@ -33,7 +33,7 @@ def test_swagger_ui_oauth2_redirect_html(client: TestClient): def test_redoc_html(client: TestClient): response = client.get("/redoc") assert response.status_code == 200, response.text - assert "https://unpkg.com/redoc@next/bundles/redoc.standalone.js" in response.text + assert "https://unpkg.com/redoc@2/bundles/redoc.standalone.js" in response.text def test_api(client: TestClient): diff --git a/tests/test_tutorial/test_custom_request_and_route/test_tutorial002.py b/tests/test_tutorial/test_custom_request_and_route/test_tutorial002.py index 6f7355aaa..647f1c5dd 100644 --- a/tests/test_tutorial/test_custom_request_and_route/test_tutorial002.py +++ b/tests/test_tutorial/test_custom_request_and_route/test_tutorial002.py @@ -1,4 +1,4 @@ -from dirty_equals import IsDict +from dirty_equals import IsDict, IsOneOf from fastapi.testclient import TestClient from docs_src.custom_request_and_route.tutorial002 import app @@ -24,14 +24,16 @@ def test_exception_handler_body_access(): "input": {"numbers": [1, 2, 3]}, } ], - "body": '{"numbers": [1, 2, 3]}', + # httpx 0.28.0 switches to compact JSON https://github.com/encode/httpx/issues/3363 + "body": IsOneOf('{"numbers": [1, 2, 3]}', '{"numbers":[1,2,3]}'), } } ) | IsDict( # TODO: remove when deprecating Pydantic v1 { "detail": { - "body": '{"numbers": [1, 2, 3]}', + # httpx 0.28.0 switches to compact JSON https://github.com/encode/httpx/issues/3363 + "body": IsOneOf('{"numbers": [1, 2, 3]}', '{"numbers":[1,2,3]}'), "errors": [ { "loc": ["body"], diff --git a/tests/test_tutorial/test_header_param_models/test_tutorial001.py b/tests/test_tutorial/test_header_param_models/test_tutorial001.py index 06b2404cf..bc876897b 100644 --- a/tests/test_tutorial/test_header_param_models/test_tutorial001.py +++ b/tests/test_tutorial/test_header_param_models/test_tutorial001.py @@ -129,13 +129,13 @@ def test_openapi_schema(client: TestClient): "schema": {"type": "string", "title": "Host"}, }, { - "name": "save_data", + "name": "save-data", "in": "header", "required": True, "schema": {"type": "boolean", "title": "Save Data"}, }, { - "name": "if_modified_since", + "name": "if-modified-since", "in": "header", "required": False, "schema": IsDict( @@ -171,7 +171,7 @@ def test_openapi_schema(client: TestClient): ), }, { - "name": "x_tag", + "name": "x-tag", "in": "header", "required": False, "schema": { diff --git a/tests/test_tutorial/test_header_param_models/test_tutorial002.py b/tests/test_tutorial/test_header_param_models/test_tutorial002.py index e07655a0c..0615521c4 100644 --- a/tests/test_tutorial/test_header_param_models/test_tutorial002.py +++ b/tests/test_tutorial/test_header_param_models/test_tutorial002.py @@ -140,13 +140,13 @@ def test_openapi_schema(client: TestClient): "schema": {"type": "string", "title": "Host"}, }, { - "name": "save_data", + "name": "save-data", "in": "header", "required": True, "schema": {"type": "boolean", "title": "Save Data"}, }, { - "name": "if_modified_since", + "name": "if-modified-since", "in": "header", "required": False, "schema": IsDict( @@ -182,7 +182,7 @@ def test_openapi_schema(client: TestClient): ), }, { - "name": "x_tag", + "name": "x-tag", "in": "header", "required": False, "schema": { diff --git a/tests/test_tutorial/test_header_param_models/test_tutorial003.py b/tests/test_tutorial/test_header_param_models/test_tutorial003.py new file mode 100644 index 000000000..60940e1da --- /dev/null +++ b/tests/test_tutorial/test_header_param_models/test_tutorial003.py @@ -0,0 +1,285 @@ +import importlib + +import pytest +from dirty_equals import IsDict +from fastapi.testclient import TestClient +from inline_snapshot import snapshot + +from tests.utils import needs_py39, needs_py310 + + +@pytest.fixture( + name="client", + params=[ + "tutorial003", + pytest.param("tutorial003_py39", marks=needs_py39), + pytest.param("tutorial003_py310", marks=needs_py310), + "tutorial003_an", + pytest.param("tutorial003_an_py39", marks=needs_py39), + pytest.param("tutorial003_an_py310", marks=needs_py310), + ], +) +def get_client(request: pytest.FixtureRequest): + mod = importlib.import_module(f"docs_src.header_param_models.{request.param}") + + client = TestClient(mod.app) + return client + + +def test_header_param_model(client: TestClient): + response = client.get( + "/items/", + headers=[ + ("save_data", "true"), + ("if_modified_since", "yesterday"), + ("traceparent", "123"), + ("x_tag", "one"), + ("x_tag", "two"), + ], + ) + assert response.status_code == 200 + assert response.json() == { + "host": "testserver", + "save_data": True, + "if_modified_since": "yesterday", + "traceparent": "123", + "x_tag": ["one", "two"], + } + + +def test_header_param_model_no_underscore(client: TestClient): + response = client.get( + "/items/", + headers=[ + ("save-data", "true"), + ("if-modified-since", "yesterday"), + ("traceparent", "123"), + ("x-tag", "one"), + ("x-tag", "two"), + ], + ) + assert response.status_code == 422 + assert response.json() == snapshot( + { + "detail": [ + IsDict( + { + "type": "missing", + "loc": ["header", "save_data"], + "msg": "Field required", + "input": { + "host": "testserver", + "traceparent": "123", + "x_tag": [], + "accept": "*/*", + "accept-encoding": "gzip, deflate", + "connection": "keep-alive", + "user-agent": "testclient", + "save-data": "true", + "if-modified-since": "yesterday", + "x-tag": "two", + }, + } + ) + | IsDict( + # TODO: remove when deprecating Pydantic v1 + { + "type": "value_error.missing", + "loc": ["header", "save_data"], + "msg": "field required", + } + ) + ] + } + ) + + +def test_header_param_model_defaults(client: TestClient): + response = client.get("/items/", headers=[("save_data", "true")]) + assert response.status_code == 200 + assert response.json() == { + "host": "testserver", + "save_data": True, + "if_modified_since": None, + "traceparent": None, + "x_tag": [], + } + + +def test_header_param_model_invalid(client: TestClient): + response = client.get("/items/") + assert response.status_code == 422 + assert response.json() == snapshot( + { + "detail": [ + IsDict( + { + "type": "missing", + "loc": ["header", "save_data"], + "msg": "Field required", + "input": { + "x_tag": [], + "host": "testserver", + "accept": "*/*", + "accept-encoding": "gzip, deflate", + "connection": "keep-alive", + "user-agent": "testclient", + }, + } + ) + | IsDict( + # TODO: remove when deprecating Pydantic v1 + { + "type": "value_error.missing", + "loc": ["header", "save_data"], + "msg": "field required", + } + ) + ] + } + ) + + +def test_header_param_model_extra(client: TestClient): + response = client.get( + "/items/", headers=[("save_data", "true"), ("tool", "plumbus")] + ) + assert response.status_code == 200, response.text + assert response.json() == snapshot( + { + "host": "testserver", + "save_data": True, + "if_modified_since": None, + "traceparent": None, + "x_tag": [], + } + ) + + +def test_openapi_schema(client: TestClient): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "summary": "Read Items", + "operationId": "read_items_items__get", + "parameters": [ + { + "name": "host", + "in": "header", + "required": True, + "schema": {"type": "string", "title": "Host"}, + }, + { + "name": "save_data", + "in": "header", + "required": True, + "schema": {"type": "boolean", "title": "Save Data"}, + }, + { + "name": "if_modified_since", + "in": "header", + "required": False, + "schema": IsDict( + { + "anyOf": [{"type": "string"}, {"type": "null"}], + "title": "If Modified Since", + } + ) + | IsDict( + # TODO: remove when deprecating Pydantic v1 + { + "type": "string", + "title": "If Modified Since", + } + ), + }, + { + "name": "traceparent", + "in": "header", + "required": False, + "schema": IsDict( + { + "anyOf": [{"type": "string"}, {"type": "null"}], + "title": "Traceparent", + } + ) + | IsDict( + # TODO: remove when deprecating Pydantic v1 + { + "type": "string", + "title": "Traceparent", + } + ), + }, + { + "name": "x_tag", + "in": "header", + "required": False, + "schema": { + "type": "array", + "items": {"type": "string"}, + "default": [], + "title": "X Tag", + }, + }, + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + } + }, + "components": { + "schemas": { + "HTTPValidationError": { + "properties": { + "detail": { + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + "type": "array", + "title": "Detail", + } + }, + "type": "object", + "title": "HTTPValidationError", + }, + "ValidationError": { + "properties": { + "loc": { + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + "type": "array", + "title": "Location", + }, + "msg": {"type": "string", "title": "Message"}, + "type": {"type": "string", "title": "Error Type"}, + }, + "type": "object", + "required": ["loc", "msg", "type"], + "title": "ValidationError", + }, + } + }, + } + ) diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial010.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial010.py index 4f52d6ff7..e08e16963 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial010.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial010.py @@ -1,14 +1,29 @@ +import importlib + import pytest from dirty_equals import IsDict from fastapi._compat import PYDANTIC_VERSION_MINOR_TUPLE from fastapi.testclient import TestClient +from ...utils import needs_py39, needs_py310 + -@pytest.fixture(name="client") -def get_client(): - from docs_src.query_params_str_validations.tutorial010 import app +@pytest.fixture( + name="client", + params=[ + "tutorial010", + pytest.param("tutorial010_py310", marks=needs_py310), + "tutorial010_an", + pytest.param("tutorial010_an_py39", marks=needs_py39), + pytest.param("tutorial010_an_py310", marks=needs_py310), + ], +) +def get_client(request: pytest.FixtureRequest): + mod = importlib.import_module( + f"docs_src.query_params_str_validations.{request.param}" + ) - client = TestClient(app) + client = TestClient(mod.app) return client diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial010_an.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial010_an.py deleted file mode 100644 index 5daca1e70..000000000 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial010_an.py +++ /dev/null @@ -1,168 +0,0 @@ -import pytest -from dirty_equals import IsDict -from fastapi._compat import PYDANTIC_VERSION_MINOR_TUPLE -from fastapi.testclient import TestClient - - -@pytest.fixture(name="client") -def get_client(): - from docs_src.query_params_str_validations.tutorial010_an import app - - client = TestClient(app) - return client - - -def test_query_params_str_validations_no_query(client: TestClient): - response = client.get("/items/") - assert response.status_code == 200 - assert response.json() == {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]} - - -def test_query_params_str_validations_item_query_fixedquery(client: TestClient): - response = client.get("/items/", params={"item-query": "fixedquery"}) - assert response.status_code == 200 - assert response.json() == { - "items": [{"item_id": "Foo"}, {"item_id": "Bar"}], - "q": "fixedquery", - } - - -def test_query_params_str_validations_q_fixedquery(client: TestClient): - response = client.get("/items/", params={"q": "fixedquery"}) - assert response.status_code == 200 - assert response.json() == {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]} - - -def test_query_params_str_validations_item_query_nonregexquery(client: TestClient): - response = client.get("/items/", params={"item-query": "nonregexquery"}) - assert response.status_code == 422 - assert response.json() == IsDict( - { - "detail": [ - { - "type": "string_pattern_mismatch", - "loc": ["query", "item-query"], - "msg": "String should match pattern '^fixedquery$'", - "input": "nonregexquery", - "ctx": {"pattern": "^fixedquery$"}, - } - ] - } - ) | IsDict( - # TODO: remove when deprecating Pydantic v1 - { - "detail": [ - { - "ctx": {"pattern": "^fixedquery$"}, - "loc": ["query", "item-query"], - "msg": 'string does not match regex "^fixedquery$"', - "type": "value_error.str.regex", - } - ] - } - ) - - -def test_openapi_schema(client: TestClient): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - "parameters": [ - { - "description": "Query string for the items to search in the database that have a good match", - "required": False, - "deprecated": True, - "schema": IsDict( - { - "anyOf": [ - { - "type": "string", - "minLength": 3, - "maxLength": 50, - "pattern": "^fixedquery$", - }, - {"type": "null"}, - ], - "title": "Query string", - "description": "Query string for the items to search in the database that have a good match", - # See https://github.com/pydantic/pydantic/blob/80353c29a824c55dea4667b328ba8f329879ac9f/tests/test_fastapi.sh#L25-L34. - **( - {"deprecated": True} - if PYDANTIC_VERSION_MINOR_TUPLE >= (2, 10) - else {} - ), - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - { - "title": "Query string", - "maxLength": 50, - "minLength": 3, - "pattern": "^fixedquery$", - "type": "string", - "description": "Query string for the items to search in the database that have a good match", - } - ), - "name": "item-query", - "in": "query", - } - ], - } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] - }, - }, - "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"}, - } - }, - }, - } - }, - } diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial010_an_py310.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial010_an_py310.py deleted file mode 100644 index 89da4d82e..000000000 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial010_an_py310.py +++ /dev/null @@ -1,175 +0,0 @@ -import pytest -from dirty_equals import IsDict -from fastapi._compat import PYDANTIC_VERSION_MINOR_TUPLE -from fastapi.testclient import TestClient - -from ...utils import needs_py310 - - -@pytest.fixture(name="client") -def get_client(): - from docs_src.query_params_str_validations.tutorial010_an_py310 import app - - client = TestClient(app) - return client - - -@needs_py310 -def test_query_params_str_validations_no_query(client: TestClient): - response = client.get("/items/") - assert response.status_code == 200 - assert response.json() == {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]} - - -@needs_py310 -def test_query_params_str_validations_item_query_fixedquery(client: TestClient): - response = client.get("/items/", params={"item-query": "fixedquery"}) - assert response.status_code == 200 - assert response.json() == { - "items": [{"item_id": "Foo"}, {"item_id": "Bar"}], - "q": "fixedquery", - } - - -@needs_py310 -def test_query_params_str_validations_q_fixedquery(client: TestClient): - response = client.get("/items/", params={"q": "fixedquery"}) - assert response.status_code == 200 - assert response.json() == {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]} - - -@needs_py310 -def test_query_params_str_validations_item_query_nonregexquery(client: TestClient): - response = client.get("/items/", params={"item-query": "nonregexquery"}) - assert response.status_code == 422 - assert response.json() == IsDict( - { - "detail": [ - { - "type": "string_pattern_mismatch", - "loc": ["query", "item-query"], - "msg": "String should match pattern '^fixedquery$'", - "input": "nonregexquery", - "ctx": {"pattern": "^fixedquery$"}, - } - ] - } - ) | IsDict( - # TODO: remove when deprecating Pydantic v1 - { - "detail": [ - { - "ctx": {"pattern": "^fixedquery$"}, - "loc": ["query", "item-query"], - "msg": 'string does not match regex "^fixedquery$"', - "type": "value_error.str.regex", - } - ] - } - ) - - -@needs_py310 -def test_openapi_schema(client: TestClient): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - "parameters": [ - { - "description": "Query string for the items to search in the database that have a good match", - "required": False, - "deprecated": True, - "schema": IsDict( - { - "anyOf": [ - { - "type": "string", - "minLength": 3, - "maxLength": 50, - "pattern": "^fixedquery$", - }, - {"type": "null"}, - ], - "title": "Query string", - "description": "Query string for the items to search in the database that have a good match", - # See https://github.com/pydantic/pydantic/blob/80353c29a824c55dea4667b328ba8f329879ac9f/tests/test_fastapi.sh#L25-L34. - **( - {"deprecated": True} - if PYDANTIC_VERSION_MINOR_TUPLE >= (2, 10) - else {} - ), - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - { - "title": "Query string", - "maxLength": 50, - "minLength": 3, - "pattern": "^fixedquery$", - "type": "string", - "description": "Query string for the items to search in the database that have a good match", - } - ), - "name": "item-query", - "in": "query", - } - ], - } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] - }, - }, - "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"}, - } - }, - }, - } - }, - } diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial010_an_py39.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial010_an_py39.py deleted file mode 100644 index f5f692b06..000000000 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial010_an_py39.py +++ /dev/null @@ -1,175 +0,0 @@ -import pytest -from dirty_equals import IsDict -from fastapi._compat import PYDANTIC_VERSION_MINOR_TUPLE -from fastapi.testclient import TestClient - -from ...utils import needs_py39 - - -@pytest.fixture(name="client") -def get_client(): - from docs_src.query_params_str_validations.tutorial010_an_py39 import app - - client = TestClient(app) - return client - - -@needs_py39 -def test_query_params_str_validations_no_query(client: TestClient): - response = client.get("/items/") - assert response.status_code == 200 - assert response.json() == {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]} - - -@needs_py39 -def test_query_params_str_validations_item_query_fixedquery(client: TestClient): - response = client.get("/items/", params={"item-query": "fixedquery"}) - assert response.status_code == 200 - assert response.json() == { - "items": [{"item_id": "Foo"}, {"item_id": "Bar"}], - "q": "fixedquery", - } - - -@needs_py39 -def test_query_params_str_validations_q_fixedquery(client: TestClient): - response = client.get("/items/", params={"q": "fixedquery"}) - assert response.status_code == 200 - assert response.json() == {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]} - - -@needs_py39 -def test_query_params_str_validations_item_query_nonregexquery(client: TestClient): - response = client.get("/items/", params={"item-query": "nonregexquery"}) - assert response.status_code == 422 - assert response.json() == IsDict( - { - "detail": [ - { - "type": "string_pattern_mismatch", - "loc": ["query", "item-query"], - "msg": "String should match pattern '^fixedquery$'", - "input": "nonregexquery", - "ctx": {"pattern": "^fixedquery$"}, - } - ] - } - ) | IsDict( - # TODO: remove when deprecating Pydantic v1 - { - "detail": [ - { - "ctx": {"pattern": "^fixedquery$"}, - "loc": ["query", "item-query"], - "msg": 'string does not match regex "^fixedquery$"', - "type": "value_error.str.regex", - } - ] - } - ) - - -@needs_py39 -def test_openapi_schema(client: TestClient): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - "parameters": [ - { - "description": "Query string for the items to search in the database that have a good match", - "required": False, - "deprecated": True, - "schema": IsDict( - { - "anyOf": [ - { - "type": "string", - "minLength": 3, - "maxLength": 50, - "pattern": "^fixedquery$", - }, - {"type": "null"}, - ], - "title": "Query string", - "description": "Query string for the items to search in the database that have a good match", - # See https://github.com/pydantic/pydantic/blob/80353c29a824c55dea4667b328ba8f329879ac9f/tests/test_fastapi.sh#L25-L34. - **( - {"deprecated": True} - if PYDANTIC_VERSION_MINOR_TUPLE >= (2, 10) - else {} - ), - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - { - "title": "Query string", - "maxLength": 50, - "minLength": 3, - "pattern": "^fixedquery$", - "type": "string", - "description": "Query string for the items to search in the database that have a good match", - } - ), - "name": "item-query", - "in": "query", - } - ], - } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] - }, - }, - "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"}, - } - }, - }, - } - }, - } diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial010_py310.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial010_py310.py deleted file mode 100644 index 5b62c969f..000000000 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial010_py310.py +++ /dev/null @@ -1,175 +0,0 @@ -import pytest -from dirty_equals import IsDict -from fastapi._compat import PYDANTIC_VERSION_MINOR_TUPLE -from fastapi.testclient import TestClient - -from ...utils import needs_py310 - - -@pytest.fixture(name="client") -def get_client(): - from docs_src.query_params_str_validations.tutorial010_py310 import app - - client = TestClient(app) - return client - - -@needs_py310 -def test_query_params_str_validations_no_query(client: TestClient): - response = client.get("/items/") - assert response.status_code == 200 - assert response.json() == {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]} - - -@needs_py310 -def test_query_params_str_validations_item_query_fixedquery(client: TestClient): - response = client.get("/items/", params={"item-query": "fixedquery"}) - assert response.status_code == 200 - assert response.json() == { - "items": [{"item_id": "Foo"}, {"item_id": "Bar"}], - "q": "fixedquery", - } - - -@needs_py310 -def test_query_params_str_validations_q_fixedquery(client: TestClient): - response = client.get("/items/", params={"q": "fixedquery"}) - assert response.status_code == 200 - assert response.json() == {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]} - - -@needs_py310 -def test_query_params_str_validations_item_query_nonregexquery(client: TestClient): - response = client.get("/items/", params={"item-query": "nonregexquery"}) - assert response.status_code == 422 - assert response.json() == IsDict( - { - "detail": [ - { - "type": "string_pattern_mismatch", - "loc": ["query", "item-query"], - "msg": "String should match pattern '^fixedquery$'", - "input": "nonregexquery", - "ctx": {"pattern": "^fixedquery$"}, - } - ] - } - ) | IsDict( - # TODO: remove when deprecating Pydantic v1 - { - "detail": [ - { - "ctx": {"pattern": "^fixedquery$"}, - "loc": ["query", "item-query"], - "msg": 'string does not match regex "^fixedquery$"', - "type": "value_error.str.regex", - } - ] - } - ) - - -@needs_py310 -def test_openapi_schema(client: TestClient): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - "parameters": [ - { - "description": "Query string for the items to search in the database that have a good match", - "required": False, - "deprecated": True, - "schema": IsDict( - { - "anyOf": [ - { - "type": "string", - "minLength": 3, - "maxLength": 50, - "pattern": "^fixedquery$", - }, - {"type": "null"}, - ], - "title": "Query string", - "description": "Query string for the items to search in the database that have a good match", - # See https://github.com/pydantic/pydantic/blob/80353c29a824c55dea4667b328ba8f329879ac9f/tests/test_fastapi.sh#L25-L34. - **( - {"deprecated": True} - if PYDANTIC_VERSION_MINOR_TUPLE >= (2, 10) - else {} - ), - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - { - "title": "Query string", - "maxLength": 50, - "minLength": 3, - "pattern": "^fixedquery$", - "type": "string", - "description": "Query string for the items to search in the database that have a good match", - } - ), - "name": "item-query", - "in": "query", - } - ], - } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] - }, - }, - "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"}, - } - }, - }, - } - }, - } diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial011.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial011.py index 5ba39b05d..f4da25752 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial011.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial011.py @@ -1,26 +1,47 @@ +import importlib + +import pytest from dirty_equals import IsDict from fastapi.testclient import TestClient -from docs_src.query_params_str_validations.tutorial011 import app +from ...utils import needs_py39, needs_py310 + + +@pytest.fixture( + name="client", + params=[ + "tutorial011", + pytest.param("tutorial011_py39", marks=needs_py310), + pytest.param("tutorial011_py310", marks=needs_py310), + "tutorial011_an", + pytest.param("tutorial011_an_py39", marks=needs_py39), + pytest.param("tutorial011_an_py310", marks=needs_py310), + ], +) +def get_client(request: pytest.FixtureRequest): + mod = importlib.import_module( + f"docs_src.query_params_str_validations.{request.param}" + ) -client = TestClient(app) + client = TestClient(mod.app) + return client -def test_multi_query_values(): +def test_multi_query_values(client: TestClient): url = "/items/?q=foo&q=bar" response = client.get(url) assert response.status_code == 200, response.text assert response.json() == {"q": ["foo", "bar"]} -def test_query_no_values(): +def test_query_no_values(client: TestClient): url = "/items/" response = client.get(url) assert response.status_code == 200, response.text assert response.json() == {"q": None} -def test_openapi_schema(): +def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial011_an.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial011_an.py deleted file mode 100644 index 3942ea77a..000000000 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial011_an.py +++ /dev/null @@ -1,108 +0,0 @@ -from dirty_equals import IsDict -from fastapi.testclient import TestClient - -from docs_src.query_params_str_validations.tutorial011_an import app - -client = TestClient(app) - - -def test_multi_query_values(): - url = "/items/?q=foo&q=bar" - response = client.get(url) - assert response.status_code == 200, response.text - assert response.json() == {"q": ["foo", "bar"]} - - -def test_query_no_values(): - url = "/items/" - response = client.get(url) - assert response.status_code == 200, response.text - assert response.json() == {"q": None} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - "parameters": [ - { - "required": False, - "schema": IsDict( - { - "anyOf": [ - {"type": "array", "items": {"type": "string"}}, - {"type": "null"}, - ], - "title": "Q", - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - { - "title": "Q", - "type": "array", - "items": {"type": "string"}, - } - ), - "name": "q", - "in": "query", - } - ], - } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] - }, - }, - "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"}, - } - }, - }, - } - }, - } diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial011_an_py310.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial011_an_py310.py deleted file mode 100644 index f2ec38c95..000000000 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial011_an_py310.py +++ /dev/null @@ -1,118 +0,0 @@ -import pytest -from dirty_equals import IsDict -from fastapi.testclient import TestClient - -from ...utils import needs_py310 - - -@pytest.fixture(name="client") -def get_client(): - from docs_src.query_params_str_validations.tutorial011_an_py310 import app - - client = TestClient(app) - return client - - -@needs_py310 -def test_multi_query_values(client: TestClient): - url = "/items/?q=foo&q=bar" - response = client.get(url) - assert response.status_code == 200, response.text - assert response.json() == {"q": ["foo", "bar"]} - - -@needs_py310 -def test_query_no_values(client: TestClient): - url = "/items/" - response = client.get(url) - assert response.status_code == 200, response.text - assert response.json() == {"q": None} - - -@needs_py310 -def test_openapi_schema(client: TestClient): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - "parameters": [ - { - "required": False, - "schema": IsDict( - { - "anyOf": [ - {"type": "array", "items": {"type": "string"}}, - {"type": "null"}, - ], - "title": "Q", - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - { - "title": "Q", - "type": "array", - "items": {"type": "string"}, - } - ), - "name": "q", - "in": "query", - } - ], - } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] - }, - }, - "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"}, - } - }, - }, - } - }, - } diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial011_an_py39.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial011_an_py39.py deleted file mode 100644 index cd7b15679..000000000 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial011_an_py39.py +++ /dev/null @@ -1,118 +0,0 @@ -import pytest -from dirty_equals import IsDict -from fastapi.testclient import TestClient - -from ...utils import needs_py39 - - -@pytest.fixture(name="client") -def get_client(): - from docs_src.query_params_str_validations.tutorial011_an_py39 import app - - client = TestClient(app) - return client - - -@needs_py39 -def test_multi_query_values(client: TestClient): - url = "/items/?q=foo&q=bar" - response = client.get(url) - assert response.status_code == 200, response.text - assert response.json() == {"q": ["foo", "bar"]} - - -@needs_py39 -def test_query_no_values(client: TestClient): - url = "/items/" - response = client.get(url) - assert response.status_code == 200, response.text - assert response.json() == {"q": None} - - -@needs_py39 -def test_openapi_schema(client: TestClient): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - "parameters": [ - { - "required": False, - "schema": IsDict( - { - "anyOf": [ - {"type": "array", "items": {"type": "string"}}, - {"type": "null"}, - ], - "title": "Q", - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - { - "title": "Q", - "type": "array", - "items": {"type": "string"}, - } - ), - "name": "q", - "in": "query", - } - ], - } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] - }, - }, - "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"}, - } - }, - }, - } - }, - } diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial011_py310.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial011_py310.py deleted file mode 100644 index bdc729516..000000000 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial011_py310.py +++ /dev/null @@ -1,118 +0,0 @@ -import pytest -from dirty_equals import IsDict -from fastapi.testclient import TestClient - -from ...utils import needs_py310 - - -@pytest.fixture(name="client") -def get_client(): - from docs_src.query_params_str_validations.tutorial011_py310 import app - - client = TestClient(app) - return client - - -@needs_py310 -def test_multi_query_values(client: TestClient): - url = "/items/?q=foo&q=bar" - response = client.get(url) - assert response.status_code == 200, response.text - assert response.json() == {"q": ["foo", "bar"]} - - -@needs_py310 -def test_query_no_values(client: TestClient): - url = "/items/" - response = client.get(url) - assert response.status_code == 200, response.text - assert response.json() == {"q": None} - - -@needs_py310 -def test_openapi_schema(client: TestClient): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - "parameters": [ - { - "required": False, - "schema": IsDict( - { - "anyOf": [ - {"type": "array", "items": {"type": "string"}}, - {"type": "null"}, - ], - "title": "Q", - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - { - "title": "Q", - "type": "array", - "items": {"type": "string"}, - } - ), - "name": "q", - "in": "query", - } - ], - } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] - }, - }, - "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"}, - } - }, - }, - } - }, - } diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial011_py39.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial011_py39.py deleted file mode 100644 index 26ac56b2f..000000000 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial011_py39.py +++ /dev/null @@ -1,118 +0,0 @@ -import pytest -from dirty_equals import IsDict -from fastapi.testclient import TestClient - -from ...utils import needs_py39 - - -@pytest.fixture(name="client") -def get_client(): - from docs_src.query_params_str_validations.tutorial011_py39 import app - - client = TestClient(app) - return client - - -@needs_py39 -def test_multi_query_values(client: TestClient): - url = "/items/?q=foo&q=bar" - response = client.get(url) - assert response.status_code == 200, response.text - assert response.json() == {"q": ["foo", "bar"]} - - -@needs_py39 -def test_query_no_values(client: TestClient): - url = "/items/" - response = client.get(url) - assert response.status_code == 200, response.text - assert response.json() == {"q": None} - - -@needs_py39 -def test_openapi_schema(client: TestClient): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - "parameters": [ - { - "required": False, - "schema": IsDict( - { - "anyOf": [ - {"type": "array", "items": {"type": "string"}}, - {"type": "null"}, - ], - "title": "Q", - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - { - "title": "Q", - "type": "array", - "items": {"type": "string"}, - } - ), - "name": "q", - "in": "query", - } - ], - } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] - }, - }, - "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"}, - } - }, - }, - } - }, - } diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial012.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial012.py index 1436db384..549a90519 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial012.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial012.py @@ -1,25 +1,44 @@ +import importlib + +import pytest from fastapi.testclient import TestClient -from docs_src.query_params_str_validations.tutorial012 import app +from ...utils import needs_py39 + + +@pytest.fixture( + name="client", + params=[ + "tutorial012", + pytest.param("tutorial012_py39", marks=needs_py39), + "tutorial012_an", + pytest.param("tutorial012_an_py39", marks=needs_py39), + ], +) +def get_client(request: pytest.FixtureRequest): + mod = importlib.import_module( + f"docs_src.query_params_str_validations.{request.param}" + ) -client = TestClient(app) + client = TestClient(mod.app) + return client -def test_default_query_values(): +def test_default_query_values(client: TestClient): url = "/items/" response = client.get(url) assert response.status_code == 200, response.text assert response.json() == {"q": ["foo", "bar"]} -def test_multi_query_values(): +def test_multi_query_values(client: TestClient): url = "/items/?q=baz&q=foobar" response = client.get(url) assert response.status_code == 200, response.text assert response.json() == {"q": ["baz", "foobar"]} -def test_openapi_schema(): +def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial012_an.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial012_an.py deleted file mode 100644 index 270763f1d..000000000 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial012_an.py +++ /dev/null @@ -1,96 +0,0 @@ -from fastapi.testclient import TestClient - -from docs_src.query_params_str_validations.tutorial012_an import app - -client = TestClient(app) - - -def test_default_query_values(): - url = "/items/" - response = client.get(url) - assert response.status_code == 200, response.text - assert response.json() == {"q": ["foo", "bar"]} - - -def test_multi_query_values(): - url = "/items/?q=baz&q=foobar" - response = client.get(url) - assert response.status_code == 200, response.text - assert response.json() == {"q": ["baz", "foobar"]} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - "parameters": [ - { - "required": False, - "schema": { - "title": "Q", - "type": "array", - "items": {"type": "string"}, - "default": ["foo", "bar"], - }, - "name": "q", - "in": "query", - } - ], - } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] - }, - }, - "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"}, - } - }, - }, - } - }, - } diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial012_an_py39.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial012_an_py39.py deleted file mode 100644 index 548391683..000000000 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial012_an_py39.py +++ /dev/null @@ -1,106 +0,0 @@ -import pytest -from fastapi.testclient import TestClient - -from ...utils import needs_py39 - - -@pytest.fixture(name="client") -def get_client(): - from docs_src.query_params_str_validations.tutorial012_an_py39 import app - - client = TestClient(app) - return client - - -@needs_py39 -def test_default_query_values(client: TestClient): - url = "/items/" - response = client.get(url) - assert response.status_code == 200, response.text - assert response.json() == {"q": ["foo", "bar"]} - - -@needs_py39 -def test_multi_query_values(client: TestClient): - url = "/items/?q=baz&q=foobar" - response = client.get(url) - assert response.status_code == 200, response.text - assert response.json() == {"q": ["baz", "foobar"]} - - -@needs_py39 -def test_openapi_schema(client: TestClient): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - "parameters": [ - { - "required": False, - "schema": { - "title": "Q", - "type": "array", - "items": {"type": "string"}, - "default": ["foo", "bar"], - }, - "name": "q", - "in": "query", - } - ], - } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] - }, - }, - "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"}, - } - }, - }, - } - }, - } diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial012_py39.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial012_py39.py deleted file mode 100644 index e7d745154..000000000 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial012_py39.py +++ /dev/null @@ -1,106 +0,0 @@ -import pytest -from fastapi.testclient import TestClient - -from ...utils import needs_py39 - - -@pytest.fixture(name="client") -def get_client(): - from docs_src.query_params_str_validations.tutorial012_py39 import app - - client = TestClient(app) - return client - - -@needs_py39 -def test_default_query_values(client: TestClient): - url = "/items/" - response = client.get(url) - assert response.status_code == 200, response.text - assert response.json() == {"q": ["foo", "bar"]} - - -@needs_py39 -def test_multi_query_values(client: TestClient): - url = "/items/?q=baz&q=foobar" - response = client.get(url) - assert response.status_code == 200, response.text - assert response.json() == {"q": ["baz", "foobar"]} - - -@needs_py39 -def test_openapi_schema(client: TestClient): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - "parameters": [ - { - "required": False, - "schema": { - "title": "Q", - "type": "array", - "items": {"type": "string"}, - "default": ["foo", "bar"], - }, - "name": "q", - "in": "query", - } - ], - } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] - }, - }, - "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"}, - } - }, - }, - } - }, - } diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial013.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial013.py index 1ba1fdf61..f2f5f7a85 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial013.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial013.py @@ -1,25 +1,43 @@ +import importlib + +import pytest from fastapi.testclient import TestClient -from docs_src.query_params_str_validations.tutorial013 import app +from ...utils import needs_py39 + + +@pytest.fixture( + name="client", + params=[ + "tutorial013", + "tutorial013_an", + pytest.param("tutorial013_an_py39", marks=needs_py39), + ], +) +def get_client(request: pytest.FixtureRequest): + mod = importlib.import_module( + f"docs_src.query_params_str_validations.{request.param}" + ) -client = TestClient(app) + client = TestClient(mod.app) + return client -def test_multi_query_values(): +def test_multi_query_values(client: TestClient): url = "/items/?q=foo&q=bar" response = client.get(url) assert response.status_code == 200, response.text assert response.json() == {"q": ["foo", "bar"]} -def test_query_no_values(): +def test_query_no_values(client: TestClient): url = "/items/" response = client.get(url) assert response.status_code == 200, response.text assert response.json() == {"q": []} -def test_openapi_schema(): +def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial013_an.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial013_an.py deleted file mode 100644 index 343261748..000000000 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial013_an.py +++ /dev/null @@ -1,96 +0,0 @@ -from fastapi.testclient import TestClient - -from docs_src.query_params_str_validations.tutorial013_an import app - -client = TestClient(app) - - -def test_multi_query_values(): - url = "/items/?q=foo&q=bar" - response = client.get(url) - assert response.status_code == 200, response.text - assert response.json() == {"q": ["foo", "bar"]} - - -def test_query_no_values(): - url = "/items/" - response = client.get(url) - assert response.status_code == 200, response.text - assert response.json() == {"q": []} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - "parameters": [ - { - "required": False, - "schema": { - "title": "Q", - "type": "array", - "items": {}, - "default": [], - }, - "name": "q", - "in": "query", - } - ], - } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] - }, - }, - "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"}, - } - }, - }, - } - }, - } diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial013_an_py39.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial013_an_py39.py deleted file mode 100644 index 537d6325b..000000000 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial013_an_py39.py +++ /dev/null @@ -1,106 +0,0 @@ -import pytest -from fastapi.testclient import TestClient - -from ...utils import needs_py39 - - -@pytest.fixture(name="client") -def get_client(): - from docs_src.query_params_str_validations.tutorial013_an_py39 import app - - client = TestClient(app) - return client - - -@needs_py39 -def test_multi_query_values(client: TestClient): - url = "/items/?q=foo&q=bar" - response = client.get(url) - assert response.status_code == 200, response.text - assert response.json() == {"q": ["foo", "bar"]} - - -@needs_py39 -def test_query_no_values(client: TestClient): - url = "/items/" - response = client.get(url) - assert response.status_code == 200, response.text - assert response.json() == {"q": []} - - -@needs_py39 -def test_openapi_schema(client: TestClient): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Read Items", - "operationId": "read_items_items__get", - "parameters": [ - { - "required": False, - "schema": { - "title": "Q", - "type": "array", - "items": {}, - "default": [], - }, - "name": "q", - "in": "query", - } - ], - } - } - }, - "components": { - "schemas": { - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] - }, - }, - "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"}, - } - }, - }, - } - }, - } diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial014.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial014.py index 7bce7590c..edd40bb1a 100644 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial014.py +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial014.py @@ -1,23 +1,43 @@ +import importlib + +import pytest from fastapi.testclient import TestClient -from docs_src.query_params_str_validations.tutorial014 import app +from ...utils import needs_py39, needs_py310 + + +@pytest.fixture( + name="client", + params=[ + "tutorial014", + pytest.param("tutorial014_py310", marks=needs_py310), + "tutorial014_an", + pytest.param("tutorial014_an_py39", marks=needs_py39), + pytest.param("tutorial014_an_py310", marks=needs_py310), + ], +) +def get_client(request: pytest.FixtureRequest): + mod = importlib.import_module( + f"docs_src.query_params_str_validations.{request.param}" + ) -client = TestClient(app) + client = TestClient(mod.app) + return client -def test_hidden_query(): +def test_hidden_query(client: TestClient): response = client.get("/items?hidden_query=somevalue") assert response.status_code == 200, response.text assert response.json() == {"hidden_query": "somevalue"} -def test_no_hidden_query(): +def test_no_hidden_query(client: TestClient): response = client.get("/items") assert response.status_code == 200, response.text assert response.json() == {"hidden_query": "Not found"} -def test_openapi_schema(): +def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial014_an.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial014_an.py deleted file mode 100644 index 2182e87b7..000000000 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial014_an.py +++ /dev/null @@ -1,81 +0,0 @@ -from fastapi.testclient import TestClient - -from docs_src.query_params_str_validations.tutorial014_an import app - -client = TestClient(app) - - -def test_hidden_query(): - response = client.get("/items?hidden_query=somevalue") - assert response.status_code == 200, response.text - assert response.json() == {"hidden_query": "somevalue"} - - -def test_no_hidden_query(): - response = client.get("/items") - assert response.status_code == 200, response.text - assert response.json() == {"hidden_query": "Not found"} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "summary": "Read Items", - "operationId": "read_items_items__get", - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - } - }, - "components": { - "schemas": { - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] - }, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - } - }, - } diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial014_an_py310.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial014_an_py310.py deleted file mode 100644 index 344004d01..000000000 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial014_an_py310.py +++ /dev/null @@ -1,91 +0,0 @@ -import pytest -from fastapi.testclient import TestClient - -from ...utils import needs_py310 - - -@pytest.fixture(name="client") -def get_client(): - from docs_src.query_params_str_validations.tutorial014_an_py310 import app - - client = TestClient(app) - return client - - -@needs_py310 -def test_hidden_query(client: TestClient): - response = client.get("/items?hidden_query=somevalue") - assert response.status_code == 200, response.text - assert response.json() == {"hidden_query": "somevalue"} - - -@needs_py310 -def test_no_hidden_query(client: TestClient): - response = client.get("/items") - assert response.status_code == 200, response.text - assert response.json() == {"hidden_query": "Not found"} - - -@needs_py310 -def test_openapi_schema(client: TestClient): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "summary": "Read Items", - "operationId": "read_items_items__get", - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - } - }, - "components": { - "schemas": { - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] - }, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - } - }, - } diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial014_an_py39.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial014_an_py39.py deleted file mode 100644 index 5d4f6df3d..000000000 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial014_an_py39.py +++ /dev/null @@ -1,91 +0,0 @@ -import pytest -from fastapi.testclient import TestClient - -from ...utils import needs_py310 - - -@pytest.fixture(name="client") -def get_client(): - from docs_src.query_params_str_validations.tutorial014_an_py39 import app - - client = TestClient(app) - return client - - -@needs_py310 -def test_hidden_query(client: TestClient): - response = client.get("/items?hidden_query=somevalue") - assert response.status_code == 200, response.text - assert response.json() == {"hidden_query": "somevalue"} - - -@needs_py310 -def test_no_hidden_query(client: TestClient): - response = client.get("/items") - assert response.status_code == 200, response.text - assert response.json() == {"hidden_query": "Not found"} - - -@needs_py310 -def test_openapi_schema(client: TestClient): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "summary": "Read Items", - "operationId": "read_items_items__get", - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - } - }, - "components": { - "schemas": { - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] - }, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - } - }, - } diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial014_py310.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial014_py310.py deleted file mode 100644 index dad49fb12..000000000 --- a/tests/test_tutorial/test_query_params_str_validations/test_tutorial014_py310.py +++ /dev/null @@ -1,91 +0,0 @@ -import pytest -from fastapi.testclient import TestClient - -from ...utils import needs_py310 - - -@pytest.fixture(name="client") -def get_client(): - from docs_src.query_params_str_validations.tutorial014_py310 import app - - client = TestClient(app) - return client - - -@needs_py310 -def test_hidden_query(client: TestClient): - response = client.get("/items?hidden_query=somevalue") - assert response.status_code == 200, response.text - assert response.json() == {"hidden_query": "somevalue"} - - -@needs_py310 -def test_no_hidden_query(client: TestClient): - response = client.get("/items") - assert response.status_code == 200, response.text - assert response.json() == {"hidden_query": "Not found"} - - -@needs_py310 -def test_openapi_schema(client: TestClient): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/items/": { - "get": { - "summary": "Read Items", - "operationId": "read_items_items__get", - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - } - }, - "components": { - "schemas": { - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] - }, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - } - }, - } diff --git a/tests/test_tutorial/test_query_params_str_validations/test_tutorial015.py b/tests/test_tutorial/test_query_params_str_validations/test_tutorial015.py new file mode 100644 index 000000000..ae1c40286 --- /dev/null +++ b/tests/test_tutorial/test_query_params_str_validations/test_tutorial015.py @@ -0,0 +1,143 @@ +import importlib + +import pytest +from dirty_equals import IsStr +from fastapi.testclient import TestClient +from inline_snapshot import snapshot + +from ...utils import needs_py39, needs_py310, needs_pydanticv2 + + +@pytest.fixture( + name="client", + params=[ + pytest.param("tutorial015_an", marks=needs_pydanticv2), + pytest.param("tutorial015_an_py310", marks=(needs_py310, needs_pydanticv2)), + pytest.param("tutorial015_an_py39", marks=(needs_py39, needs_pydanticv2)), + ], +) +def get_client(request: pytest.FixtureRequest): + mod = importlib.import_module( + f"docs_src.query_params_str_validations.{request.param}" + ) + + client = TestClient(mod.app) + return client + + +def test_get_random_item(client: TestClient): + response = client.get("/items") + assert response.status_code == 200, response.text + assert response.json() == {"id": IsStr(), "name": IsStr()} + + +def test_get_item(client: TestClient): + response = client.get("/items?id=isbn-9781529046137") + assert response.status_code == 200, response.text + assert response.json() == { + "id": "isbn-9781529046137", + "name": "The Hitchhiker's Guide to the Galaxy", + } + + +def test_get_item_does_not_exist(client: TestClient): + response = client.get("/items?id=isbn-nope") + assert response.status_code == 200, response.text + assert response.json() == {"id": "isbn-nope", "name": None} + + +def test_get_invalid_item(client: TestClient): + response = client.get("/items?id=wtf-yes") + assert response.status_code == 422, response.text + assert response.json() == snapshot( + { + "detail": [ + { + "type": "value_error", + "loc": ["query", "id"], + "msg": 'Value error, Invalid ID format, it must start with "isbn-" or "imdb-"', + "input": "wtf-yes", + "ctx": {"error": {}}, + } + ] + } + ) + + +def test_openapi_schema(client: TestClient): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + assert response.json() == snapshot( + { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/items/": { + "get": { + "summary": "Read Items", + "operationId": "read_items_items__get", + "parameters": [ + { + "name": "id", + "in": "query", + "required": False, + "schema": { + "anyOf": [{"type": "string"}, {"type": "null"}], + "title": "Id", + }, + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + } + }, + "components": { + "schemas": { + "HTTPValidationError": { + "properties": { + "detail": { + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + "type": "array", + "title": "Detail", + } + }, + "type": "object", + "title": "HTTPValidationError", + }, + "ValidationError": { + "properties": { + "loc": { + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + "type": "array", + "title": "Location", + }, + "msg": {"type": "string", "title": "Message"}, + "type": {"type": "string", "title": "Error Type"}, + }, + "type": "object", + "required": ["loc", "msg", "type"], + "title": "ValidationError", + }, + } + }, + } + ) diff --git a/tests/test_tutorial/test_request_files/test_tutorial001.py b/tests/test_tutorial/test_request_files/test_tutorial001.py index f5817593b..b06919961 100644 --- a/tests/test_tutorial/test_request_files/test_tutorial001.py +++ b/tests/test_tutorial/test_request_files/test_tutorial001.py @@ -1,23 +1,28 @@ +import importlib + +import pytest from dirty_equals import IsDict from fastapi.testclient import TestClient -from docs_src.request_files.tutorial001 import app +from ...utils import needs_py39 -client = TestClient(app) +@pytest.fixture( + name="client", + params=[ + "tutorial001", + "tutorial001_an", + pytest.param("tutorial001_an_py39", marks=needs_py39), + ], +) +def get_client(request: pytest.FixtureRequest): + mod = importlib.import_module(f"docs_src.request_files.{request.param}") -file_required = { - "detail": [ - { - "loc": ["body", "file"], - "msg": "field required", - "type": "value_error.missing", - } - ] -} + client = TestClient(mod.app) + return client -def test_post_form_no_body(): +def test_post_form_no_body(client: TestClient): response = client.post("/files/") assert response.status_code == 422, response.text assert response.json() == IsDict( @@ -45,7 +50,7 @@ def test_post_form_no_body(): ) -def test_post_body_json(): +def test_post_body_json(client: TestClient): response = client.post("/files/", json={"file": "Foo"}) assert response.status_code == 422, response.text assert response.json() == IsDict( @@ -73,41 +78,38 @@ def test_post_body_json(): ) -def test_post_file(tmp_path): +def test_post_file(tmp_path, client: TestClient): path = tmp_path / "test.txt" path.write_bytes(b"") - client = TestClient(app) with path.open("rb") as file: response = client.post("/files/", files={"file": file}) assert response.status_code == 200, response.text assert response.json() == {"file_size": 14} -def test_post_large_file(tmp_path): +def test_post_large_file(tmp_path, client: TestClient): default_pydantic_max_size = 2**16 path = tmp_path / "test.txt" path.write_bytes(b"x" * (default_pydantic_max_size + 1)) - client = TestClient(app) with path.open("rb") as file: response = client.post("/files/", files={"file": file}) assert response.status_code == 200, response.text assert response.json() == {"file_size": default_pydantic_max_size + 1} -def test_post_upload_file(tmp_path): +def test_post_upload_file(tmp_path, client: TestClient): path = tmp_path / "test.txt" path.write_bytes(b"") - client = TestClient(app) with path.open("rb") as file: response = client.post("/uploadfile/", files={"file": file}) assert response.status_code == 200, response.text assert response.json() == {"filename": "test.txt"} -def test_openapi_schema(): +def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { diff --git a/tests/test_tutorial/test_request_files/test_tutorial001_02.py b/tests/test_tutorial/test_request_files/test_tutorial001_02.py index 42f75442a..9075a1756 100644 --- a/tests/test_tutorial/test_request_files/test_tutorial001_02.py +++ b/tests/test_tutorial/test_request_files/test_tutorial001_02.py @@ -1,46 +1,63 @@ +import importlib +from pathlib import Path + +import pytest from dirty_equals import IsDict from fastapi.testclient import TestClient -from docs_src.request_files.tutorial001_02 import app +from ...utils import needs_py39, needs_py310 + + +@pytest.fixture( + name="client", + params=[ + "tutorial001_02", + pytest.param("tutorial001_02_py310", marks=needs_py310), + "tutorial001_02_an", + pytest.param("tutorial001_02_an_py39", marks=needs_py39), + pytest.param("tutorial001_02_an_py310", marks=needs_py310), + ], +) +def get_client(request: pytest.FixtureRequest): + mod = importlib.import_module(f"docs_src.request_files.{request.param}") -client = TestClient(app) + client = TestClient(mod.app) + return client -def test_post_form_no_body(): +def test_post_form_no_body(client: TestClient): response = client.post("/files/") assert response.status_code == 200, response.text assert response.json() == {"message": "No file sent"} -def test_post_uploadfile_no_body(): +def test_post_uploadfile_no_body(client: TestClient): response = client.post("/uploadfile/") assert response.status_code == 200, response.text assert response.json() == {"message": "No upload file sent"} -def test_post_file(tmp_path): +def test_post_file(tmp_path: Path, client: TestClient): path = tmp_path / "test.txt" path.write_bytes(b"") - client = TestClient(app) with path.open("rb") as file: response = client.post("/files/", files={"file": file}) assert response.status_code == 200, response.text assert response.json() == {"file_size": 14} -def test_post_upload_file(tmp_path): +def test_post_upload_file(tmp_path: Path, client: TestClient): path = tmp_path / "test.txt" path.write_bytes(b"") - client = TestClient(app) with path.open("rb") as file: response = client.post("/uploadfile/", files={"file": file}) assert response.status_code == 200, response.text assert response.json() == {"filename": "test.txt"} -def test_openapi_schema(): +def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { diff --git a/tests/test_tutorial/test_request_files/test_tutorial001_02_an.py b/tests/test_tutorial/test_request_files/test_tutorial001_02_an.py deleted file mode 100644 index f63eb339c..000000000 --- a/tests/test_tutorial/test_request_files/test_tutorial001_02_an.py +++ /dev/null @@ -1,208 +0,0 @@ -from dirty_equals import IsDict -from fastapi.testclient import TestClient - -from docs_src.request_files.tutorial001_02_an import app - -client = TestClient(app) - - -def test_post_form_no_body(): - response = client.post("/files/") - assert response.status_code == 200, response.text - assert response.json() == {"message": "No file sent"} - - -def test_post_uploadfile_no_body(): - response = client.post("/uploadfile/") - assert response.status_code == 200, response.text - assert response.json() == {"message": "No upload file sent"} - - -def test_post_file(tmp_path): - path = tmp_path / "test.txt" - path.write_bytes(b"") - - client = TestClient(app) - with path.open("rb") as file: - response = client.post("/files/", files={"file": file}) - assert response.status_code == 200, response.text - assert response.json() == {"file_size": 14} - - -def test_post_upload_file(tmp_path): - path = tmp_path / "test.txt" - path.write_bytes(b"") - - client = TestClient(app) - with path.open("rb") as file: - response = client.post("/uploadfile/", files={"file": file}) - assert response.status_code == 200, response.text - assert response.json() == {"filename": "test.txt"} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/files/": { - "post": { - "summary": "Create File", - "operationId": "create_file_files__post", - "requestBody": { - "content": { - "multipart/form-data": { - "schema": IsDict( - { - "allOf": [ - { - "$ref": "#/components/schemas/Body_create_file_files__post" - } - ], - "title": "Body", - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - { - "$ref": "#/components/schemas/Body_create_file_files__post" - } - ) - } - } - }, - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - }, - "/uploadfile/": { - "post": { - "summary": "Create Upload File", - "operationId": "create_upload_file_uploadfile__post", - "requestBody": { - "content": { - "multipart/form-data": { - "schema": IsDict( - { - "allOf": [ - { - "$ref": "#/components/schemas/Body_create_upload_file_uploadfile__post" - } - ], - "title": "Body", - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - { - "$ref": "#/components/schemas/Body_create_upload_file_uploadfile__post" - } - ) - } - } - }, - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - }, - }, - "components": { - "schemas": { - "Body_create_file_files__post": { - "title": "Body_create_file_files__post", - "type": "object", - "properties": { - "file": IsDict( - { - "title": "File", - "anyOf": [ - {"type": "string", "format": "binary"}, - {"type": "null"}, - ], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "File", "type": "string", "format": "binary"} - ) - }, - }, - "Body_create_upload_file_uploadfile__post": { - "title": "Body_create_upload_file_uploadfile__post", - "type": "object", - "properties": { - "file": IsDict( - { - "title": "File", - "anyOf": [ - {"type": "string", "format": "binary"}, - {"type": "null"}, - ], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "File", "type": "string", "format": "binary"} - ) - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] - }, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - } - }, - } diff --git a/tests/test_tutorial/test_request_files/test_tutorial001_02_an_py310.py b/tests/test_tutorial/test_request_files/test_tutorial001_02_an_py310.py deleted file mode 100644 index 94b6ac67e..000000000 --- a/tests/test_tutorial/test_request_files/test_tutorial001_02_an_py310.py +++ /dev/null @@ -1,220 +0,0 @@ -from pathlib import Path - -import pytest -from dirty_equals import IsDict -from fastapi.testclient import TestClient - -from ...utils import needs_py310 - - -@pytest.fixture(name="client") -def get_client(): - from docs_src.request_files.tutorial001_02_an_py310 import app - - client = TestClient(app) - return client - - -@needs_py310 -def test_post_form_no_body(client: TestClient): - response = client.post("/files/") - assert response.status_code == 200, response.text - assert response.json() == {"message": "No file sent"} - - -@needs_py310 -def test_post_uploadfile_no_body(client: TestClient): - response = client.post("/uploadfile/") - assert response.status_code == 200, response.text - assert response.json() == {"message": "No upload file sent"} - - -@needs_py310 -def test_post_file(tmp_path: Path, client: TestClient): - path = tmp_path / "test.txt" - path.write_bytes(b"") - - with path.open("rb") as file: - response = client.post("/files/", files={"file": file}) - assert response.status_code == 200, response.text - assert response.json() == {"file_size": 14} - - -@needs_py310 -def test_post_upload_file(tmp_path: Path, client: TestClient): - path = tmp_path / "test.txt" - path.write_bytes(b"") - - with path.open("rb") as file: - response = client.post("/uploadfile/", files={"file": file}) - assert response.status_code == 200, response.text - assert response.json() == {"filename": "test.txt"} - - -@needs_py310 -def test_openapi_schema(client: TestClient): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/files/": { - "post": { - "summary": "Create File", - "operationId": "create_file_files__post", - "requestBody": { - "content": { - "multipart/form-data": { - "schema": IsDict( - { - "allOf": [ - { - "$ref": "#/components/schemas/Body_create_file_files__post" - } - ], - "title": "Body", - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - { - "$ref": "#/components/schemas/Body_create_file_files__post" - } - ) - } - } - }, - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - }, - "/uploadfile/": { - "post": { - "summary": "Create Upload File", - "operationId": "create_upload_file_uploadfile__post", - "requestBody": { - "content": { - "multipart/form-data": { - "schema": IsDict( - { - "allOf": [ - { - "$ref": "#/components/schemas/Body_create_upload_file_uploadfile__post" - } - ], - "title": "Body", - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - { - "$ref": "#/components/schemas/Body_create_upload_file_uploadfile__post" - } - ) - } - } - }, - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - }, - }, - "components": { - "schemas": { - "Body_create_file_files__post": { - "title": "Body_create_file_files__post", - "type": "object", - "properties": { - "file": IsDict( - { - "title": "File", - "anyOf": [ - {"type": "string", "format": "binary"}, - {"type": "null"}, - ], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "File", "type": "string", "format": "binary"} - ) - }, - }, - "Body_create_upload_file_uploadfile__post": { - "title": "Body_create_upload_file_uploadfile__post", - "type": "object", - "properties": { - "file": IsDict( - { - "title": "File", - "anyOf": [ - {"type": "string", "format": "binary"}, - {"type": "null"}, - ], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "File", "type": "string", "format": "binary"} - ) - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] - }, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - } - }, - } diff --git a/tests/test_tutorial/test_request_files/test_tutorial001_02_an_py39.py b/tests/test_tutorial/test_request_files/test_tutorial001_02_an_py39.py deleted file mode 100644 index fcb39f8f1..000000000 --- a/tests/test_tutorial/test_request_files/test_tutorial001_02_an_py39.py +++ /dev/null @@ -1,220 +0,0 @@ -from pathlib import Path - -import pytest -from dirty_equals import IsDict -from fastapi.testclient import TestClient - -from ...utils import needs_py39 - - -@pytest.fixture(name="client") -def get_client(): - from docs_src.request_files.tutorial001_02_an_py39 import app - - client = TestClient(app) - return client - - -@needs_py39 -def test_post_form_no_body(client: TestClient): - response = client.post("/files/") - assert response.status_code == 200, response.text - assert response.json() == {"message": "No file sent"} - - -@needs_py39 -def test_post_uploadfile_no_body(client: TestClient): - response = client.post("/uploadfile/") - assert response.status_code == 200, response.text - assert response.json() == {"message": "No upload file sent"} - - -@needs_py39 -def test_post_file(tmp_path: Path, client: TestClient): - path = tmp_path / "test.txt" - path.write_bytes(b"") - - with path.open("rb") as file: - response = client.post("/files/", files={"file": file}) - assert response.status_code == 200, response.text - assert response.json() == {"file_size": 14} - - -@needs_py39 -def test_post_upload_file(tmp_path: Path, client: TestClient): - path = tmp_path / "test.txt" - path.write_bytes(b"") - - with path.open("rb") as file: - response = client.post("/uploadfile/", files={"file": file}) - assert response.status_code == 200, response.text - assert response.json() == {"filename": "test.txt"} - - -@needs_py39 -def test_openapi_schema(client: TestClient): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/files/": { - "post": { - "summary": "Create File", - "operationId": "create_file_files__post", - "requestBody": { - "content": { - "multipart/form-data": { - "schema": IsDict( - { - "allOf": [ - { - "$ref": "#/components/schemas/Body_create_file_files__post" - } - ], - "title": "Body", - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - { - "$ref": "#/components/schemas/Body_create_file_files__post" - } - ) - } - } - }, - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - }, - "/uploadfile/": { - "post": { - "summary": "Create Upload File", - "operationId": "create_upload_file_uploadfile__post", - "requestBody": { - "content": { - "multipart/form-data": { - "schema": IsDict( - { - "allOf": [ - { - "$ref": "#/components/schemas/Body_create_upload_file_uploadfile__post" - } - ], - "title": "Body", - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - { - "$ref": "#/components/schemas/Body_create_upload_file_uploadfile__post" - } - ) - } - } - }, - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - }, - }, - "components": { - "schemas": { - "Body_create_file_files__post": { - "title": "Body_create_file_files__post", - "type": "object", - "properties": { - "file": IsDict( - { - "title": "File", - "anyOf": [ - {"type": "string", "format": "binary"}, - {"type": "null"}, - ], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "File", "type": "string", "format": "binary"} - ) - }, - }, - "Body_create_upload_file_uploadfile__post": { - "title": "Body_create_upload_file_uploadfile__post", - "type": "object", - "properties": { - "file": IsDict( - { - "title": "File", - "anyOf": [ - {"type": "string", "format": "binary"}, - {"type": "null"}, - ], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "File", "type": "string", "format": "binary"} - ) - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] - }, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - } - }, - } diff --git a/tests/test_tutorial/test_request_files/test_tutorial001_02_py310.py b/tests/test_tutorial/test_request_files/test_tutorial001_02_py310.py deleted file mode 100644 index a700752a3..000000000 --- a/tests/test_tutorial/test_request_files/test_tutorial001_02_py310.py +++ /dev/null @@ -1,220 +0,0 @@ -from pathlib import Path - -import pytest -from dirty_equals import IsDict -from fastapi.testclient import TestClient - -from ...utils import needs_py310 - - -@pytest.fixture(name="client") -def get_client(): - from docs_src.request_files.tutorial001_02_py310 import app - - client = TestClient(app) - return client - - -@needs_py310 -def test_post_form_no_body(client: TestClient): - response = client.post("/files/") - assert response.status_code == 200, response.text - assert response.json() == {"message": "No file sent"} - - -@needs_py310 -def test_post_uploadfile_no_body(client: TestClient): - response = client.post("/uploadfile/") - assert response.status_code == 200, response.text - assert response.json() == {"message": "No upload file sent"} - - -@needs_py310 -def test_post_file(tmp_path: Path, client: TestClient): - path = tmp_path / "test.txt" - path.write_bytes(b"") - - with path.open("rb") as file: - response = client.post("/files/", files={"file": file}) - assert response.status_code == 200, response.text - assert response.json() == {"file_size": 14} - - -@needs_py310 -def test_post_upload_file(tmp_path: Path, client: TestClient): - path = tmp_path / "test.txt" - path.write_bytes(b"") - - with path.open("rb") as file: - response = client.post("/uploadfile/", files={"file": file}) - assert response.status_code == 200, response.text - assert response.json() == {"filename": "test.txt"} - - -@needs_py310 -def test_openapi_schema(client: TestClient): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/files/": { - "post": { - "summary": "Create File", - "operationId": "create_file_files__post", - "requestBody": { - "content": { - "multipart/form-data": { - "schema": IsDict( - { - "allOf": [ - { - "$ref": "#/components/schemas/Body_create_file_files__post" - } - ], - "title": "Body", - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - { - "$ref": "#/components/schemas/Body_create_file_files__post" - } - ) - } - } - }, - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - }, - "/uploadfile/": { - "post": { - "summary": "Create Upload File", - "operationId": "create_upload_file_uploadfile__post", - "requestBody": { - "content": { - "multipart/form-data": { - "schema": IsDict( - { - "allOf": [ - { - "$ref": "#/components/schemas/Body_create_upload_file_uploadfile__post" - } - ], - "title": "Body", - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - { - "$ref": "#/components/schemas/Body_create_upload_file_uploadfile__post" - } - ) - } - } - }, - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - }, - }, - "components": { - "schemas": { - "Body_create_file_files__post": { - "title": "Body_create_file_files__post", - "type": "object", - "properties": { - "file": IsDict( - { - "title": "File", - "anyOf": [ - {"type": "string", "format": "binary"}, - {"type": "null"}, - ], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "File", "type": "string", "format": "binary"} - ) - }, - }, - "Body_create_upload_file_uploadfile__post": { - "title": "Body_create_upload_file_uploadfile__post", - "type": "object", - "properties": { - "file": IsDict( - { - "title": "File", - "anyOf": [ - {"type": "string", "format": "binary"}, - {"type": "null"}, - ], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "File", "type": "string", "format": "binary"} - ) - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] - }, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - } - }, - } diff --git a/tests/test_tutorial/test_request_files/test_tutorial001_03.py b/tests/test_tutorial/test_request_files/test_tutorial001_03.py index f02170814..9fbe2166c 100644 --- a/tests/test_tutorial/test_request_files/test_tutorial001_03.py +++ b/tests/test_tutorial/test_request_files/test_tutorial001_03.py @@ -1,33 +1,47 @@ +import importlib + +import pytest from fastapi.testclient import TestClient -from docs_src.request_files.tutorial001_03 import app +from ...utils import needs_py39 + + +@pytest.fixture( + name="client", + params=[ + "tutorial001_03", + "tutorial001_03_an", + pytest.param("tutorial001_03_an_py39", marks=needs_py39), + ], +) +def get_client(request: pytest.FixtureRequest): + mod = importlib.import_module(f"docs_src.request_files.{request.param}") -client = TestClient(app) + client = TestClient(mod.app) + return client -def test_post_file(tmp_path): +def test_post_file(tmp_path, client: TestClient): path = tmp_path / "test.txt" path.write_bytes(b"") - client = TestClient(app) with path.open("rb") as file: response = client.post("/files/", files={"file": file}) assert response.status_code == 200, response.text assert response.json() == {"file_size": 14} -def test_post_upload_file(tmp_path): +def test_post_upload_file(tmp_path, client: TestClient): path = tmp_path / "test.txt" path.write_bytes(b"") - client = TestClient(app) with path.open("rb") as file: response = client.post("/uploadfile/", files={"file": file}) assert response.status_code == 200, response.text assert response.json() == {"filename": "test.txt"} -def test_openapi_schema(): +def test_openapi_schema(client: TestClient): response = client.get("/openapi.json") assert response.status_code == 200, response.text assert response.json() == { diff --git a/tests/test_tutorial/test_request_files/test_tutorial001_03_an.py b/tests/test_tutorial/test_request_files/test_tutorial001_03_an.py deleted file mode 100644 index acfb749ce..000000000 --- a/tests/test_tutorial/test_request_files/test_tutorial001_03_an.py +++ /dev/null @@ -1,159 +0,0 @@ -from fastapi.testclient import TestClient - -from docs_src.request_files.tutorial001_03_an import app - -client = TestClient(app) - - -def test_post_file(tmp_path): - path = tmp_path / "test.txt" - path.write_bytes(b"") - - client = TestClient(app) - with path.open("rb") as file: - response = client.post("/files/", files={"file": file}) - assert response.status_code == 200, response.text - assert response.json() == {"file_size": 14} - - -def test_post_upload_file(tmp_path): - path = tmp_path / "test.txt" - path.write_bytes(b"") - - client = TestClient(app) - with path.open("rb") as file: - response = client.post("/uploadfile/", files={"file": file}) - assert response.status_code == 200, response.text - assert response.json() == {"filename": "test.txt"} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/files/": { - "post": { - "summary": "Create File", - "operationId": "create_file_files__post", - "requestBody": { - "content": { - "multipart/form-data": { - "schema": { - "$ref": "#/components/schemas/Body_create_file_files__post" - } - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - }, - "/uploadfile/": { - "post": { - "summary": "Create Upload File", - "operationId": "create_upload_file_uploadfile__post", - "requestBody": { - "content": { - "multipart/form-data": { - "schema": { - "$ref": "#/components/schemas/Body_create_upload_file_uploadfile__post" - } - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - }, - }, - "components": { - "schemas": { - "Body_create_file_files__post": { - "title": "Body_create_file_files__post", - "required": ["file"], - "type": "object", - "properties": { - "file": { - "title": "File", - "type": "string", - "description": "A file read as bytes", - "format": "binary", - } - }, - }, - "Body_create_upload_file_uploadfile__post": { - "title": "Body_create_upload_file_uploadfile__post", - "required": ["file"], - "type": "object", - "properties": { - "file": { - "title": "File", - "type": "string", - "description": "A file read as UploadFile", - "format": "binary", - } - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] - }, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - } - }, - } diff --git a/tests/test_tutorial/test_request_files/test_tutorial001_03_an_py39.py b/tests/test_tutorial/test_request_files/test_tutorial001_03_an_py39.py deleted file mode 100644 index 36e5faac1..000000000 --- a/tests/test_tutorial/test_request_files/test_tutorial001_03_an_py39.py +++ /dev/null @@ -1,167 +0,0 @@ -import pytest -from fastapi.testclient import TestClient - -from ...utils import needs_py39 - - -@pytest.fixture(name="client") -def get_client(): - from docs_src.request_files.tutorial001_03_an_py39 import app - - client = TestClient(app) - return client - - -@needs_py39 -def test_post_file(tmp_path, client: TestClient): - path = tmp_path / "test.txt" - path.write_bytes(b"") - - with path.open("rb") as file: - response = client.post("/files/", files={"file": file}) - assert response.status_code == 200, response.text - assert response.json() == {"file_size": 14} - - -@needs_py39 -def test_post_upload_file(tmp_path, client: TestClient): - path = tmp_path / "test.txt" - path.write_bytes(b"") - - with path.open("rb") as file: - response = client.post("/uploadfile/", files={"file": file}) - assert response.status_code == 200, response.text - assert response.json() == {"filename": "test.txt"} - - -@needs_py39 -def test_openapi_schema(client: TestClient): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/files/": { - "post": { - "summary": "Create File", - "operationId": "create_file_files__post", - "requestBody": { - "content": { - "multipart/form-data": { - "schema": { - "$ref": "#/components/schemas/Body_create_file_files__post" - } - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - }, - "/uploadfile/": { - "post": { - "summary": "Create Upload File", - "operationId": "create_upload_file_uploadfile__post", - "requestBody": { - "content": { - "multipart/form-data": { - "schema": { - "$ref": "#/components/schemas/Body_create_upload_file_uploadfile__post" - } - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - }, - }, - "components": { - "schemas": { - "Body_create_file_files__post": { - "title": "Body_create_file_files__post", - "required": ["file"], - "type": "object", - "properties": { - "file": { - "title": "File", - "type": "string", - "description": "A file read as bytes", - "format": "binary", - } - }, - }, - "Body_create_upload_file_uploadfile__post": { - "title": "Body_create_upload_file_uploadfile__post", - "required": ["file"], - "type": "object", - "properties": { - "file": { - "title": "File", - "type": "string", - "description": "A file read as UploadFile", - "format": "binary", - } - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] - }, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - } - }, - } diff --git a/tests/test_tutorial/test_request_files/test_tutorial001_an.py b/tests/test_tutorial/test_request_files/test_tutorial001_an.py deleted file mode 100644 index 1c78e3679..000000000 --- a/tests/test_tutorial/test_request_files/test_tutorial001_an.py +++ /dev/null @@ -1,218 +0,0 @@ -from dirty_equals import IsDict -from fastapi.testclient import TestClient - -from docs_src.request_files.tutorial001_an import app - -client = TestClient(app) - - -def test_post_form_no_body(): - response = client.post("/files/") - assert response.status_code == 422, response.text - assert response.json() == IsDict( - { - "detail": [ - { - "type": "missing", - "loc": ["body", "file"], - "msg": "Field required", - "input": None, - } - ] - } - ) | IsDict( - # TODO: remove when deprecating Pydantic v1 - { - "detail": [ - { - "loc": ["body", "file"], - "msg": "field required", - "type": "value_error.missing", - } - ] - } - ) - - -def test_post_body_json(): - response = client.post("/files/", json={"file": "Foo"}) - assert response.status_code == 422, response.text - assert response.json() == IsDict( - { - "detail": [ - { - "type": "missing", - "loc": ["body", "file"], - "msg": "Field required", - "input": None, - } - ] - } - ) | IsDict( - # TODO: remove when deprecating Pydantic v1 - { - "detail": [ - { - "loc": ["body", "file"], - "msg": "field required", - "type": "value_error.missing", - } - ] - } - ) - - -def test_post_file(tmp_path): - path = tmp_path / "test.txt" - path.write_bytes(b"") - - client = TestClient(app) - with path.open("rb") as file: - response = client.post("/files/", files={"file": file}) - assert response.status_code == 200, response.text - assert response.json() == {"file_size": 14} - - -def test_post_large_file(tmp_path): - default_pydantic_max_size = 2**16 - path = tmp_path / "test.txt" - path.write_bytes(b"x" * (default_pydantic_max_size + 1)) - - client = TestClient(app) - with path.open("rb") as file: - response = client.post("/files/", files={"file": file}) - assert response.status_code == 200, response.text - assert response.json() == {"file_size": default_pydantic_max_size + 1} - - -def test_post_upload_file(tmp_path): - path = tmp_path / "test.txt" - path.write_bytes(b"") - - client = TestClient(app) - with path.open("rb") as file: - response = client.post("/uploadfile/", files={"file": file}) - assert response.status_code == 200, response.text - assert response.json() == {"filename": "test.txt"} - - -def test_openapi_schema(): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/files/": { - "post": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Create File", - "operationId": "create_file_files__post", - "requestBody": { - "content": { - "multipart/form-data": { - "schema": { - "$ref": "#/components/schemas/Body_create_file_files__post" - } - } - }, - "required": True, - }, - } - }, - "/uploadfile/": { - "post": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Create Upload File", - "operationId": "create_upload_file_uploadfile__post", - "requestBody": { - "content": { - "multipart/form-data": { - "schema": { - "$ref": "#/components/schemas/Body_create_upload_file_uploadfile__post" - } - } - }, - "required": True, - }, - } - }, - }, - "components": { - "schemas": { - "Body_create_upload_file_uploadfile__post": { - "title": "Body_create_upload_file_uploadfile__post", - "required": ["file"], - "type": "object", - "properties": { - "file": {"title": "File", "type": "string", "format": "binary"} - }, - }, - "Body_create_file_files__post": { - "title": "Body_create_file_files__post", - "required": ["file"], - "type": "object", - "properties": { - "file": {"title": "File", "type": "string", "format": "binary"} - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] - }, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, - } diff --git a/tests/test_tutorial/test_request_files/test_tutorial001_an_py39.py b/tests/test_tutorial/test_request_files/test_tutorial001_an_py39.py deleted file mode 100644 index 843fcec28..000000000 --- a/tests/test_tutorial/test_request_files/test_tutorial001_an_py39.py +++ /dev/null @@ -1,228 +0,0 @@ -import pytest -from dirty_equals import IsDict -from fastapi.testclient import TestClient - -from ...utils import needs_py39 - - -@pytest.fixture(name="client") -def get_client(): - from docs_src.request_files.tutorial001_an_py39 import app - - client = TestClient(app) - return client - - -@needs_py39 -def test_post_form_no_body(client: TestClient): - response = client.post("/files/") - assert response.status_code == 422, response.text - assert response.json() == IsDict( - { - "detail": [ - { - "type": "missing", - "loc": ["body", "file"], - "msg": "Field required", - "input": None, - } - ] - } - ) | IsDict( - # TODO: remove when deprecating Pydantic v1 - { - "detail": [ - { - "loc": ["body", "file"], - "msg": "field required", - "type": "value_error.missing", - } - ] - } - ) - - -@needs_py39 -def test_post_body_json(client: TestClient): - response = client.post("/files/", json={"file": "Foo"}) - assert response.status_code == 422, response.text - assert response.json() == IsDict( - { - "detail": [ - { - "type": "missing", - "loc": ["body", "file"], - "msg": "Field required", - "input": None, - } - ] - } - ) | IsDict( - # TODO: remove when deprecating Pydantic v1 - { - "detail": [ - { - "loc": ["body", "file"], - "msg": "field required", - "type": "value_error.missing", - } - ] - } - ) - - -@needs_py39 -def test_post_file(tmp_path, client: TestClient): - path = tmp_path / "test.txt" - path.write_bytes(b"") - - with path.open("rb") as file: - response = client.post("/files/", files={"file": file}) - assert response.status_code == 200, response.text - assert response.json() == {"file_size": 14} - - -@needs_py39 -def test_post_large_file(tmp_path, client: TestClient): - default_pydantic_max_size = 2**16 - path = tmp_path / "test.txt" - path.write_bytes(b"x" * (default_pydantic_max_size + 1)) - - with path.open("rb") as file: - response = client.post("/files/", files={"file": file}) - assert response.status_code == 200, response.text - assert response.json() == {"file_size": default_pydantic_max_size + 1} - - -@needs_py39 -def test_post_upload_file(tmp_path, client: TestClient): - path = tmp_path / "test.txt" - path.write_bytes(b"") - - with path.open("rb") as file: - response = client.post("/uploadfile/", files={"file": file}) - assert response.status_code == 200, response.text - assert response.json() == {"filename": "test.txt"} - - -@needs_py39 -def test_openapi_schema(client: TestClient): - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/files/": { - "post": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Create File", - "operationId": "create_file_files__post", - "requestBody": { - "content": { - "multipart/form-data": { - "schema": { - "$ref": "#/components/schemas/Body_create_file_files__post" - } - } - }, - "required": True, - }, - } - }, - "/uploadfile/": { - "post": { - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - "summary": "Create Upload File", - "operationId": "create_upload_file_uploadfile__post", - "requestBody": { - "content": { - "multipart/form-data": { - "schema": { - "$ref": "#/components/schemas/Body_create_upload_file_uploadfile__post" - } - } - }, - "required": True, - }, - } - }, - }, - "components": { - "schemas": { - "Body_create_upload_file_uploadfile__post": { - "title": "Body_create_upload_file_uploadfile__post", - "required": ["file"], - "type": "object", - "properties": { - "file": {"title": "File", "type": "string", "format": "binary"} - }, - }, - "Body_create_file_files__post": { - "title": "Body_create_file_files__post", - "required": ["file"], - "type": "object", - "properties": { - "file": {"title": "File", "type": "string", "format": "binary"} - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] - }, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": {"$ref": "#/components/schemas/ValidationError"}, - } - }, - }, - } - }, - } diff --git a/tests/test_tutorial/test_request_files/test_tutorial002.py b/tests/test_tutorial/test_request_files/test_tutorial002.py index db1552e5c..446a87657 100644 --- a/tests/test_tutorial/test_request_files/test_tutorial002.py +++ b/tests/test_tutorial/test_request_files/test_tutorial002.py @@ -1,12 +1,35 @@ +import importlib + +import pytest from dirty_equals import IsDict +from fastapi import FastAPI from fastapi.testclient import TestClient -from docs_src.request_files.tutorial002 import app +from ...utils import needs_py39 + + +@pytest.fixture( + name="app", + params=[ + "tutorial002", + "tutorial002_an", + pytest.param("tutorial002_py39", marks=needs_py39), + pytest.param("tutorial002_an_py39", marks=needs_py39), + ], +) +def get_app(request: pytest.FixtureRequest): + mod = importlib.import_module(f"docs_src.request_files.{request.param}") -client = TestClient(app) + return mod.app + + +@pytest.fixture(name="client") +def get_client(app: FastAPI): + client = TestClient(app) + return client -def test_post_form_no_body(): +def test_post_form_no_body(client: TestClient): response = client.post("/files/") assert response.status_code == 422, response.text assert response.json() == IsDict( @@ -34,7 +57,7 @@ def test_post_form_no_body(): ) -def test_post_body_json(): +def test_post_body_json(client: TestClient): response = client.post("/files/", json={"file": "Foo"}) assert response.status_code == 422, response.text assert response.json() == IsDict( @@ -62,7 +85,7 @@ def test_post_body_json(): ) -def test_post_files(tmp_path): +def test_post_files(tmp_path, app: FastAPI): path = tmp_path / "test.txt" path.write_bytes(b"") path2 = tmp_path / "test2.txt" @@ -81,7 +104,7 @@ def test_post_files(tmp_path): assert response.json() == {"file_sizes": [14, 15]} -def test_post_upload_file(tmp_path): +def test_post_upload_file(tmp_path, app: FastAPI): path = tmp_path / "test.txt" path.write_bytes(b"") path2 = tmp_path / "test2.txt" @@ -100,14 +123,14 @@ def test_post_upload_file(tmp_path): assert response.json() == {"filenames": ["test.txt", "test2.txt"]} -def test_get_root(): +def test_get_root(app: FastAPI): client = TestClient(app) response = client.get("/") assert response.status_code == 200, response.text assert b"") - path2 = tmp_path / "test2.txt" - path2.write_bytes(b"") - - client = TestClient(app) - with path.open("rb") as file, path2.open("rb") as file2: - response = client.post( - "/files/", - files=( - ("files", ("test.txt", file)), - ("files", ("test2.txt", file2)), - ), - ) - assert response.status_code == 200, response.text - assert response.json() == {"file_sizes": [14, 15]} - - -def test_post_upload_file(tmp_path): - path = tmp_path / "test.txt" - path.write_bytes(b"") - path2 = tmp_path / "test2.txt" - path2.write_bytes(b"") - - client = TestClient(app) - with path.open("rb") as file, path2.open("rb") as file2: - response = client.post( - "/uploadfiles/", - files=( - ("files", ("test.txt", file)), - ("files", ("test2.txt", file2)), - ), - ) - assert response.status_code == 200, response.text - assert response.json() == {"filenames": ["test.txt", "test2.txt"]} - - -def test_get_root(): - client = TestClient(app) - response = client.get("/") - assert response.status_code == 200, response.text - assert b"") - path2 = tmp_path / "test2.txt" - path2.write_bytes(b"") - - client = TestClient(app) - with path.open("rb") as file, path2.open("rb") as file2: - response = client.post( - "/files/", - files=( - ("files", ("test.txt", file)), - ("files", ("test2.txt", file2)), - ), - ) - assert response.status_code == 200, response.text - assert response.json() == {"file_sizes": [14, 15]} - - -@needs_py39 -def test_post_upload_file(tmp_path, app: FastAPI): - path = tmp_path / "test.txt" - path.write_bytes(b"") - path2 = tmp_path / "test2.txt" - path2.write_bytes(b"") - - client = TestClient(app) - with path.open("rb") as file, path2.open("rb") as file2: - response = client.post( - "/uploadfiles/", - files=( - ("files", ("test.txt", file)), - ("files", ("test2.txt", file2)), - ), - ) - assert response.status_code == 200, response.text - assert response.json() == {"filenames": ["test.txt", "test2.txt"]} - - -@needs_py39 -def test_get_root(app: FastAPI): - client = TestClient(app) - response = client.get("/") - assert response.status_code == 200, response.text - assert b"") - path2 = tmp_path / "test2.txt" - path2.write_bytes(b"") - - client = TestClient(app) - with path.open("rb") as file, path2.open("rb") as file2: - response = client.post( - "/files/", - files=( - ("files", ("test.txt", file)), - ("files", ("test2.txt", file2)), - ), - ) - assert response.status_code == 200, response.text - assert response.json() == {"file_sizes": [14, 15]} - - -@needs_py39 -def test_post_upload_file(tmp_path, app: FastAPI): - path = tmp_path / "test.txt" - path.write_bytes(b"") - path2 = tmp_path / "test2.txt" - path2.write_bytes(b"") - - client = TestClient(app) - with path.open("rb") as file, path2.open("rb") as file2: - response = client.post( - "/uploadfiles/", - files=( - ("files", ("test.txt", file)), - ("files", ("test2.txt", file2)), - ), - ) - assert response.status_code == 200, response.text - assert response.json() == {"filenames": ["test.txt", "test2.txt"]} - - -@needs_py39 -def test_get_root(app: FastAPI): - client = TestClient(app) - response = client.get("/") - assert response.status_code == 200, response.text - assert b"") path2 = tmp_path / "test2.txt" @@ -24,7 +47,7 @@ def test_post_files(tmp_path): assert response.json() == {"file_sizes": [14, 15]} -def test_post_upload_file(tmp_path): +def test_post_upload_file(tmp_path, app: FastAPI): path = tmp_path / "test.txt" path.write_bytes(b"") path2 = tmp_path / "test2.txt" @@ -43,14 +66,14 @@ def test_post_upload_file(tmp_path): assert response.json() == {"filenames": ["test.txt", "test2.txt"]} -def test_get_root(): +def test_get_root(app: FastAPI): client = TestClient(app) response = client.get("/") assert response.status_code == 200, response.text assert b"") - path2 = tmp_path / "test2.txt" - path2.write_bytes(b"") - - client = TestClient(app) - with path.open("rb") as file, path2.open("rb") as file2: - response = client.post( - "/files/", - files=( - ("files", ("test.txt", file)), - ("files", ("test2.txt", file2)), - ), - ) - assert response.status_code == 200, response.text - assert response.json() == {"file_sizes": [14, 15]} - - -def test_post_upload_file(tmp_path): - path = tmp_path / "test.txt" - path.write_bytes(b"") - path2 = tmp_path / "test2.txt" - path2.write_bytes(b"") - - client = TestClient(app) - with path.open("rb") as file, path2.open("rb") as file2: - response = client.post( - "/uploadfiles/", - files=( - ("files", ("test.txt", file)), - ("files", ("test2.txt", file2)), - ), - ) - assert response.status_code == 200, response.text - assert response.json() == {"filenames": ["test.txt", "test2.txt"]} - - -def test_get_root(): - client = TestClient(app) - response = client.get("/") - assert response.status_code == 200, response.text - assert b"") - path2 = tmp_path / "test2.txt" - path2.write_bytes(b"") - - client = TestClient(app) - with path.open("rb") as file, path2.open("rb") as file2: - response = client.post( - "/files/", - files=( - ("files", ("test.txt", file)), - ("files", ("test2.txt", file2)), - ), - ) - assert response.status_code == 200, response.text - assert response.json() == {"file_sizes": [14, 15]} - - -@needs_py39 -def test_post_upload_file(tmp_path, app: FastAPI): - path = tmp_path / "test.txt" - path.write_bytes(b"") - path2 = tmp_path / "test2.txt" - path2.write_bytes(b"") - - client = TestClient(app) - with path.open("rb") as file, path2.open("rb") as file2: - response = client.post( - "/uploadfiles/", - files=( - ("files", ("test.txt", file)), - ("files", ("test2.txt", file2)), - ), - ) - assert response.status_code == 200, response.text - assert response.json() == {"filenames": ["test.txt", "test2.txt"]} - - -@needs_py39 -def test_get_root(app: FastAPI): - client = TestClient(app) - response = client.get("/") - assert response.status_code == 200, response.text - assert b"") - path2 = tmp_path / "test2.txt" - path2.write_bytes(b"") - - client = TestClient(app) - with path.open("rb") as file, path2.open("rb") as file2: - response = client.post( - "/files/", - files=( - ("files", ("test.txt", file)), - ("files", ("test2.txt", file2)), - ), - ) - assert response.status_code == 200, response.text - assert response.json() == {"file_sizes": [14, 15]} - - -@needs_py39 -def test_post_upload_file(tmp_path, app: FastAPI): - path = tmp_path / "test.txt" - path.write_bytes(b"") - path2 = tmp_path / "test2.txt" - path2.write_bytes(b"") - - client = TestClient(app) - with path.open("rb") as file, path2.open("rb") as file2: - response = client.post( - "/uploadfiles/", - files=( - ("files", ("test.txt", file)), - ("files", ("test2.txt", file2)), - ), - ) - assert response.status_code == 200, response.text - assert response.json() == {"filenames": ["test.txt", "test2.txt"]} - - -@needs_py39 -def test_get_root(app: FastAPI): - client = TestClient(app) - response = client.get("/") - assert response.status_code == 200, response.text - assert b" ModuleType: + mod: ModuleType = importlib.import_module(f"docs_src.app_testing.{request.param}") + return mod + + +def test_app(test_module: ModuleType): + test_main = test_module test_main.test_create_existing_item() test_main.test_create_item() test_main.test_create_item_bad_token() diff --git a/tests/test_tutorial/test_testing/test_main_b_an.py b/tests/test_tutorial/test_testing/test_main_b_an.py deleted file mode 100644 index e53fc3224..000000000 --- a/tests/test_tutorial/test_testing/test_main_b_an.py +++ /dev/null @@ -1,10 +0,0 @@ -from docs_src.app_testing.app_b_an import test_main - - -def test_app(): - test_main.test_create_existing_item() - test_main.test_create_item() - test_main.test_create_item_bad_token() - test_main.test_read_nonexistent_item() - test_main.test_read_item() - test_main.test_read_item_bad_token() diff --git a/tests/test_tutorial/test_testing/test_main_b_an_py310.py b/tests/test_tutorial/test_testing/test_main_b_an_py310.py deleted file mode 100644 index c974e5dc1..000000000 --- a/tests/test_tutorial/test_testing/test_main_b_an_py310.py +++ /dev/null @@ -1,13 +0,0 @@ -from ...utils import needs_py310 - - -@needs_py310 -def test_app(): - from docs_src.app_testing.app_b_an_py310 import test_main - - test_main.test_create_existing_item() - test_main.test_create_item() - test_main.test_create_item_bad_token() - test_main.test_read_nonexistent_item() - test_main.test_read_item() - test_main.test_read_item_bad_token() diff --git a/tests/test_tutorial/test_testing/test_main_b_an_py39.py b/tests/test_tutorial/test_testing/test_main_b_an_py39.py deleted file mode 100644 index 71f99726c..000000000 --- a/tests/test_tutorial/test_testing/test_main_b_an_py39.py +++ /dev/null @@ -1,13 +0,0 @@ -from ...utils import needs_py39 - - -@needs_py39 -def test_app(): - from docs_src.app_testing.app_b_an_py39 import test_main - - test_main.test_create_existing_item() - test_main.test_create_item() - test_main.test_create_item_bad_token() - test_main.test_read_nonexistent_item() - test_main.test_read_item() - test_main.test_read_item_bad_token() diff --git a/tests/test_tutorial/test_testing/test_main_b_py310.py b/tests/test_tutorial/test_testing/test_main_b_py310.py deleted file mode 100644 index e30cdc073..000000000 --- a/tests/test_tutorial/test_testing/test_main_b_py310.py +++ /dev/null @@ -1,13 +0,0 @@ -from ...utils import needs_py310 - - -@needs_py310 -def test_app(): - from docs_src.app_testing.app_b_py310 import test_main - - test_main.test_create_existing_item() - test_main.test_create_item() - test_main.test_create_item_bad_token() - test_main.test_read_nonexistent_item() - test_main.test_read_item() - test_main.test_read_item_bad_token() diff --git a/tests/test_tutorial/test_testing_dependencies/test_tutorial001.py b/tests/test_tutorial/test_testing_dependencies/test_tutorial001.py index af26307f5..00ee6ab1e 100644 --- a/tests/test_tutorial/test_testing_dependencies/test_tutorial001.py +++ b/tests/test_tutorial/test_testing_dependencies/test_tutorial001.py @@ -1,25 +1,48 @@ -from docs_src.dependency_testing.tutorial001 import ( - app, - client, - test_override_in_items, - test_override_in_items_with_params, - test_override_in_items_with_q, +import importlib +from types import ModuleType + +import pytest + +from ...utils import needs_py39, needs_py310 + + +@pytest.fixture( + name="test_module", + params=[ + "tutorial001", + pytest.param("tutorial001_py310", marks=needs_py310), + "tutorial001_an", + pytest.param("tutorial001_an_py39", marks=needs_py39), + pytest.param("tutorial001_an_py310", marks=needs_py310), + ], ) +def get_test_module(request: pytest.FixtureRequest) -> ModuleType: + mod: ModuleType = importlib.import_module( + f"docs_src.dependency_testing.{request.param}" + ) + return mod -def test_override_in_items_run(): +def test_override_in_items_run(test_module: ModuleType): + test_override_in_items = test_module.test_override_in_items + test_override_in_items() -def test_override_in_items_with_q_run(): +def test_override_in_items_with_q_run(test_module: ModuleType): + test_override_in_items_with_q = test_module.test_override_in_items_with_q + test_override_in_items_with_q() -def test_override_in_items_with_params_run(): +def test_override_in_items_with_params_run(test_module: ModuleType): + test_override_in_items_with_params = test_module.test_override_in_items_with_params + test_override_in_items_with_params() -def test_override_in_users(): +def test_override_in_users(test_module: ModuleType): + client = test_module.client response = client.get("/users/") assert response.status_code == 200, response.text assert response.json() == { @@ -28,7 +51,8 @@ def test_override_in_users(): } -def test_override_in_users_with_q(): +def test_override_in_users_with_q(test_module: ModuleType): + client = test_module.client response = client.get("/users/?q=foo") assert response.status_code == 200, response.text assert response.json() == { @@ -37,7 +61,8 @@ def test_override_in_users_with_q(): } -def test_override_in_users_with_params(): +def test_override_in_users_with_params(test_module: ModuleType): + client = test_module.client response = client.get("/users/?q=foo&skip=100&limit=200") assert response.status_code == 200, response.text assert response.json() == { @@ -46,7 +71,9 @@ def test_override_in_users_with_params(): } -def test_normal_app(): +def test_normal_app(test_module: ModuleType): + app = test_module.app + client = test_module.client app.dependency_overrides = None response = client.get("/items/?q=foo&skip=100&limit=200") assert response.status_code == 200, response.text diff --git a/tests/test_tutorial/test_testing_dependencies/test_tutorial001_an.py b/tests/test_tutorial/test_testing_dependencies/test_tutorial001_an.py deleted file mode 100644 index fc1f9149a..000000000 --- a/tests/test_tutorial/test_testing_dependencies/test_tutorial001_an.py +++ /dev/null @@ -1,56 +0,0 @@ -from docs_src.dependency_testing.tutorial001_an import ( - app, - client, - test_override_in_items, - test_override_in_items_with_params, - test_override_in_items_with_q, -) - - -def test_override_in_items_run(): - test_override_in_items() - - -def test_override_in_items_with_q_run(): - test_override_in_items_with_q() - - -def test_override_in_items_with_params_run(): - test_override_in_items_with_params() - - -def test_override_in_users(): - response = client.get("/users/") - assert response.status_code == 200, response.text - assert response.json() == { - "message": "Hello Users!", - "params": {"q": None, "skip": 5, "limit": 10}, - } - - -def test_override_in_users_with_q(): - response = client.get("/users/?q=foo") - assert response.status_code == 200, response.text - assert response.json() == { - "message": "Hello Users!", - "params": {"q": "foo", "skip": 5, "limit": 10}, - } - - -def test_override_in_users_with_params(): - response = client.get("/users/?q=foo&skip=100&limit=200") - assert response.status_code == 200, response.text - assert response.json() == { - "message": "Hello Users!", - "params": {"q": "foo", "skip": 5, "limit": 10}, - } - - -def test_normal_app(): - app.dependency_overrides = None - response = client.get("/items/?q=foo&skip=100&limit=200") - assert response.status_code == 200, response.text - assert response.json() == { - "message": "Hello Items!", - "params": {"q": "foo", "skip": 100, "limit": 200}, - } diff --git a/tests/test_tutorial/test_testing_dependencies/test_tutorial001_an_py310.py b/tests/test_tutorial/test_testing_dependencies/test_tutorial001_an_py310.py deleted file mode 100644 index a3d27f47f..000000000 --- a/tests/test_tutorial/test_testing_dependencies/test_tutorial001_an_py310.py +++ /dev/null @@ -1,75 +0,0 @@ -from ...utils import needs_py310 - - -@needs_py310 -def test_override_in_items_run(): - from docs_src.dependency_testing.tutorial001_an_py310 import test_override_in_items - - test_override_in_items() - - -@needs_py310 -def test_override_in_items_with_q_run(): - from docs_src.dependency_testing.tutorial001_an_py310 import ( - test_override_in_items_with_q, - ) - - test_override_in_items_with_q() - - -@needs_py310 -def test_override_in_items_with_params_run(): - from docs_src.dependency_testing.tutorial001_an_py310 import ( - test_override_in_items_with_params, - ) - - test_override_in_items_with_params() - - -@needs_py310 -def test_override_in_users(): - from docs_src.dependency_testing.tutorial001_an_py310 import client - - response = client.get("/users/") - assert response.status_code == 200, response.text - assert response.json() == { - "message": "Hello Users!", - "params": {"q": None, "skip": 5, "limit": 10}, - } - - -@needs_py310 -def test_override_in_users_with_q(): - from docs_src.dependency_testing.tutorial001_an_py310 import client - - response = client.get("/users/?q=foo") - assert response.status_code == 200, response.text - assert response.json() == { - "message": "Hello Users!", - "params": {"q": "foo", "skip": 5, "limit": 10}, - } - - -@needs_py310 -def test_override_in_users_with_params(): - from docs_src.dependency_testing.tutorial001_an_py310 import client - - response = client.get("/users/?q=foo&skip=100&limit=200") - assert response.status_code == 200, response.text - assert response.json() == { - "message": "Hello Users!", - "params": {"q": "foo", "skip": 5, "limit": 10}, - } - - -@needs_py310 -def test_normal_app(): - from docs_src.dependency_testing.tutorial001_an_py310 import app, client - - app.dependency_overrides = None - response = client.get("/items/?q=foo&skip=100&limit=200") - assert response.status_code == 200, response.text - assert response.json() == { - "message": "Hello Items!", - "params": {"q": "foo", "skip": 100, "limit": 200}, - } diff --git a/tests/test_tutorial/test_testing_dependencies/test_tutorial001_an_py39.py b/tests/test_tutorial/test_testing_dependencies/test_tutorial001_an_py39.py deleted file mode 100644 index f03ed5e07..000000000 --- a/tests/test_tutorial/test_testing_dependencies/test_tutorial001_an_py39.py +++ /dev/null @@ -1,75 +0,0 @@ -from ...utils import needs_py39 - - -@needs_py39 -def test_override_in_items_run(): - from docs_src.dependency_testing.tutorial001_an_py39 import test_override_in_items - - test_override_in_items() - - -@needs_py39 -def test_override_in_items_with_q_run(): - from docs_src.dependency_testing.tutorial001_an_py39 import ( - test_override_in_items_with_q, - ) - - test_override_in_items_with_q() - - -@needs_py39 -def test_override_in_items_with_params_run(): - from docs_src.dependency_testing.tutorial001_an_py39 import ( - test_override_in_items_with_params, - ) - - test_override_in_items_with_params() - - -@needs_py39 -def test_override_in_users(): - from docs_src.dependency_testing.tutorial001_an_py39 import client - - response = client.get("/users/") - assert response.status_code == 200, response.text - assert response.json() == { - "message": "Hello Users!", - "params": {"q": None, "skip": 5, "limit": 10}, - } - - -@needs_py39 -def test_override_in_users_with_q(): - from docs_src.dependency_testing.tutorial001_an_py39 import client - - response = client.get("/users/?q=foo") - assert response.status_code == 200, response.text - assert response.json() == { - "message": "Hello Users!", - "params": {"q": "foo", "skip": 5, "limit": 10}, - } - - -@needs_py39 -def test_override_in_users_with_params(): - from docs_src.dependency_testing.tutorial001_an_py39 import client - - response = client.get("/users/?q=foo&skip=100&limit=200") - assert response.status_code == 200, response.text - assert response.json() == { - "message": "Hello Users!", - "params": {"q": "foo", "skip": 5, "limit": 10}, - } - - -@needs_py39 -def test_normal_app(): - from docs_src.dependency_testing.tutorial001_an_py39 import app, client - - app.dependency_overrides = None - response = client.get("/items/?q=foo&skip=100&limit=200") - assert response.status_code == 200, response.text - assert response.json() == { - "message": "Hello Items!", - "params": {"q": "foo", "skip": 100, "limit": 200}, - } diff --git a/tests/test_tutorial/test_testing_dependencies/test_tutorial001_py310.py b/tests/test_tutorial/test_testing_dependencies/test_tutorial001_py310.py deleted file mode 100644 index 776b916ff..000000000 --- a/tests/test_tutorial/test_testing_dependencies/test_tutorial001_py310.py +++ /dev/null @@ -1,75 +0,0 @@ -from ...utils import needs_py310 - - -@needs_py310 -def test_override_in_items_run(): - from docs_src.dependency_testing.tutorial001_py310 import test_override_in_items - - test_override_in_items() - - -@needs_py310 -def test_override_in_items_with_q_run(): - from docs_src.dependency_testing.tutorial001_py310 import ( - test_override_in_items_with_q, - ) - - test_override_in_items_with_q() - - -@needs_py310 -def test_override_in_items_with_params_run(): - from docs_src.dependency_testing.tutorial001_py310 import ( - test_override_in_items_with_params, - ) - - test_override_in_items_with_params() - - -@needs_py310 -def test_override_in_users(): - from docs_src.dependency_testing.tutorial001_py310 import client - - response = client.get("/users/") - assert response.status_code == 200, response.text - assert response.json() == { - "message": "Hello Users!", - "params": {"q": None, "skip": 5, "limit": 10}, - } - - -@needs_py310 -def test_override_in_users_with_q(): - from docs_src.dependency_testing.tutorial001_py310 import client - - response = client.get("/users/?q=foo") - assert response.status_code == 200, response.text - assert response.json() == { - "message": "Hello Users!", - "params": {"q": "foo", "skip": 5, "limit": 10}, - } - - -@needs_py310 -def test_override_in_users_with_params(): - from docs_src.dependency_testing.tutorial001_py310 import client - - response = client.get("/users/?q=foo&skip=100&limit=200") - assert response.status_code == 200, response.text - assert response.json() == { - "message": "Hello Users!", - "params": {"q": "foo", "skip": 5, "limit": 10}, - } - - -@needs_py310 -def test_normal_app(): - from docs_src.dependency_testing.tutorial001_py310 import app, client - - app.dependency_overrides = None - response = client.get("/items/?q=foo&skip=100&limit=200") - assert response.status_code == 200, response.text - assert response.json() == { - "message": "Hello Items!", - "params": {"q": "foo", "skip": 100, "limit": 200}, - } diff --git a/tests/test_union_forms.py b/tests/test_union_forms.py new file mode 100644 index 000000000..cbe98ea82 --- /dev/null +++ b/tests/test_union_forms.py @@ -0,0 +1,156 @@ +from typing import Union + +from fastapi import FastAPI, Form +from fastapi.testclient import TestClient +from pydantic import BaseModel +from typing_extensions import Annotated + +app = FastAPI() + + +class UserForm(BaseModel): + name: str + email: str + + +class CompanyForm(BaseModel): + company_name: str + industry: str + + +@app.post("/form-union/") +def post_union_form(data: Annotated[Union[UserForm, CompanyForm], Form()]): + return {"received": data} + + +client = TestClient(app) + + +def test_post_user_form(): + response = client.post( + "/form-union/", data={"name": "John Doe", "email": "john@example.com"} + ) + assert response.status_code == 200, response.text + assert response.json() == { + "received": {"name": "John Doe", "email": "john@example.com"} + } + + +def test_post_company_form(): + response = client.post( + "/form-union/", data={"company_name": "Tech Corp", "industry": "Technology"} + ) + assert response.status_code == 200, response.text + assert response.json() == { + "received": {"company_name": "Tech Corp", "industry": "Technology"} + } + + +def test_invalid_form_data(): + response = client.post( + "/form-union/", + data={"name": "John", "company_name": "Tech Corp"}, + ) + assert response.status_code == 422, response.text + + +def test_empty_form(): + response = client.post("/form-union/") + assert response.status_code == 422, response.text + + +def test_openapi_schema(): + response = client.get("/openapi.json") + assert response.status_code == 200, response.text + + assert response.json() == { + "openapi": "3.1.0", + "info": {"title": "FastAPI", "version": "0.1.0"}, + "paths": { + "/form-union/": { + "post": { + "summary": "Post Union Form", + "operationId": "post_union_form_form_union__post", + "requestBody": { + "content": { + "application/x-www-form-urlencoded": { + "schema": { + "anyOf": [ + {"$ref": "#/components/schemas/UserForm"}, + {"$ref": "#/components/schemas/CompanyForm"}, + ], + "title": "Data", + } + } + }, + "required": True, + }, + "responses": { + "200": { + "description": "Successful Response", + "content": {"application/json": {"schema": {}}}, + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + }, + }, + }, + } + } + }, + "components": { + "schemas": { + "CompanyForm": { + "properties": { + "company_name": {"type": "string", "title": "Company Name"}, + "industry": {"type": "string", "title": "Industry"}, + }, + "type": "object", + "required": ["company_name", "industry"], + "title": "CompanyForm", + }, + "HTTPValidationError": { + "properties": { + "detail": { + "items": {"$ref": "#/components/schemas/ValidationError"}, + "type": "array", + "title": "Detail", + } + }, + "type": "object", + "title": "HTTPValidationError", + }, + "UserForm": { + "properties": { + "name": {"type": "string", "title": "Name"}, + "email": {"type": "string", "title": "Email"}, + }, + "type": "object", + "required": ["name", "email"], + "title": "UserForm", + }, + "ValidationError": { + "properties": { + "loc": { + "items": { + "anyOf": [{"type": "string"}, {"type": "integer"}] + }, + "type": "array", + "title": "Location", + }, + "msg": {"type": "string", "title": "Message"}, + "type": {"type": "string", "title": "Error Type"}, + }, + "type": "object", + "required": ["loc", "msg", "type"], + "title": "ValidationError", + }, + } + }, + } diff --git a/tests/test_validate_response_recursive/app_pv1.py b/tests/test_validate_response_recursive/app.py similarity index 79% rename from tests/test_validate_response_recursive/app_pv1.py rename to tests/test_validate_response_recursive/app.py index 4cfc4b3ee..d23d27980 100644 --- a/tests/test_validate_response_recursive/app_pv1.py +++ b/tests/test_validate_response_recursive/app.py @@ -1,6 +1,7 @@ from typing import List from fastapi import FastAPI +from fastapi._compat import PYDANTIC_V2 from pydantic import BaseModel app = FastAPI() @@ -11,9 +12,6 @@ class RecursiveItem(BaseModel): name: str -RecursiveItem.update_forward_refs() - - class RecursiveSubitemInSubmodel(BaseModel): sub_items2: List["RecursiveItemViaSubmodel"] = [] name: str @@ -24,7 +22,13 @@ class RecursiveItemViaSubmodel(BaseModel): name: str -RecursiveSubitemInSubmodel.update_forward_refs() +if PYDANTIC_V2: + RecursiveItem.model_rebuild() + RecursiveSubitemInSubmodel.model_rebuild() + RecursiveItemViaSubmodel.model_rebuild() +else: + RecursiveItem.update_forward_refs() + RecursiveSubitemInSubmodel.update_forward_refs() @app.get("/items/recursive", response_model=RecursiveItem) diff --git a/tests/test_validate_response_recursive/app_pv2.py b/tests/test_validate_response_recursive/app_pv2.py deleted file mode 100644 index 8c93a8349..000000000 --- a/tests/test_validate_response_recursive/app_pv2.py +++ /dev/null @@ -1,51 +0,0 @@ -from typing import List - -from fastapi import FastAPI -from pydantic import BaseModel - -app = FastAPI() - - -class RecursiveItem(BaseModel): - sub_items: List["RecursiveItem"] = [] - name: str - - -RecursiveItem.model_rebuild() - - -class RecursiveSubitemInSubmodel(BaseModel): - sub_items2: List["RecursiveItemViaSubmodel"] = [] - name: str - - -class RecursiveItemViaSubmodel(BaseModel): - sub_items1: List[RecursiveSubitemInSubmodel] = [] - name: str - - -RecursiveSubitemInSubmodel.model_rebuild() -RecursiveItemViaSubmodel.model_rebuild() - - -@app.get("/items/recursive", response_model=RecursiveItem) -def get_recursive(): - return {"name": "item", "sub_items": [{"name": "subitem", "sub_items": []}]} - - -@app.get("/items/recursive-submodel", response_model=RecursiveItemViaSubmodel) -def get_recursive_submodel(): - return { - "name": "item", - "sub_items1": [ - { - "name": "subitem", - "sub_items2": [ - { - "name": "subsubitem", - "sub_items1": [{"name": "subsubsubitem", "sub_items2": []}], - } - ], - } - ], - } diff --git a/tests/test_validate_response_recursive/test_validate_response_recursive_pv2.py b/tests/test_validate_response_recursive/test_validate_response_recursive.py similarity index 90% rename from tests/test_validate_response_recursive/test_validate_response_recursive_pv2.py rename to tests/test_validate_response_recursive/test_validate_response_recursive.py index 7d45e7fe4..21a299ab8 100644 --- a/tests/test_validate_response_recursive/test_validate_response_recursive_pv2.py +++ b/tests/test_validate_response_recursive/test_validate_response_recursive.py @@ -1,12 +1,9 @@ from fastapi.testclient import TestClient -from ..utils import needs_pydanticv2 +from .app import app -@needs_pydanticv2 def test_recursive(): - from .app_pv2 import app - client = TestClient(app) response = client.get("/items/recursive") assert response.status_code == 200, response.text diff --git a/tests/test_validate_response_recursive/test_validate_response_recursive_pv1.py b/tests/test_validate_response_recursive/test_validate_response_recursive_pv1.py deleted file mode 100644 index de578ae03..000000000 --- a/tests/test_validate_response_recursive/test_validate_response_recursive_pv1.py +++ /dev/null @@ -1,33 +0,0 @@ -from fastapi.testclient import TestClient - -from ..utils import needs_pydanticv1 - - -@needs_pydanticv1 -def test_recursive(): - from .app_pv1 import app - - client = TestClient(app) - response = client.get("/items/recursive") - assert response.status_code == 200, response.text - assert response.json() == { - "sub_items": [{"name": "subitem", "sub_items": []}], - "name": "item", - } - - response = client.get("/items/recursive-submodel") - assert response.status_code == 200, response.text - assert response.json() == { - "name": "item", - "sub_items1": [ - { - "name": "subitem", - "sub_items2": [ - { - "name": "subsubitem", - "sub_items1": [{"name": "subsubsubitem", "sub_items2": []}], - } - ], - } - ], - } diff --git a/tests/utils.py b/tests/utils.py index 460c028f7..ae9543e3b 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -2,6 +2,7 @@ import sys import pytest from fastapi._compat import PYDANTIC_V2 +from inline_snapshot import Snapshot needs_py39 = pytest.mark.skipif(sys.version_info < (3, 9), reason="requires python3.9+") needs_py310 = pytest.mark.skipif( @@ -9,3 +10,25 @@ needs_py310 = pytest.mark.skipif( ) needs_pydanticv2 = pytest.mark.skipif(not PYDANTIC_V2, reason="requires Pydantic v2") needs_pydanticv1 = pytest.mark.skipif(PYDANTIC_V2, reason="requires Pydantic v1") + + +def pydantic_snapshot( + *, + v2: Snapshot, + v1: Snapshot, # TODO: remove v1 argument when deprecating Pydantic v1 +): + """ + This function should be used like this: + + >>> assert value == pydantic_snapshot(v2=snapshot(),v1=snapshot()) + + inline-snapshot will create the snapshots when pytest is executed for each versions of pydantic. + + It is also possible to use the function inside snapshots for version-specific values. + + >>> assert value == snapshot({ + "data": "some data", + "version_specific": pydantic_snapshot(v2=snapshot(),v1=snapshot()), + }) + """ + return v2 if PYDANTIC_V2 else v1