diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml index 128b69e94..fe2a39c45 100644 --- a/.github/workflows/build-docs.yml +++ b/.github/workflows/build-docs.yml @@ -4,10 +4,6 @@ on: branches: - master pull_request: - types: - - opened - - synchronize - permissions: {} jobs: @@ -21,7 +17,7 @@ jobs: outputs: docs: ${{ steps.filter.outputs.docs }} steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: false # For pull requests it's not necessary to checkout the code but for the main branch it is @@ -47,19 +43,19 @@ jobs: outputs: langs: ${{ steps.show-langs.outputs.langs }} steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: false - name: Set up Python - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 with: python-version-file: ".python-version" - name: Setup uv - uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 + uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0 with: # Before upgrading uv version, make sure astral-sh/setup-uv knows its checksum. # See: https://github.com/astral-sh/setup-uv/issues/851#issuecomment-4282017837 - version: "0.11.4" + version: "0.11.18" enable-cache: true cache-dependency-glob: | pyproject.toml @@ -86,19 +82,19 @@ jobs: env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: false - name: Set up Python - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 with: python-version-file: ".python-version" - name: Setup uv - uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 + uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0 with: # Before upgrading uv version, make sure astral-sh/setup-uv knows its checksum. # See: https://github.com/astral-sh/setup-uv/issues/851#issuecomment-4282017837 - version: "0.11.4" + version: "0.11.18" enable-cache: true cache-dependency-glob: | pyproject.toml @@ -107,7 +103,7 @@ jobs: run: uv sync --locked --no-dev --group docs - name: Update Languages run: uv run ./scripts/docs.py update-languages - - uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 + - uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 with: key: zensical-${{ matrix.lang }}-${{ github.ref }} path: site_zensical_src/${{ matrix.lang }}/.cache diff --git a/.github/workflows/contributors.yml b/.github/workflows/contributors.yml index cc963ee55..1d869e7b8 100644 --- a/.github/workflows/contributors.yml +++ b/.github/workflows/contributors.yml @@ -23,19 +23,19 @@ jobs: env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: true # Required for `git push` in `contributors.py` - name: Set up Python - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 with: python-version-file: ".python-version" - name: Setup uv - uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 + uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0 with: # Before upgrading uv version, make sure astral-sh/setup-uv knows its checksum. # See: https://github.com/astral-sh/setup-uv/issues/851#issuecomment-4282017837 - version: "0.11.4" + version: "0.11.18" enable-cache: true cache-dependency-glob: | pyproject.toml @@ -44,7 +44,7 @@ jobs: run: uv sync --locked --no-dev --group github-actions # Allow debugging with tmate - name: Setup tmate session - uses: mxschmitt/action-tmate@c0afd6f790e3a5564914980036ebf83216678101 # v3.23 + uses: mxschmitt/action-tmate@35b54afac29c97fb54faba5b513f8fbd1882f113 # v3.24 if: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.debug_enabled == 'true' }} with: limit-access-to-actor: true diff --git a/.github/workflows/create-draft-release.yml b/.github/workflows/create-draft-release.yml index 2f6134341..e0af097e2 100644 --- a/.github/workflows/create-draft-release.yml +++ b/.github/workflows/create-draft-release.yml @@ -22,20 +22,20 @@ jobs: env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: ref: ${{ github.event.repository.default_branch }} persist-credentials: true - name: Set up Python - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 with: python-version-file: ".python-version" - name: Install uv - uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 + uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0 with: # Before upgrading uv version, make sure astral-sh/setup-uv knows its checksum. # See: https://github.com/astral-sh/setup-uv/issues/851#issuecomment-4282017837 - version: "0.11.4" + version: "0.11.18" - name: Extract release details id: release-details run: | diff --git a/.github/workflows/deploy-docs.yml b/.github/workflows/deploy-docs.yml index 1009ec6aa..d8353ad55 100644 --- a/.github/workflows/deploy-docs.yml +++ b/.github/workflows/deploy-docs.yml @@ -22,19 +22,19 @@ jobs: env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: false - name: Set up Python - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 with: python-version-file: ".python-version" - name: Setup uv - uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 + uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0 with: # Before upgrading uv version, make sure astral-sh/setup-uv knows its checksum. # See: https://github.com/astral-sh/setup-uv/issues/851#issuecomment-4282017837 - version: "0.11.4" + version: "0.11.18" enable-cache: false - name: Install GitHub Actions dependencies run: uv sync --locked --no-dev --group github-actions diff --git a/.github/workflows/issue-manager.yml b/.github/workflows/issue-manager.yml index fca3f1f2f..bba089c6f 100644 --- a/.github/workflows/issue-manager.yml +++ b/.github/workflows/issue-manager.yml @@ -29,29 +29,6 @@ jobs: env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - - uses: tiangolo/issue-manager@2fb3484ec9279485df8659e8ec73de262431737d # 0.6.0 + - uses: tiangolo/issue-manager@75d60679db1ea348f6f6ea1d0e20de80a7c04645 # 0.7.1 with: token: ${{ secrets.GITHUB_TOKEN }} - config: > - { - "answered": { - "delay": 864000, - "message": "Assuming the original need was handled, this will be automatically closed now. But feel free to add more comments or create new issues or PRs." - }, - "waiting": { - "delay": 2628000, - "message": "As this PR has been waiting for the original user for a while but seems to be inactive, it's now going to be closed. But if there's anyone interested, feel free to create a new PR.", - "reminder": { - "before": "P3D", - "message": "Heads-up: this will be closed in 3 days unless there's new activity." - } - }, - "invalid": { - "delay": 0, - "message": "This was marked as invalid and will be closed now. If this is an error, please provide additional details." - }, - "maybe-ai": { - "delay": 0, - "message": "This was marked as potentially AI generated and will be closed now. If this is an error, please provide additional details, make sure to read the docs about contributing and AI." - } - } diff --git a/.github/workflows/label-approved.yml b/.github/workflows/label-approved.yml index 55ec5c1c1..6d4f2ef52 100644 --- a/.github/workflows/label-approved.yml +++ b/.github/workflows/label-approved.yml @@ -19,19 +19,19 @@ jobs: env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: false - name: Set up Python - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 with: python-version-file: ".python-version" - name: Setup uv - uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 + uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0 with: # Before upgrading uv version, make sure astral-sh/setup-uv knows its checksum. # See: https://github.com/astral-sh/setup-uv/issues/851#issuecomment-4282017837 - version: "0.11.4" + version: "0.11.18" enable-cache: true cache-dependency-glob: | pyproject.toml diff --git a/.github/workflows/latest-changes.yml b/.github/workflows/latest-changes.yml index 92f8f24c9..111b47424 100644 --- a/.github/workflows/latest-changes.yml +++ b/.github/workflows/latest-changes.yml @@ -28,14 +28,14 @@ jobs: env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: # To allow latest-changes to commit to the main branch token: ${{ secrets.FASTAPI_LATEST_CHANGES }} # zizmor: ignore[secrets-outside-env] persist-credentials: true # required by tiangolo/latest-changes # Allow debugging with tmate - name: Setup tmate session - uses: mxschmitt/action-tmate@c0afd6f790e3a5564914980036ebf83216678101 # v3.23 + uses: mxschmitt/action-tmate@35b54afac29c97fb54faba5b513f8fbd1882f113 # v3.24 if: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.debug_enabled == 'true' }} with: limit-access-to-actor: true diff --git a/.github/workflows/notify-translations.yml b/.github/workflows/notify-translations.yml index 820ac7040..aa006978c 100644 --- a/.github/workflows/notify-translations.yml +++ b/.github/workflows/notify-translations.yml @@ -30,19 +30,19 @@ jobs: env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: false - name: Set up Python - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 with: python-version-file: ".python-version" - name: Setup uv - uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 + uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0 with: # Before upgrading uv version, make sure astral-sh/setup-uv knows its checksum. # See: https://github.com/astral-sh/setup-uv/issues/851#issuecomment-4282017837 - version: "0.11.4" + version: "0.11.18" enable-cache: true cache-dependency-glob: | pyproject.toml @@ -51,7 +51,7 @@ jobs: run: uv sync --locked --no-dev --group github-actions # Allow debugging with tmate - name: Setup tmate session - uses: mxschmitt/action-tmate@c0afd6f790e3a5564914980036ebf83216678101 # v3.23 + uses: mxschmitt/action-tmate@35b54afac29c97fb54faba5b513f8fbd1882f113 # v3.24 if: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.debug_enabled == 'true' }} with: limit-access-to-actor: true diff --git a/.github/workflows/people.yml b/.github/workflows/people.yml index b9c0502a5..2e48c9d70 100644 --- a/.github/workflows/people.yml +++ b/.github/workflows/people.yml @@ -23,19 +23,19 @@ jobs: env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: true # Required for `git push` in `people.py` - name: Set up Python - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 with: python-version-file: ".python-version" - name: Setup uv - uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 + uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0 with: # Before upgrading uv version, make sure astral-sh/setup-uv knows its checksum. # See: https://github.com/astral-sh/setup-uv/issues/851#issuecomment-4282017837 - version: "0.11.4" + version: "0.11.18" enable-cache: true cache-dependency-glob: | pyproject.toml @@ -44,7 +44,7 @@ jobs: run: uv sync --locked --no-dev --group github-actions # Allow debugging with tmate - name: Setup tmate session - uses: mxschmitt/action-tmate@c0afd6f790e3a5564914980036ebf83216678101 # v3.23 + uses: mxschmitt/action-tmate@35b54afac29c97fb54faba5b513f8fbd1882f113 # v3.24 if: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.debug_enabled == 'true' }} with: limit-access-to-actor: true diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml index 1e156b249..963fd68ab 100644 --- a/.github/workflows/pre-commit.yml +++ b/.github/workflows/pre-commit.yml @@ -2,10 +2,6 @@ name: pre-commit on: pull_request: - types: - - opened - - synchronize - permissions: {} env: @@ -21,7 +17,7 @@ jobs: env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 name: Checkout PR for own repo if: env.HAS_SECRETS == 'true' with: @@ -34,7 +30,7 @@ jobs: token: ${{ secrets.PRE_COMMIT }} # zizmor: ignore[secrets-outside-env] persist-credentials: true # Required for `git push` command # pre-commit lite ci needs the default checkout configs to work - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 name: Checkout PR for fork if: env.HAS_SECRETS == 'false' with: @@ -43,15 +39,15 @@ jobs: fetch-depth: 0 persist-credentials: false - name: Set up Python - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 with: python-version-file: ".python-version" - name: Setup uv - uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 + uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0 with: # Before upgrading uv version, make sure astral-sh/setup-uv knows its checksum. # See: https://github.com/astral-sh/setup-uv/issues/851#issuecomment-4282017837 - version: "0.11.4" + version: "0.11.18" cache-dependency-glob: | pyproject.toml uv.lock diff --git a/.github/workflows/prepare-release.yml b/.github/workflows/prepare-release.yml index 73bf4affc..5b241aa4f 100644 --- a/.github/workflows/prepare-release.yml +++ b/.github/workflows/prepare-release.yml @@ -34,20 +34,20 @@ jobs: env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: token: ${{ secrets.FASTAPI_LATEST_CHANGES }} # zizmor: ignore[secrets-outside-env] persist-credentials: true - name: Set up Python - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 with: python-version-file: ".python-version" - name: Install uv - uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 + uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0 with: # Before upgrading uv version, make sure astral-sh/setup-uv knows its checksum. # See: https://github.com/astral-sh/setup-uv/issues/851#issuecomment-4282017837 - version: "0.11.4" + version: "0.11.18" - name: Prepare release env: PREPARE_RELEASE_BUMP: ${{ inputs.bump }} diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 57a6af204..447ce8c33 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -19,19 +19,19 @@ jobs: env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: false - name: Set up Python - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 with: python-version-file: ".python-version" - name: Install uv - uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 + uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0 with: # Before upgrading uv version, make sure astral-sh/setup-uv knows its checksum. # See: https://github.com/astral-sh/setup-uv/issues/851#issuecomment-4282017837 - version: "0.11.4" + version: "0.11.18" enable-cache: "false" - name: Build distribution run: uv build diff --git a/.github/workflows/smokeshow.yml b/.github/workflows/smokeshow.yml index 27bb8b195..41804cee9 100644 --- a/.github/workflows/smokeshow.yml +++ b/.github/workflows/smokeshow.yml @@ -19,18 +19,18 @@ jobs: env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: false - - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + - uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 with: python-version-file: ".python-version" - name: Setup uv - uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 + uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0 with: # Before upgrading uv version, make sure astral-sh/setup-uv knows its checksum. # See: https://github.com/astral-sh/setup-uv/issues/851#issuecomment-4282017837 - version: "0.11.4" + version: "0.11.18" cache-dependency-glob: | pyproject.toml uv.lock diff --git a/.github/workflows/sponsors.yml b/.github/workflows/sponsors.yml index f1538caef..a20dcaf05 100644 --- a/.github/workflows/sponsors.yml +++ b/.github/workflows/sponsors.yml @@ -24,19 +24,19 @@ jobs: env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: true # Required for `git push` in `sponsors.py` - name: Set up Python - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 with: python-version-file: ".python-version" - name: Setup uv - uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 + uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0 with: # Before upgrading uv version, make sure astral-sh/setup-uv knows its checksum. # See: https://github.com/astral-sh/setup-uv/issues/851#issuecomment-4282017837 - version: "0.11.4" + version: "0.11.18" enable-cache: true cache-dependency-glob: | pyproject.toml @@ -45,7 +45,7 @@ jobs: run: uv sync --locked --no-dev --group github-actions # Allow debugging with tmate - name: Setup tmate session - uses: mxschmitt/action-tmate@c0afd6f790e3a5564914980036ebf83216678101 # v3.23 + uses: mxschmitt/action-tmate@35b54afac29c97fb54faba5b513f8fbd1882f113 # v3.24 if: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.debug_enabled == 'true' }} with: limit-access-to-actor: true diff --git a/.github/workflows/test-redistribute.yml b/.github/workflows/test-redistribute.yml index c78fbff56..cffb9d8c8 100644 --- a/.github/workflows/test-redistribute.yml +++ b/.github/workflows/test-redistribute.yml @@ -5,10 +5,6 @@ on: branches: - master pull_request: - types: - - opened - - synchronize - permissions: {} jobs: @@ -20,11 +16,11 @@ jobs: env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: false - name: Set up Python - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 with: python-version-file: ".python-version" - name: Install build dependencies diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index df77c9bde..e28e90e3e 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -5,9 +5,6 @@ on: branches: - master pull_request: - types: - - opened - - synchronize schedule: # cron every week on monday - cron: "0 0 * * 1" @@ -29,7 +26,7 @@ jobs: outputs: src: ${{ steps.filter.outputs.src }} steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: false # For pull requests it's not necessary to checkout the code but for the main branch it is @@ -110,19 +107,19 @@ jobs: env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: false - name: Set up Python - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 with: python-version: ${{ matrix.python-version }} - name: Setup uv - uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 + uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0 with: # Before upgrading uv version, make sure astral-sh/setup-uv knows its checksum. # See: https://github.com/astral-sh/setup-uv/issues/851#issuecomment-4282017837 - version: "0.11.4" + version: "0.11.18" enable-cache: true cache-dependency-glob: | pyproject.toml @@ -174,19 +171,19 @@ jobs: env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: false - name: Set up Python - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 with: python-version: "3.13" - name: Setup uv - uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 + uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0 with: # Before upgrading uv version, make sure astral-sh/setup-uv knows its checksum. # See: https://github.com/astral-sh/setup-uv/issues/851#issuecomment-4282017837 - version: "0.11.4" + version: "0.11.18" enable-cache: true cache-dependency-glob: | pyproject.toml @@ -194,7 +191,7 @@ jobs: - name: Install Dependencies run: uv sync --no-dev --group tests --extra all - name: CodSpeed benchmarks - uses: CodSpeedHQ/action@3194d9a39c4d46684cb44bf7207fc56626aad8fd # v4.15.1 + uses: CodSpeedHQ/action@63f3e98b61959fe67f146a3ff022e4136fe9bb9c # v4.17.6 with: mode: simulation run: uv run --no-sync pytest tests/benchmarks --codspeed @@ -209,18 +206,18 @@ jobs: env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: false - - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + - uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 with: python-version-file: ".python-version" - name: Setup uv - uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 + uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0 with: # Before upgrading uv version, make sure astral-sh/setup-uv knows its checksum. # See: https://github.com/astral-sh/setup-uv/issues/851#issuecomment-4282017837 - version: "0.11.4" + version: "0.11.18" enable-cache: true cache-dependency-glob: | pyproject.toml @@ -245,9 +242,10 @@ jobs: - run: uv run coverage report --fail-under=100 # https://github.com/marketplace/actions/alls-green#why - check: # This job does nothing and is only used for the branch protection + test-alls-green: # This job does nothing and is only used for the branch protection if: always() needs: + - test - coverage-combine - benchmark runs-on: ubuntu-latest diff --git a/.github/workflows/topic-repos.yml b/.github/workflows/topic-repos.yml index 1b34f1f58..b0fb40398 100644 --- a/.github/workflows/topic-repos.yml +++ b/.github/workflows/topic-repos.yml @@ -19,19 +19,19 @@ jobs: env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: true # Required for `git push` in `topic_repos.py` - name: Set up Python - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 with: python-version-file: ".python-version" - name: Setup uv - uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 + uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0 with: # Before upgrading uv version, make sure astral-sh/setup-uv knows its checksum. # See: https://github.com/astral-sh/setup-uv/issues/851#issuecomment-4282017837 - version: "0.11.4" + version: "0.11.18" enable-cache: true cache-dependency-glob: | pyproject.toml diff --git a/.github/workflows/translate.yml b/.github/workflows/translate.yml index 4c624c93c..7f96798da 100644 --- a/.github/workflows/translate.yml +++ b/.github/workflows/translate.yml @@ -50,19 +50,19 @@ jobs: langs: ${{ steps.show-langs.outputs.langs }} commands: ${{ steps.show-langs.outputs.commands }} steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: false - name: Set up Python - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 with: python-version-file: ".python-version" - name: Setup uv - uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 + uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0 with: # Before upgrading uv version, make sure astral-sh/setup-uv knows its checksum. # See: https://github.com/astral-sh/setup-uv/issues/851#issuecomment-4282017837 - version: "0.11.4" + version: "0.11.18" cache-dependency-glob: | pyproject.toml uv.lock @@ -92,20 +92,20 @@ jobs: env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: fetch-depth: 0 persist-credentials: true # Required for `git push` in `translate.py` - name: Set up Python - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 with: python-version-file: ".python-version" - name: Setup uv - uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 + uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0 with: # Before upgrading uv version, make sure astral-sh/setup-uv knows its checksum. # See: https://github.com/astral-sh/setup-uv/issues/851#issuecomment-4282017837 - version: "0.11.4" + version: "0.11.18" cache-dependency-glob: | pyproject.toml uv.lock @@ -113,7 +113,7 @@ jobs: run: uv sync --locked --no-dev --group github-actions --group translations # Allow debugging with tmate - name: Setup tmate session - uses: mxschmitt/action-tmate@c0afd6f790e3a5564914980036ebf83216678101 # v3.23 + uses: mxschmitt/action-tmate@35b54afac29c97fb54faba5b513f8fbd1882f113 # v3.24 if: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.debug_enabled == 'true' }} with: limit-access-to-actor: true diff --git a/.github/workflows/zizmor.yml b/.github/workflows/zizmor.yml index 7cf628679..11ecb8272 100644 --- a/.github/workflows/zizmor.yml +++ b/.github/workflows/zizmor.yml @@ -4,6 +4,7 @@ on: push: branches: - main + pull_request: workflow_dispatch: permissions: {} @@ -17,8 +18,8 @@ jobs: security-events: write # Required for upload-sarif (used by zizmor-action) to upload SARIF files. steps: - name: Checkout repository - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: false - name: Run zizmor - uses: zizmorcore/zizmor-action@5f14fd08f7cf1cb1609c1e344975f152c7ee938d # v0.5.6 + uses: zizmorcore/zizmor-action@192e21d79ab29983730a13d1382995c2307fbcaa # v0.5.7 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index b53e2c9ea..eb0762df5 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -15,7 +15,7 @@ repos: - id: trailing-whitespace - repo: https://github.com/crate-ci/typos - rev: bbaefadf97b0ec5fdc942684b647f1a6ab250274 # v1.46.0 + rev: 37bb98842b0d8c4ffebdb75301a13db0267cef89 # v1.47.2 hooks: - id: typos args: [--force-exclude] @@ -45,7 +45,7 @@ repos: - id: local-ty name: ty check - entry: uv run ty check fastapi + entry: uv run ty check require_serial: true language: unsupported pass_filenames: false @@ -65,6 +65,13 @@ repos: files: ^docs/en/docs/index\.md|docs/en/data/sponsors\.yml|scripts/docs\.py$ pass_filenames: false + - id: render-banner-sponsors + language: unsupported + name: render sponsor banner partial + entry: uv run ./scripts/docs.py render-banner-sponsors + files: ^docs/en/data/sponsors\.yml|^docs/en/overrides/partials/banner-sponsors\.html|^scripts/docs\.py$ + pass_filenames: false + - id: update-languages language: unsupported name: update languages diff --git a/README.md b/README.md index 86e751090..03cd90e77 100644 --- a/README.md +++ b/README.md @@ -52,9 +52,7 @@ The key features are: ### Gold Sponsors - - @@ -66,12 +64,10 @@ The key features are: - - - + @@ -435,13 +431,13 @@ For a more complete example including more features, see the Dependency Injection** system. * Security and authentication, including support for **OAuth2** with **JWT tokens** and **HTTP Basic** auth. * More advanced (but equally easy) techniques for declaring **deeply nested JSON models** (thanks to Pydantic). * **GraphQL** integration with [Strawberry](https://strawberry.rocks) and other libraries. -* Many extra features (thanks to Starlette) as: +* Many extra features (thanks to Starlette) such as: * **WebSockets** * extremely easy tests based on HTTPX and `pytest` * **CORS** @@ -450,9 +446,7 @@ For a more complete example including more features, see the @@ -468,6 +462,8 @@ Deploying to FastAPI Cloud... +The CLI will automatically detect your FastAPI application and deploy it to the cloud. If you are not logged in, your browser will open to complete the authentication process. + That's it! Now you can access your app at that URL. ✨ #### About FastAPI Cloud diff --git a/docs/de/docs/_llm-test.md b/docs/de/docs/_llm-test.md index 81e8e25f5..3fec41817 100644 --- a/docs/de/docs/_llm-test.md +++ b/docs/de/docs/_llm-test.md @@ -1,17 +1,17 @@ # LLM-Testdatei { #llm-test-file } -Dieses Dokument testet, ob das LLM, das die Dokumentation übersetzt, den `general_prompt` in `scripts/translate.py` und den sprachspezifischen Prompt in `docs/{language code}/llm-prompt.md` versteht. Der sprachsspezifische Prompt wird an `general_prompt` angehängt. +Dieses Dokument testet, ob das LLM, das die Dokumentation übersetzt, den `general_prompt` in `scripts/translate.py` und den sprachspezifischen Prompt in `docs/{language code}/llm-prompt.md` versteht. Der sprachspezifische Prompt wird an `general_prompt` angehängt. -Hier hinzugefügte Tests werden von allen Erstellern sprachsspezifischer Prompts gesehen. +Hier hinzugefügte Tests werden von allen Erstellern sprachspezifischer Prompts gesehen. So verwenden: -* Einen sprachsspezifischen Prompt haben – `docs/{language code}/llm-prompt.md`. +* Einen sprachspezifischen Prompt haben – `docs/{language code}/llm-prompt.md`. * Eine frische Übersetzung dieses Dokuments in die gewünschte Zielsprache durchführen (siehe z. B. das Kommando `translate-page` der `translate.py`). Dadurch wird die Übersetzung unter `docs/{language code}/docs/_llm-test.md` erstellt. * Prüfen Sie, ob in der Übersetzung alles in Ordnung ist. -* Verbessern Sie bei Bedarf Ihren sprachsspezifischen Prompt, den allgemeinen Prompt oder das englische Dokument. +* Verbessern Sie bei Bedarf Ihren sprachspezifischen Prompt, den allgemeinen Prompt oder das englische Dokument. * Beheben Sie anschließend manuell die verbleibenden Probleme in der Übersetzung, sodass es eine gute Übersetzung ist. -* Übersetzen Sie erneut, nachdem die gute Übersetzung vorliegt. Das ideale Ergebnis wäre, dass das LLM an der Übersetzung keine Änderungen mehr vornimmt. Das bedeutet, dass der allgemeine Prompt und Ihr sprachsspezifischer Prompt so gut sind, wie sie sein können (Es wird manchmal ein paar scheinbar zufällige Änderungen machen, der Grund ist, dass [LLMs keine deterministischen Algorithmen sind](https://doublespeak.chat/#/handbook#deterministic-output)). +* Übersetzen Sie erneut, nachdem die gute Übersetzung vorliegt. Das ideale Ergebnis wäre, dass das LLM an der Übersetzung keine Änderungen mehr vornimmt. Das bedeutet, dass der allgemeine Prompt und Ihr sprachspezifischer Prompt so gut sind, wie sie sein können (Es wird manchmal ein paar scheinbar zufällige Änderungen machen, der Grund ist, dass [LLMs keine deterministischen Algorithmen sind](https://doublespeak.chat/#/handbook#deterministic-output)). Die Tests: @@ -211,7 +211,7 @@ Siehe Abschnitt `### HTML abbr elements` im allgemeinen Prompt in `scripts/trans //// -## HTML „dfn“-Elemente { #html-dfn-elements } +## HTML-„dfn“-Elemente { #html-dfn-elements } * Cluster * Deep Learning @@ -240,7 +240,7 @@ Die einzige strenge Regel für Überschriften ist, dass das LLM den Hash-Teil in Siehe Abschnitt `### Headings` im allgemeinen Prompt in `scripts/translate.py`. -Für einige sprachsspezifische Anweisungen, siehe z. B. den Abschnitt `### Headings` in `docs/de/llm-prompt.md`. +Für einige sprachspezifische Anweisungen, siehe z. B. den Abschnitt `### Headings` in `docs/de/llm-prompt.md`. //// @@ -363,12 +363,12 @@ Für einige sprachsspezifische Anweisungen, siehe z. B. den Abschnitt `### Headi * die Umgebungsvariable * die Umgebungsvariable * der `PATH` -* die `PATH`-Umgebungsvariable +* die `PATH`-Variable * die Authentifizierung * der Authentifizierungsanbieter * die Autorisierung -* das Anmeldeformular +* das Autorisierungsformular * der Autorisierungsanbieter * der Benutzer authentisiert sich * das System authentifiziert den Benutzer diff --git a/docs/de/docs/advanced/additional-responses.md b/docs/de/docs/advanced/additional-responses.md index bc7c477c8..f2214713b 100644 --- a/docs/de/docs/advanced/additional-responses.md +++ b/docs/de/docs/advanced/additional-responses.md @@ -34,7 +34,7 @@ Beachten Sie, dass Sie die `JSONResponse` direkt zurückgeben müssen. /// -/// info | Info +/// note | Hinweis Der `model`-Schlüssel ist nicht Teil von OpenAPI. @@ -183,7 +183,7 @@ Beachten Sie, dass Sie das Bild direkt mit einer `FileResponse` zurückgeben mü /// -/// info | Info +/// note | Hinweis Sofern Sie in Ihrem Parameter `responses` nicht explizit einen anderen Medientyp angeben, geht FastAPI davon aus, dass die Response denselben Medientyp wie die Haupt-Response-Klasse hat (Standardmäßig `application/json`). diff --git a/docs/de/docs/advanced/additional-status-codes.md b/docs/de/docs/advanced/additional-status-codes.md index f1a74a32c..6f0114cc1 100644 --- a/docs/de/docs/advanced/additional-status-codes.md +++ b/docs/de/docs/advanced/additional-status-codes.md @@ -1,5 +1,6 @@ # Zusätzliche Statuscodes { #additional-status-codes } + Standardmäßig liefert **FastAPI** die Responses als `JSONResponse` zurück und fügt den Inhalt, den Sie aus Ihrer *Pfadoperation* zurückgeben, in diese `JSONResponse` ein. Es wird der Default-Statuscode oder derjenige verwendet, den Sie in Ihrer *Pfadoperation* festgelegt haben. diff --git a/docs/de/docs/advanced/advanced-dependencies.md b/docs/de/docs/advanced/advanced-dependencies.md index ab2cab071..da06794a9 100644 --- a/docs/de/docs/advanced/advanced-dependencies.md +++ b/docs/de/docs/advanced/advanced-dependencies.md @@ -1,5 +1,6 @@ # Fortgeschrittene Abhängigkeiten { #advanced-dependencies } + ## Parametrisierte Abhängigkeiten { #parameterized-dependencies } Alle Abhängigkeiten, die wir bisher gesehen haben, waren festgelegte Funktionen oder Klassen. @@ -98,7 +99,7 @@ Wenn Sie beispielsweise eine Datenbanksession in einer Abhängigkeit mit `yield` Dieses Verhalten wurde in 0.118.0 zurückgenommen, sodass der Exit-Code nach `yield` ausgeführt wird, nachdem die Response gesendet wurde. -/// info | Info +/// note | Hinweis Wie Sie unten sehen werden, ähnelt dies sehr dem Verhalten vor Version 0.106.0, jedoch mit mehreren Verbesserungen und Bugfixes für Sonderfälle. diff --git a/docs/de/docs/advanced/custom-response.md b/docs/de/docs/advanced/custom-response.md index 9a11089ad..377c7f569 100644 --- a/docs/de/docs/advanced/custom-response.md +++ b/docs/de/docs/advanced/custom-response.md @@ -41,7 +41,7 @@ Um eine Response mit HTML direkt von **FastAPI** zurückzugeben, verwenden Sie ` {* ../../docs_src/custom_response/tutorial002_py310.py hl[2,7] *} -/// info | Info +/// note | Hinweis Der Parameter `response_class` wird auch verwendet, um den „Medientyp“ der Response zu definieren. @@ -65,7 +65,7 @@ Eine `Response`, die direkt von Ihrer *Pfadoperation-Funktion* zurückgegeben wi /// -/// info | Info +/// note | Hinweis Natürlich stammen der eigentliche `Content-Type`-Header, der Statuscode, usw., aus dem `Response`-Objekt, das Sie zurückgegeben haben. @@ -158,6 +158,7 @@ Sie können eine `RedirectResponse` direkt zurückgeben: Oder Sie können sie im Parameter `response_class` verwenden: + {* ../../docs_src/custom_response/tutorial006b_py310.py hl[2,7,9] *} Wenn Sie das tun, können Sie die URL direkt von Ihrer *Pfadoperation*-Funktion zurückgeben. diff --git a/docs/de/docs/advanced/dataclasses.md b/docs/de/docs/advanced/dataclasses.md index 743aea699..bacf9d162 100644 --- a/docs/de/docs/advanced/dataclasses.md +++ b/docs/de/docs/advanced/dataclasses.md @@ -1,5 +1,6 @@ # Datenklassen verwenden { #using-dataclasses } + FastAPI basiert auf **Pydantic**, und ich habe Ihnen gezeigt, wie Sie Pydantic-Modelle verwenden können, um Requests und Responses zu deklarieren. Aber FastAPI unterstützt auf die gleiche Weise auch die Verwendung von [`dataclasses`](https://docs.python.org/3/library/dataclasses.html): @@ -18,7 +19,7 @@ Und natürlich wird das gleiche unterstützt: Das funktioniert genauso wie mit Pydantic-Modellen. Und tatsächlich wird es unter der Haube mittels Pydantic auf die gleiche Weise bewerkstelligt. -/// info | Info +/// note | Hinweis Bedenken Sie, dass Datenklassen nicht alles können, was Pydantic-Modelle können. diff --git a/docs/de/docs/advanced/events.md b/docs/de/docs/advanced/events.md index ea04e3ebd..6efe96809 100644 --- a/docs/de/docs/advanced/events.md +++ b/docs/de/docs/advanced/events.md @@ -102,7 +102,7 @@ Diese Funktionen können mit `async def` oder normalem `def` deklariert werden. ### `startup`-Event { #startup-event } -Um eine Funktion hinzuzufügen, die vor dem Start der Anwendung ausgeführt werden soll, deklarieren Sie diese mit dem Event `startup`: +Um eine Funktion hinzuzufügen, die vor dem Start der Anwendung ausgeführt werden soll, deklarieren Sie diese mit dem Event `"startup"`: {* ../../docs_src/events/tutorial001_py310.py hl[8] *} @@ -114,13 +114,13 @@ Und Ihre Anwendung empfängt erst dann Requests, wenn alle `startup`-Eventhandle ### `shutdown`-Event { #shutdown-event } -Um eine Funktion hinzuzufügen, die beim Shutdown der Anwendung ausgeführt werden soll, deklarieren Sie sie mit dem Event `shutdown`: +Um eine Funktion hinzuzufügen, die beim Shutdown der Anwendung ausgeführt werden soll, deklarieren Sie sie mit dem Event `"shutdown"`: {* ../../docs_src/events/tutorial002_py310.py hl[6] *} Hier schreibt die `shutdown`-Eventhandler-Funktion eine Textzeile `"Application shutdown"` in eine Datei `log.txt`. -/// info | Info +/// note | Hinweis In der Funktion `open()` bedeutet `mode="a"` „append“ („anhängen“), sodass die Zeile nach dem, was sich in dieser Datei befindet, hinzugefügt wird, ohne den vorherigen Inhalt zu überschreiben. @@ -150,9 +150,9 @@ Aus diesem Grund wird jetzt empfohlen, stattdessen `lifespan` wie oben erläuter Nur ein technisches Detail für die neugierigen Nerds. 🤓 -In der technischen ASGI-Spezifikation ist dies Teil des [Lifespan Protokolls](https://asgi.readthedocs.io/en/latest/specs/lifespan.html) und definiert Events namens `startup` und `shutdown`. +In der technischen ASGI-Spezifikation ist dies Teil des [Lifespan-Protokolls](https://asgi.readthedocs.io/en/latest/specs/lifespan.html) und definiert Events namens `startup` und `shutdown`. -/// info | Info +/// note | Hinweis Weitere Informationen zu Starlettes `lifespan`-Handlern finden Sie in [Starlettes Lifespan-Dokumentation](https://www.starlette.dev/lifespan/). diff --git a/docs/de/docs/advanced/generate-clients.md b/docs/de/docs/advanced/generate-clients.md index 4eab5bcb6..d93641bd3 100644 --- a/docs/de/docs/advanced/generate-clients.md +++ b/docs/de/docs/advanced/generate-clients.md @@ -20,21 +20,6 @@ FastAPI generiert automatisch **OpenAPI 3.1**-Spezifikationen, daher muss jedes /// -## SDK-Generatoren von FastAPI-Sponsoren { #sdk-generators-from-fastapi-sponsors } - -Dieser Abschnitt hebt **venture-unterstützte** und **firmengestützte** Lösungen hervor, die von Unternehmen entwickelt werden, welche FastAPI sponsern. Diese Produkte bieten **zusätzliche Funktionen** und **Integrationen** zusätzlich zu hochwertig generierten SDKs. - -Durch das ✨ [**Sponsoring von FastAPI**](../help-fastapi.md#sponsor-the-author) ✨ helfen diese Unternehmen sicherzustellen, dass das Framework und sein **Ökosystem** gesund und **nachhaltig** bleiben. - -Ihr Sponsoring zeigt auch ein starkes Engagement für die FastAPI-**Community** (Sie), was bedeutet, dass sie nicht nur einen **großartigen Service** bieten möchten, sondern auch ein **robustes und florierendes Framework**, FastAPI, unterstützen möchten. 🙇 - -Zum Beispiel könnten Sie ausprobieren: - -* [Stainless](https://www.stainless.com/?utm_source=fastapi&utm_medium=referral) -* [liblab](https://developers.liblab.com/tutorials/sdk-for-fastapi?utm_source=fastapi) - -Einige dieser Lösungen sind möglicherweise auch Open Source oder bieten kostenlose Tarife an, sodass Sie diese ohne finanzielle Verpflichtung ausprobieren können. Andere kommerzielle SDK-Generatoren sind online verfügbar und können dort gefunden werden. 🤓 - ## Ein TypeScript-SDK erstellen { #create-a-typescript-sdk } Beginnen wir mit einer einfachen FastAPI-Anwendung: diff --git a/docs/de/docs/advanced/json-base64-bytes.md b/docs/de/docs/advanced/json-base64-bytes.md index 26c7e7089..618bbd1a9 100644 --- a/docs/de/docs/advanced/json-base64-bytes.md +++ b/docs/de/docs/advanced/json-base64-bytes.md @@ -4,7 +4,7 @@ Wenn Ihre App JSON-Daten empfangen und senden muss, Sie darin aber Binärdaten e ## Base64 vs Dateien { #base64-vs-files } -Prüfen Sie zunächst, ob Sie [Request Files](../tutorial/request-files.md) zum Hochladen von Binärdaten und [Benutzerdefinierte Response – FileResponse](./custom-response.md#fileresponse--fileresponse-) zum Senden von Binärdaten verwenden können, anstatt sie in JSON zu kodieren. +Prüfen Sie zunächst, ob Sie [Requestdateien](../tutorial/request-files.md) zum Hochladen von Binärdaten und [Benutzerdefinierte Response – FileResponse](./custom-response.md#fileresponse) zum Senden von Binärdaten verwenden können, anstatt sie in JSON zu kodieren. JSON kann nur UTF-8-kodierte Strings enthalten, es kann daher keine rohen Bytes enthalten. diff --git a/docs/de/docs/advanced/openapi-callbacks.md b/docs/de/docs/advanced/openapi-callbacks.md index 0d2471489..b5d49c7e8 100644 --- a/docs/de/docs/advanced/openapi-callbacks.md +++ b/docs/de/docs/advanced/openapi-callbacks.md @@ -12,7 +12,7 @@ Sehen wir uns das alles anhand eines Beispiels an. Stellen Sie sich vor, Sie entwickeln eine Anwendung, mit der Sie Rechnungen erstellen können. -Diese Rechnungen haben eine `id`, einen optionalen `title`, einen `customer` (Kunde) und ein `total` (Gesamtsumme). +Diese Rechnungen haben eine `id`, einen `title` (optional), einen `customer` und ein `total`. Der Benutzer Ihrer API (ein externer Entwickler) erstellt mit einem POST-Request eine Rechnung in Ihrer API. @@ -118,13 +118,13 @@ In diesem Fall ist es der `str`: "{$callback_url}/invoices/{$request.body.id}" ``` -Wenn Ihr API-Benutzer (der externe Entwickler) also einen Request an *Ihre API* sendet, via: +Wenn Ihr API-Benutzer (der externe Entwickler) also einen Request an *Ihre API* sendet, an: ``` https://yourapi.com/invoices/?callback_url=https://www.external.org/events ``` -mit einem JSON-Körper: +mit einem JSON-Body: ```JSON { @@ -167,13 +167,13 @@ Beachten Sie, dass die verwendete Callback-URL die URL enthält, die als Query-P An diesem Punkt haben Sie die benötigte(n) *Callback-Pfadoperation(en)* (diejenige(n), die der *externe Entwickler* in der *externen API* implementieren sollte) im Callback-Router, den Sie oben erstellt haben. -Verwenden Sie nun den Parameter `callbacks` im *Pfadoperation-Dekorator Ihrer API*, um das Attribut `.routes` (das ist eigentlich nur eine `list`e von Routen/*Pfadoperationen*) dieses Callback-Routers zu übergeben: +Verwenden Sie nun den Parameter `callbacks` im *Pfadoperation-Dekorator Ihrer API*, um das Attribut `.routes` dieses Callback-Routers zu übergeben: {* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[33] *} /// tip | Tipp -Beachten Sie, dass Sie nicht den Router selbst (`invoices_callback_router`) an `callback=` übergeben, sondern das Attribut `.routes`, wie in `invoices_callback_router.routes`. +Beachten Sie, dass Sie nicht den Router selbst (`invoices_callback_router`) an `callbacks=` übergeben, sondern dessen `.routes`, wie in `invoices_callback_router.routes`. FastAPI wird diese Routen verwenden, um die Callback-OpenAPI-Dokumentation zu generieren. /// diff --git a/docs/de/docs/advanced/openapi-webhooks.md b/docs/de/docs/advanced/openapi-webhooks.md index e6984de74..fbec6996a 100644 --- a/docs/de/docs/advanced/openapi-webhooks.md +++ b/docs/de/docs/advanced/openapi-webhooks.md @@ -22,7 +22,7 @@ Mit **FastAPI**, mithilfe von OpenAPI, können Sie die Namen dieser Webhooks, di Dies kann es Ihren Benutzern viel einfacher machen, **deren APIs zu implementieren**, um Ihre **Webhook**-Requests zu empfangen. Möglicherweise können diese sogar einen Teil ihres eigenen API-Codes automatisch generieren. -/// info | Info +/// note | Hinweis Webhooks sind in OpenAPI 3.1.0 und höher verfügbar und werden von FastAPI `0.99.0` und höher unterstützt. @@ -36,7 +36,7 @@ Wenn Sie eine **FastAPI**-Anwendung erstellen, gibt es ein `webhooks`-Attribut, Die von Ihnen definierten Webhooks landen im **OpenAPI**-Schema und der automatischen **Dokumentations-Oberfläche**. -/// info | Info +/// note | Hinweis Das `app.webhooks`-Objekt ist eigentlich nur ein `APIRouter`, derselbe Typ, den Sie verwenden würden, wenn Sie Ihre App mit mehreren Dateien strukturieren. diff --git a/docs/de/docs/advanced/path-operation-advanced-configuration.md b/docs/de/docs/advanced/path-operation-advanced-configuration.md index e6ff498eb..6899a582a 100644 --- a/docs/de/docs/advanced/path-operation-advanced-configuration.md +++ b/docs/de/docs/advanced/path-operation-advanced-configuration.md @@ -16,17 +16,11 @@ Sie müssten sicherstellen, dass sie für jede Operation eindeutig ist. ### Verwendung des Namens der *Pfadoperation-Funktion* als operationId { #using-the-path-operation-function-name-as-the-operationid } -Wenn Sie die Funktionsnamen Ihrer API als `operationId`s verwenden möchten, können Sie über alle iterieren und die `operation_id` jeder *Pfadoperation* mit deren `APIRoute.name` überschreiben. +Wenn Sie die Funktionsnamen Ihrer APIs als `operationId`s verwenden möchten, können Sie `FastAPI` eine eigene `generate_unique_id_function` übergeben. -Sie sollten dies tun, nachdem Sie alle Ihre *Pfadoperationen* hinzugefügt haben. +Diese Funktion erhält jeweils die `APIRoute` und gibt die `operationId` zurück, die für diese Pfadoperation verwendet werden soll. -{* ../../docs_src/path_operation_advanced_configuration/tutorial002_py310.py hl[2, 12:21, 24] *} - -/// tip | Tipp - -Wenn Sie `app.openapi()` manuell aufrufen, sollten Sie vorher die `operationId`s aktualisiert haben. - -/// +{* ../../docs_src/path_operation_advanced_configuration/tutorial002_py310.py hl[2,5:6,9] *} /// warning | Achtung diff --git a/docs/de/docs/advanced/response-change-status-code.md b/docs/de/docs/advanced/response-change-status-code.md index a0d90fe80..a334cc0bb 100644 --- a/docs/de/docs/advanced/response-change-status-code.md +++ b/docs/de/docs/advanced/response-change-status-code.md @@ -1,5 +1,6 @@ # Response – Statuscode ändern { #response-change-status-code } + Sie haben wahrscheinlich schon vorher gelesen, dass Sie einen Default-[Response-Statuscode](../tutorial/response-status-code.md) festlegen können. In manchen Fällen müssen Sie jedoch einen anderen als den Default-Statuscode zurückgeben. diff --git a/docs/de/docs/advanced/response-cookies.md b/docs/de/docs/advanced/response-cookies.md index 672bbbe78..34eb6cfe9 100644 --- a/docs/de/docs/advanced/response-cookies.md +++ b/docs/de/docs/advanced/response-cookies.md @@ -1,5 +1,6 @@ # Response-Cookies { #response-cookies } + ## Einen `Response`-Parameter verwenden { #use-a-response-parameter } Sie können einen Parameter vom Typ `Response` in Ihrer *Pfadoperation-Funktion* deklarieren. diff --git a/docs/de/docs/advanced/response-directly.md b/docs/de/docs/advanced/response-directly.md index 4235e8db0..fb5db473c 100644 --- a/docs/de/docs/advanced/response-directly.md +++ b/docs/de/docs/advanced/response-directly.md @@ -16,9 +16,9 @@ Normalerweise erzielen Sie eine deutlich bessere Leistung, wenn Sie ein [Respons ## Eine `Response` zurückgeben { #return-a-response } -Tatsächlich können Sie jede `Response` oder jede Unterklasse davon zurückgeben. +Sie können eine `Response` oder jede Unterklasse davon zurückgeben. -/// info | Info +/// note | Hinweis `JSONResponse` selbst ist eine Unterklasse von `Response`. diff --git a/docs/de/docs/advanced/response-headers.md b/docs/de/docs/advanced/response-headers.md index bcec04be8..baf5715a3 100644 --- a/docs/de/docs/advanced/response-headers.md +++ b/docs/de/docs/advanced/response-headers.md @@ -38,4 +38,4 @@ Und da die `Response` häufig zum Setzen von Headern und Cookies verwendet wird, Beachten Sie, dass benutzerdefinierte proprietäre Header [mit dem Präfix `X-`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers) hinzugefügt werden können. -Wenn Sie jedoch benutzerdefinierte Header haben, die ein Client in einem Browser sehen können soll, müssen Sie diese zu Ihrer CORS-Konfiguration hinzufügen (weitere Informationen finden Sie unter [CORS (Cross-Origin Resource Sharing)](../tutorial/cors.md)), unter Verwendung des Parameters `expose_headers`, dokumentiert in [Starlettes CORS-Dokumentation](https://www.starlette.dev/middleware/#corsmiddleware). +Wenn Sie jedoch benutzerdefinierte Header haben, die ein Client in einem Browser sehen können soll, müssen Sie diese zu Ihren CORS-Konfigurationen hinzufügen (weitere Informationen finden Sie unter [CORS (Cross-Origin Resource Sharing)](../tutorial/cors.md)), unter Verwendung des Parameters `expose_headers`, dokumentiert in [Starlettes CORS-Dokumentation](https://www.starlette.dev/middleware/#corsmiddleware). diff --git a/docs/de/docs/advanced/security/oauth2-scopes.md b/docs/de/docs/advanced/security/oauth2-scopes.md index a903fbeb9..74457b40d 100644 --- a/docs/de/docs/advanced/security/oauth2-scopes.md +++ b/docs/de/docs/advanced/security/oauth2-scopes.md @@ -18,7 +18,7 @@ Sie benötigen nicht unbedingt OAuth2-Scopes, und Sie können die Authentifizier Aber OAuth2 mit Scopes kann bequem in Ihre API (mit OpenAPI) und deren API-Dokumentation integriert werden. -Dennoch, verwenden Sie solche Scopes oder andere Sicherheits-/Autorisierungsanforderungen in Ihrem Code so wie Sie es möchten. +Dennoch erzwingen Sie solche Scopes oder andere Sicherheits-/Autorisierungsanforderungen in Ihrem Code so, wie Sie es benötigen. In vielen Fällen kann OAuth2 mit Scopes ein Overkill sein. @@ -46,7 +46,7 @@ Er wird normalerweise verwendet, um bestimmte Sicherheitsberechtigungen zu dekla * `instagram_basic` wird von Facebook / Instagram verwendet. * `https://www.googleapis.com/auth/drive` wird von Google verwendet. -/// info | Info +/// note | Hinweis In OAuth2 ist ein „Scope“ nur ein String, der eine bestimmte erforderliche Berechtigung deklariert. @@ -126,7 +126,7 @@ Wir tun dies hier, um zu demonstrieren, wie **FastAPI** auf verschiedenen Ebenen {* ../../docs_src/security/tutorial005_an_py310.py hl[5,141,172] *} -/// info | Technische Details +/// note | Technische Details `Security` ist tatsächlich eine Unterklasse von `Depends` und hat nur noch einen zusätzlichen Parameter, den wir später kennenlernen werden. @@ -247,7 +247,7 @@ Das würde einer Drittanbieteranwendung passieren, die versucht, auf eine dieser ## Über Integrationen von Drittanbietern { #about-third-party-integrations } -In diesem Beispiel verwenden wir den OAuth2-Flow „Password“. +In diesem Beispiel verwenden wir den OAuth2-Flow „password“. Das ist angemessen, wenn wir uns bei unserer eigenen Anwendung anmelden, wahrscheinlich mit unserem eigenen Frontend. @@ -255,9 +255,9 @@ Weil wir darauf vertrauen können, dass es den `username` und das `password` erh Wenn Sie jedoch eine OAuth2-Anwendung erstellen, mit der andere eine Verbindung herstellen würden (d.h. wenn Sie einen Authentifizierungsanbieter erstellen, der Facebook, Google, GitHub usw. entspricht), sollten Sie einen der anderen Flows verwenden. -Am häufigsten ist der „Implicit“-Flow. +Am häufigsten ist der implicit Flow. -Am sichersten ist der „Code“-Flow, die Implementierung ist jedoch komplexer, da mehr Schritte erforderlich sind. Da er komplexer ist, schlagen viele Anbieter letztendlich den „Implicit“-Flow vor. +Am sichersten ist der code Flow, die Implementierung ist jedoch komplexer, da mehr Schritte erforderlich sind. Da er komplexer ist, schlagen viele Anbieter letztendlich den implicit Flow vor. /// note | Hinweis diff --git a/docs/de/docs/advanced/settings.md b/docs/de/docs/advanced/settings.md index 1df74802b..993e5ae71 100644 --- a/docs/de/docs/advanced/settings.md +++ b/docs/de/docs/advanced/settings.md @@ -14,13 +14,13 @@ Um Umgebungsvariablen zu verstehen, können Sie [Umgebungsvariablen](../environm ## Typen und Validierung { #types-and-validation } -Diese Umgebungsvariablen können nur Text-Zeichenketten verarbeiten, da sie außerhalb von Python liegen und mit anderen Programmen und dem Rest des Systems (und sogar mit verschiedenen Betriebssystemen wie Linux, Windows, macOS) kompatibel sein müssen. +Diese Umgebungsvariablen können nur Text-Strings verarbeiten, da sie außerhalb von Python liegen und mit anderen Programmen und dem Rest des Systems (und sogar mit verschiedenen Betriebssystemen wie Linux, Windows, macOS) kompatibel sein müssen. Das bedeutet, dass jeder in Python aus einer Umgebungsvariablen gelesene Wert ein `str` ist und jede Konvertierung in einen anderen Typ oder jede Validierung im Code erfolgen muss. ## Pydantic `Settings` { #pydantic-settings } -Glücklicherweise bietet Pydantic ein großartiges Werkzeug zur Verarbeitung dieser Einstellungen, die von Umgebungsvariablen stammen, mit [Pydantic: Settings Management](https://docs.pydantic.dev/latest/concepts/pydantic_settings/). +Glücklicherweise bietet Pydantic ein großartiges Werkzeug zur Verarbeitung dieser Einstellungen, die von Umgebungsvariablen stammen, mit [Pydantic: Settings-Verwaltung](https://docs.pydantic.dev/latest/concepts/pydantic_settings/). ### `pydantic-settings` installieren { #install-pydantic-settings } @@ -92,9 +92,9 @@ Um mehrere Umgebungsvariablen für einen einzelnen Befehl festzulegen, trennen S /// -Und dann würde die Einstellung `admin_email` auf „deadpool@example.com“ gesetzt. +Und dann würde die Einstellung `admin_email` auf `"deadpool@example.com"` gesetzt. -Der `app_name` wäre „ChimichangApp“. +Der `app_name` wäre `"ChimichangApp"`. Und `items_per_user` würde seinen Defaultwert von `50` behalten. @@ -128,7 +128,7 @@ Ausgehend vom vorherigen Beispiel könnte Ihre Datei `config.py` so aussehen: {* ../../docs_src/settings/app02_an_py310/config.py hl[10] *} -Beachten Sie, dass wir jetzt keine Standardinstanz `settings = Settings()` erstellen. +Beachten Sie, dass wir jetzt keine Defaultinstanz `settings = Settings()` erstellen. ### Die Haupt-Anwendungsdatei { #the-main-app-file } @@ -158,7 +158,7 @@ Bei der Abhängigkeitsüberschreibung legen wir einen neuen Wert für `admin_ema Dann können wir testen, ob das verwendet wird. -## Lesen einer `.env`-Datei { #reading-a-env-file } +## Eine `.env`-Datei lesen { #reading-a-env-file } Wenn Sie viele Einstellungen haben, die sich möglicherweise oft ändern, vielleicht in verschiedenen Umgebungen, kann es nützlich sein, diese in eine Datei zu schreiben und sie dann daraus zu lesen, als wären sie Umgebungsvariablen. @@ -172,7 +172,7 @@ Aber eine dotenv-Datei muss nicht unbedingt genau diesen Dateinamen haben. /// -Pydantic unterstützt das Lesen dieser Dateitypen mithilfe einer externen Bibliothek. Weitere Informationen finden Sie unter [Pydantic Settings: Dotenv (.env) support](https://docs.pydantic.dev/latest/concepts/pydantic_settings/#dotenv-env-support). +Pydantic unterstützt das Lesen dieser Dateitypen mithilfe einer externen Bibliothek. Weitere Informationen finden Sie unter [Pydantic Settings: Dotenv (.env)-Unterstützung](https://docs.pydantic.dev/latest/concepts/pydantic_settings/#dotenv-env-support). /// tip | Tipp @@ -197,13 +197,13 @@ Und dann aktualisieren Sie Ihre `config.py` mit: /// tip | Tipp -Das Attribut `model_config` wird nur für die Pydantic-Konfiguration verwendet. Weitere Informationen finden Sie unter [Pydantic: Concepts: Configuration](https://docs.pydantic.dev/latest/concepts/config/). +Das Attribut `model_config` wird nur für die Pydantic-Konfiguration verwendet. Weitere Informationen finden Sie unter [Pydantic: Konzepte: Konfiguration](https://docs.pydantic.dev/latest/concepts/config/). /// Hier definieren wir die Konfiguration `env_file` innerhalb Ihrer Pydantic-`Settings`-Klasse und setzen den Wert auf den Dateinamen mit der dotenv-Datei, die wir verwenden möchten. -### Die `Settings` nur einmal laden mittels `lru_cache` { #creating-the-settings-only-once-with-lru-cache } +### Die `Settings` nur einmal mittels `lru_cache` erstellen { #creating-the-settings-only-once-with-lru-cache } Das Lesen einer Datei von der Festplatte ist normalerweise ein kostspieliger (langsamer) Vorgang, daher möchten Sie ihn wahrscheinlich nur einmal ausführen und dann dasselbe Einstellungsobjekt erneut verwenden, anstatt es für jeden Request zu lesen. @@ -291,7 +291,7 @@ Im Fall unserer Abhängigkeit `get_settings()` akzeptiert die Funktion nicht ein Auf diese Weise verhält es sich fast so, als wäre es nur eine globale Variable. Da es jedoch eine Abhängigkeitsfunktion verwendet, können wir diese zu Testzwecken problemlos überschreiben. -`@lru_cache` ist Teil von `functools`, welches Teil von Pythons Standardbibliothek ist. Weitere Informationen dazu finden Sie in der [Python Dokumentation für `@lru_cache`](https://docs.python.org/3/library/functools.html#functools.lru_cache). +`@lru_cache` ist Teil von `functools`, welches Teil von Pythons Standardbibliothek ist. Weitere Informationen dazu finden Sie in der [Python-Dokumentation für `@lru_cache`](https://docs.python.org/3/library/functools.html#functools.lru_cache). ## Zusammenfassung { #recap } diff --git a/docs/de/docs/advanced/stream-data.md b/docs/de/docs/advanced/stream-data.md index 7cff1d47e..16ff73e78 100644 --- a/docs/de/docs/advanced/stream-data.md +++ b/docs/de/docs/advanced/stream-data.md @@ -4,7 +4,7 @@ Wenn Sie Daten streamen möchten, die als JSON strukturiert werden können, soll Wenn Sie jedoch **reine Binärdaten** oder Strings streamen möchten, so können Sie es machen. -/// info | Info +/// note | Hinweis Hinzugefügt in FastAPI 0.134.0. @@ -20,13 +20,13 @@ Sie könnten auf diese Weise auch **Video** oder **Audio** streamen, es könnte ## Eine `StreamingResponse` mit `yield` { #a-streamingresponse-with-yield } -Wenn Sie in Ihrer Pfadoperation-Funktion ein `response_class=StreamingResponse` deklarieren, können Sie `yield` verwenden, um nacheinander jeden Datenchunk zu senden. +Wenn Sie in Ihrer *Pfadoperation-Funktion* ein `response_class=StreamingResponse` deklarieren, können Sie `yield` verwenden, um nacheinander jeden Datenchunk zu senden. {* ../../docs_src/stream_data/tutorial001_py310.py ln[1:23] hl[20,23] *} FastAPI übergibt jeden Datenchunk unverändert an die `StreamingResponse`, es wird nicht versucht, ihn in JSON oder etwas Ähnliches zu konvertieren. -### Nicht-async-Pfadoperation-Funktionen { #non-async-path-operation-functions } +### Nicht-async-*Pfadoperation-Funktionen* { #non-async-path-operation-functions } Sie können auch reguläre `def`-Funktionen (ohne `async`) verwenden und `yield` auf die gleiche Weise einsetzen. @@ -58,7 +58,7 @@ Zum Beispiel können Sie eine `PNGStreamingResponse` erstellen, die den `Content {* ../../docs_src/stream_data/tutorial002_py310.py ln[6,19:20] hl[20] *} -Dann können Sie diese neue Klasse mit `response_class=PNGStreamingResponse` in Ihrer Pfadoperation-Funktion verwenden: +Dann können Sie diese neue Klasse mit `response_class=PNGStreamingResponse` in Ihrer *Pfadoperation-Funktion* verwenden: {* ../../docs_src/stream_data/tutorial002_py310.py ln[23:27] hl[23] *} @@ -90,7 +90,7 @@ Beispielsweise haben sie kein `await file.read()` oder `async for chunk in file` Und in vielen Fällen wäre das Lesen eine blockierende Operation (die die Event-Loop blockieren könnte), weil von der Festplatte oder aus dem Netzwerk gelesen wird. -/// info | Info +/// note | Hinweis Das obige Beispiel ist tatsächlich eine Ausnahme, weil sich das `io.BytesIO`-Objekt bereits im Speicher befindet, daher blockiert sein Lesen nichts. @@ -98,7 +98,7 @@ Aber in vielen Fällen würde das Lesen einer Datei oder eines dateiähnlichen O /// -Um die Event-Loop nicht zu blockieren, können Sie die Pfadoperation-Funktion einfach mit normalem `def` statt `async def` deklarieren, dadurch führt FastAPI sie in einem Threadpool-Worker aus, um die Haupt-Event-Loop nicht zu blockieren. +Um die Event-Loop nicht zu blockieren, können Sie die *Pfadoperation-Funktion* einfach mit normalem `def` statt `async def` deklarieren, dadurch führt FastAPI sie in einem Threadpool-Worker aus, um die Haupt-Event-Loop nicht zu blockieren. {* ../../docs_src/stream_data/tutorial002_py310.py ln[30:34] hl[31] *} diff --git a/docs/de/docs/advanced/strict-content-type.md b/docs/de/docs/advanced/strict-content-type.md index 2fcfa3e09..db9ab9f24 100644 --- a/docs/de/docs/advanced/strict-content-type.md +++ b/docs/de/docs/advanced/strict-content-type.md @@ -81,7 +81,7 @@ Wenn Sie Clients unterstützen müssen, die keinen `Content-Type`-Header senden, Mit dieser Einstellung werden Requests ohne `Content-Type`-Header im Body als JSON geparst. Das entspricht dem Verhalten älterer FastAPI-Versionen. -/// info | Info +/// note | Hinweis Dieses Verhalten und diese Konfiguration wurden in FastAPI 0.132.0 hinzugefügt. diff --git a/docs/de/docs/advanced/websockets.md b/docs/de/docs/advanced/websockets.md index c96cfb28b..a0f3a1f33 100644 --- a/docs/de/docs/advanced/websockets.md +++ b/docs/de/docs/advanced/websockets.md @@ -111,7 +111,7 @@ Diese funktionieren auf die gleiche Weise wie für andere FastAPI-Endpunkte/*Pfa {* ../../docs_src/websockets_/tutorial002_an_py310.py hl[68:69,82] *} -/// info | Info +/// note | Hinweis Da es sich um einen WebSocket handelt, macht es keinen Sinn, eine `HTTPException` auszulösen, stattdessen lösen wir eine `WebSocketException` aus. diff --git a/docs/de/docs/advanced/wsgi.md b/docs/de/docs/advanced/wsgi.md index 89e513dc0..353734a3a 100644 --- a/docs/de/docs/advanced/wsgi.md +++ b/docs/de/docs/advanced/wsgi.md @@ -1,12 +1,13 @@ # WSGI inkludieren – Flask, Django und andere { #including-wsgi-flask-django-others } + Sie können WSGI-Anwendungen mounten, wie Sie es in [Unteranwendungen – Mounts](sub-applications.md), [Hinter einem Proxy](behind-a-proxy.md) gesehen haben. Dazu können Sie die `WSGIMiddleware` verwenden und damit Ihre WSGI-Anwendung wrappen, zum Beispiel Flask, Django usw. ## `WSGIMiddleware` verwenden { #using-wsgimiddleware } -/// info | Info +/// note | Hinweis Dafür muss `a2wsgi` installiert sein, z. B. mit `pip install a2wsgi`. diff --git a/docs/de/docs/alternatives.md b/docs/de/docs/alternatives.md index 70948e499..5a814cb55 100644 --- a/docs/de/docs/alternatives.md +++ b/docs/de/docs/alternatives.md @@ -283,7 +283,7 @@ Aus diesem Grund basiert **FastAPI** auf Starlette, da dieses das schnellste ver Falcon ist ein weiteres leistungsstarkes Python-Framework. Es ist minimalistisch konzipiert und dient als Grundlage für andere Frameworks wie Hug. -Es ist so konzipiert, dass es über Funktionen verfügt, welche zwei Parameter empfangen, einen „Request“ und eine „Response“. Dann „lesen“ Sie Teile des Requests und „schreiben“ Teile der Response. Aufgrund dieses Designs ist es nicht möglich, Request-Parameter und -Bodys mit Standard-Python-Typhinweisen als Funktionsparameter zu deklarieren. +Es ist so konzipiert, dass es über Funktionen verfügt, welche zwei Parameter empfangen, einen „Request“ und eine „Response“. Dann „lesen“ Sie Teile des Requests und „schreiben“ Teile der Response. Aufgrund dieses Designs ist es nicht möglich, Request-Parameter und Requestbodys mit Standard-Python-Typhinweisen als Funktionsparameter zu deklarieren. Daher müssen Datenvalidierung, Serialisierung und Dokumentation im Code und nicht automatisch erfolgen. Oder sie müssen als Framework oberhalb von Falcon implementiert werden, so wie Hug. Dieselbe Unterscheidung findet auch in anderen Frameworks statt, die vom Design von Falcon inspiriert sind und ein Requestobjekt und ein Responseobjekt als Parameter haben. @@ -351,11 +351,11 @@ Hug inspirierte **FastAPI** dazu, einen `response`-Parameter in Funktionen zu de /// -### [APIStar](https://github.com/encode/apistar) (≦ 0.5) { #apistar-0-5 } +### [APIStar](https://github.com/encode/apistar) (<= 0.5) { #apistar-0-5 } Kurz bevor ich mich entschied, **FastAPI** zu erstellen, fand ich den **APIStar**-Server. Er hatte fast alles, was ich suchte, und ein tolles Design. -Er war eine der ersten Implementierungen eines Frameworks, die ich je gesehen hatte (vor NestJS und Molten), welches Python-Typhinweise zur Deklaration von Parametern und Requests verwendeten. Ich habe ihn mehr oder weniger zeitgleich mit Hug gefunden. Aber APIStar nutzte den OpenAPI-Standard. +Er war eine der ersten Implementierungen eines Frameworks, die ich je gesehen hatte (vor NestJS und Molten), das Python-Typhinweise zur Deklaration von Parametern und Requests verwendete. Ich habe ihn mehr oder weniger zeitgleich mit Hug gefunden. Aber APIStar nutzte den OpenAPI-Standard. Er verfügte an mehreren Stellen über automatische Datenvalidierung, Datenserialisierung und OpenAPI-Schemagenerierung, basierend auf denselben Typhinweisen. @@ -433,7 +433,7 @@ Es bietet: * CORS, GZip, statische Dateien, Responses streamen. * Session- und Cookie-Unterstützung. * 100 % Testabdeckung. -* 100 % Typannotierte Codebasis. +* 100 % typannotierte Codebasis. * Wenige starke Abhängigkeiten. Starlette ist derzeit das schnellste getestete Python-Framework. Nur übertroffen von Uvicorn, welches kein Framework, sondern ein Server ist. @@ -448,7 +448,7 @@ Das ist eines der wichtigsten Dinge, welche **FastAPI** hinzufügt, alles basier ASGI ist ein neuer „Standard“, welcher von Mitgliedern des Django-Kernteams entwickelt wird. Es handelt sich immer noch nicht um einen „Python-Standard“ (ein PEP), obwohl sie gerade dabei sind, das zu tun. -Dennoch wird es bereits von mehreren Tools als „Standard“ verwendet. Das verbessert die Interoperabilität erheblich, da Sie Uvicorn mit jeden anderen ASGI-Server (wie Daphne oder Hypercorn) tauschen oder ASGI-kompatible Tools wie `python-socketio` hinzufügen können. +Dennoch wird es bereits von mehreren Tools als „Standard“ verwendet. Das verbessert die Interoperabilität erheblich, da Sie Uvicorn mit jedem anderen ASGI-Server (wie Daphne oder Hypercorn) tauschen oder ASGI-kompatible Tools wie `python-socketio` hinzufügen können. /// diff --git a/docs/de/docs/async.md b/docs/de/docs/async.md index d2a3a1de2..060e39bf9 100644 --- a/docs/de/docs/async.md +++ b/docs/de/docs/async.md @@ -44,7 +44,7 @@ Wenn Ihre Anwendung (irgendwie) nicht mit etwas anderem kommunizieren und auf de --- -Wenn Sie sich unsicher sind, verwenden Sie einfach `def`. +Wenn Sie sich unsicher sind, verwenden Sie normales `def`. --- @@ -70,7 +70,7 @@ Asynchroner Code bedeutet lediglich, dass die Sprache 💬 eine Möglichkeit hat Während der Zeit, die „Langsam-Datei“ 📝 benötigt, kann das System also andere Aufgaben erledigen. -Dann kommt der Computer / das Programm 🤖 bei jeder Gelegenheit zurück, weil es entweder wieder wartet oder wann immer es 🤖 die ganze Arbeit erledigt hat, die zu diesem Zeitpunkt zu tun war. Und es 🤖 wird nachschauen, ob eine der Aufgaben, auf die es gewartet hat, fertig ist. +Dann kommt der Computer / das Programm 🤖 bei jeder Gelegenheit zurück, weil es entweder wieder wartet oder wann immer es 🤖 die ganze Arbeit erledigt hat, die zu diesem Zeitpunkt zu tun war. Und es 🤖 wird nachschauen, ob eine der Aufgaben, auf die es gewartet hat, bereits fertig ist, und tun, was es zu tun hatte. Dann nimmt es 🤖 die erste erledigte Aufgabe (sagen wir, unsere „Langsam-Datei“ 📝) und bearbeitet sie weiter. @@ -361,7 +361,7 @@ Wenn Sie mit **FastAPI** arbeiten, müssen Sie sich darüber keine Sorgen machen Wenn Sie jedoch `async` / `await` ohne FastAPI verwenden möchten, können Sie dies auch tun. -### Schreiben Sie Ihren eigenen asynchronen Code { #write-your-own-async-code } +### Ihren eigenen asynchronen Code schreiben { #write-your-own-async-code } Starlette (und **FastAPI**) basieren auf [AnyIO](https://anyio.readthedocs.io/en/stable/), was bedeutet, dass es sowohl kompatibel mit der Python-Standardbibliothek [asyncio](https://docs.python.org/3/library/asyncio-task.html) als auch mit [Trio](https://trio.readthedocs.io/en/stable/) ist. diff --git a/docs/de/docs/deployment/cloud.md b/docs/de/docs/deployment/cloud.md index 2c8fe85c4..75f7ef881 100644 --- a/docs/de/docs/deployment/cloud.md +++ b/docs/de/docs/deployment/cloud.md @@ -16,7 +16,7 @@ FastAPI Cloud ist der Hauptsponsor und Finanzierungsgeber für die *FastAPI and ## Cloudanbieter – Sponsoren { #cloud-providers-sponsors } -Einige andere Cloudanbieter ✨ [**sponsern FastAPI**](../help-fastapi.md#sponsor-the-author) ✨ ebenfalls. 🙇 +Einige andere Cloudanbieter ✨ [**sponsern FastAPI**](https://github.com/sponsors/tiangolo) ✨ ebenfalls. 🙇 Sie könnten diese ebenfalls in Betracht ziehen, deren Anleitungen folgen und ihre Dienste ausprobieren: diff --git a/docs/de/docs/deployment/concepts.md b/docs/de/docs/deployment/concepts.md index be00b2260..487ad6392 100644 --- a/docs/de/docs/deployment/concepts.md +++ b/docs/de/docs/deployment/concepts.md @@ -1,6 +1,6 @@ # Deployment-Konzepte { #deployments-concepts } -Bei dem Deployment – der Bereitstellung – einer **FastAPI**-Anwendung, oder eigentlich jeder Art von Web-API, gibt es mehrere Konzepte, die Sie wahrscheinlich interessieren, und mithilfe der Sie die **am besten geeignete** Methode zum **Deployment Ihrer Anwendung** finden können. +Beim Deployment einer **FastAPI**-Anwendung, oder eigentlich jeder Art von Web-API, gibt es mehrere Konzepte, die Sie wahrscheinlich interessieren, und mithilfe derer Sie die **am besten geeignete** Methode zum **Deployment Ihrer Anwendung** finden können. Einige wichtige Konzepte sind: @@ -59,7 +59,7 @@ Die nächsten zu berücksichtigenden Konzepte drehen sich dann um das Programm, Wir werden viel über den laufenden „**Prozess**“ sprechen, daher ist es nützlich, Klarheit darüber zu haben, was das bedeutet und was der Unterschied zum Wort „**Programm**“ ist. -### Was ist ein Programm { #what-is-a-program } +### Was ein Programm ist { #what-is-a-program } Das Wort **Programm** wird häufig zur Beschreibung vieler Dinge verwendet: @@ -67,14 +67,14 @@ Das Wort **Programm** wird häufig zur Beschreibung vieler Dinge verwendet: * Die **Datei**, die vom Betriebssystem **ausgeführt** werden kann, zum Beispiel: `python`, `python.exe` oder `uvicorn`. * Ein bestimmtes Programm, während es auf dem Betriebssystem **läuft**, die CPU nutzt und Dinge im Arbeitsspeicher ablegt. Dies wird auch als **Prozess** bezeichnet. -### Was ist ein Prozess { #what-is-a-process } +### Was ein Prozess ist { #what-is-a-process } Das Wort **Prozess** wird normalerweise spezifischer verwendet und bezieht sich nur auf das, was im Betriebssystem ausgeführt wird (wie im letzten Punkt oben): * Ein bestimmtes Programm, während es auf dem Betriebssystem **ausgeführt** wird. * Dies bezieht sich weder auf die Datei noch auf den Code, sondern **speziell** auf das, was vom Betriebssystem **ausgeführt** und verwaltet wird. -* Jedes Programm, jeder Code **kann nur dann Dinge tun**, wenn er **ausgeführt** wird, wenn also ein **Prozess läuft**. -* Der Prozess kann von Ihnen oder vom Betriebssystem **terminiert** („beendet“, „gekillt“) werden. An diesem Punkt hört es auf zu laufen/ausgeführt zu werden und kann **keine Dinge mehr tun**. +* Jedes Programm, jeder Code **kann nur dann Dinge tun**, wenn er **ausgeführt** wird. Also dann, wenn ein **Prozess läuft**. +* Der Prozess kann von Ihnen oder vom Betriebssystem **terminiert** („beendet“, „gekillt“) werden. An diesem Punkt hört er auf zu laufen/ausgeführt zu werden und kann **keine Dinge mehr tun**. * Hinter jeder Anwendung, die Sie auf Ihrem Computer ausführen, steckt ein Prozess, jedes laufende Programm, jedes Fenster usw. Und normalerweise laufen viele Prozesse **gleichzeitig**, während ein Computer eingeschaltet ist. * Es können **mehrere Prozesse** desselben **Programms** gleichzeitig ausgeführt werden. @@ -117,7 +117,7 @@ Einige Beispiele für Tools, die diese Aufgabe übernehmen können, sind: * Docker * Kubernetes * Docker Compose -* Docker im Schwarm-Modus +* Docker im Swarm-Modus * Systemd * Supervisor * Es wird intern von einem Cloudanbieter im Rahmen seiner Dienste verwaltet @@ -137,7 +137,7 @@ Und wir als Entwickler verbessern den Code ständig, wenn wir diese Bugs finden ### Kleine Fehler automatisch handhaben { #small-errors-automatically-handled } -Wenn beim Erstellen von Web-APIs mit FastAPI ein Fehler in unserem Code auftritt, wird FastAPI ihn normalerweise dem einzelnen Request zurückgeben, der den Fehler ausgelöst hat. 🛡 +Wenn beim Erstellen von Web-APIs mit FastAPI ein Fehler in unserem Code auftritt, wird FastAPI ihn normalerweise auf den einzelnen Request beschränken, der den Fehler ausgelöst hat. 🛡 Der Client erhält für diesen Request einen **500 Internal Server Error**, aber die Anwendung arbeitet bei den nächsten Requests weiter, anstatt einfach komplett abzustürzen. @@ -170,7 +170,7 @@ Dies könnte zum Beispiel erledigt werden durch: * Docker * Kubernetes * Docker Compose -* Docker im Schwarm-Modus +* Docker im Swarm-Modus * Systemd * Supervisor * Intern von einem Cloudanbieter im Rahmen seiner Dienste @@ -178,7 +178,7 @@ Dies könnte zum Beispiel erledigt werden durch: ## Replikation – Prozesse und Arbeitsspeicher { #replication-processes-and-memory } -Wenn Sie eine FastAPI-Anwendung verwenden und ein Serverprogramm wie den `fastapi`-Befehl, der Uvicorn ausführt, kann **ein einzelner Prozess** an mehrere Clients gleichzeitig ausliefern. +Wenn Sie eine FastAPI-Anwendung verwenden und ein Serverprogramm wie den `fastapi`-Befehl, der Uvicorn ausführt, kann die Ausführung in **einem Prozess** mehrere Clients gleichzeitig versorgen. In vielen Fällen möchten Sie jedoch mehrere Workerprozesse gleichzeitig ausführen. @@ -200,7 +200,7 @@ Um also **mehrere Prozesse** gleichzeitig zu haben, muss es einen **einzelnen Pr Wenn das Programm nun Dinge in den Arbeitsspeicher lädt, zum Beispiel ein Modell für maschinelles Lernen in einer Variablen oder den Inhalt einer großen Datei in einer Variablen, verbraucht das alles **einen Teil des Arbeitsspeichers (RAM – Random Access Memory)** des Servers. -Und mehrere Prozesse teilen sich normalerweise keinen Speicher. Das bedeutet, dass jeder laufende Prozess seine eigenen Dinge, eigenen Variablen und eigenen Speicher hat. Und wenn Sie in Ihrem Code viel Speicher verbrauchen, verbraucht **jeder Prozess** die gleiche Menge Speicher. +Und mehrere Prozesse **teilen sich normalerweise keinen Speicher**. Das bedeutet, dass jeder laufende Prozess seine eigenen Dinge, eigenen Variablen und eigenen Speicher hat. Und wenn Sie in Ihrem Code viel Speicher verbrauchen, verbraucht **jeder Prozess** die gleiche Menge Speicher. ### Serverspeicher { #server-memory } diff --git a/docs/de/docs/deployment/docker.md b/docs/de/docs/deployment/docker.md index ee230d5d1..0ab886c46 100644 --- a/docs/de/docs/deployment/docker.md +++ b/docs/de/docs/deployment/docker.md @@ -36,7 +36,7 @@ CMD ["fastapi", "run", "app/main.py", "--port", "80"] Container (hauptsächlich Linux-Container) sind eine sehr **leichtgewichtige** Möglichkeit, Anwendungen einschließlich aller ihrer Abhängigkeiten und erforderlichen Dateien zu verpacken und sie gleichzeitig von anderen Containern (anderen Anwendungen oder Komponenten) im selben System isoliert zu halten. -Linux-Container werden mit demselben Linux-Kernel des Hosts (Maschine, virtuellen Maschine, Cloud-Servers, usw.) ausgeführt. Das bedeutet einfach, dass sie sehr leichtgewichtig sind (im Vergleich zu vollständigen virtuellen Maschinen, die ein gesamtes Betriebssystem emulieren). +Linux-Container werden mit demselben Linux-Kernel des Hosts (Maschine, virtueller Maschine, Cloud-Server usw.) ausgeführt. Das bedeutet einfach, dass sie sehr leichtgewichtig sind (im Vergleich zu vollständigen virtuellen Maschinen, die ein gesamtes Betriebssystem emulieren). Auf diese Weise verbrauchen Container **wenig Ressourcen**, eine Menge vergleichbar mit der direkten Ausführung der Prozesse (eine virtuelle Maschine würde viel mehr verbrauchen). @@ -46,7 +46,7 @@ Container verfügen außerdem über ihre eigenen **isoliert** laufenden Prozesse Ein **Container** wird von einem **Containerimage** ausgeführt. -Ein Containerimage ist eine **statische** Version aller Dateien, Umgebungsvariablen und des Standardbefehls/-programms, welche in einem Container vorhanden sein sollten. **Statisch** bedeutet hier, dass das Container-**Image** nicht läuft, nicht ausgeführt wird, sondern nur die gepackten Dateien und Metadaten enthält. +Ein Containerimage ist eine **statische** Version aller Dateien, Umgebungsvariablen und des Standardbefehls/-programms, die in einem Container vorhanden sein sollten. **Statisch** bedeutet hier, dass das Container-**Image** nicht läuft, nicht ausgeführt wird, sondern nur die gepackten Dateien und Metadaten enthält. Im Gegensatz zu einem „**Containerimage**“, bei dem es sich um den gespeicherten statischen Inhalt handelt, bezieht sich ein „**Container**“ normalerweise auf die laufende Instanz, das Ding, das **ausgeführt** wird. @@ -89,7 +89,7 @@ Ein Container läuft, solange der **Hauptprozess** (Befehl oder Programm) läuft Ein Container hat normalerweise einen **einzelnen Prozess**, aber es ist auch möglich, Unterprozesse vom Hauptprozess aus zu starten, und auf diese Weise haben Sie **mehrere Prozesse** im selben Container. -Es ist jedoch nicht möglich, einen laufenden Container, ohne **mindestens einen laufenden Prozess** zu haben. Wenn der Hauptprozess stoppt, stoppt der Container. +Es ist jedoch nicht möglich, einen laufenden Container ohne **mindestens einen laufenden Prozess** zu haben. Wenn der Hauptprozess stoppt, stoppt der Container. ## Ein Docker-Image für FastAPI erstellen { #build-a-docker-image-for-fastapi } @@ -132,7 +132,7 @@ Successfully installed fastapi pydantic -/// info | Info +/// note | Hinweis Es gibt andere Formate und Tools zum Definieren und Installieren von Paketabhängigkeiten. @@ -184,19 +184,19 @@ COPY ./app /code/app CMD ["fastapi", "run", "app/main.py", "--port", "80"] ``` -1. Beginne mit dem offiziellen Python-Basisimage. +1. Beginnen Sie mit dem offiziellen Python-Basisimage. -2. Setze das aktuelle Arbeitsverzeichnis auf `/code`. +2. Setzen Sie das aktuelle Arbeitsverzeichnis auf `/code`. Hier platzieren wir die Datei `requirements.txt` und das Verzeichnis `app`. -3. Kopiere die Datei mit den Paketanforderungen in das Verzeichnis `/code`. +3. Kopieren Sie die Datei mit den Paketanforderungen in das Verzeichnis `/code`. Kopieren Sie zuerst **nur** die Datei mit den Anforderungen, nicht den Rest des Codes. Da sich diese Datei **nicht oft ändert**, erkennt Docker das und verwendet den **Cache** für diesen Schritt, wodurch der Cache auch für den nächsten Schritt aktiviert wird. -4. Installiere die Paketabhängigkeiten aus der Anforderungsdatei. +4. Installieren Sie die Paketabhängigkeiten aus der Anforderungsdatei. Die Option `--no-cache-dir` weist `pip` an, die heruntergeladenen Pakete nicht lokal zu speichern, da dies nur benötigt wird, sollte `pip` erneut ausgeführt werden, um dieselben Pakete zu installieren, aber das ist beim Arbeiten mit Containern nicht der Fall. @@ -212,13 +212,13 @@ CMD ["fastapi", "run", "app/main.py", "--port", "80"] Durch die Verwendung des Caches in diesem Schritt **sparen** Sie viel **Zeit**, wenn Sie das Image während der Entwicklung immer wieder erstellen, anstatt **jedes Mal** alle Abhängigkeiten **herunterzuladen und zu installieren**. -5. Kopiere das Verzeichnis `./app` in das Verzeichnis `/code`. +5. Kopieren Sie das Verzeichnis `./app` in das Verzeichnis `/code`. Da hier der gesamte Code enthalten ist, der sich **am häufigsten ändert**, wird der Docker-**Cache** nicht ohne weiteres für diesen oder andere **folgende Schritte** verwendet. Daher ist es wichtig, dies **nahe dem Ende** des `Dockerfile`s zu platzieren, um die Erstellungszeiten des Containerimages zu optimieren. -6. Lege den **Befehl** fest, um `fastapi run` zu nutzen, welches Uvicorn darunter verwendet. +6. Legen Sie den **Befehl** fest, um `fastapi run` zu nutzen, welches Uvicorn darunter verwendet. `CMD` nimmt eine Liste von Zeichenfolgen entgegen. Jede dieser Zeichenfolgen entspricht dem, was Sie durch Leerzeichen getrennt in die Befehlszeile eingeben würden. @@ -334,7 +334,7 @@ $ docker build -t myimage . Beachten Sie das `.` am Ende, es entspricht `./` und teilt Docker mit, welches Verzeichnis zum Erstellen des Containerimages verwendet werden soll. -In diesem Fall handelt es sich um dasselbe aktuelle Verzeichnis (`.`). +In diesem Case handelt es sich um dasselbe aktuelle Verzeichnis (`.`). /// @@ -405,7 +405,7 @@ COPY ./main.py /code/ CMD ["fastapi", "run", "main.py", "--port", "80"] ``` -1. Kopiere die Datei `main.py` direkt in das Verzeichnis `/code` (ohne ein Verzeichnis `./app`). +1. Kopieren Sie die Datei `main.py` direkt in das Verzeichnis `/code` (ohne ein Verzeichnis `./app`). 2. Verwenden Sie `fastapi run`, um Ihre Anwendung in der einzelnen Datei `main.py` bereitzustellen. @@ -440,7 +440,7 @@ Traefik verfügt über Integrationen mit Docker, Kubernetes und anderen, sodass /// -Alternativ könnte HTTPS von einem Cloud-Anbieter als einer seiner Dienste gehandhabt werden (während die Anwendung weiterhin in einem Container ausgeführt wird). +Alternativ könnte HTTPS von einem Cloudanbieter als einer seiner Dienste gehandhabt werden (während die Anwendung weiterhin in einem Container ausgeführt wird). ## Beim Hochfahren ausführen und Neustarts { #running-on-startup-and-restarts } @@ -488,7 +488,7 @@ Und normalerweise wäre dieser **Load Balancer** in der Lage, Requests zu verarb In einem solchen Szenario möchten Sie wahrscheinlich **einen einzelnen (Uvicorn-)Prozess pro Container** haben, da Sie die Replikation bereits auf Cluster-Ebene durchführen würden. -In diesem Fall möchten Sie also **nicht** mehrere Worker im Container haben, z. B. mit der `--workers` Befehlszeilenoption. Sie möchten nur einen **einzelnen Uvicorn-Prozess** pro Container haben (wahrscheinlich aber mehrere Container). +In diesem Fall möchten Sie also **nicht** mehrere Worker im Container haben, z. B. mit der `--workers`-Befehlszeilenoption. Sie möchten nur einen **einzelnen Uvicorn-Prozess** pro Container haben (wahrscheinlich aber mehrere Container). Ein weiterer Prozessmanager im Container (wie es bei mehreren Workern der Fall wäre) würde nur **unnötige Komplexität** hinzufügen, um welche Sie sich höchstwahrscheinlich bereits mit Ihrem Clustersystem kümmern. @@ -496,7 +496,7 @@ Ein weiterer Prozessmanager im Container (wie es bei mehreren Workern der Fall w Natürlich gibt es **Sonderfälle**, in denen Sie **einen Container** mit mehreren **Uvicorn-Workerprozessen** haben möchten. -In diesen Fällen können Sie die `--workers` Befehlszeilenoption verwenden, um die Anzahl der zu startenden Worker festzulegen: +In diesen Fällen können Sie die `--workers`-Befehlszeilenoption verwenden, um die Anzahl der zu startenden Worker festzulegen: ```{ .dockerfile .annotate } FROM python:3.14 @@ -513,7 +513,7 @@ COPY ./app /code/app CMD ["fastapi", "run", "app/main.py", "--port", "80", "--workers", "4"] ``` -1. Hier verwenden wir die `--workers` Befehlszeilenoption, um die Anzahl der Worker auf 4 festzulegen. +1. Hier verwenden wir die `--workers`-Befehlszeilenoption, um die Anzahl der Worker auf 4 festzulegen. Hier sind einige Beispiele, wann das sinnvoll sein könnte: @@ -529,7 +529,7 @@ Dann möchten Sie vielleicht **einen einzelnen Container** mit einem **Prozessma --- -Der Hauptpunkt ist, dass **keine** dieser Regeln **in Stein gemeißelt** ist, der man blind folgen muss. Sie können diese Ideen verwenden, um **Ihren eigenen Anwendungsfall zu evaluieren**, zu entscheiden, welcher Ansatz für Ihr System am besten geeignet ist und herauszufinden, wie Sie folgende Konzepte verwalten: +Der Hauptpunkt ist, dass **keine** dieser Regeln **in Stein gemeißelt** ist, der man blind folgen muss. Sie können diese Ideen verwenden, um **I Ihren eigenen Anwendungsfall zu evaluieren**, zu entscheiden, welcher Ansatz für Ihr System am besten geeignet ist und herauszufinden, wie Sie folgende Konzepte verwalten: * Sicherheit – HTTPS * Beim Hochfahren ausführen @@ -556,7 +556,7 @@ Wenn Sie Container (z. B. Docker, Kubernetes) verwenden, können Sie hauptsächl Wenn Sie **mehrere Container** haben, von denen wahrscheinlich jeder einen **einzelnen Prozess** ausführt (z. B. in einem **Kubernetes**-Cluster), dann möchten Sie wahrscheinlich einen **separaten Container** haben, welcher die Arbeit der **Vorab-Schritte** in einem einzelnen Container, mit einem einzelnen Prozess ausführt, **bevor** die replizierten Workercontainer ausgeführt werden. -/// info | Info +/// note | Hinweis Wenn Sie Kubernetes verwenden, wäre dies wahrscheinlich ein [Init-Container](https://kubernetes.io/docs/concepts/workloads/pods/init-containers/). @@ -576,7 +576,7 @@ Sie sollten wahrscheinlich **nicht** dieses Basis-Docker-Image (oder ein anderes Wenn Sie **Kubernetes** (oder andere) verwenden und bereits **Replikation** auf Cluster-Ebene mit mehreren **Containern** eingerichtet haben. In diesen Fällen ist es besser, **ein Image von Grund auf neu zu erstellen**, wie oben beschrieben: [Ein Docker-Image für FastAPI erstellen](#build-a-docker-image-for-fastapi). -Und wenn Sie mehrere Worker benötigen, können Sie einfach die `--workers` Befehlszeilenoption verwenden. +Und wenn Sie mehrere Worker benötigen, können Sie einfach die `--workers`-Befehlszeilenoption verwenden. /// note | Technische Details diff --git a/docs/de/docs/deployment/fastapicloud.md b/docs/de/docs/deployment/fastapicloud.md index c77826aaf..d563fd822 100644 --- a/docs/de/docs/deployment/fastapicloud.md +++ b/docs/de/docs/deployment/fastapicloud.md @@ -1,26 +1,6 @@ # FastAPI Cloud { #fastapi-cloud } -Sie können Ihre FastAPI-App in der [FastAPI Cloud](https://fastapicloud.com) mit **einem einzigen Befehl** deployen – tragen Sie sich in die Warteliste ein, falls noch nicht geschehen. 🚀 - -## Anmelden { #login } - -Stellen Sie sicher, dass Sie bereits ein **FastAPI-Cloud-Konto** haben (wir haben Sie von der Warteliste eingeladen 😉). - -Melden Sie sich dann an: - -
- -```console -$ fastapi login - -You are logged in to FastAPI Cloud 🚀 -``` - -
- -## Deployen { #deploy } - -Stellen Sie Ihre App jetzt mit **einem einzigen Befehl** bereit: +Sie können Ihre FastAPI-App in der [FastAPI Cloud](https://fastapicloud.com) mit **einem einzigen Befehl** deployen. 🚀
@@ -36,6 +16,8 @@ Deploying to FastAPI Cloud...
+Das CLI erkennt Ihre FastAPI-App automatisch und deployt sie in die Cloud. Wenn Sie nicht angemeldet sind, öffnet sich Ihr Browser, um den Authentifizierungsprozess abzuschließen. + Das war’s! Jetzt können Sie Ihre App unter dieser URL aufrufen. ✨ ## Über FastAPI Cloud { #about-fastapi-cloud } @@ -62,4 +44,4 @@ Folgen Sie den Anleitungen Ihres Cloudanbieters, um dort FastAPI-Apps zu deploye ## Auf den eigenen Server deployen { #deploy-your-own-server } -Ich werde Ihnen später in diesem **Deployment-Leitfaden** auch alle Details zeigen, sodass Sie verstehen, was passiert, was geschehen muss und wie Sie FastAPI-Apps selbst deployen können, auch auf Ihre eigenen Server. 🤓 +Ich werde Ihnen später in diesem **Deployment**-Leitfaden auch alle Details zeigen, sodass Sie verstehen, was passiert, was geschehen muss und wie Sie FastAPI-Apps selbst deployen können, auch auf Ihre eigenen Server. 🤓 diff --git a/docs/de/docs/deployment/https.md b/docs/de/docs/deployment/https.md index 0f97909c2..b4c49ff4d 100644 --- a/docs/de/docs/deployment/https.md +++ b/docs/de/docs/deployment/https.md @@ -21,10 +21,10 @@ Aus **Sicht des Entwicklers** sollten Sie beim Nachdenken über HTTPS Folgendes * Und dann müssen sie vom Dritten **erneuert**, **erneut erworben** werden. * Die Verschlüsselung der Verbindung erfolgt auf **TCP-Ebene**. * Das ist eine Schicht **unter HTTP**. - * Die Handhabung von **Zertifikaten und Verschlüsselung** erfolgt also **vor HTTP**. + * Die **Zertifikats- und Verschlüsselungs**-Handhabung erfolgt also **vor HTTP**. * **TCP weiß nichts über „Domains“**. Nur über IP-Adressen. * Die Informationen über die angeforderte **spezifische Domain** befinden sich in den **HTTP-Daten**. -* Die **HTTPS-Zertifikate** „zertifizieren“ eine **bestimmte Domain**, aber das Protokoll und die Verschlüsselung erfolgen auf TCP-Ebene, **ohne zu wissen**, um welche Domain es sich handelt. +* Die **HTTPS-Zertifikate** „zertifizieren“ eine **bestimmte Domain**, aber das Protokoll und die Verschlüsselung erfolgen auf TCP-Ebene, **bevor bekannt ist**, um welche Domain es sich handelt. * **Standardmäßig** bedeutet das, dass Sie nur **ein HTTPS-Zertifikat pro IP-Adresse** haben können. * Ganz gleich, wie groß Ihr Server ist oder wie klein die einzelnen Anwendungen darauf sind. * Hierfür gibt es jedoch eine **Lösung**. @@ -194,7 +194,7 @@ Dieser ganze Erneuerungsprozess, während die Anwendung weiterhin bereitgestellt Wenn Sie einen Proxy zur Verarbeitung von HTTPS verwenden, weiß Ihr **Anwendungsserver** (z. B. Uvicorn über das FastAPI CLI) nichts über den HTTPS-Prozess, er kommuniziert per einfachem HTTP mit dem **TLS-Terminierungsproxy**. -Dieser **Proxy** würde normalerweise unmittelbar vor dem Übermitteln der Anfrage an den **Anwendungsserver** einige HTTP-Header dynamisch setzen, um dem Anwendungsserver mitzuteilen, dass der Request vom Proxy **weitergeleitet** wird. +Dieser **Proxy** würde normalerweise unmittelbar vor dem Übermitteln des Requests an den **Anwendungsserver** einige HTTP-Header dynamisch setzen, um dem Anwendungsserver mitzuteilen, dass der Request vom Proxy **weitergeleitet** wird. /// note | Technische Details diff --git a/docs/de/docs/deployment/manually.md b/docs/de/docs/deployment/manually.md index 53fe230e5..fa8a9c963 100644 --- a/docs/de/docs/deployment/manually.md +++ b/docs/de/docs/deployment/manually.md @@ -55,8 +55,7 @@ Es gibt mehrere Alternativen, einschließlich: * [Uvicorn](https://www.uvicorn.dev/): ein hochperformanter ASGI-Server. * [Hypercorn](https://hypercorn.readthedocs.io/): ein ASGI-Server, der unter anderem kompatibel mit HTTP/2 und Trio ist. * [Daphne](https://github.com/django/daphne): der für Django Channels entwickelte ASGI-Server. -* [Granian](https://github.com/emmett-framework/granian): Ein Rust HTTP-Server für Python-Anwendungen. -* [NGINX Unit](https://unit.nginx.org/howto/fastapi/): NGINX Unit ist eine leichte und vielseitige Laufzeitumgebung für Webanwendungen. +* [Granian](https://github.com/emmett-framework/granian): Ein Rust-HTTP-Server für Python-Anwendungen. ## Servermaschine und Serverprogramm { #server-machine-and-server-program } @@ -66,11 +65,11 @@ Das Wort „**Server**“ wird häufig verwendet, um sowohl den entfernten/Cloud Denken Sie einfach daran, dass sich „Server“ im Allgemeinen auf eines dieser beiden Dinge beziehen kann. -Wenn man sich auf die entfernte Maschine bezieht, wird sie üblicherweise als **Server**, aber auch als **Maschine**, **VM** (virtuelle Maschine) oder **Knoten** bezeichnet. Diese Begriffe beziehen sich auf irgendeine Art von entfernten Rechner, normalerweise unter Linux, auf dem Sie Programme ausführen. +Wenn man sich auf die entfernte Maschine bezieht, wird sie üblicherweise als **Server**, aber auch als **Maschine**, **VM** (virtuelle Maschine) oder **Knoten** bezeichnet. Diese Begriffe beziehen sich auf irgendeine Art von entferntem Rechner, normalerweise unter Linux, auf dem Sie Programme ausführen. ## Das Serverprogramm installieren { #install-the-server-program } -Wenn Sie FastAPI installieren, wird es mit einem Produktionsserver, Uvicorn, geliefert, und Sie können ihn mit dem `fastapi run` Befehl starten. +Wenn Sie FastAPI installieren, wird es mit einem Produktionsserver, Uvicorn, geliefert, und Sie können ihn mit dem `fastapi run`-Befehl starten. Aber Sie können auch ein ASGI-Serverprogramm manuell installieren. diff --git a/docs/de/docs/deployment/server-workers.md b/docs/de/docs/deployment/server-workers.md index 27ae53f7d..6b0cc834e 100644 --- a/docs/de/docs/deployment/server-workers.md +++ b/docs/de/docs/deployment/server-workers.md @@ -17,7 +17,7 @@ Wie Sie im vorherigen Kapitel über [Deployment-Konzepte](concepts.md) gesehen h Hier zeige ich Ihnen, wie Sie **Uvicorn** mit **Workerprozessen** verwenden, indem Sie den `fastapi`-Befehl oder den `uvicorn`-Befehl direkt verwenden. -/// info | Info +/// note | Hinweis Wenn Sie Container verwenden, beispielsweise mit Docker oder Kubernetes, erzähle ich Ihnen mehr darüber im nächsten Kapitel: [FastAPI in Containern – Docker](docker.md). diff --git a/docs/de/docs/editor-support.md b/docs/de/docs/editor-support.md index 97782f54f..f93dd5346 100644 --- a/docs/de/docs/editor-support.md +++ b/docs/de/docs/editor-support.md @@ -1,6 +1,6 @@ # Editor-Unterstützung { #editor-support } -Die offizielle [FastAPI-Erweiterung](https://marketplace.visualstudio.com/items?itemName=FastAPILabs.fastapi-vscode) verbessert Ihren FastAPI-Entwicklungsworkflow mit Pfadoperation-Erkennung und -Navigation sowie FastAPI-Cloud-Deployment und Live-Logstreaming. +Die offizielle [FastAPI-Erweiterung](https://marketplace.visualstudio.com/items?itemName=FastAPILabs.fastapi-vscode) verbessert Ihren FastAPI-Entwicklungsworkflow mit *Pfadoperation*-Erkennung und -Navigation sowie FastAPI-Cloud-Deployment und Live-Logstreaming. Weitere Details zur Erweiterung finden Sie im README im [GitHub-Repository](https://github.com/fastapi/fastapi-vscode). @@ -14,10 +14,10 @@ Standardmäßig erkennt die Erweiterung FastAPI-Anwendungen in Ihrem Workspace a ## Funktionen { #features } -- Pfadoperation-Explorer – Eine Baumansicht in der Seitenleiste aller *Pfadoperationen* in Ihrer Anwendung. Klicken Sie, um zu einer beliebigen Route- oder Router-Definition zu springen. -- Routensuche – Suchen Sie nach Pfad, Methode oder Namen mit Ctrl + Shift + E (unter macOS: Cmd + Shift + E). -- CodeLens-Navigation – Anklickbare Links oberhalb von Testclient-Aufrufen (z. B. `client.get('/items')`), die zur passenden Pfadoperation springen und so eine schnelle Navigation zwischen Tests und Implementierung ermöglichen. -- Zu FastAPI Cloud deployen – Deployment Ihrer App mit einem Klick auf [FastAPI Cloud](https://fastapicloud.com/). -- Anwendungslogs streamen – Echtzeit-Logstreaming Ihrer auf FastAPI Cloud deployten Anwendung mit Loglevel-Filterung und Textsuche. +- **Pfadoperation-Explorer** – Eine Baumansicht in der Seitenleiste aller *Pfadoperationen* in Ihrer Anwendung. Klicken Sie, um zu einer beliebigen Route- oder Router-Definition zu springen. +- **Routensuche** – Suchen Sie nach Pfad, Methode oder Namen mit Ctrl + Shift + E (unter macOS: Cmd + Shift + E). +- **CodeLens-Navigation** – Anklickbare Links oberhalb von Testclient-Aufrufen (z. B. `client.get('/items')`), die zur passenden *Pfadoperation* springen und so eine schnelle Navigation zwischen Tests und Implementierung ermöglichen. +- **Zu FastAPI Cloud deployen** – Deployment Ihrer App mit einem Klick auf [FastAPI Cloud](https://fastapicloud.com/). +- **Anwendungslogs streamen** – Echtzeit-Logstreaming Ihrer auf FastAPI Cloud deployten Anwendung mit Loglevel-Filterung und Textsuche. -Wenn Sie sich mit den Funktionen der Erweiterung vertraut machen möchten, können Sie den Erweiterungs‑Walkthrough aufrufen, indem Sie die Befehlspalette öffnen (Ctrl + Shift + P oder unter macOS: Cmd + Shift + P) und „Welcome: Open walkthrough …“ auswählen und anschließend den Walkthrough „Get started with FastAPI“ wählen. +Wenn Sie sich mit den Funktionen der Erweiterung vertraut machen möchten, können Sie den Erweiterungs‑Walkthrough aufrufen, indem Sie die Befehlspalette öffnen (Ctrl + Shift + P oder unter macOS: Cmd + Shift + P) und „Welcome: Open walkthrough ...“ auswählen und anschließend den Walkthrough „Get started with FastAPI“ wählen. diff --git a/docs/de/docs/environment-variables.md b/docs/de/docs/environment-variables.md index 7bff442cd..1678ead27 100644 --- a/docs/de/docs/environment-variables.md +++ b/docs/de/docs/environment-variables.md @@ -12,7 +12,7 @@ Umgebungsvariablen können nützlich sein, um **Einstellungen** der Anwendung zu ## Umgebungsvariablen erstellen und verwenden { #create-and-use-env-vars } -Sie können Umgebungsvariablen in der **Shell (Terminal)** erstellen und verwenden, ohne Python zu benötigen: +Sie können Umgebungsvariablen in der **Shell (Terminal)** **erstellen** und verwenden, ohne Python zu benötigen: //// tab | Linux, macOS, Windows Bash @@ -67,7 +67,7 @@ print(f"Hello {name} from Python") Das zweite Argument von [`os.getenv()`](https://docs.python.org/3.8/library/os.html#os.getenv) ist der Defaultwert, der zurückgegeben wird. -Wenn er nicht angegeben wird, ist er standardmäßig `None`. Hier geben wir „World“ als den zu verwendenden Defaultwert an. +Wenn er nicht angegeben wird, ist er standardmäßig `None`. Hier geben wir `"World"` als den zu verwendenden Defaultwert an. /// @@ -255,7 +255,7 @@ $ python //// tab | Linux, macOS -Das System wird das `python` Programm in `/opt/custompython/bin` **finden** und es ausführen. +Das System wird das `python`-Programm in `/opt/custompython/bin` **finden** und es ausführen. Es wäre ungefähr gleichbedeutend mit der Eingabe von: @@ -271,7 +271,7 @@ $ /opt/custompython/bin/python //// tab | Windows -Das System wird das `python` Programm in `C:\opt\custompython\bin\python` **finden** und es ausführen. +Das System wird das `python`-Programm in `C:\opt\custompython\bin\python` **finden** und es ausführen. Es wäre ungefähr gleichbedeutend mit der Eingabe von: diff --git a/docs/de/docs/features.md b/docs/de/docs/features.md index 73fa876a9..f24ec2426 100644 --- a/docs/de/docs/features.md +++ b/docs/de/docs/features.md @@ -1,10 +1,10 @@ # Merkmale { #features } -## FastAPI Merkmale { #fastapi-features } +## FastAPI-Merkmale { #fastapi-features } **FastAPI** ermöglicht Ihnen Folgendes: -### Basiert auf offenen Standards { #based-on-open-standards } +### Auf offenen Standards basieren { #based-on-open-standards } * [**OpenAPI**](https://github.com/OAI/OpenAPI-Specification) für die Erstellung von APIs, inklusive Deklarationen von Pfad-Operationen, Parametern, Requestbodys, Sicherheit, usw. * Automatische Dokumentation der Datenmodelle mit [**JSON Schema**](https://json-schema.org/) (da OpenAPI selbst auf JSON Schema basiert). @@ -15,7 +15,7 @@ Interaktive API-Dokumentation und erkundbare Web-Benutzeroberflächen. Da das Framework auf OpenAPI basiert, gibt es mehrere Optionen, zwei sind standardmäßig vorhanden. -* [**Swagger UI**](https://github.com/swagger-api/swagger-ui), bietet interaktive Erkundung, testen und rufen Sie Ihre API direkt im Webbrowser auf. +* [**Swagger UI**](https://github.com/swagger-api/swagger-ui), mit interaktiver Erkundung, rufen Sie Ihre API direkt vom Browser aus auf und testen Sie sie. ![Swagger UI Interaktion](https://fastapi.tiangolo.com/img/index/index-03-swagger-02.png) @@ -36,7 +36,7 @@ from datetime import date from pydantic import BaseModel -# Deklarieren Sie eine Variable als ein str +# Deklarieren Sie eine Variable vom Typ str # und bekommen Sie Editor-Unterstützung innerhalb der Funktion def main(user_id: str): return user_id @@ -67,11 +67,11 @@ my_second_user: User = User(**second_user_data) `**second_user_data` bedeutet: -Nimm die Schlüssel-Wert-Paare des `second_user_data` Dicts und übergebe sie direkt als Schlüsselwort-Argumente. Äquivalent zu: `User(id=4, name="Mary", joined="2018-11-30")` +Übergeben Sie die Schlüssel und Werte des `second_user_data` Dicts direkt als Schlüssel-Wert-Argumente, äquivalent zu: `User(id=4, name="Mary", joined="2018-11-30")` /// -### Editor Unterstützung { #editor-support } +### Editorunterstützung { #editor-support } Das ganze Framework wurde so entworfen, dass es einfach und intuitiv zu benutzen ist; alle Entscheidungen wurden auf mehreren Editoren getestet, sogar vor der Implementierung, um die bestmögliche Entwicklererfahrung zu gewährleisten. @@ -85,31 +85,31 @@ So kann Ihr Editor Sie unterstützen: * in [Visual Studio Code](https://code.visualstudio.com/): -![Editor Unterstützung](https://fastapi.tiangolo.com/img/vscode-completion.png) +![Editorunterstützung](https://fastapi.tiangolo.com/img/vscode-completion.png) * in [PyCharm](https://www.jetbrains.com/pycharm/): -![Editor Unterstützung](https://fastapi.tiangolo.com/img/pycharm-completion.png) +![Editorunterstützung](https://fastapi.tiangolo.com/img/pycharm-completion.png) -Sie bekommen sogar Autovervollständigung an Stellen, an denen Sie dies vorher nicht für möglich gehalten hätten. Zum Beispiel der `price` Schlüssel in einem JSON Datensatz (dieser könnte auch verschachtelt sein), der aus einem Request kommt. +Sie bekommen sogar Autovervollständigung an Stellen, an denen Sie dies vorher nicht für möglich gehalten hätten. Zum Beispiel der `price`-Schlüssel innerhalb eines JSON-Bodys (dieser könnte auch verschachtelt sein), der aus einem Request kommt. Nie wieder falsche Schlüsselnamen tippen, Hin und Herhüpfen zwischen der Dokumentation, Hoch- und Runterscrollen, um herauszufinden, ob es `username` oder `user_name` war. ### Kompakt { #short } -Es gibt für alles sensible **Defaultwerte**, mit optionaler Konfiguration überall. Alle Parameter können feinjustiert werden, damit sie tun, was Sie benötigen, und die API definieren, die Sie brauchen. +Es gibt für alles sinnvolle **Defaultwerte**, mit optionaler Konfiguration überall. Alle Parameter können feinjustiert werden, damit sie tun, was Sie benötigen, und die API definieren, die Sie brauchen. Aber standardmäßig **„funktioniert einfach alles“**. ### Validierung { #validation } * Validierung für die meisten (oder alle?) Python-**Datentypen**, hierzu gehören: - * JSON Objekte (`dict`). - * JSON Listen (`list`), die den Typ ihrer Elemente definieren. - * Strings (`str`) mit definierter minimaler und maximaler Länge. + * JSON-Objekte (`dict`). + * JSON-Array (`list`), das Elementtypen definiert. + * String-Felder (`str`) mit definierter minimaler und maximaler Länge. * Zahlen (`int`, `float`) mit Mindest- und Maximalwerten, usw. -* Validierung für mehr exotische Typen, wie: +* Validierung für exotischere Typen, wie: * URL. * E-Mail. * UUID. @@ -124,42 +124,42 @@ Sicherheit und Authentifizierung sind integriert. Ohne Kompromisse bei Datenbank Alle in OpenAPI definierten Sicherheitsschemas, inklusive: * HTTP Basic. -* **OAuth2** (auch mit **JWT Tokens**). Siehe dazu das Tutorial zu [OAuth2 mit JWT](tutorial/security/oauth2-jwt.md). -* API Schlüssel in: +* **OAuth2** (auch mit **JWT-Tokens**). Siehe dazu das Tutorial zu [OAuth2 mit JWT](tutorial/security/oauth2-jwt.md). +* API-Schlüssel in: * Headern. * Query-Parametern. * Cookies, usw. -Zusätzlich alle Sicherheitsfunktionen von Starlette (inklusive **Session Cookies**). +Zusätzlich alle Sicherheitsfunktionen von Starlette (inklusive **Session-Cookies**). -Alles als wiederverwendbare Tools und Komponenten gebaut, die einfach in Ihre Systeme, Datenspeicher, relationale und nicht-relationale Datenbanken, usw., integriert werden können. +Alles als wiederverwendbare Tools und Komponenten gebaut, die einfach in Ihre Systeme, Datenspeicher, relationale und NoSQL-Datenbanken, usw., integriert werden können. ### Dependency Injection { #dependency-injection } -FastAPI enthält ein extrem einfach zu verwendendes, aber extrem mächtiges Dependency Injection System. +FastAPI enthält ein extrem einfach zu verwendendes, aber extrem mächtiges Dependency Injection-System. * Selbst Abhängigkeiten können Abhängigkeiten haben, woraus eine Hierarchie oder ein **„Graph“ von Abhängigkeiten** entsteht. * Alles **automatisch gehandhabt** durch das Framework. -* Alle Abhängigkeiten können Daten von Requests anfordern und das Verhalten von **Pfadoperationen** und der automatisierten Dokumentation **modifizieren**. +* Alle Abhängigkeiten können Daten von Requests anfordern und die Einschränkungen der **Pfadoperationen** sowie die automatische Dokumentation **erweitern**. * **Automatische Validierung** selbst für solche Parameter von *Pfadoperationen*, welche in Abhängigkeiten definiert sind. -* Unterstützung für komplexe Authentifizierungssysteme, **Datenbankverbindungen**, usw. +* Unterstützung für komplexe Benutzerauthentifizierungssysteme, **Datenbankverbindungen**, usw. * **Keine Kompromisse** bei Datenbanken, Frontends, usw., sondern einfache Integration mit allen. -### Unbegrenzte Erweiterungen { #unlimited-plug-ins } +### Unbegrenzte „Plug-ins“ { #unlimited-plug-ins } Oder mit anderen Worten, sie werden nicht benötigt. Importieren und nutzen Sie den Code, den Sie brauchen. -Jede Integration wurde so entworfen, dass sie so einfach zu nutzen ist (mit Abhängigkeiten), dass Sie eine Erweiterung für Ihre Anwendung mit nur zwei Zeilen Code erstellen können. Hierbei nutzen Sie die gleiche Struktur und Syntax, wie bei *Pfadoperationen*. +Jede Integration wurde so entworfen, dass sie so einfach zu nutzen ist (mit Abhängigkeiten), dass Sie ein „Plug-in“ für Ihre Anwendung mit nur 2 Zeilen Code erstellen können. Hierbei nutzen Sie die gleiche Struktur und Syntax, wie bei *Pfadoperationen*. ### Getestet { #tested } * 100 % Testabdeckung. -* 100 % Typen annotiert. +* Zu 100 % typannotierte Codebasis. * Verwendet in Produktionsanwendungen. -## Starlette Merkmale { #starlette-features } +## Starlette-Merkmale { #starlette-features } -**FastAPI** ist vollkommen kompatibel (und basiert auf) [**Starlette**](https://www.starlette.dev/). Das bedeutet, wenn Sie eigenen Starlette Quellcode haben, funktioniert der. +**FastAPI** ist vollkommen kompatibel (und basiert auf) [**Starlette**](https://www.starlette.dev/). Das bedeutet, wenn Sie eigenen Starlette-Quellcode haben, funktioniert dieser auch. `FastAPI` ist tatsächlich eine Unterklasse von `Starlette`. Wenn Sie also bereits Starlette kennen oder benutzen, das meiste funktioniert genau so. @@ -173,11 +173,11 @@ Mit **FastAPI** bekommen Sie alles von **Starlette** (da FastAPI nur Starlette a * **CORS**, GZip, statische Dateien, Responses streamen. * **Sitzungs- und Cookie**-Unterstützung. * 100 % Testabdeckung. -* 100 % Typen annotierte Codebasis. +* Zu 100 % typannotierte Codebasis. -## Pydantic Merkmale { #pydantic-features } +## Pydantic-Merkmale { #pydantic-features } -**FastAPI** ist vollkommen kompatibel (und basiert auf) [**Pydantic**](https://docs.pydantic.dev/). Das bedeutet, wenn Sie eigenen Pydantic Quellcode haben, funktioniert der. +**FastAPI** ist vollkommen kompatibel (und basiert auf) [**Pydantic**](https://docs.pydantic.dev/). Das bedeutet, wenn Sie eigenen Pydantic-Quellcode haben, funktioniert dieser auch. Inklusive externer Bibliotheken, die auf Pydantic basieren, wie ORMs, ODMs für Datenbanken. @@ -188,14 +188,14 @@ Das gleiche gilt auch für die andere Richtung: Sie können in vielen Fällen da Mit **FastAPI** bekommen Sie alle Funktionen von **Pydantic** (da FastAPI für die gesamte Datenverarbeitung Pydantic nutzt): * **Kein Kopfzerbrechen**: - * Keine neue Schemadefinition-Mikrosprache zu lernen. + * Keine neue Schemadefinitions-Mikrosprache zu lernen. * Wenn Sie Pythons Typen kennen, wissen Sie, wie man Pydantic verwendet. * Gutes Zusammenspiel mit Ihrer/Ihrem **IDE/Linter/Gehirn**: * Weil Pydantics Datenstrukturen einfach nur Instanzen ihrer definierten Klassen sind; Autovervollständigung, Linting, mypy und Ihre Intuition sollten alle einwandfrei mit Ihren validierten Daten funktionieren. * Validierung von **komplexen Strukturen**: - * Benutzung von hierarchischen Pydantic-Modellen, Python-`typing`s `List` und `Dict`, etc. - * Die Validierer erlauben es, komplexe Datenschemen klar und einfach zu definieren, überprüft und dokumentiert als JSON Schema. - * Sie können tief **verschachtelte JSON** Objekte haben, die alle validiert und annotiert sind. + * Benutzung von hierarchischen Pydantic-Modellen, Python-`typing`s `List` und `Dict`, usw. + * Die Validierer erlauben es, komplexe Datenschemas klar und einfach zu definieren, überprüft und dokumentiert als JSON Schema. + * Sie können tief **verschachtelte JSON**-Objekte haben, die alle validiert und annotiert sind. * **Erweiterbar**: - * Pydantic erlaubt die Definition von eigenen Datentypen oder sie können die Validierung mit einer `validator`-dekorierten Methode im Modell erweitern. + * Pydantic erlaubt die Definition von eigenen Datentypen oder Sie können die Validierung mit Methoden in einem Modell erweitern, die mit dem Validator-Dekorator dekoriert sind. * 100 % Testabdeckung. diff --git a/docs/de/docs/help-fastapi.md b/docs/de/docs/help-fastapi.md index 83d015739..4a8687562 100644 --- a/docs/de/docs/help-fastapi.md +++ b/docs/de/docs/help-fastapi.md @@ -1,5 +1,6 @@ # Helfen { #help } + Möchten Sie FastAPI helfen oder Hilfe zu FastAPI erhalten? Es gibt sehr einfache Möglichkeiten, zu helfen und Hilfe zu bekommen. diff --git a/docs/de/docs/how-to/configure-swagger-ui.md b/docs/de/docs/how-to/configure-swagger-ui.md index 2f8904be7..d25062615 100644 --- a/docs/de/docs/how-to/configure-swagger-ui.md +++ b/docs/de/docs/how-to/configure-swagger-ui.md @@ -67,4 +67,4 @@ presets: [ Dabei handelt es sich um **JavaScript**-Objekte, nicht um Strings, daher können Sie diese nicht direkt vom Python-Code aus übergeben. -Wenn Sie solche JavaScript-Konfigurationen verwenden müssen, können Sie einen der früher genannten Wege verwenden. Überschreiben Sie alle *Pfadoperationen* der Swagger-Oberfläche und schreiben Sie manuell jedes benötigte JavaScript. +Wenn Sie solche Nur-JavaScript-Konfigurationen verwenden müssen, können Sie einen der früher genannten Wege verwenden. Überschreiben Sie die gesamte *Pfadoperation* der Swagger-Oberfläche und schreiben Sie manuell jedes benötigte JavaScript. diff --git a/docs/de/docs/how-to/custom-request-and-route.md b/docs/de/docs/how-to/custom-request-and-route.md index 5e2dee95d..60fe71ed3 100644 --- a/docs/de/docs/how-to/custom-request-and-route.md +++ b/docs/de/docs/how-to/custom-request-and-route.md @@ -1,5 +1,6 @@ # Benutzerdefinierte Request- und APIRoute-Klasse { #custom-request-and-apiroute-class } + In einigen Fällen möchten Sie möglicherweise die von den Klassen `Request` und `APIRoute` verwendete Logik überschreiben. Das kann insbesondere eine gute Alternative zur Logik in einer Middleware sein. diff --git a/docs/de/docs/how-to/extending-openapi.md b/docs/de/docs/how-to/extending-openapi.md index 8005344c8..23824117e 100644 --- a/docs/de/docs/how-to/extending-openapi.md +++ b/docs/de/docs/how-to/extending-openapi.md @@ -25,9 +25,17 @@ Diese Funktion `get_openapi()` erhält als Parameter: * `openapi_version`: Die Version der verwendeten OpenAPI-Spezifikation. Standardmäßig die neueste Version: `3.1.0`. * `summary`: Eine kurze Zusammenfassung der API. * `description`: Die Beschreibung Ihrer API. Dies kann Markdown enthalten und wird in der Dokumentation angezeigt. -* `routes`: Eine Liste von Routen, dies sind alle registrierten *Pfadoperationen*. Sie stammen von `app.routes`. +* `routes`: Die Routen der Anwendung, entnommen aus `app.routes`. FastAPI nutzt sie, um die registrierten *Pfadoperationen* zu sammeln, einschließlich derer aus eingebundenen Routern. -/// info | Info +/// tip | Technische Details + +`app.routes` ist eine Routenstruktur auf niedrigerer Ebene. Sie kann Routenkandidaten enthalten, die FastAPI intern für eingebundene Router verwendet, nicht nur endgültige `APIRoute`-Objekte. + +Sie können dennoch `app.routes` an `get_openapi()` übergeben. FastAPI durchläuft diesen Routenbaum, um die tatsächlich wirksamen Pfadoperationen zu sammeln. + +/// + +/// note | Hinweis Der Parameter `summary` ist in OpenAPI 3.1.0 und höher verfügbar und wird von FastAPI 0.99.0 und höher unterstützt. diff --git a/docs/de/docs/how-to/graphql.md b/docs/de/docs/how-to/graphql.md index bf1490f70..cb1891b63 100644 --- a/docs/de/docs/how-to/graphql.md +++ b/docs/de/docs/how-to/graphql.md @@ -1,5 +1,6 @@ # GraphQL { #graphql } + Da **FastAPI** auf dem **ASGI**-Standard basiert, ist es sehr einfach, jede **GraphQL**-Bibliothek zu integrieren, die auch mit ASGI kompatibel ist. Sie können normale FastAPI-*Pfadoperationen* mit GraphQL in derselben Anwendung kombinieren. diff --git a/docs/de/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md b/docs/de/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md index c252b3e0f..5ea3b9561 100644 --- a/docs/de/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md +++ b/docs/de/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md @@ -8,6 +8,8 @@ FastAPI Version 0.119.0 führte eine teilweise Unterstützung für Pydantic v1 i FastAPI 0.126.0 entfernte die Unterstützung für Pydantic v1, während `pydantic.v1` noch eine Weile unterstützt wurde. +FastAPI 0.128.0 entfernte ebenfalls die Unterstützung für `pydantic.v1`, daher erfordern die neuesten Versionen von FastAPI Pydantic v2. + /// warning | Achtung Das Pydantic-Team hat die Unterstützung für Pydantic v1 in den neuesten Python-Versionen eingestellt, beginnend mit **Python 3.14**. @@ -54,6 +56,16 @@ Das bedeutet, Sie können die neueste Version von Pydantic v2 installieren und d ### FastAPI-Unterstützung für Pydantic v1 in v2 { #fastapi-support-for-pydantic-v1-in-v2 } +/// warning | Achtung + +Diese FastAPI-Unterstützung für `pydantic.v1`-Modelle wurde in **FastAPI 0.119.0** hinzugefügt und in **FastAPI 0.128.0** entfernt. Sie war als temporäre Hilfe für die Migration zu Pydantic v2 gedacht. + +In aktuellen Versionen von FastAPI löst die Verwendung eines `pydantic.v1`-Modells in Ihrer App einen Fehler aus. + +Der Rest dieses Abschnitts beschreibt die temporäre Unterstützung, die nur in diesen älteren Versionen verfügbar ist. + +/// + Seit FastAPI 0.119.0 gibt es außerdem eine teilweise Unterstützung für Pydantic v1 innerhalb von Pydantic v2, um die Migration auf v2 zu erleichtern. Sie könnten also Pydantic auf die neueste Version 2 aktualisieren und die Importe so ändern, dass das Untermodul `pydantic.v1` verwendet wird, und in vielen Fällen würde es einfach funktionieren. @@ -122,6 +134,12 @@ Wenn Sie einige der FastAPI-spezifischen Tools für Parameter wie `Body`, `Query ### In Schritten migrieren { #migrate-in-steps } +/// warning | Achtung + +Die unten beschriebene schrittweise Migration mit sowohl Pydantic‑v1‑ als auch Pydantic‑v2‑Modellen in derselben App funktioniert nur in **FastAPI 0.119.0 bis 0.127.x**. Sie wurde in **FastAPI 0.128.0** entfernt, die neuesten Versionen erfordern **Pydantic‑v2**-Modelle. + +/// + /// tip | Tipp Probieren Sie zuerst `bump-pydantic` aus. Wenn Ihre Tests erfolgreich sind und das funktioniert, sind Sie mit einem einzigen Befehl fertig. ✨ diff --git a/docs/de/docs/how-to/separate-openapi-schemas.md b/docs/de/docs/how-to/separate-openapi-schemas.md index 16f9c8a14..ae1df6176 100644 --- a/docs/de/docs/how-to/separate-openapi-schemas.md +++ b/docs/de/docs/how-to/separate-openapi-schemas.md @@ -1,5 +1,6 @@ # Separate OpenAPI-Schemas für Eingabe und Ausgabe oder nicht { #separate-openapi-schemas-for-input-and-output-or-not } + Seit der Veröffentlichung von **Pydantic v2** ist die generierte OpenAPI etwas genauer und **korrekter** als zuvor. 😎 Tatsächlich gibt es in einigen Fällen sogar **zwei JSON-Schemas** in OpenAPI für dasselbe Pydantic-Modell, für Eingabe und Ausgabe, je nachdem, ob sie **Defaultwerte** haben. @@ -85,7 +86,7 @@ Der Hauptanwendungsfall hierfür besteht wahrscheinlich darin, dass Sie das mal In diesem Fall können Sie diese Funktion in **FastAPI** mit dem Parameter `separate_input_output_schemas=False` deaktivieren. -/// info | Info +/// note | Hinweis Unterstützung für `separate_input_output_schemas` wurde in FastAPI `0.102.0` hinzugefügt. 🤓 diff --git a/docs/de/docs/index.md b/docs/de/docs/index.md index d557554a1..9922e7621 100644 --- a/docs/de/docs/index.md +++ b/docs/de/docs/index.md @@ -167,7 +167,7 @@ Es gibt einen [FastAPI-Mini-Dokumentarfilm](https://www.youtube.com/watch?v=mpR8
-Wenn Sie eine CLI-Anwendung für das Terminal erstellen, anstelle einer Web-API, schauen Sie sich [**Typer**](https://typer.tiangolo.com/) an. +Wenn Sie eine CLI-Anwendung für das Terminal erstellen, anstelle einer Web-API, schauen Sie sich [**Typer**](https://typer.tiangolo.com/) an. **Typer** ist die kleine Schwester von FastAPI. Und es soll das **FastAPI der CLIs** sein. ⌨️ 🚀 @@ -192,7 +192,7 @@ $ pip install "fastapi[standard]" -**Hinweis**: Stellen Sie sicher, dass Sie `"fastapi[standard]"` in Anführungszeichen setzen, damit es in allen Terminals funktioniert. +**Hinweis**: Stellen Sie sicher, dass Sie „fastapi[standard]“ in Anführungszeichen setzen, damit es in allen Terminals funktioniert. ## Beispiel { #example } @@ -492,9 +492,7 @@ Für ein vollständigeres Beispiel, mit weiteren Funktionen, siehe das @@ -510,6 +508,8 @@ Deploying to FastAPI Cloud... +Das CLI erkennt Ihre FastAPI-Anwendung automatisch und deployt sie in die Cloud. Wenn Sie nicht eingeloggt sind, wird Ihr Browser geöffnet, um den Authentifizierungsprozess abzuschließen. + Das war’s! Jetzt können Sie unter dieser URL auf Ihre App zugreifen. ✨ #### Über FastAPI Cloud { #about-fastapi-cloud } diff --git a/docs/de/docs/project-generation.md b/docs/de/docs/project-generation.md index fd754906a..d2dbadbc9 100644 --- a/docs/de/docs/project-generation.md +++ b/docs/de/docs/project-generation.md @@ -17,7 +17,7 @@ GitHub-Repository: [Full Stack FastAPI Template](https://github.com/tiangolo/ful - 🎨 [Tailwind CSS](https://tailwindcss.com) und [shadcn/ui](https://ui.shadcn.com) für die Frontend-Komponenten. - 🤖 Ein automatisch generierter Frontend-Client. - 🧪 [Playwright](https://playwright.dev) für End-to-End-Tests. - - 🦇 „Dark-Mode“-Unterstützung. + - 🦇 Dark-Mode-Unterstützung. - 🐋 [Docker Compose](https://www.docker.com) für Entwicklung und Produktion. - 🔒 Sicheres Passwort-Hashing standardmäßig. - 🔑 JWT (JSON Web Token)-Authentifizierung. diff --git a/docs/de/docs/python-types.md b/docs/de/docs/python-types.md index aee30fc2f..a67b8b309 100644 --- a/docs/de/docs/python-types.md +++ b/docs/de/docs/python-types.md @@ -44,7 +44,7 @@ Es ist ein sehr einfaches Programm. Aber nun stellen Sie sich vor, Sie würden es selbst schreiben. -Irgendwann sind die Funktions-Parameter fertig, Sie starten mit der Definition des Körpers ... +Irgendwann beginnen Sie, die Funktion zu definieren, und haben die Parameter bereit ... Aber dann müssen Sie „diese Methode aufrufen, die den ersten Buchstaben in Großbuchstaben umwandelt“. @@ -52,7 +52,7 @@ War es `upper`? War es `uppercase`? `first_uppercase`? `capitalize`? Dann versuchen Sie es mit dem langjährigen Freund des Programmierers, der Editor-Autovervollständigung. -Sie geben den ersten Parameter der Funktion ein, `first_name`, dann einen Punkt (`.`) und drücken `Strg+Leertaste`, um die Vervollständigung auszulösen. +Sie geben den ersten Parameter der Funktion ein, `first_name`, dann einen Punkt (`.`) und drücken `Ctrl+Space`, um die Vervollständigung auszulösen. Aber leider erhalten Sie nichts Nützliches: @@ -62,7 +62,7 @@ Aber leider erhalten Sie nichts Nützliches: Lassen Sie uns eine einzelne Zeile aus der vorherigen Version ändern. -Wir ändern den folgenden Teil, die Parameter der Funktion, von: +Wir ändern genau dieses Fragment, die Parameter der Funktion, von: ```Python first_name, last_name @@ -94,7 +94,7 @@ Und das Hinzufügen von Typhinweisen ändert normalerweise nichts an dem, was oh Aber jetzt stellen Sie sich vor, Sie sind wieder mitten in der Erstellung dieser Funktion, aber mit Typhinweisen. -An derselben Stelle versuchen Sie, die Autovervollständigung mit „Strg+Leertaste“ auszulösen, und Sie sehen: +An derselben Stelle versuchen Sie, die Autovervollständigung mit `Ctrl+Space` auszulösen, und Sie sehen: @@ -116,7 +116,7 @@ Jetzt, da Sie wissen, dass Sie das reparieren müssen, konvertieren Sie `age` mi {* ../../docs_src/python_types/tutorial004_py310.py hl[2] *} -## Deklarieren von Typen { #declaring-types } +## Typen deklarieren { #declaring-types } Sie haben gerade den Haupt-Einsatzort für die Deklaration von Typhinweisen gesehen. Als Funktionsparameter. @@ -180,7 +180,7 @@ In diesem Fall ist `str` der Typ-Parameter, der an `list` übergeben wird. /// -Das bedeutet: Die Variable `items` ist eine Liste – `list` – und jedes der Elemente in dieser Liste ist ein String – `str`. +Das bedeutet: „Die Variable `items` ist eine `list`, und jedes der Elemente in dieser Liste ist ein `str`“. Auf diese Weise kann Ihr Editor Sie auch bei der Bearbeitung von Einträgen aus der Liste unterstützen: @@ -263,9 +263,9 @@ Und wiederum bekommen Sie die volle Editor-Unterstützung: -Beachten Sie, das bedeutet: „`one_person` ist eine **Instanz** der Klasse `Person`“. +Beachten Sie, dass das bedeutet: „`one_person` ist eine **Instanz** der Klasse `Person`“. -Es bedeutet nicht: „`one_person` ist die **Klasse** genannt `Person`“. +Es bedeutet nicht: „`one_person` ist die **Klasse** namens `Person`“. ## Pydantic-Modelle { #pydantic-models } @@ -279,7 +279,7 @@ Dann erzeugen Sie eine Instanz dieser Klasse mit einigen Werten, und Pydantic va Und Sie erhalten volle Editor-Unterstützung für dieses Objekt. -Ein Beispiel aus der offiziellen Pydantic Dokumentation: +Ein Beispiel aus der offiziellen Pydantic-Dokumentation: {* ../../docs_src/python_types/tutorial011_py310.py *} @@ -301,11 +301,11 @@ Sie können `Annotated` von `typing` importieren. {* ../../docs_src/python_types/tutorial013_py310.py hl[1,4] *} -Python selbst macht nichts mit `Annotated`. Für Editoren und andere Tools ist der Typ immer noch `str`. +Python selbst macht nichts mit diesem `Annotated`. Für Editoren und andere Tools ist der Typ immer noch `str`. -Aber Sie können `Annotated` nutzen, um **FastAPI** mit Metadaten zu versorgen, die ihm sagen, wie sich Ihre Anwendung verhalten soll. +Aber Sie können diesen Platz in `Annotated` nutzen, um **FastAPI** zusätzliche Metadaten darüber bereitzustellen, wie sich Ihre Anwendung verhalten soll. -Wichtig ist, dass **der erste *Typ-Parameter***, den Sie `Annotated` übergeben, der **tatsächliche Typ** ist. Der Rest sind Metadaten für andere Tools. +Wichtig ist, dass **der erste *Typ-Parameter***, den Sie `Annotated` übergeben, der **tatsächliche Typ** ist. Der Rest sind nur Metadaten für andere Tools. Im Moment müssen Sie nur wissen, dass `Annotated` existiert, und dass es Standard-Python ist. 😎 @@ -335,7 +335,7 @@ Mit **FastAPI** deklarieren Sie Parameter mit Typhinweisen, und Sie erhalten: * **Daten zu validieren**: aus jedem Request: * **Automatische Fehler** generieren, die an den Client zurückgegeben werden, wenn die Daten ungültig sind. * Die API mit OpenAPI zu **dokumentieren**: - * Die dann von den Benutzeroberflächen der automatisch generierten interaktiven Dokumentation verwendet wird. + * die dann von den Benutzeroberflächen der automatisch generierten interaktiven Dokumentation verwendet wird. Das mag alles abstrakt klingen. Machen Sie sich keine Sorgen. Sie werden all das in Aktion sehen im [Tutorial – Benutzerhandbuch](tutorial/index.md). diff --git a/docs/de/docs/tutorial/bigger-applications.md b/docs/de/docs/tutorial/bigger-applications.md index c6fec3f6a..119f3e8c0 100644 --- a/docs/de/docs/tutorial/bigger-applications.md +++ b/docs/de/docs/tutorial/bigger-applications.md @@ -17,16 +17,16 @@ Nehmen wir an, Sie haben eine Dateistruktur wie diese: ``` . ├── app -│   ├── __init__.py -│   ├── main.py -│   ├── dependencies.py -│   └── routers -│   │ ├── __init__.py -│   │ ├── items.py -│   │ └── users.py -│   └── internal -│   ├── __init__.py -│   └── admin.py +│ ├── __init__.py +│ ├── main.py +│ ├── dependencies.py +│ └── routers +│ │ ├── __init__.py +│ │ ├── items.py +│ │ └── users.py +│ └── internal +│ ├── __init__.py +│ └── admin.py ``` /// tip | Tipp @@ -396,9 +396,9 @@ Es wird alle Routen von diesem Router als Teil von dieser inkludieren. /// note | Technische Details -Tatsächlich wird intern eine *Pfadoperation* für jede *Pfadoperation* erstellt, die im `APIRouter` deklariert wurde. +FastAPI behält den ursprünglichen `APIRouter` und seine `APIRoute`s aktiv, wenn der Router in die Hauptanwendung eingebunden wird. -Hinter den Kulissen wird es also tatsächlich so funktionieren, als ob alles dieselbe einzige Anwendung wäre. +Das bedeutet, dass benutzerdefinierte Subklassen von `APIRouter` und `APIRoute` auch nach dem Einbinden weiterhin beteiligt sein können. /// @@ -406,7 +406,7 @@ Hinter den Kulissen wird es also tatsächlich so funktionieren, als ob alles die Bei der Einbindung von Routern müssen Sie sich keine Gedanken über die Leistung machen. -Dies dauert Mikrosekunden und geschieht nur beim Start. +Dies ist so konzipiert, dass es leichtgewichtig ist und keinen Overhead pro Request hinzufügt. Es hat also keinen Einfluss auf die Leistung. ⚡ @@ -459,9 +459,9 @@ und es wird korrekt funktionieren, zusammen mit allen anderen *Pfadoperationen*, Die `APIRouter` sind nicht „gemountet“, sie sind nicht vom Rest der Anwendung isoliert. -Das liegt daran, dass wir deren *Pfadoperationen* in das OpenAPI-Schema und die Benutzeroberflächen einbinden möchten. +Das liegt daran, dass wir ihre *Pfadoperationen* im OpenAPI-Schema und in den Benutzeroberflächen inkludieren möchten. -Da wir sie nicht einfach isolieren und unabhängig vom Rest „mounten“ können, werden die *Pfadoperationen* „geklont“ (neu erstellt) und nicht direkt einbezogen. +FastAPI behält die ursprünglichen Router und Pfadoperationen aktiv und kombiniert Router-Präfixe, Abhängigkeiten, Tags, Responses und weitere Metadaten beim Bearbeiten von Requests und beim Generieren von OpenAPI. /// @@ -532,4 +532,16 @@ Auf die gleiche Weise, wie Sie einen `APIRouter` in eine `FastAPI`-Anwendung ein router.include_router(other_router) ``` -Stellen Sie sicher, dass Sie dies tun, bevor Sie `router` in die `FastAPI`-App einbinden, damit auch die *Pfadoperationen* von `other_router` inkludiert werden. +Sie können dies vor oder nach dem Einbinden von `router` in die `FastAPI`-App tun. FastAPI inkludiert die *Pfadoperationen* von `other_router` dennoch in Routing und OpenAPI. + +Gleiches gilt für später zu den Routern hinzugefügte *Pfadoperationen*. Sie sind auch über die frühere Inklusion sichtbar. + +/// warning | Technische Details + +Vermeiden Sie es, `router.routes` direkt zu mutieren, nachdem ein Router inkludiert wurde. FastAPI behandelt Router-Inklusion als „live“, sodass der ursprüngliche Router und seine Routen Teil des Routings und der OpenAPI-Generierung bleiben. + +Verwenden Sie dokumentierte APIs wie Pfadoperation-Dekoratoren und `.include_router()`, um Routen und Router hinzuzufügen. + +Betrachten Sie `router.routes` als eine Low-Level-Routenstruktur, die sowohl Routendefinitionen als auch inkludierte Router enthalten kann, und verlassen Sie sich nicht darauf als flache Liste endgültiger Pfadoperationen. + +/// diff --git a/docs/de/docs/tutorial/body-multiple-params.md b/docs/de/docs/tutorial/body-multiple-params.md index 60a0ceefe..2d5765dcd 100644 --- a/docs/de/docs/tutorial/body-multiple-params.md +++ b/docs/de/docs/tutorial/body-multiple-params.md @@ -108,7 +108,7 @@ Zum Beispiel: {* ../../docs_src/body_multiple_params/tutorial004_an_py310.py hl[28] *} -/// info | Info +/// note | Hinweis `Body` hat die gleichen zusätzlichen Validierungs- und Metadaten-Parameter wie `Query`, `Path` und andere, die Sie später kennenlernen werden. @@ -123,7 +123,7 @@ Standardmäßig wird **FastAPI** dann seinen Body direkt erwarten. Aber wenn Sie möchten, dass es einen JSON-Body mit einem Schlüssel `item` erwartet, und darin den Inhalt des Modells, so wie es das tut, wenn Sie mehrere Body-Parameter deklarieren, dann können Sie den speziellen `Body`-Parameter `embed` setzen: ```Python -item: Item = Body(embed=True) +item: Annotated[Item, Body(embed=True)] ``` so wie in: diff --git a/docs/de/docs/tutorial/body-nested-models.md b/docs/de/docs/tutorial/body-nested-models.md index 62f04a37d..f95b65e57 100644 --- a/docs/de/docs/tutorial/body-nested-models.md +++ b/docs/de/docs/tutorial/body-nested-models.md @@ -4,7 +4,7 @@ Mit **FastAPI** können Sie (dank Pydantic) beliebig tief verschachtelte Modelle ## Listen als Felder { #list-fields } -Sie können ein Attribut als Kindtyp definieren, zum Beispiel eine Python-`list`. +Sie können ein Attribut als Kindtyp definieren. Zum Beispiel eine Python-`list`: {* ../../docs_src/body_nested_models/tutorial001_py310.py hl[12] *} @@ -12,11 +12,12 @@ Das bewirkt, dass `tags` eine Liste ist, wenngleich es nichts über den Typ der ## Listen mit Typ-Parametern als Felder { #list-fields-with-type-parameter } -Aber Python erlaubt es, Listen mit inneren Typen, auch „Typ-Parameter“ genannt, zu deklarieren. +Aber Python hat eine spezifische Möglichkeit, Listen mit inneren Typen, auch „Typ-Parameter“ genannt, zu deklarieren: ### Eine `list` mit einem Typ-Parameter deklarieren { #declare-a-list-with-a-type-parameter } -Um Typen zu deklarieren, die Typ-Parameter (innere Typen) haben, wie `list`, `dict`, `tuple`, übergeben Sie den/die inneren Typ(en) als „Typ-Parameter“ in eckigen Klammern: `[` und `]` +Um Typen zu deklarieren, die Typ-Parameter (innere Typen) haben, wie `list`, `dict`, `tuple`, +übergeben Sie den/die inneren Typ(en) als „Typ-Parameter“ in eckigen Klammern: `[` und `]` ```Python my_list: list[str] @@ -32,19 +33,19 @@ In unserem Beispiel können wir also bewirken, dass `tags` spezifisch eine „Li ## Set-Typen { #set-types } -Aber dann denken wir darüber nach und stellen fest, dass sich die Tags nicht wiederholen sollen, es sollen eindeutige Strings sein. +Aber dann denken wir darüber nach und stellen fest, dass sich die Tags nicht wiederholen sollten, sie wären wahrscheinlich eindeutige Strings. -Python hat einen Datentyp speziell für Mengen eindeutiger Dinge: das `set`. +Und Python hat einen speziellen Datentyp für Mengen eindeutiger Elemente, das `set`. -Deklarieren wir also `tags` als Set von Strings. +Dann können wir `tags` als Set von Strings deklarieren: {* ../../docs_src/body_nested_models/tutorial003_py310.py hl[12] *} -Jetzt, selbst wenn Sie einen Request mit duplizierten Daten erhalten, werden diese zu einem Set eindeutiger Dinge konvertiert. +Damit wird, selbst wenn Sie einen Request mit duplizierten Daten erhalten, dieser zu einem Set eindeutiger Elemente konvertiert. -Und wann immer Sie diese Daten ausgeben, selbst wenn die Quelle Duplikate hatte, wird es als Set von eindeutigen Dingen ausgegeben. +Und wann immer Sie diese Daten ausgeben, selbst wenn die Quelle Duplikate hatte, wird es als Set von eindeutigen Elementen ausgegeben. -Und es wird entsprechend annotiert/dokumentiert. +Und es wird entsprechend annotiert / dokumentiert. ## Verschachtelte Modelle { #nested-models } @@ -52,13 +53,13 @@ Jedes Attribut eines Pydantic-Modells hat einen Typ. Aber dieser Typ kann selbst ein anderes Pydantic-Modell sein. -Sie können also tief verschachtelte JSON-„Objekte“ deklarieren, mit spezifischen Attributnamen, -typen, und -validierungen. +Sie können also tief verschachtelte JSON-„Objekte“ deklarieren, mit spezifischen Attributnamen, Typen und Validierungen. Alles das beliebig tief verschachtelt. ### Ein Kindmodell definieren { #define-a-submodel } -Für ein Beispiel können wir ein `Image`-Modell definieren. +Zum Beispiel können wir ein `Image`-Modell definieren: {* ../../docs_src/body_nested_models/tutorial004_py310.py hl[7:9] *} @@ -68,7 +69,7 @@ Und dann können wir es als Typ eines Attributes verwenden: {* ../../docs_src/body_nested_models/tutorial004_py310.py hl[18] *} -Das würde bedeuten, dass **FastAPI** einen Body wie folgt erwartet: +Das würde bedeuten, dass **FastAPI** einen Body ähnlich dem folgenden erwartet: ```JSON { @@ -84,7 +85,7 @@ Das würde bedeuten, dass **FastAPI** einen Body wie folgt erwartet: } ``` -Wiederum, nur mit dieser Deklaration erhalten Sie von **FastAPI**: +Wiederum, nur mit dieser Deklaration erhalten Sie mit **FastAPI**: * Editor-Unterstützung (Codevervollständigung, usw.), selbst für verschachtelte Modelle * Datenkonvertierung @@ -105,7 +106,7 @@ Es wird getestet, ob der String eine gültige URL ist, und als solche wird er in ## Attribute mit Listen von Kindmodellen { #attributes-with-lists-of-submodels } -Sie können Pydantic-Modelle auch als Typen innerhalb von `list`, `set`, usw. verwenden: +Sie können Pydantic-Modelle auch als Kindtypen von `list`, `set`, usw. verwenden: {* ../../docs_src/body_nested_models/tutorial006_py310.py hl[18] *} @@ -135,7 +136,7 @@ Das wird einen JSON-Body erwarten (konvertieren, validieren, dokumentieren, usw. } ``` -/// info | Info +/// note | Hinweis Beachten Sie, dass der `images`-Schlüssel jetzt eine Liste von Bild-Objekten hat. @@ -147,15 +148,15 @@ Sie können beliebig tief verschachtelte Modelle definieren: {* ../../docs_src/body_nested_models/tutorial007_py310.py hl[7,12,18,21,25] *} -/// info | Info +/// note | Hinweis -Beachten Sie, wie `Offer` eine Liste von `Item`s hat, die ihrerseits eine optionale Liste von `Image`s haben. +Beachten Sie, wie `Offer` eine Liste von `Item`s hat, die ihrerseits eine optionale Liste von `Image`s haben /// ## Bodys aus reinen Listen { #bodies-of-pure-lists } -Wenn das äußerste Element des JSON-Bodys, das Sie erwarten, ein JSON-`array` (eine Python-`list`) ist, können Sie den Typ im Funktionsparameter deklarieren, mit der gleichen Syntax wie in Pydantic-Modellen: +Wenn der Wert auf oberster Ebene des JSON-Bodys, den Sie erwarten, ein JSON-`array` (eine Python-`list`) ist, können Sie den Typ im Parameter der Funktion deklarieren, genau wie in Pydantic-Modellen: ```Python images: list[Image] @@ -169,29 +170,29 @@ so wie in: Und Sie erhalten Editor-Unterstützung überall. -Selbst für Dinge in Listen: +Selbst für Elemente innerhalb von Listen: -Sie würden diese Editor-Unterstützung nicht erhalten, wenn Sie direkt mit `dict`, statt mit Pydantic-Modellen arbeiten würden. +Sie würden diese Art von Editor-Unterstützung nicht erhalten, wenn Sie direkt mit `dict`, statt mit Pydantic-Modellen arbeiten würden. -Aber Sie müssen sich auch nicht weiter um die Modelle kümmern, hereinkommende Dicts werden automatisch in sie konvertiert. Und was Sie zurückgeben, wird automatisch nach JSON konvertiert. +Aber Sie müssen sich auch nicht um diese kümmern, hereinkommende Dicts werden automatisch konvertiert und Ihre Ausgabe wird ebenfalls automatisch nach JSON konvertiert. ## Bodys mit beliebigen `dict`s { #bodies-of-arbitrary-dicts } Sie können einen Body auch als `dict` deklarieren, mit Schlüsseln eines Typs und Werten eines anderen Typs. -So brauchen Sie vorher nicht zu wissen, wie die Feld-/Attributnamen lauten (wie es bei Pydantic-Modellen der Fall wäre). +So brauchen Sie vorher nicht zu wissen, wie die gültigen Feld-/Attributnamen lauten (wie es bei Pydantic-Modellen der Fall wäre). -Das ist nützlich, wenn Sie Schlüssel empfangen, deren Namen Sie nicht bereits kennen. +Das ist nützlich, wenn Sie Schlüssel empfangen wollen, die Sie nicht bereits kennen. --- Ein anderer nützlicher Anwendungsfall ist, wenn Sie Schlüssel eines anderen Typs haben wollen, z. B. `int`. -Das schauen wir uns mal an. +Das schauen wir uns hier an. -Im folgenden Beispiel akzeptieren Sie irgendein `dict`, solange es `int`-Schlüssel und `float`-Werte hat: +In diesem Fall akzeptieren Sie irgendein `dict`, solange es `int`-Schlüssel mit `float`-Werten hat: {* ../../docs_src/body_nested_models/tutorial009_py310.py hl[7] *} @@ -201,9 +202,9 @@ Bedenken Sie, dass JSON nur `str` als Schlüssel unterstützt. Aber Pydantic hat automatische Datenkonvertierung. -Das bedeutet, dass Ihre API-Clients nur Strings senden können, aber solange diese Strings nur Zahlen enthalten, wird Pydantic sie konvertieren und validieren. +Das bedeutet, dass Ihre API-Clients zwar nur Strings als Schlüssel senden können, Pydantic diese aber konvertieren und validieren wird, solange diese Strings nur Ganzzahlen enthalten. -Und das `dict`, welches Sie als `weights` erhalten, wird `int`-Schlüssel und `float`-Werte haben. +Und das `dict`, welches Sie als `weights` erhalten, wird tatsächlich `int`-Schlüssel und `float`-Werte haben. /// @@ -213,8 +214,8 @@ Mit **FastAPI** haben Sie die maximale Flexibilität von Pydantic-Modellen, wäh Aber mit all den Vorzügen: -* Editor-Unterstützung (Codevervollständigung überall) -* Datenkonvertierung (auch bekannt als Parsen, Serialisierung) +* Editor-Unterstützung (Codevervollständigung überall!) +* Datenkonvertierung (auch bekannt als Parsen / Serialisierung) * Datenvalidierung * Schema-Dokumentation * Automatische Dokumentation diff --git a/docs/de/docs/tutorial/body.md b/docs/de/docs/tutorial/body.md index 9e87dfccf..6ced5f732 100644 --- a/docs/de/docs/tutorial/body.md +++ b/docs/de/docs/tutorial/body.md @@ -8,13 +8,13 @@ Ihre API muss fast immer einen **Response**body senden. Aber Clients müssen nic Um einen **Request**body zu deklarieren, verwenden Sie [Pydantic](https://docs.pydantic.dev/)-Modelle mit all deren Fähigkeiten und Vorzügen. -/// info | Info +/// note | Hinweis Um Daten zu senden, sollten Sie eines von: `POST` (meistverwendet), `PUT`, `DELETE` oder `PATCH` verwenden. Das Senden eines Bodys mit einem `GET`-Request hat ein undefiniertes Verhalten in den Spezifikationen, wird aber dennoch von FastAPI unterstützt, nur für sehr komplexe/extreme Anwendungsfälle. -Da davon abgeraten wird, zeigt die interaktive Dokumentation mit Swagger-Benutzeroberfläche die Dokumentation für den Body nicht an, wenn `GET` verwendet wird, und zwischengeschaltete Proxys unterstützen es möglicherweise nicht. +Da davon abgeraten wird, zeigt die interaktive Dokumentation mit Swagger UI die Dokumentation für den Body nicht an, wenn `GET` verwendet wird, und zwischengeschaltete Proxys unterstützen es möglicherweise nicht. /// @@ -32,6 +32,7 @@ Verwenden Sie Standard-Python-Typen für alle Attribute: {* ../../docs_src/body/tutorial001_py310.py hl[5:9] *} + Wie auch bei der Deklaration von Query-Parametern gilt: Wenn ein Modellattribut einen Defaultwert hat, ist das Attribut nicht erforderlich. Andernfalls ist es erforderlich. Verwenden Sie `None`, um es einfach optional zu machen. Zum Beispiel deklariert das obige Modell ein JSON „`object`“ (oder Python-`dict`) wie dieses: @@ -45,7 +46,7 @@ Zum Beispiel deklariert das obige Modell ein JSON „`object`“ (oder Python- -/// info | Info +/// note | Hinweis Bitte beachten Sie, dass Browser Cookies auf spezielle Weise und im Hintergrund bearbeiten, sodass sie **nicht** leicht **JavaScript** erlauben, diese zu berühren. diff --git a/docs/de/docs/tutorial/cookie-params.md b/docs/de/docs/tutorial/cookie-params.md index 81a753211..db5f3332c 100644 --- a/docs/de/docs/tutorial/cookie-params.md +++ b/docs/de/docs/tutorial/cookie-params.md @@ -24,13 +24,13 @@ Aber denken Sie daran, dass, wenn Sie `Query`, `Path`, `Cookie` und andere von ` /// -/// info | Info +/// note | Hinweis Um Cookies zu deklarieren, müssen Sie `Cookie` verwenden, da die Parameter sonst als Query-Parameter interpretiert würden. /// -/// info | Info +/// note | Hinweis Beachten Sie, dass **Browser Cookies auf besondere Weise und hinter den Kulissen handhaben** und **JavaScript** **nicht** ohne Weiteres erlauben, auf sie zuzugreifen. diff --git a/docs/de/docs/tutorial/debugging.md b/docs/de/docs/tutorial/debugging.md index 5e5f748ba..f7949d027 100644 --- a/docs/de/docs/tutorial/debugging.md +++ b/docs/de/docs/tutorial/debugging.md @@ -99,7 +99,7 @@ So könnte es aussehen: --- -Wenn Sie Pycharm verwenden, können Sie: +Wenn Sie PyCharm verwenden, können Sie: * Das Menü „Run“ öffnen. * Die Option „Debug ...“ auswählen. diff --git a/docs/de/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md b/docs/de/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md index 028d280dc..a3ef1d5a8 100644 --- a/docs/de/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md +++ b/docs/de/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md @@ -28,7 +28,7 @@ Damit wird auch vermieden, neue Entwickler möglicherweise zu verwirren, die ein /// -/// info | Info +/// note | Hinweis In diesem Beispiel verwenden wir zwei erfundene benutzerdefinierte Header `X-Key` und `X-Token`. diff --git a/docs/de/docs/tutorial/dependencies/dependencies-with-yield.md b/docs/de/docs/tutorial/dependencies/dependencies-with-yield.md index e1eec2350..5bb8868fc 100644 --- a/docs/de/docs/tutorial/dependencies/dependencies-with-yield.md +++ b/docs/de/docs/tutorial/dependencies/dependencies-with-yield.md @@ -2,7 +2,7 @@ FastAPI unterstützt Abhängigkeiten, die einige zusätzliche Schritte nach Abschluss ausführen. -Verwenden Sie dazu `yield` statt `return` und schreiben Sie die zusätzlichen Schritte / den zusätzlichen Code danach. +Verwenden Sie dazu `yield` statt `return` und schreiben Sie die zusätzlichen Schritte (Code) danach. /// tip | Tipp @@ -77,7 +77,7 @@ Und wiederum benötigt `dependency_b` den Wert von `dependency_a` (hier `dep_a` {* ../../docs_src/dependencies/tutorial008_an_py310.py hl[18:19,26:27] *} -Auf die gleiche Weise könnten Sie einige Abhängigkeiten mit `yield` und einige andere Abhängigkeiten mit `return` haben, und alle können beliebig voneinander abhängen. +Auf die gleiche Weise könnten Sie einige Abhängigkeiten mit `yield` und einige andere Abhängigkeiten mit `return` haben, und einige davon von einigen der anderen abhängen lassen. Und Sie könnten eine einzelne Abhängigkeit haben, die auf mehreren ge`yield`eten Abhängigkeiten basiert, usw. @@ -170,7 +170,7 @@ participant tasks as Hintergrundtasks end ``` -/// info | Info +/// note | Hinweis Es wird nur **eine Response** an den Client gesendet. Es kann eine Error-Response oder die Response der *Pfadoperation* sein. @@ -234,6 +234,7 @@ participant operation as Pfadoperation Abhängigkeiten mit `yield` haben sich im Laufe der Zeit weiterentwickelt, um verschiedene Anwendungsfälle abzudecken und einige Probleme zu beheben. Wenn Sie sehen möchten, was sich in verschiedenen Versionen von FastAPI geändert hat, lesen Sie mehr dazu im fortgeschrittenen Teil, unter [Fortgeschrittene Abhängigkeiten – Abhängigkeiten mit `yield`, `HTTPException`, `except` und Hintergrundtasks](../../advanced/advanced-dependencies.md#dependencies-with-yield-httpexception-except-and-background-tasks). + ## Kontextmanager { #context-managers } ### Was sind „Kontextmanager“ { #what-are-context-managers } @@ -266,18 +267,19 @@ Wenn Sie gerade erst mit **FastAPI** beginnen, möchten Sie das vielleicht vorer In Python können Sie Kontextmanager erstellen, indem Sie [eine Klasse mit zwei Methoden erzeugen: `__enter__()` und `__exit__()`](https://docs.python.org/3/reference/datamodel.html#context-managers). -Sie können solche auch innerhalb von **FastAPI**-Abhängigkeiten mit `yield` verwenden, indem Sie `with`- oder `async with`-Anweisungen innerhalb der Abhängigkeits-Funktion verwenden: +Sie können solche auch innerhalb von **FastAPI**-Abhängigkeiten mit `yield` verwenden, indem Sie +`with`- oder `async with`-Anweisungen innerhalb der Abhängigkeits-Funktion verwenden: {* ../../docs_src/dependencies/tutorial010_py310.py hl[1:9,13] *} /// tip | Tipp -Andere Möglichkeiten, einen Kontextmanager zu erstellen, sind: +Eine weitere Möglichkeit, einen Kontextmanager zu erstellen, ist: * [`@contextlib.contextmanager`](https://docs.python.org/3/library/contextlib.html#contextlib.contextmanager) oder * [`@contextlib.asynccontextmanager`](https://docs.python.org/3/library/contextlib.html#contextlib.asynccontextmanager) -Verwenden Sie diese, um eine Funktion zu dekorieren, die ein einziges `yield` hat. +indem Sie damit eine Funktion dekorieren, die ein einziges `yield` hat. Das ist es auch, was **FastAPI** intern für Abhängigkeiten mit `yield` verwendet. diff --git a/docs/de/docs/tutorial/dependencies/index.md b/docs/de/docs/tutorial/dependencies/index.md index 49c65eb37..e631e7863 100644 --- a/docs/de/docs/tutorial/dependencies/index.md +++ b/docs/de/docs/tutorial/dependencies/index.md @@ -50,7 +50,7 @@ In diesem Fall erwartet diese Abhängigkeit: Und dann wird einfach ein `dict` zurückgegeben, welches diese Werte enthält. -/// info | Info +/// note | Hinweis FastAPI unterstützt (und empfiehlt die Verwendung von) `Annotated` seit Version 0.95.0. @@ -105,7 +105,7 @@ common_parameters --> read_users Auf diese Weise schreiben Sie gemeinsam genutzten Code nur einmal, und **FastAPI** kümmert sich darum, ihn für Ihre *Pfadoperationen* aufzurufen. -/// check | Testen +/// tip | Tipp Beachten Sie, dass Sie keine spezielle Klasse erstellen und diese irgendwo an **FastAPI** übergeben müssen, um sie zu „registrieren“ oder so ähnlich. diff --git a/docs/de/docs/tutorial/dependencies/sub-dependencies.md b/docs/de/docs/tutorial/dependencies/sub-dependencies.md index b01cc80a7..d6a2056cd 100644 --- a/docs/de/docs/tutorial/dependencies/sub-dependencies.md +++ b/docs/de/docs/tutorial/dependencies/sub-dependencies.md @@ -35,7 +35,7 @@ Diese Abhängigkeit verwenden wir nun wie folgt: {* ../../docs_src/dependencies/tutorial005_an_py310.py hl[23] *} -/// info | Info +/// note | Hinweis Beachten Sie, dass wir in der *Pfadoperation-Funktion* nur eine einzige Abhängigkeit deklarieren, den `query_or_cookie_extractor`. diff --git a/docs/de/docs/tutorial/extra-data-types.md b/docs/de/docs/tutorial/extra-data-types.md index 92401172b..d1feab1a0 100644 --- a/docs/de/docs/tutorial/extra-data-types.md +++ b/docs/de/docs/tutorial/extra-data-types.md @@ -1,5 +1,6 @@ # Zusätzliche Datentypen { #extra-data-types } + Bisher haben Sie gängige Datentypen verwendet, wie zum Beispiel: * `int` diff --git a/docs/de/docs/tutorial/extra-models.md b/docs/de/docs/tutorial/extra-models.md index 59580d73a..8e0b094ad 100644 --- a/docs/de/docs/tutorial/extra-models.md +++ b/docs/de/docs/tutorial/extra-models.md @@ -63,7 +63,7 @@ würden wir ein Python-`dict` erhalten mit: #### Ein `dict` entpacken { #unpacking-a-dict } -Wenn wir ein `dict` wie `user_dict` nehmen und es einer Funktion (oder Klasse) mit `**user_dict` übergeben, wird Python es „entpacken“. Es wird die Schlüssel und Werte von `user_dict` direkt als Schlüsselwort-Argumente übergeben. +Wenn wir ein `dict` wie `user_dict` nehmen und es einer Funktion (oder Klasse) mit `**user_dict` übergeben, wird Python es „entpacken“. Es wird die Schlüssel und Werte von `user_dict` direkt als Schlüssel-Wert-Argumente übergeben. Setzen wir also das `user_dict` von oben ein: @@ -196,7 +196,7 @@ Dafür verwenden Sie Pythons Standard-`list`: ## Response mit beliebigem `dict` { #response-with-arbitrary-dict } -Sie können auch eine Response deklarieren, die ein beliebiges `dict` zurückgibt, indem Sie nur die Typen der Schlüssel und Werte ohne ein Pydantic-Modell deklarieren. +Sie können auch eine Response deklarieren, die ein einfaches beliebiges `dict` verwendet, indem Sie nur den Typ der Schlüssel und Werte deklarieren, ohne ein Pydantic-Modell zu verwenden. Dies ist nützlich, wenn Sie die gültigen Feld-/Attributnamen nicht im Voraus kennen (die für ein Pydantic-Modell benötigt werden würden). @@ -208,4 +208,4 @@ In diesem Fall können Sie `dict` verwenden: Verwenden Sie gerne mehrere Pydantic-Modelle und vererben Sie je nach Bedarf. -Sie brauchen kein einzelnes Datenmodell pro Einheit, wenn diese Einheit in der Lage sein muss, verschiedene „Zustände“ zu haben. Wie im Fall der Benutzer-„Einheit“ mit einem Zustand einschließlich `password`, `password_hash` und ohne Passwort. +Sie brauchen kein einzelnes Datenmodell pro Entität, wenn diese Entität in der Lage sein muss, verschiedene „Zustände“ zu haben. Die **Benutzer**-„Entität“ ist ein Beispiel, mit Zuständen, die `password`, `password_hash` oder kein Passwort umfassen. diff --git a/docs/de/docs/tutorial/first-steps.md b/docs/de/docs/tutorial/first-steps.md index 0cf3d03a9..8e97b5b5d 100644 --- a/docs/de/docs/tutorial/first-steps.md +++ b/docs/de/docs/tutorial/first-steps.md @@ -180,7 +180,7 @@ was äquivalent wäre zu: from backend.main import app ``` -### `fastapi dev` mit Pfad { #fastapi-dev-with-path } +### `fastapi dev` mit Pfad oder mit der CLI-Option `--entrypoint` { #fastapi-dev-with-path-or-with-entrypoint-cli-option } Sie können auch den Dateipfad an den Befehl `fastapi dev` übergeben, und er wird das zu verwendende FastAPI-App-Objekt erraten: @@ -188,29 +188,19 @@ Sie können auch den Dateipfad an den Befehl `fastapi dev` übergeben, und er wi $ fastapi dev main.py ``` -Aber Sie müssten sich daran erinnern, bei jedem Aufruf des `fastapi`-Befehls den korrekten Pfad zu übergeben. - -Zusätzlich könnten andere Tools es nicht finden, z. B. die [VS Code-Erweiterung](../editor-support.md) oder [FastAPI Cloud](https://fastapicloud.com). Daher wird empfohlen, den `entrypoint` in `pyproject.toml` zu verwenden. - -### Ihre App deployen (optional) { #deploy-your-app-optional } - -Sie können optional Ihre FastAPI-App in der [FastAPI Cloud](https://fastapicloud.com) deployen, treten Sie der Warteliste bei, falls Sie es noch nicht getan haben. 🚀 - -Wenn Sie bereits ein **FastAPI Cloud**-Konto haben (wir haben Sie von der Warteliste eingeladen 😉), können Sie Ihre Anwendung mit einem Befehl deployen. - -Vor dem Deployen, stellen Sie sicher, dass Sie eingeloggt sind: - -
+Oder Sie können die Option `--entrypoint` an den Befehl `fastapi dev` übergeben: ```console -$ fastapi login - -You are logged in to FastAPI Cloud 🚀 +$ fastapi dev --entrypoint main:app ``` -
+Aber Sie müssten sich daran erinnern, bei jedem Aufruf des `fastapi`-Befehls den korrekten Pfad\entrypoint zu übergeben. + +Zusätzlich könnten andere Tools es nicht finden, z. B. die [VS Code-Erweiterung](../editor-support.md) oder [FastAPI Cloud](https://fastapicloud.com). Daher wird empfohlen, den `entrypoint` in `pyproject.toml` zu verwenden. -Dann stellen Sie Ihre App bereit: +### Ihre App deployen (optional) { #deploy-your-app-optional } + +Sie können optional Ihre FastAPI-App in der [FastAPI Cloud](https://fastapicloud.com) mit einem einzigen Befehl deployen. 🚀
@@ -226,6 +216,8 @@ Deploying to FastAPI Cloud...
+Das CLI erkennt Ihre FastAPI-Anwendung automatisch und deployt sie in die Cloud. Wenn Sie nicht eingeloggt sind, wird Ihr Browser geöffnet, um die Authentifizierung abzuschließen. + Das war's! Jetzt können Sie Ihre App unter dieser URL aufrufen. ✨ ## Zusammenfassung, Schritt für Schritt { #recap-step-by-step } @@ -244,7 +236,7 @@ Sie können alle [Starlette](https://www.starlette.dev/)-Funktionalitäten auch /// -### Schritt 2: Erzeugen einer `FastAPI`-„Instanz“ { #step-2-create-a-fastapi-instance } +### Schritt 2: Eine `FastAPI`-„Instanz“ erstellen { #step-2-create-a-fastapi-instance } {* ../../docs_src/first_steps/tutorial001_py310.py hl[3] *} @@ -252,7 +244,7 @@ In diesem Beispiel ist die Variable `app` eine „Instanz“ der Klasse `FastAPI Dies wird der Hauptinteraktionspunkt für die Erstellung all Ihrer APIs sein. -### Schritt 3: Erstellen einer *Pfadoperation* { #step-3-create-a-path-operation } +### Schritt 3: Eine *Pfadoperation* erstellen { #step-3-create-a-path-operation } #### Pfad { #path } @@ -270,7 +262,7 @@ https://example.com/items/foo /items/foo ``` -/// info | Info +/// note | Hinweis Ein „Pfad“ wird häufig auch als „Endpunkt“ oder „Route“ bezeichnet. @@ -313,7 +305,7 @@ In OpenAPI wird folglich jede dieser HTTP-Methoden als „Operation“ bezeichne Wir werden sie auch „**Operationen**“ nennen. -#### Definieren eines *Pfadoperation-Dekorators* { #define-a-path-operation-decorator } +#### Einen *Pfadoperation-Dekorator* definieren { #define-a-path-operation-decorator } {* ../../docs_src/first_steps/tutorial001_py310.py hl[6] *} @@ -322,7 +314,7 @@ Das `@app.get("/")` sagt **FastAPI**, dass die Funktion direkt darunter für die * den Pfad `/` * unter der Verwendung der get-Operation gehen -/// info | `@decorator` Info +/// note | `@decorator` Info Diese `@something`-Syntax wird in Python „Dekorator“ genannt. @@ -361,7 +353,7 @@ Wenn Sie beispielsweise GraphQL verwenden, führen Sie normalerweise alle Aktion /// -### Schritt 4: Definieren der **Pfadoperation-Funktion** { #step-4-define-the-path-operation-function } +### Schritt 4: Die **Pfadoperation-Funktion** definieren { #step-4-define-the-path-operation-function } Das ist unsere „**Pfadoperation-Funktion**“: @@ -407,11 +399,11 @@ Stellen Sie Ihre App in der **[FastAPI Cloud](https://fastapicloud.com)** mit ei **[FastAPI Cloud](https://fastapicloud.com)** wird vom selben Autor und Team hinter **FastAPI** entwickelt. -Es vereinfacht den Prozess des Erstellens, Deployens und des Zugriffs auf eine API mit minimalem Aufwand. +Es vereinfacht den Prozess des **Erstellens**, **Deployens** und des **Zugriffs** auf eine API mit minimalem Aufwand. Es bringt die gleiche **Developer-Experience** beim Erstellen von Apps mit FastAPI auch zum **Deployment** in der Cloud. 🎉 -FastAPI Cloud ist der Hauptsponsor und Finanzierer der „FastAPI and friends“ Open-Source-Projekte. ✨ +FastAPI Cloud ist der Hauptsponsor und Finanzierer der *FastAPI and friends*-Open-Source-Projekte. ✨ #### Zu anderen Cloudanbietern deployen { #deploy-to-other-cloud-providers } @@ -422,7 +414,7 @@ Folgen Sie den Anleitungen Ihres Cloudanbieters, um dort FastAPI-Apps bereitzust ## Zusammenfassung { #recap } * Importieren Sie `FastAPI`. -* Erstellen Sie eine `app` Instanz. +* Erstellen Sie eine `app`-Instanz. * Schreiben Sie einen **Pfadoperation-Dekorator** unter Verwendung von Dekoratoren wie `@app.get("/")`. * Definieren Sie eine **Pfadoperation-Funktion**, zum Beispiel `def root(): ...`. * Starten Sie den Entwicklungsserver mit dem Befehl `fastapi dev`. diff --git a/docs/de/docs/tutorial/frontend.md b/docs/de/docs/tutorial/frontend.md new file mode 100644 index 000000000..9cd4644d9 --- /dev/null +++ b/docs/de/docs/tutorial/frontend.md @@ -0,0 +1,133 @@ +# Frontend { #frontend } + +Sie können statische Frontend-Apps mit `app.frontend()` (oder `router.frontend()`) bereitstellen. + +Das ist nützlich für Frontend-Tools, die statische Dateien generieren, wie React mit Vite, TanStack Router, Astro, Vue, Svelte, Angular, Solid und andere. + +Mit diesen Tools haben Sie normalerweise einen Schritt, der das Frontend baut, mit einem Befehl wie: + +```bash +npm run build +``` + +Das würde ein Verzeichnis wie `./dist/` mit Ihren Frontend-Dateien generieren. + +Sie können `app.frontend()` verwenden, um dieses Verzeichnis gemäß den Konventionen bereitzustellen, die von diesen Frontend-Frameworks benötigt werden. + +**FastAPI** prüft zuerst *Pfadoperationen*. Die Frontend-Dateien werden nur geprüft, wenn keine normale Route gepasst hat, sodass Ihre API nicht beeinträchtigt wird. + +## Ein Frontend bereitstellen { #serve-a-frontend } + +Nachdem Sie Ihr Frontend gebaut haben, zum Beispiel mit `npm run build`, legen Sie die generierten Dateien in ein Verzeichnis, zum Beispiel `dist`. + +Ihre Projektstruktur könnte so aussehen: + +```text +. +├── pyproject.toml +├── app +│ ├── __init__.py +│ └── main.py +└── dist + ├── index.html + └── assets + └── app.js +``` + +Stellen Sie es dann mit `app.frontend()` bereit: + +{* ../../docs_src/frontend/tutorial001_py310.py hl[5] *} + +Damit kann ein Request für `/assets/app.js` `dist/assets/app.js` ausliefern. + +Wenn Sie außerdem eine **FastAPI**-*Pfadoperation* haben, gewinnt die *Pfadoperation*. + +## Clientseitiges Routing { #client-side-routing } + +Viele Frontend-Apps, einschließlich **Single-Page-Apps** (SPAs), verwenden clientseitiges Routing. Ein Pfad wie `/dashboard/settings` ist möglicherweise keine echte Datei, aber das Framework würde sich darum kümmern, ihn zu handhaben. + +Wenn also direkt auf diese URL zugegriffen wird (statt durch die App zu navigieren), sollte das Backend die Frontend-App von `index.html` bereitstellen, sodass das Frontend-Framework anschließend das clientseitige Routing handhaben kann. + +Verwenden Sie dafür `fallback="index.html"`: + +{* ../../docs_src/frontend/tutorial002_py310.py hl[5] *} + +**FastAPI** verwendet diesen Fallback nur für `GET`- und `HEAD`-Requests, die wie Browser-Navigation aussehen. Fehlende Dateien wie JavaScript, CSS und Bilder geben weiterhin `404` zurück. + +Requests mit anderen Methoden, wie `POST` oder `PUT`, an Pfade, die nur zum Frontend-Fallback passen, geben ebenfalls `404` zurück. Reguläre **FastAPI**-*Pfadoperationen* haben weiterhin eine höhere Priorität als Frontend-Routen. + +/// tip | Tipp + +Standardmäßig hat `fallback` einen Wert von `fallback="auto"`. In den meisten Fällen müssen Sie `fallback` nicht angeben. Lesen Sie weiter unten die Details. + +/// + +Das ist das, was Sie bei vielen Frontend-Apps möchten, die clientseitiges Routing verwenden, zum Beispiel React mit TanStack Router, Vue, Angular, SvelteKit oder Solid. + +## Benutzerdefinierte 404-Seite { #custom-404-page } + +Sie können auch eine statische `404.html`-Seite für fehlende Frontend-Pfade ausliefern: + +{* ../../docs_src/frontend/tutorial003_py310.py hl[5] *} + +Diese Response behält einen Statuscode von `404`. + +In diesem Fall liefert **FastAPI** für fehlende Frontend-Pfade nicht `index.html` aus. Stattdessen wird die Datei `404.html` zurückgegeben. + +/// tip | Tipp + +Standardmäßig hat `fallback` einen Wert von `fallback="auto"`. Damit wird, wenn eine `404.html`-Datei gefunden wird, diese automatisch als Fallback verwendet. + +Sie können das `fallback`-Argument also normalerweise weglassen. + +/// + +Das ist nützlich bei Frontend-Tools, die für jede Seite statische HTML-Dateien generieren, wie Astro. + +## Automatischer Fallback { #fallback-auto } + +Standardmäßig verwendet `app.frontend()` `fallback="auto"`. + +Wenn es im Frontend-Verzeichnis eine `404.html`-Datei gibt, liefern fehlende Frontend-Pfade diese Datei mit dem Statuscode `404` aus. + +Andernfalls, wenn es eine `index.html`-Datei gibt, liefern fehlende Browser-Navigationspfade `index.html` aus, was viele Frontend-Apps mit clientseitigem Routing erwarten. + +In den meisten Fällen können Sie also `app.frontend("/", directory="dist")` verwenden, ohne das `fallback`-Argument anzugeben. + +{* ../../docs_src/frontend/tutorial001_py310.py hl[5] *} + +## Fallback deaktivieren { #disable-fallback } + +Wenn Sie keine Fallback-Datei für fehlende Frontend-Pfade ausliefern möchten, verwenden Sie `fallback=None`: + +{* ../../docs_src/frontend/tutorial005_py310.py hl[5] *} + +Dann geben fehlende Frontend-Pfade das normale `404` zurück. + +## Verzeichnis prüfen { #check-directory } + +Standardmäßig prüft `app.frontend()`, dass das Verzeichnis existiert, wenn die App erstellt wird. + +Das hilft, Konfigurationsfehler früh zu erkennen. Wenn zum Beispiel das Output-Verzeichnis des Frontend-Builds fehlt, löst **FastAPI** beim Startup einen Fehler aus. + +Wenn Ihre Frontend-Dateien später erstellt werden, zum Beispiel durch einen separaten Build-Schritt, nachdem das App-Objekt erstellt wurde, setzen Sie `check_dir=False`: + +{* ../../docs_src/frontend/tutorial006_py310.py hl[5] *} + +Mit `check_dir=False` prüft **FastAPI** das Verzeichnis nicht, wenn die App erstellt wird. Wenn das konfigurierte Verzeichnis beim Verarbeiten eines Requests immer noch fehlt, löst **FastAPI** dann einen Fehler aus. + +## Mit `APIRouter` verwenden { #use-it-with-apirouter } + +Sie können Frontend-Dateien auch zu einem `APIRouter` hinzufügen und ihn mit einem Präfix einbinden: + +{* ../../docs_src/frontend/tutorial004_py310.py hl[6,7] *} + +In diesem Beispiel werden Frontend-Pfade unter `/app` bereitgestellt. + +Alle regulären *Pfadoperationen* in der App haben weiterhin Vorrang, auch in anderen Routern. + +## Nur statischer Build-Output { #static-build-output-only } + +`app.frontend()` liefert Dateien aus, die bereits von Ihrem Frontend-Build generiert wurden. + +Es führt kein serverseitiges Rendering aus. Es ist für Frontend-Frameworks gedacht, die statische Dateien generieren, nicht für Frameworks, die dynamisches Rendering auf dem Server für jeden Request benötigen. diff --git a/docs/de/docs/tutorial/handling-errors.md b/docs/de/docs/tutorial/handling-errors.md index 261831a8e..17e2767fe 100644 --- a/docs/de/docs/tutorial/handling-errors.md +++ b/docs/de/docs/tutorial/handling-errors.md @@ -8,12 +8,12 @@ Sie könnten dem Client mitteilen müssen, dass: * Der Client nicht genügend Berechtigungen für diese Operation hat. * Der Client keinen Zugriff auf diese Ressource hat. -* Die Ressource, auf die der Client versucht hat, zuzugreifen, nicht existiert. +* Das Item, auf das der Client versucht hat zuzugreifen, nicht existiert. * usw. In diesen Fällen würden Sie normalerweise einen **HTTP-Statuscode** im Bereich **400** (von 400 bis 499) zurückgeben. -Dies ist vergleichbar mit den HTTP-Statuscodes im Bereich 200 (von 200 bis 299). Diese „200“-Statuscodes bedeuten, dass der Request in irgendeiner Weise erfolgreich war. +Dies ist vergleichbar mit den HTTP-Statuscodes im Bereich 200 (von 200 bis 299). Diese „200“-Statuscodes bedeuten, dass der Request irgendwie ein „Erfolg“ war. Die Statuscodes im Bereich 400 bedeuten hingegen, dass es einen Fehler seitens des Clients gab. @@ -37,7 +37,7 @@ Das bedeutet auch, wenn Sie sich innerhalb einer Hilfsfunktion befinden, die Sie Der Vorteil des Auslösens einer Exception gegenüber dem Zurückgeben eines Wertes wird im Abschnitt über Abhängigkeiten und Sicherheit deutlicher werden. -In diesem Beispiel lösen wir eine Exception mit einem Statuscode von `404` aus, wenn der Client einen Artikel mit einer nicht existierenden ID anfordert: +In diesem Beispiel lösen wir eine Exception mit einem Statuscode von `404` aus, wenn der Client ein Item mit einer nicht existierenden ID anfordert: {* ../../docs_src/handling_errors/tutorial001_py310.py hl[11] *} @@ -51,7 +51,7 @@ Wenn der Client `http://example.com/items/foo` anfordert (ein `item_id` `"foo"`) } ``` -Aber wenn der Client `http://example.com/items/bar` anfordert (ein nicht-existierendes `item_id` `"bar"`), erhält er einen HTTP-Statuscode 404 (der „Not Found“-Error) und eine JSON-Response wie: +Aber wenn der Client `http://example.com/items/bar` anfordert (ein nicht-existierendes `item_id` `"bar"`), erhält er einen HTTP-Statuscode 404 (der „not found“-Error) und eine JSON-Response wie: ```JSON { @@ -71,7 +71,7 @@ Diese werden von **FastAPI** automatisch gehandhabt und in JSON konvertiert. ## Benutzerdefinierte Header hinzufügen { #add-custom-headers } -Es gibt Situationen, in denen es nützlich ist, dem HTTP-Error benutzerdefinierte Header hinzuzufügen. Zum Beispiel in einigen Sicherheitsszenarien. +Es gibt Situationen, in denen es nützlich ist, dem HTTP-Error benutzerdefinierte Header hinzuzufügen. Zum Beispiel für einige Arten von Sicherheit. Sie werden es wahrscheinlich nicht direkt in Ihrem Code verwenden müssen. @@ -117,7 +117,7 @@ Diese Handler sind dafür verantwortlich, die Default-JSON-Responses zurückzuge Sie können diese Exceptionhandler mit Ihren eigenen überschreiben. -### Überschreiben von Request-Validierungs-Exceptions { #override-request-validation-exceptions } +### Request-Validierungs-Exceptions überschreiben { #override-request-validation-exceptions } Wenn ein Request ungültige Daten enthält, löst **FastAPI** intern einen `RequestValidationError` aus. @@ -153,7 +153,7 @@ Validation errors: Field: ('path', 'item_id'), Error: Input should be a valid integer, unable to parse string as an integer ``` -### Überschreiben des `HTTPException`-Fehlerhandlers { #override-the-httpexception-error-handler } +### Den `HTTPException`-Fehlerhandler überschreiben { #override-the-httpexception-error-handler } Auf die gleiche Weise können Sie den `HTTPException`-Handler überschreiben. @@ -177,7 +177,7 @@ Das bedeutet aber auch, dass, wenn Sie ihn einfach in einen String umwandeln und /// -### Verwenden des `RequestValidationError`-Bodys { #use-the-requestvalidationerror-body } +### Den `RequestValidationError`-Body verwenden { #use-the-requestvalidationerror-body } Der `RequestValidationError` enthält den empfangenen `body` mit den ungültigen Daten. @@ -185,7 +185,7 @@ Sie könnten diesen während der Entwicklung Ihrer Anwendung verwenden, um den B {* ../../docs_src/handling_errors/tutorial005_py310.py hl[14] *} -Versuchen Sie nun, einen ungültigen Artikel zu senden: +Versuchen Sie nun, ein ungültiges Item zu senden: ```JSON { @@ -194,7 +194,7 @@ Versuchen Sie nun, einen ungültigen Artikel zu senden: } ``` -Sie erhalten eine Response, die Ihnen sagt, dass die Daten ungültig sind und die den empfangenen Body enthält: +Sie erhalten eine Response, die Ihnen sagt, dass die Daten ungültig sind, und die den empfangenen Body enthält: ```JSON hl_lines="12-15" { diff --git a/docs/de/docs/tutorial/index.md b/docs/de/docs/tutorial/index.md index 4b5272ebd..c0f25c916 100644 --- a/docs/de/docs/tutorial/index.md +++ b/docs/de/docs/tutorial/index.md @@ -1,5 +1,6 @@ # Tutorial – Benutzerhandbuch { #tutorial-user-guide } + Dieses Tutorial zeigt Ihnen Schritt für Schritt, wie Sie **FastAPI** mit den meisten seiner Funktionen verwenden können. Jeder Abschnitt baut schrittweise auf den vorhergehenden auf, ist jedoch in einzelne Themen gegliedert, sodass Sie direkt zu einem bestimmten Thema übergehen können, um Ihre spezifischen API-Anforderungen zu lösen. diff --git a/docs/de/docs/tutorial/metadata.md b/docs/de/docs/tutorial/metadata.md index 498ad83a8..e6549aa3c 100644 --- a/docs/de/docs/tutorial/metadata.md +++ b/docs/de/docs/tutorial/metadata.md @@ -11,7 +11,7 @@ Sie können die folgenden Felder festlegen, die in der OpenAPI-Spezifikation und | `title` | `str` | Der Titel der API. | | `summary` | `str` | Eine kurze Zusammenfassung der API. Verfügbar seit OpenAPI 3.1.0, FastAPI 0.99.0. | | `description` | `str` | Eine kurze Beschreibung der API. Kann Markdown verwenden. | -| `version` | `string` | Die Version der API. Das ist die Version Ihrer eigenen Anwendung, nicht die von OpenAPI. Zum Beispiel `2.5.0`. | +| `version` | `str` | Die Version der API. Das ist die Version Ihrer eigenen Anwendung, nicht die von OpenAPI. Zum Beispiel `2.5.0`. | | `terms_of_service` | `str` | Eine URL zu den Nutzungsbedingungen für die API. Falls angegeben, muss es sich um eine URL handeln. | | `contact` | `dict` | Die Kontaktinformationen für die freigegebene API. Kann mehrere Felder enthalten.
contact-Felder
ParameterTypBeschreibung
namestrDer identifizierende Name der Kontaktperson/Organisation.
urlstrDie URL, die auf die Kontaktinformationen verweist. MUSS im Format einer URL vorliegen.
emailstrDie E-Mail-Adresse der Kontaktperson/Organisation. MUSS im Format einer E-Mail-Adresse vorliegen.
| | `license_info` | `dict` | Die Lizenzinformationen für die freigegebene API. Kann mehrere Felder enthalten.
license_info-Felder
ParameterTypBeschreibung
namestrERFORDERLICH (wenn eine license_info festgelegt ist). Der für die API verwendete Lizenzname.
identifierstrEin [SPDX](https://spdx.org/licenses/)-Lizenzausdruck für die API. Das Feld identifier und das Feld url schließen sich gegenseitig aus. Verfügbar seit OpenAPI 3.1.0, FastAPI 0.99.0.
urlstrEine URL zur Lizenz, die für die API verwendet wird. MUSS im Format einer URL vorliegen.
| @@ -74,7 +74,7 @@ Verwenden Sie den Parameter `tags` mit Ihren *Pfadoperationen* (und `APIRouter`n {* ../../docs_src/metadata/tutorial004_py310.py hl[21,26] *} -/// info | Info +/// note | Hinweis Lesen Sie mehr zu Tags unter [Pfadoperation-Konfiguration](path-operation-configuration.md#tags). diff --git a/docs/de/docs/tutorial/path-operation-configuration.md b/docs/de/docs/tutorial/path-operation-configuration.md index 111c71494..56c8a69e7 100644 --- a/docs/de/docs/tutorial/path-operation-configuration.md +++ b/docs/de/docs/tutorial/path-operation-configuration.md @@ -38,11 +38,11 @@ Diese werden zum OpenAPI-Schema hinzugefügt und von den automatischen Dokumenta -### Tags mittels Enumeration { #tags-with-enums } +### Tags mit Enums { #tags-with-enums } -Wenn Sie eine große Anwendung haben, können sich am Ende **viele Tags** anhäufen, und Sie möchten sicherstellen, dass Sie für verwandte *Pfadoperationen* immer den **gleichen Tag** verwenden. +Wenn Sie eine große Anwendung haben, können sich am Ende **mehrere Tags** anhäufen, und Sie möchten sicherstellen, dass Sie für verwandte *Pfadoperationen* immer den **gleichen Tag** verwenden. -In diesem Fall macht es Sinn, die Tags in einem `Enum` zu speichern. +In diesen Fällen kann es sinnvoll sein, die Tags in einem `Enum` zu speichern. **FastAPI** unterstützt das auf die gleiche Weise wie einfache Strings: @@ -72,13 +72,13 @@ Sie können die Response mit dem Parameter `response_description` beschreiben: {* ../../docs_src/path_operation_configuration/tutorial005_py310.py hl[18] *} -/// info | Info +/// note | Hinweis Beachten Sie, dass sich `response_description` speziell auf die Response bezieht, während `description` sich generell auf die *Pfadoperation* bezieht. /// -/// check | Testen +/// tip | Tipp OpenAPI verlangt, dass jede *Pfadoperation* über eine Beschreibung der Response verfügt. @@ -104,4 +104,4 @@ Vergleichen Sie, wie deprecatete und nicht-deprecatete *Pfadoperationen* aussehe ## Zusammenfassung { #recap } -Sie können auf einfache Weise Metadaten für Ihre *Pfadoperationen* definieren, indem Sie den *Pfadoperation-Dekoratoren* Parameter hinzufügen. +Sie können Ihre *Pfadoperationen* einfach konfigurieren und Metadaten hinzufügen, indem Sie den *Pfadoperation-Dekoratoren* Parameter übergeben. diff --git a/docs/de/docs/tutorial/path-params-numeric-validations.md b/docs/de/docs/tutorial/path-params-numeric-validations.md index 76c782c52..59464ac8f 100644 --- a/docs/de/docs/tutorial/path-params-numeric-validations.md +++ b/docs/de/docs/tutorial/path-params-numeric-validations.md @@ -8,7 +8,7 @@ Importieren Sie zuerst `Path` von `fastapi`, und importieren Sie `Annotated`: {* ../../docs_src/path_params_numeric_validations/tutorial001_an_py310.py hl[1,3] *} -/// info | Info +/// note | Hinweis FastAPI hat in Version 0.95.0 Unterstützung für `Annotated` hinzugefügt und es zur Verwendung empfohlen. @@ -131,7 +131,7 @@ Und Sie können auch Zahlenvalidierungen deklarieren: * `lt`: `l`ess `t`han (kleiner als) * `le`: `l`ess than or `e`qual (kleiner oder gleich) -/// info | Info +/// note | Hinweis `Query`, `Path`, und andere Klassen, die Sie später sehen werden, sind Unterklassen einer gemeinsamen `Param`-Klasse. diff --git a/docs/de/docs/tutorial/path-params.md b/docs/de/docs/tutorial/path-params.md index 0e0a3bdbd..d462a7407 100644 --- a/docs/de/docs/tutorial/path-params.md +++ b/docs/de/docs/tutorial/path-params.md @@ -20,7 +20,7 @@ Sie können den Typ eines Pfad-Parameters in der Argumentliste der Funktion dekl In diesem Fall wird `item_id` als `int` deklariert, also als Ganzzahl. -/// check | Testen +/// tip | Tipp Dadurch erhalten Sie Editor-Unterstützung innerhalb Ihrer Funktion, mit Fehlerprüfungen, Codevervollständigung, usw. @@ -34,7 +34,7 @@ Wenn Sie dieses Beispiel ausführen und Ihren Browser unter [http://127.0.0.1:80 {"item_id":3} ``` -/// check | Testen +/// tip | Tipp Beachten Sie, dass der Wert, den Ihre Funktion erhält und zurückgibt, die Zahl `3` ist, also ein `int`. Nicht der String „3“, also ein `str`. @@ -66,7 +66,7 @@ Der Pfad-Parameter `item_id` hatte den Wert „foo“, was kein `int` ist. Die gleiche Fehlermeldung würde angezeigt werden, wenn Sie ein `float` (also eine Kommazahl) statt eines `int`s übergeben würden, wie etwa in: [http://127.0.0.1:8000/items/4.2](http://127.0.0.1:8000/items/4.2) -/// check | Testen +/// tip | Tipp Sprich, mit der gleichen Python-Typdeklaration gibt Ihnen **FastAPI** Datenvalidierung. @@ -82,7 +82,7 @@ Wenn Sie die Seite [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs) in I -/// check | Testen +/// tip | Tipp Wiederum, mit dieser gleichen Python-Typdeklaration gibt Ihnen **FastAPI** eine automatische, interaktive Dokumentation (verwendet die Swagger-Benutzeroberfläche). diff --git a/docs/de/docs/tutorial/query-params-str-validations.md b/docs/de/docs/tutorial/query-params-str-validations.md index ed277456e..bec5f574a 100644 --- a/docs/de/docs/tutorial/query-params-str-validations.md +++ b/docs/de/docs/tutorial/query-params-str-validations.md @@ -29,7 +29,7 @@ Um dies zu erreichen, importieren Sie zuerst: {* ../../docs_src/query_params_str_validations/tutorial002_an_py310.py hl[1,3] *} -/// info | Info +/// note | Hinweis FastAPI hat Unterstützung für `Annotated` hinzugefügt (und begonnen, es zu empfehlen) in der Version 0.95.0. @@ -81,7 +81,7 @@ FastAPI wird nun: * Die Daten **validieren**, um sicherzustellen, dass die Länge maximal 50 Zeichen beträgt * Einen **klaren Fehler** für den Client anzeigen, wenn die Daten ungültig sind -* Den Parameter in der OpenAPI-Schema-*Pfadoperation* **dokumentieren** (sodass er in der **automatischen Dokumentation** angezeigt wird) +* Den Parameter in der OpenAPI-Schema-*Pfadoperation* **dokumentieren** (sodass er in der **automatischen Dokumentationsoberfläche** angezeigt wird) ## Alternative (alt): `Query` als Defaultwert { #alternative-old-query-as-the-default-value } @@ -179,7 +179,7 @@ Dieses spezielle Suchmuster im regulären Ausdruck überprüft, dass der erhalte Wenn Sie sich mit all diesen **„regulärer Ausdruck“**-Ideen verloren fühlen, keine Sorge. Sie sind ein schwieriges Thema für viele Menschen. Sie können noch viele Dinge tun, ohne reguläre Ausdrücke direkt zu benötigen. -Aber nun wissen Sie, dass Sie sie in **FastAPI** immer dann verwenden können, wenn Sie sie brauchen. +Nun wissen Sie, dass Sie sie in **FastAPI** immer dann verwenden können, wenn Sie sie brauchen. ## Defaultwerte { #default-values } @@ -276,7 +276,7 @@ Wenn Sie zu: http://localhost:8000/items/ ``` -gehen, wird der Default für `q` sein: `["foo", "bar"]`, und Ihre Response wird sein: +gehen, wird der Defaultwert für `q` sein: `["foo", "bar"]`, und Ihre Response wird sein: ```JSON { @@ -311,7 +311,7 @@ Diese Informationen werden in das generierte OpenAPI aufgenommen und von den Dok Beachten Sie, dass verschiedene Tools möglicherweise unterschiedliche Unterstützungslevels für OpenAPI haben. -Einige davon könnten noch nicht alle zusätzlichen Informationen anzuzeigen, die Sie erklärten, obwohl in den meisten Fällen die fehlende Funktionalität bereits in der Entwicklung geplant ist. +Einige davon könnten noch nicht alle zusätzlichen Informationen anzeigen, die Sie deklariert haben, obwohl in den meisten Fällen die fehlende Funktionalität bereits in der Entwicklung geplant ist. /// @@ -335,7 +335,7 @@ http://127.0.0.1:8000/items/?item-query=foobaritems Aber `item-query` ist kein gültiger Name für eine Variable in Python. -Der am ähnlichsten wäre `item_query`. +Am ähnlichsten wäre `item_query`. Aber Sie benötigen dennoch, dass er genau `item-query` ist ... @@ -347,7 +347,7 @@ Dann können Sie ein `alias` deklarieren, und dieser Alias wird verwendet, um de Nehmen wir an, Ihnen gefällt dieser Parameter nicht mehr. -Sie müssen ihn eine Weile dort belassen, da es Clients gibt, die ihn verwenden, aber Sie möchten, dass die Dokumentation ihn klar als deprecatet anzeigt. +Sie müssen ihn eine Weile dort belassen, da es Clients gibt, die ihn verwenden, aber Sie möchten, dass die Dokumentation ihn klar als deprecatet anzeigt. Dann übergeben Sie den Parameter `deprecated=True` an `Query`: @@ -381,7 +381,7 @@ Zum Beispiel überprüft dieser benutzerdefinierte Validator, ob die Artikel-ID {* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py hl[5,16:19,24] *} -/// info | Info +/// note | Hinweis Dies ist verfügbar seit Pydantic Version 2 oder höher. 😎 @@ -395,7 +395,7 @@ Diese benutzerdefinierten Validatoren sind für Dinge gedacht, die einfach mit d /// -### Dieses Codebeispiel verstehen { #understand-that-code } +### Diesen Code verstehen { #understand-that-code } Der wichtige Punkt ist einfach die Verwendung von **`AfterValidator` mit einer Funktion innerhalb von `Annotated`**. Fühlen Sie sich frei, diesen Teil zu überspringen. 🤸 @@ -403,9 +403,9 @@ Der wichtige Punkt ist einfach die Verwendung von **`AfterValidator` mit einer F Aber wenn Sie neugierig auf dieses spezielle Codebeispiel sind und immer noch Spaß haben, hier sind einige zusätzliche Details. -#### Zeichenkette mit `value.startswith()` { #string-with-value-startswith } +#### String mit `value.startswith()` { #string-with-value-startswith } -Haben Sie bemerkt? Eine Zeichenkette mit `value.startswith()` kann ein Tuple übernehmen, und es wird jeden Wert im Tuple überprüfen: +Haben Sie bemerkt? Ein String mit `value.startswith()` kann ein Tuple übernehmen, und es wird jeden Wert im Tuple überprüfen: {* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py ln[16:19] hl[17] *} diff --git a/docs/de/docs/tutorial/query-params.md b/docs/de/docs/tutorial/query-params.md index 56aca4c2e..86ec9f4ab 100644 --- a/docs/de/docs/tutorial/query-params.md +++ b/docs/de/docs/tutorial/query-params.md @@ -23,7 +23,7 @@ Aber wenn Sie sie mit Python-Typen deklarieren (im obigen Beispiel als `int`), w Die gleichen Prozesse, die für Pfad-Parameter gelten, werden auch auf Query-Parameter angewendet: -* Editor Unterstützung (natürlich) +* Editor-Unterstützung (natürlich) * Daten-„Parsen“ * Datenvalidierung * Automatische Dokumentation @@ -65,19 +65,19 @@ Auf die gleiche Weise können Sie optionale Query-Parameter deklarieren, indem S In diesem Fall wird der Funktionsparameter `q` optional und standardmäßig `None` sein. -/// check | Testen +/// tip | Tipp -Beachten Sie auch, dass **FastAPI** intelligent genug ist, um zu erkennen, dass `item_id` ein Pfad-Parameter ist und `q` keiner, daher muss letzteres ein Query-Parameter sein. +Beachten Sie auch, dass **FastAPI** intelligent genug ist, um zu erkennen, dass der Pfad-Parameter `item_id` ein Pfad-Parameter ist und `q` keiner, daher muss letzteres ein Query-Parameter sein. /// -## Query-Parameter Typkonvertierung { #query-parameter-type-conversion } +## Typkonvertierung von Query-Parametern { #query-parameter-type-conversion } Sie können auch `bool`-Typen deklarieren, und sie werden konvertiert: {* ../../docs_src/query_params/tutorial003_py310.py hl[7] *} -Wenn Sie nun zu: +Wenn Sie in diesem Fall zu: ``` http://127.0.0.1:8000/items/foo?short=1 @@ -109,6 +109,7 @@ http://127.0.0.1:8000/items/foo?short=yes gehen, oder zu irgendeiner anderen Variante der Groß-/Kleinschreibung (Alles groß, Anfangsbuchstabe groß, usw.), dann wird Ihre Funktion den Parameter `short` mit dem `bool`-Wert `True` sehen, ansonsten mit dem Wert `False`. + ## Mehrere Pfad- und Query-Parameter { #multiple-path-and-query-parameters } Sie können mehrere Pfad-Parameter und Query-Parameter gleichzeitig deklarieren, **FastAPI** weiß, welches welcher ist. @@ -121,7 +122,7 @@ Parameter werden anhand ihres Namens erkannt: ## Erforderliche Query-Parameter { #required-query-parameters } -Wenn Sie einen Defaultwert für Nicht-Pfad-Parameter deklarieren (Bis jetzt haben wir nur Query-Parameter gesehen), dann ist der Parameter nicht erforderlich. +Wenn Sie einen Defaultwert für Nicht-Pfad-Parameter deklarieren (bis jetzt haben wir nur Query-Parameter gesehen), dann ist der Parameter nicht erforderlich. Wenn Sie keinen spezifischen Wert haben wollen, sondern der Parameter einfach optional sein soll, dann setzen Sie den Defaultwert auf `None`. @@ -129,7 +130,7 @@ Aber wenn Sie wollen, dass ein Query-Parameter erforderlich ist, vergeben Sie ei {* ../../docs_src/query_params/tutorial005_py310.py hl[6:7] *} -Hier ist `needy` ein erforderlicher Query-Parameter vom Typ `str`. +Hier ist der Query-Parameter `needy` ein erforderlicher Query-Parameter vom Typ `str`. Wenn Sie in Ihrem Browser eine URL wie: @@ -137,7 +138,7 @@ Wenn Sie in Ihrem Browser eine URL wie: http://127.0.0.1:8000/items/foo-item ``` -... öffnen, ohne den benötigten Parameter `needy`, dann erhalten Sie einen Fehler wie den folgenden: +... öffnen, ohne den erforderlichen Parameter `needy` hinzuzufügen, dann erhalten Sie einen Fehler wie den folgenden: ```JSON { @@ -161,7 +162,7 @@ Da `needy` ein erforderlicher Parameter ist, müssen Sie ihn in der URL setzen: http://127.0.0.1:8000/items/foo-item?needy=sooooneedy ``` -... Das funktioniert: +... das funktioniert: ```JSON { @@ -174,7 +175,7 @@ Und natürlich können Sie einige Parameter als erforderlich, einige mit Default {* ../../docs_src/query_params/tutorial006_py310.py hl[8] *} -In diesem Fall gibt es drei Query-Parameter: +In diesem Fall gibt es 3 Query-Parameter: * `needy`, ein erforderlicher `str`. * `skip`, ein `int` mit einem Defaultwert `0`. diff --git a/docs/de/docs/tutorial/request-files.md b/docs/de/docs/tutorial/request-files.md index a4c1318ef..7a344604a 100644 --- a/docs/de/docs/tutorial/request-files.md +++ b/docs/de/docs/tutorial/request-files.md @@ -2,7 +2,7 @@ Sie können Dateien, die vom Client hochgeladen werden, mithilfe von `File` definieren. -/// info | Info +/// note | Hinweis Um hochgeladene Dateien zu empfangen, installieren Sie zuerst [`python-multipart`](https://github.com/Kludex/python-multipart). @@ -24,11 +24,11 @@ Importieren Sie `File` und `UploadFile` von `fastapi`: ## `File`-Parameter definieren { #define-file-parameters } -Erstellen Sie Datei-Parameter, so wie Sie es auch mit `Body` und `Form` machen würden: +Erstellen Sie Datei-Parameter, so wie Sie es auch mit `Body` oder `Form` machen würden: {* ../../docs_src/request_files/tutorial001_an_py310.py hl[9] *} -/// info | Info +/// note | Hinweis `File` ist eine Klasse, die direkt von `Form` erbt. @@ -44,7 +44,7 @@ Um Dateibodys zu deklarieren, müssen Sie `File` verwenden, da diese Parameter s Die Dateien werden als „Formulardaten“ hochgeladen. -Wenn Sie den Typ Ihrer *Pfadoperation-Funktion* als `bytes` deklarieren, wird **FastAPI** die Datei für Sie auslesen, und Sie erhalten den Inhalt als `bytes`. +Wenn Sie den Typ des Parameters Ihrer *Pfadoperation-Funktion* als `bytes` deklarieren, wird **FastAPI** die Datei für Sie auslesen, und Sie erhalten den Inhalt als `bytes`. Bedenken Sie, dass das bedeutet, dass sich der gesamte Inhalt der Datei im Arbeitsspeicher befindet. Das wird für kleinere Dateien gut funktionieren. @@ -63,27 +63,27 @@ Definieren Sie einen Datei-Parameter mit dem Typ `UploadFile`: * Eine Datei, die bis zu einem bestimmten Größen-Limit im Arbeitsspeicher behalten wird, und wenn das Limit überschritten wird, auf der Festplatte gespeichert wird. * Das bedeutet, es wird für große Dateien wie Bilder, Videos, große Binärdateien, usw. gut funktionieren, ohne den ganzen Arbeitsspeicher aufzubrauchen. * Sie können Metadaten aus der hochgeladenen Datei auslesen. -* Es hat eine [dateiartige](https://docs.python.org/3/glossary.html#term-file-like-object) `async`hrone Schnittstelle. +* Es hat eine [dateiartige](https://docs.python.org/3/glossary.html#term-file-like-object) `async`-Schnittstelle. * Es stellt ein tatsächliches Python-[`SpooledTemporaryFile`](https://docs.python.org/3/library/tempfile.html#tempfile.SpooledTemporaryFile)-Objekt bereit, welches Sie direkt anderen Bibliotheken übergeben können, die ein dateiartiges Objekt erwarten. ### `UploadFile` { #uploadfile } `UploadFile` hat die folgenden Attribute: -* `filename`: Ein `str` mit dem ursprünglichen Namen der hochgeladenen Datei (z. B. `meinbild.jpg`). +* `filename`: Ein `str` mit dem ursprünglichen Namen der hochgeladenen Datei (z. B. `myimage.jpg`). * `content_type`: Ein `str` mit dem Inhaltstyp (MIME-Typ / Medientyp) (z. B. `image/jpeg`). -* `file`: Ein [`SpooledTemporaryFile`](https://docs.python.org/3/library/tempfile.html#tempfile.SpooledTemporaryFile) (ein [dateiartiges](https://docs.python.org/3/glossary.html#term-file-like-object) Objekt). Das ist das tatsächliche Python-Objekt, das Sie direkt anderen Funktionen oder Bibliotheken übergeben können, welche ein „file-like“-Objekt erwarten. +* `file`: Ein [`SpooledTemporaryFile`](https://docs.python.org/3/library/tempfile.html#tempfile.SpooledTemporaryFile) (ein [dateiartiges](https://docs.python.org/3/glossary.html#term-file-like-object) Objekt). Das ist das tatsächliche Python-Dateiobjekt, das Sie direkt anderen Funktionen oder Bibliotheken übergeben können, welche ein „file-like“-Objekt erwarten. -`UploadFile` hat die folgenden `async`hronen Methoden. Sie alle rufen die entsprechenden Methoden des darunterliegenden Datei-Objekts auf (wobei intern `SpooledTemporaryFile` verwendet wird). +`UploadFile` hat die folgenden `async`-Methoden. Sie alle rufen die entsprechenden Methoden des darunterliegenden Datei-Objekts auf (wobei intern `SpooledTemporaryFile` verwendet wird). -* `write(daten)`: Schreibt `daten` (`str` oder `bytes`) in die Datei. -* `read(anzahl)`: Liest `anzahl` (`int`) bytes/Zeichen aus der Datei. -* `seek(versatz)`: Geht zur Position `versatz` (`int`) in der Datei. +* `write(data)`: Schreibt `data` (`str` oder `bytes`) in die Datei. +* `read(size)`: Liest `size` (`int`) Bytes/Zeichen aus der Datei. +* `seek(offset)`: Geht zur Byte-Position `offset` (`int`) in der Datei. * z. B. würde `await myfile.seek(0)` zum Anfang der Datei gehen. * Das ist besonders dann nützlich, wenn Sie `await myfile.read()` einmal ausführen und dann diese Inhalte erneut auslesen müssen. * `close()`: Schließt die Datei. -Da alle diese Methoden `async`hron sind, müssen Sie sie „await“en („erwarten“). +Da alle diese Methoden `async`-Methoden sind, müssen Sie sie „await“en („erwarten“). Zum Beispiel können Sie innerhalb einer `async` *Pfadoperation-Funktion* den Inhalt wie folgt auslesen: @@ -105,7 +105,7 @@ Wenn Sie die `async`-Methoden verwenden, führt **FastAPI** die Datei-Methoden i /// note | Technische Details zu Starlette -FastAPIs `UploadFile` erbt direkt von Starlettes `UploadFile`, fügt aber ein paar notwendige Teile hinzu, um es kompatibel mit **Pydantic** und anderen Teilen von FastAPI zu machen. +**FastAPI**s `UploadFile` erbt direkt von **Starlette**s `UploadFile`, fügt aber ein paar notwendige Teile hinzu, um es kompatibel mit **Pydantic** und anderen Teilen von FastAPI zu machen. /// @@ -113,15 +113,15 @@ FastAPIs `UploadFile` erbt direkt von Starlettes `UploadFile`, fügt aber ein pa Der Weg, wie HTML-Formulare (`
`) die Daten zum Server senden, verwendet normalerweise eine „spezielle“ Kodierung für diese Daten. Diese unterscheidet sich von JSON. -**FastAPI** stellt sicher, dass diese Daten korrekt ausgelesen werden, statt JSON zu erwarten. +**FastAPI** stellt sicher, dass diese Daten von der richtigen Stelle ausgelesen werden, statt JSON zu erwarten. /// note | Technische Details -Daten aus Formularen werden, wenn es keine Dateien sind, normalerweise mit dem „media type“ `application/x-www-form-urlencoded` kodiert. +Daten aus Formularen werden, wenn sie keine Dateien enthalten, normalerweise mit dem „media type“ `application/x-www-form-urlencoded` kodiert. Sollte das Formular aber Dateien enthalten, dann werden diese mit `multipart/form-data` kodiert. Wenn Sie `File` verwenden, wird **FastAPI** wissen, dass es die Dateien vom korrekten Teil des Bodys holen muss. -Wenn Sie mehr über diese Kodierungen und Formularfelder lesen möchten, besuchen Sie die [MDN-Webdokumentation für `POST`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST). +Wenn Sie mehr über diese Kodierungen und Formularfelder lesen möchten, besuchen Sie die [MDN-Webdokumentation für `POST`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST). /// @@ -149,7 +149,7 @@ Sie können auch `File()` mit `UploadFile` verwenden, um zum Beispiel zusätzlic Es ist auch möglich, mehrere Dateien gleichzeitig hochzuladen. -Diese werden demselben Formularfeld zugeordnet, welches mit den Formulardaten gesendet wird. +Diese werden demselben „Formularfeld“ zugeordnet, welches mittels „Formulardaten“ gesendet wird. Um das zu machen, deklarieren Sie eine Liste von `bytes` oder `UploadFile`s: diff --git a/docs/de/docs/tutorial/request-form-models.md b/docs/de/docs/tutorial/request-form-models.md index f3ddaee81..b40d60d0b 100644 --- a/docs/de/docs/tutorial/request-form-models.md +++ b/docs/de/docs/tutorial/request-form-models.md @@ -2,7 +2,7 @@ Sie können **Pydantic-Modelle** verwenden, um **Formularfelder** in FastAPI zu deklarieren. -/// info | Info +/// note | Hinweis Um Formulare zu verwenden, installieren Sie zuerst [`python-multipart`](https://github.com/Kludex/python-multipart). diff --git a/docs/de/docs/tutorial/request-forms-and-files.md b/docs/de/docs/tutorial/request-forms-and-files.md index 8b4e85c0d..98e542851 100644 --- a/docs/de/docs/tutorial/request-forms-and-files.md +++ b/docs/de/docs/tutorial/request-forms-and-files.md @@ -2,7 +2,7 @@ Sie können gleichzeitig Dateien und Formulardaten mit `File` und `Form` definieren. -/// info | Info +/// note | Hinweis Um hochgeladene Dateien und/oder Formulardaten zu empfangen, installieren Sie zuerst [`python-multipart`](https://github.com/Kludex/python-multipart). diff --git a/docs/de/docs/tutorial/request-forms.md b/docs/de/docs/tutorial/request-forms.md index bc2578c01..aedcd4a51 100644 --- a/docs/de/docs/tutorial/request-forms.md +++ b/docs/de/docs/tutorial/request-forms.md @@ -1,8 +1,9 @@ # Formulardaten { #form-data } + Wenn Sie Felder aus Formularen statt JSON empfangen müssen, können Sie `Form` verwenden. -/// info | Info +/// note | Hinweis Um Formulare zu verwenden, installieren Sie zuerst [`python-multipart`](https://github.com/Kludex/python-multipart). @@ -22,7 +23,7 @@ Importieren Sie `Form` von `fastapi`: ## `Form`-Parameter definieren { #define-form-parameters } -Erstellen Sie Formular-Parameter, so wie Sie es auch mit `Body` und `Query` machen würden: +Erstellen Sie Formular-Parameter, so wie Sie es auch mit `Body` oder `Query` machen würden: {* ../../docs_src/request_forms/tutorial001_an_py310.py hl[9] *} @@ -32,7 +33,7 @@ Die Spezifikation erfordert, dass die Felder ex Mit `Form` haben Sie die gleichen Konfigurationsmöglichkeiten wie mit `Body` (und `Query`, `Path`, `Cookie`), inklusive Validierung, Beispielen, einem Alias (z. B. `user-name` statt `username`), usw. -/// info | Info +/// note | Hinweis `Form` ist eine Klasse, die direkt von `Body` erbt. @@ -56,7 +57,7 @@ Daten aus Formularen werden normalerweise mit dem „med Wenn das Formular stattdessen Dateien enthält, werden diese mit `multipart/form-data` kodiert. Im nächsten Kapitel erfahren Sie mehr über die Handhabung von Dateien. -Wenn Sie mehr über Formularfelder und ihre Kodierungen lesen möchten, besuchen Sie die [MDN-Webdokumentation für `POST`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST). +Wenn Sie mehr über Formularfelder und ihre Kodierungen lesen möchten, besuchen Sie die [MDN-Webdokumentation für `POST`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST). /// diff --git a/docs/de/docs/tutorial/response-model.md b/docs/de/docs/tutorial/response-model.md index 0aafda954..2b580bd6d 100644 --- a/docs/de/docs/tutorial/response-model.md +++ b/docs/de/docs/tutorial/response-model.md @@ -72,7 +72,7 @@ Im Folgenden deklarieren wir ein `UserIn`-Modell; es enthält ein Klartext-Passw {* ../../docs_src/response_model/tutorial002_py310.py hl[7,9] *} -/// info | Info +/// note | Hinweis Um `EmailStr` zu verwenden, installieren Sie zuerst [`email-validator`](https://github.com/JoshData/python-email-validator). @@ -251,7 +251,7 @@ Wenn Sie also den Artikel mit der ID `foo` bei der *Pfadoperation* anfragen, wir } ``` -/// info | Info +/// note | Hinweis Sie können auch: diff --git a/docs/de/docs/tutorial/response-status-code.md b/docs/de/docs/tutorial/response-status-code.md index a0018a13d..63962829d 100644 --- a/docs/de/docs/tutorial/response-status-code.md +++ b/docs/de/docs/tutorial/response-status-code.md @@ -1,5 +1,6 @@ # Response-Statuscode { #response-status-code } + Genauso wie Sie ein Responsemodell angeben können, können Sie auch den HTTP-Statuscode für die Response mit dem Parameter `status_code` in jeder der *Pfadoperationen* deklarieren: * `@app.get()` @@ -18,7 +19,7 @@ Beachten Sie, dass `status_code` ein Parameter der „Dekorator“-Methode ist ( Dem `status_code`-Parameter wird eine Zahl mit dem HTTP-Statuscode übergeben. -/// info | Info +/// note | Hinweis Alternativ kann `status_code` auch ein `IntEnum` erhalten, wie etwa Pythons [`http.HTTPStatus`](https://docs.python.org/3/library/http.html#http.HTTPStatus). diff --git a/docs/de/docs/tutorial/schema-extra-example.md b/docs/de/docs/tutorial/schema-extra-example.md index bdb67bd68..9bf0eafec 100644 --- a/docs/de/docs/tutorial/schema-extra-example.md +++ b/docs/de/docs/tutorial/schema-extra-example.md @@ -14,7 +14,7 @@ Diese zusätzlichen Informationen werden unverändert zum für dieses Modell aus Sie können das Attribut `model_config` verwenden, das ein `dict` akzeptiert, wie beschrieben in [Pydantic-Dokumentation: Configuration](https://docs.pydantic.dev/latest/api/config/). -Sie können `json_schema_extra` setzen, mit einem `dict`, das alle zusätzlichen Daten enthält, die im generierten JSON-Schema angezeigt werden sollen, einschließlich `examples`. +Sie können `"json_schema_extra"` setzen, mit einem `dict`, das alle zusätzlichen Daten enthält, die im generierten JSON-Schema angezeigt werden sollen, einschließlich `examples`. /// tip | Tipp @@ -24,7 +24,7 @@ Sie könnten das beispielsweise verwenden, um Metadaten für eine Frontend-Benut /// -/// info | Info +/// note | Hinweis OpenAPI 3.1.0 (verwendet seit FastAPI 0.99.0) hat Unterstützung für `examples` hinzugefügt, was Teil des **JSON Schema** Standards ist. @@ -88,7 +88,7 @@ Das Format dieses OpenAPI-spezifischen Felds `examples` ist ein `dict` mit **meh Dies erfolgt nicht innerhalb jedes in OpenAPI enthaltenen JSON-Schemas, sondern außerhalb, in der *Pfadoperation*. -### Verwendung des Parameters `openapi_examples` { #using-the-openapi-examples-parameter } +### Den Parameter `openapi_examples` verwenden { #using-the-openapi-examples-parameter } Sie können die OpenAPI-spezifischen `examples` in FastAPI mit dem Parameter `openapi_examples` deklarieren, für: @@ -155,7 +155,7 @@ OpenAPI fügte auch die Felder `example` und `examples` zu anderen Teilen der Sp * `File()` * `Form()` -/// info | Info +/// note | Hinweis Dieser alte, OpenAPI-spezifische `examples`-Parameter heißt seit FastAPI `0.103.0` jetzt `openapi_examples`. @@ -171,7 +171,7 @@ Und jetzt hat dieses neue `examples`-Feld Vorrang vor dem alten (und benutzerdef Dieses neue `examples`-Feld in JSON Schema ist **nur eine `list`** von Beispielen, kein Dict mit zusätzlichen Metadaten wie an den anderen Stellen in OpenAPI (oben beschrieben). -/// info | Info +/// note | Hinweis Selbst, nachdem OpenAPI 3.1.0 veröffentlicht wurde, mit dieser neuen, einfacheren Integration mit JSON Schema, unterstützte Swagger UI, das Tool, das die automatische Dokumentation bereitstellt, eine Zeit lang OpenAPI 3.1.0 nicht (das tut es seit Version 5.0.0 🎉). @@ -189,9 +189,9 @@ In Versionen von FastAPI vor 0.99.0 (0.99.0 und höher verwenden das neuere Open Aber jetzt, da FastAPI 0.99.0 und höher, OpenAPI 3.1.0 verwendet, das JSON Schema 2020-12 verwendet, und Swagger UI 5.0.0 und höher, ist alles konsistenter und die Beispiele sind in JSON Schema enthalten. -### Swagger-Benutzeroberfläche und OpenAPI-spezifische `examples` { #swagger-ui-and-openapi-specific-examples } +### Swagger UI und OpenAPI-spezifische `examples` { #swagger-ui-and-openapi-specific-examples } -Da die Swagger-Benutzeroberfläche derzeit nicht mehrere JSON Schema Beispiele unterstützt (Stand: 26.08.2023), hatten Benutzer keine Möglichkeit, mehrere Beispiele in der Dokumentation anzuzeigen. +Da Swagger UI derzeit nicht mehrere JSON Schema Beispiele unterstützt (Stand: 26.08.2023), hatten Benutzer keine Möglichkeit, mehrere Beispiele in der Dokumentation anzuzeigen. Um dieses Problem zu lösen, hat FastAPI `0.103.0` **Unterstützung** für die Deklaration desselben alten **OpenAPI-spezifischen** `examples`-Felds mit dem neuen Parameter `openapi_examples` hinzugefügt. 🤓 diff --git a/docs/de/docs/tutorial/security/first-steps.md b/docs/de/docs/tutorial/security/first-steps.md index 8a1d2fbf1..69e8abec0 100644 --- a/docs/de/docs/tutorial/security/first-steps.md +++ b/docs/de/docs/tutorial/security/first-steps.md @@ -1,5 +1,6 @@ # Sicherheit – Erste Schritte { #security-first-steps } + Stellen wir uns vor, dass Sie Ihre **Backend**-API auf einer Domain haben. Und Sie haben ein **Frontend** auf einer anderen Domain oder in einem anderen Pfad derselben Domain (oder in einer Mobile-Anwendung). @@ -24,7 +25,7 @@ Kopieren Sie das Beispiel in eine Datei `main.py`: ## Ausführen { #run-it } -/// info | Info +/// note | Hinweis Das Paket [`python-multipart`](https://github.com/Kludex/python-multipart) wird automatisch mit **FastAPI** installiert, wenn Sie den Befehl `pip install "fastapi[standard]"` ausführen. @@ -62,7 +63,7 @@ Sie werden etwa Folgendes sehen: -/// check | Authorize-Button! +/// tip | Authorize-Button! Sie haben bereits einen glänzenden, neuen „Authorize“-Button. @@ -120,7 +121,7 @@ Betrachten wir es also aus dieser vereinfachten Sicht: In diesem Beispiel verwenden wir **OAuth2** mit dem **Password**-Flow und einem **Bearer**-Token. Wir machen das mit der Klasse `OAuth2PasswordBearer`. -/// info | Info +/// note | Hinweis Ein „Bearer“-Token ist nicht die einzige Option. @@ -150,7 +151,7 @@ Dieser Parameter erstellt nicht diesen Endpunkt / diese *Pfadoperation*, sondern Wir werden demnächst auch die eigentliche Pfadoperation erstellen. -/// info | Info +/// note | Hinweis Wenn Sie ein sehr strenger „Pythonista“ sind, missfällt Ihnen möglicherweise die Schreibweise des Parameternamens `tokenUrl` anstelle von `token_url`. @@ -178,7 +179,7 @@ Diese Abhängigkeit stellt einen `str` bereit, der dem Parameter `token` der *Pf **FastAPI** weiß, dass es diese Abhängigkeit verwenden kann, um ein „Sicherheitsschema“ im OpenAPI-Schema (und der automatischen API-Dokumentation) zu definieren. -/// info | Technische Details +/// note | Technische Details **FastAPI** weiß, dass es die Klasse `OAuth2PasswordBearer` (deklariert in einer Abhängigkeit) verwenden kann, um das Sicherheitsschema in OpenAPI zu definieren, da es von `fastapi.security.oauth2.OAuth2` erbt, das wiederum von `fastapi.security.base.SecurityBase` erbt. diff --git a/docs/de/docs/tutorial/security/get-current-user.md b/docs/de/docs/tutorial/security/get-current-user.md index cfb59ff12..1bcccfd82 100644 --- a/docs/de/docs/tutorial/security/get-current-user.md +++ b/docs/de/docs/tutorial/security/get-current-user.md @@ -14,7 +14,7 @@ Erstellen wir zunächst ein Pydantic-Benutzermodell. So wie wir Pydantic zum Deklarieren von Bodys verwenden, können wir es auch überall sonst verwenden: -{* ../../docs_src/security/tutorial002_an_py310.py hl[5,12:6] *} +{* ../../docs_src/security/tutorial002_an_py310.py hl[5,12:16] *} ## Eine `get_current_user`-Abhängigkeit erstellen { #create-a-get-current-user-dependency } @@ -52,7 +52,7 @@ Weil Sie `Depends` verwenden, wird **FastAPI** hier aber nicht verwirrt. /// -/// check | Testen +/// tip | Tipp Die Art und Weise, wie dieses System von Abhängigkeiten konzipiert ist, ermöglicht es uns, verschiedene Abhängigkeiten (verschiedene „Dependables“) zu haben, die alle ein `User`-Modell zurückgeben. diff --git a/docs/de/docs/tutorial/security/oauth2-jwt.md b/docs/de/docs/tutorial/security/oauth2-jwt.md index 2f727b167..d04bd00d4 100644 --- a/docs/de/docs/tutorial/security/oauth2-jwt.md +++ b/docs/de/docs/tutorial/security/oauth2-jwt.md @@ -4,7 +4,7 @@ Da wir nun über den gesamten Sicherheitsablauf verfügen, machen wir die Anwend Diesen Code können Sie tatsächlich in Ihrer Anwendung verwenden, die Passwort-Hashes in Ihrer Datenbank speichern, usw. -Wir bauen auf dem vorherigen Kapitel auf. +Wir bauen auf dem vorherigen Kapitel auf und erweitern es. ## Über JWT { #about-jwt } @@ -42,7 +42,7 @@ $ pip install pyjwt -/// info | Info +/// note | Hinweis Wenn Sie planen, digitale Signaturalgorithmen wie RSA oder ECDSA zu verwenden, sollten Sie die Kryptografie-Abhängigkeit `pyjwt[crypto]` installieren. @@ -120,7 +120,7 @@ Und noch eine, um einen Benutzer zu authentifizieren und zurückzugeben. Wenn `authenticate_user` mit einem Benutzernamen aufgerufen wird, der in der Datenbank nicht existiert, führen wir dennoch `verify_password` gegen einen Dummy-Hash aus. -So stellt man sicher, dass der Endpunkt ungefähr gleich viel Zeit für die Antwort benötigt, unabhängig davon, ob der Benutzername gültig ist oder nicht. Dadurch werden Timing-Angriffe verhindert, mit denen vorhandene Benutzernamen ermittelt werden könnten. +So stellt man sicher, dass der Endpunkt ungefähr gleich viel Zeit für die Antwort benötigt, unabhängig davon, ob der Benutzername gültig ist oder nicht. Dadurch werden **Timing-Angriffe** verhindert, mit denen vorhandene Benutzernamen ermittelt werden könnten. /// note | Hinweis @@ -168,7 +168,7 @@ Wenn der Token ungültig ist, geben Sie sofort einen HTTP-Fehler zurück. {* ../../docs_src/security/tutorial004_an_py310.py hl[93:110] *} -## Die *Pfadoperation* `/token` aktualisieren { #update-the-token-path-operation } +## Die `/token`-*Pfadoperation* aktualisieren { #update-the-token-path-operation } Erstellen Sie ein `timedelta` mit der Ablaufzeit des Tokens. @@ -213,7 +213,7 @@ Verwenden Sie die Anmeldeinformationen: Benutzername: `johndoe` Passwort: `secret` -/// check | Testen +/// tip | Tipp Beachten Sie, dass im Code nirgendwo das Klartext-Passwort „`secret`“ steht, wir haben nur die gehashte Version. diff --git a/docs/de/docs/tutorial/security/simple-oauth2.md b/docs/de/docs/tutorial/security/simple-oauth2.md index 32720706e..b7b041bc1 100644 --- a/docs/de/docs/tutorial/security/simple-oauth2.md +++ b/docs/de/docs/tutorial/security/simple-oauth2.md @@ -20,7 +20,7 @@ Die Spezifikation besagt auch, dass `username` und `password` als Formulardaten ### `scope` { #scope } -Ferner sagt die Spezifikation, dass der Client ein weiteres Formularfeld "`scope`" („Geltungsbereich“) senden kann. +Ferner sagt die Spezifikation, dass der Client ein weiteres Formularfeld „`scope`“ senden kann. Der Name des Formularfelds lautet `scope` (im Singular), tatsächlich handelt es sich jedoch um einen langen String mit durch Leerzeichen getrennten „Scopes“. @@ -32,7 +32,7 @@ Diese werden normalerweise verwendet, um bestimmte Sicherheitsberechtigungen zu * `instagram_basic` wird von Facebook / Instagram verwendet. * `https://www.googleapis.com/auth/drive` wird von Google verwendet. -/// info | Info +/// note | Hinweis In OAuth2 ist ein „Scope“ nur ein String, der eine bestimmte erforderliche Berechtigung deklariert. @@ -72,7 +72,7 @@ Wenn Sie es erzwingen müssen, verwenden Sie `OAuth2PasswordRequestFormStrict` a * Eine optionale `client_id` (benötigen wir für unser Beispiel nicht). * Ein optionales `client_secret` (benötigen wir für unser Beispiel nicht). -/// info | Info +/// note | Hinweis `OAuth2PasswordRequestForm` ist keine spezielle Klasse für **FastAPI**, so wie `OAuth2PasswordBearer`. @@ -120,7 +120,7 @@ Immer wenn Sie genau den gleichen Inhalt (genau das gleiche Passwort) übergeben Sie können jedoch nicht vom Kauderwelsch zurück zum Passwort konvertieren. -##### Warum Passwort-Hashing verwenden? { #why-use-password-hashing } +##### Warum Passwort-Hashing verwenden { #why-use-password-hashing } Wenn Ihre Datenbank gestohlen wird, hat der Dieb nicht die Klartext-Passwörter Ihrer Benutzer, sondern nur die Hashes. @@ -144,9 +144,9 @@ UserInDB( ) ``` -/// info | Info +/// note | Hinweis -Eine ausführlichere Erklärung von `**user_dict` finden Sie in [der Dokumentation für **Extra Modelle**](../extra-models.md#about-user-in-dict). +Eine ausführlichere Erklärung von `**user_dict` finden Sie in [der Dokumentation für **Extra Modelle**](../extra-models.md#about-user-in-model-dump). /// @@ -196,7 +196,7 @@ In unserem Endpunkt erhalten wir also nur dann einen Benutzer, wenn der Benutzer {* ../../docs_src/security/tutorial003_an_py310.py hl[58:66,69:74,94] *} -/// info | Info +/// note | Hinweis Der zusätzliche Header `WWW-Authenticate` mit dem Wert `Bearer`, den wir hier zurückgeben, ist ebenfalls Teil der Spezifikation. @@ -226,7 +226,7 @@ Verwenden Sie die Anmeldedaten: Benutzer: `johndoe` -Passwort: `secret`. +Passwort: `secret` @@ -264,9 +264,9 @@ Wenn Sie auf das Schlosssymbol klicken und sich abmelden und dann den gleichen V Versuchen Sie es nun mit einem inaktiven Benutzer und authentisieren Sie sich mit: -Benutzer: `alice`. +Benutzer: `alice` -Passwort: `secret2`. +Passwort: `secret2` Und versuchen Sie, die Operation `GET` mit dem Pfad `/users/me` zu verwenden. diff --git a/docs/de/docs/tutorial/server-sent-events.md b/docs/de/docs/tutorial/server-sent-events.md index f465c1131..8e6f35c71 100644 --- a/docs/de/docs/tutorial/server-sent-events.md +++ b/docs/de/docs/tutorial/server-sent-events.md @@ -2,9 +2,9 @@ Sie können Daten mithilfe von **Server-Sent Events** (SSE) an den Client streamen. -Das ist ähnlich wie [JSON Lines streamen](stream-json-lines.md), verwendet aber das Format `text/event-stream`, das von Browsern nativ mit der [die `EventSource`-API](https://developer.mozilla.org/en-US/docs/Web/API/EventSource) unterstützt wird. +Das ist ähnlich wie [JSON Lines streamen](stream-json-lines.md), verwendet aber das Format `text/event-stream`, das von Browsern nativ mit der [`EventSource`-API](https://developer.mozilla.org/en-US/docs/Web/API/EventSource) unterstützt wird. -/// info | Info +/// note | Hinweis Hinzugefügt in FastAPI 0.135.0. @@ -29,7 +29,7 @@ SSE wird häufig für KI-Chat-Streaming, Live-Benachrichtigungen, Logs und Obser /// tip | Tipp -Wenn Sie Binärdaten streamen wollen, z. B. Video oder Audio, sehen Sie im fortgeschrittenen Handbuch nach: [Daten streamen](../advanced/stream-data.md). +Wenn Sie Binärdaten streamen wollen, z. B. Video oder Audio, sehen Sie im Handbuch für fortgeschrittene Benutzer nach: [Daten streamen](../advanced/stream-data.md). /// @@ -103,7 +103,7 @@ Sie können ihn als Header-Parameter einlesen und verwenden, um den Stream dort ## SSE mit POST { #sse-with-post } -SSE funktioniert mit **jedem HTTP-Method**, nicht nur mit `GET`. +SSE funktioniert mit **jeder HTTP-Methode**, nicht nur mit `GET`. Das ist nützlich für Protokolle wie [MCP](https://modelcontextprotocol.io), die SSE über `POST` streamen: @@ -113,7 +113,7 @@ Das ist nützlich für Protokolle wie [MCP](https://modelcontextprotocol.io), di FastAPI implementiert einige bewährte SSE-Praktiken direkt out of the box. -- Alle 15 Sekunden, wenn keine Nachricht gesendet wurde, einen **„keep alive“-`ping`-Kommentar** senden, um zu verhindern, dass einige Proxys die Verbindung schließen, wie in der [HTML-Spezifikation: Server-Sent Events](https://html.spec.whatwg.org/multipage/server-sent-events.html#authoring-notes) vorgeschlagen. +- Einen **„keep alive“-`ping`-Kommentar** alle 15 Sekunden senden, wenn keine Nachricht gesendet wurde, um zu verhindern, dass einige Proxys die Verbindung schließen, wie in der [HTML-Spezifikation: Server-Sent Events](https://html.spec.whatwg.org/multipage/server-sent-events.html#authoring-notes) vorgeschlagen. - Den Header `Cache-Control: no-cache` setzen, um **Caching** des Streams zu verhindern. - Einen speziellen Header `X-Accel-Buffering: no` setzen, um **Buffering** in einigen Proxys wie Nginx zu verhindern. diff --git a/docs/de/docs/tutorial/sql-databases.md b/docs/de/docs/tutorial/sql-databases.md index d7988f9a2..3c7aabae3 100644 --- a/docs/de/docs/tutorial/sql-databases.md +++ b/docs/de/docs/tutorial/sql-databases.md @@ -8,7 +8,7 @@ Hier werden wir ein Beispiel mit [SQLModel](https://sqlmodel.tiangolo.com/) sehe /// tip | Tipp -Sie könnten jede andere SQL- oder NoSQL-Datenbankbibliothek verwenden, die Sie möchten (in einigen Fällen als „ORMs“ bezeichnet), FastAPI zwingt Sie nicht, irgendetwas zu verwenden. 😎 +Sie könnten jede andere SQL- oder NoSQL-Datenbankbibliothek verwenden, die Sie möchten (in einigen Fällen als „ORMs“ bezeichnet), FastAPI zwingt Sie nicht, irgendetwas zu verwenden. 😎 /// @@ -121,7 +121,7 @@ Da jedes SQLModel-Modell auch ein Pydantic-Modell ist, können Sie es in denselb Wenn Sie beispielsweise einen Parameter vom Typ `Hero` deklarieren, wird er aus dem **JSON-Body** gelesen. -Auf die gleiche Weise können Sie es als **Rückgabetyp** der Funktion deklarieren, und dann wird die Form der Daten in der automatischen API-Dokumentation angezeigt. +Auf die gleiche Weise können Sie es als **Rückgabetyp** der Funktion deklarieren, und dann wird die Form der Daten in der automatischen API-Dokumentations-UI angezeigt. {* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[40:45] hl[40:45] *} @@ -266,7 +266,7 @@ In der vorherigen Version der App hatten wir keine Möglichkeit, einen Helden ** Das `HeroUpdate`-*Datenmodell* ist etwas Besonderes, es hat **die selben Felder**, die benötigt werden, um einen neuen Helden zu erstellen, aber alle Felder sind **optional** (sie haben alle einen Defaultwert). Auf diese Weise, wenn Sie einen Helden aktualisieren, können Sie nur die Felder senden, die Sie aktualisieren möchten. -Da sich tatsächlich **alle Felder ändern** (der Typ enthält jetzt `None` und sie haben jetzt einen Standardwert von `None`), müssen wir sie erneut **deklarieren**. +Da sich tatsächlich **alle Felder ändern** (der Typ enthält jetzt `None` und sie haben jetzt einen Defaultwert von `None`), müssen wir sie erneut **deklarieren**. Wir müssen wirklich nicht von `HeroBase` erben, weil wir alle Felder neu deklarieren. Ich lasse es aus Konsistenzgründen erben, aber das ist nicht notwendig. Es ist mehr eine Frage des persönlichen Geschmacks. 🤷 diff --git a/docs/de/docs/tutorial/static-files.md b/docs/de/docs/tutorial/static-files.md index 8fb4c1908..ef75ca91a 100644 --- a/docs/de/docs/tutorial/static-files.md +++ b/docs/de/docs/tutorial/static-files.md @@ -2,6 +2,14 @@ Mit `StaticFiles` können Sie statische Dateien aus einem Verzeichnis automatisch bereitstellen. +/// tip | Tipp + +Wenn Sie ein Frontend hosten müssen, verwenden Sie stattdessen `app.frontend()`; lesen Sie mehr dazu unter [Frontend](frontend.md). + +`app.frontend()` verwendet darunter `StaticFiles`, mit mehreren zusätzlichen Vorteilen für Frontends, wie der Handhabung von clientseitigem Routing. + +/// + ## `StaticFiles` verwenden { #use-staticfiles } * Importieren Sie `StaticFiles`. diff --git a/docs/de/docs/tutorial/stream-json-lines.md b/docs/de/docs/tutorial/stream-json-lines.md index 3625853b5..61bf3fafa 100644 --- a/docs/de/docs/tutorial/stream-json-lines.md +++ b/docs/de/docs/tutorial/stream-json-lines.md @@ -2,7 +2,7 @@ Sie könnten eine Folge von Daten haben, die Sie in einem „Stream“ senden möchten, das können Sie mit **JSON Lines** tun. -/// info | Info +/// note | Hinweis Hinzugefügt in FastAPI 0.134.0. @@ -48,7 +48,7 @@ Eine Response hätte einen Content-Type von `application/jsonl` (anstelle von `a Es ist einem JSON-Array (entspricht einer Python-Liste) sehr ähnlich, aber anstatt in `[]` eingeschlossen zu sein und `,` zwischen den Elementen zu haben, gibt es hier **ein JSON-Objekt pro Zeile**, sie sind durch ein Zeilenumbruchzeichen getrennt. -/// info | Info +/// note | Hinweis Der wichtige Punkt ist, dass Ihre App in der Lage ist, jede Zeile der Reihe nach zu erzeugen, während der Client die vorherigen Zeilen konsumiert. diff --git a/docs/de/docs/tutorial/testing.md b/docs/de/docs/tutorial/testing.md index f7b0b87eb..59d0be6bb 100644 --- a/docs/de/docs/tutorial/testing.md +++ b/docs/de/docs/tutorial/testing.md @@ -8,7 +8,7 @@ Damit können Sie [pytest](https://docs.pytest.org/) direkt mit **FastAPI** verw ## `TestClient` verwenden { #using-testclient } -/// info | Info +/// note | Hinweis Um `TestClient` zu verwenden, installieren Sie zunächst [`httpx`](https://www.python-httpx.org). @@ -24,7 +24,7 @@ Importieren Sie `TestClient`. Erstellen Sie einen `TestClient`, indem Sie ihm Ihre **FastAPI**-Anwendung übergeben. -Erstellen Sie Funktionen mit einem Namen, der mit `test_` beginnt (das sind `pytest`-Konventionen). +Erstellen Sie Funktionen mit einem Namen, der mit `test_` beginnt (das ist eine Standard-`pytest`-Konvention). Verwenden Sie das `TestClient`-Objekt auf die gleiche Weise wie `httpx`. @@ -36,7 +36,7 @@ Schreiben Sie einfache `assert`-Anweisungen mit den Standard-Python-Ausdrücken, Beachten Sie, dass die Testfunktionen normal `def` und nicht `async def` sind. -Und die Anrufe an den Client sind ebenfalls normale Anrufe, die nicht `await` verwenden. +Und die Aufrufe an den Client sind ebenfalls normale Aufrufe, die nicht `await` verwenden. Dadurch können Sie `pytest` ohne Komplikationen direkt nutzen. @@ -62,7 +62,7 @@ In einer echten Anwendung würden Sie Ihre Tests wahrscheinlich in einer anderen Und Ihre **FastAPI**-Anwendung könnte auch aus mehreren Dateien/Modulen, usw. bestehen. -### **FastAPI** Anwendungsdatei { #fastapi-app-file } +### **FastAPI**-Anwendungsdatei { #fastapi-app-file } Nehmen wir an, Sie haben eine Dateistruktur wie in [Größere Anwendungen](bigger-applications.md) beschrieben: @@ -131,7 +131,7 @@ Anschließend könnten Sie `test_main.py` mit den erweiterten Tests aktualisiere {* ../../docs_src/app_testing/app_b_an_py310/test_main.py *} -Wenn Sie möchten, dass der Client Informationen im Request übergibt und Sie nicht wissen, wie das geht, können Sie suchen (googeln), wie es mit `httpx` gemacht wird, oder sogar, wie es mit `requests` gemacht wird, da das Design von HTTPX auf dem Design von Requests basiert. +Immer wenn der Client Informationen im Request übergeben soll und Sie nicht wissen, wie, können Sie danach suchen (googeln), wie es mit `httpx` gemacht wird, oder sogar, wie es mit `requests` gemacht wird, da das Design von HTTPX auf dem Design von Requests basiert. Dann machen Sie in Ihren Tests einfach das gleiche. @@ -145,7 +145,7 @@ Z. B.: Weitere Informationen zum Übergeben von Daten an das Backend (mithilfe von `httpx` oder dem `TestClient`) finden Sie in der [HTTPX-Dokumentation](https://www.python-httpx.org). -/// info | Info +/// note | Hinweis Beachten Sie, dass der `TestClient` Daten empfängt, die nach JSON konvertiert werden können, keine Pydantic-Modelle. diff --git a/docs/de/docs/virtual-environments.md b/docs/de/docs/virtual-environments.md index 81d13cc91..782d1cdcf 100644 --- a/docs/de/docs/virtual-environments.md +++ b/docs/de/docs/virtual-environments.md @@ -443,6 +443,8 @@ Auf diese Weise, wenn Sie `python` ausführen, wird nicht versucht, es aus diese Jetzt sind Sie bereit, mit Ihrem Projekt zu arbeiten. + + /// tip | Tipp Möchten Sie verstehen, was das alles oben bedeutet? @@ -455,7 +457,7 @@ Lesen Sie weiter. 👇🤓 Um mit FastAPI zu arbeiten, müssen Sie [Python](https://www.python.org/) installieren. -Danach müssen Sie FastAPI und alle anderen Pakete, die Sie verwenden möchten, **installieren**. +Danach müssen Sie FastAPI und alle anderen **Pakete**, die Sie verwenden möchten, **installieren**. Um Pakete zu installieren, würden Sie normalerweise den `pip`-Befehl verwenden, der mit Python geliefert wird (oder ähnliche Alternativen). @@ -639,7 +641,7 @@ $ source .venv/Scripts/activate Dieser Befehl erstellt oder ändert einige [Umgebungsvariablen](environment-variables.md), die für die nächsten Befehle verfügbar sein werden. -Eine dieser Variablen ist die `PATH`-Umgebungsvariable. +Eine dieser Variablen ist die `PATH`-Variable. /// tip | Tipp @@ -649,7 +651,7 @@ Sie können mehr über die `PATH`-Umgebungsvariable im Abschnitt [Umgebungsvaria Das Aktivieren einer virtuellen Umgebung fügt deren Pfad `.venv/bin` (auf Linux und macOS) oder `.venv\Scripts` (auf Windows) zur `PATH`-Umgebungsvariable hinzu. -Angenommen, die `PATH`-Umgebungsvariable sah vor dem Aktivieren der Umgebung so aus: +Angenommen, die `PATH`-Variable sah vor dem Aktivieren der Umgebung so aus: //// tab | Linux, macOS @@ -678,7 +680,7 @@ Das bedeutet, dass das System nach Programmen sucht in: //// -Nach dem Aktivieren der virtuellen Umgebung würde die `PATH`-Umgebungsvariable folgendermaßen aussehen: +Nach dem Aktivieren der virtuellen Umgebung würde die `PATH`-Variable folgendermaßen aussehen: //// tab | Linux, macOS @@ -728,7 +730,7 @@ finden und dieses verwenden. //// -Ein wichtiger Punkt ist, dass es den Pfad der virtuellen Umgebung am **Anfang** der `PATH`-Umgebungsvariable platziert. Das System wird es **vor** allen anderen verfügbaren Pythons finden. Auf diese Weise, wenn Sie `python` ausführen, wird das Python **aus der virtuellen Umgebung** verwendet anstelle eines anderen `python` (zum Beispiel, einem `python` aus einer globalen Umgebung). +Ein wichtiger Punkt ist, dass es den Pfad der virtuellen Umgebung am **Anfang** der `PATH`-Variable platziert. Das System wird es **vor** allen anderen verfügbaren Pythons finden. Auf diese Weise, wenn Sie `python` ausführen, wird das Python **aus der virtuellen Umgebung** verwendet anstelle eines anderen `python` (zum Beispiel, einem `python` aus einer globalen Umgebung). Das Aktivieren einer virtuellen Umgebung ändert auch ein paar andere Dinge, aber dies ist eines der wichtigsten Dinge, die es tut. diff --git a/docs/en/data/contributors.yml b/docs/en/data/contributors.yml index 7e1572146..b22e0975b 100644 --- a/docs/en/data/contributors.yml +++ b/docs/en/data/contributors.yml @@ -1,21 +1,21 @@ tiangolo: login: tiangolo - count: 961 + count: 1005 avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 url: https://github.com/tiangolo dependabot: login: dependabot - count: 201 + count: 221 avatarUrl: https://avatars.githubusercontent.com/in/29110?v=4 url: https://github.com/apps/dependabot YuriiMotov: login: YuriiMotov - count: 78 + count: 82 avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=bc48be95c429989224786106b027f3c5e40cc354&v=4 url: https://github.com/YuriiMotov alejsdev: login: alejsdev - count: 56 + count: 57 avatarUrl: https://avatars.githubusercontent.com/u/90076947?u=0facffe3abf87f57a1f05fa773d1119cc5c2f6a5&v=4 url: https://github.com/alejsdev pre-commit-ci: diff --git a/docs/en/data/sponsors.yml b/docs/en/data/sponsors.yml index 1466536d0..ae2c0f6e2 100644 --- a/docs/en/data/sponsors.yml +++ b/docs/en/data/sponsors.yml @@ -1,67 +1,66 @@ keystone: - url: https://fastapicloud.com title: FastAPI Cloud. By the same team behind FastAPI. You code. We Cloud. - img: https://fastapi.tiangolo.com/img/sponsors/fastapicloud.png + img: /img/sponsors/fastapicloud.png gold: - url: https://blockbee.io?ref=fastapi title: BlockBee Cryptocurrency Payment Gateway - img: https://fastapi.tiangolo.com/img/sponsors/blockbee.png - - 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 + img: /img/sponsors/blockbee.png + banner_img: /img/sponsors/blockbee-banner.png - 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://liblab.com?utm_source=fastapi - title: liblab - Generate SDKs from FastAPI - img: https://fastapi.tiangolo.com/img/sponsors/liblab.png + img: /img/sponsors/propelauth.png + banner_url: https://www.propelauth.com/?utm_source=fastapi&utm_campaign=1223&utm_medium=topbanner + banner_img: /img/sponsors/propelauth-banner.png - 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 + img: /img/sponsors/render.svg + banner_img: /img/sponsors/render-banner.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 + img: /img/sponsors/coderabbit.png + banner_url: https://www.coderabbit.ai/?utm_source=fastapi&utm_medium=banner&utm_campaign=fastapi + banner_img: /img/sponsors/coderabbit-banner.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 + img: /img/sponsors/subtotal.svg + banner_title: Making Retail Purchases Actionable for Brands and Developers + banner_img: /img/sponsors/subtotal-banner.svg - 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 + img: /img/sponsors/railway.png + banner_img: /img/sponsors/railway-banner.png - url: https://serpapi.com/?utm_source=fastapi_website title: "SerpApi: Web Search API" - img: https://fastapi.tiangolo.com/img/sponsors/serpapi.png + img: /img/sponsors/serpapi.png + banner_img: /img/sponsors/serpapi-banner.png - url: https://www.greptile.com/?utm_source=fastapi&utm_medium=sponsorship&utm_campaign=fastapi_sponsor_page title: "Greptile: The AI Code Reviewer" - img: https://fastapi.tiangolo.com/img/sponsors/greptile.png + img: /img/sponsors/greptile.png + banner_img: /img/sponsors/greptile-banner.png silver: - 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 + img: /img/sponsors/databento.svg - url: https://www.svix.com/ title: Svix - Webhooks as a service - img: https://fastapi.tiangolo.com/img/sponsors/svix.svg - - 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 + img: /img/sponsors/svix.svg - 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 + img: /img/sponsors/permit.png - url: https://dribia.com/en/ title: Dribia - Data Science within your reach - img: https://fastapi.tiangolo.com/img/sponsors/dribia.png - - url: https://talordata.com/?campaignid=oh5dVZ3Zc3YGiAI2&utm_source=fastapi&utm_term=fastapi - title: TalorData SERP API - Multi-Engine Search Results Data - img: https://fastapi.tiangolo.com/img/sponsors/talordata.png + img: /img/sponsors/dribia.png - url: https://www.rapidproxy.io/?ref=fastapi title: Try RapidProxy for free - Residential Proxies with 90M+ Global IPs. Starting from $0.65/GB for web scraping, automation, and data collection. - img: https://fastapi.tiangolo.com/img/sponsors/rapidproxy.png + img: /img/sponsors/rapidproxy.png + - url: https://www.bairesdev.com/ + title: "BairesDev | Nearshore Software Development & Staff Augmentation Company" + img: /img/sponsors/bairesdev.svg 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 + # img: /img/sponsors/testdriven.svg + - url: https://www.testmu.ai/?utm_source=fastapi&utm_medium=partner&utm_campaign=sponsor&utm_term=opensource&utm_content=webpage + title: TestMu AI. The Native AI-Agentic Cloud Platform to Supercharge Quality Engineering. + img: /img/sponsors/testmu.png diff --git a/docs/en/data/topic_repos.yml b/docs/en/data/topic_repos.yml index 9013ebc1c..ecfad6cb4 100644 --- a/docs/en/data/topic_repos.yml +++ b/docs/en/data/topic_repos.yml @@ -1,186 +1,191 @@ +- name: headroom + html_url: https://github.com/headroomlabs-ai/headroom + stars: 55017 + owner_login: headroomlabs-ai + owner_html_url: https://github.com/headroomlabs-ai - name: full-stack-fastapi-template html_url: https://github.com/fastapi/full-stack-fastapi-template - stars: 43447 + stars: 43994 owner_login: fastapi owner_html_url: https://github.com/fastapi - name: Hello-Python html_url: https://github.com/mouredev/Hello-Python - stars: 35831 + stars: 36226 owner_login: mouredev owner_html_url: https://github.com/mouredev - name: serve html_url: https://github.com/jina-ai/serve - stars: 21864 + stars: 21862 owner_login: jina-ai owner_html_url: https://github.com/jina-ai - name: HivisionIDPhotos html_url: https://github.com/Zeyi-Lin/HivisionIDPhotos - stars: 21144 + stars: 21212 owner_login: Zeyi-Lin owner_html_url: https://github.com/Zeyi-Lin - name: Douyin_TikTok_Download_API html_url: https://github.com/Evil0ctal/Douyin_TikTok_Download_API - stars: 18122 + stars: 18599 owner_login: Evil0ctal owner_html_url: https://github.com/Evil0ctal - name: sqlmodel html_url: https://github.com/fastapi/sqlmodel - stars: 17987 + stars: 18156 owner_login: fastapi owner_html_url: https://github.com/fastapi - name: fastapi-best-practices html_url: https://github.com/zhanymkanov/fastapi-best-practices - stars: 17401 + stars: 17608 owner_login: zhanymkanov owner_html_url: https://github.com/zhanymkanov - name: SurfSense html_url: https://github.com/MODSetter/SurfSense - stars: 14374 + stars: 15161 owner_login: MODSetter owner_html_url: https://github.com/MODSetter - name: machine-learning-zoomcamp html_url: https://github.com/DataTalksClub/machine-learning-zoomcamp - stars: 13169 + stars: 13445 owner_login: DataTalksClub owner_html_url: https://github.com/DataTalksClub +- name: peewee + html_url: https://github.com/coleifer/peewee + stars: 11976 + owner_login: coleifer + owner_html_url: https://github.com/coleifer - name: fastapi_mcp html_url: https://github.com/tadata-org/fastapi_mcp - stars: 11885 + stars: 11932 owner_login: tadata-org owner_html_url: https://github.com/tadata-org -- name: awesome-fastapi - html_url: https://github.com/mjhea0/awesome-fastapi - stars: 11406 - owner_login: mjhea0 - owner_html_url: https://github.com/mjhea0 - name: XHS-Downloader html_url: https://github.com/JoeanAmier/XHS-Downloader - stars: 11375 + stars: 11768 owner_login: JoeanAmier owner_html_url: https://github.com/JoeanAmier +- name: awesome-fastapi + html_url: https://github.com/mjhea0/awesome-fastapi + stars: 11478 + owner_login: mjhea0 + owner_html_url: https://github.com/mjhea0 - name: polar html_url: https://github.com/polarsource/polar - stars: 9894 + stars: 9999 owner_login: polarsource owner_html_url: https://github.com/polarsource - name: pycaret html_url: https://github.com/pycaret/pycaret - stars: 9801 + stars: 9818 owner_login: pycaret owner_html_url: https://github.com/pycaret - name: FastUI html_url: https://github.com/pydantic/FastUI - stars: 8966 + stars: 8970 owner_login: pydantic owner_html_url: https://github.com/pydantic - name: FileCodeBox html_url: https://github.com/vastsa/FileCodeBox - stars: 8305 + stars: 8376 owner_login: vastsa owner_html_url: https://github.com/vastsa - name: nonebot2 html_url: https://github.com/nonebot/nonebot2 - stars: 7544 + stars: 7593 owner_login: nonebot owner_html_url: https://github.com/nonebot - name: hatchet html_url: https://github.com/hatchet-dev/hatchet - stars: 7258 + stars: 7441 owner_login: hatchet-dev owner_html_url: https://github.com/hatchet-dev - name: fastapi-users html_url: https://github.com/fastapi-users/fastapi-users - stars: 6152 + stars: 6182 owner_login: fastapi-users owner_html_url: https://github.com/fastapi-users -- name: serge - html_url: https://github.com/serge-chat/serge - stars: 5726 - owner_login: serge-chat - owner_html_url: https://github.com/serge-chat - name: Yuxi html_url: https://github.com/xerrors/Yuxi - stars: 5323 + stars: 5926 owner_login: xerrors owner_html_url: https://github.com/xerrors +- name: serge + html_url: https://github.com/serge-chat/serge + stars: 5723 + owner_login: serge-chat + owner_html_url: https://github.com/serge-chat +- name: honcho + html_url: https://github.com/plastic-labs/honcho + stars: 5680 + owner_login: plastic-labs + owner_html_url: https://github.com/plastic-labs - name: Kokoro-FastAPI html_url: https://github.com/remsky/Kokoro-FastAPI - stars: 4936 + stars: 5085 owner_login: remsky owner_html_url: https://github.com/remsky - name: devpush html_url: https://github.com/hunvreus/devpush - stars: 4664 + stars: 4693 owner_login: hunvreus owner_html_url: https://github.com/hunvreus - name: strawberry html_url: https://github.com/strawberry-graphql/strawberry - stars: 4663 + stars: 4677 owner_login: strawberry-graphql owner_html_url: https://github.com/strawberry-graphql -- name: honcho - html_url: https://github.com/plastic-labs/honcho - stars: 4606 - owner_login: plastic-labs - owner_html_url: https://github.com/plastic-labs - name: poem html_url: https://github.com/poem-web/poem - stars: 4398 + stars: 4415 owner_login: poem-web owner_html_url: https://github.com/poem-web -- name: dynaconf - html_url: https://github.com/dynaconf/dynaconf - stars: 4302 - owner_login: dynaconf - owner_html_url: https://github.com/dynaconf - name: logfire html_url: https://github.com/pydantic/logfire - stars: 4276 + stars: 4340 owner_login: pydantic owner_html_url: https://github.com/pydantic +- name: dynaconf + html_url: https://github.com/dynaconf/dynaconf + stars: 4310 + owner_login: dynaconf + owner_html_url: https://github.com/dynaconf - name: chatgpt-web-share html_url: https://github.com/chatpire/chatgpt-web-share - stars: 4273 + stars: 4269 owner_login: chatpire owner_html_url: https://github.com/chatpire - name: huma html_url: https://github.com/danielgtaylor/huma - stars: 4133 + stars: 4203 owner_login: danielgtaylor owner_html_url: https://github.com/danielgtaylor - name: atrilabs-engine html_url: https://github.com/Atri-Labs/atrilabs-engine - stars: 4073 + stars: 4071 owner_login: Atri-Labs owner_html_url: https://github.com/Atri-Labs +- name: mcp-context-forge + html_url: https://github.com/IBM/mcp-context-forge + stars: 3989 + owner_login: IBM + owner_html_url: https://github.com/IBM - name: datamodel-code-generator html_url: https://github.com/koxudaxi/datamodel-code-generator - stars: 3918 + stars: 3952 owner_login: koxudaxi owner_html_url: https://github.com/koxudaxi - name: LitServe html_url: https://github.com/Lightning-AI/LitServe - stars: 3886 + stars: 3901 owner_login: Lightning-AI owner_html_url: https://github.com/Lightning-AI -- name: mcp-context-forge - html_url: https://github.com/IBM/mcp-context-forge - stars: 3797 - owner_login: IBM - owner_html_url: https://github.com/IBM - name: fastapi-admin html_url: https://github.com/fastapi-admin/fastapi-admin - stars: 3784 + stars: 3799 owner_login: fastapi-admin owner_html_url: https://github.com/fastapi-admin -- name: headroom - html_url: https://github.com/chopratejas/headroom - stars: 3701 - owner_login: chopratejas - owner_html_url: https://github.com/chopratejas - name: tracecat html_url: https://github.com/TracecatHQ/tracecat - stars: 3624 + stars: 3703 owner_login: TracecatHQ owner_html_url: https://github.com/TracecatHQ - name: farfalle @@ -188,139 +193,159 @@ stars: 3535 owner_login: rashadphz owner_html_url: https://github.com/rashadphz +- name: Rapid-MLX + html_url: https://github.com/raullenchai/Rapid-MLX + stars: 3155 + owner_login: raullenchai + owner_html_url: https://github.com/raullenchai - name: opyrator html_url: https://github.com/ml-tooling/opyrator - stars: 3136 + stars: 3133 owner_login: ml-tooling owner_html_url: https://github.com/ml-tooling - name: docarray html_url: https://github.com/docarray/docarray - stars: 3119 + stars: 3121 owner_login: docarray owner_html_url: https://github.com/docarray - name: fastapi-realworld-example-app html_url: https://github.com/nsidnev/fastapi-realworld-example-app - stars: 3110 + stars: 3109 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: 2910 + stars: 2914 owner_login: tiangolo owner_html_url: https://github.com/tiangolo +- name: any-auto-register + html_url: https://github.com/lxf746/any-auto-register + stars: 2832 + owner_login: lxf746 + owner_html_url: https://github.com/lxf746 - name: FastAPI-template html_url: https://github.com/s3rius/FastAPI-template - stars: 2800 + stars: 2810 owner_login: s3rius owner_html_url: https://github.com/s3rius - name: YC-Killer html_url: https://github.com/sahibzada-allahyar/YC-Killer - stars: 2770 + stars: 2779 owner_login: sahibzada-allahyar owner_html_url: https://github.com/sahibzada-allahyar - name: sqladmin html_url: https://github.com/smithyhq/sqladmin - stars: 2739 + stars: 2759 owner_login: smithyhq owner_html_url: https://github.com/smithyhq - name: best-of-web-python html_url: https://github.com/ml-tooling/best-of-web-python - stars: 2723 + stars: 2731 owner_login: ml-tooling owner_html_url: https://github.com/ml-tooling -- name: Rapid-MLX - html_url: https://github.com/raullenchai/Rapid-MLX - stars: 2640 - owner_login: raullenchai - owner_html_url: https://github.com/raullenchai +- name: NoteDiscovery + html_url: https://github.com/gamosoft/NoteDiscovery + stars: 2595 + owner_login: gamosoft + owner_html_url: https://github.com/gamosoft - name: fastapi-react html_url: https://github.com/Buuntu/fastapi-react stars: 2588 owner_login: Buuntu owner_html_url: https://github.com/Buuntu -- name: any-auto-register - html_url: https://github.com/lxf746/any-auto-register - stars: 2542 - owner_login: lxf746 - owner_html_url: https://github.com/lxf746 -- name: NoteDiscovery - html_url: https://github.com/gamosoft/NoteDiscovery - stars: 2531 - owner_login: gamosoft - owner_html_url: https://github.com/gamosoft - name: supabase-py html_url: https://github.com/supabase/supabase-py - stars: 2518 + stars: 2530 owner_login: supabase owner_html_url: https://github.com/supabase - name: 30-Days-of-Python html_url: https://github.com/codingforentrepreneurs/30-Days-of-Python - stars: 2470 + stars: 2483 owner_login: codingforentrepreneurs owner_html_url: https://github.com/codingforentrepreneurs - name: RasaGPT html_url: https://github.com/paulpierre/RasaGPT - stars: 2466 + stars: 2462 owner_login: paulpierre owner_html_url: https://github.com/paulpierre -- name: AIstudioProxyAPI - html_url: https://github.com/CJackHwang/AIstudioProxyAPI - stars: 2396 - owner_login: CJackHwang - owner_html_url: https://github.com/CJackHwang - name: fastapi-langgraph-agent-production-ready-template html_url: https://github.com/wassim249/fastapi-langgraph-agent-production-ready-template - stars: 2338 + stars: 2456 owner_login: wassim249 owner_html_url: https://github.com/wassim249 +- name: AIstudioProxyAPI + html_url: https://github.com/CJackHwang/AIstudioProxyAPI + stars: 2445 + owner_login: CJackHwang + owner_html_url: https://github.com/CJackHwang - name: nextpy html_url: https://github.com/dot-agent/nextpy - stars: 2336 + stars: 2341 owner_login: dot-agent owner_html_url: https://github.com/dot-agent - name: langserve html_url: https://github.com/langchain-ai/langserve - stars: 2330 + stars: 2329 owner_login: langchain-ai owner_html_url: https://github.com/langchain-ai -- name: fastapi-utils - html_url: https://github.com/fastapiutils/fastapi-utils - stars: 2310 - owner_login: fastapiutils - owner_html_url: https://github.com/fastapiutils - name: fastapi-best-architecture html_url: https://github.com/fastapi-practices/fastapi-best-architecture - stars: 2256 + stars: 2318 owner_login: fastapi-practices owner_html_url: https://github.com/fastapi-practices -- name: solara - html_url: https://github.com/widgetti/solara - stars: 2162 - owner_login: widgetti - owner_html_url: https://github.com/widgetti +- name: fastapi-utils + html_url: https://github.com/fastapiutils/fastapi-utils + stars: 2308 + owner_login: fastapiutils + owner_html_url: https://github.com/fastapiutils - name: vue-fastapi-admin html_url: https://github.com/mizhexiaoxiao/vue-fastapi-admin - stars: 2148 + stars: 2184 owner_login: mizhexiaoxiao owner_html_url: https://github.com/mizhexiaoxiao +- name: solara + html_url: https://github.com/widgetti/solara + stars: 2166 + owner_login: widgetti + owner_html_url: https://github.com/widgetti - name: mangum html_url: https://github.com/Kludex/mangum - stars: 2119 + stars: 2125 owner_login: Kludex owner_html_url: https://github.com/Kludex +- name: codex-lb + html_url: https://github.com/Soju06/codex-lb + stars: 2122 + owner_login: Soju06 + owner_html_url: https://github.com/Soju06 +- name: kiro-gateway + html_url: https://github.com/jwadow/kiro-gateway + stars: 2068 + owner_login: jwadow + owner_html_url: https://github.com/jwadow +- name: open-wearables + html_url: https://github.com/the-momentum/open-wearables + stars: 2036 + owner_login: the-momentum + owner_html_url: https://github.com/the-momentum - name: slowapi html_url: https://github.com/laurentS/slowapi - stars: 2000 + stars: 2022 owner_login: laurentS owner_html_url: https://github.com/laurentS - name: xhs_ai_publisher html_url: https://github.com/BetaStreetOmnis/xhs_ai_publisher - stars: 1980 + stars: 2004 owner_login: BetaStreetOmnis owner_html_url: https://github.com/BetaStreetOmnis +- name: FastAPI-boilerplate + html_url: https://github.com/benavlabs/FastAPI-boilerplate + stars: 1984 + owner_login: benavlabs + owner_html_url: https://github.com/benavlabs - name: openapi-python-client html_url: https://github.com/openapi-generators/openapi-python-client - stars: 1960 + stars: 1967 owner_login: openapi-generators owner_html_url: https://github.com/openapi-generators - name: agentkit @@ -328,34 +353,24 @@ stars: 1944 owner_login: BCG-X-Official owner_html_url: https://github.com/BCG-X-Official -- name: FastAPI-boilerplate - html_url: https://github.com/benavlabs/FastAPI-boilerplate - stars: 1931 - owner_login: benavlabs - owner_html_url: https://github.com/benavlabs - name: piccolo html_url: https://github.com/piccolo-orm/piccolo - stars: 1904 + stars: 1922 owner_login: piccolo-orm owner_html_url: https://github.com/piccolo-orm - name: manage-fastapi html_url: https://github.com/ycd/manage-fastapi - stars: 1903 + stars: 1905 owner_login: ycd owner_html_url: https://github.com/ycd - name: fastapi-cache html_url: https://github.com/long2ice/fastapi-cache - stars: 1865 + stars: 1866 owner_login: long2ice owner_html_url: https://github.com/long2ice -- name: kiro-gateway - html_url: https://github.com/jwadow/kiro-gateway - stars: 1853 - owner_login: jwadow - owner_html_url: https://github.com/jwadow - name: ormar html_url: https://github.com/ormar-orm/ormar - stars: 1809 + stars: 1806 owner_login: ormar-orm owner_html_url: https://github.com/ormar-orm - name: python-week-2022 @@ -363,39 +378,29 @@ stars: 1806 owner_login: rochacbruno owner_html_url: https://github.com/rochacbruno -- name: open-wearables - html_url: https://github.com/the-momentum/open-wearables - stars: 1782 - owner_login: the-momentum - owner_html_url: https://github.com/the-momentum +- name: WebRPA + html_url: https://github.com/pmh1314520/WebRPA + stars: 1781 + owner_login: pmh1314520 + owner_html_url: https://github.com/pmh1314520 - name: termpair html_url: https://github.com/cs01/termpair stars: 1735 owner_login: cs01 owner_html_url: https://github.com/cs01 -- name: WebRPA - html_url: https://github.com/pmh1314520/WebRPA - stars: 1718 - owner_login: pmh1314520 - owner_html_url: https://github.com/pmh1314520 -- name: codex-lb - html_url: https://github.com/Soju06/codex-lb - stars: 1709 - owner_login: Soju06 - owner_html_url: https://github.com/Soju06 - name: fastapi-crudrouter html_url: https://github.com/awtkns/fastapi-crudrouter - stars: 1692 + stars: 1694 owner_login: awtkns owner_html_url: https://github.com/awtkns - name: bracket html_url: https://github.com/evroon/bracket - stars: 1682 + stars: 1694 owner_login: evroon owner_html_url: https://github.com/evroon - name: fastapi-pagination html_url: https://github.com/uriyyo/fastapi-pagination - stars: 1658 + stars: 1670 owner_login: uriyyo owner_html_url: https://github.com/uriyyo - name: langchain-serve @@ -405,91 +410,86 @@ owner_html_url: https://github.com/jina-ai - name: awesome-fastapi-projects html_url: https://github.com/Kludex/awesome-fastapi-projects - stars: 1603 + stars: 1608 owner_login: Kludex owner_html_url: https://github.com/Kludex - name: coronavirus-tracker-api html_url: https://github.com/ExpDev07/coronavirus-tracker-api - stars: 1567 + stars: 1568 owner_login: ExpDev07 owner_html_url: https://github.com/ExpDev07 - name: fastapi-amis-admin html_url: https://github.com/amisadmin/fastapi-amis-admin - stars: 1554 + stars: 1559 owner_login: amisadmin owner_html_url: https://github.com/amisadmin - name: fastcrud html_url: https://github.com/benavlabs/fastcrud - stars: 1519 + stars: 1531 owner_login: benavlabs owner_html_url: https://github.com/benavlabs - name: tavily-key-generator html_url: https://github.com/skernelx/tavily-key-generator - stars: 1507 + stars: 1526 owner_login: skernelx owner_html_url: https://github.com/skernelx - name: fastapi-boilerplate html_url: https://github.com/teamhide/fastapi-boilerplate - stars: 1490 + stars: 1491 owner_login: teamhide owner_html_url: https://github.com/teamhide +- name: full-stack-ai-agent-template + html_url: https://github.com/vstorm-co/full-stack-ai-agent-template + stars: 1484 + owner_login: vstorm-co + owner_html_url: https://github.com/vstorm-co - name: prometheus-fastapi-instrumentator html_url: https://github.com/trallnag/prometheus-fastapi-instrumentator - stars: 1458 + stars: 1471 owner_login: trallnag owner_html_url: https://github.com/trallnag - name: awesome-python-resources html_url: https://github.com/DjangoEx/awesome-python-resources - stars: 1448 + stars: 1451 owner_login: DjangoEx owner_html_url: https://github.com/DjangoEx -- name: fastapi-tutorial - html_url: https://github.com/liaogx/fastapi-tutorial - stars: 1404 - owner_login: liaogx - owner_html_url: https://github.com/liaogx -- name: fastapi-code-generator - html_url: https://github.com/koxudaxi/fastapi-code-generator - stars: 1397 - owner_login: koxudaxi - owner_html_url: https://github.com/koxudaxi - name: aktools html_url: https://github.com/akfamily/aktools - stars: 1394 + stars: 1431 owner_login: akfamily owner_html_url: https://github.com/akfamily - name: RuoYi-Vue3-FastAPI html_url: https://github.com/insistence/RuoYi-Vue3-FastAPI - stars: 1364 + stars: 1419 owner_login: insistence owner_html_url: https://github.com/insistence +- name: fastapi-tutorial + html_url: https://github.com/liaogx/fastapi-tutorial + stars: 1418 + owner_login: liaogx + owner_html_url: https://github.com/liaogx +- name: fastapi-code-generator + html_url: https://github.com/koxudaxi/fastapi-code-generator + stars: 1396 + owner_login: koxudaxi + owner_html_url: https://github.com/koxudaxi +- name: yubal + html_url: https://github.com/guillevc/yubal + stars: 1388 + owner_login: guillevc + owner_html_url: https://github.com/guillevc - name: budgetml html_url: https://github.com/ebhy/budgetml - stars: 1345 + stars: 1343 owner_login: ebhy owner_html_url: https://github.com/ebhy -- name: full-stack-ai-agent-template - html_url: https://github.com/vstorm-co/full-stack-ai-agent-template - stars: 1316 - owner_login: vstorm-co - owner_html_url: https://github.com/vstorm-co -- name: bolt-python - html_url: https://github.com/slackapi/bolt-python - stars: 1308 - owner_login: slackapi - owner_html_url: https://github.com/slackapi -- name: bedrock-chat - html_url: https://github.com/aws-samples/bedrock-chat - stars: 1304 - owner_login: aws-samples - owner_html_url: https://github.com/aws-samples +- name: Chatterbox-TTS-Server + html_url: https://github.com/devnen/Chatterbox-TTS-Server + stars: 1328 + owner_login: devnen + owner_html_url: https://github.com/devnen - name: restish html_url: https://github.com/rest-sh/restish - stars: 1303 + stars: 1321 owner_login: rest-sh owner_html_url: https://github.com/rest-sh -- name: yubal - html_url: https://github.com/guillevc/yubal - stars: 1302 - owner_login: guillevc - owner_html_url: https://github.com/guillevc diff --git a/docs/en/data/translation_reviewers.yml b/docs/en/data/translation_reviewers.yml index 3ed7d09d9..ccc4d604f 100644 --- a/docs/en/data/translation_reviewers.yml +++ b/docs/en/data/translation_reviewers.yml @@ -28,6 +28,11 @@ hard-coders: count: 102 avatarUrl: https://avatars.githubusercontent.com/u/9651103?u=78d12d1acdf853c817700145e73de7fd9e5d068b&v=4 url: https://github.com/hard-coders +YuriiMotov: + login: YuriiMotov + count: 95 + avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=bc48be95c429989224786106b027f3c5e40cc354&v=4 + url: https://github.com/YuriiMotov hasansezertasan: login: hasansezertasan count: 95 @@ -38,11 +43,6 @@ alv2017: count: 88 avatarUrl: https://avatars.githubusercontent.com/u/31544722?v=4 url: https://github.com/alv2017 -YuriiMotov: - login: YuriiMotov - count: 87 - avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=bc48be95c429989224786106b027f3c5e40cc354&v=4 - url: https://github.com/YuriiMotov nazarepiedady: login: nazarepiedady count: 87 @@ -383,6 +383,11 @@ mastizada: count: 16 avatarUrl: https://avatars.githubusercontent.com/u/1975818?u=0751a06d7271c8bf17cb73b1b845644ab4d2c6dc&v=4 url: https://github.com/mastizada +waketzheng: + login: waketzheng + count: 16 + avatarUrl: https://avatars.githubusercontent.com/u/35413830?u=df19e4fd5bb928e7d086e053ef26a46aad23bf84&v=4 + url: https://github.com/waketzheng Joao-Pedro-P-Holanda: login: Joao-Pedro-P-Holanda count: 16 @@ -448,11 +453,6 @@ impocode: count: 13 avatarUrl: https://avatars.githubusercontent.com/u/109408819?u=9cdfc5ccb31a2094c520f41b6087012fa9048982&v=4 url: https://github.com/impocode -waketzheng: - login: waketzheng - count: 13 - avatarUrl: https://avatars.githubusercontent.com/u/35413830?u=df19e4fd5bb928e7d086e053ef26a46aad23bf84&v=4 - url: https://github.com/waketzheng wesinalves: login: wesinalves count: 13 @@ -563,6 +563,11 @@ Pyth3rEx: count: 11 avatarUrl: https://avatars.githubusercontent.com/u/26427764?u=087724f74d813c95925d51e354554bd4b6d6bb60&v=4 url: https://github.com/Pyth3rEx +ABcDexter: + login: ABcDexter + count: 11 + avatarUrl: https://avatars.githubusercontent.com/u/7236257?u=baa7e62eb4d0014b5854bfd0d5c2b20bd9617e0d&v=4 + url: https://github.com/ABcDexter mariacamilagl: login: mariacamilagl count: 10 @@ -661,7 +666,7 @@ eVery1337: aykhans: login: aykhans count: 9 - avatarUrl: https://avatars.githubusercontent.com/u/88669260?u=798da457cc3276d3c6dd7fd628d0005ad8b298cc&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/88669260?u=2760f6f6728ed11108b56265682bcf68d46067a5&v=4 url: https://github.com/aykhans riroan: login: riroan @@ -671,7 +676,7 @@ riroan: MinLee0210: login: MinLee0210 count: 9 - avatarUrl: https://avatars.githubusercontent.com/u/57653278?u=e7c4d8d7eeb7bceed1680ef0e5dafec0695f57e0&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/57653278?u=9fef84dd2f7497e8b43db01ba517a5b2bd66ad88&v=4 url: https://github.com/MinLee0210 yodai-yodai: login: yodai-yodai @@ -693,11 +698,6 @@ Yarous: count: 9 avatarUrl: https://avatars.githubusercontent.com/u/61277193?u=5b462347458a373b2d599c6f416d2b75eddbffad&v=4 url: https://github.com/Yarous -ABcDexter: - login: ABcDexter - count: 9 - avatarUrl: https://avatars.githubusercontent.com/u/7236257?u=baa7e62eb4d0014b5854bfd0d5c2b20bd9617e0d&v=4 - url: https://github.com/ABcDexter dimaqq: login: dimaqq count: 8 @@ -756,7 +756,7 @@ EdmilsonRodrigues: roli2py: login: roli2py count: 8 - avatarUrl: https://avatars.githubusercontent.com/u/61126128?u=bcb7a286e435a6b9d6a84b07db1232580ee796d4&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/61126128?u=d20921080d6b9499b39ef3431e850432fe68f903&v=4 url: https://github.com/roli2py Serrones: login: Serrones @@ -1281,7 +1281,7 @@ rafsaf: frnsimoes: login: frnsimoes count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/66239468?u=be491199e4695bb0ac43d17d59cf7d41f9df629f&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/66239468?u=c86ceed4afa180477e28b9ff0019ab894a1e1eb9&v=4 url: https://github.com/frnsimoes lieryan: login: lieryan diff --git a/docs/en/data/translators.yml b/docs/en/data/translators.yml index d0ca9a1d6..ccad6767f 100644 --- a/docs/en/data/translators.yml +++ b/docs/en/data/translators.yml @@ -5,7 +5,7 @@ nilslindemann: url: https://github.com/nilslindemann tiangolo: login: tiangolo - count: 78 + count: 100 avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 url: https://github.com/tiangolo jaystone776: @@ -23,6 +23,11 @@ valentinDruzhinin: count: 29 avatarUrl: https://avatars.githubusercontent.com/u/12831905?u=aae1ebc675c91e8fa582df4fcc4fc4128106344d&v=4 url: https://github.com/valentinDruzhinin +YuriiMotov: + login: YuriiMotov + count: 24 + avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=bc48be95c429989224786106b027f3c5e40cc354&v=4 + url: https://github.com/YuriiMotov tokusumi: login: tokusumi count: 23 @@ -33,11 +38,6 @@ SwftAlpc: count: 23 avatarUrl: https://avatars.githubusercontent.com/u/52768429?u=6a3aa15277406520ad37f6236e89466ed44bc5b8&v=4 url: https://github.com/SwftAlpc -YuriiMotov: - login: YuriiMotov - count: 23 - avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=bc48be95c429989224786106b027f3c5e40cc354&v=4 - url: https://github.com/YuriiMotov hasansezertasan: login: hasansezertasan count: 22 @@ -466,7 +466,7 @@ ArtemKhymenko: hasnatsajid: login: hasnatsajid count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/86589885?u=3712c0362d7a4000d76022339c545cf46aa5903f&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/86589885?u=a1f0d462a558e4fc7271bfcdc7e5e7de92b9e10b&v=4 url: https://github.com/hasnatsajid alperiox: login: alperiox diff --git a/docs/en/docs/_llm-test.md b/docs/en/docs/_llm-test.md index 2b548064d..603474cfc 100644 --- a/docs/en/docs/_llm-test.md +++ b/docs/en/docs/_llm-test.md @@ -185,7 +185,7 @@ See section `### Links` in the general prompt in `scripts/translate.py`. //// tab | Test -Here some things wrapped in HTML "abbr" elements (Some are invented): +Here are some things wrapped in HTML "abbr" elements (Some are invented): ### The abbr gives a full phrase { #the-abbr-gives-a-full-phrase } @@ -488,7 +488,7 @@ For some language specific instructions, see e.g. section `### Headings` in `doc //// tab | Info -This is a not complete and not normative list of (mostly) technical terms seen in the docs. It may be helpful for the prompt designer to figure out for which terms the LLM needs a helping hand. For example when it keeps reverting a good translation to a suboptimal translation. Or when it has problems conjugating/declinating a term in your language. +This is neither a complete nor a normative list of (mostly) technical terms seen in the docs. It may be helpful for the prompt designer to figure out for which terms the LLM needs a helping hand. For example when it keeps reverting a good translation to a suboptimal translation. Or when it has problems conjugating/declinating a term in your language. See e.g. section `### List of English terms and their preferred German translations` in `docs/de/llm-prompt.md`. diff --git a/docs/en/docs/advanced/additional-status-codes.md b/docs/en/docs/advanced/additional-status-codes.md index 3b6da2355..c4f1bf389 100644 --- a/docs/en/docs/advanced/additional-status-codes.md +++ b/docs/en/docs/advanced/additional-status-codes.md @@ -8,7 +8,7 @@ It will use the default status code or the one you set in your *path operation*. If you want to return additional status codes apart from the main one, you can do that by returning a `Response` directly, like a `JSONResponse`, and set the additional status code directly. -For example, let's say that you want to have a *path operation* that allows to update items, and returns HTTP status codes of 200 "OK" when successful. +For example, let's say that you want to have a *path operation* that allows updating items, and returns HTTP status codes of 200 "OK" when successful. But you also want it to accept new items. And when the items didn't exist before, it creates them, and returns an HTTP status code of 201 "Created". diff --git a/docs/en/docs/advanced/advanced-dependencies.md b/docs/en/docs/advanced/advanced-dependencies.md index 59ab62bf0..e039788ae 100644 --- a/docs/en/docs/advanced/advanced-dependencies.md +++ b/docs/en/docs/advanced/advanced-dependencies.md @@ -54,7 +54,7 @@ checker(q="somequery") /// tip -All this might seem contrived. And it might not be very clear how is it useful yet. +All this might seem contrived. And it might not be very clear how it is useful yet. These examples are intentionally simple, but show how it all works. @@ -112,7 +112,7 @@ For example, imagine you have code that uses a database session in a dependency In this case, the database session would be held until the response is finished being sent, but if you don't use it, then it wouldn't be necessary to hold it. -Here's how it could look like: +Here's how it could look: {* ../../docs_src/dependencies/tutorial013_an_py310.py *} diff --git a/docs/en/docs/advanced/dataclasses.md b/docs/en/docs/advanced/dataclasses.md index 292dc3fba..fbabe0c87 100644 --- a/docs/en/docs/advanced/dataclasses.md +++ b/docs/en/docs/advanced/dataclasses.md @@ -24,7 +24,7 @@ Keep in mind that dataclasses can't do everything Pydantic models can do. So, you might still need to use Pydantic models. -But if you have a bunch of dataclasses laying around, this is a nice trick to use them to power a web API using FastAPI. 🤓 +But if you have a bunch of dataclasses lying around, this is a nice trick to use them to power a web API using FastAPI. 🤓 /// diff --git a/docs/en/docs/advanced/events.md b/docs/en/docs/advanced/events.md index 3e65854e7..8f8cdb017 100644 --- a/docs/en/docs/advanced/events.md +++ b/docs/en/docs/advanced/events.md @@ -142,7 +142,7 @@ So, we declare the event handler function with standard `def` instead of `async There's a high chance that the logic for your *startup* and *shutdown* is connected, you might want to start something and then finish it, acquire a resource and then release it, etc. -Doing that in separated functions that don't share logic or variables together is more difficult as you would need to store values in global variables or similar tricks. +Doing that in separate functions that don't share logic or variables together is more difficult as you would need to store values in global variables or similar tricks. Because of that, it's now recommended to instead use the `lifespan` as explained above. diff --git a/docs/en/docs/advanced/generate-clients.md b/docs/en/docs/advanced/generate-clients.md index 1fff3c9dc..67dfe736f 100644 --- a/docs/en/docs/advanced/generate-clients.md +++ b/docs/en/docs/advanced/generate-clients.md @@ -20,21 +20,6 @@ FastAPI automatically generates **OpenAPI 3.1** specifications, so any tool you /// -## SDK Generators from FastAPI Sponsors { #sdk-generators-from-fastapi-sponsors } - -This section highlights **venture-backed** and **company-supported** solutions from companies that sponsor FastAPI. These products provide **additional features** and **integrations** on top of high-quality generated SDKs. - -By ✨ [**sponsoring FastAPI**](../help-fastapi.md#sponsor-the-author) ✨, these companies help ensure the framework and its **ecosystem** remain healthy and **sustainable**. - -Their sponsorship also demonstrates a strong commitment to the FastAPI **community** (you), showing that they care not only about offering a **great service** but also about supporting a **robust and thriving framework**, FastAPI. 🙇 - -For example, you might want to try: - -* [Stainless](https://www.stainless.com/?utm_source=fastapi&utm_medium=referral) -* [liblab](https://developers.liblab.com/tutorials/sdk-for-fastapi?utm_source=fastapi) - -Some of these solutions may also be open source or offer free tiers, so you can try them without a financial commitment. Other commercial SDK generators are available and can be found online. 🤓 - ## Create a TypeScript SDK { #create-a-typescript-sdk } Let's start with a simple FastAPI application: diff --git a/docs/en/docs/advanced/json-base64-bytes.md b/docs/en/docs/advanced/json-base64-bytes.md index 9f0602c54..55f4a99b4 100644 --- a/docs/en/docs/advanced/json-base64-bytes.md +++ b/docs/en/docs/advanced/json-base64-bytes.md @@ -4,7 +4,7 @@ If your app needs to receive and send JSON data, but you need to include binary ## Base64 vs Files { #base64-vs-files } -Consider first if you can use [Request Files](../tutorial/request-files.md) for uploading binary data and [Custom Response - FileResponse](./custom-response.md#fileresponse--fileresponse-) for sending binary data, instead of encoding it in JSON. +Consider first if you can use [Request Files](../tutorial/request-files.md) for uploading binary data and [Custom Response - FileResponse](./custom-response.md#fileresponse) for sending binary data, instead of encoding it in JSON. JSON can only contain UTF-8 encoded strings, so it can't contain raw bytes. diff --git a/docs/en/docs/advanced/openapi-callbacks.md b/docs/en/docs/advanced/openapi-callbacks.md index 40cf47956..17910e1cf 100644 --- a/docs/en/docs/advanced/openapi-callbacks.md +++ b/docs/en/docs/advanced/openapi-callbacks.md @@ -4,7 +4,7 @@ You could create an API with a *path operation* that could trigger a request to The process that happens when your API app calls the *external API* is named a "callback". Because the software that the external developer wrote sends a request to your API and then your API *calls back*, sending a request to an *external API* (that was probably created by the same developer). -In this case, you could want to document how that external API *should* look like. What *path operation* it should have, what body it should expect, what response it should return, etc. +In this case, you could want to document how that external API *should* look. What *path operation* it should have, what body it should expect, what response it should return, etc. ## An app with callbacks { #an-app-with-callbacks } @@ -25,7 +25,7 @@ Then your API will (let's imagine): ## The normal **FastAPI** app { #the-normal-fastapi-app } -Let's first see how the normal API app would look like before adding the callback. +Let's first see how the normal API app would look before adding the callback. It will have a *path operation* that will receive an `Invoice` body, and a query parameter `callback_url` that will contain the URL for the callback. @@ -56,7 +56,7 @@ httpx.post(callback_url, json={"description": "Invoice paid", "paid": True}) But possibly the most important part of the callback is making sure that your API user (the external developer) implements the *external API* correctly, according to the data that *your API* is going to send in the request body of the callback, etc. -So, what we will do next is add the code to document how that *external API* should look like to receive the callback from *your API*. +So, what we will do next is add the code to document how that *external API* should look to receive the callback from *your API*. That documentation will show up in the Swagger UI at `/docs` in your API, and it will let external developers know how to build the *external API*. @@ -72,11 +72,11 @@ When implementing the callback yourself, you could use something like [HTTPX](ht ## Write the callback documentation code { #write-the-callback-documentation-code } -This code won't be executed in your app, we only need it to *document* how that *external API* should look like. +This code won't be executed in your app, we only need it to *document* how that *external API* should look. But, you already know how to easily create automatic documentation for an API with **FastAPI**. -So we are going to use that same knowledge to document how the *external API* should look like... by creating the *path operation(s)* that the external API should implement (the ones your API will call). +So we are going to use that same knowledge to document how the *external API* should look... by creating the *path operation(s)* that the external API should implement (the ones your API will call). /// tip @@ -167,13 +167,13 @@ Notice how the callback URL used contains the URL received as a query parameter At this point you have the *callback path operation(s)* needed (the one(s) that the *external developer* should implement in the *external API*) in the callback router you created above. -Now use the parameter `callbacks` in *your API's path operation decorator* to pass the attribute `.routes` (that's actually just a `list` of routes/*path operations*) from that callback router: +Now use the parameter `callbacks` in *your API's path operation decorator* to pass the attribute `.routes` from that callback router: {* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[33] *} /// tip -Notice that you are not passing the router itself (`invoices_callback_router`) to `callback=`, but the attribute `.routes`, as in `invoices_callback_router.routes`. +Notice that you are not passing the router itself (`invoices_callback_router`) to `callbacks=`, but its `.routes`, as in `invoices_callback_router.routes`. FastAPI will use those routes to generate the callback OpenAPI documentation. /// @@ -181,6 +181,6 @@ Notice that you are not passing the router itself (`invoices_callback_router`) t Now you can start your app and go to [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs). -You will see your docs including a "Callbacks" section for your *path operation* that shows how the *external API* should look like: +You will see your docs including a "Callbacks" section for your *path operation* that shows how the *external API* should look: diff --git a/docs/en/docs/advanced/path-operation-advanced-configuration.md b/docs/en/docs/advanced/path-operation-advanced-configuration.md index 800bf305d..9dca4d712 100644 --- a/docs/en/docs/advanced/path-operation-advanced-configuration.md +++ b/docs/en/docs/advanced/path-operation-advanced-configuration.md @@ -16,17 +16,11 @@ You would have to make sure that it is unique for each operation. ### Using the *path operation function* name as the operationId { #using-the-path-operation-function-name-as-the-operationid } -If you want to use your APIs' function names as `operationId`s, you can iterate over all of them and override each *path operation's* `operation_id` using their `APIRoute.name`. +If you want to use your APIs' function names as `operationId`s, you can pass a custom `generate_unique_id_function` to `FastAPI`. -You should do it after adding all your *path operations*. +The function receives each `APIRoute` and returns the `operationId` to use for that path operation. -{* ../../docs_src/path_operation_advanced_configuration/tutorial002_py310.py hl[2, 12:21, 24] *} - -/// tip - -If you manually call `app.openapi()`, you should update the `operationId`s before that. - -/// +{* ../../docs_src/path_operation_advanced_configuration/tutorial002_py310.py hl[2,5:6,9] *} /// warning diff --git a/docs/en/docs/advanced/response-change-status-code.md b/docs/en/docs/advanced/response-change-status-code.md index 8efd63198..747016722 100644 --- a/docs/en/docs/advanced/response-change-status-code.md +++ b/docs/en/docs/advanced/response-change-status-code.md @@ -18,7 +18,7 @@ For those cases, you can use a `Response` parameter. You can declare a parameter of type `Response` in your *path operation function* (as you can do for cookies and headers). -And then you can set the `status_code` in that *temporal* response object. +And then you can set the `status_code` in that *temporary* response object. {* ../../docs_src/response_change_status_code/tutorial001_py310.py hl[1,9,12] *} @@ -26,6 +26,6 @@ And then you can return any object you need, as you normally would (a `dict`, a And if you declared a `response_model`, it will still be used to filter and convert the object you returned. -**FastAPI** will use that *temporal* response to extract the status code (also cookies and headers), and will put them in the final response that contains the value you returned, filtered by any `response_model`. +**FastAPI** will use that *temporary* response to extract the status code (also cookies and headers), and will put them in the final response that contains the value you returned, filtered by any `response_model`. You can also declare the `Response` parameter in dependencies, and set the status code in them. But keep in mind that the last one to be set will win. diff --git a/docs/en/docs/advanced/response-cookies.md b/docs/en/docs/advanced/response-cookies.md index a7ad90cad..f523a5c63 100644 --- a/docs/en/docs/advanced/response-cookies.md +++ b/docs/en/docs/advanced/response-cookies.md @@ -4,7 +4,7 @@ You can declare a parameter of type `Response` in your *path operation function*. -And then you can set cookies in that *temporal* response object. +And then you can set cookies in that *temporary* response object. {* ../../docs_src/response_cookies/tutorial002_py310.py hl[1, 8:9] *} @@ -12,7 +12,7 @@ And then you can return any object you need, as you normally would (a `dict`, a And if you declared a `response_model`, it will still be used to filter and convert the object you returned. -**FastAPI** will use that *temporal* response to extract the cookies (also headers and status code), and will put them in the final response that contains the value you returned, filtered by any `response_model`. +**FastAPI** will use that *temporary* response to extract the cookies (also headers and status code), and will put them in the final response that contains the value you returned, filtered by any `response_model`. You can also declare the `Response` parameter in dependencies, and set cookies (and headers) in them. diff --git a/docs/en/docs/advanced/response-headers.md b/docs/en/docs/advanced/response-headers.md index d7738635d..cbc28e495 100644 --- a/docs/en/docs/advanced/response-headers.md +++ b/docs/en/docs/advanced/response-headers.md @@ -4,7 +4,7 @@ You can declare a parameter of type `Response` in your *path operation function* (as you can do for cookies). -And then you can set headers in that *temporal* response object. +And then you can set headers in that *temporary* response object. {* ../../docs_src/response_headers/tutorial002_py310.py hl[1, 7:8] *} @@ -12,7 +12,7 @@ And then you can return any object you need, as you normally would (a `dict`, a And if you declared a `response_model`, it will still be used to filter and convert the object you returned. -**FastAPI** will use that *temporal* response to extract the headers (also cookies and status code), and will put them in the final response that contains the value you returned, filtered by any `response_model`. +**FastAPI** will use that *temporary* response to extract the headers (also cookies and status code), and will put them in the final response that contains the value you returned, filtered by any `response_model`. You can also declare the `Response` parameter in dependencies, and set headers (and cookies) in them. diff --git a/docs/en/docs/advanced/security/oauth2-scopes.md b/docs/en/docs/advanced/security/oauth2-scopes.md index 92b604757..60e900d2c 100644 --- a/docs/en/docs/advanced/security/oauth2-scopes.md +++ b/docs/en/docs/advanced/security/oauth2-scopes.md @@ -194,11 +194,11 @@ For this, we use `security_scopes.scopes`, that contains a `list` with all these Let's review again this dependency tree and the scopes. -As the `get_current_active_user` dependency has as a sub-dependency on `get_current_user`, the scope `"me"` declared at `get_current_active_user` will be included in the list of required scopes in the `security_scopes.scopes` passed to `get_current_user`. +As the `get_current_active_user` dependency has `get_current_user` as a sub-dependency, the scope `"me"` declared at `get_current_active_user` will be included in the list of required scopes in the `security_scopes.scopes` passed to `get_current_user`. The *path operation* itself also declares a scope, `"items"`, so this will also be in the list of `security_scopes.scopes` passed to `get_current_user`. -Here's how the hierarchy of dependencies and scopes looks like: +Here's what the hierarchy of dependencies and scopes looks like: * The *path operation* `read_own_items` has: * Required scopes `["items"]` with the dependency: diff --git a/docs/en/docs/advanced/settings.md b/docs/en/docs/advanced/settings.md index f0f3bb41d..ff313f088 100644 --- a/docs/en/docs/advanced/settings.md +++ b/docs/en/docs/advanced/settings.md @@ -14,7 +14,7 @@ To understand environment variables you can read [Environment Variables](../envi ## Types and validation { #types-and-validation } -These environment variables can only handle text strings, as they are external to Python and have to be compatible with other programs and the rest of the system (and even with different operating systems, as Linux, Windows, macOS). +These environment variables can only handle text strings, as they are external to Python and have to be compatible with other programs and the rest of the system (and even with different operating systems, such as Linux, Windows, and macOS). That means that any value read in Python from an environment variable will be a `str`, and any conversion to a different type or any validation has to be done in code. diff --git a/docs/en/docs/advanced/stream-data.md b/docs/en/docs/advanced/stream-data.md index 3e7c89a93..40ea33743 100644 --- a/docs/en/docs/advanced/stream-data.md +++ b/docs/en/docs/advanced/stream-data.md @@ -14,7 +14,7 @@ Added in FastAPI 0.134.0. You could use this if you want to stream pure strings, for example directly from the output of an **AI LLM** service. -You could also use it to stream **large binary files**, where you stream each chunk of data as you read it, without having to read it all in memory at once. +You could also use it to stream **large binary files**, where you stream each chunk of data as you read it, without having to read it all into memory at once. You could also stream **video** or **audio** this way, it could even be generated as you process and send it. diff --git a/docs/en/docs/advanced/wsgi.md b/docs/en/docs/advanced/wsgi.md index 39a492eb6..8dcc3c401 100644 --- a/docs/en/docs/advanced/wsgi.md +++ b/docs/en/docs/advanced/wsgi.md @@ -24,7 +24,7 @@ And then mount that under a path. Previously, it was recommended to use `WSGIMiddleware` from `fastapi.middleware.wsgi`, but it is now deprecated. -It’s advised to use the `a2wsgi` package instead. The usage remains the same. +It's advised to use the `a2wsgi` package instead. The usage remains the same. Just ensure that you have the `a2wsgi` package installed and import `WSGIMiddleware` correctly from `a2wsgi`. diff --git a/docs/en/docs/alternatives.md b/docs/en/docs/alternatives.md index 0e7dc8571..d4942a37b 100644 --- a/docs/en/docs/alternatives.md +++ b/docs/en/docs/alternatives.md @@ -24,7 +24,7 @@ It was created to generate the HTML in the backend, not to create APIs used by a ### [Django REST Framework](https://www.django-rest-framework.org/) { #django-rest-framework } -Django REST framework was created to be a flexible toolkit for building Web APIs using Django underneath, to improve its API capabilities. +Django REST Framework was created to be a flexible toolkit for building Web APIs using Django underneath, to improve its API capabilities. It is used by many companies including Mozilla, Red Hat and Eventbrite. @@ -345,7 +345,7 @@ Hug was created by Timothy Crosley, the same creator of [`isort`](https://github Hug inspired parts of APIStar, and was one of the tools I found most promising, alongside APIStar. -Hug helped inspiring **FastAPI** to use Python type hints to declare parameters, and to generate a schema defining the API automatically. +Hug helped inspire **FastAPI** to use Python type hints to declare parameters, and to generate a schema defining the API automatically. Hug inspired **FastAPI** to declare a `response` parameter in functions to set headers and cookies. @@ -380,7 +380,7 @@ Now APIStar is a set of tools to validate OpenAPI specifications, not a web fram APIStar was created by Tom Christie. The same guy that created: * Django REST Framework -* Starlette (in which **FastAPI** is based) +* Starlette (on which **FastAPI** is based) * Uvicorn (used by Starlette and **FastAPI**) /// @@ -393,7 +393,7 @@ The idea of declaring multiple things (data validation, serialization and docume And after searching for a long time for a similar framework and testing many different alternatives, APIStar was the best option available. -Then APIStar stopped to exist as a server and Starlette was created, and was a new better foundation for such a system. That was the final inspiration to build **FastAPI**. +Then APIStar stopped existing as a server and Starlette was created, and was a new better foundation for such a system. That was the final inspiration to build **FastAPI**. I consider **FastAPI** a "spiritual successor" to APIStar, while improving and increasing the features, typing system, and other parts, based on the learnings from all these previous tools. diff --git a/docs/en/docs/async.md b/docs/en/docs/async.md index 1ad996034..d975ddb53 100644 --- a/docs/en/docs/async.md +++ b/docs/en/docs/async.md @@ -70,7 +70,7 @@ Asynchronous code just means that the language 💬 has a way to tell the comput So, during that time, the computer can go and do some other work, while "slow-file" 📝 finishes. -Then the computer / program 🤖 will come back every time it has a chance because it's waiting again, or whenever it 🤖 finished all the work it had at that point. And it 🤖 will see if any of the tasks it was waiting for have already finished, doing whatever it had to do. +Then the computer / program 🤖 will come back every time it has a chance because it's waiting again, or whenever it 🤖 finishes all the work it had at that point. And it 🤖 will see if any of the tasks it was waiting for have already finished, doing whatever it had to do. Next, it 🤖 takes the first task to finish (let's say, our "slow-file" 📝) and continues whatever it had to do with it. @@ -78,7 +78,7 @@ That "wait for something else" normally refers to - -```console -$ fastapi login - -You are logged in to FastAPI Cloud 🚀 -``` - - - -## Deploy { #deploy } - -Now deploy your app, with **one command**: +You can deploy your FastAPI app to [FastAPI Cloud](https://fastapicloud.com) with just **one command**. 🚀
@@ -36,6 +16,8 @@ Deploying to FastAPI Cloud...
+The CLI will automatically detect your FastAPI application and deploy it to the cloud. If you are not logged in, your browser will open to complete the authentication process. + That's it! Now you can access your app at that URL. ✨ ## About FastAPI Cloud { #about-fastapi-cloud } diff --git a/docs/en/docs/deployment/https.md b/docs/en/docs/deployment/https.md index 886dfbe78..8280c1173 100644 --- a/docs/en/docs/deployment/https.md +++ b/docs/en/docs/deployment/https.md @@ -59,7 +59,7 @@ The idea is to automate the acquisition and renewal of these certificates so tha ## HTTPS for Developers { #https-for-developers } -Here's an example of how an HTTPS API could look like, step by step, paying attention mainly to the ideas important for developers. +Here's an example of how an HTTPS API could look, step by step, paying attention mainly to the ideas important for developers. ### Domain Name { #domain-name } diff --git a/docs/en/docs/deployment/manually.md b/docs/en/docs/deployment/manually.md index 47af49ea6..ed49aa00a 100644 --- a/docs/en/docs/deployment/manually.md +++ b/docs/en/docs/deployment/manually.md @@ -93,7 +93,7 @@ A similar process would apply to any other ASGI server program. By adding the `standard`, Uvicorn will install and use some recommended extra dependencies. -That including `uvloop`, the high-performance drop-in replacement for `asyncio`, that provides the big concurrency performance boost. +That includes `uvloop`, the high-performance drop-in replacement for `asyncio`, that provides the big concurrency performance boost. When you install FastAPI with something like `pip install "fastapi[standard]"` you already get `uvicorn[standard]` as well. diff --git a/docs/en/docs/editor-support.md b/docs/en/docs/editor-support.md index 4f74cf131..0936456eb 100644 --- a/docs/en/docs/editor-support.md +++ b/docs/en/docs/editor-support.md @@ -20,4 +20,4 @@ By default, the extension will automatically discover FastAPI applications in yo - **Deploy to FastAPI Cloud** - One-click deployment of your app to [FastAPI Cloud](https://fastapicloud.com/). - **Stream Application Logs** - Real-time log streaming from your FastAPI Cloud-deployed application with level filtering and text search. -If you'd like to familiarize yourself with the extension's features, you can checkout the extension walkthrough by opening the Command Palette (Ctrl + Shift + P or on macOS: Cmd + Shift + P) and selecting "Welcome: Open walkthrough..." and then choosing the "Get started with FastAPI" walkthrough. +If you'd like to familiarize yourself with the extension's features, you can check out the extension walkthrough by opening the Command Palette (Ctrl + Shift + P or on macOS: Cmd + Shift + P) and selecting "Welcome: Open walkthrough..." and then choosing the "Get started with FastAPI" walkthrough. diff --git a/docs/en/docs/environment-variables.md b/docs/en/docs/environment-variables.md index 91bc25671..f0446473a 100644 --- a/docs/en/docs/environment-variables.md +++ b/docs/en/docs/environment-variables.md @@ -159,7 +159,7 @@ You can read more about it at [The Twelve-Factor App: Config](https://12factor.n ## Types and Validation { #types-and-validation } -These environment variables can only handle **text strings**, as they are external to Python and have to be compatible with other programs and the rest of the system (and even with different operating systems, as Linux, Windows, macOS). +These environment variables can only handle **text strings**, as they are external to Python and have to be compatible with other programs and the rest of the system (and even with different operating systems, such as Linux, Windows, and macOS). That means that **any value** read in Python from an environment variable **will be a `str`**, and any conversion to a different type or any validation has to be done in code. diff --git a/docs/en/docs/external-links.md b/docs/en/docs/external-links.md index e1614e818..d614c64eb 100644 --- a/docs/en/docs/external-links.md +++ b/docs/en/docs/external-links.md @@ -7,7 +7,7 @@ include_yaml: **FastAPI** has a great community constantly growing. -There are many posts, articles, tools, and projects, related to **FastAPI**. +There are many posts, articles, tools, and projects related to **FastAPI**. You could easily use a search engine or video platform to find many resources related to FastAPI. diff --git a/docs/en/docs/fastapi-people.md b/docs/en/docs/fastapi-people.md index ad32966e5..e79928fb3 100644 --- a/docs/en/docs/fastapi-people.md +++ b/docs/en/docs/fastapi-people.md @@ -31,7 +31,7 @@ This is me: -I'm the creator of **FastAPI**. You can read more about that in [Help FastAPI - Get Help - Connect with the author](help-fastapi.md#connect-with-the-author). +I'm the creator of **FastAPI**. You can read more about that in [Help FastAPI - Follow the author](help-fastapi.md#follow-the-author). ...But here I want to show you the community. @@ -42,9 +42,8 @@ I'm the creator of **FastAPI**. You can read more about that in [Help FastAPI - These are the people that: * [Help others with questions in GitHub](help-fastapi.md#help-others-with-questions-in-github). -* [Create Pull Requests](help-fastapi.md#create-a-pull-request). -* Review Pull Requests, [especially important for translations](contributing.md#translations). -* Help [manage the repository](management-tasks.md) (team members). +* Create or review Pull Requests. +* Help [manage the repository](https://tiangolo.com/open-source/management-tasks/) (team members). All these tasks help maintain the repository. @@ -54,7 +53,7 @@ A round of applause to them. 👏 🙇 This is the current list of team members. 😎 -They have different levels of involvement and permissions, they can perform [repository management tasks](./management-tasks.md) and together we [manage the FastAPI repository](./management.md). +They have different levels of involvement and permissions, they can perform [repository management tasks](https://tiangolo.com/open-source/management-tasks/) and together we [manage the FastAPI repository](./management.md).
@@ -66,7 +65,7 @@ They have different levels of involvement and permissions, they can perform [rep
-Although the team members have the permissions to perform privileged tasks, all the [help from others maintaining FastAPI](./help-fastapi.md#help-maintain-fastapi) is very much appreciated! 🙇‍♂️ +Although the team members have the permissions to perform privileged tasks, all the help from others maintaining FastAPI is very much appreciated! 🙇‍♂️ ## FastAPI Experts @@ -186,7 +185,7 @@ These are the users that have [helped others the most with questions in GitHub]( Here are the **Top Contributors**. 👷 -These users have [created the most Pull Requests](help-fastapi.md#create-a-pull-request) that have been *merged*. +These users have created the most Pull Requests that have been *merged*. They have contributed source code, documentation, etc. 📦 @@ -210,7 +209,7 @@ There are hundreds of other contributors, you can see them all in the [FastAPI G These users are the **Top Translation Reviewers**. 🕵️ -Translation reviewers have the [**power to approve translations**](contributing.md#translations) of the documentation. Without them, there wouldn't be documentation in several other languages. +Translation reviewers have the **power to approve translations** of the documentation. Without them, there wouldn't be documentation in several other languages.
{% for user in (translation_reviewers.values() | list)[:50] %} diff --git a/docs/en/docs/features.md b/docs/en/docs/features.md index a1a271d28..b4cafd00a 100644 --- a/docs/en/docs/features.md +++ b/docs/en/docs/features.md @@ -73,11 +73,11 @@ Pass the keys and values of the `second_user_data` dict directly as key-value ar ### Editor support { #editor-support } -All the framework was designed to be easy and intuitive to use, all the decisions were tested on multiple editors even before starting development, to ensure the best development experience. +The whole framework was designed to be easy and intuitive to use, all the decisions were tested on multiple editors even before starting development, to ensure the best development experience. In the Python developer surveys, it's clear [that one of the most used features is "autocompletion"](https://www.jetbrains.com/research/python-developers-survey-2017/#tools-and-features). -The whole **FastAPI** framework is based to satisfy that. Autocompletion works everywhere. +The whole **FastAPI** framework is designed to satisfy that. Autocompletion works everywhere. You will rarely need to come back to the docs. @@ -147,7 +147,7 @@ FastAPI includes an extremely easy to use, but extremely powerful ORMs, ODMs for databases. +Including external libraries also based on Pydantic, such as ORMs and ODMs for databases. This also means that in many cases you can pass the same object you get from a request **directly to the database**, as everything is validated automatically. diff --git a/docs/en/docs/help-fastapi.md b/docs/en/docs/help-fastapi.md index 3fcd400e7..14bd05646 100644 --- a/docs/en/docs/help-fastapi.md +++ b/docs/en/docs/help-fastapi.md @@ -26,7 +26,7 @@ You can follow **FastAPI** online in several places: You can "star" FastAPI in GitHub (clicking the star button at the top right): [https://github.com/fastapi/fastapi](https://github.com/fastapi/fastapi). ⭐️ -By adding a star, other users will be able to find it more easily and see that it has been already useful for others. +By adding a star, other users will be able to find it more easily and see that it has already been useful for others. ## Watch the GitHub repository for releases { #watch-the-github-repository-for-releases } diff --git a/docs/en/docs/how-to/configure-swagger-ui.md b/docs/en/docs/how-to/configure-swagger-ui.md index 7c3d9cb25..c7cacd97e 100644 --- a/docs/en/docs/how-to/configure-swagger-ui.md +++ b/docs/en/docs/how-to/configure-swagger-ui.md @@ -67,4 +67,4 @@ presets: [ These are **JavaScript** objects, not strings, so you can't pass them from Python code directly. -If you need to use JavaScript-only configurations like those, you can use one of the methods above. Override all the Swagger UI *path operation* and manually write any JavaScript you need. +If you need to use JavaScript-only configurations like those, you can use one of the methods above. Override the whole Swagger UI *path operation* and manually write any JavaScript you need. diff --git a/docs/en/docs/how-to/custom-request-and-route.md b/docs/en/docs/how-to/custom-request-and-route.md index bce232017..2b353d9b4 100644 --- a/docs/en/docs/how-to/custom-request-and-route.md +++ b/docs/en/docs/how-to/custom-request-and-route.md @@ -94,7 +94,7 @@ All we need to do is handle the request inside a `try`/`except` block: {* ../../docs_src/custom_request_and_route/tutorial002_an_py310.py hl[14,16] *} -If an exception occurs, the`Request` instance will still be in scope, so we can read and make use of the request body when handling the error: +If an exception occurs, the `Request` instance will still be in scope, so we can read and make use of the request body when handling the error: {* ../../docs_src/custom_request_and_route/tutorial002_an_py310.py hl[17:19] *} diff --git a/docs/en/docs/how-to/extending-openapi.md b/docs/en/docs/how-to/extending-openapi.md index 65f584438..8368eea50 100644 --- a/docs/en/docs/how-to/extending-openapi.md +++ b/docs/en/docs/how-to/extending-openapi.md @@ -25,7 +25,15 @@ And that function `get_openapi()` receives as parameters: * `openapi_version`: The version of the OpenAPI specification used. By default, the latest: `3.1.0`. * `summary`: A short summary of the API. * `description`: The description of your API, this can include markdown and will be shown in the docs. -* `routes`: A list of routes, these are each of the registered *path operations*. They are taken from `app.routes`. +* `routes`: The routes from the application, taken from `app.routes`. FastAPI uses them to collect the registered *path operations*, including those from included routers. + +/// tip | Technical Details + +`app.routes` is a lower-level route tree. It can include route candidates that FastAPI uses internally for included routers, not only final `APIRoute` objects. + +You can still pass `app.routes` to `get_openapi()`. FastAPI will traverse that route tree to collect the effective path operations. + +/// /// note diff --git a/docs/en/docs/how-to/graphql.md b/docs/en/docs/how-to/graphql.md index 2d93876f3..de149a74a 100644 --- a/docs/en/docs/how-to/graphql.md +++ b/docs/en/docs/how-to/graphql.md @@ -57,4 +57,4 @@ If you need GraphQL, I still would recommend you check out [Strawberry](https:// You can learn more about **GraphQL** in the [official GraphQL documentation](https://graphql.org/). -You can also read more about each those libraries described above in their links. +You can also read more about each of those libraries described above in their links. diff --git a/docs/en/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md b/docs/en/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md index 99d3835c3..816cf54f5 100644 --- a/docs/en/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md +++ b/docs/en/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md @@ -8,6 +8,8 @@ FastAPI version 0.119.0 introduced partial support for Pydantic v1 from inside o FastAPI 0.126.0 dropped support for Pydantic v1, while still supporting `pydantic.v1` for a little while. +FastAPI 0.128.0 dropped support for `pydantic.v1` as well, so the latest versions of FastAPI require Pydantic v2. + /// warning The Pydantic team stopped support for Pydantic v1 for the latest versions of Python, starting with **Python 3.14**. @@ -54,6 +56,16 @@ This means that you can install the latest version of Pydantic v2 and import and ### FastAPI support for Pydantic v1 in v2 { #fastapi-support-for-pydantic-v1-in-v2 } +/// warning + +This FastAPI support for `pydantic.v1` models was added in **FastAPI 0.119.0** and removed in **FastAPI 0.128.0**. It was meant to be a temporary aid for the migration to Pydantic v2. + +In current versions of FastAPI, using a `pydantic.v1` model in your app will raise an error. + +The rest of this section describes the temporary support available only in those older versions. + +/// + Since FastAPI 0.119.0, there's also partial support for Pydantic v1 from inside of Pydantic v2, to facilitate the migration to v2. So, you could upgrade Pydantic to the latest version 2, and change the imports to use the `pydantic.v1` submodule, and in many cases it would just work. @@ -88,7 +100,7 @@ graph TB style V2Field fill:#f9fff3 ``` -...but, you can have separated models using Pydantic v1 and v2 in the same app. +...but you can have separate models, some using Pydantic v1 and others using Pydantic v2, in the same app. ```mermaid graph TB @@ -122,6 +134,12 @@ If you need to use some of the FastAPI-specific tools for parameters like `Body` ### Migrate in steps { #migrate-in-steps } +/// warning + +The gradual migration using both Pydantic v1 and v2 models in the same app described below only works in **FastAPI 0.119.0 to 0.127.x**. It was removed in **FastAPI 0.128.0**, the latest versions require **Pydantic v2** models. + +/// + /// tip First try with `bump-pydantic`, if your tests pass and that works, then you're done in one command. ✨ @@ -130,6 +148,6 @@ First try with `bump-pydantic`, if your tests pass and that works, then you're d If `bump-pydantic` doesn't work for your use case, you can use the support for both Pydantic v1 and v2 models in the same app to do the migration to Pydantic v2 gradually. -You could fist upgrade Pydantic to use the latest version 2, and change the imports to use `pydantic.v1` for all your models. +You could first upgrade Pydantic to use the latest version 2, and change the imports to use `pydantic.v1` for all your models. Then, you can start migrating your models from Pydantic v1 to v2 in groups, in gradual steps. 🚶 diff --git a/docs/en/docs/how-to/separate-openapi-schemas.md b/docs/en/docs/how-to/separate-openapi-schemas.md index 4eb684dc9..66755f8b7 100644 --- a/docs/en/docs/how-to/separate-openapi-schemas.md +++ b/docs/en/docs/how-to/separate-openapi-schemas.md @@ -46,7 +46,7 @@ If you interact with the docs and check the response, even though the code didn' This means that it will **always have a value**, it's just that sometimes the value could be `None` (or `null` in JSON). -That means that, clients using your API don't have to check if the value exists or not, they can **assume the field will always be there**, but just that in some cases it will have the default value of `None`. +That means that clients using your API don't have to check if the value exists or not, they can **assume the field will always be there**, but just that in some cases it will have the default value of `None`. The way to describe this in OpenAPI, is to mark that field as **required**, because it will always be there. diff --git a/docs/en/docs/img/sponsors/bairesdev.svg b/docs/en/docs/img/sponsors/bairesdev.svg new file mode 100644 index 000000000..c982d4e0e --- /dev/null +++ b/docs/en/docs/img/sponsors/bairesdev.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/docs/en/docs/index.md b/docs/en/docs/index.md index 0aeee755e..7baeaab26 100644 --- a/docs/en/docs/index.md +++ b/docs/en/docs/index.md @@ -477,13 +477,13 @@ For a more complete example including more features, see the Dependency Injection** system. * Security and authentication, including support for **OAuth2** with **JWT tokens** and **HTTP Basic** auth. * More advanced (but equally easy) techniques for declaring **deeply nested JSON models** (thanks to Pydantic). * **GraphQL** integration with [Strawberry](https://strawberry.rocks) and other libraries. -* Many extra features (thanks to Starlette) as: +* Many extra features (thanks to Starlette) such as: * **WebSockets** * extremely easy tests based on HTTPX and `pytest` * **CORS** @@ -492,9 +492,7 @@ For a more complete example including more features, see the @@ -510,6 +508,8 @@ Deploying to FastAPI Cloud...
+The CLI will automatically detect your FastAPI application and deploy it to the cloud. If you are not logged in, your browser will open to complete the authentication process. + That's it! Now you can access your app at that URL. ✨ #### About FastAPI Cloud { #about-fastapi-cloud } diff --git a/docs/en/docs/project-generation.md b/docs/en/docs/project-generation.md index 23e798ba9..ab6e87527 100644 --- a/docs/en/docs/project-generation.md +++ b/docs/en/docs/project-generation.md @@ -2,7 +2,7 @@ Templates, while they typically come with a specific setup, are designed to be flexible and customizable. This allows you to modify and adapt them to your project's requirements, making them an excellent starting point. 🏁 -You can use this template to get started, as it includes a lot of the initial set up, security, database and some API endpoints already done for you. +You can use this template to get started, as it includes a lot of the initial setup, security, database and some API endpoints already done for you. GitHub Repository: [Full Stack FastAPI Template](https://github.com/tiangolo/full-stack-fastapi-template) diff --git a/docs/en/docs/python-types.md b/docs/en/docs/python-types.md index 976129117..c8d9bf41c 100644 --- a/docs/en/docs/python-types.md +++ b/docs/en/docs/python-types.md @@ -2,7 +2,7 @@ Python has support for optional "type hints" (also called "type annotations"). -These **"type hints"** or annotations are a special syntax that allow declaring the type of a variable. +These **"type hints"** or annotations are a special syntax that allows declaring the type of a variable. By declaring types for your variables, editors and tools can give you better support. @@ -44,7 +44,7 @@ It's a very simple program. But now imagine that you were writing it from scratch. -At some point you would have started the definition of the function, you had the parameters ready... +At some point you start defining the function, and you have the parameters ready... But then you have to call "that method that converts the first letter to upper case". @@ -80,7 +80,7 @@ Those are the "type hints": {* ../../docs_src/python_types/tutorial002_py310.py hl[1] *} -That is not the same as declaring default values like would be with: +That is not the same as declaring default values like it would be with: ```Python first_name="john", last_name="doe" diff --git a/docs/en/docs/reference/apirouter.md b/docs/en/docs/reference/apirouter.md index d77364e45..819366dfb 100644 --- a/docs/en/docs/reference/apirouter.md +++ b/docs/en/docs/reference/apirouter.md @@ -13,6 +13,7 @@ from fastapi import APIRouter members: - websocket - include_router + - frontend - get - put - post diff --git a/docs/en/docs/reference/fastapi.md b/docs/en/docs/reference/fastapi.md index d5367ff34..e8ec991e5 100644 --- a/docs/en/docs/reference/fastapi.md +++ b/docs/en/docs/reference/fastapi.md @@ -18,6 +18,7 @@ from fastapi import FastAPI - openapi - websocket - include_router + - frontend - get - put - post diff --git a/docs/en/docs/reference/status.md b/docs/en/docs/reference/status.md index 6e0e816d3..16af90e0f 100644 --- a/docs/en/docs/reference/status.md +++ b/docs/en/docs/reference/status.md @@ -16,7 +16,7 @@ For example: * 403: `status.HTTP_403_FORBIDDEN` * etc. -It can be convenient to quickly access HTTP (and WebSocket) status codes in your app, using autocompletion for the name without having to remember the integer status codes by memory. +It can be convenient to quickly access HTTP (and WebSocket) status codes in your app, using autocompletion for the name without having to memorize the integer status codes. Read more about it in the [FastAPI docs about Response Status Code](https://fastapi.tiangolo.com/tutorial/response-status-code/). diff --git a/docs/en/docs/reference/websockets.md b/docs/en/docs/reference/websockets.md index bd9f438be..b1158b387 100644 --- a/docs/en/docs/reference/websockets.md +++ b/docs/en/docs/reference/websockets.md @@ -50,7 +50,7 @@ When you want to define dependencies that should be compatible with both HTTP an Additional classes for handling WebSockets. -Provided directly by Starlette, but you can import it from `fastapi`: +Provided directly by Starlette, but you can import them from `fastapi`: ```python from fastapi.websockets import WebSocketDisconnect, WebSocketState @@ -60,7 +60,7 @@ from fastapi.websockets import WebSocketDisconnect, WebSocketState When a client disconnects, a `WebSocketDisconnect` exception is raised, you can catch it. -You can import it directly form `fastapi`: +You can import it directly from `fastapi`: ```python from fastapi import WebSocketDisconnect diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 1ab8e490c..eb72ce6f7 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -7,8 +7,194 @@ hide: ## Latest Changes +### Translations + +* 🌐 Update translations for fr (update-outdated). PR [#15897](https://github.com/fastapi/fastapi/pull/15897) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for ja (update-outdated). PR [#15895](https://github.com/fastapi/fastapi/pull/15895) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for zh-hant (update-outdated). PR [#15896](https://github.com/fastapi/fastapi/pull/15896) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for de (update-outdated). PR [#15899](https://github.com/fastapi/fastapi/pull/15899) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for es (update-outdated). PR [#15892](https://github.com/fastapi/fastapi/pull/15892) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for tr (update-outdated). PR [#15891](https://github.com/fastapi/fastapi/pull/15891) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for pt (update-outdated). PR [#15893](https://github.com/fastapi/fastapi/pull/15893) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for zh (update-outdated). PR [#15898](https://github.com/fastapi/fastapi/pull/15898) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for uk (update-outdated). PR [#15900](https://github.com/fastapi/fastapi/pull/15900) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for ko (update-outdated). PR [#15890](https://github.com/fastapi/fastapi/pull/15890) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for ru (update-outdated). PR [#15894](https://github.com/fastapi/fastapi/pull/15894) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for ko (add-missing). PR [#15888](https://github.com/fastapi/fastapi/pull/15888) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for es (add-missing). PR [#15880](https://github.com/fastapi/fastapi/pull/15880) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for zh-hant (add-missing). PR [#15889](https://github.com/fastapi/fastapi/pull/15889) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for pt (add-missing). PR [#15883](https://github.com/fastapi/fastapi/pull/15883) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for zh (add-missing). PR [#15885](https://github.com/fastapi/fastapi/pull/15885) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for ja (add-missing). PR [#15882](https://github.com/fastapi/fastapi/pull/15882) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for tr (add-missing). PR [#15887](https://github.com/fastapi/fastapi/pull/15887) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for uk (add-missing). PR [#15886](https://github.com/fastapi/fastapi/pull/15886) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for fr (add-missing). PR [#15881](https://github.com/fastapi/fastapi/pull/15881) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for de (add-missing). PR [#15884](https://github.com/fastapi/fastapi/pull/15884) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for ru (add-missing). PR [#15879](https://github.com/fastapi/fastapi/pull/15879) by [@tiangolo](https://github.com/tiangolo). + +### Internal + +* 👥 Update FastAPI GitHub topic repositories. PR [#15906](https://github.com/fastapi/fastapi/pull/15906) by [@tiangolo](https://github.com/tiangolo). +* 👥 Update FastAPI People - Contributors and Translators. PR [#15878](https://github.com/fastapi/fastapi/pull/15878) by [@tiangolo](https://github.com/tiangolo). +* 👷 Remove not needed `allow-unsafe-pr-checkout: true`. PR [#15876](https://github.com/fastapi/fastapi/pull/15876) by [@YuriiMotov](https://github.com/YuriiMotov). +* ⬆ Bump the github-actions group with 5 updates. PR [#15872](https://github.com/fastapi/fastapi/pull/15872) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump the python-packages group across 1 directory with 10 updates. PR [#15870](https://github.com/fastapi/fastapi/pull/15870) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump CodSpeedHQ/action from 4.17.0 to 4.17.5 in the github-actions group. PR [#15826](https://github.com/fastapi/fastapi/pull/15826) by [@dependabot[bot]](https://github.com/apps/dependabot). + +## 0.138.2 (2026-06-29) + +### Refactors + +* ♻️ Make `app.frontend()` return 404 for methods other than `GET` or `HEAD` with no static file matches. PR [#15863](https://github.com/fastapi/fastapi/pull/15863) by [@tiangolo](https://github.com/tiangolo). + +### Internal + +* 🔧 Update sponsors: remove Stainless. PR [#15862](https://github.com/fastapi/fastapi/pull/15862) by [@tiangolo](https://github.com/tiangolo). +* ♻️ Refactor how sponsors data is handled for banners. PR [#15852](https://github.com/fastapi/fastapi/pull/15852) by [@tiangolo](https://github.com/tiangolo). + +## 0.138.1 (2026-06-25) + +### Refactors + +* ♻️ Refactor Library Skills, make info easier to find for agents. PR [#15841](https://github.com/fastapi/fastapi/pull/15841) by [@tiangolo](https://github.com/tiangolo). + +### Internal + +* 👷 Simplify pull request workflow triggers. PR [#15836](https://github.com/fastapi/fastapi/pull/15836) by [@tiangolo](https://github.com/tiangolo). +* 👷 Update issue-manager to 0.7.1. PR [#15833](https://github.com/fastapi/fastapi/pull/15833) by [@tiangolo](https://github.com/tiangolo). +* ⬆️ Update issue-manager to 0.7.0. PR [#15831](https://github.com/fastapi/fastapi/pull/15831) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Update sponsors: Add TestMu again. PR [#15830](https://github.com/fastapi/fastapi/pull/15830) by [@tiangolo](https://github.com/tiangolo). +* 🔒️ Update zizmor workflow security checks. PR [#15820](https://github.com/fastapi/fastapi/pull/15820) by [@tiangolo](https://github.com/tiangolo). +* ⬆ Bump pydantic-settings from 2.14.1 to 2.14.2. PR [#15799](https://github.com/fastapi/fastapi/pull/15799) by [@dependabot[bot]](https://github.com/apps/dependabot). + +## 0.138.0 (2026-06-20) + +### Features + +* ✨ Add support for `app.frontend("/", directory="dist")` and `router.frontend("/", directory="dist")`. PR [#15800](https://github.com/fastapi/fastapi/pull/15800) by [@tiangolo](https://github.com/tiangolo). + * Read the docs: [Frontend](https://fastapi.tiangolo.com/tutorial/frontend/). + +### Docs + +* 📝 Fix typo in release notes. PR [#15807](https://github.com/fastapi/fastapi/pull/15807) by [@tiangolo](https://github.com/tiangolo). +* 📝 Add `app.frontend()` instructions to Agent Library Skill. PR [#15805](https://github.com/fastapi/fastapi/pull/15805) by [@tiangolo](https://github.com/tiangolo). +* 📝 Update release notes link. PR [#15802](https://github.com/fastapi/fastapi/pull/15802) by [@tiangolo](https://github.com/tiangolo). +* ✏️ Update white space characters in bigger apps. PR [#15801](https://github.com/fastapi/fastapi/pull/15801) by [@tiangolo](https://github.com/tiangolo). +* ✏️ Fix grammar, typos, and broken links in docs. PR [#15694](https://github.com/fastapi/fastapi/pull/15694) by [@YuriiMotov](https://github.com/YuriiMotov). + +### Translations + +* 🌐 Enable Hindi docs translations. PR [#15554](https://github.com/fastapi/fastapi/pull/15554) by [@YuriiMotov](https://github.com/YuriiMotov). + +### Internal + +* 🐛 Fix failing test, update format for raised errors. PR [#15804](https://github.com/fastapi/fastapi/pull/15804) by [@tiangolo](https://github.com/tiangolo). +* 👷 Fix test-alls-green. PR [#15803](https://github.com/fastapi/fastapi/pull/15803) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Enable checking `release-notes.md` for typos. PR [#15796](https://github.com/fastapi/fastapi/pull/15796) by [@YuriiMotov](https://github.com/YuriiMotov). +* 📝 Tweak wording about deploying to FastAPI Cloud. PR [#15793](https://github.com/fastapi/fastapi/pull/15793) by [@tiangolo](https://github.com/tiangolo). +* 🔨 Use `gpt-5.5` model in `translate.py`, specify `-chat` to avoid warnings. PR [#15792](https://github.com/fastapi/fastapi/pull/15792) by [@YuriiMotov](https://github.com/YuriiMotov). + +## 0.137.2 (2026-06-18) + +### Features + +* ✨ Add `iter_route_contexts()` for advanced use cases that used to use `router.routes` (e.g. Jupyverse). PR [#15785](https://github.com/fastapi/fastapi/pull/15785) by [@tiangolo](https://github.com/tiangolo). + +### Translations + +* 🌐 Fix broken Markdown in Korean custom response docs. PR [#15774](https://github.com/fastapi/fastapi/pull/15774) by [@kooqooo](https://github.com/kooqooo). +* 🌐 Update translations for fr (update-outdated). PR [#15761](https://github.com/fastapi/fastapi/pull/15761) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for zh-hant (update-outdated). PR [#15760](https://github.com/fastapi/fastapi/pull/15760) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for de (update-outdated). PR [#15759](https://github.com/fastapi/fastapi/pull/15759) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for ko (update-outdated). PR [#15757](https://github.com/fastapi/fastapi/pull/15757) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for uk (update-outdated). PR [#15756](https://github.com/fastapi/fastapi/pull/15756) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for zh (update-outdated). PR [#15755](https://github.com/fastapi/fastapi/pull/15755) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for tr (update-outdated). PR [#15754](https://github.com/fastapi/fastapi/pull/15754) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for pt (update-outdated). PR [#15753](https://github.com/fastapi/fastapi/pull/15753) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for es (update-outdated). PR [#15752](https://github.com/fastapi/fastapi/pull/15752) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for ja (update-outdated). PR [#15751](https://github.com/fastapi/fastapi/pull/15751) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for ru (update-outdated). PR [#15758](https://github.com/fastapi/fastapi/pull/15758) by [@tiangolo](https://github.com/tiangolo). + +### Internal + +* 🔧 Update sponsors: add BairesDev. PR [#15787](https://github.com/fastapi/fastapi/pull/15787) by [@tiangolo](https://github.com/tiangolo). +* 🔨 Update sponsors script to simplify previews. PR [#15786](https://github.com/fastapi/fastapi/pull/15786) by [@tiangolo](https://github.com/tiangolo). +* ⬆ Bump the python-packages group across 1 directory with 7 updates. PR [#15777](https://github.com/fastapi/fastapi/pull/15777) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump cryptography from 46.0.7 to 48.0.1. PR [#15779](https://github.com/fastapi/fastapi/pull/15779) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump aiohttp from 3.14.0 to 3.14.1. PR [#15781](https://github.com/fastapi/fastapi/pull/15781) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump starlette from 1.2.1 to 1.3.1. PR [#15780](https://github.com/fastapi/fastapi/pull/15780) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump astral-sh/setup-uv from 8.1.0 to 8.2.0 in the github-actions group. PR [#15776](https://github.com/fastapi/fastapi/pull/15776) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump https://github.com/crate-ci/typos from v1.47.1 to v1.47.2 in the pre-commit group. PR [#15775](https://github.com/fastapi/fastapi/pull/15775) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump python-multipart from 0.0.30 to 0.0.32. PR [#15778](https://github.com/fastapi/fastapi/pull/15778) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⏪️ Revert removing scripts, only remove `coverage.sh`. PR [#15772](https://github.com/fastapi/fastapi/pull/15772) by [@tiangolo](https://github.com/tiangolo). +* 🔥 Remove unused scripts. PR [#15771](https://github.com/fastapi/fastapi/pull/15771) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Add ty configs to check docs sources. PR [#15770](https://github.com/fastapi/fastapi/pull/15770) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Add ty configs to check docs sources. PR [#15769](https://github.com/fastapi/fastapi/pull/15769) by [@tiangolo](https://github.com/tiangolo). + +## 0.137.1 (2026-06-15) + +### Fixes + +* 🚨 Fix typing checks for APIRoute. PR [#15765](https://github.com/fastapi/fastapi/pull/15765) by [@tiangolo](https://github.com/tiangolo). +* 🐛 Fix bug, allow empty path in path operation in prefixless router. PR [#15763](https://github.com/fastapi/fastapi/pull/15763) by [@tiangolo](https://github.com/tiangolo). + +## 0.137.0 (2026-06-14) + +### Breaking Changes + +* ♻️ Refactor internals to preserve `APIRouter` and `APIRoute` instances. PR [#15745](https://github.com/fastapi/fastapi/pull/15745) by [@tiangolo](https://github.com/tiangolo). + +Unblocks ✨ SO MANY THINGS ✨ + +Before this, `router.include_router(other_router)` would take each path operation from `other_router` and "clone" it, or recreate it from scratch. + +This would mean that in the end there was only one top level router, part of the app. + +The way it is structured here is that there are a few additional classes to handle intermediate metadata for router and route inclusion. That way the information of "router X includes Y and Y includes Z" is stored somewhere, without affecting (recreating / cloning) the final route. + +#### Non Objectives + +Dependencies for 404: previously I intended to support dependencies that would be executed even for 404, but that would conflict with the fact that a router could _not_ find a match, but the next router _did_ find a match. Executing dependencies in the router that did not find a match would not make sense, they could consume the request, body, etc. This original idea was discarded. + +#### Specific Breaking Changes + +Now `router.routes` is no longer a plain list of `APIRoute` objects, it can contain these intermediate objects that can contain additional routers, forming a tree. + +Any logic that depended on iterating on the `router.routes` directly would be affected, that logic cannot expect to be able to extract data from a plain list of routes, as it's no longer a plain list but a tree. + +Additionally, any logic that iterated on `router.routes` to modify them would now also see these new objects, and would not see all the routes in the app. + +`router.routes` should be considered an internal implementation detail, only passed around to the FastAPI functions that need it. + +#### Features + +* Adding routes (path operations) after a router is included now works, they are reflected as they are not copied. +* Including `subrouter` in `mainrouter` can be done before adding routes (path operations) to `subrouter`, because now the entire object is stored instead of copying the routes. +* As routes are not copied, in some cases that might save some memory. + +#### Alpha Features + +This is not documented yet, so it's not officially supported yet and could change in the future. + +But, as `APIRoute` and `APIRouter` instances are now preserved, they could be customized. + +`APIRouter` has two new methods, `.matches()` and `.handle()`, counterpart to the existing ones in `APIRoute`. With this a router could customize how it matches and handles requests. For example, it could match only requests that include some specific header, for example for handling versions in headers. + +Still, for now, consider this very experimental and potentially changing and breaking in the future. + +#### Future Features Enabled + +* Custom `APIRoute` subclasses (undocumented, but already works as described above) +* Custom `APIRouter` subclasses (undocumented, but already works as described above) +* Dependencies per router +* Exception handlers per router +* Middleware per router +* Other features planned + ### Docs +* 📝 Update release notes. PR [#15747](https://github.com/fastapi/fastapi/pull/15747) by [@tiangolo](https://github.com/tiangolo). +* 📝 Update FastAPI Cloud deployment instructions. PR [#15724](https://github.com/fastapi/fastapi/pull/15724) by [@alejsdev](https://github.com/alejsdev). * ✏️ Use `Annotated` in inline example in `docs/en/docs/tutorial/body-multiple-params.md`. PR [#15591](https://github.com/fastapi/fastapi/pull/15591) by [@TheArchons](https://github.com/TheArchons). * 📝 Remove "NGINX Unit" from the list of ASGI-servers in docs. PR [#15475](https://github.com/fastapi/fastapi/pull/15475) by [@angryfoxx](https://github.com/angryfoxx). * 📝 Update `docs/en/docs/tutorial/security/oauth2-jwt.md`. PR [#14781](https://github.com/fastapi/fastapi/pull/14781) by [@zadevhub](https://github.com/zadevhub). @@ -29,6 +215,16 @@ hide: ### Internal +* 🔧 Update sponsors: remove TalorData. PR [#15744](https://github.com/fastapi/fastapi/pull/15744) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Update sponsors: remove ExoFlare. PR [#15736](https://github.com/fastapi/fastapi/pull/15736) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Update sponsors: remove InterviewPal. PR [#15735](https://github.com/fastapi/fastapi/pull/15735) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Update sponsors: remove Liblab. PR [#15731](https://github.com/fastapi/fastapi/pull/15731) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Update sponsors: remove Scalar. PR [#15730](https://github.com/fastapi/fastapi/pull/15730) by [@tiangolo](https://github.com/tiangolo). +* ⬆ Bump the python-packages group across 1 directory with 6 updates. PR [#15721](https://github.com/fastapi/fastapi/pull/15721) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump python-multipart from 0.0.29 to 0.0.30. PR [#15723](https://github.com/fastapi/fastapi/pull/15723) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump the github-actions group with 3 updates. PR [#15720](https://github.com/fastapi/fastapi/pull/15720) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump starlette from 1.1.0 to 1.2.1. PR [#15722](https://github.com/fastapi/fastapi/pull/15722) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump https://github.com/crate-ci/typos from v1.46.0 to v1.47.1 in the pre-commit group. PR [#15719](https://github.com/fastapi/fastapi/pull/15719) by [@dependabot[bot]](https://github.com/apps/dependabot). * 🔧 Update sponsors, add Rapidproxy. PR [#15689](https://github.com/fastapi/fastapi/pull/15689) by [@tiangolo](https://github.com/tiangolo). * 🔧 Update sponsors: Remove TestMu. PR [#15688](https://github.com/fastapi/fastapi/pull/15688) by [@tiangolo](https://github.com/tiangolo). * ⬆ Bump the python-packages group across 1 directory with 11 updates. PR [#15683](https://github.com/fastapi/fastapi/pull/15683) by [@dependabot[bot]](https://github.com/apps/dependabot). @@ -295,7 +491,7 @@ hide: ### Features * ✨ Add support for streaming JSON Lines and binary data with `yield`. PR [#15022](https://github.com/fastapi/fastapi/pull/15022) by [@tiangolo](https://github.com/tiangolo). - * This also upgrades Starlette from `>=0.40.0` to `>=0.46.0`, as it's needed to properly unrwap and re-raise exceptions from exception groups. + * This also upgrades Starlette from `>=0.40.0` to `>=0.46.0`, as it's needed to properly unwrap and re-raise exceptions from exception groups. * New docs: [Stream JSON Lines](https://fastapi.tiangolo.com/tutorial/stream-json-lines/). * And new docs: [Stream Data](https://fastapi.tiangolo.com/advanced/stream-data/). @@ -1318,7 +1514,7 @@ You can read more about it in the docs for [Advanced Dependencies - Dependencies * 🌐 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). +* 🌐 Add Bengali translation for `docs/bn/about/index.md`. PR [#13882](https://github.com/fastapi/fastapi/pull/13882) by [@sajjadrahman56](https://github.com/sajjadrahman56). ### Internal @@ -2160,7 +2356,7 @@ If you want to install `fastapi` with the standard dependencies but without `fas * ➕ Add docs dependency: markdown-include-variants. PR [#12399](https://github.com/fastapi/fastapi/pull/12399) by [@tiangolo](https://github.com/tiangolo). * 📝 Fix extra mdx-base-path paths. PR [#12397](https://github.com/fastapi/fastapi/pull/12397) by [@tiangolo](https://github.com/tiangolo). * 👷 Tweak labeler to not override custom labels. PR [#12398](https://github.com/fastapi/fastapi/pull/12398) by [@tiangolo](https://github.com/tiangolo). -* 👷 Update worfkow deploy-docs-notify URL. PR [#12392](https://github.com/fastapi/fastapi/pull/12392) by [@tiangolo](https://github.com/tiangolo). +* 👷 Update workflow deploy-docs-notify URL. PR [#12392](https://github.com/fastapi/fastapi/pull/12392) by [@tiangolo](https://github.com/tiangolo). * 👷 Update Cloudflare GitHub Action. PR [#12387](https://github.com/fastapi/fastapi/pull/12387) by [@tiangolo](https://github.com/tiangolo). * ⬆ Bump pypa/gh-action-pypi-publish from 1.10.1 to 1.10.3. PR [#12386](https://github.com/fastapi/fastapi/pull/12386) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump mkdocstrings[python] from 0.25.1 to 0.26.1. PR [#12371](https://github.com/fastapi/fastapi/pull/12371) by [@dependabot[bot]](https://github.com/apps/dependabot). @@ -2676,7 +2872,7 @@ Discussed here: [#11522](https://github.com/fastapi/fastapi/pull/11522) and here * 📝 Update `security/first-steps.md`. PR [#11673](https://github.com/tiangolo/fastapi/pull/11673) by [@alejsdev](https://github.com/alejsdev). * 📝 Update note in `path-params-numeric-validations.md`. PR [#11672](https://github.com/tiangolo/fastapi/pull/11672) by [@alejsdev](https://github.com/alejsdev). * 📝 Tweak intro docs about `Annotated` and `Query()` params. PR [#11664](https://github.com/tiangolo/fastapi/pull/11664) by [@tiangolo](https://github.com/tiangolo). -* 📝 Update JWT auth documentation to use PyJWT instead of pyhon-jose. PR [#11589](https://github.com/tiangolo/fastapi/pull/11589) by [@estebanx64](https://github.com/estebanx64). +* 📝 Update JWT auth documentation to use PyJWT instead of python-jose. PR [#11589](https://github.com/tiangolo/fastapi/pull/11589) by [@estebanx64](https://github.com/estebanx64). * 📝 Update docs. PR [#11603](https://github.com/tiangolo/fastapi/pull/11603) by [@alejsdev](https://github.com/alejsdev). * ✏️ Fix typo: convert every 're-use' to 'reuse'.. PR [#11598](https://github.com/tiangolo/fastapi/pull/11598) by [@hasansezertasan](https://github.com/hasansezertasan). * ✏️ Fix typo in `fastapi/applications.py`. PR [#11593](https://github.com/tiangolo/fastapi/pull/11593) by [@petarmaric](https://github.com/petarmaric). @@ -3115,7 +3311,7 @@ def my_dep(): ### Security fixes -* ⬆️ Upgrade minimum version of `python-multipart` to `>=0.0.7` to fix a vulnerability when using form data with a ReDos attack. You can also simply upgrade `python-multipart`. +* ⬆️ Upgrade minimum version of `python-multipart` to `>=0.0.7` to fix a vulnerability when using form data with a ReDoS attack. You can also simply upgrade `python-multipart`. Read more in the [advisory: Content-Type Header ReDoS](https://github.com/tiangolo/fastapi/security/advisories/GHSA-qf9m-vfgh-m389). @@ -4623,7 +4819,7 @@ You hopefully updated to a supported version of Python a while ago. If you haven ### Fixes * 🐛 Fix `RuntimeError` raised when `HTTPException` has a status code with no content. PR [#5365](https://github.com/tiangolo/fastapi/pull/5365) by [@iudeen](https://github.com/iudeen). -* 🐛 Fix empty response body when default `status_code` is empty but the a `Response` parameter with `response.status_code` is set. PR [#5360](https://github.com/tiangolo/fastapi/pull/5360) by [@tmeckel](https://github.com/tmeckel). +* 🐛 Fix empty response body when default `status_code` is empty but the `Response` parameter with `response.status_code` is set. PR [#5360](https://github.com/tiangolo/fastapi/pull/5360) by [@tmeckel](https://github.com/tmeckel). ### Docs @@ -4985,7 +5181,7 @@ def main( ### Internal * ♻ Refactor dict value extraction to minimize key lookups `fastapi/utils.py`. PR [#3139](https://github.com/tiangolo/fastapi/pull/3139) by [@ShahriyarR](https://github.com/ShahriyarR). -* ✅ Add tests for required nonable parameters and body fields. PR [#4907](https://github.com/tiangolo/fastapi/pull/4907) by [@tiangolo](https://github.com/tiangolo). +* ✅ Add tests for required `None`-able parameters and body fields. PR [#4907](https://github.com/tiangolo/fastapi/pull/4907) by [@tiangolo](https://github.com/tiangolo). * 👷 Fix installing Material for MkDocs Insiders in CI. PR [#4897](https://github.com/tiangolo/fastapi/pull/4897) by [@tiangolo](https://github.com/tiangolo). * 👷 Add pre-commit CI instead of custom GitHub Action. PR [#4896](https://github.com/tiangolo/fastapi/pull/4896) by [@tiangolo](https://github.com/tiangolo). * 👷 Add pre-commit GitHub Action workflow. PR [#4895](https://github.com/tiangolo/fastapi/pull/4895) by [@tiangolo](https://github.com/tiangolo). @@ -5378,7 +5574,7 @@ Soon there will be a new FastAPI release upgrading Starlette to take advantage o ### Internal -* ✨ Update GitHub Action: notify-translations, to avoid a race conditions. PR [#3989](https://github.com/tiangolo/fastapi/pull/3989) by [@tiangolo](https://github.com/tiangolo). +* ✨ Update GitHub Action: notify-translations, to avoid race conditions. PR [#3989](https://github.com/tiangolo/fastapi/pull/3989) by [@tiangolo](https://github.com/tiangolo). * ⬆️ Upgrade development `autoflake`, supporting multi-line imports. PR [#3988](https://github.com/tiangolo/fastapi/pull/3988) by [@tiangolo](https://github.com/tiangolo). * ⬆️ Increase dependency ranges for tests and docs: pytest-cov, pytest-asyncio, black, httpx, sqlalchemy, databases, mkdocs-markdownextradata-plugin. PR [#3987](https://github.com/tiangolo/fastapi/pull/3987) by [@tiangolo](https://github.com/tiangolo). * 👥 Update FastAPI People. PR [#3986](https://github.com/tiangolo/fastapi/pull/3986) by [@github-actions[bot]](https://github.com/apps/github-actions). @@ -5766,7 +5962,7 @@ router = APIRouter(prefix="/users", dependencies=[Depends(some_dependency)]) Most of these settings are now supported in `APIRouter`, which normally lives closer to the related code, so it is recommended to use `APIRouter` when possible. -But `include_router` is still useful to, for example, adding options (like `dependencies`, `prefix`, and `tags`) when including a third party router, or a generic router that is shared between several projects. +But `include_router` is still useful to, for example, add options (like `dependencies`, `prefix`, and `tags`) when including a third party router, or a generic router that is shared between several projects. This PR allows setting the (mostly new) parameters (additionally to the already existing parameters): @@ -5828,7 +6024,7 @@ Note: all the previous parameters are still there, so it's still possible to dec * ✏️ Fix typo in Tutorial - Path Parameters. PR [#2231](https://github.com/tiangolo/fastapi/pull/2231) by [@mariacamilagl](https://github.com/mariacamilagl). * ✏ Fix a stylistic error in docs. PR [#2206](https://github.com/tiangolo/fastapi/pull/2206) by [@ddobrinskiy](https://github.com/ddobrinskiy). -* ✏ Fix capitalizaiton typo in docs. PR [#2204](https://github.com/tiangolo/fastapi/pull/2204) by [@imba-tjd](https://github.com/imba-tjd). +* ✏ Fix capitalization typo in docs. PR [#2204](https://github.com/tiangolo/fastapi/pull/2204) by [@imba-tjd](https://github.com/imba-tjd). * ✏ Fix typo in docs. PR [#2179](https://github.com/tiangolo/fastapi/pull/2179) by [@ammarasmro](https://github.com/ammarasmro). * 📝 Update/fix links in docs to use HTTPS. PR [#2165](https://github.com/tiangolo/fastapi/pull/2165) by [@imba-tjd](https://github.com/imba-tjd). * ✏ Fix typos and add rewording in docs. PR [#2159](https://github.com/tiangolo/fastapi/pull/2159) by [@nukopy](https://github.com/nukopy). @@ -5956,7 +6152,7 @@ Note: all the previous parameters are still there, so it's still possible to dec * Fix typo in docs for query parameters. PR [#1832](https://github.com/tiangolo/fastapi/pull/1832) by [@ycd](https://github.com/ycd). * Add docs about [Async Tests](https://fastapi.tiangolo.com/advanced/async-tests/). PR [#1619](https://github.com/tiangolo/fastapi/pull/1619) by [@empicano](https://github.com/empicano). * Raise an exception when using form data (`Form`, `File`) without having `python-multipart` installed. - * Up to now the application would run, and raise an exception only when receiving a request with form data, the new behavior, raising early, will prevent from deploying applications with broken dependencies. + * Up to now the application would run, and raise an exception only when receiving a request with form data, the new behavior, raising early, will prevent deploying applications with broken dependencies. * It also detects if the correct package `python-multipart` is installed instead of the incorrect `multipart` (both importable as `multipart`). * PR [#1851](https://github.com/tiangolo/fastapi/pull/1851) based on original PR [#1627](https://github.com/tiangolo/fastapi/pull/1627) by [@chrisngyn](https://github.com/chrisngyn), [@YKo20010](https://github.com/YKo20010), [@kx-chen](https://github.com/kx-chen). * Re-enable Gitter releases bot. PR [#1831](https://github.com/tiangolo/fastapi/pull/1831). @@ -6106,7 +6302,7 @@ Note: all the previous parameters are still there, so it's still possible to dec * [Using FastAPI with Django](https://www.stavros.io/posts/fastapi-with-django/) by [Stavros Korokithakis](https://x.com/Stavros). * [Introducing Dispatch](https://netflixtechblog.com/introducing-dispatch-da4b8a2a8072) by [Netflix](https://netflixtechblog.com/). * **Podcasts**: - * [Build The Next Generation Of Python Web Applications With FastAPI - Episode 259 - interview to Sebastían Ramírez (tiangolo)](https://www.pythonpodcast.com/fastapi-web-application-framework-episode-259/) by [Podcast.`__init__`](https://www.pythonpodcast.com/). + * [Build The Next Generation Of Python Web Applications With FastAPI - Episode 259 - interview to Sebastián Ramírez (tiangolo)](https://www.pythonpodcast.com/fastapi-web-application-framework-episode-259/) by [Podcast.`__init__`](https://www.pythonpodcast.com/). * **Talks**: * [PyConBY 2020: Serve ML models easily with FastAPI](https://www.youtube.com/watch?v=z9K5pwb0rt8) by [Sebastián Ramírez (tiangolo)](https://x.com/tiangolo). * [[VIRTUAL] Py.Amsterdam's flying Software Circus: Intro to FastAPI](https://www.youtube.com/watch?v=PnpTY1f4k2U) by [Sebastián Ramírez (tiangolo)](https://x.com/tiangolo). @@ -6121,7 +6317,7 @@ Note: all the previous parameters are still there, so it's still possible to dec * Allow enums to allow them to have their own schemas in OpenAPI. To support [pydantic/pydantic#1432](https://github.com/pydantic/pydantic/pull/1432) in FastAPI. PR [#1461](https://github.com/tiangolo/fastapi/pull/1461). * Add links for funding through [GitHub sponsors](https://github.com/sponsors/tiangolo). PR [#1425](https://github.com/tiangolo/fastapi/pull/1425). -* Update issue template for for questions. PR [#1344](https://github.com/tiangolo/fastapi/pull/1344) by [@retnikt](https://github.com/retnikt). +* Update issue template for questions. PR [#1344](https://github.com/tiangolo/fastapi/pull/1344) by [@retnikt](https://github.com/retnikt). * Update warning about storing passwords in docs. PR [#1336](https://github.com/tiangolo/fastapi/pull/1336) by [@skorokithakis](https://github.com/skorokithakis). * Fix typo. PR [#1326](https://github.com/tiangolo/fastapi/pull/1326) by [@chenl](https://github.com/chenl). * Add translation to Portuguese for [Alternatives, Inspiration and Comparisons - Alternativas, Inspiração e Comparações](https://fastapi.tiangolo.com/pt/alternatives/). PR [#1325](https://github.com/tiangolo/fastapi/pull/1325) by [@Serrones](https://github.com/Serrones). @@ -6512,7 +6708,7 @@ Note: all the previous parameters are still there, so it's still possible to dec * When declaring a `response_model` it is used directly to generate the response content, from whatever was returned from the *path operation function*. * Before this, the return content was first passed through `jsonable_encoder` to ensure it was a "jsonable" object, like a `dict`, instead of an arbitrary object with attributes (like an ORM model). That's why you should make sure to update your Pydantic models for objects with attributes to use `orm_mode = True`. * If you don't have a `response_model`, the return object will still be passed through `jsonable_encoder` first. - * When a `response_model` is declared, the same `response_model` type declaration won't be used as is, it will be "cloned" to create an new one (a cloned Pydantic `Field` with all the submodels cloned as well). + * When a `response_model` is declared, the same `response_model` type declaration won't be used as is, it will be "cloned" to create a new one (a cloned Pydantic `Field` with all the submodels cloned as well). * This avoids/fixes a potential security issue: as the returned object is passed directly to Pydantic, if the returned object was a subclass of the `response_model` (e.g. you return a `UserInDB` that inherits from `User` but contains extra fields, like `hashed_password`, and `User` is used in the `response_model`), it would still pass the validation (because `UserInDB` is a subclass of `User`) and the object would be returned as-is, including the `hashed_password`. To fix this, the declared `response_model` is cloned, if it is a Pydantic model class (or contains Pydantic model classes in it, e.g. in a `List[Item]`), the Pydantic model class(es) will be a different one (the "cloned" one). So, an object that is a subclass won't simply pass the validation and returned as-is, because it is no longer a sub-class of the cloned `response_model`. Instead, a new Pydantic model object will be created with the contents of the returned object. So, it will be a new object (made with the data from the returned one), and will be filtered by the cloned `response_model`, containing only the declared fields as normally. * PR [#322](https://github.com/tiangolo/fastapi/pull/322). @@ -6655,7 +6851,7 @@ Note: all the previous parameters are still there, so it's still possible to dec * Add support for `dependencies` parameter: * A parameter in *path operation decorators*, for dependencies that should be executed but the return value is not important or not used in the *path operation function*. * A parameter in the `.include_router()` method of FastAPI applications and routers, to include dependencies that should be executed in each *path operation* in a router. - * This is useful, for example, to require authentication or permissions in specific group of *path operations*. + * This is useful, for example, to require authentication or permissions in a specific group of *path operations*. * Different `dependencies` can be applied to different routers. * These `dependencies` are run before the normal parameter dependencies. And normal dependencies are run too. They can be combined. * Dependencies declared in a router are executed first, then the ones defined in *path operation decorators*, and then the ones declared in normal parameters. They are all combined and executed. diff --git a/docs/en/docs/translations.md b/docs/en/docs/translations.md index ee5531877..2f1067255 100644 --- a/docs/en/docs/translations.md +++ b/docs/en/docs/translations.md @@ -16,10 +16,10 @@ PRs with suggestions to the language-specific LLM prompt require approval from a Let's say that you want to request translations for a language that is not yet translated, not even some pages. For example, Latin. -* The first step would be for you to find other 2 people that would be willing to be reviewing translation PRs for that language with you. +* The first step would be for you to find 2 other people who would be willing to be reviewing translation PRs for that language with you. * Once there are at least 3 people that would be willing to commit to help maintain that language, you can continue the next steps. * Create a new discussion following the template. -* Tag the other 2 people that will help with the language, and ask them to confirm there they will help. +* Tag the other 2 people that will help with the language, and ask them to confirm in the comments that they will help. Once there are several people in the discussion, the FastAPI team can evaluate it and can make it an official translation. diff --git a/docs/en/docs/tutorial/bigger-applications.md b/docs/en/docs/tutorial/bigger-applications.md index 8950d59b4..07478b5cc 100644 --- a/docs/en/docs/tutorial/bigger-applications.md +++ b/docs/en/docs/tutorial/bigger-applications.md @@ -17,16 +17,16 @@ Let's say you have a file structure like this: ``` . ├── app -│   ├── __init__.py -│   ├── main.py -│   ├── dependencies.py -│   └── routers -│   │ ├── __init__.py -│   │ ├── items.py -│   │ └── users.py -│   └── internal -│   ├── __init__.py -│   └── admin.py +│ ├── __init__.py +│ ├── main.py +│ ├── dependencies.py +│ └── routers +│ │ ├── __init__.py +│ │ ├── items.py +│ │ └── users.py +│ └── internal +│ ├── __init__.py +│ └── admin.py ``` /// tip @@ -232,7 +232,7 @@ would mean: But that file doesn't exist, our dependencies are in a file at `app/dependencies.py`. -Remember how our app/file structure looks like: +Remember what our app/file structure looks like: @@ -396,9 +396,9 @@ It will include all the routes from that router as part of it. /// note | Technical Details -It will actually internally create a *path operation* for each *path operation* that was declared in the `APIRouter`. +FastAPI keeps the original `APIRouter` and its `APIRoute`s active when the router is included in the main application. -So, behind the scenes, it will actually work as if everything was the same single app. +That means custom `APIRouter` and `APIRoute` subclasses can still participate after the router is included. /// @@ -406,7 +406,7 @@ So, behind the scenes, it will actually work as if everything was the same singl You don't have to worry about performance when including routers. -This will take microseconds and will only happen at startup. +This is designed to be lightweight and to avoid adding overhead to each request. So it won't affect performance. ⚡ @@ -461,7 +461,7 @@ The `APIRouter`s are not "mounted", they are not isolated from the rest of the a This is because we want to include their *path operations* in the OpenAPI schema and the user interfaces. -As we cannot just isolate them and "mount" them independently of the rest, the *path operations* are "cloned" (re-created), not included directly. +FastAPI keeps the original routers and path operations active, and combines the router prefixes, dependencies, tags, responses, and other metadata when handling requests and generating OpenAPI. /// @@ -532,4 +532,16 @@ The same way you can include an `APIRouter` in a `FastAPI` application, you can router.include_router(other_router) ``` -Make sure you do it before including `router` in the `FastAPI` app, so that the *path operations* from `other_router` are also included. +You can do this before or after including `router` in the `FastAPI` app. FastAPI will still include the *path operations* from `other_router` in routing and OpenAPI. + +The same applies to *path operations* added later to the routers. They will be visible through the earlier inclusion too. + +/// warning | Technical Details + +Avoid directly mutating `router.routes` after including a router. FastAPI treats router inclusion as live, so the original router and its routes remain part of routing and OpenAPI generation. + +Use documented APIs such as path operation decorators and `.include_router()` to add routes and routers. + +Treat `router.routes` as a lower-level route tree that can contain route definitions and included routers, and avoid relying on it as a flat list of final path operations. + +/// diff --git a/docs/en/docs/tutorial/body-nested-models.md b/docs/en/docs/tutorial/body-nested-models.md index 5479ab2a4..61ed93202 100644 --- a/docs/en/docs/tutorial/body-nested-models.md +++ b/docs/en/docs/tutorial/body-nested-models.md @@ -96,7 +96,7 @@ Again, doing just that declaration, with **FastAPI** you get: Apart from normal singular types like `str`, `int`, `float`, etc. you can use more complex singular types that inherit from `str`. -To see all the options you have, checkout [Pydantic's Type Overview](https://docs.pydantic.dev/latest/concepts/types/). You will see some examples in the next chapter. +To see all the options you have, check out [Pydantic's Type Overview](https://docs.pydantic.dev/latest/concepts/types/). You will see some examples in the next chapter. For example, as in the `Image` model we have a `url` field, we can declare it to be an instance of Pydantic's `HttpUrl` instead of a `str`: diff --git a/docs/en/docs/tutorial/body.md b/docs/en/docs/tutorial/body.md index 1cc0aff49..70869cc6a 100644 --- a/docs/en/docs/tutorial/body.md +++ b/docs/en/docs/tutorial/body.md @@ -10,7 +10,7 @@ To declare a **request** body, you use [Pydantic](https://docs.pydantic.dev/) mo /// note -To send data, you should use one of: `POST` (the more common), `PUT`, `DELETE` or `PATCH`. +To send data, you should use one of: `POST` (the most common), `PUT`, `DELETE` or `PATCH`. Sending a body with a `GET` request has undefined behavior in the specifications, nevertheless, it is supported by FastAPI, only for very complex/extreme use cases. diff --git a/docs/en/docs/tutorial/debugging.md b/docs/en/docs/tutorial/debugging.md index 8db47b934..5b57fe85b 100644 --- a/docs/en/docs/tutorial/debugging.md +++ b/docs/en/docs/tutorial/debugging.md @@ -99,7 +99,7 @@ Here's how it might look: --- -If you use Pycharm, you can: +If you use PyCharm, you can: * Open the "Run" menu. * Select the option "Debug...". diff --git a/docs/en/docs/tutorial/dependencies/dependencies-with-yield.md b/docs/en/docs/tutorial/dependencies/dependencies-with-yield.md index 658dee7c2..5574af519 100644 --- a/docs/en/docs/tutorial/dependencies/dependencies-with-yield.md +++ b/docs/en/docs/tutorial/dependencies/dependencies-with-yield.md @@ -234,6 +234,7 @@ participant operation as Path Operation Dependencies with `yield` have evolved over time to cover different use cases and fix some issues. If you want to see what has changed in different versions of FastAPI, you can read more about it in the advanced guide, in [Advanced Dependencies - Dependencies with `yield`, `HTTPException`, `except` and Background Tasks](../../advanced/advanced-dependencies.md#dependencies-with-yield-httpexception-except-and-background-tasks). + ## Context Managers { #context-managers } ### What are "Context Managers" { #what-are-context-managers } diff --git a/docs/en/docs/tutorial/extra-data-types.md b/docs/en/docs/tutorial/extra-data-types.md index 611aa9b9e..63c914efe 100644 --- a/docs/en/docs/tutorial/extra-data-types.md +++ b/docs/en/docs/tutorial/extra-data-types.md @@ -36,7 +36,7 @@ Here are some of the additional data types you can use: * `datetime.timedelta`: * A Python `datetime.timedelta`. * In requests and responses will be represented as a `float` of total seconds. - * Pydantic also allows representing it as a "ISO 8601 time diff encoding", [see the docs for more info](https://docs.pydantic.dev/latest/concepts/serialization/#custom-serializers). + * Pydantic also allows representing it as an "ISO 8601 time diff encoding", [see the docs for more info](https://docs.pydantic.dev/latest/concepts/serialization/#custom-serializers). * `frozenset`: * In requests and responses, treated the same as a `set`: * In requests, a list will be read, eliminating duplicates and converting it to a `set`. diff --git a/docs/en/docs/tutorial/extra-models.md b/docs/en/docs/tutorial/extra-models.md index e231aea90..d2b53cb66 100644 --- a/docs/en/docs/tutorial/extra-models.md +++ b/docs/en/docs/tutorial/extra-models.md @@ -18,7 +18,7 @@ If you don't know, you will learn what a "password hash" is in the [security cha ## Multiple models { #multiple-models } -Here's a general idea of how the models could look like with their password fields and the places where they are used: +Here's a general idea of what the models could look like with their password fields and the places where they are used: {* ../../docs_src/extra_models/tutorial001_py310.py hl[7,9,14,20,22,27:28,31:33,38:39] *} @@ -142,7 +142,7 @@ The supporting additional functions `fake_password_hasher` and `fake_save_user` Reducing code duplication is one of the core ideas in **FastAPI**. -As code duplication increments the chances of bugs, security issues, code desynchronization issues (when you update in one place but not in the others), etc. +As code duplication increases the chances of bugs, security issues, code desynchronization issues (when you update in one place but not in the others), etc. And these models are all sharing a lot of the data and duplicating attribute names and types. @@ -208,4 +208,4 @@ In this case, you can use `dict`: Use multiple Pydantic models and inherit freely for each case. -You don't need to have a single data model per entity if that entity must be able to have different "states". As the case with the user "entity" with a state including `password`, `password_hash` and no password. +You don't need to have a single data model per entity if that entity must be able to have different "states". The **user** "entity" is an example, with states that include `password`, `password_hash`, or no password. diff --git a/docs/en/docs/tutorial/first-steps.md b/docs/en/docs/tutorial/first-steps.md index ae43e401b..afef39341 100644 --- a/docs/en/docs/tutorial/first-steps.md +++ b/docs/en/docs/tutorial/first-steps.md @@ -108,7 +108,7 @@ OpenAPI defines an API schema for your API. And that schema includes definitions #### Check the `openapi.json` { #check-the-openapi-json } -If you are curious about how the raw OpenAPI schema looks like, FastAPI automatically generates a JSON (schema) with the descriptions of all your API. +If you are curious about what the raw OpenAPI schema looks like, FastAPI automatically generates a JSON (schema) with the descriptions of all your API. You can see it directly at: [http://127.0.0.1:8000/openapi.json](http://127.0.0.1:8000/openapi.json). @@ -200,23 +200,7 @@ Additionally, other tools might not be able to find it, for example the [VS Code ### Deploy your app (optional) { #deploy-your-app-optional } -You can optionally deploy your FastAPI app to [FastAPI Cloud](https://fastapicloud.com), go and join the waiting list if you haven't. 🚀 - -If you already have a **FastAPI Cloud** account (we invited you from the waiting list 😉), you can deploy your application with one command. - -Before deploying, make sure you are logged in: - -
- -```console -$ fastapi login - -You are logged in to FastAPI Cloud 🚀 -``` - -
- -Then deploy your app: +You can optionally deploy your FastAPI app to [FastAPI Cloud](https://fastapicloud.com) with a single command. 🚀
@@ -232,6 +216,8 @@ Deploying to FastAPI Cloud...
+The CLI will automatically detect your FastAPI application and deploy it to the cloud. If you are not logged in, your browser will open to complete the authentication process. + That's it! Now you can access your app at that URL. ✨ ## Recap, step by step { #recap-step-by-step } diff --git a/docs/en/docs/tutorial/frontend.md b/docs/en/docs/tutorial/frontend.md new file mode 100644 index 000000000..4cbc21fa1 --- /dev/null +++ b/docs/en/docs/tutorial/frontend.md @@ -0,0 +1,133 @@ +# Frontend { #frontend } + +You can serve static frontend apps with `app.frontend()` (or `router.frontend()`). + +This is useful for frontend tools that generate static files, like React with Vite, TanStack Router, Astro, Vue, Svelte, Angular, Solid, and others. + +With these tools, you normally have a step that builds the frontend, with a command like: + +```bash +npm run build +``` + +That would generate a directory like `./dist/` with your frontend files. + +You can use `app.frontend()` to serve that directory following the conventions needed by these frontend frameworks. + +**FastAPI** checks *path operations* first. The frontend files are checked only if no normal route matched, so your API won't be affected. + +## Serve a Frontend { #serve-a-frontend } + +After building your frontend, for example with `npm run build`, put the generated files in a directory, for example, `dist`. + +Your project structure could look like this: + +```text +. +├── pyproject.toml +├── app +│ ├── __init__.py +│ └── main.py +└── dist + ├── index.html + └── assets + └── app.js +``` + +Then serve it with `app.frontend()`: + +{* ../../docs_src/frontend/tutorial001_py310.py hl[5] *} + +With this, a request for `/assets/app.js` can serve `dist/assets/app.js`. + +If you also have a **FastAPI** *path operation*, the *path operation* wins. + +## Client-Side Routing { #client-side-routing } + +Many frontend apps, including **single-page apps** (SPAs), use client-side routing. A path like `/dashboard/settings` might not be a real file but the framework would take care of handling it. + +So, if accessing that URL directly (instead of navigating through the app), the backend should serve the frontend app from `index.html`, so that the frontend framework can then handle the client-side routing. + +For that, use `fallback="index.html"`: + +{* ../../docs_src/frontend/tutorial002_py310.py hl[5] *} + +**FastAPI** uses this fallback only for `GET` and `HEAD` requests that look like browser navigation. Missing files like JavaScript, CSS, and images still return `404`. + +Requests with other methods, like `POST` or `PUT`, to paths that only match the frontend fallback also return `404`. Regular **FastAPI** *path operations* still have higher priority than frontend routes. + +/// tip + +By default, `fallback` has a value of `fallback="auto"`. In most cases you won't need to specify `fallback`. Read below for details. + +/// + +This is what you would want with many frontend apps that use client-side routing, for example, React with TanStack Router, Vue, Angular, SvelteKit, or Solid. + +## Custom 404 Page { #custom-404-page } + +You can also serve a static `404.html` page for missing frontend paths: + +{* ../../docs_src/frontend/tutorial003_py310.py hl[5] *} + +That response keeps a status code of `404`. + +In this case, **FastAPI** won't serve `index.html` for missing frontend paths. It will return the `404.html` file instead. + +/// tip + +By default, `fallback` has a value of `fallback="auto"`. With this, if a `404.html` file is found, it will be used as the fallback automatically. + +So, you can normally omit the `fallback` argument. + +/// + +This is useful with frontend tools that generate static HTML files for each page, like Astro. + +## Fallback Auto { #fallback-auto } + +By default, `app.frontend()` uses `fallback="auto"`. + +If there is a `404.html` file in the frontend directory, missing frontend paths serve that file with status code `404`. + +Otherwise, if there is an `index.html` file, missing browser navigation paths serve `index.html`, which is what many frontend apps with client-side routing expect. + +So, in most cases you can use `app.frontend("/", directory="dist")` without specifying the `fallback` argument. + +{* ../../docs_src/frontend/tutorial001_py310.py hl[5] *} + +## Disable Fallback { #disable-fallback } + +If you don't want to serve a fallback file for missing frontend paths, use `fallback=None`: + +{* ../../docs_src/frontend/tutorial005_py310.py hl[5] *} + +Then missing frontend paths return the normal `404`. + +## Check Directory { #check-directory } + +By default, `app.frontend()` checks that the directory exists when the app is created. + +This helps catch configuration errors early. For example, if the frontend build output directory is missing, **FastAPI** will raise an error on startup. + +If your frontend files are created later, for example by a separate build step after the app object is created, set `check_dir=False`: + +{* ../../docs_src/frontend/tutorial006_py310.py hl[5] *} + +With `check_dir=False`, **FastAPI** will not check the directory when the app is created. If the configured directory is still missing when a request is handled, **FastAPI** will raise an error then. + +## Use it with `APIRouter` { #use-it-with-apirouter } + +You can also add frontend files to an `APIRouter` and include it with a prefix: + +{* ../../docs_src/frontend/tutorial004_py310.py hl[6,7] *} + +In this example, frontend paths are served under `/app`. + +Any regular *path operations* in the app will still take precedence, including in other routers. + +## Static Build Output Only { #static-build-output-only } + +`app.frontend()` serves files already generated by your frontend build. + +It does not run server-side rendering. It is for frontend frameworks that generate static files, not for frameworks that need dynamic rendering on the server for each request. diff --git a/docs/en/docs/tutorial/handling-errors.md b/docs/en/docs/tutorial/handling-errors.md index 78a5f1f20..bb99813be 100644 --- a/docs/en/docs/tutorial/handling-errors.md +++ b/docs/en/docs/tutorial/handling-errors.md @@ -1,6 +1,6 @@ # Handling Errors { #handling-errors } -There are many situations in which you need to notify an error to a client that is using your API. +There are many situations in which you need to report an error to a client that is using your API. This client could be a browser with a frontend, a code from someone else, an IoT device, etc. @@ -71,7 +71,7 @@ They are handled automatically by **FastAPI** and converted to JSON. ## Add custom headers { #add-custom-headers } -There are some situations in where it's useful to be able to add custom headers to the HTTP error. For example, for some types of security. +There are some situations where it's useful to be able to add custom headers to the HTTP error. For example, for some types of security. You probably won't need to use it directly in your code. diff --git a/docs/en/docs/tutorial/index.md b/docs/en/docs/tutorial/index.md index 8a37756c7..9e7357919 100644 --- a/docs/en/docs/tutorial/index.md +++ b/docs/en/docs/tutorial/index.md @@ -92,7 +92,7 @@ FastAPI has an [official extension for VS Code](https://marketplace.visualstudio ## Advanced User Guide { #advanced-user-guide } -There is also an **Advanced User Guide** that you can read later after this **Tutorial - User guide**. +There is also an **Advanced User Guide** that you can read later after this **Tutorial - User Guide**. The **Advanced User Guide** builds on this one, uses the same concepts, and teaches you some extra features. diff --git a/docs/en/docs/tutorial/metadata.md b/docs/en/docs/tutorial/metadata.md index 9cab5ca71..4516d49b0 100644 --- a/docs/en/docs/tutorial/metadata.md +++ b/docs/en/docs/tutorial/metadata.md @@ -11,7 +11,7 @@ You can set the following fields that are used in the OpenAPI specification and | `title` | `str` | The title of the API. | | `summary` | `str` | A short summary of the API. Available since OpenAPI 3.1.0, FastAPI 0.99.0. | | `description` | `str` | A short description of the API. It can use Markdown. | -| `version` | `string` | The version of the API. This is the version of your own application, not of OpenAPI. For example `2.5.0`. | +| `version` | `str` | The version of the API. This is the version of your own application, not of OpenAPI. For example `2.5.0`. | | `terms_of_service` | `str` | A URL to the Terms of Service for the API. If provided, this has to be a URL. | | `contact` | `dict` | The contact information for the exposed API. It can contain several fields.
contact fields
ParameterTypeDescription
namestrThe identifying name of the contact person/organization.
urlstrThe URL pointing to the contact information. MUST be in the format of a URL.
emailstrThe email address of the contact person/organization. MUST be in the format of an email address.
| | `license_info` | `dict` | The license information for the exposed API. It can contain several fields.
license_info fields
ParameterTypeDescription
namestrREQUIRED (if a license_info is set). The license name used for the API.
identifierstrAn [SPDX](https://spdx.org/licenses/) license expression for the API. The identifier field is mutually exclusive of the url field. Available since OpenAPI 3.1.0, FastAPI 0.99.0.
urlstrA URL to the license used for the API. MUST be in the format of a URL.
| diff --git a/docs/en/docs/tutorial/path-operation-configuration.md b/docs/en/docs/tutorial/path-operation-configuration.md index 8dfc6e2ff..9ba32ec97 100644 --- a/docs/en/docs/tutorial/path-operation-configuration.md +++ b/docs/en/docs/tutorial/path-operation-configuration.md @@ -98,7 +98,7 @@ It will be clearly marked as deprecated in the interactive docs: -Check how deprecated and non-deprecated *path operations* look like: +Check how deprecated and non-deprecated *path operations* look: diff --git a/docs/en/docs/tutorial/query-params-str-validations.md b/docs/en/docs/tutorial/query-params-str-validations.md index 0714d8beb..eb9fa2607 100644 --- a/docs/en/docs/tutorial/query-params-str-validations.md +++ b/docs/en/docs/tutorial/query-params-str-validations.md @@ -406,7 +406,7 @@ But if you're curious about this specific code example and you're still entertai #### String with `value.startswith()` { #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: +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] *} diff --git a/docs/en/docs/tutorial/query-params.md b/docs/en/docs/tutorial/query-params.md index 563d39f7d..cb89e23e7 100644 --- a/docs/en/docs/tutorial/query-params.md +++ b/docs/en/docs/tutorial/query-params.md @@ -21,7 +21,7 @@ As they are part of the URL, they are "naturally" strings. But when you declare them with Python types (in the example above, as `int`), they are converted to that type and validated against it. -All the same process that applied for path parameters also applies for query parameters: +All the same processes that apply to path parameters also apply to query parameters: * Editor support (obviously) * Data "parsing" diff --git a/docs/en/docs/tutorial/request-files.md b/docs/en/docs/tutorial/request-files.md index fe4290449..df7894781 100644 --- a/docs/en/docs/tutorial/request-files.md +++ b/docs/en/docs/tutorial/request-files.md @@ -60,7 +60,7 @@ Using `UploadFile` has several advantages over `bytes`: * You don't have to use `File()` in the default value of the parameter. * It uses a "spooled" file: - * A file stored in memory up to a maximum size limit, and after passing this limit it will be stored in disk. + * A file stored in memory up to a maximum size limit, and after passing this limit it will be stored on disk. * This means that it will work well for large files like images, videos, large binaries, etc. without consuming all the memory. * You can get metadata from the uploaded file. * It has a [file-like](https://docs.python.org/3/glossary.html#term-file-like-object) `async` interface. @@ -111,7 +111,7 @@ When you use the `async` methods, **FastAPI** runs the file methods in a threadp ## What is "Form Data" { #what-is-form-data } -The way HTML forms (`
`) sends the data to the server normally uses a "special" encoding for that data, it's different from JSON. +The way HTML forms (`
`) send the data to the server normally uses a "special" encoding for that data, it's different from JSON. **FastAPI** will make sure to read that data from the right place instead of JSON. diff --git a/docs/en/docs/tutorial/request-forms.md b/docs/en/docs/tutorial/request-forms.md index 64e90a244..45af663c8 100644 --- a/docs/en/docs/tutorial/request-forms.md +++ b/docs/en/docs/tutorial/request-forms.md @@ -46,7 +46,7 @@ To declare form bodies, you need to use `Form` explicitly, because without it th ## About "Form Fields" { #about-form-fields } -The way HTML forms (`
`) sends the data to the server normally uses a "special" encoding for that data, it's different from JSON. +The way HTML forms (`
`) send the data to the server normally uses a "special" encoding for that data, it's different from JSON. **FastAPI** will make sure to read that data from the right place instead of JSON. diff --git a/docs/en/docs/tutorial/response-status-code.md b/docs/en/docs/tutorial/response-status-code.md index a5f82ffb6..2dabc0617 100644 --- a/docs/en/docs/tutorial/response-status-code.md +++ b/docs/en/docs/tutorial/response-status-code.md @@ -49,7 +49,7 @@ If you already know what HTTP status codes are, skip to the next section. In HTTP, you send a numeric status code of 3 digits as part of the response. -These status codes have a name associated to recognize them, but the important part is the number. +These status codes have an associated name to help recognize them, but the important part is the number. In short: diff --git a/docs/en/docs/tutorial/schema-extra-example.md b/docs/en/docs/tutorial/schema-extra-example.md index 67c7ac37c..280162531 100644 --- a/docs/en/docs/tutorial/schema-extra-example.md +++ b/docs/en/docs/tutorial/schema-extra-example.md @@ -78,7 +78,7 @@ Nevertheless, at the time of writing this, Swagger ### OpenAPI-specific `examples` { #openapi-specific-examples } -Since before **JSON Schema** supported `examples` OpenAPI had support for a different field also called `examples`. +Since before **JSON Schema** supported `examples`, OpenAPI had support for a different field also called `examples`. This **OpenAPI-specific** `examples` goes in another section in the OpenAPI specification. It goes in the **details for each *path operation***, not inside each JSON Schema. diff --git a/docs/en/docs/tutorial/security/first-steps.md b/docs/en/docs/tutorial/security/first-steps.md index 095b8b901..7dae3edf4 100644 --- a/docs/en/docs/tutorial/security/first-steps.md +++ b/docs/en/docs/tutorial/security/first-steps.md @@ -88,7 +88,7 @@ And it can also be used by yourself, to debug, check and test the same applicati ## The `password` flow { #the-password-flow } -Now let's go back a bit and understand what is all that. +Now let's go back a bit and understand what all that is. The `password` "flow" is one of the ways ("flows") defined in OAuth2, to handle security and authentication. diff --git a/docs/en/docs/tutorial/security/get-current-user.md b/docs/en/docs/tutorial/security/get-current-user.md index f8a5fdf82..59a90a7e1 100644 --- a/docs/en/docs/tutorial/security/get-current-user.md +++ b/docs/en/docs/tutorial/security/get-current-user.md @@ -14,7 +14,7 @@ First, let's create a Pydantic user model. The same way we use Pydantic to declare bodies, we can use it anywhere else: -{* ../../docs_src/security/tutorial002_an_py310.py hl[5,12:6] *} +{* ../../docs_src/security/tutorial002_an_py310.py hl[5,12:16] *} ## Create a `get_current_user` dependency { #create-a-get-current-user-dependency } diff --git a/docs/en/docs/tutorial/security/oauth2-jwt.md b/docs/en/docs/tutorial/security/oauth2-jwt.md index 6c1ab27b2..68bad4e10 100644 --- a/docs/en/docs/tutorial/security/oauth2-jwt.md +++ b/docs/en/docs/tutorial/security/oauth2-jwt.md @@ -124,7 +124,7 @@ This ensures the endpoint takes roughly the same amount of time to respond wheth /// note -If you check the new (fake) database `fake_users_db`, you will see how the hashed password looks like now: `"$argon2id$v=19$m=65536,t=3,p=4$wagCPXjifgvUFBzq4hqe3w$CYaIb8sB+wtD+Vu/P4uod1+Qof8h+1g7bbDlBID48Rc"`. +If you check the new (fake) database `fake_users_db`, you will see what the hashed password looks like now: `"$argon2id$v=19$m=65536,t=3,p=4$wagCPXjifgvUFBzq4hqe3w$CYaIb8sB+wtD+Vu/P4uod1+Qof8h+1g7bbDlBID48Rc"`. /// diff --git a/docs/en/docs/tutorial/security/simple-oauth2.md b/docs/en/docs/tutorial/security/simple-oauth2.md index afe3ba128..72e08b19a 100644 --- a/docs/en/docs/tutorial/security/simple-oauth2.md +++ b/docs/en/docs/tutorial/security/simple-oauth2.md @@ -6,7 +6,7 @@ Now let's build from the previous chapter and add the missing parts to have a co We are going to use **FastAPI** security utilities to get the `username` and `password`. -OAuth2 specifies that when using the "password flow" (that we are using) the client/user must send a `username` and `password` fields as form data. +OAuth2 specifies that when using the "password flow" (that we are using) the client/user must send `username` and `password` fields as form data. And the spec says that the fields have to be named like that. So `user-name` or `email` wouldn't work. @@ -146,7 +146,7 @@ UserInDB( /// note -For a more complete explanation of `**user_dict` check back in [the documentation for **Extra Models**](../extra-models.md#about-user-in-dict). +For a more complete explanation of `**user_dict` check back in [the documentation for **Extra Models**](../extra-models.md#about-user-in-model-dump). /// @@ -190,7 +190,7 @@ We want to get the `current_user` *only* if this user is active. So, we create an additional dependency `get_current_active_user` that in turn uses `get_current_user` as a dependency. -Both of these dependencies will just return an HTTP error if the user doesn't exist, or if is inactive. +Both of these dependencies will just return an HTTP error if the user doesn't exist, or is inactive. So, in our endpoint, we will only get a user if the user exists, was correctly authenticated, and is active: diff --git a/docs/en/docs/tutorial/sql-databases.md b/docs/en/docs/tutorial/sql-databases.md index b8cbac295..1f4b12ca9 100644 --- a/docs/en/docs/tutorial/sql-databases.md +++ b/docs/en/docs/tutorial/sql-databases.md @@ -201,7 +201,7 @@ Then let's create `Hero`, the actual *table model*, with the **extra fields** th * `id` * `secret_name` -Because `Hero` inherits form `HeroBase`, it **also** has the **fields** declared in `HeroBase`, so all the fields for `Hero` are: +Because `Hero` inherits from `HeroBase`, it **also** has the **fields** declared in `HeroBase`, so all the fields for `Hero` are: * `id` * `name` diff --git a/docs/en/docs/tutorial/static-files.md b/docs/en/docs/tutorial/static-files.md index 38c2ef248..4b5057c08 100644 --- a/docs/en/docs/tutorial/static-files.md +++ b/docs/en/docs/tutorial/static-files.md @@ -2,6 +2,14 @@ You can serve static files automatically from a directory using `StaticFiles`. +/// tip + +If you need to host a frontend, use `app.frontend()` instead, read about it in [Frontend](frontend.md). + +`app.frontend()` uses `StaticFiles` underneath, with several additional advantages for frontends, like handling client-side routing. + +/// + ## Use `StaticFiles` { #use-staticfiles } * Import `StaticFiles`. @@ -33,7 +41,7 @@ The `directory="static"` refers to the name of the directory that contains your The `name="static"` gives it a name that can be used internally by **FastAPI**. -All these parameters can be different than "`static`", adjust them with the needs and specific details of your own application. +All these parameters can be different than "`static`", adjust them to the needs and specific details of your own application. ## More info { #more-info } diff --git a/docs/en/docs/tutorial/testing.md b/docs/en/docs/tutorial/testing.md index 72f849f4b..38976dc31 100644 --- a/docs/en/docs/tutorial/testing.md +++ b/docs/en/docs/tutorial/testing.md @@ -24,7 +24,7 @@ Import `TestClient`. Create a `TestClient` by passing your **FastAPI** application to it. -Create functions with a name that starts with `test_` (this is standard `pytest` conventions). +Create functions with a name that starts with `test_` (this is a standard `pytest` convention). Use the `TestClient` object the same way as you do with `httpx`. diff --git a/docs/en/docs/virtual-environments.md b/docs/en/docs/virtual-environments.md index 119a6926a..7f95cad24 100644 --- a/docs/en/docs/virtual-environments.md +++ b/docs/en/docs/virtual-environments.md @@ -100,7 +100,7 @@ $ uv venv By default, `uv` will create a virtual environment in a directory called `.venv`. -But you could customize it passing an additional argument with the directory name. +But you could customize it by passing an additional argument with the directory name. /// @@ -258,7 +258,7 @@ $ python -m ensurepip --upgrade -This command will install pip if it is not already installed and also ensures that the installed version of pip is at least as recent as the one available in `ensurepip`. +This command will install pip if it is not already installed and also ensure that the installed version of pip is at least as recent as the one available in `ensurepip`. /// @@ -447,7 +447,7 @@ Now you're ready to start working on your project. /// tip -Do you want to understand what's all that above? +Do you want to understand what all that above is? Continue reading. 👇🤓 @@ -548,7 +548,7 @@ Also, depending on your operating system (e.g. Linux, Windows, macOS), it could ## Where are Packages Installed { #where-are-packages-installed } -When you install Python, it creates some directories with some files in your computer. +When you install Python, it creates some directories with some files on your computer. Some of these directories are the ones in charge of having all the packages you install. @@ -568,7 +568,7 @@ That will download a compressed file with the FastAPI code, normally from [PyPI] It will also **download** files for other packages that FastAPI depends on. -Then it will **extract** all those files and put them in a directory in your computer. +Then it will **extract** all those files and put them in a directory on your computer. By default, it will put those files downloaded and extracted in the directory that comes with your Python installation, that's the **global environment**. @@ -846,7 +846,7 @@ This is a simple guide to get you started and teach you how everything works **u There are many **alternatives** to managing virtual environments, package dependencies (requirements), projects. -Once you are ready and want to use a tool to **manage the entire project**, packages dependencies, virtual environments, etc. I would suggest you try [uv](https://github.com/astral-sh/uv). +Once you are ready and want to use a tool to **manage the entire project**, package dependencies, virtual environments, etc. I would suggest you try [uv](https://github.com/astral-sh/uv). `uv` can do a lot of things, it can: diff --git a/docs/en/mkdocs.yml b/docs/en/mkdocs.yml index 6393f3844..884307dcf 100644 --- a/docs/en/mkdocs.yml +++ b/docs/en/mkdocs.yml @@ -133,6 +133,7 @@ nav: - tutorial/server-sent-events.md - tutorial/background-tasks.md - tutorial/metadata.md + - tutorial/frontend.md - tutorial/static-files.md - tutorial/testing.md - tutorial/debugging.md @@ -303,6 +304,8 @@ extra: name: es - español - link: /fr/ name: fr - français + - link: /hi/ + name: hi - हिन्दी - link: /ja/ name: ja - 日本語 - link: /ko/ diff --git a/docs/en/overrides/main.html b/docs/en/overrides/main.html index 7559de529..1905a6573 100644 --- a/docs/en/overrides/main.html +++ b/docs/en/overrides/main.html @@ -7,7 +7,7 @@
{% include ".icons/material/cloud-arrow-up.svg" %} - Join the FastAPI Cloud waiting list 🚀 + Deploy on FastAPI Cloud 🚀
@@ -40,66 +40,7 @@
-
- - - - -
-
- - - - -
-
- - - - -
-
- - - - -
-
- - - - -
-
- - - - -
-
- - - - -
-
- - - - -
-
- - - - -
-
- - - - -
+ {% include "partials/banner-sponsors.html" %}
{% endblock %} diff --git a/docs/en/overrides/partials/banner-sponsors.html b/docs/en/overrides/partials/banner-sponsors.html new file mode 100644 index 000000000..ae689ad89 --- /dev/null +++ b/docs/en/overrides/partials/banner-sponsors.html @@ -0,0 +1,48 @@ +
+ + + + +
+
+ + + + +
+
+ + + + +
+
+ + + + +
+
+ + + + +
+
+ + + + +
+
+ + + + +
+
+ + + + +
diff --git a/docs/es/docs/_llm-test.md b/docs/es/docs/_llm-test.md index d0ffcc540..e5191d9da 100644 --- a/docs/es/docs/_llm-test.md +++ b/docs/es/docs/_llm-test.md @@ -197,7 +197,7 @@ Aquí algunas cosas envueltas en elementos HTML "abbr" (algunas son inventadas): ### El abbr da una frase completa y una explicación { #the-abbr-gives-a-full-phrase-and-an-explanation } * MDN -* I/O. +* I/O. //// @@ -464,7 +464,7 @@ Para instrucciones específicas del idioma, mira p. ej. la sección `### Heading * el middleware * la aplicación móvil * el módulo -* el mount +* el mounting * la red * el origen * el override diff --git a/docs/es/docs/advanced/additional-responses.md b/docs/es/docs/advanced/additional-responses.md index 83053d3a9..6695caf1b 100644 --- a/docs/es/docs/advanced/additional-responses.md +++ b/docs/es/docs/advanced/additional-responses.md @@ -34,7 +34,7 @@ Ten en cuenta que debes devolver el `JSONResponse` directamente. /// -/// info | Información +/// note | Nota La clave `model` no es parte de OpenAPI. @@ -183,7 +183,7 @@ Nota que debes devolver la imagen usando un `FileResponse` directamente. /// -/// info | Información +/// note | Nota A menos que especifiques un media type diferente explícitamente en tu parámetro `responses`, FastAPI asumirá que el response tiene el mismo media type que la clase de response principal (por defecto `application/json`). diff --git a/docs/es/docs/advanced/additional-status-codes.md b/docs/es/docs/advanced/additional-status-codes.md index 5c0ab6980..ea6db5feb 100644 --- a/docs/es/docs/advanced/additional-status-codes.md +++ b/docs/es/docs/advanced/additional-status-codes.md @@ -1,5 +1,6 @@ # Códigos de Estado Adicionales { #additional-status-codes } + Por defecto, **FastAPI** devolverá los responses usando un `JSONResponse`, colocando el contenido que devuelves desde tu *path operation* dentro de ese `JSONResponse`. Usará el código de estado por defecto o el que configures en tu *path operation*. diff --git a/docs/es/docs/advanced/advanced-dependencies.md b/docs/es/docs/advanced/advanced-dependencies.md index cee93692d..47e9d72a0 100644 --- a/docs/es/docs/advanced/advanced-dependencies.md +++ b/docs/es/docs/advanced/advanced-dependencies.md @@ -10,7 +10,7 @@ Imaginemos que queremos tener una dependencia que revise si el parámetro de que Pero queremos poder parametrizar ese contenido fijo. -## Una *instance* "callable" { #a-callable-instance } +## Una instance "callable" { #a-callable-instance } En Python hay una forma de hacer que una instance de una clase sea un "callable". @@ -98,7 +98,7 @@ Por ejemplo, si tenías una sesión de base de datos en una dependencia con `yie Este comportamiento se revirtió en la 0.118.0, para hacer que el código de salida después de `yield` se ejecute después de que la response sea enviada. -/// info | Información +/// note | Nota Como verás abajo, esto es muy similar al comportamiento anterior a la versión 0.106.0, pero con varias mejoras y arreglos de bugs para casos límite. @@ -108,7 +108,7 @@ Como verás abajo, esto es muy similar al comportamiento anterior a la versión Hay algunos casos de uso con condiciones específicas que podrían beneficiarse del comportamiento antiguo de ejecutar el código de salida de dependencias con `yield` antes de enviar la response. -Por ejemplo, imagina que tienes código que usa una sesión de base de datos en una dependencia con `yield` solo para verificar un usuario, pero la sesión de base de datos no se vuelve a usar en la *path operation function*, solo en la dependencia, y la response tarda mucho en enviarse, como un `StreamingResponse` que envía datos lentamente, pero que por alguna razón no usa la base de datos. +Por ejemplo, imagina que tienes código que usa una sesión de base de datos en una dependencia con `yield` solo para verificar un usuario, pero la sesión de base de datos no se vuelve a usar en la *path operation function*, solo en la dependencia, **y** la response tarda mucho en enviarse, como un `StreamingResponse` que envía datos lentamente, pero que por alguna razón no usa la base de datos. En este caso, la sesión de base de datos se mantendría hasta que la response termine de enviarse, pero si no la usas, entonces no sería necesario mantenerla. diff --git a/docs/es/docs/advanced/custom-response.md b/docs/es/docs/advanced/custom-response.md index e1db10147..838118cca 100644 --- a/docs/es/docs/advanced/custom-response.md +++ b/docs/es/docs/advanced/custom-response.md @@ -24,7 +24,7 @@ Si declaras un [Response Model](../tutorial/response-model.md) FastAPI lo usará Si no declaras un response model, FastAPI usará el `jsonable_encoder` explicado en [Codificador Compatible con JSON](../tutorial/encoder.md) y lo pondrá en un `JSONResponse`. -Si declaras un `response_class` con un media type JSON (`application/json`), como es el caso con `JSONResponse`, los datos que devuelvas se convertirán automáticamente (y serán filtrados) con cualquier `response_model` de Pydantic que hayas declarado en el *path operation decorator*. Pero los datos no se serializarán a bytes JSON con Pydantic, en su lugar se convertirán con el `jsonable_encoder` y luego se pasarán a la clase `JSONResponse`, que los serializará a bytes usando la librería JSON estándar de Python. +Si declaras un `response_class` con un media type JSON (`application/json`), como es el caso con `JSONResponse`, los datos que devuelvas se convertirán automáticamente (y serán filtrados) con cualquier `response_model` de Pydantic que hayas declarado en el *path operation decorator*. Pero los datos no se serializarán a bytes JSON con Pydantic, en su lugar se convertirán con el `jsonable_encoder` y luego se pasarán a la clase `JSONResponse`, que los serializará a bytes usando el paquete JSON estándar de Python. ### Rendimiento JSON { #json-performance } @@ -41,7 +41,7 @@ Para devolver un response con HTML directamente desde **FastAPI**, usa `HTMLResp {* ../../docs_src/custom_response/tutorial002_py310.py hl[2,7] *} -/// info | Información +/// note | Nota El parámetro `response_class` también se utilizará para definir el "media type" del response. @@ -65,7 +65,7 @@ Una `Response` devuelta directamente por tu *path operation function* no se docu /// -/// info | Información +/// note | Nota Por supuesto, el `Content-Type` header real, el código de estado, etc., provendrán del objeto `Response` que devolviste. @@ -181,7 +181,7 @@ Toma un generador `async` o un generador/iterador normal (una función con `yiel Una tarea `async` solo puede cancelarse cuando llega a un `await`. Si no hay `await`, el generador (función con `yield`) no se puede cancelar correctamente y puede seguir ejecutándose incluso después de solicitar la cancelación. -Como este pequeño ejemplo no necesita ninguna sentencia `await`, añadimos un `await anyio.sleep(0)` para darle al loop de eventos la oportunidad de manejar la cancelación. +Como este pequeño ejemplo no necesita ninguna statement `await`, añadimos un `await anyio.sleep(0)` para darle al loop de eventos la oportunidad de manejar la cancelación. Esto sería aún más importante con streams grandes o infinitos. diff --git a/docs/es/docs/advanced/dataclasses.md b/docs/es/docs/advanced/dataclasses.md index 3ce5c754f..9c988dc37 100644 --- a/docs/es/docs/advanced/dataclasses.md +++ b/docs/es/docs/advanced/dataclasses.md @@ -18,7 +18,7 @@ Y por supuesto, soporta lo mismo: Esto funciona de la misma manera que con los modelos de Pydantic. Y en realidad se logra de la misma manera internamente, utilizando Pydantic. -/// info | Información +/// note | Nota Ten en cuenta que los dataclasses no pueden hacer todo lo que los modelos de Pydantic pueden hacer. @@ -82,7 +82,7 @@ En ese caso, simplemente puedes intercambiar los `dataclasses` estándar con `py Puedes combinar `dataclasses` con otras anotaciones de tipos en muchas combinaciones diferentes para formar estructuras de datos complejas. -Revisa las anotaciones en el código arriba para ver más detalles específicos. +Revisa los consejos de anotación en el código arriba para ver más detalles específicos. ## Aprende Más { #learn-more } diff --git a/docs/es/docs/advanced/events.md b/docs/es/docs/advanced/events.md index 264ee27ed..1d221e033 100644 --- a/docs/es/docs/advanced/events.md +++ b/docs/es/docs/advanced/events.md @@ -6,13 +6,13 @@ De la misma manera, puedes definir lógica (código) que debería ser ejecutada Debido a que este código se ejecuta antes de que la aplicación **comience** a tomar requests, y justo después de que **termine** de manejarlos, cubre todo el **lifespan** de la aplicación (la palabra "lifespan" será importante en un momento 😉). -Esto puede ser muy útil para configurar **recursos** que necesitas usar para toda la app, y que son **compartidos** entre requests, y/o que necesitas **limpiar** después. Por ejemplo, un pool de conexiones a una base de datos, o cargando un modelo de machine learning compartido. +Esto puede ser muy útil para configurar **recursos** que necesitas usar para toda la app, y que son **compartidos** entre requests, y/o que necesitas **limpiar** después. Por ejemplo, un pool de conexiones a una base de datos, o cargando un modelo de Machine Learning compartido. ## Caso de Uso { #use-case } Empecemos con un ejemplo de **caso de uso** y luego veamos cómo resolverlo con esto. -Imaginemos que tienes algunos **modelos de machine learning** que quieres usar para manejar requests. 🤖 +Imaginemos que tienes algunos **modelos de Machine Learning** que quieres usar para manejar requests. 🤖 Los mismos modelos son compartidos entre requests, por lo que no es un modelo por request, o uno por usuario o algo similar. @@ -32,7 +32,7 @@ Creamos una función asíncrona `lifespan()` con `yield` así: {* ../../docs_src/events/tutorial003_py310.py hl[16,19] *} -Aquí estamos simulando la operación costosa de *startup* de cargar el modelo poniendo la función del (falso) modelo en el diccionario con modelos de machine learning antes del `yield`. Este código será ejecutado **antes** de que la aplicación **comience a tomar requests**, durante el *startup*. +Aquí estamos simulando la operación costosa de *startup* de cargar el modelo poniendo la función del (falso) modelo en el diccionario con modelos de Machine Learning antes del `yield`. Este código será ejecutado **antes** de que la aplicación **comience a tomar requests**, durante el *startup*. Y luego, justo después del `yield`, quitaremos el modelo de memoria. Este código será ejecutado **después** de que la aplicación **termine de manejar requests**, justo antes del *shutdown*. Esto podría, por ejemplo, liberar recursos como la memoria o una GPU. @@ -120,7 +120,7 @@ Para añadir una función que debería ejecutarse cuando la aplicación se esté Aquí, la función manejadora del evento `shutdown` escribirá una línea de texto `"Application shutdown"` a un archivo `log.txt`. -/// info | Información +/// note | Nota En la función `open()`, el `mode="a"` significa "añadir", por lo tanto, la línea será añadida después de lo que sea que esté en ese archivo, sin sobrescribir el contenido anterior. @@ -152,7 +152,7 @@ Solo un detalle técnico para los nerds curiosos. 🤓 Por debajo, en la especificación técnica ASGI, esto es parte del [Protocolo de Lifespan](https://asgi.readthedocs.io/en/latest/specs/lifespan.html), y define eventos llamados `startup` y `shutdown`. -/// info | Información +/// note | Nota Puedes leer más sobre los manejadores `lifespan` de Starlette en [la documentación de `Lifespan` de Starlette](https://www.starlette.dev/lifespan/). diff --git a/docs/es/docs/advanced/generate-clients.md b/docs/es/docs/advanced/generate-clients.md index 534c5e98a..a44c92294 100644 --- a/docs/es/docs/advanced/generate-clients.md +++ b/docs/es/docs/advanced/generate-clients.md @@ -20,21 +20,6 @@ FastAPI genera automáticamente especificaciones **OpenAPI 3.1**, así que cualq /// -## Generadores de SDKs de sponsors de FastAPI { #sdk-generators-from-fastapi-sponsors } - -Esta sección destaca soluciones **respaldadas por empresas** y **venture-backed** de compañías que sponsorean FastAPI. Estos productos ofrecen **funcionalidades adicionales** e **integraciones** además de SDKs generados de alta calidad. - -Al ✨ [**sponsorear FastAPI**](../help-fastapi.md#sponsor-the-author) ✨, estas compañías ayudan a asegurar que el framework y su **ecosistema** se mantengan saludables y **sustentables**. - -Su sponsorship también demuestra un fuerte compromiso con la **comunidad** de FastAPI (tú), mostrando que no solo les importa ofrecer un **gran servicio**, sino también apoyar un **framework robusto y próspero**, FastAPI. 🙇 - -Por ejemplo, podrías querer probar: - -* [Stainless](https://www.stainless.com/?utm_source=fastapi&utm_medium=referral) -* [liblab](https://developers.liblab.com/tutorials/sdk-for-fastapi?utm_source=fastapi) - -Algunas de estas soluciones también pueden ser open source u ofrecer niveles gratuitos, así que puedes probarlas sin un compromiso financiero. Hay otros generadores de SDK comerciales disponibles y se pueden encontrar en línea. 🤓 - ## Crea un SDK de TypeScript { #create-a-typescript-sdk } Empecemos con una aplicación simple de FastAPI: @@ -53,7 +38,7 @@ Puedes ver esos esquemas porque fueron declarados con los modelos en la app. Esa información está disponible en el **OpenAPI schema** de la app, y luego se muestra en la documentación de la API. -Y esa misma información de los modelos que está incluida en OpenAPI es lo que puede usarse para **generar el código del cliente**. +Esa misma información de los modelos que está incluida en OpenAPI es lo que puede usarse para **generar el código del cliente**. ### Hey API { #hey-api } @@ -132,7 +117,7 @@ Puedes **modificar** la forma en que estos operation IDs son **generados** para En este caso tendrás que asegurarte de que cada operation ID sea **único** de alguna otra manera. -Por ejemplo, podrías asegurarte de que cada *path operation* tenga un tag, y luego generar el operation ID basado en el **tag** y el **name** de la *path operation* (el nombre de la función). +Por ejemplo, podrías asegurarte de que cada *path operation* tenga un tag, y luego generar el operation ID basado en el **tag** y el **nombre** de la *path operation* (el nombre de la función). ### Función personalizada para generar ID único { #custom-generate-unique-id-function } diff --git a/docs/es/docs/advanced/json-base64-bytes.md b/docs/es/docs/advanced/json-base64-bytes.md index 12936722c..8c0bcfe09 100644 --- a/docs/es/docs/advanced/json-base64-bytes.md +++ b/docs/es/docs/advanced/json-base64-bytes.md @@ -4,7 +4,7 @@ Si tu app necesita recibir y enviar datos JSON, pero necesitas incluir datos bin ## Base64 vs Archivos { #base64-vs-files } -Considera primero si puedes usar [Archivos en request](../tutorial/request-files.md) para subir datos binarios y [Response personalizada - FileResponse](./custom-response.md#fileresponse--fileresponse-) para enviar datos binarios, en lugar de codificarlos en JSON. +Considera primero si puedes usar [Archivos en request](../tutorial/request-files.md) para subir datos binarios y [Response personalizada - FileResponse](./custom-response.md#fileresponse) para enviar datos binarios, en lugar de codificarlos en JSON. JSON solo puede contener strings codificados en UTF-8, así que no puede contener bytes crudos. @@ -14,7 +14,7 @@ Usa base64 solo si definitivamente necesitas incluir datos binarios en JSON y no ## Pydantic `bytes` { #pydantic-bytes } -Puedes declarar un modelo de Pydantic con campos `bytes`, y luego usar `val_json_bytes` en la configuración del modelo para indicarle que use base64 para validar datos JSON de entrada; como parte de esa validación decodificará el string base64 en bytes. +Puedes declarar un modelo de Pydantic con campos `bytes`, y luego usar `val_json_bytes` en la configuración del modelo para indicarle que use base64 para *validar* datos JSON de entrada; como parte de esa validación decodificará el string base64 en bytes. {* ../../docs_src/json_base64_bytes/tutorial001_py310.py ln[1:9,29:35] hl[9] *} @@ -52,12 +52,12 @@ Recibirás una response como: ## Pydantic `bytes` para datos de salida { #pydantic-bytes-for-output-data } -También puedes usar campos `bytes` con `ser_json_bytes` en la configuración del modelo para datos de salida, y Pydantic serializará los bytes como base64 al generar la response JSON. +También puedes usar campos `bytes` con `ser_json_bytes` en la configuración del modelo para datos de salida, y Pydantic *serializará* los bytes como base64 al generar la response JSON. {* ../../docs_src/json_base64_bytes/tutorial001_py310.py ln[1:2,12:16,29,38:41] hl[16] *} ## Pydantic `bytes` para datos de entrada y salida { #pydantic-bytes-for-input-and-output-data } -Y por supuesto, puedes usar el mismo modelo configurado para usar base64 para manejar tanto la entrada (*validate*) con `val_json_bytes` como la salida (*serialize*) con `ser_json_bytes` al recibir y enviar datos JSON. +Y por supuesto, puedes usar el mismo modelo configurado para usar base64 para manejar tanto la entrada (*validar*) con `val_json_bytes` como la salida (*serializar*) con `ser_json_bytes` al recibir y enviar datos JSON. {* ../../docs_src/json_base64_bytes/tutorial001_py310.py ln[1:2,19:26,29,44:46] hl[23:26] *} diff --git a/docs/es/docs/advanced/openapi-callbacks.md b/docs/es/docs/advanced/openapi-callbacks.md index 5e3a1572c..6b04f2da0 100644 --- a/docs/es/docs/advanced/openapi-callbacks.md +++ b/docs/es/docs/advanced/openapi-callbacks.md @@ -4,7 +4,7 @@ Podrías crear una API con una *path operation* que podría desencadenar un requ El proceso que ocurre cuando tu aplicación API llama a la *API externa* se llama un "callback". Porque el software que escribió el desarrollador externo envía un request a tu API y luego tu API hace un *callback*, enviando un request a una *API externa* (que probablemente fue creada por el mismo desarrollador). -En este caso, podrías querer documentar cómo esa API externa *debería* verse. Qué *path operation* debería tener, qué cuerpo debería esperar, qué response debería devolver, etc. +En este caso, podrías querer documentar cómo esa API externa *debería* verse. Qué *path operation* debería tener, qué body debería esperar, qué response debería devolver, etc. ## Una aplicación con callbacks { #an-app-with-callbacks } @@ -167,13 +167,13 @@ Observa cómo la URL del callback utilizada contiene la URL recibida como parám En este punto tienes las *path operation(s)* del callback necesarias (las que el *desarrollador externo* debería implementar en la *API externa*) en el router de callback que creaste arriba. -Ahora usa el parámetro `callbacks` en el *decorador de path operation de tu API* para pasar el atributo `.routes` (que en realidad es solo un `list` de rutas/*path operations*) de ese router de callback: +Ahora usa el parámetro `callbacks` en el *decorador de path operation de tu API* para pasar el atributo `.routes` de ese router de callback: {* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[33] *} /// tip | Consejo -Observa que no estás pasando el router en sí (`invoices_callback_router`) a `callback=`, sino el atributo `.routes`, como en `invoices_callback_router.routes`. +Observa que no estás pasando el router en sí (`invoices_callback_router`) a `callbacks=`, sino su `.routes`, como en `invoices_callback_router.routes`. FastAPI usará esas rutas para generar la documentación OpenAPI del callback. /// diff --git a/docs/es/docs/advanced/openapi-webhooks.md b/docs/es/docs/advanced/openapi-webhooks.md index 163293f83..9e51735b1 100644 --- a/docs/es/docs/advanced/openapi-webhooks.md +++ b/docs/es/docs/advanced/openapi-webhooks.md @@ -22,7 +22,7 @@ Con **FastAPI**, usando OpenAPI, puedes definir los nombres de estos webhooks, l Esto puede hacer mucho más fácil para tus usuarios **implementar sus APIs** para recibir tus requests de **webhook**, incluso podrían ser capaces de autogenerar algo de su propio código de API. -/// info | Información +/// note | Nota Los webhooks están disponibles en OpenAPI 3.1.0 y superiores, soportados por FastAPI `0.99.0` y superiores. @@ -36,7 +36,7 @@ Cuando creas una aplicación de **FastAPI**, hay un atributo `webhooks` que pued Los webhooks que defines terminarán en el esquema de **OpenAPI** y en la interfaz automática de **documentación**. -/// info | Información +/// note | Nota El objeto `app.webhooks` es en realidad solo un `APIRouter`, el mismo tipo que usarías al estructurar tu aplicación con múltiples archivos. diff --git a/docs/es/docs/advanced/path-operation-advanced-configuration.md b/docs/es/docs/advanced/path-operation-advanced-configuration.md index a21975bc7..99fb14017 100644 --- a/docs/es/docs/advanced/path-operation-advanced-configuration.md +++ b/docs/es/docs/advanced/path-operation-advanced-configuration.md @@ -16,17 +16,11 @@ Tendrías que asegurarte de que sea único para cada operación. ### Usar el nombre de la *path operation function* como el operationId { #using-the-path-operation-function-name-as-the-operationid } -Si quieres usar los nombres de las funciones de tus APIs como `operationId`s, puedes iterar sobre todas ellas y sobrescribir el `operation_id` de cada *path operation* usando su `APIRoute.name`. +Si quieres usar los nombres de las funciones de tus APIs como `operationId`s, puedes pasar una `generate_unique_id_function` personalizada a `FastAPI`. -Deberías hacerlo después de agregar todas tus *path operations*. +La función recibe cada `APIRoute` y devuelve el `operationId` a usar para esa *path operation*. -{* ../../docs_src/path_operation_advanced_configuration/tutorial002_py310.py hl[2, 12:21, 24] *} - -/// tip | Consejo - -Si llamas manualmente a `app.openapi()`, deberías actualizar los `operationId`s antes de eso. - -/// +{* ../../docs_src/path_operation_advanced_configuration/tutorial002_py310.py hl[2,5:6,9] *} /// warning | Advertencia diff --git a/docs/es/docs/advanced/response-change-status-code.md b/docs/es/docs/advanced/response-change-status-code.md index 859f484de..aa3c8bf42 100644 --- a/docs/es/docs/advanced/response-change-status-code.md +++ b/docs/es/docs/advanced/response-change-status-code.md @@ -2,7 +2,7 @@ Probablemente leíste antes que puedes establecer un [Código de Estado de Response](../tutorial/response-status-code.md) por defecto. -Pero en algunos casos necesitas devolver un código de estado diferente al predeterminado. +Pero en algunos casos necesitas devolver un código de estado diferente al por defecto. ## Caso de uso { #use-case } diff --git a/docs/es/docs/advanced/response-cookies.md b/docs/es/docs/advanced/response-cookies.md index e40a19129..917072cbe 100644 --- a/docs/es/docs/advanced/response-cookies.md +++ b/docs/es/docs/advanced/response-cookies.md @@ -1,6 +1,6 @@ # Cookies de Response { #response-cookies } -## Usar un parámetro `Response` { #use-a-response-parameter } +## Usa un parámetro `Response` { #use-a-response-parameter } Puedes declarar un parámetro de tipo `Response` en tu *path operation function*. @@ -16,11 +16,11 @@ Y si declaraste un `response_model`, todavía se utilizará para filtrar y conve También puedes declarar el parámetro `Response` en las dependencias, y establecer cookies (y headers) en ellas. -## Devolver una `Response` directamente { #return-a-response-directly } +## Devuelve una `Response` directamente { #return-a-response-directly } También puedes crear cookies al devolver una `Response` directamente en tu código. -Para hacer eso, puedes crear un response como se describe en [Devolver un Response Directamente](response-directly.md). +Para hacer eso, puedes crear un response como se describe en [Devuelve un Response Directamente](response-directly.md). Luego establece Cookies en ella, y luego devuélvela: diff --git a/docs/es/docs/advanced/response-directly.md b/docs/es/docs/advanced/response-directly.md index b2d5d18b8..fa05a3ed6 100644 --- a/docs/es/docs/advanced/response-directly.md +++ b/docs/es/docs/advanced/response-directly.md @@ -16,9 +16,9 @@ Normalmente tendrás mucho mejor rendimiento usando un [Response Model](../tutor ## Devolver una `Response` { #return-a-response } -De hecho, puedes devolver cualquier `Response` o cualquier subclase de ella. +Puedes devolver una `Response` o cualquier subclase de ella. -/// info | Información +/// note | Nota `JSONResponse` en sí misma es una subclase de `Response`. @@ -78,6 +78,6 @@ En su lugar, toma los bytes JSON generados con Pydantic usando el response model Cuando devuelves una `Response` directamente, sus datos no son validados, convertidos (serializados), ni documentados automáticamente. -Pero aún puedes documentarlo como se describe en [Additional Responses in OpenAPI](additional-responses.md). +Pero aún puedes documentarlo como se describe en [Respuestas adicionales en OpenAPI](additional-responses.md). Puedes ver en secciones posteriores cómo usar/declarar estas `Response`s personalizadas mientras todavía tienes conversión automática de datos, documentación, etc. diff --git a/docs/es/docs/advanced/response-headers.md b/docs/es/docs/advanced/response-headers.md index 06107eb2d..e2eb8f550 100644 --- a/docs/es/docs/advanced/response-headers.md +++ b/docs/es/docs/advanced/response-headers.md @@ -1,5 +1,6 @@ # Headers de Response { #response-headers } + ## Usa un parámetro `Response` { #use-a-response-parameter } Puedes declarar un parámetro de tipo `Response` en tu *path operation function* (como puedes hacer para cookies). diff --git a/docs/es/docs/advanced/security/oauth2-scopes.md b/docs/es/docs/advanced/security/oauth2-scopes.md index 6ee3dd5ac..e399cd855 100644 --- a/docs/es/docs/advanced/security/oauth2-scopes.md +++ b/docs/es/docs/advanced/security/oauth2-scopes.md @@ -1,5 +1,6 @@ # Scopes de OAuth2 { #oauth2-scopes } + Puedes usar scopes de OAuth2 directamente con **FastAPI**, están integrados para funcionar de manera fluida. Esto te permitiría tener un sistema de permisos más detallado, siguiendo el estándar de OAuth2, integrado en tu aplicación OpenAPI (y la documentación de la API). @@ -46,7 +47,7 @@ Normalmente se utilizan para declarar permisos de seguridad específicos, por ej * `instagram_basic` es usado por Facebook / Instagram. * `https://www.googleapis.com/auth/drive` es usado por Google. -/// info | Información +/// note | Nota En OAuth2 un "scope" es solo un string que declara un permiso específico requerido. @@ -126,7 +127,7 @@ Lo estamos haciendo aquí para demostrar cómo **FastAPI** maneja scopes declara {* ../../docs_src/security/tutorial005_an_py310.py hl[5,141,172] *} -/// info | Información Técnica +/// note | Detalles técnicos `Security` es en realidad una subclase de `Depends`, y tiene solo un parámetro extra que veremos más adelante. diff --git a/docs/es/docs/advanced/settings.md b/docs/es/docs/advanced/settings.md index 2411ddc45..e61229f0d 100644 --- a/docs/es/docs/advanced/settings.md +++ b/docs/es/docs/advanced/settings.md @@ -20,7 +20,7 @@ Eso significa que cualquier valor leído en Python desde una variable de entorno ## Pydantic `Settings` { #pydantic-settings } -Afortunadamente, Pydantic proporciona una gran utilidad para manejar estas configuraciones provenientes de variables de entorno con [Pydantic: Settings management](https://docs.pydantic.dev/latest/concepts/pydantic_settings/). +Afortunadamente, Pydantic proporciona una gran utilidad para manejar estas configuraciones provenientes de variables de entorno con [Pydantic: Gestión de Settings](https://docs.pydantic.dev/latest/concepts/pydantic_settings/). ### Instalar `pydantic-settings` { #install-pydantic-settings } @@ -120,7 +120,7 @@ También necesitarías un archivo `__init__.py` como viste en [Aplicaciones Más En algunas ocasiones podría ser útil proporcionar las configuraciones desde una dependencia, en lugar de tener un objeto global con `settings` que se use en todas partes. -Esto podría ser especialmente útil durante las pruebas, ya que es muy fácil sobrescribir una dependencia con tus propias configuraciones personalizadas. +Esto podría ser especialmente útil al escribir pruebas, ya que es muy fácil sobrescribir una dependencia con tus propias configuraciones personalizadas. ### El archivo de configuración { #the-config-file } @@ -148,9 +148,9 @@ Y luego podemos requerirlo desde la *path operation function* como una dependenc {* ../../docs_src/settings/app02_an_py310/main.py hl[17,19:21] *} -### Configuraciones y pruebas { #settings-and-testing } +### Configuraciones y escribir pruebas { #settings-and-testing } -Luego sería muy fácil proporcionar un objeto de configuraciones diferente durante las pruebas al crear una sobrescritura de dependencia para `get_settings`: +Luego sería muy fácil proporcionar un objeto de configuraciones diferente al escribir pruebas creando una sobrescritura de dependencia para `get_settings`: {* ../../docs_src/settings/app02_an_py310/test_main.py hl[9:10,13,21] *} @@ -160,7 +160,7 @@ Luego podemos probar que se está usando. ## Leer un archivo `.env` { #reading-a-env-file } -Si tienes muchas configuraciones que posiblemente cambien mucho, tal vez en diferentes entornos, podría ser útil ponerlos en un archivo y luego leerlos desde allí como si fueran variables de entorno. +Si tienes muchas configuraciones que posiblemente cambien mucho, tal vez en diferentes entornos, podría ser útil ponerlas en un archivo y luego leerlas desde allí como si fueran variables de entorno. Esta práctica es lo suficientemente común que tiene un nombre, estas variables de entorno generalmente se colocan en un archivo `.env`, y el archivo se llama un "dotenv". @@ -172,7 +172,7 @@ Pero un archivo dotenv realmente no tiene que tener ese nombre exacto. /// -Pydantic tiene soporte para leer desde estos tipos de archivos usando un paquete externo. Puedes leer más en [Pydantic Settings: Dotenv (.env) support](https://docs.pydantic.dev/latest/concepts/pydantic_settings/#dotenv-env-support). +Pydantic tiene soporte para leer desde estos tipos de archivos usando un paquete externo. Puedes leer más en [Pydantic Settings: soporte para Dotenv (.env)](https://docs.pydantic.dev/latest/concepts/pydantic_settings/#dotenv-env-support). /// tip | Consejo @@ -197,7 +197,7 @@ Y luego actualizar tu `config.py` con: /// tip | Consejo -El atributo `model_config` se usa solo para configuración de Pydantic. Puedes leer más en [Pydantic: Concepts: Configuration](https://docs.pydantic.dev/latest/concepts/config/). +El atributo `model_config` se usa solo para configuración de Pydantic. Puedes leer más en [Pydantic: Conceptos: Configuración](https://docs.pydantic.dev/latest/concepts/config/). /// @@ -289,14 +289,14 @@ participant execute as Ejecutar función En el caso de nuestra dependencia `get_settings()`, la función ni siquiera toma argumentos, por lo que siempre devuelve el mismo valor. -De esa manera, se comporta casi como si fuera solo una variable global. Pero como usa una función de dependencia, entonces podemos sobrescribirla fácilmente para las pruebas. +De esa manera, se comporta casi como si fuera solo una variable global. Pero como usa una función de dependencia, entonces podemos sobrescribirla fácilmente al escribir pruebas. -`@lru_cache` es parte de `functools`, que es parte del paquete estándar de Python, puedes leer más sobre él en las [docs de Python para `@lru_cache`](https://docs.python.org/3/library/functools.html#functools.lru_cache). +`@lru_cache` es parte de `functools`, que es parte del paquete estándar de Python, puedes leer más sobre él en la [documentación de Python para `@lru_cache`](https://docs.python.org/3/library/functools.html#functools.lru_cache). ## Resumen { #recap } Puedes usar Pydantic Settings para manejar las configuraciones o ajustes de tu aplicación, con todo el poder de los modelos de Pydantic. -* Al usar una dependencia, puedes simplificar las pruebas. +* Al usar una dependencia, puedes simplificar la escritura de pruebas. * Puedes usar archivos `.env` con él. -* Usar `@lru_cache` te permite evitar leer el archivo dotenv una y otra vez para cada request, mientras te permite sobrescribirlo durante las pruebas. +* Usar `@lru_cache` te permite evitar leer el archivo dotenv una y otra vez para cada request, mientras te permite sobrescribirlo al escribir pruebas. diff --git a/docs/es/docs/advanced/stream-data.md b/docs/es/docs/advanced/stream-data.md index 964a9ed58..68c89ce44 100644 --- a/docs/es/docs/advanced/stream-data.md +++ b/docs/es/docs/advanced/stream-data.md @@ -2,9 +2,9 @@ Si quieres transmitir datos que se puedan estructurar como JSON, deberías [Transmitir JSON Lines](../tutorial/stream-json-lines.md). -Pero si quieres transmitir datos binarios puros o strings, aquí tienes cómo hacerlo. +Pero si quieres **transmitir datos binarios puros** o strings, aquí tienes cómo hacerlo. -/// info | Información +/// note | Nota Añadido en FastAPI 0.134.0. @@ -12,11 +12,11 @@ Añadido en FastAPI 0.134.0. ## Casos de uso { #use-cases } -Podrías usar esto si quieres transmitir strings puros, por ejemplo directamente de la salida de un servicio de AI LLM. +Podrías usar esto si quieres transmitir strings puros, por ejemplo directamente de la salida de un servicio de **AI LLM**. -También podrías usarlo para transmitir archivos binarios grandes, donde transmites cada bloque de datos a medida que lo lees, sin tener que leerlo todo en memoria de una sola vez. +También podrías usarlo para transmitir **archivos binarios grandes**, donde transmites cada bloque de datos a medida que lo lees, sin tener que leerlo todo en memoria de una sola vez. -También podrías transmitir video o audio de esta manera; incluso podría generarse mientras lo procesas y lo envías. +También podrías transmitir **video** o **audio** de esta manera; incluso podría generarse mientras lo procesas y lo envías. ## Un `StreamingResponse` con `yield` { #a-streamingresponse-with-yield } @@ -40,7 +40,7 @@ Como FastAPI no intentará convertir los datos a JSON con Pydantic ni serializar {* ../../docs_src/stream_data/tutorial001_py310.py ln[32:35] hl[33] *} -Esto también significa que con `StreamingResponse` tienes la libertad y la responsabilidad de producir y codificar los bytes de datos exactamente como necesites enviarlos, independientemente de las anotaciones de tipos. 🤓 +Esto también significa que con `StreamingResponse` tienes la **libertad** y la **responsabilidad** de producir y codificar los bytes de datos exactamente como necesites enviarlos, independientemente de las anotaciones de tipos. 🤓 ### Transmitir bytes { #stream-bytes } @@ -90,7 +90,7 @@ Por ejemplo, no tienen un `await file.read()`, ni un `async for chunk in file`. Y en muchos casos leerlos sería una operación bloqueante (que podría bloquear el event loop), porque se leen desde disco o desde la red. -/// info | Información +/// note | Nota El ejemplo anterior es en realidad una excepción, porque el objeto `io.BytesIO` ya está en memoria, así que leerlo no bloqueará nada. diff --git a/docs/es/docs/advanced/strict-content-type.md b/docs/es/docs/advanced/strict-content-type.md index 41615edf3..d8003dc9d 100644 --- a/docs/es/docs/advanced/strict-content-type.md +++ b/docs/es/docs/advanced/strict-content-type.md @@ -40,7 +40,7 @@ Ten en cuenta que ambos tienen el mismo host. Luego, usando el frontend, puedes hacer que el agente de IA haga cosas en tu nombre. -Como está corriendo localmente y no en Internet abierta, decides no tener ninguna autenticación configurada, confiando simplemente en el acceso a la red local. +Como está corriendo **localmente** y no en Internet abierta, decides **no tener ninguna autenticación** configurada, confiando simplemente en el acceso a la red local. Entonces, uno de tus usuarios podría instalarlo y ejecutarlo localmente. @@ -69,9 +69,9 @@ Si tu app está en Internet abierta, no “confiarías en la red” ni permitir Los atacantes podrían simplemente ejecutar un script para enviar requests a tu API, sin necesidad de interacción del navegador, así que probablemente ya estás asegurando cualquier endpoint privilegiado. -En ese caso, este ataque/riesgo no aplica a ti. +En ese caso, **este ataque/riesgo no aplica a ti**. -Este riesgo y ataque es relevante principalmente cuando la app corre en la red local y esa es la única protección asumida. +Este riesgo y ataque es relevante principalmente cuando la app corre en la **red local** y esa es la **única protección asumida**. ## Permitir requests sin Content-Type { #allowing-requests-without-content-type } @@ -81,7 +81,7 @@ Si necesitas soportar clientes que no envían un header `Content-Type`, puedes d Con esta configuración, las requests sin un header `Content-Type` tendrán su body parseado como JSON, que es el mismo comportamiento de versiones anteriores de FastAPI. -/// info | Información +/// note | Nota Este comportamiento y configuración se añadieron en FastAPI 0.132.0. diff --git a/docs/es/docs/advanced/websockets.md b/docs/es/docs/advanced/websockets.md index fe75e644b..e3e0ba554 100644 --- a/docs/es/docs/advanced/websockets.md +++ b/docs/es/docs/advanced/websockets.md @@ -111,7 +111,7 @@ Funcionan de la misma manera que para otros endpoints de FastAPI/*path operation {* ../../docs_src/websockets_/tutorial002_an_py310.py hl[68:69,82] *} -/// info | Información +/// note | Nota Como esto es un WebSocket no tiene mucho sentido lanzar un `HTTPException`, en su lugar lanzamos un `WebSocketException`. diff --git a/docs/es/docs/advanced/wsgi.md b/docs/es/docs/advanced/wsgi.md index 0d0c42fd5..c85b8cc89 100644 --- a/docs/es/docs/advanced/wsgi.md +++ b/docs/es/docs/advanced/wsgi.md @@ -1,12 +1,13 @@ # Incluyendo WSGI - Flask, Django, otros { #including-wsgi-flask-django-others } + Puedes montar aplicaciones WSGI como viste con [Sub Aplicaciones - Mounts](sub-applications.md), [Detrás de un Proxy](behind-a-proxy.md). Para eso, puedes usar el `WSGIMiddleware` y usarlo para envolver tu aplicación WSGI, por ejemplo, Flask, Django, etc. ## Usando `WSGIMiddleware` { #using-wsgimiddleware } -/// info | Información +/// note | Nota Esto requiere instalar `a2wsgi`, por ejemplo con `pip install a2wsgi`. diff --git a/docs/es/docs/alternatives.md b/docs/es/docs/alternatives.md index 3bc1bf969..693e4d511 100644 --- a/docs/es/docs/alternatives.md +++ b/docs/es/docs/alternatives.md @@ -24,7 +24,7 @@ Fue creado para generar el HTML en el backend, no para crear APIs utilizadas por ### [Django REST Framework](https://www.django-rest-framework.org/) { #django-rest-framework } -El framework Django REST fue creado para ser un kit de herramientas flexible para construir APIs Web utilizando Django, mejorando sus capacidades API. +Django REST Framework fue creado para ser un toolkit flexible para construir APIs Web usando Django por debajo, para mejorar sus capacidades de API. Es utilizado por muchas empresas, incluidas Mozilla, Red Hat y Eventbrite. @@ -88,7 +88,7 @@ La forma en que lo usas es muy sencilla. Por ejemplo, para hacer un `GET` reques response = requests.get("http://example.com/some/url") ``` -La operación de path equivalente en FastAPI podría verse como: +La *path operation* API equivalente de FastAPI podría verse como: ```Python hl_lines="1" @app.get("/some/url") @@ -183,7 +183,7 @@ Pero la documentación todavía falta. Entonces APISpec fue creado. Es un plug-in para muchos frameworks (y hay un plug-in para Starlette también). -La manera en que funciona es que escribes la definición del esquema usando el formato YAML dentro del docstring de cada función que maneja un path. +La manera en que funciona es que escribes la definición del esquema usando el formato YAML dentro del docstring de cada función que maneja una ruta. Y genera esquemas OpenAPI. @@ -245,11 +245,11 @@ Logra algo algo similar a lo que se puede hacer con Flask-apispec. Tiene un sistema de inyección de dependencias integrado, inspirado por Angular 2. Requiere pre-registrar los "inyectables" (como todos los otros sistemas de inyección de dependencias que conozco), por lo que añade a la verbosidad y repetición de código. -Como los parámetros se describen con tipos de TypeScript (similar a las anotaciones de tipos en Python), el soporte editorial es bastante bueno. +Como los parámetros se describen con tipos de TypeScript (similar a las anotaciones de tipos en Python), el soporte del editor es bastante bueno. Pero como los datos de TypeScript no se preservan después de la compilación a JavaScript, no puede depender de los tipos para definir validación, serialización y documentación al mismo tiempo. Debido a esto y algunas decisiones de diseño, para obtener validación, serialización y generación automática del esquema, es necesario agregar decoradores en muchos lugares. Por lo tanto, se vuelve bastante verboso. -No puede manejar muy bien modelos anidados. Entonces, si el cuerpo JSON en la request es un objeto JSON que tiene campos internos que a su vez son objetos JSON anidados, no puede ser documentado y validado apropiadamente. +No puede manejar muy bien modelos anidados. Entonces, si el body JSON en la request es un objeto JSON que tiene campos internos que a su vez son objetos JSON anidados, no puede ser documentado y validado apropiadamente. /// tip | Inspiró a **FastAPI** a @@ -311,11 +311,11 @@ Requiere configuraciones un poquito más verbosas. Y dado que se basa en WSGI (e El sistema de inyección de dependencias requiere pre-registrar las dependencias y las dependencias se resuelven en base a los tipos declarados. Por lo tanto, no es posible declarar más de un "componente" que proporcione cierto tipo. -Los paths se declaran en un solo lugar, usando funciones declaradas en otros lugares (en lugar de usar decoradores que pueden colocarse justo encima de la función que maneja el endpoint). Esto se acerca más a cómo lo hace Django que a cómo lo hace Flask (y Starlette). Separa en el código cosas que están relativamente acopladas. +Las rutas se declaran en un solo lugar, usando funciones declaradas en otros lugares (en lugar de usar decoradores que pueden colocarse justo encima de la función que maneja el endpoint). Esto se acerca más a cómo lo hace Django que a cómo lo hace Flask (y Starlette). Separa en el código cosas que están relativamente acopladas. /// tip | Inspiró a **FastAPI** a -Definir validaciones extra para tipos de datos usando el valor "default" de los atributos del modelo. Esto mejora el soporte del editor y no estaba disponible en Pydantic antes. +Definir validaciones extra para tipos de datos usando el valor "por defecto" de los atributos del modelo. Esto mejora el soporte del editor y no estaba disponible en Pydantic antes. Esto en realidad inspiró la actualización de partes de Pydantic, para soportar el mismo estilo de declaración de validación (toda esta funcionalidad ya está disponible en Pydantic). @@ -433,7 +433,7 @@ Tiene: * CORS, GZip, Archivos estáticos, Responses en streaming. * Soporte para sesiones y cookies. * Cobertura de tests del 100%. -* code base 100% tipada. +* codebase 100% con anotaciones de tipos. * Pocas dependencias obligatorias. Starlette es actualmente el framework de Python más rápido probado. Solo superado por Uvicorn, que no es un framework, sino un servidor. diff --git a/docs/es/docs/async.md b/docs/es/docs/async.md index 299bd83e3..be64f4cbe 100644 --- a/docs/es/docs/async.md +++ b/docs/es/docs/async.md @@ -89,7 +89,7 @@ Como el tiempo de ejecución se consume principalmente esperando operaciones de Se llama "asíncrono" porque la computadora / programa no tiene que estar "sincronizado" con la tarea lenta, esperando el momento exacto en que la tarea termine, sin hacer nada, para poder tomar el resultado de la tarea y continuar el trabajo. -En lugar de eso, al ser un sistema "asíncrono", una vez terminado, la tarea puede esperar un poco en la cola (algunos microsegundos) para que la computadora / programa termine lo que salió a hacer, y luego regrese para tomar los resultados y continuar trabajando con ellos. +En lugar de eso, al ser un sistema "asíncrono", una vez terminado, la tarea puede esperar un poquito en la cola (algunos microsegundos) para que la computadora / programa termine lo que salió a hacer, y luego regrese para tomar los resultados y continuar trabajando con ellos. Para el "sincrónico" (contrario al "asíncrono") comúnmente también usan el término "secuencial", porque la computadora / programa sigue todos los pasos en secuencia antes de cambiar a una tarea diferente, incluso si esos pasos implican esperar. @@ -151,7 +151,7 @@ Imagina que eres la computadora / programa 🤖 en esa historia. Mientras estás en la fila, estás inactivo 😴, esperando tu turno, sin hacer nada muy "productivo". Pero la fila es rápida porque el cajero solo está tomando los pedidos (no preparándolos), así que está bien. -Luego, cuando es tu turno, haces un trabajo realmente "productivo", procesas el menú, decides lo que quieres, obtienes la elección de tu crush, pagas, verificas que das el billete o tarjeta correctos, verificas que te cobren correctamente, verificas que el pedido tenga los artículos correctos, etc. +Luego, cuando es tu turno, haces un trabajo realmente "productivo", procesas el menú, decides lo que quieres, obtienes la elección de tu crush, pagas, revisas que das el billete o tarjeta correctos, revisas que te cobren correctamente, revisas que el pedido tenga los artículos correctos, etc. Pero luego, aunque todavía no tienes tus hamburguesas, tu trabajo con el cajero está "en pausa" ⏸, porque tienes que esperar 🕙 a que tus hamburguesas estén listas. @@ -387,7 +387,7 @@ En versiones previas de NodeJS / JavaScript en el Navegador, habrías usado "cal ## Coroutines { #coroutines } -**Coroutines** es simplemente el término muy elegante para la cosa que devuelve una función `async def`. Python sabe que es algo parecido a una función, que puede comenzar y que terminará en algún momento, pero que podría pausar ⏸ internamente también, siempre que haya un `await` dentro de él. +**Coroutine** es simplemente el término muy elegante para la cosa que devuelve una función `async def`. Python sabe que es algo parecido a una función, que puede comenzar y que terminará en algún momento, pero que podría pausar ⏸ internamente también, siempre que haya un `await` dentro de él. Pero toda esta funcionalidad de usar código asíncrono con `async` y `await` a menudo se resume como utilizar "coroutines". Es comparable a la funcionalidad clave principal de Go, las "Goroutines". @@ -417,7 +417,7 @@ Si tienes bastante conocimiento técnico (coroutines, hilos, bloqueo, etc.) y ti Cuando declaras una *path operation function* con `def` normal en lugar de `async def`, se ejecuta en un threadpool externo que luego es esperado, en lugar de ser llamado directamente (ya que bloquearía el servidor). -Si vienes de otro framework async que no funciona de la manera descrita anteriormente y estás acostumbrado a definir funciones de *path operation* solo de cómputo trivial con `def` normal para una pequeña ganancia de rendimiento (alrededor de 100 nanosegundos), ten en cuenta que en **FastAPI** el efecto sería bastante opuesto. En estos casos, es mejor usar `async def` a menos que tus *path operation functions* usen código que realice I/O de bloqueo. +Si vienes de otro framework async que no funciona de la manera descrita anteriormente y estás acostumbrado a definir *path operation functions* solo de cómputo trivial con `def` normal para una pequeña ganancia de rendimiento (alrededor de 100 nanosegundos), ten en cuenta que en **FastAPI** el efecto sería bastante opuesto. En estos casos, es mejor usar `async def` a menos que tus *path operation functions* usen código que realice I/O de bloqueo. Aun así, en ambas situaciones, es probable que **FastAPI** [siga siendo más rápida](index.md#performance) que (o al menos comparable a) tu framework anterior. diff --git a/docs/es/docs/deployment/cloud.md b/docs/es/docs/deployment/cloud.md index 266d3cfd2..64711455d 100644 --- a/docs/es/docs/deployment/cloud.md +++ b/docs/es/docs/deployment/cloud.md @@ -16,7 +16,7 @@ FastAPI Cloud es el sponsor principal y proveedor de financiamiento de los proye ## Proveedores de Nube - Sponsors { #cloud-providers-sponsors } -Otros proveedores de nube ✨ [**son sponsors de FastAPI**](../help-fastapi.md#sponsor-the-author) ✨ también. 🙇 +Algunos otros proveedores de nube ✨ [**son sponsors de FastAPI**](https://github.com/sponsors/tiangolo) ✨ también. 🙇 También podrías considerarlos para seguir sus guías y probar sus servicios: diff --git a/docs/es/docs/deployment/concepts.md b/docs/es/docs/deployment/concepts.md index 9b3ac0a34..6a2d20a35 100644 --- a/docs/es/docs/deployment/concepts.md +++ b/docs/es/docs/deployment/concepts.md @@ -1,5 +1,6 @@ # Conceptos de Implementación { #deployments-concepts } + Cuando implementas una aplicación **FastAPI**, o en realidad, cualquier tipo de API web, hay varios conceptos que probablemente te importen, y al entenderlos, puedes encontrar la **forma más adecuada** de **implementar tu aplicación**. Algunos de los conceptos importantes son: diff --git a/docs/es/docs/deployment/docker.md b/docs/es/docs/deployment/docker.md index 6ce0e192a..e54f0c205 100644 --- a/docs/es/docs/deployment/docker.md +++ b/docs/es/docs/deployment/docker.md @@ -1,5 +1,6 @@ # FastAPI en Contenedores - Docker { #fastapi-in-containers-docker } + Al desplegar aplicaciones de FastAPI, un enfoque común es construir una **imagen de contenedor de Linux**. Normalmente se realiza usando [**Docker**](https://www.docker.com/). Luego puedes desplegar esa imagen de contenedor de varias formas. Usar contenedores de Linux tiene varias ventajas, incluyendo **seguridad**, **replicabilidad**, **simplicidad**, y otras. @@ -132,7 +133,7 @@ Successfully installed fastapi pydantic -/// info | Información +/// note | Nota Existen otros formatos y herramientas para definir e instalar dependencias de paquetes. @@ -556,7 +557,7 @@ Si estás usando contenedores (por ejemplo, Docker, Kubernetes), entonces hay do Si tienes **múltiples contenedores**, probablemente cada uno ejecutando un **proceso único** (por ejemplo, en un cluster de **Kubernetes**), entonces probablemente querrías tener un **contenedor separado** realizando el trabajo de los **pasos previos** en un solo contenedor, ejecutando un solo proceso, **antes** de ejecutar los contenedores worker replicados. -/// info | Información +/// note | Nota Si estás usando Kubernetes, probablemente sería un [Contenedor de Inicialización](https://kubernetes.io/docs/concepts/workloads/pods/init-containers/). diff --git a/docs/es/docs/deployment/fastapicloud.md b/docs/es/docs/deployment/fastapicloud.md index fc770d1ee..9c289f4b1 100644 --- a/docs/es/docs/deployment/fastapicloud.md +++ b/docs/es/docs/deployment/fastapicloud.md @@ -1,26 +1,6 @@ # FastAPI Cloud { #fastapi-cloud } -Puedes desplegar tu app de FastAPI en [FastAPI Cloud](https://fastapicloud.com) con **un solo comando**; ve y únete a la lista de espera si aún no lo has hecho. 🚀 - -## Iniciar sesión { #login } - -Asegúrate de que ya tienes una cuenta de **FastAPI Cloud** (te invitamos desde la lista de espera 😉). - -Luego inicia sesión: - -
- -```console -$ fastapi login - -You are logged in to FastAPI Cloud 🚀 -``` - -
- -## Desplegar { #deploy } - -Ahora despliega tu app, con **un solo comando**: +Puedes desplegar tu app de FastAPI en [FastAPI Cloud](https://fastapicloud.com) con **un solo comando**. 🚀
@@ -36,6 +16,8 @@ Deploying to FastAPI Cloud...
+La CLI detectará automáticamente tu aplicación de FastAPI y la desplegará en la nube. Si no has iniciado sesión, se abrirá tu navegador para completar el proceso de autenticación. + ¡Eso es todo! Ahora puedes acceder a tu app en esa URL. ✨ ## Acerca de FastAPI Cloud { #about-fastapi-cloud } diff --git a/docs/es/docs/deployment/https.md b/docs/es/docs/deployment/https.md index 227aab0d6..32f0fc28c 100644 --- a/docs/es/docs/deployment/https.md +++ b/docs/es/docs/deployment/https.md @@ -32,7 +32,7 @@ Ahora, desde una **perspectiva de desarrollador**, aquí hay varias cosas a tene * Esta extensión SNI permite que un solo servidor (con una **sola dirección IP**) tenga **varios certificados HTTPS** y sirva **múltiples dominios/aplicaciones HTTPS**. * Para que esto funcione, un componente (programa) **único** que se ejecute en el servidor, escuchando en la **dirección IP pública**, debe tener **todos los certificados HTTPS** en el servidor. * **Después** de obtener una conexión segura, el protocolo de comunicación sigue siendo **HTTP**. - * Los contenidos están **encriptados**, aunque se envién con el **protocolo HTTP**. + * Los contenidos están **encriptados**, aunque se envíen con el **protocolo HTTP**. Es una práctica común tener **un programa/servidor HTTP** ejecutándose en el servidor (la máquina, host, etc.) y **gestionando todas las partes de HTTPS**: recibiendo los **requests HTTPS encriptados**, enviando los **requests HTTP desencriptados** a la aplicación HTTP real que se ejecuta en el mismo servidor (la aplicación **FastAPI**, en este caso), tomando el **response HTTP** de la aplicación, **encriptándolo** usando el **certificado HTTPS** adecuado y enviándolo de vuelta al cliente usando **HTTPS**. Este servidor a menudo se llama un **[TLS Termination Proxy](https://en.wikipedia.org/wiki/TLS_termination_proxy)**. diff --git a/docs/es/docs/deployment/manually.md b/docs/es/docs/deployment/manually.md index f3c771a51..90e25ecb4 100644 --- a/docs/es/docs/deployment/manually.md +++ b/docs/es/docs/deployment/manually.md @@ -56,7 +56,6 @@ Hay varias alternativas, incluyendo: * [Hypercorn](https://hypercorn.readthedocs.io/): un servidor ASGI compatible con HTTP/2 y Trio entre otras funcionalidades. * [Daphne](https://github.com/django/daphne): el servidor ASGI construido para Django Channels. * [Granian](https://github.com/emmett-framework/granian): Un servidor HTTP Rust para aplicaciones en Python. -* [NGINX Unit](https://unit.nginx.org/howto/fastapi/): NGINX Unit es un runtime para aplicaciones web ligero y versátil. ## Máquina Servidor y Programa Servidor { #server-machine-and-server-program } @@ -94,7 +93,7 @@ Un proceso similar se aplicaría a cualquier otro programa de servidor ASGI. Al añadir `standard`, Uvicorn instalará y usará algunas dependencias adicionales recomendadas. -Eso incluye `uvloop`, el reemplazo de alto rendimiento para `asyncio`, que proporciona un gran impulso de rendimiento en concurrencia. +Eso incluye `uvloop`, el reemplazo directo de alto rendimiento para `asyncio`, que proporciona un gran impulso de rendimiento en concurrencia. Cuando instalas FastAPI con algo como `pip install "fastapi[standard]"` ya obtienes `uvicorn[standard]` también. diff --git a/docs/es/docs/deployment/server-workers.md b/docs/es/docs/deployment/server-workers.md index 3e3a1898b..a7665ccb6 100644 --- a/docs/es/docs/deployment/server-workers.md +++ b/docs/es/docs/deployment/server-workers.md @@ -17,7 +17,7 @@ Como viste en el capítulo anterior sobre [Conceptos de Despliegue](concepts.md) Aquí te mostraré cómo usar **Uvicorn** con **worker processes** usando el comando `fastapi` o el comando `uvicorn` directamente. -/// info | Información +/// note | Nota Si estás usando contenedores, por ejemplo con Docker o Kubernetes, te contaré más sobre eso en el próximo capítulo: [FastAPI en Contenedores - Docker](docker.md). diff --git a/docs/es/docs/editor-support.md b/docs/es/docs/editor-support.md index fa552db23..9c9abdd5e 100644 --- a/docs/es/docs/editor-support.md +++ b/docs/es/docs/editor-support.md @@ -10,7 +10,7 @@ La **Extensión de FastAPI** está disponible tanto para [VS Code](https://code. ### Descubrimiento de la aplicación { #application-discovery } -Por defecto, la extensión descubrirá automáticamente aplicaciones FastAPI en tu espacio de trabajo escaneando archivos que creen un instance de `FastAPI()`. Si la detección automática no funciona con la estructura de tu proyecto, puedes especificar un punto de entrada mediante `[tool.fastapi]` en `pyproject.toml` o la configuración de VS Code `fastapi.entryPoint` usando notación de módulo (p. ej. `myapp.main:app`). +Por defecto, la extensión descubrirá automáticamente aplicaciones FastAPI en tu espacio de trabajo escaneando archivos que crean un instance de `FastAPI()`. Si la detección automática no funciona con la estructura de tu proyecto, puedes especificar un punto de entrada mediante `[tool.fastapi]` en `pyproject.toml` o la configuración de VS Code `fastapi.entryPoint` usando notación de módulo (p. ej. `myapp.main:app`). ## Funcionalidades { #features } diff --git a/docs/es/docs/environment-variables.md b/docs/es/docs/environment-variables.md index 5c58771d9..aab76ebe6 100644 --- a/docs/es/docs/environment-variables.md +++ b/docs/es/docs/environment-variables.md @@ -1,5 +1,6 @@ # Variables de Entorno { #environment-variables } + /// tip | Consejo Si ya sabes qué son las "variables de entorno" y cómo usarlas, siéntete libre de saltarte esto. diff --git a/docs/es/docs/features.md b/docs/es/docs/features.md index 799af26e9..1feed92bd 100644 --- a/docs/es/docs/features.md +++ b/docs/es/docs/features.md @@ -130,7 +130,7 @@ Todos los esquemas de seguridad definidos en OpenAPI, incluyendo: * Parámetros de query. * Cookies, etc. -Además de todas las características de seguridad de Starlette (incluyendo **cookies de sesión**). +Además de todas las funcionalidades de seguridad de Starlette (incluyendo **cookies de sesión**). Todo construido como herramientas y componentes reutilizables que son fáciles de integrar con tus sistemas, almacenes de datos, bases de datos relacionales y NoSQL, etc. @@ -179,7 +179,7 @@ Con **FastAPI** obtienes todas las funcionalidades de **Starlette** (ya que Fast **FastAPI** es totalmente compatible con (y está basado en) [**Pydantic**](https://docs.pydantic.dev/). Por lo tanto, cualquier código adicional de Pydantic que tengas, también funcionará. -Incluyendo paquetes externos también basados en Pydantic, como ORMs, ODMs para bases de datos. +Incluyendo paquetes externos también basados en Pydantic, como ORMs y ODMs para bases de datos. Esto también significa que, en muchos casos, puedes pasar el mismo objeto que obtienes de un request **directamente a la base de datos**, ya que todo se valida automáticamente. diff --git a/docs/es/docs/help-fastapi.md b/docs/es/docs/help-fastapi.md index 71e872d50..e1a8d1a52 100644 --- a/docs/es/docs/help-fastapi.md +++ b/docs/es/docs/help-fastapi.md @@ -68,7 +68,7 @@ Puedes [crear una nueva pregunta](https://github.com/fastapi/fastapi/discussions ## Únete al chat { #join-the-chat } -Únete al servidor de chat 👥 [Discord](https://discord.gg/VQjSZaeJmf) 👥 y charla con otros en la comunidad de FastAPI. +Únete al 👥 [servidor de chat de Discord](https://discord.gg/VQjSZaeJmf) 👥 y charla con otros en la comunidad de FastAPI. /// tip | Consejo diff --git a/docs/es/docs/how-to/configure-swagger-ui.md b/docs/es/docs/how-to/configure-swagger-ui.md index 8230f4a14..7ff728eef 100644 --- a/docs/es/docs/how-to/configure-swagger-ui.md +++ b/docs/es/docs/how-to/configure-swagger-ui.md @@ -1,4 +1,4 @@ -# Configurar Swagger UI { #configure-swagger-ui } +# Configura Swagger UI { #configure-swagger-ui } Puedes configurar algunos [parámetros adicionales de Swagger UI](https://swagger.io/docs/open-source-tools/swagger-ui/usage/configuration/). @@ -8,7 +8,7 @@ Para configurarlos, pasa el argumento `swagger_ui_parameters` al crear el objeto FastAPI convierte las configuraciones a **JSON** para hacerlas compatibles con JavaScript, ya que eso es lo que Swagger UI necesita. -## Desactivar el resaltado de sintaxis { #disable-syntax-highlighting } +## Desactiva el resaltado de sintaxis { #disable-syntax-highlighting } Por ejemplo, podrías desactivar el resaltado de sintaxis en Swagger UI. @@ -24,7 +24,7 @@ Pero puedes desactivarlo estableciendo `syntaxHighlight` en `False`: -## Cambiar el tema { #change-the-theme } +## Cambia el tema { #change-the-theme } De la misma manera, podrías configurar el tema del resaltado de sintaxis con la clave `"syntaxHighlight.theme"` (ten en cuenta que tiene un punto en el medio): @@ -34,7 +34,7 @@ Esa configuración cambiaría el tema de color del resaltado de sintaxis: -## Cambiar los parámetros por defecto de Swagger UI { #change-default-swagger-ui-parameters } +## Cambia los parámetros por defecto de Swagger UI { #change-default-swagger-ui-parameters } FastAPI incluye algunos parámetros de configuración por defecto apropiados para la mayoría de los casos de uso. diff --git a/docs/es/docs/how-to/custom-request-and-route.md b/docs/es/docs/how-to/custom-request-and-route.md index 56013a5c7..5b4d8570f 100644 --- a/docs/es/docs/how-to/custom-request-and-route.md +++ b/docs/es/docs/how-to/custom-request-and-route.md @@ -18,8 +18,8 @@ Si apenas estás comenzando con **FastAPI**, quizás quieras saltar esta secció Algunos casos de uso incluyen: -* Convertir cuerpos de requests no-JSON a JSON (por ejemplo, [`msgpack`](https://msgpack.org/index.html)). -* Descomprimir cuerpos de requests comprimidos con gzip. +* Convertir request bodies no-JSON a JSON (por ejemplo, [`msgpack`](https://msgpack.org/index.html)). +* Descomprimir request bodies comprimidos con gzip. * Registrar automáticamente todos los request bodies. ## Manejo de codificaciones personalizadas de request body { #handling-custom-request-body-encodings } @@ -32,7 +32,7 @@ Y una subclase de `APIRoute` para usar esa clase de request personalizada. /// tip | Consejo -Este es un ejemplo sencillo para demostrar cómo funciona. Si necesitas soporte para Gzip, puedes usar el [`GzipMiddleware`](../advanced/middleware.md#gzipmiddleware) proporcionado. +Este es un ejemplo de juguete para demostrar cómo funciona, si necesitas soporte para Gzip, puedes usar el [`GzipMiddleware`](../advanced/middleware.md#gzipmiddleware) proporcionado. /// @@ -60,11 +60,11 @@ Aquí lo usamos para crear un `GzipRequest` a partir del request original. Un `Request` tiene un atributo `request.scope`, que es simplemente un `dict` de Python que contiene los metadatos relacionados con el request. -Un `Request` también tiene un `request.receive`, que es una función para "recibir" el request body. +Un `Request` también tiene un `request.receive`, que es una función para "recibir" el body del request. El `dict` `scope` y la función `receive` son ambos parte de la especificación ASGI. -Y esas dos cosas, `scope` y `receive`, son lo que se necesita para crear una nueva *Request instance*. +Y esas dos cosas, `scope` y `receive`, son lo que se necesita para crear una nueva instance de `Request`. Para aprender más sobre el `Request`, revisa [la documentación de Starlette sobre Requests](https://www.starlette.dev/requests/). @@ -94,7 +94,7 @@ Todo lo que necesitamos hacer es manejar el request dentro de un bloque `try`/`e {* ../../docs_src/custom_request_and_route/tutorial002_an_py310.py hl[14,16] *} -Si ocurre una excepción, la `Request instance` aún estará en el alcance, así que podemos leer y hacer uso del request body cuando manejamos el error: +Si ocurre una excepción, el instance de `Request` todavía estará en el alcance, así que podemos leer y hacer uso del request body cuando manejamos el error: {* ../../docs_src/custom_request_and_route/tutorial002_an_py310.py hl[17:19] *} diff --git a/docs/es/docs/how-to/extending-openapi.md b/docs/es/docs/how-to/extending-openapi.md index d00455afd..b0fa23024 100644 --- a/docs/es/docs/how-to/extending-openapi.md +++ b/docs/es/docs/how-to/extending-openapi.md @@ -25,9 +25,17 @@ Y esa función `get_openapi()` recibe como parámetros: * `openapi_version`: La versión de la especificación OpenAPI utilizada. Por defecto, la más reciente: `3.1.0`. * `summary`: Un breve resumen de la API. * `description`: La descripción de tu API, esta puede incluir markdown y se mostrará en la documentación. -* `routes`: Una list de rutas, estas son cada una de las *path operations* registradas. Se toman de `app.routes`. +* `routes`: Las rutas de la aplicación, tomadas de `app.routes`. FastAPI las usa para recolectar las *path operations* registradas, incluidas las de los routers incluidos. -/// info | Información +/// tip | Detalles técnicos + +`app.routes` es un árbol de rutas de nivel inferior. Puede incluir rutas candidatas que FastAPI usa internamente para routers incluidos, no solo objetos `APIRoute` finales. + +Aun así puedes pasar `app.routes` a `get_openapi()`. FastAPI recorrerá ese árbol de rutas para recolectar las path operations efectivas. + +/// + +/// note | Nota El parámetro `summary` está disponible en OpenAPI 3.1.0 y versiones superiores, soportado por FastAPI 0.99.0 y superiores. diff --git a/docs/es/docs/how-to/graphql.md b/docs/es/docs/how-to/graphql.md index 11c0cc23c..a58a11764 100644 --- a/docs/es/docs/how-to/graphql.md +++ b/docs/es/docs/how-to/graphql.md @@ -29,7 +29,7 @@ Aquí algunos de los paquetes de **GraphQL** que tienen soporte **ASGI**. Podrí ## GraphQL con Strawberry { #graphql-with-strawberry } -Si necesitas o quieres trabajar con **GraphQL**, [**Strawberry**](https://strawberry.rocks/) es el paquete **recomendado** ya que tiene un diseño muy similar al diseño de **FastAPI**, todo basado en **anotaciones de tipos**. +Si necesitas o quieres trabajar con **GraphQL**, [**Strawberry**](https://strawberry.rocks/) es el paquete **recomendado** ya que tiene el diseño más cercano al diseño de **FastAPI**, todo basado en **anotaciones de tipos**. Dependiendo de tu caso de uso, podrías preferir usar un paquete diferente, pero si me preguntas, probablemente te sugeriría probar **Strawberry**. diff --git a/docs/es/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md b/docs/es/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md index 22d51674d..571554cad 100644 --- a/docs/es/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md +++ b/docs/es/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md @@ -8,6 +8,8 @@ FastAPI versión 0.119.0 introdujo compatibilidad parcial con Pydantic v1 desde FastAPI 0.126.0 eliminó la compatibilidad con Pydantic v1, aunque siguió soportando `pydantic.v1` por un poquito más de tiempo. +FastAPI 0.128.0 también eliminó la compatibilidad con `pydantic.v1`, así que las versiones más recientes de FastAPI requieren Pydantic v2. + /// warning | Advertencia El equipo de Pydantic dejó de dar soporte a Pydantic v1 para las versiones más recientes de Python, comenzando con **Python 3.14**. @@ -54,6 +56,16 @@ Esto significa que puedes instalar la versión más reciente de Pydantic v2 e im ### Compatibilidad de FastAPI con Pydantic v1 en v2 { #fastapi-support-for-pydantic-v1-in-v2 } +/// warning | Advertencia + +Esta compatibilidad de FastAPI con modelos de `pydantic.v1` se añadió en **FastAPI 0.119.0** y se eliminó en **FastAPI 0.128.0**. Estaba pensada para ser una ayuda temporal para la migración a Pydantic v2. + +En las versiones actuales de FastAPI, usar un modelo de `pydantic.v1` en tu app generará un error. + +El resto de esta sección describe la compatibilidad temporal disponible solo en esas versiones antiguas. + +/// + Desde FastAPI 0.119.0, también hay compatibilidad parcial para Pydantic v1 desde dentro de Pydantic v2, para facilitar la migración a v2. Así que podrías actualizar Pydantic a la última versión 2 y cambiar los imports para usar el submódulo `pydantic.v1`, y en muchos casos simplemente funcionaría. @@ -122,6 +134,12 @@ Si necesitas usar algunas de las herramientas específicas de FastAPI para pará ### Migra por pasos { #migrate-in-steps } +/// warning | Advertencia + +La migración gradual usando tanto modelos de Pydantic v1 como de v2 en la misma app descrita abajo solo funciona en **FastAPI 0.119.0 a 0.127.x**. Se eliminó en **FastAPI 0.128.0**, las versiones más recientes requieren modelos de **Pydantic v2**. + +/// + /// tip | Consejo Primero prueba con `bump-pydantic`, si tus tests pasan y eso funciona, entonces terminaste con un solo comando. ✨ diff --git a/docs/es/docs/how-to/separate-openapi-schemas.md b/docs/es/docs/how-to/separate-openapi-schemas.md index db9b46ddb..14990a79a 100644 --- a/docs/es/docs/how-to/separate-openapi-schemas.md +++ b/docs/es/docs/how-to/separate-openapi-schemas.md @@ -77,7 +77,7 @@ Pero para `Item-Output`, `description` **es requerido**, tiene un asterisco rojo Con esta funcionalidad de **Pydantic v2**, la documentación de tu API es más **precisa**, y si tienes clientes y SDKs autogenerados, también serán más precisos, con una mejor **experiencia para desarrolladores** y consistencia. 🎉 -## No Separar Esquemas { #do-not-separate-schemas } +## No separes esquemas { #do-not-separate-schemas } Ahora, hay algunos casos donde podrías querer tener el **mismo esquema para entrada y salida**. @@ -85,7 +85,7 @@ Probablemente el caso principal para esto es si ya tienes algún código cliente En ese caso, puedes desactivar esta funcionalidad en **FastAPI**, con el parámetro `separate_input_output_schemas=False`. -/// info | Información +/// note | Nota El soporte para `separate_input_output_schemas` fue agregado en FastAPI `0.102.0`. 🤓 diff --git a/docs/es/docs/index.md b/docs/es/docs/index.md index 1217c4c6f..7a9caec51 100644 --- a/docs/es/docs/index.md +++ b/docs/es/docs/index.md @@ -45,7 +45,7 @@ Las funcionalidades clave son: * **Rápido**: Muy alto rendimiento, a la par con **NodeJS** y **Go** (gracias a Starlette y Pydantic). [Uno de los frameworks Python más rápidos disponibles](#performance). * **Rápido de programar**: Aumenta la velocidad para desarrollar funcionalidades en aproximadamente un 200% a 300%. * * **Menos bugs**: Reduce en aproximadamente un 40% los errores inducidos por humanos (desarrolladores). * -* **Intuitivo**: Gran soporte para editores. Autocompletado en todas partes. Menos tiempo depurando. +* **Intuitivo**: Gran soporte para editores. Autocompletado en todas partes. Menos tiempo depurando. * **Fácil**: Diseñado para ser fácil de usar y aprender. Menos tiempo leyendo documentación. * **Corto**: Minimiza la duplicación de código. Múltiples funcionalidades desde cada declaración de parámetro. Menos bugs. * **Robusto**: Obtén código listo para producción. Con documentación interactiva automática. @@ -479,7 +479,7 @@ Para un ejemplo más completo incluyendo más funcionalidades, ve al Inyección de Dependencias** muy poderoso y fácil de usar. +* Un sistema de **Inyección de Dependencias** muy poderoso y fácil de usar. * Seguridad y autenticación, incluyendo soporte para **OAuth2** con **tokens JWT** y autenticación **HTTP Basic**. * Técnicas más avanzadas (pero igualmente fáciles) para declarar **modelos JSON profundamente anidados** (gracias a Pydantic). * Integración con **GraphQL** usando [Strawberry](https://strawberry.rocks) y otros paquetes. @@ -492,9 +492,7 @@ Para un ejemplo más completo incluyendo más funcionalidades, ve al @@ -510,6 +508,8 @@ Deploying to FastAPI Cloud... +La CLI detectará automáticamente tu aplicación de FastAPI y la desplegará en la nube. Si no has iniciado sesión, se abrirá tu navegador para completar el proceso de autenticación. + ¡Eso es todo! Ahora puedes acceder a tu app en esa URL. ✨ #### Acerca de FastAPI Cloud { #about-fastapi-cloud } diff --git a/docs/es/docs/project-generation.md b/docs/es/docs/project-generation.md index 11a560eba..fd0fd7017 100644 --- a/docs/es/docs/project-generation.md +++ b/docs/es/docs/project-generation.md @@ -9,18 +9,18 @@ Repositorio de GitHub: [Plantilla Full Stack FastAPI](https://github.com/tiangol ## Plantilla Full Stack FastAPI - Stack de tecnología y funcionalidades { #full-stack-fastapi-template-technology-stack-and-features } - ⚡ [**FastAPI**](https://fastapi.tiangolo.com/es) para la API del backend en Python. - - 🧰 [SQLModel](https://sqlmodel.tiangolo.com) para las interacciones con bases de datos SQL en Python (ORM). - - 🔍 [Pydantic](https://docs.pydantic.dev), utilizado por FastAPI, para la validación de datos y gestión de configuraciones. - - 💾 [PostgreSQL](https://www.postgresql.org) como base de datos SQL. + - 🧰 [SQLModel](https://sqlmodel.tiangolo.com) para las interacciones con bases de datos SQL en Python (ORM). + - 🔍 [Pydantic](https://docs.pydantic.dev), utilizado por FastAPI, para la validación de datos y gestión de configuraciones. + - 💾 [PostgreSQL](https://www.postgresql.org) como base de datos SQL. - 🚀 [React](https://react.dev) para el frontend. - - 💃 Usando TypeScript, hooks, Vite, y otras partes de una stack moderna de frontend. - - 🎨 [Tailwind CSS](https://tailwindcss.com) y [shadcn/ui](https://ui.shadcn.com) para los componentes del frontend. - - 🤖 Un cliente de frontend generado automáticamente. - - 🧪 [Playwright](https://playwright.dev) para escribir pruebas End-to-End. - - 🦇 Soporte para modo oscuro. + - 💃 Usando TypeScript, hooks, Vite, y otras partes de una stack moderna de frontend. + - 🎨 [Tailwind CSS](https://tailwindcss.com) y [shadcn/ui](https://ui.shadcn.com) para los componentes del frontend. + - 🤖 Un cliente de frontend generado automáticamente. + - 🧪 [Playwright](https://playwright.dev) para escribir pruebas End-to-End. + - 🦇 Soporte para modo oscuro. - 🐋 [Docker Compose](https://www.docker.com) para desarrollo y producción. - 🔒 Hashing seguro de contraseñas por defecto. -- 🔑 Autenticación con tokens JWT. +- 🔑 Autenticación con JWT (JSON Web Token). - 📫 Recuperación de contraseñas basada en email. - ✅ Pruebas con [Pytest](https://pytest.org). - 📞 [Traefik](https://traefik.io) como proxy inverso / load balancer. diff --git a/docs/es/docs/python-types.md b/docs/es/docs/python-types.md index 878c8be03..6a13b97eb 100644 --- a/docs/es/docs/python-types.md +++ b/docs/es/docs/python-types.md @@ -1,8 +1,8 @@ # Introducción a Tipos en Python { #python-types-intro } -Python tiene soporte para "anotaciones de tipos" opcionales (también llamadas "type hints"). +Python tiene soporte para "anotaciones de tipos" opcionales (también llamadas "anotaciones de tipos"). -Estas **"anotaciones de tipos"** o type hints son una sintaxis especial que permite declarar el tipo de una variable. +Estas **"anotaciones de tipos"** o anotaciones son una sintaxis especial que permite declarar el tipo de una variable. Al declarar tipos para tus variables, los editores y herramientas te pueden proporcionar un mejor soporte. @@ -44,7 +44,7 @@ Es un programa muy simple. Pero ahora imagina que lo escribieras desde cero. -En algún momento habrías empezado la definición de la función, tenías los parámetros listos... +En algún momento empiezas a definir la función, y tienes los parámetros listos... Pero luego tienes que llamar "ese método que convierte la primera letra a mayúscula". @@ -58,7 +58,7 @@ Pero, tristemente, no obtienes nada útil: -### Añadir tipos { #add-types } +### Añade tipos { #add-types } Modifiquemos una sola línea de la versión anterior. @@ -120,7 +120,7 @@ Ahora sabes que debes corregirlo, convertir `age` a un string con `str(age)`: Acabas de ver el lugar principal para declarar anotaciones de tipos. Como parámetros de función. -Este también es el lugar principal donde los utilizarías con **FastAPI**. +Este también es el lugar principal donde las utilizarías con **FastAPI**. ### Tipos simples { #simple-types } @@ -137,7 +137,7 @@ Puedes usar, por ejemplo: ### Módulo `typing` { #typing-module } -Para algunos casos adicionales, podrías necesitar importar algunas cosas del módulo `typing` de la standard library, por ejemplo cuando quieres declarar que algo tiene "cualquier tipo", puedes usar `Any` de `typing`: +Para algunos casos adicionales, podrías necesitar importar algunas cosas del módulo `typing` del paquete estándar, por ejemplo cuando quieres declarar que algo tiene "cualquier tipo", puedes usar `Any` de `typing`: ```python from typing import Any @@ -149,7 +149,7 @@ def some_function(data: Any): ### Tipos genéricos { #generic-types } -Algunos tipos pueden tomar "parámetros de tipo" entre corchetes, para definir sus tipos internos, por ejemplo una "lista de strings" se declararía `list[str]`. +Algunos tipos pueden tomar "parámetros de tipo" entre corchetes, para definir sus tipos internos, por ejemplo una "list de strings" se declararía `list[str]`. Estos tipos que pueden tomar parámetros de tipo se llaman **Tipos Genéricos** o **Genéricos**. @@ -160,7 +160,7 @@ Puedes usar los mismos tipos integrados como genéricos (con corchetes y tipos d * `set` * `dict` -#### Lista { #list } +#### List { #list } Por ejemplo, vamos a definir una variable para ser una `list` de `str`. @@ -168,7 +168,7 @@ Declara la variable, con la misma sintaxis de dos puntos (`:`). Como tipo, pon `list`. -Como la lista es un tipo que contiene algunos tipos internos, los pones entre corchetes: +Como la `list` es un tipo que contiene algunos tipos internos, los pones entre corchetes: {* ../../docs_src/python_types/tutorial006_py310.py hl[1] *} @@ -180,15 +180,15 @@ En este caso, `str` es el parámetro de tipo pasado a `list`. /// -Eso significa: "la variable `items` es una `list`, y cada uno de los ítems en esta lista es un `str`". +Eso significa: "la variable `items` es una `list`, y cada uno de los ítems en esta `list` es un `str`". -Al hacer eso, tu editor puede proporcionar soporte incluso mientras procesa elementos de la lista: +Al hacer eso, tu editor puede proporcionar soporte incluso mientras procesa elementos de la `list`: Sin tipos, eso es casi imposible de lograr. -Nota que la variable `item` es uno de los elementos en la lista `items`. +Nota que la variable `item` es uno de los elementos en la `list` `items`. Y aún así, el editor sabe que es un `str` y proporciona soporte para eso. diff --git a/docs/es/docs/tutorial/bigger-applications.md b/docs/es/docs/tutorial/bigger-applications.md index 583cc380e..31688d8ab 100644 --- a/docs/es/docs/tutorial/bigger-applications.md +++ b/docs/es/docs/tutorial/bigger-applications.md @@ -17,16 +17,16 @@ Digamos que tienes una estructura de archivos como esta: ``` . ├── app -│   ├── __init__.py -│   ├── main.py -│   ├── dependencies.py -│   └── routers -│   │ ├── __init__.py -│   │ ├── items.py -│   │ └── users.py -│   └── internal -│   ├── __init__.py -│   └── admin.py +│ ├── __init__.py +│ ├── main.py +│ ├── dependencies.py +│ └── routers +│ │ ├── __init__.py +│ │ ├── items.py +│ │ └── users.py +│ └── internal +│ ├── __init__.py +│ └── admin.py ``` /// tip | Consejo @@ -181,12 +181,12 @@ El resultado final es que los paths de item son ahora: ...como pretendíamos. * Serán marcados con una lista de tags que contiene un solo string `"items"`. - * Estos "tags" son especialmente útiles para los sistemas de documentación interactiva automática (usando OpenAPI). + * Estos "tags" son especialmente útiles para los sistemas de documentación interactiva automática (usando OpenAPI). * Todos incluirán las `responses` predefinidas. * Todas estas *path operations* tendrán la lista de `dependencies` evaluadas/ejecutadas antes de ellas. - * Si también declaras dependencias en una *path operation* específica, **también se ejecutarán**. - * Las dependencias del router se ejecutan primero, luego las [`dependencies` en el decorador](dependencies/dependencies-in-path-operation-decorators.md), y luego las dependencias de parámetros normales. - * También puedes agregar [dependencias de `Security` con `scopes`](../advanced/security/oauth2-scopes.md). + * Si también declaras dependencias en una *path operation* específica, **también se ejecutarán**. + * Las dependencias del router se ejecutan primero, luego las [`dependencies` en el decorador](dependencies/dependencies-in-path-operation-decorators.md), y luego las dependencias de parámetros normales. + * También puedes agregar [dependencias de `Security` con `scopes`](../advanced/security/oauth2-scopes.md). /// tip | Consejo @@ -396,9 +396,9 @@ Incluirá todas las rutas de ese router como parte de ella. /// note | Detalles Técnicos -En realidad creará internamente una *path operation* para cada *path operation* que fue declarada en el `APIRouter`. +FastAPI mantiene activo el `APIRouter` original y sus `APIRoute`s cuando el router se incluye en la aplicación principal. -Así, detrás de escena, funcionará como si todo fuera la misma única app. +Eso significa que las subclases personalizadas de `APIRouter` y `APIRoute` aún pueden participar después de incluir el router. /// @@ -406,7 +406,7 @@ Así, detrás de escena, funcionará como si todo fuera la misma única app. No tienes que preocuparte por el rendimiento al incluir routers. -Esto tomará microsegundos y solo sucederá al inicio. +Esto está diseñado para ser liviano y evitar añadir sobrecarga a cada request. Así que no afectará el rendimiento. ⚡ @@ -461,7 +461,7 @@ Los `APIRouter`s no están "montados", no están aislados del resto de la aplica Esto se debe a que queremos incluir sus *path operations* en el esquema de OpenAPI y las interfaces de usuario. -Como no podemos simplemente aislarlos y "montarlos" independientemente del resto, las *path operations* se "clonan" (se vuelven a crear), no se incluyen directamente. +FastAPI mantiene los routers y path operations originales activos, y combina los prefijos del router, dependencias, tags, responses y otros metadatos al manejar requests y generar OpenAPI. /// @@ -532,4 +532,16 @@ De la misma manera que puedes incluir un `APIRouter` en una aplicación `FastAPI router.include_router(other_router) ``` -Asegúrate de hacerlo antes de incluir `router` en la app de `FastAPI`, para que las *path operations* de `other_router` también se incluyan. +Puedes hacerlo antes o después de incluir `router` en la app de `FastAPI`. FastAPI seguirá incluyendo las *path operations* de `other_router` en el ruteo y en OpenAPI. + +Lo mismo aplica a las *path operations* añadidas después a los routers. También serán visibles a través de la inclusión anterior. + +/// warning | Detalles Técnicos + +Evita mutar directamente `router.routes` después de incluir un router. FastAPI trata la inclusión de routers como “en vivo”, así que el router original y sus rutas siguen formando parte del ruteo y de la generación de OpenAPI. + +Usa APIs documentadas como los decoradores de *path operations* y `.include_router()` para agregar rutas y routers. + +Trata `router.routes` como un árbol de rutas de nivel bajo que puede contener definiciones de rutas y routers incluidos, y evita depender de él como una lista plana de *path operations* finales. + +/// diff --git a/docs/es/docs/tutorial/body-multiple-params.md b/docs/es/docs/tutorial/body-multiple-params.md index c78dd2881..e1b0d4b1c 100644 --- a/docs/es/docs/tutorial/body-multiple-params.md +++ b/docs/es/docs/tutorial/body-multiple-params.md @@ -108,7 +108,7 @@ Por ejemplo: {* ../../docs_src/body_multiple_params/tutorial004_an_py310.py hl[28] *} -/// info | Información +/// note | Nota `Body` también tiene todos los mismos parámetros de validación y metadatos extras que `Query`, `Path` y otros que verás luego. @@ -123,7 +123,7 @@ Por defecto, **FastAPI** esperará su cuerpo directamente. Pero si deseas que espere un JSON con una clave `item` y dentro de ella los contenidos del modelo, como lo hace cuando declaras parámetros de cuerpo extra, puedes usar el parámetro especial `Body` `embed`: ```Python -item: Item = Body(embed=True) +item: Annotated[Item, Body(embed=True)] ``` como en: diff --git a/docs/es/docs/tutorial/body-nested-models.md b/docs/es/docs/tutorial/body-nested-models.md index 742f78d42..3ca586014 100644 --- a/docs/es/docs/tutorial/body-nested-models.md +++ b/docs/es/docs/tutorial/body-nested-models.md @@ -23,7 +23,7 @@ pasa el/los tipo(s) interno(s) como "parámetros de tipo" usando corchetes: `[` my_list: list[str] ``` -Eso es toda la sintaxis estándar de Python para declaraciones de tipo. +Esa es toda la sintaxis estándar de Python para declaraciones de tipo. Usa esa misma sintaxis estándar para atributos de modelos con tipos internos. @@ -136,7 +136,7 @@ Esto esperará (convertirá, validará, documentará, etc.) un cuerpo JSON como: } ``` -/// info | Información +/// note | Nota Nota cómo la clave `images` ahora tiene una lista de objetos de imagen. @@ -148,7 +148,7 @@ Puedes definir modelos anidados tan profundamente como desees: {* ../../docs_src/body_nested_models/tutorial007_py310.py hl[7,12,18,21,25] *} -/// info | Información +/// note | Nota Observa cómo `Offer` tiene una lista de `Item`s, que a su vez tienen una lista opcional de `Image`s diff --git a/docs/es/docs/tutorial/body.md b/docs/es/docs/tutorial/body.md index 7c3b8e9d9..a71b81a40 100644 --- a/docs/es/docs/tutorial/body.md +++ b/docs/es/docs/tutorial/body.md @@ -1,5 +1,6 @@ # Request Body { #request-body } + Cuando necesitas enviar datos desde un cliente (digamos, un navegador) a tu API, los envías como un **request body**. Un **request** body es un dato enviado por el cliente a tu API. Un **response** body es el dato que tu API envía al cliente. @@ -8,7 +9,7 @@ Tu API casi siempre tiene que enviar un **response** body. Pero los clientes no Para declarar un **request** body, usas modelos de [Pydantic](https://docs.pydantic.dev/) con todo su poder y beneficios. -/// info | Información +/// note | Nota Para enviar datos, deberías usar uno de estos métodos: `POST` (el más común), `PUT`, `DELETE` o `PATCH`. diff --git a/docs/es/docs/tutorial/cookie-param-models.md b/docs/es/docs/tutorial/cookie-param-models.md index 4e6038a46..3fbf0bcb5 100644 --- a/docs/es/docs/tutorial/cookie-param-models.md +++ b/docs/es/docs/tutorial/cookie-param-models.md @@ -32,7 +32,7 @@ Puedes ver las cookies definidas en la UI de la documentación en `/docs`: -/// info | Información +/// note | Nota Ten en cuenta que, como los **navegadores manejan las cookies** de maneras especiales y detrás de escenas, **no** permiten fácilmente que **JavaScript** las toque. diff --git a/docs/es/docs/tutorial/cookie-params.md b/docs/es/docs/tutorial/cookie-params.md index 598872c0a..eecd61907 100644 --- a/docs/es/docs/tutorial/cookie-params.md +++ b/docs/es/docs/tutorial/cookie-params.md @@ -24,13 +24,13 @@ Pero recuerda que cuando importas `Query`, `Path`, `Cookie` y otros desde `fasta /// -/// info | Información +/// note | Nota Para declarar cookies, necesitas usar `Cookie`, porque de lo contrario los parámetros serían interpretados como parámetros de query. /// -/// info | Información +/// note | Nota Ten en cuenta que, como **los navegadores manejan las cookies** de formas especiales y por detrás, **no** permiten fácilmente que **JavaScript** las toque. diff --git a/docs/es/docs/tutorial/debugging.md b/docs/es/docs/tutorial/debugging.md index b5d0704e0..95e19c149 100644 --- a/docs/es/docs/tutorial/debugging.md +++ b/docs/es/docs/tutorial/debugging.md @@ -1,5 +1,6 @@ # Depuración { #debugging } + Puedes conectar el depurador en tu editor, por ejemplo con Visual Studio Code o PyCharm. ## Llama a `uvicorn` { #call-uvicorn } @@ -62,7 +63,7 @@ from myapp import app # Algún código adicional ``` -en ese caso, la variable creada automáticamente dentro de `myapp.py` no tendrá la variable `__name__` con un valor de `"__main__"`. +en ese caso, la variable creada automáticamente `__name__` dentro de `myapp.py` no tendrá el valor `"__main__"`. Así que, la línea: @@ -72,7 +73,7 @@ Así que, la línea: no se ejecutará. -/// info | Información +/// note | Nota Para más información, revisa [la documentación oficial de Python](https://docs.python.org/3/library/__main__.html). @@ -88,7 +89,7 @@ Por ejemplo, en Visual Studio Code, puedes: * Ir al panel de "Debug". * "Add configuration...". -* Seleccionar "Python". +* Seleccionar "Python" * Ejecutar el depurador con la opción "`Python: Current File (Integrated Terminal)`". Luego, iniciará el servidor con tu código **FastAPI**, deteniéndose en tus puntos de interrupción, etc. diff --git a/docs/es/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md b/docs/es/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md index 72e4e973e..3c5796b8b 100644 --- a/docs/es/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md +++ b/docs/es/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md @@ -28,7 +28,7 @@ También puede ayudar a evitar confusiones para nuevos desarrolladores que vean /// -/// info | Información +/// note | Nota En este ejemplo usamos headers personalizados inventados `X-Key` y `X-Token`. diff --git a/docs/es/docs/tutorial/dependencies/dependencies-with-yield.md b/docs/es/docs/tutorial/dependencies/dependencies-with-yield.md index 084d72aa4..aab8eca7b 100644 --- a/docs/es/docs/tutorial/dependencies/dependencies-with-yield.md +++ b/docs/es/docs/tutorial/dependencies/dependencies-with-yield.md @@ -170,7 +170,7 @@ participant tasks as Background tasks end ``` -/// info | Información +/// note | Nota Solo **un response** será enviado al cliente. Podría ser uno de los responses de error o será el response de la *path operation*. @@ -234,6 +234,7 @@ participant operation as Path Operation Las dependencias con `yield` han evolucionado con el tiempo para cubrir diferentes casos de uso y corregir algunos problemas. Si quieres ver qué ha cambiado en diferentes versiones de FastAPI, puedes leer más al respecto en la guía avanzada, en [Dependencias avanzadas - Dependencias con `yield`, `HTTPException`, `except` y Tareas en Background](../../advanced/advanced-dependencies.md#dependencies-with-yield-httpexception-except-and-background-tasks). + ## Context Managers { #context-managers } ### Qué son los "Context Managers" { #what-are-context-managers } diff --git a/docs/es/docs/tutorial/dependencies/index.md b/docs/es/docs/tutorial/dependencies/index.md index ed5783f39..f725f4061 100644 --- a/docs/es/docs/tutorial/dependencies/index.md +++ b/docs/es/docs/tutorial/dependencies/index.md @@ -1,6 +1,6 @@ # Dependencias { #dependencies } -**FastAPI** tiene un sistema de **Inyección de Dependencias** muy poderoso pero intuitivo. +**FastAPI** tiene un sistema de **Inyección de Dependencias** muy poderoso pero intuitivo. Está diseñado para ser muy simple de usar, y para hacer que cualquier desarrollador integre otros componentes con **FastAPI** de forma muy sencilla. @@ -51,7 +51,7 @@ En este caso, esta dependencia espera: Y luego solo devuelve un `dict` que contiene esos valores. -/// info | Información +/// note | Nota FastAPI agregó soporte para `Annotated` (y comenzó a recomendarlo) en la versión 0.95.0. @@ -106,7 +106,7 @@ common_parameters --> read_users De esta manera escribes código compartido una vez y **FastAPI** se encarga de llamarlo para tus *path operations*. -/// check | Revisa +/// tip | Consejo Nota que no tienes que crear una clase especial y pasarla en algún lugar a **FastAPI** para "registrarla" o algo similar. diff --git a/docs/es/docs/tutorial/dependencies/sub-dependencies.md b/docs/es/docs/tutorial/dependencies/sub-dependencies.md index 95f3fe817..2432707f7 100644 --- a/docs/es/docs/tutorial/dependencies/sub-dependencies.md +++ b/docs/es/docs/tutorial/dependencies/sub-dependencies.md @@ -35,7 +35,7 @@ Entonces podemos usar la dependencia con: {* ../../docs_src/dependencies/tutorial005_an_py310.py hl[23] *} -/// info | Información +/// note | Nota Fíjate que solo estamos declarando una dependencia en la *path operation function*, `query_or_cookie_extractor`. diff --git a/docs/es/docs/tutorial/extra-data-types.md b/docs/es/docs/tutorial/extra-data-types.md index b92d0fcd4..bd5fdc073 100644 --- a/docs/es/docs/tutorial/extra-data-types.md +++ b/docs/es/docs/tutorial/extra-data-types.md @@ -1,5 +1,6 @@ # Tipos de Datos Extra { #extra-data-types } + Hasta ahora, has estado usando tipos de datos comunes, como: * `int` diff --git a/docs/es/docs/tutorial/extra-models.md b/docs/es/docs/tutorial/extra-models.md index 4a3b75b5b..903a13c70 100644 --- a/docs/es/docs/tutorial/extra-models.md +++ b/docs/es/docs/tutorial/extra-models.md @@ -208,4 +208,4 @@ En este caso, puedes usar `dict`: Usa múltiples modelos Pydantic y hereda libremente para cada caso. -No necesitas tener un solo modelo de datos por entidad si esa entidad debe poder tener diferentes "estados". Como el caso con la "entidad" usuario con un estado que incluye `password`, `password_hash` y sin contraseña. +No necesitas tener un solo modelo de datos por entidad si esa entidad debe poder tener diferentes "estados". La "entidad" **usuario** es un ejemplo, con estados que incluyen `password`, `password_hash` o ninguna contraseña. diff --git a/docs/es/docs/tutorial/first-steps.md b/docs/es/docs/tutorial/first-steps.md index 1fcfdc140..61e5f4099 100644 --- a/docs/es/docs/tutorial/first-steps.md +++ b/docs/es/docs/tutorial/first-steps.md @@ -90,13 +90,13 @@ Verás la documentación alternativa automática (proporcionada por [ReDoc](http Un "esquema" es una definición o descripción de algo. No el código que lo implementa, sino solo una descripción abstracta. -#### Esquema de la API { #api-schema } +#### "Esquema" de la API { #api-schema } En este caso, [OpenAPI](https://github.com/OAI/OpenAPI-Specification) es una especificación que dicta cómo definir un esquema de tu API. Esta definición de esquema incluye los paths de tu API, los posibles parámetros que toman, etc. -#### Esquema de Datos { #data-schema } +#### "Esquema" de datos { #data-schema } El término "esquema" también podría referirse a la forma de algunos datos, como el contenido JSON. @@ -180,7 +180,7 @@ lo cual sería equivalente a: from backend.main import app ``` -### `fastapi dev` con path { #fastapi-dev-with-path } +### `fastapi dev` con path o con la opción de CLI `--entrypoint` { #fastapi-dev-with-path-or-with-entrypoint-cli-option } También puedes pasar el path del archivo al comando `fastapi dev`, y adivinará el objeto app de FastAPI que debe usar: @@ -188,29 +188,19 @@ También puedes pasar el path del archivo al comando `fastapi dev`, y adivinará $ fastapi dev main.py ``` -Pero tendrías que recordar pasar el path correcto cada vez que llames al comando `fastapi`. - -Además, otras herramientas podrían no ser capaces de encontrarlo, por ejemplo la [Extensión de VS Code](../editor-support.md) o [FastAPI Cloud](https://fastapicloud.com), así que se recomienda usar el `entrypoint` en `pyproject.toml`. - -### Despliega tu app (opcional) { #deploy-your-app-optional } - -Opcionalmente puedes desplegar tu app de FastAPI en [FastAPI Cloud](https://fastapicloud.com), ve y únete a la lista de espera si aún no lo has hecho. 🚀 - -Si ya tienes una cuenta de **FastAPI Cloud** (te invitamos desde la lista de espera 😉), puedes desplegar tu aplicación con un solo comando. - -Antes de desplegar, asegúrate de haber iniciado sesión: - -
+O, también puedes pasar la opción `--entrypoint` al comando `fastapi dev`: ```console -$ fastapi login - -You are logged in to FastAPI Cloud 🚀 +$ fastapi dev --entrypoint main:app ``` -
+Pero tendrías que recordar pasar el path\entrypoint correcto cada vez que llames al comando `fastapi`. + +Además, otras herramientas podrían no ser capaces de encontrarlo, por ejemplo la [Extensión de VS Code](../editor-support.md) o [FastAPI Cloud](https://fastapicloud.com), así que se recomienda usar el `entrypoint` en `pyproject.toml`. -Luego despliega tu app: +### Despliega tu app (opcional) { #deploy-your-app-optional } + +Opcionalmente puedes desplegar tu app de FastAPI en [FastAPI Cloud](https://fastapicloud.com) con un solo comando. 🚀
@@ -226,6 +216,8 @@ Deploying to FastAPI Cloud...
+La CLI detectará automáticamente tu aplicación de FastAPI y la desplegará en la nube. Si no has iniciado sesión, se abrirá tu navegador para completar el proceso de autenticación. + ¡Eso es todo! Ahora puedes acceder a tu app en esa URL. ✨ ## Recapitulación, paso a paso { #recap-step-by-step } @@ -270,7 +262,7 @@ https://example.com/items/foo /items/foo ``` -/// info | Información +/// note | Nota Un "path" también es comúnmente llamado "endpoint" o "ruta". @@ -309,7 +301,7 @@ Normalmente usas: * `PUT`: para actualizar datos. * `DELETE`: para eliminar datos. -Así que, en OpenAPI, cada uno de los métodos HTTP se llama una "operation". +Así que, en OpenAPI, cada uno de los métodos HTTP se llama una "operación". Vamos a llamarlas "**operaciones**" también. @@ -322,7 +314,7 @@ El `@app.get("/")` le dice a **FastAPI** que la función justo debajo se encarga * el path `/` * usando una get operación -/// info | Información sobre `@decorator` +/// note | Información sobre `@decorator` Esa sintaxis `@algo` en Python se llama un "decorador". diff --git a/docs/es/docs/tutorial/frontend.md b/docs/es/docs/tutorial/frontend.md new file mode 100644 index 000000000..707772467 --- /dev/null +++ b/docs/es/docs/tutorial/frontend.md @@ -0,0 +1,133 @@ +# Frontend { #frontend } + +Puedes servir apps frontend estáticas con `app.frontend()` (o `router.frontend()`). + +Esto es útil para herramientas de frontend que generan archivos estáticos, como React con Vite, TanStack Router, Astro, Vue, Svelte, Angular, Solid y otras. + +Con estas herramientas, normalmente tienes un paso que construye el frontend, con un comando como: + +```bash +npm run build +``` + +Eso generaría un directorio como `./dist/` con tus archivos frontend. + +Puedes usar `app.frontend()` para servir ese directorio siguiendo las convenciones que necesitan estos frameworks frontend. + +**FastAPI** revisa primero las *path operations*. Los archivos frontend se revisan solo si ninguna ruta normal coincide, así que tu API no se verá afectada. + +## Sirve un Frontend { #serve-a-frontend } + +Después de construir tu frontend, por ejemplo con `npm run build`, pon los archivos generados en un directorio, por ejemplo, `dist`. + +La estructura de tu proyecto podría verse así: + +```text +. +├── pyproject.toml +├── app +│ ├── __init__.py +│ └── main.py +└── dist + ├── index.html + └── assets + └── app.js +``` + +Luego sírvelo con `app.frontend()`: + +{* ../../docs_src/frontend/tutorial001_py310.py hl[5] *} + +Con esto, un request a `/assets/app.js` puede servir `dist/assets/app.js`. + +Si también tienes una *path operation* de **FastAPI**, la *path operation* gana. + +## Routing del lado del cliente { #client-side-routing } + +Muchas apps frontend, incluidas las **single-page apps** (SPAs), usan routing del lado del cliente. Un path como `/dashboard/settings` podría no ser un archivo real, pero el framework se encargaría de manejarlo. + +Entonces, si se accede a esa URL directamente (en lugar de navegar por la app), el backend debería servir la app frontend desde `index.html`, para que el framework frontend pueda manejar el routing del lado del cliente. + +Para eso, usa `fallback="index.html"`: + +{* ../../docs_src/frontend/tutorial002_py310.py hl[5] *} + +**FastAPI** usa este fallback solo para requests `GET` y `HEAD` que parecen navegación del navegador. Los archivos faltantes como JavaScript, CSS e imágenes siguen devolviendo `404`. + +Los requests con otros métodos, como `POST` o `PUT`, a paths que solo coinciden con el fallback del frontend también devuelven `404`. Las *path operations* normales de **FastAPI** siguen teniendo mayor prioridad que las rutas frontend. + +/// tip | Consejo + +Por defecto, `fallback` tiene un valor de `fallback="auto"`. En la mayoría de los casos no necesitarás especificar `fallback`. Lee más abajo para los detalles. + +/// + +Esto es lo que querrías con muchas apps frontend que usan routing del lado del cliente, por ejemplo, React con TanStack Router, Vue, Angular, SvelteKit o Solid. + +## Página 404 personalizada { #custom-404-page } + +También puedes servir una página estática `404.html` para paths frontend faltantes: + +{* ../../docs_src/frontend/tutorial003_py310.py hl[5] *} + +Esa response mantiene un código de estado `404`. + +En este caso, **FastAPI** no servirá `index.html` para paths frontend faltantes. En su lugar, devolverá el archivo `404.html`. + +/// tip | Consejo + +Por defecto, `fallback` tiene un valor de `fallback="auto"`. Con esto, si se encuentra un archivo `404.html`, se usará automáticamente como fallback. + +Así que normalmente puedes omitir el argumento `fallback`. + +/// + +Esto es útil con herramientas de frontend que generan archivos HTML estáticos para cada página, como Astro. + +## Fallback automático { #fallback-auto } + +Por defecto, `app.frontend()` usa `fallback="auto"`. + +Si hay un archivo `404.html` en el directorio frontend, los paths frontend faltantes sirven ese archivo con código de estado `404`. + +De lo contrario, si hay un archivo `index.html`, los paths faltantes de navegación del navegador sirven `index.html`, que es lo que muchas apps frontend con routing del lado del cliente esperan. + +Así que, en la mayoría de los casos, puedes usar `app.frontend("/", directory="dist")` sin especificar el argumento `fallback`. + +{* ../../docs_src/frontend/tutorial001_py310.py hl[5] *} + +## Desactiva el fallback { #disable-fallback } + +Si no quieres servir un archivo fallback para paths frontend faltantes, usa `fallback=None`: + +{* ../../docs_src/frontend/tutorial005_py310.py hl[5] *} + +Entonces los paths frontend faltantes devuelven el `404` normal. + +## Revisa el directorio { #check-directory } + +Por defecto, `app.frontend()` revisa que el directorio exista cuando se crea la app. + +Esto ayuda a detectar errores de configuración temprano. Por ejemplo, si falta el directorio de salida del build del frontend, **FastAPI** lanzará un error al iniciar. + +Si tus archivos frontend se crean más tarde, por ejemplo mediante un paso de build separado después de crear el objeto app, configura `check_dir=False`: + +{* ../../docs_src/frontend/tutorial006_py310.py hl[5] *} + +Con `check_dir=False`, **FastAPI** no revisará el directorio cuando se cree la app. Si el directorio configurado todavía falta cuando se maneja un request, **FastAPI** lanzará un error en ese momento. + +## Úsalo con `APIRouter` { #use-it-with-apirouter } + +También puedes agregar archivos frontend a un `APIRouter` e incluirlo con un prefijo: + +{* ../../docs_src/frontend/tutorial004_py310.py hl[6,7] *} + +En este ejemplo, los paths frontend se sirven bajo `/app`. + +Cualquier *path operation* regular en la app seguirá teniendo prioridad, incluso en otros routers. + +## Solo salida estática del build { #static-build-output-only } + +`app.frontend()` sirve archivos ya generados por tu build del frontend. + +No ejecuta renderizado del lado del servidor. Es para frameworks frontend que generan archivos estáticos, no para frameworks que necesitan renderizado dinámico en el servidor para cada request. diff --git a/docs/es/docs/tutorial/handling-errors.md b/docs/es/docs/tutorial/handling-errors.md index 737c43e41..f64064231 100644 --- a/docs/es/docs/tutorial/handling-errors.md +++ b/docs/es/docs/tutorial/handling-errors.md @@ -101,7 +101,7 @@ Así que recibirás un error limpio, con un código de estado HTTP de `418` y un {"message": "Oops! yolo did something. There goes a rainbow..."} ``` -/// note | Nota Técnica +/// note | Detalles Técnicos También podrías usar `from starlette.requests import Request` y `from starlette.responses import JSONResponse`. @@ -109,11 +109,11 @@ También podrías usar `from starlette.requests import Request` y `from starlett /// -## Sobrescribir los manejadores de excepciones predeterminados { #override-the-default-exception-handlers } +## Sobrescribir los manejadores de excepciones por defecto { #override-the-default-exception-handlers } -**FastAPI** tiene algunos manejadores de excepciones predeterminados. +**FastAPI** tiene algunos manejadores de excepciones por defecto. -Estos manejadores se encargan de devolver los responses JSON predeterminadas cuando lanzas un `HTTPException` y cuando el request tiene datos inválidos. +Estos manejadores se encargan de devolver los responses JSON por defecto cuando lanzas un `HTTPException` y cuando el request tiene datos inválidos. Puedes sobrescribir estos manejadores de excepciones con los tuyos propios. @@ -121,7 +121,7 @@ Puedes sobrescribir estos manejadores de excepciones con los tuyos propios. Cuando un request contiene datos inválidos, **FastAPI** lanza internamente un `RequestValidationError`. -Y también incluye un manejador de excepciones predeterminado para ello. +Y también incluye un manejador de excepciones por defecto para ello. Para sobrescribirlo, importa el `RequestValidationError` y úsalo con `@app.exception_handler(RequestValidationError)` para decorar el manejador de excepciones. @@ -161,7 +161,7 @@ Por ejemplo, podrías querer devolver un response de texto plano en lugar de JSO {* ../../docs_src/handling_errors/tutorial004_py310.py hl[3:4,9:11,25] *} -/// note | Nota Técnica +/// note | Detalles Técnicos También podrías usar `from starlette.responses import PlainTextResponse`. @@ -237,8 +237,8 @@ from starlette.exceptions import HTTPException as StarletteHTTPException ### Reutilizar los manejadores de excepciones de **FastAPI** { #reuse-fastapis-exception-handlers } -Si quieres usar la excepción junto con los mismos manejadores de excepciones predeterminados de **FastAPI**, puedes importar y reutilizar los manejadores de excepciones predeterminados de `fastapi.exception_handlers`: +Si quieres usar la excepción junto con los mismos manejadores de excepciones por defecto de **FastAPI**, puedes importar y reutilizar los manejadores de excepciones por defecto de `fastapi.exception_handlers`: {* ../../docs_src/handling_errors/tutorial006_py310.py hl[2:5,15,21] *} -En este ejemplo solo estás `print`eando el error con un mensaje muy expresivo, pero te haces una idea. Puedes usar la excepción y luego simplemente reutilizar los manejadores de excepciones predeterminados. +En este ejemplo solo estás `print`eando el error con un mensaje muy expresivo, pero te haces una idea. Puedes usar la excepción y luego simplemente reutilizar los manejadores de excepciones por defecto. diff --git a/docs/es/docs/tutorial/index.md b/docs/es/docs/tutorial/index.md index 414e865b2..59b9e4164 100644 --- a/docs/es/docs/tutorial/index.md +++ b/docs/es/docs/tutorial/index.md @@ -54,7 +54,7 @@ $ fastapi dev Es **ALTAMENTE recomendable** que escribas o copies el código, lo edites y lo ejecutes localmente. -Usarlo en tu editor es lo que realmente te muestra los beneficios de FastAPI, al ver cuán poco código tienes que escribir, todos los chequeos de tipos, autocompletado, etc. +Usarlo en tu editor es lo que realmente te muestra los beneficios de FastAPI, al ver cuán poco código tienes que escribir, todo el chequeo de tipos, autocompletado, etc. --- diff --git a/docs/es/docs/tutorial/metadata.md b/docs/es/docs/tutorial/metadata.md index 35bc98a26..d8b7176d5 100644 --- a/docs/es/docs/tutorial/metadata.md +++ b/docs/es/docs/tutorial/metadata.md @@ -1,4 +1,4 @@ -# Metadata y URLs de Docs { #metadata-and-docs-urls } +# Metadata y URLs de documentación { #metadata-and-docs-urls } Puedes personalizar varias configuraciones de metadata en tu aplicación **FastAPI**. @@ -11,7 +11,7 @@ Puedes establecer los siguientes campos que se usan en la especificación OpenAP | `title` | `str` | El título de la API. | | `summary` | `str` | Un resumen corto de la API. Disponible desde OpenAPI 3.1.0, FastAPI 0.99.0. | | `description` | `str` | Una breve descripción de la API. Puede usar Markdown. | -| `version` | `string` | La versión de la API. Esta es la versión de tu propia aplicación, no de OpenAPI. Por ejemplo, `2.5.0`. | +| `version` | `str` | La versión de la API. Esta es la versión de tu propia aplicación, no de OpenAPI. Por ejemplo, `2.5.0`. | | `terms_of_service` | `str` | Una URL a los Términos de Servicio para la API. Si se proporciona, debe ser una URL. | | `contact` | `dict` | La información de contacto para la API expuesta. Puede contener varios campos.
contact fields
ParámetroTipoDescripción
namestrEl nombre identificativo de la persona/organización de contacto.
urlstrLa URL que apunta a la información de contacto. DEBE tener el formato de una URL.
emailstrLa dirección de correo electrónico de la persona/organización de contacto. DEBE tener el formato de una dirección de correo.
| | `license_info` | `dict` | La información de la licencia para la API expuesta. Puede contener varios campos.
license_info fields
ParámetroTipoDescripción
namestrREQUERIDO (si se establece un license_info). El nombre de la licencia utilizada para la API.
identifierstrUna expresión de licencia [SPDX](https://spdx.org/licenses/) para la API. El campo identifier es mutuamente excluyente del campo url. Disponible desde OpenAPI 3.1.0, FastAPI 0.99.0.
urlstrUna URL a la licencia utilizada para la API. DEBE tener el formato de una URL.
| @@ -74,7 +74,7 @@ Usa el parámetro `tags` con tus *path operations* (y `APIRouter`s) para asignar {* ../../docs_src/metadata/tutorial004_py310.py hl[21,26] *} -/// info | Información +/// note | Nota Lee más sobre etiquetas en [Configuración de Path Operation](path-operation-configuration.md#tags). @@ -104,7 +104,7 @@ Por ejemplo, para configurarlo para que se sirva en `/api/v1/openapi.json`: Si quieres deshabilitar el esquema OpenAPI completamente, puedes establecer `openapi_url=None`, eso también deshabilitará las interfaces de usuario de documentación que lo usan. -## URLs de Docs { #docs-urls } +## URLs de documentación { #docs-urls } Puedes configurar las dos interfaces de usuario de documentación incluidas: diff --git a/docs/es/docs/tutorial/path-operation-configuration.md b/docs/es/docs/tutorial/path-operation-configuration.md index 21fd503bb..7331b0f3a 100644 --- a/docs/es/docs/tutorial/path-operation-configuration.md +++ b/docs/es/docs/tutorial/path-operation-configuration.md @@ -56,7 +56,7 @@ Puedes añadir un `summary` y `description`: ## Descripción desde docstring { #description-from-docstring } -Como las descripciones tienden a ser largas y cubrir múltiples líneas, puedes declarar la descripción de la *path operation* en la docstring de la función y **FastAPI** la leerá desde allí. +Como las descripciones tienden a ser largas y cubrir múltiples líneas, puedes declarar la descripción de la *path operation* en la docstring de la función y **FastAPI** la leerá desde allí. Puedes escribir [Markdown](https://en.wikipedia.org/wiki/Markdown) en el docstring, se interpretará y mostrará correctamente (teniendo en cuenta la indentación del docstring). @@ -72,13 +72,13 @@ Puedes especificar la descripción del response con el parámetro `response_desc {* ../../docs_src/path_operation_configuration/tutorial005_py310.py hl[18] *} -/// info | Información +/// note | Nota Ten en cuenta que `response_description` se refiere específicamente al response, mientras que `description` se refiere a la *path operation* en general. /// -/// check | Revisa +/// tip | Consejo OpenAPI especifica que cada *path operation* requiere una descripción de response. @@ -90,11 +90,11 @@ Entonces, si no proporcionas una, **FastAPI** generará automáticamente una de ## Deprecar una *path operation* { #deprecate-a-path-operation } -Si necesitas marcar una *path operation* como deprecated, pero sin eliminarla, pasa el parámetro `deprecated`: +Si necesitas marcar una *path operation* como obsoleta, pero sin eliminarla, pasa el parámetro `deprecated`: {* ../../docs_src/path_operation_configuration/tutorial006_py310.py hl[16] *} -Se marcará claramente como deprecado en la documentación interactiva: +Se marcará claramente como deprecated en la documentación interactiva: diff --git a/docs/es/docs/tutorial/path-params-numeric-validations.md b/docs/es/docs/tutorial/path-params-numeric-validations.md index 5e7b9a978..24cd5117e 100644 --- a/docs/es/docs/tutorial/path-params-numeric-validations.md +++ b/docs/es/docs/tutorial/path-params-numeric-validations.md @@ -8,7 +8,7 @@ Primero, importa `Path` de `fastapi`, e importa `Annotated`: {* ../../docs_src/path_params_numeric_validations/tutorial001_an_py310.py hl[1,3] *} -/// info | Información +/// note | Nota FastAPI agregó soporte para `Annotated` (y comenzó a recomendar su uso) en la versión 0.95.0. @@ -131,7 +131,7 @@ Y también puedes declarar validaciones numéricas: * `lt`: `l`ess `t`han * `le`: `l`ess than or `e`qual -/// info | Información +/// note | Nota `Query`, `Path` y otras clases que verás más adelante son subclases de una clase común `Param`. diff --git a/docs/es/docs/tutorial/path-params.md b/docs/es/docs/tutorial/path-params.md index f1aa4ef8b..94465013e 100644 --- a/docs/es/docs/tutorial/path-params.md +++ b/docs/es/docs/tutorial/path-params.md @@ -20,7 +20,7 @@ Puedes declarar el tipo de un parámetro de path en la función, usando anotacio En este caso, `item_id` se declara como un `int`. -/// check | Revisa +/// tip | Consejo Esto te dará soporte del editor dentro de tu función, con chequeo de errores, autocompletado, etc. @@ -34,7 +34,7 @@ Si ejecutas este ejemplo y abres tu navegador en [http://127.0.0.1:8000/items/3] {"item_id":3} ``` -/// check | Revisa +/// tip | Consejo Nota que el valor que tu función recibió (y devolvió) es `3`, como un `int` de Python, no un string `"3"`. @@ -66,7 +66,7 @@ porque el parámetro de path `item_id` tenía un valor de `"foo"`, que no es un El mismo error aparecería si proporcionaras un `float` en lugar de un `int`, como en: [http://127.0.0.1:8000/items/4.2](http://127.0.0.1:8000/items/4.2) -/// check | Revisa +/// tip | Consejo Entonces, con la misma declaración de tipo de Python, **FastAPI** te ofrece validación de datos. @@ -82,7 +82,7 @@ Y cuando abras tu navegador en [http://127.0.0.1:8000/docs](http://127.0.0.1:800 -/// check | Revisa +/// tip | Consejo Nuevamente, solo con esa misma declaración de tipo de Python, **FastAPI** te ofrece documentación automática e interactiva (integrando Swagger UI). @@ -130,7 +130,7 @@ La primera siempre será utilizada ya que el path coincide primero. ## Valores predefinidos { #predefined-values } -Si tienes una *path operation* que recibe un *path parameter*, pero quieres que los valores posibles válidos del *path parameter* estén predefinidos, puedes usar un `Enum` estándar de Python. +Si tienes una *path operation* que recibe un *path parameter*, pero quieres que los valores posibles válidos del *path parameter* estén predefinidos, puedes usar un `Enum` estándar de Python. ### Crear una clase `Enum` { #create-an-enum-class } diff --git a/docs/es/docs/tutorial/query-params-str-validations.md b/docs/es/docs/tutorial/query-params-str-validations.md index 44beba2d3..fab02dd35 100644 --- a/docs/es/docs/tutorial/query-params-str-validations.md +++ b/docs/es/docs/tutorial/query-params-str-validations.md @@ -18,7 +18,7 @@ Tener `str | None` permitirá que tu editor te dé un mejor soporte y detecte er ## Validaciones adicionales { #additional-validation } -Vamos a hacer que, aunque `q` sea opcional, siempre que se proporcione, su longitud no exceda los 50 caracteres. +Vamos a hacer que, aunque `q` sea opcional, siempre que se proporcione, **su longitud no exceda los 50 caracteres**. ### Importar `Query` y `Annotated` { #import-query-and-annotated } @@ -29,7 +29,7 @@ Para lograr eso, primero importa: {* ../../docs_src/query_params_str_validations/tutorial002_an_py310.py hl[1,3] *} -/// info | Información +/// note | Nota FastAPI añadió soporte para `Annotated` (y empezó a recomendarlo) en la versión 0.95.0. @@ -69,7 +69,7 @@ Ahora que tenemos este `Annotated` donde podemos poner más información (en est Nota que el valor por defecto sigue siendo `None`, por lo que el parámetro sigue siendo opcional. -Pero ahora, al tener `Query(max_length=50)` dentro de `Annotated`, le estamos diciendo a FastAPI que queremos que tenga validación adicional para este valor, queremos que tenga un máximo de 50 caracteres. 😎 +Pero ahora, al tener `Query(max_length=50)` dentro de `Annotated`, le estamos diciendo a FastAPI que queremos que tenga **validación adicional** para este valor, queremos que tenga un máximo de 50 caracteres. 😎 /// tip | Consejo @@ -79,9 +79,9 @@ Aquí estamos usando `Query()` porque este es un **parámetro de query**. Más a FastAPI ahora: -* Validará los datos asegurándose de que la longitud máxima sea de 50 caracteres -* Mostrará un error claro para el cliente cuando los datos no sean válidos -* Documentará el parámetro en el OpenAPI esquema *path operation* (así aparecerá en la UI de documentación automática) +* **Validará** los datos asegurándose de que la longitud máxima sea de 50 caracteres +* Mostrará un **error claro** para el cliente cuando los datos no sean válidos +* **Documentará** el parámetro en el esquema de OpenAPI *path operation* (así aparecerá en la **UI de documentación automática**) ## Alternativa (antigua): `Query` como valor por defecto { #alternative-old-query-as-the-default-value } @@ -120,7 +120,7 @@ Luego, podemos pasar más parámetros a `Query`. En este caso, el parámetro `ma q: str | None = Query(default=None, max_length=50) ``` -Esto validará los datos, mostrará un error claro cuando los datos no sean válidos, y documentará el parámetro en el esquema del *path operation* de OpenAPI. +Esto validará los datos, mostrará un error claro cuando los datos no sean válidos, y documentará el parámetro en el esquema de OpenAPI *path operation*. ### `Query` como valor por defecto o en `Annotated` { #query-as-the-default-value-or-in-annotated } @@ -150,13 +150,13 @@ q: str = Query(default="rick") ### Ventajas de `Annotated` { #advantages-of-annotated } -Usar `Annotated` es recomendado en lugar del valor por defecto en los parámetros de función, es mejor por múltiples razones. 🤓 +**Usar `Annotated` es recomendado** en lugar del valor por defecto en los parámetros de función, es **mejor** por múltiples razones. 🤓 -El valor por defecto del parámetro de función es el valor real por defecto, eso es más intuitivo con Python en general. 😌 +El valor **por defecto** del **parámetro de función** es el **valor real por defecto**, eso es más intuitivo con Python en general. 😌 -Podrías llamar a esa misma función en otros lugares sin FastAPI, y funcionaría como se espera. Si hay un parámetro requerido (sin un valor por defecto), tu editor te avisará con un error, Python también se quejará si lo ejecutas sin pasar el parámetro requerido. +Podrías **llamar** a esa misma función en **otros lugares** sin FastAPI, y **funcionaría como se espera**. Si hay un parámetro **requerido** (sin un valor por defecto), tu **editor** te avisará con un error, **Python** también se quejará si lo ejecutas sin pasar el parámetro requerido. -Cuando no usas `Annotated` y en su lugar usas el estilo de valor por defecto (antiguo), si llamas a esa función sin FastAPI en otros lugares, tienes que recordar pasar los argumentos a la función para que funcione correctamente, de lo contrario, los valores serán diferentes de lo que esperas (por ejemplo, `QueryInfo` o algo similar en lugar de `str`). Y tu editor no se quejará, y Python no se quejará al ejecutar esa función, solo cuando los errores dentro de las operaciones hagan que funcione incorrectamente. +Cuando no usas `Annotated` y en su lugar usas el **estilo de valor por defecto (antiguo)**, si llamas a esa función sin FastAPI en **otros lugares**, tienes que **recordar** pasar los argumentos a la función para que funcione correctamente, de lo contrario, los valores serán diferentes de lo que esperas (por ejemplo, `QueryInfo` o algo similar en lugar de `str`). Y tu editor no se quejará, y Python no se quejará al ejecutar esa función, solo cuando las operaciones internas generen errores. Dado que `Annotated` puede tener más de una anotación de metadato, ahora podrías incluso usar la misma función con otras herramientas, como [Typer](https://typer.tiangolo.com/). 🚀 @@ -172,13 +172,13 @@ Puedes definir una ISBN o con `imdb-` para un ID de URL de película de IMDB: +Por ejemplo, este validador personalizado revisa que el ID del ítem empiece con `isbn-` para un número de libro ISBN o con `imdb-` para un ID de URL de película de IMDB: {* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py hl[5,16:19,24] *} -/// info | Información +/// note | Nota Esto está disponible con Pydantic versión 2 o superior. 😎 @@ -390,15 +390,15 @@ Esto está disponible con Pydantic versión 2 o superior. 😎 /// tip | Consejo -Si necesitas hacer cualquier tipo de validación que requiera comunicarte con algún componente externo, como una base de datos u otra API, deberías usar Dependencias de FastAPI, las aprenderás más adelante. +Si necesitas hacer cualquier tipo de validación que requiera comunicarte con algún **componente externo**, como una base de datos u otra API, deberías usar **Dependencias de FastAPI**, las aprenderás más adelante. -Estos validadores personalizados son para cosas que pueden comprobarse solo con los mismos datos provistos en el request. +Estos validadores personalizados son para cosas que pueden revisarse **solo** con los **mismos datos** provistos en el request. /// ### Entiende ese código { #understand-that-code } -El punto importante es solo usar `AfterValidator` con una función dentro de `Annotated`. Si quieres, sáltate esta parte. 🤸 +El punto importante es solo usar **`AfterValidator` con una función dentro de `Annotated`**. Si quieres, sáltate esta parte. 🤸 --- @@ -406,7 +406,7 @@ Pero si te da curiosidad este ejemplo de código específico y sigues entretenid #### String con `value.startswith()` { #string-with-value-startswith } -¿Lo notaste? un string usando `value.startswith()` puede recibir una tupla, y comprobará cada valor en la tupla: +¿Lo notaste? Un string usando `value.startswith()` puede recibir una tupla, y revisará cada valor en la tupla: {* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py ln[16:19] hl[17] *} @@ -416,13 +416,13 @@ Con `data.items()` obtenemos un `) envían los datos al /// note | Detalles Técnicos -Los datos de los forms normalmente se codifican usando el "media type" `application/x-www-form-urlencoded` cuando no incluyen archivos. +Los datos de los formularios normalmente se codifican usando el "media type" `application/x-www-form-urlencoded` cuando no incluyen archivos. Pero cuando el formulario incluye archivos, se codifica como `multipart/form-data`. Si usas `File`, **FastAPI** sabrá que tiene que obtener los archivos de la parte correcta del cuerpo. diff --git a/docs/es/docs/tutorial/request-form-models.md b/docs/es/docs/tutorial/request-form-models.md index b20421bd0..e0685d4be 100644 --- a/docs/es/docs/tutorial/request-form-models.md +++ b/docs/es/docs/tutorial/request-form-models.md @@ -2,7 +2,7 @@ Puedes usar **modelos de Pydantic** para declarar **campos de formulario** en FastAPI. -/// info | Información +/// note | Nota Para usar formularios, primero instala [`python-multipart`](https://github.com/Kludex/python-multipart). diff --git a/docs/es/docs/tutorial/request-forms-and-files.md b/docs/es/docs/tutorial/request-forms-and-files.md index f7b5000b7..434a665c9 100644 --- a/docs/es/docs/tutorial/request-forms-and-files.md +++ b/docs/es/docs/tutorial/request-forms-and-files.md @@ -2,7 +2,7 @@ Puedes definir archivos y campos de formulario al mismo tiempo usando `File` y `Form`. -/// info | Información +/// note | Nota Para recibir archivos subidos y/o form data, primero instala [`python-multipart`](https://github.com/Kludex/python-multipart). diff --git a/docs/es/docs/tutorial/request-forms.md b/docs/es/docs/tutorial/request-forms.md index 7b78aee69..640e02282 100644 --- a/docs/es/docs/tutorial/request-forms.md +++ b/docs/es/docs/tutorial/request-forms.md @@ -1,8 +1,8 @@ -# Datos de formulario { #form-data } +# Form Data { #form-data } Cuando necesitas recibir campos de formulario en lugar de JSON, puedes usar `Form`. -/// info | Información +/// note | Nota Para usar formularios, primero instala [`python-multipart`](https://github.com/Kludex/python-multipart). @@ -14,13 +14,13 @@ $ pip install python-multipart /// -## Importar `Form` { #import-form } +## Importa `Form` { #import-form } -Importar `Form` desde `fastapi`: +Importa `Form` desde `fastapi`: {* ../../docs_src/request_forms/tutorial001_an_py310.py hl[3] *} -## Definir parámetros de `Form` { #define-form-parameters } +## Define parámetros de `Form` { #define-form-parameters } Crea parámetros de formulario de la misma manera que lo harías para `Body` o `Query`: @@ -32,7 +32,7 @@ La especificación requiere que los campos se Con `Form` puedes declarar las mismas configuraciones que con `Body` (y `Query`, `Path`, `Cookie`), incluyendo validación, ejemplos, un alias (por ejemplo, `user-name` en lugar de `username`), etc. -/// info | Información +/// note | Nota `Form` es una clase que hereda directamente de `Body`. @@ -70,4 +70,4 @@ Esto no es una limitación de **FastAPI**, es parte del protocolo HTTP. ## Recapitulación { #recap } -Usa `Form` para declarar parámetros de entrada de datos de formulario. +Usa `Form` para declarar parámetros de entrada de form data. diff --git a/docs/es/docs/tutorial/response-model.md b/docs/es/docs/tutorial/response-model.md index fc9028bee..2c97a6764 100644 --- a/docs/es/docs/tutorial/response-model.md +++ b/docs/es/docs/tutorial/response-model.md @@ -72,7 +72,7 @@ Aquí estamos declarando un modelo `UserIn`, contendrá una contraseña en texto {* ../../docs_src/response_model/tutorial002_py310.py hl[7,9] *} -/// info | Información +/// note | Nota Para usar `EmailStr`, primero instala [`email-validator`](https://github.com/JoshData/python-email-validator). @@ -251,7 +251,7 @@ Entonces, si envías un request a esa *path operation* para el ítem con ID `foo } ``` -/// info | Información +/// note | Nota También puedes usar: diff --git a/docs/es/docs/tutorial/response-status-code.md b/docs/es/docs/tutorial/response-status-code.md index a070819bb..2e0b88c5d 100644 --- a/docs/es/docs/tutorial/response-status-code.md +++ b/docs/es/docs/tutorial/response-status-code.md @@ -1,5 +1,6 @@ # Código de Estado del Response { #response-status-code } + De la misma manera que puedes especificar un modelo de response, también puedes declarar el código de estado HTTP usado para el response con el parámetro `status_code` en cualquiera de las *path operations*: * `@app.get()` @@ -18,7 +19,7 @@ Observa que `status_code` es un parámetro del método "decorador" (`get`, `post El parámetro `status_code` recibe un número con el código de estado HTTP. -/// info | Información +/// note | Nota `status_code` también puede recibir un `IntEnum`, como por ejemplo el [`http.HTTPStatus`](https://docs.python.org/3/library/http.html#http.HTTPStatus) de Python. diff --git a/docs/es/docs/tutorial/schema-extra-example.md b/docs/es/docs/tutorial/schema-extra-example.md index 73d0cdbe4..310697d0b 100644 --- a/docs/es/docs/tutorial/schema-extra-example.md +++ b/docs/es/docs/tutorial/schema-extra-example.md @@ -1,4 +1,4 @@ -# Declarar Datos de Ejemplo de Request { #declare-request-example-data } +# Declara Datos de Ejemplo de Request { #declare-request-example-data } Puedes declarar ejemplos de los datos que tu aplicación puede recibir. @@ -24,7 +24,7 @@ Por ejemplo, podrías usarlo para añadir metadatos para una interfaz de usuario /// -/// info | Información +/// note | Nota OpenAPI 3.1.0 (usado desde FastAPI 0.99.0) añadió soporte para `examples`, que es parte del estándar de **JSON Schema**. @@ -155,7 +155,7 @@ OpenAPI también añadió los campos `example` y `examples` a otras partes de la * `File()` * `Form()` -/// info | Información +/// note | Nota Este viejo parámetro `examples` específico de OpenAPI ahora es `openapi_examples` desde FastAPI `0.103.0`. @@ -171,7 +171,7 @@ Y ahora este nuevo campo `examples` tiene precedencia sobre el viejo campo únic Este nuevo campo `examples` en JSON Schema es **solo una `list`** de ejemplos, no un dict con metadatos adicionales como en los otros lugares en OpenAPI (descritos arriba). -/// info | Información +/// note | Nota Incluso después de que OpenAPI 3.1.0 fue lanzado con esta nueva integración más sencilla con JSON Schema, por un tiempo, Swagger UI, la herramienta que proporciona la documentación automática, no soportaba OpenAPI 3.1.0 (lo hace desde la versión 5.0.0 🎉). diff --git a/docs/es/docs/tutorial/security/first-steps.md b/docs/es/docs/tutorial/security/first-steps.md index 8118906e5..a8df7e9a5 100644 --- a/docs/es/docs/tutorial/security/first-steps.md +++ b/docs/es/docs/tutorial/security/first-steps.md @@ -24,7 +24,7 @@ Copia el ejemplo en un archivo `main.py`: ## Ejecútalo { #run-it } -/// info | Información +/// note | Nota El paquete [`python-multipart`](https://github.com/Kludex/python-multipart) se instala automáticamente con **FastAPI** cuando ejecutas el comando `pip install "fastapi[standard]"`. @@ -60,7 +60,7 @@ Verás algo así: -/// check | ¡Botón de autorización! +/// tip | ¡Botón de autorización! Ya tienes un nuevo y brillante botón de "Authorize". @@ -118,7 +118,7 @@ Así que, revisémoslo desde ese punto de vista simplificado: En este ejemplo vamos a usar **OAuth2**, con el flujo **Password**, usando un token **Bearer**. Hacemos eso utilizando la clase `OAuth2PasswordBearer`. -/// info | Información +/// note | Nota Un token "bearer" no es la única opción. @@ -146,9 +146,9 @@ Usar una URL relativa es importante para asegurarse de que tu aplicación siga f Este parámetro no crea ese endpoint / *path operation*, pero declara que la URL `/token` será la que el cliente deberá usar para obtener el token. Esa información se usa en OpenAPI, y luego en los sistemas de documentación interactiva del API. -Pronto también crearemos la verdadera *path operation*. +Pronto también crearemos la path operation real. -/// info | Información +/// note | Nota Si eres un "Pythonista" muy estricto, tal vez no te guste el estilo del nombre del parámetro `tokenUrl` en lugar de `token_url`. @@ -174,13 +174,13 @@ Ahora puedes pasar ese `oauth2_scheme` en una dependencia con `Depends`. Esta dependencia proporcionará un `str` que se asigna al parámetro `token` de la *path operation function*. -**FastAPI** sabrá que puede usar esta dependencia para definir un "security scheme" en el esquema OpenAPI (y en los docs automáticos del API). +**FastAPI** sabrá que puede usar esta dependencia para definir un "security scheme" en el esquema OpenAPI (y en la documentación automática de la API). -/// info | Detalles técnicos +/// note | Detalles técnicos **FastAPI** sabrá que puede usar la clase `OAuth2PasswordBearer` (declarada en una dependencia) para definir el esquema de seguridad en OpenAPI porque hereda de `fastapi.security.oauth2.OAuth2`, que a su vez hereda de `fastapi.security.base.SecurityBase`. -Todas las utilidades de seguridad que se integran con OpenAPI (y los docs automáticos del API) heredan de `SecurityBase`, así es como **FastAPI** puede saber cómo integrarlas en OpenAPI. +Todas las utilidades de seguridad que se integran con OpenAPI (y la documentación automática de la API) heredan de `SecurityBase`, así es como **FastAPI** puede saber cómo integrarlas en OpenAPI. /// diff --git a/docs/es/docs/tutorial/security/get-current-user.md b/docs/es/docs/tutorial/security/get-current-user.md index 67b6c5835..a47cfb0bc 100644 --- a/docs/es/docs/tutorial/security/get-current-user.md +++ b/docs/es/docs/tutorial/security/get-current-user.md @@ -4,7 +4,9 @@ En el capítulo anterior, el sistema de seguridad (que se basa en el sistema de {* ../../docs_src/security/tutorial001_an_py310.py hl[12] *} -Pero eso aún no es tan útil. Vamos a hacer que nos dé el usuario actual. +Pero eso aún no es tan útil. + +Vamos a hacer que nos dé el usuario actual. ## Crear un modelo de usuario { #create-a-user-model } @@ -12,7 +14,7 @@ Primero, vamos a crear un modelo de usuario con Pydantic. De la misma manera que usamos Pydantic para declarar cuerpos, podemos usarlo en cualquier otra parte: -{* ../../docs_src/security/tutorial002_an_py310.py hl[5,12:6] *} +{* ../../docs_src/security/tutorial002_an_py310.py hl[5,12:16] *} ## Crear una dependencia `get_current_user` { #create-a-get-current-user-dependency } @@ -50,7 +52,7 @@ Aquí **FastAPI** no se confundirá porque estás usando `Depends`. /// -/// check | Revisa +/// tip | Consejo El modo en que este sistema de dependencias está diseñado nos permite tener diferentes dependencias (diferentes "dependables") que todas devuelven un modelo `User`. @@ -66,7 +68,7 @@ Y puedes usar cualquier modelo o datos para los requisitos de seguridad (en este Pero no estás limitado a usar algún modelo de datos, clase o tipo específico. -¿Quieres tener un `id` y `email` y no tener un `username` en tu modelo? Claro. Puedes usar estas mismas herramientas. +¿Quieres tener un `id` y `email` y no tener ningún `username` en tu modelo? Claro. Puedes usar estas mismas herramientas. ¿Quieres solo tener un `str`? ¿O solo un `dict`? ¿O un instance de clase modelo de base de datos directamente? Todo funciona de la misma manera. diff --git a/docs/es/docs/tutorial/security/oauth2-jwt.md b/docs/es/docs/tutorial/security/oauth2-jwt.md index af1140d1b..5b74ffd11 100644 --- a/docs/es/docs/tutorial/security/oauth2-jwt.md +++ b/docs/es/docs/tutorial/security/oauth2-jwt.md @@ -1,5 +1,6 @@ # OAuth2 con Password (y hashing), Bearer con tokens JWT { #oauth2-with-password-and-hashing-bearer-with-jwt-tokens } + Ahora que tenemos todo el flujo de seguridad, hagamos que la aplicación sea realmente segura, usando tokens JWT y hashing de contraseñas seguras. Este código es algo que puedes usar realmente en tu aplicación, guardar los hashes de las contraseñas en tu base de datos, etc. @@ -42,7 +43,7 @@ $ pip install pyjwt -/// info | Información +/// note | Nota Si planeas usar algoritmos de firma digital como RSA o ECDSA, deberías instalar la dependencia del paquete de criptografía `pyjwt[crypto]`. @@ -213,7 +214,7 @@ Usando las credenciales: Usuario: `johndoe` Contraseña: `secret` -/// check | Revisa +/// tip | Consejo Observa que en ninguna parte del código está la contraseña en texto claro "`secret`", solo tenemos la versión con hash. diff --git a/docs/es/docs/tutorial/security/simple-oauth2.md b/docs/es/docs/tutorial/security/simple-oauth2.md index 15c7146bd..d3e2bd2cb 100644 --- a/docs/es/docs/tutorial/security/simple-oauth2.md +++ b/docs/es/docs/tutorial/security/simple-oauth2.md @@ -32,7 +32,7 @@ Normalmente se utilizan para declarar permisos de seguridad específicos, por ej * `instagram_basic` es usado por Facebook / Instagram. * `https://www.googleapis.com/auth/drive` es usado por Google. -/// info | Información +/// note | Nota En OAuth2 un "scope" es solo un string que declara un permiso específico requerido. @@ -72,7 +72,7 @@ Si necesitas imponerlo, utiliza `OAuth2PasswordRequestFormStrict` en lugar de `O * Un `client_id` opcional (no lo necesitamos para nuestro ejemplo). * Un `client_secret` opcional (no lo necesitamos para nuestro ejemplo). -/// info | Información +/// note | Nota `OAuth2PasswordRequestForm` no es una clase especial para **FastAPI** como lo es `OAuth2PasswordBearer`. @@ -94,7 +94,7 @@ No estamos usando `scopes` en este ejemplo, pero la funcionalidad está ahí si /// -Ahora, obtén los datos del usuario desde la base de datos (falsa), usando el `username` del campo del form. +Ahora, obtén los datos del usuario desde la base de datos (falsa), usando el `username` del campo del formulario. Si no existe tal usuario, devolvemos un error diciendo "Incorrect username or password". @@ -144,9 +144,9 @@ UserInDB( ) ``` -/// info | Información +/// note | Nota -Para una explicación más completa de `**user_dict` revisa en [la documentación para **Extra Models**](../extra-models.md#about-user-in-dict). +Para una explicación más completa de `**user_dict` revisa en [la documentación para **Extra Models**](../extra-models.md#about-user-in-model-dump). /// @@ -196,7 +196,7 @@ Así que, en nuestro endpoint, solo obtendremos un usuario si el usuario existe, {* ../../docs_src/security/tutorial003_an_py310.py hl[58:66,69:74,94] *} -/// info | Información +/// note | Nota El header adicional `WWW-Authenticate` con el valor `Bearer` que estamos devolviendo aquí también es parte de la especificación. diff --git a/docs/es/docs/tutorial/server-sent-events.md b/docs/es/docs/tutorial/server-sent-events.md index 0a008c0de..79716ac85 100644 --- a/docs/es/docs/tutorial/server-sent-events.md +++ b/docs/es/docs/tutorial/server-sent-events.md @@ -4,7 +4,7 @@ Puedes enviar datos en streaming al cliente usando **Server-Sent Events** (SSE). Esto es similar a [Stream JSON Lines](stream-json-lines.md), pero usa el formato `text/event-stream`, que los navegadores soportan de forma nativa con la [`EventSource` API](https://developer.mozilla.org/en-US/docs/Web/API/EventSource). -/// info | Información +/// note | Nota Añadido en FastAPI 0.135.0. diff --git a/docs/es/docs/tutorial/sql-databases.md b/docs/es/docs/tutorial/sql-databases.md index 7131716ee..3bb3209b2 100644 --- a/docs/es/docs/tutorial/sql-databases.md +++ b/docs/es/docs/tutorial/sql-databases.md @@ -65,7 +65,7 @@ Hay algunas diferencias: * `Field(primary_key=True)` le dice a SQLModel que `id` es la **clave primaria** en la base de datos SQL (puedes aprender más sobre claves primarias de SQL en la documentación de SQLModel). - Nota: Usamos `int | None` para el campo de clave primaria para que en el código Python podamos *crear un objeto sin un `id`* (`id=None`), asumiendo que la base de datos lo *generará al guardar*. SQLModel entiende que la base de datos proporcionará el `id` y *define la columna como un `INTEGER` no nulo* en el esquema de la base de datos. Consulta la [documentación de SQLModel sobre claves primarias](https://sqlmodel.tiangolo.com/tutorial/create-db-and-table/#primary-key-id) para más detalles. + **Nota:** Usamos `int | None` para el campo de clave primaria para que en el código Python podamos *crear un objeto sin un `id`* (`id=None`), asumiendo que la base de datos lo *generará al guardar*. SQLModel entiende que la base de datos proporcionará el `id` y *define la columna como un `INTEGER` no nulo* en el esquema de la base de datos. Consulta la [documentación de SQLModel sobre claves primarias](https://sqlmodel.tiangolo.com/tutorial/create-db-and-table/#primary-key-id) para más detalles. * `Field(index=True)` le dice a SQLModel que debe crear un **índice SQL** para esta columna, lo que permitirá búsquedas más rápidas en la base de datos cuando se lean datos filtrados por esta columna. @@ -181,7 +181,7 @@ Arreglaremos estas cosas añadiendo unos **modelos extra**. Aquí es donde SQLMo En **SQLModel**, cualquier clase de modelo que tenga `table=True` es un **modelo de tabla**. -Y cualquier clase de modelo que no tenga `table=True` es un **modelo de datos**, estos son en realidad solo modelos de Pydantic (con un par de características extra pequeñas). 🤓 +Y cualquier clase de modelo que no tenga `table=True` es un **modelo de datos**, estos son en realidad solo modelos de Pydantic (con un par de pequeñas funcionalidades extra). 🤓 Con SQLModel, podemos usar **herencia** para **evitar duplicar** todos los campos en todos los casos. @@ -296,7 +296,7 @@ Ahora usamos `response_model=HeroPublic` en lugar de la **anotación de tipo de Si hubiéramos declarado `-> HeroPublic`, tu editor y linter se quejarían (con razón) de que estás devolviendo un `Hero` en lugar de un `HeroPublic`. -Al declararlo en `response_model` le estamos diciendo a **FastAPI** que haga lo suyo, sin interferir con las anotaciones de tipo y la ayuda de tu editor y otras herramientas. +Al declararlo en `response_model` le estamos diciendo a **FastAPI** que haga lo suyo, sin interferir con las anotaciones de tipos y la ayuda de tu editor y otras herramientas. /// diff --git a/docs/es/docs/tutorial/static-files.md b/docs/es/docs/tutorial/static-files.md index b99ed5f9c..177be6302 100644 --- a/docs/es/docs/tutorial/static-files.md +++ b/docs/es/docs/tutorial/static-files.md @@ -2,6 +2,14 @@ Puedes servir archivos estáticos automáticamente desde un directorio utilizando `StaticFiles`. +/// tip | Consejo + +Si necesitas alojar un frontend, usa `app.frontend()` en su lugar, lee sobre ello en [Frontend](frontend.md). + +`app.frontend()` usa `StaticFiles` por debajo, con varias ventajas adicionales para frontends, como manejar el routing del lado del cliente. + +/// + ## Usa `StaticFiles` { #use-staticfiles } * Importa `StaticFiles`. diff --git a/docs/es/docs/tutorial/stream-json-lines.md b/docs/es/docs/tutorial/stream-json-lines.md index e7fe18f5e..356b4e0bf 100644 --- a/docs/es/docs/tutorial/stream-json-lines.md +++ b/docs/es/docs/tutorial/stream-json-lines.md @@ -2,7 +2,7 @@ Podrías tener una secuencia de datos que quieras enviar en un "**stream**", podrías hacerlo con **JSON Lines**. -/// info | Información +/// note | Nota Añadido en FastAPI 0.134.0. @@ -48,7 +48,7 @@ Una response tendría un tipo de contenido `application/jsonl` (en lugar de `app Es muy similar a un array JSON (equivalente de una list de Python), pero en lugar de estar envuelto en `[]` y tener `,` entre los ítems, tiene **un objeto JSON por línea**, separados por un carácter de nueva línea. -/// info | Información +/// note | Nota El punto importante es que tu app podrá producir cada línea a su turno, mientras el cliente consume las líneas anteriores. diff --git a/docs/es/docs/tutorial/testing.md b/docs/es/docs/tutorial/testing.md index a40d90c5e..9c4ff69b8 100644 --- a/docs/es/docs/tutorial/testing.md +++ b/docs/es/docs/tutorial/testing.md @@ -1,4 +1,4 @@ -# Testing { #testing } +# Pruebas { #testing } Gracias a [Starlette](https://www.starlette.dev/testclient/), escribir pruebas para aplicaciones de **FastAPI** es fácil y agradable. @@ -8,7 +8,7 @@ Con él, puedes usar [pytest](https://docs.pytest.org/) directamente con **FastA ## Usando `TestClient` { #using-testclient } -/// info | Información +/// note | Nota Para usar `TestClient`, primero instala [`httpx`](https://www.python-httpx.org). @@ -28,7 +28,7 @@ Crea funciones con un nombre que comience con `test_` (esta es la convención es Usa el objeto `TestClient` de la misma manera que con `httpx`. -Escribe declaraciones `assert` simples con las expresiones estándar de Python que necesites revisar (otra vez, estándar de `pytest`). +Escribe statements `assert` simples con las expresiones estándar de Python que necesites revisar (otra vez, estándar de `pytest`). {* ../../docs_src/app_testing/tutorial001_py310.py hl[2,12,15:18] *} @@ -90,7 +90,7 @@ Entonces podrías tener un archivo `test_main.py` con tus pruebas. Podría estar │   └── test_main.py ``` -Debido a que este archivo está en el mismo paquete, puedes usar importaciones relativas para importar el objeto `app` desde el módulo `main` (`main.py`): +Debido a que este archivo está en el mismo paquete, puedes usar imports relativos para importar el objeto `app` desde el módulo `main` (`main.py`): {* ../../docs_src/app_testing/app_a_py310/test_main.py hl[3] *} @@ -142,7 +142,7 @@ Por ejemplo: Para más información sobre cómo pasar datos al backend (usando `httpx` o el `TestClient`) revisa la [documentación de HTTPX](https://www.python-httpx.org). -/// info | Información +/// note | Nota Ten en cuenta que el `TestClient` recibe datos que pueden ser convertidos a JSON, no modelos de Pydantic. diff --git a/docs/es/docs/virtual-environments.md b/docs/es/docs/virtual-environments.md index 1679fd02b..92cb83ba2 100644 --- a/docs/es/docs/virtual-environments.md +++ b/docs/es/docs/virtual-environments.md @@ -288,8 +288,8 @@ $ echo "*" > .venv/.gitignore /// details | Qué significa ese comando -* `echo "*"`: "imprimirá" el texto `*` en el terminal (la siguiente parte cambia eso un poco) -* `>`: cualquier cosa impresa en el terminal por el comando a la izquierda de `>` no debería imprimirse, sino escribirse en el archivo que va a la derecha de `>` +* `echo "*"`: "imprimirá" el texto `*` en la terminal (la siguiente parte cambia eso un poco) +* `>`: cualquier cosa impresa en la terminal por el comando a la izquierda de `>` no debería imprimirse, sino escribirse en el archivo que va a la derecha de `>` * `.gitignore`: el nombre del archivo donde debería escribirse el texto Y `*` para Git significa "todo". Así que, ignorará todo en el directorio `.venv`. @@ -443,6 +443,8 @@ De esta manera, cuando ejecutes `python` no intentará ejecutarse desde ese ento Ahora estás listo para empezar a trabajar en tu proyecto. + + /// tip | Consejo ¿Quieres entender todo lo anterior? @@ -694,7 +696,7 @@ Eso significa que el sistema ahora comenzará a buscar primero los programas en: antes de buscar en los otros directorios. -Así que, cuando escribas `python` en el terminal, el sistema encontrará el programa Python en +Así que, cuando escribas `python` en la terminal, el sistema encontrará el programa Python en ```plaintext /home/user/code/awesome-project/.venv/bin/python @@ -718,7 +720,7 @@ C:\Users\user\code\awesome-project\.venv\Scripts antes de buscar en los otros directorios. -Así que, cuando escribas `python` en el terminal, el sistema encontrará el programa Python en +Así que, cuando escribas `python` en la terminal, el sistema encontrará el programa Python en ```plaintext C:\Users\user\code\awesome-project\.venv\Scripts\python @@ -800,7 +802,7 @@ $ cd ~/code/prisoner-of-azkaban -Si no desactivas el entorno virtual para `philosophers-stone`, cuando ejecutes `python` en el terminal, intentará usar el Python de `philosophers-stone`. +Si no desactivas el entorno virtual para `philosophers-stone`, cuando ejecutes `python` en la terminal, intentará usar el Python de `philosophers-stone`.
diff --git a/docs/fr/docs/_llm-test.md b/docs/fr/docs/_llm-test.md index 9ee61126e..02092c89d 100644 --- a/docs/fr/docs/_llm-test.md +++ b/docs/fr/docs/_llm-test.md @@ -148,7 +148,7 @@ Du texte //// tab | Info -Les onglets et les blocs « Info »/« Note »/« Warning »/etc. doivent avoir la traduction de leur titre ajoutée après une barre verticale (« | »). +Les onglets et les blocs « Info »/« Note »/« Warning »/etc. doivent avoir la traduction de leur titre ajoutée après une barre verticale (`|`). Voir les sections `### Special blocks` et `### Tab blocks` dans l’invite générale dans `scripts/translate.py`. diff --git a/docs/fr/docs/advanced/additional-responses.md b/docs/fr/docs/advanced/additional-responses.md index e7b684e36..bcf562f30 100644 --- a/docs/fr/docs/advanced/additional-responses.md +++ b/docs/fr/docs/advanced/additional-responses.md @@ -34,7 +34,7 @@ Gardez à l'esprit que vous devez renvoyer directement `JSONResponse`. /// -/// info +/// note | Remarque La clé `model` ne fait pas partie d'OpenAPI. @@ -183,7 +183,7 @@ Notez que vous devez retourner l'image en utilisant directement un `FileResponse /// -/// info +/// note | Remarque À moins que vous ne spécifiiez explicitement un type de média différent dans votre paramètre `responses`, FastAPI supposera que la réponse a le même type de média que la classe de réponse principale (par défaut `application/json`). diff --git a/docs/fr/docs/advanced/additional-status-codes.md b/docs/fr/docs/advanced/additional-status-codes.md index 59e8c3eae..5d50666f5 100644 --- a/docs/fr/docs/advanced/additional-status-codes.md +++ b/docs/fr/docs/advanced/additional-status-codes.md @@ -1,6 +1,6 @@ # Codes HTTP supplémentaires { #additional-status-codes } -Par défaut, **FastAPI** renverra les réponses à l'aide d'une structure de données `JSONResponse`, en plaçant la réponse de votre *chemin d'accès* à l'intérieur de cette `JSONResponse`. +Par défaut, **FastAPI** renverra les réponses en utilisant une `JSONResponse`, en plaçant le contenu que vous renvoyez depuis votre *chemin d'accès* à l'intérieur de cette `JSONResponse`. Il utilisera le code HTTP par défaut ou celui que vous avez défini dans votre *chemin d'accès*. diff --git a/docs/fr/docs/advanced/advanced-dependencies.md b/docs/fr/docs/advanced/advanced-dependencies.md index d5066ca25..e0003552d 100644 --- a/docs/fr/docs/advanced/advanced-dependencies.md +++ b/docs/fr/docs/advanced/advanced-dependencies.md @@ -36,7 +36,7 @@ Nous pouvons créer une instance de cette classe avec : {* ../../docs_src/dependencies/tutorial011_an_py310.py hl[18] *} -Et de cette façon, nous pouvons « paramétrer » notre dépendance, qui contient maintenant « bar », en tant qu’attribut `checker.fixed_content`. +Et de cette façon, nous pouvons « paramétrer » notre dépendance, qui contient maintenant `"bar"`, en tant qu’attribut `checker.fixed_content`. ## Utiliser l'instance comme dépendance { #use-the-instance-as-a-dependency } @@ -78,7 +78,7 @@ Les dépendances avec `yield` ont évolué au fil du temps pour couvrir différe ### Dépendances avec `yield` et `scope` { #dependencies-with-yield-and-scope } -Dans la version 0.121.0, **FastAPI** a ajouté la prise en charge de `Depends(scope="function")` pour les dépendances avec `yield`. +Dans la version 0.121.0, FastAPI a ajouté la prise en charge de `Depends(scope="function")` pour les dépendances avec `yield`. Avec `Depends(scope="function")`, le code d’arrêt après `yield` s’exécute immédiatement après la fin de la *fonction de chemin d'accès*, avant que la réponse ne soit renvoyée au client. @@ -98,7 +98,7 @@ Par exemple, si vous aviez une session de base de données dans une dépendance Ce comportement a été annulé en 0.118.0, afin que le code d’arrêt après `yield` s’exécute après l’envoi de la réponse. -/// info +/// note | Remarque Comme vous le verrez ci‑dessous, c’est très similaire au comportement avant la version 0.106.0, mais avec plusieurs améliorations et corrections de bogues pour des cas limites. diff --git a/docs/fr/docs/advanced/custom-response.md b/docs/fr/docs/advanced/custom-response.md index a1a60ebf6..8fd2e627f 100644 --- a/docs/fr/docs/advanced/custom-response.md +++ b/docs/fr/docs/advanced/custom-response.md @@ -41,7 +41,7 @@ Pour renvoyer une réponse avec du HTML directement depuis **FastAPI**, utilisez {* ../../docs_src/custom_response/tutorial002_py310.py hl[2,7] *} -/// info +/// note | Remarque Le paramètre `response_class` sera aussi utilisé pour définir le « media type » de la réponse. @@ -65,7 +65,7 @@ Une `Response` renvoyée directement par votre *fonction de chemin d'accès* ne /// -/// info +/// note | Remarque Bien sûr, l'en-tête `Content-Type` réel, le code d'état, etc., proviendront de l'objet `Response` que vous avez renvoyé. diff --git a/docs/fr/docs/advanced/dataclasses.md b/docs/fr/docs/advanced/dataclasses.md index b63a995d9..01d136910 100644 --- a/docs/fr/docs/advanced/dataclasses.md +++ b/docs/fr/docs/advanced/dataclasses.md @@ -6,7 +6,7 @@ Mais FastAPI prend aussi en charge l'utilisation de [`dataclasses`](https://docs {* ../../docs_src/dataclasses_/tutorial001_py310.py hl[1,6:11,18:19] *} -Cela fonctionne grâce à **Pydantic**, qui offre une [prise en charge interne des `dataclasses`](https://docs.pydantic.dev/latest/concepts/dataclasses/#use-of-stdlib-dataclasses-with-basemodel). +C'est toujours pris en charge grâce à **Pydantic**, qui offre une [prise en charge interne des `dataclasses`](https://docs.pydantic.dev/latest/concepts/dataclasses/#use-of-stdlib-dataclasses-with-basemodel). Ainsi, même avec le code ci‑dessus qui n'emploie pas explicitement Pydantic, FastAPI utilise Pydantic pour convertir ces dataclasses standard en la variante de dataclasses de Pydantic. @@ -18,9 +18,9 @@ Et bien sûr, cela prend en charge la même chose : Cela fonctionne de la même manière qu'avec les modèles Pydantic. Et, en réalité, c'est mis en œuvre de la même façon en interne, en utilisant Pydantic. -/// info +/// note | Remarque -Gardez à l'esprit que les dataclasses ne peuvent pas tout ce que peuvent faire les modèles Pydantic. +Gardez à l'esprit que les dataclasses ne peuvent pas faire tout ce que peuvent faire les modèles Pydantic. Vous pourriez donc avoir encore besoin d'utiliser des modèles Pydantic. diff --git a/docs/fr/docs/advanced/events.md b/docs/fr/docs/advanced/events.md index c585dd563..4ab175239 100644 --- a/docs/fr/docs/advanced/events.md +++ b/docs/fr/docs/advanced/events.md @@ -102,7 +102,7 @@ Ces fonctions peuvent être déclarées avec `async def` ou un `def` normal. ### Événement `startup` { #startup-event } -Pour ajouter une fonction qui doit être exécutée avant le démarrage de l'application, déclarez-la avec l'événement « startup » : +Pour ajouter une fonction qui doit être exécutée avant le démarrage de l'application, déclarez-la avec l'événement `"startup"` : {* ../../docs_src/events/tutorial001_py310.py hl[8] *} @@ -114,13 +114,13 @@ Et votre application ne commencera pas à recevoir des requêtes avant que tous ### Événement `shutdown` { #shutdown-event } -Pour ajouter une fonction qui doit être exécutée lorsque l'application s'arrête, déclarez-la avec l'événement « shutdown » : +Pour ajouter une fonction qui doit être exécutée lorsque l'application s'arrête, déclarez-la avec l'événement `"shutdown"` : {* ../../docs_src/events/tutorial002_py310.py hl[6] *} -Ici, la fonction gestionnaire de l'événement `shutdown` écrira une ligne de texte « Application shutdown » dans un fichier `log.txt`. +Ici, la fonction gestionnaire de l'événement `shutdown` écrira une ligne de texte `"Application shutdown"` dans un fichier `log.txt`. -/// info +/// note | Remarque Dans la fonction `open()`, le `mode="a"` signifie « append » (ajouter) ; la ligne sera donc ajoutée après ce qui se trouve déjà dans ce fichier, sans écraser le contenu précédent. @@ -152,7 +152,7 @@ Juste un détail technique pour les nerds curieux. 🤓 Sous le capot, dans la spécification technique ASGI, cela fait partie du [protocole Lifespan](https://asgi.readthedocs.io/en/latest/specs/lifespan.html), et il y définit des événements appelés `startup` et `shutdown`. -/// info +/// note | Remarque Vous pouvez en lire plus sur les gestionnaires `lifespan` de Starlette dans la [documentation « Lifespan » de Starlette](https://www.starlette.dev/lifespan/). diff --git a/docs/fr/docs/advanced/generate-clients.md b/docs/fr/docs/advanced/generate-clients.md index 69402aefe..7aa0a5150 100644 --- a/docs/fr/docs/advanced/generate-clients.md +++ b/docs/fr/docs/advanced/generate-clients.md @@ -1,4 +1,4 @@ -# Générer des SDK { #generating-sdks } +# Générer des SDKs { #generating-sdks } Parce que **FastAPI** est basé sur la spécification **OpenAPI**, ses API peuvent être décrites dans un format standard compris par de nombreux outils. @@ -20,21 +20,6 @@ FastAPI génère automatiquement des spécifications **OpenAPI 3.1**, donc tout /// -## Générateurs de SDK par les sponsors de FastAPI { #sdk-generators-from-fastapi-sponsors } - -Cette section met en avant des solutions **soutenues par des fonds** et **par des entreprises** qui sponsorisent FastAPI. Ces produits offrent **des fonctionnalités supplémentaires** et **des intégrations** en plus de SDK de haute qualité générés. - -En ✨ [**sponsorisant FastAPI**](../help-fastapi.md#sponsor-the-author) ✨, ces entreprises contribuent à garantir que le framework et son **écosystème** restent sains et **durables**. - -Leur sponsoring démontre également un fort engagement envers la **communauté** FastAPI (vous), montrant qu’elles se soucient non seulement d’offrir un **excellent service**, mais aussi de soutenir un **framework robuste et florissant**, FastAPI. 🙇 - -Par exemple, vous pourriez essayer : - -* [Stainless](https://www.stainless.com/?utm_source=fastapi&utm_medium=referral) -* [liblab](https://developers.liblab.com/tutorials/sdk-for-fastapi?utm_source=fastapi) - -Certaines de ces solutions peuvent aussi être open source ou proposer des niveaux gratuits, afin que vous puissiez les essayer sans engagement financier. D’autres générateurs de SDK commerciaux existent et peuvent être trouvés en ligne. 🤓 - ## Créer un SDK TypeScript { #create-a-typescript-sdk } Commençons par une application FastAPI simple : @@ -57,7 +42,7 @@ Ces mêmes informations issues des modèles, incluses dans OpenAPI, peuvent êtr ### Hey API { #hey-api } -Une fois que vous avez une application FastAPI avec les modèles, vous pouvez utiliser Hey API pour générer un client TypeScript. Le moyen le plus rapide de le faire est via npx. +Une fois que nous avons une application FastAPI avec les modèles, nous pouvons utiliser Hey API pour générer un client TypeScript. Le moyen le plus rapide de le faire est via npx. ```sh npx @hey-api/openapi-ts -i http://localhost:8000/openapi.json -o src/client diff --git a/docs/fr/docs/advanced/json-base64-bytes.md b/docs/fr/docs/advanced/json-base64-bytes.md index 1b5acb081..4d9bdd602 100644 --- a/docs/fr/docs/advanced/json-base64-bytes.md +++ b/docs/fr/docs/advanced/json-base64-bytes.md @@ -4,7 +4,7 @@ Si votre application doit recevoir et envoyer des données JSON, mais que vous d ## Base64 vs fichiers { #base64-vs-files } -Envisagez d'abord d'utiliser [Fichiers de requête](../tutorial/request-files.md) pour téléverser des données binaires et [Réponse personnalisée - FileResponse](./custom-response.md#fileresponse--fileresponse-) pour envoyer des données binaires, plutôt que de les encoder dans du JSON. +Envisagez d'abord d'utiliser [Fichiers de requête](../tutorial/request-files.md) pour téléverser des données binaires et [Réponse personnalisée - FileResponse](./custom-response.md#fileresponse) pour envoyer des données binaires, plutôt que de les encoder dans du JSON. JSON ne peut contenir que des chaînes encodées en UTF-8, il ne peut donc pas contenir d'octets bruts. @@ -14,7 +14,7 @@ N'utilisez base64 que si vous devez absolument inclure des données binaires dan ## Pydantic `bytes` { #pydantic-bytes } -Vous pouvez déclarer un modèle Pydantic avec des champs `bytes`, puis utiliser `val_json_bytes` dans la configuration du modèle pour lui indiquer d'utiliser base64 pour valider les données JSON en entrée ; dans le cadre de cette validation, il décodera la chaîne base64 en octets. +Vous pouvez déclarer un modèle Pydantic avec des champs `bytes`, puis utiliser `val_json_bytes` dans la configuration du modèle pour lui indiquer d'utiliser base64 pour *valider* les données JSON en entrée ; dans le cadre de cette validation, il décodera la chaîne base64 en octets. {* ../../docs_src/json_base64_bytes/tutorial001_py310.py ln[1:9,29:35] hl[9] *} @@ -52,12 +52,12 @@ Vous recevrez une réponse comme : ## Pydantic `bytes` pour les données de sortie { #pydantic-bytes-for-output-data } -Vous pouvez également utiliser des champs `bytes` avec `ser_json_bytes` dans la configuration du modèle pour les données de sortie ; Pydantic sérialisera alors les octets en base64 lors de la génération de la réponse JSON. +Vous pouvez également utiliser des champs `bytes` avec `ser_json_bytes` dans la configuration du modèle pour les données de sortie ; Pydantic *sérialisera* alors les octets en base64 lors de la génération de la réponse JSON. {* ../../docs_src/json_base64_bytes/tutorial001_py310.py ln[1:2,12:16,29,38:41] hl[16] *} ## Pydantic `bytes` pour les données d'entrée et de sortie { #pydantic-bytes-for-input-and-output-data } -Et bien sûr, vous pouvez utiliser le même modèle configuré pour utiliser base64 afin de gérer à la fois l'entrée (valider) avec `val_json_bytes` et la sortie (sérialiser) avec `ser_json_bytes` lors de la réception et de l'envoi de données JSON. +Et bien sûr, vous pouvez utiliser le même modèle configuré pour utiliser base64 afin de gérer à la fois l'entrée (*valider*) avec `val_json_bytes` et la sortie (*sérialiser*) avec `ser_json_bytes` lors de la réception et de l'envoi de données JSON. {* ../../docs_src/json_base64_bytes/tutorial001_py310.py ln[1:2,19:26,29,44:46] hl[23:26] *} diff --git a/docs/fr/docs/advanced/openapi-callbacks.md b/docs/fr/docs/advanced/openapi-callbacks.md index 369a638c8..54f8e3ff7 100644 --- a/docs/fr/docs/advanced/openapi-callbacks.md +++ b/docs/fr/docs/advanced/openapi-callbacks.md @@ -1,10 +1,10 @@ # Callbacks OpenAPI { #openapi-callbacks } -Vous pourriez créer une API avec un *chemin d'accès* qui déclenche une requête vers une *API externe* créée par quelqu'un d'autre (probablement la même personne développeuse qui utiliserait votre API). +Vous pourriez créer une API avec un *chemin d'accès* qui déclenche une requête vers une *API externe* créée par quelqu'un d'autre (probablement la même personne développeuse qui *utiliserait* votre API). -Le processus qui se produit lorsque votre application API appelle l’*API externe* s’appelle un « callback ». Parce que le logiciel écrit par la personne développeuse externe envoie une requête à votre API puis votre API « rappelle », en envoyant une requête à une *API externe* (probablement créée par la même personne développeuse). +Le processus qui se produit lorsque votre application API appelle l’*API externe* s’appelle un « callback ». Parce que le logiciel écrit par la personne développeuse externe envoie une requête à votre API puis votre API *rappelle*, en envoyant une requête à une *API externe* (probablement créée par la même personne développeuse). -Dans ce cas, vous pourriez vouloir documenter à quoi cette API externe devrait ressembler. Quel *chemin d'accès* elle devrait avoir, quel corps elle devrait attendre, quelle réponse elle devrait renvoyer, etc. +Dans ce cas, vous pourriez vouloir documenter à quoi cette API externe *devrait* ressembler. Quel *chemin d'accès* elle devrait avoir, quel corps elle devrait attendre, quelle réponse elle devrait renvoyer, etc. ## Une application avec des callbacks { #an-app-with-callbacks } @@ -47,7 +47,7 @@ Le code réel du callback dépendra fortement de votre application API. Et il variera probablement beaucoup d’une application à l’autre. -Cela pourrait être seulement une ou deux lignes de code, comme : +Cela pourrait être seulement une ou deux lignes de code, comme : ```Python callback_url = "https://example.com/api/v1/invoices/events/" @@ -96,35 +96,35 @@ Commencez par créer un nouveau `APIRouter` qui contiendra un ou plusieurs callb Pour créer le *chemin d'accès* du callback, utilisez le même `APIRouter` que vous avez créé ci-dessus. -Il devrait ressembler exactement à un *chemin d'accès* FastAPI normal : +Il devrait ressembler exactement à un *chemin d'accès* FastAPI normal : * Il devrait probablement déclarer le corps qu’il doit recevoir, par exemple `body: InvoiceEvent`. * Et il pourrait aussi déclarer la réponse qu’il doit renvoyer, par exemple `response_model=InvoiceEventReceived`. {* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[14:16,19:20,26:30] *} -Il y a 2 principales différences par rapport à un *chemin d'accès* normal : +Il y a 2 principales différences par rapport à un *chemin d'accès* normal : * Il n’a pas besoin d’avoir de code réel, car votre application n’appellera jamais ce code. Il sert uniquement à documenter l’*API externe*. La fonction peut donc simplement contenir `pass`. -* Le *chemin* peut contenir une [expression OpenAPI 3](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#key-expression) (voir plus bas) où il peut utiliser des variables avec des paramètres et des parties de la requête originale envoyée à *votre API*. +* Le *chemin* peut contenir une [expression OpenAPI 3](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#key-expression) (voir plus bas) où il peut utiliser des variables avec des paramètres et des parties de la requête originale envoyée à *votre API*. ### L’expression du chemin de callback { #the-callback-path-expression } -Le *chemin* du callback peut contenir une [expression OpenAPI 3](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#key-expression) qui peut inclure des parties de la requête originale envoyée à *votre API*. +Le *chemin* du callback peut contenir une [expression OpenAPI 3](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#key-expression) qui peut inclure des parties de la requête originale envoyée à *votre API*. -Dans ce cas, c’est la `str` : +Dans ce cas, c’est la `str` : ```Python "{$callback_url}/invoices/{$request.body.id}" ``` -Ainsi, si l’utilisateur de votre API (la personne développeuse externe) envoie une requête à *votre API* vers : +Ainsi, si l’utilisateur de votre API (la personne développeuse externe) envoie une requête à *votre API* vers : ``` https://yourapi.com/invoices/?callback_url=https://www.external.org/events ``` -avec un corps JSON : +avec un corps JSON : ```JSON { @@ -134,13 +134,13 @@ avec un corps JSON : } ``` -alors *votre API* traitera la facture et, à un moment ultérieur, enverra une requête de callback à `callback_url` (l’*API externe*) : +alors *votre API* traitera la facture et, à un moment ultérieur, enverra une requête de callback à `callback_url` (l’*API externe*) : ``` https://www.external.org/events/invoices/2expen51ve ``` -avec un corps JSON contenant quelque chose comme : +avec un corps JSON contenant quelque chose comme : ```JSON { @@ -149,7 +149,7 @@ avec un corps JSON contenant quelque chose comme : } ``` -et elle s’attendra à une réponse de cette *API externe* avec un corps JSON comme : +et elle s’attendrait à une réponse de cette *API externe* avec un corps JSON comme : ```JSON { @@ -167,13 +167,13 @@ Remarquez que l’URL de callback utilisée contient l’URL reçue en paramètr À ce stade, vous avez le(s) *chemin(s) d'accès de callback* nécessaire(s) (celui/ceux que la *personne développeuse externe* doit implémenter dans l’*API externe*) dans le routeur de callback que vous avez créé ci-dessus. -Utilisez maintenant le paramètre `callbacks` dans *le décorateur de chemin d'accès de votre API* pour passer l’attribut `.routes` (qui est en fait juste une `list` de routes/*chemins d'accès*) depuis ce routeur de callback : +Utilisez maintenant le paramètre `callbacks` dans *le décorateur de chemin d'accès de votre API* pour passer l’attribut `.routes` depuis ce routeur de callback : {* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[33] *} /// tip | Astuce -Remarquez que vous ne passez pas le routeur lui-même (`invoices_callback_router`) à `callback=`, mais l’attribut `.routes`, comme dans `invoices_callback_router.routes`. +Remarquez que vous ne passez pas le routeur lui-même (`invoices_callback_router`) à `callbacks=`, mais son attribut `.routes`, comme dans `invoices_callback_router.routes`. FastAPI utilisera ces routes pour générer la documentation OpenAPI du callback. /// @@ -181,6 +181,6 @@ Remarquez que vous ne passez pas le routeur lui-même (`invoices_callback_router Vous pouvez maintenant démarrer votre application et aller sur [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs). -Vous verrez votre documentation incluant une section « Callbacks » pour votre *chemin d'accès* qui montre à quoi l’*API externe* devrait ressembler : +Vous verrez votre documentation incluant une section « Callbacks » pour votre *chemin d'accès* qui montre à quoi l’*API externe* devrait ressembler : diff --git a/docs/fr/docs/advanced/openapi-webhooks.md b/docs/fr/docs/advanced/openapi-webhooks.md index c36c2f82b..722455063 100644 --- a/docs/fr/docs/advanced/openapi-webhooks.md +++ b/docs/fr/docs/advanced/openapi-webhooks.md @@ -16,13 +16,13 @@ Et vos utilisateurs définissent aussi, d'une manière ou d'une autre (par exemp Toute la logique de gestion des URL des webhooks et le code qui envoie effectivement ces requêtes vous incombent. Vous l'implémentez comme vous le souhaitez dans votre propre code. -## Documenter des webhooks avec FastAPI et OpenAPI { #documenting-webhooks-with-fastapi-and-openapi } +## Documenter des webhooks avec **FastAPI** et OpenAPI { #documenting-webhooks-with-fastapi-and-openapi } -Avec FastAPI, en utilisant OpenAPI, vous pouvez définir les noms de ces webhooks, les types d'opérations HTTP que votre application peut envoyer (par exemple `POST`, `PUT`, etc.) et les corps des requêtes que votre application enverra. +Avec **FastAPI**, en utilisant OpenAPI, vous pouvez définir les noms de ces webhooks, les types d'opérations HTTP que votre application peut envoyer (par exemple `POST`, `PUT`, etc.) et les **corps** des requêtes que votre application enverra. -Cela peut grandement faciliter la tâche de vos utilisateurs pour implémenter leurs API afin de recevoir vos requêtes de webhook ; ils pourront même peut-être générer automatiquement une partie de leur propre code d'API. +Cela peut grandement faciliter la tâche de vos utilisateurs pour **implémenter leurs API** afin de recevoir vos requêtes de **webhook** ; ils pourront même peut-être générer automatiquement une partie de leur propre code d'API. -/// info +/// note | Remarque Les webhooks sont disponibles dans OpenAPI 3.1.0 et versions ultérieures, pris en charge par FastAPI `0.99.0` et versions ultérieures. @@ -30,13 +30,13 @@ Les webhooks sont disponibles dans OpenAPI 3.1.0 et versions ultérieures, pris ## Créer une application avec des webhooks { #an-app-with-webhooks } -Lorsque vous créez une application FastAPI, il existe un attribut `webhooks` que vous pouvez utiliser pour définir des webhooks, de la même manière que vous définiriez des chemins d'accès, par exemple avec `@app.webhooks.post()`. +Lorsque vous créez une application **FastAPI**, il existe un attribut `webhooks` que vous pouvez utiliser pour définir des webhooks, de la même manière que vous définiriez des chemins d'accès, par exemple avec `@app.webhooks.post()`. {* ../../docs_src/openapi_webhooks/tutorial001_py310.py hl[9:12,15:20] *} -Les webhooks que vous définissez apparaîtront dans le schéma OpenAPI et dans l'interface de documentation automatique. +Les webhooks que vous définissez apparaîtront dans le schéma **OpenAPI** et dans l'**interface de documentation** automatique. -/// info +/// note | Remarque L'objet `app.webhooks` est en fait simplement un `APIRouter`, le même type que vous utiliseriez pour structurer votre application en plusieurs fichiers. @@ -50,6 +50,6 @@ C'est parce qu'on s'attend à ce que vos utilisateurs définissent, par un autre Vous pouvez maintenant démarrer votre application et aller sur [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs). -Vous verrez que votre documentation contient les chemins d'accès habituels et désormais aussi des webhooks : +Vous verrez que votre documentation contient les *chemins d'accès* habituels et désormais aussi des **webhooks** : diff --git a/docs/fr/docs/advanced/path-operation-advanced-configuration.md b/docs/fr/docs/advanced/path-operation-advanced-configuration.md index 67a5d46d4..0c56a1406 100644 --- a/docs/fr/docs/advanced/path-operation-advanced-configuration.md +++ b/docs/fr/docs/advanced/path-operation-advanced-configuration.md @@ -16,17 +16,11 @@ Vous devez vous assurer qu’il est unique pour chaque opération. ### Utiliser le nom de la fonction de chemin d’accès comme operationId { #using-the-path-operation-function-name-as-the-operationid } -Si vous souhaitez utiliser les noms de fonction de vos API comme `operationId`, vous pouvez les parcourir tous et remplacer l’`operation_id` de chaque chemin d’accès en utilisant leur `APIRoute.name`. +Si vous souhaitez utiliser les noms de fonction de vos API comme `operationId`, vous pouvez passer une fonction personnalisée `generate_unique_id_function` à `FastAPI`. -Vous devez le faire après avoir ajouté tous vos chemins d’accès. +Cette fonction reçoit chaque `APIRoute` et renvoie l’`operationId` à utiliser pour ce chemin d’accès. -{* ../../docs_src/path_operation_advanced_configuration/tutorial002_py310.py hl[2, 12:21, 24] *} - -/// tip | Astuce - -Si vous appelez manuellement `app.openapi()`, vous devez mettre à jour les `operationId` avant cela. - -/// +{* ../../docs_src/path_operation_advanced_configuration/tutorial002_py310.py hl[2,5:6,9] *} /// warning | Alertes diff --git a/docs/fr/docs/advanced/response-change-status-code.md b/docs/fr/docs/advanced/response-change-status-code.md index 222825702..317fcb03d 100644 --- a/docs/fr/docs/advanced/response-change-status-code.md +++ b/docs/fr/docs/advanced/response-change-status-code.md @@ -16,7 +16,7 @@ Pour ces cas, vous pouvez utiliser un paramètre `Response`. ## Utiliser un paramètre `Response` { #use-a-response-parameter } -Vous pouvez déclarer un paramètre de type `Response` dans votre fonction de chemin d'accès (comme vous pouvez le faire pour les cookies et les en-têtes). +Vous pouvez déclarer un paramètre de type `Response` dans votre *fonction de chemin d'accès* (comme vous pouvez le faire pour les cookies et les en-têtes). Vous pouvez ensuite définir le `status_code` dans cet objet de réponse *temporaire*. diff --git a/docs/fr/docs/advanced/response-cookies.md b/docs/fr/docs/advanced/response-cookies.md index 174c9a72d..9efa045b1 100644 --- a/docs/fr/docs/advanced/response-cookies.md +++ b/docs/fr/docs/advanced/response-cookies.md @@ -1,5 +1,6 @@ # Cookies de réponse { #response-cookies } + ## Utiliser un paramètre `Response` { #use-a-response-parameter } Vous pouvez déclarer un paramètre de type `Response` dans votre *fonction de chemin d'accès*. diff --git a/docs/fr/docs/advanced/response-directly.md b/docs/fr/docs/advanced/response-directly.md index 5ef479584..3c3827d66 100644 --- a/docs/fr/docs/advanced/response-directly.md +++ b/docs/fr/docs/advanced/response-directly.md @@ -18,7 +18,7 @@ Vous aurez normalement une bien meilleure performance en utilisant un [Modèle d Vous pouvez renvoyer une `Response` ou n'importe laquelle de ses sous-classes. -/// info +/// note | Remarque `JSONResponse` est elle-même une sous-classe de `Response`. diff --git a/docs/fr/docs/advanced/response-headers.md b/docs/fr/docs/advanced/response-headers.md index b7568b51f..e319ffefb 100644 --- a/docs/fr/docs/advanced/response-headers.md +++ b/docs/fr/docs/advanced/response-headers.md @@ -2,9 +2,9 @@ ## Utiliser un paramètre `Response` { #use-a-response-parameter } -Vous pouvez déclarer un paramètre de type `Response` dans votre fonction de chemin d'accès (comme vous pouvez le faire pour les cookies). +Vous pouvez déclarer un paramètre de type `Response` dans votre *fonction de chemin d'accès* (comme vous pouvez le faire pour les cookies). -Vous pouvez ensuite définir des en-têtes dans cet objet de réponse temporaire. +Vous pouvez ensuite définir des en-têtes dans cet objet de réponse *temporaire*. {* ../../docs_src/response_headers/tutorial002_py310.py hl[1, 7:8] *} @@ -12,7 +12,7 @@ Ensuite, vous pouvez renvoyer n'importe quel objet dont vous avez besoin, comme Et si vous avez déclaré un `response_model`, il sera toujours utilisé pour filtrer et convertir l'objet que vous avez renvoyé. -**FastAPI** utilisera cette réponse temporaire pour extraire les en-têtes (ainsi que les cookies et le code de statut), et les placera dans la réponse finale qui contient la valeur que vous avez renvoyée, filtrée par tout `response_model`. +**FastAPI** utilisera cette réponse *temporaire* pour extraire les en-têtes (ainsi que les cookies et le code de statut), et les placera dans la réponse finale qui contient la valeur que vous avez renvoyée, filtrée par tout `response_model`. Vous pouvez également déclarer le paramètre `Response` dans des dépendances, et y définir des en-têtes (et des cookies). diff --git a/docs/fr/docs/advanced/security/oauth2-scopes.md b/docs/fr/docs/advanced/security/oauth2-scopes.md index f27b95b4b..a193aeacd 100644 --- a/docs/fr/docs/advanced/security/oauth2-scopes.md +++ b/docs/fr/docs/advanced/security/oauth2-scopes.md @@ -2,11 +2,11 @@ Vous pouvez utiliser des scopes OAuth2 directement avec **FastAPI**, ils sont intégrés pour fonctionner de manière transparente. -Cela vous permettrait d’avoir un système d’autorisations plus fin, conforme au standard OAuth2, intégré à votre application OpenAPI (et à la documentation de l’API). +Cela vous permettrait d’avoir un système d’autorisations plus fin, conforme au standard OAuth2, intégré à votre application OpenAPI (et aux documents de l’API). OAuth2 avec scopes est le mécanisme utilisé par de nombreux grands fournisseurs d’authentification, comme Facebook, Google, GitHub, Microsoft, X (Twitter), etc. Ils l’utilisent pour fournir des permissions spécifiques aux utilisateurs et aux applications. -Chaque fois que vous « log in with » Facebook, Google, GitHub, Microsoft, X (Twitter), cette application utilise OAuth2 avec scopes. +Chaque fois que vous utilisez « se connecter avec » Facebook, Google, GitHub, Microsoft, X (Twitter), cette application utilise OAuth2 avec scopes. Dans cette section, vous verrez comment gérer l’authentification et l’autorisation avec le même OAuth2 avec scopes dans votre application **FastAPI**. @@ -16,7 +16,7 @@ C’est une section plus ou moins avancée. Si vous débutez, vous pouvez la pas Vous n’avez pas nécessairement besoin des scopes OAuth2, et vous pouvez gérer l’authentification et l’autorisation comme vous le souhaitez. -Mais OAuth2 avec scopes peut s’intégrer élégamment à votre API (avec OpenAPI) et à votre documentation d’API. +Mais OAuth2 avec scopes peut s’intégrer élégamment à votre API (avec OpenAPI) et à vos documents d’API. Néanmoins, c’est toujours à vous de faire appliquer ces scopes, ou toute autre exigence de sécurité/autorisation, selon vos besoins, dans votre code. @@ -34,7 +34,7 @@ Le contenu de chacune de ces chaînes peut avoir n’importe quel format, mais n Ces scopes représentent des « permissions ». -Dans OpenAPI (par ex. la documentation de l’API), vous pouvez définir des « schémas de sécurité ». +Dans OpenAPI (par ex. les documents de l’API), vous pouvez définir des « schémas de sécurité ». Lorsqu’un de ces schémas de sécurité utilise OAuth2, vous pouvez aussi déclarer et utiliser des scopes. @@ -46,7 +46,7 @@ Ils sont généralement utilisés pour déclarer des permissions de sécurité s * `instagram_basic` est utilisé par Facebook / Instagram. * `https://www.googleapis.com/auth/drive` est utilisé par Google. -/// info +/// note | Remarque Dans OAuth2, un « scope » est simplement une chaîne qui déclare une permission spécifique requise. @@ -74,7 +74,7 @@ Le paramètre `scopes` reçoit un `dict` avec chaque scope en clé et la descrip {* ../../docs_src/security/tutorial005_an_py310.py hl[63:66] *} -Comme nous déclarons maintenant ces scopes, ils apparaîtront dans la documentation de l’API lorsque vous vous authentifiez/autorisez. +Comme nous déclarons maintenant ces scopes, ils apparaîtront dans les documents de l’API lorsque vous vous authentifiez/autorisez. Et vous pourrez sélectionner à quels scopes vous souhaitez accorder l’accès : `me` et `items`. @@ -126,7 +126,7 @@ Nous le faisons ici pour montrer comment **FastAPI** gère des scopes déclarés {* ../../docs_src/security/tutorial005_an_py310.py hl[5,141,172] *} -/// info | Détails techniques +/// note | Détails techniques `Security` est en réalité une sous-classe de `Depends`, et elle n’a qu’un paramètre supplémentaire que nous verrons plus tard. @@ -235,11 +235,11 @@ Elles seront vérifiées indépendamment pour chaque *chemin d’accès*. ## Tester { #check-it } -Si vous ouvrez la documentation de l’API, vous pouvez vous authentifier et spécifier quels scopes vous voulez autoriser. +Si vous ouvrez les documents de l’API, vous pouvez vous authentifier et spécifier quels scopes vous voulez autoriser. -Si vous ne sélectionnez aucun scope, vous serez « authenticated », mais lorsque vous essayerez d’accéder à `/users/me/` ou `/users/me/items/`, vous obtiendrez une erreur indiquant que vous n’avez pas suffisamment de permissions. Vous pourrez toujours accéder à `/status/`. +Si vous ne sélectionnez aucun scope, vous serez « authentifié », mais lorsque vous essayerez d’accéder à `/users/me/` ou `/users/me/items/`, vous obtiendrez une erreur indiquant que vous n’avez pas suffisamment de permissions. Vous pourrez toujours accéder à `/status/`. Et si vous sélectionnez le scope `me` mais pas le scope `items`, vous pourrez accéder à `/users/me/` mais pas à `/users/me/items/`. diff --git a/docs/fr/docs/advanced/settings.md b/docs/fr/docs/advanced/settings.md index e6eb52a4e..722274d57 100644 --- a/docs/fr/docs/advanced/settings.md +++ b/docs/fr/docs/advanced/settings.md @@ -144,7 +144,7 @@ Pour l'instant, vous pouvez supposer que `get_settings()` est une fonction norma /// -Nous pouvons ensuite l'exiger depuis la fonction de chemin d'accès comme dépendance et l'utiliser où nous en avons besoin. +Nous pouvons ensuite l'exiger depuis la *fonction de chemin d'accès* comme dépendance et l'utiliser où nous en avons besoin. {* ../../docs_src/settings/app02_an_py310/main.py hl[17,19:21] *} diff --git a/docs/fr/docs/advanced/stream-data.md b/docs/fr/docs/advanced/stream-data.md index 3b22910a1..23884b2f0 100644 --- a/docs/fr/docs/advanced/stream-data.md +++ b/docs/fr/docs/advanced/stream-data.md @@ -2,9 +2,9 @@ Si vous voulez diffuser des données pouvant être structurées en JSON, vous devez [Diffuser des JSON Lines](../tutorial/stream-json-lines.md). -Mais si vous voulez diffuser des données binaires pures ou des chaînes, voici comment procéder. +Mais si vous voulez **diffuser des données binaires pures** ou des chaînes, voici comment procéder. -/// info +/// note | Remarque Ajouté dans FastAPI 0.134.0. @@ -14,7 +14,7 @@ Ajouté dans FastAPI 0.134.0. Vous pouvez l'utiliser si vous souhaitez diffuser des chaînes pures, par exemple directement depuis la sortie d'un service d'**IA LLM**. -Vous pouvez également l'utiliser pour diffuser de gros fichiers binaires, en envoyant chaque bloc de données au fur et à mesure de la lecture, sans tout charger en mémoire d'un coup. +Vous pouvez également l'utiliser pour diffuser de **gros fichiers binaires**, en envoyant chaque bloc de données au fur et à mesure de la lecture, sans tout charger en mémoire d'un coup. Vous pouvez aussi diffuser de la **vidéo** ou de l'**audio** de cette manière ; cela peut même être généré au fil du traitement et de l'envoi. @@ -26,7 +26,7 @@ Si vous déclarez un `response_class=StreamingResponse` dans votre *fonction de FastAPI transmettra chaque bloc de données à la `StreamingResponse` tel quel ; il n'essaiera pas de le convertir en JSON ni autre chose similaire. -### Fonctions de chemin d'accès non async { #non-async-path-operation-functions } +### *Fonctions de chemin d'accès* non async { #non-async-path-operation-functions } Vous pouvez également utiliser des fonctions `def` classiques (sans `async`), et utiliser `yield` de la même manière. @@ -40,7 +40,7 @@ Comme FastAPI n'essaiera pas de convertir les données en JSON avec Pydantic ni {* ../../docs_src/stream_data/tutorial001_py310.py ln[32:35] hl[33] *} -Cela signifie aussi qu'avec `StreamingResponse` vous avez la liberté — et la responsabilité — de produire et d'encoder les octets de données exactement comme vous avez besoin de les envoyer, indépendamment des annotations de type. 🤓 +Cela signifie aussi qu'avec `StreamingResponse` vous avez la **liberté** et la **responsabilité** de produire et d'encoder les octets de données exactement comme vous avez besoin de les envoyer, indépendamment des annotations de type. 🤓 ### Diffuser des bytes { #stream-bytes } @@ -90,7 +90,7 @@ Par exemple, ils n'ont pas de `await file.read()`, ni de `async for chunk in fil Et dans de nombreux cas, leur lecture serait une opération bloquante (pouvant bloquer la boucle d'événements), car ils sont lus depuis le disque ou le réseau. -/// info +/// note | Remarque L'exemple ci-dessus est en réalité une exception, car l'objet `io.BytesIO` est déjà en mémoire ; sa lecture ne bloquera donc rien. diff --git a/docs/fr/docs/advanced/strict-content-type.md b/docs/fr/docs/advanced/strict-content-type.md index d5c749e9d..bd4ba3b80 100644 --- a/docs/fr/docs/advanced/strict-content-type.md +++ b/docs/fr/docs/advanced/strict-content-type.md @@ -81,7 +81,7 @@ Si vous devez prendre en charge des clients qui n’envoient pas d’en-tête `C Avec ce paramètre, les requêtes sans en-tête `Content-Type` verront leur corps analysé comme JSON, ce qui correspond au comportement des anciennes versions de FastAPI. -/// info +/// note | Remarque Ce comportement et cette configuration ont été ajoutés dans FastAPI 0.132.0. diff --git a/docs/fr/docs/advanced/websockets.md b/docs/fr/docs/advanced/websockets.md index 737bbc72e..b544c6d06 100644 --- a/docs/fr/docs/advanced/websockets.md +++ b/docs/fr/docs/advanced/websockets.md @@ -111,7 +111,7 @@ Ils fonctionnent de la même manière que pour les autres endpoints/*chemins d'a {* ../../docs_src/websockets_/tutorial002_an_py310.py hl[68:69,82] *} -/// info +/// note | Remarque Comme il s'agit d'un WebSocket, il n'est pas vraiment logique de lever une `HTTPException`, nous levons plutôt une `WebSocketException`. diff --git a/docs/fr/docs/advanced/wsgi.md b/docs/fr/docs/advanced/wsgi.md index fe39729f7..6e6ce85c8 100644 --- a/docs/fr/docs/advanced/wsgi.md +++ b/docs/fr/docs/advanced/wsgi.md @@ -1,12 +1,13 @@ # Inclure WSGI - Flask, Django, autres { #including-wsgi-flask-django-others } + Vous pouvez monter des applications WSGI comme vous l'avez vu avec [Sous-applications - Montages](sub-applications.md), [Derrière un proxy](behind-a-proxy.md). Pour cela, vous pouvez utiliser `WSGIMiddleware` et l'utiliser pour envelopper votre application WSGI, par exemple Flask, Django, etc. ## Utiliser `WSGIMiddleware` { #using-wsgimiddleware } -/// info +/// note | Remarque Cela nécessite l'installation de `a2wsgi`, par exemple avec `pip install a2wsgi`. diff --git a/docs/fr/docs/alternatives.md b/docs/fr/docs/alternatives.md index b56d10481..91a81e2dc 100644 --- a/docs/fr/docs/alternatives.md +++ b/docs/fr/docs/alternatives.md @@ -39,19 +39,19 @@ premières idées qui a inspiré « la recherche de » **FastAPI**. /// note | Remarque -Django REST Framework a été créé par Tom Christie. Le créateur de Starlette et Uvicorn, sur lesquels **FastAPI** est basé. +Django REST Framework a été créé par Tom Christie. Le même créateur de Starlette et Uvicorn, sur lesquels **FastAPI** est basé. /// /// tip | A inspiré **FastAPI** à -Avoir une interface de documentation automatique de l'API. +Avoir une interface utilisateur web de documentation automatique de l'API. /// ### [Flask](https://flask.palletsprojects.com) { #flask } -Flask est un « micro‑framework », il ne comprend pas d'intégrations de bases de données ni beaucoup de choses qui sont fournies par défaut dans Django. +Flask est un « microframework », il ne comprend pas d'intégrations de bases de données ni beaucoup de choses qui sont fournies par défaut dans Django. Cette simplicité et cette flexibilité permettent d'utiliser des bases de données NoSQL comme principal système de stockage de données. @@ -60,22 +60,22 @@ technique par moments. Il est aussi couramment utilisé pour d'autres applications qui n'ont pas nécessairement besoin d'une base de données, de gestion des utilisateurs ou de l'une des nombreuses fonctionnalités préinstallées dans Django. Bien que beaucoup de ces fonctionnalités puissent être ajoutées avec des plug-ins. -Ce découplage des parties, et le fait d'être un « micro‑framework » qui puisse être étendu pour couvrir exactement ce +Ce découplage des parties, et le fait d'être un « microframework » qui puisse être étendu pour couvrir exactement ce qui est nécessaire, était une caractéristique clé que je voulais conserver. Compte tenu de la simplicité de Flask, il semblait bien adapté à la création d'API. La prochaine chose à trouver était un « Django REST Framework » pour Flask. /// tip | A inspiré **FastAPI** à -Être un micro‑framework. Il est donc facile de combiner les outils et les pièces nécessaires. +Être un micro-framework. Il est donc facile de combiner les outils et les pièces nécessaires. -Proposer un système de routage simple et facile à utiliser. +Proposer un système de routing simple et facile à utiliser. /// ### [Requests](https://requests.readthedocs.io) { #requests } -**FastAPI** n'est pas réellement une alternative à **Requests**. Leur cadre est très différent. +**FastAPI** n'est pas réellement une alternative à **Requests**. Leur portée est très différente. Il serait en fait plus courant d'utiliser Requests _à l'intérieur_ d'une application FastAPI. @@ -85,7 +85,7 @@ Mais quand même, FastAPI s'est inspiré de Requests. Ils sont, plus ou moins, aux extrémités opposées, se complétant l'un l'autre. -Requests a un design très simple et intuitif, il est très facile à utiliser, avec des valeurs par défaut raisonnables, tout en étant très puissant et personnalisable. +Requests a un design très simple et intuitif, il est très facile à utiliser, avec des valeurs par défaut raisonnables. Mais en même temps, il est très puissant et personnalisable. C'est pourquoi, comme le dit le site officiel : @@ -97,7 +97,7 @@ La façon dont vous l'utilisez est très simple. Par exemple, pour faire une req response = requests.get("http://example.com/some/url") ``` -L’opération de chemin d'accès correspondante dans **FastAPI** pourrait ressembler à ceci : +Le *chemin d'accès* d'API correspondant dans **FastAPI** pourrait ressembler à ceci : ```Python hl_lines="1" @app.get("/some/url") @@ -117,7 +117,7 @@ Notez les similitudes entre `requests.get(...)` et `@app.get(...)`. ### [Swagger](https://swagger.io/) / [OpenAPI](https://github.com/OAI/OpenAPI-Specification/) { #swagger-openapi } -La principale fonctionnalité que j'ai emprunté à Django REST Framework était la documentation automatique des API. +La principale fonctionnalité que j'ai empruntée à Django REST Framework était la documentation automatique des API. Puis j'ai découvert qu'il existait une norme pour documenter les API, en utilisant JSON (ou YAML, une extension de JSON) appelée Swagger. @@ -132,12 +132,12 @@ C'est pourquoi, lorsqu'on parle de la version 2.0, il est courant de dire « Swa Adopter et utiliser une norme ouverte pour les spécifications des API, au lieu d'un schéma personnalisé. -Intégrer des outils d'interface utilisateur basés sur des normes : +Et intégrer des outils d'interface utilisateur basés sur des normes : * [Swagger UI](https://github.com/swagger-api/swagger-ui) * [ReDoc](https://github.com/Rebilly/ReDoc) -Ces deux-là ont été choisis parce qu'ils sont populaires et stables, mais en faisant une recherche rapide, vous pourriez trouver des dizaines d'alternatives supplémentaires pour OpenAPI (que vous pouvez utiliser avec **FastAPI**). +Ces deux-là ont été choisis parce qu'ils sont populaires et stables, mais en faisant une recherche rapide, vous pourriez trouver des dizaines d'interfaces utilisateur alternatives pour OpenAPI (que vous pouvez utiliser avec **FastAPI**). /// @@ -149,14 +149,13 @@ permanents qui les rendent inadaptés. ### [Marshmallow](https://marshmallow.readthedocs.io/en/stable/) { #marshmallow } -L'une des principales fonctionnalités nécessaires aux systèmes API est la « sérialisation » des données, qui consiste à prendre les données du code (Python) et à +L'une des principales fonctionnalités nécessaires aux systèmes API est la « sérialisation » des données, qui consiste à prendre les données du code (Python) et à les convertir en quelque chose qui peut être envoyé sur le réseau. Par exemple, convertir un objet contenant des données provenant d'une base de données en un objet JSON. Convertir des objets `datetime` en strings, etc. La validation des données est une autre fonctionnalité importante dont ont besoin les API. Elle permet de s'assurer que les données sont valides, compte tenu de certains paramètres. Par exemple, qu'un champ est un `int`, et non un -string. -Ceci est particulièrement utile pour les données entrantes. +string. Ceci est particulièrement utile pour les données entrantes. Sans un système de validation des données, vous devriez effectuer toutes les vérifications à la main, dans le code. @@ -182,7 +181,7 @@ C'est un outil formidable et je l'ai beaucoup utilisé aussi, avant d'avoir **Fa /// note | Remarque -Webargs a été créé par les développeurs de Marshmallow. +Webargs a été créé par les mêmes développeurs de Marshmallow. /// @@ -206,13 +205,13 @@ Et il génère des schémas OpenAPI. C'est ainsi que cela fonctionne dans Flask, Starlette, Responder, etc. -Mais alors, nous avons à nouveau le problème d'avoir une micro-syntaxe, dans une docstring Python (un gros morceau de YAML). +Mais alors, nous avons à nouveau le problème d'avoir une micro-syntaxe, dans une string Python (un gros morceau de YAML). L'éditeur ne peut guère aider en la matière. Et si nous modifions les paramètres ou les schémas Marshmallow et que nous oublions de modifier également cette docstring YAML, le schéma généré deviendrait obsolète. /// note | Remarque -APISpec a été créé par les développeurs de Marshmallow. +APISpec a été créé par les mêmes développeurs de Marshmallow. /// @@ -241,11 +240,11 @@ j'ai (ainsi que plusieurs équipes externes) utilisées jusqu'à présent : * [https://github.com/tiangolo/full-stack-flask-couchbase](https://github.com/tiangolo/full-stack-flask-couchbase) * [https://github.com/tiangolo/full-stack-flask-couchdb](https://github.com/tiangolo/full-stack-flask-couchdb) -Ces mêmes générateurs full-stack ont servi de base aux [Générateurs de projets pour **FastAPI**](project-generation.md). +Et ces mêmes générateurs full-stack ont servi de base aux [Générateurs de projets **FastAPI**](project-generation.md). /// note | Remarque -Flask-apispec a été créé par les développeurs de Marshmallow. +Flask-apispec a été créé par les mêmes développeurs de Marshmallow. /// @@ -284,9 +283,9 @@ C'était l'un des premiers frameworks Python extrêmement rapides basés sur `as /// note | Détails techniques -Il utilisait [`uvloop`](https://github.com/MagicStack/uvloop) au lieu du système par défaut de Python `asyncio`. C'est ce qui l'a rendu si rapide. +Il utilisait [`uvloop`](https://github.com/MagicStack/uvloop) au lieu de la boucle par défaut de Python `asyncio`. C'est ce qui l'a rendu si rapide. -Il a clairement inspiré Uvicorn et Starlette, qui sont actuellement plus rapides que Sanic dans les benchmarks. +Il a clairement inspiré Uvicorn et Starlette, qui sont actuellement plus rapides que Sanic dans les benchmarks ouverts. /// @@ -304,7 +303,7 @@ Falcon est un autre framework Python haute performance, il est conçu pour être Il est conçu pour avoir des fonctions qui reçoivent deux paramètres, une « requête » et une « réponse ». Ensuite, vous « lisez » des parties de la requête et « écrivez » des parties dans la réponse. En raison de cette conception, il n'est -pas possible de déclarer des paramètres de requête et des corps avec des indications de type Python standard comme paramètres de fonction. +pas possible de déclarer des paramètres de requête et des corps avec des annotations de type Python standard comme paramètres de fonction. Ainsi, la validation, la sérialisation et la documentation des données doivent être effectuées dans le code, et non pas automatiquement. Ou bien elles doivent être implémentées comme un framework au-dessus de Falcon, comme Hug. Cette même distinction se retrouve dans d'autres frameworks qui s'inspirent de la conception de Falcon, qui consiste à avoir un objet de requête et un objet de réponse comme paramètres. @@ -326,7 +325,7 @@ J'ai découvert Molten lors des premières étapes de développement de **FastAP * Validation et documentation via ces types. * Système d'injection de dépendances. -Il n'utilise pas une librairie tiers de validation, sérialisation et de documentation tel que Pydantic, il utilise son propre système. Ainsi, ces définitions de types de données ne sont pas réutilisables aussi facilement. +Il n'utilise pas une librairie tierce de validation, sérialisation et de documentation telle que Pydantic, il utilise son propre système. Ainsi, ces définitions de types de données ne sont pas réutilisables aussi facilement. Il nécessite une configuration un peu plus verbeuse. Et comme il est basé sur WSGI (au lieu d'ASGI), il n'est pas conçu pour profiter des hautes performances fournies par des outils comme Uvicorn, Starlette et Sanic. @@ -363,7 +362,7 @@ Comme il est basé sur l'ancienne norme pour les frameworks web Python synchrone /// note | Remarque -Hug a été créé par Timothy Crosley, le créateur de [`isort`](https://github.com/timothycrosley/isort), un excellent outil pour trier automatiquement les imports dans les fichiers Python. +Hug a été créé par Timothy Crosley, le même créateur de [`isort`](https://github.com/timothycrosley/isort), un excellent outil pour trier automatiquement les imports dans les fichiers Python. /// @@ -388,11 +387,11 @@ et les requêtes que j'ai vues (avant NestJS et Molten). Je l'ai trouvé plus ou Il disposait de la validation automatique, sérialisation des données et d'une génération de schéma OpenAPI basée sur les mêmes annotations de type à plusieurs endroits. -La définition du schéma de corps de requête n'utilisait pas les mêmes annotations de type Python que Pydantic, il était un peu plus proche de Marshmallow, donc le support de l'éditeur n'était pas aussi bon, mais APIStar était quand même la meilleure option disponible. +Les définitions de schéma de corps n'utilisaient pas les mêmes annotations de type Python que Pydantic, c'était un peu plus proche de Marshmallow, donc le support de l'éditeur n'était pas aussi bon, mais APIStar était quand même la meilleure option disponible. Il avait les meilleures performances d'après les benchmarks de l'époque (seulement surpassé par Starlette). -Au départ, il ne disposait pas d'une interface web de documentation automatique de l'API, mais je savais que je pouvais lui ajouter une interface Swagger. +Au départ, il ne disposait pas d'une interface utilisateur web de documentation automatique de l'API, mais je savais que je pouvais lui ajouter Swagger UI. Il avait un système d'injection de dépendances. Il nécessitait un pré-enregistrement des composants, comme d'autres outils discutés ci-dessus. Mais c'était quand même une excellente fonctionnalité. @@ -422,7 +421,7 @@ L'idée de déclarer plusieurs choses (validation des données, sérialisation e Et après avoir longtemps cherché un framework similaire et testé de nombreuses alternatives, APIStar était la meilleure option disponible. -Puis APIStar a cessé d'exister en tant que serveur et Starlette a été créé, et a constitué une meilleure base pour un tel système. Ce fut l'inspiration finale pour construire **FastAPI**. +Puis APIStar a cessé d'exister en tant que serveur et Starlette a été créé, et a constitué une nouvelle base meilleure pour un tel système. Ce fut l'inspiration finale pour construire **FastAPI**. Je considère **FastAPI** comme un « successeur spirituel » d'APIStar, tout en améliorant et en augmentant les fonctionnalités, le système de typage et d'autres parties, sur la base des enseignements tirés de tous ces outils précédents. @@ -441,7 +440,7 @@ basé sur les mêmes annotations de type Python, le support de l'éditeur est gr /// tip | **FastAPI** l'utilise pour -Gérer toute la validation des données, leur sérialisation et la documentation automatique du modèle (basée sur le schéma JSON). +Gérer toute la validation des données, leur sérialisation et la documentation automatique du modèle (basée sur JSON Schema). **FastAPI** prend ensuite ces données JSON Schema et les place dans OpenAPI, en plus de toutes les autres choses qu'il fait. @@ -455,20 +454,20 @@ Il est très simple et intuitif. Il est conçu pour être facilement extensible Il offre : -- Des performances vraiment impressionnantes. -- Le support des WebSockets. -- Les tâches d'arrière-plan. -- Les événements de démarrage et d'arrêt. -- Un client de test basé sur HTTPX. -- CORS, GZip, fichiers statiques, streaming des réponses. -- Le support des sessions et des cookies. -- Une couverture de test à 100 %. -- 100 % de la base de code avec des annotations de type. -- Peu de dépendances strictes. +* Des performances vraiment impressionnantes. +* Le support de WebSocket. +* Les tâches d'arrière-plan in-process. +* Les événements de démarrage et d'arrêt. +* Un client de test basé sur HTTPX. +* CORS, GZip, fichiers statiques, streaming des réponses. +* Le support des sessions et des cookies. +* Une couverture de test à 100 %. +* 100 % de la base de code avec des annotations de type. +* Peu de dépendances strictes. Starlette est actuellement le framework Python le plus rapide testé. Seulement dépassé par Uvicorn, qui n'est pas un framework, mais un serveur. -Starlette fournit toutes les fonctionnalités de base d'un micro‑framework web. +Starlette fournit toutes les fonctionnalités de base d'un microframework web. Mais il ne fournit pas de validation automatique des données, de sérialisation ou de documentation. @@ -496,7 +495,7 @@ Ainsi, tout ce que vous pouvez faire avec Starlette, vous pouvez le faire direct Uvicorn est un serveur ASGI rapide comme l'éclair, basé sur uvloop et httptools. -Il ne s'agit pas d'un framework web, mais d'un serveur. Par exemple, il ne fournit pas d'outils pour le routing. C'est +Il ne s'agit pas d'un framework web, mais d'un serveur. Par exemple, il ne fournit pas d'outils pour le routing par chemins. C'est quelque chose qu'un framework comme Starlette (ou **FastAPI**) fournirait par-dessus. C'est le serveur recommandé pour Starlette et **FastAPI**. diff --git a/docs/fr/docs/async.md b/docs/fr/docs/async.md index b3fc9169a..ccd176072 100644 --- a/docs/fr/docs/async.md +++ b/docs/fr/docs/async.md @@ -44,19 +44,19 @@ Si votre application (d'une certaine manière) n'a pas à communiquer avec une a --- -Si vous ne savez pas, utilisez seulement `def`. +Si vous ne savez pas, utilisez un `def` normal. --- -Note : vous pouvez mélanger `def` et `async def` dans vos *fonctions de chemin d'accès* autant que nécessaire, et définir chacune avec l’option la plus adaptée pour vous. FastAPI fera ce qu'il faut avec elles. +**Remarque** : vous pouvez mélanger `def` et `async def` dans vos *fonctions de chemin d'accès* autant que nécessaire, et définir chacune avec l’option la plus adaptée pour vous. FastAPI fera ce qu'il faut avec elles. Au final, peu importe le cas parmi ceux ci-dessus, FastAPI fonctionnera de manière asynchrone et sera extrêmement rapide. -Mais si vous suivez bien les instructions ci-dessus, il pourra effectuer quelques optimisations et ainsi améliorer les performances. +Mais si vous suivez bien les étapes ci-dessus, il pourra effectuer quelques optimisations de performance. ## Détails techniques { #technical-details } -Les versions modernes de Python supportent le **code asynchrone** grâce aux **« coroutines »** avec les syntaxes **`async` et `await`**. +Les versions modernes de Python supportent le **« code asynchrone »** en utilisant quelque chose appelé **« coroutines »**, avec la syntaxe **`async` et `await`**. Analysons les différentes parties de cette phrase dans les sections suivantes : @@ -70,7 +70,7 @@ Faire du code asynchrone signifie que le langage 💬 est capable de dire à l'o Donc, pendant ce temps, l'ordinateur pourra effectuer d'autres tâches, pendant que « slow-file » 📝 se termine. -Ensuite l'ordinateur / le programme 🤖 reviendra à chaque fois qu'il en a la chance que ce soit parce qu'il attend à nouveau, ou car il 🤖 a fini tout le travail qu'il avait à faire. Il 🤖 regardera donc si les tâches qu'il attend ont terminé d'être effectuées. +Ensuite l'ordinateur / le programme 🤖 reviendra à chaque fois qu'il en a la chance, parce qu'il attend à nouveau, ou quand il 🤖 a fini tout le travail qu'il avait à faire à ce moment-là. Et il 🤖 regardera si des tâches qu'il attendait ont déjà terminé, en faisant ce qu'il devait faire. Ensuite, il 🤖 prendra la première tâche à finir (disons, notre « slow-file » 📝) et continuera à faire avec cette dernière ce qu'il était censé. @@ -80,18 +80,18 @@ Ce « attendre quelque chose d'autre » fait généralement référence à des o * de la donnée envoyée depuis votre programme soit reçue par le client à travers le réseau * le contenu d'un fichier sur le disque soit lu par le système et passé à votre programme * le contenu que votre programme a passé au système soit écrit sur le disque -* une opération effectuée à distance par une API se termine +* une opération effectuée à distance par une API * une opération en base de données se termine * une requête à une base de données renvoie un résultat * etc. Le temps d'exécution étant consommé majoritairement par l'attente d'opérations I/O, on appelle ceci des opérations « I/O bound ». -Ce concept se nomme « asynchrone » car l'ordinateur / le programme n'a pas besoin d'être « synchronisé » avec la tâche, attendant le moment exact où cette dernière se terminera en ne faisant rien, pour être capable de récupérer le résultat de la tâche et l'utiliser dans la suite des opérations. +Ce concept se nomme « asynchrone » car l'ordinateur / le programme n'a pas besoin d'être « synchronisé » avec la tâche lente, attendant le moment exact où cette dernière se terminera en ne faisant rien, pour être capable de récupérer le résultat de la tâche et l'utiliser dans la suite des opérations. -À la place, en étant « asynchrone », une fois terminée, une tâche peut légèrement attendre (quelques microsecondes) que l'ordinateur / le programme finisse ce qu'il était en train de faire, et revienne récupérer le résultat. +À la place, en étant un système « asynchrone », une fois terminée, la tâche peut attendre un peu dans la file (quelques microsecondes) que l'ordinateur / le programme finisse ce qu'il était en train de faire, puis revienne récupérer les résultats et continue à travailler avec eux. -Pour parler de tâches « synchrones » (en opposition à « asynchrones »), on utilise souvent le terme « séquentiel », car l'ordinateur / le programme va effectuer toutes les étapes d'une tâche séquentiellement avant de passer à une autre tâche, même si ces étapes impliquent de l'attente. +Pour parler de tâches « synchrones » (en opposition à « asynchrones »), on utilise souvent aussi le terme « séquentiel », car l'ordinateur / le programme va effectuer toutes les étapes d'une tâche séquentiellement avant de passer à une autre tâche, même si ces étapes impliquent de l'attente. ### Concurrence et Burgers { #concurrency-and-burgers } @@ -99,49 +99,49 @@ L'idée de code **asynchrone** décrite ci-dessus est parfois aussi appelée ** La **concurrence** et le **parallélisme** sont tous deux liés à l'idée de « différentes choses arrivant plus ou moins au même moment ». -Mais les détails entre la **concurrence** et le **parallélisme** diffèrent sur de nombreux points. +Mais les détails entre la *concurrence* et le *parallélisme* sont assez différents. -Pour expliquer la différence, voici une histoire de burgers : +Pour expliquer la différence, imaginez l'histoire suivante à propos de burgers : ### Burgers concurrents { #concurrent-burgers } -Vous amenez votre crush 😍 dans votre fast food 🍔 favori, et faites la queue pendant que le serveur 💁 prend les commandes des personnes devant vous. +Vous allez avec votre crush chercher de la nourriture dans un fast food, vous faites la queue pendant que le caissier prend les commandes des personnes devant vous. 😍 -Puis vient votre tour, vous commandez alors 2 magnifiques burgers 🍔 pour votre crush 😍 et vous. +Puis vient votre tour, vous commandez alors 2 burgers très sophistiqués pour votre crush et vous. 🍔🍔 -Le serveur 💁 dit quelque chose à son collègue dans la cuisine 👨‍🍳 pour qu'il sache qu'il doit préparer vos burgers 🍔 (bien qu'il soit déjà en train de préparer ceux des clients précédents). +Le caissier dit quelque chose au cuisinier dans la cuisine pour qu'il sache qu'il doit préparer vos burgers (bien qu'il soit déjà en train de préparer ceux des clients précédents). -Vous payez 💸. +Vous payez. 💸 -Le serveur 💁 vous donne le numéro assigné à votre commande. +Le caissier vous donne le numéro de votre tour. -Pendant que vous attendez, vous allez choisir une table avec votre crush 😍, vous discutez avec votre crush 😍 pendant un long moment (les burgers étant « magnifiques » ils sont très longs à préparer ✨🍔✨). +Pendant que vous attendez, vous allez choisir une table avec votre crush, vous vous asseyez et discutez avec votre crush pendant un long moment (vos burgers étant très sophistiqués, ils prennent du temps à préparer). -Pendant que vous êtes assis à table, en attendant que les burgers 🍔 soient prêts, vous pouvez passer ce temps à admirer à quel point votre crush 😍 est géniale, mignonne et intelligente ✨😍✨. +Pendant que vous êtes assis à table avec votre crush, en attendant les burgers, vous pouvez passer ce temps à admirer à quel point votre crush est géniale, mignonne et intelligente ✨😍✨. -Pendant que vous discutez avec votre crush 😍, de temps en temps vous jetez un coup d’œil au nombre affiché au-dessus du comptoir pour savoir si c'est à votre tour d'être servis. +Pendant que vous attendez et discutez avec votre crush, de temps en temps, vous jetez un coup d’œil au nombre affiché au-dessus du comptoir pour savoir si c'est déjà votre tour. -Jusqu'au moment où c'est (enfin) votre tour. Vous allez au comptoir, récupérez vos burgers 🍔 et revenez à votre table. +Puis, à un moment, c'est enfin votre tour. Vous allez au comptoir, récupérez vos burgers et revenez à votre table. -Vous et votre crush 😍 mangez les burgers 🍔 et passez un bon moment ✨. +Vous et votre crush mangez les burgers et passez un bon moment. ✨ /// note | Remarque -Illustrations proposées par [Ketrina Thompson](https://www.instagram.com/ketrinadrawsalot). 🎨 +Belles illustrations par [Ketrina Thompson](https://www.instagram.com/ketrinadrawsalot). 🎨 /// @@ -149,103 +149,103 @@ Illustrations proposées par [Ketrina Thompson](https://www.instagram.com/ketrin Imaginez que vous êtes l'ordinateur / le programme 🤖 dans cette histoire. -Pendant que vous faites la queue, vous être simplement inactif 😴, attendant votre tour, ne faisant rien de « productif ». Mais la queue est rapide car le serveur 💁 prend seulement les commandes (et ne les prépare pas), donc tout va bien. +Pendant que vous faites la queue, vous êtes simplement inactif 😴, attendant votre tour, ne faisant rien de très « productif ». Mais la queue est rapide car le caissier prend seulement les commandes (et ne les prépare pas), donc tout va bien. -Ensuite, quand c'est votre tour, vous faites des actions « productives » 🤓, vous étudiez le menu, décidez ce que vous voulez, demandez à votre crush 😍 son choix, payez 💸, vérifiez que vous utilisez la bonne carte de crédit, vérifiez que le montant débité sur la carte est correct, vérifiez que la commande contient les bons produits, etc. +Ensuite, quand c'est votre tour, vous faites du vrai travail « productif », vous étudiez le menu, décidez ce que vous voulez, demandez à votre crush son choix, payez, vérifiez que vous donnez le bon billet ou la bonne carte, vérifiez que le montant débité est correct, vérifiez que la commande contient les bons produits, etc. -Mais ensuite, même si vous n'avez pas encore vos burgers 🍔, votre travail avec le serveur 💁 est « en pause » ⏸, car vous devez attendre 🕙 que vos burgers soient prêts. +Mais ensuite, même si vous n'avez toujours pas vos burgers, votre travail avec le caissier est « en pause » ⏸, car vous devez attendre 🕙 que vos burgers soient prêts. -Après vous être écarté du comptoir et vous être assis à votre table avec le numéro de votre commande, vous pouvez tourner 🔀 votre attention vers votre crush 😍, et « travailler » ⏯ 🤓 là-dessus. Vous êtes donc à nouveau en train de faire quelque chose de « productif » 🤓, vous flirtez avec votre crush 😍. +Mais lorsque vous vous écartez du comptoir et vous asseyez à table avec un numéro pour votre tour, vous pouvez tourner 🔀 votre attention vers votre crush, et « travailler » ⏯ 🤓 là-dessus. Vous êtes donc à nouveau en train de faire quelque chose de très « productif », comme flirter avec votre crush 😍. -Puis le serveur 💁 dit « J'ai fini de préparer les burgers » 🍔 en mettant votre numéro sur l'affichage du comptoir, mais vous ne courez pas immédiatement au moment où votre numéro s'affiche. Vous savez que personne ne volera vos burgers 🍔 car vous avez votre numéro et les autres clients ont le leur. +Puis le caissier 💁 dit « J'ai fini de faire les burgers » en mettant votre numéro sur l'affichage du comptoir, mais vous ne sautez pas comme un fou immédiatement quand le numéro affiché change pour devenir votre numéro. Vous savez que personne ne volera vos burgers car vous avez le numéro de votre tour, et les autres ont le leur. -Vous attendez donc que votre crush 😍 finisse son histoire, souriez gentiment et dites que vous allez chercher les burgers ⏸. +Vous attendez donc que votre crush finisse son histoire (termine le travail actuel ⏯ / la tâche en cours de traitement 🤓), souriez gentiment et dites que vous allez chercher les burgers ⏸. -Pour finir vous allez au comptoir 🔀, vers la tâche initiale qui est désormais terminée ⏯, récupérez les burgers 🍔, remerciez le serveur et ramenez les burgers 🍔 à votre table. Ceci termine l'étape / la tâche d'interaction avec le comptoir ⏹. Ce qui ensuite, crée une nouvelle tâche de « manger les burgers » 🔀 ⏯, mais la précédente, « récupérer les burgers » est terminée ⏹. +Puis vous allez au comptoir 🔀, vers la tâche initiale qui est désormais terminée ⏯, récupérez les burgers, remerciez et ramenez les burgers à votre table. Ceci termine l'étape / la tâche d'interaction avec le comptoir ⏹. Ce qui ensuite crée une nouvelle tâche, « manger les burgers » 🔀 ⏯, mais la précédente, « récupérer les burgers », est terminée ⏹. ### Burgers parallèles { #parallel-burgers } -Imaginons désormais que ce ne sont pas des « burgers concurrents » mais des « burgers parallèles ». +Imaginons désormais que ce ne sont pas des « Burgers concurrents » mais des « Burgers parallèles ». -Vous allez avec votre crush 😍 dans un fast food 🍔 parallélisé. +Vous allez avec votre crush chercher de la nourriture dans un fast food parallèle. -Vous attendez pendant que plusieurs (disons 8) serveurs qui sont aussi des cuisiniers 👨‍🍳👨‍🍳👨‍🍳👨‍🍳👨‍🍳👨‍🍳👨‍🍳👨‍🍳 prennent les commandes des personnes devant vous. +Vous attendez pendant que plusieurs (disons 8) caissiers qui sont en même temps cuisiniers prennent les commandes des personnes devant vous. -Chaque personne devant vous attend 🕙 que son burger 🍔 soit prêt avant de quitter le comptoir car chacun des 8 serveurs va lui-même préparer le burger directement avant de prendre la commande suivante. +Chaque personne devant vous attend que son burger soit prêt avant de quitter le comptoir car chacun des 8 caissiers va préparer le burger directement avant de prendre la commande suivante. -Puis c'est enfin votre tour, vous commandez 2 magnifiques burgers 🍔 pour vous et votre crush 😍. +Puis c'est enfin votre tour, vous commandez 2 burgers très sophistiqués pour vous et votre crush. Vous payez 💸. -Le serveur va dans la cuisine 👨‍🍳. +Le caissier va dans la cuisine. -Vous attendez devant le comptoir afin que personne ne prenne vos burgers 🍔 avant vous, vu qu'il n'y a pas de numéro de commande. +Vous attendez, debout devant le comptoir 🕙, afin que personne d'autre ne prenne vos burgers avant vous, vu qu'il n'y a pas de numéros pour les tours. -Vous et votre crush 😍 étant occupés à vérifier que personne ne passe devant vous prendre vos burgers au moment où ils arriveront 🕙, vous ne pouvez pas vous préoccuper de votre crush 😞. +Vous et votre crush étant occupés à ne laisser personne passer devant vous et prendre vos burgers au moment où ils arriveront, vous ne pouvez pas prêter attention à votre crush. 😞 -C'est du travail « synchrone », vous être « synchronisés » avec le serveur/cuisinier 👨‍🍳. Vous devez attendre 🕙 et être présent au moment exact où le serveur/cuisinier 👨‍🍳 finira les burgers 🍔 et vous les donnera, sinon quelqu'un risque de vous les prendre. +C'est du travail « synchrone », vous être « synchronisés » avec le caissier/cuisinier 👨‍🍳. Vous devez attendre 🕙 et être présent au moment exact où le caissier/cuisinier 👨‍🍳 finira les burgers et vous les donnera, sinon quelqu'un d'autre risque de vous les prendre. -Puis le serveur/cuisinier 👨‍🍳 revient enfin avec vos burgers 🍔, après un long moment d'attente 🕙 devant le comptoir. +Puis votre caissier/cuisinier 👨‍🍳 revient enfin avec vos burgers, après un long moment d'attente 🕙 devant le comptoir. -Vous prenez vos burgers 🍔 et allez à une table avec votre crush 😍 +Vous prenez vos burgers et allez à une table avec votre crush. -Vous les mangez, et vous avez terminé 🍔 ⏹. +Vous les mangez simplement, et vous avez terminé. ⏹ -Durant tout ce processus, il n'y a presque pas eu de discussions ou de flirts car la plupart de votre temps à été passé à attendre 🕙 devant le comptoir 😞. +Il n'y a pas eu beaucoup de discussions ou de flirts car la plupart du temps a été passé à attendre 🕙 devant le comptoir. 😞 /// note | Remarque -Illustrations proposées par [Ketrina Thompson](https://www.instagram.com/ketrinadrawsalot). 🎨 +Belles illustrations par [Ketrina Thompson](https://www.instagram.com/ketrinadrawsalot). 🎨 /// --- -Dans ce scénario de burgers parallèles, vous êtes un ordinateur / programme 🤖 avec deux processeurs (vous et votre crush 😍) attendant 🕙 à deux et dédiant votre attention ⏯ à « attendre devant le comptoir » 🕙 pour une longue durée. +Dans ce scénario de burgers parallèles, vous êtes un ordinateur / programme 🤖 avec deux processeurs (vous et votre crush), tous deux attendant 🕙 et dédiant leur attention ⏯ à « attendre devant le comptoir » 🕙 pour une longue durée. -Le fast-food a 8 processeurs (serveurs/cuisiniers) 👨‍🍳👨‍🍳👨‍🍳👨‍🍳👨‍🍳👨‍🍳👨‍🍳👨‍🍳. Alors que le fast-food de burgers concurrents en avait 2 (un serveur et un cuisinier). +Le fast food a 8 processeurs (caissiers/cuisiniers). Alors que le fast food de burgers concurrents aurait pu n'en avoir que 2 (un caissier et un cuisinier). -Et pourtant l'expérience finale n'est pas meilleure 😞. +Mais tout de même, l'expérience finale n'est pas la meilleure. 😞 --- -C'est donc l'histoire équivalente parallèle pour les burgers 🍔. +Ce serait donc l'histoire équivalente parallèle pour les burgers. 🍔 -Pour un exemple plus courant dans la « vie réelle », imaginez une banque. +Pour un exemple plus « vie réelle », imaginez une banque. -Jusqu'à récemment, la plupart des banques avaient plusieurs caisses (et banquiers) 👨‍💼👨‍💼👨‍💼👨‍💼 et une unique file d'attente 🕙🕙🕙🕙🕙🕙🕙🕙. +Jusqu'à récemment, la plupart des banques avaient plusieurs caissiers 👨‍💼👨‍💼👨‍💼👨‍💼 et une grande file d'attente 🕙🕙🕙🕙🕙🕙🕙🕙. -Tous les banquiers faisaient l'intégralité du travail avec chaque client avant de passer au suivant 👨‍💼⏯. +Tous les caissiers faisaient tout le travail avec chaque client avant de passer au suivant 👨‍💼⏯. -Et vous deviez attendre 🕙 dans la file pendant un long moment ou vous perdiez votre place. +Et vous devez attendre 🕙 dans la file pendant un long moment ou vous perdez votre tour. -Vous n'auriez donc probablement pas envie d'amener votre crush 😍 avec vous à la banque 🏦. +Vous n'auriez donc probablement pas envie d'amener votre crush 😍 avec vous pour faire des démarches à la banque 🏦. ### Conclusion sur les burgers { #burger-conclusion } -Dans ce scénario des « burgers du fast-food avec votre crush », comme il y a beaucoup d'attente 🕙, il est très logique d'avoir un système concurrent ⏸🔀⏯. +Dans ce scénario des « burgers de fast food avec votre crush », comme il y a beaucoup d'attente 🕙, il est beaucoup plus logique d'avoir un système concurrent ⏸🔀⏯. -Et c'est le cas pour la plupart des applications web. +C'est le cas pour la plupart des applications web. -Vous aurez de nombreux, nombreux utilisateurs, mais votre serveur attendra 🕙 que leur connexion peu performante envoie des requêtes. +De très, très nombreux utilisateurs, mais votre serveur attend 🕙 que leur connexion pas très bonne envoie leurs requêtes. -Puis vous attendrez 🕙 de nouveau que leurs réponses reviennent. +Puis attend 🕙 de nouveau que les réponses reviennent. -Cette « attente » 🕙 se mesure en microsecondes, mais tout de même, en cumulé cela fait beaucoup d'attente. +Cette « attente » 🕙 se mesure en microsecondes, mais tout de même, en les cumulant toutes, cela fait beaucoup d'attente au final. -C'est pourquoi il est logique d'utiliser du code asynchrone ⏸🔀⏯ pour des APIs web. +C'est pourquoi il est très logique d'utiliser du code asynchrone ⏸🔀⏯ pour des APIs web. Ce type d'asynchronicité est ce qui a rendu NodeJS populaire (bien que NodeJS ne soit pas parallèle) et c'est la force de Go en tant que langage de programmation. @@ -255,11 +255,11 @@ Et comme on peut avoir du parallélisme et de l'asynchronicité en même temps, ### Est-ce que la concurrence est mieux que le parallélisme ? { #is-concurrency-better-than-parallelism } -Nope ! C'est ça la morale de l'histoire. +Nope ! Ce n'est pas la morale de l'histoire. -La concurrence est différente du parallélisme. C'est mieux sur des scénarios **spécifiques** qui impliquent beaucoup d'attente. À cause de ça, c'est généralement bien meilleur que le parallélisme pour le développement d'applications web. Mais pas pour tout. +La concurrence est différente du parallélisme. Et c'est mieux dans des scénarios **spécifiques** qui impliquent beaucoup d'attente. À cause de ça, c'est généralement bien meilleur que le parallélisme pour le développement d'applications web. Mais pas pour tout. -Donc pour équilibrer tout ça, imaginez l'histoire suivante : +Donc pour équilibrer tout ça, imaginez l'histoire courte suivante : > Vous devez nettoyer une grande et sale maison. @@ -269,42 +269,42 @@ Donc pour équilibrer tout ça, imaginez l'histoire suivante : Il n'y a plus d'attente 🕙 nulle part, juste beaucoup de travail à effectuer, dans différentes pièces de la maison. -Vous pourriez diviser en différentes sections comme avec les burgers, d'abord le salon, puis la cuisine, etc. Mais vous n'attendez 🕙 rien, vous ne faites que nettoyer et nettoyer, la séparation en sections ne changerait rien au final. +Vous pourriez avoir des tours comme dans l'exemple des burgers, d'abord le salon, puis la cuisine, mais comme vous n'attendez 🕙 rien, vous ne faites que nettoyer et nettoyer, les tours ne changeraient rien. -Cela prendrait autant de temps pour finir avec ou sans sections (concurrence) et vous auriez effectué la même quantité de travail. +Cela prendrait autant de temps pour finir avec ou sans tours (concurrence) et vous auriez effectué la même quantité de travail. -Mais dans ce cas, si pouviez amener 8 ex-serveurs/cuisiniers/devenus-nettoyeurs 👨‍🍳👨‍🍳👨‍🍳👨‍🍳👨‍🍳👨‍🍳👨‍🍳👨‍🍳, et que chacun d'eux (plus vous) pouvait prendre une zone de la maison pour la nettoyer, vous pourriez faire tout le travail en parallèle, et finir plus tôt. +Mais dans ce cas, si vous pouviez amener les 8 ex-caissiers/cuisiniers/désormais-nettoyeurs, et que chacun d'eux (plus vous) pouvait prendre une zone de la maison pour la nettoyer, vous pourriez faire tout le travail en **parallèle**, avec l'aide supplémentaire, et finir beaucoup plus tôt. Dans ce scénario, chacun des nettoyeurs (vous y compris) serait un processeur, faisant sa partie du travail. -Et comme la plupart du temps d'exécution est pris par du « vrai » travail (et non de l'attente), et que le travail dans un ordinateur est fait par un CPU, ce sont des problèmes dits « CPU bound ». +Et comme la plupart du temps d'exécution est pris par du vrai travail (et non de l'attente), et que le travail dans un ordinateur est fait par un CPU, ce sont des problèmes dits « CPU bound ». --- -Des exemples communs d'opérations « CPU bound » sont les procédés qui requièrent des traitements mathématiques complexes. +Des exemples communs d'opérations CPU bound sont les choses qui requièrent des traitements mathématiques complexes. Par exemple : -* Traitements d'**audio** et d'**images**. -* La **vision par ordinateur** : une image est composée de millions de pixels, chaque pixel ayant 3 valeurs / couleurs, les traiter tous va nécessiter d'effectuer des traitements sur chaque pixel, et de préférence tous en même temps. -* L'apprentissage automatique (ou **Machine Learning**) : cela nécessite de nombreuses multiplications de matrices et vecteurs. Imaginez une énorme feuille de calcul remplie de nombres que vous multiplierez entre eux tous au même moment. -* L'apprentissage profond (ou **Deep Learning**) : est un sous-domaine du **Machine Learning**, donc les mêmes raisons s'appliquent. Avec la différence qu'il n'y a pas une unique feuille de calcul de nombres à multiplier, mais une énorme quantité d'entre elles, et dans de nombreux cas, on utilise un processeur spécial pour construire et / ou utiliser ces modèles. +* Traitements d'**audio** ou d'**images**. +* **Computer vision** : une image est composée de millions de pixels, chaque pixel ayant 3 valeurs / couleurs, les traiter nécessite normalement d'effectuer des calculs sur ces pixels, tous en même temps. +* **Machine Learning** : cela nécessite normalement de nombreuses multiplications de « matrices » et de « vecteurs ». Imaginez une énorme feuille de calcul remplie de nombres et les multiplier tous ensemble au même moment. +* **Deep Learning** : c'est un sous-domaine du Machine Learning, donc les mêmes raisons s'appliquent. C'est juste qu'il n'y a pas une unique feuille de calcul de nombres à multiplier, mais une énorme quantité d'entre elles, et dans de nombreux cas, on utilise un processeur spécial pour construire et / ou utiliser ces modèles. ### Concurrence + Parallélisme : Web + Machine Learning { #concurrency-parallelism-web-machine-learning } -Avec **FastAPI** vous pouvez bénéficier de la concurrence qui est très courante en développement web (c'est l'attrait principal de NodeJS). +Avec **FastAPI** vous pouvez bénéficier de la concurrence qui est très courante en développement web (le même attrait principal de NodeJS). -Mais vous pouvez aussi profiter du parallélisme et du multiprocessing (plusieurs processus s'exécutant en parallèle) afin de gérer des charges **CPU bound** qui sont récurrentes dans les systèmes de *Machine Learning*. +Mais vous pouvez aussi profiter du parallélisme et du multiprocessing (plusieurs processus s'exécutant en parallèle) afin de gérer des charges **CPU bound** comme celles des systèmes de Machine Learning. -Ça, ajouté au fait que Python soit le langage le plus populaire pour la **Data Science**, le **Machine Learning** et surtout le **Deep Learning**, font de **FastAPI** un très bon choix pour les APIs et applications de **Data Science** / **Machine Learning**. +Ça, ajouté au simple fait que Python soit le langage principal pour la **Data Science**, le Machine Learning et surtout le Deep Learning, fait de FastAPI un très bon choix pour les APIs web et applications de Data Science / Machine Learning (entre autres). -Pour comprendre comment mettre en place ce parallélisme en production, allez lire la section [Déploiement](deployment/index.md). +Pour comprendre comment mettre en place ce parallélisme en production, consultez la section sur le [Déploiement](deployment/index.md). ## `async` et `await` { #async-and-await } -Les versions modernes de Python ont une manière très intuitive de définir le code asynchrone, tout en gardant une apparence de code « séquentiel » classique en laissant Python faire l'attente pour vous au bon moment. +Les versions modernes de Python ont une manière très intuitive de définir le code asynchrone. Cela le fait ressembler à du code « séquentiel » normal et effectue l'« attente » pour vous aux bons moments. -Pour une opération qui nécessite de l'attente avant de donner un résultat et qui supporte ces nouvelles fonctionnalités Python, vous pouvez l'utiliser comme tel : +Pour une opération qui nécessite de l'attente avant de donner un résultat et qui supporte ces nouvelles fonctionnalités Python, vous pouvez l'écrire comme ceci : ```Python burgers = await get_burgers(2) @@ -312,7 +312,7 @@ burgers = await get_burgers(2) Le mot-clé important ici est `await`. Il informe Python qu'il faut attendre ⏸ que `get_burgers(2)` finisse d'effectuer ses opérations 🕙 avant de stocker les résultats dans la variable `burgers`. Grâce à cela, Python saura qu'il peut aller effectuer d'autres opérations 🔀 ⏯ pendant ce temps (comme par exemple recevoir une autre requête). -Pour que `await` fonctionne, il doit être placé dans une fonction qui supporte l'asynchronicité. Pour que ça soit le cas, il faut déclarer cette dernière avec `async def` : +Pour que `await` fonctionne, il doit être placé dans une fonction qui supporte cette asynchronicité. Pour que ça soit le cas, il faut déclarer cette dernière avec `async def` : ```Python hl_lines="1" async def get_burgers(number: int): @@ -320,7 +320,7 @@ async def get_burgers(number: int): return burgers ``` -... et non `def` : +... au lieu de `def` : ```Python hl_lines="2" # Ceci n'est pas asynchrone @@ -331,16 +331,16 @@ def get_sequential_burgers(number: int): Avec `async def`, Python sait que dans cette fonction il doit prendre en compte les expressions `await`, et qu'il peut mettre en pause ⏸ l'exécution de la fonction pour aller faire autre chose 🔀 avant de revenir. -Pour appeler une fonction définie avec `async def`, vous devez utiliser `await`. Donc ceci ne marche pas : +Lorsque vous voulez appeler une fonction `async def`, vous devez l'« attendre ». Donc ceci ne marche pas : ```Python -# Ceci ne fonctionne pas, car get_burgers a été défini avec async def +# Ceci ne fonctionne pas, car get_burgers a été défini avec : async def burgers = get_burgers(2) ``` --- -Donc, si vous utilisez une bibliothèque qui nécessite que ses fonctions soient appelées avec `await`, vous devez définir la *fonction de chemin d'accès* en utilisant `async def` comme dans : +Donc, si vous utilisez une bibliothèque qui vous indique que vous pouvez l'appeler avec `await`, vous devez créer les *fonctions de chemin d'accès* qui l'utilisent avec `async def`, comme dans : ```Python hl_lines="2-3" @app.get('/burgers') @@ -351,13 +351,13 @@ async def read_burgers(): ### Plus de détails techniques { #more-technical-details } -Vous avez donc compris que `await` peut seulement être utilisé dans des fonctions définies avec `async def`. +Vous avez peut-être remarqué que `await` peut seulement être utilisé dans des fonctions définies avec `async def`. -Mais en même temps, les fonctions définies avec `async def` doivent être appelées avec `await` et donc dans des fonctions définies elles aussi avec `async def`. +Mais en même temps, les fonctions définies avec `async def` doivent être « attendues ». Donc, les fonctions avec `async def` peuvent seulement être appelées à l'intérieur de fonctions définies elles aussi avec `async def`. -Vous avez donc remarqué ce paradoxe d'œuf et de la poule, comment appelle-t-on la première fonction `async` ? +Donc, à propos de l'œuf et de la poule, comment appelle-t-on la première fonction `async` ? -Si vous utilisez **FastAPI**, pas besoin de vous en inquiéter, car cette « première » fonction sera votre *fonction de chemin d'accès* ; et **FastAPI** saura comment arriver au résultat attendu. +Si vous utilisez **FastAPI**, pas besoin de vous en inquiéter, car cette « première » fonction sera votre *fonction de chemin d'accès*, et FastAPI saura comment faire ce qu'il faut. Mais si vous souhaitez utiliser `async` / `await` sans FastAPI, vous pouvez également le faire. @@ -367,7 +367,7 @@ Starlette (et **FastAPI**) s’appuie sur [AnyIO](https://anyio.readthedocs.io/e En particulier, vous pouvez utiliser directement [AnyIO](https://anyio.readthedocs.io/en/stable/) pour vos cas d’usage de concurrence avancés qui nécessitent des schémas plus élaborés dans votre propre code. -Et même si vous n’utilisiez pas FastAPI, vous pourriez aussi écrire vos propres applications async avec [AnyIO](https://anyio.readthedocs.io/en/stable/) pour une grande compatibilité et pour bénéficier de ses avantages (par ex. la « structured concurrency »). +Et même si vous n’utilisiez pas FastAPI, vous pourriez aussi écrire vos propres applications async avec [AnyIO](https://anyio.readthedocs.io/en/stable/) pour une grande compatibilité et pour bénéficier de ses avantages (par ex. la *structured concurrency*). J’ai créé une autre bibliothèque au-dessus d’AnyIO, comme une fine surcouche, pour améliorer un peu les annotations de type et obtenir une meilleure **autocomplétion**, des **erreurs en ligne**, etc. Elle propose également une introduction et un tutoriel accessibles pour vous aider à **comprendre** et écrire **votre propre code async** : [Asyncer](https://asyncer.tiangolo.com/). Elle sera particulièrement utile si vous devez **combiner du code async avec du code classique** (bloquant/synchrone). @@ -377,25 +377,25 @@ L'utilisation d'`async` et `await` est relativement nouvelle dans ce langage. Mais cela rend la programmation asynchrone bien plus simple. -Cette même syntaxe (ou presque) a aussi été incluse récemment dans les versions modernes de JavaScript (dans les navigateurs et NodeJS). +Cette même syntaxe (ou presque) a aussi été incluse récemment dans les versions modernes de JavaScript (dans le navigateur et NodeJS). Mais avant ça, gérer du code asynchrone était bien plus complexe et difficile. -Dans les versions précédentes de Python, vous auriez utilisé des threads ou [Gevent](https://www.gevent.org/). Mais le code aurait été bien plus difficile à comprendre, débugger, et concevoir. +Dans les versions précédentes de Python, vous auriez pu utiliser des threads ou [Gevent](https://www.gevent.org/). Mais le code est bien plus difficile à comprendre, débugger, et concevoir. -Dans les versions précédentes de JavaScript côté navigateur / NodeJS, vous auriez utilisé des « callbacks ». Menant potentiellement à ce que l'on appelle le « callback hell ». +Dans les versions précédentes de NodeJS / JavaScript de navigateur, vous auriez utilisé des « callbacks ». Ce qui mène au « callback hell ». ## Coroutines { #coroutines } -« Coroutine » est juste un terme élaboré pour désigner ce qui est retourné par une fonction définie avec `async def`. Python sait que c'est comme une fonction classique qui va démarrer à un moment et terminer à un autre, mais qu'elle peut aussi être mise en pause ⏸, du moment qu'il y a un `await` dans son contenu. +**Coroutine** est juste un terme élaboré pour désigner ce qui est retourné par une fonction définie avec `async def`. Python sait que c'est comme une fonction, qui peut démarrer et qui se terminera à un moment, mais qu'elle peut aussi être mise en pause ⏸ en interne, quand il y a un `await` à l'intérieur. Mais toutes ces fonctionnalités d'utilisation de code asynchrone avec `async` et `await` sont souvent résumées comme l'utilisation des « coroutines ». On peut comparer cela à la principale fonctionnalité clé de Go, les « Goroutines ». ## Conclusion { #conclusion } -Reprenons la phrase du début de la page : +Reprenons la même phrase ci-dessus : -> Les versions modernes de Python supportent le **code asynchrone** grâce aux **« coroutines »** avec les syntaxes **`async` et `await`**. +> Les versions modernes de Python supportent le **« code asynchrone »** en utilisant quelque chose appelé **« coroutines »**, avec la syntaxe **`async` et `await`**. Ceci devrait être plus compréhensible désormais. ✨ @@ -409,25 +409,25 @@ Vous pouvez probablement ignorer cela. Ce sont des détails très poussés sur comment **FastAPI** fonctionne en arrière-plan. -Si vous avez de bonnes connaissances techniques (coroutines, threads, code bloquant, etc.) et êtes curieux de comment **FastAPI** gère `async def` versus le `def` classique, cette partie est faite pour vous. +Si vous avez de bonnes connaissances techniques (coroutines, threads, code bloquant, etc.) et êtes curieux de comment FastAPI gère `async def` versus le `def` classique, cette partie est faite pour vous. /// ### Fonctions de chemin d'accès { #path-operation-functions } -Quand vous déclarez une *fonction de chemin d'accès* avec un `def` normal et non `async def`, elle est exécutée dans un groupe de threads (threadpool) externe qui est ensuite attendu, plutôt que d'être appelée directement (car cela bloquerait le serveur). +Quand vous déclarez une *fonction de chemin d'accès* avec un `def` normal et non `async def`, elle est exécutée dans une threadpool externe qui est ensuite attendue, plutôt que d'être appelée directement (car cela bloquerait le serveur). -Si vous venez d'un autre framework asynchrone qui ne fonctionne pas comme de la façon décrite ci-dessus et que vous êtes habitué à définir des *fonctions de chemin d'accès* basiques et purement calculatoires avec un simple `def` pour un faible gain de performance (environ 100 nanosecondes), veuillez noter que dans **FastAPI**, l'effet serait plutôt contraire. Dans ces cas-là, il vaut mieux utiliser `async def` à moins que votre *fonction de chemin d'accès* utilise du code qui effectue des opérations I/O bloquantes. +Si vous venez d'un autre framework async qui ne fonctionne pas de la façon décrite ci-dessus et que vous êtes habitué à définir des *fonctions de chemin d'accès* triviales faisant uniquement du calcul avec un simple `def` pour un faible gain de performance (environ 100 nanosecondes), veuillez noter que dans **FastAPI**, l'effet serait plutôt contraire. Dans ces cas-là, il vaut mieux utiliser `async def` à moins que vos *fonctions de chemin d'accès* utilisent du code qui effectue des opérations I/O bloquantes. -Au final, dans les deux situations, il est fort probable que **FastAPI** soit tout de même [plus rapide](index.md#performance) que (ou au moins de vitesse égale à) votre framework précédent. +Au final, dans les deux situations, il est fort probable que **FastAPI** soit [tout de même plus rapide](index.md#performance) que (ou au moins comparable à) votre framework précédent. ### Dépendances { #dependencies } -La même chose s'applique aux [dépendances](tutorial/dependencies/index.md). Si une dépendance est définie avec `def` plutôt que `async def`, elle est exécutée dans la threadpool externe. +La même chose s'applique aux [dépendances](tutorial/dependencies/index.md). Si une dépendance est une fonction standard `def` plutôt qu'`async def`, elle est exécutée dans la threadpool externe. ### Sous-dépendances { #sub-dependencies } -Vous pouvez avoir de multiples dépendances et [sous-dépendances](tutorial/dependencies/sub-dependencies.md) dépendant les unes des autres (en tant que paramètres de la définition de la *fonction de chemin d'accès*), certaines créées avec `async def` et d'autres avec `def`. Cela fonctionnerait aussi, et celles définies avec un simple `def` seraient exécutées sur un thread externe (venant de la threadpool) plutôt que d'être « attendues ». +Vous pouvez avoir de multiples dépendances et [sous-dépendances](tutorial/dependencies/sub-dependencies.md) dépendant les unes des autres (en tant que paramètres des définitions des fonctions), certaines créées avec `async def` et d'autres avec un `def` normal. Cela fonctionnerait aussi, et celles définies avec un `def` normal seraient appelées sur un thread externe (venant de la threadpool) plutôt que d'être « attendues ». ### Autres fonctions utilitaires { #other-utility-functions } @@ -435,10 +435,10 @@ Toute autre fonction utilitaire que vous appelez directement peut être créée Contrairement aux fonctions que FastAPI appelle pour vous : les *fonctions de chemin d'accès* et dépendances. -Si votre fonction utilitaire est une fonction classique définie avec `def`, elle sera appelée directement (telle qu'écrite dans votre code), pas dans une threadpool ; si la fonction est définie avec `async def` alors vous devrez attendre (avec `await`) que cette fonction se termine avant de passer à la suite du code. +Si votre fonction utilitaire est une fonction classique définie avec `def`, elle sera appelée directement (telle qu'écrite dans votre code), pas dans une threadpool ; si la fonction est définie avec `async def` alors vous devez `await` cette fonction lorsque vous l'appelez dans votre code. --- Encore une fois, ce sont des détails très techniques qui peuvent être utiles si vous venez ici les chercher. -Sinon, les instructions de la section Vous êtes pressés ? ci-dessus sont largement suffisantes. +Sinon, les instructions de la section ci-dessus sont largement suffisantes : Vous êtes pressés ?. diff --git a/docs/fr/docs/deployment/cloud.md b/docs/fr/docs/deployment/cloud.md index 1ed030f0a..368966372 100644 --- a/docs/fr/docs/deployment/cloud.md +++ b/docs/fr/docs/deployment/cloud.md @@ -1,6 +1,6 @@ # Déployer FastAPI sur des fournisseurs cloud { #deploy-fastapi-on-cloud-providers } -Vous pouvez utiliser pratiquement n'importe quel fournisseur cloud pour déployer votre application FastAPI. +Vous pouvez utiliser pratiquement **n'importe quel fournisseur cloud** pour déployer votre application FastAPI. Dans la plupart des cas, les principaux fournisseurs cloud proposent des guides pour déployer FastAPI avec leurs services. @@ -16,7 +16,7 @@ FastAPI Cloud est le sponsor principal et le financeur des projets open source * ## Fournisseurs cloud - Sponsors { #cloud-providers-sponsors } -D'autres fournisseurs cloud ✨ [**parrainent FastAPI**](../help-fastapi.md#sponsor-the-author) ✨ également. 🙇 +Certains autres fournisseurs cloud ✨ [**parrainent FastAPI**](https://github.com/sponsors/tiangolo) ✨ également. 🙇 Vous pouvez également envisager ces fournisseurs pour suivre leurs guides et essayer leurs services : diff --git a/docs/fr/docs/deployment/concepts.md b/docs/fr/docs/deployment/concepts.md index 1d5497d93..d6940c683 100644 --- a/docs/fr/docs/deployment/concepts.md +++ b/docs/fr/docs/deployment/concepts.md @@ -1,5 +1,6 @@ # Concepts de déploiement { #deployments-concepts } + Lorsque vous déployez une application **FastAPI**, ou en fait n'importe quel type de web API, il existe plusieurs concepts qui vous importent probablement, et en les utilisant vous pouvez trouver la manière la **plus appropriée** de **déployer votre application**. Parmi les concepts importants, on trouve : diff --git a/docs/fr/docs/deployment/docker.md b/docs/fr/docs/deployment/docker.md index 1567e1d58..688f3b5d8 100644 --- a/docs/fr/docs/deployment/docker.md +++ b/docs/fr/docs/deployment/docker.md @@ -132,7 +132,7 @@ Successfully installed fastapi pydantic
-/// info +/// note | Remarque Il existe d'autres formats et outils pour définir et installer des dépendances de paquets. @@ -232,7 +232,7 @@ Passez en revue ce que fait chaque ligne en cliquant sur chaque bulle numéroté /// warning | Alertes -Vous devez vous assurer d'utiliser **toujours** la **forme exec** de l'instruction `CMD`, comme expliqué ci-dessous. +Vous devez **toujours** utiliser la **forme exec** de l'instruction `CMD`, comme expliqué ci-dessous. /// @@ -254,7 +254,7 @@ CMD ["fastapi", "run", "app/main.py", "--port", "80"] CMD fastapi run app/main.py --port 80 ``` -Assurez-vous d'utiliser toujours la forme **exec** pour garantir que FastAPI peut s'arrêter proprement et que les [événements de cycle de vie](../advanced/events.md) sont déclenchés. +Vous devez toujours utiliser la forme **exec** pour garantir que FastAPI peut s'arrêter proprement et que les [événements de cycle de vie](../advanced/events.md) sont déclenchés. Vous pouvez en lire davantage dans la [documentation Docker sur les formes shell et exec](https://docs.docker.com/reference/dockerfile/#shell-and-exec-form). @@ -556,7 +556,7 @@ Si vous utilisez des conteneurs (par ex. Docker, Kubernetes), alors il existe de Si vous avez **plusieurs conteneurs**, probablement chacun exécutant un **seul processus** (par exemple, dans un cluster **Kubernetes**), alors vous voudrez probablement avoir un **conteneur séparé** effectuant le travail des **étapes préalables** dans un seul conteneur, exécutant un seul processus, **avant** d'exécuter les conteneurs worker répliqués. -/// info +/// note | Remarque Si vous utilisez Kubernetes, ce sera probablement un [Init Container](https://kubernetes.io/docs/concepts/workloads/pods/init-containers/). diff --git a/docs/fr/docs/deployment/fastapicloud.md b/docs/fr/docs/deployment/fastapicloud.md index 836e91489..82c16330e 100644 --- a/docs/fr/docs/deployment/fastapicloud.md +++ b/docs/fr/docs/deployment/fastapicloud.md @@ -1,26 +1,6 @@ # FastAPI Cloud { #fastapi-cloud } -Vous pouvez déployer votre application FastAPI sur [FastAPI Cloud](https://fastapicloud.com) avec une **seule commande**, allez vous inscrire sur la liste d’attente si ce n’est pas déjà fait. 🚀 - -## Se connecter { #login } - -Vous devez vous assurer que vous avez déjà un compte **FastAPI Cloud** (nous vous avons invité depuis la liste d’attente 😉). - -Connectez-vous ensuite : - -
- -```console -$ fastapi login - -You are logged in to FastAPI Cloud 🚀 -``` - -
- -## Déployer { #deploy } - -Déployez maintenant votre application, avec une **seule commande** : +Vous pouvez déployer votre application FastAPI sur [FastAPI Cloud](https://fastapicloud.com) avec une **seule commande**. 🚀
@@ -36,6 +16,8 @@ Deploying to FastAPI Cloud...
+La CLI détecte automatiquement votre application FastAPI et la déploie dans le cloud. Si vous n’êtes pas connecté, votre navigateur s’ouvrira pour terminer le processus d’authentification. + C’est tout ! Vous pouvez maintenant accéder à votre application à cette URL. ✨ ## À propos de FastAPI Cloud { #about-fastapi-cloud } @@ -62,4 +44,4 @@ Suivez les guides de votre fournisseur cloud pour déployer des applications Fas ## Déployer votre propre serveur { #deploy-your-own-server } -Je vous expliquerai également plus loin dans ce guide de **Déploiement** tous les détails, afin que vous compreniez ce qui se passe, ce qui doit être fait, et comment déployer des applications FastAPI par vous-même, y compris sur vos propres serveurs. 🤓 +Je vous expliquerai également plus loin dans ce guide de **Déploiement** tous les détails, afin que vous compreniez ce qui se passe, ce qui doit être fait, ou comment déployer des applications FastAPI par vous-même, y compris sur vos propres serveurs. 🤓 diff --git a/docs/fr/docs/deployment/https.md b/docs/fr/docs/deployment/https.md index 34922f168..5150ecdeb 100644 --- a/docs/fr/docs/deployment/https.md +++ b/docs/fr/docs/deployment/https.md @@ -10,9 +10,9 @@ Si vous êtes pressé ou si cela ne vous intéresse pas, continuez avec les sect /// -Pour apprendre les bases du HTTPS, du point de vue d'un utilisateur, consultez [https://howhttps.works/](https://howhttps.works/). +Pour **apprendre les bases du HTTPS**, du point de vue d'un utilisateur, consultez [https://howhttps.works/](https://howhttps.works/). -Maintenant, du point de vue d'un développeur, voici plusieurs choses à avoir en tête en pensant au HTTPS : +Maintenant, du **point de vue d'un développeur**, voici plusieurs choses à avoir en tête en pensant au HTTPS : * Pour le HTTPS, **le serveur** doit **disposer de « certificats »** générés par une **tierce partie**. * Ces certificats sont en réalité **acquis** auprès de la tierce partie, et non « générés ». @@ -65,7 +65,7 @@ Voici un exemple de ce à quoi pourrait ressembler une API HTTPS, étape par ét Tout commencerait probablement par le fait que vous **acquériez** un **nom de domaine**. Ensuite, vous le configureriez dans un serveur DNS (possiblement le même que votre fournisseur cloud). -Vous obtiendriez probablement un serveur cloud (une machine virtuelle) ou quelque chose de similaire, et il aurait une adresse IP publique fixe. +Vous obtiendriez probablement un serveur cloud (une machine virtuelle) ou quelque chose de similaire, et il aurait une **adresse IP publique** fixe. Dans le ou les serveurs DNS, vous configureriez un enregistrement (un « `A record` ») pour faire pointer **votre domaine** vers l'**adresse IP publique de votre serveur**. diff --git a/docs/fr/docs/deployment/manually.md b/docs/fr/docs/deployment/manually.md index 4b87df993..2d9cc4f8f 100644 --- a/docs/fr/docs/deployment/manually.md +++ b/docs/fr/docs/deployment/manually.md @@ -40,7 +40,7 @@ $ fastapi run ASGI. FastAPI est un framework web ASGI. -La principale chose dont vous avez besoin pour exécuter une application **FastAPI** (ou toute autre application ASGI) sur une machine serveur distante est un programme serveur ASGI comme **Uvicorn**, c'est celui utilisé par défaut par la commande `fastapi`. +La principale chose dont vous avez besoin pour exécuter une application **FastAPI** (ou toute autre application ASGI) sur une machine serveur distante est un programme serveur ASGI comme **Uvicorn**, c'est celui fourni par défaut avec la commande `fastapi`. Il existe plusieurs alternatives, notamment : @@ -56,15 +56,14 @@ Il existe plusieurs alternatives, notamment : * [Hypercorn](https://hypercorn.readthedocs.io/) : un serveur ASGI compatible avec HTTP/2 et Trio entre autres fonctionnalités. * [Daphne](https://github.com/django/daphne) : le serveur ASGI conçu pour Django Channels. * [Granian](https://github.com/emmett-framework/granian) : un serveur HTTP Rust pour les applications Python. -* [NGINX Unit](https://unit.nginx.org/howto/fastapi/) : NGINX Unit est un environnement d'exécution d'applications web léger et polyvalent. ## Machine serveur et programme serveur { #server-machine-and-server-program } Il y a un petit détail sur les noms à garder à l'esprit. 💡 -Le mot « serveur » est couramment utilisé pour désigner à la fois l'ordinateur distant/cloud (la machine physique ou virtuelle) et également le programme qui s'exécute sur cette machine (par exemple, Uvicorn). +Le mot « **serveur** » est couramment utilisé pour désigner à la fois l'ordinateur distant/cloud (la machine physique ou virtuelle) et également le programme qui s'exécute sur cette machine (par exemple, Uvicorn). -Gardez cela à l'esprit lorsque vous lisez « serveur » en général, cela pourrait faire référence à l'une de ces deux choses. +Gardez simplement à l'esprit que lorsque vous lisez « serveur » en général, cela pourrait faire référence à l'une de ces deux choses. Lorsqu'on se réfère à la machine distante, il est courant de l'appeler **serveur**, mais aussi **machine**, **VM** (machine virtuelle), **nœud**. Tout cela fait référence à un type de machine distante, exécutant normalement Linux, sur laquelle vous exécutez des programmes. @@ -118,7 +117,7 @@ $ uvicorn main:app --host 0.0.0.0 --port 80 La commande `uvicorn main:app` fait référence à : -* `main` : le fichier `main.py` (le « module » Python). +* `main` : le fichier `main.py` (le « module » Python). * `app` : l'objet créé dans `main.py` avec la ligne `app = FastAPI()`. C'est équivalent à : diff --git a/docs/fr/docs/deployment/server-workers.md b/docs/fr/docs/deployment/server-workers.md index c0eca2dcc..4271621c8 100644 --- a/docs/fr/docs/deployment/server-workers.md +++ b/docs/fr/docs/deployment/server-workers.md @@ -17,7 +17,7 @@ Comme vous l'avez vu dans le chapitre précédent sur les [Concepts de déploiem Ici, je vais vous montrer comment utiliser Uvicorn avec des processus workers en utilisant la commande `fastapi` ou directement la commande `uvicorn`. -/// info | Info +/// note | Remarque Si vous utilisez des conteneurs, par exemple avec Docker ou Kubernetes, je vous en dirai plus à ce sujet dans le prochain chapitre : [FastAPI dans des conteneurs - Docker](docker.md). diff --git a/docs/fr/docs/editor-support.md b/docs/fr/docs/editor-support.md index 59e0b3f15..a29b3b261 100644 --- a/docs/fr/docs/editor-support.md +++ b/docs/fr/docs/editor-support.md @@ -1,6 +1,6 @@ # Prise en charge des éditeurs { #editor-support } -L’extension officielle [Extension FastAPI](https://marketplace.visualstudio.com/items?itemName=FastAPILabs.fastapi-vscode) améliore votre flux de développement FastAPI grâce à la découverte des chemins d'accès, à la navigation, ainsi qu’au déploiement sur FastAPI Cloud et à la diffusion en direct des journaux. +L’extension officielle [Extension FastAPI](https://marketplace.visualstudio.com/items?itemName=FastAPILabs.fastapi-vscode) améliore votre flux de développement FastAPI grâce à la découverte des *chemins d'accès*, à la navigation, ainsi qu’au déploiement sur FastAPI Cloud et à la diffusion en direct des journaux. Pour plus de détails sur l’extension, reportez-vous au README sur le [référentiel GitHub](https://github.com/fastapi/fastapi-vscode). diff --git a/docs/fr/docs/environment-variables.md b/docs/fr/docs/environment-variables.md index 7f052f27f..065194700 100644 --- a/docs/fr/docs/environment-variables.md +++ b/docs/fr/docs/environment-variables.md @@ -6,13 +6,13 @@ Si vous savez déjà ce que sont les « variables d'environnement » et comment /// -Une variable d'environnement (également appelée « env var ») est une variable qui vit en dehors du code Python, dans le système d'exploitation, et qui peut être lue par votre code Python (ou par d'autres programmes également). +Une variable d'environnement (également appelée « **env var** ») est une variable qui vit **en dehors** du code Python, dans le **système d'exploitation**, et qui peut être lue par votre code Python (ou par d'autres programmes également). Les variables d'environnement peuvent être utiles pour gérer des **paramètres** d'application, dans le cadre de l'**installation** de Python, etc. ## Créer et utiliser des variables d'environnement { #create-and-use-env-vars } -Vous pouvez créer et utiliser des variables d'environnement dans le **shell (terminal)**, sans avoir besoin de Python : +Vous pouvez **créer** et utiliser des variables d'environnement dans le **shell (terminal)**, sans avoir besoin de Python : //// tab | Linux, macOS, Windows Bash @@ -54,7 +54,7 @@ Hello Wade Wilson Vous pouvez également créer des variables d'environnement **en dehors** de Python, dans le terminal (ou par tout autre moyen), puis les **lire en Python**. -Par exemple, vous pouvez avoir un fichier `main.py` contenant : +Par exemple, vous pouvez avoir un fichier `main.py` contenant : ```Python hl_lines="3" import os @@ -71,7 +71,7 @@ S'il n'est pas fourni, c'est `None` par défaut ; ici, nous fournissons `"World" /// -Vous pouvez ensuite exécuter ce programme Python : +Vous pouvez ensuite exécuter ce programme Python : //// tab | Linux, macOS, Windows Bash @@ -131,7 +131,7 @@ Comme les variables d'environnement peuvent être définies en dehors du code, m Vous pouvez également créer une variable d'environnement uniquement pour l'**invocation d'un programme spécifique**, qui ne sera disponible que pour ce programme et uniquement pendant sa durée d'exécution. -Pour cela, créez-la juste avant le programme, sur la même ligne : +Pour cela, créez-la juste avant le programme, sur la même ligne :
@@ -159,7 +159,7 @@ Vous pouvez en lire davantage sur [The Twelve-Factor App : Config](https://12fac ## Gérer les types et la validation { #types-and-validation } -Ces variables d'environnement ne peuvent gérer que des **chaînes de texte**, car elles sont externes à Python et doivent être compatibles avec les autres programmes et le reste du système (et même avec différents systèmes d'exploitation, comme Linux, Windows, macOS). +Ces variables d'environnement ne peuvent gérer que des **chaînes de texte**, car elles sont externes à Python et doivent être compatibles avec les autres programmes et le reste du système (et même avec différents systèmes d'exploitation, comme Linux, Windows et macOS). Cela signifie que **toute valeur** lue en Python à partir d'une variable d'environnement **sera une `str`**, et que toute conversion vers un autre type ou toute validation doit être effectuée dans le code. @@ -167,11 +167,11 @@ Vous en apprendrez davantage sur l'utilisation des variables d'environnement pou ## Variable d'environnement `PATH` { #path-environment-variable } -Il existe une **variable d'environnement spéciale** appelée **`PATH`** qui est utilisée par les systèmes d'exploitation (Linux, macOS, Windows) pour trouver les programmes à exécuter. +Il existe une variable d'environnement **spéciale** appelée **`PATH`** qui est utilisée par les systèmes d'exploitation (Linux, macOS, Windows) pour trouver les programmes à exécuter. La valeur de la variable `PATH` est une longue chaîne composée de répertoires séparés par deux-points `:` sous Linux et macOS, et par point-virgule `;` sous Windows. -Par exemple, la variable d'environnement `PATH` peut ressembler à ceci : +Par exemple, la variable d'environnement `PATH` peut ressembler à ceci : //// tab | Linux, macOS @@ -179,7 +179,7 @@ Par exemple, la variable d'environnement `PATH` peut ressembler à ceci : /usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin ``` -Cela signifie que le système doit rechercher les programmes dans les répertoires : +Cela signifie que le système doit rechercher les programmes dans les répertoires : * `/usr/local/bin` * `/usr/bin` @@ -195,7 +195,7 @@ Cela signifie que le système doit rechercher les programmes dans les répertoir C:\Program Files\Python312\Scripts;C:\Program Files\Python312;C:\Windows\System32 ``` -Cela signifie que le système doit rechercher les programmes dans les répertoires : +Cela signifie que le système doit rechercher les programmes dans les répertoires : * `C:\Program Files\Python312\Scripts` * `C:\Program Files\Python312` @@ -219,7 +219,7 @@ Supposons que vous installiez Python et qu'il se retrouve dans un répertoire `/ Si vous acceptez de mettre à jour la variable d'environnement `PATH`, l'installateur ajoutera `/opt/custompython/bin` à la variable d'environnement `PATH`. -Cela pourrait ressembler à ceci : +Cela pourrait ressembler à ceci : ```plaintext /usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/custompython/bin @@ -243,7 +243,7 @@ Ainsi, lorsque vous tapez `python` dans le terminal, le système trouvera le pro //// -Ainsi, si vous tapez : +Ainsi, si vous tapez :
@@ -257,7 +257,7 @@ $ python Le système va **trouver** le programme `python` dans `/opt/custompython/bin` et l'exécuter. -Cela reviendrait à peu près à taper : +Cela reviendrait à peu près à taper :
@@ -273,7 +273,7 @@ $ /opt/custompython/bin/python Le système va **trouver** le programme `python` dans `C:\opt\custompython\bin\python` et l'exécuter. -Cela reviendrait à peu près à taper : +Cela reviendrait à peu près à taper :
diff --git a/docs/fr/docs/features.md b/docs/fr/docs/features.md index 0bb16b343..4ded18206 100644 --- a/docs/fr/docs/features.md +++ b/docs/fr/docs/features.md @@ -17,7 +17,7 @@ Documentation d'API interactive et interfaces web d'exploration. Comme le framew * [**Swagger UI**](https://github.com/swagger-api/swagger-ui), avec exploration interactive, appelez et testez votre API directement depuis le navigateur. -![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-03-swagger-02.png) +![interaction avec Swagger UI](https://fastapi.tiangolo.com/img/index/index-03-swagger-02.png) * Documentation d'API alternative avec [**ReDoc**](https://github.com/Rebilly/ReDoc). @@ -85,11 +85,11 @@ Voici comment votre éditeur peut vous aider : * dans [Visual Studio Code](https://code.visualstudio.com/) : -![editor support](https://fastapi.tiangolo.com/img/vscode-completion.png) +![support de l'éditeur](https://fastapi.tiangolo.com/img/vscode-completion.png) * dans [PyCharm](https://www.jetbrains.com/pycharm/) : -![editor support](https://fastapi.tiangolo.com/img/pycharm-completion.png) +![support de l'éditeur](https://fastapi.tiangolo.com/img/pycharm-completion.png) Vous obtiendrez de l'autocomplétion dans du code que vous auriez pu considérer impossible auparavant. Par exemple, la clé `price` à l'intérieur d'un corps JSON (qui aurait pu être imbriqué) provenant d'une requête. @@ -105,7 +105,7 @@ Mais par défaut, tout **« just works »**. * Validation pour la plupart (ou tous ?) des **types de données** Python, y compris : * objets JSON (`dict`). - * tableaux JSON (`list`) définissant les types d'éléments. + * tableau JSON (`list`) définissant les types d'éléments. * champs String (`str`), définition des longueurs minimale et maximale. * nombres (`int`, `float`) avec valeurs minimale et maximale, etc. diff --git a/docs/fr/docs/help-fastapi.md b/docs/fr/docs/help-fastapi.md index 7a6da3c08..db46bcbc1 100644 --- a/docs/fr/docs/help-fastapi.md +++ b/docs/fr/docs/help-fastapi.md @@ -1,5 +1,6 @@ # Aider { #help } + Souhaitez-vous aider FastAPI ou obtenir de l'aide à propos de FastAPI ? Il existe des moyens très simples d'aider et d'obtenir de l'aide. diff --git a/docs/fr/docs/how-to/configure-swagger-ui.md b/docs/fr/docs/how-to/configure-swagger-ui.md index 34db05558..e4f876323 100644 --- a/docs/fr/docs/how-to/configure-swagger-ui.md +++ b/docs/fr/docs/how-to/configure-swagger-ui.md @@ -50,11 +50,11 @@ Par exemple, pour désactiver `deepLinking`, vous pourriez passer ces paramètre ## Autres paramètres de Swagger UI { #other-swagger-ui-parameters } -Pour voir toutes les autres configurations possibles que vous pouvez utiliser, lisez les [documents officiels pour les paramètres de Swagger UI](https://swagger.io/docs/open-source-tools/swagger-ui/usage/configuration/). +Pour voir toutes les autres configurations possibles que vous pouvez utiliser, lisez les documents officiels [pour les paramètres de Swagger UI](https://swagger.io/docs/open-source-tools/swagger-ui/usage/configuration/). ## Paramètres JavaScript uniquement { #javascript-only-settings } -Swagger UI permet également d'autres configurations qui sont des objets réservés à JavaScript (par exemple, des fonctions JavaScript). +Swagger UI permet également d'autres configurations qui sont des objets **réservés à JavaScript** (par exemple, des fonctions JavaScript). FastAPI inclut aussi ces paramètres `presets` réservés à JavaScript : diff --git a/docs/fr/docs/how-to/custom-request-and-route.md b/docs/fr/docs/how-to/custom-request-and-route.md index 4acb6464f..0b3ab88b9 100644 --- a/docs/fr/docs/how-to/custom-request-and-route.md +++ b/docs/fr/docs/how-to/custom-request-and-route.md @@ -66,7 +66,7 @@ Le `dict` `scope` et la fonction `receive` font tous deux partie de la spécific Et ces deux éléments, `scope` et `receive`, sont ce dont on a besoin pour créer une nouvelle instance de `Request`. -Pour en savoir plus sur `Request`, consultez [la documentation de Starlette sur les requêtes](https://www.starlette.dev/requests/). +Pour en savoir plus sur `Request`, consultez [les documents de Starlette sur les requêtes](https://www.starlette.dev/requests/). /// diff --git a/docs/fr/docs/how-to/extending-openapi.md b/docs/fr/docs/how-to/extending-openapi.md index bdf4eeba9..dab3e5868 100644 --- a/docs/fr/docs/how-to/extending-openapi.md +++ b/docs/fr/docs/how-to/extending-openapi.md @@ -25,9 +25,17 @@ Et cette fonction `get_openapi()` reçoit comme paramètres : * `openapi_version` : La version de la spécification OpenAPI utilisée. Par défaut, la plus récente : `3.1.0`. * `summary` : Un court résumé de l'API. * `description` : La description de votre API ; elle peut inclure du markdown et sera affichée dans la documentation. -* `routes` : Une liste de routes ; chacune correspond à un *chemin d'accès* enregistré. Elles sont extraites de `app.routes`. +* `routes` : Les routes de l'application, extraites de `app.routes`. FastAPI les utilise pour collecter les *chemins d'accès* enregistrés, y compris ceux provenant des routeurs inclus. -/// info +/// tip | Détails techniques + +`app.routes` est un arbre de routes de plus bas niveau. Il peut inclure des routes candidates que FastAPI utilise en interne pour les routeurs inclus, et pas uniquement des objets `APIRoute` finaux. + +Vous pouvez néanmoins passer `app.routes` à `get_openapi()`. FastAPI parcourra cet arbre de routes pour collecter les chemins d'accès effectifs. + +/// + +/// note | Remarque Le paramètre `summary` est disponible à partir d'OpenAPI 3.1.0, pris en charge par FastAPI 0.99.0 et versions ultérieures. diff --git a/docs/fr/docs/how-to/graphql.md b/docs/fr/docs/how-to/graphql.md index 912608a98..10fa6be8a 100644 --- a/docs/fr/docs/how-to/graphql.md +++ b/docs/fr/docs/how-to/graphql.md @@ -19,9 +19,9 @@ Assurez-vous d'évaluer si les **bénéfices** pour votre cas d'utilisation comp Voici quelques bibliothèques **GraphQL** qui prennent en charge **ASGI**. Vous pouvez les utiliser avec **FastAPI** : * [Strawberry](https://strawberry.rocks/) 🍓 - * Avec [la documentation pour FastAPI](https://strawberry.rocks/docs/integrations/fastapi) + * Avec [les documents pour FastAPI](https://strawberry.rocks/docs/integrations/fastapi) * [Ariadne](https://ariadnegraphql.org/) - * Avec [la documentation pour FastAPI](https://ariadnegraphql.org/docs/fastapi-integration) + * Avec [les documents pour FastAPI](https://ariadnegraphql.org/docs/fastapi-integration) * [Tartiflette](https://tartiflette.io/) * Avec [Tartiflette ASGI](https://tartiflette.github.io/tartiflette-asgi/) pour fournir l'intégration ASGI * [Graphene](https://graphene-python.org/) @@ -39,7 +39,7 @@ Voici un petit aperçu de la manière dont vous pouvez intégrer Strawberry avec Vous pouvez en apprendre davantage sur Strawberry dans la [documentation de Strawberry](https://strawberry.rocks/). -Et également la documentation sur [Strawberry avec FastAPI](https://strawberry.rocks/docs/integrations/fastapi). +Et également les documents sur [Strawberry avec FastAPI](https://strawberry.rocks/docs/integrations/fastapi). ## Ancien `GraphQLApp` de Starlette { #older-graphqlapp-from-starlette } diff --git a/docs/fr/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md b/docs/fr/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md index 99d68ba81..48d4b3f2e 100644 --- a/docs/fr/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md +++ b/docs/fr/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md @@ -8,6 +8,8 @@ FastAPI version 0.119.0 a introduit une prise en charge partielle de Pydantic v1 FastAPI 0.126.0 a supprimé la prise en charge de Pydantic v1, tout en continuant à prendre en charge `pydantic.v1` pendant un certain temps. +FastAPI 0.128.0 a également supprimé la prise en charge de `pydantic.v1`, donc les dernières versions de FastAPI nécessitent Pydantic v2. + /// warning | Alertes L'équipe Pydantic a arrêté la prise en charge de Pydantic v1 pour les dernières versions de Python, à partir de **Python 3.14**. @@ -54,6 +56,16 @@ Cela signifie que vous pouvez installer la dernière version de Pydantic v2 et i ### Prise en charge de FastAPI pour Pydantic v1 dans v2 { #fastapi-support-for-pydantic-v1-in-v2 } +/// warning | Alertes + +Cette prise en charge FastAPI des modèles `pydantic.v1` a été ajoutée dans **FastAPI 0.119.0** et supprimée dans **FastAPI 0.128.0**. Elle était destinée à être une aide temporaire pour la migration vers Pydantic v2. + +Dans les versions actuelles de FastAPI, l'utilisation d'un modèle `pydantic.v1` dans votre application lèvera une erreur. + +Le reste de cette section décrit la prise en charge temporaire disponible uniquement dans ces anciennes versions. + +/// + Depuis FastAPI 0.119.0, il existe également une prise en charge partielle de Pydantic v1 depuis l'intérieur de Pydantic v2, pour faciliter la migration vers v2. Vous pouvez donc mettre à niveau Pydantic vers la dernière version 2 et modifier les imports pour utiliser le sous-module `pydantic.v1`, et dans de nombreux cas cela fonctionnera tel quel. @@ -122,6 +134,12 @@ Si vous devez utiliser certains des outils spécifiques à FastAPI pour les para ### Migrer par étapes { #migrate-in-steps } +/// warning | Alertes + +La migration progressive utilisant à la fois des modèles Pydantic v1 et v2 dans la même application décrite ci-dessous ne fonctionne que dans **FastAPI 0.119.0 à 0.127.x**. Elle a été supprimée dans **FastAPI 0.128.0**, les dernières versions nécessitent des modèles **Pydantic v2**. + +/// + /// tip | Astuce Essayez d'abord avec `bump-pydantic` ; si vos tests passent et que cela fonctionne, vous avez tout terminé en une seule commande. ✨ diff --git a/docs/fr/docs/how-to/separate-openapi-schemas.md b/docs/fr/docs/how-to/separate-openapi-schemas.md index fd767d738..4cb92c1df 100644 --- a/docs/fr/docs/how-to/separate-openapi-schemas.md +++ b/docs/fr/docs/how-to/separate-openapi-schemas.md @@ -34,7 +34,7 @@ Mais si vous utilisez le même modèle en sortie, comme ici : {* ../../docs_src/separate_openapi_schemas/tutorial001_py310.py hl[19] *} -... alors, comme `description` a une valeur par défaut, si vous ne retournez rien pour ce champ, il aura tout de même cette **valeur par défaut**. +... alors, comme `description` a une valeur par défaut, si vous **ne retournez rien** pour ce champ, il aura tout de même cette **valeur par défaut**. ### Modèle pour les données de réponse en sortie { #model-for-output-response-data } @@ -52,8 +52,8 @@ La manière de décrire cela dans OpenAPI est de marquer ce champ comme **requis Pour cette raison, le schéma JSON d'un modèle peut être différent selon qu'il est utilisé pour **l'entrée ou la sortie** : -- pour **l'entrée**, `description` ne sera **pas requis** -- pour **la sortie**, il sera **requis** (et éventuellement `None`, ou en termes JSON, `null`) +* pour **l'entrée**, `description` ne sera **pas requis** +* pour **la sortie**, il sera **requis** (et éventuellement `None`, ou en termes JSON, `null`) ### Modèle de sortie dans les documents { #model-for-output-in-docs } @@ -79,13 +79,13 @@ Avec cette fonctionnalité de **Pydantic v2**, la documentation de votre API est ## Ne pas séparer les schémas { #do-not-separate-schemas } -Il existe des cas où vous pourriez vouloir avoir le **même schéma pour l'entrée et la sortie**. +Maintenant, il existe des cas où vous pourriez vouloir avoir le **même schéma pour l'entrée et la sortie**. Le cas d'usage principal est probablement que vous avez déjà du code client/SDKs générés automatiquement et que vous ne souhaitez pas encore mettre à jour tout ce code client/ces SDKs générés automatiquement ; vous le ferez sans doute à un moment donné, mais peut‑être pas tout de suite. Dans ce cas, vous pouvez désactiver cette fonctionnalité dans **FastAPI**, avec le paramètre `separate_input_output_schemas=False`. -/// info | info +/// note | Remarque La prise en charge de `separate_input_output_schemas` a été ajoutée dans FastAPI `0.102.0`. 🤓 @@ -95,7 +95,7 @@ La prise en charge de `separate_input_output_schemas` a été ajoutée dans Fast ### Utiliser le même schéma pour les modèles d'entrée et de sortie dans les documents { #same-schema-for-input-and-output-models-in-docs } -Désormais, il n'y aura qu'un seul schéma pour l'entrée et la sortie du modèle, uniquement `Item`, et `description` ne sera pas requis : +Désormais, il n'y aura qu'un seul schéma pour l'entrée et la sortie du modèle, uniquement `Item`, et `description` sera **non requis** :
diff --git a/docs/fr/docs/index.md b/docs/fr/docs/index.md index 4c5bea3e4..ccc00236a 100644 --- a/docs/fr/docs/index.md +++ b/docs/fr/docs/index.md @@ -45,7 +45,7 @@ Les principales fonctionnalités sont : * **Rapide** : très hautes performances, au niveau de **NodeJS** et **Go** (grâce à Starlette et Pydantic). [L'un des frameworks Python les plus rapides](#performance). * **Rapide à coder** : augmente la vitesse de développement des fonctionnalités d'environ 200 % à 300 %. * * **Moins de bugs** : réduit d'environ 40 % les erreurs induites par le développeur. * -* **Intuitif** : excellente compatibilité avec les éditeurs. Autocomplétion partout. Moins de temps passé à déboguer. +* **Intuitif** : excellente compatibilité avec les éditeurs. Autocomplétion partout. Moins de temps passé à déboguer. * **Facile** : conçu pour être facile à utiliser et à apprendre. Moins de temps passé à lire les documents. * **Concis** : diminue la duplication de code. Plusieurs fonctionnalités à partir de chaque déclaration de paramètre. Moins de bugs. * **Robuste** : obtenez un code prêt pour la production. Avec une documentation interactive automatique. @@ -143,7 +143,7 @@ Les principales fonctionnalités sont : --- -« _Si quelqu’un cherche à construire une API Python de production, je recommande vivement **FastAPI**. Il est **magnifiquement conçu**, **simple à utiliser** et **hautement scalable** — il est devenu un **composant clé** de notre stratégie de développement API-first._ » +« _Si quelqu’un cherche à construire une API Python de production, je recommande vivement **FastAPI**. Il est **magnifiquement conçu**, **simple à utiliser** et **hautement scalable**, il est devenu un **composant clé** de notre stratégie de développement API-first et alimente de nombreuses automatisations et services tels que notre Virtual TAC Engineer._ »
Deon Pillsbury - Cisco (ref)
@@ -192,7 +192,7 @@ $ pip install "fastapi[standard]"
-**Remarque** : Vous devez vous assurer de mettre « fastapi[standard] » entre guillemets pour garantir que cela fonctionne dans tous les terminaux. +**Remarque** : Vous devez vous assurer de mettre `"fastapi[standard]"` entre guillemets pour garantir que cela fonctionne dans tous les terminaux. ## Exemple { #example } @@ -239,7 +239,7 @@ async def read_item(item_id: int, q: str | None = None): **Remarque** : -Si vous ne savez pas, consultez la section « Vous êtes pressés ? » à propos de [`async` et `await` dans la documentation](https://fastapi.tiangolo.com/fr/async/#in-a-hurry). +Si vous ne savez pas, consultez la section « Vous êtes pressés ? » à propos de [`async` et `await` dans les documents](https://fastapi.tiangolo.com/fr/async/#in-a-hurry). @@ -492,9 +492,7 @@ Pour un exemple plus complet comprenant plus de fonctionnalités, voir le @@ -510,6 +508,8 @@ Deploying to FastAPI Cloud...
+La CLI détectera automatiquement votre application FastAPI et la déploiera dans le cloud. Si vous n'êtes pas connecté, votre navigateur s'ouvrira pour terminer le processus d'authentification. + C'est tout ! Vous pouvez maintenant accéder à votre application à cette URL. ✨ #### À propos de FastAPI Cloud { #about-fastapi-cloud } diff --git a/docs/fr/docs/project-generation.md b/docs/fr/docs/project-generation.md index e0636bfe5..b1f3f6cc4 100644 --- a/docs/fr/docs/project-generation.md +++ b/docs/fr/docs/project-generation.md @@ -1,5 +1,6 @@ # Modèle Full Stack FastAPI { #full-stack-fastapi-template } + Les modèles, bien qu'ils soient généralement livrés avec une configuration spécifique, sont conçus pour être flexibles et personnalisables. Cela vous permet de les modifier et de les adapter aux exigences de votre projet, ce qui en fait un excellent point de départ. 🏁 Vous pouvez utiliser ce modèle pour démarrer, car il inclut une grande partie de la configuration initiale, la sécurité, la base de données et quelques endpoints d'API déjà prêts pour vous. diff --git a/docs/fr/docs/python-types.md b/docs/fr/docs/python-types.md index 55bc8bdc9..8e9dbc598 100644 --- a/docs/fr/docs/python-types.md +++ b/docs/fr/docs/python-types.md @@ -44,7 +44,7 @@ C'est un programme très simple. Mais maintenant imaginez que vous l'écriviez de zéro. -À un certain moment, vous auriez commencé la définition de la fonction, vous aviez les paramètres prêts ... +À un moment donné, vous commencez à définir la fonction, et vous avez les paramètres prêts ... Mais ensuite vous devez appeler « cette méthode qui convertit la première lettre en majuscule ». @@ -279,13 +279,13 @@ Ensuite, vous créez une instance de cette classe avec certaines valeurs et elle Et vous obtenez tout le support de l'éditeur avec cet objet résultant. -Un exemple tiré de la documentation officielle de Pydantic : +Un exemple tiré des documents officiels de Pydantic : {* ../../docs_src/python_types/tutorial011_py310.py *} /// note | Remarque -Pour en savoir plus à propos de [Pydantic, consultez sa documentation](https://docs.pydantic.dev/). +Pour en savoir plus à propos de [Pydantic, consultez ses documents](https://docs.pydantic.dev/). /// @@ -305,7 +305,7 @@ Python lui-même ne fait rien avec ce `Annotated`. Et pour les éditeurs et autr Mais vous pouvez utiliser cet espace dans `Annotated` pour fournir à **FastAPI** des métadonnées supplémentaires sur la façon dont vous voulez que votre application se comporte. -L'important à retenir est que **le premier « paramètre de type »** que vous passez à `Annotated` est le **type réel**. Le reste n'est que des métadonnées pour d'autres outils. +L'important à retenir est que **le premier *paramètre de type*** que vous passez à `Annotated` est le **type réel**. Le reste n'est que des métadonnées pour d'autres outils. Pour l'instant, vous avez juste besoin de savoir que `Annotated` existe, et que c'est du Python standard. 😎 diff --git a/docs/fr/docs/tutorial/bigger-applications.md b/docs/fr/docs/tutorial/bigger-applications.md index d5e1bb567..92976bca0 100644 --- a/docs/fr/docs/tutorial/bigger-applications.md +++ b/docs/fr/docs/tutorial/bigger-applications.md @@ -17,16 +17,16 @@ Supposons que vous ayez une structure de fichiers comme ceci : ``` . ├── app -│   ├── __init__.py -│   ├── main.py -│   ├── dependencies.py -│   └── routers -│   │ ├── __init__.py -│   │ ├── items.py -│   │ └── users.py -│   └── internal -│   ├── __init__.py -│   └── admin.py +│ ├── __init__.py +│ ├── main.py +│ ├── dependencies.py +│ └── routers +│ │ ├── __init__.py +│ │ ├── items.py +│ │ └── users.py +│ └── internal +│ ├── __init__.py +│ └── admin.py ``` /// tip | Astuce @@ -283,7 +283,7 @@ Mais nous pouvons toujours ajouter _davantage_ de `tags` qui seront appliqués /// tip | Astuce -Ce dernier *chemin d'accès* aura la combinaison de tags : `["items", "custom"]`. +Ce dernier chemin d'accès aura la combinaison de tags : `["items", "custom"]`. Et il aura également les deux réponses dans la documentation, une pour `404` et une pour `403`. @@ -396,9 +396,9 @@ Cela inclura toutes les routes de ce routeur comme faisant partie de l'applicati /// note | Détails techniques -En interne, cela créera en fait un *chemin d'accès* pour chaque *chemin d'accès* qui a été déclaré dans le `APIRouter`. +FastAPI conserve le `APIRouter` original et ses `APIRoute` actifs lorsque le routeur est inclus dans l'application principale. -Donc, en coulisses, cela fonctionnera comme si tout faisait partie d'une seule et même application. +Cela signifie que des sous-classes personnalisées de `APIRouter` et `APIRoute` peuvent toujours intervenir après l'inclusion du routeur. /// @@ -406,7 +406,7 @@ Donc, en coulisses, cela fonctionnera comme si tout faisait partie d'une seule e Vous n'avez pas à vous soucier de la performance lors de l'inclusion de routeurs. -Cela prendra des microsecondes et ne se produira qu'au démarrage. +C'est conçu pour être léger et pour éviter d'ajouter une surcharge à chaque requête. Donc cela n'affectera pas la performance. ⚡ @@ -453,7 +453,7 @@ et cela fonctionnera correctement, avec tous les autres *chemins d'accès* ajout /// note | Détails très techniques -Note : c'est un détail très technique que vous pouvez probablement **simplement ignorer**. +**Remarque** : c'est un détail très technique que vous pouvez probablement **simplement ignorer**. --- @@ -461,7 +461,7 @@ Les `APIRouter` ne sont pas « montés », ils ne sont pas isolés du reste de l C'est parce que nous voulons inclure leurs *chemins d'accès* dans le schéma OpenAPI et les interfaces utilisateur. -Comme nous ne pouvons pas simplement les isoler et les « monter » indépendamment du reste, les *chemins d'accès* sont « clonés » (recréés), pas inclus directement. +FastAPI conserve les routeurs et chemins d'accès originaux actifs, et combine les préfixes de routeur, dépendances, tags, réponses et autres métadonnées lors du traitement des requêtes et de la génération d'OpenAPI. /// @@ -482,7 +482,7 @@ from app.main import app De cette façon, la commande `fastapi` saura où trouver votre app. -/// note | Remarque +/// Note | Remarque Vous pourriez aussi passer le chemin à la commande, comme : @@ -490,13 +490,13 @@ Vous pourriez aussi passer le chemin à la commande, comme : $ fastapi dev app/main.py ``` -Mais vous devriez vous rappeler de passer le bon chemin à chaque fois que vous appelez la commande `fastapi`. +Mais vous devez vous rappeler de passer le bon chemin à chaque fois que vous appelez la commande `fastapi`. En outre, d'autres outils pourraient ne pas être en mesure de la trouver, par exemple l'[Extension VS Code](../editor-support.md) ou [FastAPI Cloud](https://fastapicloud.com), il est donc recommandé d'utiliser l'`entrypoint` dans `pyproject.toml`. /// -## Consulter la documentation API automatique { #check-the-automatic-api-docs } +## Consulter les documents d'API automatiques { #check-the-automatic-api-docs } Maintenant, exécutez votre application : @@ -512,7 +512,7 @@ $ fastapi dev Et ouvrez les documents à [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs). -Vous verrez la documentation API automatique, incluant les chemins de tous les sous-modules, utilisant les bons chemins (et préfixes) et les bons tags : +Vous verrez les documents d'API automatiques, incluant les chemins de tous les sous-modules, utilisant les bons chemins (et préfixes) et les bons tags : @@ -532,4 +532,16 @@ De la même manière que vous pouvez inclure un `APIRouter` dans une application router.include_router(other_router) ``` -Vous devez vous assurer de le faire avant d'inclure `router` dans l'application `FastAPI`, afin que les *chemins d'accès* de `other_router` soient également inclus. +Vous pouvez le faire avant ou après avoir inclus `router` dans l'application `FastAPI`. FastAPI inclura quand même les *chemins d'accès* de `other_router` dans le routage et dans OpenAPI. + +Il en va de même pour les *chemins d'accès* ajoutés plus tard aux routeurs. Ils seront visibles via l'inclusion antérieure également. + +/// warning | Détails techniques + +Évitez de modifier directement `router.routes` après avoir inclus un routeur. FastAPI considère l'inclusion d'un routeur comme « en direct », de sorte que le routeur original et ses routes restent utilisés pour le routage et la génération d'OpenAPI. + +Utilisez les API documentées comme les décorateurs de *chemin d'accès* et `.include_router()` pour ajouter des routes et des routeurs. + +Considérez `router.routes` comme un arbre de routes de plus bas niveau pouvant contenir des définitions de routes et des routeurs inclus, et évitez de vous y fier comme à une liste plate de *chemins d'accès* finaux. + +/// diff --git a/docs/fr/docs/tutorial/body-multiple-params.md b/docs/fr/docs/tutorial/body-multiple-params.md index 1c1ab0fca..d8d1af94f 100644 --- a/docs/fr/docs/tutorial/body-multiple-params.md +++ b/docs/fr/docs/tutorial/body-multiple-params.md @@ -108,7 +108,7 @@ Par exemple : {* ../../docs_src/body_multiple_params/tutorial004_an_py310.py hl[28] *} -/// info +/// note | Remarque `Body` possède également les mêmes paramètres supplémentaires de validation et de métadonnées que `Query`, `Path` et d'autres que vous verrez plus tard. @@ -123,7 +123,7 @@ Par défaut, **FastAPI** attendra alors son contenu directement. Mais si vous voulez qu'il attende un JSON avec une clé `item` contenant le contenu du modèle, comme lorsqu'on déclare des paramètres supplémentaires du corps de la requête, vous pouvez utiliser le paramètre spécial `embed` de `Body` : ```Python -item: Item = Body(embed=True) +item: Annotated[Item, Body(embed=True)] ``` comme dans : diff --git a/docs/fr/docs/tutorial/body-nested-models.md b/docs/fr/docs/tutorial/body-nested-models.md index 2d4064310..051317a8c 100644 --- a/docs/fr/docs/tutorial/body-nested-models.md +++ b/docs/fr/docs/tutorial/body-nested-models.md @@ -1,6 +1,6 @@ # Corps - Modèles imbriqués { #body-nested-models } -Avec FastAPI, vous pouvez définir, valider, documenter et utiliser des modèles imbriqués à n'importe quelle profondeur (grâce à Pydantic). +Avec **FastAPI**, vous pouvez définir, valider, documenter et utiliser des modèles imbriqués à n'importe quelle profondeur (grâce à Pydantic). ## Déclarer des champs de liste { #list-fields } @@ -69,7 +69,7 @@ Nous pouvons ensuite l'utiliser comme type d'un attribut : {* ../../docs_src/body_nested_models/tutorial004_py310.py hl[18] *} -Cela signifie que FastAPI attendrait un corps similaire à : +Cela signifie que **FastAPI** attendrait un corps similaire à : ```JSON { @@ -85,7 +85,7 @@ Cela signifie que FastAPI attendrait un corps similaire à : } ``` -Là encore, avec cette simple déclaration, avec FastAPI vous obtenez : +Là encore, avec cette simple déclaration, avec **FastAPI** vous obtenez : - Prise en charge par l'éditeur (autocomplétion, etc.), même pour les modèles imbriqués - Conversion des données @@ -135,7 +135,7 @@ Cela attendra (convertira, validera, documentera, etc.) un corps JSON comme : ] } ``` -/// info +/// note | Remarque Remarquez que la clé `images` contient maintenant une liste d'objets image. @@ -147,7 +147,7 @@ Vous pouvez définir des modèles imbriqués à une profondeur arbitraire : {* ../../docs_src/body_nested_models/tutorial007_py310.py hl[7,12,18,21,25] *} -/// info +/// note | Remarque Remarquez que `Offer` a une liste d’`Item`, qui à leur tour ont une liste optionnelle d’`Image`. @@ -209,7 +209,7 @@ Et le `dict` que vous recevez dans `weights` aura en réalité des clés `int` e ## Récapitulatif { #recap } -Avec FastAPI, vous bénéficiez de la flexibilité maximale fournie par les modèles Pydantic, tout en gardant votre code simple, concis et élégant. +Avec **FastAPI**, vous bénéficiez de la flexibilité maximale fournie par les modèles Pydantic, tout en gardant votre code simple, concis et élégant. Mais avec tous les avantages : diff --git a/docs/fr/docs/tutorial/body.md b/docs/fr/docs/tutorial/body.md index 6a9466798..2ff716125 100644 --- a/docs/fr/docs/tutorial/body.md +++ b/docs/fr/docs/tutorial/body.md @@ -1,18 +1,18 @@ # Corps de la requête { #request-body } -Quand vous avez besoin d'envoyer de la donnée depuis un client (comme un navigateur) vers votre API, vous l'envoyez en tant que **corps de requête**. +Quand vous avez besoin d'envoyer de la donnée depuis un client (comme un navigateur) vers votre API, vous l'envoyez en tant que **corps de la requête**. Le corps d'une **requête** est de la donnée envoyée par le client à votre API. Le corps d'une **réponse** est la donnée envoyée par votre API au client. -Votre API aura presque toujours à envoyer un corps de **réponse**. Mais un client n'a pas toujours à envoyer un **corps de requête** : parfois il demande seulement un chemin, peut-être avec quelques paramètres de requête, mais n'envoie pas de corps. +Votre API aura presque toujours à envoyer un corps de **réponse**. Mais un client n'a pas toujours à envoyer un **corps de la requête** : parfois il demande seulement un chemin, peut-être avec quelques paramètres de requête, mais n'envoie pas de corps. Pour déclarer un corps de **requête**, on utilise les modèles de [Pydantic](https://docs.pydantic.dev/) en profitant de tous leurs avantages et fonctionnalités. -/// info +/// note | Remarque -Pour envoyer de la donnée, vous devez utiliser : `POST` (le plus populaire), `PUT`, `DELETE` ou `PATCH`. +Pour envoyer de la donnée, vous devez utiliser l'une de ces méthodes : `POST` (le plus populaire), `PUT`, `DELETE` ou `PATCH`. -Envoyer un corps dans une requête `GET` a un comportement non défini dans les spécifications, cela est néanmoins supporté par **FastAPI**, seulement pour des cas d'utilisation très complexes/extrêmes. +Envoyer un corps dans une requête `GET` a un comportement non défini dans les spécifications, cela est néanmoins supporté par FastAPI, seulement pour des cas d'utilisation très complexes/extrêmes. Ceci étant découragé, la documentation interactive générée par Swagger UI ne montrera pas de documentation pour le corps d'une requête `GET`, et les proxys intermédiaires risquent de ne pas le supporter. @@ -32,6 +32,7 @@ Utilisez les types Python standard pour tous les attributs : {* ../../docs_src/body/tutorial001_py310.py hl[5:9] *} + Tout comme pour la déclaration de paramètres de requête, quand un attribut de modèle a une valeur par défaut, il n'est pas nécessaire. Sinon, il est requis. Utilisez `None` pour le rendre simplement optionnel. Par exemple, le modèle ci-dessus déclare un JSON « `object` » (ou `dict` Python) tel que : @@ -73,7 +74,7 @@ En utilisant uniquement les déclarations de type Python, **FastAPI** réussit * Passer la donnée reçue dans le paramètre `item`. * Ce paramètre ayant été déclaré dans la fonction comme étant de type `Item`, vous aurez aussi tout le support offert par l'éditeur (autocomplétion, etc.) pour tous les attributs de ce paramètre et les types de ces attributs. * Générer des définitions [JSON Schema](https://json-schema.org) pour votre modèle ; vous pouvez également les utiliser partout ailleurs si cela a du sens pour votre projet. -* Ces schémas participeront à la constitution du schéma généré OpenAPI, et seront utilisés par les documentations automatiques UIs. +* Ces schémas feront partie du schéma OpenAPI généré, et seront utilisés par les UIs de la documentation automatique. ## Documentation automatique { #automatic-docs } @@ -97,11 +98,11 @@ Et vous obtenez aussi des vérifications d'erreurs pour les opérations de types Ce n'est pas un hasard, ce framework entier a été bâti avec ce design comme objectif. -Et cela a été rigoureusement testé durant la phase de design, avant toute implémentation, pour vous assurer que cela fonctionnerait avec tous les éditeurs. +Et cela a été rigoureusement testé durant la phase de design, avant toute implémentation, pour s'assurer que cela fonctionnerait avec tous les éditeurs. Des changements sur Pydantic ont même été faits pour supporter cela. -Les captures d'écran précédentes ont été prises sur [Visual Studio Code](https://code.visualstudio.com). +Les captures d'écran précédentes ont été prises avec [Visual Studio Code](https://code.visualstudio.com). Mais vous auriez le même support de l'éditeur avec [PyCharm](https://www.jetbrains.com/pycharm/) et la majorité des autres éditeurs de code Python : @@ -129,15 +130,16 @@ Dans la fonction, vous pouvez accéder à tous les attributs de l'objet du modè ## Corps de la requête + paramètres de chemin { #request-body-path-parameters } -Vous pouvez déclarer des paramètres de chemin et un corps de requête pour la même *chemin d'accès*. +Vous pouvez déclarer des paramètres de chemin et le corps de la requête en même temps. -**FastAPI** est capable de reconnaître que les paramètres de la fonction qui correspondent aux paramètres de chemin doivent être **récupérés depuis le chemin**, et que les paramètres de fonctions déclarés comme modèles Pydantic devraient être **récupérés depuis le corps de la requête**. +**FastAPI** est capable de reconnaître que les paramètres de la fonction qui correspondent aux paramètres de chemin doivent être **récupérés depuis le chemin**, et que les paramètres de la fonction déclarés comme modèles Pydantic devraient être **récupérés depuis le corps de la requête**. {* ../../docs_src/body/tutorial003_py310.py hl[15:16] *} + ## Corps de la requête + paramètres de chemin et de requête { #request-body-path-query-parameters } -Vous pouvez aussi déclarer un **corps**, et des paramètres de **chemin** et de **requête** dans la même *chemin d'accès*. +Vous pouvez aussi déclarer un **corps**, et des paramètres de **chemin** et de **requête**, tous en même temps. **FastAPI** saura reconnaître chacun d'entre eux et récupérer la bonne donnée au bon endroit. @@ -151,9 +153,9 @@ Les paramètres de la fonction seront reconnus comme tel : /// note | Remarque -**FastAPI** saura que la valeur de `q` n'est pas requise grâce à la valeur par défaut `= None`. +FastAPI saura que la valeur de `q` n'est pas requise grâce à la valeur par défaut `= None`. -L'annotation de type `str | None` n'est pas utilisée par **FastAPI** pour déterminer que la valeur n'est pas requise, il le saura parce qu'elle a une valeur par défaut `= None`. +L'annotation de type `str | None` n'est pas utilisée par FastAPI pour déterminer que la valeur n'est pas requise, il le saura parce qu'elle a une valeur par défaut `= None`. Mais ajouter ces annotations de type permettra à votre éditeur de vous offrir un meilleur support et de détecter des erreurs. diff --git a/docs/fr/docs/tutorial/cookie-param-models.md b/docs/fr/docs/tutorial/cookie-param-models.md index c6fc2f826..2b8edbab7 100644 --- a/docs/fr/docs/tutorial/cookie-param-models.md +++ b/docs/fr/docs/tutorial/cookie-param-models.md @@ -32,7 +32,7 @@ Vous pouvez voir les cookies définis dans l'interface de la documentation à `/
-/// info +/// note | Remarque Gardez à l'esprit que, comme les **navigateurs gèrent les cookies** de manière particulière et en arrière-plan, ils **n'autorisent pas** facilement **JavaScript** à y accéder. diff --git a/docs/fr/docs/tutorial/cookie-params.md b/docs/fr/docs/tutorial/cookie-params.md index 8f77d35dc..1d3801219 100644 --- a/docs/fr/docs/tutorial/cookie-params.md +++ b/docs/fr/docs/tutorial/cookie-params.md @@ -24,13 +24,13 @@ Mais rappelez-vous que lorsque vous importez `Query`, `Path`, `Cookie` et d'autr /// -/// info +/// note | Remarque Pour déclarer des cookies, vous devez utiliser `Cookie`, sinon les paramètres seraient interprétés comme des paramètres de requête. /// -/// info +/// note | Remarque Gardez à l'esprit que, comme **les navigateurs gèrent les cookies** de manière particulière et en coulisses, ils **n'autorisent pas** facilement **JavaScript** à y accéder. diff --git a/docs/fr/docs/tutorial/debugging.md b/docs/fr/docs/tutorial/debugging.md index 6452b43fa..cdcfe702e 100644 --- a/docs/fr/docs/tutorial/debugging.md +++ b/docs/fr/docs/tutorial/debugging.md @@ -72,9 +72,9 @@ Ainsi, la ligne : ne sera pas exécutée. -/// info +/// note | Remarque -Pour plus d'informations, consultez [la documentation officielle de Python](https://docs.python.org/3/library/__main__.html). +Pour plus d'informations, consultez [les documents officiels de Python](https://docs.python.org/3/library/__main__.html). /// @@ -86,10 +86,10 @@ Parce que vous exécutez le serveur Uvicorn directement depuis votre code, vous Par exemple, dans Visual Studio Code, vous pouvez : -- Allez dans le panneau « Debug ». -- « Add configuration ... ». -- Sélectionnez « Python ». -- Lancez le débogueur avec l'option « Python: Current File (Integrated Terminal) ». +* Allez dans le panneau « Debug ». +* « Add configuration... ». +* Sélectionnez « Python ». +* Lancez le débogueur avec l'option « `Python: Current File (Integrated Terminal)` ». Il démarrera alors le serveur avec votre code **FastAPI**, s'arrêtera à vos points d'arrêt, etc. @@ -99,12 +99,12 @@ Voici à quoi cela pourrait ressembler : --- -Si vous utilisez Pycharm, vous pouvez : +Si vous utilisez PyCharm, vous pouvez : -- Ouvrez le menu « Run ». -- Sélectionnez l'option « Debug ... ». -- Un menu contextuel s'affiche alors. -- Sélectionnez le fichier à déboguer (dans ce cas, `main.py`). +* Ouvrez le menu « Run ». +* Sélectionnez l'option « Debug... ». +* Un menu contextuel s'affiche alors. +* Sélectionnez le fichier à déboguer (dans ce cas, `main.py`). Il démarrera alors le serveur avec votre code **FastAPI**, s'arrêtera à vos points d'arrêt, etc. diff --git a/docs/fr/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md b/docs/fr/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md index b32728a30..ce3c7923e 100644 --- a/docs/fr/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md +++ b/docs/fr/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md @@ -28,7 +28,7 @@ Cela peut également éviter toute confusion pour les nouveaux développeurs qui /// -/// info | Info +/// note | Remarque Dans cet exemple, nous utilisons des en-têtes personnalisés fictifs `X-Key` et `X-Token`. diff --git a/docs/fr/docs/tutorial/dependencies/dependencies-with-yield.md b/docs/fr/docs/tutorial/dependencies/dependencies-with-yield.md index 53d4ae4cf..23114c0cb 100644 --- a/docs/fr/docs/tutorial/dependencies/dependencies-with-yield.md +++ b/docs/fr/docs/tutorial/dependencies/dependencies-with-yield.md @@ -1,6 +1,6 @@ # Utiliser des dépendances avec `yield` { #dependencies-with-yield } -FastAPI prend en charge des dépendances qui effectuent des étapes supplémentaires après l'exécution. +FastAPI prend en charge des dépendances qui effectuent des étapes supplémentaires après l'exécution. Pour cela, utilisez `yield` au lieu de `return`, et écrivez les étapes supplémentaires (code) après. @@ -170,7 +170,7 @@ participant tasks as Background tasks end ``` -/// info +/// note | Remarque Une **seule réponse** sera envoyée au client. Il peut s'agir d'une des réponses d'erreur ou de la réponse provenant du *chemin d'accès*. @@ -194,16 +194,16 @@ Mais si vous savez que vous n'aurez pas besoin d'utiliser la dépendance après `Depends()` reçoit un paramètre `scope` qui peut être : -* « function » : démarrer la dépendance avant la *fonction de chemin d'accès* qui gère la requête, terminer la dépendance après la fin de la *fonction de chemin d'accès*, mais **avant** que la réponse ne soit renvoyée au client. Ainsi, la fonction de dépendance sera exécutée **autour** de la *fonction de chemin d'accès*. -* « request » : démarrer la dépendance avant la *fonction de chemin d'accès* qui gère la requête (similaire à l'utilisation de « function »), mais terminer **après** que la réponse a été renvoyée au client. Ainsi, la fonction de dépendance sera exécutée **autour** du cycle **requête** et réponse. +* `"function"` : démarrer la dépendance avant la *fonction de chemin d'accès* qui gère la requête, terminer la dépendance après la fin de la *fonction de chemin d'accès*, mais **avant** que la réponse ne soit renvoyée au client. Ainsi, la fonction de dépendance sera exécutée **autour** de la *fonction de chemin d'accès*. +* `"request"` : démarrer la dépendance avant la *fonction de chemin d'accès* qui gère la requête (similaire à l'utilisation de `"function"`), mais terminer **après** que la réponse a été renvoyée au client. Ainsi, la fonction de dépendance sera exécutée **autour** du cycle **requête** et réponse. -S'il n'est pas spécifié et que la dépendance utilise `yield`, le `scope` sera par défaut « request ». +S'il n'est pas spécifié et que la dépendance utilise `yield`, le `scope` sera par défaut `"request"`. ### Définir `scope` pour les sous-dépendances { #scope-for-sub-dependencies } -Lorsque vous déclarez une dépendance avec un `scope="request"` (par défaut), toute sous-dépendance doit également avoir un `scope` de « request ». +Lorsque vous déclarez une dépendance avec un `scope="request"` (par défaut), toute sous-dépendance doit également avoir un `scope` de `"request"`. -Mais une dépendance avec un `scope` de « function » peut avoir des dépendances avec un `scope` de « function » et un `scope` de « request ». +Mais une dépendance avec un `scope` de `"function"` peut avoir des dépendances avec un `scope` de `"function"` et un `scope` de `"request"`. Cela vient du fait que toute dépendance doit pouvoir exécuter son code de sortie avant ses sous-dépendances, car elle pourrait encore avoir besoin de les utiliser pendant son code de sortie. @@ -234,6 +234,7 @@ participant operation as Path Operation Les dépendances avec `yield` ont évolué au fil du temps pour couvrir différents cas d'utilisation et corriger certains problèmes. Si vous souhaitez voir ce qui a changé dans différentes versions de FastAPI, vous pouvez en savoir plus dans le guide avancé, dans [Dépendances avancées - Dépendances avec `yield`, `HTTPException`, `except` et Background Tasks](../../advanced/advanced-dependencies.md#dependencies-with-yield-httpexception-except-and-background-tasks). + ## Gestionnaires de contexte { #context-managers } ### Que sont les « Context Managers » { #what-are-context-managers } diff --git a/docs/fr/docs/tutorial/dependencies/index.md b/docs/fr/docs/tutorial/dependencies/index.md index 03eea57e3..84b4b70b6 100644 --- a/docs/fr/docs/tutorial/dependencies/index.md +++ b/docs/fr/docs/tutorial/dependencies/index.md @@ -6,7 +6,7 @@ Il est conçu pour être très simple à utiliser, et pour faciliter l’intégr ## Qu’est-ce que « l’injection de dépendances » { #what-is-dependency-injection } -L’**« injection de dépendances »** signifie, en programmation, qu’il existe un moyen pour votre code (dans ce cas, vos fonctions de chemins d’accès) de déclarer ce dont il a besoin pour fonctionner et utiliser : « dépendances ». +L’**« injection de dépendances »** signifie, en programmation, qu’il existe un moyen pour votre code (dans ce cas, vos fonctions de chemin d’accès) de déclarer ce dont il a besoin pour fonctionner et utiliser : « dépendances ». Ensuite, ce système (dans ce cas **FastAPI**) se charge de faire tout le nécessaire pour fournir à votre code ces dépendances requises (« injecter » les dépendances). @@ -37,7 +37,7 @@ C’est tout. **2 lignes**. -Et elle a la même forme et structure que toutes vos fonctions de chemins d’accès. +Et elle a la même forme et structure que toutes vos fonctions de chemin d’accès. Vous pouvez la considérer comme une fonction de chemin d’accès sans le « décorateur » (sans le `@app.get("/some-path")`). @@ -51,7 +51,7 @@ Dans ce cas, cette dépendance attend : Puis elle retourne simplement un `dict` contenant ces valeurs. -/// info +/// note | Remarque FastAPI a ajouté la prise en charge de `Annotated` (et a commencé à le recommander) dans la version 0.95.0. @@ -79,7 +79,7 @@ Ce paramètre doit être quelque chose comme une fonction. Vous ne l’appelez pas directement (n’ajoutez pas de parenthèses à la fin), vous le passez simplement en paramètre à `Depends()`. -Et cette fonction prend des paramètres de la même manière que les fonctions de chemins d’accès. +Et cette fonction prend des paramètres de la même manière que les fonctions de chemin d’accès. /// tip | Astuce @@ -106,7 +106,7 @@ common_parameters --> read_users De cette façon vous écrivez le code partagé une seule fois et **FastAPI** se charge de l’appeler pour vos chemins d’accès. -/// check | Vérifications +/// tip | Astuce Notez que vous n’avez pas à créer une classe spéciale et à la passer quelque part à **FastAPI** pour l’« enregistrer » ou quoi que ce soit de similaire. @@ -142,11 +142,11 @@ Cela sera particulièrement utile lorsque vous l’utiliserez dans une **grande ## Utiliser `async` ou non { #to-async-or-not-to-async } -Comme les dépendances seront aussi appelées par **FastAPI** (tout comme vos fonctions de chemins d’accès), les mêmes règles s’appliquent lors de la définition de vos fonctions. +Comme les dépendances seront aussi appelées par **FastAPI** (tout comme vos fonctions de chemin d’accès), les mêmes règles s’appliquent lors de la définition de vos fonctions. Vous pouvez utiliser `async def` ou un `def` normal. -Et vous pouvez déclarer des dépendances avec `async def` à l’intérieur de fonctions de chemins d’accès `def` normales, ou des dépendances `def` à l’intérieur de fonctions de chemins d’accès `async def`, etc. +Et vous pouvez déclarer des dépendances avec `async def` à l’intérieur de fonctions de chemin d’accès `def` normales, ou des dépendances `def` à l’intérieur de fonctions de chemin d’accès `async def`, etc. Peu importe. **FastAPI** saura quoi faire. @@ -166,7 +166,7 @@ Ainsi, la documentation interactive contiendra aussi toutes les informations iss ## Utilisation simple { #simple-usage } -Si vous y regardez de près, les fonctions de chemins d’accès sont déclarées pour être utilisées chaque fois qu’un « chemin » et une « opération » correspondent, puis **FastAPI** se charge d’appeler la fonction avec les bons paramètres, en extrayant les données de la requête. +Si vous y regardez de près, les fonctions de chemin d’accès sont déclarées pour être utilisées chaque fois qu’un « chemin » et une « opération » correspondent, puis **FastAPI** se charge d’appeler la fonction avec les bons paramètres, en extrayant les données de la requête. En réalité, tous (ou la plupart) des frameworks web fonctionnent de cette manière. @@ -184,7 +184,7 @@ D’autres termes courants pour cette même idée « d’injection de dépendanc ## Plug-ins **FastAPI** { #fastapi-plug-ins } -Les intégrations et « plug-ins » peuvent être construits en utilisant le système d’**injection de dépendances**. Mais en réalité, il n’y a **pas besoin de créer des « plug-ins »**, car en utilisant des dépendances il est possible de déclarer un nombre infini d’intégrations et d’interactions qui deviennent disponibles pour vos fonctions de chemins d’accès. +Les intégrations et « plug-ins » peuvent être construits en utilisant le système d’**injection de dépendances**. Mais en réalité, il n’y a **pas besoin de créer des « plug-ins »**, car en utilisant des dépendances il est possible de déclarer un nombre infini d’intégrations et d’interactions qui deviennent disponibles pour vos fonctions de chemin d’accès. Et les dépendances peuvent être créées de manière très simple et intuitive, ce qui vous permet d’importer juste les packages Python dont vous avez besoin, et de les intégrer à vos fonctions d’API en quelques lignes de code, *littéralement*. diff --git a/docs/fr/docs/tutorial/dependencies/sub-dependencies.md b/docs/fr/docs/tutorial/dependencies/sub-dependencies.md index 473ff02ba..c1ba81630 100644 --- a/docs/fr/docs/tutorial/dependencies/sub-dependencies.md +++ b/docs/fr/docs/tutorial/dependencies/sub-dependencies.md @@ -1,8 +1,8 @@ # Sous-dépendances { #sub-dependencies } -Vous pouvez créer des dépendances qui ont des sous-dépendances. +Vous pouvez créer des dépendances qui ont des **sous-dépendances**. -Elles peuvent être aussi profondes que nécessaire. +Elles peuvent être aussi **profondes** que nécessaire. **FastAPI** se chargera de les résoudre. @@ -35,7 +35,7 @@ Nous pouvons ensuite utiliser la dépendance avec : {* ../../docs_src/dependencies/tutorial005_an_py310.py hl[23] *} -/// info +/// note | Remarque Notez que nous ne déclarons qu'une seule dépendance dans la *fonction de chemin d'accès*, `query_or_cookie_extractor`. diff --git a/docs/fr/docs/tutorial/extra-data-types.md b/docs/fr/docs/tutorial/extra-data-types.md index 7ee6816c8..c0c4df137 100644 --- a/docs/fr/docs/tutorial/extra-data-types.md +++ b/docs/fr/docs/tutorial/extra-data-types.md @@ -36,7 +36,7 @@ Voici quelques types de données supplémentaires que vous pouvez utiliser : * `datetime.timedelta` : * Un `datetime.timedelta` Python. * Dans les requêtes et les réponses, il sera représenté sous forme de `float` de secondes totales. - * Pydantic permet aussi de le représenter sous la forme d'un « encodage de différence de temps ISO 8601 », [voir la documentation pour plus d'informations](https://docs.pydantic.dev/latest/concepts/serialization/#custom-serializers). + * Pydantic permet aussi de le représenter sous la forme d'un « encodage de différence de temps ISO 8601 », [voir les documents pour plus d'informations](https://docs.pydantic.dev/latest/concepts/serialization/#custom-serializers). * `frozenset` : * Dans les requêtes et les réponses, traité de la même manière qu'un `set` : * Dans les requêtes, une liste sera lue, les doublons éliminés, puis convertie en `set`. diff --git a/docs/fr/docs/tutorial/extra-models.md b/docs/fr/docs/tutorial/extra-models.md index 24a3fa31b..7d542955b 100644 --- a/docs/fr/docs/tutorial/extra-models.md +++ b/docs/fr/docs/tutorial/extra-models.md @@ -4,9 +4,9 @@ En poursuivant l'exemple précédent, il est courant d'avoir plusieurs modèles C'est particulièrement vrai pour les modèles d'utilisateur, car : -* Le modèle d'entrée doit pouvoir contenir un mot de passe. -* Le modèle de sortie ne doit pas avoir de mot de passe. -* Le modèle de base de données devra probablement avoir un mot de passe haché. +* Le **modèle d'entrée** doit pouvoir contenir un mot de passe. +* Le **modèle de sortie** ne doit pas avoir de mot de passe. +* Le **modèle de base de données** aurait probablement besoin d'avoir un mot de passe haché. /// danger | Danger @@ -30,13 +30,13 @@ Voici une idée générale de l'apparence des modèles avec leurs champs de mot Les modèles Pydantic ont une méthode `.model_dump()` qui renvoie un `dict` avec les données du modèle. -Ainsi, si nous créons un objet Pydantic `user_in` comme : +Ainsi, si nous créons un objet Pydantic `user_in` comme : ```Python user_in = UserIn(username="john", password="secret", email="john.doe@example.com") ``` -et que nous appelons ensuite : +et que nous appelons ensuite : ```Python user_dict = user_in.model_dump() @@ -44,13 +44,13 @@ user_dict = user_in.model_dump() nous avons maintenant un `dict` avec les données dans la variable `user_dict` (c'est un `dict` au lieu d'un objet modèle Pydantic). -Et si nous appelons : +Et si nous appelons : ```Python print(user_dict) ``` -nous obtiendrions un `dict` Python contenant : +nous obtiendrions un `dict` Python contenant : ```Python { @@ -63,15 +63,15 @@ nous obtiendrions un `dict` Python contenant : #### Déballer un `dict` { #unpacking-a-dict } -Si nous prenons un `dict` comme `user_dict` et que nous le passons à une fonction (ou une classe) avec `**user_dict`, Python va « déballer » ce `dict`. Il passera les clés et valeurs de `user_dict` directement comme arguments nommés. +Si nous prenons un `dict` comme `user_dict` et que nous le passons à une fonction (ou une classe) avec `**user_dict`, Python va « déballer » ce `dict`. Il passera les clés et valeurs de `user_dict` directement comme arguments clé-valeur. -Ainsi, en reprenant `user_dict` ci-dessus, écrire : +Ainsi, en reprenant `user_dict` ci-dessus, écrire : ```Python UserInDB(**user_dict) ``` -aurait pour résultat quelque chose d'équivalent à : +aurait pour résultat quelque chose d'équivalent à : ```Python UserInDB( @@ -82,7 +82,7 @@ UserInDB( ) ``` -Ou plus exactement, en utilisant `user_dict` directement, quels que soient ses contenus futurs : +Ou plus exactement, en utilisant `user_dict` directement, quels que soient ses contenus futurs : ```Python UserInDB( @@ -95,14 +95,14 @@ UserInDB( #### Créer un modèle Pydantic à partir du contenu d'un autre { #a-pydantic-model-from-the-contents-of-another } -Comme dans l'exemple ci-dessus nous avons obtenu `user_dict` depuis `user_in.model_dump()`, ce code : +Comme dans l'exemple ci-dessus nous avons obtenu `user_dict` depuis `user_in.model_dump()`, ce code : ```Python user_dict = user_in.model_dump() UserInDB(**user_dict) ``` -serait équivalent à : +serait équivalent à : ```Python UserInDB(**user_in.model_dump()) @@ -114,13 +114,13 @@ Ainsi, nous obtenons un modèle Pydantic à partir des données d'un autre modè #### Déballer un `dict` et ajouter des mots-clés supplémentaires { #unpacking-a-dict-and-extra-keywords } -Et en ajoutant ensuite l'argument nommé supplémentaire `hashed_password=hashed_password`, comme ici : +Et en ajoutant ensuite l'argument nommé supplémentaire `hashed_password=hashed_password`, comme ici : ```Python UserInDB(**user_in.model_dump(), hashed_password=hashed_password) ``` -... revient à : +... revient à : ```Python UserInDB( @@ -152,7 +152,7 @@ Nous pouvons déclarer un modèle `UserBase` qui sert de base à nos autres mod Toutes les conversions de données, validations, documentation, etc., fonctionneront comme d'habitude. -De cette façon, nous pouvons ne déclarer que les différences entre les modèles (avec `password` en clair, avec `hashed_password` et sans mot de passe) : +De cette façon, nous pouvons ne déclarer que les différences entre les modèles (avec `password` en clair, avec `hashed_password` et sans mot de passe) : {* ../../docs_src/extra_models/tutorial002_py310.py hl[7,13:14,17:18,21:22] *} @@ -162,7 +162,7 @@ Vous pouvez déclarer qu'une réponse est l'`Union` de deux types ou plus, ce qu Cela sera défini dans OpenAPI avec `anyOf`. -Pour ce faire, utilisez l'annotation de type Python standard [`typing.Union`](https://docs.python.org/3/library/typing.html#typing.Union) : +Pour ce faire, utilisez l'annotation de type Python standard [`typing.Union`](https://docs.python.org/3/library/typing.html#typing.Union) : /// note | Remarque @@ -176,21 +176,21 @@ Lors de la définition d'une [`Union`](https://docs.pydantic.dev/latest/concepts Dans cet exemple, nous passons `Union[PlaneItem, CarItem]` comme valeur de l'argument `response_model`. -Comme nous le passons comme valeur d'un argument au lieu de l'utiliser dans une annotation de type, nous devons utiliser `Union` même en Python 3.10. +Comme nous le passons comme **valeur à un argument** au lieu de l'utiliser dans une **annotation de type**, nous devons utiliser `Union` même en Python 3.10. -S'il s'agissait d'une annotation de type, nous pourrions utiliser la barre verticale, comme : +S'il s'agissait d'une annotation de type, nous pourrions utiliser la barre verticale, comme : ```Python some_variable: PlaneItem | CarItem ``` -Mais si nous écrivons cela dans l'affectation `response_model=PlaneItem | CarItem`, nous obtiendrons une erreur, car Python essaierait d'effectuer une « opération invalide » entre `PlaneItem` et `CarItem` au lieu de l'interpréter comme une annotation de type. +Mais si nous écrivons cela dans l'affectation `response_model=PlaneItem | CarItem`, nous obtiendrons une erreur, car Python essaierait d'effectuer une **opération invalide** entre `PlaneItem` et `CarItem` au lieu de l'interpréter comme une annotation de type. ## Liste de modèles { #list-of-models } De la même manière, vous pouvez déclarer des réponses contenant des listes d'objets. -Pour cela, utilisez le `list` Python standard : +Pour cela, utilisez le `list` Python standard : {* ../../docs_src/extra_models/tutorial004_py310.py hl[18] *} @@ -200,7 +200,7 @@ Vous pouvez également déclarer une réponse en utilisant un simple `dict` arbi C'est utile si vous ne connaissez pas à l'avance les noms de champs/attributs valides (qui seraient nécessaires pour un modèle Pydantic). -Dans ce cas, vous pouvez utiliser `dict` : +Dans ce cas, vous pouvez utiliser `dict` : {* ../../docs_src/extra_models/tutorial005_py310.py hl[6] *} @@ -208,4 +208,4 @@ Dans ce cas, vous pouvez utiliser `dict` : Utilisez plusieurs modèles Pydantic et héritez librement selon chaque cas. -Vous n'avez pas besoin d'avoir un seul modèle de données par entité si cette entité doit pouvoir avoir différents « états ». Comme pour l'« entité » utilisateur, avec un état incluant `password`, `password_hash` et sans mot de passe. +Vous n'avez pas besoin d'avoir un seul modèle de données par entité si cette entité doit pouvoir avoir différents « états ». L'« entité » **utilisateur** est un exemple, avec des états qui incluent `password`, `password_hash`, ou aucun mot de passe. diff --git a/docs/fr/docs/tutorial/first-steps.md b/docs/fr/docs/tutorial/first-steps.md index 0a82004d2..9e31e2b55 100644 --- a/docs/fr/docs/tutorial/first-steps.md +++ b/docs/fr/docs/tutorial/first-steps.md @@ -145,20 +145,20 @@ Vous pourriez également l’utiliser pour générer du code automatiquement, po ### Configurer le `entrypoint` de l’application dans `pyproject.toml` { #configure-the-app-entrypoint-in-pyproject-toml } -Vous pouvez configurer l’emplacement de votre application dans un fichier `pyproject.toml` comme : +Vous pouvez configurer l’emplacement de votre application dans un fichier `pyproject.toml` comme : ```toml [tool.fastapi] entrypoint = "main:app" ``` -Ce `entrypoint` indiquera à la commande `fastapi` qu’elle doit importer l’application comme : +Ce `entrypoint` indiquera à la commande `fastapi` qu’elle doit importer l’application comme : ```python from main import app ``` -Si votre code est structuré comme : +Si votre code est structuré comme : ``` . @@ -167,50 +167,40 @@ Si votre code est structuré comme : │   ├── __init__.py ``` -Alors vous définiriez le `entrypoint` comme : +Alors vous définiriez le `entrypoint` comme : ```toml [tool.fastapi] entrypoint = "backend.main:app" ``` -ce qui équivaudrait à : +ce qui équivaudrait à : ```python from backend.main import app ``` -### `fastapi dev` avec un chemin { #fastapi-dev-with-path } +### `fastapi dev` avec un chemin ou avec l’option CLI `--entrypoint` { #fastapi-dev-with-path-or-with-entrypoint-cli-option } -Vous pouvez également passer le chemin du fichier à la commande `fastapi dev`, et elle devinera l’objet d’application FastAPI à utiliser : +Vous pouvez également passer le chemin du fichier à la commande `fastapi dev`, et elle devinera l’objet d’application FastAPI à utiliser : ```console $ fastapi dev main.py ``` -Mais vous devrez vous souvenir de passer le chemin correct à chaque exécution de la commande `fastapi`. - -De plus, d’autres outils pourraient ne pas être capables de le trouver, par exemple l’[Extension VS Code](../editor-support.md) ou [FastAPI Cloud](https://fastapicloud.com), il est donc recommandé d’utiliser le `entrypoint` dans `pyproject.toml`. - -### Déployer votre application (optionnel) { #deploy-your-app-optional } - -Vous pouvez, si vous le souhaitez, déployer votre application FastAPI sur [FastAPI Cloud](https://fastapicloud.com), allez rejoindre la liste d’attente si ce n’est pas déjà fait. 🚀 - -Si vous avez déjà un compte **FastAPI Cloud** (nous vous avons invité depuis la liste d’attente 😉), vous pouvez déployer votre application avec une seule commande. - -Avant de déployer, vous devez vous assurer que vous êtes connecté : - -
+Ou bien, vous pouvez aussi passer l’option `--entrypoint` à la commande `fastapi dev` : ```console -$ fastapi login - -You are logged in to FastAPI Cloud 🚀 +$ fastapi dev --entrypoint main:app ``` -
+Mais vous devez vous souvenir de passer le chemin\entrypoint correct à chaque exécution de la commande `fastapi`. + +De plus, d’autres outils pourraient ne pas être capables de le trouver, par exemple l’[Extension VS Code](../editor-support.md) ou [FastAPI Cloud](https://fastapicloud.com), il est donc recommandé d’utiliser le `entrypoint` dans `pyproject.toml`. -Puis déployez votre application : +### Déployer votre application (optionnel) { #deploy-your-app-optional } + +Vous pouvez éventuellement déployer votre application FastAPI sur [FastAPI Cloud](https://fastapicloud.com) avec une seule commande. 🚀
@@ -226,6 +216,8 @@ Deploying to FastAPI Cloud...
+Le CLI détectera automatiquement votre application FastAPI et la déploiera dans le cloud. Si vous n’êtes pas connecté, votre navigateur s’ouvrira pour terminer le processus d’authentification. + C’est tout ! Vous pouvez maintenant accéder à votre application à cette URL. ✨ ## Récapitulatif, étape par étape { #recap-step-by-step } @@ -252,7 +244,7 @@ Ici, la variable `app` sera une « instance » de la classe `FastAPI`. Ce sera le point principal d’interaction pour créer toute votre API. -### Étape 3 : créer un « chemin d’accès » { #step-3-create-a-path-operation } +### Étape 3 : créer un *chemin d’accès* { #step-3-create-a-path-operation } #### Chemin { #path } @@ -270,7 +262,7 @@ https://example.com/items/foo /items/foo ``` -/// info +/// note | Remarque Un « chemin » est aussi couramment appelé « endpoint » ou « route ». @@ -313,26 +305,26 @@ Donc, dans OpenAPI, chacune des méthodes HTTP est appelée une « opération » Nous allons donc aussi les appeler « opérations ». -#### Définir un « décorateur de chemin d’accès » { #define-a-path-operation-decorator } +#### Définir un *décorateur de chemin d’accès* { #define-a-path-operation-decorator } {* ../../docs_src/first_steps/tutorial001_py310.py hl[6] *} -Le `@app.get("/")` indique à **FastAPI** que la fonction juste en dessous est chargée de gérer les requêtes qui vont vers : +Le `@app.get("/")` indique à **FastAPI** que la fonction juste en dessous est chargée de gérer les requêtes qui vont vers : * le chemin `/` * en utilisant une get opération -/// info | `@decorator` Info +/// note | Informations sur `@decorator` Cette syntaxe `@something` en Python est appelée un « décorateur ». -Vous la mettez au-dessus d’une fonction. Comme un joli chapeau décoratif (j’imagine que c’est de là que vient le terme 🤷🏻‍♂). +Vous la mettez au-dessus d’une fonction. Comme un joli chapeau décoratif (j’imagine que c’est de là que vient le terme). Un « décorateur » prend la fonction en dessous et fait quelque chose avec. Dans notre cas, ce décorateur indique à **FastAPI** que la fonction en dessous correspond au **chemin** `/` avec une **opération** `get`. -C’est le « décorateur de chemin d’accès ». +C’est le **« décorateur de chemin d’accès »**. /// @@ -363,7 +355,7 @@ Par exemple, lorsque vous utilisez GraphQL, vous effectuez normalement toutes le ### Étape 4 : définir la **fonction de chemin d’accès** { #step-4-define-the-path-operation-function } -Voici notre « fonction de chemin d’accès » : +Voici notre **« fonction de chemin d’accès »** : * **chemin** : `/`. * **opération** : `get`. @@ -373,7 +365,7 @@ Voici notre « fonction de chemin d’accès » : C’est une fonction Python. -Elle sera appelée par **FastAPI** chaque fois qu’il recevra une requête vers l’URL « / » en utilisant une opération `GET`. +Elle sera appelée par **FastAPI** chaque fois qu’il recevra une requête vers l’URL « `/` » en utilisant une opération `GET`. Dans ce cas, c’est une fonction `async`. @@ -385,7 +377,7 @@ Vous pouvez aussi la définir comme une fonction normale au lieu de `async def` /// note | Remarque -Si vous ne connaissez pas la différence, consultez [Asynchrone : « Pressé ? »](../async.md#in-a-hurry). +Si vous ne connaissez pas la différence, consultez [Asynchrone : *« Pressé ? »*](../async.md#in-a-hurry). /// diff --git a/docs/fr/docs/tutorial/frontend.md b/docs/fr/docs/tutorial/frontend.md new file mode 100644 index 000000000..6adb8a241 --- /dev/null +++ b/docs/fr/docs/tutorial/frontend.md @@ -0,0 +1,133 @@ +# Frontend { #frontend } + +Vous pouvez servir des applications frontend statiques avec `app.frontend()` (ou `router.frontend()`). + +C'est utile pour les outils frontend qui génèrent des fichiers statiques, comme React avec Vite, TanStack Router, Astro, Vue, Svelte, Angular, Solid, et d'autres. + +Avec ces outils, vous avez normalement une étape qui build le frontend, avec une commande comme : + +```bash +npm run build +``` + +Cela générerait un répertoire comme `./dist/` avec vos fichiers frontend. + +Vous pouvez utiliser `app.frontend()` pour servir ce répertoire en suivant les conventions nécessaires à ces frameworks frontend. + +**FastAPI** vérifie d'abord les *chemins d'accès*. Les fichiers frontend ne sont vérifiés que si aucune route normale ne correspond, donc votre API ne sera pas affectée. + +## Servir un frontend { #serve-a-frontend } + +Après avoir build votre frontend, par exemple avec `npm run build`, placez les fichiers générés dans un répertoire, par exemple `dist`. + +La structure de votre projet pourrait ressembler à ceci : + +```text +. +├── pyproject.toml +├── app +│ ├── __init__.py +│ └── main.py +└── dist + ├── index.html + └── assets + └── app.js +``` + +Servez-le ensuite avec `app.frontend()` : + +{* ../../docs_src/frontend/tutorial001_py310.py hl[5] *} + +Avec cela, une requête vers `/assets/app.js` peut servir `dist/assets/app.js`. + +Si vous avez également un *chemin d'accès* **FastAPI**, le *chemin d'accès* est prioritaire. + +## Routage côté client { #client-side-routing } + +De nombreuses applications frontend, y compris les **applications monopages** (SPAs), utilisent le routage côté client. Un chemin comme `/dashboard/settings` peut ne pas être un vrai fichier, mais le framework se chargerait de le gérer. + +Ainsi, si vous accédez directement à cette URL (au lieu de naviguer via l'application), le backend doit servir l'application frontend depuis `index.html`, afin que le framework frontend puisse ensuite gérer le routage côté client. + +Pour cela, utilisez `fallback="index.html"` : + +{* ../../docs_src/frontend/tutorial002_py310.py hl[5] *} + +**FastAPI** utilise ce fallback uniquement pour les requêtes `GET` et `HEAD` qui ressemblent à une navigation de navigateur. Les fichiers manquants comme JavaScript, CSS et les images renvoient toujours `404`. + +Les requêtes avec d'autres méthodes, comme `POST` ou `PUT`, vers des chemins qui ne correspondent qu'au fallback frontend renvoient également `404`. Les *chemins d'accès* **FastAPI** réguliers ont toujours une priorité plus élevée que les routes frontend. + +/// tip | Astuce + +Par défaut, `fallback` a une valeur de `fallback="auto"`. Dans la plupart des cas, vous n'avez pas besoin de spécifier `fallback`. Lisez ci-dessous pour plus de détails. + +/// + +C'est ce que vous souhaitez avec de nombreuses applications frontend qui utilisent le routage côté client, par exemple React avec TanStack Router, Vue, Angular, SvelteKit ou Solid. + +## Page 404 personnalisée { #custom-404-page } + +Vous pouvez également servir une page statique `404.html` pour les chemins frontend manquants : + +{* ../../docs_src/frontend/tutorial003_py310.py hl[5] *} + +Cette réponse conserve un code de statut `404`. + +Dans ce cas, **FastAPI** ne servira pas `index.html` pour les chemins frontend manquants. Il renverra le fichier `404.html` à la place. + +/// tip | Astuce + +Par défaut, `fallback` a une valeur de `fallback="auto"`. Avec cela, si un fichier `404.html` est trouvé, il sera utilisé automatiquement comme fallback. + +Vous pouvez donc normalement omettre l'argument `fallback`. + +/// + +C'est utile avec les outils frontend qui génèrent des fichiers HTML statiques pour chaque page, comme Astro. + +## Fallback automatique { #fallback-auto } + +Par défaut, `app.frontend()` utilise `fallback="auto"`. + +S'il y a un fichier `404.html` dans le répertoire frontend, les chemins frontend manquants servent ce fichier avec le code de statut `404`. + +Sinon, s'il y a un fichier `index.html`, les chemins de navigation de navigateur manquants servent `index.html`, ce qui est attendu par de nombreuses applications frontend avec routage côté client. + +Ainsi, dans la plupart des cas, vous pouvez utiliser `app.frontend("/", directory="dist")` sans spécifier l'argument `fallback`. + +{* ../../docs_src/frontend/tutorial001_py310.py hl[5] *} + +## Désactiver le fallback { #disable-fallback } + +Si vous ne souhaitez pas servir de fichier fallback pour les chemins frontend manquants, utilisez `fallback=None` : + +{* ../../docs_src/frontend/tutorial005_py310.py hl[5] *} + +Les chemins frontend manquants renvoient alors le `404` normal. + +## Vérifier le répertoire { #check-directory } + +Par défaut, `app.frontend()` vérifie que le répertoire existe lorsque l'application est créée. + +Cela permet de détecter tôt les erreurs de configuration. Par exemple, si le répertoire de sortie du build frontend est manquant, **FastAPI** lèvera une erreur au démarrage. + +Si vos fichiers frontend sont créés plus tard, par exemple par une étape de build séparée après la création de l'objet app, définissez `check_dir=False` : + +{* ../../docs_src/frontend/tutorial006_py310.py hl[5] *} + +Avec `check_dir=False`, **FastAPI** ne vérifiera pas le répertoire lorsque l'application est créée. Si le répertoire configuré est toujours manquant lorsqu'une requête est traitée, **FastAPI** lèvera alors une erreur. + +## L'utiliser avec `APIRouter` { #use-it-with-apirouter } + +Vous pouvez également ajouter des fichiers frontend à un `APIRouter` et l'inclure avec un préfixe : + +{* ../../docs_src/frontend/tutorial004_py310.py hl[6,7] *} + +Dans cet exemple, les chemins frontend sont servis sous `/app`. + +Tous les *chemins d'accès* réguliers dans l'application seront toujours prioritaires, y compris dans d'autres routers. + +## Sortie de build statique uniquement { #static-build-output-only } + +`app.frontend()` sert des fichiers déjà générés par votre build frontend. + +Il n'exécute pas de rendu côté serveur. Il est destiné aux frameworks frontend qui génèrent des fichiers statiques, pas aux frameworks qui nécessitent un rendu dynamique sur le serveur pour chaque requête. diff --git a/docs/fr/docs/tutorial/handling-errors.md b/docs/fr/docs/tutorial/handling-errors.md index a697571f3..5c52e7be1 100644 --- a/docs/fr/docs/tutorial/handling-errors.md +++ b/docs/fr/docs/tutorial/handling-errors.md @@ -43,7 +43,7 @@ Dans cet exemple, lorsque le client demande un élément par un ID qui n'existe ### Réponse résultante { #the-resulting-response } -Si le client demande `http://example.com/items/foo` (un `item_id` « foo »), il recevra un code d'état HTTP 200 et une réponse JSON : +Si le client demande `http://example.com/items/foo` (un `item_id` `"foo"`), il recevra un code d'état HTTP 200 et une réponse JSON : ```JSON { @@ -51,7 +51,7 @@ Si le client demande `http://example.com/items/foo` (un `item_id` « foo »), il } ``` -Mais si le client demande `http://example.com/items/bar` (un `item_id` inexistant « bar »), il recevra un code d'état HTTP 404 (l'erreur « not found ») et une réponse JSON : +Mais si le client demande `http://example.com/items/bar` (un `item_id` inexistant `"bar"`), il recevra un code d'état HTTP 404 (l'erreur « not found ») et une réponse JSON : ```JSON { diff --git a/docs/fr/docs/tutorial/index.md b/docs/fr/docs/tutorial/index.md index 2fc177ed9..1e28cfc6d 100644 --- a/docs/fr/docs/tutorial/index.md +++ b/docs/fr/docs/tutorial/index.md @@ -1,5 +1,6 @@ # Tutoriel - Guide utilisateur { #tutorial-user-guide } + Ce tutoriel vous montre comment utiliser **FastAPI** avec la plupart de ses fonctionnalités, étape par étape. Chaque section s'appuie progressivement sur les précédentes, mais elle est structurée de manière à séparer les sujets, afin que vous puissiez aller directement à l'un d'entre eux pour répondre à vos besoins spécifiques d'API. diff --git a/docs/fr/docs/tutorial/metadata.md b/docs/fr/docs/tutorial/metadata.md index 87f72fefa..1f1859eed 100644 --- a/docs/fr/docs/tutorial/metadata.md +++ b/docs/fr/docs/tutorial/metadata.md @@ -11,7 +11,7 @@ Vous pouvez définir les champs suivants qui sont utilisés dans la spécificati | `title` | `str` | Le titre de l’API. | | `summary` | `str` | Un court résumé de l’API. Disponible depuis OpenAPI 3.1.0, FastAPI 0.99.0. | | `description` | `str` | Une brève description de l’API. Elle peut utiliser Markdown. | -| `version` | `string` | La version de l’API. C’est la version de votre propre application, pas d’OpenAPI. Par exemple `2.5.0`. | +| `version` | `str` | La version de l’API. C’est la version de votre propre application, pas d’OpenAPI. Par exemple `2.5.0`. | | `terms_of_service` | `str` | Une URL vers les Conditions d’utilisation de l’API. Le cas échéant, il doit s’agir d’une URL. | | `contact` | `dict` | Les informations de contact pour l’API exposée. Cela peut contenir plusieurs champs.
champs de contact
ParamètreTypeDescription
namestrLe nom identifiant de la personne/organisation de contact.
urlstrL’URL pointant vers les informations de contact. DOIT être au format d’une URL.
emailstrL’adresse e-mail de la personne/organisation de contact. DOIT être au format d’une adresse e-mail.
| | `license_info` | `dict` | Les informations de licence pour l’API exposée. Cela peut contenir plusieurs champs.
champs de license_info
ParamètreTypeDescription
namestrOBLIGATOIRE (si un license_info est défini). Le nom de la licence utilisée pour l’API.
identifierstrUne expression de licence [SPDX](https://spdx.org/licenses/) pour l’API. Le champ identifier est mutuellement exclusif du champ url. Disponible depuis OpenAPI 3.1.0, FastAPI 0.99.0.
urlstrUne URL vers la licence utilisée pour l’API. DOIT être au format d’une URL.
| @@ -74,7 +74,7 @@ Utilisez le paramètre `tags` avec vos *chemins d'accès* (et `APIRouter`s) pour {* ../../docs_src/metadata/tutorial004_py310.py hl[21,26] *} -/// info +/// note | Remarque En savoir plus sur les tags dans [Configuration de chemins d'accès](path-operation-configuration.md#tags). diff --git a/docs/fr/docs/tutorial/path-operation-configuration.md b/docs/fr/docs/tutorial/path-operation-configuration.md index 185adb6dd..bd9aed879 100644 --- a/docs/fr/docs/tutorial/path-operation-configuration.md +++ b/docs/fr/docs/tutorial/path-operation-configuration.md @@ -1,5 +1,6 @@ # Configurer les chemins d'accès { #path-operation-configuration } + Vous pouvez passer plusieurs paramètres à votre *décorateur de chemin d'accès* pour le configurer. /// warning | Alertes @@ -72,13 +73,13 @@ Vous pouvez spécifier la description de la réponse avec le paramètre `respons {* ../../docs_src/path_operation_configuration/tutorial005_py310.py hl[18] *} -/// info +/// note | Remarque Notez que `response_description` se réfère spécifiquement à la réponse, tandis que `description` se réfère au *chemin d'accès* en général. /// -/// check | Vérifications +/// tip | Astuce OpenAPI spécifie que chaque *chemin d'accès* requiert une description de réponse. diff --git a/docs/fr/docs/tutorial/path-params-numeric-validations.md b/docs/fr/docs/tutorial/path-params-numeric-validations.md index b61b42ef7..c308541a1 100644 --- a/docs/fr/docs/tutorial/path-params-numeric-validations.md +++ b/docs/fr/docs/tutorial/path-params-numeric-validations.md @@ -8,7 +8,7 @@ Tout d'abord, importez `Path` de `fastapi`, et importez `Annotated` : {* ../../docs_src/path_params_numeric_validations/tutorial001_an_py310.py hl[1,3] *} -/// info +/// note | Remarque FastAPI a ajouté le support pour `Annotated` (et a commencé à le recommander) dans la version 0.95.0. @@ -131,7 +131,7 @@ Et vous pouvez également déclarer des validations numériques : * `lt` : `l`ess `t`han * `le` : `l`ess than or `e`qual -/// info +/// note | Remarque `Query`, `Path`, et d'autres classes que vous verrez plus tard sont des sous-classes d'une classe commune `Param`. diff --git a/docs/fr/docs/tutorial/path-params.md b/docs/fr/docs/tutorial/path-params.md index f84c4c035..e8d20bb74 100644 --- a/docs/fr/docs/tutorial/path-params.md +++ b/docs/fr/docs/tutorial/path-params.md @@ -20,7 +20,7 @@ Vous pouvez déclarer le type d'un paramètre de chemin dans la fonction, en uti Ici, `item_id` est déclaré comme `int`. -/// check | Vérifications +/// tip | Astuce Cela vous apporte la prise en charge par l'éditeur dans votre fonction, avec vérifications d'erreurs, autocomplétion, etc. @@ -34,7 +34,7 @@ Si vous exécutez cet exemple et ouvrez votre navigateur sur [http://127.0.0.1:8 {"item_id":3} ``` -/// check | Vérifications +/// tip | Astuce Remarquez que la valeur reçue par votre fonction (et renvoyée) est `3`, en tant qu'entier (`int`) Python, pas la chaîne de caractères « 3 ». @@ -66,7 +66,7 @@ car le paramètre de chemin `item_id` a pour valeur « foo », qui n'est pas un La même erreur apparaîtrait si vous fournissiez un `float` au lieu d'un `int`, comme ici : [http://127.0.0.1:8000/items/4.2](http://127.0.0.1:8000/items/4.2) -/// check | Vérifications +/// tip | Astuce Ainsi, avec la même déclaration de type Python, **FastAPI** vous fournit la validation de données. @@ -82,7 +82,7 @@ Et lorsque vous ouvrez votre navigateur sur [http://127.0.0.1:8000/docs](http:// -/// check | Vérifications +/// tip | Astuce À nouveau, simplement avec cette même déclaration de type Python, **FastAPI** vous fournit une documentation interactive automatique (intégrant Swagger UI). diff --git a/docs/fr/docs/tutorial/query-params-str-validations.md b/docs/fr/docs/tutorial/query-params-str-validations.md index 57d358758..1b0fa88b3 100644 --- a/docs/fr/docs/tutorial/query-params-str-validations.md +++ b/docs/fr/docs/tutorial/query-params-str-validations.md @@ -29,7 +29,7 @@ Pour ce faire, importez d’abord : {* ../../docs_src/query_params_str_validations/tutorial002_an_py310.py hl[1,3] *} -/// info +/// note | Remarque FastAPI a ajouté la prise en charge de `Annotated` (et a commencé à le recommander) dans la version 0.95.0. @@ -81,7 +81,7 @@ FastAPI va maintenant : - **Valider** les données en s’assurant que la longueur maximale est de 50 caractères - Afficher une **erreur claire** au client quand les données ne sont pas valides -- **Documenter** le paramètre dans la *chemin d'accès* du schéma OpenAPI (il apparaîtra donc dans l’**interface de documentation automatique**) +- **Documenter** le paramètre dans le *chemin d'accès* du schéma OpenAPI (il apparaîtra donc dans l’**interface de documentation automatique**) ## Alternative (ancienne) : `Query` comme valeur par défaut { #alternative-old-query-as-the-default-value } @@ -89,7 +89,7 @@ Les versions précédentes de FastAPI (avant 0.95.0spécification exige que les champs soient Avec `Form`, vous pouvez déclarer les mêmes configurations que pour `Body` (ainsi que `Query`, `Path`, `Cookie`), y compris la validation, des exemples, un alias (p. ex. `user-name` au lieu de `username`), etc. -/// info +/// note | Remarque `Form` est une classe qui hérite directement de `Body`. @@ -56,7 +56,7 @@ Les données issues des formulaires sont normalement encodées avec le « type d Mais lorsque le formulaire inclut des fichiers, il est encodé en `multipart/form-data`. Vous lirez la gestion des fichiers dans le chapitre suivant. -Si vous voulez en savoir plus sur ces encodages et les champs de formulaire, consultez la [MDN web docs pour `POST`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST). +Si vous voulez en savoir plus sur ces encodages et les champs de formulaire, consultez les [documents web de la MDN pour `POST`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST). /// diff --git a/docs/fr/docs/tutorial/response-model.md b/docs/fr/docs/tutorial/response-model.md index e3926a0c1..322b17044 100644 --- a/docs/fr/docs/tutorial/response-model.md +++ b/docs/fr/docs/tutorial/response-model.md @@ -72,7 +72,7 @@ Ici, nous déclarons un modèle `UserIn`, il contiendra un mot de passe en clair {* ../../docs_src/response_model/tutorial002_py310.py hl[7,9] *} -/// info | Info +/// note | Remarque Pour utiliser `EmailStr`, installez d'abord [`email-validator`](https://github.com/JoshData/python-email-validator). @@ -251,7 +251,7 @@ Ainsi, si vous envoyez une requête à ce *chemin d'accès* pour l'article avec } ``` -/// info | Info +/// note | Remarque Vous pouvez également utiliser : diff --git a/docs/fr/docs/tutorial/response-status-code.md b/docs/fr/docs/tutorial/response-status-code.md index c8e45cd40..398d1f1a1 100644 --- a/docs/fr/docs/tutorial/response-status-code.md +++ b/docs/fr/docs/tutorial/response-status-code.md @@ -1,5 +1,6 @@ # Code d'état de la réponse { #response-status-code } + De la même manière que vous pouvez spécifier un modèle de réponse, vous pouvez également déclarer le code d'état HTTP utilisé pour la réponse avec le paramètre `status_code` dans n'importe lequel des chemins d'accès : * `@app.get()` @@ -18,7 +19,7 @@ Remarquez que `status_code` est un paramètre de la méthode « decorator » (`g Le paramètre `status_code` reçoit un nombre correspondant au code d'état HTTP. -/// info +/// note | Remarque `status_code` peut aussi recevoir un `IntEnum`, comme le [`http.HTTPStatus`](https://docs.python.org/3/library/http.html#http.HTTPStatus) de Python. diff --git a/docs/fr/docs/tutorial/schema-extra-example.md b/docs/fr/docs/tutorial/schema-extra-example.md index 404edff46..85905f5f5 100644 --- a/docs/fr/docs/tutorial/schema-extra-example.md +++ b/docs/fr/docs/tutorial/schema-extra-example.md @@ -1,6 +1,6 @@ # Déclarer des exemples de données de requête { #declare-request-example-data } -Vous pouvez déclarer des exemples des données que votre application peut recevoir. +Vous pouvez déclarer des exemples de données que votre application peut recevoir. Voici plusieurs façons de le faire. @@ -10,9 +10,9 @@ Vous pouvez déclarer `examples` pour un modèle Pydantic qui seront ajoutés au {* ../../docs_src/schema_extra_example/tutorial001_py310.py hl[13:24] *} -Ces informations supplémentaires seront ajoutées telles quelles au **JSON Schema** de sortie pour ce modèle, et elles seront utilisées dans la documentation de l'API. +Ces informations supplémentaires seront ajoutées telles quelles au **JSON Schema** de sortie pour ce modèle, et elles seront utilisées dans les documents de l'API. -Vous pouvez utiliser l'attribut `model_config` qui accepte un `dict` comme décrit dans [Documentation de Pydantic : Configuration](https://docs.pydantic.dev/latest/api/config/). +Vous pouvez utiliser l'attribut `model_config` qui accepte un `dict` comme décrit dans [documents de Pydantic : Configuration](https://docs.pydantic.dev/latest/api/config/). Vous pouvez définir `"json_schema_extra"` avec un `dict` contenant toutes les données supplémentaires que vous souhaitez voir apparaître dans le JSON Schema généré, y compris `examples`. @@ -24,11 +24,11 @@ Par exemple, vous pourriez l'utiliser pour ajouter des métadonnées pour une in /// -/// info +/// note | Remarque OpenAPI 3.1.0 (utilisé depuis FastAPI 0.99.0) a ajouté la prise en charge de `examples`, qui fait partie du standard **JSON Schema**. -Avant cela, seule la clé `example` avec un exemple unique était prise en charge. Elle l'est toujours par OpenAPI 3.1.0, mais elle est dépréciée et ne fait pas partie du standard JSON Schema. Vous êtes donc encouragé à migrer de `example` vers `examples`. 🤓 +Avant cela, seul le mot-clé `example` avec un exemple unique était pris en charge. Il l'est toujours par OpenAPI 3.1.0, mais il est déprécié et ne fait pas partie du standard JSON Schema. Vous êtes donc encouragé à migrer de `example` vers `examples`. 🤓 Vous pouvez en lire davantage à la fin de cette page. @@ -155,7 +155,7 @@ OpenAPI a également ajouté les champs `example` et `examples` à d'autres part * `File()` * `Form()` -/// info +/// note | Remarque Ce paramètre `examples` ancien et spécifique à OpenAPI est désormais `openapi_examples` depuis FastAPI `0.103.0`. @@ -171,9 +171,9 @@ Et désormais, ce nouveau champ `examples` a priorité sur l'ancien champ unique Ce nouveau champ `examples` dans JSON Schema est **juste une `list`** d'exemples, et non pas un dict avec des métadonnées supplémentaires comme dans les autres endroits d'OpenAPI (décrits ci-dessus). -/// info +/// note | Remarque -Même après la sortie d'OpenAPI 3.1.0 avec cette nouvelle intégration plus simple avec JSON Schema, pendant un temps, Swagger UI, l'outil qui fournit la documentation automatique, ne prenait pas en charge OpenAPI 3.1.0 (il le fait depuis la version 5.0.0 🎉). +Même après la sortie d'OpenAPI 3.1.0 avec cette nouvelle intégration plus simple avec JSON Schema, pendant un temps, Swagger UI, l'outil qui fournit les documents automatiques, ne prenait pas en charge OpenAPI 3.1.0 (il le fait depuis la version 5.0.0 🎉). À cause de cela, les versions de FastAPI antérieures à 0.99.0 utilisaient encore des versions d'OpenAPI inférieures à 3.1.0. @@ -183,7 +183,7 @@ Même après la sortie d'OpenAPI 3.1.0 avec cette nouvelle intégration plus sim Lorsque vous ajoutez `examples` dans un modèle Pydantic, en utilisant `schema_extra` ou `Field(examples=["something"])`, cet exemple est ajouté au **JSON Schema** de ce modèle Pydantic. -Et ce **JSON Schema** du modèle Pydantic est inclus dans l'**OpenAPI** de votre API, puis il est utilisé dans l'interface de la documentation. +Et ce **JSON Schema** du modèle Pydantic est inclus dans l'**OpenAPI** de votre API, puis il est utilisé dans l'interface des documents. Dans les versions de FastAPI antérieures à 0.99.0 (0.99.0 et supérieures utilisent le nouveau OpenAPI 3.1.0), lorsque vous utilisiez `example` ou `examples` avec l'une des autres utilitaires (`Query()`, `Body()`, etc.), ces exemples n'étaient pas ajoutés au JSON Schema qui décrit ces données (pas même à la version de JSON Schema propre à OpenAPI), ils étaient ajoutés directement à la déclaration du *chemin d'accès* dans OpenAPI (en dehors des parties d'OpenAPI qui utilisent JSON Schema). @@ -191,7 +191,7 @@ Mais maintenant que FastAPI 0.99.0 et supérieures utilisent OpenAPI 3.1.0, qui ### Swagger UI et `examples` spécifiques à OpenAPI { #swagger-ui-and-openapi-specific-examples } -Comme Swagger UI ne prenait pas en charge plusieurs exemples JSON Schema (au 2023-08-26), les utilisateurs n'avaient pas de moyen d'afficher plusieurs exemples dans les documents. +Maintenant, comme Swagger UI ne prenait pas en charge plusieurs exemples JSON Schema (au 2023-08-26), les utilisateurs n'avaient pas de moyen d'afficher plusieurs exemples dans les documents. Pour résoudre cela, FastAPI `0.103.0` a **ajouté la prise en charge** de la déclaration du même ancien champ `examples` **spécifique à OpenAPI** avec le nouveau paramètre `openapi_examples`. 🤓 diff --git a/docs/fr/docs/tutorial/security/first-steps.md b/docs/fr/docs/tutorial/security/first-steps.md index c1d36d501..66005d907 100644 --- a/docs/fr/docs/tutorial/security/first-steps.md +++ b/docs/fr/docs/tutorial/security/first-steps.md @@ -24,7 +24,7 @@ Copiez l'exemple dans un fichier `main.py` : ## Exécuter { #run-it } -/// info +/// note | Remarque Le package [`python-multipart`](https://github.com/Kludex/python-multipart) est installé automatiquement avec **FastAPI** lorsque vous exécutez la commande `pip install "fastapi[standard]"`. @@ -54,13 +54,13 @@ $ fastapi dev ## Vérifier { #check-it } -Allez à la documentation interactive à l'adresse : [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs). +Allez aux documents interactifs à l'adresse : [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs). Vous verrez quelque chose comme ceci : -/// check | Bouton « Authorize » ! +/// tip | Bouton « Authorize » ! Vous avez déjà un tout nouveau bouton « Authorize ». @@ -98,19 +98,19 @@ Mais dans ce cas, la même application **FastAPI** gérera l'API et l'authentifi Voyons cela selon ce point de vue simplifié : -- L'utilisateur saisit le `username` et le `password` dans le frontend, puis appuie sur Entrée. -- Le frontend (exécuté dans le navigateur de l'utilisateur) envoie ce `username` et ce `password` vers une URL spécifique de notre API (déclarée avec `tokenUrl="token"`). -- L'API vérifie ce `username` et ce `password`, et répond avec un « token » (nous n'avons encore rien implémenté de tout cela). - - Un « token » n'est qu'une chaîne contenant des informations que nous pouvons utiliser plus tard pour vérifier cet utilisateur. - - Normalement, un token est configuré pour expirer après un certain temps. - - Ainsi, l'utilisateur devra se reconnecter à un moment donné. - - Et si le token est volé, le risque est moindre. Ce n'est pas une clé permanente qui fonctionnerait indéfiniment (dans la plupart des cas). -- Le frontend stocke ce token temporairement quelque part. -- L'utilisateur clique dans le frontend pour aller vers une autre section de l'application web frontend. -- Le frontend doit récupérer d'autres données depuis l'API. - - Mais cela nécessite une authentification pour cet endpoint spécifique. - - Donc, pour s'authentifier auprès de notre API, il envoie un en-tête `Authorization` avec une valeur `Bearer ` suivie du token. - - Si le token contient `foobar`, le contenu de l'en-tête `Authorization` serait : `Bearer foobar`. +* L'utilisateur saisit le `username` et le `password` dans le frontend, puis appuie sur Entrée. +* Le frontend (exécuté dans le navigateur de l'utilisateur) envoie ce `username` et ce `password` vers une URL spécifique de notre API (déclarée avec `tokenUrl="token"`). +* L'API vérifie ce `username` et ce `password`, et répond avec un « token » (nous n'avons encore rien implémenté de tout cela). + * Un « token » n'est qu'une chaîne contenant des informations que nous pouvons utiliser plus tard pour vérifier cet utilisateur. + * Normalement, un token est configuré pour expirer après un certain temps. + * Ainsi, l'utilisateur devra se reconnecter à un moment donné. + * Et si le token est volé, le risque est moindre. Ce n'est pas une clé permanente qui fonctionnerait indéfiniment (dans la plupart des cas). +* Le frontend stocke ce token temporairement quelque part. +* L'utilisateur clique dans le frontend pour aller vers une autre section de l'application web frontend. +* Le frontend doit récupérer d'autres données depuis l'API. + * Mais cela nécessite une authentification pour cet endpoint spécifique. + * Donc, pour s'authentifier auprès de notre API, il envoie un en-tête `Authorization` avec une valeur `Bearer ` suivie du token. + * Si le token contient `foobar`, le contenu de l'en-tête `Authorization` serait : `Bearer foobar`. ## Le `OAuth2PasswordBearer` de **FastAPI** { #fastapis-oauth2passwordbearer } @@ -118,7 +118,7 @@ Voyons cela selon ce point de vue simplifié : Dans cet exemple, nous allons utiliser **OAuth2**, avec le flux **Password**, en utilisant un token **Bearer**. Nous le faisons avec la classe `OAuth2PasswordBearer`. -/// info +/// note | Remarque Un token « bearer » n'est pas la seule option. @@ -148,7 +148,7 @@ Ce paramètre ne crée pas cet endpoint / *chemin d'accès*, mais déclare que l Nous créerons bientôt aussi le véritable chemin d'accès. -/// info +/// note | Remarque Si vous êtes un « Pythonista » très strict, vous pourriez ne pas apprécier le style du nom de paramètre `tokenUrl` au lieu de `token_url`. @@ -172,15 +172,15 @@ Vous pouvez maintenant passer ce `oauth2_scheme` en dépendance avec `Depends`. {* ../../docs_src/security/tutorial001_an_py310.py hl[12] *} -Cette dépendance fournira une `str` qui est affectée au paramètre `token` de la fonction de *chemin d'accès*. +Cette dépendance fournira une `str` qui est affectée au paramètre `token` de la *fonction de chemin d'accès*. -**FastAPI** saura qu'il peut utiliser cette dépendance pour définir un « schéma de sécurité » dans le schéma OpenAPI (et la documentation API automatique). +**FastAPI** saura qu'il peut utiliser cette dépendance pour définir un « schéma de sécurité » dans le schéma OpenAPI (et les documents automatiques de l'API). -/// info | Détails techniques +/// note | Détails techniques **FastAPI** saura qu'il peut utiliser la classe `OAuth2PasswordBearer` (déclarée dans une dépendance) pour définir le schéma de sécurité dans OpenAPI parce qu'elle hérite de `fastapi.security.oauth2.OAuth2`, qui hérite à son tour de `fastapi.security.base.SecurityBase`. -Tous les utilitaires de sécurité qui s'intègrent à OpenAPI (et à la documentation API automatique) héritent de `SecurityBase`, c'est ainsi que **FastAPI** sait comment les intégrer dans OpenAPI. +Tous les utilitaires de sécurité qui s'intègrent à OpenAPI (et aux documents automatiques de l'API) héritent de `SecurityBase`, c'est ainsi que **FastAPI** sait comment les intégrer dans OpenAPI. /// @@ -192,7 +192,7 @@ S'il ne voit pas d'en-tête `Authorization`, ou si la valeur n'a pas de token `B Vous n'avez même pas à vérifier si le token existe pour renvoyer une erreur. Vous pouvez être sûr que si votre fonction est exécutée, elle aura une `str` dans ce token. -Vous pouvez déjà l'essayer dans la documentation interactive : +Vous pouvez déjà l'essayer dans les documents interactifs : diff --git a/docs/fr/docs/tutorial/security/get-current-user.md b/docs/fr/docs/tutorial/security/get-current-user.md index 5f73efea9..664814bc3 100644 --- a/docs/fr/docs/tutorial/security/get-current-user.md +++ b/docs/fr/docs/tutorial/security/get-current-user.md @@ -14,7 +14,7 @@ Commençons par créer un modèle d'utilisateur Pydantic. De la même manière que nous utilisons Pydantic pour déclarer des corps de requête, nous pouvons l'utiliser ailleurs : -{* ../../docs_src/security/tutorial002_an_py310.py hl[5,12:6] *} +{* ../../docs_src/security/tutorial002_an_py310.py hl[5,12:16] *} ## Créer une dépendance `get_current_user` { #create-a-get-current-user-dependency } @@ -52,7 +52,7 @@ Ici, **FastAPI** ne s'y trompera pas car vous utilisez `Depends`. /// -/// check | Vérifications +/// tip | Astuce La manière dont ce système de dépendances est conçu nous permet d'avoir différentes dépendances (différents « dependables ») qui retournent toutes un modèle `User`. diff --git a/docs/fr/docs/tutorial/security/oauth2-jwt.md b/docs/fr/docs/tutorial/security/oauth2-jwt.md index eec5ab13c..f92fd75a6 100644 --- a/docs/fr/docs/tutorial/security/oauth2-jwt.md +++ b/docs/fr/docs/tutorial/security/oauth2-jwt.md @@ -42,7 +42,7 @@ $ pip install pyjwt
-/// info +/// note | Remarque Si vous prévoyez d'utiliser des algorithmes de signature numérique comme RSA ou ECDSA, vous devez installer la dépendance de bibliothèque de cryptographie `pyjwt[crypto]`. @@ -58,7 +58,7 @@ Chaque fois que vous fournissez exactement le même contenu (exactement le même Mais vous ne pouvez pas convertir le charabia en sens inverse vers le mot de passe. -### Pourquoi utiliser le hachage de mot passe { #why-use-password-hashing } +### Pourquoi utiliser le hachage de mot de passe { #why-use-password-hashing } Si votre base de données est volée, le voleur n'aura pas les mots de passe en clair de vos utilisateurs, seulement les hachages. @@ -120,7 +120,7 @@ Et une autre pour authentifier et renvoyer un utilisateur. Lorsque `authenticate_user` est appelée avec un nom d'utilisateur qui n'existe pas dans la base de données, nous exécutons tout de même `verify_password` contre un hachage factice. -Cela garantit que le point de terminaison met approximativement le même temps à répondre que le nom d'utilisateur soit valide ou non, empêchant des **attaques temporelles** qui pourraient être utilisées pour énumérer les noms d'utilisateur existants. +Cela garantit que l'endpoint met approximativement le même temps à répondre que le nom d'utilisateur soit valide ou non, empêchant des **attaques temporelles** qui pourraient être utilisées pour énumérer les noms d'utilisateur existants. /// note | Remarque @@ -152,7 +152,7 @@ Créez une variable `ALGORITHM` avec l'algorithme utilisé pour signer le jeton Créez une variable pour l'expiration du jeton. -Définissez un modèle Pydantic qui sera utilisé dans le point de terminaison du jeton pour la réponse. +Définissez un modèle Pydantic qui sera utilisé dans l'endpoint du jeton pour la réponse. Créez une fonction utilitaire pour générer un nouveau jeton d'accès. @@ -200,7 +200,7 @@ L'important à garder à l'esprit est que la clé `sub` doit contenir un identif ## Vérifier { #check-it } -Lancez le serveur et allez à la documentation : [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs). +Lancez le serveur et accédez aux documents : [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs). Vous verrez l'interface utilisateur suivante : @@ -213,15 +213,15 @@ En utilisant les identifiants : Nom d'utilisateur : `johndoe` Mot de passe : `secret` -/// check | Vérifications +/// tip | Astuce -Remarquez qu'à aucun endroit du code le mot de passe en clair « secret » n'apparaît, nous n'avons que la version hachée. +Remarquez qu'à aucun endroit du code le mot de passe en clair « `secret` » n'apparaît, nous n'avons que la version hachée. /// -Appelez le point de terminaison `/users/me/`, vous obtiendrez la réponse suivante : +Appelez l'endpoint `/users/me/`, vous obtiendrez la réponse suivante : ```JSON { diff --git a/docs/fr/docs/tutorial/security/simple-oauth2.md b/docs/fr/docs/tutorial/security/simple-oauth2.md index f47d94aa2..1ee9e61ec 100644 --- a/docs/fr/docs/tutorial/security/simple-oauth2.md +++ b/docs/fr/docs/tutorial/security/simple-oauth2.md @@ -14,13 +14,13 @@ Mais ne vous inquiétez pas, vous pouvez l'afficher comme vous le souhaitez à v Et vos modèles de base de données peuvent utiliser les noms que vous voulez. -Mais pour le chemin d'accès de connexion, nous devons utiliser ces noms pour être compatibles avec la spécification (et pouvoir, par exemple, utiliser le système de documentation API intégré). +Mais pour le *chemin d'accès* de connexion, nous devons utiliser ces noms pour être compatibles avec la spécification (et pouvoir, par exemple, utiliser le système de documentation API intégré). La spécification précise également que `username` et `password` doivent être envoyés en données de formulaire (donc pas de JSON ici). ### `scope` { #scope } -La spécification indique aussi que le client peut envoyer un autre champ de formulaire « scope ». +La spécification indique aussi que le client peut envoyer un autre champ de formulaire « `scope` ». Le nom du champ de formulaire est `scope` (au singulier), mais il s'agit en fait d'une longue chaîne contenant des « scopes » séparés par des espaces. @@ -32,7 +32,7 @@ Ils sont normalement utilisés pour déclarer des permissions de sécurité spé * `instagram_basic` est utilisé par Facebook / Instagram. * `https://www.googleapis.com/auth/drive` est utilisé par Google. -/// info +/// note | Remarque En OAuth2, un « scope » est simplement une chaîne qui déclare une permission spécifique requise. @@ -50,7 +50,7 @@ Utilisons maintenant les utilités fournies par **FastAPI** pour gérer cela. ### `OAuth2PasswordRequestForm` { #oauth2passwordrequestform } -Tout d'abord, importez `OAuth2PasswordRequestForm`, et utilisez-la en tant que dépendance avec `Depends` dans le chemin d'accès pour `/token` : +Tout d'abord, importez `OAuth2PasswordRequestForm`, et utilisez-la en tant que dépendance avec `Depends` dans le *chemin d'accès* pour `/token` : {* ../../docs_src/security/tutorial003_an_py310.py hl[4,78] *} @@ -63,7 +63,7 @@ Tout d'abord, importez `OAuth2PasswordRequestForm`, et utilisez-la en tant que d /// tip | Astuce -La spécification OAuth2 exige en réalité un champ `grant_type` avec la valeur fixe `password`, mais `OAuth2PasswordRequestForm` ne l'impose pas. +La spécification OAuth2 *exige* en réalité un champ `grant_type` avec la valeur fixe `password`, mais `OAuth2PasswordRequestForm` ne l'impose pas. Si vous avez besoin de l'imposer, utilisez `OAuth2PasswordRequestFormStrict` au lieu de `OAuth2PasswordRequestForm`. @@ -72,7 +72,7 @@ Si vous avez besoin de l'imposer, utilisez `OAuth2PasswordRequestFormStrict` au * Un `client_id` optionnel (nous n'en avons pas besoin pour notre exemple). * Un `client_secret` optionnel (nous n'en avons pas besoin pour notre exemple). -/// info +/// note | Remarque La classe `OAuth2PasswordRequestForm` n'est pas une classe spéciale pour **FastAPI** comme l'est `OAuth2PasswordBearer`. @@ -132,7 +132,7 @@ Ainsi, il ne pourra pas essayer d'utiliser ces mêmes mots de passe dans un autr `UserInDB(**user_dict)` signifie : -Passez les clés et valeurs de `user_dict` directement comme arguments clé‑valeur, équivalent à : +*Passez les clés et valeurs de `user_dict` directement comme arguments clé‑valeur, équivalent à :* ```Python UserInDB( @@ -144,9 +144,9 @@ UserInDB( ) ``` -/// info +/// note | Remarque -Pour une explication plus complète de `**user_dict`, consultez [la documentation pour **Modèles supplémentaires**](../extra-models.md#about-user-in-dict). +Pour une explication plus complète de `**user_dict`, consultez [la documentation pour **Modèles supplémentaires**](../extra-models.md#about-user-in-model-dump). /// @@ -154,7 +154,7 @@ Pour une explication plus complète de `**user_dict`, consultez [la documentatio La réponse de l'endpoint `token` doit être un objet JSON. -Il doit contenir un `token_type`. Dans notre cas, comme nous utilisons des jetons « Bearer », le type de jeton doit être « bearer ». +Il doit contenir un `token_type`. Dans notre cas, comme nous utilisons des jetons « Bearer », le type de jeton doit être « `bearer` ». Et il doit contenir un `access_token`, avec une chaîne contenant notre jeton d'accès. @@ -186,7 +186,7 @@ Pour le reste, **FastAPI** s'en charge pour vous. Nous allons maintenant mettre à jour nos dépendances. -Nous voulons obtenir `current_user` uniquement si cet utilisateur est actif. +Nous voulons obtenir `current_user` *uniquement* si cet utilisateur est actif. Nous créons donc une dépendance supplémentaire `get_current_active_user` qui utilise à son tour `get_current_user` comme dépendance. @@ -196,7 +196,7 @@ Ainsi, dans notre endpoint, nous n'obtiendrons un utilisateur que si l'utilisate {* ../../docs_src/security/tutorial003_an_py310.py hl[58:66,69:74,94] *} -/// info +/// note | Remarque L'en‑tête supplémentaire `WWW-Authenticate` avec la valeur `Bearer` que nous renvoyons ici fait également partie de la spécification. @@ -216,7 +216,7 @@ C'est l'avantage des standards ... ## Voir en action { #see-it-in-action } -Ouvrez la documentation interactive : [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs). +Ouvrez les documents interactifs : [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs). ### S'authentifier { #authenticate } diff --git a/docs/fr/docs/tutorial/server-sent-events.md b/docs/fr/docs/tutorial/server-sent-events.md index f4ed506f6..d62e3bfa7 100644 --- a/docs/fr/docs/tutorial/server-sent-events.md +++ b/docs/fr/docs/tutorial/server-sent-events.md @@ -4,7 +4,7 @@ Vous pouvez diffuser des données vers le client en utilisant les **Server-Sent C'est similaire à [Diffuser des JSON Lines](stream-json-lines.md), mais cela utilise le format `text/event-stream`, pris en charge nativement par les navigateurs via l’API [`EventSource`](https://developer.mozilla.org/en-US/docs/Web/API/EventSource). -/// info | Info +/// note | Remarque Ajouté dans FastAPI 0.135.0. diff --git a/docs/fr/docs/tutorial/sql-databases.md b/docs/fr/docs/tutorial/sql-databases.md index 70e5b1dba..2f6aad3a9 100644 --- a/docs/fr/docs/tutorial/sql-databases.md +++ b/docs/fr/docs/tutorial/sql-databases.md @@ -30,7 +30,7 @@ Il existe un générateur de projet officiel avec **FastAPI** et **PostgreSQL**, /// -Il s'agit d'un tutoriel très simple et court ; si vous souhaitez apprendre sur les bases de données en général, sur SQL, ou des fonctionnalités plus avancées, allez voir la [documentation SQLModel](https://sqlmodel.tiangolo.com/). +Il s'agit d'un tutoriel très simple et court ; si vous souhaitez apprendre sur les bases de données en général, sur SQL, ou des fonctionnalités plus avancées, allez voir les [documents de SQLModel](https://sqlmodel.tiangolo.com/). ## Installer `SQLModel` { #install-sqlmodel } @@ -57,15 +57,15 @@ Importez `SQLModel` et créez un modèle de base de données : {* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[1:11] hl[7:11] *} -La classe `Hero` est très similaire à un modèle Pydantic (en fait, en dessous, c'est réellement un modèle Pydantic). +La classe `Hero` est très similaire à un modèle Pydantic (en fait, en dessous, c'est réellement *un modèle Pydantic*). Il y a quelques différences : * `table=True` indique à SQLModel qu'il s'agit d'un *modèle de table*, il doit représenter une **table** dans la base SQL, ce n'est pas seulement un *modèle de données* (comme le serait n'importe quelle autre classe Pydantic classique). -* `Field(primary_key=True)` indique à SQLModel que `id` est la **clé primaire** dans la base SQL (vous pouvez en savoir plus sur les clés primaires SQL dans la documentation SQLModel). +* `Field(primary_key=True)` indique à SQLModel que `id` est la **clé primaire** dans la base SQL (vous pouvez en savoir plus sur les clés primaires SQL dans les documents de SQLModel). - Remarque : nous utilisons `int | None` pour le champ clé primaire afin qu'en Python nous puissions *créer un objet sans `id`* (`id=None`), en supposant que la base *le génère à l'enregistrement*. SQLModel comprend que la base fournira l'`id` et *définit la colonne comme un `INTEGER` non nul* dans le schéma de base. Voir la [documentation SQLModel sur les clés primaires](https://sqlmodel.tiangolo.com/tutorial/create-db-and-table/#primary-key-id) pour plus de détails. + **Remarque :** nous utilisons `int | None` pour le champ clé primaire afin qu'en Python nous puissions *créer un objet sans `id`* (`id=None`), en supposant que la base *le génère à l'enregistrement*. SQLModel comprend que la base fournira l'`id` et *définit la colonne comme un `INTEGER` non nul* dans le schéma de base. Voir les [documents de SQLModel sur les clés primaires](https://sqlmodel.tiangolo.com/tutorial/create-db-and-table/#primary-key-id) pour plus de détails. * `Field(index=True)` indique à SQLModel qu'il doit créer un **index SQL** pour cette colonne, ce qui permettra des recherches plus rapides dans la base lors de la lecture de données filtrées par cette colonne. @@ -121,7 +121,7 @@ Comme chaque modèle SQLModel est aussi un modèle Pydantic, vous pouvez l'utili Par exemple, si vous déclarez un paramètre de type `Hero`, il sera lu depuis le **corps JSON**. -De la même manière, vous pouvez le déclarer comme **type de retour** de la fonction, et alors la forme des données apparaîtra dans l'UI automatique de documentation de l'API. +De la même manière, vous pouvez le déclarer comme **type de retour** de la fonction, et alors la forme des données apparaîtra dans l'UI automatique des documents de l'API. {* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[40:45] hl[40:45] *} @@ -173,7 +173,7 @@ Si vous vérifiez l'application précédente, dans l'UI vous pouvez voir que, ju Nous ne devrions pas laisser cela se produire, ils pourraient écraser un `id` que nous avons déjà attribué dans la base. Décider de l'`id` doit être fait par le **backend** ou la **base**, **pas par le client**. -De plus, nous créons un `secret_name` pour le héros, mais jusqu'ici, nous le renvoyons partout, ce n'est pas très « secret » ... 😅 +De plus, nous créons un `secret_name` pour le héros, mais jusqu'ici, nous le renvoyons partout, ce n'est pas très **secret** ... 😅 Nous allons corriger ces choses en ajoutant quelques **modèles supplémentaires**. C'est là que SQLModel brille. ✨ @@ -354,4 +354,4 @@ Si vous allez sur l'UI `/docs` de l'API, vous verrez qu'elle est maintenant à j Vous pouvez utiliser [**SQLModel**](https://sqlmodel.tiangolo.com/) pour interagir avec une base SQL et simplifier le code avec des *modèles de données* et des *modèles de table*. -Vous pouvez en apprendre beaucoup plus dans la documentation **SQLModel**, il y a un mini [tutoriel plus long sur l'utilisation de SQLModel avec **FastAPI**](https://sqlmodel.tiangolo.com/tutorial/fastapi/). 🚀 +Vous pouvez en apprendre beaucoup plus dans les documents de **SQLModel**, il y a un mini [tutoriel plus long sur l'utilisation de SQLModel avec **FastAPI**](https://sqlmodel.tiangolo.com/tutorial/fastapi/). 🚀 diff --git a/docs/fr/docs/tutorial/static-files.md b/docs/fr/docs/tutorial/static-files.md index 6a54840af..cfbbe86b9 100644 --- a/docs/fr/docs/tutorial/static-files.md +++ b/docs/fr/docs/tutorial/static-files.md @@ -2,6 +2,14 @@ Vous pouvez servir des fichiers statiques automatiquement à partir d'un répertoire en utilisant `StaticFiles`. +/// tip | Astuce + +Si vous devez héberger un frontend, utilisez plutôt `app.frontend()`, lisez-en davantage dans [Frontend](frontend.md). + +`app.frontend()` utilise `StaticFiles` en interne, avec plusieurs avantages supplémentaires pour les frontends, comme la gestion du routing côté client. + +/// + ## Utiliser `StaticFiles` { #use-staticfiles } - Importer `StaticFiles`. diff --git a/docs/fr/docs/tutorial/stream-json-lines.md b/docs/fr/docs/tutorial/stream-json-lines.md index aed0205cb..c06c0e006 100644 --- a/docs/fr/docs/tutorial/stream-json-lines.md +++ b/docs/fr/docs/tutorial/stream-json-lines.md @@ -1,8 +1,8 @@ # Diffuser des JSON Lines { #stream-json-lines } -Vous pouvez avoir une séquence de données que vous souhaitez envoyer en « flux » ; vous pouvez le faire avec « JSON Lines ». +Vous pouvez avoir une séquence de données que vous souhaitez envoyer en « flux », vous pouvez le faire avec « JSON Lines ». -/// info +/// note | Remarque Ajouté dans FastAPI 0.134.0. @@ -48,7 +48,7 @@ Une réponse aurait un type de contenu `application/jsonl` (au lieu de `applicat C'est très similaire à un tableau JSON (équivalent d'une liste Python), mais au lieu d'être entouré de `[]` et d'avoir des `,` entre les éléments, il y a un objet JSON par ligne, ils sont séparés par un caractère de saut de ligne. -/// info +/// note | Remarque Le point important est que votre application pourra produire chaque ligne à son tour, tandis que le client consomme les lignes précédentes. diff --git a/docs/fr/docs/tutorial/testing.md b/docs/fr/docs/tutorial/testing.md index 5cb2ee629..883a61155 100644 --- a/docs/fr/docs/tutorial/testing.md +++ b/docs/fr/docs/tutorial/testing.md @@ -8,11 +8,11 @@ Avec cela, vous pouvez utiliser [pytest](https://docs.pytest.org/) directement a ## Utiliser `TestClient` { #using-testclient } -/// info +/// note | Remarque Pour utiliser `TestClient`, installez d’abord [`httpx`](https://www.python-httpx.org). -Vous devez créer un [environnement virtuel](../virtual-environments.md), l’activer, puis y installer le paquet, par exemple : +Vous devez vous assurer de créer un [environnement virtuel](../virtual-environments.md), de l’activer, puis d’y installer le paquet, par exemple : ```console $ pip install httpx @@ -144,7 +144,7 @@ Par exemple : Pour plus d’informations sur la manière de transmettre des données au backend (en utilisant `httpx` ou le `TestClient`), consultez la [documentation HTTPX](https://www.python-httpx.org). -/// info +/// note | Remarque Notez que le `TestClient` reçoit des données qui peuvent être converties en JSON, pas des modèles Pydantic. @@ -156,7 +156,7 @@ Si vous avez un modèle Pydantic dans votre test et que vous souhaitez envoyer s Après cela, vous avez simplement besoin d’installer `pytest`. -Vous devez créer un [environnement virtuel](../virtual-environments.md), l’activer, puis y installer le paquet, par exemple : +Vous devez vous assurer de créer un [environnement virtuel](../virtual-environments.md), de l’activer, puis d’y installer le paquet, par exemple :
diff --git a/docs/fr/docs/virtual-environments.md b/docs/fr/docs/virtual-environments.md index c9eefb37b..f2a9f47da 100644 --- a/docs/fr/docs/virtual-environments.md +++ b/docs/fr/docs/virtual-environments.md @@ -1,6 +1,6 @@ # Environnements virtuels { #virtual-environments } -Lorsque vous travaillez sur des projets Python, vous devriez probablement utiliser un environnement virtuel (ou un mécanisme similaire) pour isoler les packages que vous installez pour chaque projet. +Lorsque vous travaillez sur des projets Python, vous devriez probablement utiliser un **environnement virtuel** (ou un mécanisme similaire) pour isoler les packages que vous installez pour chaque projet. /// note | Remarque @@ -10,19 +10,19 @@ Si vous connaissez déjà les environnements virtuels, comment les créer et les /// tip | Astuce -Un environnement virtuel est différent d’une variable d’environnement. +Un **environnement virtuel** est différent d’une **variable d’environnement**. -Une variable d’environnement est une variable du système qui peut être utilisée par des programmes. +Une **variable d’environnement** est une variable du système qui peut être utilisée par des programmes. -Un environnement virtuel est un répertoire contenant certains fichiers. +Un **environnement virtuel** est un répertoire contenant certains fichiers. /// /// note | Remarque -Cette page vous apprendra à utiliser les environnements virtuels et à comprendre leur fonctionnement. +Cette page vous apprendra à utiliser les **environnements virtuels** et à comprendre leur fonctionnement. -Si vous êtes prêt à adopter un outil qui gère tout pour vous (y compris l’installation de Python), essayez [uv](https://github.com/astral-sh/uv). +Si vous êtes prêt à adopter un **outil qui gère tout** pour vous (y compris l’installation de Python), essayez [uv](https://github.com/astral-sh/uv). /// @@ -53,11 +53,11 @@ $ cd awesome-project ## Créer un environnement virtuel { #create-a-virtual-environment } -Lorsque vous commencez à travailler sur un projet Python pour la première fois, créez un environnement virtuel dans votre projet. +Lorsque vous commencez à travailler sur un projet Python **pour la première fois**, créez un environnement virtuel **dans votre projet**. /// tip | Astuce -Vous n’avez besoin de faire cela qu’une seule fois par projet, pas à chaque fois que vous travaillez. +Vous n’avez besoin de faire cela qu’**une seule fois par projet**, pas à chaque fois que vous travaillez. /// @@ -120,7 +120,7 @@ Activez le nouvel environnement virtuel afin que toute commande Python que vous /// tip | Astuce -Faites cela à chaque fois que vous démarrez une nouvelle session de terminal pour travailler sur le projet. +Faites cela **chaque fois** que vous démarrez une **nouvelle session de terminal** pour travailler sur le projet. /// @@ -164,9 +164,9 @@ $ source .venv/Scripts/activate /// tip | Astuce -Chaque fois que vous installez un nouveau package dans cet environnement, activez de nouveau l’environnement. +Chaque fois que vous installez un **nouveau package** dans cet environnement, **activez** de nouveau l’environnement. -Vous vous assurez ainsi que si vous utilisez un programme de terminal (CLI) installé par ce package, vous utilisez celui de votre environnement virtuel et non un autre qui pourrait être installé globalement, probablement avec une version différente de celle dont vous avez besoin. +Vous vous assurez ainsi que si vous utilisez un **programme de terminal (CLI)** installé par ce package, vous utilisez celui de votre environnement virtuel et non un autre qui pourrait être installé globalement, probablement avec une version différente de celle dont vous avez besoin. /// @@ -176,7 +176,7 @@ Vérifiez que l’environnement virtuel est actif (la commande précédente a fo /// tip | Astuce -C’est facultatif, mais c’est une bonne manière de vérifier que tout fonctionne comme prévu et que vous utilisez l’environnement virtuel voulu. +C’est **facultatif**, mais c’est une bonne manière de **vérifier** que tout fonctionne comme prévu et que vous utilisez l’environnement virtuel voulu. /// @@ -220,13 +220,13 @@ Si vous utilisez [`uv`](https://github.com/astral-sh/uv), vous l’utiliserez po /// -Si vous utilisez `pip` pour installer des packages (il est fourni par défaut avec Python), vous devez le mettre à niveau vers la dernière version. +Si vous utilisez `pip` pour installer des packages (il est fourni par défaut avec Python), vous devez le **mettre à niveau** vers la dernière version. Beaucoup d’erreurs exotiques lors de l’installation d’un package se résolvent simplement en mettant d’abord `pip` à niveau. /// tip | Astuce -Vous feriez normalement cela une seule fois, juste après avoir créé l’environnement virtuel. +Vous feriez normalement cela **une seule fois**, juste après avoir créé l’environnement virtuel. /// @@ -264,7 +264,7 @@ Cette commande installera pip s’il n’est pas déjà installé et garantit au ## Ajouter `.gitignore` { #add-gitignore } -Si vous utilisez Git (vous devriez), ajoutez un fichier `.gitignore` pour exclure tout ce qui se trouve dans votre `.venv` de Git. +Si vous utilisez **Git** (vous devriez), ajoutez un fichier `.gitignore` pour exclure tout ce qui se trouve dans votre `.venv` de Git. /// tip | Astuce @@ -274,7 +274,7 @@ Si vous avez utilisé [`uv`](https://github.com/astral-sh/uv) pour créer l’en /// tip | Astuce -Faites cela une seule fois, juste après avoir créé l’environnement virtuel. +Faites cela **une seule fois**, juste après avoir créé l’environnement virtuel. /// @@ -308,19 +308,19 @@ Après avoir activé l’environnement, vous pouvez y installer des packages. /// tip | Astuce -Faites cela une seule fois lorsque vous installez ou mettez à niveau les packages nécessaires à votre projet. +Faites cela **une seule fois** lorsque vous installez ou mettez à niveau les packages nécessaires à votre projet. -Si vous devez mettre à niveau une version ou ajouter un nouveau package, vous le referez. +Si vous devez mettre à niveau une version ou ajouter un nouveau package, vous le **referez**. /// ### Installer des packages directement { #install-packages-directly } -Si vous êtes pressé et ne souhaitez pas utiliser un fichier pour déclarer les dépendances de votre projet, vous pouvez les installer directement. +Si vous êtes pressé et ne souhaitez pas utiliser un fichier pour déclarer les dépendances de packages de votre projet, vous pouvez les installer directement. /// tip | Astuce -C’est une très bonne idée de placer les packages et leurs versions nécessaires à votre programme dans un fichier (par exemple `requirements.txt` ou `pyproject.toml`). +C’est une (très) bonne idée de placer les packages et leurs versions nécessaires à votre programme dans un fichier (par exemple `requirements.txt` ou `pyproject.toml`). /// @@ -421,13 +421,13 @@ Par exemple : /// tip | Astuce -Vous devez normalement faire cela une seule fois, lorsque vous créez l’environnement virtuel. +Vous devez normalement faire cela seulement **une fois**, lorsque vous créez l’environnement virtuel. /// ## Désactiver l’environnement virtuel { #deactivate-the-virtual-environment } -Une fois que vous avez fini de travailler sur votre projet, vous pouvez désactiver l’environnement virtuel. +Une fois que vous avez fini de travailler sur votre projet, vous pouvez **désactiver** l’environnement virtuel.
@@ -457,17 +457,17 @@ Continuez la lecture. 👇🤓 Pour travailler avec FastAPI, vous devez installer [Python](https://www.python.org/). -Ensuite, vous devrez installer FastAPI et tout autre package que vous souhaitez utiliser. +Ensuite, vous devez **installer** FastAPI et tout autre **package** que vous souhaitez utiliser. Pour installer des packages, vous utiliseriez normalement la commande `pip` fournie avec Python (ou des alternatives similaires). -Néanmoins, si vous utilisez simplement `pip` directement, les packages seraient installés dans votre environnement Python global (l’installation globale de Python). +Néanmoins, si vous utilisez simplement `pip` directement, les packages seraient installés dans votre **environnement Python global** (l’installation globale de Python). ### Le problème { #the-problem } Alors, quel est le problème d’installer des packages dans l’environnement Python global ? -À un moment donné, vous finirez probablement par écrire de nombreux programmes différents qui dépendent de packages différents. Et certains de ces projets sur lesquels vous travaillez dépendront de versions différentes du même package. 😱 +À un moment donné, vous finirez probablement par écrire de nombreux programmes différents qui dépendent de **packages différents**. Et certains de ces projets sur lesquels vous travaillez dépendront de **versions différentes** du même package. 😱 Par exemple, vous pourriez créer un projet appelé `philosophers-stone`, ce programme dépend d’un autre package appelé **`harry`, en version `1`**. Vous devez donc installer `harry`. @@ -483,7 +483,7 @@ flowchart LR azkaban(prisoner-of-azkaban) --> |requires| harry-3[harry v3] ``` -Mais maintenant, le problème est que, si vous installez les packages globalement (dans l’environnement global) au lieu de dans un environnement virtuel local, vous devrez choisir quelle version de `harry` installer. +Mais maintenant, le problème est que, si vous installez les packages globalement (dans l’environnement global) au lieu de dans un **environnement virtuel** local, vous devrez choisir quelle version de `harry` installer. Si vous voulez exécuter `philosophers-stone`, vous devrez d’abord installer `harry` en version `1`, par exemple avec : @@ -519,7 +519,7 @@ $ pip install "harry==3" Et vous vous retrouverez alors avec `harry` version `3` installé dans votre environnement Python global. -Et si vous essayez d’exécuter à nouveau `philosophers-stone`, il y a une chance que cela ne fonctionne pas car il a besoin de `harry` version `1`. +Et si vous essayez d’exécuter à nouveau `philosophers-stone`, il y a une chance que cela **ne fonctionne pas** car il a besoin de `harry` version `1`. ```mermaid flowchart LR @@ -538,13 +538,13 @@ flowchart LR /// tip | Astuce -Il est très courant que les packages Python fassent de leur mieux pour éviter les changements cassants dans les nouvelles versions, mais il vaut mieux jouer la sécurité et installer de nouvelles versions intentionnellement et lorsque vous pouvez exécuter les tests pour vérifier que tout fonctionne correctement. +Il est très courant que les packages Python fassent de leur mieux pour **éviter les changements cassants** dans les **nouvelles versions**, mais il vaut mieux jouer la sécurité et installer de nouvelles versions intentionnellement et lorsque vous pouvez exécuter les tests pour vérifier que tout fonctionne correctement. /// -Maintenant, imaginez cela avec beaucoup d’autres packages dont tous vos projets dépendent. C’est très difficile à gérer. Et vous finiriez probablement par exécuter certains projets avec des versions incompatibles des packages, sans savoir pourquoi quelque chose ne fonctionne pas. +Maintenant, imaginez cela avec **beaucoup** d’autres **packages** dont tous vos **projets dépendent**. C’est très difficile à gérer. Et vous finiriez probablement par exécuter certains projets avec des **versions incompatibles** des packages, sans savoir pourquoi quelque chose ne fonctionne pas. -De plus, selon votre système d’exploitation (par exemple Linux, Windows, macOS), il se peut qu’il soit livré avec Python déjà installé. Et dans ce cas, il avait probablement des packages préinstallés avec des versions spécifiques nécessaires à votre système. Si vous installez des packages dans l’environnement Python global, vous pourriez finir par casser certains des programmes fournis avec votre système d’exploitation. +De plus, selon votre système d’exploitation (par exemple Linux, Windows, macOS), il se peut qu’il soit livré avec Python déjà installé. Et dans ce cas, il avait probablement des packages préinstallés avec des versions spécifiques **nécessaires à votre système**. Si vous installez des packages dans l’environnement Python global, vous pourriez finir par **casser** certains des programmes fournis avec votre système d’exploitation. ## Où les packages sont-ils installés { #where-are-packages-installed } @@ -566,17 +566,17 @@ $ pip install "fastapi[standard]" Cela téléchargera un fichier compressé avec le code de FastAPI, normalement depuis [PyPI](https://pypi.org/project/fastapi/). -Il téléchargera également des fichiers pour d’autres packages dont FastAPI dépend. +Il **téléchargera** également des fichiers pour d’autres packages dont FastAPI dépend. -Ensuite, il extraira tous ces fichiers et les placera dans un répertoire de votre ordinateur. +Ensuite, il **extraira** tous ces fichiers et les placera dans un répertoire de votre ordinateur. -Par défaut, il placera ces fichiers téléchargés et extraits dans le répertoire fourni avec votre installation de Python, c’est l’environnement global. +Par défaut, il placera ces fichiers téléchargés et extraits dans le répertoire fourni avec votre installation de Python, c’est l’**environnement global**. ## Qu’est-ce qu’un environnement virtuel { #what-are-virtual-environments } -La solution aux problèmes posés par le fait d’avoir tous les packages dans l’environnement global est d’utiliser un environnement virtuel pour chaque projet sur lequel vous travaillez. +La solution aux problèmes posés par le fait d’avoir tous les packages dans l’environnement global est d’utiliser un **environnement virtuel pour chaque projet** sur lequel vous travaillez. -Un environnement virtuel est un répertoire, très similaire à celui global, où vous pouvez installer les packages pour un projet. +Un environnement virtuel est un **répertoire**, très similaire à celui global, où vous pouvez installer les packages pour un projet. De cette manière, chaque projet aura son propre environnement virtuel (répertoire `.venv`) avec ses propres packages. @@ -730,7 +730,7 @@ et utilisera celui-ci. //// -Un détail important est qu’il placera le chemin de l’environnement virtuel au début de la variable `PATH`. Le système le trouvera avant de trouver tout autre Python disponible. Ainsi, lorsque vous exécutez `python`, il utilisera le Python de l’environnement virtuel au lieu de tout autre `python` (par exemple, un `python` d’un environnement global). +Un détail important est qu’il placera le chemin de l’environnement virtuel au **début** de la variable `PATH`. Le système le trouvera **avant** de trouver tout autre Python disponible. Ainsi, lorsque vous exécutez `python`, il utilisera le Python **de l’environnement virtuel** au lieu de tout autre `python` (par exemple, un `python` d’un environnement global). Activer un environnement virtuel change aussi deux ou trois autres choses, mais c’est l’un des points les plus importants. @@ -766,11 +766,11 @@ C:\Users\user\code\awesome-project\.venv\Scripts\python //// -Cela signifie que le programme `python` qui sera utilisé est celui dans l’environnement virtuel. +Cela signifie que le programme `python` qui sera utilisé est celui **dans l’environnement virtuel**. Vous utilisez `which` sous Linux et macOS et `Get-Command` sous Windows PowerShell. -La façon dont cette commande fonctionne est qu’elle va vérifier la variable d’environnement `PATH`, en parcourant chaque chemin dans l’ordre, à la recherche du programme nommé `python`. Une fois trouvé, elle vous affichera le chemin vers ce programme. +La façon dont cette commande fonctionne est qu’elle va vérifier la variable d’environnement `PATH`, en parcourant **chaque chemin dans l’ordre**, à la recherche du programme nommé `python`. Une fois trouvé, elle vous **affichera le chemin** vers ce programme. La partie la plus importante est que lorsque vous appelez `python`, c’est exactement « `python` » qui sera exécuté. @@ -778,9 +778,9 @@ Ainsi, vous pouvez confirmer si vous êtes dans le bon environnement virtuel. /// tip | Astuce -Il est facile d’activer un environnement virtuel, d’obtenir un Python, puis d’aller vers un autre projet. +Il est facile d’activer un environnement virtuel, d’obtenir un Python, puis d’**aller vers un autre projet**. -Et le second projet ne fonctionnerait pas parce que vous utilisez le Python incorrect, provenant d’un environnement virtuel d’un autre projet. +Et le second projet **ne fonctionnerait pas** parce que vous utilisez le **Python incorrect**, provenant d’un environnement virtuel d’un autre projet. Il est utile de pouvoir vérifier quel `python` est utilisé. 🤓 @@ -788,9 +788,9 @@ Il est utile de pouvoir vérifier quel `python` est utilisé. 🤓 ## Pourquoi désactiver un environnement virtuel { #why-deactivate-a-virtual-environment } -Par exemple, vous pourriez travailler sur un projet `philosophers-stone`, activer cet environnement virtuel, installer des packages et travailler avec cet environnement. +Par exemple, vous pourriez travailler sur un projet `philosophers-stone`, **activer cet environnement virtuel**, installer des packages et travailler avec cet environnement. -Puis vous souhaitez travailler sur un autre projet `prisoner-of-azkaban`. +Puis vous souhaitez travailler sur **un autre projet** `prisoner-of-azkaban`. Vous allez vers ce projet : @@ -842,23 +842,23 @@ I solemnly swear 🐺 ## Alternatives { #alternatives } -Ceci est un guide simple pour vous lancer et vous montrer comment tout fonctionne en dessous. +Ceci est un guide simple pour vous lancer et vous montrer comment tout fonctionne **en dessous**. -Il existe de nombreuses alternatives pour gérer les environnements virtuels, les dépendances de packages (requirements), les projets. +Il existe de nombreuses **alternatives** pour gérer les environnements virtuels, les dépendances de packages (requirements), les projets. -Lorsque vous êtes prêt et souhaitez utiliser un outil pour gérer l’ensemble du projet, les dépendances, les environnements virtuels, etc., je vous suggère d’essayer [uv](https://github.com/astral-sh/uv). +Lorsque vous êtes prêt et souhaitez utiliser un outil pour **gérer l’ensemble du projet**, les dépendances de packages, les environnements virtuels, etc., je vous suggère d’essayer [uv](https://github.com/astral-sh/uv). `uv` peut faire beaucoup de choses, il peut : -* Installer Python pour vous, y compris différentes versions -* Gérer l’environnement virtuel pour vos projets -* Installer des packages -* Gérer les dépendances de packages et leurs versions pour votre projet -* Vous assurer d’avoir un ensemble exact de packages et de versions à installer, y compris leurs dépendances, afin que vous puissiez être certain d’exécuter votre projet en production exactement comme sur votre ordinateur pendant le développement, cela s’appelle le locking +* **Installer Python** pour vous, y compris différentes versions +* Gérer l’**environnement virtuel** pour vos projets +* Installer des **packages** +* Gérer les **dépendances et versions** de packages pour votre projet +* Vous assurer d’avoir un ensemble **exact** de packages et de versions à installer, y compris leurs dépendances, afin que vous puissiez être certain d’exécuter votre projet en production exactement comme sur votre ordinateur pendant le développement, cela s’appelle le **locking** * Et bien d’autres choses ## Conclusion { #conclusion } -Si vous avez lu et compris tout cela, vous en savez maintenant bien plus sur les environnements virtuels que beaucoup de développeurs. 🤓 +Si vous avez lu et compris tout cela, vous en savez maintenant **bien plus** sur les environnements virtuels que beaucoup de développeurs. 🤓 -Connaître ces détails vous sera très probablement utile à l’avenir lorsque vous déboguerez quelque chose qui semble complexe, mais vous saurez comment tout fonctionne en dessous. 😎 +Connaître ces détails vous sera très probablement utile à l’avenir lorsque vous déboguerez quelque chose qui semble complexe, mais vous saurez **comment tout fonctionne en dessous**. 😎 diff --git a/docs/hi/docs/_llm-test.md b/docs/hi/docs/_llm-test.md new file mode 100644 index 000000000..6dfa18fd7 --- /dev/null +++ b/docs/hi/docs/_llm-test.md @@ -0,0 +1,495 @@ +# LLM परीक्षण फ़ाइल { #llm-test-file } + +यह दस्तावेज़ यह परखता है कि LLM, जो डॉक्यूमेंटेशन का अनुवाद करता है, `scripts/translate.py` में दिए गए `general_prompt` और `docs/{language code}/llm-prompt.md` में दिए गए भाषा-विशिष्ट प्रॉम्प्ट को समझता है या नहीं। भाषा-विशिष्ट प्रॉम्प्ट को `general_prompt` के साथ जोड़ा जाता है। + +यहाँ जो परीक्षण जोड़े गए हैं, वे भाषा-विशिष्ट प्रॉम्प्ट के सभी डिज़ाइनर्स को दिखाई देंगे। + +उपयोग इस प्रकार करें: + +* एक भाषा-विशिष्ट प्रॉम्प्ट रखें - `docs/{language code}/llm-prompt.md`। +* इस दस्तावेज़ का अपने इच्छित लक्ष्य-भाषा में नया अनुवाद करें (उदाहरण के लिए `translate.py` के `translate-page` कमांड को देखें)। यह अनुवाद `docs/{language code}/docs/_llm-test.md` के अंतर्गत बना देगा। +* जाँचें कि अनुवाद में सब कुछ ठीक है। +* आवश्यकता होने पर, अपने भाषा-विशिष्ट प्रॉम्प्ट, जनरल प्रॉम्प्ट या अंग्रेज़ी दस्तावेज़ में सुधार करें। +* फिर अनुवाद में बचे हुए मुद्दों को हाथ से ठीक करें ताकि यह एक अच्छा अनुवाद बन जाए। +* दुबारा अनुवाद करें, इस बार अच्छा अनुवाद जगह पर रहते हुए। आदर्श परिणाम होगा कि LLM अब अनुवाद में कोई परिवर्तन न करे। इसका मतलब है कि जनरल प्रॉम्प्ट और आपका भाषा-विशिष्ट प्रॉम्प्ट जितने अच्छे हो सकते हैं उतने अच्छे हैं (कभी-कभी यह कुछ यादृच्छिक-से परिवर्तन कर देगा, कारण यह है कि [LLM नियतात्मक एल्गोरिथ्म नहीं हैं](https://doublespeak.chat/#/handbook#deterministic-output))। + +परीक्षण: + +## कोड स्निपेट्स { #code-snippets } + +//// tab | परीक्षण + +यह एक कोड स्निपेट है: `foo`। और यह एक और कोड स्निपेट है: `bar`। और एक और: `baz quux`। + +//// + +//// tab | जानकारी + +कोड स्निपेट्स की सामग्री को ज्यों का त्यों छोड़ देना चाहिए। + +`scripts/translate.py` में जनरल प्रॉम्प्ट के सेक्शन `### Content of code snippets` को देखें। + +//// + +## उद्धरण { #quotes } + +//// tab | परीक्षण + +कल, मेरे दोस्त ने लिखा: "अगर आप 'गलत' को सही लिखते हैं, तो आपने उसे गलत लिखा है"। जिसके जवाब में मैंने कहा: "सही, लेकिन 'गलत' गलत है '"गलत"' नहीं"। + +/// note | टिप्पणी + +LLM संभवतः इसे गलत अनुवादित करेगा। दिलचस्प यह है कि पुनः-अनुवाद करने पर क्या यह ठीक किया हुआ अनुवाद बनाए रखता है। + +/// + +//// + +//// tab | जानकारी + +प्रॉम्प्ट डिज़ाइनर यह चुन सकते हैं कि वे साधारण कोट्स को टाइपोग्राफ़िक कोट्स में बदलना चाहते हैं या नहीं। उन्हें ज्यों का त्यों छोड़ना भी ठीक है। + +उदाहरण के लिए `docs/de/llm-prompt.md` में सेक्शन `### Quotes` देखें। + +//// + +## कोड स्निपेट्स में उद्धरण { #quotes-in-code-snippets } + +//// tab | परीक्षण + +`pip install "foo[bar]"` + +कोड स्निपेट्स में स्ट्रिंग लिटरल्स के उदाहरण: `"this"`, `'that'`. + +कोड स्निपेट्स में स्ट्रिंग लिटरल्स का एक कठिन उदाहरण: `f"I like {'oranges' if orange else "apples"}"` + +हार्डकोर: `Yesterday, my friend wrote: "If you spell incorrectly correctly, you have spelled it incorrectly". To which I answered: "Correct, but 'incorrectly' is incorrectly not '"incorrectly"'"` + +//// + +//// tab | जानकारी + +... लेकिन, कोड स्निपेट्स के अंदर के उद्धरण ज्यों के त्यों रहने चाहिए। + +//// + +## कोड ब्लॉक्स { #code-blocks } + +//// tab | परीक्षण + +एक Bash कोड उदाहरण... + +```bash +# ब्रह्मांड के लिए अभिवादन प्रिंट करें +echo "Hello universe" +``` + +...और एक कंसोल कोड उदाहरण... + +```console +$ fastapi run main.py + FastAPI Starting server + Searching for package file structure +``` + +...और एक अन्य कंसोल कोड उदाहरण... + +```console +// "Code" नाम की डायरेक्टरी बनाएँ +$ mkdir code +// उस डायरेक्टरी में जाएँ +$ cd code +``` + +...और एक Python कोड उदाहरण... + +```Python +wont_work() # यह काम नहीं करेगा 😱 +works(foo="bar") # यह काम करता है 🎉 +``` + +...और बस इतना ही। + +//// + +//// tab | जानकारी + +कोड ब्लॉक्स के अंदर के कोड में बदलाव नहीं होना चाहिए, सिवाय टिप्पणियों (comments) के। + +`scripts/translate.py` में जनरल प्रॉम्प्ट के सेक्शन `### Content of code blocks` को देखें। + +//// + +## टैब और रंगीन बॉक्स { #tabs-and-colored-boxes } + +//// tab | परीक्षण + +/// note | टिप्पणी +कुछ पाठ +/// + +/// note | तकनीकी विवरण +कुछ पाठ +/// + +/// tip | सुझाव +कुछ पाठ +/// + +/// warning | चेतावनी +कुछ पाठ +/// + +/// danger | खतरा +कुछ पाठ +/// + +//// + +//// tab | जानकारी + +टैब और `Info`/`Note`/`Warning`/आदि ब्लॉक्स में उनके शीर्षक का अनुवाद ऊर्ध्वाधर रेखा (`|`) के बाद जोड़ा जाना चाहिए। + +`scripts/translate.py` में जनरल प्रॉम्प्ट के सेक्शन `### Special blocks` और `### Tab blocks` देखें। + +//// + +## वेब और आंतरिक लिंक { #web-and-internal-links } + +//// tab | परीक्षण + +लिंक का टेक्स्ट अनुवादित होना चाहिए, लिंक का पता अपरिवर्तित रहे: + +* [ऊपर दिए गए शीर्षक का लिंक](#code-snippets) +* [आंतरिक लिंक](index.md#installation) +* [बाहरी लिंक](https://sqlmodel.tiangolo.com/) +* [एक स्टाइल का लिंक](https://fastapi.tiangolo.com/css/styles.css) +* [एक स्क्रिप्ट का लिंक](https://fastapi.tiangolo.com/js/logic.js) +* [एक छवि का लिंक](https://fastapi.tiangolo.com/img/foo.jpg) + +लिंक का टेक्स्ट अनुवादित होना चाहिए, लिंक का पता अनुवाद की ओर इशारा करना चाहिए: + +* [FastAPI लिंक](https://fastapi.tiangolo.com/hi/) + +//// + +//// tab | जानकारी + +लिंक अनुवादित होने चाहिए, लेकिन उनके पते अपरिवर्तित रहें। अपवाद है FastAPI डॉक्यूमेंटेशन के पेजों के पूर्ण (absolute) लिंक। उस स्थिति में लिंक अनुवाद की ओर इशारा करना चाहिए। + +`scripts/translate.py` में जनरल प्रॉम्प्ट के सेक्शन `### Links` देखें। + +//// + +## HTML "abbr" एलिमेंट्स { #html-abbr-elements } + +//// tab | परीक्षण + +यहाँ HTML "abbr" एलिमेंट्स में लिपटी कुछ चीज़ें हैं (कुछ गढ़ी हुई भी): + +### abbr एक पूरा वाक्यांश देता है { #the-abbr-gives-a-full-phrase } + +* GTD +* lt +* XWT +* PSGI + +### abbr एक पूरा वाक्यांश और उसका स्पष्टीकरण देता है { #the-abbr-gives-a-full-phrase-and-an-explanation } + +* MDN +* I/O. + +//// + +//// tab | जानकारी + +"abbr" एलिमेंट्स के "title" ऐट्रिब्यूट्स का अनुवाद कुछ विशिष्ट निर्देशों का पालन करते हुए किया जाता है। + +अनुवाद अपने स्वयं के "abbr" एलिमेंट्स जोड़ सकते हैं जिन्हें LLM को हटाना नहीं चाहिए। जैसे अंग्रेज़ी शब्दों को समझाने के लिए। + +`scripts/translate.py` में जनरल प्रॉम्प्ट के सेक्शन `### HTML abbr elements` देखें। + +//// + +## HTML "dfn" एलिमेंट्स { #html-dfn-elements } + +* क्लस्टर +* डीप लर्निंग + +## शीर्षक { #headings } + +//// tab | परीक्षण + +### एक वेबऐप विकसित करें - एक ट्यूटोरियल { #develop-a-webapp-a-tutorial } + +नमस्ते। + +### टाइप हिंट्स और -एनोटेशन्स { #type-hints-and-annotations } + +फिर से नमस्ते। + +### सुपर- और सबक्लासेज़ { #super-and-subclasses } + +फिर से नमस्ते। + +//// + +//// tab | जानकारी + +शीर्षकों के लिए एकमात्र कड़ा नियम यह है कि LLM कर्ली ब्रैकेट्स के अंदर के हैश-पार्ट को अपरिवर्तित छोड़े, जिससे लिंक न टूटें। + +`scripts/translate.py` में जनरल प्रॉम्प्ट के सेक्शन `### Headings` देखें। + +कुछ भाषा-विशिष्ट निर्देशों के लिए, जैसे `docs/de/llm-prompt.md` में सेक्शन `### Headings` देखें। + +//// + +## डॉक्स में प्रयुक्त शब्द { #terms-used-in-the-docs } + +//// tab | परीक्षण + +* आप +* आपका + +* उदा. +* आदि + +* `foo` एक `int` के रूप में +* `bar` एक `str` के रूप में +* `baz` एक `list` के रूप में + +* ट्यूटोरियल - उपयोगकर्ता गाइड +* उन्नत उपयोगकर्ता गाइड +* SQLModel डॉक्स +* API डॉक्स +* स्वचालित डॉक्स + +* डेटा साइंस +* डीप लर्निंग +* मशीन लर्निंग +* डिपेंडेंसी इंजेक्शन +* HTTP बेसिक ऑथेंटिकेशन +* HTTP डाइजेस्ट +* ISO फ़ॉरमैट +* JSON Schema मानक +* JSON स्कीमा +* स्कीमा परिभाषा +* पासवर्ड फ्लो +* मोबाइल + +* अप्रचलित +* डिज़ाइन किया गया +* अमान्य +* तुरंत +* मानक +* डिफ़ॉल्ट +* केस-संवेदी +* केस-असंवेदी + +* एप्लिकेशन को सर्व करना +* पेज को सर्व करना + +* ऐप +* एप्लिकेशन + +* रिक्वेस्ट +* रिस्पांस +* त्रुटि रिस्पांस + +* पाथ ऑपरेशन +* पाथ ऑपरेशन डेकोरेटर +* पाथ ऑपरेशन फ़ंक्शन + +* बॉडी +* रिक्वेस्ट बॉडी +* रिस्पांस बॉडी +* JSON बॉडी +* फॉर्म बॉडी +* फ़ाइल बॉडी +* फ़ंक्शन बॉडी + +* पैरामीटर +* बॉडी पैरामीटर +* पाथ पैरामीटर +* क्वेरी पैरामीटर +* कुकी पैरामीटर +* हेडर पैरामीटर +* फॉर्म पैरामीटर +* फ़ंक्शन पैरामीटर + +* इवेंट +* स्टार्टअप इवेंट +* सर्वर का स्टार्टअप +* शटडाउन इवेंट +* लाइफस्पैन इवेंट + +* हैंडलर +* इवेंट हैंडलर +* एक्सेप्शन हैंडलर +* हैंडल करना + +* मॉडल +* Pydantic मॉडल +* डेटा मॉडल +* डेटाबेस मॉडल +* फॉर्म मॉडल +* मॉडल ऑब्जेक्ट + +* क्लास +* बेस क्लास +* पैरेंट क्लास +* सबक्लास +* चाइल्ड क्लास +* सिब्लिंग क्लास +* क्लास मेथड + +* हेडर +* हेडर्स +* ऑथराइज़ेशन हेडर +* `Authorization` हेडर +* फॉरवर्डेड हेडर + +* डिपेंडेंसी इंजेक्शन सिस्टम +* डिपेंडेंसी +* डिपेंडेबल +* डिपेन्डन्ट + +* I/O बाउंड +* CPU बाउंड +* समकालिकता +* समान्तरता +* मल्टीप्रोसेसिंग + +* env var +* पर्यावरण चर +* `PATH` +* `PATH` वेरिएबल + +* प्रमाणीकरण +* प्रमाणीकरण प्रदाता +* अधिकारीकरण +* अधिकारीकरण फॉर्म +* अधिकारीकरण प्रदाता +* उपयोगकर्ता प्रमाणीकरण करता है +* सिस्टम उपयोगकर्ता का प्रमाणीकरण करता है + +* CLI +* कमांड लाइन इंटरफेस + +* सर्वर +* क्लाइंट + +* क्लाउड प्रदाता +* क्लाउड सेवा + +* विकास +* विकास चरण + +* dict +* डिक्शनरी +* एन्युमरेशन +* एनम +* एनम सदस्य + +* एन्कोडर +* डीकोडर +* एन्कोड करना +* डीकोड करना + +* एक्सेप्शन +* रेज़ करना + +* एक्सप्रेशन +* स्टेटमेंट + +* फ्रंटएंड +* बैकएंड + +* GitHub चर्चा +* GitHub इश्यू + +* प्रदर्शन +* प्रदर्शन अनुकूलन + +* रिटर्न टाइप +* रिटर्न वैल्यू + +* सुरक्षा +* सुरक्षा स्कीम + +* टास्क +* बैकग्राउंड टास्क +* टास्क फ़ंक्शन + +* टेम्पलेट +* टेम्पलेट इंजन + +* टाइप एनोटेशन +* टाइप हिंट + +* सर्वर वर्कर +* Uvicorn वर्कर +* Gunicorn Worker +* वर्कर प्रोसेस +* वर्कर क्लास +* वर्कलोड + +* डिप्लॉयमेंट +* डिप्लॉय करना + +* SDK +* सॉफ़्टवेयर डेवलपमेंट किट + +* `APIRouter` +* `requirements.txt` +* Bearer Token +* ब्रेकिंग चेंज +* बग +* बटन +* कॉल करने योग्य +* कोड +* कमिट +* कॉन्टेक्स्ट मैनेजर +* कोरूटीन +* डेटाबेस सेशन +* डिस्क +* डोमेन +* इंजन +* नकली X +* HTTP GET मेथड +* आइटम +* लाइब्रेरी +* लाइफस्पैन +* लॉक +* मिडलवेयर +* मोबाइल एप्लिकेशन +* मॉड्यूल +* माउंटिंग +* नेटवर्क +* ओरिजिन +* ओवरराइड +* पेलोड +* प्रोसेसर +* प्रॉपर्टी +* प्रॉक्सी +* पुल रिक्वेस्ट +* क्वेरी +* RAM +* रिमोट मशीन +* स्टेटस कोड +* स्ट्रिंग +* टैग +* वेब फ़्रेमवर्क +* वाइल्डकार्ड +* वापस करना +* सत्यापित करना + +//// + +//// tab | जानकारी + +यह डॉक्स में दिखने वाले (ज़्यादातर) तकनीकी शब्दों की न तो पूर्ण और न ही मानक सूची है। यह प्रॉम्प्ट डिज़ाइनर को यह समझने में मदद कर सकती है कि किन शब्दों के लिए LLM को सहायक निर्देशों की ज़रूरत है। उदाहरण के लिए जब यह एक अच्छे अनुवाद को कमतर अनुवाद में वापस बदल देता है। या जब इसे आपकी भाषा में किसी शब्द का रूपांतरण/विभक्ति करने में समस्या होती है। + +उदाहरण के लिए `docs/de/llm-prompt.md` में सेक्शन `### List of English terms and their preferred German translations` देखें। + +//// diff --git a/docs/hi/docs/index.md b/docs/hi/docs/index.md new file mode 100644 index 000000000..cbc81dbe5 --- /dev/null +++ b/docs/hi/docs/index.md @@ -0,0 +1,585 @@ +--- +include_yaml: + sponsors: data/sponsors.yml +--- + +# FastAPI { #fastapi } + + + +

+ FastAPI +

+

+ FastAPI फ़्रेमवर्क, उच्च प्रदर्शन, सीखने में आसान, कोड लिखने में तेज़, प्रोडक्शन के लिए तैयार +

+

+ + टेस्ट + + + कवरेज + + + पैकेज संस्करण + + + समर्थित Python संस्करण + +

+ +--- + +**दस्तावेज़**: [https://fastapi.tiangolo.com](https://fastapi.tiangolo.com/hi) + +**स्रोत कोड**: [https://github.com/fastapi/fastapi](https://github.com/fastapi/fastapi) + +--- + +FastAPI एक आधुनिक, तेज़ (उच्च-प्रदर्शन) वेब फ़्रेमवर्क है जो मानक Python type hints के आधार पर Python से APIs बनाने के लिए है। + +मुख्य विशेषताएँ: + +* **तेज़**: बहुत उच्च प्रदर्शन, **NodeJS** और **Go** के समकक्ष (Starlette और Pydantic की बदौलत)। [उपलब्ध सबसे तेज़ Python फ़्रेमवर्क्स में से एक](#performance)। +* **कोड लिखने में तेज़**: फ़ीचर्स विकसित करने की गति लगभग 200% से 300% तक बढ़ाएँ। * +* **कम बग्स**: मानवीय (डेवलपर) त्रुटियों में लगभग 40% की कमी। * +* **सहज**: बेहतरीन एडिटर सपोर्ट। हर जगह ऑटो-कम्प्लीट। डिबगिंग में कम समय। +* **आसान**: इस्तेमाल और सीखने में आसान। दस्तावेज़ पढ़ने में कम समय। +* **संक्षिप्त**: कोड डुप्लीकेशन को न्यूनतम करें। प्रत्येक parameter declaration से कई फ़ीचर्स। कम बग्स। +* **मजबूत**: प्रोडक्शन-रेडी कोड प्राप्त करें। स्वतः इंटरैक्टिव दस्तावेज़ीकरण के साथ। +* **मानकों पर आधारित**: APIs के खुले मानकों पर आधारित (और पूर्णतः अनुकूल): [OpenAPI](https://github.com/OAI/OpenAPI-Specification) (जिसे पहले Swagger कहा जाता था) और [JSON Schema](https://json-schema.org/)। + +* आंतरिक डेवलपमेंट टीम द्वारा प्रोडक्शन ऐप्स बनाते समय किए गए परीक्षणों के आधार पर अनुमान। + +## प्रायोजक { #sponsors } + + + +### कीस्टोन प्रायोजक { #keystone-sponsor } + +
+{% for sponsor in sponsors.keystone -%} +{{ sponsor.title }} +{% endfor -%} +
+ +### गोल्ड प्रायोजक { #gold-sponsors } + +
+{% for sponsor in sponsors.gold -%} +{{ sponsor.title }} +{% endfor -%} +
+ +### सिल्वर प्रायोजक { #silver-sponsors } + +
+{% for sponsor in sponsors.silver -%} +{{ sponsor.title }} +{% endfor %} +
+ + + +[अन्य प्रायोजक](https://fastapi.tiangolo.com/hi/fastapi-people/#sponsors) + +## विचार { #opinions } + + +
+
+ + + + +
+ +
+
"मैं इन दिनों FastAPI का बहुत उपयोग कर रहा/रही हूँ। वास्तव में मैं अपनी टीम की Microsoft में ML सेवाओं के लिए इसे उपयोग करने की योजना बना रहा/रही हूँ। इनमें से कुछ को मुख्य Windows प्रोडक्ट और कुछ Office प्रोडक्ट्स में इंटीग्रेट किया जा रहा है।"
+
— कबीर खान, Microsoft (संदर्भ)
+
+ + + +
+ + +
+ +"_[...] मैं इन दिनों **FastAPI** का बहुत उपयोग कर रहा/रही हूँ। [...] वास्तव में मैं अपनी टीम की **Microsoft में ML सेवाओं** के लिए इसे उपयोग करने की योजना बना रहा/रही हूँ। इनमें से कुछ को मुख्य **Windows** प्रोडक्ट और कुछ **Office** प्रोडक्ट्स में इंटीग्रेट किया जा रहा है._" + +
कबीर खान - Microsoft (संदर्भ)
+ +--- + +"_हमने **FastAPI** लाइब्रेरी अपनाई ताकि एक **REST** सर्वर स्पॉन किया जा सके जिसे **अनुमानों** को प्राप्त करने के लिए क्वेरी किया जा सके। [Ludwig के लिए]_" + +
पिएरो मोलिनो, यारोस्लाव डुडिन, और साई सुमंत मिर्याला - Uber (संदर्भ)
+ +--- + +"_**Netflix** हमारे **संकट प्रबंधन** ऑर्केस्ट्रेशन फ़्रेमवर्क: **Dispatch** के ओपन-सोर्स रिलीज़ की घोषणा करते हुए प्रसन्न है! [**FastAPI** के साथ बनाया गया]_" + +
केविन ग्लिसन, मार्क विलानोवा, फॉरेस्ट मॉन्सेन - Netflix (संदर्भ)
+ +--- + +"_यदि कोई प्रोडक्शन Python API बनाना चाहता है, तो मैं **FastAPI** की अत्यधिक अनुशंसा करूंगा/करूंगी। यह **सुंदरता से डिज़ाइन** किया गया है, **उपयोग में सरल** है और **बेहद स्केलेबल** है, यह हमारी API-फ़र्स्ट डेवलपमेंट रणनीति का **मुख्य घटक** बन गया है और हमारे Virtual TAC Engineer जैसे कई ऑटोमेशन्स और सेवाओं को चला रहा है._" + +
डीयोन पिल्सबरी - Cisco (संदर्भ)
+ +--- + +
+ +## FastAPI कॉन्फ़ { #fastapi-conf } + +[**FastAPI Conf '26**](https://fastapiconf.com) **28 अक्टूबर, 2026** को **एम्स्टर्डम, नीदरलैंड्स** में हो रही है। सब कुछ FastAPI के बारे में, सीधे स्रोत से। 🎤 + +FastAPI Conf '26 - 28 अक्टूबर, 2026 - एम्स्टर्डम, NL + +## FastAPI मिनी डॉक्यूमेंट्री { #fastapi-mini-documentary } + +साल 2025 के अंत में एक [FastAPI मिनी डॉक्यूमेंट्री](https://www.youtube.com/watch?v=mpR8ngthqiE) रिलीज़ हुई, आप इसे ऑनलाइन देख सकते हैं: + +FastAPI मिनी डॉक्यूमेंट्री + +## **Typer**, CLIs का FastAPI { #typer-the-fastapi-of-clis } + + + +यदि आप वेब API के बजाय टर्मिनल में उपयोग होने वाला CLI ऐप बना रहे हैं, तो [**Typer**](https://typer.tiangolo.com/) देखें। + +**Typer**, FastAPI का छोटा भाई/बहन है। और इसका उद्देश्य **CLIs का FastAPI** होना है। ⌨️ 🚀 + +## आवश्यकताएँ { #requirements } + +FastAPI दिग्गजों के कंधों पर खड़ा है: + +* वेब हिस्सों के लिए [Starlette](https://www.starlette.dev/)। +* डेटा हिस्सों के लिए [Pydantic](https://docs.pydantic.dev/)। + +## स्थापना { #installation } + +एक [वर्चुअल एन्वायरनमेंट](https://fastapi.tiangolo.com/hi/virtual-environments/) बनाएँ और सक्रिय करें, और फिर FastAPI स्थापित करें: + +
+ +```console +$ pip install "fastapi[standard]" + +---> 100% +``` + +
+ +**नोट**: सुनिश्चित करें कि आप सभी टर्मिनलों में काम करने के लिए `"fastapi[standard]"` को उद्धरण-चिह्नों में रखें। + +## उदाहरण { #example } + +### इसे बनाएँ { #create-it } + +`main.py` फ़ाइल बनाएँ और इसमें लिखें: + +```Python +from fastapi import FastAPI + +app = FastAPI() + + +@app.get("/") +def read_root(): + return {"Hello": "World"} + + +@app.get("/items/{item_id}") +def read_item(item_id: int, q: str | None = None): + return {"item_id": item_id, "q": q} +``` + +
+या async def का उपयोग करें... + +यदि आपका कोड `async` / `await` का उपयोग करता है, तो `async def` का उपयोग करें: + +```Python hl_lines="7 12" +from fastapi import FastAPI + +app = FastAPI() + + +@app.get("/") +async def read_root(): + return {"Hello": "World"} + + +@app.get("/items/{item_id}") +async def read_item(item_id: int, q: str | None = None): + return {"item_id": item_id, "q": q} +``` + +**नोट**: + +यदि आप नहीं जानते, तो _"जल्दी में?"_ सेक्शन देखें: दस्तावेज़ में [`async` और `await`](https://fastapi.tiangolo.com/hi/async/#in-a-hurry) के बारे में। + +
+ +### इसे चलाएँ { #run-it } + +सर्वर को इस कमांड से चलाएँ: + +
+ +```console +$ fastapi dev + + ╭────────── FastAPI CLI - Development mode ───────────╮ + │ │ + │ Serving at: http://127.0.0.1:8000 │ + │ │ + │ API docs: http://127.0.0.1:8000/docs │ + │ │ + │ Running in development mode, for production use: │ + │ │ + │ fastapi run │ + │ │ + ╰─────────────────────────────────────────────────────╯ + +INFO: Will watch for changes in these directories: ['/home/user/code/awesomeapp'] +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +INFO: Started reloader process [2248755] using WatchFiles +INFO: Started server process [2248757] +INFO: Waiting for application startup. +INFO: Application startup complete. +``` + +
+ +
+fastapi dev कमांड के बारे में... + +`fastapi dev` कमांड आपका `main.py` फ़ाइल स्वतः पढ़ता है, उसमें **FastAPI** ऐप का पता लगाता है, और [Uvicorn](https://www.uvicorn.dev) का उपयोग करके सर्वर शुरू करता है। + +डिफ़ॉल्ट रूप से, `fastapi dev` लोकल डेवलपमेंट के लिए auto-reload सक्षम करके शुरू होगा। + +आप इसके बारे में और पढ़ सकते हैं: [FastAPI CLI दस्तावेज़](https://fastapi.tiangolo.com/hi/fastapi-cli/) में। + +
+ +### इसे जाँचें { #check-it } + +अपने ब्राउज़र में [http://127.0.0.1:8000/items/5?q=somequery](http://127.0.0.1:8000/items/5?q=somequery) खोलें। + +आपको JSON प्रतिक्रिया इस प्रकार दिखेगी: + +```JSON +{"item_id": 5, "q": "somequery"} +``` + +आपने पहले ही एक API बना ली है जो: + +* _paths_ `/` और `/items/{item_id}` पर HTTP अनुरोध स्वीकार करती है। +* दोनों _paths_ `GET` operations लेती हैं (जिन्हें HTTP _methods_ भी कहा जाता है)। +* _path_ `/items/{item_id}` में एक _path parameter_ `item_id` है जो `int` होना चाहिए। +* _path_ `/items/{item_id}` में एक वैकल्पिक `str` _query parameter_ `q` है। + +### इंटरैक्टिव API दस्तावेज़ { #interactive-api-docs } + +अब [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs) पर जाएँ। + +आपको स्वचालित इंटरैक्टिव API दस्तावेज़ीकरण दिखेगा (जो [Swagger UI](https://github.com/swagger-api/swagger-ui) द्वारा प्रदान किया जाता है): + +![Swagger UI](https://fastapi.tiangolo.com/img/index/index-01-swagger-ui-simple.png) + +### वैकल्पिक API दस्तावेज़ { #alternative-api-docs } + +और अब, [http://127.0.0.1:8000/redoc](http://127.0.0.1:8000/redoc) पर जाएँ। + +आपको वैकल्पिक स्वचालित दस्तावेज़ीकरण दिखेगा (जो [ReDoc](https://github.com/Rebilly/ReDoc) द्वारा प्रदान किया जाता है): + +![ReDoc](https://fastapi.tiangolo.com/img/index/index-02-redoc-simple.png) + +## उदाहरण उन्नयन { #example-upgrade } + +अब `PUT` अनुरोध से body प्राप्त करने के लिए `main.py` फ़ाइल संशोधित करें। + +Pydantic की बदौलत, body को मानक Python प्रकारों से घोषित करें। + +```Python hl_lines="2 7-10 23-25" +from fastapi import FastAPI +from pydantic import BaseModel + +app = FastAPI() + + +class Item(BaseModel): + name: str + price: float + is_offer: bool | None = None + + +@app.get("/") +def read_root(): + return {"Hello": "World"} + + +@app.get("/items/{item_id}") +def read_item(item_id: int, q: str | None = None): + return {"item_id": item_id, "q": q} + + +@app.put("/items/{item_id}") +def update_item(item_id: int, item: Item): + return {"item_name": item.name, "item_id": item_id} +``` + +`fastapi dev` सर्वर स्वतः रीलोड होना चाहिए। + +### इंटरैक्टिव API दस्तावेज़ उन्नयन { #interactive-api-docs-upgrade } + +अब [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs) पर जाएँ। + +* इंटरैक्टिव API दस्तावेज़ स्वतः अपडेट हो जाएगा, नए body सहित: + +![Swagger UI](https://fastapi.tiangolo.com/img/index/index-03-swagger-02.png) + +* "Try it out" बटन पर क्लिक करें, यह आपको parameters भरने और सीधे API के साथ इंटरेक्ट करने की अनुमति देता है: + +![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-04-swagger-03.png) + +* फिर "Execute" बटन पर क्लिक करें, यूज़र इंटरफ़ेस आपकी API से संवाद करेगा, parameters भेजेगा, परिणाम प्राप्त करेगा और उन्हें स्क्रीन पर दिखाएगा: + +![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-05-swagger-04.png) + +### वैकल्पिक API दस्तावेज़ उन्नयन { #alternative-api-docs-upgrade } + +और अब, [http://127.0.0.1:8000/redoc](http://127.0.0.1:8000/redoc) पर जाएँ। + +* वैकल्पिक दस्तावेज़ भी नए query parameter और body को दर्शाएगा: + +![ReDoc](https://fastapi.tiangolo.com/img/index/index-06-redoc-02.png) + +### पुनरावलोकन { #recap } + +संक्षेप में, आप parameters, body, आदि के प्रकार फ़ंक्शन parameters के रूप में **एक बार** घोषित करते हैं। + +आप यह मानक आधुनिक Python प्रकारों से करते हैं। + +आपको किसी नई सिंटैक्स, किसी विशेष लाइब्रेरी के methods या classes, आदि सीखने की आवश्यकता नहीं है। + +बस मानक **Python**। + +उदाहरण के लिए, एक `int` के लिए: + +```Python +item_id: int +``` + +या एक अधिक जटिल `Item` मॉडल के लिए: + +```Python +item: Item +``` + +...और केवल उसी एक घोषणा के साथ आपको मिलता है: + +* एडिटर सपोर्ट, जिसमें शामिल है: + * कम्प्लीशन। + * प्रकार जाँच। +* डेटा का वैधीकरण: + * जब डेटा अमान्य हो तो स्वतः और स्पष्ट त्रुटियाँ। + * गहराई से nested JSON objects के लिए भी वैधीकरण। +* इनपुट डेटा का रूपांतरण: नेटवर्क से Python डेटा और प्रकारों में। इनमें से पढ़ना: + * JSON। + * Path parameters। + * Query parameters। + * Cookies। + * Headers। + * Forms। + * Files। +* आउटपुट डेटा का रूपांतरण: Python डेटा और प्रकारों से नेटवर्क डेटा (JSON के रूप में) में: + * Python प्रकारों का रूपांतरण (`str`, `int`, `float`, `bool`, `list`, आदि)। + * `datetime` ऑब्जेक्ट्स। + * `UUID` ऑब्जेक्ट्स। + * डेटाबेस मॉडल्स। + * ...और बहुत कुछ। +* स्वचालित इंटरैक्टिव API दस्तावेज़ीकरण, जिनमें 2 वैकल्पिक यूज़र इंटरफ़ेस शामिल हैं: + * Swagger UI। + * ReDoc। + +--- + +पिछले कोड उदाहरण पर लौटते हुए, **FastAPI** यह करेगा: + +* `GET` और `PUT` अनुरोधों के लिए path में `item_id` है, यह सत्यापित करेगा। +* `GET` और `PUT` अनुरोधों के लिए `item_id` का प्रकार `int` है, यह सत्यापित करेगा। + * यदि नहीं है, तो क्लाइंट को एक उपयोगी, स्पष्ट त्रुटि दिखाई देगी। +* `GET` अनुरोधों के लिए यह जाँच करेगा कि `q` नाम का एक वैकल्पिक query parameter है (जैसे `http://127.0.0.1:8000/items/foo?q=somequery`)। + * क्योंकि `q` parameter `= None` के साथ घोषित है, यह वैकल्पिक है। + * `None` के बिना यह आवश्यक होता (जैसे `PUT` के मामले में body आवश्यक है)। +* `/items/{item_id}` पर `PUT` अनुरोधों के लिए, body को JSON के रूप में पढ़ेगा: + * यह जाँचेगा कि एक आवश्यक attribute `name` है जो `str` होना चाहिए। + * यह जाँचेगा कि एक आवश्यक attribute `price` है जो `float` होना चाहिए। + * यह जाँचेगा कि एक वैकल्पिक attribute `is_offer` है, जो यदि मौजूद है तो `bool` होना चाहिए। + * यह सब गहराई से nested JSON objects के लिए भी काम करेगा। +* JSON से और JSON में स्वतः रूपांतरण। +* हर चीज़ को OpenAPI के साथ दस्तावेज़ित करेगा, जिसे निम्न द्वारा उपयोग किया जा सकता है: + * इंटरैक्टिव दस्तावेज़ीकरण प्रणालियाँ। + * कई भाषाओं के लिए स्वचालित क्लाइंट कोड जनरेशन प्रणालियाँ। +* सीधे 2 इंटरैक्टिव दस्तावेज़ीकरण वेब इंटरफेसेज़ प्रदान करेगा। + +--- + +हमने केवल सतह को छुआ है, लेकिन आपको पहले ही समझ आ गया होगा कि यह सब कैसे काम करता है। + +इस पंक्ति को बदलकर देखें: + +```Python + return {"item_name": item.name, "item_id": item_id} +``` + +...यहाँ से: + +```Python + ... "item_name": item.name ... +``` + +...यहाँ तक: + +```Python + ... "item_price": item.price ... +``` + +...और देखें कि आपका एडिटर attributes को कैसे auto-complete करेगा और उनके प्रकार जानेगा: + +![editor support](https://fastapi.tiangolo.com/img/vscode-completion.png) + +अधिक फ़ीचर्स सहित एक अधिक सम्पूर्ण उदाहरण के लिए, ट्यूटोरियल - यूज़र गाइड देखें। + +**स्पॉइलर अलर्ट**: ट्यूटोरियल - यूज़र गाइड में शामिल है: + +* विभिन्न स्थानों से **parameters** की घोषणा: **headers**, **cookies**, **form fields** और **files**। +* `maximum_length` या `regex` जैसी **validation constraints** कैसे सेट करें। +* एक बहुत शक्तिशाली और उपयोग में आसान **डिपेंडेंसी इंजेक्शन** सिस्टम। +* सुरक्षा और प्रमाणीकरण, जिसमें **OAuth2** के साथ **JWT tokens** और **HTTP Basic** auth का समर्थन शामिल है। +* **गहराई से nested JSON मॉडल्स** घोषित करने की अधिक उन्नत (पर समान रूप से आसान) तकनीकें (Pydantic की बदौलत)। +* [Strawberry](https://strawberry.rocks) और अन्य लाइब्रेरीज़ के साथ **GraphQL** एकीकरण। +* कई अतिरिक्त फ़ीचर्स (Starlette की बदौलत) जैसे: + * **WebSockets** + * HTTPX और `pytest` पर आधारित अत्यंत आसान टेस्ट्स + * **CORS** + * **Cookie Sessions** + * ...आदि। + +### अपनी ऐप परिनियोजित करें (वैकल्पिक) { #deploy-your-app-optional } + +आप वैकल्पिक रूप से अपनी FastAPI ऐप को [FastAPI Cloud](https://fastapicloud.com) पर एक ही कमांड से डिप्लॉय कर सकते हैं। 🚀 + +
+ +```console +$ fastapi deploy + +Deploying to FastAPI Cloud... + +✅ Deployment successful! + +🐔 Ready the chicken! Your app is ready at https://myapp.fastapicloud.dev +``` + +
+ +CLI आपकी FastAPI एप्लिकेशन को स्वतः पहचान लेगा और उसे क्लाउड पर डिप्लॉय करेगा। यदि आप logged in नहीं हैं, तो प्रमाणीकरण प्रक्रिया पूरी करने के लिए आपका ब्राउज़र खुलेगा। + +बस इतना ही! अब आप उस URL पर अपनी ऐप एक्सेस कर सकते हैं। ✨ + +#### FastAPI Cloud के बारे में { #about-fastapi-cloud } + +**[FastAPI Cloud](https://fastapicloud.com)** को **FastAPI** के ही लेखक और टीम ने बनाया है। + +यह न्यूनतम प्रयास में किसी API को **बनाने**, **डिप्लॉय** करने और **एक्सेस** करने की प्रक्रिया को सरल बनाता है। + +यह FastAPI के साथ ऐप्स बनाने के उसी **डेवलपर अनुभव** को उन्हें क्लाउड में **डिप्लॉय** करने तक लाता है। 🎉 + +FastAPI Cloud, *FastAPI and friends* ओपन सोर्स प्रोजेक्ट्स के लिए मुख्य प्रायोजक और फंडिंग प्रदाता है। ✨ + +#### अन्य क्लाउड प्रदाताओं पर डिप्लॉय करें { #deploy-to-other-cloud-providers } + +FastAPI ओपन सोर्स है और मानकों पर आधारित है। आप FastAPI ऐप्स को किसी भी क्लाउड प्रदाता पर डिप्लॉय कर सकते हैं। + +अपने क्लाउड प्रदाता के गाइड्स का पालन करें और उनके साथ FastAPI ऐप्स डिप्लॉय करें। 🤓 + +## प्रदर्शन { #performance } + +स्वतंत्र TechEmpower बेंचमार्क दिखाते हैं कि Uvicorn के तहत चलने वाले **FastAPI** एप्लीकेशन्स [उपलब्ध सबसे तेज़ Python फ़्रेमवर्क्स में से एक](https://www.techempower.com/benchmarks/#section=test&runid=7464e520-0dc2-473d-bd34-dbdfd7e85911&hw=ph&test=query&l=zijzen-7) हैं, केवल Starlette और Uvicorn (जो FastAPI द्वारा आंतरिक रूप से उपयोग किए जाते हैं) से नीचे। (*) + +इसके बारे में अधिक समझने के लिए, [बेंचमार्क्स](https://fastapi.tiangolo.com/hi/benchmarks/) सेक्शन देखें। + +## निर्भरताएँ { #dependencies } + +FastAPI, Pydantic और Starlette पर निर्भर करता है। + +### `standard` निर्भरताएँ { #standard-dependencies } + +जब आप `pip install "fastapi[standard]"` के साथ FastAPI स्थापित करते हैं, तो यह `standard` समूह की वैकल्पिक निर्भरताओं के साथ आता है: + +Pydantic द्वारा उपयोग किया गया: + +* [`email-validator`](https://github.com/JoshData/python-email-validator) - ईमेल वैधीकरण के लिए। + +Starlette द्वारा उपयोग किया गया: + +* [`httpx`](https://www.python-httpx.org) - यदि आप `TestClient` का उपयोग करना चाहते हैं तो आवश्यक। +* [`jinja2`](https://jinja.palletsprojects.com) - यदि आप डिफ़ॉल्ट टेम्पलेट कॉन्फ़िगरेशन का उपयोग करना चाहते हैं तो आवश्यक। +* [`python-multipart`](https://github.com/Kludex/python-multipart) - यदि आप फॉर्म "पार्सिंग" का समर्थन करना चाहते हैं, `request.form()` के साथ, तो आवश्यक। + +FastAPI द्वारा उपयोग किया गया: + +* [`uvicorn`](https://www.uvicorn.dev) - वह सर्वर जो आपकी एप्लिकेशन को लोड और सर्व करता है। इसमें `uvicorn[standard]` शामिल है, जिसमें उच्च-प्रदर्शन सर्विंग के लिए कुछ निर्भरताएँ (जैसे `uvloop`) शामिल हैं। +* `fastapi-cli[standard]` - `fastapi` कमांड प्रदान करने के लिए। + * इसमें `fastapi-cloud-cli` शामिल है, जो आपको अपनी FastAPI एप्लिकेशन को [FastAPI Cloud](https://fastapicloud.com) पर डिप्लॉय करने की अनुमति देता है। + +### `standard` निर्भरताओं के बिना { #without-standard-dependencies } + +यदि आप `standard` वैकल्पिक निर्भरताओं को शामिल नहीं करना चाहते, तो आप `pip install fastapi` के साथ स्थापित कर सकते हैं, `pip install "fastapi[standard]"` के बजाय। + +### `fastapi-cloud-cli` के बिना { #without-fastapi-cloud-cli } + +यदि आप standard निर्भरताओं के साथ लेकिन `fastapi-cloud-cli` के बिना FastAPI स्थापित करना चाहते हैं, तो `pip install "fastapi[standard-no-fastapi-cloud-cli]"` के साथ स्थापित कर सकते हैं। + +### अतिरिक्त वैकल्पिक निर्भरताएँ { #additional-optional-dependencies } + +कुछ अतिरिक्त निर्भरताएँ हैं जिन्हें आप स्थापित करना चाहेंगे। + +अतिरिक्त वैकल्पिक Pydantic निर्भरताएँ: + +* [`pydantic-settings`](https://docs.pydantic.dev/latest/usage/pydantic_settings/) - सेटिंग्स प्रबंधन के लिए। +* [`pydantic-extra-types`](https://docs.pydantic.dev/latest/usage/types/extra_types/extra_types/) - Pydantic के साथ उपयोग करने के लिए अतिरिक्त प्रकारों हेतु। + +अतिरिक्त वैकल्पिक FastAPI निर्भरताएँ: + +* [`orjson`](https://github.com/ijl/orjson) - यदि आप `ORJSONResponse` उपयोग करना चाहते हैं तो आवश्यक। +* [`ujson`](https://github.com/esnme/ultrajson) - यदि आप `UJSONResponse` उपयोग करना चाहते हैं तो आवश्यक। + +## लाइसेंस { #license } + +यह प्रोजेक्ट MIT लाइसेंस की शर्तों के अंतर्गत लाइसेंस प्राप्त है। diff --git a/docs/hi/docs/translation-banner.md b/docs/hi/docs/translation-banner.md new file mode 100644 index 000000000..af9fedda8 --- /dev/null +++ b/docs/hi/docs/translation-banner.md @@ -0,0 +1,11 @@ +/// details | 🌐 एआई और मनुष्यों द्वारा किया गया अनुवाद + +यह अनुवाद मनुष्यों के मार्गदर्शन में एआई द्वारा किया गया है। 🤝 + +इसमें मूल अर्थ को गलत समझने या अप्राकृतिक लगने आदि जैसी गलतियाँ हो सकती हैं। 🤖 + +आप [हमें एआई LLM को बेहतर मार्गदर्शन करने में मदद करके](https://fastapi.tiangolo.com/hi/contributing/#translations) इस अनुवाद को बेहतर बना सकते हैं। + +[अंग्रेज़ी संस्करण](ENGLISH_VERSION_URL) + +/// diff --git a/docs/hi/llm-prompt.md b/docs/hi/llm-prompt.md new file mode 100644 index 000000000..337ea3823 --- /dev/null +++ b/docs/hi/llm-prompt.md @@ -0,0 +1,5 @@ +### Target language + +Translate to Hindi (हिन्दी). + +Language code: hi. diff --git a/docs/hi/mkdocs.yml b/docs/hi/mkdocs.yml new file mode 100644 index 000000000..de18856f4 --- /dev/null +++ b/docs/hi/mkdocs.yml @@ -0,0 +1 @@ +INHERIT: ../en/mkdocs.yml diff --git a/docs/ja/docs/_llm-test.md b/docs/ja/docs/_llm-test.md index 4edaa93bf..91eeffd0c 100644 --- a/docs/ja/docs/_llm-test.md +++ b/docs/ja/docs/_llm-test.md @@ -1,5 +1,6 @@ # LLM テストファイル { #llm-test-file } + このドキュメントは、ドキュメントを翻訳する LLM が、`scripts/translate.py` の `general_prompt` と、`docs/{language code}/llm-prompt.md` の言語固有プロンプトを理解しているかをテストします。言語固有プロンプトは `general_prompt` の末尾に追加されます。 ここに追加したテストは、すべての言語固有プロンプトの設計者が参照します。 diff --git a/docs/ja/docs/advanced/additional-responses.md b/docs/ja/docs/advanced/additional-responses.md index 1d7c2f80e..ad0b1d4c9 100644 --- a/docs/ja/docs/advanced/additional-responses.md +++ b/docs/ja/docs/advanced/additional-responses.md @@ -34,7 +34,7 @@ FastAPI はそのモデルから JSON Schema を生成し、OpenAPI の適切な /// -/// info | 情報 +/// note | 備考 `model` キーは OpenAPI の一部ではありません。 @@ -183,7 +183,7 @@ FastAPI はそこから Pydantic モデルを取得して JSON Schema を生成 /// -/// info | 情報 +/// note | 備考 `responses` パラメータで明示的に別のメディアタイプを指定しない限り、FastAPI はレスポンスがメインのレスポンスクラスと同じメディアタイプ(デフォルトは `application/json`)であるとみなします。 diff --git a/docs/ja/docs/advanced/additional-status-codes.md b/docs/ja/docs/advanced/additional-status-codes.md index ad9bd57dc..0c19abd49 100644 --- a/docs/ja/docs/advanced/additional-status-codes.md +++ b/docs/ja/docs/advanced/additional-status-codes.md @@ -16,7 +16,7 @@ {* ../../docs_src/additional_status_codes/tutorial001_an_py310.py hl[4,25] *} -/// warning +/// warning | 注意 上の例のように `Response` を直接返すと、それはそのまま返されます。 diff --git a/docs/ja/docs/advanced/advanced-dependencies.md b/docs/ja/docs/advanced/advanced-dependencies.md index 5181e39d8..e06ca4721 100644 --- a/docs/ja/docs/advanced/advanced-dependencies.md +++ b/docs/ja/docs/advanced/advanced-dependencies.md @@ -10,9 +10,9 @@ ただし、その固定の内容はパラメータ化できるようにしたいです。 -## "callable" なインスタンス { #a-callable-instance } +## 「callable」なインスタンス { #a-callable-instance } -Python には、クラスのインスタンスを "callable" にする方法があります。 +Python には、クラスのインスタンスを「callable」にする方法があります。 クラス自体(これはすでに callable です)ではなく、そのクラスのインスタンスです。 @@ -98,7 +98,7 @@ FastAPI 0.118.0 より前では、`yield` を使う依存関係を使用する この挙動は 0.118.0 で元に戻され、`yield` の後の終了コードはレスポンス送信後に実行されるようになりました。 -/// info | 情報 +/// note | 備考 以下で見るように、これはバージョン 0.106.0 より前の挙動ととても似ていますが、いくつかのコーナーケースに対する改良とバグ修正が含まれています。 @@ -146,7 +146,7 @@ FastAPI 0.110.0 より前では、`yield` を持つ依存関係を使い、そ FastAPI 0.106.0 より前では、`yield` の後で例外を送出することはできませんでした。`yield` を持つ依存関係の終了コードはレスポンス送信「後」に実行されるため、[例外ハンドラ](../tutorial/handling-errors.md#install-custom-exception-handlers)はすでに実行済みでした。 -これは主に、依存関係が "yield" した同じオブジェクトをバックグラウンドタスク内で利用できるようにするための設計でした。終了コードはバックグラウンドタスク完了後に実行されるからです。 +これは主に、依存関係が「yield」した同じオブジェクトをバックグラウンドタスク内で利用できるようにするための設計でした。終了コードはバックグラウンドタスク完了後に実行されるからです。 これは、レスポンスがネットワーク上を移動するのを待っている間にリソースを保持しないようにする意図で、FastAPI 0.106.0 で変更されました。 diff --git a/docs/ja/docs/advanced/custom-response.md b/docs/ja/docs/advanced/custom-response.md index e66b1f494..34178a50e 100644 --- a/docs/ja/docs/advanced/custom-response.md +++ b/docs/ja/docs/advanced/custom-response.md @@ -41,7 +41,7 @@ FastAPI はデフォルトでJSONレスポンスを返します。 {* ../../docs_src/custom_response/tutorial002_py310.py hl[2,7] *} -/// info | 情報 +/// note | 備考 パラメータ `response_class` は、レスポンスの「メディアタイプ」を定義するためにも使用されます。 @@ -65,7 +65,7 @@ FastAPI はデフォルトでJSONレスポンスを返します。 /// -/// info | 情報 +/// note | 備考 もちろん、実際の `Content-Type` ヘッダーやステータスコードなどは、返した `Response` オブジェクトに由来します。 diff --git a/docs/ja/docs/advanced/dataclasses.md b/docs/ja/docs/advanced/dataclasses.md index e3ad7afb6..2cfe8e905 100644 --- a/docs/ja/docs/advanced/dataclasses.md +++ b/docs/ja/docs/advanced/dataclasses.md @@ -18,7 +18,7 @@ FastAPI は **Pydantic** の上に構築されており、これまでにリク これは Pydantic モデルの場合と同じように動作します。内部的にも同様に Pydantic を使って実現されています。 -/// info | 情報 +/// note | 備考 dataclasses は、Pydantic モデルができることをすべては行えない点に留意してください。 @@ -74,7 +74,7 @@ dataclass は自動的に Pydantic の dataclass に変換されます。 いつもどおり、FastAPI では必要に応じて `def` と `async def` を組み合わせられます。 - どちらをいつ使うかの復習が必要な場合は、[`async` と `await`](../async.md#in-a-hurry) に関するドキュメントの _"In a hurry?"_ セクションを参照してください。 + どちらをいつ使うかの復習が必要な場合は、[`async` と `await`](../async.md#in-a-hurry) に関するドキュメントの _「急いでいますか?」_ セクションを参照してください。 9. この *path operation 関数* は(可能ではありますが)dataclass 自体は返さず、内部データを持つ辞書のリストを返しています。 @@ -82,7 +82,7 @@ dataclass は自動的に Pydantic の dataclass に変換されます。 `dataclasses` は他の型注釈と多様な組み合わせが可能で、複雑なデータ構造を構成できます。 -上記のコード内コメントのヒントを参照して、より具体的な詳細を確認してください。 +上記のコード内の注釈のヒントを参照して、より具体的な詳細を確認してください。 ## さらに学ぶ { #learn-more } diff --git a/docs/ja/docs/advanced/events.md b/docs/ja/docs/advanced/events.md index e2cbe2eb0..12064f948 100644 --- a/docs/ja/docs/advanced/events.md +++ b/docs/ja/docs/advanced/events.md @@ -120,7 +120,7 @@ async with lifespan(app): ここでは、`shutdown` のイベントハンドラ関数が、テキスト行 `"Application shutdown"` をファイル `log.txt` に書き込みます。 -/// info | 情報 +/// note | 備考 `open()` 関数の `mode="a"` は「追加」(append)を意味します。つまり、そのファイルに既にある内容を上書きせず、行が後ろに追記されます。 @@ -140,7 +140,7 @@ async with lifespan(app): ### `startup` と `shutdown` をまとめて { #startup-and-shutdown-together } -起動時とシャットダウン時のロジックは関連していることが多いです。何かを開始してから終了したい、リソースを獲得してから解放したい、などです. +起動時とシャットダウン時のロジックは関連していることが多いです。何かを開始してから終了したい、リソースを獲得してから解放したい、などです。 共有するロジックや変数のない別々の関数でそれを行うのは難しく、グローバル変数などに値を保存する必要が出てきます。 @@ -152,7 +152,7 @@ async with lifespan(app): 内部的には、ASGI の技術仕様において、これは [Lifespan プロトコル](https://asgi.readthedocs.io/en/latest/specs/lifespan.html) の一部であり、`startup` と `shutdown` というイベントが定義されています。 -/// info | 情報 +/// note | 備考 Starlette の `lifespan` ハンドラについては、[Starlette の Lifespan ドキュメント](https://www.starlette.dev/lifespan/)で詳しく読むことができます。 diff --git a/docs/ja/docs/advanced/generate-clients.md b/docs/ja/docs/advanced/generate-clients.md index eee8575f6..196ec5280 100644 --- a/docs/ja/docs/advanced/generate-clients.md +++ b/docs/ja/docs/advanced/generate-clients.md @@ -20,21 +20,6 @@ FastAPI は自動的に **OpenAPI 3.1** の仕様を生成します。したが /// -## FastAPI スポンサーによる SDK ジェネレータ { #sdk-generators-from-fastapi-sponsors } - -このセクションでは、FastAPI をスポンサーしている企業による、**ベンチャー支援**および**企業支援**のソリューションを紹介します。これらの製品は、高品質な生成 SDK に加えて、**追加機能**や**統合**を提供します。 - -✨ [**FastAPI をスポンサーする**](../help-fastapi.md#sponsor-the-author) ✨ ことで、これらの企業はフレームワークとその**エコシステム**の健全性と**持続可能性**を支援しています。 - -この支援は、FastAPI の**コミュニティ**(皆さん)への強いコミットメントの表明でもあり、**優れたサービス**の提供だけでなく、堅牢で発展するフレームワーク FastAPI を支える姿勢を示しています。🙇 - -例えば、次のようなものがあります: - -* [Stainless](https://www.stainless.com/?utm_source=fastapi&utm_medium=referral) -* [liblab](https://developers.liblab.com/tutorials/sdk-for-fastapi?utm_source=fastapi) - -これらのソリューションの中にはオープンソースや無料枠を提供するものもあり、金銭的コミットメントなしで試すことができます。他の商用 SDK ジェネレータも存在し、オンラインで見つけられます。🤓 - ## TypeScript SDK を作成する { #create-a-typescript-sdk } まずは簡単な FastAPI アプリから始めます: diff --git a/docs/ja/docs/advanced/json-base64-bytes.md b/docs/ja/docs/advanced/json-base64-bytes.md index c3c361a96..214ce14c6 100644 --- a/docs/ja/docs/advanced/json-base64-bytes.md +++ b/docs/ja/docs/advanced/json-base64-bytes.md @@ -4,7 +4,7 @@ ## Base64 とファイル { #base64-vs-files } -バイナリデータのアップロードにはまず、JSON にエンコードする代わりに [Request Files](../tutorial/request-files.md) を、バイナリデータの送信には [カスタムレスポンス - FileResponse](./custom-response.md#fileresponse--fileresponse-) を使えるか検討してください。 +バイナリデータのアップロードにはまず、JSON にエンコードする代わりに [リクエストファイル](../tutorial/request-files.md) を、バイナリデータの送信には [カスタムレスポンス - FileResponse](./custom-response.md#fileresponse) を使えるか検討してください。 JSON は UTF-8 でエンコードされた文字列のみを含められるため、生のバイト列は含められません。 diff --git a/docs/ja/docs/advanced/openapi-callbacks.md b/docs/ja/docs/advanced/openapi-callbacks.md index 31d17e270..e3ddeab98 100644 --- a/docs/ja/docs/advanced/openapi-callbacks.md +++ b/docs/ja/docs/advanced/openapi-callbacks.md @@ -23,7 +23,7 @@ * API 利用者(外部開発者)に通知を送り返します。 * これは(あなたの API から)外部開発者が提供する *外部 API* に POST リクエストを送ることで行われます(これが「コールバック」です)。 -## 通常の FastAPI アプリ { #the-normal-fastapi-app } +## 通常の **FastAPI** アプリ { #the-normal-fastapi-app } まず、コールバックを追加する前の通常の API アプリがどうなるか見てみましょう。 @@ -76,7 +76,7 @@ httpx.post(callback_url, json={"description": "Invoice paid", "paid": True}) しかし、あなたはすでに **FastAPI** で API の自動ドキュメントを簡単に作る方法を知っています。 -その知識を使って、*外部 API* がどうあるべきかをドキュメント化します……つまり、外部 API が実装すべき *path operation(s)*(あなたの API が呼び出すもの)を作成します。 +その知識を使って、*外部 API* がどうあるべきかをドキュメント化します... つまり、外部 API が実装すべき *path operation(s)*(あなたの API が呼び出すもの)を作成します。 /// tip | 豆知識 @@ -86,13 +86,13 @@ httpx.post(callback_url, json={"description": "Invoice paid", "paid": True}) /// -### コールバック用 APIRouter を作成 { #create-a-callback-apirouter } +### コールバック用 `APIRouter` を作成 { #create-a-callback-apirouter } まず、1 つ以上のコールバックを含む新しい `APIRouter` を作成します。 {* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[1,23] *} -### コールバックの path operation を作成 { #create-the-callback-path-operation } +### コールバックの *path operation* を作成 { #create-the-callback-path-operation } 上で作成したのと同じ `APIRouter` を使って、コールバックの *path operation* を作成します。 @@ -167,13 +167,13 @@ JSON ボディは次のような内容です: これで、上で作成したコールバック用ルーター内に、必要なコールバックの *path operation(s)*(*外部開発者* が *外部 API* に実装すべきもの)が用意できました。 -次に、*あなたの API の path operation デコレータ*の `callbacks` パラメータに、そのコールバック用ルーターの属性 `.routes`(実体はルート/*path operations* の `list`)を渡します: +次に、*あなたの API の path operation デコレータ*の `callbacks` パラメータに、そのコールバック用ルーターの属性 `.routes` を渡します: {* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[33] *} /// tip | 豆知識 -`callback=` に渡すのはルーター本体(`invoices_callback_router`)ではなく、属性 `.routes`(`invoices_callback_router.routes`)である点に注意してください。 +`callbacks=` に渡すのはルーター本体(`invoices_callback_router`)ではなく、属性 `.routes`(`invoices_callback_router.routes`)である点に注意してください。FastAPI はそれらのルートを使ってコールバックの OpenAPI ドキュメントを生成します。 /// diff --git a/docs/ja/docs/advanced/openapi-webhooks.md b/docs/ja/docs/advanced/openapi-webhooks.md index 7f7a72680..f559de13b 100644 --- a/docs/ja/docs/advanced/openapi-webhooks.md +++ b/docs/ja/docs/advanced/openapi-webhooks.md @@ -22,7 +22,7 @@ Webhook の URL を登録する方法や実際にリクエストを送るコー これにより、ユーザーがあなたの **Webhook** リクエストを受け取るための**API を実装**するのが大幅に簡単になります。場合によっては、ユーザーが自分たちの API コードを自動生成できるかもしれません。 -/// info | 情報 +/// note | 備考 Webhook は OpenAPI 3.1.0 以上で利用可能で、FastAPI `0.99.0` 以上が対応しています。 @@ -36,7 +36,7 @@ Webhook は OpenAPI 3.1.0 以上で利用可能で、FastAPI `0.99.0` 以上が 定義した webhook は **OpenAPI** スキーマおよび自動生成される **ドキュメント UI** に反映されます。 -/// info | 情報 +/// note | 備考 `app.webhooks` オブジェクトは実際には単なる `APIRouter` で、複数ファイルでアプリを構成する際に使うものと同じ型です。 diff --git a/docs/ja/docs/advanced/path-operation-advanced-configuration.md b/docs/ja/docs/advanced/path-operation-advanced-configuration.md index 65b56dba4..bc08092f8 100644 --- a/docs/ja/docs/advanced/path-operation-advanced-configuration.md +++ b/docs/ja/docs/advanced/path-operation-advanced-configuration.md @@ -16,17 +16,11 @@ OpenAPIの「エキスパート」でなければ、これはおそらく必要 ### *path operation関数* の名前をoperationIdとして使用する { #using-the-path-operation-function-name-as-the-operationid } -APIの関数名を `operationId` として利用したい場合、すべてのAPI関数をイテレーションし、各 *path operation* の `operation_id` を `APIRoute.name` で上書きすれば可能です。 +API の関数名を `operationId` として使いたい場合は、`FastAPI` にカスタムの `generate_unique_id_function` を渡せます。 -すべての *path operation* を追加した後に行うべきです。 +この関数は各 `APIRoute` を受け取り、その *path operation* で使う `operationId` を返します。 -{* ../../docs_src/path_operation_advanced_configuration/tutorial002_py310.py hl[2, 12:21, 24] *} - -/// tip | 豆知識 - -`app.openapi()` を手動で呼び出す場合、その前に `operationId` を更新するべきです。 - -/// +{* ../../docs_src/path_operation_advanced_configuration/tutorial002_py310.py hl[2,5:6,9] *} /// warning | 注意 diff --git a/docs/ja/docs/advanced/response-change-status-code.md b/docs/ja/docs/advanced/response-change-status-code.md index 22f5f3701..35fcc5bbd 100644 --- a/docs/ja/docs/advanced/response-change-status-code.md +++ b/docs/ja/docs/advanced/response-change-status-code.md @@ -1,5 +1,6 @@ # レスポンス - ステータスコードの変更 { #response-change-status-code } + すでに、デフォルトの[レスポンスのステータスコード](../tutorial/response-status-code.md)を設定できることをご存知かもしれません。 しかし場合によっては、デフォルトとは異なるステータスコードを返す必要があります。 diff --git a/docs/ja/docs/advanced/response-cookies.md b/docs/ja/docs/advanced/response-cookies.md index c395b09c6..912181554 100644 --- a/docs/ja/docs/advanced/response-cookies.md +++ b/docs/ja/docs/advanced/response-cookies.md @@ -1,5 +1,6 @@ # レスポンスの Cookie { #response-cookies } + ## `Response` パラメータを使う { #use-a-response-parameter } *path operation 関数*で `Response` 型のパラメータを宣言できます。 diff --git a/docs/ja/docs/advanced/response-directly.md b/docs/ja/docs/advanced/response-directly.md index b5c9fc5cb..366eed2b9 100644 --- a/docs/ja/docs/advanced/response-directly.md +++ b/docs/ja/docs/advanced/response-directly.md @@ -18,7 +18,7 @@ 実際は、`Response` やそのサブクラスを返すことができます。 -/// info +/// note `JSONResponse` それ自体は、`Response` のサブクラスです。 diff --git a/docs/ja/docs/advanced/response-headers.md b/docs/ja/docs/advanced/response-headers.md index 3a61f5742..d5f6f31a3 100644 --- a/docs/ja/docs/advanced/response-headers.md +++ b/docs/ja/docs/advanced/response-headers.md @@ -1,5 +1,6 @@ # レスポンスヘッダー { #response-headers } + ## `Response` パラメータを使う { #use-a-response-parameter } (Cookie と同様に)*path operation 関数*で `Response` 型のパラメータを宣言できます。 diff --git a/docs/ja/docs/advanced/security/oauth2-scopes.md b/docs/ja/docs/advanced/security/oauth2-scopes.md index 3afc26e3a..b01bd01ca 100644 --- a/docs/ja/docs/advanced/security/oauth2-scopes.md +++ b/docs/ja/docs/advanced/security/oauth2-scopes.md @@ -1,5 +1,6 @@ # OAuth2 のスコープ { #oauth2-scopes } + OAuth2 のスコープは **FastAPI** で直接利用でき、シームレスに統合されています。 これにより、OAuth2 標準に従った、よりきめ細かな権限システムを、OpenAPI 対応アプリケーション(および API ドキュメント)に統合できます。 @@ -46,7 +47,7 @@ OpenAPI(例: API ドキュメント)では、「セキュリティスキー - `instagram_basic` は Facebook / Instagram で使われています。 - `https://www.googleapis.com/auth/drive` は Google で使われています。 -/// info | 情報 +/// note | 備考 OAuth2 において「スコープ」は、必要な特定の権限を宣言する単なる文字列です。 @@ -126,7 +127,7 @@ OAuth2 にとっては、単に文字列に過ぎません。 {* ../../docs_src/security/tutorial005_an_py310.py hl[5,141,172] *} -/// info | 技術詳細 +/// note | 技術詳細 `Security` は実際には `Depends` のサブクラスで、後述する追加パラメータが 1 つあるだけです。 diff --git a/docs/ja/docs/advanced/settings.md b/docs/ja/docs/advanced/settings.md index e42ec845c..b3fd89a46 100644 --- a/docs/ja/docs/advanced/settings.md +++ b/docs/ja/docs/advanced/settings.md @@ -52,7 +52,7 @@ Pydantic から `BaseSettings` をインポートして、そのサブクラス Pydantic モデルと同様に、型アノテーションと(必要なら)デフォルト値を持つクラス属性を宣言します。 -`Field()` による追加バリデーションなど、Pydantic モデルで使えるのと同じバリデーション機能をすべて利用できます。 +異なるデータ型や `Field()` による追加バリデーションなど、Pydantic モデルで使えるのと同じバリデーション機能とツールをすべて利用できます。 {* ../../docs_src/settings/tutorial001_py310.py hl[2,5:8,11] *} diff --git a/docs/ja/docs/advanced/stream-data.md b/docs/ja/docs/advanced/stream-data.md index 52bbfd3fd..6360cdab5 100644 --- a/docs/ja/docs/advanced/stream-data.md +++ b/docs/ja/docs/advanced/stream-data.md @@ -2,9 +2,9 @@ JSON として構造化できるデータをストリームしたい場合は、[JSON Lines をストリームする](../tutorial/stream-json-lines.md) を参照してください。 -しかし、純粋なバイナリデータや文字列をストリームしたい場合は、次のようにできます。 +しかし、**純粋なバイナリデータ**や文字列をストリームしたい場合は、次のようにできます。 -/// info | 情報 +/// note | 備考 FastAPI 0.134.0 で追加されました。 @@ -12,21 +12,21 @@ FastAPI 0.134.0 で追加されました。 ## ユースケース { #use-cases } -例えば、AI LLM サービスの出力をそのまま、純粋な文字列としてストリームしたい場合に使えます。 +例えば、**AI LLM** サービスの出力をそのまま、純粋な文字列としてストリームしたい場合に使えます。 -メモリに一度に全て読み込むことなく、読み込みながらチャンクごとに送ることで、巨大なバイナリファイルをストリームすることにも使えます。 +メモリに一度に全て読み込むことなく、読み込みながらチャンクごとに送ることで、**巨大なバイナリファイル**をストリームすることにも使えます。 -同様に、動画や音声をストリームすることもできます。処理しながら生成し、そのまま送信することも可能です。 +同様に、**動画**や**音声**をストリームすることもできます。処理しながら生成し、そのまま送信することも可能です。 ## `yield` を使った `StreamingResponse` { #a-streamingresponse-with-yield } -path operation 関数で `response_class=StreamingResponse` を宣言すると、`yield` を使ってデータをチャンクごとに順次送信できます。 +*path operation 関数*で `response_class=StreamingResponse` を宣言すると、`yield` を使ってデータをチャンクごとに順次送信できます。 {* ../../docs_src/stream_data/tutorial001_py310.py ln[1:23] hl[20,23] *} FastAPI は各データチャンクをそのまま `StreamingResponse` に渡し、JSON などに変換しようとはしません。 -### 非 async な path operation 関数 { #non-async-path-operation-functions } +### 非 async な *path operation 関数* { #non-async-path-operation-functions } `async` なしの通常の `def` 関数でも同様に `yield` を使えます。 @@ -40,7 +40,7 @@ FastAPI は各データチャンクをそのまま `StreamingResponse` に渡し {* ../../docs_src/stream_data/tutorial001_py310.py ln[32:35] hl[33] *} -つまり、`StreamingResponse` では型アノテーションに依存せず、送信したい形式に合わせてバイト列を生成・エンコードする「自由」と「責任」があなたにあります。 🤓 +つまり、`StreamingResponse` では型アノテーションに依存せず、送信したい形式に合わせてバイト列を生成・エンコードする**自由**と**責任**があなたにあります。 🤓 ### バイト列をストリームする { #stream-bytes } @@ -58,7 +58,7 @@ FastAPI は各データチャンクをそのまま `StreamingResponse` に渡し {* ../../docs_src/stream_data/tutorial002_py310.py ln[6,19:20] hl[20] *} -その後、path operation 関数で `response_class=PNGStreamingResponse` としてこの新しいクラスを使用できます: +その後、*path operation 関数*で `response_class=PNGStreamingResponse` としてこの新しいクラスを使用できます: {* ../../docs_src/stream_data/tutorial002_py310.py ln[23:27] hl[23] *} @@ -90,7 +90,7 @@ FastAPI は各データチャンクをそのまま `StreamingResponse` に渡し また、多くの場合、ディスクやネットワークから読み出すため、読み取りはブロッキング(イベントループをブロックし得る)処理になります。 -/// info | 情報 +/// note | 備考 上記の例は例外で、`io.BytesIO` は既にメモリ上にあるため、読み取りが何かをブロックすることはありません。 @@ -98,7 +98,7 @@ FastAPI は各データチャンクをそのまま `StreamingResponse` に渡し /// -イベントループのブロッキングを避けるには、path operation 関数を `async def` ではなく通常の `def` で宣言してください。そうすると FastAPI はその関数をスレッドプールワーカー上で実行し、メインループのブロッキングを避けます。 +イベントループのブロッキングを避けるには、*path operation 関数*を `async def` ではなく通常の `def` で宣言してください。そうすると FastAPI はその関数をスレッドプールワーカー上で実行し、メインループのブロッキングを避けます。 {* ../../docs_src/stream_data/tutorial002_py310.py ln[30:34] hl[31] *} diff --git a/docs/ja/docs/advanced/strict-content-type.md b/docs/ja/docs/advanced/strict-content-type.md index 994cb8672..a21832fec 100644 --- a/docs/ja/docs/advanced/strict-content-type.md +++ b/docs/ja/docs/advanced/strict-content-type.md @@ -81,7 +81,7 @@ http://localhost:8000/v1/agents/multivac この設定では、`Content-Type` ヘッダーがないリクエストでもボディが JSON として解析されます。これは古いバージョンの FastAPI と同じ挙動です。 -/// info | 情報 +/// note | 備考 この挙動と設定は FastAPI 0.132.0 で追加されました。 diff --git a/docs/ja/docs/advanced/websockets.md b/docs/ja/docs/advanced/websockets.md index 802110b58..b310adfe9 100644 --- a/docs/ja/docs/advanced/websockets.md +++ b/docs/ja/docs/advanced/websockets.md @@ -111,7 +111,7 @@ WebSocketエンドポイントでは、`fastapi` から以下をインポート {* ../../docs_src/websockets_/tutorial002_an_py310.py hl[68:69,82] *} -/// info | 情報 +/// note | 備考 これはWebSocketであるため、`HTTPException` を発生させることはあまり意味がありません。代わりに `WebSocketException` を発生させます。 diff --git a/docs/ja/docs/advanced/wsgi.md b/docs/ja/docs/advanced/wsgi.md index 6895eb658..40511398d 100644 --- a/docs/ja/docs/advanced/wsgi.md +++ b/docs/ja/docs/advanced/wsgi.md @@ -1,12 +1,13 @@ # WSGI の組み込み - Flask、Django など { #including-wsgi-flask-django-others } + [サブアプリケーション - マウント](sub-applications.md)、[プロキシの背後](behind-a-proxy.md) で見たように、WSGI アプリケーションをマウントできます。 そのために `WSGIMiddleware` を使用して、Flask や Django などの WSGI アプリをラップできます。 ## `WSGIMiddleware` の使用 { #using-wsgimiddleware } -/// info | 情報 +/// note | 備考 これには `a2wsgi` のインストールが必要です。例: `pip install a2wsgi`。 diff --git a/docs/ja/docs/alternatives.md b/docs/ja/docs/alternatives.md index b1b3874a7..3b3140ed8 100644 --- a/docs/ja/docs/alternatives.md +++ b/docs/ja/docs/alternatives.md @@ -88,7 +88,7 @@ Requestsは非常にシンプルかつ直感的なデザインで使いやすく response = requests.get("http://example.com/some/url") ``` -対応するFastAPIのAPIのpath operationはこのようになります: +対応するFastAPI側のAPI *path operation* はこのようになります: ```Python hl_lines="1" @app.get("/some/url") @@ -96,12 +96,12 @@ def read_url(): return {"message": "Hello World"} ``` - `requests.get(...)` と`@app.get(...)` には類似点が見受けられます。 +`requests.get(...)` と`@app.get(...)` には類似点が見受けられます。 /// tip | **FastAPI**へ与えたインスピレーション * シンプルで直感的なAPIを持っている点。 -* HTTPメソッド名を直接利用し、単純で直感的である。 +* HTTPメソッド名 (operation) を直接利用し、単純で直感的である。 * 適切なデフォルト値を持ちつつ、強力なカスタマイズ性を持っている。 /// @@ -223,7 +223,7 @@ Flask、Flask-apispec、Marshmallow、Webargsの組み合わせは、**FastAPI** * [https://github.com/tiangolo/full-stack-flask-couchbase](https://github.com/tiangolo/full-stack-flask-couchbase) * [https://github.com/tiangolo/full-stack-flask-couchdb](https://github.com/tiangolo/full-stack-flask-couchdb) -そして、これらのフルスタックジェネレーターは、[**FastAPI** Project Generators](project-generation.md)の元となっていました。 +そして、これらのフルスタックジェネレーターは、[**FastAPI** プロジェクトジェネレーター](project-generation.md)の元となっていました。 /// note | 備考 @@ -247,7 +247,7 @@ Angular 2にインスピレーションを受けた、統合された依存性 パラメータはTypeScriptの型で記述されるので (Pythonの型ヒントに似ています) 、エディタのサポートはとても良いです。 -しかし、TypeScriptのデータはJavaScriptへのコンパイル後には残されないため、バリデーション、シリアライゼーション、ドキュメント化を同時に定義するのに型に頼ることはできません。そのため、バリデーション、シリアライゼーション、スキーマの自動生成を行うためには、多くの場所でデコレータを追加する必要があり、非常に冗長になります。 +しかし、TypeScriptのデータはJavaScriptへのコンパイル後には残されないため、バリデーション、シリアライゼーション、ドキュメント化を同時に定義するのに型に頼ることはできません。このことといくつかの設計上の判断により、バリデーション、シリアライゼーション、スキーマの自動生成を行うためには、多くの場所でデコレータを追加する必要があり、非常に冗長になります。 入れ子になったモデルをうまく扱えません。そのため、リクエストのJSONボディが内部フィールドを持つJSONオブジェクトで、それが順番にネストされたJSONオブジェクトになっている場合、適切にドキュメント化やバリデーションをすることができません。 @@ -333,15 +333,15 @@ OpenAPIやJSON Schemaのような標準に基づいたものではありませ 同じフレームワークを使ってAPIとCLIを作成できる、面白く珍しい機能を持っています。 -以前のPythonの同期型Webフレームワーク標準 (WSGI) をベースにしているため、Websocketなどは扱えませんが、それでも高性能です。 +以前のPythonの同期型Webフレームワーク標準 (WSGI) をベースにしているため、WebSocketなどは扱えませんが、それでも高性能です。 /// note | 備考 -HugはTimothy Crosleyにより作成されました。彼は[`isort`](https://github.com/timothycrosley/isort)など、Pythonのファイル内のインポートの並び替えを自動的におこうなう素晴らしいツールの開発者です。 +HugはTimothy Crosleyにより作成されました。彼は[`isort`](https://github.com/timothycrosley/isort)など、Pythonのファイル内のインポートの並び替えを自動的に行う素晴らしいツールの開発者です。 /// -/// tip | **FastAPI**へ与えたインスピレーション +/// tip | **FastAPI**にインスピレーションを与えたアイデア HugはAPIStarに部分的なインスピレーションを与えており、私が発見した中ではAPIStarと同様に最も期待の持てるツールの一つでした。 @@ -430,7 +430,7 @@ Starletteは、軽量な -/// info | 情報 +/// note | 備考 パッケージの依存関係を定義しインストールするためのフォーマットやツールは他にもあります。 @@ -243,14 +243,14 @@ Docker命令 [`CMD`](https://docs.docker.com/reference/dockerfile/#cmd) は2つ ✅ **Exec** 形式: ```Dockerfile -# ✅ Do this +# ✅ こうしてください CMD ["fastapi", "run", "app/main.py", "--port", "80"] ``` ⛔️ **Shell** 形式: ```Dockerfile -# ⛔️ Don't do this +# ⛔️ こうしないでください CMD fastapi run app/main.py --port 80 ``` @@ -340,7 +340,7 @@ $ docker build -t myimage . /// -### Dockerコンテナの起動する { #start-the-docker-container } +### Dockerコンテナを起動する { #start-the-docker-container } * イメージに基づいてコンテナを実行します: @@ -417,7 +417,7 @@ CMD ["fastapi", "run", "main.py", "--port", "80"] コンテナという観点から、[デプロイのコンセプト](concepts.md)に共通するいくつかについて、もう一度説明しましょう。 -コンテナは主に、アプリケーションの**ビルドとデプロイ**のプロセスを簡素化するためのツールですが、これらの**デプロイのコンセプト**を扱うための特定のアプローチを強制するものではなく、いくつかの戦略があります。 +コンテナは主に、アプリケーションの**ビルドとデプロイ**のプロセスを簡素化するための工具ですが、これらの**デプロイのコンセプト**を扱うための特定のアプローチを強制するものではなく、いくつかの戦略があります。 **良いニュース**は、それぞれの異なる戦略には、すべてのデプロイメントのコンセプトをカバーする方法があるということです。🎉 @@ -562,7 +562,7 @@ Docker Composeで**単一サーバ**(クラスタではない)にデプロ 複数の**コンテナ**があり、おそらくそれぞれが**単一のプロセス**を実行している場合(例えば、**Kubernetes**クラスタなど)、レプリケートされたワーカーコンテナを実行する**前に**、単一のコンテナで**事前のステップ**の作業を行う**別のコンテナ**を持ちたいと思うでしょう。 -/// info | 情報 +/// note | 備考 もしKubernetesを使用している場合, これはおそらく[Init Container](https://kubernetes.io/docs/concepts/workloads/pods/init-containers/)でしょう。 diff --git a/docs/ja/docs/deployment/fastapicloud.md b/docs/ja/docs/deployment/fastapicloud.md index 3dd5685a2..d8c1cb2ec 100644 --- a/docs/ja/docs/deployment/fastapicloud.md +++ b/docs/ja/docs/deployment/fastapicloud.md @@ -1,26 +1,6 @@ # FastAPI Cloud { #fastapi-cloud } -[FastAPI Cloud](https://fastapicloud.com) に **コマンド1つ** でデプロイできます。まだならウェイティングリストにご登録ください。🚀 - -## ログイン { #login } - -すでに **FastAPI Cloud** アカウントをお持ちであることを確認してください(ウェイティングリストからご招待しています 😉)。 - -次にログインします: - -
- -```console -$ fastapi login - -You are logged in to FastAPI Cloud 🚀 -``` - -
- -## デプロイ { #deploy } - -では、**コマンド1つ** でアプリをデプロイします: +[FastAPI Cloud](https://fastapicloud.com) に **コマンド1つ** で FastAPI アプリをデプロイできます。🚀
@@ -36,6 +16,8 @@ Deploying to FastAPI Cloud...
+CLI は FastAPI アプリケーションを自動検出してクラウドにデプロイします。ログインしていない場合は、認証を完了するためにブラウザが開きます。 + 以上です!その URL からアプリにアクセスできます。✨ ## FastAPI Cloud について { #about-fastapi-cloud } diff --git a/docs/ja/docs/deployment/https.md b/docs/ja/docs/deployment/https.md index 37ad7072c..fc4ca9b67 100644 --- a/docs/ja/docs/deployment/https.md +++ b/docs/ja/docs/deployment/https.md @@ -43,7 +43,6 @@ TLS Termination Proxyとして使えるオプションには、以下のよう * Nginx * HAProxy - ## Let's Encrypt { #lets-encrypt } Let's Encrypt以前は、これらの**HTTPS証明書**は信頼できる第三者によって販売されていました。 @@ -100,11 +99,9 @@ TLS接続を確立するためのクライアントとサーバー間のこの ### SNI拡張機能付きのTLS { #tls-with-sni-extension } -サーバー内の**1つのプロセス**だけが、特定の**IPアドレス**の特定の**ポート**で待ち受けることができます。 - -同じIPアドレスの他のポートで他のプロセスがリッスンしている可能性もありますが、IPアドレスとポートの組み合わせごとに1つだけです。 +サーバー内の**1つのプロセス**だけが、特定の**IPアドレス**の特定の**ポート**で待ち受けることができます。同じIPアドレスの他のポートで他のプロセスがリッスンしている可能性もありますが、IPアドレスとポートの組み合わせごとに1つだけです。 -TLS(HTTPS)はデフォルトで`443`という特定のポートを使用する。つまり、これが必要なポートです。 +TLS(HTTPS)はデフォルトで`443`という特定のポートを使用します。つまり、これが必要なポートです。 このポートをリクエストできるのは1つのプロセスだけなので、これを実行するプロセスは**TLS Termination Proxy**となります。 @@ -120,9 +117,9 @@ TLS Termination Proxyは、1つ以上の**TLS証明書**(HTTPS証明書)に 次に証明書を使用して、クライアントとTLS Termination Proxy は、 **TCP通信**の残りを**どのように暗号化するかを決定**します。これで**TLSハンドシェイク**の部分が完了します。 -この後、クライアントとサーバーは**暗号化されたTCP接続**を持ちます。そして、その接続を使って実際の**HTTP通信**を開始することができます。 +この後、クライアントとサーバーは**暗号化されたTCP接続**を持ちます。これがTLSの提供するものです。そして、その接続を使って実際の**HTTP通信**を開始することができます。 -これが**HTTPS**であり、純粋な(暗号化されていない)TCP接続ではなく、**セキュアなTLS接続**の中に**HTTP**があるだけです。 +これが**HTTPS**であり、純粋な(暗号化されていない)TCP接続ではなく、**セキュアなTLS接続**の中に単なる**HTTP**があるだけです。 /// tip | 豆知識 @@ -152,7 +149,7 @@ TLS Termination Proxy は、合意が取れている暗号化を使用して、* ### HTTPS レスポンス { #https-response } -TLS Termination Proxyは次に、事前に合意が取れている暗号(`someapp.example.com`の証明書から始まる)を使って**レスポンスを暗号化し**、ブラウザに送り返す。 +TLS Termination Proxyは次に、事前に合意が取れている暗号(`someapp.example.com`の証明書から始まる)を使って**レスポンスを暗号化し**、ブラウザに送り返します。 その後ブラウザでは、レスポンスが有効で正しい暗号キーで暗号化されていることなどを検証します。そして、ブラウザはレスポンスを**復号化**して処理します。 @@ -191,7 +188,6 @@ TLS Termination Proxyは次に、事前に合意が取れている暗号(`someap * これは、同じTLS Termination Proxyが証明書の更新処理も行う場合に非常に便利な理由の1つです。 * そうでなければ、TLS Termination Proxyを一時的に停止し、証明書を取得するために更新プログラムを起動し、TLS Termination Proxyで証明書を設定し、TLS Termination Proxyを再起動しなければならないかもしれません。TLS Termination Proxyが停止している間はアプリが利用できなくなるため、これは理想的ではありません。 - アプリを提供しながらこのような更新処理を行うことは、アプリケーション・サーバー(Uvicornなど)でTLS証明書を直接使用するのではなく、TLS Termination Proxyを使用して**HTTPSを処理する別のシステム**を用意したくなる主な理由の1つです。 ## プロキシ転送ヘッダー { #proxy-forwarded-headers } diff --git a/docs/ja/docs/deployment/manually.md b/docs/ja/docs/deployment/manually.md index 1c0d59a71..98cd48575 100644 --- a/docs/ja/docs/deployment/manually.md +++ b/docs/ja/docs/deployment/manually.md @@ -1,6 +1,6 @@ # サーバーを手動で実行する { #run-a-server-manually } -## fastapi run コマンドを使う { #use-the-fastapi-run-command } +## `fastapi run` コマンドを使う { #use-the-fastapi-run-command } 結論として、FastAPI アプリケーションを提供するには `fastapi run` を使います: @@ -56,7 +56,6 @@ FastAPI は、Python の Web フレームワークとサーバーのための標 * [Hypercorn](https://hypercorn.readthedocs.io/): HTTP/2 や Trio に対応する ASGI サーバーなど。 * [Daphne](https://github.com/django/daphne): Django Channels のために作られた ASGI サーバー。 * [Granian](https://github.com/emmett-framework/granian): Python アプリケーション向けの Rust 製 HTTP サーバー。 -* [NGINX Unit](https://unit.nginx.org/howto/fastapi/): 軽量で多用途な Web アプリケーションランタイム。 ## サーバーマシンとサーバープログラム { #server-machine-and-server-program } diff --git a/docs/ja/docs/deployment/server-workers.md b/docs/ja/docs/deployment/server-workers.md index c4c6e9355..55cf2d247 100644 --- a/docs/ja/docs/deployment/server-workers.md +++ b/docs/ja/docs/deployment/server-workers.md @@ -17,7 +17,7 @@ ここでは、`fastapi` コマンド、または `uvicorn` コマンドを直接使って、**ワーカープロセス**付きの **Uvicorn** を使う方法を紹介します。 -/// info | 情報 +/// note DockerやKubernetesなどのコンテナを使用している場合は、次の章で詳しく説明します: [コンテナ内のFastAPI - Docker](docker.md)。 diff --git a/docs/ja/docs/editor-support.md b/docs/ja/docs/editor-support.md index d82e970f9..b0e5466d6 100644 --- a/docs/ja/docs/editor-support.md +++ b/docs/ja/docs/editor-support.md @@ -20,4 +20,4 @@ - **FastAPI Cloud へデプロイ** - [FastAPI Cloud](https://fastapicloud.com/) にワンクリックでアプリをデプロイできます。 - **アプリケーションログのストリーミング** - FastAPI Cloud にデプロイしたアプリから、レベルフィルタやテキスト検索付きでリアルタイムにログをストリーミングできます。 -拡張機能の機能に慣れるには、コマンドパレット(Ctrl + Shift + P、macOS: Cmd + Shift + P)を開き、"Welcome: Open walkthrough..." を選択してから、"Get started with FastAPI" のウォークスルーを選んでください。 +拡張機能の機能に慣れるには、コマンドパレット(Ctrl + Shift + P、macOS: Cmd + Shift + P)を開き、「Welcome: Open walkthrough...」を選択してから、「Get started with FastAPI」のウォークスルーを選んでください。 diff --git a/docs/ja/docs/environment-variables.md b/docs/ja/docs/environment-variables.md index 846f32846..eb20d3a58 100644 --- a/docs/ja/docs/environment-variables.md +++ b/docs/ja/docs/environment-variables.md @@ -163,7 +163,7 @@ Hello World from Python つまり、環境変数からPythonで読み取る**あらゆる値**は **`str`になり**、他の型への変換やバリデーションはコード内で行う必要があります。 -環境変数を使って**アプリケーション設定**を扱う方法については、[高度なユーザーガイド - Settings and Environment Variables](./advanced/settings.md)で詳しく学べます。 +環境変数を使って**アプリケーション設定**を扱う方法については、[高度なユーザーガイド - 設定と環境変数](./advanced/settings.md)で詳しく学べます。 ## `PATH`環境変数 { #path-environment-variable } @@ -285,7 +285,7 @@ $ C:\opt\custompython\bin\python //// -この情報は、[Virtual Environments](virtual-environments.md)について学ぶ際にも役立ちます。 +この情報は、[仮想環境](virtual-environments.md)について学ぶ際にも役立ちます。 ## まとめ { #conclusion } @@ -295,4 +295,4 @@ $ C:\opt\custompython\bin\python 多くの場合、環境変数がどのように役立ち、すぐに適用できるのかはあまり明確ではありません。しかし、開発中のさまざまなシナリオで何度も登場するため、知っておくとよいでしょう。 -例えば、次のセクションの[Virtual Environments](virtual-environments.md)でこの情報が必要になります。 +例えば、次のセクションの[仮想環境](virtual-environments.md)でこの情報が必要になります。 diff --git a/docs/ja/docs/features.md b/docs/ja/docs/features.md index 607a59c4d..930988428 100644 --- a/docs/ja/docs/features.md +++ b/docs/ja/docs/features.md @@ -99,7 +99,7 @@ Python 開発者調査では、[最もよく使われる機能の 1 つが「オ すべてに妥当な **デフォルト** があり、どこでもオプションで構成できます。必要に応じてすべてのパラメータを微調整して、求める API を定義できます。 -しかしデフォルトのままでも、すべて **うまく動きます**。 +しかしデフォルトのままでも、すべて **「うまく動きます」**。 ### 検証 { #validation } @@ -140,7 +140,7 @@ FastAPI には、非常に使いやすく、かつ非常に強力な * 本番アプリケーションを構築している社内開発チームのテストに基づく見積もりです。 -## Sponsors { #sponsors } +## スポンサー { #sponsors } -### Keystone Sponsor { #keystone-sponsor } +### Keystone スポンサー { #keystone-sponsor }
{% for sponsor in sponsors.keystone -%} @@ -65,7 +65,7 @@ FastAPI は、Python の標準である型ヒントに基づいて Python で AP {% endfor -%}
-### Gold Sponsors { #gold-sponsors } +### Gold スポンサー { #gold-sponsors }
{% for sponsor in sponsors.gold -%} @@ -73,7 +73,7 @@ FastAPI は、Python の標準である型ヒントに基づいて Python で AP {% endfor -%}
-### Silver Sponsors { #silver-sponsors } +### Silver スポンサー { #silver-sponsors }
{% for sponsor in sponsors.silver -%} @@ -125,7 +125,7 @@ FastAPI は、Python の標準である型ヒントに基づいて Python で AP
-"_[...] 最近 **FastAPI** を使っています。 [...] 実際に私のチームの全ての **Microsoft の機械学習サービス** で使用する予定です。 そのうちのいくつかのコアな **Windows** 製品と **Office** 製品に統合されつつあります。_" +"_[...] 最近 **FastAPI** をたくさん使っています。 [...] 実際に私のチームの全ての **Microsoft の機械学習サービス** で使用する予定です。 そのうちのいくつかのコアな **Windows** 製品と **Office** 製品に統合されつつあります。_"
Kabir Khan - Microsoft (ref)
@@ -275,7 +275,7 @@ INFO: Application startup complete.
-fastapi dev コマンドについて +fastapi dev コマンドについて... `fastapi dev` コマンドは `main.py` ファイルを自動的に読み取り、その中の **FastAPI** アプリを検出し、[Uvicorn](https://www.uvicorn.dev) を使用してサーバーを起動します。 @@ -471,11 +471,11 @@ item: Item ...に変更し、エディタが属性を自動補完し、その型を知ることを確認してください。 -![editor support](https://fastapi.tiangolo.com/img/vscode-completion.png) +![エディタサポート](https://fastapi.tiangolo.com/img/vscode-completion.png) -より多くの機能を含む、より完全な例については、Tutorial - User Guide を参照してください。 +より多くの機能を含む、より完全な例については、チュートリアル - ユーザーガイド を参照してください。 -**ネタバレ注意**: tutorial - user guide には以下が含まれます。 +**ネタバレ注意**: チュートリアル - ユーザーガイドには以下が含まれます。 * **ヘッダー**、**Cookie**、**フォームフィールド**、**ファイル**など、他のさまざまな場所からの **パラメータ** 宣言。 * `maximum_length` や `regex` のような **検証制約** を設定する方法。 @@ -492,9 +492,7 @@ item: Item ### アプリをデプロイ(任意) { #deploy-your-app-optional } -必要に応じて FastAPI アプリを [FastAPI Cloud](https://fastapicloud.com) にデプロイできます。まだの場合はウェイティングリストに参加してください。 🚀 - -すでに **FastAPI Cloud** アカウント(ウェイティングリストから招待されました 😉)がある場合は、1 コマンドでアプリケーションをデプロイできます。 +1 コマンドで FastAPI アプリを [FastAPI Cloud](https://fastapicloud.com) にデプロイできます。 🚀
@@ -510,6 +508,8 @@ Deploying to FastAPI Cloud...
+CLI は自動的に FastAPI アプリケーションを検出し、クラウドへデプロイします。ログインしていない場合は、認証を完了するためにブラウザが開きます。 + これで完了です!その URL でアプリにアクセスできます。 ✨ #### FastAPI Cloud について { #about-fastapi-cloud } diff --git a/docs/ja/docs/project-generation.md b/docs/ja/docs/project-generation.md index b6550e3ac..829d6a608 100644 --- a/docs/ja/docs/project-generation.md +++ b/docs/ja/docs/project-generation.md @@ -2,7 +2,7 @@ テンプレートは通常、特定のセットアップが含まれていますが、柔軟でカスタマイズできるように設計されています。これにより、プロジェクトの要件に合わせて変更・適応でき、優れた出発点になります。🏁 -このテンプレートを使って開始できます。初期セットアップ、セキュリティ、データベース、いくつかのAPIエンドポイントがすでに用意されています。 +このテンプレートを使って開始できます。初期セットアップの多く、セキュリティ、データベース、いくつかのAPIエンドポイントがすでに用意されています。 GitHubリポジトリ: [Full Stack FastAPI Template](https://github.com/tiangolo/full-stack-fastapi-template) diff --git a/docs/ja/docs/python-types.md b/docs/ja/docs/python-types.md index 2399503fc..e6ff3c25d 100644 --- a/docs/ja/docs/python-types.md +++ b/docs/ja/docs/python-types.md @@ -151,7 +151,7 @@ def some_function(data: Any): 一部の型は、角括弧内で「型パラメータ」を受け取り、内部の型を定義できます。例えば「文字列のリスト」は `list[str]` として宣言します。 -このように型パラメータを取れる型は **Generic types**(ジェネリクス)と呼ばれます。 +このように型パラメータを取れる型は **Generic types** または **Generics**(ジェネリクス)と呼ばれます。 次の組み込み型をジェネリクスとして(角括弧と内部の型で)使えます: @@ -265,7 +265,7 @@ def some_function(data: Any): これは「`one_person` はクラス `Person` の **インスタンス** である」ことを意味します。 -「`one_person` は `Person` という名前の **クラ ス** である」という意味ではありません。 +「`one_person` は `Person` という名前の **クラス** である」という意味ではありません。 ## Pydantic のモデル { #pydantic-models } @@ -343,6 +343,6 @@ Python 自体は、この `Annotated` で何かをするわけではありませ /// note | 備考 -すでにすべてのチュートリアルを終えて、型についての詳細を見るためにこのページに戻ってきた場合は、良いリソースとして [`mypy` の「チートシート`](https://mypy.readthedocs.io/en/latest/cheat_sheet_py3.html) があります。 +すでにすべてのチュートリアルを終えて、型についての詳細を見るためにこのページに戻ってきた場合は、良いリソースとして [`mypy` の「チートシート」](https://mypy.readthedocs.io/en/latest/cheat_sheet_py3.html) があります。 /// diff --git a/docs/ja/docs/tutorial/bigger-applications.md b/docs/ja/docs/tutorial/bigger-applications.md index 3cd80d797..51ea7be51 100644 --- a/docs/ja/docs/tutorial/bigger-applications.md +++ b/docs/ja/docs/tutorial/bigger-applications.md @@ -17,16 +17,16 @@ Flask 出身であれば、Flask の Blueprint に相当します。 ``` . ├── app -│   ├── __init__.py -│   ├── main.py -│   ├── dependencies.py -│   └── routers -│   │ ├── __init__.py -│   │ ├── items.py -│   │ └── users.py -│   └── internal -│   ├── __init__.py -│   └── admin.py +│ ├── __init__.py +│ ├── main.py +│ ├── dependencies.py +│ └── routers +│ │ ├── __init__.py +│ │ ├── items.py +│ │ └── users.py +│ └── internal +│ ├── __init__.py +│ └── admin.py ``` /// tip | 豆知識 @@ -396,9 +396,9 @@ from .routers.users import router /// note | 技術詳細 -実際には、`APIRouter` で宣言された各 *path operation* ごとに内部的に *path operation* が作成されます。 +FastAPI は、ルーターをメインアプリに取り込んだ後も、元の `APIRouter` とその `APIRoute` を有効なまま保持します。 -つまり裏側では、すべてが同じ単一のアプリであるかのように動作します。 +そのため、カスタムの `APIRouter` や `APIRoute` のサブクラスも、取り込み後に引き続き機能します。 /// @@ -406,7 +406,7 @@ from .routers.users import router ルーターを取り込んでもパフォーマンスを心配する必要はありません。 -これは起動時にマイクロ秒で行われます。 +これは軽量に設計され、各リクエストにオーバーヘッドを追加しないようになっています。 したがってパフォーマンスには影響しません。⚡ @@ -461,7 +461,7 @@ from .routers.users import router これは、それらの *path operations* を OpenAPI スキーマやユーザーインターフェースに含めたいからです。 -完全に分離して独立に「マウント」できないため、*path operations* は直接取り込まれるのではなく「クローン(再作成)」されます。 +FastAPI は元のルーターと *path operations* を有効なまま保持し、リクエスト処理や OpenAPI 生成の際に、ルーターの prefix、dependencies、tags、responses、その他のメタデータを組み合わせます。 /// @@ -532,4 +532,16 @@ $ fastapi dev router.include_router(other_router) ``` -`router` を `FastAPI` アプリに取り込む前にこれを実行して、`other_router` の *path operations* も含まれるようにしてください。 +これは、`router` を `FastAPI` アプリに取り込む前でも後でも実行できます。FastAPI は `other_router` の *path operations* をルーティングと OpenAPI に含めます。 + +同様に、後からルーターに追加された *path operations* も、以前の取り込みを通して見えるようになります。 + +/// warning | 注意 + +`router` を取り込んだ後に、`router.routes` を直接ミューテートするのは避けてください。FastAPI はルーターの取り込みをライブとして扱うため、元のルーターとそのルートはルーティングと OpenAPI 生成の一部のままです。 + +ルートやルーターを追加するには、path operation デコレータや `.include_router()` などのドキュメント化された API を使用してください。 + +`router.routes` は、ルート定義や取り込まれたルーターを含みうる低レベルのルートツリーとして扱い、最終的な *path operations* のフラットな一覧として当てにしないでください。 + +/// diff --git a/docs/ja/docs/tutorial/body-multiple-params.md b/docs/ja/docs/tutorial/body-multiple-params.md index 0f81f4c46..1a150d192 100644 --- a/docs/ja/docs/tutorial/body-multiple-params.md +++ b/docs/ja/docs/tutorial/body-multiple-params.md @@ -110,7 +110,7 @@ q: str | None = None {* ../../docs_src/body_multiple_params/tutorial004_an_py310.py hl[28] *} -/// info | 情報 +/// note | 備考 `Body`もまた、後述する `Query` や `Path` などと同様に、すべての追加検証パラメータとメタデータパラメータを持っています。 @@ -125,7 +125,7 @@ Pydanticモデル`Item`の単一の`item`ボディパラメータしかないと しかし、追加のボディパラメータを宣言したときのように、キー `item` を持つ JSON と、その中のモデル内容を期待したい場合は、特別な `Body` パラメータ `embed` を使うことができます: ```Python -item: Item = Body(embed=True) +item: Annotated[Item, Body(embed=True)] ``` 以下において: diff --git a/docs/ja/docs/tutorial/body-nested-models.md b/docs/ja/docs/tutorial/body-nested-models.md index 5187eb14e..d926189ff 100644 --- a/docs/ja/docs/tutorial/body-nested-models.md +++ b/docs/ja/docs/tutorial/body-nested-models.md @@ -1,5 +1,6 @@ # ボディ - ネストされたモデル { #body-nested-models } + **FastAPI** を使用すると、深くネストされた任意のモデルを定義、検証、文書化、使用することができます(Pydanticのおかげです)。 ## リストのフィールド { #list-fields } @@ -135,8 +136,7 @@ Pydanticモデルを`list`や`set`などのサブタイプとして使用する ] } ``` - -/// info | 情報 +/// note | 備考 `images`キーが画像オブジェクトのリストを持つようになったことに注目してください。 @@ -148,7 +148,7 @@ Pydanticモデルを`list`や`set`などのサブタイプとして使用する {* ../../docs_src/body_nested_models/tutorial007_py310.py hl[7,12,18,21,25] *} -/// info | 情報 +/// note | 備考 `Offer`は`Item`のリストであり、それらがさらにオプションの`Image`のリストを持っていることに注目してください。 diff --git a/docs/ja/docs/tutorial/body.md b/docs/ja/docs/tutorial/body.md index 9f100738c..c26198d3b 100644 --- a/docs/ja/docs/tutorial/body.md +++ b/docs/ja/docs/tutorial/body.md @@ -1,5 +1,6 @@ # リクエストボディ { #request-body } + クライアント(例えばブラウザ)からAPIにデータを送信する必要がある場合、**リクエストボディ**として送信します。 **リクエスト**ボディは、クライアントからAPIへ送信されるデータです。**レスポンス**ボディは、APIがクライアントに送信するデータです。 @@ -8,7 +9,7 @@ APIはほとんどの場合 **レスポンス** ボディを送信する必要 **リクエスト**ボディを宣言するには、[Pydantic](https://docs.pydantic.dev/) モデルを使用し、その強力な機能とメリットをすべて利用します。 -/// info | 情報 +/// note | 備考 データを送信するには、`POST`(より一般的)、`PUT`、`DELETE`、`PATCH` のいずれかを使用すべきです。 diff --git a/docs/ja/docs/tutorial/cookie-param-models.md b/docs/ja/docs/tutorial/cookie-param-models.md index 89ae42438..a90ffdbb7 100644 --- a/docs/ja/docs/tutorial/cookie-param-models.md +++ b/docs/ja/docs/tutorial/cookie-param-models.md @@ -32,7 +32,7 @@
-/// info | 情報 +/// note | 備考 **ブラウザがクッキーを処理し**ていますが、特別な方法で内部的に処理を行っているために、**JavaScript**からは簡単に操作**できない**ことに留意してください。 diff --git a/docs/ja/docs/tutorial/cookie-params.md b/docs/ja/docs/tutorial/cookie-params.md index 1e5a0d3cf..894eb9edb 100644 --- a/docs/ja/docs/tutorial/cookie-params.md +++ b/docs/ja/docs/tutorial/cookie-params.md @@ -24,13 +24,13 @@ /// -/// info | 情報 +/// note | 備考 クッキーを宣言するには、`Cookie`を使う必要があります。なぜなら、そうしないとパラメータがクエリのパラメータとして解釈されてしまうからです。 /// -/// info | 情報 +/// note | 備考 **ブラウザがクッキーを**特殊な方法で裏側で扱うため、**JavaScript** から簡単には触れられないことを念頭に置いてください。 diff --git a/docs/ja/docs/tutorial/debugging.md b/docs/ja/docs/tutorial/debugging.md index a5b0c9016..1a02e1933 100644 --- a/docs/ja/docs/tutorial/debugging.md +++ b/docs/ja/docs/tutorial/debugging.md @@ -99,7 +99,7 @@ from myapp import app --- -Pycharmを使用する場合、次のことが可能です: +PyCharmを使用する場合、次のことが可能です: * 「実行」メニューをオープン。 * オプション「デバッグ...」を選択。 diff --git a/docs/ja/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md b/docs/ja/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md index 573ccc1f9..56eefa3c8 100644 --- a/docs/ja/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md +++ b/docs/ja/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md @@ -28,11 +28,11 @@ /// -/// info | 情報 +/// note | 備考 この例では、架空のカスタムヘッダー `X-Key` と `X-Token` を使用しています。 -しかし実際のケースでセキュリティを実装する際は、統合された[Security utilities(次の章)](../security/index.md)を使うことで、より多くの利点を得られます。 +しかし実際のケースでセキュリティを実装する際は、統合された[セキュリティユーティリティ(次の章)](../security/index.md)を使うことで、より多くの利点を得られます。 /// @@ -62,7 +62,7 @@ ## *path operation*のグループに対する依存関係 { #dependencies-for-a-group-of-path-operations } -後で、より大きなアプリケーションを(おそらく複数ファイルで)構造化する方法([Bigger Applications - Multiple Files](../../tutorial/bigger-applications.md))について読むときに、*path operation*のグループに対して単一の`dependencies`パラメータを宣言する方法を学びます。 +後で、より大きなアプリケーションを(おそらく複数ファイルで)構造化する方法([より大きなアプリケーション - 複数ファイル](../../tutorial/bigger-applications.md))について読むときに、*path operation*のグループに対して単一の`dependencies`パラメータを宣言する方法を学びます。 ## グローバル依存関係 { #global-dependencies } diff --git a/docs/ja/docs/tutorial/dependencies/dependencies-with-yield.md b/docs/ja/docs/tutorial/dependencies/dependencies-with-yield.md index 83e4f8809..b4ddfe7f8 100644 --- a/docs/ja/docs/tutorial/dependencies/dependencies-with-yield.md +++ b/docs/ja/docs/tutorial/dependencies/dependencies-with-yield.md @@ -170,7 +170,7 @@ participant tasks as Background tasks end ``` -/// info | 情報 +/// note | 備考 **1つのレスポンス** だけがクライアントに送信されます。それはエラーレスポンスの一つかもしれませんし、*path operation*からのレスポンスかもしれません。 @@ -234,6 +234,7 @@ participant operation as Path Operation `yield`を持つ依存関係は、さまざまなユースケースをカバーし、いくつかの問題を修正するために、時間とともに進化してきました。 FastAPIの異なるバージョンで何が変わったのかを知りたい場合は、上級ガイドの[上級の依存関係 - `yield`、`HTTPException`、`except`、バックグラウンドタスクを持つ依存関係](../../advanced/advanced-dependencies.md#dependencies-with-yield-httpexception-except-and-background-tasks)で詳しく読めます。 + ## コンテキストマネージャ { #context-managers } ### 「コンテキストマネージャ」とは { #what-are-context-managers } diff --git a/docs/ja/docs/tutorial/dependencies/index.md b/docs/ja/docs/tutorial/dependencies/index.md index a3cf3e26b..9b8b5ad57 100644 --- a/docs/ja/docs/tutorial/dependencies/index.md +++ b/docs/ja/docs/tutorial/dependencies/index.md @@ -51,7 +51,7 @@ そして、これらの値を含む`dict`を返します。 -/// info | 情報 +/// note | 備考 FastAPI はバージョン 0.95.0 で `Annotated` のサポートを追加し(そして推奨し始めました)。 @@ -106,7 +106,7 @@ common_parameters --> read_users この方法では、共有されるコードを一度書き、**FastAPI** が*path operation*のための呼び出しを行います。 -/// check | 確認 +/// tip | 豆知識 特別なクラスを作成してどこかで **FastAPI** に渡して「登録」する必要はないことに注意してください。 diff --git a/docs/ja/docs/tutorial/dependencies/sub-dependencies.md b/docs/ja/docs/tutorial/dependencies/sub-dependencies.md index fa27781f9..5d6533b11 100644 --- a/docs/ja/docs/tutorial/dependencies/sub-dependencies.md +++ b/docs/ja/docs/tutorial/dependencies/sub-dependencies.md @@ -35,7 +35,7 @@ {* ../../docs_src/dependencies/tutorial005_an_py310.py hl[23] *} -/// info | 情報 +/// note | 備考 *path operation 関数*の中で宣言している依存関係は`query_or_cookie_extractor`の1つだけであることに注意してください。 diff --git a/docs/ja/docs/tutorial/extra-data-types.md b/docs/ja/docs/tutorial/extra-data-types.md index 1bbfeb71e..b63e3fe1a 100644 --- a/docs/ja/docs/tutorial/extra-data-types.md +++ b/docs/ja/docs/tutorial/extra-data-types.md @@ -1,5 +1,6 @@ # 追加データ型 { #extra-data-types } + 今まで、以下のような一般的なデータ型を使用してきました: * `int` diff --git a/docs/ja/docs/tutorial/extra-models.md b/docs/ja/docs/tutorial/extra-models.md index 20883068c..d9548500e 100644 --- a/docs/ja/docs/tutorial/extra-models.md +++ b/docs/ja/docs/tutorial/extra-models.md @@ -208,4 +208,4 @@ some_variable: PlaneItem | CarItem 複数のPydanticモデルを使用し、ケースごとに自由に継承します。 -エンティティが異なる「状態」を持たなければならない場合は、エンティティごとに単一のデータモデルを持つ必要はありません。`password`、`password_hash`、パスワードなしを含む状態を持つユーザー「エンティティ」の場合と同様です。 +エンティティが異なる「状態」を持たなければならない場合は、エンティティごとに単一のデータモデルを持つ必要はありません。`password`、`password_hash`、パスワードなしを含む状態を持つ**ユーザー**「エンティティ」の場合と同様です。 diff --git a/docs/ja/docs/tutorial/first-steps.md b/docs/ja/docs/tutorial/first-steps.md index 26cb49159..ae0556d15 100644 --- a/docs/ja/docs/tutorial/first-steps.md +++ b/docs/ja/docs/tutorial/first-steps.md @@ -78,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](http://127.0.0.1:8000/redoc)にアクセスします。 -先ほどとは異なる、自動生成された対話的APIドキュメントが表示されます([ReDoc](https://github.com/Rebilly/ReDoc)によって提供): +代替の自動生成ドキュメントが表示されます([ReDoc](https://github.com/Rebilly/ReDoc)によって提供): ![ReDoc](https://fastapi.tiangolo.com/img/index/index-02-redoc-simple.png) @@ -104,7 +104,7 @@ INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) #### OpenAPIおよびJSONスキーマ { #openapi-and-json-schema } -OpenAPIはAPIのためのAPIスキーマを定義します。そして、そのスキーマは**JSONデータスキーマ**の標準規格である**JSON Schema**を利用するAPIによって送受されるデータの定義(または「スキーマ」)を含んでいます。 +OpenAPIはAPIのためのAPIスキーマを定義します。そして、そのスキーマには、JSONデータスキーマの標準である**JSON Schema**を使用して、APIによって送受信されるデータの定義(または「スキーマ」)が含まれます。 #### `openapi.json`を確認 { #check-the-openapi-json } @@ -180,7 +180,7 @@ entrypoint = "backend.main:app" from backend.main import app ``` -### パス付きの`fastapi dev` { #fastapi-dev-with-path } +### パス指定の`fastapi dev`または`--entrypoint` CLIオプション { #fastapi-dev-with-path-or-with-entrypoint-cli-option } `fastapi dev`コマンドにファイルパスを渡すこともでき、使用すべきFastAPIのappオブジェクトを推測します: @@ -188,29 +188,19 @@ from backend.main import app $ fastapi dev main.py ``` -ただし、その場合は毎回`fastapi`コマンドを呼ぶたびに正しいパスを渡すことを覚えておく必要があります。 - -さらに、他のツール(たとえば、[VS Code 拡張機能](../editor-support.md)や[FastAPI Cloud](https://fastapicloud.com))が見つけられない場合があります。そのため、`pyproject.toml`の`entrypoint`を使うことを推奨します。 - -### アプリをデプロイ(任意) { #deploy-your-app-optional } - -任意でFastAPIアプリを[FastAPI Cloud](https://fastapicloud.com)にデプロイできます。まだなら、待機リストに登録してください。 🚀 - -すでに**FastAPI Cloud**アカウントがある場合(待機リストから招待済みの場合😉)、1コマンドでアプリケーションをデプロイできます。 - -デプロイする前に、ログインしていることを確認してください: - -
+または、`fastapi dev`コマンドに`--entrypoint`オプションを渡すこともできます: ```console -$ fastapi login - -You are logged in to FastAPI Cloud 🚀 +$ fastapi dev --entrypoint main:app ``` -
+ただし、その場合は毎回`fastapi`コマンドを呼ぶたびに正しいパスや`entrypoint`を渡すことを覚えておく必要があります。 -その後、アプリをデプロイします: +さらに、他のツール(たとえば、[VS Code 拡張機能](../editor-support.md)や[FastAPI Cloud](https://fastapicloud.com))が見つけられない場合があります。そのため、`pyproject.toml`の`entrypoint`を使うことを推奨します。 + +### アプリをデプロイ(任意) { #deploy-your-app-optional } + +任意でFastAPIアプリを[FastAPI Cloud](https://fastapicloud.com)に1コマンドでデプロイできます。 🚀
@@ -226,6 +216,8 @@ Deploying to FastAPI Cloud...
+CLIはFastAPIアプリケーションを自動検出してクラウドにデプロイします。ログインしていない場合、認証を完了するためにブラウザが開きます。 + 以上です!これで、そのURLでアプリにアクセスできます。 ✨ ## ステップ毎の要約 { #recap-step-by-step } @@ -247,6 +239,7 @@ Deploying to FastAPI Cloud... ### Step 2: `FastAPI`の「インスタンス」を生成 { #step-2-create-a-fastapi-instance } {* ../../docs_src/first_steps/tutorial001_py310.py hl[3] *} + ここで、`app`変数が`FastAPI`クラスの「インスタンス」になります。 これが、すべてのAPIを作成するための主要なポイントになります。 @@ -269,7 +262,7 @@ https://example.com/items/foo /items/foo ``` -/// info | 情報 +/// note | 備考 「パス」は一般に「エンドポイント」または「ルート」とも呼ばれます。 @@ -321,7 +314,7 @@ APIを構築するときは、通常、これらの特定のHTTPメソッドを * パス `/` * get オペレーション -/// info | `@decorator` 情報 +/// note | `@decorator` 情報 Pythonにおける`@something`シンタックスはデコレータと呼ばれます。 diff --git a/docs/ja/docs/tutorial/frontend.md b/docs/ja/docs/tutorial/frontend.md new file mode 100644 index 000000000..facbbc1d1 --- /dev/null +++ b/docs/ja/docs/tutorial/frontend.md @@ -0,0 +1,133 @@ +# フロントエンド { #frontend } + +`app.frontend()`(または `router.frontend()`)で静的なフロントエンドアプリを配信できます。 + +これは、Vite を使った React、TanStack Router、Astro、Vue、Svelte、Angular、Solid など、静的ファイルを生成するフロントエンドツールで役立ちます。 + +これらのツールでは、通常、次のようなコマンドでフロントエンドをビルドするステップがあります。 + +```bash +npm run build +``` + +これにより、フロントエンドファイルを含む `./dist/` のようなディレクトリが生成されます。 + +`app.frontend()` を使うと、これらのフロントエンドフレームワークが必要とする規約に従って、そのディレクトリを配信できます。 + +**FastAPI** は最初に *path operations* をチェックします。通常のルートに一致しなかった場合にのみフロントエンドファイルがチェックされるため、API には影響しません。 + +## フロントエンドの配信 { #serve-a-frontend } + +たとえば `npm run build` でフロントエンドをビルドした後、生成されたファイルを `dist` などのディレクトリに配置します。 + +プロジェクト構成は次のようになります。 + +```text +. +├── pyproject.toml +├── app +│ ├── __init__.py +│ └── main.py +└── dist + ├── index.html + └── assets + └── app.js +``` + +そして `app.frontend()` で配信します。 + +{* ../../docs_src/frontend/tutorial001_py310.py hl[5] *} + +これにより、`/assets/app.js` へのリクエストで `dist/assets/app.js` を配信できます。 + +**FastAPI** の *path operation* もある場合は、*path operation* が優先されます。 + +## クライアントサイドルーティング { #client-side-routing } + +**single-page apps**(SPA)を含む多くのフロントエンドアプリは、クライアントサイドルーティングを使います。`/dashboard/settings` のようなパスは実際のファイルではなく、フレームワークが処理するものかもしれません。 + +そのため、その URL に直接アクセスした場合(アプリ内で遷移するのではなく)、バックエンドは `index.html` からフロントエンドアプリを配信し、フロントエンドフレームワークがクライアントサイドルーティングを処理できるようにする必要があります。 + +そのためには、`fallback="index.html"` を使います。 + +{* ../../docs_src/frontend/tutorial002_py310.py hl[5] *} + +**FastAPI** は、このフォールバックをブラウザのナビゲーションに見える `GET` および `HEAD` リクエストにのみ使用します。JavaScript、CSS、画像などの存在しないファイルは引き続き `404` を返します。 + +`POST` や `PUT` など、他のメソッドのリクエストがフロントエンドのフォールバックにのみ一致するパスへ送られた場合も、`404` を返します。通常の **FastAPI** の *path operations* は、フロントエンドのルートよりも引き続き高い優先順位を持ちます。 + +/// tip | 豆知識 + +デフォルトでは、`fallback` の値は `fallback="auto"` です。ほとんどの場合、`fallback` を指定する必要はありません。詳細は以下を参照してください。 + +/// + +これは、TanStack Router を使った React、Vue、Angular、SvelteKit、Solid など、クライアントサイドルーティングを使う多くのフロントエンドアプリで望まれる動作です。 + +## カスタム 404 ページ { #custom-404-page } + +存在しないフロントエンドパスに対して、静的な `404.html` ページを配信することもできます。 + +{* ../../docs_src/frontend/tutorial003_py310.py hl[5] *} + +そのレスポンスはステータスコード `404` を保持します。 + +この場合、**FastAPI** は存在しないフロントエンドパスに対して `index.html` を配信しません。代わりに `404.html` ファイルを返します。 + +/// tip | 豆知識 + +デフォルトでは、`fallback` の値は `fallback="auto"` です。これにより、`404.html` ファイルが見つかった場合、自動的にフォールバックとして使われます。 + +そのため、通常は `fallback` 引数を省略できます。 + +/// + +これは、Astro のように各ページの静的 HTML ファイルを生成するフロントエンドツールで役立ちます。 + +## 自動フォールバック { #fallback-auto } + +デフォルトでは、`app.frontend()` は `fallback="auto"` を使います。 + +フロントエンドディレクトリに `404.html` ファイルがある場合、存在しないフロントエンドパスはそのファイルをステータスコード `404` で配信します。 + +そうでない場合、`index.html` ファイルがあれば、存在しないブラウザナビゲーションのパスは `index.html` を配信します。これは、クライアントサイドルーティングを使う多くのフロントエンドアプリが期待する動作です。 + +そのため、ほとんどの場合、`fallback` 引数を指定せずに `app.frontend("/", directory="dist")` を使用できます。 + +{* ../../docs_src/frontend/tutorial001_py310.py hl[5] *} + +## フォールバックの無効化 { #disable-fallback } + +存在しないフロントエンドパスに対してフォールバックファイルを配信したくない場合は、`fallback=None` を使います。 + +{* ../../docs_src/frontend/tutorial005_py310.py hl[5] *} + +すると、存在しないフロントエンドパスは通常の `404` を返します。 + +## ディレクトリのチェック { #check-directory } + +デフォルトでは、`app.frontend()` はアプリ作成時にディレクトリが存在することをチェックします。 + +これにより、設定エラーを早期に検出できます。たとえば、フロントエンドのビルド出力ディレクトリが存在しない場合、**FastAPI** は起動時にエラーを発生させます。 + +アプリオブジェクトの作成後に別のビルドステップなどでフロントエンドファイルが作成される場合は、`check_dir=False` を設定します。 + +{* ../../docs_src/frontend/tutorial006_py310.py hl[5] *} + +`check_dir=False` を指定すると、**FastAPI** はアプリ作成時にディレクトリをチェックしません。リクエストが処理される時点で設定されたディレクトリがまだ存在しない場合、**FastAPI** はその時点でエラーを発生させます。 + +## `APIRouter` での使用 { #use-it-with-apirouter } + +フロントエンドファイルを `APIRouter` に追加し、prefix 付きで include することもできます。 + +{* ../../docs_src/frontend/tutorial004_py310.py hl[6,7] *} + +この例では、フロントエンドのパスは `/app` 配下で配信されます。 + +他の router 内のものを含め、アプリ内の通常の *path operations* は引き続き優先されます。 + +## 静的ビルド出力のみ { #static-build-output-only } + +`app.frontend()` は、フロントエンドのビルドで既に生成されたファイルを配信します。 + +server-side rendering は実行しません。これは静的ファイルを生成するフロントエンドフレームワーク向けであり、各リクエストごとにサーバー上で動的レンダリングを必要とするフレームワーク向けではありません。 diff --git a/docs/ja/docs/tutorial/handling-errors.md b/docs/ja/docs/tutorial/handling-errors.md index 8d0190cb0..491b72da2 100644 --- a/docs/ja/docs/tutorial/handling-errors.md +++ b/docs/ja/docs/tutorial/handling-errors.md @@ -1,5 +1,6 @@ # エラーハンドリング { #handling-errors } + APIを使用しているクライアントにエラーを通知する必要がある状況はたくさんあります。 このクライアントは、フロントエンドを持つブラウザ、誰かのコード、IoTデバイスなどが考えられます。 diff --git a/docs/ja/docs/tutorial/index.md b/docs/ja/docs/tutorial/index.md index 8182c92ae..42b0eb523 100644 --- a/docs/ja/docs/tutorial/index.md +++ b/docs/ja/docs/tutorial/index.md @@ -1,5 +1,6 @@ # チュートリアル - ユーザーガイド { #tutorial-user-guide } + このチュートリアルでは、**FastAPI**のほとんどの機能を使う方法を段階的に紹介します。 各セクションは前のセクションを踏まえた内容になっています。しかし、トピックごとに分割されているので、特定のAPIのニーズを満たすために、任意の特定のトピックに直接進めるようになっています。 diff --git a/docs/ja/docs/tutorial/metadata.md b/docs/ja/docs/tutorial/metadata.md index 6802e6c9a..0f5f0cb6c 100644 --- a/docs/ja/docs/tutorial/metadata.md +++ b/docs/ja/docs/tutorial/metadata.md @@ -11,10 +11,10 @@ OpenAPI仕様および自動APIドキュメントUIで使用される次のフ | `title` | `str` | APIのタイトルです。 | | `summary` | `str` | APIの短い要約です。 OpenAPI 3.1.0、FastAPI 0.99.0 以降で利用できます。 | | `description` | `str` | APIの短い説明です。Markdownを使用できます。 | -| `version` | `string` | APIのバージョンです。これはOpenAPIのバージョンではなく、あなた自身のアプリケーションのバージョンです。たとえば `2.5.0` です。 | +| `version` | `str` | APIのバージョンです。これはOpenAPIのバージョンではなく、あなた自身のアプリケーションのバージョンです。たとえば `2.5.0` です。 | | `terms_of_service` | `str` | APIの利用規約へのURLです。指定する場合、URLである必要があります。 | -| `contact` | `dict` | 公開されるAPIの連絡先情報です。複数のフィールドを含められます。
contact fields
ParameterTypeDescription
namestr連絡先の個人/組織を識別する名前です。
urlstr連絡先情報を指すURLです。URL形式である必要があります。
emailstr連絡先の個人/組織のメールアドレスです。メールアドレス形式である必要があります。
| -| `license_info` | `dict` | 公開されるAPIのライセンス情報です。複数のフィールドを含められます。
license_info fields
ParameterTypeDescription
namestr必須license_info が設定されている場合)。APIに使用されるライセンス名です。
identifierstrAPIの [SPDX](https://spdx.org/licenses/) ライセンス式です。identifier フィールドは url フィールドと同時に指定できません。 OpenAPI 3.1.0、FastAPI 0.99.0 以降で利用できます。
urlstrAPIに使用されるライセンスへのURLです。URL形式である必要があります。
| +| `contact` | `dict` | 公開されるAPIの連絡先情報です。複数のフィールドを含められます。
contact のフィールド
パラメータ説明
namestr連絡先の個人/組織を識別する名前です。
urlstr連絡先情報を指すURLです。URL形式である必要があります。
emailstr連絡先の個人/組織のメールアドレスです。メールアドレス形式である必要があります。
| +| `license_info` | `dict` | 公開されるAPIのライセンス情報です。複数のフィールドを含められます。
license_info のフィールド
パラメータ説明
namestr必須license_info が設定されている場合)。APIに使用されるライセンス名です。
identifierstrAPIの [SPDX](https://spdx.org/licenses/) ライセンス式です。identifier フィールドは url フィールドと同時に指定できません。 OpenAPI 3.1.0、FastAPI 0.99.0 以降で利用できます。
urlstrAPIに使用されるライセンスへのURLです。URL形式である必要があります。
| 以下のように設定できます: @@ -74,7 +74,7 @@ OpenAPI 3.1.0 および FastAPI 0.99.0 以降では、`license_info` を `url` {* ../../docs_src/metadata/tutorial004_py310.py hl[21,26] *} -/// info | 情報 +/// note | 備考 タグの詳細は [Path Operation の設定](path-operation-configuration.md#tags) を参照してください。 diff --git a/docs/ja/docs/tutorial/path-operation-configuration.md b/docs/ja/docs/tutorial/path-operation-configuration.md index 25a2783ea..05bf9208e 100644 --- a/docs/ja/docs/tutorial/path-operation-configuration.md +++ b/docs/ja/docs/tutorial/path-operation-configuration.md @@ -1,5 +1,6 @@ # Path Operationの設定 { #path-operation-configuration } + *path operationデコレータ*を設定するためのパラメータがいくつかあります。 /// warning | 注意 @@ -72,13 +73,13 @@ docstringに[Markdown](https://en.wikipedia.org/wiki/Markdown)を記述すれば {* ../../docs_src/path_operation_configuration/tutorial005_py310.py hl[18] *} -/// info | 情報 +/// note | 備考 `response_description`は具体的にレスポンスを参照し、`description`は*path operation*全般を参照していることに注意してください。 /// -/// check | 確認 +/// tip | 豆知識 OpenAPIは*path operation*ごとにレスポンスの説明を必要としています。 diff --git a/docs/ja/docs/tutorial/path-params-numeric-validations.md b/docs/ja/docs/tutorial/path-params-numeric-validations.md index 55930eece..1e36e7dd1 100644 --- a/docs/ja/docs/tutorial/path-params-numeric-validations.md +++ b/docs/ja/docs/tutorial/path-params-numeric-validations.md @@ -8,7 +8,7 @@ {* ../../docs_src/path_params_numeric_validations/tutorial001_an_py310.py hl[1,3] *} -/// info | 情報 +/// note | 備考 FastAPI はバージョン 0.95.0 で`Annotated`のサポートを追加し(そして推奨し始めました)。 @@ -131,7 +131,7 @@ Pythonはその`*`で何かをすることはありませんが、それ以降 * `lt`: `l`ess `t`han * `le`: `l`ess than or `e`qual -/// info | 情報 +/// note | 備考 `Query`、`Path`、および後で見る他のクラスは、共通の`Param`クラスのサブクラスです。 diff --git a/docs/ja/docs/tutorial/path-params.md b/docs/ja/docs/tutorial/path-params.md index 8556b1c37..ec47cbe7a 100644 --- a/docs/ja/docs/tutorial/path-params.md +++ b/docs/ja/docs/tutorial/path-params.md @@ -20,7 +20,7 @@ Pythonのformat文字列と同様のシンタックスで「パスパラメー ここでは、 `item_id` は `int` として宣言されています。 -/// check | 確認 +/// tip | 豆知識 これにより、関数内でのエディターサポート (エラーチェックや補完など) が提供されます。 @@ -34,7 +34,7 @@ Pythonのformat文字列と同様のシンタックスで「パスパラメー {"item_id":3} ``` -/// check | 確認 +/// tip | 豆知識 関数が受け取った(および返した)値は、文字列の `"3"` ではなく、Pythonの `int` としての `3` であることに注意してください。 @@ -66,7 +66,7 @@ Pythonのformat文字列と同様のシンタックスで「パスパラメー [http://127.0.0.1:8000/items/4.2](http://127.0.0.1:8000/items/4.2) で見られるように、`int` のかわりに `float` が与えられた場合にも同様なエラーが表示されます。 -/// check | 確認 +/// tip | 豆知識 したがって、同じPythonの型宣言を使用することで、**FastAPI**はデータのバリデーションを行います。 @@ -82,7 +82,7 @@ Pythonのformat文字列と同様のシンタックスで「パスパラメー -/// check | 確認 +/// tip | 豆知識 繰り返しになりますが、同じPython型宣言を使用するだけで、**FastAPI**は対話的なドキュメントを自動的に生成します(Swagger UIを統合)。 diff --git a/docs/ja/docs/tutorial/query-params-str-validations.md b/docs/ja/docs/tutorial/query-params-str-validations.md index d34059801..38d2b5c68 100644 --- a/docs/ja/docs/tutorial/query-params-str-validations.md +++ b/docs/ja/docs/tutorial/query-params-str-validations.md @@ -24,12 +24,12 @@ FastAPIは、 `q` はデフォルト値が `= None` であるため、必須で そのために、まずは以下をインポートします: -* `fastapi` から `Query` -* `typing` から `Annotated` +- `fastapi` から `Query` +- `typing` から `Annotated` {* ../../docs_src/query_params_str_validations/tutorial002_an_py310.py hl[1,3] *} -/// info | 情報 +/// note | 備考 FastAPI はバージョン 0.95.0 で `Annotated` のサポートを追加し(推奨し始め)ました。 @@ -41,7 +41,7 @@ FastAPI はバージョン 0.95.0 で `Annotated` のサポートを追加し( ## `q` パラメータの型で `Annotated` を使う { #use-annotated-in-the-type-for-the-q-parameter } -以前、[Python Types Intro](../python-types.md#type-hints-with-metadata-annotations) で `Annotated` を使ってパラメータにメタデータを追加できると説明したことを覚えていますか? +以前、[Python 型入門](../python-types.md#type-hints-with-metadata-annotations) で `Annotated` を使ってパラメータにメタデータを追加できると説明したことを覚えていますか? いよいよ FastAPI で使うときです。 🚀 @@ -79,9 +79,9 @@ q: Annotated[str | None] = None FastAPI は次を行います: -* 最大長が 50 文字であることを確かめるようデータを **検証** する -* データが有効でないときに、クライアントに **明確なエラー** を表示する -* OpenAPI スキーマの *path operation* にパラメータを **ドキュメント化** する(その結果、**自動ドキュメント UI** に表示されます) +- 最大長が 50 文字であることを確かめるようデータを **検証** する +- データが有効でないときに、クライアントに **明確なエラー** を表示する +- OpenAPI スキーマの *path operation* にパラメータを **ドキュメント化** する(その結果、**自動ドキュメント UI** に表示されます) ## 代替(古い方法): デフォルト値としての `Query` { #alternative-old-query-as-the-default-value } @@ -174,9 +174,9 @@ FastAPI なしで同じ関数を **別の場所** から **呼び出しても** この特定の正規表現パターンは受け取ったパラメータの値をチェックします: -* `^`: は、これ以降の文字で始まり、これより以前には文字はありません。 -* `fixedquery`: は、正確な`fixedquery`を持っています. -* `$`: で終わる場合、`fixedquery`以降には文字はありません. +- `^`: は、これ以降の文字で始まり、これより以前には文字はありません。 +- `fixedquery`: は、正確な`fixedquery`を持っています. +- `$`: で終わる場合、`fixedquery`以降には文字はありません. もしこれらすべての **「正規表現」** のアイデアについて迷っていても、心配しないでください。多くの人にとって難しい話題です。正規表現を必要としなくても、まだ、多くのことができます。 @@ -242,7 +242,7 @@ q: Annotated[str | None, Query(min_length=3)] = None http://localhost:8000/items/?q=foo&q=bar ``` -*path operation function* 内の *function parameter* `q` で、複数の `q` *query parameters'* 値(`foo` と `bar`)を Python の `list` として受け取ります。 +*path operation function* 内の *function parameter* `q` で、複数の `q` *クエリパラメータ*の値(`foo` と `bar`)を Python の `list` として受け取ります。 そのため、このURLのレスポンスは以下のようになります: @@ -382,7 +382,7 @@ Pydantic には [`BeforeValidator`](https://docs.pydantic.dev/latest/concepts/va {* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py hl[5,16:19,24] *} -/// info | 情報 +/// note | 備考 これは Pydantic バージョン 2 以上で利用できます。 😎 @@ -432,16 +432,16 @@ Pydantic には [`BeforeValidator`](https://docs.pydantic.dev/latest/concepts/va 一般的なバリデーションとメタデータ: -* `alias` -* `title` -* `description` -* `deprecated` +- `alias` +- `title` +- `description` +- `deprecated` 文字列に固有のバリデーション: -* `min_length` -* `max_length` -* `pattern` +- `min_length` +- `max_length` +- `pattern` `AfterValidator` を使ったカスタムバリデーション。 diff --git a/docs/ja/docs/tutorial/query-params.md b/docs/ja/docs/tutorial/query-params.md index 51e4eb944..2bca43a95 100644 --- a/docs/ja/docs/tutorial/query-params.md +++ b/docs/ja/docs/tutorial/query-params.md @@ -1,5 +1,6 @@ # クエリパラメータ { #query-parameters } + パスパラメータではない関数パラメータを宣言すると、それらは自動的に「クエリ」パラメータとして解釈されます。 {* ../../docs_src/query_params/tutorial001_py310.py hl[9] *} @@ -65,7 +66,7 @@ http://127.0.0.1:8000/items/?skip=20 この場合、関数パラメータ `q` はオプショナルとなり、デフォルトでは `None` になります。 -/// check | 確認 +/// tip | 豆知識 パスパラメータ `item_id` はパスパラメータであり、`q` はそれとは違ってクエリパラメータであると判別できるほど**FastAPI** が賢いということにも注意してください。 diff --git a/docs/ja/docs/tutorial/request-files.md b/docs/ja/docs/tutorial/request-files.md index 30a494afb..f4bd2314b 100644 --- a/docs/ja/docs/tutorial/request-files.md +++ b/docs/ja/docs/tutorial/request-files.md @@ -1,8 +1,9 @@ # リクエストファイル { #request-files } + `File` を使って、クライアントがアップロードするファイルを定義できます。 -/// info | 情報 +/// note | 備考 アップロードされたファイルを受け取るには、まず [`python-multipart`](https://github.com/Kludex/python-multipart) をインストールします。 @@ -28,7 +29,7 @@ $ pip install python-multipart {* ../../docs_src/request_files/tutorial001_an_py310.py hl[9] *} -/// info | 情報 +/// note | 備考 `File` は `Form` を直接継承したクラスです。 diff --git a/docs/ja/docs/tutorial/request-form-models.md b/docs/ja/docs/tutorial/request-form-models.md index 62aa9e298..6a71c149d 100644 --- a/docs/ja/docs/tutorial/request-form-models.md +++ b/docs/ja/docs/tutorial/request-form-models.md @@ -2,7 +2,7 @@ FastAPI では、フォームフィールドを宣言するために **Pydantic モデル**を使用できます。 -/// info | 情報 +/// note | 備考 フォームを使うには、まず [`python-multipart`](https://github.com/Kludex/python-multipart) をインストールします。 diff --git a/docs/ja/docs/tutorial/request-forms-and-files.md b/docs/ja/docs/tutorial/request-forms-and-files.md index 651f07ff0..4865f29ae 100644 --- a/docs/ja/docs/tutorial/request-forms-and-files.md +++ b/docs/ja/docs/tutorial/request-forms-and-files.md @@ -2,7 +2,7 @@ `File`と`Form`を同時に使うことでファイルとフォームフィールドを定義することができます。 -/// info | 情報 +/// note | 備考 アップロードされたファイルやフォームデータを受信するには、まず[`python-multipart`](https://github.com/Kludex/python-multipart)をインストールします。 diff --git a/docs/ja/docs/tutorial/request-forms.md b/docs/ja/docs/tutorial/request-forms.md index c6b2a921a..0478a5439 100644 --- a/docs/ja/docs/tutorial/request-forms.md +++ b/docs/ja/docs/tutorial/request-forms.md @@ -2,7 +2,7 @@ JSONの代わりにフィールドを受け取る場合は、`Form`を使用します。 -/// info | 情報 +/// note | 備考 フォームを使うためには、まず[`python-multipart`](https://github.com/Kludex/python-multipart)をインストールします。 @@ -32,7 +32,7 @@ $ pip install python-multipart `Form`では`Body`(および`Query`や`Path`、`Cookie`)と同じ設定を宣言することができます。これには、バリデーション、例、エイリアス(例えば`username`の代わりに`user-name`)などが含まれます。 -/// info | 情報 +/// note | 備考 `Form`は`Body`を直接継承するクラスです。 @@ -56,7 +56,7 @@ HTMLフォーム(`
`)がサーバにデータを送信する方 しかし、フォームがファイルを含む場合は、`multipart/form-data`としてエンコードされます。ファイルの扱いについては次の章で説明します。 -これらのエンコーディングやフォームフィールドの詳細については、[MDN の `POST` ウェブドキュメント](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST)を参照してください。 +これらのエンコーディングやフォームフィールドの詳細については、[MDN の `POST` のウェブドキュメント](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST)を参照してください。 /// @@ -70,4 +70,4 @@ HTMLフォーム(`
`)がサーバにデータを送信する方 ## まとめ { #recap } -フォームデータの入力パラメータを宣言するには、`Form`を使用する。 +フォームデータの入力パラメータを宣言するには、`Form`を使用します。 diff --git a/docs/ja/docs/tutorial/response-model.md b/docs/ja/docs/tutorial/response-model.md index b4024e0a0..4b38e6de9 100644 --- a/docs/ja/docs/tutorial/response-model.md +++ b/docs/ja/docs/tutorial/response-model.md @@ -72,7 +72,7 @@ FastAPIはこの `response_model` を使って、データのドキュメント {* ../../docs_src/response_model/tutorial002_py310.py hl[7,9] *} -/// info | 情報 +/// note | 備考 `EmailStr` を使用するには、最初に [`email-validator`](https://github.com/JoshData/python-email-validator) をインストールしてください。 @@ -251,7 +251,7 @@ Pydanticフィールドとして有効ではないものを返し、ツール( } ``` -/// info | 情報 +/// note | 備考 以下も使用できます: diff --git a/docs/ja/docs/tutorial/response-status-code.md b/docs/ja/docs/tutorial/response-status-code.md index 9237ac784..e4239e11a 100644 --- a/docs/ja/docs/tutorial/response-status-code.md +++ b/docs/ja/docs/tutorial/response-status-code.md @@ -1,5 +1,6 @@ # レスポンスステータスコード { #response-status-code } + レスポンスモデルを指定するのと同じ方法で、レスポンスに使用されるHTTPステータスコードを以下の*path operations*のいずれかの`status_code`パラメータで宣言することもできます。 * `@app.get()` @@ -18,7 +19,7 @@ `status_code`パラメータはHTTPステータスコードを含む数値を受け取ります。 -/// info | 情報 +/// note | 備考 `status_code`は代わりに、Pythonの[`http.HTTPStatus`](https://docs.python.org/3/library/http.html#http.HTTPStatus)のように、`IntEnum`を受け取ることもできます。 diff --git a/docs/ja/docs/tutorial/schema-extra-example.md b/docs/ja/docs/tutorial/schema-extra-example.md index 87ee85f40..e44e2471d 100644 --- a/docs/ja/docs/tutorial/schema-extra-example.md +++ b/docs/ja/docs/tutorial/schema-extra-example.md @@ -1,5 +1,6 @@ # リクエストのExampleデータの宣言 { #declare-request-example-data } + アプリが受け取れるデータの例を宣言できます。 ここでは、それを行ういくつかの方法を紹介します。 @@ -24,7 +25,7 @@ /// -/// info | 情報 +/// note | 備考 OpenAPI 3.1.0(FastAPI 0.99.0以降で使用)では、**JSON Schema**標準の一部である`examples`がサポートされました。 @@ -155,7 +156,7 @@ OpenAPIは、仕様の他の部分にも`example`と`examples`フィールドを * `File()` * `Form()` -/// info | 情報 +/// note | 備考 この古いOpenAPI固有の`examples`パラメータは、FastAPI `0.103.0`以降は`openapi_examples`になりました。 @@ -171,7 +172,7 @@ OpenAPIは、仕様の他の部分にも`example`と`examples`フィールドを JSON Schemaのこの新しい`examples`フィールドは、OpenAPIの他の場所(上で説明)にあるような追加メタデータを持つdictではなく、**単なる例の`list`**です。 -/// info | 情報 +/// note | 備考 OpenAPI 3.1.0がこのJSON Schemaとの新しいよりシンプルな統合とともにリリースされた後も、しばらくの間、自動ドキュメントを提供するツールであるSwagger UIはOpenAPI 3.1.0をサポートしていませんでした(バージョン5.0.0からサポートされています🎉)。 diff --git a/docs/ja/docs/tutorial/security/first-steps.md b/docs/ja/docs/tutorial/security/first-steps.md index e678ebce1..e5d7c58b5 100644 --- a/docs/ja/docs/tutorial/security/first-steps.md +++ b/docs/ja/docs/tutorial/security/first-steps.md @@ -24,7 +24,7 @@ ## 実行 { #run-it } -/// info | 情報 +/// note | 備考 [`python-multipart`](https://github.com/Kludex/python-multipart) パッケージは、`pip install "fastapi[standard]"` コマンドを実行すると **FastAPI** と一緒に自動的にインストールされます。 @@ -60,7 +60,7 @@ $ fastapi dev -/// check | Authorizeボタン! +/// tip | Authorizeボタン! すでにピカピカの新しい「Authorize」ボタンがあります。 @@ -109,7 +109,7 @@ OAuth2は、バックエンドやAPIがユーザーを認証するサーバー * ユーザーがフロントエンドでクリックして、フロントエンドのWebアプリの別のセクションに移動します。 * フロントエンドはAPIからさらにデータを取得する必要があります。 * しかし、特定のエンドポイントの認証が必要です。 - * したがって、APIで認証するため、HTTPヘッダー`Authorization`に`Bearer`の文字列とトークンを加えた値を送信します。 + * したがって、APIで認証するため、HTTPヘッダー`Authorization`に`Bearer `の文字列とトークンを加えた値を送信します。 * トークンに`foobar`が含まれている場合、`Authorization`ヘッダーの内容は次のようになります: `Bearer foobar`。 ## **FastAPI**の`OAuth2PasswordBearer` { #fastapis-oauth2passwordbearer } @@ -118,7 +118,7 @@ OAuth2は、バックエンドやAPIがユーザーを認証するサーバー この例では、**Bearer**トークンを使用して**OAuth2**を**Password**フローで使用します。これには`OAuth2PasswordBearer`クラスを使用します。 -/// info | 情報 +/// note | 備考 「bearer」トークンが、唯一の選択肢ではありません。 @@ -148,7 +148,7 @@ OAuth2は、バックエンドやAPIがユーザーを認証するサーバー 実際の path operation もすぐに作ります。 -/// info | 情報 +/// note | 備考 非常に厳格な「Pythonista」であれば、パラメーター名のスタイルが`tokenUrl`ではなく`token_url`であることを気に入らないかもしれません。 @@ -176,9 +176,9 @@ oauth2_scheme(some, parameters) **FastAPI**は、この依存関係を使用してOpenAPIスキーマ (および自動APIドキュメント) で「セキュリティスキーム」を定義できることを知っています。 -/// info | 技術詳細 +/// note | 技術詳細 -**FastAPI**は、`OAuth2PasswordBearer` クラス (依存関係で宣言されている) を使用してOpenAPIのセキュリティスキームを定義できることを知っています。これは`fastapi.security.oauth2.OAuth2`、`fastapi.security.base.SecurityBase`を継承しているからです。 +**FastAPI**は、`OAuth2PasswordBearer` クラス (依存関係で宣言されている) を使用してOpenAPIのセキュリティスキームを定義できることを知っています。これは、このクラスが`fastapi.security.oauth2.OAuth2`を継承しており、さらにそれが`fastapi.security.base.SecurityBase`を継承しているからです。 OpenAPIと統合するセキュリティユーティリティ (および自動APIドキュメント) はすべて`SecurityBase`を継承しています。それにより、**FastAPI**はそれらをOpenAPIに統合する方法を知ることができます。 diff --git a/docs/ja/docs/tutorial/security/get-current-user.md b/docs/ja/docs/tutorial/security/get-current-user.md index 60378fd98..f8e4295bf 100644 --- a/docs/ja/docs/tutorial/security/get-current-user.md +++ b/docs/ja/docs/tutorial/security/get-current-user.md @@ -14,7 +14,7 @@ ボディを宣言するのにPydanticを使用するのと同じやり方で、Pydanticを別のどんなところでも使うことができます: -{* ../../docs_src/security/tutorial002_an_py310.py hl[5,12:6] *} +{* ../../docs_src/security/tutorial002_an_py310.py hl[5,12:16] *} ## 依存関係 `get_current_user` を作成 { #create-a-get-current-user-dependency } @@ -52,7 +52,7 @@ Pydanticモデルの `User` として、 `current_user` の型を宣言するこ /// -/// check | 確認 +/// tip | 豆知識 依存関係システムがこのように設計されているおかげで、 `User` モデルを返却する別の依存関係(別の「dependables」)を持つことができます。 diff --git a/docs/ja/docs/tutorial/security/oauth2-jwt.md b/docs/ja/docs/tutorial/security/oauth2-jwt.md index 9c527121e..40cefad9d 100644 --- a/docs/ja/docs/tutorial/security/oauth2-jwt.md +++ b/docs/ja/docs/tutorial/security/oauth2-jwt.md @@ -1,6 +1,6 @@ # パスワード(およびハッシュ化)によるOAuth2、JWTトークンによるBearer { #oauth2-with-password-and-hashing-bearer-with-jwt-tokens } -これでセキュリティの流れが全てわかったので、JWTトークンと安全なパスワードのハッシュ化を使用して、実際にアプリケーションを安全にしてみましょう。 +これでセキュリティの流れが全てわかったので、JWTトークンと安全なパスワードのハッシュ化を使用して、実際にアプリケーションを安全にしてみましょう。 このコードは、アプリケーションで実際に使用したり、パスワードハッシュをデータベースに保存するといった用途に利用できます。 @@ -42,11 +42,11 @@ $ pip install pyjwt
-/// info | 情報 +/// note | 備考 RSAやECDSAのようなデジタル署名アルゴリズムを使用する予定がある場合は、cryptographyライブラリの依存関係`pyjwt[crypto]`をインストールしてください。 -詳細は[PyJWT Installation docs](https://pyjwt.readthedocs.io/en/latest/installation.html)で確認できます。 +詳細は[PyJWT インストールに関するドキュメント](https://pyjwt.readthedocs.io/en/latest/installation.html)で確認できます。 /// @@ -120,7 +120,7 @@ pwdlibはbcryptハッシュアルゴリズムもサポートしていますが `authenticate_user` がデータベースに存在しないユーザー名で呼び出された場合でも、ダミーのハッシュを使って `verify_password` を実行します。 -これにより、ユーザー名が有効かどうかに関わらずエンドポイントの応答時間がおおよそ同じになり、既存のユーザー名を列挙するために悪用されうる「タイミング攻撃」を防止できます。 +これにより、ユーザー名が有効かどうかに関わらずエンドポイントの応答時間がおおよそ同じになり、既存のユーザー名を列挙するために悪用されうる**タイミング攻撃**を防止できます。 /// note | 備考 @@ -213,9 +213,9 @@ IDの衝突を回避するために、ユーザーのJWTトークンを作成す Username: `johndoe` Password: `secret` -/// check | 確認 +/// tip | 豆知識 -コードのどこにも平文のパスワード"`secret`"はなく、ハッシュ化されたものしかないことを確認してください。 +コードのどこにも平文のパスワード「`secret`」はなく、ハッシュ化されたものしかないことを確認してください。 /// diff --git a/docs/ja/docs/tutorial/security/simple-oauth2.md b/docs/ja/docs/tutorial/security/simple-oauth2.md index 842cd02e5..84f6101b7 100644 --- a/docs/ja/docs/tutorial/security/simple-oauth2.md +++ b/docs/ja/docs/tutorial/security/simple-oauth2.md @@ -14,7 +14,7 @@ OAuth2 では、「password flow」(ここで使用するフロー)を使う また、データベースのモデルでは任意の別名を使って構いません。 -しかし、ログイン用の path operation では、仕様との互換性を保つ(たとえば組み込みのAPIドキュメントシステムを使えるようにする)ために、これらの名前を使う必要があります。 +しかし、ログイン用の *path operation* では、仕様との互換性を保つ(たとえば組み込みのAPIドキュメントシステムを使えるようにする)ために、これらの名前を使う必要があります。 また、仕様では `username` と `password` はフォームデータとして送らなければならない(つまり、ここではJSONは使わない)ことも定められています。 @@ -32,7 +32,7 @@ OAuth2 では、「password flow」(ここで使用するフロー)を使う - `instagram_basic` は Facebook / Instagram で使われます。 - `https://www.googleapis.com/auth/drive` は Google で使われます。 -/// info | 情報 +/// note | 備考 OAuth2 における「スコープ」は、要求される特定の権限を表す単なる文字列です。 @@ -50,7 +50,7 @@ OAuth2 にとっては単なる文字列です。 ### `OAuth2PasswordRequestForm` { #oauth2passwordrequestform } -まず、`OAuth2PasswordRequestForm` をインポートし、`/token` の path operation に `Depends` で依存関係として使います: +まず、`OAuth2PasswordRequestForm` をインポートし、`/token` の *path operation* に `Depends` で依存関係として使います: {* ../../docs_src/security/tutorial003_an_py310.py hl[4,78] *} @@ -72,7 +72,7 @@ OAuth2 の仕様では、固定値 `password` を持つフィールド `grant_ty - オプションの `client_id`(この例では不要) - オプションの `client_secret`(この例では不要) -/// info | 情報 +/// note | 備考 `OAuth2PasswordRequestForm` は、`OAuth2PasswordBearer` のように **FastAPI** にとって特別なクラスではありません。 @@ -132,7 +132,7 @@ OAuth2 の仕様では、固定値 `password` を持つフィールド `grant_ty `UserInDB(**user_dict)` は次を意味します: -`user_dict` のキーと値を、そのままキーワード引数として渡します。つまり次と同等です: +*`user_dict` のキーと値を、そのままキーワード引数として渡します。つまり次と同等です:* ```Python UserInDB( @@ -144,9 +144,9 @@ UserInDB( ) ``` -/// info | 情報 +/// note | 備考 -`**user_dict` のより完全な解説は、[**追加モデル**のドキュメント](../extra-models.md#about-user-in-dict)を参照してください。 +`**user_dict` のより完全な解説は、[**追加モデル**のドキュメント](../extra-models.md#about-user-in-model-dump)を参照してください。 /// @@ -188,7 +188,7 @@ UserInDB( アクティブなユーザーの場合にのみ `current_user` を取得したいとします。 -そこで、`get_current_active_user` を依存関係として利用する追加の依存関係 `get_current_active_user` を作成します。 +そこで、今度は `get_current_user` を依存関係として利用する追加の依存関係 `get_current_active_user` を作成します。 これら2つの依存関係は、ユーザーが存在しない、または非アクティブである場合に、HTTPエラーを返すだけです。 @@ -196,7 +196,7 @@ UserInDB( {* ../../docs_src/security/tutorial003_an_py310.py hl[58:66,69:74,94] *} -/// info | 情報 +/// note | 備考 ここで返している値が `Bearer` の追加ヘッダー `WWW-Authenticate` も仕様の一部です。 @@ -236,7 +236,7 @@ Password: `secret` ### 自分のユーザーデータを取得 { #get-your-own-user-data } -`GET` の path `/users/me` を使います。 +今度は path `/users/me` で operation `GET` を使います。 次のようなユーザーデータが取得できます: @@ -268,7 +268,7 @@ User: `alice` Password: `secret2` -そして `GET` の path `/users/me` を使います。 +そして path `/users/me` で operation `GET` を使ってみます。 次のような「Inactive user」エラーになります: @@ -284,6 +284,6 @@ Password: `secret2` これらの道具を使えば、任意のデータベース、任意のユーザー/データモデルと互換性のあるセキュリティシステムを構築できます。 -ただし、実際にはまだ「安全」ではありません。 +唯一欠けている点は、実際にはまだ「安全」ではないことです。 次の章では、安全なパスワードハッシュライブラリと JWT トークンの使い方を見ていきます。 diff --git a/docs/ja/docs/tutorial/server-sent-events.md b/docs/ja/docs/tutorial/server-sent-events.md index d8168cef3..1019f806e 100644 --- a/docs/ja/docs/tutorial/server-sent-events.md +++ b/docs/ja/docs/tutorial/server-sent-events.md @@ -4,7 +4,7 @@ これは[JSON Lines のストリーミング](stream-json-lines.md)に似ていますが、`text/event-stream` フォーマットを使用します。これはブラウザがネイティブに [`EventSource` API](https://developer.mozilla.org/en-US/docs/Web/API/EventSource) でサポートしています。 -/// info | 情報 +/// note FastAPI 0.135.0 で追加されました。 @@ -27,7 +27,7 @@ data: {"name": "Plumbus", "price": 32.99} SSE は、AI チャットのストリーミング、ライブ通知、ログやオブザビリティなど、サーバーがクライアントへ更新をプッシュする用途で一般的に使われます。 -/// tip | 豆知識 +/// tip バイナリデータ(例: 動画や音声)をストリーミングしたい場合は、上級ガイド [データのストリーミング](../advanced/stream-data.md) を参照してください。 @@ -47,7 +47,7 @@ yield された各アイテムは JSON にエンコードされ、SSE イベン {* ../../docs_src/server_sent_events/tutorial001_py310.py ln[1:25] hl[10:12,23] *} -/// tip | 豆知識 +/// tip Pydantic が**Rust** 側でシリアライズを行うため、戻り値の型を宣言しない場合に比べて大幅に**高性能**になります。 @@ -81,13 +81,13 @@ Pydantic が**Rust** 側でシリアライズを行うため、戻り値の型 ## 生データ { #raw-data } -JSON エンコードせずにデータを送る必要がある場合は、`data` の代わりに `raw_data` を使用します。 +JSON エンコードせずにデータを送る必要がある場合は、`raw_data` を使用します。 -これは、整形済みテキスト、ログ行、または `[DONE]` のような特別な "センチネル" 値を送るのに有用です。 +これは、整形済みテキスト、ログ行、または 「センチネル」 といった特別な値(例: `[DONE]`)を送るのに有用です。 {* ../../docs_src/server_sent_events/tutorial003_py310.py hl[17] *} -/// note | 備考 +/// note `data` と `raw_data` は相互排他的です。各 `ServerSentEvent` ではどちらか一方しか設定できません。 diff --git a/docs/ja/docs/tutorial/sql-databases.md b/docs/ja/docs/tutorial/sql-databases.md index 13c71fdb2..190eedbbb 100644 --- a/docs/ja/docs/tutorial/sql-databases.md +++ b/docs/ja/docs/tutorial/sql-databases.md @@ -1,5 +1,6 @@ # SQL(リレーショナル)データベース { #sql-relational-databases } + FastAPI は SQL(リレーショナル)データベースの使用を必須にはしません。必要であれば、任意のデータベースを使用できます。 ここでは [SQLModel](https://sqlmodel.tiangolo.com/) を使った例を見ていきます。 diff --git a/docs/ja/docs/tutorial/static-files.md b/docs/ja/docs/tutorial/static-files.md index 81f281c2e..fd0d47e9c 100644 --- a/docs/ja/docs/tutorial/static-files.md +++ b/docs/ja/docs/tutorial/static-files.md @@ -2,6 +2,14 @@ `StaticFiles` を使用して、ディレクトリから静的ファイルを自動的に提供できます。 +/// tip | 豆知識 + +フロントエンドをホストする必要がある場合は、代わりに `app.frontend()` を使用してください。詳しくは [フロントエンド](frontend.md) を読んでください。 + +`app.frontend()` は内部で `StaticFiles` を使用しており、client-side routing の処理など、フロントエンド向けの追加の利点がいくつかあります。 + +/// + ## `StaticFiles` の使用 { #use-staticfiles } * `StaticFiles` をインポート。 diff --git a/docs/ja/docs/tutorial/stream-json-lines.md b/docs/ja/docs/tutorial/stream-json-lines.md index a247234e2..1f7af2f68 100644 --- a/docs/ja/docs/tutorial/stream-json-lines.md +++ b/docs/ja/docs/tutorial/stream-json-lines.md @@ -2,7 +2,7 @@ データのシーケンスを**「ストリーム」**で送りたい場合、**JSON Lines** を使って実現できます。 -/// info | 情報 +/// note | 備考 FastAPI 0.134.0 で追加されました。 @@ -48,7 +48,7 @@ sequenceDiagram これは JSON 配列(Python の list に相当)にとてもよく似ていますが、`[]` で囲まず、アイテム間の `,` もありません。その代わりに、**1 行に 1 つの JSON オブジェクト**で、改行文字で区切られます。 -/// info | 情報 +/// note | 備考 重要な点は、クライアントが前の行を消費している間に、アプリ側は次の行を順次生成して送れることです。 diff --git a/docs/ja/docs/tutorial/testing.md b/docs/ja/docs/tutorial/testing.md index 0277d73b7..e82fc261e 100644 --- a/docs/ja/docs/tutorial/testing.md +++ b/docs/ja/docs/tutorial/testing.md @@ -8,7 +8,7 @@ ## `TestClient` を使用 { #using-testclient } -/// info +/// note | 備考 `TestClient` を使用するには、まず [`httpx`](https://www.python-httpx.org) をインストールします。 @@ -22,7 +22,7 @@ $ pip install httpx `TestClient` をインポートします。 -`TestClient` を作成し、**FastAPI** に渡します。 +**FastAPI** アプリケーションを渡して `TestClient` を作成します。 `test_` から始まる名前の関数を作成します (これは `pytest` の標準的なコンベンションです)。 @@ -32,7 +32,7 @@ $ pip install httpx {* ../../docs_src/app_testing/tutorial001_py310.py hl[2,12,15:18] *} -/// tip +/// tip | 豆知識 テスト関数は `async def` ではなく、通常の `def` であることに注意してください。 @@ -50,9 +50,9 @@ $ pip install httpx /// -/// tip +/// tip | 豆知識 -FastAPIアプリケーションへのリクエストの送信とは別に、テストで `async` 関数 (非同期データベース関数など) を呼び出したい場合は、高度なチュートリアルの[Async Tests](../advanced/async-tests.md) を参照してください。 +FastAPIアプリケーションへのリクエストの送信とは別に、テストで `async` 関数 (非同期データベース関数など) を呼び出したい場合は、高度なチュートリアルの[非同期テスト](../advanced/async-tests.md) を参照してください。 /// @@ -64,7 +64,7 @@ FastAPIアプリケーションへのリクエストの送信とは別に、テ ### **FastAPI** アプリファイル { #fastapi-app-file } -[Bigger Applications](bigger-applications.md) で説明されている、次のようなファイル構成があるとします: +[大規模なアプリケーション](bigger-applications.md) で説明されている、次のようなファイル構成があるとします: ``` . @@ -113,7 +113,7 @@ FastAPIアプリケーションへのリクエストの送信とは別に、テ │   └── test_main.py ``` -ここで、**FastAPI** アプリがある `main.py` ファイルには、他の path operation があります。 +ここで、**FastAPI** アプリがある `main.py` ファイルには、他の **path operations** がいくつかあります。 エラーを返す可能性のある `GET` オペレーションがあります。 @@ -144,7 +144,7 @@ FastAPIアプリケーションへのリクエストの送信とは別に、テ (`httpx` または `TestClient` を使用して) バックエンドにデータを渡す方法の詳細は、[HTTPXのドキュメント](https://www.python-httpx.org)を確認してください。 -/// info +/// note | 備考 `TestClient` は、Pydanticモデルではなく、JSONに変換できるデータを受け取ることに注意してください。 diff --git a/docs/ja/docs/virtual-environments.md b/docs/ja/docs/virtual-environments.md index 633825b64..19325fa1d 100644 --- a/docs/ja/docs/virtual-environments.md +++ b/docs/ja/docs/virtual-environments.md @@ -35,15 +35,15 @@ Pythonプロジェクトの作業では、**仮想環境**(または類似の
```console -// Go to the home directory +// ホームディレクトリに移動 $ cd -// Create a directory for all your code projects +// すべてのコードプロジェクト用のディレクトリを作成 $ mkdir code -// Enter into that code directory +// その code ディレクトリに入る $ cd code -// Create a directory for this project +// このプロジェクト用のディレクトリを作成 $ mkdir awesome-project -// Enter into that project directory +// そのプロジェクトディレクトリに入る $ cd awesome-project ``` diff --git a/docs/ko/docs/_llm-test.md b/docs/ko/docs/_llm-test.md index ea22d6191..9e9d0ee73 100644 --- a/docs/ko/docs/_llm-test.md +++ b/docs/ko/docs/_llm-test.md @@ -7,11 +7,11 @@ 사용 방법은 다음과 같습니다: * 언어별 프롬프트 `docs/{language code}/llm-prompt.md`를 준비합니다. -* 이 문서를 원하는 대상 언어로 새로 번역합니다(예: `translate.py`의 `translate-page` 명령). 그러면 `docs/{language code}/docs/_llm-test.md` 아래에 번역이 생성됩니다. +* 이 문서를 원하는 대상 언어로 새로 번역합니다(예: `translate.py`의 `translate-page` 명령어). 그러면 `docs/{language code}/docs/_llm-test.md` 아래에 번역이 생성됩니다. * 번역에서 문제가 없는지 확인합니다. * 필요하다면 언어별 프롬프트, 일반 프롬프트, 또는 영어 문서를 개선합니다. * 그런 다음 번역에서 남아 있는 문제를 수동으로 수정해 좋은 번역이 되게 합니다. -* 좋은 번역을 둔 상태에서 다시 번역합니다. 이상적인 결과는 LLM이 더 이상 번역에 변경을 만들지 않는 것입니다. 이는 일반 프롬프트와 언어별 프롬프트가 가능한 한 최선이라는 뜻입니다(때때로 몇 가지 seemingly random 변경을 할 수 있는데, 그 이유는 [LLM은 결정론적 알고리즘이 아니기 때문](https://doublespeak.chat/#/handbook#deterministic-output)입니다). +* 좋은 번역을 둔 상태에서 다시 번역합니다. 이상적인 결과는 LLM이 더 이상 번역에 변경을 만들지 않는 것입니다. 이는 일반 프롬프트와 언어별 프롬프트가 가능한 한 최선이라는 뜻입니다(때때로 몇 가지 겉보기에 무작위인 변경을 할 수 있는데, 그 이유는 [LLM은 결정론적 알고리즘이 아니기 때문](https://doublespeak.chat/#/handbook#deterministic-output)입니다). 테스트: @@ -150,7 +150,7 @@ works(foo="bar") # 이건 동작합니다 🎉 탭과 `Info`/`Note`/`Warning`/등의 블록은 제목 번역을 수직 막대(`|`) 뒤에 추가해야 합니다. -`scripts/translate.py`의 일반 프롬프트에서 `### Special blocks`와 `### Tab blocks` 석션을 참고하세요. +`scripts/translate.py`의 일반 프롬프트에서 `### Special blocks`와 `### Tab blocks` 섹션을 참고하세요. //// @@ -240,7 +240,7 @@ works(foo="bar") # 이건 동작합니다 🎉 `scripts/translate.py`의 일반 프롬프트에서 `### Headings` 섹션을 참고하세요. -언어별 지침은 예를 들어 `docs/de/llm-prompt.md`의 `### Headings` 석션을 참고하세요. +언어별 지침은 예를 들어 `docs/de/llm-prompt.md`의 `### Headings` 섹션을 참고하세요. //// @@ -289,7 +289,7 @@ works(foo="bar") # 이건 동작합니다 🎉 * 애플리케이션을 서빙하다 * 페이지를 서빙하다 -* 앱 +* 애플리케이션 * 애플리케이션 * 요청 @@ -490,6 +490,6 @@ works(foo="bar") # 이건 동작합니다 🎉 이것은 문서에서 보이는 (대부분) 기술 용어의 불완전하고 비규범적인 목록입니다. 프롬프트 설계자가 어떤 용어에 대해 LLM에 추가적인 도움이 필요한지 파악하는 데 유용할 수 있습니다. 예를 들어, 좋은 번역을 계속 덜 좋은 번역으로 되돌릴 때, 또는 언어에서 용어의 활용/변화를 처리하는 데 문제가 있을 때 도움이 됩니다. -예를 들어 `docs/de/llm-prompt.md`의 `### List of English terms and their preferred German translations` 석션을 참고하세요. +예를 들어 `docs/de/llm-prompt.md`의 `### List of English terms and their preferred German translations` 섹션을 참고하세요. //// diff --git a/docs/ko/docs/advanced/additional-responses.md b/docs/ko/docs/advanced/additional-responses.md index e43d7c727..87866946b 100644 --- a/docs/ko/docs/advanced/additional-responses.md +++ b/docs/ko/docs/advanced/additional-responses.md @@ -34,7 +34,7 @@ /// -/// info | 정보 +/// note | 참고 `model` 키는 OpenAPI의 일부가 아닙니다. @@ -183,7 +183,7 @@ /// -/// info | 정보 +/// note | 참고 `responses` 파라미터에서 다른 미디어 타입을 명시적으로 지정하지 않는 한, FastAPI는 응답이 주요 응답 클래스와 동일한 미디어 타입(기본값 `application/json`)을 가진다고 가정합니다. diff --git a/docs/ko/docs/advanced/additional-status-codes.md b/docs/ko/docs/advanced/additional-status-codes.md index 6251b68b2..4762c8eed 100644 --- a/docs/ko/docs/advanced/additional-status-codes.md +++ b/docs/ko/docs/advanced/additional-status-codes.md @@ -8,7 +8,7 @@ 기본 상태 코드와 별도로 추가 상태 코드를 반환하려면 `JSONResponse`와 같이 `Response`를 직접 반환하고 추가 상태 코드를 직접 설정할 수 있습니다. -예를 들어 항목을 업데이트할 수 있는 *경로 처리*가 있고 성공 시 200 “OK”의 HTTP 상태 코드를 반환한다고 가정해 보겠습니다. +예를 들어 항목을 업데이트할 수 있는 *경로 처리*가 있고 성공 시 200 "OK"의 HTTP 상태 코드를 반환한다고 가정해 보겠습니다. 하지만 새로운 항목을 허용하기를 원할 것입니다. 그리고 항목이 이전에 존재하지 않았다면 이를 생성하고 HTTP 상태 코드 201 "Created"를 반환합니다. diff --git a/docs/ko/docs/advanced/advanced-dependencies.md b/docs/ko/docs/advanced/advanced-dependencies.md index 2755986a2..49b96bdad 100644 --- a/docs/ko/docs/advanced/advanced-dependencies.md +++ b/docs/ko/docs/advanced/advanced-dependencies.md @@ -79,7 +79,7 @@ checker(q="somequery") ### `yield`와 `scope`가 있는 의존성 { #dependencies-with-yield-and-scope } -0.121.0 버전에서 FastAPI는 `Depends(scope="function")` 지원을 추가했습니다. +0.121.0 버전에서 FastAPI는 `yield`가 있는 의존성을 위한 `Depends(scope="function")` 지원을 추가했습니다. `Depends(scope="function")`를 사용하면, `yield` 이후의 종료 코드는 *경로 처리 함수*가 끝난 직후(클라이언트에 응답이 반환되기 전)에 실행됩니다. @@ -99,7 +99,7 @@ FastAPI 0.118.0 이전에는 `yield`가 있는 의존성을 사용하면, *경 이 동작은 0.118.0에서 되돌려져, `yield` 이후의 종료 코드가 응답이 전송된 뒤 실행되도록 변경되었습니다. -/// info | 정보 +/// note | 참고 아래에서 보시겠지만, 이는 0.106.0 버전 이전의 동작과 매우 비슷하지만, 여러 개선 사항과 코너 케이스에 대한 버그 수정이 포함되어 있습니다. diff --git a/docs/ko/docs/advanced/custom-response.md b/docs/ko/docs/advanced/custom-response.md index e85ec3c74..d81a9dafb 100644 --- a/docs/ko/docs/advanced/custom-response.md +++ b/docs/ko/docs/advanced/custom-response.md @@ -41,7 +41,7 @@ {* ../../docs_src/custom_response/tutorial002_py310.py hl[2,7] *} -/// info | 정보 +/// note | 참고 `response_class` 매개변수는 응답의 "미디어 타입"을 정의하는 데에도 사용됩니다. @@ -65,7 +65,7 @@ /// -/// info | 정보 +/// note | 참고 물론 실제 `Content-Type` 헤더, 상태 코드 등은 반환된 `Response` 객체에서 가져옵니다. diff --git a/docs/ko/docs/advanced/dataclasses.md b/docs/ko/docs/advanced/dataclasses.md index 77e8d0464..609cb6cd9 100644 --- a/docs/ko/docs/advanced/dataclasses.md +++ b/docs/ko/docs/advanced/dataclasses.md @@ -18,7 +18,7 @@ FastAPI는 **Pydantic** 위에 구축되어 있으며, 지금까지는 Pydantic 이는 Pydantic 모델을 사용할 때와 같은 방식으로 동작합니다. 그리고 실제로도 내부적으로는 Pydantic을 사용해 같은 방식으로 구현됩니다. -/// info +/// note | 참고 dataclasses는 Pydantic 모델이 할 수 있는 모든 것을 할 수는 없다는 점을 기억하세요. diff --git a/docs/ko/docs/advanced/events.md b/docs/ko/docs/advanced/events.md index 708ad443f..13db29ef2 100644 --- a/docs/ko/docs/advanced/events.md +++ b/docs/ko/docs/advanced/events.md @@ -6,15 +6,15 @@ 이 코드는 애플리케이션이 요청을 받기 **시작**하기 전에 실행되고, 요청 처리를 **끝낸 직후**에 실행되기 때문에 전체 애플리케이션의 **수명(lifespan)**을 다룹니다(잠시 후 "lifespan"이라는 단어가 중요해집니다 😉). -이는 전체 앱에서 사용해야 하는 **자원**을 설정하고, 요청 간에 **공유되는** 자원을 설정하고, 그리고/또는 이후에 **정리**하는 데 매우 유용할 수 있습니다. 예를 들어, 데이터베이스 연결 풀 또는 공유 머신러닝 모델을 로드하는 경우입니다. +이는 전체 애플리케이션에서 사용해야 하는 **자원**을 설정하고, 요청 간에 **공유되는** 자원을 설정하고, 그리고/또는 이후에 **정리**하는 데 매우 유용할 수 있습니다. 예를 들어, 데이터베이스 연결 풀 또는 공유 머신러닝 모델을 로드하는 경우입니다. ## 사용 사례 { #use-case } 먼저 **사용 사례** 예시로 시작한 다음, 이를 어떻게 해결할지 살펴보겠습니다. -요청을 처리하는 데 사용하고 싶은 **머신러닝 모델**이 있다고 상상해 봅시다. 🤖 +요청을 처리하는 데 사용하고 싶은 몇 가지 **머신러닝 모델**이 있다고 상상해 봅시다. 🤖 -동일한 모델이 요청 간에 공유되므로, 요청마다 모델이 하나씩 있거나 사용자마다 하나씩 있는 등의 방식이 아닙니다. +동일한 모델들이 요청 간에 공유되므로, 요청마다 모델이 하나씩 있거나 사용자마다 하나씩 있는 등의 방식이 아닙니다. 모델을 로드하는 데 **상당한 시간이 걸린다고 상상해 봅시다**, 왜냐하면 모델이 **디스크에서 많은 데이터를 읽어야** 하기 때문입니다. 그래서 모든 요청마다 이를 수행하고 싶지는 않습니다. @@ -24,7 +24,7 @@ ## Lifespan { #lifespan } -`FastAPI` 앱의 `lifespan` 매개변수와 "컨텍스트 매니저"를 사용하여 *시작*과 *종료* 로직을 정의할 수 있습니다(컨텍스트 매니저가 무엇인지 잠시 후에 보여드리겠습니다). +`FastAPI` 애플리케이션의 `lifespan` 매개변수와 "컨텍스트 매니저"를 사용하여 *시작*과 *종료* 로직을 정의할 수 있습니다(컨텍스트 매니저가 무엇인지 잠시 후에 보여드리겠습니다). 예제로 시작한 다음 자세히 살펴보겠습니다. @@ -32,7 +32,7 @@ {* ../../docs_src/events/tutorial003_py310.py hl[16,19] *} -여기서는 `yield` 이전에 (가짜) 모델 함수를 머신러닝 모델이 들어 있는 딕셔너리에 넣어 모델을 로드하는 비용이 큰 *시작* 작업을 시뮬레이션합니다. 이 코드는 애플리케이션이 **요청을 받기 시작하기 전**, *시작* 동안에 실행됩니다. +여기서는 `yield` 이전에 (가짜) 모델 함수를 머신러닝 모델들이 들어 있는 딕셔너리에 넣어 모델을 로드하는 비용이 큰 *시작* 작업을 시뮬레이션합니다. 이 코드는 애플리케이션이 **요청을 받기 시작하기 전**, *시작* 동안에 실행됩니다. 그리고 `yield` 직후에는 모델을 언로드합니다. 이 코드는 애플리케이션이 **요청 처리를 마친 후**, *종료* 직전에 실행됩니다. 예를 들어 메모리나 GPU 같은 자원을 해제할 수 있습니다. @@ -80,7 +80,7 @@ async with lifespan(app): 위의 코드 예제에서는 직접 사용하지 않고, FastAPI에 전달하여 FastAPI가 이를 사용하도록 합니다. -`FastAPI` 앱의 `lifespan` 매개변수는 **비동기 컨텍스트 매니저**를 받으므로, 새 `lifespan` 비동기 컨텍스트 매니저를 전달할 수 있습니다. +`FastAPI` 애플리케이션의 `lifespan` 매개변수는 **비동기 컨텍스트 매니저**를 받으므로, 새 `lifespan` 비동기 컨텍스트 매니저를 전달할 수 있습니다. {* ../../docs_src/events/tutorial003_py310.py hl[22] *} @@ -88,7 +88,7 @@ async with lifespan(app): /// warning | 경고 -*시작*과 *종료*를 처리하는 권장 방법은 위에서 설명한 대로 `FastAPI` 앱의 `lifespan` 매개변수를 사용하는 것입니다. `lifespan` 매개변수를 제공하면 `startup`과 `shutdown` 이벤트 핸들러는 더 이상 호출되지 않습니다. `lifespan`만 쓰거나 이벤트만 쓰거나 둘 중 하나이지, 둘 다는 아닙니다. +*시작*과 *종료*를 처리하는 권장 방법은 위에서 설명한 대로 `FastAPI` 애플리케이션의 `lifespan` 매개변수를 사용하는 것입니다. `lifespan` 매개변수를 제공하면 `startup`과 `shutdown` 이벤트 핸들러는 더 이상 호출되지 않습니다. `lifespan`만 쓰거나 이벤트만 쓰거나 둘 중 하나이지, 둘 다는 아닙니다. 이 부분은 아마 건너뛰셔도 됩니다. @@ -120,7 +120,7 @@ async with lifespan(app): 여기서 `shutdown` 이벤트 핸들러 함수는 텍스트 한 줄 `"Application shutdown"`을 `log.txt` 파일에 기록합니다. -/// info | 정보 +/// note | 참고 `open()` 함수에서 `mode="a"`는 "append"(추가)를 의미하므로, 기존 내용을 덮어쓰지 않고 파일에 있던 내용 뒤에 줄이 추가됩니다. @@ -150,9 +150,9 @@ async with lifespan(app): 호기심 많은 분들을 위한 기술적인 세부사항입니다. 🤓 -내부적으로 ASGI 기술 사양에서는 이것이 [Lifespan Protocol](https://asgi.readthedocs.io/en/latest/specs/lifespan.html)의 일부이며, `startup`과 `shutdown`이라는 이벤트를 정의합니다. +내부적으로 ASGI 기술 사양에서는 이것이 [Lifespan 프로토콜](https://asgi.readthedocs.io/en/latest/specs/lifespan.html)의 일부이며, `startup`과 `shutdown`이라는 이벤트를 정의합니다. -/// info | 정보 +/// note | 참고 Starlette `lifespan` 핸들러에 대해서는 [Starlette의 Lifespan 문서](https://www.starlette.dev/lifespan/)에서 더 읽어볼 수 있습니다. diff --git a/docs/ko/docs/advanced/generate-clients.md b/docs/ko/docs/advanced/generate-clients.md index 1c2e32377..9cbe46ff8 100644 --- a/docs/ko/docs/advanced/generate-clients.md +++ b/docs/ko/docs/advanced/generate-clients.md @@ -2,7 +2,7 @@ **FastAPI**는 **OpenAPI** 사양을 기반으로 하므로, FastAPI의 API는 많은 도구가 이해할 수 있는 표준 형식으로 설명할 수 있습니다. -덕분에 여러 언어용 클라이언트 라이브러리(**SDKs**), 최신 **문서**, 그리고 코드와 동기화된 **테스트** 또는 **자동화 워크플로**를 쉽게 생성할 수 있습니다. +덕분에 최신 **문서**, 여러 언어용 클라이언트 라이브러리(**SDKs**), 그리고 코드와 동기화된 **테스트** 또는 **자동화 워크플로**를 쉽게 생성할 수 있습니다. 이 가이드에서는 FastAPI 백엔드용 **TypeScript SDK**를 생성하는 방법을 배웁니다. @@ -20,21 +20,6 @@ FastAPI는 **OpenAPI 3.1** 사양을 자동으로 생성하므로, 사용하는 /// -## FastAPI 스폰서의 SDK 생성기 { #sdk-generators-from-fastapi-sponsors } - -이 섹션에서는 FastAPI를 후원하는 회사들이 제공하는 **벤처 투자 기반** 및 **기업 지원** 솔루션을 소개합니다. 이 제품들은 고품질로 생성된 SDK에 더해 **추가 기능**과 **통합**을 제공합니다. - -✨ [**FastAPI 후원하기**](../help-fastapi.md#sponsor-the-author) ✨를 통해, 이 회사들은 프레임워크와 그 **생태계**가 건강하고 **지속 가능**하게 유지되도록 돕습니다. - -또한 이들의 후원은 FastAPI **커뮤니티**(여러분)에 대한 강한 헌신을 보여주며, **좋은 서비스**를 제공하는 것뿐 아니라, 견고하고 활발한 프레임워크인 FastAPI를 지원하는 데에도 관심이 있음을 나타냅니다. 🙇 - -예를 들어 다음을 사용해 볼 수 있습니다: - -* [Stainless](https://www.stainless.com/?utm_source=fastapi&utm_medium=referral) -* [liblab](https://developers.liblab.com/tutorials/sdk-for-fastapi?utm_source=fastapi) - -이 중 일부는 오픈 소스이거나 무료 티어를 제공하므로, 비용 부담 없이 사용해 볼 수 있습니다. 다른 상용 SDK 생성기도 있으며 온라인에서 찾을 수 있습니다. 🤓 - ## TypeScript SDK 만들기 { #create-a-typescript-sdk } 간단한 FastAPI 애플리케이션으로 시작해 보겠습니다: diff --git a/docs/ko/docs/advanced/json-base64-bytes.md b/docs/ko/docs/advanced/json-base64-bytes.md index b5e55a41a..b24acda86 100644 --- a/docs/ko/docs/advanced/json-base64-bytes.md +++ b/docs/ko/docs/advanced/json-base64-bytes.md @@ -4,7 +4,7 @@ ## Base64와 파일 { #base64-vs-files } -바이너리 데이터 업로드에는 [요청 파일](../tutorial/request-files.md)을, 바이너리 데이터 전송에는 [커스텀 응답 - FileResponse](./custom-response.md#fileresponse--fileresponse-)를 사용할 수 있는지 먼저 고려하세요. JSON으로 인코딩하는 대신 말입니다. +바이너리 데이터 업로드에는 [요청 파일](../tutorial/request-files.md)을, 바이너리 데이터 전송에는 [커스텀 응답 - FileResponse](./custom-response.md#fileresponse)를 사용할 수 있는지 먼저 고려하세요. JSON으로 인코딩하는 대신 말입니다. JSON은 UTF-8로 인코딩된 문자열만 포함할 수 있으므로, 원시 바이트를 그대로 담을 수 없습니다. diff --git a/docs/ko/docs/advanced/openapi-callbacks.md b/docs/ko/docs/advanced/openapi-callbacks.md index fa71acdcf..a44997ba2 100644 --- a/docs/ko/docs/advanced/openapi-callbacks.md +++ b/docs/ko/docs/advanced/openapi-callbacks.md @@ -165,15 +165,15 @@ https://www.external.org/events/invoices/2expen51ve ### 콜백 라우터 추가하기 { #add-the-callback-router } -이 시점에서, 위에서 만든 콜백 라우터 안에 *콜백 경로 처리(들)*(즉 *external developer*가 *external API*에 구현해야 하는 것들)을 준비했습니다. +이 시점에서, 위에서 만든 콜백 라우터 안에 *콜백 경로 처리(들)*(즉 *외부 개발자*가 *external API*에 구현해야 하는 것들)을 준비했습니다. -이제 *여러분의 API 경로 처리 데코레이터*에서 `callbacks` 파라미터를 사용해, 그 콜백 라우터의 `.routes` 속성(실제로는 routes/*경로 처리*의 `list`)을 전달합니다: +이제 *여러분의 API 경로 처리 데코레이터*에서 `callbacks` 파라미터를 사용해, 그 콜백 라우터의 `.routes` 속성을 전달합니다: {* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[33] *} /// tip | 팁 -`callback=`에 라우터 자체(`invoices_callback_router`)를 넘기는 것이 아니라, `invoices_callback_router.routes`처럼 `.routes` 속성을 넘긴다는 점에 주목하세요. +`callbacks=`에 라우터 자체(`invoices_callback_router`)를 넘기는 것이 아니라, `invoices_callback_router.routes`처럼 `.routes` 속성을 넘긴다는 점에 주목하세요. FastAPI는 이 라우트들을 사용하여 콜백 OpenAPI 문서를 생성합니다. /// diff --git a/docs/ko/docs/advanced/openapi-webhooks.md b/docs/ko/docs/advanced/openapi-webhooks.md index e40a7bb18..bb3f7895c 100644 --- a/docs/ko/docs/advanced/openapi-webhooks.md +++ b/docs/ko/docs/advanced/openapi-webhooks.md @@ -22,7 +22,7 @@ webhook의 URL을 등록하는 방법과 실제로 그 요청을 보내는 코 이렇게 하면 사용자가 여러분의 **webhook** 요청을 받기 위해 **자신들의 API를 구현**하기가 훨씬 쉬워지고, 경우에 따라서는 자신의 API 코드 일부를 자동 생성할 수도 있습니다. -/// info | 정보 +/// note | 참고 Webhooks는 OpenAPI 3.1.0 이상에서 사용할 수 있으며, FastAPI `0.99.0` 이상에서 지원됩니다. @@ -36,7 +36,7 @@ Webhooks는 OpenAPI 3.1.0 이상에서 사용할 수 있으며, FastAPI `0.99.0` 여러분이 정의한 webhook은 **OpenAPI** 스키마와 자동 **docs UI**에 포함됩니다. -/// info | 정보 +/// note | 참고 `app.webhooks` 객체는 실제로 `APIRouter`일 뿐이며, 여러 파일로 앱을 구조화할 때 사용하는 것과 동일한 타입입니다. diff --git a/docs/ko/docs/advanced/path-operation-advanced-configuration.md b/docs/ko/docs/advanced/path-operation-advanced-configuration.md index 253a6f302..398816005 100644 --- a/docs/ko/docs/advanced/path-operation-advanced-configuration.md +++ b/docs/ko/docs/advanced/path-operation-advanced-configuration.md @@ -2,7 +2,7 @@ ## OpenAPI operationId { #openapi-operationid } -/// warning | 경고 +/// warning OpenAPI “전문가”가 아니라면, 아마 이 내용은 필요하지 않을 것입니다. @@ -16,19 +16,13 @@ OpenAPI “전문가”가 아니라면, 아마 이 내용은 필요하지 않 ### *경로 처리 함수* 이름을 operationId로 사용하기 { #using-the-path-operation-function-name-as-the-operationid } -API의 함수 이름을 `operationId`로 사용하고 싶다면, 모든 API를 순회하면서 `APIRoute.name`을 사용해 각 *경로 처리*의 `operation_id`를 덮어쓸 수 있습니다. +API의 함수 이름을 `operationId`로 사용하고 싶다면, `FastAPI`에 사용자 정의 `generate_unique_id_function`을 전달할 수 있습니다. -모든 *경로 처리*를 추가한 뒤에 수행해야 합니다. +이 함수는 각 `APIRoute`를 받아 그 *경로 처리*에 사용할 `operationId`를 반환합니다. -{* ../../docs_src/path_operation_advanced_configuration/tutorial002_py310.py hl[2, 12:21, 24] *} +{* ../../docs_src/path_operation_advanced_configuration/tutorial002_py310.py hl[2,5:6,9] *} -/// tip | 팁 - -`app.openapi()`를 수동으로 호출한다면, 그 전에 `operationId`들을 업데이트해야 합니다. - -/// - -/// warning | 경고 +/// warning 이렇게 할 경우, 각 *경로 처리 함수*의 이름이 고유하도록 보장해야 합니다. @@ -78,7 +72,7 @@ OpenAPI 명세에서는 이를 [Operation Object](https://github.com/OAI/OpenAPI 이 *경로 처리* 전용 OpenAPI 스키마는 보통 **FastAPI**가 자동으로 생성하지만, 확장할 수도 있습니다. -/// tip | 팁 +/// tip 이는 저수준 확장 지점입니다. @@ -163,7 +157,7 @@ OpenAPI 명세에서는 이를 [Operation Object](https://github.com/OAI/OpenAPI {* ../../docs_src/path_operation_advanced_configuration/tutorial007_py310.py hl[24:31] *} -/// tip | 팁 +/// tip 여기서는 같은 Pydantic 모델을 재사용합니다. diff --git a/docs/ko/docs/advanced/response-change-status-code.md b/docs/ko/docs/advanced/response-change-status-code.md index f30474917..5e54dc75e 100644 --- a/docs/ko/docs/advanced/response-change-status-code.md +++ b/docs/ko/docs/advanced/response-change-status-code.md @@ -1,5 +1,6 @@ # 응답 - 상태 코드 변경 { #response-change-status-code } + 기본 [응답 상태 코드 설정](../tutorial/response-status-code.md)이 가능하다는 걸 이미 알고 계실 겁니다. 하지만 경우에 따라 기본 설정과 다른 상태 코드를 반환해야 할 때가 있습니다. diff --git a/docs/ko/docs/advanced/response-cookies.md b/docs/ko/docs/advanced/response-cookies.md index b73d71969..f17046e7b 100644 --- a/docs/ko/docs/advanced/response-cookies.md +++ b/docs/ko/docs/advanced/response-cookies.md @@ -26,7 +26,7 @@ {* ../../docs_src/response_cookies/tutorial001_py310.py hl[10:12] *} -/// tip +/// tip | 팁 `Response` 매개변수를 사용하지 않고 응답을 직접 반환하는 경우, FastAPI는 이를 직접 반환한다는 점에 유의하세요. diff --git a/docs/ko/docs/advanced/response-directly.md b/docs/ko/docs/advanced/response-directly.md index 301a259b2..fc2efc728 100644 --- a/docs/ko/docs/advanced/response-directly.md +++ b/docs/ko/docs/advanced/response-directly.md @@ -18,7 +18,7 @@ `Response` 또는 그 하위 클래스를 반환할 수 있습니다. -/// info | 정보 +/// note | 참고 `JSONResponse` 자체도 `Response`의 하위 클래스입니다. diff --git a/docs/ko/docs/advanced/response-headers.md b/docs/ko/docs/advanced/response-headers.md index e7157d8f4..769972967 100644 --- a/docs/ko/docs/advanced/response-headers.md +++ b/docs/ko/docs/advanced/response-headers.md @@ -1,5 +1,6 @@ # 응답 헤더 { #response-headers } + ## `Response` 매개변수 사용하기 { #use-a-response-parameter } 여러분은 *경로 처리 함수*에서 `Response` 타입의 매개변수를 선언할 수 있습니다 (쿠키와 같이 사용할 수 있습니다). diff --git a/docs/ko/docs/advanced/security/oauth2-scopes.md b/docs/ko/docs/advanced/security/oauth2-scopes.md index 5a785ff9f..265f82aa7 100644 --- a/docs/ko/docs/advanced/security/oauth2-scopes.md +++ b/docs/ko/docs/advanced/security/oauth2-scopes.md @@ -4,9 +4,9 @@ 이를 통해 OAuth2 표준을 따르는 더 세밀한 권한 시스템을 OpenAPI 애플리케이션(및 API 문서)에 통합할 수 있습니다. -스코프를 사용하는 OAuth2는 Facebook, Google, GitHub, Microsoft, X(Twitter) 등 많은 대형 인증 제공자가 사용하는 메커니즘입니다. 이들은 이를 통해 사용자와 애플리케이션에 특정 권한을 제공합니다. +스코프를 사용하는 OAuth2는 Facebook, Google, GitHub, Microsoft, X (Twitter) 등 많은 대형 인증 제공자가 사용하는 메커니즘입니다. 이들은 이를 통해 사용자와 애플리케이션에 특정 권한을 제공합니다. -Facebook, Google, GitHub, Microsoft, X(Twitter)로 “로그인”할 때마다, 해당 애플리케이션은 스코프가 있는 OAuth2를 사용하고 있습니다. +Facebook, Google, GitHub, Microsoft, X (Twitter)로 “로그인”할 때마다, 해당 애플리케이션은 스코프가 있는 OAuth2를 사용하고 있습니다. 이 섹션에서는 **FastAPI** 애플리케이션에서 동일한 “스코프가 있는 OAuth2”로 인증(Authentication)과 인가(Authorization)를 관리하는 방법을 확인합니다. @@ -46,7 +46,7 @@ OpenAPI(예: API 문서)에서는 “security schemes”를 정의할 수 있습 * `instagram_basic` 는 Facebook/Instagram에서 사용합니다. * `https://www.googleapis.com/auth/drive` 는 Google에서 사용합니다. -/// info | 정보 +/// note | 참고 OAuth2에서 “스코프”는 필요한 특정 권한을 선언하는 문자열일 뿐입니다. @@ -126,7 +126,7 @@ OAuth2 입장에서는 그저 문자열입니다. {* ../../docs_src/security/tutorial005_an_py310.py hl[5,141,172] *} -/// info | 기술 세부사항 +/// note | 기술 세부사항 `Security`는 실제로 `Depends`의 서브클래스이며, 나중에 보게 될 추가 매개변수 하나만 더 있습니다. diff --git a/docs/ko/docs/advanced/settings.md b/docs/ko/docs/advanced/settings.md index 49a2b640e..f7e8c20e7 100644 --- a/docs/ko/docs/advanced/settings.md +++ b/docs/ko/docs/advanced/settings.md @@ -1,5 +1,6 @@ # 설정과 환경 변수 { #settings-and-environment-variables } + 많은 경우 애플리케이션에는 외부 설정이나 구성(예: secret key, 데이터베이스 자격 증명, 이메일 서비스 자격 증명 등)이 필요할 수 있습니다. 이러한 설정 대부분은 데이터베이스 URL처럼 변동 가능(변경될 수 있음)합니다. 그리고 많은 설정은 secret처럼 민감할 수 있습니다. diff --git a/docs/ko/docs/advanced/stream-data.md b/docs/ko/docs/advanced/stream-data.md index 5eda170cb..94276876f 100644 --- a/docs/ko/docs/advanced/stream-data.md +++ b/docs/ko/docs/advanced/stream-data.md @@ -2,9 +2,9 @@ JSON으로 구조화할 수 있는 데이터를 스트리밍하려면 [JSON Lines 스트리밍](../tutorial/stream-json-lines.md)을 사용하세요. -하지만 순수 바이너리 데이터나 문자열을 스트리밍하려면 다음과 같이 하면 됩니다. +하지만 **순수 바이너리 데이터**나 문자열을 스트리밍하려면 다음과 같이 하면 됩니다. -/// info | 정보 +/// note | 참고 FastAPI 0.134.0에 추가되었습니다. @@ -12,21 +12,21 @@ FastAPI 0.134.0에 추가되었습니다. ## 사용 예시 { #use-cases } -예를 들어 AI LLM 서비스의 출력에서 바로 순수 문자열을 스트리밍하고 싶다면 이를 사용할 수 있습니다. +예를 들어 **AI LLM** 서비스의 출력에서 바로 순수 문자열을 스트리밍하고 싶다면 이를 사용할 수 있습니다. -또한 큰 바이너리 파일을 스트리밍하는 데 사용할 수 있습니다. 한 번에 모두 메모리로 읽지 않고, 읽는 즉시 데이터 청크를 순차적으로 스트리밍합니다. +또한 **큰 바이너리 파일**을 스트리밍하는 데 사용할 수 있습니다. 한 번에 모두 메모리로 읽지 않고, 읽는 즉시 데이터 청크를 순차적으로 스트리밍합니다. -이 방식으로 비디오나 오디오를 스트리밍할 수도 있으며, 처리하면서 생성된 데이터를 곧바로 전송할 수도 있습니다. +이 방식으로 **비디오**나 **오디오**를 스트리밍할 수도 있으며, 처리하면서 생성된 데이터를 곧바로 전송할 수도 있습니다. ## `yield`와 함께 `StreamingResponse` 사용하기 { #a-streamingresponse-with-yield } -경로 처리 함수에서 `response_class=StreamingResponse`를 선언하면 `yield`를 사용해 데이터 청크를 순차적으로 보낼 수 있습니다. +*경로 처리 함수*에서 `response_class=StreamingResponse`를 선언하면 `yield`를 사용해 데이터 청크를 순차적으로 보낼 수 있습니다. {* ../../docs_src/stream_data/tutorial001_py310.py ln[1:23] hl[20,23] *} FastAPI는 각 데이터 청크를 있는 그대로 `StreamingResponse`에 전달하며, JSON 등으로 변환하려고 하지 않습니다. -### async가 아닌 경로 처리 함수 { #non-async-path-operation-functions } +### async가 아닌 *경로 처리 함수* { #non-async-path-operation-functions } `async`가 없는 일반 `def` 함수에서도 동일하게 `yield`를 사용할 수 있습니다. @@ -40,7 +40,7 @@ FastAPI는 데이터를 Pydantic으로 JSON으로 변환하거나 어떤 방식 {* ../../docs_src/stream_data/tutorial001_py310.py ln[32:35] hl[33] *} -이는 곧 `StreamingResponse`를 사용할 때 타입 애너테이션과 무관하게, 전송 기준에 맞춰 바이트 데이터를 생성하고 인코딩할 자유와 책임이 여러분에게 있음을 의미합니다. 🤓 +이는 곧 `StreamingResponse`를 사용할 때 타입 애너테이션과 무관하게, 전송 기준에 맞춰 바이트 데이터를 생성하고 인코딩할 **자유**와 **책임**이 여러분에게 있음을 의미합니다. 🤓 ### 바이트 스트리밍 { #stream-bytes } @@ -58,7 +58,7 @@ FastAPI는 데이터를 Pydantic으로 JSON으로 변환하거나 어떤 방식 {* ../../docs_src/stream_data/tutorial002_py310.py ln[6,19:20] hl[20] *} -그런 다음 경로 처리 함수에서 `response_class=PNGStreamingResponse`로 이 새 클래스를 사용할 수 있습니다: +그런 다음 *경로 처리 함수*에서 `response_class=PNGStreamingResponse`로 이 새 클래스를 사용할 수 있습니다: {* ../../docs_src/stream_data/tutorial002_py310.py ln[23:27] hl[23] *} @@ -90,7 +90,7 @@ FastAPI는 데이터를 Pydantic으로 JSON으로 변환하거나 어떤 방식 또한 디스크나 네트워크에서 읽기 때문에, 많은 경우 읽기 작업은 이벤트 루프를 막을 수 있는 블로킹 연산입니다. -/// info | 정보 +/// note | 참고 위의 예시는 예외적인 경우입니다. `io.BytesIO` 객체는 이미 메모리에 있으므로 읽기가 아무 것도 차단하지 않습니다. @@ -98,7 +98,7 @@ FastAPI는 데이터를 Pydantic으로 JSON으로 변환하거나 어떤 방식 /// -이벤트 루프가 블로킹되는 것을 피하려면 경로 처리 함수를 `async def` 대신 일반 `def`로 선언하세요. 그러면 FastAPI가 스레드풀 워커에서 실행하여 메인 루프가 막히지 않도록 합니다. +이벤트 루프가 블로킹되는 것을 피하려면 *경로 처리 함수*를 `async def` 대신 일반 `def`로 선언하세요. 그러면 FastAPI가 스레드풀 워커에서 실행하여 메인 루프가 막히지 않도록 합니다. {* ../../docs_src/stream_data/tutorial002_py310.py ln[30:34] hl[31] *} diff --git a/docs/ko/docs/advanced/strict-content-type.md b/docs/ko/docs/advanced/strict-content-type.md index 82683e15c..39ecde4b6 100644 --- a/docs/ko/docs/advanced/strict-content-type.md +++ b/docs/ko/docs/advanced/strict-content-type.md @@ -81,7 +81,7 @@ http://localhost:8000/v1/agents/multivac 이 설정을 사용하면 `Content-Type` 헤더가 없는 요청도 본문이 JSON으로 파싱됩니다. 이는 이전 버전의 FastAPI와 동일한 동작입니다. -/// info | 정보 +/// note | 참고 이 동작과 설정은 FastAPI 0.132.0에 추가되었습니다. diff --git a/docs/ko/docs/advanced/websockets.md b/docs/ko/docs/advanced/websockets.md index 0b920c3b3..b37d93804 100644 --- a/docs/ko/docs/advanced/websockets.md +++ b/docs/ko/docs/advanced/websockets.md @@ -111,7 +111,7 @@ WebSocket 엔드포인트에서 `fastapi`에서 다음을 가져와 사용할 {* ../../docs_src/websockets_/tutorial002_an_py310.py hl[68:69,82] *} -/// info | 정보 +/// note | 참고 WebSocket이기 때문에 `HTTPException`을 발생시키는 것은 적절하지 않습니다. 대신 `WebSocketException`을 발생시킵니다. diff --git a/docs/ko/docs/advanced/wsgi.md b/docs/ko/docs/advanced/wsgi.md index 921e426ef..2b3012a46 100644 --- a/docs/ko/docs/advanced/wsgi.md +++ b/docs/ko/docs/advanced/wsgi.md @@ -6,7 +6,7 @@ ## `WSGIMiddleware` 사용하기 { #using-wsgimiddleware } -/// info | 정보 +/// note | 참고 이를 사용하려면 `a2wsgi`를 설치해야 합니다. 예: `pip install a2wsgi` @@ -42,7 +42,7 @@ Hello, World from Flask! ``` -그리고 [http://localhost:8000/v2](http://localhost:8000/v2)로 이동하면 **FastAPI**의 응답을 볼 수 있습니다: +그리고 [http://localhost:8000/v2](http://localhost:8000/v2)로 이동하면 FastAPI의 응답을 볼 수 있습니다: ```JSON { diff --git a/docs/ko/docs/alternatives.md b/docs/ko/docs/alternatives.md index ab92c0ea8..1bd0ba56a 100644 --- a/docs/ko/docs/alternatives.md +++ b/docs/ko/docs/alternatives.md @@ -24,7 +24,7 @@ ### [Django REST Framework](https://www.django-rest-framework.org/) { #django-rest-framework } -Django REST framework는 Django를 기반으로 Web API를 구축하기 위한 유연한 toolkit으로 만들어졌고, Django의 API 기능을 개선하기 위한 목적이었습니다. +Django REST Framework는 Django를 기반으로 Web API를 구축하기 위한 유연한 toolkit으로 만들어졌고, Django의 API 기능을 개선하기 위한 목적이었습니다. Mozilla, Red Hat, Eventbrite를 포함해 많은 회사에서 사용합니다. @@ -36,7 +36,7 @@ Django REST Framework는 Tom Christie가 만들었습니다. **FastAPI**의 기 /// -/// tip | 팁 +/// tip | **FastAPI**에 영감을 준 점 자동 API 문서화 웹 사용자 인터페이스를 제공하기. @@ -56,7 +56,7 @@ Flask는 "microframework"로, Django에 기본으로 포함된 데이터베이 Flask의 단순함을 고려하면 API를 구축하는 데 잘 맞는 것처럼 보였습니다. 다음으로 찾고자 했던 것은 Flask용 "Django REST Framework"였습니다. -/// tip | 팁 +/// tip | **FastAPI**에 영감을 준 점 micro-framework가 되기. 필요한 도구와 구성요소를 쉽게 조합할 수 있도록 하기. @@ -80,7 +80,7 @@ Requests는 매우 단순하고 직관적인 설계를 가졌고, 합리적인 그래서 공식 웹사이트에서 말하듯이: -> Requests is one of the most downloaded Python packages of all time +> Requests는 역대 가장 많이 다운로드된 Python 패키지 중 하나입니다 사용 방법은 매우 간단합니다. 예를 들어 `GET` 요청을 하려면 다음처럼 작성합니다: @@ -98,7 +98,7 @@ def read_url(): `requests.get(...)`와 `@app.get(...)`의 유사성을 확인해 보세요. -/// tip | 팁 +/// tip | **FastAPI**에 영감을 준 점 * 단순하고 직관적인 API를 갖기. * HTTP method 이름(operations)을 직접, 직관적이고 명확한 방식으로 사용하기. @@ -118,7 +118,7 @@ def read_url(): 그래서 2.0 버전을 이야기할 때는 "Swagger"라고 말하는 것이 일반적이고, 3+ 버전은 "OpenAPI"라고 말하는 것이 일반적입니다. -/// tip | 팁 +/// tip | **FastAPI**에 영감을 준 점 커스텀 schema 대신, API 사양을 위한 열린 표준을 채택하고 사용하기. @@ -147,7 +147,7 @@ API에 또 하나 크게 필요한 기능은 데이터 검증입니다. 특정 하지만 Python type hints가 존재하기 전에 만들어졌습니다. 그래서 각 스키마를 정의하려면 Marshmallow가 제공하는 특정 유틸리티와 클래스를 사용해야 합니다. -/// tip | 팁 +/// tip | **FastAPI**에 영감을 준 점 데이터 타입과 검증을 제공하는 "schema"를 코드로 정의하고, 이를 자동으로 활용하기. @@ -169,7 +169,7 @@ Webargs는 Marshmallow와 같은 개발자들이 만들었습니다. /// -/// tip | 팁 +/// tip | **FastAPI**에 영감을 준 점 들어오는 요청 데이터의 자동 검증을 갖기. @@ -199,7 +199,7 @@ APISpec은 Marshmallow와 같은 개발자들이 만들었습니다. /// -/// tip | 팁 +/// tip | **FastAPI**에 영감을 준 점 API를 위한 열린 표준인 OpenAPI를 지원하기. @@ -231,7 +231,7 @@ Flask-apispec은 Marshmallow와 같은 개발자들이 만들었습니다. /// -/// tip | 팁 +/// tip | **FastAPI**에 영감을 준 점 serialization과 validation을 정의하는 동일한 코드로부터 OpenAPI schema를 자동 생성하기. @@ -251,7 +251,7 @@ Angular 2에서 영감을 받은 의존성 주입 시스템이 통합되어 있 중첩 모델을 잘 처리하지 못합니다. 즉, 요청의 JSON body가 내부 필드를 가진 JSON 객체이고 그 내부 필드들이 다시 중첩된 JSON 객체인 경우, 제대로 문서화하고 검증할 수 없습니다. -/// tip | 팁 +/// tip | **FastAPI**에 영감을 준 점 Python 타입을 사용해 뛰어난 에디터 지원을 제공하기. @@ -271,7 +271,7 @@ Python 타입을 사용해 뛰어난 에디터 지원을 제공하기. /// -/// tip | 팁 +/// tip | **FastAPI**에 영감을 준 점 미친 성능을 낼 수 있는 방법을 찾기. @@ -283,11 +283,11 @@ Python 타입을 사용해 뛰어난 에디터 지원을 제공하기. Falcon은 또 다른 고성능 Python framework로, 최소한으로 설계되었고 Hug 같은 다른 framework의 기반으로 동작하도록 만들어졌습니다. -함수가 두 개의 파라미터(하나는 "request", 하나는 "response")를 받도록 설계되어 있습니다. 그런 다음 request에서 일부를 "읽고", response에 일부를 "작성"합니다. 이 설계 때문에, 표준 Python type hints를 함수 파라미터로 사용해 요청 파라미터와 body를 선언하는 것이 불가능합니다. +함수가 두 개의 파라미터(하나는 "요청", 하나는 "응답")를 받도록 설계되어 있습니다. 그런 다음 요청에서 일부를 "읽고", 응답에 일부를 "작성"합니다. 이 설계 때문에, 표준 Python type hints를 함수 파라미터로 사용해 요청 파라미터와 body를 선언하는 것이 불가능합니다. -따라서 데이터 검증, serialization, 문서화는 자동으로 되지 않고 코드로 해야 합니다. 또는 Hug처럼 Falcon 위에 framework를 얹어 구현해야 합니다. request 객체 하나와 response 객체 하나를 파라미터로 받는 Falcon의 설계에서 영감을 받은 다른 framework에서도 같은 구분이 나타납니다. +따라서 데이터 검증, serialization, 문서화는 자동으로 되지 않고 코드로 해야 합니다. 또는 Hug처럼 Falcon 위에 framework를 얹어 구현해야 합니다. 요청 객체 하나와 응답 객체 하나를 파라미터로 받는 Falcon의 설계에서 영감을 받은 다른 framework에서도 같은 구분이 나타납니다. -/// tip | 팁 +/// tip | **FastAPI**에 영감을 준 점 훌륭한 성능을 얻는 방법을 찾기. @@ -313,7 +313,7 @@ Pydantic 같은 서드파티 라이브러리를 사용해 데이터 검증/seria Route는 한 곳에서 선언하고, 다른 곳에 선언된 함수를 사용합니다(엔드포인트를 처리하는 함수 바로 위에 둘 수 있는 decorator를 사용하는 대신). 이는 Flask(및 Starlette)보다는 Django 방식에 가깝습니다. 코드에서 상대적으로 강하게 결합된 것들을 분리해 놓습니다. -/// tip | 팁 +/// tip | **FastAPI**에 영감을 준 점 모델 속성의 "default" 값으로 데이터 타입에 대한 추가 검증을 정의하기. 이는 에디터 지원을 개선하며, 이전에는 Pydantic에 없었습니다. @@ -341,7 +341,7 @@ Hug는 Timothy Crosley가 만들었습니다. Python 파일에서 import를 자 /// -/// tip | 팁 +/// tip | **FastAPI**에 영감을 준 아이디어 Hug는 APIStar의 일부에 영감을 주었고, 저는 APIStar와 함께 Hug를 가장 유망한 도구 중 하나로 보았습니다. @@ -385,7 +385,7 @@ APIStar는 Tom Christie가 만들었습니다. 다음을 만든 사람과 동일 /// -/// tip | 팁 +/// tip | **FastAPI**에 영감을 준 점 존재하게 만들기. @@ -409,7 +409,7 @@ Pydantic은 Python type hints를 기반으로 데이터 검증, serialization, Marshmallow와 비교할 수 있습니다. 다만 benchmark에서 Marshmallow보다 빠릅니다. 그리고 동일한 Python type hints를 기반으로 하므로 에디터 지원도 훌륭합니다. -/// tip | 팁 +/// tip | **FastAPI**는 이를 사용해 모든 데이터 검증, 데이터 serialization, 자동 모델 문서화(JSON Schema 기반)를 처리하기. @@ -430,7 +430,7 @@ Starlette는 경량 -Dockerfile Preview 👀 +Dockerfile 미리보기 👀 ```Dockerfile FROM python:3.14 @@ -26,7 +26,7 @@ COPY ./app /code/app CMD ["fastapi", "run", "app/main.py", "--port", "80"] -# If running behind a proxy like Nginx or Traefik add --proxy-headers +# Nginx나 Traefik 같은 프록시 뒤에서 실행한다면 --proxy-headers를 추가하세요 # CMD ["fastapi", "run", "app/main.py", "--port", "80", "--proxy-headers"] ``` @@ -46,7 +46,7 @@ CMD ["fastapi", "run", "app/main.py", "--port", "80"] **컨테이너**는 **컨테이너 이미지**에서 실행됩니다. -컨테이너 이미지는 컨테이너에 있어야 하는 모든 파일, 환경 변수, 기본 명령/프로그램의 **정적** 버전입니다. 여기서 **정적**이라는 것은 컨테이너 **이미지**가 실행 중이거나 수행되는 것이 아니라, 패키징된 파일과 메타데이터일 뿐이라는 뜻입니다. +컨테이너 이미지는 컨테이너에 있어야 하는 모든 파일, 환경 변수, 기본 명령어/프로그램의 **정적** 버전입니다. 여기서 **정적**이라는 것은 컨테이너 **이미지**가 실행 중이거나 수행되는 것이 아니라, 패키징된 파일과 메타데이터일 뿐이라는 뜻입니다. 저장된 정적 콘텐츠인 "**컨테이너 이미지**"와 달리, "**컨테이너**"는 보통 실행 중인 인스턴스, 즉 **실행되는** 대상을 의미합니다. @@ -62,7 +62,7 @@ Docker는 **컨테이너 이미지**와 **컨테이너**를 생성하고 관리 또한 [Docker Hub](https://hub.docker.com/)에는 다양한 도구, 환경, 데이터베이스, 애플리케이션을 위한 미리 만들어진 **공식 컨테이너 이미지**가 공개되어 있습니다. -예를 들어, 공식 [Python Image](https://hub.docker.com/_/python)가 있습니다. +예를 들어, 공식 [Python 이미지](https://hub.docker.com/_/python)가 있습니다. 그리고 데이터베이스 등 다양한 용도의 다른 이미지도 많이 있습니다. 예를 들면: @@ -81,11 +81,11 @@ Docker나 Kubernetes 같은 모든 컨테이너 관리 시스템에는 이러한 ## 컨테이너와 프로세스 { #containers-and-processes } -**컨테이너 이미지**는 보통 **컨테이너**가 시작될 때 실행되어야 하는 기본 프로그램/명령과 해당 프로그램에 전달할 매개변수를 메타데이터에 포함합니다. 커맨드 라인에서 실행할 때와 매우 유사합니다. +**컨테이너 이미지**는 보통 **컨테이너**가 시작될 때 실행되어야 하는 기본 프로그램/명령어와 해당 프로그램에 전달할 매개변수를 메타데이터에 포함합니다. 커맨드 라인에서 실행할 때와 매우 유사합니다. -**컨테이너**가 시작되면 해당 명령/프로그램을 실행합니다(다만 오버라이드하여 다른 명령/프로그램을 실행하게 할 수도 있습니다). +**컨테이너**가 시작되면 해당 명령어/프로그램을 실행합니다(다만 오버라이드하여 다른 명령어/프로그램을 실행하게 할 수도 있습니다). -컨테이너는 **메인 프로세스**(명령 또는 프로그램)가 실행되는 동안 실행됩니다. +컨테이너는 **메인 프로세스**(명령어 또는 프로그램)가 실행되는 동안 실행됩니다. 컨테이너는 보통 **단일 프로세스**를 가지지만, 메인 프로세스에서 서브프로세스를 시작할 수도 있으며, 그러면 같은 컨테이너에 **여러 프로세스**가 존재하게 됩니다. @@ -132,7 +132,7 @@ Successfully installed fastapi pydantic
-/// info | 정보 +/// note | 참고 패키지 의존성을 정의하고 설치하는 다른 형식과 도구도 있습니다. @@ -218,11 +218,11 @@ CMD ["fastapi", "run", "app/main.py", "--port", "80"] 따라서 컨테이너 이미지 빌드 시간을 최적화하려면 `Dockerfile`의 **끝부분 근처**에 두는 것이 중요합니다. -6. 내부적으로 Uvicorn을 사용하는 `fastapi run`을 사용하도록 **명령**을 설정합니다. +6. 내부적으로 Uvicorn을 사용하는 `fastapi run`을 사용하도록 **명령어**를 설정합니다. `CMD`는 문자열 리스트를 받으며, 각 문자열은 커맨드 라인에서 공백으로 구분해 입력하는 항목들입니다. - 이 명령은 **현재 작업 디렉터리**에서 실행되며, 이는 위에서 `WORKDIR /code`로 설정한 `/code` 디렉터리와 같습니다. + 이 명령어는 **현재 작업 디렉터리**에서 실행되며, 이는 위에서 `WORKDIR /code`로 설정한 `/code` 디렉터리와 같습니다. /// tip | 팁 @@ -258,7 +258,7 @@ FastAPI가 정상적으로 종료(graceful shutdown)되고 [lifespan 이벤트]( 자세한 내용은 [shell and exec form에 대한 Docker 문서](https://docs.docker.com/reference/dockerfile/#shell-and-exec-form)를 참고하세요. -이는 `docker compose`를 사용할 때 꽤 눈에 띌 수 있습니다. 좀 더 기술적인 상세 내용은 Docker Compose FAQ 섹션을 참고하세요: [Why do my services take 10 seconds to recreate or stop?](https://docs.docker.com/compose/faq/#why-do-my-services-take-10-seconds-to-recreate-or-stop). +이는 `docker compose`를 사용할 때 꽤 눈에 띌 수 있습니다. 좀 더 기술적인 상세 내용은 Docker Compose FAQ 섹션을 참고하세요: [왜 내 서비스는 다시 생성되거나 중지되는 데 10초가 걸리나요?](https://docs.docker.com/compose/faq/#why-do-my-services-take-10-seconds-to-recreate-or-stop). #### 디렉터리 구조 { #directory-structure } @@ -409,7 +409,7 @@ CMD ["fastapi", "run", "main.py", "--port", "80"] 2. 단일 파일 `main.py`에 있는 애플리케이션을 제공(serve)하기 위해 `fastapi run`을 사용합니다. -`fastapi run`에 파일을 전달하면, 이것이 패키지의 일부가 아닌 단일 파일이라는 것을 자동으로 감지하고, 어떻게 임포트해서 FastAPI 앱을 제공할지 알아냅니다. 😎 +`fastapi run`에 파일을 전달하면, 이것이 패키지의 일부가 아닌 단일 파일이라는 것을 자동으로 감지하고, 어떻게 임포트해서 FastAPI 애플리케이션을 제공할지 알아냅니다. 😎 ## 배포 개념 { #deployment-concepts } @@ -472,17 +472,17 @@ HTTPS에 사용되는 동일한 **TLS 종료 프록시** 컴포넌트가 **로 /// -또한 컨테이너로 작업할 때, 이를 시작하고 관리하는 시스템은 이미 해당 **로드 밸런서**(또는 **TLS 종료 프록시**)에서 여러분의 앱이 있는 컨테이너로 **네트워크 통신**(예: HTTP 요청)을 전달하는 내부 도구를 가지고 있습니다. +또한 컨테이너로 작업할 때, 이를 시작하고 관리하는 시스템은 이미 해당 **로드 밸런서**(또는 **TLS 종료 프록시**)에서 여러분의 애플리케이션이 있는 컨테이너로 **네트워크 통신**(예: HTTP 요청)을 전달하는 내부 도구를 가지고 있습니다. ### 하나의 로드 밸런서 - 여러 워커 컨테이너 { #one-load-balancer-multiple-worker-containers } -**Kubernetes** 같은 분산 컨테이너 관리 시스템에서는 내부 네트워킹 메커니즘을 통해, 메인 **포트**에서 대기하는 단일 **로드 밸런서**가 여러분의 앱을 실행하는 **여러 컨테이너**로 통신(요청)을 전달할 수 있습니다. +**Kubernetes** 같은 분산 컨테이너 관리 시스템에서는 내부 네트워킹 메커니즘을 통해, 메인 **포트**에서 대기하는 단일 **로드 밸런서**가 여러분의 애플리케이션을 실행하는 **여러 컨테이너**로 통신(요청)을 전달할 수 있습니다. -앱을 실행하는 각 컨테이너는 보통 **프로세스 하나만** 가집니다(예: FastAPI 애플리케이션을 실행하는 Uvicorn 프로세스). 모두 같은 것을 실행하는 **동일한 컨테이너**이지만, 각자 고유한 프로세스, 메모리 등을 가집니다. 이렇게 하면 CPU의 **서로 다른 코어** 또는 **서로 다른 머신**에서 **병렬화**의 이점을 얻을 수 있습니다. +애플리케이션을 실행하는 각 컨테이너는 보통 **프로세스 하나만** 가집니다(예: FastAPI 애플리케이션을 실행하는 Uvicorn 프로세스). 모두 같은 것을 실행하는 **동일한 컨테이너**이지만, 각자 고유한 프로세스, 메모리 등을 가집니다. 이렇게 하면 CPU의 **서로 다른 코어** 또는 **서로 다른 머신**에서 **병렬화**의 이점을 얻을 수 있습니다. -그리고 **로드 밸런서**가 있는 분산 컨테이너 시스템은 여러분의 앱을 실행하는 각 컨테이너에 **번갈아가며** 요청을 **분산**합니다. 따라서 각 요청은 여러분의 앱을 실행하는 여러 **복제된 컨테이너** 중 하나에서 처리될 수 있습니다. +그리고 **로드 밸런서**가 있는 분산 컨테이너 시스템은 여러분의 애플리케이션을 실행하는 각 컨테이너에 **번갈아가며** 요청을 **분산**합니다. 따라서 각 요청은 여러분의 애플리케이션을 실행하는 여러 **복제된 컨테이너** 중 하나에서 처리될 수 있습니다. -또한 보통 이 **로드 밸런서**는 클러스터 내 *다른* 앱으로 가는 요청(예: 다른 도메인, 또는 다른 URL 경로 접두사 아래로 가는 요청)도 처리할 수 있으며, 그 통신을 클러스터에서 실행 중인 *그 다른* 애플리케이션의 올바른 컨테이너로 전달할 수 있습니다. +또한 보통 이 **로드 밸런서**는 클러스터 내 *다른* 애플리케이션으로 가는 요청(예: 다른 도메인, 또는 다른 URL 경로 접두사 아래로 가는 요청)도 처리할 수 있으며, 그 통신을 클러스터에서 실행 중인 *그 다른* 애플리케이션의 올바른 컨테이너로 전달할 수 있습니다. ### 컨테이너당 하나의 프로세스 { #one-process-per-container } @@ -556,7 +556,7 @@ CMD ["fastapi", "run", "app/main.py", "--port", "80", "--workers", "4"] **여러 컨테이너**가 있고 각 컨테이너가 보통 **단일 프로세스**를 실행한다면(예: **Kubernetes** 클러스터), 복제된 워커 컨테이너를 실행하기 **전에**, 단일 컨테이너에서 단일 프로세스로 **시작 전 사전 단계**를 수행하는 **별도의 컨테이너**를 두고 싶을 가능성이 큽니다. -/// info | 정보 +/// note | 참고 Kubernetes를 사용한다면, 이는 아마도 [Init Container](https://kubernetes.io/docs/concepts/workloads/pods/init-containers/)일 것입니다. @@ -566,7 +566,7 @@ Kubernetes를 사용한다면, 이는 아마도 [Init Container](https://kuberne ### 단일 컨테이너 { #single-container } -**단일 컨테이너**에서 여러 **워커 프로세스**(또는 단일 프로세스)를 시작하는 단순한 셋업이라면, 앱이 있는 프로세스를 시작하기 직전에 같은 컨테이너에서 시작 전 사전 단계를 실행할 수 있습니다. +**단일 컨테이너**에서 여러 **워커 프로세스**(또는 단일 프로세스)를 시작하는 단순한 셋업이라면, 애플리케이션이 있는 프로세스를 시작하기 직전에 같은 컨테이너에서 시작 전 사전 단계를 실행할 수 있습니다. ### 베이스 도커 이미지 { #base-docker-image } @@ -582,7 +582,7 @@ Kubernetes를 사용한다면, 이는 아마도 [Init Container](https://kuberne 이 Docker 이미지는 Uvicorn이 죽은 워커를 관리하고 재시작하는 기능을 지원하지 않던 시기에 만들어졌습니다. 그래서 Gunicorn과 Uvicorn을 함께 사용해야 했고, Gunicorn이 Uvicorn 워커 프로세스를 관리하고 재시작하도록 하기 위해 상당한 복잡성이 추가되었습니다. -하지만 이제 Uvicorn(그리고 `fastapi` 명령)은 `--workers`를 지원하므로, 베이스 도커 이미지를 사용하는 대신 직접 이미지를 빌드하지 않을 이유가 없습니다(코드 양도 사실상 거의 같습니다 😅). +하지만 이제 Uvicorn(그리고 `fastapi` 명령어)은 `--workers`를 지원하므로, 베이스 도커 이미지를 사용하는 대신 직접 이미지를 빌드하지 않을 이유가 없습니다(코드 양도 사실상 거의 같습니다 😅). /// @@ -600,7 +600,7 @@ Kubernetes를 사용한다면, 이는 아마도 [Init Container](https://kuberne ## `uv`를 사용하는 도커 이미지 { #docker-image-with-uv } -프로젝트를 설치하고 관리하기 위해 [uv](https://github.com/astral-sh/uv)를 사용한다면, [uv Docker guide](https://docs.astral.sh/uv/guides/integration/docker/)를 따를 수 있습니다. +프로젝트를 설치하고 관리하기 위해 [uv](https://github.com/astral-sh/uv)를 사용한다면, [uv Docker 가이드](https://docs.astral.sh/uv/guides/integration/docker/)를 따를 수 있습니다. ## 요약 { #recap } diff --git a/docs/ko/docs/deployment/fastapicloud.md b/docs/ko/docs/deployment/fastapicloud.md index a601f5416..5fe057f47 100644 --- a/docs/ko/docs/deployment/fastapicloud.md +++ b/docs/ko/docs/deployment/fastapicloud.md @@ -1,26 +1,6 @@ # FastAPI Cloud { #fastapi-cloud } -**한 번의 명령**으로 FastAPI 앱을 [FastAPI Cloud](https://fastapicloud.com)에 배포할 수 있습니다. 아직이라면 대기자 명단에 등록해 보세요. 🚀 - -## 로그인하기 { #login } - -먼저 **FastAPI Cloud** 계정이 이미 있는지 확인하세요(대기자 명단에서 초대해 드렸을 거예요 😉). - -그다음 로그인합니다: - -
- -```console -$ fastapi login - -You are logged in to FastAPI Cloud 🚀 -``` - -
- -## 배포하기 { #deploy } - -이제 **한 번의 명령**으로 앱을 배포합니다: +**한 번의 명령**으로 FastAPI 앱을 [FastAPI Cloud](https://fastapicloud.com)에 배포할 수 있습니다. 🚀
@@ -36,6 +16,8 @@ Deploying to FastAPI Cloud...
+CLI가 FastAPI 애플리케이션을 자동으로 감지하여 클라우드에 배포합니다. 로그인되어 있지 않다면, 인증을 완료할 수 있도록 브라우저가 자동으로 열립니다. + 이게 전부입니다! 이제 해당 URL에서 앱에 접근할 수 있습니다. ✨ ## FastAPI Cloud 소개 { #about-fastapi-cloud } diff --git a/docs/ko/docs/deployment/https.md b/docs/ko/docs/deployment/https.md index 06ac147cd..1db7dd25c 100644 --- a/docs/ko/docs/deployment/https.md +++ b/docs/ko/docs/deployment/https.md @@ -14,7 +14,7 @@ HTTPS는 그냥 “켜져 있거나” 아니면 “꺼져 있는” 것이라 이제 **개발자 관점**에서 HTTPS를 생각할 때 염두에 두어야 할 여러 가지가 있습니다: -* HTTPS를 사용하려면, **서버**가 **제3자**가 발급한 **"인증서(certificates)"**를 **보유**해야 합니다. +* HTTPS를 사용하려면, **서버**가 **제3자**가 생성한 **"인증서(certificates)"**를 **보유**해야 합니다. * 이 인증서는 실제로 '생성'되는 것이 아니라 제3자로부터 **발급/획득**하는 것입니다. * 인증서에는 **유효 기간**이 있습니다. * 즉, **만료**됩니다. diff --git a/docs/ko/docs/deployment/manually.md b/docs/ko/docs/deployment/manually.md index 719968682..fbac8169f 100644 --- a/docs/ko/docs/deployment/manually.md +++ b/docs/ko/docs/deployment/manually.md @@ -1,6 +1,6 @@ # 서버를 수동으로 실행하기 { #run-a-server-manually } -## `fastapi run` 명령 사용하기 { #use-the-fastapi-run-command } +## `fastapi run` 명령어 사용하기 { #use-the-fastapi-run-command } 요약하면, `fastapi run`을 사용해 FastAPI 애플리케이션을 서비스하세요: @@ -40,7 +40,7 @@ $ fastapi run fastapi run ASGI라고 불리는, Python 웹 프레임워크와 서버를 만들기 위한 표준을 사용합니다. FastAPI는 ASGI 웹 프레임워크입니다. -원격 서버 머신에서 **FastAPI** 애플리케이션(또는 다른 ASGI 애플리케이션)을 실행하기 위해 필요한 핵심 요소는 **Uvicorn** 같은 ASGI 서버 프로그램입니다. `fastapi` 명령에는 기본으로 이것이 포함되어 있습니다. +원격 서버 머신에서 **FastAPI** 애플리케이션(또는 다른 ASGI 애플리케이션)을 실행하기 위해 필요한 핵심 요소는 **Uvicorn** 같은 ASGI 서버 프로그램입니다. `fastapi` 명령어에는 기본으로 이것이 포함되어 있습니다. 다음을 포함해 여러 대안이 있습니다: @@ -56,7 +56,6 @@ FastAPI는 - +
**Pydantic v2**의 이 기능 덕분에 API 문서는 더 **정밀**해지고, 자동 생성된 클라이언트와 SDK가 있다면 그것들도 더 정밀해져서 더 나은 **developer experience**와 일관성을 제공할 수 있습니다. 🎉 @@ -85,7 +85,7 @@ 그런 경우에는, **FastAPI**에서 `separate_input_output_schemas=False` 파라미터로 이 기능을 비활성화할 수 있습니다. -/// info | 정보 +/// note | 참고 `separate_input_output_schemas` 지원은 FastAPI `0.102.0`에 추가되었습니다. 🤓 diff --git a/docs/ko/docs/index.md b/docs/ko/docs/index.md index 0dd0bef59..f839c82ef 100644 --- a/docs/ko/docs/index.md +++ b/docs/ko/docs/index.md @@ -125,7 +125,7 @@ FastAPI는 현대적이고, 빠르며(고성능), 파이썬 표준 타입 힌트
-"_[...] 저는 요즘 **FastAPI**를 많이 사용하고 있습니다. [...] 사실 우리 팀의 **마이크로소프트 ML 서비스** 전부를 바꿀 계획입니다. 그중 일부는 핵심 **Windows**와 몇몇의 **Office** 제품들이 통합되고 있습니다._" +"_[...] 저는 요즘 **FastAPI**를 많이 사용하고 있습니다. [...] 사실 우리 팀의 **마이크로소프트 ML 서비스** 전부에 사용할 계획입니다. 그중 일부는 핵심 **Windows** 제품과 일부 **Office** 제품에 통합되고 있습니다._"
Kabir Khan - Microsoft (ref)
@@ -137,13 +137,13 @@ FastAPI는 현대적이고, 빠르며(고성능), 파이썬 표준 타입 힌트 --- -"_**Netflix**는 우리의 오픈 소스 배포판인 **위기 관리** 오케스트레이션 프레임워크를 발표할 수 있어 기쁩니다: 바로 **Dispatch**입니다! [**FastAPI**로 빌드]_" +"_**Netflix**는 우리의 **위기 관리** 오케스트레이션 프레임워크인 **Dispatch**의 오픈 소스 공개를 발표하게 되어 기쁩니다! [**FastAPI**로 빌드]_"
Kevin Glisson, Marc Vilanova, Forest Monsen - Netflix (ref)
--- -"_프로덕션 Python API를 만들고자 한다면, 저는 **FastAPI**를 강력히 추천합니다. **아름답게 설계**되었고, **사용이 간단**하며, **확장성이 매우 뛰어나** 우리의 API 우선 개발 전략에서 **핵심 구성 요소**가 되었습니다._" +"_프로덕션 Python API를 만들고자 한다면, 저는 **FastAPI**를 강력히 추천합니다. **아름답게 설계**되었고, **사용이 간단**하며, **확장성이 매우 뛰어나** 우리의 API 우선 개발 전략에서 **핵심 구성 요소**가 되었고, 우리의 Virtual TAC Engineer와 같은 여러 자동화와 서비스들을 추진하고 있습니다._"
Deon Pillsbury - Cisco (ref)
@@ -192,7 +192,7 @@ $ pip install "fastapi[standard]"
-**Note**: 모든 터미널에서 동작하도록 `"fastapi[standard]"`를 따옴표로 감싸 넣었는지 확인하세요. +**참고**: 모든 터미널에서 동작하도록 `"fastapi[standard]"`를 따옴표로 감싸 넣었는지 확인하세요. ## 예제 { #example } @@ -237,9 +237,9 @@ async def read_item(item_id: int, q: str | None = None): return {"item_id": item_id, "q": q} ``` -**Note**: +**참고**: -잘 모르겠다면, ["급하세요?"](https://fastapi.tiangolo.com/ko/async/#in-a-hurry) 섹션을 확인해 보십시오. +잘 모르겠다면, 문서의 [`async`와 `await`](https://fastapi.tiangolo.com/ko/async/#in-a-hurry)에 관한 _"급하세요?"_ 섹션을 확인해 보십시오. @@ -492,9 +492,7 @@ item: Item ### 앱 배포하기(선택 사항) { #deploy-your-app-optional } -선택적으로 FastAPI 앱을 [FastAPI Cloud](https://fastapicloud.com)에 배포할 수 있습니다. 아직이라면 대기자 명단에 등록해 보세요. 🚀 - -이미 **FastAPI Cloud** 계정이 있다면(대기자 명단에서 초대해 드렸습니다 😉), 한 번의 명령으로 애플리케이션을 배포할 수 있습니다. +선택적으로 FastAPI 앱을 한 번의 명령어로 [FastAPI Cloud](https://fastapicloud.com)에 배포할 수 있습니다. 🚀
@@ -510,6 +508,8 @@ Deploying to FastAPI Cloud...
+CLI가 여러분의 FastAPI 애플리케이션을 자동으로 감지하여 클라우드에 배포합니다. 로그인되어 있지 않다면, 인증을 완료하기 위해 브라우저가 열립니다. + 이게 전부입니다! 이제 해당 URL에서 앱에 접근할 수 있습니다. ✨ #### FastAPI Cloud 소개 { #about-fastapi-cloud } diff --git a/docs/ko/docs/project-generation.md b/docs/ko/docs/project-generation.md index 774b03a19..3a5a9b940 100644 --- a/docs/ko/docs/project-generation.md +++ b/docs/ko/docs/project-generation.md @@ -1,5 +1,6 @@ # Full Stack FastAPI 템플릿 { #full-stack-fastapi-template } + 템플릿은 일반적으로 특정 설정과 함께 제공되지만, 유연하고 커스터마이징이 가능하게 디자인 되었습니다. 이 특성들은 여러분이 프로젝트의 요구사항에 맞춰 수정, 적용을 할 수 있게 해주고, 템플릿이 완벽한 시작점이 되게 해줍니다. 🏁 많은 초기 설정, 보안, 데이터베이스 및 일부 API 엔드포인트가 이미 준비되어 있으므로, 여러분은 이 템플릿을 시작하는 데 사용할 수 있습니다. diff --git a/docs/ko/docs/python-types.md b/docs/ko/docs/python-types.md index 10b74b228..a0216cd5b 100644 --- a/docs/ko/docs/python-types.md +++ b/docs/ko/docs/python-types.md @@ -124,7 +124,7 @@ John Doe 이것은 **FastAPI**와 함께 사용할 때도 주요 위치입니다. -### Simple 타입 { #simple-types } +### 간단한 타입 { #simple-types } `str`뿐 아니라 모든 파이썬 표준 타입을 선언할 수 있습니다. @@ -287,7 +287,7 @@ Pydantic 공식 문서의 예시: /// note | 참고 -Pydantic에 대해 더 알아보려면 [문서를 확인하세요](https://docs.pydantic.dev/). +더 알아보려면 [Pydantic 문서를 확인하세요](https://docs.pydantic.dev/). /// diff --git a/docs/ko/docs/tutorial/bigger-applications.md b/docs/ko/docs/tutorial/bigger-applications.md index a206bfdc1..bb3637f75 100644 --- a/docs/ko/docs/tutorial/bigger-applications.md +++ b/docs/ko/docs/tutorial/bigger-applications.md @@ -17,16 +17,16 @@ Flask를 사용해 보셨다면, 이는 Flask의 Blueprints에 해당하는 개 ``` . ├── app -│   ├── __init__.py -│   ├── main.py -│   ├── dependencies.py -│   └── routers -│   │ ├── __init__.py -│   │ ├── items.py -│   │ └── users.py -│   └── internal -│   ├── __init__.py -│   └── admin.py +│ ├── __init__.py +│ ├── main.py +│ ├── dependencies.py +│ └── routers +│ │ ├── __init__.py +│ │ ├── items.py +│ │ └── users.py +│ └── internal +│ ├── __init__.py +│ └── admin.py ``` /// tip | 팁 @@ -75,11 +75,11 @@ from app.routers import items 사용자만 처리하는 전용 파일이 `/app/routers/users.py`의 submodule이라고 해봅시다. -코드를 정리하기 위해 사용자와 관련된 *path operations*를 나머지 코드와 분리해 두고 싶을 것입니다. +코드를 정리하기 위해 사용자와 관련된 *경로 처리*를 나머지 코드와 분리해 두고 싶을 것입니다. 하지만 이것은 여전히 같은 **FastAPI** 애플리케이션/웹 API의 일부입니다(같은 "Python Package"의 일부입니다). -`APIRouter`를 사용해 해당 모듈의 *path operations*를 만들 수 있습니다. +`APIRouter`를 사용해 해당 모듈의 *경로 처리*를 만들 수 있습니다. ### `APIRouter` import하기 { #import-apirouter } @@ -87,9 +87,9 @@ from app.routers import items {* ../../docs_src/bigger_applications/app_an_py310/routers/users.py hl[1,3] title["app/routers/users.py"] *} -### `APIRouter`로 *path operations* 만들기 { #path-operations-with-apirouter } +### `APIRouter`로 *경로 처리* 만들기 { #path-operations-with-apirouter } -그 다음 이를 사용해 *path operations*를 선언합니다. +그 다음 이를 사용해 *경로 처리*를 선언합니다. `FastAPI` 클래스를 사용할 때와 동일한 방식으로 사용합니다: @@ -107,7 +107,7 @@ from app.routers import items /// -이제 이 `APIRouter`를 메인 `FastAPI` 앱에 포함(include)할 것이지만, 먼저 dependencies와 다른 `APIRouter` 하나를 확인해 보겠습니다. +이제 이 `APIRouter`를 메인 `FastAPI` 애플리케이션에 포함(include)할 것이지만, 먼저 dependencies와 다른 `APIRouter` 하나를 확인해 보겠습니다. ## Dependencies { #dependencies } @@ -131,7 +131,7 @@ from app.routers import items 애플리케이션의 "items"를 처리하는 전용 endpoint들도 `app/routers/items.py` 모듈에 있다고 해봅시다. -여기에는 다음에 대한 *path operations*가 있습니다: +여기에는 다음에 대한 *경로 처리*가 있습니다: * `/items/` * `/items/{item_id}` @@ -140,18 +140,18 @@ from app.routers import items 하지만 우리는 조금 더 똑똑하게, 코드를 약간 단순화하고 싶습니다. -이 모듈의 모든 *path operations*에는 다음이 동일하게 적용됩니다: +이 모듈의 모든 *경로 처리*에는 다음이 동일하게 적용됩니다: * 경로 `prefix`: `/items`. * `tags`: (태그 하나: `items`). * 추가 `responses`. * `dependencies`: 모두 우리가 만든 `X-Token` dependency가 필요합니다. -따라서 각 *path operation*마다 매번 모두 추가하는 대신, `APIRouter`에 한 번에 추가할 수 있습니다. +따라서 각 *경로 처리*마다 매번 모두 추가하는 대신, `APIRouter`에 한 번에 추가할 수 있습니다. {* ../../docs_src/bigger_applications/app_an_py310/routers/items.py hl[5:10,16,21] title["app/routers/items.py"] *} -각 *path operation*의 경로는 다음처럼 `/`로 시작해야 하므로: +각 *경로 처리*의 경로는 다음처럼 `/`로 시작해야 하므로: ```Python hl_lines="1" @router.get("/{item_id}") @@ -163,13 +163,13 @@ async def read_item(item_id: str): 따라서 이 경우 prefix는 `/items`입니다. -또한 이 router에 포함된 모든 *path operations*에 적용될 `tags` 목록과 추가 `responses`도 넣을 수 있습니다. +또한 이 router에 포함된 모든 *경로 처리*에 적용될 `tags` 목록과 추가 `responses`도 넣을 수 있습니다. -그리고 router의 모든 *path operations*에 추가될 `dependencies` 목록도 추가할 수 있으며, 해당 경로들로 들어오는 각 요청마다 실행/해결됩니다. +그리고 router의 모든 *경로 처리*에 추가될 `dependencies` 목록도 추가할 수 있으며, 해당 경로들로 들어오는 각 요청마다 실행/해결됩니다. /// tip | 팁 -[*path operation decorator의 dependencies*](dependencies/dependencies-in-path-operation-decorators.md)와 마찬가지로, *path operation function*에 어떤 값도 전달되지 않습니다. +[*경로 처리 데코레이터*의 dependencies](dependencies/dependencies-in-path-operation-decorators.md)와 마찬가지로, *경로 처리 함수*에 어떤 값도 전달되지 않습니다. /// @@ -183,14 +183,14 @@ async def read_item(item_id: str): * 단일 문자열 `"items"`를 포함하는 태그 목록으로 표시됩니다. * 이 "tags"는 자동 대화형 문서 시스템(OpenAPI 사용)에 특히 유용합니다. * 모두 미리 정의된 `responses`를 포함합니다. -* 이 모든 *path operations*는 실행되기 전에 `dependencies` 목록이 평가/실행됩니다. - * 특정 *path operation*에 dependencies를 추가로 선언하면 **그것들도 실행됩니다**. - * router dependencies가 먼저 실행되고, 그 다음에 [decorator의 `dependencies`](dependencies/dependencies-in-path-operation-decorators.md), 그리고 일반 파라미터 dependencies가 실행됩니다. +* 이 모든 *경로 처리*는 실행되기 전에 `dependencies` 목록이 평가/실행됩니다. + * 특정 *경로 처리*에 dependencies를 추가로 선언하면 **그것들도 실행됩니다**. + * router dependencies가 먼저 실행되고, 그 다음에 [데코레이터의 `dependencies`](dependencies/dependencies-in-path-operation-decorators.md), 그리고 일반 파라미터 dependencies가 실행됩니다. * [`scopes`가 있는 `Security` dependencies](../advanced/security/oauth2-scopes.md)도 추가할 수 있습니다. /// tip | 팁 -`APIRouter`에 `dependencies`를 두는 것은 예를 들어 전체 *path operations* 그룹에 인증을 요구할 때 사용할 수 있습니다. 각 경로 처리에 개별적으로 dependencies를 추가하지 않아도 됩니다. +`APIRouter`에 `dependencies`를 두는 것은 예를 들어 전체 *경로 처리* 그룹에 인증을 요구할 때 사용할 수 있습니다. 각 경로 처리에 개별적으로 dependencies를 추가하지 않아도 됩니다. /// @@ -232,7 +232,7 @@ from .dependencies import get_token_header 하지만 그 파일은 존재하지 않습니다. dependencies는 `app/dependencies.py` 파일에 있습니다. -우리 앱/파일 구조를 다시 떠올려 보세요: +우리 애플리케이션/파일 구조를 다시 떠올려 보세요: @@ -271,13 +271,13 @@ from ...dependencies import get_token_header 이는 `app/` 위쪽의 어떤 package(자신의 `__init__.py` 파일 등을 가진)에 대한 참조가 됩니다. 하지만 우리는 그런 것이 없습니다. 그래서 이 예시에서는 에러가 발생합니다. 🚨 -이제 어떻게 동작하는지 알았으니, 앱이 얼마나 복잡하든 상대 import를 사용할 수 있습니다. 🤓 +이제 어떻게 동작하는지 알았으니, 애플리케이션이 얼마나 복잡하든 상대 import를 사용할 수 있습니다. 🤓 ### 커스텀 `tags`, `responses`, `dependencies` 추가하기 { #add-some-custom-tags-responses-and-dependencies } -`APIRouter`에 이미 prefix `/items`와 `tags=["items"]`를 추가했기 때문에 각 *path operation*에 이를 추가하지 않습니다. +`APIRouter`에 이미 prefix `/items`와 `tags=["items"]`를 추가했기 때문에 각 *경로 처리*에 이를 추가하지 않습니다. -하지만 특정 *path operation*에만 적용될 _추가_ `tags`를 더할 수도 있고, 그 *path operation* 전용의 추가 `responses`도 넣을 수 있습니다: +하지만 특정 *경로 처리*에만 적용될 _추가_ `tags`를 더할 수도 있고, 그 *경로 처리* 전용의 추가 `responses`도 넣을 수 있습니다: {* ../../docs_src/bigger_applications/app_an_py310/routers/items.py hl[30:31] title["app/routers/items.py"] *} @@ -396,9 +396,9 @@ from .routers.users import router /// note | 기술 세부사항 -내부적으로는 `APIRouter`에 선언된 각 *path operation*마다 *path operation*을 실제로 생성합니다. +FastAPI는 메인 애플리케이션에 router를 포함해도 원래의 `APIRouter`와 그 `APIRoute`들을 활성 상태로 유지합니다. -즉, 내부적으로는 모든 것이 동일한 하나의 앱인 것처럼 동작합니다. +즉, 커스텀 `APIRouter`와 `APIRoute` 서브클래스가 포함된 이후에도 계속 작동할 수 있습니다. /// @@ -406,7 +406,7 @@ from .routers.users import router router를 포함(include)할 때 성능을 걱정할 필요는 없습니다. -이 작업은 마이크로초 단위이며 시작 시에만 발생합니다. +이 기능은 매우 가볍게 설계되었고 각 요청에 오버헤드를 추가하지 않도록 되어 있습니다. 따라서 성능에 영향을 주지 않습니다. ⚡ @@ -416,13 +416,13 @@ router를 포함(include)할 때 성능을 걱정할 필요는 없습니다. 이제 조직에서 `app/internal/admin.py` 파일을 받았다고 가정해 봅시다. -여기에는 조직에서 여러 프로젝트 간에 공유하는 관리자용 *path operations*가 있는 `APIRouter`가 들어 있습니다. +여기에는 조직에서 여러 프로젝트 간에 공유하는 관리자용 *경로 처리*가 있는 `APIRouter`가 들어 있습니다. 이 예시에서는 매우 단순하게 만들겠습니다. 하지만 조직 내 다른 프로젝트와 공유되기 때문에, 이를 수정할 수 없어 `prefix`, `dependencies`, `tags` 등을 `APIRouter`에 직접 추가할 수 없다고 해봅시다: {* ../../docs_src/bigger_applications/app_an_py310/internal/admin.py hl[3] title["app/internal/admin.py"] *} -하지만 `APIRouter`를 포함할 때 커스텀 `prefix`를 지정해 모든 *path operations*가 `/admin`으로 시작하게 하고, 이 프로젝트에서 이미 가진 `dependencies`로 보호하고, `tags`와 `responses`도 포함하고 싶습니다. +하지만 `APIRouter`를 포함할 때 커스텀 `prefix`를 지정해 모든 *경로 처리*가 `/admin`으로 시작하게 하고, 이 프로젝트에서 이미 가진 `dependencies`로 보호하고, `tags`와 `responses`도 포함하고 싶습니다. 원래 `APIRouter`를 수정하지 않고도 `app.include_router()`에 파라미터를 전달해서 이를 선언할 수 있습니다: @@ -430,26 +430,26 @@ router를 포함(include)할 때 성능을 걱정할 필요는 없습니다. 이렇게 하면 원래 `APIRouter`는 수정되지 않으므로, 조직 내 다른 프로젝트에서도 동일한 `app/internal/admin.py` 파일을 계속 공유할 수 있습니다. -결과적으로 우리 앱에서 `admin` 모듈의 각 *path operations*는 다음을 갖게 됩니다: +결과적으로 우리 애플리케이션에서 `admin` 모듈의 각 *경로 처리*는 다음을 갖게 됩니다: * prefix `/admin`. * tag `admin`. * dependency `get_token_header`. * 응답 `418`. 🍵 -하지만 이는 우리 앱에서 그 `APIRouter`에만 영향을 주며, 이를 사용하는 다른 코드에는 영향을 주지 않습니다. +하지만 이는 우리 애플리케이션에서 그 `APIRouter`에만 영향을 주며, 이를 사용하는 다른 코드에는 영향을 주지 않습니다. 따라서 다른 프로젝트들은 같은 `APIRouter`를 다른 인증 방식으로 사용할 수도 있습니다. -### *path operation* 포함하기 { #include-a-path-operation } +### *경로 처리* 포함하기 { #include-a-path-operation } -*path operations*를 `FastAPI` 앱에 직접 추가할 수도 있습니다. +*경로 처리*를 `FastAPI` 애플리케이션에 직접 추가할 수도 있습니다. 여기서는 가능하다는 것을 보여주기 위해... 그냥 해봅니다 🤷: {* ../../docs_src/bigger_applications/app_an_py310/main.py hl[21:23] title["app/main.py"] *} -그리고 `app.include_router()`로 추가한 다른 모든 *path operations*와 함께 올바르게 동작합니다. +그리고 `app.include_router()`로 추가한 다른 모든 *경로 처리*와 함께 올바르게 동작합니다. /// note | 매우 기술적인 세부사항 @@ -459,9 +459,9 @@ router를 포함(include)할 때 성능을 걱정할 필요는 없습니다. `APIRouter`는 "mount"되는 것이 아니며, 애플리케이션의 나머지 부분과 격리되어 있지 않습니다. -이는 OpenAPI 스키마와 사용자 인터페이스에 그들의 *path operations*를 포함시키고 싶기 때문입니다. +이는 OpenAPI 스키마와 사용자 인터페이스에 그들의 *경로 처리*를 포함시키기 위함입니다. -나머지와 독립적으로 격리해 "mount"할 수 없으므로, *path operations*는 직접 포함되는 것이 아니라 "clone"(재생성)됩니다. +FastAPI는 원래의 router와 경로 처리를 활성 상태로 유지하고, 요청을 처리하고 OpenAPI를 생성할 때 router의 prefix, dependencies, tags, responses 및 기타 메타데이터를 결합합니다. /// @@ -480,7 +480,7 @@ entrypoint = "app.main:app" from app.main import app ``` -이렇게 하면 `fastapi` 명령어가 여러분의 앱이 어디에 있는지 알 수 있습니다. +이렇게 하면 `fastapi` 명령어가 여러분의 애플리케이션이 어디에 있는지 알 수 있습니다. /// Note | 참고 @@ -498,7 +498,7 @@ $ fastapi dev app/main.py ## 자동 API 문서 확인하기 { #check-the-automatic-api-docs } -이제 앱을 실행하세요: +이제 애플리케이션을 실행하세요:
@@ -532,4 +532,16 @@ $ fastapi dev router.include_router(other_router) ``` -`FastAPI` 앱에 `router`를 포함하기 전에 수행해야 하며, 그래야 `other_router`의 *path operations*도 함께 포함됩니다. +`router`를 `FastAPI` 애플리케이션에 포함하기 전이든 후든, 어느 시점에 해도 됩니다. FastAPI는 라우팅과 OpenAPI에 `other_router`의 *경로 처리*도 포함합니다. + +나중에 router들에 추가된 *경로 처리*도 동일하게 적용됩니다. 이전에 수행한 포함을 통해서도 보이게 됩니다. + +/// warning | 기술 세부사항 + +router를 포함한 뒤에 `router.routes`를 직접 변형하는 것은 피하세요. FastAPI는 router 포함을 실시간으로 처리하므로, 원래 router와 그 routes는 라우팅과 OpenAPI 생성의 일부로 남아 있습니다. + +경로와 router를 추가할 때는 경로 처리 데코레이터와 `.include_router()` 같은 문서화된 API를 사용하세요. + +`router.routes`는 최종 *경로 처리*의 평탄화된 목록이 아니라, route 정의와 포함된 router를 담는 하위 수준의 트리로 취급하고, 여기에 의존하지 마세요. + +/// diff --git a/docs/ko/docs/tutorial/body-multiple-params.md b/docs/ko/docs/tutorial/body-multiple-params.md index 3db614d72..c686e8a5a 100644 --- a/docs/ko/docs/tutorial/body-multiple-params.md +++ b/docs/ko/docs/tutorial/body-multiple-params.md @@ -111,7 +111,7 @@ q: str | None = None {* ../../docs_src/body_multiple_params/tutorial004_an_py310.py hl[28] *} -/// info | 정보 +/// note | 참고 `Body` 또한 `Query`, `Path` 그리고 이후에 볼 다른 것들과 마찬가지로 동일한 추가 검증과 메타데이터 매개변수를 모두 갖고 있습니다. @@ -126,7 +126,7 @@ Pydantic 모델 `Item`에서 가져온 단일 `item` 본문 매개변수만 있 하지만 추가 본문 매개변수를 선언할 때처럼, `item` 키를 가지고 그 안에 모델 내용이 들어 있는 JSON을 예상하게 하려면, `Body`의 특별한 매개변수 `embed`를 사용할 수 있습니다: ```Python -item: Item = Body(embed=True) +item: Annotated[Item, Body(embed=True)] ``` 다음과 같이요: diff --git a/docs/ko/docs/tutorial/body-nested-models.md b/docs/ko/docs/tutorial/body-nested-models.md index bbb95cf00..7ca6305c3 100644 --- a/docs/ko/docs/tutorial/body-nested-models.md +++ b/docs/ko/docs/tutorial/body-nested-models.md @@ -136,7 +136,7 @@ Pydantic 모델의 각 어트리뷰트는 타입을 갖습니다. } ``` -/// info | 정보 +/// note | 참고 `images` 키가 이제 이미지 객체 리스트를 갖는지 주목하세요. @@ -148,7 +148,7 @@ Pydantic 모델의 각 어트리뷰트는 타입을 갖습니다. {* ../../docs_src/body_nested_models/tutorial007_py310.py hl[7,12,18,21,25] *} -/// info | 정보 +/// note | 참고 `Offer`가 `Item`의 리스트를 가지고, 그 `Item`이 다시 선택 사항인 `Image` 리스트를 갖는지 주목하세요 @@ -182,7 +182,7 @@ Pydantic 모델 대신 `dict`로 직접 작업한다면 이런 종류의 편집 또한 키는 어떤 타입이고 값은 다른 타입인 `dict`로 본문을 선언할 수 있습니다. -이렇게 하면 (Pydantic 모델을 사용하는 경우처럼) 유효한 필드/어트리뷰트 이름이 무엇인지 미리 알 필요가 없습니다. +이렇게 하면 (Pydantic 모델을 사용하는 경우와 달리) 유효한 필드/어트리뷰트 이름이 무엇인지 미리 알 필요가 없습니다. 아직 모르는 키를 받으려는 경우에 유용합니다. diff --git a/docs/ko/docs/tutorial/body.md b/docs/ko/docs/tutorial/body.md index d124b4bef..dde070807 100644 --- a/docs/ko/docs/tutorial/body.md +++ b/docs/ko/docs/tutorial/body.md @@ -8,9 +8,9 @@ **요청** 본문을 선언하기 위해서 모든 강력함과 이점을 갖춘 [Pydantic](https://docs.pydantic.dev/) 모델을 사용합니다. -/// info | 정보 +/// note | 참고 -데이터를 보내기 위해, (좀 더 보편적인) `POST`, `PUT`, `DELETE` 혹은 `PATCH` 중에 하나를 사용하는 것이 좋습니다. +데이터를 보내기 위해, `POST` (가장 일반적), `PUT`, `DELETE` 혹은 `PATCH` 중에 하나를 사용하는 것이 좋습니다. `GET` 요청에 본문을 담아 보내는 것은 명세서에 정의되지 않은 행동입니다. 그럼에도 불구하고, 이 방식은 아주 복잡한/극한의 사용 상황에서만 FastAPI에 의해 지원됩니다. @@ -88,7 +88,7 @@ ## 편집기 지원 { #editor-support } -편집기에서, 함수 내에서 타입 힌트와 완성을 어디서나 (만약 Pydantic model 대신에 `dict`을 받을 경우 나타나지 않을 수 있습니다) 받을 수 있습니다: +편집기에서, 함수 내에서 타입 힌트와 완성을 어디서나 (만약 Pydantic 모델 대신에 `dict`을 받을 경우 나타나지 않을 수 있습니다) 받을 수 있습니다: @@ -141,14 +141,14 @@ **본문**, **경로** 그리고 **쿼리** 매개변수 모두 동시에 선언할 수도 있습니다. -**FastAPI**는 각각을 인지하고 데이터를 올바른 위치에 가져올 것입니다. +**FastAPI**는 각각을 인지하고 데이터를 올바른 위치에서 가져올 것입니다. {* ../../docs_src/body/tutorial004_py310.py hl[16] *} 함수 매개변수는 다음을 따라서 인지하게 됩니다: * 만약 매개변수가 **경로**에도 선언되어 있다면, 이는 경로 매개변수로 사용될 것입니다. -* 만약 매개변수가 (`int`, `float`, `str`, `bool` 등과 같은) **유일한 타입**으로 되어있으면, **쿼리** 매개변수로 해석될 것입니다. +* 만약 매개변수가 (`int`, `float`, `str`, `bool` 등과 같은) **단일 타입**으로 되어있으면, **쿼리** 매개변수로 해석될 것입니다. * 만약 매개변수가 **Pydantic 모델** 타입으로 선언되어 있으면, 요청 **본문**으로 해석될 것입니다. /// note | 참고 @@ -163,4 +163,4 @@ FastAPI는 `q`의 값이 필요없음을 기본 값 `= None` 때문에 알게 ## Pydantic없이 { #without-pydantic } -만약 Pydantic 모델을 사용하고 싶지 않다면, **Body** 매개변수를 사용할 수도 있습니다. [Body - Multiple Parameters: Singular values in body](body-multiple-params.md#singular-values-in-body) 문서를 확인하세요. +만약 Pydantic 모델을 사용하고 싶지 않다면, **Body** 매개변수를 사용할 수도 있습니다. [Body - 여러 매개변수: 본문의 단일 값](body-multiple-params.md#singular-values-in-body) 문서를 확인하세요. diff --git a/docs/ko/docs/tutorial/cookie-param-models.md b/docs/ko/docs/tutorial/cookie-param-models.md index 70b76e09c..2105bea86 100644 --- a/docs/ko/docs/tutorial/cookie-param-models.md +++ b/docs/ko/docs/tutorial/cookie-param-models.md @@ -32,7 +32,7 @@
-/// info | 정보 +/// note | 참고 명심하세요, 내부적으로 **브라우저는 쿠키를 특별한 방식으로 처리**하기 때문에 **자바스크립트**가 쉽게 쿠키를 건드릴 수 **없습니다**. diff --git a/docs/ko/docs/tutorial/cookie-params.md b/docs/ko/docs/tutorial/cookie-params.md index 6ea09101c..223d896e0 100644 --- a/docs/ko/docs/tutorial/cookie-params.md +++ b/docs/ko/docs/tutorial/cookie-params.md @@ -24,13 +24,13 @@ /// -/// info +/// note 쿠키를 선언하기 위해서는 `Cookie`를 사용해야 합니다. 그렇지 않으면 해당 매개변수를 쿼리 매개변수로 해석하기 때문입니다. /// -/// info +/// note **브라우저는 쿠키를** 내부적으로 특별한 방식으로 처리하기 때문에, **JavaScript**가 쉽게 쿠키를 다루도록 허용하지 않는다는 점을 염두에 두세요. diff --git a/docs/ko/docs/tutorial/debugging.md b/docs/ko/docs/tutorial/debugging.md index f437286b2..c3d06c0b8 100644 --- a/docs/ko/docs/tutorial/debugging.md +++ b/docs/ko/docs/tutorial/debugging.md @@ -59,7 +59,7 @@ Python에 의해 자동으로 생성된 파일의 내부 변수 `__name__`은 ```Python from myapp import app -# Some more code +# 추가 코드 ``` 이 경우 `myapp.py` 내부의 자동 변수 `__name__`에는 값이 `"__main__"`이 들어가지 않습니다. @@ -99,7 +99,7 @@ from myapp import app --- -Pycharm을 사용하는 경우 다음을 수행할 수 있습니다 +PyCharm을 사용하는 경우 다음을 수행할 수 있습니다 * "Run" 메뉴를 엽니다. * "Debug..." 옵션을 선택합니다. diff --git a/docs/ko/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md b/docs/ko/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md index 880a47157..f31a57586 100644 --- a/docs/ko/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md +++ b/docs/ko/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md @@ -28,7 +28,7 @@ /// -/// info | 정보 +/// note | 참고 이 예시에서 `X-Key`와 `X-Token`이라는 커스텀 헤더를 만들어 사용했습니다. diff --git a/docs/ko/docs/tutorial/dependencies/dependencies-with-yield.md b/docs/ko/docs/tutorial/dependencies/dependencies-with-yield.md index 56f690f59..67405ff6c 100644 --- a/docs/ko/docs/tutorial/dependencies/dependencies-with-yield.md +++ b/docs/ko/docs/tutorial/dependencies/dependencies-with-yield.md @@ -4,7 +4,7 @@ FastAPI는 union이 있는 경우에도 동일합니다. 예를 들어, 아래는 실패합니다 💥: +또한, 유효한 Pydantic 타입이 아닌 타입이 하나 이상 포함된 여러 타입 간의 유니온이 있는 경우에도 동일합니다. 예를 들어, 아래는 실패합니다 💥: {* ../../docs_src/response_model/tutorial003_04_py310.py hl[8] *} -...이는 타입 어노테이션이 Pydantic 타입이 아니고, 단일 `Response` 클래스/서브클래스도 아니며, `Response`와 `dict` 간 union(둘 중 아무거나)이기 때문에 실패합니다. +...이는 타입 어노테이션이 Pydantic 타입이 아니고, 단일 `Response` 클래스/서브클래스도 아니며, `Response`와 `dict` 간 유니온(둘 중 아무거나)이기 때문에 실패합니다. ### 응답 모델 비활성화 { #disable-response-model } @@ -251,7 +251,7 @@ FastAPI는 Pydantic을 내부적으로 여러 방식으로 사용하여, 클래 } ``` -/// info | 정보 +/// note | 참고 다음도 사용할 수 있습니다: diff --git a/docs/ko/docs/tutorial/response-status-code.md b/docs/ko/docs/tutorial/response-status-code.md index 68db66e33..f8d46b945 100644 --- a/docs/ko/docs/tutorial/response-status-code.md +++ b/docs/ko/docs/tutorial/response-status-code.md @@ -1,5 +1,6 @@ # 응답 상태 코드 { #response-status-code } + 응답 모델을 지정하는 것과 같은 방법으로, 어떤 *경로 처리*에서든 `status_code` 매개변수를 사용하여 응답에 사용할 HTTP 상태 코드를 선언할 수도 있습니다: * `@app.get()` @@ -12,13 +13,13 @@ /// note | 참고 -`status_code` 는 "데코레이터" 메소드(`get`, `post` 등)의 매개변수입니다. 모든 매개변수들과 본문처럼 *경로 처리 함수*가 아닙니다. +`status_code` 는 "데코레이터" 메소드(`get`, `post` 등)의 매개변수입니다. 다른 매개변수나 본문과 달리, *경로 처리 함수*의 매개변수가 아닙니다. /// `status_code` 매개변수는 HTTP 상태 코드를 숫자로 입력받습니다. -/// info | 정보 +/// note | 참고 `status_code` 는 파이썬의 [`http.HTTPStatus`](https://docs.python.org/3/library/http.html#http.HTTPStatus) 와 같은 `IntEnum` 을 입력받을 수도 있습니다. diff --git a/docs/ko/docs/tutorial/schema-extra-example.md b/docs/ko/docs/tutorial/schema-extra-example.md index ffa97375d..039bee079 100644 --- a/docs/ko/docs/tutorial/schema-extra-example.md +++ b/docs/ko/docs/tutorial/schema-extra-example.md @@ -1,6 +1,6 @@ # 요청 예제 데이터 선언 { #declare-request-example-data } -여러분의 앱이 받을 수 있는 데이터 예제를 선언할 수 있습니다. +여러분의 애플리케이션이 받을 수 있는 데이터 예제를 선언할 수 있습니다. 여기 이를 위한 몇 가지 방식이 있습니다. @@ -24,7 +24,7 @@ JSON 스키마를 확장하고 여러분의 별도의 자체 데이터를 추가 /// -/// info | 정보 +/// note | 참고 (FastAPI 0.99.0부터 쓰이기 시작한) OpenAPI 3.1.0은 **JSON 스키마** 표준의 일부인 `examples`에 대한 지원을 추가했습니다. @@ -155,7 +155,7 @@ OpenAPI는 또한 `example`과 `examples` 필드를 명세서의 다른 부분 * `File()` * `Form()` -/// info | 정보 +/// note | 참고 이 예전 OpenAPI-특화 `examples` 매개변수는 이제 FastAPI `0.103.0`부터 `openapi_examples`입니다. @@ -171,7 +171,7 @@ OpenAPI는 또한 `example`과 `examples` 필드를 명세서의 다른 부분 JSON 스키마의 새로운 `examples` 필드는 예제의 **단순한 `list`**일 뿐이며, (위에서 상술한 것처럼) OpenAPI의 다른 곳에 존재하는 추가 메타데이터가 있는 dict가 아닙니다. -/// info | 정보 +/// note | 참고 더 쉽고 새로운 JSON 스키마와의 통합과 함께 OpenAPI 3.1.0가 배포되었지만, 잠시동안 자동 문서 생성을 제공하는 도구인 Swagger UI는 OpenAPI 3.1.0을 지원하지 않았습니다 (5.0.0 버전부터 지원합니다 🎉). diff --git a/docs/ko/docs/tutorial/security/first-steps.md b/docs/ko/docs/tutorial/security/first-steps.md index 8b7563ec3..d8050968d 100644 --- a/docs/ko/docs/tutorial/security/first-steps.md +++ b/docs/ko/docs/tutorial/security/first-steps.md @@ -1,5 +1,6 @@ # 보안 - 첫 단계 { #security-first-steps } + 어떤 도메인에 **backend** API가 있다고 가정해 보겠습니다. 그리고 다른 도메인에 **frontend**가 있거나, 같은 도메인의 다른 경로에 있거나(또는 모바일 애플리케이션에 있을 수도 있습니다). @@ -24,7 +25,7 @@ ## 실행하기 { #run-it } -/// info | 정보 +/// note | 참고 [`python-multipart`](https://github.com/Kludex/python-multipart) 패키지는 `pip install "fastapi[standard]"` 명령을 실행하면 **FastAPI**와 함께 자동으로 설치됩니다. @@ -60,7 +61,7 @@ $ fastapi dev -/// check | Authorize 버튼! +/// tip | Authorize 버튼! 반짝이는 새 "Authorize" 버튼이 이미 있습니다. @@ -118,7 +119,7 @@ OAuth2는 backend 또는 API가 사용자를 인증하는 서버와 독립적일 이 예제에서는 **OAuth2**의 **Password** 플로우와 **Bearer** token을 사용합니다. 이를 위해 `OAuth2PasswordBearer` 클래스를 사용합니다. -/// info | 정보 +/// note | 참고 "bearer" token만이 유일한 선택지는 아닙니다. @@ -148,7 +149,7 @@ OAuth2는 backend 또는 API가 사용자를 인증하는 서버와 독립적일 곧 실제 경로 처리를 만들 것입니다. -/// info | 정보 +/// note | 참고 엄격한 "Pythonista"라면 `token_url` 대신 `tokenUrl` 같은 파라미터 이름 스타일이 마음에 들지 않을 수도 있습니다. @@ -176,7 +177,7 @@ oauth2_scheme(some, parameters) **FastAPI**는 이 의존성을 사용해 OpenAPI 스키마(및 자동 API 문서)에 "security scheme"를 정의할 수 있다는 것을 알게 됩니다. -/// info | 기술 세부사항 +/// note | 기술 세부사항 **FastAPI**는 (의존성에 선언된) `OAuth2PasswordBearer` 클래스를 사용해 OpenAPI에서 보안 스킴을 정의할 수 있다는 것을 알고 있습니다. 이는 `OAuth2PasswordBearer`가 `fastapi.security.oauth2.OAuth2`를 상속하고, 이것이 다시 `fastapi.security.base.SecurityBase`를 상속하기 때문입니다. diff --git a/docs/ko/docs/tutorial/security/get-current-user.md b/docs/ko/docs/tutorial/security/get-current-user.md index eab599e27..4ff6ab4d2 100644 --- a/docs/ko/docs/tutorial/security/get-current-user.md +++ b/docs/ko/docs/tutorial/security/get-current-user.md @@ -14,7 +14,7 @@ Pydantic을 사용해 본문을 선언하는 것과 같은 방식으로, 다른 곳에서도 어디서든 사용할 수 있습니다: -{* ../../docs_src/security/tutorial002_an_py310.py hl[5,12:6] *} +{* ../../docs_src/security/tutorial002_an_py310.py hl[5,12:16] *} ## `get_current_user` 의존성 생성하기 { #create-a-get-current-user-dependency } @@ -52,7 +52,7 @@ Pydantic을 사용해 본문을 선언하는 것과 같은 방식으로, 다른 /// -/// check | 확인 +/// tip | 팁 이 의존성 시스템이 설계된 방식은 모두 `User` 모델을 반환하는 서로 다른 의존성(서로 다른 "dependables")을 가질 수 있도록 합니다. diff --git a/docs/ko/docs/tutorial/security/oauth2-jwt.md b/docs/ko/docs/tutorial/security/oauth2-jwt.md index 3c3b93e3a..f0b0176e0 100644 --- a/docs/ko/docs/tutorial/security/oauth2-jwt.md +++ b/docs/ko/docs/tutorial/security/oauth2-jwt.md @@ -1,6 +1,7 @@ # 패스워드(해싱 포함)를 사용하는 OAuth2, JWT 토큰을 사용하는 Bearer { #oauth2-with-password-and-hashing-bearer-with-jwt-tokens } -모든 보안 흐름을 구성했으므로, 이제 JWT 토큰과 안전한 패스워드 해싱을 사용해 애플리케이션을 실제로 안전하게 만들겠습니다. + +모든 보안 흐름을 구성했으므로, 이제 JWT 토큰과 안전한 패스워드 해싱을 사용해 애플리케이션을 실제로 안전하게 만들겠습니다. 이 코드는 실제로 애플리케이션에서 사용할 수 있으며, 패스워드 해시를 데이터베이스에 저장하는 등의 작업에 활용할 수 있습니다. @@ -42,7 +43,7 @@ $ pip install pyjwt
-/// info | 정보 +/// note | 참고 RSA나 ECDSA 같은 전자 서명 알고리즘을 사용할 계획이라면, cryptography 라이브러리 의존성인 `pyjwt[crypto]`를 설치해야 합니다. @@ -213,7 +214,7 @@ JWT는 사용자를 식별하고 사용자가 API에서 직접 작업을 수행 Username: `johndoe` Password: `secret` -/// check | 확인 +/// tip | 팁 코드 어디에도 평문 패스워드 "`secret`"은 없고, 해시된 버전만 있다는 점에 유의하십시오. diff --git a/docs/ko/docs/tutorial/security/simple-oauth2.md b/docs/ko/docs/tutorial/security/simple-oauth2.md index 48361de83..5901f2d09 100644 --- a/docs/ko/docs/tutorial/security/simple-oauth2.md +++ b/docs/ko/docs/tutorial/security/simple-oauth2.md @@ -6,7 +6,7 @@ **FastAPI** 보안 유틸리티를 사용하여 `username` 및 `password`를 가져올 것입니다. -OAuth2는 (우리가 사용하고 있는) "패스워드 플로우"을 사용할 때 클라이언트/유저가 `username` 및 `password` 필드를 폼 데이터로 보내야 함을 지정합니다. +OAuth2는 (우리가 사용하고 있는) "패스워드 플로우"를 사용할 때 클라이언트/유저가 `username` 및 `password` 필드를 폼 데이터로 보내야 함을 지정합니다. 그리고 사양에는 필드의 이름을 그렇게 지정해야 한다고 나와 있습니다. 따라서 `user-name` 또는 `email`은 작동하지 않습니다. @@ -32,7 +32,7 @@ OAuth2는 (우리가 사용하고 있는) "패스워드 플로우"을 사용할 * `instagram_basic`은 페이스북/인스타그램에서 사용합니다. * `https://www.googleapis.com/auth/drive`는 Google에서 사용합니다. -/// info | 정보 +/// note | 참고 OAuth2에서 "범위"는 필요한 특정 권한을 선언하는 문자열입니다. @@ -72,7 +72,7 @@ OAuth2 사양은 실제로 `password`라는 고정 값이 있는 `grant_type` * `client_id`(선택적으로 사용) (예제에서는 필요하지 않습니다). * `client_secret`(선택적으로 사용) (예제에서는 필요하지 않습니다). -/// info | 정보 +/// note | 참고 `OAuth2PasswordRequestForm`은 `OAuth2PasswordBearer`와 같이 **FastAPI**에 대한 특수 클래스가 아닙니다. @@ -104,7 +104,7 @@ OAuth2 사양은 실제로 `password`라는 고정 값이 있는 `grant_type` ### 패스워드 확인하기 { #check-the-password } -이 시점에서 데이터베이스의 사용자 데이터 형식을 확인했지만 암호를 확인하지 않았습니다. +이 시점에서 데이터베이스의 사용자 데이터는 있지만, 아직 패스워드는 확인하지 않았습니다. 먼저 데이터를 Pydantic `UserInDB` 모델에 넣겠습니다. @@ -144,9 +144,9 @@ UserInDB( ) ``` -/// info | 정보 +/// note | 참고 -`**user_dict`에 대한 자세한 설명은 [**추가 모델** 문서](../extra-models.md#about-user-in-dict)를 다시 확인해보세요. +`**user_dict`에 대한 자세한 설명은 [**추가 모델** 문서](../extra-models.md#about-user-in-model-dump)를 다시 확인해보세요. /// @@ -196,7 +196,7 @@ UserInDB( {* ../../docs_src/security/tutorial003_an_py310.py hl[58:66,69:74,94] *} -/// info | 정보 +/// note | 참고 여기서 반환하는 값이 `Bearer`인 추가 헤더 `WWW-Authenticate`도 사양의 일부입니다. diff --git a/docs/ko/docs/tutorial/server-sent-events.md b/docs/ko/docs/tutorial/server-sent-events.md index a8ae1180f..abcabd997 100644 --- a/docs/ko/docs/tutorial/server-sent-events.md +++ b/docs/ko/docs/tutorial/server-sent-events.md @@ -4,7 +4,7 @@ 이는 [JSON Lines 스트리밍](stream-json-lines.md)과 비슷하지만, 브라우저가 기본적으로 [`EventSource` API](https://developer.mozilla.org/en-US/docs/Web/API/EventSource)를 통해 지원하는 `text/event-stream` 형식을 사용합니다. -/// info | 정보 +/// note | 참고 FastAPI 0.135.0에 추가되었습니다. diff --git a/docs/ko/docs/tutorial/sql-databases.md b/docs/ko/docs/tutorial/sql-databases.md index b046d14b5..6a48e3076 100644 --- a/docs/ko/docs/tutorial/sql-databases.md +++ b/docs/ko/docs/tutorial/sql-databases.md @@ -1,5 +1,6 @@ # SQL (관계형) 데이터베이스 { #sql-relational-databases } + **FastAPI**에서 SQL(관계형) 데이터베이스 사용은 필수가 아닙니다. 하지만 여러분이 원하는 **어떤 데이터베이스든** 사용할 수 있습니다. 여기서는 [SQLModel](https://sqlmodel.tiangolo.com/)을 사용하는 예제를 살펴보겠습니다. diff --git a/docs/ko/docs/tutorial/static-files.md b/docs/ko/docs/tutorial/static-files.md index d4c6f6c2d..b6f5bb938 100644 --- a/docs/ko/docs/tutorial/static-files.md +++ b/docs/ko/docs/tutorial/static-files.md @@ -2,6 +2,14 @@ `StaticFiles`를 사용하면 디렉터리에서 정적 파일을 자동으로 제공할 수 있습니다. +/// tip | 팁 + +프론트엔드를 호스팅해야 한다면 대신 `app.frontend()`를 사용하세요. 자세한 내용은 [프론트엔드](frontend.md)에서 확인하세요. + +`app.frontend()`는 내부적으로 `StaticFiles`를 사용하며, 클라이언트 사이드 라우팅 처리와 같은 프론트엔드를 위한 여러 추가 이점이 있습니다. + +/// + ## `StaticFiles` 사용 { #use-staticfiles } * `StaticFiles`를 임포트합니다. diff --git a/docs/ko/docs/tutorial/stream-json-lines.md b/docs/ko/docs/tutorial/stream-json-lines.md index 816338d7e..cc2e051db 100644 --- a/docs/ko/docs/tutorial/stream-json-lines.md +++ b/docs/ko/docs/tutorial/stream-json-lines.md @@ -2,7 +2,7 @@ 연속된 데이터를 "**스트림**"으로 보내고 싶다면 **JSON Lines**를 사용할 수 있습니다. -/// info +/// note FastAPI 0.134.0에 추가되었습니다. @@ -48,7 +48,7 @@ sequenceDiagram JSON 배열(Python의 list에 해당)과 매우 비슷하지만, 항목들을 `[]`로 감싸고 항목 사이에 `,`를 넣는 대신, 줄마다 하나의 JSON 객체가 있고, 새 줄 문자로 구분됩니다. -/// info +/// note 핵심은 애플리케이션이 각 줄을 차례로 생성하는 동안, 클라이언트는 이전 줄을 소비할 수 있다는 점입니다. diff --git a/docs/ko/docs/tutorial/testing.md b/docs/ko/docs/tutorial/testing.md index aab85580b..d6c627fb6 100644 --- a/docs/ko/docs/tutorial/testing.md +++ b/docs/ko/docs/tutorial/testing.md @@ -8,7 +8,7 @@ ## `TestClient` 사용하기 { #using-testclient } -/// info | 정보 +/// note | 참고 `TestClient` 사용하려면, 우선 [`httpx`](https://www.python-httpx.org)를 설치해야 합니다. @@ -62,7 +62,7 @@ FastAPI 애플리케이션에 요청을 보내는 것 외에도 테스트에서 그리고 **FastAPI** 애플리케이션도 여러 파일이나 모듈 등으로 구성될 수 있습니다. -### **FastAPI** app 파일 { #fastapi-app-file } +### **FastAPI** 애플리케이션 파일 { #fastapi-app-file } [더 큰 애플리케이션](bigger-applications.md)에 묘사된 파일 구조를 가지고 있는 것으로 가정해봅시다. @@ -73,7 +73,7 @@ FastAPI 애플리케이션에 요청을 보내는 것 외에도 테스트에서 │   └── main.py ``` -`main.py` 파일 안에 **FastAPI** app 을 만들었습니다: +`main.py` 파일 안에 **FastAPI** 애플리케이션이 있습니다: {* ../../docs_src/app_testing/app_a_py310/main.py *} @@ -101,7 +101,7 @@ FastAPI 애플리케이션에 요청을 보내는 것 외에도 테스트에서 이제 위의 예시를 확장하고 더 많은 세부 사항을 추가하여 다양한 부분을 어떻게 테스트하는지 살펴보겠습니다. -### 확장된 **FastAPI** app 파일 { #extended-fastapi-app-file } +### 확장된 **FastAPI** 애플리케이션 파일 { #extended-fastapi-app-file } 이전과 같은 파일 구조를 계속 사용해 보겠습니다. @@ -113,7 +113,7 @@ FastAPI 애플리케이션에 요청을 보내는 것 외에도 테스트에서 │   └── test_main.py ``` -이제 **FastAPI** 앱이 있는 `main.py` 파일에 몇 가지 다른 **경로 처리**가 추가된 경우를 생각해봅시다. +이제 **FastAPI** 애플리케이션이 있는 `main.py` 파일에 몇 가지 다른 **경로 처리**가 추가된 경우를 생각해봅시다. 오류를 반환할 수 있는 `GET` 작업이 있습니다. @@ -144,7 +144,7 @@ FastAPI 애플리케이션에 요청을 보내는 것 외에도 테스트에서 백엔드로 데이터를 어떻게 보내는지 정보를 더 얻으려면 (`httpx` 혹은 `TestClient`를 이용해서) [HTTPX 문서](https://www.python-httpx.org)를 확인하세요. -/// info | 정보 +/// note | 참고 `TestClient`는 Pydantic 모델이 아니라 JSON으로 변환될 수 있는 데이터를 받습니다. diff --git a/docs/ko/docs/virtual-environments.md b/docs/ko/docs/virtual-environments.md index d75ee8017..d2bf72ab8 100644 --- a/docs/ko/docs/virtual-environments.md +++ b/docs/ko/docs/virtual-environments.md @@ -1,5 +1,6 @@ # 가상 환경 { #virtual-environments } + Python 프로젝트를 작업할 때는 **가상 환경**(또는 이와 유사한 메커니즘)을 사용해 각 프로젝트마다 설치하는 패키지를 분리하는 것이 좋습니다. /// note | 참고 diff --git a/docs/pt/docs/_llm-test.md b/docs/pt/docs/_llm-test.md index 714c121b4..2e20e5b58 100644 --- a/docs/pt/docs/_llm-test.md +++ b/docs/pt/docs/_llm-test.md @@ -11,7 +11,7 @@ Use da seguinte forma: * Verifique se está tudo certo na tradução. * Se necessário, melhore seu prompt específico do idioma, o prompt geral ou o documento em inglês. * Em seguida, corrija manualmente os problemas restantes na tradução, para que fique uma boa tradução. -* Retraduzir, tendo a boa tradução no lugar. O resultado ideal seria que o LLM não fizesse mais mudanças na tradução. Isso significa que o prompt geral e o seu prompt específico do idioma estão tão bons quanto possível (às vezes fará algumas mudanças aparentemente aleatórias, a razão é que [LLMs não são algoritmos determinísticos](https://doublespeak.chat/#/handbook#deterministic-output)). +* Retraduza, tendo a boa tradução no lugar. O resultado ideal seria que o LLM não fizesse mais mudanças na tradução. Isso significa que o prompt geral e o seu prompt específico do idioma estão tão bons quanto possível (às vezes fará algumas mudanças aparentemente aleatórias, a razão é que [LLMs não são algoritmos determinísticos](https://doublespeak.chat/#/handbook#deterministic-output)). Os testes: @@ -189,15 +189,15 @@ Aqui estão algumas coisas envolvidas em elementos HTML "abbr" (algumas são inv ### O abbr fornece uma frase completa { #the-abbr-gives-a-full-phrase } -* GTD -* lt -* XWT -* PSGI +* GTD +* lt +* XWT +* PSGI ### O abbr fornece uma frase completa e uma explicação { #the-abbr-gives-a-full-phrase-and-an-explanation } -* MDN -* I/O. +* MDN +* I/O. //// diff --git a/docs/pt/docs/advanced/additional-responses.md b/docs/pt/docs/advanced/additional-responses.md index 1df4b9851..1e68134d3 100644 --- a/docs/pt/docs/advanced/additional-responses.md +++ b/docs/pt/docs/advanced/additional-responses.md @@ -34,7 +34,7 @@ Lembre-se que você deve retornar o `JSONResponse` diretamente. /// -/// info | Informação +/// note | Nota A chave `model` não é parte do OpenAPI. @@ -183,7 +183,7 @@ Note que você deve retornar a imagem utilizando um `FileResponse` diretamente. /// -/// info | Informação +/// note | Nota A menos que você especifique um media type diferente explicitamente em seu parâmetro `responses`, o FastAPI assumirá que o retorno possui o mesmo media type contido na classe principal de retorno (padrão `application/json`). diff --git a/docs/pt/docs/advanced/additional-status-codes.md b/docs/pt/docs/advanced/additional-status-codes.md index af1cefaf2..b702b8b41 100644 --- a/docs/pt/docs/advanced/additional-status-codes.md +++ b/docs/pt/docs/advanced/additional-status-codes.md @@ -30,12 +30,12 @@ Garanta que ele tenha toda informação que você deseja, e que os valores sejam Você também pode utilizar `from starlette.responses import JSONResponse`. -O **FastAPI** disponibiliza o `starlette.responses` como `fastapi.responses` apenas por conveniência para você, o programador. Porém a maioria dos retornos disponíveis vem diretamente do Starlette. O mesmo com `status`. +O **FastAPI** disponibiliza o `starlette.responses` como `fastapi.responses` apenas por conveniência para você, o programador. Porém a maioria das respostas disponíveis vem diretamente do Starlette. O mesmo com `status`. /// ## OpenAPI e documentação da API { #openapi-and-api-docs } -Se você retorna códigos de status adicionais e retornos diretamente, eles não serão incluídos no esquema do OpenAPI (a documentação da API), porque o FastAPI não tem como saber de antemão o que será retornado. +Se você retorna códigos de status adicionais e respostas diretamente, eles não serão incluídos no esquema do OpenAPI (a documentação da API), porque o FastAPI não tem como saber de antemão o que será retornado. -Mas você pode documentar isso no seu código, utilizando: [Retornos Adicionais](additional-responses.md). +Mas você pode documentar isso no seu código, utilizando: [Respostas Adicionais](additional-responses.md). diff --git a/docs/pt/docs/advanced/advanced-dependencies.md b/docs/pt/docs/advanced/advanced-dependencies.md index dbcf99390..21c1490ff 100644 --- a/docs/pt/docs/advanced/advanced-dependencies.md +++ b/docs/pt/docs/advanced/advanced-dependencies.md @@ -1,5 +1,6 @@ # Dependências avançadas { #advanced-dependencies } + ## Dependências parametrizadas { #parameterized-dependencies } Todas as dependências que vimos até agora são funções ou classes fixas. @@ -98,7 +99,7 @@ Por exemplo, se você tivesse uma sessão de banco de dados em uma dependência Esse comportamento foi revertido na versão 0.118.0, para que o código de saída após o `yield` seja executado depois que a resposta for enviada. -/// info | Informação +/// note | Nota Como você verá abaixo, isso é muito semelhante ao comportamento antes da versão 0.106.0, mas com várias melhorias e correções de bugs para casos extremos. @@ -108,7 +109,7 @@ Como você verá abaixo, isso é muito semelhante ao comportamento antes da vers Há alguns casos de uso, com condições específicas, que poderiam se beneficiar do comportamento antigo de executar o código de saída das dependências com `yield` antes de enviar a resposta. -Por exemplo, imagine que você tem código que usa uma sessão de banco de dados em uma dependência com `yield` apenas para verificar um usuário, mas a sessão de banco de dados nunca é usada novamente na *função de operação de rota*, somente na dependência, e a resposta demora a ser enviada, como um `StreamingResponse` que envia dados lentamente, mas por algum motivo não usa o banco de dados. +Por exemplo, imagine que você tem código que usa uma sessão de banco de dados em uma dependência com `yield` apenas para verificar um usuário, mas a sessão de banco de dados nunca é usada novamente na *função de operação de rota*, somente na dependência, e a response demora a ser enviada, como um `StreamingResponse` que envia dados lentamente, mas por algum motivo não usa o banco de dados. Nesse caso, a sessão de banco de dados seria mantida até que a resposta termine de ser enviada, mas se você não a usa, então não seria necessário mantê-la. diff --git a/docs/pt/docs/advanced/custom-response.md b/docs/pt/docs/advanced/custom-response.md index a360bd3c9..3f8e8461c 100644 --- a/docs/pt/docs/advanced/custom-response.md +++ b/docs/pt/docs/advanced/custom-response.md @@ -41,7 +41,7 @@ Para retornar uma resposta com HTML diretamente do **FastAPI**, utilize `HTMLRes {* ../../docs_src/custom_response/tutorial002_py310.py hl[2,7] *} -/// info | Informação +/// note | Nota O parâmetro `response_class` também será usado para definir o "media type" da resposta. @@ -65,7 +65,7 @@ Uma `Response` retornada diretamente em sua *função de operação de rota* nã /// -/// info | Informação +/// note | Nota Obviamente, o cabeçalho `Content-Type`, o código de status, etc, virão do objeto `Response` que você retornou. diff --git a/docs/pt/docs/advanced/dataclasses.md b/docs/pt/docs/advanced/dataclasses.md index 9a1f212d6..f1cc5a070 100644 --- a/docs/pt/docs/advanced/dataclasses.md +++ b/docs/pt/docs/advanced/dataclasses.md @@ -8,7 +8,7 @@ Mas o FastAPI também suporta o uso de [`dataclasses`](https://docs.python.org/3 Isso ainda é suportado graças ao **Pydantic**, pois ele tem [suporte interno para `dataclasses`](https://docs.pydantic.dev/latest/concepts/dataclasses/#use-of-stdlib-dataclasses-with-basemodel). -Então, mesmo com o código acima que não usa Pydantic explicitamente, o FastAPI está usando Pydantic para converter essas dataclasses padrão para a versão do Pydantic. +Então, mesmo com o código acima que não usa Pydantic explicitamente, o FastAPI está usando Pydantic para converter essas dataclasses padrão para a própria versão de dataclasses do Pydantic. E claro, ele suporta o mesmo: @@ -18,7 +18,7 @@ E claro, ele suporta o mesmo: Isso funciona da mesma forma que com os modelos Pydantic. E na verdade é alcançado da mesma maneira por baixo dos panos, usando Pydantic. -/// info | Informação +/// note | Nota Lembre-se de que dataclasses não podem fazer tudo o que os modelos Pydantic podem fazer. diff --git a/docs/pt/docs/advanced/events.md b/docs/pt/docs/advanced/events.md index 7f15d833e..eee4dc880 100644 --- a/docs/pt/docs/advanced/events.md +++ b/docs/pt/docs/advanced/events.md @@ -1,5 +1,6 @@ # Eventos de lifespan { #lifespan-events } + Você pode definir a lógica (código) que deve ser executada antes da aplicação **inicializar**. Isso significa que esse código será executado **uma vez**, **antes** de a aplicação **começar a receber requisições**. Da mesma forma, você pode definir a lógica (código) que deve ser executada quando a aplicação estiver **encerrando**. Nesse caso, esse código será executado **uma vez**, **depois** de possivelmente ter tratado **várias requisições**. @@ -120,7 +121,7 @@ Para adicionar uma função que deve ser executada quando a aplicação estiver Aqui, a função de manipulador do evento `shutdown` escreverá uma linha de texto `"Application shutdown"` no arquivo `log.txt`. -/// info | Informação +/// note | Nota Na função `open()`, o `mode="a"` significa "acrescentar", então a linha será adicionada depois do que já estiver naquele arquivo, sem sobrescrever o conteúdo anterior. @@ -152,7 +153,7 @@ Apenas um detalhe técnico para nerds curiosos. 🤓 Por baixo, na especificação técnica do ASGI, isso é parte do [Protocolo Lifespan](https://asgi.readthedocs.io/en/latest/specs/lifespan.html), e define eventos chamados `startup` e `shutdown`. -/// info | Informação +/// note | Nota Você pode ler mais sobre os manipuladores de `lifespan` do Starlette na [Documentação do Lifespan do Starlette](https://www.starlette.dev/lifespan/). diff --git a/docs/pt/docs/advanced/generate-clients.md b/docs/pt/docs/advanced/generate-clients.md index e6279a48b..975fb902d 100644 --- a/docs/pt/docs/advanced/generate-clients.md +++ b/docs/pt/docs/advanced/generate-clients.md @@ -20,28 +20,13 @@ O FastAPI gera automaticamente especificações **OpenAPI 3.1**, então qualquer /// -## Geradores de SDK dos patrocinadores do FastAPI { #sdk-generators-from-fastapi-sponsors } - -Esta seção destaca soluções **financiadas por investimento** e **com suporte de empresas** que patrocinam o FastAPI. Esses produtos fornecem **funcionalidades adicionais** e **integrações** além de SDKs gerados com alta qualidade. - -Ao ✨ [**patrocinar o FastAPI**](../help-fastapi.md#sponsor-the-author) ✨, essas empresas ajudam a garantir que o framework e seu **ecossistema** continuem saudáveis e **sustentáveis**. - -O patrocínio também demonstra um forte compromisso com a **comunidade** FastAPI (você), mostrando que elas se importam não apenas em oferecer um **ótimo serviço**, mas também em apoiar um **framework robusto e próspero**, o FastAPI. 🙇 - -Por exemplo, você pode querer experimentar: - -* [Stainless](https://www.stainless.com/?utm_source=fastapi&utm_medium=referral) -* [liblab](https://developers.liblab.com/tutorials/sdk-for-fastapi?utm_source=fastapi) - -Algumas dessas soluções também podem ser open source ou oferecer planos gratuitos, para que você possa testá-las sem compromisso financeiro. Outros geradores comerciais de SDK estão disponíveis e podem ser encontrados online. 🤓 - ## Crie um SDK em TypeScript { #create-a-typescript-sdk } Vamos começar com uma aplicação FastAPI simples: {* ../../docs_src/generate_clients/tutorial001_py310.py hl[7:9,12:13,16:17,21] *} -Observe que as *operações de rota* definem os modelos que usam para o corpo da requisição e o corpo da resposta, usando os modelos `Item` e `ResponseMessage`. +Observe que as *operações de rota* definem os modelos que usam para o payload da requisição e o payload da resposta, usando os modelos `Item` e `ResponseMessage`. ### Documentação da API { #api-docs } @@ -73,7 +58,7 @@ Agora você pode importar e usar o código do cliente. Poderia ser assim, observ -Você também obterá preenchimento automático para o corpo a ser enviado: +Você também obterá preenchimento automático para o payload a enviar: @@ -122,7 +107,7 @@ ItemsService.createItemItemsPost({name: "Plumbus", price: 5}) ...isso ocorre porque o gerador de clientes usa o **ID de operação interno do OpenAPI** para cada *operação de rota*. -O OpenAPI exige que cada ID de operação seja único em todas as *operações de rota*, então o FastAPI usa o **nome da função**, o **path** e o **método HTTP** para gerar esse ID de operação, porque dessa forma ele pode garantir que os IDs de operação sejam únicos. +O OpenAPI exige que cada ID de operação seja único em todas as *operações de rota*, então o FastAPI usa o **nome da função**, o **path** e o **método/operação HTTP** para gerar esse ID de operação, porque dessa forma ele pode garantir que os IDs de operação sejam únicos. Mas eu vou te mostrar como melhorar isso a seguir. 🤓 @@ -195,8 +180,8 @@ Depois de gerar o novo cliente, você terá agora **nomes de métodos “limpos Ao usar os clientes gerados automaticamente, você terá **preenchimento automático** para: * Métodos. -* Corpos de requisições, parâmetros de query, etc. -* Corpos de respostas. +* Payloads de requisições no body, parâmetros de query, etc. +* Payloads de respostas. Você também terá **erros em linha** para tudo. diff --git a/docs/pt/docs/advanced/json-base64-bytes.md b/docs/pt/docs/advanced/json-base64-bytes.md index cc956da4f..8034430ab 100644 --- a/docs/pt/docs/advanced/json-base64-bytes.md +++ b/docs/pt/docs/advanced/json-base64-bytes.md @@ -4,7 +4,7 @@ Se sua aplicação precisa receber e enviar dados JSON, mas você precisa inclui ## Base64 vs Arquivos { #base64-vs-files } -Primeiro, considere se você pode usar [Arquivos na request](../tutorial/request-files.md) para fazer upload de dados binários e [Response personalizada - FileResponse](./custom-response.md#fileresponse--fileresponse-) para enviar dados binários, em vez de codificá-los em JSON. +Primeiro, considere se você pode usar [Arquivos na request](../tutorial/request-files.md) para fazer upload de dados binários e [Response personalizada - FileResponse](./custom-response.md#fileresponse) para enviar dados binários, em vez de codificá-los em JSON. JSON só pode conter strings codificadas em UTF-8, portanto não pode conter bytes puros. diff --git a/docs/pt/docs/advanced/openapi-callbacks.md b/docs/pt/docs/advanced/openapi-callbacks.md index df9e7e0bf..08877e4f7 100644 --- a/docs/pt/docs/advanced/openapi-callbacks.md +++ b/docs/pt/docs/advanced/openapi-callbacks.md @@ -1,16 +1,16 @@ # Callbacks na OpenAPI { #openapi-callbacks } -Você poderia criar uma API com uma *operação de rota* que poderia acionar um request a uma *API externa* criada por outra pessoa (provavelmente o mesmo desenvolvedor que estaria *usando* sua API). +Você poderia criar uma API com uma *operação de rota* que poderia acionar um request para uma *API externa* criada por outra pessoa (provavelmente o mesmo desenvolvedor que estaria *usando* sua API). O processo que acontece quando sua aplicação de API chama a *API externa* é chamado de "callback". Porque o software que o desenvolvedor externo escreveu envia um request para sua API e então sua API *chama de volta*, enviando um request para uma *API externa* (que provavelmente foi criada pelo mesmo desenvolvedor). Nesse caso, você poderia querer documentar como essa API externa *deveria* ser. Que *operação de rota* ela deveria ter, que corpo ela deveria esperar, que resposta ela deveria retornar, etc. -## Um aplicativo com callbacks { #an-app-with-callbacks } +## Uma aplicação com callbacks { #an-app-with-callbacks } Vamos ver tudo isso com um exemplo. -Imagine que você desenvolve um aplicativo que permite criar faturas. +Imagine que você desenvolve uma aplicação que permite criar faturas. Essas faturas terão um `id`, `title` (opcional), `customer` e `total`. @@ -23,11 +23,11 @@ Então sua API irá (vamos imaginar): * Enviar a notificação de volta para o usuário da API (o desenvolvedor externo). * Isso será feito enviando um request POST (de *sua API*) para alguma *API externa* fornecida por esse desenvolvedor externo (este é o "callback"). -## O aplicativo **FastAPI** normal { #the-normal-fastapi-app } +## A aplicação **FastAPI** normal { #the-normal-fastapi-app } -Vamos primeiro ver como o aplicativo da API normal se pareceria antes de adicionar o callback. +Vamos primeiro ver como a aplicação da API normal se pareceria antes de adicionar o callback. -Ele terá uma *operação de rota* que receberá um corpo `Invoice`, e um parâmetro de consulta `callback_url` que conterá a URL para o callback. +Ela terá uma *operação de rota* que receberá um corpo `Invoice`, e um parâmetro de consulta `callback_url` que conterá a URL para o callback. Essa parte é bastante normal, a maior parte do código provavelmente já é familiar para você: @@ -45,7 +45,7 @@ A única novidade é o `callbacks=invoices_callback_router.routes` como argument O código real do callback dependerá muito da sua própria aplicação de API. -E provavelmente variará muito de um aplicativo para o outro. +E provavelmente variará muito de uma aplicação para outra. Poderia ser apenas uma ou duas linhas de código, como: @@ -72,7 +72,7 @@ Ao implementar o callback por conta própria, você pode usar algo como [HTTPX]( ## Escreva o código de documentação do callback { #write-the-callback-documentation-code } -Esse código não será executado em seu aplicativo, nós só precisamos dele para *documentar* como essa *API externa* deveria ser. +Esse código não será executado em sua aplicação, nós só precisamos dele para *documentar* como essa *API externa* deveria ser. Mas, você já sabe como criar facilmente documentação automática para uma API com o **FastAPI**. @@ -105,7 +105,7 @@ Ela deve parecer exatamente como uma *operação de rota* normal do FastAPI: Há 2 diferenças principais de uma *operação de rota* normal: -* Ela não necessita ter nenhum código real, porque seu aplicativo nunca chamará esse código. Ele é usado apenas para documentar a *API externa*. Então, a função poderia ter apenas `pass`. +* Ela não necessita ter nenhum código real, porque sua aplicação nunca chamará esse código. Ele é usado apenas para documentar a *API externa*. Então, a função poderia ter apenas `pass`. * O *path* pode conter uma [expressão OpenAPI 3](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#key-expression) (veja mais abaixo) em que pode usar variáveis com parâmetros e partes do request original enviado para *sua API*. ### A expressão do path do callback { #the-callback-path-expression } @@ -163,23 +163,23 @@ Perceba como a URL de callback usada contém a URL recebida como um parâmetro d /// -### Adicione o roteador de callback { #add-the-callback-router } +### Adicione o router de callback { #add-the-callback-router } -Nesse ponto você tem a(s) *operação(ões) de rota de callback* necessária(s) (a(s) que o *desenvolvedor externo* deveria implementar na *API externa*) no roteador de callback que você criou acima. +Nesse ponto você tem a(s) *operação(ões) de rota de callback* necessária(s) (a(s) que o *desenvolvedor externo* deveria implementar na *API externa*) no router de callback que você criou acima. -Agora use o parâmetro `callbacks` no decorador da *operação de rota da sua API* para passar o atributo `.routes` (que é na verdade apenas uma `list` de rotas/*operações de path*) do roteador de callback: +Agora use o parâmetro `callbacks` no decorador da *operação de rota da sua API* para passar o atributo `.routes` desse router de callback: {* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[33] *} /// tip | Dica -Perceba que você não está passando o roteador em si (`invoices_callback_router`) para `callback=`, mas o atributo `.routes`, como em `invoices_callback_router.routes`. +Perceba que você não está passando o router em si (`invoices_callback_router`) para `callbacks=`, mas seu `.routes`, como em `invoices_callback_router.routes`. FastAPI usará essas rotas para gerar a documentação OpenAPI do callback. /// ### Verifique a documentação { #check-the-docs } -Agora você pode iniciar seu aplicativo e ir para [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs). +Agora você pode iniciar sua aplicação e ir para [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs). Você verá sua documentação incluindo uma seção "Callbacks" para sua *operação de rota* que mostra como a *API externa* deveria ser: diff --git a/docs/pt/docs/advanced/openapi-webhooks.md b/docs/pt/docs/advanced/openapi-webhooks.md index 0c675089c..0e474c042 100644 --- a/docs/pt/docs/advanced/openapi-webhooks.md +++ b/docs/pt/docs/advanced/openapi-webhooks.md @@ -22,7 +22,7 @@ Com o **FastAPI**, utilizando o OpenAPI, você pode definir os nomes destes webh Isto pode facilitar bastante para os seus usuários **implementarem as APIs deles** para receber as requisições dos seus **webhooks**, eles podem inclusive ser capazes de gerar parte do código da API deles. -/// info | Informação +/// note | Nota Webhooks estão disponíveis a partir do OpenAPI 3.1.0, e possui suporte do FastAPI a partir da versão `0.99.0`. @@ -36,7 +36,7 @@ Quando você cria uma aplicação com o **FastAPI**, existe um atributo chamado Os webhooks que você define aparecerão no esquema do **OpenAPI** e na **página de documentação** gerada automaticamente. -/// info | Informação +/// note | Nota O objeto `app.webhooks` é na verdade apenas um `APIRouter`, o mesmo tipo que você utilizaria ao estruturar a sua aplicação com diversos arquivos. diff --git a/docs/pt/docs/advanced/path-operation-advanced-configuration.md b/docs/pt/docs/advanced/path-operation-advanced-configuration.md index b9862876c..8aca43e08 100644 --- a/docs/pt/docs/advanced/path-operation-advanced-configuration.md +++ b/docs/pt/docs/advanced/path-operation-advanced-configuration.md @@ -16,17 +16,11 @@ Você deveria ter certeza que ele é único para cada operação. ### Utilizando o nome da *função de operação de rota* como o operationId { #using-the-path-operation-function-name-as-the-operationid } -Se você quiser utilizar o nome das funções da sua API como `operationId`s, você pode iterar sobre todos esses nomes e sobrescrever o `operation_id` em cada *operação de rota* utilizando o `APIRoute.name` dela. +Se você quiser utilizar os nomes das funções da sua API como `operationId`s, você pode passar uma `generate_unique_id_function` personalizada para o `FastAPI`. -Você deveria fazer isso depois de adicionar todas as suas *operações de rota*. +A função recebe cada `APIRoute` e retorna o `operationId` a ser usado para aquela operação de rota. -{* ../../docs_src/path_operation_advanced_configuration/tutorial002_py310.py hl[2, 12:21, 24] *} - -/// tip | Dica - -Se você chamar `app.openapi()` manualmente, você deveria atualizar os `operationId`s antes dessa chamada. - -/// +{* ../../docs_src/path_operation_advanced_configuration/tutorial002_py310.py hl[2,5:6,9] *} /// warning | Atenção diff --git a/docs/pt/docs/advanced/response-change-status-code.md b/docs/pt/docs/advanced/response-change-status-code.md index 44ca6062a..1e902338b 100644 --- a/docs/pt/docs/advanced/response-change-status-code.md +++ b/docs/pt/docs/advanced/response-change-status-code.md @@ -18,7 +18,7 @@ Para estes casos, você pode utilizar um parâmetro `Response`. Você pode declarar um parâmetro do tipo `Response` em sua *função de operação de rota* (assim como você pode fazer para cookies e headers). -E então você pode definir o `status_code` neste objeto de retorno *temporal*. +E então você pode definir o `status_code` neste objeto de retorno *temporário*. {* ../../docs_src/response_change_status_code/tutorial001_py310.py hl[1,9,12] *} @@ -26,6 +26,6 @@ E então você pode retornar qualquer objeto que você precise, como você faria E se você declarar um `response_model`, ele ainda será utilizado para filtrar e converter o objeto que você retornou. -O **FastAPI** utilizará este retorno *temporal* para extrair o código de status (e também cookies e headers), e irá colocá-los no retorno final que contém o valor que você retornou, filtrado por qualquer `response_model`. +O **FastAPI** utilizará este retorno *temporário* para extrair o código de status (e também cookies e headers), e irá colocá-los no retorno final que contém o valor que você retornou, filtrado por qualquer `response_model`. Você também pode declarar o parâmetro `Response` nas dependências, e definir o código de status nelas. Mas lembre-se que o último que for definido é o que prevalecerá. diff --git a/docs/pt/docs/advanced/response-cookies.md b/docs/pt/docs/advanced/response-cookies.md index 691bd1b9c..e77502750 100644 --- a/docs/pt/docs/advanced/response-cookies.md +++ b/docs/pt/docs/advanced/response-cookies.md @@ -30,7 +30,7 @@ Então, defina os cookies nela e a retorne: Lembre-se de que se você retornar uma resposta diretamente em vez de usar o parâmetro `Response`, FastAPI a retornará diretamente. -Portanto, você terá que garantir que seus dados sejam do tipo correto. E.g. será compatível com JSON se você estiver retornando um `JSONResponse`. +Portanto, você terá que garantir que seus dados sejam do tipo correto. Por exemplo, será compatível com JSON se você estiver retornando um `JSONResponse`. E também que você não esteja enviando nenhum dado que deveria ter sido filtrado por um `response_model`. diff --git a/docs/pt/docs/advanced/response-directly.md b/docs/pt/docs/advanced/response-directly.md index 9024897c1..cc1a630c3 100644 --- a/docs/pt/docs/advanced/response-directly.md +++ b/docs/pt/docs/advanced/response-directly.md @@ -18,7 +18,7 @@ Normalmente você terá um desempenho muito melhor usando um [Modelo de resposta Você pode retornar uma `Response` ou qualquer subclasse dela. -/// info | Informação +/// note | Nota A própria `JSONResponse` é uma subclasse de `Response`. diff --git a/docs/pt/docs/advanced/response-headers.md b/docs/pt/docs/advanced/response-headers.md index 7235b5eb8..08a1b6708 100644 --- a/docs/pt/docs/advanced/response-headers.md +++ b/docs/pt/docs/advanced/response-headers.md @@ -1,5 +1,6 @@ # Cabeçalhos de resposta { #response-headers } + ## Use um parâmetro `Response` { #use-a-response-parameter } Você pode declarar um parâmetro do tipo `Response` na sua *função de operação de rota* (assim como você pode fazer para cookies). diff --git a/docs/pt/docs/advanced/security/oauth2-scopes.md b/docs/pt/docs/advanced/security/oauth2-scopes.md index 7ea61ad60..b0b9e8348 100644 --- a/docs/pt/docs/advanced/security/oauth2-scopes.md +++ b/docs/pt/docs/advanced/security/oauth2-scopes.md @@ -2,9 +2,9 @@ Você pode utilizar escopos do OAuth2 diretamente com o **FastAPI**, eles são integrados para funcionar perfeitamente. -Isso permitiria que você tivesse um sistema de permissionamento mais refinado, seguindo o padrão do OAuth2 integrado na sua aplicação OpenAPI (e as documentações da API). +Isso permitiria que você tivesse um sistema de permissionamento mais refinado, seguindo o padrão OAuth2, integrado na sua aplicação OpenAPI (e a documentação da API). -OAuth2 com escopos é o mecanismo utilizado por muitos provedores de autenticação, como o Facebook, Google, GitHub, Microsoft, X (Twitter), etc. Eles utilizam isso para prover permissões específicas para os usuários e aplicações. +OAuth2 com escopos é o mecanismo utilizado por muitos grandes provedores de autenticação, como o Facebook, Google, GitHub, Microsoft, X (Twitter), etc. Eles utilizam isso para prover permissões específicas para os usuários e aplicações. Toda vez que você "se autentica com" Facebook, Google, GitHub, Microsoft, X (Twitter), aquela aplicação está utilizando o OAuth2 com escopos. @@ -34,7 +34,7 @@ O conteúdo de cada uma dessas strings pode ter qualquer formato, mas não devem Estes escopos representam "permissões". -No OpenAPI (e.g. os documentos da API), você pode definir "esquemas de segurança". +No OpenAPI (por exemplo, a documentação da API), você pode definir "esquemas de segurança". Quando um desses esquemas de segurança utiliza OAuth2, você pode também declarar e utilizar escopos. @@ -42,11 +42,11 @@ Cada "escopo" é apenas uma string (sem espaços). Eles são normalmente utilizados para declarar permissões de segurança específicas, como por exemplo: -* `users:read` or `users:write` são exemplos comuns. +* `users:read` ou `users:write` são exemplos comuns. * `instagram_basic` é utilizado pelo Facebook / Instagram. * `https://www.googleapis.com/auth/drive` é utilizado pelo Google. -/// info | Informação +/// note | Nota No OAuth2, um "escopo" é apenas uma string que declara uma permissão específica necessária. @@ -60,7 +60,7 @@ Para o OAuth2, eles são apenas strings. ## Visão global { #global-view } -Primeiro, vamos olhar rapidamente as partes que mudam dos exemplos do **Tutorial - Guia de Usuário** para [OAuth2 com Senha (e hash), Bearer com tokens JWT](../../tutorial/security/oauth2-jwt.md). Agora utilizando escopos OAuth2: +Primeiro, vamos olhar rapidamente as partes que mudam dos exemplos no **Tutorial - Guia de Usuário** principal para [OAuth2 com Senha (e hash), Bearer com tokens JWT](../../tutorial/security/oauth2-jwt.md). Agora utilizando escopos OAuth2: {* ../../docs_src/security/tutorial005_an_py310.py hl[5,9,13,47,65,106,108:116,122:126,130:136,141,157] *} @@ -74,7 +74,7 @@ O parâmetro `scopes` recebe um `dict` contendo cada escopo como chave e a descr {* ../../docs_src/security/tutorial005_an_py310.py hl[63:66] *} -Pelo motivo de estarmos declarando estes escopos, eles aparecerão nos documentos da API quando você se autenticar/autorizar. +Pelo motivo de estarmos declarando estes escopos, eles aparecerão na documentação da API quando você se autenticar/autorizar. E você poderá selecionar quais escopos você deseja dar acesso: `me` e `items`. @@ -108,7 +108,7 @@ Para isso, nós importamos e utilizamos `Security` de `fastapi`. Você pode utilizar `Security` para declarar dependências (assim como `Depends`), porém o `Security` também recebe o parâmetro `scopes` com uma lista de escopos (strings). -Neste caso, nós passamos a função `get_current_active_user` como dependência para `Security` (da mesma forma que nós faríamos com `Depends`). +Neste caso, nós passamos a função de dependência `get_current_active_user` para `Security` (da mesma forma que nós faríamos com `Depends`). Mas nós também passamos uma `list` de escopos, neste caso com apenas um escopo: `items` (poderia ter mais). @@ -142,7 +142,7 @@ Agora atualize a dependência `get_current_user`. Este é o usado pelas dependências acima. -Aqui é onde estamos utilizando o mesmo esquema OAuth2 que nós declaramos antes, declarando-o como uma dependência: `oauth2_scheme`. +Aqui é onde estamos utilizando o mesmo esquema OAuth2 que nós criamos antes, declarando-o como uma dependência: `oauth2_scheme`. Porque esta função de dependência não possui nenhum requerimento de escopo, nós podemos utilizar `Depends` com o `oauth2_scheme`. Nós não precisamos utilizar `Security` quando nós não precisamos especificar escopos de segurança. @@ -235,7 +235,7 @@ Todos eles serão validados independentemente para cada *operação de rota*. ## Verifique { #check-it } -Se você abrir os documentos da API, você pode autenticar e especificar quais escopos você quer autorizar. +Se você abrir a documentação da API, você pode autenticar e especificar quais escopos você quer autorizar. @@ -249,11 +249,11 @@ Isso é o que aconteceria se uma aplicação terceira que tentou acessar uma des Neste exemplo nós estamos utilizando o fluxo de senha do OAuth2. -Isso é apropriado quando nós estamos autenticando em nossa própria aplicação, provavelmente com o nosso próprio "*frontend*". +Isso é apropriado quando nós estamos autenticando em nossa própria aplicação, provavelmente com o nosso próprio frontend. Porque nós podemos confiar nele para receber o `username` e o `password`, pois nós controlamos isso. -Mas se nós estamos construindo uma aplicação OAuth2 que outros poderiam conectar (i.e., se você está construindo um provedor de autenticação equivalente ao Facebook, Google, GitHub, etc.) você deveria utilizar um dos outros fluxos. +Mas se nós estamos construindo uma aplicação OAuth2 que outros poderiam conectar (ou seja, se você está construindo um provedor de autenticação equivalente ao Facebook, Google, GitHub, etc.) você deveria utilizar um dos outros fluxos. O mais comum é o fluxo implícito. diff --git a/docs/pt/docs/advanced/settings.md b/docs/pt/docs/advanced/settings.md index 371d5711b..029290aed 100644 --- a/docs/pt/docs/advanced/settings.md +++ b/docs/pt/docs/advanced/settings.md @@ -1,5 +1,6 @@ # Configurações e Variáveis de Ambiente { #settings-and-environment-variables } + Em muitos casos, sua aplicação pode precisar de configurações externas, por exemplo chaves secretas, credenciais de banco de dados, credenciais para serviços de e-mail, etc. A maioria dessas configurações é variável (pode mudar), como URLs de banco de dados. E muitas podem ser sensíveis, como segredos. diff --git a/docs/pt/docs/advanced/stream-data.md b/docs/pt/docs/advanced/stream-data.md index 8e0bf08b6..1a9284a91 100644 --- a/docs/pt/docs/advanced/stream-data.md +++ b/docs/pt/docs/advanced/stream-data.md @@ -2,9 +2,9 @@ Se você quer transmitir dados que podem ser estruturados como JSON, você deveria [Transmitir JSON Lines](../tutorial/stream-json-lines.md). -Mas se você quer transmitir dados binários puros ou strings, veja como fazer. +Mas se você quer **transmitir dados binários puros** ou strings, veja como fazer. -/// info | Informação +/// note | Nota Adicionado no FastAPI 0.134.0. @@ -12,15 +12,15 @@ Adicionado no FastAPI 0.134.0. ## Casos de uso { #use-cases } -Você pode usar isto para transmitir strings puras, por exemplo diretamente da saída de um serviço de AI LLM. +Você pode usar isto para transmitir strings puras, por exemplo diretamente da saída de um serviço de **AI LLM**. -Você também pode usá-lo para transmitir arquivos binários grandes, enviando cada bloco de dados à medida que o lê, sem precisar carregar tudo na memória de uma vez. +Você também pode usá-lo para transmitir **arquivos binários grandes**, enviando cada bloco de dados à medida que o lê, sem precisar carregar tudo na memória de uma vez. -Você também pode transmitir vídeo ou áudio desta forma; pode até ser gerado enquanto você processa e envia. +Você também pode transmitir **vídeo** ou **áudio** desta forma; pode até ser gerado enquanto você processa e envia. ## Um `StreamingResponse` com `yield` { #a-streamingresponse-with-yield } -Se você declarar `response_class=StreamingResponse` na sua função de operação de rota, você pode usar `yield` para enviar cada bloco de dados em sequência. +Se você declarar `response_class=StreamingResponse` na sua *função de operação de rota*, você pode usar `yield` para enviar cada bloco de dados em sequência. {* ../../docs_src/stream_data/tutorial001_py310.py ln[1:23] hl[20,23] *} @@ -40,7 +40,7 @@ Como o FastAPI não tentará converter os dados para JSON com Pydantic nem seria {* ../../docs_src/stream_data/tutorial001_py310.py ln[32:35] hl[33] *} -Isso também significa que, com `StreamingResponse`, você tem a liberdade e a responsabilidade de produzir e codificar os bytes exatamente como precisam ser enviados, independentemente das anotações de tipo. 🤓 +Isso também significa que, com `StreamingResponse`, você tem a **liberdade** e a **responsabilidade** de produzir e codificar os bytes exatamente como precisam ser enviados, independentemente das anotações de tipo. 🤓 ### Transmitir bytes { #stream-bytes } @@ -50,7 +50,7 @@ Um dos principais casos de uso é transmitir `bytes` em vez de strings; você po ## Um `PNGStreamingResponse` personalizado { #a-custom-pngstreamingresponse } -Nos exemplos acima, os bytes eram transmitidos, mas a resposta não tinha um cabeçalho `Content-Type`, então o cliente não sabia que tipo de dado estava recebendo. +Nos exemplos acima, os bytes eram transmitidos, mas a response não tinha um cabeçalho `Content-Type`, então o cliente não sabia que tipo de dado estava recebendo. Você pode criar uma subclasse personalizada de `StreamingResponse` que define o cabeçalho `Content-Type` para o tipo de dado que você está transmitindo. @@ -58,7 +58,7 @@ Por exemplo, você pode criar um `PNGStreamingResponse` que define o cabeçalho {* ../../docs_src/stream_data/tutorial002_py310.py ln[6,19:20] hl[20] *} -Em seguida, você pode usar essa nova classe em `response_class=PNGStreamingResponse` na sua função de operação de rota: +Em seguida, você pode usar essa nova classe em `response_class=PNGStreamingResponse` na sua *função de operação de rota*: {* ../../docs_src/stream_data/tutorial002_py310.py ln[23:27] hl[23] *} @@ -78,7 +78,7 @@ Apenas para que possa viver no mesmo arquivo deste exemplo e você possa copiar /// -Ao usar um bloco `with`, garantimos que o objeto semelhante a arquivo seja fechado após a função geradora (a função com `yield`) terminar. Ou seja, após terminar de enviar a resposta. +Ao usar um bloco `with`, garantimos que o objeto semelhante a arquivo seja fechado após a função geradora (a função com `yield`) terminar. Ou seja, após terminar de enviar a response. Isso não seria tão importante neste exemplo específico porque é um arquivo falso em memória (com `io.BytesIO`), mas com um arquivo real, seria importante garantir que o arquivo fosse fechado ao final do trabalho. @@ -90,7 +90,7 @@ Por exemplo, eles não têm `await file.read()`, nem `async for chunk in file`. E, em muitos casos, lê-los seria uma operação bloqueante (que poderia bloquear o loop de eventos), pois são lidos do disco ou da rede. -/// info | Informação +/// note | Nota O exemplo acima é, na verdade, uma exceção, porque o objeto `io.BytesIO` já está em memória, então lê-lo não bloqueará nada. @@ -98,7 +98,7 @@ Mas, em muitos casos, ler um arquivo ou um objeto semelhante a arquivo bloqueari /// -Para evitar bloquear o loop de eventos, você pode simplesmente declarar a função de operação de rota com `def` normal em vez de `async def`. Assim, o FastAPI a executará em um worker de threadpool, evitando bloquear o loop principal. +Para evitar bloquear o loop de eventos, você pode simplesmente declarar a *função de operação de rota* com `def` normal em vez de `async def`. Assim, o FastAPI a executará em um worker de threadpool, evitando bloquear o loop principal. {* ../../docs_src/stream_data/tutorial002_py310.py ln[30:34] hl[31] *} diff --git a/docs/pt/docs/advanced/strict-content-type.md b/docs/pt/docs/advanced/strict-content-type.md index 9530501d4..843caa848 100644 --- a/docs/pt/docs/advanced/strict-content-type.md +++ b/docs/pt/docs/advanced/strict-content-type.md @@ -1,6 +1,6 @@ # Verificação Estrita de Content-Type { #strict-content-type-checking } -Por padrão, o **FastAPI** usa verificação estrita do cabeçalho `Content-Type` para corpos de requisição JSON; isso significa que requisições JSON devem incluir um `Content-Type` válido (por exemplo, `application/json`) para que o corpo seja interpretado como JSON. +Por padrão, o **FastAPI** usa verificação estrita do cabeçalho `Content-Type` para corpos de requisição JSON; isso significa que requisições JSON **devem** incluir um `Content-Type` válido (por exemplo, `application/json`) para que o corpo seja interpretado como JSON. ## Risco de CSRF { #csrf-risk } @@ -40,7 +40,7 @@ Observe que ambos têm o mesmo host. Usando o frontend, você pode fazer o agente de IA executar ações em seu nome. -Como está em execução localmente e não na Internet aberta, você decide não configurar autenticação, confiando apenas no acesso à rede local. +Como está em execução **localmente** e não na Internet aberta, você decide **não configurar autenticação**, confiando apenas no acesso à rede local. Então um de seus usuários poderia instalá-lo e executá-lo localmente. @@ -69,9 +69,9 @@ Se sua aplicação está na Internet aberta, você não “confiaria na rede” Atacantes poderiam simplesmente executar um script para enviar requisições à sua API, sem necessidade de interação do navegador, então você provavelmente já está protegendo quaisquer endpoints privilegiados. -Nesse caso, esse ataque/risco não se aplica a você. +Nesse caso, **esse ataque/risco não se aplica a você**. -Esse risco e ataque é relevante principalmente quando a aplicação roda na rede local e essa é a única proteção presumida. +Esse risco e ataque é relevante principalmente quando a aplicação roda na **rede local** e essa é a **única proteção presumida**. ## Permitindo Requisições sem Content-Type { #allowing-requests-without-content-type } @@ -81,7 +81,7 @@ Se você precisa dar suporte a clientes que não enviam um cabeçalho `Content-T Com essa configuração, requisições sem um cabeçalho `Content-Type` terão o corpo interpretado como JSON, o mesmo comportamento das versões mais antigas do FastAPI. -/// info | Informação +/// note | Nota Esse comportamento e configuração foram adicionados no FastAPI 0.132.0. diff --git a/docs/pt/docs/advanced/websockets.md b/docs/pt/docs/advanced/websockets.md index 70b2ee853..5367a91be 100644 --- a/docs/pt/docs/advanced/websockets.md +++ b/docs/pt/docs/advanced/websockets.md @@ -111,7 +111,7 @@ Eles funcionam da mesma forma que para outros endpoints FastAPI/*operações de {* ../../docs_src/websockets_/tutorial002_an_py310.py hl[68:69,82] *} -/// info | Informação +/// note | Nota Como isso é um WebSocket, não faz muito sentido levantar uma `HTTPException`, em vez disso levantamos uma `WebSocketException`. diff --git a/docs/pt/docs/advanced/wsgi.md b/docs/pt/docs/advanced/wsgi.md index 110bba053..fafa147fa 100644 --- a/docs/pt/docs/advanced/wsgi.md +++ b/docs/pt/docs/advanced/wsgi.md @@ -1,12 +1,13 @@ # Adicionando WSGI - Flask, Django, entre outros { #including-wsgi-flask-django-others } + Como você viu em [Subaplicações - Montagens](sub-applications.md) e [Atrás de um Proxy](behind-a-proxy.md), você pode montar aplicações WSGI. Para isso, você pode utilizar o `WSGIMiddleware` para encapsular a sua aplicação WSGI, como por exemplo Flask, Django, etc. ## Usando `WSGIMiddleware` { #using-wsgimiddleware } -/// info | Informação +/// note | Nota Isso requer instalar `a2wsgi`, por exemplo com `pip install a2wsgi`. diff --git a/docs/pt/docs/alternatives.md b/docs/pt/docs/alternatives.md index b32b260c3..8a63a3073 100644 --- a/docs/pt/docs/alternatives.md +++ b/docs/pt/docs/alternatives.md @@ -18,13 +18,13 @@ Mas em algum momento, não havia outra opção senão criar algo que fornecesse É o framework Python mais popular e amplamente confiável. É utilizado para construir sistemas como o Instagram. -É relativamente bem acoplado com bancos de dados relacionais (como MySQL ou PostgreSQL), então, ter um banco de dados NoSQL (como Couchbase, MongoDB, Cassandra, etc.) como mecanismo principal de armazenamento não é muito fácil. +É relativamente fortemente acoplado com bancos de dados relacionais (como MySQL ou PostgreSQL), então, ter um banco de dados NoSQL (como Couchbase, MongoDB, Cassandra, etc.) como mecanismo principal de armazenamento não é muito fácil. Foi criado para gerar o HTML no backend, não para criar APIs usadas por um frontend moderno (como React, Vue.js e Angular) ou por outros sistemas (como dispositivos IoT) comunicando com ele. ### [Django REST Framework](https://www.django-rest-framework.org/) { #django-rest-framework } -Django REST framework foi criado para ser uma caixa de ferramentas flexível para construção de APIs Web utilizando Django por baixo, para melhorar suas capacidades de API. +Django REST Framework foi criado para ser uma caixa de ferramentas flexível para construção de APIs Web utilizando Django por baixo, para melhorar suas capacidades de API. Ele é utilizado por muitas empresas incluindo Mozilla, Red Hat e Eventbrite. @@ -88,7 +88,7 @@ O jeito de usar é muito simples. Por exemplo, para fazer uma requisição `GET` response = requests.get("http://example.com/some/url") ``` -A contra-parte na aplicação FastAPI, a operação de rota, poderia ficar assim: +A *operação de rota* da API equivalente no FastAPI poderia ficar assim: ```Python hl_lines="1" @app.get("/some/url") @@ -377,7 +377,7 @@ Agora APIStar é um conjunto de ferramentas para validar especificações OpenAP /// note | Nota -APIStar foi criado por Tom Christie. O mesmo cara que criou: +APIStar foi criado por Tom Christie. A mesma pessoa que criou: * Django REST Framework * Starlette (no qual **FastAPI** é baseado) diff --git a/docs/pt/docs/async.md b/docs/pt/docs/async.md index 8c497d451..3fa92b085 100644 --- a/docs/pt/docs/async.md +++ b/docs/pt/docs/async.md @@ -44,11 +44,11 @@ Se sua aplicação (de alguma forma) não tem que se comunicar com nada mais e e --- -Se você simplesmente não sabe, use apenas `def`. +Se você simplesmente não sabe, use `def` normal. --- -**Note**: Você pode misturar `def` e `async def` nas suas *funções de operação de rota* tanto quanto necessário e definir cada função usando a melhor opção para você. FastAPI irá fazer a coisa certa com elas. +**Nota**: Você pode misturar `def` e `async def` nas suas *funções de operação de rota* tanto quanto necessário e definir cada função usando a melhor opção para você. FastAPI irá fazer a coisa certa com elas. De qualquer forma, em ambos os casos acima, FastAPI irá trabalhar assincronamente e ser extremamente rápido. @@ -82,10 +82,10 @@ Esse "esperar por algo" normalmente se refere a operações I/O, essas operações são chamadas operações "limitadas por I/O". +Como 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" 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. @@ -109,7 +109,7 @@ Você vai com seu _crush_ na lanchonete, e fica na fila enquanto o caixa pega os -Então chega a sua vez, você pede dois saborosos hambúrgueres para você e seu _crush_. 🍔🍔 +Então chega a sua vez, você pede dois saborosos hambúrgueres para você e seu _crush_. 🍔🍔 @@ -189,17 +189,17 @@ Você espera, na frente do balcão 🕙, para que ninguém pegue seus hambúrgue 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 os der 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_. -Vocês comem os hambúrgueres, e o trabalho está terminado. ⏹ +Vocês apenas os comem, e o trabalho está terminado. ⏹ @@ -213,15 +213,15 @@ Belas ilustrações de [Ketrina Thompson](https://www.instagram.com/ketrinadraws --- -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. +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 ⏯ a "esperar no balcão" 🕙 por um bom tempo. -A lanchonete paralela tem 8 processadores (caixas / cozinheiros), enquanto a lanchonete dos hambúrgueres concorrentes tinha apenas 2 (um caixa e um cozinheiro). +A lanchonete tem 8 processadores (caixas/cozinheiros). Enquanto a lanchonete dos hambúrgueres concorrentes poderia ter apenas 2 (um caixa e um cozinheiro). Ainda assim, a experiência final não foi a melhor. 😞 --- -Essa seria o equivalente paralelo à história dos hambúrgueres. 🍔 +Essa seria a história equivalente paralela para hambúrgueres. 🍔 Para um exemplo "mais real", imagine um banco. @@ -231,15 +231,15 @@ 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. -Você provavelmente não gostaria de levar seu _crush_ 😍 com você para um rolezinho no banco 🏦. +Você provavelmente não gostaria de levar seu _crush_ 😍 com você para resolver assuntos no banco 🏦. ### Conclusão dos hambúrgueres { #burger-conclusion } -Nesse cenário dos "hambúrgueres com seu _crush_", como tem muita espera, faz mais sentido ter um sistema concorrente ⏸🔀⏯. +Nesse cenário dos "hambúrgueres de fast food com seu _crush_", como tem muita espera 🕙, faz mais sentido ter um sistema concorrente ⏸🔀⏯. Esse é o caso da maioria das aplicações web. -Muitos, muitos usuários, mas seu servidor está esperando 🕙 pela sua conexão não tão boa enviar suas requisições. +Muitos, muitos usuários, mas seu servidor está esperando 🕙 pela conexão não tão boa deles enviar suas requisições. E então esperando 🕙 novamente as respostas voltarem. @@ -269,11 +269,11 @@ Então, para equilibrar tudo, imagine a seguinte historinha: 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 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. +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 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. +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. @@ -285,18 +285,18 @@ Exemplos comuns de operações limitadas por CPU são coisas que exigem processa Por exemplo: -* **Processamento de áudio** ou **imagem** -* **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 -* **Aprendizado de Máquina**: 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 Aprendizado de Máquina, 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. +* **Processamento de áudio** ou **imagem**. +* **Visão Computacional**: uma imagem é composta por milhões de pixels, cada pixel tem 3 valores / cores, processar isso normalmente exige alguma computação nesses pixels, todos ao mesmo tempo. +* **Aprendizado de Máquina**: 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 Aprendizado de Máquina, então, o mesmo se aplica. A diferença é que não há apenas uma 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 + Aprendizado de Máquina { #concurrency-parallelism-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 **limitados por CPU** como aqueles em sistemas de Aprendizado de Máquina. +Mas você também pode explorar os benefícios do paralelismo e multiprocessamento (tendo múltiplos processos rodando em paralelo) para trabalhos **limitados por CPU** como aqueles em sistemas de Aprendizado de Máquina. -Isso, somado ao simples fato que Python é a principal linguagem para **Data Science**, Aprendizado de Máquina e especialmente Deep Learning, faz do FastAPI uma ótima escolha para APIs web e aplicações com Data Science / Aprendizado de Máquina (entre muitas outras). +Isso, somado ao simples fato que Python é a principal linguagem para **Data Science**, Aprendizado de Máquina e especialmente Deep Learning, faz do FastAPI uma ótima escolha para APIs web e aplicações de Data Science / Aprendizado de Máquina (entre muitas outras). Para ver como alcançar esse paralelismo em produção veja a seção sobre [Implantação](deployment/index.md). @@ -340,7 +340,7 @@ burgers = get_burgers(2) --- -Então, se você está usando uma biblioteca que diz que você pode chamá-la com `await`, você precisa criar as *funções de operação de rota* com `async def`, como em: +Então, se você está usando uma biblioteca que diz que você pode chamá-la com `await`, você precisa criar as *funções de operação de rota* que a utilizam com `async def`, como em: ```Python hl_lines="2-3" @app.get('/burgers') @@ -355,9 +355,9 @@ Você deve ter observado que `await` pode ser usado somente dentro de funções Mas ao mesmo tempo, funções definidas com `async def` têm que ser "aguardadas". Então, funções com `async def` podem 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? +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. +Se você estiver 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, você também pode fazê-lo. @@ -423,7 +423,7 @@ Ainda, em ambas as situações, as chances são que o **FastAPI** [ainda será m ### Dependências { #dependencies } -O mesmo se aplica para as [dependências](tutorial/dependencies/index.md). 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). Se uma dependência é uma função `def` padrão ao invés de `async def`, ela é rodada no threadpool externo. ### Sub-dependências { #sub-dependencies } @@ -435,7 +435,7 @@ Qualquer outra função de utilidade que você chame diretamente pode ser criada Isso está em contraste às funções que o FastAPI chama para você: *funções de operação de rota* e dependências. -Se sua função de utilidade é uma função normal com `def`, ela será chamada diretamente (como você a escreve no código), não em uma threadpool, se a função é criada com `async def` então você deve esperar por essa função quando você chamá-la no seu código. +Se sua função de utilidade é uma função normal com `def`, ela será chamada diretamente (como você a escreve no código), não em uma threadpool, se a função é criada com `async def` então você deveria usar `await` nessa função quando você chamá-la no seu código. --- diff --git a/docs/pt/docs/deployment/cloud.md b/docs/pt/docs/deployment/cloud.md index 4b0eb9553..68a2fd003 100644 --- a/docs/pt/docs/deployment/cloud.md +++ b/docs/pt/docs/deployment/cloud.md @@ -16,7 +16,7 @@ FastAPI Cloud é o patrocinador principal e provedor de financiamento dos projet ## Provedores de Nuvem - Patrocinadores { #cloud-providers-sponsors } -Alguns outros provedores de nuvem ✨ [**patrocinam o FastAPI**](../help-fastapi.md#sponsor-the-author) ✨ também. 🙇 +Alguns outros provedores de nuvem ✨ [**patrocinam o FastAPI**](https://github.com/sponsors/tiangolo) ✨ também. 🙇 Você também pode considerá-los para seguir seus tutoriais e experimentar seus serviços: diff --git a/docs/pt/docs/deployment/concepts.md b/docs/pt/docs/deployment/concepts.md index e6338d5ea..0625c6d64 100644 --- a/docs/pt/docs/deployment/concepts.md +++ b/docs/pt/docs/deployment/concepts.md @@ -1,6 +1,6 @@ # Conceitos de Implantações { #deployments-concepts } -Ao implantar um aplicativo **FastAPI**, ou na verdade, qualquer tipo de API da web, há vários conceitos com os quais você provavelmente se importa e, usando-os, você pode encontrar a maneira **mais apropriada** de **implantar seu aplicativo**. +Ao implantar uma aplicação **FastAPI**, ou na verdade, qualquer tipo de API da web, há vários conceitos com os quais você provavelmente se importa e, usando-os, você pode encontrar a maneira **mais apropriada** de **implantar sua aplicação**. Alguns dos conceitos importantes são: @@ -19,7 +19,7 @@ Vou lhe contar um pouco mais sobre esses **conceitos** aqui, e espero que isso l Ao considerar esses conceitos, você será capaz de **avaliar e projetar** a melhor maneira de implantar **suas próprias APIs**. -Nos próximos capítulos, darei a você mais **receitas concretas** para implantar aplicativos FastAPI. +Nos próximos capítulos, darei a você mais **receitas concretas** para implantar aplicações FastAPI. Mas por enquanto, vamos verificar essas importantes **ideias conceituais**. Esses conceitos também se aplicam a qualquer outro tipo de API da web. 💡 @@ -27,7 +27,7 @@ Mas por enquanto, vamos verificar essas importantes **ideias conceituais**. Esse No [capítulo anterior sobre HTTPS](https.md) aprendemos como o HTTPS fornece criptografia para sua API. -Também vimos que o HTTPS normalmente é fornecido por um componente **externo** ao seu servidor de aplicativos, um **Proxy de terminação TLS**. +Também vimos que o HTTPS normalmente é fornecido por um componente **externo** ao seu servidor de aplicações, um **Proxy de terminação TLS**. E tem que haver algo responsável por **renovar os certificados HTTPS**, pode ser o mesmo componente ou pode ser algo diferente. @@ -75,7 +75,7 @@ A palavra **processo** normalmente é usada de forma mais específica, referindo * Isso não se refere ao arquivo, nem ao código, refere-se **especificamente** à coisa que está sendo **executada** e gerenciada pelo sistema operacional. * Qualquer programa, qualquer código, **só pode fazer coisas** quando está sendo **executado**. Então, quando há um **processo em execução**. * O processo pode ser **terminado** (ou "morto") por você, ou pelo sistema operacional. Nesse ponto, ele para de rodar/ser executado, e ele **não pode mais fazer coisas**. -* Cada aplicativo que você tem em execução no seu computador tem algum processo por trás dele, cada programa em execução, cada janela, etc. E normalmente há muitos processos em execução **ao mesmo tempo** enquanto um computador está ligado. +* Cada aplicação que você tem em execução no seu computador tem algum processo por trás dela, cada programa em execução, cada janela, etc. E normalmente há muitos processos em execução **ao mesmo tempo** enquanto um computador está ligado. * Pode haver **vários processos** do **mesmo programa** em execução ao mesmo tempo. Se você verificar o "gerenciador de tarefas" ou o "monitor do sistema" (ou ferramentas semelhantes) no seu sistema operacional, poderá ver muitos desses processos em execução. @@ -104,11 +104,11 @@ E se o servidor for reiniciado (por exemplo, após atualizações ou migrações ### Executar automaticamente na inicialização { #run-automatically-on-startup } -Em geral, você provavelmente desejará que o programa do servidor (por exemplo, Uvicorn) seja iniciado automaticamente na inicialização do servidor e, sem precisar de nenhuma **intervenção humana**, tenha um processo sempre em execução com sua API (por exemplo, Uvicorn executando seu aplicativo FastAPI). +Em geral, você provavelmente desejará que o programa do servidor (por exemplo, Uvicorn) seja iniciado automaticamente na inicialização do servidor e, sem precisar de nenhuma **intervenção humana**, tenha um processo sempre em execução com sua API (por exemplo, Uvicorn executando sua aplicação FastAPI). ### Programa separado { #separate-program } -Para conseguir isso, você normalmente terá um **programa separado** que garantiria que seu aplicativo fosse executado na inicialização. E em muitos casos, ele também garantiria que outros componentes ou aplicativos também fossem executados, por exemplo, um banco de dados. +Para conseguir isso, você normalmente terá um **programa separado** que garantiria que sua aplicação fosse executada na inicialização. E em muitos casos, ele também garantiria que outros componentes ou aplicações também fossem executados, por exemplo, um banco de dados. ### Ferramentas de exemplo para executar na inicialização { #example-tools-to-run-at-startup } @@ -127,7 +127,7 @@ Darei exemplos mais concretos nos próximos capítulos. ## Reinicializações { #restarts } -Semelhante a garantir que seu aplicativo seja executado na inicialização, você provavelmente também deseja garantir que ele seja **reiniciado** após falhas. +Semelhante a garantir que sua aplicação seja executada na inicialização, você provavelmente também deseja garantir que ela seja **reiniciada** após falhas. ### Nós cometemos erros { #we-make-mistakes } @@ -137,15 +137,15 @@ E nós, como desenvolvedores, continuamos aprimorando o código à medida que en ### Pequenos erros são tratados automaticamente { #small-errors-automatically-handled } -Ao criar APIs da web com FastAPI, se houver um erro em nosso código, o FastAPI normalmente o conterá na única solicitação que acionou o erro. 🛡 +Ao criar APIs da web com FastAPI, se houver um erro em nosso código, o FastAPI normalmente o conterá na única request que acionou o erro. 🛡 -O cliente receberá um **Erro Interno do Servidor 500** para essa solicitação, mas o aplicativo continuará funcionando para as próximas solicitações em vez de travar completamente. +O cliente receberá um **Erro Interno do Servidor 500** para essa request, mas a aplicação continuará funcionando para as próximas requests em vez de travar completamente. ### Erros maiores - Travamentos { #bigger-errors-crashes } -No entanto, pode haver casos em que escrevemos algum código que **trava todo o aplicativo**, fazendo com que o Uvicorn e o Python travem. 💥 +No entanto, pode haver casos em que escrevemos algum código que **trava toda a aplicação**, fazendo com que o Uvicorn e o Python travem. 💥 -E ainda assim, você provavelmente não gostaria que o aplicativo permanecesse inativo porque houve um erro em um lugar, você provavelmente quer que ele **continue em execução** pelo menos para as *operações de rota* que não estão quebradas. +E ainda assim, você provavelmente não gostaria que a aplicação permanecesse inativa porque houve um erro em um lugar, você provavelmente quer que ela **continue em execução** pelo menos para as *operações de rota* que não estão quebradas. ### Reiniciar após falha { #restart-after-crash } @@ -153,13 +153,13 @@ Mas nos casos com erros realmente graves que travam o **processo** em execução /// tip | Dica -...Embora se o aplicativo inteiro estiver **travando imediatamente**, provavelmente não faça sentido reiniciá-lo para sempre. Mas nesses casos, você provavelmente notará isso durante o desenvolvimento, ou pelo menos logo após a implantação. +...Embora se a aplicação inteira estiver **travando imediatamente**, provavelmente não faça sentido reiniciá-la para sempre. Mas nesses casos, você provavelmente notará isso durante o desenvolvimento, ou pelo menos logo após a implantação. -Então, vamos nos concentrar nos casos principais, onde ele pode travar completamente em alguns casos específicos **no futuro**, e ainda faz sentido reiniciá-lo. +Então, vamos nos concentrar nos casos principais, onde ela pode travar completamente em alguns casos específicos **no futuro**, e ainda faz sentido reiniciá-la. /// -Você provavelmente gostaria de ter a coisa responsável por reiniciar seu aplicativo como um **componente externo**, porque a essa altura, o mesmo aplicativo com Uvicorn e Python já havia travado, então não há nada no mesmo código do mesmo aplicativo que possa fazer algo a respeito. +Você provavelmente gostaria de ter a coisa responsável por reiniciar sua aplicação como um **componente externo**, porque a essa altura, a mesma aplicação com Uvicorn e Python já havia travado, então não há nada no mesmo código da mesma aplicação que possa fazer algo a respeito. ### Ferramentas de exemplo para reiniciar automaticamente { #example-tools-to-restart-automatically } @@ -178,13 +178,13 @@ Por exemplo, isso poderia ser resolvido por: ## Replicação - Processos e Memória { #replication-processes-and-memory } -Com um aplicativo FastAPI, usando um programa de servidor como o comando `fastapi` que executa o Uvicorn, executá-lo uma vez em **um processo** pode atender a vários clientes simultaneamente. +Com uma aplicação FastAPI, usando um programa de servidor como o comando `fastapi` que executa o Uvicorn, executá-lo uma vez em **um processo** pode atender a vários clientes simultaneamente. Mas em muitos casos, você desejará executar vários processos de trabalho ao mesmo tempo. ### Processos Múltiplos - Trabalhadores { #multiple-processes-workers } -Se você tiver mais clientes do que um único processo pode manipular (por exemplo, se a máquina virtual não for muito grande) e tiver **vários núcleos** na CPU do servidor, você poderá ter **vários processos** em execução com o mesmo aplicativo ao mesmo tempo e distribuir todas as solicitações entre eles. +Se você tiver mais clientes do que um único processo pode manipular (por exemplo, se a máquina virtual não for muito grande) e tiver **vários núcleos** na CPU do servidor, você poderá ter **vários processos** em execução com a mesma aplicação ao mesmo tempo e distribuir todas as requests entre eles. Quando você executa **vários processos** do mesmo programa de API, eles são comumente chamados de **trabalhadores**. @@ -214,11 +214,11 @@ Neste exemplo, há um **Processo Gerenciador** que inicia e controla dois **Proc Este Processo de Gerenciador provavelmente seria o que escutaria na **porta** no IP. E ele transmitiria toda a comunicação para os processos de trabalho. -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. +Esses processos de trabalho seriam aqueles que executariam sua aplicação, eles executariam os cálculos principais para receber uma **request** 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. +E, claro, a mesma máquina provavelmente teria **outros processos** em execução, além da sua aplicação. Um detalhe interessante é que a porcentagem da **CPU usada** por cada processo pode **variar** muito ao longo do tempo, mas a **memória (RAM)** normalmente fica mais ou menos **estável**. @@ -255,9 +255,9 @@ Por exemplo, você pode querer executar **migrações de banco de dados**. Mas na maioria dos casos, você precisará executar essas etapas apenas **uma vez**. -Portanto, você vai querer ter um **processo único** para executar essas **etapas anteriores** antes de iniciar o aplicativo. +Portanto, você vai querer ter um **processo único** para executar essas **etapas anteriores** antes de iniciar a aplicação. -E você terá que se certificar de que é um único processo executando essas etapas anteriores *mesmo* se depois, você iniciar **vários processos** (vários trabalhadores) para o próprio aplicativo. Se essas etapas fossem executadas por **vários processos**, eles **duplicariam** o trabalho executando-o em **paralelo**, e se as etapas fossem algo delicado como uma migração de banco de dados, elas poderiam causar conflitos entre si. +E você terá que se certificar de que é um único processo executando essas etapas anteriores *mesmo* se depois, você iniciar **vários processos** (vários trabalhadores) para a própria aplicação. Se essas etapas fossem executadas por **vários processos**, eles **duplicariam** o trabalho executando-o em **paralelo**, e se as etapas fossem algo delicado como uma migração de banco de dados, elas poderiam causar conflitos entre si. Claro, há alguns casos em que não há problema em executar as etapas anteriores várias vezes; nesse caso, é muito mais fácil de lidar. @@ -276,7 +276,7 @@ Isso **dependerá muito** da maneira como você **implanta seu sistema** e prova Aqui estão algumas ideias possíveis: * Um "Init Container" no Kubernetes que roda antes do seu app container -* Um script bash que roda os passos anteriores e então inicia seu aplicativo +* Um script bash que roda os passos anteriores e então inicia sua aplicação * Você ainda precisaria de uma maneira de iniciar/reiniciar *aquele* script bash, detectar erros, etc. /// tip | Dica @@ -307,7 +307,7 @@ Você pode usar ferramentas simples como `htop` para ver a CPU e a RAM usadas no ## Recapitular { #recap } -Você leu aqui alguns dos principais conceitos que provavelmente precisa ter em mente ao decidir como implantar seu aplicativo: +Você leu aqui alguns dos principais conceitos que provavelmente precisa ter em mente ao decidir como implantar sua aplicação: * Segurança - HTTPS * Executando na inicialização diff --git a/docs/pt/docs/deployment/docker.md b/docs/pt/docs/deployment/docker.md index 33e23351f..f68784855 100644 --- a/docs/pt/docs/deployment/docker.md +++ b/docs/pt/docs/deployment/docker.md @@ -50,7 +50,7 @@ Uma imagem de contêiner é uma versão **estática** de todos os arquivos, vari Em contraste com a "**imagem de contêiner**" que contém os conteúdos estáticos armazenados, um "**contêiner**" normalmente se refere à instância rodando, a coisa que está sendo **executada**. -Quando o **contêiner** é iniciado e está rodando (iniciado a partir de uma **imagem de contêiner**), ele pode criar ou modificar arquivos, variáveis de ambiente, etc. Essas mudanças vão existir somente nesse contêiner, mas não persistirão na imagem subjacente do container (não serão salvas no disco). +Quando o **contêiner** é iniciado e está rodando (iniciado a partir de uma **imagem de contêiner**), ele pode criar ou modificar arquivos, variáveis de ambiente, etc. Essas mudanças vão existir somente nesse contêiner, mas não persistirão na imagem subjacente do contêiner (não serão salvas no disco). Uma imagem de contêiner é comparável ao arquivo de **programa** e seus conteúdos, ex.: `python` e algum arquivo `main.py`. @@ -64,7 +64,7 @@ E existe um [Docker Hub](https://hub.docker.com/) público com **imagens de cont Por exemplo, há uma [Imagem Python](https://hub.docker.com/_/python) oficial. -E existe muitas outras imagens para diferentes coisas, como bancos de dados, por exemplo: +E existem muitas outras imagens para diferentes coisas, como bancos de dados, por exemplo: * [PostgreSQL](https://hub.docker.com/_/postgres) * [MySQL](https://hub.docker.com/_/mysql) @@ -87,11 +87,11 @@ Quando um **contêiner** é iniciado, ele irá rodar esse comando/programa (embo Um contêiner está rodando enquanto o **processo principal** (comando ou programa) estiver rodando. -Um contêiner normalmente tem um **único processo**, mas também é possível iniciar sub-processos a partir do processo principal, e dessa forma você terá **vários processos** no mesmo contêiner. +Um contêiner normalmente tem um **único processo**, mas também é possível iniciar subprocessos a partir do processo principal, e dessa forma você terá **vários processos** no mesmo contêiner. Mas não é possível ter um contêiner rodando sem **pelo menos um processo rodando**. Se o processo principal parar, o contêiner também para. -## Construir uma Imagem Docker para FastAPI { #build-a-docker-image-for-fastapi } +## Construa uma Imagem Docker para FastAPI { #build-a-docker-image-for-fastapi } Okay, vamos construir algo agora! 🚀 @@ -132,7 +132,7 @@ Successfully installed fastapi pydantic -/// info | Informação +/// note | Nota Há outros formatos e ferramentas para definir e instalar dependências de pacotes. @@ -262,7 +262,7 @@ Isso pode ser bem perceptível ao usar `docker compose`. Veja esta seção de FA #### Estrutura de diretórios { #directory-structure } -Agora você deve haver uma estrutura de diretório como: +Agora você deveria ter uma estrutura de diretório como: ``` . @@ -275,7 +275,7 @@ Agora você deve haver uma estrutura de diretório como: #### Por trás de um Proxy de Terminação TLS { #behind-a-tls-termination-proxy } -Se você está executando seu contêiner atrás de um Proxy de Terminação TLS (load balancer) como Nginx ou Traefik, adicione a opção `--proxy-headers`, isso fará com que o Uvicorn (pela CLI do FastAPI) confie nos cabeçalhos enviados por esse proxy, informando que o aplicativo está sendo executado atrás do HTTPS, etc. +Se você está executando seu contêiner atrás de um Proxy de Terminação TLS (balanceador de carga) como Nginx ou Traefik, adicione a opção `--proxy-headers`, isso fará com que o Uvicorn (pela CLI do FastAPI) confie nos cabeçalhos enviados por esse proxy, informando que o aplicativo está sendo executado atrás do HTTPS, etc. ```Dockerfile CMD ["fastapi", "run", "app/main.py", "--proxy-headers", "--port", "80"] @@ -289,7 +289,7 @@ Existe um truque importante nesse `Dockerfile`, primeiro copiamos o **arquivo co COPY ./requirements.txt /code/requirements.txt ``` -Docker e outras ferramentas **constróem** essas imagens de contêiner **incrementalmente**, adicionando **uma camada em cima da outra**, começando do topo do `Dockerfile` e adicionando qualquer arquivo criado por cada uma das instruções do `Dockerfile`. +Docker e outras ferramentas **constroem** essas imagens de contêiner **incrementalmente**, adicionando **uma camada em cima da outra**, começando do topo do `Dockerfile` e adicionando qualquer arquivo criado por cada uma das instruções do `Dockerfile`. Docker e ferramentas similares também usam um **cache interno** ao construir a imagem, se um arquivo não mudou desde a última vez que a imagem do contêiner foi construída, então ele irá **reutilizar a mesma camada** criada na última vez, ao invés de copiar o arquivo novamente e criar uma nova camada do zero. @@ -352,7 +352,7 @@ $ docker run -d --name mycontainer -p 80:80 myimage ## Verifique { #check-it } -Você deve ser capaz de verificar isso no URL do seu contêiner Docker, por exemplo: [http://192.168.99.100/items/5?q=somequery](http://192.168.99.100/items/5?q=somequery) ou [http://127.0.0.1/items/5?q=somequery](http://127.0.0.1/items/5?q=somequery) (ou equivalente, usando seu host Docker). +Você deveria conseguir verificar isso no URL do seu contêiner Docker, por exemplo: [http://192.168.99.100/items/5?q=somequery](http://192.168.99.100/items/5?q=somequery) ou [http://127.0.0.1/items/5?q=somequery](http://127.0.0.1/items/5?q=somequery) (ou equivalente, usando seu host Docker). Você verá algo como: @@ -376,9 +376,9 @@ Você verá a documentação alternativa automática (fornecida pelo [ReDoc](htt ![ReDoc](https://fastapi.tiangolo.com/img/index/index-02-redoc-simple.png) -## Construa uma Imagem Docker com um FastAPI de Arquivo Único { #build-a-docker-image-with-a-single-file-fastapi } +## Construa uma Imagem Docker com uma aplicação FastAPI de Arquivo Único { #build-a-docker-image-with-a-single-file-fastapi } -Se seu FastAPI for um único arquivo, por exemplo, `main.py` sem um diretório `./app`, sua estrutura de arquivos poderia ser assim: +Se sua aplicação FastAPI for um único arquivo, por exemplo, `main.py` sem um diretório `./app`, sua estrutura de arquivos poderia ser assim: ``` . @@ -456,7 +456,7 @@ Sem usar contêineres, fazer aplicativos executarem na inicialização e com rei Se você tiver um cluster de máquinas com **Kubernetes**, Docker Swarm Mode, Nomad ou outro sistema complexo semelhante para gerenciar contêineres distribuídos em várias máquinas, então provavelmente desejará **lidar com a replicação** no **nível do cluster** em vez de usar um **gerenciador de processos** (como Uvicorn com workers) em cada contêiner. -Um desses sistemas de gerenciamento de contêineres distribuídos como o Kubernetes normalmente tem alguma maneira integrada de lidar com a **replicação de contêineres** enquanto ainda oferece **balanceamento de carga** para as solicitações recebidas. Tudo no **nível do cluster**. +Um desses sistemas de gerenciamento de contêineres distribuídos como o Kubernetes normalmente tem alguma maneira integrada de lidar com a **replicação de contêineres** enquanto ainda oferece **balanceamento de carga** para os requests recebidos. Tudo no **nível do cluster**. Nesses casos, você provavelmente desejará criar uma **imagem Docker do zero** como [explicado acima](#dockerfile), instalando suas dependências e executando **um único processo Uvicorn** em vez de usar múltiplos workers do Uvicorn. @@ -464,7 +464,7 @@ Nesses casos, você provavelmente desejará criar uma **imagem Docker do zero** Quando usando contêineres, normalmente você terá algum componente **escutando na porta principal**. Poderia ser outro contêiner que também é um **Proxy de Terminação TLS** para lidar com **HTTPS** ou alguma ferramenta semelhante. -Como esse componente assumiria a **carga** de solicitações e distribuiria isso entre os workers de uma maneira (esperançosamente) **balanceada**, ele também é comumente chamado de **Balanceador de Carga**. +Como esse componente assumiria a **carga** de requests e distribuiria isso entre os workers de uma maneira (esperançosamente) **balanceada**, ele também é comumente chamado de **Balanceador de Carga**. /// tip | Dica @@ -472,17 +472,17 @@ O mesmo componente **Proxy de Terminação TLS** usado para HTTPS provavelmente /// -E quando trabalhar com contêineres, o mesmo sistema que você usa para iniciar e gerenciá-los já terá ferramentas internas para transmitir a **comunicação de rede** (por exemplo, solicitações HTTP) do **balanceador de carga** (que também pode ser um **Proxy de Terminação TLS**) para o(s) contêiner(es) com seu aplicativo. +E quando trabalhar com contêineres, o mesmo sistema que você usa para iniciar e gerenciá-los já terá ferramentas internas para transmitir a **comunicação de rede** (por exemplo, requests HTTP) do **balanceador de carga** (que também pode ser um **Proxy de Terminação TLS**) para o(s) contêiner(es) com seu aplicativo. ### Um Balanceador de Carga - Múltiplos Contêineres de Workers { #one-load-balancer-multiple-worker-containers } -Quando trabalhando com **Kubernetes** ou sistemas similares de gerenciamento de contêiner distribuído, usar seus mecanismos de rede internos permite que o único **balanceador de carga** que está escutando na **porta principal** transmita a comunicação (solicitações) para possivelmente **múltiplos contêineres** executando seu aplicativo. +Quando trabalhando com **Kubernetes** ou sistemas similares de gerenciamento de contêiner distribuído, usar seus mecanismos de rede internos permite que o único **balanceador de carga** que está escutando na **porta principal** transmita a comunicação (requests) para possivelmente **múltiplos contêineres** executando seu aplicativo. Cada um desses contêineres executando seu aplicativo normalmente teria **apenas um processo** (ex.: um processo Uvicorn executando seu aplicativo FastAPI). Todos seriam **contêineres idênticos**, executando a mesma coisa, mas cada um com seu próprio processo, memória, etc. Dessa forma, você aproveitaria a **paralelização** em **núcleos diferentes** da CPU, ou até mesmo em **máquinas diferentes**. -E o sistema de contêiner com o **balanceador de carga** iria **distribuir as solicitações** para cada um dos contêineres com seu aplicativo **em turnos**. Portanto, cada solicitação poderia ser tratada por um dos múltiplos **contêineres replicados** executando seu aplicativo. +E o sistema de contêiner com o **balanceador de carga** iria **distribuir os requests** para cada um dos contêineres com seu aplicativo **em turnos**. Portanto, cada request poderia ser tratado por um dos múltiplos **contêineres replicados** executando seu aplicativo. -E normalmente esse **balanceador de carga** seria capaz de lidar com solicitações que vão para *outros* aplicativos em seu cluster (por exemplo, para um domínio diferente, ou sob um prefixo de URL diferente), e transmitiria essa comunicação para os contêineres certos para *esse outro* aplicativo em execução em seu cluster. +E normalmente esse **balanceador de carga** seria capaz de lidar com requests que vão para *outros* aplicativos em seu cluster (por exemplo, para um domínio diferente, ou sob um prefixo de path de URL diferente), e transmitiria essa comunicação para os contêineres certos para *esse outro* aplicativo em execução em seu cluster. ### Um Processo por Contêiner { #one-process-per-container } @@ -544,7 +544,7 @@ Se você executar **um único processo por contêiner**, terá uma quantidade ma E então você pode definir esses mesmos limites e requisitos de memória em suas configurações para seu sistema de gerenciamento de contêineres (por exemplo, no **Kubernetes**). Dessa forma, ele poderá **replicar os contêineres** nas **máquinas disponíveis** levando em consideração a quantidade de memória necessária por eles e a quantidade disponível nas máquinas no cluster. -Se sua aplicação for **simples**, isso provavelmente **não será um problema**, e você pode não precisar especificar limites de memória rígidos. Mas se você estiver **usando muita memória** (por exemplo, com **modelos de aprendizado de máquina**), deve verificar quanta memória está consumindo e ajustar o **número de contêineres** que executa em **cada máquina** (e talvez adicionar mais máquinas ao seu cluster). +Se sua aplicação for **simples**, isso provavelmente **não será um problema**, e você pode não precisar especificar limites de memória rígidos. Mas se você estiver **usando muita memória** (por exemplo, com modelos de **Aprendizado de Máquina**), você deveria verificar quanta memória está consumindo e ajustar o **número de contêineres** que executa em **cada máquina** (e talvez adicionar mais máquinas ao seu cluster). Se você executar **múltiplos processos por contêiner**, deve garantir que o número de processos iniciados não **consuma mais memória** do que o disponível. @@ -556,7 +556,7 @@ Se você estiver usando contêineres (por exemplo, Docker, Kubernetes), existem Se você tiver **múltiplos contêineres**, provavelmente cada um executando um **único processo** (por exemplo, em um cluster do **Kubernetes**), então provavelmente você gostaria de ter um **contêiner separado** fazendo o trabalho dos **passos anteriores** em um único contêiner, executando um único processo, **antes** de executar os contêineres workers replicados. -/// info | Informação +/// note | Nota Se você estiver usando o Kubernetes, provavelmente será um [Init Container](https://kubernetes.io/docs/concepts/workloads/pods/init-containers/). @@ -572,7 +572,7 @@ Se você tiver uma configuração simples, com um **único contêiner** que ent Antes havia uma imagem oficial do FastAPI para Docker: [tiangolo/uvicorn-gunicorn-fastapi](https://github.com/tiangolo/uvicorn-gunicorn-fastapi-docker). Mas agora ela está descontinuada. ⛔️ -Você provavelmente **não** deve usar essa imagem base do Docker (ou qualquer outra semelhante). +Você provavelmente **não** deveria usar essa imagem base do Docker (ou qualquer outra semelhante). Se você está usando **Kubernetes** (ou outros) e já está definindo a **replicação** no nível do cluster, com vários **contêineres**. Nesses casos, é melhor **construir uma imagem do zero** como descrito acima: [Construir uma Imagem Docker para FastAPI](#build-a-docker-image-for-fastapi). diff --git a/docs/pt/docs/deployment/fastapicloud.md b/docs/pt/docs/deployment/fastapicloud.md index 26ec85ac0..0504a444c 100644 --- a/docs/pt/docs/deployment/fastapicloud.md +++ b/docs/pt/docs/deployment/fastapicloud.md @@ -1,26 +1,6 @@ # FastAPI Cloud { #fastapi-cloud } -Você pode implantar sua aplicação FastAPI no [FastAPI Cloud](https://fastapicloud.com) com um **único comando**; entre na lista de espera, caso ainda não tenha feito isso. 🚀 - -## Login { #login } - -Certifique-se de que você já tem uma conta no **FastAPI Cloud** (nós convidamos você a partir da lista de espera 😉). - -Depois, faça login: - -
- -```console -$ fastapi login - -You are logged in to FastAPI Cloud 🚀 -``` - -
- -## Implantar { #deploy } - -Agora, implante sua aplicação, com **um único comando**: +Você pode implantar sua aplicação FastAPI no [FastAPI Cloud](https://fastapicloud.com) com apenas **um comando**. 🚀
@@ -36,6 +16,8 @@ Deploying to FastAPI Cloud...
+A CLI detectará automaticamente sua aplicação FastAPI e a implantará na nuvem. Se você não estiver autenticado, seu navegador será aberto para concluir o processo de autenticação. + É isso! Agora você pode acessar sua aplicação nesse URL. ✨ ## Sobre o FastAPI Cloud { #about-fastapi-cloud } diff --git a/docs/pt/docs/deployment/https.md b/docs/pt/docs/deployment/https.md index 0e8ae2ba6..d89e0bbff 100644 --- a/docs/pt/docs/deployment/https.md +++ b/docs/pt/docs/deployment/https.md @@ -10,31 +10,31 @@ Se você está com pressa ou não se importa, continue com as seções seguintes /// -Para aprender o básico de HTTPS do ponto de vista do consumidor, verifique [https://howhttps.works/](https://howhttps.works/). - -Agora, a partir de uma perspectiva do desenvolvedor, aqui estão algumas coisas para ter em mente ao pensar em HTTPS: - -* Para HTTPS, o servidor precisa ter "certificados" gerados por um terceiro. - * Esses certificados são na verdade adquiridos de um terceiro, eles não são simplesmente "gerados". -* Certificados têm um tempo de vida. - * Eles expiram. - * E então eles precisam ser renovados, adquirindo-os novamente de um terceiro. -* A criptografia da conexão acontece no nível TCP. - * Essa é uma camada abaixo do HTTP. - * Portanto, o manuseio do certificado e da criptografia é feito antes do HTTP. -* O TCP não sabe sobre "domínios". Apenas sobre endereços IP. - * As informações sobre o domínio específico solicitado vão nos dados HTTP. -* Os certificados HTTPS “certificam” um determinado domínio, mas o protocolo e a encriptação acontecem ao nível do TCP, antes de sabermos de que domínio se trata. -* Por padrão, isso significa que você só pode ter um certificado HTTPS por endereço IP. +Para **aprender o básico de HTTPS**, do ponto de vista do consumidor, verifique [https://howhttps.works/](https://howhttps.works/). + +Agora, a partir de uma **perspectiva do desenvolvedor**, aqui estão algumas coisas para ter em mente ao pensar em HTTPS: + +* Para HTTPS, **o servidor** precisa **ter "certificados"** gerados por um **terceiro**. + * Esses certificados são na verdade **adquiridos** de um terceiro, eles não são simplesmente "gerados". +* Certificados têm um **tempo de vida**. + * Eles **expiram**. + * E então eles precisam ser **renovados**, **adquiridos novamente** de um terceiro. +* A criptografia da conexão acontece no **nível TCP**. + * Essa é uma camada **abaixo do HTTP**. + * Portanto, o manuseio do **certificado e da criptografia** é feito **antes do HTTP**. +* **O TCP não sabe sobre "domínios"**. Apenas sobre endereços IP. + * As informações sobre o **domínio específico** solicitado vão nos **dados HTTP**. +* Os **certificados HTTPS** “certificam” um **determinado domínio**, mas o protocolo e a encriptação acontecem ao nível do TCP, **antes de sabermos** de que domínio se trata. +* **Por padrão**, isso significa que você só pode ter **um certificado HTTPS por endereço IP**. * Não importa o tamanho do seu servidor ou quão pequeno cada aplicativo que você tem nele possa ser. - * No entanto, existe uma solução para isso. -* Há uma extensão para o protocolo TLS (aquele que lida com a criptografia no nível TCP, antes do HTTP) chamada [SNI](https://en.wikipedia.org/wiki/Server_Name_Indication). - * 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) chamada **[SNI](https://en.wikipedia.org/wiki/Server_Name_Indication)**. + * 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: recebendo as requisições HTTPS encriptadas, enviando as solicitações HTTP descriptografadas para o aplicativo HTTP real em execução no mesmo servidor (a aplicação FastAPI, neste caso), pegar a resposta HTTP do aplicativo, criptografá-la usando o certificado HTTPS apropriado e enviá-la de volta ao cliente usando HTTPS. Este servidor é frequentemente chamado de [Proxy de Terminação TLS](https://en.wikipedia.org/wiki/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 HTTPS encriptadas**, enviando as **solicitações HTTP descriptografadas** para o aplicativo HTTP real em execução no mesmo servidor (a aplicação **FastAPI**, neste caso), pegar a **resposta HTTP** do aplicativo, **criptografá-la** usando o **certificado HTTPS** apropriado e enviá-la de volta ao cliente usando **HTTPS**. Este servidor é frequentemente chamado de **[Proxy de Terminação TLS](https://en.wikipedia.org/wiki/TLS_termination_proxy)**. Algumas das opções que você pode usar como Proxy de Terminação TLS são: @@ -45,17 +45,17 @@ Algumas das opções que você pode usar como Proxy de Terminação TLS são: ## Let's Encrypt { #lets-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 o [Let's Encrypt](https://letsencrypt.org/) foi criado. +Mas então o **[Let's Encrypt](https://letsencrypt.org/)** 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 é, na verdade, melhor por causa do seu lifespan reduzido. +Ele é um projeto da Linux Foundation. Ele 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 do seu lifespan reduzido. 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 { #https-for-developers } @@ -63,11 +63,11 @@ Aqui está um exemplo de como uma API HTTPS poderia ser estruturada, passo a pas ### Nome do domínio { #domain-name } -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). +A etapa inicial provavelmente seria **adquirir** algum **nome de domínio**. Então, você iria configurá-lo em um servidor DNS (possivelmente no mesmo provedor em nuvem). -Você provavelmente usaria um servidor em nuvem (máquina virtual) ou algo parecido, e ele teria um fixo Endereço IP público. +Você provavelmente usaria um servidor em nuvem (máquina virtual) ou algo parecido, e ele teria um **endereço IP público** fixo. -No(s) servidor(es) DNS, você configuraria um registro (um `A record`) para apontar seu domínio para o endereço IP público do seu servidor. +No(s) servidor(es) DNS, você configuraria um registro (um "`A record`") para apontar **seu domínio** para o **endereço IP público do seu servidor**. Você provavelmente fará isso apenas uma vez, na primeira vez em que tudo estiver sendo configurado. @@ -81,120 +81,120 @@ Essa parte do Nome do Domínio se dá muito antes do HTTPS, mas como tudo depend 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`. +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. +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 { #tls-handshake-start } -O navegador então irá comunicar-se com esse endereço IP na porta 443 (a porta HTTPS). +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. +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 { #tls-with-sni-extension } -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. +**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. +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). +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. +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. +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. +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. +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). +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. +Perceba que a encriptação da comunicação acontece no **nível do TCP**, não no nível do HTTP. /// ### Solicitação HTTPS { #https-request } -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. +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. +Então, o cliente envia uma **solicitação HTTPS**. Que é apenas uma solicitação HTTP sobre uma conexão TLS encriptada. ### Desencripte a Solicitação { #decrypt-the-request } -O Proxy de Terminação TLS então usaria a encriptação combinada para desencriptar a solicitação, e transmitiria a solicitação básica (desencriptada) para o processo executando a aplicação (por exemplo, um processo com Uvicorn executando a aplicação FastAPI). +O Proxy de Terminação TLS então usaria a encriptação combinada para **desencriptar a solicitação**, e transmitiria a **solicitação HTTP básica (desencriptada)** para o processo executando a aplicação (por exemplo, um processo com Uvicorn executando a aplicação FastAPI). ### Resposta HTTP { #http-response } -A aplicação processaria a solicitação e retornaria uma resposta HTTP básica (não encriptada) para o Proxy de Terminação TLS. +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 { #https-response } -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. +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. +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. +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 { #multiple-applications } -Podem existir múltiplas aplicações em execução no mesmo servidor (ou servidores), por exemplo: outras APIs ou um banco de dados. +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. +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. +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 { #certificate-renewal } -Em algum momento futuro, cada certificado irá expirar (aproximadamente 3 meses após a aquisição). +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). +E então, haverá outro programa (em alguns casos é 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. +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. +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 +* **Modificar alguns registros DNS**. * Para isso, o programa de renovação precisa ter suporte às 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. +* **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 adquirir os certificados, depois configurá-los com o Proxy de Terminação TLS, e então reiniciar o Proxy de Terminação TLS. Isso não é o ideal, já que sua(s) aplicação(ões) não vão estar disponíveis enquanto o Proxy de Terminação TLS estiver desligado. -Todo esse processo de renovação, enquanto o aplicativo ainda funciona, é uma das principais razões para preferir um sistema separado para gerenciar HTTPS com um Proxy de Terminação TLS em vez de usar os certificados TLS no servidor da aplicação diretamente (e.g. com o Uvicorn). +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). ## Cabeçalhos encaminhados por Proxy { #proxy-forwarded-headers } -Ao usar um proxy para lidar com HTTPS, seu servidor de aplicação (por exemplo, Uvicorn via FastAPI CLI) não sabe nada sobre o processo de HTTPS; ele se comunica com HTTP simples com o Proxy de Terminação TLS. +Ao usar um proxy para lidar com HTTPS, seu **servidor de aplicação** (por exemplo, Uvicorn via FastAPI CLI) não sabe nada sobre o processo de HTTPS; ele se comunica com HTTP simples com o **Proxy de Terminação TLS**. -Esse proxy normalmente define alguns cabeçalhos HTTP dinamicamente antes de transmitir a requisição para o servidor de aplicação, para informar ao servidor de aplicação que a requisição está sendo encaminhada pelo proxy. +Esse **proxy** normalmente define alguns cabeçalhos HTTP dinamicamente antes de transmitir a requisição para o **servidor de aplicação**, para informar ao servidor de aplicação que a requisição está sendo **encaminhada** pelo proxy. /// note | Detalhes Técnicos @@ -206,11 +206,11 @@ Os cabeçalhos do proxy são: /// -No entanto, como o servidor de aplicação não sabe que está atrás de um proxy confiável, por padrão ele não confiaria nesses cabeçalhos. +No entanto, como o **servidor de aplicação** não sabe que está atrás de um **proxy** confiável, por padrão ele não confiaria nesses cabeçalhos. -Mas você pode configurar o servidor de aplicação para confiar nos cabeçalhos encaminhados enviados pelo proxy. Se você estiver usando o FastAPI CLI, pode usar a opção de CLI `--forwarded-allow-ips` para dizer de quais IPs ele deve confiar nesses cabeçalhos encaminhados. +Mas você pode configurar o **servidor de aplicação** para confiar nos cabeçalhos *encaminhados* enviados pelo **proxy**. Se você estiver usando o FastAPI CLI, pode usar a *Opção de CLI* `--forwarded-allow-ips` para dizer de quais IPs ele deve confiar nesses cabeçalhos *encaminhados*. -Por exemplo, se o servidor de aplicação só estiver recebendo comunicação do proxy confiável, você pode defini-lo como `--forwarded-allow-ips="*"` para fazê-lo confiar em todos os IPs de entrada, já que ele só receberá requisições de seja lá qual for o IP usado pelo proxy. +Por exemplo, se o **servidor de aplicação** só estiver recebendo comunicação do **proxy** confiável, você pode defini-lo como `--forwarded-allow-ips="*"` para fazê-lo confiar em todos os IPs de entrada, já que ele só receberá requisições de seja lá qual for o IP usado pelo **proxy**. Dessa forma, a aplicação seria capaz de saber qual é sua própria URL pública, se está usando HTTPS, o domínio, etc. @@ -224,8 +224,8 @@ Você pode saber mais sobre isso na documentação em [Atrás de um Proxy - Habi ## Recapitulando { #recap } -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. +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. +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. 🔒 +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/deployment/manually.md b/docs/pt/docs/deployment/manually.md index 19ed1a4ab..0c8db162e 100644 --- a/docs/pt/docs/deployment/manually.md +++ b/docs/pt/docs/deployment/manually.md @@ -53,10 +53,9 @@ A principal coisa que você precisa para executar uma aplicação **FastAPI** (o Existem diversas alternativas, incluindo: * [Uvicorn](https://www.uvicorn.dev/): um servidor ASGI de alta performance. -* [Hypercorn](https://hypercorn.readthedocs.io/): um servidor ASGI compatível com HTTP/2, Trio e outros recursos. +* [Hypercorn](https://hypercorn.readthedocs.io/): um servidor ASGI compatível com HTTP/2, Trio e outras funcionalidades. * [Daphne](https://github.com/django/daphne): servidor ASGI construído para Django Channels. * [Granian](https://github.com/emmett-framework/granian): um servidor HTTP Rust para aplicações Python. -* [NGINX Unit](https://unit.nginx.org/howto/fastapi/): NGINX Unit é um runtime de aplicação web leve e versátil. ## Máquina Servidora e Programa Servidor { #server-machine-and-server-program } @@ -137,7 +136,7 @@ Uvicorn e outros servidores suportam a opção `--reload` que é útil durante o A opção `--reload` consome muito mais recursos, é mais instável, etc. -Ela ajuda muito durante o **desenvolvimento**, mas você **não deve** usá-la em **produção**. +Ela ajuda muito durante o **desenvolvimento**, mas você **não deveria** usá-la em **produção**. /// diff --git a/docs/pt/docs/deployment/server-workers.md b/docs/pt/docs/deployment/server-workers.md index 98c1877c2..4d70de966 100644 --- a/docs/pt/docs/deployment/server-workers.md +++ b/docs/pt/docs/deployment/server-workers.md @@ -17,7 +17,7 @@ Como você viu no capítulo anterior sobre [Conceitos de implantação](concepts Aqui mostrarei como usar o **Uvicorn** com **processos de trabalho** usando o comando `fastapi` ou o comando `uvicorn` diretamente. -/// info | Informação +/// note | Nota Se você estiver usando contêineres, por exemplo com Docker ou Kubernetes, falarei mais sobre isso no próximo capítulo: [FastAPI em contêineres - Docker](docker.md). diff --git a/docs/pt/docs/editor-support.md b/docs/pt/docs/editor-support.md index 7eedd3908..de02c5d7c 100644 --- a/docs/pt/docs/editor-support.md +++ b/docs/pt/docs/editor-support.md @@ -1,6 +1,6 @@ # Suporte a Editores { #editor-support } -A [FastAPI Extension](https://marketplace.visualstudio.com/items?itemName=FastAPILabs.fastapi-vscode) oficial melhora seu fluxo de trabalho de desenvolvimento com descoberta e navegação de *operação de rota*, além de implantação no FastAPI Cloud e transmissão ao vivo de logs. +A [FastAPI Extension](https://marketplace.visualstudio.com/items?itemName=FastAPILabs.fastapi-vscode) oficial melhora seu fluxo de trabalho de desenvolvimento FastAPI com descoberta e navegação de *operação de rota*, além de implantação no FastAPI Cloud e transmissão ao vivo de logs. Para mais detalhes sobre a extensão, consulte o README no [repositório do GitHub](https://github.com/fastapi/fastapi-vscode). diff --git a/docs/pt/docs/environment-variables.md b/docs/pt/docs/environment-variables.md index a464becee..ebf037faa 100644 --- a/docs/pt/docs/environment-variables.md +++ b/docs/pt/docs/environment-variables.md @@ -289,7 +289,7 @@ Essas informações serão úteis ao aprender sobre [Ambientes Virtuais](virtual ## Conclusão { #conclusion } -Com isso, você deve ter uma compreensão básica do que são **variáveis ​​de ambiente** e como usá-las em Python. +Com isso, você deveria ter uma compreensão básica do que são **variáveis ​​de ambiente** e como usá-las em Python. Você também pode ler mais sobre elas na [Wikipedia para Variáveis ​​de Ambiente](https://en.wikipedia.org/wiki/Environment_variable). diff --git a/docs/pt/docs/features.md b/docs/pt/docs/features.md index 8b14c5fea..846bc7f94 100644 --- a/docs/pt/docs/features.md +++ b/docs/pt/docs/features.md @@ -1,15 +1,15 @@ -# Recursos { #features } +# Funcionalidades { #features } -## Recursos do FastAPI { #fastapi-features } +## Funcionalidades do FastAPI { #fastapi-features } **FastAPI** te oferece o seguinte: ### Baseado em padrões abertos { #based-on-open-standards } -* [**OpenAPI**](https://github.com/OAI/OpenAPI-Specification) para criação de APIs, incluindo declarações de caminho operações, parâmetros, requisições de corpo, segurança etc. +* [**OpenAPI**](https://github.com/OAI/OpenAPI-Specification) para criação de APIs, incluindo declarações de path operações, parâmetros, corpos de requisição, segurança etc. * Documentação automática de modelos de dados com [**JSON Schema**](https://json-schema.org/) (já que o OpenAPI em si é baseado no JSON Schema). * Projetado em torno desses padrões, após um estudo meticuloso. Em vez de uma camada improvisada por cima. -* Isso também permite o uso de **geração de código do cliente** automaticamente em muitas linguagens. +* Isso também permite o uso de **geração de código de cliente** automaticamente em muitas linguagens. ### Documentação automática { #automatic-docs } @@ -75,7 +75,7 @@ Passe as chaves e valores do dicionário `second_user_data` diretamente como arg Todo o framework foi projetado para ser fácil e intuitivo de usar, todas as decisões foram testadas em vários editores antes do início do desenvolvimento, para garantir a melhor experiência de desenvolvimento. -Na pesquisa de desenvolvedores Python, ficou claro [que um dos recursos mais utilizados é o "preenchimento automático"](https://www.jetbrains.com/research/python-developers-survey-2017/#tools-and-features). +Nas pesquisas de desenvolvedores Python, ficou claro [que uma das funcionalidades mais utilizadas é o "preenchimento automático"](https://www.jetbrains.com/research/python-developers-survey-2017/#tools-and-features). Todo o framework **FastAPI** é feito para satisfazer isso. O preenchimento automático funciona em todos os lugares. @@ -97,9 +97,9 @@ Sem a necessidade de digitar nomes de chaves erroneamente, ir e voltar entre doc ### Breve { #short } -Há **padrões** sensíveis para tudo, com configurações adicionais em todos os lugares. Todos os parâmetros podem ser regulados para fazer o que você precisa e para definir a API que você necessita. +Há **valores padrão** sensíveis para tudo, com configurações adicionais em todos os lugares. Todos os parâmetros podem ser regulados para fazer o que você precisa e para definir a API que você necessita. -Por padrão, tudo **"simplesmente funciona"**. +Mas, por padrão, tudo **"simplesmente funciona"**. ### Validação { #validation } @@ -121,7 +121,7 @@ Toda a validação é controlada pelo robusto e bem estabelecido **Pydantic**. Segurança e autenticação integradas. Sem nenhum compromisso com bancos de dados ou modelos de dados. -Todos os esquemas de seguranças definidos no OpenAPI, incluindo: +Todos os esquemas de segurança definidos no OpenAPI, incluindo: * HTTP Basic. * **OAuth2** (também com **tokens JWT**). Confira o tutorial em [OAuth2 com JWT](tutorial/security/oauth2-jwt.md). @@ -130,9 +130,9 @@ Todos os esquemas de seguranças definidos no OpenAPI, incluindo: * parâmetros da Query. * Cookies etc. -Além disso, todos os recursos de segurança do Starlette (incluindo **cookies de sessão**). +Além disso, todas as funcionalidades de segurança do Starlette (incluindo **cookies de sessão**). -Tudo construído como ferramentas e componentes reutilizáveis que são fáceis de integrar com seus sistemas, armazenamento de dados, banco de dados relacionais e não-relacionais etc. +Tudo construído como ferramentas e componentes reutilizáveis que são fáceis de integrar com seus sistemas, armazenamentos de dados, bancos de dados relacionais e NoSQL etc. ### Injeção de dependência { #dependency-injection } @@ -142,40 +142,40 @@ FastAPI inclui um sistema de @@ -52,9 +52,9 @@ $ fastapi dev -É **ALTAMENTE recomendado** que você escreva ou copie o código, edite-o e rode-o localmente. +É **ALTAMENTE recomendado** que você escreva ou copie o código, edite-o e execute-o localmente. -Usá-lo em seu editor é o que realmente te mostra os benefícios do FastAPI, ver quão pouco código você tem que escrever, todas as conferências de tipo, preenchimento automático, etc. +Usá-lo em seu editor é o que realmente mostra os benefícios do FastAPI, vendo quão pouco código você tem que escrever, todas as verificações de tipo, preenchimento automático, etc. --- @@ -94,7 +94,7 @@ O FastAPI tem uma [extensão oficial para o VS Code](https://marketplace.visuals Há também um **Guia Avançado de Usuário** que você pode ler após esse **Tutorial - Guia de Usuário**. -O **Guia Avançado de Usuário** constrói sobre esse, usa os mesmos conceitos e te ensina algumas funcionalidades extras. +O **Guia Avançado de Usuário** constrói sobre esse, usa os mesmos conceitos e ensina algumas funcionalidades extras. Mas você deveria ler primeiro o **Tutorial - Guia de Usuário** (que você está lendo agora). diff --git a/docs/pt/docs/tutorial/metadata.md b/docs/pt/docs/tutorial/metadata.md index 3d9610978..c6f76d215 100644 --- a/docs/pt/docs/tutorial/metadata.md +++ b/docs/pt/docs/tutorial/metadata.md @@ -11,7 +11,7 @@ Você pode definir os seguintes campos que são usados na especificação OpenAP | `title` | `str` | O título da API. | | `summary` | `str` | Um breve resumo da API. Disponível desde OpenAPI 3.1.0, FastAPI 0.99.0. | | `description` | `str` | Uma breve descrição da API. Pode usar Markdown. | -| `version` | `string` | A versão da API. Esta é a versão da sua aplicação, não do OpenAPI. Por exemplo, `2.5.0`. | +| `version` | `str` | A versão da API. Esta é a versão da sua aplicação, não do OpenAPI. Por exemplo, `2.5.0`. | | `terms_of_service` | `str` | Uma URL para os Termos de Serviço da API. Se fornecido, deve ser uma URL. | | `contact` | `dict` | As informações de contato da API exposta. Pode conter vários campos.
Campos de contact
ParâmetroTipoDescrição
namestrO nome identificador da pessoa/organização de contato.
urlstrA URL que aponta para as informações de contato. DEVE estar no formato de uma URL.
emailstrO endereço de e-mail da pessoa/organização de contato. DEVE estar no formato de um endereço de e-mail.
| | `license_info` | `dict` | As informações de licença para a API exposta. Ela pode conter vários campos.
Campos de license_info
ParâmetroTipoDescrição
namestrOBRIGATÓRIO (se um license_info for definido). O nome da licença usada para a API.
identifierstrUma expressão de licença [SPDX](https://spdx.org/licenses/) para a API. O campo identifier é mutuamente exclusivo do campo url. Disponível desde OpenAPI 3.1.0, FastAPI 0.99.0.
urlstrUma URL para a licença usada para a API. DEVE estar no formato de uma URL.
| @@ -74,13 +74,13 @@ Use o parâmetro `tags` com suas *operações de rota* (e `APIRouter`s) para atr {* ../../docs_src/metadata/tutorial004_py310.py hl[21,26] *} -/// info | Informação +/// note | Nota Leia mais sobre tags em [Configuração de operação de rota](path-operation-configuration.md#tags). /// -### Cheque os documentos { #check-the-docs } +### Verifique a documentação { #check-the-docs } Agora, se você verificar a documentação, ela exibirá todos os metadados adicionais: diff --git a/docs/pt/docs/tutorial/path-operation-configuration.md b/docs/pt/docs/tutorial/path-operation-configuration.md index 745b9b698..cce159fa6 100644 --- a/docs/pt/docs/tutorial/path-operation-configuration.md +++ b/docs/pt/docs/tutorial/path-operation-configuration.md @@ -40,7 +40,7 @@ Eles serão adicionados ao esquema OpenAPI e usados pelas interfaces de document ### Tags com Enums { #tags-with-enums } -Se você tem uma grande aplicação, você pode acabar acumulando **várias tags**, e você gostaria de ter certeza de que você sempre usa a ** mesma tag** para *operações de rota* relacionadas. +Se você tem uma grande aplicação, você pode acabar acumulando **várias tags**, e você gostaria de ter certeza de que você sempre usa a **mesma tag** para *operações de rota* relacionadas. Nestes casos, pode fazer sentido armazenar as tags em um `Enum`. @@ -72,13 +72,13 @@ Você pode especificar a descrição da resposta com o parâmetro `response_desc {* ../../docs_src/path_operation_configuration/tutorial005_py310.py hl[18] *} -/// info | Informação +/// note | Nota -Note que `response_description` se refere especificamente à resposta, a `description` se refere à *operação de rota* em geral. +Observe que `response_description` se refere especificamente à resposta, a `description` se refere à *operação de rota* em geral. /// -/// check | Verifique +/// tip | Dica OpenAPI especifica que cada *operação de rota* requer uma descrição de resposta. diff --git a/docs/pt/docs/tutorial/path-params-numeric-validations.md b/docs/pt/docs/tutorial/path-params-numeric-validations.md index 9bbe14c75..0a48c09e4 100644 --- a/docs/pt/docs/tutorial/path-params-numeric-validations.md +++ b/docs/pt/docs/tutorial/path-params-numeric-validations.md @@ -8,7 +8,7 @@ Primeiro, importe `Path` de `fastapi`, e importe `Annotated`: {* ../../docs_src/path_params_numeric_validations/tutorial001_an_py310.py hl[1,3] *} -/// info | Informação +/// note | Nota O FastAPI adicionou suporte a `Annotated` (e passou a recomendá-lo) na versão 0.95.0. @@ -131,7 +131,7 @@ E você também pode declarar validações numéricas: * `lt`: menor que (`l`ess `t`han) * `le`: menor que ou igual (`l`ess than or `e`qual) -/// info | Informação +/// note | Nota `Query`, `Path` e outras classes que você verá depois são subclasses de uma classe comum `Param`. diff --git a/docs/pt/docs/tutorial/path-params.md b/docs/pt/docs/tutorial/path-params.md index ea9af63f3..30251970d 100644 --- a/docs/pt/docs/tutorial/path-params.md +++ b/docs/pt/docs/tutorial/path-params.md @@ -20,7 +20,7 @@ Você pode declarar o tipo de um parâmetro de path na função, usando as anota Neste caso, `item_id` é declarado como um `int`. -/// check | Verifique +/// tip | Dica Isso fornecerá suporte do editor dentro da sua função, com verificações de erros, preenchimento automático, etc. /// @@ -32,7 +32,7 @@ Se você executar este exemplo e abrir seu navegador em [http://127.0.0.1:8000/i {"item_id":3} ``` -/// check | Verifique +/// tip | Dica Perceba que o valor que sua função recebeu (e retornou) é `3`, como um `int` do Python, não uma string `"3"`. Então, com essa declaração de tipo, o **FastAPI** fornece "parsing" automático do request. @@ -62,7 +62,7 @@ porque o parâmetro de path `item_id` tinha o valor `"foo"`, que não é um `int O mesmo erro apareceria se você fornecesse um `float` em vez de um `int`, como em: [http://127.0.0.1:8000/items/4.2](http://127.0.0.1:8000/items/4.2) -/// check | Verifique +/// tip | Dica Então, com a mesma declaração de tipo do Python, o **FastAPI** fornece validação de dados. Observe que o erro também declara claramente exatamente o ponto onde a validação não passou. @@ -76,7 +76,7 @@ E quando você abrir seu navegador em [http://127.0.0.1:8000/docs](http://127.0. -/// check | Verifique +/// tip | Dica Novamente, apenas com a mesma declaração de tipo do Python, o **FastAPI** fornece documentação automática e interativa (integrando o Swagger UI). Observe que o parâmetro de path está declarado como um inteiro. diff --git a/docs/pt/docs/tutorial/query-params-str-validations.md b/docs/pt/docs/tutorial/query-params-str-validations.md index 5ee41684a..d37db2875 100644 --- a/docs/pt/docs/tutorial/query-params-str-validations.md +++ b/docs/pt/docs/tutorial/query-params-str-validations.md @@ -18,7 +18,7 @@ Ter `str | None` permitirá que seu editor lhe ofereça melhor suporte e detecte ## Validação adicional { #additional-validation } -Vamos impor que, embora `q` seja opcional, sempre que for fornecido, seu comprimento não exceda 50 caracteres. +Vamos impor que, embora `q` seja opcional, sempre que for fornecido, **seu comprimento não exceda 50 caracteres**. ### Importe `Query` e `Annotated` { #import-query-and-annotated } @@ -29,7 +29,7 @@ Para isso, primeiro importe: {* ../../docs_src/query_params_str_validations/tutorial002_an_py310.py hl[1,3] *} -/// info | Informação +/// note | Nota O FastAPI adicionou suporte a `Annotated` (e passou a recomendá-lo) na versão 0.95.0. @@ -69,19 +69,19 @@ Agora que temos esse `Annotated` onde podemos colocar mais informações (neste Perceba que o valor padrão continua sendo `None`, então o parâmetro ainda é opcional. -Mas agora, com `Query(max_length=50)` dentro de `Annotated`, estamos dizendo ao FastAPI que queremos validação adicional para este valor, queremos que tenha no máximo 50 caracteres. 😎 +Mas agora, com `Query(max_length=50)` dentro de `Annotated`, estamos dizendo ao FastAPI que queremos **validação adicional** para este valor, queremos que tenha no máximo 50 caracteres. 😎 /// tip | Dica -Aqui estamos usando `Query()` porque este é um parâmetro de consulta. Mais adiante veremos outros como `Path()`, `Body()`, `Header()` e `Cookie()`, que também aceitam os mesmos argumentos que `Query()`. +Aqui estamos usando `Query()` porque este é um **parâmetro de consulta**. Mais adiante veremos outros como `Path()`, `Body()`, `Header()` e `Cookie()`, que também aceitam os mesmos argumentos que `Query()`. /// Agora o FastAPI vai: -* Validar os dados garantindo que o comprimento máximo seja de 50 caracteres -* Mostrar um erro claro para o cliente quando os dados não forem válidos -* Documentar o parâmetro na operação de rota do esquema OpenAPI (então ele aparecerá na UI de docs automática) +* **Validar** os dados garantindo que o comprimento máximo seja de 50 caracteres +* Mostrar um **erro claro** para o cliente quando os dados não forem válidos +* **Documentar** o parâmetro na *operação de rota* do esquema OpenAPI (então ele aparecerá na **UI de documentação automática**) ## Alternativa (antiga): `Query` como valor padrão { #alternative-old-query-as-the-default-value } @@ -120,7 +120,7 @@ Então, podemos passar mais parâmetros para `Query`. Neste caso, o parâmetro ` q: str | None = Query(default=None, max_length=50) ``` -Isso validará os dados, mostrará um erro claro quando os dados não forem válidos e documentará o parâmetro na operação de rota do esquema OpenAPI. +Isso validará os dados, mostrará um erro claro quando os dados não forem válidos e documentará o parâmetro na *operação de rota* do esquema OpenAPI. ### `Query` como valor padrão ou em `Annotated` { #query-as-the-default-value-or-in-annotated } @@ -150,13 +150,13 @@ q: str = Query(default="rick") ### Vantagens de `Annotated` { #advantages-of-annotated } -Usar `Annotated` é recomendado em vez do valor padrão nos parâmetros da função, é melhor por vários motivos. 🤓 +**Usar `Annotated` é recomendado** em vez do valor padrão nos parâmetros da função, é **melhor** por vários motivos. 🤓 -O valor padrão do parâmetro da função é o valor padrão real, isso é mais intuitivo com Python em geral. 😌 +O valor **padrão** do **parâmetro da função** é o valor **padrão real**, isso é mais intuitivo com Python em geral. 😌 -Você poderia chamar essa mesma função em outros lugares sem FastAPI, e ela funcionaria como esperado. Se houver um parâmetro obrigatório (sem valor padrão), seu editor vai avisar com um erro, e o Python também reclamará se você executá-la sem passar o parâmetro obrigatório. +Você poderia **chamar** essa mesma função em **outros lugares** sem FastAPI, e ela **funcionaria como esperado**. Se houver um parâmetro **obrigatório** (sem valor padrão), seu **editor** vai avisar com um erro, e o **Python** também reclamará se você executá-la sem passar o parâmetro obrigatório. -Quando você não usa `Annotated` e em vez disso usa o estilo de valor padrão (antigo), se você chamar essa função sem FastAPI em outros lugares, terá que lembrar de passar os argumentos para a função para que funcione corretamente, caso contrário os valores serão diferentes do esperado (por exemplo, `QueryInfo` ou algo parecido em vez de `str`). E seu editor não vai avisar, e o Python também não vai reclamar ao executar a função, apenas quando as operações internas falharem. +Quando você não usa `Annotated` e em vez disso usa o **estilo de valor padrão (antigo)**, se você chamar essa função sem FastAPI em **outros lugares**, terá que **lembrar** de passar os argumentos para a função para que funcione corretamente, caso contrário os valores serão diferentes do esperado (por exemplo, `QueryInfo` ou algo parecido em vez de `str`). E seu editor não vai avisar, e o Python também não vai reclamar ao executar a função, apenas quando as operações internas falharem. Como `Annotated` pode ter mais de uma anotação de metadados, você agora pode até usar a mesma função com outras ferramentas, como o [Typer](https://typer.tiangolo.com/). 🚀 @@ -168,7 +168,7 @@ Você também pode adicionar um parâmetro `min_length`: ## Adicione expressões regulares { #add-regular-expressions } -Você pode definir um `pattern` de expressão regular que o parâmetro deve corresponder: +Você pode definir um `pattern` de expressão regular que o parâmetro deve corresponder: {* ../../docs_src/query_params_str_validations/tutorial004_an_py310.py hl[11] *} @@ -178,9 +178,9 @@ Esse padrão específico de expressão regular verifica se o valor recebido no p * `fixedquery`: tem exatamente o valor `fixedquery`. * `$`: termina ali, não tem mais caracteres depois de `fixedquery`. -Se você se sentir perdido com essas ideias de "expressão regular", não se preocupe. Esse é um assunto difícil para muitas pessoas. Você ainda pode fazer muitas coisas sem precisar de expressões regulares por enquanto. +Se você se sentir perdido com essas ideias de **"expressão regular"**, não se preocupe. Esse é um assunto difícil para muitas pessoas. Você ainda pode fazer muitas coisas sem precisar de expressões regulares por enquanto. -Agora você sabe que, sempre que precisar delas, pode usá-las no FastAPI. +Agora você sabe que, sempre que precisar delas, pode usá-las no **FastAPI**. ## Valores padrão { #default-values } @@ -242,7 +242,7 @@ Então, com uma URL como: http://localhost:8000/items/?q=foo&q=bar ``` -você receberia os múltiplos valores dos parâmetros de consulta `q` (`foo` e `bar`) em uma `list` Python dentro da sua função de operação de rota, no parâmetro da função `q`. +você receberia os múltiplos valores dos *parâmetros de consulta* `q` (`foo` e `bar`) em uma `list` Python dentro da sua *função de operação de rota*, no *parâmetro da função* `q`. Assim, a resposta para essa URL seria: @@ -298,7 +298,7 @@ Você também pode usar `list` diretamente em vez de `list[str]`: Tenha em mente que, neste caso, o FastAPI não verificará o conteúdo da lista. -Por exemplo, `list[int]` verificaria (and documentaria) que os conteúdos da lista são inteiros. Mas `list` sozinho não. +Por exemplo, `list[int]` verificaria (e documentaria) que os conteúdos da lista são inteiros. Mas `list` sozinho não. /// @@ -360,15 +360,15 @@ A documentação vai mostrar assim: ## Excluir parâmetros do OpenAPI { #exclude-parameters-from-openapi } -Para excluir um parâmetro de consulta do OpenAPI gerado (e portanto, dos sistemas de documentação automáticos), defina o parâmetro `include_in_schema` de `Query` como `False`: +Para excluir um parâmetro de consulta do esquema OpenAPI gerado (e portanto, dos sistemas de documentação automáticos), defina o parâmetro `include_in_schema` de `Query` como `False`: {* ../../docs_src/query_params_str_validations/tutorial014_an_py310.py hl[10] *} ## Validação personalizada { #custom-validation } -Podem existir casos em que você precise fazer alguma validação personalizada que não pode ser feita com os parâmetros mostrados acima. +Podem existir casos em que você precise fazer alguma **validação personalizada** que não pode ser feita com os parâmetros mostrados acima. -Nesses casos, você pode usar uma função validadora personalizada que é aplicada após a validação normal (por exemplo, depois de validar que o valor é uma `str`). +Nesses casos, você pode usar uma **função validadora personalizada** que é aplicada após a validação normal (por exemplo, depois de validar que o valor é uma `str`). Você pode fazer isso usando o [`AfterValidator` do Pydantic](https://docs.pydantic.dev/latest/concepts/validators/#field-after-validator) dentro de `Annotated`. @@ -382,7 +382,7 @@ Por exemplo, este validador personalizado verifica se o ID do item começa com ` {* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py hl[5,16:19,24] *} -/// info | Informação +/// note | Nota Isso está disponível com a versão 2 do Pydantic ou superior. 😎 @@ -390,15 +390,15 @@ Isso está disponível com a versão 2 do Pydantic ou superior. 😎 /// tip | Dica -Se você precisar fazer qualquer tipo de validação que exija comunicação com algum componente externo, como um banco de dados ou outra API, você deveria usar Dependências do FastAPI em vez disso; você aprenderá sobre elas mais adiante. +Se você precisar fazer qualquer tipo de validação que exija comunicação com algum **componente externo**, como um banco de dados ou outra API, você deveria usar **Dependências do FastAPI** em vez disso; você aprenderá sobre elas mais adiante. -Esses validadores personalizados são para coisas que podem ser verificadas apenas com os mesmos dados fornecidos na requisição. +Esses validadores personalizados são para coisas que podem ser verificadas **apenas** com os **mesmos dados** fornecidos na requisição. /// ### Entenda esse código { #understand-that-code } -O ponto importante é apenas usar `AfterValidator` com uma função dentro de `Annotated`. Sinta-se à vontade para pular esta parte. 🤸 +O ponto importante é apenas usar **`AfterValidator` com uma função dentro de `Annotated`**. Sinta-se à vontade para pular esta parte. 🤸 --- @@ -414,15 +414,15 @@ Percebeu? Uma string usando `value.startswith()` pode receber uma tupla, e verif Com `data.items()` obtemos um objeto iterável com tuplas contendo a chave e o valor de cada item do dicionário. -Convertimos esse objeto iterável em uma `list` adequada com `list(data.items())`. +Convertemos esse objeto iterável em uma `list` adequada com `list(data.items())`. -Em seguida, com `random.choice()` podemos obter um valor aleatório da lista, então obtemos uma tupla com `(id, name)`. Será algo como `("imdb-tt0371724", "The Hitchhiker's Guide to the Galaxy")`. +Em seguida, com `random.choice()` podemos obter um **valor aleatório** da lista, então obtemos uma tupla com `(id, name)`. Será algo como `("imdb-tt0371724", "The Hitchhiker's Guide to the Galaxy")`. -Depois atribuímos esses dois valores da tupla às variáveis `id` e `name`. +Depois **atribuímos esses dois valores** da tupla às variáveis `id` e `name`. Assim, se o usuário não fornecer um ID de item, ele ainda receberá uma sugestão aleatória. -...fazemos tudo isso em uma única linha simples. 🤯 Você não ama Python? 🐍 +...fazemos tudo isso em uma **única linha simples**. 🤯 Você não ama Python? 🐍 {* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py ln[22:30] hl[29] *} diff --git a/docs/pt/docs/tutorial/query-params.md b/docs/pt/docs/tutorial/query-params.md index 472c12be6..1f098ee7a 100644 --- a/docs/pt/docs/tutorial/query-params.md +++ b/docs/pt/docs/tutorial/query-params.md @@ -54,8 +54,8 @@ http://127.0.0.1:8000/items/?skip=20 Os valores dos parâmetros na sua função serão: -* `skip=20`: Por que você definiu isso na URL -* `limit=10`: Por que esse era o valor padrão +* `skip=20`: porque você definiu isso na URL +* `limit=10`: porque esse era o valor padrão ## Parâmetros opcionais { #optional-parameters } @@ -65,7 +65,7 @@ Da mesma forma, você pode declarar parâmetros de consulta opcionais, definindo Nesse caso, o parâmetro da função `q` será opcional, e `None` será o padrão. -/// check | Verifique +/// tip | Dica Você também pode notar que o **FastAPI** é esperto o suficiente para perceber que o parâmetro da rota `item_id` é um parâmetro da rota, e `q` não é, portanto, `q` é o parâmetro de consulta. @@ -109,6 +109,7 @@ http://127.0.0.1:8000/items/foo?short=yes ou qualquer outra variação (tudo em maiúscula, primeira letra em maiúscula, etc), a sua função vai ver o parâmetro `short` com um valor `bool` de `True`. Caso contrário `False`. + ## Múltiplos parâmetros de rota e consulta { #multiple-path-and-query-parameters } Você pode declarar múltiplos parâmetros de rota e parâmetros de consulta ao mesmo tempo, o **FastAPI** vai saber o quê é o quê. @@ -129,9 +130,9 @@ Porém, quando você quiser fazer com que o parâmetro de consulta seja obrigat {* ../../docs_src/query_params/tutorial005_py310.py hl[6:7] *} -Aqui o parâmetro da consulta `needy` é um valor obrigatório, do tipo `str`. +Aqui o parâmetro da consulta `needy` é um parâmetro de consulta obrigatório, do tipo `str`. -Se você abrir no seu navegador a URL: +Se você abrir no seu navegador uma URL como: ``` http://127.0.0.1:8000/items/foo-item diff --git a/docs/pt/docs/tutorial/request-files.md b/docs/pt/docs/tutorial/request-files.md index 912878cd5..8b3463036 100644 --- a/docs/pt/docs/tutorial/request-files.md +++ b/docs/pt/docs/tutorial/request-files.md @@ -2,7 +2,7 @@ Você pode definir arquivos para serem enviados pelo cliente usando `File`. -/// info | Informação +/// note | Nota Para receber arquivos enviados, primeiro instale [`python-multipart`](https://github.com/Kludex/python-multipart). @@ -28,7 +28,7 @@ Crie parâmetros de arquivo da mesma forma que você faria para `Body` ou `Form` {* ../../docs_src/request_files/tutorial001_an_py310.py hl[9] *} -/// info | Informação +/// note | Nota `File` é uma classe que herda diretamente de `Form`. @@ -44,7 +44,7 @@ Para declarar corpos de arquivos, você precisa usar `File`, caso contrário, os Os arquivos serão enviados como "dados de formulário". -Se você declarar o tipo do parâmetro da função da sua *operação de rota* como `bytes`, o **FastAPI** lerá o arquivo para você e você receberá o conteúdo como `bytes`. +Se você declarar o tipo do parâmetro da sua *função de operação de rota* como `bytes`, o **FastAPI** lerá o arquivo para você e você receberá o conteúdo como `bytes`. Mantenha em mente que isso significa que todo o conteúdo será armazenado na memória. Isso funcionará bem para arquivos pequenos. @@ -63,8 +63,8 @@ Utilizar `UploadFile` tem várias vantagens sobre `bytes`: * Um arquivo armazenado na memória até um limite máximo de tamanho, e após passar esse limite, ele será armazenado no disco. * Isso significa que funcionará bem para arquivos grandes como imagens, vídeos, binários grandes, etc., sem consumir toda a memória. * Você pode receber metadados do arquivo enviado. -* Ele tem uma [file-like](https://docs.python.org/3/glossary.html#term-file-like-object) interface `assíncrona`. -* Ele expõe um objeto python [`SpooledTemporaryFile`](https://docs.python.org/3/library/tempfile.html#tempfile.SpooledTemporaryFile) que você pode passar diretamente para outras bibliotecas que esperam um objeto semelhante a um arquivo. +* Ele tem uma interface [file-like](https://docs.python.org/3/glossary.html#term-file-like-object) `async`. +* Ele expõe um objeto Python [`SpooledTemporaryFile`](https://docs.python.org/3/library/tempfile.html#tempfile.SpooledTemporaryFile) real que você pode passar diretamente para outras bibliotecas que esperam um objeto semelhante a um arquivo. ### `UploadFile` { #uploadfile } @@ -72,9 +72,9 @@ Utilizar `UploadFile` tem várias vantagens sobre `bytes`: * `filename`: Uma `str` com o nome do arquivo original que foi enviado (por exemplo, `myimage.jpg`). * `content_type`: Uma `str` com o tipo de conteúdo (MIME type / media type) (por exemplo, `image/jpeg`). -* `file`: Um [`SpooledTemporaryFile`](https://docs.python.org/3/library/tempfile.html#tempfile.SpooledTemporaryFile) (um [file-like](https://docs.python.org/3/glossary.html#term-file-like-object) objeto). Este é o objeto de arquivo Python que você pode passar diretamente para outras funções ou bibliotecas que esperam um objeto semelhante a um arquivo. +* `file`: Um [`SpooledTemporaryFile`](https://docs.python.org/3/library/tempfile.html#tempfile.SpooledTemporaryFile) (um objeto [file-like](https://docs.python.org/3/glossary.html#term-file-like-object)). Este é o objeto de arquivo Python que você pode passar diretamente para outras funções ou bibliotecas que esperam um objeto semelhante a um arquivo. -`UploadFile` tem os seguintes métodos `assíncronos`. Todos eles chamam os métodos de arquivo correspondentes por baixo dos panos (usando o `SpooledTemporaryFile` interno). +`UploadFile` tem os seguintes métodos `async`. Todos eles chamam os métodos de arquivo correspondentes por baixo dos panos (usando o `SpooledTemporaryFile` interno). * `write(data)`: Escreve `data` (`str` ou `bytes`) no arquivo. * `read(size)`: Lê `size` (`int`) bytes/caracteres do arquivo. @@ -83,15 +83,15 @@ Utilizar `UploadFile` tem várias vantagens sobre `bytes`: * Isso é especialmente útil se você executar `await myfile.read()` uma vez e precisar ler o conteúdo novamente. * `close()`: Fecha o arquivo. -Como todos esses métodos são métodos `assíncronos`, você precisa "aguardar" por eles. +Como todos esses métodos são métodos `async`, você precisa "aguardar" por eles. -Por exemplo, dentro de uma função de *operação de rota* `assíncrona`, você pode obter o conteúdo com: +Por exemplo, dentro de uma *função de operação de rota* `async`, você pode obter o conteúdo com: ```Python contents = await myfile.read() ``` -Se você estiver dentro de uma função de *operação de rota* normal `def`, você pode acessar o `UploadFile.file` diretamente, por exemplo: +Se você estiver dentro de uma *função de operação de rota* normal `def`, você pode acessar o `UploadFile.file` diretamente, por exemplo: ```Python contents = myfile.file.read() @@ -109,7 +109,7 @@ O `UploadFile` do **FastAPI** herda diretamente do `UploadFile` do **Starlette** /// -## O que é "Form Data" { #what-is-form-data } +## O que são "Dados de Formulário" { #what-is-form-data } O jeito que os formulários HTML (`
`) enviam os dados para o servidor normalmente usa uma codificação "especial" para esses dados, a qual é diferente do JSON. @@ -119,9 +119,9 @@ O jeito que os formulários HTML (`
`) enviam os dados para o servid Dados de formulários normalmente são codificados usando o "media type" `application/x-www-form-urlencoded` quando não incluem arquivos. -Mas quando o formulário inclui arquivos, ele é codificado como `multipart/form-data`. Se você usar `File`, o **FastAPI** saberá que tem que pegar os arquivos da parte correta do corpo da requisição. +Mas quando o formulário inclui arquivos, ele é codificado como `multipart/form-data`. Se você usar `File`, o **FastAPI** saberá que tem que pegar os arquivos da parte correta do corpo. -Se você quiser ler mais sobre essas codificações e campos de formulário, vá para a [MDN web docs para `POST`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST). +Se você quiser ler mais sobre essas codificações e campos de formulário, vá para a [documentação web da MDN para `POST`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST). /// diff --git a/docs/pt/docs/tutorial/request-form-models.md b/docs/pt/docs/tutorial/request-form-models.md index 953c3fdce..8e265d6ad 100644 --- a/docs/pt/docs/tutorial/request-form-models.md +++ b/docs/pt/docs/tutorial/request-form-models.md @@ -2,7 +2,7 @@ Você pode utilizar **Modelos Pydantic** para declarar **campos de formulários** no FastAPI. -/// info | Informação +/// note | Nota Para utilizar formulários, instale primeiramente o [`python-multipart`](https://github.com/Kludex/python-multipart). @@ -28,7 +28,7 @@ Você precisa apenas declarar um **modelo Pydantic** com os campos que deseja re O **FastAPI** irá **extrair** as informações para **cada campo** dos **dados do formulário** na requisição e dar para você o modelo Pydantic que você definiu. -## Confira os Documentos { #check-the-docs } +## Confira a Documentação { #check-the-docs } Você pode verificar na UI de documentação em `/docs`: diff --git a/docs/pt/docs/tutorial/request-forms-and-files.md b/docs/pt/docs/tutorial/request-forms-and-files.md index 04d7f9a4e..45d6f5c2c 100644 --- a/docs/pt/docs/tutorial/request-forms-and-files.md +++ b/docs/pt/docs/tutorial/request-forms-and-files.md @@ -2,7 +2,7 @@ Você pode definir arquivos e campos de formulário ao mesmo tempo usando `File` e `Form`. -/// info | Informação +/// note | Nota Para receber arquivos carregados e/ou dados de formulário, primeiro instale [`python-multipart`](https://github.com/Kludex/python-multipart). diff --git a/docs/pt/docs/tutorial/request-forms.md b/docs/pt/docs/tutorial/request-forms.md index 5b7c4d809..bfca3562a 100644 --- a/docs/pt/docs/tutorial/request-forms.md +++ b/docs/pt/docs/tutorial/request-forms.md @@ -2,7 +2,7 @@ Quando você precisar receber campos de formulário em vez de JSON, você pode usar `Form`. -/// info | Informação +/// note | Nota Para usar formulários, primeiro instale [`python-multipart`](https://github.com/Kludex/python-multipart). @@ -32,7 +32,7 @@ A especificação exige que os campos sejam e Com `Form` você pode declarar as mesmas configurações que com `Body` (e `Query`, `Path`, `Cookie`), incluindo validação, exemplos, um alias (por exemplo, `user-name` em vez de `username`), etc. -/// info | Informação +/// note | Nota `Form` é uma classe que herda diretamente de `Body`. @@ -56,7 +56,7 @@ Os dados dos formulários são normalmente codificados usando o "media type" `ap Mas quando o formulário inclui arquivos, ele é codificado como `multipart/form-data`. Você lerá sobre como lidar com arquivos no próximo capítulo. -Se você quiser ler mais sobre essas codificações e campos de formulário, vá para o [MDN web docs para `POST`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST). +Se você quiser ler mais sobre essas codificações e campos de formulário, vá para a [documentação web da MDN para `POST`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST). /// diff --git a/docs/pt/docs/tutorial/response-model.md b/docs/pt/docs/tutorial/response-model.md index 7a28bcecd..1753f9dae 100644 --- a/docs/pt/docs/tutorial/response-model.md +++ b/docs/pt/docs/tutorial/response-model.md @@ -72,7 +72,7 @@ Aqui estamos declarando um modelo `UserIn`, ele conterá uma senha em texto simp {* ../../docs_src/response_model/tutorial002_py310.py hl[7,9] *} -/// info | Informação +/// note | Nota Para usar `EmailStr`, primeiro instale [`email-validator`](https://github.com/JoshData/python-email-validator). @@ -251,7 +251,7 @@ Então, se você enviar uma solicitação para essa *operação de rota* para o } ``` -/// info | Informação +/// note | Nota Você também pode usar: diff --git a/docs/pt/docs/tutorial/response-status-code.md b/docs/pt/docs/tutorial/response-status-code.md index d5a81fa03..aeeaf225d 100644 --- a/docs/pt/docs/tutorial/response-status-code.md +++ b/docs/pt/docs/tutorial/response-status-code.md @@ -12,13 +12,13 @@ Da mesma forma que você pode especificar um modelo de resposta, você também p /// note | Nota -Observe que `status_code` é um parâmetro do método "decorador" (`get`, `post`, etc). Não da sua função de *operação de rota*, como todos os parâmetros e corpo. +Observe que `status_code` é um parâmetro do método "decorador" (`get`, `post`, etc). Não da sua *função de operação de rota*, como todos os parâmetros e corpo. /// O parâmetro `status_code` recebe um número com o código de status HTTP. -/// info | Informação +/// note | Nota `status_code` também pode receber um `IntEnum`, como [`http.HTTPStatus`](https://docs.python.org/3/library/http.html#http.HTTPStatus) do Python. @@ -35,7 +35,7 @@ Dessa forma: Alguns códigos de resposta (consulte a próxima seção) indicam que a resposta não possui um corpo. -O FastAPI sabe disso e produzirá documentos OpenAPI informando que não há corpo de resposta. +O FastAPI sabe disso e produzirá documentação OpenAPI informando que não há corpo de resposta. /// @@ -84,7 +84,7 @@ Você pode usar as variáveis de conveniência de `fastapi.status`. {* ../../docs_src/response_status_code/tutorial002_py310.py hl[1,6] *} -Eles são apenas uma conveniência, eles possuem o mesmo número, mas dessa forma você pode usar o preenchimento automático do editor para encontrá-los: +Eles são apenas uma conveniência, eles possuem o mesmo número, mas dessa forma você pode usar o autocompletar do editor para encontrá-los: diff --git a/docs/pt/docs/tutorial/schema-extra-example.md b/docs/pt/docs/tutorial/schema-extra-example.md index cd2ac13c5..6e10c5857 100644 --- a/docs/pt/docs/tutorial/schema-extra-example.md +++ b/docs/pt/docs/tutorial/schema-extra-example.md @@ -1,5 +1,6 @@ # Declare dados de exemplo da requisição { #declare-request-example-data } + Você pode declarar exemplos dos dados que sua aplicação pode receber. Aqui estão várias maneiras de fazer isso. @@ -24,7 +25,7 @@ Por exemplo, você poderia usá-la para adicionar metadados para uma interface d /// -/// info | Informação +/// note | Nota O OpenAPI 3.1.0 (usado desde o FastAPI 0.99.0) adicionou suporte a `examples`, que faz parte do padrão **JSON Schema**. @@ -155,7 +156,7 @@ O OpenAPI também adicionou os campos `example` e `examples` a outras partes da * `File()` * `Form()` -/// info | Informação +/// note | Nota Esse parâmetro antigo `examples` específico do OpenAPI agora é `openapi_examples` desde o FastAPI `0.103.0`. @@ -171,7 +172,7 @@ E agora esse novo campo `examples` tem precedência sobre o antigo campo único Esse novo campo `examples` no JSON Schema é **apenas uma `list`** de exemplos, não um dict com metadados extras como nos outros lugares do OpenAPI (descritos acima). -/// info | Informação +/// note | Nota Mesmo após o lançamento do OpenAPI 3.1.0 com essa nova integração mais simples com o JSON Schema, por um tempo o Swagger UI, a ferramenta que fornece a documentação automática, não suportava OpenAPI 3.1.0 (passou a suportar desde a versão 5.0.0 🎉). diff --git a/docs/pt/docs/tutorial/security/first-steps.md b/docs/pt/docs/tutorial/security/first-steps.md index d16c15140..9780f8a69 100644 --- a/docs/pt/docs/tutorial/security/first-steps.md +++ b/docs/pt/docs/tutorial/security/first-steps.md @@ -24,7 +24,7 @@ Copie o exemplo em um arquivo `main.py`: ## Execute-o { #run-it } -/// info | Informação +/// note | Nota O pacote [`python-multipart`](https://github.com/Kludex/python-multipart) é instalado automaticamente com o **FastAPI** quando você executa o comando `pip install "fastapi[standard]"`. @@ -60,11 +60,11 @@ Você verá algo deste tipo: -/// check | Botão Autorizar! +/// tip | Botão Autorizar! -Você já tem um novo botão 'Authorize'. +Você já tem um novo e brilhante botão "Authorize". -E sua operação de rota tem um pequeno cadeado no canto superior direito em que você pode clicar. +E sua *operação de rota* tem um pequeno cadeado no canto superior direito em que você pode clicar. /// @@ -80,7 +80,7 @@ Não importa o que você digite no formulário, ainda não vai funcionar. Mas n Claro que este não é o frontend para os usuários finais, mas é uma ótima ferramenta automática para documentar interativamente toda a sua API. -Pode ser usada pelo time de frontend (que pode ser você mesmo). +Pode ser usada pela equipe de frontend (que pode ser você mesmo). Pode ser usada por aplicações e sistemas de terceiros. @@ -106,7 +106,7 @@ Então, vamos rever de um ponto de vista simplificado: * Então, o usuário terá que fazer login novamente em algum momento. * E se o token for roubado, o risco é menor. Não é como uma chave permanente que funcionará para sempre (na maioria dos casos). * O frontend armazena esse token temporariamente em algum lugar. -* O usuário clica no frontend para ir para outra seção do aplicativo web. +* O usuário clica no frontend para ir para outra seção da aplicação web do frontend. * O frontend precisa buscar mais dados da API. * Mas precisa de autenticação para aquele endpoint específico. * Então, para autenticar com nossa API, ele envia um header `Authorization` com o valor `Bearer ` mais o token. @@ -118,7 +118,7 @@ O **FastAPI** fornece várias ferramentas, em diferentes níveis de abstração, Neste exemplo, vamos usar **OAuth2**, com o fluxo **Password**, usando um token **Bearer**. Fazemos isso usando a classe `OAuth2PasswordBearer`. -/// info | Informação +/// note | Nota Um token "bearer" não é a única opção. @@ -144,11 +144,11 @@ Usar uma URL relativa é importante para garantir que sua aplicação continue f /// -Esse parâmetro não cria aquele endpoint/operação de rota, mas declara que a URL `/token` será aquela que o client deve usar para obter o token. Essa informação é usada no OpenAPI e depois nos sistemas de documentação interativa da API. +Esse parâmetro não cria aquele endpoint / *operação de rota*, mas declara que a URL `/token` será aquela que o client deve usar para obter o token. Essa informação é usada no OpenAPI e depois nos sistemas de documentação interativa da API. Em breve também criaremos a operação de rota real. -/// info | Informação +/// note | Nota Se você é um "Pythonista" muito rigoroso, pode não gostar do estilo do nome do parâmetro `tokenUrl` em vez de `token_url`. @@ -176,7 +176,7 @@ Essa dependência fornecerá uma `str` que é atribuída ao parâmetro `token` d O **FastAPI** saberá que pode usar essa dependência para definir um "esquema de segurança" no esquema OpenAPI (e na documentação automática da API). -/// info | Detalhes Técnicos +/// note | Detalhes Técnicos O **FastAPI** saberá que pode usar a classe `OAuth2PasswordBearer` (declarada em uma dependência) para definir o esquema de segurança no OpenAPI porque ela herda de `fastapi.security.oauth2.OAuth2`, que por sua vez herda de `fastapi.security.base.SecurityBase`. diff --git a/docs/pt/docs/tutorial/security/get-current-user.md b/docs/pt/docs/tutorial/security/get-current-user.md index 4c6397c31..d56de4f8f 100644 --- a/docs/pt/docs/tutorial/security/get-current-user.md +++ b/docs/pt/docs/tutorial/security/get-current-user.md @@ -14,11 +14,11 @@ Primeiro, vamos criar um modelo de usuário com Pydantic. Da mesma forma que usamos o Pydantic para declarar corpos, podemos usá-lo em qualquer outro lugar: -{* ../../docs_src/security/tutorial002_an_py310.py hl[5,12:6] *} +{* ../../docs_src/security/tutorial002_an_py310.py hl[5,12:16] *} ## Criar uma dependência `get_current_user` { #create-a-get-current-user-dependency } -Vamos criar uma dependência chamada `get_current_user`. +Vamos criar uma dependência `get_current_user`. Lembra que as dependências podem ter subdependências? @@ -52,7 +52,7 @@ Aqui, o **FastAPI** não ficará confuso porque você está usando `Depends`. /// -/// check | Verifique +/// tip | Dica A forma como esse sistema de dependências foi projetado nos permite ter diferentes dependências (diferentes "dependables") que retornam um modelo `User`. diff --git a/docs/pt/docs/tutorial/security/oauth2-jwt.md b/docs/pt/docs/tutorial/security/oauth2-jwt.md index 6397664fb..dbbbdc79d 100644 --- a/docs/pt/docs/tutorial/security/oauth2-jwt.md +++ b/docs/pt/docs/tutorial/security/oauth2-jwt.md @@ -1,6 +1,6 @@ # OAuth2 com Senha (e hashing), Bearer com tokens JWT { #oauth2-with-password-and-hashing-bearer-with-jwt-tokens } -Agora que temos todo o fluxo de segurança, vamos tornar a aplicação realmente segura, usando tokens JWT e hashing de senhas seguras. +Agora que temos todo o fluxo de segurança, vamos tornar a aplicação realmente segura, usando tokens JWT e hashing seguro de senhas. Este código é algo que você pode realmente usar na sua aplicação, salvar os hashes das senhas no seu banco de dados, etc. @@ -42,9 +42,9 @@ $ pip install pyjwt -/// info | Informação +/// note | Nota -Se você pretente utilizar algoritmos de assinatura digital como o RSA ou o ECDSA, você deve instalar a dependência da biblioteca de criptografia `pyjwt[crypto]`. +Se você pretende utilizar algoritmos de assinatura digital como o RSA ou o ECDSA, você deveria instalar a dependência da biblioteca de criptografia `pyjwt[crypto]`. Você pode ler mais sobre isso na [documentação de instalação do PyJWT](https://pyjwt.readthedocs.io/en/latest/installation.html). @@ -88,7 +88,7 @@ $ pip install "pwdlib[argon2]" Com o `pwdlib`, você poderia até configurá-lo para ser capaz de ler senhas criadas pelo **Django**, um plug-in de segurança do **Flask** ou muitos outros. -Assim, você poderia, por exemplo, compartilhar os mesmos dados de um aplicativo Django em um banco de dados com um aplicativo FastAPI. Ou migrar gradualmente uma aplicação Django usando o mesmo banco de dados. +Assim, você poderia, por exemplo, compartilhar os mesmos dados de uma aplicação Django em um banco de dados com uma aplicação FastAPI. Ou migrar gradualmente uma aplicação Django usando o mesmo banco de dados. E seus usuários poderiam fazer login tanto pela sua aplicação Django quanto pela sua aplicação **FastAPI**, ao mesmo tempo. @@ -213,7 +213,7 @@ Usando as credenciais: Username: `johndoe` Password: `secret` -/// check | Verifique +/// tip | Dica Observe que em nenhuma parte do código está a senha em texto puro "`secret`", nós temos apenas o hash. @@ -260,7 +260,7 @@ Com o que você viu até agora, você pode configurar uma aplicação **FastAPI* Em quase qualquer framework, lidar com a segurança se torna rapidamente um assunto bastante complexo. -Muitos pacotes que simplificam bastante isso precisam fazer muitas concessões com o modelo de dados, o banco de dados e os recursos disponíveis. E alguns desses pacotes que simplificam demais na verdade têm falhas de segurança subjacentes. +Muitos pacotes que simplificam bastante isso precisam fazer muitas concessões com o modelo de dados, o banco de dados e as funcionalidades disponíveis. E alguns desses pacotes que simplificam demais na verdade têm falhas de segurança subjacentes. --- diff --git a/docs/pt/docs/tutorial/security/simple-oauth2.md b/docs/pt/docs/tutorial/security/simple-oauth2.md index f582a8141..802879a53 100644 --- a/docs/pt/docs/tutorial/security/simple-oauth2.md +++ b/docs/pt/docs/tutorial/security/simple-oauth2.md @@ -4,9 +4,9 @@ Agora vamos construir a partir do capítulo anterior e adicionar as partes que f ## Obtenha o `username` e a `password` { #get-the-username-and-password } -É utilizado o utils de segurança da **FastAPI** para obter o `username` e a `password`. +Vamos usar os utilitários de segurança da **FastAPI** para obter o `username` e a `password`. -OAuth2 especifica que ao usar o "password flow" (fluxo de senha), que estamos usando, o cliente/usuário deve enviar os campos `username` e `password` como dados do formulário. +OAuth2 especifica que, ao usar o "fluxo de senha" (que estamos usando), o cliente/usuário deve enviar os campos `username` e `password` como dados do formulário. E a especificação diz que os campos devem ser nomeados assim. Portanto, `user-name` ou `email` não funcionariam. @@ -29,10 +29,10 @@ Cada “scope” é apenas uma string (sem espaços). Normalmente são usados para declarar permissões de segurança específicas, por exemplo: * `users:read` ou `users:write` são exemplos comuns. -* `instagram_basic` é usado pelo Facebook e Instagram. +* `instagram_basic` é usado pelo Facebook / Instagram. * `https://www.googleapis.com/auth/drive` é usado pelo Google. -/// info | Informação +/// note | Nota No OAuth2, um "scope" é apenas uma string que declara uma permissão específica necessária. @@ -72,13 +72,13 @@ Se você precisar aplicá-lo, use `OAuth2PasswordRequestFormStrict` em vez de `O * Um `client_id` opcional (não precisamos dele em nosso exemplo). * Um `client_secret` opcional (não precisamos dele em nosso exemplo). -/// info | Informação +/// note | Nota O `OAuth2PasswordRequestForm` não é uma classe especial para **FastAPI** como é `OAuth2PasswordBearer`. `OAuth2PasswordBearer` faz com que **FastAPI** saiba que é um esquema de segurança. Portanto, é adicionado dessa forma ao OpenAPI. -Mas `OAuth2PasswordRequestForm` é apenas uma dependência de classe que você mesmo poderia ter escrito ou poderia ter declarado os parâmetros do `Form` (formulário) diretamente. +Mas `OAuth2PasswordRequestForm` é apenas uma dependência de classe que você mesmo poderia ter escrito ou poderia ter declarado os parâmetros de `Form` diretamente. Mas como é um caso de uso comum, ele é fornecido diretamente pelo **FastAPI**, apenas para facilitar. @@ -108,7 +108,7 @@ Neste ponto temos os dados do usuário do nosso banco de dados, mas não verific Vamos colocar esses dados primeiro no modelo `UserInDB` do Pydantic. -Você nunca deve salvar senhas em texto simples, portanto, usaremos o sistema de hashing de senhas (falsas). +Você nunca deveria salvar senhas em texto simples, portanto, usaremos o sistema (falso) de hashing de senhas. Se as senhas não corresponderem, retornaremos o mesmo erro. @@ -120,7 +120,7 @@ Sempre que você passa exatamente o mesmo conteúdo (exatamente a mesma senha), Mas você não pode converter a sequência aleatória de caracteres de volta para a senha. -##### Porque usar hashing de senha { #why-use-password-hashing } +##### Por que usar hashing de senha { #why-use-password-hashing } Se o seu banco de dados for roubado, o ladrão não terá as senhas em texto simples dos seus usuários, apenas os hashes. @@ -144,10 +144,9 @@ UserInDB( ) ``` +/// note | Nota -/// info | Informação - -Para uma explicação mais completa de `**user_dict`, verifique [a documentação para **Extra Models**](../extra-models.md#about-user-in-dict). +Para uma explicação mais completa de `**user_dict`, verifique [a documentação para **Extra Models**](../extra-models.md#about-user-in-model-dump). /// @@ -173,7 +172,7 @@ Mas, por enquanto, vamos nos concentrar nos detalhes específicos de que precisa /// tip | Dica -Pela especificação, você deve retornar um JSON com um `access_token` e um `token_type`, o mesmo que neste exemplo. +Pela especificação, você deveria retornar um JSON com um `access_token` e um `token_type`, o mesmo que neste exemplo. Isso é algo que você mesmo deve fazer em seu código e certifique-se de usar essas chaves JSON. @@ -197,7 +196,7 @@ Portanto, em nosso endpoint, só obteremos um usuário se o usuário existir, ti {* ../../docs_src/security/tutorial003_an_py310.py hl[58:66,69:74,94] *} -/// info | Informação +/// note | Nota O cabeçalho adicional `WWW-Authenticate` com valor `Bearer` que estamos retornando aqui também faz parte da especificação. @@ -217,7 +216,7 @@ Esse é o benefício dos padrões... ## Veja em ação { #see-it-in-action } -Abra o docs interativo: [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs). +Abra a documentação interativa: [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs). ### Autentique-se { #authenticate } diff --git a/docs/pt/docs/tutorial/server-sent-events.md b/docs/pt/docs/tutorial/server-sent-events.md index 33389873c..63d82c321 100644 --- a/docs/pt/docs/tutorial/server-sent-events.md +++ b/docs/pt/docs/tutorial/server-sent-events.md @@ -4,7 +4,7 @@ Você pode transmitir dados para o cliente usando Server-Sent Events (SSE). Isso é semelhante a [Stream de JSON Lines](stream-json-lines.md), mas usa o formato `text/event-stream`, que é suportado nativamente pelos navegadores com a [`EventSource` API](https://developer.mozilla.org/en-US/docs/Web/API/EventSource). -/// info | Informação +/// note | Nota Adicionado no FastAPI 0.135.0. diff --git a/docs/pt/docs/tutorial/sql-databases.md b/docs/pt/docs/tutorial/sql-databases.md index 10be4c865..e715007eb 100644 --- a/docs/pt/docs/tutorial/sql-databases.md +++ b/docs/pt/docs/tutorial/sql-databases.md @@ -4,7 +4,7 @@ Aqui veremos um exemplo usando [SQLModel](https://sqlmodel.tiangolo.com/). -**SQLModel** é construído sobre [SQLAlchemy](https://www.sqlalchemy.org/) e Pydantic. Ele foi criado pelo mesmo autor do **FastAPI** para ser o par perfeito para aplicações **FastAPI** que precisam usar **bancos de dados SQL**. +**SQLModel** é construído sobre [SQLAlchemy](https://www.sqlalchemy.org/) e Pydantic. Ele foi criado pelo mesmo autor do **FastAPI** para ser o par perfeito para aplicações FastAPI que precisam usar **bancos de dados SQL**. /// tip | Dica @@ -32,7 +32,7 @@ Existe um gerador de projetos oficial com **FastAPI** e **PostgreSQL** incluindo Este é um tutorial muito simples e curto, se você quiser aprender sobre bancos de dados em geral, sobre SQL ou recursos mais avançados, acesse a [documentação do SQLModel](https://sqlmodel.tiangolo.com/). -## Instalar o `SQLModel` { #install-sqlmodel } +## Instale o `SQLModel` { #install-sqlmodel } Primeiro, certifique-se de criar seu [ambiente virtual](../virtual-environments.md), ativá-lo e, em seguida, instalar o `sqlmodel`: @@ -45,13 +45,13 @@ $ pip install sqlmodel -## Crear o App com um Único Modelo { #create-the-app-with-a-single-model } +## Crie o App com um Único Modelo { #create-the-app-with-a-single-model } Vamos criar a primeira versão mais simples do app com um único modelo **SQLModel**. Depois, vamos melhorá-lo aumentando a segurança e versatilidade com **múltiplos modelos** abaixo. 🤓 -### Criar Modelos { #create-models } +### Crie Modelos { #create-models } Importe o `SQLModel` e crie um modelo de banco de dados: @@ -71,7 +71,8 @@ Existem algumas diferenças: O SQLModel saberá que algo declarado como `str` será uma coluna SQL do tipo `TEXT` (ou `VARCHAR`, dependendo do banco de dados). -### Criar um Engine { #create-an-engine } +### Crie um Engine { #create-an-engine } + Um `engine` SQLModel (por baixo dos panos, ele é na verdade um `engine` do SQLAlchemy) é o que **mantém as conexões** com o banco de dados. Você teria **um único objeto `engine`** para todo o seu código se conectar ao mesmo banco de dados. @@ -82,13 +83,13 @@ Usar `check_same_thread=False` permite que o FastAPI use o mesmo banco de dados Não se preocupe, com a forma como o código está estruturado, garantiremos que usamos **uma única *sessão* SQLModel por requisição** mais tarde, isso é realmente o que o `check_same_thread` está tentando conseguir. -### Criar as Tabelas { #create-the-tables } +### Crie as Tabelas { #create-the-tables } Em seguida, adicionamos uma função que usa `SQLModel.metadata.create_all(engine)` para **criar as tabelas** para todos os *modelos de tabela*. {* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[21:22] hl[21:22] *} -### Criar uma Dependência de Sessão { #create-a-session-dependency } +### Crie uma Dependência de Sessão { #create-a-session-dependency } Uma **`Session`** é o que armazena os **objetos na memória** e acompanha as alterações necessárias nos dados, para então **usar o `engine`** para se comunicar com o banco de dados. @@ -98,7 +99,7 @@ Então, criamos uma dependência `Annotated` chamada `SessionDep` para simplific {* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[25:30] hl[25:27,30] *} -### Criar Tabelas de Banco de Dados na Inicialização { #create-database-tables-on-startup } +### Crie Tabelas de Banco de Dados na Inicialização { #create-database-tables-on-startup } Vamos criar as tabelas do banco de dados quando o aplicativo for iniciado. @@ -114,7 +115,7 @@ O SQLModel terá utilitários de migração envolvendo o Alembic, mas por enquan /// -### Criar um Hero { #create-a-hero } +### Crie um Hero { #create-a-hero } Como cada modelo SQLModel também é um modelo Pydantic, você pode usá-lo nas mesmas **anotações de tipo** que usaria para modelos Pydantic. @@ -126,25 +127,25 @@ Da mesma forma, você pode declará-lo como o **tipo de retorno** da função, e Aqui, usamos a dependência `SessionDep` (uma `Session`) para adicionar o novo `Hero` à instância `Session`, fazer commit das alterações no banco de dados, atualizar os dados no `hero` e então retorná-lo. -### Ler Heroes { #read-heroes } +### Leia Heroes { #read-heroes } Podemos **ler** `Hero`s do banco de dados usando um `select()`. Podemos incluir um `limit` e `offset` para paginar os resultados. {* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[48:55] hl[51:52,54] *} -### Ler um Único Hero { #read-one-hero } +### Leia um Único Hero { #read-one-hero } Podemos **ler** um único `Hero`. {* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[58:63] hl[60] *} -### Deletar um Hero { #delete-a-hero } +### Delete um Hero { #delete-a-hero } Também podemos **deletar** um `Hero`. {* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[66:73] hl[71] *} -### Executar o App { #run-the-app } +### Execute o App { #run-the-app } Você pode executar o app: @@ -164,19 +165,19 @@ Então, vá para a interface `/docs`, você verá que o **FastAPI** está usando -## Atualizar o App com Múltiplos Modelos { #update-the-app-with-multiple-models } +## Atualize o App com Múltiplos Modelos { #update-the-app-with-multiple-models } Agora vamos **refatorar** este app um pouco para aumentar a **segurança** e **versatilidade**. -Se você verificar o app anterior, na interface você pode ser que, até agora, ele permite que o cliente decida o `id` do `Hero` a ser criado. 😱 +Se você verificar o app anterior, na interface você pode ver que, até agora, ele permite que o cliente decida o `id` do `Hero` a ser criado. 😱 -Não deveríamos deixar isso acontecer, eles poderiam sobrescrever um `id` que já atribuimos na base de dados. Decidir o `id` deve ser feito pelo **backend** ou pelo **banco de dados**, **não pelo cliente**. +Não deveríamos deixar isso acontecer, eles poderiam sobrescrever um `id` que já atribuímos no banco de dados. Decidir o `id` deve ser feito pelo **backend** ou pelo **banco de dados**, **não pelo cliente**. Além disso, criamos um `secret_name` para o hero, mas até agora estamos retornando ele em todos os lugares, isso não é muito **secreto**... 😅 Vamos corrigir essas coisas adicionando alguns **modelos extras**. Aqui é onde o SQLModel vai brilhar. ✨ -### Criar Múltiplos Modelos { #create-multiple-models } +### Crie Múltiplos Modelos { #create-multiple-models } No **SQLModel**, qualquer classe de modelo que tenha `table=True` é um **modelo de tabela**. @@ -277,7 +278,7 @@ Os campos de `HeroUpdate` são: {* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[7:28] hl[25:28] *} -### Criar com `HeroCreate` e retornar um `HeroPublic` { #create-with-herocreate-and-return-a-heropublic } +### Crie com `HeroCreate` e retorne um `HeroPublic` { #create-with-herocreate-and-return-a-heropublic } Agora que temos **múltiplos modelos**, podemos atualizar as partes do app que os utilizam. @@ -299,19 +300,19 @@ Ao declará-lo no `response_model`, estamos dizendo ao **FastAPI** para fazer o /// -### Ler Heroes com `HeroPublic` { #read-heroes-with-heropublic } +### Leia Heroes com `HeroPublic` { #read-heroes-with-heropublic } Podemos fazer o mesmo que antes para **ler** `Hero`s, novamente, usamos `response_model=list[HeroPublic]` para garantir que os dados sejam validados e serializados corretamente. {* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[65:72] hl[65] *} -### Ler Um Hero com `HeroPublic` { #read-one-hero-with-heropublic } +### Leia Um Hero com `HeroPublic` { #read-one-hero-with-heropublic } Podemos **ler** um único herói: {* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[75:80] hl[77] *} -### Atualizar um Hero com `HeroUpdate` { #update-a-hero-with-heroupdate } +### Atualize um Hero com `HeroUpdate` { #update-a-hero-with-heroupdate } Podemos **atualizar um hero**. Para isso, usamos uma operação HTTP `PATCH`. @@ -321,7 +322,7 @@ Em seguida, usamos `hero_db.sqlmodel_update(hero_data)` para atualizar o `hero_d {* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[83:93] hl[83:84,88:89] *} -### Deletar um Hero Novamente { #delete-a-hero-again } +### Delete um Hero Novamente { #delete-a-hero-again } **Deletar** um hero permanece praticamente o mesmo. @@ -329,7 +330,7 @@ Não vamos satisfazer o desejo de refatorar tudo neste aqui. 😅 {* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[96:103] hl[101] *} -### Executar o App Novamente { #run-the-app-again } +### Execute o App Novamente { #run-the-app-again } Você pode executar o app novamente: diff --git a/docs/pt/docs/tutorial/static-files.md b/docs/pt/docs/tutorial/static-files.md index e9150facd..4e8d4319a 100644 --- a/docs/pt/docs/tutorial/static-files.md +++ b/docs/pt/docs/tutorial/static-files.md @@ -2,6 +2,14 @@ Você pode servir arquivos estáticos automaticamente a partir de um diretório usando `StaticFiles`. +/// tip | Dica + +Se você precisar hospedar um frontend, use `app.frontend()` em vez disso, leia sobre isso em [Frontend](frontend.md). + +`app.frontend()` usa `StaticFiles` por baixo, com várias vantagens adicionais para frontends, como lidar com roteamento do lado do cliente. + +/// + ## Use `StaticFiles` { #use-staticfiles } * Importe `StaticFiles`. diff --git a/docs/pt/docs/tutorial/stream-json-lines.md b/docs/pt/docs/tutorial/stream-json-lines.md index f6d5c26f0..a76bacd11 100644 --- a/docs/pt/docs/tutorial/stream-json-lines.md +++ b/docs/pt/docs/tutorial/stream-json-lines.md @@ -2,7 +2,7 @@ Você pode ter uma sequência de dados que deseja enviar em um "**Stream**"; é possível fazer isso com **JSON Lines**. -/// info | Informação +/// note | Nota Adicionado no FastAPI 0.134.0. @@ -48,7 +48,7 @@ Uma response teria um tipo de conteúdo `application/jsonl` (em vez de `applicat É muito semelhante a um array JSON (equivalente a uma list do Python), mas em vez de estar envolto em `[]` e ter `,` entre os itens, há **um objeto JSON por linha**, separados por um caractere de nova linha. -/// info | Informação +/// note | Nota O ponto importante é que sua aplicação poderá produzir cada linha em sequência, enquanto o cliente consome as anteriores. diff --git a/docs/pt/docs/tutorial/testing.md b/docs/pt/docs/tutorial/testing.md index 1730511e6..9d94cddcd 100644 --- a/docs/pt/docs/tutorial/testing.md +++ b/docs/pt/docs/tutorial/testing.md @@ -8,7 +8,7 @@ Com ele, você pode usar o [pytest](https://docs.pytest.org/) diretamente com ** ## Usando `TestClient` { #using-testclient } -/// info | Informação +/// note | Nota Para usar o `TestClient`, primeiro instale [`httpx`](https://www.python-httpx.org). @@ -52,7 +52,7 @@ Você também pode usar `from starlette.testclient import TestClient`. /// tip | Dica -Se você quiser chamar funções `async` em seus testes além de enviar solicitações à sua aplicação FastAPI (por exemplo, funções de banco de dados assíncronas), dê uma olhada em [Testes assíncronos](../advanced/async-tests.md) no tutorial avançado. +Se você quiser chamar funções `async` em seus testes além de enviar requests à sua aplicação FastAPI (por exemplo, funções de banco de dados assíncronas), dê uma olhada em [Testes assíncronos](../advanced/async-tests.md) no tutorial avançado. /// @@ -94,6 +94,7 @@ Como esse arquivo está no mesmo pacote, você pode usar importações relativas {* ../../docs_src/app_testing/app_a_py310/test_main.py hl[3] *} + ...e ter o código para os testes como antes. ## Testando: exemplo estendido { #testing-extended-example } @@ -112,13 +113,13 @@ Vamos continuar com a mesma estrutura de arquivo de antes: │   └── test_main.py ``` -Digamos que agora o arquivo `main.py` com sua aplicação **FastAPI** tenha algumas outras **operações de rotas**. +Digamos que agora o arquivo `main.py` com sua aplicação **FastAPI** tenha algumas outras **operações de rota**. Ele tem uma operação `GET` que pode retornar um erro. Ele tem uma operação `POST` que pode retornar vários erros. -Ambas as *operações de rotas* requerem um cabeçalho `X-Token`. +Ambas as *operações de rota* requerem um cabeçalho `X-Token`. {* ../../docs_src/app_testing/app_b_an_py310/main.py *} @@ -128,6 +129,7 @@ Você pode então atualizar `test_main.py` com os testes estendidos: {* ../../docs_src/app_testing/app_b_an_py310/test_main.py *} + Sempre que você precisar que o cliente passe informações na requisição e não souber como, você pode pesquisar (no Google) como fazer isso no `httpx`, ou até mesmo como fazer isso com `requests`, já que o design do HTTPX é baseado no design do Requests. Depois é só fazer o mesmo nos seus testes. @@ -142,11 +144,11 @@ Por exemplo: Para mais informações sobre como passar dados para o backend (usando `httpx` ou `TestClient`), consulte a [documentação do HTTPX](https://www.python-httpx.org). -/// info | Informação +/// note | Nota Observe que o `TestClient` recebe dados que podem ser convertidos para JSON, não para modelos Pydantic. -Se você tiver um modelo Pydantic em seu teste e quiser enviar seus dados para o aplicativo durante o teste, poderá usar o `jsonable_encoder` descrito em [Codificador compatível com JSON](encoder.md). +Se você tiver um modelo Pydantic em seu teste e quiser enviar seus dados para a aplicação durante o teste, poderá usar o `jsonable_encoder` descrito em [Codificador compatível com JSON](encoder.md). /// diff --git a/docs/pt/docs/virtual-environments.md b/docs/pt/docs/virtual-environments.md index 245919608..121032d6c 100644 --- a/docs/pt/docs/virtual-environments.md +++ b/docs/pt/docs/virtual-environments.md @@ -26,7 +26,7 @@ Se você estiver pronto para adotar uma **ferramenta que gerencia tudo** para vo /// -## Criar um Projeto { #create-a-project } +## Crie um Projeto { #create-a-project } Primeiro, crie um diretório para seu projeto. @@ -212,7 +212,7 @@ Se ele mostrar o binário `python` em `.venv\Scripts\python`, dentro do seu proj //// -## Atualizar `pip` { #upgrade-pip } +## Atualize `pip` { #upgrade-pip } /// tip | Dica @@ -262,7 +262,7 @@ Esse comando instalará o pip caso ele ainda não esteja instalado e também gar /// -## Adicionar `.gitignore` { #add-gitignore } +## Adicione `.gitignore` { #add-gitignore } Se você estiver usando **Git** (você deveria), adicione um arquivo `.gitignore` para excluir tudo em seu `.venv` do Git. @@ -302,7 +302,7 @@ Esse comando criará um arquivo `.gitignore` com o conteúdo: /// -## Instalar Pacotes { #install-packages } +## Instale Pacotes { #install-packages } Após ativar o ambiente, você pode instalar pacotes nele. @@ -314,7 +314,7 @@ Se precisar atualizar uma versão ou adicionar um novo pacote, você **fará iss /// -### Instalar pacotes diretamente { #install-packages-directly } +### Instale pacotes diretamente { #install-packages-directly } Se estiver com pressa e não quiser usar um arquivo para declarar os requisitos de pacote do seu projeto, você pode instalá-los diretamente. @@ -353,7 +353,7 @@ $ uv pip install "fastapi[standard]" //// -### Instalar a partir de `requirements.txt` { #install-from-requirements-txt } +### Instale a partir de `requirements.txt` { #install-from-requirements-txt } Se você tiver um `requirements.txt`, agora poderá usá-lo para instalar seus pacotes. @@ -425,7 +425,7 @@ Normalmente, você só precisa fazer isso **uma vez**, ao criar o ambiente virtu /// -## Desativar o ambiente virtual { #deactivate-the-virtual-environment } +## Desative o ambiente virtual { #deactivate-the-virtual-environment } Quando terminar de trabalhar no seu projeto, você pode **desativar** o ambiente virtual. @@ -768,7 +768,7 @@ C:\Users\user\code\awesome-project\.venv\Scripts\python Isso significa que o programa `python` que será usado é aquele **no ambiente virtual**. -você usa `which` no Linux e macOS e `Get-Command` no Windows PowerShell. +Você usa `which` no Linux e macOS e `Get-Command` no Windows PowerShell. A maneira como esse comando funciona é que ele vai e verifica na variável de ambiente `PATH`, passando por **cada caminho em ordem**, procurando pelo programa chamado `python`. Uma vez que ele o encontre, ele **mostrará o caminho** para esse programa. @@ -811,7 +811,7 @@ $ cd ~/code/prisoner-of-azkaban $ python main.py -// Erro ao importar o Sirius, ele não está instalado 😱 +// Erro ao importar sirius, ele não está instalado 😱 Traceback (most recent call last): File "main.py", line 1, in import sirius @@ -861,4 +861,4 @@ Quando estiver pronto e quiser usar uma ferramenta para **gerenciar todo o proje Se você leu e entendeu tudo isso, agora **você sabe muito mais** sobre ambientes virtuais do que muitos desenvolvedores por aí. 🤓 -Saber esses detalhes provavelmente será útil no futuro, quando você estiver depurando algo que parece complexo, mas você saberá **como tudo funciona**. 😎 +Saber esses detalhes provavelmente será útil no futuro, quando você estiver depurando algo que parece complexo, mas você saberá **como tudo funciona por baixo**. 😎 diff --git a/docs/ru/docs/_llm-test.md b/docs/ru/docs/_llm-test.md index d33e803a0..1b2ee8f18 100644 --- a/docs/ru/docs/_llm-test.md +++ b/docs/ru/docs/_llm-test.md @@ -258,7 +258,7 @@ works(foo="bar") # Это работает 🎉 * `bar` как `str` * `baz` как `list` -* Учебник — Руководство пользователя +* Учебник - Руководство пользователя * Расширенное руководство пользователя * Документация по SQLModel * Документация API @@ -461,7 +461,7 @@ works(foo="bar") # Это работает 🎉 * библиотека * lifespan * блокировка -* middleware (Промежуточный слой) +* middleware (промежуточный слой) * мобильное приложение * модуль * монтирование diff --git a/docs/ru/docs/advanced/additional-responses.md b/docs/ru/docs/advanced/additional-responses.md index f7e8d9dec..ef9d3f223 100644 --- a/docs/ru/docs/advanced/additional-responses.md +++ b/docs/ru/docs/advanced/additional-responses.md @@ -34,7 +34,7 @@ /// -/// info | Информация +/// note | Примечание Ключ `model` не является частью OpenAPI. @@ -183,7 +183,7 @@ /// -/// info | Информация +/// note | Примечание Если вы явно не укажете другой тип содержимого в параметре `responses`, FastAPI будет считать, что ответ имеет тот же тип содержимого, что и основной класс ответа (по умолчанию `application/json`). diff --git a/docs/ru/docs/advanced/additional-status-codes.md b/docs/ru/docs/advanced/additional-status-codes.md index aec66a13f..a0d21e445 100644 --- a/docs/ru/docs/advanced/additional-status-codes.md +++ b/docs/ru/docs/advanced/additional-status-codes.md @@ -1,5 +1,6 @@ # Дополнительные статус-коды { #additional-status-codes } + По умолчанию **FastAPI** будет возвращать ответы, используя `JSONResponse`, помещая содержимое, которое вы возвращаете из вашей *операции пути*, внутрь этого `JSONResponse`. Он будет использовать статус-код по умолчанию или тот, который вы укажете в вашей *операции пути*. diff --git a/docs/ru/docs/advanced/advanced-dependencies.md b/docs/ru/docs/advanced/advanced-dependencies.md index fe37a79c1..0092313b2 100644 --- a/docs/ru/docs/advanced/advanced-dependencies.md +++ b/docs/ru/docs/advanced/advanced-dependencies.md @@ -36,7 +36,7 @@ {* ../../docs_src/dependencies/tutorial011_an_py310.py hl[18] *} -Так мы «параметризуем» нашу зависимость: теперь внутри неё хранится "bar" в атрибуте `checker.fixed_content`. +Так мы «параметризуем» нашу зависимость: теперь внутри неё хранится `"bar"` в атрибуте `checker.fixed_content`. ## Используем экземпляр как зависимость { #use-the-instance-as-a-dependency } @@ -48,7 +48,7 @@ checker(q="somequery") ``` -…и передаст возвращённое значение как значение зависимости в параметр `fixed_content_included` нашей *функции-обработчику пути*: +…и передаст возвращённое значение как значение зависимости в нашу *функцию-обработчик пути* в параметр `fixed_content_included`: {* ../../docs_src/dependencies/tutorial011_an_py310.py hl[22] *} @@ -98,7 +98,7 @@ checker(q="somequery") В версии 0.118.0 это поведение было возвращено к тому, что код после `yield` выполняется после отправки ответа. -/// info | Информация +/// note | Примечание Как вы увидите ниже, это очень похоже на поведение до версии 0.106.0, но с несколькими улучшениями и исправлениями краевых случаев. diff --git a/docs/ru/docs/advanced/custom-response.md b/docs/ru/docs/advanced/custom-response.md index fdfe2c549..695506223 100644 --- a/docs/ru/docs/advanced/custom-response.md +++ b/docs/ru/docs/advanced/custom-response.md @@ -41,7 +41,7 @@ {* ../../docs_src/custom_response/tutorial002_py310.py hl[2,7] *} -/// info | Информация +/// note | Примечание Параметр `response_class` также используется для указания «типа содержимого» ответа. @@ -65,7 +65,7 @@ /// -/// info | Информация +/// note | Примечание Разумеется, фактический заголовок `Content-Type`, статус-код и т.д. возьмутся из объекта `Response`, который вы вернули. diff --git a/docs/ru/docs/advanced/dataclasses.md b/docs/ru/docs/advanced/dataclasses.md index f9f8689b0..5388e9832 100644 --- a/docs/ru/docs/advanced/dataclasses.md +++ b/docs/ru/docs/advanced/dataclasses.md @@ -12,13 +12,13 @@ FastAPI построен поверх **Pydantic**, и я показывал в И, конечно, поддерживаются те же возможности: -- валидация данных -- сериализация данных -- документирование данных и т.д. +* валидация данных +* сериализация данных +* документирование данных и т.д. Это работает так же, как с Pydantic-моделями. И на самом деле под капотом это достигается тем же образом, с использованием Pydantic. -/// info | Информация +/// note | Примечание Помните, что dataclasses не умеют всего того, что умеют Pydantic-модели. diff --git a/docs/ru/docs/advanced/events.md b/docs/ru/docs/advanced/events.md index 464bba93e..00319575f 100644 --- a/docs/ru/docs/advanced/events.md +++ b/docs/ru/docs/advanced/events.md @@ -1,30 +1,30 @@ # События lifespan { #lifespan-events } -Вы можете определить логику (код), которую нужно выполнить перед тем, как приложение начнет запускаться. Это означает, что этот код будет выполнен один раз, перед тем как приложение начнет получать HTTP-запросы. +Вы можете определить логику (код), которую нужно выполнить перед тем, как приложение **запустится**. Это означает, что этот код будет выполнен **один раз**, **перед** тем как приложение **начнет получать HTTP-запросы**. -Аналогично, вы можете определить логику (код), которую нужно выполнить, когда приложение завершает работу. В этом случае код будет выполнен один раз, после обработки, возможно, многих запросов. +Аналогично, вы можете определить логику (код), которую нужно выполнить, когда приложение **завершает работу**. В этом случае код будет выполнен **один раз**, **после обработки**, возможно, **многих HTTP-запросов**. -Поскольку этот код выполняется до того, как приложение начинает принимать запросы, и сразу после того, как оно заканчивает их обрабатывать, он охватывает весь lifespan (жизненный цикл) приложения (слово «lifespan» станет важным через секунду 😉). +Поскольку этот код выполняется до того, как приложение **начинает** принимать HTTP-запросы, и сразу после того, как оно **заканчивает** их обрабатывать, он охватывает весь **lifespan** (жизненный цикл) приложения (слово «lifespan» станет важным через секунду 😉). -Это может быть очень полезно для настройки ресурсов, которые нужны для всего приложения, которые разделяются между запросами и/или которые нужно затем очистить. Например, пул подключений к базе данных или загрузка общей модели Машинного обучения. +Это может быть очень полезно для настройки **ресурсов**, которые нужны для всего приложения, которые **разделяются** между HTTP-запросами и/или которые нужно затем **очистить**. Например, пул подключений к базе данных или загрузка общей модели Машинного обучения. ## Вариант использования { #use-case } -Начнем с примера варианта использования, а затем посмотрим, как это решить. +Начнем с примера **варианта использования**, а затем посмотрим, как это решить. -Представим, что у вас есть несколько моделей Машинного обучения, которые вы хотите использовать для обработки запросов. 🤖 +Представим, что у вас есть несколько **моделей Машинного обучения**, которые вы хотите использовать для обработки HTTP-запросов. 🤖 -Эти же модели разделяются между запросами, то есть это не одна модель на запрос, не одна на пользователя и т.п. +Эти же модели разделяются между HTTP-запросами, то есть это не одна модель на HTTP-запрос, не одна на пользователя и т.п. -Представим, что загрузка модели может занимать довольно много времени, потому что ей нужно прочитать много данных с диска. Поэтому вы не хотите делать это для каждого запроса. +Представим, что загрузка модели может **занимать довольно много времени**, потому что ей нужно прочитать много **данных с диска**. Поэтому вы не хотите делать это для каждого HTTP-запроса. -Вы могли бы загрузить её на верхнем уровне модуля/файла, но это означало бы, что модель загружается даже если вы просто запускаете простой автоматический тест; тогда этот тест будет медленным, так как ему придется ждать загрузки модели перед запуском независимой части кода. +Вы могли бы загрузить её на верхнем уровне модуля/файла, но это означало бы, что модель будет **загружаться** даже если вы просто запускаете простой автоматический тест; тогда этот тест будет **медленным**, так как ему придется ждать загрузки модели перед запуском независимой части кода. -Именно это мы и решим: давайте загружать модель перед тем, как начнётся обработка запросов, но только непосредственно перед тем, как приложение начнет принимать запросы, а не во время загрузки кода. +Именно это мы и решим: давайте загружать модель перед тем, как начнётся обработка HTTP-запросов, но только непосредственно перед тем, как приложение начнет принимать HTTP-запросы, а не во время загрузки кода. ## Lifespan { #lifespan } -Вы можете определить логику для startup и shutdown, используя параметр `lifespan` приложения `FastAPI` и «менеджер контекста» (через секунду покажу что это). +Вы можете определить логику для *startup* и *shutdown*, используя параметр `lifespan` приложения `FastAPI` и «менеджер контекста» (через секунду покажу что это). Начнем с примера, а затем разберём его подробнее. @@ -32,13 +32,13 @@ {* ../../docs_src/events/tutorial003_py310.py hl[16,19] *} -Здесь мы симулируем дорогую операцию startup по загрузке модели, помещая (фиктивную) функцию модели в словарь с моделями Машинного обучения до `yield`. Этот код будет выполнен до того, как приложение начнет принимать запросы, во время startup. +Здесь мы симулируем дорогую операцию *startup* по загрузке модели, помещая (фиктивную) функцию модели в словарь с моделями Машинного обучения до `yield`. Этот код будет выполнен **до** того, как приложение **начнет принимать HTTP-запросы**, во время *startup*. -А затем сразу после `yield` мы выгружаем модель. Этот код будет выполнен после того, как приложение закончит обрабатывать запросы, непосредственно перед shutdown. Это может, например, освободить ресурсы, такие как память или GPU. +А затем сразу после `yield` мы выгружаем модель. Этот код будет выполнен **после** того, как приложение **закончит обрабатывать HTTP-запросы**, непосредственно перед *shutdown*. Это может, например, освободить ресурсы, такие как память или GPU. /// tip | Совет -`shutdown` произойдёт, когда вы останавливаете приложение. +`shutdown` произойдёт, когда вы **останавливаете** приложение. Возможно, вам нужно запустить новую версию, или вы просто устали от него. 🤷 @@ -50,26 +50,26 @@ {* ../../docs_src/events/tutorial003_py310.py hl[14:19] *} -Первая часть функции, до `yield`, будет выполнена до запуска приложения. +Первая часть функции, до `yield`, будет выполнена **до** запуска приложения. -А часть после `yield` будет выполнена после завершения работы приложения. +А часть после `yield` будет выполнена **после** завершения работы приложения. ### Асинхронный менеджер контекста { #async-context-manager } Если присмотреться, функция декорирована `@asynccontextmanager`. -Это превращает функцию в «асинхронный менеджер контекста». +Это превращает функцию в «**асинхронный менеджер контекста**». {* ../../docs_src/events/tutorial003_py310.py hl[1,13] *} -Менеджер контекста в Python — это то, что можно использовать в операторе `with`. Например, `open()` можно использовать как менеджер контекста: +**Менеджер контекста** в Python — это то, что можно использовать в операторе `with`. Например, `open()` можно использовать как менеджер контекста: ```Python with open("file.txt") as file: file.read() ``` -В последних версиях Python есть также асинхронный менеджер контекста. Его используют с `async with`: +В последних версиях Python есть также **асинхронный менеджер контекста**. Его используют с `async with`: ```Python async with lifespan(app): @@ -80,7 +80,7 @@ async with lifespan(app): В нашем примере выше мы не используем его напрямую, а передаём его в FastAPI, чтобы он использовал его сам. -Параметр `lifespan` приложения `FastAPI` принимает асинхронный менеджер контекста, поэтому мы можем передать ему наш новый асинхронный менеджер контекста `lifespan`. +Параметр `lifespan` приложения `FastAPI` принимает **асинхронный менеджер контекста**, поэтому мы можем передать ему наш новый асинхронный менеджер контекста `lifespan`. {* ../../docs_src/events/tutorial003_py310.py hl[22] *} @@ -88,13 +88,13 @@ async with lifespan(app): /// warning | Предупреждение -Рекомендуемый способ обрабатывать startup и shutdown — использовать параметр `lifespan` приложения `FastAPI`, как описано выше. Если вы укажете параметр `lifespan`, обработчики событий `startup` и `shutdown` больше вызываться не будут. Либо всё через `lifespan`, либо всё через события — не одновременно. +Рекомендуемый способ обрабатывать *startup* и *shutdown* — использовать параметр `lifespan` приложения `FastAPI`, как описано выше. Если вы укажете параметр `lifespan`, обработчики событий `startup` и `shutdown` больше вызываться не будут. Либо всё через `lifespan`, либо всё через события — не одновременно. Эту часть, скорее всего, можно пропустить. /// -Есть альтернативный способ определить логику, которую нужно выполнить во время startup и во время shutdown. +Есть альтернативный способ определить логику, которую нужно выполнить во время *startup* и во время *shutdown*. Вы можете определить обработчики событий (функции), которые нужно выполнить до старта приложения или при его завершении. @@ -110,7 +110,7 @@ async with lifespan(app): Вы можете добавить более одного обработчика события. -И ваше приложение не начнет принимать запросы, пока все обработчики события `startup` не завершатся. +И ваше приложение не начнет принимать HTTP-запросы, пока все обработчики события `startup` не завершатся. ### Событие `shutdown` { #shutdown-event } @@ -120,7 +120,7 @@ async with lifespan(app): Здесь функция-обработчик события `shutdown` запишет строку текста `"Application shutdown"` в файл `log.txt`. -/// info | Информация +/// note | Примечание В функции `open()` параметр `mode="a"` означает «добавление» (append), то есть строка будет добавлена в конец файла, без перезаписи предыдущего содержимого. @@ -140,7 +140,7 @@ async with lifespan(app): ### `startup` и `shutdown` вместе { #startup-and-shutdown-together } -С высокой вероятностью логика для вашего startup и shutdown связана: вы можете хотеть что-то запустить, а затем завершить, получить ресурс, а затем освободить его и т.д. +С высокой вероятностью логика для вашего *startup* и *shutdown* связана: вы можете хотеть что-то запустить, а затем завершить, получить ресурс, а затем освободить его и т.д. Делать это в отдельных функциях, которые не разделяют общую логику или переменные, сложнее, так как придётся хранить значения в глобальных переменных или использовать похожие приёмы. @@ -148,11 +148,11 @@ async with lifespan(app): ## Технические детали { #technical-details } -Немного технических подробностей для любопытных умников. 🤓 +Просто техническая подробность для любопытных умников. 🤓 -Под капотом, в ASGI-технической спецификации, это часть [Протокола Lifespan](https://asgi.readthedocs.io/en/latest/specs/lifespan.html), и он определяет события `startup` и `shutdown`. +Под капотом, в технической спецификации ASGI, это часть [Протокола Lifespan](https://asgi.readthedocs.io/en/latest/specs/lifespan.html), и он определяет события `startup` и `shutdown`. -/// info | Информация +/// note | Примечание Вы можете прочитать больше про обработчики `lifespan` в Starlette в [документации Starlette по Lifespan](https://www.starlette.dev/lifespan/). @@ -162,4 +162,4 @@ async with lifespan(app): ## Подприложения { #sub-applications } -🚨 Имейте в виду, что эти события lifespan (startup и shutdown) будут выполнены только для основного приложения, а не для [Подприложения — Mounts](sub-applications.md). +🚨 Имейте в виду, что эти события lifespan (startup и shutdown) будут выполнены только для основного приложения, а не для [Подприложений - Mounts](sub-applications.md). diff --git a/docs/ru/docs/advanced/generate-clients.md b/docs/ru/docs/advanced/generate-clients.md index dfedc5dc0..04e8e88bc 100644 --- a/docs/ru/docs/advanced/generate-clients.md +++ b/docs/ru/docs/advanced/generate-clients.md @@ -20,21 +20,6 @@ FastAPI автоматически генерирует спецификации /// -## Генераторы SDK от спонсоров FastAPI { #sdk-generators-from-fastapi-sponsors } - -В этом разделе представлены решения с **венчурной поддержкой** и **поддержкой компаний** от компаний, которые спонсируют FastAPI. Эти продукты предоставляют **дополнительные возможности** и **интеграции** сверх высококачественно генерируемых SDK. - -Благодаря ✨ [**спонсорству FastAPI**](../help-fastapi.md#sponsor-the-author) ✨ эти компании помогают обеспечивать, чтобы фреймворк и его **экосистема** оставались здоровыми и **устойчивыми**. - -Их спонсорство также демонстрирует серьёзную приверженность **сообществу** FastAPI (вам), показывая, что им важно не только предоставлять **отличный сервис**, но и поддерживать **надёжный и процветающий фреймворк** FastAPI. 🙇 - -Например, вы можете попробовать: - -* [Stainless](https://www.stainless.com/?utm_source=fastapi&utm_medium=referral) -* [liblab](https://developers.liblab.com/tutorials/sdk-for-fastapi?utm_source=fastapi) - -Некоторые из этих решений также могут быть open source или иметь бесплатные тарифы, так что вы сможете попробовать их без финансовых затрат. Другие коммерческие генераторы SDK доступны и их можно найти онлайн. 🤓 - ## Создать TypeScript SDK { #create-a-typescript-sdk } Начнём с простого приложения FastAPI: @@ -83,7 +68,7 @@ npx @hey-api/openapi-ts -i http://localhost:8000/openapi.json -o src/client /// -Вы получите ошибки прямо в редакторе для отправляемых данных: +Вы получите ошибки прямо в редакторе кода для отправляемых данных: @@ -186,7 +171,7 @@ FastAPI использует **уникальный ID** для каждой *о npx @hey-api/openapi-ts -i ./openapi.json -o src/client ``` -После генерации нового клиента у вас будут **чистые имена методов**, со всем **автозавершением**, **ошибками прямо в редакторе** и т.д.: +После генерации нового клиента у вас будут **чистые имена методов**, со всем **автозавершением**, **ошибками прямо в редакторе кода** и т.д.: @@ -198,7 +183,7 @@ npx @hey-api/openapi-ts -i ./openapi.json -o src/client * Данных запроса — в теле запроса, query‑параметрах и т.д. * Данных ответа. -У вас также будут **ошибки прямо в редакторе** для всего. +У вас также будут **ошибки прямо в редакторе кода** для всего. И каждый раз, когда вы обновляете код бэкенда и **перегенерируете** фронтенд, в нём появятся новые *операции пути* как методы, старые будут удалены, а любые другие изменения отразятся в сгенерированном коде. 🤓 diff --git a/docs/ru/docs/advanced/json-base64-bytes.md b/docs/ru/docs/advanced/json-base64-bytes.md index 390dd17fa..262766889 100644 --- a/docs/ru/docs/advanced/json-base64-bytes.md +++ b/docs/ru/docs/advanced/json-base64-bytes.md @@ -4,7 +4,7 @@ ## Base64 и файлы { #base64-vs-files } -Сначала рассмотрите возможность использовать [Файлы в запросе](../tutorial/request-files.md) для загрузки бинарных данных и [Пользовательский HTTP-ответ — FileResponse](./custom-response.md#fileresponse--fileresponse-) для отправки бинарных данных вместо кодирования их в JSON. +Сначала рассмотрите возможность использовать [Файлы в запросе](../tutorial/request-files.md) для загрузки бинарных данных и [Пользовательский HTTP-ответ — FileResponse](./custom-response.md#fileresponse) для отправки бинарных данных вместо кодирования их в JSON. JSON может содержать только строки в кодировке UTF-8, поэтому он не может содержать «сырые» байты. @@ -14,7 +14,7 @@ Base64 может кодировать бинарные данные в стро ## Pydantic `bytes` { #pydantic-bytes } -Вы можете объявить Pydantic-модель с полями `bytes`, а затем использовать `val_json_bytes` в конфиге модели, чтобы указать использовать base64 для валидации входящих JSON-данных; как часть этой валидации строка base64 будет декодирована в байты. +Вы можете объявить Pydantic-модель с полями `bytes`, а затем использовать `val_json_bytes` в конфиге модели, чтобы указать использовать base64 для *валидации* входящих JSON-данных; как часть этой валидации строка base64 будет декодирована в байты. {* ../../docs_src/json_base64_bytes/tutorial001_py310.py ln[1:9,29:35] hl[9] *} @@ -52,12 +52,12 @@ Base64 может кодировать бинарные данные в стро ## Pydantic `bytes` для выходных данных { #pydantic-bytes-for-output-data } -Вы также можете использовать поля `bytes` с `ser_json_bytes` в конфиге модели для выходных данных, и Pydantic будет сериализовать байты в base64 при формировании JSON-ответа. +Вы также можете использовать поля `bytes` с `ser_json_bytes` в конфиге модели для выходных данных, и Pydantic будет *сериализовать* байты в base64 при формировании JSON-ответа. {* ../../docs_src/json_base64_bytes/tutorial001_py310.py ln[1:2,12:16,29,38:41] hl[16] *} ## Pydantic `bytes` для входных и выходных данных { #pydantic-bytes-for-input-and-output-data } -И, конечно, вы можете использовать одну и ту же модель, настроенную на использование base64, чтобы обрабатывать и входящие данные (валидация) с `val_json_bytes`, и исходящие данные (сериализация) с `ser_json_bytes` при приеме и отправке JSON-данных. +И, конечно, вы можете использовать одну и ту же модель, настроенную на использование base64, чтобы обрабатывать и входящие данные (*валидировать*) с `val_json_bytes`, и исходящие данные (*сериализовать*) с `ser_json_bytes` при приеме и отправке JSON-данных. {* ../../docs_src/json_base64_bytes/tutorial001_py310.py ln[1:2,19:26,29,44:46] hl[23:26] *} diff --git a/docs/ru/docs/advanced/openapi-callbacks.md b/docs/ru/docs/advanced/openapi-callbacks.md index 3d791de2c..002b69c7c 100644 --- a/docs/ru/docs/advanced/openapi-callbacks.md +++ b/docs/ru/docs/advanced/openapi-callbacks.md @@ -1,10 +1,10 @@ # Обратные вызовы в OpenAPI { #openapi-callbacks } -Вы можете создать API с *операцией пути* (обработчиком пути), которая будет инициировать HTTP-запрос к *внешнему API*, созданному кем-то другим (скорее всего тем же разработчиком, который будет использовать ваш API). +Вы можете создать API с *операцией пути* (обработчиком пути), которая будет инициировать HTTP-запрос к *внешнему API*, созданному кем-то другим (скорее всего тем же разработчиком, который будет *использовать* ваш API). -Процесс, происходящий, когда ваше приложение API обращается к *внешнему API*, называется «callback» (обратный вызов). Программное обеспечение, написанное внешним разработчиком, отправляет HTTP-запрос вашему API, а затем ваш API выполняет обратный вызов, отправляя HTTP-запрос во *внешний API* (который, вероятно, тоже создал тот же разработчик). +Процесс, происходящий, когда ваше приложение API обращается к *внешнему API*, называется «callback» (обратный вызов). Потому что программное обеспечение, написанное внешним разработчиком, отправляет HTTP-запрос вашему API, а затем ваш API выполняет обратный вызов, отправляя HTTP-запрос во *внешний API* (который, вероятно, тоже создал тот же разработчик). -В этом случае вам может понадобиться задокументировать, как должно выглядеть это внешнее API: какую *операцию пути* оно должно иметь, какое тело запроса ожидать, какой ответ возвращать и т.д. +В этом случае вам может понадобиться задокументировать, как это внешнее API *должно* выглядеть: какую *операцию пути* оно должно иметь, какое тело запроса ожидать, какой HTTP-ответ возвращать и т.д. ## Приложение с обратными вызовами { #an-app-with-callbacks } @@ -82,7 +82,7 @@ httpx.post(callback_url, json={"description": "Invoice paid", "paid": True}) Когда вы пишете код для документирования обратного вызова, полезно представить, что вы — тот самый *внешний разработчик*. И что вы сейчас реализуете *внешний API*, а не *свой API*. -Временное принятие этой точки зрения (внешнего разработчика) поможет интуитивно понять, куда поместить параметры, какую Pydantic-модель использовать для тела запроса, для ответа и т.д. во *внешнем API*. +Временное принятие этой точки зрения (внешнего разработчика) поможет интуитивно понять, куда поместить параметры, какую Pydantic-модель использовать для тела запроса, для HTTP-ответа и т.д. во *внешнем API*. /// @@ -99,7 +99,7 @@ httpx.post(callback_url, json={"description": "Invoice paid", "paid": True}) Она должна выглядеть как обычная *операция пути* FastAPI: * Вероятно, в ней должно быть объявление тела запроса, например `body: InvoiceEvent`. -* А также может быть объявление модели ответа, например `response_model=InvoiceEventReceived`. +* А также может быть объявление HTTP-ответа, который она должна возвращать, например `response_model=InvoiceEventReceived`. {* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[14:16,19:20,26:30] *} @@ -124,7 +124,7 @@ httpx.post(callback_url, json={"description": "Invoice paid", "paid": True}) https://yourapi.com/invoices/?callback_url=https://www.external.org/events ``` -с телом JSON: +с телом запроса JSON: ```JSON { @@ -140,7 +140,7 @@ https://yourapi.com/invoices/?callback_url=https://www.external.org/events https://www.external.org/events/invoices/2expen51ve ``` -с телом JSON примерно такого вида: +с телом запроса JSON примерно такого вида: ```JSON { @@ -149,7 +149,7 @@ https://www.external.org/events/invoices/2expen51ve } ``` -и будет ожидать от *внешнего API* ответ с телом JSON вида: +и будет ожидать от *внешнего API* HTTP-ответ с JSON в теле ответа: ```JSON { @@ -163,17 +163,17 @@ https://www.external.org/events/invoices/2expen51ve /// -### Подключите маршрутизатор обратного вызова { #add-the-callback-router } +### Добавьте роутер обратного вызова { #add-the-callback-router } -К этому моменту у вас есть необходимые *операции пути* обратного вызова (те, которые *внешний разработчик* должен реализовать во *внешнем API*) в созданном выше маршрутизаторе обратных вызовов. +К этому моменту у вас есть необходимые *операции пути* обратного вызова (те, которые *внешний разработчик* должен реализовать во *внешнем API*) в созданном выше роутере обратных вызовов. -Теперь используйте параметр `callbacks` в *декораторе операции пути вашего API*, чтобы передать атрибут `.routes` (это, по сути, просто `list` маршрутов/*операций пути*) из этого маршрутизатора обратных вызовов: +Теперь используйте параметр `callbacks` в *декораторе операции пути вашего API*, чтобы передать атрибут `.routes` из этого роутера обратных вызовов: {* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[33] *} /// tip | Совет -Обратите внимание, что вы передаёте не сам маршрутизатор (`invoices_callback_router`) в `callback=`, а его атрибут `.routes`, то есть `invoices_callback_router.routes`. +Обратите внимание, что вы передаёте не сам роутер (`invoices_callback_router`) в `callbacks=`, а его атрибут `.routes`, то есть `invoices_callback_router.routes`. FastAPI будет использовать эти маршруты для генерации документации OpenAPI для обратных вызовов. /// diff --git a/docs/ru/docs/advanced/openapi-webhooks.md b/docs/ru/docs/advanced/openapi-webhooks.md index 9b1988ff3..cd4d23e7e 100644 --- a/docs/ru/docs/advanced/openapi-webhooks.md +++ b/docs/ru/docs/advanced/openapi-webhooks.md @@ -22,7 +22,7 @@ Это значительно упростит вашим пользователям реализацию их API для приема ваших вебхук-запросов; возможно, они даже смогут автоматически сгенерировать часть кода своего API. -/// info | Информация +/// note | Примечание Вебхуки доступны в OpenAPI 3.1.0 и выше, поддерживаются в FastAPI `0.99.0` и новее. @@ -36,7 +36,7 @@ Определенные вами вебхуки попадут в схему **OpenAPI** и в автоматический **интерфейс документации**. -/// info | Информация +/// note | Примечание Объект `app.webhooks` на самом деле — это обычный `APIRouter`, тот же тип, который вы используете при структурировании приложения по нескольким файлам. diff --git a/docs/ru/docs/advanced/path-operation-advanced-configuration.md b/docs/ru/docs/advanced/path-operation-advanced-configuration.md index fe2996362..e3bd78d50 100644 --- a/docs/ru/docs/advanced/path-operation-advanced-configuration.md +++ b/docs/ru/docs/advanced/path-operation-advanced-configuration.md @@ -16,17 +16,11 @@ ### Использование имени *функции-обработчика пути* как operationId { #using-the-path-operation-function-name-as-the-operationid } -Если вы хотите использовать имена функций ваших API в качестве `operationId`, вы можете пройти по всем из них и переопределить `operation_id` каждой *операции пути* с помощью их `APIRoute.name`. +Если вы хотите использовать имена функций ваших API в качестве `operationId`, вы можете передать пользовательскую `generate_unique_id_function` в `FastAPI`. -Делать это следует после добавления всех *операций пути*. +Эта функция получает каждый `APIRoute` и возвращает `operationId`, который нужно использовать для этой операции пути. -{* ../../docs_src/path_operation_advanced_configuration/tutorial002_py310.py hl[2, 12:21, 24] *} - -/// tip | Совет - -Если вы вызываете `app.openapi()` вручную, обновите `operationId` до этого. - -/// +{* ../../docs_src/path_operation_advanced_configuration/tutorial002_py310.py hl[2,5:6,9] *} /// warning | Предупреждение diff --git a/docs/ru/docs/advanced/response-change-status-code.md b/docs/ru/docs/advanced/response-change-status-code.md index 3dd0c9446..a4ebd4fbc 100644 --- a/docs/ru/docs/advanced/response-change-status-code.md +++ b/docs/ru/docs/advanced/response-change-status-code.md @@ -1,6 +1,6 @@ # Response - Изменение статус-кода { #response-change-status-code } -Вы, вероятно, уже читали о том, что можно установить [статус-код ответа по умолчанию](../tutorial/response-status-code.md). +Вы, вероятно, уже читали о том, что можно установить [статус-код ответа](../tutorial/response-status-code.md) по умолчанию. Но в некоторых случаях нужно вернуть другой статус-код, отличный от значения по умолчанию. @@ -16,7 +16,7 @@ ## Использование параметра `Response` { #use-a-response-parameter } -Вы можете объявить параметр типа `Response` в вашей *функции обработки пути* (как и для cookies и HTTP-заголовков). +Вы можете объявить параметр типа `Response` в вашей *функции-обработчике пути* (как и для cookies и HTTP-заголовков). И затем вы можете установить `status_code` в этом *временном* объекте ответа. diff --git a/docs/ru/docs/advanced/response-cookies.md b/docs/ru/docs/advanced/response-cookies.md index 2adc1af85..3e16fe892 100644 --- a/docs/ru/docs/advanced/response-cookies.md +++ b/docs/ru/docs/advanced/response-cookies.md @@ -1,5 +1,6 @@ # Cookies в ответе { #response-cookies } + ## Использование параметра `Response` { #use-a-response-parameter } Вы можете объявить параметр типа `Response` в вашей функции-обработчике пути. diff --git a/docs/ru/docs/advanced/response-directly.md b/docs/ru/docs/advanced/response-directly.md index fcb8d533d..c9a229018 100644 --- a/docs/ru/docs/advanced/response-directly.md +++ b/docs/ru/docs/advanced/response-directly.md @@ -18,7 +18,7 @@ Вы можете возвращать `Response` или любой его подкласс. -/// info | Информация +/// note | Примечание `JSONResponse` сам по себе является подклассом `Response`. diff --git a/docs/ru/docs/advanced/response-headers.md b/docs/ru/docs/advanced/response-headers.md index 806b89e1f..e0cfa66ed 100644 --- a/docs/ru/docs/advanced/response-headers.md +++ b/docs/ru/docs/advanced/response-headers.md @@ -2,7 +2,7 @@ ## Использовать параметр `Response` { #use-a-response-parameter } -Вы можете объявить параметр типа `Response` в вашей функции-обработчике пути (как можно сделать и для cookie). +Вы можете объявить параметр типа `Response` в вашей *функции-обработчике пути* (как можно сделать и для cookie). А затем вы можете устанавливать HTTP-заголовки в этом *временном* объекте ответа. @@ -14,13 +14,13 @@ **FastAPI** использует этот *временный* ответ, чтобы извлечь HTTP-заголовки (а также cookie и статус-код) и поместит их в финальный HTTP-ответ, который содержит возвращённое вами значение, отфильтрованное согласно `response_model`. -Вы также можете объявлять параметр `Response` в зависимостях и устанавливать в них заголовки (и cookie). +Вы также можете объявлять параметр `Response` в зависимостях и устанавливать в них HTTP-заголовки (и cookie). ## Вернуть `Response` напрямую { #return-a-response-directly } Вы также можете добавить HTTP-заголовки, когда возвращаете `Response` напрямую. -Создайте ответ, как описано в [Вернуть Response напрямую](response-directly.md), и передайте заголовки как дополнительный параметр: +Создайте ответ, как описано в [Вернуть Response напрямую](response-directly.md), и передайте HTTP-заголовки как дополнительный параметр: {* ../../docs_src/response_headers/tutorial001_py310.py hl[10:12] *} @@ -30,12 +30,12 @@ **FastAPI** предоставляет те же самые `starlette.responses` как `fastapi.responses` — для вашего удобства как разработчика. Но большинство доступных классов ответов поступают напрямую из Starlette. -И поскольку `Response` часто используется для установки заголовков и cookie, **FastAPI** также предоставляет его как `fastapi.Response`. +И поскольку `Response` часто используется для установки HTTP-заголовков и cookie, **FastAPI** также предоставляет его как `fastapi.Response`. /// ## Пользовательские HTTP-заголовки { #custom-headers } -Помните, что собственные проприетарные заголовки можно добавлять, [используя префикс `X-`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers). +Помните, что собственные проприетарные HTTP-заголовки можно добавлять, [используя префикс `X-`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers). -Но если у вас есть пользовательские заголовки, которые вы хотите показывать клиенту в браузере, вам нужно добавить их в настройки CORS (подробнее см. в [CORS (Cross-Origin Resource Sharing)](../tutorial/cors.md)), используя параметр `expose_headers`, описанный в [документации Starlette по CORS](https://www.starlette.dev/middleware/#corsmiddleware). +Но если у вас есть пользовательские HTTP-заголовки, которые вы хотите показывать клиенту в браузере, вам нужно добавить их в настройки CORS (подробнее см. в [CORS (Cross-Origin Resource Sharing)](../tutorial/cors.md)), используя параметр `expose_headers`, описанный в [документации Starlette по CORS](https://www.starlette.dev/middleware/#corsmiddleware). diff --git a/docs/ru/docs/advanced/security/oauth2-scopes.md b/docs/ru/docs/advanced/security/oauth2-scopes.md index 944baeeeb..7b1731c5d 100644 --- a/docs/ru/docs/advanced/security/oauth2-scopes.md +++ b/docs/ru/docs/advanced/security/oauth2-scopes.md @@ -46,7 +46,7 @@ OAuth2 со scopes — это механизм, который использу - `instagram_basic` используется Facebook / Instagram. - `https://www.googleapis.com/auth/drive` используется Google. -/// info | Информация +/// note | Примечание В OAuth2 «scope» — это просто строка, объявляющая требуемое конкретное разрешение. @@ -76,7 +76,7 @@ OAuth2 со scopes — это механизм, который использу Так как теперь мы объявляем эти scopes, они появятся в документации API при входе/авторизации. -И вы сможете выбрать, какие scopes вы хотите выдать доступ: `me` и `items`. +И вы сможете выбрать, для каких scopes хотите предоставить доступ: `me` и `items`. Это тот же механизм, когда вы даёте разрешения при входе через Facebook, Google, GitHub и т.д.: @@ -100,7 +100,7 @@ OAuth2 со scopes — это механизм, который использу {* ../../docs_src/security/tutorial005_an_py310.py hl[157] *} -## Объявление scopes в *обработчиках путей* и зависимостях { #declare-scopes-in-path-operations-and-dependencies } +## Объявление scopes в *операциях пути* и зависимостях { #declare-scopes-in-path-operations-and-dependencies } Теперь объявим, что операция пути для `/users/me/items/` требует scope `items`. @@ -126,7 +126,7 @@ OAuth2 со scopes — это механизм, который использу {* ../../docs_src/security/tutorial005_an_py310.py hl[5,141,172] *} -/// info | Технические детали +/// note | Технические детали `Security` на самом деле является подклассом `Depends` и имеет всего один дополнительный параметр, который мы рассмотрим позже. diff --git a/docs/ru/docs/advanced/settings.md b/docs/ru/docs/advanced/settings.md index 3ae063340..b85aa3959 100644 --- a/docs/ru/docs/advanced/settings.md +++ b/docs/ru/docs/advanced/settings.md @@ -205,7 +205,7 @@ APP_NAME="ChimichangApp" ### Создание `Settings` только один раз с помощью `lru_cache` { #creating-the-settings-only-once-with-lru-cache } -Чтение файла с диска обычно затратная (медленная) операция, поэтому, вероятно, вы захотите сделать это один раз и затем переиспользовать один и тот же объект настроек, а не читать файл при каждом запросе. +Чтение файла с диска обычно затратная (медленная) операция, поэтому, вероятно, вы захотите сделать это один раз и затем переиспользовать один и тот же объект настроек, а не читать файл при каждом HTTP-запросе. Но каждый раз, когда мы делаем: @@ -222,13 +222,13 @@ def get_settings(): return Settings() ``` -мы бы создавали этот объект для каждого запроса и читали файл `.env` на каждый запрос. ⚠️ +мы бы создавали этот объект для каждого HTTP-запроса и читали файл `.env` на каждый HTTP-запрос. ⚠️ Но так как мы используем декоратор `@lru_cache` сверху, объект `Settings` будет создан только один раз — при первом вызове. ✔️ {* ../../docs_src/settings/app03_an_py310/main.py hl[1,11] *} -Затем при любых последующих вызовах `get_settings()` в зависимостях для следующих запросов, вместо выполнения внутреннего кода `get_settings()` и создания нового объекта `Settings`, будет возвращаться тот же объект, что был возвращен при первом вызове, снова и снова. +Затем при любых последующих вызовах `get_settings()` в зависимостях для следующих HTTP-запросов, вместо выполнения внутреннего кода `get_settings()` и создания нового объекта `Settings`, будет возвращаться тот же объект, что был возвращен при первом вызове, снова и снова. #### Технические детали `lru_cache` { #lru-cache-technical-details } @@ -299,4 +299,4 @@ participant execute as Execute function * Используя зависимость, вы упрощаете тестирование. * Можно использовать файлы `.env`. -* `@lru_cache` позволяет не читать файл dotenv снова и снова для каждого запроса, при этом давая возможность переопределять его во время тестирования. +* `@lru_cache` позволяет не читать файл dotenv снова и снова для каждого HTTP-запроса, при этом давая возможность переопределять его во время тестирования. diff --git a/docs/ru/docs/advanced/stream-data.md b/docs/ru/docs/advanced/stream-data.md index 4c373db1a..d6957a6cf 100644 --- a/docs/ru/docs/advanced/stream-data.md +++ b/docs/ru/docs/advanced/stream-data.md @@ -2,9 +2,9 @@ Если вам нужно передавать потоковые данные, которые можно представить как JSON, воспользуйтесь [стримингом JSON Lines](../tutorial/stream-json-lines.md). -Но если вы хотите передавать в потоке чистые бинарные данные или строки, ниже показано, как это сделать. +Но если вы хотите передавать в потоке **чистые бинарные данные** или строки, ниже показано, как это сделать. -/// info | Информация +/// note | Примечание Добавлено в FastAPI 0.134.0. @@ -40,7 +40,7 @@ FastAPI будет передавать каждый чанк данных в `S {* ../../docs_src/stream_data/tutorial001_py310.py ln[32:35] hl[33] *} -Это также означает, что с `StreamingResponse` у вас есть и свобода, и ответственность — производить и кодировать байты данных ровно в том виде, в котором они должны быть отправлены, независимо от аннотаций типов. 🤓 +Это также означает, что с `StreamingResponse` у вас есть и **свобода**, и **ответственность** — производить и кодировать байты данных ровно в том виде, в котором они должны быть отправлены, независимо от аннотаций типов. 🤓 ### Потоковая передача байтов { #stream-bytes } @@ -90,7 +90,7 @@ FastAPI будет передавать каждый чанк данных в `S И во многих случаях чтение таких объектов будет блокирующей операцией (которая может заблокировать цикл событий), потому что данные читаются с диска или из сети. -/// info | Информация +/// note | Примечание Приведённый выше пример — исключение, потому что объект `io.BytesIO` уже находится в памяти, поэтому чтение ничего не блокирует. diff --git a/docs/ru/docs/advanced/strict-content-type.md b/docs/ru/docs/advanced/strict-content-type.md index 1a0cbbc31..1d732421c 100644 --- a/docs/ru/docs/advanced/strict-content-type.md +++ b/docs/ru/docs/advanced/strict-content-type.md @@ -81,7 +81,7 @@ http://localhost:8000/v1/agents/multivac С этой настройкой запросы без заголовка `Content-Type` будут иметь тело запроса, обработанное как JSON — это такое же поведение, как в более старых версиях FastAPI. -/// info | Информация +/// note | Примечание Это поведение и настройка были добавлены в FastAPI 0.132.0. diff --git a/docs/ru/docs/advanced/websockets.md b/docs/ru/docs/advanced/websockets.md index abfd789a4..0f69f57b3 100644 --- a/docs/ru/docs/advanced/websockets.md +++ b/docs/ru/docs/advanced/websockets.md @@ -111,7 +111,7 @@ $ fastapi dev {* ../../docs_src/websockets_/tutorial002_an_py310.py hl[68:69,82] *} -/// info | Примечание +/// note | Примечание В веб-сокете вызывать `HTTPException` не имеет смысла. Вместо этого нужно использовать `WebSocketException`. diff --git a/docs/ru/docs/advanced/wsgi.md b/docs/ru/docs/advanced/wsgi.md index 3ed85d0e9..99ba50938 100644 --- a/docs/ru/docs/advanced/wsgi.md +++ b/docs/ru/docs/advanced/wsgi.md @@ -6,7 +6,7 @@ ## Использование `WSGIMiddleware` { #using-wsgimiddleware } -/// info | Информация +/// note | Примечание Для этого требуется установить `a2wsgi`, например с помощью `pip install a2wsgi`. @@ -14,7 +14,7 @@ Нужно импортировать `WSGIMiddleware` из `a2wsgi`. -Затем оберните WSGI‑приложение (например, Flask) в middleware (Промежуточный слой). +Затем оберните WSGI‑приложение (например, Flask) в middleware (промежуточный слой). После этого смонтируйте его на путь. @@ -26,7 +26,7 @@ Вместо него рекомендуется использовать пакет `a2wsgi`. Использование остаётся таким же. -Просто убедитесь, что пакет `a2wsgi` установлен, и импортируйте `WSGIMiddleware` из `a2wsgi`. +Просто убедитесь, что пакет `a2wsgi` установлен, и правильно импортируйте `WSGIMiddleware` из `a2wsgi`. /// diff --git a/docs/ru/docs/alternatives.md b/docs/ru/docs/alternatives.md index 13f099da8..e1b8e277d 100644 --- a/docs/ru/docs/alternatives.md +++ b/docs/ru/docs/alternatives.md @@ -20,7 +20,7 @@ Он относительно тесно связан с реляционными базами данных (например, MySQL или PostgreSQL), поэтому использовать NoSQL-базу данных (например, Couchbase, MongoDB, Cassandra и т. п.) в качестве основного хранилища не очень просто. -Он был создан для генерации HTML на бэкенде, а не для создания API, используемых современным фронтендом (например, React, Vue.js и Angular) или другими системами (например, устройствами IoT), которые с ним общаются. +Он был создан для генерации HTML на бэкенде, а не для создания API, используемых современным фронтендом (например, React, Vue.js и Angular) или другими системами (например, устройствами IoT), которые с ним общаются. ### [Django REST Framework](https://www.django-rest-framework.org/) { #django-rest-framework } @@ -88,7 +88,7 @@ Requests имеет очень простой и понятный дизайн, response = requests.get("http://example.com/some/url") ``` -Соответствующая в FastAPI API-операция пути могла бы выглядеть так: +Соответствующая в FastAPI API-*операция пути* могла бы выглядеть так: ```Python hl_lines="1" @app.get("/some/url") diff --git a/docs/ru/docs/async.md b/docs/ru/docs/async.md index e2b98bd61..aba77a96b 100644 --- a/docs/ru/docs/async.md +++ b/docs/ru/docs/async.md @@ -12,7 +12,7 @@ results = await some_library() ``` -Тогда объявляйте *функции-обработчиков пути* с `async def`, например: +Тогда объявляйте *функции-обработчики пути* с `async def`, например: ```Python hl_lines="2" @app.get('/') @@ -29,7 +29,7 @@ async def read_results(): --- -Если вы используете стороннюю библиотеку, которая взаимодействует с чем-то (база данных, API, файловая система и т.д.) и не поддерживает использование `await` (сейчас это относится к большинству библиотек для БД), тогда объявляйте *функции-обработчиков пути* как обычно, просто с `def`, например: +Если вы используете стороннюю библиотеку, которая взаимодействует с чем-то (база данных, API, файловая система и т.д.) и не поддерживает использование `await` (сейчас это относится к большинству библиотек для БД), тогда объявляйте *функции-обработчики пути* как обычно, просто с `def`, например: ```Python hl_lines="2" @app.get('/') @@ -48,7 +48,7 @@ def results(): --- -**Примечание**: вы можете смешивать `def` и `async def` в *функциях-обработчиков пути* столько, сколько нужно, и объявлять каждую так, как лучше для вашего случая. FastAPI сделает с ними всё как надо. +**Примечание**: вы можете смешивать `def` и `async def` в *функциях-обработчиках пути* столько, сколько нужно, и объявлять каждую так, как лучше для вашего случая. FastAPI сделает с ними всё как надо. В любом из случаев выше FastAPI всё равно работает асинхронно и очень быстро. @@ -249,7 +249,7 @@ def results(): Именно такая асинхронность сделала NodeJS популярным (хотя NodeJS — не параллельный), и это сильная сторона Go как языка программирования. -Того же уровня производительности вы получаете с **FastAPI**. +Тот же уровень производительности вы получаете с **FastAPI**. А так как можно одновременно использовать параллелизм и асинхронность, вы получаете производительность выше, чем у большинства протестированных фреймворков на NodeJS и на уровне Go, который — компилируемый язык, ближе к C [(всё благодаря Starlette)](https://www.techempower.com/benchmarks/#section=data-r17&hw=ph&test=query&l=zijmkf-1). @@ -340,7 +340,7 @@ burgers = get_burgers(2) --- -Итак, если вы используете библиотеку, которую можно вызывать с `await`, вам нужно создать *функцию-обработчик пути*, которая её использует, с `async def`, например: +Итак, если вы используете библиотеку, которую можно вызывать с `await`, вам нужно создать *функции-обработчики пути*, которые её используют, с `async def`, например: ```Python hl_lines="2-3" @app.get('/burgers') diff --git a/docs/ru/docs/deployment/cloud.md b/docs/ru/docs/deployment/cloud.md index cbd517e36..eb1b49aa5 100644 --- a/docs/ru/docs/deployment/cloud.md +++ b/docs/ru/docs/deployment/cloud.md @@ -1,6 +1,6 @@ # Развертывание FastAPI у облачных провайдеров { #deploy-fastapi-on-cloud-providers } -Вы можете использовать практически любого облачного провайдера, чтобы развернуть свое приложение на FastAPI. +Вы можете использовать практически **любого облачного провайдера**, чтобы развернуть свое приложение на FastAPI. В большинстве случаев у основных облачных провайдеров есть руководства по развертыванию FastAPI на их платформе. @@ -16,7 +16,7 @@ FastAPI Cloud — основной спонсор и источник финан ## Облачные провайдеры — спонсоры { #cloud-providers-sponsors } -Некоторые другие облачные провайдеры ✨ [**спонсируют FastAPI**](../help-fastapi.md#sponsor-the-author) ✨ тоже. 🙇 +Некоторые другие облачные провайдеры ✨ [**спонсируют FastAPI**](https://github.com/sponsors/tiangolo) ✨ тоже. 🙇 Возможно, вы захотите попробовать их сервисы и воспользоваться их руководствами: diff --git a/docs/ru/docs/deployment/concepts.md b/docs/ru/docs/deployment/concepts.md index 900b842f9..23c62b8d3 100644 --- a/docs/ru/docs/deployment/concepts.md +++ b/docs/ru/docs/deployment/concepts.md @@ -243,7 +243,7 @@ Не беспокойтесь, если некоторые пункты про **контейнеры**, Docker или Kubernetes пока кажутся неочевидными. -Я расскажу больше про образы контейнеров, Docker, Kubernetes и т.п. в следующей главе: [FastAPI внутри контейнеров — Docker](docker.md). +Я расскажу больше про образы контейнеров, Docker, Kubernetes и т.п. в одной из будущих глав: [FastAPI внутри контейнеров — Docker](docker.md). /// @@ -281,7 +281,7 @@ /// tip | Совет -Я приведу более конкретные примеры с контейнерами в следующей главе: [FastAPI внутри контейнеров — Docker](docker.md). +Я приведу более конкретные примеры с контейнерами в одной из будущих глав: [FastAPI внутри контейнеров — Docker](docker.md). /// @@ -301,9 +301,9 @@ Также возможен **всплеск** использования вашего API: он мог «взорваться» по популярности, или какие‑то сервисы/боты начали его активно использовать. На такие случаи стоит иметь запас ресурсов. -Можно задать **целевое значение**, например **между 50% и 90%** использования ресурсов. Скорее всего, именно эти вещи вы будете измерять и на их основе настраивать развёртывание. +Можно задать **произвольное число** в качестве цели, например **между 50% и 90%** использования ресурсов. Скорее всего, именно эти вещи вы будете измерять и на их основе настраивать развёртывание. -Можно использовать простые инструменты вроде `htop`, чтобы смотреть загрузку CPU и RAM на сервере или по процессам. Или более сложные распределённые системы мониторинга. +Можно использовать простые инструменты вроде `htop`, чтобы смотреть загрузку CPU и RAM на сервере или по процессам. Или более сложные инструменты мониторинга, которые могут быть распределены по серверам и т.п. ## Резюме { #recap } diff --git a/docs/ru/docs/deployment/docker.md b/docs/ru/docs/deployment/docker.md index 3b16d7798..c3cf9a328 100644 --- a/docs/ru/docs/deployment/docker.md +++ b/docs/ru/docs/deployment/docker.md @@ -132,7 +132,7 @@ Successfully installed fastapi pydantic -/// info | Информация +/// note | Заметка Существуют и другие форматы и инструменты для описания и установки зависимостей. @@ -275,7 +275,7 @@ CMD fastapi run app/main.py --port 80 #### За прокси-сервером TSL-терминации { #behind-a-tls-termination-proxy } -Если вы запускаете контейнер за прокси-сервером TSL-терминации (балансировщиком нагрузки), таким как Nginx или Traefik, добавьте опцию `--proxy-headers`. Это сообщит Uvicorn (через FastAPI CLI), что приложение работает за HTTPS и можно доверять соответствующим заголовкам. +Если вы запускаете контейнер за прокси-сервером TSL-терминации (балансировщиком нагрузки), таким как Nginx или Traefik, добавьте опцию `--proxy-headers`. Это сообщит Uvicorn (через FastAPI CLI), что можно доверять заголовкам, отправленным этим прокси и сообщающим, что приложение работает за HTTPS, и т.д. ```Dockerfile CMD ["fastapi", "run", "app/main.py", "--proxy-headers", "--port", "80"] @@ -407,9 +407,9 @@ CMD ["fastapi", "run", "main.py", "--port", "80"] 1. Копируем файл `main.py` напрямую в `/code` (без директории `./app`). -2. Используем `fastapi run` для запуска приложения из одного файла `main.py`. +2. Используем `fastapi run`, чтобы «отдавать» приложение из одного файла `main.py`. -Когда вы передаёте файл в `fastapi run`, он автоматически определит, что это одиночный файл, а не часть пакета, и поймёт, как его импортировать и запустить ваше FastAPI-приложение. 😎 +Когда вы передаёте файл в `fastapi run`, он автоматически определит, что это одиночный файл, а не часть пакета, и поймёт, как импортировать и «отдавать» ваше FastAPI-приложение. 😎 ## Концепции развертывания { #deployment-concepts } @@ -525,7 +525,7 @@ CMD ["fastapi", "run", "app/main.py", "--port", "80", "--workers", "4"] Вы можете развёртывать на **одном сервере** (не кластере) с **Docker Compose**, и у вас не будет простого способа управлять репликацией контейнеров (в Docker Compose), сохраняя общую сеть и **балансировку нагрузки**. -Тогда вы можете захотеть **один контейнер** с **менеджером процессов**, который запускает **несколько воркеров** внутри. +Тогда вы можете захотеть **один контейнер** с **менеджером процессов**, который запускает **несколько воркер-процессов** внутри. --- @@ -556,7 +556,7 @@ CMD ["fastapi", "run", "app/main.py", "--port", "80", "--workers", "4"] Если у вас **несколько контейнеров**, и, вероятно, каждый запускает **один процесс** (например, в кластере **Kubernetes**), то вы, скорее всего, захотите иметь **отдельный контейнер**, выполняющий **предварительные шаги** в одном контейнере и одном процессе **до** запуска реплицированных контейнеров-воркеров. -/// info | Информация +/// note | Заметка Если вы используете Kubernetes, это, вероятно, будет [Init Container](https://kubernetes.io/docs/concepts/workloads/pods/init-containers/). @@ -566,7 +566,7 @@ CMD ["fastapi", "run", "app/main.py", "--port", "80", "--workers", "4"] ### Один контейнер { #single-container } -Если у вас простая схема с **одним контейнером**, который затем запускает несколько **воркеров** (или один процесс), можно выполнить подготовительные шаги в этом же контейнере непосредственно перед запуском процесса с приложением. +Если у вас простая схема с **одним контейнером**, который затем запускает несколько **воркер-процессов** (или один процесс), можно выполнить подготовительные шаги в этом же контейнере непосредственно перед запуском процесса с приложением. ### Базовый Docker-образ { #base-docker-image } @@ -580,7 +580,7 @@ CMD ["fastapi", "run", "app/main.py", "--port", "80", "--workers", "4"] /// note | Технические подробности -Этот Docker-образ был создан в то время, когда Uvicorn не умел управлять и перезапускать «упавших» воркеров, и приходилось использовать Gunicorn вместе с Uvicorn, что добавляло заметную сложность, лишь бы Gunicorn управлял и перезапускал воркеров Uvicorn. +Этот Docker-образ был создан в то время, когда Uvicorn не умел управлять и перезапускать «упавших» воркеров, и приходилось использовать Gunicorn вместе с Uvicorn, что добавляло заметную сложность, лишь бы Gunicorn управлял и перезапускал воркер-процессы Uvicorn. Но теперь, когда Uvicorn (и команда `fastapi`) поддерживают `--workers`, нет причин использовать базовый Docker-образ вместо сборки своего (кода получается примерно столько же 😅). @@ -615,4 +615,4 @@ CMD ["fastapi", "run", "app/main.py", "--port", "80", "--workers", "4"] В большинстве случаев вы, вероятно, не захотите использовать какой-либо базовый образ, а вместо этого **соберёте образ контейнера с нуля** на основе официального Docker-образа Python. -Заботясь о **порядке** инструкций в `Dockerfile` и используя **кэш Docker**, вы можете **минимизировать время сборки**, чтобы повысить продуктивность (и не скучать). 😎 +Заботясь о **порядке** инструкций в `Dockerfile` и используя **кэш Docker**, вы можете **минимизировать время сборки**, чтобы повысить продуктивность (и не скучать). 😎 diff --git a/docs/ru/docs/deployment/fastapicloud.md b/docs/ru/docs/deployment/fastapicloud.md index 95db3387f..fa3160519 100644 --- a/docs/ru/docs/deployment/fastapicloud.md +++ b/docs/ru/docs/deployment/fastapicloud.md @@ -1,26 +1,6 @@ # FastAPI Cloud { #fastapi-cloud } -Вы можете развернуть своё приложение FastAPI в [FastAPI Cloud](https://fastapicloud.com) одной командой, присоединяйтесь к списку ожидания, если ещё не сделали этого. 🚀 - -## Вход { #login } - -Убедитесь, что у вас уже есть аккаунт **FastAPI Cloud** (мы пригласили вас из списка ожидания 😉). - -Затем выполните вход: - -
- -```console -$ fastapi login - -You are logged in to FastAPI Cloud 🚀 -``` - -
- -## Деплой { #deploy } - -Теперь разверните приложение одной командой: +Вы можете развернуть своё приложение FastAPI в [FastAPI Cloud](https://fastapicloud.com) всего **одной командой**. 🚀
@@ -36,6 +16,8 @@ Deploying to FastAPI Cloud...
+CLI автоматически определит ваше приложение FastAPI и развернёт его в облаке. Если вы не вошли в аккаунт, откроется браузер для завершения процесса аутентификации. + Вот и всё! Теперь вы можете открыть своё приложение по этому URL. ✨ ## О FastAPI Cloud { #about-fastapi-cloud } diff --git a/docs/ru/docs/deployment/https.md b/docs/ru/docs/deployment/https.md index 181cac0d8..8c1b153f0 100644 --- a/docs/ru/docs/deployment/https.md +++ b/docs/ru/docs/deployment/https.md @@ -6,7 +6,7 @@ /// tip | Совет -Если вы торопитесь или вам это не важно, переходите к следующим разделам с пошаговыми инструкциями по настройке всего разными способами. +Если вы торопитесь или вам это не важно, продолжайте со следующих разделов с пошаговыми инструкциями по настройке всего разными способами. /// @@ -65,7 +65,7 @@ Чаще всего всё начинается с **приобретения** **имени домена**. Затем вы настраиваете его на DNS‑сервере (возможно, у того же облачного провайдера). -Скорее всего, вы получите облачный сервер (виртуальную машину) или что-то подобное, и у него будет постоянный **публичный IP-адрес**. +Скорее всего, вы получите облачный сервер (виртуальную машину) или что-то подобное, и у него будет постоянный **публичный IP-адрес**. На DNS‑сервере(ах) вы настроите запись («`A record`» - запись типа A), указывающую, что **ваш домен** должен указывать на публичный **IP‑адрес вашего сервера**. @@ -194,7 +194,7 @@ DNS‑серверы ответят браузеру, какой **конкре Когда вы используете прокси для обработки HTTPS, ваш **сервер приложения** (например, Uvicorn через FastAPI CLI) ничего не знает о процессе HTTPS, он общается обычным HTTP с **прокси‑сервером TLS-терминации**. -Обычно этот **прокси** на лету добавляет некоторые HTTP‑заголовки перед тем, как переслать запрос на **сервер приложения**, чтобы тот знал, что запрос был **проксирован**. +Обычно этот **прокси** на лету добавляет некоторые HTTP‑заголовки перед тем, как переслать запрос на **сервер приложения**, чтобы тот знал, что запрос был **переслан** прокси. /// note | Технические детали @@ -218,7 +218,7 @@ DNS‑серверы ответят браузеру, какой **конкре /// tip | Совет -Подробнее об этом вы можете узнать в документации: [За прокси — Включить пересылаемые заголовки прокси](../advanced/behind-a-proxy.md#enable-proxy-forwarded-headers) +Подробнее об этом вы можете узнать в документации: [За прокси — включить пересылаемые заголовки прокси](../advanced/behind-a-proxy.md#enable-proxy-forwarded-headers) /// diff --git a/docs/ru/docs/deployment/manually.md b/docs/ru/docs/deployment/manually.md index 3169f3189..e6408c944 100644 --- a/docs/ru/docs/deployment/manually.md +++ b/docs/ru/docs/deployment/manually.md @@ -2,7 +2,7 @@ ## Используйте команду `fastapi run` { #use-the-fastapi-run-command } -Коротко: используйте `fastapi run`, чтобы запустить ваше приложение FastAPI: +Коротко: используйте `fastapi run`, чтобы предоставлять доступ к вашему приложению FastAPI:
@@ -46,7 +46,7 @@ $ fastapi run ASGI. FastAPI — ASGI-веб‑фреймворк. +FastAPI использует стандарт для построения Python‑веб‑фреймворков и серверов под названием ASGI. FastAPI — ASGI-веб‑фреймворк. Главное, что вам нужно, чтобы запустить приложение **FastAPI** (или любое другое ASGI‑приложение) на удалённой серверной машине, — это программа ASGI‑сервера, такая как **Uvicorn**; именно он используется по умолчанию в команде `fastapi`. @@ -56,7 +56,6 @@ FastAPI использует стандарт для построения Python * [Hypercorn](https://hypercorn.readthedocs.io/): ASGI‑сервер, среди прочего совместимый с HTTP/2 и Trio. * [Daphne](https://github.com/django/daphne): ASGI‑сервер, созданный для Django Channels. * [Granian](https://github.com/emmett-framework/granian): HTTP‑сервер на Rust для Python‑приложений. -* [NGINX Unit](https://unit.nginx.org/howto/fastapi/): NGINX Unit — лёгкая и многофункциональная среда выполнения веб‑приложений. ## Сервер как машина и сервер как программа { #server-machine-and-server-program } diff --git a/docs/ru/docs/deployment/server-workers.md b/docs/ru/docs/deployment/server-workers.md index 2caf79f7d..8d4bd33ef 100644 --- a/docs/ru/docs/deployment/server-workers.md +++ b/docs/ru/docs/deployment/server-workers.md @@ -17,7 +17,7 @@ Здесь я покажу, как использовать **Uvicorn** с **воркер-процессами** через команду `fastapi` или напрямую через команду `uvicorn`. -/// info | Информация +/// note | Примечание Если вы используете контейнеры, например Docker или Kubernetes, я расскажу об этом подробнее в следующей главе: [FastAPI в контейнерах — Docker](docker.md). diff --git a/docs/ru/docs/editor-support.md b/docs/ru/docs/editor-support.md index 0543e7162..cd02c0f40 100644 --- a/docs/ru/docs/editor-support.md +++ b/docs/ru/docs/editor-support.md @@ -20,4 +20,4 @@ - **Развернуть в FastAPI Cloud** — развертывание вашего приложения в один клик в [FastAPI Cloud](https://fastapicloud.com/). - **Поток логов приложения** — потоковая передача логов в реальном времени из вашего приложения, развернутого в FastAPI Cloud, с фильтрацией по уровню и текстовым поиском. -Если вы хотите поверхностно ознакомиться с возможностями расширения, откройте палитру команд (Ctrl + Shift + P или на macOS: Cmd + Shift + P), выберите «Welcome: Open walkthrough...», а затем «Get started with FastAPI». +Если вы хотите ознакомиться с возможностями расширения, вы можете посмотреть walkthrough расширения, открыв палитру команд (Ctrl + Shift + P или на macOS: Cmd + Shift + P) и выбрав «Welcome: Open walkthrough...», а затем walkthrough «Get started with FastAPI». diff --git a/docs/ru/docs/environment-variables.md b/docs/ru/docs/environment-variables.md index 8db16d16c..3cd0bc78b 100644 --- a/docs/ru/docs/environment-variables.md +++ b/docs/ru/docs/environment-variables.md @@ -50,9 +50,9 @@ Hello Wade Wilson //// -## Чтение переменных окружения в python { #read-env-vars-in-python } +## Чтение переменных окружения в Python { #read-env-vars-in-python } -Так же существует возможность создания переменных окружения **вне** Python, в терминале (или любым другим способом), а затем **чтения их в Python**. +Также существует возможность создания переменных окружения **вне** Python, в терминале (или любым другим способом), а затем **чтения их в Python**. Например, у вас есть файл `main.py`: @@ -67,7 +67,7 @@ print(f"Hello {name} from Python") Второй аргумент [`os.getenv()`](https://docs.python.org/3.8/library/os.html#os.getenv) - это возвращаемое по умолчанию значение. -Если значение не указано, то по умолчанию оно равно `None`. В данном случае мы указываем `«World»` в качестве значения по умолчанию. +Если значение не указано, то по умолчанию оно равно `None`. В данном случае мы указываем `"World"` в качестве значения по умолчанию. /// @@ -157,13 +157,13 @@ Hello World from Python /// -## Типизация и Валидация { #types-and-validation } +## Типы и валидация { #types-and-validation } Эти переменные окружения могут работать только с **текстовыми строками**, поскольку они являются внешними по отношению к Python и должны быть совместимы с другими программами и остальной системой (и даже с различными операционными системами, такими как Linux, Windows, macOS). Это означает, что **любое значение**, считанное в Python из переменной окружения, **будет `str`**, и любое преобразование к другому типу или любая валидация должны быть выполнены в коде. -Подробнее об использовании переменных окружения для работы с **настройками приложения** вы узнаете в [Расширенное руководство пользователя - Настройки и переменные среды](./advanced/settings.md). +Подробнее об использовании переменных окружения для работы с **настройками приложения** вы узнаете в [Расширенном руководстве пользователя - Настройки и переменные окружения](./advanced/settings.md). ## Переменная окружения `PATH` { #path-environment-variable } @@ -285,14 +285,14 @@ $ C:\opt\custompython\bin\python //// -Эта информация будет полезна при изучении [Виртуальных окружений](virtual-environments.md). +Эта информация будет полезна при изучении [виртуальных окружений](virtual-environments.md). ## Вывод { #conclusion } Благодаря этому вы должны иметь базовое представление о том, что такое **переменные окружения** и как использовать их в Python. -Подробнее о них вы также можете прочитать в [статье о переменных окружения на википедии](https://en.wikipedia.org/wiki/Environment_variable). +Подробнее о них вы также можете прочитать в [статье о переменных окружения на Википедии](https://en.wikipedia.org/wiki/Environment_variable). Во многих случаях не всегда очевидно, как переменные окружения могут быть полезны и применимы. Но они постоянно появляются в различных сценариях разработки, поэтому знать о них полезно. -Например, эта информация понадобится вам в следующем разделе, посвященном [Виртуальным окружениям](virtual-environments.md). +Например, эта информация понадобится вам в следующем разделе, посвященном [виртуальным окружениям](virtual-environments.md). diff --git a/docs/ru/docs/features.md b/docs/ru/docs/features.md index 9755c3fe5..25bbe850c 100644 --- a/docs/ru/docs/features.md +++ b/docs/ru/docs/features.md @@ -17,7 +17,7 @@ * [**Swagger UI**](https://github.com/swagger-api/swagger-ui), с интерактивным исследованием, вызовом и тестированием вашего API прямо из браузера. -![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-03-swagger-02.png) +![Взаимодействие со Swagger UI](https://fastapi.tiangolo.com/img/index/index-03-swagger-02.png) * Альтернативная документация API в [**ReDoc**](https://github.com/Rebilly/ReDoc). @@ -36,7 +36,7 @@ from datetime import date from pydantic import BaseModel -# Объявляем параметр как `str` +# Объявляем переменную как `str` # и получаем поддержку редактора кода внутри функции def main(user_id: str): return user_id @@ -71,9 +71,9 @@ my_second_user: User = User(**second_user_data) /// -### Поддержка редакторов { #editor-support } +### Поддержка редакторов кода { #editor-support } -Весь фреймворк был продуман так, чтобы быть простым и интуитивно понятным в использовании, все решения были проверены на множестве редакторов еще до начала разработки, чтобы обеспечить наилучшие условия при написании кода. +Весь фреймворк был продуман так, чтобы быть простым и интуитивно понятным в использовании, все решения были проверены на множестве редакторов кода еще до начала разработки, чтобы обеспечить наилучшие условия при написании кода. В опросах Python‑разработчиков видно, [что одной из самых часто используемых функций является «автозавершение»](https://www.jetbrains.com/research/python-developers-survey-2017/#tools-and-features). @@ -81,15 +81,15 @@ my_second_user: User = User(**second_user_data) Вам редко нужно будет возвращаться к документации. -Вот как ваш редактор может вам помочь: +Вот как ваш редактор кода может вам помочь: * в [Visual Studio Code](https://code.visualstudio.com/): -![editor support](https://fastapi.tiangolo.com/img/vscode-completion.png) +![поддержка редактора кода](https://fastapi.tiangolo.com/img/vscode-completion.png) * в [PyCharm](https://www.jetbrains.com/pycharm/): -![editor support](https://fastapi.tiangolo.com/img/pycharm-completion.png) +![поддержка редактора кода](https://fastapi.tiangolo.com/img/pycharm-completion.png) Вы будете получать автозавершение кода даже там, где вы считали это невозможным раньше. Как пример, ключ `price` внутри тела JSON (который может быть вложенным), приходящего в запросе. @@ -151,11 +151,11 @@ FastAPI включает в себя чрезвычайно простую в и Любая интеграция разработана настолько простой в использовании (с зависимостями), что вы можете создать «плагин» для своего приложения в пару строк кода, используя ту же структуру и синтаксис, что и для ваших *операций пути*. -### Проверен { #tested } +### Протестирован { #tested } -* 100% покрытие тестами. +* 100% покрытие тестами. * 100% аннотирование типов в кодовой базе. -* Используется в продакшн‑приложениях. +* Используется в приложениях в продакшн. ## Возможности Starlette { #starlette-features } @@ -190,7 +190,7 @@ FastAPI включает в себя чрезвычайно простую в и * **Никакой нервотрёпки**: * Не нужно изучать новые схемы в микроязыках. * Если вы знаете типы в Python, вы знаете, как использовать Pydantic. -* Прекрасно сочетается с вашим **IDE/линтер/мозгом**: +* Прекрасно сочетается с вашим **IDE/линтер/мозгом**: * Потому что структуры данных pydantic — это всего лишь экземпляры классов, определённых вами; автозавершение, проверка кода, mypy и ваша интуиция — всё будет работать с вашими валидированными данными. * Валидация **сложных структур**: * Использование иерархических моделей Pydantic; `List`, `Dict` и т.п. из модуля `typing`. diff --git a/docs/ru/docs/help-fastapi.md b/docs/ru/docs/help-fastapi.md index f9b9ebea3..ff47b93e8 100644 --- a/docs/ru/docs/help-fastapi.md +++ b/docs/ru/docs/help-fastapi.md @@ -38,7 +38,7 @@ ## Подписаться на автора { #follow-the-author } -Вы можете подписаться на [меня (Sebastián Ramírez / `tiangolo`)](https://tiangolo.com) в нескольких местах, чтобы узнавать новости о FastAPI и друзьях: +Вы можете подписаться на [меня (Sebastián Ramírez / `tiangolo`)](https://tiangolo.com), автора, в нескольких местах, чтобы узнавать новости о FastAPI и друзьях: * [@tiangolo в **GitHub**](https://github.com/tiangolo). * [@tiangolo в **X (Twitter)**](https://x.com/tiangolo) diff --git a/docs/ru/docs/how-to/configure-swagger-ui.md b/docs/ru/docs/how-to/configure-swagger-ui.md index b57a086b6..0dd60b423 100644 --- a/docs/ru/docs/how-to/configure-swagger-ui.md +++ b/docs/ru/docs/how-to/configure-swagger-ui.md @@ -26,7 +26,7 @@ FastAPI преобразует эти настройки в **JSON**, чтобы ## Изменить тему { #change-the-theme } -Аналогично вы можете задать тему подсветки синтаксиса с ключом "syntaxHighlight.theme" (обратите внимание, что посередине стоит точка): +Аналогично вы можете задать тему подсветки синтаксиса с ключом `"syntaxHighlight.theme"` (обратите внимание, что посередине стоит точка): {* ../../docs_src/configure_swagger_ui/tutorial002_py310.py hl[3] *} diff --git a/docs/ru/docs/how-to/custom-request-and-route.md b/docs/ru/docs/how-to/custom-request-and-route.md index 1e3a60856..6a7ecbca9 100644 --- a/docs/ru/docs/how-to/custom-request-and-route.md +++ b/docs/ru/docs/how-to/custom-request-and-route.md @@ -18,13 +18,13 @@ Некоторые сценарии: -* Преобразование тел запросов, не в формате JSON, в JSON (например, [`msgpack`](https://msgpack.org/index.html)). +* Преобразование тел запросов не в формате JSON в JSON (например, [`msgpack`](https://msgpack.org/index.html)). * Распаковка тел запросов, сжатых с помощью gzip. * Автоматическое логирование всех тел запросов. ## Обработка пользовательского кодирования тела запроса { #handling-custom-request-body-encodings } -Посмотрим как использовать пользовательский подкласс `Request` для распаковки gzip-запросов. +Посмотрим, как использовать пользовательский подкласс `Request` для распаковки gzip-запросов. И подкласс `APIRoute`, чтобы использовать этот пользовательский класс запроса. @@ -38,9 +38,9 @@ Сначала создадим класс `GzipRequest`, который переопределит метод `Request.body()` и распакует тело запроса при наличии соответствующего HTTP-заголовка. -Если в заголовке нет `gzip`, он не будет пытаться распаковывать тело. +Если в HTTP-заголовке нет `gzip`, он не будет пытаться распаковывать тело. -Таким образом, один и тот же класс маршрута сможет обрабатывать как gzip-сжатые, так и несжатые запросы. +Таким образом, один и тот же класс маршрута сможет обрабатывать как gzip-сжатые, так и несжатые HTTP-запросы. {* ../../docs_src/custom_request_and_route/tutorial001_an_py310.py hl[9:16] *} @@ -90,7 +90,7 @@ Тем же подходом можно воспользоваться, чтобы получить доступ к телу запроса в обработчике исключений. -Нужно лишь обработать запрос внутри блока `try`/`except`: +Нужно лишь обработать HTTP-запрос внутри блока `try`/`except`: {* ../../docs_src/custom_request_and_route/tutorial002_an_py310.py hl[14,16] *} @@ -104,6 +104,6 @@ {* ../../docs_src/custom_request_and_route/tutorial003_py310.py hl[26] *} -В этом примере *операции пути*, объявленные в `router`, будут использовать пользовательский класс `TimedRoute` и получат дополнительный HTTP-заголовок `X-Response-Time` в ответе с временем, затраченным на формирование ответа: +В этом примере *операции пути*, объявленные в `router`, будут использовать пользовательский класс `TimedRoute` и получат дополнительный HTTP-заголовок `X-Response-Time` в HTTP-ответе с временем, затраченным на формирование HTTP-ответа: {* ../../docs_src/custom_request_and_route/tutorial003_py310.py hl[13:20] *} diff --git a/docs/ru/docs/how-to/extending-openapi.md b/docs/ru/docs/how-to/extending-openapi.md index c1e369f5e..4a0a91b1c 100644 --- a/docs/ru/docs/how-to/extending-openapi.md +++ b/docs/ru/docs/how-to/extending-openapi.md @@ -25,11 +25,19 @@ * `openapi_version`: Версия используемой спецификации OpenAPI. По умолчанию — последняя: `3.1.0`. * `summary`: Краткое описание API. * `description`: Описание вашего API; может включать Markdown и будет отображаться в документации. -* `routes`: Список маршрутов — это каждая зарегистрированная *операция пути*. Берутся из `app.routes`. +* `routes`: Список маршрутов — это каждая зарегистрированная *операция пути*. Берутся из `app.routes`. FastAPI использует их, чтобы собрать зарегистрированные *операции пути*, включая те из подключённых роутеров. -/// info | Информация +/// tip | Технические детали -Параметр `summary` доступен в OpenAPI 3.1.0 и выше, поддерживается FastAPI версии 0.99.0 и выше. +`app.routes` — это более низкоуровневое дерево маршрутов. Оно может включать кандидаты маршрутов, которые FastAPI использует внутренне для подключённых роутеров, а не только конечные объекты `APIRoute`. + +Вы всё равно можете передать `app.routes` в `get_openapi()`. FastAPI обойдёт это дерево маршрутов, чтобы собрать фактические операции пути. + +/// + +/// note | Примечание + +Параметр `summary` доступен в OpenAPI 3.1.0 и выше, поддерживается FastAPI 0.99.0 и выше. /// diff --git a/docs/ru/docs/how-to/graphql.md b/docs/ru/docs/how-to/graphql.md index 1829a211c..880fca2a2 100644 --- a/docs/ru/docs/how-to/graphql.md +++ b/docs/ru/docs/how-to/graphql.md @@ -1,5 +1,6 @@ # GraphQL { #graphql } + Так как **FastAPI** основан на стандарте **ASGI**, очень легко интегрировать любую библиотеку **GraphQL**, также совместимую с ASGI. Вы можете комбинировать обычные *операции пути* FastAPI с GraphQL в одном приложении. diff --git a/docs/ru/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md b/docs/ru/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md index 46b4071da..e32192656 100644 --- a/docs/ru/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md +++ b/docs/ru/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md @@ -8,6 +8,8 @@ FastAPI версии 0.119.0 добавил частичную поддержк FastAPI 0.126.0 убрал поддержку Pydantic v1, при этом ещё некоторое время продолжал поддерживать `pydantic.v1`. +FastAPI 0.128.0 также убрал поддержку `pydantic.v1`, так что последние версии FastAPI требуют Pydantic v2. + /// warning | Предупреждение Команда Pydantic прекратила поддержку Pydantic v1 для последних версий Python, начиная с **Python 3.14**. @@ -54,6 +56,16 @@ Pydantic v2 включает всё из Pydantic v1 как подмодуль ` ### Поддержка FastAPI для Pydantic v1 внутри v2 { #fastapi-support-for-pydantic-v1-in-v2 } +/// warning | Предупреждение + +Эта поддержка FastAPI для моделей `pydantic.v1` была добавлена в **FastAPI 0.119.0** и удалена в **FastAPI 0.128.0**. Она задумывалась как временная помощь при миграции на Pydantic v2. + +В текущих версиях FastAPI использование модели `pydantic.v1` в вашем приложении вызовет ошибку. + +Остальная часть этого раздела описывает временную поддержку, доступную только в этих старых версиях. + +/// + Начиная с FastAPI 0.119.0, есть также частичная поддержка Pydantic v1 изнутри Pydantic v2, чтобы упростить миграцию на v2. Таким образом, вы можете обновить Pydantic до последней версии 2 и сменить импорты на подмодуль `pydantic.v1` — во многих случаях всё просто заработает. @@ -122,6 +134,12 @@ graph TB ### Мигрируйте по шагам { #migrate-in-steps } +/// warning | Предупреждение + +Постепенная миграция с использованием моделей Pydantic v1 и v2 в одном приложении, описанная ниже, работает только в **FastAPI 0.119.0 до 0.127.x**. Она была удалена в **FastAPI 0.128.0**, последние версии требуют модели **Pydantic v2**. + +/// + /// tip | Совет Сначала попробуйте `bump-pydantic`: если тесты проходят и всё работает, вы справились одной командой. ✨ diff --git a/docs/ru/docs/how-to/separate-openapi-schemas.md b/docs/ru/docs/how-to/separate-openapi-schemas.md index 8f6c83e7e..32a056fd2 100644 --- a/docs/ru/docs/how-to/separate-openapi-schemas.md +++ b/docs/ru/docs/how-to/separate-openapi-schemas.md @@ -1,6 +1,6 @@ # Разделять схемы OpenAPI для входа и выхода или нет { #separate-openapi-schemas-for-input-and-output-or-not } -При использовании **Pydantic v2** сгенерированный OpenAPI становится чуть более точным и **корректным**, чем раньше. 😎 +С момента выхода **Pydantic v2** сгенерированный OpenAPI становится чуть более точным и **корректным**, чем раньше. 😎 На самом деле, в некоторых случаях в OpenAPI будет даже **две JSON-схемы** для одной и той же Pydantic‑модели: для входа и для выхода — в зависимости от наличия **значений по умолчанию**. @@ -85,7 +85,7 @@ В таком случае вы можете отключить эту функциональность в **FastAPI** с помощью параметра `separate_input_output_schemas=False`. -/// info | Информация +/// note | Примечание Поддержка `separate_input_output_schemas` появилась в FastAPI `0.102.0`. 🤓 diff --git a/docs/ru/docs/index.md b/docs/ru/docs/index.md index 015b9769e..717d5d783 100644 --- a/docs/ru/docs/index.md +++ b/docs/ru/docs/index.md @@ -57,7 +57,7 @@ FastAPI — это современный, быстрый (высокопрои -### Ключевой-спонсор { #keystone-sponsor } +### Ключевой спонсор { #keystone-sponsor }
{% for sponsor in sponsors.keystone -%} @@ -161,7 +161,7 @@ FastAPI — это современный, быстрый (высокопрои В конце 2025 года вышел [мини-документальный фильм о FastAPI](https://www.youtube.com/watch?v=mpR8ngthqiE), вы можете посмотреть его онлайн: -FastAPI Mini Documentary +Мини-документальный фильм о FastAPI ## **Typer**, FastAPI для CLI { #typer-the-fastapi-of-clis } @@ -364,11 +364,11 @@ def update_item(item_id: int, item: Item): * Нажмите кнопку «Try it out», это позволит вам заполнить параметры и напрямую взаимодействовать с API: -![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-04-swagger-03.png) +![Взаимодействие со Swagger UI](https://fastapi.tiangolo.com/img/index/index-04-swagger-03.png) * Затем нажмите кнопку «Execute», интерфейс свяжется с вашим API, отправит параметры, получит результаты и отобразит их на экране: -![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-05-swagger-04.png) +![Взаимодействие со Swagger UI](https://fastapi.tiangolo.com/img/index/index-05-swagger-04.png) ### Обновление альтернативной документации API { #alternative-api-docs-upgrade } @@ -471,7 +471,7 @@ item: Item ...и посмотрите, как ваш редактор кода будет автоматически дополнять атрибуты и знать их типы: -![editor support](https://fastapi.tiangolo.com/img/vscode-completion.png) +![Поддержка редактора кода](https://fastapi.tiangolo.com/img/vscode-completion.png) Более полный пример с дополнительными возможностями см. в Учебник - Руководство пользователя. @@ -492,9 +492,7 @@ item: Item ### Разверните приложение (опционально) { #deploy-your-app-optional } -При желании вы можете развернуть своё приложение FastAPI в [FastAPI Cloud](https://fastapicloud.com), присоединяйтесь к списку ожидания, если ещё не сделали этого. 🚀 - -Если у вас уже есть аккаунт **FastAPI Cloud** (мы пригласили вас из списка ожидания 😉), вы можете развернуть ваше приложение одной командой. +При желании вы можете развернуть своё приложение FastAPI в [FastAPI Cloud](https://fastapicloud.com) одной командой. 🚀
@@ -510,6 +508,8 @@ Deploying to FastAPI Cloud...
+CLI автоматически определит ваше приложение FastAPI и развернёт его в облаке. Если вы не вошли в систему, откроется браузер для завершения процесса аутентификации. + Вот и всё! Теперь вы можете открыть ваше приложение по этой ссылке. ✨ #### О FastAPI Cloud { #about-fastapi-cloud } @@ -524,7 +524,7 @@ FastAPI Cloud — основной спонсор и источник финан #### Развертывание у других облачных провайдеров { #deploy-to-other-cloud-providers } -FastAPI — это open source и стандартизированный фреймворк. Вы можете развернуть приложения FastAPI у любого облачного провайдера на ваш выбор. +FastAPI — это проект с открытым исходным кодом, основанный на стандартах. Вы можете развернуть приложения FastAPI у любого облачного провайдера на ваш выбор. Следуйте руководствам вашего облачного провайдера по развертыванию приложений FastAPI. 🤓 @@ -544,7 +544,7 @@ FastAPI зависит от Pydantic и Starlette. Используется Pydantic: -* [`email-validator`](https://github.com/JoshData/python-email-validator) — для проверки адресов электронной почты. +* [`email-validator`](https://github.com/JoshData/python-email-validator) — для валидации адресов электронной почты. Используется Starlette: diff --git a/docs/ru/docs/project-generation.md b/docs/ru/docs/project-generation.md index 7a46b210d..abcc78edb 100644 --- a/docs/ru/docs/project-generation.md +++ b/docs/ru/docs/project-generation.md @@ -20,9 +20,9 @@ - 🦇 Поддержка тёмной темы. - 🐋 [Docker Compose](https://www.docker.com) для разработки и продакшн. - 🔒 Безопасное хэширование паролей по умолчанию. -- 🔑 Аутентификация по JWT‑токенам. +- 🔑 Аутентификация JWT (JSON Web Token). - 📫 Восстановление пароля по электронной почте. - ✅ Тесты с [Pytest](https://pytest.org). - 📞 [Traefik](https://traefik.io) в роли обратного прокси / балансировщика нагрузки. - 🚢 Инструкции по развёртыванию с использованием Docker Compose, включая настройку фронтенд‑прокси Traefik для автоматического получения сертификатов HTTPS. -- 🏭 CI (continuous integration) и CD (continuous deployment) на основе GitHub Actions. +- 🏭 CI (непрерывная интеграция) и CD (непрерывное развертывание) на основе GitHub Actions. diff --git a/docs/ru/docs/python-types.md b/docs/ru/docs/python-types.md index 4afdad935..4791899b1 100644 --- a/docs/ru/docs/python-types.md +++ b/docs/ru/docs/python-types.md @@ -1,20 +1,20 @@ # Введение в типы Python { #python-types-intro } -Python поддерживает необязательные «подсказки типов» (их также называют «аннотациями типов»). +Python поддерживает необязательные «аннотации типов» (также называемые «подсказками типов»). -Эти **«подсказки типов»** или аннотации — это специальный синтаксис, позволяющий объявлять тип переменной. +Эти **«аннотации типов»**, или просто аннотации, — это специальный синтаксис, позволяющий объявлять тип переменной. Объявляя типы для ваших переменных, редакторы кода и инструменты смогут лучше вас поддерживать. -Это всего лишь **краткое руководство / напоминание** о подсказках типов в Python. Оно охватывает только минимум, необходимый для их использования с **FastAPI**... что на самом деле очень мало. +Это всего лишь **краткое руководство / напоминание** об аннотациях типов в Python. Оно охватывает только минимум, необходимый для их использования с **FastAPI**... что на самом деле очень мало. -**FastAPI** целиком основан на этих подсказках типов — они дают ему множество преимуществ и выгод. +**FastAPI** целиком основан на этих аннотациях типов — они дают ему множество преимуществ и выгод. Но даже если вы никогда не используете **FastAPI**, вам будет полезно немного узнать о них. /// note | Примечание -Если вы являетесь экспертом в Python и уже знаете всё о подсказках типов, переходите к следующей главе. +Если вы являетесь экспертом в Python и уже знаете всё об аннотациях типов, переходите к следующей главе. /// @@ -76,7 +76,7 @@ John Doe Вот и всё. -Это и есть «подсказки типов»: +Это и есть «аннотации типов»: {* ../../docs_src/python_types/tutorial002_py310.py hl[1] *} @@ -90,9 +90,9 @@ John Doe Здесь мы используем двоеточия (`:`), а не знак равенства (`=`). -И добавление подсказок типов обычно не меняет поведение программы по сравнению с вариантом без них. +И добавление аннотаций типов обычно не меняет поведение программы по сравнению с вариантом без них. -Но теперь представьте, что вы снова посередине написания этой функции, только уже с подсказками типов. +Но теперь представьте, что вы снова посередине написания этой функции, только уже с аннотациями типов. В тот же момент вы пробуете вызвать автозавершение с помощью `Ctrl+Space` — и видите: @@ -104,7 +104,7 @@ John Doe ## Больше мотивации { #more-motivation } -Посмотрите на эту функцию — у неё уже есть подсказки типов: +Посмотрите на эту функцию — у неё уже есть аннотации типов: {* ../../docs_src/python_types/tutorial003_py310.py hl[1] *} @@ -118,7 +118,7 @@ John Doe ## Объявление типов { #declaring-types } -Вы только что увидели основное место, где объявляют подсказки типов — параметры функции. +Вы только что увидели основное место, где объявляют аннотации типов — параметры функции. Это также основное место, где вы будете использовать их с **FastAPI**. @@ -293,9 +293,9 @@ def some_function(data: Any): Вы увидите намного больше всего этого на практике в [Учебник - Руководство пользователя](tutorial/index.md). -## Подсказки типов с аннотациями метаданных { #type-hints-with-metadata-annotations } +## Аннотации типов с аннотациями метаданных { #type-hints-with-metadata-annotations } -В Python также есть возможность добавлять **дополнительные метаданные** к подсказкам типов с помощью `Annotated`. +В Python также есть возможность добавлять **дополнительные метаданные** к аннотациям типов с помощью `Annotated`. Вы можете импортировать `Annotated` из `typing`. @@ -321,16 +321,16 @@ def some_function(data: Any): ## Аннотации типов в **FastAPI** { #type-hints-in-fastapi } -**FastAPI** использует эти подсказки типов для выполнения нескольких задач. +**FastAPI** использует эти аннотации типов для выполнения нескольких задач. -С **FastAPI** вы объявляете параметры с подсказками типов и получаете: +С **FastAPI** вы объявляете параметры с аннотациями типов и получаете: * **Поддержку редактора кода**. * **Проверки типов**. ...и **FastAPI** использует эти же объявления для: -* **Определения требований**: из path-параметров пути запроса, query-параметров, HTTP-заголовков, тел запросов, зависимостей и т.д. +* **Определения требований**: из path-параметров HTTP-запроса, query-параметров, HTTP-заголовков, тел запросов, зависимостей и т.д. * **Преобразования данных**: из HTTP-запроса к требуемому типу. * **Валидации данных**: приходящих с каждого HTTP-запроса: * Генерации **автоматических ошибок**, возвращаемых клиенту, когда данные некорректны. diff --git a/docs/ru/docs/tutorial/bigger-applications.md b/docs/ru/docs/tutorial/bigger-applications.md index 453851d34..038777b0c 100644 --- a/docs/ru/docs/tutorial/bigger-applications.md +++ b/docs/ru/docs/tutorial/bigger-applications.md @@ -17,16 +17,16 @@ ``` . ├── app -│   ├── __init__.py -│   ├── main.py -│   ├── dependencies.py -│   └── routers -│   │ ├── __init__.py -│   │ ├── items.py -│   │ └── users.py -│   └── internal -│   ├── __init__.py -│   └── admin.py +│ ├── __init__.py +│ ├── main.py +│ ├── dependencies.py +│ └── routers +│ │ ├── __init__.py +│ │ ├── items.py +│ │ └── users.py +│ └── internal +│ ├── __init__.py +│ └── admin.py ``` /// tip | Подсказка @@ -58,16 +58,16 @@ from app.routers import items ```bash . -├── app # "app" пакет +├── app # "app" — Python-пакет │   ├── __init__.py # этот файл превращает "app" в "Python-пакет" │   ├── main.py # модуль "main", напр.: import app.main │   ├── dependencies.py # модуль "dependencies", напр.: import app.dependencies -│   └── routers # подпакет "routers" -│   │ ├── __init__.py # превращает "routers" в подпакет +│   └── routers # "routers" — "Python-подпакет" +│   │ ├── __init__.py # превращает "routers" в "Python-подпакет" │   │ ├── items.py # подмодуль "items", напр.: import app.routers.items │   │ └── users.py # подмодуль "users", напр.: import app.routers.users -│   └── internal # подпакет "internal" -│   ├── __init__.py # превращает "internal" в подпакет +│   └── internal # "internal" — "Python-подпакет" +│   ├── __init__.py # превращает "internal" в "Python-подпакет" │   └── admin.py # подмодуль "admin", напр.: import app.internal.admin ``` @@ -121,7 +121,7 @@ from app.routers import items /// tip | Подсказка -Для простоты мы воспользовались выдуманным заголовком. +Для простоты мы воспользовались выдуманным HTTP-заголовком. В реальных случаях для получения наилучших результатов используйте интегрированные [утилиты безопасности](security/index.md). @@ -163,9 +163,9 @@ async def read_item(item_id: str): В нашем случае префиксом является `/items`. -Мы также можем добавить список `tags` и дополнительные `responses`, которые будут применяться ко всем *операциям пути*, включённым в этот маршрутизатор. +Мы также можем добавить список `tags` и дополнительные `responses`, которые будут применяться ко всем *операциям пути*, включённым в этот роутер. -И ещё мы можем добавить список `dependencies`, которые будут добавлены ко всем *операциям пути* в маршрутизаторе и будут выполняться/разрешаться для каждого HTTP-запроса к ним. +И ещё мы можем добавить список `dependencies`, которые будут добавлены ко всем *операциям пути* в роутере и будут выполняться/разрешаться для каждого HTTP-запроса к ним. /// tip | Подсказка @@ -185,7 +185,7 @@ async def read_item(item_id: str): * Все они будут включать предопределённые `responses`. * Все эти *операции пути* будут иметь список `dependencies`, вычисляемых/выполняемых перед ними. * Если вы также объявите зависимости в конкретной *операции пути*, **они тоже будут выполнены**. - * Сначала выполняются зависимости маршрутизатора, затем [`dependencies` в декораторе](dependencies/dependencies-in-path-operation-decorators.md), и затем обычные параметрические зависимости. + * Сначала выполняются зависимости роутера, затем [`dependencies` в декораторе](dependencies/dependencies-in-path-operation-decorators.md), и затем обычные параметрические зависимости. * Вы также можете добавить [`Security`-зависимости с `scopes`](../advanced/security/oauth2-scopes.md). /// tip | Подсказка @@ -263,7 +263,7 @@ from ...dependencies import get_token_header то это бы означало: -* Начать в том же пакете, в котором находится этот модуль (файл `app/routers/items.py`) расположен в (каталоге `app/routers/`)... +* Начать в том же пакете, в котором находится этот модуль (файл `app/routers/items.py`) (каталог `app/routers/`)... * перейти в родительский пакет (каталог `app/`)... * затем перейти в родительский пакет этого пакета (родительского пакета нет, `app` — верхний уровень 😱)... * и там найти модуль `dependencies` (файл `app/dependencies.py`)... @@ -285,7 +285,7 @@ from ...dependencies import get_token_header Эта последняя операция пути будет иметь комбинацию тегов: `["items", "custom"]`. -И в документации у неё будут оба ответа: один для `404` и один для `403`. +И в документации у неё будут оба HTTP-ответа: один для `404` и один для `403`. /// @@ -325,7 +325,7 @@ from .routers import items, users означает: -* Начать в том же пакете, в котором находится этот модуль (файл `app/main.py`) расположен в (каталоге `app/`)... +* Начать в том же пакете, в котором находится этот модуль (файл `app/main.py`) (каталог `app/`)... * найти подпакет `routers` (каталог `app/routers/`)... * и импортировать из него подмодули `items` (файл `app/routers/items.py`) и `users` (файл `app/routers/users.py`)... @@ -392,21 +392,21 @@ from .routers.users import router С помощью `app.include_router()` мы можем добавить каждый `APIRouter` в основное приложение `FastAPI`. -Он включит все маршруты этого маршрутизатора как часть приложения. +Он включит все маршруты этого роутера как часть приложения. /// note | Технические детали -Фактически, внутри он создаст *операцию пути* для каждой *операции пути*, объявленной в `APIRouter`. +FastAPI сохраняет исходный `APIRouter` и его `APIRoute` активными, когда роутер включается в основное приложение. -Так что под капотом всё будет работать так, как будто всё было одним приложением. +Это означает, что пользовательские подклассы `APIRouter` и `APIRoute` по-прежнему участвуют после подключения роутера. /// /// tip | Подсказка -При подключении маршрутизаторов не нужно беспокоиться о производительности. +При подключении роутеров не нужно беспокоиться о производительности. -Это займёт микросекунды и произойдёт только при старте. +Это сделано максимально лёгким и не добавляет накладных расходов на каждый запрос. Так что это не повлияет на производительность. ⚡ @@ -435,7 +435,7 @@ from .routers.users import router * Префикс `/admin`. * Тег `admin`. * Зависимость `get_token_header`. -* Ответ `418`. 🍵 +* HTTP-ответ `418`. 🍵 Но это повлияет только на этот `APIRouter` в нашем приложении, а не на любой другой код, который его использует. @@ -459,9 +459,9 @@ from .routers.users import router `APIRouter` не «монтируются», они не изолированы от остального приложения. -Это потому, что мы хотим включить их *операции пути* в OpenAPI-схему и пользовательские интерфейсы. +Это потому, что мы хотим включить их *операции пути* в схему OpenAPI и пользовательские интерфейсы. -Так как мы не можем просто изолировать их и «смонтировать» независимо от остального, *операции пути* «клонируются» (пересоздаются), а не включаются напрямую. +FastAPI сохраняет исходные роутеры и операции пути активными и комбинирует префиксы роутеров, зависимости, теги, HTTP-ответы и другие метаданные при обработке HTTP-запросов и генерации OpenAPI. /// @@ -516,15 +516,15 @@ $ fastapi dev -## Подключение одного и того же маршрутизатора несколько раз с разными `prefix` { #include-the-same-router-multiple-times-with-different-prefix } +## Подключение одного и того же роутера несколько раз с разными `prefix` { #include-the-same-router-multiple-times-with-different-prefix } -Вы можете использовать `.include_router()` несколько раз с *одним и тем же* маршрутизатором, используя разные префиксы. +Вы можете использовать `.include_router()` несколько раз с *одним и тем же* роутером, используя разные префиксы. Это может быть полезно, например, чтобы предоставить доступ к одному и тому же API с разными префиксами, например `/api/v1` и `/api/latest`. Это продвинутое использование, которое вам может и не понадобиться, но оно есть на случай, если понадобится. -## Подключение `APIRouter` в другой `APIRouter` { #include-an-apirouter-in-another } +## Подключение `APIRouter` в другой `APIRouter` { #include-an-apirouter-in-another } Точно так же, как вы можете подключить `APIRouter` к приложению `FastAPI`, вы можете подключить `APIRouter` к другому `APIRouter`, используя: @@ -532,4 +532,16 @@ $ fastapi dev router.include_router(other_router) ``` -Убедитесь, что вы сделали это до подключения `router` к приложению `FastAPI`, чтобы *операции пути* из `other_router` также были подключены. +Вы можете сделать это до или после подключения `router` к приложению `FastAPI`. FastAPI всё равно включит *операции пути* из `other_router` в маршрутизацию и OpenAPI. + +То же относится к *операциям пути*, добавленным позже в роутеры. Они также будут видны через более раннее включение. + +/// warning | Технические детали + +Избегайте прямой мутации `router.routes` после включения роутера. FastAPI рассматривает включение роутера как «живое», поэтому исходный роутер и его маршруты остаются частью маршрутизации и генерации OpenAPI. + +Используйте документированные API, такие как декораторы операций пути и `.include_router()`, чтобы добавлять маршруты и роутеры. + +Считайте `router.routes` низкоуровневым деревом маршрутов, которое может содержать определения маршрутов и включённые роутеры, и избегайте воспринимать его как плоский список итоговых операций пути. + +/// diff --git a/docs/ru/docs/tutorial/body-multiple-params.md b/docs/ru/docs/tutorial/body-multiple-params.md index ddd9c6fdd..cd9c56012 100644 --- a/docs/ru/docs/tutorial/body-multiple-params.md +++ b/docs/ru/docs/tutorial/body-multiple-params.md @@ -108,7 +108,7 @@ q: str | None = None {* ../../docs_src/body_multiple_params/tutorial004_an_py310.py hl[28] *} -/// info | Информация +/// note | Заметка `Body` также имеет все те же дополнительные параметры валидации и метаданных, как у `Query`, `Path` и других, которые вы увидите позже. @@ -123,7 +123,7 @@ q: str | None = None Но если вы хотите чтобы он ожидал JSON с ключом `item` с содержимым модели внутри, также как это происходит при объявлении дополнительных body-параметров, вы можете использовать специальный параметр `embed` у типа `Body`: ```Python -item: Item = Body(embed=True) +item: Annotated[Item, Body(embed=True)] ``` так же, как в этом примере: diff --git a/docs/ru/docs/tutorial/body-nested-models.md b/docs/ru/docs/tutorial/body-nested-models.md index fab025dbc..5dc06d28a 100644 --- a/docs/ru/docs/tutorial/body-nested-models.md +++ b/docs/ru/docs/tutorial/body-nested-models.md @@ -12,11 +12,12 @@ ## Поля-списки с параметром типа { #list-fields-with-type-parameter } -В Python есть специальный способ объявлять списки с внутренними типами, или «параметрами типа»: +Но в Python есть специальный способ объявлять списки с внутренними типами, или «параметрами типа»: ### Объявите `list` с параметром типа { #declare-a-list-with-a-type-parameter } -Для объявления типов, у которых есть параметры типа (внутренние типы), таких как `list`, `dict`, `tuple`, передайте внутренний(ие) тип(ы) как «параметры типа», используя квадратные скобки: `[` и `]` +Для объявления типов, у которых есть параметры типа (внутренние типы), таких как `list`, `dict`, `tuple`, +передайте внутренний(ие) тип(ы) как «параметры типа», используя квадратные скобки: `[` и `]` ```Python my_list: list[str] @@ -109,7 +110,7 @@ my_list: list[str] {* ../../docs_src/body_nested_models/tutorial006_py310.py hl[18] *} -Такая реализация будет ожидать (конвертировать, валидировать, документировать и т.д.) JSON-содержимое в следующем формате: +Такая реализация будет ожидать (конвертировать, валидировать, документировать и т.д.) JSON-тело запроса в следующем формате: ```JSON hl_lines="11" { @@ -135,7 +136,7 @@ my_list: list[str] } ``` -/// info | Информация +/// note | Примечание Заметьте, что теперь у ключа `images` есть список объектов изображений. @@ -147,15 +148,15 @@ my_list: list[str] {* ../../docs_src/body_nested_models/tutorial007_py310.py hl[7,12,18,21,25] *} -/// info | Информация +/// note | Примечание Заметьте, что у объекта `Offer` есть список объектов `Item`, которые, в свою очередь, могут содержать необязательный список объектов `Image` /// -## Тела с чистыми списками элементов { #bodies-of-pure-lists } +## Тела запросов с чистыми списками элементов { #bodies-of-pure-lists } -Если верхний уровень значения тела JSON-объекта представляет собой JSON `array` (в Python — `list`), вы можете объявить тип в параметре функции, так же как в моделях Pydantic: +Если верхний уровень значения JSON-тела запроса представляет собой JSON `array` (в Python — `list`), вы можете объявить тип в параметре функции, так же как в моделях Pydantic: ```Python images: list[Image] @@ -211,7 +212,7 @@ images: list[Image] С помощью **FastAPI** вы получаете максимальную гибкость, предоставляемую моделями Pydantic, сохраняя при этом простоту, краткость и элегантность вашего кода. -И дополнительно вы получаете: +Но со всеми преимуществами: * Поддержку редактора кода (автозавершение доступно везде!) * Преобразование данных (также известно как парсинг / сериализация) diff --git a/docs/ru/docs/tutorial/body.md b/docs/ru/docs/tutorial/body.md index 8a67c8f51..f1b76cba3 100644 --- a/docs/ru/docs/tutorial/body.md +++ b/docs/ru/docs/tutorial/body.md @@ -8,7 +8,7 @@ Чтобы объявить тело **запроса**, используйте модели [Pydantic](https://docs.pydantic.dev/), со всей их мощью и преимуществами. -/// info | Информация +/// note | Заметка Чтобы отправить данные, используйте один из методов: `POST` (чаще всего), `PUT`, `DELETE` или `PATCH`. @@ -70,7 +70,7 @@ * Считает тело запроса как JSON. * Приведёт данные к соответствующим типам (если потребуется). * Проведёт валидацию данных. - * Если данные некорректны, вернёт понятную и наглядную ошибку, указывающую, где именно и что было некорректно. + * Если данные некорректны, вернёт понятную и наглядную ошибку, указывающую, где именно and что было некорректно. * Передаст полученные данные в параметр `item`. * Поскольку внутри функции вы объявили его с типом `Item`, у вас будет поддержка со стороны редактора кода (автозавершение и т.п.) для всех атрибутов и их типов. * Сгенерирует определения [JSON Schema](https://json-schema.org) для вашей модели; вы можете использовать их и в других местах, если это имеет смысл для вашего проекта. diff --git a/docs/ru/docs/tutorial/cookie-param-models.md b/docs/ru/docs/tutorial/cookie-param-models.md index 9b34cf030..2b9681433 100644 --- a/docs/ru/docs/tutorial/cookie-param-models.md +++ b/docs/ru/docs/tutorial/cookie-param-models.md @@ -32,7 +32,7 @@
-/// info | Дополнительная информация +/// note | Заметка Имейте в виду, что, поскольку **браузеры обрабатывают cookies** особым образом и под капотом, они **не** позволят **JavaScript** легко получить доступ к ним. diff --git a/docs/ru/docs/tutorial/cookie-params.md b/docs/ru/docs/tutorial/cookie-params.md index 8dad3873e..f801c4ac4 100644 --- a/docs/ru/docs/tutorial/cookie-params.md +++ b/docs/ru/docs/tutorial/cookie-params.md @@ -24,13 +24,13 @@ /// -/// info | Дополнительная информация +/// note | Примечание Для объявления cookies, вам нужно использовать `Cookie`, иначе параметры будут интерпретированы как параметры запроса. /// -/// info | Дополнительная информация +/// note | Примечание Имейте в виду, что, поскольку **браузеры обрабатывают cookies** особым образом и «за кулисами», они **не** позволяют **JavaScript** просто так получать к ним доступ. diff --git a/docs/ru/docs/tutorial/debugging.md b/docs/ru/docs/tutorial/debugging.md index 330055be4..5a5808579 100644 --- a/docs/ru/docs/tutorial/debugging.md +++ b/docs/ru/docs/tutorial/debugging.md @@ -1,10 +1,10 @@ # Отладка { #debugging } -Вы можете подключить отладчик в своем редакторе, например, в Visual Studio Code или PyCharm. +Вы можете подключить отладчик в своем редакторе кода, например, в Visual Studio Code или PyCharm. ## Вызов `uvicorn` { #call-uvicorn } -В вашем FastAPI приложении, импортируйте и вызовите `uvicorn` напрямую: +В вашем FastAPI приложении, импортируйте и запустите `uvicorn` напрямую: {* ../../docs_src/debugging/tutorial001_py310.py hl[1,15] *} @@ -62,7 +62,7 @@ from myapp import app # Еще немного кода ``` -то автоматическая создаваемая внутри файла `myapp.py` переменная `__name__` будет иметь значение отличающееся от `"__main__"`. +то автоматически создаваемая внутри файла `myapp.py` переменная `__name__` будет иметь значение, отличающееся от `"__main__"`. Следовательно, строка: @@ -72,7 +72,7 @@ from myapp import app не будет выполнена. -/// info | Информация +/// note | Примечание Для получения дополнительной информации, ознакомьтесь с [официальной документацией Python](https://docs.python.org/3/library/__main__.html). @@ -80,7 +80,7 @@ from myapp import app ## Запуск вашего кода с помощью отладчика { #run-your-code-with-your-debugger } -Так как вы запускаете сервер Uvicorn непосредственно из вашего кода, вы можете вызвать Python программу (ваше FastAPI приложение) напрямую из отладчика. +Так как вы запускаете сервер Uvicorn непосредственно из вашего кода, вы можете запустить Python программу (ваше FastAPI приложение) напрямую из отладчика. --- diff --git a/docs/ru/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md b/docs/ru/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md index b4b7ce631..2193343e6 100644 --- a/docs/ru/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md +++ b/docs/ru/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md @@ -28,7 +28,7 @@ /// -/// info | Примечание +/// note | Примечание В этом примере мы используем выдуманные пользовательские HTTP-заголовки `X-Key` и `X-Token`. diff --git a/docs/ru/docs/tutorial/dependencies/dependencies-with-yield.md b/docs/ru/docs/tutorial/dependencies/dependencies-with-yield.md index 04c2c2da4..71e782c0b 100644 --- a/docs/ru/docs/tutorial/dependencies/dependencies-with-yield.md +++ b/docs/ru/docs/tutorial/dependencies/dependencies-with-yield.md @@ -123,7 +123,7 @@ FastAPI поддерживает зависимости, которые выпо ### Всегда делайте `raise` в зависимостях с `yield` и `except` { #always-raise-in-dependencies-with-yield-and-except } -Если вы ловите исключение в зависимости с `yield`, то, если вы не вызываете другой `HTTPException` или что-то подобное, вам следует повторно вызвать исходное исключение. +Если вы ловите исключение в зависимости с `yield`, то, если вы не вызываете другой `HTTPException` или что-то подобное, **вам следует повторно вызвать исходное исключение**. Вы можете повторно вызвать то же самое исключение с помощью `raise`: @@ -170,7 +170,7 @@ participant tasks as Background tasks end ``` -/// info | Дополнительная информация +/// note | Примечание Клиенту будет отправлен только **один ответ**. Это может быть один из ответов об ошибке или ответ от *операции пути*. @@ -219,7 +219,7 @@ participant operation as Функция-обработчик пути Note over dep_req: Выполнить код до yield dep_req ->> dep_func: Передать значение Note over dep_func: Выполнить код до yield - dep_func ->> operation: Выполнить функцию-обработчик пути + dep_func ->> operation: Выполнить функцию-обработчика пути operation ->> dep_func: Выход из функции-обработчика пути Note over dep_func: Выполнить код после yield Note over dep_func: ✅ Зависимость закрыта @@ -234,6 +234,7 @@ participant operation as Функция-обработчик пути Зависимости с `yield` со временем эволюционировали, чтобы покрыть разные сценарии и исправить некоторые проблемы. Если вы хотите посмотреть, что менялось в разных версиях FastAPI, вы можете прочитать об этом подробнее в продвинутом руководстве: [Продвинутые зависимости — зависимости с `yield`, `HTTPException`, `except` и фоновыми задачами](../../advanced/advanced-dependencies.md#dependencies-with-yield-httpexception-except-and-background-tasks). + ## Контекстные менеджеры { #context-managers } ### Что такое «контекстные менеджеры» { #what-are-context-managers } diff --git a/docs/ru/docs/tutorial/dependencies/index.md b/docs/ru/docs/tutorial/dependencies/index.md index 4aed03554..6efd023e2 100644 --- a/docs/ru/docs/tutorial/dependencies/index.md +++ b/docs/ru/docs/tutorial/dependencies/index.md @@ -51,7 +51,7 @@ А затем просто возвращает `dict`, содержащий эти значения. -/// info | Информация +/// note | Примечание FastAPI добавил поддержку `Annotated` (и начал рекомендовать его использование) в версии 0.95.0. @@ -106,7 +106,7 @@ common_parameters --> read_users Таким образом, вы пишете общий код один раз, а **FastAPI** позаботится о его вызове для ваших *операций пути*. -/// check | Проверка +/// tip | Подсказка Обратите внимание, что вам не нужно создавать специальный класс и передавать его куда-то в **FastAPI**, чтобы «зарегистрировать» его или что-то подобное. diff --git a/docs/ru/docs/tutorial/dependencies/sub-dependencies.md b/docs/ru/docs/tutorial/dependencies/sub-dependencies.md index 3c71defd8..b36adf486 100644 --- a/docs/ru/docs/tutorial/dependencies/sub-dependencies.md +++ b/docs/ru/docs/tutorial/dependencies/sub-dependencies.md @@ -6,9 +6,9 @@ **FastAPI** сам займётся их управлением. -## Первая зависимость { #first-dependency-dependable } +## Первая «зависимость» { #first-dependency-dependable } -Можно создать первую зависимость следующим образом: +Можно создать первую «зависимость» следующим образом: {* ../../docs_src/dependencies/tutorial005_an_py310.py hl[8:9] *} @@ -35,7 +35,7 @@ {* ../../docs_src/dependencies/tutorial005_an_py310.py hl[23] *} -/// info | Дополнительная информация +/// note | Примечание Обратите внимание, что мы объявляем только одну зависимость в *функции операции пути* - `query_or_cookie_extractor`. diff --git a/docs/ru/docs/tutorial/extra-data-types.md b/docs/ru/docs/tutorial/extra-data-types.md index 062c19574..d05a00eca 100644 --- a/docs/ru/docs/tutorial/extra-data-types.md +++ b/docs/ru/docs/tutorial/extra-data-types.md @@ -12,7 +12,7 @@ При этом у вас останутся те же возможности, что и до сих пор: * Отличная поддержка редактора кода. -* Преобразование данных из входящих запросов. +* Преобразование данных из входящих HTTP-запросов. * Преобразование данных для ответа. * Валидация данных. * Автоматическая аннотация и документация. @@ -23,32 +23,32 @@ * `UUID`: * Стандартный "Универсальный уникальный идентификатор", используемый в качестве идентификатора во многих базах данных и системах. - * В запросах и ответах будет представлен как `str`. + * В HTTP-запросах и HTTP-ответах будет представлен как `str`. * `datetime.datetime`: * Встроенный в Python `datetime.datetime`. - * В запросах и ответах будет представлен как `str` в формате ISO 8601, например: `2008-09-15T15:53:00+05:00`. + * В HTTP-запросах и HTTP-ответах будет представлен как `str` в формате ISO 8601, например: `2008-09-15T15:53:00+05:00`. * `datetime.date`: * Встроенный в Python `datetime.date`. - * В запросах и ответах будет представлен как `str` в формате ISO 8601, например: `2008-09-15`. + * В HTTP-запросах и HTTP-ответах будет представлен как `str` в формате ISO 8601, например: `2008-09-15`. * `datetime.time`: * Встроенный в Python `datetime.time`. - * В запросах и ответах будет представлен как `str` в формате ISO 8601, например: `14:23:55.003`. + * В HTTP-запросах и HTTP-ответах будет представлен как `str` в формате ISO 8601, например: `14:23:55.003`. * `datetime.timedelta`: * Встроенный в Python `datetime.timedelta`. - * В запросах и ответах будет представлен в виде общего количества секунд типа `float`. + * В HTTP-запросах и HTTP-ответах будет представлен в виде общего количества секунд типа `float`. * Pydantic также позволяет представить его как "Кодировку разницы во времени ISO 8601", [см. документацию для получения дополнительной информации](https://docs.pydantic.dev/latest/concepts/serialization/#custom-serializers). * `frozenset`: - * В запросах и ответах обрабатывается так же, как и `set`: - * В запросах будет прочитан список, исключены дубликаты и преобразован в `set`. - * В ответах `set` будет преобразован в `list`. + * В HTTP-запросах и HTTP-ответах обрабатывается так же, как и `set`: + * В HTTP-запросах будет прочитан список, исключены дубликаты и преобразован в `set`. + * В HTTP-ответах `set` будет преобразован в `list`. * В сгенерированной схеме будет указано, что значения `set` уникальны (с помощью JSON-схемы `uniqueItems`). * `bytes`: * Встроенный в Python `bytes`. - * В запросах и ответах будет рассматриваться как `str`. - * В сгенерированной схеме будет указано, что это `str` в формате `binary`. + * В HTTP-запросах и HTTP-ответах будет рассматриваться как `str`. + * В сгенерированной схеме будет указано, что это `str` в "формате" `binary`. * `Decimal`: * Встроенный в Python `Decimal`. - * В запросах и ответах обрабатывается так же, как и `float`. + * В HTTP-запросах и HTTP-ответах обрабатывается так же, как и `float`. * Вы можете проверить все допустимые типы данных Pydantic здесь: [Типы данных Pydantic](https://docs.pydantic.dev/latest/usage/types/types/). ## Пример { #example } diff --git a/docs/ru/docs/tutorial/extra-models.md b/docs/ru/docs/tutorial/extra-models.md index becb76bc3..cec61ed5d 100644 --- a/docs/ru/docs/tutorial/extra-models.md +++ b/docs/ru/docs/tutorial/extra-models.md @@ -208,4 +208,4 @@ some_variable: PlaneItem | CarItem Используйте несколько Pydantic-моделей и свободно применяйте наследование для каждого случая. -Вам не обязательно иметь единственную модель данных для каждой сущности, если эта сущность должна иметь возможность быть в разных "состояниях". Как в случае с "сущностью" пользователя, у которого есть состояние, включающее `password`, `password_hash` и отсутствие пароля. +Вам не обязательно иметь единственную модель данных для каждой сущности, если эта сущность должна иметь возможность быть в разных "состояниях". **Пользователь** — пример такой "сущности", с состояниями, которые включают `password`, `password_hash` или отсутствие пароля. diff --git a/docs/ru/docs/tutorial/first-steps.md b/docs/ru/docs/tutorial/first-steps.md index 7216d4cb7..8841a9004 100644 --- a/docs/ru/docs/tutorial/first-steps.md +++ b/docs/ru/docs/tutorial/first-steps.md @@ -180,7 +180,7 @@ entrypoint = "backend.main:app" from backend.main import app ``` -### `fastapi dev` с путём { #fastapi-dev-with-path } +### `fastapi dev` с путём или с опцией CLI `--entrypoint` { #fastapi-dev-with-path-or-with-entrypoint-cli-option } Вы также можете передать путь к файлу в команду `fastapi dev`, и она попытается определить объект приложения FastAPI для использования: @@ -188,29 +188,19 @@ from backend.main import app $ fastapi dev main.py ``` -Но в этом случае вам придётся каждый раз помнить о передаче корректного пути при вызове команды `fastapi`. - -Кроме того, другие инструменты могут его не найти, например [Расширение VS Code](../editor-support.md) или [FastAPI Cloud](https://fastapicloud.com), поэтому рекомендуется использовать `entrypoint` в `pyproject.toml`. - -### Разверните приложение (необязательно) { #deploy-your-app-optional } - -При желании вы можете развернуть своё приложение FastAPI в [FastAPI Cloud](https://fastapicloud.com), перейдите и присоединитесь к списку ожидания, если ещё не сделали этого. 🚀 - -Если у вас уже есть аккаунт **FastAPI Cloud** (мы пригласили вас из списка ожидания 😉), вы можете развернуть приложение одной командой. - -Перед развертыванием убедитесь, что вы вошли в систему: - -
+Или вы можете передать опцию `--entrypoint` команде `fastapi dev`: ```console -$ fastapi login - -You are logged in to FastAPI Cloud 🚀 +$ fastapi dev --entrypoint main:app ``` -
+Но в этом случае вам придётся каждый раз помнить о передаче корректного пути/entrypoint при вызове команды `fastapi`. + +Кроме того, другие инструменты могут его не найти, например [Расширение VS Code](../editor-support.md) или [FastAPI Cloud](https://fastapicloud.com), поэтому рекомендуется использовать `entrypoint` в `pyproject.toml`. -Затем разверните приложение: +### Разверните приложение (необязательно) { #deploy-your-app-optional } + +При желании вы можете развернуть своё приложение FastAPI в [FastAPI Cloud](https://fastapicloud.com) одной командой. 🚀
@@ -226,6 +216,8 @@ Deploying to FastAPI Cloud...
+CLI автоматически определит ваше приложение FastAPI и развернёт его в облаке. Если вы не вошли в систему, откроется браузер для завершения процесса аутентификации. + Готово! Теперь вы можете открыть своё приложение по этому URL. ✨ ## Рассмотрим поэтапно { #recap-step-by-step } @@ -252,9 +244,9 @@ Deploying to FastAPI Cloud... Это будет основная точка взаимодействия для создания всего вашего API. -### Шаг 3: создайте *операцию пути (path operation)* { #step-3-create-a-path-operation } +### Шаг 3: создайте *операцию пути* { #step-3-create-a-path-operation } -#### Путь (path) { #path } +#### Путь { #path } Здесь «путь» — это последняя часть URL, начиная с первого символа `/`. @@ -270,7 +262,7 @@ https://example.com/items/foo /items/foo ``` -/// info | Информация +/// note | Примечание «Путь» также часто называют «эндпоинт» или «маршрут». @@ -278,7 +270,7 @@ https://example.com/items/foo При создании API «путь» — это основной способ разделения «задач» и «ресурсов». -#### Операция (operation) { #operation } +#### Операция { #operation } «Операция» здесь — это один из HTTP-«методов». @@ -311,18 +303,18 @@ https://example.com/items/foo Таким образом, в OpenAPI каждый HTTP-метод называется «операцией». -Мы тоже будем называть их «операциями». +Мы тоже будем называть их «**операциями**». -#### Определите *декоратор операции пути (path operation decorator)* { #define-a-path-operation-decorator } +#### Определите *декоратор операции пути* { #define-a-path-operation-decorator } {* ../../docs_src/first_steps/tutorial001_py310.py hl[6] *} -`@app.get("/")` сообщает **FastAPI**, что функция прямо под ним отвечает за обработку запросов, поступающих: +`@app.get("/")` сообщает **FastAPI**, что функция прямо под ним отвечает за обработку HTTP-запросов, поступающих: * по пути `/` -* с использованием get операции +* с использованием операции get -/// info | Информация о `@decorator` +/// note | Информация о `@decorator` Синтаксис `@something` в Python называется «декоратор». @@ -361,9 +353,9 @@ https://example.com/items/foo /// -### Шаг 4: определите **функцию операции пути** { #step-4-define-the-path-operation-function } +### Шаг 4: определите **функцию-обработчик пути** { #step-4-define-the-path-operation-function } -Вот наша «функция операции пути»: +Вот наша «**функция-обработчик пути**»: * **путь**: `/`. * **операция**: `get`. @@ -373,7 +365,7 @@ https://example.com/items/foo Это функция на Python. -**FastAPI** будет вызывать её каждый раз, когда получает запрос к URL «`/`» с операцией `GET`. +**FastAPI** будет вызывать её каждый раз, когда получает HTTP-запрос к URL «`/`» с операцией `GET`. В данном случае это асинхронная (`async`) функция. @@ -411,7 +403,7 @@ https://example.com/items/foo Он переносит тот же **опыт разработчика** при создании приложений с FastAPI на их **развертывание** в облаке. 🎉 -FastAPI Cloud — основной спонсор и источник финансирования для open-source проектов «FastAPI и друзья». ✨ +FastAPI Cloud — основной спонсор и источник финансирования для open-source проектов *FastAPI и друзья*. ✨ #### Развертывание у других облачных провайдеров { #deploy-to-other-cloud-providers } @@ -424,6 +416,6 @@ FastAPI — open-source и основан на стандартах. Вы мож * Импортируйте `FastAPI`. * Создайте экземпляр `app`. * Напишите **декоратор операции пути**, например `@app.get("/")`. -* Определите **функцию операции пути**; например, `def root(): ...`. +* Определите **функцию-обработчик пути**; например, `def root(): ...`. * Запустите сервер разработки командой `fastapi dev`. * При желании разверните приложение командой `fastapi deploy`. diff --git a/docs/ru/docs/tutorial/frontend.md b/docs/ru/docs/tutorial/frontend.md new file mode 100644 index 000000000..3b3e43809 --- /dev/null +++ b/docs/ru/docs/tutorial/frontend.md @@ -0,0 +1,133 @@ +# Фронтенд { #frontend } + +Вы можете «отдавать» статические фронтенд-приложения с помощью `app.frontend()` (или `router.frontend()`). + +Это полезно для фронтенд-инструментов, которые генерируют статические файлы, таких как React с Vite, TanStack Router, Astro, Vue, Svelte, Angular, Solid и других. + +С такими инструментами обычно есть этап сборки фронтенда с помощью команды вроде: + +```bash +npm run build +``` + +Она сгенерирует директорию вроде `./dist/` с файлами вашего фронтенда. + +Вы можете использовать `app.frontend()`, чтобы «отдавать» эту директорию, следуя соглашениям, которые требуются этим фронтенд-фреймворкам. + +**FastAPI** сначала проверяет *операции пути*. Файлы фронтенда проверяются только если не совпал ни один обычный маршрут, поэтому ваш API не будет затронут. + +## Отдача фронтенда { #serve-a-frontend } + +После сборки фронтенда, например с помощью `npm run build`, поместите сгенерированные файлы в директорию, например `dist`. + +Структура вашего проекта может выглядеть так: + +```text +. +├── pyproject.toml +├── app +│ ├── __init__.py +│ └── main.py +└── dist + ├── index.html + └── assets + └── app.js +``` + +Затем «отдавайте» её с помощью `app.frontend()`: + +{* ../../docs_src/frontend/tutorial001_py310.py hl[5] *} + +При этом запрос к `/assets/app.js` может отдать `dist/assets/app.js`. + +Если у вас также есть *операция пути* **FastAPI**, приоритет будет у *операции пути*. + +## Маршрутизация на стороне клиента { #client-side-routing } + +Многие фронтенд-приложения, включая **single-page apps** (SPA), используют маршрутизацию на стороне клиента. Путь вроде `/dashboard/settings` может не быть реальным файлом, но фреймворк возьмёт на себя его обработку. + +Поэтому, если обратиться к этому URL напрямую (а не перейти к нему через приложение), backend должен отдать фронтенд-приложение из `index.html`, чтобы затем фронтенд-фреймворк мог обработать маршрутизацию на стороне клиента. + +Для этого используйте `fallback="index.html"`: + +{* ../../docs_src/frontend/tutorial002_py310.py hl[5] *} + +**FastAPI** использует этот fallback только для запросов `GET` и `HEAD`, которые похожи на навигацию в браузере. Отсутствующие файлы, такие как JavaScript, CSS и изображения, по-прежнему возвращают `404`. + +Запросы с другими методами, например `POST` или `PUT`, к путям, которые совпадают только с fallback фронтенда, также возвращают `404`. Обычные *операции пути* **FastAPI** по-прежнему имеют более высокий приоритет, чем маршруты фронтенда. + +/// tip | Совет + +По умолчанию `fallback` имеет значение `fallback="auto"`. В большинстве случаев вам не нужно будет указывать `fallback`. Подробности ниже. + +/// + +Именно такое поведение нужно для многих фронтенд-приложений, которые используют маршрутизацию на стороне клиента, например React с TanStack Router, Vue, Angular, SvelteKit или Solid. + +## Кастомная страница 404 { #custom-404-page } + +Вы также можете отдавать статическую страницу `404.html` для отсутствующих путей фронтенда: + +{* ../../docs_src/frontend/tutorial003_py310.py hl[5] *} + +Этот HTTP-ответ сохраняет статус-код `404`. + +В этом случае **FastAPI** не будет отдавать `index.html` для отсутствующих путей фронтенда. Вместо этого он вернёт файл `404.html`. + +/// tip | Совет + +По умолчанию `fallback` имеет значение `fallback="auto"`. При этом, если найден файл `404.html`, он будет автоматически использован как fallback. + +Поэтому обычно можно не указывать аргумент `fallback`. + +/// + +Это полезно с фронтенд-инструментами, которые генерируют статические HTML-файлы для каждой страницы, например Astro. + +## Автоматический fallback { #fallback-auto } + +По умолчанию `app.frontend()` использует `fallback="auto"`. + +Если в директории фронтенда есть файл `404.html`, отсутствующие пути фронтенда отдают этот файл со статус-кодом `404`. + +В противном случае, если есть файл `index.html`, отсутствующие пути навигации в браузере отдают `index.html`, что и ожидают многие фронтенд-приложения с маршрутизацией на стороне клиента. + +Поэтому в большинстве случаев можно использовать `app.frontend("/", directory="dist")` без указания аргумента `fallback`. + +{* ../../docs_src/frontend/tutorial001_py310.py hl[5] *} + +## Отключение fallback { #disable-fallback } + +Если вы не хотите отдавать fallback-файл для отсутствующих путей фронтенда, используйте `fallback=None`: + +{* ../../docs_src/frontend/tutorial005_py310.py hl[5] *} + +Тогда отсутствующие пути фронтенда будут возвращать обычный `404`. + +## Проверка директории { #check-directory } + +По умолчанию `app.frontend()` проверяет, что директория существует, при создании приложения. + +Это помогает рано обнаруживать ошибки конфигурации. Например, если отсутствует директория с результатом сборки фронтенда, **FastAPI** вызовет ошибку при запуске. + +Если ваши фронтенд-файлы создаются позже, например отдельным этапом сборки после создания объекта приложения, установите `check_dir=False`: + +{* ../../docs_src/frontend/tutorial006_py310.py hl[5] *} + +С `check_dir=False` **FastAPI** не будет проверять директорию при создании приложения. Если настроенная директория всё ещё отсутствует во время обработки HTTP-запроса, **FastAPI** вызовет ошибку тогда. + +## Использование с `APIRouter` { #use-it-with-apirouter } + +Вы также можете добавить фронтенд-файлы в `APIRouter` и включить его с префиксом: + +{* ../../docs_src/frontend/tutorial004_py310.py hl[6,7] *} + +В этом примере пути фронтенда отдаются под `/app`. + +Любые обычные *операции пути* в приложении всё равно будут иметь приоритет, включая операции в других роутерах. + +## Только статический результат сборки { #static-build-output-only } + +`app.frontend()` отдаёт файлы, уже сгенерированные сборкой вашего фронтенда. + +Он не запускает server-side rendering. Он предназначен для фронтенд-фреймворков, которые генерируют статические файлы, а не для фреймворков, которым требуется динамический рендеринг на сервере для каждого HTTP-запроса. diff --git a/docs/ru/docs/tutorial/handling-errors.md b/docs/ru/docs/tutorial/handling-errors.md index fde188f09..9676ac78b 100644 --- a/docs/ru/docs/tutorial/handling-errors.md +++ b/docs/ru/docs/tutorial/handling-errors.md @@ -13,11 +13,11 @@ В таких случаях обычно возвращают **HTTP статус-код** в диапазоне **400** (от 400 до 499). -Они похожи на двухсотые HTTP статус-коды (от 200 до 299), которые означают, что запрос обработан успешно. +Они похожи на двухсотые HTTP статус-коды (от 200 до 299). Эти статус-коды "200" означают, что в HTTP-запросе в каком-то смысле был "успех". -Четырёхсотые статус-коды означают, что ошибка произошла по вине клиента. +HTTP статус-коды в диапазоне 400 означают, что произошла ошибка со стороны клиента. -Помните ли ошибки **"404 Not Found "** (и шутки) ? +Помните все эти ошибки **"404 Not Found"** (и шутки)? ## Использование `HTTPException` { #use-httpexception } @@ -31,19 +31,19 @@ `HTTPException` - это обычное исключение Python с дополнительными данными, актуальными для API. -Поскольку это исключение Python, то его не `возвращают`, а `вызывают`. +Поскольку это исключение Python, то его не `return`, а `raise`. -Это также означает, что если вы находитесь внутри функции, которая вызывается внутри вашей *функции операции пути*, и вы поднимаете `HTTPException` внутри этой функции, то она не будет выполнять остальной код в *функции операции пути*, а сразу завершит запрос и отправит HTTP-ошибку из `HTTPException` клиенту. +Это также означает, что если вы находитесь внутри вспомогательной функции, которая вызывается внутри вашей *функции-обработчика пути*, и вы вызываете `HTTPException` изнутри этой вспомогательной функции, то остальной код в *функции-обработчике пути* выполняться не будет, запрос сразу завершится, а HTTP-ошибка из `HTTPException` будет отправлена клиенту. -О том, насколько выгоднее `вызывать` исключение, чем `возвращать` значение, будет рассказано в разделе, посвященном зависимостям и безопасности. +Преимущество вызова исключения перед возвратом значения станет более очевидным в разделе о зависимостях и безопасности. -В данном примере, когда клиент запрашивает элемент по несуществующему ID, возникает исключение со статус-кодом `404`: +В данном примере, когда клиент запрашивает элемент по несуществующему ID, вызовите исключение со статус-кодом `404`: {* ../../docs_src/handling_errors/tutorial001_py310.py hl[11] *} ### Возвращаемый ответ { #the-resulting-response } -Если клиент запросит `http://example.com/items/foo` (`item_id` `"foo"`), то он получит статус-код 200 и ответ в формате JSON: +Если клиент запросит `http://example.com/items/foo` (`item_id` `"foo"`), то он получит HTTP статус-код 200 и ответ в формате JSON: ```JSON { @@ -51,7 +51,7 @@ } ``` -Но если клиент запросит `http://example.com/items/bar` (несуществующий `item_id` `"bar"`), то он получит статус-код 404 (ошибка "не найдено") и JSON-ответ в виде: +Но если клиент запросит `http://example.com/items/bar` (несуществующий `item_id` `"bar"`), то он получит HTTP статус-код 404 (ошибка "не найдено") и JSON-ответ в виде: ```JSON { @@ -69,13 +69,13 @@ /// -## Добавление пользовательских заголовков { #add-custom-headers } +## Добавление пользовательских HTTP-заголовков { #add-custom-headers } -В некоторых ситуациях полезно иметь возможность добавлять пользовательские HTTP-заголовки к ошибке HTTP. Например, для некоторых типов безопасности. +В некоторых ситуациях полезно иметь возможность добавлять пользовательские HTTP-заголовки к HTTP-ошибке. Например, для некоторых типов безопасности. -Скорее всего, вам не потребуется использовать его непосредственно в коде. +Скорее всего, вам не потребуется использовать это непосредственно в коде. -Но в случае, если это необходимо для продвинутого сценария, можно добавить пользовательские заголовки: +Но в случае, если это необходимо для продвинутого сценария, можно добавить пользовательские HTTP-заголовки: {* ../../docs_src/handling_errors/tutorial002_py310.py hl[14] *} @@ -83,7 +83,7 @@ Вы можете добавить пользовательские обработчики исключений с помощью [тех же утилит обработки исключений из Starlette](https://www.starlette.dev/exceptions/). -Допустим, у вас есть пользовательское исключение `UnicornException`, которое вы (или используемая вами библиотека) можете `вызвать`. +Допустим, у вас есть пользовательское исключение `UnicornException`, которое вы (или используемая вами библиотека) можете вызвать с помощью `raise`. И вы хотите обрабатывать это исключение глобально с помощью FastAPI. @@ -95,7 +95,7 @@ Но оно будет обработано `unicorn_exception_handler`. -Таким образом, вы получите чистую ошибку с кодом состояния HTTP `418` и содержимым JSON: +Таким образом, вы получите чистую ошибку с HTTP статус-кодом `418` и содержимым JSON: ```JSON {"message": "Oops! yolo did something. There goes a rainbow..."} @@ -113,17 +113,17 @@ **FastAPI** имеет некоторые обработчики исключений по умолчанию. -Эти обработчики отвечают за возврат стандартных JSON-ответов при `вызове` `HTTPException` и при наличии в запросе недопустимых данных. +Эти обработчики отвечают за возврат стандартных JSON-ответов при вызове `HTTPException` с помощью `raise` и при наличии в HTTP-запросе недопустимых данных. Вы можете переопределить эти обработчики исключений на свои собственные. -### Переопределение обработчика исключений проверки запроса { #override-request-validation-exceptions } +### Переопределение исключений валидации запроса { #override-request-validation-exceptions } -Когда запрос содержит недопустимые данные, **FastAPI** внутренне вызывает ошибку `RequestValidationError`. +Когда HTTP-запрос содержит недопустимые данные, **FastAPI** внутренне вызывает `RequestValidationError`. -А также включает в себя обработчик исключений по умолчанию. +А также включает в себя обработчик исключений по умолчанию для него. -Чтобы переопределить его, импортируйте `RequestValidationError` и используйте его с `@app.exception_handler(RequestValidationError)` для создания обработчика исключений. +Чтобы переопределить его, импортируйте `RequestValidationError` и используйте его с `@app.exception_handler(RequestValidationError)`, чтобы декорировать обработчик исключений. Обработчик исключения получит объект `Request` и исключение. @@ -146,7 +146,7 @@ } ``` -вы получите текстовую версию: +вы получите текстовую версию с: ``` Validation errors: @@ -171,7 +171,7 @@ Field: ('path', 'item_id'), Error: Input should be a valid integer, unable to pa /// warning | Внимание -Имейте в виду, что `RequestValidationError` содержит информацию об имени файла и строке, где произошла ошибка валидации, чтобы вы могли при желании отобразить её в логах с релевантными данными. +Имейте в виду, что `RequestValidationError` содержит информацию об имени файла и строке, где происходит ошибка валидации, чтобы вы могли при желании отобразить её в логах вместе с релевантной информацией. Но это означает, что если вы просто преобразуете её в строку и вернёте эту информацию напрямую, вы можете допустить небольшую утечку информации о своей системе, поэтому здесь код извлекает и показывает каждую ошибку отдельно. @@ -179,13 +179,13 @@ Field: ('path', 'item_id'), Error: Input should be a valid integer, unable to pa ### Используйте тело `RequestValidationError` { #use-the-requestvalidationerror-body } -Ошибка `RequestValidationError` содержит полученное `тело` с недопустимыми данными. +Ошибка `RequestValidationError` содержит `body` (тело запроса), которое она получила с недопустимыми данными. -Вы можете использовать его при разработке приложения для регистрации тела и его отладки, возврата пользователю и т.д. +Вы можете использовать его при разработке приложения для логирования тела запроса и его отладки, возврата пользователю и т.д. {* ../../docs_src/handling_errors/tutorial005_py310.py hl[14] *} -Теперь попробуйте отправить недействительный элемент, например: +Теперь попробуйте отправить недопустимый элемент, например: ```JSON { @@ -194,7 +194,7 @@ Field: ('path', 'item_id'), Error: Input should be a valid integer, unable to pa } ``` -Вы получите ответ о том, что данные недействительны, содержащий следующее тело: +Вы получите ответ о том, что данные недопустимы, содержащий полученное тело запроса: ```JSON hl_lines="12-15" { @@ -215,7 +215,7 @@ Field: ('path', 'item_id'), Error: Input should be a valid integer, unable to pa } ``` -#### `HTTPException` в FastAPI или в Starlette { #fastapis-httpexception-vs-starlettes-httpexception } +#### `HTTPException` в FastAPI и `HTTPException` в Starlette { #fastapis-httpexception-vs-starlettes-httpexception } **FastAPI** имеет собственный `HTTPException`. @@ -227,9 +227,9 @@ Field: ('path', 'item_id'), Error: Input should be a valid integer, unable to pa Но когда вы регистрируете обработчик исключений, вы должны зарегистрировать его для `HTTPException` от Starlette. -Таким образом, если какая-либо часть внутреннего кодa Starlette, расширение или плагин Starlette вызовет исключение Starlette `HTTPException`, ваш обработчик сможет перехватить и обработать его. +Таким образом, если какая-либо часть внутреннего кода Starlette, расширение или плагин Starlette вызовет исключение Starlette `HTTPException`, ваш обработчик сможет перехватить и обработать его. -В данном примере, чтобы иметь возможность использовать оба `HTTPException` в одном коде, исключения Starlette переименованы в `StarletteHTTPException`: +В данном примере, чтобы иметь возможность использовать оба `HTTPException` в одном коде, исключение Starlette переименовано в `StarletteHTTPException`: ```Python from starlette.exceptions import HTTPException as StarletteHTTPException @@ -241,4 +241,4 @@ from starlette.exceptions import HTTPException as StarletteHTTPException {* ../../docs_src/handling_errors/tutorial006_py310.py hl[2:5,15,21] *} -В этом примере вы просто `выводите в терминал` ошибку с очень выразительным сообщением, но идея вам понятна. Вы можете использовать исключение, а затем просто повторно использовать стандартные обработчики исключений. +В этом примере вы просто выводите ошибку с очень выразительным сообщением, но идея вам понятна. Вы можете использовать исключение, а затем просто повторно использовать стандартные обработчики исключений. diff --git a/docs/ru/docs/tutorial/index.md b/docs/ru/docs/tutorial/index.md index eec217b75..b843515f8 100644 --- a/docs/ru/docs/tutorial/index.md +++ b/docs/ru/docs/tutorial/index.md @@ -1,5 +1,6 @@ # Учебник - Руководство пользователя { #tutorial-user-guide } + В этом руководстве шаг за шагом показано, как использовать **FastAPI** с большинством его функций. Каждый раздел постепенно основывается на предыдущих, но структура разделяет темы, так что вы можете сразу перейти к нужной теме для решения ваших конкретных задач по API. diff --git a/docs/ru/docs/tutorial/metadata.md b/docs/ru/docs/tutorial/metadata.md index 261cc43f5..958c9cbbb 100644 --- a/docs/ru/docs/tutorial/metadata.md +++ b/docs/ru/docs/tutorial/metadata.md @@ -11,10 +11,10 @@ | `title` | `str` | Заголовок API. | | `summary` | `str` | Краткое резюме API. Доступно начиная с OpenAPI 3.1.0, FastAPI 0.99.0. | | `description` | `str` | Краткое описание API. Может быть использован Markdown. | -| `version` | `string` | Версия API. Версия вашего собственного приложения, а не OpenAPI. К примеру `2.5.0`. | -| `terms_of_service` | `str` | Ссылка к условиям пользования API. Если указано, то это должен быть URL-адрес. | -| `contact` | `dict` | Контактная информация для открытого API. Может содержать несколько полей.
поля contact
ПараметрТипОписание
namestrИдентификационное имя контактного лица/организации.
urlstrURL указывающий на контактную информацию. ДОЛЖЕН быть в формате URL.
emailstrEmail адрес контактного лица/организации. ДОЛЖЕН быть в формате email адреса.
| -| `license_info` | `dict` | Информация о лицензии открытого API. Может содержать несколько полей.
поля license_info
ПараметрТипОписание
namestrОБЯЗАТЕЛЬНО (если установлен параметр license_info). Название лицензии, используемой для API.
identifierstrВыражение лицензии [SPDX](https://spdx.org/licenses/) для API. Поле identifier взаимоисключающее с полем url. Доступно начиная с OpenAPI 3.1.0, FastAPI 0.99.0.
urlstrURL, указывающий на лицензию, используемую для API. ДОЛЖЕН быть в формате URL.
| +| `version` | `str` | Версия API. Версия вашего собственного приложения, а не OpenAPI. К примеру `2.5.0`. | +| `terms_of_service` | `str` | Ссылка на условия пользования API. Если указано, то это должен быть URL-адрес. | +| `contact` | `dict` | Контактная информация для открытого API. Может содержать несколько полей.
поля contact
ПараметрТипОписание
namestrИдентификационное имя контактного лица/организации.
urlstrURL, указывающий на контактную информацию. ДОЛЖЕН быть в формате URL.
emailstrEmail-адрес контактного лица/организации. ДОЛЖЕН быть в формате email-адреса.
| +| `license_info` | `dict` | Информация о лицензии открытого API. Может содержать несколько полей.
поля license_info
ПараметрТипОписание
namestrОБЯЗАТЕЛЬНО (если установлен параметр license_info). Название лицензии, используемой для API.
identifierstrВыражение лицензии [SPDX](https://spdx.org/licenses/) для API. Поле identifier является взаимоисключающим с полем url. Доступно начиная с OpenAPI 3.1.0, FastAPI 0.99.0.
urlstrURL, указывающий на лицензию, используемую для API. ДОЛЖЕН быть в формате URL.
| Вы можете задать их следующим образом: @@ -48,7 +48,7 @@ * `name` (**обязательно**): `str`-значение с тем же именем тега, которое вы используете в параметре `tags` в ваших *операциях пути* и `APIRouter`ах. * `description`: `str`-значение с кратким описанием для тега. Может содержать Markdown и будет отображаться в UI документации. -* `externalDocs`: `dict`-значение описывающее внешнюю документацию. Включает в себя: +* `externalDocs`: `dict`-значение, описывающее внешнюю документацию. Включает в себя: * `description`: `str`-значение с кратким описанием для внешней документации. * `url` (**обязательно**): `str`-значение с URL-адресом для внешней документации. @@ -64,7 +64,7 @@ /// tip | Подсказка -Вам необязательно добавлять метаданные для всех используемых тегов +Вам необязательно добавлять метаданные для всех используемых тегов. /// @@ -74,7 +74,7 @@ {* ../../docs_src/metadata/tutorial004_py310.py hl[21,26] *} -/// info | Дополнительная информация +/// note | Примечание Узнайте больше о тегах в [Конфигурации операции пути](path-operation-configuration.md#tags). @@ -94,11 +94,11 @@ ## URL-адрес OpenAPI { #openapi-url } -По умолчанию схема OpenAPI отображена по адресу `/openapi.json`. +По умолчанию схема OpenAPI отдаётся по адресу `/openapi.json`. Но вы можете изменить это с помощью параметра `openapi_url`. -К примеру, чтобы задать её отображение по адресу `/api/v1/openapi.json`: +К примеру, чтобы задать её отдачу по адресу `/api/v1/openapi.json`: {* ../../docs_src/metadata/tutorial002_py310.py hl[3] *} @@ -106,15 +106,15 @@ ## URL-адреса документации { #docs-urls } -Вы можете изменить конфигурацию двух пользовательских интерфейсов документации, которые включены: +Вы можете изменить конфигурацию двух включённых пользовательских интерфейсов документации: -* **Swagger UI**: отображаемый по адресу `/docs`. +* **Swagger UI**: отдаётся по адресу `/docs`. * Вы можете задать его URL с помощью параметра `docs_url`. * Вы можете отключить это с помощью настройки `docs_url=None`. -* **ReDoc**: отображаемый по адресу `/redoc`. +* **ReDoc**: отдаётся по адресу `/redoc`. * Вы можете задать его URL с помощью параметра `redoc_url`. * Вы можете отключить это с помощью настройки `redoc_url=None`. -К примеру, чтобы задать отображение Swagger UI по адресу `/documentation` и отключить ReDoc: +К примеру, чтобы настроить отдачу Swagger UI по адресу `/documentation` и отключить ReDoc: {* ../../docs_src/metadata/tutorial003_py310.py hl[3] *} diff --git a/docs/ru/docs/tutorial/path-operation-configuration.md b/docs/ru/docs/tutorial/path-operation-configuration.md index 965f2a1ba..c5099c3e0 100644 --- a/docs/ru/docs/tutorial/path-operation-configuration.md +++ b/docs/ru/docs/tutorial/path-operation-configuration.md @@ -1,10 +1,10 @@ -# Конфигурация операций пути { #path-operation-configuration } +# Конфигурация операции пути { #path-operation-configuration } -Существует несколько параметров, которые вы можете передать вашему *декоратору операций пути* для его настройки. +Существует несколько параметров, которые вы можете передать вашему *декоратору операции пути* для его настройки. /// warning | Внимание -Помните, что эти параметры передаются непосредственно *декоратору операций пути*, а не вашей *функции-обработчику пути*. +Помните, что эти параметры передаются непосредственно *декоратору операции пути*, а не вашей *функции-обработчику пути*. /// @@ -30,11 +30,11 @@ ## Теги { #tags } -Вы можете добавлять теги к вашим *операциям пути*, добавив параметр `tags` с `list` заполненным `str`-значениями (обычно в нём только одна строка): +Вы можете добавлять теги к вашей *операции пути*, передав параметр `tags` с `list` из `str` (обычно в нём только одна строка): {* ../../docs_src/path_operation_configuration/tutorial002_py310.py hl[15,20,25] *} -Они будут добавлены в схему OpenAPI и будут использованы в автоматической документации интерфейса: +Они будут добавлены в схему OpenAPI и будут использованы автоматическими интерфейсами документации: @@ -56,7 +56,7 @@ ## Описание из строк документации { #description-from-docstring } -Так как описания обычно длинные и содержат много строк, вы можете объявить описание *операции пути* в строке документации функции, и **FastAPI** прочитает её оттуда. +Так как описания обычно длинные и содержат много строк, вы можете объявить описание *операции пути* в строке документации функции, и **FastAPI** прочитает её оттуда. Вы можете использовать [Markdown](https://en.wikipedia.org/wiki/Markdown) в строке документации, и он будет интерпретирован и отображён корректно (с учетом отступа в строке документации). @@ -72,13 +72,13 @@ {* ../../docs_src/path_operation_configuration/tutorial005_py310.py hl[18] *} -/// info | Дополнительная информация +/// note | Примечание Помните, что `response_description` относится конкретно к ответу, а `description` относится к *операции пути* в целом. /// -/// check | Проверка +/// tip | Совет OpenAPI указывает, что каждой *операции пути* необходимо описание ответа. @@ -94,7 +94,7 @@ OpenAPI указывает, что каждой *операции пути* не {* ../../docs_src/path_operation_configuration/tutorial006_py310.py hl[16] *} -Он будет четко помечен как устаревший в интерактивной документации: +Она будет четко помечена как устаревшая в интерактивной документации: diff --git a/docs/ru/docs/tutorial/path-params-numeric-validations.md b/docs/ru/docs/tutorial/path-params-numeric-validations.md index 34eeb80cb..dbbc025f1 100644 --- a/docs/ru/docs/tutorial/path-params-numeric-validations.md +++ b/docs/ru/docs/tutorial/path-params-numeric-validations.md @@ -8,7 +8,7 @@ {* ../../docs_src/path_params_numeric_validations/tutorial001_an_py310.py hl[1,3] *} -/// info | Информация +/// note | Примечание Поддержка `Annotated` была добавлена в FastAPI начиная с версии 0.95.0 (и с этой версии рекомендуется использовать этот подход). @@ -131,7 +131,7 @@ Python не будет ничего делать с `*`, но он будет з * `lt`: меньше (`l`ess `t`han) * `le`: меньше или равно (`l`ess than or `e`qual) -/// info | Информация +/// note | Примечание `Query`, `Path` и другие классы, которые вы разберёте позже, являются наследниками общего класса `Param`. diff --git a/docs/ru/docs/tutorial/path-params.md b/docs/ru/docs/tutorial/path-params.md index 79343a158..cfc96189c 100644 --- a/docs/ru/docs/tutorial/path-params.md +++ b/docs/ru/docs/tutorial/path-params.md @@ -20,7 +20,7 @@ Здесь, `item_id` объявлен типом `int`. -/// check | Заметка +/// tip | Подсказка Это обеспечит поддержку редактора кода внутри функции (проверка ошибок, автозавершение и т.п.). @@ -34,7 +34,7 @@ {"item_id":3} ``` -/// check | Заметка +/// tip | Подсказка Обратите внимание на значение `3`, которое получила (и вернула) функция. Это целочисленный Python `int`, а не строка `"3"`. @@ -66,7 +66,7 @@ Та же ошибка возникнет, если вместо `int` передать `float`, например: [http://127.0.0.1:8000/items/4.2](http://127.0.0.1:8000/items/4.2) -/// check | Заметка +/// tip | Подсказка **FastAPI** обеспечивает валидацию данных, используя всё те же определения типов. @@ -82,7 +82,7 @@ -/// check | Заметка +/// tip | Подсказка Ещё раз, просто используя определения типов, **FastAPI** обеспечивает автоматическую интерактивную документацию (с интеграцией Swagger UI). diff --git a/docs/ru/docs/tutorial/query-params-str-validations.md b/docs/ru/docs/tutorial/query-params-str-validations.md index 08a5e11a5..5783b0cdf 100644 --- a/docs/ru/docs/tutorial/query-params-str-validations.md +++ b/docs/ru/docs/tutorial/query-params-str-validations.md @@ -29,7 +29,7 @@ FastAPI поймёт, что значение `q` не обязательно, {* ../../docs_src/query_params_str_validations/tutorial002_an_py310.py hl[1,3] *} -/// info | Дополнительная информация +/// note | Примечание Поддержка `Annotated` (и рекомендация использовать его) появилась в FastAPI версии 0.95.0. @@ -80,8 +80,8 @@ q: Annotated[str | None] = None Теперь FastAPI будет: * **валидировать** данные, удостоверяясь, что максимальная длина — 50 символов; -* показывать **понятную ошибку** клиенту, если данные невалидны; -* **документировать** параметр в *операции пути* схемы OpenAPI (он будет показан в **UI автоматической документации**). +* отображать **понятную ошибку** клиенту, если данные невалидны; +* **документировать** параметр в *операции пути* схемы OpenAPI (он будет отображаться в **UI автоматической документации**). ## Альтернатива (устаревшее): `Query` как значение по умолчанию { #alternative-old-query-as-the-default-value } @@ -119,7 +119,7 @@ q: str | None = None q: str | None = Query(default=None, max_length=50) ``` -Это провалидирует данные, покажет понятную ошибку, если данные невалидны, и задокументирует параметр в *операции пути* схемы OpenAPI. +Это провалидирует данные, отобразит понятную ошибку, если данные невалидны, и задокументирует параметр в *операции пути* схемы OpenAPI. ### `Query` как значение по умолчанию или внутри `Annotated` { #query-as-the-default-value-or-in-annotated } @@ -141,7 +141,7 @@ q: Annotated[str, Query(default="rick")] = "morty" q: Annotated[str, Query()] = "rick" ``` -...или в старой кодовой базе вы увидите: +...или в старых кодовых базах вы увидите: ```Python q: str = Query(default="rick") @@ -153,19 +153,19 @@ q: str = Query(default="rick") **Значение по умолчанию** у **параметра функции** — это **настоящее значение по умолчанию**, что более интуитивно для Python. 😌 -Вы можете **вызвать** эту же функцию в **других местах** без FastAPI, и она будет **работать как ожидается**. Если есть **обязательный** параметр (без значения по умолчанию), ваш **редактор** сообщит об ошибке, **Python** тоже пожалуется, если вы запустите её без передачи обязательного параметра. +Вы можете **вызвать** эту же функцию в **других местах** без FastAPI, и она будет **работать как ожидается**. Если есть **обязательный** параметр (без значения по умолчанию), ваш **редактор кода** сообщит об ошибке, **Python** тоже пожалуется, если вы запустите её без передачи обязательного параметра. -Если вы не используете `Annotated`, а применяете **(устаревший) стиль со значением по умолчанию**, то при вызове этой функции без FastAPI в **других местах** вам нужно **помнить** о том, что надо передать аргументы, чтобы всё работало корректно, иначе значения будут не такими, как вы ожидаете (например, вместо `str` будет `QueryInfo` или что-то подобное). И ни редактор, ни Python не будут ругаться при самом вызове функции — ошибка проявится лишь при операциях внутри. +Если вы не используете `Annotated`, а применяете **(устаревший) стиль со значением по умолчанию**, то при вызове этой функции без FastAPI в **других местах** вам нужно **помнить** о том, что надо передать аргументы, чтобы всё работало корректно, иначе значения будут не такими, как вы ожидаете (например, вместо `str` будет `QueryInfo` или что-то подобное). И ни редактор кода, ни Python не будут ругаться при самом вызове функции — ошибка проявится лишь при операциях внутри. Так как `Annotated` может содержать больше одной аннотации метаданных, теперь вы можете использовать ту же функцию и с другими инструментами, например с [Typer](https://typer.tiangolo.com/). 🚀 -## Больше валидаций { #add-more-validations } +## Добавим больше валидаций { #add-more-validations } Можно также добавить параметр `min_length`: {* ../../docs_src/query_params_str_validations/tutorial003_an_py310.py hl[10] *} -## Регулярные выражения { #add-regular-expressions } +## Добавим регулярные выражения { #add-regular-expressions } Вы можете определить регулярное выражение `pattern`, которому должен соответствовать параметр: @@ -173,7 +173,7 @@ q: str = Query(default="rick") Данный шаблон регулярного выражения проверяет, что полученное значение параметра: -* `^`: начинается с следующих символов, до них нет символов. +* `^`: начинается со следующих символов, до них нет символов. * `fixedquery`: имеет точное значение `fixedquery`. * `$`: заканчивается здесь, после `fixedquery` нет никаких символов. @@ -191,7 +191,7 @@ q: str = Query(default="rick") /// note | Примечание -Наличие значения по умолчанию любого типа, включая `None`, делает параметр необязательным. +Наличие значения по умолчанию любого типа, включая `None`, делает параметр необязательным (не обязательным). /// @@ -243,7 +243,7 @@ http://localhost:8000/items/?q=foo&q=bar вы получите множественные значения *query-параметров* `q` (`foo` и `bar`) в виде Python-`list` внутри вашей *функции-обработчика пути*, в *параметре функции* `q`. -Таким образом, ответ на этот URL будет: +Таким образом, HTTP-ответом на этот URL будет: ```JSON { @@ -276,7 +276,7 @@ http://localhost:8000/items/?q=foo&q=bar http://localhost:8000/items/ ``` -значение по умолчанию для `q` будет: `["foo", "bar"]`, и ответом будет: +значение по умолчанию для `q` будет: `["foo", "bar"]`, и вашим HTTP-ответом будет: ```JSON { @@ -301,7 +301,7 @@ http://localhost:8000/items/ /// -## Больше метаданных { #declare-more-metadata } +## Объявление дополнительных метаданных { #declare-more-metadata } Можно добавить больше информации о параметре. @@ -369,7 +369,7 @@ http://127.0.0.1:8000/items/?item-query=foobaritems В таких случаях можно использовать **кастомную функцию-валидатор**, которая применяется после обычной валидации (например, после проверки, что значение — это `str`). -Этого можно добиться, используя [`AfterValidator` Pydantic](https://docs.pydantic.dev/latest/concepts/validators/#field-after-validator) внутри `Annotated`. +Этого можно добиться, используя [Pydantic `AfterValidator`](https://docs.pydantic.dev/latest/concepts/validators/#field-after-validator) внутри `Annotated`. /// tip | Совет @@ -377,11 +377,11 @@ http://127.0.0.1:8000/items/?item-query=foobaritems /// -Например, эта кастомная проверка убеждается, что ID элемента начинается с `isbn-` для номера книги ISBN или с `imdb-` для ID URL фильма на IMDB: +Например, эта кастомная проверка убеждается, что ID элемента начинается с `isbn-` для номера книги ISBN или с `imdb-` для ID URL фильма в IMDB: {* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py hl[5,16:19,24] *} -/// info | Дополнительная информация +/// note | Примечание Это доступно в Pydantic версии 2 и выше. 😎 @@ -391,7 +391,7 @@ http://127.0.0.1:8000/items/?item-query=foobaritems Если вам нужна валидация, требующая общения с каким‑либо **внешним компонентом** — базой данных или другим API — вместо этого используйте **Зависимости FastAPI**, вы познакомитесь с ними позже. -Эти кастомные валидаторы предназначены для проверок, которые можно выполнить, имея **только** те же **данные**, что пришли в запросе. +Эти кастомные валидаторы предназначены для проверок, которые можно выполнить, имея **только** те же **данные**, что пришли в HTTP-запросе. /// @@ -429,7 +429,7 @@ http://127.0.0.1:8000/items/?item-query=foobaritems Вы можете объявлять дополнительные проверки и метаданные для параметров. -Общие метаданные и настройки: +Общие проверки и метаданные: * `alias` * `title` diff --git a/docs/ru/docs/tutorial/query-params.md b/docs/ru/docs/tutorial/query-params.md index 99f2a98ae..65c0c2d9a 100644 --- a/docs/ru/docs/tutorial/query-params.md +++ b/docs/ru/docs/tutorial/query-params.md @@ -1,10 +1,10 @@ # Query-параметры { #query-parameters } -Когда вы объявляете параметры функции, которые не являются параметрами пути, они автоматически интерпретируются как "query"-параметры. +Когда вы объявляете параметры функции, которые не являются частью path-параметров, они автоматически интерпретируются как "query"-параметры. {* ../../docs_src/query_params/tutorial001_py310.py hl[9] *} -Query-параметры представляют из себя набор пар ключ-значение, которые идут после знака `?` в URL-адресе, разделенные символами `&`. +Query — это набор пар ключ-значение, которые идут после знака `?` в URL-адресе, разделенные символами `&`. Например, в этом URL-адресе: @@ -12,25 +12,25 @@ Query-параметры представляют из себя набор па http://127.0.0.1:8000/items/?skip=0&limit=10 ``` -...параметры запроса такие: +...query-параметры такие: * `skip`: со значением `0` * `limit`: со значением `10` -Будучи частью URL-адреса, они "по умолчанию" являются строками. +Будучи частью URL-адреса, они "естественным образом" являются строками. Но когда вы объявляете их с использованием типов Python (в примере выше, как `int`), они конвертируются в указанный тип данных и проходят проверку на соответствие ему. -Все те же правила, которые применяются к path-параметрам, также применяются и query-параметрам: +Все те же процессы, которые применяются к path-параметрам, также применяются и к query-параметрам: * Поддержка от редактора кода (очевидно) -* "Парсинг" данных -* Проверка на соответствие данных (Валидация) +* "Парсинг" данных +* Валидация данных * Автоматическая документация ## Значения по умолчанию { #defaults } -Поскольку query-параметры не являются фиксированной частью пути, они могут быть не обязательными и иметь значения по умолчанию. +Поскольку query-параметры не являются фиксированной частью пути, они могут быть необязательными и иметь значения по умолчанию. В примере выше значения по умолчанию равны `skip=0` и `limit=10`. @@ -40,13 +40,13 @@ http://127.0.0.1:8000/items/?skip=0&limit=10 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 @@ -55,7 +55,7 @@ http://127.0.0.1:8000/items/?skip=20 Значения параметров в вашей функции будут: * `skip=20`: потому что вы установили это в URL-адресе -* `limit=10`: т.к это было значение по умолчанию +* `limit=10`: потому что это было значение по умолчанию ## Необязательные параметры { #optional-parameters } @@ -63,21 +63,21 @@ http://127.0.0.1:8000/items/?skip=20 {* ../../docs_src/query_params/tutorial002_py310.py hl[7] *} -В этом случае, параметр `q` будет не обязательным и будет иметь значение `None` по умолчанию. +В этом случае параметр функции `q` будет необязательным и будет иметь значение `None` по умолчанию. -/// check | Важно +/// tip | Подсказка -Также обратите внимание, что **FastAPI** достаточно умён чтобы заметить, что параметр `item_id` является path-параметром, а `q` нет, поэтому, это параметр запроса. +Также обратите внимание, что **FastAPI** достаточно умён, чтобы заметить, что path-параметр `item_id` является path-параметром, а `q` — нет, поэтому это query-параметр. /// -## Преобразование типа параметра запроса { #query-parameter-type-conversion } +## Преобразование типа query-параметра { #query-parameter-type-conversion } -Вы также можете объявлять параметры с типом `bool`, которые будут преобразованы соответственно: +Вы также можете объявлять типы `bool`, и они будут преобразованы: {* ../../docs_src/query_params/tutorial003_py310.py hl[7] *} -В этом случае, если вы сделаете запрос: +В этом случае, если вы перейдёте по: ``` http://127.0.0.1:8000/items/foo?short=1 @@ -107,11 +107,12 @@ http://127.0.0.1:8000/items/foo?short=on http://127.0.0.1:8000/items/foo?short=yes ``` -или в любом другом варианте написания (в верхнем регистре, с заглавной буквой, и т.п), внутри вашей функции параметр `short` будет иметь значение `True` типа данных `bool` . В противном случае - `False`. +или в любом другом варианте написания (в верхнем регистре, с заглавной буквой и т.п.), внутри вашей функции параметр `short` будет иметь значение `True` типа данных `bool`. В противном случае — `False`. + -## Смешивание query-параметров и path-параметров { #multiple-path-and-query-parameters } +## Несколько path-параметров и query-параметров { #multiple-path-and-query-parameters } -Вы можете объявлять несколько query-параметров и path-параметров одновременно, **FastAPI** сам разберётся, что чем является. +Вы можете объявлять несколько path-параметров и query-параметров одновременно, **FastAPI** знает, что чем является. И вы не обязаны объявлять их в каком-либо определенном порядке. @@ -123,21 +124,21 @@ http://127.0.0.1:8000/items/foo?short=yes Когда вы объявляете значение по умолчанию для параметра, который не является path-параметром (в этом разделе мы пока что рассмотрели только query-параметры), то он не является обязательным. -Если вы не хотите задавать конкретное значение, но хотите сделать параметр необязательным, вы можете установить значение по умолчанию равным `None`. +Если вы не хотите задавать конкретное значение, но хотите просто сделать параметр необязательным, установите значение по умолчанию равным `None`. Но если вы хотите сделать query-параметр обязательным, вы можете просто не указывать значение по умолчанию: {* ../../docs_src/query_params/tutorial005_py310.py hl[6:7] *} -Здесь параметр запроса `needy` является обязательным параметром с типом данных `str`. +Здесь query-параметр `needy` является обязательным query-параметром с типом данных `str`. -Если вы откроете в браузере URL-адрес, например: +Если вы откроете в браузере URL-адрес вроде: ``` http://127.0.0.1:8000/items/foo-item ``` -...без добавления обязательного параметра `needy`, вы увидите подобного рода ошибку: +...без добавления обязательного параметра `needy`, вы увидите ошибку вроде: ```JSON { @@ -170,18 +171,18 @@ http://127.0.0.1:8000/items/foo-item?needy=sooooneedy } ``` -Конечно, вы можете определить некоторые параметры как обязательные, некоторые — со значением по умолчанию, а некоторые — полностью необязательные: +И, конечно, вы можете определить некоторые параметры как обязательные, некоторые — со значением по умолчанию, а некоторые — полностью необязательные: {* ../../docs_src/query_params/tutorial006_py310.py hl[8] *} -В этом примере, у нас есть 3 параметра запроса: +В этом случае есть 3 query-параметра: * `needy`, обязательный `str`. -* `skip`, типа `int` и со значением по умолчанию `0`. +* `skip`, `int` со значением по умолчанию `0`. * `limit`, необязательный `int`. /// tip | Подсказка -Вы можете использовать класс `Enum` также, как ранее применяли его с [Path-параметрами](path-params.md#predefined-values). +Вы можете использовать `Enum` так же, как ранее применяли его с [Path-параметрами](path-params.md#predefined-values). /// diff --git a/docs/ru/docs/tutorial/request-files.md b/docs/ru/docs/tutorial/request-files.md index e8500adba..6d40aaac6 100644 --- a/docs/ru/docs/tutorial/request-files.md +++ b/docs/ru/docs/tutorial/request-files.md @@ -2,7 +2,7 @@ Используя класс `File`, мы можем позволить клиентам загружать файлы. -/// info | Дополнительная информация +/// note | Примечание Чтобы получать загруженные файлы, сначала установите [`python-multipart`](https://github.com/Kludex/python-multipart). @@ -28,7 +28,7 @@ $ pip install python-multipart {* ../../docs_src/request_files/tutorial001_an_py310.py hl[9] *} -/// info | Дополнительная информация +/// note | Примечание `File` - это класс, который наследуется непосредственно от `Form`. @@ -38,13 +38,13 @@ $ pip install python-multipart /// tip | Подсказка -Для объявления тела файла необходимо использовать `File`, поскольку в противном случае параметры будут интерпретироваться как параметры запроса или параметры тела (JSON). +Чтобы объявить файлы в теле запроса, необходимо использовать `File`, поскольку иначе параметры будут интерпретироваться как параметры запроса или body-параметры (JSON). /// Файлы будут загружены как данные формы. -Если вы объявите тип параметра у *функции операции пути* как `bytes`, то **FastAPI** прочитает файл за вас, и вы получите его содержимое в виде `bytes`. +Если вы объявите тип параметра у *функции-обработчика пути* как `bytes`, то **FastAPI** прочитает файл за вас, и вы получите его содержимое в виде `bytes`. Следует иметь в виду, что все содержимое будет храниться в памяти. Это хорошо подходит для небольших файлов. @@ -64,15 +64,15 @@ $ pip install python-multipart * Это означает, что он будет хорошо работать с большими файлами, такими как изображения, видео, большие бинарные файлы и т.д., не потребляя при этом всю память. * Из загруженного файла можно получить метаданные. * Он реализует [file-like](https://docs.python.org/3/glossary.html#term-file-like-object) `async` интерфейс. -* Он предоставляет реальный объект Python [`SpooledTemporaryFile`](https://docs.python.org/3/library/tempfile.html#tempfile.SpooledTemporaryFile), который вы можете передать непосредственно другим библиотекам, которые ожидают файл в качестве объекта. +* Он предоставляет реальный объект Python [`SpooledTemporaryFile`](https://docs.python.org/3/library/tempfile.html#tempfile.SpooledTemporaryFile), который вы можете передать непосредственно другим библиотекам, которые ожидают file-like объект. ### `UploadFile` { #uploadfile } `UploadFile` имеет следующие атрибуты: * `filename`: Строка `str` с исходным именем файла, который был загружен (например, `myimage.jpg`). -* `content_type`: Строка `str` с типом содержимого (MIME type / media type) (например, `image/jpeg`). -* `file`: [`SpooledTemporaryFile`](https://docs.python.org/3/library/tempfile.html#tempfile.SpooledTemporaryFile) (a [file-like](https://docs.python.org/3/glossary.html#term-file-like-object) объект). Это фактический файл Python, который можно передавать непосредственно другим функциям или библиотекам, ожидающим файл в качестве объекта. +* `content_type`: Строка `str` с типом содержимого (MIME-тип / тип содержимого) (например, `image/jpeg`). +* `file`: [`SpooledTemporaryFile`](https://docs.python.org/3/library/tempfile.html#tempfile.SpooledTemporaryFile) ([file-like](https://docs.python.org/3/glossary.html#term-file-like-object) объект). Это фактический файл Python, который можно передавать непосредственно другим функциям или библиотекам, ожидающим file-like объект. `UploadFile` имеет следующие методы `async`. Все они вызывают соответствующие файловые методы (используя внутренний `SpooledTemporaryFile`). @@ -85,19 +85,18 @@ $ pip install python-multipart Поскольку все эти методы являются `async` методами, вам следует использовать "await" вместе с ними. -Например, внутри `async` *функции операции пути* можно получить содержимое с помощью: +Например, внутри `async` *функции-обработчика пути* можно получить содержимое с помощью: ```Python contents = await myfile.read() ``` -Если вы находитесь внутри обычной `def` *функции операции пути*, можно получить прямой доступ к файлу `UploadFile.file`, например: +Если вы находитесь внутри обычной `def` *функции-обработчика пути*, можно получить прямой доступ к файлу `UploadFile.file`, например: ```Python contents = myfile.file.read() ``` - /// note | Технические детали `async` При использовании методов `async` **FastAPI** запускает файловые методы в пуле потоков и ожидает их. @@ -106,7 +105,7 @@ contents = myfile.file.read() /// note | Технические детали Starlette -**FastAPI** наследует `UploadFile` непосредственно из **Starlette**, но добавляет некоторые детали для совместимости с **Pydantic** и другими частями FastAPI. +`UploadFile` из **FastAPI** наследуется непосредственно от `UploadFile` из **Starlette**, но добавляет некоторые необходимые части для совместимости с **Pydantic** и другими частями FastAPI. /// @@ -118,17 +117,17 @@ contents = myfile.file.read() /// note | Технические детали -Данные из форм обычно кодируются с использованием "media type" `application/x-www-form-urlencoded` когда он не включает файлы. +Данные из форм обычно кодируются с использованием типа содержимого `application/x-www-form-urlencoded`, когда они не включают файлы. -Но когда форма включает файлы, она кодируется как `multipart/form-data`. Если вы используете `File`, **FastAPI** будет знать, что ему нужно получить файлы из нужной части тела. +Но когда форма включает файлы, она кодируется как `multipart/form-data`. Если вы используете `File`, **FastAPI** будет знать, что ему нужно получить файлы из нужной части тела запроса. -Если вы хотите узнать больше об этих кодировках и полях форм, перейдите по ссылке [MDN web docs for `POST`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST). +Если вы хотите узнать больше об этих кодировках и полях форм, перейдите к [веб-документации MDN по `POST`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST). /// /// warning | Внимание -В операции *функции операции пути* можно объявить несколько параметров `File` и `Form`, но нельзя также объявлять поля `Body`, которые предполагается получить в виде JSON, поскольку тело запроса будет закодировано с помощью `multipart/form-data`, а не `application/json`. +В *операции пути* можно объявить несколько параметров `File` и `Form`, но нельзя также объявлять поля `Body`, которые предполагается получить в виде JSON, поскольку HTTP-запрос будет иметь тело, закодированное с помощью `multipart/form-data`, а не `application/json`. Это не является ограничением **FastAPI**, это часть протокола HTTP. @@ -174,4 +173,4 @@ contents = myfile.file.read() ## Резюме { #recap } -Используйте `File`, `bytes` и `UploadFile` для работы с файлами, которые будут загружаться и передаваться в виде данных формы. +Используйте `File`, `bytes` и `UploadFile`, чтобы объявлять файлы для загрузки в HTTP-запросе, передаваемые как данные формы. diff --git a/docs/ru/docs/tutorial/request-form-models.md b/docs/ru/docs/tutorial/request-form-models.md index c7f37c2ba..3852e3a03 100644 --- a/docs/ru/docs/tutorial/request-form-models.md +++ b/docs/ru/docs/tutorial/request-form-models.md @@ -2,7 +2,7 @@ Вы можете использовать **Pydantic-модели** для объявления **полей формы** в FastAPI. -/// info | Дополнительная информация +/// note | Заметка Чтобы использовать формы, сначала установите [`python-multipart`](https://github.com/Kludex/python-multipart). diff --git a/docs/ru/docs/tutorial/request-forms-and-files.md b/docs/ru/docs/tutorial/request-forms-and-files.md index f291d5347..347818ae3 100644 --- a/docs/ru/docs/tutorial/request-forms-and-files.md +++ b/docs/ru/docs/tutorial/request-forms-and-files.md @@ -2,7 +2,7 @@ Вы можете определять файлы и поля формы одновременно, используя `File` и `Form`. -/// info | Информация +/// note | Примечание Чтобы получать загруженные файлы и/или данные форм, сначала установите [`python-multipart`](https://github.com/Kludex/python-multipart). diff --git a/docs/ru/docs/tutorial/request-forms.md b/docs/ru/docs/tutorial/request-forms.md index 3760a8a3b..2067195dd 100644 --- a/docs/ru/docs/tutorial/request-forms.md +++ b/docs/ru/docs/tutorial/request-forms.md @@ -1,8 +1,9 @@ # Данные формы { #form-data } + Когда вам нужно получить поля формы вместо JSON, вы можете использовать `Form`. -/// info | Дополнительная информация +/// note | Примечание Чтобы использовать формы, сначала установите [`python-multipart`](https://github.com/Kludex/python-multipart). @@ -32,7 +33,7 @@ $ pip install python-multipart С помощью `Form` вы можете объявить те же настройки, что и с `Body` (и `Query`, `Path`, `Cookie`), включая валидацию, примеры, псевдоним (например, `user-name` вместо `username`) и т.д. -/// info | Дополнительная информация +/// note | Примечание `Form` — это класс, который наследуется непосредственно от `Body`. diff --git a/docs/ru/docs/tutorial/response-model.md b/docs/ru/docs/tutorial/response-model.md index 510143d7b..bf0a6fc0a 100644 --- a/docs/ru/docs/tutorial/response-model.md +++ b/docs/ru/docs/tutorial/response-model.md @@ -72,11 +72,11 @@ FastAPI будет использовать этот `response_model` для д {* ../../docs_src/response_model/tutorial002_py310.py hl[7,9] *} -/// info | Информация +/// note | Примечание Чтобы использовать `EmailStr`, сначала установите [`email-validator`](https://github.com/JoshData/python-email-validator). -Убедитесь, что вы создали [виртуальное окружение](../virtual-environments.md), активировали его, а затем установите пакет, например: +Убедитесь, что вы создали [виртуальное окружение](../virtual-environments.md), активировали его, а затем установили пакет, например: ```console $ pip install email-validator @@ -178,7 +178,7 @@ FastAPI делает несколько вещей внутри вместе с ## Другие аннотации возвращаемых типов { #other-return-type-annotations } -Бывают случаи, когда вы возвращаете что-то, что не является валидным полем Pydantic, и аннотируете это в функции только ради поддержки инструментов (редактор кода, mypy и т.д.). +Бывают случаи, когда вы возвращаете что-то, что не является валидным полем Pydantic, и аннотируете это в функции только ради поддержки инструментов (редактор коды, mypy и т.д.). ### Возврат Response напрямую { #return-a-response-directly } @@ -251,7 +251,7 @@ FastAPI делает несколько вещей внутри вместе с } ``` -/// info | Информация +/// note | Примечание Вы также можете использовать: diff --git a/docs/ru/docs/tutorial/response-status-code.md b/docs/ru/docs/tutorial/response-status-code.md index f3144a33a..16f83cd61 100644 --- a/docs/ru/docs/tutorial/response-status-code.md +++ b/docs/ru/docs/tutorial/response-status-code.md @@ -1,6 +1,6 @@ # Статус-код ответа { #response-status-code } -Подобно тому, как вы можете задать модель/схему ответа, вы можете объявить HTTP статус-код, используемый для ответа, с помощью параметра `status_code` в любой из *операций пути*: +Подобно тому, как вы можете задать модель ответа, вы можете объявить HTTP статус-код, используемый для ответа, с помощью параметра `status_code` в любой из *операций пути*: * `@app.get()` * `@app.post()` @@ -18,7 +18,7 @@ Параметр `status_code` принимает число, обозначающее HTTP статус-код. -/// info | Информация +/// note | Примечание В качестве значения параметра `status_code` также может использоваться `IntEnum`, например, из библиотеки [`http.HTTPStatus`](https://docs.python.org/3/library/http.html#http.HTTPStatus) в Python. @@ -26,8 +26,8 @@ Это позволит: -* Возвращать указанный код статуса в ответе. -* Документировать его как код статуса ответа в OpenAPI схеме (а значит, и в пользовательских интерфейсах): +* Возвращать указанный статус-код в ответе. +* Документировать его как статус-код ответа в OpenAPI схеме (а значит, и в пользовательских интерфейсах): @@ -47,26 +47,26 @@ FastAPI знает об этом и создаст документацию Open /// -В протоколе HTTP числовой код состояния из 3 цифр отправляется как часть ответа. +В протоколе HTTP числовой статус-код из 3 цифр отправляется как часть ответа. -У кодов статуса есть названия, чтобы упростить их распознавание, но важны именно числовые значения. +У статус-кодов есть названия, чтобы упростить их распознавание, но важны именно числовые значения. Кратко: -* `100 - 199` – статус-коды информационного типа. Они редко используются разработчиками напрямую. Ответы с этими кодами не могут иметь тела. +* `100 - 199` – статус-коды информационного типа. Они редко используются разработчиками напрямую. Ответы с этими статус-кодами не могут иметь тела. * **`200 - 299`** – статус-коды, сообщающие об успешной обработке запроса. Они используются чаще всего. - * `200` – это код статуса ответа по умолчанию, который означает, что все прошло "OK". + * `200` – это статус-код по умолчанию, который означает, что все прошло "OK". * Другим примером может быть статус `201`, "Created". Он обычно используется после создания новой записи в базе данных. * Особый случай – `204`, "No Content". Этот статус ответа используется, когда нет содержимого для возврата клиенту, и поэтому ответ не должен иметь тела. -* **`300 - 399`** – статус-коды, сообщающие о перенаправлениях. Ответы с этими кодами статуса могут иметь или не иметь тело, за исключением ответов со статусом `304`, "Not Modified", у которых не должно быть тела. +* **`300 - 399`** – статус-коды, сообщающие о перенаправлениях. Ответы с этими статус-кодами могут иметь или не иметь тело, за исключением ответов со статусом `304`, "Not Modified", у которых не должно быть тела. * **`400 - 499`** – статус-коды, сообщающие о клиентской ошибке. Это ещё одна наиболее часто используемая категория. * Пример – код `404` для статуса "Not Found". * Для общих ошибок со стороны клиента можно просто использовать код `400`. -* `500 - 599` – статус-коды, сообщающие о серверной ошибке. Они почти никогда не используются разработчиками напрямую. Когда что-то идет не так в какой-то части кода вашего приложения или на сервере, он автоматически вернёт один из этих кодов статуса. +* `500 - 599` – статус-коды, сообщающие о серверной ошибке. Они почти никогда не используются разработчиками напрямую. Когда что-то идет не так в какой-то части кода вашего приложения или на сервере, он автоматически вернёт один из этих статус-кодов. /// tip | Подсказка -Чтобы узнать больше о HTTP кодах статуса и о том, для чего каждый из них предназначен, ознакомьтесь с [MDN документацией об HTTP статус-кодах](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status). +Чтобы узнать больше о HTTP статус-кодах и о том, для чего каждый из них предназначен, ознакомьтесь с [MDN документацией об HTTP статус-кодах](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status). /// @@ -76,7 +76,7 @@ FastAPI знает об этом и создаст документацию Open {* ../../docs_src/response_status_code/tutorial001_py310.py hl[6] *} -`201` – это код статуса "Создано". +`201` – это статус-код для "Created". Но вам не обязательно запоминать, что означает каждый из этих кодов. @@ -84,7 +84,7 @@ FastAPI знает об этом и создаст документацию Open {* ../../docs_src/response_status_code/tutorial002_py310.py hl[1,6] *} -Они содержат те же числовые значения, но позволяют использовать автозавершение редактора кода для выбора кода статуса: +Они существуют только для удобства, содержат те же числовые значения, но позволяют использовать автозавершение редактора кода для выбора статус-кода: diff --git a/docs/ru/docs/tutorial/schema-extra-example.md b/docs/ru/docs/tutorial/schema-extra-example.md index ee2f5b991..917e80838 100644 --- a/docs/ru/docs/tutorial/schema-extra-example.md +++ b/docs/ru/docs/tutorial/schema-extra-example.md @@ -1,4 +1,4 @@ -# Объявление примеров данных запроса { #declare-request-example-data } +# Объявление примеров данных HTTP-запроса { #declare-request-example-data } Вы можете объявлять примеры данных, которые ваше приложение может получать. @@ -12,7 +12,7 @@ Эта дополнительная информация будет добавлена как есть в выходную **JSON Schema** этой модели и будет использоваться в документации API. -Вы можете использовать атрибут `model_config`, который принимает `dict`, как описано в [Документация Pydantic: Конфигурация](https://docs.pydantic.dev/latest/api/config/). +Вы можете использовать атрибут `model_config`, который принимает `dict`, как описано в [документации Pydantic: Конфигурация](https://docs.pydantic.dev/latest/api/config/). Вы можете задать `"json_schema_extra"` с `dict`, содержащим любые дополнительные данные, которые вы хотите видеть в сгенерированной JSON Schema, включая `examples`. @@ -24,9 +24,9 @@ /// -/// info | Информация +/// note | Примечание -OpenAPI 3.1.0 (используется начиная с FastAPI 0.99.0) добавил поддержку `examples`, который является частью стандарта **JSON Schema**. +OpenAPI 3.1.0 (используется начиная с FastAPI 0.99.0) добавил поддержку `examples`, которое является частью стандарта **JSON Schema**. До этого поддерживалось только ключевое слово `example` с одним примером. Оно всё ещё поддерживается в OpenAPI 3.1.0, но помечено как устаревшее и не является частью стандарта JSON Schema. Поэтому рекомендуется мигрировать `example` на `examples`. 🤓 @@ -80,13 +80,13 @@ OpenAPI 3.1.0 (используется начиная с FastAPI 0.99.0) доб Ещё до того как **JSON Schema** поддержала `examples`, в OpenAPI была поддержка другого поля, также называемого `examples`. -Эти **специфические для OpenAPI** `examples` находятся в другой секции спецификации OpenAPI. Они находятся в **подробностях для каждой операции пути (обработчика пути)**, а не внутри каждого объекта Schema. +Эти **специфические для OpenAPI** `examples` находятся в другой секции спецификации OpenAPI. Они находятся в **подробностях каждой *операции пути***, а не внутри каждой JSON Schema. И Swagger UI уже какое‑то время поддерживает именно это поле `examples`. Поэтому вы можете использовать его, чтобы **отобразить** разные **примеры в UI документации**. Структура этого специфичного для OpenAPI поля `examples` — это `dict` с **несколькими примерами** (вместо `list`), каждый с дополнительной информацией, которая также будет добавлена в **OpenAPI**. -Это не помещается внутрь каждого объекта Schema в OpenAPI, это находится снаружи, непосредственно на уровне самой *операции пути*. +Это не помещается внутрь каждой JSON Schema, содержащейся в OpenAPI, это находится снаружи, непосредственно на уровне самой *операции пути*. ### Использование параметра `openapi_examples` { #using-the-openapi-examples-parameter } @@ -155,7 +155,7 @@ OpenAPI также добавила поля `example` и `examples` в друг * `File()` * `Form()` -/// info | Информация +/// note | Примечание Этот старый специфичный для OpenAPI параметр `examples` теперь называется `openapi_examples`, начиная с FastAPI `0.103.0`. @@ -171,7 +171,7 @@ OpenAPI также добавила поля `example` и `examples` в друг Это новое поле `examples` в JSON Schema — это **просто `list`** примеров, а не dict с дополнительными метаданными, как в других местах OpenAPI (описанных выше). -/// info | Информация +/// note | Примечание Даже после того как OpenAPI 3.1.0 была выпущена с этой новой, более простой интеграцией с JSON Schema, какое‑то время Swagger UI, инструмент, предоставляющий автоматическую документацию, не поддерживал OpenAPI 3.1.0 (поддержка появилась начиная с версии 5.0.0 🎉). diff --git a/docs/ru/docs/tutorial/security/first-steps.md b/docs/ru/docs/tutorial/security/first-steps.md index c55e832f4..35d63c843 100644 --- a/docs/ru/docs/tutorial/security/first-steps.md +++ b/docs/ru/docs/tutorial/security/first-steps.md @@ -24,7 +24,7 @@ ## Запуск { #run-it } -/// info | Дополнительная информация +/// note | Примечание Пакет [`python-multipart`](https://github.com/Kludex/python-multipart) автоматически устанавливается вместе с **FastAPI**, если вы запускаете команду `pip install "fastapi[standard]"`. @@ -60,7 +60,7 @@ $ fastapi dev -/// check | Кнопка авторизации! +/// tip | Кнопка авторизации! У вас уже появилась новая кнопка «Authorize». @@ -118,7 +118,7 @@ OAuth2 был спроектирован так, чтобы бэкенд или В этом примере мы будем использовать **OAuth2**, с потоком **Password**, используя токен **Bearer**. Для этого мы используем класс `OAuth2PasswordBearer`. -/// info | Дополнительная информация +/// note | Примечание Токен «bearer» — не единственный вариант. @@ -148,7 +148,7 @@ OAuth2 был спроектирован так, чтобы бэкенд или Скоро мы также создадим и саму операцию пути. -/// info | Дополнительная информация +/// note | Примечание Если вы очень строгий «питонист», вам может не понравиться стиль имени параметра `tokenUrl` вместо `token_url`. @@ -176,7 +176,7 @@ oauth2_scheme(some, parameters) **FastAPI** будет знать, что может использовать эту зависимость для определения «схемы безопасности» в схеме OpenAPI (и в автоматической документации по API). -/// info | Технические детали +/// note | Технические детали **FastAPI** будет знать, что может использовать класс `OAuth2PasswordBearer` (объявленный в зависимости) для определения схемы безопасности в OpenAPI, потому что он наследуется от `fastapi.security.oauth2.OAuth2`, который, в свою очередь, наследуется от `fastapi.security.base.SecurityBase`. @@ -186,9 +186,9 @@ oauth2_scheme(some, parameters) ## Что он делает { #what-it-does } -Он будет искать в запросе заголовок `Authorization`, проверять, что его значение — это `Bearer ` плюс некоторый токен, и вернет токен как `str`. +Он будет искать в HTTP-запросе HTTP-заголовок `Authorization`, проверять, что его значение — это `Bearer ` плюс некоторый токен, и вернет токен как `str`. -Если заголовок `Authorization` отсутствует или его значение не содержит токен `Bearer `, он сразу ответит ошибкой со статус-кодом 401 (`UNAUTHORIZED`). +Если HTTP-заголовок `Authorization` отсутствует или его значение не содержит токен `Bearer `, он сразу ответит ошибкой со статус-кодом 401 (`UNAUTHORIZED`). Вам даже не нужно проверять наличие токена, чтобы вернуть ошибку. Вы можете быть уверены: если ваша функция была выполнена, в этом токене будет `str`. diff --git a/docs/ru/docs/tutorial/security/get-current-user.md b/docs/ru/docs/tutorial/security/get-current-user.md index 8388b672c..8beebc51d 100644 --- a/docs/ru/docs/tutorial/security/get-current-user.md +++ b/docs/ru/docs/tutorial/security/get-current-user.md @@ -14,7 +14,7 @@ Точно так же, как мы используем Pydantic для объявления тел запросов, мы можем использовать его где угодно: -{* ../../docs_src/security/tutorial002_an_py310.py hl[5,12:6] *} +{* ../../docs_src/security/tutorial002_an_py310.py hl[5,12:16] *} ## Создать зависимость `get_current_user` { #create-a-get-current-user-dependency } @@ -30,7 +30,7 @@ ## Получить пользователя { #get-the-user } -`get_current_user` будет использовать созданную нами (ненастоящую) служебную функцию, которая принимает токен типа `str` и возвращает нашу Pydantic-модель `User`: +`get_current_user` будет использовать созданную нами (ненастоящую) вспомогательную функцию, которая принимает токен типа `str` и возвращает нашу Pydantic-модель `User`: {* ../../docs_src/security/tutorial002_an_py310.py hl[19:22,26:27] *} @@ -52,9 +52,9 @@ /// -/// check | Заметка +/// tip | Подсказка -То, как устроена эта система зависимостей, позволяет иметь разные зависимости, которые возвращают модель `User`. +То, как устроена эта система зависимостей, позволяет иметь разные зависимости (разные "dependables"), которые все возвращают модель `User`. Мы не ограничены наличием только одной зависимости, которая может возвращать такой тип данных. @@ -78,7 +78,7 @@ ## Размер кода { #code-size } -Этот пример может показаться многословным. Имейте в виду, что в одном файле мы смешиваем безопасность, модели данных, служебные функции и *операции пути*. +Этот пример может показаться многословным. Имейте в виду, что в одном файле мы смешиваем безопасность, модели данных, вспомогательные функции и *операции пути*. Но вот ключевой момент. diff --git a/docs/ru/docs/tutorial/security/oauth2-jwt.md b/docs/ru/docs/tutorial/security/oauth2-jwt.md index e3729dfc8..63492e630 100644 --- a/docs/ru/docs/tutorial/security/oauth2-jwt.md +++ b/docs/ru/docs/tutorial/security/oauth2-jwt.md @@ -28,7 +28,7 @@ eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4 ## Установка `PyJWT` { #install-pyjwt } -Нам необходимо установить `pyjwt` для генерации и проверки JWT-токенов на языке Python. +Нам необходимо установить `PyJWT` для генерации и проверки JWT-токенов на языке Python. Убедитесь, что вы создали [виртуальное окружение](../../virtual-environments.md), активируйте его, а затем установите `pyjwt`: @@ -42,7 +42,7 @@ $ pip install pyjwt
-/// info | Дополнительная информация +/// note | Примечание Если вы планируете использовать алгоритмы цифровой подписи, такие как RSA или ECDSA, вам следует установить зависимость библиотеки криптографии `pyjwt[crypto]`. @@ -110,9 +110,9 @@ pwdlib также поддерживает алгоритм хешировани /// -Создайте служебную функцию для хэширования пароля, поступающего от пользователя. +Создайте вспомогательную функцию для хэширования пароля, поступающего от пользователя. -А затем создайте другую — для проверки соответствия полученного пароля и хранимого хэша. +А затем создайте другую вспомогательную функцию — для проверки соответствия полученного пароля и хранимого хэша. И еще одну — для аутентификации и возврата пользователя. @@ -120,15 +120,15 @@ pwdlib также поддерживает алгоритм хешировани Когда `authenticate_user` вызывается с именем пользователя, которого нет в базе данных, мы все равно запускаем `verify_password` с использованием фиктивного хэша. -Это гарантирует, что эндпоинт отвечает примерно за одно и то же время вне зависимости от того, существует имя пользователя или нет, предотвращая тайминговые атаки (атака по времени), с помощью которых можно было бы перечислять существующие имена пользователей. +Это гарантирует, что эндпоинт отвечает примерно за одно и то же время вне зависимости от того, существует имя пользователя или нет, предотвращая **тайминговые атаки** (атаки по времени), с помощью которых можно было бы перечислять существующие имена пользователей. -/// note | Технические детали +/// note | Примечание Если проверить новую (фальшивую) базу данных `fake_users_db`, то можно увидеть, как теперь выглядит хэшированный пароль: `"$argon2id$v=19$m=65536,t=3,p=4$wagCPXjifgvUFBzq4hqe3w$CYaIb8sB+wtD+Vu/P4uod1+Qof8h+1g7bbDlBID48Rc"`. /// -## Работа с JWT токенами { #handle-jwt-tokens } +## Работа с JWT-токенами { #handle-jwt-tokens } Импортируйте установленные модули. @@ -154,7 +154,7 @@ $ openssl rand -hex 32 Определите Pydantic-модель, которая будет использоваться для формирования ответа на запрос на получение токена. -Создайте служебную функцию для генерации нового токена доступа. +Создайте вспомогательную функцию для генерации нового токена доступа. {* ../../docs_src/security/tutorial004_an_py310.py hl[4,7,13:15,29:31,82:90] *} @@ -172,7 +172,7 @@ $ openssl rand -hex 32 Создайте `timedelta` со временем истечения срока действия токена. -Создайте реальный токен доступа JWT и верните его +Создайте реальный токен доступа JWT и верните его. {* ../../docs_src/security/tutorial004_an_py310.py hl[121:136] *} @@ -188,13 +188,13 @@ JWT может использоваться и для других целей, Затем вы могли бы добавить права доступа к этой сущности, например "управлять" (для автомобиля) или "редактировать" (для блога). -Затем вы могли бы передать этот JWT-токен пользователю (или боту), и они использовали бы его для выполнения определенных действий (управление автомобилем или редактирование запись в блоге), даже не имея учетной записи, просто используя JWT-токен, сгенерированный вашим API. +Затем вы могли бы передать этот JWT-токен пользователю (или боту), и они использовали бы его для выполнения определенных действий (управление автомобилем или редактирование записи в блоге), даже не имея учетной записи, просто используя JWT-токен, сгенерированный вашим API. Используя эти идеи, JWT можно применять для гораздо более сложных сценариев. В отдельных случаях несколько сущностей могут иметь один и тот же идентификатор, скажем, `foo` (пользователь `foo`, автомобиль `foo` и запись в блоге `foo`). -Поэтому, чтобы избежать коллизий идентификаторов, при создании JWT-токена для пользователя можно добавить префикс `username` к значению ключа `sub`. Таким образом, в данном примере значение `sub` было бы `username:johndoe`. +Поэтому, чтобы избежать коллизий идентификаторов, при создании JWT-токена для пользователя можно добавить префикс `username:` к значению ключа `sub`. Таким образом, в данном примере значение `sub` могло бы быть: `username:johndoe`. Важно помнить, что ключ `sub` должен иметь уникальный идентификатор для всего приложения и представлять собой строку. @@ -213,7 +213,7 @@ JWT может использоваться и для других целей, Username: `johndoe` Password: `secret` -/// check | Проверка +/// tip | Подсказка Обратите внимание, что нигде в коде не используется открытый текст пароля "`secret`", мы используем только его хэшированную версию. @@ -238,7 +238,7 @@ Password: `secret` -/// note | Техническая информация +/// note | Примечание Обратите внимание на HTTP-заголовок `Authorization`, значение которого начинается с `Bearer `. diff --git a/docs/ru/docs/tutorial/security/simple-oauth2.md b/docs/ru/docs/tutorial/security/simple-oauth2.md index 4ef5109e4..5ce89730c 100644 --- a/docs/ru/docs/tutorial/security/simple-oauth2.md +++ b/docs/ru/docs/tutorial/security/simple-oauth2.md @@ -14,7 +14,7 @@ OAuth2 определяет, что при использовании "password А ваши модели баз данных могут использовать любые другие имена. -Но для логин-операции пути нам нужно использовать именно эти имена, чтобы быть совместимыми со спецификацией (и иметь возможность, например, использовать встроенную систему документации API). +Но для *операции пути* входа в систему нам нужно использовать именно эти имена, чтобы быть совместимыми со спецификацией (и иметь возможность, например, использовать встроенную систему документации API). В спецификации также указано, что `username` и `password` должны передаваться в виде данных формы (так что никакого JSON здесь нет). @@ -32,7 +32,7 @@ OAuth2 определяет, что при использовании "password * `instagram_basic` используется Facebook / Instagram. * `https://www.googleapis.com/auth/drive` используется Google. -/// info | Дополнительная информация +/// note | Примечание В OAuth2 "scope" — это просто строка, которая указывает требуемое конкретное разрешение. Не имеет значения, содержит ли она другие символы, например `:`, или является ли это URL. @@ -68,7 +68,7 @@ OAuth2 определяет, что при использовании "password * Необязательное поле `client_id` (в нашем примере оно не нужно). * Необязательное поле `client_secret` (в нашем примере оно не нужно). -/// info | Дополнительная информация +/// note | Примечание `OAuth2PasswordRequestForm` — это не специальный класс для **FastAPI**, как `OAuth2PasswordBearer`. `OAuth2PasswordBearer` сообщает **FastAPI**, что это схема безопасности. Поэтому она добавляется в OpenAPI соответствующим образом. @@ -88,7 +88,7 @@ OAuth2 определяет, что при использовании "password Теперь получим данные о пользователе из (ненастоящей) базы данных, используя `username` из поля формы. -Если такого пользователя нет, то мы возвращаем ошибку "Incorrect username or password" (неверное имя пользователя или пароль). +Если такого пользователя нет, то мы возвращаем ошибку "Incorrect username or password". Для ошибки используем исключение `HTTPException`: @@ -136,13 +136,13 @@ UserInDB( ) ``` -/// info | Дополнительная информация -Более полное объяснение `**user_dict` можно найти в [документации к **Дополнительным моделям**](../extra-models.md#about-user-in-dict). +/// note | Примечание +Более полное объяснение `**user_dict` можно найти в [документации к **Дополнительным моделям**](../extra-models.md#about-user-in-model-dump). /// ## Возврат токена { #return-the-token } -Ответ операции пути `/token` должен быть объектом JSON. +Ответ эндпоинта `token` должен быть объектом JSON. В нём должен быть `token_type`. В нашем случае, поскольку мы используем токены типа "Bearer", тип токена должен быть `bearer`. @@ -151,7 +151,7 @@ UserInDB( В этом простом примере мы намеренно поступим небезопасно и вернём тот же `username` в качестве токена. /// tip | Подсказка -В следующей главе вы увидите реальную защищённую реализацию с хешированием паролей и токенами JWT. +В следующей главе вы увидите реальную защищённую реализацию с хешированием паролей и токенами JWT. Но пока давайте сосредоточимся на необходимых нам деталях. /// @@ -182,7 +182,7 @@ UserInDB( {* ../../docs_src/security/tutorial003_an_py310.py hl[58:66,69:74,94] *} -/// info | Дополнительная информация +/// note | Примечание Дополнительный HTTP-заголовок `WWW-Authenticate` со значением `Bearer`, который мы здесь возвращаем, также является частью спецификации. Любой HTTP статус-код 401 "UNAUTHORIZED" должен также возвращать заголовок `WWW-Authenticate`. @@ -266,8 +266,8 @@ UserInDB( Теперь у вас есть инструменты для реализации полноценной системы безопасности на основе `username` и `password` для вашего API. -Используя эти средства, можно сделать систему безопасности совместимой с любой базой данных и с любой пользовательской или моделью данных. +Используя эти средства, можно сделать систему безопасности совместимой с любой базой данных и с любой моделью пользователя или моделью данных. Единственная деталь, которой не хватает, — система пока ещё не "защищена" по-настоящему. -В следующей главе вы увидите, как использовать библиотеку безопасного хеширования паролей и токены JWT. +В следующей главе вы увидите, как использовать библиотеку безопасного хеширования паролей и токены JWT. diff --git a/docs/ru/docs/tutorial/server-sent-events.md b/docs/ru/docs/tutorial/server-sent-events.md index be6bd2366..ea49f85c8 100644 --- a/docs/ru/docs/tutorial/server-sent-events.md +++ b/docs/ru/docs/tutorial/server-sent-events.md @@ -4,7 +4,7 @@ Это похоже на [Стриминг JSON Lines](stream-json-lines.md), но использует формат `text/event-stream`, который нативно поддерживается браузерами через [`EventSource` API](https://developer.mozilla.org/en-US/docs/Web/API/EventSource). -/// info | Информация +/// note | Примечание Добавлено в FastAPI 0.135.0. @@ -29,7 +29,7 @@ SSE часто используют для стриминга ответов И /// tip | Совет -Если вам нужно стримить бинарные данные, например видео или аудио, посмотрите расширенное руководство: [Stream Data](../advanced/stream-data.md). +Если вам нужно стримить бинарные данные, например видео или аудио, посмотрите расширенное руководство: [Потоковая передача данных](../advanced/stream-data.md). /// @@ -113,7 +113,7 @@ SSE работает с любым HTTP-методом, не только с `GE FastAPI из коробки реализует некоторые лучшие практики для SSE. -- Отправлять комментарий «ping» для поддержания соединения («keep alive») каждые 15 секунд, когда нет сообщений, чтобы предотвратить закрытие соединения некоторыми прокси, как рекомендовано в [HTML specification: Server-Sent Events](https://html.spec.whatwg.org/multipage/server-sent-events.html#authoring-notes). +- Отправлять комментарий «ping» для поддержания соединения («keep alive») каждые 15 секунд, когда нет сообщений, чтобы предотвратить закрытие соединения некоторыми прокси, как рекомендовано в [Спецификация HTML: Server-Sent Events](https://html.spec.whatwg.org/multipage/server-sent-events.html#authoring-notes). - Устанавливать заголовок `Cache-Control: no-cache`, чтобы предотвратить кэширование потока. - Устанавливать специальный заголовок `X-Accel-Buffering: no`, чтобы предотвратить буферизацию в некоторых прокси, например Nginx. diff --git a/docs/ru/docs/tutorial/sql-databases.md b/docs/ru/docs/tutorial/sql-databases.md index ae8637338..bf2e16fb9 100644 --- a/docs/ru/docs/tutorial/sql-databases.md +++ b/docs/ru/docs/tutorial/sql-databases.md @@ -1,6 +1,6 @@ # SQL (реляционные) базы данных { #sql-relational-databases } -**FastAPI** не требует использовать SQL (реляционную) базу данных. Но вы можете использовать любую базу данных, которую хотите. +**FastAPI** не требует использовать SQL (реляционную) базу данных. Но вы можете использовать **любую базу данных**, которую хотите. Здесь мы рассмотрим пример с использованием [SQLModel](https://sqlmodel.tiangolo.com/). @@ -8,7 +8,7 @@ /// tip | Подсказка -Вы можете использовать любую другую библиотеку для работы с SQL или NoSQL базами данных (иногда их называют "ORMs"), FastAPI ничего не навязывает. 😎 +Вы можете использовать любую другую библиотеку для работы с SQL или NoSQL базами данных (иногда их называют "ORMs"), FastAPI ничего не навязывает. 😎 /// @@ -119,7 +119,7 @@ $ pip install sqlmodel Так как каждая модель SQLModel также является моделью Pydantic, вы можете использовать её в тех же **аннотациях типов**, в которых используете модели Pydantic. -Например, если вы объявите параметр типа `Hero`, он будет прочитан из **JSON body (тела запроса)**. +Например, если вы объявите параметр типа `Hero`, он будет прочитан из **JSON-тела запроса**. Аналогично вы можете объявить её как **тип возвращаемого значения** функции, и тогда форма данных отобразится в автоматически сгенерированном UI документации API. diff --git a/docs/ru/docs/tutorial/static-files.md b/docs/ru/docs/tutorial/static-files.md index dfcc77b6f..84084ffac 100644 --- a/docs/ru/docs/tutorial/static-files.md +++ b/docs/ru/docs/tutorial/static-files.md @@ -2,6 +2,14 @@ Вы можете предоставлять статические файлы автоматически из директории, используя `StaticFiles`. +/// tip | Совет + +Если вам нужно разместить фронтенд, используйте вместо этого `app.frontend()`, подробнее читайте в разделе [Фронтенд](frontend.md). + +`app.frontend()` использует `StaticFiles` под капотом, с несколькими дополнительными преимуществами для фронтендов, такими как обработка маршрутизации на стороне клиента. + +/// + ## Использование `StaticFiles` { #use-staticfiles } * Импортируйте `StaticFiles`. @@ -21,8 +29,7 @@ "Монтирование" означает добавление полноценного "независимого" приложения на определённый путь, которое затем обрабатывает все подпути. -Это отличается от использования `APIRouter`, так как примонтированное приложение является полностью независимым. -OpenAPI и документация из вашего главного приложения не будут содержать ничего из примонтированного приложения, и т.д. +Это отличается от использования `APIRouter`, так как примонтированное приложение является полностью независимым. OpenAPI и документация из вашего главного приложения не будут содержать ничего из примонтированного приложения, и т.д. Вы можете прочитать больше об этом в [Расширенном руководстве пользователя](../advanced/index.md). diff --git a/docs/ru/docs/tutorial/stream-json-lines.md b/docs/ru/docs/tutorial/stream-json-lines.md index d8bb9132b..a9390685e 100644 --- a/docs/ru/docs/tutorial/stream-json-lines.md +++ b/docs/ru/docs/tutorial/stream-json-lines.md @@ -2,7 +2,7 @@ У вас может быть последовательность данных, которую вы хотите отправлять в «**потоке**». Это можно сделать с помощью **JSON Lines**. -/// info | Информация +/// note | Примечание Добавлено в FastAPI 0.134.0. @@ -48,7 +48,7 @@ sequenceDiagram Это очень похоже на JSON-массив (эквивалент списка Python), но вместо того чтобы быть обернутым в `[]` и иметь `,` между элементами, здесь **один JSON-объект на строку**, они разделены символом новой строки. -/// info | Информация +/// note | Примечание Важный момент в том, что ваше приложение сможет по очереди производить каждую строку, пока клиент потребляет предыдущие строки. diff --git a/docs/ru/docs/tutorial/testing.md b/docs/ru/docs/tutorial/testing.md index aef7b86de..d6038a3de 100644 --- a/docs/ru/docs/tutorial/testing.md +++ b/docs/ru/docs/tutorial/testing.md @@ -8,7 +8,7 @@ ## Использование класса `TestClient` { #using-testclient } -/// info | Информация +/// note | Примечание Для использования класса `TestClient` сначала установите [`httpx`](https://www.python-httpx.org). @@ -90,7 +90,7 @@ $ pip install httpx │   └── test_main.py ``` -Так как оба файла находятся в одной директории, для импорта объекта приложения из файла `main` в файл `test_main` Вы можете использовать относительный импорт: +Так как этот файл находится в том же пакете, для импорта объекта `app` из модуля `main` (`main.py`) Вы можете использовать относительный импорт: {* ../../docs_src/app_testing/app_a_py310/test_main.py hl[3] *} @@ -113,7 +113,7 @@ $ pip install httpx │   └── test_main.py ``` -Предположим, что в файле `main.py` с приложением **FastAPI** есть несколько **операций пути**. +Предположим, что теперь в файле `main.py` с приложением **FastAPI** есть несколько других **операций пути**. В нём описана операция `GET`, которая может вернуть ошибку. @@ -125,26 +125,26 @@ $ pip install httpx ### Расширенный файл тестов { #extended-testing-file } -Теперь обновим файл `test_main.py`, добавив в него тестов: +Теперь можно обновить файл `test_main.py`, добавив в него расширенные тесты: {* ../../docs_src/app_testing/app_b_an_py310/test_main.py *} -Если Вы не знаете, как передать информацию в запросе, можете воспользоваться поисковиком (погуглить) и задать вопрос: "Как передать информацию в запросе с помощью `httpx`", можно даже спросить: "Как передать информацию в запросе с помощью `requests`", поскольку дизайн HTTPX основан на дизайне Requests. +Если Вы не знаете, как передать информацию в запросе, можете воспользоваться поиском (Google) и задать вопрос: "Как передать информацию в запросе с помощью `httpx`", можно даже спросить: "Как передать информацию в запросе с помощью `requests`", поскольку дизайн HTTPX основан на дизайне Requests. Затем Вы просто применяете найденные ответы в тестах. Например: -* Передаёте *path*-параметры или *query*-параметры, вписав их непосредственно в строку URL. +* Чтобы передать *path*-параметр или *query*-параметр, добавьте его непосредственно в URL. * Передаёте JSON в теле запроса, передав Python-объект (например: `dict`) через именованный параметр `json`. -* Если же Вам необходимо отправить *форму с данными* вместо JSON, то используйте параметр `data` вместо `json`. +* Если же Вам необходимо отправить *данные формы* вместо JSON, то используйте параметр `data` вместо `json`. * Для передачи *HTTP-заголовков*, передайте объект `dict` через параметр `headers`. * Для передачи *cookies* также передайте `dict`, но через параметр `cookies`. Для получения дополнительной информации о передаче данных на бэкенд с помощью `httpx` или `TestClient` ознакомьтесь с [документацией HTTPX](https://www.python-httpx.org). -/// info | Информация +/// note | Примечание Обратите внимание, что `TestClient` принимает данные, которые можно конвертировать в JSON, но не модели Pydantic. diff --git a/docs/ru/docs/virtual-environments.md b/docs/ru/docs/virtual-environments.md index 119f3645e..b7c750842 100644 --- a/docs/ru/docs/virtual-environments.md +++ b/docs/ru/docs/virtual-environments.md @@ -811,7 +811,7 @@ $ cd ~/code/prisoner-of-azkaban $ python main.py -// Error importing sirius, it's not installed 😱 +// Ошибка при импорте sirius, он не установлен 😱 Traceback (most recent call last): File "main.py", line 1, in import sirius diff --git a/docs/tr/docs/_llm-test.md b/docs/tr/docs/_llm-test.md index bc3dc8977..049aa2676 100644 --- a/docs/tr/docs/_llm-test.md +++ b/docs/tr/docs/_llm-test.md @@ -37,7 +37,7 @@ Code snippet'lerin içeriği olduğu gibi bırakılmalıdır. Dün bir arkadaşım şunu yazdı: "If you spell incorrectly correctly, you have spelled it incorrectly". Ben de şunu yanıtladım: "Correct, but 'incorrectly' is incorrectly not '"incorrectly"'". -/// note +/// note | Not LLM muhtemelen bunu yanlış çevirecektir. Yeniden çeviri yapıldığında düzeltilmiş çeviriyi koruyup korumadığı önemlidir. @@ -124,7 +124,7 @@ Code block'ların içindeki code değiştirilmemelidir; tek istisna yorumlardır //// tab | Test -/// note +/// note | Not Bazı metin /// @@ -132,15 +132,15 @@ Bazı metin Bazı metin /// -/// tip +/// tip | İpucu Bazı metin /// -/// warning +/// warning | Uyarı Bazı metin /// -/// danger +/// danger | Tehlike Bazı metin /// diff --git a/docs/tr/docs/advanced/additional-responses.md b/docs/tr/docs/advanced/additional-responses.md index 92999b287..8bf1ea7cd 100644 --- a/docs/tr/docs/advanced/additional-responses.md +++ b/docs/tr/docs/advanced/additional-responses.md @@ -34,7 +34,7 @@ Bu response `dict`'lerinin her birinde, `response_model`'e benzer şekilde bir P /// -/// info | Bilgi +/// note | Not `model` anahtarı OpenAPI'nin bir parçası değildir. @@ -183,7 +183,7 @@ Görseli `FileResponse` kullanarak doğrudan döndürmeniz gerektiğine dikkat e /// -/// info | Bilgi +/// note | Not `responses` parametrenizde açıkça farklı bir media type belirtmediğiniz sürece FastAPI, response'un ana response class'ı ile aynı media type'a sahip olduğunu varsayar (varsayılan `application/json`). diff --git a/docs/tr/docs/advanced/additional-status-codes.md b/docs/tr/docs/advanced/additional-status-codes.md index 6db570aef..21d113ffe 100644 --- a/docs/tr/docs/advanced/additional-status-codes.md +++ b/docs/tr/docs/advanced/additional-status-codes.md @@ -1,5 +1,6 @@ # Ek Status Code'ları { #additional-status-codes } + Varsayılan olarak **FastAPI**, response'ları bir `JSONResponse` kullanarak döndürür; *path operation*'ınızdan döndürdüğünüz içeriği bu `JSONResponse`'un içine yerleştirir. Varsayılan status code'u veya *path operation* içinde sizin belirlediğiniz status code'u kullanır. diff --git a/docs/tr/docs/advanced/advanced-dependencies.md b/docs/tr/docs/advanced/advanced-dependencies.md index 24453f689..86a15a6c1 100644 --- a/docs/tr/docs/advanced/advanced-dependencies.md +++ b/docs/tr/docs/advanced/advanced-dependencies.md @@ -78,7 +78,7 @@ Bu detaylar, özellikle 0.121.0'dan eski bir FastAPI uygulamanız varsa ve `yiel ### `yield` ve `scope` ile dependency'ler { #dependencies-with-yield-and-scope } -0.121.0 sürümünde FastAPI, `Depends(scope="function")` desteğini ekledi. +0.121.0 sürümünde FastAPI, `yield` kullanan dependency'ler için `Depends(scope="function")` desteğini ekledi. `Depends(scope="function")` kullanıldığında, `yield` sonrasındaki çıkış kodu, *path operation function* biter bitmez, response client'a geri gönderilmeden önce çalıştırılır. @@ -98,7 +98,7 @@ Bu değişiklik aynı zamanda şunu da ifade ediyordu: `StreamingResponse` dönd Bu davranış 0.118.0'da geri alındı ve `yield` sonrasındaki çıkış kodunun, response gönderildikten sonra çalıştırılması sağlandı. -/// info | Bilgi +/// note | Not Aşağıda göreceğiniz gibi, bu davranış 0.106.0 sürümünden önceki davranışa oldukça benzer; ancak köşe durumlar için çeşitli iyileştirmeler ve bug fix'ler içerir. diff --git a/docs/tr/docs/advanced/custom-response.md b/docs/tr/docs/advanced/custom-response.md index 73ac29b16..537290eb5 100644 --- a/docs/tr/docs/advanced/custom-response.md +++ b/docs/tr/docs/advanced/custom-response.md @@ -41,7 +41,7 @@ Kısaca, en yüksek performansı istiyorsanız bir [Response Model](../tutorial/ {* ../../docs_src/custom_response/tutorial002_py310.py hl[2,7] *} -/// info | Bilgi +/// note | Not `response_class` parametresi, response’un "media type"’ını tanımlamak için de kullanılır. @@ -65,7 +65,7 @@ Yukarıdaki örneğin aynısı, bu sefer bir `HTMLResponse` döndürerek, şöyl /// -/// info | Bilgi +/// note | Not Elbette gerçek `Content-Type` header’ı, status code vb. değerler, döndürdüğünüz `Response` objesinden gelir. diff --git a/docs/tr/docs/advanced/dataclasses.md b/docs/tr/docs/advanced/dataclasses.md index 998ccea8a..9f79a6cbe 100644 --- a/docs/tr/docs/advanced/dataclasses.md +++ b/docs/tr/docs/advanced/dataclasses.md @@ -1,5 +1,6 @@ # Dataclass Kullanımı { #using-dataclasses } + FastAPI, **Pydantic** üzerine inşa edilmiştir ve request/response tanımlamak için Pydantic model'lerini nasıl kullanacağınızı gösteriyordum. Ancak FastAPI, [`dataclasses`](https://docs.python.org/3/library/dataclasses.html) kullanmayı da aynı şekilde destekler: @@ -18,7 +19,7 @@ Ve elbette aynı özellikleri destekler: Bu, Pydantic model'lerinde olduğu gibi çalışır. Aslında arka planda da aynı şekilde, Pydantic kullanılarak yapılır. -/// info | Bilgi +/// note | Not Dataclass'ların, Pydantic model'lerinin yapabildiği her şeyi yapamadığını unutmayın. diff --git a/docs/tr/docs/advanced/events.md b/docs/tr/docs/advanced/events.md index c66342213..4c96b2296 100644 --- a/docs/tr/docs/advanced/events.md +++ b/docs/tr/docs/advanced/events.md @@ -2,7 +2,7 @@ Uygulama **başlamadan** önce çalıştırılması gereken mantığı (kodu) tanımlayabilirsiniz. Bu, bu kodun **bir kez**, uygulama **request almaya başlamadan önce** çalıştırılacağı anlamına gelir. -Benzer şekilde, uygulama **kapanırken** çalıştırılması gereken mantığı (kodu) da tanımlayabilirsiniz. Bu durumda bu kod, muhtemelen **çok sayıda request** işlendi **sonra**, **bir kez** çalıştırılır. +Benzer şekilde, uygulama **kapanırken** çalıştırılması gereken mantığı (kodu) da tanımlayabilirsiniz. Bu durumda bu kod, muhtemelen **çok sayıda request** işlendikten **sonra**, **bir kez** çalıştırılır. Bu kod, uygulama request almaya **başlamadan** önce ve request’leri işlemeyi **bitirdikten** hemen sonra çalıştığı için, uygulamanın tüm **lifespan**’ını (birazdan "lifespan" kelimesi önemli olacak 😉) kapsar. @@ -120,7 +120,7 @@ Uygulama kapanırken çalıştırılacak bir fonksiyon eklemek için, `"shutdown Burada `shutdown` event handler fonksiyonu, `log.txt` dosyasına `"Application shutdown"` satırını yazar. -/// info | Bilgi +/// note | Not `open()` fonksiyonunda `mode="a"` "append" anlamına gelir; yani satır, önceki içeriği silmeden dosyada ne varsa onun sonuna eklenir. @@ -152,7 +152,7 @@ Meraklı nerd’ler için küçük bir teknik detay. 🤓 Altta, ASGI teknik spesifikasyonunda bu, [Lifespan Protokolü](https://asgi.readthedocs.io/en/latest/specs/lifespan.html)’nün bir parçasıdır ve `startup` ile `shutdown` adında event’ler tanımlar. -/// info | Bilgi +/// note | Not Starlette `lifespan` handler’ları hakkında daha fazlasını [Starlette Lifespan dokümanları](https://www.starlette.dev/lifespan/) içinde okuyabilirsiniz. diff --git a/docs/tr/docs/advanced/generate-clients.md b/docs/tr/docs/advanced/generate-clients.md index 80b5f6bbb..6e12efe3c 100644 --- a/docs/tr/docs/advanced/generate-clients.md +++ b/docs/tr/docs/advanced/generate-clients.md @@ -20,21 +20,6 @@ FastAPI otomatik olarak **OpenAPI 3.1** spesifikasyonları üretir; bu yüzden k /// -## FastAPI Sponsorlarından SDK Üreteçleri { #sdk-generators-from-fastapi-sponsors } - -Bu bölüm, FastAPI'yi sponsorlayan şirketlerin sunduğu **yatırım destekli** ve **şirket destekli** çözümleri öne çıkarır. Bu ürünler, yüksek kaliteli üretilen SDK'ların üzerine **ek özellikler** ve **entegrasyonlar** sağlar. - -✨ [**FastAPI'ye sponsor olarak**](../help-fastapi.md#sponsor-the-author) ✨ bu şirketler, framework'ün ve **ekosisteminin** sağlıklı ve **sürdürülebilir** kalmasına yardımcı olur. - -Sponsor olmaları aynı zamanda FastAPI **topluluğuna** (size) güçlü bir bağlılığı da gösterir; yalnızca **iyi bir hizmet** sunmayı değil, aynı zamanda **güçlü ve gelişen bir framework** olan FastAPI'yi desteklemeyi de önemsediklerini gösterir. 🙇 - -Örneğin şunları deneyebilirsiniz: - -* [Stainless](https://www.stainless.com/?utm_source=fastapi&utm_medium=referral) -* [liblab](https://developers.liblab.com/tutorials/sdk-for-fastapi?utm_source=fastapi) - -Bu çözümlerin bazıları açık kaynak olabilir veya ücretsiz katman sunabilir; yani finansal bir taahhüt olmadan deneyebilirsiniz. Başka ticari SDK üreteçleri de vardır ve internette bulunabilir. 🤓 - ## TypeScript SDK Oluşturma { #create-a-typescript-sdk } Basit bir FastAPI uygulamasıyla başlayalım: diff --git a/docs/tr/docs/advanced/json-base64-bytes.md b/docs/tr/docs/advanced/json-base64-bytes.md index 68e1cba7a..b7712194c 100644 --- a/docs/tr/docs/advanced/json-base64-bytes.md +++ b/docs/tr/docs/advanced/json-base64-bytes.md @@ -4,7 +4,7 @@ Uygulamanız JSON veri alıp gönderiyorsa ve bunun içine ikili (binary) veri e ## Base64 ve Dosyalar { #base64-vs-files } -İkili veriyi JSON içinde encode etmek yerine, yükleme için [Request Files](../tutorial/request-files.md) ve gönderim için [Custom Response - FileResponse](./custom-response.md#fileresponse--fileresponse-) kullanıp kullanamayacağınıza önce bir bakın. +İkili veriyi JSON içinde encode etmek yerine, yükleme için [Request Files](../tutorial/request-files.md) ve gönderim için [Custom Response - FileResponse](./custom-response.md#fileresponse) kullanıp kullanamayacağınıza önce bir bakın. JSON sadece UTF-8 ile encode edilmiş string'ler içerebilir, dolayısıyla ham bytes içeremez. diff --git a/docs/tr/docs/advanced/openapi-callbacks.md b/docs/tr/docs/advanced/openapi-callbacks.md index 627e6cb6c..91ff84411 100644 --- a/docs/tr/docs/advanced/openapi-callbacks.md +++ b/docs/tr/docs/advanced/openapi-callbacks.md @@ -167,13 +167,13 @@ Callback URL'sinin, `callback_url` içindeki query parametresi olarak alınan UR Bu noktada, yukarıda oluşturduğunuz callback router'ında gerekli callback *path operation*'ları (external geliştiricinin *external API*'de implemente etmesi gerekenler) hazır. -Şimdi sizin API'nizin *path operation decorator*'ında `callbacks` parametresini kullanarak, callback router'ının `.routes` attribute'unu (bu aslında route/*path operation*'lardan oluşan bir `list`) geçin: +Şimdi sizin API'nizin *path operation decorator*'ında `callbacks` parametresini kullanarak, callback router'ının `.routes` attribute'unu geçin: {* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[33] *} /// tip | İpucu -`callback=` içine router'ın kendisini (`invoices_callback_router`) değil, `invoices_callback_router.routes` şeklinde `.routes` attribute'unu verdiğinize dikkat edin. +`callbacks=` içine router'ın kendisini (`invoices_callback_router`) değil, `invoices_callback_router.routes` şeklinde `.routes` attribute'unu verdiğinize dikkat edin. FastAPI bu route'ları callback OpenAPI dokümantasyonunu üretmek için kullanacaktır. /// diff --git a/docs/tr/docs/advanced/openapi-webhooks.md b/docs/tr/docs/advanced/openapi-webhooks.md index a9f21662c..eda5ba218 100644 --- a/docs/tr/docs/advanced/openapi-webhooks.md +++ b/docs/tr/docs/advanced/openapi-webhooks.md @@ -22,7 +22,7 @@ Webhook'lar için URL'lerin nasıl kaydedileceğine dair tüm **mantık** ve bu Bu, kullanıcılarınızın **webhook** request'lerinizi alacak şekilde **API'lerini implement etmesini** çok daha kolaylaştırabilir; hatta kendi API kodlarının bir kısmını otomatik üretebilirler. -/// info | Bilgi +/// note | Not Webhook'lar OpenAPI 3.1.0 ve üzeri sürümlerde mevcuttur; FastAPI `0.99.0` ve üzeri tarafından desteklenir. @@ -36,7 +36,7 @@ Bir **FastAPI** uygulaması oluşturduğunuzda, *webhook*'ları tanımlamak içi Tanımladığınız webhook'lar **OpenAPI** şemasında ve otomatik **docs UI**'da yer alır. -/// info | Bilgi +/// note | Not `app.webhooks` nesnesi aslında sadece bir `APIRouter`'dır; uygulamanızı birden fazla dosya ile yapılandırırken kullanacağınız türün aynısıdır. diff --git a/docs/tr/docs/advanced/path-operation-advanced-configuration.md b/docs/tr/docs/advanced/path-operation-advanced-configuration.md index 00ce76588..c5d682af7 100644 --- a/docs/tr/docs/advanced/path-operation-advanced-configuration.md +++ b/docs/tr/docs/advanced/path-operation-advanced-configuration.md @@ -16,17 +16,11 @@ Bunun her operation için benzersiz olduğundan emin olmanız gerekir. ### operationId olarak *path operation function* adını kullanma { #using-the-path-operation-function-name-as-the-operationid } -API’lerinizin function adlarını `operationId` olarak kullanmak istiyorsanız, hepsini dolaşıp her *path operation*’ın `operation_id` değerini `APIRoute.name` ile override edebilirsiniz. +API’lerinizin function adlarını `operationId` olarak kullanmak istiyorsanız, `FastAPI`'ye özel bir `generate_unique_id_function` geçebilirsiniz. -Bunu, tüm *path operation*’ları ekledikten sonra yapmalısınız. +Bu function her bir `APIRoute`'u alır ve ilgili *path operation* için kullanılacak `operationId`'yi döndürür. -{* ../../docs_src/path_operation_advanced_configuration/tutorial002_py310.py hl[2, 12:21, 24] *} - -/// tip | İpucu - -`app.openapi()` fonksiyonunu manuel olarak çağırıyorsanız, bunu yapmadan önce `operationId`’leri güncellemelisiniz. - -/// +{* ../../docs_src/path_operation_advanced_configuration/tutorial002_py310.py hl[2,5:6,9] *} /// warning | Uyarı diff --git a/docs/tr/docs/advanced/response-change-status-code.md b/docs/tr/docs/advanced/response-change-status-code.md index f15ed77f5..552daa0b2 100644 --- a/docs/tr/docs/advanced/response-change-status-code.md +++ b/docs/tr/docs/advanced/response-change-status-code.md @@ -18,7 +18,7 @@ Bu tür durumlarda bir `Response` parametresi kullanabilirsiniz. *Path operation function* içinde `Response` tipinde bir parametre tanımlayabilirsiniz (cookie ve header'lar için yapabildiğiniz gibi). -Ardından bu *geçici (temporal)* `Response` nesnesi üzerinde `status_code` değerini ayarlayabilirsiniz. +Ardından bu *geçici* `Response` nesnesi üzerinde `status_code` değerini ayarlayabilirsiniz. {* ../../docs_src/response_change_status_code/tutorial001_py310.py hl[1,9,12] *} @@ -26,6 +26,6 @@ Sonrasında, normalde yaptığınız gibi ihtiyacınız olan herhangi bir nesney Ve eğer bir `response_model` tanımladıysanız, döndürdüğünüz nesneyi filtrelemek ve dönüştürmek için yine kullanılacaktır. -**FastAPI**, status code'u (ayrıca cookie ve header'ları) bu *geçici (temporal)* response'tan alır ve `response_model` ile filtrelenmiş, sizin döndürdüğünüz değeri içeren nihai response'a yerleştirir. +**FastAPI**, status code'u (ayrıca cookie ve header'ları) bu *geçici* response'tan alır ve `response_model` ile filtrelenmiş, sizin döndürdüğünüz değeri içeren nihai response'a yerleştirir. Ayrıca `Response` parametresini dependency'lerde de tanımlayıp status code'u orada ayarlayabilirsiniz. Ancak unutmayın, en son ayarlanan değer geçerli olur. diff --git a/docs/tr/docs/advanced/response-cookies.md b/docs/tr/docs/advanced/response-cookies.md index 3d3b978bc..a33d4ef37 100644 --- a/docs/tr/docs/advanced/response-cookies.md +++ b/docs/tr/docs/advanced/response-cookies.md @@ -26,7 +26,7 @@ Sonra bunun içinde Cookie'leri set edin ve response'u döndürün: {* ../../docs_src/response_cookies/tutorial001_py310.py hl[10:12] *} -/// tip +/// tip | İpucu `Response` parametresini kullanmak yerine doğrudan bir response döndürürseniz, FastAPI onu olduğu gibi (doğrudan) döndürür. diff --git a/docs/tr/docs/advanced/response-directly.md b/docs/tr/docs/advanced/response-directly.md index 8db51e351..ce48cf44c 100644 --- a/docs/tr/docs/advanced/response-directly.md +++ b/docs/tr/docs/advanced/response-directly.md @@ -18,7 +18,7 @@ Ayrıca doğrudan bir `JSONResponse` oluşturup döndürebilirsiniz. Aslında herhangi bir `Response` veya onun herhangi bir alt sınıfını döndürebilirsiniz. -/// info | Bilgi +/// note | Not `JSONResponse` zaten `Response`'un bir alt sınıfıdır. diff --git a/docs/tr/docs/advanced/response-headers.md b/docs/tr/docs/advanced/response-headers.md index d61e24da3..c4a654792 100644 --- a/docs/tr/docs/advanced/response-headers.md +++ b/docs/tr/docs/advanced/response-headers.md @@ -1,5 +1,6 @@ # Response Header'ları { #response-headers } + ## Bir `Response` parametresi kullanın { #use-a-response-parameter } *Path operation function* içinde (cookie'lerde yapabildiğiniz gibi) tipi `Response` olan bir parametre tanımlayabilirsiniz. diff --git a/docs/tr/docs/advanced/security/oauth2-scopes.md b/docs/tr/docs/advanced/security/oauth2-scopes.md index 6ac6ea6c1..1d1dcb3cf 100644 --- a/docs/tr/docs/advanced/security/oauth2-scopes.md +++ b/docs/tr/docs/advanced/security/oauth2-scopes.md @@ -1,5 +1,6 @@ # OAuth2 scope'ları { #oauth2-scopes } + OAuth2 scope'larını **FastAPI** ile doğrudan kullanabilirsiniz; sorunsuz çalışacak şekilde entegre edilmiştir. Bu sayede OAuth2 standardını takip eden, daha ince taneli bir izin sistemini OpenAPI uygulamanıza (ve API dokümanlarınıza) entegre edebilirsiniz. @@ -46,7 +47,7 @@ Genellikle belirli güvenlik izinlerini tanımlamak için kullanılır, örneği * `instagram_basic` Facebook / Instagram tarafından kullanılır. * `https://www.googleapis.com/auth/drive` Google tarafından kullanılır. -/// info | Bilgi +/// note | Not OAuth2'de "scope", gereken belirli bir izni bildiren bir string'den ibarettir. @@ -126,7 +127,7 @@ Burada, **FastAPI**'nin farklı seviyelerde tanımlanan scope'ları nasıl ele a {* ../../docs_src/security/tutorial005_an_py310.py hl[5,141,172] *} -/// info | Teknik Detaylar +/// note | Teknik Detaylar `Security` aslında `Depends`'in bir alt sınıfıdır ve sadece birazdan göreceğimiz bir ek parametreye sahiptir. diff --git a/docs/tr/docs/advanced/settings.md b/docs/tr/docs/advanced/settings.md index a39e28a92..5734387fe 100644 --- a/docs/tr/docs/advanced/settings.md +++ b/docs/tr/docs/advanced/settings.md @@ -1,5 +1,6 @@ # Ayarlar ve Ortam Değişkenleri { #settings-and-environment-variables } + Birçok durumda uygulamanızın bazı harici ayarlara veya konfigürasyonlara ihtiyacı olabilir; örneğin secret key'ler, veritabanı kimlik bilgileri, e-posta servisleri için kimlik bilgileri vb. Bu ayarların çoğu değişkendir (değişebilir); örneğin veritabanı URL'leri. Ayrıca birçoğu hassas olabilir; örneğin secret'lar. diff --git a/docs/tr/docs/advanced/stream-data.md b/docs/tr/docs/advanced/stream-data.md index 4310edc35..9b58d962b 100644 --- a/docs/tr/docs/advanced/stream-data.md +++ b/docs/tr/docs/advanced/stream-data.md @@ -2,9 +2,9 @@ Veriyi JSON olarak yapılandırabiliyorsanız, [JSON Lines Akışı](../tutorial/stream-json-lines.md) kullanın. -Ancak saf ikili (binary) veri ya da string akıtmak istiyorsanız, bunu şöyle yapabilirsiniz. +Ancak **saf ikili (binary) veri** ya da string akıtmak istiyorsanız, bunu şöyle yapabilirsiniz. -/// info | Bilgi +/// note | Not FastAPI 0.134.0 ile eklendi. @@ -40,7 +40,7 @@ FastAPI veriyi Pydantic ile JSON'a çevirmeye veya herhangi bir şekilde serile {* ../../docs_src/stream_data/tutorial001_py310.py ln[32:35] hl[33] *} -Bu aynı zamanda `StreamingResponse` ile veriyi tam olarak ihtiyaç duyduğunuz biçimde üretme ve encode etme konusunda hem bir özgürlük hem de bir sorumluluk verdiği anlamına gelir; tip annotasyonlarından bağımsızdır. 🤓 +Bu aynı zamanda `StreamingResponse` ile veriyi tam olarak ihtiyaç duyduğunuz biçimde üretme ve encode etme konusunda hem bir **özgürlük** hem de bir **sorumluluk** verdiği anlamına gelir; tip annotasyonlarından bağımsızdır. 🤓 ### Bytes Akışı { #stream-bytes } @@ -90,7 +90,7 @@ Bu özel örnekte o kadar da önemli değil, çünkü sahte ve bellekte (yani `i Ve birçok durumda, diskte ya da ağda okundukları için, okumak engelleyici (event loop'u bloke edebilen) bir işlem olabilir. -/// info | Bilgi +/// note | Not Yukarıdaki örnek aslında bir istisna; çünkü `io.BytesIO` nesnesi zaten bellekte, dolayısıyla onu okumak hiçbir şeyi bloke etmez. diff --git a/docs/tr/docs/advanced/strict-content-type.md b/docs/tr/docs/advanced/strict-content-type.md index 94716e31f..93c23b83b 100644 --- a/docs/tr/docs/advanced/strict-content-type.md +++ b/docs/tr/docs/advanced/strict-content-type.md @@ -81,7 +81,7 @@ Content-Type header’ı göndermeyen client’ları desteklemeniz gerekiyorsa, Bu ayarla, Content-Type header’ı olmayan request’lerin body’si JSON olarak parse edilir. Bu, FastAPI’nin eski sürümlerindeki davranışla aynıdır. -/// info | Bilgi +/// note | Not Bu davranış ve yapılandırma FastAPI 0.132.0’da eklendi. diff --git a/docs/tr/docs/advanced/websockets.md b/docs/tr/docs/advanced/websockets.md index d15d63559..103a0aa18 100644 --- a/docs/tr/docs/advanced/websockets.md +++ b/docs/tr/docs/advanced/websockets.md @@ -111,7 +111,7 @@ Diğer FastAPI endpoint'leri/*path operations* ile aynı şekilde çalışırlar {* ../../docs_src/websockets_/tutorial002_an_py310.py hl[68:69,82] *} -/// info +/// note Bu bir WebSocket olduğu için `HTTPException` raise etmek pek anlamlı değildir; bunun yerine `WebSocketException` raise ederiz. diff --git a/docs/tr/docs/advanced/wsgi.md b/docs/tr/docs/advanced/wsgi.md index 06a3f2834..6e61aff6a 100644 --- a/docs/tr/docs/advanced/wsgi.md +++ b/docs/tr/docs/advanced/wsgi.md @@ -1,12 +1,13 @@ # WSGI'yi Dahil Etme - Flask, Django ve Diğerleri { #including-wsgi-flask-django-others } + WSGI uygulamalarını [Alt Uygulamalar - Mount Etme](sub-applications.md), [Bir Proxy Arkasında](behind-a-proxy.md) bölümlerinde gördüğünüz gibi mount edebilirsiniz. Bunun için `WSGIMiddleware`'ı kullanabilir ve bunu WSGI uygulamanızı (örneğin Flask, Django vb.) sarmalamak için kullanabilirsiniz. ## `WSGIMiddleware` Kullanımı { #using-wsgimiddleware } -/// info +/// note | Not Bunun için `a2wsgi` kurulmalıdır; örneğin `pip install a2wsgi` ile. @@ -20,7 +21,7 @@ Ve sonra bunu bir path'in altına mount edin. {* ../../docs_src/wsgi/tutorial001_py310.py hl[1,3,23] *} -/// note +/// note | Not Önceden, `fastapi.middleware.wsgi` içindeki `WSGIMiddleware`'ın kullanılması öneriliyordu, ancak artık kullanımdan kaldırıldı. diff --git a/docs/tr/docs/alternatives.md b/docs/tr/docs/alternatives.md index 556e7abbe..e214907b5 100644 --- a/docs/tr/docs/alternatives.md +++ b/docs/tr/docs/alternatives.md @@ -10,7 +10,7 @@ Başkalarının daha önceki çalışmaları olmasaydı, **FastAPI** var olmazd Yıllarca yeni bir framework oluşturmaktan kaçındım. Önce **FastAPI**’ın bugün kapsadığı özelliklerin tamamını, birçok farklı framework, eklenti ve araçla çözmeyi denedim. -Namun bir noktada, geçmişteki araçlardan en iyi fikirleri alıp, mümkün olan en iyi şekilde birleştiren ve daha önce mevcut olmayan dil özelliklerini (Python 3.6+ tip belirteçleri) kullanarak tüm bu özellikleri sağlayan bir şey geliştirmekten başka seçenek kalmadı. +Ancak bir noktada, geçmişteki araçlardan en iyi fikirleri alıp, mümkün olan en iyi şekilde birleştiren ve daha önce mevcut olmayan dil özelliklerini (Python 3.6+ tip belirteçleri) kullanarak tüm bu özellikleri sağlayan bir şey geliştirmekten başka seçenek kalmadı. ## Daha Önce Geliştirilen Araçlar { #previous-tools } @@ -60,7 +60,7 @@ Flask’ın sadeliği göz önüne alındığında, API geliştirmek için iyi b Gereken araç ve parçaları kolayca eşleştirip birleştirmeyi sağlayan bir mikroframework olmak. -Basit ve kullanımı kolay bir yönlendirme (routing) sistemine sahip olmak. +Basit ve kullanımı kolay bir routing sistemine sahip olmak. /// @@ -72,7 +72,7 @@ Hatta bir FastAPI uygulamasının içinde Requests kullanmak yaygındır. Yine de FastAPI, Requests’ten epey ilham almıştır. -**Requests** bir kütüphane olarak API’larla (istemci olarak) etkileşime geçmeye yararken, **FastAPI** API’lar (sunucu olarak) geliştirmeye yarar. +**Requests** bir kütüphane olarak API’larla (client olarak) etkileşime geçmeye yararken, **FastAPI** API’lar (server olarak) geliştirmeye yarar. Yani daha çok zıt uçlardadırlar ama birbirlerini tamamlarlar. @@ -82,7 +82,7 @@ Bu yüzden resmi web sitesinde de söylendiği gibi: > Requests, tüm zamanların en çok indirilen Python paketlerinden biridir -Kullanımı çok basittir. Örneğin bir `GET` isteği yapmak için: +Kullanımı çok basittir. Örneğin bir `GET` request'i yapmak için: ```Python response = requests.get("http://example.com/some/url") @@ -137,9 +137,9 @@ Birçok Flask REST framework’ü var; ancak zaman ayırıp inceledikten sonra ### [Marshmallow](https://marshmallow.readthedocs.io/en/stable/) { #marshmallow } -API sistemlerinin ihtiyaç duyduğu temel özelliklerden biri, koddan (Python) veriyi alıp ağ üzerinden gönderilebilecek bir şeye dönüştürmek, yani veri “dönüşüm”üdür. Örneğin, bir veritabanından gelen verileri içeren bir objeyi JSON objesine dönüştürmek, `datetime` objelerini string’e çevirmek vb. +API sistemlerinin ihtiyaç duyduğu temel özelliklerden biri, koddan (Python) veriyi alıp ağ üzerinden gönderilebilecek bir şeye dönüştürmek, yani veri “serileştirme”dir. Örneğin, bir veritabanından gelen verileri içeren bir objeyi JSON objesine dönüştürmek, `datetime` objelerini string’e çevirmek vb. -API’ların ihtiyaç duyduğu bir diğer önemli özellik, veri doğrulamadır; belirli parametreler göz önüne alındığında verinin geçerli olduğundan emin olmak. Örneğin, bir alanın `int` olması ve rastgele bir metin olmaması. Bu özellikle dışarıdan gelen veriler için kullanışlıdır. +API’ların ihtiyaç duyduğu bir diğer önemli özellik, veri doğrulamadır; belirli parametreler göz önüne alındığında verinin geçerli olduğundan emin olmak. Örneğin, bir alanın `int` olması ve rastgele bir metin olmaması. Bu özellikle gelen veriler için kullanışlıdır. Bir veri doğrulama sistemi olmadan, tüm bu kontrolleri kod içinde el ile yapmanız gerekir. @@ -155,7 +155,7 @@ Kodla, veri tiplerini ve doğrulamayı otomatik sağlayan “şemalar” tanıml ### [Webargs](https://webargs.readthedocs.io/en/latest/) { #webargs } -API’ların ihtiyaç duyduğu bir diğer büyük özellik, gelen isteklerden veriyi ayrıştırmadır. +API’ların ihtiyaç duyduğu bir diğer büyük özellik, gelen request'lerden veriyi ayrıştırmadır. Webargs, Flask dahil birkaç framework’ün üzerinde bunu sağlamak için geliştirilmiş bir araçtır. @@ -163,7 +163,7 @@ Veri doğrulama için arka planda Marshmallow’u kullanır. Aynı geliştiricil **FastAPI**’dan önce benim de çok kullandığım harika bir araçtır. -/// info | Bilgi +/// note | Not Webargs, Marshmallow geliştiricileri tarafından oluşturuldu. @@ -171,13 +171,13 @@ Webargs, Marshmallow geliştiricileri tarafından oluşturuldu. /// tip | **FastAPI**'ye ilham olan -Gelen istek verisini otomatik doğrulamak. +Gelen request verisini otomatik doğrulamak. /// ### [APISpec](https://apispec.readthedocs.io/en/stable/) { #apispec } -Marshmallow ve Webargs; doğrulama, ayrıştırma ve dönüşümü eklenti olarak sağlar. +Marshmallow ve Webargs; doğrulama, ayrıştırma ve serileştirmeyi eklenti olarak sağlar. Ama dökümantasyon eksikti. Sonra APISpec geliştirildi. @@ -193,7 +193,7 @@ Ancak yine, Python metni içinde (kocaman bir YAML) mikro bir söz dizimi sorunu Editör bu konuda pek yardımcı olamaz. Parametreleri veya Marshmallow şemalarını değiştirip docstring’teki YAML’ı güncellemeyi unutursak, üretilen şema geçerliliğini yitirir. -/// info | Bilgi +/// note | Not APISpec, Marshmallow geliştiricileri tarafından oluşturuldu. @@ -225,7 +225,7 @@ Bunu kullanmak, birkaç Flask full‑stack üreticisinin ortaya çıkmasına yol Aynı full‑stack üreticiler, [**FastAPI** Proje Üreticileri](project-generation.md)’nin de temelini oluşturdu. -/// info | Bilgi +/// note | Not Flask-apispec, Marshmallow geliştiricileri tarafından oluşturuldu. @@ -233,7 +233,7 @@ Flask-apispec, Marshmallow geliştiricileri tarafından oluşturuldu. /// tip | **FastAPI**'ye ilham olan -Veri dönüşümü ve doğrulamayı tanımlayan aynı koddan, OpenAPI şemasını otomatik üretmek. +Serileştirme ve doğrulamayı tanımlayan aynı koddan, OpenAPI şemasını otomatik üretmek. /// @@ -247,9 +247,9 @@ Angular 2’den esinlenen, entegre bir bağımlılık enjeksiyonu sistemi vardı Parametreler TypeScript tipleriyle (Python tip belirteçlerine benzer) açıklandığından, editör desteği oldukça iyidir. -Ancak TypeScript tip bilgisi JavaScript’e derlemeden sonra korunmadığından, aynı anda tiplere dayanarak doğrulama, dönüşüm ve dökümantasyon tanımlanamaz. Bu ve bazı tasarım kararları nedeniyle doğrulama, dönüşüm ve otomatik şema üretimi için birçok yere dekoratör eklemek gerekir; proje oldukça ayrıntılı hâle gelir. +Ancak TypeScript tip bilgisi JavaScript’e derlemeden sonra korunmadığından, aynı anda tiplere dayanarak doğrulama, serileştirme ve dökümantasyon tanımlanamaz. Bu ve bazı tasarım kararları nedeniyle doğrulama, serileştirme ve otomatik şema üretimi için birçok yere dekoratör eklemek gerekir; proje oldukça ayrıntılı hâle gelir. -İçiçe modelleri çok iyi işleyemez. Yani istek gövdesindeki JSON, içinde başka alanları ve onlar da içiçe JSON objelerini içeriyorsa, doğru şekilde dökümante edilip doğrulanamaz. +İç içe modelleri çok iyi işleyemez. Yani request'teki JSON body, içinde başka alanları ve onlar da iç içe JSON objelerini içeriyorsa, doğru şekilde dökümante edilip doğrulanamaz. /// tip | **FastAPI**'ye ilham olan @@ -283,15 +283,17 @@ Bu yüzden **FastAPI**, en hızlı framework olduğu için (üçüncü parti kı Falcon, başka bir yüksek performanslı Python framework’üdür; minimal olacak şekilde tasarlanmış ve Hug gibi diğer framework’lere temel olmuştur. -İki parametre alan fonksiyonlar etrafında tasarlanmıştır: “request” ve “response”. İstekten parçalar “okur”, cevaba parçalar “yazarsınız”. Bu tasarım nedeniyle, fonksiyon parametreleriyle standart Python tip belirteçlerini kullanarak istek parametrelerini ve gövdelerini ilan etmek mümkün değildir. +İki parametre alan fonksiyonlar etrafında tasarlanmıştır: bir “request” ve bir “response”. Sonra request'ten parçalar “okur”, response'a parçalar “yazarsınız”. Bu tasarım nedeniyle, fonksiyon parametreleriyle standart Python tip belirteçlerini kullanarak request parametrelerini ve body'lerini ilan etmek mümkün değildir. -Dolayısıyla veri doğrulama, dönüşüm ve dökümantasyon kodda yapılmalı; otomatik olmaz. Ya da Hug’da olduğu gibi Falcon’un üzerine bir framework olarak uygulanmalıdır. Falcon’un tasarımından etkilenen ve tek bir request objesi ile response objesini parametre olarak alan diğer framework’lerde de aynı ayrım vardır. +Dolayısıyla veri doğrulama, serileştirme ve dökümantasyon kodda yapılmalı; otomatik olmaz. Ya da Hug’da olduğu gibi Falcon’un üzerine bir framework olarak uygulanmalıdır. Falcon’un tasarımından etkilenen ve tek bir request objesi ile response objesini parametre olarak alan diğer framework’lerde de aynı ayrım vardır. /// tip | **FastAPI**'ye ilham olan Harika performans elde etmenin yollarını bulmak. -Hug ile birlikte (Hug, Falcon’a dayanır) **FastAPI**'de fonksiyonlarda opsiyonel bir `response` parametresi ilan edilmesi fikrine ilham vermek. FastAPI'de bu parametre çoğunlukla header, cookie ve alternatif durum kodlarını ayarlamak için kullanılır. +Hug ile birlikte (Hug, Falcon’a dayanır) **FastAPI**'de fonksiyonlarda bir `response` parametresi ilan edilmesi fikrine ilham vermek. + +FastAPI'de bu parametre opsiyoneldir ve çoğunlukla header, cookie ve alternatif durum kodlarını ayarlamak için kullanılır. /// @@ -303,7 +305,7 @@ Hug ile birlikte (Hug, Falcon’a dayanır) **FastAPI**'de fonksiyonlarda opsiyo * Bu tiplere bağlı doğrulama ve dökümantasyon sağlar. * Bağımlılık enjeksiyonu sistemi vardır. -Pydantic gibi doğrulama, dönüşüm ve dökümantasyon için üçüncü parti bir kütüphane kullanmaz; kendi içinde sağlar. Bu yüzden bu veri tipi tanımlarını tekrar kullanmak o kadar kolay olmaz. +Pydantic gibi doğrulama, serileştirme ve dökümantasyon için üçüncü parti bir kütüphane kullanmaz; kendi içinde sağlar. Bu yüzden bu veri tipi tanımlarını tekrar kullanmak o kadar kolay olmaz. Biraz daha ayrıntılı yapılandırma ister. Ve ASGI yerine WSGI tabanlı olduğundan, Uvicorn, Starlette ve Sanic gibi araçların yüksek performansından faydalanmaya yönelik tasarlanmamıştır. @@ -333,7 +335,7 @@ Nadir bir özelliği daha vardı: aynı framework ile hem API’lar hem de CLI Senkron Python web framework’leri için önceki standart olan WSGI’ye dayandığından, WebSocket vb. şeyleri işleyemez, ancak yine de yüksek performansa sahiptir. -/// info | Bilgi +/// note | Not Hug, Python dosyalarındaki import’ları otomatik sıralayan harika bir araç olan [`isort`](https://github.com/timothycrosley/isort)’un geliştiricisi Timothy Crosley tarafından geliştirildi. @@ -353,11 +355,11 @@ Ayrıca header ve cookie ayarlamak için fonksiyonlarda `response` parametresi i **FastAPI**’yi inşa etmeye karar vermeden hemen önce **APIStar** sunucusunu buldum. Aradığım şeylerin neredeyse hepsine sahipti ve harika bir tasarımı vardı. -Python tip belirteçleriyle parametreleri ve istekleri ilan eden bir framework’ün gördüğüm ilk örneklerindendi (NestJS ve Molten’dan önce). Aşağı yukarı Hug ile aynı zamanlarda buldum; ancak APIStar, OpenAPI standardını kullanıyordu. +Python tip belirteçleriyle parametreleri ve request'leri ilan eden bir framework’ün gördüğüm ilk örneklerindendi (NestJS ve Molten’dan önce). Aşağı yukarı Hug ile aynı zamanlarda buldum; ancak APIStar, OpenAPI standardını kullanıyordu. -Farklı yerlerdeki aynı tip belirteçlerine dayanarak otomatik veri doğrulama, veri dönüşümü ve OpenAPI şeması üretimi vardı. +Farklı yerlerdeki aynı tip belirteçlerine dayanarak otomatik veri doğrulama, veri serileştirme ve OpenAPI şeması üretimi vardı. -Gövde şema tanımları Pydantic’tekiyle aynı Python tip belirteçlerini kullanmıyordu; biraz daha Marshmallow’a benziyordu. Bu yüzden editör desteği o kadar iyi olmazdı; yine de APIStar mevcut en iyi seçenekti. +Body şema tanımları Pydantic’tekiyle aynı Python tip belirteçlerini kullanmıyordu; biraz daha Marshmallow’a benziyordu. Bu yüzden editör desteği o kadar iyi olmazdı; yine de APIStar mevcut en iyi seçenekti. O dönem kıyaslamalarda en iyi performansa sahipti (sadece Starlette tarafından geçiliyordu). @@ -373,7 +375,7 @@ Artık bir API web framework’ü değildi; geliştirici Starlette’e odaklanma Şimdi APIStar, bir web framework’ü değil, OpenAPI spesifikasyonlarını doğrulamak için araçlar takımından ibaret. -/// info | Bilgi +/// note | Not APIStar, aşağıdakilerin de yaratıcısı olan Tom Christie tarafından geliştirildi: @@ -387,7 +389,7 @@ APIStar, aşağıdakilerin de yaratıcısı olan Tom Christie tarafından geliş Var olmak. -Aynı Python tipleriyle (hem veri doğrulama, dönüşüm ve dökümantasyon) birden çok şeyi ilan etmek ve aynı anda harika editör desteği sağlamak, bence dahiyane bir fikirdi. +Aynı Python tipleriyle (hem veri doğrulama, serileştirme ve dökümantasyon) birden çok şeyi ilan etmek ve aynı anda harika editör desteği sağlamak, bence dahiyane bir fikirdi. Uzun süre benzer bir framework arayıp birçok alternatifi denedikten sonra, APIStar mevcut en iyi seçenekti. @@ -401,7 +403,7 @@ Sonra APIStar bir sunucu olarak var olmaktan çıktı ve Starlette oluşturuldu; ### [Pydantic](https://docs.pydantic.dev/) { #pydantic } -Pydantic, Python tip belirteçlerine dayalı olarak veri doğrulama, dönüşüm ve dökümantasyon (JSON Schema kullanarak) tanımlamak için bir kütüphanedir. +Pydantic, Python tip belirteçlerine dayalı olarak veri doğrulama, serileştirme ve dökümantasyon (JSON Schema kullanarak) tanımlamak için bir kütüphanedir. Bu onu aşırı sezgisel kılar. @@ -409,7 +411,7 @@ Marshmallow ile karşılaştırılabilir. Kıyaslamalarda Marshmallow’dan daha /// tip | **FastAPI** bunu şurada kullanır -Tüm veri doğrulama, veri dönüşümü ve JSON Schema tabanlı otomatik model dökümantasyonunu halletmekte. +Tüm veri doğrulama, veri serileştirme ve JSON Schema tabanlı otomatik model dökümantasyonunu halletmekte. **FastAPI** daha sonra bu JSON Schema verisini alır ve (yaptığı diğer şeylerin yanı sıra) OpenAPI içine yerleştirir. @@ -427,9 +429,9 @@ Starlette, yüksek performanslı asyncio servisleri oluşturmak için ideal, haf * WebSocket desteği. * Süreç içi arka plan görevleri. * Başlatma ve kapatma olayları. -* HTTPX üzerinde geliştirilmiş test istemcisi. -* CORS, GZip, Statik Dosyalar, Streaming cevaplar. -* Oturum (Session) ve Cookie desteği. +* HTTPX üzerinde geliştirilmiş test client'ı. +* CORS, GZip, Statik Dosyalar, Streaming response'lar. +* Session ve Cookie desteği. * %100 test kapsamı. * %100 tip anotasyonlu kod tabanı. * Az sayıda zorunlu bağımlılık. @@ -438,7 +440,7 @@ Starlette, şu anda test edilen en hızlı Python framework’üdür. Yalnızca Starlette, temel web mikroframework işlevselliğinin tamamını sağlar. -Ancak otomatik veri doğrulama, dönüşüm veya dökümantasyon sağlamaz. +Ancak otomatik veri doğrulama, serileştirme veya dökümantasyon sağlamaz. **FastAPI**’nin bunun üzerine eklediği ana şeylerden biri, Pydantic kullanarak, bütünüyle Python tip belirteçlerine dayalı bu özelliklerdir. Buna ek olarak bağımlılık enjeksiyonu sistemi, güvenlik yardımcıları, OpenAPI şema üretimi vb. gelir. @@ -464,7 +466,7 @@ Dolayısıyla Starlette ile yapabildiğiniz her şeyi, adeta “turbo şarjlı S Uvicorn, uvloop ve httptools üzerinde inşa edilmiş, ışık hızında bir ASGI sunucusudur. -Bir web framework’ü değil, bir sunucudur. Örneğin path’lere göre yönlendirme araçları sağlamaz; bunu Starlette (veya **FastAPI**) gibi bir framework üstte sağlar. +Bir web framework’ü değil, bir sunucudur. Örneğin path’lere göre routing araçları sağlamaz; bunu Starlette (veya **FastAPI**) gibi bir framework üstte sağlar. Starlette ve **FastAPI** için önerilen sunucudur. diff --git a/docs/tr/docs/async.md b/docs/tr/docs/async.md index 5acf5c145..b65756587 100644 --- a/docs/tr/docs/async.md +++ b/docs/tr/docs/async.md @@ -82,12 +82,12 @@ Bu "başka bir şeyi beklemek" genelde işlemci ve RAM hızına kıyasla nispete * programınızın sisteme verdiği içeriğin diske yazılması * uzak bir API işlemi * bir veritabanı işleminin bitmesi -* bir veritabanı sorgusunun sonuç döndürmesi +* bir veritabanı query'sinin sonuç döndürmesi * vb. Çalışma süresi çoğunlukla I/O işlemlerini beklemekle geçtiğinden, bunlara "I/O bound" işlemler denir. -"Bunun" asenkron" denmesinin sebebi, bilgisayarın / programın yavaş görevle "senkronize" olmak, görev tam bittiği anda orada olup görev sonucunu almak ve işe devam etmek için hiçbir şey yapmadan beklemek zorunda olmamasıdır. +Buna "asenkron" denmesinin sebebi, bilgisayarın / programın yavaş görevle "senkronize" olmak, görev tam bittiği anda orada olup görev sonucunu almak ve işe devam etmek için hiçbir şey yapmadan beklemek zorunda olmamasıdır. Bunun yerine "asenkron" bir sistem olarak, görev bittiğinde, bilgisayarın / programın o sırada yaptığı işi bitirmesi için biraz (birkaç mikrosaniye) sırada bekleyebilir ve sonra sonuçları almak üzere geri dönüp onlarla çalışmaya devam edebilir. @@ -139,7 +139,7 @@ Aşkınla burgerleri yiyip güzel vakit geçiriyorsunuz. ✨ -/// note | Bilgi +/// note | Not Harika çizimler: [Ketrina Thompson](https://www.instagram.com/ketrinadrawsalot). 🎨 @@ -205,7 +205,7 @@ Sadece yiyorsunuz ve iş bitiyor. ⏹ Vaktin çoğu tezgâhın önünde 🕙 beklemekle geçtiğinden, pek konuşma ya da flört olmadı. 😞 -/// note | Bilgi +/// note | Not Harika çizimler: [Ketrina Thompson](https://www.instagram.com/ketrinadrawsalot). 🎨 @@ -239,9 +239,9 @@ Muhtemelen, bankada 🏦 işlerini hallederken aşkını 😍 yanında götürme Bu, çoğu web uygulaması için de geçerlidir. -Çok fazla kullanıcı vardır; ancak sunucunuz, iyi olmayan bağlantılarından gelen istekleri 🕙 bekler. +Çok fazla kullanıcı vardır; ancak sunucunuz, onların pek iyi olmayan bağlantıları üzerinden request'lerin gelmesini 🕙 bekler. -Ve sonra yanıtların geri gelmesini yine 🕙 bekler. +Ardından response'ların geri gelmesini yine 🕙 bekler. Bu "beklemeler" 🕙 mikrosaniyelerle ölçülür; ama hepsi toplandığında sonuçta oldukça fazla bekleme olur. diff --git a/docs/tr/docs/deployment/cloud.md b/docs/tr/docs/deployment/cloud.md index b263ecc57..92a631734 100644 --- a/docs/tr/docs/deployment/cloud.md +++ b/docs/tr/docs/deployment/cloud.md @@ -16,7 +16,7 @@ FastAPI Cloud, *FastAPI and friends* açık kaynak projelerinin birincil sponsor ## Bulut Sağlayıcılar - Sponsorlar { #cloud-providers-sponsors } -Diğer bazı bulut sağlayıcılar da ✨ [**FastAPI'ye sponsor olur**](../help-fastapi.md#sponsor-the-author) ✨. 🙇 +Diğer bazı bulut sağlayıcılar da ✨ [**FastAPI'ye sponsor olur**](https://github.com/sponsors/tiangolo) ✨. 🙇 Kılavuzlarını takip etmek ve servislerini denemek için onları da değerlendirmek isteyebilirsiniz: diff --git a/docs/tr/docs/deployment/concepts.md b/docs/tr/docs/deployment/concepts.md index 211e2ab51..ee62ef647 100644 --- a/docs/tr/docs/deployment/concepts.md +++ b/docs/tr/docs/deployment/concepts.md @@ -1,5 +1,6 @@ # Deployment Kavramları { #deployments-concepts } + Bir **FastAPI** uygulamasını (hatta genel olarak herhangi bir web API'yi) deploy ederken, muhtemelen önemseyeceğiniz bazı kavramlar vardır. Bu kavramları kullanarak, **uygulamanızı deploy etmek** için **en uygun** yöntemi bulabilirsiniz. Önemli kavramlardan bazıları şunlardır: diff --git a/docs/tr/docs/deployment/docker.md b/docs/tr/docs/deployment/docker.md index 0b2da213c..aebde767b 100644 --- a/docs/tr/docs/deployment/docker.md +++ b/docs/tr/docs/deployment/docker.md @@ -26,7 +26,7 @@ COPY ./app /code/app CMD ["fastapi", "run", "app/main.py", "--port", "80"] -# If running behind a proxy like Nginx or Traefik add --proxy-headers +# Nginx veya Traefik gibi bir proxy arkasında çalıştırıyorsanız --proxy-headers ekleyin # CMD ["fastapi", "run", "app/main.py", "--port", "80", "--proxy-headers"] ``` @@ -132,7 +132,7 @@ Successfully installed fastapi pydantic -/// info | Bilgi +/// note | Not Paket bağımlılıklarını tanımlamak ve yüklemek için başka formatlar ve araçlar da vardır. @@ -243,14 +243,14 @@ Aşağıda açıklandığı gibi `CMD` talimatının **her zaman** **exec form** ✅ **Exec** form: ```Dockerfile -# ✅ Do this +# ✅ Bunu yapın CMD ["fastapi", "run", "app/main.py", "--port", "80"] ``` ⛔️ **Shell** form: ```Dockerfile -# ⛔️ Don't do this +# ⛔️ Bunu yapmayın CMD fastapi run app/main.py --port 80 ``` @@ -556,7 +556,7 @@ Container kullanıyorsanız (örn. Docker, Kubernetes), temelde iki yaklaşım v **Birden fazla container**'ınız varsa ve muhtemelen her biri **tek process** çalıştırıyorsa (ör. bir **Kubernetes** cluster'ında), replication yapılan worker container'lar çalışmadan **önce**, **başlatmadan önceki adımlar**ın işini yapan **ayrı bir container** kullanmak isteyebilirsiniz (tek container, tek process). -/// info | Bilgi +/// note | Not Kubernetes kullanıyorsanız, bu muhtemelen bir [Init Container](https://kubernetes.io/docs/concepts/workloads/pods/init-containers/) olur. diff --git a/docs/tr/docs/deployment/fastapicloud.md b/docs/tr/docs/deployment/fastapicloud.md index 890e31915..eecf25d66 100644 --- a/docs/tr/docs/deployment/fastapicloud.md +++ b/docs/tr/docs/deployment/fastapicloud.md @@ -1,26 +1,6 @@ # FastAPI Cloud { #fastapi-cloud } -FastAPI uygulamanızı [FastAPI Cloud](https://fastapicloud.com)'a **tek bir komutla** deploy edebilirsiniz. Henüz yapmadıysanız gidip bekleme listesine katılın. 🚀 - -## Giriş Yapma { #login } - -Önceden bir **FastAPI Cloud** hesabınız olduğundan emin olun (sizi bekleme listesinden davet ettik 😉). - -Ardından giriş yapın: - -
- -```console -$ fastapi login - -You are logged in to FastAPI Cloud 🚀 -``` - -
- -## Deploy { #deploy } - -Şimdi uygulamanızı **tek bir komutla** deploy edin: +FastAPI uygulamanızı [FastAPI Cloud](https://fastapicloud.com)'a yalnızca **tek bir komutla** deploy edebilirsiniz. 🚀
@@ -36,20 +16,22 @@ Deploying to FastAPI Cloud...
+CLI, FastAPI uygulamanızı otomatik olarak algılar ve buluta deploy eder. Giriş yapmadıysanız, kimlik doğrulamasını tamamlamak için tarayıcınız açılır. + Hepsi bu! Artık uygulamanıza o URL üzerinden erişebilirsiniz. ✨ ## FastAPI Cloud Hakkında { #about-fastapi-cloud } **[FastAPI Cloud](https://fastapicloud.com)**, **FastAPI**'nin arkasındaki aynı yazar ve ekip tarafından geliştirilmiştir. -Bir API'yi minimum eforla **geliştirme**, **deploy etme** ve **erişilebilir kılma** sürecini sadeleştirir. +Bir API'yi minimum eforla **geliştirme**, **deploy etme** ve **erişim** süreçlerini sadeleştirir. FastAPI ile uygulama geliştirirken elde ettiğiniz aynı **developer experience**'ı, onları buluta **deploy etmeye** de taşır. 🎉 Ayrıca bir uygulamayı deploy ederken ihtiyaç duyacağınız pek çok şeyi de sizin için halleder; örneğin: * HTTPS -* Replication (çoğaltma), request'lere göre autoscaling ile +* Replication, request'lere göre autoscaling ile * vb. FastAPI Cloud, *FastAPI and friends* açık kaynak projelerinin birincil sponsoru ve finansman sağlayıcısıdır. ✨ @@ -62,4 +44,4 @@ FastAPI uygulamalarını deploy etmek için cloud sağlayıcınızın kendi kıl ## Kendi server'ınıza deploy etme { #deploy-your-own-server } -Bu **Deployment** kılavuzunun ilerleyen bölümlerinde tüm detayları da ele alacağız; böylece neler olduğunu, nelerin gerçekleşmesi gerektiğini ve FastAPI uygulamalarını kendi başınıza (kendi server'larınızla da) nasıl deploy edebileceğinizi anlayacaksınız. 🤓 +Bu **Deployment** kılavuzunun ilerleyen bölümlerinde size tüm detayları da öğreteceğim; böylece neler olduğunu, nelerin gerçekleşmesi gerektiğini ve FastAPI uygulamalarını kendi başınıza, kendi server'larınızla da nasıl deploy edebileceğinizi anlayacaksınız. 🤓 diff --git a/docs/tr/docs/deployment/https.md b/docs/tr/docs/deployment/https.md index 1b8f34e5c..98fd9a230 100644 --- a/docs/tr/docs/deployment/https.md +++ b/docs/tr/docs/deployment/https.md @@ -17,7 +17,7 @@ Bir kullanıcı gözüyle **HTTPS’in temellerini öğrenmek** için [https://h * HTTPS için **server**’ın, **üçüncü bir taraf** tarafından verilen **"sertifikalara"** sahip olması gerekir. * Bu sertifikalar aslında üçüncü tarafça "üretilmez", üçüncü taraftan **temin edilir**. * Sertifikaların bir **geçerlilik süresi** vardır. - * Süresi **dolar**. + * Süreleri **sona erer**. * Sonrasında **yenilenmeleri**, üçüncü taraftan **yeniden temin edilmeleri** gerekir. * Bağlantının şifrelenmesi **TCP seviyesinde** gerçekleşir. * Bu, **HTTP’nin bir katman altıdır**. @@ -169,7 +169,7 @@ Bu şekilde TLS Termination Proxy, birden fazla uygulama için **birden fazla do ### Sertifika Yenileme { #certificate-renewal } -Gelecekte bir noktada, her sertifikanın süresi **dolar** (temin edildikten yaklaşık 3 ay sonra). +Gelecekte bir noktada, her sertifikanın süresi **sona erer** (temin edildikten yaklaşık 3 ay sonra). Ardından başka bir program (bazı durumlarda ayrı bir programdır, bazı durumlarda aynı TLS Termination Proxy olabilir) Let's Encrypt ile konuşup sertifika(ları) yeniler. diff --git a/docs/tr/docs/deployment/manually.md b/docs/tr/docs/deployment/manually.md index 08a548172..2a2b16818 100644 --- a/docs/tr/docs/deployment/manually.md +++ b/docs/tr/docs/deployment/manually.md @@ -1,5 +1,6 @@ # Bir Sunucuyu Manuel Olarak Çalıştırın { #run-a-server-manually } + ## `fastapi run` Komutunu Kullanın { #use-the-fastapi-run-command } Kısacası, FastAPI uygulamanızı sunmak için `fastapi run` kullanın: @@ -56,7 +57,6 @@ Buna alternatif birkaç seçenek daha vardır, örneğin: * [Hypercorn](https://hypercorn.readthedocs.io/): diğer özelliklerin yanında HTTP/2 ve Trio ile uyumlu bir ASGI server. * [Daphne](https://github.com/django/daphne): Django Channels için geliştirilmiş ASGI server. * [Granian](https://github.com/emmett-framework/granian): Python uygulamaları için bir Rust HTTP server. -* [NGINX Unit](https://unit.nginx.org/howto/fastapi/): NGINX Unit, hafif ve çok yönlü bir web uygulaması runtime'ıdır. ## Sunucu Makinesi ve Sunucu Programı { #server-machine-and-server-program } diff --git a/docs/tr/docs/deployment/server-workers.md b/docs/tr/docs/deployment/server-workers.md index 0cb9831a8..878048e32 100644 --- a/docs/tr/docs/deployment/server-workers.md +++ b/docs/tr/docs/deployment/server-workers.md @@ -17,7 +17,7 @@ Uygulamaları deploy ederken, çok çekirdekten (multiple cores) faydalanmak ve Burada, `fastapi` komutunu kullanarak ya da `uvicorn` komutunu doğrudan çalıştırarak worker process'lerle Uvicorn'u nasıl kullanacağınızı göstereceğim. -/// info | Bilgi +/// note | Not Container kullanıyorsanız (örneğin Docker veya Kubernetes ile), bununla ilgili daha fazlasını bir sonraki bölümde anlatacağım: [Container'larda FastAPI - Docker](docker.md). diff --git a/docs/tr/docs/editor-support.md b/docs/tr/docs/editor-support.md index 47182834e..d279152cb 100644 --- a/docs/tr/docs/editor-support.md +++ b/docs/tr/docs/editor-support.md @@ -2,7 +2,7 @@ Resmi [FastAPI Extension](https://marketplace.visualstudio.com/items?itemName=FastAPILabs.fastapi-vscode), FastAPI geliştirme akışınızı iyileştirir: *path operation* keşfi, gezinme, FastAPI Cloud’a deploy ve canlı log akışı. -Daha fazla ayrıntı için, GitHub deposundaki README’ye bakın: [GitHub repository](https://github.com/fastapi/fastapi-vscode). +Daha fazla ayrıntı için, GitHub deposundaki README’ye bakın: [GitHub deposu](https://github.com/fastapi/fastapi-vscode). ## Kurulum ve Yükleme { #setup-and-installation } diff --git a/docs/tr/docs/environment-variables.md b/docs/tr/docs/environment-variables.md index f34c859e0..b54e1cbfd 100644 --- a/docs/tr/docs/environment-variables.md +++ b/docs/tr/docs/environment-variables.md @@ -19,10 +19,10 @@ Python’a ihtiyaç duymadan, **shell (terminal)** içinde ortam değişkenleri
```console -// You could create an env var MY_NAME with +// MY_NAME adlı bir env var'ı şöyle oluşturabilirsiniz $ export MY_NAME="Wade Wilson" -// Then you could use it with other programs, like +// Sonra bunu diğer programlarla şöyle kullanabilirsiniz $ echo "Hello $MY_NAME" Hello Wade Wilson @@ -37,10 +37,10 @@ Hello Wade Wilson
```console -// Create an env var MY_NAME +// MY_NAME adlı bir env var oluşturun $ $Env:MY_NAME = "Wade Wilson" -// Use it with other programs, like +// Bunu diğer programlarla şöyle kullanın $ echo "Hello $Env:MY_NAME" Hello Wade Wilson @@ -78,20 +78,20 @@ Sonrasında bu Python programını çalıştırabilirsiniz:
```console -// Here we don't set the env var yet +// Burada env var'ı henüz ayarlamıyoruz $ python main.py -// As we didn't set the env var, we get the default value +// Env var'ı ayarlamadığımız için varsayılan değeri alırız Hello World from Python -// But if we create an environment variable first +// Ama önce bir ortam değişkeni oluşturursak $ export MY_NAME="Wade Wilson" -// And then call the program again +// Sonra programı tekrar çağırırsak $ python main.py -// Now it can read the environment variable +// Artık ortam değişkenini okuyabilir Hello Wade Wilson from Python ``` @@ -105,20 +105,20 @@ Hello Wade Wilson from Python
```console -// Here we don't set the env var yet +// Burada env var'ı henüz ayarlamıyoruz $ python main.py -// As we didn't set the env var, we get the default value +// Env var'ı ayarlamadığımız için varsayılan değeri alırız Hello World from Python -// But if we create an environment variable first +// Ama önce bir ortam değişkeni oluşturursak $ $Env:MY_NAME = "Wade Wilson" -// And then call the program again +// Sonra programı tekrar çağırırsak $ python main.py -// Now it can read the environment variable +// Artık ortam değişkenini okuyabilir Hello Wade Wilson from Python ``` @@ -136,14 +136,14 @@ Bunu yapmak için, program komutunun hemen öncesinde ve aynı satırda tanımla
```console -// Create an env var MY_NAME in line for this program call +// Bu program çağrısı için aynı satırda MY_NAME adlı bir env var oluşturun $ MY_NAME="Wade Wilson" python main.py -// Now it can read the environment variable +// Artık ortam değişkenini okuyabilir Hello Wade Wilson from Python -// The env var no longer exists afterwards +// Sonrasında env var artık mevcut değildir $ python main.py Hello World from Python diff --git a/docs/tr/docs/features.md b/docs/tr/docs/features.md index 1f034d690..9a85863b7 100644 --- a/docs/tr/docs/features.md +++ b/docs/tr/docs/features.md @@ -99,7 +99,7 @@ Artık anahtar adlarını yanlış yazmak, dokümana gidip gelmek ya da sonunda Her şey için mantıklı **varsayılanlar** ve her yerde isteğe bağlı yapılandırmalar vardır. Tüm parametreler, ihtiyacınızı karşılayacak şekilde ince ayar yapılarak tanımlamak istediğiniz API’yi oluşturabilir. -Ancak varsayılan hâliyle hepsi **“hemen çalışır”**. +Ancak varsayılan hâliyle hepsi **"hemen çalışır"**. ### Doğrulama { #validation } @@ -149,7 +149,7 @@ FastAPI, son derece kolay kullanımlı ama son derece güçlü bir - Supported Python versions + Supported Python versions

@@ -45,11 +45,11 @@ Temel özellikleri şunlardır: * **Hızlı**: Çok yüksek performanslı, **NodeJS** ve **Go** ile eşit düzeyde (Starlette ve Pydantic sayesinde). [Mevcut en hızlı Python framework'lerinden biri](#performance). * **Kodlaması Hızlı**: Özellik geliştirme hızını yaklaşık %200 ile %300 aralığında artırır. * * **Daha az hata**: İnsan (geliştirici) kaynaklı hataları yaklaşık %40 azaltır. * -* **Sezgisel**: Harika bir editör desteği. Her yerde Tamamlama. Hata ayıklamaya daha az zaman. +* **Sezgisel**: Harika bir editör desteği. Her yerde Tamamlama. Hata ayıklamaya daha az zaman. * **Kolay**: Kullanımı ve öğrenmesi kolay olacak şekilde tasarlandı. Doküman okumaya daha az zaman. * **Kısa**: Kod tekrarını minimize eder. Her parametre tanımından birden fazla özellik. Daha az hata. * **Sağlam**: Production'a hazır kod elde edersiniz. Otomatik etkileşimli dokümantasyon ile birlikte. -* **Standardlara dayalı**: API'lar için açık standartlara dayalıdır (ve tamamen uyumludur); [OpenAPI](https://github.com/OAI/OpenAPI-Specification) (önceden Swagger olarak biliniyordu) ve [JSON Schema](https://json-schema.org/). +* **Standartlara dayalı**: API'lar için açık standartlara dayalıdır (ve tamamen uyumludur); [OpenAPI](https://github.com/OAI/OpenAPI-Specification) (önceden Swagger olarak biliniyordu) ve [JSON Schema](https://json-schema.org/). * tahmin, production uygulamalar geliştiren dahili bir geliştirme ekibinin yaptığı testlere dayanmaktadır. @@ -492,9 +492,7 @@ Daha fazla özellik içeren daha kapsamlı bir örnek için @@ -510,6 +508,8 @@ Deploying to FastAPI Cloud...
+CLI, FastAPI uygulamanızı otomatik olarak algılar ve cloud'a deploy eder. Giriş yapmadıysanız, kimlik doğrulama sürecini tamamlamak için tarayıcınız açılır. + Hepsi bu! Artık uygulamanıza bu URL'den erişebilirsiniz. ✨ #### FastAPI Cloud hakkında { #about-fastapi-cloud } diff --git a/docs/tr/docs/project-generation.md b/docs/tr/docs/project-generation.md index 6c73a942d..3dfe7a9a7 100644 --- a/docs/tr/docs/project-generation.md +++ b/docs/tr/docs/project-generation.md @@ -1,5 +1,6 @@ # Full Stack FastAPI Şablonu { #full-stack-fastapi-template } + Şablonlar genellikle belirli bir kurulumla gelir, ancak esnek ve özelleştirilebilir olacak şekilde tasarlanırlar. Bu sayede şablonu projenizin gereksinimlerine göre değiştirip uyarlayabilir, çok iyi bir başlangıç noktası olarak kullanabilirsiniz. 🏁 Bu şablonu başlangıç için kullanabilirsiniz; çünkü ilk kurulumun, güvenliğin, veritabanının ve bazı API endpoint'lerinin önemli bir kısmı sizin için zaten hazırlanmıştır. diff --git a/docs/tr/docs/python-types.md b/docs/tr/docs/python-types.md index f3a3447f1..69f256d00 100644 --- a/docs/tr/docs/python-types.md +++ b/docs/tr/docs/python-types.md @@ -1,5 +1,6 @@ # Python Tiplerine Giriş { #python-types-intro } + Python, isteğe bağlı "type hints" (diğer adıyla "type annotations") desteğine sahiptir. Bu **"type hints"** veya annotations, bir değişkenin tip'ini bildirmeye yarayan özel bir sözdizimidir. diff --git a/docs/tr/docs/tutorial/bigger-applications.md b/docs/tr/docs/tutorial/bigger-applications.md index fb0d2e73d..81866e8f7 100644 --- a/docs/tr/docs/tutorial/bigger-applications.md +++ b/docs/tr/docs/tutorial/bigger-applications.md @@ -17,16 +17,16 @@ Diyelim ki şöyle bir dosya yapınız var: ``` . ├── app -│   ├── __init__.py -│   ├── main.py -│   ├── dependencies.py -│   └── routers -│   │ ├── __init__.py -│   │ ├── items.py -│   │ └── users.py -│   └── internal -│   ├── __init__.py -│   └── admin.py +│ ├── __init__.py +│ ├── main.py +│ ├── dependencies.py +│ └── routers +│ │ ├── __init__.py +│ │ ├── items.py +│ │ └── users.py +│ └── internal +│ ├── __init__.py +│ └── admin.py ``` /// tip | İpucu @@ -44,7 +44,7 @@ from app.routers import items /// * `app` dizini her şeyi içerir. Ayrıca boş bir `app/__init__.py` dosyası olduğu için bir "Python package" (bir "Python module" koleksiyonu) olur: `app`. -* İçinde bir `app/main.py` dosyası vardır. Bir Python package'in (içinde `__init__.py` dosyası olan bir dizinin) içinde olduğundan, o package'in bir "module"’üdür: `app.main`. +* İçinde bir `app/main.py` dosyası vardır. Bir Python package’in (içinde `__init__.py` dosyası olan bir dizinin) içinde olduğundan, o package’in bir "module"’üdür: `app.main`. * Benzer şekilde `app/dependencies.py` dosyası da bir "module"’dür: `app.dependencies`. * `app/routers/` adında bir alt dizin vardır ve içinde başka bir `__init__.py` dosyası bulunur; dolayısıyla bu bir "Python subpackage"’dir: `app.routers`. * `app/routers/items.py` dosyası `app/routers/` package’i içinde olduğundan bir submodule’dür: `app.routers.items`. @@ -138,7 +138,7 @@ Diyelim ki uygulamanızdaki "items" ile ilgili endpoint'ler de `app/routers/item Bu, `app/routers/users.py` ile aynı yapıdadır. -Namun biraz daha akıllı davranıp kodu sadeleştirmek istiyoruz. +Ancak biraz daha akıllı davranıp kodu sadeleştirmek istiyoruz. Bu module’deki tüm *path operation*’ların şu ortak özelliklere sahip olduğunu biliyoruz: @@ -230,7 +230,7 @@ from .dependencies import get_token_header * `dependencies` module’ünü bul (`app/routers/dependencies.py` gibi hayali bir dosya)... * ve oradan `get_token_header` function’ını import et. -Ama o dosya yok; bizim dependency’lerimiz `app/dependencies.py` dosyasında. +Ancak o dosya yok; bizim dependency’lerimiz `app/dependencies.py` dosyasında. Uygulama/dosya yapımızın nasıl göründüğünü hatırlayın: @@ -396,17 +396,17 @@ Böylece o router içindeki tüm route’lar uygulamanın bir parçası olarak d /// note | Teknik Detaylar -Aslında içeride, `APIRouter` içinde tanımlanan her *path operation* için bir *path operation* oluşturur. +Router ana uygulamaya dahil edildiğinde FastAPI, orijinal `APIRouter`’ı ve içindeki `APIRoute`’ları etkin tutar. -Yani perde arkasında, her şey tek bir uygulamaymış gibi çalışır. +Bu da, özel (custom) `APIRouter` ve `APIRoute` alt sınıflarının, router dahil edildikten sonra da işleyişe katılabileceği anlamına gelir. /// /// tip | İpucu -Router’ları dahil ederken performans konusunda endişelenmeniz gerekmez. +Router’ları dahil ederken performans konusunda endişelenmeyin. -Bu işlem mikrosaniyeler sürer ve sadece startup sırasında olur. +Bu mekanizma hafif olacak ve her request'e ek yük bindirmeyecek şekilde tasarlanmıştır. Dolayısıyla performansı etkilemez. ⚡ @@ -453,15 +453,15 @@ ve `app.include_router()` ile eklenen diğer tüm *path operation*’larla birli /// note | Çok Teknik Detaylar -**Not**: Bu oldukça teknik bir detay; büyük ihtimalle **direkt geçebilirsiniz**. +Not: Bu, muhtemelen doğrudan atlayabileceğiniz oldukça teknik bir detaydır. --- `APIRouter`’lar "mount" edilmez; uygulamanın geri kalanından izole değildir. -Çünkü *path operation*’larını OpenAPI şemasına ve kullanıcı arayüzlerine dahil etmek istiyoruz. +Bunun nedeni, onların *path operation*’larını OpenAPI şemasına ve kullanıcı arayüzlerine dahil etmek istememizdir. -Onları tamamen izole edip bağımsız şekilde "mount" edemediğimiz için, *path operation*’lar doğrudan eklenmek yerine "klonlanır" (yeniden oluşturulur). +FastAPI, orijinal router’ları ve *path operation*’ları etkin tutar; istekleri işlerken ve OpenAPI üretirken router prefix’lerini, dependency’leri, tag’leri, responses’ları ve diğer metaverileri birleştirir. /// @@ -490,7 +490,7 @@ Komuta dosya yolunu da verebilirsiniz, örneğin: $ fastapi dev app/main.py ``` -Ama o zaman her `fastapi` komutunu çalıştırdığınızda doğru yolu hatırlayıp geçirmeniz gerekir. +Ancak o zaman her `fastapi` komutunu çalıştırdığınızda doğru yolu hatırlayıp geçirmeniz gerekir. Ayrıca, diğer araçlar uygulamayı bulamayabilir; örneğin [VS Code Eklentisi](../editor-support.md) veya [FastAPI Cloud](https://fastapicloud.com). Bu yüzden `pyproject.toml` içinde `entrypoint` kullanmanız önerilir. @@ -532,4 +532,16 @@ Bir `APIRouter`’ı `FastAPI` uygulamasına dahil ettiğiniz gibi, bir `APIRout router.include_router(other_router) ``` -`router`’ı `FastAPI` uygulamasına dahil etmeden önce bunu yaptığınızdan emin olun; böylece `other_router` içindeki *path operation*’lar da dahil edilmiş olur. +Bunu, `router`’ı `FastAPI` uygulamasına dahil etmeden önce de sonra da yapabilirsiniz. FastAPI, `other_router` içindeki *path operation*’ları yönlendirmeye (routing) ve OpenAPI’ye yine dahil eder. + +Aynı şey, router’lara daha sonra eklenen *path operation*’lar için de geçerlidir. Önceden yapılmış dahil etme üzerinden de görünür olurlar. + +/// warning | Teknik Detaylar + +Bir router’ı dahil ettikten sonra `router.routes`’i doğrudan değiştirmekten kaçının. FastAPI, router dahilini canlı (live) kabul eder; bu nedenle orijinal router ve içindeki route’lar, yönlendirme ve OpenAPI üretiminin bir parçası olarak kalır. + +Route ve router eklemek için path operation decorator’ları ve `.include_router()` gibi belgelenmiş API’leri kullanın. + +`router.routes`’i, route tanımlarını ve dahil edilmiş router’ları barındırabilen daha alt seviye bir route ağacı olarak düşünün; bunu nihai *path operation*’ların düz bir listesiymiş gibi kullanmaktan kaçının. + +/// diff --git a/docs/tr/docs/tutorial/body-multiple-params.md b/docs/tr/docs/tutorial/body-multiple-params.md index 4cd381b86..be6ab676d 100644 --- a/docs/tr/docs/tutorial/body-multiple-params.md +++ b/docs/tr/docs/tutorial/body-multiple-params.md @@ -111,7 +111,7 @@ q: str | None = None {* ../../docs_src/body_multiple_params/tutorial004_an_py310.py hl[28] *} -/// info | Bilgi +/// note | Not `Body`, `Query`, `Path` ve daha sonra göreceğiniz diğerleriyle aynı ek validasyon ve metadata parametrelerine de sahiptir. @@ -126,7 +126,7 @@ Varsayılan olarak **FastAPI**, body'nin doğrudan bu modelin içeriği olmasın Ancak, ek body parametreleri tanımladığınızda olduğu gibi, `item` anahtarı olan bir JSON ve onun içinde modelin içeriğini beklemesini istiyorsanız, `Body`'nin özel parametresi olan `embed`'i kullanabilirsiniz: ```Python -item: Item = Body(embed=True) +item: Annotated[Item, Body(embed=True)] ``` yani şöyle: diff --git a/docs/tr/docs/tutorial/body-nested-models.md b/docs/tr/docs/tutorial/body-nested-models.md index 4f078e035..d9f30c862 100644 --- a/docs/tr/docs/tutorial/body-nested-models.md +++ b/docs/tr/docs/tutorial/body-nested-models.md @@ -1,5 +1,6 @@ # Body - İç İçe Modeller { #body-nested-models } + **FastAPI** ile (Pydantic sayesinde) istediğiniz kadar derin iç içe geçmiş modelleri tanımlayabilir, doğrulayabilir, dokümante edebilir ve kullanabilirsiniz. ## List alanları { #list-fields } @@ -135,7 +136,7 @@ Bu, aşağıdaki gibi bir JSON body bekler (dönüştürür, doğrular, doküman } ``` -/// info | Bilgi +/// note | Not `images` key’inin artık image object’lerinden oluşan bir list içerdiğine dikkat edin. @@ -147,7 +148,7 @@ Bu, aşağıdaki gibi bir JSON body bekler (dönüştürür, doğrular, doküman {* ../../docs_src/body_nested_models/tutorial007_py310.py hl[7,12,18,21,25] *} -/// info | Bilgi +/// note | Not `Offer`’ın bir `Item` list’i olduğuna, `Item`’ların da opsiyonel bir `Image` list’ine sahip olduğuna dikkat edin. diff --git a/docs/tr/docs/tutorial/body.md b/docs/tr/docs/tutorial/body.md index 26f51ffec..d05bd54ec 100644 --- a/docs/tr/docs/tutorial/body.md +++ b/docs/tr/docs/tutorial/body.md @@ -1,5 +1,6 @@ # Request Body { #request-body } + Bir client'ten (örneğin bir tarayıcıdan) API'nize veri göndermeniz gerektiğinde, bunu **request body** olarak gönderirsiniz. Bir **request** body, client'in API'nize gönderdiği veridir. Bir **response** body ise API'nizin client'e gönderdiği veridir. @@ -8,7 +9,7 @@ API'niz neredeyse her zaman bir **response** body göndermek zorundadır. Ancak Bir **request** body tanımlamak için, tüm gücü ve avantajlarıyla [Pydantic](https://docs.pydantic.dev/) modellerini kullanırsınız. -/// info | Bilgi +/// note | Not Veri göndermek için şunlardan birini kullanmalısınız: `POST` (en yaygını), `PUT`, `DELETE` veya `PATCH`. diff --git a/docs/tr/docs/tutorial/cookie-param-models.md b/docs/tr/docs/tutorial/cookie-param-models.md index 0fa399c6a..9b4984bcf 100644 --- a/docs/tr/docs/tutorial/cookie-param-models.md +++ b/docs/tr/docs/tutorial/cookie-param-models.md @@ -6,7 +6,7 @@ Bu sayede **model'i yeniden kullanabilir**, **birden fazla yerde** tekrar tekrar /// note | Not -This is supported since FastAPI version `0.115.0`. 🤓 +Bu özellik FastAPI'nin `0.115.0` sürümünden itibaren desteklenmektedir. 🤓 /// @@ -32,7 +32,7 @@ Tanımlanan cookie'leri `/docs` altındaki docs UI'da görebilirsiniz:
-/// info | Bilgi +/// note | Not Tarayıcıların cookie'leri özel biçimlerde ve arka planda yönetmesi nedeniyle, **JavaScript**'in cookie'lere erişmesine kolayca izin vermediğini aklınızda bulundurun. diff --git a/docs/tr/docs/tutorial/cookie-params.md b/docs/tr/docs/tutorial/cookie-params.md index 28b57fd7e..2cec37fd0 100644 --- a/docs/tr/docs/tutorial/cookie-params.md +++ b/docs/tr/docs/tutorial/cookie-params.md @@ -24,13 +24,13 @@ Ancak `fastapi`'dan `Query`, `Path`, `Cookie` ve diğerlerini import ettiğinizd /// -/// info | Bilgi +/// note | Not Cookie'leri tanımlamak için `Cookie` kullanmanız gerekir, aksi halde parametreler query parametreleri olarak yorumlanır. /// -/// info | Bilgi +/// note | Not **Tarayıcılar cookie'leri** özel şekillerde ve arka planda işlediği için, **JavaScript**'in onlara dokunmasına kolayca izin **vermezler**. diff --git a/docs/tr/docs/tutorial/debugging.md b/docs/tr/docs/tutorial/debugging.md index 48f99e99c..b73d65137 100644 --- a/docs/tr/docs/tutorial/debugging.md +++ b/docs/tr/docs/tutorial/debugging.md @@ -59,7 +59,7 @@ Yani örneğin `importer.py` adında başka bir dosyanız var ve içinde şunlar ```Python from myapp import app -# Some more code +# Biraz daha kod ``` bu durumda `myapp.py` içindeki otomatik oluşturulan `__name__` değişkeni `"__main__"` değerine sahip olmaz. diff --git a/docs/tr/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md b/docs/tr/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md index 8764d736f..caafcafaa 100644 --- a/docs/tr/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md +++ b/docs/tr/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md @@ -28,7 +28,7 @@ Ayrıca kodunuzda kullanılmayan bir parametreyi gören yeni geliştiricilerin b /// -/// info | Bilgi +/// note | Not Bu örnekte uydurma özel header'lar olan `X-Key` ve `X-Token` kullanıyoruz. diff --git a/docs/tr/docs/tutorial/dependencies/dependencies-with-yield.md b/docs/tr/docs/tutorial/dependencies/dependencies-with-yield.md index 5ed7660c5..be9588297 100644 --- a/docs/tr/docs/tutorial/dependencies/dependencies-with-yield.md +++ b/docs/tr/docs/tutorial/dependencies/dependencies-with-yield.md @@ -1,6 +1,6 @@ # `yield` ile Dependency'ler { #dependencies-with-yield } -FastAPI, işini bitirdikten sonra ek adımlar çalıştıran dependency'leri destekler. +FastAPI, işini bitirdikten sonra ek adımlar çalıştıran dependency'leri destekler. Bunu yapmak için `return` yerine `yield` kullanın ve ek adımları (kodu) `yield` satırından sonra yazın. @@ -111,7 +111,7 @@ Ama ihtiyaç duyarsanız diye burada. 🤓 {* ../../docs_src/dependencies/tutorial008b_an_py310.py hl[18:22,31] *} -Exception yakalayıp buna göre özel bir response oluşturmak istiyorsanız bir [Custom Exception Handler](../handling-errors.md#install-custom-exception-handlers) oluşturun. +Exception yakalayıp buna göre özel bir response oluşturmak istiyorsanız bir [Özel Exception Handler](../handling-errors.md#install-custom-exception-handlers) oluşturun. ## `yield` ve `except` ile Dependency'ler { #dependencies-with-yield-and-except } @@ -170,7 +170,7 @@ participant tasks as Background tasks end ``` -/// info | Bilgi +/// note | Not Client'a yalnızca **tek bir response** gönderilir. Bu, error response'lardan biri olabilir ya da *path operation*'dan dönen response olabilir. @@ -233,7 +233,8 @@ participant operation as Path Operation `yield` kullanan dependency'ler, zaman içinde farklı kullanım senaryolarını kapsamak ve bazı sorunları düzeltmek için gelişti. -FastAPI'nin farklı sürümlerinde nelerin değiştiğini görmek isterseniz, advanced guide'da şu bölümü okuyabilirsiniz: [Advanced Dependencies - Dependencies with `yield`, `HTTPException`, `except` and Background Tasks](../../advanced/advanced-dependencies.md#dependencies-with-yield-httpexception-except-and-background-tasks). +FastAPI'nin farklı sürümlerinde nelerin değiştiğini görmek isterseniz, gelişmiş kılavuzda şu bölümü okuyabilirsiniz: [Gelişmiş Dependency'ler - `yield`, `HTTPException`, `except` ve Background Tasks ile Dependency'ler](../../advanced/advanced-dependencies.md#dependencies-with-yield-httpexception-except-and-background-tasks). + ## Context Managers { #context-managers } ### "Context Managers" Nedir? { #what-are-context-managers } diff --git a/docs/tr/docs/tutorial/dependencies/index.md b/docs/tr/docs/tutorial/dependencies/index.md index 6cf626e05..21809fc0a 100644 --- a/docs/tr/docs/tutorial/dependencies/index.md +++ b/docs/tr/docs/tutorial/dependencies/index.md @@ -51,7 +51,7 @@ Bu örnekte, bu dependency şunları bekler: Sonra da bu değerleri içeren bir `dict` döndürür. -/// info | Bilgi +/// note | Not FastAPI, `Annotated` desteğini 0.95.0 sürümünde ekledi (ve önermeye başladı). @@ -106,7 +106,7 @@ common_parameters --> read_users Bu şekilde paylaşılan kodu bir kez yazarsınız ve onu *path operation*'larda çağırma işini **FastAPI** halleder. -/// check | Ek bilgi +/// tip | İpucu Dikkat edin: Bunu "register" etmek ya da benzeri bir şey yapmak için özel bir class oluşturup **FastAPI**'ye bir yere geçirmeniz gerekmez. diff --git a/docs/tr/docs/tutorial/dependencies/sub-dependencies.md b/docs/tr/docs/tutorial/dependencies/sub-dependencies.md index ab196d829..706b5a4f7 100644 --- a/docs/tr/docs/tutorial/dependencies/sub-dependencies.md +++ b/docs/tr/docs/tutorial/dependencies/sub-dependencies.md @@ -35,7 +35,7 @@ Sonra bu bağımlılığı şöyle kullanabiliriz: {* ../../docs_src/dependencies/tutorial005_an_py310.py hl[23] *} -/// info | Bilgi +/// note | Not Dikkat edin, *path operation function* içinde yalnızca tek bir bağımlılık tanımlıyoruz: `query_or_cookie_extractor`. diff --git a/docs/tr/docs/tutorial/extra-data-types.md b/docs/tr/docs/tutorial/extra-data-types.md index 93ae034b2..da0aab01b 100644 --- a/docs/tr/docs/tutorial/extra-data-types.md +++ b/docs/tr/docs/tutorial/extra-data-types.md @@ -53,7 +53,7 @@ Kullanabileceğiniz ek veri tiplerinden bazıları şunlardır: ## Örnek { #example } -Yukarıdaki tiplerden bazılarını kullanan parametrelere sahip bir örnek *path operation* şöyle: +Yukarıdaki tiplerden bazılarını kullanan parametrelere sahip bir örnek *path operation*: {* ../../docs_src/extra_data_types/tutorial001_an_py310.py hl[1,3,12:16] *} diff --git a/docs/tr/docs/tutorial/extra-models.md b/docs/tr/docs/tutorial/extra-models.md index d25a80aad..9a499b30b 100644 --- a/docs/tr/docs/tutorial/extra-models.md +++ b/docs/tr/docs/tutorial/extra-models.md @@ -1,5 +1,6 @@ # Ek Modeller { #extra-models } + Önceki örnekten devam edersek, birbiriyle ilişkili birden fazla modelin olması oldukça yaygındır. Bu durum özellikle kullanıcı modellerinde sık görülür, çünkü: diff --git a/docs/tr/docs/tutorial/first-steps.md b/docs/tr/docs/tutorial/first-steps.md index 0ffa28dbf..5147f2577 100644 --- a/docs/tr/docs/tutorial/first-steps.md +++ b/docs/tr/docs/tutorial/first-steps.md @@ -1,5 +1,6 @@ # İlk Adımlar { #first-steps } + En sade FastAPI dosyası şu şekilde görünür: {* ../../docs_src/first_steps/tutorial001_py310.py *} @@ -180,7 +181,7 @@ Bu da şuna eşdeğer olur: from backend.main import app ``` -### Path ile `fastapi dev` { #fastapi-dev-with-path } +### Path ile veya `--entrypoint` CLI seçeneğiyle `fastapi dev` { #fastapi-dev-with-path-or-with-entrypoint-cli-option } Dosya path'ini `fastapi dev` komutuna da verebilirsiniz; hangi FastAPI app objesini kullanacağını tahmin eder: @@ -188,29 +189,19 @@ Dosya path'ini `fastapi dev` komutuna da verebilirsiniz; hangi FastAPI app objes $ fastapi dev main.py ``` -Ancak `fastapi` komutunu her çağırdığınızda doğru path'i geçmeyi hatırlamanız gerekir. - -Ayrıca, [VS Code Eklentisi](../editor-support.md) veya [FastAPI Cloud](https://fastapicloud.com) gibi başka araçlar da onu bulamayabilir; bu yüzden `pyproject.toml` içindeki `entrypoint`'i kullanmanız önerilir. - -### Uygulamanızı Yayınlayın (opsiyonel) { #deploy-your-app-optional } - -İsterseniz FastAPI uygulamanızı [FastAPI Cloud](https://fastapicloud.com)'a deploy edebilirsiniz; henüz katılmadıysanız gidip bekleme listesine yazılın. 🚀 - -Zaten bir **FastAPI Cloud** hesabınız varsa (bekleme listesinden sizi davet ettiysek 😉), uygulamanızı tek komutla deploy edebilirsiniz. - -Deploy etmeden önce giriş yaptığınızdan emin olun: - -
+Veya `fastapi dev` komutuna `--entrypoint` seçeneğini de geçebilirsiniz: ```console -$ fastapi login - -You are logged in to FastAPI Cloud 🚀 +$ fastapi dev --entrypoint main:app ``` -
+Ancak `fastapi` komutunu her çağırdığınızda doğru path'i veya entrypoint'i geçmeyi hatırlamanız gerekir. -Ardından uygulamanızı deploy edin: +Ayrıca, [VS Code Eklentisi](../editor-support.md) veya [FastAPI Cloud](https://fastapicloud.com) gibi başka araçlar da onu bulamayabilir; bu yüzden `pyproject.toml` içindeki `entrypoint`'i kullanmanız önerilir. + +### Uygulamanızı Yayınlayın (opsiyonel) { #deploy-your-app-optional } + +İsterseniz FastAPI uygulamanızı [FastAPI Cloud](https://fastapicloud.com)'a tek komutla deploy edebilirsiniz. 🚀
@@ -226,6 +217,8 @@ Deploying to FastAPI Cloud...
+CLI, FastAPI uygulamanızı otomatik olarak algılar ve buluta deploy eder. Giriş yapmadıysanız, kimlik doğrulama işlemini tamamlamak için tarayıcınız açılır. + Bu kadar! Artık uygulamanıza o URL üzerinden erişebilirsiniz. ✨ ## Adım Adım Özetleyelim { #recap-step-by-step } @@ -270,7 +263,7 @@ https://example.com/items/foo /items/foo ``` -/// info | Bilgi +/// note | Not Bir "path" genellikle "endpoint" veya "route" olarak da adlandırılır. @@ -322,7 +315,7 @@ Biz de bunlara "**operation**" diyeceğiz. * path `/` * get operation kullanarak -/// info | `@decorator` Bilgisi +/// note | `@decorator` Bilgisi Python'daki `@something` söz dizimi "decorator" olarak adlandırılır. diff --git a/docs/tr/docs/tutorial/frontend.md b/docs/tr/docs/tutorial/frontend.md new file mode 100644 index 000000000..7918ca593 --- /dev/null +++ b/docs/tr/docs/tutorial/frontend.md @@ -0,0 +1,133 @@ +# Frontend { #frontend } + +Statik frontend uygulamalarını `app.frontend()` (veya `router.frontend()`) ile sunabilirsiniz. + +Bu, Vite ile React, TanStack Router, Astro, Vue, Svelte, Angular, Solid ve benzeri statik dosyalar üreten frontend araçları için kullanışlıdır. + +Bu araçlarda genellikle frontend'i build eden bir adım olur, örneğin şöyle bir komutla: + +```bash +npm run build +``` + +Bu komut, frontend dosyalarınızla birlikte `./dist/` gibi bir dizin oluşturur. + +Bu dizini, frontend framework'lerinin ihtiyaç duyduğu kurallara uygun şekilde sunmak için `app.frontend()` kullanabilirsiniz. + +**FastAPI** önce *path operation*'ları kontrol eder. Frontend dosyaları yalnızca hiçbir normal route eşleşmezse kontrol edilir, bu yüzden API'niz bundan etkilenmez. + +## Frontend Sunma { #serve-a-frontend } + +Frontend'inizi build ettikten sonra, örneğin `npm run build` ile, oluşturulan dosyaları bir dizine koyun; örneğin `dist`. + +Proje yapınız şöyle görünebilir: + +```text +. +├── pyproject.toml +├── app +│ ├── __init__.py +│ └── main.py +└── dist + ├── index.html + └── assets + └── app.js +``` + +Ardından bunu `app.frontend()` ile sunun: + +{* ../../docs_src/frontend/tutorial001_py310.py hl[5] *} + +Böylece `/assets/app.js` için gelen bir request, `dist/assets/app.js` dosyasını sunabilir. + +Aynı zamanda bir **FastAPI** *path operation*'ınız varsa, öncelik *path operation*'dadır. + +## Client-Side Routing { #client-side-routing } + +**Single-page app**'ler (SPA'ler) dahil birçok frontend uygulaması client-side routing kullanır. `/dashboard/settings` gibi bir path gerçek bir dosya olmayabilir; bunu frontend framework'ü ele alır. + +Bu yüzden, o URL'ye doğrudan erişildiğinde (uygulama içinde gezinmek yerine), backend frontend uygulamasını `index.html` üzerinden sunmalıdır. Böylece frontend framework'ü client-side routing'i işleyebilir. + +Bunun için `fallback="index.html"` kullanın: + +{* ../../docs_src/frontend/tutorial002_py310.py hl[5] *} + +**FastAPI** bu fallback'i yalnızca tarayıcı gezinmesi gibi görünen `GET` ve `HEAD` request'leri için kullanır. JavaScript, CSS ve görseller gibi eksik dosyalar yine `404` döndürür. + +`POST` veya `PUT` gibi diğer metotlarla, yalnızca frontend fallback'i ile eşleşen path'lere yapılan request'ler de `404` döndürür. Normal **FastAPI** *path operation*'ları frontend route'larından yine daha yüksek önceliğe sahiptir. + +/// tip | İpucu + +Varsayılan olarak `fallback`, `fallback="auto"` değerine sahiptir. Çoğu durumda `fallback` belirtmeniz gerekmez. Detaylar için aşağıyı okuyun. + +/// + +Client-side routing kullanan birçok frontend uygulamasında istediğiniz davranış budur; örneğin TanStack Router ile React, Vue, Angular, SvelteKit veya Solid. + +## Özel 404 Sayfası { #custom-404-page } + +Bulunamayan frontend path'leri için statik bir `404.html` sayfası da sunabilirsiniz: + +{* ../../docs_src/frontend/tutorial003_py310.py hl[5] *} + +Bu response, `404` status code'unu korur. + +Bu durumda **FastAPI**, bulunamayan frontend path'leri için `index.html` sunmaz. Bunun yerine `404.html` dosyasını döndürür. + +/// tip | İpucu + +Varsayılan olarak `fallback`, `fallback="auto"` değerine sahiptir. Bu durumda bir `404.html` dosyası bulunursa, otomatik olarak fallback olarak kullanılır. + +Bu yüzden normalde `fallback` argümanını atlayabilirsiniz. + +/// + +Bu, Astro gibi her sayfa için statik HTML dosyaları üreten frontend araçlarıyla kullanışlıdır. + +## Otomatik Fallback { #fallback-auto } + +Varsayılan olarak `app.frontend()`, `fallback="auto"` kullanır. + +Frontend dizininde bir `404.html` dosyası varsa, bulunamayan frontend path'leri bu dosyayı `404` status code'u ile sunar. + +Aksi halde bir `index.html` dosyası varsa, bulunamayan tarayıcı gezinme path'leri `index.html` sunar. Client-side routing kullanan birçok frontend uygulamasının beklediği davranış budur. + +Bu yüzden çoğu durumda `fallback` argümanını belirtmeden `app.frontend("/", directory="dist")` kullanabilirsiniz. + +{* ../../docs_src/frontend/tutorial001_py310.py hl[5] *} + +## Fallback'i Devre Dışı Bırakma { #disable-fallback } + +Bulunamayan frontend path'leri için fallback dosyası sunmak istemiyorsanız `fallback=None` kullanın: + +{* ../../docs_src/frontend/tutorial005_py310.py hl[5] *} + +Bundan sonra bulunamayan frontend path'leri normal `404` döndürür. + +## Dizini Kontrol Etme { #check-directory } + +Varsayılan olarak `app.frontend()`, uygulama oluşturulduğunda dizinin var olduğunu kontrol eder. + +Bu, yapılandırma hatalarını erken yakalamaya yardımcı olur. Örneğin frontend build çıktısı dizini yoksa, **FastAPI** başlangıçta hata verir. + +Frontend dosyalarınız daha sonra oluşturuluyorsa, örneğin app nesnesi oluşturulduktan sonra ayrı bir build adımıyla, `check_dir=False` ayarlayın: + +{* ../../docs_src/frontend/tutorial006_py310.py hl[5] *} + +`check_dir=False` ile **FastAPI**, app oluşturulduğunda dizini kontrol etmez. Yapılandırılan dizin bir request işlendiği sırada hâlâ yoksa, **FastAPI** o zaman hata verir. + +## `APIRouter` ile Kullanma { #use-it-with-apirouter } + +Frontend dosyalarını bir `APIRouter`'a da ekleyebilir ve bunu bir prefix ile dahil edebilirsiniz: + +{* ../../docs_src/frontend/tutorial004_py310.py hl[6,7] *} + +Bu örnekte frontend path'leri `/app` altında sunulur. + +Uygulamadaki herhangi bir normal *path operation*, diğer router'larda olanlar dahil, yine öncelikli olur. + +## Yalnızca Statik Build Çıktısı { #static-build-output-only } + +`app.frontend()`, frontend build'iniz tarafından önceden oluşturulmuş dosyaları sunar. + +Server-side rendering çalıştırmaz. Her request için server'da dinamik rendering gerektiren framework'ler için değil, statik dosyalar üreten frontend framework'leri içindir. diff --git a/docs/tr/docs/tutorial/handling-errors.md b/docs/tr/docs/tutorial/handling-errors.md index b90e186a6..0339bde14 100644 --- a/docs/tr/docs/tutorial/handling-errors.md +++ b/docs/tr/docs/tutorial/handling-errors.md @@ -93,7 +93,7 @@ Ve bu exception’ı FastAPI ile global olarak handle etmek istiyorsunuz. Burada `/unicorns/yolo` için request atarsanız, *path operation* bir `UnicornException` `raise` eder. -Namun bu, `unicorn_exception_handler` tarafından handle edilir. +Ancak bu, `unicorn_exception_handler` tarafından handle edilir. Böylece HTTP status code’u `418` olan, JSON içeriği şu şekilde temiz bir hata response’u alırsınız: diff --git a/docs/tr/docs/tutorial/index.md b/docs/tr/docs/tutorial/index.md index 5dacd280a..e30f3bfbb 100644 --- a/docs/tr/docs/tutorial/index.md +++ b/docs/tr/docs/tutorial/index.md @@ -76,11 +76,11 @@ $ pip install "fastapi[standard]" /// note | Not -`pip install "fastapi[standard]"` ile kurduğunuzda, bazı varsayılan opsiyonel standard bağımlılıklarla birlikte gelir. Bunlara `fastapi-cloud-cli` da dahildir; bu sayede [FastAPI Cloud](https://fastapicloud.com)'a deploy edebilirsiniz. +`pip install "fastapi[standard]"` ile kurduğunuzda, bazı varsayılan opsiyonel standart bağımlılıklarla birlikte gelir. Bunlara `fastapi-cloud-cli` da dahildir; bu sayede [FastAPI Cloud](https://fastapicloud.com)'a deploy edebilirsiniz. Bu opsiyonel bağımlılıkları istemiyorsanız bunun yerine `pip install fastapi` kurabilirsiniz. -Standard bağımlılıkları kurmak istiyor ama `fastapi-cloud-cli` olmasın diyorsanız, `pip install "fastapi[standard-no-fastapi-cloud-cli]"` ile kurabilirsiniz. +Standart bağımlılıkları kurmak istiyor ama `fastapi-cloud-cli` olmasın diyorsanız, `pip install "fastapi[standard-no-fastapi-cloud-cli]"` ile kurabilirsiniz. /// diff --git a/docs/tr/docs/tutorial/metadata.md b/docs/tr/docs/tutorial/metadata.md index a8d44570f..8b97505e4 100644 --- a/docs/tr/docs/tutorial/metadata.md +++ b/docs/tr/docs/tutorial/metadata.md @@ -11,7 +11,7 @@ OpenAPI spesifikasyonunda ve otomatik API doküman arayüzlerinde kullanılan ş | `title` | `str` | API'nin başlığı. | | `summary` | `str` | API'nin kısa özeti. OpenAPI 3.1.0, FastAPI 0.99.0 sürümünden itibaren mevcut. | | `description` | `str` | API'nin kısa açıklaması. Markdown kullanabilir. | -| `version` | `string` | API'nin sürümü. Bu, OpenAPI'nin değil, kendi uygulamanızın sürümüdür. Örneğin `2.5.0`. | +| `version` | `str` | API'nin sürümü. Bu, OpenAPI'nin değil, kendi uygulamanızın sürümüdür. Örneğin `2.5.0`. | | `terms_of_service` | `str` | API'nin Kullanım Koşulları (Terms of Service) için bir URL. Verilirse, URL formatında olmalıdır. | | `contact` | `dict` | Yayınlanan API için iletişim bilgileri. Birden fazla alan içerebilir.
contact alanları
ParametreTipAçıklama
namestrİletişim kişisi/kuruluşunu tanımlayan ad.
urlstrİletişim bilgilerine işaret eden URL. URL formatında OLMALIDIR.
emailstrİletişim kişisi/kuruluşunun e-posta adresi. E-posta adresi formatında OLMALIDIR.
| | `license_info` | `dict` | Yayınlanan API için lisans bilgileri. Birden fazla alan içerebilir.
license_info alanları
ParametreTipAçıklama
namestrZORUNLU (license_info ayarlanmışsa). API için kullanılan lisans adı.
identifierstrAPI için bir [SPDX](https://spdx.org/licenses/) lisans ifadesi. identifier alanı, url alanıyla karşılıklı olarak dışlayıcıdır (ikisi aynı anda kullanılamaz). OpenAPI 3.1.0, FastAPI 0.99.0 sürümünden itibaren mevcut.
urlstrAPI için kullanılan lisansa ait URL. URL formatında OLMALIDIR.
| @@ -74,9 +74,9 @@ Kullandığınız tüm tag'ler için metadata eklemek zorunda değilsiniz. {* ../../docs_src/metadata/tutorial004_py310.py hl[21,26] *} -/// info | Bilgi +/// note | Not -Tag'ler hakkında daha fazlası için: [Path Operation Configuration](path-operation-configuration.md#tags). +Tag'ler hakkında daha fazlası için: [Path Operation Yapılandırması](path-operation-configuration.md#tags). /// diff --git a/docs/tr/docs/tutorial/path-operation-configuration.md b/docs/tr/docs/tutorial/path-operation-configuration.md index 3653090af..ee4bc8739 100644 --- a/docs/tr/docs/tutorial/path-operation-configuration.md +++ b/docs/tr/docs/tutorial/path-operation-configuration.md @@ -1,5 +1,6 @@ # Path Operation Yapılandırması { #path-operation-configuration } + Onu yapılandırmak için *path operation decorator*’ınıza geçebileceğiniz çeşitli parametreler vardır. /// warning | Uyarı @@ -66,19 +67,19 @@ Interactive docs’ta şöyle kullanılacaktır: -## Response description { #response-description } +## Response Açıklaması { #response-description } `response_description` parametresi ile response açıklamasını belirtebilirsiniz: {* ../../docs_src/path_operation_configuration/tutorial005_py310.py hl[18] *} -/// info | Bilgi +/// note | Not `response_description` özellikle response’u ifade eder; `description` ise genel olarak *path operation*’ı ifade eder. /// -/// check | Ek bilgi +/// tip | İpucu OpenAPI, her *path operation* için bir response description zorunlu kılar. diff --git a/docs/tr/docs/tutorial/path-params-numeric-validations.md b/docs/tr/docs/tutorial/path-params-numeric-validations.md index 43da894bb..1e6121f99 100644 --- a/docs/tr/docs/tutorial/path-params-numeric-validations.md +++ b/docs/tr/docs/tutorial/path-params-numeric-validations.md @@ -8,7 +8,7 @@ {* ../../docs_src/path_params_numeric_validations/tutorial001_an_py310.py hl[1,3] *} -/// info | Bilgi +/// note | Not FastAPI, 0.95.0 sürümünde `Annotated` desteğini ekledi (ve bunu önermeye başladı). @@ -56,7 +56,7 @@ Dolayısıyla fonksiyonunuzu şöyle tanımlayabilirsiniz: {* ../../docs_src/path_params_numeric_validations/tutorial002_py310.py hl[7] *} -Namun şunu unutmayın: `Annotated` kullanırsanız bu problem olmaz; çünkü `Query()` veya `Path()` için fonksiyon parametresi default değerlerini kullanmıyorsunuz. +Ancak şunu unutmayın: `Annotated` kullanırsanız bu problem olmaz; çünkü `Query()` veya `Path()` için fonksiyon parametresi default değerlerini kullanmıyorsunuz. {* ../../docs_src/path_params_numeric_validations/tutorial002_an_py310.py *} @@ -131,7 +131,7 @@ Ayrıca sayısal doğrulamalar da tanımlayabilirsiniz: * `lt`: `l`ess `t`han * `le`: `l`ess than or `e`qual -/// info | Bilgi +/// note | Not `Query`, `Path` ve ileride göreceğiniz diğer class'lar ortak bir `Param` class'ının alt class'larıdır. diff --git a/docs/tr/docs/tutorial/path-params.md b/docs/tr/docs/tutorial/path-params.md index c29d8567e..d1a9b6fca 100644 --- a/docs/tr/docs/tutorial/path-params.md +++ b/docs/tr/docs/tutorial/path-params.md @@ -20,7 +20,7 @@ Standart Python tip belirteçlerini kullanarak path parametresinin tipini fonksi Bu durumda, `item_id` bir `int` olarak tanımlanır. -/// check | Ek bilgi +/// tip | İpucu Bu sayede, fonksiyon içinde hata denetimi, kod tamamlama vb. konularda editör desteğine kavuşursunuz. @@ -34,7 +34,7 @@ Bu örneği çalıştırıp tarayıcınızda [http://127.0.0.1:8000/items/3](htt {"item_id":3} ``` -/// check | Ek bilgi +/// tip | İpucu Dikkat edin: fonksiyonunuzun aldığı (ve döndürdüğü) değer olan `3`, string `"3"` değil, bir Python `int`'idir. @@ -66,7 +66,7 @@ Ancak tarayıcınızda [http://127.0.0.1:8000/items/foo](http://127.0.0.1:8000/i Aynı hata, şu örnekte olduğu gibi `int` yerine `float` verirseniz de ortaya çıkar: [http://127.0.0.1:8000/items/4.2](http://127.0.0.1:8000/items/4.2) -/// check | Ek bilgi +/// tip | İpucu Yani, aynı Python tip tanımıyla birlikte **FastAPI** size veri doğrulama sağlar. @@ -82,7 +82,7 @@ Tarayıcınızı [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs) adresi -/// check | Ek bilgi +/// tip | İpucu Yine, sadece aynı Python tip tanımıyla **FastAPI** size otomatik ve interaktif dokümantasyon (Swagger UI entegrasyonuyla) sağlar. diff --git a/docs/tr/docs/tutorial/query-params-str-validations.md b/docs/tr/docs/tutorial/query-params-str-validations.md index 7012cca20..831cfcb1d 100644 --- a/docs/tr/docs/tutorial/query-params-str-validations.md +++ b/docs/tr/docs/tutorial/query-params-str-validations.md @@ -1,5 +1,6 @@ # Query Parametreleri ve String Doğrulamaları { #query-parameters-and-string-validations } + **FastAPI**, parametreleriniz için ek bilgi ve doğrulamalar (validation) tanımlamanıza izin verir. Örnek olarak şu uygulamayı ele alalım: @@ -29,7 +30,7 @@ Bunu yapmak için önce şunları import edin: {* ../../docs_src/query_params_str_validations/tutorial002_an_py310.py hl[1,3] *} -/// info | Bilgi +/// note | Not FastAPI, 0.95.0 sürümünde `Annotated` desteğini ekledi (ve önermeye başladı). @@ -348,7 +349,7 @@ O zaman bir `alias` tanımlayabilirsiniz; bu alias, parametre değerini bulmak i Diyelim ki artık bu parametreyi istemiyorsunuz. -Bazı client’lar hâlâ kullandığı için bir süre tutmanız gerekiyor, ama dokümanların bunu açıkça deprecated olarak göstermesini istiyorsunuz. +Bazı client’lar hâlâ kullandığı için bir süre tutmanız gerekiyor, ama dokümanların bunu açıkça kullanımdan kalkmış olarak göstermesini istiyorsunuz. O zaman `Query`’ye `deprecated=True` parametresini geçin: @@ -382,7 +383,7 @@ Pydantic’te [`BeforeValidator`](https://docs.pydantic.dev/latest/concepts/vali {* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py hl[5,16:19,24] *} -/// info | Bilgi +/// note | Not Bu özellik Pydantic 2 ve üzeri sürümlerde mevcuttur. 😎 diff --git a/docs/tr/docs/tutorial/query-params.md b/docs/tr/docs/tutorial/query-params.md index fa485f51a..4f12c4fad 100644 --- a/docs/tr/docs/tutorial/query-params.md +++ b/docs/tr/docs/tutorial/query-params.md @@ -1,4 +1,4 @@ -# Sorgu Parametreleri { #query-parameters } +# Query Parametreleri { #query-parameters } Fonksiyonda path parametrelerinin parçası olmayan diğer parametreleri tanımladığınızda, bunlar otomatik olarak "query" parametreleri olarak yorumlanır. @@ -65,13 +65,13 @@ Aynı şekilde, varsayılan değerlerini `None` yaparak isteğe bağlı query pa Bu durumda, fonksiyon parametresi `q` isteğe bağlı olur ve varsayılan olarak `None` olur. -/// check | Ek bilgi +/// tip | İpucu Ayrıca, **FastAPI** path parametresi olan `item_id`'nin bir path parametresi olduğunu ve `q`'nun path olmadığını fark edecek kadar akıllıdır; dolayısıyla bu bir query parametresidir. /// -## Sorgu parametresi tip dönüşümü { #query-parameter-type-conversion } +## Query parametresi tip dönüşümü { #query-parameter-type-conversion } `bool` tipleri de tanımlayabilirsiniz, ve bunlar dönüştürülür: diff --git a/docs/tr/docs/tutorial/request-files.md b/docs/tr/docs/tutorial/request-files.md index 0ba4f8af6..ab54cfd39 100644 --- a/docs/tr/docs/tutorial/request-files.md +++ b/docs/tr/docs/tutorial/request-files.md @@ -2,11 +2,11 @@ İstemcinin upload edeceği dosyaları `File` kullanarak tanımlayabilirsiniz. -/// info | Bilgi +/// note | Not Upload edilen dosyaları alabilmek için önce [`python-multipart`](https://github.com/Kludex/python-multipart) yükleyin. -Bir [virtual environment](../virtual-environments.md) oluşturduğunuzdan, aktive ettiğinizden ve ardından paketi yüklediğinizden emin olun. Örneğin: +Bir [Sanal ortam](../virtual-environments.md) oluşturduğunuzdan, aktive ettiğinizden ve ardından paketi yüklediğinizden emin olun. Örneğin: ```console $ pip install python-multipart @@ -28,7 +28,7 @@ Bunun nedeni, upload edilen dosyaların "form data" olarak gönderilmesidir. {* ../../docs_src/request_files/tutorial001_an_py310.py hl[9] *} -/// info | Bilgi +/// note | Not `File`, doğrudan `Form`’dan türeyen bir sınıftır. @@ -64,7 +64,7 @@ Tipi `UploadFile` olan bir dosya parametresi tanımlayın: * Bu sayede görüntüler, videolar, büyük binary’ler vb. gibi büyük dosyalarda tüm belleği tüketmeden iyi çalışır. * Upload edilen dosyadan metadata alabilirsiniz. * [file-like](https://docs.python.org/3/glossary.html#term-file-like-object) bir `async` arayüze sahiptir. -* [`SpooledTemporaryFile`](https://docs.python.org/3/library/tempfile.html#tempfile.SpooledTemporaryFile) nesnesini dışa açar; bunu, file-like nesne bekleyen diğer library’lere doğrudan geçebilirsiniz. +* Gerçek bir Python [`SpooledTemporaryFile`](https://docs.python.org/3/library/tempfile.html#tempfile.SpooledTemporaryFile) nesnesini dışa açar; bunu, file-like nesne bekleyen diğer library’lere doğrudan geçebilirsiniz. ### `UploadFile` { #uploadfile } diff --git a/docs/tr/docs/tutorial/request-form-models.md b/docs/tr/docs/tutorial/request-form-models.md index 30fdaee13..6f5532b58 100644 --- a/docs/tr/docs/tutorial/request-form-models.md +++ b/docs/tr/docs/tutorial/request-form-models.md @@ -2,11 +2,11 @@ FastAPI'de **form field**'larını tanımlamak için **Pydantic model**'lerini kullanabilirsiniz. -/// info | Bilgi +/// note | Not Form'ları kullanmak için önce [`python-multipart`](https://github.com/Kludex/python-multipart)'ı yükleyin. -Bir [virtual environment](../virtual-environments.md) oluşturduğunuzdan, onu etkinleştirdiğinizden ve ardından paketi kurduğunuzdan emin olun. Örneğin: +Bir [Sanal ortam](../virtual-environments.md) oluşturduğunuzdan, onu etkinleştirdiğinizden ve ardından paketi kurduğunuzdan emin olun. Örneğin: ```console $ pip install python-multipart diff --git a/docs/tr/docs/tutorial/request-forms-and-files.md b/docs/tr/docs/tutorial/request-forms-and-files.md index 96f5adcc2..fc50491ce 100644 --- a/docs/tr/docs/tutorial/request-forms-and-files.md +++ b/docs/tr/docs/tutorial/request-forms-and-files.md @@ -2,7 +2,7 @@ `File` ve `Form` kullanarak aynı anda hem dosyaları hem de form alanlarını tanımlayabilirsiniz. -/// info | Bilgi +/// note | Not Yüklenen dosyaları ve/veya form verisini almak için önce [`python-multipart`](https://github.com/Kludex/python-multipart) paketini kurun. diff --git a/docs/tr/docs/tutorial/request-forms.md b/docs/tr/docs/tutorial/request-forms.md index 0b2f39f13..57f10fb1b 100644 --- a/docs/tr/docs/tutorial/request-forms.md +++ b/docs/tr/docs/tutorial/request-forms.md @@ -1,8 +1,9 @@ # Form Verisi { #form-data } + JSON yerine form alanlarını almanız gerektiğinde `Form` kullanabilirsiniz. -/// info | Bilgi +/// note | Not Formları kullanmak için önce [`python-multipart`](https://github.com/Kludex/python-multipart) paketini kurun. @@ -28,11 +29,11 @@ Form parametrelerini `Body` veya `Query` için yaptığınız gibi oluşturun: Örneğin OAuth2 spesifikasyonunun kullanılabileceği ("password flow" olarak adlandırılan) yollardan birinde, form alanları olarak bir `username` ve `password` göndermek zorunludur. -Spesifikasyon, alanların adının tam olarak `username` ve `password` olmasını ve JSON değil form alanları olarak gönderilmesini gerektirir. +spesifikasyon, alanların adının tam olarak `username` ve `password` olmasını ve JSON değil form alanları olarak gönderilmesini gerektirir. `Form` ile `Body` (ve `Query`, `Path`, `Cookie`) ile yaptığınız aynı konfigürasyonları tanımlayabilirsiniz; validasyon, örnekler, alias (örn. `username` yerine `user-name`) vb. dahil. -/// info | Bilgi +/// note | Not `Form`, doğrudan `Body`'den miras alan bir sınıftır. @@ -62,7 +63,7 @@ Bu encoding'ler ve form alanları hakkında daha fazla okumak isterseniz, [ -/// check | Authorize butonu! +/// tip | Authorize butonu! Artık parıl parıl yeni bir "Authorize" butonunuz var. @@ -118,7 +118,7 @@ O yüzden basitleştirilmiş bu bakış açısından üzerinden geçelim: Bu örnekte **OAuth2**’yi, **Password** flow ile, **Bearer** token kullanarak uygulayacağız. Bunu `OAuth2PasswordBearer` sınıfı ile yaparız. -/// info | Bilgi +/// note | Not "Bearer" token tek seçenek değildir. @@ -140,7 +140,7 @@ Burada `tokenUrl="token"`, henüz oluşturmadığımız göreli bir URL olan `to Göreli URL kullandığımız için, API’niz `https://example.com/` adresinde olsaydı `https://example.com/token` anlamına gelirdi. Ama API’niz `https://example.com/api/v1/` adresinde olsaydı, bu kez `https://example.com/api/v1/token` anlamına gelirdi. -Göreli URL kullanmak, [Behind a Proxy](../../advanced/behind-a-proxy.md) gibi daha ileri kullanım senaryolarında bile uygulamanızın çalışmaya devam etmesini garanti etmek açısından önemlidir. +Göreli URL kullanmak, [Bir Proxy Arkasında](../../advanced/behind-a-proxy.md) gibi daha ileri kullanım senaryolarında bile uygulamanızın çalışmaya devam etmesini garanti etmek açısından önemlidir. /// @@ -148,7 +148,7 @@ Bu parametre o endpoint’i / *path operation*’ı oluşturmaz; fakat `/token` Birazdan gerçek path operation’ı da oluşturacağız. -/// info | Teknik Detaylar +/// note | Teknik Detaylar Eğer çok katı bir "Pythonista" iseniz, `token_url` yerine `tokenUrl` şeklindeki parametre adlandırma stilini sevmeyebilirsiniz. @@ -176,7 +176,7 @@ Bu dependency, *path operation function* içindeki `token` parametresine atanaca **FastAPI**, bu dependency’yi OpenAPI şemasında (ve otomatik API dokümanlarında) bir "security scheme" tanımlamak için kullanabileceğini bilir. -/// info | Teknik Detaylar +/// note | Teknik Detaylar **FastAPI**, bir dependency içinde tanımlanan `OAuth2PasswordBearer` sınıfını OpenAPI’de security scheme tanımlamak için kullanabileceğini bilir; çünkü bu sınıf `fastapi.security.oauth2.OAuth2`’den kalıtım alır, o da `fastapi.security.base.SecurityBase`’den kalıtım alır. diff --git a/docs/tr/docs/tutorial/security/get-current-user.md b/docs/tr/docs/tutorial/security/get-current-user.md index cc7f7a51b..2883c06fe 100644 --- a/docs/tr/docs/tutorial/security/get-current-user.md +++ b/docs/tr/docs/tutorial/security/get-current-user.md @@ -14,7 +14,7 @@ Bize mevcut kullanıcıyı verecek şekilde düzenleyelim. Body'leri bildirmek için Pydantic'i nasıl kullanıyorsak, aynı şekilde onu başka her yerde de kullanabiliriz: -{* ../../docs_src/security/tutorial002_an_py310.py hl[5,12:6] *} +{* ../../docs_src/security/tutorial002_an_py310.py hl[5,12:16] *} ## `get_current_user` dependency'si oluşturun { #create-a-get-current-user-dependency } @@ -52,7 +52,7 @@ Burada `Depends` kullandığınız için **FastAPI** karışıklık yaşamaz. /// -/// check | Ek bilgi +/// tip | İpucu Bu dependency sisteminin tasarımı, hepsi `User` modeli döndüren farklı dependency'lere (farklı "dependable"lara) sahip olmamıza izin verir. diff --git a/docs/tr/docs/tutorial/security/oauth2-jwt.md b/docs/tr/docs/tutorial/security/oauth2-jwt.md index 4b68bc451..df893ec82 100644 --- a/docs/tr/docs/tutorial/security/oauth2-jwt.md +++ b/docs/tr/docs/tutorial/security/oauth2-jwt.md @@ -42,7 +42,7 @@ $ pip install pyjwt
-/// info | Bilgi +/// note | Not RSA veya ECDSA gibi dijital imza algoritmaları kullanmayı planlıyorsanız, `pyjwt[crypto]` bağımlılığı olan `cryptography` kütüphanesini kurmalısınız. @@ -120,7 +120,7 @@ Bir tane de kullanıcıyı authenticate edip geri döndüren bir yardımcı fonk `authenticate_user`, veritabanında var olmayan bir username ile çağrıldığında, yine de sahte (dummy) bir hash'e karşı `verify_password` çalıştırıyoruz. -Bu, username geçerli olsun ya da olmasın endpoint'in yaklaşık aynı sürede yanıt vermesini sağlar; böylece mevcut username'leri saymaya yarayabilecek zamanlama saldırılarını (timing attacks) engeller. +Bu, username geçerli olsun ya da olmasın endpoint'in yaklaşık aynı sürede yanıt vermesini sağlar; böylece mevcut username'leri saymaya yarayabilecek **timing attacks** saldırılarını engeller. /// note | Not @@ -213,7 +213,7 @@ Uygulamayı, öncekiyle aynı şekilde authorize edin. Username: `johndoe` Password: `secret` -/// check | Ek bilgi +/// tip | İpucu Kodun hiçbir yerinde düz metin password "`secret`" yok; sadece hash'lenmiş hâli var. diff --git a/docs/tr/docs/tutorial/security/simple-oauth2.md b/docs/tr/docs/tutorial/security/simple-oauth2.md index 9893cc800..fdc318019 100644 --- a/docs/tr/docs/tutorial/security/simple-oauth2.md +++ b/docs/tr/docs/tutorial/security/simple-oauth2.md @@ -32,7 +32,7 @@ Genelde belirli güvenlik izinlerini (permission) belirtmek için kullanılırla * `instagram_basic` Facebook / Instagram tarafından kullanılır. * `https://www.googleapis.com/auth/drive` Google tarafından kullanılır. -/// info | Bilgi +/// note | Not OAuth2’de bir "scope", gerekli olan belirli bir izni ifade eden basit bir string’dir. @@ -72,7 +72,7 @@ Bunu zorlamak istiyorsanız, `OAuth2PasswordRequestForm` yerine `OAuth2PasswordR * Opsiyonel `client_id` (bu örnekte ihtiyacımız yok). * Opsiyonel `client_secret` (bu örnekte ihtiyacımız yok). -/// info | Bilgi +/// note | Not `OAuth2PasswordRequestForm`, `OAuth2PasswordBearer` gibi **FastAPI**’ye özel “özel bir sınıf” değildir. @@ -144,9 +144,9 @@ UserInDB( ) ``` -/// info | Bilgi +/// note | Not -`**user_dict` için daha kapsamlı bir açıklama için [**Extra Models** dokümantasyonundaki ilgili bölüme](../extra-models.md#about-user-in-dict) geri dönüp bakın. +`**user_dict` için daha kapsamlı bir açıklama için [**Extra Models** dokümantasyonundaki ilgili bölüme](../extra-models.md#about-user-in-model-dump) geri dönüp bakın. /// @@ -196,7 +196,7 @@ Dolayısıyla endpoint’imizde kullanıcıyı ancak kullanıcı varsa, doğru {* ../../docs_src/security/tutorial003_an_py310.py hl[58:66,69:74,94] *} -/// info | Bilgi +/// note | Not Burada `Bearer` değerine sahip ek `WWW-Authenticate` header’ını döndürmemiz de spesifikasyonun bir parçasıdır. diff --git a/docs/tr/docs/tutorial/server-sent-events.md b/docs/tr/docs/tutorial/server-sent-events.md index 385541012..5f3621de4 100644 --- a/docs/tr/docs/tutorial/server-sent-events.md +++ b/docs/tr/docs/tutorial/server-sent-events.md @@ -4,7 +4,7 @@ Bu, [JSON Lines Akışı](stream-json-lines.md) ile benzerdir ancak tarayıcılar tarafından yerel olarak desteklenen [`EventSource` API'si](https://developer.mozilla.org/en-US/docs/Web/API/EventSource) ile `text/event-stream` formatını kullanır. -/// info | Bilgi +/// note | Not FastAPI 0.135.0'da eklendi. diff --git a/docs/tr/docs/tutorial/sql-databases.md b/docs/tr/docs/tutorial/sql-databases.md index ea4b9ebc4..1145c209a 100644 --- a/docs/tr/docs/tutorial/sql-databases.md +++ b/docs/tr/docs/tutorial/sql-databases.md @@ -352,6 +352,6 @@ $ fastapi dev ## Özet { #recap } -Bir SQL veritabanıyla etkileşim kurmak için [**SQLModel**](https://sqlmodel.tiangolo.com/) kullanabilir ve *data model* ile *table model* yaklaşımıyla kodu sadeleştirebilirsiniz. +Bir SQL veritabanıyla etkileşim kurmak için [**SQLModel**](https://sqlmodel.tiangolo.com/) kullanabilir ve *data model*’ler ile *table model*’ler kullanarak kodu sadeleştirebilirsiniz. **SQLModel** dokümantasyonunda çok daha fazlasını öğrenebilirsiniz; **FastAPI** ile SQLModel kullanımı için daha uzun bir mini [tutorial](https://sqlmodel.tiangolo.com/tutorial/fastapi/) da bulunuyor. 🚀 diff --git a/docs/tr/docs/tutorial/static-files.md b/docs/tr/docs/tutorial/static-files.md index 13c20cfa9..b271139a2 100644 --- a/docs/tr/docs/tutorial/static-files.md +++ b/docs/tr/docs/tutorial/static-files.md @@ -2,6 +2,14 @@ `StaticFiles` kullanarak bir dizindeki statik dosyaları otomatik olarak sunabilirsiniz. +/// tip | İpucu + +Bir frontend host etmeniz gerekiyorsa, bunun yerine `app.frontend()` kullanın; bununla ilgili bilgileri [Frontend](frontend.md) bölümünde okuyabilirsiniz. + +`app.frontend()`, altında `StaticFiles` kullanır ve frontend'ler için client-side routing'i handle etmek gibi ek avantajlar sağlar. + +/// + ## `StaticFiles` Kullanımı { #use-staticfiles } * `StaticFiles`'ı import edin. diff --git a/docs/tr/docs/tutorial/stream-json-lines.md b/docs/tr/docs/tutorial/stream-json-lines.md index 200689d71..d9755d168 100644 --- a/docs/tr/docs/tutorial/stream-json-lines.md +++ b/docs/tr/docs/tutorial/stream-json-lines.md @@ -2,7 +2,7 @@ Bir veri dizisini “akış” olarak göndermek istediğiniz durumlar olabilir; bunu **JSON Lines** ile yapabilirsiniz. -/// info | Bilgi +/// note | Not FastAPI 0.134.0 ile eklendi. @@ -48,7 +48,7 @@ Response’un `application/json` yerine `application/jsonl` içerik türü (Cont Bir JSON dizisine (Python list eşdeğeri) çok benzer; ancak öğeler `[]` içine alınmak ve araya `,` konmak yerine, her satırda **bir JSON nesnesi** vardır; bunlar yeni satır karakteri ile ayrılır. -/// info | Bilgi +/// note | Not Önemli nokta, uygulamanız her satırı sırayla üretebilirken, istemcinin de önceki satırları tüketmeye devam edebilmesidir. diff --git a/docs/tr/docs/tutorial/testing.md b/docs/tr/docs/tutorial/testing.md index c5f8692f7..df5248ff4 100644 --- a/docs/tr/docs/tutorial/testing.md +++ b/docs/tr/docs/tutorial/testing.md @@ -8,7 +8,7 @@ Bununla birlikte **FastAPI** ile [pytest](https://docs.pytest.org/)'i doğrudan ## `TestClient` Kullanımı { #using-testclient } -/// info | Bilgi +/// note | Not `TestClient` kullanmak için önce [`httpx`](https://www.python-httpx.org)'i kurun. @@ -75,6 +75,7 @@ Ayrıca **FastAPI** uygulamanız birden fazla dosya/modül vb. ile de oluşturul `main.py` dosyasında **FastAPI** uygulamanız bulunuyor olsun: + {* ../../docs_src/app_testing/app_a_py310/main.py *} ### Test Dosyası { #testing-file } @@ -93,6 +94,7 @@ Bu dosya aynı package içinde olduğu için, `main` modülünden (`main.py`) `a {* ../../docs_src/app_testing/app_a_py310/test_main.py hl[3] *} + ...ve test kodunu da öncekiyle aynı şekilde yazabilirsiniz. ## Test Etme: Genişletilmiş Örnek { #testing-extended-example } @@ -127,6 +129,7 @@ Sonrasında `test_main.py` dosyanızı genişletilmiş testlerle güncelleyebili {* ../../docs_src/app_testing/app_b_an_py310/test_main.py *} + Client'ın request içinde bir bilgi göndermesi gerektiğinde ve bunu nasıl yapacağınızı bilemediğinizde, `httpx` ile nasıl yapılacağını aratabilirsiniz (Google) ya da HTTPX’in tasarımı Requests’e dayandığı için `requests` ile nasıl yapıldığını da arayabilirsiniz. Sonra testlerinizde aynısını uygularsınız. @@ -141,7 +144,7 @@ Sonra testlerinizde aynısını uygularsınız. Backend'e veri geçme hakkında daha fazla bilgi için (`httpx` veya `TestClient` kullanarak) [HTTPX dokümantasyonu](https://www.python-httpx.org)'na bakın. -/// info | Bilgi +/// note | Not `TestClient`'ın Pydantic model'lerini değil, JSON'a dönüştürülebilen verileri aldığını unutmayın. diff --git a/docs/tr/docs/virtual-environments.md b/docs/tr/docs/virtual-environments.md index 4db3b132f..60494ac12 100644 --- a/docs/tr/docs/virtual-environments.md +++ b/docs/tr/docs/virtual-environments.md @@ -53,7 +53,7 @@ $ cd awesome-project ## Virtual Environment Oluşturun { #create-a-virtual-environment } -Bir Python projesi üzerinde **ilk kez** çalışmaya başladığınızda, **virtual environment**'i projenizin içinde oluşturun. +Bir Python projesi üzerinde **ilk kez** çalışmaya başladığınızda, virtual environment'i **projenizin içinde** oluşturun. /// tip | İpucu @@ -443,6 +443,8 @@ Böylece `python` çalıştırdığınızda, o virtual environment içinden (ve Artık projeniz üzerinde çalışmaya başlayabilirsiniz. + + /// tip | İpucu Yukarıdaki her şeyin aslında ne olduğunu anlamak ister misiniz? @@ -517,7 +519,7 @@ $ pip install "harry==3" Sonuç olarak global Python environment'ınızda `harry` versiyon `3` kurulu olur. -Ve `philosophers-stone`'u tekrar çalıştırmaya kalkarsanız, `harry` versiyon `1`e ihtiyaç duyduğu için **çalışmama** ihtimali vardır. +Ve `philosophers-stone`'u tekrar çalıştırmaya kalkarsanız, `harry` versiyon `1`'e ihtiyaç duyduğu için **çalışmama** ihtimali vardır. ```mermaid flowchart LR diff --git a/docs/uk/docs/_llm-test.md b/docs/uk/docs/_llm-test.md index 22c5bc436..7de364bbd 100644 --- a/docs/uk/docs/_llm-test.md +++ b/docs/uk/docs/_llm-test.md @@ -203,9 +203,9 @@ works(foo="bar") # Це працює 🎉 //// tab | Інформація -Атрибути "title" елементів "abbr" перекладаються за певними інструкціями. +Атрибути «title» елементів «abbr» перекладаються за певними інструкціями. -Переклади можуть додавати власні елементи "abbr", які LLM не повинен прибирати. Наприклад, щоб пояснити англійські слова. +Переклади можуть додавати власні елементи «abbr», які LLM не повинен прибирати. Наприклад, щоб пояснити англійські слова. Див. розділ `### HTML abbr elements` в загальній підсказці в `scripts/translate.py`. diff --git a/docs/uk/docs/advanced/additional-responses.md b/docs/uk/docs/advanced/additional-responses.md index 2d2005837..3b30645f6 100644 --- a/docs/uk/docs/advanced/additional-responses.md +++ b/docs/uk/docs/advanced/additional-responses.md @@ -34,7 +34,7 @@ /// -/// info | Інформація +/// note | Примітка Ключ `model` не є частиною OpenAPI. @@ -183,7 +183,7 @@ /// -/// info | Інформація +/// note | Примітка Поки ви явно не вкажете інший тип медіа в параметрі `responses`, FastAPI вважатиме, що відповідь має той самий тип медіа, що й основний клас відповіді (типово `application/json`). diff --git a/docs/uk/docs/advanced/additional-status-codes.md b/docs/uk/docs/advanced/additional-status-codes.md index 26e2c1454..421f35c97 100644 --- a/docs/uk/docs/advanced/additional-status-codes.md +++ b/docs/uk/docs/advanced/additional-status-codes.md @@ -1,5 +1,6 @@ # Додаткові коди статусу { #additional-status-codes } + За замовчуванням **FastAPI** повертатиме відповіді за допомогою `JSONResponse`, поміщаючи вміст, який ви повертаєте з вашої *операції шляху*, у цей `JSONResponse`. Він використовуватиме код статусу за замовчуванням або той, який ви встановите у своїй *операції шляху*. diff --git a/docs/uk/docs/advanced/advanced-dependencies.md b/docs/uk/docs/advanced/advanced-dependencies.md index 48a10ba4d..9a597f7b7 100644 --- a/docs/uk/docs/advanced/advanced-dependencies.md +++ b/docs/uk/docs/advanced/advanced-dependencies.md @@ -10,11 +10,11 @@ Але ми хочемо мати змогу параметризувати цей фіксований вміст. -## Екземпляр «callable» { #a-callable-instance } +## Викликаємий екземпляр { #a-callable-instance } -У Python є спосіб зробити екземпляр класу «callable». +У Python є спосіб зробити екземпляр класу викликаємим. -Не сам клас (який уже є «callable»), а екземпляр цього класу. +Не сам клас (який уже є викликаємим), а екземпляр цього класу. Щоб це зробити, оголошуємо метод `__call__`: @@ -36,7 +36,7 @@ {* ../../docs_src/dependencies/tutorial011_an_py310.py hl[18] *} -Таким чином ми «параметризуємо» нашу залежність, яка тепер містить «bar» як атрибут `checker.fixed_content`. +Таким чином ми «параметризуємо» нашу залежність, яка тепер містить `"bar"` як атрибут `checker.fixed_content`. ## Використовувати екземпляр як залежність { #use-the-instance-as-a-dependency } @@ -78,7 +78,7 @@ checker(q="somequery") ### Залежності з `yield` і `scope` { #dependencies-with-yield-and-scope } -У версії 0.121.0 **FastAPI** додано підтримку `Depends(scope="function")` для залежностей з `yield`. +У версії 0.121.0 FastAPI додано підтримку `Depends(scope="function")` для залежностей з `yield`. З `Depends(scope="function")` завершальний код після `yield` виконується одразу після завершення *функції операції шляху*, до того як відповідь буде надіслана клієнту. @@ -88,7 +88,7 @@ checker(q="somequery") ### Залежності з `yield` і `StreamingResponse`, технічні деталі { #dependencies-with-yield-and-streamingresponse-technical-details } -До **FastAPI** 0.118.0, якщо ви використовували залежність із `yield`, завершальний код виконувався після повернення з *функції операції шляху*, але безпосередньо перед відправленням відповіді. +До FastAPI 0.118.0, якщо ви використовували залежність із `yield`, завершальний код виконувався після повернення з *функції операції шляху*, але безпосередньо перед відправленням відповіді. Метою було уникнути утримання ресурсів довше, ніж потрібно, очікуючи, поки відповідь пройде мережею. @@ -98,7 +98,7 @@ checker(q="somequery") Цю поведінку змінено у 0.118.0: завершальний код після `yield` знову виконується після відправлення відповіді. -/// info | Інформація +/// note | Примітка Як побачите нижче, це дуже схоже на поведінку до версії 0.106.0, але з кількома покращеннями та виправленнями помилок у крайових випадках. @@ -138,17 +138,17 @@ checker(q="somequery") ### Залежності з `yield` і `except`, технічні деталі { #dependencies-with-yield-and-except-technical-details } -До **FastAPI** 0.110.0, якщо ви використовували залежність із `yield`, перехоплювали виняток через `except` у цій залежності і не піднімали його знову, виняток автоматично піднімався/пересилався до будь-яких обробників винятків або внутрішнього обробника помилок сервера. +До FastAPI 0.110.0, якщо ви використовували залежність із `yield`, перехоплювали виняток через `except` у цій залежності і не піднімали його знову, виняток автоматично піднімався/пересилався до будь-яких обробників винятків або внутрішнього обробника помилок сервера. Це змінено у версії 0.110.0, щоб усунути неконтрольоване споживання пам'яті від пересланих винятків без обробника (внутрішні помилки сервера) та зробити поведінку узгодженою зі звичайним Python-кодом. ### Фонові задачі та залежності з `yield`, технічні деталі { #background-tasks-and-dependencies-with-yield-technical-details } -До **FastAPI** 0.106.0 піднімати винятки після `yield` було неможливо: завершальний код у залежностях з `yield` виконувався після надсилання відповіді, тож [обробники винятків](../tutorial/handling-errors.md#install-custom-exception-handlers) уже відпрацювали б. +До FastAPI 0.106.0 піднімати винятки після `yield` було неможливо: завершальний код у залежностях з `yield` виконувався після надсилання відповіді, тож [обробники винятків](../tutorial/handling-errors.md#install-custom-exception-handlers) уже відпрацювали б. Так було спроєктовано головно для того, щоб дозволити використовувати ті самі об'єкти, «віддані» залежностями через `yield`, усередині фонових задач, оскільки завершальний код виконувався після завершення фонових задач. -У **FastAPI** 0.106.0 це змінено, щоб не утримувати ресурси під час очікування, поки відповідь піде мережею. +У FastAPI 0.106.0 це змінено, щоб не утримувати ресурси під час очікування, поки відповідь піде мережею. /// tip | Порада @@ -160,4 +160,4 @@ checker(q="somequery") Якщо ви раніше покладалися на цю поведінку, тепер слід створювати ресурси для фонових задач усередині самої фонової задачі та використовувати всередині лише дані, що не залежать від ресурсів залежностей із `yield`. -Наприклад, замість використання тієї самої сесії бази даних ви створюватимете нову сесію в самій фоновій задачі та отримуватимете об'єкти з бази даних, використовуючи Цю нову сесію. І далі, замість передавання об'єкта з бази даних як параметра у функцію фонової задачі, ви передасте ідентифікатор цього об'єкта, а потім отримаєте об'єкт знову всередині функції фонової задачі. +Наприклад, замість використання тієї самої сесії бази даних ви створюватимете нову сесію в самій фоновій задачі та отримуватимете об'єкти з бази даних, використовуючи цю нову сесію. І далі, замість передавання об'єкта з бази даних як параметра у функцію фонової задачі, ви передасте ідентифікатор цього об'єкта, а потім отримаєте об'єкт знову всередині функції фонової задачі. diff --git a/docs/uk/docs/advanced/custom-response.md b/docs/uk/docs/advanced/custom-response.md index 4ed7616bf..aa4c39ee0 100644 --- a/docs/uk/docs/advanced/custom-response.md +++ b/docs/uk/docs/advanced/custom-response.md @@ -41,7 +41,7 @@ {* ../../docs_src/custom_response/tutorial002_py310.py hl[2,7] *} -/// info | Інформація +/// note | Примітка Параметр `response_class` також визначатиме «медіа-тип» відповіді. @@ -65,7 +65,7 @@ /// -/// info | Інформація +/// note | Примітка Звісно, фактичні заголовок `Content-Type`, код статусу тощо прийдуть з об'єкта `Response`, який ви повернули. diff --git a/docs/uk/docs/advanced/dataclasses.md b/docs/uk/docs/advanced/dataclasses.md index 1c91304b0..f019183db 100644 --- a/docs/uk/docs/advanced/dataclasses.md +++ b/docs/uk/docs/advanced/dataclasses.md @@ -1,5 +1,6 @@ # Використання dataclasses { #using-dataclasses } + FastAPI побудовано поверх **Pydantic**, і я показував вам, як використовувати моделі Pydantic для оголошення запитів і відповідей. Але FastAPI також підтримує використання [`dataclasses`](https://docs.python.org/3/library/dataclasses.html) таким самим чином: @@ -18,7 +19,7 @@ FastAPI побудовано поверх **Pydantic**, і я показував Це працює так само, як із моделями Pydantic. Насправді під капотом це також досягається за допомогою Pydantic. -/// info +/// note | Примітка Майте на увазі, що dataclasses не можуть робити все те, що можуть моделі Pydantic. @@ -64,7 +65,7 @@ Dataclass буде автоматично перетворено на dataclass 6. Тут ми повертаємо словник, що містить `items`, який є списком dataclass. - FastAPI усе ще здатний серіалізувати дані до JSON. + FastAPI усе ще здатний серіалізувати дані до JSON. 7. Тут у `response_model` використано анотацію типу список dataclass `Author`. diff --git a/docs/uk/docs/advanced/events.md b/docs/uk/docs/advanced/events.md index 33f6314fe..bc6e78457 100644 --- a/docs/uk/docs/advanced/events.md +++ b/docs/uk/docs/advanced/events.md @@ -1,30 +1,30 @@ # Події тривалості життя { #lifespan-events } -Ви можете визначити логіку (код), яку слід виконати перед тим, як застосунок запуститься. Це означає, що цей код буде виконано один раз, перед тим як застосунок почне отримувати запити. +Ви можете визначити логіку (код), яку слід виконати перед тим, як застосунок **запуститься**. Це означає, що цей код буде виконано **один раз**, **перед** тим як застосунок **почне отримувати запити**. -Так само ви можете визначити логіку (код), яку слід виконати під час вимкнення застосунку. У цьому випадку код буде виконано один раз, після обробки можливо багатьох запитів. +Так само ви можете визначити логіку (код), яку слід виконати під час **вимкнення** застосунку. У цьому випадку код буде виконано **один раз**, після обробки можливо **багатьох запитів**. -Оскільки цей код виконується перед тим, як застосунок почне приймати запити, і одразу після того, як він завершить їх обробку, він охоплює всю тривалість життя застосунку (слово «lifespan» буде важливим за мить 😉). +Оскільки цей код виконується перед тим, як застосунок **почне** приймати запити, і одразу після того, як він **завершить** їх обробку, він охоплює всю **тривалість життя** застосунку (слово «lifespan» буде важливим за мить 😉). -Це дуже корисно для налаштування ресурсів, які потрібні для всього застосунку, які спільні між запитами, та/або які потрібно потім прибрати. Наприклад, пул з’єднань з базою даних або завантаження спільної моделі машинного навчання. +Це дуже корисно для налаштування **ресурсів**, які потрібні для всього застосунку, які **спільні** між запитами, та/або які потрібно потім **прибрати**. Наприклад, пул з’єднань з базою даних або завантаження спільної моделі машинного навчання. ## Випадок використання { #use-case } -Почнемо з прикладу випадку використання, а потім подивимось, як це вирішити. +Почнемо з прикладу **випадку використання**, а потім подивимось, як це вирішити. -Уявімо, що у вас є моделі машинного навчання, якими ви хочете обробляти запити. 🤖 +Уявімо, що у вас є **моделі машинного навчання**, якими ви хочете обробляти запити. 🤖 Ті самі моделі спільні між запитами, тобто це не окрема модель на запит чи на користувача. -Уявімо, що завантаження моделі може займати чимало часу, бо треба читати багато даних з диска. Тож ви не хочете робити це для кожного запиту. +Уявімо, що завантаження моделі може **займати чимало часу**, бо треба читати багато **даних з диска**. Тож ви не хочете робити це для кожного запиту. -Ви могли б завантажити її на верхньому рівні модуля/файлу, але це означало б, що модель завантажиться навіть якщо ви просто запускаєте простий автоматизований тест - тоді тест буде повільним, бо йому доведеться чекати завантаження моделі перед виконанням незалежної частини коду. +Ви могли б завантажити її на верхньому рівні модуля/файлу, але це означало б, що модель **завантажиться** навіть якщо ви просто запускаєте простий автоматизований тест - тоді тест буде **повільним**, бо йому доведеться чекати завантаження моделі перед виконанням незалежної частини коду. Ось це ми й вирішимо: завантажимо модель перед обробкою запитів, але лише безпосередньо перед тим, як застосунок почне отримувати запити, а не під час завантаження коду. ## Тривалість життя { #lifespan } -Ви можете визначити цю логіку запуску і вимкнення за допомогою параметра `lifespan` застосунку `FastAPI` та «менеджера контексту» (зараз покажу, що це). +Ви можете визначити цю логіку *запуску* і *вимкнення* за допомогою параметра `lifespan` застосунку `FastAPI` та «менеджера контексту» (зараз покажу, що це). Почнемо з прикладу, а потім розберемо детально. @@ -32,13 +32,13 @@ {* ../../docs_src/events/tutorial003_py310.py hl[16,19] *} -Тут ми імітуємо дорогу операцію запуску із завантаженням моделі, поміщаючи (фальшиву) функцію моделі у словник з моделями машинного навчання перед `yield`. Цей код буде виконано перед тим, як застосунок почне приймати запити, під час запуску. +Тут ми імітуємо дорогу операцію *запуску* із завантаженням моделі, поміщаючи (фальшиву) функцію моделі у словник з моделями машинного навчання перед `yield`. Цей код буде виконано **перед** тим, як застосунок **почне приймати запити**, під час *запуску*. -А одразу після `yield` ми розвантажуємо модель. Цей код буде виконано після того, як застосунок завершить обробку запитів, безпосередньо перед вимкненням. Це, наприклад, може звільнити ресурси на кшталт пам’яті або GPU. +А одразу після `yield` ми розвантажуємо модель. Цей код буде виконано **після** того, як застосунок **завершить обробку запитів**, безпосередньо перед *вимкненням*. Це, наприклад, може звільнити ресурси на кшталт пам’яті або GPU. /// tip | Порада -Подія `shutdown` відбувається, коли ви зупиняєте застосунок. +Подія `shutdown` відбувається, коли ви **зупиняєте** застосунок. Можливо, вам треба запустити нову версію, або ви просто втомилися її запускати. 🤷 @@ -50,26 +50,26 @@ {* ../../docs_src/events/tutorial003_py310.py hl[14:19] *} -Перша частина функції до `yield` буде виконана перед запуском застосунку. +Перша частина функції до `yield` буде виконана **перед** запуском застосунку. -А частина після `yield` буде виконана після завершення роботи застосунку. +А частина після `yield` буде виконана **після** завершення роботи застосунку. ### Асинхронний менеджер контексту { #async-context-manager } Якщо придивитися, функція задекорована за допомогою `@asynccontextmanager`. -Це перетворює функцію на так званий «асинхронний менеджер контексту». +Це перетворює функцію на так званий «**асинхронний менеджер контексту**». {* ../../docs_src/events/tutorial003_py310.py hl[1,13] *} -Менеджер контексту в Python - це те, що можна використовувати в операторі `with`, наприклад, `open()` можна використовувати як менеджер контексту: +**Менеджер контексту** в Python - це те, що можна використовувати в операторі `with`, наприклад, `open()` можна використовувати як менеджер контексту: ```Python with open("file.txt") as file: file.read() ``` -У новіших версіях Python також є асинхронний менеджер контексту. Його використовують з `async with`: +У новіших версіях Python також є **асинхронний менеджер контексту**. Його використовують з `async with`: ```Python async with lifespan(app): @@ -80,7 +80,7 @@ async with lifespan(app): У нашому прикладі коду вище ми не використовуємо його напряму, а передаємо його до FastAPI, щоб він його використав. -Параметр `lifespan` застосунку `FastAPI` приймає асинхронний менеджер контексту, тож ми можемо передати йому наш новий асинхронний менеджер контексту `lifespan`. +Параметр `lifespan` застосунку `FastAPI` приймає **асинхронний менеджер контексту**, тож ми можемо передати йому наш новий асинхронний менеджер контексту `lifespan`. {* ../../docs_src/events/tutorial003_py310.py hl[22] *} @@ -88,13 +88,13 @@ async with lifespan(app): /// warning | Попередження -Рекомендований спосіб обробляти запуск і вимкнення - використовувати параметр `lifespan` застосунку `FastAPI`, як описано вище. Якщо ви надаєте параметр `lifespan`, обробники подій `startup` і `shutdown` більше не будуть викликані. Або все через `lifespan`, або все через події - не обидва одночасно. +Рекомендований спосіб обробляти *запуск* і *вимкнення* - використовувати параметр `lifespan` застосунку `FastAPI`, як описано вище. Якщо ви надаєте параметр `lifespan`, обробники подій `startup` і `shutdown` більше не будуть викликані. Або все через `lifespan`, або все через події - не обидва одночасно. Можете, ймовірно, пропустити цю частину. /// -Є альтернативний спосіб визначити логіку, яку слід виконати під час запуску і під час вимкнення. +Є альтернативний спосіб визначити логіку, яку слід виконати під час *запуску* і під час *вимкнення*. Ви можете визначити обробники подій (функції), які потрібно виконати перед запуском застосунку або коли застосунок вимикається. @@ -120,7 +120,7 @@ async with lifespan(app): Тут функція-обробник події `shutdown` запише текстовий рядок `"Application shutdown"` у файл `log.txt`. -/// info | Інформація +/// note | Примітка У функції `open()` параметр `mode="a"` означає «append», тож рядок буде додано після всього, що є у файлі, без перезапису попереднього вмісту. @@ -130,7 +130,7 @@ async with lifespan(app): Зауважте, що в цьому випадку ми використовуємо стандартну Python-функцію `open()`, яка працює з файлом. -Тобто вона включає I/O (input/output), де потрібно «чекати», поки дані буде записано на диск. +Тобто вона включає I/O (введення/виведення), де потрібно «чекати», поки дані буде записано на диск. Але `open()` не використовує `async` і `await`. @@ -140,7 +140,7 @@ async with lifespan(app): ### Разом `startup` і `shutdown` { #startup-and-shutdown-together } -Велика ймовірність, що логіка для вашого запуску і вимкнення пов’язана: ви можете хотіти щось запустити, а потім завершити, отримати ресурс, а потім звільнити його тощо. +Велика ймовірність, що логіка для вашого *запуску* і *вимкнення* пов’язана: ви можете хотіти щось запустити, а потім завершити, отримати ресурс, а потім звільнити його тощо. Робити це в окремих функціях, які не діляться логікою чи змінними, складніше - доведеться зберігати значення у глобальних змінних або вдаватися до подібних трюків. @@ -152,9 +152,9 @@ async with lifespan(app): Під капотом, у технічній специфікації ASGI, це частина [Протоколу тривалості життя](https://asgi.readthedocs.io/en/latest/specs/lifespan.html), і там визначені події `startup` і `shutdown`. -/// info | Інформація +/// note | Примітка -Ви можете прочитати більше про обробники `lifespan` у [документації Starlette про Lifespan](https://www.starlette.dev/lifespan/). +Ви можете прочитати більше про обробники `lifespan` Starlette у [документації Starlette про Lifespan](https://www.starlette.dev/lifespan/). Зокрема, як працювати зі станом тривалості життя, який можна використовувати в інших ділянках вашого коду. diff --git a/docs/uk/docs/advanced/generate-clients.md b/docs/uk/docs/advanced/generate-clients.md index d1b7e9c0c..0fad82dff 100644 --- a/docs/uk/docs/advanced/generate-clients.md +++ b/docs/uk/docs/advanced/generate-clients.md @@ -10,7 +10,7 @@ Універсальним варіантом є [OpenAPI Generator](https://openapi-generator.tech/), який підтримує **багато мов програмування** та може генерувати SDK з вашої специфікації OpenAPI. -Для **клієнтів TypeScript** [Hey API](https://heyapi.dev/) — спеціалізоване рішення, що надає оптимізований досвід для екосистеми TypeScript. +Для **клієнтів TypeScript** [Hey API](https://heyapi.dev/) - спеціалізоване рішення, що надає оптимізований досвід для екосистеми TypeScript. Більше генераторів SDK ви можете знайти на [OpenAPI.Tools](https://openapi.tools/#sdk). @@ -20,21 +20,6 @@ FastAPI автоматично генерує специфікації **OpenAPI /// -## Генератори SDK від спонсорів FastAPI { #sdk-generators-from-fastapi-sponsors } - -У цьому розділі представлено рішення від компаній, що спонсорують FastAPI: вони мають **венчурну підтримку** та **корпоративну підтримку**. Ці продукти надають **додаткові можливості** та **інтеграції** поверх високоякісно згенерованих SDK. - -Завдяки ✨ [**спонсорству FastAPI**](../help-fastapi.md#sponsor-the-author) ✨ ці компанії допомагають підтримувати фреймворк та його **екосистему** здоровими та **сталими**. - -Їхня підтримка також демонструє сильну відданість **спільноті** FastAPI (вам), показуючи, що їм важливо не лише надавати **відмінний сервіс**, а й підтримувати **міцний і процвітаючий фреймворк**, FastAPI. 🙇 - -Наприклад, ви можете спробувати: - -* [Stainless](https://www.stainless.com/?utm_source=fastapi&utm_medium=referral) -* [liblab](https://developers.liblab.com/tutorials/sdk-for-fastapi?utm_source=fastapi) - -Деякі з цих рішень також можуть бути з відкритим кодом або мати безкоштовні тарифи, тож ви можете спробувати їх без фінансових зобов'язань. Інші комерційні генератори SDK також доступні й їх можна знайти онлайн. 🤓 - ## Створити TypeScript SDK { #create-a-typescript-sdk } Почнімо з простого застосунку FastAPI: diff --git a/docs/uk/docs/advanced/json-base64-bytes.md b/docs/uk/docs/advanced/json-base64-bytes.md index 2cb6461ec..72786f05e 100644 --- a/docs/uk/docs/advanced/json-base64-bytes.md +++ b/docs/uk/docs/advanced/json-base64-bytes.md @@ -4,7 +4,7 @@ ## Base64 проти файлів { #base64-vs-files } -Насамперед розгляньте, чи можете ви використати [Файли запиту](../tutorial/request-files.md) для завантаження двійкових даних і [Користувацька відповідь - FileResponse](./custom-response.md#fileresponse--fileresponse-) для надсилання двійкових даних замість кодування їх у JSON. +Насамперед розгляньте, чи можете ви використати [Файли запиту](../tutorial/request-files.md) для завантаження двійкових даних і [Користувацька відповідь - FileResponse](./custom-response.md#fileresponse) для надсилання двійкових даних замість кодування їх у JSON. JSON може містити лише строки, закодовані в UTF-8, тому він не може містити «сирі» байти. @@ -14,7 +14,7 @@ Base64 може кодувати двійкові дані у строках, а ## Pydantic `bytes` { #pydantic-bytes } -Ви можете оголосити модель Pydantic з полями `bytes`, а потім використати `val_json_bytes` у конфігурації моделі, щоб вказати їй використовувати base64 для перевірки вхідних даних JSON; як частина цієї перевірки, вона декодує строку base64 у байти. +Ви можете оголосити модель Pydantic з полями `bytes`, а потім використати `val_json_bytes` у конфігурації моделі, щоб вказати їй використовувати base64 для *перевірки* вхідних даних JSON; як частина цієї перевірки, вона декодує строку base64 у байти. {* ../../docs_src/json_base64_bytes/tutorial001_py310.py ln[1:9,29:35] hl[9] *} @@ -52,12 +52,12 @@ Base64 може кодувати двійкові дані у строках, а ## Pydantic `bytes` для вихідних даних { #pydantic-bytes-for-output-data } -Ви також можете використовувати поля `bytes` з `ser_json_bytes` у конфігурації моделі для вихідних даних, і Pydantic серіалізує байти як base64 під час формування відповіді JSON. +Ви також можете використовувати поля `bytes` з `ser_json_bytes` у конфігурації моделі для вихідних даних, і Pydantic *серіалізує* байти як base64 під час формування відповіді JSON. {* ../../docs_src/json_base64_bytes/tutorial001_py310.py ln[1:2,12:16,29,38:41] hl[16] *} ## Pydantic `bytes` для вхідних і вихідних даних { #pydantic-bytes-for-input-and-output-data } -І, звісно, ви можете використовувати ту саму модель, налаштовану на base64, щоб обробляти і вхідні дані (перевіряти) з `val_json_bytes`, і вихідні дані (серіалізувати) з `ser_json_bytes` під час отримання та надсилання даних JSON. +І, звісно, ви можете використовувати ту саму модель, налаштовану на base64, щоб обробляти і вхідні дані (*перевіряти*) з `val_json_bytes`, і вихідні дані (*серіалізувати*) з `ser_json_bytes` під час отримання та надсилання даних JSON. {* ../../docs_src/json_base64_bytes/tutorial001_py310.py ln[1:2,19:26,29,44:46] hl[23:26] *} diff --git a/docs/uk/docs/advanced/openapi-callbacks.md b/docs/uk/docs/advanced/openapi-callbacks.md index 5c5c96661..ab0eb15ea 100644 --- a/docs/uk/docs/advanced/openapi-callbacks.md +++ b/docs/uk/docs/advanced/openapi-callbacks.md @@ -1,10 +1,10 @@ # Зворотні виклики OpenAPI { #openapi-callbacks } -Ви можете створити API з операцією шляху, яка ініціюватиме запит до зовнішнього API, створеного кимось іншим (ймовірно тим самим розробником, який буде використовувати ваш API). +Ви можете створити API з *операцією шляху*, яка ініціюватиме запит до *зовнішнього API*, створеного кимось іншим (ймовірно тим самим розробником, який буде *використовувати* ваш API). -Процес, що відбувається, коли ваш застосунок API викликає зовнішній API, називається «зворотний виклик». Тому що програмне забезпечення, написане зовнішнім розробником, надсилає запит до вашого API, а потім ваш API виконує зворотний виклик, надсилаючи запит до зовнішнього API (його, ймовірно, також створив той самий розробник). +Процес, що відбувається, коли ваш застосунок API викликає *зовнішній API*, називається «зворотний виклик». Тому що програмне забезпечення, написане зовнішнім розробником, надсилає запит до вашого API, а потім ваш API *виконує зворотний виклик*, надсилаючи запит до *зовнішнього API* (його, ймовірно, також створив той самий розробник). -У такому випадку вам може знадобитися задокументувати, яким має бути той зовнішній API: які операції шляху він має мати, яке тіло очікувати, яку відповідь повертати тощо. +У такому випадку вам може знадобитися задокументувати, яким має бути той *зовнішній API*: яку *операцію шляху* він має мати, яке тіло очікувати, яку відповідь повертати тощо. ## Застосунок зі зворотними викликами { #an-app-with-callbacks } @@ -21,13 +21,13 @@ - Надсилати рахунок деякому клієнту зовнішнього розробника. - Отримувати оплату. - Надсилати сповіщення назад користувачу API (зовнішньому розробнику). - - Це буде зроблено шляхом надсилання POST-запиту (з вашого API) до деякого зовнішнього API, наданого тим зовнішнім розробником (це і є «зворотний виклик»). + - Це буде зроблено шляхом надсилання POST-запиту (з *вашого API*) до деякого *зовнішнього API*, наданого тим зовнішнім розробником (це і є «зворотний виклик»). -## Звичайний застосунок FastAPI { #the-normal-fastapi-app } +## Звичайний застосунок **FastAPI** { #the-normal-fastapi-app } Спочатку подивімося, як виглядав би звичайний застосунок API до додавання зворотного виклику. -Він матиме операцію шляху, яка отримуватиме тіло `Invoice`, і параметр запиту `callback_url`, що міститиме URL для зворотного виклику. +Він матиме *операцію шляху*, яка отримуватиме тіло `Invoice`, і параметр запиту `callback_url`, що міститиме URL для зворотного виклику. Ця частина цілком звична, більшість коду вам, ймовірно, уже знайома: @@ -39,7 +39,7 @@ /// -Єдина нова річ - це `callbacks=invoices_callback_router.routes` як аргумент декоратора операції шляху. Далі розглянемо, що це таке. +Єдина нова річ - це `callbacks=invoices_callback_router.routes` як аргумент *декоратора операції шляху*. Далі розглянемо, що це таке. ## Документування зворотного виклику { #documenting-the-callback } @@ -54,11 +54,11 @@ callback_url = "https://example.com/api/v1/invoices/events/" httpx.post(callback_url, json={"description": "Invoice paid", "paid": True}) ``` -Але, можливо, найважливіша частина зворотного виклику - переконатися, що користувач вашого API (зовнішній розробник) правильно реалізує зовнішній API відповідно до даних, які ваш API надсилатиме в тілі запиту зворотного виклику тощо. +Але, можливо, найважливіша частина зворотного виклику - переконатися, що користувач вашого API (зовнішній розробник) правильно реалізує *зовнішній API* відповідно до даних, які *ваш API* надсилатиме в тілі запиту зворотного виклику тощо. -Тому далі ми додамо код, щоб задокументувати, яким має бути цей зовнішній API, щоб приймати зворотний виклик від вашого API. +Тому далі ми додамо код, щоб задокументувати, яким має бути цей *зовнішній API*, щоб приймати зворотний виклик від *вашого API*. -Ця документація з'явиться в Swagger UI за адресою `/docs` у вашому API і дасть змогу зовнішнім розробникам зрозуміти, як створити зовнішній API. +Ця документація з'явиться в Swagger UI за адресою `/docs` у вашому API і дасть змогу зовнішнім розробникам зрозуміти, як створити *зовнішній API*. У цьому прикладі сам зворотний виклик не реалізовано (це може бути лише один рядок коду), лише частину з документацією. @@ -72,47 +72,47 @@ httpx.post(callback_url, json={"description": "Invoice paid", "paid": True}) ## Напишіть код документації для зворотного виклику { #write-the-callback-documentation-code } -Цей код не виконуватиметься у вашому застосунку, він потрібен лише, щоб задокументувати, яким має бути зовнішній API. +Цей код не виконуватиметься у вашому застосунку, він потрібен лише, щоб *задокументувати*, яким має бути *зовнішній API*. -Але ви вже знаєте, як легко створювати автоматичну документацію для API за допомогою FastAPI. +Але ви вже знаєте, як легко створювати автоматичну документацію для API за допомогою **FastAPI**. -Тож ми скористаємося цими знаннями, щоб задокументувати, яким має бути зовнішній API... створивши операції шляху, які має реалізувати зовнішній API (ті, які викликатиме ваш API). +Тож ми скористаємося цими знаннями, щоб задокументувати, яким має бути *зовнішній API*... створивши *операції шляху*, які має реалізувати зовнішній API (ті, які викликатиме ваш API). /// tip | Порада Пишучи код для документування зворотного виклику, корисно уявити, що ви - той *зовнішній розробник*. І що ви зараз реалізуєте *зовнішній API*, а не *ваш API*. -Тимчасово прийнявши цю точку зору ( *зовнішнього розробника* ), вам буде очевидніше, куди помістити параметри, яку Pydantic-модель використати для тіла, для відповіді тощо для того *зовнішнього API*. +Тимчасово прийнявши цю точку зору (*зовнішнього розробника*), вам буде очевидніше, куди помістити параметри, яку Pydantic-модель використати для тіла, для відповіді тощо для того *зовнішнього API*. /// -### Створіть callback `APIRouter` { #create-a-callback-apirouter } +### Створіть `APIRouter` зворотного виклику { #create-a-callback-apirouter } Спочатку створіть новий `APIRouter`, який міститиме один або кілька зворотних викликів. {* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[1,23] *} -### Створіть операцію шляху зворотного виклику { #create-the-callback-path-operation } +### Створіть *операцію шляху* зворотного виклику { #create-the-callback-path-operation } -Щоб створити операцію шляху зворотного виклику, використайте той самий `APIRouter`, який ви створили вище. +Щоб створити *операцію шляху* зворотного виклику, використайте той самий `APIRouter`, який ви створили вище. -Вона має виглядати як звичайна операція шляху FastAPI: +Вона має виглядати як звичайна *операція шляху* FastAPI: -- Ймовірно має містити оголошення тіла, яке вона приймає, напр. `body: InvoiceEvent`. -- І також може містити оголошення відповіді, яку вона повертає, напр. `response_model=InvoiceEventReceived`. +- Ймовірно має містити оголошення тіла, яке вона приймає, наприклад `body: InvoiceEvent`. +- І також може містити оголошення відповіді, яку вона повертає, наприклад `response_model=InvoiceEventReceived`. {* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[14:16,19:20,26:30] *} -Є 2 основні відмінності від звичайної операції шляху: +Є 2 основні відмінності від звичайної *операції шляху*: -- Їй не потрібен реальний код, адже ваш застосунок ніколи не викликатиме цей код. Вона використовується лише для документування зовнішнього API. Тому функція може просто містити `pass`. -- Шлях може містити [вираз OpenAPI 3](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#key-expression) (див. нижче), де можна використовувати змінні з параметрами та частини оригінального запиту, надісланого до вашого API. +- Їй не потрібен реальний код, адже ваш застосунок ніколи не викликатиме цей код. Вона використовується лише для документування *зовнішнього API*. Тому функція може просто містити `pass`. +- *Шлях* може містити [вираз OpenAPI 3](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#key-expression) (див. нижче), де можна використовувати змінні з параметрами та частини оригінального запиту, надісланого до *вашого API*. ### Вираз шляху зворотного виклику { #the-callback-path-expression } -Шлях зворотного виклику може містити [вираз OpenAPI 3](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#key-expression), який включає частини оригінального запиту, надісланого до вашого API. +*Шлях* зворотного виклику може містити [вираз OpenAPI 3](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#key-expression), який включає частини оригінального запиту, надісланого до *вашого API*. -У цьому випадку це строка: +У цьому випадку це `str`: ```Python "{$callback_url}/invoices/{$request.body.id}" @@ -134,7 +134,7 @@ https://yourapi.com/invoices/?callback_url=https://www.external.org/events } ``` -тоді *ваш API* опрацює рахунок і згодом надішле запит зворотного виклику на `callback_url` ( *зовнішній API* ): +тоді *ваш API* опрацює рахунок і згодом надішле запит зворотного виклику на `callback_url` (*зовнішній API*): ``` https://www.external.org/events/invoices/2expen51ve @@ -165,15 +165,15 @@ https://www.external.org/events/invoices/2expen51ve ### Додайте маршрутизатор зворотного виклику { #add-the-callback-router } -На цьому етапі ви маєте потрібні операції шляху зворотного виклику (ті, які має реалізувати *зовнішній розробник* у *зовнішньому API*) у створеному вище маршрутизаторі зворотного виклику. +На цьому етапі ви маєте потрібні *операції шляху зворотного виклику* (ті, які має реалізувати *зовнішній розробник* у *зовнішньому API*) у створеному вище маршрутизаторі зворотного виклику. -Тепер використайте параметр `callbacks` у декораторі операції шляху вашого API, щоб передати атрибут `.routes` (це насправді просто `list` маршрутів/операцій шляху) з цього маршрутизатора зворотного виклику: +Тепер використайте параметр `callbacks` у *декораторі операції шляху вашого API*, щоб передати атрибут `.routes` з цього маршрутизатора зворотного виклику: {* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[33] *} /// tip | Порада -Зверніть увагу, що ви передаєте не сам маршрутизатор (`invoices_callback_router`) у `callback=`, а атрибут `.routes`, тобто `invoices_callback_router.routes`. +Зверніть увагу, що ви передаєте не сам маршрутизатор (`invoices_callback_router`) у `callbacks=`, а його `.routes`, тобто `invoices_callback_router.routes`. FastAPI використає ці маршрути, щоб згенерувати документацію OpenAPI для зворотних викликів. /// @@ -181,6 +181,6 @@ https://www.external.org/events/invoices/2expen51ve Тепер ви можете запустити застосунок і перейти за адресою [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs). -Ви побачите вашу документацію з розділом «Callbacks» для вашої операції шляху, який показує, як має виглядати зовнішній API: +Ви побачите вашу документацію з розділом «Callbacks» для вашої *операції шляху*, який показує, як має виглядати *зовнішній API*: diff --git a/docs/uk/docs/advanced/openapi-webhooks.md b/docs/uk/docs/advanced/openapi-webhooks.md index bf51f5466..b46b0ce46 100644 --- a/docs/uk/docs/advanced/openapi-webhooks.md +++ b/docs/uk/docs/advanced/openapi-webhooks.md @@ -22,7 +22,7 @@ Це значно спростить для ваших користувачів **реалізацію їхніх API** для отримання ваших запитів **вебхуків**; вони навіть зможуть згенерувати частину власного коду API автоматично. -/// info | Інформація +/// note | Примітка Вебхуки доступні в OpenAPI 3.1.0 і вище, підтримуються FastAPI `0.99.0` і вище. @@ -36,7 +36,7 @@ Визначені вами вебхуки потраплять до **схеми OpenAPI** та автоматичного **інтерфейсу документації**. -/// info | Інформація +/// note | Примітка Об'єкт `app.webhooks` насправді є просто `APIRouter` - тим самим типом, який ви використовуєте, структуризуючи застосунок у кількох файлах. diff --git a/docs/uk/docs/advanced/path-operation-advanced-configuration.md b/docs/uk/docs/advanced/path-operation-advanced-configuration.md index f760209ab..07508422c 100644 --- a/docs/uk/docs/advanced/path-operation-advanced-configuration.md +++ b/docs/uk/docs/advanced/path-operation-advanced-configuration.md @@ -16,17 +16,11 @@ ### Використання назви *функції операції шляху* як operationId { #using-the-path-operation-function-name-as-the-operationid } -Якщо ви хочете використовувати назви функцій ваших API як `operationId`, ви можете пройтися по всіх них і переписати `operation_id` кожної *операції шляху*, використовуючи їхній `APIRoute.name`. +Якщо ви хочете використовувати назви функцій ваших API як `operationId`, ви можете передати власну `generate_unique_id_function` до `FastAPI`. -Зробіть це після додавання всіх *операцій шляху*. +Функція отримує кожен `APIRoute` і повертає `operationId`, який слід використовувати для цієї операції шляху. -{* ../../docs_src/path_operation_advanced_configuration/tutorial002_py310.py hl[2, 12:21, 24] *} - -/// tip | Порада - -Якщо ви вручну викликаєте `app.openapi()`, оновіть усі `operationId` до цього. - -/// +{* ../../docs_src/path_operation_advanced_configuration/tutorial002_py310.py hl[2,5:6,9] *} /// warning | Попередження diff --git a/docs/uk/docs/advanced/response-change-status-code.md b/docs/uk/docs/advanced/response-change-status-code.md index 167df8313..e52479228 100644 --- a/docs/uk/docs/advanced/response-change-status-code.md +++ b/docs/uk/docs/advanced/response-change-status-code.md @@ -1,5 +1,6 @@ # Відповідь - зміна коду статусу { #response-change-status-code } + Ймовірно, ви вже читали, що можна встановити типовий [код статусу відповіді](../tutorial/response-status-code.md). Але інколи потрібно повернути інший код статусу, ніж типовий. diff --git a/docs/uk/docs/advanced/response-cookies.md b/docs/uk/docs/advanced/response-cookies.md index f4a79fb98..2e062adff 100644 --- a/docs/uk/docs/advanced/response-cookies.md +++ b/docs/uk/docs/advanced/response-cookies.md @@ -26,7 +26,7 @@ {* ../../docs_src/response_cookies/tutorial001_py310.py hl[10:12] *} -/// tip +/// tip | Порада Майте на увазі, що якщо ви повертаєте відповідь безпосередньо замість використання параметра `Response`, FastAPI поверне її напряму. diff --git a/docs/uk/docs/advanced/response-directly.md b/docs/uk/docs/advanced/response-directly.md index 30d8f5860..18318e6f3 100644 --- a/docs/uk/docs/advanced/response-directly.md +++ b/docs/uk/docs/advanced/response-directly.md @@ -18,7 +18,7 @@ Ви можете повертати `Response` або будь-який його підклас. -/// info | Інформація +/// note | Примітка `JSONResponse` сам є підкласом `Response`. diff --git a/docs/uk/docs/advanced/response-headers.md b/docs/uk/docs/advanced/response-headers.md index 95ab57fe0..67f1f0c6a 100644 --- a/docs/uk/docs/advanced/response-headers.md +++ b/docs/uk/docs/advanced/response-headers.md @@ -38,4 +38,4 @@ Майте на увазі, що власні пропрієтарні заголовки можна додавати [за допомогою префікса `X-`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers). -Але якщо у вас є власні заголовки, які клієнт у браузері має бачити, вам потрібно додати їх у вашу конфігурацію CORS (докладніше в [CORS (Cross-Origin Resource Sharing)](../tutorial/cors.md)), використовуючи параметр `expose_headers`, задокументований у [документації Starlette щодо CORS](https://www.starlette.dev/middleware/#corsmiddleware). +Але якщо у вас є власні заголовки, які клієнт у браузері має бачити, вам потрібно додати їх у вашу конфігурацію CORS (докладніше в [CORS (спільне використання ресурсів між різними джерелами)](../tutorial/cors.md)), використовуючи параметр `expose_headers`, задокументований у [документації Starlette щодо CORS](https://www.starlette.dev/middleware/#corsmiddleware). diff --git a/docs/uk/docs/advanced/security/oauth2-scopes.md b/docs/uk/docs/advanced/security/oauth2-scopes.md index 7f5ba9692..7c898da70 100644 --- a/docs/uk/docs/advanced/security/oauth2-scopes.md +++ b/docs/uk/docs/advanced/security/oauth2-scopes.md @@ -46,7 +46,7 @@ OAuth2 зі scopes - це механізм, який використовуют - `instagram_basic` використовується Facebook / Instagram. - `https://www.googleapis.com/auth/drive` використовується Google. -/// info | Інформація +/// note | Примітка В OAuth2 «scope» - це просто строка, що декларує конкретний потрібний дозвіл. @@ -76,7 +76,7 @@ OAuth2 зі scopes - це механізм, який використовуют Оскільки тепер ми оголошуємо ці scopes, вони з’являться в документації API, коли ви увійдете/авторизуєтеся. -І ви зможете обрати, які scopes надати доступ: `me` і `items`. +І ви зможете обрати, яким scopes надати доступ: `me` і `items`. Це той самий механізм, який використовується, коли ви надаєте дозволи під час входу через Facebook, Google, GitHub тощо: @@ -126,13 +126,13 @@ OAuth2 зі scopes - це механізм, який використовуют {* ../../docs_src/security/tutorial005_an_py310.py hl[5,141,172] *} -/// info | Технічні деталі +/// note | Технічні деталі `Security` насправді є підкласом `Depends`, і має лише один додатковий параметр, який ми побачимо пізніше. Але використовуючи `Security` замість `Depends`, **FastAPI** знатиме, що можна оголошувати scopes безпеки, використовувати їх внутрішньо та документувати API через OpenAPI. -Коли ви імпортуєте `Query`, `Path`, `Depends`, `Security` та інші з `fastapi`, це насправді функції, що повертають спеціальні класи. +Але коли ви імпортуєте `Query`, `Path`, `Depends`, `Security` та інші з `fastapi`, це насправді функції, що повертають спеціальні класи. /// @@ -152,7 +152,7 @@ OAuth2 зі scopes - це механізм, який використовуют {* ../../docs_src/security/tutorial005_an_py310.py hl[9,106] *} -## Використовуйте scopes { #use-the-scopes } +## Використовуйте `scopes` { #use-the-scopes } Параметр `security_scopes` матиме тип `SecurityScopes`. @@ -194,9 +194,9 @@ OAuth2 зі scopes - це механізм, який використовуют Ще раз розгляньмо дерево залежностей і scopes. -Оскільки залежність `get_current_active_user` має підзалежність `get_current_user`, scope «me», оголошений у `get_current_active_user`, буде включений до списку потрібних scopes у `security_scopes.scopes`, переданого до `get_current_user`. +Оскільки залежність `get_current_active_user` має підзалежність `get_current_user`, scope `"me"`, оголошений у `get_current_active_user`, буде включений до списку потрібних scopes у `security_scopes.scopes`, переданого до `get_current_user`. -Сама операція шляху також оголошує scope «items», отже він також буде у списку `security_scopes.scopes`, переданому до `get_current_user`. +Сама операція шляху також оголошує scope `"items"`, отже він також буде у списку `security_scopes.scopes`, переданому до `get_current_user`. Ось як виглядає ієрархія залежностей і scopes: diff --git a/docs/uk/docs/advanced/settings.md b/docs/uk/docs/advanced/settings.md index b369e2f12..867eb23b0 100644 --- a/docs/uk/docs/advanced/settings.md +++ b/docs/uk/docs/advanced/settings.md @@ -100,7 +100,7 @@ $ ADMIN_EMAIL="deadpool@example.com" APP_NAME="ChimichangApp" fastapi run main.p ## Налаштування в іншому модулі { #settings-in-another-module } -Ви можете розмістити ці налаштування в іншому модулі, як ви бачили в [Більші застосунки - кілька файлів](../tutorial/bigger-applications.md). +Ви можете розмістити ці налаштування в іншому файлі модуля, як ви бачили в [Більші застосунки - кілька файлів](../tutorial/bigger-applications.md). Наприклад, у вас може бути файл `config.py` з: @@ -297,6 +297,6 @@ participant execute as Execute function Ви можете використовувати Pydantic Settings для обробки налаштувань або конфігурацій вашого застосунку, з усією потужністю моделей Pydantic. -- Використовуючи залежність, ви можете спростити тестування. -- Ви можете використовувати з ним файли `.env`. -- Використання `@lru_cache` дає змогу уникнути повторного читання файла dotenv для кожного запиту, водночас дозволяючи переписувати його під час тестування. +* Використовуючи залежність, ви можете спростити тестування. +* Ви можете використовувати з ним файли `.env`. +* Використання `@lru_cache` дає змогу уникнути повторного читання файла dotenv для кожного запиту, водночас дозволяючи переписувати його під час тестування. diff --git a/docs/uk/docs/advanced/stream-data.md b/docs/uk/docs/advanced/stream-data.md index 4f12132e0..29d66739e 100644 --- a/docs/uk/docs/advanced/stream-data.md +++ b/docs/uk/docs/advanced/stream-data.md @@ -2,9 +2,9 @@ Якщо ви хочете передавати потоком дані, які можна структурувати як JSON, див. [Потокова передача JSON Lines](../tutorial/stream-json-lines.md). -Але якщо ви хочете передавати потоком чисті бінарні дані або строки, ось як це зробити. +Але якщо ви хочете передавати потоком **чисті бінарні дані** або строки, ось як це зробити. -/// info | Інформація +/// note | Примітка Додано у FastAPI 0.134.0. @@ -12,21 +12,21 @@ ## Варіанти використання { #use-cases } -Це можна використовувати, якщо ви хочете передавати потоком чисті строки, наприклад безпосередньо з виводу сервісу AI LLM. +Це можна використовувати, якщо ви хочете передавати потоком чисті строки, наприклад безпосередньо з виводу сервісу **AI LLM**. -Також це можна використати для потокової передачі великих бінарних файлів, коли ви надсилаєте кожний фрагмент даних під час читання, без потреби завантажувати все в пам'ять одразу. +Також це можна використати для потокової передачі **великих бінарних файлів**, коли ви надсилаєте кожний фрагмент даних під час читання, без потреби завантажувати все в пам'ять одразу. -Так само можна стрімити відео чи аудіо; їх навіть можна генерувати під час обробки та надсилання. +Так само можна стрімити **відео** чи **аудіо**; їх навіть можна генерувати під час обробки та надсилання. ## `StreamingResponse` з `yield` { #a-streamingresponse-with-yield } -Якщо ви оголосите `response_class=StreamingResponse` у вашій функції операції шляху, ви можете використовувати `yield`, щоб послідовно надсилати кожний фрагмент даних. +Якщо ви оголосите `response_class=StreamingResponse` у вашій *функції операції шляху*, ви можете використовувати `yield`, щоб послідовно надсилати кожний фрагмент даних. {* ../../docs_src/stream_data/tutorial001_py310.py ln[1:23] hl[20,23] *} FastAPI передаватиме кожний фрагмент даних до `StreamingResponse` як є; він не намагатиметься перетворити його на JSON чи щось подібне. -### Не-async функції операції шляху { #non-async-path-operation-functions } +### Не-async *функції операції шляху* { #non-async-path-operation-functions } Можна також використовувати звичайні функції `def` (без `async`) і так само застосовувати `yield`. @@ -40,7 +40,7 @@ FastAPI передаватиме кожний фрагмент даних до ` {* ../../docs_src/stream_data/tutorial001_py310.py ln[32:35] hl[33] *} -Це також означає, що з `StreamingResponse` у вас є свобода і відповідальність формувати та кодувати байти даних саме так, як їх потрібно надіслати, незалежно від анотацій типів. 🤓 +Це також означає, що з `StreamingResponse` у вас є **свобода** і **відповідальність** формувати та кодувати байти даних саме так, як їх потрібно надіслати, незалежно від анотацій типів. 🤓 ### Потік байтів { #stream-bytes } @@ -58,7 +58,7 @@ FastAPI передаватиме кожний фрагмент даних до ` {* ../../docs_src/stream_data/tutorial002_py310.py ln[6,19:20] hl[20] *} -Потім ви можете використати цей новий клас у `response_class=PNGStreamingResponse` у вашій функції операції шляху: +Потім ви можете використати цей новий клас у `response_class=PNGStreamingResponse` у вашій *функції операції шляху*: {* ../../docs_src/stream_data/tutorial002_py310.py ln[23:27] hl[23] *} @@ -90,7 +90,7 @@ FastAPI передаватиме кожний фрагмент даних до ` І часто їх читання є блокувальною операцією (що може блокувати цикл подій), адже дані зчитуються з диска або мережі. -/// info | Інформація +/// note | Примітка Наведений вище приклад - виняток, адже об'єкт `io.BytesIO` вже в пам'яті, тож читання нічого не блокує. @@ -98,7 +98,7 @@ FastAPI передаватиме кожний фрагмент даних до ` /// -Щоб уникнути блокування циклу подій, просто оголосіть функцію операції шляху зі звичайним `def` замість `async def`. Тоді FastAPI виконуватиме її в працівнику пулу потоків, щоб не блокувати головний цикл. +Щоб уникнути блокування циклу подій, просто оголосіть *функцію операції шляху* зі звичайним `def` замість `async def`. Тоді FastAPI виконуватиме її в працівнику пулу потоків, щоб не блокувати головний цикл. {* ../../docs_src/stream_data/tutorial002_py310.py ln[30:34] hl[31] *} diff --git a/docs/uk/docs/advanced/strict-content-type.md b/docs/uk/docs/advanced/strict-content-type.md index a244ec901..7d3156b09 100644 --- a/docs/uk/docs/advanced/strict-content-type.md +++ b/docs/uk/docs/advanced/strict-content-type.md @@ -40,7 +40,7 @@ http://localhost:8000 Використовуючи фронтенд, ви можете змушувати AI-агента виконувати дії від вашого імені. -Оскільки він працює локально, а не у відкритому інтернеті, ви вирішуєте не налаштовувати жодної автентифікації, просто покладаючись на доступ до локальної мережі. +Оскільки він працює **локально**, а не у відкритому інтернеті, ви вирішуєте **не налаштовувати жодної автентифікації**, просто покладаючись на доступ до локальної мережі. Один із ваших користувачів може встановити його і запустити локально. @@ -81,7 +81,7 @@ http://localhost:8000/v1/agents/multivac З цим налаштуванням запити без заголовка `Content-Type` матимуть тіло, розібране як JSON, що відповідає поведінці старіших версій FastAPI. -/// info | Інформація +/// note | Примітка Цю поведінку і конфігурацію додано у FastAPI 0.132.0. diff --git a/docs/uk/docs/advanced/websockets.md b/docs/uk/docs/advanced/websockets.md index aa290b389..1d96933be 100644 --- a/docs/uk/docs/advanced/websockets.md +++ b/docs/uk/docs/advanced/websockets.md @@ -111,7 +111,7 @@ $ fastapi dev {* ../../docs_src/websockets_/tutorial002_an_py310.py hl[68:69,82] *} -/// info +/// note Оскільки це WebSocket, не має сенсу піднімати `HTTPException`, натомість ми піднімаємо `WebSocketException`. diff --git a/docs/uk/docs/advanced/wsgi.md b/docs/uk/docs/advanced/wsgi.md index 84d4aa460..aa4dcb6b0 100644 --- a/docs/uk/docs/advanced/wsgi.md +++ b/docs/uk/docs/advanced/wsgi.md @@ -1,12 +1,13 @@ # Підключення WSGI - Flask, Django та інші { #including-wsgi-flask-django-others } + Ви можете монтувати застосунки WSGI, як ви бачили в [Підзастосунки - монтування](sub-applications.md), [За представником](behind-a-proxy.md). Для цього ви можете використати `WSGIMiddleware` і обгорнути ним ваш застосунок WSGI, наприклад Flask, Django тощо. ## Використання `WSGIMiddleware` { #using-wsgimiddleware } -/// info | Інформація +/// note | Примітка Для цього потрібно встановити `a2wsgi`, наприклад за допомогою `pip install a2wsgi`. diff --git a/docs/uk/docs/alternatives.md b/docs/uk/docs/alternatives.md index 155c727df..f903f3f20 100644 --- a/docs/uk/docs/alternatives.md +++ b/docs/uk/docs/alternatives.md @@ -44,11 +44,11 @@ Django REST Framework створив Том Крісті. Той самий тв ### [Flask](https://flask.palletsprojects.com) { #flask } -Flask — це «мікрофреймворк», він не включає інтеграцію бази даних, а також багато речей, які за замовчуванням є в Django. +Flask - це «мікрофреймворк», він не включає інтеграцію бази даних, а також багато речей, які за замовчуванням є в Django. Ця простота та гнучкість дозволяють використовувати бази даних NoSQL як основну систему зберігання даних. -Оскільки він дуже простий, він порівняно легкий та інтуїтивний для освоєння, хоча в деяких моментах документація стає дещо технічною. +Оскільки він дуже простий, він порівняно інтуїтивний для освоєння, хоча в деяких моментах документація стає дещо технічною. Він також зазвичай використовується для інших програм, яким не обов’язково потрібна база даних, керування користувачами або будь-яка з багатьох функцій, які є попередньо вбудованими в Django. Хоча багато з цих функцій можна додати за допомогою плагінів. @@ -72,7 +72,7 @@ Flask — це «мікрофреймворк», він не включає ін Але все ж FastAPI черпав натхнення з Requests. -**Requests** — це бібліотека для *взаємодії* з API (як клієнт), а **FastAPI** — це бібліотека для *створення* API (як сервер). +**Requests** - це бібліотека для *взаємодії* з API (як клієнт), а **FastAPI** - це бібліотека для *створення* API (як сервер). Вони більш-менш знаходяться на протилежних кінцях, доповнюючи одна одну. @@ -88,7 +88,7 @@ Requests мають дуже простий та інтуїтивно зрозу response = requests.get("http://example.com/some/url") ``` -Відповідна операція шляху API FastAPI може виглядати так: +Відповідна *операція шляху* API FastAPI може виглядати так: ```Python hl_lines="1" @app.get("/some/url") @@ -124,7 +124,7 @@ def read_url(): Інтегрувати інструменти інтерфейсу на основі стандартів: -* [Інтерфейс Swagger](https://github.com/swagger-api/swagger-ui) +* [Swagger UI](https://github.com/swagger-api/swagger-ui) * [ReDoc](https://github.com/Rebilly/ReDoc) Ці два було обрано через те, що вони досить популярні та стабільні, але, виконавши швидкий пошук, ви можете знайти десятки додаткових альтернативних інтерфейсів для OpenAPI (які можна використовувати з **FastAPI**). @@ -157,7 +157,7 @@ Marshmallow створено для забезпечення цих функці Іншою важливою функцією, необхідною для API, є аналіз даних із вхідних запитів. -Webargs — це інструмент, створений, щоб забезпечити це поверх кількох фреймворків, включаючи Flask. +Webargs - це інструмент, створений, щоб забезпечити це поверх кількох фреймворків, включаючи Flask. Він використовує Marshmallow в основі для перевірки даних. І створений тими ж розробниками. @@ -239,7 +239,7 @@ Flask-apispec був створений тими ж розробниками Mar ### [NestJS](https://nestjs.com/) (та [Angular](https://angular.io/)) { #nestjs-and-angular } -Це навіть не Python, NestJS — це фреймворк NodeJS JavaScript (TypeScript), натхненний Angular. +Це навіть не Python, NestJS - це фреймворк NodeJS JavaScript (TypeScript), натхненний Angular. Це досягає чогось подібного до того, що можна зробити з Flask-apispec. @@ -281,7 +281,7 @@ Flask-apispec був створений тими ж розробниками Mar ### [Falcon](https://falconframework.org/) { #falcon } -Falcon — ще один високопродуктивний фреймворк Python, він розроблений як мінімальний і працює як основа інших фреймворків, таких як Hug. +Falcon - ще один високопродуктивний фреймворк Python, він розроблений як мінімальний і працює як основа інших фреймворків, таких як Hug. Він розроблений таким чином, щоб мати функції, які отримують два параметри, один «запит» і один «відповідь». Потім ви «читаєте» частини запиту та «записуєте» частини у відповідь. Через такий дизайн неможливо оголосити параметри запиту та тіла за допомогою стандартних підказок типу Python як параметри функції. @@ -351,7 +351,7 @@ Hug надихнув **FastAPI** оголосити параметр `response` /// -### [APIStar](https://github.com/encode/apistar) (<= 0,5) { #apistar-0-5 } +### [APIStar](https://github.com/encode/apistar) (<= 0.5) { #apistar-0-5 } Безпосередньо перед тим, як вирішити створити **FastAPI**, я знайшов сервер **APIStar**. Він мав майже все, що я шукав, і мав чудовий дизайн. @@ -373,7 +373,7 @@ Hug надихнув **FastAPI** оголосити параметр `response` Це вже не був веб-фреймворк API, оскільки творцю потрібно було зосередитися на Starlette. -Тепер APIStar — це набір інструментів для перевірки специфікацій OpenAPI, а не веб-фреймворк. +Тепер APIStar - це набір інструментів для перевірки специфікацій OpenAPI, а не веб-фреймворк. /// note | Примітка @@ -403,7 +403,7 @@ APIStar створив Том Крісті. Той самий хлопець, я ### [Pydantic](https://docs.pydantic.dev/) { #pydantic } -Pydantic — це бібліотека для визначення перевірки даних, серіалізації та документації (за допомогою Схеми JSON) на основі підказок типу Python. +Pydantic - це бібліотека для визначення перевірки даних, серіалізації та документації (за допомогою Схеми JSON) на основі підказок типу Python. Це робить його надзвичайно інтуїтивним. @@ -419,7 +419,7 @@ Pydantic — це бібліотека для визначення переві ### [Starlette](https://www.starlette.dev/) { #starlette } -Starlette — це легкий фреймворк/набір інструментів ASGI, який ідеально підходить для створення високопродуктивних asyncio сервісів. +Starlette - це легкий фреймворк/набір інструментів ASGI, який ідеально підходить для створення високопродуктивних asyncio сервісів. Він дуже простий та інтуїтивно зрозумілий. Його розроблено таким чином, щоб його можна було легко розширювати та мати модульні компоненти. @@ -433,7 +433,7 @@ Starlette — це легкий фреймворк/набір інструмен * CORS, GZip, статичні файли, потокові відповіді. * Підтримку сеансів і кукі. * 100% покриття тестом. -* 100% анотовану кодову базу. +* 100% анотовану типами кодову базу. * Кілька жорстких залежностей. Starlette наразі є найшвидшим фреймворком Python із перевірених. Перевершує лише Uvicorn, який є не фреймворком, а сервером. @@ -446,7 +446,7 @@ Starlette надає всі основні функції веб-мікрофр /// note | Технічні деталі -ASGI — це новий «стандарт», який розробляється членами основної команди Django. Це ще не «стандарт Python» (PEP), хоча вони в процесі цього. +ASGI - це новий «стандарт», який розробляється членами основної команди Django. Це ще не «стандарт Python» (PEP), хоча вони в процесі цього. Тим не менш, він уже використовується як «стандарт» кількома інструментами. Це значно покращує сумісність, оскільки ви можете переключити Uvicorn на будь-який інший сервер ASGI (наприклад, Daphne або Hypercorn), або ви можете додати інструменти, сумісні з ASGI, як-от `python-socketio`. @@ -464,9 +464,9 @@ ASGI — це новий «стандарт», який розробляєтьс ### [Uvicorn](https://www.uvicorn.dev/) { #uvicorn } -Uvicorn — це блискавичний сервер ASGI, побудований на uvloop і httptools. +Uvicorn - це блискавичний сервер ASGI, побудований на uvloop і httptools. -Це не веб-фреймворк, а сервер. Наприклад, він не надає інструментів для маршрутизації. Це те, що фреймворк на кшталт Starlette (або **FastAPI**) забезпечить поверх нього. +Це не веб-фреймворк, а сервер. Наприклад, він не надає інструментів для маршрутизації за шляхами. Це те, що фреймворк на кшталт Starlette (або **FastAPI**) забезпечить поверх нього. Це рекомендований сервер для Starlette і **FastAPI**. diff --git a/docs/uk/docs/async.md b/docs/uk/docs/async.md index 72e29b3ea..9a9a90d12 100644 --- a/docs/uk/docs/async.md +++ b/docs/uk/docs/async.md @@ -1,6 +1,6 @@ # Рівночасність і async / await { #concurrency-and-async-await } -Деталі щодо синтаксису `async def` для функцій операції шляху і деякі відомості про асинхронний код, рівночасність і паралелізм. +Деталі щодо синтаксису `async def` для *функцій операції шляху* і деякі відомості про асинхронний код, рівночасність і паралелізм. ## Поспішаєте? { #in-a-hurry } @@ -12,7 +12,7 @@ results = await some_library() ``` -Тоді оголошуйте ваші функції операції шляху з `async def`, наприклад: +Тоді оголошуйте ваші *функції операції шляху* з `async def`, наприклад: ```Python hl_lines="2" @app.get('/') @@ -29,7 +29,7 @@ async def read_results(): --- -Якщо ви використовуєте сторонню бібліотеку, яка взаємодіє з чимось (база даних, API, файлова система тощо) і не підтримує використання `await` (наразі це стосується більшості бібліотек баз даних), тоді оголошуйте ваші функції операції шляху як зазвичай, просто з `def`, наприклад: +Якщо ви використовуєте сторонню бібліотеку, яка взаємодіє з чимось (база даних, API, файлова система тощо) і не підтримує використання `await` (наразі це стосується більшості бібліотек баз даних), тоді оголошуйте ваші *функції операції шляху* як зазвичай, просто з `def`, наприклад: ```Python hl_lines="2" @app.get('/') @@ -48,7 +48,7 @@ def results(): --- -Примітка: ви можете змішувати `def` і `async def` у ваших функціях операції шляху скільки завгодно і визначати кожну з них найкращим для вас способом. FastAPI зробить з ними все правильно. +**Примітка**: ви можете змішувати `def` і `async def` у ваших *функціях операції шляху* скільки завгодно і визначати кожну з них найкращим для вас способом. FastAPI зробить з ними все правильно. У будь-якому з наведених випадків FastAPI все одно працюватиме асинхронно і буде надзвичайно швидким. @@ -56,17 +56,17 @@ def results(): ## Технічні деталі { #technical-details } -Сучасні версії Python мають підтримку «асинхронного коду» за допомогою так званих «співпрограм» з синтаксисом **`async` і `await`**. +Сучасні версії Python мають підтримку **«асинхронного коду»** за допомогою так званих **«співпрограм»** з синтаксисом **`async` і `await`**. Розгляньмо цю фразу по частинах у секціях нижче: -- Асинхронний код -- `async` і `await` -- Співпрограми +- **Асинхронний код** +- **`async` і `await`** +- **Співпрограми** ## Асинхронний код { #asynchronous-code } -Асинхронний код означає, що мова 💬 має спосіб сказати комп’ютеру/програмі 🤖, що в певний момент у коді він 🤖 має почекати, поки «щось інше» завершиться десь ще. Скажімо, це «щось інше» називається «slow-file» 📝. +Асинхронний код означає, що мова 💬 має спосіб сказати комп’ютеру/програмі 🤖, що в певний момент у коді він 🤖 має почекати, поки *«щось інше»* завершиться десь ще. Скажімо, це *«щось інше»* називається «slow-file» 📝. Отже, в цей час комп’ютер може піти і зробити іншу роботу, доки «slow-file» 📝 завершується. @@ -97,9 +97,9 @@ def results(): Ідею **асинхронного** коду, описану вище, інколи також називають **«рівночасністю»**. Вона відрізняється від **«паралелізму»**. -І рівночасність, і паралелізм стосуються «різних речей, що відбуваються більш-менш одночасно». +**Рівночасність** і **паралелізм** стосуються «різних речей, що відбуваються більш-менш одночасно». -Але деталі між рівночасністю і паралелізмом досить різні. +Але деталі між *рівночасністю* і *паралелізмом* досить різні. Щоб побачити різницю, уявімо таку історію про бургери: @@ -257,7 +257,7 @@ def results(): Ні! Це не мораль історії. -Рівночасність відрізняється від паралелізму. І вона краща у конкретних сценаріях, що містять багато очікування. Через це зазвичай вона значно краща за паралелізм для розробки вебзастосунків. Але не для всього. +Рівночасність відрізняється від паралелізму. І вона краща у **конкретних** сценаріях, що містять багато очікування. Через це зазвичай вона значно краща за паралелізм для розробки вебзастосунків. Але не для всього. Щоб урівноважити це, уявімо коротку історію: @@ -273,15 +273,15 @@ def results(): Завершення займе той самий час із «чергами» чи без (рівночасність), і ви виконаєте той самий обсяг роботи. -Але в цьому випадку, якби ви могли привести 8 колишніх касирів/кухарів/тепер прибиральників, і кожен з них (разом із вами) взяв би свою зону будинку для прибирання, ви могли б виконати всю роботу паралельно — з додатковою допомогою — і завершити значно швидше. +Але в цьому випадку, якби ви могли привести 8 колишніх касирів/кухарів/тепер прибиральників, і кожен з них (разом із вами) взяв би свою зону будинку для прибирання, ви могли б виконати всю роботу **паралельно** - з додатковою допомогою - і завершити значно швидше. У цьому сценарії кожен з прибиральників (включно з вами) був би процесором, що виконує свою частину роботи. -І оскільки більшість часу виконання займає реальна робота (а не очікування), а роботу на комп’ютері виконує CPU, ці проблеми називають «CPU bound». +І оскільки більшість часу виконання займає реальна робота (а не очікування), а роботу на комп’ютері виконує CPU, ці проблеми називають **«CPU bound»**. --- -Поширені приклади «CPU bound» операцій - це речі, що потребують складної математичної обробки. +Поширені приклади **CPU bound** операцій - це речі, що потребують складної математичної обробки. Наприклад: @@ -294,7 +294,7 @@ def results(): З **FastAPI** ви можете скористатися рівночасністю, що дуже поширена у веброзробці (та ж головна принада NodeJS). -Але ви також можете використати переваги паралелізму і багатопроцесорності (наявність кількох процесів, що працюють паралельно) для навантажень «CPU bound», як у системах машинного навчання. +Але ви також можете використати переваги паралелізму і багатопроцесорності (наявність кількох процесів, що працюють паралельно) для навантажень **«CPU bound»**, як у системах машинного навчання. Це, плюс простий факт, що Python є основною мовою для **Data Science**, машинного навчання і особливо глибокого навчання, робить FastAPI дуже вдалим вибором для веб API та застосунків Data Science / машинного навчання (серед багатьох інших). @@ -340,7 +340,7 @@ burgers = get_burgers(2) --- -Отже, якщо ви використовуєте бібліотеку, яку можна викликати з `await`, вам потрібно створити функцію операції шляху, що її використовує, з `async def`, як тут: +Отже, якщо ви використовуєте бібліотеку, яку можна викликати з `await`, вам потрібно створити *функцію операції шляху*, що її використовує, з `async def`, як тут: ```Python hl_lines="2-3" @app.get('/burgers') @@ -357,7 +357,7 @@ async def read_burgers(): Тож як же викликати першу `async`-функцію - курка чи яйце? -Якщо ви працюєте з **FastAPI**, вам не потрібно про це турбуватися, адже цією «першою» функцією буде ваша функція операції шляху, і FastAPI знатиме, як учинити правильно. +Якщо ви працюєте з **FastAPI**, вам не потрібно про це турбуватися, адже цією «першою» функцією буде ваша *функція операції шляху*, і FastAPI знатиме, як учинити правильно. Але якщо ви хочете використовувати `async` / `await` без FastAPI, ви також можете це зробити. @@ -395,7 +395,7 @@ Starlette (і **FastAPI**) базуються на [AnyIO](https://anyio.readthe Погляньмо на ту саму фразу ще раз: -> Сучасні версії Python мають підтримку «асинхронного коду» за допомогою так званих «співпрограм», з синтаксисом **`async` і `await`**. +> Сучасні версії Python мають підтримку **«асинхронного коду»** за допомогою так званих **«співпрограм»**, з синтаксисом **`async` і `await`**. Тепер це має більше сенсу. ✨ @@ -415,11 +415,11 @@ Starlette (і **FastAPI**) базуються на [AnyIO](https://anyio.readthe ### Функції операції шляху { #path-operation-functions } -Коли ви оголошуєте функцію операції шляху зі звичайним `def` замість `async def`, вона виконується у зовнішньому пулі потоків (threadpool), який потім «очікується», замість прямого виклику (оскільки прямий виклик блокував би сервер). +Коли ви оголошуєте *функцію операції шляху* зі звичайним `def` замість `async def`, вона виконується у зовнішньому пулі потоків (threadpool), який потім «очікується», замість прямого виклику (оскільки прямий виклик блокував би сервер). -Якщо ви прийшли з іншого async-фреймворку, який не працює так, як описано вище, і звикли визначати тривіальні, лише обчислювальні функції операції шляху зі звичайним `def` заради крихітного виграшу у продуктивності (близько 100 наносекунд), зверніть увагу, що у **FastAPI** ефект буде протилежним. У таких випадках краще використовувати `async def`, якщо тільки ваші функції операції шляху не використовують код, що виконує блокуюче I/O. +Якщо ви прийшли з іншого async-фреймворку, який не працює так, як описано вище, і звикли визначати тривіальні, лише обчислювальні *функції операції шляху* зі звичайним `def` заради крихітного виграшу у продуктивності (близько 100 наносекунд), зверніть увагу, що у **FastAPI** ефект буде протилежним. У таких випадках краще використовувати `async def`, якщо тільки ваші *функції операції шляху* не використовують код, що виконує блокуюче I/O. -Втім, у будь-якій ситуації є велика ймовірність, що **FastAPI** [все одно буде швидшим](index.md#performance) (або принаймні порівнянним) за ваш попередній фреймворк. +Втім, в обох ситуаціях є велика ймовірність, що **FastAPI** [все одно буде швидшим](index.md#performance) (або принаймні порівнянним) за ваш попередній фреймворк. ### Залежності { #dependencies } @@ -433,7 +433,7 @@ Starlette (і **FastAPI**) базуються на [AnyIO](https://anyio.readthe Будь-яка інша допоміжна функція, яку ви викликаєте безпосередньо, може бути створена зі звичайним `def` або `async def`, і FastAPI не впливатиме на спосіб її виклику. -Це відрізняється від функцій, які FastAPI викликає за вас: функції операції шляху і залежності. +Це відрізняється від функцій, які FastAPI викликає за вас: *функції операції шляху* і залежності. Якщо ваша допоміжна функція є звичайною функцією з `def`, її буде викликано безпосередньо (як ви написали у своєму коді), не в пулі потоків; якщо функція створена з `async def`, тоді вам слід використовувати `await` при її виклику у вашому коді. diff --git a/docs/uk/docs/deployment/cloud.md b/docs/uk/docs/deployment/cloud.md index 97d972717..8c7259946 100644 --- a/docs/uk/docs/deployment/cloud.md +++ b/docs/uk/docs/deployment/cloud.md @@ -16,7 +16,7 @@ FastAPI Cloud є основним спонсором і джерелом фін ## Хмарні постачальники - спонсори { #cloud-providers-sponsors } -Деякі інші хмарні постачальники ✨ [**спонсорують FastAPI**](../help-fastapi.md#sponsor-the-author) ✨ також. 🙇 +Деякі інші хмарні постачальники ✨ [**спонсорують FastAPI**](https://github.com/sponsors/tiangolo) ✨ також. 🙇 Можливо, ви захочете розглянути їх, щоб дотримуватися їхніх інструкцій і спробувати їхні сервіси: diff --git a/docs/uk/docs/deployment/concepts.md b/docs/uk/docs/deployment/concepts.md index a6a5bc80e..cec4d8f01 100644 --- a/docs/uk/docs/deployment/concepts.md +++ b/docs/uk/docs/deployment/concepts.md @@ -5,11 +5,11 @@ Деякі важливі концепції: - Безпека - HTTPS -- Запуск під час старту +- Запуск під час запуску - Перезапуски - Реплікація (кількість запущених процесів) - Пам'ять -- Попередні кроки перед стартом +- Попередні кроки перед запуском Подивимось, як вони впливають на **розгортання**. @@ -88,7 +88,7 @@ Тепер, коли ми знаємо різницю між термінами **процес** і **програма**, продовжимо говорити про розгортання. -## Запуск під час старту { #running-on-startup } +## Запуск під час запуску { #running-on-startup } У більшості випадків, коли ви створюєте веб-API, ви хочете, щоб він **працював постійно**, без перерв, щоб клієнти завжди мали до нього доступ. Звісно, якщо немає особливих причин запускати його лише в певних ситуаціях. Але зазвичай ви хочете, щоб він постійно працював і був **доступний**. @@ -102,15 +102,15 @@ І якщо сервер буде перезавантажено (наприклад, після оновлень або міграцій у хмарного провайдера), ви, ймовірно, **не помітите цього**. І через це ви навіть не знатимете, що треба вручну перезапустити процес. У результаті ваш API просто залишиться «мертвим». 😱 -### Автоматичний запуск під час старту { #run-automatically-on-startup } +### Автоматичний запуск під час запуску { #run-automatically-on-startup } -Загалом ви, напевно, захочете, щоб серверна програма (наприклад, Uvicorn) запускалася автоматично під час старту сервера і без будь-якого **людського втручання**, щоб завжди був запущений процес із вашим API (наприклад, Uvicorn із вашим FastAPI-застосунком). +Загалом ви, напевно, захочете, щоб серверна програма (наприклад, Uvicorn) запускалася автоматично під час запуску сервера і без будь-якого **людського втручання**, щоб завжди був запущений процес із вашим API (наприклад, Uvicorn із вашим FastAPI-застосунком). ### Окрема програма { #separate-program } -Щоб цього досягти, зазвичай використовують **окрему програму**, яка гарантує запуск вашого застосунку під час старту. І в багатьох випадках вона також забезпечує запуск інших компонентів або застосунків, наприклад бази даних. +Щоб цього досягти, зазвичай використовують **окрему програму**, яка гарантує запуск вашого застосунку під час запуску. І в багатьох випадках вона також забезпечує запуск інших компонентів або застосунків, наприклад бази даних. -### Приклади інструментів для запуску під час старту { #example-tools-to-run-at-startup } +### Приклади інструментів для запуску під час запуску { #example-tools-to-run-at-startup } Приклади інструментів, які можуть це робити: @@ -127,7 +127,7 @@ ## Перезапуски { #restarts } -Подібно до забезпечення запуску застосунку під час старту системи, ви, ймовірно, також захочете гарантувати його **перезапуск** після збоїв. +Подібно до забезпечення запуску застосунку під час запуску системи, ви, ймовірно, також захочете гарантувати його **перезапуск** після збоїв. ### Ми помиляємося { #we-make-mistakes } @@ -163,7 +163,7 @@ ### Приклади інструментів для автоматичного перезапуску { #example-tools-to-restart-automatically } -У більшості випадків той самий інструмент, який використовується для **запуску програми під час старту**, також використовується для автоматичних **перезапусків**. +У більшості випадків той самий інструмент, який використовується для **запуску програми під час запуску**, також використовується для автоматичних **перезапусків**. Наприклад, це можуть забезпечувати: @@ -192,7 +192,7 @@ Пам'ятаєте з документації [Про HTTPS](https.md), що на сервері лише один процес може слухати певну комбінацію порту та IP-адреси? -Это досі так. +Це досі так. Отже, щоб мати **кілька процесів** одночасно, має бути **єдиний процес, який слухає порт**, і який далі якимось чином передає комунікацію кожному процесу-працівнику. @@ -247,9 +247,9 @@ /// -## Попередні кроки перед стартом { #previous-steps-before-starting } +## Попередні кроки перед запуском { #previous-steps-before-starting } -Є багато випадків, коли потрібно виконати деякі кроки **перед стартом** вашого застосунку. +Є багато випадків, коли потрібно виконати деякі кроки **перед запуском** вашого застосунку. Наприклад, ви можете захотіти запустити **міграції бази даних**. @@ -310,11 +310,11 @@ Тут ви прочитали про основні концепції, які, ймовірно, потрібно тримати в голові, вирішуючи, як розгортати ваш застосунок: - Безпека - HTTPS -- Запуск під час старту +- Запуск під час запуску - Перезапуски - Реплікація (кількість запущених процесів) - Пам'ять -- Попередні кроки перед стартом +- Попередні кроки перед запуском Розуміння цих ідей і того, як їх застосовувати, має дати вам інтуїцію, необхідну для прийняття рішень під час конфігурування і тонкого налаштування ваших розгортань. 🤓 diff --git a/docs/uk/docs/deployment/docker.md b/docs/uk/docs/deployment/docker.md index 9d9afc0d1..83799a00f 100644 --- a/docs/uk/docs/deployment/docker.md +++ b/docs/uk/docs/deployment/docker.md @@ -1,8 +1,8 @@ # FastAPI у контейнерах - Docker { #fastapi-in-containers-docker } -Під час розгортання застосунків FastAPI поширений підхід - збирати образи контейнерів Linux. Зазвичай це робиться за допомогою [Docker](https://www.docker.com/). Потім ви можете розгорнути цей образ контейнера кількома різними способами. +Під час розгортання застосунків FastAPI поширений підхід - збирати **образи контейнерів Linux**. Зазвичай це робиться за допомогою [**Docker**](https://www.docker.com/). Потім ви можете розгорнути цей образ контейнера кількома різними способами. -Використання контейнерів Linux має кілька переваг, зокрема безпека, відтворюваність, простота та інші. +Використання контейнерів Linux має кілька переваг, зокрема **безпека**, **відтворюваність**, **простота** та інші. /// tip | Порада @@ -34,33 +34,33 @@ CMD ["fastapi", "run", "app/main.py", "--port", "80"] ## Що таке контейнер { #what-is-a-container } -Контейнери (переважно контейнери Linux) - це дуже легкий спосіб упакувати застосунки з усіма їхніми залежностями та потрібними файлами, ізолювавши їх від інших контейнерів (інших застосунків або компонентів) у тій самій системі. +Контейнери (переважно контейнери Linux) - це дуже **легкий** спосіб упакувати застосунки з усіма їхніми залежностями та потрібними файлами, ізолювавши їх від інших контейнерів (інших застосунків або компонентів) у тій самій системі. -Контейнери Linux працюють, використовуючи той самий ядро Linux, що й хост (машина, віртуальна машина, хмарний сервер тощо). Це означає, що вони дуже легкі (у порівнянні з повними віртуальними машинами, які емулюють цілу операційну систему). +Контейнери Linux працюють, використовуючи те саме ядро Linux, що й хост (машина, віртуальна машина, хмарний сервер тощо). Це означає, що вони дуже легкі (у порівнянні з повними віртуальними машинами, які емулюють цілу операційну систему). -Таким чином контейнери споживають мало ресурсів, приблизно як безпосередньо запущені процеси (віртуальна машина споживала б значно більше). +Таким чином контейнери споживають **мало ресурсів**, приблизно як безпосередньо запущені процеси (віртуальна машина споживала б значно більше). -У контейнерів також є власні ізольовані процеси виконання (зазвичай лише один процес), файлові системи та мережі, що спрощує розгортання, безпеку, розробку тощо. +У контейнерів також є власні **ізольовані** процеси виконання (зазвичай лише один процес), файлові системи та мережі, що спрощує розгортання, безпеку, розробку тощо. ## Що таке образ контейнера { #what-is-a-container-image } -Контейнер запускається з образу контейнера. +**Контейнер** запускається з **образу контейнера**. -Образ контейнера - це статична версія всіх файлів, змінних оточення та типова команда/програма, яка має бути присутня в контейнері. Тут «статична» означає, що образ контейнера не запущений, він не виконується, це лише упаковані файли та метадані. +Образ контейнера - це **статична** версія всіх файлів, змінних оточення та типова команда/програма, яка має бути присутня в контейнері. Тут **«статична»** означає, що **образ** контейнера не запущений, він не виконується, це лише упаковані файли та метадані. -На противагу «образу контейнера», що є збереженим статичним вмістом, «контейнер» зазвичай означає запущений екземпляр, те, що виконується. +На противагу «**образу контейнера**», що є збереженим статичним вмістом, «**контейнер**» зазвичай означає запущений екземпляр, те, що **виконується**. -Коли контейнер запущено (запущений з образу контейнера), він може створювати або змінювати файли, змінні оточення тощо. Ці зміни існуватимуть лише в цьому контейнері, але не збережуться в базовому образі контейнера (не будуть записані на диск). +Коли **контейнер** запущено (запущений з **образу контейнера**), він може створювати або змінювати файли, змінні оточення тощо. Ці зміни існуватимуть лише в цьому контейнері, але не збережуться в базовому образі контейнера (не будуть записані на диск). -Образ контейнера можна порівняти з файлом і вмістом програми, наприклад `python` і файлом `main.py`. +Образ контейнера можна порівняти з файлом і вмістом **програми**, наприклад `python` і файлом `main.py`. -А сам контейнер (на відміну від образу) - це фактично запущений екземпляр образу, порівнянний із процесом. Насправді контейнер працює лише тоді, коли в ньому працює процес (і зазвичай це один процес). Контейнер зупиняється, коли в ньому не працює жоден процес. +А сам **контейнер** (на відміну від **образу контейнера**) - це фактично запущений екземпляр образу, порівнянний із **процесом**. Насправді контейнер працює лише тоді, коли в ньому **працює процес** (і зазвичай це один процес). Контейнер зупиняється, коли в ньому не працює жоден процес. ## Образи контейнерів { #container-images } -Docker був одним з основних інструментів для створення та керування образами контейнерів і контейнерами. +Docker був одним з основних інструментів для створення та керування **образами контейнерів** і **контейнерами**. -Існує публічний [Docker Hub](https://hub.docker.com/) з готовими офіційними образами для багатьох інструментів, середовищ, баз даних і застосунків. +Існує публічний [Docker Hub](https://hub.docker.com/) з готовими **офіційними образами контейнерів** для багатьох інструментів, середовищ, баз даних і застосунків. Наприклад, є офіційний [образ Python](https://hub.docker.com/_/python). @@ -71,43 +71,43 @@ Docker був одним з основних інструментів для с * [MongoDB](https://hub.docker.com/_/mongo) * [Redis](https://hub.docker.com/_/redis) тощо. -Використовуючи готовий образ контейнера, дуже легко поєднувати та використовувати різні інструменти. Наприклад, щоб випробувати нову базу даних. У більшості випадків ви можете використати офіційні образи та просто налаштувати їх змінними оточення. +Використовуючи готовий образ контейнера, дуже легко **поєднувати** та використовувати різні інструменти. Наприклад, щоб випробувати нову базу даних. У більшості випадків ви можете використати **офіційні образи** та просто налаштувати їх змінними оточення. Таким чином, у багатьох випадках ви зможете навчитися працювати з контейнерами і Docker та повторно використати ці знання з багатьма різними інструментами і компонентами. -Тобто ви запускатимете кілька контейнерів з різними речами, як-от базу даних, застосунок на Python, вебсервер із фронтендом на React, і з’єднаєте їх через внутрішню мережу. +Тобто ви запускатимете **кілька контейнерів** з різними речами, як-от базу даних, застосунок на Python, вебсервер із фронтендом на React, і з’єднаєте їх через внутрішню мережу. Усі системи керування контейнерами (як Docker чи Kubernetes) мають ці мережеві можливості вбудовано. ## Контейнери і процеси { #containers-and-processes } -Образ контейнера зазвичай містить у своїх метаданих типову програму або команду, яку слід виконати під час запуску контейнера, і параметри для цієї програми. Дуже схоже на те, що ви б виконали в командному рядку. +**Образ контейнера** зазвичай містить у своїх метаданих типову програму або команду, яку слід виконати під час запуску **контейнера**, і параметри для цієї програми. Дуже схоже на те, що ви б виконали в командному рядку. -Коли контейнер запускається, він виконає цю команду/програму (хоча ви можете перевизначити її і запустити іншу команду/програму). +Коли **контейнер** запускається, він виконає цю команду/програму (хоча ви можете перевизначити її і запустити іншу команду/програму). -Контейнер працює доти, доки працює головний процес (команда або програма). +Контейнер працює доти, доки працює **головний процес** (команда або програма). -Зазвичай контейнер має один процес, але також можливо запускати підпроцеси з головного процесу, і таким чином у вас може бути кілька процесів у тому самому контейнері. +Зазвичай контейнер має **один процес**, але також можливо запускати підпроцеси з головного процесу, і таким чином у вас може бути **кілька процесів** у тому самому контейнері. -Але неможливо мати запущений контейнер без принаймні одного запущеного процесу. Якщо головний процес зупиняється, контейнер зупиняється. +Але неможливо мати запущений контейнер без **принаймні одного запущеного процесу**. Якщо головний процес зупиняється, контейнер зупиняється. ## Зібрати Docker-образ для FastAPI { #build-a-docker-image-for-fastapi } Гаразд, зберімо щось зараз! 🚀 -Я покажу вам, як зібрати образ Docker для FastAPI з нуля на основі офіційного образу Python. +Я покажу вам, як зібрати **образ Docker** для FastAPI **з нуля** на основі **офіційного образу Python**. -Це те, що ви захочете робити у більшості випадків, наприклад: +Це те, що ви захочете робити у **більшості випадків**, наприклад: -* Використання Kubernetes або подібних інструментів -* Під час запуску на Raspberry Pi +* Використання **Kubernetes** або подібних інструментів +* Під час запуску на **Raspberry Pi** * Використання хмарного сервісу, який запустить для вас образ контейнера тощо ### Вимоги до пакетів { #package-requirements } -Зазвичай ви маєте вимоги до пакетів для вашого застосунку в окремому файлі. +Зазвичай ви маєте **вимоги до пакетів** для вашого застосунку в окремому файлі. -Це залежить переважно від інструменту, який ви використовуєте для встановлення цих вимог. +Це залежить переважно від інструменту, який ви використовуєте для **встановлення** цих вимог. Найпоширеніший спосіб - мати файл `requirements.txt` з назвами пакетів і їхніми версіями, по одному на рядок. @@ -132,7 +132,7 @@ Successfully installed fastapi pydantic
-/// info | Інформація +/// note | Примітка Існують інші формати та інструменти для визначення і встановлення залежностей пакетів. @@ -192,9 +192,9 @@ CMD ["fastapi", "run", "app/main.py", "--port", "80"] 3. Скопіюйте файл з вимогами в директорію `/code`. - Спочатку скопіюйте лише файл з вимогами, а не решту коду. + Спочатку скопіюйте **лише** файл з вимогами, а не решту коду. - Оскільки цей файл змінюється нечасто, Docker виявить це і використає кеш для цього кроку, що також увімкне кеш і для наступного кроку. + Оскільки цей файл **змінюється нечасто**, Docker виявить це і використає **кеш** для цього кроку, що також увімкне кеш і для наступного кроку. 4. Встановіть залежності пакетів із файлу вимог. @@ -208,21 +208,21 @@ CMD ["fastapi", "run", "app/main.py", "--port", "80"] Опція `--upgrade` каже `pip` оновити пакети, якщо вони вже встановлені. - Оскільки попередній крок копіювання файлу може бути виявлений кешем Docker, цей крок також використовуватиме кеш Docker, коли це можливо. + Оскільки попередній крок копіювання файлу може бути виявлений **кешем Docker**, цей крок також **використовуватиме кеш Docker**, коли це можливо. - Використання кешу на цьому кроці збереже вам багато часу під час повторних збірок образу в розробці, замість того щоб завжди завантажувати і встановлювати всі залежності. + Використання кешу на цьому кроці **збереже** вам багато **часу** під час повторних збірок образу в розробці, замість того щоб **завантажувати і встановлювати** всі залежності **щоразу**. 5. Скопіюйте директорію `./app` у директорію `/code`. - Оскільки тут увесь код, який змінюється найчастіше, кеш Docker не буде легко використаний для цього або будь-яких наступних кроків. + Оскільки тут увесь код, який **змінюється найчастіше**, **кеш** Docker не буде легко використаний для цього або будь-яких **наступних кроків**. - Тому важливо розмістити це ближче до кінця `Dockerfile`, щоб оптимізувати час збірки образу контейнера. + Тому важливо розмістити це **ближче до кінця** `Dockerfile`, щоб оптимізувати час збірки образу контейнера. -6. Встановіть команду для використання `fastapi run`, яка всередині використовує Uvicorn. +6. Встановіть **команду** для використання `fastapi run`, яка всередині використовує Uvicorn. `CMD` приймає список строк, кожна з яких - це те, що ви б набирали в командному рядку, розділене пробілами. - Ця команда буде виконана з поточної робочої директорії, тієї самої `/code`, яку ви вказали вище через `WORKDIR /code`. + Ця команда буде виконана з **поточної робочої директорії**, тієї самої `/code`, яку ви вказали вище через `WORKDIR /code`. /// tip | Порада @@ -232,7 +232,7 @@ CMD ["fastapi", "run", "app/main.py", "--port", "80"] /// warning | Попередження -Обов’язково завжди використовуйте exec form інструкції `CMD`, як пояснено нижче. +Обов’язково **завжди** використовуйте **exec form** інструкції `CMD`, як пояснено нижче. /// @@ -240,21 +240,21 @@ CMD ["fastapi", "run", "app/main.py", "--port", "80"] Інструкцію Docker [`CMD`](https://docs.docker.com/reference/dockerfile/#cmd) можна записати у двох формах: -✅ Exec form: +✅ **Exec** form: ```Dockerfile # ✅ Робіть так CMD ["fastapi", "run", "app/main.py", "--port", "80"] ``` -⛔️ Shell form: +⛔️ **Shell** form: ```Dockerfile # ⛔️ Не робіть так CMD fastapi run app/main.py --port 80 ``` -Обов’язково завжди використовуйте exec form, щоб FastAPI міг коректно завершувати роботу та щоб були викликані [події тривалості життя](../advanced/events.md). +Обов’язково завжди використовуйте **exec** form, щоб FastAPI міг коректно завершувати роботу та щоб були викликані [події тривалості життя](../advanced/events.md). Докладніше про це можна прочитати в [документації Docker про shell та exec form](https://docs.docker.com/reference/dockerfile/#shell-and-exec-form). @@ -283,31 +283,31 @@ CMD ["fastapi", "run", "app/main.py", "--proxy-headers", "--port", "80"] #### Кеш Docker { #docker-cache } -У цьому `Dockerfile` є важливий трюк: спочатку ми копіюємо лише файл із залежностями, а не решту коду. Ось чому. +У цьому `Dockerfile` є важливий трюк: спочатку ми копіюємо лише **файл із залежностями**, а не решту коду. Ось чому. ```Dockerfile COPY ./requirements.txt /code/requirements.txt ``` -Docker та інші інструменти збирають ці образи контейнерів інкрементально, додаючи один шар поверх іншого, починаючи з верхньої частини `Dockerfile` і додаючи будь-які файли, створені кожною інструкцією в `Dockerfile`. +Docker та інші інструменти **збирають** ці образи контейнерів **інкрементально**, додаючи **один шар поверх іншого**, починаючи з верхньої частини `Dockerfile` і додаючи будь-які файли, створені кожною інструкцією в `Dockerfile`. -Docker та подібні інструменти також використовують внутрішній кеш під час збірки образу. Якщо файл не змінювався з моменту останньої збірки, тоді він повторно використає той самий шар, створений востаннє, замість копіювання файлу знову та створення нового шару з нуля. +Docker та подібні інструменти також використовують **внутрішній кеш** під час збірки образу. Якщо файл не змінювався з моменту останньої збірки, тоді він **повторно використає той самий шар**, створений востаннє, замість копіювання файлу знову та створення нового шару з нуля. -Просте уникнення копіювання файлів не обов’язково суттєво покращує ситуацію, але оскільки для цього кроку використано кеш, він може використати кеш і для наступного кроку. Наприклад, він може використати кеш для інструкції, яка встановлює залежності: +Просте уникнення копіювання файлів не обов’язково суттєво покращує ситуацію, але оскільки для цього кроку використано кеш, він може **використати кеш і для наступного кроку**. Наприклад, він може використати кеш для інструкції, яка встановлює залежності: ```Dockerfile RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt ``` -Файл із вимогами до пакетів змінюватиметься нечасто. Отже, копіюючи лише цей файл, Docker зможе використати кеш для цього кроку. +Файл із вимогами до пакетів **змінюватиметься нечасто**. Отже, копіюючи лише цей файл, Docker зможе **використати кеш** для цього кроку. -А потім Docker зможе використати кеш і для наступного кроку, який завантажує та встановлює ці залежності. І саме тут ми заощаджуємо багато часу. ✨ ...і уникаємо нудного очікування. 😪😆 +А потім Docker зможе **використати кеш і для наступного кроку**, який завантажує та встановлює ці залежності. І саме тут ми **заощаджуємо багато часу**. ✨ ...і уникаємо нудного очікування. 😪😆 -Завантаження і встановлення залежностей пакетів може займати хвилини, але використання кешу займе максимум секунди. +Завантаження і встановлення залежностей пакетів **може займати хвилини**, але використання **кешу** займе **максимум секунди**. І оскільки ви збиратимете образ контейнера знову і знову під час розробки, щоб перевіряти, що зміни у вашому коді працюють, це заощадить багато накопиченого часу. -Потім, ближче до кінця `Dockerfile`, ми копіюємо весь код. Оскільки це те, що змінюється найчастіше, ми розміщуємо це ближче до кінця, адже майже завжди все після цього кроку не зможе використати кеш. +Потім, ближче до кінця `Dockerfile`, ми копіюємо весь код. Оскільки це те, що **змінюється найчастіше**, ми розміщуємо це ближче до кінця, адже майже завжди все після цього кроку не зможе використати кеш. ```Dockerfile COPY ./app /code/app @@ -415,11 +415,11 @@ CMD ["fastapi", "run", "main.py", "--port", "80"] Поговорімо знову про деякі з тих самих [Концепцій розгортання](concepts.md) у термінах контейнерів. -Контейнери - це переважно інструмент для спрощення процесу збирання та розгортання застосунку, але вони не нав’язують конкретний підхід до обробки цих концепцій розгортання, і існує кілька можливих стратегій. +Контейнери - це переважно інструмент для спрощення процесу **збирання та розгортання** застосунку, але вони не нав’язують конкретний підхід до обробки цих **концепцій розгортання**, і існує кілька можливих стратегій. -Гарна новина полягає в тому, що для кожної стратегії є спосіб покрити всі концепції розгортання. 🎉 +**Гарна новина** полягає в тому, що для кожної стратегії є спосіб покрити всі концепції розгортання. 🎉 -Розгляньмо ці концепції розгортання в контексті контейнерів: +Розгляньмо ці **концепції розгортання** в контексті контейнерів: * HTTPS * Автозапуск @@ -430,9 +430,9 @@ CMD ["fastapi", "run", "main.py", "--port", "80"] ## HTTPS { #https } -Якщо зосередитись лише на образі контейнера для застосунку FastAPI (а згодом на запущеному контейнері), HTTPS зазвичай обробляється зовнішнім іншим інструментом. +Якщо зосередитись лише на **образі контейнера** для застосунку FastAPI (а згодом на запущеному **контейнері**), HTTPS зазвичай обробляється **зовнішнім** іншим інструментом. -Це може бути інший контейнер, наприклад з [Traefik](https://traefik.io/), що обробляє HTTPS і автоматичне отримання сертифікатів. +Це може бути інший контейнер, наприклад з [Traefik](https://traefik.io/), що обробляє **HTTPS** і **автоматичне** отримання **сертифікатів**. /// tip | Порада @@ -444,57 +444,57 @@ Traefik має інтеграції з Docker, Kubernetes та іншими, т ## Автозапуск і перезапуски { #running-on-startup-and-restarts } -Зазвичай інший інструмент відповідає за запуск і виконання вашого контейнера. +Зазвичай інший інструмент відповідає за **запуск і виконання** вашого контейнера. -Це може бути безпосередньо Docker, Docker Compose, Kubernetes, хмарний сервіс тощо. +Це може бути безпосередньо **Docker**, **Docker Compose**, **Kubernetes**, **хмарний сервіс** тощо. У більшості (або всіх) випадків є проста опція, щоб увімкнути запуск контейнера при старті системи та перезапуски у разі збоїв. Наприклад, у Docker це опція командного рядка `--restart`. -Без використання контейнерів змусити застосунки запускатися при старті системи та з перезапусками може бути клопітно і складно. Але під час роботи з контейнерами у більшості випадків ця функціональність вбудована за замовчуванням. ✨ +Без використання контейнерів змусити застосунки запускатися при старті системи та з перезапусками може бути клопітно і складно. Але під час **роботи з контейнерами** у більшості випадків ця функціональність вбудована за замовчуванням. ✨ ## Реплікація - кількість процесів { #replication-number-of-processes } -Якщо у вас є кластер машин із Kubernetes, Docker Swarm Mode, Nomad або іншою подібною складною системою для керування розподіленими контейнерами на кількох машинах, тоді ви, ймовірно, захочете обробляти реплікацію на рівні кластера замість використання менеджера процесів (як-от Uvicorn з працівниками) у кожному контейнері. +Якщо у вас є кластер машин із **Kubernetes**, Docker Swarm Mode, Nomad або іншою подібною складною системою для керування розподіленими контейнерами на кількох машинах, тоді ви, ймовірно, захочете **обробляти реплікацію** на **рівні кластера** замість використання **менеджера процесів** (як-от Uvicorn з працівниками) у кожному контейнері. -Одна з таких розподілених систем керування контейнерами, як-от Kubernetes, зазвичай має інтегровані способи обробляти реплікацію контейнерів, підтримуючи водночас балансування навантаження для вхідних запитів. Усе це - на рівні кластера. +Одна з таких розподілених систем керування контейнерами, як-от Kubernetes, зазвичай має інтегровані способи обробляти **реплікацію контейнерів**, підтримуючи водночас **балансування навантаження** для вхідних запитів. Усе це - на **рівні кластера**. -У таких випадках ви, ймовірно, захочете зібрати Docker-образ з нуля, як [пояснено вище](#dockerfile), встановивши ваші залежності і запустивши один процес Uvicorn замість використання кількох працівників Uvicorn. +У таких випадках ви, ймовірно, захочете зібрати **Docker-образ з нуля**, як [пояснено вище](#dockerfile), встановивши ваші залежності і запустивши **один процес Uvicorn** замість використання кількох працівників Uvicorn. ### Балансувальник навантаження { #load-balancer } -При використанні контейнерів зазвичай є якийсь компонент, що слухає на головному порту. Це може бути інший контейнер, який також є представником з термінацією TLS для обробки HTTPS, або подібний інструмент. +При використанні контейнерів зазвичай є якийсь компонент, що **слухає на головному порту**. Це може бути інший контейнер, який також є **представником з термінацією TLS** для обробки **HTTPS**, або подібний інструмент. -Оскільки цей компонент приймає навантаження запитів і розподіляє його між працівниками (сподіваємось) збалансовано, його також часто називають балансувальником навантаження. +Оскільки цей компонент приймає **навантаження** запитів і розподіляє його між працівниками (сподіваємось) **збалансовано**, його також часто називають **балансувальником навантаження**. /// tip | Порада -Той самий компонент представника з термінацією TLS, що використовується для HTTPS, швидше за все, також буде балансувальником навантаження. +Той самий компонент **представника з термінацією TLS**, що використовується для HTTPS, швидше за все, також буде **балансувальником навантаження**. /// -І під час роботи з контейнерами та сама система, яку ви використовуєте для їх запуску і керування ними, вже матиме внутрішні інструменти для передавання мережевої комунікації (наприклад, HTTP-запитів) від цього балансувальника навантаження (який також може бути представником з термінацією TLS) до контейнерів із вашим застосунком. +І під час роботи з контейнерами та сама система, яку ви використовуєте для їх запуску і керування ними, вже матиме внутрішні інструменти для передавання **мережевої комунікації** (наприклад, HTTP-запитів) від цього **балансувальника навантаження** (який також може бути **представником з термінацією TLS**) до контейнерів із вашим застосунком. ### Один балансувальник навантаження - кілька контейнерів-працівників { #one-load-balancer-multiple-worker-containers } -Під час роботи з Kubernetes або подібними розподіленими системами керування контейнерами використання їхніх внутрішніх мережевих механізмів дозволяє єдиному балансувальнику навантаження, що слухає на головному порту, передавати комунікацію (запити) до кількох контейнерів, у яких запущено ваш застосунок. +Під час роботи з **Kubernetes** або подібними розподіленими системами керування контейнерами використання їхніх внутрішніх мережевих механізмів дозволяє єдиному **балансувальнику навантаження**, що слухає на головному **порту**, передавати комунікацію (запити) до кількох **контейнерів**, у яких запущено ваш застосунок. -Кожен з цих контейнерів із вашим застосунком зазвичай має лише один процес (наприклад, процес Uvicorn, що запускає ваш застосунок FastAPI). Усі вони будуть ідентичними контейнерами, які запускають те саме, але кожен зі своїм процесом, пам’яттю тощо. Таким чином ви використаєте переваги паралелізму на різних ядрах процесора або навіть на різних машинах. +Кожен з цих контейнерів із вашим застосунком зазвичай має **лише один процес** (наприклад, процес Uvicorn, що запускає ваш застосунок FastAPI). Усі вони будуть **ідентичними контейнерами**, які запускають те саме, але кожен зі своїм процесом, пам’яттю тощо. Таким чином ви використаєте переваги **паралелізації** на **різних ядрах** процесора або навіть на **різних машинах**. -А розподілена система контейнерів із балансувальником навантаження розподілятиме запити між кожним із контейнерів із вашим застосунком по черзі. Тож кожен запит може оброблятися одним із кількох реплікованих контейнерів, що запускають ваш застосунок. +А розподілена система контейнерів із **балансувальником навантаження** **розподілятиме запити** між кожним із контейнерів із вашим застосунком **по черзі**. Тож кожен запит може оброблятися одним із кількох **реплікованих контейнерів**, що запускають ваш застосунок. -І зазвичай цей балансувальник навантаження зможе обробляти запити, які йдуть до інших застосунків у вашому кластері (наприклад, до іншого домену або під іншим префіксом шляху URL), і передаватиме комунікацію до відповідних контейнерів для того іншого застосунку, що працює у вашому кластері. +І зазвичай цей **балансувальник навантаження** зможе обробляти запити, які йдуть до *інших* застосунків у вашому кластері (наприклад, до іншого домену або під іншим префіксом шляху URL), і передаватиме комунікацію до відповідних контейнерів для *того іншого* застосунку, що працює у вашому кластері. ### Один процес на контейнер { #one-process-per-container } -У такому сценарії ви, ймовірно, захочете мати один (Uvicorn) процес на контейнер, адже ви вже обробляєте реплікацію на рівні кластера. +У такому сценарії ви, ймовірно, захочете мати **один (Uvicorn) процес на контейнер**, адже ви вже обробляєте реплікацію на рівні кластера. -Тобто в цьому випадку ви не захочете мати кількох працівників у контейнері, наприклад через опцію командного рядка `--workers`. Ви захочете мати лише один процес Uvicorn на контейнер (але, ймовірно, кілька контейнерів). +Тобто в цьому випадку ви **не захочете** мати кількох працівників у контейнері, наприклад через опцію командного рядка `--workers`. Ви захочете мати лише **один процес Uvicorn** на контейнер (але, ймовірно, кілька контейнерів). -Наявність іншого менеджера процесів всередині контейнера (як це було б із кількома працівниками) лише додасть зайвої складності, яку, найімовірніше, ви вже вирішуєте на рівні кластера. +Наявність іншого менеджера процесів всередині контейнера (як це було б із кількома працівниками) лише додасть **зайвої складності**, яку, найімовірніше, ви вже вирішуєте на рівні кластера. ### Контейнери з кількома процесами та особливі випадки { #containers-with-multiple-processes-and-special-cases } -Звісно, є особливі випадки, коли ви можете захотіти мати контейнер із кількома процесами-працівниками Uvicorn всередині. +Звісно, є **особливі випадки**, коли ви можете захотіти мати **контейнер** із кількома **процесами-працівниками Uvicorn** всередині. У таких випадках ви можете використати опцію командного рядка `--workers`, щоб задати кількість працівників, яких потрібно запустити: @@ -519,17 +519,17 @@ CMD ["fastapi", "run", "app/main.py", "--port", "80", "--workers", "4"] #### Простий застосунок { #a-simple-app } -Ви можете захотіти менеджер процесів у контейнері, якщо ваш застосунок достатньо простий, щоб запускати його на одному сервері, а не на кластері. +Ви можете захотіти менеджер процесів у контейнері, якщо ваш застосунок **достатньо простий**, щоб запускати його на **одному сервері**, а не на кластері. #### Docker Compose { #docker-compose } -Ви можете розгортати на одному сервері (не в кластері) за допомогою Docker Compose, тож у вас не буде простого способу керувати реплікацією контейнерів (у Docker Compose), зберігаючи спільну мережу та балансування навантаження. +Ви можете розгортати на **одному сервері** (не в кластері) за допомогою **Docker Compose**, тож у вас не буде простого способу керувати реплікацією контейнерів (у Docker Compose), зберігаючи спільну мережу та **балансування навантаження**. -Тоді ви можете захотіти мати один контейнер із менеджером процесів, що запускає кілька процесів-працівників всередині. +Тоді ви можете захотіти мати **один контейнер** із **менеджером процесів**, що запускає **кілька процесів-працівників** всередині. --- -Головна думка: це не правила, викарбувані в камені, яких потрібно сліпо дотримуватися. Ви можете використати ці ідеї, щоб оцінити власний кейс і вирішити, який підхід найкращий для вашої системи, розглядаючи, як керувати такими концепціями: +Головна думка: **жодне** з цього не є **правилами, викарбуваними в камені**, яких потрібно сліпо дотримуватися. Ви можете використати ці ідеї, щоб **оцінити власний кейс** і вирішити, який підхід найкращий для вашої системи, розглядаючи, як керувати такими концепціями: * Безпека - HTTPS * Автозапуск @@ -540,13 +540,13 @@ CMD ["fastapi", "run", "app/main.py", "--port", "80", "--workers", "4"] ## Пам’ять { #memory } -Якщо ви запускаєте один процес на контейнер, ви матимете більш-менш чітко визначений, стабільний і обмежений обсяг пам’яті, що споживається кожним із цих контейнерів (їх може бути більше одного, якщо вони репліковані). +Якщо ви запускаєте **один процес на контейнер**, ви матимете більш-менш чітко визначений, стабільний і обмежений обсяг пам’яті, що споживається кожним із цих контейнерів (їх може бути більше одного, якщо вони репліковані). -Потім ви можете встановити ті самі ліміти та вимоги до пам’яті у ваших конфігураціях для системи керування контейнерами (наприклад, у Kubernetes). Таким чином вона зможе реплікувати контейнери на доступних машинах, враховуючи обсяг пам’яті, потрібний їм, і обсяг доступної пам’яті на машинах у кластері. +Потім ви можете встановити ті самі ліміти та вимоги до пам’яті у ваших конфігураціях для системи керування контейнерами (наприклад, у **Kubernetes**). Таким чином вона зможе **реплікувати контейнери** на **доступних машинах**, враховуючи обсяг пам’яті, потрібний їм, і обсяг доступної пам’яті на машинах у кластері. -Якщо ваш застосунок простий, імовірно, це не буде проблемою, і вам може не знадобитися задавати жорсткі ліміти пам’яті. Але якщо ви використовуєте багато пам’яті (наприклад, із моделями машинного навчання), вам слід перевірити, скільки пам’яті ви споживаєте, і відкоригувати кількість контейнерів, що запускаються на кожній машині (і, можливо, додати більше машин у ваш кластер). +Якщо ваш застосунок **простий**, імовірно, це **не буде проблемою**, і вам може не знадобитися задавати жорсткі ліміти пам’яті. Але якщо ви **використовуєте багато пам’яті** (наприклад, із моделями **машинного навчання**), вам слід перевірити, скільки пам’яті ви споживаєте, і відкоригувати **кількість контейнерів**, що запускаються на **кожній машині** (і, можливо, додати більше машин у ваш кластер). -Якщо ви запускаєте кілька процесів на контейнер, вам потрібно переконатися, що кількість запущених процесів не споживає більше пам’яті, ніж доступно. +Якщо ви запускаєте **кілька процесів на контейнер**, вам потрібно переконатися, що кількість запущених процесів не **споживає більше пам’яті**, ніж доступно. ## Попередні кроки перед запуском і контейнери { #previous-steps-before-starting-and-containers } @@ -554,27 +554,27 @@ CMD ["fastapi", "run", "app/main.py", "--port", "80", "--workers", "4"] ### Кілька контейнерів { #multiple-containers } -Якщо у вас кілька контейнерів, імовірно кожен запускає один процес (наприклад, у кластері Kubernetes), тоді ви, ймовірно, захочете мати окремий контейнер, який виконає попередні кроки в одному контейнері, запустивши один процес, перед запуском реплікованих контейнерів-працівників. +Якщо у вас **кілька контейнерів**, імовірно кожен запускає **один процес** (наприклад, у кластері **Kubernetes**), тоді ви, ймовірно, захочете мати **окремий контейнер**, який виконає **попередні кроки** в одному контейнері, запустивши один процес, **перед** запуском реплікованих контейнерів-працівників. -/// info | Інформація +/// note | Примітка Якщо ви використовуєте Kubernetes, це, ймовірно, буде [Init Container](https://kubernetes.io/docs/concepts/workloads/pods/init-containers/). /// -Якщо у вашому випадку немає проблеми запускати ці попередні кроки кілька разів паралельно (наприклад, якщо ви не виконуєте міграції бази даних, а лише перевіряєте, чи база вже готова), тоді ви також можете просто помістити їх у кожен контейнер безпосередньо перед запуском головного процесу. +Якщо у вашому випадку немає проблеми запускати ці попередні кроки **кілька разів паралельно** (наприклад, якщо ви не виконуєте міграції бази даних, а лише перевіряєте, чи база вже готова), тоді ви також можете просто помістити їх у кожен контейнер безпосередньо перед запуском головного процесу. ### Один контейнер { #single-container } -Якщо у вас просте налаштування з одним контейнером, який потім запускає кілька процесів-працівників (або теж лише один процес), тоді ви можете виконати ці попередні кроки в тому ж контейнері безпосередньо перед запуском процесу із застосунком. +Якщо у вас просте налаштування з **одним контейнером**, який потім запускає кілька **процесів-працівників** (або теж лише один процес), тоді ви можете виконати ці попередні кроки в тому ж контейнері безпосередньо перед запуском процесу із застосунком. ### Базовий образ Docker { #base-docker-image } Колись існував офіційний образ Docker для FastAPI: [tiangolo/uvicorn-gunicorn-fastapi](https://github.com/tiangolo/uvicorn-gunicorn-fastapi-docker). Але зараз він застарілий. ⛔️ -Ймовірно, вам не слід використовувати цей базовий образ Docker (або будь-який інший подібний). +Ймовірно, вам **не** слід використовувати цей базовий образ Docker (або будь-який інший подібний). -Якщо ви використовуєте Kubernetes (або інші) і вже налаштовуєте реплікацію на рівні кластера з кількома контейнерами. У таких випадках краще зібрати образ з нуля, як описано вище: [Зібрати Docker-образ для FastAPI](#build-a-docker-image-for-fastapi). +Якщо ви використовуєте **Kubernetes** (або інші) і вже налаштовуєте **реплікацію** на рівні кластера з кількома **контейнерами**. У таких випадках краще **зібрати образ з нуля**, як описано вище: [Зібрати Docker-образ для FastAPI](#build-a-docker-image-for-fastapi). А якщо вам потрібно мати кілька працівників, ви можете просто використати опцію командного рядка `--workers`. @@ -592,8 +592,8 @@ CMD ["fastapi", "run", "app/main.py", "--port", "80", "--workers", "4"] Наприклад: -* З Docker Compose на одному сервері -* З кластером Kubernetes +* З **Docker Compose** на одному сервері +* З кластером **Kubernetes** * З кластером Docker Swarm Mode * З іншим інструментом, як-от Nomad * З хмарним сервісом, який бере ваш образ контейнера і розгортає його @@ -604,7 +604,7 @@ CMD ["fastapi", "run", "app/main.py", "--port", "80", "--workers", "4"] ## Підсумок { #recap } -Використовуючи системи контейнерів (наприклад, з Docker і Kubernetes), досить просто обробляти всі концепції розгортання: +Використовуючи системи контейнерів (наприклад, з **Docker** і **Kubernetes**), досить просто обробляти всі **концепції розгортання**: * HTTPS * Автозапуск @@ -613,6 +613,6 @@ CMD ["fastapi", "run", "app/main.py", "--port", "80", "--workers", "4"] * Пам’ять * Попередні кроки перед запуском -У більшості випадків ви, ймовірно, не захочете використовувати будь-який базовий образ, а натомість зібрати образ контейнера з нуля на основі офіційного образу Python для Docker. +У більшості випадків ви, ймовірно, не захочете використовувати будь-який базовий образ, а натомість **зібрати образ контейнера з нуля** на основі офіційного образу Python для Docker. -Дотримуючись порядку інструкцій у `Dockerfile` і використовуючи кеш Docker, ви можете мінімізувати час збірки, щоб максимізувати свою продуктивність (і уникнути нудьги). 😎 +Дотримуючись **порядку** інструкцій у `Dockerfile` і використовуючи **кеш Docker**, ви можете **мінімізувати час збірки**, щоб максимізувати свою продуктивність (і уникнути нудьги). 😎 diff --git a/docs/uk/docs/deployment/fastapicloud.md b/docs/uk/docs/deployment/fastapicloud.md index 63d9fa459..cc59caa30 100644 --- a/docs/uk/docs/deployment/fastapicloud.md +++ b/docs/uk/docs/deployment/fastapicloud.md @@ -1,26 +1,6 @@ # FastAPI Cloud { #fastapi-cloud } -Ви можете розгорнути свій застосунок FastAPI на [FastAPI Cloud](https://fastapicloud.com) **однією командою**, приєднуйтесь до списку очікування, якщо ще ні. 🚀 - -## Вхід { #login } - -Переконайтеся, що у вас вже є обліковий запис **FastAPI Cloud** (ми запросили вас зі списку очікування 😉). - -Потім увійдіть: - -
- -```console -$ fastapi login - -You are logged in to FastAPI Cloud 🚀 -``` - -
- -## Розгортання { #deploy } - -Тепер розгорніть свій застосунок **однією командою**: +Ви можете розгорнути свій застосунок FastAPI на [FastAPI Cloud](https://fastapicloud.com) лише **однією командою**. 🚀
@@ -36,6 +16,8 @@ Deploying to FastAPI Cloud...
+CLI автоматично визначить ваш застосунок FastAPI та розгорне його у хмарі. Якщо ви не увійшли, ваш браузер відкриється, щоб завершити процес автентифікації. + Ось і все! Тепер ви можете отримати доступ до свого застосунку за цим URL. ✨ ## Про FastAPI Cloud { #about-fastapi-cloud } diff --git a/docs/uk/docs/deployment/https.md b/docs/uk/docs/deployment/https.md index 439adf61e..fd5471470 100644 --- a/docs/uk/docs/deployment/https.md +++ b/docs/uk/docs/deployment/https.md @@ -14,8 +14,8 @@ Тепер, з **точки зору розробника**, ось кілька речей, які варто пам'ятати, розмірковуючи про HTTPS: -* Для HTTPS **сервер** має **мати «сертифікати»**, видані **третьою стороною**. - * Насправді ці сертифікати **«отримуються»** у третьої сторони, а не **«генеруються»**. +* Для HTTPS **сервер** має **мати «сертифікати»**, згенеровані **третьою стороною**. + * Насправді ці сертифікати **«отримуються»** у третьої сторони, а не **«згенеровані»**. * Сертифікати мають **строк дії**. * Їхній строк дії **спливає**. * І тоді їх потрібно **поновити**, **знову отримавши** у третьої сторони. @@ -190,15 +190,15 @@ TLS Termination Proxy використає узгоджене шифруванн Увесь цей процес поновлення, паралельно з обслуговуванням застосунку, - одна з головних причин, чому ви можете захотіти мати **окрему систему для обробки HTTPS** за допомогою TLS Termination Proxy замість того, щоб просто використовувати сертифікати TLS безпосередньо з сервером застосунку (наприклад, Uvicorn). -## Направлені заголовки проксі { #proxy-forwarded-headers } +## Направлені заголовки представника { #proxy-forwarded-headers } -Коли ви використовуєте проксі для обробки HTTPS, ваш **сервер застосунку** (наприклад, Uvicorn через FastAPI CLI) нічого не знає про процес HTTPS, він спілкується звичайним HTTP із **TLS Termination Proxy**. +Коли ви використовуєте представника для обробки HTTPS, ваш **сервер застосунку** (наприклад, Uvicorn через FastAPI CLI) нічого не знає про процес HTTPS, він спілкується звичайним HTTP із **TLS Termination Proxy**. -Цей **проксі** зазвичай динамічно встановлює деякі HTTP-заголовки перед передачею запиту **серверу застосунку**, щоб дати йому знати, що запит **направляється** проксі. +Цей **представник** зазвичай динамічно встановлює деякі HTTP-заголовки перед передачею запиту **серверу застосунку**, щоб дати йому знати, що запит **направляється** представником. /// note | Технічні деталі -Заголовки проксі: +Заголовки представника: * [X-Forwarded-For](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Forwarded-For) * [X-Forwarded-Proto](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Forwarded-Proto) @@ -206,11 +206,11 @@ TLS Termination Proxy використає узгоджене шифруванн /// -Втім, оскільки **сервер застосунку** не знає, що він стоїть за довіреним **проксі**, за замовчуванням він не довірятиме цим заголовкам. +Втім, оскільки **сервер застосунку** не знає, що він стоїть за довіреним **представником**, за замовчуванням він не довірятиме цим заголовкам. -Але ви можете налаштувати **сервер застосунку**, щоб довіряти направленим заголовкам, надісланим **проксі**. Якщо ви використовуєте FastAPI CLI, ви можете скористатися курсивною *опцією CLI* `--forwarded-allow-ips`, щоб повідомити, з яких IP-адрес слід довіряти цим направленим заголовкам. +Але ви можете налаштувати **сервер застосунку**, щоб довіряти *направленим* заголовкам, надісланим **представником**. Якщо ви використовуєте FastAPI CLI, ви можете скористатися *опцією CLI* `--forwarded-allow-ips`, щоб повідомити, з яких IP-адрес слід довіряти цим *направленим* заголовкам. -Наприклад, якщо **сервер застосунку** отримує комунікацію лише від довіреного **проксі**, ви можете встановити `--forwarded-allow-ips="*"`, щоб довіряти всім вхідним IP-адресам, оскільки він отримуватиме запити лише з тієї IP-адреси, яку використовує **проксі**. +Наприклад, якщо **сервер застосунку** отримує комунікацію лише від довіреного **представника**, ви можете встановити `--forwarded-allow-ips="*"`, щоб довіряти всім вхідним IP-адресам, оскільки він отримуватиме запити лише з тієї IP-адреси, яку використовує **представник**. Так застосунок зможе знати свою публічну URL-адресу, чи використовує він HTTPS, домен тощо. @@ -218,7 +218,7 @@ TLS Termination Proxy використає узгоджене шифруванн /// tip | Порада -Ви можете дізнатися більше про це в документації [За проксі - Увімкнути направлені заголовки проксі](../advanced/behind-a-proxy.md#enable-proxy-forwarded-headers) +Ви можете дізнатися більше про це в документації [За представником - Увімкнути направлені заголовки представника](../advanced/behind-a-proxy.md#enable-proxy-forwarded-headers) /// diff --git a/docs/uk/docs/deployment/manually.md b/docs/uk/docs/deployment/manually.md index 7ea2c78e3..6692efd56 100644 --- a/docs/uk/docs/deployment/manually.md +++ b/docs/uk/docs/deployment/manually.md @@ -40,7 +40,7 @@ $ fastapi run @@ -143,7 +142,7 @@ Uvicorn та інші сервери підтримують опцію `--reload ## Концепції розгортання { #deployment-concepts } -Ці приклади запускають серверну програму (наприклад, Uvicorn), піднімаючи один процес, що слухає всі IP (`0.0.0.0`) на визначеному порту (наприклад, `80`). +Ці приклади запускають серверну програму (наприклад, Uvicorn), піднімаючи **один процес**, що слухає всі IP (`0.0.0.0`) на визначеному порту (наприклад, `80`). Це базова ідея. Але, ймовірно, вам знадобиться подбати ще про таке: diff --git a/docs/uk/docs/deployment/server-workers.md b/docs/uk/docs/deployment/server-workers.md index f165bb707..3bbf4454a 100644 --- a/docs/uk/docs/deployment/server-workers.md +++ b/docs/uk/docs/deployment/server-workers.md @@ -17,7 +17,7 @@ Тут я покажу, як використовувати Uvicorn із процесами-працівниками за допомогою команди `fastapi` або безпосередньо команди `uvicorn`. -/// info | Інформація +/// note | Примітка Якщо ви використовуєте контейнери, наприклад з Docker або Kubernetes, я розповім про це більше в наступному розділі: [FastAPI у контейнерах - Docker](docker.md). diff --git a/docs/uk/docs/editor-support.md b/docs/uk/docs/editor-support.md index f0edf6297..cc4c2ccb7 100644 --- a/docs/uk/docs/editor-support.md +++ b/docs/uk/docs/editor-support.md @@ -1,5 +1,6 @@ # Підтримка редакторів { #editor-support } + Офіційне [FastAPI Extension](https://marketplace.visualstudio.com/items?itemName=FastAPILabs.fastapi-vscode) покращує ваш робочий процес розробки FastAPI завдяки виявленню й навігації по *операціях шляху*, а також розгортанню у FastAPI Cloud і потоковому передаванню журналів у реальному часі. Докладніше про розширення дивіться у README в [репозиторії GitHub](https://github.com/fastapi/fastapi-vscode). diff --git a/docs/uk/docs/environment-variables.md b/docs/uk/docs/environment-variables.md index 7b5223bc2..95c142c7c 100644 --- a/docs/uk/docs/environment-variables.md +++ b/docs/uk/docs/environment-variables.md @@ -6,13 +6,13 @@ /// -Змінна оточення (також відома як «env var») - це змінна, що існує поза кодом Python, в операційній системі, і може бути прочитана вашим кодом Python (а також іншими програмами). +Змінна оточення (також відома як «**env var**») - це змінна, що існує **поза** кодом Python, в **операційній системі**, і може бути прочитана вашим кодом Python (а також іншими програмами). -Змінні оточення корисні для роботи з налаштуваннями застосунку, як частина встановлення Python тощо. +Змінні оточення корисні для роботи з **налаштуваннями** застосунку, як частина **встановлення** Python тощо. ## Створення і використання змінних оточення { #create-and-use-env-vars } -Ви можете створювати і використовувати змінні оточення в оболонці (терміналі) без участі Python: +Ви можете **створювати** і використовувати змінні оточення в **оболонці (терміналі)** без участі Python: //// tab | Linux, macOS, Windows Bash @@ -52,7 +52,7 @@ Hello Wade Wilson ## Читання змінних оточення в Python { #read-env-vars-in-python } -Ви також можете створити змінні оточення поза Python, у терміналі (або будь-яким іншим способом), а потім зчитати їх у Python. +Ви також можете створити змінні оточення **поза** Python, у терміналі (або будь-яким іншим способом), а потім **зчитати їх у Python**. Наприклад, у вас може бути файл `main.py` з: @@ -127,9 +127,9 @@ Hello Wade Wilson from Python //// -Оскільки змінні оточення можна встановлювати поза кодом, але читати в коді, і їх не потрібно зберігати (фіксувати у `git`) разом з іншими файлами, їх часто використовують для конфігурацій або налаштувань. +Оскільки змінні оточення можна встановлювати поза кодом, але читати в коді, і їх не потрібно зберігати (фіксувати у `git`) разом з іншими файлами, їх часто використовують для конфігурацій або **налаштувань**. -Ви також можете створити змінну оточення лише для конкретного запуску програми, вона буде доступна тільки цій програмі і лише на час її виконання. +Ви також можете створити змінну оточення лише для **конкретного запуску програми**, вона буде доступна тільки цій програмі і лише на час її виконання. Щоб зробити це, створіть її безпосередньо перед командою запуску програми, в тому самому рядку: @@ -159,15 +159,15 @@ Hello World from Python ## Типи і перевірка { #types-and-validation } -Ці змінні оточення можуть містити лише текстові строки, оскільки вони зовнішні щодо Python і мають бути сумісними з іншими програмами та рештою системи (і навіть з різними операційними системами, як-от Linux, Windows, macOS). +Ці змінні оточення можуть містити лише **текстові строки**, оскільки вони зовнішні щодо Python і мають бути сумісними з іншими програмами та рештою системи (і навіть з різними операційними системами, як-от Linux, Windows, macOS). -Це означає, що будь-яке значення, прочитане в Python зі змінної оточення, буде `str`, а будь-яке перетворення до іншого типу або будь-яка перевірка має виконуватися в коді. +Це означає, що **будь-яке значення**, прочитане в Python зі змінної оточення, **буде `str`**, а будь-яке перетворення до іншого типу або будь-яка перевірка має виконуватися в коді. -Ви дізнаєтеся більше про використання змінних оточення для роботи з налаштуваннями застосунку в розділі [Просунутий посібник користувача - Налаштування і змінні оточення](./advanced/settings.md). +Ви дізнаєтеся більше про використання змінних оточення для роботи з **налаштуваннями застосунку** в розділі [Просунутий посібник користувача - Налаштування і змінні оточення](./advanced/settings.md). ## Змінна оточення `PATH` { #path-environment-variable } -Є спеціальна змінна оточення `PATH`, яку використовують операційні системи (Linux, macOS, Windows) для пошуку програм для запуску. +Є **спеціальна** змінна оточення **`PATH`**, яку використовують операційні системи (Linux, macOS, Windows) для пошуку програм для запуску. Значення змінної `PATH` - це довга строка, що складається з каталогів, розділених двокрапкою `:` у Linux і macOS та крапкою з комою `;` у Windows. @@ -203,11 +203,11 @@ C:\Program Files\Python312\Scripts;C:\Program Files\Python312;C:\Windows\System3 //// -Коли ви вводите команду в терміналі, операційна система шукає програму в кожному з тих каталогів, перелічених у змінній оточення `PATH`. +Коли ви вводите **команду** в терміналі, операційна система **шукає** програму в **кожному з тих каталогів**, перелічених у змінній оточення `PATH`. -Наприклад, коли ви вводите `python` у терміналі, операційна система шукає програму з назвою `python` у першому каталозі цього списку. +Наприклад, коли ви вводите `python` у терміналі, операційна система шукає програму з назвою `python` у **першому каталозі** цього списку. -Якщо знайде, вона використає її. Інакше продовжить пошук в інших каталогах. +Якщо знайде, вона **використає її**. Інакше продовжить пошук в **інших каталогах**. ### Встановлення Python і оновлення `PATH` { #installing-python-and-updating-the-path } @@ -255,7 +255,7 @@ $ python //// tab | Linux, macOS -Система знайде програму `python` у `/opt/custompython/bin` і запустить її. +Система **знайде** програму `python` у `/opt/custompython/bin` і запустить її. Це приблизно еквівалентно введенню: @@ -271,7 +271,7 @@ $ /opt/custompython/bin/python //// tab | Windows -Система знайде програму `python` у `C:\opt\custompython\bin\python` і запустить її. +Система **знайде** програму `python` у `C:\opt\custompython\bin\python` і запустить її. Це приблизно еквівалентно введенню: @@ -289,7 +289,7 @@ $ C:\opt\custompython\bin\python ## Висновок { #conclusion } -Тепер ви маєте базове розуміння того, що таке змінні оточення і як їх використовувати в Python. +Тепер ви маєте базове розуміння того, що таке **змінні оточення** і як їх використовувати в Python. Також можна прочитати більше у [Вікіпедії про змінну оточення](https://en.wikipedia.org/wiki/Environment_variable). diff --git a/docs/uk/docs/features.md b/docs/uk/docs/features.md index 2ee24181f..3f8b0049b 100644 --- a/docs/uk/docs/features.md +++ b/docs/uk/docs/features.md @@ -6,8 +6,8 @@ ### На основі відкритих стандартів { #based-on-open-standards } -* [**OpenAPI**](https://github.com/OAI/OpenAPI-Specification) для створення API, включаючи оголошення шляхів операцій, параметрів, тіл запитів, безпеки тощо. -* Автоматична документація моделей даних за допомогою [**JSON Schema**](https://json-schema.org/) (оскільки OpenAPI базується саме на JSON Schema). +* [**OpenAPI**](https://github.com/OAI/OpenAPI-Specification) для створення API, включаючи оголошення шляхових операцій, параметрів, тіл запитів, безпеки тощо. +* Автоматична документація моделей даних за допомогою [**Схеми JSON**](https://json-schema.org/) (оскільки OpenAPI базується саме на Схемі JSON). * Розроблено на основі цих стандартів після ретельного аналізу, а не як додатковий рівень поверх основної архітектури. * Це також дає змогу використовувати автоматичну **генерацію клієнтського коду** багатьма мовами. @@ -15,9 +15,9 @@ Інтерактивна документація API та вебінтерфейси для його дослідження. Оскільки фреймворк базується на OpenAPI, є кілька варіантів, 2 з яких включені за замовчуванням. -* [**Swagger UI**](https://github.com/swagger-api/swagger-ui) — з інтерактивним дослідженням, викликом і тестуванням вашого API прямо з браузера. +* [**Swagger UI**](https://github.com/swagger-api/swagger-ui) - з інтерактивним дослідженням, викликом і тестуванням вашого API прямо з браузера. -![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-03-swagger-02.png) +![взаємодія Swagger UI](https://fastapi.tiangolo.com/img/index/index-03-swagger-02.png) * Альтернативна документація API за допомогою [**ReDoc**](https://github.com/Rebilly/ReDoc). @@ -27,7 +27,7 @@ Усе базується на стандартних оголошеннях **типів Python** (завдяки Pydantic). Жодного нового синтаксису для вивчення. Лише стандартний сучасний Python. -Якщо вам потрібно 2-хвилинне нагадування про те, як використовувати типи Python (навіть якщо ви не використовуєте FastAPI), перегляньте короткий підручник: [Типи Python](python-types.md). +Якщо вам потрібно 2-хвилинне нагадування про те, як використовувати типи Python (навіть якщо ви не використовуєте FastAPI), перегляньте короткий навчальний посібник: [Типи Python](python-types.md). Ви пишете стандартний Python з типами: @@ -85,13 +85,13 @@ my_second_user: User = User(**second_user_data) * у [Visual Studio Code](https://code.visualstudio.com/): -![editor support](https://fastapi.tiangolo.com/img/vscode-completion.png) +![підтримка редактора](https://fastapi.tiangolo.com/img/vscode-completion.png) * у [PyCharm](https://www.jetbrains.com/pycharm/): -![editor support](https://fastapi.tiangolo.com/img/pycharm-completion.png) +![підтримка редактора](https://fastapi.tiangolo.com/img/pycharm-completion.png) -Ви отримаєте автодоповнення в коді, який раніше могли вважати навіть неможливим. Наприклад, для ключа `price` всередині JSON body (який міг бути вкладеним), що надходить із запиту. +Ви отримаєте автодоповнення в коді, який раніше могли вважати навіть неможливим. Наприклад, для ключа `price` всередині тіла JSON (яке могло бути вкладеним), що надходить із запиту. Більше не доведеться вводити неправильні назви ключів, постійно повертатися до документації або прокручувати вгору-вниз, щоб знайти, чи ви зрештою використали `username` чи `user_name`. @@ -106,7 +106,7 @@ FastAPI має розумні **налаштування за замовчува * Підтримка валідації для більшості (або всіх?) **типів даних Python**, зокрема: * JSON-об'єктів (`dict`). * JSON-масивів (`list`) із визначенням типів елементів. - * Полів-рядків (`str`) із визначенням мінімальної та максимальної довжини. + * Полів-строк (`str`) із визначенням мінімальної та максимальної довжини. * Чисел (`int`, `float`) з мінімальними та максимальними значеннями тощо. * Валідація для більш екзотичних типів, як-от: @@ -124,30 +124,30 @@ FastAPI має розумні **налаштування за замовчува Підтримуються всі схеми безпеки, визначені в OpenAPI, включно з: * HTTP Basic. -* **OAuth2** (також із підтримкою **JWT tokens**). Перегляньте підручник: [OAuth2 із JWT](tutorial/security/oauth2-jwt.md). +* **OAuth2** (також із підтримкою **JWT tokens**). Перегляньте навчальний посібник: [OAuth2 із JWT](tutorial/security/oauth2-jwt.md). * Ключі API в: * Заголовках. * Параметрах запиту. - * Cookies тощо. + * Кукі тощо. -А також усі можливості безпеки від Starlette (зокрема **session cookies**). +А також усі можливості безпеки від Starlette (зокрема **сесійні кукі**). Усе це зроблено як багаторазові інструменти та компоненти, які легко інтегруються з вашими системами, сховищами даних, реляційними та NoSQL базами даних тощо. ### Впровадження залежностей { #dependency-injection } -FastAPI містить надзвичайно просту у використанні, але надзвичайно потужну систему Впровадження залежностей. +FastAPI містить надзвичайно просту у використанні, але надзвичайно потужну систему Впровадження залежностей. * Навіть залежності можуть мати власні залежності, утворюючи ієрархію або **«граф» залежностей**. * Усе **автоматично обробляється** фреймворком. * Усі залежності можуть вимагати дані із запитів і **розширювати обмеження операції шляху** та автоматичну документацію. -* **Автоматична валідація** навіть для *операції шляху*, визначених у залежностях. +* **Автоматична валідація** навіть для параметрів *операції шляху*, визначених у залежностях. * Підтримка складних систем автентифікації користувачів, **підключень до баз даних** тощо. * **Жодних компромісів** із базами даних, фронтендами тощо. Але проста інтеграція з усіма ними. ### Необмежені «плагіни» { #unlimited-plug-ins } -Інакше кажучи, вони не потрібні — імпортуйте та використовуйте код, який вам потрібен. +Інакше кажучи, вони не потрібні - імпортуйте та використовуйте код, який вам потрібен. Будь-яка інтеграція спроєктована так, щоб її було дуже просто використовувати (із залежностями), тож ви можете створити «плагін» для свого застосунку у 2 рядках коду, використовуючи ту саму структуру та синтаксис, що й для ваших *операцій шляху*. @@ -163,15 +163,15 @@ FastAPI містить надзвичайно просту у використа `FastAPI` фактично є підкласом `Starlette`. Тому, якщо ви вже знайомі зі Starlette або використовуєте його, більшість функціональності працюватиме так само. -З **FastAPI** ви отримуєте всі можливості **Starlette** (адже FastAPI — це просто Starlette на стероїдах): +З **FastAPI** ви отримуєте всі можливості **Starlette** (адже FastAPI - це просто Starlette на стероїдах): * Разюча продуктивність. Це [один із найшвидших доступних Python-фреймворків, на рівні з **NodeJS** і **Go**](https://github.com/encode/starlette#performance). * Підтримка **WebSocket**. * Фонові задачі у процесі. -* Події запуску та завершення роботи. +* Події запуску та вимкнення. * Клієнт для тестування, побудований на HTTPX. * Підтримка **CORS**, **GZip**, статичних файлів, потокових відповідей. -* Підтримка **сесій** і **cookie**. +* Підтримка **сесій і кукі**. * 100% покриття тестами. * 100% анотована типами кодова база. @@ -183,7 +183,7 @@ FastAPI містить надзвичайно просту у використа Це також означає, що в багатьох випадках ви можете передати той самий об'єкт, який отримуєте із запиту, **безпосередньо в базу даних**, оскільки все автоматично перевіряється. -Те саме застосовується й у зворотному напрямку — у багатьох випадках ви можете просто передати об'єкт, який отримуєте з бази даних, **безпосередньо клієнту**. +Те саме застосовується й у зворотному напрямку - у багатьох випадках ви можете просто передати об'єкт, який отримуєте з бази даних, **безпосередньо клієнту**. З **FastAPI** ви отримуєте всі можливості **Pydantic** (адже FastAPI базується на Pydantic для обробки всіх даних): @@ -193,8 +193,8 @@ FastAPI містить надзвичайно просту у використа * Легко працює з вашим **IDE/linter/мозком**: * Оскільки структури даних pydantic є просто екземплярами класів, які ви визначаєте; автодоповнення, лінтинг, mypy і ваша інтуїція повинні добре працювати з вашими перевіреними даними. * Валідує **складні структури**: - * Використання ієрархічних моделей Pydantic, Python `typing`’s `List` і `Dict` тощо. - * Валідатори дають змогу складні схеми даних чітко й просто визначати, перевіряти й документувати як JSON Schema. + * Використання ієрархічних моделей Pydantic, `List` і `Dict` з Python `typing` тощо. + * Валідатори дають змогу складні схеми даних чітко й просто визначати, перевіряти й документувати як Схему JSON. * Ви можете мати глибоко **вкладені JSON** об'єкти, і всі вони будуть валідовані та анотовані. * **Розширюваність**: * Pydantic дозволяє визначати користувацькі типи даних або ви можете розширити валідацію методами в моделі, позначеними декоратором validator. diff --git a/docs/uk/docs/help-fastapi.md b/docs/uk/docs/help-fastapi.md index e093bdece..fe1b35c47 100644 --- a/docs/uk/docs/help-fastapi.md +++ b/docs/uk/docs/help-fastapi.md @@ -6,7 +6,7 @@ ## Підпишіться на розсилку { #subscribe-to-the-newsletter } -Ви можете підписатися на (нечасту) розсилку [**FastAPI and friends**](newsletter.md), щоб бути в курсі: +Ви можете підписатися на (нечасту) [розсилку **FastAPI and friends**](newsletter.md), щоб бути в курсі: * Новин про FastAPI та друзів 🚀 * Посібників 📝 diff --git a/docs/uk/docs/how-to/configure-swagger-ui.md b/docs/uk/docs/how-to/configure-swagger-ui.md index 5fe47d12e..2322c67bc 100644 --- a/docs/uk/docs/how-to/configure-swagger-ui.md +++ b/docs/uk/docs/how-to/configure-swagger-ui.md @@ -67,4 +67,4 @@ presets: [ Це об’єкти **JavaScript**, а не строки, тому ви не можете передати їх безпосередньо з коду Python. -Якщо вам потрібно використати такі налаштування лише для JavaScript, скористайтеся одним із методів вище. Повністю перепишіть операцію шляху Swagger UI та вручну напишіть потрібний JavaScript. +Якщо вам потрібно використати такі налаштування лише для JavaScript, скористайтеся одним із методів вище. Повністю перепишіть *операцію шляху* Swagger UI та вручну напишіть потрібний JavaScript. diff --git a/docs/uk/docs/how-to/custom-request-and-route.md b/docs/uk/docs/how-to/custom-request-and-route.md index 6a46b5723..f45fc1eea 100644 --- a/docs/uk/docs/how-to/custom-request-and-route.md +++ b/docs/uk/docs/how-to/custom-request-and-route.md @@ -18,9 +18,9 @@ Деякі варіанти використання: -- Перетворення не-JSON тіл запитів на JSON (наприклад, [`msgpack`](https://msgpack.org/index.html)). -- Розпакування тіл запитів, стиснених gzip. -- Автоматичне логування всіх тіл запитів. +* Перетворення не-JSON тіл запитів на JSON (наприклад, [`msgpack`](https://msgpack.org/index.html)). +* Розпакування тіл запитів, стиснених gzip. +* Автоматичне логування всіх тіл запитів. ## Обробка користувацьких кодувань тіла запиту { #handling-custom-request-body-encodings } @@ -76,7 +76,7 @@ Після цього вся логіка обробки залишається тією самою. -А завдяки змінам у `GzipRequest.body` тіло запиту за потреби буде автоматично розпаковане під час завантаження **FastAPI**. +Але завдяки змінам у `GzipRequest.body` тіло запиту за потреби буде автоматично розпаковане, коли **FastAPI** завантажуватиме його. ## Доступ до тіла запиту в обробнику виключень { #accessing-the-request-body-in-an-exception-handler } diff --git a/docs/uk/docs/how-to/extending-openapi.md b/docs/uk/docs/how-to/extending-openapi.md index fcd0982a9..4267d37b9 100644 --- a/docs/uk/docs/how-to/extending-openapi.md +++ b/docs/uk/docs/how-to/extending-openapi.md @@ -25,9 +25,17 @@ - `openapi_version`: Версія специфікації OpenAPI, що використовується. Типово остання: `3.1.0`. - `summary`: Короткий підсумок API. - `description`: Опис вашого API; може містити markdown і буде показаний у документації. -- `routes`: Список маршрутів, це кожна з зареєстрованих *операцій шляху*. Їх беруть з `app.routes`. +- `routes`: Маршрути із застосунку, взяті з `app.routes`. FastAPI використовує їх для збирання зареєстрованих *операцій шляху*, включно з тими, що з підключених роутерів. -/// info | Інформація +/// tip | Технічні деталі + +`app.routes` - це нижчорівневе дерево маршрутів. Воно може містити кандидати маршрутів, які FastAPI внутрішньо використовує для підключених роутерів, а не лише кінцеві об'єкти `APIRoute`. + +Ви все одно можете передати `app.routes` до `get_openapi()`. FastAPI обійде це дерево маршрутів, щоб зібрати фактичні операції шляху. + +/// + +/// note | Примітка Параметр `summary` доступний в OpenAPI 3.1.0 і вище, підтримується FastAPI 0.99.0 і вище. diff --git a/docs/uk/docs/how-to/graphql.md b/docs/uk/docs/how-to/graphql.md index c070c7e0c..91fa3619d 100644 --- a/docs/uk/docs/how-to/graphql.md +++ b/docs/uk/docs/how-to/graphql.md @@ -1,22 +1,22 @@ # GraphQL { #graphql } -Оскільки FastAPI базується на стандарті ASGI, дуже просто інтегрувати будь-яку бібліотеку GraphQL, сумісну з ASGI. +Оскільки **FastAPI** базується на стандарті **ASGI**, дуже просто інтегрувати будь-яку бібліотеку **GraphQL**, сумісну з ASGI. Ви можете поєднувати звичайні *операції шляху* FastAPI з GraphQL в одному застосунку. /// tip | Порада -GraphQL розв’язує деякі дуже специфічні сценарії використання. +**GraphQL** розв’язує деякі дуже специфічні сценарії використання. -Порівняно зі звичайними веб-API він має переваги та недоліки. +Порівняно зі звичайними **веб-API** він має **переваги** та **недоліки**. -Переконайтеся, що переваги для вашого випадку використання переважають недоліки. 🤓 +Переконайтеся, що **переваги** для вашого випадку використання переважають **недоліки**. 🤓 /// ## Бібліотеки GraphQL { #graphql-libraries } -Ось деякі бібліотеки GraphQL з підтримкою ASGI. Ви можете використовувати їх із FastAPI: +Ось деякі бібліотеки **GraphQL** з підтримкою **ASGI**. Ви можете використовувати їх із **FastAPI**: * [Strawberry](https://strawberry.rocks/) 🍓 * З [документацією для FastAPI](https://strawberry.rocks/docs/integrations/fastapi) @@ -29,23 +29,23 @@ GraphQL розв’язує деякі дуже специфічні сцена ## GraphQL зі Strawberry { #graphql-with-strawberry } -Якщо вам потрібен або ви хочете використовувати GraphQL, [Strawberry](https://strawberry.rocks/) - рекомендована бібліотека, адже її дизайн найближчий до дизайну FastAPI; усе базується на анотаціях типів. +Якщо вам потрібен або ви хочете використовувати **GraphQL**, [**Strawberry**](https://strawberry.rocks/) - **рекомендована** бібліотека, адже її дизайн найближчий до дизайну **FastAPI**; усе базується на **анотаціях типів**. -Залежно від вашого сценарію використання ви можете надати перевагу іншій бібліотеці, але якби ви запитали мене, я, ймовірно, порадив би спробувати Strawberry. +Залежно від вашого сценарію використання ви можете надати перевагу іншій бібліотеці, але якби ви запитали мене, я, ймовірно, порадив би спробувати **Strawberry**. -Ось невеликий приклад того, як інтегрувати Strawberry з FastAPI: +Ось невеликий попередній перегляд того, як ви могли б інтегрувати Strawberry з FastAPI: {* ../../docs_src/graphql_/tutorial001_py310.py hl[3,22,25] *} Більше про Strawberry ви можете дізнатися в [документації Strawberry](https://strawberry.rocks/). -І також [документацію про Strawberry з FastAPI](https://strawberry.rocks/docs/integrations/fastapi). +І також документацію про [Strawberry з FastAPI](https://strawberry.rocks/docs/integrations/fastapi). ## Застарілий `GraphQLApp` зі Starlette { #older-graphqlapp-from-starlette } Попередні версії Starlette містили клас `GraphQLApp` для інтеграції з [Graphene](https://graphene-python.org/). -Його вилучено з Starlette як застарілий, але якщо у вас є код, що його використовував, ви можете легко мігрувати на [starlette-graphene3](https://github.com/ciscorn/starlette-graphene3), який покриває той самий сценарій використання та має майже ідентичний інтерфейс. +Його було оголошено застарілим у Starlette, але якщо у вас є код, що його використовував, ви можете легко **мігрувати** на [starlette-graphene3](https://github.com/ciscorn/starlette-graphene3), який покриває той самий сценарій використання та має **майже ідентичний інтерфейс**. /// tip | Порада @@ -55,6 +55,6 @@ GraphQL розв’язує деякі дуже специфічні сцена ## Дізнайтеся більше { #learn-more } -Ви можете дізнатися більше про GraphQL в [офіційній документації GraphQL](https://graphql.org/). +Ви можете дізнатися більше про **GraphQL** в [офіційній документації GraphQL](https://graphql.org/). -Також ви можете почитати більше про кожну з цих бібліотек за наведеними посиланнями. +Також ви можете почитати більше про кожну з цих бібліотек, описаних вище, за наведеними посиланнями. diff --git a/docs/uk/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md b/docs/uk/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md index c5519b98d..7f71df245 100644 --- a/docs/uk/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md +++ b/docs/uk/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md @@ -8,9 +8,11 @@ FastAPI версії 0.119.0 запровадив часткову підтри FastAPI 0.126.0 припинив підтримку Pydantic v1, водночас ще певний час підтримував `pydantic.v1`. +FastAPI 0.128.0 також припинив підтримку `pydantic.v1`, тому найновіші версії FastAPI вимагають Pydantic v2. + /// warning | Попередження -Команда Pydantic припинила підтримку Pydantic v1 для останніх версій Python, починаючи з Python 3.14. +Команда Pydantic припинила підтримку Pydantic v1 для останніх версій Python, починаючи з **Python 3.14**. Це стосується і `pydantic.v1`, який більше не підтримується в Python 3.14 і новіших. @@ -18,7 +20,7 @@ FastAPI 0.126.0 припинив підтримку Pydantic v1, водноча /// -Якщо у вас стара програма FastAPI з Pydantic v1, нижче я покажу, як мігрувати на Pydantic v2, а також можливості FastAPI 0.119.0, які допоможуть з поступовою міграцією. +Якщо у вас стара програма FastAPI з Pydantic v1, нижче я покажу, як мігрувати на Pydantic v2, а також **можливості FastAPI 0.119.0**, які допоможуть з поступовою міграцією. ## Офіційний посібник { #official-guide } @@ -54,6 +56,16 @@ Pydantic v2 містить усе з Pydantic v1 як підмодуль `pydant ### Підтримка FastAPI для Pydantic v1 у v2 { #fastapi-support-for-pydantic-v1-in-v2 } +/// warning | Попередження + +Цю підтримку FastAPI для моделей `pydantic.v1` було додано у **FastAPI 0.119.0** і видалено у **FastAPI 0.128.0**. Вона була задумана як тимчасова допомога для міграції на Pydantic v2. + +У поточних версіях FastAPI використання моделі `pydantic.v1` у вашій програмі спричинить помилку. + +Решта цього розділу описує тимчасову підтримку, доступну лише в тих старіших версіях. + +/// + Починаючи з FastAPI 0.119.0, також є часткова підтримка Pydantic v1 всередині Pydantic v2, щоб спростити перехід на v2. Тож ви можете оновити Pydantic до останньої версії 2 і змінити імпорти на використання підмодуля `pydantic.v1`, і в багатьох випадках усе просто запрацює. @@ -122,6 +134,12 @@ graph TB ### Покрокова міграція { #migrate-in-steps } +/// warning | Попередження + +Поступова міграція з використанням моделей Pydantic v1 і v2 в одній програмі, описана нижче, працює лише у **FastAPI 0.119.0 до 0.127.x**. Її було видалено у **FastAPI 0.128.0**, найновіші версії вимагають моделей **Pydantic v2**. + +/// + /// tip | Порада Спершу спробуйте `bump-pydantic`: якщо ваші тести проходять і все працює - ви впоралися однією командою. ✨ diff --git a/docs/uk/docs/how-to/separate-openapi-schemas.md b/docs/uk/docs/how-to/separate-openapi-schemas.md index 7e6fcbf5f..3e9baead6 100644 --- a/docs/uk/docs/how-to/separate-openapi-schemas.md +++ b/docs/uk/docs/how-to/separate-openapi-schemas.md @@ -1,8 +1,8 @@ # Окремі схеми OpenAPI для введення та виведення, чи ні { #separate-openapi-schemas-for-input-and-output-or-not } -Відколи вийшов **Pydantic v2**, згенерований OpenAPI став трохи точнішим і більш коректним, ніж раніше. 😎 +Відколи вийшов **Pydantic v2**, згенерований OpenAPI став трохи точнішим і більш **коректним**, ніж раніше. 😎 -Насправді подекуди буде навіть **дві схеми JSON** в OpenAPI для тієї самої моделі Pydantic: для введення та для виведення - залежно від наявності значень за замовчуванням. +Насправді подекуди буде навіть **дві Схеми JSON** в OpenAPI для тієї самої моделі Pydantic: для введення та для виведення - залежно від наявності **значень за замовчуванням**. Розгляньмо, як це працює, і як це змінити за потреби. @@ -18,7 +18,7 @@ {* ../../docs_src/separate_openapi_schemas/tutorial001_py310.py ln[1:15] hl[14] *} -…тоді поле `description` не буде обов'язковим, адже воно має значення за замовчуванням `None`. +…тоді поле `description` **не буде обов'язковим**. Адже воно має значення за замовчуванням `None`. ### Модель для введення в документації { #input-model-in-docs } @@ -34,7 +34,7 @@ {* ../../docs_src/separate_openapi_schemas/tutorial001_py310.py hl[19] *} -…тоді, оскільки `description` має значення за замовчуванням, якщо ви нічого не повернете для цього поля, воно все одно матиме це **значення за замовчуванням**. +…тоді, оскільки `description` має значення за замовчуванням, якщо ви **нічого не повернете** для цього поля, воно все одно матиме це **значення за замовчуванням**. ### Модель для даних відповіді при виведенні { #model-for-output-response-data } @@ -51,12 +51,13 @@ У OpenAPI це описується тим, що поле позначається як **обов'язкове**, адже воно завжди присутнє. Тому Схема JSON для моделі може відрізнятися залежно від того, чи використовується вона для **введення або виведення**: -- для **введення** `description` не буде обов'язковим -- для **виведення** воно буде **обов'язковим** (і можливо `None`, або в термінах JSON - `null`) + +* для **введення** `description` **не буде обов'язковим** +* для **виведення** воно буде **обов'язковим** (і можливо `None`, або в термінах JSON - `null`) ### Модель для виведення в документації { #model-for-output-in-docs } -У документації ви також можете перевірити модель для виведення: **і** `name`, і `description` позначені як **обов'язкові** червоною зірочкою: +У документації ви також можете перевірити модель для виведення: **і** `name`, і `description` позначені як **обов'язкові** **червоною зірочкою**:
@@ -84,7 +85,7 @@ У такому разі ви можете вимкнути цю можливість у **FastAPI** параметром `separate_input_output_schemas=False`. -/// info | Інформація +/// note | Примітка Підтримку `separate_input_output_schemas` додано у FastAPI `0.102.0`. 🤓 diff --git a/docs/uk/docs/index.md b/docs/uk/docs/index.md index 2b770ff39..fe7d111d7 100644 --- a/docs/uk/docs/index.md +++ b/docs/uk/docs/index.md @@ -49,7 +49,7 @@ FastAPI - це сучасний, швидкий (високопродуктив * **Простий**: спроєктований так, щоб бути простим у використанні та вивченні. Менше часу на читання документації. * **Короткий**: мінімізує дублювання коду. Кілька можливостей з кожного оголошення параметра. Менше помилок. * **Надійний**: ви отримуєте код, готовий до продакшну. З автоматичною інтерактивною документацією. -* **Заснований на стандартах**: базується на (і повністю сумісний з) відкритими стандартами для API: [OpenAPI](https://github.com/OAI/OpenAPI-Specification) (раніше відомий як Swagger) та [JSON Schema](https://json-schema.org/). +* **Заснований на стандартах**: базується на (і повністю сумісний з) відкритими стандартами для API: [OpenAPI](https://github.com/OAI/OpenAPI-Specification) (раніше відомий як Swagger) та [Схема JSON](https://json-schema.org/). * оцінка на основі тестів, проведених внутрішньою командою розробників, що створює продакшн-застосунки. @@ -105,47 +105,47 @@ FastAPI - це сучасний, швидкий (високопродуктив
-
«Я дуже часто використовую FastAPI останнім часом. Я насправді планую використовувати його для всіх ML-сервісів моєї команди в Microsoft. Деякі з них інтегруються до основного продукту Windows і деякі з продуктів Office».
-
+
«Я дуже часто використовую FastAPI останнім часом. Я насправді планую використовувати його для всіх ML-сервісів моєї команди в Microsoft. Деякі з них інтегруються до основного продукту Windows і деяких продуктів Office».
+
- Kabir Khan, Microsoft (джерело)
-"_[...] I'm using **FastAPI** a ton these days. [...] I'm actually planning to use it for all of my team's **ML services at Microsoft**. Some of them are getting integrated into the core **Windows** product and some **Office** products._" +"_[...] Я дуже часто використовую **FastAPI** останнім часом. [...] Я насправді планую використовувати його для всіх **ML-сервісів моєї команди в Microsoft**. Деякі з них інтегруються до основного продукту **Windows** і деяких продуктів **Office**._" -
Kabir Khan - Microsoft (ref)
+
Kabir Khan - Microsoft (джерело)
--- -"_We adopted the **FastAPI** library to spawn a **REST** server that can be queried to obtain **predictions**. [for Ludwig]_" +"_Ми прийняли бібліотеку **FastAPI**, щоб запустити сервер **REST**, до якого можна надсилати запити для отримання **прогнозів**. [для Ludwig]_" -
Piero Molino, Yaroslav Dudin, and Sai Sumanth Miryala - Uber (ref)
+
Piero Molino, Yaroslav Dudin, and Sai Sumanth Miryala - Uber (джерело)
--- -"_**Netflix** is pleased to announce the open-source release of our **crisis management** orchestration framework: **Dispatch**! [built with **FastAPI**]_" +"_**Netflix** із задоволенням оголошує про випуск з відкритим кодом нашого фреймворку оркестрації **керування кризами**: **Dispatch**! [побудовано з **FastAPI**]_" -
Kevin Glisson, Marc Vilanova, Forest Monsen - Netflix (ref)
+
Kevin Glisson, Marc Vilanova, Forest Monsen - Netflix (джерело)
--- -"_If anyone is looking to build a production Python API, I would highly recommend **FastAPI**. It is **beautifully designed**, **simple to use** and **highly scalable**, it has become a **key component** in our API first development strategy and is driving many automations and services such as our Virtual TAC Engineer._" +"_Якщо хтось хоче створювати продакшн-API на Python, я дуже рекомендую **FastAPI**. Він **чудово спроєктований**, **простий у використанні** і **дуже масштабований**, він став **ключовим компонентом** у нашій стратегії розробки з пріоритетом API і забезпечує багато автоматизацій та сервісів, як-от наш Virtual TAC Engineer._" -
Deon Pillsbury - Cisco (ref)
+
Deon Pillsbury - Cisco (джерело)
--- @@ -239,7 +239,7 @@ async def read_item(item_id: int, q: str | None = None): **Примітка**: -Якщо ви не знаєте, перегляньте розділ _"In a hurry?"_ про [`async` та `await` у документації](https://fastapi.tiangolo.com/uk/async/#in-a-hurry). +Якщо ви не знаєте, перегляньте розділ _«Поспішаєте?»_ про [`async` та `await` у документації](https://fastapi.tiangolo.com/uk/async/#in-a-hurry). @@ -412,10 +412,10 @@ item: Item * JSON. * Параметрів шляху. * Параметрів запиту. - * Cookies. - * Headers. - * Forms. - * Files. + * Кукі. + * Заголовків. + * Форм. + * Файлів. * Перетворення вихідних даних: перетворення з даних і типів Python у мережеві дані (як JSON): * Перетворення типів Python (`str`, `int`, `float`, `bool`, `list`, тощо). * Обʼєктів `datetime`. @@ -477,10 +477,10 @@ item: Item **Попередження про спойлер**: навчальний посібник - посібник користувача містить: -* Оголошення **параметрів** з інших різних місць, як-от: **headers**, **cookies**, **form fields** та **files**. +* Оголошення **параметрів** з інших різних місць, як-от: **заголовки**, **кукі**, **поля форми** та **файли**. * Як встановлювати **обмеження валідації** як `maximum_length` або `regex`. * Дуже потужну і просту у використанні систему **Впровадження залежностей**. -* Безпеку та автентифікацію, включно з підтримкою **OAuth2** з **JWT tokens** та **HTTP Basic** auth. +* Безпеку та автентифікацію, включно з підтримкою **OAuth2** з **токенами JWT** та **базовою автентифікацією HTTP**. * Досконаліші (але однаково прості) техніки для оголошення **глибоко вкладених моделей JSON** (завдяки Pydantic). * Інтеграцію **GraphQL** з [Strawberry](https://strawberry.rocks) та іншими бібліотеками. * Багато додаткових можливостей (завдяки Starlette) як-от: @@ -492,9 +492,7 @@ item: Item ### Розгортання застосунку (необовʼязково) { #deploy-your-app-optional } -За бажання ви можете розгорнути ваш застосунок FastAPI у [FastAPI Cloud](https://fastapicloud.com), перейдіть і приєднайтеся до списку очікування, якщо ви ще цього не зробили. 🚀 - -Якщо у вас вже є обліковий запис **FastAPI Cloud** (ми запросили вас зі списку очікування 😉), ви можете розгорнути ваш застосунок однією командою. +За бажання ви можете розгорнути ваш застосунок FastAPI у [FastAPI Cloud](https://fastapicloud.com) однією командою. 🚀
@@ -510,6 +508,8 @@ Deploying to FastAPI Cloud...
+CLI автоматично визначить ваш застосунок FastAPI і розгорне його в хмарі. Якщо ви не ввійшли в обліковий запис, ваш браузер відкриється для завершення процесу автентифікації. + Ось і все! Тепер ви можете отримати доступ до вашого застосунку за цією URL-адресою. ✨ #### Про FastAPI Cloud { #about-fastapi-cloud } @@ -518,13 +518,13 @@ Deploying to FastAPI Cloud... Він спрощує процес **створення**, **розгортання** та **доступу** до API з мінімальними зусиллями. -Він забезпечує той самий **developer experience** створення застосунків на FastAPI під час їх **розгортання** у хмарі. 🎉 +Він забезпечує той самий **досвід розробника** створення застосунків на FastAPI під час їх **розгортання** у хмарі. 🎉 -FastAPI Cloud - основний спонсор і джерело фінансування open source проєктів *FastAPI and friends*. ✨ +FastAPI Cloud - основний спонсор і джерело фінансування проєктів з відкритим кодом *FastAPI and friends*. ✨ #### Розгортання в інших хмарних провайдерів { #deploy-to-other-cloud-providers } -FastAPI - open source проєкт і базується на стандартах. Ви можете розгортати застосунки FastAPI в будь-якому хмарному провайдері, який ви оберете. +FastAPI - проєкт з відкритим кодом і базується на стандартах. Ви можете розгортати застосунки FastAPI в будь-якому хмарному провайдері, який ви оберете. Дотримуйтеся інструкцій вашого хмарного провайдера, щоб розгорнути застосунки FastAPI у нього. 🤓 @@ -532,7 +532,7 @@ FastAPI - open source проєкт і базується на стандарта Незалежні тести TechEmpower показують застосунки **FastAPI**, які працюють під керуванням Uvicorn, як [одні з найшвидших доступних Python-фреймворків](https://www.techempower.com/benchmarks/#section=test&runid=7464e520-0dc2-473d-bd34-dbdfd7e85911&hw=ph&test=query&l=zijzen-7), поступаючись лише Starlette та Uvicorn (які внутрішньо використовуються в FastAPI). (*) -Щоб дізнатися більше, перегляньте розділ [Benchmarks](https://fastapi.tiangolo.com/uk/benchmarks/). +Щоб дізнатися більше, перегляньте розділ [Тести продуктивності](https://fastapi.tiangolo.com/uk/benchmarks/). ## Залежності { #dependencies } diff --git a/docs/uk/docs/project-generation.md b/docs/uk/docs/project-generation.md index 6e3781740..e4e825607 100644 --- a/docs/uk/docs/project-generation.md +++ b/docs/uk/docs/project-generation.md @@ -1,5 +1,6 @@ # Шаблон Full Stack FastAPI { #full-stack-fastapi-template } + Шаблони, хоча зазвичай постачаються з певним налаштуванням, спроєктовані бути гнучкими та налаштовуваними. Це дає змогу змінювати їх і адаптувати до вимог вашого проєкту, що робить їх чудовою відправною точкою. 🏁 Ви можете використати цей шаблон для старту, адже в ньому вже виконано значну частину початкового налаштування, безпеки, роботи з базою даних і деяких кінцевих точок API. diff --git a/docs/uk/docs/python-types.md b/docs/uk/docs/python-types.md index 332d78f21..06cc67f02 100644 --- a/docs/uk/docs/python-types.md +++ b/docs/uk/docs/python-types.md @@ -2,7 +2,7 @@ Python підтримує додаткові «підказки типів» (також звані «анотаціями типів»). -Ці **«підказки типів»** або анотації — це спеціальний синтаксис, що дозволяє оголошувати тип змінної. +Ці **«підказки типів»** або анотації - це спеціальний синтаксис, що дозволяє оголошувати тип змінної. За допомогою оголошення типів для ваших змінних редактори та інструменти можуть надати вам кращу підтримку. @@ -50,7 +50,7 @@ John Doe Це буде `upper`? Чи `uppercase`? `first_uppercase`? `capitalize`? -Тоді ви спробуєте давнього друга програміста — автозаповнення редактора коду. +Тоді ви спробуєте давнього друга програміста - автозаповнення редактора коду. Ви надрукуєте перший параметр функції, `first_name`, тоді крапку (`.`), а тоді натиснете `Ctrl+Space`, щоб запустити автозаповнення. @@ -147,20 +147,20 @@ def some_function(data: Any): print(data) ``` -### Generic типи { #generic-types } +### Узагальнені типи { #generic-types } Деякі типи можуть приймати «параметри типів» у квадратних дужках, щоб визначити їх внутрішні типи. Наприклад, «list строк» буде оголошений як `list[str]`. -Ці типи, які можуть приймати параметри типів, називаються **generic типами** або **generics**. +Ці типи, які можуть приймати параметри типів, називаються **узагальненими типами** або **дженериками**. -Ви можете використовувати ті самі вбудовані типи як generics (з квадратними дужками та типами всередині): +Ви можете використовувати ті самі вбудовані типи як дженерики (з квадратними дужками та типами всередині): * `list` * `tuple` * `set` * `dict` -#### List { #list } +#### Список { #list } Наприклад, давайте визначимо змінну, яка буде `list` із `str`. @@ -176,11 +176,11 @@ def some_function(data: Any): Ці внутрішні типи в квадратних дужках називаються «параметрами типу». -У цьому випадку `str` — це параметр типу, переданий у `list`. +У цьому випадку `str` - це параметр типу, переданий у `list`. /// -Це означає: «змінна `items` — це `list`, і кожен з елементів у цьому списку — `str`». +Це означає: «змінна `items` - це `list`, і кожен з елементів у цьому списку - `str`». Зробивши це, ваш редактор може надати підтримку навіть під час обробки елементів зі списку: @@ -192,7 +192,7 @@ def some_function(data: Any): І все ж редактор знає, що це `str`, і надає підтримку для цього. -#### Tuple and Set { #tuple-and-set } +#### Кортеж і множина { #tuple-and-set } Ви повинні зробити те ж саме, щоб оголосити `tuple` і `set`: @@ -200,10 +200,10 @@ def some_function(data: Any): Це означає: -* Змінна `items_t` — це `tuple` з 3 елементами: `int`, ще `int`, та `str`. -* Змінна `items_s` — це `set`, і кожен його елемент має тип `bytes`. +* Змінна `items_t` - це `tuple` з 3 елементами: `int`, ще `int`, та `str`. +* Змінна `items_s` - це `set`, і кожен його елемент має тип `bytes`. -#### Dict { #dict } +#### Словник { #dict } Щоб оголосити `dict`, вам потрібно передати 2 параметри типу, розділені комами. @@ -215,17 +215,17 @@ def some_function(data: Any): Це означає: -* Змінна `prices` — це `dict`: +* Змінна `prices` - це `dict`: * Ключі цього `dict` мають тип `str` (скажімо, назва кожного предмета). * Значення цього `dict` мають тип `float` (скажімо, ціна кожного предмета). -#### Union { #union } +#### Об’єднання { #union } Ви можете оголосити, що змінна може бути будь-яким із **кількох типів**, наприклад `int` або `str`. Щоб визначити це, використовуйте вертикальну риску (`|`), щоб розділити обидва типи. -Це називається «union», тому що змінна може бути чимось із об’єднання цих двох множин типів. +Це називається «об’єднанням», тому що змінна може бути чимось із об’єднання цих двох множин типів. ```Python hl_lines="1" {!> ../../docs_src/python_types/tutorial008b_py310.py!} @@ -263,11 +263,11 @@ def some_function(data: Any): -Зверніть увагу, що це означає: «`one_person` — це **екземпляр** класу `Person`». +Зверніть увагу, що це означає: «`one_person` - це **екземпляр** класу `Person`». -Це не означає: «`one_person` — це **клас** з назвою `Person`». +Це не означає: «`one_person` - це **клас** з назвою `Person`». -## Pydantic моделі { #pydantic-models } +## Моделі Pydantic { #pydantic-models } [Pydantic](https://docs.pydantic.dev/) — це бібліотека Python для валідації даних. @@ -295,7 +295,7 @@ def some_function(data: Any): ## Підказки типів з анотаціями метаданих { #type-hints-with-metadata-annotations } -У Python також є можливість додавати **додаткові метадані** до цих підказок типів за допомогою `Annotated`. +У Python також є можливість додавати **додаткові метадані** до цих підказок типів за допомогою `Annotated`. Ви можете імпортувати `Annotated` з `typing`. @@ -305,7 +305,7 @@ def some_function(data: Any): Але ви можете використати це місце в `Annotated`, щоб надати **FastAPI** додаткові метадані про те, як ви хочете, щоб ваш застосунок поводився. -Важливо пам’ятати, що **перший *параметр типу***, який ви передаєте в `Annotated`, — це **фактичний тип**. Решта — це лише метадані для інших інструментів. +Важливо пам’ятати, що **перший *параметр типу***, який ви передаєте в `Annotated`, - це **фактичний тип**. Решта - це лише метадані для інших інструментів. Наразі вам просто потрібно знати, що `Annotated` існує і що це стандартний Python. 😎 @@ -335,7 +335,7 @@ def some_function(data: Any): * **Перевірки даних**: що надходять від кожного запиту: * Генерування **автоматичних помилок**, що повертаються клієнту, коли дані недійсні. * **Документування** API за допомогою OpenAPI: - * який потім використовується для автоматичної інтерактивної документації користувальницьких інтерфейсів. + * що потім використовується автоматичними інтерактивними користувацькими інтерфейсами документації. Все це може здатися абстрактним. Не хвилюйтеся. Ви побачите все це в дії в [Навчальний посібник - Посібник користувача](tutorial/index.md). diff --git a/docs/uk/docs/tutorial/bigger-applications.md b/docs/uk/docs/tutorial/bigger-applications.md index 3a31ece46..85a6c66a0 100644 --- a/docs/uk/docs/tutorial/bigger-applications.md +++ b/docs/uk/docs/tutorial/bigger-applications.md @@ -17,16 +17,16 @@ ``` . ├── app -│   ├── __init__.py -│   ├── main.py -│   ├── dependencies.py -│   └── routers -│   │ ├── __init__.py -│   │ ├── items.py -│   │ └── users.py -│   └── internal -│   ├── __init__.py -│   └── admin.py +│ ├── __init__.py +│ ├── main.py +│ ├── dependencies.py +│ └── routers +│ │ ├── __init__.py +│ │ ├── items.py +│ │ └── users.py +│ └── internal +│ ├── __init__.py +│ └── admin.py ``` /// tip | Порада @@ -384,9 +384,9 @@ from .routers.users import router /// note | Примітка -`users.router` містить `APIRouter` у файлі `app/routers/users.py`. +`users.router` містить `APIRouter` всередині файлу `app/routers/users.py`. -А `items.router` містить `APIRouter` у файлі `app/routers/items.py`. +А `items.router` містить `APIRouter` всередині файлу `app/routers/items.py`. /// @@ -396,9 +396,9 @@ from .routers.users import router /// note | Технічні деталі -Фактично, всередині для кожної *операції шляху*, оголошеної в `APIRouter`, буде створена окрема *операція шляху*. +FastAPI зберігає оригінальний `APIRouter` і його `APIRoute` активними після включення router'а до основного застосунку. -Тобто за лаштунками все працюватиме так, ніби це один і той самий застосунок. +Це означає, що користувацькі підкласи `APIRouter` і `APIRoute` і надалі братимуть участь після включення router'а. /// @@ -406,7 +406,7 @@ from .routers.users import router Вам не потрібно перейматися продуктивністю під час включення router'ів. -Це займе мікросекунди і відбуватиметься лише під час запуску. +Це спроєктовано як легковагове рішення і не додає накладних витрат до кожного запиту. Тож це не вплине на продуктивність. ⚡ @@ -453,7 +453,7 @@ from .routers.users import router /// note | Дуже технічні деталі -Примітка: це дуже технічна деталь, яку ви, ймовірно, можете просто пропустити. +**Примітка**: це дуже технічна деталь, яку ви, ймовірно, можете **просто пропустити**. --- @@ -461,7 +461,7 @@ from .routers.users import router Це тому, що ми хочемо включати їхні *операції шляху* в схему OpenAPI та інтерфейси користувача. -Оскільки ми не можемо просто ізолювати їх і «змонтувати» незалежно від решти, *операції шляху* «клонуються» (створюються заново), а не включаються безпосередньо. +FastAPI зберігає оригінальні router'и та операції шляху активними й поєднує префікси router'ів, залежності, мітки, відповіді та інші метадані під час обробки запитів і генерації OpenAPI. /// @@ -518,7 +518,7 @@ $ fastapi dev ## Включайте той самий router кілька разів з різними `prefix` { #include-the-same-router-multiple-times-with-different-prefix } -Ви також можете використовувати `.include_router()` кілька разів з одним і тим самим router'ом, але з різними префіксами. +Ви також можете використовувати `.include_router()` кілька разів з *тим самим* router'ом, але з різними префіксами. Це може бути корисно, наприклад, щоб публікувати той самий API під різними префіксами, наприклад `/api/v1` і `/api/latest`. @@ -532,4 +532,16 @@ $ fastapi dev router.include_router(other_router) ``` -Переконайтеся, що ви робите це до включення `router` в застосунок `FastAPI`, щоб *операції шляху* з `other_router` також були включені. +Ви можете зробити це до або після включення `router` у застосунок `FastAPI`. FastAPI все одно включить *операції шляху* з `other_router` у маршрутизацію та OpenAPI. + +Те саме стосується *операцій шляху*, доданих пізніше до router'ів. Вони також будуть видимі через попереднє включення. + +/// warning | Технічні деталі + +Уникайте прямої мутації `router.routes` після включення router'а. FastAPI розглядає включення router'а як «живе», тому оригінальний router і його маршрути залишаються частиною маршрутизації та генерації OpenAPI. + +Використовуйте задокументовані API, такі як декоратори *операцій шляху* і `.include_router()`, щоб додавати маршрути та router'и. + +Сприймайте `router.routes` як нижчорівневе дерево маршрутів, яке може містити визначення маршрутів і включені router'и, і уникайте покладатися на нього як на плаский список кінцевих *операцій шляху*. + +/// diff --git a/docs/uk/docs/tutorial/body-multiple-params.md b/docs/uk/docs/tutorial/body-multiple-params.md index a0db2b186..8658e4a9b 100644 --- a/docs/uk/docs/tutorial/body-multiple-params.md +++ b/docs/uk/docs/tutorial/body-multiple-params.md @@ -111,7 +111,7 @@ q: str | None = None {* ../../docs_src/body_multiple_params/tutorial004_an_py310.py hl[28] *} -/// info | Інформація +/// note | Примітка `Body` також має всі ті самі додаткові параметри валідації та метаданих, що й `Query`, `Path` та інші, які ви побачите пізніше. @@ -126,7 +126,7 @@ q: str | None = None Але якщо ви хочете, щоб він очікував JSON з ключем `item`, а всередині нього - вміст моделі, як це відбувається, коли ви оголошуєте додаткові параметри тіла, ви можете використати спеціальний параметр `Body` - `embed`: ```Python -item: Item = Body(embed=True) +item: Annotated[Item, Body(embed=True)] ``` як у прикладі: diff --git a/docs/uk/docs/tutorial/body-nested-models.md b/docs/uk/docs/tutorial/body-nested-models.md index 97fea36dc..c1daaf671 100644 --- a/docs/uk/docs/tutorial/body-nested-models.md +++ b/docs/uk/docs/tutorial/body-nested-models.md @@ -27,17 +27,17 @@ my_list: list[str] Використовуйте той самий стандартний синтаксис для атрибутів моделей з внутрішніми типами. -Отже, у нашому прикладі, ми можемо зробити `tags` саме «списком рядків»: +Отже, у нашому прикладі, ми можемо зробити `tags` саме «списком строк»: {* ../../docs_src/body_nested_models/tutorial002_py310.py hl[12] *} ## Типи множин { #set-types } -Але потім ми подумали, що теги не повинні повторюватися, вони, ймовірно, повинні бути унікальними рядками. +Але потім ми подумали, що теги не повинні повторюватися, вони, ймовірно, повинні бути унікальними строками. -І Python має спеціальний тип даних для множин унікальних елементів — це `set`. +І Python має спеціальний тип даних для множин унікальних елементів - це `set`. -Тому ми можемо оголосити `tags` як множину рядків: +Тому ми можемо оголосити `tags` як множину строк: {* ../../docs_src/body_nested_models/tutorial003_py310.py hl[12] *} @@ -45,7 +45,7 @@ my_list: list[str] І коли ви будете виводити ці дані, навіть якщо джерело містить дублікати, вони будуть виведені як множина унікальних елементів. -І це буде анотовано/документовано відповідно. +І це буде анотовано / документовано відповідно. ## Вкладені моделі { #nested-models } @@ -69,7 +69,7 @@ my_list: list[str] {* ../../docs_src/body_nested_models/tutorial004_py310.py hl[18] *} -Це означатиме, що **FastAPI** очікуватиме тіло запиту такого вигляду: +Це означатиме, що **FastAPI** очікуватиме тіло, подібне до: ```JSON { @@ -85,7 +85,7 @@ my_list: list[str] } ``` -Завдяки такій декларації у **FastAPI** ви отримуєте: +Знову ж, лише завдяки такому оголошенню, з **FastAPI** ви отримуєте: * Підтримку в редакторі (автозавершення тощо), навіть для вкладених моделей * Конвертацію даних @@ -94,23 +94,23 @@ my_list: list[str] ## Спеціальні типи та валідація { #special-types-and-validation } -Окрім звичайних типів, таких як `str`, `int`, `float`, та ін. ви можете використовувати складніші типи, які наслідують `str`. +Окрім звичайних одиничних типів, таких як `str`, `int`, `float`, та ін. ви можете використовувати складніші одиничні типи, які наслідують `str`. Щоб побачити всі доступні варіанти, ознайомтеся з [Оглядом типів у Pydantic](https://docs.pydantic.dev/latest/concepts/types/). Деякі приклади будуть у наступному розділі. -Наприклад, у моделі `Image` є поле `url`, тому ми можемо оголосити його як `HttpUrl` від Pydantic замість `str`: +Наприклад, оскільки в моделі `Image` є поле `url`, ми можемо оголосити його як екземпляр `HttpUrl` від Pydantic замість `str`: {* ../../docs_src/body_nested_models/tutorial005_py310.py hl[2,8] *} -Рядок буде перевірено як дійсну URL-адресу і задокументовано в JSON Schema / OpenAPI як URL. +Строку буде перевірено як дійсну URL-адресу і задокументовано в Схемі JSON / OpenAPI як таку. ## Атрибути зі списками підмоделей { #attributes-with-lists-of-submodels } -У Pydantic ви можете використовувати моделі як підтипи для `list`, `set` тощо: +У Pydantic ви також можете використовувати моделі як підтипи для `list`, `set` тощо: {* ../../docs_src/body_nested_models/tutorial006_py310.py hl[18] *} -Це означає, що **FastAPI** буде очікувати (конвертувати, валідувати, документувати тощо) JSON тіло запиту у вигляді: +Це очікуватиме (конвертуватиме, валідуватиме, документуватиме тощо) тіло JSON у вигляді: ```JSON hl_lines="11" { @@ -136,7 +136,7 @@ my_list: list[str] } ``` -/// info | Інформація +/// note | Примітка Зверніть увагу, що тепер ключ `images` містить список об'єктів зображень. @@ -148,63 +148,63 @@ my_list: list[str] {* ../../docs_src/body_nested_models/tutorial007_py310.py hl[7,12,18,21,25] *} -/// info | Інформація +/// note | Примітка -Зверніть увагу, що в моделі `Offer` є список `Item`ів, які, своєю чергою, можуть мати необов'язковий список `Image`ів. +Зверніть увагу, що `Offer` має список `Item`ів, які, своєю чергою, мають необов'язковий список `Image`ів /// ## Тіла запитів, що складаються зі списків { #bodies-of-pure-lists } -Якщо верхній рівень JSON тіла, яке ви очікуєте, є JSON `масивом` (у Python — `list`), ви можете оголосити тип у параметрі функції, як і в моделях Pydantic: +Якщо значення верхнього рівня JSON тіла, яке ви очікуєте, є JSON `array` (Python `list`), ви можете оголосити тип у параметрі функції так само, як у моделях Pydantic: ```Python images: list[Image] ``` -наприклад: +як у: {* ../../docs_src/body_nested_models/tutorial008_py310.py hl[13] *} ## Підтримка в редакторі всюди { #editor-support-everywhere } -Ви отримаєте підтримку в редакторі всюди. +І ви отримаєте підтримку в редакторі всюди. Навіть для елементів у списках: -Ви не змогли б отримати таку підтримку в редакторі, якби працювали напряму зі `dict`, а не з моделями Pydantic. +Ви не змогли б отримати таку підтримку в редакторі, якби працювали напряму зі `dict`, а не з моделями Pydantic. -Але вам не потрібно турбуватися про це: вхідні dict'и автоматично конвертуються, а вихідні дані автоматично перетворюються в JSON. +Але вам також не потрібно турбуватися про них: вхідні словники автоматично конвертуються, а вихідні дані автоматично перетворюються в JSON. ## Тіла з довільними `dict` { #bodies-of-arbitrary-dicts } Ви також можете оголосити тіло як `dict` з ключами одного типу та значеннями іншого типу. -Це корисно, якщо ви не знаєте наперед, які імена полів будуть дійсними (як у випадку з моделями Pydantic). +Таким чином, вам не потрібно наперед знати, які імена полів/атрибутів є дійсними (як це було б у випадку з моделями Pydantic). Це буде корисно, якщо ви хочете приймати ключі, які заздалегідь невідомі. --- -Це також зручно, якщо ви хочете мати ключі іншого типу (наприклад, `int`). +Інший корисний випадок - коли ви хочете мати ключі іншого типу (наприклад, `int`). -Ось що ми розглянемо далі. +Ось що ми розглянемо тут. -У цьому випадку ви можете приймати будь-який `dict`, якщо його ключі — це `int`, а значення — `float`: +У цьому випадку ви можете приймати будь-який `dict`, якщо він має ключі `int` зі значеннями `float`: {* ../../docs_src/body_nested_models/tutorial009_py310.py hl[7] *} /// tip | Порада -Майте на увазі, що в JSON тілі ключі можуть бути лише рядками (`str`). +Майте на увазі, що JSON підтримує лише `str` як ключі. -Але Pydantic автоматично конвертує дані. +Але Pydantic має автоматичну конвертацію даних. -Це означає, що навіть якщо клієнти вашого API надсилатимуть ключі у вигляді рядків, якщо вони містять цілі числа, Pydantic конвертує їх і проведе валідацію. +Це означає, що навіть якщо клієнти вашого API можуть надсилати лише строки як ключі, якщо ці строки містять цілі числа, Pydantic конвертує їх і проведе валідацію. -Тобто `dict`, який ви отримаєте як `weights`, матиме ключі типу `int` та значення типу `float`. +І `dict`, який ви отримаєте як `weights`, фактично матиме ключі типу `int` та значення типу `float`. /// @@ -212,10 +212,10 @@ images: list[Image] З **FastAPI** ви маєте максимальну гнучкість завдяки моделям Pydantic, зберігаючи при цьому код простим, коротким та елегантним. -А також отримуєте всі переваги: +Але з усіма перевагами: -* Підтримка в редакторі (автодоповнення всюди!) -* Конвертація даних (парсинг/серіалізація) +* Підтримка в редакторі (автозавершення всюди!) +* Конвертація даних (також відома як парсинг / серіалізація) * Валідація даних * Документація схем -* Автоматичне створення документації +* Автоматична документація diff --git a/docs/uk/docs/tutorial/body.md b/docs/uk/docs/tutorial/body.md index 91c4b4252..64d9af95e 100644 --- a/docs/uk/docs/tutorial/body.md +++ b/docs/uk/docs/tutorial/body.md @@ -4,11 +4,11 @@ Тіло **запиту** - це дані, надіслані клієнтом до вашого API. Тіло **відповіді** - це дані, які ваш API надсилає клієнту. -Ваш API майже завжди має надсилати тіло **відповіді**. Але клієнтам не обов’язково потрібно постійно надсилати тіла **запитів** — інколи вони лише запитують шлях, можливо з деякими параметрами запиту, але не надсилають тіло. +Ваш API майже завжди має надсилати тіло **відповіді**. Але клієнтам не обов’язково потрібно постійно надсилати тіла **запитів** - інколи вони лише запитують шлях, можливо з деякими параметрами запиту, але не надсилають тіло. Щоб оголосити тіло **запиту**, ви використовуєте [Pydantic](https://docs.pydantic.dev/) моделі з усією їх потужністю та перевагами. -/// info | Інформація +/// note | Примітка Щоб надіслати дані, ви повинні використовувати один із: `POST` (більш поширений), `PUT`, `DELETE` або `PATCH`. diff --git a/docs/uk/docs/tutorial/cookie-param-models.md b/docs/uk/docs/tutorial/cookie-param-models.md index dab57c536..add562dfd 100644 --- a/docs/uk/docs/tutorial/cookie-param-models.md +++ b/docs/uk/docs/tutorial/cookie-param-models.md @@ -32,13 +32,13 @@
-/// info | Інформація +/// note | Примітка Майте на увазі, що оскільки **браузери обробляють cookies** особливим чином і «за лаштунками», вони **не** дозволяють **JavaScript** легко з ними працювати. Якщо ви зайдете до **інтерфейсу документації API** за адресою `/docs`, ви зможете побачити **документацію** для cookies у ваших *операціях шляху*. -Але навіть якщо ви заповните дані й натиснете "Execute", оскільки інтерфейс документації працює з **JavaScript**, cookies не будуть відправлені, і ви побачите **помилку**, ніби ви не ввели жодних значень. +Але навіть якщо ви **заповните дані** й натиснете "Execute", оскільки інтерфейс документації працює з **JavaScript**, cookies не будуть відправлені, і ви побачите **помилку**, ніби ви не ввели жодних значень. /// @@ -73,4 +73,4 @@ ## Підсумок { #summary } -Ви можете використовувати **Pydantic-моделі** для оголошення **cookies** у **FastAPI**. 😎 +Ви можете використовувати **Pydantic-моделі** для оголошення **кукі** у **FastAPI**. 😎 diff --git a/docs/uk/docs/tutorial/cookie-params.md b/docs/uk/docs/tutorial/cookie-params.md index 3a2e6fa24..b55c37774 100644 --- a/docs/uk/docs/tutorial/cookie-params.md +++ b/docs/uk/docs/tutorial/cookie-params.md @@ -24,13 +24,13 @@ /// -/// info +/// note Для визначення кукі ви маєте використовувати `Cookie`, тому що в іншому випадку параметри будуть інтерпретовані як параметри запиту. /// -/// info +/// note Майте на увазі, що оскільки **браузери обробляють кукі** спеціальним чином і за лаштунками, вони **не** дозволяють **JavaScript** легко взаємодіяти з ними. diff --git a/docs/uk/docs/tutorial/debugging.md b/docs/uk/docs/tutorial/debugging.md index 821b55801..4d995698c 100644 --- a/docs/uk/docs/tutorial/debugging.md +++ b/docs/uk/docs/tutorial/debugging.md @@ -1,5 +1,6 @@ # Налагодження { #debugging } + Ви можете під'єднати дебагер у вашому редакторі коду, наприклад, у Visual Studio Code або PyCharm. ## Виклик `uvicorn` { #call-uvicorn } diff --git a/docs/uk/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md b/docs/uk/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md index a82461c8d..f82150919 100644 --- a/docs/uk/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md +++ b/docs/uk/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md @@ -28,7 +28,7 @@ /// -/// info | Інформація +/// note | Примітка У цьому прикладі ми використовуємо вигадані власні заголовки `X-Key` і `X-Token`. diff --git a/docs/uk/docs/tutorial/dependencies/dependencies-with-yield.md b/docs/uk/docs/tutorial/dependencies/dependencies-with-yield.md index 53b49e61b..9642cebe0 100644 --- a/docs/uk/docs/tutorial/dependencies/dependencies-with-yield.md +++ b/docs/uk/docs/tutorial/dependencies/dependencies-with-yield.md @@ -63,7 +63,7 @@ FastAPI підтримує залежності, які виконують де Ви можете мати підзалежності та «дерева» підзалежностей будь-якого розміру і форми, і будь-яка або всі з них можуть використовувати `yield`. -**FastAPI** гарантує, що «exit code» у кожній залежності з `yield` буде виконано в правильному порядку. +**FastAPI** гарантує, що «код виходу» у кожній залежності з `yield` буде виконано в правильному порядку. Наприклад, `dependency_c` може залежати від `dependency_b`, а `dependency_b` - від `dependency_a`: @@ -170,7 +170,7 @@ participant tasks as Background tasks end ``` -/// info | Інформація +/// note | Примітка Лише **одна відповідь** буде надіслана клієнту. Це може бути одна з помилкових відповідей або відповідь від *операції шляху*. @@ -194,7 +194,7 @@ participant tasks as Background tasks `Depends()` приймає параметр `scope`, який може бути: -* `"function"`: запустити залежність перед *функцією операції шляху*, що обробляє запит, завершити залежність після завершення *функції операції шляху*, але **до** того, як відповідь буде відправлена клієнту. Тобто функція залежності буде виконуватися **навколо** *функції операції **шляху***. +* `"function"`: запустити залежність перед *функцією операції шляху*, що обробляє запит, завершити залежність після завершення *функції операції шляху*, але **до** того, як відповідь буде відправлена клієнту. Тобто функція залежності буде виконуватися **навколо** ***функції** операції шляху*. * `"request"`: запустити залежність перед *функцією операції шляху*, що обробляє запит (подібно до `"function"`), але завершити **після** того, як відповідь буде відправлена клієнту. Тобто функція залежності буде виконуватися **навколо** циклу **запиту** та відповіді. Якщо не вказано, і залежність має `yield`, за замовчуванням `scope` дорівнює `"request"`. @@ -234,6 +234,7 @@ participant operation as Path Operation Залежності з `yield` еволюціонували з часом, щоб покрити різні сценарії та виправити деякі проблеми. Якщо ви хочете дізнатися, що змінювалося в різних версіях FastAPI, прочитайте про це в просунутому посібнику користувача: [Розширені залежності - Залежності з `yield`, `HTTPException`, `except` і фоновими задачами](../../advanced/advanced-dependencies.md#dependencies-with-yield-httpexception-except-and-background-tasks). + ## Менеджери контексту { #context-managers } ### Що таке «Менеджери контексту» { #what-are-context-managers } diff --git a/docs/uk/docs/tutorial/dependencies/index.md b/docs/uk/docs/tutorial/dependencies/index.md index bea5f598d..2021db260 100644 --- a/docs/uk/docs/tutorial/dependencies/index.md +++ b/docs/uk/docs/tutorial/dependencies/index.md @@ -51,7 +51,7 @@ Потім вона просто повертає `dict`, що містить ці значення. -/// info | Інформація +/// note | Примітка FastAPI додав підтримку `Annotated` (і почав її рекомендувати) у версії 0.95.0. @@ -106,7 +106,7 @@ common_parameters --> read_users Таким чином ви пишете спільний код один раз, а **FastAPI** подбає про його виклик для ваших *операцій шляху*. -/// check | Перевірте +/// tip | Порада Зверніть увагу, що вам не потрібно створювати спеціальний клас і передавати його кудись у **FastAPI**, щоб «зареєструвати» його чи щось подібне. @@ -138,7 +138,7 @@ commons: Annotated[dict, Depends(common_parameters)] Залежності продовжать працювати як очікується, і **найкраще** те, що **інформація про типи буде збережена**, а це означає, що ваш редактор зможе й надалі надавати **автозаповнення**, **помилки в рядку** тощо. Те саме і для інших інструментів, як-от `mypy`. -Це буде особливо корисно у **великій кодовій базі**, де ви використовуєте **одні й ті самі залежності** знову і знову в **багатьох *операціях шляху***. +Це буде особливо корисно у **великій кодовій базі**, де ви використовуєте **одні й ті ж залежності** знову і знову в **багатьох *операціях шляху***. ## Бути `async` чи не бути `async` { #to-async-or-not-to-async } diff --git a/docs/uk/docs/tutorial/dependencies/sub-dependencies.md b/docs/uk/docs/tutorial/dependencies/sub-dependencies.md index 4e7488086..c98d917c1 100644 --- a/docs/uk/docs/tutorial/dependencies/sub-dependencies.md +++ b/docs/uk/docs/tutorial/dependencies/sub-dependencies.md @@ -4,7 +4,7 @@ Вони можуть бути настільки глибокими, наскільки потрібно. -FastAPI подбає про їх розв'язання. +**FastAPI** подбає про їх розв'язання. ## Перша залежність «dependable» { #first-dependency-dependable } @@ -35,11 +35,11 @@ FastAPI подбає про їх розв'язання. {* ../../docs_src/dependencies/tutorial005_an_py310.py hl[23] *} -/// info | Інформація +/// note | Примітка Зверніть увагу, що ми оголошуємо лише одну залежність у функції операції шляху — `query_or_cookie_extractor`. -Але FastAPI знатиме, що спочатку треба розв'язати `query_extractor`, щоб передати його результат у `query_or_cookie_extractor` під час виклику. +Але **FastAPI** знатиме, що спочатку треба розв'язати `query_extractor`, щоб передати його результат у `query_or_cookie_extractor` під час виклику. /// @@ -56,7 +56,7 @@ query_extractor --> query_or_cookie_extractor --> read_query ## Використання тієї ж залежності кілька разів { #using-the-same-dependency-multiple-times } -Якщо одна з ваших залежностей оголошена кілька разів для однієї операції шляху, наприклад, кілька залежностей мають спільну підзалежність, FastAPI знатиме, що цю підзалежність потрібно викликати лише один раз на запит. +Якщо одна з ваших залежностей оголошена кілька разів для однієї операції шляху, наприклад, кілька залежностей мають спільну підзалежність, **FastAPI** знатиме, що цю підзалежність потрібно викликати лише один раз на запит. І він збереже повернуте значення у «кеш» і передасть його всім «dependants», яким воно потрібне в цьому конкретному запиті, замість того щоб викликати залежність кілька разів для одного й того ж запиту. @@ -88,7 +88,7 @@ async def needy_dependency(fresh_value: str = Depends(get_value, use_cache=False ## Підсумок { #recap } -Попри всі модні терміни, система впровадження залежностей досить проста. +Попри всі модні терміни, система **впровадження залежностей** досить проста. Це просто функції, які виглядають так само, як функції операцій шляху. diff --git a/docs/uk/docs/tutorial/extra-data-types.md b/docs/uk/docs/tutorial/extra-data-types.md index 26d7c306f..15e6b64a4 100644 --- a/docs/uk/docs/tutorial/extra-data-types.md +++ b/docs/uk/docs/tutorial/extra-data-types.md @@ -22,7 +22,7 @@ Ось додаткові типи даних для використання: * `UUID`: - * Стандартний "Універсальний унікальний ідентифікатор", який часто використовується як ID у багатьох базах даних та системах. + * Стандартний «Універсальний унікальний ідентифікатор», який часто використовується як ID у багатьох базах даних та системах. * У запитах та відповідях буде представлений як `str`. * `datetime.datetime`: * Пайтонівський `datetime.datetime`. @@ -36,16 +36,16 @@ * `datetime.timedelta`: * Пайтонівський `datetime.timedelta`. * У запитах та відповідях буде представлений як `float` загальної кількості секунд. - * Pydantic також дозволяє представляти це як "ISO 8601 time diff encoding", [дивіться документацію для отримання додаткової інформації](https://docs.pydantic.dev/latest/concepts/serialization/#custom-serializers). + * Pydantic також дозволяє представляти це як «ISO 8601 time diff encoding», [дивіться документацію для отримання додаткової інформації](https://docs.pydantic.dev/latest/concepts/serialization/#custom-serializers). * `frozenset`: * У запитах і відповідях це буде оброблено так само, як і `set`: * У запитах список буде зчитано, дублікати буде видалено, і його буде перетворено на `set`. * У відповідях `set` буде перетворено на `list`. - * Згенерована схема буде вказувати, що значення `set` є унікальними (з використанням JSON Schema's `uniqueItems`). + * Згенерована схема буде вказувати, що значення `set` є унікальними (з використанням `uniqueItems` Схеми JSON). * `bytes`: * Стандартний Пайтонівський `bytes`. * У запитах і відповідях це буде оброблено як `str`. - * Згенерована схема буде вказувати, що це `str` з "форматом" `binary`. + * Згенерована схема буде вказувати, що це `str` з «форматом» `binary`. * `Decimal`: * Стандартний Пайтонівський `Decimal`. * У запитах і відповідях це буде оброблено так само, як і `float`. diff --git a/docs/uk/docs/tutorial/extra-models.md b/docs/uk/docs/tutorial/extra-models.md index 271e553fd..564f9fc44 100644 --- a/docs/uk/docs/tutorial/extra-models.md +++ b/docs/uk/docs/tutorial/extra-models.md @@ -63,7 +63,7 @@ print(user_dict) #### Розпакування `dict` { #unpacking-a-dict } -Якщо взяти `dict`, наприклад `user_dict`, і передати його у функцію (або клас) як `**user_dict`, Python «розпакує» його. Ключі та значення `user_dict` будуть передані безпосередньо як іменовані аргументи. +Якщо взяти `dict`, наприклад `user_dict`, і передати його у функцію (або клас) як `**user_dict`, Python «розпакує» його. Ключі та значення `user_dict` будуть передані безпосередньо як аргументи ключ-значення. Отже, продовжуючи з `user_dict` вище, запис: @@ -176,7 +176,7 @@ UserInDB( У цьому прикладі ми передаємо `Union[PlaneItem, CarItem]` як значення аргументу `response_model`. -Оскільки ми передаємо його як значення аргументу, а не в анотації типу, потрібно використовувати `Union` навіть у Python 3.10. +Оскільки ми передаємо його як **значення аргументу**, а не розміщуємо в **анотації типу**, потрібно використовувати `Union` навіть у Python 3.10. Якби це була анотація типу, можна було б використати вертикальну риску, наприклад: @@ -184,7 +184,7 @@ UserInDB( some_variable: PlaneItem | CarItem ``` -Але якщо записати це як присвоєння `response_model=PlaneItem | CarItem`, отримаємо помилку, тому що Python спробує виконати невалідну операцію між `PlaneItem` і `CarItem`, замість того щоб трактувати це як анотацію типу. +Але якщо записати це як присвоєння `response_model=PlaneItem | CarItem`, отримаємо помилку, тому що Python спробує виконати **невалідну операцію** між `PlaneItem` і `CarItem`, замість того щоб трактувати це як анотацію типу. ## Список моделей { #list-of-models } @@ -208,4 +208,4 @@ some_variable: PlaneItem | CarItem Використовуйте кілька моделей Pydantic і вільно наслідуйте для кожного випадку. -Не обов’язково мати одну модель даних на сутність, якщо ця сутність може мати різні «стани». Як у випадку сутності користувача зі станами: з `password`, з `password_hash` і без пароля. +Не обов’язково мати одну модель даних на сутність, якщо ця сутність повинна мати різні «стани». «Сутність» **користувач** є прикладом зі станами, що включають `password`, `password_hash` або відсутність пароля. diff --git a/docs/uk/docs/tutorial/first-steps.md b/docs/uk/docs/tutorial/first-steps.md index 0f46890d9..0469e6c4d 100644 --- a/docs/uk/docs/tutorial/first-steps.md +++ b/docs/uk/docs/tutorial/first-steps.md @@ -88,13 +88,13 @@ INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) #### «Схема» { #schema } -«Схема» — це визначення або опис чогось. Це не код, який його реалізує, а просто абстрактний опис. +«Схема» - це визначення або опис чогось. Це не код, який його реалізує, а просто абстрактний опис. #### API «схема» { #api-schema } У цьому випадку, [OpenAPI](https://github.com/OAI/OpenAPI-Specification) є специфікацією, яка визначає, як описати схему вашого API. -Це визначення схеми включає шляхи (paths) вашого API, можливі параметри, які вони приймають, тощо. +Це визначення схеми включає шляхи вашого API, можливі параметри, які вони приймають, тощо. #### «Схема» даних { #data-schema } @@ -102,13 +102,13 @@ INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) У цьому випадку це означає атрибути JSON і типи даних, які вони мають, тощо. -#### OpenAPI і JSON Schema { #openapi-and-json-schema } +#### OpenAPI і Схема JSON { #openapi-and-json-schema } -OpenAPI описує схему API для вашого API. І ця схема включає визначення (або «схеми») даних, що надсилаються та отримуються вашим API, за допомогою **JSON Schema**, стандарту для схем даних JSON. +OpenAPI описує схему API для вашого API. І ця схема включає визначення (або «схеми») даних, що надсилаються та отримуються вашим API, за допомогою **Схеми JSON**, стандарту для схем даних JSON. #### Перевірте `openapi.json` { #check-the-openapi-json } -Якщо вас цікавить, як виглядає «сирий» OpenAPI schema, FastAPI автоматично генерує JSON (schema) з описами всього вашого API. +Якщо вас цікавить, як виглядає «сирa» схема OpenAPI, FastAPI автоматично генерує JSON (схему) з описами всього вашого API. Ви можете побачити це напряму тут: [http://127.0.0.1:8000/openapi.json](http://127.0.0.1:8000/openapi.json). @@ -137,7 +137,7 @@ OpenAPI описує схему API для вашого API. І ця схема #### Для чого потрібний OpenAPI { #what-is-openapi-for } -OpenAPI schema — це те, на чому працюють дві включені системи інтерактивної документації. +Схема OpenAPI - це те, на чому працюють дві включені системи інтерактивної документації. Також існують десятки альтернатив, і всі вони засновані на OpenAPI. Ви можете легко додати будь-яку з цих альтернатив до вашого застосунку, створеного з **FastAPI**. @@ -180,7 +180,7 @@ entrypoint = "backend.main:app" from backend.main import app ``` -### `fastapi dev` із шляхом { #fastapi-dev-with-path } +### `fastapi dev` із шляхом або з параметром CLI `--entrypoint` { #fastapi-dev-with-path-or-with-entrypoint-cli-option } Ви також можете передати шлях до файлу в команду `fastapi dev`, і вона вгадає обʼєкт FastAPI app, який слід використовувати: @@ -188,29 +188,19 @@ from backend.main import app $ fastapi dev main.py ``` -Але вам доведеться щоразу памʼятати передавати правильний шлях під час виклику команди `fastapi`. - -Крім того, інші інструменти можуть не знайти його, наприклад [Розширення VS Code](../editor-support.md) або [FastAPI Cloud](https://fastapicloud.com), тому рекомендується використовувати `entrypoint` у `pyproject.toml`. - -### Розгорніть ваш застосунок (необовʼязково) { #deploy-your-app-optional } - -За бажанням ви можете розгорнути ваш FastAPI-застосунок у [FastAPI Cloud](https://fastapicloud.com), перейдіть і приєднайтеся до списку очікування, якщо ви цього ще не зробили. 🚀 - -Якщо у вас вже є обліковий запис **FastAPI Cloud** (ми запросили вас зі списку очікування 😉), ви можете розгорнути ваш застосунок однією командою. - -Перед розгортанням переконайтеся, що ви увійшли: - -
+Або ви також можете передати параметр `--entrypoint` команді `fastapi dev`: ```console -$ fastapi login - -You are logged in to FastAPI Cloud 🚀 +$ fastapi dev --entrypoint main:app ``` -
+Але вам доведеться щоразу памʼятати передавати правильний шлях\entrypoint під час виклику команди `fastapi`. + +Крім того, інші інструменти можуть не знайти його, наприклад [Розширення VS Code](../editor-support.md) або [FastAPI Cloud](https://fastapicloud.com), тому рекомендується використовувати `entrypoint` у `pyproject.toml`. + +### Розгорніть ваш застосунок (необовʼязково) { #deploy-your-app-optional } -Потім розгорніть ваш застосунок: +За бажанням ви можете розгорнути ваш FastAPI-застосунок у [FastAPI Cloud](https://fastapicloud.com) однією командою. 🚀
@@ -226,6 +216,8 @@ Deploying to FastAPI Cloud...
+CLI автоматично визначить ваш застосунок FastAPI і розгорне його в хмарі. Якщо ви не ввійшли, ваш браузер відкриється для завершення процесу автентифікації. + Ось і все! Тепер ви можете отримати доступ до вашого застосунку за цим URL. ✨ ## Підібʼємо підсумки, крок за кроком { #recap-step-by-step } @@ -234,11 +226,11 @@ Deploying to FastAPI Cloud... {* ../../docs_src/first_steps/tutorial001_py310.py hl[1] *} -`FastAPI` — це клас у Python, який надає всю функціональність для вашого API. +`FastAPI` - це клас у Python, який надає всю функціональність для вашого API. /// note | Технічні деталі -`FastAPI` — це клас, який успадковується безпосередньо від `Starlette`. +`FastAPI` - це клас, який успадковується безпосередньо від `Starlette`. Ви також можете використовувати всю функціональність [Starlette](https://www.starlette.dev/) у `FastAPI`. @@ -270,7 +262,7 @@ https://example.com/items/foo /items/foo ``` -/// info +/// note | Примітка «Шлях» також зазвичай називають «ендпоінтом» або «маршрутом». @@ -320,9 +312,9 @@ https://example.com/items/foo Декоратор `@app.get("/")` повідомляє **FastAPI**, що функція одразу нижче відповідає за обробку запитів, які надходять до: * шляху `/` -* використовуючи get операція +* використовуючи операцію get -/// info | `@decorator` Інформація +/// note | `@decorator` Інформація Синтаксис `@something` у Python називається «декоратором». @@ -349,7 +341,7 @@ https://example.com/items/foo * `@app.patch()` * `@app.trace()` -/// tip +/// tip | Порада Ви можете використовувати кожну операцію (HTTP-метод) як забажаєте. @@ -383,7 +375,7 @@ https://example.com/items/foo {* ../../docs_src/first_steps/tutorial003_py310.py hl[7] *} -/// note +/// note | Примітка Якщо ви не знаєте різницю, подивіться [Асинхронність: *«Поспішаєте?»*](../async.md#in-a-hurry). @@ -397,7 +389,7 @@ https://example.com/items/foo Також можна повернути моделі Pydantic (про це ви дізнаєтесь пізніше). -Існує багато інших обʼєктів і моделей, які будуть автоматично конвертовані в JSON (зокрема ORM тощо). Спробуйте використати свої улюблені — велика ймовірність, що вони вже підтримуються. +Існує багато інших обʼєктів і моделей, які будуть автоматично конвертовані в JSON (зокрема ORM тощо). Спробуйте використати свої улюблені - велика ймовірність, що вони вже підтримуються. ### Крок 6: розгорніть його { #step-6-deploy-it } @@ -411,11 +403,11 @@ https://example.com/items/foo Він переносить той самий **досвід розробника** зі створення застосунків на FastAPI на **розгортання** їх у хмарі. 🎉 -FastAPI Cloud — основний спонсор і джерело фінансування для open source проєктів *FastAPI and friends*. ✨ +FastAPI Cloud - основний спонсор і джерело фінансування для open source проєктів *FastAPI and friends*. ✨ #### Розгортання в інших хмарних провайдерах { #deploy-to-other-cloud-providers } -FastAPI — це open source і базується на стандартах. Ви можете розгортати FastAPI-застосунки у будь-якого хмарного провайдера на ваш вибір. +FastAPI - це open source і базується на стандартах. Ви можете розгортати FastAPI-застосунки у будь-якого хмарного провайдера на ваш вибір. Дотримуйтеся інструкцій вашого хмарного провайдера, щоб розгорнути FastAPI-застосунки з їхньою допомогою. 🤓 diff --git a/docs/uk/docs/tutorial/frontend.md b/docs/uk/docs/tutorial/frontend.md new file mode 100644 index 000000000..c85e6693e --- /dev/null +++ b/docs/uk/docs/tutorial/frontend.md @@ -0,0 +1,133 @@ +# Фронтенд { #frontend } + +Ви можете обслуговувати статичні фронтенд-застосунки за допомогою `app.frontend()` (або `router.frontend()`). + +Це корисно для фронтенд-інструментів, які генерують статичні файли, як-от React з Vite, TanStack Router, Astro, Vue, Svelte, Angular, Solid та інші. + +З такими інструментами зазвичай є крок, який збирає фронтенд, командою на кшталт: + +```bash +npm run build +``` + +Це згенерує директорію на кшталт `./dist/` з вашими фронтенд-файлами. + +Ви можете використати `app.frontend()`, щоб обслуговувати цю директорію відповідно до конвенцій, потрібних цим фронтенд-фреймворкам. + +**FastAPI** спочатку перевіряє *операції шляху*. Фронтенд-файли перевіряються лише тоді, коли жоден звичайний маршрут не збігся, тому ваш API не буде зачеплено. + +## Обслуговування фронтенду { #serve-a-frontend } + +Після збірки вашого фронтенду, наприклад за допомогою `npm run build`, помістіть згенеровані файли в директорію, наприклад `dist`. + +Структура вашого проєкту може виглядати так: + +```text +. +├── pyproject.toml +├── app +│ ├── __init__.py +│ └── main.py +└── dist + ├── index.html + └── assets + └── app.js +``` + +Потім обслуговуйте її за допомогою `app.frontend()`: + +{* ../../docs_src/frontend/tutorial001_py310.py hl[5] *} + +З цим запит до `/assets/app.js` може обслуговувати `dist/assets/app.js`. + +Якщо у вас також є *операція шляху* **FastAPI**, *операція шляху* має пріоритет. + +## Маршрутизація на боці клієнта { #client-side-routing } + +Багато фронтенд-застосунків, включно з **односторінковими застосунками** (SPA), використовують маршрутизацію на боці клієнта. Шлях на кшталт `/dashboard/settings` може не бути реальним файлом, але фреймворк подбає про його обробку. + +Тому, якщо звертатися до цієї URL-адреси напряму (замість навігації через застосунок), бекенд має обслуговувати фронтенд-застосунок з `index.html`, щоб фронтенд-фреймворк потім міг обробити маршрутизацію на боці клієнта. + +Для цього використовуйте `fallback="index.html"`: + +{* ../../docs_src/frontend/tutorial002_py310.py hl[5] *} + +**FastAPI** використовує цей fallback лише для запитів `GET` і `HEAD`, які виглядають як навігація браузера. Відсутні файли, як-от JavaScript, CSS і зображення, все ще повертають `404`. + +Запити з іншими методами, як-от `POST` або `PUT`, до шляхів, що збігаються лише з frontend fallback, також повертають `404`. Звичайні *операції шляху* **FastAPI** все ще мають вищий пріоритет, ніж фронтенд-маршрути. + +/// tip | Порада + +За замовчуванням `fallback` має значення `fallback="auto"`. У більшості випадків вам не потрібно вказувати `fallback`. Деталі читайте нижче. + +/// + +Саме це потрібно для багатьох фронтенд-застосунків, які використовують маршрутизацію на боці клієнта, наприклад React з TanStack Router, Vue, Angular, SvelteKit або Solid. + +## Користувацька сторінка 404 { #custom-404-page } + +Ви також можете обслуговувати статичну сторінку `404.html` для відсутніх фронтенд-шляхів: + +{* ../../docs_src/frontend/tutorial003_py310.py hl[5] *} + +Ця відповідь зберігає код статусу `404`. + +У цьому випадку **FastAPI** не буде обслуговувати `index.html` для відсутніх фронтенд-шляхів. Натомість він поверне файл `404.html`. + +/// tip | Порада + +За замовчуванням `fallback` має значення `fallback="auto"`. З ним, якщо файл `404.html` знайдено, він буде використаний як fallback автоматично. + +Тому зазвичай ви можете не вказувати аргумент `fallback`. + +/// + +Це корисно з фронтенд-інструментами, які генерують статичні HTML-файли для кожної сторінки, як-от Astro. + +## Автоматичний fallback { #fallback-auto } + +За замовчуванням `app.frontend()` використовує `fallback="auto"`. + +Якщо в директорії фронтенду є файл `404.html`, відсутні фронтенд-шляхи обслуговують цей файл з кодом статусу `404`. + +Інакше, якщо є файл `index.html`, відсутні шляхи навігації браузера обслуговують `index.html`, що й очікують багато фронтенд-застосунків з маршрутизацією на боці клієнта. + +Отже, у більшості випадків ви можете використовувати `app.frontend("/", directory="dist")` без вказання аргументу `fallback`. + +{* ../../docs_src/frontend/tutorial001_py310.py hl[5] *} + +## Вимкнення fallback { #disable-fallback } + +Якщо ви не хочете обслуговувати fallback-файл для відсутніх фронтенд-шляхів, використовуйте `fallback=None`: + +{* ../../docs_src/frontend/tutorial005_py310.py hl[5] *} + +Тоді відсутні фронтенд-шляхи повертають звичайний `404`. + +## Перевірка директорії { #check-directory } + +За замовчуванням `app.frontend()` перевіряє, що директорія існує, коли застосунок створюється. + +Це допомагає виявити помилки конфігурації завчасно. Наприклад, якщо директорія вихідних файлів збірки фронтенду відсутня, **FastAPI** викличе помилку під час запуску. + +Якщо ваші фронтенд-файли створюються пізніше, наприклад окремим кроком збірки після створення об'єкта застосунку, встановіть `check_dir=False`: + +{* ../../docs_src/frontend/tutorial006_py310.py hl[5] *} + +З `check_dir=False` **FastAPI** не перевірятиме директорію під час створення застосунку. Якщо налаштована директорія все ще відсутня під час обробки запиту, **FastAPI** викличе помилку тоді. + +## Використання з `APIRouter` { #use-it-with-apirouter } + +Ви також можете додати фронтенд-файли до `APIRouter` і включити його з префіксом: + +{* ../../docs_src/frontend/tutorial004_py310.py hl[6,7] *} + +У цьому прикладі фронтенд-шляхи обслуговуються під `/app`. + +Будь-які звичайні *операції шляху* в застосунку все ще матимуть перевагу, включно з операціями в інших роутерах. + +## Лише статичний результат збірки { #static-build-output-only } + +`app.frontend()` обслуговує файли, вже згенеровані вашою фронтенд-збіркою. + +Він не виконує рендеринг на боці сервера. Він призначений для фронтенд-фреймворків, які генерують статичні файли, а не для фреймворків, що потребують динамічного рендерингу на сервері для кожного запиту. diff --git a/docs/uk/docs/tutorial/handling-errors.md b/docs/uk/docs/tutorial/handling-errors.md index 262efa0e0..381e65cc0 100644 --- a/docs/uk/docs/tutorial/handling-errors.md +++ b/docs/uk/docs/tutorial/handling-errors.md @@ -33,7 +33,7 @@ Оскільки це помилка Python, ви не `return` її, а `raise` її. -Це також означає, що якщо ви перебуваєте всередині допоміжної функції, яку викликаєте всередині своєї *функції операції шляху*, і там згенеруєте `HTTPException` всередині цієї допоміжної функції, то решта коду в *функції операції шляху* не буде виконана. Запит одразу завершиться, і HTTP-помилка з `HTTPException` буде надіслана клієнту. +Це також означає, що якщо ви перебваєте всередині допоміжної функції, яку викликаєте всередині своєї *функції операції шляху*, і там згенеруєте `HTTPException` всередині цієї допоміжної функції, то решта коду в *функції операції шляху* не буде виконана. Запит одразу завершиться, і HTTP-помилка з `HTTPException` буде надіслана клієнту. Перевага генерації виключення замість повернення значення стане більш очевидною в розділі про залежності та безпеку. diff --git a/docs/uk/docs/tutorial/index.md b/docs/uk/docs/tutorial/index.md index 629b71dec..f89656236 100644 --- a/docs/uk/docs/tutorial/index.md +++ b/docs/uk/docs/tutorial/index.md @@ -54,7 +54,7 @@ $ fastapi dev **ДУЖЕ радимо** написати або скопіювати код, відредагувати його та запустити локально. -Використання його у своєму редакторі – це те, що дійсно показує вам переваги FastAPI, бачите, як мало коду вам потрібно написати, всі перевірки типів, автозаповнення тощо. +Використання його у своєму редакторі - це те, що дійсно показує вам переваги FastAPI, бачите, як мало коду вам потрібно написати, всі перевірки типів, автозаповнення тощо. --- @@ -86,7 +86,7 @@ $ pip install "fastapi[standard]" /// tip | Порада -FastAPI має [офіційне розширення для VS Code](https://marketplace.visualstudio.com/items?itemName=FastAPILabs.fastapi-vscode) (та Cursor), яке надає багато можливостей, включно з переглядачем операцій шляху, пошуком операцій шляху, навігацією CodeLens у тестах (перехід до визначення з тестів), а також розгортанням і журналами FastAPI Cloud — усе безпосередньо з вашого редактора. +FastAPI має [офіційне розширення для VS Code](https://marketplace.visualstudio.com/items?itemName=FastAPILabs.fastapi-vscode) (та Cursor), яке надає багато можливостей, включно з переглядачем операцій шляху, пошуком операцій шляху, навігацією CodeLens у тестах (перехід до визначення з тестів), а також розгортанням і журналами FastAPI Cloud - усе безпосередньо з вашого редактора. /// diff --git a/docs/uk/docs/tutorial/metadata.md b/docs/uk/docs/tutorial/metadata.md index ee1fdaf6d..fd7a13b72 100644 --- a/docs/uk/docs/tutorial/metadata.md +++ b/docs/uk/docs/tutorial/metadata.md @@ -1,6 +1,6 @@ # Метадані та URL-адреси документації { #metadata-and-docs-urls } -Ви можете налаштувати кілька конфігурацій метаданих у Вашому додатку **FastAPI**. +Ви можете налаштувати кілька конфігурацій метаданих у вашому додатку **FastAPI**. ## Метадані для API { #metadata-for-api } @@ -11,7 +11,7 @@ | `title` | `str` | Назва API. | | `summary` | `str` | Короткий підсумок API. Доступно з OpenAPI 3.1.0, FastAPI 0.99.0. | | `description` | `str` | Короткий опис API. Може використовувати Markdown. | -| `version` | `string` | Версія API. Це версія Вашого додатка, а не OpenAPI. Наприклад, `2.5.0`. | +| `version` | `str` | Версія API. Це версія вашого додатка, а не OpenAPI. Наприклад, `2.5.0`. | | `terms_of_service` | `str` | URL до умов використання API. Якщо вказано, має бути у форматі URL. | | `contact` | `dict` | Інформація для контакту з опублікованим API. Може містити кілька полів.
contact поля
ПараметрТипОпис
namestrІдентифікаційне ім'я контактної особи або організації.
urlstrURL, що вказує на контактну інформацію. МАЄ бути у форматі URL.
emailstrАдреса електронної пошти контактної особи або організації. МАЄ бути у форматі адреси електронної пошти.
| | `license_info` | `dict` | Інформація про ліцензію для опублікованого API. Може містити кілька полів.
license_info поля
ПараметрТипОпис
namestrОБОВ'ЯЗКОВО (якщо встановлено license_info). Назва ліцензії для API.
identifierstrЛіцензійний вираз за [SPDX](https://spdx.org/licenses/) для API. Поле identifier взаємовиключне з полем url. Доступно з OpenAPI 3.1.0, FastAPI 0.99.0.
urlstrURL до ліцензії, яка використовується для API. МАЄ бути у форматі URL.
| @@ -32,7 +32,7 @@ ## Ідентифікатор ліцензії { #license-identifier } -З початку використання OpenAPI 3.1.0 та FastAPI 0.99.0 Ви також можете налаштувати `license_info` за допомогою `identifier` замість `url`. +З початку використання OpenAPI 3.1.0 та FastAPI 0.99.0 ви також можете налаштувати `license_info` за допомогою `identifier` замість `url`. Наприклад: @@ -46,7 +46,7 @@ Кожен словник може містити: -* `name` (**обов'язково**): `str` з тією ж назвою тегу, яку Ви використовуєте у параметрі `tags` у Ваших *операціях шляху* та `APIRouter`s. +* `name` (**обов'язково**): `str` з тією ж назвою тегу, яку ви використовуєте у параметрі `tags` у ваших *операціях шляху* та `APIRouter`s. * `description`: `str` з коротким описом тегу. Може містити Markdown і буде показано в інтерфейсі документації. * `externalDocs`: `dict`, який описує зовнішню документацію з такими полями: * `description`: `str` з коротким описом зовнішньої документації. @@ -64,7 +64,7 @@ /// tip | Порада -Вам не потрібно додавати метадані для всіх тегів, які Ви використовуєте. +Вам не потрібно додавати метадані для всіх тегів, які ви використовуєте. /// @@ -74,7 +74,7 @@ {* ../../docs_src/metadata/tutorial004_py310.py hl[21,26] *} -/// info | Інформація +/// note | Примітка Детальніше про теги читайте в розділі [Конфігурація операції шляху](path-operation-configuration.md#tags). @@ -82,7 +82,7 @@ ### Перевірте документацію { #check-the-docs } -Тепер, якщо Ви перевірите документацію, вона покаже всі додаткові метадані: +Тепер, якщо ви перевірите документацію, вона покаже всі додаткові метадані: @@ -96,13 +96,13 @@ За замовчуванням схема OpenAPI надається за адресою `/openapi.json`. -Але Ви можете налаштувати це за допомогою параметра `openapi_url`. +Але ви можете налаштувати це за допомогою параметра `openapi_url`. Наприклад, щоб налаштувати його на `/api/v1/openapi.json`: {* ../../docs_src/metadata/tutorial002_py310.py hl[3] *} -Якщо Ви хочете повністю вимкнути схему OpenAPI, Ви можете встановити `openapi_url=None`, це також вимкне інтерфейси документації, які її використовують. +Якщо ви хочете повністю вимкнути схему OpenAPI, ви можете встановити `openapi_url=None`, це також вимкне інтерфейси документації, які її використовують. ## URL-адреси документації { #docs-urls } diff --git a/docs/uk/docs/tutorial/path-operation-configuration.md b/docs/uk/docs/tutorial/path-operation-configuration.md index 292066c1f..151e79d1e 100644 --- a/docs/uk/docs/tutorial/path-operation-configuration.md +++ b/docs/uk/docs/tutorial/path-operation-configuration.md @@ -12,7 +12,7 @@ Ви можете визначити (HTTP) `status_code`, який буде використано у відповіді вашої «операції шляху». -Можна передати безпосередньо цілий код, наприклад `404`. +Ви можете передати безпосередньо код `int`, наприклад `404`. Якщо ви не пам'ятаєте призначення числових кодів, скористайтеся скороченими константами в `status`: @@ -24,7 +24,7 @@ Ви також можете використати `from starlette import status`. -FastAPI надає той самий `starlette.status` як `fastapi.status` для вашої зручності як розробника. Але він походить безпосередньо зі Starlette. +**FastAPI** надає той самий `starlette.status` як `fastapi.status` для вашої зручності як розробника. Але він походить безпосередньо зі Starlette. /// @@ -40,11 +40,11 @@ FastAPI надає той самий `starlette.status` як `fastapi.status` д ### Мітки з переліками { #tags-with-enums } -У великому застосунку ви можете накопичити багато міток і захочете переконатися, що завжди використовуєте ту саму мітку для пов'язаних «операцій шляху». +У великому застосунку ви можете накопичити **багато міток** і захочете переконатися, що завжди використовуєте **ту саму мітку** для пов'язаних «операцій шляху». У таких випадках має сенс зберігати мітки в `Enum`. -FastAPI підтримує це так само, як і зі звичайними строками: +**FastAPI** підтримує це так само, як і зі звичайними строками: {* ../../docs_src/path_operation_configuration/tutorial002b_py310.py hl[1,8:10,13,18] *} @@ -56,7 +56,7 @@ FastAPI підтримує це так само, як і зі звичайним ## Опис зі строки документації { #description-from-docstring } -Оскільки описи зазвичай довгі та займають кілька рядків, ви можете оголосити опис «операції шляху» у строці документації функції, і FastAPI прочитає його звідти. +Оскільки описи зазвичай довгі та займають кілька рядків, ви можете оголосити опис «операції шляху» у строці документації функції, і **FastAPI** прочитає його звідти. Ви можете писати [Markdown](https://en.wikipedia.org/wiki/Markdown) у строці документації, його буде інтерпретовано та показано коректно (з урахуванням відступів у строці документації). @@ -72,17 +72,17 @@ FastAPI підтримує це так само, як і зі звичайним {* ../../docs_src/path_operation_configuration/tutorial005_py310.py hl[18] *} -/// info | Інформація +/// note | Примітка Зверніть увагу, що `response_description` стосується саме відповіді, а `description` стосується «операції шляху» загалом. /// -/// check | Перевірте +/// tip | Порада OpenAPI визначає, що кожна «операція шляху» потребує опису відповіді. -Тому, якщо ви його не надасте, FastAPI автоматично згенерує «Successful response». +Тому, якщо ви його не надасте, **FastAPI** автоматично згенерує «Successful response». /// @@ -98,7 +98,7 @@ OpenAPI визначає, що кожна «операція шляху» пот -Подивіться, як виглядають застарілі та незастарілі «операції шляху»: +Перевірте, як виглядають застарілі та незастарілі «операції шляху»: diff --git a/docs/uk/docs/tutorial/path-params-numeric-validations.md b/docs/uk/docs/tutorial/path-params-numeric-validations.md index 39397a3b1..8320ee8c4 100644 --- a/docs/uk/docs/tutorial/path-params-numeric-validations.md +++ b/docs/uk/docs/tutorial/path-params-numeric-validations.md @@ -8,7 +8,7 @@ {* ../../docs_src/path_params_numeric_validations/tutorial001_an_py310.py hl[1,3] *} -/// info | Інформація +/// note | Примітка FastAPI додав підтримку `Annotated` (і почав рекомендувати його використання) у версії 0.95.0. @@ -131,7 +131,7 @@ Python нічого не зробить із цією `*`, але розпізн * `lt`: `l`ess `t`han * `le`: `l`ess than or `e`qual -/// info | Інформація +/// note | Примітка `Query`, `Path` та інші класи, які ви побачите пізніше, є підкласами спільного класу `Param`. diff --git a/docs/uk/docs/tutorial/path-params.md b/docs/uk/docs/tutorial/path-params.md index eb05a4412..12fdecae3 100644 --- a/docs/uk/docs/tutorial/path-params.md +++ b/docs/uk/docs/tutorial/path-params.md @@ -20,7 +20,7 @@ У цьому випадку `item_id` оголошено як `int`. -/// check | Перевірте +/// tip | Порада Це дасть вам підтримку редактора всередині функції з перевірками помилок, автодоповненням тощо. @@ -34,7 +34,7 @@ {"item_id":3} ``` -/// check | Перевірте +/// tip | Порада Зверніть увагу, що значення, яке отримала (і повернула) ваша функція, — це `3`, як Python `int`, а не рядок `"3"`. @@ -66,7 +66,7 @@ Та сама помилка з’явиться, якщо ви передасте `float` замість `int`, як у: [http://127.0.0.1:8000/items/4.2](http://127.0.0.1:8000/items/4.2) -/// check | Перевірте +/// tip | Порада Отже, з тим самим оголошенням типу в Python **FastAPI** надає вам валідацію даних. @@ -82,7 +82,7 @@ -/// check | Перевірте +/// tip | Порада Знову ж таки, лише з тим самим оголошенням типу в Python **FastAPI** надає вам автоматичну, інтерактивну документацію (з інтеграцією Swagger UI). diff --git a/docs/uk/docs/tutorial/query-params-str-validations.md b/docs/uk/docs/tutorial/query-params-str-validations.md index afe86d482..610e83f41 100644 --- a/docs/uk/docs/tutorial/query-params-str-validations.md +++ b/docs/uk/docs/tutorial/query-params-str-validations.md @@ -1,4 +1,4 @@ -# Query параметри та валідація рядків { #query-parameters-and-string-validations } +# Параметри запиту та валідація строк { #query-parameters-and-string-validations } **FastAPI** дозволяє оголошувати додаткову інформацію та виконувати валідацію для ваших параметрів. @@ -6,7 +6,7 @@ {* ../../docs_src/query_params_str_validations/tutorial001_py310.py hl[7] *} -Query параметр `q` має тип `str | None`, що означає, що він має тип `str`, але також може бути `None`, і справді, значення за замовчуванням — `None`, тож FastAPI знатиме, що він не є обов'язковим. +Параметр запиту `q` має тип `str | None`, що означає, що він має тип `str`, але також може бути `None`, і справді, значення за замовчуванням - `None`, тож FastAPI знатиме, що він не є обов'язковим. /// note | Примітка @@ -18,7 +18,7 @@ FastAPI знатиме, що значення `q` не є обов’язков ## Додаткова валідація { #additional-validation } -Ми хочемо, щоб навіть якщо `q` є необов’язковим, коли його передають, його довжина не перевищувала 50 символів. +Ми забезпечимо, що навіть якщо `q` є необов’язковим, коли його передають, **його довжина не перевищувала 50 символів**. ### Імпорт `Query` та `Annotated` { #import-query-and-annotated } @@ -29,7 +29,7 @@ FastAPI знатиме, що значення `q` не є обов’язков {* ../../docs_src/query_params_str_validations/tutorial002_an_py310.py hl[1,3] *} -/// info | Інформація +/// note | Примітка FastAPI додав підтримку `Annotated` (і почав рекомендувати його) у версії 0.95.0. @@ -45,7 +45,7 @@ FastAPI додав підтримку `Annotated` (і почав рекомен Зараз саме час використати його разом із FastAPI. 🚀 -Раніше ми мали таку анотацію типу: +Ми мали таку анотацію типу: ```Python q: str | None = None @@ -57,31 +57,31 @@ q: str | None = None q: Annotated[str | None] = None ``` -Обидві ці версії означають одне й те саме: `q` — це параметр, який може бути `str` або `None`, і за замовчуванням має значення `None`. +Обидві ці версії означають одне й те саме: `q` - це параметр, який може бути `str` або `None`, і за замовчуванням має значення `None`. А тепер переходимо до цікавого! 🎉 ## Додавання `Query` до `Annotated` у параметр `q` { #add-query-to-annotated-in-the-q-parameter } -Тепер, коли у нас є `Annotated`, де ми можемо додавати додаткову інформацію (у цьому випадку — додаткову валідацію), додамо `Query` всередину `Annotated` і встановимо параметр `max_length` у `50`: +Тепер, коли у нас є `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 символів. 😎 +Але тепер, додавши `Query(max_length=50)` всередину `Annotated`, ми повідомляємо FastAPI, що хочемо **додаткову валідацію** для цього значення: ми хочемо, щоб воно мало максимум 50 символів. 😎 /// tip | Порада -Тут ми використовуємо `Query()`, оскільки це query параметр. Далі ми розглянемо інші варіанти, як-от `Path()`, `Body()`, `Header()` та `Cookie()`, які приймають ті самі аргументи, що й `Query()`. +Тут ми використовуємо `Query()`, оскільки це **параметр запиту**. Далі ми розглянемо інші варіанти, як-от `Path()`, `Body()`, `Header()` та `Cookie()`, які приймають ті самі аргументи, що й `Query()`. /// Тепер FastAPI: -* Перевірить дані, щоб переконатися, що їхня максимальна довжина — 50 символів -* Покажe чітку помилку клієнту, якщо дані недійсні -* Задокументує параметр в OpenAPI-схемі операції шляху (що відобразиться в автоматично згенерованій документації) +* **Перевірить** дані, щоб переконатися, що їхня максимальна довжина - 50 символів +* Покажe **чітку помилку** клієнту, якщо дані недійсні +* **Задокументує** параметр в *операції шляху* схеми OpenAPI (що відобразиться в **автоматичному інтерфейсі документації**) ## Альтернативний (застарілий) метод: `Query` як значення за замовчуванням { #alternative-old-query-as-the-default-value } @@ -93,7 +93,7 @@ q: Annotated[str | None] = None /// -Раніше ми писали `Query()` як значення за замовчуванням для параметра функції, встановлюючи `max_length` у 50: +Раніше ми писали `Query()` як значення за замовчуванням для параметра функції, встановлюючи параметр `max_length` у 50: {* ../../docs_src/query_params_str_validations/tutorial002_py310.py hl[7] *} @@ -107,19 +107,20 @@ q: str | None = Query(default=None) ...робить параметр необов’язковим зі значенням за замовчуванням `None`, що еквівалентно: + ```Python q: str | None = None ``` -Але у версії з `Query` ми явно вказуємо, що це query параметр. +Але у версії з `Query` ми явно вказуємо, що це параметр запиту. -Далі ми можемо передавати `Query` додаткові параметри. У цьому випадку — параметр `max_length`, який застосовується до рядків: +Далі ми можемо передавати `Query` додаткові параметри. У цьому випадку - параметр `max_length`, який застосовується до строк: ```Python q: str | None = Query(default=None, max_length=50) ``` -Це забезпечить валідацію даних, виведе зрозумілу помилку у разі недійсних даних і задокументує параметр у схемі OpenAPI операції шляху. +Це забезпечить валідацію даних, виведе зрозумілу помилку у разі недійсних даних і задокументує параметр у *операції шляху* схеми OpenAPI. ### `Query` як значення за замовчуванням або всередині `Annotated` { #query-as-the-default-value-or-in-annotated } @@ -149,13 +150,13 @@ q: str = Query(default="rick") ### Переваги використання `Annotated` { #advantages-of-annotated } -Використання `Annotated` є рекомендованим замість задання значення за замовчуванням у параметрах функції, оскільки воно краще з кількох причин. 🤓 +**Використання `Annotated` є рекомендованим** замість задання значення за замовчуванням у параметрах функції, оскільки воно **краще** з кількох причин. 🤓 -Значення за замовчуванням параметра функції є фактичним значенням за замовчуванням, що є більш інтуїтивним у Python загалом. 😌 +**Значення за замовчуванням** **параметра функції** є **фактичним значенням за замовчуванням**, що є більш інтуїтивним у Python загалом. 😌 -Ви можете викликати ту саму функцію в інших місцях без FastAPI, і вона працюватиме очікувано. Якщо параметр є обов’язковим (без значення за замовчуванням), ваш редактор повідомить про помилку, а Python також видасть помилку, якщо ви виконаєте функцію без передавання цього параметра. +Ви можете **викликати** ту саму функцію в **інших місцях** без FastAPI, і вона **працюватиме очікувано**. Якщо параметр є **обов’язковим** (без значення за замовчуванням), ваш **редактор** повідомить про помилку, а **Python** також видасть помилку, якщо ви виконаєте функцію без передавання обов’язкового параметра. -Якщо ви не використовуєте `Annotated`, а використовуєте (старий) стиль значень за замовчуванням, то при виклику цієї функції без FastAPI в інших місцях потрібно пам’ятати передати їй аргументи, щоб вона працювала коректно, інакше значення будуть відрізнятися від очікуваних (наприклад, ви отримаєте `QueryInfo` або щось подібне замість `str`). І ваш редактор не повідомить про помилку, і Python не скаржитиметься під час запуску цієї функції — лише коли операції всередині завершаться помилкою. +Якщо ви не використовуєте `Annotated`, а використовуєте **(старий) стиль значень за замовчуванням**, то при виклику цієї функції без FastAPI в **інших місцях** потрібно **пам’ятати** передати їй аргументи, щоб вона працювала коректно, інакше значення будуть відрізнятися від очікуваних (наприклад, ви отримаєте `QueryInfo` або щось подібне замість `str`). І ваш редактор не повідомить про помилку, і Python не скаржитиметься під час запуску цієї функції - лише коли операції всередині завершаться помилкою. Оскільки `Annotated` може містити кілька анотацій метаданих, тепер ви навіть можете використовувати ту саму функцію з іншими інструментами, такими як [Typer](https://typer.tiangolo.com/). 🚀 @@ -167,7 +168,7 @@ q: str = Query(default="rick") ## Додавання регулярних виразів { #add-regular-expressions } -Ви можете визначити регулярний вираз `pattern`, якому має відповідати параметр: +Ви можете визначити регулярний вираз `pattern`, якому має відповідати параметр: {* ../../docs_src/query_params_str_validations/tutorial004_an_py310.py hl[11] *} @@ -177,7 +178,7 @@ q: str = Query(default="rick") * `fixedquery`: точно відповідає значенню `fixedquery`. * `$`: закінчується тут, після `fixedquery` немає жодних символів. -Якщо ви почуваєтеся розгублено щодо **«regular expression»**, не хвилюйтеся. Це складна тема для багатьох людей. Ви все одно можете робити багато речей без використання регулярних виразів. +Якщо ви почуваєтеся розгублено щодо всіх цих ідей **«регулярного виразу»**, не хвилюйтеся. Це складна тема для багатьох людей. Ви все одно можете робити багато речей без потреби в регулярних виразах. Тепер ви знаєте, що коли вони знадобляться, їх можна застосовувати у **FastAPI**. @@ -185,19 +186,19 @@ q: str = Query(default="rick") Ви можете, звісно, використовувати значення за замовчуванням, відмінні від `None`. -Припустімо, що ви хочете оголосити query параметр `q` з `min_length` `3` і значенням за замовчуванням `"fixedquery"`: +Припустімо, що ви хочете оголосити параметр запиту `q` з `min_length` `3` і значенням за замовчуванням `"fixedquery"`: {* ../../docs_src/query_params_str_validations/tutorial005_an_py310.py hl[9] *} /// note | Примітка -Наявність значення за замовчуванням будь-якого типу, включаючи `None`, робить параметр необов’язковим (not required). +Наявність значення за замовчуванням будь-якого типу, включаючи `None`, робить параметр необов’язковим (не обов’язковим). /// ## Обов’язкові параметри { #required-parameters } -Якщо нам не потрібно оголошувати додаткові валідації або метадані, ми можемо зробити query параметр `q` обов’язковим, просто не вказуючи значення за замовчуванням, наприклад: +Якщо нам не потрібно оголошувати додаткові валідації або метадані, ми можемо зробити параметр запиту `q` обов’язковим, просто не вказуючи значення за замовчуванням, наприклад: ```Python q: str @@ -227,11 +228,11 @@ q: Annotated[str | None, Query(min_length=3)] = None {* ../../docs_src/query_params_str_validations/tutorial006c_an_py310.py hl[9] *} -## Список query параметрів / кілька значень { #query-parameter-list-multiple-values } +## Список параметрів запиту / кілька значень { #query-parameter-list-multiple-values } -Коли ви явно визначаєте query параметр за допомогою `Query`, ви також можете оголосити, що він має приймати список значень, або, іншими словами, кілька значень. +Коли ви явно визначаєте параметр запиту за допомогою `Query`, ви також можете оголосити, що він має приймати список значень, або, іншими словами, кілька значень. -Наприклад, щоб оголосити query параметр `q`, який може з’являтися в URL кілька разів, можна написати: +Наприклад, щоб оголосити параметр запиту `q`, який може з’являтися в URL кілька разів, можна написати: {* ../../docs_src/query_params_str_validations/tutorial011_an_py310.py hl[9] *} @@ -241,7 +242,7 @@ q: Annotated[str | None, Query(min_length=3)] = None http://localhost:8000/items/?q=foo&q=bar ``` -ви отримаєте кілька значень `q` query параметрів (`foo` і `bar`) у вигляді Python `list` у вашій функції операції шляху, у параметрі функції `q`. +ви отримаєте кілька значень *параметрів запиту* `q` (`foo` і `bar`) у вигляді Python `list` у вашій *функції операції шляху*, у *параметрі функції* `q`. Отже, відповідь на цей URL буде: @@ -256,7 +257,7 @@ http://localhost:8000/items/?q=foo&q=bar /// tip | Порада -Щоб оголосити query параметр з типом `list`, як у наведеному вище прикладі, потрібно явно використовувати `Query`, інакше він буде інтерпретований як тіло запиту. +Щоб оголосити параметр запиту з типом `list`, як у наведеному вище прикладі, потрібно явно використовувати `Query`, інакше він буде інтерпретований як тіло запиту. /// @@ -264,7 +265,7 @@ http://localhost:8000/items/?q=foo&q=bar -### Список query параметрів / кілька значень за замовчуванням { #query-parameter-list-multiple-values-with-defaults } +### Список параметрів запиту / кілька значень за замовчуванням { #query-parameter-list-multiple-values-with-defaults } Ви також можете визначити значення за замовчуванням `list`, якщо жодне значення не було передане: @@ -297,7 +298,7 @@ http://localhost:8000/items/ Майте на увазі, що в цьому випадку FastAPI не перевірятиме вміст списку. -Наприклад, `list[int]` перевірятиме (і документуватиме), що вміст списку — цілі числа. Але `list` без уточнення цього не робитиме. +Наприклад, `list[int]` перевірятиме (і документуватиме), що вміст списку - цілі числа. Але `list` без уточнення цього не робитиме. /// @@ -305,7 +306,7 @@ http://localhost:8000/items/ Ви можете додати більше інформації про параметр. -Ця інформація буде включена у згенерований OpenAPI та використана інтерфейсами документації та зовнішніми інструментами. +Ця інформація буде включена у згенерований OpenAPI та використана користувацькими інтерфейсами документації та зовнішніми інструментами. /// note | Примітка @@ -333,9 +334,9 @@ http://localhost:8000/items/ http://127.0.0.1:8000/items/?item-query=foobaritems ``` -Але `item-query` — це некоректна назва змінної в Python. +Але `item-query` - це некоректна назва змінної в Python. -Найближчий допустимий варіант — `item_query`. +Найближчий допустимий варіант - `item_query`. Проте вам потрібно, щоб параметр залишався саме `item-query`... @@ -359,17 +360,17 @@ http://127.0.0.1:8000/items/?item-query=foobaritems ## Виняток параметрів з OpenAPI { #exclude-parameters-from-openapi } -Щоб виключити query параметр зі згенерованої схеми OpenAPI (і, таким чином, з автоматичних систем документації), встановіть параметр `include_in_schema` для `Query` в `False`: +Щоб виключити параметр запиту зі згенерованої схеми OpenAPI (і, таким чином, з автоматичних систем документації), встановіть параметр `include_in_schema` для `Query` в `False`: {* ../../docs_src/query_params_str_validations/tutorial014_an_py310.py hl[10] *} ## Кастомна валідація { #custom-validation } -Можуть бути випадки, коли вам потрібно провести кастомну валідацію, яку не можна реалізувати за допомогою параметрів, показаних вище. +Можуть бути випадки, коли вам потрібно провести **кастомну валідацію**, яку не можна реалізувати за допомогою параметрів, показаних вище. -У таких випадках ви можете використати кастомну функцію-валідатор, яка буде застосована після звичайної валідації (наприклад, після перевірки, що значення є типом `str`). +У таких випадках ви можете використати **кастомну функцію-валідатор**, яка буде застосована після звичайної валідації (наприклад, після перевірки, що значення є типом `str`). -Це можна досягти за допомогою [Pydantic's `AfterValidator`](https://docs.pydantic.dev/latest/concepts/validators/#field-after-validator) в середині `Annotated`. +Це можна досягти за допомогою [Pydantic's `AfterValidator`](https://docs.pydantic.dev/latest/concepts/validators/#field-after-validator) всередині `Annotated`. /// tip | Порада @@ -377,11 +378,11 @@ Pydantic також має [`BeforeValidator`](https://docs.pydantic.dev/latest/ /// -Наприклад, цей кастомний валідатор перевіряє, чи починається ID елемента з `isbn-` для номера книги ISBN або з `imdb-` для ID URL фільму на IMDB: +Наприклад, цей кастомний валідатор перевіряє, чи починається ID предмета з `isbn-` для номера книги ISBN або з `imdb-` для ID URL фільму на IMDB: {* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py hl[5,16:19,24] *} -/// info | Інформація +/// note | Примітка Це доступно з версії Pydantic 2 або вище. 😎 @@ -389,39 +390,39 @@ Pydantic також має [`BeforeValidator`](https://docs.pydantic.dev/latest/ /// tip | Порада -Якщо вам потрібно виконати будь-яку валідацію, яка вимагає взаємодії з будь-яким зовнішнім компонентом, таким як база даних чи інший API, замість цього слід використовувати FastAPI Dependencies — ви дізнаєтесь про них пізніше. +Якщо вам потрібно виконати будь-яку валідацію, яка вимагає взаємодії з будь-яким **зовнішнім компонентом**, таким як база даних чи інший API, замість цього слід використовувати **FastAPI Dependencies** - ви дізнаєтесь про них пізніше. -Ці кастомні валідатори використовуються для речей, які можна перевірити лише з тими самими даними, що надані в запиті. +Ці кастомні валідатори використовуються для речей, які можна перевірити **лише** з **тими самими даними**, що надані в запиті. /// ### Зрозумійте цей код { #understand-that-code } -Головний момент — це використання `AfterValidator` з функцією всередині `Annotated`. Можете пропустити цю частину, якщо хочете. 🤸 +Головний момент - це використання **`AfterValidator` з функцією всередині `Annotated`**. Можете пропустити цю частину, якщо хочете. 🤸 --- Але якщо вам цікаво розібратися в цьому конкретному прикладі коду і вам ще не набридло, ось кілька додаткових деталей. -#### Рядок із `value.startswith()` { #string-with-value-startswith } +#### Строка з `value.startswith()` { #string-with-value-startswith } -Звернули увагу? Рядок із `value.startswith()` може приймати кортеж, і тоді він перевірятиме кожне значення в кортежі: +Звернули увагу? Строка з `value.startswith()` може приймати кортеж, і тоді він перевірятиме кожне значення в кортежі: {* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py ln[16:19] hl[17] *} -#### Випадковий елемент { #a-random-item } +#### Випадковий предмет { #a-random-item } -За допомогою `data.items()` ми отримуємо ітерабельний об'єкт із кортежами, що містять ключ і значення для кожного елемента словника. +За допомогою `data.items()` ми отримуємо ітерабельний об'єкт із кортежами, що містять ключ і значення для кожного предмета словника. Ми перетворюємо цей ітерабельний об'єкт у звичайний `list` за допомогою `list(data.items())`. -Потім, використовуючи `random.choice()`, ми можемо отримати випадкове значення зі списку, тобто отримуємо кортеж із `(id, name)`. Це може бути щось на зразок `("imdb-tt0371724", "The Hitchhiker's Guide to the Galaxy")`. +Потім, використовуючи `random.choice()`, ми можемо отримати **випадкове значення** зі списку, тобто отримуємо кортеж із `(id, name)`. Це може бути щось на зразок `("imdb-tt0371724", "The Hitchhiker's Guide to the Galaxy")`. -Далі ми присвоюємо ці два значення кортежу змінним `id` і `name`. +Далі ми **присвоюємо ці два значення** кортежу змінним `id` і `name`. -Тож, якщо користувач не вказав ID елемента, він все одно отримає випадкову рекомендацію. +Тож, якщо користувач не вказав ID предмета, він все одно отримає випадкову рекомендацію. -...ми робимо все це в одному простому рядку. 🤯 Хіба ви не любите Python? 🐍 +...ми робимо все це в **одному простому рядку**. 🤯 Хіба ви не любите Python? 🐍 {* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py ln[22:30] hl[29] *} @@ -436,7 +437,7 @@ Pydantic також має [`BeforeValidator`](https://docs.pydantic.dev/latest/ * `description` * `deprecated` -Валідації, специфічні для рядків: +Валідації, специфічні для строк: * `min_length` * `max_length` diff --git a/docs/uk/docs/tutorial/query-params.md b/docs/uk/docs/tutorial/query-params.md index b665a620e..d70fb1fe3 100644 --- a/docs/uk/docs/tutorial/query-params.md +++ b/docs/uk/docs/tutorial/query-params.md @@ -1,10 +1,10 @@ -# Query параметри { #query-parameters } +# Параметри запиту { #query-parameters } -Коли ви оголошуєте інші параметри функції, які не є частиною параметрів шляху, вони автоматично інтерпретуються як параметри «query». +Коли ви оголошуєте інші параметри функції, які не є частиною параметрів шляху, вони автоматично інтерпретуються як параметри «запиту». {* ../../docs_src/query_params/tutorial001_py310.py hl[9] *} -Query — це набір пар ключ-значення, що йдуть після символу `?` в URL, розділені символами `&`. +Запит - це набір пар ключ-значення, що йдуть після символу `?` в URL, розділені символами `&`. Наприклад, в URL: @@ -12,25 +12,25 @@ Query — це набір пар ключ-значення, що йдуть пі http://127.0.0.1:8000/items/?skip=0&limit=10 ``` -...параметрами query є: +...параметрами запиту є: * `skip`: зі значенням `0` * `limit`: зі значенням `10` -Оскільки вони є частиною URL, вони «природно» є рядками. +Оскільки вони є частиною URL, вони «природно» є строками. Але коли ви оголошуєте їх із типами Python (у наведеному прикладі як `int`), вони перетворюються на цей тип і проходять перевірку відповідності. -Увесь той самий процес, який застосовується до параметрів шляху, також застосовується до параметрів query: +Увесь той самий процес, який застосовується до параметрів шляху, також застосовується до параметрів запиту: * Підтримка в редакторі (очевидно) -* «парсинг» даних +* «парсинг» даних * Валідація даних * Автоматична документація ## Значення за замовчуванням { #defaults } -Оскільки параметри query не є фіксованою частиною шляху, вони можуть бути необов’язковими та мати значення за замовчуванням. +Оскільки параметри запиту не є фіксованою частиною шляху, вони можуть бути необов’язковими та мати значення за замовчуванням. У наведеному вище прикладі вони мають значення за замовчуванням: `skip=0` і `limit=10`. @@ -59,19 +59,19 @@ http://127.0.0.1:8000/items/?skip=20 ## Необов'язкові параметри { #optional-parameters } -Так само ви можете оголосити необов’язкові параметри query, встановивши для них значення за замовчуванням `None`: +Так само ви можете оголосити необов’язкові параметри запиту, встановивши для них значення за замовчуванням `None`: {* ../../docs_src/query_params/tutorial002_py310.py hl[7] *} У цьому випадку параметр функції `q` буде необов’язковим і за замовчуванням матиме значення `None`. -/// check | Перевірте +/// tip | Порада -Також зверніть увагу, що **FastAPI** достатньо розумний, щоб визначити, що параметр шляху `item_id` є параметром шляху, а `q` — ні, отже, це параметр query. +Також зверніть увагу, що **FastAPI** достатньо розумний, щоб визначити, що параметр шляху `item_id` є параметром шляху, а `q` - ні, отже, це параметр запиту. /// -## Перетворення типу параметра query { #query-parameter-type-conversion } +## Перетворення типу параметра запиту { #query-parameter-type-conversion } Ви також можете оголошувати параметри типу `bool`, і вони будуть автоматично конвертовані: @@ -107,12 +107,12 @@ http://127.0.0.1:8000/items/foo?short=on http://127.0.0.1:8000/items/foo?short=yes ``` -або будь-який інший варіант написання (великі літери, перша літера велика тощо), ваша функція побачить параметр `short` зі значенням `True` типу `bool`. В іншому випадку — `False`. +або будь-який інший варіант написання (великі літери, перша літера велика тощо), ваша функція побачить параметр `short` зі значенням `True` типу `bool`. В іншому випадку - `False`. -## Кілька path і query параметрів { #multiple-path-and-query-parameters } +## Кілька параметрів шляху та запиту { #multiple-path-and-query-parameters } -Ви можете одночасно оголошувати кілька параметрів шляху та параметрів query, **FastAPI** знає, який з них який. +Ви можете одночасно оголошувати кілька параметрів шляху та параметрів запиту, **FastAPI** знає, який з них який. І вам не потрібно оголошувати їх у якомусь конкретному порядку. @@ -120,17 +120,17 @@ http://127.0.0.1:8000/items/foo?short=yes {* ../../docs_src/query_params/tutorial004_py310.py hl[6,8] *} -## Обов’язкові параметри query { #required-query-parameters } +## Обов’язкові параметри запиту { #required-query-parameters } -Коли ви оголошуєте значення за замовчуванням для не-path-параметрів (поки що ми бачили лише параметри query), тоді вони не є обов’язковими. +Коли ви оголошуєте значення за замовчуванням для параметрів, що не є параметрами шляху (поки що ми бачили лише параметри запиту), тоді вони не є обов’язковими. Якщо ви не хочете задавати конкретне значення, а просто зробити параметр необов’язковим, задайте `None` як значення за замовчуванням. -Але якщо ви хочете зробити параметр query обов’язковим, просто не вказуйте для нього значення за замовчуванням: +Але якщо ви хочете зробити параметр запиту обов’язковим, просто не вказуйте для нього значення за замовчуванням: {* ../../docs_src/query_params/tutorial005_py310.py hl[6:7] *} -Тут параметр query `needy` — обов’язковий параметр query типу `str`. +Тут параметр запиту `needy` - обов’язковий параметр запиту типу `str`. Якщо ви відкриєте у браузері URL-адресу: @@ -171,11 +171,11 @@ http://127.0.0.1:8000/items/foo-item?needy=sooooneedy } ``` -І звісно, ви можете визначити деякі параметри як обов’язкові, деякі — зі значенням за замовчуванням, а деякі — повністю необов’язкові: +І звісно, ви можете визначити деякі параметри як обов’язкові, деякі - зі значенням за замовчуванням, а деякі - повністю необов’язкові: {* ../../docs_src/query_params/tutorial006_py310.py hl[8] *} -У цьому випадку є 3 параметри query: +У цьому випадку є 3 параметри запиту: * `needy`, обов’язковий `str`. * `skip`, `int` зі значенням за замовчуванням `0`. diff --git a/docs/uk/docs/tutorial/request-files.md b/docs/uk/docs/tutorial/request-files.md index f81e468d0..0785dd206 100644 --- a/docs/uk/docs/tutorial/request-files.md +++ b/docs/uk/docs/tutorial/request-files.md @@ -2,7 +2,7 @@ Ви можете визначити файли, які будуть завантажуватися клієнтом, використовуючи `File`. -/// info | Інформація +/// note | Примітка Щоб отримувати завантажені файли, спочатку встановіть [`python-multipart`](https://github.com/Kludex/python-multipart). @@ -12,7 +12,7 @@ $ pip install python-multipart ``` -Це необхідно, оскільки завантажені файли передаються у вигляді «form data». +Це необхідно, оскільки завантажені файли передаються як «дані форми». /// @@ -28,9 +28,9 @@ $ pip install python-multipart {* ../../docs_src/request_files/tutorial001_an_py310.py hl[9] *} -/// info | Інформація +/// note | Примітка -`File` — це клас, який безпосередньо успадковує `Form`. +`File` - це клас, який безпосередньо успадковує `Form`. Але пам’ятайте, що коли ви імпортуєте `Query`, `Path`, `File` та інші з `fastapi`, це насправді функції, які повертають спеціальні класи. @@ -42,7 +42,7 @@ $ pip install python-multipart /// -Файли будуть завантажені у вигляді «form data». +Файли будуть завантажені як «дані форми». Якщо ви оголосите тип параметра *функції операції шляху* як `bytes`, **FastAPI** прочитає файл за вас, і ви отримаєте його вміст у вигляді `bytes`. @@ -70,8 +70,8 @@ $ pip install python-multipart `UploadFile` має такі атрибути: -* `filename`: Рядок `str` з оригінальною назвою файлу, який був завантажений (наприклад, `myimage.jpg`). -* `content_type`: Рядок `str` з типом вмісту (MIME type / media type) (наприклад, `image/jpeg`). +* `filename`: Строка `str` з оригінальною назвою файлу, який був завантажений (наприклад, `myimage.jpg`). +* `content_type`: Строка `str` з типом вмісту (MIME type / media type) (наприклад, `image/jpeg`). * `file`: [`SpooledTemporaryFile`](https://docs.python.org/3/library/tempfile.html#tempfile.SpooledTemporaryFile) ([file-like](https://docs.python.org/3/glossary.html#term-file-like-object) об'єкт). Це фактичний файловий об'єкт Python, який ви можете передавати безпосередньо іншим функціям або бібліотекам, що очікують «file-like» об'єкт. `UploadFile` має такі асинхронні `async` методи. Вони всі викликають відповідні методи файлу під капотом (використовуючи внутрішній `SpooledTemporaryFile`). @@ -109,7 +109,7 @@ contents = myfile.file.read() /// -## Що таке «Form Data» { #what-is-form-data } +## Що таке «дані форми» { #what-is-form-data } Спосіб, у який HTML-форми (`
`) надсилають дані на сервер, зазвичай використовує «спеціальне» кодування для цих даних, відмінне від JSON. @@ -121,7 +121,7 @@ contents = myfile.file.read() Але якщо форма містить файли, вона кодується як `multipart/form-data`. Якщо ви використовуєте `File`, **FastAPI** знатиме, що потрібно отримати файли з правильної частини тіла. -Якщо ви хочете дізнатися більше про ці типи кодування та формові поля, ознайомтеся з [MDN web docs для `POST`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST). +Якщо ви хочете дізнатися більше про ці типи кодування та поля форми, ознайомтеся з [MDN web docs для `POST`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST). /// @@ -149,7 +149,7 @@ contents = myfile.file.read() Можна завантажувати кілька файлів одночасно. -Вони будуть пов’язані з одним і тим самим «form field», який передається у вигляді «form data». +Вони будуть пов’язані з одним і тим самим «полем форми», яке передається як «дані форми». Щоб це реалізувати, потрібно оголосити список `bytes` або `UploadFile`: @@ -173,4 +173,4 @@ contents = myfile.file.read() ## Підсумок { #recap } -Використовуйте `File`, `bytes` та `UploadFile`, щоб оголошувати файли для завантаження в запиті, надіслані у вигляді form data. +Використовуйте `File`, `bytes` та `UploadFile`, щоб оголошувати файли для завантаження в запиті, надіслані як дані форми. diff --git a/docs/uk/docs/tutorial/request-form-models.md b/docs/uk/docs/tutorial/request-form-models.md index 6f785016d..c61eeeaab 100644 --- a/docs/uk/docs/tutorial/request-form-models.md +++ b/docs/uk/docs/tutorial/request-form-models.md @@ -2,7 +2,7 @@ У FastAPI ви можете використовувати **Pydantic-моделі** для оголошення **полів форми**. -/// info +/// note | Примітка Щоб використовувати форми, спочатку встановіть [`python-multipart`](https://github.com/Kludex/python-multipart). @@ -14,7 +14,7 @@ $ pip install python-multipart /// -/// note +/// note | Примітка Це підтримується, починаючи з FastAPI версії `0.113.0`. 🤓 @@ -40,7 +40,7 @@ $ pip install python-multipart У деяких особливих випадках (ймовірно, не дуже поширених) ви можете **обмежити** поля форми лише тими, які були оголошені в Pydantic-моделі. І **заборонити** будь-які **додаткові** поля. -/// note +/// note | Примітка Це підтримується, починаючи з FastAPI версії `0.114.0`. 🤓 diff --git a/docs/uk/docs/tutorial/request-forms-and-files.md b/docs/uk/docs/tutorial/request-forms-and-files.md index c6d254808..74de8018c 100644 --- a/docs/uk/docs/tutorial/request-forms-and-files.md +++ b/docs/uk/docs/tutorial/request-forms-and-files.md @@ -2,7 +2,7 @@ Ви можете одночасно визначати файли та поля форми, використовуючи `File` і `Form`. -/// info | Інформація +/// note | Примітка Щоб отримувати завантажені файли та/або дані форми, спочатку встановіть [`python-multipart`](https://github.com/Kludex/python-multipart). diff --git a/docs/uk/docs/tutorial/request-forms.md b/docs/uk/docs/tutorial/request-forms.md index d02b85068..311377908 100644 --- a/docs/uk/docs/tutorial/request-forms.md +++ b/docs/uk/docs/tutorial/request-forms.md @@ -2,7 +2,7 @@ Коли вам потрібно отримувати поля форми замість JSON, ви можете використовувати `Form`. -/// info | Інформація +/// note | Примітка Щоб використовувати форми, спочатку встановіть [`python-multipart`](https://github.com/Kludex/python-multipart). @@ -26,15 +26,15 @@ $ pip install python-multipart {* ../../docs_src/request_forms/tutorial001_an_py310.py hl[9] *} -Наприклад, один зі способів використання специфікації OAuth2 (так званий «password flow») вимагає надсилати `username` та `password` як поля форми. +Наприклад, один зі способів використання специфікації OAuth2 (так званий «потік паролю») вимагає надсилати `username` та `password` як поля форми. специфікація вимагає, щоб ці поля мали точні назви `username` і `password` та надсилалися у вигляді полів форми, а не JSON. З `Form` ви можете оголошувати ті ж конфігурації, що і з `Body` (та `Query`, `Path`, `Cookie`), включаючи валідацію, приклади, псевдоніми (наприклад, `user-name` замість `username`) тощо. -/// info | Інформація +/// note | Примітка -`Form` — це клас, який безпосередньо наслідується від `Body`. +`Form` - це клас, який безпосередньо наслідується від `Body`. /// diff --git a/docs/uk/docs/tutorial/response-model.md b/docs/uk/docs/tutorial/response-model.md index 86f12bff4..a5c297289 100644 --- a/docs/uk/docs/tutorial/response-model.md +++ b/docs/uk/docs/tutorial/response-model.md @@ -72,7 +72,7 @@ FastAPI використовуватиме цей `response_model` для вик {* ../../docs_src/response_model/tutorial002_py310.py hl[7,9] *} -/// info | Інформація +/// note | Примітка Щоб використовувати `EmailStr`, спочатку встановіть [`email-validator`](https://github.com/JoshData/python-email-validator). @@ -182,7 +182,7 @@ FastAPI виконує кілька внутрішніх операцій з Pyd ### Повернути Response напряму { #return-a-response-directly } -Найпоширенішим випадком буде [повернення Response напряму, як пояснюється пізніше у розширеній документації](../advanced/response-directly.md). +Найпоширенішим випадком буде [повернення Response напряму, як пояснюється пізніше у просунутому посібнику користувача](../advanced/response-directly.md). {* ../../docs_src/response_model/tutorial003_02_py310.py hl[8,10:11] *} @@ -251,7 +251,7 @@ FastAPI виконує кілька внутрішніх операцій з Pyd } ``` -/// info | Інформація +/// note | Примітка Ви також можете використовувати: diff --git a/docs/uk/docs/tutorial/response-status-code.md b/docs/uk/docs/tutorial/response-status-code.md index d453510f9..4e49cdc60 100644 --- a/docs/uk/docs/tutorial/response-status-code.md +++ b/docs/uk/docs/tutorial/response-status-code.md @@ -1,5 +1,6 @@ # Код статусу відповіді { #response-status-code } + Так само, як ви можете вказати модель відповіді, ви також можете оголосити HTTP код статусу, що використовується для відповіді, за допомогою параметра `status_code` в будь-якій з *операцій шляху*: * `@app.get()` @@ -18,7 +19,7 @@ Параметр `status_code` приймає число з HTTP кодом статусу. -/// info | Інформація +/// note | Примітка `status_code` також може, як альтернативу, приймати `IntEnum`, наприклад, Python [`http.HTTPStatus`](https://docs.python.org/3/library/http.html#http.HTTPStatus). diff --git a/docs/uk/docs/tutorial/schema-extra-example.md b/docs/uk/docs/tutorial/schema-extra-example.md index 742871e39..734a06d1a 100644 --- a/docs/uk/docs/tutorial/schema-extra-example.md +++ b/docs/uk/docs/tutorial/schema-extra-example.md @@ -1,4 +1,4 @@ -# Декларування прикладів вхідних даних { #declare-request-example-data } +# Декларування прикладів даних запиту { #declare-request-example-data } Ви можете задати приклади даних, які ваш застосунок може отримувати. @@ -24,7 +24,7 @@ /// -/// info | Інформація +/// note | Примітка OpenAPI 3.1.0 (який використовується починаючи з FastAPI 0.99.0) додав підтримку `examples`, що є частиною стандарту **Схеми JSON**. @@ -42,7 +42,7 @@ OpenAPI 3.1.0 (який використовується починаючи з F ## `examples` у Схемі JSON - OpenAPI { #examples-in-json-schema-openapi } -При використанні будь-кого з наступного: +Під час використання будь-чого з наведеного: * `Path()` * `Query()` @@ -109,7 +109,7 @@ OpenAPI 3.1.0 (який використовується починаючи з F * `value`: це сам приклад, який буде показано, наприклад `dict`. * `externalValue`: альтернатива `value`, URL-адреса, що вказує на приклад. Проте це може не підтримуватися такою кількістю інструментів, як `value`. -Використання виглядає так: +Ви можете використати це так: {* ../../docs_src/schema_extra_example/tutorial005_an_py310.py hl[23:49] *} @@ -155,7 +155,7 @@ OpenAPI також додала поля `example` і `examples` до інших * `File()` * `Form()` -/// info | Інформація +/// note | Примітка Цей старий специфічний для OpenAPI параметр `examples` тепер називається `openapi_examples`, починаючи з FastAPI `0.103.0`. @@ -171,7 +171,7 @@ OpenAPI також додала поля `example` і `examples` до інших Це нове поле `examples` у Схемі JSON - це **просто `list`** прикладів, а не `dict` з додатковими метаданими, як в інших місцях OpenAPI (описаних вище). -/// info | Інформація +/// note | Примітка Навіть після релізу OpenAPI 3.1.0 з цією новою простішою інтеграцією зі Схемою JSON, протягом певного часу Swagger UI, інструмент, який надає автоматичну документацію, не підтримував OpenAPI 3.1.0 (тепер підтримує, починаючи з версії 5.0.0 🎉). diff --git a/docs/uk/docs/tutorial/security/first-steps.md b/docs/uk/docs/tutorial/security/first-steps.md index bfe196223..7feee1c02 100644 --- a/docs/uk/docs/tutorial/security/first-steps.md +++ b/docs/uk/docs/tutorial/security/first-steps.md @@ -4,7 +4,7 @@ А **frontend** - на іншому домені або в іншому шляху того ж домену (або у мобільному застосунку). -І ви хочете, щоб frontend міг автентифікуватися в backend, використовуючи ім'я користувача та пароль. +І ви хочете, щоб frontend міг автентифікуватися в backend, використовуючи **ім'я користувача** та **пароль**. Ми можемо використати **OAuth2**, щоб збудувати це з **FastAPI**. @@ -24,7 +24,7 @@ ## Запустіть { #run-it } -/// info | Інформація +/// note | Примітка Пакет [`python-multipart`](https://github.com/Kludex/python-multipart) автоматично встановлюється з **FastAPI**, коли ви виконуєте команду `pip install "fastapi[standard]"`. @@ -40,7 +40,7 @@ $ pip install python-multipart /// -Запустіть приклад: +Запустіть приклад за допомогою:
@@ -60,7 +60,7 @@ $ fastapi dev -/// check | Кнопка Authorize! +/// tip | Кнопка «Authorize»! У вас уже є нова блискуча кнопка «Authorize». @@ -78,7 +78,7 @@ $ fastapi dev /// -Звісно, це не frontend для кінцевих користувачів, але це чудовий інструмент для інтерактивної документації всього вашого API. +Звісно, це не frontend для кінцевих користувачів, але це чудовий автоматичний інструмент для інтерактивного документування всього вашого API. Ним може користуватися команда frontend (якою можете бути і ви самі). @@ -86,11 +86,11 @@ $ fastapi dev І ним також можете користуватися ви самі, щоб налагоджувати, перевіряти та тестувати той самий застосунок. -## Потік паролю { #the-password-flow } +## Потік `password` { #the-password-flow } Тепер повернімося трохи назад і розберімося, що це все таке. -`password` «flow» - це один зі способів («flows»), визначених в OAuth2, для обробки безпеки та автентифікації. +`password` «потік» - це один зі способів («потоків»), визначених в OAuth2, для обробки безпеки та автентифікації. OAuth2 був спроєктований так, щоб backend або API могли бути незалежними від сервера, який автентифікує користувача. @@ -100,7 +100,7 @@ OAuth2 був спроєктований так, щоб backend або API мо - Користувач вводить `username` і `password` у frontend і натискає `Enter`. - Frontend (у браузері користувача) надсилає ці `username` і `password` на специфічну URL-адресу нашого API (оголошену як `tokenUrl="token"`). -- API перевіряє ці `username` і `password` та повертає «токен» (ми ще нічого з цього не реалізували). +- API перевіряє ці `username` і `password` та відповідає «токеном» (ми ще нічого з цього не реалізували). - «Токен» - це просто строка з деяким вмістом, який ми можемо пізніше використати, щоб перевірити цього користувача. - Зазвичай токен налаштований на завершення строку дії через певний час. - Тож користувачу доведеться знову увійти пізніше. @@ -116,11 +116,11 @@ OAuth2 був спроєктований так, щоб backend або API мо **FastAPI** надає кілька інструментів на різних рівнях абстракції, щоб реалізувати ці функції безпеки. -У цьому прикладі ми використаємо **OAuth2** з потоком **Password**, використовуючи токен **Bearer**. Це робиться за допомогою класу `OAuth2PasswordBearer`. +У цьому прикладі ми використаємо **OAuth2** з потоком **Password**, використовуючи **токен носія**. Це робиться за допомогою класу `OAuth2PasswordBearer`. -/// info | Інформація +/// note | Примітка -«Bearer»-токен - не єдиний варіант. +«Токен носія» - не єдиний варіант. Але це найкращий для нашого сценарію. @@ -138,7 +138,7 @@ OAuth2 був спроєктований так, щоб backend або API мо Тут `tokenUrl="token"` відноситься до відносної URL-адреси `token`, яку ми ще не створили. Оскільки це відносна URL-адреса, вона еквівалентна `./token`. -Тому, якщо ваш API розміщений на `https://example.com/`, це буде `https://example.com/token`. А якщо на `https://example.com/api/v1/`, тоді це буде `https://example.com/api/v1/token`. +Оскільки ми використовуємо відносну URL-адресу, якщо ваш API розміщений на `https://example.com/`, це буде `https://example.com/token`. А якщо ваш API розміщений на `https://example.com/api/v1/`, тоді це буде `https://example.com/api/v1/token`. Використання відносної URL-адреси важливе, щоб ваша програма продовжувала працювати навіть у просунутому сценарії, як-от [За представником](../../advanced/behind-a-proxy.md). @@ -148,7 +148,7 @@ OAuth2 був спроєктований так, щоб backend або API мо Незабаром ми також створимо фактичну операцію шляху. -/// info | Інформація +/// note | Примітка Якщо ви дуже строгий «Pythonista», вам може не подобатися стиль імені параметра `tokenUrl` замість `token_url`. @@ -176,7 +176,7 @@ oauth2_scheme(some, parameters) **FastAPI** знатиме, що може використати цю залежність, щоб визначити «схему безпеки» в схемі OpenAPI (і в автоматичній документації API). -/// info | Технічні деталі +/// note | Технічні деталі **FastAPI** знатиме, що може використати клас `OAuth2PasswordBearer` (оголошений у залежності), щоб визначити схему безпеки в OpenAPI, тому що він наслідує `fastapi.security.oauth2.OAuth2`, який своєю чергою наслідує `fastapi.security.base.SecurityBase`. @@ -188,7 +188,7 @@ oauth2_scheme(some, parameters) Вона шукатиме в запиті заголовок `Authorization`, перевірить, чи його значення - це `Bearer ` плюс деякий токен, і поверне токен як `str`. -Якщо заголовка `Authorization` немає або значення не містить токена `Bearer `, вона одразу відповість помилкою зі статус-кодом 401 (`UNAUTHORIZED`). +Якщо заголовка `Authorization` немає або значення не містить токена `Bearer `, вона одразу відповість помилкою з кодом статусу 401 (`UNAUTHORIZED`). Вам навіть не потрібно перевіряти, чи існує токен, щоб повернути помилку. Ви можете бути певні: якщо ваша функція виконується, у параметрі токена буде `str`. diff --git a/docs/uk/docs/tutorial/security/get-current-user.md b/docs/uk/docs/tutorial/security/get-current-user.md index 2371ad9fc..1cd308534 100644 --- a/docs/uk/docs/tutorial/security/get-current-user.md +++ b/docs/uk/docs/tutorial/security/get-current-user.md @@ -1,6 +1,6 @@ # Отримати поточного користувача { #get-current-user } -У попередньому розділі система безпеки (яка базується на системі впровадження залежностей) передавала функції операції шляху `token` як `str`: +У попередньому розділі система безпеки (яка базується на системі впровадження залежностей) передавала *функції операції шляху* `token` як `str`: {* ../../docs_src/security/tutorial001_an_py310.py hl[12] *} @@ -14,7 +14,7 @@ Так само, як ми використовуємо Pydantic для оголошення тіл, ми можемо використовувати його будь-де: -{* ../../docs_src/security/tutorial002_an_py310.py hl[5,12:6] *} +{* ../../docs_src/security/tutorial002_an_py310.py hl[5,12:16] *} ## Створити залежність `get_current_user` { #create-a-get-current-user-dependency } @@ -24,19 +24,19 @@ `get_current_user` матиме залежність із тим самим `oauth2_scheme`, який ми створили раніше. -Так само, як ми робили раніше безпосередньо в операції шляху, наша нова залежність `get_current_user` отримає `token` як `str` від підзалежності `oauth2_scheme`: +Так само, як ми робили раніше безпосередньо в *операції шляху*, наша нова залежність `get_current_user` отримає `token` як `str` від підзалежності `oauth2_scheme`: {* ../../docs_src/security/tutorial002_an_py310.py hl[25] *} ## Отримати користувача { #get-the-user } -`get_current_user` використає (фальшиву) утилітну функцію, яку ми створили, що приймає `token` як `str` і повертає нашу Pydantic-модель `User`: +`get_current_user` використає (фальшиву) утилітну функцію, яку ми створили, що приймає токен як `str` і повертає нашу Pydantic-модель `User`: {* ../../docs_src/security/tutorial002_an_py310.py hl[19:22,26:27] *} ## Впровадити поточного користувача { #inject-the-current-user } -Тепер ми можемо використати той самий `Depends` з нашим `get_current_user` в операції шляху: +Тепер ми можемо використати той самий `Depends` з нашим `get_current_user` в *операції шляху*: {* ../../docs_src/security/tutorial002_an_py310.py hl[31] *} @@ -52,7 +52,7 @@ /// -/// check | Перевірте +/// tip | Порада Те, як спроєктована ця система залежностей, дозволяє мати різні залежності (різні «залежні»), які всі повертають модель `User`. @@ -62,13 +62,13 @@ ## Інші моделі { #other-models } -Тепер ви можете отримувати поточного користувача безпосередньо у функціях операцій шляху та працювати з механізмами безпеки на рівні **впровадження залежностей**, використовуючи `Depends`. +Тепер ви можете отримувати поточного користувача безпосередньо у *функціях операцій шляху* та працювати з механізмами безпеки на рівні **впровадження залежностей**, використовуючи `Depends`. І ви можете використовувати будь-яку модель або дані для вимог безпеки (у цьому випадку Pydantic-модель `User`). -Але ви не обмежені використанням якоїсь конкретної модели даних, класу чи типу. +Але ви не обмежені використанням якоїсь конкретної моделі даних, класу чи типу. -Хочете мати id та email і не мати жодного username у вашій моделі? Без проблем. Ви можете використовувати ті самі інструменти. +Хочете мати `id` та `email` і не мати жодного `username` у вашій моделі? Без проблем. Ви можете використовувати ті самі інструменти. Хочете мати просто `str`? Або лише `dict`? Або безпосередньо екземпляр класу моделі бази даних? Усе працює так само. @@ -78,7 +78,7 @@ ## Розмір коду { #code-size } -Цей приклад може здаватися багатослівним. Майте на увазі, що ми змішуємо безпеку, моделі даних, утилітні функції та операції шляху в одному файлі. +Цей приклад може здаватися багатослівним. Майте на увазі, що ми змішуємо безпеку, моделі даних, утилітні функції та *операції шляху* в одному файлі. Але ось ключовий момент. @@ -86,20 +86,20 @@ І ви можете зробити це настільки складним, наскільки потрібно. І все одно мати це написаним лише один раз, в одному місці. З усією гнучкістю. -Зате ви можете мати тисячі кінцевих точок (операцій шляху), що використовують одну й ту саму систему безпеки. +Зате ви можете мати тисячі кінцевих точок (*операцій шляху*), що використовують одну й ту саму систему безпеки. І всі вони (або будь-яка їхня частина, яку ви захочете) можуть скористатися повторним використанням цих залежностей або будь-яких інших, які ви створите. -І всі ці тисячі операцій шляху можуть бути всього у 3 рядки: +І всі ці тисячі *операцій шляху* можуть бути всього у 3 рядки: {* ../../docs_src/security/tutorial002_an_py310.py hl[30:32] *} ## Підсумок { #recap } -Тепер ви можете отримувати поточного користувача безпосередньо у вашій функції операції шляху. +Тепер ви можете отримувати поточного користувача безпосередньо у вашій *функції операції шляху*. Ми вже на півдорозі. -Потрібно лише додати операцію шляху, щоб користувач/клієнт міг фактично надіслати `username` і `password`. +Потрібно лише додати *операцію шляху*, щоб користувач/клієнт міг фактично надіслати `username` і `password`. Далі саме це. diff --git a/docs/uk/docs/tutorial/security/oauth2-jwt.md b/docs/uk/docs/tutorial/security/oauth2-jwt.md index 64774af6d..1fb53ff41 100644 --- a/docs/uk/docs/tutorial/security/oauth2-jwt.md +++ b/docs/uk/docs/tutorial/security/oauth2-jwt.md @@ -10,7 +10,7 @@ JWT означає «JSON Web Tokens». -Це стандарт кодування об'єкта JSON у довгий щільний рядок без пробілів. Він виглядає так: +Це стандарт кодування об'єкта JSON у довгу щільну строку без пробілів. Він виглядає так: ``` eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c @@ -42,7 +42,7 @@ $ pip install pyjwt
-/// info | Інформація +/// note | Примітка Якщо ви плануєте використовувати алгоритми цифрового підпису на кшталт RSA або ECDSA, слід встановити залежність криптобібліотеки `pyjwt[crypto]`. @@ -168,7 +168,7 @@ $ openssl rand -hex 32 {* ../../docs_src/security/tutorial004_an_py310.py hl[93:110] *} -## Оновіть операцію шляху `/token` { #update-the-token-path-operation } +## Оновіть *операцію шляху* `/token` { #update-the-token-path-operation } Створіть `timedelta` з часом життя токена. @@ -213,7 +213,7 @@ JWT може використовуватися й для інших речей, Username: `johndoe` Password: `secret` -/// check | Перевірте +/// tip | Порада Зверніть увагу, що ніде в коді немає відкритого пароля "`secret`", ми маємо лише хешовану версію. diff --git a/docs/uk/docs/tutorial/security/simple-oauth2.md b/docs/uk/docs/tutorial/security/simple-oauth2.md index 7c83e4c2a..7500792cc 100644 --- a/docs/uk/docs/tutorial/security/simple-oauth2.md +++ b/docs/uk/docs/tutorial/security/simple-oauth2.md @@ -28,11 +28,11 @@ OAuth2 визначає, що під час використання «пото Їх зазвичай використовують для оголошення конкретних прав доступу, наприклад: -- `users:read` або `users:write` — поширені приклади. -- `instagram_basic` використовується Facebook / Instagram. -- `https://www.googleapis.com/auth/drive` використовується Google. +* `users:read` або `users:write` — поширені приклади. +* `instagram_basic` використовується Facebook / Instagram. +* `https://www.googleapis.com/auth/drive` використовується Google. -/// info | Інформація +/// note | Примітка У OAuth2 «scope» — це просто строка, що оголошує конкретний потрібний дозвіл. @@ -56,23 +56,23 @@ OAuth2 визначає, що під час використання «пото `OAuth2PasswordRequestForm` — це клас залежності, що оголошує тіло форми з: -- `username`. -- `password`. -- Необов'язковим полем `scope` як великою строкою, складеною зі строк, розділених пробілами. -- Необов'язковим `grant_type`. +* `username`. +* `password`. +* Необов'язковим полем `scope` як великою строкою, складеною зі строк, розділених пробілами. +* Необов'язковим `grant_type`. /// tip | Порада -Специфікація OAuth2 насправді вимагає поле `grant_type` із фіксованим значенням `password`, але `OAuth2PasswordRequestForm` цього не примушує. +Специфікація OAuth2 насправді *вимагає* поле `grant_type` із фіксованим значенням `password`, але `OAuth2PasswordRequestForm` цього не примушує. Якщо вам потрібно це примусити, використовуйте `OAuth2PasswordRequestFormStrict` замість `OAuth2PasswordRequestForm`. /// -- Необов'язковим `client_id` (для нашого прикладу не потрібно). -- Необов'язковим `client_secret` (для нашого прикладу не потрібно). +* Необов'язковим `client_id` (для нашого прикладу не потрібно). +* Необов'язковим `client_secret` (для нашого прикладу не потрібно). -/// info | Інформація +/// note | Примітка `OAuth2PasswordRequestForm` — не спеціальний клас для **FastAPI**, як `OAuth2PasswordBearer`. @@ -132,7 +132,7 @@ OAuth2 визначає, що під час використання «пото `UserInDB(**user_dict)` означає: -Передати ключі та значення з `user_dict` безпосередньо як аргументи ключ-значення, еквівалентно до: +*Передати ключі та значення з `user_dict` безпосередньо як аргументи ключ-значення, еквівалентно до:* ```Python UserInDB( @@ -144,9 +144,9 @@ UserInDB( ) ``` -/// info | Інформація +/// note | Примітка -Для повнішого пояснення `**user_dict` перегляньте [документацію для **Додаткових моделей**](../extra-models.md#about-user-in-dict). +Для повнішого пояснення `**user_dict` перегляньте [документацію для **Додаткових моделей**](../extra-models.md#about-user-in-model-dump). /// @@ -186,7 +186,7 @@ UserInDB( Тепер оновимо наші залежності. -Ми хочемо отримати `current_user` лише якщо цей користувач активний. +Ми хочемо отримати `current_user` *лише* якщо цей користувач активний. Тому створимо додаткову залежність `get_current_active_user`, яка своєю чергою використовує як залежність `get_current_user`. @@ -196,11 +196,11 @@ UserInDB( {* ../../docs_src/security/tutorial003_an_py310.py hl[58:66,69:74,94] *} -/// info | Інформація +/// note | Примітка Додатковий заголовок `WWW-Authenticate` зі значенням `Bearer`, який ми тут повертаємо, також є частиною специфікації. -Будь-який HTTP (помилка) зі статус-кодом 401 «UNAUTHORIZED» також має повертати заголовок `WWW-Authenticate`. +Будь-який HTTP (помилка) з кодом статусу 401 «UNAUTHORIZED» також має повертати заголовок `WWW-Authenticate`. У випадку токенів носія (наш випадок) значенням цього заголовка має бути `Bearer`. diff --git a/docs/uk/docs/tutorial/server-sent-events.md b/docs/uk/docs/tutorial/server-sent-events.md index 8234085cf..ffb56e3cb 100644 --- a/docs/uk/docs/tutorial/server-sent-events.md +++ b/docs/uk/docs/tutorial/server-sent-events.md @@ -4,7 +4,7 @@ Це подібно до [Потік JSON Lines](stream-json-lines.md), але використовує формат `text/event-stream`, який нативно підтримується браузерами через [API `EventSource`](https://developer.mozilla.org/en-US/docs/Web/API/EventSource). -/// info | Інформація +/// note | Примітка Додано у FastAPI 0.135.0. @@ -81,7 +81,7 @@ FastAPI подбає про коректне виконання, щоб воно ## Сирі дані { #raw-data } -Якщо потрібно надіслати дані **без** кодування в JSON, використовуйте `raw_data` замість `data`. +Якщо потрібно надіслати дані без кодування в JSON, використовуйте `raw_data` замість `data`. Це корисно для надсилання попередньо відформатованого тексту, рядків логів або спеціальних значень «значення-сторож», як-от `[DONE]`. @@ -103,7 +103,7 @@ FastAPI подбає про коректне виконання, щоб воно ## SSE з POST { #sse-with-post } -SSE працює з **будь-яким HTTP-методом**, не лише з `GET`. +SSE працює з будь-яким HTTP-методом, не лише з `GET`. Це корисно для протоколів на кшталт [MCP](https://modelcontextprotocol.io), які транслюють SSE через `POST`: @@ -113,8 +113,8 @@ SSE працює з **будь-яким HTTP-методом**, не лише з FastAPI реалізує деякі найкращі практики SSE «з коробки». -- Надсилати **коментар «keep alive» `ping`** кожні 15 секунд, коли не було жодного повідомлення, щоб запобігти закриттю з'єднання деякими проксі, як рекомендовано у [Специфікації HTML: Події, надіслані сервером](https://html.spec.whatwg.org/multipage/server-sent-events.html#authoring-notes). -- Встановити заголовок `Cache-Control: no-cache`, щоб **запобігти кешуванню** потоку. -- Встановити спеціальний заголовок `X-Accel-Buffering: no`, щоб **запобігти буферизації** у деяких проксі, наприклад Nginx. +- Надсилати коментар «keep alive» `ping` кожні 15 секунд, коли не було жодного повідомлення, щоб запобігти закриттю з'єднання деякими проксі, як рекомендовано у [Специфікації HTML: Події, надіслані сервером](https://html.spec.whatwg.org/multipage/server-sent-events.html#authoring-notes). +- Встановити заголовок `Cache-Control: no-cache`, щоб запобігти кешуванню потоку. +- Встановити спеціальний заголовок `X-Accel-Buffering: no`, щоб запобігти буферизації у деяких проксі, наприклад Nginx. Вам не потрібно нічого з цим робити, воно працює «з коробки». 🤓 diff --git a/docs/uk/docs/tutorial/sql-databases.md b/docs/uk/docs/tutorial/sql-databases.md index 57b67226a..ff294052c 100644 --- a/docs/uk/docs/tutorial/sql-databases.md +++ b/docs/uk/docs/tutorial/sql-databases.md @@ -1,6 +1,6 @@ # SQL (реляційні) бази даних { #sql-relational-databases } -**FastAPI** не вимагає від вас використовувати SQL (реляційну) базу даних. Але ви можете скористатися будь-якою базою даних, яку забажаєте. +**FastAPI** не вимагає від вас використовувати SQL (реляційну) базу даних. Але ви можете скористатися **будь-якою базою даних**, яку забажаєте. Тут ми розглянемо приклад з [SQLModel](https://sqlmodel.tiangolo.com/). @@ -8,7 +8,7 @@ /// tip | Порада -Ви можете використовувати будь-яку іншу бібліотеку для SQL або NoSQL баз (інколи їх називають "ORMs"), FastAPI нічого не нав’язує. 😎 +Ви можете використовувати будь-яку іншу бібліотеку для SQL або NoSQL баз (інколи їх називають «ORMs»), FastAPI нічого не нав’язує. 😎 /// @@ -65,7 +65,7 @@ $ pip install sqlmodel * `Field(primary_key=True)` каже SQLModel, що `id` - це **первинний ключ** у SQL базі даних (більше про первинні ключі в SQL див. у документації SQLModel). - Примітка: Ми використовуємо `int | None` для поля первинного ключа, щоб у Python-коді можна було створити об’єкт без `id` (`id=None`), припускаючи, що база даних згенерує його під час збереження. SQLModel розуміє, що `id` надасть база даних, і визначає стовпець як ненульовий `INTEGER` у схемі бази даних. Докладніше див. [документацію SQLModel про первинні ключі](https://sqlmodel.tiangolo.com/tutorial/create-db-and-table/#primary-key-id). + **Примітка:** Ми використовуємо `int | None` для поля первинного ключа, щоб у Python-коді можна було створити об’єкт без `id` (`id=None`), припускаючи, що база даних згенерує його під час збереження. SQLModel розуміє, що `id` надасть база даних, і визначає стовпець як ненульовий `INTEGER` у схемі бази даних. Докладніше див. [документацію SQLModel про первинні ключі](https://sqlmodel.tiangolo.com/tutorial/create-db-and-table/#primary-key-id). * `Field(index=True)` каже SQLModel створити **SQL-індекс** для цього стовпця, що дозволить швидше виконувати пошук у базі даних під час читання даних, відфільтрованих за цим стовпцем. diff --git a/docs/uk/docs/tutorial/static-files.md b/docs/uk/docs/tutorial/static-files.md index 2141744c3..26c3c592a 100644 --- a/docs/uk/docs/tutorial/static-files.md +++ b/docs/uk/docs/tutorial/static-files.md @@ -2,10 +2,18 @@ Ви можете автоматично надавати статичні файли з каталогу, використовуючи `StaticFiles`. +/// tip | Порада + +Якщо вам потрібно розмістити фронтенд, натомість використовуйте `app.frontend()`, прочитайте про це у [Frontend](frontend.md). + +`app.frontend()` використовує `StaticFiles` всередині, з кількома додатковими перевагами для фронтендів, як-от обробка клієнтської маршрутизації. + +/// + ## Використання `StaticFiles` { #use-staticfiles } * Імпортуйте `StaticFiles`. -* «Під'єднати» екземпляр `StaticFiles()` з вказанням необхідного шляху. +* «Змонтуйте» екземпляр `StaticFiles()` у певному шляху. {* ../../docs_src/static_files/tutorial001_py310.py hl[2,6] *} @@ -17,24 +25,24 @@ /// -### Що таке «Під'єднання» { #what-is-mounting } +### Що таке «Монтування» { #what-is-mounting } -«Під'єднання» означає додавання повноцінного «незалежного» застосунку за певним шляхом, який потім обробляє всі під шляхи. +«Монтування» означає додавання повноцінного «незалежного» застосунку за певним шляхом, який потім відповідає за обробку всіх підшляхів. -Це відрізняється від використання `APIRouter`, оскільки під'єднаний застосунок є повністю незалежним. OpenAPI та документація вашого основного застосунку не будуть знати нічого про ваш під'єднаний застосунок тощо. +Це відрізняється від використання `APIRouter`, оскільки змонтований застосунок є повністю незалежним. OpenAPI та документація вашого основного застосунку не включатимуть нічого зі змонтованого застосунку тощо. -Ви можете дізнатися більше про це в [Посібнику для просунутих користувачів](../advanced/index.md). +Ви можете дізнатися більше про це в [Просунутому посібнику користувача](../advanced/index.md). ## Деталі { #details } -Перше `"/static"` вказує на під шлях, за яким буде «під'єднано» цей новий «підзастосунок». Тому будь-який шлях, який починається з `"/static"`, буде оброблятися ним. +Перше `"/static"` стосується підшляху, на якому буде «змонтовано» цей «підзастосунок». Тому будь-який шлях, який починається з `"/static"`, буде оброблятися ним. `directory="static"` визначає назву каталогу, що містить ваші статичні файли. -`name="static"` це ім'я, яке можна використовувати всередині **FastAPI**. +`name="static"` надає йому ім'я, яке можна використовувати всередині **FastAPI**. Усі ці параметри можуть бути іншими за "`static`", налаштуйте їх відповідно до потреб і особливостей вашого застосунку. ## Додаткова інформація { #more-info } -Детальніше про налаштування та можливості можна дізнатися в [документації Starlette про статичні файли](https://www.starlette.dev/staticfiles/). +Для отримання додаткової інформації та параметрів перевірте [документацію Starlette про Static Files](https://www.starlette.dev/staticfiles/). diff --git a/docs/uk/docs/tutorial/stream-json-lines.md b/docs/uk/docs/tutorial/stream-json-lines.md index f7be4a1b2..488e36e75 100644 --- a/docs/uk/docs/tutorial/stream-json-lines.md +++ b/docs/uk/docs/tutorial/stream-json-lines.md @@ -2,7 +2,7 @@ У вас може бути послідовність даних, яку ви хочете надсилати у **«потоці»**, це можна зробити за допомогою **JSON Lines**. -/// info | Інформація +/// note | Примітка Додано в FastAPI 0.134.0. @@ -48,7 +48,7 @@ sequenceDiagram Це дуже схоже на масив JSON (еквівалент списку Python), але замість того, щоб бути загорнутим у `[]` і мати `,` між елементами, тут є **по одному об’єкту JSON на рядок**, вони розділені символом нового рядка. -/// info | Інформація +/// note | Примітка Важливо те, що ваш застосунок зможе по черзі створювати кожен рядок, поки клієнт споживає попередні рядки. diff --git a/docs/uk/docs/tutorial/testing.md b/docs/uk/docs/tutorial/testing.md index ccae2303a..393855a0c 100644 --- a/docs/uk/docs/tutorial/testing.md +++ b/docs/uk/docs/tutorial/testing.md @@ -8,7 +8,7 @@ ## Використання `TestClient` { #using-testclient } -/// info | Інформація +/// note | Примітка Щоб використовувати `TestClient`, спочатку встановіть [`httpx`](https://www.python-httpx.org). @@ -52,7 +52,7 @@ $ pip install httpx /// tip | Порада -Якщо ви хочете викликати `async`-функції у ваших тестах, окрім відправлення запитів до вашого застосунку FastAPI (наприклад, асинхронні функції роботи з базою даних), перегляньте [Async Tests](../advanced/async-tests.md) у розширеному керівництві. +Якщо ви хочете викликати `async`-функції у ваших тестах, окрім відправлення запитів до вашого застосунку FastAPI (наприклад, асинхронні функції роботи з базою даних), перегляньте [Асинхронні тести](../advanced/async-tests.md) у просунутому навчальному посібнику. /// @@ -64,7 +64,7 @@ $ pip install httpx ### Файл застосунку **FastAPI** { #fastapi-app-file } -Припустимо, у вас є структура файлів, описана в розділі [Bigger Applications](bigger-applications.md): +Припустимо, у вас є структура файлів, описана в розділі [Більші застосунки](bigger-applications.md): ``` . @@ -130,25 +130,25 @@ $ pip install httpx {* ../../docs_src/app_testing/app_b_an_py310/test_main.py *} -Коли вам потрібно передати клієнту інформацію в запиті, але ви не знаєте, як це зробити, ви можете пошукати (Google), як це зробити в `httpx`, або навіть як це зробити з `requests`, оскільки дизайн HTTPX базується на дизайні Requests. +Коли вам потрібно, щоб клієнт передав інформацію в запиті, але ви не знаєте, як це зробити, ви можете пошукати (Google), як це зробити в `httpx`, або навіть як це зробити з `requests`, оскільки дизайн HTTPX базується на дизайні Requests. Далі ви просто повторюєте ці ж дії у ваших тестах. Наприклад: -* Щоб передати *path* або *query* параметр, додайте його безпосередньо до URL. +* Щоб передати параметр *шляху* або *запиту*, додайте його безпосередньо до URL. * Щоб передати тіло JSON, передайте Python-об'єкт (наприклад, `dict`) у параметр `json`. -* Якщо потрібно надіслати *Form Data* замість JSON, використовуйте параметр `data`. -* Щоб передати заголовки *headers*, використовуйте `dict` у параметрі `headers`. -* Для *cookies* використовуйте `dict` у параметрі `cookies`. +* Якщо потрібно надіслати *дані форми* замість JSON, використовуйте параметр `data`. +* Щоб передати *заголовки*, використовуйте `dict` у параметрі `headers`. +* Для *кукі* використовуйте `dict` у параметрі `cookies`. Докладніше про передачу даних у бекенд (за допомогою `httpx` або `TestClient`) можна знайти в [документації HTTPX](https://www.python-httpx.org). -/// info | Інформація +/// note | Примітка Зверніть увагу, що `TestClient` отримує дані, які можна конвертувати в JSON, а не Pydantic-моделі. -Якщо у вас є Pydantic-модель у тесті, і ви хочете передати її дані в застосунок під час тестування, ви можете використати `jsonable_encoder`, описаний у розділі [JSON Compatible Encoder](encoder.md). +Якщо у вас є Pydantic-модель у тесті, і ви хочете передати її дані в застосунок під час тестування, ви можете використати `jsonable_encoder`, описаний у розділі [JSON-сумісний кодувальник](encoder.md). /// diff --git a/docs/uk/docs/virtual-environments.md b/docs/uk/docs/virtual-environments.md index 26ad6b0cb..57f3e90df 100644 --- a/docs/uk/docs/virtual-environments.md +++ b/docs/uk/docs/virtual-environments.md @@ -1,6 +1,6 @@ # Віртуальні середовища { #virtual-environments } -Коли ви працюєте над проєктами Python, вам, імовірно, слід використовувати віртуальне середовище (або схожий механізм), щоб ізолювати пакети, які ви встановлюєте для кожного проєкту. +Коли ви працюєте над проєктами Python, вам, імовірно, слід використовувати **віртуальне середовище** (або схожий механізм), щоб ізолювати пакети, які ви встановлюєте для кожного проєкту. /// note | Примітка @@ -10,19 +10,19 @@ /// tip | Порада -Віртуальне середовище відрізняється від змінної оточення. +**Віртуальне середовище** відрізняється від **змінної оточення**. -Змінна оточення - це змінна в системі, яку можуть використовувати програми. +**Змінна оточення** - це змінна в системі, яку можуть використовувати програми. -Віртуальне середовище - це каталог із файлами в ньому. +**Віртуальне середовище** - це каталог із файлами в ньому. /// /// note | Примітка -На цій сторінці ви дізнаєтеся, як використовувати віртуальні середовища і як вони працюють. +На цій сторінці ви дізнаєтеся, як використовувати **віртуальні середовища** і як вони працюють. -Якщо ви готові прийняти інструмент, що керує всім за вас (включно з установленням Python), спробуйте [uv](https://github.com/astral-sh/uv). +Якщо ви готові прийняти **інструмент, що керує всім** за вас (включно з установленням Python), спробуйте [uv](https://github.com/astral-sh/uv). /// @@ -53,11 +53,11 @@ $ cd awesome-project ## Створіть віртуальне середовище { #create-a-virtual-environment } -Коли ви починаєте працювати над проєктом Python уперше, створіть віртуальне середовище у вашому проєкті **у вашому проєкті**. +Коли ви починаєте працювати над проєктом Python **уперше**, створіть віртуальне середовище **у вашому проєкті**. /// tip | Порада -Це потрібно робити лише один раз на проєкт, не щоразу, коли ви працюєте. +Це потрібно робити лише **один раз на проєкт**, не щоразу, коли ви працюєте. /// @@ -120,7 +120,7 @@ $ uv venv /// tip | Порада -Робіть це щоразу, коли ви починаєте нову сесію термінала для роботи над проєктом. +Робіть це **щоразу**, коли ви починаєте **нову сесію термінала** для роботи над проєктом. /// @@ -164,9 +164,9 @@ $ source .venv/Scripts/activate /// tip | Порада -Кожного разу, коли ви встановлюєте новий пакет у це середовище, активуйте середовище знову. +Кожного разу, коли ви встановлюєте **новий пакет** у це середовище, **активуйте** середовище знову. -Це гарантує, що якщо ви використовуєте програму термінала (CLI), встановлену цим пакетом, ви використовуєте саме ту з вашого віртуального середовища, а не будь-яку іншу, яка може бути встановлена глобально, імовірно з іншою версією, ніж вам потрібно. +Це гарантує, що якщо ви використовуєте **програму термінала (CLI)**, встановлену цим пакетом, ви використовуєте саме ту з вашого віртуального середовища, а не будь-яку іншу, яка може бути встановлена глобально, імовірно з іншою версією, ніж вам потрібно. /// @@ -176,7 +176,7 @@ $ source .venv/Scripts/activate /// tip | Порада -Це необов'язково, але це гарний спосіб перевірити, що все працює як очікується і ви використовуєте саме те віртуальне середовище, яке планували. +Це **необов'язково**, але це гарний спосіб **перевірити**, що все працює як очікується і ви використовуєте саме те віртуальне середовище, яке планували. /// @@ -220,13 +220,13 @@ C:\Users\user\code\awesome-project\.venv\Scripts\python /// -Якщо ви використовуєте `pip` для встановлення пакетів (він іде за замовчуванням із Python), вам слід оновити його до найновішої версії. +Якщо ви використовуєте `pip` для встановлення пакетів (він іде за замовчуванням із Python), вам слід **оновити** його до найновішої версії. Багато дивних помилок під час встановлення пакета вирішуються тим, що спочатку оновлюють `pip`. /// tip | Порада -Зазвичай це роблять один раз, відразу після створення віртуального середовища. +Зазвичай це роблять **один раз**, відразу після створення віртуального середовища. /// @@ -264,7 +264,7 @@ $ python -m ensurepip --upgrade ## Додайте `.gitignore` { #add-gitignore } -Якщо ви використовуєте Git (варто це робити), додайте файл `.gitignore`, щоб виключити з Git усе у вашому `.venv`. +Якщо ви використовуєте **Git** (варто це робити), додайте файл `.gitignore`, щоб виключити з Git усе у вашому `.venv`. /// tip | Порада @@ -274,7 +274,7 @@ $ python -m ensurepip --upgrade /// tip | Порада -Зробіть це один раз, відразу після створення віртуального середовища. +Зробіть це **один раз**, відразу після створення віртуального середовища. /// @@ -308,9 +308,9 @@ $ echo "*" > .venv/.gitignore /// tip | Порада -Робіть це один раз під час встановлення або оновлення пакетів, потрібних вашому проєкту. +Робіть це **один раз** під час встановлення або оновлення пакетів, потрібних вашому проєкту. -Якщо вам потрібно оновити версію або додати новий пакет, ви зробите це знову. +Якщо вам потрібно оновити версію або додати новий пакет, ви **зробите це знову**. /// @@ -421,13 +421,13 @@ Hello World /// tip | Порада -Зазвичай це потрібно робити лише один раз, коли ви створюєте віртуальне середовище. +Зазвичай це потрібно робити лише **один раз**, коли ви створюєте віртуальне середовище. /// ## Деактивуйте віртуальне середовище { #deactivate-the-virtual-environment } -Коли ви завершили роботу над проєктом, ви можете деактивувати віртуальне середовище. +Коли ви завершили роботу над проєктом, ви можете **деактивувати** віртуальне середовище.
@@ -443,6 +443,8 @@ $ deactivate Тепер ви готові почати працювати над вашим проєктом. + + /// tip | Порада Хочете зрозуміти, що це все було вище? @@ -455,33 +457,33 @@ $ deactivate Щоб працювати з FastAPI, вам потрібно встановити [Python](https://www.python.org/). -Після цього вам потрібно буде встановити FastAPI та інші пакети, які ви хочете використовувати. +Після цього вам потрібно буде **встановити** FastAPI та інші **пакети**, які ви хочете використовувати. Для встановлення пакетів зазвичай використовують команду `pip`, що постачається з Python (або схожі альтернативи). -Однак, якщо ви просто користуватиметеся `pip` напряму, пакети встановлюватимуться у ваше глобальне середовище Python (глобальну інсталяцію Python). +Однак, якщо ви просто користуватиметеся `pip` напряму, пакети встановлюватимуться у ваше **глобальне середовище Python** (глобальну інсталяцію Python). ### Проблема { #the-problem } То в чому ж проблема встановлення пакетів у глобальне середовище Python? -З часом ви, вірогідно, писатимете багато різних програм, які залежать від різних пакетів. І деякі з цих ваших проєктів залежатимуть від різних версій одного й того ж пакета. 😱 +З часом ви, вірогідно, писатимете багато різних програм, які залежать від **різних пакетів**. І деякі з цих ваших проєктів залежатимуть від **різних версій** одного й того ж пакета. 😱 -Наприклад, ви можете створити проєкт із назвою `philosophers-stone`, ця програма залежить від іншого пакета з назвою `harry`, використовуючи версію `1`. Тож вам потрібно встановити `harry`. +Наприклад, ви можете створити проєкт із назвою `philosophers-stone`, ця програма залежить від іншого пакета з назвою **`harry`, використовуючи версію `1`**. Тож вам потрібно встановити `harry`. ```mermaid flowchart LR stone(philosophers-stone) -->|requires| harry-1[harry v1] ``` -Потім, трохи згодом, ви створюєте інший проєкт із назвою `prisoner-of-azkaban`, і цей проєкт також залежить від `harry`, але йому потрібна версія `harry` `3`. +Потім, трохи згодом, ви створюєте інший проєкт із назвою `prisoner-of-azkaban`, і цей проєкт також залежить від `harry`, але йому потрібна **версія `harry` `3`**. ```mermaid flowchart LR azkaban(prisoner-of-azkaban) --> |requires| harry-3[harry v3] ``` -Але тепер проблема в тому, що якщо ви встановлюєте пакети глобально (у глобальне середовище), а не у локальне віртуальне середовище, вам доведеться вибирати, яку версію `harry` встановити. +Але тепер проблема в тому, що якщо ви встановлюєте пакети глобально (у глобальне середовище), а не у локальне **віртуальне середовище**, вам доведеться вибирати, яку версію `harry` встановити. Якщо ви хочете запустити `philosophers-stone`, вам спочатку потрібно встановити `harry` версії `1`, наприклад, так: @@ -517,7 +519,7 @@ $ pip install "harry==3" У підсумку у вас буде встановлено `harry` версії `3` у глобальному середовищі Python. -А якщо ви знову спробуєте запустити `philosophers-stone`, є шанс, що він не працюватиме, тому що йому потрібен `harry` версії `1`. +А якщо ви знову спробуєте запустити `philosophers-stone`, є шанс, що він **не працюватиме**, тому що йому потрібен `harry` версії `1`. ```mermaid flowchart LR @@ -536,13 +538,13 @@ flowchart LR /// tip | Порада -У пакетах Python дуже поширена практика намагатися якнайкраще уникати несумісних змін у нових версіях, але краще підстрахуватися та встановлювати новіші версії свідомо і тоді, коли ви можете запустити тести, щоб перевірити, що все працює коректно. +У пакетах Python дуже поширена практика намагатися якнайкраще **уникати несумісних змін** у **нових версіях**, але краще підстрахуватися та встановлювати новіші версії свідомо і тоді, коли ви можете запустити тести, щоб перевірити, що все працює коректно. /// -Тепер уявіть те саме з багатьма іншими пакетами, від яких залежать усі ваші проєкти. Це дуже складно керувати. І ви, імовірно, запускатимете деякі проєкти з деякими несумісними версіями пакетів і не розумітимете, чому щось не працює. +Тепер уявіть те саме з **багатьма** іншими **пакетами**, від яких залежать усі ваші **проєкти**. Це дуже складно керувати. І ви, імовірно, запускатимете деякі проєкти з деякими **несумісними версіями** пакетів і не розумітимете, чому щось не працює. -Також, залежно від вашої операційної системи (напр., Linux, Windows, macOS), у ній може бути вже встановлений Python. І в такому разі, імовірно, уже будуть попередньо встановлені деякі пакети з певними версіями, потрібними вашій системі. Якщо ви встановлюєте пакети в глобальне середовище Python, ви можете зламати деякі програми, що постачаються з вашою операційною системою. +Також, залежно від вашої операційної системи (напр., Linux, Windows, macOS), у ній може бути вже встановлений Python. І в такому разі, імовірно, уже будуть попередньо встановлені деякі пакети з певними версіями, **потрібними вашій системі**. Якщо ви встановлюєте пакети в глобальне середовище Python, ви можете **зламати** деякі програми, що постачаються з вашою операційною системою. ## Де встановлюються пакети { #where-are-packages-installed } @@ -564,17 +566,17 @@ $ pip install "fastapi[standard]" Це завантажить стиснений файл з кодом FastAPI, зазвичай із [PyPI](https://pypi.org/project/fastapi/). -Також будуть завантажені файли для інших пакетів, від яких залежить FastAPI. +Також будуть **завантажені** файли для інших пакетів, від яких залежить FastAPI. -Потім усе це буде розпаковано та покладено в каталог на вашому комп'ютері. +Потім усе це буде **розпаковано** та покладено в каталог на вашому комп'ютері. -Типово ці завантажені та розпаковані файли будуть покладені в каталог, що постачається з вашою інсталяцією Python, це глобальне середовище. +Типово ці завантажені та розпаковані файли будуть покладені в каталог, що постачається з вашою інсталяцією Python, це **глобальне середовище**. ## Що таке віртуальні середовища { #what-are-virtual-environments } -Рішенням проблеми з наявністю всіх пакетів у глобальному середовищі є використання віртуального середовища для кожного проєкту, над яким ви працюєте. +Рішенням проблеми з наявністю всіх пакетів у глобальному середовищі є використання **віртуального середовища для кожного проєкту**, над яким ви працюєте. -Віртуальне середовище - це каталог, дуже схожий на глобальний, у якому ви можете встановлювати пакети для конкретного проєкту. +Віртуальне середовище - це **каталог**, дуже схожий на глобальний, у якому ви можете встановлювати пакети для конкретного проєкту. Таким чином кожен проєкт матиме власне віртуальне середовище (каталог `.venv`) із власними пакетами. @@ -637,7 +639,7 @@ $ source .venv/Scripts/activate //// -Ця команда створить або змінить деякі [Змінні оточення](environment-variables.md), які будуть доступні для наступних команд. +Ця команда створить або змінить деякі [змінні оточення](environment-variables.md), які будуть доступні для наступних команд. Однією з цих змінних є змінна `PATH`. @@ -728,7 +730,7 @@ C:\Users\user\code\awesome-project\.venv\Scripts\python //// -Важлива деталь: шлях до віртуального середовища буде додано на початок змінної `PATH`. Система знайде його раніше за будь-який інший доступний Python. Таким чином, коли ви запускаєте `python`, використовується саме Python із віртуального середовища, а не будь-який інший `python` (наприклад, з глобального середовища). +Важлива деталь: шлях до віртуального середовища буде додано на **початок** змінної `PATH`. Система знайде його **раніше** за будь-який інший доступний Python. Таким чином, коли ви запускаєте `python`, використовується саме Python **із віртуального середовища**, а не будь-який інший `python` (наприклад, з глобального середовища). Активація віртуального середовища також змінює ще кілька речей, але це одна з найважливіших. @@ -764,11 +766,11 @@ C:\Users\user\code\awesome-project\.venv\Scripts\python //// -Це означає, що програма `python`, яка буде використана, знаходиться у віртуальному середовищі. +Це означає, що програма `python`, яка буде використана, знаходиться **у віртуальному середовищі**. На Linux і macOS використовують `which`, а в Windows PowerShell - `Get-Command`. -Принцип роботи цієї команди в тому, що вона перевіряє змінну оточення `PATH`, проходячи по кожному шляху по порядку, шукаючи програму з назвою `python`. Щойно вона її знайде, вона покаже вам шлях до цієї програми. +Принцип роботи цієї команди в тому, що вона перевіряє змінну оточення `PATH`, проходячи по **кожному шляху по порядку**, шукаючи програму з назвою `python`. Щойно вона її знайде, вона **покаже вам шлях** до цієї програми. Найважливіше, що коли ви викликаєте `python`, це рівно той «`python`», який буде виконаний. @@ -776,9 +778,9 @@ C:\Users\user\code\awesome-project\.venv\Scripts\python /// tip | Порада -Легко активувати одне віртуальне середовище, отримати один Python, а потім перейти до іншого проєкту. +Легко активувати одне віртуальне середовище, отримати один Python, а потім **перейти до іншого проєкту**. -І другий проєкт не працюватиме, бо ви використовуєте некоректний Python з віртуального середовища іншого проєкту. +І другий проєкт **не працюватиме**, бо ви використовуєте **некоректний Python** з віртуального середовища іншого проєкту. Корисно вміти перевіряти, який саме `python` використовується. 🤓 @@ -786,9 +788,9 @@ C:\Users\user\code\awesome-project\.venv\Scripts\python ## Навіщо деактивувати віртуальне середовище { #why-deactivate-a-virtual-environment } -Наприклад, ви працюєте над проєктом `philosophers-stone`, активували його віртуальне середовище, встановили пакети та працюєте з цим середовищем. +Наприклад, ви працюєте над проєктом `philosophers-stone`, **активували його віртуальне середовище**, встановили пакети та працюєте з цим середовищем. -А потім ви хочете працювати над іншим проєктом `prisoner-of-azkaban`. +А потім ви хочете працювати над **іншим проєктом** `prisoner-of-azkaban`. Ви переходите до цього проєкту: @@ -840,23 +842,23 @@ I solemnly swear 🐺 ## Альтернативи { #alternatives } -Це простий посібник, щоб ви швидко стартували та зрозуміли, як усе працює «під капотом». +Це простий посібник, щоб ви швидко стартували та зрозуміли, як усе працює **«під капотом»**. -Існує багато альтернатив керування віртуальними середовищами, залежностями пакетів (вимогами), проєктами. +Існує багато **альтернатив** керування віртуальними середовищами, залежностями пакетів (вимогами), проєктами. -Коли будете готові й захочете використовувати інструмент для керування всім проєктом, залежностями пакетів, віртуальними середовищами тощо, я раджу спробувати [uv](https://github.com/astral-sh/uv). +Коли будете готові й захочете використовувати інструмент для **керування всім проєктом**, залежностями пакетів, віртуальними середовищами тощо, я раджу спробувати [uv](https://github.com/astral-sh/uv). `uv` уміє багато чого, зокрема: -* Встановлювати Python для вас, включно з різними версіями -* Керувати віртуальним середовищем ваших проєктів -* Встановлювати пакети -* Керувати залежностями пакетів і версіями у вашому проєкті -* Гарантувати, що у вас є точний набір пакетів і версій для встановлення, включно з їхніми залежностями, щоб ви були певні, що зможете запустити ваш проєкт у продакшені точно так само, як і на вашому комп'ютері під час розробки - це називається блокуванням +* **Встановлювати Python** для вас, включно з різними версіями +* Керувати **віртуальним середовищем** ваших проєктів +* Встановлювати **пакети** +* Керувати **залежностями і версіями** пакетів у вашому проєкті +* Гарантувати, що у вас є **точний** набір пакетів і версій для встановлення, включно з їхніми залежностями, щоб ви були певні, що зможете запустити ваш проєкт у продакшені точно так само, як і на вашому комп'ютері під час розробки - це називається **блокуванням** * І багато іншого ## Висновок { #conclusion } -Якщо ви все це прочитали й зрозуміли, тепер ви знаєте значно більше про віртуальні середовища, ніж багато розробників. 🤓 +Якщо ви все це прочитали й зрозуміли, тепер **ви знаєте значно більше** про віртуальні середовища, ніж багато розробників. 🤓 -Знання цих деталей, найімовірніше, стане в пригоді в майбутньому, коли ви налагоджуватимете щось, що виглядає складним, але ви знатимете, як усе працює «під капотом». 😎 +Знання цих деталей, найімовірніше, стане в пригоді в майбутньому, коли ви налагоджуватимете щось, що виглядає складним, але ви знатимете, **як усе працює «під капотом»**. 😎 diff --git a/docs/zh-hant/docs/_llm-test.md b/docs/zh-hant/docs/_llm-test.md index 0ea674cd8..09efe8377 100644 --- a/docs/zh-hant/docs/_llm-test.md +++ b/docs/zh-hant/docs/_llm-test.md @@ -35,7 +35,7 @@ //// tab | 測試 -Yesterday, my friend wrote: "If you spell incorrectly correctly, you have spelled it incorrectly". To which I answered: "Correct, but 'incorrectly' is incorrectly not '"incorrectly"'". +昨天,我的朋友寫道:「如果你正確地拼寫 incorrectly,你就把它拼成 incorrectly 了」。我回答:「正確,但 'incorrectly' 錯在它不是 '"incorrectly"'"」。 /// note | 注意 @@ -59,7 +59,7 @@ LLM 很可能會把這段翻譯錯。重點只在於重新翻譯時是否能保 `pip install "foo[bar]"` -程式碼片段中字串常值的例子:"this"、'that'。 +程式碼片段中字串常值的例子:`"this"`、`'that'`。 較難的程式碼片段中字串常值例子:`f"I like {'oranges' if orange else "apples"}"` @@ -125,23 +125,23 @@ works(foo="bar") # 這可以運作 🎉 //// tab | 測試 /// note | 注意 -Some text +一些文字 /// /// note | 技術細節 -Some text +一些文字 /// /// tip | 提示 -Some text +一些文字 /// /// warning | 警告 -Some text +一些文字 /// /// danger | 危險 -Some text +一些文字 /// //// @@ -222,15 +222,15 @@ Some text ### 開發網頁應用程式 - 教學 { #develop-a-webapp-a-tutorial } -Hello. +你好。 ### 型別提示與註解 { #type-hints-and-annotations } -Hello again. +再次你好。 ### 超類與子類別 { #super-and-subclasses } -Hello again. +再次你好。 //// @@ -248,15 +248,15 @@ Hello again. //// tab | 測試 -* you -* your +* 你 +* 你的 -* e.g. -* etc. +* 例如 +* 等等 -* `foo` as an `int` -* `bar` as a `str` -* `baz` as a `list` +* `foo` 作為 `int` +* `bar` 作為 `str` +* `baz` 作為 `list` * 教學 - 使用者指南 * 進階使用者指南 @@ -283,7 +283,7 @@ Hello again. * 即時 * 標準 * 預設 -* 区分大小寫 +* 區分大小寫 * 不區分大小寫 * 提供應用程式服務 diff --git a/docs/zh-hant/docs/advanced/additional-responses.md b/docs/zh-hant/docs/advanced/additional-responses.md index 118c65e04..552ce2e23 100644 --- a/docs/zh-hant/docs/advanced/additional-responses.md +++ b/docs/zh-hant/docs/advanced/additional-responses.md @@ -34,7 +34,7 @@ /// -/// info | 說明 +/// note | 注意 `model` 這個鍵不屬於 OpenAPI。 @@ -183,7 +183,7 @@ /// -/// info | 說明 +/// note | 注意 除非你在 `responses` 參數中明確指定不同的媒體型別,否則 FastAPI 會假設回應的媒體型別與主回應類別相同(預設為 `application/json`)。 diff --git a/docs/zh-hant/docs/advanced/additional-status-codes.md b/docs/zh-hant/docs/advanced/additional-status-codes.md index 0e5941a8d..bbb4f57dc 100644 --- a/docs/zh-hant/docs/advanced/additional-status-codes.md +++ b/docs/zh-hant/docs/advanced/additional-status-codes.md @@ -1,5 +1,6 @@ # 額外的狀態碼 { #additional-status-codes } + 在預設情況下,**FastAPI** 會使用 `JSONResponse` 傳回回應,並把你從你的「路徑操作(path operation)」回傳的內容放進該 `JSONResponse` 中。 它會使用預設的狀態碼,或你在路徑操作中設定的狀態碼。 diff --git a/docs/zh-hant/docs/advanced/advanced-dependencies.md b/docs/zh-hant/docs/advanced/advanced-dependencies.md index 559ca245f..92dabdaf1 100644 --- a/docs/zh-hant/docs/advanced/advanced-dependencies.md +++ b/docs/zh-hant/docs/advanced/advanced-dependencies.md @@ -1,5 +1,6 @@ # 進階相依 { #advanced-dependencies } + ## 參數化的相依 { #parameterized-dependencies } 到目前為止看到的相依都是固定的函式或類別。 @@ -98,7 +99,7 @@ checker(q="somequery") 這個行為在 0.118.0 被還原,使得 `yield` 之後的結束程式碼會在回應送出之後才被執行。 -/// info | 資訊 +/// note | 注意 如下所見,這與 0.106.0 之前的行為非常類似,但對一些邊界情況做了多項改進與錯誤修正。 diff --git a/docs/zh-hant/docs/advanced/custom-response.md b/docs/zh-hant/docs/advanced/custom-response.md index c8355937c..76631e37e 100644 --- a/docs/zh-hant/docs/advanced/custom-response.md +++ b/docs/zh-hant/docs/advanced/custom-response.md @@ -41,7 +41,7 @@ FastAPI 預設回傳 JSON 回應。 {* ../../docs_src/custom_response/tutorial002_py310.py hl[2,7] *} -/// info +/// note 參數 `response_class` 也會用來定義回應的「media type」。 @@ -65,7 +65,7 @@ FastAPI 預設回傳 JSON 回應。 /// -/// info +/// note 當然,實際的 `Content-Type` 標頭、狀態碼等,會來自你回傳的 `Response` 物件。 diff --git a/docs/zh-hant/docs/advanced/dataclasses.md b/docs/zh-hant/docs/advanced/dataclasses.md index a18b421c4..64ba7dde2 100644 --- a/docs/zh-hant/docs/advanced/dataclasses.md +++ b/docs/zh-hant/docs/advanced/dataclasses.md @@ -18,7 +18,7 @@ FastAPI 建立在 **Pydantic** 之上,我之前示範過如何使用 Pydantic 它的運作方式與 Pydantic 模型相同;實際上,底層就是透過 Pydantic 達成的。 -/// info +/// note 請記得,dataclass 無法做到 Pydantic 模型能做的一切。 @@ -63,12 +63,12 @@ FastAPI 建立在 **Pydantic** 之上,我之前示範過如何使用 Pydantic 7. 這裡 `response_model` 使用的是「`Author` dataclass 的清單」這種型別註記。 同樣地,你可以把 `dataclasses` 與標準型別註記組合使用。 -8. 注意這個「路徑操作函式」使用的是一般的 `def` 而非 `async def`。 +8. 注意這個*路徑操作函式*使用的是一般的 `def` 而非 `async def`。 一如往常,在 FastAPI 中你可以視需要混用 `def` 與 `async def`。 - 如果需要複習何時用哪個,請參考文件中關於 [`async` 與 `await`](../async.md#in-a-hurry) 的章節「In a hurry?」。 -9. 這個「路徑操作函式」回傳的不是 dataclass(雖然也可以),而是一個包含內部資料的字典清單。 + 如果需要複習何時用哪個,請參考文件中關於 [`async` 與 `await`](../async.md#in-a-hurry) 的章節 _「趕時間?」_。 +9. 這個*路徑操作函式*回傳的不是 dataclass(雖然也可以),而是一個包含內部資料的字典清單。 FastAPI 會使用 `response_model` 參數(其中包含 dataclass)來轉換回應。 diff --git a/docs/zh-hant/docs/advanced/events.md b/docs/zh-hant/docs/advanced/events.md index 7def525fa..e132d9f3d 100644 --- a/docs/zh-hant/docs/advanced/events.md +++ b/docs/zh-hant/docs/advanced/events.md @@ -1,5 +1,6 @@ # 生命週期事件 { #lifespan-events } + 你可以定義在應用程式**啟動**之前要執行的邏輯(程式碼)。也就是說,這段程式碼會在應用開始接收請求**之前**、**只執行一次**。 同樣地,你也可以定義在應用程式**關閉**時要執行的邏輯(程式碼)。在這種情況下,這段程式碼會在處理了**許多請求**之後、**只執行一次**。 @@ -120,7 +121,7 @@ async with lifespan(app): 在這裡,`shutdown` 事件處理器函式會把一行文字 `"Application shutdown"` 寫入檔案 `log.txt`。 -/// info +/// note 在 `open()` 函式中,`mode="a"` 表示「append(附加)」;也就是說,這行文字會加在檔案現有內容之後,而不會覆寫先前的內容。 @@ -152,7 +153,7 @@ async with lifespan(app): 在底層的 ASGI 技術規範中,這屬於 [Lifespan Protocol](https://asgi.readthedocs.io/en/latest/specs/lifespan.html) 的一部分,並定義了 `startup` 與 `shutdown` 兩種事件。 -/// info +/// note 你可以在 [Starlette 的 Lifespan 文件](https://www.starlette.dev/lifespan/) 讀到更多關於 Starlette `lifespan` 處理器的資訊。 diff --git a/docs/zh-hant/docs/advanced/generate-clients.md b/docs/zh-hant/docs/advanced/generate-clients.md index c1aa88ef7..cc7a6865a 100644 --- a/docs/zh-hant/docs/advanced/generate-clients.md +++ b/docs/zh-hant/docs/advanced/generate-clients.md @@ -20,21 +20,6 @@ FastAPI 會自動產生 **OpenAPI 3.1** 規格,因此你使用的任何工具 /// -## 來自 FastAPI 贊助商的 SDK 產生器 { #sdk-generators-from-fastapi-sponsors } - -本節重點介紹由贊助 FastAPI 的公司提供的**創投支持**與**公司維運**的解決方案。這些產品在高品質的自動產生 SDK 之外,還提供**額外功能**與**整合**。 - -透過 ✨ [**贊助 FastAPI**](../help-fastapi.md#sponsor-the-author) ✨,這些公司幫助確保框架與其**生態系**維持健康且**永續**。 - -他們的贊助也展現對 FastAPI **社群**(你)的高度承諾,不僅關心提供**優良服務**,也支持 **FastAPI** 作為一個**穩健且蓬勃的框架**。🙇 - -例如,你可以嘗試: - -* [Stainless](https://www.stainless.com/?utm_source=fastapi&utm_medium=referral) -* [liblab](https://developers.liblab.com/tutorials/sdk-for-fastapi?utm_source=fastapi) - -其中有些方案也可能是開源或提供免費方案,讓你不需財務承諾就能試用。其他商業的 SDK 產生器也不少,你可以在網路上找到。🤓 - ## 建立 TypeScript SDK { #create-a-typescript-sdk } 先從一個簡單的 FastAPI 應用開始: @@ -57,7 +42,7 @@ FastAPI 會自動產生 **OpenAPI 3.1** 規格,因此你使用的任何工具 ### Hey API { #hey-api } -當我們有含模型的 FastAPI 應用後,就能用 Hey API 來產生 TypeScript 用戶端。最快的方法是透過 npx: +當我們有含模型的 FastAPI 應用後,就能用 Hey API 來產生 TypeScript 用戶端。最快的方法是透過 npx。 ```sh npx @hey-api/openapi-ts -i http://localhost:8000/openapi.json -o src/client @@ -195,7 +180,7 @@ npx @hey-api/openapi-ts -i ./openapi.json -o src/client 使用自動產生的用戶端時,你會得到以下項目的**自動完成**: * 方法 -* 本文中的請求有效載荷、查詢參數等 +* Body 中的請求有效載荷、查詢參數等 * 回應的有效載荷 你也會對所有內容獲得**行內錯誤**提示。 diff --git a/docs/zh-hant/docs/advanced/json-base64-bytes.md b/docs/zh-hant/docs/advanced/json-base64-bytes.md index 9f1ecfa2e..bdf146b8c 100644 --- a/docs/zh-hant/docs/advanced/json-base64-bytes.md +++ b/docs/zh-hant/docs/advanced/json-base64-bytes.md @@ -4,7 +4,7 @@ ## Base64 與檔案 { #base64-vs-files } -請先考慮是否能用 [請求檔案](../tutorial/request-files.md) 來上傳二進位資料,並用 [自訂回應 - FileResponse](./custom-response.md#fileresponse--fileresponse-) 來傳送二進位資料,而不是把它們編碼進 JSON。 +請先考慮是否能用 [請求檔案](../tutorial/request-files.md) 來上傳二進位資料,並用 [自訂回應 - FileResponse](./custom-response.md#fileresponse) 來傳送二進位資料,而不是把它們編碼進 JSON。 JSON 只能包含 UTF-8 編碼的字串,因此無法直接包含原始位元組。 @@ -14,7 +14,7 @@ Base64 可以把二進位資料編碼成字串,但為此會使用比原始二 ## Pydantic `bytes` { #pydantic-bytes } -你可以宣告含有 `bytes` 欄位的 Pydantic 模型,並在模型設定中使用 `val_json_bytes`,使其在驗證輸入的 JSON 資料時使用 base64;在驗證過程中,它會將 base64 字串解碼為位元組。 +你可以宣告含有 `bytes` 欄位的 Pydantic 模型,並在模型設定中使用 `val_json_bytes`,使其在*驗證*輸入的 JSON 資料時使用 base64;在驗證過程中,它會將 base64 字串解碼為位元組。 {* ../../docs_src/json_base64_bytes/tutorial001_py310.py ln[1:9,29:35] hl[9] *} @@ -52,12 +52,12 @@ Base64 可以把二進位資料編碼成字串,但為此會使用比原始二 ## Pydantic `bytes` 用於輸出資料 { #pydantic-bytes-for-output-data } -你也可以在模型設定中搭配 `ser_json_bytes` 使用 `bytes` 欄位來處理輸出資料;當產生 JSON 回應時,Pydantic 會將位元組以 base64 進行序列化。 +你也可以在模型設定中搭配 `ser_json_bytes` 使用 `bytes` 欄位來處理輸出資料;當產生 JSON 回應時,Pydantic 會將位元組以 base64 進行*序列化*。 {* ../../docs_src/json_base64_bytes/tutorial001_py310.py ln[1:2,12:16,29,38:41] hl[16] *} ## Pydantic `bytes` 用於輸入與輸出資料 { #pydantic-bytes-for-input-and-output-data } -當然,你也可以使用同一個以 base64 設定的模型,同時處理輸入(以 `val_json_bytes` 驗證)與輸出(以 `ser_json_bytes` 序列化)的 JSON 資料。 +當然,你也可以使用同一個以 base64 設定的模型,同時處理接收與傳送 JSON 資料時的輸入(以 `val_json_bytes` *驗證*)與輸出(以 `ser_json_bytes` *序列化*)。 {* ../../docs_src/json_base64_bytes/tutorial001_py310.py ln[1:2,19:26,29,44:46] hl[23:26] *} diff --git a/docs/zh-hant/docs/advanced/openapi-callbacks.md b/docs/zh-hant/docs/advanced/openapi-callbacks.md index 3b01f4201..6ab869acc 100644 --- a/docs/zh-hant/docs/advanced/openapi-callbacks.md +++ b/docs/zh-hant/docs/advanced/openapi-callbacks.md @@ -4,7 +4,7 @@ 當你的 API 應用呼叫「外部 API」時發生的過程稱為「回呼(callback)」。因為外部開發者撰寫的軟體會先向你的 API 發出請求,接著你的 API 再「回呼」,也就是向(可能同一位開發者建立的)外部 API 發送請求。 -在這種情況下,你可能想要文件化說明該外部 API 應該長什麼樣子。它應該有哪些「路徑操作」、應該接受什麼 body、應該回傳什麼 response,等等。 +在這種情況下,你可能想要文件化說明該外部 API 應該長什麼樣子。它應該有哪些「路徑操作」、應該接受什麼 body、應該回傳什麼回應,等等。 ## 帶有回呼的應用 { #an-app-with-callbacks } @@ -82,7 +82,7 @@ httpx.post(callback_url, json={"description": "Invoice paid", "paid": True}) 在撰寫回呼的文件化程式碼時,把自己想像成那位「外部開發者」會很有幫助。而且你現在是在實作「外部 API」,不是「你的 API」。 -暫時採用這個(外部開發者)的視角,有助於讓你更直覺地決定該把參數、body 的 Pydantic 模型、response 的模型等放在哪裡,對於那個「外部 API」會更清楚。 +暫時採用這個(外部開發者)的視角,有助於讓你更直覺地決定該把參數、body 的 Pydantic 模型、回應模型等放在哪裡,對於那個「外部 API」會更清楚。 /// @@ -99,7 +99,7 @@ httpx.post(callback_url, json={"description": "Invoice paid", "paid": True}) 它看起來就像一般的 FastAPI「路徑操作」: * 可能需要宣告它應該接收的 body,例如 `body: InvoiceEvent`。 -* 也可以宣告它應該回傳的 response,例如 `response_model=InvoiceEventReceived`。 +* 也可以宣告它應該回傳的回應,例如 `response_model=InvoiceEventReceived`。 {* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[14:16,19:20,26:30] *} @@ -167,13 +167,13 @@ https://www.external.org/events/invoices/2expen51ve 此時你已經在先前建立的回呼 router 中,擁有所需的回呼「路徑操作(們)」(也就是「外部開發者」應該在「外部 API」中實作的那些)。 -現在在「你的 API 的路徑操作裝飾器」中使用參數 `callbacks`,將該回呼 router 的屬性 `.routes`(實際上就是一個由路由/「路徑操作」所組成的 `list`)傳入: +現在在「你的 API 的路徑操作裝飾器」中使用參數 `callbacks`,將該回呼 router 的屬性 `.routes` 傳入: {* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[33] *} /// tip -注意你傳給 `callback=` 的不是整個 router 本身(`invoices_callback_router`),而是它的屬性 `.routes`,也就是 `invoices_callback_router.routes`。 +注意你不是把整個 router 本身(`invoices_callback_router`)傳給 `callbacks=`,而是它的 `.routes`,也就是 `invoices_callback_router.routes`。FastAPI 會使用這些路由來產生回呼的 OpenAPI 文件。 /// diff --git a/docs/zh-hant/docs/advanced/openapi-webhooks.md b/docs/zh-hant/docs/advanced/openapi-webhooks.md index 18206c447..0e5789aa1 100644 --- a/docs/zh-hant/docs/advanced/openapi-webhooks.md +++ b/docs/zh-hant/docs/advanced/openapi-webhooks.md @@ -22,7 +22,7 @@ 這能讓你的使用者更容易實作他們的 API 以接收你的 webhook 請求,甚至可能自動產生部分他們自己的 API 程式碼。 -/// info +/// note Webhook 功能自 OpenAPI 3.1.0 起提供,FastAPI `0.99.0` 以上版本支援。 @@ -36,7 +36,7 @@ Webhook 功能自 OpenAPI 3.1.0 起提供,FastAPI `0.99.0` 以上版本支援 你定義的 webhook 會出現在 OpenAPI 結構描述與自動產生的文件 UI 中。 -/// info +/// note `app.webhooks` 其實就是一個 `APIRouter`,與你在將應用拆分為多個檔案時所使用的型別相同。 diff --git a/docs/zh-hant/docs/advanced/path-operation-advanced-configuration.md b/docs/zh-hant/docs/advanced/path-operation-advanced-configuration.md index f1607a1da..e342ccc11 100644 --- a/docs/zh-hant/docs/advanced/path-operation-advanced-configuration.md +++ b/docs/zh-hant/docs/advanced/path-operation-advanced-configuration.md @@ -16,21 +16,15 @@ ### 使用路徑操作函式(path operation function)的名稱作為 operationId { #using-the-path-operation-function-name-as-the-operationid } -如果你想用 API 的函式名稱作為 `operationId`,你可以遍歷所有路徑,並使用各自的 `APIRoute.name` 覆寫每個*路徑操作*的 `operation_id`。 +如果你想用 API 的函式名稱作為 `operationId`,你可以在 `FastAPI` 中傳入自訂的 `generate_unique_id_function`。 -應在加入所有*路徑操作*之後再這麼做。 +該函式會接收每個 `APIRoute` 並回傳該路徑操作要使用的 `operationId`。 -{* ../../docs_src/path_operation_advanced_configuration/tutorial002_py310.py hl[2, 12:21, 24] *} - -/// tip - -如果你會手動呼叫 `app.openapi()`,請務必先更新所有 `operationId` 再呼叫。 - -/// +{* ../../docs_src/path_operation_advanced_configuration/tutorial002_py310.py hl[2,5:6,9] *} /// warning -如果你這樣做,必須確保每個*路徑操作函式*都有唯一的名稱, +如果你這樣做,必須確保每個*路徑操作函式*都有唯一的名稱。 即使它們位於不同的模組(Python 檔案)中。 diff --git a/docs/zh-hant/docs/advanced/response-change-status-code.md b/docs/zh-hant/docs/advanced/response-change-status-code.md index 31b688512..ee6373a30 100644 --- a/docs/zh-hant/docs/advanced/response-change-status-code.md +++ b/docs/zh-hant/docs/advanced/response-change-status-code.md @@ -1,5 +1,6 @@ # 回應 - 變更狀態碼 { #response-change-status-code } + 你可能已經讀過,可以設定預設的[回應狀態碼](../tutorial/response-status-code.md)。 但有些情況你需要回傳與預設不同的狀態碼。 diff --git a/docs/zh-hant/docs/advanced/response-cookies.md b/docs/zh-hant/docs/advanced/response-cookies.md index 2ba14c3f6..b27552330 100644 --- a/docs/zh-hant/docs/advanced/response-cookies.md +++ b/docs/zh-hant/docs/advanced/response-cookies.md @@ -2,9 +2,9 @@ ## 使用 `Response` 參數 { #use-a-response-parameter } -你可以在路徑操作函式(path operation function)中宣告一個型別為 `Response` 的參數。 +你可以在你的*路徑操作函式*(path operation function)中宣告一個型別為 `Response` 的參數。 -接著你可以在那個「暫時」的 `Response` 物件上設定 Cookie。 +接著你可以在那個*暫時*的 `Response` 物件上設定 Cookie。 {* ../../docs_src/response_cookies/tutorial002_py310.py hl[1, 8:9] *} @@ -12,7 +12,7 @@ 如果你宣告了 `response_model`,它仍會用來過濾並轉換你回傳的物件。 -FastAPI 會使用那個暫時的 `Response` 取出 Cookie(以及標頭與狀態碼),並將它們放入最終回應;最終回應包含你回傳的值,且會套用任何 `response_model` 的過濾。 +**FastAPI** 會使用那個*暫時*的 `Response` 取出 Cookie(以及標頭與狀態碼),並將它們放入最終回應;最終回應包含你回傳的值,且會套用任何 `response_model` 的過濾。 你也可以在相依項(dependencies)中宣告 `Response` 參數,並在其中設定 Cookie(與標頭)。 @@ -42,9 +42,9 @@ FastAPI 會使用那個暫時的 `Response` 取出 Cookie(以及標頭與狀 你也可以使用 `from starlette.responses import Response` 或 `from starlette.responses import JSONResponse`。 -為了方便開發者,FastAPI 也將相同的 `starlette.responses` 透過 `fastapi.responses` 提供。不過,大多數可用的回應類別都直接來自 Starlette。 +**FastAPI** 為了方便你這位開發者,也將相同的 `starlette.responses` 透過 `fastapi.responses` 提供。不過,大多數可用的回應類別都直接來自 Starlette。 -另外由於 `Response` 常用於設定標頭與 Cookie,FastAPI 也在 `fastapi.Response` 提供了它。 +另外由於 `Response` 常用於設定標頭與 Cookie,**FastAPI** 也在 `fastapi.Response` 提供了它。 /// diff --git a/docs/zh-hant/docs/advanced/response-directly.md b/docs/zh-hant/docs/advanced/response-directly.md index 16face261..c4b8cb075 100644 --- a/docs/zh-hant/docs/advanced/response-directly.md +++ b/docs/zh-hant/docs/advanced/response-directly.md @@ -10,7 +10,7 @@ /// tip -通常使用 [回應模型](../tutorial/response-model.md) 會有更好的效能,因為那樣會在 Rust 端使用 Pydantic 來序列化資料,而不是直接回傳 `JSONResponse`。 +通常使用 [回應模型](../tutorial/response-model.md) 會有更好的效能,因為那樣會在 Rust 端使用 Pydantic 來序列化資料。 /// @@ -18,7 +18,7 @@ 其實,你可以回傳任何 `Response`,或其任何子類別。 -/// info +/// note `JSONResponse` 本身就是 `Response` 的子類別。 diff --git a/docs/zh-hant/docs/advanced/response-headers.md b/docs/zh-hant/docs/advanced/response-headers.md index 4f7494a8b..002fb0e54 100644 --- a/docs/zh-hant/docs/advanced/response-headers.md +++ b/docs/zh-hant/docs/advanced/response-headers.md @@ -12,7 +12,7 @@ 如果你宣告了 `response_model`,它仍會用來過濾並轉換你回傳的物件。 -FastAPI 會使用那個暫時性的回應來擷取標頭(還有 Cookie 與狀態碼),並把它們放到最終回應中;最終回應包含你回傳的值,且會依任何 `response_model` 進行過濾。 +**FastAPI** 會使用那個暫時性的回應來擷取標頭(還有 Cookie 與狀態碼),並把它們放到最終回應中;最終回應包含你回傳的值,且會依任何 `response_model` 進行過濾。 你也可以在依賴中宣告 `Response` 參數,並在其中設定標頭(與 Cookie)。 @@ -28,9 +28,9 @@ FastAPI 會使用那個暫時性的回應來擷取標頭(還有 Cookie 與狀 你也可以使用 `from starlette.responses import Response` 或 `from starlette.responses import JSONResponse`。 -為了方便開發者,FastAPI 提供與 `starlette.responses` 相同的內容於 `fastapi.responses`。但大多數可用的回應類型其實直接來自 Starlette。 +為了方便開發者,**FastAPI** 提供與 `starlette.responses` 相同的內容於 `fastapi.responses`。但大多數可用的回應類型其實直接來自 Starlette。 -由於 `Response` 常用來設定標頭與 Cookie,FastAPI 也在 `fastapi.Response` 提供了它。 +由於 `Response` 常用來設定標頭與 Cookie,**FastAPI** 也在 `fastapi.Response` 提供了它。 /// diff --git a/docs/zh-hant/docs/advanced/security/oauth2-scopes.md b/docs/zh-hant/docs/advanced/security/oauth2-scopes.md index 05088be7e..bfd9260e3 100644 --- a/docs/zh-hant/docs/advanced/security/oauth2-scopes.md +++ b/docs/zh-hant/docs/advanced/security/oauth2-scopes.md @@ -1,6 +1,6 @@ # OAuth2 範圍(scopes) { #oauth2-scopes } -你可以直接在 FastAPI 中使用 OAuth2 的 scopes,已整合可無縫運作。 +你可以直接在 **FastAPI** 中使用 OAuth2 的 scopes,已整合可無縫運作。 這能讓你在 OpenAPI 應用(以及 API 文件)中,依照 OAuth2 標準,實作更細粒度的權限系統。 @@ -8,7 +8,7 @@ 每次你「使用」Facebook、Google、GitHub、Microsoft、X(Twitter)「登入」時,那個應用就是在使用帶有 scopes 的 OAuth2。 -在本節中,你將看到如何在你的 FastAPI 應用中,用同樣的帶有 scopes 的 OAuth2 管理驗證與授權。 +在本節中,你將看到如何在你的 **FastAPI** 應用中,用同樣的帶有 scopes 的 OAuth2 管理驗證與授權。 /// warning @@ -42,11 +42,11 @@ OAuth2 規格將「scopes」定義為以空白分隔的一串字串列表。 它們通常用來宣告特定的安全性權限,例如: -- `users:read` 或 `users:write` 是常見的例子。 -- `instagram_basic` 是 Facebook / Instagram 使用的。 -- `https://www.googleapis.com/auth/drive` 是 Google 使用的。 +* `users:read` 或 `users:write` 是常見的例子。 +* `instagram_basic` 是 Facebook / Instagram 使用的。 +* `https://www.googleapis.com/auth/drive` 是 Google 使用的。 -/// info +/// note 在 OAuth2 中,「scope」只是宣告所需特定權限的一個字串。 @@ -58,9 +58,9 @@ OAuth2 規格將「scopes」定義為以空白分隔的一串字串列表。 /// -## 全局概觀 { #global-view } +## 全域概觀 { #global-view } -先快速看看相對於主教學「使用密碼(與雜湊)、Bearer 與 JWT token 的 OAuth2」的差異([OAuth2 with Password (and hashing), Bearer with JWT tokens](../../tutorial/security/oauth2-jwt.md))。現在加入了 OAuth2 scopes: +先快速看看主要 **教學 - 使用者指南** 中 [OAuth2 with Password (and hashing), Bearer with JWT tokens](../../tutorial/security/oauth2-jwt.md) 範例的變更部分。現在加入了 OAuth2 scopes: {* ../../docs_src/security/tutorial005_an_py310.py hl[5,9,13,47,65,106,108:116,122:126,130:136,141,157] *} @@ -84,7 +84,7 @@ OAuth2 規格將「scopes」定義為以空白分隔的一串字串列表。 ## 內含 scopes 的 JWT token { #jwt-token-with-scopes } -現在,修改 token 的路徑操作以回傳所請求的 scopes。 +現在,修改 token 的*路徑操作*以回傳所請求的 scopes。 我們仍然使用相同的 `OAuth2PasswordRequestForm`。它包含屬性 `scopes`,其為 `list` 的 `str`,列出請求中收到的每個 scope。 @@ -100,9 +100,9 @@ OAuth2 規格將「scopes」定義為以空白分隔的一串字串列表。 {* ../../docs_src/security/tutorial005_an_py310.py hl[157] *} -## 在路徑操作與相依性中宣告 scopes { #declare-scopes-in-path-operations-and-dependencies } +## 在*路徑操作*與相依性中宣告 scopes { #declare-scopes-in-path-operations-and-dependencies } -現在我們宣告 `/users/me/items/` 這個路徑操作需要 `items` 這個 scope。 +現在我們宣告 `/users/me/items/` 這個*路徑操作*需要 `items` 這個 scope。 為此,我們從 `fastapi` 匯入並使用 `Security`。 @@ -120,17 +120,17 @@ OAuth2 規格將「scopes」定義為以空白分隔的一串字串列表。 你不一定需要在不同地方加上不同的 scopes。 -我們在這裡這樣做,是為了示範 FastAPI 如何處理在不同層級宣告的 scopes。 +我們在這裡這樣做,是為了示範 **FastAPI** 如何處理在不同層級宣告的 scopes。 /// {* ../../docs_src/security/tutorial005_an_py310.py hl[5,141,172] *} -/// info | 技術細節 +/// note | 技術細節 `Security` 其實是 `Depends` 的子類別,僅多了一個我們稍後會看到的參數。 -改用 `Security` 而不是 `Depends`,能讓 FastAPI 知道可以宣告安全性 scopes、在內部使用它們,並用 OpenAPI 文件化 API。 +改用 `Security` 而不是 `Depends`,能讓 **FastAPI** 知道可以宣告安全性 scopes、在內部使用它們,並用 OpenAPI 文件化 API。 另外,當你從 `fastapi` 匯入 `Query`、`Path`、`Depends`、`Security` 等時,實際上它們是回傳特殊類別的函式。 @@ -184,7 +184,7 @@ OAuth2 規格將「scopes」定義為以空白分隔的一串字串列表。 ## 驗證 `scopes` { #verify-the-scopes } -我們現在要驗證,此相依性與所有相依者(包含路徑操作)所要求的所有 scopes,是否都包含在收到的 token 內所提供的 scopes 中;否則就丟出 `HTTPException`。 +我們現在要驗證,此相依性與所有相依者(包含*路徑操作*)所要求的所有 scopes,是否都包含在收到的 token 內所提供的 scopes 中;否則就丟出 `HTTPException`。 為此,我們使用 `security_scopes.scopes`,其中包含一個 `list`,列出所有這些 `str` 形式的 scopes。 @@ -196,30 +196,30 @@ OAuth2 規格將「scopes」定義為以空白分隔的一串字串列表。 由於 `get_current_active_user` 相依於 `get_current_user`,因此在 `get_current_active_user` 宣告的 `"me"` 這個 scope 會包含在傳給 `get_current_user` 的 `security_scopes.scopes` 的必須 scopes 清單中。 -路徑操作本身也宣告了 `"items"` 這個 scope,因此它也會包含在傳給 `get_current_user` 的 `security_scopes.scopes` 中。 +*路徑操作*本身也宣告了 `"items"` 這個 scope,因此它也會包含在傳給 `get_current_user` 的 `security_scopes.scopes` 中。 以下是相依性與 scopes 的階層關係: -- 路徑操作 `read_own_items` 具有: - - 需要的 scopes `["items"]`,並有相依性: - - `get_current_active_user`: - - 相依函式 `get_current_active_user` 具有: - - 需要的 scopes `["me"]`,並有相依性: - - `get_current_user`: - - 相依函式 `get_current_user` 具有: - - 自身沒有需要的 scopes。 - - 一個使用 `oauth2_scheme` 的相依性。 - - 一個型別為 `SecurityScopes` 的 `security_scopes` 參數: - - 這個 `security_scopes` 參數有屬性 `scopes`,其為一個 `list`,包含了上面宣告的所有 scopes,因此: - - 對於路徑操作 `read_own_items`,`security_scopes.scopes` 會包含 `["me", "items"]`。 - - 對於路徑操作 `read_users_me`,因為它在相依性 `get_current_active_user` 中被宣告,`security_scopes.scopes` 會包含 `["me"]`。 - - 對於路徑操作 `read_system_status`,因為它沒有宣告任何帶 `scopes` 的 `Security`,且其相依性 `get_current_user` 也未宣告任何 `scopes`,所以 `security_scopes.scopes` 會包含 `[]`(空)。 +* *路徑操作* `read_own_items` 具有: + * 需要的 scopes `["items"]`,並有相依性: + * `get_current_active_user`: + * 相依函式 `get_current_active_user` 具有: + * 需要的 scopes `["me"]`,並有相依性: + * `get_current_user`: + * 相依函式 `get_current_user` 具有: + * 自身沒有需要的 scopes。 + * 一個使用 `oauth2_scheme` 的相依性。 + * 一個型別為 `SecurityScopes` 的 `security_scopes` 參數: + * 這個 `security_scopes` 參數有屬性 `scopes`,其為一個 `list`,包含了上面宣告的所有 scopes,因此: + * 對於*路徑操作* `read_own_items`,`security_scopes.scopes` 會包含 `["me", "items"]`。 + * 對於*路徑操作* `read_users_me`,因為它在相依性 `get_current_active_user` 中被宣告,`security_scopes.scopes` 會包含 `["me"]`。 + * 對於*路徑操作* `read_system_status`,因為它沒有宣告任何帶 `scopes` 的 `Security`,且其相依性 `get_current_user` 也未宣告任何 `scopes`,所以 `security_scopes.scopes` 會包含 `[]`(空)。 /// tip -這裡重要且「神奇」的是:`get_current_user` 在每個路徑操作中,會有不同的 `scopes` 清單需要檢查。 +這裡重要且「神奇」的是:`get_current_user` 在每個*路徑操作*中,會有不同的 `scopes` 清單需要檢查。 -這完全取決於該路徑操作與其相依性樹中每個相依性所宣告的 `scopes`。 +這完全取決於該特定*路徑操作*與其相依性樹中每個相依性所宣告的 `scopes`。 /// @@ -227,11 +227,11 @@ OAuth2 規格將「scopes」定義為以空白分隔的一串字串列表。 你可以在任意位置、多個地方使用 `SecurityScopes`,它不需要位於「根」相依性。 -它會永遠帶有對於「該特定」路徑操作與「該特定」相依性樹中,目前 `Security` 相依性所宣告的安全性 scopes(以及所有相依者): +它會永遠帶有對於**該特定***路徑操作*與**該特定**相依性樹中,目前 `Security` 相依性所宣告的安全性 scopes(以及所有相依者)。 -因為 `SecurityScopes` 會擁有由相依者宣告的所有 scopes,你可以在一個集中式相依函式中用它來驗證 token 是否具有所需 scopes,然後在不同路徑操作中宣告不同的 scope 要求。 +因為 `SecurityScopes` 會擁有由相依者宣告的所有 scopes,你可以在一個集中式相依函式中用它來驗證 token 是否具有所需 scopes,然後在不同*路徑操作*中宣告不同的 scope 要求。 -它們會在每個路徑操作被各自獨立檢查。 +它們會在每個*路徑操作*被各自獨立檢查。 ## 試用看看 { #check-it } @@ -241,9 +241,9 @@ OAuth2 規格將「scopes」定義為以空白分隔的一串字串列表。 如果你沒有選任何 scope,你仍會「通過驗證」,但當你嘗試存取 `/users/me/` 或 `/users/me/items/` 時,會收到沒有足夠權限的錯誤。你仍能存取 `/status/`。 -若你只選了 `me` 而未選 `items`,你能存取 `/users/me/`,但無法存取 `/users/me/items/`。 +若你只選了 `me` 這個 scope 而未選 `items` 這個 scope,你能存取 `/users/me/`,但無法存取 `/users/me/items/`。 -這就是第三方應用在取得使用者提供的 token 後,嘗試存取上述路徑操作時,會依使用者授與該應用的權限多寡而有不同結果。 +這就是第三方應用在取得使用者提供的 token 後,嘗試存取上述其中一個*路徑操作*時,會依使用者授與該應用的權限多寡而有不同結果。 ## 關於第三方整合 { #about-third-party-integrations } @@ -255,9 +255,9 @@ OAuth2 規格將「scopes」定義為以空白分隔的一串字串列表。 但如果你要打造一個讓他人連接的 OAuth2 應用(也就是你要建立一個相當於 Facebook、Google、GitHub 等的身分驗證提供者),你應該使用其他流程之一。 -最常見的是 Implicit Flow(隱式流程)。 +最常見的是 implicit flow(隱式流程)。 -最安全的是 Authorization Code Flow(授權碼流程),但它需要更多步驟、實作也更複雜。因為較複雜,許多提供者最後會建議使用隱式流程。 +最安全的是 code flow(授權碼流程),但它需要更多步驟、實作也更複雜。因為較複雜,許多提供者最後會建議使用隱式流程。 /// note @@ -267,7 +267,7 @@ OAuth2 規格將「scopes」定義為以空白分隔的一串字串列表。 /// -FastAPI 在 `fastapi.security.oauth2` 中提供了所有這些 OAuth2 驗證流程的工具。 +**FastAPI** 在 `fastapi.security.oauth2` 中提供了所有這些 OAuth2 驗證流程的工具。 ## 在裝飾器 `dependencies` 中使用 `Security` { #security-in-decorator-dependencies } diff --git a/docs/zh-hant/docs/advanced/settings.md b/docs/zh-hant/docs/advanced/settings.md index 9892f8f00..4ec1ea672 100644 --- a/docs/zh-hant/docs/advanced/settings.md +++ b/docs/zh-hant/docs/advanced/settings.md @@ -297,6 +297,6 @@ participant execute as Execute function 你可以使用 Pydantic Settings 來處理應用程式的設定或組態,並享有 Pydantic model 的全部能力。 -- 透過相依可以讓測試更容易。 -- 你可以搭配 `.env` 檔使用。 -- 使用 `@lru_cache` 可以避免每個請求都重複讀取 dotenv 檔,同時仍可在測試時覆寫設定。 +* 透過相依可以讓測試更容易。 +* 你可以搭配 `.env` 檔使用。 +* 使用 `@lru_cache` 可以避免每個請求都重複讀取 dotenv 檔,同時仍可在測試時覆寫設定。 diff --git a/docs/zh-hant/docs/advanced/stream-data.md b/docs/zh-hant/docs/advanced/stream-data.md index 0f55ae651..c38c48faf 100644 --- a/docs/zh-hant/docs/advanced/stream-data.md +++ b/docs/zh-hant/docs/advanced/stream-data.md @@ -2,9 +2,9 @@ 如果你要串流可用 JSON 結構化的資料,應該[串流 JSON Lines](../tutorial/stream-json-lines.md)。 -但如果你想串流純二進位資料或字串,以下是做法。 +但如果你想**串流純二進位資料**或字串,以下是做法。 -/// info +/// note 已在 FastAPI 0.134.0 新增。 @@ -12,11 +12,11 @@ ## 使用情境 { #use-cases } -當你想串流純字串時可以用這個機制,例如直接轉發來自 AI LLM 服務的輸出。 +當你想串流純字串時可以用這個機制,例如直接轉發來自 **AI LLM** 服務的輸出。 -你也可以用它來串流大型二進位檔案,邊讀邊將每個區塊(chunk)串流出去,而不必一次把整個檔案載入記憶體。 +你也可以用它來串流**大型二進位檔案**,邊讀邊將每個區塊(chunk)串流出去,而不必一次把整個檔案載入記憶體。 -你也可以用同樣方式串流視訊或音訊,甚至可以在處理的同時即時產生並傳送。 +你也可以用同樣方式串流**視訊**或**音訊**,甚至可以在處理的同時即時產生並傳送。 ## 使用 `yield` 的 `StreamingResponse` { #a-streamingresponse-with-yield } @@ -40,7 +40,7 @@ FastAPI 會如實將每個資料區塊交給 `StreamingResponse`,不會嘗試 {* ../../docs_src/stream_data/tutorial001_py310.py ln[32:35] hl[33] *} -這也意味著使用 `StreamingResponse` 時,你擁有自由與責任,需依需求自行產生並編碼要傳送的位元組資料,與型別註解無關。 🤓 +這也意味著使用 `StreamingResponse` 時,你擁有**自由**與**責任**,需依需求自行產生並編碼要傳送的位元組資料,與型別註解無關。 🤓 ### 串流位元組 { #stream-bytes } @@ -90,7 +90,7 @@ FastAPI 會如實將每個資料區塊交給 `StreamingResponse`,不會嘗試 而且在許多情況下,讀取它們會是阻塞操作(可能阻塞事件迴圈),因為資料是從磁碟或網路讀取。 -/// info +/// note 上面的範例其實是例外,因為 `io.BytesIO` 物件已在記憶體中,讀取不會阻塞任何東西。 diff --git a/docs/zh-hant/docs/advanced/strict-content-type.md b/docs/zh-hant/docs/advanced/strict-content-type.md index 9d2ffb843..e4735c3e8 100644 --- a/docs/zh-hant/docs/advanced/strict-content-type.md +++ b/docs/zh-hant/docs/advanced/strict-content-type.md @@ -81,7 +81,7 @@ http://localhost:8000/v1/agents/multivac 啟用此設定後,缺少 `Content-Type` 標頭的請求會將其主體解析為 JSON,這與舊版 FastAPI 的行為相同。 -/// info | 資訊 +/// note | 注意 此行為與設定新增於 FastAPI 0.132.0。 diff --git a/docs/zh-hant/docs/advanced/websockets.md b/docs/zh-hant/docs/advanced/websockets.md index 57f51bcfb..29a95498c 100644 --- a/docs/zh-hant/docs/advanced/websockets.md +++ b/docs/zh-hant/docs/advanced/websockets.md @@ -111,7 +111,7 @@ $ fastapi dev {* ../../docs_src/websockets_/tutorial002_an_py310.py hl[68:69,82] *} -/// info +/// note 因為這是 WebSocket,拋出 `HTTPException` 並沒有意義,因此我們改為拋出 `WebSocketException`。 diff --git a/docs/zh-hant/docs/advanced/wsgi.md b/docs/zh-hant/docs/advanced/wsgi.md index c1baff34e..161496a98 100644 --- a/docs/zh-hant/docs/advanced/wsgi.md +++ b/docs/zh-hant/docs/advanced/wsgi.md @@ -1,12 +1,13 @@ # 包含 WSGI:Flask、Django 等 { #including-wsgi-flask-django-others } + 你可以像在 [子應用程式 - 掛載](sub-applications.md)、[在 Proxy 後方](behind-a-proxy.md) 中所見那樣掛載 WSGI 應用。 為此,你可以使用 `WSGIMiddleware` 來包住你的 WSGI 應用,例如 Flask、Django 等。 ## 使用 `WSGIMiddleware` { #using-wsgimiddleware } -/// info +/// note 這需要先安裝 `a2wsgi`,例如使用 `pip install a2wsgi`。 diff --git a/docs/zh-hant/docs/alternatives.md b/docs/zh-hant/docs/alternatives.md index fc3f7b38e..d9573892e 100644 --- a/docs/zh-hant/docs/alternatives.md +++ b/docs/zh-hant/docs/alternatives.md @@ -80,7 +80,7 @@ Requests 設計非常簡單直觀、容易使用,且有合理的預設值。 因此,如其官網所言: -> Requests is one of the most downloaded Python packages of all time +> Requests 是有史以來下載次數最多的 Python 套件之一 用法非常簡單。例如,發出一個 `GET` 請求,你會寫: @@ -213,7 +213,7 @@ APISpec 由與 Marshmallow 相同的開發者創建。 它是個很棒但被低估的工具。它理應比許多 Flask 外掛更受歡迎,可能因為它的文件過於簡潔與抽象。 -這解決了在 Python 文件字串中撰寫 YAML(另一種語法)的问题。 +這解決了在 Python 文件字串中撰寫 YAML(另一種語法)的問題。 在打造 **FastAPI** 前,我最喜歡的後端技術組合就是 Flask、Flask-apispec、Marshmallow 與 Webargs。 diff --git a/docs/zh-hant/docs/async.md b/docs/zh-hant/docs/async.md index 74eb8081d..cad99a5a6 100644 --- a/docs/zh-hant/docs/async.md +++ b/docs/zh-hant/docs/async.md @@ -2,7 +2,7 @@ 有關*路徑操作函式*的 `async def` 語法的細節與非同步 (asynchronous) 程式碼、並行 (concurrency) 與平行 (parallelism) 的一些背景知識。 -## 趕時間嗎? { #in-a-hurry } +## 趕時間嗎 { #in-a-hurry } TL;DR: @@ -14,7 +14,6 @@ results = await some_library() 然後,使用 `async def` 宣告你的*路徑操作函式*: - ```Python hl_lines="2" @app.get('/') async def read_results(): @@ -49,7 +48,7 @@ def results(): --- -**注意**:你可以在*路徑操作函式*中混合使用 `def` 和 `async def` ,並使用最適合你需求的方式來定義每個函式。FastAPI 會幫你做正確的處理。 +**注意**:你可以在*路徑操作函式*中混合使用 `def` 和 `async def`,並使用最適合你需求的方式來定義每個函式。FastAPI 會幫你做正確的處理。 無論如何,在上述哪種情況下,FastAPI 仍將以非同步方式運行,並且速度非常快。 @@ -57,7 +56,7 @@ def results(): ## 技術細節 { #technical-details } -現代版本的 Python 支援使用 **「協程」** 的 **`async` 和 `await`** 語法來寫 **「非同步程式碼」**。 +現代版本的 Python 支援使用稱為 **「協程」** 的東西,透過 **`async` 和 `await`** 語法來寫 **「非同步程式碼」**。 接下來我們逐一介紹: @@ -67,39 +66,40 @@ def results(): ## 非同步程式碼 { #asynchronous-code } -非同步程式碼僅意味著程式語言 💬 有辦法告訴電腦/程式 🤖 在程式碼中的某個點,它 🤖 需要等待某些事情完成。讓我們假設這些事情被稱為「慢速檔案」📝。 +非同步程式碼僅意味著程式語言 💬 有辦法告訴電腦 / 程式 🤖 在程式碼中的某個點,它 🤖 需要等待其他地方的*某些事情*完成。讓我們假設這個*某些事情*被稱為「慢速檔案」📝。 + +因此,在「慢速檔案」📝 完成的這段時間,電腦可以去處理一些其他工作。 -因此,在等待「慢速檔案」📝 完成的這段時間,電腦可以去處理一些其他工作。 +接著電腦 / 程式 🤖 會在每次有機會時回來,因為它又在等待,或是在它 🤖 完成當時手上的所有工作時回來。然後它 🤖 會查看是否有任何等待中的任務已經完成,並執行必要的後續操作。 -接著程式 🤖 會在有空檔時回來查看是否有等待的工作已經完成,並執行必要的後續操作。 +接下來,它 🤖 取得第一個完成的任務(例如我們的「慢速檔案」📝),並繼續執行與之相關的所有操作。 -接下來,它 🤖 完成第一個工作(例如我們的「慢速檔案」📝)並繼續執行相關的所有操作。 -這個「等待其他事情」通常指的是一些相對較慢的(與處理器和 RAM 記憶體的速度相比)的 I/O 操作,比如說: +這個「等待其他事情」通常指的是一些相對較慢的(與處理器和 RAM 記憶體的速度相比)的 I/O 操作,比如說等待: * 透過網路傳送來自用戶端的資料 -* 從網路接收來自用戶端的資料 -* 從磁碟讀取檔案內容 -* 將內容寫入磁碟 +* 你的程式傳送的資料透過網路被用戶端接收 +* 系統從磁碟讀取檔案內容並提供給你的程式 +* 你的程式交給系統的內容被寫入磁碟 * 遠端 API 操作 -* 資料庫操作 -* 資料庫查詢 +* 資料庫操作完成 +* 資料庫查詢回傳結果 * 等等 -由於大部分的執行時間都消耗在等待 I/O 操作上,因此這些操作被稱為 "I/O 密集型" 操作。 +由於大部分的執行時間都消耗在等待 I/O 操作上,因此這些操作被稱為 "I/O bound" 操作。 -之所以稱為「非同步」,是因為電腦/程式不需要與那些耗時的任務「同步」,等待任務完成的精確時間,然後才能取得結果並繼續工作。 +之所以稱為「非同步」,是因為電腦 / 程式不需要與那些耗時的任務「同步」,在什麼都不做的情況下等待任務完成的精確時間,才能取得任務結果並繼續工作。 -相反地,非同步系統在任務完成後,可以讓任務稍微等一下(幾微秒),等待電腦/程式完成手頭上的其他工作,然後再回來取得結果繼續進行。 +相反地,作為一個「非同步」系統,任務完成後,可以讓任務稍微排隊等一下(幾微秒),等待電腦 / 程式完成手頭上的其他工作,然後再回來取得結果繼續進行。 -相對於「非同步」(asynchronous),「同步」(synchronous)也常被稱作「順序性」(sequential),因為電腦/程式會依序執行所有步驟,即便這些步驟涉及等待,才會切換到其他任務。 +相對於「非同步」(asynchronous),「同步」(synchronous)也常被稱作「順序性」(sequential),因為電腦 / 程式會依序執行所有步驟,即便這些步驟涉及等待,才會切換到其他任務。 ### 並行與漢堡 { #concurrency-and-burgers } -上述非同步程式碼的概念有時也被稱為「並行」,它不同於「平行」。 +上述**非同步**程式碼的概念有時也被稱為**「並行」**,它不同於**「平行」**。 -並行和平行都與 "不同的事情或多或少同時發生" 有關。 +**並行**和平行都與 "不同的事情或多或少同時發生" 有關。 -但並行和平行之間的細節是完全不同的。 +但*並行*和平行之間的細節是完全不同的。 為了理解差異,請想像以下有關漢堡的故事: @@ -113,7 +113,7 @@ def results(): -收銀員通知廚房準備你的漢堡(儘管他們還在為前面其他顧客準備食物)。 +收銀員通知廚房的廚師,讓他們知道需要準備你的漢堡(儘管他們還在為前面其他顧客準備食物)。 @@ -125,7 +125,7 @@ def results(): 在等待漢堡的同時,你可以與戀人選一張桌子,然後坐下來聊很長一段時間(因為漢堡十分豪華,準備特別費工。) -這段時間,你還能欣賞你的戀人有多麼的可愛、聰明與迷人。✨😍✨ +當你和戀人坐在桌邊等待漢堡時,你可以把這段時間拿來欣賞你的戀人有多麼棒、可愛又聰明 ✨😍✨。 @@ -135,7 +135,7 @@ def results(): -你和戀人享用這頓大餐,整個過程十分開心✨ +你和戀人享用這頓大餐,整個過程十分開心。✨ @@ -147,21 +147,21 @@ def results(): --- -想像你是故事中的電腦或程式 🤖。 +想像你是故事中的電腦 / 程式 🤖。 當你排隊時,你在放空😴,等待輪到你,沒有做任何「生產性」的事情。但這沒關係,因為收銀員只是接單(而不是準備食物),所以排隊速度很快。 -然後,當輪到你時,你開始做真正「有生產力」的工作,處理菜單,決定你想要什麼,替戀人選擇餐點,付款,確認你給了正確的帳單或信用卡,檢查你是否被正確收費,確認訂單中的項目是否正確等等。 +然後,當輪到你時,你開始做真正「有生產力」的工作,處理菜單,決定你想要什麼,取得戀人的選擇,付款,確認你給了正確的帳單或信用卡,檢查你是否被正確收費,確認訂單中的項目是否正確等等。 但是,即使你還沒有拿到漢堡,你與收銀員的工作已經「暫停」了 ⏸,因為你必須等待 🕙 漢堡準備好。 但當你離開櫃檯,坐到桌子旁,拿著屬於你的號碼等待時,你可以把注意力 🔀 轉移到戀人身上,並開始「工作」⏯ 🤓——也就是和戀人調情 😍。這時你又開始做一些非常「有生產力」的事情。 -接著,收銀員 💁 將你的號碼顯示在櫃檯螢幕上,並告訴你「漢堡已經做好了」。但你不會瘋狂地立刻跳起來,因為顯示的號碼變成了你的。你知道沒有人會搶走你的漢堡,因為你有自己的號碼,他們也有他們的號碼。 +接著,收銀員 💁 透過把你的號碼顯示在櫃檯螢幕上,表示「漢堡已經做好了」,但你不會在顯示的號碼變成你的號碼時就瘋狂地立刻跳起來。你知道沒有人會搶走你的漢堡,因為你有自己的號碼,他們也有他們的號碼。 -所以你會等戀人講完故事(完成當前的工作 ⏯/正在進行的任務 🤓),然後微笑著溫柔地說你要去拿漢堡了 ⏸。 +所以你會等戀人講完故事(完成當前的工作 ⏯ / 正在進行的任務 🤓),然後微笑著溫柔地說你要去拿漢堡了 ⏸。 -然後你走向櫃檯 🔀,回到已經完成的最初任務 ⏯,拿起漢堡,說聲謝謝,並帶回桌上。這就結束了與櫃檯的互動步驟/任務 ⏹,接下來會產生一個新的任務,「吃漢堡」 🔀 ⏯,而先前的「拿漢堡」任務已經完成了 ⏹。 +然後你走向櫃檯 🔀,回到已經完成的最初任務 ⏯,拿起漢堡,說聲謝謝,並帶回桌上。這就結束了與櫃檯互動的步驟 / 任務 ⏹。接著,這又產生了一個新的任務,「吃漢堡」🔀 ⏯,而先前的「拿漢堡」任務已經完成了 ⏹。 ### 平行漢堡 { #parallel-burgers } @@ -181,19 +181,19 @@ def results(): -收銀員走進廚房準備食物。 +收銀員走進廚房。 你站在櫃檯前等待 🕙,以免其他人先拿走你的漢堡,因為這裡沒有號碼牌系統。 -由於你和戀人都忙著不讓別人搶走你的漢堡,等漢堡準備好時,你根本無法專心和戀人互動。😞 +由於你和戀人都忙著不讓別人插到你前面並在漢堡送來時拿走你的漢堡,你根本無法專心和戀人互動。😞 -這是「同步」(synchronous)工作,你和收銀員/廚師 👨‍🍳 是「同步化」的。你必須等到 🕙 收銀員/廚師 👨‍🍳 完成漢堡並交給你的那一刻,否則別人可能會拿走你的餐點。 +這是「同步」(synchronous)工作,你和收銀員 / 廚師 👨‍🍳 是「同步化」的。你必須等到 🕙 收銀員 / 廚師 👨‍🍳 完成漢堡並交給你的那一刻,否則別人可能會拿走你的餐點。 -最終,經過長時間的等待 🕙,收銀員/廚師 👨‍🍳 拿著漢堡回來了。 +最終,經過長時間在櫃檯前的等待 🕙,收銀員 / 廚師 👨‍🍳 拿著漢堡回來了。 @@ -203,7 +203,7 @@ def results(): -整個過程中沒有太多的談情說愛,因為大部分時間 🕙 都花在櫃檯前等待。😞 +整個過程中沒有太多聊天或談情說愛,因為大部分時間 🕙 都花在櫃檯前等待。😞 /// note | 注意 @@ -213,15 +213,15 @@ def results(): --- -在這個平行漢堡的情境下,你是一個程式 🤖 且有兩個處理器(你和戀人),兩者都在等待 🕙 並專注於等待櫃檯上的餐點 🕙,等待的時間非常長。 +在這個平行漢堡的情境下,你是一個程式 🤖 且有兩個處理器(你和戀人),兩者都在等待 🕙 並專注 ⏯ 於在櫃檯前等待 🕙,等待的時間非常長。 -這家速食店有 8 個處理器(收銀員/廚師)。而並行漢堡店可能只有 2 個處理器(一位收銀員和一位廚師)。 +這家速食店有 8 個處理器(收銀員 / 廚師)。而並行漢堡店可能只有 2 個處理器(一位收銀員和一位廚師)。 儘管如此,最終的體驗並不是最理想的。😞 --- -這是與漢堡類似的故事。🍔 +這是與漢堡類似的平行版本故事。🍔 一個更「現實」的例子,想像一間銀行。 @@ -241,29 +241,29 @@ def results(): 許多用戶正在使用你的應用程式,而你的伺服器則在等待 🕙 這些用戶不那麼穩定的網路來傳送請求。 -接著,再次等待 🕙 回應。 +接著,再次等待 🕙 回應回來。 -這種「等待」 🕙 通常以微秒來衡量,但累加起來,最終還是花費了很多等待時間。 +這種「等待」🕙 通常以微秒來衡量,但累加起來,最終還是花費了很多等待時間。 -這就是為什麼對於 Web API 來說,使用非同步程式碼 ⏸🔀⏯ 是非常有意味的。 +這就是為什麼對於 Web API 來說,使用非同步程式碼 ⏸🔀⏯ 是非常有意義的。 這種類型的非同步性正是 NodeJS 成功的原因(儘管 NodeJS 不是平行的),這也是 Go 語言作為程式語言的一個強大優勢。 -這與 **FastAPI** 所能提供的性能水平相同。 +這與 **FastAPI** 所能提供的效能水準相同。 -你可以同時利用並行性和平行性,進一步提升效能,這比大多數已測試的 NodeJS 框架都更快,並且與 Go 語言相當,而 Go 是一種更接近 C 的編譯語言([感謝 Starlette](https://www.techempower.com/benchmarks/#section=data-r17&hw=ph&test=query&l=zijmkf-1))。 +你可以同時利用平行性和非同步性,進一步提升效能,這比大多數已測試的 NodeJS 框架都更快,並且與 Go 語言相當,而 Go 是一種更接近 C 的編譯語言([這都要歸功於 Starlette](https://www.techempower.com/benchmarks/#section=data-r17&hw=ph&test=query&l=zijmkf-1))。 -### 並行比平行更好嗎? { #is-concurrency-better-than-parallelism } +### 並行比平行更好嗎 { #is-concurrency-better-than-parallelism } 不是的!這不是故事的本意。 並行與平行不同。並行在某些 **特定** 的需要大量等待的情境下表現更好。正因如此,並行在 Web 應用程式開發中通常比平行更有優勢。但並不是所有情境都如此。 -因此,為了平衡報導,想像下面這個短故事 +因此,為了平衡報導,想像下面這個短故事: > 你需要打掃一間又大又髒的房子。 -*是的,這就是全部的故事。* +*是的,這就是全部的故事*。 --- @@ -273,32 +273,32 @@ def results(): 無論輪流執行與否(並行),你都需要相同的工時完成任務,同時需要執行相同工作量。 -但是,在這種情境下,如果你可以邀請8位前收銀員/廚師(現在是清潔工)來幫忙,每個人(加上你)負責房子的某個區域,這樣你就可以 **平行** 地更快完成工作。 +但是,在這種情境下,如果你可以邀請 8 位前收銀員 / 廚師(現在是清潔工)來幫忙,每個人(加上你)負責房子的某個區域,這樣你就可以在額外協助下 **平行** 地更快完成工作。 在這個場景中,每個清潔工(包括你)都是一個處理器,完成工作的一部分。 -由於大多數的執行時間都花在實際的工作上(而不是等待),而電腦中的工作由 CPU 完成,因此這些問題被稱為「CPU 密集型」。 +由於大多數的執行時間都花在實際的工作上(而不是等待),而電腦中的工作由 CPU 完成,因此這些問題被稱為「CPU bound」。 --- -常見的 CPU 密集型操作範例包括那些需要進行複雜數學計算的任務。 +常見的 CPU bound 操作範例包括那些需要進行複雜數學計算的任務。 例如: -* **音訊**或**圖像處理**; -* **電腦視覺**:一張圖片由數百萬個像素組成,每個像素有 3 個值/顏色,處理這些像素通常需要同時進行大量計算; -* **機器學習**: 通常需要大量的「矩陣」和「向量」運算。想像一個包含數字的巨大電子表格,並所有的數字同時相乘; -* **深度學習**: 這是機器學習的子領域,同樣適用。只不過這不僅僅是一張數字表格,而是大量的數據集合,並且在很多情況下,你會使用特殊的處理器來構建或使用這些模型。 +* **音訊**或**圖像處理**。 +* **電腦視覺**:一張圖片由數百萬個像素組成,每個像素有 3 個值 / 顏色,處理這些像素通常需要同時進行大量計算。 +* **機器學習**:通常需要大量的「矩陣」和「向量」運算。想像一個包含數字的巨大電子表格,並將所有數字同時相乘。 +* **深度學習**:這是機器學習的子領域,同樣適用。只不過這不僅僅是一張要相乘的數字表格,而是大量的數據集合,並且在很多情況下,你會使用特殊的處理器來構建及 / 或使用這些模型。 ### 並行 + 平行: Web + 機器學習 { #concurrency-parallelism-web-machine-learning } 使用 **FastAPI**,你可以利用並行的優勢,這在 Web 開發中非常常見(這也是 NodeJS 的最大吸引力)。 -但你也可以利用平行與多行程 (multiprocessing)(讓多個行程同時運行) 的優勢來處理機器學習系統中的 **CPU 密集型**工作。 +但你也可以利用平行與多行程 (multiprocessing)(讓多個行程同時運行) 的優勢來處理機器學習系統中的 **CPU bound** 工作。 -這一點,再加上 Python 是 **資料科學**、機器學習,尤其是深度學習的主要語言,讓 **FastAPI** 成為資料科學/機器學習 Web API 和應用程式(以及許多其他應用程式)的絕佳選擇。 +這一點,再加上 Python 是 **資料科學**、機器學習,尤其是深度學習的主要語言,讓 **FastAPI** 成為資料科學 / 機器學習 Web API 和應用程式(以及許多其他應用程式)的絕佳選擇。 -想了解如何在生產環境中實現這種平行性,請參見 [部屬](deployment/index.md)。 +想了解如何在生產環境中實現這種平行性,請參見 [部署](deployment/index.md)。 ## `async` 和 `await` { #async-and-await } @@ -310,37 +310,37 @@ def results(): burgers = await get_burgers(2) ``` -這裡的關鍵是 `await`。它告訴 Python 必須等待 ⏸ `get_burgers(2)` 完成它的工作 🕙, 然後將結果儲存在 `burgers` 中。如此,Python 就可以在此期間去處理其他事情 🔀 ⏯ (例如接收另一個請求)。 +這裡的關鍵是 `await`。它告訴 Python 必須等待 ⏸ `get_burgers(2)` 完成它的工作 🕙,然後將結果儲存在 `burgers` 中。如此,Python 就可以在此期間去處理其他事情 🔀 ⏯(例如接收另一個請求)。 -要讓 `await` 運作,它必須位於支持非同步功能的函式內。為此,只需使用 `async def` 宣告函式: +要讓 `await` 運作,它必須位於支援非同步功能的函式內。為此,只需使用 `async def` 宣告函式: ```Python hl_lines="1" async def get_burgers(number: int): - # Do some asynchronous stuff to create the burgers + # 做一些非同步的事情來製作漢堡 return burgers ``` -...而不是 `def`: +...而不是 `def`: ```Python hl_lines="2" -# This is not asynchronous +# 這不是非同步的 def get_sequential_burgers(number: int): - # Do some sequential stuff to create the burgers + # 做一些循序的事情來製作漢堡 return burgers ``` -使用 `async def`,Python 知道在該函式內需要注意 `await`,並且它可以「暫停」 ⏸ 執行該函式,然後執行其他任務 🔀 後回來。 +使用 `async def`,Python 知道在該函式內需要注意 `await` 運算式,並且它可以「暫停」⏸ 執行該函式,然後執行其他任務 🔀 後回來。 當你想要呼叫 `async def` 函式時,必須使用「await」。因此,這樣寫將無法運行: ```Python -# This won't work, because get_burgers was defined with: async def +# 這不會運作,因為 get_burgers 是用 async def 定義的 burgers = get_burgers(2) ``` --- -如果你正在使用某個函式庫,它告訴你可以使用 `await` 呼叫它,那麼你需要用 `async def` 定義*路徑操作函式*,如: +如果你正在使用某個函式庫,它告訴你可以使用 `await` 呼叫它,那麼你需要用 `async def` 建立使用它的*路徑操作函式*,如: ```Python hl_lines="2-3" @app.get('/burgers') @@ -357,7 +357,7 @@ async def read_burgers(): 那麼,這就像「先有雞還是先有蛋」的問題,要如何呼叫第一個 `async` 函式呢? -如果你使用 FastAPI,無需擔心這個問題,因為「第一個」函式將是你的*路徑操作函式*,FastAPI 會知道如何正確處理這個問題。 +如果你使用 **FastAPI**,無需擔心這個問題,因為「第一個」函式將是你的*路徑操作函式*,FastAPI 會知道如何正確處理這個問題。 但如果你想在沒有 FastAPI 的情況下使用 `async` / `await`,你也可以這樣做。 @@ -367,9 +367,9 @@ Starlette(和 **FastAPI**)是基於 [AnyIO](https://anyio.readthedocs.io/en/ 特別是,你可以直接使用 [AnyIO](https://anyio.readthedocs.io/en/stable/) 來處理更複雜的並行使用案例,這些案例需要你在自己的程式碼中使用更高階的模式。 -即使你不使用 **FastAPI**,你也可以使用 [AnyIO](https://anyio.readthedocs.io/en/stable/) 來撰寫自己的非同步應用程式,並獲得高相容性及一些好處(例如「結構化並行」)。 +即使你不使用 FastAPI,你也可以使用 [AnyIO](https://anyio.readthedocs.io/en/stable/) 來撰寫自己的非同步應用程式,並獲得高相容性及一些好處(例如*結構化並行*)。 -我另外在 AnyIO 之上做了一個薄封裝的函式庫,稍微改進型別註解以獲得更好的**自動補全**、**即時錯誤**等。同時它也提供友善的介紹與教學,幫助你**理解**並撰寫**自己的非同步程式碼**:[Asyncer](https://asyncer.tiangolo.com/)。當你需要**將非同步程式碼與一般**(阻塞/同步)**程式碼整合**時,它特別實用。 +我另外在 AnyIO 之上做了一個薄封裝的函式庫,稍微改進型別註解以獲得更好的**自動補全**、**即時錯誤**等。同時它也提供友善的介紹與教學,幫助你**理解**並撰寫**自己的非同步程式碼**:[Asyncer](https://asyncer.tiangolo.com/)。當你需要**將非同步程式碼與一般**(阻塞 / 同步)**程式碼整合**時,它特別實用。 ### 其他形式的非同步程式碼 { #other-forms-of-asynchronous-code } @@ -381,21 +381,21 @@ Starlette(和 **FastAPI**)是基於 [AnyIO](https://anyio.readthedocs.io/en/ 但在此之前,處理非同步程式碼要更加複雜和困難。 -在較舊的 Python 版本中,你可能會使用多執行緒或 [Gevent](https://www.gevent.org/)。但這些程式碼要更難以理解、調試和思考。 +在較舊的 Python 版本中,你可能會使用多執行緒或 [Gevent](https://www.gevent.org/)。但這些程式碼要更難以理解、偵錯和思考。 -在較舊的 NodeJS / 瀏覽器 JavaScript 中,你會使用「回呼」,這可能會導致“回呼地獄”。 +在較舊的 NodeJS / 瀏覽器 JavaScript 中,你會使用「回呼」。這可能會導致「回呼地獄」。 ## 協程 { #coroutines } -「協程」只是 `async def` 函式所回傳的非常特殊的事物名稱。Python 知道它是一個類似函式的東西,可以啟動它,並且在某個時刻它會結束,但它也可能在內部暫停 ⏸,只要遇到 `await`。 +**協程**只是 `async def` 函式所回傳的非常特殊的事物名稱。Python 知道它是一個類似函式的東西,可以啟動它,並且在某個時刻它會結束,但它也可能在內部暫停 ⏸,只要遇到 `await`。 -這種使用 `async` 和 `await` 的非同步程式碼功能通常被概括為「協程」。這與 Go 語言的主要特性「Goroutines」相似。 +但這種使用 `async` 和 `await` 的非同步程式碼功能,通常被概括為使用「協程」。這與 Go 語言的主要特性「Goroutines」相似。 ## 結論 { #conclusion } 讓我們再次回顧之前的句子: -> 現代版本的 Python 支持使用 **"協程"** 的 **`async` 和 `await`** 語法來寫 **"非同步程式碼"**。 +> 現代版本的 Python 支援使用稱為 **「協程」** 的東西,透過 **`async` 和 `await`** 語法來寫 **「非同步程式碼」**。 現在應該能明白其含意了。✨ @@ -407,7 +407,7 @@ Starlette(和 **FastAPI**)是基於 [AnyIO](https://anyio.readthedocs.io/en/ 你大概可以跳過這段。 -這裡是有關 FastAPI 內部技術細節。 +這裡是有關 **FastAPI** 底層如何運作的非常技術性的細節。 如果你有相當多的技術背景(例如協程、執行緒、阻塞等),並且對 FastAPI 如何處理 `async def` 與常規 `def` 感到好奇,請繼續閱讀。 @@ -415,9 +415,9 @@ Starlette(和 **FastAPI**)是基於 [AnyIO](https://anyio.readthedocs.io/en/ ### 路徑操作函式 { #path-operation-functions } -當你使用 `def` 而不是 `async def` 宣告*路徑操作函式*時,該函式會在外部的執行緒池(threadpool)中執行,然後等待結果,而不是直接呼叫(因為這樣會阻塞伺服器)。 +當你使用一般的 `def` 而不是 `async def` 宣告*路徑操作函式*時,該函式會在外部的執行緒池(threadpool)中執行,然後等待結果,而不是直接呼叫(因為這樣會阻塞伺服器)。 -如果你來自於其他不以這種方式運作的非同步框架,而且你習慣於使用普通的 `def` 定義僅進行簡單計算的*路徑操作函式*,目的是獲得微小的性能增益(大約 100 奈秒),請注意,在 FastAPI 中,效果會完全相反。在這些情況下,最好使用 `async def`,除非你的*路徑操作函式*執行阻塞的 I/O 的程式碼。 +如果你來自於其他不以這種方式運作的非同步框架,而且你習慣於使用普通的 `def` 定義僅進行簡單計算的*路徑操作函式*,目的是獲得微小的效能增益(大約 100 奈秒),請注意,在 **FastAPI** 中,效果會完全相反。在這些情況下,最好使用 `async def`,除非你的*路徑操作函式*執行阻塞的 I/O 的程式碼。 不過,在這兩種情況下,**FastAPI** [仍然很快](index.md#performance),至少與你之前的框架相當(或者更快)。 @@ -427,18 +427,18 @@ Starlette(和 **FastAPI**)是基於 [AnyIO](https://anyio.readthedocs.io/en/ ### 子依賴項 { #sub-dependencies } -你可以擁有多個相互依賴的依賴項和[子依賴項](tutorial/dependencies/sub-dependencies.md)(作為函式定義的參數),其中一些可能是用 `async def` 宣告,也可能是用 `def` 宣告。它們仍然可以正常運作,用 `def` 定義的那些將會在外部的執行緒中呼叫(來自執行緒池),而不是被「等待」。 +你可以擁有多個相互依賴的依賴項和[子依賴項](tutorial/dependencies/sub-dependencies.md)(作為函式定義的參數),其中一些可能是用 `async def` 宣告,也可能是用一般的 `def` 宣告。它們仍然可以正常運作,用一般的 `def` 定義的那些將會在外部的執行緒中呼叫(來自執行緒池),而不是被「等待」。 ### 其他輔助函式 { #other-utility-functions } -你可以直接呼叫任何使用 `def` 或 `async def` 建立的其他輔助函式,FastAPI 不會影響你呼叫它們的方式。 +你可以直接呼叫任何使用一般的 `def` 或 `async def` 建立的其他輔助函式,FastAPI 不會影響你呼叫它們的方式。 -這與 FastAPI 為你呼叫*路徑操作函式*和依賴項的邏輯有所不同。 +這與 FastAPI 為你呼叫的函式有所不同:*路徑操作函式*和依賴項。 -如果你的輔助函式是用 `def` 宣告的,它將會被直接呼叫(按照你在程式碼中撰寫的方式),而不是在執行緒池中。如果該函式是用 `async def` 宣告,那麼你在呼叫時應該使用 `await` 等待其結果。 +如果你的輔助函式是用 `def` 宣告的一般函式,它將會被直接呼叫(按照你在程式碼中撰寫的方式),而不是在執行緒池中。如果該函式是用 `async def` 宣告,那麼你在程式碼中呼叫它時應該使用 `await` 等待其結果。 --- 再一次強調,這些都是非常技術性的細節,如果你特地在尋找這些資訊,這些內容可能會對你有幫助。 -否則,只需遵循上面提到的指引即可:趕時間嗎?。 +否則,只需遵循上面提到章節的指引即可:趕時間嗎?。 diff --git a/docs/zh-hant/docs/deployment/cloud.md b/docs/zh-hant/docs/deployment/cloud.md index 86d216ca6..caf05ec16 100644 --- a/docs/zh-hant/docs/deployment/cloud.md +++ b/docs/zh-hant/docs/deployment/cloud.md @@ -16,7 +16,7 @@ FastAPI Cloud 是 *FastAPI and friends* 開源專案的主要贊助與資金提 ## 雲端供應商 - 贊助商 { #cloud-providers-sponsors } -其他一些雲端供應商也會 ✨ [**贊助 FastAPI**](../help-fastapi.md#sponsor-the-author) ✨。🙇 +其他一些雲端供應商也會 ✨ [**贊助 FastAPI**](https://github.com/sponsors/tiangolo) ✨。🙇 你也可以參考他們的指南並試用其服務: diff --git a/docs/zh-hant/docs/deployment/concepts.md b/docs/zh-hant/docs/deployment/concepts.md index 0b8677bfd..070bcf544 100644 --- a/docs/zh-hant/docs/deployment/concepts.md +++ b/docs/zh-hant/docs/deployment/concepts.md @@ -1,5 +1,6 @@ # 部署概念 { #deployments-concepts } + 當你要部署一個 FastAPI 應用,或其實任何類型的 Web API 時,有幾個你可能在意的概念。掌握這些概念後,你就能找出最適合部署你應用的方式。 一些重要的概念包括: diff --git a/docs/zh-hant/docs/deployment/docker.md b/docs/zh-hant/docs/deployment/docker.md index 03b9f2f76..b10299def 100644 --- a/docs/zh-hant/docs/deployment/docker.md +++ b/docs/zh-hant/docs/deployment/docker.md @@ -132,7 +132,7 @@ Successfully installed fastapi pydantic
-/// info | 資訊 +/// note | 注意 還有其他格式與工具可以用來定義與安裝套件相依。 @@ -258,7 +258,7 @@ CMD fastapi run app/main.py --port 80 你可以在 [Docker 關於 shell 與 exec 形式的文件](https://docs.docker.com/reference/dockerfile/#shell-and-exec-form) 閱讀更多。 -使用 `docker compose` 時這會特別明顯。技術細節請見這段 Docker Compose 常見問題:[為什麼我的服務要花 10 秒才重新建立或停止?](https://docs.docker.com/compose/faq/#why-do-my-services-take-10-seconds-to-recreate-or-stop) +使用 `docker compose` 時這會特別明顯。技術細節請見這段 Docker Compose 常見問題:[為什麼我的服務要花 10 秒才重新建立或停止?](https://docs.docker.com/compose/faq/#why-do-my-services-take-10-seconds-to-recreate-or-stop)。 #### 目錄結構 { #directory-structure } @@ -454,7 +454,7 @@ Traefik 與 Docker、Kubernetes 等整合良好,因此為你的容器設定與 ## 複本 - 行程數量 { #replication-number-of-processes } -如果你在有 Kubernetes、Docker Swarm Mode、Nomad,或其他類似的分散式容器管理系統的「叢集」上運作,那你大概會希望在「叢集層級」處理「複本」,而不是在每個容器內使用「行程管理器」(例如帶有 workers 的 Uvicorn)。 +如果你在有 Kubernetes、Docker Swarm Mode、Nomad,或其他類似的分散式容器管理系統的「叢集」上運作,那你大概會希望在「叢集層級」處理「複本」,而不是在每個容器內使用「行程管理器」(例如帶有 workers 的 Uvicorn)。 像 Kubernetes 這類的分散式容器管理系統,通常內建處理「容器複本」以及支援進入請求的「負載平衡」的能力——全部都在「叢集層級」。 @@ -556,7 +556,7 @@ CMD ["fastapi", "run", "app/main.py", "--port", "80", "--workers", "4"] 如果你有「多個容器」,且每個容器大概都只執行「單一行程」(例如在一個 Kubernetes 叢集中),那你可能會想要一個「獨立的容器」來完成「前置步驟」的工作,並只在單一容器、單一行程中執行,接著才啟動多個複本的工作容器。 -/// info | 資訊 +/// note | 注意 如果你使用 Kubernetes,這大概會是一個 [Init Container](https://kubernetes.io/docs/concepts/workloads/pods/init-containers/)。 @@ -574,7 +574,7 @@ CMD ["fastapi", "run", "app/main.py", "--port", "80", "--workers", "4"] 你大概「不應該」使用這個基底 Docker 映像(或其他類似的)。 -如果你使用 Kubernetes(或其他)並已在叢集層級設定「複本」、使用多個「容器」。在這些情況下,更好的做法是如上所述[從零建置映像](#build-a-docker-image-for-fastapi)。 +如果你使用 Kubernetes(或其他)並已在叢集層級設定「複本」、使用多個「容器」。在這些情況下,更好的做法是如上所述「從零建置映像」:[為 FastAPI 建置 Docker 映像](#build-a-docker-image-for-fastapi)。 若你需要多個 workers,只要使用 `--workers` 命令列選項即可。 diff --git a/docs/zh-hant/docs/deployment/fastapicloud.md b/docs/zh-hant/docs/deployment/fastapicloud.md index 4b6fb86b4..0d5c5e7b1 100644 --- a/docs/zh-hant/docs/deployment/fastapicloud.md +++ b/docs/zh-hant/docs/deployment/fastapicloud.md @@ -1,26 +1,6 @@ # FastAPI Cloud { #fastapi-cloud } -你可以用「一行指令」把你的 FastAPI 應用程式部署到 [FastAPI Cloud](https://fastapicloud.com)。如果你還沒加入,快去登記等候名單吧!🚀 - -## 登入 { #login } - -請先確認你已經有 **FastAPI Cloud** 帳號(我們已從等候名單邀請你 😉)。 - -然後登入: - -
- -```console -$ fastapi login - -You are logged in to FastAPI Cloud 🚀 -``` - -
- -## 部署 { #deploy } - -現在用「一行指令」部署你的應用: +你可以只用 **一個指令** 就把你的 FastAPI 應用程式部署到 [FastAPI Cloud](https://fastapicloud.com)。🚀
@@ -36,6 +16,8 @@ Deploying to FastAPI Cloud...
+CLI 會自動偵測你的 FastAPI 應用並將其部署到雲端。若你尚未登入,瀏覽器會自動開啟以完成驗證流程。 + 就這樣!現在你可以透過該 URL 造訪你的應用。✨ ## 關於 FastAPI Cloud { #about-fastapi-cloud } diff --git a/docs/zh-hant/docs/deployment/https.md b/docs/zh-hant/docs/deployment/https.md index ddafcb34b..fead5a4b9 100644 --- a/docs/zh-hant/docs/deployment/https.md +++ b/docs/zh-hant/docs/deployment/https.md @@ -1,5 +1,6 @@ # 關於 HTTPS { #about-https } + 人們很容易以為 HTTPS 只是「啟用或未啟用」的功能。 但實際上複雜得多。 diff --git a/docs/zh-hant/docs/deployment/manually.md b/docs/zh-hant/docs/deployment/manually.md index 71e9e27c8..590d0b011 100644 --- a/docs/zh-hant/docs/deployment/manually.md +++ b/docs/zh-hant/docs/deployment/manually.md @@ -40,7 +40,7 @@ $ fastapi run fastapi run ASGI。FastAPI 是一個 ASGI 網頁框架。 -在遠端伺服器機器上執行 FastAPI 應用(或任何 ASGI 應用)所需的關鍵是 ASGI 伺服器程式,例如 Uvicorn;`fastapi` 指令預設就是使用它。 +在遠端伺服器機器上執行 **FastAPI** 應用(或任何 ASGI 應用)所需的關鍵是 ASGI 伺服器程式,例如 **Uvicorn**;`fastapi` 指令預設就是使用它。 有數個替代方案,包括: @@ -56,17 +56,16 @@ FastAPI 採用建立 Python 網頁框架與伺服器的標準 路徑
操作、參數、請求內文、安全性等宣告。 +* 使用 [**OpenAPI**](https://github.com/OAI/OpenAPI-Specification) 來建立 API,包含 路徑 操作、參數、請求內文、安全性等宣告。 * 使用 [**JSON Schema**](https://json-schema.org/)(因為 OpenAPI 本身就是基於 JSON Schema)自動生成資料模型文件。 * 經過縝密的研究後圍繞這些標準進行設計,而不是事後在已有系統上附加的一層功能。 * 這也讓我們在多種語言中可以使用自動**用戶端程式碼生成**。 ### 能夠自動生成文件 { #automatic-docs } -FastAPI 能生成互動式 API 文件和探索性的 Web 使用者介面。由於該框架基於 OpenAPI,因此有多種選擇,預設提供了兩種。 +互動式 API 文件與探索用的 Web 使用者介面。由於該框架基於 OpenAPI,因此有多種選擇,預設包含 2 種。 * [**Swagger UI**](https://github.com/swagger-api/swagger-ui) 提供互動式探索,讓你可以直接從瀏覽器呼叫並測試你的 API 。 @@ -27,22 +27,22 @@ FastAPI 能生成互動式 API 文件和探索性的 Web 使用者介面。由 這一切都基於標準的 **Python 型別**宣告(感謝 Pydantic)。無需學習新的語法,只需使用標準的現代 Python。 -如果你需要 2 分鐘來學習如何使用 Python 型別(即使你不使用 FastAPI),可以看看這個簡短的教學:[Python 型別](python-types.md)。 +如果你需要 2 分鐘來複習如何使用 Python 型別(即使你不使用 FastAPI),可以看看這個簡短的教學:[Python 型別](python-types.md)。 -如果你寫帶有 Python 型別的程式碼: +你撰寫帶有型別的標準 Python: ```Python from datetime import date from pydantic import BaseModel -# 宣告一個變數為 string -# 並在函式中獲得 editor support +# 將變數宣告為 str +# 並在函式內取得 editor support def main(user_id: str): return user_id -# 宣告一個 Pydantic model +# 一個 Pydantic model class User(BaseModel): id: int name: str @@ -65,9 +65,9 @@ my_second_user: User = User(**second_user_data) /// note -`**second_user_data` 意思是: +`**second_user_data` 意思是: -將 `second_user_data` 字典直接作為 key-value 引數傳遞,等同於:`User(id=4, name="Mary", joined="2018-11-30")` +將 `second_user_data` dict 的 keys 和 values 直接作為 key-value 引數傳遞,等同於:`User(id=4, name="Mary", joined="2018-11-30")` /// @@ -75,31 +75,31 @@ my_second_user: User = User(**second_user_data) 整個框架的設計是為了讓使用變得簡單且直觀,在開始開發之前,所有決策都在多個編輯器上進行了測試,以確保提供最佳的開發體驗。 -在最近的 Python 開發者調查中,我們能看到[被使用最多的功能是 autocompletion](https://www.jetbrains.com/research/python-developers-survey-2017/#tools-and-features)。 +在 Python 開發者調查中,我們能清楚看到[最常用的功能之一是「autocompletion」](https://www.jetbrains.com/research/python-developers-survey-2017/#tools-and-features)。 整個 **FastAPI** 框架就是基於這一點,任何地方都可以進行自動補齊。 -你幾乎不需要經常來回看文件。 +你很少需要回來查看文件。 在這裡,你的編輯器可能會這樣幫助你: -* 在 [Visual Studio Code](https://code.visualstudio.com/) 中: +* 在 [Visual Studio Code](https://code.visualstudio.com/) 中: ![editor support](https://fastapi.tiangolo.com/img/vscode-completion.png) -* 在 [PyCharm](https://www.jetbrains.com/pycharm/) 中: +* 在 [PyCharm](https://www.jetbrains.com/pycharm/) 中: ![editor support](https://fastapi.tiangolo.com/img/pycharm-completion.png) -你將能進行程式碼補齊,這是在之前你可能曾認為不可能的事。例如,請求 JSON body(可能是巢狀的)中的鍵 `price`。 +你將能進行程式碼補齊,這是在之前你可能曾認為不可能的事。例如,來自請求的 JSON body(可能是巢狀的)中的鍵 `price`。 這樣比較不會輸錯鍵名,不用來回翻看文件,也不用來回滾動尋找你最後使用的 `username` 或者 `user_name`。 ### 簡潔 { #short } -FastAPI 為你提供了**預設值**,讓你不必在初期進行繁瑣的配置,一切都可以自動運作。如果你有更具體的需求,則可以進行調整和自定義。 +它為所有內容提供合理的**預設值**,並且每處都可選擇性設定。所有參數都可以微調,以完成你需要的行為並定義你需要的 API。 -但預設情況下,一切都「直接可用」。 +但預設情況下,一切都 **「直接可用」**。 ### 驗證 { #validation } @@ -109,47 +109,47 @@ FastAPI 為你提供了**預設值**,讓你不必在初期進行繁瑣的配 * 字串 (`str`) 欄位,定義最小或最大長度。 * 數字 (`int`, `float`) 與其最大值和最小值等。 -* 驗證外來的型別,比如: - * URL - * Email - * UUID +* 驗證較特殊的型別,比如: + * URL。 + * Email。 + * UUID。 * ...等等。 所有的驗證都由完善且強大的 **Pydantic** 處理。 ### 安全性及身份驗證 { #security-and-authentication } -FastAPI 已經整合了安全性和身份驗證的功能,但不會強制與特定的資料庫或資料模型進行綁定。 +FastAPI 已經整合了安全性和身份驗證的功能。不需在資料庫或資料模型上妥協。 -OpenAPI 中定義的安全模式,包括: +OpenAPI 中定義的所有安全模式,包括: * HTTP 基本認證。 * **OAuth2**(也使用 **JWT tokens**)。在 [OAuth2 with JWT](tutorial/security/oauth2-jwt.md) 查看教學。 * API 密鑰,在: - * 標頭(Header) - * 查詢參數 + * 標頭。 + * 查詢參數。 * Cookies,等等。 -加上來自 Starlette(包括 **session cookie**)的所有安全特性。 +加上來自 Starlette(包括 **session cookies**)的所有安全特性。 -所有的這些都是可重複使用的工具和套件,可以輕鬆與你的系統、資料儲存(Data Stores)、關聯式資料庫(RDBMS)以及非關聯式資料庫(NoSQL)等等整合。 +所有的這些都是可重複使用的工具和元件,可以輕鬆與你的系統、資料儲存、關聯式和 NoSQL 資料庫等整合。 ### 依賴注入(Dependency Injection) { #dependency-injection } FastAPI 有一個使用簡單,但是非常強大的 依賴注入 系統。 -* 依賴項甚至可以有自己的依賴,從而形成一個層級或**依賴圖**的結構。 +* 依賴項甚至可以有自己的依賴,從而形成一個層級或**依賴項的「圖」**結構。 * 所有**自動化處理**都由框架完成。 -* 依賴項不僅能從請求中提取資料,還能**對 API 的路徑操作進行強化**,並自動生成文檔。 -* 即使是依賴項中定義的*路徑操作參數*,也會**自動進行驗證**。 -* 支持複雜的用戶身份驗證系統、**資料庫連接**等。 -* 不與資料庫、前端等進行強制綁定,但能輕鬆整合它們。 +* 所有依賴項都可以從請求中要求資料,並**擴充路徑操作**的限制條件與自動文件。 +* 即使是依賴項中定義的*路徑操作*參數,也會**自動進行驗證**。 +* 支援複雜的使用者身份驗證系統、**資料庫連接**等。 +* **不需妥協**資料庫、前端等。但能輕鬆整合它們。 ### 無限制「擴充功能」 { #unlimited-plug-ins } -或者說,無需其他額外配置,直接導入並使用你所需要的程式碼。 +或者說,其實不需要它們,匯入並使用你需要的程式碼即可。 -任何整合都被設計得非常簡單易用(通過依賴注入),你只需用與*路徑操作*相同的結構和語法,用兩行程式碼就能為你的應用程式建立一個「擴充功能」。 +任何整合都被設計得非常簡單易用(通過依賴),你只需用與*路徑操作*相同的結構和語法,用 2 行程式碼就能為你的應用程式建立一個「plug-in」。 ### 測試 { #tested } @@ -159,7 +159,9 @@ FastAPI 有一個使用簡單,但是非常強大的 ORMs、ODMs。 +相容包括同樣基於 Pydantic 的外部函式庫,例如用於資料庫的 ORMs 和 ODMs。 -這也意味著在很多情況下,你可以把從請求中獲得的物件**直接傳到資料庫**,因為所有資料都會自動進行驗證。 +這也意味著在很多情況下,你可以把從請求中獲得的相同物件**直接傳到資料庫**,因為所有資料都會自動進行驗證。 反之亦然,在很多情況下,你也可以把從資料庫中獲取的物件**直接傳給客戶端**。 通過 **FastAPI** 你可以獲得所有 **Pydantic** 的特性(FastAPI 基於 Pydantic 做了所有的資料處理): -* **更簡單**: - * 不需要學習新的 micro-language 來定義結構。 +* **不傷腦筋**: + * 不需要學習新的 schema 定義 micro-language。 * 如果你知道 Python 型別,你就知道如何使用 Pydantic。 -* 和你的 **IDE/linter/brain** 都能好好配合: - * 因為 Pydantic 的資料結構其實就是你自己定義的類別實例,所以自動補齊、linting、mypy 以及你的直覺都能很好地在經過驗證的資料上發揮作用。 +* 和你的 **IDE/linter/brain** 都能好好配合: + * 因為 pydantic 的資料結構其實就是你自己定義的類別實例,所以自動補齊、linting、mypy 以及你的直覺都能很好地在經過驗證的資料上發揮作用。 * 驗證**複雜結構**: - * 使用 Pydantic 模型時,你可以把資料結構分層設計,並且用 Python 的 `List` 和 `Dict` 等型別來定義。 + * 使用階層式 Pydantic 模型、Python `typing` 的 `List` 和 `Dict` 等。 * 驗證器讓我們可以輕鬆地定義和檢查複雜的資料結構,並把它們轉換成 JSON Schema 進行記錄。 - * 你可以擁有深層**巢狀的 JSON** 物件,並對它們進行驗證和註釋。 -* **可擴展**: - * Pydantic 讓我們可以定義客製化的資料型別,或者你可以使用帶有 validator 裝飾器的方法來擴展模型中的驗證功能。 + * 你可以擁有深層**巢狀的 JSON** 物件,並對它們進行驗證和註解。 +* **可擴充**: + * Pydantic 讓我們可以定義客製化的資料型別,或者你可以使用帶有 validator 裝飾器的方法來擴充模型中的驗證功能。 * 100% 測試覆蓋率。 diff --git a/docs/zh-hant/docs/help-fastapi.md b/docs/zh-hant/docs/help-fastapi.md index 69af48a56..4a4a4fda5 100644 --- a/docs/zh-hant/docs/help-fastapi.md +++ b/docs/zh-hant/docs/help-fastapi.md @@ -1,5 +1,6 @@ # 協助 { #help } + 你想要協助 FastAPI,或取得關於 FastAPI 的協助嗎? 有一些非常簡單的方式可以提供協助並取得協助。 diff --git a/docs/zh-hant/docs/how-to/configure-swagger-ui.md b/docs/zh-hant/docs/how-to/configure-swagger-ui.md index cbb63ef5e..37d9487b4 100644 --- a/docs/zh-hant/docs/how-to/configure-swagger-ui.md +++ b/docs/zh-hant/docs/how-to/configure-swagger-ui.md @@ -65,6 +65,6 @@ presets: [ ] ``` -這些是 JavaScript 物件,而不是字串,因此無法直接從 Python 程式碼傳遞。 +這些是 **JavaScript** 物件,而不是字串,因此無法直接從 Python 程式碼傳遞。 -若需要使用這類僅限 JavaScript 的設定,你可以使用上面介紹的方法:覆寫所有 Swagger UI 的路徑操作(path operation),並手動撰寫所需的 JavaScript。 +若需要使用這類僅限 JavaScript 的設定,你可以使用上述其中一種方法。覆寫整個 Swagger UI *路徑操作*,並手動撰寫所需的 JavaScript。 diff --git a/docs/zh-hant/docs/how-to/custom-request-and-route.md b/docs/zh-hant/docs/how-to/custom-request-and-route.md index 00031fcaa..afd097f51 100644 --- a/docs/zh-hant/docs/how-to/custom-request-and-route.md +++ b/docs/zh-hant/docs/how-to/custom-request-and-route.md @@ -104,6 +104,6 @@ {* ../../docs_src/custom_request_and_route/tutorial003_py310.py hl[26] *} -在此範例中,`router` 底下的路徑操作會使用自訂的 `TimedRoute` 類別,並在回應中多加上一個 `X-Response-Time` 標頭,標示產生該回應所花費的時間: +在此範例中,`router` 底下的 *路徑操作* 會使用自訂的 `TimedRoute` 類別,並在回應中多加上一個 `X-Response-Time` 標頭,標示產生該回應所花費的時間: {* ../../docs_src/custom_request_and_route/tutorial003_py310.py hl[13:20] *} diff --git a/docs/zh-hant/docs/how-to/extending-openapi.md b/docs/zh-hant/docs/how-to/extending-openapi.md index b5adca0f7..0a6ba5a59 100644 --- a/docs/zh-hant/docs/how-to/extending-openapi.md +++ b/docs/zh-hant/docs/how-to/extending-openapi.md @@ -25,9 +25,17 @@ * `openapi_version`:所使用的 OpenAPI 規格版本。預設為最新版本:`3.1.0`。 * `summary`:API 的簡短摘要。 * `description`:API 的描述,可包含 Markdown,會顯示在文件中。 -* `routes`:路由列表,也就是所有已註冊的路徑操作。來源為 `app.routes`。 +* `routes`:路由列表,來源為 `app.routes`。FastAPI 會用它們彙整已註冊的路徑操作,包含來自被包含的 routers。 -/// info +/// tip | 技術細節 + +`app.routes` 是較低階的路由樹。它可能包含 FastAPI 內部用於被包含的 routers 的候選路由,不僅僅是最終的 `APIRoute` 物件。 + +你仍然可以把 `app.routes` 傳給 `get_openapi()`。FastAPI 會遍歷那棵路由樹以收集實際生效的路徑操作。 + +/// + +/// note | 注意 `summary` 參數在 OpenAPI 3.1.0 以上可用,且需 FastAPI 0.99.0 以上版本支援。 diff --git a/docs/zh-hant/docs/how-to/graphql.md b/docs/zh-hant/docs/how-to/graphql.md index 24e4d8979..fce5f4119 100644 --- a/docs/zh-hant/docs/how-to/graphql.md +++ b/docs/zh-hant/docs/how-to/graphql.md @@ -1,22 +1,22 @@ # GraphQL { #graphql } -由於 FastAPI 基於 ASGI 標準,整合任何與 ASGI 相容的 GraphQL 函式庫都很容易。 +由於 **FastAPI** 基於 **ASGI** 標準,整合任何也相容於 ASGI 的 **GraphQL** 函式庫都很容易。 -你可以在同一個應用程式中同時使用一般的 FastAPI 路徑操作 (path operation) 與 GraphQL。 +你可以在同一個應用程式中同時使用一般的 FastAPI *路徑操作 (path operation)* 與 GraphQL。 /// tip -GraphQL 解決某些非常特定的使用情境。 +**GraphQL** 解決某些非常特定的使用情境。 -與一般的 Web API 相比,它有優點也有缺點。 +與一般的 **Web API** 相比,它有**優點**也有**缺點**。 -請確認在你的使用情境中,這些效益是否足以彌補其限制。 🤓 +請確認在你的使用情境中,這些**效益**是否足以彌補其**限制**。 🤓 /// ## GraphQL 函式庫 { #graphql-libraries } -下面是支援 ASGI 的部分 GraphQL 函式庫,你可以與 FastAPI 一起使用: +下面是支援 **ASGI** 的部分 **GraphQL** 函式庫,你可以與 **FastAPI** 一起使用: * [Strawberry](https://strawberry.rocks/) 🍓 * 提供 [FastAPI 文件](https://strawberry.rocks/docs/integrations/fastapi) @@ -29,9 +29,9 @@ GraphQL 解決某些非常特定的使用情境。 ## 使用 Strawberry 的 GraphQL { #graphql-with-strawberry } -如果你需要或想使用 GraphQL,[Strawberry](https://strawberry.rocks/) 是推薦的函式庫,因為它的設計與 FastAPI 最接近,全部都基於型別註解 (type annotations)。 +如果你需要或想使用 **GraphQL**,[**Strawberry**](https://strawberry.rocks/) 是**推薦的**函式庫,因為它的設計最接近 **FastAPI** 的設計,全部都基於**型別註解**。 -視你的使用情境而定,你可能會偏好其他函式庫,但如果你問我,我大概會建議你先試試 Strawberry。 +視你的使用情境而定,你可能會偏好其他函式庫,但如果你問我,我大概會建議你先試試 **Strawberry**。 以下是如何將 Strawberry 與 FastAPI 整合的一個小例子: @@ -45,7 +45,7 @@ GraphQL 解決某些非常特定的使用情境。 早期版本的 Starlette 提供 `GraphQLApp` 類別以整合 [Graphene](https://graphene-python.org/)。 -它已在 Starlette 中被棄用,但如果你的程式碼使用了它,可以輕鬆遷移到 [starlette-graphene3](https://github.com/ciscorn/starlette-graphene3),涵蓋相同的使用情境,且介面幾乎相同。 +它已在 Starlette 中被棄用,但如果你的程式碼使用了它,可以輕鬆**遷移**到 [starlette-graphene3](https://github.com/ciscorn/starlette-graphene3),涵蓋相同的使用情境,且介面**幾乎相同**。 /// tip @@ -55,6 +55,6 @@ GraphQL 解決某些非常特定的使用情境。 ## 進一步了解 { #learn-more } -你可以在 [官方 GraphQL 文件](https://graphql.org/) 中進一步了解 GraphQL。 +你可以在 [官方 GraphQL 文件](https://graphql.org/) 中進一步了解 **GraphQL**。 你也可以透過上述連結閱讀各個函式庫的更多內容。 diff --git a/docs/zh-hant/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md b/docs/zh-hant/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md index 4495e3dd7..77a58251e 100644 --- a/docs/zh-hant/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md +++ b/docs/zh-hant/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md @@ -8,6 +8,8 @@ FastAPI 0.119.0 透過 Pydantic v2 內的 `pydantic.v1` 提供對 Pydantic v1 FastAPI 0.126.0 移除了對 Pydantic v1 的支援,但在一段時間內仍支援 `pydantic.v1`。 +FastAPI 0.128.0 也移除了對 `pydantic.v1` 的支援,因此最新版本的 FastAPI 需要 Pydantic v2。 + /// warning Pydantic 團隊自 **Python 3.14** 起,已停止在最新的 Python 版本中支援 Pydantic v1。 @@ -46,7 +48,7 @@ Pydantic 提供從 v1 遷移到 v2 的官方[遷移指南](https://docs.pydantic ## v2 中的 Pydantic v1 { #pydantic-v1-in-v2 } -Pydantic v2 內含子模組 `pydantic.v1`,提供 Pydantic v1 的所有內容。但在 Python 3.13 以上版本不再支援。 +Pydantic v2 內含子模組 `pydantic.v1`,提供 Pydantic v1 的所有內容。但在 Python 3.13 之後的版本不再支援。 這表示你可以安裝最新的 Pydantic v2,並從該子模組匯入並使用舊的 Pydantic v1 元件,就像安裝了舊版 Pydantic v1 一樣。 @@ -54,6 +56,16 @@ Pydantic v2 內含子模組 `pydantic.v1`,提供 Pydantic v1 的所有內容 ### FastAPI 對 v2 中 Pydantic v1 的支援 { #fastapi-support-for-pydantic-v1-in-v2 } +/// warning + +FastAPI 對 `pydantic.v1` 模型的支援是在 **FastAPI 0.119.0** 加入,並在 **FastAPI 0.128.0** 移除。這原本是為了遷移到 Pydantic v2 而提供的臨時協助。 + +在目前版本的 FastAPI 中,在你的應用使用 `pydantic.v1` 模型會引發錯誤。 + +本節其餘內容描述的是只在那些較舊版本中可用的臨時支援。 + +/// + 自 FastAPI 0.119.0 起,也支援透過 Pydantic v2 內的 Pydantic v1(部分)以協助遷移至 v2。 因此,你可以先升級到最新的 Pydantic v2,並將匯入改為使用 `pydantic.v1` 子模組,在多數情況下即可正常運作。 @@ -122,6 +134,12 @@ graph TB ### 分步遷移 { #migrate-in-steps } +/// warning + +以下描述的,在同一應用中同時使用 Pydantic v1 與 v2 模型進行漸進式遷移,只適用於 **FastAPI 0.119.0 到 0.127.x**。這項支援已在 **FastAPI 0.128.0** 移除,最新版本需要 **Pydantic v2** 模型。 + +/// + /// tip 先嘗試使用 `bump-pydantic`,如果測試通過且一切正常,你就能用一條指令完成遷移。✨ diff --git a/docs/zh-hant/docs/how-to/separate-openapi-schemas.md b/docs/zh-hant/docs/how-to/separate-openapi-schemas.md index 2ecb6afbc..72a806b4c 100644 --- a/docs/zh-hant/docs/how-to/separate-openapi-schemas.md +++ b/docs/zh-hant/docs/how-to/separate-openapi-schemas.md @@ -1,8 +1,8 @@ # 是否將輸入與輸出使用不同的 OpenAPI 結構描述 { #separate-openapi-schemas-for-input-and-output-or-not } -自從 Pydantic v2 發佈後,生成的 OpenAPI 比以往更精確也更正確。😎 +自從 **Pydantic v2** 發佈後,生成的 OpenAPI 比以往更精確也更**正確**。😎 -實際上,在某些情況下,同一個 Pydantic 模型在 OpenAPI 中會同時有兩個 JSON Schema:分別用於輸入與輸出,這取決於它是否有預設值。 +實際上,在某些情況下,同一個 Pydantic 模型在 OpenAPI 中會同時有**兩個 JSON Schema**:分別用於輸入與輸出,這取決於它是否有**預設值**。 來看看它如何運作,以及若需要時該如何調整。 @@ -18,11 +18,11 @@ {* ../../docs_src/separate_openapi_schemas/tutorial001_py310.py ln[1:15] hl[14] *} -...則 `description` 欄位將不是必填。因為它的預設值是 `None`。 +...則 `description` 欄位將**不是必填**。因為它的預設值是 `None`。 ### 文件中的輸入模型 { #input-model-in-docs } -你可以在文件中確認,`description` 欄位沒有紅色星號,表示不是必填: +你可以在文件中確認,`description` 欄位沒有**紅色星號**,表示不是必填:
@@ -34,7 +34,7 @@ {* ../../docs_src/separate_openapi_schemas/tutorial001_py310.py hl[19] *} -...由於 `description` 有預設值,就算你沒有為該欄位回傳任何內容,它仍會有那個預設值。 +...由於 `description` 有預設值,就算你**沒有為該欄位回傳任何內容**,它仍會有那個**預設值**。 ### 輸出回應資料的模型 { #model-for-output-response-data } @@ -44,20 +44,20 @@
-這代表該欄位一定會有值,只是有時候值可能是 `None`(在 JSON 中為 `null`)。 +這代表該欄位**一定會有值**,只是有時候值可能是 `None`(在 JSON 中為 `null`)。 -因此,使用你 API 的用戶端不必檢查值是否存在,可以假設該欄位一定存在;只是有些情況下它的值會是預設的 `None`。 +因此,使用你 API 的用戶端不必檢查值是否存在,可以**假設該欄位一定存在**;只是有些情況下它的值會是預設的 `None`。 -在 OpenAPI 中,描述這種情況的方式是將該欄位標記為必填,因為它一定存在。 +在 OpenAPI 中,描述這種情況的方式是將該欄位標記為**必填**,因為它一定存在。 -因此,同一個模型的 JSON Schema 會依用於輸入或輸出而不同: +因此,同一個模型的 JSON Schema 會依用於**輸入或輸出**而不同: -- 用於輸入時,`description` 不是必填 -- 用於輸出時,`description` 是必填(且可能為 `None`,在 JSON 中為 `null`) +* 用於**輸入**時,`description` **不是必填** +* 用於**輸出**時,`description` 是**必填**(且可能為 `None`,在 JSON 中為 `null`) ### 文件中的輸出模型 { #model-for-output-in-docs } -你也可以在文件中檢視輸出模型,`name` 與 `description` 都以紅色星號標示為必填: +你也可以在文件中檢視輸出模型,`name` 與 `description` **兩者**都以**紅色星號**標示為**必填**:
@@ -67,25 +67,25 @@ 如果你查看 OpenAPI 中所有可用的結構描述(JSON Schema),會看到有兩個:`Item-Input` 與 `Item-Output`。 -對於 `Item-Input`,`description` 不是必填,沒有紅色星號。 +對於 `Item-Input`,`description` **不是必填**,沒有紅色星號。 -但對於 `Item-Output`,`description` 是必填,有紅色星號。 +但對於 `Item-Output`,`description` 是**必填**,有紅色星號。
-有了 Pydantic v2 的這個特性,你的 API 文件會更精確;若你有自動產生的用戶端與 SDK,它們也會更精確,提供更好的開發者體驗與一致性。🎉 +有了 **Pydantic v2** 的這個特性,你的 API 文件會更**精確**;若你有自動產生的用戶端與 SDK,它們也會更精確,提供更好的**開發者體驗**與一致性。🎉 ## 不要分開結構描述 { #do-not-separate-schemas } -不過,在某些情況下,你可能會希望輸入與輸出使用相同的結構描述。 +不過,在某些情況下,你可能會希望**輸入與輸出使用相同的結構描述**。 最常見的情境是:你已經有一些自動產生的用戶端程式碼/SDK,目前還不想全部更新;也許之後會做,但不是現在。 -在這種情況下,你可以在 FastAPI 中透過參數 `separate_input_output_schemas=False` 停用這個功能。 +在這種情況下,你可以在 **FastAPI** 中透過參數 `separate_input_output_schemas=False` 停用這個功能。 -/// info +/// note 自 FastAPI `0.102.0` 起新增 `separate_input_output_schemas` 的支援。🤓 @@ -95,7 +95,7 @@ ### 文件中輸入與輸出使用相同結構描述的模型 { #same-schema-for-input-and-output-models-in-docs } -此時輸入與輸出將共用同一個模型結構描述,只有 `Item`,其中 `description` 不是必填: +此時輸入與輸出將共用同一個模型結構描述,只有 `Item`,其中 `description` **不是必填**:
diff --git a/docs/zh-hant/docs/index.md b/docs/zh-hant/docs/index.md index 09974e59d..743357b96 100644 --- a/docs/zh-hant/docs/index.md +++ b/docs/zh-hant/docs/index.md @@ -277,7 +277,7 @@ INFO: Application startup complete.
關於指令 fastapi dev... -指令 `fastapi dev` 會讀取你的 `main.py`,偵測其中的 **FastAPI** 應用,並使用 [Uvicorn](https://www.uvicorn.dev) 啟動伺服器。 +指令 `fastapi dev` 會自動讀取你的 `main.py`,偵測其中的 **FastAPI** 應用,並使用 [Uvicorn](https://www.uvicorn.dev) 啟動伺服器。 預設情況下,`fastapi dev` 會在本機開發時啟用自動重新載入。 @@ -473,13 +473,13 @@ item: Item ![editor support](https://fastapi.tiangolo.com/img/vscode-completion.png) -若想看包含更多功能的完整範例,請參考 Tutorial - User Guide。 +若想看包含更多功能的完整範例,請參考 教學 - 使用者指南。 **劇透警告**:教學 - 使用者指南包含: * 來自不同來源的**參數**宣告:例如 **headers**、**cookies**、**form fields** 和 **files**。 * 如何設定**驗證限制**,如 `maximum_length` 或 `regex`。 -* 一個非常強大且易用的 **依賴注入** 系統。 +* 一個非常強大且易用的 **依賴注入** 系統。 * 安全與驗證,包含支援 **OAuth2** 搭配 **JWT tokens** 與 **HTTP Basic** 驗證。 * 宣告**深度巢狀 JSON 模型**的進階(但同樣簡單)技巧(感謝 Pydantic)。 * 與 [Strawberry](https://strawberry.rocks) 及其他函式庫的 **GraphQL** 整合。 @@ -492,9 +492,7 @@ item: Item ### 部署你的應用(可選) { #deploy-your-app-optional } -你也可以選擇將 FastAPI 應用部署到 [FastAPI Cloud](https://fastapicloud.com),如果你還沒加入,去登記等候名單吧。🚀 - -如果你已經有 **FastAPI Cloud** 帳號(我們已從等候名單邀請你 😉),你可以用一個指令部署你的應用。 +你可以選擇只用一個指令,將 FastAPI 應用部署到 [FastAPI Cloud](https://fastapicloud.com)。🚀
@@ -510,6 +508,8 @@ Deploying to FastAPI Cloud...
+CLI 會自動偵測你的 FastAPI 應用並將其部署到雲端。若你尚未登入,系統會開啟瀏覽器以完成驗證流程。 + 就這樣!現在你可以在該 URL 造訪你的應用。✨ #### 關於 FastAPI Cloud { #about-fastapi-cloud } @@ -520,7 +520,7 @@ Deploying to FastAPI Cloud... 它把用 FastAPI 開發應用的**開發者體驗**帶到**部署**到雲端的流程中。🎉 -FastAPI Cloud 是「FastAPI 與好朋友們」這些開源專案的主要贊助與資金來源。✨ +FastAPI Cloud 是 *FastAPI 與好朋友們* 這些開源專案的主要贊助與資金來源。✨ #### 部署到其他雲端供應商 { #deploy-to-other-cloud-providers } diff --git a/docs/zh-hant/docs/project-generation.md b/docs/zh-hant/docs/project-generation.md index fc5c8e465..862417aff 100644 --- a/docs/zh-hant/docs/project-generation.md +++ b/docs/zh-hant/docs/project-generation.md @@ -1,5 +1,6 @@ # 全端 FastAPI 範本 { #full-stack-fastapi-template } + 範本通常附帶特定的設定,但設計上具有彈性且可自訂。這讓你可以依專案需求調整與擴充,因此非常適合作為起點。🏁 你可以使用此範本快速起步,裡面已替你完成大量初始設定、安全性、資料庫,以及部分 API 端點。 diff --git a/docs/zh-hant/docs/python-types.md b/docs/zh-hant/docs/python-types.md index dc7160261..295921760 100644 --- a/docs/zh-hant/docs/python-types.md +++ b/docs/zh-hant/docs/python-types.md @@ -2,11 +2,11 @@ Python 支援可選用的「型別提示」(也稱為「型別註記」)。 -這些「型別提示」或註記是一種特殊語法,用來宣告變數的型別。 +這些 **「型別提示」** 或註記是一種特殊語法,用來宣告變數的型別。 為你的變數宣告型別後,編輯器與工具就能提供更好的支援。 -這裡只是關於 Python 型別提示的快速教學/複習。它只涵蓋使用在 **FastAPI** 時所需的最低限度...其實非常少。 +這裡只是關於 Python 型別提示的**快速教學/複習**。它只涵蓋使用在 **FastAPI** 時所需的最低限度...其實非常少。 **FastAPI** 完全是以這些型別提示為基礎,並因此帶來許多優勢與好處。 @@ -137,7 +137,7 @@ John Doe ### `typing` 模組 { #typing-module } -在一些其他情境中,你可能需要從標準程式庫的 `typing` 模組匯入一些東西,比如當你想宣告某個東西可以是「任何型別」時,可以用 `typing` 裡的 `Any`: +在一些其他情境中,你可能需要從標準程式庫的 `typing` 模組匯入一些東西,比如當你想宣告某個東西可以是「任何型別」時,可以用 `Any`: ```python from typing import Any @@ -151,7 +151,7 @@ def some_function(data: Any): 有些型別可以在方括號中接收「型別參數」,以定義其內部元素的型別,例如「字串的 list」可以宣告為 `list[str]`。 -這些能接收型別參數的型別稱為「泛型(Generic types)」或「Generics」。 +這些能接收型別參數的型別稱為 **泛型(Generic types)** 或 **Generics**。 你可以將相同的內建型別用作泛型(使用方括號並在裡面放型別): @@ -221,7 +221,7 @@ def some_function(data: Any): #### Union { #union } -你可以宣告一個變數可以是「多種型別」中的任一種,例如 `int` 或 `str`。 +你可以宣告一個變數可以是**多種型別**中的任一種,例如 `int` 或 `str`。 要這麼定義,你使用豎線(`|`)來分隔兩種型別。 @@ -263,9 +263,9 @@ def some_function(data: Any): -請注意,這表示「`one_person` 是類別 `Person` 的『實例(instance)』」。 +請注意,這表示「`one_person` 是類別 `Person` 的**實例(instance)**」。 -並不是「`one_person` 就是名為 `Person` 的『類別(class)』」。 +並不是「`one_person` 就是名為 `Person` 的**類別(class)**」。 ## Pydantic 模型 { #pydantic-models } @@ -295,7 +295,7 @@ def some_function(data: Any): ## 含中繼資料的型別提示 { #type-hints-with-metadata-annotations } -Python 也有一個功能,允許使用 `Annotated` 在這些型別提示中放入額外的中繼資料。 +Python 也有一個功能,允許使用 `Annotated` 在這些型別提示中放入**額外的中繼資料**。 你可以從 `typing` 匯入 `Annotated`。 @@ -305,15 +305,15 @@ Python 本身不會對這個 `Annotated` 做任何事。對編輯器與其他工 但你可以利用 `Annotated` 這個空間,來提供 **FastAPI** 額外的中繼資料,告訴它你希望應用程式如何運作。 -重要的是要記住,傳給 `Annotated` 的「第一個型別參數」才是「真正的型別」。其餘的,都是給其他工具用的中繼資料。 +重要的是要記住,傳給 `Annotated` 的**第一個*型別參數***才是**實際型別**。其餘的,都是給其他工具用的中繼資料。 目前你只需要知道 `Annotated` 的存在,而且它是標準的 Python。😎 -之後你會看到它有多「強大」。 +之後你會看到它有多**強大**。 /// tip | 提示 -因為這是「標準 Python」,所以你在編輯器、分析與重構程式碼的工具等方面,仍然能獲得「最佳的開發體驗」。✨ +因為這是**標準 Python**,所以你在編輯器、分析與重構程式碼的工具等方面,仍然能獲得**最佳的開發體驗**。✨ 而且你的程式碼也會與許多其他 Python 工具與程式庫非常相容。🚀 @@ -325,17 +325,17 @@ Python 本身不會對這個 `Annotated` 做任何事。對編輯器與其他工 在 **FastAPI** 中,你用型別提示來宣告參數,然後你會得到: -* 編輯器支援 -* 型別檢查 +* **編輯器支援**。 +* **型別檢查**。 ...而 **FastAPI** 也會用同樣的宣告來: -* 定義需求:來自請求的路徑參數、查詢參數、標頭、主體(body)、相依性等 -* 轉換資料:把請求中的資料轉成所需型別 -* 驗證資料:來自每個請求的資料: - * 當資料無效時,自動產生錯誤並回傳給用戶端 -* 使用 OpenAPI 書寫 API 文件: - * 之後會由自動的互動式文件介面所使用 +* **定義需求**:來自請求的路徑參數、查詢參數、標頭、主體(body)、相依性等。 +* **轉換資料**:把請求中的資料轉成所需型別。 +* **驗證資料**:來自每個請求的資料: + * 當資料無效時,產生回傳給用戶端的**自動錯誤**。 +* 使用 OpenAPI **記錄** API: + * 之後會由自動的互動式文件介面所使用。 這些現在聽起來可能有點抽象。別擔心。你會在[教學 - 使用者指南](tutorial/index.md)中看到它們的實際運作。 diff --git a/docs/zh-hant/docs/tutorial/bigger-applications.md b/docs/zh-hant/docs/tutorial/bigger-applications.md index 73adef3f0..624b2c2bc 100644 --- a/docs/zh-hant/docs/tutorial/bigger-applications.md +++ b/docs/zh-hant/docs/tutorial/bigger-applications.md @@ -17,16 +17,16 @@ FastAPI 提供了一個方便的工具,讓你在維持彈性的同時,幫你 ``` . ├── app -│   ├── __init__.py -│   ├── main.py -│   ├── dependencies.py -│   └── routers -│   │ ├── __init__.py -│   │ ├── items.py -│   │ └── users.py -│   └── internal -│   ├── __init__.py -│   └── admin.py +│ ├── __init__.py +│ ├── main.py +│ ├── dependencies.py +│ └── routers +│ │ ├── __init__.py +│ │ ├── items.py +│ │ └── users.py +│ └── internal +│ ├── __init__.py +│ └── admin.py ``` /// tip | 提示 @@ -396,9 +396,9 @@ from .routers.users import router /// note | 技術細節 -實際上,它會在內部為 `APIRouter` 中宣告的每一個「路徑操作」建立一個對應的「路徑操作」。 +當 router 被納入主應用時,FastAPI 會保留原本的 `APIRouter` 與其 `APIRoute` 仍然是活的。 -所以在幕後,它實際運作起來就像是一個單一的應用。 +這表示自訂的 `APIRouter` 與 `APIRoute` 子類別在被納入之後依然會參與運作。 /// @@ -406,7 +406,7 @@ from .routers.users import router 把 router 納入時不需要擔心效能。 -這只會在啟動時花費微秒等級,且只發生一次。 +這個設計相當輕量,且避免為每次請求增加額外負擔。 因此不會影響效能。⚡ @@ -461,7 +461,7 @@ from .routers.users import router 這是因為我們要把它們的路徑操作包含進 OpenAPI 結構與使用者介面中。 -由於無法將它們隔離並獨立「掛載」,所以這些路徑操作會被「複製」(重新建立),而不是直接包含進來。 +FastAPI 會保留原始的 routers 與路徑操作處於活躍狀態,並在處理請求與產生 OpenAPI 時,合併 router 的前綴、相依性、標籤、回應與其他中繼資料。 /// @@ -532,4 +532,16 @@ $ fastapi dev router.include_router(other_router) ``` -請確保在把 `router` 納入 `FastAPI` 應用之前先這麼做,這樣 `other_router` 的路徑操作也會被包含進去。 +你可以在把 `router` 納入 `FastAPI` 應用的前或後這麼做。FastAPI 仍會在路由與 OpenAPI 中包含 `other_router` 的路徑操作。 + +同樣地,之後新增到這些 routers 的路徑操作也適用。透過先前的納入,它們也會被看見。 + +/// warning | 技術細節 + +避免在納入 router 之後直接修改 `router.routes`。FastAPI 將 router 的納入視為即時的,因此原始 router 與其 routes 仍然是路由與 OpenAPI 產生的一部分。 + +請使用有文件記載的 API,例如路徑操作的裝飾器與 `.include_router()` 來新增路由與 routers。 + +把 `router.routes` 視為較低階的路由樹結構,它可能同時包含路由定義與被納入的 routers,避免將它當成最終路徑操作的扁平清單來依賴。 + +/// diff --git a/docs/zh-hant/docs/tutorial/body-multiple-params.md b/docs/zh-hant/docs/tutorial/body-multiple-params.md index 1c334f51f..e511b2ea5 100644 --- a/docs/zh-hant/docs/tutorial/body-multiple-params.md +++ b/docs/zh-hant/docs/tutorial/body-multiple-params.md @@ -108,7 +108,7 @@ q: str | None = None {* ../../docs_src/body_multiple_params/tutorial004_an_py310.py hl[28] *} -/// info | 注意 +/// note | 注意 `Body` 也具有與 `Query`、`Path` 以及之後你會看到的其他工具相同的額外驗證與中繼資料參數。 @@ -123,7 +123,7 @@ q: str | None = None 但如果你想讓它像宣告多個 Body 參數時那樣,期望一個帶有 `item` 鍵、其內含模型內容的 JSON,你可以使用 `Body` 的特殊參數 `embed`: ```Python -item: Item = Body(embed=True) +item: Annotated[Item, Body(embed=True)] ``` 如下: diff --git a/docs/zh-hant/docs/tutorial/body-nested-models.md b/docs/zh-hant/docs/tutorial/body-nested-models.md index f7b8627b4..4e2e6427c 100644 --- a/docs/zh-hant/docs/tutorial/body-nested-models.md +++ b/docs/zh-hant/docs/tutorial/body-nested-models.md @@ -1,5 +1,6 @@ # Body - 巢狀模型 { #body-nested-models } + 使用 **FastAPI**,你可以定義、驗證、文件化,並使用任意深度的巢狀模型(感謝 Pydantic)。 ## 列表欄位 { #list-fields } @@ -134,8 +135,7 @@ my_list: list[str] ] } ``` - -/// info +/// note 注意 `images` 鍵現在是一個由 image 物件組成的列表。 @@ -147,7 +147,7 @@ my_list: list[str] {* ../../docs_src/body_nested_models/tutorial007_py310.py hl[7,12,18,21,25] *} -/// info +/// note 請注意,`Offer` 具有一個 `Item` 的列表,而每個 `Item` 又有一個可選的 `Image` 列表。 diff --git a/docs/zh-hant/docs/tutorial/body.md b/docs/zh-hant/docs/tutorial/body.md index 08246f513..f1ba8e954 100644 --- a/docs/zh-hant/docs/tutorial/body.md +++ b/docs/zh-hant/docs/tutorial/body.md @@ -8,7 +8,7 @@ 要宣告**請求**本文,你會使用 [Pydantic](https://docs.pydantic.dev/) 模型,享受其完整的功能與優點。 -/// info +/// note 要傳送資料,應使用下列其中一種方法:`POST`(最常見)、`PUT`、`DELETE` 或 `PATCH`。 @@ -32,6 +32,7 @@ {* ../../docs_src/body/tutorial001_py310.py hl[5:9] *} + 就和宣告查詢參數時一樣,當模型屬性有預設值時,它就不是必填;否則就是必填。使用 `None` 可使其成為選填。 例如,上述模型對應的 JSON「`object`」(或 Python `dict`)如下: @@ -135,6 +136,7 @@ {* ../../docs_src/body/tutorial003_py310.py hl[15:16] *} + ## 請求本文 + 路徑 + 查詢參數 { #request-body-path-query-parameters } 你也可以同時宣告**本文**、**路徑**與**查詢**參數。 diff --git a/docs/zh-hant/docs/tutorial/cookie-param-models.md b/docs/zh-hant/docs/tutorial/cookie-param-models.md index 8997903e3..7eade4b86 100644 --- a/docs/zh-hant/docs/tutorial/cookie-param-models.md +++ b/docs/zh-hant/docs/tutorial/cookie-param-models.md @@ -32,7 +32,7 @@
-/// info +/// note 請注意,由於**瀏覽器會以特殊且在背景進行的方式處理 Cookie**,因此**不會**輕易允許 **JavaScript** 存取它們。 diff --git a/docs/zh-hant/docs/tutorial/cookie-params.md b/docs/zh-hant/docs/tutorial/cookie-params.md index cc9d4b682..e24a87ede 100644 --- a/docs/zh-hant/docs/tutorial/cookie-params.md +++ b/docs/zh-hant/docs/tutorial/cookie-params.md @@ -24,19 +24,19 @@ /// -/// info +/// note 要宣告 cookies,你需要使用 `Cookie`,否則參數會被當作查詢參數(query parameters)來解析。 /// -/// info +/// note -請注意,由於瀏覽器以特殊且在背後處理的方式管理 cookies,它們通常不允許 JavaScript 輕易存取它們。 +請注意,由於**瀏覽器會以特殊方式並在背後處理 cookies**,因此**不**容易讓 **JavaScript** 觸碰到它們。 -如果你前往位於 `/docs` 的 API 文件介面,你可以在你的路徑操作(path operations)的文件中看到 cookies 的說明。 +如果你前往位於 `/docs` 的 **API 文件介面**,你可以在你的*路徑操作(path operations)*中看到 cookies 的**文件**。 -但即使你填入資料並點擊「Execute」,由於該文件介面是以 JavaScript 運作,cookies 不會被送出,你會看到一則錯誤訊息,就好像你沒有填任何值一樣。 +但即使你**填入資料**並點擊「Execute」,由於該文件介面是以 **JavaScript** 運作,cookies 不會被送出,你會看到一則**錯誤**訊息,就好像你沒有填任何值一樣。 /// diff --git a/docs/zh-hant/docs/tutorial/debugging.md b/docs/zh-hant/docs/tutorial/debugging.md index 1230ed6cc..a3254e3d1 100644 --- a/docs/zh-hant/docs/tutorial/debugging.md +++ b/docs/zh-hant/docs/tutorial/debugging.md @@ -1,5 +1,6 @@ # 偵錯 { #debugging } + 你可以在編輯器中連接偵錯器,例如 Visual Studio Code 或 PyCharm。 ## 呼叫 `uvicorn` { #call-uvicorn } @@ -72,7 +73,7 @@ from myapp import app 就不會被執行。 -/// info | 說明 +/// note 想了解更多,參考 [Python 官方文件](https://docs.python.org/3/library/__main__.html)。 diff --git a/docs/zh-hant/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md b/docs/zh-hant/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md index bd5711624..0b548b8e8 100644 --- a/docs/zh-hant/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md +++ b/docs/zh-hant/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md @@ -28,11 +28,11 @@ /// -/// info +/// note 在這個範例中我們使用了自訂的(虛構的)標頭 `X-Key` 與 `X-Token`。 -但在實際情況下,當你實作安全機制時,使用整合的 [Security utilities(下一章)](../security/index.md) 會獲得更多好處。 +但在實際情況下,當你實作安全機制時,使用整合的 [安全工具(下一章)](../security/index.md) 會獲得更多好處。 /// diff --git a/docs/zh-hant/docs/tutorial/dependencies/dependencies-with-yield.md b/docs/zh-hant/docs/tutorial/dependencies/dependencies-with-yield.md index 8174dca40..c41f3ba7d 100644 --- a/docs/zh-hant/docs/tutorial/dependencies/dependencies-with-yield.md +++ b/docs/zh-hant/docs/tutorial/dependencies/dependencies-with-yield.md @@ -170,7 +170,7 @@ participant tasks as Background tasks end ``` -/// info +/// note 只會向用戶端送出「一個回應」。可能是其中一個錯誤回應,或是來自該路徑操作的回應。 @@ -234,6 +234,7 @@ participant operation as Path Operation 含 `yield` 的相依隨時間演進,以涵蓋不同的使用情境並修正一些問題。 如果你想了解在不同 FastAPI 版本中改了哪些內容,可以在進階指南中閱讀:[進階相依 — 含 `yield`、`HTTPException`、`except` 與背景任務的相依](../../advanced/advanced-dependencies.md#dependencies-with-yield-httpexception-except-and-background-tasks)。 + ## 情境管理器 { #context-managers } ### 什麼是「情境管理器」 { #what-are-context-managers } diff --git a/docs/zh-hant/docs/tutorial/dependencies/index.md b/docs/zh-hant/docs/tutorial/dependencies/index.md index 86aea50f0..04d2019b7 100644 --- a/docs/zh-hant/docs/tutorial/dependencies/index.md +++ b/docs/zh-hant/docs/tutorial/dependencies/index.md @@ -49,7 +49,7 @@ 然後它只會回傳一個包含這些值的 `dict`。 -/// info | 說明 +/// note | 注意 FastAPI 在 0.95.0 版新增了對 `Annotated` 的支援(並開始建議使用)。 @@ -104,7 +104,7 @@ common_parameters --> read_users 如此一來,你只需撰寫一次共用程式碼,**FastAPI** 會替你的各個「路徑操作」呼叫它。 -/// check | 檢查 +/// tip | 提示 注意,你不必建立特殊的類別並把它傳到 **FastAPI** 去「註冊」或做類似的事。 diff --git a/docs/zh-hant/docs/tutorial/dependencies/sub-dependencies.md b/docs/zh-hant/docs/tutorial/dependencies/sub-dependencies.md index 50c4e1790..a2a2ac308 100644 --- a/docs/zh-hant/docs/tutorial/dependencies/sub-dependencies.md +++ b/docs/zh-hant/docs/tutorial/dependencies/sub-dependencies.md @@ -35,7 +35,7 @@ {* ../../docs_src/dependencies/tutorial005_an_py310.py hl[23] *} -/// info +/// note 注意,在路徑操作函式中我們只宣告了一個相依項 `query_or_cookie_extractor`。 diff --git a/docs/zh-hant/docs/tutorial/extra-data-types.md b/docs/zh-hant/docs/tutorial/extra-data-types.md index a5573379d..23c753232 100644 --- a/docs/zh-hant/docs/tutorial/extra-data-types.md +++ b/docs/zh-hant/docs/tutorial/extra-data-types.md @@ -1,5 +1,6 @@ # 額外的資料型別 { #extra-data-types } + 到目前為止,你一直在使用常見的資料型別,例如: * `int` diff --git a/docs/zh-hant/docs/tutorial/extra-models.md b/docs/zh-hant/docs/tutorial/extra-models.md index f5509f531..162325e9d 100644 --- a/docs/zh-hant/docs/tutorial/extra-models.md +++ b/docs/zh-hant/docs/tutorial/extra-models.md @@ -4,9 +4,9 @@ 對使用者模型尤其如此,因為: -* 「輸入模型」需要能包含密碼。 -* 「輸出模型」不應包含密碼。 -* 「資料庫模型」通常需要儲存雜湊後的密碼。 +* **輸入模型**需要能包含密碼。 +* **輸出模型**不應包含密碼。 +* **資料庫模型**通常需要儲存雜湊後的密碼。 /// danger @@ -140,7 +140,7 @@ UserInDB( ## 減少重複 { #reduce-duplication } -減少程式碼重複是 FastAPI 的核心理念之一。 +減少程式碼重複是 **FastAPI** 的核心理念之一。 因為重複的程式碼會提高發生錯誤、安全性問題、程式不同步(某處更新但其他處未更新)等風險。 @@ -176,7 +176,7 @@ UserInDB( 此範例中,我們將 `Union[PlaneItem, CarItem]` 作為引數 `response_model` 的值。 -由於這裡是把它當作引數的「值」傳入,而非用於型別註記,因此即使在 Python 3.10 也必須使用 `Union`。 +由於這裡是把它當作**引數的值**傳入,而非放在**型別註記**中,因此即使在 Python 3.10 也必須使用 `Union`。 若用於型別註記,則可以使用直線(|),如下: @@ -184,7 +184,7 @@ UserInDB( some_variable: PlaneItem | CarItem ``` -但若寫成指定值 `response_model=PlaneItem | CarItem` 會發生錯誤,因為 Python 會嘗試在 `PlaneItem` 與 `CarItem` 之間執行「無效運算」,而非將其視為型別註記。 +但若寫成指定值 `response_model=PlaneItem | CarItem` 會發生錯誤,因為 Python 會嘗試在 `PlaneItem` 與 `CarItem` 之間執行**無效運算**,而非將其視為型別註記。 ## 模型的清單 { #list-of-models } @@ -208,4 +208,4 @@ some_variable: PlaneItem | CarItem 依情境使用多個 Pydantic 模型並靈活繼承。 -當一個實體需要呈現不同「狀態」時,不必侷限於一個資料模型。例如使用者這個實體,可能有包含 `password`、包含 `password_hash`,或不含密碼等不同狀態。 +當一個實體需要呈現不同「狀態」時,不必侷限於一個資料模型。**使用者**「實體」是一個例子,可能有包含 `password`、包含 `password_hash`,或不含密碼等不同狀態。 diff --git a/docs/zh-hant/docs/tutorial/first-steps.md b/docs/zh-hant/docs/tutorial/first-steps.md index d6b1a72e3..bc023cc39 100644 --- a/docs/zh-hant/docs/tutorial/first-steps.md +++ b/docs/zh-hant/docs/tutorial/first-steps.md @@ -137,9 +137,9 @@ OpenAPI 為你的 API 定義了 API 的 schema。而該 schema 會包含你的 A #### OpenAPI 的用途 { #what-is-openapi-for } -OpenAPI schema 驅動了兩個互動式文件系統。 +OpenAPI schema 驅動了內建的兩個互動式文件系統。 -而且有許多替代方案,所有這些都是基於 OpenAPI。你可以輕鬆地將任何這些替代方案添加到使用 **FastAPI** 建置的應用程式中。 +而且有數十種替代方案,所有這些都是基於 OpenAPI。你可以輕鬆地將任何這些替代方案加入到使用 **FastAPI** 建置的應用程式中。 你也可以用它自動生成程式碼,讓用戶端與你的 API 通訊。例如前端、手機或物聯網(IoT)應用程式。 @@ -180,7 +180,7 @@ entrypoint = "backend.main:app" from backend.main import app ``` -### 搭配路徑使用 `fastapi dev` { #fastapi-dev-with-path } +### 使用路徑或 `--entrypoint` 命令列選項執行 `fastapi dev` { #fastapi-dev-with-path-or-with-entrypoint-cli-option } 你也可以把檔案路徑傳給 `fastapi dev` 指令,它會自動猜測要使用的 FastAPI app 物件: @@ -188,29 +188,19 @@ from backend.main import app $ fastapi dev main.py ``` -但這樣每次執行 `fastapi` 指令時都要記得傳入正確路徑。 - -此外,其他工具可能找不到它,例如 [VS Code 擴充套件](../editor-support.md) 或 [FastAPI Cloud](https://fastapicloud.com),因此建議在 `pyproject.toml` 中使用 `entrypoint`。 - -### 部署你的應用程式(可選) { #deploy-your-app-optional } - -你可以選擇將你的 FastAPI 應用程式部署到 [FastAPI Cloud](https://fastapicloud.com),如果還沒有,去加入候補名單吧。🚀 - -如果你已經有 **FastAPI Cloud** 帳號(我們已從候補名單邀請你 😉),你可以用一個指令部署你的應用程式。 - -部署之前,先確保你已登入: - -
+或者,你也可以把 `--entrypoint` 選項傳給 `fastapi dev` 指令: ```console -$ fastapi login - -You are logged in to FastAPI Cloud 🚀 +$ fastapi dev --entrypoint main:app ``` -
+但這樣每次執行 `fastapi` 指令時都要記得傳入正確的路徑\entrypoint。 + +此外,其他工具可能找不到它,例如 [VS Code 擴充套件](../editor-support.md) 或 [FastAPI Cloud](https://fastapicloud.com),因此建議在 `pyproject.toml` 中使用 `entrypoint`。 -接著部署你的應用程式: +### 部署你的應用程式(可選) { #deploy-your-app-optional } + +你可以選擇將你的 FastAPI 應用程式部署到 [FastAPI Cloud](https://fastapicloud.com),只要一行指令。🚀
@@ -226,6 +216,8 @@ Deploying to FastAPI Cloud...
+CLI 會自動偵測你的 FastAPI 應用並將它部署到雲端。若你尚未登入,瀏覽器會開啟以完成驗證流程。 + 就這樣!現在你可以透過該 URL 存取你的應用程式了。✨ ## 逐步回顧 { #recap-step-by-step } @@ -234,7 +226,7 @@ Deploying to FastAPI Cloud... {* ../../docs_src/first_steps/tutorial001_py310.py hl[1] *} -`FastAPI` 是一個 Python 類別,提供所有 API 的全部功能。 +`FastAPI` 是一個 Python 類別,提供你的 API 所需的所有功能。 /// note | 技術細節 @@ -252,7 +244,7 @@ Deploying to FastAPI Cloud... 這將是你建立所有 API 的主要互動點。 -### 第三步:建立一個「路徑操作」 { #step-3-create-a-path-operation } +### 第三步:建立一個*路徑操作* { #step-3-create-a-path-operation } #### 路徑 { #path } @@ -264,13 +256,13 @@ Deploying to FastAPI Cloud... https://example.com/items/foo ``` -……的路徑將會是: +...的路徑將會是: ``` /items/foo ``` -/// info +/// note 「路徑」也常被稱為「端點 endpoint」或「路由 route」。 @@ -289,7 +281,7 @@ https://example.com/items/foo * `PUT` * `DELETE` -……以及更少見的: +...以及更少見的: * `OPTIONS` * `HEAD` @@ -313,16 +305,16 @@ https://example.com/items/foo 我們將會稱它們為「**操作**」。 -#### 定義一個「路徑操作裝飾器」 { #define-a-path-operation-decorator } +#### 定義一個*路徑操作裝飾器* { #define-a-path-operation-decorator } {* ../../docs_src/first_steps/tutorial001_py310.py hl[6] *} -`@app.get("/")` 告訴 **FastAPI** 那個函式負責處理請求: +`@app.get("/")` 告訴 **FastAPI** 正下方的函式負責處理前往以下位置的請求: * 路徑 `/` -* 使用 get 操作 +* 使用 get 操作 -/// info | `@decorator` 說明 +/// note | `@decorator` 說明 Python 中的 `@something` 語法被稱為「裝飾器」。 @@ -361,7 +353,7 @@ Python 中的 `@something` 語法被稱為「裝飾器」。 /// -### 第四步:定義「路徑操作函式」 { #step-4-define-the-path-operation-function } +### 第四步:定義**路徑操作函式** { #step-4-define-the-path-operation-function } 這是我們的「**路徑操作函式**」: @@ -385,7 +377,7 @@ Python 中的 `@something` 語法被稱為「裝飾器」。 /// note -如果你不知道差別,請查看 [Async: *"In a hurry?"*](../async.md#in-a-hurry)。 +如果你不知道差別,請查看 [Async:*「很趕時間?」*](../async.md#in-a-hurry)。 /// @@ -407,11 +399,11 @@ Python 中的 `@something` 語法被稱為「裝飾器」。 **[FastAPI Cloud](https://fastapicloud.com)** 由 **FastAPI** 的作者與團隊打造。 -它讓你以最小的成本完成 API 的**建置**、**部署**與**存取**流程。 +它讓你以最少的心力簡化 API 的**建置**、**部署**與**存取**流程。 它把用 FastAPI 開發應用的同樣**開發者體驗**帶到將應用**部署**到雲端的流程中。🎉 -FastAPI Cloud 也是「FastAPI 與其好友」這些開源專案的主要贊助與資金提供者。✨ +FastAPI Cloud 也是 *FastAPI 與其好友* 這些開源專案的主要贊助與資金提供者。✨ #### 部署到其他雲端供應商 { #deploy-to-other-cloud-providers } @@ -423,7 +415,7 @@ FastAPI 是開源並基於標準的。你可以把 FastAPI 應用部署到你選 * 引入 `FastAPI`。 * 建立一個 `app` 實例。 -* 寫一個「路徑操作裝飾器」,像是 `@app.get("/")`。 -* 定義一個「路徑操作函式」;例如,`def root(): ...`。 +* 寫一個**路徑操作裝飾器**,像是 `@app.get("/")`。 +* 定義一個**路徑操作函式**;例如,`def root(): ...`。 * 使用命令 `fastapi dev` 執行開發伺服器。 * 可選:使用 `fastapi deploy` 部署你的應用程式。 diff --git a/docs/zh-hant/docs/tutorial/frontend.md b/docs/zh-hant/docs/tutorial/frontend.md new file mode 100644 index 000000000..0c568b9f5 --- /dev/null +++ b/docs/zh-hant/docs/tutorial/frontend.md @@ -0,0 +1,133 @@ +# 前端 { #frontend } + +你可以使用 `app.frontend()`(或 `router.frontend()`)來提供靜態前端應用程式。 + +這對會產生靜態檔案的前端工具很有用,例如搭配 Vite 的 React、TanStack Router、Astro、Vue、Svelte、Angular、Solid 等。 + +使用這些工具時,你通常會有一個建置前端的步驟,使用像這樣的指令: + +```bash +npm run build +``` + +那會產生像 `./dist/` 這樣的目錄,裡面包含你的前端檔案。 + +你可以使用 `app.frontend()` 依照這些前端框架所需的慣例來提供該目錄。 + +**FastAPI** 會先檢查*路徑操作*。只有在沒有一般路由符合時,才會檢查前端檔案,因此你的 API 不會受到影響。 + +## 提供前端 { #serve-a-frontend } + +在建置前端之後,例如使用 `npm run build`,將產生的檔案放在某個目錄中,例如 `dist`。 + +你的專案結構可能如下: + +```text +. +├── pyproject.toml +├── app +│ ├── __init__.py +│ └── main.py +└── dist + ├── index.html + └── assets + └── app.js +``` + +然後使用 `app.frontend()` 來提供它: + +{* ../../docs_src/frontend/tutorial001_py310.py hl[5] *} + +如此一來,對 `/assets/app.js` 的請求就可以提供 `dist/assets/app.js`。 + +如果你也有 **FastAPI** *路徑操作*,則*路徑操作*會優先。 + +## 用戶端路由 { #client-side-routing } + +許多前端應用程式,包括 **single-page apps**(SPAs),都會使用用戶端路由。像 `/dashboard/settings` 這樣的路徑可能不是真實檔案,而是由框架負責處理。 + +因此,如果直接存取該 URL(而不是透過應用程式內導覽),後端應該從 `index.html` 提供前端應用程式,讓前端框架接著處理用戶端路由。 + +為此,請使用 `fallback="index.html"`: + +{* ../../docs_src/frontend/tutorial002_py310.py hl[5] *} + +**FastAPI** 只會對看起來像瀏覽器導覽的 `GET` 和 `HEAD` 請求使用這個 fallback。遺失的檔案,例如 JavaScript、CSS 和圖片,仍會回傳 `404`。 + +對於只符合前端 fallback 的路徑,使用其他方法的請求,例如 `POST` 或 `PUT`,也會回傳 `404`。一般的 **FastAPI** *路徑操作*仍然比前端路由有更高優先順序。 + +/// tip + +預設情況下,`fallback` 的值是 `fallback="auto"`。在大多數情況下,你不需要指定 `fallback`。請閱讀下方內容以了解詳細資訊。 + +/// + +這正是許多使用用戶端路由的前端應用程式所需要的行為,例如搭配 TanStack Router 的 React、Vue、Angular、SvelteKit 或 Solid。 + +## 自訂 404 頁面 { #custom-404-page } + +你也可以為遺失的前端路徑提供靜態 `404.html` 頁面: + +{* ../../docs_src/frontend/tutorial003_py310.py hl[5] *} + +該回應會保留 `404` 狀態碼。 + +在這種情況下,**FastAPI** 不會為遺失的前端路徑提供 `index.html`。它會改為回傳 `404.html` 檔案。 + +/// tip + +預設情況下,`fallback` 的值是 `fallback="auto"`。如此一來,如果找到 `404.html` 檔案,就會自動將其用作 fallback。 + +因此,你通常可以省略 `fallback` 引數。 + +/// + +這對會為每個頁面產生靜態 HTML 檔案的前端工具很有用,例如 Astro。 + +## 自動 Fallback { #fallback-auto } + +預設情況下,`app.frontend()` 會使用 `fallback="auto"`。 + +如果前端目錄中有 `404.html` 檔案,遺失的前端路徑會提供該檔案,並使用狀態碼 `404`。 + +否則,如果有 `index.html` 檔案,遺失的瀏覽器導覽路徑會提供 `index.html`,這正是許多使用用戶端路由的前端應用程式所預期的行為。 + +因此,在大多數情況下,你可以使用 `app.frontend("/", directory="dist")`,而不需要指定 `fallback` 引數。 + +{* ../../docs_src/frontend/tutorial001_py310.py hl[5] *} + +## 停用 Fallback { #disable-fallback } + +如果你不想為遺失的前端路徑提供 fallback 檔案,請使用 `fallback=None`: + +{* ../../docs_src/frontend/tutorial005_py310.py hl[5] *} + +接著,遺失的前端路徑會回傳一般的 `404`。 + +## 檢查目錄 { #check-directory } + +預設情況下,`app.frontend()` 會在建立應用程式時檢查目錄是否存在。 + +這有助於及早發現設定錯誤。例如,如果缺少前端建置輸出目錄,**FastAPI** 會在啟動時引發錯誤。 + +如果你的前端檔案稍後才會建立,例如在建立 app 物件之後由另一個建置步驟產生,請設定 `check_dir=False`: + +{* ../../docs_src/frontend/tutorial006_py310.py hl[5] *} + +使用 `check_dir=False` 時,**FastAPI** 不會在建立應用程式時檢查目錄。如果在處理請求時,設定的目錄仍然不存在,**FastAPI** 會在那時引發錯誤。 + +## 與 `APIRouter` 搭配使用 { #use-it-with-apirouter } + +你也可以將前端檔案加入 `APIRouter`,並使用前綴包含它: + +{* ../../docs_src/frontend/tutorial004_py310.py hl[6,7] *} + +在這個範例中,前端路徑會在 `/app` 底下提供。 + +應用程式中的任何一般*路徑操作*仍會優先,包括其他 router 中的路徑操作。 + +## 僅限靜態建置輸出 { #static-build-output-only } + +`app.frontend()` 會提供你的前端建置已經產生的檔案。 + +它不會執行 server-side rendering。它適用於會產生靜態檔案的前端框架,不適用於需要在伺服器上為每個請求進行動態 rendering 的框架。 diff --git a/docs/zh-hant/docs/tutorial/handling-errors.md b/docs/zh-hant/docs/tutorial/handling-errors.md index b1ffd3e03..dc6d7a7cc 100644 --- a/docs/zh-hant/docs/tutorial/handling-errors.md +++ b/docs/zh-hant/docs/tutorial/handling-errors.md @@ -11,13 +11,13 @@ * 用戶端嘗試存取的項目不存在。 * 等等。 -在這些情況下,通常會回傳範圍為 400(400 到 499)的 HTTP 狀態碼。 +在這些情況下,通常會回傳範圍為 **400**(400 到 499)的 **HTTP 狀態碼**。 這類似於 200 範圍的 HTTP 狀態碼(200 到 299)。那些「200」狀態碼表示請求在某種程度上是「成功」的。 400 範圍的狀態碼表示用戶端錯誤。 -還記得那些「404 Not Found」錯誤(和梗)嗎? +還記得那些 **「404 Not Found」** 錯誤(和梗)嗎? ## 使用 `HTTPException` { #use-httpexception } diff --git a/docs/zh-hant/docs/tutorial/index.md b/docs/zh-hant/docs/tutorial/index.md index e19121511..e20c9ca24 100644 --- a/docs/zh-hant/docs/tutorial/index.md +++ b/docs/zh-hant/docs/tutorial/index.md @@ -98,4 +98,4 @@ FastAPI 提供了 [VS Code 官方擴充功能](https://marketplace.visualstudio. 但首先你應該閱讀**教學 - 使用者指南**(你正在閱讀的內容)。 -它被設計成你可以使用**教學 - 使用者指南**來建立一個完整的應用程式,然後根據你的需求,使用一些額外的想法來擴展它。 +它被設計成你可以使用**教學 - 使用者指南**來建立一個完整的應用程式,然後根據你的需求,使用**進階使用者指南**中的一些額外想法,以不同方式擴展它。 diff --git a/docs/zh-hant/docs/tutorial/metadata.md b/docs/zh-hant/docs/tutorial/metadata.md index 720b5d87c..55fa4bdbf 100644 --- a/docs/zh-hant/docs/tutorial/metadata.md +++ b/docs/zh-hant/docs/tutorial/metadata.md @@ -1,6 +1,6 @@ # 中繼資料與文件 URL { #metadata-and-docs-urls } -你可以在你的 FastAPI 應用程式中自訂多項中繼資料設定。 +你可以在你的 **FastAPI** 應用程式中自訂多項中繼資料設定。 ## API 的中繼資料 { #metadata-for-api } @@ -11,7 +11,7 @@ | `title` | `str` | API 的標題。 | | `summary` | `str` | API 的簡短摘要。自 OpenAPI 3.1.0、FastAPI 0.99.0 起可用。 | | `description` | `str` | API 的簡短說明。可使用 Markdown。 | -| `version` | `string` | API 的版本號。這是你自己的應用程式版本,不是 OpenAPI 的版本,例如 `2.5.0`。 | +| `version` | `str` | API 的版本號。這是你自己的應用程式版本,不是 OpenAPI 的版本,例如 `2.5.0`。 | | `terms_of_service` | `str` | 指向 API 服務條款的 URL。若提供,必須是 URL。 | | `contact` | `dict` | 對外公開的 API 聯絡資訊。可包含多個欄位。
contact 欄位
參數型別說明
namestr聯絡人/組織的識別名稱。
urlstr指向聯絡資訊的 URL。必須是 URL 格式。
emailstr聯絡人/組織的電子郵件地址。必須是電子郵件格式。
| | `license_info` | `dict` | 對外公開的 API 授權資訊。可包含多個欄位。
license_info 欄位
參數型別說明
namestr必填(若有設定 license_info)。API 使用的授權名稱。
identifierstrAPI 的 [SPDX](https://spdx.org/licenses/) 授權表示式。identifier 欄位與 url 欄位互斥。自 OpenAPI 3.1.0、FastAPI 0.99.0 起可用。
urlstrAPI 所採用授權的 URL。必須是 URL 格式。
| @@ -46,7 +46,7 @@ 每個 dictionary 可包含: -* `name`(**必填**):一個 `str`,其值需與你在路徑操作與 `APIRouter`s 的 `tags` 參數中使用的標籤名稱相同。 +* `name`(**必填**):一個 `str`,其值需與你在*路徑操作*與 `APIRouter`s 的 `tags` 參數中使用的標籤名稱相同。 * `description`:一個 `str`,為該標籤的簡短描述。可使用 Markdown,並會顯示在文件介面中。 * `externalDocs`:一個 `dict`,描述外部文件,包含: * `description`:一個 `str`,外部文件的簡短描述。 @@ -70,13 +70,13 @@ ### 使用你的標籤 { #use-your-tags } -在你的路徑操作(以及 `APIRouter`s)上使用 `tags` 參數,將它們歸類到不同標籤下: +在你的*路徑操作*(以及 `APIRouter`s)上使用 `tags` 參數,將它們歸類到不同標籤下: {* ../../docs_src/metadata/tutorial004_py310.py hl[21,26] *} -/// info | 資訊 +/// note | 注意 -在 [Path Operation Configuration](path-operation-configuration.md#tags) 中閱讀更多關於標籤的內容。 +在 [路徑操作設定](path-operation-configuration.md#tags) 中閱讀更多關於標籤的內容。 /// @@ -108,10 +108,10 @@ 你可以設定內建的兩個文件使用者介面: -* Swagger UI:提供於 `/docs`。 +* **Swagger UI**:提供於 `/docs`。 * 可用 `docs_url` 參數設定其 URL。 * 設定 `docs_url=None` 可停用。 -* ReDoc:提供於 `/redoc`。 +* **ReDoc**:提供於 `/redoc`。 * 可用 `redoc_url` 參數設定其 URL。 * 設定 `redoc_url=None` 可停用。 diff --git a/docs/zh-hant/docs/tutorial/path-operation-configuration.md b/docs/zh-hant/docs/tutorial/path-operation-configuration.md index 9ca738a98..edd10178c 100644 --- a/docs/zh-hant/docs/tutorial/path-operation-configuration.md +++ b/docs/zh-hant/docs/tutorial/path-operation-configuration.md @@ -1,5 +1,6 @@ # 路徑操作設定 { #path-operation-configuration } + 你可以在你的「路徑操作裝飾器」中傳入多個參數來進行設定。 /// warning | 警告 @@ -72,13 +73,13 @@ {* ../../docs_src/path_operation_configuration/tutorial005_py310.py hl[18] *} -/// info | 資訊 +/// note | 注意 請注意,`response_description` 專指回應,而 `description` 則是針對整個「路徑操作」的一般描述。 /// -/// check | 檢查 +/// tip OpenAPI 規範要求每個「路徑操作」都必須有一個回應描述。 diff --git a/docs/zh-hant/docs/tutorial/path-params-numeric-validations.md b/docs/zh-hant/docs/tutorial/path-params-numeric-validations.md index 68eb837e9..fd8bf0cec 100644 --- a/docs/zh-hant/docs/tutorial/path-params-numeric-validations.md +++ b/docs/zh-hant/docs/tutorial/path-params-numeric-validations.md @@ -8,7 +8,7 @@ {* ../../docs_src/path_params_numeric_validations/tutorial001_an_py310.py hl[1,3] *} -/// info +/// note FastAPI 在 0.95.0 版加入並開始推薦使用 `Annotated`。 @@ -131,7 +131,7 @@ Python 不會對這個 `*` 做任何事,但它會知道後續的所有參數 * `lt`:小於(`l`ess `t`han) * `le`:小於或等於(`l`ess than or `e`qual) -/// info +/// note 你之後會看到的 `Query`、`Path` 與其他類別,都是共同父類別 `Param` 的子類別。 diff --git a/docs/zh-hant/docs/tutorial/path-params.md b/docs/zh-hant/docs/tutorial/path-params.md index d46e32bb1..4e8d3dd8f 100644 --- a/docs/zh-hant/docs/tutorial/path-params.md +++ b/docs/zh-hant/docs/tutorial/path-params.md @@ -20,7 +20,7 @@ 在這個例子裡,`item_id` 被宣告為 `int`。 -/// check +/// tip 這會在你的函式中提供編輯器支援,包括錯誤檢查、自動完成等。 @@ -34,7 +34,7 @@ {"item_id":3} ``` -/// check +/// tip 注意你的函式接收(並回傳)的值是 `3`,也就是 Python 的 `int`,而不是字串 `"3"`。 @@ -66,7 +66,7 @@ 同樣的錯誤也會在你提供 `float` 而不是 `int` 時出現,例如:[http://127.0.0.1:8000/items/4.2](http://127.0.0.1:8000/items/4.2) -/// check +/// tip 因此,搭配相同的 Python 型別宣告,**FastAPI** 會為你進行資料驗證。 @@ -82,7 +82,7 @@ -/// check +/// tip 同樣地,只要使用那個 Python 型別宣告,**FastAPI** 就會提供自動、互動式的文件(整合 Swagger UI)。 diff --git a/docs/zh-hant/docs/tutorial/query-params-str-validations.md b/docs/zh-hant/docs/tutorial/query-params-str-validations.md index 0932c8d90..99690708e 100644 --- a/docs/zh-hant/docs/tutorial/query-params-str-validations.md +++ b/docs/zh-hant/docs/tutorial/query-params-str-validations.md @@ -1,6 +1,6 @@ # 查詢參數與字串驗證 { #query-parameters-and-string-validations } -FastAPI 允許你為參數宣告額外的資訊與驗證。 +**FastAPI** 允許你為參數宣告額外的資訊與驗證。 以下面這個應用為例: @@ -18,18 +18,18 @@ FastAPI 會因為預設值是 `= None` 而知道 `q` 不是必填。 ## 額外驗證 { #additional-validation } -我們要強制:即使 `q` 是可選,只要提供了,長度就不能超過 50 個字元。 +我們要強制:即使 `q` 是可選,只要提供了,**長度就不能超過 50 個字元**。 ### 匯入 `Query` 與 `Annotated` { #import-query-and-annotated } 要達成這點,先匯入: -- 從 `fastapi` 匯入 `Query` -- 從 `typing` 匯入 `Annotated` +* 從 `fastapi` 匯入 `Query` +* 從 `typing` 匯入 `Annotated` {* ../../docs_src/query_params_str_validations/tutorial002_an_py310.py hl[1,3] *} -/// info | 說明 +/// note | 注意 FastAPI 自 0.95.0 版起加入並開始推薦使用 `Annotated`。 @@ -69,19 +69,19 @@ q: Annotated[str | None] = None 注意預設值仍然是 `None`,所以這個參數仍是可選。 -不過,現在在 `Annotated` 裡有 `Query(max_length=50)`,我們就告訴 FastAPI 要對這個值做「額外驗證」,最多 50 個字元即可。😎 +不過,現在在 `Annotated` 裡有 `Query(max_length=50)`,我們就告訴 FastAPI 要對這個值做**額外驗證**,最多 50 個字元即可。😎 /// tip | 提示 -這裡用的是 `Query()`,因為這是「查詢參數」。稍後你會看到 `Path()`、`Body()`、`Header()`、`Cookie()` 等,它們也接受與 `Query()` 相同的參數。 +這裡用的是 `Query()`,因為這是**查詢參數**。稍後你會看到 `Path()`、`Body()`、`Header()`、`Cookie()` 等,它們也接受與 `Query()` 相同的參數。 /// FastAPI 現在會: -- 驗證資料,確保長度最多 50 個字元 -- 當資料不合法時,回給用戶端清楚的錯誤 -- 在 OpenAPI 的路徑操作中文件化該參數(因此會出現在自動文件 UI) +* **驗證**資料,確保長度最多 50 個字元 +* 當資料不合法時,回給用戶端**清楚的錯誤** +* 在 OpenAPI schema *路徑操作*中**文件化**該參數(因此會出現在**自動文件 UI**) ## 替代方式(舊):將 `Query` 作為預設值 { #alternative-old-query-as-the-default-value } @@ -105,7 +105,8 @@ FastAPI 現在會: q: str | None = Query(default=None) ``` -…會讓參數變為可選、預設值是 `None`,等同於: +...會讓參數變為可選、預設值是 `None`,等同於: + ```Python q: str | None = None @@ -119,7 +120,7 @@ q: str | None = None q: str | None = Query(default=None, max_length=50) ``` -這一樣會驗證資料、在資料不合法時顯示清楚錯誤,並在 OpenAPI 的路徑操作中文件化該參數。 +這一樣會驗證資料、在資料不合法時顯示清楚錯誤,並在 OpenAPI schema *路徑操作*中文件化該參數。 ### 將 `Query` 作為預設值或放在 `Annotated` 中 { #query-as-the-default-value-or-in-annotated } @@ -133,7 +134,7 @@ q: str | None = Query(default=None, max_length=50) q: Annotated[str, Query(default="rick")] = "morty" ``` -…因為不清楚預設值到底該是 `"rick"` 還是 `"morty"`。 +...因為不清楚預設值到底該是 `"rick"` 還是 `"morty"`。 因此,你可以(且更推薦)這樣寫: @@ -141,7 +142,7 @@ q: Annotated[str, Query(default="rick")] = "morty" q: Annotated[str, Query()] = "rick" ``` -…或在較舊的程式碼中你會看到: +...或在較舊的程式碼中你會看到: ```Python q: str = Query(default="rick") @@ -149,13 +150,13 @@ q: str = Query(default="rick") ### `Annotated` 的優點 { #advantages-of-annotated } -建議使用 `Annotated`,而不是在函式參數上使用(舊式的)預設值寫法,理由很多,且更好。🤓 +建議**使用 `Annotated`**,而不是在函式參數上使用預設值寫法,理由很多,且**更好**。🤓 -函式參數的「預設值」就是「實際的預設值」,這在 Python 的直覺上更一致。😌 +函式參數的**預設值**就是**實際的預設值**,這在 Python 的直覺上更一致。😌 -你也可以在沒有 FastAPI 的其他地方「直接呼叫」同一個函式,而且能「如預期」運作。若有「必填」參數(沒有預設值),你的「編輯器」會提示錯誤,「Python」在執行時也會抱怨你未傳遞必填參數。 +你也可以在沒有 FastAPI 的**其他地方**「**呼叫**」同一個函式,而且能「**如預期**」運作。若有**必填**參數(沒有預設值),你的**編輯器**會提示錯誤,**Python** 在執行時也會抱怨你未傳遞必填參數。 -若不使用 `Annotated`、改用「(舊式)預設值」寫法,你在沒有 FastAPI 的「其他地方」呼叫該函式時,就得「記得」傳入正確參數,否則值會和預期不同(例如會得到 `QueryInfo` 或類似的東西,而不是 `str`)。你的編輯器不會提示,Python 執行該函式時也不會抱怨,只有在內部操作失敗時才會出錯。 +若不使用 `Annotated`、改用**(舊式)預設值**寫法,你在沒有 FastAPI 的**其他地方**呼叫該函式時,就得**記得**傳入正確參數,否則值會和預期不同(例如會得到 `QueryInfo` 或類似的東西,而不是 `str`)。你的編輯器不會提示,Python 執行該函式時也不會抱怨,只有在內部操作失敗時才會出錯。 因為 `Annotated` 可以有多個中繼資料註解,你甚至可以用同一個函式配合其他工具,例如 [Typer](https://typer.tiangolo.com/)。🚀 @@ -167,19 +168,19 @@ q: str = Query(default="rick") ## 加入正規表示式 { #add-regular-expressions } -你可以定義參數必須符合的 regular expression `pattern`: +你可以定義參數必須符合的 正規表示式 `pattern`: {* ../../docs_src/query_params_str_validations/tutorial004_an_py310.py hl[11] *} 這個特定的正規表示式樣式會檢查收到的參數值是否: -- `^`:以後續的字元開頭,前面不能有其他字元。 -- `fixedquery`:必須正好等於 `fixedquery`。 -- `$`:在此結束,`fixedquery` 後面不能再有其他字元。 +* `^`:以後續的字元開頭,前面不能有其他字元。 +* `fixedquery`:必須正好等於 `fixedquery`。 +* `$`:在此結束,`fixedquery` 後面不能再有其他字元。 -如果你對「正規表示式」感到困惑,別擔心。這對很多人來說都不容易。你仍然可以先不使用正規表示式就完成很多事情。 +如果你對所有這些**「正規表示式」**概念感到困惑,別擔心。這對很多人來說都不容易。你仍然可以先不使用正規表示式就完成很多事情。 -現在你知道,當你需要它們時,可以在 FastAPI 中使用它們。 +現在你知道,當你需要它們時,可以在 **FastAPI** 中使用它們。 ## 預設值 { #default-values } @@ -235,13 +236,13 @@ q: Annotated[str | None, Query(min_length=3)] = None {* ../../docs_src/query_params_str_validations/tutorial011_an_py310.py hl[9] *} -若使用這樣的 URL: +接著,若使用這樣的 URL: ``` http://localhost:8000/items/?q=foo&q=bar ``` -你會在路徑操作函式的參數 `q` 中,收到多個 `q` 查詢參數的值(`foo` 與 `bar`),以 Python 的 `list` 形式。 +你會在*路徑操作函式*的*函式參數* `q` 中,收到多個 `q` *查詢參數*的值(`foo` 與 `bar`),以 Python 的 `list` 形式。 因此,對該 URL 的回應會是: @@ -276,7 +277,7 @@ http://localhost:8000/items/?q=foo&q=bar http://localhost:8000/items/ ``` -`q` 的預設值會是:`["foo", "bar"]`,而回應會是: +`q` 的預設值會是:`["foo", "bar"]`,而你的回應會是: ```JSON { @@ -359,15 +360,15 @@ http://127.0.0.1:8000/items/?item-query=foobaritems ## 從 OpenAPI 排除參數 { #exclude-parameters-from-openapi } -若要把某個查詢參數從產生的 OpenAPI(以及自動文件系統)中排除,將 `Query` 的 `include_in_schema` 設為 `False`: +若要把某個查詢參數從產生的 OpenAPI schema(以及自動文件系統)中排除,將 `Query` 的 `include_in_schema` 設為 `False`: {* ../../docs_src/query_params_str_validations/tutorial014_an_py310.py hl[10] *} ## 自訂驗證 { #custom-validation } -有時你需要做一些上述參數無法處理的「自訂驗證」。 +有時你需要做一些上述參數無法處理的**自訂驗證**。 -這種情況下,你可以使用「自訂驗證函式」,它會在一般驗證之後套用(例如先確認值是 `str` 之後)。 +這種情況下,你可以使用**自訂驗證函式**,它會在一般驗證之後套用(例如先確認值是 `str` 之後)。 你可以在 `Annotated` 中使用 [Pydantic 的 `AfterValidator`](https://docs.pydantic.dev/latest/concepts/validators/#field-after-validator) 來達成。 @@ -381,7 +382,7 @@ Pydantic 也有 [`BeforeValidator`](https://docs.pydantic.dev/latest/concepts/va {* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py hl[5,16:19,24] *} -/// info | 說明 +/// note | 注意 這需搭配 Pydantic 2 或以上版本。😎 @@ -389,15 +390,15 @@ Pydantic 也有 [`BeforeValidator`](https://docs.pydantic.dev/latest/concepts/va /// tip | 提示 -如果你需要做任何需要與「外部元件」溝通的驗證(例如資料庫或其他 API),應該改用「FastAPI 依賴」(FastAPI Dependencies),你稍後會學到。 +如果你需要做任何需要與**外部元件**溝通的驗證(例如資料庫或其他 API),應該改用 **FastAPI Dependencies**,你稍後會學到。 -這些自訂驗證器適用於只需使用請求中「同一份資料」即可完成的檢查。 +這些自訂驗證器適用於只需使用請求中**同一份資料**即可完成的檢查。 /// ### 理解這段程式碼 { #understand-that-code } -重點就是在 `Annotated` 中使用「`AfterValidator` 搭配函式」。如果你願意,可以略過這一節。🤸 +重點就是在 `Annotated` 中使用 **`AfterValidator` 搭配函式**。如果你願意,可以略過這一節。🤸 --- @@ -411,17 +412,17 @@ Pydantic 也有 [`BeforeValidator`](https://docs.pydantic.dev/latest/concepts/va #### 隨機項目 { #a-random-item } -透過 `data.items()` 我們會得到一個包含每個字典項目鍵值對 tuple 的 iterable object。 +透過 `data.items()` 我們會得到一個包含每個字典項目鍵值對 tuple 的 可疊代物件。 我們用 `list(data.items())` 把這個可疊代物件轉成正式的 `list`。 -接著用 `random.choice()` 從清單中取得一個「隨機值」,也就是一個 `(id, name)` 的 tuple。可能像是 `("imdb-tt0371724", "The Hitchhiker's Guide to the Galaxy")`。 +接著用 `random.choice()` 從清單中取得一個**隨機值**,也就是一個 `(id, name)` 的 tuple。可能像是 `("imdb-tt0371724", "The Hitchhiker's Guide to the Galaxy")`。 -然後把這個 tuple 的兩個值分別指定給變數 `id` 和 `name`。 +然後把這個 tuple 的**兩個值分別指定**給變數 `id` 和 `name`。 因此,即使使用者沒有提供 item ID,仍然會收到一個隨機建議。 -……而這全部只用一行簡單的程式碼完成。🤯 你不愛 Python 嗎?🐍 +...而這全部只用**一行簡單的程式碼**完成。🤯 你不愛 Python 嗎?🐍 {* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py ln[22:30] hl[29] *} @@ -431,16 +432,16 @@ Pydantic 也有 [`BeforeValidator`](https://docs.pydantic.dev/latest/concepts/va 通用的驗證與中繼資料: -- `alias` -- `title` -- `description` -- `deprecated` +* `alias` +* `title` +* `description` +* `deprecated` 字串專用的驗證: -- `min_length` -- `max_length` -- `pattern` +* `min_length` +* `max_length` +* `pattern` 使用 `AfterValidator` 的自訂驗證。 diff --git a/docs/zh-hant/docs/tutorial/query-params.md b/docs/zh-hant/docs/tutorial/query-params.md index 89c083456..86cf60a5a 100644 --- a/docs/zh-hant/docs/tutorial/query-params.md +++ b/docs/zh-hant/docs/tutorial/query-params.md @@ -65,9 +65,9 @@ http://127.0.0.1:8000/items/?skip=20 在這種情況下,函式參數 `q` 為選用,且預設為 `None`。 -/// check | 注意 +/// tip | 提示 -另外請注意,FastAPI 能辨識出路徑參數 `item_id` 是路徑參數,而 `q` 不是,因此 `q` 會被當作查詢參數。 +另外請注意,**FastAPI** 能辨識出路徑參數 `item_id` 是路徑參數,而 `q` 不是,因此 `q` 會被當作查詢參數。 /// @@ -109,9 +109,10 @@ http://127.0.0.1:8000/items/foo?short=yes 或任何其他大小寫變化(全大寫、首字母大寫等),你的函式會將參數 `short` 視為 `bool` 值 `True`。否則為 `False`。 + ## 多個路徑與查詢參數 { #multiple-path-and-query-parameters } -你可以同時宣告多個路徑參數與查詢參數,FastAPI 會自動分辨。 +你可以同時宣告多個路徑參數與查詢參數,**FastAPI** 會自動分辨。 而且不必按特定順序宣告。 diff --git a/docs/zh-hant/docs/tutorial/request-files.md b/docs/zh-hant/docs/tutorial/request-files.md index 4e20544ea..979a579eb 100644 --- a/docs/zh-hant/docs/tutorial/request-files.md +++ b/docs/zh-hant/docs/tutorial/request-files.md @@ -1,8 +1,9 @@ # 請求中的檔案 { #request-files } + 你可以使用 `File` 定義由用戶端上傳的檔案。 -/// info +/// note 若要接收上傳的檔案,請先安裝 [`python-multipart`](https://github.com/Kludex/python-multipart)。 @@ -28,7 +29,7 @@ $ pip install python-multipart {* ../../docs_src/request_files/tutorial001_an_py310.py hl[9] *} -/// info +/// note `File` 是直接繼承自 `Form` 的類別。 diff --git a/docs/zh-hant/docs/tutorial/request-form-models.md b/docs/zh-hant/docs/tutorial/request-form-models.md index f8a0e8c6c..9bafb0ef7 100644 --- a/docs/zh-hant/docs/tutorial/request-form-models.md +++ b/docs/zh-hant/docs/tutorial/request-form-models.md @@ -2,7 +2,7 @@ 你可以使用 **Pydantic 模型** 在 FastAPI 中宣告 **表單欄位**。 -/// info | 說明 +/// note | 注意 要使用表單,首先安裝 [`python-multipart`](https://github.com/Kludex/python-multipart)。 diff --git a/docs/zh-hant/docs/tutorial/request-forms-and-files.md b/docs/zh-hant/docs/tutorial/request-forms-and-files.md index c508bf7f7..2db9e283b 100644 --- a/docs/zh-hant/docs/tutorial/request-forms-and-files.md +++ b/docs/zh-hant/docs/tutorial/request-forms-and-files.md @@ -2,7 +2,7 @@ 你可以使用 `File` 與 `Form` 同時定義檔案與表單欄位。 -/// info +/// note 要接收上傳的檔案與/或表單資料,請先安裝 [`python-multipart`](https://github.com/Kludex/python-multipart)。 diff --git a/docs/zh-hant/docs/tutorial/request-forms.md b/docs/zh-hant/docs/tutorial/request-forms.md index d38db96f1..590779168 100644 --- a/docs/zh-hant/docs/tutorial/request-forms.md +++ b/docs/zh-hant/docs/tutorial/request-forms.md @@ -1,8 +1,9 @@ # 表單資料 { #form-data } + 當你需要接收表單欄位而不是 JSON 時,可以使用 `Form`。 -/// info +/// note 要使用表單,請先安裝 [`python-multipart`](https://github.com/Kludex/python-multipart)。 @@ -32,7 +33,7 @@ $ pip install python-multipart 使用 `Form` 時,你可以宣告與 `Body`(以及 `Query`、`Path`、`Cookie`)相同的設定,包括驗證、範例、別名(例如用 `user-name` 取代 `username`)等。 -/// info +/// note `Form` 是一個直接繼承自 `Body` 的類別。 diff --git a/docs/zh-hant/docs/tutorial/response-model.md b/docs/zh-hant/docs/tutorial/response-model.md index d9ad9d9d1..be276945b 100644 --- a/docs/zh-hant/docs/tutorial/response-model.md +++ b/docs/zh-hant/docs/tutorial/response-model.md @@ -72,7 +72,7 @@ FastAPI 會使用這個 `response_model` 來做所有的資料文件、驗證等 {* ../../docs_src/response_model/tutorial002_py310.py hl[7,9] *} -/// info | 說明 +/// note | 注意 要使用 `EmailStr`,請先安裝 [`email-validator`](https://github.com/JoshData/python-email-validator)。 @@ -251,7 +251,7 @@ FastAPI 在內部會搭配 Pydantic 做一些事情,來確保不會把類別 } ``` -/// info | 說明 +/// note | 注意 你也可以使用: diff --git a/docs/zh-hant/docs/tutorial/response-status-code.md b/docs/zh-hant/docs/tutorial/response-status-code.md index 9ac2e41da..d649dc785 100644 --- a/docs/zh-hant/docs/tutorial/response-status-code.md +++ b/docs/zh-hant/docs/tutorial/response-status-code.md @@ -1,5 +1,6 @@ # 回應狀態碼 { #response-status-code } + 就像你可以指定回應模型一樣,你也可以在任一個「路徑操作(path operation)」的參數 `status_code` 中宣告回應所使用的 HTTP 狀態碼: * `@app.get()` @@ -18,7 +19,7 @@ 參數 `status_code` 接受一個數字作為 HTTP 狀態碼。 -/// info | 資訊 +/// note | 注意 `status_code` 也可以接收一個 `IntEnum`,例如 Python 的 [`http.HTTPStatus`](https://docs.python.org/3/library/http.html#http.HTTPStatus)。 @@ -27,7 +28,7 @@ 它會: * 在回應中傳回該狀態碼。 -* 在 OpenAPI 結構中如此記錄(因此也會反映在使用者介面中): +* 在 OpenAPI 構架中如此記錄(因此也會反映在使用者介面中): diff --git a/docs/zh-hant/docs/tutorial/schema-extra-example.md b/docs/zh-hant/docs/tutorial/schema-extra-example.md index 1c2caef85..8cca5003a 100644 --- a/docs/zh-hant/docs/tutorial/schema-extra-example.md +++ b/docs/zh-hant/docs/tutorial/schema-extra-example.md @@ -10,7 +10,7 @@ {* ../../docs_src/schema_extra_example/tutorial001_py310.py hl[13:24] *} -這些額外資訊會原封不動加入該模型輸出的 JSON Schema,並且會用在 API 文件裡。 +這些額外資訊會原封不動加入該模型輸出的 **JSON Schema**,並且會用在 API 文件裡。 你可以使用屬性 `model_config`(接收一個 `dict`),詳見 [Pydantic 文件:Configuration](https://docs.pydantic.dev/latest/api/config/)。 @@ -24,7 +24,7 @@ /// -/// info +/// note OpenAPI 3.1.0(自 FastAPI 0.99.0 起使用)新增了對 `examples` 的支援,這是 **JSON Schema** 標準的一部分。 @@ -135,7 +135,7 @@ OpenAPI 3.1.0(自 FastAPI 0.99.0 起使用)新增了對 `examples` 的支援 以下是關於 **JSON Schema** 與 **OpenAPI** 標準的技術細節。 -如果上面的做法對你已經足夠可用,就不需要這些細節,儘管直接跳過。 +如果上面的做法對你已經足夠可用,就不需要這些細節,可以直接跳過。 /// @@ -155,7 +155,7 @@ OpenAPI 也在規範的其他部分新增了 `example` 與 `examples` 欄位: * `File()` * `Form()` -/// info +/// note 這個舊的、OpenAPI 特定的 `examples` 參數,從 FastAPI `0.103.0` 起改名為 `openapi_examples`。 @@ -171,7 +171,7 @@ OpenAPI 也在規範的其他部分新增了 `example` 與 `examples` 欄位: JSON Schema 中新的 `examples` 欄位「就是一個 `list`」的範例集合,而不是像 OpenAPI 其他地方(如上所述)那樣附帶額外中繼資料的 `dict`。 -/// info +/// note 即使 OpenAPI 3.1.0 已發佈並與 JSON Schema 有更簡潔的整合,一段時間內提供自動文件的 Swagger UI 並不支援 OpenAPI 3.1.0(自 5.0.0 版起支援 🎉)。 diff --git a/docs/zh-hant/docs/tutorial/security/first-steps.md b/docs/zh-hant/docs/tutorial/security/first-steps.md index 7f12ec1a3..7640a4556 100644 --- a/docs/zh-hant/docs/tutorial/security/first-steps.md +++ b/docs/zh-hant/docs/tutorial/security/first-steps.md @@ -1,16 +1,16 @@ # 安全性 - 入門 { #security-first-steps } -想像你有一個部署在某個網域的後端 API。 +想像你有一個部署在某個網域的 **後端** API。 -還有一個前端在另一個網域,或同一網域的不同路徑(或是行動應用程式)。 +還有一個 **前端** 在另一個網域,或同一網域的不同路徑(或是行動應用程式)。 -你希望前端能用使用者名稱與密碼向後端進行身分驗證。 +你希望前端能用**使用者名稱**與**密碼**向後端進行身分驗證。 -我們可以用 OAuth2 搭配 FastAPI 來實作。 +我們可以用 **OAuth2** 搭配 **FastAPI** 來實作。 但不必通讀整份冗長規格只為了找出你需要的幾個重點。 -就用 FastAPI 提供的工具處理安全性。 +就用 **FastAPI** 提供的工具處理安全性。 ## 看起來如何 { #how-it-looks } @@ -24,9 +24,9 @@ ## 執行 { #run-it } -/// info +/// note -當你使用 `pip install "fastapi[standard]"` 指令安裝時,[`python-multipart`](https://github.com/Kludex/python-multipart) 套件會隨 FastAPI 自動安裝。 +當你使用 `pip install "fastapi[standard]"` 指令安裝時,[`python-multipart`](https://github.com/Kludex/python-multipart) 套件會隨 **FastAPI** 自動安裝。 不過若只執行 `pip install fastapi`,預設不會包含 `python-multipart`。 @@ -36,7 +36,7 @@ $ pip install python-multipart ``` -因為 OAuth2 會以「form data」傳送 `username` 與 `password`。 +因為 **OAuth2** 會以「form data」傳送 `username` 與 `password`。 /// @@ -60,11 +60,11 @@ $ fastapi dev -/// check | Authorize 按鈕! +/// tip | Authorize 按鈕! -你會看到一個新的「Authorize」按鈕。 +你已經有一個亮眼的全新「Authorize」按鈕。 -而你的「路徑操作」右上角也會出現一個小鎖頭可以點擊。 +而你的 *路徑操作* 右上角也會出現一個小鎖頭可以點擊。 /// @@ -94,31 +94,31 @@ $ fastapi dev OAuth2 的設計讓後端或 API 可以獨立於執行使用者驗證的伺服器。 -但在這個例子中,同一個 FastAPI 應用會同時處理 API 與驗證。 +但在這個例子中,同一個 **FastAPI** 應用會同時處理 API 與驗證。 簡化來看流程如下: - 使用者在前端輸入 `username` 與 `password`,按下 `Enter`。 - 前端(在使用者的瀏覽器中執行)把 `username` 與 `password` 傳到我們 API 的特定 URL(在程式中宣告為 `tokenUrl="token"`)。 -- API 檢查 `username` 與 `password`,並回傳一個「token(權杖)」(我們還沒實作這部分)。 +- API 檢查 `username` 與 `password`,並回應一個「token(權杖)」(我們還沒實作這部分)。 - 「token(權杖)」就是一段字串,之後可用來識別並驗證此使用者。 - 通常 token 會設定一段時間後失效。 - 因此使用者之後需要重新登入。 - 若 token 被竊取,風險也較低;它不像永遠有效的萬用鑰匙(多數情況下)。 - 前端會暫存這個 token。 -- 使用者在前端點擊前往其他頁面/區段。 +- 使用者在前端點擊,前往前端網頁應用程式的另一個區段。 - 前端需要再向 API 取得資料。 - 但該端點需要驗證。 - 因此為了向 API 驗證,請求會帶上一個 `Authorization` 標頭,值為 `Bearer ` 加上 token。 - 例如 token 是 `foobar`,則 `Authorization` 標頭內容為:`Bearer foobar`。 -## FastAPI 的 `OAuth2PasswordBearer` { #fastapis-oauth2passwordbearer } +## **FastAPI** 的 `OAuth2PasswordBearer` { #fastapis-oauth2passwordbearer } -FastAPI 提供多層抽象的工具來實作這些安全機制。 +**FastAPI** 提供多層抽象的工具來實作這些安全機制。 -本例將使用 OAuth2 的 Password 流程,並以 Bearer token 進行驗證;我們會用 `OAuth2PasswordBearer` 類別來完成。 +本例將使用 **OAuth2** 的 **Password** 流程,並以 **Bearer** token 進行驗證;我們會用 `OAuth2PasswordBearer` 類別來完成。 -/// info +/// note 「Bearer」token 不是唯一選項。 @@ -126,7 +126,7 @@ FastAPI 提供多層抽象的工具來實作這些安全機制。 通常對多數情境也足夠,除非你是 OAuth2 專家並確信有更適合你的選項。 -在那種情況下,FastAPI 也提供相應工具讓你自行組合。 +在那種情況下,**FastAPI** 也提供相應工具讓你自行組合。 /// @@ -144,11 +144,11 @@ FastAPI 提供多層抽象的工具來實作這些安全機制。 /// -這個參數不會建立該端點/「路徑操作」,而是宣告 `/token` 將是客戶端用來取得 token 的 URL。這些資訊會出現在 OpenAPI,並被互動式 API 文件系統使用。 +這個參數不會建立該端點 / *路徑操作*,而是宣告 `/token` 將是客戶端用來取得 token 的 URL。這些資訊會出現在 OpenAPI,並被互動式 API 文件系統使用。 我們很快也會建立實際的路徑操作。 -/// info +/// note 如果你是非常嚴格的「Pythonista」,可能不喜歡參數名稱用 `tokenUrl` 而不是 `token_url`。 @@ -172,15 +172,15 @@ oauth2_scheme(some, parameters) {* ../../docs_src/security/tutorial001_an_py310.py hl[12] *} -此相依性會提供一個 `str`,指派給「路徑操作函式」的參數 `token`。 +此相依性會提供一個 `str`,指派給 *路徑操作函式* 的參數 `token`。 -FastAPI 會知道可以使用這個相依性,在 OpenAPI(以及自動產生的 API 文件)中定義一個「安全性方案」。 +**FastAPI** 會知道可以使用這個相依性,在 OpenAPI schema(以及自動產生的 API 文件)中定義一個「安全性方案」。 -/// info | 技術細節 +/// note | 技術細節 -FastAPI 之所以知道可以用(相依性中宣告的)`OAuth2PasswordBearer` 類別,在 OpenAPI 中定義安全性方案,是因為它繼承自 `fastapi.security.oauth2.OAuth2`,而後者又繼承自 `fastapi.security.base.SecurityBase`。 +**FastAPI** 之所以知道可以用(相依性中宣告的)`OAuth2PasswordBearer` 類別,在 OpenAPI 中定義安全性方案,是因為它繼承自 `fastapi.security.oauth2.OAuth2`,而後者又繼承自 `fastapi.security.base.SecurityBase`。 -所有能與 OpenAPI(以及自動 API 文件)整合的安全工具都繼承自 `SecurityBase`,FastAPI 才能知道如何把它們整合進 OpenAPI。 +所有能與 OpenAPI(以及自動 API 文件)整合的安全工具都繼承自 `SecurityBase`,**FastAPI** 才能知道如何把它們整合進 OpenAPI。 /// @@ -188,7 +188,7 @@ FastAPI 之所以知道可以用(相依性中宣告的)`OAuth2PasswordBearer 它會從請求中尋找 `Authorization` 標頭,檢查其值是否為 `Bearer ` 加上一段 token,並將該 token 以 `str` 回傳。 -若未找到 `Authorization` 標頭,或其值不是 `Bearer ` token,則會直接回傳 401(`UNAUTHORIZED`)錯誤。 +若未找到 `Authorization` 標頭,或其值不是 `Bearer ` token,則會直接回應 401 狀態碼錯誤(`UNAUTHORIZED`)。 你不必再自行檢查 token 是否存在;你可以確信只要你的函式被執行,該 token 參數就一定會是 `str`。 diff --git a/docs/zh-hant/docs/tutorial/security/get-current-user.md b/docs/zh-hant/docs/tutorial/security/get-current-user.md index b223d4823..5309d78c0 100644 --- a/docs/zh-hant/docs/tutorial/security/get-current-user.md +++ b/docs/zh-hant/docs/tutorial/security/get-current-user.md @@ -14,7 +14,7 @@ 就像用 Pydantic 宣告請求體一樣,我們也可以在其他地方使用它: -{* ../../docs_src/security/tutorial002_an_py310.py hl[5,12:6] *} +{* ../../docs_src/security/tutorial002_an_py310.py hl[5,12:16] *} ## 建立 `get_current_user` 依賴 { #create-a-get-current-user-dependency } @@ -52,7 +52,7 @@ /// -/// check | 檢查 +/// tip | 提示 這個依賴系統的設計讓我們可以有不同的依賴(不同的 "dependables"),都回傳 `User` 模型。 diff --git a/docs/zh-hant/docs/tutorial/security/oauth2-jwt.md b/docs/zh-hant/docs/tutorial/security/oauth2-jwt.md index abd920ce6..dc75092b4 100644 --- a/docs/zh-hant/docs/tutorial/security/oauth2-jwt.md +++ b/docs/zh-hant/docs/tutorial/security/oauth2-jwt.md @@ -42,7 +42,7 @@ $ pip install pyjwt
-/// info | 說明 +/// note | 注意 如果你打算使用像 RSA 或 ECDSA 這類的數位簽章演算法,應該安裝帶有加密函式庫相依的 `pyjwt[crypto]`。 @@ -120,7 +120,7 @@ pwdlib 也支援 bcrypt 雜湊演算法,但不包含傳統(legacy)演算 當以不存在於資料庫的使用者名稱呼叫 `authenticate_user` 時,我們仍然會拿一個假的雜湊去跑一次 `verify_password`。 -這可確保無論使用者名稱是否有效,端點的回應時間都大致相同,避免可用來枚舉既有使用者名稱的「計時攻擊」(timing attacks)。 +這可確保無論使用者名稱是否有效,端點的回應時間都大致相同,避免可用來枚舉既有使用者名稱的 **計時攻擊**(timing attacks)。 /// note | 注意 @@ -168,7 +168,7 @@ $ openssl rand -hex 32 {* ../../docs_src/security/tutorial004_an_py310.py hl[93:110] *} -## 更新 `/token` 路徑操作 { #update-the-token-path-operation } +## 更新 `/token` *路徑操作* { #update-the-token-path-operation } 用權杖有效期建立一個 `timedelta`。 @@ -213,7 +213,7 @@ JWT 除了用來識別使用者並允許他直接對你的 API 執行操作外 Username: `johndoe` Password: `secret` -/// check | 檢查 +/// tip | 提示 注意在程式碼中完全沒有明文密碼「`secret`」,我們只有雜湊後的版本。 diff --git a/docs/zh-hant/docs/tutorial/security/simple-oauth2.md b/docs/zh-hant/docs/tutorial/security/simple-oauth2.md index 251848aa5..2b29daa0d 100644 --- a/docs/zh-hant/docs/tutorial/security/simple-oauth2.md +++ b/docs/zh-hant/docs/tutorial/security/simple-oauth2.md @@ -32,7 +32,7 @@ OAuth2 規範中,當使用「password flow」(我們現在使用的)時, - `instagram_basic` 用在 Facebook / Instagram - `https://www.googleapis.com/auth/drive` 用在 Google -/// info +/// note 在 OAuth2 裡,「scope」只是用來宣告特定所需權限的一個字串。 @@ -72,7 +72,7 @@ OAuth2 規範中,當使用「password flow」(我們現在使用的)時, - 可選的 `client_id`(本例不需要) - 可選的 `client_secret`(本例不需要) -/// info +/// note `OAuth2PasswordRequestForm` 並不是像 `OAuth2PasswordBearer` 那樣對 **FastAPI** 來說的特殊類別。 @@ -128,11 +128,11 @@ OAuth2 規範中,當使用「password flow」(我們現在使用的)時, {* ../../docs_src/security/tutorial003_an_py310.py hl[82:85] *} -#### 關於 `**user_dict**` { #about-user-dict } +#### 關於 `**user_dict` { #about-user-dict } `UserInDB(**user_dict)` 的意思是: -把 `user_dict` 的鍵和值直接當作具名參數傳入,等同於: +*把 `user_dict` 的鍵和值直接當作具名參數傳入,等同於:* ```Python UserInDB( @@ -144,9 +144,9 @@ UserInDB( ) ``` -/// info +/// note -想更完整地了解 `**user_dict`,請回到[**額外模型** 的文件](../extra-models.md#about-user-in-dict)。 +想更完整地了解 `**user_dict`,請回到[**額外模型** 的文件](../extra-models.md#about-user-in-model-dump)。 /// @@ -196,7 +196,7 @@ UserInDB( {* ../../docs_src/security/tutorial003_an_py310.py hl[58:66,69:74,94] *} -/// info +/// note 這裡我們一併回傳值為 `Bearer` 的額外標頭 `WWW-Authenticate`,這也是規範的一部分。 diff --git a/docs/zh-hant/docs/tutorial/server-sent-events.md b/docs/zh-hant/docs/tutorial/server-sent-events.md index ced91e358..e539f65d8 100644 --- a/docs/zh-hant/docs/tutorial/server-sent-events.md +++ b/docs/zh-hant/docs/tutorial/server-sent-events.md @@ -4,7 +4,7 @@ 這與[串流 JSON Lines](stream-json-lines.md)類似,但使用瀏覽器原生支援、透過 [`EventSource` API](https://developer.mozilla.org/en-US/docs/Web/API/EventSource) 的 `text/event-stream` 格式。 -/// info +/// note 在 FastAPI 0.135.0 新增。 diff --git a/docs/zh-hant/docs/tutorial/sql-databases.md b/docs/zh-hant/docs/tutorial/sql-databases.md index a37e16432..3a0e43d84 100644 --- a/docs/zh-hant/docs/tutorial/sql-databases.md +++ b/docs/zh-hant/docs/tutorial/sql-databases.md @@ -1,10 +1,10 @@ # SQL(關聯式)資料庫 { #sql-relational-databases } -FastAPI 不強制你使用 SQL(關聯式)資料庫。你可以使用任何你想要的資料庫。 +**FastAPI** 不強制你使用 SQL(關聯式)資料庫。但你可以使用**任何你想要的資料庫**。 這裡我們會用 [SQLModel](https://sqlmodel.tiangolo.com/) 作為範例。 -SQLModel 建立在 [SQLAlchemy](https://www.sqlalchemy.org/) 與 Pydantic 之上。它由 FastAPI 的作者開發,非常適合需要使用 SQL 資料庫的 FastAPI 應用。 +**SQLModel** 建立在 [SQLAlchemy](https://www.sqlalchemy.org/) 與 Pydantic 之上。它由 **FastAPI** 的作者開發,非常適合需要使用 **SQL 資料庫**的 FastAPI 應用。 /// tip | 提示 @@ -12,7 +12,7 @@ SQLModel 建立在 [SQLAlchemy](https://www.sqlalchemy.org/) 與 Pydantic 之上 /// -因為 SQLModel 建立在 SQLAlchemy 之上,你可以輕鬆使用 SQLAlchemy 所支援的任何資料庫(因此 SQLModel 也支援),例如: +因為 SQLModel 建立在 SQLAlchemy 之上,你可以輕鬆使用 SQLAlchemy 所支援的**任何資料庫**(因此 SQLModel 也支援),例如: * PostgreSQL * MySQL @@ -20,17 +20,17 @@ SQLModel 建立在 [SQLAlchemy](https://www.sqlalchemy.org/) 與 Pydantic 之上 * Oracle * Microsoft SQL Server,等等。 -在這個範例中,我們會使用 SQLite,因為它只用到單一檔案,而且 Python 內建支援。你可以直接複製這個範例並原樣執行。 +在這個範例中,我們會使用 **SQLite**,因為它只用到單一檔案,而且 Python 內建支援。你可以直接複製這個範例並原樣執行。 -之後,在你的正式環境應用中,你可能會想使用像 PostgreSQL 這類的資料庫伺服器。 +之後,在你的正式環境應用中,你可能會想使用像 **PostgreSQL** 這類的資料庫伺服器。 /// tip | 提示 -有一個包含 FastAPI 與 PostgreSQL 的官方專案腳手架,還有前端與更多工具:[https://github.com/fastapi/full-stack-fastapi-template](https://github.com/fastapi/full-stack-fastapi-template) +有一個包含 **FastAPI** 與 **PostgreSQL** 的官方專案產生器,還有前端與更多工具:[https://github.com/fastapi/full-stack-fastapi-template](https://github.com/fastapi/full-stack-fastapi-template) /// -這是一份非常簡短的教學,如果你想更全面學習資料庫、SQL,或更進階的功能,請參考 [SQLModel 文件](https://sqlmodel.tiangolo.com/)。 +這是一份非常簡單且簡短的教學,如果你想更全面學習資料庫、SQL,或更進階的功能,請參考 [SQLModel 文件](https://sqlmodel.tiangolo.com/)。 ## 安裝 `SQLModel` { #install-sqlmodel } @@ -47,9 +47,9 @@ $ pip install sqlmodel ## 建立只有單一模型的應用 { #create-the-app-with-a-single-model } -我們先用單一 SQLModel 模型建立這個應用的最簡版。 +我們先用單一 **SQLModel** 模型建立這個應用的最簡版。 -接著我們會在下方用多個模型來提升安全性與彈性。🤓 +接著我們會在下方用**多個模型**來提升安全性與彈性。🤓 ### 建立模型 { #create-models } @@ -57,43 +57,43 @@ $ pip install sqlmodel {* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[1:11] hl[7:11] *} -`Hero` 類別與 Pydantic 模型非常相似(事實上,在底層它就是一個 Pydantic 模型)。 +`Hero` 類別與 Pydantic 模型非常相似(事實上,在底層它其實*就是一個 Pydantic 模型*)。 有幾點差異: -* `table=True` 告訴 SQLModel 這是一個「資料表模型」(table model),它應該代表 SQL 資料庫中的一個資料表,而不僅僅是「資料模型」(就像一般的 Pydantic 類別)。 +* `table=True` 告訴 SQLModel 這是一個*資料表模型*(table model),它應該代表 SQL 資料庫中的一個**資料表**,而不僅僅是*資料模型*(就像一般的 Pydantic 類別)。 -* `Field(primary_key=True)` 告訴 SQLModel,`id` 是 SQL 資料庫中的「主鍵」。 (你可以在 SQLModel 文件中進一步了解 SQL 主鍵) +* `Field(primary_key=True)` 告訴 SQLModel,`id` 是 SQL 資料庫中的**主鍵**(你可以在 SQLModel 文件中進一步了解 SQL 主鍵)。 - 注意:我們在主鍵欄位使用 `int | None`,這樣在 Python 程式碼中我們可以「在沒有 `id` 的情況下建立物件」(`id=None`),假設資料庫在儲存時會「自動產生」。SQLModel 瞭解資料庫會提供 `id`,並且在資料庫綱要中「將該欄位定義為非空的 `INTEGER`」。詳情請見 [SQLModel 文件:主鍵](https://sqlmodel.tiangolo.com/tutorial/create-db-and-table/#primary-key-id)。 + **注意:** 我們在主鍵欄位使用 `int | None`,這樣在 Python 程式碼中我們可以*在沒有 `id` 的情況下建立物件*(`id=None`),假設資料庫在儲存時會*自動產生*。SQLModel 瞭解資料庫會提供 `id`,並且在資料庫綱要中*將該欄位定義為非空的 `INTEGER`*。詳情請見 [SQLModel 文件:主鍵](https://sqlmodel.tiangolo.com/tutorial/create-db-and-table/#primary-key-id)。 -* `Field(index=True)` 告訴 SQLModel 應為此欄位建立「SQL 索引」,以便在用此欄位過濾讀取資料時更快查詢。 +* `Field(index=True)` 告訴 SQLModel 應為此欄位建立 **SQL 索引**,以便在用此欄位過濾讀取資料時更快查詢。 SQLModel 會知道宣告為 `str` 的欄位在 SQL 中會是 `TEXT`(或 `VARCHAR`,依資料庫而定)。 ### 建立引擎 { #create-an-engine } -SQLModel 的 `engine`(底層實際上是 SQLAlchemy 的 `engine`)是用來「維護與資料庫連線」的東西。 +SQLModel 的 `engine`(底層實際上是 SQLAlchemy 的 `engine`)是用來**維護與資料庫連線**的東西。 -你的程式中應該只有「單一 `engine` 物件」來連到同一個資料庫。 +你的程式中應該只有**單一 `engine` 物件**來連到同一個資料庫。 {* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[14:18] hl[14:15,17:18] *} -使用 `check_same_thread=False` 允許 FastAPI 在不同執行緒中使用同一個 SQLite 資料庫。這是必要的,因為「單一請求」可能會使用「多個執行緒」(例如在依賴項中)。 +使用 `check_same_thread=False` 允許 FastAPI 在不同執行緒中使用同一個 SQLite 資料庫。這是必要的,因為**單一請求**可能會使用**多個執行緒**(例如在依賴項中)。 -別擔心,依照我們的程式結構,稍後我們會確保「每個請求只使用單一 SQLModel 的 session」,這其實就是 `check_same_thread` 想要達成的事。 +別擔心,依照我們的程式結構,稍後我們會確保**每個請求只使用單一 SQLModel 的 *session***,這其實就是 `check_same_thread` 想要達成的事。 ### 建立資料表 { #create-the-tables } -接著我們新增一個函式,使用 `SQLModel.metadata.create_all(engine)` 為所有「資料表模型」建立資料表。 +接著我們新增一個函式,使用 `SQLModel.metadata.create_all(engine)` 為所有*資料表模型* **建立資料表**。 {* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[21:22] hl[21:22] *} ### 建立 Session 依賴 { #create-a-session-dependency } -「`Session`」會在記憶體中保存物件並追蹤資料需要的任何變更,然後透過「`engine`」與資料庫溝通。 +**`Session`** 會在記憶體中保存**物件**並追蹤資料需要的任何變更,然後透過 **`engine`** 與資料庫溝通。 -我們會用 `yield` 建立一個 FastAPI 的「依賴」,為每個請求提供一個新的 `Session`。這可確保每個請求只使用單一的 session。🤓 +我們會用 `yield` 建立一個 FastAPI 的**依賴**,為每個請求提供一個新的 `Session`。這可確保每個請求只使用單一的 session。🤓 接著我們建立一個 `Annotated` 的依賴 `SessionDep`,讓後續使用這個依賴的程式碼更簡潔。 @@ -117,11 +117,11 @@ SQLModel 之後會提供包裝 Alembic 的遷移工具,但目前你可以直 ### 建立 Hero { #create-a-hero } -因為每個 SQLModel 模型同時也是一個 Pydantic 模型,你可以在「型別標註」中像使用 Pydantic 模型一樣使用它。 +因為每個 SQLModel 模型同時也是一個 Pydantic 模型,你可以在與 Pydantic 模型相同的**型別標註**中使用它。 -例如,如果你宣告一個參數型別為 `Hero`,它會從「JSON body」中讀取。 +例如,如果你宣告一個參數型別為 `Hero`,它會從 **JSON body** 中讀取。 -同樣地,你也可以將它宣告為函式的「回傳型別」,然後在自動產生的 API 文件 UI 中就會顯示其資料結構。 +同樣地,你也可以將它宣告為函式的**回傳型別**,然後在自動產生的 API 文件 UI 中就會顯示其資料結構。 {* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[40:45] hl[40:45] *} @@ -129,19 +129,19 @@ SQLModel 之後會提供包裝 Alembic 的遷移工具,但目前你可以直 ### 讀取多個 Hero { #read-heroes } -我們可以用 `select()` 從資料庫「讀取」多個 `Hero`。可以加入 `limit` 與 `offset` 來分頁。 +我們可以用 `select()` 從資料庫**讀取**多個 `Hero`。可以加入 `limit` 與 `offset` 來分頁。 {* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[48:55] hl[51:52,54] *} ### 讀取單一 Hero { #read-one-hero } -我們可以「讀取」單一的 `Hero`。 +我們可以**讀取**單一的 `Hero`。 {* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[58:63] hl[60] *} ### 刪除 Hero { #delete-a-hero } -我們也可以「刪除」一個 `Hero`。 +我們也可以**刪除**一個 `Hero`。 {* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[66:73] hl[71] *} @@ -159,7 +159,7 @@ $ fastapi dev -然後前往 `/docs` 的 UI,你會看到 FastAPI 使用這些模型來「文件化」API,也會用它們來「序列化」與「驗證」資料。 +然後前往 `/docs` 的 UI,你會看到 **FastAPI** 使用這些**模型**來**文件化** API,也會用它們來**序列化**與**驗證**資料。
@@ -167,27 +167,27 @@ $ fastapi dev ## 用多個模型更新應用 { #update-the-app-with-multiple-models } -現在我們稍微「重構」一下這個應用,以提升「安全性」與「彈性」。 +現在我們稍微**重構**一下這個應用,以提升**安全性**與**彈性**。 如果你檢查前一版的應用,在 UI 中你會看到,到目前為止它讓用戶端自己決定要建立的 `Hero` 的 `id`。😱 -我們不該允許這樣,因為他們可能會覆蓋資料庫中我們已分配的 `id`。決定 `id` 應該由「後端」或「資料庫」來做,「不是用戶端」。 +我們不該允許這樣,因為他們可能會覆蓋資料庫中我們已分配的 `id`。決定 `id` 應該由**後端**或**資料庫**來做,**不是用戶端**。 -另外,我們為 hero 建立了 `secret_name`,但目前我們在各處都把它回傳出去,這一點都不「保密」... 😅 +另外,我們為 hero 建立了 `secret_name`,但目前我們在各處都把它回傳出去,這一點都不**保密**... 😅 -我們會透過加入一些「額外模型」來修正這些問題。這正是 SQLModel 大放異彩的地方。✨ +我們會透過加入一些**額外模型**來修正這些問題。這正是 SQLModel 大放異彩的地方。✨ ### 建立多個模型 { #create-multiple-models } -在 SQLModel 中,任何設了 `table=True` 的模型類別都是「資料表模型」。 +在 **SQLModel** 中,任何設了 `table=True` 的模型類別都是**資料表模型**。 -而沒有設 `table=True` 的模型類別就是「資料模型」,這些其實就是 Pydantic 模型(只有一點小增強)。🤓 +而沒有設 `table=True` 的模型類別就是**資料模型**,這些其實就是 Pydantic 模型(只有一點小增強)。🤓 -使用 SQLModel,我們可以利用「繼承」來「避免重複」在各種情況下一再宣告所有欄位。 +使用 SQLModel,我們可以利用**繼承**來**避免重複**在各種情況下一再宣告所有欄位。 #### `HeroBase` - 基底類別 { #herobase-the-base-class } -先從 `HeroBase` 模型開始,它包含所有模型「共享」的欄位: +先從 `HeroBase` 模型開始,它包含所有模型**共享**的欄位: * `name` * `age` @@ -196,12 +196,12 @@ $ fastapi dev #### `Hero` - 資料表模型 { #hero-the-table-model } -接著建立 `Hero`,也就是實際的「資料表模型」,它包含不一定會出現在其他模型中的「額外欄位」: +接著建立 `Hero`,也就是實際的*資料表模型*,它包含不一定會出現在其他模型中的**額外欄位**: * `id` * `secret_name` -因為 `Hero` 繼承自 `HeroBase`,它「也」擁有 `HeroBase` 中宣告的「欄位」,因此 `Hero` 的完整欄位為: +因為 `Hero` 繼承自 `HeroBase`,它**也**擁有 `HeroBase` 中宣告的**欄位**,因此 `Hero` 的完整欄位為: * `id` * `name` @@ -212,19 +212,19 @@ $ fastapi dev #### `HeroPublic` - 公開的資料模型 { #heropublic-the-public-data-model } -接下來建立 `HeroPublic` 模型,它是要「回傳」給 API 用戶端的模型。 +接下來建立 `HeroPublic` 模型,它是要**回傳**給 API 用戶端的模型。 它擁有與 `HeroBase` 相同的欄位,因此不會包含 `secret_name`。 終於,我們英雄的真實身分受保護了!🥷 -它也重新宣告了 `id: int`。這麼做是與 API 用戶端訂立一個「契約」,讓他們可以確定 `id` 一定存在而且是 `int`(不會是 `None`)。 +它也重新宣告了 `id: int`。這麼做是與 API 用戶端訂立一個**契約**,讓他們可以確定 `id` 一定存在而且是 `int`(不會是 `None`)。 /// tip | 提示 讓回傳模型保證某個值一定存在、而且一定是 `int`(不是 `None`),對 API 用戶端非常有幫助。他們在有這個確信下可以寫出更簡單的程式碼。 -此外,透過「自動產生的客戶端」也會有更簡潔的介面,讓要使用你 API 的開發者能有更好的開發體驗。😎 +此外,透過**自動產生的客戶端**也會有更簡潔的介面,讓要使用你 API 的開發者能有更好的開發體驗。😎 /// @@ -238,17 +238,17 @@ $ fastapi dev #### `HeroCreate` - 用於建立 Hero 的資料模型 { #herocreate-the-data-model-to-create-a-hero } -現在我們建立 `HeroCreate` 模型,這是用來「驗證」用戶端送來資料的模型。 +現在我們建立 `HeroCreate` 模型,這是用來**驗證**用戶端送來資料的模型。 它具有與 `HeroBase` 相同的欄位,並且還有 `secret_name`。 -接下來,當用戶端「建立新 hero」時,他們會送上 `secret_name`,它會被儲存在資料庫中,但這些祕密名稱不會在 API 中回傳給用戶端。 +接下來,當用戶端**建立新 hero** 時,他們會送上 `secret_name`,它會被儲存在資料庫中,但這些祕密名稱不會在 API 中回傳給用戶端。 /// tip | 提示 -這也就是你處理「密碼」的方式。接收它們,但不要在 API 中回傳。 +這也就是你處理**密碼**的方式。接收它們,但不要在 API 中回傳。 -你也應該在儲存前先對密碼做「雜湊」,「永遠不要以明文儲存」。 +你也應該在儲存前先對密碼做**雜湊**,**永遠不要以明文儲存**。 /// @@ -262,11 +262,11 @@ $ fastapi dev #### `HeroUpdate` - 用於更新 Hero 的資料模型 { #heroupdate-the-data-model-to-update-a-hero } -在前一版的應用中,我們沒有「更新 hero」的方式,但現在有了「多個模型」,我們就能做到。🎉 +在前一版的應用中,我們沒有**更新 hero** 的方式,但現在有了**多個模型**,我們就能做到。🎉 -`HeroUpdate` 這個資料模型有點特別,它包含「建立新 hero 所需的所有欄位」,但所有欄位都是「可選的」(都有預設值)。這樣在更新時,你只需要送出想要更新的欄位即可。 +`HeroUpdate` 這個*資料模型*有點特別,它包含**建立新 hero 所需的所有欄位**,但所有欄位都是**可選的**(都有預設值)。這樣在更新時,你只需要送出想要更新的欄位即可。 -因為所有欄位的「型別其實都改變了」(型別現在包含 `None`,而且預設值為 `None`),我們需要「重新宣告」它們。 +因為所有**欄位其實都改變了**(型別現在包含 `None`,而且預設值為 `None`),我們需要**重新宣告**它們。 其實不一定要繼承 `HeroBase`,因為我們會重新宣告所有欄位。我這裡保留繼承只是為了一致性,並非必要。這主要是個人偏好的問題。🤷 @@ -280,43 +280,43 @@ $ fastapi dev ### 用 `HeroCreate` 建立並回傳 `HeroPublic` { #create-with-herocreate-and-return-a-heropublic } -現在我們有了「多個模型」,可以更新應用中使用它們的部分。 +現在我們有了**多個模型**,可以更新應用中使用它們的部分。 -我們在請求中接收 `HeroCreate`(資料模型),並由它建立一個 `Hero`(資料表模型)。 +我們在請求中接收 `HeroCreate` *資料模型*,並由它建立一個 `Hero` *資料表模型*。 -這個新的資料表模型 `Hero` 會有用戶端傳來的欄位,並且會由資料庫產生一個 `id`。 +這個新的*資料表模型* `Hero` 會有用戶端傳來的欄位,並且會由資料庫產生一個 `id`。 -然後我們直接從函式回傳這個資料表模型 `Hero`。但因為我們用 `HeroPublic` 當作 `response_model`,FastAPI 會用 `HeroPublic` 來驗證與序列化資料。 +然後我們直接從函式回傳這個*資料表模型* `Hero`。但因為我們用 `HeroPublic` *資料模型*當作 `response_model`,**FastAPI** 會用 `HeroPublic` 來驗證與序列化資料。 {* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[56:62] hl[56:58] *} /// tip | 提示 -現在我們用 `response_model=HeroPublic`,而不是用回傳型別標註 `-> HeroPublic`,因為我們實際回傳的值其實「不是」`HeroPublic`。 +現在我們用 `response_model=HeroPublic`,而不是用**回傳型別標註** `-> HeroPublic`,因為我們實際回傳的值其實*不是* `HeroPublic`。 如果我們宣告 `-> HeroPublic`,你的編輯器與 linter 會(理所當然地)抱怨你回傳的是 `Hero` 而不是 `HeroPublic`。 -在 `response_model` 中宣告,就是要讓 FastAPI 去做它該做的事,而不影響型別標註,以及你的編輯器與其他工具提供的協助。 +在 `response_model` 中宣告,就是要讓 **FastAPI** 去做它該做的事,而不影響型別標註,以及你的編輯器與其他工具提供的協助。 /// ### 使用 `HeroPublic` 讀取多個 Hero { #read-heroes-with-heropublic } -我們可以像先前一樣「讀取」多個 `Hero`。同樣地,我們使用 `response_model=list[HeroPublic]` 來確保資料被正確驗證與序列化。 +我們可以像先前一樣**讀取**多個 `Hero`。同樣地,我們使用 `response_model=list[HeroPublic]` 來確保資料被正確驗證與序列化。 {* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[65:72] hl[65] *} ### 使用 `HeroPublic` 讀取單一 Hero { #read-one-hero-with-heropublic } -我們可以「讀取」單一 hero: +我們可以**讀取**單一 hero: {* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[75:80] hl[77] *} ### 使用 `HeroUpdate` 更新 Hero { #update-a-hero-with-heroupdate } -我們可以「更新 hero」。為此我們使用 HTTP 的 `PATCH` 操作。 +我們可以**更新 hero**。為此我們使用 HTTP 的 `PATCH` 操作。 -在程式碼中,我們會取得一個只包含用戶端有傳送的資料的 `dict`,不包含只是因為有預設值而存在的欄位。為了達成這點,我們使用 `exclude_unset=True`。這是關鍵。🪄 +在程式碼中,我們會取得一個只包含用戶端有傳送的資料的 `dict`,**只包含用戶端傳送的資料**,不包含只是因為有預設值而存在的欄位。為了達成這點,我們使用 `exclude_unset=True`。這是關鍵。🪄 然後我們使用 `hero_db.sqlmodel_update(hero_data)` 以 `hero_data` 的資料更新 `hero_db`。 @@ -324,7 +324,7 @@ $ fastapi dev ### 再次刪除 Hero { #delete-a-hero-again } -「刪除」 hero 基本上維持不變。 +**刪除** hero 基本上維持不變。 我們不會為了重構而重構一切。😅 @@ -352,6 +352,6 @@ $ fastapi dev ## 總結 { #recap } -你可以使用 [SQLModel](https://sqlmodel.tiangolo.com/) 與 SQL 資料庫互動,並用「資料模型」與「資料表模型」讓程式碼更簡潔。 +你可以使用 [**SQLModel**](https://sqlmodel.tiangolo.com/) 與 SQL 資料庫互動,並用*資料模型*與*資料表模型*讓程式碼更簡潔。 -你可以在 SQLModel 文件學到更多內容,這裡還有一份更長的 [使用 SQLModel 與 FastAPI 的教學](https://sqlmodel.tiangolo.com/tutorial/fastapi/)。🚀 +你可以在 **SQLModel** 文件學到更多內容,這裡還有一份更長的 [使用 SQLModel 與 **FastAPI** 的教學](https://sqlmodel.tiangolo.com/tutorial/fastapi/)。🚀 diff --git a/docs/zh-hant/docs/tutorial/static-files.md b/docs/zh-hant/docs/tutorial/static-files.md index 1b9e92a1c..0d6369eef 100644 --- a/docs/zh-hant/docs/tutorial/static-files.md +++ b/docs/zh-hant/docs/tutorial/static-files.md @@ -2,6 +2,14 @@ 你可以使用 `StaticFiles` 從某個目錄自動提供靜態檔案。 +/// tip + +如果你需要託管前端,請改用 `app.frontend()`,請在 [前端](frontend.md) 閱讀相關內容。 + +`app.frontend()` 底層使用 `StaticFiles`,並為前端提供幾項額外優勢,例如處理客戶端路由。 + +/// + ## 使用 `StaticFiles` { #use-staticfiles } - 匯入 `StaticFiles`。 diff --git a/docs/zh-hant/docs/tutorial/stream-json-lines.md b/docs/zh-hant/docs/tutorial/stream-json-lines.md index 204d32ffd..6276db788 100644 --- a/docs/zh-hant/docs/tutorial/stream-json-lines.md +++ b/docs/zh-hant/docs/tutorial/stream-json-lines.md @@ -2,7 +2,7 @@ 當你有一連串資料想以「**串流**」方式傳送時,可以使用 **JSON Lines**。 -/// info +/// note 在 FastAPI 0.134.0 新增。 @@ -48,7 +48,7 @@ sequenceDiagram 它和 JSON 陣列(相當於 Python 的 list)很像,但不同於用 `[]` 包起來並以 `,` 分隔項目,它是每一行各放一個 JSON 物件,彼此以換行字元分隔。 -/// info +/// note 重點在於你的應用能夠逐行產生資料,同時用戶端在消耗前一行的資料。 diff --git a/docs/zh-hant/docs/tutorial/testing.md b/docs/zh-hant/docs/tutorial/testing.md index f6bef5d96..09f6c0ec7 100644 --- a/docs/zh-hant/docs/tutorial/testing.md +++ b/docs/zh-hant/docs/tutorial/testing.md @@ -8,7 +8,7 @@ ## 使用 `TestClient` { #using-testclient } -/// info +/// note 要使用 `TestClient`,請先安裝 [`httpx`](https://www.python-httpx.org)。 @@ -113,13 +113,13 @@ $ pip install httpx │   └── test_main.py ``` -假設現在你的 **FastAPI** 應用所在的 `main.py` 有一些其他的路徑操作(path operations)。 +假設現在你的 **FastAPI** 應用所在的 `main.py` 有一些其他的 **路徑操作**。 它有一個可能回傳錯誤的 `GET` 操作。 它有一個可能回傳多種錯誤的 `POST` 操作。 -兩個路徑操作都需要一個 `X-Token` 標頭(header)。 +兩個 *路徑操作* 都需要一個 `X-Token` 標頭(header)。 {* ../../docs_src/app_testing/app_b_an_py310/main.py *} @@ -136,15 +136,15 @@ $ pip install httpx 例如: -* 要傳遞路徑或查詢參數,直接把它加在 URL 上。 +* 要傳遞 *path* 或 *query* 參數,直接把它加在 URL 上。 * 要傳遞 JSON 本文,將 Python 物件(例如 `dict`)傳給 `json` 參數。 -* 如果需要送出表單資料(Form Data)而不是 JSON,改用 `data` 參數。 -* 要傳遞標頭(headers),在 `headers` 參數中放一個 `dict`。 -* 對於 Cookie(cookies),在 `cookies` 參數中放一個 `dict`。 +* 如果需要送出 *Form Data* 而不是 JSON,改用 `data` 參數。 +* 要傳遞 *headers*,在 `headers` 參數中放一個 `dict`。 +* 對於 *cookies*,在 `cookies` 參數中放一個 `dict`。 關於如何把資料傳給後端(使用 `httpx` 或 `TestClient`),更多資訊請參考 [HTTPX 文件](https://www.python-httpx.org)。 -/// info +/// note 請注意,`TestClient` 接收的是可轉為 JSON 的資料,而不是 Pydantic models。 diff --git a/docs/zh-hant/docs/virtual-environments.md b/docs/zh-hant/docs/virtual-environments.md index a4d649c13..550363413 100644 --- a/docs/zh-hant/docs/virtual-environments.md +++ b/docs/zh-hant/docs/virtual-environments.md @@ -73,7 +73,7 @@ $ python -m venv .venv
-/// details | 上述命令的含義 +/// details | 上述指令的含義 * `python`: 使用名為 `python` 的程式 * `-m`: 以腳本的方式呼叫一個模組,我們將告訴它接下來使用哪個模組 @@ -106,7 +106,7 @@ $ uv venv //// -這個命令會在一個名為 `.venv` 的目錄中建立一個新的虛擬環境。 +這個指令會在一個名為 `.venv` 的目錄中建立一個新的虛擬環境。 /// details | `.venv`,或是其他名稱 @@ -164,7 +164,7 @@ $ source .venv/Scripts/activate /// tip -每次你在這個環境中安裝一個**新的套件**時,都需要**重新啟動**這個環境。 +每次你在這個環境中安裝一個**新的套件**時,都需要**再次啟用**這個環境。 這麼做確保了當你使用一個由這個套件安裝的**終端(CLI)程式**時,你使用的是你的虛擬環境中的程式,而不是全域安裝、可能版本不同的程式。 @@ -242,7 +242,7 @@ $ python -m pip install --upgrade pip -/// tip | 注意 +/// tip 有時你在嘗試升級 pip 時,可能會遇到 **`No module named pip`** 的錯誤。 @@ -544,7 +544,7 @@ Python 套件在推出**新版本**時通常會儘量**避免破壞性更改** 現在,想像一下如果有**許多**其他**套件**,它們都是你的**專案所依賴的**。這樣是非常難以管理的。你可能會發現有些專案使用了一些**不相容的套件版本**,而無法得知為什麼某些程式無法正常運作。 -此外,取決於你的操作系統(例如 Linux、Windows、macOS),它可能已經預先安裝了 Python。在這種情況下,它可能已經有一些系統所需的套件和特定版本。如果你在全域 Python 環境中安裝套件,可能會**破壞**某些隨作業系統一起安裝的程式。 +此外,取決於你的作業系統(例如 Linux、Windows、macOS),它可能已經預先安裝了 Python。在這種情況下,它可能已經有一些系統所需的套件和特定版本。如果你在全域 Python 環境中安裝套件,可能會**破壞**某些隨作業系統一起安裝的程式。 ## 套件安裝在哪裡 { #where-are-packages-installed } diff --git a/docs/zh/docs/_llm-test.md b/docs/zh/docs/_llm-test.md index 0da76d43c..5748c0900 100644 --- a/docs/zh/docs/_llm-test.md +++ b/docs/zh/docs/_llm-test.md @@ -37,7 +37,7 @@ 昨天,我的朋友写道:"如果你把 incorrectly 拼对了,你就把它拼错了"。我回答:"没错,但 'incorrectly' 错的不是 '"incorrectly"'"。 -/// note +/// note | 注意 LLM 很可能会把这段翻错。我们只关心在重新翻译时它是否能保持修正后的译文。 @@ -124,24 +124,24 @@ works(foo="bar") # 这可行 🎉 //// tab | 测试 -/// note -Some text +/// note | 注意 +一些文本 /// /// note | 技术细节 -Some text +一些文本 /// -/// tip -Some text +/// tip | 提示 +一些文本 /// -/// warning -Some text +/// warning | 警告 +一些文本 /// -/// danger -Some text +/// danger | 危险 +一些文本 /// //// @@ -213,7 +213,7 @@ Some text ## HTML "dfn" 元素 { #html-dfn-elements } -* 集群 +* 集群 * 深度学习 ## 标题 { #headings } @@ -222,15 +222,15 @@ Some text ### 开发 Web 应用——教程 { #develop-a-webapp-a-tutorial } -Hello. +你好。 ### 类型提示与注解 { #type-hints-and-annotations } -Hello again. +再次你好。 ### 超类与子类 { #super-and-subclasses } -Hello again. +再次你好。 //// @@ -248,241 +248,241 @@ Hello again. //// tab | 测试 -* you -* your +* 你 +* 你的 -* e.g. -* etc. +* 例如 +* 等 -* `foo` as an `int` -* `bar` as a `str` -* `baz` as a `list` +* 作为 `int` 的 `foo` +* 作为 `str` 的 `bar` +* 作为 `list` 的 `baz` -* the Tutorial - User guide -* the Advanced User Guide -* the SQLModel docs -* the API docs -* the automatic docs +* 教程 - 用户指南 +* 高级用户指南 +* SQLModel 文档 +* API 文档 +* 自动文档 -* Data Science -* Deep Learning -* Machine Learning -* Dependency Injection -* HTTP Basic authentication +* 数据科学 +* 深度学习 +* 机器学习 +* 依赖注入 +* HTTP Basic 认证 * HTTP Digest -* ISO format -* the JSON Schema standard -* the JSON schema -* the schema definition -* Password Flow -* Mobile - -* deprecated -* designed -* invalid -* on the fly -* standard -* default -* case-sensitive -* case-insensitive - -* to serve the application -* to serve the page - -* the app -* the application - -* the request -* the response -* the error response - -* the path operation -* the path operation decorator -* the path operation function - -* the body -* the request body -* the response body -* the JSON body -* the form body -* the file body -* the function body - -* the parameter -* the body parameter -* the path parameter -* the query parameter -* the cookie parameter -* the header parameter -* the form parameter -* the function parameter - -* the event -* the startup event -* the startup of the server -* the shutdown event -* the lifespan event - -* the handler -* the event handler -* the exception handler -* to handle - -* the model -* the Pydantic model -* the data model -* the database model -* the form model -* the model object - -* the class -* the base class -* the parent class -* the subclass -* the child class -* the sibling class -* the class method - -* the header -* the headers -* the authorization header -* the `Authorization` header -* the forwarded header - -* the dependency injection system -* the dependency -* the dependable -* the dependant - -* I/O bound -* CPU bound -* concurrency -* parallelism -* multiprocessing - -* the env var -* the environment variable -* the `PATH` -* the `PATH` variable - -* the authentication -* the authentication provider -* the authorization -* the authorization form -* the authorization provider -* the user authenticates -* the system authenticates the user - -* the CLI -* the command line interface - -* the server -* the client - -* the cloud provider -* the cloud service - -* the development -* the development stages - -* the dict -* the dictionary -* the enumeration -* the enum -* the enum member - -* the encoder -* the decoder -* to encode -* to decode - -* the exception -* to raise - -* the expression -* the statement - -* the frontend -* the backend - -* the GitHub discussion -* the GitHub issue - -* the performance -* the performance optimization - -* the return type -* the return value - -* the security -* the security scheme - -* the task -* the background task -* the task function - -* the template -* the template engine - -* the type annotation -* the type hint - -* the server worker -* the Uvicorn worker -* the Gunicorn Worker -* the worker process -* the worker class -* the workload - -* the deployment -* to deploy - -* the SDK -* the software development kit - -* the `APIRouter` -* the `requirements.txt` -* the Bearer Token -* the breaking change -* the bug -* the button -* the callable -* the code -* the commit -* the context manager -* the coroutine -* the database session -* the disk -* the domain -* the engine -* the fake X -* the HTTP GET method -* the item -* the library -* the lifespan -* the lock -* the middleware -* the mobile application -* the module -* the mounting -* the network -* the origin -* the override -* the payload -* the processor -* the property -* the proxy -* the pull request -* the query -* the RAM -* the remote machine -* the status code -* the string -* the tag -* the web framework -* the wildcard -* to return -* to validate +* ISO 格式 +* JSON Schema 标准 +* JSON schema +* schema 定义 +* 密码流 +* 移动端 + +* 已弃用 +* 设计的 +* 无效 +* 动态地 +* 标准 +* 默认 +* 区分大小写 +* 不区分大小写 + +* 为应用提供服务 +* 为页面提供服务 + +* 应用 +* 应用程序 + +* 请求 +* 响应 +* 错误响应 + +* 路径操作 +* 路径操作装饰器 +* 路径操作函数 + +* 请求体 +* 请求体 +* 响应体 +* JSON 请求体 +* 表单体 +* 文件体 +* 函数体 + +* 参数 +* 请求体参数 +* 路径参数 +* 查询参数 +* Cookie 参数 +* Header 参数 +* 表单参数 +* 函数参数 + +* 事件 +* 启动事件 +* 服务器启动 +* 关闭事件 +* lifespan 事件 + +* 处理器 +* 事件处理器 +* 异常处理器 +* 处理 + +* 模型 +* Pydantic 模型 +* 数据模型 +* 数据库模型 +* 表单模型 +* 模型对象 + +* 类 +* 基类 +* 父类 +* 子类 +* 子类 +* 兄弟类 +* 类方法 + +* Header +* Headers +* 授权 Header +* `Authorization` header +* 转发 Header + +* 依赖注入系统 +* 依赖项 +* 可依赖项 +* 依赖方 + +* I/O 密集型 +* CPU 密集型 +* 并发 +* 并行 +* 多进程 + +* 环境变量 +* 环境变量 +* `PATH` +* `PATH` 变量 + +* 认证 +* 认证提供方 +* 授权 +* 授权表单 +* 授权提供方 +* 用户进行认证 +* 系统对用户进行认证 + +* CLI +* 命令行界面 + +* 服务器 +* 客户端 + +* 云服务提供商 +* 云服务 + +* 开发 +* 开发阶段 + +* dict +* 字典 +* 枚举 +* 枚举 +* 枚举成员 + +* 编码器 +* 解码器 +* 编码 +* 解码 + +* 异常 +* 抛出 + +* 表达式 +* 语句 + +* 前端 +* 后端 + +* GitHub 讨论 +* GitHub issue + +* 性能 +* 性能优化 + +* 返回类型 +* 返回值 + +* 安全 +* 安全方案 + +* 任务 +* 后台任务 +* 任务函数 + +* 模板 +* 模板引擎 + +* 类型注解 +* 类型提示 + +* 服务器 worker +* Uvicorn worker +* Gunicorn Worker +* worker 进程 +* worker 类 +* 工作负载 + +* 部署 +* 部署 + +* SDK +* 软件开发工具包 + +* `APIRouter` +* `requirements.txt` +* Bearer Token +* 破坏性变更 +* bug +* 按钮 +* 可调用对象 +* 代码 +* 提交 +* 上下文管理器 +* 协程 +* 数据库会话 +* 磁盘 +* 域名 +* 引擎 +* 虚假 X +* HTTP GET 方法 +* 项 +* 库 +* 生命周期 +* 锁 +* 中间件 +* 移动应用 +* 模块 +* 挂载 +* 网络 +* 源 +* 覆盖 +* 载荷 +* 处理器 +* 属性 +* 代理 +* Pull Request +* 查询 +* RAM +* 远程机器 +* 状态码 +* 字符串 +* 标签 +* Web 框架 +* 通配符 +* 返回 +* 校验 //// diff --git a/docs/zh/docs/advanced/additional-responses.md b/docs/zh/docs/advanced/additional-responses.md index 365ba3db4..842d49b4c 100644 --- a/docs/zh/docs/advanced/additional-responses.md +++ b/docs/zh/docs/advanced/additional-responses.md @@ -34,7 +34,7 @@ /// -/// info | 信息 +/// note | 注意 `model` 键不是 OpenAPI 的一部分。 @@ -183,7 +183,7 @@ /// -/// info | 信息 +/// note | 注意 除非你在 `responses` 参数中明确指定不同的媒体类型,否则 FastAPI 会假设响应与主响应类具有相同的媒体类型(默认是 `application/json`)。 diff --git a/docs/zh/docs/advanced/additional-status-codes.md b/docs/zh/docs/advanced/additional-status-codes.md index af212ad8b..0f2e3d2ee 100644 --- a/docs/zh/docs/advanced/additional-status-codes.md +++ b/docs/zh/docs/advanced/additional-status-codes.md @@ -16,7 +16,7 @@ {* ../../docs_src/additional_status_codes/tutorial001_an_py310.py hl[4,25] *} -/// warning +/// warning | 警告 当你直接返回一个像上面例子中的 `Response` 对象时,它会直接返回。 @@ -38,4 +38,4 @@ 如果你直接返回额外的状态码和响应,它们不会包含在 OpenAPI 方案(API 文档)中,因为 FastAPI 没办法预先知道你要返回什么。 -但是你可以使用 [额外的响应](additional-responses.md) 在代码中记录这些内容。 +但是你可以使用:[额外的响应](additional-responses.md),在代码中记录这些内容。 diff --git a/docs/zh/docs/advanced/advanced-dependencies.md b/docs/zh/docs/advanced/advanced-dependencies.md index edaf964c9..12f2616c0 100644 --- a/docs/zh/docs/advanced/advanced-dependencies.md +++ b/docs/zh/docs/advanced/advanced-dependencies.md @@ -1,5 +1,6 @@ # 高级依赖项 { #advanced-dependencies } + ## 参数化的依赖项 { #parameterized-dependencies } 目前我们看到的依赖项都是固定的函数或类。 @@ -98,7 +99,7 @@ checker(q="somequery") 在 0.118.0 中,这一行为被回退为:让 `yield` 之后的退出代码在响应发送之后再执行。 -/// info | 信息 +/// note | 注意 如你在下文所见,这与 0.106.0 之前的行为非常相似,但对若干边界情况做了改进和修复。 diff --git a/docs/zh/docs/advanced/custom-response.md b/docs/zh/docs/advanced/custom-response.md index ce595572d..053fa34c7 100644 --- a/docs/zh/docs/advanced/custom-response.md +++ b/docs/zh/docs/advanced/custom-response.md @@ -41,7 +41,7 @@ {* ../../docs_src/custom_response/tutorial002_py310.py hl[2,7] *} -/// info | 信息 +/// note | 注意 参数 `response_class` 也会用来定义响应的「媒体类型」。 @@ -65,7 +65,7 @@ /// -/// info | 信息 +/// note | 注意 当然,实际的 `Content-Type` 头、状态码等等,将来自于你返回的 `Response` 对象。 diff --git a/docs/zh/docs/advanced/dataclasses.md b/docs/zh/docs/advanced/dataclasses.md index 42b4e4cc4..df94a7de7 100644 --- a/docs/zh/docs/advanced/dataclasses.md +++ b/docs/zh/docs/advanced/dataclasses.md @@ -1,5 +1,6 @@ # 使用数据类 { #using-dataclasses } + FastAPI 基于 **Pydantic** 构建,我已经向你展示过如何使用 Pydantic 模型声明请求与响应。 但 FastAPI 也支持以相同方式使用 [`dataclasses`](https://docs.python.org/3/library/dataclasses.html): @@ -18,7 +19,7 @@ FastAPI 基于 **Pydantic** 构建,我已经向你展示过如何使用 Pydant 这与使用 Pydantic 模型时的工作方式相同。而且底层实际上也是借助 Pydantic 实现的。 -/// info | 信息 +/// note | 注意 请注意,数据类不能完成 Pydantic 模型能做的所有事情。 diff --git a/docs/zh/docs/advanced/events.md b/docs/zh/docs/advanced/events.md index 0b647a438..49d497d3d 100644 --- a/docs/zh/docs/advanced/events.md +++ b/docs/zh/docs/advanced/events.md @@ -1,5 +1,6 @@ # 生命周期事件 { #lifespan-events } + 你可以定义在应用**启动**前执行的逻辑(代码)。这意味着在应用**开始接收请求**之前,这些代码只会被执行**一次**。 同样地,你可以定义在应用**关闭**时应执行的逻辑。在这种情况下,这段代码将在**处理可能的多次请求后**执行**一次**。 @@ -120,7 +121,7 @@ async with lifespan(app): 此处,`shutdown` 事件处理器函数会向文件 `log.txt` 写入一行文本 `"Application shutdown"`。 -/// info | 信息 +/// note | 注意 在 `open()` 函数中,`mode="a"` 指的是“追加”。因此这行文本会添加在文件已有内容之后,不会覆盖之前的内容。 @@ -152,7 +153,7 @@ async with lifespan(app): 在底层,这部分是 ASGI 技术规范中的 [Lifespan 协议](https://asgi.readthedocs.io/en/latest/specs/lifespan.html)的一部分,定义了称为 `startup` 和 `shutdown` 的事件。 -/// info | 信息 +/// note | 注意 你可以在 [Starlette 的 Lifespan 文档](https://www.starlette.dev/lifespan/) 中阅读更多关于 `lifespan` 处理器的内容。 diff --git a/docs/zh/docs/advanced/generate-clients.md b/docs/zh/docs/advanced/generate-clients.md index 049241bc9..dd15f0e9c 100644 --- a/docs/zh/docs/advanced/generate-clients.md +++ b/docs/zh/docs/advanced/generate-clients.md @@ -20,21 +20,6 @@ FastAPI 会自动生成 **OpenAPI 3.1** 规范,因此你使用的任何工具 /// -## 来自 FastAPI 赞助商的 SDK 生成器 { #sdk-generators-from-fastapi-sponsors } - -本节介绍的是由赞助 FastAPI 的公司提供的、具备**风险投资背景**或**公司支持**的方案。这些产品在高质量生成的 SDK 之上,提供了**更多特性**和**集成**。 - -通过 ✨ [**赞助 FastAPI**](../help-fastapi.md#sponsor-the-author) ✨,这些公司帮助确保框架及其**生态**保持健康并且**可持续**。 - -他们的赞助也体现了对 FastAPI **社区**(也就是你)的高度承诺,不仅关注提供**优秀的服务**,也支持一个**健壮且繁荣的框架**——FastAPI。🙇 - -例如,你可以尝试: - -* [Stainless](https://www.stainless.com/?utm_source=fastapi&utm_medium=referral) -* [liblab](https://developers.liblab.com/tutorials/sdk-for-fastapi?utm_source=fastapi) - -其中一些方案也可能是开源的或提供免费层级,你可以不花钱就先试用。其他商业 SDK 生成器也可在网上找到。🤓 - ## 创建一个 TypeScript SDK { #create-a-typescript-sdk } 先从一个简单的 FastAPI 应用开始: @@ -57,7 +42,7 @@ OpenAPI 中包含的这些模型信息就是用于**生成客户端代码**的 ### Hey API { #hey-api } -当我们有了带模型的 FastAPI 应用后,可以使用 Hey API 来生成 TypeScript 客户端。最快的方式是通过 npx: +当我们有了带模型的 FastAPI 应用后,可以使用 Hey API 来生成 TypeScript 客户端。最快的方式是通过 npx。 ```sh npx @hey-api/openapi-ts -i http://localhost:8000/openapi.json -o src/client @@ -83,7 +68,7 @@ npx @hey-api/openapi-ts -i http://localhost:8000/openapi.json -o src/client /// -你发送的数据如果不符合要求,会在编辑器中显示内联错误: +你发送的数据会有**内联错误**: @@ -120,9 +105,9 @@ npx @hey-api/openapi-ts -i http://localhost:8000/openapi.json -o src/client ItemsService.createItemItemsPost({name: "Plumbus", price: 5}) ``` -...这是因为客户端生成器会把每个*路径操作*的 OpenAPI 内部**操作 ID(operation ID)**用作方法名的一部分。 +...这是因为客户端生成器会使用每个*路径操作*的 OpenAPI 内部**操作 ID(operation ID)**。 -OpenAPI 要求每个操作 ID 在所有*路径操作*中都是唯一的,因此 FastAPI 会使用**函数名**、**路径**和**HTTP 方法/操作**来生成操作 ID,以确保其唯一性。 +OpenAPI 要求每个操作 ID 在所有*路径操作*中都是唯一的,因此 FastAPI 会使用**函数名**、**路径**和**HTTP 方法/操作**来生成操作 ID,因为这样可以确保操作 ID 是唯一的。 接下来我会告诉你如何改进。🤓 @@ -194,9 +179,9 @@ npx @hey-api/openapi-ts -i ./openapi.json -o src/client 使用自动生成的客户端时,你会获得以下内容的**自动补全**: -* 方法 -* 请求体中的数据、查询参数等 -* 响应数据 +* 方法。 +* 请求体中的数据、查询参数等。 +* 响应数据。 你还会为所有内容获得**内联错误**。 diff --git a/docs/zh/docs/advanced/json-base64-bytes.md b/docs/zh/docs/advanced/json-base64-bytes.md index 7792282c7..040957c69 100644 --- a/docs/zh/docs/advanced/json-base64-bytes.md +++ b/docs/zh/docs/advanced/json-base64-bytes.md @@ -4,7 +4,7 @@ ## Base64 与文件 { #base64-vs-files } -请先考虑是否可以使用 [请求文件](../tutorial/request-files.md) 来上传二进制数据,并使用 [自定义响应 - FileResponse](./custom-response.md#fileresponse--fileresponse-) 来发送二进制数据,而不是把它编码进 JSON。 +请先考虑是否可以使用 [请求文件](../tutorial/request-files.md) 来上传二进制数据,并使用 [自定义响应 - FileResponse](./custom-response.md#fileresponse) 来发送二进制数据,而不是把它编码进 JSON。 JSON 只能包含 UTF-8 编码的字符串,因此无法直接包含原始字节。 @@ -14,7 +14,7 @@ Base64 可以把二进制数据编码为字符串,但为此会使用比原始 ## Pydantic `bytes` { #pydantic-bytes } -你可以声明带有 `bytes` 字段的 Pydantic 模型,然后在模型配置中使用 `val_json_bytes` 指定用 base64 来验证输入的 JSON 数据;作为验证的一部分,它会将该 base64 字符串解码为字节。 +你可以声明带有 `bytes` 字段的 Pydantic 模型,然后在模型配置中使用 `val_json_bytes` 指定用 base64 来*验证*输入的 JSON 数据;作为验证的一部分,它会将该 base64 字符串解码为字节。 {* ../../docs_src/json_base64_bytes/tutorial001_py310.py ln[1:9,29:35] hl[9] *} @@ -52,12 +52,12 @@ Base64 可以把二进制数据编码为字符串,但为此会使用比原始 ## 用于输出数据的 Pydantic `bytes` { #pydantic-bytes-for-output-data } -对于输出数据,你也可以在模型配置中为 `bytes` 字段使用 `ser_json_bytes`,Pydantic 会在生成 JSON 响应时将字节以 base64 进行序列化。 +对于输出数据,你也可以在模型配置中为 `bytes` 字段使用 `ser_json_bytes`,Pydantic 会在生成 JSON 响应时将字节以 base64 进行*序列化*。 {* ../../docs_src/json_base64_bytes/tutorial001_py310.py ln[1:2,12:16,29,38:41] hl[16] *} ## 用于输入和输出数据的 Pydantic `bytes` { #pydantic-bytes-for-input-and-output-data } -当然,你也可以使用同一个配置了 base64 的模型,在接收和发送 JSON 数据时,同时处理输入(使用 `val_json_bytes` 进行验证)和输出(使用 `ser_json_bytes` 进行序列化)。 +当然,你也可以使用同一个配置了 base64 的模型,在接收和发送 JSON 数据时,同时处理输入(使用 `val_json_bytes` 进行*验证*)和输出(使用 `ser_json_bytes` 进行*序列化*)。 {* ../../docs_src/json_base64_bytes/tutorial001_py310.py ln[1:2,19:26,29,44:46] hl[23:26] *} diff --git a/docs/zh/docs/advanced/openapi-callbacks.md b/docs/zh/docs/advanced/openapi-callbacks.md index 49cef3648..3ca99b980 100644 --- a/docs/zh/docs/advanced/openapi-callbacks.md +++ b/docs/zh/docs/advanced/openapi-callbacks.md @@ -1,35 +1,35 @@ # OpenAPI 回调 { #openapi-callbacks } -您可以创建一个包含*路径操作*的 API,它会触发对别人创建的*外部 API*的请求(很可能就是那个会“使用”您 API 的同一个开发者)。 +你可以创建一个包含*路径操作*的 API,该*路径操作*可以触发对其他人创建的*外部 API*的请求(很可能就是那个会*使用*你的 API 的同一个开发者)。 -当您的 API 应用调用*外部 API*时,这个过程被称为“回调”。因为外部开发者编写的软件会先向您的 API 发送请求,然后您的 API 再进行*回调*,向*外部 API*发送请求(很可能也是该开发者创建的)。 +当你的 API 应用调用*外部 API*时,这个过程被称为“回调”。因为外部开发者编写的软件会先向你的 API 发送请求,然后你的 API 再*回调*,向*外部 API*发送请求(很可能也是该开发者创建的)。 -此时,我们需要存档外部 API 的*信息*,比如应该有哪些*路径操作*,请求体应该是什么,应该返回什么响应等。 +在这种情况下,你可能希望记录该外部 API *应该*是什么样子。它应该有哪些*路径操作*,应该接收什么请求体,应该返回什么响应等。 ## 使用回调的应用 { #an-app-with-callbacks } -示例如下。 +让我们通过一个例子来看这一切。 -假设要开发一个创建发票的应用。 +假设你开发一个可以创建发票的应用。 -发票包括 `id`、`title`(可选)、`customer`、`total` 等属性。 +这些发票会有 `id`、`title`(可选)、`customer` 和 `total`。 -API 的用户(外部开发者)要在您的 API 内使用 POST 请求创建一条发票记录。 +你的 API 用户(外部开发者)会通过 POST 请求在你的 API 中创建一张发票。 -(假设)您的 API 将: +然后你的 API 会(假设): -* 把发票发送至外部开发者的消费者 -* 归集现金 -* 把通知发送至 API 的用户(外部开发者) - * 通过(从您的 API)发送 POST 请求至外部 API(即**回调**)来完成 +* 将发票发送给外部开发者的某个客户。 +* 收款。 +* 向 API 用户(外部开发者)发回通知。 + * 这会通过(从*你的 API*)向该外部开发者提供的某个*外部 API*发送 POST 请求来完成(这就是“回调”)。 ## 常规 **FastAPI** 应用 { #the-normal-fastapi-app } -添加回调前,首先看下常规 API 应用是什么样子。 +我们先看看在添加回调之前,常规 API 应用会是什么样子。 -常规 API 应用包含接收 `Invoice` 请求体的*路径操作*,还有包含回调 URL 的查询参数 `callback_url`。 +它会有一个接收 `Invoice` 请求体的*路径操作*,以及一个包含回调 URL 的查询参数 `callback_url`。 -这部分代码很常规,您对绝大多数代码应该都比较熟悉了: +这部分很常规,大部分代码你应该已经很熟悉了: {* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[7:11,34:51] *} @@ -39,92 +39,92 @@ API 的用户(外部开发者)要在您的 API 内使用 POST 请求创建 /// -此处唯一比较新的内容是*路径操作装饰器*中的 `callbacks=invoices_callback_router.routes` 参数,下文介绍。 +唯一的新内容是*路径操作装饰器*中的参数 `callbacks=invoices_callback_router.routes`。接下来我们会看看它是什么。 -## 存档回调 { #documenting-the-callback } +## 为回调编写文档 { #documenting-the-callback } -实际的回调代码高度依赖于您自己的 API 应用。 +实际的回调代码会高度依赖你自己的 API 应用。 -并且可能每个应用都各不相同。 +而且很可能在不同应用之间差异很大。 -回调代码可能只有一两行,比如: +它可能只有一两行代码,例如: ```Python callback_url = "https://example.com/api/v1/invoices/events/" httpx.post(callback_url, json={"description": "Invoice paid", "paid": True}) ``` -但回调最重要的部分可能是,根据 API 要发送给回调请求体的数据等内容,确保您的 API 用户(外部开发者)正确地实现*外部 API*。 +但回调最重要的部分可能是确保你的 API 用户(外部开发者)正确实现*外部 API*,与*你的 API*将在回调请求体中发送的数据等相匹配。 -因此,我们下一步要做的就是添加代码,为从 API 接收回调的*外部 API*存档。 +因此,接下来我们要做的是添加代码,用来记录该*外部 API*应该是什么样子,才能接收来自*你的 API*的回调。 -这部分文档在 `/docs` 下的 Swagger UI 中显示,并且会告诉外部开发者如何构建*外部 API*。 +这份文档会显示在你的 API 的 `/docs` 下的 Swagger UI 中,并且会让外部开发者知道如何构建*外部 API*。 -本例没有实现回调本身(只是一行代码),只有文档部分。 +本例不实现回调本身(那可能只是一行代码),只实现文档部分。 /// tip | 提示 -实际的回调只是 HTTP 请求。 +实际的回调只是一个 HTTP 请求。 -实现回调时,要使用 [HTTPX](https://www.python-httpx.org) 或 [Requests](https://requests.readthedocs.io/)。 +自己实现回调时,你可以使用类似 [HTTPX](https://www.python-httpx.org) 或 [Requests](https://requests.readthedocs.io/) 的工具。 /// ## 编写回调文档代码 { #write-the-callback-documentation-code } -应用不执行这部分代码,只是用它来*记录 外部 API* 。 +这段代码不会在你的应用中执行,我们只需要用它来*记录*该*外部 API*应该是什么样子。 -但,您已经知道用 **FastAPI** 创建自动 API 文档有多简单了。 +不过,你已经知道如何使用 **FastAPI** 轻松为 API 创建自动文档了。 -我们要使用与存档*外部 API* 相同的知识...通过创建外部 API 要实现的*路径操作*(您的 API 要调用的)。 +因此,我们会使用相同的知识来记录该*外部 API*应该是什么样子...通过创建外部 API 应该实现的*路径操作*(也就是你的 API 将调用的那些)。 /// tip | 提示 -编写存档回调的代码时,假设您是*外部开发者*可能会用的上。并且您当前正在实现的是*外部 API*,不是*您自己的 API*。 +在编写用于记录回调的代码时,可以想象你就是那个*外部开发者*。而且你现在正在实现的是*外部 API*,不是*你的 API*。 -临时改变(为外部开发者的)视角能让您更清楚该如何放置*外部 API* 响应和请求体的参数与 Pydantic 模型等。 +临时采用这个(*外部开发者*的)视角,可以帮助你更清楚地判断该把参数、请求体的 Pydantic 模型、响应等放在该*外部 API*的什么位置。 /// -### 创建回调的 `APIRouter` { #create-a-callback-apirouter } +### 创建回调 `APIRouter` { #create-a-callback-apirouter } -首先,新建包含一些用于回调的 `APIRouter`。 +首先创建一个新的 `APIRouter`,它将包含一个或多个回调。 {* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[1,23] *} ### 创建回调*路径操作* { #create-the-callback-path-operation } -创建回调*路径操作*也使用之前创建的 `APIRouter`。 +要创建回调*路径操作*,请使用你在上面创建的同一个 `APIRouter`。 -它看起来和常规 FastAPI *路径操作*差不多: +它看起来应该就像普通的 FastAPI *路径操作*: -* 声明要接收的请求体,例如,`body: InvoiceEvent` -* 还要声明要返回的响应,例如,`response_model=InvoiceEventReceived` +* 它可能应该声明要接收的请求体,例如 `body: InvoiceEvent`。 +* 它也可以声明要返回的响应,例如 `response_model=InvoiceEventReceived`。 {* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[14:16,19:20,26:30] *} -回调*路径操作*与常规*路径操作*有两点主要区别: +它与普通*路径操作*有 2 个主要区别: -* 它不需要任何实际的代码,因为应用不会调用这段代码。它只是用于存档*外部 API*。因此,函数的内容只需要 `pass` 就可以了 -* *路径*可以包含 [OpenAPI 3 表达式](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#key-expression)(详见下文),可以使用带参数的变量,以及发送至您的 API 的原始请求的部分 +* 它不需要任何实际代码,因为你的应用永远不会调用这段代码。它只用于记录*外部 API*。因此,函数可以只有 `pass`。 +* *路径*可以包含 [OpenAPI 3 表达式](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#key-expression)(见下文),其中可以使用带参数的变量,以及发送到*你的 API*的原始请求的部分内容。 ### 回调路径表达式 { #the-callback-path-expression } -回调*路径*支持包含发送给您的 API 的原始请求的部分的 [OpenAPI 3 表达式](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#key-expression)。 +回调*路径*可以有一个 [OpenAPI 3 表达式](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#key-expression),其中可以包含发送到*你的 API*的原始请求的部分内容。 -本例中是 `str`: +在这个例子中,它是这个 `str`: ```Python "{$callback_url}/invoices/{$request.body.id}" ``` -因此,如果您的 API 用户(外部开发者)发送请求到您的 API: +所以,如果你的 API 用户(外部开发者)向*你的 API*发送请求到: ``` https://yourapi.com/invoices/?callback_url=https://www.external.org/events ``` -使用如下 JSON 请求体: +并带有如下 JSON 请求体: ```JSON { @@ -134,13 +134,13 @@ https://yourapi.com/invoices/?callback_url=https://www.external.org/events } ``` -然后,您的 API 就会处理发票,并在某个点之后,发送回调请求至 `callback_url`(外部 API): +那么*你的 API*会处理该发票,并在稍后的某个时间点,向 `callback_url`(*外部 API*)发送回调请求: ``` https://www.external.org/events/invoices/2expen51ve ``` -JSON 请求体包含如下内容: +并带有类似如下内容的 JSON 请求体: ```JSON { @@ -149,7 +149,7 @@ JSON 请求体包含如下内容: } ``` -它会预期*外部 API* 的响应包含如下 JSON 请求体: +它会预期该*外部 API*返回类似如下 JSON 请求体的响应: ```JSON { @@ -159,28 +159,28 @@ JSON 请求体包含如下内容: /// tip | 提示 -注意,回调 URL 包含 `callback_url`(`https://www.external.org/events`)中的查询参数,还有 JSON 请求体内部的发票 ID(`2expen51ve`)。 +请注意,使用的回调 URL 包含在 `callback_url` 中作为查询参数接收到的 URL(`https://www.external.org/events`),也包含 JSON 请求体内部的发票 `id`(`2expen51ve`)。 /// ### 添加回调路由 { #add-the-callback-router } -至此,在上文创建的回调路由里就包含了*回调路径操作*(外部开发者要在外部 API 中实现)。 +此时,你已经在上面创建的回调路由中拥有了所需的*回调路径操作*(即*外部开发者*应该在*外部 API*中实现的那些)。 -现在使用 API *路径操作装饰器*的参数 `callbacks`,从回调路由传递属性 `.routes`(实际上只是路由/路径操作的**列表**): +现在,在*你的 API 的路径操作装饰器*中使用参数 `callbacks`,传入该回调路由的 `.routes` 属性: {* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[33] *} /// tip | 提示 -注意,不能把路由本身(`invoices_callback_router`)传递给 `callbacks=`,要传递 `invoices_callback_router.routes` 中的 `.routes` 属性。 +请注意,你不是把路由本身(`invoices_callback_router`)传给 `callbacks=`,而是传它的 `.routes`,也就是 `invoices_callback_router.routes`。FastAPI 会使用这些路由来生成回调的 OpenAPI 文档。 /// ### 查看文档 { #check-the-docs } -现在,启动应用并打开 [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs)。 +现在你可以启动应用并访问 [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs)。 -就能看到文档的*路径操作*已经包含了**回调**的内容以及*外部 API*: +你会看到文档中为你的*路径操作*包含了一个 "Callbacks" 部分,展示了*外部 API*应该是什么样子: diff --git a/docs/zh/docs/advanced/openapi-webhooks.md b/docs/zh/docs/advanced/openapi-webhooks.md index 3d6bcc9bc..8bec3b618 100644 --- a/docs/zh/docs/advanced/openapi-webhooks.md +++ b/docs/zh/docs/advanced/openapi-webhooks.md @@ -22,7 +22,7 @@ 这能让您的用户更轻松地**实现他们的 API** 来接收您的**网络钩子**请求,他们甚至可能能够自动生成一些自己的 API 代码。 -/// info | 信息 +/// note | 注意 网络钩子在 OpenAPI 3.1.0 及以上版本中可用,FastAPI `0.99.0` 及以上版本支持。 @@ -36,7 +36,7 @@ 您定义的网络钩子将被包含在 `OpenAPI` 的架构中,并出现在自动生成的**文档 UI** 中。 -/// info | 信息 +/// note | 注意 `app.webhooks` 对象实际上只是一个 `APIRouter` ,与您在使用多个文件来构建应用程序时所使用的类型相同。 diff --git a/docs/zh/docs/advanced/path-operation-advanced-configuration.md b/docs/zh/docs/advanced/path-operation-advanced-configuration.md index 67f3bd7e9..a9f2c1e86 100644 --- a/docs/zh/docs/advanced/path-operation-advanced-configuration.md +++ b/docs/zh/docs/advanced/path-operation-advanced-configuration.md @@ -16,17 +16,11 @@ ### 使用 *路径操作函数* 的函数名作为 operationId { #using-the-path-operation-function-name-as-the-operationid } -如果你想用 API 的函数名作为 `operationId`,你可以遍历所有路径操作,并使用它们的 `APIRoute.name` 重写每个 *路径操作* 的 `operation_id`。 +如果你想用 API 的函数名作为 `operationId`,你可以向 `FastAPI` 传入自定义的 `generate_unique_id_function`。 -你应该在添加了所有 *路径操作* 之后执行此操作。 +该函数会接收每个 `APIRoute`,并返回用于该路径操作的 `operationId`。 -{* ../../docs_src/path_operation_advanced_configuration/tutorial002_py310.py hl[2, 12:21, 24] *} - -/// tip - -如果你手动调用 `app.openapi()`,你应该在此之前更新 `operationId`。 - -/// +{* ../../docs_src/path_operation_advanced_configuration/tutorial002_py310.py hl[2,5:6,9] *} /// warning diff --git a/docs/zh/docs/advanced/response-change-status-code.md b/docs/zh/docs/advanced/response-change-status-code.md index 379afd4eb..4339875e4 100644 --- a/docs/zh/docs/advanced/response-change-status-code.md +++ b/docs/zh/docs/advanced/response-change-status-code.md @@ -22,7 +22,7 @@ {* ../../docs_src/response_change_status_code/tutorial001_py310.py hl[1,9,12] *} -然后你可以像平常一样返回任何你需要的对象(例如一个`dict`或者一个数据库模型)。 +然后你可以像平常一样返回任何你需要的对象(一个`dict`、一个数据库模型等)。 如果你声明了一个`response_model`,它仍然会被用来过滤和转换你返回的对象。 diff --git a/docs/zh/docs/advanced/response-cookies.md b/docs/zh/docs/advanced/response-cookies.md index 7fad89e5c..9a41b95e4 100644 --- a/docs/zh/docs/advanced/response-cookies.md +++ b/docs/zh/docs/advanced/response-cookies.md @@ -1,36 +1,38 @@ -# 响应Cookies { #response-cookies } +# 响应 Cookies { #response-cookies } ## 使用 `Response` 参数 { #use-a-response-parameter } -你可以在 *路径操作函数* 中定义一个类型为 `Response` 的参数,这样你就可以在这个临时响应对象中设置cookie了。 +你可以在*路径操作函数*中声明一个类型为 `Response` 的参数。 + +然后你可以在这个*临时*响应对象中设置 Cookie。 {* ../../docs_src/response_cookies/tutorial002_py310.py hl[1, 8:9] *} -而且你还可以根据你的需要响应不同的对象,比如常用的 `dict`,数据库model等。 +然后你可以像平常一样返回所需的任何对象(`dict`、数据库模型等)。 -如果你定义了 `response_model`,程序会自动根据`response_model`来过滤和转换你响应的对象。 +如果你声明了 `response_model`,它仍会用于过滤和转换你返回的对象。 -**FastAPI** 会使用这个 *临时* 响应对象去装在这些cookies信息 (同样还有headers和状态码等信息), 最终会将这些信息和通过`response_model`转化过的数据合并到最终的响应里。 +**FastAPI** 会使用这个*临时*响应来提取 Cookie(还有 header 和状态码),并将它们放入最终响应中;最终响应包含你返回的值,并经过任何 `response_model` 过滤。 -你也可以在依赖中定义`Response`参数,并设置cookie和header。 +你也可以在依赖项中声明 `Response` 参数,并在其中设置 Cookie(和 header)。 -## 直接响应 `Response` { #return-a-response-directly } +## 直接返回 `Response` { #return-a-response-directly } -你还可以在直接响应`Response`时直接创建cookies。 +在代码中直接返回 `Response` 时,你也可以创建 Cookie。 为此,你可以按照[直接返回 Response](response-directly.md)中的说明创建一个响应。 -然后设置Cookies,并返回: +然后在其中设置 Cookie,并返回它: {* ../../docs_src/response_cookies/tutorial001_py310.py hl[10:12] *} /// tip | 提示 -需要注意,如果你直接反馈一个response对象,而不是使用`Response`入参,FastAPI则会直接反馈你封装的response对象。 +请记住,如果你直接返回响应,而不是使用 `Response` 参数,FastAPI 会直接返回它。 -所以你需要确保你响应数据类型的正确性,如:你可以使用`JSONResponse`来兼容JSON的场景。 +因此,你必须确保你的数据类型正确。例如,如果你返回的是 `JSONResponse`,数据就需要兼容 JSON。 -同时,你也应当仅反馈通过`response_model`过滤过的数据。 +并且还要确保你没有发送本应由 `response_model` 过滤的数据。 /// @@ -38,12 +40,12 @@ /// note | 技术细节 -你也可以使用`from starlette.responses import Response` 或者 `from starlette.responses import JSONResponse`。 +你也可以使用 `from starlette.responses import Response` 或者 `from starlette.responses import JSONResponse`。 -为了方便开发者,**FastAPI** 封装了相同数据类型,如`starlette.responses` 和 `fastapi.responses`。不过大部分response对象都是直接引用自Starlette。 +**FastAPI** 为了方便开发者,提供了与 `starlette.responses` 相同的 `fastapi.responses`。但大多数可用的响应都直接来自 Starlette。 -因为`Response`对象可以非常便捷的设置headers和cookies,所以 **FastAPI** 同时也封装了`fastapi.Response`。 +由于 `Response` 经常用于设置 header 和 Cookie,**FastAPI** 也在 `fastapi.Response` 中提供了它。 /// -如果你想查看所有可用的参数和选项,可以参考 [Starlette 文档](https://www.starlette.dev/responses/#set-cookie)。 +要查看所有可用参数和选项,请查看 [Starlette 文档](https://www.starlette.dev/responses/#set-cookie)。 diff --git a/docs/zh/docs/advanced/response-directly.md b/docs/zh/docs/advanced/response-directly.md index 196622146..f9a865137 100644 --- a/docs/zh/docs/advanced/response-directly.md +++ b/docs/zh/docs/advanced/response-directly.md @@ -5,9 +5,9 @@ 如果你声明了 [响应模型](../tutorial/response-model.md),FastAPI 会使用它通过 Pydantic 将数据序列化为 JSON。 如果你没有声明响应模型,**FastAPI** 会使用在 [JSON 兼容编码器](../tutorial/encoder.md) 中阐述的 `jsonable_encoder`。 -然后,**FastAPI** 会在后台将这些兼容 JSON 的数据(比如字典)放到一个 `JSONResponse` 中,该 `JSONResponse` 会用来发送响应给客户端。 +然后,**FastAPI** 会将其放入一个 `JSONResponse` 中。 -但是你可以在你的 *路径操作* 中直接返回一个 `JSONResponse`。 +你也可以直接创建一个 `JSONResponse` 并返回它。 /// tip | 提示 @@ -17,9 +17,9 @@ ## 返回 `Response` { #return-a-response } -事实上,你可以返回任意 `Response` 或者任意 `Response` 的子类。 +你可以返回一个 `Response` 或其任意子类。 -/// info | 信息 +/// note | 注意 `JSONResponse` 本身是一个 `Response` 的子类。 diff --git a/docs/zh/docs/advanced/response-headers.md b/docs/zh/docs/advanced/response-headers.md index ab99a4ece..89357058d 100644 --- a/docs/zh/docs/advanced/response-headers.md +++ b/docs/zh/docs/advanced/response-headers.md @@ -1,5 +1,6 @@ # 响应头 { #response-headers } + ## 使用 `Response` 参数 { #use-a-response-parameter } 你可以在你的*路径操作函数*中声明一个 `Response` 类型的参数(就像你可以为 cookies 做的那样)。 diff --git a/docs/zh/docs/advanced/security/oauth2-scopes.md b/docs/zh/docs/advanced/security/oauth2-scopes.md index a1ecc641c..fa0dd8eff 100644 --- a/docs/zh/docs/advanced/security/oauth2-scopes.md +++ b/docs/zh/docs/advanced/security/oauth2-scopes.md @@ -46,7 +46,7 @@ OAuth2 规范将“作用域”定义为由空格分隔的字符串列表。 * Facebook / Instagram 使用 `instagram_basic` * Google 使用 `https://www.googleapis.com/auth/drive` -/// info | 信息 +/// note | 注意 在 OAuth2 中,“作用域”只是一个声明所需特定权限的字符串。 @@ -86,7 +86,7 @@ OAuth2 规范将“作用域”定义为由空格分隔的字符串列表。 现在,修改令牌的*路径操作*以返回请求的作用域。 -我们仍然使用 `OAuth2PasswordRequestForm`。它包含 `scopes` 属性,其值是 `list[str]`,包含请求中接收到的每个作用域。 +我们仍然使用 `OAuth2PasswordRequestForm`。它包含 `scopes` 属性,其值是 `list` of `str`,包含请求中接收到的每个作用域。 我们把这些作用域作为 JWT 令牌的一部分返回。 @@ -126,7 +126,7 @@ OAuth2 规范将“作用域”定义为由空格分隔的字符串列表。 {* ../../docs_src/security/tutorial005_an_py310.py hl[5,141,172] *} -/// info | 技术细节 +/// note | 技术细节 `Security` 实际上是 `Depends` 的子类,它只多了一个我们稍后会看到的参数。 @@ -174,7 +174,7 @@ OAuth2 规范将“作用域”定义为由空格分隔的字符串列表。 为此,我们给 Pydantic 模型 `TokenData` 添加了一个新属性 `scopes`。 -通过用 Pydantic 验证数据,我们可以确保确实得到了例如一个由作用域组成的 `list[str]`,以及一个 `str` 类型的 `username`。 +通过用 Pydantic 验证数据,我们可以确保确实得到了例如一个由作用域组成的 `list` of `str`,以及一个 `str` 类型的 `username`。 而不是,例如得到一个 `dict` 或其它什么,这可能会在后续某个时刻破坏应用,形成安全风险。 diff --git a/docs/zh/docs/advanced/settings.md b/docs/zh/docs/advanced/settings.md index 31a7cc82d..2159ccb25 100644 --- a/docs/zh/docs/advanced/settings.md +++ b/docs/zh/docs/advanced/settings.md @@ -297,6 +297,6 @@ participant execute as Execute function 你可以使用 Pydantic Settings 来处理应用的设置或配置,享受 Pydantic 模型的全部能力。 -- 通过使用依赖项,你可以简化测试。 -- 你可以与它一起使用 `.env` 文件。 -- 使用 `@lru_cache` 可以避免为每个请求反复读取 dotenv 文件,同时允许你在测试时进行覆盖。 +* 通过使用依赖项,你可以简化测试。 +* 你可以与它一起使用 `.env` 文件。 +* 使用 `@lru_cache` 可以避免为每个请求反复读取 dotenv 文件,同时允许你在测试时进行覆盖。 diff --git a/docs/zh/docs/advanced/stream-data.md b/docs/zh/docs/advanced/stream-data.md index 322561ac1..44e005ace 100644 --- a/docs/zh/docs/advanced/stream-data.md +++ b/docs/zh/docs/advanced/stream-data.md @@ -2,9 +2,9 @@ 如果你要流式传输可以结构化为 JSON 的数据,你应该[流式传输 JSON Lines](../tutorial/stream-json-lines.md)。 -但如果你想流式传输纯二进制数据或字符串,可以按下面的方法操作。 +但如果你想**流式传输纯二进制数据**或字符串,可以按下面的方法操作。 -/// info | 信息 +/// note | 注意 自 FastAPI 0.134.0 起新增。 @@ -12,11 +12,11 @@ ## 使用场景 { #use-cases } -如果你想流式传输纯字符串,例如直接来自某个 AI LLM 服务的输出,可以使用它。 +如果你想流式传输纯字符串,例如直接来自某个 **AI LLM** 服务的输出,可以使用它。 -你也可以用它来流式传输大型二进制文件,在读取的同时按块发送,无需一次性把所有内容读入内存。 +你也可以用它来流式传输**大型二进制文件**,在读取的同时按块发送,无需一次性把所有内容读入内存。 -你还可以用这种方式流式传输视频或音频,甚至可以在处理的同时生成并发送。 +你还可以用这种方式流式传输**视频**或**音频**,甚至可以在处理的同时生成并发送。 ## 使用 `yield` 的 `StreamingResponse` { #a-streamingresponse-with-yield } @@ -40,7 +40,7 @@ FastAPI 会将每个数据块原样交给 `StreamingResponse`,不会尝试将 {* ../../docs_src/stream_data/tutorial001_py310.py ln[32:35] hl[33] *} -这也意味着,使用 `StreamingResponse` 时,你拥有按需精确生成与编码字节数据的自由,同时也承担相应的责任,它与类型注解无关。🤓 +这也意味着,使用 `StreamingResponse` 时,你拥有按需精确生成与编码字节数据的**自由**,同时也承担相应的**责任**,它与类型注解无关。🤓 ### 流式传输字节 { #stream-bytes } @@ -90,7 +90,7 @@ FastAPI 会将每个数据块原样交给 `StreamingResponse`,不会尝试将 而且很多情况下,读取它们是一个阻塞操作(可能会阻塞事件循环),因为数据来自磁盘或网络。 -/// info | 信息 +/// note | 注意 上面的示例其实是个例外,因为 `io.BytesIO` 对象已经在内存中,所以读取它不会阻塞。 diff --git a/docs/zh/docs/advanced/strict-content-type.md b/docs/zh/docs/advanced/strict-content-type.md index 973d1840c..0cf9242af 100644 --- a/docs/zh/docs/advanced/strict-content-type.md +++ b/docs/zh/docs/advanced/strict-content-type.md @@ -81,7 +81,7 @@ http://localhost:8000/v1/agents/multivac 启用该设置后,缺少 `Content-Type` 头的请求其请求体也会按 JSON 解析,这与旧版本 FastAPI 的行为一致。 -/// info | 信息 +/// note | 注意 此行为和配置在 FastAPI 0.132.0 中新增。 diff --git a/docs/zh/docs/advanced/websockets.md b/docs/zh/docs/advanced/websockets.md index d90ef8733..7950f90ea 100644 --- a/docs/zh/docs/advanced/websockets.md +++ b/docs/zh/docs/advanced/websockets.md @@ -111,11 +111,11 @@ $ fastapi dev {* ../../docs_src/websockets_/tutorial002_an_py310.py hl[68:69,82] *} -/// info +/// note | 注意 由于这是一个 WebSocket,抛出 `HTTPException` 并不是很合理,而是抛出 `WebSocketException`。 -您可以使用[规范中定义的有效代码](https://tools.ietf.org/html/rfc6455#section-7.4.1)。 +您可以使用[规范中定义的有效关闭代码](https://tools.ietf.org/html/rfc6455#section-7.4.1)。 /// @@ -140,7 +140,7 @@ $ fastapi dev * "Item ID",用于路径。 * "Token",作为查询参数。 -/// tip +/// tip | 提示 注意,查询参数 `token` 将由依赖项处理。 @@ -168,13 +168,13 @@ $ fastapi dev Client #1596980209979 left the chat ``` -/// tip +/// tip | 提示 上面的应用程序是一个最小和简单的示例,用于演示如何处理和向多个 WebSocket 连接广播消息。 但请记住,由于所有内容都在内存中以单个列表的形式处理,因此它只能在进程运行时工作,并且只能使用单个进程。 -如果您需要与 FastAPI 集成更简单但更强大的功能,支持 Redis、PostgreSQL 或其他功能,请查看 [encode/broadcaster](https://github.com/encode/broadcaster)。 +如果您需要与 FastAPI 集成更简单但更健壮的方案,支持 Redis、PostgreSQL 或其他,请查看 [encode/broadcaster](https://github.com/encode/broadcaster)。 /// diff --git a/docs/zh/docs/advanced/wsgi.md b/docs/zh/docs/advanced/wsgi.md index 038b672f8..eb83a09b2 100644 --- a/docs/zh/docs/advanced/wsgi.md +++ b/docs/zh/docs/advanced/wsgi.md @@ -1,12 +1,13 @@ # 包含 WSGI - Flask,Django,其它 { #including-wsgi-flask-django-others } + 您可以挂载 WSGI 应用,正如您在 [子应用 - 挂载](sub-applications.md)、[在代理之后](behind-a-proxy.md) 中所看到的那样。 为此, 您可以使用 `WSGIMiddleware` 来包装你的 WSGI 应用,如:Flask,Django,等等。 ## 使用 `WSGIMiddleware` { #using-wsgimiddleware } -/// info | 信息 +/// note | 注意 需要安装 `a2wsgi`,例如使用 `pip install a2wsgi`。 diff --git a/docs/zh/docs/alternatives.md b/docs/zh/docs/alternatives.md index 08893fca7..20de25cbd 100644 --- a/docs/zh/docs/alternatives.md +++ b/docs/zh/docs/alternatives.md @@ -28,7 +28,7 @@ Django REST framework 作为一个灵活工具箱而创建,用于在底层使 它被包括 Mozilla、Red Hat、Eventbrite 在内的许多公司使用。 -它是最早的“自动 API 文档”的范例之一,这正是启发“寻找” **FastAPI** 的最初想法之一。 +它是最早的**自动 API 文档**的范例之一,这正是启发“寻找” **FastAPI** 的最初想法之一。 /// note | 注意 @@ -58,8 +58,9 @@ Flask 是一个“微框架”,它不包含数据库集成,也没有像 Djan /// tip | 启发 **FastAPI**: -- 成为微框架,便于按需组合所需的工具与组件。 -- 提供简单易用的路由系统。 +成为微框架。让按需组合所需的工具与组件变得容易。 + +提供简单易用的路由系统。 /// @@ -87,7 +88,7 @@ Requests 设计非常简单直观,易于使用,且有合理的默认值。 response = requests.get("http://example.com/some/url") ``` -对应地,FastAPI 的 API 路径操作可能看起来是这样的: +对应地,FastAPI 的 API *路径操作*可能看起来是这样的: ```Python hl_lines="1" @app.get("/some/url") @@ -282,7 +283,7 @@ Flask-apispec 由与 Marshmallow 相同的开发者创建。 Falcon 是另一个高性能 Python 框架,它被设计为精简且可作为 Hug 等其他框架的基础。 -它设计为接收两个参数的函数:一个“request”和一个“response”。然后从 request 中“读取”,向 response 中“写入”。由于这种设计,无法用标准的 Python 类型提示将请求参数和请求体声明为函数形参。 +它设计为接收两个参数的函数:一个“请求”和一个“响应”。然后从请求中“读取”,向响应中“写入”。由于这种设计,无法用标准的 Python 类型提示将请求参数和请求体声明为函数形参。 因此,数据校验、序列化与文档要么需要手写完成,无法自动化;要么需要在 Falcon 之上实现一个框架,例如 Hug。其他受 Falcon 设计启发、采用“一个 request 对象 + 一个 response 对象作为参数”的框架也有同样的区别。 diff --git a/docs/zh/docs/async.md b/docs/zh/docs/async.md index bee98fc8b..8645fd634 100644 --- a/docs/zh/docs/async.md +++ b/docs/zh/docs/async.md @@ -95,11 +95,11 @@ Python 的现代版本支持通过一种叫**“协程”**——使用 `async` ### 并发与汉堡 { #concurrency-and-burgers } -上述异步代码的思想有时也被称为“并发”,它不同于“并行”。 +上述**异步**代码的思想有时也被称为**“并发”**,它不同于**“并行”**。 -并发和并行都与“不同的事情或多或少同时发生”有关。 +**并发**和**并行**都与“不同的事情或多或少同时发生”有关。 -但是并发和并行之间的细节是完全不同的。 +但是*并发*和*并行*之间的细节是完全不同的。 要了解差异,请想象以下关于汉堡的故事: @@ -367,7 +367,7 @@ Starlette(和 **FastAPI**)是基于 [AnyIO](https://anyio.readthedocs.io/en/ 特别是,你可以直接使用 [AnyIO](https://anyio.readthedocs.io/en/stable/) 来处理高级的并发用例,这些用例需要在自己的代码中使用更高级的模式。 -即使你没有使用 **FastAPI**,你也可以使用 [AnyIO](https://anyio.readthedocs.io/en/stable/) 编写自己的异步程序,使其拥有较高的兼容性并获得一些好处(例如,结构化并发)。 +即使你没有使用 FastAPI,你也可以使用 [AnyIO](https://anyio.readthedocs.io/en/stable/) 编写自己的异步程序,使其拥有较高的兼容性并获得一些好处(例如,结构化并发)。 我基于 AnyIO 新建了一个库,作为一个轻量级的封装层,用来优化类型注解,同时提供了更好的**自动补全**、**内联错误提示**等功能。这个库还附带了一个友好的入门指南和教程,能帮助你**理解**并编写**自己的异步代码**:[Asyncer](https://asyncer.tiangolo.com/)。如果你有**结合使用异步代码和常规**(阻塞/同步)代码的需求,这个库会特别有用。 @@ -429,13 +429,13 @@ Starlette(和 **FastAPI**)是基于 [AnyIO](https://anyio.readthedocs.io/en/ 你可以拥有多个相互依赖的依赖以及[子依赖](tutorial/dependencies/sub-dependencies.md)(作为函数的参数),它们中的一些可能是通过 `async def` 声明,也可能是通过 `def` 声明。它们仍然可以正常工作,这些通过 `def` 声明的函数将会在外部线程中调用(来自线程池),而不是“被等待”。 -### 其他函数 { #other-utility-functions } +### 其他工具函数 { #other-utility-functions } -你可直接调用通过 `def` 或 `async def` 创建的任何其他函数,FastAPI 不会影响你调用它们的方式。 +你可直接调用通过 `def` 或 `async def` 创建的任何其他工具函数,FastAPI 不会影响你调用它们的方式。 这与 FastAPI 为你调用*路径操作函数*和依赖项的逻辑相反。 -如果你的函数是通过 `def` 声明的,它将被直接调用(在代码中编写的地方),而不会在线程池中;如果这个函数通过 `async def` 声明,当在代码中调用时,你就应该使用 `await` 等待函数的结果。 +如果你的工具函数是通过 `def` 声明的,它将被直接调用(在代码中编写的地方),而不会在线程池中;如果这个函数通过 `async def` 声明,当在代码中调用时,你就应该使用 `await` 等待函数的结果。 --- diff --git a/docs/zh/docs/deployment/cloud.md b/docs/zh/docs/deployment/cloud.md index 025715f52..d20cc3ce1 100644 --- a/docs/zh/docs/deployment/cloud.md +++ b/docs/zh/docs/deployment/cloud.md @@ -16,7 +16,7 @@ FastAPI Cloud 是 *FastAPI and friends* 开源项目的主要赞助方和资金 ## 云服务商 - 赞助商 { #cloud-providers-sponsors } -还有一些云服务商也会 ✨ [**赞助 FastAPI**](../help-fastapi.md#sponsor-the-author) ✨。🙇 +还有一些云服务商也会 ✨ [**赞助 FastAPI**](https://github.com/sponsors/tiangolo) ✨。🙇 你也可以考虑按照他们的指南尝试他们的服务: diff --git a/docs/zh/docs/deployment/concepts.md b/docs/zh/docs/deployment/concepts.md index dd5ba2ba8..4e7d69b41 100644 --- a/docs/zh/docs/deployment/concepts.md +++ b/docs/zh/docs/deployment/concepts.md @@ -1,6 +1,6 @@ # 部署概念 { #deployments-concepts } -在部署 **FastAPI** 应用程序或任何类型的 Web API 时,有几个概念值得了解,通过掌握这些概念您可以找到**最合适的**方法来**部署您的应用程序**。 +在部署 **FastAPI** 应用程序,或者实际上,任何类型的 Web API 时,有几个你可能会关心的概念,通过掌握这些概念你可以找到**最合适的**方法来**部署你的应用程序**。 一些重要的概念是: @@ -9,23 +9,23 @@ * 重新启动 * 复制(运行的进程数) * 内存 -* 开始前的先前步骤 +* 启动前的先前步骤 我们接下来了解它们将如何影响**部署**。 -我们的最终目标是能够以**安全**的方式**为您的 API 客户端**提供服务,同时要**避免中断**,并且尽可能高效地利用**计算资源**(例如远程服务器/虚拟机)。 🚀 +最终目标是能够以**安全**的方式**为你的 API 客户端**提供服务,同时**避免中断**,并且尽可能高效地利用**计算资源**(例如远程服务器/虚拟机)。 🚀 -我将在这里告诉您更多关于这些**概念**的信息,希望能给您提供**直觉**来决定如何在非常不同的环境中部署 API,甚至在是尚不存在的**未来**的环境里。 +我将在这里告诉你更多关于这些**概念**的信息,希望能给你提供**直觉**来决定如何在非常不同的环境中部署你的 API,甚至是在尚不存在的**未来**环境里。 -通过考虑这些概念,您将能够**评估和设计**部署**您自己的 API**的最佳方式。 +通过考虑这些概念,你将能够**评估和设计**部署**你自己的 API** 的最佳方式。 -在接下来的章节中,我将为您提供更多部署 FastAPI 应用程序的**具体方法**。 +在接下来的章节中,我将为你提供更多部署 FastAPI 应用程序的**具体方案**。 -但现在,让我们仔细看一下这些重要的**概念**。 这些概念也适用于任何其他类型的 Web API。 💡 +但现在,让我们仔细看一下这些重要的**概念性想法**。这些概念也适用于任何其他类型的 Web API。 💡 ## 安全性 - HTTPS { #security-https } -在[上一章有关 HTTPS](https.md) 中,我们了解了 HTTPS 如何为您的 API 提供加密。 +在[上一章有关 HTTPS](https.md) 中,我们了解了 HTTPS 如何为你的 API 提供加密。 我们还看到,HTTPS 通常由应用程序服务器的**外部**组件(**TLS 终止代理**)提供。 @@ -33,7 +33,7 @@ ### HTTPS 示例工具 { #example-tools-for-https } -您可以用作 TLS 终止代理的一些工具包括: +你可以用作 TLS 终止代理的一些工具包括: * Traefik * 自动处理证书更新 ✨ @@ -43,13 +43,13 @@ * 使用 Certbot 等外部组件进行证书更新 * HAProxy * 使用 Certbot 等外部组件进行证书更新 -* 带有 Ingress Controller(如 Nginx) 的 Kubernetes +* 带有 Ingress Controller(如 Nginx)的 Kubernetes * 使用诸如 cert-manager 之类的外部组件来进行证书更新 * 由云服务商内部处理,作为其服务的一部分(请阅读下文👇) -另一种选择是您可以使用**云服务**来完成更多工作,包括设置 HTTPS。 它可能有一些限制或向您收取更多费用等。但在这种情况下,您不必自己设置 TLS 终止代理。 +另一种选择是你可以使用**云服务**来完成更多工作,包括设置 HTTPS。它可能有一些限制或向你收取更多费用等。但在这种情况下,你不必自己设置 TLS 终止代理。 -我将在接下来的章节中向您展示一些具体示例。 +我将在接下来的章节中向你展示一些具体示例。 --- @@ -63,52 +63,52 @@ **程序**这个词通常用来描述很多东西: -* 您编写的 **代码**,**Python 文件**。 -* 操作系统可以**执行**的**文件**,例如:`python`、`python.exe`或`uvicorn`。 -* 在操作系统上**运行**、使用CPU 并将内容存储在内存上的特定程序。 这也被称为**进程**。 +* 你编写的 **代码**,**Python 文件**。 +* 操作系统可以**执行**的**文件**,例如:`python`、`python.exe` 或 `uvicorn`。 +* 在操作系统上**运行**、使用 CPU 并将内容存储在内存上的特定程序。这也被称为**进程**。 ### 什么是进程 { #what-is-a-process } -**进程** 这个词通常以更具体的方式使用,仅指在操作系统中运行的东西(如上面的最后一点): +**进程**这个词通常以更具体的方式使用,仅指在操作系统中运行的东西(如上面的最后一点): * 在操作系统上**运行**的特定程序。 * 这不是指文件,也不是指代码,它**具体**指的是操作系统正在**执行**和管理的东西。 -* 任何程序,任何代码,**只有在执行时才能做事**。 因此,是当有**进程正在运行**时。 -* 该进程可以由您或操作系统**终止**(或“杀死”)。 那时,它停止运行/被执行,并且它可以**不再做事情**。 -* 您计算机上运行的每个应用程序背后都有一些进程,每个正在运行的程序,每个窗口等。并且通常在计算机打开时**同时**运行许多进程。 +* 任何程序,任何代码,**只有在执行时才能做事**。因此,是当有**进程正在运行**时。 +* 该进程可以由你或操作系统**终止**(或“杀死”)。那时,它停止运行/被执行,并且它**不再能做事情**。 +* 你计算机上运行的每个应用程序背后都有一些进程,每个正在运行的程序,每个窗口等。并且通常在计算机打开时**同时**运行许多进程。 * **同一程序**可以有**多个进程**同时运行。 -如果您检查操作系统中的“任务管理器”或“系统监视器”(或类似工具),您将能够看到许多正在运行的进程。 +如果你检查操作系统中的“任务管理器”或“系统监视器”(或类似工具),你将能够看到许多正在运行的进程。 -例如,您可能会看到有多个进程运行同一个浏览器程序(Firefox、Chrome、Edge 等)。 他们通常每个tab运行一个进程,再加上一些其他额外的进程。 +例如,你可能会看到有多个进程运行同一个浏览器程序(Firefox、Chrome、Edge 等)。它们通常每个 tab 运行一个进程,再加上一些其他额外的进程。 --- -现在我们知道了术语“进程”和“程序”之间的区别,让我们继续讨论部署。 +现在我们知道了术语 **进程** 和 **程序** 之间的区别,让我们继续讨论部署。 ## 启动时运行 { #running-on-startup } -在大多数情况下,当您创建 Web API 时,您希望它**始终运行**、不间断,以便您的客户端始终可以访问它。 这是当然的,除非您有特定原因希望它仅在某些情况下运行,但大多数时候您希望它不断运行并且**可用**。 +在大多数情况下,当你创建 Web API 时,你希望它**始终运行**、不间断,以便你的客户端始终可以访问它。当然,除非你有特定原因希望它仅在某些情况下运行,但大多数时候你希望它不断运行并且**可用**。 ### 在远程服务器中 { #in-a-remote-server } -当您设置远程服务器(云服务器、虚拟机等)时,您可以做的最简单的事情就是使用 `fastapi run`(它使用 Uvicorn)或类似方式,手动运行,就像本地开发时一样。 +当你设置远程服务器(云服务器、虚拟机等)时,你可以做的最简单的事情就是使用 `fastapi run`(它使用 Uvicorn)或类似方式,手动运行,就像本地开发时一样。 -它将会在**开发过程中**发挥作用并发挥作用。 +它将会**在开发过程中**发挥作用并且很有用。 -但是,如果您与服务器的连接丢失,**正在运行的进程**可能会终止。 +但是,如果你与服务器的连接丢失,**正在运行的进程**可能会终止。 -如果服务器重新启动(例如更新后或从云提供商迁移后),您可能**不会注意到它**。 因此,您甚至不知道必须手动重新启动该进程。 所以,你的 API 将一直处于挂掉的状态。 😱 +如果服务器重新启动(例如更新后或从云提供商迁移后),你可能**不会注意到它**。因此,你甚至不知道必须手动重新启动该进程。所以,你的 API 将一直处于挂掉的状态。 😱 ### 启动时自动运行 { #run-automatically-on-startup } -一般来说,您可能希望服务器程序(例如 Uvicorn)在服务器启动时自动启动,并且不需要任何**人为干预**,让进程始终与您的 API 一起运行(例如 Uvicorn 运行您的 FastAPI 应用程序) 。 +一般来说,你可能希望服务器程序(例如 Uvicorn)在服务器启动时自动启动,并且不需要任何**人为干预**,让进程始终与你的 API 一起运行(例如 Uvicorn 运行你的 FastAPI 应用程序)。 ### 单独的程序 { #separate-program } -为了实现这一点,您通常会有一个**单独的程序**来确保您的应用程序在启动时运行。 在许多情况下,它还可以确保其他组件或应用程序也运行,例如数据库。 +为了实现这一点,你通常会有一个**单独的程序**来确保你的应用程序在启动时运行。在许多情况下,它还可以确保其他组件或应用程序也运行,例如数据库。 ### 启动时运行的示例工具 { #example-tools-to-run-at-startup } @@ -123,43 +123,43 @@ * 作为其服务的一部分由云提供商内部处理 * 其他的... -我将在接下来的章节中为您提供更具体的示例。 +我将在接下来的章节中为你提供更具体的示例。 ## 重新启动 { #restarts } -与确保应用程序在启动时运行类似,您可能还想确保它在挂掉后**重新启动**。 +与确保应用程序在启动时运行类似,你可能还想确保它在失败后**重新启动**。 ### 我们会犯错误 { #we-make-mistakes } -作为人类,我们总是会犯**错误**。 软件几乎*总是*在不同的地方隐藏着**bug**。 🐛 +作为人类,我们总是会犯**错误**。软件几乎*总是*在不同的地方隐藏着 **bug**。 🐛 -作为开发人员,当我们发现这些bug并实现新功能(也可能添加新bug😅)时,我们会不断改进代码。 +作为开发人员,当我们发现这些 bug 并实现新功能(也可能添加新 bug 😅)时,我们会不断改进代码。 ### 自动处理小错误 { #small-errors-automatically-handled } -使用 FastAPI 构建 Web API 时,如果我们的代码中存在错误,FastAPI 通常会将其包含到触发错误的单个请求中。 🛡 +使用 FastAPI 构建 Web API 时,如果我们的代码中存在错误,FastAPI 通常会将其限制在触发错误的单个请求中。 🛡 对于该请求,客户端将收到 **500 内部服务器错误**,但应用程序将继续处理下一个请求,而不是完全崩溃。 ### 更大的错误 - 崩溃 { #bigger-errors-crashes } -尽管如此,在某些情况下,我们编写的一些代码可能会导致整个应用程序崩溃,从而导致 Uvicorn 和 Python 崩溃。 💥 +尽管如此,在某些情况下,我们编写的一些代码可能会**导致整个应用程序崩溃**,从而导致 Uvicorn 和 Python 崩溃。 💥 -尽管如此,您可能不希望应用程序因为某个地方出现错误而保持死机状态,您可能希望它**继续运行**,至少对于未破坏的*路径操作*。 +尽管如此,你可能不希望应用程序因为某个地方出现错误而保持死机状态,你可能希望它**继续运行**,至少对于未损坏的*路径操作*。 ### 崩溃后重新启动 { #restart-after-crash } -但在那些严重错误导致正在运行的**进程**崩溃的情况下,您需要一个外部组件来负责**重新启动**进程,至少尝试几次... +但在那些严重错误导致正在运行的**进程**崩溃的情况下,你需要一个外部组件来负责**重新启动**进程,至少尝试几次... /// tip | 提示 -...尽管如果整个应用程序只是**立即崩溃**,那么永远重新启动它可能没有意义。 但在这些情况下,您可能会在开发过程中注意到它,或者至少在部署后立即注意到它。 +...尽管如果整个应用程序只是**立即崩溃**,那么永远重新启动它可能没有意义。但在这些情况下,你可能会在开发过程中注意到它,或者至少在部署后立即注意到它。 因此,让我们关注主要情况,在**未来**的某些特定情况下,它可能会完全崩溃,但重新启动它仍然有意义。 /// -您可能希望让这个东西作为 **外部组件** 负责重新启动您的应用程序,因为到那时,使用 Uvicorn 和 Python 的同一应用程序已经崩溃了,因此同一应用程序的相同代码中没有东西可以对此做出什么。 +你可能希望让这个负责重新启动你的应用程序的东西作为一个**外部组件**,因为到那时,使用 Uvicorn 和 Python 的同一应用程序已经崩溃了,因此同一应用程序的相同代码中没有任何东西可以对此做什么。 ### 自动重新启动的示例工具 { #example-tools-to-restart-automatically } @@ -178,19 +178,19 @@ ## 复制 - 进程和内存 { #replication-processes-and-memory } -对于 FastAPI 应用程序,使用像 `fastapi` 命令(运行 Uvicorn)这样的服务器程序,在**一个进程**中运行一次就可以同时为多个客户端提供服务。 +对于 FastAPI 应用程序,使用像运行 Uvicorn 的 `fastapi` 命令这样的服务器程序,在**一个进程**中运行一次就可以同时为多个客户端提供服务。 -但在许多情况下,您会希望同时运行多个工作进程。 +但在许多情况下,你会希望同时运行多个工作进程。 ### 多进程 - Workers { #multiple-processes-workers } -如果您的客户端数量多于单个进程可以处理的数量(例如,如果虚拟机不是太大),并且服务器的 CPU 中有 **多个核心**,那么您可以让 **多个进程** 同时运行同一个应用程序,并在它们之间分发所有请求。 +如果你的客户端数量多于单个进程可以处理的数量(例如,如果虚拟机不是太大),并且服务器的 CPU 中有**多个核心**,那么你可以让**多个进程**同时运行同一个应用程序,并在它们之间分发所有请求。 -当您运行同一 API 程序的**多个进程**时,它们通常称为 **workers**。 +当你运行同一 API 程序的**多个进程**时,它们通常称为 **workers**。 ### 工作进程和端口 { #worker-processes-and-ports } -还记得文档 [关于 HTTPS](https.md) 中只有一个进程可以侦听服务器中的端口和 IP 地址的一种组合吗? +还记得文档[关于 HTTPS](https.md) 中说的,在服务器中只有一个进程可以侦听端口和 IP 地址的一种组合吗? 现在仍然是对的。 @@ -198,124 +198,124 @@ ### 每个进程的内存 { #memory-per-process } -现在,当程序将内容加载到内存中时,例如,将机器学习模型加载到变量中,或者将大文件的内容加载到变量中,所有这些都会消耗服务器的一点内存 (RAM) 。 +现在,当程序将内容加载到内存中时,例如,将机器学习模型加载到变量中,或者将大文件的内容加载到变量中,所有这些都会**消耗服务器的一些内存 (RAM)**。 -多个进程通常**不共享任何内存**。 这意味着每个正在运行的进程都有自己的东西、变量和内存。 如果您的代码消耗了大量内存,**每个进程**将消耗等量的内存。 +多个进程通常**不共享任何内存**。这意味着每个正在运行的进程都有自己的东西、变量和内存。如果你的代码消耗了大量内存,**每个进程**将消耗等量的内存。 ### 服务器内存 { #server-memory } -例如,如果您的代码加载 **1 GB 大小**的机器学习模型,则当您使用 API 运行一个进程时,它将至少消耗 1 GB RAM。 如果您启动 **4 个进程**(4 个工作进程),每个进程将消耗 1 GB RAM。 因此,您的 API 总共将消耗 **4 GB RAM**。 +例如,如果你的代码加载**大小为 1 GB** 的机器学习模型,则当你使用 API 运行一个进程时,它将至少消耗 1 GB RAM。如果你启动 **4 个进程**(4 个工作进程),每个进程将消耗 1 GB RAM。因此,你的 API 总共将消耗 **4 GB RAM**。 -如果您的远程服务器或虚拟机只有 3 GB RAM,尝试加载超过 4 GB RAM 将导致问题。 🚨 +如果你的远程服务器或虚拟机只有 3 GB RAM,尝试加载超过 4 GB RAM 将导致问题。 🚨 ### 多进程 - 一个例子 { #multiple-processes-an-example } 在此示例中,有一个 **Manager Process** 启动并控制两个 **Worker Processes**。 -该管理器进程可能是监听 IP 中的 **端口** 的进程。 它将所有通信传输到工作进程。 +该管理器进程可能是监听 IP 中的**端口**的进程。它将所有通信传输到工作进程。 -这些工作进程将是运行您的应用程序的进程,它们将执行主要计算以接收 **请求** 并返回 **响应**,并且它们将加载您放入 RAM 中的变量中的任何内容。 +这些工作进程将是运行你的应用程序的进程,它们将执行主要计算以接收**请求**并返回**响应**,并且它们将加载你放入 RAM 中的变量中的任何内容。 -当然,除了您的应用程序之外,同一台机器可能还运行**其他进程**。 +当然,除了你的应用程序之外,同一台机器可能还运行**其他进程**。 一个有趣的细节是,随着时间的推移,每个进程使用的 **CPU 百分比**可能会发生很大变化,但**内存 (RAM)** 通常会或多或少保持**稳定**。 -如果您有一个每次执行相当数量的计算的 API,并且您有很多客户端,那么 **CPU 利用率** 可能也会保持稳定(而不是不断快速上升和下降)。 +如果你有一个每次执行相当数量的计算的 API,并且你有很多客户端,那么 **CPU 利用率** 可能*也会保持稳定*(而不是不断快速上升和下降)。 ### 复制工具和策略示例 { #examples-of-replication-tools-and-strategies } -可以通过多种方法来实现这一目标,我将在接下来的章节中向您详细介绍具体策略,例如在谈论 Docker 和容器时。 +可以通过多种方法来实现这一目标,我将在接下来的章节中向你详细介绍具体策略,例如在谈论 Docker 和容器时。 -要考虑的主要限制是必须有一个**单个**组件来处理**公共IP**中的**端口**。 然后它必须有一种方法将通信**传输**到复制的**进程/worker**。 +要考虑的主要限制是必须有一个**单个**组件来处理**公共 IP** 中的**端口**。然后它必须有一种方法将通信**传输**到复制的**进程/worker**。 以下是一些可能的组合和策略: * 带有 `--workers` 的 **Uvicorn** - * 一个 Uvicorn **进程管理器** 将监听 **IP** 和 **端口**,并且它将启动 **多个 Uvicorn 工作进程**。 -* **Kubernetes** 和其他分布式 **容器系统** - * **Kubernetes** 层中的某些东西将侦听 **IP** 和 **端口**。 复制将通过拥有**多个容器**,每个容器运行**一个 Uvicorn 进程**。 -* **云服务** 为您处理此问题 - * 云服务可能**为您处理复制**。 它可能会让您定义 **要运行的进程**,或要使用的 **容器映像**,在任何情况下,它很可能是 **单个 Uvicorn 进程**,并且云服务将负责复制它。 + * 一个 Uvicorn **进程管理器**将监听 **IP** 和**端口**,并且它将启动**多个 Uvicorn 工作进程**。 +* **Kubernetes** 和其他分布式**容器系统** + * **Kubernetes** 层中的某些东西将侦听 **IP** 和**端口**。复制将通过拥有**多个容器**来完成,每个容器运行**一个 Uvicorn 进程**。 +* **云服务** 为你处理此问题 + * 云服务可能**为你处理复制**。它可能会让你定义**要运行的进程**,或要使用的**容器镜像**,在任何情况下,它很可能是**单个 Uvicorn 进程**,并且云服务将负责复制它。 /// tip | 提示 -如果这些关于 **容器**、Docker 或 Kubernetes 的内容还没有多大意义,请不要担心。 +如果这些关于**容器**、Docker 或 Kubernetes 的内容还没有多大意义,请不要担心。 -我将在以后的章节中向您详细介绍容器镜像、Docker、Kubernetes 等:[容器中的 FastAPI - Docker](docker.md)。 +我将在以后的章节中向你详细介绍容器镜像、Docker、Kubernetes 等:[容器中的 FastAPI - Docker](docker.md)。 /// ## 启动之前的步骤 { #previous-steps-before-starting } -在很多情况下,您希望在**启动**应用程序之前执行一些步骤。 +在很多情况下,你希望在**启动**应用程序之前执行一些步骤。 -例如,您可能想要运行**数据库迁移**。 +例如,你可能想要运行**数据库迁移**。 -但在大多数情况下,您只想执行这些步骤**一次**。 +但在大多数情况下,你只想执行这些步骤**一次**。 -因此,在启动应用程序之前,您将需要一个**单个进程**来执行这些**前面的步骤**。 +因此,在启动应用程序之前,你将需要一个**单个进程**来执行这些**前面的步骤**。 -而且您必须确保它是运行前面步骤的单个进程, *即使*之后您为应用程序本身启动**多个进程**(多个worker)。 如果这些步骤由**多个进程**运行,它们会通过在**并行**运行来**重复**工作,并且如果这些步骤像数据库迁移一样需要小心处理,它们可能会导致每个进程和其他进程发生冲突。 +而且你必须确保它是运行前面步骤的单个进程,*即使*之后你为应用程序本身启动**多个进程**(多个 worker)。如果这些步骤由**多个进程**运行,它们会通过**并行**运行来**重复**工作,并且如果这些步骤像数据库迁移一样需要小心处理,它们可能会导致彼此之间发生冲突。 当然,也有一些情况,多次运行前面的步骤也没有问题,这样的话就好办多了。 /// tip | 提示 -另外,请记住,根据您的设置,在某些情况下,您在开始应用程序之前**可能甚至不需要任何先前的步骤**。 +另外,请记住,根据你的设置,在某些情况下,你在启动应用程序之前**可能甚至不需要任何先前的步骤**。 -在这种情况下,您就不必担心这些。 🤷 +在这种情况下,你就不必担心这些。 🤷 /// ### 前面步骤策略的示例 { #examples-of-previous-steps-strategies } -这将在**很大程度上取决于您部署系统的方式**,并且可能与您启动程序、处理重启等的方式有关。 +这将在**很大程度上取决于你部署系统的方式**,并且可能与你启动程序、处理重启等的方式有关。 以下是一些可能的想法: * Kubernetes 中的“Init Container”在应用程序容器之前运行 -* 一个 bash 脚本,运行前面的步骤,然后启动您的应用程序 - * 您仍然需要一种方法来启动/重新启动 bash 脚本、检测错误等。 +* 一个 bash 脚本,运行前面的步骤,然后启动你的应用程序 + * 你仍然需要一种方法来启动/重新启动*那个* bash 脚本、检测错误等。 /// tip | 提示 -我将在以后的章节中为您提供使用容器执行此操作的更具体示例:[容器中的 FastAPI - Docker](docker.md)。 +我将在以后的章节中为你提供使用容器执行此操作的更具体示例:[容器中的 FastAPI - Docker](docker.md)。 /// ## 资源利用率 { #resource-utilization } -您的服务器是一个**资源**,您可以通过您的程序消耗或**利用**CPU 上的计算时间以及可用的 RAM 内存。 +你的服务器是一个**资源**,你可以通过你的程序消耗或**利用** CPU 上的计算时间以及可用的 RAM 内存。 -您想要消耗/利用多少系统资源? 您可能很容易认为“不多”,但实际上,您可能希望在不崩溃的情况下**尽可能多地消耗**。 +你想要消耗/利用多少系统资源?你可能很容易认为“不多”,但实际上,你可能希望在不崩溃的情况下**尽可能多地消耗**。 -如果您支付了 3 台服务器的费用,但只使用了它们的一点点 RAM 和 CPU,那么您可能**浪费金钱** 💸,并且可能 **浪费服务器电力** 🌎,等等。 +如果你支付了 3 台服务器的费用,但只使用了它们的一点点 RAM 和 CPU,那么你可能**浪费金钱** 💸,并且可能**浪费服务器电力** 🌎,等等。 在这种情况下,最好只拥有 2 台服务器并使用更高比例的资源(CPU、内存、磁盘、网络带宽等)。 -另一方面,如果您有 2 台服务器,并且正在使用 **100% 的 CPU 和 RAM**,则在某些时候,一个进程会要求更多内存,并且服务器将不得不使用磁盘作为“内存” (这可能会慢数千倍),甚至**崩溃**。 或者一个进程可能需要执行一些计算,并且必须等到 CPU 再次空闲。 +另一方面,如果你有 2 台服务器,并且正在使用**它们 100% 的 CPU 和 RAM**,则在某些时候,一个进程会要求更多内存,并且服务器将不得不使用磁盘作为“内存”(这可能会慢数千倍),甚至**崩溃**。或者一个进程可能需要执行一些计算,并且必须等到 CPU 再次空闲。 在这种情况下,最好购买**一台额外的服务器**并在其上运行一些进程,以便它们都有**足够的 RAM 和 CPU 时间**。 -由于某种原因,您的 API 的使用量也有可能出现**激增**。 也许它像病毒一样传播开来,或者也许其他一些服务或机器人开始使用它。 在这些情况下,您可能需要额外的资源来保证安全。 +由于某种原因,你的 API 的使用量也有可能出现**激增**。也许它像病毒一样传播开来,或者也许其他一些服务或机器人开始使用它。在这些情况下,你可能需要额外的资源来保证安全。 -您可以将一个**任意数字**设置为目标,例如,资源利用率**在 50% 到 90%** 之间。 重点是,这些可能是您想要衡量和用来调整部署的主要内容。 +你可以将一个**任意数字**设置为目标,例如,资源利用率**在 50% 到 90%** 之间。重点是,这些可能是你想要衡量和用来调整部署的主要内容。 -您可以使用“htop”等简单工具来查看服务器中使用的 CPU 和 RAM 或每个进程使用的数量。 或者您可以使用更复杂的监控工具,这些工具可能分布在服务器等上。 +你可以使用 `htop` 等简单工具来查看服务器中使用的 CPU 和 RAM 或每个进程使用的数量。或者你可以使用更复杂的监控工具,这些工具可能分布在服务器等上。 ## 回顾 { #recap } -您在这里阅读了一些在决定如何部署应用程序时可能需要牢记的主要概念: +你在这里阅读了一些在决定如何部署应用程序时可能需要牢记的主要概念: * 安全性 - HTTPS * 启动时运行 * 重新启动 * 复制(运行的进程数) * 内存 -* 开始前的先前步骤 +* 启动前的先前步骤 -了解这些想法以及如何应用它们应该会给您足够的直觉在配置和调整部署时做出任何决定。 🤓 +了解这些想法以及如何应用它们应该会给你足够的直觉,以便在配置和调整部署时做出任何决定。 🤓 -在接下来的部分中,我将为您提供更具体的示例,说明您可以遵循的可能策略。 🚀 +在接下来的部分中,我将为你提供更具体的示例,说明你可以遵循的可能策略。 🚀 diff --git a/docs/zh/docs/deployment/docker.md b/docs/zh/docs/deployment/docker.md index aa7b60b50..5e3919bd2 100644 --- a/docs/zh/docs/deployment/docker.md +++ b/docs/zh/docs/deployment/docker.md @@ -1,5 +1,6 @@ # 容器中的 FastAPI - Docker { #fastapi-in-containers-docker } + 部署 FastAPI 应用时,常见做法是构建一个**Linux 容器镜像**。通常使用 [**Docker**](https://www.docker.com/) 实现。然后你可以用几种方式之一部署该镜像。 使用 Linux 容器有多种优势,包括**安全性**、**可复制性**、**简单性**等。 @@ -132,7 +133,7 @@ Successfully installed fastapi pydantic -/// info | 信息 +/// note | 注意 还有其他格式和工具可以定义并安装包依赖。 @@ -556,7 +557,7 @@ CMD ["fastapi", "run", "app/main.py", "--port", "80", "--workers", "4"] 如果你有**多个容器**,可能每个容器运行一个**单独进程**(例如在 **Kubernetes** 集群中),那么你可能希望使用一个**单独的容器**来执行**前置步骤**,在一个容器中运行一个进程,**在**启动那些复制的 worker 容器**之前**完成。 -/// info | 信息 +/// note | 注意 如果你使用 Kubernetes,这通常会是一个 [Init Container](https://kubernetes.io/docs/concepts/workloads/pods/init-containers/)。 diff --git a/docs/zh/docs/deployment/fastapicloud.md b/docs/zh/docs/deployment/fastapicloud.md index d43870993..9140e30c0 100644 --- a/docs/zh/docs/deployment/fastapicloud.md +++ b/docs/zh/docs/deployment/fastapicloud.md @@ -1,26 +1,6 @@ # FastAPI Cloud { #fastapi-cloud } -你可以用**一条命令**将你的 FastAPI 应用部署到 [FastAPI Cloud](https://fastapicloud.com),如果还没有,去加入候补名单吧。🚀 - -## 登录 { #login } - -请确保你已有 **FastAPI Cloud** 账号(我们已从候补名单向你发出邀请 😉)。 - -然后登录: - -
- -```console -$ fastapi login - -You are logged in to FastAPI Cloud 🚀 -``` - -
- -## 部署 { #deploy } - -现在用**一条命令**部署你的应用: +你可以用**一条命令**将你的 FastAPI 应用部署到 [FastAPI Cloud](https://fastapicloud.com)。🚀
@@ -36,6 +16,8 @@ Deploying to FastAPI Cloud...
+CLI 会自动检测你的 FastAPI 应用并将其部署到云端。如果你尚未登录,浏览器会自动打开以完成认证流程。 + 就这样!现在你可以通过该 URL 访问你的应用。✨ ## 关于 FastAPI Cloud { #about-fastapi-cloud } diff --git a/docs/zh/docs/deployment/https.md b/docs/zh/docs/deployment/https.md index 916fb46da..090c4ba59 100644 --- a/docs/zh/docs/deployment/https.md +++ b/docs/zh/docs/deployment/https.md @@ -67,7 +67,7 @@ 你可能拥有一个云服务器(虚拟机)或类似的东西,并且它会有一个固定 **公共IP地址**。 -在 DNS 服务器中,你可以配置一条记录(“A 记录”)以将 **你的域名** 指向你服务器的公共 **IP 地址**。 +在 DNS 服务器中,你可以配置一条记录(一个 `A record`)以将 **你的域名** 指向你服务器的公共 **IP 地址**。 这个操作一般只需要在最开始执行一次。 @@ -179,7 +179,7 @@ TLS 终止代理将使用协商好的加密算法**解密请求**,并将**( 因此,要更新证书,更新程序需要向权威机构(Let's Encrypt)**证明**它确实**“拥有”并控制该域名**。 -有多种方法可以做到这一点。 一些流行的方式是: +有多种方法可以做到这一点,并适应不同的应用需求。 一些流行的方式是: * **修改一些DNS记录**。 * 为此,续订程序需要支持 DNS 提供商的 API,因此,要看你使用的 DNS 提供商是否提供这一功能。 @@ -188,8 +188,7 @@ TLS 终止代理将使用协商好的加密算法**解密请求**,并将**( * 这就是当同一个 TLS 终止代理还负责证书续订过程时它非常有用的原因之一。 * 否则,你可能需要暂时停止 TLS 终止代理,启动续订程序以获取证书,然后使用 TLS 终止代理配置它们,然后重新启动 TLS 终止代理。 这并不理想,因为你的应用程序在 TLS 终止代理关闭期间将不可用。 -通过拥有一个**单独的系统来使用 TLS 终止代理来处理 HTTPS**, 而不是直接将 TLS 证书与应用程序服务器一起使用 (例如 Uvicorn),你可以在 -更新证书的过程中同时保持提供服务。 +在仍然为应用提供服务的同时完成整个更新流程,是你想要用 TLS 终止代理拥有一个**单独系统来处理 HTTPS**,而不是直接在应用服务器(例如 Uvicorn)上使用 TLS 证书的主要原因之一。 ## 代理转发请求头 { #proxy-forwarded-headers } @@ -209,7 +208,7 @@ TLS 终止代理将使用协商好的加密算法**解密请求**,并将**( 不过,由于**应用服务器**并不知道自己位于受信任的**代理**之后,默认情况下,它不会信任这些请求头。 -但你可以配置**应用服务器**去信任由**代理**发送的这些“转发”请求头。如果你在使用 FastAPI CLI,可以使用命令行选项 `--forwarded-allow-ips` 指定它应该信任哪些 IP 发来的这些“转发”请求头。 +但你可以配置**应用服务器**去信任由**代理**发送的这些*转发*请求头。如果你在使用 FastAPI CLI,可以使用 *CLI 选项* `--forwarded-allow-ips` 指定它应该信任哪些 IP 发来的这些*转发*请求头。 例如,如果**应用服务器**只接收来自受信任**代理**的通信,你可以设置 `--forwarded-allow-ips="*"`,让它信任所有传入的 IP,因为它只会接收来自**代理**所使用 IP 的请求。 diff --git a/docs/zh/docs/deployment/manually.md b/docs/zh/docs/deployment/manually.md index c440aa924..ee468f4e4 100644 --- a/docs/zh/docs/deployment/manually.md +++ b/docs/zh/docs/deployment/manually.md @@ -2,7 +2,7 @@ ## 使用 `fastapi run` 命令 { #use-the-fastapi-run-command } -简而言之,使用 `fastapi run` 来运行您的 FastAPI 应用程序: +简而言之,使用 `fastapi run` 来运行你的 FastAPI 应用程序:
@@ -40,7 +40,7 @@ $ fastapi run fastapi run ASGI。FastAPI 本质上是一个 ASGI Web 框架。 -要在远程服务器上运行 **FastAPI** 应用(或任何其他 ASGI 应用),您需要一个 ASGI 服务器程序,例如 **Uvicorn**。它是 `fastapi` 命令默认使用的 ASGI 服务器。 +要在远程服务器上运行 **FastAPI** 应用(或任何其他 ASGI 应用),你需要一个 ASGI 服务器程序,例如 **Uvicorn**。它是 `fastapi` 命令默认使用的 ASGI 服务器。 除此之外,还有其他一些可选的 ASGI 服务器,例如: @@ -56,7 +56,6 @@ FastAPI 使用了一种用于构建 Python Web 框架和服务器的标准,称 * [Hypercorn](https://hypercorn.readthedocs.io/): 与 HTTP/2 和 Trio 等兼容的 ASGI 服务器。 * [Daphne](https://github.com/django/daphne): 为 Django Channels 构建的 ASGI 服务器。 * [Granian](https://github.com/emmett-framework/granian): 基于 Rust 的 HTTP 服务器,专为 Python 应用设计。 -* [NGINX Unit](https://unit.nginx.org/howto/fastapi/): NGINX Unit 是一个轻量级且灵活的 Web 应用运行时环境。 ## 服务器主机和服务器程序 { #server-machine-and-server-program } @@ -64,17 +63,17 @@ FastAPI 使用了一种用于构建 Python Web 框架和服务器的标准,称 “**服务器**”一词通常用于指远程/云计算机(物理机或虚拟机)以及在该计算机上运行的程序(例如 Uvicorn)。 -请记住,当您一般读到“服务器”这个名词时,它可能指的是这两者之一。 +请记住,当你一般读到“服务器”这个名词时,它可能指的是这两者之一。 -当提到远程主机时,通常将其称为**服务器**,但也称为**机器**(machine)、**VM**(虚拟机)、**节点**。 这些都是指某种类型的远程计算机,通常运行 Linux,您可以在其中运行程序。 +当提到远程主机时,通常将其称为**服务器**,但也称为**机器**(machine)、**VM**(虚拟机)、**节点**。 这些都是指某种类型的远程计算机,通常运行 Linux,你可以在其中运行程序。 ## 安装服务器程序 { #install-the-server-program } -当您安装 FastAPI 时,它自带一个生产环境服务器——Uvicorn,并且您可以使用 `fastapi run` 命令来启动它。 +当你安装 FastAPI 时,它自带一个生产环境服务器——Uvicorn,并且你可以使用 `fastapi run` 命令来启动它。 -不过,您也可以手动安装 ASGI 服务器。 +不过,你也可以手动安装 ASGI 服务器。 -请确保您创建并激活一个[虚拟环境](../virtual-environments.md),然后再安装服务器应用程序。 +请确保你创建并激活一个[虚拟环境](../virtual-environments.md),然后再安装服务器应用程序。 例如,要安装 Uvicorn,可以运行以下命令: @@ -96,13 +95,13 @@ $ pip install "uvicorn[standard]" 其中包括 `uvloop`,这是 `asyncio` 的高性能替代方案,能够显著提升并发性能。 -当您使用 `pip install "fastapi[standard]"` 安装 FastAPI 时,实际上也会安装 `uvicorn[standard]`。 +当你使用 `pip install "fastapi[standard]"` 安装 FastAPI 时,实际上也会安装 `uvicorn[standard]`。 /// ## 运行服务器程序 { #run-the-server-program } -如果您手动安装了 ASGI 服务器,通常需要以特定格式传递一个导入字符串,以便服务器能够正确导入您的 FastAPI 应用: +如果你手动安装了 ASGI 服务器,通常需要以特定格式传递一个导入字符串,以便服务器能够正确导入你的 FastAPI 应用:
@@ -129,7 +128,7 @@ from main import app /// -每种 ASGI 服务器程序通常都会有类似的命令,您可以在它们的官方文档中找到更多信息。 +每种 ASGI 服务器程序通常都会有类似的命令,你可以在它们的官方文档中找到更多信息。 /// warning | 警告 @@ -145,7 +144,7 @@ Uvicorn 和其他服务器支持 `--reload` 选项,该选项在开发过程中 这些示例运行服务器程序(例如 Uvicorn),启动**单个进程**,在所有 IP(`0.0.0.0`)上监听预定义端口(例如`80`)。 -这是基本思路。 但您可能需要处理一些其他事情,例如: +这是基本思路。 但你可能需要处理一些其他事情,例如: * 安全性 - HTTPS * 启动时运行 @@ -154,4 +153,4 @@ Uvicorn 和其他服务器支持 `--reload` 选项,该选项在开发过程中 * 内存 * 开始前的步骤 -在接下来的章节中,我将向您详细介绍每个概念、如何思考它们,以及一些具体示例以及处理它们的策略。 🚀 +在接下来的章节中,我将向你详细介绍每个概念、如何思考它们,以及一些具体示例以及处理它们的策略。 🚀 diff --git a/docs/zh/docs/deployment/server-workers.md b/docs/zh/docs/deployment/server-workers.md index add83ac1a..e20d9ef95 100644 --- a/docs/zh/docs/deployment/server-workers.md +++ b/docs/zh/docs/deployment/server-workers.md @@ -17,7 +17,7 @@ 在本章节中,我将向您展示如何使用 `fastapi` 命令或直接使用 `uvicorn` 命令以**多工作进程模式**运行 **Uvicorn**。 -/// info | 信息 +/// note | 注意 如果您正在使用容器,例如 Docker 或 Kubernetes,我将在下一章中告诉您更多相关信息:[容器中的 FastAPI - Docker](docker.md)。 diff --git a/docs/zh/docs/editor-support.md b/docs/zh/docs/editor-support.md index 5028c6c95..7caff801e 100644 --- a/docs/zh/docs/editor-support.md +++ b/docs/zh/docs/editor-support.md @@ -14,7 +14,7 @@ ## 功能 { #features } -- **Path Operation 资源管理器** - 侧边栏树状视图展示应用中的所有 *路径操作*。点击可跳转至任一路由或 APIRouter 的定义。 +- **Path Operation 资源管理器** - 侧边栏树状视图展示应用中的所有 *路径操作*。点击可跳转至任一路由或 router 的定义。 - **路由搜索** - 使用 Ctrl + Shift + E(macOS 上为 Cmd + Shift + E)按路径、方法或名称进行搜索。 - **CodeLens 导航** - 测试客户端调用(例如 `client.get('/items')`)上方的可点击链接,可跳转到匹配的*路径操作*,在测试与实现之间快速往返。 - **部署到 FastAPI Cloud** - 一键将你的应用部署到 [FastAPI Cloud](https://fastapicloud.com/)。 diff --git a/docs/zh/docs/environment-variables.md b/docs/zh/docs/environment-variables.md index 3a90ecde6..be6869e44 100644 --- a/docs/zh/docs/environment-variables.md +++ b/docs/zh/docs/environment-variables.md @@ -1,5 +1,6 @@ # 环境变量 { #environment-variables } + /// tip | 提示 如果你已经知道什么是“环境变量”并且知道如何使用它们,你可以放心跳过这一部分。 diff --git a/docs/zh/docs/features.md b/docs/zh/docs/features.md index 5fd9d48c4..1405bee46 100644 --- a/docs/zh/docs/features.md +++ b/docs/zh/docs/features.md @@ -19,11 +19,11 @@ ![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-03-swagger-02.png) -* 另外的 API 文档:[**ReDoc**](https://github.com/Rebilly/ReDoc) +* 另外的 API 文档:[**ReDoc**](https://github.com/Rebilly/ReDoc)。 ![ReDoc](https://fastapi.tiangolo.com/img/index/index-06-redoc-02.png) -### 更主流的 Python { #just-modern-python } +### 就是现代 Python { #just-modern-python } 全部都基于标准的 **Python 类型** 声明(感谢 Pydantic)。没有新的语法需要学习。只需要标准的现代 Python。 @@ -98,7 +98,7 @@ my_second_user: User = User(**second_user_data) ### 简洁 { #short } -任何类型都有合理的**默认值**,任何和地方都有可选配置。所有的参数被微调,来满足你的需求,定义成你需要的 API。 +任何类型都有合理的**默认值**,任何地方都有可选配置。所有的参数被微调,来满足你的需求,定义成你需要的 API。 但是默认情况下,一切都能**“顺利工作”**。 @@ -110,7 +110,7 @@ my_second_user: User = User(**second_user_data) * 字符串 (`str`) 字段,定义最小或最大长度。 * 数字 (`int`, `float`) 有最大值和最小值,等等。 -* 校验外来类型,比如: +* 校验更特殊的类型,比如: * URL。 * Email。 * UUID。 @@ -120,9 +120,9 @@ my_second_user: User = User(**second_user_data) ### 安全性及身份验证 { #security-and-authentication } -集成了安全性和身份认证。杜绝数据库或者数据模型的渗透风险。 +集成了安全性和身份验证。不需要在数据库或数据模型上作出任何妥协。 -OpenAPI 中定义的安全模式,包括: +OpenAPI 中定义的所有安全模式,包括: * HTTP 基本认证。 * **OAuth2**(也使用 **JWT tokens**)。在 [使用 JWT 的 OAuth2](tutorial/security/oauth2-jwt.md) 查看教程。 @@ -131,7 +131,7 @@ OpenAPI 中定义的安全模式,包括: * 查询参数。 * Cookies,等等。 -加上来自 Starlette(包括 **session cookie**)的所有安全特性。 +加上来自 Starlette(包括 **session cookies**)的所有安全特性。 所有的这些都是可复用的工具和组件,可以轻松与你的系统,数据仓库,关系型以及 NoSQL 数据库等等集成。 @@ -142,7 +142,7 @@ FastAPI 有一个使用非常简单,但是非常强大的测试覆盖。 -* 代码库100% 类型注释。 +* 代码库100% 类型标注。 * 用于生产应用。 ## Starlette 特性 { #starlette-features } -**FastAPI** 和 [**Starlette**](https://www.starlette.dev/) 完全兼容(并基于)。所以,你有的其他的 Starlette 代码也能正常工作。`FastAPI` 实际上是 `Starlette` 的一个子类。所以,如果你已经知道或者使用 Starlette,大部分的功能会以相同的方式工作。 +**FastAPI** 与 [**Starlette**](https://www.starlette.dev/) 完全兼容(并基于它构建)。所以,你有的其他的 Starlette 代码也能正常工作。 + +`FastAPI` 实际上是 `Starlette` 的一个子类。所以,如果你已经知道或者使用 Starlette,大部分的功能会以相同的方式工作。 通过 **FastAPI** 你可以获得所有 **Starlette** 的特性(FastAPI 就像加强版的 Starlette): @@ -172,11 +174,11 @@ FastAPI 有一个使用非常简单,但是非常强大的IDE/linter/brain** 适配: * 因为 pydantic 数据结构仅仅是你定义的类的实例;自动补全,linting,mypy 以及你的直觉应该可以和你验证的数据一起正常工作。 * 验证**复杂结构**: diff --git a/docs/zh/docs/help-fastapi.md b/docs/zh/docs/help-fastapi.md index 2ff9752eb..1692d07ec 100644 --- a/docs/zh/docs/help-fastapi.md +++ b/docs/zh/docs/help-fastapi.md @@ -26,7 +26,7 @@ 你可以在 GitHub 上为 FastAPI 点亮「星标」(点击右上角的星形按钮):[https://github.com/fastapi/fastapi](https://github.com/fastapi/fastapi)。⭐️ -加星后,其他用户更容易发现它,并看到它已经对许多人有帮助。 +加星后,其他用户更容易发现它,并看到它已经对其他人有帮助。 ## 关注 GitHub 资源库的版本发布 { #watch-the-github-repository-for-releases } @@ -34,7 +34,7 @@ 在那里你可以选择「Releases only」。 -这样做之后,每当 **FastAPI** 发布新版本(包含修复和新功能),你都会收到通知(邮件)。 +这样做之后,每当 **FastAPI** 发布包含 Bug 修复和新功能的新版本时,你都会收到通知(邮件)。 ## 关注作者 { #follow-the-author } diff --git a/docs/zh/docs/how-to/configure-swagger-ui.md b/docs/zh/docs/how-to/configure-swagger-ui.md index 3dbc54911..d1909488a 100644 --- a/docs/zh/docs/how-to/configure-swagger-ui.md +++ b/docs/zh/docs/how-to/configure-swagger-ui.md @@ -16,11 +16,11 @@ FastAPI会将这些配置转换为 **JSON**,使其与 JavaScript 兼容,因 -但是你可以通过设置 `syntaxHighlight` 为 `False` 来禁用 Swagger UI 中的语法高亮: +但是你可以通过设置 `syntaxHighlight` 为 `False` 来禁用它: {* ../../docs_src/configure_swagger_ui/tutorial001_py310.py hl[3] *} -...在此之后,Swagger UI 将不会高亮代码: +...在此之后,Swagger UI 将不再显示语法高亮: @@ -30,7 +30,7 @@ FastAPI会将这些配置转换为 **JSON**,使其与 JavaScript 兼容,因 {* ../../docs_src/configure_swagger_ui/tutorial002_py310.py hl[3] *} -这个配置会改变语法高亮主题: +这个配置会改变语法高亮颜色主题: diff --git a/docs/zh/docs/how-to/custom-request-and-route.md b/docs/zh/docs/how-to/custom-request-and-route.md index 79860a562..4065818ea 100644 --- a/docs/zh/docs/how-to/custom-request-and-route.md +++ b/docs/zh/docs/how-to/custom-request-and-route.md @@ -72,7 +72,7 @@ 由 `GzipRequest.get_route_handler` 返回的函数唯一不同之处是把 `Request` 转换为 `GzipRequest`。 -这样,在传给我们的路径操作之前,`GzipRequest` 会(在需要时)负责解压数据。 +这样,在传给我们的*路径操作*之前,`GzipRequest` 会(在需要时)负责解压数据。 之后,其余处理逻辑完全相同。 @@ -104,6 +104,6 @@ {* ../../docs_src/custom_request_and_route/tutorial003_py310.py hl[26] *} -在此示例中,`router` 下的路径操作将使用自定义的 `TimedRoute` 类,响应中会多一个 `X-Response-Time` 头,包含生成响应所用的时间: +在此示例中,`router` 下的*路径操作*将使用自定义的 `TimedRoute` 类,响应中会多一个 `X-Response-Time` 头,包含生成响应所用的时间: {* ../../docs_src/custom_request_and_route/tutorial003_py310.py hl[13:20] *} diff --git a/docs/zh/docs/how-to/extending-openapi.md b/docs/zh/docs/how-to/extending-openapi.md index fd39e439f..9b8d1c07e 100644 --- a/docs/zh/docs/how-to/extending-openapi.md +++ b/docs/zh/docs/how-to/extending-openapi.md @@ -25,9 +25,17 @@ - `openapi_version`:使用的 OpenAPI 规范版本。默认是最新的 `3.1.0`。 - `summary`:API 的简短摘要。 - `description`:API 的描述,可包含 Markdown,并会展示在文档中。 -- `routes`:路由列表,即已注册的每个路径操作。来自 `app.routes`。 +- `routes`:应用的路由,来自 `app.routes`。FastAPI 使用它们来收集已注册的路径操作,包括来自已包含路由器的那些。 -/// info | 信息 +/// tip | 技术细节 + +`app.routes` 是一个更底层的路由树。它可能包含 FastAPI 在内部用于包含的路由器的候选路由,而不仅仅是最终的 `APIRoute` 对象。 + +你仍然可以把 `app.routes` 传给 `get_openapi()`。FastAPI 会遍历这棵路由树来收集实际生效的路径操作。 + +/// + +/// note | 注意 参数 `summary` 仅在 OpenAPI 3.1.0 及更高版本中可用,FastAPI 0.99.0 及以上版本支持。 @@ -61,7 +69,7 @@ 你可以把 `.openapi_schema` 属性当作“缓存”,用来存储已生成的架构。 -这样一来,用户每次打开 API 文档时,应用就不必重新生成架构。 +这样一来,应用每次打开 API 文档时就不必重新生成架构。 它只会生成一次,后续请求都会使用同一份缓存的架构。 diff --git a/docs/zh/docs/how-to/graphql.md b/docs/zh/docs/how-to/graphql.md index b33d6759f..31d15d3b4 100644 --- a/docs/zh/docs/how-to/graphql.md +++ b/docs/zh/docs/how-to/graphql.md @@ -2,7 +2,7 @@ 由于 **FastAPI** 基于 **ASGI** 标准,因此很容易集成任何也兼容 ASGI 的 **GraphQL** 库。 -你可以在同一个应用中将常规的 FastAPI 路径操作与 GraphQL 结合使用。 +你可以在同一个应用中将常规的 FastAPI *路径操作* 与 GraphQL 结合使用。 /// tip | 提示 diff --git a/docs/zh/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md b/docs/zh/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md index 3723eb032..ecfdd0278 100644 --- a/docs/zh/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md +++ b/docs/zh/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md @@ -8,9 +8,11 @@ FastAPI 0.119.0 引入了在 Pydantic v2 内部以 `pydantic.v1` 形式对 Pydan FastAPI 0.126.0 移除了对 Pydantic v1 的支持,但在一段时间内仍支持 `pydantic.v1`。 +FastAPI 0.128.0 也移除了对 `pydantic.v1` 的支持,因此最新版本的 FastAPI 需要 Pydantic v2。 + /// warning | 警告 -从 Python 3.14 开始,Pydantic 团队不再为最新的 Python 版本提供 Pydantic v1 的支持。 +从 **Python 3.14** 开始,Pydantic 团队不再为最新的 Python 版本提供 Pydantic v1 的支持。 这也包括 `pydantic.v1`,在 Python 3.14 及更高版本中不再受支持。 @@ -18,7 +20,7 @@ FastAPI 0.126.0 移除了对 Pydantic v1 的支持,但在一段时间内仍支 /// -如果你的旧 FastAPI 应用在用 Pydantic v1,这里将向你展示如何迁移到 Pydantic v2,以及 FastAPI 0.119.0 中可帮助你渐进式迁移的功能。 +如果你的旧 FastAPI 应用在用 Pydantic v1,这里将向你展示如何迁移到 Pydantic v2,以及 **FastAPI 0.119.0 中的功能** 可帮助你渐进式迁移。 ## 官方指南 { #official-guide } @@ -54,6 +56,16 @@ Pydantic v2 以子模块 `pydantic.v1` 的形式包含了 Pydantic v1 的全部 ### FastAPI 对 v2 中 Pydantic v1 的支持 { #fastapi-support-for-pydantic-v1-in-v2 } +/// warning | 警告 + +此 FastAPI 对 `pydantic.v1` 模型的支持是在 **FastAPI 0.119.0** 中添加的,并在 **FastAPI 0.128.0** 中移除。它原本是为了迁移到 Pydantic v2 而提供的临时辅助。 + +在当前版本的 FastAPI 中,在你的应用里使用 `pydantic.v1` 模型会引发错误。 + +本节其余部分描述的临时支持仅在那些较旧版本中可用。 + +/// + 自 FastAPI 0.119.0 起,FastAPI 也对 Pydantic v2 内的 Pydantic v1 提供了部分支持,以便迁移到 v2。 因此,你可以将 Pydantic 升级到最新的 v2,并将导入改为使用 `pydantic.v1` 子模块,在很多情况下就能直接工作。 @@ -122,6 +134,12 @@ graph TB ### 分步迁移 { #migrate-in-steps } +/// warning | 警告 + +下面描述的在同一应用中同时使用 Pydantic v1 和 v2 模型进行渐进式迁移,只适用于 **FastAPI 0.119.0 到 0.127.x**。它已在 **FastAPI 0.128.0** 中移除,最新版本需要 **Pydantic v2** 模型。 + +/// + /// tip | 提示 优先尝试 `bump-pydantic`,如果测试通过且可行,那么你就用一个命令完成了。✨ diff --git a/docs/zh/docs/how-to/separate-openapi-schemas.md b/docs/zh/docs/how-to/separate-openapi-schemas.md index c3efe5f1a..a7335143a 100644 --- a/docs/zh/docs/how-to/separate-openapi-schemas.md +++ b/docs/zh/docs/how-to/separate-openapi-schemas.md @@ -1,5 +1,6 @@ # 是否为输入和输出分别生成 OpenAPI JSON Schema { #separate-openapi-schemas-for-input-and-output-or-not } + 自从发布了 **Pydantic v2**,生成的 OpenAPI 比之前更精确、更**正确**了。😎 事实上,在某些情况下,对于同一个 Pydantic 模型,OpenAPI 中会根据是否带有**默认值**,为输入和输出分别生成**两个 JSON Schema**。 @@ -85,7 +86,7 @@ 这种情况下,你可以在 **FastAPI** 中通过参数 `separate_input_output_schemas=False` 禁用该特性。 -/// info | 信息 +/// note | 注意 对 `separate_input_output_schemas` 的支持是在 FastAPI `0.102.0` 中添加的。🤓 diff --git a/docs/zh/docs/index.md b/docs/zh/docs/index.md index f89d0a653..6b75291fe 100644 --- a/docs/zh/docs/index.md +++ b/docs/zh/docs/index.md @@ -106,19 +106,19 @@ FastAPI 是一个用于构建 API 的现代、快速(高性能)的 Web 框
“我最近大量使用 FastAPI。我实际上计划把它用于我团队在 微软的机器学习(ML)服务。其中一些正在集成进核心 Windows 产品以及一些 Office 产品。”
-
— Kabir Khan,Microsoft (ref)
+
— Kabir Khan,Microsoft (参考)
@@ -127,25 +127,25 @@ FastAPI 是一个用于构建 API 的现代、快速(高性能)的 Web 框 「_[...] 我最近大量使用 **FastAPI**。[...] 我实际上计划把它用于我团队在 **微软的机器学习(ML)服务**。其中一些正在集成进核心 **Windows** 产品以及一些 **Office** 产品。_」 -
Kabir Khan - Microsoft (ref)
+
Kabir Khan - Microsoft (参考)
--- 「_我们采用 **FastAPI** 库来启动一个可查询以获取**预测结果**的 **REST** 服务器。[用于 Ludwig]_」 -
Piero Molino,Yaroslav Dudin,Sai Sumanth Miryala - Uber (ref)
+
Piero Molino,Yaroslav Dudin,Sai Sumanth Miryala - Uber (参考)
--- 「_**Netflix** 很高兴宣布开源我们的**危机管理**编排框架:**Dispatch**![使用 **FastAPI** 构建]_」 -
Kevin Glisson,Marc Vilanova,Forest Monsen - Netflix (ref)
+
Kevin Glisson,Marc Vilanova,Forest Monsen - Netflix (参考)
--- 「_如果有人正在构建生产级的 Python API,我强烈推荐 **FastAPI**。它**设计优雅**、**使用简单**且**高度可扩展**,它已经成为我们 API 优先开发战略中的**关键组件**,并驱动了许多自动化和服务,比如我们的 Virtual TAC Engineer。_」 -
Deon Pillsbury - Cisco (ref)
+
Deon Pillsbury - Cisco (参考)
--- @@ -192,7 +192,7 @@ $ pip install "fastapi[standard]"
-**Note**: 请确保把 `"fastapi[standard]"` 用引号包起来,以保证在所有终端中都能正常工作。 +**注意**: 请确保把 `"fastapi[standard]"` 用引号包起来,以保证在所有终端中都能正常工作。 ## 示例 { #example } @@ -237,7 +237,7 @@ async def read_item(item_id: int, q: str | None = None): return {"item_id": item_id, "q": q} ``` -**Note**: +**注意**: 如果你不确定,请查看文档中 _"In a hurry?"_ 章节的 [`async` 和 `await`](https://fastapi.tiangolo.com/zh/async/#in-a-hurry) 部分。 @@ -400,7 +400,7 @@ item_id: int item: Item ``` -……通过一次声明,你将获得: +...通过一次声明,你将获得: * 编辑器支持,包括: * 自动补全。 @@ -421,7 +421,7 @@ item: Item * `datetime` 对象。 * `UUID` 对象。 * 数据库模型。 - * ……以及更多。 + * ...以及更多。 * 自动生成的交互式 API 文档,包括两种可选的用户界面: * Swagger UI。 * ReDoc。 @@ -457,19 +457,19 @@ item: Item return {"item_name": item.name, "item_id": item_id} ``` -……从: +...从: ```Python ... "item_name": item.name ... ``` -……改为: +...改为: ```Python ... "item_price": item.price ... ``` -……看看你的编辑器如何自动补全属性并知道它们的类型: +...看看你的编辑器如何自动补全属性并知道它们的类型: ![editor support](https://fastapi.tiangolo.com/img/vscode-completion.png) @@ -488,13 +488,11 @@ item: Item * 基于 HTTPX 和 `pytest` 的极其简单的测试 * **CORS** * **Cookie Sessions** - * ……以及更多。 + * ...以及更多。 ### 部署你的应用(可选) { #deploy-your-app-optional } -你可以选择把 FastAPI 应用部署到 [FastAPI Cloud](https://fastapicloud.com),如果还没有的话去加入候补名单吧。🚀 - -如果你已经有 **FastAPI Cloud** 账号(我们从候补名单邀请了你 😉),你可以用一个命令部署你的应用。 +你可以选择用一条命令将 FastAPI 应用部署到 [FastAPI Cloud](https://fastapicloud.com)。🚀
@@ -510,6 +508,8 @@ Deploying to FastAPI Cloud...
+CLI 会自动检测你的 FastAPI 应用并将其部署到云端。如果你尚未登录,浏览器会打开以完成认证流程。 + 就这样!现在你可以通过该 URL 访问你的应用了。✨ #### 关于 FastAPI Cloud { #about-fastapi-cloud } diff --git a/docs/zh/docs/project-generation.md b/docs/zh/docs/project-generation.md index 8cc50c096..371eb7319 100644 --- a/docs/zh/docs/project-generation.md +++ b/docs/zh/docs/project-generation.md @@ -1,5 +1,6 @@ # FastAPI全栈模板 { #full-stack-fastapi-template } + 模板通常带有特定的设置,但它们被设计为灵活且可定制。这样你可以根据项目需求进行修改和调整,使其成为很好的起点。🏁 你可以使用此模板开始,它已经为你完成了大量的初始设置、安全性、数据库以及一些 API 端点。 diff --git a/docs/zh/docs/python-types.md b/docs/zh/docs/python-types.md index 7901f9702..4d2c2749a 100644 --- a/docs/zh/docs/python-types.md +++ b/docs/zh/docs/python-types.md @@ -2,11 +2,11 @@ Python 支持可选的“类型提示”(也叫“类型注解”)。 -这些“类型提示”或注解是一种特殊语法,用来声明变量的类型。 +这些 **“类型提示”** 或注解是一种特殊语法,用来声明变量的类型。 通过为变量声明类型,编辑器和工具可以为你提供更好的支持。 -这只是一个关于 Python 类型提示的快速入门/复习。它只涵盖与 **FastAPI** 一起使用所需的最少部分...实际上非常少。 +这只是一个关于 Python 类型提示的**快速入门/复习**。它只涵盖与 **FastAPI** 一起使用所需的最少部分...实际上非常少。 **FastAPI** 完全基于这些类型提示构建,它们带来了许多优势和好处。 @@ -44,7 +44,7 @@ John Doe 但现在想象你要从零开始写它。 -在某个时刻你开始定义函数,并且准备好了参数…… +在某个时刻你开始定义函数,并且准备好了参数... 接下来你需要调用“那个把首字母变大写的方法”。 @@ -62,7 +62,7 @@ John Doe 我们来改前一个版本的一行代码。 -把函数参数从: +我们会把这个片段,也就是函数参数,从: ```Python first_name, last_name @@ -151,7 +151,7 @@ def some_function(data: Any): 有些类型可以在方括号中接收“类型参数”(type parameters),用于声明其内部值的类型。比如“字符串列表”可以写为 `list[str]`。 -这些能接收类型参数的类型称为“泛型类型”(Generic types)或“泛型”(Generics)。 +这些能接收类型参数的类型称为**泛型类型**(Generic types)或**泛型**(Generics)。 你可以把相同的内建类型作为泛型使用(带方括号和内部类型): @@ -221,7 +221,7 @@ def some_function(data: Any): #### Union { #union } -你可以声明一个变量可以是若干种类型中的任意一种,比如既可以是 `int` 也可以是 `str`。 +你可以声明一个变量可以是**若干种类型**中的任意一种,比如既可以是 `int` 也可以是 `str`。 定义时使用竖线(`|`)把两种类型分开。 @@ -263,9 +263,9 @@ def some_function(data: Any): -注意,这表示“`one_person` 是类 `Person` 的一个实例(instance)”。 +注意,这表示“`one_person` 是类 `Person` 的一个**实例**(instance)”。 -它并不表示“`one_person` 是名为 `Person` 的类本身(class)”。 +它并不表示“`one_person` 是名为 `Person` 的**类**(class)”。 ## Pydantic 模型 { #pydantic-models } @@ -285,7 +285,7 @@ def some_function(data: Any): /// note | 注意 -想了解更多关于 [Pydantic](https://docs.pydantic.dev/) 的信息,请查看其文档。 +要了解更多关于 [Pydantic 的信息,请查看其文档](https://docs.pydantic.dev/)。 /// @@ -295,7 +295,7 @@ def some_function(data: Any): ## 带元数据注解的类型提示 { #type-hints-with-metadata-annotations } -Python 还提供了一个特性,可以使用 `Annotated` 在这些类型提示中放入额外的元数据。 +Python 还提供了一个特性,可以使用 `Annotated` 在这些类型提示中放入**额外的元数据**。 你可以从 `typing` 导入 `Annotated`。 @@ -305,15 +305,15 @@ Python 本身不会对这个 `Annotated` 做任何处理。对于编辑器和其 但你可以在 `Annotated` 中为 **FastAPI** 提供额外的元数据,来描述你希望应用如何行为。 -重要的是要记住:传给 `Annotated` 的第一个类型参数才是实际类型。其余的只是给其他工具用的元数据。 +重要的是要记住:传给 `Annotated` 的**第一个*类型参数***才是**实际类型**。其余的只是给其他工具用的元数据。 现在你只需要知道 `Annotated` 的存在,并且它是标准 Python。😎 -稍后你会看到它有多么强大。 +稍后你会看到它有多么**强大**。 /// tip | 提示 -这是标准 Python,这意味着你仍然可以在编辑器里获得尽可能好的开发体验,并能和你用来分析、重构代码的工具良好协作等。✨ +这是**标准 Python**,这意味着你仍然可以在编辑器里获得**尽可能好的开发体验**,并能和你用来分析、重构代码的工具良好协作等。✨ 同时你的代码也能与许多其他 Python 工具和库高度兼容。🚀 @@ -325,16 +325,16 @@ Python 本身不会对这个 `Annotated` 做任何处理。对于编辑器和其 在 **FastAPI** 中,用类型提示来声明参数,你将获得: -* 编辑器支持。 -* 类型检查。 +* **编辑器支持**。 +* **类型检查**。 -……并且 **FastAPI** 会使用相同的声明来: +...并且 **FastAPI** 会使用相同的声明来: -* 定义要求:从请求路径参数、查询参数、请求头、请求体、依赖等。 -* 转换数据:把请求中的数据转换为所需类型。 -* 校验数据:对于每个请求: - * 当数据无效时,自动生成错误信息返回给客户端。 -* 使用 OpenAPI 记录 API: +* **定义要求**:从请求路径参数、查询参数、请求头、请求体、依赖等。 +* **转换数据**:把请求中的数据转换为所需类型。 +* **校验数据**:对于每个请求: + * 当数据无效时,自动生成返回给客户端的**错误**。 +* 使用 OpenAPI **记录** API: * 然后用于自动生成交互式文档界面。 这些听起来可能有点抽象。别担心。你会在[教程 - 用户指南](tutorial/index.md)中看到所有这些的实际效果。 @@ -343,6 +343,6 @@ Python 本身不会对这个 `Annotated` 做任何处理。对于编辑器和其 /// note | 注意 -如果你已经读完所有教程,又回来想进一步了解类型,一个不错的资源是 [`mypy` 的“速查表”](https://mypy.readthedocs.io/en/latest/cheat_sheet_py3.html)。 +如果你已经读完整个教程,又回来想进一步了解类型,一个不错的资源是 [`mypy` 的“速查表”](https://mypy.readthedocs.io/en/latest/cheat_sheet_py3.html)。 /// diff --git a/docs/zh/docs/tutorial/bigger-applications.md b/docs/zh/docs/tutorial/bigger-applications.md index cbee84f35..9bb4bea99 100644 --- a/docs/zh/docs/tutorial/bigger-applications.md +++ b/docs/zh/docs/tutorial/bigger-applications.md @@ -17,16 +17,16 @@ ``` . ├── app -│   ├── __init__.py -│   ├── main.py -│   ├── dependencies.py -│   └── routers -│   │ ├── __init__.py -│   │ ├── items.py -│   │ └── users.py -│   └── internal -│   ├── __init__.py -│   └── admin.py +│ ├── __init__.py +│ ├── main.py +│ ├── dependencies.py +│ └── routers +│ │ ├── __init__.py +│ │ ├── items.py +│ │ └── users.py +│ └── internal +│ ├── __init__.py +│ └── admin.py ``` /// tip | 提示 @@ -396,9 +396,9 @@ from .routers.users import router /// note | 技术细节 -实际上,它将在内部为声明在 `APIRouter` 中的每个*路径操作*创建一个*路径操作*。 +当在主应用中包含路由器时,FastAPI 会保留原始的 `APIRouter` 及其 `APIRoute` 处于活动状态。 -所以,在幕后,它实际上会像所有的东西都是同一个应用程序一样工作。 +这意味着自定义的 `APIRouter` 和 `APIRoute` 子类在被包含之后仍然能够参与工作。 /// @@ -406,7 +406,7 @@ from .routers.users import router 包含路由器时,你不必担心性能问题。 -这将花费几微秒时间,并且只会在启动时发生。 +这被设计为轻量级的,并且避免给每个请求增加开销。 因此,它不会影响性能。⚡ @@ -457,11 +457,11 @@ from .routers.users import router --- -`APIRouter` 没有被「挂载」,它们与应用程序的其余部分没有隔离。 +`APIRouter` 并不是「挂载」的,它们并没有和应用程序的其余部分隔离。 -这是因为我们想要在 OpenAPI 模式和用户界面中包含它们的*路径操作*。 +这是因为我们希望在 OpenAPI 模式和用户界面中包含它们的*路径操作*。 -由于我们不能仅仅隔离它们并独立于其余部分来「挂载」它们,因此*路径操作*是被「克隆的」(重新创建),而不是直接包含。 +FastAPI 会保留原始的路由器和路径操作处于活动状态,并在处理请求和生成 OpenAPI 时组合路由器的前缀、依赖项、标签、响应以及其他元数据。 /// @@ -532,4 +532,16 @@ $ fastapi dev router.include_router(other_router) ``` -请确保在你将 `router` 包含到 `FastAPI` 应用程序之前进行此操作,以便 `other_router` 中的*路径操作*也能被包含进来。 +你可以在将 `router` 包含到 `FastAPI` 应用之前或之后执行此操作。FastAPI 仍然会在路由和 OpenAPI 中包含 `other_router` 中的*路径操作*。 + +同样适用于之后添加到这些路由器的*路径操作*。它们也会通过先前的包含可见。 + +/// warning | 技术细节 + +在包含路由器之后,避免直接修改 `router.routes`。FastAPI 将路由器的包含视为「实时」的,因此原始路由器及其路由会继续参与路由和 OpenAPI 生成。 + +使用文档化的 API(例如路径操作装饰器和 `.include_router()`)来添加路由和路由器。 + +将 `router.routes` 视为较低层级的路由树,它可以包含路由定义和被包含的路由器;避免把它当作最终路径操作的扁平列表来依赖。 + +/// diff --git a/docs/zh/docs/tutorial/body-multiple-params.md b/docs/zh/docs/tutorial/body-multiple-params.md index 39b84904f..8cb465764 100644 --- a/docs/zh/docs/tutorial/body-multiple-params.md +++ b/docs/zh/docs/tutorial/body-multiple-params.md @@ -108,7 +108,7 @@ q: str | None = None {* ../../docs_src/body_multiple_params/tutorial004_an_py310.py hl[28] *} -/// info | 信息 +/// note | 注意 `Body` 同样具有与 `Query`、`Path` 以及其他后面将看到的类完全相同的额外校验和元数据参数。 @@ -123,7 +123,7 @@ q: str | None = None 但是,如果你希望它期望一个拥有 `item` 键并在值中包含模型内容的 JSON,就像在声明额外的请求体参数时所做的那样,则可以使用一个特殊的 `Body` 参数 `embed`: ```Python -item: Item = Body(embed=True) +item: Annotated[Item, Body(embed=True)] ``` 比如: diff --git a/docs/zh/docs/tutorial/body-nested-models.md b/docs/zh/docs/tutorial/body-nested-models.md index 93a34da55..ce10b74a9 100644 --- a/docs/zh/docs/tutorial/body-nested-models.md +++ b/docs/zh/docs/tutorial/body-nested-models.md @@ -135,9 +135,9 @@ Pydantic 模型的每个属性都具有类型。 } ``` -/// info | 信息 +/// note | 注意 -请注意 `images` 键现在具有一组 image 对象是如何发生的。 +请注意 `images` 键现在具有一个 image 对象列表是如何发生的。 /// @@ -147,9 +147,9 @@ Pydantic 模型的每个属性都具有类型。 {* ../../docs_src/body_nested_models/tutorial007_py310.py hl[7,12,18,21,25] *} -/// info | 信息 +/// note | 注意 -请注意 `Offer` 拥有一组 `Item` 而反过来 `Item` 又是一个可选的 `Image` 列表是如何发生的。 +请注意 `Offer` 拥有一个 `Item` 列表,而反过来 `Item` 又有一个可选的 `Image` 列表是如何发生的。 /// diff --git a/docs/zh/docs/tutorial/body.md b/docs/zh/docs/tutorial/body.md index 0a4c9c5e5..b32a5ac60 100644 --- a/docs/zh/docs/tutorial/body.md +++ b/docs/zh/docs/tutorial/body.md @@ -8,7 +8,7 @@ 使用 [Pydantic](https://docs.pydantic.dev/) 模型来声明**请求体**,能充分利用它的功能和优点。 -/// info | 信息 +/// note | 注意 发送数据应使用以下之一:`POST`(最常见)、`PUT`、`DELETE` 或 `PATCH`。 @@ -20,21 +20,22 @@ ## 导入 Pydantic 的 `BaseModel` { #import-pydantics-basemodel } -从 `pydantic` 中导入 `BaseModel`: +首先,你需要从 `pydantic` 中导入 `BaseModel`: {* ../../docs_src/body/tutorial001_py310.py hl[2] *} ## 创建数据模型 { #create-your-data-model } -把数据模型声明为继承 `BaseModel` 的类。 +然后,把数据模型声明为继承 `BaseModel` 的类。 使用 Python 标准类型声明所有属性: {* ../../docs_src/body/tutorial001_py310.py hl[5:9] *} + 与声明查询参数一样,包含默认值的模型属性是可选的,否则就是必选的。把默认值设为 `None` 可使其变为可选。 -例如,上述模型声明如下 JSON "object"(即 Python `dict`): +例如,上述模型声明如下 JSON "`object`"(即 Python `dict`): ```JSON { @@ -45,7 +46,7 @@ } ``` -...由于 `description` 和 `tax` 是可选的(默认值为 `None`),下面的 JSON "object" 也有效: +...由于 `description` 和 `tax` 是可选的(默认值为 `None`),下面的 JSON "`object`" 也有效: ```JSON { @@ -123,7 +124,7 @@ ## 使用模型 { #use-the-model } -在*路径操作*函数内部直接访问模型对象的所有属性: +在函数内部直接访问模型对象的所有属性: {* ../../docs_src/body/tutorial002_py310.py *} @@ -135,6 +136,7 @@ {* ../../docs_src/body/tutorial003_py310.py hl[15:16] *} + ## 请求体 + 路径 + 查询参数 { #request-body-path-query-parameters } 也可以同时声明**请求体**、**路径**和**查询**参数。 diff --git a/docs/zh/docs/tutorial/cookie-param-models.md b/docs/zh/docs/tutorial/cookie-param-models.md index 8e094c7d3..368fe4762 100644 --- a/docs/zh/docs/tutorial/cookie-param-models.md +++ b/docs/zh/docs/tutorial/cookie-param-models.md @@ -1,8 +1,8 @@ # Cookie 参数模型 { #cookie-parameter-models } -如果您有一组相关的 **cookie**,您可以创建一个 **Pydantic 模型**来声明它们。🍪 +如果你有一组相关的 **cookie**,你可以创建一个 **Pydantic 模型**来声明它们。🍪 -这将允许您在**多个地方**能够**重用模型**,并且可以一次性声明所有参数的验证方式和元数据。😎 +这将允许你在**多个地方**能够**重用模型**,并且可以一次性声明所有参数的验证方式和元数据。😎 /// note | 注意 @@ -22,39 +22,39 @@ {* ../../docs_src/cookie_param_models/tutorial001_an_py310.py hl[9:12,16] *} -**FastAPI** 将从请求中接收到的 **cookie** 中**提取**出**每个字段**的数据,并提供您定义的 Pydantic 模型。 +**FastAPI** 将从请求中接收到的 **cookie** 中**提取**出**每个字段**的数据,并提供你定义的 Pydantic 模型。 ## 查看文档 { #check-the-docs } -您可以在文档 UI 的 `/docs` 中查看定义的 cookie: +你可以在文档 UI 的 `/docs` 中查看定义的 cookie:
-/// info | 信息 +/// note | 注意 请记住,由于**浏览器**以特殊方式**处理 cookie**,并在后台进行操作,因此它们**不会**轻易允许 **JavaScript** 访问这些 cookie。 -如果您访问 `/docs` 的 **API 文档 UI**,您将能够查看您*路径操作*的 cookie **文档**。 +如果你访问 `/docs` 的 **API 文档 UI**,你将能够查看你*路径操作*的 cookie **文档**。 -但是即使您**填写数据**并点击“执行”,由于文档界面使用 **JavaScript**,cookie 将不会被发送。而您会看到一条**错误**消息,就好像您没有输入任何值一样。 +但是即使你**填写数据**并点击“执行”,由于文档界面使用 **JavaScript**,cookie 将不会被发送。而你会看到一条**错误**消息,就好像你没有输入任何值一样。 /// ## 禁止额外的 Cookie { #forbid-extra-cookies } -在某些特殊使用情况下(可能并不常见),您可能希望**限制**您想要接收的 cookie。 +在某些特殊使用情况下(可能并不常见),你可能希望**限制**你想要接收的 cookie。 -您的 API 现在可以控制自己的 cookie 同意。🤪🍪 +你的 API 现在可以控制自己的 cookie 同意。🤪🍪 -您可以使用 Pydantic 的模型配置来禁止( `forbid` )任何额外( `extra` )字段: +你可以使用 Pydantic 的模型配置来禁止( `forbid` )任何额外( `extra` )字段: {* ../../docs_src/cookie_param_models/tutorial002_an_py310.py hl[10] *} 如果客户端尝试发送一些**额外的 cookie**,他们将收到**错误**响应。 -可怜的 cookie 通知条,费尽心思为了获得您的同意,却被API 拒绝了。🍪 +可怜的 cookie 通知条,费尽心思为了获得你的同意,却被API 拒绝了。🍪 例如,如果客户端尝试发送一个值为 `good-list-please` 的 `santa_tracker` cookie,客户端将收到一个**错误**响应,告知他们 `santa_tracker` cookie 是不允许的: @@ -73,4 +73,4 @@ ## 总结 { #summary } -您可以使用 **Pydantic 模型**在 **FastAPI** 中声明 **cookie**。😎 +你可以使用 **Pydantic 模型**在 **FastAPI** 中声明 **cookie**。😎 diff --git a/docs/zh/docs/tutorial/cookie-params.md b/docs/zh/docs/tutorial/cookie-params.md index ab05cd7d2..97bf00c65 100644 --- a/docs/zh/docs/tutorial/cookie-params.md +++ b/docs/zh/docs/tutorial/cookie-params.md @@ -12,7 +12,7 @@ 声明 `Cookie` 参数的方式与声明 `Query` 和 `Path` 参数相同。 -第一个值是默认值,还可以传递所有验证参数或注释参数: +你可以定义默认值,以及所有额外的验证或注解参数: {* ../../docs_src/cookie_params/tutorial001_an_py310.py hl[9] *} @@ -24,13 +24,13 @@ /// -/// info | 信息 +/// note | 注意 必须使用 `Cookie` 声明 cookie 参数,否则该参数会被解释为查询参数。 /// -/// info | 信息 +/// note | 注意 请注意,由于**浏览器会以特殊方式并在幕后处理 cookies**,它们**不会**轻易允许**JavaScript**访问它们。 diff --git a/docs/zh/docs/tutorial/debugging.md b/docs/zh/docs/tutorial/debugging.md index 19e6f8a61..0b1ada2de 100644 --- a/docs/zh/docs/tutorial/debugging.md +++ b/docs/zh/docs/tutorial/debugging.md @@ -42,12 +42,14 @@ $ python myapp.py 那么文件中由 Python 自动创建的内部变量 `__name__`,会将字符串 `"__main__"` 作为值。 -所以,下面这部分代码才会运行: +所以,这一段: ```Python uvicorn.run(app, host="0.0.0.0", port=8000) ``` +会运行。 + --- 如果你是导入这个模块(文件)就不会这样。 @@ -60,15 +62,17 @@ from myapp import app # 其他一些代码 ``` -在这种情况下,`myapp.py` 内部的自动变量不会有值为 `"__main__"` 的变量 `__name__`。 +在这种情况下,`myapp.py` 内部自动创建的变量 `__name__` 不会有值 `"__main__"`。 -所以,下面这一行不会被执行: +所以,这一行: ```Python uvicorn.run(app, host="0.0.0.0", port=8000) ``` -/// info | 信息 +不会被执行。 + +/// note | 注意 更多信息请检查 [Python 官方文档](https://docs.python.org/3/library/__main__.html). @@ -85,7 +89,7 @@ from myapp import app * 进入到「调试」面板。 * 「添加配置...」。 * 选中「Python」 -* 运行「Python:当前文件(集成终端)」选项的调试器。 +* 使用选项 "`Python: Current File (Integrated Terminal)`" 运行调试器。 然后它会使用你的 **FastAPI** 代码开启服务器,停在断点处,等等。 @@ -95,7 +99,7 @@ from myapp import app --- -如果使用 Pycharm,你可以: +如果使用 PyCharm,你可以: * 打开「运行」菜单。 * 选中「调试...」。 diff --git a/docs/zh/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md b/docs/zh/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md index a3b2e6a41..afd3dc982 100644 --- a/docs/zh/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md +++ b/docs/zh/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md @@ -28,7 +28,7 @@ /// -/// info | 信息 +/// note | 注意 本例中,使用的是自定义响应头 `X-Key` 和 `X-Token`。 diff --git a/docs/zh/docs/tutorial/dependencies/dependencies-with-yield.md b/docs/zh/docs/tutorial/dependencies/dependencies-with-yield.md index a365bccf0..85510bbf4 100644 --- a/docs/zh/docs/tutorial/dependencies/dependencies-with-yield.md +++ b/docs/zh/docs/tutorial/dependencies/dependencies-with-yield.md @@ -170,7 +170,7 @@ participant tasks as Background tasks end ``` -/// info | 信息 +/// note | 注意 只会向客户端发送**一次响应**。它可能是某个错误响应,或者是来自 *路径操作* 的响应。 @@ -267,7 +267,8 @@ with open("./somefile.txt") as f: 在 Python 中,你可以通过[创建一个带有 `__enter__()` 和 `__exit__()` 方法的类](https://docs.python.org/3/reference/datamodel.html#context-managers)来创建上下文管理器。 -你也可以在 **FastAPI** 的带有 `yield` 的依赖中,使用依赖函数内部的 `with` 或 `async with` 语句来使用它们: +你也可以在 **FastAPI** 的带有 `yield` 的依赖中通过在依赖函数内部使用 +`with` 或 `async with` 语句来使用它们: {* ../../docs_src/dependencies/tutorial010_py310.py hl[1:9,13] *} diff --git a/docs/zh/docs/tutorial/dependencies/index.md b/docs/zh/docs/tutorial/dependencies/index.md index 939470f40..08a04ad88 100644 --- a/docs/zh/docs/tutorial/dependencies/index.md +++ b/docs/zh/docs/tutorial/dependencies/index.md @@ -51,7 +51,7 @@ 然后它只需返回一个包含这些值的 `dict`。 -/// info | 信息 +/// note | 注意 FastAPI 在 0.95.0 版本中新增了对 `Annotated` 的支持(并开始推荐使用)。 @@ -106,7 +106,7 @@ common_parameters --> read_users 这样,你只需编写一次共享代码,**FastAPI** 会在你的*路径操作*中为你调用它。 -/// check | 检查 +/// tip | 提示 注意,无需创建专门的类并传给 **FastAPI** 去“注册”之类的操作。 @@ -164,7 +164,7 @@ commons: Annotated[dict, Depends(common_parameters)] -## 简单用法 { #simple-usage } +## 簡单用法 { #simple-usage } 观察一下就会发现,只要*路径*和*操作*匹配,就会使用声明的*路径操作函数*。随后,**FastAPI** 会用正确的参数调用该函数,并从请求中提取数据。 diff --git a/docs/zh/docs/tutorial/dependencies/sub-dependencies.md b/docs/zh/docs/tutorial/dependencies/sub-dependencies.md index 1c30b4380..a57271c8e 100644 --- a/docs/zh/docs/tutorial/dependencies/sub-dependencies.md +++ b/docs/zh/docs/tutorial/dependencies/sub-dependencies.md @@ -35,7 +35,7 @@ FastAPI 支持创建含**子依赖项**的依赖项。 {* ../../docs_src/dependencies/tutorial005_an_py310.py hl[23] *} -/// info | 信息 +/// note | 注意 注意,这里在*路径操作函数*中只声明了一个依赖项,即 `query_or_cookie_extractor` 。 diff --git a/docs/zh/docs/tutorial/extra-data-types.md b/docs/zh/docs/tutorial/extra-data-types.md index 76748a7a3..441558285 100644 --- a/docs/zh/docs/tutorial/extra-data-types.md +++ b/docs/zh/docs/tutorial/extra-data-types.md @@ -1,15 +1,15 @@ # 额外数据类型 { #extra-data-types } -到目前为止,您一直在使用常见的数据类型,如: +到目前为止,你一直在使用常见的数据类型,如: * `int` * `float` * `str` * `bool` -但是您也可以使用更复杂的数据类型。 +但是你也可以使用更复杂的数据类型。 -您仍然会拥有现在已经看到的相同的特性: +你仍然会拥有现在已经看到的相同的特性: * 很棒的编辑器支持。 * 传入请求的数据转换。 @@ -49,7 +49,7 @@ * `Decimal`: * 标准的 Python `Decimal`。 * 在请求和响应中被当做 `float` 一样处理。 -* 您可以在这里检查所有有效的 Pydantic 数据类型: [Pydantic data types](https://docs.pydantic.dev/latest/usage/types/types/)。 +* 你可以在这里检查所有有效的 Pydantic 数据类型: [Pydantic data types](https://docs.pydantic.dev/latest/usage/types/types/)。 ## 例子 { #example } diff --git a/docs/zh/docs/tutorial/extra-models.md b/docs/zh/docs/tutorial/extra-models.md index 0ad35cc4f..60f66c5f1 100644 --- a/docs/zh/docs/tutorial/extra-models.md +++ b/docs/zh/docs/tutorial/extra-models.md @@ -1,5 +1,6 @@ # 更多模型 { #extra-models } + 书接上文,多个关联模型这种情况很常见。 特别是用户模型,因为: diff --git a/docs/zh/docs/tutorial/first-steps.md b/docs/zh/docs/tutorial/first-steps.md index 78db1fefc..cadcac3e2 100644 --- a/docs/zh/docs/tutorial/first-steps.md +++ b/docs/zh/docs/tutorial/first-steps.md @@ -1,5 +1,6 @@ # 第一步 { #first-steps } + 最简单的 FastAPI 文件可能像下面这样: {* ../../docs_src/first_steps/tutorial001_py310.py *} @@ -180,7 +181,7 @@ entrypoint = "backend.main:app" from backend.main import app ``` -### `fastapi dev` 带路径 { #fastapi-dev-with-path } +### 带路径或使用 `--entrypoint` CLI 选项的 `fastapi dev` { #fastapi-dev-with-path-or-with-entrypoint-cli-option } 你也可以把文件路径传给 `fastapi dev` 命令,它会尝试推断要使用的 FastAPI 应用对象: @@ -188,29 +189,19 @@ from backend.main import app $ fastapi dev main.py ``` -但这样每次调用 `fastapi` 命令时都需要记得传入正确的路径。 - -另外,其他工具可能无法找到它,例如 [VS Code 扩展](../editor-support.md) 或 [FastAPI Cloud](https://fastapicloud.com),因此推荐在 `pyproject.toml` 中使用 `entrypoint`。 - -### 部署你的应用(可选) { #deploy-your-app-optional } - -你可以选择将 FastAPI 应用部署到 [FastAPI Cloud](https://fastapicloud.com),如果还没有,先去加入候补名单。🚀 - -如果你已经拥有 **FastAPI Cloud** 账户(我们从候补名单邀请了你 😉),你可以用一条命令部署应用。 - -部署前,先确保已登录: - -
+或者,你也可以给 `fastapi dev` 命令传入 `--entrypoint` 选项: ```console -$ fastapi login - -You are logged in to FastAPI Cloud 🚀 +$ fastapi dev --entrypoint main:app ``` -
+但这样每次调用 `fastapi` 命令时都需要记得传入正确的路径/entrypoint。 + +另外,其他工具可能无法找到它,例如 [VS Code 扩展](../editor-support.md) 或 [FastAPI Cloud](https://fastapicloud.com),因此推荐在 `pyproject.toml` 中使用 `entrypoint`。 + +### 部署你的应用(可选) { #deploy-your-app-optional } -然后部署你的应用: +你可以选择用一条命令将 FastAPI 应用部署到 [FastAPI Cloud](https://fastapicloud.com)。🚀
@@ -226,6 +217,8 @@ Deploying to FastAPI Cloud...
+CLI 会自动检测你的 FastAPI 应用并将其部署到云端。如果你尚未登录,浏览器会打开以完成认证流程。 + 就这些!现在你可以通过该 URL 访问你的应用了。✨ ## 分步概括 { #recap-step-by-step } @@ -270,7 +263,7 @@ https://example.com/items/foo /items/foo ``` -/// info +/// note | 注意 「路径」也通常被称为「端点」或「路由」。 @@ -322,7 +315,7 @@ https://example.com/items/foo * 请求路径为 `/` * 使用 get 操作 -/// info | `@decorator` 信息 +/// note | `@decorator` 信息 `@something` 语法在 Python 中被称为「装饰器」。 @@ -349,7 +342,7 @@ https://example.com/items/foo * `@app.patch()` * `@app.trace()` -/// tip +/// tip | 提示 你可以随意使用任何一个操作(HTTP方法)。 @@ -383,7 +376,7 @@ https://example.com/items/foo {* ../../docs_src/first_steps/tutorial003_py310.py hl[7] *} -/// note +/// note | 注意 如果你不知道两者的区别,请查阅 [并发: *赶时间吗?*](../async.md#in-a-hurry)。 diff --git a/docs/zh/docs/tutorial/frontend.md b/docs/zh/docs/tutorial/frontend.md new file mode 100644 index 000000000..8b57bbe60 --- /dev/null +++ b/docs/zh/docs/tutorial/frontend.md @@ -0,0 +1,133 @@ +# 前端 { #frontend } + +你可以使用 `app.frontend()`(或 `router.frontend()`)来提供静态前端应用。 + +这对会生成静态文件的前端工具很有用,例如使用 Vite 的 React、TanStack Router、Astro、Vue、Svelte、Angular、Solid 等。 + +使用这些工具时,通常会有一个构建前端的步骤,命令类似: + +```bash +npm run build +``` + +它会生成一个类似 `./dist/` 的目录,里面包含你的前端文件。 + +你可以使用 `app.frontend()` 按照这些前端框架所需的约定来提供该目录。 + +**FastAPI** 会先检查*路径操作*。只有在没有普通路由匹配时,才会检查前端文件,因此你的 API 不会受到影响。 + +## 提供前端服务 { #serve-a-frontend } + +构建前端之后,例如使用 `npm run build`,将生成的文件放入一个目录,例如 `dist`。 + +你的项目结构可能如下所示: + +```text +. +├── pyproject.toml +├── app +│ ├── __init__.py +│ └── main.py +└── dist + ├── index.html + └── assets + └── app.js +``` + +然后使用 `app.frontend()` 提供服务: + +{* ../../docs_src/frontend/tutorial001_py310.py hl[5] *} + +这样,对 `/assets/app.js` 的请求可以提供 `dist/assets/app.js`。 + +如果你还有一个 **FastAPI** *路径操作*,则*路径操作*优先。 + +## 客户端路由 { #client-side-routing } + +许多前端应用,包括**单页应用**(SPA),都会使用客户端路由。像 `/dashboard/settings` 这样的路径可能并不是一个真实文件,而是由框架负责处理。 + +因此,如果直接访问该 URL(而不是通过应用内导航访问),后端应该从 `index.html` 提供前端应用,这样前端框架就可以处理客户端路由。 + +为此,使用 `fallback="index.html"`: + +{* ../../docs_src/frontend/tutorial002_py310.py hl[5] *} + +**FastAPI** 只会对看起来像浏览器导航的 `GET` 和 `HEAD` 请求使用此 fallback。缺失的 JavaScript、CSS 和图片等文件仍会返回 `404`。 + +对于其他方法的请求,例如 `POST` 或 `PUT`,如果路径只匹配前端 fallback,也会返回 `404`。常规 **FastAPI** *路径操作*仍然比前端路由具有更高优先级。 + +/// tip | 提示 + +默认情况下,`fallback` 的值为 `fallback="auto"`。在大多数情况下,你不需要指定 `fallback`。详情见下文。 + +/// + +这正是许多使用客户端路由的前端应用所需的行为,例如使用 TanStack Router 的 React、Vue、Angular、SvelteKit 或 Solid。 + +## 自定义 404 页面 { #custom-404-page } + +你也可以为缺失的前端路径提供一个静态 `404.html` 页面: + +{* ../../docs_src/frontend/tutorial003_py310.py hl[5] *} + +该响应会保持 `404` 状态码。 + +在这种情况下,**FastAPI** 不会为缺失的前端路径提供 `index.html`,而是返回 `404.html` 文件。 + +/// tip | 提示 + +默认情况下,`fallback` 的值为 `fallback="auto"`。这样,如果找到 `404.html` 文件,它会自动用作 fallback。 + +因此,通常你可以省略 `fallback` 参数。 + +/// + +这对会为每个页面生成静态 HTML 文件的前端工具很有用,例如 Astro。 + +## 自动 Fallback { #fallback-auto } + +默认情况下,`app.frontend()` 使用 `fallback="auto"`。 + +如果前端目录中存在 `404.html` 文件,缺失的前端路径会以状态码 `404` 提供该文件。 + +否则,如果存在 `index.html` 文件,缺失的浏览器导航路径会提供 `index.html`,这正是许多使用客户端路由的前端应用所期望的行为。 + +因此,在大多数情况下,你可以使用 `app.frontend("/", directory="dist")`,而无需指定 `fallback` 参数。 + +{* ../../docs_src/frontend/tutorial001_py310.py hl[5] *} + +## 禁用 Fallback { #disable-fallback } + +如果你不想为缺失的前端路径提供 fallback 文件,请使用 `fallback=None`: + +{* ../../docs_src/frontend/tutorial005_py310.py hl[5] *} + +这样,缺失的前端路径会返回普通的 `404`。 + +## 检查目录 { #check-directory } + +默认情况下,`app.frontend()` 会在应用创建时检查目录是否存在。 + +这有助于尽早发现配置错误。例如,如果前端构建输出目录缺失,**FastAPI** 会在启动时抛出错误。 + +如果你的前端文件会稍后创建,例如在应用对象创建之后由单独的构建步骤创建,请设置 `check_dir=False`: + +{* ../../docs_src/frontend/tutorial006_py310.py hl[5] *} + +使用 `check_dir=False` 时,**FastAPI** 不会在应用创建时检查目录。如果在处理请求时配置的目录仍然缺失,**FastAPI** 会在那时抛出错误。 + +## 与 `APIRouter` 一起使用 { #use-it-with-apirouter } + +你也可以将前端文件添加到一个 `APIRouter`,并使用前缀包含它: + +{* ../../docs_src/frontend/tutorial004_py310.py hl[6,7] *} + +在这个示例中,前端路径会在 `/app` 下提供服务。 + +应用中的任何常规*路径操作*仍会优先,包括其他 router 中的路径操作。 + +## 仅限静态构建输出 { #static-build-output-only } + +`app.frontend()` 提供的是你的前端构建已经生成的文件。 + +它不会运行服务端渲染。它适用于生成静态文件的前端框架,而不适用于需要在服务器上为每个请求进行动态渲染的框架。 diff --git a/docs/zh/docs/tutorial/handling-errors.md b/docs/zh/docs/tutorial/handling-errors.md index f3a23fab0..b77ca7a6c 100644 --- a/docs/zh/docs/tutorial/handling-errors.md +++ b/docs/zh/docs/tutorial/handling-errors.md @@ -6,16 +6,16 @@ 你可能需要告诉客户端: -- 客户端没有执行该操作的权限 -- 客户端没有访问该资源的权限 -- 客户端要访问的项目不存在 -- 等等 +* 客户端没有执行该操作的权限 +* 客户端没有访问该资源的权限 +* 客户端要访问的项目不存在 +* 等等 -遇到这些情况时,通常要返回 **4XX**(400 至 499)**HTTP 状态码**。 +遇到这些情况时,通常要返回 **400** 范围内(400 至 499)的 **HTTP 状态码**。 -这与表示请求成功的 **2XX**(200 至 299)HTTP 状态码类似。那些“200”状态码表示某种程度上的“成功”。 +这与 200 HTTP 状态码(200 至 299)类似。那些“200”状态码表示请求在某种程度上“成功”。 -而 **4XX** 状态码表示客户端发生了错误。 +而 400 范围内的状态码表示客户端发生了错误。 大家都知道**「404 Not Found」**错误,还有调侃这个错误的笑话吧? @@ -237,8 +237,8 @@ from starlette.exceptions import HTTPException as StarletteHTTPException ### 复用 **FastAPI** 的异常处理器 { #reuse-fastapis-exception-handlers } -如果你想在自定义处理后仍复用 **FastAPI** 的默认异常处理器,可以从 `fastapi.exception_handlers` 导入并复用这些默认处理器: +如果你想在使用该异常的同时使用 **FastAPI** 的相同默认异常处理器,可以从 `fastapi.exception_handlers` 导入并复用这些默认处理器: {* ../../docs_src/handling_errors/tutorial006_py310.py hl[2:5,15,21] *} -虽然本例只是用非常夸张的信息打印了错误,但足以说明:你可以先处理异常,然后再复用默认的异常处理器。 +虽然本例只是用非常夸张的信息打印了错误,但足以说明:你可以使用该异常,然后直接复用默认的异常处理器。 diff --git a/docs/zh/docs/tutorial/index.md b/docs/zh/docs/tutorial/index.md index 8d6cbc7a6..fde264d2c 100644 --- a/docs/zh/docs/tutorial/index.md +++ b/docs/zh/docs/tutorial/index.md @@ -1,10 +1,10 @@ # 教程 - 用户指南 { #tutorial-user-guide } -本教程将一步步向您展示如何使用 **FastAPI** 的绝大部分特性。 +本教程将一步步向你展示如何使用 **FastAPI** 的绝大部分特性。 -各个章节的内容循序渐进,但是又围绕着单独的主题,所以您可以直接跳转到某个章节以解决您的特定 API 需求。 +各个章节的内容循序渐进,但是又围绕着单独的主题,所以你可以直接跳转到某个章节以解决你的特定 API 需求。 -本教程同样可以作为将来的参考手册,所以您可以随时回到本教程并查阅您需要的内容。 +本教程同样可以作为将来的参考手册,所以你可以随时回到本教程并查阅你需要的内容。 ## 运行代码 { #run-the-code } @@ -52,7 +52,7 @@ $ fastapi dev -**强烈建议**您在本地编写或复制代码,对其进行编辑并运行。 +**强烈建议**你在本地编写或复制代码,对其进行编辑并运行。 在编辑器中使用 FastAPI 会真正地展现出它的优势:只需要编写很少的代码,所有的类型检查,代码补全等等。 @@ -60,9 +60,9 @@ $ fastapi dev ## 安装 FastAPI { #install-fastapi } -第一个步骤是安装 FastAPI. +第一个步骤是安装 FastAPI。 -请确保您创建并激活一个[虚拟环境](../virtual-environments.md),然后**安装 FastAPI**: +请确保你创建并激活一个[虚拟环境](../virtual-environments.md),然后**安装 FastAPI**:
@@ -76,11 +76,11 @@ $ pip install "fastapi[standard]" /// note | 注意 -当您使用 `pip install "fastapi[standard]"` 安装时,它会附带一些默认的可选标准依赖项,其中包括 `fastapi-cloud-cli`,它可以让您部署到 [FastAPI Cloud](https://fastapicloud.com)。 +当你使用 `pip install "fastapi[standard]"` 安装时,它会附带一些默认的可选标准依赖项,其中包括 `fastapi-cloud-cli`,它可以让你部署到 [FastAPI Cloud](https://fastapicloud.com)。 -如果您不想安装这些可选依赖,可以选择安装 `pip install fastapi`。 +如果你不想安装这些可选依赖,可以选择安装 `pip install fastapi`。 -如果您想安装标准依赖但不包含 `fastapi-cloud-cli`,可以使用 `pip install "fastapi[standard-no-fastapi-cloud-cli]"` 安装。 +如果你想安装标准依赖但不包含 `fastapi-cloud-cli`,可以使用 `pip install "fastapi[standard-no-fastapi-cloud-cli]"` 安装。 /// @@ -92,10 +92,10 @@ FastAPI 提供了一个[VS Code 官方扩展](https://marketplace.visualstudio.c ## 进阶用户指南 { #advanced-user-guide } -在本**教程-用户指南**之后,您可以阅读**进阶用户指南**。 +在本**教程-用户指南**之后,你可以阅读**进阶用户指南**。 **进阶用户指南**以本教程为基础,使用相同的概念,并教授一些额外的特性。 -但是您应该先阅读**教程-用户指南**(即您现在正在阅读的内容)。 +但是你应该先阅读**教程-用户指南**(即你现在正在阅读的内容)。 -教程经过精心设计,使您可以仅通过**教程-用户指南**来开发一个完整的应用程序,然后根据您的需要,使用**进阶用户指南**中的一些其他概念,以不同的方式来扩展它。 +教程经过精心设计,使你可以仅通过**教程-用户指南**来开发一个完整的应用程序,然后根据你的需要,使用**进阶用户指南**中的一些其他概念,以不同的方式来扩展它。 diff --git a/docs/zh/docs/tutorial/metadata.md b/docs/zh/docs/tutorial/metadata.md index b761f0888..6518d096c 100644 --- a/docs/zh/docs/tutorial/metadata.md +++ b/docs/zh/docs/tutorial/metadata.md @@ -1,6 +1,6 @@ # 元数据和文档 URL { #metadata-and-docs-urls } -你可以在 FastAPI 应用程序中自定义多个元数据配置。 +你可以在 **FastAPI** 应用程序中自定义多个元数据配置。 ## API 元数据 { #metadata-for-api } @@ -11,7 +11,7 @@ | `title` | `str` | API 的标题。 | | `summary` | `str` | API 的简短摘要。 自 OpenAPI 3.1.0、FastAPI 0.99.0 起可用。 | | `description` | `str` | API 的简短描述。可以使用 Markdown。 | -| `version` | `string` | API 的版本。这是您自己的应用程序的版本,而不是 OpenAPI 的版本。例如 `2.5.0`。 | +| `version` | `str` | API 的版本。这是你自己的应用程序的版本,而不是 OpenAPI 的版本。例如 `2.5.0`。 | | `terms_of_service` | `str` | API 服务条款的 URL。如果提供,则必须是 URL。 | | `contact` | `dict` | 公开的 API 的联系信息。它可以包含多个字段。
contact 字段
参数类型描述
namestr联系人/组织的识别名称。
urlstr指向联系信息的 URL。必须采用 URL 格式。
emailstr联系人/组织的电子邮件地址。必须采用电子邮件地址的格式。
| | `license_info` | `dict` | 公开的 API 的许可证信息。它可以包含多个字段。
license_info 字段
参数类型描述
namestr必须(如果设置了 license_info)。用于 API 的许可证名称。
identifierstrAPI 的 [SPDX](https://spdx.org/licenses/) 许可证表达式。字段 identifier 与字段 url 互斥。自 OpenAPI 3.1.0、FastAPI 0.99.0 起可用。
urlstr用于 API 的许可证的 URL。必须采用 URL 格式。
| @@ -46,11 +46,11 @@ 每个字典可以包含: -- `name`(必填):一个 `str`,与在你的*路径操作*和 `APIRouter` 的 `tags` 参数中使用的标签名相同。 -- `description`:一个 `str`,该标签的简短描述。可以使用 Markdown,并会显示在文档 UI 中。 -- `externalDocs`:一个 `dict`,描述外部文档,包含: - - `description`:一个 `str`,该外部文档的简短描述。 - - `url`(必填):一个 `str`,该外部文档的 URL。 +* `name`(**必填**):一个 `str`,与在你的*路径操作*和 `APIRouter` 的 `tags` 参数中使用的标签名相同。 +* `description`:一个 `str`,该标签的简短描述。可以使用 Markdown,并会显示在文档 UI 中。 +* `externalDocs`:一个 `dict`,描述外部文档,包含: + * `description`:一个 `str`,该外部文档的简短描述。 + * `url`(**必填**):一个 `str`,该外部文档的 URL。 ### 创建标签元数据 { #create-metadata-for-tags } @@ -74,7 +74,7 @@ {* ../../docs_src/metadata/tutorial004_py310.py hl[21,26] *} -/// info | 信息 +/// note | 注意 阅读更多关于标签的信息[路径操作配置](path-operation-configuration.md#tags)。 @@ -108,12 +108,12 @@ 你可以配置两个文档用户界面,包括: -- **Swagger UI**:服务于 `/docs`。 - - 可以使用参数 `docs_url` 设置它的 URL。 - - 可以通过设置 `docs_url=None` 禁用它。 -- **ReDoc**:服务于 `/redoc`。 - - 可以使用参数 `redoc_url` 设置它的 URL。 - - 可以通过设置 `redoc_url=None` 禁用它。 +* **Swagger UI**:服务于 `/docs`。 + * 可以使用参数 `docs_url` 设置它的 URL。 + * 可以通过设置 `docs_url=None` 禁用它。 +* **ReDoc**:服务于 `/redoc`。 + * 可以使用参数 `redoc_url` 设置它的 URL。 + * 可以通过设置 `redoc_url=None` 禁用它。 例如,设置 Swagger UI 服务于 `/documentation` 并禁用 ReDoc: diff --git a/docs/zh/docs/tutorial/path-operation-configuration.md b/docs/zh/docs/tutorial/path-operation-configuration.md index b9046a13b..f1aae0bc2 100644 --- a/docs/zh/docs/tutorial/path-operation-configuration.md +++ b/docs/zh/docs/tutorial/path-operation-configuration.md @@ -1,5 +1,6 @@ # 路径操作配置 { #path-operation-configuration } + *路径操作装饰器*支持多种配置参数。 /// warning | 警告 @@ -56,7 +57,7 @@ OpenAPI 概图会自动添加标签,供 API 文档接口使用: ## 从 docstring 获取描述 { #description-from-docstring } -描述内容比较长且占用多行时,可以在函数的 docstring 中声明*路径操作*的描述,**FastAPI** 会从中读取。 +描述内容比较长且占用多行时,可以在函数的 文档字符串 中声明*路径操作*的描述,**FastAPI** 会从中读取。 文档字符串支持 [Markdown](https://en.wikipedia.org/wiki/Markdown),能正确解析和显示 Markdown 的内容,但要注意文档字符串的缩进。 @@ -72,13 +73,13 @@ OpenAPI 概图会自动添加标签,供 API 文档接口使用: {* ../../docs_src/path_operation_configuration/tutorial005_py310.py hl[18] *} -/// info | 信息 +/// note | 注意 注意,`response_description` 只用于描述响应,`description` 一般则用于描述*路径操作*。 /// -/// check | 检查 +/// tip | 提示 OpenAPI 规定每个*路径操作*都要有响应描述。 diff --git a/docs/zh/docs/tutorial/path-params-numeric-validations.md b/docs/zh/docs/tutorial/path-params-numeric-validations.md index 26b91c1d7..cb4985119 100644 --- a/docs/zh/docs/tutorial/path-params-numeric-validations.md +++ b/docs/zh/docs/tutorial/path-params-numeric-validations.md @@ -8,7 +8,7 @@ {* ../../docs_src/path_params_numeric_validations/tutorial001_an_py310.py hl[1,3] *} -/// info | 信息 +/// note | 注意 FastAPI 在 0.95.0 版本添加了对 `Annotated` 的支持(并开始推荐使用它)。 @@ -131,7 +131,7 @@ Python 不会对这个 `*` 做任何事,但它会知道之后的所有参数 * `lt`:小于(`l`ess `t`han) * `le`:小于等于(`l`ess than or `e`qual) -/// info | 信息 +/// note | 注意 `Query`、`Path` 以及你后面会看到的其他类,都是一个通用 `Param` 类的子类。 @@ -139,7 +139,7 @@ Python 不会对这个 `*` 做任何事,但它会知道之后的所有参数 /// -/// note | 注意 +/// note | 技术细节 当你从 `fastapi` 导入 `Query`、`Path` 和其他对象时,它们实际上是函数。 diff --git a/docs/zh/docs/tutorial/path-params.md b/docs/zh/docs/tutorial/path-params.md index df9210673..0db71859c 100644 --- a/docs/zh/docs/tutorial/path-params.md +++ b/docs/zh/docs/tutorial/path-params.md @@ -20,7 +20,7 @@ 本例把 `item_id` 的类型声明为 `int`。 -/// check | 检查 +/// tip | 提示 类型声明将为函数提供错误检查、代码补全等编辑器支持。 @@ -34,7 +34,7 @@ {"item_id":3} ``` -/// check | 检查 +/// tip | 提示 注意,函数接收并返回的值是 `3`( `int`),不是 `"3"`(`str`)。 @@ -66,7 +66,7 @@ 值的类型不是 `int` 而是浮点数(`float`)时也会显示同样的错误,比如: [http://127.0.0.1:8000/items/4.2](http://127.0.0.1:8000/items/4.2) -/// check | 检查 +/// tip | 提示 **FastAPI** 使用同样的 Python 类型声明实现了数据校验。 @@ -82,7 +82,7 @@ -/// check | 检查 +/// tip | 提示 还是使用 Python 类型声明,**FastAPI** 提供了(集成 Swagger UI 的)自动交互式文档。 @@ -102,7 +102,7 @@ ## Pydantic { #pydantic } -FastAPI 充分地利用了 [Pydantic](https://docs.pydantic.dev/) 的优势,用它在后台校验数据。众所周知,Pydantic 擅长的就是数据校验。 +所有数据校验都由 [Pydantic](https://docs.pydantic.dev/) 在幕后完成,因此你能从中获得所有好处。而且你可以放心。 同样,`str`、`float`、`bool` 以及很多复合数据类型都可以使用类型声明。 diff --git a/docs/zh/docs/tutorial/query-params-str-validations.md b/docs/zh/docs/tutorial/query-params-str-validations.md index 67a5b4000..0164c27e6 100644 --- a/docs/zh/docs/tutorial/query-params-str-validations.md +++ b/docs/zh/docs/tutorial/query-params-str-validations.md @@ -1,5 +1,6 @@ # 查询参数和字符串校验 { #query-parameters-and-string-validations } + **FastAPI** 允许你为参数声明额外的信息和校验。 让我们以下面的应用为例: @@ -29,7 +30,7 @@ FastAPI 会因为默认值 `= None` 而知道 `q` 的值不是必填的。 {* ../../docs_src/query_params_str_validations/tutorial002_an_py310.py hl[1,3] *} -/// info | 信息 +/// note | 注意 FastAPI 在 0.95.0 版本中添加了对 `Annotated` 的支持(并开始推荐使用)。 @@ -381,7 +382,7 @@ Pydantic 还有 [`BeforeValidator`](https://docs.pydantic.dev/latest/concepts/va {* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py hl[5,16:19,24] *} -/// info | 信息 +/// note | 注意 这在 Pydantic 2 或更高版本中可用。😎 diff --git a/docs/zh/docs/tutorial/query-params.md b/docs/zh/docs/tutorial/query-params.md index 9d6c05fbb..971dbb0ed 100644 --- a/docs/zh/docs/tutorial/query-params.md +++ b/docs/zh/docs/tutorial/query-params.md @@ -1,5 +1,6 @@ # 查询参数 { #query-parameters } + 声明的参数不是路径参数时,路径操作函数会把该参数自动解释为“查询”参数。 {* ../../docs_src/query_params/tutorial001_py310.py hl[9] *} @@ -65,7 +66,7 @@ http://127.0.0.1:8000/items/?skip=20 本例中,查询参数 `q` 是可选的,默认值为 `None`。 -/// check | 检查 +/// tip | 提示 注意,**FastAPI** 可以识别出 `item_id` 是路径参数,`q` 不是路径参数,而是查询参数。 diff --git a/docs/zh/docs/tutorial/request-files.md b/docs/zh/docs/tutorial/request-files.md index 6569e1715..38c089ff3 100644 --- a/docs/zh/docs/tutorial/request-files.md +++ b/docs/zh/docs/tutorial/request-files.md @@ -2,7 +2,7 @@ 你可以使用 `File` 定义由客户端上传的文件。 -/// info | 信息 +/// note | 注意 要接收上传的文件,请先安装 [`python-multipart`](https://github.com/Kludex/python-multipart)。 @@ -28,7 +28,7 @@ $ pip install python-multipart {* ../../docs_src/request_files/tutorial001_an_py310.py hl[9] *} -/// info | 信息 +/// note | 注意 `File` 是直接继承自 `Form` 的类。 @@ -147,7 +147,7 @@ HTML 表单(`
`)向服务器发送数据的方式通常会对数 ## 多文件上传 { #multiple-file-uploads } -FastAPI 支持同时上传多个文件。 +可以同时上传多个文件。 它们会被关联到同一个通过「表单数据」发送的「表单字段」。 diff --git a/docs/zh/docs/tutorial/request-form-models.md b/docs/zh/docs/tutorial/request-form-models.md index ec52710a8..bbe805ef8 100644 --- a/docs/zh/docs/tutorial/request-form-models.md +++ b/docs/zh/docs/tutorial/request-form-models.md @@ -2,7 +2,7 @@ 你可以在 FastAPI 中使用 **Pydantic 模型**声明**表单字段**。 -/// info | 信息 +/// note | 注意 要使用表单,首先安装 [`python-multipart`](https://github.com/Kludex/python-multipart)。 diff --git a/docs/zh/docs/tutorial/request-forms-and-files.md b/docs/zh/docs/tutorial/request-forms-and-files.md index 8e092af0a..d97239136 100644 --- a/docs/zh/docs/tutorial/request-forms-and-files.md +++ b/docs/zh/docs/tutorial/request-forms-and-files.md @@ -2,7 +2,7 @@ FastAPI 支持同时使用 `File` 和 `Form` 定义文件和表单字段。 -/// info | 信息 +/// note | 注意 接收上传的文件和/或表单数据,首先安装 [`python-multipart`](https://github.com/Kludex/python-multipart)。 diff --git a/docs/zh/docs/tutorial/request-forms.md b/docs/zh/docs/tutorial/request-forms.md index ab82a181a..0e7f19c70 100644 --- a/docs/zh/docs/tutorial/request-forms.md +++ b/docs/zh/docs/tutorial/request-forms.md @@ -2,7 +2,7 @@ 当你需要接收表单字段而不是 JSON 时,可以使用 `Form`。 -/// info +/// note | 注意 要使用表单,首先安装 [`python-multipart`](https://github.com/Kludex/python-multipart)。 @@ -32,13 +32,13 @@ $ pip install python-multipart 使用 `Form` 可以像使用 `Body`(以及 `Query`、`Path`、`Cookie`)一样声明相同的配置,包括校验、示例、别名(例如将 `username` 写成 `user-name`)等。 -/// info +/// note | 注意 `Form` 是直接继承自 `Body` 的类。 /// -/// tip +/// tip | 提示 要声明表单请求体,必须显式使用 `Form`,否则这些参数会被当作查询参数或请求体(JSON)参数。 @@ -60,9 +60,9 @@ HTML 表单(`
`)向服务器发送数据时通常会对数据使 /// -/// warning +/// warning | 警告 -你可以在一个路径操作中声明多个 `Form` 参数,但不能同时再声明要接收为 JSON 的 `Body` 字段,因为此时请求体会使用 `application/x-www-form-urlencoded` 而不是 `application/json` 进行编码。 +你可以在一个*路径操作*中声明多个 `Form` 参数,但不能同时再声明要接收为 JSON 的 `Body` 字段,因为此时请求体会使用 `application/x-www-form-urlencoded` 而不是 `application/json` 进行编码。 这不是 **FastAPI** 的限制,而是 HTTP 协议的一部分。 diff --git a/docs/zh/docs/tutorial/response-model.md b/docs/zh/docs/tutorial/response-model.md index 9b4e0382e..5d8d0c185 100644 --- a/docs/zh/docs/tutorial/response-model.md +++ b/docs/zh/docs/tutorial/response-model.md @@ -72,7 +72,7 @@ FastAPI 会使用这个 `response_model` 来完成数据文档、校验等,并 {* ../../docs_src/response_model/tutorial002_py310.py hl[7,9] *} -/// info | 信息 +/// note | 注意 要使用 `EmailStr`,首先安装 [`email-validator`](https://github.com/JoshData/python-email-validator)。 @@ -116,7 +116,7 @@ $ pip install "pydantic[email]" {* ../../docs_src/response_model/tutorial003_py310.py hl[24] *} -……我们仍将 `response_model` 声明为不包含密码的 `UserOut` 模型: +...我们仍将 `response_model` 声明为不包含密码的 `UserOut` 模型: {* ../../docs_src/response_model/tutorial003_py310.py hl[22] *} @@ -128,7 +128,7 @@ $ pip install "pydantic[email]" 这就是为什么在这个例子里我们必须在 `response_model` 参数中声明它。 -……但继续往下读,看看如何更好地处理这种情况。 +...但继续往下读,看看如何更好地处理这种情况。 ## 返回类型与数据过滤 { #return-type-and-data-filtering } @@ -206,7 +206,7 @@ FastAPI 在内部配合 Pydantic 做了多项处理,确保不会把类继承 {* ../../docs_src/response_model/tutorial003_04_py310.py hl[8] *} -……它失败是因为该类型注解不是 Pydantic 类型,也不只是单个 `Response` 类或其子类,而是 `Response` 与 `dict` 的联合类型(任意其一)。 +...它失败是因为该类型注解不是 Pydantic 类型,也不只是单个 `Response` 类或其子类,而是 `Response` 与 `dict` 的联合类型(任意其一)。 ### 禁用响应模型 { #disable-response-model } @@ -251,7 +251,7 @@ FastAPI 在内部配合 Pydantic 做了多项处理,确保不会把类继承 } ``` -/// info | 信息 +/// note | 注意 你还可以使用: diff --git a/docs/zh/docs/tutorial/response-status-code.md b/docs/zh/docs/tutorial/response-status-code.md index e57c0e593..c06e67e6f 100644 --- a/docs/zh/docs/tutorial/response-status-code.md +++ b/docs/zh/docs/tutorial/response-status-code.md @@ -6,7 +6,7 @@ * `@app.post()` * `@app.put()` * `@app.delete()` -* 等... +* 等。 {* ../../docs_src/response_status_code/tutorial001_py310.py hl[6] *} @@ -18,7 +18,7 @@ `status_code` 参数接收表示 HTTP 状态码的数字。 -/// info | 信息 +/// note | 注意 `status_code` 还能接收 `IntEnum` 类型,比如 Python 的 [`http.HTTPStatus`](https://docs.python.org/3/library/http.html#http.HTTPStatus)。 @@ -27,13 +27,13 @@ 它可以: * 在响应中返回状态码 -* 在 OpenAPI 概图(及用户界面)中存档: +* 在 OpenAPI schema(以及用户界面)中将其记录为该状态码: /// note | 注意 -某些响应状态码表示响应没有响应体(参阅下一章)。 +某些响应状态码表示响应没有响应体(参阅下一节)。 FastAPI 可以进行识别,并生成表明无响应体的 OpenAPI 文档。 @@ -43,7 +43,7 @@ FastAPI 可以进行识别,并生成表明无响应体的 OpenAPI 文档。 /// note | 注意 -如果已经了解 HTTP 状态码,请跳到下一章。 +如果已经了解 HTTP 状态码,请跳到下一节。 /// diff --git a/docs/zh/docs/tutorial/schema-extra-example.md b/docs/zh/docs/tutorial/schema-extra-example.md index 482abd21d..b18e69641 100644 --- a/docs/zh/docs/tutorial/schema-extra-example.md +++ b/docs/zh/docs/tutorial/schema-extra-example.md @@ -10,7 +10,7 @@ {* ../../docs_src/schema_extra_example/tutorial001_py310.py hl[13:24] *} -这些额外信息会原样添加到该模型输出的 JSON Schema 中,并会在 API 文档中使用。 +这些额外信息会原样添加到该模型输出的 **JSON Schema** 中,并会在 API 文档中使用。 你可以使用属性 `model_config`,它接收一个 `dict`,详见 [Pydantic 文档:配置](https://docs.pydantic.dev/latest/api/config/)。 @@ -24,9 +24,9 @@ /// -/// info | 信息 +/// note | 注意 -OpenAPI 3.1.0(自 FastAPI 0.99.0 起使用)增加了对 `examples` 的支持,它是 JSON Schema 标准的一部分。 +OpenAPI 3.1.0(自 FastAPI 0.99.0 起使用)增加了对 `examples` 的支持,它是 **JSON Schema** 标准的一部分。 在此之前,只支持使用单个示例的关键字 `example`。OpenAPI 3.1.0 仍然支持它,但它已被弃用,并不属于 JSON Schema 标准。因此,建议你把 `example` 迁移到 `examples`。🤓 @@ -52,7 +52,7 @@ OpenAPI 3.1.0(自 FastAPI 0.99.0 起使用)增加了对 `examples` 的支持 - `Form()` - `File()` -你也可以声明一组 `examples`,这些带有附加信息的示例将被添加到它们在 OpenAPI 中的 JSON Schema 里。 +你也可以声明一组 `examples`,这些带有附加信息的示例将被添加到它们在 **OpenAPI** 中的 **JSON Schema** 里。 ### 带有 `examples` 的 `Body` { #body-with-examples } @@ -72,21 +72,21 @@ OpenAPI 3.1.0(自 FastAPI 0.99.0 起使用)增加了对 `examples` 的支持 {* ../../docs_src/schema_extra_example/tutorial004_an_py310.py hl[23:38] *} -这样做时,这些示例会成为该请求体数据内部 JSON Schema 的一部分。 +这样做时,这些示例会成为该请求体数据内部 **JSON Schema** 的一部分。 -不过,在撰写本文时,用于展示文档 UI 的 Swagger UI 并不支持显示 JSON Schema 中数据的多个示例。但请继续阅读,下面有一种变通方法。 +不过,在撰写本文时,用于展示文档 UI 的 Swagger UI 并不支持显示 **JSON Schema** 中数据的多个示例。但请继续阅读,下面有一种变通方法。 ### OpenAPI 特定的 `examples` { #openapi-specific-examples } -在 JSON Schema 支持 `examples` 之前,OpenAPI 就已支持一个同名但不同的字段 `examples`。 +在 **JSON Schema** 支持 `examples` 之前,OpenAPI 就已支持一个同名但不同的字段 `examples`。 -这个面向 OpenAPI 的 `examples` 位于 OpenAPI 规范的另一处。它放在每个路径操作的详细信息中,而不是每个 JSON Schema 里。 +这个 **OpenAPI 特定的** `examples` 位于 OpenAPI 规范的另一处。它放在**每个*路径操作*的详细信息**中,而不是每个 JSON Schema 里。 -而 Swagger UI 早就支持这个特定的 `examples` 字段。因此,你可以用它在文档 UI 中展示不同的示例。 +而 Swagger UI 早就支持这个特定的 `examples` 字段。因此,你可以用它在文档 UI 中**展示**不同的**示例**。 -这个 OpenAPI 特定字段 `examples` 的结构是一个包含多个示例的 `dict`(而不是一个 `list`),每个示例都包含会被添加到 OpenAPI 的额外信息。 +这个 OpenAPI 特定字段 `examples` 的结构是一个包含**多个示例**的 `dict`(而不是一个 `list`),每个示例都包含会被添加到 **OpenAPI** 的额外信息。 -这不放在 OpenAPI 内部包含的各个 JSON Schema 里,而是直接放在路径操作上。 +这不放在 OpenAPI 内部包含的各个 JSON Schema 里,而是直接放在*路径操作*上。 ### 使用 `openapi_examples` 参数 { #using-the-openapi-examples-parameter } @@ -123,23 +123,23 @@ OpenAPI 3.1.0(自 FastAPI 0.99.0 起使用)增加了对 `examples` 的支持 /// tip | 提示 -如果你已经在使用 FastAPI 版本 0.99.0 或更高版本,你大概率可以跳过这些细节。 +如果你已经在使用 **FastAPI** 版本 **0.99.0 或更高版本**,你大概率可以**跳过**这些细节。 它们对更早版本(OpenAPI 3.1.0 尚不可用之前)更相关。 -你可以把这当作一堂简短的 OpenAPI 和 JSON Schema 历史课。🤓 +你可以把这当作一堂简短的 OpenAPI 和 JSON Schema **历史课**。🤓 /// /// warning | 警告 -以下是关于 JSON Schema 和 OpenAPI 标准的非常技术性的细节。 +以下是关于 **JSON Schema** 和 **OpenAPI** 标准的非常技术性的细节。 如果上面的思路对你已经足够可用,你可能不需要这些细节,可以直接跳过。 /// -在 OpenAPI 3.1.0 之前,OpenAPI 使用的是一个更旧且经过修改的 JSON Schema 版本。 +在 OpenAPI 3.1.0 之前,OpenAPI 使用的是一个更旧且经过修改的 **JSON Schema** 版本。 当时 JSON Schema 没有 `examples`,所以 OpenAPI 在它修改过的版本中添加了自己的 `example` 字段。 @@ -155,7 +155,7 @@ OpenAPI 还在规范的其他部分添加了 `example` 和 `examples` 字段: - `File()` - `Form()` -/// info | 信息 +/// note | 注意 这个旧的、OpenAPI 特定的 `examples` 参数,自 FastAPI `0.103.0` 起改名为 `openapi_examples`。 @@ -169,9 +169,9 @@ OpenAPI 还在规范的其他部分添加了 `example` 和 `examples` 字段: 现在,这个新的 `examples` 字段优先于旧的单个(且自定义的)`example` 字段,后者已被弃用。 -JSON Schema 中这个新的 `examples` 字段只是一个由示例组成的 `list`,而不是像上面提到的 OpenAPI 其他位置那样带有额外元数据的 `dict`。 +在 JSON Schema 中,这个新的 `examples` 字段**只是一个由示例组成的 `list`**,而不是像上面提到的 OpenAPI 其他位置那样带有额外元数据的 `dict`。 -/// info | 信息 +/// note | 注意 即使在 OpenAPI 3.1.0 发布、并与 JSON Schema 有了这种更简单的集成之后,有一段时间里,提供自动文档的 Swagger UI 并不支持 OpenAPI 3.1.0(它自 5.0.0 版本起已支持 🎉)。 @@ -181,22 +181,22 @@ JSON Schema 中这个新的 `examples` 字段只是一个由示例组成的 `lis ### Pydantic 与 FastAPI 的 `examples` { #pydantic-and-fastapi-examples } -当你在 Pydantic 模型中添加 `examples`,通过 `schema_extra` 或 `Field(examples=["something"])`,这些示例会被添加到该 Pydantic 模型的 JSON Schema 中。 +当你在 Pydantic 模型中添加 `examples`,通过 `schema_extra` 或 `Field(examples=["something"])`,这些示例会被添加到该 Pydantic 模型的 **JSON Schema** 中。 -这个 Pydantic 模型的 JSON Schema 会被包含到你的 API 的 OpenAPI 中,然后在文档 UI 中使用。 +这个 Pydantic 模型的 **JSON Schema** 会被包含到你的 API 的 **OpenAPI** 中,然后在文档 UI 中使用。 -在 FastAPI 0.99.0 之前的版本(0.99.0 及以上使用更新的 OpenAPI 3.1.0),当你在其他工具(`Query()`、`Body()` 等)中使用 `example` 或 `examples` 时,这些示例不会被添加到描述该数据的 JSON Schema 中(甚至不会添加到 OpenAPI 自己的 JSON Schema 版本中),而是会直接添加到 OpenAPI 的路径操作声明中(在 OpenAPI 使用 JSON Schema 的部分之外)。 +在 FastAPI 0.99.0 之前的版本(0.99.0 及以上使用更新的 OpenAPI 3.1.0),当你在其他工具(`Query()`、`Body()` 等)中使用 `example` 或 `examples` 时,这些示例不会被添加到描述该数据的 JSON Schema 中(甚至不会添加到 OpenAPI 自己的 JSON Schema 版本中),而是会直接添加到 OpenAPI 的*路径操作*声明中(在 OpenAPI 使用 JSON Schema 的部分之外)。 但现在 FastAPI 0.99.0 及以上使用 OpenAPI 3.1.0(其使用 JSON Schema 2020-12)以及 Swagger UI 5.0.0 及以上后,一切更加一致,示例会包含在 JSON Schema 中。 ### Swagger UI 与 OpenAPI 特定的 `examples` { #swagger-ui-and-openapi-specific-examples } -此前,由于 Swagger UI 不支持多个 JSON Schema 示例(截至 2023-08-26),用户无法在文档中展示多个示例。 +由于截至 2023-08-26,Swagger UI 不支持多个 JSON Schema 示例,用户无法在文档中展示多个示例。 -为了解决这个问题,FastAPI `0.103.0` 通过新增参数 `openapi_examples`,为声明同样的旧式 OpenAPI 特定 `examples` 字段提供了支持。🤓 +为了解决这个问题,FastAPI `0.103.0` **增加了支持**,可以通过新参数 `openapi_examples` 声明同样的旧式 **OpenAPI 特定的** `examples` 字段。🤓 ### 总结 { #summary } -我曾经说我不太喜欢历史……结果现在在这儿上“技术史”课。😅 +我曾经说我不太喜欢历史... 结果现在在这儿上“技术史”课。😅 -简而言之,升级到 FastAPI 0.99.0 或更高版本,一切会更简单、一致、直观,你也不必了解这些历史细节。😎 +简而言之,**升级到 FastAPI 0.99.0 或更高版本**,一切会更**简单、一致、直观**,你也不必了解这些历史细节。😎 diff --git a/docs/zh/docs/tutorial/security/first-steps.md b/docs/zh/docs/tutorial/security/first-steps.md index 6cc91211a..ca3ef8352 100644 --- a/docs/zh/docs/tutorial/security/first-steps.md +++ b/docs/zh/docs/tutorial/security/first-steps.md @@ -1,5 +1,6 @@ # 安全 - 第一步 { #security-first-steps } + 假设你的**后端** API 位于某个域名下。 而**前端**在另一个域名,或同一域名的不同路径(或在移动应用中)。 @@ -24,13 +25,13 @@ ## 运行 { #run-it } -/// info | 信息 +/// note | 注意 当你使用命令 `pip install "fastapi[standard]"` 安装 **FastAPI** 时,[`python-multipart`](https://github.com/Kludex/python-multipart) 包会自动安装。 但是,如果你使用 `pip install fastapi`,默认不会包含 `python-multipart` 包。 -如需手动安装,请先创建并激活[虚拟环境](../../virtual-environments.md),然后执行: +如需手动安装,请先创建[虚拟环境](../../virtual-environments.md)、激活它,然后执行: ```console $ pip install python-multipart @@ -60,7 +61,7 @@ $ fastapi dev -/// check | Authorize 按钮! +/// tip | Authorize 按钮! 页面右上角已经有一个崭新的“Authorize”按钮。 @@ -118,7 +119,7 @@ OAuth2 的设计目标是让后端或 API 与负责用户认证的服务器解 本示例将使用 **OAuth2** 的 **Password** 流程并配合 **Bearer** 令牌,通过 `OAuth2PasswordBearer` 类来实现。 -/// info | 信息 +/// note | 注意 “Bearer” 令牌并非唯一选项。 @@ -148,7 +149,7 @@ OAuth2 的设计目标是让后端或 API 与负责用户认证的服务器解 我们很快也会创建对应的实际路径操作。 -/// info | 信息 +/// note | 注意 如果你是非常严格的 “Pythonista”,可能不喜欢使用参数名 `tokenUrl` 而不是 `token_url`。 @@ -176,7 +177,7 @@ oauth2_scheme(some, parameters) **FastAPI** 会据此在 OpenAPI 架构(以及自动生成的 API 文档)中定义一个“安全方案”。 -/// info | 技术细节 +/// note | 技术细节 **FastAPI** 之所以知道可以使用(在依赖中声明的)`OAuth2PasswordBearer` 在 OpenAPI 中定义安全方案,是因为它继承自 `fastapi.security.oauth2.OAuth2`,而后者又继承自 `fastapi.security.base.SecurityBase`。 diff --git a/docs/zh/docs/tutorial/security/get-current-user.md b/docs/zh/docs/tutorial/security/get-current-user.md index 814ff2c82..dc8c70014 100644 --- a/docs/zh/docs/tutorial/security/get-current-user.md +++ b/docs/zh/docs/tutorial/security/get-current-user.md @@ -8,14 +8,13 @@ 接下来,我们学习如何返回当前用户。 - ## 创建用户模型 { #create-a-user-model } 首先,创建 Pydantic 用户模型。 与使用 Pydantic 声明请求体相同,并且可在任何位置使用: -{* ../../docs_src/security/tutorial002_an_py310.py hl[5,12:6] *} +{* ../../docs_src/security/tutorial002_an_py310.py hl[5,12:16] *} ## 创建 `get_current_user` 依赖项 { #create-a-get-current-user-dependency } @@ -53,9 +52,9 @@ /// -/// check | 检查 +/// tip | 提示 -依赖系统的这种设计方式可以支持不同的依赖项返回同一个 `User` 模型。 +依赖系统的这种设计方式可以支持不同的依赖项(不同的“可依赖项”)返回同一个 `User` 模型。 而不是局限于只能有一个返回该类型数据的依赖项。 @@ -77,7 +76,6 @@ 尽管使用应用所需的任何模型、类、数据库。**FastAPI** 通过依赖注入系统都能帮您搞定。 - ## 代码大小 { #code-size } 这个示例看起来有些冗长。毕竟这个文件同时包含了安全、数据模型的工具函数,以及路径操作等代码。 diff --git a/docs/zh/docs/tutorial/security/oauth2-jwt.md b/docs/zh/docs/tutorial/security/oauth2-jwt.md index 8a56137d3..418b3b97d 100644 --- a/docs/zh/docs/tutorial/security/oauth2-jwt.md +++ b/docs/zh/docs/tutorial/security/oauth2-jwt.md @@ -42,7 +42,7 @@ $ pip install pyjwt
-/// info | 信息 +/// note | 注意 如果你计划使用类似 RSA 或 ECDSA 的数字签名算法,你应该安装加密库依赖项 `pyjwt[crypto]`。 @@ -120,7 +120,7 @@ pwdlib 也支持 bcrypt 哈希算法,但不包含遗留算法——如果需 当使用一个在数据库中不存在的用户名调用 `authenticate_user` 时,我们仍然会针对一个虚拟哈希运行 `verify_password`。 -这可以确保无论用户名是否有效,端点的响应时间大致相同,从而防止可用于枚举已存在用户名的“时间攻击”(timing attacks)。 +这可以确保无论用户名是否有效,端点的响应时间大致相同,从而防止可用于枚举已存在用户名的**时序攻击**。 /// note | 注意 @@ -168,7 +168,7 @@ $ openssl rand -hex 32 {* ../../docs_src/security/tutorial004_an_py310.py hl[93:110] *} -## 更新 `/token` 路径操作 { #update-the-token-path-operation } +## 更新 `/token` *路径操作* { #update-the-token-path-operation } 用令牌的过期时间创建一个 `timedelta`。 @@ -213,7 +213,7 @@ JWT 除了用于识别用户并允许其直接在你的 API 上执行操作之 用户名: `johndoe` 密码: `secret` -/// check | 检查 +/// tip | 提示 注意,代码中的任何地方都没有明文密码 “`secret`”,我们只有它的哈希版本。 diff --git a/docs/zh/docs/tutorial/security/simple-oauth2.md b/docs/zh/docs/tutorial/security/simple-oauth2.md index d8d5b561e..92cf02dd2 100644 --- a/docs/zh/docs/tutorial/security/simple-oauth2.md +++ b/docs/zh/docs/tutorial/security/simple-oauth2.md @@ -6,7 +6,7 @@ 首先,使用 **FastAPI** 安全工具获取 `username` 和 `password`。 -OAuth2 规范要求使用“密码流”时,客户端或用户必须以表单数据形式发送 `username` 和 `password` 字段。 +OAuth2 规范要求使用“密码流”(也就是我们正在使用的流程)时,客户端或用户必须以表单数据形式发送 `username` 和 `password` 字段。 并且,这两个字段必须命名为 `username` 和 `password`,不能使用 `user-name` 或 `email` 等其它名称。 @@ -32,7 +32,7 @@ OAuth2 还支持客户端发送**`scope`**表单字段。 * 脸书和 Instagram 使用 `instagram_basic` * 谷歌使用 `https://www.googleapis.com/auth/drive` -/// info | 信息 +/// note | 注意 OAuth2 中,**作用域**只是声明指定权限的字符串。 @@ -72,7 +72,7 @@ OAuth2 中,**作用域**只是声明指定权限的字符串。 * 可选的 `client_id`(本例未使用) * 可选的 `client_secret`(本例未使用) -/// info | 信息 +/// note | 注意 `OAuth2PasswordRequestForm` 并不像 `OAuth2PasswordBearer` 那样是 **FastAPI** 的特殊类。 @@ -80,7 +80,7 @@ OAuth2 中,**作用域**只是声明指定权限的字符串。 但 `OAuth2PasswordRequestForm` 只是可以自行编写的类依赖项,也可以直接声明 `Form` 参数。 -但由于这种用例很常见,FastAPI 为了简便,就直接提供了对它的支持。 +但由于这种用例很常见,**FastAPI** 为了简便,就直接提供了对它的支持。 /// @@ -144,9 +144,9 @@ UserInDB( ) ``` -/// info | 信息 +/// note | 注意 -`user_dict` 的说明,详见[**更多模型**一章](../extra-models.md#about-user-in-dict)。 +关于 `**user_dict` 的更完整说明,详见[**更多模型**文档](../extra-models.md#about-user-in-model-dump)。 /// @@ -196,7 +196,7 @@ UserInDB( {* ../../docs_src/security/tutorial003_an_py310.py hl[58:66,69:74,94] *} -/// info | 信息 +/// note | 注意 此处返回值为 `Bearer` 的响应头 `WWW-Authenticate` 也是规范的一部分。 @@ -208,7 +208,7 @@ UserInDB( 之所以在此提供这个附加响应头,是为了符合规范的要求。 -说不定什么时候,就有工具用得上它,而且,开发者或用户也可能用得上。 +此外,现在或将来,可能会有工具期望并使用它,而且现在或将来这也可能对你或你的用户有用。 这就是遵循标准的好处... diff --git a/docs/zh/docs/tutorial/server-sent-events.md b/docs/zh/docs/tutorial/server-sent-events.md index c78562b91..8542756f2 100644 --- a/docs/zh/docs/tutorial/server-sent-events.md +++ b/docs/zh/docs/tutorial/server-sent-events.md @@ -4,7 +4,7 @@ 这类似于[流式传输 JSON Lines](stream-json-lines.md),但使用 `text/event-stream` 格式,浏览器原生通过 [`EventSource` API](https://developer.mozilla.org/en-US/docs/Web/API/EventSource) 支持。 -/// info | 信息 +/// note | 注意 新增于 FastAPI 0.135.0。 diff --git a/docs/zh/docs/tutorial/sql-databases.md b/docs/zh/docs/tutorial/sql-databases.md index 9004983b1..1d6a3cd34 100644 --- a/docs/zh/docs/tutorial/sql-databases.md +++ b/docs/zh/docs/tutorial/sql-databases.md @@ -8,7 +8,7 @@ /// tip | 提示 -你可以使用任意其他你想要的 SQL 或 NoSQL 数据库库(在某些情况下称为 "ORMs"),FastAPI 不会强迫你使用任何东西。😎 +你可以使用任意其他你想要的 SQL 或 NoSQL 数据库类库(在某些情况下称为 "ORMs"),FastAPI 不会强迫你使用任何东西。😎 /// @@ -57,7 +57,7 @@ $ pip install sqlmodel {* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[1:11] hl[7:11] *} -`Hero` 类与 Pydantic 模型非常相似(实际上,从底层来看,它确实就是一个 Pydantic 模型)。 +`Hero` 类与 Pydantic 模型非常相似(实际上,从底层来看,它*确实就是一个 Pydantic 模型*)。 有一些区别: @@ -65,7 +65,7 @@ $ pip install sqlmodel * `Field(primary_key=True)` 会告诉 SQLModel `id` 是 SQL 数据库中的**主键**(你可以在 SQLModel 文档中了解更多关于 SQL 主键的信息)。 - **注意:** 我们为主键字段使用 `int | None`,这样在 Python 代码中我们可以在没有 `id`(`id=None`)的情况下创建对象,并假定数据库在保存时会生成它。SQLModel 会理解数据库会提供 `id`,并在数据库模式中将该列定义为非空的 `INTEGER`。详见 [SQLModel 关于主键的文档](https://sqlmodel.tiangolo.com/tutorial/create-db-and-table/#primary-key-id)。 + **注意:** 我们为主键字段使用 `int | None`,这样在 Python 代码中我们可以*在没有 `id` 的情况下创建对象*(`id=None`),并假定数据库会*在保存时生成它*。SQLModel 会理解数据库会提供 `id`,并在数据库模式中*将该列定义为非空的 `INTEGER`*。详见 [SQLModel 关于主键的文档](https://sqlmodel.tiangolo.com/tutorial/create-db-and-table/#primary-key-id)。 * `Field(index=True)` 会告诉 SQLModel 应该为此列创建一个 **SQL 索引**,这样在读取按此列过滤的数据时,程序能在数据库中进行更快的查找。 @@ -292,7 +292,7 @@ $ fastapi dev /// tip | 提示 -现在我们使用 `response_model=HeroPublic` 来代替**返回类型注解** `-> HeroPublic`,因为我们返回的值实际上并不是 `HeroPublic`。 +现在我们使用 `response_model=HeroPublic` 来代替**返回类型注解** `-> HeroPublic`,因为我们返回的值实际上*并不是* `HeroPublic`。 如果我们声明了 `-> HeroPublic`,你的编辑器和代码检查工具会(理所应当地)抱怨你返回了一个 `Hero` 而不是一个 `HeroPublic`。 diff --git a/docs/zh/docs/tutorial/static-files.md b/docs/zh/docs/tutorial/static-files.md index 65262bdb4..b700f46d6 100644 --- a/docs/zh/docs/tutorial/static-files.md +++ b/docs/zh/docs/tutorial/static-files.md @@ -2,6 +2,14 @@ 你可以使用 `StaticFiles` 从目录中自动提供静态文件。 +/// tip | 提示 + +如果你需要托管前端,请改用 `app.frontend()`,可在[前端](frontend.md)中阅读相关内容。 + +`app.frontend()` 底层使用 `StaticFiles`,并为前端提供了几个额外优势,例如处理客户端路由。 + +/// + ## 使用 `StaticFiles` { #use-staticfiles } * 导入 `StaticFiles`。 diff --git a/docs/zh/docs/tutorial/stream-json-lines.md b/docs/zh/docs/tutorial/stream-json-lines.md index 8a27dce76..e98022501 100644 --- a/docs/zh/docs/tutorial/stream-json-lines.md +++ b/docs/zh/docs/tutorial/stream-json-lines.md @@ -2,7 +2,7 @@ 当你想以“流”的方式发送一系列数据时,可以使用 JSON Lines。 -/// info | 信息 +/// note | 注意 新增于 FastAPI 0.134.0。 @@ -48,7 +48,7 @@ sequenceDiagram 它与 JSON 数组(相当于 Python 的 list)非常相似,但不是用 `[]` 包裹、并在各项之间使用 `,` 分隔,而是每行一个 JSON 对象,彼此以换行符分隔。 -/// info | 信息 +/// note | 注意 关键在于你的应用可以逐行生成数据,而客户端在消费前面的行。 diff --git a/docs/zh/docs/tutorial/testing.md b/docs/zh/docs/tutorial/testing.md index 6607a1239..79e5044c9 100644 --- a/docs/zh/docs/tutorial/testing.md +++ b/docs/zh/docs/tutorial/testing.md @@ -8,7 +8,7 @@ ## 使用 `TestClient` { #using-testclient } -/// info | 信息 +/// note | 注意 要使用 `TestClient`,先要安装 [`httpx`](https://www.python-httpx.org)。 @@ -52,7 +52,7 @@ $ pip install httpx /// tip | 提示 -除了发送请求之外,如果你还想测试时在FastAPI应用中调用 `async` 函数(例如异步数据库函数), 可以在高级教程中看下 [Async Tests](../advanced/async-tests.md) 。 +除了发送请求之外,如果你还想测试时在FastAPI应用中调用 `async` 函数(例如异步数据库函数), 可以在高级教程中看下[异步测试](../advanced/async-tests.md)。 /// @@ -60,7 +60,7 @@ $ pip install httpx 在实际应用中,你可能会把你的测试放在另一个文件里。 -您的**FastAPI**应用程序也可能由一些文件/模块组成等等。 +你的**FastAPI**应用程序也可能由一些文件/模块组成等等。 ### **FastAPI** app 文件 { #fastapi-app-file } @@ -80,7 +80,7 @@ $ pip install httpx ### 测试文件 { #testing-file } -然后你会有一个包含测试的文件 `test_main.py` 。app可以像Python包那样存在(一样是目录,但有个 `__init__.py` 文件): +然后你会有一个包含测试的文件 `test_main.py` 。它可以位于同一个 Python 包中(一样是目录,但有个 `__init__.py` 文件): ``` hl_lines="5" . @@ -94,6 +94,7 @@ $ pip install httpx {* ../../docs_src/app_testing/app_a_py310/test_main.py hl[3] *} + ...然后测试代码和之前一样的。 ## 测试:扩展示例 { #testing-extended-example } @@ -114,20 +115,21 @@ $ pip install httpx 假设现在包含**FastAPI** app的文件 `main.py` 有些其他**路径操作**。 -有个 `GET` 操作会返回错误。 +有个 `GET` 操作可能返回一个错误。 -有个 `POST` 操作会返回一些错误。 +有个 `POST` 操作可能返回多个错误。 -所有*路径操作* 都需要一个`X-Token` 头。 +两个*路径操作* 都需要一个`X-Token` 头。 {* ../../docs_src/app_testing/app_b_an_py310/main.py *} ### 扩展后的测试文件 { #extended-testing-file } -然后您可以使用扩展后的测试更新`test_main.py`: +然后你可以使用扩展后的测试更新`test_main.py`: {* ../../docs_src/app_testing/app_b_an_py310/test_main.py *} + 每当你需要客户端在请求中传递信息,但你不知道如何传递时,你可以通过搜索(谷歌)如何用 `httpx` 做,或者是用 `requests` 做,毕竟HTTPX的设计是基于Requests的设计的。 接着只需在测试中同样操作。 @@ -142,11 +144,11 @@ $ pip install httpx 关于如何传数据给后端的更多信息(使用 `httpx` 或 `TestClient`),请查阅 [HTTPX 文档](https://www.python-httpx.org)。 -/// info | 信息 +/// note | 注意 注意 `TestClient` 接收可以被转化为JSON的数据,而不是Pydantic模型。 -如果你在测试中有一个Pydantic模型,并且你想在测试时发送它的数据给应用,你可以使用在[JSON Compatible Encoder](encoder.md)介绍的`jsonable_encoder` 。 +如果你在测试中有一个Pydantic模型,并且你想在测试时发送它的数据给应用,你可以使用在[JSON 兼容编码器](encoder.md)介绍的`jsonable_encoder` 。 /// @@ -166,7 +168,7 @@ $ pip install pytest -他会自动检测文件和测试,执行测试,然后向你报告结果。 +它会自动检测文件和测试,执行测试,然后向你报告结果。 执行测试: diff --git a/docs/zh/docs/virtual-environments.md b/docs/zh/docs/virtual-environments.md index d10251dbe..a31240d9f 100644 --- a/docs/zh/docs/virtual-environments.md +++ b/docs/zh/docs/virtual-environments.md @@ -861,4 +861,4 @@ I solemnly swear 🐺 如果你读过并理解了所有这些,现在**你对虚拟环境的了解比很多开发者都要多**。🤓 -在未来当你调看看起来复杂的东西时,了解这些细节很可能会有用,你会知道**它是如何在底层工作的**。😎 +在未来当你调试看起来复杂的东西时,了解这些细节很可能会有用,你会知道**它是如何在底层工作的**。😎 diff --git a/docs_src/frontend/__init__.py b/docs_src/frontend/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/docs_src/frontend/tutorial001_py310.py b/docs_src/frontend/tutorial001_py310.py new file mode 100644 index 000000000..69e6f37f9 --- /dev/null +++ b/docs_src/frontend/tutorial001_py310.py @@ -0,0 +1,5 @@ +from fastapi import FastAPI + +app = FastAPI() + +app.frontend("/", directory="dist") diff --git a/docs_src/frontend/tutorial002_py310.py b/docs_src/frontend/tutorial002_py310.py new file mode 100644 index 000000000..bb5349cde --- /dev/null +++ b/docs_src/frontend/tutorial002_py310.py @@ -0,0 +1,5 @@ +from fastapi import FastAPI + +app = FastAPI() + +app.frontend("/", directory="dist", fallback="index.html") diff --git a/docs_src/frontend/tutorial003_py310.py b/docs_src/frontend/tutorial003_py310.py new file mode 100644 index 000000000..d0a526632 --- /dev/null +++ b/docs_src/frontend/tutorial003_py310.py @@ -0,0 +1,5 @@ +from fastapi import FastAPI + +app = FastAPI() + +app.frontend("/", directory="dist", fallback="404.html") diff --git a/docs_src/frontend/tutorial004_py310.py b/docs_src/frontend/tutorial004_py310.py new file mode 100644 index 000000000..647e92d10 --- /dev/null +++ b/docs_src/frontend/tutorial004_py310.py @@ -0,0 +1,7 @@ +from fastapi import APIRouter, FastAPI + +app = FastAPI() +router = APIRouter() + +router.frontend("/", directory="dist", fallback="index.html") +app.include_router(router, prefix="/app") diff --git a/docs_src/frontend/tutorial005_py310.py b/docs_src/frontend/tutorial005_py310.py new file mode 100644 index 000000000..a167824af --- /dev/null +++ b/docs_src/frontend/tutorial005_py310.py @@ -0,0 +1,5 @@ +from fastapi import FastAPI + +app = FastAPI() + +app.frontend("/", directory="dist", fallback=None) diff --git a/docs_src/frontend/tutorial006_py310.py b/docs_src/frontend/tutorial006_py310.py new file mode 100644 index 000000000..451d2416d --- /dev/null +++ b/docs_src/frontend/tutorial006_py310.py @@ -0,0 +1,5 @@ +from fastapi import FastAPI + +app = FastAPI() + +app.frontend("/", directory="dist", check_dir=False) diff --git a/docs_src/path_operation_advanced_configuration/tutorial002_py310.py b/docs_src/path_operation_advanced_configuration/tutorial002_py310.py index 3aaae9b37..5c2257ed6 100644 --- a/docs_src/path_operation_advanced_configuration/tutorial002_py310.py +++ b/docs_src/path_operation_advanced_configuration/tutorial002_py310.py @@ -1,24 +1,14 @@ from fastapi import FastAPI from fastapi.routing import APIRoute -app = FastAPI() - -@app.get("/items/") -async def read_items(): - return [{"item_id": "Foo"}] +def custom_generate_unique_id(route: APIRoute) -> str: + return route.name -def use_route_names_as_operation_ids(app: FastAPI) -> None: - """ - Simplify operation IDs so that generated API clients have simpler function - names. +app = FastAPI(generate_unique_id_function=custom_generate_unique_id) - Should be called only after all routes have been added. - """ - for route in app.routes: - if isinstance(route, APIRoute): - route.operation_id = route.name # in this case, 'read_items' - -use_route_names_as_operation_ids(app) +@app.get("/items/") +async def read_items(): + return [{"item_id": "Foo"}] diff --git a/fastapi/.agents/skills/fastapi/SKILL.md b/fastapi/.agents/skills/fastapi/SKILL.md index 48cfdabb8..fc35b97ed 100644 --- a/fastapi/.agents/skills/fastapi/SKILL.md +++ b/fastapi/.agents/skills/fastapi/SKILL.md @@ -1,12 +1,23 @@ --- name: fastapi -description: FastAPI best practices and conventions. Use when working with FastAPI APIs and Pydantic models for them. Keeps FastAPI code clean and up to date with the latest features and patterns, updated with new versions. Write new code or refactor and update old code. +description: FastAPI best practices and conventions. Use when working with FastAPI APIs, Pydantic models, dependencies, streaming responses including Server-Sent Events (SSE), and serving frontend apps. Keeps FastAPI code clean and up to date with the latest features and patterns. --- # FastAPI Official FastAPI skill to write code with best practices, keeping up to date with new versions and features. +## Quick Reference + +* Serve frontend apps: use `app.frontend()` or `router.frontend()` for built frontend assets; see [Serve Frontend Apps](#serve-frontend-apps). +* Server-Sent Events (SSE): use `response_class=EventSourceResponse` and `yield`; see [Streaming](#streaming-json-lines-sse-bytes) and [the streaming reference](references/streaming.md). +* JSON Lines and byte streaming: see [the streaming reference](references/streaming.md). +* Dependencies: use `Annotated[..., Depends(...)]`; see [Dependency Injection](#dependency-injection) and [the dependency injection reference](references/dependencies.md) for `yield`, scopes, and class dependencies. +* Response models: prefer return types; use `response_model` when the public response schema differs from the internal return value; see [the response reference](references/responses.md). +* Pydantic models: do not use ellipsis or `RootModel`; see [the Pydantic reference](references/pydantic.md). +* Routing: declare router-level prefix, tags, and shared dependencies on the `APIRouter`; see [the path operation reference](references/path-operations.md). +* Tooling and related libraries: use uv, Ruff, ty, Asyncer, SQLModel, and HTTPX when applicable; see [the other tools reference](references/other-tools.md). + ## Use the `fastapi` CLI Run the development server on localhost with reload: @@ -15,39 +26,28 @@ Run the development server on localhost with reload: fastapi dev ``` - Run the production server: ```bash fastapi run ``` -### Add an entrypoint in `pyproject.toml` - -FastAPI CLI will read the entrypoint in `pyproject.toml` to know where the FastAPI app is declared. +Prefer declaring the entrypoint in `pyproject.toml`: ```toml [tool.fastapi] entrypoint = "my_app.main:app" ``` -### Use `fastapi` with a path - -When adding the entrypoint to `pyproject.toml` is not possible, or the user explicitly asks not to, or it's running an independent small app, you can pass the app file path to the `fastapi` command: +When adding the entrypoint is not possible, or the user explicitly asks not to, pass the app file path: ```bash fastapi dev my_app/main.py ``` -Prefer to set the entrypoint in `pyproject.toml` when possible. - ## Use `Annotated` -Always prefer the `Annotated` style for parameter and dependency declarations. - -It keeps the function signatures working in other contexts, respects the types, allows reusability. - -### In Parameter Declarations +Always prefer the `Annotated` style for parameter and dependency declarations. It keeps function signatures working in other contexts, respects the types, and allows reusability. Use `Annotated` for parameter declarations, including `Path`, `Query`, `Header`, etc.: @@ -67,23 +67,7 @@ async def read_item( return {"message": "Hello World"} ``` -instead of: - -```python -# DO NOT DO THIS -@app.get("/items/{item_id}") -async def read_item( - item_id: int = Path(ge=1, description="The item ID"), - q: str | None = Query(default=None, max_length=50), -): - return {"message": "Hello World"} -``` - -### For Dependencies - -Use `Annotated` for dependencies with `Depends()`. - -Unless asked not to, create a new type alias for the dependency to allow re-using it. +Use `Annotated` for dependencies with `Depends()`. Unless asked not to, create a new type alias for the dependency to allow reusing it: ```python from typing import Annotated @@ -105,20 +89,9 @@ async def read_item(current_user: CurrentUserDep): return {"message": "Hello World"} ``` -instead of: - -```python -# DO NOT DO THIS -@app.get("/items/") -async def read_item(current_user: dict = Depends(get_current_user)): - return {"message": "Hello World"} -``` - ## Do not use Ellipsis for *path operations* or Pydantic models -Do not use `...` as a default value for required parameters, it's not needed and not recommended. - -Do this, without Ellipsis (`...`): +Do not use `...` as a default value for required parameters or model fields. It's not needed and not recommended. ```python from typing import Annotated @@ -126,6 +99,8 @@ from typing import Annotated from fastapi import FastAPI, Query from pydantic import BaseModel, Field +app = FastAPI() + class Item(BaseModel): name: str @@ -133,29 +108,12 @@ class Item(BaseModel): price: float = Field(gt=0) -app = FastAPI() - - @app.post("/items/") -async def create_item(item: Item, project_id: Annotated[int, Query()]): ... +async def create_item(item: Item, project_id: Annotated[int, Query()]): + return item ``` -instead of this: - -```python -# DO NOT DO THIS -class Item(BaseModel): - name: str = ... - description: str | None = None - price: float = Field(..., gt=0) - - -app = FastAPI() - - -@app.post("/items/") -async def create_item(item: Item, project_id: Annotated[int, Query(...)]): ... -``` +See [the Pydantic reference](references/pydantic.md) for more details. ## Return Type or Response Model @@ -178,62 +136,9 @@ async def get_item() -> Item: return Item(name="Plumbus", description="All-purpose home device") ``` -**Important**: Return types or response models are what filter data ensuring no sensitive information is exposed. And they are used to serialize data with Pydantic (in Rust), this is the main idea that can increase response performance. - -The return type doesn't have to be a Pydantic model, it could be a different type, like a list of integers, or a dict, etc. - -### When to use `response_model` instead - -If the return type is not the same as the type that you want to use to validate, filter, or serialize, use the `response_model` parameter on the decorator instead. - -```python -from typing import Any +Return types or response models filter data to avoid exposing sensitive information, and they let Pydantic serialize the data on the Rust side for performance. -from fastapi import FastAPI -from pydantic import BaseModel - -app = FastAPI() - - -class Item(BaseModel): - name: str - description: str | None = None - - -@app.get("/items/me", response_model=Item) -async def get_item() -> Any: - return {"name": "Foo", "description": "A very nice Item"} -``` - -This can be particularly useful when filtering data to expose only the public fields and avoid exposing sensitive information. - -```python -from typing import Any - -from fastapi import FastAPI -from pydantic import BaseModel - -app = FastAPI() - - -class InternalItem(BaseModel): - name: str - description: str | None = None - secret_key: str - - -class Item(BaseModel): - name: str - description: str | None = None - - -@app.get("/items/me", response_model=Item) -async def get_item() -> Any: - item = InternalItem( - name="Foo", description="A very nice Item", secret_key="supersecret" - ) - return item -``` +Use `response_model` when the type you return is not the same as the public schema you want to validate, filter, document, and serialize. See [the response reference](references/responses.md). ## Performance @@ -243,16 +148,23 @@ Instead, declare a return type or response model. Pydantic will handle the data ## Including Routers -When declaring routers, prefer to add router level parameters like prefix, tags, etc. to the router itself, instead of in `include_router()`. - -Do this: +When declaring routers, prefer to add router-level parameters like prefix, tags, and shared dependencies to the router itself instead of in `include_router()`. ```python -from fastapi import APIRouter, FastAPI +from fastapi import APIRouter, Depends, FastAPI app = FastAPI() -router = APIRouter(prefix="/items", tags=["items"]) + +def get_current_user(): + return {"username": "johndoe"} + + +router = APIRouter( + prefix="/items", + tags=["items"], + dependencies=[Depends(get_current_user)], +) @router.get("/") @@ -260,45 +172,48 @@ async def list_items(): return [] -# In main.py app.include_router(router) ``` -instead of this: +See [the path operation reference](references/path-operations.md) for more routing patterns. + +## Serve Frontend Apps + +Use `app.frontend()` to serve a built static frontend app, for example a directory generated by Vite, Astro, Angular, Svelte, Vue, or a similar tool. ```python -# DO NOT DO THIS -from fastapi import APIRouter, FastAPI +from fastapi import FastAPI app = FastAPI() -router = APIRouter() +app.frontend("/", directory="dist") +``` +Use `router.frontend()` when the frontend belongs to an `APIRouter`; normal router prefix behavior applies when the router is included. -@router.get("/") -async def list_items(): - return [] +```python +from fastapi import APIRouter, FastAPI +app = FastAPI() +router = APIRouter(prefix="/admin") -# In main.py -app.include_router(router, prefix="/items", tags=["items"]) +router.frontend("/", directory="admin-dist") +app.include_router(router) ``` -There could be exceptions, but try to follow this convention. - -Apply shared dependencies at the router level via `dependencies=[Depends(...)]`. +`app.frontend()` and `router.frontend()` are low-priority routes: regular API routes are matched first, then frontend files and client-side routing fallbacks. Use this for single-page apps and built frontend assets instead of mounting `StaticFiles` manually. ## Dependency Injection -See [the dependency injection reference](references/dependencies.md) for detailed patterns including `yield` with `scope`, and class dependencies. - -Use dependencies when the logic can't be declared in Pydantic validation, depends on external resources, needs cleanup (with `yield`), or is shared across endpoints. +Use dependencies when the logic can't be declared in Pydantic validation, depends on external resources, needs cleanup with `yield`, or is shared across endpoints. Apply shared dependencies at the router level via `dependencies=[Depends(...)]`. +See [the dependency injection reference](references/dependencies.md) for detailed patterns including `yield` with `scope`, and class dependencies. + ## Async vs Sync *path operations* -Use `async` *path operations* only when fully certain that the logic called inside is compatible with async and await (it's called with `await`) or that doesn't block. +Use `async` *path operations* only when fully certain that the logic called inside is compatible with async and await, and that it doesn't block. ```python from fastapi import FastAPI @@ -306,30 +221,44 @@ from fastapi import FastAPI app = FastAPI() -# Use async def when calling async code @app.get("/async-items/") async def read_async_items(): data = await some_async_library.fetch_items() return data -# Use plain def when calling blocking/sync code or when in doubt @app.get("/items/") def read_items(): data = some_blocking_library.fetch_items() return data ``` -In case of doubt, or by default, use regular `def` functions, those will be run in a threadpool so they don't block the event loop. +In case of doubt, or by default, use regular `def` functions. They will be run in a threadpool so they don't block the event loop. The same rules apply to dependencies. -The same rules apply to dependencies. - -Make sure blocking code is not run inside of `async` functions. The logic will work, but will damage the performance heavily. +Make sure blocking code is not run inside of `async` functions. The logic will work, but will damage performance heavily. When needing to mix blocking and async code, see Asyncer in [the other tools reference](references/other-tools.md). ## Streaming (JSON Lines, SSE, bytes) +To stream Server-Sent Events, use `response_class=EventSourceResponse` and `yield` items from the endpoint. + +```python +from collections.abc import AsyncIterable + +from fastapi import FastAPI +from fastapi.sse import EventSourceResponse, ServerSentEvent + +app = FastAPI() + + +@app.get("/events", response_class=EventSourceResponse) +async def stream_events() -> AsyncIterable[ServerSentEvent]: + yield ServerSentEvent(data={"status": "started"}, event="status", id="1") +``` + +Plain objects are automatically JSON-serialized as `data:` fields. Use `ServerSentEvent` for full control over SSE fields (`event`, `id`, `retry`, `comment`) and `raw_data` for pre-formatted strings. + See [the streaming reference](references/streaming.md) for JSON Lines, Server-Sent Events (`EventSourceResponse`, `ServerSentEvent`), and byte streaming (`StreamingResponse`) patterns. ## Tooling @@ -346,9 +275,7 @@ See [the other tools reference](references/other-tools.md) for details on other ## Do not use Pydantic RootModels -Do not use Pydantic `RootModel`, instead use regular type annotations with `Annotated` and Pydantic validation utilities. - -For example, for a list with validations you could do: +Do not use Pydantic `RootModel`; instead use regular type annotations with `Annotated` and Pydantic validation utilities. ```python from typing import Annotated @@ -364,35 +291,11 @@ async def create_items(items: Annotated[list[int], Field(min_length=1), Body()]) return items ``` -instead of: - -```python -# DO NOT DO THIS -from typing import Annotated - -from fastapi import FastAPI -from pydantic import Field, RootModel - -app = FastAPI() - - -class ItemList(RootModel[Annotated[list[int], Field(min_length=1)]]): - pass - - -@app.post("/items/") -async def create_items(items: ItemList): - return items - -``` - -FastAPI supports these type annotations and will create a Pydantic `TypeAdapter` for them, so that types can work as normally and there's no need for the custom logic and types in RootModels. +FastAPI supports these type annotations and will create a Pydantic `TypeAdapter` for them, so types work normally without custom wrapper models. See [the Pydantic reference](references/pydantic.md). ## Use one HTTP operation per function -Don't mix HTTP operations in a single function, having one function per HTTP operation helps separate concerns and organize the code. - -Do this: +Don't mix HTTP operations in a single function. Having one function per HTTP operation helps separate concerns and organize the code. ```python from fastapi import FastAPI @@ -415,22 +318,4 @@ async def create_item(item: Item): return item ``` -instead of this: - -```python -# DO NOT DO THIS -from fastapi import FastAPI, Request -from pydantic import BaseModel - -app = FastAPI() - - -class Item(BaseModel): - name: str - - -@app.api_route("/items/", methods=["GET", "POST"]) -async def handle_items(request: Request): - if request.method == "GET": - return [] -``` +See [the path operation reference](references/path-operations.md) for more examples. diff --git a/fastapi/.agents/skills/fastapi/references/dependencies.md b/fastapi/.agents/skills/fastapi/references/dependencies.md index ca709096e..a562dd946 100644 --- a/fastapi/.agents/skills/fastapi/references/dependencies.md +++ b/fastapi/.agents/skills/fastapi/references/dependencies.md @@ -5,7 +5,7 @@ Use dependencies when: * They can't be declared in Pydantic validation and require additional logic * The logic depends on external resources or could block in any other way * Other dependencies need their results (it's a sub-dependency) -* The logic can be shared by multiple endpoints to do things like error early, authentication, etc. +* The logic can be shared by multiple endpoints to do things like error early, handle authentication, etc. * They need to handle cleanup (e.g., DB sessions, file handles), using dependencies with `yield` * Their logic needs input data from the request, like headers, query parameters, etc. @@ -53,7 +53,7 @@ def get_username(): try: yield "Rick" finally: - print("Cleanup up before response is sent") + print("Clean up before response is sent") UserNameDep = Annotated[str, Depends(get_username, scope="function")] diff --git a/fastapi/.agents/skills/fastapi/references/other-tools.md b/fastapi/.agents/skills/fastapi/references/other-tools.md index 58b19d096..b5b58cfd6 100644 --- a/fastapi/.agents/skills/fastapi/references/other-tools.md +++ b/fastapi/.agents/skills/fastapi/references/other-tools.md @@ -71,6 +71,6 @@ Prefer it over SQLAlchemy. ## HTTPX -Use HTTPX for handling HTTP communication (e.g. with other APIs). It support sync and async usage. +Use HTTPX for handling HTTP communication (e.g. with other APIs). It supports sync and async usage. Prefer it over Requests. diff --git a/fastapi/.agents/skills/fastapi/references/path-operations.md b/fastapi/.agents/skills/fastapi/references/path-operations.md new file mode 100644 index 000000000..1292c1774 --- /dev/null +++ b/fastapi/.agents/skills/fastapi/references/path-operations.md @@ -0,0 +1,93 @@ +# Path Operations and Routing + +## Including Routers + +When declaring routers, prefer to add router-level parameters like prefix, tags, and shared dependencies to the router itself instead of in `include_router()`. + +Do this: + +```python +from fastapi import APIRouter, FastAPI + +app = FastAPI() + +router = APIRouter(prefix="/items", tags=["items"]) + + +@router.get("/") +async def list_items(): + return [] + + +app.include_router(router) +``` + +Instead of: + +```python +# DO NOT DO THIS +from fastapi import APIRouter, FastAPI + +app = FastAPI() + +router = APIRouter() + + +@router.get("/") +async def list_items(): + return [] + + +app.include_router(router, prefix="/items", tags=["items"]) +``` + +There could be exceptions, but try to follow this convention. + +Apply shared dependencies at the router level via `dependencies=[Depends(...)]`. + +## Use one HTTP operation per function + +Don't mix HTTP operations in a single function. Having one function per HTTP operation helps separate concerns and organize the code. + +Do this: + +```python +from fastapi import FastAPI +from pydantic import BaseModel + +app = FastAPI() + + +class Item(BaseModel): + name: str + + +@app.get("/items/") +async def list_items(): + return [] + + +@app.post("/items/") +async def create_item(item: Item): + return item +``` + +Instead of: + +```python +# DO NOT DO THIS +from fastapi import FastAPI, Request +from pydantic import BaseModel + +app = FastAPI() + + +class Item(BaseModel): + name: str + + +@app.api_route("/items/", methods=["GET", "POST"]) +async def handle_items(request: Request): + if request.method == "GET": + return [] +``` diff --git a/fastapi/.agents/skills/fastapi/references/pydantic.md b/fastapi/.agents/skills/fastapi/references/pydantic.md new file mode 100644 index 000000000..fadf99c1a --- /dev/null +++ b/fastapi/.agents/skills/fastapi/references/pydantic.md @@ -0,0 +1,93 @@ +# Pydantic + +## Do not use Ellipsis + +Do not use `...` as a default value for required parameters or model fields. It's not needed and not recommended. + +Do this, without Ellipsis (`...`): + +```python +from typing import Annotated + +from fastapi import FastAPI, Query +from pydantic import BaseModel, Field + +app = FastAPI() + + +class Item(BaseModel): + name: str + description: str | None = None + price: float = Field(gt=0) + + +@app.post("/items/") +async def create_item(item: Item, project_id: Annotated[int, Query()]): + return item +``` + +Instead of: + +```python +# DO NOT DO THIS +from typing import Annotated + +from fastapi import FastAPI, Query +from pydantic import BaseModel, Field + +app = FastAPI() + + +class Item(BaseModel): + name: str = ... + description: str | None = None + price: float = Field(..., gt=0) + + +@app.post("/items/") +async def create_item(item: Item, project_id: Annotated[int, Query(...)]): + return item +``` + +## Do not use Pydantic RootModels + +Do not use Pydantic `RootModel`; instead use regular type annotations with `Annotated` and Pydantic validation utilities. + +For example, for a list with validations: + +```python +from typing import Annotated + +from fastapi import Body, FastAPI +from pydantic import Field + +app = FastAPI() + + +@app.post("/items/") +async def create_items(items: Annotated[list[int], Field(min_length=1), Body()]): + return items +``` + +Instead of: + +```python +# DO NOT DO THIS +from typing import Annotated + +from fastapi import FastAPI +from pydantic import Field, RootModel + +app = FastAPI() + + +class ItemList(RootModel[Annotated[list[int], Field(min_length=1)]]): + pass + + +@app.post("/items/") +async def create_items(items: ItemList): + return items +``` + +FastAPI supports these type annotations and will create a Pydantic `TypeAdapter` for them, so types work normally without custom wrapper models. diff --git a/fastapi/.agents/skills/fastapi/references/responses.md b/fastapi/.agents/skills/fastapi/references/responses.md new file mode 100644 index 000000000..09081236a --- /dev/null +++ b/fastapi/.agents/skills/fastapi/references/responses.md @@ -0,0 +1,79 @@ +# Responses + +## Return Type or Response Model + +When possible, include a return type. It will be used to validate, filter, document, and serialize the response. + +```python +from fastapi import FastAPI +from pydantic import BaseModel + +app = FastAPI() + + +class Item(BaseModel): + name: str + description: str | None = None + + +@app.get("/items/me") +async def get_item() -> Item: + return Item(name="Plumbus", description="All-purpose home device") +``` + +Return types or response models filter data to avoid exposing sensitive information. They also let Pydantic serialize data on the Rust side for performance. + +The return type doesn't have to be a Pydantic model. It can be a different type, like a list of integers, a dict, etc. + +## When to use `response_model` + +If the return type is not the same as the type that you want to use to validate, filter, or serialize, use the `response_model` parameter on the decorator. + +```python +from typing import Any + +from fastapi import FastAPI +from pydantic import BaseModel + +app = FastAPI() + + +class Item(BaseModel): + name: str + description: str | None = None + + +@app.get("/items/me", response_model=Item) +async def get_item() -> Any: + return {"name": "Foo", "description": "A very nice Item"} +``` + +This is particularly useful when filtering data to expose only the public fields and avoid exposing sensitive information. + +```python +from typing import Any + +from fastapi import FastAPI +from pydantic import BaseModel + +app = FastAPI() + + +class InternalItem(BaseModel): + name: str + description: str | None = None + secret_key: str + + +class Item(BaseModel): + name: str + description: str | None = None + + +@app.get("/items/me", response_model=Item) +async def get_item() -> Any: + item = InternalItem( + name="Foo", description="A very nice Item", secret_key="supersecret" + ) + return item +``` diff --git a/fastapi/__init__.py b/fastapi/__init__.py index 38e747232..af5117aec 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.136.3" +__version__ = "0.138.2" from starlette import status as status diff --git a/fastapi/applications.py b/fastapi/applications.py index faac6853f..56e1a3e60 100644 --- a/fastapi/applications.py +++ b/fastapi/applications.py @@ -1,6 +1,7 @@ +import os from collections.abc import Awaitable, Callable, Coroutine, Sequence from enum import Enum -from typing import Annotated, Any, TypeVar +from typing import Annotated, Any, Literal, TypeVar from annotated_doc import Doc from fastapi import routing @@ -921,6 +922,7 @@ class FastAPI(Starlette): ), ] = "3.1.0" self.openapi_schema: dict[str, Any] | None = None + self._openapi_routes_version: int | None = None if self.openapi_url: assert self.title, "A title must be provided for OpenAPI, e.g.: 'My API'" assert self.version, "A version must be provided for OpenAPI, e.g.: '2.1.0'" @@ -1079,7 +1081,8 @@ class FastAPI(Starlette): Read more in the [FastAPI docs for OpenAPI](https://fastapi.tiangolo.com/how-to/extending-openapi/). """ - if not self.openapi_schema: + routes_version = self.router._get_routes_version() + if not self.openapi_schema or self._openapi_routes_version != routes_version: self.openapi_schema = get_openapi( title=self.title, version=self.version, @@ -1096,6 +1099,7 @@ class FastAPI(Starlette): separate_input_output_schemas=self.separate_input_output_schemas, external_docs=self.openapi_external_docs, ) + self._openapi_routes_version = routes_version return self.openapi_schema def setup(self) -> None: @@ -1215,6 +1219,79 @@ class FastAPI(Starlette): generate_unique_id_function=generate_unique_id_function, ) + def frontend( + self, + path: Annotated[ + str, + Doc( + """ + The URL path prefix where the frontend build should be served. + """ + ), + ], + *, + directory: Annotated[ + str | os.PathLike[str], + Doc( + """ + The directory containing the static frontend build output. + """ + ), + ], + fallback: Annotated[ + Literal["auto", "index.html", "404.html"] | None, + Doc( + """ + The fallback file behavior for missing frontend paths. + """ + ), + ] = "auto", + check_dir: Annotated[ + bool, + Doc( + """ + Check that the frontend directory exists when the app is created. + """ + ), + ] = True, + ) -> None: + """ + Serve a static frontend build as low-priority routes. + + Use this for frontend tools that build static files into a directory, + such as `dist`. **FastAPI** path operations are checked first, and + the frontend files are checked only if no normal route matched. + + A typical project could look like this: + + ```text + . + ├── pyproject.toml + ├── app + │ ├── __init__.py + │ └── main.py + └── dist + ├── index.html + └── assets + └── app.js + ``` + + Then in `app/main.py`: + + ```python + from fastapi import FastAPI + + app = FastAPI() + app.frontend("/", directory="dist") + ``` + """ + self.router.frontend( + path, + directory=directory, + fallback=fallback, + check_dir=check_dir, + ) + def api_route( self, path: str, diff --git a/fastapi/openapi/utils.py b/fastapi/openapi/utils.py index 1c7a17c4c..2e0aca118 100644 --- a/fastapi/openapi/utils.py +++ b/fastapi/openapi/utils.py @@ -213,7 +213,7 @@ def get_openapi_operation_request_body( def generate_operation_id( - *, route: routing.APIRoute, method: str + *, route: routing._APIRouteLike, method: str ) -> str: # pragma: nocover warnings.warn( message="fastapi.openapi.utils.generate_operation_id() was deprecated, " @@ -227,14 +227,14 @@ def generate_operation_id( return generate_operation_id_for_path(name=route.name, path=path, method=method) -def generate_operation_summary(*, route: routing.APIRoute, method: str) -> str: +def generate_operation_summary(*, route: routing._APIRouteLike, method: str) -> str: if route.summary: return route.summary return route.name.replace("_", " ").title() def get_openapi_operation_metadata( - *, route: routing.APIRoute, method: str, operation_ids: set[str] + *, route: routing._APIRouteLike, method: str, operation_ids: set[str] ) -> dict[str, Any]: operation: dict[str, Any] = {} if route.tags: @@ -259,7 +259,7 @@ def get_openapi_operation_metadata( def get_openapi_path( *, - route: routing.APIRoute, + route: routing._APIRouteLike, operation_ids: set[str], model_name_map: ModelNameMap, field_mapping: dict[ @@ -329,7 +329,7 @@ def get_openapi_path( cb_security_schemes, cb_definitions, ) = get_openapi_path( - route=callback, + route=cast(routing._APIRouteLike, callback), operation_ids=operation_ids, model_name_map=model_name_map, field_mapping=field_mapping, @@ -478,31 +478,40 @@ def get_openapi_path( return path, security_schemes, definitions +def _get_api_route_for_openapi( + route_context: routing.RouteContext, +) -> routing._APIRouteLike | None: + if isinstance(route_context.original_route, routing.APIRoute): + return cast(routing._APIRouteLike, route_context) + return None + + def get_fields_from_routes( - routes: Sequence[BaseRoute], + routes: Sequence[BaseRoute | routing.RouteContext], ) -> list[ModelField]: body_fields_from_routes: list[ModelField] = [] responses_from_routes: list[ModelField] = [] request_fields_from_routes: list[ModelField] = [] callback_flat_models: list[ModelField] = [] - for route in routes: - if not isinstance(route, routing.APIRoute): + for route_context in routing.iter_route_contexts(routes): + api_route = _get_api_route_for_openapi(route_context) + if api_route is None: continue - if route.include_in_schema: - if route.body_field: - assert isinstance(route.body_field, ModelField), ( + if api_route.include_in_schema: + if api_route.body_field: + assert isinstance(api_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) - if route.response_fields: - responses_from_routes.extend(route.response_fields.values()) - if route.stream_item_field: - responses_from_routes.append(route.stream_item_field) - if route.callbacks: - callback_flat_models.extend(get_fields_from_routes(route.callbacks)) - params = get_flat_params(route.dependant) + body_fields_from_routes.append(api_route.body_field) + if api_route.response_field: + responses_from_routes.append(api_route.response_field) + if api_route.response_fields: + responses_from_routes.extend(api_route.response_fields.values()) + if api_route.stream_item_field: + responses_from_routes.append(api_route.stream_item_field) + if api_route.callbacks: + callback_flat_models.extend(get_fields_from_routes(api_route.callbacks)) + params = get_flat_params(api_route.dependant) request_fields_from_routes.extend(params) flat_models = callback_flat_models + list( @@ -518,8 +527,8 @@ def get_openapi( openapi_version: str = "3.1.0", summary: str | None = None, description: str | None = None, - routes: Sequence[BaseRoute], - webhooks: Sequence[BaseRoute] | None = None, + routes: Sequence[BaseRoute | routing.RouteContext], + webhooks: Sequence[BaseRoute | routing.RouteContext] | None = None, tags: list[dict[str, Any]] | None = None, servers: list[dict[str, str | Any]] | None = None, terms_of_service: str | None = None, @@ -546,7 +555,7 @@ def get_openapi( paths: dict[str, dict[str, Any]] = {} webhook_paths: dict[str, dict[str, Any]] = {} operation_ids: set[str] = set() - all_fields = get_fields_from_routes(list(routes or []) + list(webhooks or [])) + all_fields = get_fields_from_routes(list(routes) + list(webhooks or [])) flat_models = get_flat_models_from_fields(all_fields, known_models=set()) model_name_map = get_model_name_map(flat_models) field_mapping, definitions = get_definitions( @@ -554,10 +563,11 @@ def get_openapi( model_name_map=model_name_map, separate_input_output_schemas=separate_input_output_schemas, ) - for route in routes or []: - if isinstance(route, routing.APIRoute): + for route_context in routing.iter_route_contexts(routes): + api_route = _get_api_route_for_openapi(route_context) + if api_route is not None: result = get_openapi_path( - route=route, + route=api_route, operation_ids=operation_ids, model_name_map=model_name_map, field_mapping=field_mapping, @@ -566,17 +576,18 @@ def get_openapi( if result: path, security_schemes, path_definitions = result if path: - paths.setdefault(route.path_format, {}).update(path) + paths.setdefault(api_route.path_format, {}).update(path) if security_schemes: components.setdefault("securitySchemes", {}).update( security_schemes ) if path_definitions: definitions.update(path_definitions) - for webhook in webhooks or []: - if isinstance(webhook, routing.APIRoute): + for webhook_context in routing.iter_route_contexts(webhooks or []): + api_webhook = _get_api_route_for_openapi(webhook_context) + if api_webhook is not None: result = get_openapi_path( - route=webhook, + route=api_webhook, operation_ids=operation_ids, model_name_map=model_name_map, field_mapping=field_mapping, @@ -585,7 +596,7 @@ def get_openapi( if result: path, security_schemes, path_definitions = result if path: - webhook_paths.setdefault(webhook.path_format, {}).update(path) + webhook_paths.setdefault(api_webhook.path_format, {}).update(path) if security_schemes: components.setdefault("securitySchemes", {}).update( security_schemes diff --git a/fastapi/routing.py b/fastapi/routing.py index aa1b37d51..c9a021df3 100644 --- a/fastapi/routing.py +++ b/fastapi/routing.py @@ -1,8 +1,12 @@ import contextlib +import copy import email.message +import errno import functools import inspect import json +import os +import stat import types from collections.abc import ( AsyncIterator, @@ -21,10 +25,14 @@ from contextlib import ( AsyncExitStack, asynccontextmanager, ) +from contextvars import ContextVar +from dataclasses import dataclass, field from enum import Enum, IntEnum from typing import ( Annotated, Any, + Literal, + Protocol, TypeVar, cast, ) @@ -74,19 +82,27 @@ from fastapi.utils import ( ) from starlette import routing from starlette._exception_handler import wrap_app_handling_exceptions -from starlette._utils import is_async_callable +from starlette._utils import get_route_path, is_async_callable from starlette.concurrency import iterate_in_threadpool, run_in_threadpool -from starlette.datastructures import FormData +from starlette.datastructures import URL, FormData, URLPath from starlette.exceptions import HTTPException from starlette.requests import Request -from starlette.responses import JSONResponse, Response, StreamingResponse +from starlette.responses import ( + JSONResponse, + PlainTextResponse, + RedirectResponse, + Response, + StreamingResponse, +) from starlette.routing import ( BaseRoute, Match, + NoMatchFound, compile_path, get_name, ) from starlette.routing import Mount as Mount # noqa +from starlette.staticfiles import StaticFiles from starlette.types import AppType, ASGIApp, Lifespan, Receive, Scope, Send from starlette.websockets import WebSocket from typing_extensions import deprecated @@ -806,7 +822,300 @@ class APIWebSocketRoute(routing.WebSocketRoute): return match, child_scope +_FASTAPI_SCOPE_KEY = "fastapi" +_FASTAPI_EFFECTIVE_ROUTE_CONTEXT_KEY = "effective_route_context" +_FASTAPI_FRONTEND_PATH_KEY = "frontend_path" +_FASTAPI_INCLUDED_ROUTER_KEY = "included_router" +_effective_route_context_var: ContextVar[Any | None] = ContextVar( + "fastapi_effective_route_context", default=None +) +_SCOPE_MISSING = object() + + +class _RouteWithPath(Protocol): + path: str + + +def _get_fastapi_scope(scope: Scope) -> dict[str, Any]: + fastapi_scope = scope.setdefault(_FASTAPI_SCOPE_KEY, {}) + assert isinstance(fastapi_scope, dict) + return fastapi_scope + + +def _update_scope(scope: Scope, child_scope: Scope) -> None: + fastapi_child_scope = child_scope.get(_FASTAPI_SCOPE_KEY) + for key, value in child_scope.items(): + if key != _FASTAPI_SCOPE_KEY: + scope[key] = value + if isinstance(fastapi_child_scope, dict): + _get_fastapi_scope(scope).update(fastapi_child_scope) + + +def _get_scope_effective_route_context(scope: Scope) -> Any | None: + return scope.get(_FASTAPI_SCOPE_KEY, {}).get(_FASTAPI_EFFECTIVE_ROUTE_CONTEXT_KEY) + + +def _get_scope_included_router(scope: Scope) -> Any | None: + return scope.get(_FASTAPI_SCOPE_KEY, {}).get(_FASTAPI_INCLUDED_ROUTER_KEY) + + +def _restore_fastapi_scope_key(scope: Scope, key: str, previous: Any) -> None: + fastapi_scope = scope.get(_FASTAPI_SCOPE_KEY) + if not isinstance(fastapi_scope, dict): + return + if previous is _SCOPE_MISSING: + fastapi_scope.pop(key, None) + else: + fastapi_scope[key] = previous + + +class _APIRouteLike(Protocol): + path: str + endpoint: Callable[..., Any] + stream_item_type: Any | None + response_model: Any + summary: str | None + response_description: str + deprecated: bool | None + operation_id: str | None + response_model_include: IncEx | None + response_model_exclude: IncEx | None + response_model_by_alias: bool + response_model_exclude_unset: bool + response_model_exclude_defaults: bool + response_model_exclude_none: bool + include_in_schema: bool + response_class: type[Response] | DefaultPlaceholder + dependency_overrides_provider: Any | None + callbacks: list[BaseRoute] | None + openapi_extra: dict[str, Any] | None + generate_unique_id_function: Callable[[Any], str] | DefaultPlaceholder + strict_content_type: bool | DefaultPlaceholder + tags: list[str | Enum] + responses: dict[int | str, dict[str, Any]] + name: str + path_regex: Any + path_format: str + param_convertors: dict[str, Any] + methods: set[str] + unique_id: str + status_code: int | None + response_field: ModelField | None + stream_item_field: ModelField | None + dependencies: list[params.Depends] + description: str + response_fields: dict[int | str, ModelField] + dependant: Dependant + _flat_dependant: Dependant + _embed_body_fields: bool + body_field: ModelField | None + is_sse_stream: bool + is_json_stream: bool + + +def _populate_api_route_state( + route: _APIRouteLike, + path: str, + endpoint: Callable[..., Any], + *, + response_model: Any = Default(None), + status_code: int | None = None, + tags: list[str | Enum] | None = None, + dependencies: Sequence[params.Depends] | None = None, + summary: str | None = None, + description: str | None = None, + response_description: str = "Successful Response", + responses: dict[int | str, dict[str, Any]] | None = None, + deprecated: bool | None = None, + name: str | None = None, + methods: set[str] | list[str] | None = None, + operation_id: str | None = None, + response_model_include: IncEx | None = None, + response_model_exclude: IncEx | None = None, + response_model_by_alias: bool = True, + response_model_exclude_unset: bool = False, + response_model_exclude_defaults: bool = False, + response_model_exclude_none: bool = False, + include_in_schema: bool = True, + response_class: type[Response] | DefaultPlaceholder = Default(JSONResponse), + dependency_overrides_provider: Any | None = None, + callbacks: list[BaseRoute] | None = None, + openapi_extra: dict[str, Any] | None = None, + generate_unique_id_function: Callable[[Any], str] | DefaultPlaceholder = Default( + generate_unique_id + ), + strict_content_type: bool | DefaultPlaceholder = Default(True), +) -> None: + route.path = path + route.endpoint = endpoint + route.stream_item_type = None + if isinstance(response_model, DefaultPlaceholder): + return_annotation = get_typed_return_annotation(endpoint) + if lenient_issubclass(return_annotation, Response): + response_model = None + else: + stream_item = get_stream_item_type(return_annotation) + if stream_item is not None: + # Extract item type for JSONL or SSE streaming when + # response_class is DefaultPlaceholder (JSONL) or + # EventSourceResponse (SSE). + # ServerSentEvent is excluded: it's a transport + # wrapper, not a data model, so it shouldn't feed + # into validation or OpenAPI schema generation. + if ( + isinstance(response_class, DefaultPlaceholder) + or lenient_issubclass(response_class, EventSourceResponse) + ) and not lenient_issubclass(stream_item, ServerSentEvent): + route.stream_item_type = stream_item + response_model = None + else: + response_model = return_annotation + route.response_model = response_model + route.summary = summary + route.response_description = response_description + route.deprecated = deprecated + route.operation_id = operation_id + route.response_model_include = response_model_include + route.response_model_exclude = response_model_exclude + route.response_model_by_alias = response_model_by_alias + route.response_model_exclude_unset = response_model_exclude_unset + route.response_model_exclude_defaults = response_model_exclude_defaults + route.response_model_exclude_none = response_model_exclude_none + route.include_in_schema = include_in_schema + route.response_class = response_class + route.dependency_overrides_provider = dependency_overrides_provider + route.callbacks = callbacks + route.openapi_extra = openapi_extra + route.generate_unique_id_function = generate_unique_id_function + route.strict_content_type = strict_content_type + route.tags = tags or [] + route.responses = responses or {} + route.name = get_name(endpoint) if name is None else name + route.path_regex, route.path_format, route.param_convertors = compile_path(path) + if methods is None: + methods = ["GET"] + route.methods = {method.upper() for method in methods} + if isinstance(generate_unique_id_function, DefaultPlaceholder): + current_generate_unique_id: Callable[[Any], str] = ( + generate_unique_id_function.value + ) + else: + current_generate_unique_id = generate_unique_id_function + route.unique_id = route.operation_id or current_generate_unique_id(route) + # normalize enums e.g. http.HTTPStatus + if isinstance(status_code, IntEnum): + status_code = int(status_code) + route.status_code = status_code + if route.response_model: + assert is_body_allowed_for_status_code(status_code), ( + f"Status code {status_code} must not have a response body" + ) + response_name = "Response_" + route.unique_id + route.response_field = create_model_field( + name=response_name, + type_=route.response_model, + mode="serialization", + ) + else: + route.response_field = None + if route.stream_item_type: + stream_item_name = "StreamItem_" + route.unique_id + route.stream_item_field = create_model_field( + name=stream_item_name, + type_=route.stream_item_type, + mode="serialization", + ) + else: + route.stream_item_field = None + route.dependencies = list(dependencies or []) + route.description = description or inspect.cleandoc(route.endpoint.__doc__ or "") + # if a "form feed" character (page break) is found in the description text, + # truncate description text to the content preceding the first "form feed" + route.description = route.description.split("\f")[0].strip() + response_fields = {} + for additional_status_code, response in route.responses.items(): + 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" + ) + response_name = f"Response_{additional_status_code}_{route.unique_id}" + response_field = create_model_field( + name=response_name, type_=model, mode="serialization" + ) + response_fields[additional_status_code] = response_field + if response_fields: + route.response_fields = response_fields + else: + route.response_fields = {} + + assert callable(endpoint), "An endpoint must be a callable" + route.dependant = get_dependant( + path=route.path_format, call=route.endpoint, scope="function" + ) + for depends in route.dependencies[::-1]: + route.dependant.dependencies.insert( + 0, + get_parameterless_sub_dependant(depends=depends, path=route.path_format), + ) + route._flat_dependant = get_flat_dependant(route.dependant) + route._embed_body_fields = _should_embed_body_fields( + route._flat_dependant.body_params + ) + route.body_field = get_body_field( + flat_dependant=route._flat_dependant, + name=route.unique_id, + embed_body_fields=route._embed_body_fields, + ) + # Detect generator endpoints that should stream as JSONL or SSE + is_generator = ( + route.dependant.is_async_gen_callable or route.dependant.is_gen_callable + ) + route.is_sse_stream = is_generator and lenient_issubclass( + response_class, EventSourceResponse + ) + route.is_json_stream = is_generator and isinstance( + response_class, DefaultPlaceholder + ) + + class APIRoute(routing.Route): + stream_item_type: Any | None + response_model: Any + summary: str | None + response_description: str + deprecated: bool | None + operation_id: str | None + response_model_include: IncEx | None + response_model_exclude: IncEx | None + response_model_by_alias: bool + response_model_exclude_unset: bool + response_model_exclude_defaults: bool + response_model_exclude_none: bool + include_in_schema: bool + response_class: type[Response] | DefaultPlaceholder + dependency_overrides_provider: Any | None + callbacks: list[BaseRoute] | None + openapi_extra: dict[str, Any] | None + generate_unique_id_function: Callable[[Any], str] | DefaultPlaceholder + strict_content_type: bool | DefaultPlaceholder + tags: list[str | Enum] + responses: dict[int | str, dict[str, Any]] + unique_id: str + status_code: int | None + response_field: ModelField | None + stream_item_field: ModelField | None + dependencies: list[params.Depends] + description: str + response_fields: dict[int | str, ModelField] + dependant: Dependant + _flat_dependant: Dependant + _embed_body_fields: bool + body_field: ModelField | None + is_sse_stream: bool + is_json_stream: bool + def __init__( self, path: str, @@ -839,166 +1148,925 @@ class APIRoute(routing.Route): | DefaultPlaceholder = Default(generate_unique_id), strict_content_type: bool | DefaultPlaceholder = Default(True), ) -> None: - self.path = path - self.endpoint = endpoint - self.stream_item_type: Any | None = None - if isinstance(response_model, DefaultPlaceholder): - return_annotation = get_typed_return_annotation(endpoint) - if lenient_issubclass(return_annotation, Response): - response_model = None - else: - stream_item = get_stream_item_type(return_annotation) - if stream_item is not None: - # Extract item type for JSONL or SSE streaming when - # response_class is DefaultPlaceholder (JSONL) or - # EventSourceResponse (SSE). - # ServerSentEvent is excluded: it's a transport - # wrapper, not a data model, so it shouldn't feed - # into validation or OpenAPI schema generation. - if ( - isinstance(response_class, DefaultPlaceholder) - or lenient_issubclass(response_class, EventSourceResponse) - ) and not lenient_issubclass(stream_item, ServerSentEvent): - self.stream_item_type = stream_item - response_model = None - else: - response_model = return_annotation - self.response_model = response_model - self.summary = summary - self.response_description = response_description - self.deprecated = deprecated - self.operation_id = operation_id - self.response_model_include = response_model_include - self.response_model_exclude = response_model_exclude - self.response_model_by_alias = response_model_by_alias - self.response_model_exclude_unset = response_model_exclude_unset - self.response_model_exclude_defaults = response_model_exclude_defaults - self.response_model_exclude_none = response_model_exclude_none - self.include_in_schema = include_in_schema - self.response_class = response_class - self.dependency_overrides_provider = dependency_overrides_provider - self.callbacks = callbacks - self.openapi_extra = openapi_extra - self.generate_unique_id_function = generate_unique_id_function - self.strict_content_type = strict_content_type - self.tags = tags or [] - self.responses = responses or {} - self.name = get_name(endpoint) if name is None else name - self.path_regex, self.path_format, self.param_convertors = compile_path(path) - if methods is None: - methods = ["GET"] - self.methods: set[str] = {method.upper() for method in methods} - if isinstance(generate_unique_id_function, DefaultPlaceholder): - current_generate_unique_id: Callable[[APIRoute], str] = ( - generate_unique_id_function.value - ) + _populate_api_route_state( + cast(_APIRouteLike, self), + path, + endpoint, + response_model=response_model, + status_code=status_code, + tags=tags, + dependencies=dependencies, + summary=summary, + description=description, + response_description=response_description, + responses=responses, + deprecated=deprecated, + name=name, + methods=methods, + operation_id=operation_id, + response_model_include=response_model_include, + response_model_exclude=response_model_exclude, + response_model_by_alias=response_model_by_alias, + response_model_exclude_unset=response_model_exclude_unset, + response_model_exclude_defaults=response_model_exclude_defaults, + response_model_exclude_none=response_model_exclude_none, + include_in_schema=include_in_schema, + response_class=response_class, + dependency_overrides_provider=dependency_overrides_provider, + callbacks=callbacks, + openapi_extra=openapi_extra, + generate_unique_id_function=generate_unique_id_function, + strict_content_type=strict_content_type, + ) + self.app = request_response(self.get_route_handler()) + + def get_route_handler(self) -> Callable[[Request], Coroutine[Any, Any, Response]]: + route = cast(_APIRouteLike, self) + # TODO: Replace or deprecate this no-scope hook so included-route + # effective context can be passed explicitly instead of via ContextVar. + effective_context = _effective_route_context_var.get() + if effective_context is not None and effective_context.original_route is self: + route = cast(_APIRouteLike, effective_context) + return get_request_handler( + dependant=route.dependant, + body_field=route.body_field, + status_code=route.status_code, + response_class=route.response_class, + response_field=route.response_field, + response_model_include=route.response_model_include, + response_model_exclude=route.response_model_exclude, + response_model_by_alias=route.response_model_by_alias, + response_model_exclude_unset=route.response_model_exclude_unset, + response_model_exclude_defaults=route.response_model_exclude_defaults, + response_model_exclude_none=route.response_model_exclude_none, + dependency_overrides_provider=route.dependency_overrides_provider, + embed_body_fields=route._embed_body_fields, + strict_content_type=route.strict_content_type, + stream_item_field=route.stream_item_field, + is_json_stream=route.is_json_stream, + ) + + def matches(self, scope: Scope) -> tuple[Match, Scope]: + effective_context = _get_scope_effective_route_context(scope) + if effective_context is not None and effective_context.original_route is self: + match, child_scope = effective_context.matches(scope) else: - current_generate_unique_id = generate_unique_id_function - self.unique_id = self.operation_id or current_generate_unique_id(self) - # normalize enums e.g. http.HTTPStatus - if isinstance(status_code, IntEnum): - 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" + match, child_scope = super().matches(scope) + if match != Match.NONE: + child_scope["route"] = self + return match, child_scope + + async def handle(self, scope: Scope, receive: Receive, send: Send) -> None: + effective_context = _get_scope_effective_route_context(scope) + if effective_context is not None and effective_context.original_route is self: + methods = effective_context.methods + if methods and scope["method"] not in methods: + headers = {"Allow": ", ".join(methods)} + if "app" in scope: + raise HTTPException(status_code=405, headers=headers) + response = PlainTextResponse( + "Method Not Allowed", status_code=405, headers=headers + ) + await response(scope, receive, send) + return + token = _effective_route_context_var.set(effective_context) + try: + app = request_response(self.get_route_handler()) + finally: + _effective_route_context_var.reset(token) + await app(scope, receive, send) + return + await super().handle(scope, receive, send) + + +@dataclass +class _RouterIncludeContext: + included_router: "APIRouter" + prefix: str = "" + tags: list[str | Enum] = field(default_factory=list) + dependencies: list[params.Depends] = field(default_factory=list) + default_response_class: type[Response] | DefaultPlaceholder = field( + default_factory=lambda: Default(JSONResponse) + ) + responses: dict[int | str, dict[str, Any]] = field(default_factory=dict) + callbacks: list[BaseRoute] = field(default_factory=list) + deprecated: bool | None = None + include_in_schema: bool = True + generate_unique_id_function: Callable[[APIRoute], str] | DefaultPlaceholder = field( + default_factory=lambda: Default(generate_unique_id) + ) + strict_content_type: bool | DefaultPlaceholder = field( + default_factory=lambda: Default(True) + ) + dependency_overrides_provider: Any | None = None + + @classmethod + def for_include( + cls, + *, + parent_router: "APIRouter", + included_router: "APIRouter", + prefix: str = "", + tags: list[str | Enum] | None = None, + dependencies: Sequence[params.Depends] | None = None, + default_response_class: type[Response] | DefaultPlaceholder = Default( + JSONResponse + ), + responses: dict[int | str, dict[str, Any]] | None = None, + callbacks: list[BaseRoute] | None = None, + deprecated: bool | None = None, + include_in_schema: bool = True, + generate_unique_id_function: Callable[[APIRoute], str] + | DefaultPlaceholder = Default(generate_unique_id), + ) -> "_RouterIncludeContext": + return cls( + included_router=included_router, + prefix=parent_router.prefix + prefix, + tags=[*parent_router.tags, *(tags or [])], + dependencies=[*parent_router.dependencies, *(dependencies or [])], + default_response_class=get_value_or_default( + default_response_class, parent_router.default_response_class + ), + responses={**parent_router.responses, **(responses or {})}, + callbacks=[*parent_router.callbacks, *(callbacks or [])], + deprecated=deprecated or parent_router.deprecated, + include_in_schema=parent_router.include_in_schema and include_in_schema, + generate_unique_id_function=get_value_or_default( + generate_unique_id_function, parent_router.generate_unique_id_function + ), + strict_content_type=parent_router.strict_content_type, + dependency_overrides_provider=parent_router.dependency_overrides_provider, + ) + + def combine( + self, child_context: "_RouterIncludeContext" + ) -> "_RouterIncludeContext": + return _RouterIncludeContext( + included_router=child_context.included_router, + prefix=self.prefix + child_context.prefix, + tags=[*self.tags, *child_context.tags], + dependencies=[*self.dependencies, *child_context.dependencies], + default_response_class=get_value_or_default( + child_context.default_response_class, self.default_response_class + ), + responses={**self.responses, **child_context.responses}, + callbacks=[*self.callbacks, *child_context.callbacks], + deprecated=self.deprecated or child_context.deprecated, + include_in_schema=self.include_in_schema + and child_context.include_in_schema, + generate_unique_id_function=get_value_or_default( + child_context.generate_unique_id_function, + self.generate_unique_id_function, + ), + strict_content_type=get_value_or_default( + child_context.strict_content_type, self.strict_content_type + ), + dependency_overrides_provider=self.dependency_overrides_provider, + ) + + def path_for(self, route: _RouteWithPath) -> str: + return self.prefix + route.path + + +@dataclass +class _EffectiveRouteContext: + original_route: BaseRoute + starlette_route: BaseRoute | None = None + path: str = "" + endpoint: Callable[..., Any] | None = None + stream_item_type: Any | None = None + response_model: Any = None + summary: str | None = None + response_description: str = "Successful Response" + deprecated: bool | None = None + operation_id: str | None = None + response_model_include: IncEx | None = None + response_model_exclude: IncEx | None = None + response_model_by_alias: bool = True + response_model_exclude_unset: bool = False + response_model_exclude_defaults: bool = False + response_model_exclude_none: bool = False + include_in_schema: bool = True + response_class: type[Response] | DefaultPlaceholder = field( + default_factory=lambda: Default(JSONResponse) + ) + dependency_overrides_provider: Any | None = None + callbacks: list[BaseRoute] | None = None + openapi_extra: dict[str, Any] | None = None + generate_unique_id_function: Callable[[Any], str] | DefaultPlaceholder = field( + default_factory=lambda: Default(generate_unique_id) + ) + strict_content_type: bool | DefaultPlaceholder = field( + default_factory=lambda: Default(True) + ) + tags: list[str | Enum] = field(default_factory=list) + responses: dict[int | str, dict[str, Any]] = field(default_factory=dict) + name: str = "" + path_regex: Any = None + path_format: str = "" + param_convertors: dict[str, Any] = field(default_factory=dict) + methods: set[str] = field(default_factory=set) + unique_id: str = "" + status_code: int | None = None + response_field: ModelField | None = None + stream_item_field: ModelField | None = None + dependencies: list[params.Depends] = field(default_factory=list) + description: str = "" + response_fields: dict[int | str, ModelField] = field(default_factory=dict) + dependant: Dependant | None = None + _flat_dependant: Dependant | None = None + _embed_body_fields: bool = False + body_field: ModelField | None = None + is_sse_stream: bool = False + is_json_stream: bool = False + + @classmethod + def from_api_route( + cls, + *, + original_route: APIRoute, + include_context: _RouterIncludeContext, + ) -> "_EffectiveRouteContext": + route = cast(_APIRouteLike, original_route) + context = cls(original_route=original_route) + _populate_api_route_state( + cast(_APIRouteLike, context), + include_context.path_for(original_route), + route.endpoint, + response_model=route.response_model, + status_code=route.status_code, + tags=[*include_context.tags, *route.tags], + dependencies=[*include_context.dependencies, *route.dependencies], + summary=route.summary, + description=route.description, + response_description=route.response_description, + responses={**include_context.responses, **route.responses}, + deprecated=route.deprecated or include_context.deprecated, + methods=route.methods, + operation_id=route.operation_id, + response_model_include=route.response_model_include, + response_model_exclude=route.response_model_exclude, + response_model_by_alias=route.response_model_by_alias, + response_model_exclude_unset=route.response_model_exclude_unset, + response_model_exclude_defaults=route.response_model_exclude_defaults, + response_model_exclude_none=route.response_model_exclude_none, + include_in_schema=route.include_in_schema + and include_context.include_in_schema, + response_class=get_value_or_default( + route.response_class, + include_context.included_router.default_response_class, + include_context.default_response_class, + ), + name=route.name, + dependency_overrides_provider=include_context.dependency_overrides_provider, + callbacks=[*include_context.callbacks, *(route.callbacks or [])], + openapi_extra=route.openapi_extra, + generate_unique_id_function=get_value_or_default( + route.generate_unique_id_function, + include_context.included_router.generate_unique_id_function, + include_context.generate_unique_id_function, + ), + strict_content_type=get_value_or_default( + route.strict_content_type, + include_context.included_router.strict_content_type, + include_context.strict_content_type, + ), + ) + return context + + def matches(self, scope: Scope) -> tuple[Match, Scope]: + if not isinstance(self.original_route, APIRoute): + assert self.starlette_route is not None + return self.starlette_route.matches(scope) + if scope["type"] != "http": + return Match.NONE, {} + route_path = get_route_path(scope) + match = self.path_regex.match(route_path) + if not match: + return Match.NONE, {} + matched_params = match.groupdict() + for key, value in matched_params.items(): + matched_params[key] = self.param_convertors[key].convert(value) + path_params = dict(scope.get("path_params", {})) + path_params.update(matched_params) + child_scope = {"endpoint": self.endpoint, "path_params": path_params} + methods = self.methods + if methods and scope["method"] not in methods: + return Match.PARTIAL, child_scope + return Match.FULL, child_scope + + def url_path_for(self, name: str, /, **path_params: Any) -> Any: + if not isinstance(self.original_route, APIRoute): + assert self.starlette_route is not None + return self.starlette_route.url_path_for(name, **path_params) + seen_params = set(path_params.keys()) + param_convertors = self.param_convertors + expected_params = set(param_convertors.keys()) + if name != self.name or seen_params != expected_params: + raise routing.NoMatchFound(name, path_params) + path, remaining_params = routing.replace_params( + self.path_format, param_convertors, path_params + ) + assert not remaining_params + return URLPath(path=path, protocol="http") + + +@dataclass(frozen=True) +class RouteContext: + route: BaseRoute + _route_context: _EffectiveRouteContext | None = field(default=None, repr=False) + + @property + def original_route(self) -> BaseRoute: + if self._route_context is not None: + return self._route_context.original_route + return self.route + + @property + def _effective_route(self) -> BaseRoute | _EffectiveRouteContext: + if self._route_context is not None: + return self._route_context + return self.route + + @property + def path(self) -> str | None: + return getattr(self._effective_route, "path", None) + + @property + def path_format(self) -> str | None: + return getattr(self._effective_route, "path_format", None) + + @property + def name(self) -> str | None: + return getattr(self._effective_route, "name", None) + + @property + def methods(self) -> set[str] | None: + return getattr(self._effective_route, "methods", None) + + @property + def endpoint(self) -> Callable[..., Any] | None: + return getattr(self._effective_route, "endpoint", None) + + def __getattr__(self, name: str) -> Any: + return getattr(self._effective_route, name) + + +@dataclass +class _IncludedRouter(BaseRoute): + original_router: "APIRouter" + include_context: _RouterIncludeContext + _effective_candidates: list["_EffectiveRouteContext | _IncludedRouter"] = field( + default_factory=list + ) + _effective_candidates_version: int | None = None + _effective_low_priority_routes: list["_EffectiveRouteContext"] = field( + default_factory=list + ) + _effective_low_priority_routes_version: int | None = None + + def effective_candidates(self) -> list["_EffectiveRouteContext | _IncludedRouter"]: + routes_version = self.original_router._get_routes_version() + if routes_version == self._effective_candidates_version: + return self._effective_candidates + self._effective_candidates = [] + candidates = self.original_router.routes + for route in candidates: + if isinstance(route, _IncludedRouter): + child_context = self.include_context.combine(route.include_context) + child_branch = _IncludedRouter( + original_router=route.original_router, + include_context=child_context, + ) + self._effective_candidates.append(child_branch) + continue + route_context = self._build_effective_context(route) + if route_context is not None: + self._effective_candidates.append(route_context) + self._effective_candidates_version = routes_version + return self._effective_candidates + + def effective_low_priority_routes(self) -> list["_EffectiveRouteContext"]: + routes_version = self.original_router._get_routes_version() + if routes_version == self._effective_low_priority_routes_version: + return self._effective_low_priority_routes + self._effective_low_priority_routes = [] + for route in self.original_router._low_priority_routes: + route_context = self._build_effective_context(route) + if route_context is not None: + self._effective_low_priority_routes.append(route_context) + for route in self.original_router.routes: + if isinstance(route, _IncludedRouter): + child_context = self.include_context.combine(route.include_context) + child_branch = _IncludedRouter( + original_router=route.original_router, + include_context=child_context, + ) + self._effective_low_priority_routes.extend( + child_branch.effective_low_priority_routes() + ) + self._effective_low_priority_routes_version = routes_version + return self._effective_low_priority_routes + + def _build_effective_context( + self, route: BaseRoute + ) -> _EffectiveRouteContext | None: + if isinstance(route, APIRoute): + return _EffectiveRouteContext.from_api_route( + original_route=route, + include_context=self.include_context, ) - response_name = "Response_" + self.unique_id - self.response_field = create_model_field( - name=response_name, - type_=self.response_model, - mode="serialization", + if isinstance(route, _FrontendRouteGroup): + return _EffectiveRouteContext( + original_route=route, + starlette_route=route.with_prefix(self.include_context.prefix), ) - else: - self.response_field = None # type: ignore[assignment] - if self.stream_item_type: - stream_item_name = "StreamItem_" + self.unique_id - self.stream_item_field: ModelField | None = create_model_field( - name=stream_item_name, - type_=self.stream_item_type, - mode="serialization", + if isinstance(route, routing.Route): + starlette_route: BaseRoute = routing.Route( + self.include_context.path_for(route), + endpoint=route.endpoint, + methods=list(route.methods or []), + name=route.name, + include_in_schema=route.include_in_schema, ) - else: - self.stream_item_field = None - self.dependencies = list(dependencies or []) - self.description = description or inspect.cleandoc(self.endpoint.__doc__ or "") - # if a "form feed" character (page break) is found in the description text, - # truncate description text to the content preceding the first "form feed" - self.description = self.description.split("\f")[0].strip() - response_fields = {} - for additional_status_code, response in self.responses.items(): - 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" + return _EffectiveRouteContext( + original_route=route, + starlette_route=starlette_route, + ) + if isinstance(route, APIWebSocketRoute): + starlette_route = APIWebSocketRoute( + self.include_context.path_for(route), + endpoint=route.endpoint, + name=route.name, + dependencies=[*self.include_context.dependencies, *route.dependencies], + dependency_overrides_provider=( + self.include_context.dependency_overrides_provider + ), + ) + return _EffectiveRouteContext( + original_route=route, + starlette_route=starlette_route, + ) + if isinstance(route, routing.WebSocketRoute): + starlette_route = routing.WebSocketRoute( + self.include_context.path_for(route), route.endpoint, name=route.name + ) + return _EffectiveRouteContext( + original_route=route, + starlette_route=starlette_route, + ) + if isinstance(route, routing.Mount): + starlette_route = copy.copy(route) + starlette_route.path = self.include_context.path_for(route).rstrip("/") + ( + starlette_route.path_regex, + starlette_route.path_format, + starlette_route.param_convertors, + ) = compile_path(starlette_route.path + "/{path:path}") + return _EffectiveRouteContext( + original_route=route, + starlette_route=starlette_route, + ) + if isinstance(route, routing.Host): + if self.include_context.prefix: + prefixed_app: ASGIApp = routing.Router( + routes=[routing.Mount(self.include_context.prefix, app=route.app)] ) - response_name = f"Response_{additional_status_code}_{self.unique_id}" - response_field = create_model_field( - name=response_name, type_=model, mode="serialization" + else: + prefixed_app = route.app + starlette_route = routing.Host( + route.host, app=prefixed_app, name=route.name + ) + return _EffectiveRouteContext( + original_route=route, + starlette_route=starlette_route, + ) + return None + + def _match( + self, scope: Scope + ) -> tuple[Match, Scope, BaseRoute | None, _EffectiveRouteContext | None]: + partial: tuple[Scope, BaseRoute, _EffectiveRouteContext | None] | None = None + for candidate in self.effective_candidates(): + if isinstance(candidate, _IncludedRouter): + match, child_scope = candidate.matches(scope) + route: BaseRoute = candidate + route_context = None + elif isinstance(candidate.original_route, APIRoute): + route_context = candidate + fastapi_scope = _get_fastapi_scope(scope) + previous_context = fastapi_scope.get( + _FASTAPI_EFFECTIVE_ROUTE_CONTEXT_KEY, _SCOPE_MISSING ) - response_fields[additional_status_code] = response_field - if response_fields: - self.response_fields: dict[int | str, ModelField] = response_fields - else: - self.response_fields = {} + fastapi_scope[_FASTAPI_EFFECTIVE_ROUTE_CONTEXT_KEY] = route_context + try: + match, child_scope = candidate.original_route.matches(scope) + finally: + _restore_fastapi_scope_key( + scope, _FASTAPI_EFFECTIVE_ROUTE_CONTEXT_KEY, previous_context + ) + route = candidate.original_route + else: + route_context = candidate + match, child_scope = candidate.matches(scope) + route = candidate.starlette_route or candidate.original_route + if match == Match.FULL: + return match, child_scope, route, route_context + if match == Match.PARTIAL and partial is None: + partial = (child_scope, route, route_context) + if partial is not None: + child_scope, route, route_context = partial + return Match.PARTIAL, child_scope, route, route_context + return Match.NONE, {}, None, None - assert callable(endpoint), "An endpoint must be a callable" - self.dependant = get_dependant( - path=self.path_format, call=self.endpoint, scope="function" + def matches(self, scope: Scope) -> tuple[Match, Scope]: + fastapi_scope = _get_fastapi_scope(scope) + previous_router = fastapi_scope.get( + _FASTAPI_INCLUDED_ROUTER_KEY, _SCOPE_MISSING ) - for depends in self.dependencies[::-1]: - self.dependant.dependencies.insert( - 0, - get_parameterless_sub_dependant(depends=depends, path=self.path_format), + fastapi_scope[_FASTAPI_INCLUDED_ROUTER_KEY] = self + try: + match, _ = self.original_router.matches(scope) + return match, {} + finally: + _restore_fastapi_scope_key( + scope, _FASTAPI_INCLUDED_ROUTER_KEY, previous_router ) - self._flat_dependant = get_flat_dependant(self.dependant) - self._embed_body_fields = _should_embed_body_fields( - self._flat_dependant.body_params - ) - self.body_field = get_body_field( - flat_dependant=self._flat_dependant, - name=self.unique_id, - embed_body_fields=self._embed_body_fields, + + async def handle(self, scope: Scope, receive: Receive, send: Send) -> None: + _get_fastapi_scope(scope)[_FASTAPI_INCLUDED_ROUTER_KEY] = self + await self.original_router.handle(scope, receive, send) + + async def _handle_selected( + self, scope: Scope, receive: Receive, send: Send + ) -> None: + match, child_scope, route, effective_context = self._match(scope) + if match == Match.NONE or route is None: + await self.original_router.default(scope, receive, send) + return + scope.update(child_scope) + if isinstance(route, _IncludedRouter): + await route.handle(scope, receive, send) + return + if effective_context is not None: + _get_fastapi_scope(scope)[_FASTAPI_EFFECTIVE_ROUTE_CONTEXT_KEY] = ( + effective_context + ) + original_route = effective_context.original_route + if isinstance(original_route, APIRoute): + scope["route"] = original_route + await original_route.handle(scope, receive, send) + return + await route.handle(scope, receive, send) + + def effective_route_contexts(self) -> Iterator[_EffectiveRouteContext]: + for candidate in self.effective_candidates(): + if isinstance(candidate, _IncludedRouter): + yield from candidate.effective_route_contexts() + else: + yield candidate + + def url_path_for(self, name: str, /, **path_params: Any) -> Any: + for route_context in self.effective_route_contexts(): + try: + return route_context.url_path_for(name, **path_params) + except routing.NoMatchFound: + pass + raise routing.NoMatchFound(name, path_params) + + +def _iter_included_route_candidates(routes: Sequence[BaseRoute]) -> Iterator[BaseRoute]: + for route, route_context in _iter_routes_with_context(routes): + if route_context is not None and route_context.starlette_route is not None: + yield route_context.starlette_route + else: + yield route + + +def iter_route_contexts( + routes: Sequence[BaseRoute | RouteContext], +) -> Iterator[RouteContext]: + for route in routes: + if isinstance(route, RouteContext): + yield route + continue + for original_route, route_context in _iter_routes_with_context([route]): + if route_context is None: + yield RouteContext(original_route) + else: + yield RouteContext(original_route, route_context) + + +def _iter_routes_with_context( + routes: Sequence[BaseRoute], +) -> Iterator[tuple[BaseRoute, _EffectiveRouteContext | None]]: + for route in routes: + if isinstance(route, _IncludedRouter): + for route_context in route.effective_route_contexts(): + yield route_context.original_route, route_context + else: + yield route, None + + +def _normalize_frontend_path(path: str) -> str: + if not path: + raise AssertionError("A frontend path cannot be empty") + if not path.startswith("/"): + raise AssertionError("A frontend path must start with '/'") + if path != "/": + path = path.rstrip("/") + return path + + +def _join_frontend_paths(prefix: str, path: str) -> str: + if not prefix: + return path + if path == "/": + return prefix + return prefix + path + + +def _frontend_path_specificity(path: str) -> int: + if path == "/": + return 0 + return len(path) + + +def _get_resolved_absolute_path(path: str | os.PathLike[str]) -> str: + return os.path.realpath(os.fspath(path)) + + +class _FrontendStaticFiles(StaticFiles): + def __init__( + self, + *, + directory: str | os.PathLike[str], + fallback: Literal["auto", "index.html", "404.html"] | None, + check_dir: bool = True, + ) -> None: + self.fallback = fallback + if check_dir and not os.path.isdir(directory): + raise RuntimeError( + f"Frontend directory '{directory}' does not exist. " + f"Resolved absolute path: '{_get_resolved_absolute_path(directory)}'" + ) + super().__init__( + directory=directory, + html=True, + check_dir=check_dir, + follow_symlink=False, ) - # Detect generator endpoints that should stream as JSONL or SSE - is_generator = ( - self.dependant.is_async_gen_callable or self.dependant.is_gen_callable + if check_dir and fallback in {"index.html", "404.html"}: + self._check_fallback_file(fallback) + + def _check_fallback_file(self, fallback: str) -> None: + _, stat_result = self.lookup_path(fallback) + if stat_result is None or not stat.S_ISREG(stat_result.st_mode): + raise RuntimeError( + f"Frontend fallback file '{fallback}' does not exist in " + f"directory '{self.directory}'. Resolved absolute directory: " + f"'{self._get_resolved_directory()}'" + ) + + def _get_resolved_directory(self) -> str: + assert self.directory is not None + return _get_resolved_absolute_path(self.directory) + + def get_path(self, scope: Scope) -> str: + path = _get_fastapi_scope(scope).get(_FASTAPI_FRONTEND_PATH_KEY, "") + assert isinstance(path, str) + return os.path.normpath(os.path.join(*path.split("/"))) + + async def get_response(self, path: str, scope: Scope) -> Response: + if scope["method"] not in ("GET", "HEAD"): + if await self._lookup_static_resource(path) is not None: + raise HTTPException(status_code=405) + raise HTTPException(status_code=404) + + static_resource = await self._lookup_static_resource(path) + if static_resource is not None: + full_path, stat_result, is_directory_index = static_resource + if is_directory_index and not scope["path"].endswith("/"): + url = URL(scope=scope) + url = url.replace(path=url.path + "/") + return RedirectResponse(url=url) + return self.file_response(full_path, stat_result, scope) + + if self.fallback == "404.html" or ( + self.fallback == "auto" and self._fallback_file_exists("404.html") + ): + return await self._fallback_response("404.html", scope, status_code=404) + + if ( + self.fallback == "index.html" + or (self.fallback == "auto" and self._fallback_file_exists("index.html")) + ) and _is_frontend_navigation_request(scope): + return await self._fallback_response("index.html", scope, status_code=200) + + raise HTTPException(status_code=404) + + async def _lookup_path(self, path: str) -> tuple[str, os.stat_result | None]: + try: + return await run_in_threadpool(self.lookup_path, path) + except PermissionError: + raise HTTPException(status_code=401) from None + except OSError as exc: + if exc.errno == errno.ENAMETOOLONG: + raise HTTPException(status_code=404) from None + raise exc + except ValueError: + raise HTTPException(status_code=404) from None + + async def _lookup_static_resource( + self, path: str + ) -> tuple[str, os.stat_result, bool] | None: + full_path, stat_result = await self._lookup_path(path) + if stat_result is None: + return None + if stat.S_ISREG(stat_result.st_mode): + return full_path, stat_result, False + if stat.S_ISDIR(stat_result.st_mode): + index_path = os.path.join(path, "index.html") + full_path, stat_result = await self._lookup_path(index_path) + if stat_result is not None and stat.S_ISREG(stat_result.st_mode): + return full_path, stat_result, True + return None + + def _fallback_file_exists(self, fallback: str) -> bool: + _, stat_result = self.lookup_path(fallback) + return stat_result is not None and stat.S_ISREG(stat_result.st_mode) + + async def _fallback_response( + self, fallback: str, scope: Scope, *, status_code: int + ) -> Response: + full_path, stat_result = await run_in_threadpool(self.lookup_path, fallback) + if stat_result is None or not stat.S_ISREG(stat_result.st_mode): + raise RuntimeError( + f"Frontend fallback file '{fallback}' does not exist in " + f"directory '{self.directory}'. Resolved absolute directory: " + f"'{self._get_resolved_directory()}'" + ) + return self.file_response( + full_path, stat_result, scope, status_code=status_code ) - self.is_sse_stream = is_generator and lenient_issubclass( - response_class, EventSourceResponse + + +def _iter_accept_media_types(accept: str) -> Iterator[tuple[str, float]]: + for raw_value in accept.split(","): + message = email.message.Message() + message["content-type"] = raw_value.strip() + q = message.get_param("q") + quality = 1.0 + if isinstance(q, str): + try: + quality = float(q) + except ValueError: + pass + yield ( + f"{message.get_content_maintype()}/{message.get_content_subtype()}", + quality, ) - self.is_json_stream = is_generator and isinstance( - response_class, DefaultPlaceholder + + +def _is_frontend_navigation_request(scope: Scope) -> bool: + route_path = get_route_path(scope) + final_segment = route_path.rsplit("/", 1)[-1] + if os.path.splitext(final_segment)[1]: + return False + request = Request(scope) + wildcard_accepted = False + html_rejected = False + for media_type, quality in _iter_accept_media_types( + request.headers.get("accept", "") + ): + if media_type in {"text/html", "application/xhtml+xml"}: + if quality == 0: + html_rejected = True + else: + return True + elif media_type == "*/*" and quality != 0: + wildcard_accepted = True + return wildcard_accepted and not html_rejected + + +class _FrontendRoute(BaseRoute): + def __init__( + self, + path: str, + *, + directory: str | os.PathLike[str], + fallback: Literal["auto", "index.html", "404.html"] | None = "auto", + check_dir: bool = True, + ) -> None: + if fallback not in {"auto", "index.html", "404.html", None}: + raise AssertionError( + "fallback must be 'auto', 'index.html', '404.html', or None" + ) + self.path = _normalize_frontend_path(path) + self.methods = {"GET", "HEAD"} + self.app = _FrontendStaticFiles( + directory=directory, fallback=fallback, check_dir=check_dir ) - self.app = request_response(self.get_route_handler()) - def get_route_handler(self) -> Callable[[Request], Coroutine[Any, Any, Response]]: - return get_request_handler( - dependant=self.dependant, - body_field=self.body_field, - status_code=self.status_code, - response_class=self.response_class, - response_field=self.response_field, - response_model_include=self.response_model_include, - response_model_exclude=self.response_model_exclude, - response_model_by_alias=self.response_model_by_alias, - response_model_exclude_unset=self.response_model_exclude_unset, - response_model_exclude_defaults=self.response_model_exclude_defaults, - response_model_exclude_none=self.response_model_exclude_none, - dependency_overrides_provider=self.dependency_overrides_provider, - embed_body_fields=self._embed_body_fields, - strict_content_type=self.strict_content_type, - stream_item_field=self.stream_item_field, - is_json_stream=self.is_json_stream, + def with_path(self, path: str) -> "_FrontendRoute": + route = copy.copy(self) + route.path = _normalize_frontend_path(path) + return route + + def matches(self, scope: Scope) -> tuple[Match, Scope]: + if scope["type"] != "http": + return Match.NONE, {} + frontend_path = self._get_frontend_path(get_route_path(scope)) + if frontend_path is None: + return Match.NONE, {} + child_scope = {_FASTAPI_SCOPE_KEY: {_FASTAPI_FRONTEND_PATH_KEY: frontend_path}} + if scope["method"] not in self.methods: + return Match.PARTIAL, child_scope + return Match.FULL, child_scope + + def _get_frontend_path(self, route_path: str) -> str | None: + if self.path == "/": + return route_path.lstrip("/") + if route_path == self.path: + return "" + prefix = self.path + "/" + if route_path.startswith(prefix): + return route_path[len(prefix) :] + return None + + async def handle(self, scope: Scope, receive: Receive, send: Send) -> None: + await self.app(scope, receive, send) + + def url_path_for(self, name: str, /, **path_params: Any) -> URLPath: + raise NoMatchFound(name, path_params) + + +class _FrontendRouteGroup(BaseRoute): + def __init__(self) -> None: + self.routes: list[_FrontendRoute] = [] + + def add_frontend_route( + self, + path: str, + *, + directory: str | os.PathLike[str], + fallback: Literal["auto", "index.html", "404.html"] | None = "auto", + check_dir: bool = True, + ) -> None: + self.routes.append( + _FrontendRoute( + path, + directory=directory, + fallback=fallback, + check_dir=check_dir, + ) ) + def with_prefix(self, prefix: str) -> "_FrontendRouteGroup": + route_group = copy.copy(self) + route_group.routes = [ + route.with_path(_join_frontend_paths(prefix, route.path)) + for route in self.routes + ] + return route_group + def matches(self, scope: Scope) -> tuple[Match, Scope]: - match, child_scope = super().matches(scope) - if match != Match.NONE: - child_scope["route"] = self + match, child_scope, _ = self._match(scope) return match, child_scope + def _match(self, scope: Scope) -> tuple[Match, Scope, _FrontendRoute | None]: + full: tuple[Scope, _FrontendRoute] | None = None + partial: tuple[Scope, _FrontendRoute] | None = None + for route in self.routes: + match, child_scope = route.matches(scope) + if match == Match.FULL: + if full is None or _frontend_path_specificity( + route.path + ) > _frontend_path_specificity(full[1].path): + full = (child_scope, route) + elif match == Match.PARTIAL: + if partial is None or _frontend_path_specificity( + route.path + ) > _frontend_path_specificity(partial[1].path): + partial = (child_scope, route) + if full is not None: + child_scope, route = full + return Match.FULL, child_scope, route + if partial is not None: + child_scope, route = partial + return Match.PARTIAL, child_scope, route + return Match.NONE, {}, None + + async def handle(self, scope: Scope, receive: Receive, send: Send) -> None: + match, child_scope, route = self._match(scope) + if match == Match.NONE or route is None: + raise HTTPException(status_code=404) + _update_scope(scope, child_scope) + await route.handle(scope, receive, send) + + def url_path_for(self, name: str, /, **path_params: Any) -> URLPath: + raise NoMatchFound(name, path_params) + class APIRouter(routing.Router): """ @@ -1311,6 +2379,287 @@ class APIRouter(routing.Router): self.default_response_class = default_response_class self.generate_unique_id_function = generate_unique_id_function self.strict_content_type = strict_content_type + self._routes_version = 0 + self._low_priority_routes: list[BaseRoute] = [] + self._frontend_routes: _FrontendRouteGroup | None = None + + def _mark_routes_changed(self) -> None: + self._routes_version += 1 + + def _get_routes_version(self, seen: set[int] | None = None) -> int: + if seen is None: + seen = set() + router_id = id(self) + if router_id in seen: + return self._routes_version + seen.add(router_id) + version = self._routes_version + for route in self.routes: + if isinstance(route, _IncludedRouter): + version += route.original_router._get_routes_version(seen) + return version + + def _contains_router( + self, router: "APIRouter", seen: set[int] | None = None + ) -> bool: + if seen is None: + seen = set() + router_id = id(self) + if router_id in seen: + return False + seen.add(router_id) + for route in self.routes: + if not isinstance(route, _IncludedRouter): + continue + if route.original_router is router: + return True + if route.original_router._contains_router(router, seen): + return True + return False + + def add_route( + self, + path: str, + endpoint: Callable[[Request], Awaitable[Response] | Response], + methods: Collection[str] | None = None, + name: str | None = None, + include_in_schema: bool = True, + ) -> None: + super().add_route( + path, + endpoint, + methods=methods, + name=name, + include_in_schema=include_in_schema, + ) + self._mark_routes_changed() + + def add_websocket_route( + self, + path: str, + endpoint: Callable[[WebSocket], Awaitable[None]], + name: str | None = None, + ) -> None: + super().add_websocket_route(path, endpoint, name=name) + self._mark_routes_changed() + + def frontend( + self, + path: Annotated[ + str, + Doc( + """ + The URL path prefix where the frontend build should be served. + """ + ), + ], + *, + directory: Annotated[ + str | os.PathLike[str], + Doc( + """ + The directory containing the static frontend build output. + """ + ), + ], + fallback: Annotated[ + Literal["auto", "index.html", "404.html"] | None, + Doc( + """ + The fallback file behavior for missing frontend paths. + """ + ), + ] = "auto", + check_dir: Annotated[ + bool, + Doc( + """ + Check that the frontend directory exists when the app is created. + """ + ), + ] = True, + ) -> None: + """ + Serve a static frontend build as low-priority routes. + + Use this for frontend tools that build static files into a directory, + such as `dist`. **FastAPI** path operations are checked first, and + the frontend files are checked only if no normal route matched. + + A typical project could look like this: + + ```text + . + ├── pyproject.toml + ├── app + │ ├── __init__.py + │ └── main.py + └── dist + ├── index.html + └── assets + └── app.js + ``` + + Then in `app/main.py`: + + ```python + from fastapi import APIRouter, FastAPI + + app = FastAPI() + router = APIRouter() + router.frontend("/", directory="dist") + app.include_router(router) + ``` + """ + normalized_path = _normalize_frontend_path(path) + if self._frontend_routes is None: + self._frontend_routes = _FrontendRouteGroup() + self._low_priority_routes.append(self._frontend_routes) + self._frontend_routes.add_frontend_route( + _join_frontend_paths(self.prefix, normalized_path), + directory=directory, + fallback=fallback, + check_dir=check_dir, + ) + self._mark_routes_changed() + + async def app(self, scope: Scope, receive: Receive, send: Send) -> None: + assert scope["type"] in ("http", "websocket", "lifespan") + + if "router" not in scope: + scope["router"] = self + + if scope["type"] == "lifespan": + await self.lifespan(scope, receive, send) + return + + partial: tuple[BaseRoute, Scope] | None = None + for route in self.routes: + match, child_scope = route.matches(scope) + if match == Match.FULL: + scope.update(child_scope) + await route.handle(scope, receive, send) + return + if match == Match.PARTIAL and partial is None: + partial = (route, child_scope) + + if partial is not None: + route, child_scope = partial + scope.update(child_scope) + await route.handle(scope, receive, send) + return + + route_path = get_route_path(scope) + if scope["type"] == "http" and self.redirect_slashes and route_path != "/": + redirect_scope = dict(scope) + if route_path.endswith("/"): + redirect_scope["path"] = redirect_scope["path"].rstrip("/") + else: + redirect_scope["path"] = redirect_scope["path"] + "/" + + for route in self.routes: + match, _ = route.matches(redirect_scope) + if match != Match.NONE: + redirect_url = URL(scope=redirect_scope) + response = RedirectResponse(url=str(redirect_url)) + await response(scope, receive, send) + return + + ( + low_priority_match, + low_priority_scope, + low_priority_route, + low_priority_context, + ) = self._match_low_priority(scope) + if low_priority_match != Match.NONE and low_priority_route is not None: + _update_scope(scope, low_priority_scope) + if low_priority_context is not None: + _get_fastapi_scope(scope)[_FASTAPI_EFFECTIVE_ROUTE_CONTEXT_KEY] = ( + low_priority_context + ) + original_route = low_priority_context.original_route + if isinstance(original_route, APIRoute): + scope["route"] = original_route + await original_route.handle(scope, receive, send) + return + await low_priority_route.handle(scope, receive, send) + return + + await self.default(scope, receive, send) + + async def handle(self, scope: Scope, receive: Receive, send: Send) -> None: + included_router = _get_scope_included_router(scope) + if ( + isinstance(included_router, _IncludedRouter) + and included_router.original_router is self + ): + await included_router._handle_selected(scope, receive, send) + return + await self.app(scope, receive, send) + + def matches(self, scope: Scope) -> tuple[Match, Scope]: + included_router = _get_scope_included_router(scope) + if ( + isinstance(included_router, _IncludedRouter) + and included_router.original_router is self + ): + match, child_scope, _, _ = included_router._match(scope) + return match, child_scope + return Match.NONE, {} + + def _iter_low_priority_routes( + self, + ) -> Iterator[BaseRoute | _EffectiveRouteContext]: + yield from self._low_priority_routes + for route in self.routes: + if isinstance(route, _IncludedRouter): + yield from route.effective_low_priority_routes() + + def _match_low_priority( + self, scope: Scope + ) -> tuple[Match, Scope, BaseRoute | None, _EffectiveRouteContext | None]: + full: tuple[Scope, BaseRoute, _EffectiveRouteContext | None] | None = None + partial: tuple[Scope, BaseRoute, _EffectiveRouteContext | None] | None = None + for candidate in self._iter_low_priority_routes(): + route: BaseRoute + if isinstance(candidate, _EffectiveRouteContext): + route_context: _EffectiveRouteContext | None = candidate + original_route = candidate.original_route + if isinstance(original_route, APIRoute): + fastapi_scope = _get_fastapi_scope(scope) + previous_context = fastapi_scope.get( + _FASTAPI_EFFECTIVE_ROUTE_CONTEXT_KEY, _SCOPE_MISSING + ) + fastapi_scope[_FASTAPI_EFFECTIVE_ROUTE_CONTEXT_KEY] = route_context + try: + match, child_scope = original_route.matches(scope) + finally: + _restore_fastapi_scope_key( + scope, + _FASTAPI_EFFECTIVE_ROUTE_CONTEXT_KEY, + previous_context, + ) + route = original_route + else: + match, child_scope = candidate.matches(scope) + route = candidate.starlette_route or original_route + else: + route_context = None + match, child_scope = candidate.matches(scope) + route = candidate + if match == Match.FULL: + if full is None: + full = (child_scope, route, route_context) + elif match == Match.PARTIAL: + if partial is None: + partial = (child_scope, route, route_context) + if full is not None: + child_scope, route, route_context = full + return Match.FULL, child_scope, route, route_context + if partial is not None: + child_scope, route, route_context = partial + return Match.PARTIAL, child_scope, route, route_context + return Match.NONE, {}, None, None def route( self, @@ -1413,6 +2762,7 @@ class APIRouter(routing.Router): ), ) self.routes.append(route) + self._mark_routes_changed() def api_route( self, @@ -1496,6 +2846,7 @@ class APIRouter(routing.Router): dependency_overrides_provider=self.dependency_overrides_provider, ) self.routes.append(route) + self._mark_routes_changed() def websocket( self, @@ -1712,111 +3063,47 @@ class APIRouter(routing.Router): "Cannot include the same APIRouter instance into itself. " "Did you mean to include a different router?" ) + assert not router._contains_router(self), ( + "Cannot include an APIRouter instance that already includes this router. " + "Did you mean to include a different 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 '/'" ) else: - for r in router.routes: - path = getattr(r, "path") # noqa: B009 - name = getattr(r, "name", "unknown") + for route, route_context in _iter_routes_with_context(router.routes): + if route_context is None: + path = getattr(route, "path", None) + name = getattr(route, "name", "unknown") + elif route_context.starlette_route is not None: + path = getattr(route_context.starlette_route, "path", None) + name = getattr(route_context.starlette_route, "name", "unknown") + else: + path = route_context.path + name = route_context.name if path is not None and not path: raise FastAPIError( f"Prefix and path cannot be both empty (path operation: {name})" ) - if responses is None: - responses = {} - for route in router.routes: - if isinstance(route, APIRoute): - combined_responses = {**responses, **route.responses} - use_response_class = get_value_or_default( - route.response_class, - router.default_response_class, - default_response_class, - self.default_response_class, - ) - current_tags = [] - if tags: - current_tags.extend(tags) - if route.tags: - current_tags.extend(route.tags) - current_dependencies: list[params.Depends] = [] - if dependencies: - current_dependencies.extend(dependencies) - if route.dependencies: - current_dependencies.extend(route.dependencies) - current_callbacks = [] - if callbacks: - current_callbacks.extend(callbacks) - if route.callbacks: - current_callbacks.extend(route.callbacks) - current_generate_unique_id = get_value_or_default( - route.generate_unique_id_function, - router.generate_unique_id_function, - generate_unique_id_function, - self.generate_unique_id_function, - ) - self.add_api_route( - prefix + route.path, - route.endpoint, - response_model=route.response_model, - status_code=route.status_code, - tags=current_tags, - dependencies=current_dependencies, - summary=route.summary, - description=route.description, - response_description=route.response_description, - responses=combined_responses, - deprecated=route.deprecated or deprecated or self.deprecated, - methods=route.methods, - operation_id=route.operation_id, - response_model_include=route.response_model_include, - response_model_exclude=route.response_model_exclude, - response_model_by_alias=route.response_model_by_alias, - response_model_exclude_unset=route.response_model_exclude_unset, - response_model_exclude_defaults=route.response_model_exclude_defaults, - response_model_exclude_none=route.response_model_exclude_none, - include_in_schema=route.include_in_schema - and self.include_in_schema - and include_in_schema, - response_class=use_response_class, - name=route.name, - route_class_override=type(route), - callbacks=current_callbacks, - openapi_extra=route.openapi_extra, - generate_unique_id_function=current_generate_unique_id, - strict_content_type=get_value_or_default( - route.strict_content_type, - router.strict_content_type, - self.strict_content_type, - ), - ) - elif isinstance(route, routing.Route): - methods = list(route.methods or []) - self.add_route( - prefix + route.path, - route.endpoint, - methods=methods, - include_in_schema=route.include_in_schema, - name=route.name, - ) - elif isinstance(route, APIWebSocketRoute): - current_dependencies = [] - if dependencies: - current_dependencies.extend(dependencies) - if route.dependencies: - current_dependencies.extend(route.dependencies) - self.add_api_websocket_route( - prefix + route.path, - route.endpoint, - dependencies=current_dependencies, - name=route.name, - ) - elif isinstance(route, routing.WebSocketRoute): - self.add_websocket_route( - prefix + route.path, route.endpoint, name=route.name - ) + include_context = _RouterIncludeContext.for_include( + parent_router=self, + included_router=router, + prefix=prefix, + tags=tags, + dependencies=dependencies, + default_response_class=default_response_class, + responses=responses, + callbacks=callbacks, + deprecated=deprecated, + include_in_schema=include_in_schema, + generate_unique_id_function=generate_unique_id_function, + ) + self.routes.append( + _IncludedRouter(original_router=router, include_context=include_context) + ) + self._mark_routes_changed() for handler in router.on_startup: self.add_event_handler("startup", handler) for handler in router.on_shutdown: diff --git a/pyproject.toml b/pyproject.toml index daa523ce2..e33e46fd8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -319,7 +319,6 @@ extend-exclude = [ "docs/de/", "docs/en/data/", "docs/en/docs/img/", - "docs/en/docs/release-notes.md", "docs/es/", "docs/fr/", "docs/ja/", @@ -331,6 +330,7 @@ extend-exclude = [ "docs/uk/", "docs/zh/", "docs/zh-hant/", + "docs/hi/", "htmlcov/", "scripts/general-llm-prompt.md", "scripts/tests/test_translation_fixer/test_complex_doc/", @@ -339,6 +339,16 @@ extend-exclude = [ "uv.lock", ] +[tool.typos.default] +extend-ignore-re = [ + # GitHub usernames in @mentions + "@[a-zA-Z0-9](?:-?[a-zA-Z0-9])*", + # Quoted typo documented in a release note + "'wll' to 'will'", + # German article title in a release note + "FastAPI Modul.", +] + [tool.typos.default.extend-identifiers] alls = "alls" @@ -349,5 +359,41 @@ havin = "havin" Ines = "Ines" ser = "ser" +[tool.ty.src] +exclude = [ + # These docs examples are intentionally partial, dynamic, environment-driven, + # deprecated, or currently require broader tutorial rewrites to satisfy ty. + "docs_src/additional_status_codes/", + "docs_src/app_testing/tutorial003_py310.py", + "docs_src/body_multiple_params/", + "docs_src/body_updates/tutorial002_py310.py", + "docs_src/custom_docs_ui/", + "docs_src/custom_response/tutorial001_py310.py", + "docs_src/custom_response/tutorial001b_py310.py", + "docs_src/custom_response/tutorial009c_py310.py", + "docs_src/dependencies/tutorial007_py310.py", + "docs_src/dependencies/tutorial008_an_py310.py", + "docs_src/dependencies/tutorial008_py310.py", + "docs_src/dependencies/tutorial010_py310.py", + "docs_src/events/", + "docs_src/extending_openapi/tutorial001_py310.py", + "docs_src/path_params_numeric_validations/", + "docs_src/pydantic_v1_in_v2/tutorial004_an_py310.py", + "docs_src/python_types/tutorial003_py310.py", + "docs_src/python_types/tutorial011_py310.py", + "docs_src/query_params_str_validations/", + "docs_src/response_model/tutorial006_py310.py", + "docs_src/security/tutorial003_an_py310.py", + "docs_src/security/tutorial003_py310.py", + "docs_src/security/tutorial004_an_py310.py", + "docs_src/security/tutorial004_py310.py", + "docs_src/security/tutorial005_an_py310.py", + "docs_src/security/tutorial005_py310.py", + "docs_src/settings/", + "docs_src/sql_databases/", + "docs_src/using_request_directly/tutorial001_py310.py", + "docs_src/wsgi/tutorial001_py310.py", +] + [tool.ty.terminal] error-on-warning = true diff --git a/scripts/contributors.py b/scripts/contributors.py index af1434d79..5e9d72d64 100644 --- a/scripts/contributors.py +++ b/scripts/contributors.py @@ -237,7 +237,7 @@ def update_content(*, content_path: Path, new_content: Any) -> bool: def main() -> None: logging.basicConfig(level=logging.INFO) - settings = Settings() + settings = Settings() # ty: ignore[missing-argument] logging.info(f"Using config: {settings.model_dump_json()}") g = Github(settings.github_token.get_secret_value()) repo = g.get_repo(settings.github_repository) diff --git a/scripts/coverage.sh b/scripts/coverage.sh deleted file mode 100755 index e07b51ec5..000000000 --- a/scripts/coverage.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/env bash - -set -e -set -x - -coverage combine -coverage report -coverage html diff --git a/scripts/deploy_docs_status.py b/scripts/deploy_docs_status.py index e620b15ba..8e5a2e38b 100644 --- a/scripts/deploy_docs_status.py +++ b/scripts/deploy_docs_status.py @@ -24,7 +24,7 @@ class LinkData(BaseModel): def main() -> None: logging.basicConfig(level=logging.INFO) - settings = Settings() + settings = Settings() # ty: ignore[missing-argument] logging.info(f"Using config: {settings.model_dump_json()}") g = Github(auth=Auth.Token(settings.github_token.get_secret_value())) diff --git a/scripts/doc_parsing_utils.py b/scripts/doc_parsing_utils.py index 88ff2c50b..f2f047c3d 100644 --- a/scripts/doc_parsing_utils.py +++ b/scripts/doc_parsing_utils.py @@ -625,14 +625,14 @@ def replace_multiline_code_block( _line_b_code, line_b_comment = _split_hash_comment(line_b) res_line = line_b if line_b_comment: - res_line = res_line.replace(line_b_comment, line_a_comment, 1) + res_line = res_line.replace(line_b_comment, line_a_comment or "", 1) code_block.append(res_line) elif block_language in {"console", "json", "slash-style-comments"}: _line_a_code, line_a_comment = _split_slashes_comment(line_a) _line_b_code, line_b_comment = _split_slashes_comment(line_b) res_line = line_b if line_b_comment: - res_line = res_line.replace(line_b_comment, line_a_comment, 1) + res_line = res_line.replace(line_b_comment, line_a_comment or "", 1) code_block.append(res_line) else: code_block.append(line_b) diff --git a/scripts/docs.py b/scripts/docs.py index a478d59a0..a108c8ddf 100644 --- a/scripts/docs.py +++ b/scripts/docs.py @@ -31,6 +31,7 @@ SUPPORTED_LANGS = { "uk", "zh", "zh-hant", + "hi", } @@ -155,7 +156,7 @@ def build_lang( """ build_zensical_lang_to_stage(lang) copy_zensical_stage_to_site(lang) - typer.secho(f"Successfully built docs for: {lang}", color=typer.colors.GREEN) + typer.secho(f"Successfully built docs for: {lang}", fg=typer.colors.GREEN) def split_markdown_header(markdown: str) -> tuple[str, str]: @@ -248,6 +249,7 @@ def stage_zensical_docs(lang: str) -> Path: encoding="utf-8", ) + render_banner_sponsors() shutil.copytree(en_docs_path / "data", lang_stage_path / "data") shutil.copytree(en_docs_path / "overrides", lang_stage_path / "overrides") @@ -311,22 +313,26 @@ index_sponsors_template = """ ### Keystone Sponsor {% for sponsor in sponsors.keystone -%} - + {% endfor %} ### Gold Sponsors {% for sponsor in sponsors.gold -%} - + {% endfor %} ### Silver Sponsors {% for sponsor in sponsors.silver -%} - + {% endfor %} """ +def sponsor_img_url(img: str) -> str: + return f"https://fastapi.tiangolo.com{img}" + + def remove_header_permalinks(content: str): lines: list[str] = [] for line in content.split("\n"): @@ -355,7 +361,7 @@ def generate_readme_content() -> str: pre_end = match_start.end() post_start = match_end.start() template = Template(index_sponsors_template) - message = template.render(sponsors=sponsors) + message = template.render(sponsors=sponsors, sponsor_img_url=sponsor_img_url) pre_content = content[frontmatter_end:pre_end] post_content = content[post_start:] new_content = pre_content + message + post_content @@ -408,7 +414,7 @@ def build_all() -> None: for lang in langs: if lang != "en": copy_zensical_stage_to_site(lang) - typer.secho("Successfully built all docs", color=typer.colors.GREEN) + typer.secho("Successfully built all docs", fg=typer.colors.GREEN) @app.command() @@ -456,6 +462,7 @@ def live() -> None: """ Serve the English docs with livereload from the source files. """ + render_banner_sponsors() subprocess.run( [ "zensical", @@ -503,6 +510,56 @@ def get_updated_config_content() -> dict[str, Any]: return config +banner_sponsors_template = """{% for sponsor in banner_sponsors -%} + +{% endfor %} +""" + + +def get_banner_sponsors(sponsors: dict[str, Any]) -> list[dict[str, str]]: + banner_sponsors: list[dict[str, str]] = [] + for sponsor in sponsors.get("gold", []): + banner_img = sponsor.get("banner_img") + if not banner_img: + continue + banner_sponsors.append( + { + "url": sponsor.get("banner_url", sponsor["url"]), + "title": sponsor.get("banner_title", sponsor["title"]), + "img": banner_img, + } + ) + return banner_sponsors + + +def render_banner_sponsors_partial() -> str: + sponsors_path = en_docs_path / "data" / "sponsors.yml" + sponsors = yaml.safe_load(sponsors_path.read_text(encoding="utf-8")) + template = Template(banner_sponsors_template) + return template.render(banner_sponsors=get_banner_sponsors(sponsors)) + + +@app.command() +def render_banner_sponsors() -> None: + """ + Render the sponsor banner partial from sponsors.yml. + """ + partial_path = en_docs_path / "overrides" / "partials" / "banner-sponsors.html" + old_content = partial_path.read_text("utf-8") if partial_path.is_file() else "" + new_content = render_banner_sponsors_partial() + if new_content != old_content: + print(f"{partial_path} outdated from the latest sponsors.yml") + print(f"Updating {partial_path}") + partial_path.write_text(new_content, encoding="utf-8") + raise typer.Exit(1) + print(f"{partial_path} is up to date ✅") + + @app.command() def ensure_non_translated() -> None: """ diff --git a/scripts/label_approved.py b/scripts/label_approved.py index 81de92efb..397a79663 100644 --- a/scripts/label_approved.py +++ b/scripts/label_approved.py @@ -22,7 +22,7 @@ class Settings(BaseSettings): config: dict[str, LabelSettings] | Literal[""] = default_config -settings = Settings() +settings = Settings() # ty: ignore[missing-argument] if settings.debug: logging.basicConfig(level=logging.DEBUG) else: diff --git a/scripts/lint.sh b/scripts/lint.sh index a4d3422d3..a7d1f2f66 100755 --- a/scripts/lint.sh +++ b/scripts/lint.sh @@ -4,6 +4,6 @@ set -e set -x mypy fastapi -ty check fastapi +ty check ruff check fastapi tests docs_src scripts ruff format fastapi tests --check diff --git a/scripts/notify_translations.py b/scripts/notify_translations.py index 3484b69c7..22fa633f4 100644 --- a/scripts/notify_translations.py +++ b/scripts/notify_translations.py @@ -304,7 +304,7 @@ def update_comment(*, settings: Settings, comment_id: str, body: str) -> Comment def main() -> None: - settings = Settings() + settings = Settings() # ty: ignore[missing-argument] if settings.debug: logging.basicConfig(level=logging.DEBUG) else: @@ -324,6 +324,7 @@ def main() -> None: ) or settings.number if number is None: raise RuntimeError("No PR number available") + number = cast(int, number) # Avoid race conditions with multiple labels sleep_time = random.random() * 10 # random number between 0 and 10 seconds diff --git a/scripts/people.py b/scripts/people.py index 5718d65da..72b591367 100644 --- a/scripts/people.py +++ b/scripts/people.py @@ -394,7 +394,7 @@ def update_content(*, content_path: Path, new_content: Any) -> bool: def main() -> None: logging.basicConfig(level=logging.INFO) - settings = Settings() + settings = Settings() # ty: ignore[missing-argument] logging.info(f"Using config: {settings.model_dump_json()}") rate_limiter.speed_multiplier = settings.speed_multiplier g = Github(settings.github_token.get_secret_value()) diff --git a/scripts/sponsors.py b/scripts/sponsors.py index fdcabc737..38d8cbfa4 100644 --- a/scripts/sponsors.py +++ b/scripts/sponsors.py @@ -158,7 +158,7 @@ def update_content(*, content_path: Path, new_content: Any) -> bool: def main() -> None: logging.basicConfig(level=logging.INFO) - settings = Settings() + settings = Settings() # ty: ignore[missing-argument] logging.info(f"Using config: {settings.model_dump_json()}") g = Github(settings.pr_token.get_secret_value()) repo = g.get_repo(settings.github_repository) diff --git a/scripts/topic_repos.py b/scripts/topic_repos.py index b7afc0864..94379d384 100644 --- a/scripts/topic_repos.py +++ b/scripts/topic_repos.py @@ -24,7 +24,7 @@ class Repo(BaseModel): def main() -> None: logging.basicConfig(level=logging.INFO) - settings = Settings() + settings = Settings() # ty: ignore[missing-argument] logging.info(f"Using config: {settings.model_dump_json()}") g = Github(settings.github_token.get_secret_value(), per_page=100) diff --git a/scripts/translate.py b/scripts/translate.py index 9bc35c018..5fec92fb9 100644 --- a/scripts/translate.py +++ b/scripts/translate.py @@ -132,7 +132,7 @@ def translate_page( print(f"Found existing translation: {out_path}") old_translation = out_path.read_text(encoding="utf-8") print(f"Translating {en_path} to {language} ({language_name})") - agent = Agent("openai:gpt-5") + agent = Agent("openai-chat:gpt-5.5") MAX_ATTEMPTS = 3 additional_instructions = "" diff --git a/tests/test_compat.py b/tests/test_compat.py index 772bd305e..76151fac9 100644 --- a/tests/test_compat.py +++ b/tests/test_compat.py @@ -1,3 +1,5 @@ +from typing import Any, cast + from fastapi import FastAPI, UploadFile from fastapi._compat import ( Undefined, @@ -56,9 +58,15 @@ def test_propagates_pydantic2_model_config(): @app.post("/") def foo(req: Model) -> dict[str, str | None]: + value = req.value + if isinstance(value, Missing): + value = None + embedded_value = req.embedded_model.value + if isinstance(embedded_value, Missing): + embedded_value = None return { - "value": req.value or None, - "embedded_value": req.embedded_model.value or None, + "value": value, + "embedded_value": embedded_value, } client = TestClient(app) @@ -100,7 +108,7 @@ def test_serialize_sequence_value_with_optional_list(): """Test that serialize_sequence_value handles optional lists correctly.""" from fastapi._compat import v2 - field_info = FieldInfo(annotation=list[str] | None) + field_info = FieldInfo(annotation=cast(Any, list[str] | None)) field = v2.ModelField(name="items", field_info=field_info) result = v2.serialize_sequence_value(field=field, value=["a", "b", "c"]) assert result == ["a", "b", "c"] @@ -111,7 +119,7 @@ def test_serialize_sequence_value_with_optional_list_pipe_union(): """Test that serialize_sequence_value handles optional lists correctly (with new syntax).""" from fastapi._compat import v2 - field_info = FieldInfo(annotation=list[str] | None) + field_info = FieldInfo(annotation=cast(Any, list[str] | None)) field = v2.ModelField(name="items", field_info=field_info) result = v2.serialize_sequence_value(field=field, value=["a", "b", "c"]) assert result == ["a", "b", "c"] @@ -125,7 +133,7 @@ def test_serialize_sequence_value_with_none_first_in_union(): from fastapi._compat import v2 # Use Union[None, list[str]] to ensure None comes first in the union args - field_info = FieldInfo(annotation=Union[None, list[str]]) # noqa: UP007 + field_info = FieldInfo(annotation=cast(Any, Union[None, list[str]])) # noqa: UP007 field = v2.ModelField(name="items", field_info=field_info) result = v2.serialize_sequence_value(field=field, value=["x", "y"]) assert result == ["x", "y"] diff --git a/tests/test_custom_middleware_exception.py b/tests/test_custom_middleware_exception.py index cf548f4ae..989ab58bc 100644 --- a/tests/test_custom_middleware_exception.py +++ b/tests/test_custom_middleware_exception.py @@ -3,6 +3,7 @@ from pathlib import Path from fastapi import APIRouter, FastAPI, File, UploadFile from fastapi.exceptions import HTTPException from fastapi.testclient import TestClient +from starlette.types import ASGIApp app = FastAPI() @@ -16,7 +17,7 @@ class ContentSizeLimitMiddleware: max_content_size (optional): the maximum content size allowed in bytes, None for no limit """ - def __init__(self, app: APIRouter, max_content_size: int | None = None): + def __init__(self, app: ASGIApp, max_content_size: int | None = None): self.app = app self.max_content_size = max_content_size @@ -31,6 +32,7 @@ class ContentSizeLimitMiddleware: body_len = len(message.get("body", b"")) received += body_len + assert self.max_content_size is not None if received > self.max_content_size: raise HTTPException( 422, diff --git a/tests/test_custom_route_class.py b/tests/test_custom_route_class.py index 786c1efc3..de5e1da90 100644 --- a/tests/test_custom_route_class.py +++ b/tests/test_custom_route_class.py @@ -3,7 +3,6 @@ from fastapi import APIRouter, FastAPI from fastapi.routing import APIRoute from fastapi.testclient import TestClient from inline_snapshot import snapshot -from starlette.routing import Route app = FastAPI() @@ -63,13 +62,9 @@ def test_get_path(path, expected_status, expected_response): def test_route_classes(): - routes = {} - for r in app.router.routes: - assert isinstance(r, Route) - routes[r.path] = r - assert getattr(routes["/a/"], "x_type") == "A" # noqa: B009 - assert getattr(routes["/a/b/"], "x_type") == "B" # noqa: B009 - assert getattr(routes["/a/b/c/"], "x_type") == "C" # noqa: B009 + assert isinstance(router_a.routes[0], APIRouteA) + assert isinstance(router_b.routes[0], APIRouteB) + assert isinstance(router_c.routes[0], APIRouteC) def test_openapi_schema(): diff --git a/tests/test_datastructures.py b/tests/test_datastructures.py index 29a70cae0..1b5335ea9 100644 --- a/tests/test_datastructures.py +++ b/tests/test_datastructures.py @@ -1,9 +1,10 @@ import io from pathlib import Path +from typing import cast import pytest from fastapi import FastAPI, UploadFile -from fastapi.datastructures import Default +from fastapi.datastructures import Default, DefaultPlaceholder from fastapi.testclient import TestClient @@ -13,8 +14,8 @@ def test_upload_file_invalid_pydantic_v2(): def test_default_placeholder_equals(): - placeholder_1 = Default("a") - placeholder_2 = Default("a") + placeholder_1 = cast(DefaultPlaceholder, Default("a")) + placeholder_2 = cast(DefaultPlaceholder, Default("a")) assert placeholder_1 == placeholder_2 assert placeholder_1.value == placeholder_2.value diff --git a/tests/test_default_response_class.py b/tests/test_default_response_class.py index 88498e560..bc60e0b14 100644 --- a/tests/test_default_response_class.py +++ b/tests/test_default_response_class.py @@ -11,7 +11,7 @@ class ORJSONResponse(JSONResponse): media_type = "application/x-orjson" def render(self, content: Any) -> bytes: - import orjson + import orjson # ty: ignore[unresolved-import] return orjson.dumps(content) diff --git a/tests/test_deprecated_responses.py b/tests/test_deprecated_responses.py index 8cbd9c11f..8a5663744 100644 --- a/tests/test_deprecated_responses.py +++ b/tests/test_deprecated_responses.py @@ -3,7 +3,7 @@ import warnings import pytest from fastapi import FastAPI from fastapi.exceptions import FastAPIDeprecationWarning -from fastapi.responses import ORJSONResponse, UJSONResponse +from fastapi.responses import ORJSONResponse, UJSONResponse # ty: ignore[deprecated] from fastapi.testclient import TestClient from pydantic import BaseModel @@ -21,7 +21,7 @@ class Item(BaseModel): def _make_orjson_app() -> FastAPI: with warnings.catch_warnings(): warnings.simplefilter("ignore", FastAPIDeprecationWarning) - app = FastAPI(default_response_class=ORJSONResponse) + app = FastAPI(default_response_class=ORJSONResponse) # ty: ignore[deprecated] @app.get("/items") def get_items() -> Item: @@ -44,7 +44,7 @@ def test_orjson_response_returns_correct_data(): @needs_orjson def test_orjson_response_emits_deprecation_warning(): with pytest.warns(FastAPIDeprecationWarning, match="ORJSONResponse is deprecated"): - ORJSONResponse(content={"hello": "world"}) + ORJSONResponse(content={"hello": "world"}) # ty: ignore[deprecated] # UJSON @@ -53,7 +53,7 @@ def test_orjson_response_emits_deprecation_warning(): def _make_ujson_app() -> FastAPI: with warnings.catch_warnings(): warnings.simplefilter("ignore", FastAPIDeprecationWarning) - app = FastAPI(default_response_class=UJSONResponse) + app = FastAPI(default_response_class=UJSONResponse) # ty: ignore[deprecated] @app.get("/items") def get_items() -> Item: @@ -76,4 +76,4 @@ def test_ujson_response_returns_correct_data(): @needs_ujson def test_ujson_response_emits_deprecation_warning(): with pytest.warns(FastAPIDeprecationWarning, match="UJSONResponse is deprecated"): - UJSONResponse(content={"hello": "world"}) + UJSONResponse(content={"hello": "world"}) # ty: ignore[deprecated] diff --git a/tests/test_frontend.py b/tests/test_frontend.py new file mode 100644 index 000000000..81cffc228 --- /dev/null +++ b/tests/test_frontend.py @@ -0,0 +1,993 @@ +import errno +import os +import runpy +from pathlib import Path +from typing import Literal + +import anyio +import pytest +from fastapi import APIRouter, FastAPI, HTTPException, Request, WebSocket +from fastapi.testclient import TestClient +from starlette.exceptions import HTTPException as StarletteHTTPException +from starlette.responses import PlainTextResponse, Response +from starlette.routing import BaseRoute, Match, NoMatchFound, Route + + +def write_file(path: Path, content: str) -> None: + path.parent.mkdir(parents=True, exist_ok=True) + path.write_text(content) + + +def test_frontend_exact_prefix_path_serves_index(tmp_path: Path): + dist = tmp_path / "dist" + write_file(dist / "index.html", "app") + app = FastAPI() + app.frontend("/app", directory=dist) + + response = TestClient(app).get("/app") + + assert response.status_code == 200 + assert response.text == "app" + + +def test_apirouter_frontend_with_router_prefix_and_frontend_subpath(tmp_path: Path): + dist = tmp_path / "dist" + write_file(dist / "asset.txt", "asset") + router = APIRouter(prefix="/internal") + router.frontend("/ui", directory=dist) + app = FastAPI() + app.include_router(router, prefix="/prefix") + + response = TestClient(app).get("/prefix/internal/ui/asset.txt") + + assert response.status_code == 200 + assert response.text == "asset" + + +def test_frontend_fallback_rejects_invalid_fallback(tmp_path: Path): + dist = tmp_path / "dist" + dist.mkdir() + app = FastAPI() + + with pytest.raises(AssertionError, match="fallback"): + app.frontend("/", directory=dist, fallback="invalid") # type: ignore[arg-type] # ty: ignore[invalid-argument-type] + + +def test_index_fallback_ignores_invalid_q_value(tmp_path: Path): + dist = tmp_path / "dist" + write_file(dist / "index.html", "app shell") + app = FastAPI() + app.frontend("/", directory=dist, fallback="index.html") + + response = TestClient(app).get( + "/dashboard/settings", headers={"accept": "text/html; q=wat"} + ) + + assert response.status_code == 200 + assert response.text == "app shell" + + +def test_frontend_static_files_lookup_errors(monkeypatch, tmp_path: Path): + dist = tmp_path / "dist" + write_file(dist / "index.html", "app") + app = FastAPI() + app.frontend("/", directory=dist) + frontend_routes = app.router._frontend_routes + assert frontend_routes is not None + static_files = frontend_routes.routes[0].app + + def raise_permission_error(path: str): + raise PermissionError + + monkeypatch.setattr(static_files, "lookup_path", raise_permission_error) + response = TestClient(app).get("/asset.txt") + assert response.status_code == 401 + + def raise_value_error(path: str): + raise ValueError + + monkeypatch.setattr(static_files, "lookup_path", raise_value_error) + response = TestClient(app).get("/asset.txt") + assert response.status_code == 404 + + def raise_name_too_long(path: str): + raise OSError(errno.ENAMETOOLONG, "name too long") + + monkeypatch.setattr(static_files, "lookup_path", raise_name_too_long) + response = TestClient(app).get("/asset.txt") + assert response.status_code == 404 + + def raise_os_error(path: str): + raise OSError(5, "other") + + monkeypatch.setattr(static_files, "lookup_path", raise_os_error) + with pytest.raises(OSError): + TestClient(app).get("/asset.txt") + + +def test_frontend_route_group_helpers(tmp_path: Path): + dist = tmp_path / "dist" + write_file(dist / "index.html", "app") + app = FastAPI() + app.frontend("/", directory=dist) + route_group = app.router._frontend_routes + assert route_group is not None + + match, child_scope = route_group.matches({"type": "websocket", "path": "/"}) + assert match == Match.NONE + assert child_scope == {} + + with pytest.raises(StarletteHTTPException) as exc_info: + anyio.run( + route_group.with_prefix("/app").handle, + {"type": "http", "path": "/missing", "method": "GET"}, + None, + None, + ) + assert exc_info.value.status_code == 404 + + with pytest.raises(NoMatchFound): + route_group.url_path_for("frontend") + with pytest.raises(NoMatchFound): + route_group.routes[0].url_path_for("frontend") + + +def test_included_low_priority_routes_cache_is_reused(): + async def low_priority_endpoint(request: Request): + return PlainTextResponse("low") + + router = APIRouter() + router._low_priority_routes.append(Route("/low", low_priority_endpoint)) + router._mark_routes_changed() + app = FastAPI() + app.include_router(router, prefix="/prefix") + included_router = next( + route + for route in app.router.routes + if hasattr(route, "effective_low_priority_routes") + ) + + first = included_router.effective_low_priority_routes() # ty: ignore[call-non-callable] + second = included_router.effective_low_priority_routes() # ty: ignore[call-non-callable] + response = TestClient(app).get("/prefix/low") + + assert first is second + assert response.status_code == 200 + assert response.text == "low" + + +def test_low_priority_api_route_handles_with_context(): + app = FastAPI() + + async def endpoint(request: Request) -> Response: + return PlainTextResponse(request.scope["path_params"]["item_id"]) + + route = app.router.route_class("/low/{item_id}", endpoint=endpoint, methods=["GET"]) + app.router._low_priority_routes.append(route) + app.router._mark_routes_changed() + + response = TestClient(app).get("/low/abc") + + assert response.status_code == 200 + assert response.text == "abc" + + +def test_included_low_priority_api_route_handles_with_context(): + router = APIRouter() + + async def endpoint(request: Request) -> Response: + return PlainTextResponse(request.scope["path_params"]["item_id"]) + + route = router.route_class("/low/{item_id}", endpoint=endpoint, methods=["GET"]) + router._low_priority_routes.append(route) + router._mark_routes_changed() + app = FastAPI() + app.include_router(router, prefix="/prefix") + + response = TestClient(app).get("/prefix/low/abc") + + assert response.status_code == 200 + assert response.text == "abc" + + +def test_normal_route_partial_match_returns_before_frontend(tmp_path: Path): + class PartialRoute(BaseRoute): + def matches(self, scope): + return Match.PARTIAL, {} + + async def handle(self, scope, receive, send): + response = PlainTextResponse("partial", status_code=405) + await response(scope, receive, send) + + dist = tmp_path / "dist" + write_file(dist / "index.html", "frontend") + app = FastAPI() + app.router.routes.append(PartialRoute()) + app.frontend("/", directory=dist) + + response = TestClient(app).get("/anything") + + assert response.status_code == 405 + assert response.text == "partial" + + +def test_normal_route_partial_match_wins_before_frontend(tmp_path: Path): + dist = tmp_path / "dist" + write_file(dist / "api", "frontend") + app = FastAPI() + + @app.get("/api") + def read_api(): + return {"source": "api"} + + app.frontend("/", directory=dist) + + client = TestClient(app) + + response = client.get("/api") + assert response.status_code == 200 + assert response.json() == {"source": "api"} + + response = client.post("/api") + assert response.status_code == 405 + + +def test_basic_file_serving(tmp_path: Path): + dist = tmp_path / "dist" + write_file(dist / "assets" / "app.js", "console.log('ok')") + app = FastAPI() + app.frontend("/", directory=dist) + + response = TestClient(app).get("/assets/app.js") + + assert response.status_code == 200 + assert response.text == "console.log('ok')" + assert "etag" in response.headers + assert "last-modified" in response.headers + + +def test_existing_api_route_wins_over_frontend(tmp_path: Path): + dist = tmp_path / "dist" + write_file(dist / "api" / "users", "frontend") + app = FastAPI() + + @app.get("/api/users") + def read_users(): + return {"source": "api"} + + app.frontend("/", directory=dist) + + response = TestClient(app).get("/api/users") + + assert response.status_code == 200 + assert response.json() == {"source": "api"} + + +def test_api_route_404_is_not_replaced_by_frontend_fallback(tmp_path: Path): + dist = tmp_path / "dist" + write_file(dist / "index.html", "frontend") + app = FastAPI() + + @app.get("/api/users") + def read_users(): + raise HTTPException(status_code=404, detail="api missing") + + app.frontend("/", directory=dist, fallback="index.html") + + response = TestClient(app).get("/api/users", headers={"accept": "text/html"}) + + assert response.status_code == 404 + assert response.json() == {"detail": "api missing"} + + +def test_index_fallback_for_navigation_request(tmp_path: Path): + dist = tmp_path / "dist" + write_file(dist / "index.html", "app shell") + app = FastAPI() + app.frontend("/", directory=dist, fallback="index.html") + + response = TestClient(app).get( + "/dashboard/settings", headers={"accept": "text/html"} + ) + + assert response.status_code == 200 + assert response.text == "app shell" + + +def test_index_fallback_parses_accept_parameters(tmp_path: Path): + dist = tmp_path / "dist" + write_file(dist / "index.html", "app shell") + app = FastAPI() + app.frontend("/", directory=dist, fallback="index.html") + + response = TestClient(app).get( + "/dashboard/settings", headers={"accept": "text/html; q=0.8"} + ) + + assert response.status_code == 200 + assert response.text == "app shell" + + +def test_index_fallback_ignores_q_zero_accept(tmp_path: Path): + dist = tmp_path / "dist" + write_file(dist / "index.html", "app shell") + app = FastAPI() + app.frontend("/", directory=dist, fallback="index.html") + + response = TestClient(app).get( + "/dashboard/settings", headers={"accept": "text/html; q=0.0"} + ) + + assert response.status_code == 404 + + +def test_index_fallback_respects_explicit_html_rejection_with_wildcard( + tmp_path: Path, +): + dist = tmp_path / "dist" + write_file(dist / "index.html", "app shell") + app = FastAPI() + app.frontend("/", directory=dist, fallback="index.html") + + response = TestClient(app).get( + "/dashboard/settings", + headers={"accept": "text/html; q=0, */*; q=1"}, + ) + + assert response.status_code == 404 + + +def test_index_fallback_respects_explicit_xhtml_rejection_with_wildcard( + tmp_path: Path, +): + dist = tmp_path / "dist" + write_file(dist / "index.html", "app shell") + app = FastAPI() + app.frontend("/", directory=dist, fallback="index.html") + + response = TestClient(app).get( + "/dashboard/settings", + headers={"accept": "application/xhtml+xml; q=0, */*; q=1"}, + ) + + assert response.status_code == 404 + + +@pytest.mark.parametrize( + ("path", "accept"), + [ + ("/assets/missing.js", "*/*"), + ("/assets/missing.css", "text/css"), + ("/assets/missing.png", "image/png"), + ("/api/missing", "application/json"), + ("/users/jane.doe", "text/html"), + ], +) +def test_index_fallback_does_not_handle_asset_like_or_non_html_requests( + tmp_path: Path, path: str, accept: str +): + dist = tmp_path / "dist" + write_file(dist / "index.html", "app shell") + app = FastAPI() + app.frontend("/", directory=dist, fallback="index.html") + + response = TestClient(app).get(path, headers={"accept": accept}) + + assert response.status_code == 404 + assert response.text != "app shell" + + +def test_404_fallback_handles_missing_assets(tmp_path: Path): + dist = tmp_path / "dist" + write_file(dist / "404.html", "missing") + app = FastAPI() + app.frontend("/", directory=dist, fallback="404.html") + + response = TestClient(app).get("/assets/missing.js") + + assert response.status_code == 404 + assert response.text == "missing" + + +def test_auto_fallback_prefers_404_over_index(tmp_path: Path): + dist = tmp_path / "dist" + write_file(dist / "index.html", "app shell") + write_file(dist / "404.html", "missing") + app = FastAPI() + app.frontend("/", directory=dist) + + response = TestClient(app).get("/dashboard", headers={"accept": "text/html"}) + + assert response.status_code == 404 + assert response.text == "missing" + + +def test_auto_fallback_uses_index_when_404_is_missing(tmp_path: Path): + dist = tmp_path / "dist" + write_file(dist / "index.html", "app shell") + app = FastAPI() + app.frontend("/", directory=dist) + + response = TestClient(app).get("/dashboard", headers={"accept": "text/html"}) + + assert response.status_code == 200 + assert response.text == "app shell" + + +def test_auto_fallback_returns_normal_404_without_fallback_files(tmp_path: Path): + dist = tmp_path / "dist" + dist.mkdir() + app = FastAPI() + app.frontend("/", directory=dist) + + response = TestClient(app).get("/dashboard", headers={"accept": "text/html"}) + + assert response.status_code == 404 + assert response.json() == {"detail": "Not Found"} + + +def test_no_fallback_returns_normal_404(tmp_path: Path): + dist = tmp_path / "dist" + write_file(dist / "index.html", "app shell") + app = FastAPI() + app.frontend("/", directory=dist, fallback=None) + + response = TestClient(app).get("/dashboard", headers={"accept": "text/html"}) + + assert response.status_code == 404 + assert response.json() == {"detail": "Not Found"} + + +def test_directory_index_and_redirect(tmp_path: Path): + dist = tmp_path / "dist" + write_file(dist / "about" / "index.html", "about") + app = FastAPI() + app.frontend("/", directory=dist) + client = TestClient(app) + + redirect = client.get("/about", follow_redirects=False) + response = client.get("/about/") + + assert redirect.status_code == 307 + assert redirect.headers["location"] == "http://testserver/about/" + assert response.status_code == 200 + assert response.text == "about" + + +def test_path_validation_and_trailing_slash_normalization(tmp_path: Path): + dist = tmp_path / "dist" + write_file(dist / "asset.txt", "ok") + app = FastAPI() + + with pytest.raises(AssertionError): + app.frontend("", directory=dist) + with pytest.raises(AssertionError): + app.frontend("app", directory=dist) + + app.frontend("/app/", directory=dist) + response = TestClient(app).get("/app/asset.txt") + + assert response.status_code == 200 + assert response.text == "ok" + + +def test_frontend_path_matching_uses_segment_boundaries(tmp_path: Path): + dist = tmp_path / "dist" + write_file(dist / "index.html", "app") + app = FastAPI() + app.frontend("/app", directory=dist, fallback="index.html") + + response = TestClient(app).get("/application", headers={"accept": "text/html"}) + + assert response.status_code == 404 + + +def test_multiple_frontends_use_longest_matching_prefix(tmp_path: Path): + site = tmp_path / "site" + admin = tmp_path / "admin" + write_file(site / "index.html", "site") + write_file(admin / "index.html", "admin") + app = FastAPI() + app.frontend("/", directory=site, fallback="index.html") + app.frontend("/admin", directory=admin, fallback="index.html") + + response = TestClient(app).get("/admin/settings", headers={"accept": "text/html"}) + + assert response.status_code == 200 + assert response.text == "admin" + + +def test_apirouter_frontend_uses_include_prefix(tmp_path: Path): + dist = tmp_path / "admin" + write_file(dist / "index.html", "admin") + router = APIRouter() + router.frontend("/", directory=dist, fallback="index.html") + app = FastAPI() + app.include_router(router, prefix="/admin") + + response = TestClient(app).get("/admin/settings", headers={"accept": "text/html"}) + + assert response.status_code == 200 + assert response.text == "admin" + + +def test_global_priority_across_included_routers(tmp_path: Path): + dist = tmp_path / "site" + write_file(dist / "index.html", "site") + site_router = APIRouter() + site_router.frontend("/", directory=dist, fallback="index.html") + api_router = APIRouter() + + @api_router.get("/api/users") + def read_users(): + return {"source": "api"} + + app = FastAPI() + app.include_router(site_router) + app.include_router(api_router) + + response = TestClient(app).get("/api/users", headers={"accept": "text/html"}) + + assert response.status_code == 200 + assert response.json() == {"source": "api"} + + +def test_nested_apirouter_frontend_uses_all_include_prefixes(tmp_path: Path): + dist = tmp_path / "admin" + write_file(dist / "index.html", "admin") + child_router = APIRouter() + child_router.frontend("/", directory=dist, fallback="index.html") + parent_router = APIRouter() + parent_router.include_router(child_router, prefix="/child") + app = FastAPI() + app.include_router(parent_router, prefix="/parent") + + response = TestClient(app).get( + "/parent/child/settings", headers={"accept": "text/html"} + ) + + assert response.status_code == 200 + assert response.text == "admin" + + +def test_low_priority_cache_updates_after_route_added_to_included_router( + tmp_path: Path, +): + dist = tmp_path / "site" + write_file(dist / "index.html", "site") + router = APIRouter() + router.frontend("/", directory=dist, fallback="index.html") + app = FastAPI() + app.include_router(router, prefix="/app") + client = TestClient(app) + + frontend_response = client.get("/app/dashboard", headers={"accept": "text/html"}) + + @router.get("/dashboard") + def read_dashboard(): + return {"source": "api"} + + api_response = client.get("/app/dashboard", headers={"accept": "text/html"}) + + assert frontend_response.status_code == 200 + assert frontend_response.text == "site" + assert api_response.status_code == 200 + assert api_response.json() == {"source": "api"} + + +def test_normal_route_slash_redirect_wins_before_frontend_redirect(tmp_path: Path): + dist = tmp_path / "site" + write_file(dist / "api" / "index.html", "frontend") + app = FastAPI() + + @app.get("/api/") + def read_api(): + return {"source": "api"} + + app.frontend("/", directory=dist) + + response = TestClient(app).get("/api", follow_redirects=False) + + assert response.status_code == 307 + assert response.headers["location"] == "http://testserver/api/" + + followed = TestClient(app).get("/api/") + assert followed.status_code == 200 + assert followed.json() == {"source": "api"} + + +def test_frontend_respects_root_path(tmp_path: Path): + dist = tmp_path / "dist" + write_file(dist / "assets" / "app.js", "console.log('ok')") + app = FastAPI() + app.frontend("/app", directory=dist) + + response = TestClient(app, root_path="/proxy").get("/app/assets/app.js") + + assert response.status_code == 200 + assert response.text == "console.log('ok')" + + +def test_websocket_route_wins_over_frontend(tmp_path: Path): + dist = tmp_path / "dist" + write_file(dist / "ws", "frontend") + app = FastAPI() + + @app.websocket("/ws") + async def websocket_endpoint(websocket: WebSocket): + await websocket.accept() + await websocket.send_text("websocket") + await websocket.close() + + app.frontend("/", directory=dist) + + with TestClient(app).websocket_connect("/ws") as websocket: + data = websocket.receive_text() + + assert data == "websocket" + + +def test_head_requests_work(tmp_path: Path): + dist = tmp_path / "dist" + write_file(dist / "asset.txt", "ok") + app = FastAPI() + app.frontend("/", directory=dist) + + response = TestClient(app).head("/asset.txt") + + assert response.status_code == 200 + assert response.text == "" + assert response.headers["content-length"] == "2" + + +def test_head_fallback_request_works(tmp_path: Path): + dist = tmp_path / "dist" + write_file(dist / "index.html", "app shell") + app = FastAPI() + app.frontend("/", directory=dist, fallback="index.html") + + response = TestClient(app).head( + "/dashboard/settings", headers={"accept": "text/html"} + ) + + assert response.status_code == 200 + assert response.text == "" + assert response.headers["content-length"] == "9" + + +def test_unsupported_methods_return_405(tmp_path: Path): + dist = tmp_path / "dist" + write_file(dist / "asset.txt", "ok") + app = FastAPI() + app.frontend("/", directory=dist) + + response = TestClient(app).post("/asset.txt") + + assert response.status_code == 405 + + +@pytest.mark.parametrize("method", ["POST", "PUT", "PATCH", "DELETE", "OPTIONS"]) +def test_unsupported_methods_to_fallback_only_routes_return_404( + tmp_path: Path, method: str +): + dist = tmp_path / "dist" + write_file(dist / "index.html", "app shell") + app = FastAPI() + app.frontend("/", directory=dist, fallback="index.html") + + response = TestClient(app).request( + method, "/dashboard/settings", headers={"accept": "text/html"} + ) + + assert response.status_code == 404 + + +def test_unsupported_methods_to_frontend_root_and_directory_index_return_405( + tmp_path: Path, +): + dist = tmp_path / "dist" + write_file(dist / "index.html", "app") + write_file(dist / "about" / "index.html", "about") + app = FastAPI() + app.frontend("/", directory=dist) + client = TestClient(app) + + root_response = client.post("/") + directory_response = client.post("/about/") + + assert root_response.status_code == 405 + assert directory_response.status_code == 405 + + +def test_unsupported_method_to_directory_without_index_returns_404(tmp_path: Path): + dist = tmp_path / "dist" + (dist / "empty").mkdir(parents=True) + write_file(dist / "index.html", "app") + app = FastAPI() + app.frontend("/", directory=dist) + + response = TestClient(app).post("/empty/") + + assert response.status_code == 404 + + +def test_unsupported_methods_to_fallback_only_routes_ignore_accept( + tmp_path: Path, +): + dist = tmp_path / "dist" + write_file(dist / "index.html", "app shell") + app = FastAPI() + app.frontend("/", directory=dist, fallback="index.html") + + response = TestClient(app).post( + "/dashboard/settings", headers={"accept": "application/json"} + ) + + assert response.status_code == 404 + + +@pytest.mark.parametrize( + ("fallback", "files"), + [ + ("404.html", {"404.html": "missing"}), + ("auto", {"index.html": "app shell"}), + (None, {"index.html": "app shell"}), + ], +) +def test_unsupported_methods_to_fallback_only_routes_return_404_for_fallback_modes( + tmp_path: Path, + fallback: Literal["auto", "index.html", "404.html"] | None, + files: dict[str, str], +): + dist = tmp_path / "dist" + for file, content in files.items(): + write_file(dist / file, content) + app = FastAPI() + app.frontend("/", directory=dist, fallback=fallback) + + response = TestClient(app).post( + "/dashboard/settings", headers={"accept": "text/html"} + ) + + assert response.status_code == 404 + + +def test_apirouter_frontend_unsupported_method_to_fallback_only_route_returns_404( + tmp_path: Path, +): + dist = tmp_path / "dist" + write_file(dist / "index.html", "admin") + router = APIRouter() + router.frontend("/", directory=dist, fallback="index.html") + app = FastAPI() + app.include_router(router, prefix="/admin") + + response = TestClient(app).post( + "/admin/client-route", headers={"accept": "text/html"} + ) + + assert response.status_code == 404 + + +def test_unsupported_method_uses_longest_matching_frontend_prefix(tmp_path: Path): + site = tmp_path / "site" + admin = tmp_path / "admin" + write_file(site / "admin" / "client-route", "site asset") + write_file(admin / "index.html", "admin") + app = FastAPI() + app.frontend("/", directory=site) + app.frontend("/admin", directory=admin, fallback="index.html") + + response = TestClient(app).post( + "/admin/client-route", headers={"accept": "text/html"} + ) + + assert response.status_code == 404 + + +@pytest.mark.parametrize( + "path", + [ + "/../secret.txt", + "/%2e%2e/secret.txt", + "/..%2fsecret.txt", + "/%5c..%5csecret.txt", + "/..%5csecret.txt", + ], +) +def test_path_traversal_cannot_escape_directory(tmp_path: Path, path: str): + dist = tmp_path / "dist" + write_file(dist / "index.html", "app") + write_file(tmp_path / "secret.txt", "secret") + app = FastAPI() + app.frontend("/", directory=dist) + + response = TestClient(app).get(path) + + assert response.status_code == 404 + assert response.text != "secret" + + +def test_symlink_outside_directory_is_not_served(tmp_path: Path): + dist = tmp_path / "dist" + dist.mkdir() + outside = tmp_path / "secret.txt" + outside.write_text("secret") + link = dist / "secret.txt" + try: + os.symlink(outside, link) + except (OSError, NotImplementedError): # pragma: no cover + pytest.skip("symlinks are not supported") + app = FastAPI() + app.frontend("/", directory=dist) + + response = TestClient(app).get("/secret.txt") + + assert response.status_code == 404 + assert response.text != "secret" + + +def test_check_dir_true_fails_early_for_missing_directory(monkeypatch, tmp_path: Path): + app = FastAPI() + monkeypatch.chdir(tmp_path) + + with pytest.raises(RuntimeError, match="does not exist") as exc_info: + app.frontend("/", directory="missing") + + message = str(exc_info.value) + assert "'missing'" in message + assert str(tmp_path / "missing") in message + + +def test_check_dir_false_allows_missing_directory_and_fails_on_request(tmp_path: Path): + app = FastAPI() + app.frontend("/", directory=tmp_path / "missing", check_dir=False) + + with pytest.raises(RuntimeError, match="does not exist"): + TestClient(app).get("/asset.txt") + + +def test_explicit_fallback_files_fail_clearly_when_missing(monkeypatch, tmp_path: Path): + dist = tmp_path / "dist" + dist.mkdir() + monkeypatch.chdir(tmp_path) + app = FastAPI() + + with pytest.raises(RuntimeError, match="index.html") as exc_info: + app.frontend("/", directory="dist", fallback="index.html") + + message = str(exc_info.value) + assert "directory 'dist'" in message + assert str(dist) in message + + app = FastAPI() + app.frontend("/", directory="dist", fallback="404.html", check_dir=False) + + with pytest.raises(RuntimeError, match="404.html") as exc_info: + TestClient(app).get("/missing.js") + + message = str(exc_info.value) + assert "directory 'dist'" in message + assert str(dist) in message + + +def test_frontend_routes_are_not_in_openapi(tmp_path: Path): + dist = tmp_path / "dist" + write_file(dist / "index.html", "app") + app = FastAPI() + + @app.get("/api") + def read_api(): + return {"ok": True} + + app.frontend("/", directory=dist, fallback="index.html") + + schema = TestClient(app).get("/openapi.json").json() + + assert set(schema["paths"]) == {"/api"} + + response = TestClient(app).get("/api") + assert response.status_code == 200 + assert response.json() == {"ok": True} + + +@pytest.mark.parametrize( + ("example", "files", "path", "status_code", "body"), + [ + ( + "tutorial001_py310.py", + {"asset.txt": "asset"}, + "/asset.txt", + 200, + "asset", + ), + ( + "tutorial002_py310.py", + {"index.html": "index"}, + "/dashboard", + 200, + "index", + ), + ( + "tutorial003_py310.py", + {"404.html": "missing"}, + "/missing", + 404, + "missing", + ), + ( + "tutorial004_py310.py", + {"index.html": "index"}, + "/app/dashboard", + 200, + "index", + ), + ( + "tutorial005_py310.py", + {"index.html": "index"}, + "/dashboard", + 404, + '{"detail":"Not Found"}', + ), + ( + "tutorial006_py310.py", + {"asset.txt": "asset"}, + "/asset.txt", + 200, + "asset", + ), + ], +) +def test_docs_frontend_examples( + tmp_path: Path, + monkeypatch, + example: str, + files: dict[str, str], + path: str, + status_code: int, + body: str, +): + dist = tmp_path / "dist" + for file, content in files.items(): + write_file(dist / file, content) + monkeypatch.chdir(tmp_path) + + namespace = runpy.run_path( + str(Path(__file__).parents[1] / "docs_src" / "frontend" / example) + ) + + app = namespace["app"] + assert isinstance(app, FastAPI) + response = TestClient(app).get(path, headers={"accept": "text/html"}) + assert response.status_code == status_code + assert response.text == body + + +def test_low_priority_routes_can_store_non_frontend_routes(): + async def low_priority_endpoint(request): + return PlainTextResponse("low") + + app = FastAPI() + app.router._low_priority_routes.append(Route("/low", low_priority_endpoint)) + app.router._mark_routes_changed() + + response = TestClient(app).get("/low") + + assert response.status_code == 200 + assert response.text == "low" + + +def test_included_low_priority_routes_can_store_non_frontend_routes(): + async def low_priority_endpoint(request): + return PlainTextResponse("low") + + router = APIRouter() + router._low_priority_routes.append(Route("/low", low_priority_endpoint)) + router._mark_routes_changed() + app = FastAPI() + app.include_router(router, prefix="/prefix") + + response = TestClient(app).get("/prefix/low") + + assert response.status_code == 200 + assert response.text == "low" diff --git a/tests/test_inherited_custom_class.py b/tests/test_inherited_custom_class.py index 8cf8952f9..54c6566a0 100644 --- a/tests/test_inherited_custom_class.py +++ b/tests/test_inherited_custom_class.py @@ -13,7 +13,7 @@ class MyUuid: def __str__(self): return self.uuid - @property # type: ignore + @property def __class__(self): return uuid.UUID diff --git a/tests/test_jsonable_encoder.py b/tests/test_jsonable_encoder.py index c23a9e5d7..8f8bd3fcb 100644 --- a/tests/test_jsonable_encoder.py +++ b/tests/test_jsonable_encoder.py @@ -87,10 +87,10 @@ def test_encode_dict(): def test_encode_dict_include_exclude_list(): pet = {"name": "Firulais", "owner": {"name": "Foo"}} assert jsonable_encoder(pet) == {"name": "Firulais", "owner": {"name": "Foo"}} - assert jsonable_encoder(pet, include=["name"]) == {"name": "Firulais"} - assert jsonable_encoder(pet, exclude=["owner"]) == {"name": "Firulais"} - assert jsonable_encoder(pet, include=[]) == {} - assert jsonable_encoder(pet, exclude=[]) == { + assert jsonable_encoder(pet, include=["name"]) == {"name": "Firulais"} # ty: ignore[invalid-argument-type] + assert jsonable_encoder(pet, exclude=["owner"]) == {"name": "Firulais"} # ty: ignore[invalid-argument-type] + assert jsonable_encoder(pet, include=[]) == {} # ty: ignore[invalid-argument-type] + assert jsonable_encoder(pet, exclude=[]) == { # ty: ignore[invalid-argument-type] "name": "Firulais", "owner": {"name": "Foo"}, } @@ -176,7 +176,7 @@ def test_encode_model_with_config(): def test_encode_model_with_alias_raises(): with pytest.raises(ValidationError): - ModelWithAlias(foo="Bar") + ModelWithAlias(foo="Bar") # ty: ignore[missing-argument, unknown-argument] def test_encode_model_with_alias(): diff --git a/tests/test_local_docs.py b/tests/test_local_docs.py index 5f102edf1..351161182 100644 --- a/tests/test_local_docs.py +++ b/tests/test_local_docs.py @@ -9,7 +9,7 @@ def test_strings_in_generated_swagger(): swagger_css_url = sig.parameters.get("swagger_css_url").default # type: ignore swagger_favicon_url = sig.parameters.get("swagger_favicon_url").default # type: ignore html = get_swagger_ui_html(openapi_url="/docs", title="title") - body_content = html.body.decode() + body_content = bytes(html.body).decode() assert swagger_js_url in body_content assert swagger_css_url in body_content assert swagger_favicon_url in body_content @@ -26,7 +26,7 @@ def test_strings_in_custom_swagger(): swagger_css_url=swagger_css_url, swagger_favicon_url=swagger_favicon_url, ) - body_content = html.body.decode() + body_content = bytes(html.body).decode() assert swagger_js_url in body_content assert swagger_css_url in body_content assert swagger_favicon_url in body_content @@ -37,7 +37,7 @@ def test_strings_in_generated_redoc(): redoc_js_url = sig.parameters.get("redoc_js_url").default # type: ignore redoc_favicon_url = sig.parameters.get("redoc_favicon_url").default # type: ignore html = get_redoc_html(openapi_url="/docs", title="title") - body_content = html.body.decode() + body_content = bytes(html.body).decode() assert redoc_js_url in body_content assert redoc_favicon_url in body_content @@ -51,17 +51,17 @@ def test_strings_in_custom_redoc(): redoc_js_url=redoc_js_url, redoc_favicon_url=redoc_favicon_url, ) - body_content = html.body.decode() + body_content = bytes(html.body).decode() assert redoc_js_url in body_content assert redoc_favicon_url in body_content def test_google_fonts_in_generated_redoc(): - body_with_google_fonts = get_redoc_html( - openapi_url="/docs", title="title" - ).body.decode() + body_with_google_fonts = bytes( + get_redoc_html(openapi_url="/docs", title="title").body + ).decode() assert "fonts.googleapis.com" in body_with_google_fonts - body_without_google_fonts = get_redoc_html( - openapi_url="/docs", title="title", with_google_fonts=False - ).body.decode() + body_without_google_fonts = bytes( + get_redoc_html(openapi_url="/docs", title="title", with_google_fonts=False).body + ).decode() assert "fonts.googleapis.com" not in body_without_google_fonts diff --git a/tests/test_openapi_schema_type.py b/tests/test_openapi_schema_type.py index e8166d2fb..610375b77 100644 --- a/tests/test_openapi_schema_type.py +++ b/tests/test_openapi_schema_type.py @@ -21,4 +21,4 @@ def test_allowed_schema_type( def test_invalid_type_value() -> None: """Test that Schema raises ValueError for invalid type values.""" with pytest.raises(ValueError, match="2 validation errors for Schema"): - Schema(type=True) # type: ignore[arg-type] + Schema(type=True) # type: ignore[arg-type] # ty: ignore[invalid-argument-type] diff --git a/tests/test_orjson_response_class.py b/tests/test_orjson_response_class.py index 3e34041dc..499b3e585 100644 --- a/tests/test_orjson_response_class.py +++ b/tests/test_orjson_response_class.py @@ -6,13 +6,13 @@ pytest.importorskip("orjson") from fastapi import FastAPI from fastapi.exceptions import FastAPIDeprecationWarning -from fastapi.responses import ORJSONResponse +from fastapi.responses import ORJSONResponse # ty: ignore[deprecated] from fastapi.testclient import TestClient from sqlalchemy.sql.elements import quoted_name with warnings.catch_warnings(): warnings.simplefilter("ignore", FastAPIDeprecationWarning) - app = FastAPI(default_response_class=ORJSONResponse) + app = FastAPI(default_response_class=ORJSONResponse) # ty: ignore[deprecated] @app.get("/orjson_non_str_keys") diff --git a/tests/test_response_model_as_return_annotation.py b/tests/test_response_model_as_return_annotation.py index 7be7902ad..36d50afa9 100644 --- a/tests/test_response_model_as_return_annotation.py +++ b/tests/test_response_model_as_return_annotation.py @@ -78,22 +78,22 @@ def no_response_model_annotation_return_same_model() -> User: @app.get("/no_response_model-annotation-return_exact_dict") def no_response_model_annotation_return_exact_dict() -> User: - return {"name": "John", "surname": "Doe"} + return {"name": "John", "surname": "Doe"} # ty: ignore[invalid-return-type] @app.get("/no_response_model-annotation-return_invalid_dict") def no_response_model_annotation_return_invalid_dict() -> User: - return {"name": "John"} + return {"name": "John"} # ty: ignore[invalid-return-type] @app.get("/no_response_model-annotation-return_invalid_model") def no_response_model_annotation_return_invalid_model() -> User: - return Item(name="Foo", price=42.0) + return Item(name="Foo", price=42.0) # ty: ignore[invalid-return-type] @app.get("/no_response_model-annotation-return_dict_with_extra_data") def no_response_model_annotation_return_dict_with_extra_data() -> User: - return {"name": "John", "surname": "Doe", "password_hash": "secret"} + return {"name": "John", "surname": "Doe", "password_hash": "secret"} # ty: ignore[invalid-return-type] @app.get("/no_response_model-annotation-return_submodel_with_extra_data") @@ -108,24 +108,24 @@ def response_model_none_annotation_return_same_model() -> User: @app.get("/response_model_none-annotation-return_exact_dict", response_model=None) def response_model_none_annotation_return_exact_dict() -> User: - return {"name": "John", "surname": "Doe"} + return {"name": "John", "surname": "Doe"} # ty: ignore[invalid-return-type] @app.get("/response_model_none-annotation-return_invalid_dict", response_model=None) def response_model_none_annotation_return_invalid_dict() -> User: - return {"name": "John"} + return {"name": "John"} # ty: ignore[invalid-return-type] @app.get("/response_model_none-annotation-return_invalid_model", response_model=None) def response_model_none_annotation_return_invalid_model() -> User: - return Item(name="Foo", price=42.0) + return Item(name="Foo", price=42.0) # ty: ignore[invalid-return-type] @app.get( "/response_model_none-annotation-return_dict_with_extra_data", response_model=None ) def response_model_none_annotation_return_dict_with_extra_data() -> User: - return {"name": "John", "surname": "Doe", "password_hash": "secret"} + return {"name": "John", "surname": "Doe", "password_hash": "secret"} # ty: ignore[invalid-return-type] @app.get( @@ -140,21 +140,21 @@ def response_model_none_annotation_return_submodel_with_extra_data() -> User: "/response_model_model1-annotation_model2-return_same_model", response_model=User ) def response_model_model1_annotation_model2_return_same_model() -> Item: - return User(name="John", surname="Doe") + return User(name="John", surname="Doe") # ty: ignore[invalid-return-type] @app.get( "/response_model_model1-annotation_model2-return_exact_dict", response_model=User ) def response_model_model1_annotation_model2_return_exact_dict() -> Item: - return {"name": "John", "surname": "Doe"} + return {"name": "John", "surname": "Doe"} # ty: ignore[invalid-return-type] @app.get( "/response_model_model1-annotation_model2-return_invalid_dict", response_model=User ) def response_model_model1_annotation_model2_return_invalid_dict() -> Item: - return {"name": "John"} + return {"name": "John"} # ty: ignore[invalid-return-type] @app.get( @@ -169,7 +169,7 @@ def response_model_model1_annotation_model2_return_invalid_model() -> Item: response_model=User, ) def response_model_model1_annotation_model2_return_dict_with_extra_data() -> Item: - return {"name": "John", "surname": "Doe", "password_hash": "secret"} + return {"name": "John", "surname": "Doe", "password_hash": "secret"} # ty: ignore[invalid-return-type] @app.get( @@ -177,7 +177,7 @@ def response_model_model1_annotation_model2_return_dict_with_extra_data() -> Ite response_model=User, ) def response_model_model1_annotation_model2_return_submodel_with_extra_data() -> Item: - return DBUser(name="John", surname="Doe", password_hash="secret") + return DBUser(name="John", surname="Doe", password_hash="secret") # ty: ignore[invalid-return-type] @app.get( diff --git a/tests/test_router_events.py b/tests/test_router_events.py index 7869a7afc..e4f5a58f0 100644 --- a/tests/test_router_events.py +++ b/tests/test_router_events.py @@ -31,31 +31,31 @@ def test_router_events(state: State) -> None: def main() -> dict[str, str]: return {"message": "Hello World"} - @app.on_event("startup") + @app.on_event("startup") # ty: ignore[deprecated] def app_startup() -> None: state.app_startup = True - @app.on_event("shutdown") + @app.on_event("shutdown") # ty: ignore[deprecated] def app_shutdown() -> None: state.app_shutdown = True router = APIRouter() - @router.on_event("startup") + @router.on_event("startup") # ty: ignore[deprecated] def router_startup() -> None: state.router_startup = True - @router.on_event("shutdown") + @router.on_event("shutdown") # ty: ignore[deprecated] def router_shutdown() -> None: state.router_shutdown = True sub_router = APIRouter() - @sub_router.on_event("startup") + @sub_router.on_event("startup") # ty: ignore[deprecated] def sub_router_startup() -> None: state.sub_router_startup = True - @sub_router.on_event("shutdown") + @sub_router.on_event("shutdown") # ty: ignore[deprecated] def sub_router_shutdown() -> None: state.sub_router_shutdown = True @@ -253,7 +253,7 @@ def test_router_async_shutdown_handler(state: State) -> None: def main() -> dict[str, str]: return {"message": "Hello World"} - @app.on_event("shutdown") + @app.on_event("shutdown") # ty: ignore[deprecated] async def app_shutdown() -> None: state.app_shutdown = True @@ -274,7 +274,7 @@ def test_router_sync_generator_lifespan(state: State) -> None: yield state.app_shutdown = True - app = FastAPI(lifespan=lifespan) # type: ignore[arg-type] + app = FastAPI(lifespan=lifespan) # type: ignore[invalid-argument-type] # ty: ignore[invalid-argument-type] @app.get("/") def main() -> dict[str, str]: @@ -300,7 +300,7 @@ def test_router_async_generator_lifespan(state: State) -> None: yield state.app_shutdown = True - app = FastAPI(lifespan=lifespan) # type: ignore[arg-type] + app = FastAPI(lifespan=lifespan) # type: ignore[invalid-argument-type] # ty: ignore[invalid-argument-type] @app.get("/") def main() -> dict[str, str]: diff --git a/tests/test_router_include_context.py b/tests/test_router_include_context.py new file mode 100644 index 000000000..cb8dc81fa --- /dev/null +++ b/tests/test_router_include_context.py @@ -0,0 +1,1013 @@ +from typing import Annotated, cast + +import pytest +from fastapi import APIRouter, Body, Depends, FastAPI, Request, Security +from fastapi.exceptions import FastAPIError +from fastapi.openapi.utils import get_openapi +from fastapi.responses import HTMLResponse, JSONResponse, PlainTextResponse +from fastapi.routing import ( + APIRoute, + RouteContext, + _IncludedRouter, + _iter_included_route_candidates, + _restore_fastapi_scope_key, + iter_route_contexts, +) +from fastapi.security import HTTPBearer +from fastapi.testclient import TestClient +from pydantic import BaseModel +from starlette.routing import BaseRoute, Host, Match, Mount, NoMatchFound, Route, Router + + +def dependency_a(): + return "a" + + +def dependency_b(): + return "b" + + +def dependency_c(): + return "c" + + +def unique_id_b(route: APIRoute) -> str: + return f"b_{route.name}" + + +def test_iter_route_contexts_returns_direct_route_context(): + router = APIRouter() + + @router.get("/items/{item_id}") + def read_item(item_id: str): # pragma: no cover + return {"item_id": item_id} + + contexts = list(iter_route_contexts(router.routes)) + + assert len(contexts) == 1 + assert isinstance(contexts[0], RouteContext) + assert contexts[0].original_route is router.routes[0] + assert contexts[0].path == "/items/{item_id}" + assert contexts[0].path_format == "/items/{item_id}" + assert contexts[0].methods == {"GET"} + assert contexts[0].endpoint is read_item + + +def test_iter_route_contexts_supports_nested_conflict_detection(): + existing_router = APIRouter() + nested_router = APIRouter() + + @nested_router.get("/{username}") + def read_user(username: str): # pragma: no cover + return {"username": username} + + existing_router.include_router(nested_router, prefix="/auth/user") + + new_router = APIRouter() + + @new_router.get("/auth/user/{username}") + def read_user_again(username: str): # pragma: no cover + return {"username": username} + + existing_paths = { + context.path for context in iter_route_contexts(existing_router.routes) + } + new_paths = {context.path for context in iter_route_contexts(new_router.routes)} + + assert existing_paths & new_paths == {"/auth/user/{username}"} + + +def test_get_openapi_accepts_filtered_route_contexts_with_effective_paths(): + router = APIRouter() + bearer_scheme = HTTPBearer() + + @router.get("/public", tags=["public"]) + def read_public(token: Annotated[str, Security(bearer_scheme)]): # pragma: no cover + return {"public": True} + + @router.get("/private", tags=["private"]) + def read_private(): # pragma: no cover + return {"private": True} + + app = FastAPI() + app.include_router(router, prefix="/api") + + public_routes = [ + context + for context in iter_route_contexts(app.routes) + if "public" in getattr(context, "tags", []) + ] + schema = get_openapi( + title="Public API", + version="1.0.0", + routes=public_routes, + ) + + assert set(schema["paths"]) == {"/api/public"} + assert "HTTPBearer" in schema["components"]["securitySchemes"] + + +def test_get_openapi_accepts_webhook_route_contexts(): + app = FastAPI() + bearer_scheme = HTTPBearer() + + class Subscription(BaseModel): + username: str + + @app.webhooks.post("new-subscription") + def new_subscription( + body: Subscription, token: Annotated[str, Security(bearer_scheme)] + ): # pragma: no cover + return None + + webhook_contexts = list(iter_route_contexts(app.webhooks.routes)) + schema = get_openapi( + title="Webhook API", + version="1.0.0", + routes=[], + webhooks=webhook_contexts, + ) + + assert set(schema["webhooks"]) == {"new-subscription"} + assert "HTTPBearer" in schema["components"]["securitySchemes"] + assert "Subscription" in schema["components"]["schemas"] + + +def test_router_include_context_matches_flattened_include_metadata(): + callback_router = APIRouter() + + @callback_router.post("/callback") + def callback(): # pragma: no cover + return {"ok": True} + + callback_route = callback_router.routes[0] + + parent_router = APIRouter() + included_router = APIRouter( + prefix="/items", + tags=["router"], + dependencies=[Depends(dependency_a)], + responses={401: {"description": "Unauthorized"}}, + callbacks=[callback_route], + default_response_class=HTMLResponse, + strict_content_type=False, + ) + + @included_router.get( + "/{item_id}", + tags=["route"], + dependencies=[Depends(dependency_b)], + responses={404: {"description": "Missing"}}, + callbacks=[callback_route], + generate_unique_id_function=unique_id_b, + ) + def read_item(item_id: str, request: Request): + context = request.scope["fastapi"]["effective_route_context"] + return JSONResponse( + { + "path": context.path, + "tags": context.tags, + "dependency_count": len(context.dependencies), + "response_codes": sorted(context.responses), + "callback_count": len(context.callbacks or []), + "deprecated": context.deprecated, + "include_in_schema": context.include_in_schema, + "response_class": context.response_class.__name__, + "generate_unique_id": context.generate_unique_id_function(context), + "strict_content_type": context.strict_content_type, + "has_dependency_overrides_provider": ( + context.dependency_overrides_provider + is app.router.dependency_overrides_provider + ), + } + ) + + parent_router.include_router( + included_router, + prefix="/api", + tags=["include"], + dependencies=[Depends(dependency_c)], + responses={400: {"description": "Bad request"}}, + callbacks=[callback_route], + deprecated=True, + include_in_schema=False, + ) + + app = FastAPI() + app.include_router(parent_router) + response = TestClient(app).get("/api/items/foo") + + assert response.status_code == 200 + assert response.json() == { + "path": "/api/items/{item_id}", + "tags": ["include", "router", "route"], + "dependency_count": 3, + "response_codes": [400, 401, 404], + "callback_count": 3, + "deprecated": True, + "include_in_schema": False, + "response_class": "HTMLResponse", + "generate_unique_id": "b_read_item", + "strict_content_type": False, + "has_dependency_overrides_provider": True, + } + + +def test_live_route_addition_uses_include_metadata_for_runtime_and_openapi(): + calls: list[str] = [] + + def included_dependency(): + calls.append("dependency") + + router = APIRouter() + app = FastAPI() + app.include_router( + router, + prefix="/api", + tags=["included"], + dependencies=[Depends(included_dependency)], + responses={418: {"description": "Teapot"}}, + ) + + @router.get("/later") + def read_later(): + return {"later": True} + + client = TestClient(app) + response = client.get("/api/later") + + assert response.status_code == 200 + assert response.json() == {"later": True} + assert calls == ["dependency"] + operation = client.get("/openapi.json").json()["paths"]["/api/later"]["get"] + assert operation["tags"] == ["included"] + assert operation["responses"]["418"] == {"description": "Teapot"} + + +def test_openapi_cache_updates_after_live_route_addition(): + router = APIRouter() + app = FastAPI() + app.include_router(router, prefix="/api") + client = TestClient(app) + + first_schema = client.get("/openapi.json").json() + assert "/api/later" not in first_schema["paths"] + + @router.get("/later") + def read_later(): # pragma: no cover + return {"later": True} + + second_schema = client.get("/openapi.json").json() + assert "/api/later" in second_schema["paths"] + + +def test_nested_router_added_after_parent_inclusion_is_live(): + parent_router = APIRouter() + child_router = APIRouter() + app = FastAPI() + app.include_router(parent_router, prefix="/api") + parent_router.include_router(child_router, prefix="/child", tags=["child"]) + + @child_router.get("/items") + def read_items(): + return ["item"] + + client = TestClient(app) + response = client.get("/api/child/items") + + assert response.status_code == 200 + assert response.json() == ["item"] + operation = client.get("/openapi.json").json()["paths"]["/api/child/items"]["get"] + assert operation["tags"] == ["child"] + + +def test_repeated_deep_inclusions_handle_all_concrete_paths(): + shared_router = APIRouter() + + @shared_router.get("/items") + def read_items(): + return [] + + parent_router = APIRouter() + parent_router.include_router(shared_router, prefix="/a") + parent_router.include_router(shared_router, prefix="/b") + + app = FastAPI() + app.include_router(parent_router, prefix="/v1") + app.include_router(parent_router, prefix="/v2") + + client = TestClient(app) + paths = ["/v1/a/items", "/v1/b/items", "/v2/a/items", "/v2/b/items"] + for path in paths: + response = client.get(path) + assert response.status_code == 200 + assert response.json() == [] + assert set(client.get("/openapi.json").json()["paths"]) == set(paths) + + +def test_url_path_for_uses_effective_context_for_live_included_route(): + router = APIRouter() + app = FastAPI() + app.include_router(router, prefix="/api") + + @router.get("/items/{item_id}", name="read_item") + def read_item(item_id: str): # pragma: no cover + return {"item_id": item_id} + + assert app.url_path_for("read_item", item_id="abc") == "/api/items/abc" + + +def test_url_path_for_uses_distinct_repeated_inclusion_contexts(): + router = APIRouter() + + @router.get("/items/{item_id}", name="read_item") + def read_item(item_id: str): # pragma: no cover + return {"item_id": item_id} + + parent_router = APIRouter() + parent_router.include_router(router, prefix="/v1") + parent_router.include_router(router, prefix="/v2") + + assert parent_router.url_path_for("read_item", item_id="abc") == "/v1/items/abc" + assert ( + parent_router.routes[1].url_path_for("read_item", item_id="abc") + == "/v2/items/abc" + ) + + +def test_indirect_router_inclusion_cycles_are_rejected(): + parent_router = APIRouter() + child_router = APIRouter() + + parent_router.include_router(child_router, prefix="/child") + + with pytest.raises(AssertionError, match="already includes this router"): + child_router.include_router(parent_router, prefix="/parent") + + parent_router = APIRouter() + child_router = APIRouter() + grandchild_router = APIRouter() + + parent_router.include_router(child_router, prefix="/child") + child_router.include_router(grandchild_router, prefix="/grandchild") + + with pytest.raises(AssertionError, match="already includes this router"): + grandchild_router.include_router(parent_router, prefix="/parent") + + +def test_original_api_route_subclass_instance_is_called_after_inclusion(): + class TrackingRoute(APIRoute): + calls = 0 + + async def handle(self, scope, receive, send): + self.calls += 1 + await super().handle(scope, receive, send) + + router = APIRouter(route_class=TrackingRoute) + + @router.get("/items") + def read_items(): + return [] + + original_route = router.routes[0] + assert isinstance(original_route, TrackingRoute) + + app = FastAPI() + app.include_router(router, prefix="/api") + + response = TestClient(app).get("/api/items") + + assert response.status_code == 200 + assert original_route.calls == 1 + + +def test_original_api_route_get_route_handler_is_called_after_inclusion(): + class TrackingRoute(APIRoute): + calls = 0 + + def get_route_handler(self): + handler = super().get_route_handler() + + async def custom_handler(request): + self.calls += 1 + return await handler(request) + + return custom_handler + + router = APIRouter(route_class=TrackingRoute) + + @router.get("/items") + def read_items(): + return [] + + original_route = router.routes[0] + assert isinstance(original_route, TrackingRoute) + original_route.calls = 0 + + app = FastAPI() + app.include_router(router, prefix="/api") + + response = TestClient(app).get("/api/items") + + assert response.status_code == 200 + assert original_route.calls == 1 + + +def test_original_api_route_matches_is_called_after_inclusion(): + class HeaderRoute(APIRoute): + calls = 0 + + def matches(self, scope): + self.calls += 1 + headers = dict(scope.get("headers", [])) + if headers.get(b"x-match") != b"yes": + return Match.NONE, {} + return super().matches(scope) + + router = APIRouter(route_class=HeaderRoute) + + @router.get("/items") + def read_items(): + return [] + + original_route = router.routes[0] + assert isinstance(original_route, HeaderRoute) + original_route.calls = 0 + + app = FastAPI() + app.include_router(router, prefix="/api") + client = TestClient(app) + + assert client.get("/api/items").status_code == 404 + assert client.get("/api/items", headers={"x-match": "yes"}).status_code == 200 + assert original_route.calls >= 2 + + +def test_effective_route_context_is_available_in_scope_during_request(): + router = APIRouter() + + @router.get("/items") + def read_items(request: Request): + fastapi_scope = request.scope.get("fastapi") + assert isinstance(fastapi_scope, dict) + return { + "has_context": "effective_route_context" in fastapi_scope, + "path": fastapi_scope["effective_route_context"].path, + } + + app = FastAPI() + app.include_router(router, prefix="/api") + + response = TestClient(app).get("/api/items") + + assert response.status_code == 200 + assert response.json() == {"has_context": True, "path": "/api/items"} + + +def test_original_api_router_matches_is_called_after_inclusion(): + class HeaderRouter(APIRouter): + calls = 0 + + def matches(self, scope): + self.calls += 1 + headers = dict(scope.get("headers", [])) + if headers.get(b"x-router-match") != b"yes": + return Match.NONE, {} + return super().matches(scope) + + router = HeaderRouter() + + @router.get("/items") + def read_items(): + return [] + + app = FastAPI() + app.include_router(router, prefix="/api") + client = TestClient(app) + + assert client.get("/api/items").status_code == 404 + assert ( + client.get("/api/items", headers={"x-router-match": "yes"}).status_code == 200 + ) + assert router.calls >= 2 + + +def test_original_nested_api_router_subclasses_are_called_after_inclusion(): + class TrackingRouter(APIRouter): + calls = 0 + + async def handle(self, scope, receive, send): + self.calls += 1 + await super().handle(scope, receive, send) + + parent_router = TrackingRouter() + child_router = TrackingRouter() + + @child_router.get("/items") + def read_items(): + return [] + + parent_router.include_router(child_router, prefix="/child") + app = FastAPI() + app.include_router(parent_router, prefix="/api") + + response = TestClient(app).get("/api/child/items") + + assert response.status_code == 200 + assert parent_router.calls == 1 + assert child_router.calls == 1 + + +def test_router_and_include_prefix_path_params_reach_endpoint_and_openapi(): + router = APIRouter(prefix="/tenants/{tenant_id}") + + @router.get("/items/{item_id}") + def read_item(version: int, tenant_id: int, item_id: int): + return {"version": version, "tenant_id": tenant_id, "item_id": item_id} + + app = FastAPI() + app.include_router(router, prefix="/api/{version}") + + client = TestClient(app) + response = client.get("/api/1/tenants/2/items/3") + + assert response.status_code == 200 + assert response.json() == {"version": 1, "tenant_id": 2, "item_id": 3} + + operation = client.get("/openapi.json").json()["paths"][ + "/api/{version}/tenants/{tenant_id}/items/{item_id}" + ]["get"] + assert {parameter["name"] for parameter in operation["parameters"]} == { + "version", + "tenant_id", + "item_id", + } + + +def test_effective_body_fields_from_app_router_include_and_route_match_openapi(): + def app_body_dependency(app_body: Annotated[str, Body()]): + return app_body + + def router_body_dependency(router_body: Annotated[int, Body()]): + return router_body + + def include_body_dependency(include_body: Annotated[bool, Body()]): + return include_body + + app = FastAPI(dependencies=[Depends(app_body_dependency)]) + router = APIRouter(dependencies=[Depends(router_body_dependency)]) + + @router.post("/items") + def create_item(route_body: Annotated[float, Body()]): + return {"route_body": route_body} + + app.include_router( + router, + prefix="/api", + dependencies=[Depends(include_body_dependency)], + ) + + client = TestClient(app) + response = client.post( + "/api/items", + json={ + "app_body": "app", + "router_body": 1, + "include_body": True, + "route_body": 2.5, + }, + ) + + assert response.status_code == 200 + assert response.json() == {"route_body": 2.5} + + schema = client.get("/openapi.json").json() + request_body_schema = schema["paths"]["/api/items"]["post"]["requestBody"][ + "content" + ]["application/json"]["schema"] + body_ref = request_body_schema["$ref"].removeprefix("#/components/schemas/") + body_schema = schema["components"]["schemas"][body_ref] + assert set(body_schema["required"]) == { + "app_body", + "router_body", + "include_body", + "route_body", + } + assert set(body_schema["properties"]) == { + "app_body", + "router_body", + "include_body", + "route_body", + } + + +def test_later_full_match_wins_over_earlier_included_partial_match(): + get_router = APIRouter() + post_router = APIRouter() + + @get_router.get("/items") + def read_items(): # pragma: no cover + return {"method": "get"} + + @post_router.post("/items") + def create_item(): + return {"method": "post"} + + app = FastAPI() + app.include_router(get_router, prefix="/api") + app.include_router(post_router, prefix="/api") + + response = TestClient(app).post("/api/items") + + assert response.status_code == 200 + assert response.json() == {"method": "post"} + + +def test_included_partial_match_returns_405_when_no_later_full_match_exists(): + router = APIRouter() + + @router.get("/items") + def read_items(): # pragma: no cover + return [] + + app = FastAPI() + app.include_router(router, prefix="/api") + + response = TestClient(app).post("/api/items") + + assert response.status_code == 405 + assert response.headers["allow"] == "GET" + + +def test_included_slash_redirect_does_not_block_later_exact_match(): + redirect_router = APIRouter() + exact_router = APIRouter() + + @redirect_router.get("/items/") + def read_items_with_slash(): # pragma: no cover + return {"path": "slash"} + + @exact_router.get("/items") + def read_items_without_slash(): + return {"path": "exact"} + + app = FastAPI() + app.include_router(redirect_router, prefix="/api") + app.include_router(exact_router, prefix="/api") + + response = TestClient(app).get("/api/items", follow_redirects=False) + + assert response.status_code == 200 + assert response.json() == {"path": "exact"} + + +def test_failed_included_match_does_not_leak_effective_context_to_later_route(): + class RejectingRoute(APIRoute): + def matches(self, scope): + return Match.NONE, {} + + rejecting_router = APIRouter(route_class=RejectingRoute) + fallback_router = APIRouter() + + @rejecting_router.get("/items") + def rejected_item(): # pragma: no cover + return {"source": "rejected"} + + @fallback_router.get("/items") + def fallback_item(request: Request): + fastapi_scope = request.scope.get("fastapi", {}) + context = fastapi_scope.get("effective_route_context") + return { + "source": "fallback", + "context_path": getattr(context, "path", None), + } + + app = FastAPI() + app.include_router(rejecting_router, prefix="/api") + app.include_router(fallback_router, prefix="/api") + + response = TestClient(app).get("/api/items") + + assert response.status_code == 200 + assert response.json() == {"source": "fallback", "context_path": "/api/items"} + + +def test_included_starlette_mount_keeps_prefix_runtime_and_url_path_for(): + def mounted_endpoint(request): + return PlainTextResponse("mounted") + + router = APIRouter( + routes=[ + Mount( + "/mounted", + routes=[Route("/items/{item_id}", mounted_endpoint, name="read_item")], + name="mounted", + ) + ] + ) + app = FastAPI() + app.include_router(router, prefix="/api") + + client = TestClient(app) + response = client.get("/api/mounted/items/abc") + + assert response.status_code == 200 + assert response.text == "mounted" + assert ( + app.url_path_for("mounted:read_item", item_id="abc") == "/api/mounted/items/abc" + ) + + +def test_included_starlette_host_keeps_prefix_runtime_and_url_path_for(): + def hosted_endpoint(request): + return PlainTextResponse("hosted") + + hosted_app = Router( + routes=[Route("/items/{item_id}", hosted_endpoint, name="read_item")] + ) + router = APIRouter( + routes=[Host("{subdomain}.example.com", hosted_app, name="hosted")] + ) + app = FastAPI() + app.include_router(router, prefix="/api") + + client = TestClient(app, base_url="http://api.example.com") + response = client.get("/api/items/abc") + + assert response.status_code == 200 + assert response.text == "hosted" + url = app.url_path_for("hosted:read_item", subdomain="api", item_id="abc") + assert str(url) == "/api/items/abc" + assert url.host == "api.example.com" + + +def test_restore_fastapi_scope_key_ignores_non_dict_fastapi_scope(): + scope = {"fastapi": "not-a-dict"} + + _restore_fastapi_scope_key(scope, "effective_route_context", object()) + + assert scope == {"fastapi": "not-a-dict"} + + +@pytest.mark.anyio +async def test_included_api_route_without_app_scope_returns_405_response(): + router = APIRouter() + + @router.get("/items") + def read_items(): # pragma: no cover + return {"items": []} + + app = FastAPI() + app.include_router(router, prefix="/api") + included_router = cast(_IncludedRouter, app.router.routes[-1]) + effective_context = next(included_router.effective_route_contexts()) + route = effective_context.original_route + messages = [] + + async def receive(): # pragma: no cover + return {"type": "http.request", "body": b"", "more_body": False} + + async def send(message): + messages.append(message) + + scope = { + "type": "http", + "method": "POST", + "path": "/api/items", + "raw_path": b"/api/items", + "root_path": "", + "scheme": "http", + "query_string": b"", + "headers": [], + "fastapi": {"effective_route_context": effective_context}, + } + + await route.handle(scope, receive, send) + + assert messages[0]["type"] == "http.response.start" + assert messages[0]["status"] == 405 + assert dict(messages[0]["headers"])[b"allow"] == b"GET" + + +def test_effective_api_route_context_does_not_match_websocket_scope(): + router = APIRouter() + + @router.get("/items") + def read_items(): # pragma: no cover + return {"items": []} + + app = FastAPI() + app.include_router(router, prefix="/api") + included_router = cast(_IncludedRouter, app.router.routes[-1]) + effective_context = next(included_router.effective_route_contexts()) + + match, child_scope = effective_context.matches( + { + "type": "websocket", + "path": "/api/items", + "root_path": "", + } + ) + + assert match == Match.NONE + assert child_scope == {} + + +def test_effective_api_route_context_url_path_for_no_match(): + router = APIRouter() + + @router.get("/items/{item_id}") + def read_item(item_id: str): # pragma: no cover + return {"item_id": item_id} + + app = FastAPI() + app.include_router(router, prefix="/api") + included_router = cast(_IncludedRouter, app.router.routes[-1]) + effective_context = next(included_router.effective_route_contexts()) + + with pytest.raises(NoMatchFound): + effective_context.url_path_for("missing", item_id="abc") + + with pytest.raises(NoMatchFound): + included_router.url_path_for("missing", item_id="abc") + + +def test_included_starlette_host_without_prefix_keeps_original_app(): + def hosted_endpoint(request): + return PlainTextResponse("hosted") + + hosted_app = Router( + routes=[Route("/items/{item_id}", hosted_endpoint, name="read_item")] + ) + router = APIRouter( + routes=[Host("{subdomain}.example.com", hosted_app, name="hosted")] + ) + app = FastAPI() + app.include_router(router) + + client = TestClient(app, base_url="http://api.example.com") + response = client.get("/items/abc") + + assert response.status_code == 200 + assert response.text == "hosted" + + +class UnknownRoute(BaseRoute): + def matches(self, scope): # pragma: no cover + return Match.NONE, {} + + async def handle(self, scope, receive, send): # pragma: no cover + raise AssertionError("UnknownRoute should not be handled") + + def url_path_for(self, name, /, **path_params): # pragma: no cover + raise NoMatchFound(name, path_params) + + +@pytest.mark.anyio +async def test_included_unknown_route_is_ignored_and_can_return_default_404(): + router = APIRouter(routes=[UnknownRoute()]) + app = FastAPI() + app.include_router(router, prefix="/api") + included_router = cast(_IncludedRouter, app.router.routes[-1]) + + assert included_router.effective_candidates() == [] + + messages = [] + + async def receive(): # pragma: no cover + return {"type": "http.request", "body": b"", "more_body": False} + + async def send(message): + messages.append(message) + + scope = { + "type": "http", + "method": "GET", + "path": "/api/missing", + "raw_path": b"/api/missing", + "root_path": "", + "scheme": "http", + "query_string": b"", + "headers": [], + "fastapi": {}, + } + + await included_router._handle_selected(scope, receive, send) + + assert messages[0]["type"] == "http.response.start" + assert messages[0]["status"] == 404 + + +def test_no_prefix_include_validation_sees_effective_starlette_route_candidates(): + def endpoint(request): # pragma: no cover + return PlainTextResponse("ok") + + child_router = APIRouter(routes=[Route("/items", endpoint, name="read_items")]) + parent_router = APIRouter() + parent_router.include_router(child_router, prefix="/child") + + candidates = list(_iter_included_route_candidates(parent_router.routes)) + + assert cast(Route, candidates[0]).path == "/child/items" + + +def test_no_prefix_include_validation_sees_effective_api_route_path(): + leaf_router = APIRouter() + + @leaf_router.get("") + def read_items(): + return [] + + parent_router = APIRouter() + parent_router.include_router(leaf_router, prefix="/items") + + # for coverage + candidates = list(_iter_included_route_candidates(parent_router.routes)) + assert cast(APIRoute, candidates[0]).path == "" + + app = FastAPI() + app.include_router(parent_router) + client = TestClient(app) + + response = client.get("/items") + + assert response.status_code == 200, response.text + assert response.json() == [] + + +def test_no_prefix_include_validation_sees_effective_starlette_route_path(): + def endpoint(request): + return PlainTextResponse("ok") + + child_router = APIRouter(routes=[Route("/items", endpoint, name="read_items")]) + parent_router = APIRouter() + parent_router.include_router(child_router, prefix="/child") + + app = FastAPI() + app.include_router(parent_router) + client = TestClient(app) + + response = client.get("/child/items") + + assert response.status_code == 200, response.text + assert response.text == "ok" + + +def test_no_prefix_include_validation_rejects_empty_effective_api_route_path(): + router = APIRouter() + + @router.get("") + def read_items(): # pragma: no cover + return [] + + app = FastAPI() + with pytest.raises(FastAPIError): + app.include_router(router) + + +def test_apirouter_matches_fallback_without_include_context(): + router = APIRouter() + + def read_items(request): # pragma: no cover + return PlainTextResponse("items") + + router.add_route("/items", read_items) + + assert router.matches({"type": "http", "path": "/items", "root_path": ""}) == ( + Match.NONE, + {}, + ) + + +@pytest.mark.anyio +async def test_apirouter_handle_fallback_without_include_context(): + router = APIRouter() + + def read_items(request): + return PlainTextResponse("items") + + router.add_route("/items", read_items) + messages = [] + + async def receive(): # pragma: no cover + return {"type": "http.request", "body": b"", "more_body": False} + + async def send(message): + messages.append(message) + + scope = { + "type": "http", + "method": "GET", + "path": "/items", + "raw_path": b"/items", + "root_path": "", + "scheme": "http", + "query_string": b"", + "headers": [], + } + + await router.handle(scope, receive, send) + + assert messages[0]["type"] == "http.response.start" + assert messages[0]["status"] == 200 + assert messages[1]["body"] == b"items" diff --git a/tests/test_schema_compat_pydantic_v2.py b/tests/test_schema_compat_pydantic_v2.py index 7612c6ab5..bf47e62b2 100644 --- a/tests/test_schema_compat_pydantic_v2.py +++ b/tests/test_schema_compat_pydantic_v2.py @@ -26,7 +26,7 @@ def get_client(): @app.get("/users") async def get_user() -> User: - return {"username": "alice", "role": "admin"} + return {"username": "alice", "role": "admin"} # ty: ignore[invalid-return-type] client = TestClient(app) return client diff --git a/tests/test_serialize_response_model.py b/tests/test_serialize_response_model.py index bb05f7bc4..6ee55ead8 100644 --- a/tests/test_serialize_response_model.py +++ b/tests/test_serialize_response_model.py @@ -18,7 +18,7 @@ def get_valid(): @app.get("/items/coerce", response_model=Item) def get_coerce(): - return Item(aliased_name="coerce", price="1.0") + return Item(aliased_name="coerce", price="1.0") # ty: ignore[invalid-argument-type] @app.get("/items/validlist", response_model=list[Item]) @@ -52,7 +52,7 @@ def get_valid_exclude_unset(): response_model_exclude_unset=True, ) def get_coerce_exclude_unset(): - return Item(aliased_name="coerce", price="1.0") + return Item(aliased_name="coerce", price="1.0") # ty: ignore[invalid-argument-type] @app.get( diff --git a/tests/test_skip_defaults.py b/tests/test_skip_defaults.py index 238da7392..170cf21e3 100644 --- a/tests/test_skip_defaults.py +++ b/tests/test_skip_defaults.py @@ -29,7 +29,7 @@ class ModelDefaults(BaseModel): @app.get("/", response_model=Model, response_model_exclude_unset=True) def get_root() -> ModelSubclass: - return ModelSubclass(sub={}, y=1, z=0) + return ModelSubclass(sub={}, y=1, z=0) # ty: ignore[invalid-argument-type] @app.get( diff --git a/tests/test_sse.py b/tests/test_sse.py index 86a67f8f9..6a9d669fe 100644 --- a/tests/test_sse.py +++ b/tests/test_sse.py @@ -227,7 +227,7 @@ def test_server_sent_event_single_line_fields_reject_newlines( field_name: str, value: str ): with pytest.raises(ValueError, match=f"SSE '{field_name}' must be a single line"): - ServerSentEvent(data="test", **{field_name: value}) + ServerSentEvent(data="test", **{field_name: value}) # ty: ignore[invalid-argument-type] def test_server_sent_event_negative_retry_rejected(): @@ -237,7 +237,7 @@ def test_server_sent_event_negative_retry_rejected(): def test_server_sent_event_float_retry_rejected(): with pytest.raises(ValueError): - ServerSentEvent(data="test", retry=1.5) # type: ignore[arg-type] + ServerSentEvent(data="test", retry=1.5) # type: ignore[arg-type] # ty: ignore[invalid-argument-type] def test_raw_data_sent_without_json_encoding(client: TestClient): diff --git a/tests/test_starlette_urlconvertors.py b/tests/test_starlette_urlconvertors.py index 5ef1b819c..cebe3dbe8 100644 --- a/tests/test_starlette_urlconvertors.py +++ b/tests/test_starlette_urlconvertors.py @@ -32,7 +32,7 @@ def test_route_converters_int(): response = client.get("/int/5") assert response.status_code == 200, response.text assert response.json() == {"int": 5} - assert app.url_path_for("int_convertor", param=5) == "/int/5" # type: ignore + assert app.url_path_for("int_convertor", param=5) == "/int/5" def test_route_converters_float(): @@ -40,7 +40,7 @@ def test_route_converters_float(): response = client.get("/float/25.5") assert response.status_code == 200, response.text assert response.json() == {"float": 25.5} - assert app.url_path_for("float_convertor", param=25.5) == "/float/25.5" # type: ignore + assert app.url_path_for("float_convertor", param=25.5) == "/float/25.5" def test_route_converters_path(): diff --git a/tests/test_stream_cancellation.py b/tests/test_stream_cancellation.py index 20069c5f6..18e6d67d5 100644 --- a/tests/test_stream_cancellation.py +++ b/tests/test_stream_cancellation.py @@ -10,6 +10,7 @@ import anyio import pytest from fastapi import FastAPI from fastapi.responses import StreamingResponse +from starlette.types import Message, Scope pytestmark = [ pytest.mark.anyio, @@ -45,16 +46,16 @@ async def _run_asgi_and_cancel(app: FastAPI, path: str, timeout: float) -> bool: """ chunks: list[bytes] = [] - async def receive(): # type: ignore[no-untyped-def] + async def receive() -> Message: # Simulate a client that never disconnects, rely on cancellation await anyio.sleep(float("inf")) return {"type": "http.disconnect"} # pragma: no cover - async def send(message: dict) -> None: # type: ignore[type-arg] + async def send(message: Message) -> None: if message["type"] == "http.response.body": chunks.append(message.get("body", b"")) - scope = { + scope: Scope = { "type": "http", "asgi": {"version": "3.0", "spec_version": "2.0"}, "http_version": "1.1", @@ -67,7 +68,7 @@ async def _run_asgi_and_cancel(app: FastAPI, path: str, timeout: float) -> bool: } with anyio.move_on_after(timeout) as cancel_scope: - await app(scope, receive, send) # type: ignore[arg-type] + await app(scope, receive, send) # If we got here within the timeout the generator was cancellable. # cancel_scope.cancelled_caught is True when move_on_after fired. diff --git a/tests/test_swagger_ui_escape.py b/tests/test_swagger_ui_escape.py index 072d21952..6b9851abd 100644 --- a/tests/test_swagger_ui_escape.py +++ b/tests/test_swagger_ui_escape.py @@ -8,7 +8,7 @@ def test_init_oauth_html_chars_are_escaped(): title="Test", init_oauth={"appName": xss_payload}, ) - body = html.body.decode() + body = bytes(html.body).decode() assert "