mirror of https://github.com/tiangolo/fastapi.git
Compare commits
No commits in common. "master" and "0.120.4" have entirely different histories.
|
|
@ -17,7 +17,6 @@ lang-all:
|
||||||
- docs/*/docs/**
|
- docs/*/docs/**
|
||||||
- all-globs-to-all-files:
|
- all-globs-to-all-files:
|
||||||
- '!docs/en/docs/**'
|
- '!docs/en/docs/**'
|
||||||
- '!docs/*/**/_*.md'
|
|
||||||
- '!fastapi/**'
|
- '!fastapi/**'
|
||||||
- '!pyproject.toml'
|
- '!pyproject.toml'
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ jobs:
|
||||||
outputs:
|
outputs:
|
||||||
docs: ${{ steps.filter.outputs.docs }}
|
docs: ${{ steps.filter.outputs.docs }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v6
|
- uses: actions/checkout@v5
|
||||||
# For pull requests it's not necessary to checkout the code but for the main branch it is
|
# For pull requests it's not necessary to checkout the code but for the main branch it is
|
||||||
- uses: dorny/paths-filter@v3
|
- uses: dorny/paths-filter@v3
|
||||||
id: filter
|
id: filter
|
||||||
|
|
@ -32,9 +32,12 @@ jobs:
|
||||||
- docs/**
|
- docs/**
|
||||||
- docs_src/**
|
- docs_src/**
|
||||||
- requirements-docs.txt
|
- requirements-docs.txt
|
||||||
|
- requirements-docs-insiders.txt
|
||||||
- pyproject.toml
|
- pyproject.toml
|
||||||
- mkdocs.yml
|
- mkdocs.yml
|
||||||
- mkdocs.env.yml
|
- mkdocs.insiders.yml
|
||||||
|
- mkdocs.maybe-insiders.yml
|
||||||
|
- mkdocs.no-insiders.yml
|
||||||
- .github/workflows/build-docs.yml
|
- .github/workflows/build-docs.yml
|
||||||
- .github/workflows/deploy-docs.yml
|
- .github/workflows/deploy-docs.yml
|
||||||
- scripts/mkdocs_hooks.py
|
- scripts/mkdocs_hooks.py
|
||||||
|
|
@ -45,7 +48,7 @@ jobs:
|
||||||
outputs:
|
outputs:
|
||||||
langs: ${{ steps.show-langs.outputs.langs }}
|
langs: ${{ steps.show-langs.outputs.langs }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v6
|
- uses: actions/checkout@v5
|
||||||
- name: Set up Python
|
- name: Set up Python
|
||||||
uses: actions/setup-python@v6
|
uses: actions/setup-python@v6
|
||||||
with:
|
with:
|
||||||
|
|
@ -60,6 +63,12 @@ jobs:
|
||||||
pyproject.toml
|
pyproject.toml
|
||||||
- name: Install docs extras
|
- name: Install docs extras
|
||||||
run: uv pip install -r requirements-docs.txt
|
run: uv pip install -r requirements-docs.txt
|
||||||
|
# Install MkDocs Material Insiders here just to put it in the cache for the rest of the steps
|
||||||
|
- name: Install Material for MkDocs Insiders
|
||||||
|
if: ( github.event_name != 'pull_request' || github.secret_source == 'Actions' )
|
||||||
|
run: uv pip install -r requirements-docs-insiders.txt
|
||||||
|
env:
|
||||||
|
TOKEN: ${{ secrets.FASTAPI_MKDOCS_MATERIAL_INSIDERS }}
|
||||||
- name: Verify Docs
|
- name: Verify Docs
|
||||||
run: python ./scripts/docs.py verify-docs
|
run: python ./scripts/docs.py verify-docs
|
||||||
- name: Export Language Codes
|
- name: Export Language Codes
|
||||||
|
|
@ -81,7 +90,7 @@ jobs:
|
||||||
env:
|
env:
|
||||||
GITHUB_CONTEXT: ${{ toJson(github) }}
|
GITHUB_CONTEXT: ${{ toJson(github) }}
|
||||||
run: echo "$GITHUB_CONTEXT"
|
run: echo "$GITHUB_CONTEXT"
|
||||||
- uses: actions/checkout@v6
|
- uses: actions/checkout@v5
|
||||||
- name: Set up Python
|
- name: Set up Python
|
||||||
uses: actions/setup-python@v6
|
uses: actions/setup-python@v6
|
||||||
with:
|
with:
|
||||||
|
|
@ -96,6 +105,11 @@ jobs:
|
||||||
pyproject.toml
|
pyproject.toml
|
||||||
- name: Install docs extras
|
- name: Install docs extras
|
||||||
run: uv pip install -r requirements-docs.txt
|
run: uv pip install -r requirements-docs.txt
|
||||||
|
- name: Install Material for MkDocs Insiders
|
||||||
|
if: ( github.event_name != 'pull_request' || github.secret_source == 'Actions' )
|
||||||
|
run: uv pip install -r requirements-docs-insiders.txt
|
||||||
|
env:
|
||||||
|
TOKEN: ${{ secrets.FASTAPI_MKDOCS_MATERIAL_INSIDERS }}
|
||||||
- name: Update Languages
|
- name: Update Languages
|
||||||
run: python ./scripts/docs.py update-languages
|
run: python ./scripts/docs.py update-languages
|
||||||
- uses: actions/cache@v4
|
- uses: actions/cache@v4
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ jobs:
|
||||||
env:
|
env:
|
||||||
GITHUB_CONTEXT: ${{ toJson(github) }}
|
GITHUB_CONTEXT: ${{ toJson(github) }}
|
||||||
run: echo "$GITHUB_CONTEXT"
|
run: echo "$GITHUB_CONTEXT"
|
||||||
- uses: actions/checkout@v6
|
- uses: actions/checkout@v5
|
||||||
- name: Set up Python
|
- name: Set up Python
|
||||||
uses: actions/setup-python@v6
|
uses: actions/setup-python@v6
|
||||||
with:
|
with:
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ jobs:
|
||||||
env:
|
env:
|
||||||
GITHUB_CONTEXT: ${{ toJson(github) }}
|
GITHUB_CONTEXT: ${{ toJson(github) }}
|
||||||
run: echo "$GITHUB_CONTEXT"
|
run: echo "$GITHUB_CONTEXT"
|
||||||
- uses: actions/checkout@v6
|
- uses: actions/checkout@v5
|
||||||
- name: Set up Python
|
- name: Set up Python
|
||||||
uses: actions/setup-python@v6
|
uses: actions/setup-python@v6
|
||||||
with:
|
with:
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ jobs:
|
||||||
env:
|
env:
|
||||||
GITHUB_CONTEXT: ${{ toJson(github) }}
|
GITHUB_CONTEXT: ${{ toJson(github) }}
|
||||||
run: echo "$GITHUB_CONTEXT"
|
run: echo "$GITHUB_CONTEXT"
|
||||||
- uses: actions/checkout@v6
|
- uses: actions/checkout@v5
|
||||||
- name: Set up Python
|
- name: Set up Python
|
||||||
uses: actions/setup-python@v6
|
uses: actions/setup-python@v6
|
||||||
with:
|
with:
|
||||||
|
|
|
||||||
|
|
@ -24,8 +24,6 @@ jobs:
|
||||||
env:
|
env:
|
||||||
GITHUB_CONTEXT: ${{ toJson(github) }}
|
GITHUB_CONTEXT: ${{ toJson(github) }}
|
||||||
run: echo "$GITHUB_CONTEXT"
|
run: echo "$GITHUB_CONTEXT"
|
||||||
# pin to actions/checkout@v5 for compatibility with latest-changes
|
|
||||||
# Ref: https://github.com/actions/checkout/issues/2313
|
|
||||||
- uses: actions/checkout@v5
|
- uses: actions/checkout@v5
|
||||||
with:
|
with:
|
||||||
# To allow latest-changes to commit to the main branch
|
# To allow latest-changes to commit to the main branch
|
||||||
|
|
@ -36,7 +34,7 @@ jobs:
|
||||||
if: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.debug_enabled == 'true' }}
|
if: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.debug_enabled == 'true' }}
|
||||||
with:
|
with:
|
||||||
limit-access-to-actor: true
|
limit-access-to-actor: true
|
||||||
- uses: tiangolo/latest-changes@0.4.1
|
- uses: tiangolo/latest-changes@0.4.0
|
||||||
with:
|
with:
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
latest_changes_file: docs/en/docs/release-notes.md
|
latest_changes_file: docs/en/docs/release-notes.md
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ jobs:
|
||||||
env:
|
env:
|
||||||
GITHUB_CONTEXT: ${{ toJson(github) }}
|
GITHUB_CONTEXT: ${{ toJson(github) }}
|
||||||
run: echo "$GITHUB_CONTEXT"
|
run: echo "$GITHUB_CONTEXT"
|
||||||
- uses: actions/checkout@v6
|
- uses: actions/checkout@v5
|
||||||
- name: Set up Python
|
- name: Set up Python
|
||||||
uses: actions/setup-python@v6
|
uses: actions/setup-python@v6
|
||||||
with:
|
with:
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ jobs:
|
||||||
env:
|
env:
|
||||||
GITHUB_CONTEXT: ${{ toJson(github) }}
|
GITHUB_CONTEXT: ${{ toJson(github) }}
|
||||||
run: echo "$GITHUB_CONTEXT"
|
run: echo "$GITHUB_CONTEXT"
|
||||||
- uses: actions/checkout@v6
|
- uses: actions/checkout@v5
|
||||||
- name: Set up Python
|
- name: Set up Python
|
||||||
uses: actions/setup-python@v6
|
uses: actions/setup-python@v6
|
||||||
with:
|
with:
|
||||||
|
|
|
||||||
|
|
@ -1,88 +0,0 @@
|
||||||
name: pre-commit
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
types:
|
|
||||||
- opened
|
|
||||||
- synchronize
|
|
||||||
|
|
||||||
env:
|
|
||||||
IS_FORK: ${{ github.event.pull_request.head.repo.full_name != github.repository }}
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
pre-commit:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Dump GitHub context
|
|
||||||
env:
|
|
||||||
GITHUB_CONTEXT: ${{ toJson(github) }}
|
|
||||||
run: echo "$GITHUB_CONTEXT"
|
|
||||||
- uses: actions/checkout@v5
|
|
||||||
name: Checkout PR for own repo
|
|
||||||
if: env.IS_FORK == 'false'
|
|
||||||
with:
|
|
||||||
# To be able to commit it needs more than the last commit
|
|
||||||
ref: ${{ github.head_ref }}
|
|
||||||
# A token other than the default GITHUB_TOKEN is needed to be able to trigger CI
|
|
||||||
token: ${{ secrets.PRE_COMMIT }}
|
|
||||||
# pre-commit lite ci needs the default checkout configs to work
|
|
||||||
- uses: actions/checkout@v5
|
|
||||||
name: Checkout PR for fork
|
|
||||||
if: env.IS_FORK == 'true'
|
|
||||||
- name: Set up Python
|
|
||||||
uses: actions/setup-python@v6
|
|
||||||
with:
|
|
||||||
python-version: "3.14"
|
|
||||||
- name: Setup uv
|
|
||||||
uses: astral-sh/setup-uv@v7
|
|
||||||
with:
|
|
||||||
cache-dependency-glob: |
|
|
||||||
requirements**.txt
|
|
||||||
pyproject.toml
|
|
||||||
uv.lock
|
|
||||||
- name: Install Dependencies
|
|
||||||
run: |
|
|
||||||
uv venv
|
|
||||||
uv pip install -r requirements.txt
|
|
||||||
- name: Run pre-commit
|
|
||||||
id: precommit
|
|
||||||
run: |
|
|
||||||
# Fetch the base branch for comparison
|
|
||||||
git fetch origin ${{ github.base_ref }}
|
|
||||||
uvx pre-commit run --from-ref origin/${{ github.base_ref }} --to-ref HEAD --show-diff-on-failure
|
|
||||||
continue-on-error: true
|
|
||||||
- name: Commit and push changes
|
|
||||||
if: env.IS_FORK == 'false'
|
|
||||||
run: |
|
|
||||||
git config user.name "github-actions[bot]"
|
|
||||||
git config user.email "github-actions[bot]@users.noreply.github.com"
|
|
||||||
git add -A
|
|
||||||
if git diff --staged --quiet; then
|
|
||||||
echo "No changes to commit"
|
|
||||||
else
|
|
||||||
git commit -m "🎨 Auto format"
|
|
||||||
git push
|
|
||||||
fi
|
|
||||||
- uses: pre-commit-ci/lite-action@v1.1.0
|
|
||||||
if: env.IS_FORK == 'true'
|
|
||||||
with:
|
|
||||||
msg: 🎨 Auto format
|
|
||||||
- name: Error out on pre-commit errors
|
|
||||||
if: steps.precommit.outcome == 'failure'
|
|
||||||
run: exit 1
|
|
||||||
|
|
||||||
# https://github.com/marketplace/actions/alls-green#why
|
|
||||||
pre-commit-alls-green: # This job does nothing and is only used for the branch protection
|
|
||||||
if: always()
|
|
||||||
needs:
|
|
||||||
- pre-commit
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Dump GitHub context
|
|
||||||
env:
|
|
||||||
GITHUB_CONTEXT: ${{ toJson(github) }}
|
|
||||||
run: echo "$GITHUB_CONTEXT"
|
|
||||||
- name: Decide whether the needed jobs succeeded or failed
|
|
||||||
uses: re-actors/alls-green@release/v1
|
|
||||||
with:
|
|
||||||
jobs: ${{ toJSON(needs) }}
|
|
||||||
|
|
@ -20,7 +20,7 @@ jobs:
|
||||||
env:
|
env:
|
||||||
GITHUB_CONTEXT: ${{ toJson(github) }}
|
GITHUB_CONTEXT: ${{ toJson(github) }}
|
||||||
run: echo "$GITHUB_CONTEXT"
|
run: echo "$GITHUB_CONTEXT"
|
||||||
- uses: actions/checkout@v6
|
- uses: actions/checkout@v5
|
||||||
- name: Set up Python
|
- name: Set up Python
|
||||||
uses: actions/setup-python@v6
|
uses: actions/setup-python@v6
|
||||||
with:
|
with:
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ env:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
smokeshow:
|
smokeshow:
|
||||||
|
if: ${{ github.event.workflow_run.conclusion == 'success' }}
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
|
|
@ -20,13 +21,15 @@ jobs:
|
||||||
env:
|
env:
|
||||||
GITHUB_CONTEXT: ${{ toJson(github) }}
|
GITHUB_CONTEXT: ${{ toJson(github) }}
|
||||||
run: echo "$GITHUB_CONTEXT"
|
run: echo "$GITHUB_CONTEXT"
|
||||||
- uses: actions/checkout@v6
|
- uses: actions/checkout@v5
|
||||||
- uses: actions/setup-python@v6
|
- uses: actions/setup-python@v6
|
||||||
with:
|
with:
|
||||||
python-version: '3.13'
|
python-version: '3.9'
|
||||||
- name: Setup uv
|
- name: Setup uv
|
||||||
uses: astral-sh/setup-uv@v7
|
uses: astral-sh/setup-uv@v7
|
||||||
with:
|
with:
|
||||||
|
version: "0.4.15"
|
||||||
|
enable-cache: true
|
||||||
cache-dependency-glob: |
|
cache-dependency-glob: |
|
||||||
requirements**.txt
|
requirements**.txt
|
||||||
pyproject.toml
|
pyproject.toml
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ jobs:
|
||||||
env:
|
env:
|
||||||
GITHUB_CONTEXT: ${{ toJson(github) }}
|
GITHUB_CONTEXT: ${{ toJson(github) }}
|
||||||
run: echo "$GITHUB_CONTEXT"
|
run: echo "$GITHUB_CONTEXT"
|
||||||
- uses: actions/checkout@v6
|
- uses: actions/checkout@v5
|
||||||
- name: Set up Python
|
- name: Set up Python
|
||||||
uses: actions/setup-python@v6
|
uses: actions/setup-python@v6
|
||||||
with:
|
with:
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ jobs:
|
||||||
env:
|
env:
|
||||||
GITHUB_CONTEXT: ${{ toJson(github) }}
|
GITHUB_CONTEXT: ${{ toJson(github) }}
|
||||||
run: echo "$GITHUB_CONTEXT"
|
run: echo "$GITHUB_CONTEXT"
|
||||||
- uses: actions/checkout@v6
|
- uses: actions/checkout@v5
|
||||||
- name: Set up Python
|
- name: Set up Python
|
||||||
uses: actions/setup-python@v6
|
uses: actions/setup-python@v6
|
||||||
with:
|
with:
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ jobs:
|
||||||
env:
|
env:
|
||||||
GITHUB_CONTEXT: ${{ toJson(github) }}
|
GITHUB_CONTEXT: ${{ toJson(github) }}
|
||||||
run: echo "$GITHUB_CONTEXT"
|
run: echo "$GITHUB_CONTEXT"
|
||||||
- uses: actions/checkout@v6
|
- uses: actions/checkout@v5
|
||||||
- name: Set up Python
|
- name: Set up Python
|
||||||
uses: actions/setup-python@v6
|
uses: actions/setup-python@v6
|
||||||
with:
|
with:
|
||||||
|
|
@ -31,53 +31,41 @@ jobs:
|
||||||
- name: Setup uv
|
- name: Setup uv
|
||||||
uses: astral-sh/setup-uv@v7
|
uses: astral-sh/setup-uv@v7
|
||||||
with:
|
with:
|
||||||
|
version: "0.4.15"
|
||||||
|
enable-cache: true
|
||||||
cache-dependency-glob: |
|
cache-dependency-glob: |
|
||||||
requirements**.txt
|
requirements**.txt
|
||||||
pyproject.toml
|
pyproject.toml
|
||||||
- name: Install Dependencies
|
- name: Install Dependencies
|
||||||
run: uv pip install -r requirements-tests.txt
|
run: uv pip install -r requirements-tests.txt
|
||||||
|
- name: Install Pydantic v2
|
||||||
|
run: uv pip install --upgrade "pydantic>=2.0.2,<3.0.0"
|
||||||
- name: Lint
|
- name: Lint
|
||||||
run: bash scripts/lint.sh
|
run: bash scripts/lint.sh
|
||||||
|
|
||||||
test:
|
test:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
os: [ windows-latest, macos-latest ]
|
python-version:
|
||||||
python-version: [ "3.14" ]
|
- "3.14"
|
||||||
pydantic-version: [ "pydantic>=2.0.2,<3.0.0" ]
|
- "3.13"
|
||||||
include:
|
- "3.12"
|
||||||
- os: ubuntu-latest
|
- "3.11"
|
||||||
python-version: "3.9"
|
- "3.10"
|
||||||
pydantic-version: "pydantic>=1.10.0,<2.0.0"
|
- "3.9"
|
||||||
coverage: coverage
|
- "3.8"
|
||||||
- os: macos-latest
|
pydantic-version: ["pydantic-v1", "pydantic-v2"]
|
||||||
python-version: "3.10"
|
exclude:
|
||||||
pydantic-version: "pydantic>=2.0.2,<3.0.0"
|
- python-version: "3.14"
|
||||||
- os: windows-latest
|
pydantic-version: "pydantic-v1"
|
||||||
python-version: "3.11"
|
|
||||||
pydantic-version: "pydantic>=1.10.0,<2.0.0"
|
|
||||||
- os: ubuntu-latest
|
|
||||||
python-version: "3.12"
|
|
||||||
pydantic-version: "pydantic>=2.0.2,<3.0.0"
|
|
||||||
- os: macos-latest
|
|
||||||
python-version: "3.13"
|
|
||||||
pydantic-version: "pydantic>=1.10.0,<2.0.0"
|
|
||||||
- os: windows-latest
|
|
||||||
python-version: "3.13"
|
|
||||||
pydantic-version: "pydantic>=2.0.2,<3.0.0"
|
|
||||||
coverage: coverage
|
|
||||||
- os: ubuntu-latest
|
|
||||||
python-version: "3.14"
|
|
||||||
pydantic-version: "pydantic>=2.0.2,<3.0.0"
|
|
||||||
coverage: coverage
|
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
runs-on: ${{ matrix.os }}
|
|
||||||
steps:
|
steps:
|
||||||
- name: Dump GitHub context
|
- name: Dump GitHub context
|
||||||
env:
|
env:
|
||||||
GITHUB_CONTEXT: ${{ toJson(github) }}
|
GITHUB_CONTEXT: ${{ toJson(github) }}
|
||||||
run: echo "$GITHUB_CONTEXT"
|
run: echo "$GITHUB_CONTEXT"
|
||||||
- uses: actions/checkout@v6
|
- uses: actions/checkout@v5
|
||||||
- name: Set up Python
|
- name: Set up Python
|
||||||
uses: actions/setup-python@v6
|
uses: actions/setup-python@v6
|
||||||
with:
|
with:
|
||||||
|
|
@ -92,20 +80,26 @@ jobs:
|
||||||
pyproject.toml
|
pyproject.toml
|
||||||
- name: Install Dependencies
|
- name: Install Dependencies
|
||||||
run: uv pip install -r requirements-tests.txt
|
run: uv pip install -r requirements-tests.txt
|
||||||
- name: Install Pydantic
|
- name: Install Pydantic v1
|
||||||
run: uv pip install "${{ matrix.pydantic-version }}"
|
if: matrix.pydantic-version == 'pydantic-v1'
|
||||||
|
run: uv pip install "pydantic>=1.10.0,<2.0.0"
|
||||||
|
- name: Install Pydantic v2
|
||||||
|
if: matrix.pydantic-version == 'pydantic-v2'
|
||||||
|
run: uv pip install --upgrade "pydantic>=2.0.2,<3.0.0"
|
||||||
|
# TODO: Remove this once Python 3.8 is no longer supported
|
||||||
|
- name: Install older AnyIO in Python 3.8
|
||||||
|
if: matrix.python-version == '3.8'
|
||||||
|
run: uv pip install "anyio[trio]<4.0.0"
|
||||||
- run: mkdir coverage
|
- run: mkdir coverage
|
||||||
- name: Test
|
- name: Test
|
||||||
run: bash scripts/test.sh
|
run: bash scripts/test.sh
|
||||||
env:
|
env:
|
||||||
COVERAGE_FILE: coverage/.coverage.${{ runner.os }}-py${{ matrix.python-version }}
|
COVERAGE_FILE: coverage/.coverage.${{ runner.os }}-py${{ matrix.python-version }}
|
||||||
CONTEXT: ${{ runner.os }}-py${{ matrix.python-version }}
|
CONTEXT: ${{ runner.os }}-py${{ matrix.python-version }}
|
||||||
# Do not store coverage for all possible combinations to avoid file size max errors in Smokeshow
|
|
||||||
- name: Store coverage files
|
- name: Store coverage files
|
||||||
if: matrix.coverage == 'coverage'
|
|
||||||
uses: actions/upload-artifact@v5
|
uses: actions/upload-artifact@v5
|
||||||
with:
|
with:
|
||||||
name: coverage-${{ runner.os }}-${{ matrix.python-version }}-${{ hashFiles('**/coverage/.coverage.*') }}
|
name: coverage-${{ matrix.python-version }}-${{ matrix.pydantic-version }}
|
||||||
path: coverage
|
path: coverage
|
||||||
include-hidden-files: true
|
include-hidden-files: true
|
||||||
|
|
||||||
|
|
@ -117,10 +111,10 @@ jobs:
|
||||||
env:
|
env:
|
||||||
GITHUB_CONTEXT: ${{ toJson(github) }}
|
GITHUB_CONTEXT: ${{ toJson(github) }}
|
||||||
run: echo "$GITHUB_CONTEXT"
|
run: echo "$GITHUB_CONTEXT"
|
||||||
- uses: actions/checkout@v6
|
- uses: actions/checkout@v5
|
||||||
- uses: actions/setup-python@v6
|
- uses: actions/setup-python@v6
|
||||||
with:
|
with:
|
||||||
python-version: '3.11'
|
python-version: '3.8'
|
||||||
- name: Setup uv
|
- name: Setup uv
|
||||||
uses: astral-sh/setup-uv@v7
|
uses: astral-sh/setup-uv@v7
|
||||||
with:
|
with:
|
||||||
|
|
@ -139,6 +133,7 @@ jobs:
|
||||||
merge-multiple: true
|
merge-multiple: true
|
||||||
- run: ls -la coverage
|
- run: ls -la coverage
|
||||||
- run: coverage combine coverage
|
- run: coverage combine coverage
|
||||||
|
- run: coverage report
|
||||||
- run: coverage html --title "Coverage for ${{ github.sha }}"
|
- run: coverage html --title "Coverage for ${{ github.sha }}"
|
||||||
- name: Store coverage HTML
|
- name: Store coverage HTML
|
||||||
uses: actions/upload-artifact@v5
|
uses: actions/upload-artifact@v5
|
||||||
|
|
@ -146,7 +141,6 @@ jobs:
|
||||||
name: coverage-html
|
name: coverage-html
|
||||||
path: htmlcov
|
path: htmlcov
|
||||||
include-hidden-files: true
|
include-hidden-files: true
|
||||||
- run: coverage report --fail-under=100
|
|
||||||
|
|
||||||
# https://github.com/marketplace/actions/alls-green#why
|
# https://github.com/marketplace/actions/alls-green#why
|
||||||
check: # This job does nothing and is only used for the branch protection
|
check: # This job does nothing and is only used for the branch protection
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ jobs:
|
||||||
env:
|
env:
|
||||||
GITHUB_CONTEXT: ${{ toJson(github) }}
|
GITHUB_CONTEXT: ${{ toJson(github) }}
|
||||||
run: echo "$GITHUB_CONTEXT"
|
run: echo "$GITHUB_CONTEXT"
|
||||||
- uses: actions/checkout@v6
|
- uses: actions/checkout@v5
|
||||||
- name: Set up Python
|
- name: Set up Python
|
||||||
uses: actions/setup-python@v6
|
uses: actions/setup-python@v6
|
||||||
with:
|
with:
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,6 @@
|
||||||
name: Translate
|
name: Translate
|
||||||
|
|
||||||
on:
|
on:
|
||||||
schedule:
|
|
||||||
- cron: "0 5 15 * *" # Run at 05:00 on the 15 of every month
|
|
||||||
|
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
inputs:
|
inputs:
|
||||||
debug_enabled:
|
debug_enabled:
|
||||||
|
|
@ -19,7 +16,7 @@ on:
|
||||||
- update-outdated
|
- update-outdated
|
||||||
- add-missing
|
- add-missing
|
||||||
- update-and-add
|
- update-and-add
|
||||||
- remove-removable
|
- remove-all-removable
|
||||||
language:
|
language:
|
||||||
description: Language to translate to as a letter code (e.g. "es" for Spanish)
|
description: Language to translate to as a letter code (e.g. "es" for Spanish)
|
||||||
type: string
|
type: string
|
||||||
|
|
@ -35,42 +32,9 @@ env:
|
||||||
UV_SYSTEM_PYTHON: 1
|
UV_SYSTEM_PYTHON: 1
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
langs:
|
job:
|
||||||
runs-on: ubuntu-latest
|
|
||||||
outputs:
|
|
||||||
langs: ${{ steps.show-langs.outputs.langs }}
|
|
||||||
commands: ${{ steps.show-langs.outputs.commands }}
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v6
|
|
||||||
- name: Set up Python
|
|
||||||
uses: actions/setup-python@v6
|
|
||||||
with:
|
|
||||||
python-version: "3.11"
|
|
||||||
- name: Setup uv
|
|
||||||
uses: astral-sh/setup-uv@v7
|
|
||||||
with:
|
|
||||||
cache-dependency-glob: |
|
|
||||||
requirements**.txt
|
|
||||||
pyproject.toml
|
|
||||||
- name: Install Dependencies
|
|
||||||
run: uv pip install -r requirements-github-actions.txt -r requirements-translations.txt
|
|
||||||
- name: Export Language Codes
|
|
||||||
id: show-langs
|
|
||||||
run: |
|
|
||||||
echo "langs=$(python ./scripts/translate.py llm-translatable-json)" >> $GITHUB_OUTPUT
|
|
||||||
echo "commands=$(python ./scripts/translate.py commands-json)" >> $GITHUB_OUTPUT
|
|
||||||
env:
|
|
||||||
LANGUAGE: ${{ github.event.inputs.language }}
|
|
||||||
COMMAND: ${{ github.event.inputs.command }}
|
|
||||||
|
|
||||||
translate:
|
|
||||||
if: github.repository_owner == 'fastapi'
|
if: github.repository_owner == 'fastapi'
|
||||||
needs: langs
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
lang: ${{ fromJson(needs.langs.outputs.langs) }}
|
|
||||||
command: ${{ fromJson(needs.langs.outputs.commands) }}
|
|
||||||
permissions:
|
permissions:
|
||||||
contents: write
|
contents: write
|
||||||
steps:
|
steps:
|
||||||
|
|
@ -78,9 +42,7 @@ jobs:
|
||||||
env:
|
env:
|
||||||
GITHUB_CONTEXT: ${{ toJson(github) }}
|
GITHUB_CONTEXT: ${{ toJson(github) }}
|
||||||
run: echo "$GITHUB_CONTEXT"
|
run: echo "$GITHUB_CONTEXT"
|
||||||
- uses: actions/checkout@v6
|
- uses: actions/checkout@v5
|
||||||
with:
|
|
||||||
fetch-depth: 0
|
|
||||||
- name: Set up Python
|
- name: Set up Python
|
||||||
uses: actions/setup-python@v6
|
uses: actions/setup-python@v6
|
||||||
with:
|
with:
|
||||||
|
|
@ -88,6 +50,8 @@ jobs:
|
||||||
- name: Setup uv
|
- name: Setup uv
|
||||||
uses: astral-sh/setup-uv@v7
|
uses: astral-sh/setup-uv@v7
|
||||||
with:
|
with:
|
||||||
|
version: "0.4.15"
|
||||||
|
enable-cache: true
|
||||||
cache-dependency-glob: |
|
cache-dependency-glob: |
|
||||||
requirements**.txt
|
requirements**.txt
|
||||||
pyproject.toml
|
pyproject.toml
|
||||||
|
|
@ -104,11 +68,10 @@ jobs:
|
||||||
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
||||||
- name: FastAPI Translate
|
- name: FastAPI Translate
|
||||||
run: |
|
run: |
|
||||||
python ./scripts/translate.py ${{ matrix.command }}
|
python ./scripts/translate.py ${{ github.event.inputs.command }}
|
||||||
python ./scripts/translate.py make-pr
|
python ./scripts/translate.py make-pr
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.FASTAPI_TRANSLATIONS }}
|
GITHUB_TOKEN: ${{ secrets.FASTAPI_TRANSLATIONS }}
|
||||||
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
||||||
LANGUAGE: ${{ matrix.lang }}
|
LANGUAGE: ${{ github.event.inputs.language }}
|
||||||
EN_PATH: ${{ github.event.inputs.en_path }}
|
EN_PATH: ${{ github.event.inputs.en_path }}
|
||||||
COMMAND: ${{ matrix.command }}
|
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,3 @@ archive.zip
|
||||||
|
|
||||||
# macOS
|
# macOS
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
|
||||||
# Ignore while the setup still depends on requirements.txt files
|
|
||||||
uv.lock
|
|
||||||
|
|
|
||||||
|
|
@ -1,29 +1,25 @@
|
||||||
# See https://pre-commit.com for more information
|
# See https://pre-commit.com for more information
|
||||||
# See https://pre-commit.com/hooks.html for more hooks
|
# See https://pre-commit.com/hooks.html for more hooks
|
||||||
|
default_language_version:
|
||||||
|
python: python3.10
|
||||||
repos:
|
repos:
|
||||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||||
rev: v6.0.0
|
rev: v6.0.0
|
||||||
hooks:
|
hooks:
|
||||||
- id: check-added-large-files
|
- id: check-added-large-files
|
||||||
- id: check-toml
|
- id: check-toml
|
||||||
- id: check-yaml
|
- id: check-yaml
|
||||||
args:
|
args:
|
||||||
- --unsafe
|
- --unsafe
|
||||||
- id: end-of-file-fixer
|
- id: end-of-file-fixer
|
||||||
- id: trailing-whitespace
|
- id: trailing-whitespace
|
||||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||||
rev: v0.14.3
|
rev: v0.14.2
|
||||||
hooks:
|
hooks:
|
||||||
- id: ruff
|
- id: ruff
|
||||||
args:
|
args:
|
||||||
- --fix
|
- --fix
|
||||||
- id: ruff-format
|
- id: ruff-format
|
||||||
- repo: local
|
ci:
|
||||||
hooks:
|
autofix_commit_msg: 🎨 [pre-commit.ci] Auto format from pre-commit.com hooks
|
||||||
- id: local-script
|
autoupdate_commit_msg: ⬆ [pre-commit.ci] pre-commit autoupdate
|
||||||
language: unsupported
|
|
||||||
name: local script
|
|
||||||
entry: uv run ./scripts/docs.py add-permalinks-pages
|
|
||||||
args:
|
|
||||||
- --update-existing
|
|
||||||
files: ^docs/en/docs/.*\.md$
|
|
||||||
|
|
|
||||||
60
README.md
60
README.md
|
|
@ -40,16 +40,11 @@ The key features are:
|
||||||
* **Robust**: Get production-ready code. With automatic interactive documentation.
|
* **Robust**: Get production-ready code. With automatic interactive documentation.
|
||||||
* **Standards-based**: Based on (and fully compatible with) the open standards for APIs: <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank">OpenAPI</a> (previously known as Swagger) and <a href="https://json-schema.org/" class="external-link" target="_blank">JSON Schema</a>.
|
* **Standards-based**: Based on (and fully compatible with) the open standards for APIs: <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank">OpenAPI</a> (previously known as Swagger) and <a href="https://json-schema.org/" class="external-link" target="_blank">JSON Schema</a>.
|
||||||
|
|
||||||
<small>* estimation based on tests conducted by an internal development team, building production applications.</small>
|
<small>* estimation based on tests on an internal development team, building production applications.</small>
|
||||||
|
|
||||||
## Sponsors
|
## Sponsors
|
||||||
|
|
||||||
<!-- sponsors -->
|
<!-- sponsors -->
|
||||||
### Keystone Sponsor
|
|
||||||
|
|
||||||
<a href="https://fastapicloud.com" target="_blank" title="FastAPI Cloud. By the same team behind FastAPI. You code. We Cloud."><img src="https://fastapi.tiangolo.com/img/sponsors/fastapicloud.png"></a>
|
|
||||||
|
|
||||||
### Gold and Silver Sponsors
|
|
||||||
|
|
||||||
<a href="https://blockbee.io?ref=fastapi" target="_blank" title="BlockBee Cryptocurrency Payment Gateway"><img src="https://fastapi.tiangolo.com/img/sponsors/blockbee.png"></a>
|
<a href="https://blockbee.io?ref=fastapi" target="_blank" title="BlockBee Cryptocurrency Payment Gateway"><img src="https://fastapi.tiangolo.com/img/sponsors/blockbee.png"></a>
|
||||||
<a href="https://github.com/scalar/scalar/?utm_source=fastapi&utm_medium=website&utm_campaign=main-badge" target="_blank" title="Scalar: Beautiful Open-Source API References from Swagger/OpenAPI files"><img src="https://fastapi.tiangolo.com/img/sponsors/scalar.svg"></a>
|
<a href="https://github.com/scalar/scalar/?utm_source=fastapi&utm_medium=website&utm_campaign=main-badge" target="_blank" title="Scalar: Beautiful Open-Source API References from Swagger/OpenAPI files"><img src="https://fastapi.tiangolo.com/img/sponsors/scalar.svg"></a>
|
||||||
|
|
@ -61,7 +56,6 @@ The key features are:
|
||||||
<a href="https://subtotal.com/?utm_source=fastapi&utm_medium=sponsorship&utm_campaign=open-source" target="_blank" title="The Gold Standard in Retail Account Linking"><img src="https://fastapi.tiangolo.com/img/sponsors/subtotal.svg"></a>
|
<a href="https://subtotal.com/?utm_source=fastapi&utm_medium=sponsorship&utm_campaign=open-source" target="_blank" title="The Gold Standard in Retail Account Linking"><img src="https://fastapi.tiangolo.com/img/sponsors/subtotal.svg"></a>
|
||||||
<a href="https://docs.railway.com/guides/fastapi?utm_medium=integration&utm_source=docs&utm_campaign=fastapi" target="_blank" title="Deploy enterprise applications at startup speed"><img src="https://fastapi.tiangolo.com/img/sponsors/railway.png"></a>
|
<a href="https://docs.railway.com/guides/fastapi?utm_medium=integration&utm_source=docs&utm_campaign=fastapi" target="_blank" title="Deploy enterprise applications at startup speed"><img src="https://fastapi.tiangolo.com/img/sponsors/railway.png"></a>
|
||||||
<a href="https://serpapi.com/?utm_source=fastapi_website" target="_blank" title="SerpApi: Web Search API"><img src="https://fastapi.tiangolo.com/img/sponsors/serpapi.png"></a>
|
<a href="https://serpapi.com/?utm_source=fastapi_website" target="_blank" title="SerpApi: Web Search API"><img src="https://fastapi.tiangolo.com/img/sponsors/serpapi.png"></a>
|
||||||
<a href="https://www.greptile.com/?utm_source=fastapi&utm_medium=sponsorship&utm_campaign=fastapi_sponsor_page" target="_blank" title="Greptile: The AI Code Reviewer"><img src="https://fastapi.tiangolo.com/img/sponsors/greptile.png"></a>
|
|
||||||
<a href="https://databento.com/?utm_source=fastapi&utm_medium=sponsor&utm_content=display" target="_blank" title="Pay as you go for market data"><img src="https://fastapi.tiangolo.com/img/sponsors/databento.svg"></a>
|
<a href="https://databento.com/?utm_source=fastapi&utm_medium=sponsor&utm_content=display" target="_blank" title="Pay as you go for market data"><img src="https://fastapi.tiangolo.com/img/sponsors/databento.svg"></a>
|
||||||
<a href="https://speakeasy.com/editor?utm_source=fastapi+repo&utm_medium=github+sponsorship" target="_blank" title="SDKs for your API | Speakeasy"><img src="https://fastapi.tiangolo.com/img/sponsors/speakeasy.png"></a>
|
<a href="https://speakeasy.com/editor?utm_source=fastapi+repo&utm_medium=github+sponsorship" target="_blank" title="SDKs for your API | Speakeasy"><img src="https://fastapi.tiangolo.com/img/sponsors/speakeasy.png"></a>
|
||||||
<a href="https://www.svix.com/" target="_blank" title="Svix - Webhooks as a service"><img src="https://fastapi.tiangolo.com/img/sponsors/svix.svg"></a>
|
<a href="https://www.svix.com/" target="_blank" title="Svix - Webhooks as a service"><img src="https://fastapi.tiangolo.com/img/sponsors/svix.svg"></a>
|
||||||
|
|
@ -453,58 +447,6 @@ For a more complete example including more features, see the <a href="https://fa
|
||||||
* **Cookie Sessions**
|
* **Cookie Sessions**
|
||||||
* ...and more.
|
* ...and more.
|
||||||
|
|
||||||
### Deploy your app (optional)
|
|
||||||
|
|
||||||
You can optionally deploy your FastAPI app to <a href="https://fastapicloud.com" class="external-link" target="_blank">FastAPI Cloud</a>, 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:
|
|
||||||
|
|
||||||
<div class="termy">
|
|
||||||
|
|
||||||
```console
|
|
||||||
$ fastapi login
|
|
||||||
|
|
||||||
You are logged in to FastAPI Cloud 🚀
|
|
||||||
```
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
Then deploy your app:
|
|
||||||
|
|
||||||
<div class="termy">
|
|
||||||
|
|
||||||
```console
|
|
||||||
$ fastapi deploy
|
|
||||||
|
|
||||||
Deploying to FastAPI Cloud...
|
|
||||||
|
|
||||||
✅ Deployment successful!
|
|
||||||
|
|
||||||
🐔 Ready the chicken! Your app is ready at https://myapp.fastapicloud.dev
|
|
||||||
```
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
That's it! Now you can access your app at that URL. ✨
|
|
||||||
|
|
||||||
#### About FastAPI Cloud
|
|
||||||
|
|
||||||
**<a href="https://fastapicloud.com" class="external-link" target="_blank">FastAPI Cloud</a>** is built by the same author and team behind **FastAPI**.
|
|
||||||
|
|
||||||
It streamlines the process of **building**, **deploying**, and **accessing** an API with minimal effort.
|
|
||||||
|
|
||||||
It brings the same **developer experience** of building apps with FastAPI to **deploying** them to the cloud. 🎉
|
|
||||||
|
|
||||||
FastAPI Cloud is the primary sponsor and funding provider for the *FastAPI and friends* open source projects. ✨
|
|
||||||
|
|
||||||
#### Deploy to other cloud providers
|
|
||||||
|
|
||||||
FastAPI is open source and based on standards. You can deploy FastAPI apps to any cloud provider you choose.
|
|
||||||
|
|
||||||
Follow your cloud provider's guides to deploy FastAPI apps with them. 🤓
|
|
||||||
|
|
||||||
## Performance
|
## Performance
|
||||||
|
|
||||||
Independent TechEmpower benchmarks show **FastAPI** applications running under Uvicorn as <a href="https://www.techempower.com/benchmarks/#section=test&runid=7464e520-0dc2-473d-bd34-dbdfd7e85911&hw=ph&test=query&l=zijzen-7" class="external-link" target="_blank">one of the fastest Python frameworks available</a>, only below Starlette and Uvicorn themselves (used internally by FastAPI). (*)
|
Independent TechEmpower benchmarks show **FastAPI** applications running under Uvicorn as <a href="https://www.techempower.com/benchmarks/#section=test&runid=7464e520-0dc2-473d-bd34-dbdfd7e85911&hw=ph&test=query&l=zijzen-7" class="external-link" target="_blank">one of the fastest Python frameworks available</a>, only below Starlette and Uvicorn themselves (used internally by FastAPI). (*)
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ So verwenden:
|
||||||
|
|
||||||
Die Tests:
|
Die Tests:
|
||||||
|
|
||||||
## Codeschnipsel { #code-snippets }
|
## Codeschnipsel { #code-snippets}
|
||||||
|
|
||||||
//// tab | Test
|
//// tab | Test
|
||||||
|
|
||||||
|
|
@ -53,7 +53,7 @@ Siehe zum Beispiel den Abschnitt `### Quotes` in `docs/de/llm-prompt.md`.
|
||||||
|
|
||||||
////
|
////
|
||||||
|
|
||||||
## Anführungszeichen in Codeschnipseln { #quotes-in-code-snippets }
|
## Anführungszeichen in Codeschnipseln { #quotes-in-code-snippets}
|
||||||
|
|
||||||
//// tab | Test
|
//// tab | Test
|
||||||
|
|
||||||
|
|
@ -443,7 +443,7 @@ Für einige sprachspezifische Anweisungen, siehe z. B. den Abschnitt `### Headin
|
||||||
* die Workload
|
* die Workload
|
||||||
|
|
||||||
* das Deployment
|
* das Deployment
|
||||||
* deployen
|
* bereitstellen
|
||||||
|
|
||||||
* das SDK
|
* das SDK
|
||||||
* das Software Development Kit
|
* das Software Development Kit
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ Jedes dieser Response-`dict`s kann einen Schlüssel `model` haben, welcher ein P
|
||||||
|
|
||||||
Um beispielsweise eine weitere Response mit dem Statuscode `404` und einem Pydantic-Modell `Message` zu deklarieren, können Sie schreiben:
|
Um beispielsweise eine weitere Response mit dem Statuscode `404` und einem Pydantic-Modell `Message` zu deklarieren, können Sie schreiben:
|
||||||
|
|
||||||
{* ../../docs_src/additional_responses/tutorial001_py39.py hl[18,22] *}
|
{* ../../docs_src/additional_responses/tutorial001.py hl[18,22] *}
|
||||||
|
|
||||||
/// note | Hinweis
|
/// note | Hinweis
|
||||||
|
|
||||||
|
|
@ -175,7 +175,7 @@ Sie können denselben `responses`-Parameter verwenden, um verschiedene Medientyp
|
||||||
|
|
||||||
Sie können beispielsweise einen zusätzlichen Medientyp `image/png` hinzufügen und damit deklarieren, dass Ihre *Pfadoperation* ein JSON-Objekt (mit dem Medientyp `application/json`) oder ein PNG-Bild zurückgeben kann:
|
Sie können beispielsweise einen zusätzlichen Medientyp `image/png` hinzufügen und damit deklarieren, dass Ihre *Pfadoperation* ein JSON-Objekt (mit dem Medientyp `application/json`) oder ein PNG-Bild zurückgeben kann:
|
||||||
|
|
||||||
{* ../../docs_src/additional_responses/tutorial002_py310.py hl[17:22,26] *}
|
{* ../../docs_src/additional_responses/tutorial002.py hl[19:24,28] *}
|
||||||
|
|
||||||
/// note | Hinweis
|
/// note | Hinweis
|
||||||
|
|
||||||
|
|
@ -203,7 +203,7 @@ Sie können beispielsweise eine Response mit dem Statuscode `404` deklarieren, d
|
||||||
|
|
||||||
Und eine Response mit dem Statuscode `200`, die Ihr `response_model` verwendet, aber ein benutzerdefiniertes Beispiel (`example`) enthält:
|
Und eine Response mit dem Statuscode `200`, die Ihr `response_model` verwendet, aber ein benutzerdefiniertes Beispiel (`example`) enthält:
|
||||||
|
|
||||||
{* ../../docs_src/additional_responses/tutorial003_py39.py hl[20:31] *}
|
{* ../../docs_src/additional_responses/tutorial003.py hl[20:31] *}
|
||||||
|
|
||||||
Es wird alles kombiniert und in Ihre OpenAPI eingebunden und in der API-Dokumentation angezeigt:
|
Es wird alles kombiniert und in Ihre OpenAPI eingebunden und in der API-Dokumentation angezeigt:
|
||||||
|
|
||||||
|
|
@ -237,7 +237,7 @@ Mit dieser Technik können Sie einige vordefinierte Responses in Ihren *Pfadoper
|
||||||
|
|
||||||
Zum Beispiel:
|
Zum Beispiel:
|
||||||
|
|
||||||
{* ../../docs_src/additional_responses/tutorial004_py310.py hl[11:15,24] *}
|
{* ../../docs_src/additional_responses/tutorial004.py hl[13:17,26] *}
|
||||||
|
|
||||||
## Weitere Informationen zu OpenAPI-Responses { #more-information-about-openapi-responses }
|
## Weitere Informationen zu OpenAPI-Responses { #more-information-about-openapi-responses }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -70,22 +70,12 @@ Wenn Sie das hier alles verstanden haben, wissen Sie bereits, wie diese Sicherhe
|
||||||
|
|
||||||
Sie benötigen diese technischen Details höchstwahrscheinlich nicht.
|
Sie benötigen diese technischen Details höchstwahrscheinlich nicht.
|
||||||
|
|
||||||
Diese Details sind hauptsächlich nützlich, wenn Sie eine FastAPI-Anwendung haben, die älter als 0.121.0 ist, und Sie auf Probleme mit Abhängigkeiten mit `yield` stoßen.
|
Diese Details sind hauptsächlich nützlich, wenn Sie eine FastAPI-Anwendung haben, die älter als 0.118.0 ist, und Sie auf Probleme mit Abhängigkeiten mit `yield` stoßen.
|
||||||
|
|
||||||
///
|
///
|
||||||
|
|
||||||
Abhängigkeiten mit `yield` haben sich im Laufe der Zeit weiterentwickelt, um verschiedene Anwendungsfälle abzudecken und einige Probleme zu beheben, hier ist eine Zusammenfassung der Änderungen.
|
Abhängigkeiten mit `yield` haben sich im Laufe der Zeit weiterentwickelt, um verschiedene Anwendungsfälle abzudecken und einige Probleme zu beheben, hier ist eine Zusammenfassung der Änderungen.
|
||||||
|
|
||||||
### Abhängigkeiten mit `yield` und `scope` { #dependencies-with-yield-and-scope }
|
|
||||||
|
|
||||||
In Version 0.121.0 hat FastAPI Unterstützung für `Depends(scope="function")` für Abhängigkeiten mit `yield` hinzugefügt.
|
|
||||||
|
|
||||||
Mit `Depends(scope="function")` wird der Exit-Code nach `yield` direkt nach dem Ende der *Pfadoperation-Funktion* ausgeführt, bevor die Response an den Client gesendet wird.
|
|
||||||
|
|
||||||
Und bei Verwendung von `Depends(scope="request")` (dem Default) wird der Exit-Code nach `yield` ausgeführt, nachdem die Response gesendet wurde.
|
|
||||||
|
|
||||||
Mehr dazu finden Sie in der Dokumentation zu [Abhängigkeiten mit `yield` – Frühes Beenden und `scope`](../tutorial/dependencies/dependencies-with-yield.md#early-exit-and-scope).
|
|
||||||
|
|
||||||
### Abhängigkeiten mit `yield` und `StreamingResponse`, Technische Details { #dependencies-with-yield-and-streamingresponse-technical-details }
|
### Abhängigkeiten mit `yield` und `StreamingResponse`, Technische Details { #dependencies-with-yield-and-streamingresponse-technical-details }
|
||||||
|
|
||||||
Vor FastAPI 0.118.0 wurde bei Verwendung einer Abhängigkeit mit `yield` der Exit-Code nach der *Pfadoperation-Funktion* ausgeführt, aber unmittelbar bevor die Response gesendet wurde.
|
Vor FastAPI 0.118.0 wurde bei Verwendung einer Abhängigkeit mit `yield` der Exit-Code nach der *Pfadoperation-Funktion* ausgeführt, aber unmittelbar bevor die Response gesendet wurde.
|
||||||
|
|
@ -144,7 +134,7 @@ Dies wurde in Version 0.110.0 geändert, um unbehandelten Speicherverbrauch durc
|
||||||
|
|
||||||
### Hintergrundtasks und Abhängigkeiten mit `yield`, Technische Details { #background-tasks-and-dependencies-with-yield-technical-details }
|
### Hintergrundtasks und Abhängigkeiten mit `yield`, Technische Details { #background-tasks-and-dependencies-with-yield-technical-details }
|
||||||
|
|
||||||
Vor FastAPI 0.106.0 war das Werfen von Exceptions nach `yield` nicht möglich, der Exit-Code in Abhängigkeiten mit `yield` wurde ausgeführt, nachdem die Response gesendet wurde, sodass [Exceptionhandler](../tutorial/handling-errors.md#install-custom-exception-handlers){.internal-link target=_blank} bereits ausgeführt worden wären.
|
Vor FastAPI 0.106.0 war das Werfen von Exceptions nach `yield` nicht möglich, der Exit-Code in Abhängigkeiten mit `yield` wurde ausgeführt, nachdem die Response gesendet wurde, sodass [Exceptionhandler](../handling-errors.md#install-custom-exception-handlers){.internal-link target=_blank} bereits ausgeführt worden wären.
|
||||||
|
|
||||||
Dies war so designt, hauptsächlich um die Verwendung derselben von Abhängigkeiten „geyieldeten“ Objekte in Hintergrundtasks zu ermöglichen, da der Exit-Code erst ausgeführt wurde, nachdem die Hintergrundtasks abgeschlossen waren.
|
Dies war so designt, hauptsächlich um die Verwendung derselben von Abhängigkeiten „geyieldeten“ Objekte in Hintergrundtasks zu ermöglichen, da der Exit-Code erst ausgeführt wurde, nachdem die Hintergrundtasks abgeschlossen waren.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,11 +32,11 @@ Betrachten wir als einfaches Beispiel eine Dateistruktur ähnlich der in [Größ
|
||||||
|
|
||||||
Die Datei `main.py` hätte als Inhalt:
|
Die Datei `main.py` hätte als Inhalt:
|
||||||
|
|
||||||
{* ../../docs_src/async_tests/app_a_py39/main.py *}
|
{* ../../docs_src/async_tests/main.py *}
|
||||||
|
|
||||||
Die Datei `test_main.py` hätte die Tests für `main.py`, das könnte jetzt so aussehen:
|
Die Datei `test_main.py` hätte die Tests für `main.py`, das könnte jetzt so aussehen:
|
||||||
|
|
||||||
{* ../../docs_src/async_tests/app_a_py39/test_main.py *}
|
{* ../../docs_src/async_tests/test_main.py *}
|
||||||
|
|
||||||
## Es ausführen { #run-it }
|
## Es ausführen { #run-it }
|
||||||
|
|
||||||
|
|
@ -56,7 +56,7 @@ $ pytest
|
||||||
|
|
||||||
Der Marker `@pytest.mark.anyio` teilt pytest mit, dass diese Testfunktion asynchron aufgerufen werden soll:
|
Der Marker `@pytest.mark.anyio` teilt pytest mit, dass diese Testfunktion asynchron aufgerufen werden soll:
|
||||||
|
|
||||||
{* ../../docs_src/async_tests/app_a_py39/test_main.py hl[7] *}
|
{* ../../docs_src/async_tests/test_main.py hl[7] *}
|
||||||
|
|
||||||
/// tip | Tipp
|
/// tip | Tipp
|
||||||
|
|
||||||
|
|
@ -66,7 +66,7 @@ Beachten Sie, dass die Testfunktion jetzt `async def` ist und nicht nur `def` wi
|
||||||
|
|
||||||
Dann können wir einen `AsyncClient` mit der App erstellen und mit `await` asynchrone Requests an ihn senden.
|
Dann können wir einen `AsyncClient` mit der App erstellen und mit `await` asynchrone Requests an ihn senden.
|
||||||
|
|
||||||
{* ../../docs_src/async_tests/app_a_py39/test_main.py hl[9:12] *}
|
{* ../../docs_src/async_tests/test_main.py hl[9:12] *}
|
||||||
|
|
||||||
Das ist das Äquivalent zu:
|
Das ist das Äquivalent zu:
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,7 @@ $ fastapi run --forwarded-allow-ips="*"
|
||||||
|
|
||||||
Angenommen, Sie definieren eine *Pfadoperation* `/items/`:
|
Angenommen, Sie definieren eine *Pfadoperation* `/items/`:
|
||||||
|
|
||||||
{* ../../docs_src/behind_a_proxy/tutorial001_01_py39.py hl[6] *}
|
{* ../../docs_src/behind_a_proxy/tutorial001_01.py hl[6] *}
|
||||||
|
|
||||||
Wenn der Client versucht, zu `/items` zu gehen, würde er standardmäßig zu `/items/` umgeleitet.
|
Wenn der Client versucht, zu `/items` zu gehen, würde er standardmäßig zu `/items/` umgeleitet.
|
||||||
|
|
||||||
|
|
@ -64,7 +64,7 @@ Wenn Sie mehr über HTTPS erfahren möchten, lesen Sie den Leitfaden [Über HTTP
|
||||||
|
|
||||||
///
|
///
|
||||||
|
|
||||||
### Wie Proxy-Forwarded-Header funktionieren { #how-proxy-forwarded-headers-work }
|
### Wie Proxy-Forwarded-Header funktionieren
|
||||||
|
|
||||||
Hier ist eine visuelle Darstellung, wie der **Proxy** weitergeleitete Header zwischen dem Client und dem **Anwendungsserver** hinzufügt:
|
Hier ist eine visuelle Darstellung, wie der **Proxy** weitergeleitete Header zwischen dem Client und dem **Anwendungsserver** hinzufügt:
|
||||||
|
|
||||||
|
|
@ -115,7 +115,7 @@ In diesem Fall würde der ursprüngliche Pfad `/app` tatsächlich unter `/api/v1
|
||||||
|
|
||||||
Auch wenn Ihr gesamter Code unter der Annahme geschrieben ist, dass es nur `/app` gibt.
|
Auch wenn Ihr gesamter Code unter der Annahme geschrieben ist, dass es nur `/app` gibt.
|
||||||
|
|
||||||
{* ../../docs_src/behind_a_proxy/tutorial001_py39.py hl[6] *}
|
{* ../../docs_src/behind_a_proxy/tutorial001.py hl[6] *}
|
||||||
|
|
||||||
Und der Proxy würde das **Pfadpräfix** on-the-fly **„entfernen“**, bevor er den <abbr title="Request – Anfrage: Daten, die der Client zum Server sendet">Request</abbr> an den Anwendungsserver (wahrscheinlich Uvicorn via FastAPI CLI) übermittelt, dafür sorgend, dass Ihre Anwendung davon überzeugt ist, dass sie unter `/app` bereitgestellt wird, sodass Sie nicht Ihren gesamten Code dahingehend aktualisieren müssen, das Präfix `/api/v1` zu verwenden.
|
Und der Proxy würde das **Pfadpräfix** on-the-fly **„entfernen“**, bevor er den <abbr title="Request – Anfrage: Daten, die der Client zum Server sendet">Request</abbr> an den Anwendungsserver (wahrscheinlich Uvicorn via FastAPI CLI) übermittelt, dafür sorgend, dass Ihre Anwendung davon überzeugt ist, dass sie unter `/app` bereitgestellt wird, sodass Sie nicht Ihren gesamten Code dahingehend aktualisieren müssen, das Präfix `/api/v1` zu verwenden.
|
||||||
|
|
||||||
|
|
@ -193,7 +193,7 @@ Sie können den aktuellen `root_path` abrufen, der von Ihrer Anwendung für jede
|
||||||
|
|
||||||
Hier fügen wir ihn, nur zu Demonstrationszwecken, in die Nachricht ein.
|
Hier fügen wir ihn, nur zu Demonstrationszwecken, in die Nachricht ein.
|
||||||
|
|
||||||
{* ../../docs_src/behind_a_proxy/tutorial001_py39.py hl[8] *}
|
{* ../../docs_src/behind_a_proxy/tutorial001.py hl[8] *}
|
||||||
|
|
||||||
Wenn Sie Uvicorn dann starten mit:
|
Wenn Sie Uvicorn dann starten mit:
|
||||||
|
|
||||||
|
|
@ -220,7 +220,7 @@ wäre die <abbr title="Response – Antwort: Daten, die der Server zum anfragend
|
||||||
|
|
||||||
Falls Sie keine Möglichkeit haben, eine Kommandozeilenoption wie `--root-path` oder ähnlich zu übergeben, können Sie, alternativ dazu, beim Erstellen Ihrer FastAPI-Anwendung den Parameter `root_path` setzen:
|
Falls Sie keine Möglichkeit haben, eine Kommandozeilenoption wie `--root-path` oder ähnlich zu übergeben, können Sie, alternativ dazu, beim Erstellen Ihrer FastAPI-Anwendung den Parameter `root_path` setzen:
|
||||||
|
|
||||||
{* ../../docs_src/behind_a_proxy/tutorial002_py39.py hl[3] *}
|
{* ../../docs_src/behind_a_proxy/tutorial002.py hl[3] *}
|
||||||
|
|
||||||
Die Übergabe des `root_path` an `FastAPI` wäre das Äquivalent zur Übergabe der `--root-path`-Kommandozeilenoption an Uvicorn oder Hypercorn.
|
Die Übergabe des `root_path` an `FastAPI` wäre das Äquivalent zur Übergabe der `--root-path`-Kommandozeilenoption an Uvicorn oder Hypercorn.
|
||||||
|
|
||||||
|
|
@ -228,7 +228,7 @@ Die Übergabe des `root_path` an `FastAPI` wäre das Äquivalent zur Übergabe d
|
||||||
|
|
||||||
Beachten Sie, dass der Server (Uvicorn) diesen `root_path` für nichts anderes verwendet als für die Weitergabe an die Anwendung.
|
Beachten Sie, dass der Server (Uvicorn) diesen `root_path` für nichts anderes verwendet als für die Weitergabe an die Anwendung.
|
||||||
|
|
||||||
Aber wenn Sie mit Ihrem Browser auf <a href="http://127.0.0.1:8000/app" class="external-link" target="_blank">http://127.0.0.1:8000/app</a> gehen, sehen Sie die normale Response:
|
Aber wenn Sie mit Ihrem Browser auf <a href="http://127.0.0.1:8000" class="external-link" target="_blank">http://127.0.0.1:8000/app</a> gehen, sehen Sie die normale Response:
|
||||||
|
|
||||||
```JSON
|
```JSON
|
||||||
{
|
{
|
||||||
|
|
@ -400,7 +400,7 @@ Wenn Sie eine benutzerdefinierte Liste von Servern (`servers`) übergeben und es
|
||||||
|
|
||||||
Zum Beispiel:
|
Zum Beispiel:
|
||||||
|
|
||||||
{* ../../docs_src/behind_a_proxy/tutorial003_py39.py hl[4:7] *}
|
{* ../../docs_src/behind_a_proxy/tutorial003.py hl[4:7] *}
|
||||||
|
|
||||||
Erzeugt ein OpenAPI-Schema, wie:
|
Erzeugt ein OpenAPI-Schema, wie:
|
||||||
|
|
||||||
|
|
@ -443,19 +443,11 @@ Die Dokumentationsoberfläche interagiert mit dem von Ihnen ausgewählten Server
|
||||||
|
|
||||||
///
|
///
|
||||||
|
|
||||||
/// note | Technische Details
|
|
||||||
|
|
||||||
Die Eigenschaft `servers` in der OpenAPI-Spezifikation ist optional.
|
|
||||||
|
|
||||||
Wenn Sie den Parameter `servers` nicht angeben und `root_path` den Wert `/` hat, wird die Eigenschaft `servers` im generierten OpenAPI-Schema standardmäßig vollständig weggelassen, was dem Äquivalent eines einzelnen Servers mit einem `url`-Wert von `/` entspricht.
|
|
||||||
|
|
||||||
///
|
|
||||||
|
|
||||||
### Den automatischen Server von `root_path` deaktivieren { #disable-automatic-server-from-root-path }
|
### Den automatischen Server von `root_path` deaktivieren { #disable-automatic-server-from-root-path }
|
||||||
|
|
||||||
Wenn Sie nicht möchten, dass **FastAPI** einen automatischen Server inkludiert, welcher `root_path` verwendet, können Sie den Parameter `root_path_in_servers=False` verwenden:
|
Wenn Sie nicht möchten, dass **FastAPI** einen automatischen Server inkludiert, welcher `root_path` verwendet, können Sie den Parameter `root_path_in_servers=False` verwenden:
|
||||||
|
|
||||||
{* ../../docs_src/behind_a_proxy/tutorial004_py39.py hl[9] *}
|
{* ../../docs_src/behind_a_proxy/tutorial004.py hl[9] *}
|
||||||
|
|
||||||
Dann wird er nicht in das OpenAPI-Schema aufgenommen.
|
Dann wird er nicht in das OpenAPI-Schema aufgenommen.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ Das liegt daran, dass FastAPI standardmäßig jedes enthaltene Element überprü
|
||||||
|
|
||||||
Wenn Sie jedoch sicher sind, dass der von Ihnen zurückgegebene Inhalt **mit JSON serialisierbar** ist, können Sie ihn direkt an die Response-Klasse übergeben und die zusätzliche Arbeit vermeiden, die FastAPI hätte, indem es Ihren zurückgegebenen Inhalt durch den `jsonable_encoder` leitet, bevor es ihn an die Response-Klasse übergibt.
|
Wenn Sie jedoch sicher sind, dass der von Ihnen zurückgegebene Inhalt **mit JSON serialisierbar** ist, können Sie ihn direkt an die Response-Klasse übergeben und die zusätzliche Arbeit vermeiden, die FastAPI hätte, indem es Ihren zurückgegebenen Inhalt durch den `jsonable_encoder` leitet, bevor es ihn an die Response-Klasse übergibt.
|
||||||
|
|
||||||
{* ../../docs_src/custom_response/tutorial001b_py39.py hl[2,7] *}
|
{* ../../docs_src/custom_response/tutorial001b.py hl[2,7] *}
|
||||||
|
|
||||||
/// info | Info
|
/// info | Info
|
||||||
|
|
||||||
|
|
@ -55,7 +55,7 @@ Um eine Response mit HTML direkt von **FastAPI** zurückzugeben, verwenden Sie `
|
||||||
* Importieren Sie `HTMLResponse`.
|
* Importieren Sie `HTMLResponse`.
|
||||||
* Übergeben Sie `HTMLResponse` als den Parameter `response_class` Ihres *Pfadoperation-Dekorators*.
|
* Übergeben Sie `HTMLResponse` als den Parameter `response_class` Ihres *Pfadoperation-Dekorators*.
|
||||||
|
|
||||||
{* ../../docs_src/custom_response/tutorial002_py39.py hl[2,7] *}
|
{* ../../docs_src/custom_response/tutorial002.py hl[2,7] *}
|
||||||
|
|
||||||
/// info | Info
|
/// info | Info
|
||||||
|
|
||||||
|
|
@ -73,7 +73,7 @@ Wie in [Eine Response direkt zurückgeben](response-directly.md){.internal-link
|
||||||
|
|
||||||
Das gleiche Beispiel von oben, das eine `HTMLResponse` zurückgibt, könnte so aussehen:
|
Das gleiche Beispiel von oben, das eine `HTMLResponse` zurückgibt, könnte so aussehen:
|
||||||
|
|
||||||
{* ../../docs_src/custom_response/tutorial003_py39.py hl[2,7,19] *}
|
{* ../../docs_src/custom_response/tutorial003.py hl[2,7,19] *}
|
||||||
|
|
||||||
/// warning | Achtung
|
/// warning | Achtung
|
||||||
|
|
||||||
|
|
@ -97,7 +97,7 @@ Die `response_class` wird dann nur zur Dokumentation der OpenAPI-*Pfadoperation*
|
||||||
|
|
||||||
Es könnte zum Beispiel so etwas sein:
|
Es könnte zum Beispiel so etwas sein:
|
||||||
|
|
||||||
{* ../../docs_src/custom_response/tutorial004_py39.py hl[7,21,23] *}
|
{* ../../docs_src/custom_response/tutorial004.py hl[7,21,23] *}
|
||||||
|
|
||||||
In diesem Beispiel generiert die Funktion `generate_html_response()` bereits eine `Response` und gibt sie zurück, anstatt das HTML in einem `str` zurückzugeben.
|
In diesem Beispiel generiert die Funktion `generate_html_response()` bereits eine `Response` und gibt sie zurück, anstatt das HTML in einem `str` zurückzugeben.
|
||||||
|
|
||||||
|
|
@ -136,7 +136,7 @@ Sie akzeptiert die folgenden Parameter:
|
||||||
|
|
||||||
FastAPI (eigentlich Starlette) fügt automatisch einen Content-Length-Header ein. Außerdem wird es einen Content-Type-Header einfügen, der auf dem media_type basiert, und für Texttypen einen Zeichensatz (charset) anfügen.
|
FastAPI (eigentlich Starlette) fügt automatisch einen Content-Length-Header ein. Außerdem wird es einen Content-Type-Header einfügen, der auf dem media_type basiert, und für Texttypen einen Zeichensatz (charset) anfügen.
|
||||||
|
|
||||||
{* ../../docs_src/response_directly/tutorial002_py39.py hl[1,18] *}
|
{* ../../docs_src/response_directly/tutorial002.py hl[1,18] *}
|
||||||
|
|
||||||
### `HTMLResponse` { #htmlresponse }
|
### `HTMLResponse` { #htmlresponse }
|
||||||
|
|
||||||
|
|
@ -146,7 +146,7 @@ Nimmt Text oder Bytes entgegen und gibt eine HTML-Response zurück, wie Sie oben
|
||||||
|
|
||||||
Nimmt Text oder Bytes entgegen und gibt eine Plain-Text-Response zurück.
|
Nimmt Text oder Bytes entgegen und gibt eine Plain-Text-Response zurück.
|
||||||
|
|
||||||
{* ../../docs_src/custom_response/tutorial005_py39.py hl[2,7,9] *}
|
{* ../../docs_src/custom_response/tutorial005.py hl[2,7,9] *}
|
||||||
|
|
||||||
### `JSONResponse` { #jsonresponse }
|
### `JSONResponse` { #jsonresponse }
|
||||||
|
|
||||||
|
|
@ -180,7 +180,7 @@ Dazu muss `ujson` installiert werden, z. B. mit `pip install ujson`.
|
||||||
|
|
||||||
///
|
///
|
||||||
|
|
||||||
{* ../../docs_src/custom_response/tutorial001_py39.py hl[2,7] *}
|
{* ../../docs_src/custom_response/tutorial001.py hl[2,7] *}
|
||||||
|
|
||||||
/// tip | Tipp
|
/// tip | Tipp
|
||||||
|
|
||||||
|
|
@ -194,13 +194,13 @@ Gibt eine HTTP-Weiterleitung (HTTP-Redirect) zurück. Verwendet standardmäßig
|
||||||
|
|
||||||
Sie können eine `RedirectResponse` direkt zurückgeben:
|
Sie können eine `RedirectResponse` direkt zurückgeben:
|
||||||
|
|
||||||
{* ../../docs_src/custom_response/tutorial006_py39.py hl[2,9] *}
|
{* ../../docs_src/custom_response/tutorial006.py hl[2,9] *}
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
Oder Sie können sie im Parameter `response_class` verwenden:
|
Oder Sie können sie im Parameter `response_class` verwenden:
|
||||||
|
|
||||||
{* ../../docs_src/custom_response/tutorial006b_py39.py hl[2,7,9] *}
|
{* ../../docs_src/custom_response/tutorial006b.py hl[2,7,9] *}
|
||||||
|
|
||||||
Wenn Sie das tun, können Sie die URL direkt von Ihrer *Pfadoperation*-Funktion zurückgeben.
|
Wenn Sie das tun, können Sie die URL direkt von Ihrer *Pfadoperation*-Funktion zurückgeben.
|
||||||
|
|
||||||
|
|
@ -210,13 +210,13 @@ In diesem Fall ist der verwendete `status_code` der Standardcode für die `Redir
|
||||||
|
|
||||||
Sie können den Parameter `status_code` auch in Kombination mit dem Parameter `response_class` verwenden:
|
Sie können den Parameter `status_code` auch in Kombination mit dem Parameter `response_class` verwenden:
|
||||||
|
|
||||||
{* ../../docs_src/custom_response/tutorial006c_py39.py hl[2,7,9] *}
|
{* ../../docs_src/custom_response/tutorial006c.py hl[2,7,9] *}
|
||||||
|
|
||||||
### `StreamingResponse` { #streamingresponse }
|
### `StreamingResponse` { #streamingresponse }
|
||||||
|
|
||||||
Nimmt einen asynchronen Generator oder einen normalen Generator/Iterator und streamt den Responsebody.
|
Nimmt einen asynchronen Generator oder einen normalen Generator/Iterator und streamt den Responsebody.
|
||||||
|
|
||||||
{* ../../docs_src/custom_response/tutorial007_py39.py hl[2,14] *}
|
{* ../../docs_src/custom_response/tutorial007.py hl[2,14] *}
|
||||||
|
|
||||||
#### Verwendung von `StreamingResponse` mit dateiartigen Objekten { #using-streamingresponse-with-file-like-objects }
|
#### Verwendung von `StreamingResponse` mit dateiartigen Objekten { #using-streamingresponse-with-file-like-objects }
|
||||||
|
|
||||||
|
|
@ -226,7 +226,7 @@ Auf diese Weise müssen Sie nicht alles zuerst in den Arbeitsspeicher lesen und
|
||||||
|
|
||||||
Das umfasst viele Bibliotheken zur Interaktion mit Cloud-Speicher, Videoverarbeitung und anderen.
|
Das umfasst viele Bibliotheken zur Interaktion mit Cloud-Speicher, Videoverarbeitung und anderen.
|
||||||
|
|
||||||
{* ../../docs_src/custom_response/tutorial008_py39.py hl[2,10:12,14] *}
|
{* ../../docs_src/custom_response/tutorial008.py hl[2,10:12,14] *}
|
||||||
|
|
||||||
1. Das ist die Generatorfunktion. Es handelt sich um eine „Generatorfunktion“, da sie `yield`-Anweisungen enthält.
|
1. Das ist die Generatorfunktion. Es handelt sich um eine „Generatorfunktion“, da sie `yield`-Anweisungen enthält.
|
||||||
2. Durch die Verwendung eines `with`-Blocks stellen wir sicher, dass das dateiartige Objekt geschlossen wird, nachdem die Generatorfunktion fertig ist. Also, nachdem sie mit dem Senden der Response fertig ist.
|
2. Durch die Verwendung eines `with`-Blocks stellen wir sicher, dass das dateiartige Objekt geschlossen wird, nachdem die Generatorfunktion fertig ist. Also, nachdem sie mit dem Senden der Response fertig ist.
|
||||||
|
|
@ -255,11 +255,11 @@ Nimmt zur Instanziierung einen anderen Satz von Argumenten entgegen als die ande
|
||||||
|
|
||||||
Datei-Responses enthalten die entsprechenden `Content-Length`-, `Last-Modified`- und `ETag`-Header.
|
Datei-Responses enthalten die entsprechenden `Content-Length`-, `Last-Modified`- und `ETag`-Header.
|
||||||
|
|
||||||
{* ../../docs_src/custom_response/tutorial009_py39.py hl[2,10] *}
|
{* ../../docs_src/custom_response/tutorial009.py hl[2,10] *}
|
||||||
|
|
||||||
Sie können auch den Parameter `response_class` verwenden:
|
Sie können auch den Parameter `response_class` verwenden:
|
||||||
|
|
||||||
{* ../../docs_src/custom_response/tutorial009b_py39.py hl[2,8,10] *}
|
{* ../../docs_src/custom_response/tutorial009b.py hl[2,8,10] *}
|
||||||
|
|
||||||
In diesem Fall können Sie den Dateipfad direkt von Ihrer *Pfadoperation*-Funktion zurückgeben.
|
In diesem Fall können Sie den Dateipfad direkt von Ihrer *Pfadoperation*-Funktion zurückgeben.
|
||||||
|
|
||||||
|
|
@ -273,7 +273,7 @@ Sie möchten etwa, dass Ihre Response eingerücktes und formatiertes JSON zurüc
|
||||||
|
|
||||||
Sie könnten eine `CustomORJSONResponse` erstellen. Das Wichtigste, was Sie tun müssen, ist, eine `Response.render(content)`-Methode zu erstellen, die den Inhalt als `bytes` zurückgibt:
|
Sie könnten eine `CustomORJSONResponse` erstellen. Das Wichtigste, was Sie tun müssen, ist, eine `Response.render(content)`-Methode zu erstellen, die den Inhalt als `bytes` zurückgibt:
|
||||||
|
|
||||||
{* ../../docs_src/custom_response/tutorial009c_py39.py hl[9:14,17] *}
|
{* ../../docs_src/custom_response/tutorial009c.py hl[9:14,17] *}
|
||||||
|
|
||||||
Statt:
|
Statt:
|
||||||
|
|
||||||
|
|
@ -299,7 +299,7 @@ Der Parameter, der das definiert, ist `default_response_class`.
|
||||||
|
|
||||||
Im folgenden Beispiel verwendet **FastAPI** standardmäßig `ORJSONResponse` in allen *Pfadoperationen*, anstelle von `JSONResponse`.
|
Im folgenden Beispiel verwendet **FastAPI** standardmäßig `ORJSONResponse` in allen *Pfadoperationen*, anstelle von `JSONResponse`.
|
||||||
|
|
||||||
{* ../../docs_src/custom_response/tutorial010_py39.py hl[2,4] *}
|
{* ../../docs_src/custom_response/tutorial010.py hl[2,4] *}
|
||||||
|
|
||||||
/// tip | Tipp
|
/// tip | Tipp
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ FastAPI basiert auf **Pydantic**, und ich habe Ihnen gezeigt, wie Sie Pydantic-M
|
||||||
|
|
||||||
Aber FastAPI unterstützt auf die gleiche Weise auch die Verwendung von <a href="https://docs.python.org/3/library/dataclasses.html" class="external-link" target="_blank">`dataclasses`</a>:
|
Aber FastAPI unterstützt auf die gleiche Weise auch die Verwendung von <a href="https://docs.python.org/3/library/dataclasses.html" class="external-link" target="_blank">`dataclasses`</a>:
|
||||||
|
|
||||||
{* ../../docs_src/dataclasses/tutorial001_py310.py hl[1,6:11,18:19] *}
|
{* ../../docs_src/dataclasses/tutorial001.py hl[1,7:12,19:20] *}
|
||||||
|
|
||||||
Das ist dank **Pydantic** ebenfalls möglich, da es <a href="https://docs.pydantic.dev/latest/concepts/dataclasses/#use-of-stdlib-dataclasses-with-basemodel" class="external-link" target="_blank">`dataclasses` intern unterstützt</a>.
|
Das ist dank **Pydantic** ebenfalls möglich, da es <a href="https://docs.pydantic.dev/latest/concepts/dataclasses/#use-of-stdlib-dataclasses-with-basemodel" class="external-link" target="_blank">`dataclasses` intern unterstützt</a>.
|
||||||
|
|
||||||
|
|
@ -32,7 +32,7 @@ Wenn Sie jedoch eine Menge Datenklassen herumliegen haben, ist dies ein guter Tr
|
||||||
|
|
||||||
Sie können `dataclasses` auch im Parameter `response_model` verwenden:
|
Sie können `dataclasses` auch im Parameter `response_model` verwenden:
|
||||||
|
|
||||||
{* ../../docs_src/dataclasses/tutorial002_py310.py hl[1,6:12,18] *}
|
{* ../../docs_src/dataclasses/tutorial002.py hl[1,7:13,19] *}
|
||||||
|
|
||||||
Die Datenklasse wird automatisch in eine Pydantic-Datenklasse konvertiert.
|
Die Datenklasse wird automatisch in eine Pydantic-Datenklasse konvertiert.
|
||||||
|
|
||||||
|
|
@ -48,7 +48,7 @@ In einigen Fällen müssen Sie möglicherweise immer noch Pydantics Version von
|
||||||
|
|
||||||
In diesem Fall können Sie einfach die Standard-`dataclasses` durch `pydantic.dataclasses` ersetzen, was einen direkten Ersatz darstellt:
|
In diesem Fall können Sie einfach die Standard-`dataclasses` durch `pydantic.dataclasses` ersetzen, was einen direkten Ersatz darstellt:
|
||||||
|
|
||||||
{* ../../docs_src/dataclasses/tutorial003_py310.py hl[1,4,7:10,13:16,22:24,27] *}
|
{* ../../docs_src/dataclasses/tutorial003.py hl[1,5,8:11,14:17,23:25,28] *}
|
||||||
|
|
||||||
1. Wir importieren `field` weiterhin von Standard-`dataclasses`.
|
1. Wir importieren `field` weiterhin von Standard-`dataclasses`.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ Beginnen wir mit einem Beispiel und sehen es uns dann im Detail an.
|
||||||
|
|
||||||
Wir erstellen eine asynchrone Funktion `lifespan()` mit `yield` wie folgt:
|
Wir erstellen eine asynchrone Funktion `lifespan()` mit `yield` wie folgt:
|
||||||
|
|
||||||
{* ../../docs_src/events/tutorial003_py39.py hl[16,19] *}
|
{* ../../docs_src/events/tutorial003.py hl[16,19] *}
|
||||||
|
|
||||||
Hier simulieren wir den langsamen *Startup*, das Laden des Modells, indem wir die (Fake-)Modellfunktion vor dem `yield` in das <abbr title="Dictionary – Zuordnungstabelle: In anderen Sprachen auch Hash, Map, Objekt, Assoziatives Array genannt">Dictionary</abbr> mit Modellen für maschinelles Lernen einfügen. Dieser Code wird ausgeführt, **bevor** die Anwendung **beginnt, Requests entgegenzunehmen**, während des *Startups*.
|
Hier simulieren wir den langsamen *Startup*, das Laden des Modells, indem wir die (Fake-)Modellfunktion vor dem `yield` in das <abbr title="Dictionary – Zuordnungstabelle: In anderen Sprachen auch Hash, Map, Objekt, Assoziatives Array genannt">Dictionary</abbr> mit Modellen für maschinelles Lernen einfügen. Dieser Code wird ausgeführt, **bevor** die Anwendung **beginnt, Requests entgegenzunehmen**, während des *Startups*.
|
||||||
|
|
||||||
|
|
@ -48,7 +48,7 @@ Möglicherweise müssen Sie eine neue Version starten, oder Sie haben es einfach
|
||||||
|
|
||||||
Das Erste, was auffällt, ist, dass wir eine asynchrone Funktion mit `yield` definieren. Das ist sehr ähnlich zu Abhängigkeiten mit `yield`.
|
Das Erste, was auffällt, ist, dass wir eine asynchrone Funktion mit `yield` definieren. Das ist sehr ähnlich zu Abhängigkeiten mit `yield`.
|
||||||
|
|
||||||
{* ../../docs_src/events/tutorial003_py39.py hl[14:19] *}
|
{* ../../docs_src/events/tutorial003.py hl[14:19] *}
|
||||||
|
|
||||||
Der erste Teil der Funktion, vor dem `yield`, wird ausgeführt **bevor** die Anwendung startet.
|
Der erste Teil der Funktion, vor dem `yield`, wird ausgeführt **bevor** die Anwendung startet.
|
||||||
|
|
||||||
|
|
@ -60,7 +60,7 @@ Wie Sie sehen, ist die Funktion mit einem `@asynccontextmanager` versehen.
|
||||||
|
|
||||||
Dadurch wird die Funktion in einen sogenannten „**asynchronen Kontextmanager**“ umgewandelt.
|
Dadurch wird die Funktion in einen sogenannten „**asynchronen Kontextmanager**“ umgewandelt.
|
||||||
|
|
||||||
{* ../../docs_src/events/tutorial003_py39.py hl[1,13] *}
|
{* ../../docs_src/events/tutorial003.py hl[1,13] *}
|
||||||
|
|
||||||
Ein **Kontextmanager** in Python ist etwas, das Sie in einer `with`-Anweisung verwenden können, zum Beispiel kann `open()` als Kontextmanager verwendet werden:
|
Ein **Kontextmanager** in Python ist etwas, das Sie in einer `with`-Anweisung verwenden können, zum Beispiel kann `open()` als Kontextmanager verwendet werden:
|
||||||
|
|
||||||
|
|
@ -82,7 +82,7 @@ In unserem obigen Codebeispiel verwenden wir ihn nicht direkt, sondern übergebe
|
||||||
|
|
||||||
Der Parameter `lifespan` der `FastAPI`-App benötigt einen **asynchronen Kontextmanager**, wir können ihm also unseren neuen asynchronen Kontextmanager `lifespan` übergeben.
|
Der Parameter `lifespan` der `FastAPI`-App benötigt einen **asynchronen Kontextmanager**, wir können ihm also unseren neuen asynchronen Kontextmanager `lifespan` übergeben.
|
||||||
|
|
||||||
{* ../../docs_src/events/tutorial003_py39.py hl[22] *}
|
{* ../../docs_src/events/tutorial003.py hl[22] *}
|
||||||
|
|
||||||
## Alternative Events (<abbr title="veraltet, obsolet: Es soll nicht mehr verwendet werden">deprecatet</abbr>) { #alternative-events-deprecated }
|
## Alternative Events (<abbr title="veraltet, obsolet: Es soll nicht mehr verwendet werden">deprecatet</abbr>) { #alternative-events-deprecated }
|
||||||
|
|
||||||
|
|
@ -104,7 +104,7 @@ Diese Funktionen können mit `async def` oder normalem `def` deklariert werden.
|
||||||
|
|
||||||
Um eine Funktion hinzuzufügen, die vor dem Start der Anwendung ausgeführt werden soll, deklarieren Sie diese mit dem Event `startup`:
|
Um eine Funktion hinzuzufügen, die vor dem Start der Anwendung ausgeführt werden soll, deklarieren Sie diese mit dem Event `startup`:
|
||||||
|
|
||||||
{* ../../docs_src/events/tutorial001_py39.py hl[8] *}
|
{* ../../docs_src/events/tutorial001.py hl[8] *}
|
||||||
|
|
||||||
In diesem Fall initialisiert die Eventhandler-Funktion `startup` die „Datenbank“ der Items (nur ein `dict`) mit einigen Werten.
|
In diesem Fall initialisiert die Eventhandler-Funktion `startup` die „Datenbank“ der Items (nur ein `dict`) mit einigen Werten.
|
||||||
|
|
||||||
|
|
@ -116,7 +116,7 @@ Und Ihre Anwendung empfängt erst dann Requests, wenn alle `startup`-Eventhandle
|
||||||
|
|
||||||
Um eine Funktion hinzuzufügen, die beim Shutdown der Anwendung ausgeführt werden soll, deklarieren Sie sie mit dem Event `shutdown`:
|
Um eine Funktion hinzuzufügen, die beim Shutdown der Anwendung ausgeführt werden soll, deklarieren Sie sie mit dem Event `shutdown`:
|
||||||
|
|
||||||
{* ../../docs_src/events/tutorial002_py39.py hl[6] *}
|
{* ../../docs_src/events/tutorial002.py hl[6] *}
|
||||||
|
|
||||||
Hier schreibt die `shutdown`-Eventhandler-Funktion eine Textzeile `"Application shutdown"` in eine Datei `log.txt`.
|
Hier schreibt die `shutdown`-Eventhandler-Funktion eine Textzeile `"Application shutdown"` in eine Datei `log.txt`.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -167,7 +167,7 @@ Aber für den generierten Client könnten wir die OpenAPI-Operation-IDs direkt v
|
||||||
|
|
||||||
Wir könnten das OpenAPI-JSON in eine Datei `openapi.json` herunterladen und dann mit einem Skript wie dem folgenden **den präfixierten Tag entfernen**:
|
Wir könnten das OpenAPI-JSON in eine Datei `openapi.json` herunterladen und dann mit einem Skript wie dem folgenden **den präfixierten Tag entfernen**:
|
||||||
|
|
||||||
{* ../../docs_src/generate_clients/tutorial004_py39.py *}
|
{* ../../docs_src/generate_clients/tutorial004.py *}
|
||||||
|
|
||||||
//// tab | Node.js
|
//// tab | Node.js
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -57,13 +57,13 @@ Erzwingt, dass alle eingehenden <abbr title="Request – Anfrage: Daten, die der
|
||||||
|
|
||||||
Alle eingehenden Requests an `http` oder `ws` werden stattdessen an das sichere Schema umgeleitet.
|
Alle eingehenden Requests an `http` oder `ws` werden stattdessen an das sichere Schema umgeleitet.
|
||||||
|
|
||||||
{* ../../docs_src/advanced_middleware/tutorial001_py39.py hl[2,6] *}
|
{* ../../docs_src/advanced_middleware/tutorial001.py hl[2,6] *}
|
||||||
|
|
||||||
## `TrustedHostMiddleware` { #trustedhostmiddleware }
|
## `TrustedHostMiddleware` { #trustedhostmiddleware }
|
||||||
|
|
||||||
Erzwingt, dass alle eingehenden Requests einen korrekt gesetzten `Host`-Header haben, um sich vor HTTP-Host-Header-Angriffen zu schützen.
|
Erzwingt, dass alle eingehenden Requests einen korrekt gesetzten `Host`-Header haben, um sich vor HTTP-Host-Header-Angriffen zu schützen.
|
||||||
|
|
||||||
{* ../../docs_src/advanced_middleware/tutorial002_py39.py hl[2,6:8] *}
|
{* ../../docs_src/advanced_middleware/tutorial002.py hl[2,6:8] *}
|
||||||
|
|
||||||
Die folgenden Argumente werden unterstützt:
|
Die folgenden Argumente werden unterstützt:
|
||||||
|
|
||||||
|
|
@ -78,7 +78,7 @@ Verarbeitet GZip-Responses für alle Requests, die `"gzip"` im `Accept-Encoding`
|
||||||
|
|
||||||
Diese Middleware verarbeitet sowohl Standard- als auch Streaming-Responses.
|
Diese Middleware verarbeitet sowohl Standard- als auch Streaming-Responses.
|
||||||
|
|
||||||
{* ../../docs_src/advanced_middleware/tutorial003_py39.py hl[2,6] *}
|
{* ../../docs_src/advanced_middleware/tutorial003.py hl[2,6] *}
|
||||||
|
|
||||||
Die folgenden Argumente werden unterstützt:
|
Die folgenden Argumente werden unterstützt:
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ Sie verfügt über eine *Pfadoperation*, die einen `Invoice`-Body empfängt, und
|
||||||
|
|
||||||
Dieser Teil ist ziemlich normal, der größte Teil des Codes ist Ihnen wahrscheinlich bereits bekannt:
|
Dieser Teil ist ziemlich normal, der größte Teil des Codes ist Ihnen wahrscheinlich bereits bekannt:
|
||||||
|
|
||||||
{* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[7:11,34:51] *}
|
{* ../../docs_src/openapi_callbacks/tutorial001.py hl[9:13,36:53] *}
|
||||||
|
|
||||||
/// tip | Tipp
|
/// tip | Tipp
|
||||||
|
|
||||||
|
|
@ -90,7 +90,7 @@ Wenn Sie diese Sichtweise (des *externen Entwicklers*) vorübergehend übernehme
|
||||||
|
|
||||||
Erstellen Sie zunächst einen neuen `APIRouter`, der einen oder mehrere Callbacks enthält.
|
Erstellen Sie zunächst einen neuen `APIRouter`, der einen oder mehrere Callbacks enthält.
|
||||||
|
|
||||||
{* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[1,23] *}
|
{* ../../docs_src/openapi_callbacks/tutorial001.py hl[3,25] *}
|
||||||
|
|
||||||
### Die Callback-*Pfadoperation* erstellen { #create-the-callback-path-operation }
|
### Die Callback-*Pfadoperation* erstellen { #create-the-callback-path-operation }
|
||||||
|
|
||||||
|
|
@ -101,7 +101,7 @@ Sie sollte wie eine normale FastAPI-*Pfadoperation* aussehen:
|
||||||
* Sie sollte wahrscheinlich eine Deklaration des Bodys enthalten, die sie erhalten soll, z. B. `body: InvoiceEvent`.
|
* Sie sollte wahrscheinlich eine Deklaration des Bodys enthalten, die sie erhalten soll, z. B. `body: InvoiceEvent`.
|
||||||
* Und sie könnte auch eine Deklaration der Response enthalten, die zurückgegeben werden soll, z. B. `response_model=InvoiceEventReceived`.
|
* Und sie könnte auch eine Deklaration der Response enthalten, die zurückgegeben werden soll, z. B. `response_model=InvoiceEventReceived`.
|
||||||
|
|
||||||
{* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[14:16,19:20,26:30] *}
|
{* ../../docs_src/openapi_callbacks/tutorial001.py hl[16:18,21:22,28:32] *}
|
||||||
|
|
||||||
Es gibt zwei Hauptunterschiede zu einer normalen *Pfadoperation*:
|
Es gibt zwei Hauptunterschiede zu einer normalen *Pfadoperation*:
|
||||||
|
|
||||||
|
|
@ -169,7 +169,7 @@ An diesem Punkt haben Sie die benötigte(n) *Callback-Pfadoperation(en)* (diejen
|
||||||
|
|
||||||
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` (das ist eigentlich nur eine `list`e von Routen/*Pfadoperationen*) dieses Callback-Routers zu übergeben:
|
||||||
|
|
||||||
{* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[33] *}
|
{* ../../docs_src/openapi_callbacks/tutorial001.py hl[35] *}
|
||||||
|
|
||||||
/// tip | Tipp
|
/// tip | Tipp
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ Webhooks sind in OpenAPI 3.1.0 und höher verfügbar und werden von FastAPI `0.9
|
||||||
|
|
||||||
Wenn Sie eine **FastAPI**-Anwendung erstellen, gibt es ein `webhooks`-Attribut, das Sie verwenden können, um *Webhooks* zu definieren, genauso wie Sie *Pfadoperationen* definieren würden, zum Beispiel mit `@app.webhooks.post()`.
|
Wenn Sie eine **FastAPI**-Anwendung erstellen, gibt es ein `webhooks`-Attribut, das Sie verwenden können, um *Webhooks* zu definieren, genauso wie Sie *Pfadoperationen* definieren würden, zum Beispiel mit `@app.webhooks.post()`.
|
||||||
|
|
||||||
{* ../../docs_src/openapi_webhooks/tutorial001_py39.py hl[9:13,36:53] *}
|
{* ../../docs_src/openapi_webhooks/tutorial001.py hl[9:13,36:53] *}
|
||||||
|
|
||||||
Die von Ihnen definierten Webhooks landen im **OpenAPI**-Schema und der automatischen **Dokumentations-Oberfläche**.
|
Die von Ihnen definierten Webhooks landen im **OpenAPI**-Schema und der automatischen **Dokumentations-Oberfläche**.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ Mit dem Parameter `operation_id` können Sie die OpenAPI `operationId` festlegen
|
||||||
|
|
||||||
Sie müssten sicherstellen, dass sie für jede Operation eindeutig ist.
|
Sie müssten sicherstellen, dass sie für jede Operation eindeutig ist.
|
||||||
|
|
||||||
{* ../../docs_src/path_operation_advanced_configuration/tutorial001_py39.py hl[6] *}
|
{* ../../docs_src/path_operation_advanced_configuration/tutorial001.py hl[6] *}
|
||||||
|
|
||||||
### Verwendung des Namens der *Pfadoperation-Funktion* als operationId { #using-the-path-operation-function-name-as-the-operationid }
|
### Verwendung des Namens der *Pfadoperation-Funktion* als operationId { #using-the-path-operation-function-name-as-the-operationid }
|
||||||
|
|
||||||
|
|
@ -20,7 +20,7 @@ Wenn Sie die Funktionsnamen Ihrer API als `operationId`s verwenden möchten, kö
|
||||||
|
|
||||||
Sie sollten dies tun, nachdem Sie alle Ihre *Pfadoperationen* hinzugefügt haben.
|
Sie sollten dies tun, nachdem Sie alle Ihre *Pfadoperationen* hinzugefügt haben.
|
||||||
|
|
||||||
{* ../../docs_src/path_operation_advanced_configuration/tutorial002_py39.py hl[2, 12:21, 24] *}
|
{* ../../docs_src/path_operation_advanced_configuration/tutorial002.py hl[2, 12:21, 24] *}
|
||||||
|
|
||||||
/// tip | Tipp
|
/// tip | Tipp
|
||||||
|
|
||||||
|
|
@ -40,7 +40,7 @@ Auch wenn diese sich in unterschiedlichen Modulen (Python-Dateien) befinden.
|
||||||
|
|
||||||
Um eine *Pfadoperation* aus dem generierten OpenAPI-Schema (und damit aus den automatischen Dokumentationssystemen) auszuschließen, verwenden Sie den Parameter `include_in_schema` und setzen Sie ihn auf `False`:
|
Um eine *Pfadoperation* aus dem generierten OpenAPI-Schema (und damit aus den automatischen Dokumentationssystemen) auszuschließen, verwenden Sie den Parameter `include_in_schema` und setzen Sie ihn auf `False`:
|
||||||
|
|
||||||
{* ../../docs_src/path_operation_advanced_configuration/tutorial003_py39.py hl[6] *}
|
{* ../../docs_src/path_operation_advanced_configuration/tutorial003.py hl[6] *}
|
||||||
|
|
||||||
## Fortgeschrittene Beschreibung mittels Docstring { #advanced-description-from-docstring }
|
## Fortgeschrittene Beschreibung mittels Docstring { #advanced-description-from-docstring }
|
||||||
|
|
||||||
|
|
@ -50,7 +50,7 @@ Das Hinzufügen eines `\f` (ein maskiertes „Form Feed“-Zeichen) führt dazu,
|
||||||
|
|
||||||
Sie wird nicht in der Dokumentation angezeigt, aber andere Tools (z. B. Sphinx) können den Rest verwenden.
|
Sie wird nicht in der Dokumentation angezeigt, aber andere Tools (z. B. Sphinx) können den Rest verwenden.
|
||||||
|
|
||||||
{* ../../docs_src/path_operation_advanced_configuration/tutorial004_py310.py hl[17:27] *}
|
{* ../../docs_src/path_operation_advanced_configuration/tutorial004.py hl[19:29] *}
|
||||||
|
|
||||||
## Zusätzliche Responses { #additional-responses }
|
## Zusätzliche Responses { #additional-responses }
|
||||||
|
|
||||||
|
|
@ -92,7 +92,7 @@ Sie können das OpenAPI-Schema für eine *Pfadoperation* erweitern, indem Sie de
|
||||||
|
|
||||||
Dieses `openapi_extra` kann beispielsweise hilfreich sein, um [OpenAPI-Erweiterungen](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#specificationExtensions) zu deklarieren:
|
Dieses `openapi_extra` kann beispielsweise hilfreich sein, um [OpenAPI-Erweiterungen](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#specificationExtensions) zu deklarieren:
|
||||||
|
|
||||||
{* ../../docs_src/path_operation_advanced_configuration/tutorial005_py39.py hl[6] *}
|
{* ../../docs_src/path_operation_advanced_configuration/tutorial005.py hl[6] *}
|
||||||
|
|
||||||
Wenn Sie die automatische API-Dokumentation öffnen, wird Ihre Erweiterung am Ende der spezifischen *Pfadoperation* angezeigt.
|
Wenn Sie die automatische API-Dokumentation öffnen, wird Ihre Erweiterung am Ende der spezifischen *Pfadoperation* angezeigt.
|
||||||
|
|
||||||
|
|
@ -139,7 +139,7 @@ Sie könnten sich beispielsweise dafür entscheiden, den <abbr title="Request
|
||||||
|
|
||||||
Das könnte man mit `openapi_extra` machen:
|
Das könnte man mit `openapi_extra` machen:
|
||||||
|
|
||||||
{* ../../docs_src/path_operation_advanced_configuration/tutorial006_py39.py hl[19:36, 39:40] *}
|
{* ../../docs_src/path_operation_advanced_configuration/tutorial006.py hl[19:36, 39:40] *}
|
||||||
|
|
||||||
In diesem Beispiel haben wir kein Pydantic-Modell deklariert. Tatsächlich wird der Requestbody nicht einmal als JSON <abbr title="von einem einfachen Format, wie Bytes, in Python-Objekte konvertieren">geparst</abbr>, sondern direkt als `bytes` gelesen und die Funktion `magic_data_reader()` wäre dafür verantwortlich, ihn in irgendeiner Weise zu parsen.
|
In diesem Beispiel haben wir kein Pydantic-Modell deklariert. Tatsächlich wird der Requestbody nicht einmal als JSON <abbr title="von einem einfachen Format, wie Bytes, in Python-Objekte konvertieren">geparst</abbr>, sondern direkt als `bytes` gelesen und die Funktion `magic_data_reader()` wäre dafür verantwortlich, ihn in irgendeiner Weise zu parsen.
|
||||||
|
|
||||||
|
|
@ -155,13 +155,13 @@ In der folgenden Anwendung verwenden wir beispielsweise weder die integrierte Fu
|
||||||
|
|
||||||
//// tab | Pydantic v2
|
//// tab | Pydantic v2
|
||||||
|
|
||||||
{* ../../docs_src/path_operation_advanced_configuration/tutorial007_py39.py hl[15:20, 22] *}
|
{* ../../docs_src/path_operation_advanced_configuration/tutorial007.py hl[17:22, 24] *}
|
||||||
|
|
||||||
////
|
////
|
||||||
|
|
||||||
//// tab | Pydantic v1
|
//// tab | Pydantic v1
|
||||||
|
|
||||||
{* ../../docs_src/path_operation_advanced_configuration/tutorial007_pv1_py39.py hl[15:20, 22] *}
|
{* ../../docs_src/path_operation_advanced_configuration/tutorial007_pv1.py hl[17:22, 24] *}
|
||||||
|
|
||||||
////
|
////
|
||||||
|
|
||||||
|
|
@ -179,13 +179,13 @@ Und dann parsen wir in unserem Code diesen YAML-Inhalt direkt und verwenden dann
|
||||||
|
|
||||||
//// tab | Pydantic v2
|
//// tab | Pydantic v2
|
||||||
|
|
||||||
{* ../../docs_src/path_operation_advanced_configuration/tutorial007_py39.py hl[24:31] *}
|
{* ../../docs_src/path_operation_advanced_configuration/tutorial007.py hl[26:33] *}
|
||||||
|
|
||||||
////
|
////
|
||||||
|
|
||||||
//// tab | Pydantic v1
|
//// tab | Pydantic v1
|
||||||
|
|
||||||
{* ../../docs_src/path_operation_advanced_configuration/tutorial007_pv1_py39.py hl[24:31] *}
|
{* ../../docs_src/path_operation_advanced_configuration/tutorial007_pv1.py hl[26:33] *}
|
||||||
|
|
||||||
////
|
////
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ Sie können einen Parameter vom Typ `Response` in Ihrer *Pfadoperation-Funktion*
|
||||||
|
|
||||||
Anschließend können Sie den `status_code` in diesem *vorübergehenden* <abbr title="Response – Antwort: Daten, die der Server zum anfragenden Client zurücksendet">Response</abbr>-Objekt festlegen.
|
Anschließend können Sie den `status_code` in diesem *vorübergehenden* <abbr title="Response – Antwort: Daten, die der Server zum anfragenden Client zurücksendet">Response</abbr>-Objekt festlegen.
|
||||||
|
|
||||||
{* ../../docs_src/response_change_status_code/tutorial001_py39.py hl[1,9,12] *}
|
{* ../../docs_src/response_change_status_code/tutorial001.py hl[1,9,12] *}
|
||||||
|
|
||||||
Und dann können Sie jedes benötigte Objekt zurückgeben, wie Sie es normalerweise tun würden (ein `dict`, ein Datenbankmodell usw.).
|
Und dann können Sie jedes benötigte Objekt zurückgeben, wie Sie es normalerweise tun würden (ein `dict`, ein Datenbankmodell usw.).
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ Sie können einen Parameter vom Typ `Response` in Ihrer *Pfadoperation-Funktion*
|
||||||
|
|
||||||
Und dann können Sie Cookies in diesem *vorübergehenden* <abbr title="Response – Antwort: Daten, die der Server zum anfragenden Client zurücksendet">Response</abbr>-Objekt setzen.
|
Und dann können Sie Cookies in diesem *vorübergehenden* <abbr title="Response – Antwort: Daten, die der Server zum anfragenden Client zurücksendet">Response</abbr>-Objekt setzen.
|
||||||
|
|
||||||
{* ../../docs_src/response_cookies/tutorial002_py39.py hl[1, 8:9] *}
|
{* ../../docs_src/response_cookies/tutorial002.py hl[1, 8:9] *}
|
||||||
|
|
||||||
Anschließend können Sie wie gewohnt jedes gewünschte Objekt zurückgeben (ein `dict`, ein Datenbankmodell, usw.).
|
Anschließend können Sie wie gewohnt jedes gewünschte Objekt zurückgeben (ein `dict`, ein Datenbankmodell, usw.).
|
||||||
|
|
||||||
|
|
@ -24,7 +24,7 @@ Dazu können Sie eine Response erstellen, wie unter [Eine Response direkt zurüc
|
||||||
|
|
||||||
Setzen Sie dann Cookies darin und geben Sie sie dann zurück:
|
Setzen Sie dann Cookies darin und geben Sie sie dann zurück:
|
||||||
|
|
||||||
{* ../../docs_src/response_cookies/tutorial001_py39.py hl[10:12] *}
|
{* ../../docs_src/response_cookies/tutorial001.py hl[10:12] *}
|
||||||
|
|
||||||
/// tip | Tipp
|
/// tip | Tipp
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ Sie können beispielsweise kein Pydantic-Modell in eine `JSONResponse` einfügen
|
||||||
|
|
||||||
In diesen Fällen können Sie den `jsonable_encoder` verwenden, um Ihre Daten zu konvertieren, bevor Sie sie an eine Response übergeben:
|
In diesen Fällen können Sie den `jsonable_encoder` verwenden, um Ihre Daten zu konvertieren, bevor Sie sie an eine Response übergeben:
|
||||||
|
|
||||||
{* ../../docs_src/response_directly/tutorial001_py310.py hl[5:6,20:21] *}
|
{* ../../docs_src/response_directly/tutorial001.py hl[6:7,21:22] *}
|
||||||
|
|
||||||
/// note | Technische Details
|
/// note | Technische Details
|
||||||
|
|
||||||
|
|
@ -54,7 +54,7 @@ Nehmen wir an, Sie möchten eine <a href="https://en.wikipedia.org/wiki/XML" cla
|
||||||
|
|
||||||
Sie könnten Ihren XML-Inhalt als String in eine `Response` einfügen und sie zurückgeben:
|
Sie könnten Ihren XML-Inhalt als String in eine `Response` einfügen und sie zurückgeben:
|
||||||
|
|
||||||
{* ../../docs_src/response_directly/tutorial002_py39.py hl[1,18] *}
|
{* ../../docs_src/response_directly/tutorial002.py hl[1,18] *}
|
||||||
|
|
||||||
## Anmerkungen { #notes }
|
## Anmerkungen { #notes }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ Sie können einen Parameter vom Typ `Response` in Ihrer *Pfadoperation-Funktion*
|
||||||
|
|
||||||
Und dann können Sie Header in diesem *vorübergehenden* <abbr title="Response – Antwort: Daten, die der Server zum anfragenden Client zurücksendet">Response</abbr>-Objekt festlegen.
|
Und dann können Sie Header in diesem *vorübergehenden* <abbr title="Response – Antwort: Daten, die der Server zum anfragenden Client zurücksendet">Response</abbr>-Objekt festlegen.
|
||||||
|
|
||||||
{* ../../docs_src/response_headers/tutorial002_py39.py hl[1, 7:8] *}
|
{* ../../docs_src/response_headers/tutorial002.py hl[1, 7:8] *}
|
||||||
|
|
||||||
Anschließend können Sie wie gewohnt jedes gewünschte Objekt zurückgeben (ein `dict`, ein Datenbankmodell, usw.).
|
Anschließend können Sie wie gewohnt jedes gewünschte Objekt zurückgeben (ein `dict`, ein Datenbankmodell, usw.).
|
||||||
|
|
||||||
|
|
@ -22,7 +22,7 @@ Sie können auch Header hinzufügen, wenn Sie eine `Response` direkt zurückgebe
|
||||||
|
|
||||||
Erstellen Sie eine Response wie in [Eine Response direkt zurückgeben](response-directly.md){.internal-link target=_blank} beschrieben und übergeben Sie die Header als zusätzlichen Parameter:
|
Erstellen Sie eine Response wie in [Eine Response direkt zurückgeben](response-directly.md){.internal-link target=_blank} beschrieben und übergeben Sie die Header als zusätzlichen Parameter:
|
||||||
|
|
||||||
{* ../../docs_src/response_headers/tutorial001_py39.py hl[10:12] *}
|
{* ../../docs_src/response_headers/tutorial001.py hl[10:12] *}
|
||||||
|
|
||||||
/// note | Technische Details
|
/// note | Technische Details
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -62,7 +62,7 @@ Sie können dieselben Validierungs-Funktionen und -Tools verwenden, die Sie für
|
||||||
|
|
||||||
//// tab | Pydantic v2
|
//// tab | Pydantic v2
|
||||||
|
|
||||||
{* ../../docs_src/settings/tutorial001_py39.py hl[2,5:8,11] *}
|
{* ../../docs_src/settings/tutorial001.py hl[2,5:8,11] *}
|
||||||
|
|
||||||
////
|
////
|
||||||
|
|
||||||
|
|
@ -74,7 +74,7 @@ In Pydantic v1 würden Sie `BaseSettings` direkt von `pydantic` statt von `pydan
|
||||||
|
|
||||||
///
|
///
|
||||||
|
|
||||||
{* ../../docs_src/settings/tutorial001_pv1_py39.py hl[2,5:8,11] *}
|
{* ../../docs_src/settings/tutorial001_pv1.py hl[2,5:8,11] *}
|
||||||
|
|
||||||
////
|
////
|
||||||
|
|
||||||
|
|
@ -92,7 +92,7 @@ Als Nächstes werden die Daten konvertiert und validiert. Wenn Sie also dieses `
|
||||||
|
|
||||||
Dann können Sie das neue `settings`-Objekt in Ihrer Anwendung verwenden:
|
Dann können Sie das neue `settings`-Objekt in Ihrer Anwendung verwenden:
|
||||||
|
|
||||||
{* ../../docs_src/settings/tutorial001_py39.py hl[18:20] *}
|
{* ../../docs_src/settings/tutorial001.py hl[18:20] *}
|
||||||
|
|
||||||
### Den Server ausführen { #run-the-server }
|
### Den Server ausführen { #run-the-server }
|
||||||
|
|
||||||
|
|
@ -126,11 +126,11 @@ Sie könnten diese Einstellungen in eine andere Moduldatei einfügen, wie Sie in
|
||||||
|
|
||||||
Sie könnten beispielsweise eine Datei `config.py` haben mit:
|
Sie könnten beispielsweise eine Datei `config.py` haben mit:
|
||||||
|
|
||||||
{* ../../docs_src/settings/app01_py39/config.py *}
|
{* ../../docs_src/settings/app01/config.py *}
|
||||||
|
|
||||||
Und dann verwenden Sie diese in einer Datei `main.py`:
|
Und dann verwenden Sie diese in einer Datei `main.py`:
|
||||||
|
|
||||||
{* ../../docs_src/settings/app01_py39/main.py hl[3,11:13] *}
|
{* ../../docs_src/settings/app01/main.py hl[3,11:13] *}
|
||||||
|
|
||||||
/// tip | Tipp
|
/// tip | Tipp
|
||||||
|
|
||||||
|
|
@ -148,7 +148,7 @@ Dies könnte besonders beim Testen nützlich sein, da es sehr einfach ist, eine
|
||||||
|
|
||||||
Ausgehend vom vorherigen Beispiel könnte Ihre Datei `config.py` so aussehen:
|
Ausgehend vom vorherigen Beispiel könnte Ihre Datei `config.py` so aussehen:
|
||||||
|
|
||||||
{* ../../docs_src/settings/app02_an_py39/config.py hl[10] *}
|
{* ../../docs_src/settings/app02/config.py hl[10] *}
|
||||||
|
|
||||||
Beachten Sie, dass wir jetzt keine Standardinstanz `settings = Settings()` erstellen.
|
Beachten Sie, dass wir jetzt keine Standardinstanz `settings = Settings()` erstellen.
|
||||||
|
|
||||||
|
|
@ -174,7 +174,7 @@ Und dann können wir das von der *Pfadoperation-Funktion* als Abhängigkeit einf
|
||||||
|
|
||||||
Dann wäre es sehr einfach, beim Testen ein anderes Einstellungsobjekt bereitzustellen, indem man eine Abhängigkeitsüberschreibung für `get_settings` erstellt:
|
Dann wäre es sehr einfach, beim Testen ein anderes Einstellungsobjekt bereitzustellen, indem man eine Abhängigkeitsüberschreibung für `get_settings` erstellt:
|
||||||
|
|
||||||
{* ../../docs_src/settings/app02_an_py39/test_main.py hl[9:10,13,21] *}
|
{* ../../docs_src/settings/app02/test_main.py hl[9:10,13,21] *}
|
||||||
|
|
||||||
Bei der Abhängigkeitsüberschreibung legen wir einen neuen Wert für `admin_email` fest, wenn wir das neue `Settings`-Objekt erstellen, und geben dann dieses neue Objekt zurück.
|
Bei der Abhängigkeitsüberschreibung legen wir einen neuen Wert für `admin_email` fest, wenn wir das neue `Settings`-Objekt erstellen, und geben dann dieses neue Objekt zurück.
|
||||||
|
|
||||||
|
|
@ -217,7 +217,7 @@ Und dann aktualisieren Sie Ihre `config.py` mit:
|
||||||
|
|
||||||
//// tab | Pydantic v2
|
//// tab | Pydantic v2
|
||||||
|
|
||||||
{* ../../docs_src/settings/app03_an_py39/config.py hl[9] *}
|
{* ../../docs_src/settings/app03_an/config.py hl[9] *}
|
||||||
|
|
||||||
/// tip | Tipp
|
/// tip | Tipp
|
||||||
|
|
||||||
|
|
@ -229,7 +229,7 @@ Das Attribut `model_config` wird nur für die Pydantic-Konfiguration verwendet.
|
||||||
|
|
||||||
//// tab | Pydantic v1
|
//// tab | Pydantic v1
|
||||||
|
|
||||||
{* ../../docs_src/settings/app03_an_py39/config_pv1.py hl[9:10] *}
|
{* ../../docs_src/settings/app03_an/config_pv1.py hl[9:10] *}
|
||||||
|
|
||||||
/// tip | Tipp
|
/// tip | Tipp
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ Wenn Sie zwei unabhängige FastAPI-Anwendungen mit deren eigenen unabhängigen O
|
||||||
|
|
||||||
Erstellen Sie zunächst die Hauptanwendung **FastAPI** und deren *Pfadoperationen*:
|
Erstellen Sie zunächst die Hauptanwendung **FastAPI** und deren *Pfadoperationen*:
|
||||||
|
|
||||||
{* ../../docs_src/sub_applications/tutorial001_py39.py hl[3, 6:8] *}
|
{* ../../docs_src/sub_applications/tutorial001.py hl[3, 6:8] *}
|
||||||
|
|
||||||
### Unteranwendung { #sub-application }
|
### Unteranwendung { #sub-application }
|
||||||
|
|
||||||
|
|
@ -18,7 +18,7 @@ Erstellen Sie dann Ihre Unteranwendung und deren *Pfadoperationen*.
|
||||||
|
|
||||||
Diese Unteranwendung ist nur eine weitere Standard-FastAPI-Anwendung, aber diese wird „gemountet“:
|
Diese Unteranwendung ist nur eine weitere Standard-FastAPI-Anwendung, aber diese wird „gemountet“:
|
||||||
|
|
||||||
{* ../../docs_src/sub_applications/tutorial001_py39.py hl[11, 14:16] *}
|
{* ../../docs_src/sub_applications/tutorial001.py hl[11, 14:16] *}
|
||||||
|
|
||||||
### Die Unteranwendung mounten { #mount-the-sub-application }
|
### Die Unteranwendung mounten { #mount-the-sub-application }
|
||||||
|
|
||||||
|
|
@ -26,7 +26,7 @@ Mounten Sie in Ihrer Top-Level-Anwendung `app` die Unteranwendung `subapi`.
|
||||||
|
|
||||||
In diesem Fall wird sie im Pfad `/subapi` gemountet:
|
In diesem Fall wird sie im Pfad `/subapi` gemountet:
|
||||||
|
|
||||||
{* ../../docs_src/sub_applications/tutorial001_py39.py hl[11, 19] *}
|
{* ../../docs_src/sub_applications/tutorial001.py hl[11, 19] *}
|
||||||
|
|
||||||
### Die automatische API-Dokumentation testen { #check-the-automatic-api-docs }
|
### Die automatische API-Dokumentation testen { #check-the-automatic-api-docs }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ $ pip install jinja2
|
||||||
* Deklarieren Sie einen `<abbr title="Request – Anfrage: Daten, die der Client zum Server sendet">Request</abbr>`-Parameter in der *Pfadoperation*, welcher ein Template zurückgibt.
|
* Deklarieren Sie einen `<abbr title="Request – Anfrage: Daten, die der Client zum Server sendet">Request</abbr>`-Parameter in der *Pfadoperation*, welcher ein Template zurückgibt.
|
||||||
* Verwenden Sie die von Ihnen erstellten `templates`, um eine `TemplateResponse` zu rendern und zurückzugeben, übergeben Sie den Namen des Templates, das Requestobjekt und ein „Kontext“-<abbr title="Dictionary – Zuordnungstabelle: In anderen Sprachen auch Hash, Map, Objekt, Assoziatives Array genannt">Dictionary</abbr> mit Schlüssel-Wert-Paaren, die innerhalb des Jinja2-Templates verwendet werden sollen.
|
* Verwenden Sie die von Ihnen erstellten `templates`, um eine `TemplateResponse` zu rendern und zurückzugeben, übergeben Sie den Namen des Templates, das Requestobjekt und ein „Kontext“-<abbr title="Dictionary – Zuordnungstabelle: In anderen Sprachen auch Hash, Map, Objekt, Assoziatives Array genannt">Dictionary</abbr> mit Schlüssel-Wert-Paaren, die innerhalb des Jinja2-Templates verwendet werden sollen.
|
||||||
|
|
||||||
{* ../../docs_src/templates/tutorial001_py39.py hl[4,11,15:18] *}
|
{* ../../docs_src/templates/tutorial001.py hl[4,11,15:18] *}
|
||||||
|
|
||||||
/// note | Hinweis
|
/// note | Hinweis
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,11 @@
|
||||||
|
|
||||||
Wenn Sie `lifespan` in Ihren Tests ausführen müssen, können Sie den `TestClient` mit einer `with`-Anweisung verwenden:
|
Wenn Sie `lifespan` in Ihren Tests ausführen müssen, können Sie den `TestClient` mit einer `with`-Anweisung verwenden:
|
||||||
|
|
||||||
{* ../../docs_src/app_testing/tutorial004_py39.py hl[9:15,18,27:28,30:32,41:43] *}
|
{* ../../docs_src/app_testing/tutorial004.py hl[9:15,18,27:28,30:32,41:43] *}
|
||||||
|
|
||||||
|
|
||||||
Sie können mehr Details unter [„Lifespan in Tests ausführen in der offiziellen Starlette-Dokumentation.“](https://www.starlette.dev/lifespan/#running-lifespan-in-tests) nachlesen.
|
Sie können mehr Details unter [„Lifespan in Tests ausführen in der offiziellen Starlette-Dokumentation.“](https://www.starlette.dev/lifespan/#running-lifespan-in-tests) nachlesen.
|
||||||
|
|
||||||
Für die deprecateten Events <abbr title="Hochfahren">`startup`</abbr> und <abbr title="Herunterfahren">`shutdown`</abbr> können Sie den `TestClient` wie folgt verwenden:
|
Für die deprecateten Events <abbr title="Hochfahren">`startup`</abbr> und <abbr title="Herunterfahren">`shutdown`</abbr> können Sie den `TestClient` wie folgt verwenden:
|
||||||
|
|
||||||
{* ../../docs_src/app_testing/tutorial003_py39.py hl[9:12,20:24] *}
|
{* ../../docs_src/app_testing/tutorial003.py hl[9:12,20:24] *}
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ Sie können den schon bekannten `TestClient` zum Testen von WebSockets verwenden
|
||||||
|
|
||||||
Dazu verwenden Sie den `TestClient` in einer `with`-Anweisung, eine Verbindung zum WebSocket herstellend:
|
Dazu verwenden Sie den `TestClient` in einer `with`-Anweisung, eine Verbindung zum WebSocket herstellend:
|
||||||
|
|
||||||
{* ../../docs_src/app_testing/tutorial002_py39.py hl[27:31] *}
|
{* ../../docs_src/app_testing/tutorial002.py hl[27:31] *}
|
||||||
|
|
||||||
/// note | Hinweis
|
/// note | Hinweis
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ Angenommen, Sie möchten auf die IP-Adresse/den Host des Clients in Ihrer *Pfado
|
||||||
|
|
||||||
Dazu müssen Sie direkt auf den Request zugreifen.
|
Dazu müssen Sie direkt auf den Request zugreifen.
|
||||||
|
|
||||||
{* ../../docs_src/using_request_directly/tutorial001_py39.py hl[1,7:8] *}
|
{* ../../docs_src/using_request_directly/tutorial001.py hl[1,7:8] *}
|
||||||
|
|
||||||
Durch die Deklaration eines *Pfadoperation-Funktionsparameters*, dessen Typ der `Request` ist, weiß **FastAPI**, dass es den `Request` diesem Parameter übergeben soll.
|
Durch die Deklaration eines *Pfadoperation-Funktionsparameters*, dessen Typ der `Request` ist, weiß **FastAPI**, dass es den `Request` diesem Parameter übergeben soll.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -38,13 +38,13 @@ In der Produktion hätten Sie eine der oben genannten Optionen.
|
||||||
|
|
||||||
Aber es ist der einfachste Weg, sich auf die Serverseite von WebSockets zu konzentrieren und ein funktionierendes Beispiel zu haben:
|
Aber es ist der einfachste Weg, sich auf die Serverseite von WebSockets zu konzentrieren und ein funktionierendes Beispiel zu haben:
|
||||||
|
|
||||||
{* ../../docs_src/websockets/tutorial001_py39.py hl[2,6:38,41:43] *}
|
{* ../../docs_src/websockets/tutorial001.py hl[2,6:38,41:43] *}
|
||||||
|
|
||||||
## Einen `websocket` erstellen { #create-a-websocket }
|
## Einen `websocket` erstellen { #create-a-websocket }
|
||||||
|
|
||||||
Erstellen Sie in Ihrer **FastAPI**-Anwendung einen `websocket`:
|
Erstellen Sie in Ihrer **FastAPI**-Anwendung einen `websocket`:
|
||||||
|
|
||||||
{* ../../docs_src/websockets/tutorial001_py39.py hl[1,46:47] *}
|
{* ../../docs_src/websockets/tutorial001.py hl[1,46:47] *}
|
||||||
|
|
||||||
/// note | Technische Details
|
/// note | Technische Details
|
||||||
|
|
||||||
|
|
@ -58,7 +58,7 @@ Sie könnten auch `from starlette.websockets import WebSocket` verwenden.
|
||||||
|
|
||||||
In Ihrer WebSocket-Route können Sie Nachrichten `await`en und Nachrichten senden.
|
In Ihrer WebSocket-Route können Sie Nachrichten `await`en und Nachrichten senden.
|
||||||
|
|
||||||
{* ../../docs_src/websockets/tutorial001_py39.py hl[48:52] *}
|
{* ../../docs_src/websockets/tutorial001.py hl[48:52] *}
|
||||||
|
|
||||||
Sie können Binär-, Text- und JSON-Daten empfangen und senden.
|
Sie können Binär-, Text- und JSON-Daten empfangen und senden.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ Wrappen Sie dann die WSGI-Anwendung (z. B. Flask) mit der Middleware.
|
||||||
|
|
||||||
Und dann mounten Sie das auf einem Pfad.
|
Und dann mounten Sie das auf einem Pfad.
|
||||||
|
|
||||||
{* ../../docs_src/wsgi/tutorial001_py39.py hl[2:3,3] *}
|
{* ../../docs_src/wsgi/tutorial001.py hl[2:3,3] *}
|
||||||
|
|
||||||
## Es testen { #check-it }
|
## Es testen { #check-it }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,24 +1,16 @@
|
||||||
# FastAPI bei Cloudanbietern deployen { #deploy-fastapi-on-cloud-providers }
|
# FastAPI bei Cloudanbietern bereitstellen { #deploy-fastapi-on-cloud-providers }
|
||||||
|
|
||||||
Sie können praktisch **jeden Cloudanbieter** verwenden, um Ihre FastAPI-Anwendung bereitzustellen.
|
Sie können praktisch **jeden Cloudanbieter** verwenden, um Ihre FastAPI-Anwendung bereitzustellen.
|
||||||
|
|
||||||
In den meisten Fällen bieten die großen Cloudanbieter Anleitungen zum Deployment von FastAPI an.
|
In den meisten Fällen bieten die großen Cloudanbieter Anleitungen zum Bereitstellen von FastAPI an.
|
||||||
|
|
||||||
## FastAPI Cloud { #fastapi-cloud }
|
|
||||||
|
|
||||||
**<a href="https://fastapicloud.com" class="external-link" target="_blank">FastAPI Cloud</a>** wurde vom selben Autor und Team hinter **FastAPI** entwickelt.
|
|
||||||
|
|
||||||
Es vereinfacht den Prozess des **Erstellens**, **Deployens** und **Zugreifens** 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 Finanzierungsgeber für die *FastAPI and friends* Open-Source-Projekte. ✨
|
|
||||||
|
|
||||||
## Cloudanbieter – Sponsoren { #cloud-providers-sponsors }
|
## Cloudanbieter – Sponsoren { #cloud-providers-sponsors }
|
||||||
|
|
||||||
Einige andere Cloudanbieter ✨ [**sponsern FastAPI**](../help-fastapi.md#sponsor-the-author){.internal-link target=_blank} ✨ ebenfalls. 🙇
|
Einige Cloudanbieter ✨ [**sponsern FastAPI**](../help-fastapi.md#sponsor-the-author){.internal-link target=_blank} ✨, dies stellt die kontinuierliche und gesunde **Entwicklung** von FastAPI und seinem **Ökosystem** sicher.
|
||||||
|
|
||||||
Sie könnten diese ebenfalls in Betracht ziehen, deren Anleitungen folgen und ihre Dienste ausprobieren:
|
Und es zeigt ihr wahres Engagement für FastAPI und seine **Community** (Sie), da sie Ihnen nicht nur einen **guten Service** bieten möchten, sondern auch sicherstellen möchten, dass Sie ein **gutes und gesundes Framework**, FastAPI, haben. 🙇
|
||||||
|
|
||||||
|
Vielleicht möchten Sie deren Dienste ausprobieren und deren Anleitungen folgen:
|
||||||
|
|
||||||
* <a href="https://docs.render.com/deploy-fastapi?utm_source=deploydoc&utm_medium=referral&utm_campaign=fastapi" class="external-link" target="_blank">Render</a>
|
* <a href="https://docs.render.com/deploy-fastapi?utm_source=deploydoc&utm_medium=referral&utm_campaign=fastapi" class="external-link" target="_blank">Render</a>
|
||||||
* <a href="https://docs.railway.com/guides/fastapi?utm_medium=integration&utm_source=docs&utm_campaign=fastapi" class="external-link" target="_blank">Railway</a>
|
* <a href="https://docs.railway.com/guides/fastapi?utm_medium=integration&utm_source=docs&utm_campaign=fastapi" class="external-link" target="_blank">Railway</a>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
# Deployment-Konzepte { #deployments-concepts }
|
# 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.
|
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 zur **Bereitstellung Ihrer Anwendung** finden können.
|
||||||
|
|
||||||
Einige wichtige Konzepte sind:
|
Einige wichtige Konzepte sind:
|
||||||
|
|
||||||
|
|
@ -15,11 +15,11 @@ Wir werden sehen, wie diese sich auf das **Deployment** auswirken.
|
||||||
|
|
||||||
Letztendlich besteht das ultimative Ziel darin, **Ihre API-Clients** auf **sichere** Weise zu versorgen, um **Unterbrechungen** zu vermeiden und die **Rechenressourcen** (z. B. entfernte Server/virtuelle Maschinen) so effizient wie möglich zu nutzen. 🚀
|
Letztendlich besteht das ultimative Ziel darin, **Ihre API-Clients** auf **sichere** Weise zu versorgen, um **Unterbrechungen** zu vermeiden und die **Rechenressourcen** (z. B. entfernte Server/virtuelle Maschinen) so effizient wie möglich zu nutzen. 🚀
|
||||||
|
|
||||||
Ich erzähle Ihnen hier etwas mehr über diese **Konzepte**, was Ihnen hoffentlich die **Intuition** gibt, die Sie benötigen, um zu entscheiden, wie Sie Ihre API in sehr unterschiedlichen Umgebungen deployen, möglicherweise sogar in **zukünftigen**, die jetzt noch nicht existieren.
|
Ich erzähle Ihnen hier etwas mehr über diese **Konzepte**, was Ihnen hoffentlich die **Intuition** gibt, die Sie benötigen, um zu entscheiden, wie Sie Ihre API in sehr unterschiedlichen Umgebungen bereitstellen, möglicherweise sogar in **zukünftigen**, die jetzt noch nicht existieren.
|
||||||
|
|
||||||
Durch die Berücksichtigung dieser Konzepte können Sie die beste Variante des Deployments **Ihrer eigenen APIs** **evaluieren und konzipieren**.
|
Durch die Berücksichtigung dieser Konzepte können Sie die beste Variante der Bereitstellung **Ihrer eigenen APIs** **evaluieren und konzipieren**.
|
||||||
|
|
||||||
In den nächsten Kapiteln werde ich Ihnen mehr **konkrete Rezepte** für das Deployment von FastAPI-Anwendungen geben.
|
In den nächsten Kapiteln werde ich Ihnen mehr **konkrete Rezepte** für die Bereitstellung von FastAPI-Anwendungen geben.
|
||||||
|
|
||||||
Aber schauen wir uns zunächst einmal diese grundlegenden **konzeptionellen Ideen** an. Diese Konzepte gelten auch für jede andere Art von Web-API. 💡
|
Aber schauen wir uns zunächst einmal diese grundlegenden **konzeptionellen Ideen** an. Diese Konzepte gelten auch für jede andere Art von Web-API. 💡
|
||||||
|
|
||||||
|
|
@ -271,7 +271,7 @@ In diesem Fall müssen Sie sich darüber keine Sorgen machen. 🤷
|
||||||
|
|
||||||
### Beispiele für Strategien für Vorab-Schritte { #examples-of-previous-steps-strategies }
|
### Beispiele für Strategien für Vorab-Schritte { #examples-of-previous-steps-strategies }
|
||||||
|
|
||||||
Es hängt **stark** davon ab, wie Sie **Ihr System deployen**, und hängt wahrscheinlich mit der Art und Weise zusammen, wie Sie Programme starten, Neustarts durchführen, usw.
|
Es hängt **stark** davon ab, wie Sie **Ihr System bereitstellen**, und hängt wahrscheinlich mit der Art und Weise zusammen, wie Sie Programme starten, Neustarts durchführen, usw.
|
||||||
|
|
||||||
Hier sind einige mögliche Ideen:
|
Hier sind einige mögliche Ideen:
|
||||||
|
|
||||||
|
|
@ -307,7 +307,7 @@ Sie können einfache Tools wie `htop` verwenden, um die in Ihrem Server verwende
|
||||||
|
|
||||||
## Zusammenfassung { #recap }
|
## Zusammenfassung { #recap }
|
||||||
|
|
||||||
Sie haben hier einige der wichtigsten Konzepte gelesen, die Sie wahrscheinlich berücksichtigen müssen, wenn Sie entscheiden, wie Sie Ihre Anwendung deployen:
|
Sie haben hier einige der wichtigsten Konzepte gelesen, die Sie wahrscheinlich berücksichtigen müssen, wenn Sie entscheiden, wie Sie Ihre Anwendung bereitstellen:
|
||||||
|
|
||||||
* Sicherheit – HTTPS
|
* Sicherheit – HTTPS
|
||||||
* Beim Hochfahren ausführen
|
* Beim Hochfahren ausführen
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
# FastAPI in Containern – Docker { #fastapi-in-containers-docker }
|
# FastAPI in Containern – Docker { #fastapi-in-containers-docker }
|
||||||
|
|
||||||
Beim Deployment von FastAPI-Anwendungen besteht ein gängiger Ansatz darin, ein **Linux-Containerimage** zu erstellen. Normalerweise erfolgt dies mit <a href="https://www.docker.com/" class="external-link" target="_blank">**Docker**</a>. Sie können dieses Containerimage dann auf eine von mehreren möglichen Arten deployen.
|
Beim Deployment von FastAPI-Anwendungen besteht ein gängiger Ansatz darin, ein **Linux-Containerimage** zu erstellen. Normalerweise erfolgt dies mit <a href="https://www.docker.com/" class="external-link" target="_blank">**Docker**</a>. Sie können dieses Containerimage dann auf eine von mehreren möglichen Arten bereitstellen.
|
||||||
|
|
||||||
Die Verwendung von Linux-Containern bietet mehrere Vorteile, darunter **Sicherheit**, **Replizierbarkeit**, **Einfachheit** und andere.
|
Die Verwendung von Linux-Containern bietet mehrere Vorteile, darunter **Sicherheit**, **Replizierbarkeit**, **Einfachheit** und andere.
|
||||||
|
|
||||||
|
|
@ -40,7 +40,7 @@ Linux-Container werden mit demselben Linux-Kernel des Hosts (Maschine, virtuelle
|
||||||
|
|
||||||
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).
|
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).
|
||||||
|
|
||||||
Container verfügen außerdem über ihre eigenen **isoliert** laufenden Prozesse (üblicherweise nur einen Prozess), über ihr eigenes Dateisystem und ihr eigenes Netzwerk, was Deployment, Sicherheit, Entwicklung usw. vereinfacht.
|
Container verfügen außerdem über ihre eigenen **isoliert** laufenden Prozesse (üblicherweise nur einen Prozess), über ihr eigenes Dateisystem und ihr eigenes Netzwerk, was die Bereitstellung, Sicherheit, Entwicklung usw. vereinfacht.
|
||||||
|
|
||||||
## Was ist ein Containerimage { #what-is-a-container-image }
|
## Was ist ein Containerimage { #what-is-a-container-image }
|
||||||
|
|
||||||
|
|
@ -598,7 +598,7 @@ Zum Beispiel:
|
||||||
* Mit einem **Kubernetes**-Cluster
|
* Mit einem **Kubernetes**-Cluster
|
||||||
* Mit einem Docker Swarm Mode-Cluster
|
* Mit einem Docker Swarm Mode-Cluster
|
||||||
* Mit einem anderen Tool wie Nomad
|
* Mit einem anderen Tool wie Nomad
|
||||||
* Mit einem Cloud-Dienst, der Ihr Containerimage nimmt und es deployt
|
* Mit einem Cloud-Dienst, der Ihr Containerimage nimmt und es bereitstellt
|
||||||
|
|
||||||
## Docker-Image mit `uv` { #docker-image-with-uv }
|
## Docker-Image mit `uv` { #docker-image-with-uv }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,65 +0,0 @@
|
||||||
# FastAPI Cloud { #fastapi-cloud }
|
|
||||||
|
|
||||||
Sie können Ihre FastAPI-App in der <a href="https://fastapicloud.com" class="external-link" target="_blank">FastAPI Cloud</a> 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:
|
|
||||||
|
|
||||||
<div class="termy">
|
|
||||||
|
|
||||||
```console
|
|
||||||
$ fastapi login
|
|
||||||
|
|
||||||
You are logged in to FastAPI Cloud 🚀
|
|
||||||
```
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
## Deployen { #deploy }
|
|
||||||
|
|
||||||
Stellen Sie Ihre App jetzt mit **einem einzigen Befehl** bereit:
|
|
||||||
|
|
||||||
<div class="termy">
|
|
||||||
|
|
||||||
```console
|
|
||||||
$ fastapi deploy
|
|
||||||
|
|
||||||
Deploying to FastAPI Cloud...
|
|
||||||
|
|
||||||
✅ Deployment successful!
|
|
||||||
|
|
||||||
🐔 Ready the chicken! Your app is ready at https://myapp.fastapicloud.dev
|
|
||||||
```
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
Das war’s! Jetzt können Sie Ihre App unter dieser URL aufrufen. ✨
|
|
||||||
|
|
||||||
## Über FastAPI Cloud { #about-fastapi-cloud }
|
|
||||||
|
|
||||||
**<a href="https://fastapicloud.com" class="external-link" target="_blank">FastAPI Cloud</a>** wird vom gleichen Autor und Team hinter **FastAPI** entwickelt.
|
|
||||||
|
|
||||||
Es vereinfacht den Prozess des **Erstellens**, **Deployens** und **Nutzens** einer API mit minimalem Aufwand.
|
|
||||||
|
|
||||||
Es bringt die gleiche **Developer-Experience** beim Erstellen von Apps mit FastAPI auch zum **Deployment** in der Cloud. 🎉
|
|
||||||
|
|
||||||
Es kümmert sich außerdem um das meiste, was beim Deployen einer App nötig ist, zum Beispiel:
|
|
||||||
|
|
||||||
* HTTPS
|
|
||||||
* Replikation, mit Autoscaling basierend auf Requests
|
|
||||||
* usw.
|
|
||||||
|
|
||||||
FastAPI Cloud ist Hauptsponsor und Finanzierer der Open-Source-Projekte *FastAPI and friends*. ✨
|
|
||||||
|
|
||||||
## Bei anderen Cloudanbietern deployen { #deploy-to-other-cloud-providers }
|
|
||||||
|
|
||||||
FastAPI ist Open Source und basiert auf Standards. Sie können FastAPI-Apps bei jedem Cloudanbieter Ihrer Wahl deployen.
|
|
||||||
|
|
||||||
Folgen Sie den Anleitungen Ihres Cloudanbieters, um dort FastAPI-Apps zu deployen. 🤓
|
|
||||||
|
|
||||||
## 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. 🤓
|
|
||||||
|
|
@ -14,9 +14,7 @@ Das steht im Gegensatz zu den **Entwicklungsphasen**, in denen Sie ständig den
|
||||||
|
|
||||||
Es gibt mehrere Möglichkeiten, dies zu tun, abhängig von Ihrem spezifischen Anwendungsfall und den von Ihnen verwendeten Tools.
|
Es gibt mehrere Möglichkeiten, dies zu tun, abhängig von Ihrem spezifischen Anwendungsfall und den von Ihnen verwendeten Tools.
|
||||||
|
|
||||||
Sie könnten mithilfe einer Kombination von Tools selbst **einen Server deployen**, Sie könnten einen **Cloud-Dienst** nutzen, der einen Teil der Arbeit für Sie erledigt, oder andere mögliche Optionen.
|
Sie könnten mithilfe einer Kombination von Tools selbst **einen Server bereitstellen**, Sie könnten einen **Cloud-Dienst** nutzen, der einen Teil der Arbeit für Sie erledigt, oder andere mögliche Optionen.
|
||||||
|
|
||||||
Zum Beispiel haben wir, das Team hinter FastAPI, <a href="https://fastapicloud.com" class="external-link" target="_blank">**FastAPI Cloud**</a> entwickelt, um das Deployment von FastAPI-Apps in der Cloud so reibungslos wie möglich zu gestalten, mit derselben Developer-Experience wie beim Arbeiten mit FastAPI.
|
|
||||||
|
|
||||||
Ich zeige Ihnen einige der wichtigsten Konzepte, die Sie beim Deployment einer **FastAPI**-Anwendung wahrscheinlich berücksichtigen sollten (obwohl das meiste davon auch für jede andere Art von Webanwendung gilt).
|
Ich zeige Ihnen einige der wichtigsten Konzepte, die Sie beim Deployment einer **FastAPI**-Anwendung wahrscheinlich berücksichtigen sollten (obwohl das meiste davon auch für jede andere Art von Webanwendung gilt).
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ Schauen wir uns die Deployment-Konzepte von früher noch einmal an:
|
||||||
|
|
||||||
Bis zu diesem Punkt, in allen Tutorials in der Dokumentation, haben Sie wahrscheinlich ein **Serverprogramm** ausgeführt, zum Beispiel mit dem `fastapi`-Befehl, der Uvicorn startet, und einen **einzelnen Prozess** ausführt.
|
Bis zu diesem Punkt, in allen Tutorials in der Dokumentation, haben Sie wahrscheinlich ein **Serverprogramm** ausgeführt, zum Beispiel mit dem `fastapi`-Befehl, der Uvicorn startet, und einen **einzelnen Prozess** ausführt.
|
||||||
|
|
||||||
Wenn Sie Anwendungen deployen, möchten Sie wahrscheinlich eine gewisse **Replikation von Prozessen**, um **mehrere Kerne** zu nutzen und mehr <abbr title="Request – Anfrage: Daten, die der Client zum Server sendet">Requests</abbr> bearbeiten zu können.
|
Wenn Sie Anwendungen bereitstellen, möchten Sie wahrscheinlich eine gewisse **Replikation von Prozessen**, um **mehrere Kerne** zu nutzen und mehr <abbr title="Request – Anfrage: Daten, die der Client zum Server sendet">Requests</abbr> bearbeiten zu können.
|
||||||
|
|
||||||
Wie Sie im vorherigen Kapitel über [Deployment-Konzepte](concepts.md){.internal-link target=_blank} gesehen haben, gibt es mehrere Strategien, die Sie anwenden können.
|
Wie Sie im vorherigen Kapitel über [Deployment-Konzepte](concepts.md){.internal-link target=_blank} gesehen haben, gibt es mehrere Strategien, die Sie anwenden können.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -66,7 +66,7 @@ Das Ausführen von `fastapi run` startet FastAPI standardmäßig im Produktionsm
|
||||||
|
|
||||||
Standardmäßig ist **Autoreload** deaktiviert. Es horcht auch auf der IP-Adresse `0.0.0.0`, was alle verfügbaren IP-Adressen bedeutet, so wird es öffentlich zugänglich für jeden, der mit der Maschine kommunizieren kann. So würden Sie es normalerweise in der Produktion ausführen, beispielsweise in einem Container.
|
Standardmäßig ist **Autoreload** deaktiviert. Es horcht auch auf der IP-Adresse `0.0.0.0`, was alle verfügbaren IP-Adressen bedeutet, so wird es öffentlich zugänglich für jeden, der mit der Maschine kommunizieren kann. So würden Sie es normalerweise in der Produktion ausführen, beispielsweise in einem Container.
|
||||||
|
|
||||||
In den meisten Fällen würden (und sollten) Sie einen „Terminierungsproxy“ haben, der HTTPS für Sie verwaltet. Dies hängt davon ab, wie Sie Ihre Anwendung deployen. Ihr Anbieter könnte dies für Sie erledigen, oder Sie müssen es selbst einrichten.
|
In den meisten Fällen würden (und sollten) Sie einen „Terminierungsproxy“ haben, der HTTPS für Sie verwaltet. Dies hängt davon ab, wie Sie Ihre Anwendung bereitstellen. Ihr Anbieter könnte dies für Sie erledigen, oder Sie müssen es selbst einrichten.
|
||||||
|
|
||||||
/// tip | Tipp
|
/// tip | Tipp
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,17 +0,0 @@
|
||||||
# Alte 403-Authentifizierungsfehler-Statuscodes verwenden { #use-old-403-authentication-error-status-codes }
|
|
||||||
|
|
||||||
Vor FastAPI-Version `0.122.0` verwendeten die integrierten Sicherheits-Utilities den HTTP-Statuscode `403 Forbidden`, wenn sie dem Client nach einer fehlgeschlagenen Authentifizierung einen Fehler zurückgaben.
|
|
||||||
|
|
||||||
Ab FastAPI-Version `0.122.0` verwenden sie den passenderen HTTP-Statuscode `401 Unauthorized` und geben in der Response einen sinnvollen `WWW-Authenticate`-Header zurück, gemäß den HTTP-Spezifikationen, <a href="https://datatracker.ietf.org/doc/html/rfc7235#section-3.1" class="external-link" target="_blank">RFC 7235</a>, <a href="https://datatracker.ietf.org/doc/html/rfc9110#name-401-unauthorized" class="external-link" target="_blank">RFC 9110</a>.
|
|
||||||
|
|
||||||
Aber falls Ihre Clients aus irgendeinem Grund vom alten Verhalten abhängen, können Sie darauf zurückgreifen, indem Sie in Ihren Sicherheitsklassen die Methode `make_not_authenticated_error` überschreiben.
|
|
||||||
|
|
||||||
Sie können beispielsweise eine Unterklasse von `HTTPBearer` erstellen, die einen Fehler `403 Forbidden` zurückgibt, statt des Default-`401 Unauthorized`-Fehlers:
|
|
||||||
|
|
||||||
{* ../../docs_src/authentication_error_status_code/tutorial001_an_py39.py hl[9:13] *}
|
|
||||||
|
|
||||||
/// tip | Tipp
|
|
||||||
|
|
||||||
Beachten Sie, dass die Funktion die Exception-Instanz zurückgibt; sie wirft sie nicht. Das Werfen erfolgt im restlichen internen Code.
|
|
||||||
|
|
||||||
///
|
|
||||||
|
|
@ -29,7 +29,7 @@ Sie können problemlos dieselben Pydantic-Einstellungen verwenden, um Ihre gener
|
||||||
|
|
||||||
Zum Beispiel:
|
Zum Beispiel:
|
||||||
|
|
||||||
{* ../../docs_src/conditional_openapi/tutorial001_py39.py hl[6,11] *}
|
{* ../../docs_src/conditional_openapi/tutorial001.py hl[6,11] *}
|
||||||
|
|
||||||
Hier deklarieren wir die Einstellung `openapi_url` mit dem gleichen Defaultwert `"/openapi.json"`.
|
Hier deklarieren wir die Einstellung `openapi_url` mit dem gleichen Defaultwert `"/openapi.json"`.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ Ohne Änderung der Einstellungen ist die Syntaxhervorhebung standardmäßig akti
|
||||||
|
|
||||||
Sie können sie jedoch deaktivieren, indem Sie `syntaxHighlight` auf `False` setzen:
|
Sie können sie jedoch deaktivieren, indem Sie `syntaxHighlight` auf `False` setzen:
|
||||||
|
|
||||||
{* ../../docs_src/configure_swagger_ui/tutorial001_py39.py hl[3] *}
|
{* ../../docs_src/configure_swagger_ui/tutorial001.py hl[3] *}
|
||||||
|
|
||||||
... und dann zeigt die Swagger-Oberfläche die Syntaxhervorhebung nicht mehr an:
|
... und dann zeigt die Swagger-Oberfläche die Syntaxhervorhebung nicht mehr an:
|
||||||
|
|
||||||
|
|
@ -28,7 +28,7 @@ Sie können sie jedoch deaktivieren, indem Sie `syntaxHighlight` auf `False` set
|
||||||
|
|
||||||
Auf die gleiche Weise könnten Sie das Theme der Syntaxhervorhebung mit dem Schlüssel `"syntaxHighlight.theme"` festlegen (beachten Sie, dass er einen Punkt in der Mitte hat):
|
Auf die gleiche Weise könnten Sie das Theme der Syntaxhervorhebung mit dem Schlüssel `"syntaxHighlight.theme"` festlegen (beachten Sie, dass er einen Punkt in der Mitte hat):
|
||||||
|
|
||||||
{* ../../docs_src/configure_swagger_ui/tutorial002_py39.py hl[3] *}
|
{* ../../docs_src/configure_swagger_ui/tutorial002.py hl[3] *}
|
||||||
|
|
||||||
Obige Konfiguration würde das Theme für die Farbe der Syntaxhervorhebung ändern:
|
Obige Konfiguration würde das Theme für die Farbe der Syntaxhervorhebung ändern:
|
||||||
|
|
||||||
|
|
@ -40,13 +40,13 @@ FastAPI enthält einige Defaultkonfigurationsparameter, die für die meisten Anw
|
||||||
|
|
||||||
Es umfasst die folgenden Defaultkonfigurationen:
|
Es umfasst die folgenden Defaultkonfigurationen:
|
||||||
|
|
||||||
{* ../../fastapi/openapi/docs.py ln[9:24] hl[18:24] *}
|
{* ../../fastapi/openapi/docs.py ln[8:23] hl[17:23] *}
|
||||||
|
|
||||||
Sie können jede davon überschreiben, indem Sie im Argument `swagger_ui_parameters` einen anderen Wert festlegen.
|
Sie können jede davon überschreiben, indem Sie im Argument `swagger_ui_parameters` einen anderen Wert festlegen.
|
||||||
|
|
||||||
Um beispielsweise `deepLinking` zu deaktivieren, könnten Sie folgende Einstellungen an `swagger_ui_parameters` übergeben:
|
Um beispielsweise `deepLinking` zu deaktivieren, könnten Sie folgende Einstellungen an `swagger_ui_parameters` übergeben:
|
||||||
|
|
||||||
{* ../../docs_src/configure_swagger_ui/tutorial003_py39.py hl[3] *}
|
{* ../../docs_src/configure_swagger_ui/tutorial003.py hl[3] *}
|
||||||
|
|
||||||
## Andere Parameter der Swagger-Oberfläche { #other-swagger-ui-parameters }
|
## Andere Parameter der Swagger-Oberfläche { #other-swagger-ui-parameters }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ Der erste Schritt besteht darin, die automatischen Dokumentationen zu deaktivier
|
||||||
|
|
||||||
Um diese zu deaktivieren, setzen Sie deren URLs beim Erstellen Ihrer `FastAPI`-App auf `None`:
|
Um diese zu deaktivieren, setzen Sie deren URLs beim Erstellen Ihrer `FastAPI`-App auf `None`:
|
||||||
|
|
||||||
{* ../../docs_src/custom_docs_ui/tutorial001_py39.py hl[8] *}
|
{* ../../docs_src/custom_docs_ui/tutorial001.py hl[8] *}
|
||||||
|
|
||||||
### Die benutzerdefinierten Dokumentationen hinzufügen { #include-the-custom-docs }
|
### Die benutzerdefinierten Dokumentationen hinzufügen { #include-the-custom-docs }
|
||||||
|
|
||||||
|
|
@ -34,7 +34,7 @@ Sie können die internen Funktionen von FastAPI wiederverwenden, um die HTML-Sei
|
||||||
|
|
||||||
Und ähnlich für ReDoc ...
|
Und ähnlich für ReDoc ...
|
||||||
|
|
||||||
{* ../../docs_src/custom_docs_ui/tutorial001_py39.py hl[2:6,11:19,22:24,27:33] *}
|
{* ../../docs_src/custom_docs_ui/tutorial001.py hl[2:6,11:19,22:24,27:33] *}
|
||||||
|
|
||||||
/// tip | Tipp
|
/// tip | Tipp
|
||||||
|
|
||||||
|
|
@ -50,7 +50,7 @@ Swagger UI erledigt das hinter den Kulissen für Sie, benötigt aber diesen „U
|
||||||
|
|
||||||
Um nun testen zu können, ob alles funktioniert, erstellen Sie eine *Pfadoperation*:
|
Um nun testen zu können, ob alles funktioniert, erstellen Sie eine *Pfadoperation*:
|
||||||
|
|
||||||
{* ../../docs_src/custom_docs_ui/tutorial001_py39.py hl[36:38] *}
|
{* ../../docs_src/custom_docs_ui/tutorial001.py hl[36:38] *}
|
||||||
|
|
||||||
### Es testen { #test-it }
|
### Es testen { #test-it }
|
||||||
|
|
||||||
|
|
@ -118,7 +118,7 @@ Danach könnte Ihre Dateistruktur wie folgt aussehen:
|
||||||
* Importieren Sie `StaticFiles`.
|
* Importieren Sie `StaticFiles`.
|
||||||
* „Mounten“ Sie eine `StaticFiles()`-Instanz in einem bestimmten Pfad.
|
* „Mounten“ Sie eine `StaticFiles()`-Instanz in einem bestimmten Pfad.
|
||||||
|
|
||||||
{* ../../docs_src/custom_docs_ui/tutorial002_py39.py hl[7,11] *}
|
{* ../../docs_src/custom_docs_ui/tutorial002.py hl[7,11] *}
|
||||||
|
|
||||||
### Die statischen Dateien testen { #test-the-static-files }
|
### Die statischen Dateien testen { #test-the-static-files }
|
||||||
|
|
||||||
|
|
@ -144,7 +144,7 @@ Wie bei der Verwendung eines benutzerdefinierten CDN besteht der erste Schritt d
|
||||||
|
|
||||||
Um sie zu deaktivieren, setzen Sie deren URLs beim Erstellen Ihrer `FastAPI`-App auf `None`:
|
Um sie zu deaktivieren, setzen Sie deren URLs beim Erstellen Ihrer `FastAPI`-App auf `None`:
|
||||||
|
|
||||||
{* ../../docs_src/custom_docs_ui/tutorial002_py39.py hl[9] *}
|
{* ../../docs_src/custom_docs_ui/tutorial002.py hl[9] *}
|
||||||
|
|
||||||
### Die benutzerdefinierten Dokumentationen für statische Dateien hinzufügen { #include-the-custom-docs-for-static-files }
|
### Die benutzerdefinierten Dokumentationen für statische Dateien hinzufügen { #include-the-custom-docs-for-static-files }
|
||||||
|
|
||||||
|
|
@ -160,7 +160,7 @@ Auch hier können Sie die internen Funktionen von FastAPI wiederverwenden, um di
|
||||||
|
|
||||||
Und ähnlich für ReDoc ...
|
Und ähnlich für ReDoc ...
|
||||||
|
|
||||||
{* ../../docs_src/custom_docs_ui/tutorial002_py39.py hl[2:6,14:22,25:27,30:36] *}
|
{* ../../docs_src/custom_docs_ui/tutorial002.py hl[2:6,14:22,25:27,30:36] *}
|
||||||
|
|
||||||
/// tip | Tipp
|
/// tip | Tipp
|
||||||
|
|
||||||
|
|
@ -176,7 +176,7 @@ Swagger UI erledigt das hinter den Kulissen für Sie, benötigt aber diesen „U
|
||||||
|
|
||||||
Um nun testen zu können, ob alles funktioniert, erstellen Sie eine *Pfadoperation*:
|
Um nun testen zu können, ob alles funktioniert, erstellen Sie eine *Pfadoperation*:
|
||||||
|
|
||||||
{* ../../docs_src/custom_docs_ui/tutorial002_py39.py hl[39:41] *}
|
{* ../../docs_src/custom_docs_ui/tutorial002.py hl[39:41] *}
|
||||||
|
|
||||||
### Benutzeroberfläche mit statischen Dateien testen { #test-static-files-ui }
|
### Benutzeroberfläche mit statischen Dateien testen { #test-static-files-ui }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,7 @@ Wenn der Header kein `gzip` enthält, wird nicht versucht, den Body zu dekomprim
|
||||||
|
|
||||||
Auf diese Weise kann dieselbe Routenklasse gzip-komprimierte oder unkomprimierte Requests verarbeiten.
|
Auf diese Weise kann dieselbe Routenklasse gzip-komprimierte oder unkomprimierte Requests verarbeiten.
|
||||||
|
|
||||||
{* ../../docs_src/custom_request_and_route/tutorial001_an_py310.py hl[9:16] *}
|
{* ../../docs_src/custom_request_and_route/tutorial001.py hl[8:15] *}
|
||||||
|
|
||||||
### Eine benutzerdefinierte `GzipRoute`-Klasse erstellen { #create-a-custom-gziproute-class }
|
### Eine benutzerdefinierte `GzipRoute`-Klasse erstellen { #create-a-custom-gziproute-class }
|
||||||
|
|
||||||
|
|
@ -54,7 +54,7 @@ Diese Methode gibt eine Funktion zurück. Und diese Funktion empfängt einen <ab
|
||||||
|
|
||||||
Hier verwenden wir sie, um aus dem ursprünglichen Request einen `GzipRequest` zu erstellen.
|
Hier verwenden wir sie, um aus dem ursprünglichen Request einen `GzipRequest` zu erstellen.
|
||||||
|
|
||||||
{* ../../docs_src/custom_request_and_route/tutorial001_an_py310.py hl[19:27] *}
|
{* ../../docs_src/custom_request_and_route/tutorial001.py hl[18:26] *}
|
||||||
|
|
||||||
/// note | Technische Details
|
/// note | Technische Details
|
||||||
|
|
||||||
|
|
@ -92,18 +92,18 @@ Wir können denselben Ansatz auch verwenden, um in einem Exceptionhandler auf de
|
||||||
|
|
||||||
Alles, was wir tun müssen, ist, den Request innerhalb eines `try`/`except`-Blocks zu handhaben:
|
Alles, was wir tun müssen, ist, den Request innerhalb eines `try`/`except`-Blocks zu handhaben:
|
||||||
|
|
||||||
{* ../../docs_src/custom_request_and_route/tutorial002_an_py310.py hl[14,16] *}
|
{* ../../docs_src/custom_request_and_route/tutorial002.py hl[13,15] *}
|
||||||
|
|
||||||
Wenn eine Exception auftritt, befindet sich die `Request`-Instanz weiterhin im Gültigkeitsbereich, sodass wir den Requestbody lesen und bei der Fehlerbehandlung verwenden können:
|
Wenn eine Exception auftritt, befindet sich die `Request`-Instanz weiterhin im Gültigkeitsbereich, sodass wir den Requestbody lesen und bei der Fehlerbehandlung verwenden können:
|
||||||
|
|
||||||
{* ../../docs_src/custom_request_and_route/tutorial002_an_py310.py hl[17:19] *}
|
{* ../../docs_src/custom_request_and_route/tutorial002.py hl[16:18] *}
|
||||||
|
|
||||||
## Benutzerdefinierte `APIRoute`-Klasse in einem Router { #custom-apiroute-class-in-a-router }
|
## Benutzerdefinierte `APIRoute`-Klasse in einem Router { #custom-apiroute-class-in-a-router }
|
||||||
|
|
||||||
Sie können auch den Parameter `route_class` eines `APIRouter` festlegen:
|
Sie können auch den Parameter `route_class` eines `APIRouter` festlegen:
|
||||||
|
|
||||||
{* ../../docs_src/custom_request_and_route/tutorial003_py310.py hl[26] *}
|
{* ../../docs_src/custom_request_and_route/tutorial003.py hl[26] *}
|
||||||
|
|
||||||
In diesem Beispiel verwenden die *Pfadoperationen* unter dem `router` die benutzerdefinierte `TimedRoute`-Klasse und haben in der Response einen zusätzlichen `X-Response-Time`-Header mit der Zeit, die zum Generieren der Response benötigt wurde:
|
In diesem Beispiel verwenden die *Pfadoperationen* unter dem `router` die benutzerdefinierte `TimedRoute`-Klasse und haben in der Response einen zusätzlichen `X-Response-Time`-Header mit der Zeit, die zum Generieren der Response benötigt wurde:
|
||||||
|
|
||||||
{* ../../docs_src/custom_request_and_route/tutorial003_py310.py hl[13:20] *}
|
{* ../../docs_src/custom_request_and_route/tutorial003.py hl[13:20] *}
|
||||||
|
|
|
||||||
|
|
@ -43,19 +43,19 @@ Fügen wir beispielsweise <a href="https://github.com/Rebilly/ReDoc/blob/master/
|
||||||
|
|
||||||
Schreiben Sie zunächst wie gewohnt Ihre ganze **FastAPI**-Anwendung:
|
Schreiben Sie zunächst wie gewohnt Ihre ganze **FastAPI**-Anwendung:
|
||||||
|
|
||||||
{* ../../docs_src/extending_openapi/tutorial001_py39.py hl[1,4,7:9] *}
|
{* ../../docs_src/extending_openapi/tutorial001.py hl[1,4,7:9] *}
|
||||||
|
|
||||||
### Das OpenAPI-Schema generieren { #generate-the-openapi-schema }
|
### Das OpenAPI-Schema generieren { #generate-the-openapi-schema }
|
||||||
|
|
||||||
Verwenden Sie dann dieselbe Hilfsfunktion, um das OpenAPI-Schema innerhalb einer `custom_openapi()`-Funktion zu generieren:
|
Verwenden Sie dann dieselbe Hilfsfunktion, um das OpenAPI-Schema innerhalb einer `custom_openapi()`-Funktion zu generieren:
|
||||||
|
|
||||||
{* ../../docs_src/extending_openapi/tutorial001_py39.py hl[2,15:21] *}
|
{* ../../docs_src/extending_openapi/tutorial001.py hl[2,15:21] *}
|
||||||
|
|
||||||
### Das OpenAPI-Schema ändern { #modify-the-openapi-schema }
|
### Das OpenAPI-Schema ändern { #modify-the-openapi-schema }
|
||||||
|
|
||||||
Jetzt können Sie die ReDoc-Erweiterung hinzufügen und dem `info`-„Objekt“ im OpenAPI-Schema ein benutzerdefiniertes `x-logo` hinzufügen:
|
Jetzt können Sie die ReDoc-Erweiterung hinzufügen und dem `info`-„Objekt“ im OpenAPI-Schema ein benutzerdefiniertes `x-logo` hinzufügen:
|
||||||
|
|
||||||
{* ../../docs_src/extending_openapi/tutorial001_py39.py hl[22:24] *}
|
{* ../../docs_src/extending_openapi/tutorial001.py hl[22:24] *}
|
||||||
|
|
||||||
### Zwischenspeichern des OpenAPI-Schemas { #cache-the-openapi-schema }
|
### Zwischenspeichern des OpenAPI-Schemas { #cache-the-openapi-schema }
|
||||||
|
|
||||||
|
|
@ -65,13 +65,13 @@ Auf diese Weise muss Ihre Anwendung das Schema nicht jedes Mal generieren, wenn
|
||||||
|
|
||||||
Es wird nur einmal generiert und dann wird dasselbe zwischengespeicherte Schema für die nächsten <abbr title="Request – Anfrage: Daten, die der Client zum Server sendet">Requests</abbr> verwendet.
|
Es wird nur einmal generiert und dann wird dasselbe zwischengespeicherte Schema für die nächsten <abbr title="Request – Anfrage: Daten, die der Client zum Server sendet">Requests</abbr> verwendet.
|
||||||
|
|
||||||
{* ../../docs_src/extending_openapi/tutorial001_py39.py hl[13:14,25:26] *}
|
{* ../../docs_src/extending_openapi/tutorial001.py hl[13:14,25:26] *}
|
||||||
|
|
||||||
### Die Methode überschreiben { #override-the-method }
|
### Die Methode überschreiben { #override-the-method }
|
||||||
|
|
||||||
Jetzt können Sie die Methode `.openapi()` durch Ihre neue Funktion ersetzen.
|
Jetzt können Sie die Methode `.openapi()` durch Ihre neue Funktion ersetzen.
|
||||||
|
|
||||||
{* ../../docs_src/extending_openapi/tutorial001_py39.py hl[29] *}
|
{* ../../docs_src/extending_openapi/tutorial001.py hl[29] *}
|
||||||
|
|
||||||
### Es testen { #check-it }
|
### Es testen { #check-it }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ Abhängig von Ihrem Anwendungsfall könnten Sie eine andere Bibliothek vorziehen
|
||||||
|
|
||||||
Hier ist eine kleine Vorschau, wie Sie Strawberry mit FastAPI integrieren können:
|
Hier ist eine kleine Vorschau, wie Sie Strawberry mit FastAPI integrieren können:
|
||||||
|
|
||||||
{* ../../docs_src/graphql/tutorial001_py39.py hl[3,22,25] *}
|
{* ../../docs_src/graphql/tutorial001.py hl[3,22,25] *}
|
||||||
|
|
||||||
Weitere Informationen zu Strawberry finden Sie in der <a href="https://strawberry.rocks/" class="external-link" target="_blank">Strawberry-Dokumentation</a>.
|
Weitere Informationen zu Strawberry finden Sie in der <a href="https://strawberry.rocks/" class="external-link" target="_blank">Strawberry-Dokumentation</a>.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -46,26 +46,20 @@ Seine Schlüssel-Merkmale sind:
|
||||||
* **Robust**: Erhalten Sie produktionsreifen Code. Mit automatischer, interaktiver Dokumentation.
|
* **Robust**: Erhalten Sie produktionsreifen Code. Mit automatischer, interaktiver Dokumentation.
|
||||||
* **Standards-basiert**: Basierend auf (und vollständig kompatibel mit) den offenen Standards für APIs: <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank">OpenAPI</a> (früher bekannt als Swagger) und <a href="https://json-schema.org/" class="external-link" target="_blank">JSON Schema</a>.
|
* **Standards-basiert**: Basierend auf (und vollständig kompatibel mit) den offenen Standards für APIs: <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank">OpenAPI</a> (früher bekannt als Swagger) und <a href="https://json-schema.org/" class="external-link" target="_blank">JSON Schema</a>.
|
||||||
|
|
||||||
<small>* Schätzung basierend auf Tests, die von einem internen Entwicklungsteam durchgeführt wurden, das Produktionsanwendungen erstellt.</small>
|
<small>* Schätzung basierend auf Tests in einem internen Entwicklungsteam, das Produktionsanwendungen erstellt.</small>
|
||||||
|
|
||||||
## Sponsoren { #sponsors }
|
## Sponsoren { #sponsors }
|
||||||
|
|
||||||
<!-- sponsors -->
|
<!-- sponsors -->
|
||||||
|
|
||||||
### Keystone-Sponsor { #keystone-sponsor }
|
{% if sponsors %}
|
||||||
|
|
||||||
{% for sponsor in sponsors.keystone -%}
|
|
||||||
<a href="{{ sponsor.url }}" target="_blank" title="{{ sponsor.title }}"><img src="{{ sponsor.img }}" style="border-radius:15px"></a>
|
|
||||||
{% endfor -%}
|
|
||||||
|
|
||||||
### Gold- und Silber-Sponsoren { #gold-and-silver-sponsors }
|
|
||||||
|
|
||||||
{% for sponsor in sponsors.gold -%}
|
{% for sponsor in sponsors.gold -%}
|
||||||
<a href="{{ sponsor.url }}" target="_blank" title="{{ sponsor.title }}"><img src="{{ sponsor.img }}" style="border-radius:15px"></a>
|
<a href="{{ sponsor.url }}" target="_blank" title="{{ sponsor.title }}"><img src="{{ sponsor.img }}" style="border-radius:15px"></a>
|
||||||
{% endfor -%}
|
{% endfor -%}
|
||||||
{%- for sponsor in sponsors.silver -%}
|
{%- for sponsor in sponsors.silver -%}
|
||||||
<a href="{{ sponsor.url }}" target="_blank" title="{{ sponsor.title }}"><img src="{{ sponsor.img }}" style="border-radius:15px"></a>
|
<a href="{{ sponsor.url }}" target="_blank" title="{{ sponsor.title }}"><img src="{{ sponsor.img }}" style="border-radius:15px"></a>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
<!-- /sponsors -->
|
<!-- /sponsors -->
|
||||||
|
|
||||||
|
|
@ -450,58 +444,6 @@ Für ein vollständigeres Beispiel, mit weiteren Funktionen, siehe das <a href="
|
||||||
* **Cookie-Sessions**
|
* **Cookie-Sessions**
|
||||||
* ... und mehr.
|
* ... und mehr.
|
||||||
|
|
||||||
### Ihre App deployen (optional) { #deploy-your-app-optional }
|
|
||||||
|
|
||||||
Optional können Sie Ihre FastAPI-App in die <a href="https://fastapicloud.com" class="external-link" target="_blank">FastAPI Cloud</a> deployen, treten Sie der Warteliste bei, falls noch nicht geschehen. 🚀
|
|
||||||
|
|
||||||
Wenn Sie bereits ein **FastAPI Cloud**-Konto haben (wir haben Sie von der Warteliste eingeladen 😉), können Sie Ihre Anwendung mit einem einzigen Befehl deployen.
|
|
||||||
|
|
||||||
Stellen Sie vor dem Deployen sicher, dass Sie eingeloggt sind:
|
|
||||||
|
|
||||||
<div class="termy">
|
|
||||||
|
|
||||||
```console
|
|
||||||
$ fastapi login
|
|
||||||
|
|
||||||
You are logged in to FastAPI Cloud 🚀
|
|
||||||
```
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
Stellen Sie dann Ihre App bereit:
|
|
||||||
|
|
||||||
<div class="termy">
|
|
||||||
|
|
||||||
```console
|
|
||||||
$ fastapi deploy
|
|
||||||
|
|
||||||
Deploying to FastAPI Cloud...
|
|
||||||
|
|
||||||
✅ Deployment successful!
|
|
||||||
|
|
||||||
🐔 Ready the chicken! Your app is ready at https://myapp.fastapicloud.dev
|
|
||||||
```
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
Das war’s! Jetzt können Sie unter dieser URL auf Ihre App zugreifen. ✨
|
|
||||||
|
|
||||||
#### Über FastAPI Cloud { #about-fastapi-cloud }
|
|
||||||
|
|
||||||
**<a href="https://fastapicloud.com" class="external-link" target="_blank">FastAPI Cloud</a>** wird vom selben Autor und Team hinter **FastAPI** entwickelt.
|
|
||||||
|
|
||||||
Es vereinfacht den Prozess des **Erstellens**, **Deployens** und **Zugreifens** 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. ✨
|
|
||||||
|
|
||||||
#### Bei anderen Cloudanbietern deployen { #deploy-to-other-cloud-providers }
|
|
||||||
|
|
||||||
FastAPI ist Open Source und basiert auf Standards. Sie können FastAPI-Apps bei jedem Cloudanbieter Ihrer Wahl deployen.
|
|
||||||
|
|
||||||
Folgen Sie den Anleitungen Ihres Cloudanbieters, um FastAPI-Apps dort bereitzustellen. 🤓
|
|
||||||
|
|
||||||
## Performanz { #performance }
|
## Performanz { #performance }
|
||||||
|
|
||||||
Unabhängige TechEmpower-Benchmarks zeigen **FastAPI**-Anwendungen, die unter Uvicorn laufen, als <a href="https://www.techempower.com/benchmarks/#section=test&runid=7464e520-0dc2-473d-bd34-dbdfd7e85911&hw=ph&test=query&l=zijzen-7" class="external-link" target="_blank">eines der schnellsten verfügbaren Python-Frameworks</a>, nur hinter Starlette und Uvicorn selbst (intern von FastAPI verwendet). (*)
|
Unabhängige TechEmpower-Benchmarks zeigen **FastAPI**-Anwendungen, die unter Uvicorn laufen, als <a href="https://www.techempower.com/benchmarks/#section=test&runid=7464e520-0dc2-473d-bd34-dbdfd7e85911&hw=ph&test=query&l=zijzen-7" class="external-link" target="_blank">eines der schnellsten verfügbaren Python-Frameworks</a>, nur hinter Starlette und Uvicorn selbst (intern von FastAPI verwendet). (*)
|
||||||
|
|
|
||||||
|
|
@ -9,20 +9,20 @@ GitHub-Repository: <a href="https://github.com/tiangolo/full-stack-fastapi-templ
|
||||||
## Full Stack FastAPI Template – Technologiestack und Funktionen { #full-stack-fastapi-template-technology-stack-and-features }
|
## Full Stack FastAPI Template – Technologiestack und Funktionen { #full-stack-fastapi-template-technology-stack-and-features }
|
||||||
|
|
||||||
- ⚡ [**FastAPI**](https://fastapi.tiangolo.com/de) für die Python-Backend-API.
|
- ⚡ [**FastAPI**](https://fastapi.tiangolo.com/de) für die Python-Backend-API.
|
||||||
- 🧰 [SQLModel](https://sqlmodel.tiangolo.com) für die Interaktion mit der Python-SQL-Datenbank (ORM).
|
- 🧰 [SQLModel](https://sqlmodel.tiangolo.com) für die Interaktion mit der Python-SQL-Datenbank (ORM).
|
||||||
- 🔍 [Pydantic](https://docs.pydantic.dev), verwendet von FastAPI, für die Datenvalidierung und das Einstellungsmanagement.
|
- 🔍 [Pydantic](https://docs.pydantic.dev), verwendet von FastAPI, für die Datenvalidierung und das Einstellungsmanagement.
|
||||||
- 💾 [PostgreSQL](https://www.postgresql.org) als SQL-Datenbank.
|
- 💾 [PostgreSQL](https://www.postgresql.org) als SQL-Datenbank.
|
||||||
- 🚀 [React](https://react.dev) für das Frontend.
|
- 🚀 [React](https://react.dev) für das Frontend.
|
||||||
- 💃 Verwendung von TypeScript, Hooks, Vite und anderen Teilen eines modernen Frontend-Stacks.
|
- 💃 Verwendung von TypeScript, Hooks, [Vite](https://vitejs.dev) und anderen Teilen eines modernen Frontend-Stacks.
|
||||||
- 🎨 [Tailwind CSS](https://tailwindcss.com) und [shadcn/ui](https://ui.shadcn.com) für die Frontend-Komponenten.
|
- 🎨 [Chakra UI](https://chakra-ui.com) für die Frontend-Komponenten.
|
||||||
- 🤖 Ein automatisch generierter Frontend-Client.
|
- 🤖 Ein automatisch generierter Frontend-Client.
|
||||||
- 🧪 [Playwright](https://playwright.dev) für End-to-End-Tests.
|
- 🧪 [Playwright](https://playwright.dev) für End-to-End-Tests.
|
||||||
- 🦇 „Dark-Mode“-Unterstützung.
|
- 🦇 Unterstützung des Dunkelmodus.
|
||||||
- 🐋 [Docker Compose](https://www.docker.com) für Entwicklung und Produktion.
|
- 🐋 [Docker Compose](https://www.docker.com) für Entwicklung und Produktion.
|
||||||
- 🔒 Sicheres Passwort-Hashing standardmäßig.
|
- 🔒 Sicheres Passwort-Hashing standardmäßig.
|
||||||
- 🔑 JWT (JSON Web Token)-Token-Authentifizierung.
|
- 🔑 JWT-Token-Authentifizierung.
|
||||||
- 📫 E-Mail-basierte Passwortwiederherstellung.
|
- 📫 E-Mail-basierte Passwortwiederherstellung.
|
||||||
- ✅ Tests mit [Pytest](https://pytest.org).
|
- ✅ Tests mit [Pytest](https://pytest.org).
|
||||||
- 📞 [Traefik](https://traefik.io) als Reverse-Proxy / Load Balancer.
|
- 📞 [Traefik](https://traefik.io) als Reverse-Proxy / Load Balancer.
|
||||||
- 🚢 Deployment-Anleitungen unter Verwendung von Docker Compose, einschließlich der Einrichtung eines Frontend-Traefik-Proxys zur Handhabung automatischer HTTPS-Zertifikate.
|
- 🚢 Deployment-Anleitungen unter Verwendung von Docker Compose, einschließlich der Einrichtung eines Frontend-Traefik-Proxys zur Handhabung automatischer HTTPS-Zertifikate.
|
||||||
- 🏭 CI (kontinuierliche Integration) und CD (kontinuierliches Deployment) basierend auf GitHub Actions.
|
- 🏭 CI (kontinuierliche Integration) und CD (kontinuierliche Bereitstellung) basierend auf GitHub Actions.
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ Wenn Sie ein Python-Experte sind und bereits alles über Typhinweise wissen, üb
|
||||||
|
|
||||||
Fangen wir mit einem einfachen Beispiel an:
|
Fangen wir mit einem einfachen Beispiel an:
|
||||||
|
|
||||||
{* ../../docs_src/python_types/tutorial001_py39.py *}
|
{* ../../docs_src/python_types/tutorial001.py *}
|
||||||
|
|
||||||
Dieses Programm gibt aus:
|
Dieses Programm gibt aus:
|
||||||
|
|
||||||
|
|
@ -34,9 +34,9 @@ Die Funktion macht Folgendes:
|
||||||
|
|
||||||
* Nimmt einen `first_name` und `last_name`.
|
* Nimmt einen `first_name` und `last_name`.
|
||||||
* Schreibt den ersten Buchstaben eines jeden Wortes groß, mithilfe von `title()`.
|
* Schreibt den ersten Buchstaben eines jeden Wortes groß, mithilfe von `title()`.
|
||||||
* <abbr title="Fügt sie zu einer Einheit zusammen. Mit dem Inhalt des einen nach dem anderen.">Verkettet</abbr> sie mit einem Leerzeichen in der Mitte.
|
* <abbr title="Füge zu einer Einheit zusammen, eins nach dem anderen.">Verkettet</abbr> sie mit einem Leerzeichen in der Mitte.
|
||||||
|
|
||||||
{* ../../docs_src/python_types/tutorial001_py39.py hl[2] *}
|
{* ../../docs_src/python_types/tutorial001.py hl[2] *}
|
||||||
|
|
||||||
### Es bearbeiten { #edit-it }
|
### Es bearbeiten { #edit-it }
|
||||||
|
|
||||||
|
|
@ -78,7 +78,7 @@ Das war's.
|
||||||
|
|
||||||
Das sind die „Typhinweise“:
|
Das sind die „Typhinweise“:
|
||||||
|
|
||||||
{* ../../docs_src/python_types/tutorial002_py39.py hl[1] *}
|
{* ../../docs_src/python_types/tutorial002.py hl[1] *}
|
||||||
|
|
||||||
Das ist nicht das gleiche wie das Deklarieren von Defaultwerten, wie es hier der Fall ist:
|
Das ist nicht das gleiche wie das Deklarieren von Defaultwerten, wie es hier der Fall ist:
|
||||||
|
|
||||||
|
|
@ -106,7 +106,7 @@ Hier können Sie durch die Optionen blättern, bis Sie diejenige finden, bei der
|
||||||
|
|
||||||
Sehen Sie sich diese Funktion an, sie hat bereits Typhinweise:
|
Sehen Sie sich diese Funktion an, sie hat bereits Typhinweise:
|
||||||
|
|
||||||
{* ../../docs_src/python_types/tutorial003_py39.py hl[1] *}
|
{* ../../docs_src/python_types/tutorial003.py hl[1] *}
|
||||||
|
|
||||||
Da der Editor die Typen der Variablen kennt, erhalten Sie nicht nur Code-Vervollständigung, sondern auch eine Fehlerprüfung:
|
Da der Editor die Typen der Variablen kennt, erhalten Sie nicht nur Code-Vervollständigung, sondern auch eine Fehlerprüfung:
|
||||||
|
|
||||||
|
|
@ -114,7 +114,7 @@ Da der Editor die Typen der Variablen kennt, erhalten Sie nicht nur Code-Vervoll
|
||||||
|
|
||||||
Jetzt, da Sie wissen, dass Sie das reparieren müssen, konvertieren Sie `age` mittels `str(age)` in einen String:
|
Jetzt, da Sie wissen, dass Sie das reparieren müssen, konvertieren Sie `age` mittels `str(age)` in einen String:
|
||||||
|
|
||||||
{* ../../docs_src/python_types/tutorial004_py39.py hl[2] *}
|
{* ../../docs_src/python_types/tutorial004.py hl[2] *}
|
||||||
|
|
||||||
## Deklarieren von Typen { #declaring-types }
|
## Deklarieren von Typen { #declaring-types }
|
||||||
|
|
||||||
|
|
@ -133,7 +133,7 @@ Zum Beispiel diese:
|
||||||
* `bool`
|
* `bool`
|
||||||
* `bytes`
|
* `bytes`
|
||||||
|
|
||||||
{* ../../docs_src/python_types/tutorial005_py39.py hl[1] *}
|
{* ../../docs_src/python_types/tutorial005.py hl[1] *}
|
||||||
|
|
||||||
### Generische Typen mit Typ-Parametern { #generic-types-with-type-parameters }
|
### Generische Typen mit Typ-Parametern { #generic-types-with-type-parameters }
|
||||||
|
|
||||||
|
|
@ -161,24 +161,56 @@ Wenn Sie über die **neueste Version von Python** verfügen, verwenden Sie die B
|
||||||
|
|
||||||
Definieren wir zum Beispiel eine Variable, die eine `list` von `str` – eine Liste von Strings – sein soll.
|
Definieren wir zum Beispiel eine Variable, die eine `list` von `str` – eine Liste von Strings – sein soll.
|
||||||
|
|
||||||
|
//// tab | Python 3.9+
|
||||||
|
|
||||||
Deklarieren Sie die Variable mit der gleichen Doppelpunkt-Syntax (`:`).
|
Deklarieren Sie die Variable mit der gleichen Doppelpunkt-Syntax (`:`).
|
||||||
|
|
||||||
Als Typ nehmen Sie `list`.
|
Als Typ nehmen Sie `list`.
|
||||||
|
|
||||||
Da die Liste ein Typ ist, welcher innere Typen enthält, werden diese von eckigen Klammern umfasst:
|
Da die Liste ein Typ ist, welcher innere Typen enthält, werden diese von eckigen Klammern umfasst:
|
||||||
|
|
||||||
{* ../../docs_src/python_types/tutorial006_py39.py hl[1] *}
|
```Python hl_lines="1"
|
||||||
|
{!> ../../docs_src/python_types/tutorial006_py39.py!}
|
||||||
|
```
|
||||||
|
|
||||||
|
////
|
||||||
|
|
||||||
|
//// tab | Python 3.8+
|
||||||
|
|
||||||
|
Von `typing` importieren Sie `List` (mit Großbuchstaben `L`):
|
||||||
|
|
||||||
|
```Python hl_lines="1"
|
||||||
|
{!> ../../docs_src/python_types/tutorial006.py!}
|
||||||
|
```
|
||||||
|
|
||||||
|
Deklarieren Sie die Variable mit der gleichen Doppelpunkt-Syntax (`:`).
|
||||||
|
|
||||||
|
Als Typ nehmen Sie das `List`, das Sie von `typing` importiert haben.
|
||||||
|
|
||||||
|
Da die Liste ein Typ ist, welcher innere Typen enthält, werden diese von eckigen Klammern umfasst:
|
||||||
|
|
||||||
|
```Python hl_lines="4"
|
||||||
|
{!> ../../docs_src/python_types/tutorial006.py!}
|
||||||
|
```
|
||||||
|
|
||||||
|
////
|
||||||
|
|
||||||
/// info | Info
|
/// info | Info
|
||||||
|
|
||||||
Die inneren Typen in den eckigen Klammern werden als „Typ-Parameter“ bezeichnet.
|
Die inneren Typen in den eckigen Klammern werden als „Typ-Parameter“ bezeichnet.
|
||||||
|
|
||||||
In diesem Fall ist `str` der Typ-Parameter, der an `list` übergeben wird.
|
In diesem Fall ist `str` der Typ-Parameter, der an `List` übergeben wird (oder `list` in Python 3.9 und darüber).
|
||||||
|
|
||||||
///
|
///
|
||||||
|
|
||||||
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 Liste – `list` – und jedes der Elemente in dieser Liste ist ein String – `str`.
|
||||||
|
|
||||||
|
/// tip | Tipp
|
||||||
|
|
||||||
|
Wenn Sie Python 3.9 oder höher verwenden, müssen Sie `List` nicht von `typing` importieren, Sie können stattdessen den regulären `list`-Typ verwenden.
|
||||||
|
|
||||||
|
///
|
||||||
|
|
||||||
Auf diese Weise kann Ihr Editor Sie auch bei der Bearbeitung von Einträgen aus der Liste unterstützen:
|
Auf diese Weise kann Ihr Editor Sie auch bei der Bearbeitung von Einträgen aus der Liste unterstützen:
|
||||||
|
|
||||||
<img src="/img/python-types/image05.png">
|
<img src="/img/python-types/image05.png">
|
||||||
|
|
@ -193,7 +225,21 @@ Und trotzdem weiß der Editor, dass es sich um ein `str` handelt, und bietet ent
|
||||||
|
|
||||||
Das Gleiche gilt für die Deklaration eines Tupels – `tuple` – und einer Menge – `set`:
|
Das Gleiche gilt für die Deklaration eines Tupels – `tuple` – und einer Menge – `set`:
|
||||||
|
|
||||||
{* ../../docs_src/python_types/tutorial007_py39.py hl[1] *}
|
//// tab | Python 3.9+
|
||||||
|
|
||||||
|
```Python hl_lines="1"
|
||||||
|
{!> ../../docs_src/python_types/tutorial007_py39.py!}
|
||||||
|
```
|
||||||
|
|
||||||
|
////
|
||||||
|
|
||||||
|
//// tab | Python 3.8+
|
||||||
|
|
||||||
|
```Python hl_lines="1 4"
|
||||||
|
{!> ../../docs_src/python_types/tutorial007.py!}
|
||||||
|
```
|
||||||
|
|
||||||
|
////
|
||||||
|
|
||||||
Das bedeutet:
|
Das bedeutet:
|
||||||
|
|
||||||
|
|
@ -208,7 +254,21 @@ Der erste Typ-Parameter ist für die Schlüssel des `dict`.
|
||||||
|
|
||||||
Der zweite Typ-Parameter ist für die Werte des `dict`:
|
Der zweite Typ-Parameter ist für die Werte des `dict`:
|
||||||
|
|
||||||
{* ../../docs_src/python_types/tutorial008_py39.py hl[1] *}
|
//// tab | Python 3.9+
|
||||||
|
|
||||||
|
```Python hl_lines="1"
|
||||||
|
{!> ../../docs_src/python_types/tutorial008_py39.py!}
|
||||||
|
```
|
||||||
|
|
||||||
|
////
|
||||||
|
|
||||||
|
//// tab | Python 3.8+
|
||||||
|
|
||||||
|
```Python hl_lines="1 4"
|
||||||
|
{!> ../../docs_src/python_types/tutorial008.py!}
|
||||||
|
```
|
||||||
|
|
||||||
|
////
|
||||||
|
|
||||||
Das bedeutet:
|
Das bedeutet:
|
||||||
|
|
||||||
|
|
@ -222,7 +282,7 @@ Sie können deklarieren, dass eine Variable einer von **verschiedenen Typen** se
|
||||||
|
|
||||||
In Python 3.6 und höher (inklusive Python 3.10) können Sie den `Union`-Typ von `typing` verwenden und die möglichen Typen innerhalb der eckigen Klammern auflisten.
|
In Python 3.6 und höher (inklusive Python 3.10) können Sie den `Union`-Typ von `typing` verwenden und die möglichen Typen innerhalb der eckigen Klammern auflisten.
|
||||||
|
|
||||||
In Python 3.10 gibt es zusätzlich eine **neue Syntax**, die es erlaubt, die möglichen Typen getrennt von einem <abbr title='auch „bitweiser Oder-Operator“ genannt, aber diese Bedeutung ist hier nicht relevant'>vertikalen Balken (`|`)</abbr> aufzulisten.
|
In Python 3.10 gibt es zusätzlich eine **neue Syntax**, die es erlaubt, die möglichen Typen getrennt von einem <abbr title='Allgemein: „oder“. In anderem Zusammenhang auch „Bitweises ODER“, aber letztere Bedeutung ist hier nicht relevant'>vertikalen Balken (`|`)</abbr> aufzulisten.
|
||||||
|
|
||||||
//// tab | Python 3.10+
|
//// tab | Python 3.10+
|
||||||
|
|
||||||
|
|
@ -232,10 +292,10 @@ In Python 3.10 gibt es zusätzlich eine **neue Syntax**, die es erlaubt, die mö
|
||||||
|
|
||||||
////
|
////
|
||||||
|
|
||||||
//// tab | Python 3.9+
|
//// tab | Python 3.8+
|
||||||
|
|
||||||
```Python hl_lines="1 4"
|
```Python hl_lines="1 4"
|
||||||
{!> ../../docs_src/python_types/tutorial008b_py39.py!}
|
{!> ../../docs_src/python_types/tutorial008b.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
////
|
////
|
||||||
|
|
@ -249,7 +309,7 @@ Sie können deklarieren, dass ein Wert ein `str`, aber vielleicht auch `None` se
|
||||||
In Python 3.6 und darüber (inklusive Python 3.10) können Sie das deklarieren, indem Sie `Optional` vom `typing` Modul importieren und verwenden.
|
In Python 3.6 und darüber (inklusive Python 3.10) können Sie das deklarieren, indem Sie `Optional` vom `typing` Modul importieren und verwenden.
|
||||||
|
|
||||||
```Python hl_lines="1 4"
|
```Python hl_lines="1 4"
|
||||||
{!../../docs_src/python_types/tutorial009_py39.py!}
|
{!../../docs_src/python_types/tutorial009.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
Wenn Sie `Optional[str]` anstelle von nur `str` verwenden, wird Ihr Editor Ihnen dabei helfen, Fehler zu erkennen, bei denen Sie annehmen könnten, dass ein Wert immer eine String (`str`) ist, obwohl er auch `None` sein könnte.
|
Wenn Sie `Optional[str]` anstelle von nur `str` verwenden, wird Ihr Editor Ihnen dabei helfen, Fehler zu erkennen, bei denen Sie annehmen könnten, dass ein Wert immer eine String (`str`) ist, obwohl er auch `None` sein könnte.
|
||||||
|
|
@ -266,18 +326,18 @@ Das bedeutet auch, dass Sie in Python 3.10 `Something | None` verwenden können:
|
||||||
|
|
||||||
////
|
////
|
||||||
|
|
||||||
//// tab | Python 3.9+
|
//// tab | Python 3.8+
|
||||||
|
|
||||||
```Python hl_lines="1 4"
|
```Python hl_lines="1 4"
|
||||||
{!> ../../docs_src/python_types/tutorial009_py39.py!}
|
{!> ../../docs_src/python_types/tutorial009.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
////
|
////
|
||||||
|
|
||||||
//// tab | Python 3.9+ Alternative
|
//// tab | Python 3.8+ Alternative
|
||||||
|
|
||||||
```Python hl_lines="1 4"
|
```Python hl_lines="1 4"
|
||||||
{!> ../../docs_src/python_types/tutorial009b_py39.py!}
|
{!> ../../docs_src/python_types/tutorial009b.py!}
|
||||||
```
|
```
|
||||||
|
|
||||||
////
|
////
|
||||||
|
|
@ -293,11 +353,11 @@ Beide sind äquivalent und im Hintergrund dasselbe, aber ich empfehle `Union` st
|
||||||
|
|
||||||
Ich denke, `Union[SomeType, None]` ist expliziter bezüglich seiner Bedeutung.
|
Ich denke, `Union[SomeType, None]` ist expliziter bezüglich seiner Bedeutung.
|
||||||
|
|
||||||
Es geht nur um Worte und Namen. Aber diese Worte können beeinflussen, wie Sie und Ihre Teamkollegen über den Code denken.
|
Es geht nur um Wörter und Namen. Aber diese Worte können beeinflussen, wie Sie und Ihre Teamkollegen über den Code denken.
|
||||||
|
|
||||||
Nehmen wir zum Beispiel diese Funktion:
|
Nehmen wir zum Beispiel diese Funktion:
|
||||||
|
|
||||||
{* ../../docs_src/python_types/tutorial009c_py39.py hl[1,4] *}
|
{* ../../docs_src/python_types/tutorial009c.py hl[1,4] *}
|
||||||
|
|
||||||
Der Parameter `name` ist definiert als `Optional[str]`, aber er ist **nicht optional**, Sie können die Funktion nicht ohne diesen Parameter aufrufen:
|
Der Parameter `name` ist definiert als `Optional[str]`, aber er ist **nicht optional**, Sie können die Funktion nicht ohne diesen Parameter aufrufen:
|
||||||
|
|
||||||
|
|
@ -330,13 +390,13 @@ Sie können die eingebauten Typen als Generics verwenden (mit eckigen Klammern u
|
||||||
* `set`
|
* `set`
|
||||||
* `dict`
|
* `dict`
|
||||||
|
|
||||||
Und ebenso wie bei früheren Python-Versionen, aus dem `typing`-Modul:
|
Verwenden Sie für den Rest, wie unter Python 3.8, das `typing`-Modul:
|
||||||
|
|
||||||
* `Union`
|
* `Union`
|
||||||
* `Optional`
|
* `Optional` (so wie unter Python 3.8)
|
||||||
* ... und andere.
|
* ... und andere.
|
||||||
|
|
||||||
In Python 3.10 können Sie als Alternative zu den Generics `Union` und `Optional` den <abbr title='auch „bitweiser Oder-Operator“ genannt, aber diese Bedeutung ist hier nicht relevant'>vertikalen Balken (`|`)</abbr> verwenden, um Vereinigungen von Typen zu deklarieren, das ist besser und einfacher.
|
In Python 3.10 können Sie als Alternative zu den Generics `Union` und `Optional` den <abbr title='Allgemein: „oder“. In anderem Zusammenhang auch „Bitweises ODER“, aber letztere Bedeutung ist hier nicht relevant'>vertikalen Balken (`|`)</abbr> verwenden, um Vereinigungen von Typen zu deklarieren, das ist besser und einfacher.
|
||||||
|
|
||||||
////
|
////
|
||||||
|
|
||||||
|
|
@ -349,7 +409,7 @@ Sie können die eingebauten Typen als Generics verwenden (mit eckigen Klammern u
|
||||||
* `set`
|
* `set`
|
||||||
* `dict`
|
* `dict`
|
||||||
|
|
||||||
Und Generics aus dem `typing`-Modul:
|
Verwenden Sie für den Rest, wie unter Python 3.8, das `typing`-Modul:
|
||||||
|
|
||||||
* `Union`
|
* `Union`
|
||||||
* `Optional`
|
* `Optional`
|
||||||
|
|
@ -357,17 +417,29 @@ Und Generics aus dem `typing`-Modul:
|
||||||
|
|
||||||
////
|
////
|
||||||
|
|
||||||
|
//// tab | Python 3.8+
|
||||||
|
|
||||||
|
* `List`
|
||||||
|
* `Tuple`
|
||||||
|
* `Set`
|
||||||
|
* `Dict`
|
||||||
|
* `Union`
|
||||||
|
* `Optional`
|
||||||
|
* ... und andere.
|
||||||
|
|
||||||
|
////
|
||||||
|
|
||||||
### Klassen als Typen { #classes-as-types }
|
### Klassen als Typen { #classes-as-types }
|
||||||
|
|
||||||
Sie können auch eine Klasse als Typ einer Variablen deklarieren.
|
Sie können auch eine Klasse als Typ einer Variablen deklarieren.
|
||||||
|
|
||||||
Nehmen wir an, Sie haben eine Klasse `Person`, mit einem Namen:
|
Nehmen wir an, Sie haben eine Klasse `Person`, mit einem Namen:
|
||||||
|
|
||||||
{* ../../docs_src/python_types/tutorial010_py39.py hl[1:3] *}
|
{* ../../docs_src/python_types/tutorial010.py hl[1:3] *}
|
||||||
|
|
||||||
Dann können Sie eine Variable vom Typ `Person` deklarieren:
|
Dann können Sie eine Variable vom Typ `Person` deklarieren:
|
||||||
|
|
||||||
{* ../../docs_src/python_types/tutorial010_py39.py hl[6] *}
|
{* ../../docs_src/python_types/tutorial010.py hl[6] *}
|
||||||
|
|
||||||
Und wiederum bekommen Sie die volle Editor-Unterstützung:
|
Und wiederum bekommen Sie die volle Editor-Unterstützung:
|
||||||
|
|
||||||
|
|
@ -391,7 +463,29 @@ 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 *}
|
//// tab | Python 3.10+
|
||||||
|
|
||||||
|
```Python
|
||||||
|
{!> ../../docs_src/python_types/tutorial011_py310.py!}
|
||||||
|
```
|
||||||
|
|
||||||
|
////
|
||||||
|
|
||||||
|
//// tab | Python 3.9+
|
||||||
|
|
||||||
|
```Python
|
||||||
|
{!> ../../docs_src/python_types/tutorial011_py39.py!}
|
||||||
|
```
|
||||||
|
|
||||||
|
////
|
||||||
|
|
||||||
|
//// tab | Python 3.8+
|
||||||
|
|
||||||
|
```Python
|
||||||
|
{!> ../../docs_src/python_types/tutorial011.py!}
|
||||||
|
```
|
||||||
|
|
||||||
|
////
|
||||||
|
|
||||||
/// info | Info
|
/// info | Info
|
||||||
|
|
||||||
|
|
@ -413,9 +507,27 @@ Pydantic verhält sich speziell, wenn Sie `Optional` oder `Union[Something, None
|
||||||
|
|
||||||
Python bietet auch die Möglichkeit, **zusätzliche <abbr title="Daten über die Daten, in diesem Fall Informationen über den Typ, z. B. eine Beschreibung.">Metadaten</abbr>** in Typhinweisen unterzubringen, mittels `Annotated`.
|
Python bietet auch die Möglichkeit, **zusätzliche <abbr title="Daten über die Daten, in diesem Fall Informationen über den Typ, z. B. eine Beschreibung.">Metadaten</abbr>** in Typhinweisen unterzubringen, mittels `Annotated`.
|
||||||
|
|
||||||
Seit Python 3.9 ist `Annotated` ein Teil der Standardbibliothek, Sie können es von `typing` importieren.
|
//// tab | Python 3.9+
|
||||||
|
|
||||||
{* ../../docs_src/python_types/tutorial013_py39.py hl[1,4] *}
|
In Python 3.9 ist `Annotated` ein Teil der Standardbibliothek, Sie können es von `typing` importieren.
|
||||||
|
|
||||||
|
```Python hl_lines="1 4"
|
||||||
|
{!> ../../docs_src/python_types/tutorial013_py39.py!}
|
||||||
|
```
|
||||||
|
|
||||||
|
////
|
||||||
|
|
||||||
|
//// tab | Python 3.8+
|
||||||
|
|
||||||
|
In Versionen niedriger als Python 3.9 importieren Sie `Annotated` von `typing_extensions`.
|
||||||
|
|
||||||
|
Es wird bereits mit **FastAPI** installiert sein.
|
||||||
|
|
||||||
|
```Python hl_lines="1 4"
|
||||||
|
{!> ../../docs_src/python_types/tutorial013.py!}
|
||||||
|
```
|
||||||
|
|
||||||
|
////
|
||||||
|
|
||||||
Python selbst macht nichts mit `Annotated`. Für Editoren und andere Tools ist der Typ immer noch `str`.
|
Python selbst macht nichts mit `Annotated`. Für Editoren und andere Tools ist der Typ immer noch `str`.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,3 @@
|
||||||
# Ressourcen { #resources }
|
# Ressourcen { #resources }
|
||||||
|
|
||||||
Zusätzliche Ressourcen, externe Links und mehr. ✈️
|
Zusätzliche Ressourcen, externe Links, Artikel und mehr. ✈️
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ Hierzu zählen beispielsweise:
|
||||||
|
|
||||||
Importieren Sie zunächst `BackgroundTasks` und definieren Sie einen Parameter in Ihrer *Pfadoperation-Funktion* mit der Typdeklaration `BackgroundTasks`:
|
Importieren Sie zunächst `BackgroundTasks` und definieren Sie einen Parameter in Ihrer *Pfadoperation-Funktion* mit der Typdeklaration `BackgroundTasks`:
|
||||||
|
|
||||||
{* ../../docs_src/background_tasks/tutorial001_py39.py hl[1,13] *}
|
{* ../../docs_src/background_tasks/tutorial001.py hl[1,13] *}
|
||||||
|
|
||||||
**FastAPI** erstellt für Sie das Objekt vom Typ `BackgroundTasks` und übergibt es als diesen Parameter.
|
**FastAPI** erstellt für Sie das Objekt vom Typ `BackgroundTasks` und übergibt es als diesen Parameter.
|
||||||
|
|
||||||
|
|
@ -31,13 +31,13 @@ In diesem Fall schreibt die Taskfunktion in eine Datei (den Versand einer E-Mail
|
||||||
|
|
||||||
Und da der Schreibvorgang nicht `async` und `await` verwendet, definieren wir die Funktion mit normalem `def`:
|
Und da der Schreibvorgang nicht `async` und `await` verwendet, definieren wir die Funktion mit normalem `def`:
|
||||||
|
|
||||||
{* ../../docs_src/background_tasks/tutorial001_py39.py hl[6:9] *}
|
{* ../../docs_src/background_tasks/tutorial001.py hl[6:9] *}
|
||||||
|
|
||||||
## Den Hintergrundtask hinzufügen { #add-the-background-task }
|
## Den Hintergrundtask hinzufügen { #add-the-background-task }
|
||||||
|
|
||||||
Übergeben Sie innerhalb Ihrer *Pfadoperation-Funktion* Ihre Taskfunktion mit der Methode `.add_task()` an das *Hintergrundtasks*-Objekt:
|
Übergeben Sie innerhalb Ihrer *Pfadoperation-Funktion* Ihre Taskfunktion mit der Methode `.add_task()` an das *Hintergrundtasks*-Objekt:
|
||||||
|
|
||||||
{* ../../docs_src/background_tasks/tutorial001_py39.py hl[14] *}
|
{* ../../docs_src/background_tasks/tutorial001.py hl[14] *}
|
||||||
|
|
||||||
`.add_task()` erhält als Argumente:
|
`.add_task()` erhält als Argumente:
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -85,7 +85,9 @@ Sie können die *Pfadoperationen* für dieses Modul mit `APIRouter` erstellen.
|
||||||
|
|
||||||
Sie importieren ihn und erstellen eine „Instanz“ auf die gleiche Weise wie mit der Klasse `FastAPI`:
|
Sie importieren ihn und erstellen eine „Instanz“ auf die gleiche Weise wie mit der Klasse `FastAPI`:
|
||||||
|
|
||||||
{* ../../docs_src/bigger_applications/app_an_py39/routers/users.py hl[1,3] title["app/routers/users.py"] *}
|
```Python hl_lines="1 3" title="app/routers/users.py"
|
||||||
|
{!../../docs_src/bigger_applications/app/routers/users.py!}
|
||||||
|
```
|
||||||
|
|
||||||
### *Pfadoperationen* mit `APIRouter` { #path-operations-with-apirouter }
|
### *Pfadoperationen* mit `APIRouter` { #path-operations-with-apirouter }
|
||||||
|
|
||||||
|
|
@ -93,7 +95,9 @@ Und dann verwenden Sie ihn, um Ihre *Pfadoperationen* zu deklarieren.
|
||||||
|
|
||||||
Verwenden Sie ihn auf die gleiche Weise wie die Klasse `FastAPI`:
|
Verwenden Sie ihn auf die gleiche Weise wie die Klasse `FastAPI`:
|
||||||
|
|
||||||
{* ../../docs_src/bigger_applications/app_an_py39/routers/users.py hl[6,11,16] title["app/routers/users.py"] *}
|
```Python hl_lines="6 11 16" title="app/routers/users.py"
|
||||||
|
{!../../docs_src/bigger_applications/app/routers/users.py!}
|
||||||
|
```
|
||||||
|
|
||||||
Sie können sich `APIRouter` als eine „Mini-`FastAPI`“-Klasse vorstellen.
|
Sie können sich `APIRouter` als eine „Mini-`FastAPI`“-Klasse vorstellen.
|
||||||
|
|
||||||
|
|
@ -117,7 +121,35 @@ Also fügen wir sie in ihr eigenes `dependencies`-Modul (`app/dependencies.py`)
|
||||||
|
|
||||||
Wir werden nun eine einfache Abhängigkeit verwenden, um einen benutzerdefinierten `X-Token`-Header zu lesen:
|
Wir werden nun eine einfache Abhängigkeit verwenden, um einen benutzerdefinierten `X-Token`-Header zu lesen:
|
||||||
|
|
||||||
{* ../../docs_src/bigger_applications/app_an_py39/dependencies.py hl[3,6:8] title["app/dependencies.py"] *}
|
//// tab | Python 3.9+
|
||||||
|
|
||||||
|
```Python hl_lines="3 6-8" title="app/dependencies.py"
|
||||||
|
{!> ../../docs_src/bigger_applications/app_an_py39/dependencies.py!}
|
||||||
|
```
|
||||||
|
|
||||||
|
////
|
||||||
|
|
||||||
|
//// tab | Python 3.8+
|
||||||
|
|
||||||
|
```Python hl_lines="1 5-7" title="app/dependencies.py"
|
||||||
|
{!> ../../docs_src/bigger_applications/app_an/dependencies.py!}
|
||||||
|
```
|
||||||
|
|
||||||
|
////
|
||||||
|
|
||||||
|
//// tab | Python 3.8+ nicht annotiert
|
||||||
|
|
||||||
|
/// tip | Tipp
|
||||||
|
|
||||||
|
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||||
|
|
||||||
|
///
|
||||||
|
|
||||||
|
```Python hl_lines="1 4-6" title="app/dependencies.py"
|
||||||
|
{!> ../../docs_src/bigger_applications/app/dependencies.py!}
|
||||||
|
```
|
||||||
|
|
||||||
|
////
|
||||||
|
|
||||||
/// tip | Tipp
|
/// tip | Tipp
|
||||||
|
|
||||||
|
|
@ -149,7 +181,9 @@ Wir wissen, dass alle *Pfadoperationen* in diesem Modul folgendes haben:
|
||||||
|
|
||||||
Anstatt also alles zu jeder *Pfadoperation* hinzuzufügen, können wir es dem `APIRouter` hinzufügen.
|
Anstatt also alles zu jeder *Pfadoperation* hinzuzufügen, können wir es dem `APIRouter` hinzufügen.
|
||||||
|
|
||||||
{* ../../docs_src/bigger_applications/app_an_py39/routers/items.py hl[5:10,16,21] title["app/routers/items.py"] *}
|
```Python hl_lines="5-10 16 21" title="app/routers/items.py"
|
||||||
|
{!../../docs_src/bigger_applications/app/routers/items.py!}
|
||||||
|
```
|
||||||
|
|
||||||
Da der Pfad jeder *Pfadoperation* mit `/` beginnen muss, wie in:
|
Da der Pfad jeder *Pfadoperation* mit `/` beginnen muss, wie in:
|
||||||
|
|
||||||
|
|
@ -208,7 +242,9 @@ Und wir müssen die Abhängigkeitsfunktion aus dem Modul `app.dependencies` impo
|
||||||
|
|
||||||
Daher verwenden wir einen relativen Import mit `..` für die Abhängigkeiten:
|
Daher verwenden wir einen relativen Import mit `..` für die Abhängigkeiten:
|
||||||
|
|
||||||
{* ../../docs_src/bigger_applications/app_an_py39/routers/items.py hl[3] title["app/routers/items.py"] *}
|
```Python hl_lines="3" title="app/routers/items.py"
|
||||||
|
{!../../docs_src/bigger_applications/app/routers/items.py!}
|
||||||
|
```
|
||||||
|
|
||||||
#### Wie relative Importe funktionieren { #how-relative-imports-work }
|
#### Wie relative Importe funktionieren { #how-relative-imports-work }
|
||||||
|
|
||||||
|
|
@ -279,7 +315,9 @@ Wir fügen weder das Präfix `/items` noch `tags=["items"]` zu jeder *Pfadoperat
|
||||||
|
|
||||||
Aber wir können immer noch _mehr_ `tags` hinzufügen, die auf eine bestimmte *Pfadoperation* angewendet werden, sowie einige zusätzliche `responses`, die speziell für diese *Pfadoperation* gelten:
|
Aber wir können immer noch _mehr_ `tags` hinzufügen, die auf eine bestimmte *Pfadoperation* angewendet werden, sowie einige zusätzliche `responses`, die speziell für diese *Pfadoperation* gelten:
|
||||||
|
|
||||||
{* ../../docs_src/bigger_applications/app_an_py39/routers/items.py hl[30:31] title["app/routers/items.py"] *}
|
```Python hl_lines="30-31" title="app/routers/items.py"
|
||||||
|
{!../../docs_src/bigger_applications/app/routers/items.py!}
|
||||||
|
```
|
||||||
|
|
||||||
/// tip | Tipp
|
/// tip | Tipp
|
||||||
|
|
||||||
|
|
@ -305,13 +343,17 @@ Sie importieren und erstellen wie gewohnt eine `FastAPI`-Klasse.
|
||||||
|
|
||||||
Und wir können sogar [globale Abhängigkeiten](dependencies/global-dependencies.md){.internal-link target=_blank} deklarieren, die mit den Abhängigkeiten für jeden `APIRouter` kombiniert werden:
|
Und wir können sogar [globale Abhängigkeiten](dependencies/global-dependencies.md){.internal-link target=_blank} deklarieren, die mit den Abhängigkeiten für jeden `APIRouter` kombiniert werden:
|
||||||
|
|
||||||
{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[1,3,7] title["app/main.py"] *}
|
```Python hl_lines="1 3 7" title="app/main.py"
|
||||||
|
{!../../docs_src/bigger_applications/app/main.py!}
|
||||||
|
```
|
||||||
|
|
||||||
### Den `APIRouter` importieren { #import-the-apirouter }
|
### Den `APIRouter` importieren { #import-the-apirouter }
|
||||||
|
|
||||||
Jetzt importieren wir die anderen Submodule, die `APIRouter` haben:
|
Jetzt importieren wir die anderen Submodule, die `APIRouter` haben:
|
||||||
|
|
||||||
{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[4:5] title["app/main.py"] *}
|
```Python hl_lines="4-5" title="app/main.py"
|
||||||
|
{!../../docs_src/bigger_applications/app/main.py!}
|
||||||
|
```
|
||||||
|
|
||||||
Da es sich bei den Dateien `app/routers/users.py` und `app/routers/items.py` um Submodule handelt, die Teil desselben Python-Packages `app` sind, können wir einen einzelnen Punkt `.` verwenden, um sie mit „relativen Imports“ zu importieren.
|
Da es sich bei den Dateien `app/routers/users.py` und `app/routers/items.py` um Submodule handelt, die Teil desselben Python-Packages `app` sind, können wir einen einzelnen Punkt `.` verwenden, um sie mit „relativen Imports“ zu importieren.
|
||||||
|
|
||||||
|
|
@ -374,13 +416,17 @@ würde der `router` von `users` den von `items` überschreiben und wir könnten
|
||||||
|
|
||||||
Um also beide in derselben Datei verwenden zu können, importieren wir die Submodule direkt:
|
Um also beide in derselben Datei verwenden zu können, importieren wir die Submodule direkt:
|
||||||
|
|
||||||
{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[5] title["app/main.py"] *}
|
```Python hl_lines="5" title="app/main.py"
|
||||||
|
{!../../docs_src/bigger_applications/app/main.py!}
|
||||||
|
```
|
||||||
|
|
||||||
### Die `APIRouter` für `users` und `items` inkludieren { #include-the-apirouters-for-users-and-items }
|
### Die `APIRouter` für `users` und `items` inkludieren { #include-the-apirouters-for-users-and-items }
|
||||||
|
|
||||||
Inkludieren wir nun die `router` aus diesen Submodulen `users` und `items`:
|
Inkludieren wir nun die `router` aus diesen Submodulen `users` und `items`:
|
||||||
|
|
||||||
{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[10:11] title["app/main.py"] *}
|
```Python hl_lines="10-11" title="app/main.py"
|
||||||
|
{!../../docs_src/bigger_applications/app/main.py!}
|
||||||
|
```
|
||||||
|
|
||||||
/// info | Info
|
/// info | Info
|
||||||
|
|
||||||
|
|
@ -420,13 +466,17 @@ Sie enthält einen `APIRouter` mit einigen administrativen *Pfadoperationen*, di
|
||||||
|
|
||||||
In diesem Beispiel wird es ganz einfach sein. Nehmen wir jedoch an, dass wir, da sie mit anderen Projekten in der Organisation geteilt wird, sie nicht ändern und kein `prefix`, `dependencies`, `tags`, usw. direkt zum `APIRouter` hinzufügen können:
|
In diesem Beispiel wird es ganz einfach sein. Nehmen wir jedoch an, dass wir, da sie mit anderen Projekten in der Organisation geteilt wird, sie nicht ändern und kein `prefix`, `dependencies`, `tags`, usw. direkt zum `APIRouter` hinzufügen können:
|
||||||
|
|
||||||
{* ../../docs_src/bigger_applications/app_an_py39/internal/admin.py hl[3] title["app/internal/admin.py"] *}
|
```Python hl_lines="3" title="app/internal/admin.py"
|
||||||
|
{!../../docs_src/bigger_applications/app/internal/admin.py!}
|
||||||
|
```
|
||||||
|
|
||||||
Aber wir möchten immer noch ein benutzerdefiniertes `prefix` festlegen, wenn wir den `APIRouter` einbinden, sodass alle seine *Pfadoperationen* mit `/admin` beginnen, wir möchten es mit den `dependencies` sichern, die wir bereits für dieses Projekt haben, und wir möchten `tags` und `responses` hinzufügen.
|
Aber wir möchten immer noch ein benutzerdefiniertes `prefix` festlegen, wenn wir den `APIRouter` einbinden, sodass alle seine *Pfadoperationen* mit `/admin` beginnen, wir möchten es mit den `dependencies` sichern, die wir bereits für dieses Projekt haben, und wir möchten `tags` und `responses` hinzufügen.
|
||||||
|
|
||||||
Wir können das alles deklarieren, ohne den ursprünglichen `APIRouter` ändern zu müssen, indem wir diese Parameter an `app.include_router()` übergeben:
|
Wir können das alles deklarieren, ohne den ursprünglichen `APIRouter` ändern zu müssen, indem wir diese Parameter an `app.include_router()` übergeben:
|
||||||
|
|
||||||
{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[14:17] title["app/main.py"] *}
|
```Python hl_lines="14-17" title="app/main.py"
|
||||||
|
{!../../docs_src/bigger_applications/app/main.py!}
|
||||||
|
```
|
||||||
|
|
||||||
Auf diese Weise bleibt der ursprüngliche `APIRouter` unverändert, sodass wir dieselbe `app/internal/admin.py`-Datei weiterhin mit anderen Projekten in der Organisation teilen können.
|
Auf diese Weise bleibt der ursprüngliche `APIRouter` unverändert, sodass wir dieselbe `app/internal/admin.py`-Datei weiterhin mit anderen Projekten in der Organisation teilen können.
|
||||||
|
|
||||||
|
|
@ -447,7 +497,9 @@ Wir können *Pfadoperationen* auch direkt zur `FastAPI`-App hinzufügen.
|
||||||
|
|
||||||
Hier machen wir es ... nur um zu zeigen, dass wir es können 🤷:
|
Hier machen wir es ... nur um zu zeigen, dass wir es können 🤷:
|
||||||
|
|
||||||
{* ../../docs_src/bigger_applications/app_an_py39/main.py hl[21:23] title["app/main.py"] *}
|
```Python hl_lines="21-23" title="app/main.py"
|
||||||
|
{!../../docs_src/bigger_applications/app/main.py!}
|
||||||
|
```
|
||||||
|
|
||||||
und es wird korrekt funktionieren, zusammen mit allen anderen *Pfadoperationen*, die mit `app.include_router()` hinzugefügt wurden.
|
und es wird korrekt funktionieren, zusammen mit allen anderen *Pfadoperationen*, die mit `app.include_router()` hinzugefügt wurden.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,14 +14,35 @@ Das bewirkt, dass `tags` eine Liste ist, wenngleich es nichts über den Typ der
|
||||||
|
|
||||||
Aber Python erlaubt es, Listen mit inneren Typen, auch „Typ-Parameter“ genannt, zu deklarieren.
|
Aber Python erlaubt es, Listen mit inneren Typen, auch „Typ-Parameter“ genannt, zu deklarieren.
|
||||||
|
|
||||||
|
### `List` von `typing` importieren { #import-typings-list }
|
||||||
|
|
||||||
|
In Python 3.9 oder darüber können Sie einfach `list` verwenden, um diese Typannotationen zu deklarieren, wie wir unten sehen werden. 💡
|
||||||
|
|
||||||
|
In Python-Versionen vor 3.9 (3.6 und darüber), müssen Sie zuerst `List` von Pythons Standardmodul `typing` importieren.
|
||||||
|
|
||||||
|
{* ../../docs_src/body_nested_models/tutorial002.py hl[1] *}
|
||||||
|
|
||||||
### Eine `list` mit einem Typ-Parameter deklarieren { #declare-a-list-with-a-type-parameter }
|
### 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 wie `list`, `dict`, `tuple` mit inneren Typ-Parametern (inneren Typen) zu deklarieren:
|
||||||
|
|
||||||
|
* Wenn Sie eine Python-Version kleiner als 3.9 verwenden, importieren Sie das Äquivalent zum entsprechenden Typ vom `typing`-Modul
|
||||||
|
* Überreichen Sie den/die inneren Typ(en) von eckigen Klammern umschlossen, `[` und `]`, als „Typ-Parameter“
|
||||||
|
|
||||||
|
In Python 3.9 wäre das:
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
my_list: list[str]
|
my_list: list[str]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Und in Python-Versionen vor 3.9:
|
||||||
|
|
||||||
|
```Python
|
||||||
|
from typing import List
|
||||||
|
|
||||||
|
my_list: List[str]
|
||||||
|
```
|
||||||
|
|
||||||
Das ist alles Standard-Python-Syntax für Typdeklarationen.
|
Das ist alles Standard-Python-Syntax für Typdeklarationen.
|
||||||
|
|
||||||
Verwenden Sie dieselbe Standardsyntax für Modellattribute mit inneren Typen.
|
Verwenden Sie dieselbe Standardsyntax für Modellattribute mit inneren Typen.
|
||||||
|
|
@ -157,6 +178,12 @@ Beachten Sie, wie `Offer` eine Liste von `Item`s hat, die ihrerseits eine option
|
||||||
|
|
||||||
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 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:
|
||||||
|
|
||||||
|
```Python
|
||||||
|
images: List[Image]
|
||||||
|
```
|
||||||
|
|
||||||
|
oder in Python 3.9 und darüber:
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
images: list[Image]
|
images: list[Image]
|
||||||
```
|
```
|
||||||
|
|
|
||||||
|
|
@ -162,7 +162,7 @@ Die Funktionsparameter werden wie folgt erkannt:
|
||||||
|
|
||||||
FastAPI weiß, dass der Wert von `q` nicht erforderlich ist, aufgrund des definierten Defaultwertes `= None`.
|
FastAPI weiß, dass der Wert von `q` nicht erforderlich ist, aufgrund des definierten Defaultwertes `= None`.
|
||||||
|
|
||||||
Das `str | None` (Python 3.10+) oder `Union` in `Union[str, None]` (Python 3.9+) wird von FastAPI nicht verwendet, um zu bestimmen, dass der Wert nicht erforderlich ist. FastAPI weiß, dass er nicht erforderlich ist, weil er einen Defaultwert von `= None` hat.
|
Das `str | None` (Python 3.10+) oder `Union` in `Union[str, None]` (Python 3.8+) wird von FastAPI nicht verwendet, um zu bestimmen, dass der Wert nicht erforderlich ist. FastAPI weiß, dass er nicht erforderlich ist, weil er einen Defaultwert von `= None` hat.
|
||||||
|
|
||||||
Das Hinzufügen der Typannotationen ermöglicht jedoch Ihrem Editor, Ihnen eine bessere Unterstützung zu bieten und Fehler zu erkennen.
|
Das Hinzufügen der Typannotationen ermöglicht jedoch Ihrem Editor, Ihnen eine bessere Unterstützung zu bieten und Fehler zu erkennen.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,7 @@ Ihre API hat jetzt die Macht, ihre eigene <abbr title="Das ist ein Scherz, nur f
|
||||||
|
|
||||||
Sie können die Modellkonfiguration von Pydantic verwenden, um `extra` Felder zu verbieten (`forbid`):
|
Sie können die Modellkonfiguration von Pydantic verwenden, um `extra` Felder zu verbieten (`forbid`):
|
||||||
|
|
||||||
{* ../../docs_src/cookie_param_models/tutorial002_an_py310.py hl[10] *}
|
{* ../../docs_src/cookie_param_models/tutorial002_an_py39.py hl[10] *}
|
||||||
|
|
||||||
Wenn ein Client versucht, einige **zusätzliche Cookies** zu senden, erhält er eine **Error-<abbr title="Response – Antwort: Daten, die der Server zum anfragenden Client zurücksendet">Response</abbr>**.
|
Wenn ein Client versucht, einige **zusätzliche Cookies** zu senden, erhält er eine **Error-<abbr title="Response – Antwort: Daten, die der Server zum anfragenden Client zurücksendet">Response</abbr>**.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,7 @@ Sie können auch angeben, ob Ihr Backend erlaubt:
|
||||||
* Bestimmte HTTP-Methoden (`POST`, `PUT`) oder alle mit der Wildcard `"*"`.
|
* Bestimmte HTTP-Methoden (`POST`, `PUT`) oder alle mit der Wildcard `"*"`.
|
||||||
* Bestimmte HTTP-Header oder alle mit der Wildcard `"*"`.
|
* Bestimmte HTTP-Header oder alle mit der Wildcard `"*"`.
|
||||||
|
|
||||||
{* ../../docs_src/cors/tutorial001_py39.py hl[2,6:11,13:19] *}
|
{* ../../docs_src/cors/tutorial001.py hl[2,6:11,13:19] *}
|
||||||
|
|
||||||
Die von der `CORSMiddleware`-Implementierung verwendeten Defaultparameter sind standardmäßig restriktiv, daher müssen Sie bestimmte Origins, Methoden oder Header ausdrücklich aktivieren, damit Browser sie in einem Cross-Domain-Kontext verwenden dürfen.
|
Die von der `CORSMiddleware`-Implementierung verwendeten Defaultparameter sind standardmäßig restriktiv, daher müssen Sie bestimmte Origins, Methoden oder Header ausdrücklich aktivieren, damit Browser sie in einem Cross-Domain-Kontext verwenden dürfen.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ Sie können den Debugger in Ihrem Editor verbinden, zum Beispiel mit Visual Stud
|
||||||
|
|
||||||
Importieren und führen Sie `uvicorn` direkt in Ihrer FastAPI-Anwendung aus:
|
Importieren und führen Sie `uvicorn` direkt in Ihrer FastAPI-Anwendung aus:
|
||||||
|
|
||||||
{* ../../docs_src/debugging/tutorial001_py39.py hl[1,15] *}
|
{* ../../docs_src/debugging/tutorial001.py hl[1,15] *}
|
||||||
|
|
||||||
### Über `__name__ == "__main__"` { #about-name-main }
|
### Über `__name__ == "__main__"` { #about-name-main }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -101,7 +101,7 @@ Jetzt können Sie Ihre Abhängigkeit mithilfe dieser Klasse deklarieren.
|
||||||
|
|
||||||
Beachten Sie, wie wir `CommonQueryParams` im obigen Code zweimal schreiben:
|
Beachten Sie, wie wir `CommonQueryParams` im obigen Code zweimal schreiben:
|
||||||
|
|
||||||
//// tab | Python 3.9+
|
//// tab | Python 3.8+
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)]
|
commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)]
|
||||||
|
|
@ -109,7 +109,7 @@ commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)]
|
||||||
|
|
||||||
////
|
////
|
||||||
|
|
||||||
//// tab | Python 3.9+ nicht annotiert
|
//// tab | Python 3.8+ nicht annotiert
|
||||||
|
|
||||||
/// tip | Tipp
|
/// tip | Tipp
|
||||||
|
|
||||||
|
|
@ -137,7 +137,7 @@ Aus diesem extrahiert FastAPI die deklarierten Parameter, und dieses ist es, was
|
||||||
|
|
||||||
In diesem Fall hat das erste `CommonQueryParams` in:
|
In diesem Fall hat das erste `CommonQueryParams` in:
|
||||||
|
|
||||||
//// tab | Python 3.9+
|
//// tab | Python 3.8+
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
commons: Annotated[CommonQueryParams, ...
|
commons: Annotated[CommonQueryParams, ...
|
||||||
|
|
@ -145,7 +145,7 @@ commons: Annotated[CommonQueryParams, ...
|
||||||
|
|
||||||
////
|
////
|
||||||
|
|
||||||
//// tab | Python 3.9+ nicht annotiert
|
//// tab | Python 3.8+ nicht annotiert
|
||||||
|
|
||||||
/// tip | Tipp
|
/// tip | Tipp
|
||||||
|
|
||||||
|
|
@ -163,7 +163,7 @@ commons: CommonQueryParams ...
|
||||||
|
|
||||||
Sie könnten tatsächlich einfach schreiben:
|
Sie könnten tatsächlich einfach schreiben:
|
||||||
|
|
||||||
//// tab | Python 3.9+
|
//// tab | Python 3.8+
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
commons: Annotated[Any, Depends(CommonQueryParams)]
|
commons: Annotated[Any, Depends(CommonQueryParams)]
|
||||||
|
|
@ -171,7 +171,7 @@ commons: Annotated[Any, Depends(CommonQueryParams)]
|
||||||
|
|
||||||
////
|
////
|
||||||
|
|
||||||
//// tab | Python 3.9+ nicht annotiert
|
//// tab | Python 3.8+ nicht annotiert
|
||||||
|
|
||||||
/// tip | Tipp
|
/// tip | Tipp
|
||||||
|
|
||||||
|
|
@ -197,7 +197,7 @@ Es wird jedoch empfohlen, den Typ zu deklarieren, da Ihr Editor so weiß, was al
|
||||||
|
|
||||||
Aber Sie sehen, dass wir hier etwas Codeduplizierung haben, indem wir `CommonQueryParams` zweimal schreiben:
|
Aber Sie sehen, dass wir hier etwas Codeduplizierung haben, indem wir `CommonQueryParams` zweimal schreiben:
|
||||||
|
|
||||||
//// tab | Python 3.9+
|
//// tab | Python 3.8+
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)]
|
commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)]
|
||||||
|
|
@ -205,7 +205,7 @@ commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)]
|
||||||
|
|
||||||
////
|
////
|
||||||
|
|
||||||
//// tab | Python 3.9+ nicht annotiert
|
//// tab | Python 3.8+ nicht annotiert
|
||||||
|
|
||||||
/// tip | Tipp
|
/// tip | Tipp
|
||||||
|
|
||||||
|
|
@ -225,7 +225,7 @@ In diesem speziellen Fall können Sie Folgendes tun:
|
||||||
|
|
||||||
Anstatt zu schreiben:
|
Anstatt zu schreiben:
|
||||||
|
|
||||||
//// tab | Python 3.9+
|
//// tab | Python 3.8+
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)]
|
commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)]
|
||||||
|
|
@ -233,7 +233,7 @@ commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)]
|
||||||
|
|
||||||
////
|
////
|
||||||
|
|
||||||
//// tab | Python 3.9+ nicht annotiert
|
//// tab | Python 3.8+ nicht annotiert
|
||||||
|
|
||||||
/// tip | Tipp
|
/// tip | Tipp
|
||||||
|
|
||||||
|
|
@ -249,7 +249,7 @@ commons: CommonQueryParams = Depends(CommonQueryParams)
|
||||||
|
|
||||||
... schreiben Sie:
|
... schreiben Sie:
|
||||||
|
|
||||||
//// tab | Python 3.9+
|
//// tab | Python 3.8+
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
commons: Annotated[CommonQueryParams, Depends()]
|
commons: Annotated[CommonQueryParams, Depends()]
|
||||||
|
|
@ -257,7 +257,7 @@ commons: Annotated[CommonQueryParams, Depends()]
|
||||||
|
|
||||||
////
|
////
|
||||||
|
|
||||||
//// tab | Python 3.9+ nicht annotiert
|
//// tab | Python 3.8 nicht annotiert
|
||||||
|
|
||||||
/// tip | Tipp
|
/// tip | Tipp
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -29,15 +29,15 @@ Sie könnten damit beispielsweise eine Datenbanksession erstellen und diese nach
|
||||||
|
|
||||||
Nur der Code vor und einschließlich der `yield`-Anweisung wird ausgeführt, bevor eine <abbr title="Response – Antwort: Daten, die der Server zum anfragenden Client zurücksendet">Response</abbr> erzeugt wird:
|
Nur der Code vor und einschließlich der `yield`-Anweisung wird ausgeführt, bevor eine <abbr title="Response – Antwort: Daten, die der Server zum anfragenden Client zurücksendet">Response</abbr> erzeugt wird:
|
||||||
|
|
||||||
{* ../../docs_src/dependencies/tutorial007_py39.py hl[2:4] *}
|
{* ../../docs_src/dependencies/tutorial007.py hl[2:4] *}
|
||||||
|
|
||||||
Der ge`yield`ete Wert ist das, was in *Pfadoperationen* und andere Abhängigkeiten eingefügt wird:
|
Der ge`yield`ete Wert ist das, was in *Pfadoperationen* und andere Abhängigkeiten eingefügt wird:
|
||||||
|
|
||||||
{* ../../docs_src/dependencies/tutorial007_py39.py hl[4] *}
|
{* ../../docs_src/dependencies/tutorial007.py hl[4] *}
|
||||||
|
|
||||||
Der auf die `yield`-Anweisung folgende Code wird nach der Response ausgeführt:
|
Der auf die `yield`-Anweisung folgende Code wird nach der Response ausgeführt:
|
||||||
|
|
||||||
{* ../../docs_src/dependencies/tutorial007_py39.py hl[5:6] *}
|
{* ../../docs_src/dependencies/tutorial007.py hl[5:6] *}
|
||||||
|
|
||||||
/// tip | Tipp
|
/// tip | Tipp
|
||||||
|
|
||||||
|
|
@ -57,7 +57,7 @@ Sie können also mit `except SomeException` diese bestimmte Exception innerhalb
|
||||||
|
|
||||||
Auf die gleiche Weise können Sie `finally` verwenden, um sicherzustellen, dass die Exit-Schritte ausgeführt werden, unabhängig davon, ob eine Exception geworfen wurde oder nicht.
|
Auf die gleiche Weise können Sie `finally` verwenden, um sicherzustellen, dass die Exit-Schritte ausgeführt werden, unabhängig davon, ob eine Exception geworfen wurde oder nicht.
|
||||||
|
|
||||||
{* ../../docs_src/dependencies/tutorial007_py39.py hl[3,5] *}
|
{* ../../docs_src/dependencies/tutorial007.py hl[3,5] *}
|
||||||
|
|
||||||
## Unterabhängigkeiten mit `yield` { #sub-dependencies-with-yield }
|
## Unterabhängigkeiten mit `yield` { #sub-dependencies-with-yield }
|
||||||
|
|
||||||
|
|
@ -184,51 +184,6 @@ Wenn Sie in dem Code der *Pfadoperation-Funktion* irgendeine Exception auslösen
|
||||||
|
|
||||||
///
|
///
|
||||||
|
|
||||||
## Frühes Beenden und `scope` { #early-exit-and-scope }
|
|
||||||
|
|
||||||
Normalerweise wird der Exit-Code von Abhängigkeiten mit `yield` ausgeführt **nachdem die Response** an den Client gesendet wurde.
|
|
||||||
|
|
||||||
Wenn Sie aber wissen, dass Sie die Abhängigkeit nach der Rückkehr aus der *Pfadoperation-Funktion* nicht mehr benötigen, können Sie `Depends(scope="function")` verwenden, um FastAPI mitzuteilen, dass es die Abhängigkeit nach der Rückkehr aus der *Pfadoperation-Funktion* schließen soll, jedoch **bevor** die **Response gesendet wird**.
|
|
||||||
|
|
||||||
{* ../../docs_src/dependencies/tutorial008e_an_py39.py hl[12,16] *}
|
|
||||||
|
|
||||||
`Depends()` erhält einen `scope`-Parameter, der sein kann:
|
|
||||||
|
|
||||||
* `"function"`: startet die Abhängigkeit vor der *Pfadoperation-Funktion*, die den Request bearbeitet, beendet die Abhängigkeit nach dem Ende der *Pfadoperation-Funktion*, aber **bevor** die Response an den Client zurückgesendet wird. Die Abhängigkeitsfunktion wird also **um** die *Pfadoperation-**Funktion*** **herum** ausgeführt.
|
|
||||||
* `"request"`: startet die Abhängigkeit vor der *Pfadoperation-Funktion*, die den Request bearbeitet (ähnlich wie bei `"function"`), beendet sie jedoch **nachdem** die Response an den Client zurückgesendet wurde. Die Abhängigkeitsfunktion wird also **um** den **Request**- und Response-Zyklus **herum** ausgeführt.
|
|
||||||
|
|
||||||
Wenn nicht angegeben und die Abhängigkeit `yield` hat, hat sie standardmäßig einen `scope` von `"request"`.
|
|
||||||
|
|
||||||
### `scope` für Unterabhängigkeiten { #scope-for-sub-dependencies }
|
|
||||||
|
|
||||||
Wenn Sie eine Abhängigkeit mit `scope="request"` (dem Default) deklarieren, muss jede Unterabhängigkeit ebenfalls einen `scope` von `"request"` haben.
|
|
||||||
|
|
||||||
Eine Abhängigkeit mit `scope` von `"function"` kann jedoch Abhängigkeiten mit `scope` von `"function"` und `scope` von `"request"` haben.
|
|
||||||
|
|
||||||
Das liegt daran, dass jede Abhängigkeit in der Lage sein muss, ihren Exit-Code vor den Unterabhängigkeiten auszuführen, da sie diese während ihres Exit-Codes möglicherweise noch verwenden muss.
|
|
||||||
|
|
||||||
```mermaid
|
|
||||||
sequenceDiagram
|
|
||||||
|
|
||||||
participant client as Client
|
|
||||||
participant dep_req as Abhängigkeit scope="request"
|
|
||||||
participant dep_func as Abhängigkeit scope="function"
|
|
||||||
participant operation as Pfadoperation
|
|
||||||
|
|
||||||
client ->> dep_req: Startet den Request
|
|
||||||
Note over dep_req: Führt den Code bis zum yield aus
|
|
||||||
dep_req ->> dep_func: Reicht Abhängigkeit weiter
|
|
||||||
Note over dep_func: Führt den Code bis zum yield aus
|
|
||||||
dep_func ->> operation: Führt Pfadoperation mit Abhängigkeit aus
|
|
||||||
operation ->> dep_func: Kehrt aus Pfadoperation zurück
|
|
||||||
Note over dep_func: Führt Code nach yield aus
|
|
||||||
Note over dep_func: ✅ Abhängigkeit geschlossen
|
|
||||||
dep_func ->> client: Sendet Response an Client
|
|
||||||
Note over client: Response gesendet
|
|
||||||
Note over dep_req: Führt Code nach yield aus
|
|
||||||
Note over dep_req: ✅ Abhängigkeit geschlossen
|
|
||||||
```
|
|
||||||
|
|
||||||
## Abhängigkeiten mit `yield`, `HTTPException`, `except` und Hintergrundtasks { #dependencies-with-yield-httpexception-except-and-background-tasks }
|
## Abhängigkeiten mit `yield`, `HTTPException`, `except` und Hintergrundtasks { #dependencies-with-yield-httpexception-except-and-background-tasks }
|
||||||
|
|
||||||
Abhängigkeiten mit `yield` haben sich im Laufe der Zeit weiterentwickelt, um verschiedene Anwendungsfälle abzudecken und einige Probleme zu beheben.
|
Abhängigkeiten mit `yield` haben sich im Laufe der Zeit weiterentwickelt, um verschiedene Anwendungsfälle abzudecken und einige Probleme zu beheben.
|
||||||
|
|
@ -268,7 +223,7 @@ In Python können Sie Kontextmanager erstellen, indem Sie <a href="https://docs.
|
||||||
|
|
||||||
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_py39.py hl[1:9,13] *}
|
{* ../../docs_src/dependencies/tutorial010.py hl[1:9,13] *}
|
||||||
|
|
||||||
/// tip | Tipp
|
/// tip | Tipp
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ Bei einigen Anwendungstypen möchten Sie möglicherweise Abhängigkeiten zur ges
|
||||||
|
|
||||||
In diesem Fall werden sie auf alle *Pfadoperationen* in der Anwendung angewendet:
|
In diesem Fall werden sie auf alle *Pfadoperationen* in der Anwendung angewendet:
|
||||||
|
|
||||||
{* ../../docs_src/dependencies/tutorial012_an_py39.py hl[17] *}
|
{* ../../docs_src/dependencies/tutorial012_an_py39.py hl[16] *}
|
||||||
|
|
||||||
Und alle Ideen aus dem Abschnitt über das [Hinzufügen von `dependencies` zu den *Pfadoperation-Dekoratoren*](dependencies-in-path-operation-decorators.md){.internal-link target=_blank} gelten weiterhin, aber in diesem Fall für alle *Pfadoperationen* in der App.
|
Und alle Ideen aus dem Abschnitt über das [Hinzufügen von `dependencies` zu den *Pfadoperation-Dekoratoren*](dependencies-in-path-operation-decorators.md){.internal-link target=_blank} gelten weiterhin, aber in diesem Fall für alle *Pfadoperationen* in der App.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -62,7 +62,7 @@ Und es speichert den zurückgegebenen Wert in einem <abbr title="Mechanismus, de
|
||||||
|
|
||||||
In einem fortgeschrittenen Szenario, bei dem Sie wissen, dass die Abhängigkeit bei jedem Schritt (möglicherweise mehrmals) in demselben Request aufgerufen werden muss, anstatt den zwischengespeicherten Wert zu verwenden, können Sie den Parameter `use_cache=False` festlegen, wenn Sie `Depends` verwenden:
|
In einem fortgeschrittenen Szenario, bei dem Sie wissen, dass die Abhängigkeit bei jedem Schritt (möglicherweise mehrmals) in demselben Request aufgerufen werden muss, anstatt den zwischengespeicherten Wert zu verwenden, können Sie den Parameter `use_cache=False` festlegen, wenn Sie `Depends` verwenden:
|
||||||
|
|
||||||
//// tab | Python 3.9+
|
//// tab | Python 3.8+
|
||||||
|
|
||||||
```Python hl_lines="1"
|
```Python hl_lines="1"
|
||||||
async def needy_dependency(fresh_value: Annotated[str, Depends(get_value, use_cache=False)]):
|
async def needy_dependency(fresh_value: Annotated[str, Depends(get_value, use_cache=False)]):
|
||||||
|
|
@ -71,7 +71,7 @@ async def needy_dependency(fresh_value: Annotated[str, Depends(get_value, use_ca
|
||||||
|
|
||||||
////
|
////
|
||||||
|
|
||||||
//// tab | Python 3.9+ nicht annotiert
|
//// tab | Python 3.8+ nicht annotiert
|
||||||
|
|
||||||
/// tip | Tipp
|
/// tip | Tipp
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
Die einfachste FastAPI-Datei könnte wie folgt aussehen:
|
Die einfachste FastAPI-Datei könnte wie folgt aussehen:
|
||||||
|
|
||||||
{* ../../docs_src/first_steps/tutorial001_py39.py *}
|
{* ../../docs_src/first_steps/tutorial001.py *}
|
||||||
|
|
||||||
Kopieren Sie das in eine Datei `main.py`.
|
Kopieren Sie das in eine Datei `main.py`.
|
||||||
|
|
||||||
|
|
@ -143,47 +143,11 @@ Es gibt dutzende Alternativen, die alle auf OpenAPI basieren. Sie können jede d
|
||||||
|
|
||||||
Ebenfalls können Sie es verwenden, um automatisch Code für Clients zu generieren, die mit Ihrer API kommunizieren. Zum Beispiel für Frontend-, Mobile- oder IoT-Anwendungen.
|
Ebenfalls können Sie es verwenden, um automatisch Code für Clients zu generieren, die mit Ihrer API kommunizieren. Zum Beispiel für Frontend-, Mobile- oder IoT-Anwendungen.
|
||||||
|
|
||||||
### Ihre App deployen (optional) { #deploy-your-app-optional }
|
|
||||||
|
|
||||||
Sie können optional Ihre FastAPI-App in der <a href="https://fastapicloud.com" class="external-link" target="_blank">FastAPI Cloud</a> 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:
|
|
||||||
|
|
||||||
<div class="termy">
|
|
||||||
|
|
||||||
```console
|
|
||||||
$ fastapi login
|
|
||||||
|
|
||||||
You are logged in to FastAPI Cloud 🚀
|
|
||||||
```
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
Dann stellen Sie Ihre App bereit:
|
|
||||||
|
|
||||||
<div class="termy">
|
|
||||||
|
|
||||||
```console
|
|
||||||
$ fastapi deploy
|
|
||||||
|
|
||||||
Deploying to FastAPI Cloud...
|
|
||||||
|
|
||||||
✅ Deployment successful!
|
|
||||||
|
|
||||||
🐔 Ready the chicken! Your app is ready at https://myapp.fastapicloud.dev
|
|
||||||
```
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
Das war's! Jetzt können Sie Ihre App unter dieser URL aufrufen. ✨
|
|
||||||
|
|
||||||
## Zusammenfassung, Schritt für Schritt { #recap-step-by-step }
|
## Zusammenfassung, Schritt für Schritt { #recap-step-by-step }
|
||||||
|
|
||||||
### Schritt 1: `FastAPI` importieren { #step-1-import-fastapi }
|
### Schritt 1: `FastAPI` importieren { #step-1-import-fastapi }
|
||||||
|
|
||||||
{* ../../docs_src/first_steps/tutorial001_py39.py hl[1] *}
|
{* ../../docs_src/first_steps/tutorial001.py hl[1] *}
|
||||||
|
|
||||||
`FastAPI` ist eine Python-Klasse, die die gesamte Funktionalität für Ihre API bereitstellt.
|
`FastAPI` ist eine Python-Klasse, die die gesamte Funktionalität für Ihre API bereitstellt.
|
||||||
|
|
||||||
|
|
@ -197,7 +161,7 @@ Sie können alle <a href="https://www.starlette.dev/" class="external-link" targ
|
||||||
|
|
||||||
### Schritt 2: Erzeugen einer `FastAPI`-„Instanz“ { #step-2-create-a-fastapi-instance }
|
### Schritt 2: Erzeugen einer `FastAPI`-„Instanz“ { #step-2-create-a-fastapi-instance }
|
||||||
|
|
||||||
{* ../../docs_src/first_steps/tutorial001_py39.py hl[3] *}
|
{* ../../docs_src/first_steps/tutorial001.py hl[3] *}
|
||||||
|
|
||||||
In diesem Beispiel ist die Variable `app` eine „Instanz“ der Klasse `FastAPI`.
|
In diesem Beispiel ist die Variable `app` eine „Instanz“ der Klasse `FastAPI`.
|
||||||
|
|
||||||
|
|
@ -266,7 +230,7 @@ Wir werden sie auch „**Operationen**“ nennen.
|
||||||
|
|
||||||
#### Definieren eines *Pfadoperation-Dekorators* { #define-a-path-operation-decorator }
|
#### Definieren eines *Pfadoperation-Dekorators* { #define-a-path-operation-decorator }
|
||||||
|
|
||||||
{* ../../docs_src/first_steps/tutorial001_py39.py hl[6] *}
|
{* ../../docs_src/first_steps/tutorial001.py hl[6] *}
|
||||||
|
|
||||||
Das `@app.get("/")` sagt **FastAPI**, dass die Funktion direkt darunter für die Bearbeitung von <abbr title="Request – Anfrage: Daten, die der Client zum Server sendet">Requests</abbr> zuständig ist, die an:
|
Das `@app.get("/")` sagt **FastAPI**, dass die Funktion direkt darunter für die Bearbeitung von <abbr title="Request – Anfrage: Daten, die der Client zum Server sendet">Requests</abbr> zuständig ist, die an:
|
||||||
|
|
||||||
|
|
@ -320,7 +284,7 @@ Das ist unsere „**Pfadoperation-Funktion**“:
|
||||||
* **Operation**: ist `get`.
|
* **Operation**: ist `get`.
|
||||||
* **Funktion**: ist die Funktion direkt unter dem „Dekorator“ (unter `@app.get("/")`).
|
* **Funktion**: ist die Funktion direkt unter dem „Dekorator“ (unter `@app.get("/")`).
|
||||||
|
|
||||||
{* ../../docs_src/first_steps/tutorial001_py39.py hl[7] *}
|
{* ../../docs_src/first_steps/tutorial001.py hl[7] *}
|
||||||
|
|
||||||
Dies ist eine Python-Funktion.
|
Dies ist eine Python-Funktion.
|
||||||
|
|
||||||
|
|
@ -332,7 +296,7 @@ In diesem Fall handelt es sich um eine `async`-Funktion.
|
||||||
|
|
||||||
Sie könnten sie auch als normale Funktion anstelle von `async def` definieren:
|
Sie könnten sie auch als normale Funktion anstelle von `async def` definieren:
|
||||||
|
|
||||||
{* ../../docs_src/first_steps/tutorial003_py39.py hl[7] *}
|
{* ../../docs_src/first_steps/tutorial003.py hl[7] *}
|
||||||
|
|
||||||
/// note | Hinweis
|
/// note | Hinweis
|
||||||
|
|
||||||
|
|
@ -342,7 +306,7 @@ Wenn Sie den Unterschied nicht kennen, lesen Sie [Async: *„In Eile?“*](../as
|
||||||
|
|
||||||
### Schritt 5: den Inhalt zurückgeben { #step-5-return-the-content }
|
### Schritt 5: den Inhalt zurückgeben { #step-5-return-the-content }
|
||||||
|
|
||||||
{* ../../docs_src/first_steps/tutorial001_py39.py hl[8] *}
|
{* ../../docs_src/first_steps/tutorial001.py hl[8] *}
|
||||||
|
|
||||||
Sie können ein `dict`, eine `list`, einzelne Werte wie `str`, `int`, usw. zurückgeben.
|
Sie können ein `dict`, eine `list`, einzelne Werte wie `str`, `int`, usw. zurückgeben.
|
||||||
|
|
||||||
|
|
@ -350,26 +314,6 @@ Sie können auch Pydantic-Modelle zurückgeben (dazu später mehr).
|
||||||
|
|
||||||
Es gibt viele andere Objekte und Modelle, die automatisch zu JSON konvertiert werden (einschließlich ORMs, usw.). Versuchen Sie, Ihre Lieblingsobjekte zu verwenden. Es ist sehr wahrscheinlich, dass sie bereits unterstützt werden.
|
Es gibt viele andere Objekte und Modelle, die automatisch zu JSON konvertiert werden (einschließlich ORMs, usw.). Versuchen Sie, Ihre Lieblingsobjekte zu verwenden. Es ist sehr wahrscheinlich, dass sie bereits unterstützt werden.
|
||||||
|
|
||||||
### Schritt 6: Deployen { #step-6-deploy-it }
|
|
||||||
|
|
||||||
Stellen Sie Ihre App in der **<a href="https://fastapicloud.com" class="external-link" target="_blank">FastAPI Cloud</a>** mit einem Befehl bereit: `fastapi deploy`. 🎉
|
|
||||||
|
|
||||||
#### Über FastAPI Cloud { #about-fastapi-cloud }
|
|
||||||
|
|
||||||
**<a href="https://fastapicloud.com" class="external-link" target="_blank">FastAPI Cloud</a>** 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 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. ✨
|
|
||||||
|
|
||||||
#### Zu anderen Cloudanbietern deployen { #deploy-to-other-cloud-providers }
|
|
||||||
|
|
||||||
FastAPI ist Open Source und basiert auf Standards. Sie können FastAPI-Apps bei jedem Cloudanbieter Ihrer Wahl deployen.
|
|
||||||
|
|
||||||
Folgen Sie den Anleitungen Ihres Cloudanbieters, um dort FastAPI-Apps bereitzustellen. 🤓
|
|
||||||
|
|
||||||
## Zusammenfassung { #recap }
|
## Zusammenfassung { #recap }
|
||||||
|
|
||||||
* Importieren Sie `FastAPI`.
|
* Importieren Sie `FastAPI`.
|
||||||
|
|
@ -377,4 +321,3 @@ Folgen Sie den Anleitungen Ihres Cloudanbieters, um dort FastAPI-Apps bereitzust
|
||||||
* Schreiben Sie einen **Pfadoperation-Dekorator** unter Verwendung von Dekoratoren wie `@app.get("/")`.
|
* Schreiben Sie einen **Pfadoperation-Dekorator** unter Verwendung von Dekoratoren wie `@app.get("/")`.
|
||||||
* Definieren Sie eine **Pfadoperation-Funktion**, zum Beispiel `def root(): ...`.
|
* Definieren Sie eine **Pfadoperation-Funktion**, zum Beispiel `def root(): ...`.
|
||||||
* Starten Sie den Entwicklungsserver mit dem Befehl `fastapi dev`.
|
* Starten Sie den Entwicklungsserver mit dem Befehl `fastapi dev`.
|
||||||
* Optional: Ihre App mit `fastapi deploy` deployen.
|
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ Um HTTP-<abbr title="Response – Antwort: Daten, die der Server zum anfragenden
|
||||||
|
|
||||||
### `HTTPException` importieren { #import-httpexception }
|
### `HTTPException` importieren { #import-httpexception }
|
||||||
|
|
||||||
{* ../../docs_src/handling_errors/tutorial001_py39.py hl[1] *}
|
{* ../../docs_src/handling_errors/tutorial001.py hl[1] *}
|
||||||
|
|
||||||
### Eine `HTTPException` in Ihrem Code auslösen { #raise-an-httpexception-in-your-code }
|
### Eine `HTTPException` in Ihrem Code auslösen { #raise-an-httpexception-in-your-code }
|
||||||
|
|
||||||
|
|
@ -39,7 +39,7 @@ Der Vorteil des Auslösens einer Exception gegenüber dem Zurückgeben eines Wer
|
||||||
|
|
||||||
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 einen Artikel mit einer nicht existierenden ID anfordert:
|
||||||
|
|
||||||
{* ../../docs_src/handling_errors/tutorial001_py39.py hl[11] *}
|
{* ../../docs_src/handling_errors/tutorial001.py hl[11] *}
|
||||||
|
|
||||||
### Die resultierende Response { #the-resulting-response }
|
### Die resultierende Response { #the-resulting-response }
|
||||||
|
|
||||||
|
|
@ -77,7 +77,7 @@ Sie werden es wahrscheinlich nicht direkt in Ihrem Code verwenden müssen.
|
||||||
|
|
||||||
Aber falls Sie es für ein fortgeschrittenes Szenario benötigen, können Sie benutzerdefinierte Header hinzufügen:
|
Aber falls Sie es für ein fortgeschrittenes Szenario benötigen, können Sie benutzerdefinierte Header hinzufügen:
|
||||||
|
|
||||||
{* ../../docs_src/handling_errors/tutorial002_py39.py hl[14] *}
|
{* ../../docs_src/handling_errors/tutorial002.py hl[14] *}
|
||||||
|
|
||||||
## Benutzerdefinierte Exceptionhandler installieren { #install-custom-exception-handlers }
|
## Benutzerdefinierte Exceptionhandler installieren { #install-custom-exception-handlers }
|
||||||
|
|
||||||
|
|
@ -89,7 +89,7 @@ Und Sie möchten diese Exception global mit FastAPI handhaben.
|
||||||
|
|
||||||
Sie könnten einen benutzerdefinierten Exceptionhandler mit `@app.exception_handler()` hinzufügen:
|
Sie könnten einen benutzerdefinierten Exceptionhandler mit `@app.exception_handler()` hinzufügen:
|
||||||
|
|
||||||
{* ../../docs_src/handling_errors/tutorial003_py39.py hl[5:7,13:18,24] *}
|
{* ../../docs_src/handling_errors/tutorial003.py hl[5:7,13:18,24] *}
|
||||||
|
|
||||||
Hier, wenn Sie `/unicorns/yolo` anfordern, wird die *Pfadoperation* eine `UnicornException` `raise`n.
|
Hier, wenn Sie `/unicorns/yolo` anfordern, wird die *Pfadoperation* eine `UnicornException` `raise`n.
|
||||||
|
|
||||||
|
|
@ -127,7 +127,7 @@ Um diesen zu überschreiben, importieren Sie den `RequestValidationError` und ve
|
||||||
|
|
||||||
Der Exceptionhandler erhält einen `Request` und die Exception.
|
Der Exceptionhandler erhält einen `Request` und die Exception.
|
||||||
|
|
||||||
{* ../../docs_src/handling_errors/tutorial004_py39.py hl[2,14:19] *}
|
{* ../../docs_src/handling_errors/tutorial004.py hl[2,14:16] *}
|
||||||
|
|
||||||
Wenn Sie nun zu `/items/foo` gehen, erhalten Sie anstelle des standardmäßigen JSON-Fehlers mit:
|
Wenn Sie nun zu `/items/foo` gehen, erhalten Sie anstelle des standardmäßigen JSON-Fehlers mit:
|
||||||
|
|
||||||
|
|
@ -149,17 +149,36 @@ Wenn Sie nun zu `/items/foo` gehen, erhalten Sie anstelle des standardmäßigen
|
||||||
eine Textversion mit:
|
eine Textversion mit:
|
||||||
|
|
||||||
```
|
```
|
||||||
Validation errors:
|
1 validation error
|
||||||
Field: ('path', 'item_id'), Error: Input should be a valid integer, unable to parse string as an integer
|
path -> item_id
|
||||||
|
value is not a valid integer (type=type_error.integer)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### `RequestValidationError` vs. `ValidationError` { #requestvalidationerror-vs-validationerror }
|
||||||
|
|
||||||
|
/// warning | Achtung
|
||||||
|
|
||||||
|
Dies sind technische Details, die Sie überspringen können, wenn sie für Sie jetzt nicht wichtig sind.
|
||||||
|
|
||||||
|
///
|
||||||
|
|
||||||
|
`RequestValidationError` ist eine Unterklasse von Pydantics <a href="https://docs.pydantic.dev/latest/concepts/models/#error-handling" class="external-link" target="_blank">`ValidationError`</a>.
|
||||||
|
|
||||||
|
**FastAPI** verwendet diesen so, dass, wenn Sie ein Pydantic-Modell in `response_model` verwenden und Ihre Daten einen Fehler haben, Sie den Fehler in Ihrem Log sehen.
|
||||||
|
|
||||||
|
Aber der Client/Benutzer wird ihn nicht sehen. Stattdessen erhält der Client einen „Internal Server Error“ mit einem HTTP-Statuscode `500`.
|
||||||
|
|
||||||
|
Es sollte so sein, denn wenn Sie einen Pydantic `ValidationError` in Ihrer *Response* oder irgendwo anders in Ihrem Code haben (nicht im *Request* des Clients), ist es tatsächlich ein Fehler in Ihrem Code.
|
||||||
|
|
||||||
|
Und während Sie den Fehler beheben, sollten Ihre Clients/Benutzer keinen Zugriff auf interne Informationen über den Fehler haben, da das eine Sicherheitslücke aufdecken könnte.
|
||||||
|
|
||||||
### Überschreiben des `HTTPException`-Fehlerhandlers { #override-the-httpexception-error-handler }
|
### Überschreiben des `HTTPException`-Fehlerhandlers { #override-the-httpexception-error-handler }
|
||||||
|
|
||||||
Auf die gleiche Weise können Sie den `HTTPException`-Handler überschreiben.
|
Auf die gleiche Weise können Sie den `HTTPException`-Handler überschreiben.
|
||||||
|
|
||||||
Zum Beispiel könnten Sie eine Klartext-Response statt JSON für diese Fehler zurückgeben wollen:
|
Zum Beispiel könnten Sie eine Klartext-Response statt JSON für diese Fehler zurückgeben wollen:
|
||||||
|
|
||||||
{* ../../docs_src/handling_errors/tutorial004_py39.py hl[3:4,9:11,25] *}
|
{* ../../docs_src/handling_errors/tutorial004.py hl[3:4,9:11,22] *}
|
||||||
|
|
||||||
/// note | Technische Details
|
/// note | Technische Details
|
||||||
|
|
||||||
|
|
@ -169,21 +188,13 @@ Sie könnten auch `from starlette.responses import PlainTextResponse` verwenden.
|
||||||
|
|
||||||
///
|
///
|
||||||
|
|
||||||
/// warning | Achtung
|
|
||||||
|
|
||||||
Beachten Sie, dass der `RequestValidationError` Informationen über den Dateinamen und die Zeile enthält, in der der Validierungsfehler auftritt, sodass Sie ihn bei Bedarf mit den relevanten Informationen in Ihren Logs anzeigen können.
|
|
||||||
|
|
||||||
Das bedeutet aber auch, dass, wenn Sie ihn einfach in einen String umwandeln und diese Informationen direkt zurückgeben, Sie möglicherweise ein paar Informationen über Ihr System preisgeben. Daher extrahiert und zeigt der Code hier jeden Fehler getrennt.
|
|
||||||
|
|
||||||
///
|
|
||||||
|
|
||||||
### Verwenden des `RequestValidationError`-Bodys { #use-the-requestvalidationerror-body }
|
### Verwenden des `RequestValidationError`-Bodys { #use-the-requestvalidationerror-body }
|
||||||
|
|
||||||
Der `RequestValidationError` enthält den empfangenen `body` mit den ungültigen Daten.
|
Der `RequestValidationError` enthält den empfangenen `body` mit den ungültigen Daten.
|
||||||
|
|
||||||
Sie könnten diesen während der Entwicklung Ihrer Anwendung verwenden, um den Body zu loggen und zu debuggen, ihn an den Benutzer zurückzugeben usw.
|
Sie könnten diesen während der Entwicklung Ihrer Anwendung verwenden, um den Body zu loggen und zu debuggen, ihn an den Benutzer zurückzugeben usw.
|
||||||
|
|
||||||
{* ../../docs_src/handling_errors/tutorial005_py39.py hl[14] *}
|
{* ../../docs_src/handling_errors/tutorial005.py hl[14] *}
|
||||||
|
|
||||||
Versuchen Sie nun, einen ungültigen Artikel zu senden:
|
Versuchen Sie nun, einen ungültigen Artikel zu senden:
|
||||||
|
|
||||||
|
|
@ -239,6 +250,6 @@ from starlette.exceptions import HTTPException as StarletteHTTPException
|
||||||
|
|
||||||
Wenn Sie die Exception zusammen mit den gleichen Default-Exceptionhandlern von **FastAPI** verwenden möchten, können Sie die Default-Exceptionhandler aus `fastapi.exception_handlers` importieren und wiederverwenden:
|
Wenn Sie die Exception zusammen mit den gleichen Default-Exceptionhandlern von **FastAPI** verwenden möchten, können Sie die Default-Exceptionhandler aus `fastapi.exception_handlers` importieren und wiederverwenden:
|
||||||
|
|
||||||
{* ../../docs_src/handling_errors/tutorial006_py39.py hl[2:5,15,21] *}
|
{* ../../docs_src/handling_errors/tutorial006.py hl[2:5,15,21] *}
|
||||||
|
|
||||||
In diesem Beispiel geben Sie nur den Fehler mit einer sehr ausdrucksstarken Nachricht aus, aber Sie verstehen das Prinzip. Sie können die Exception verwenden und dann einfach die Default-Exceptionhandler wiederverwenden.
|
In diesem Beispiel geben Sie nur den Fehler mit einer sehr ausdrucksstarken Nachricht aus, aber Sie verstehen das Prinzip. Sie können die Exception verwenden und dann einfach die Default-Exceptionhandler wiederverwenden.
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ Sie können die folgenden Felder festlegen, die in der OpenAPI-Spezifikation und
|
||||||
|
|
||||||
Sie können diese wie folgt setzen:
|
Sie können diese wie folgt setzen:
|
||||||
|
|
||||||
{* ../../docs_src/metadata/tutorial001_py39.py hl[3:16, 19:32] *}
|
{* ../../docs_src/metadata/tutorial001.py hl[3:16, 19:32] *}
|
||||||
|
|
||||||
/// tip | Tipp
|
/// tip | Tipp
|
||||||
|
|
||||||
|
|
@ -36,7 +36,7 @@ Seit OpenAPI 3.1.0 und FastAPI 0.99.0 können Sie die `license_info` auch mit ei
|
||||||
|
|
||||||
Zum Beispiel:
|
Zum Beispiel:
|
||||||
|
|
||||||
{* ../../docs_src/metadata/tutorial001_1_py39.py hl[31] *}
|
{* ../../docs_src/metadata/tutorial001_1.py hl[31] *}
|
||||||
|
|
||||||
## Metadaten für Tags { #metadata-for-tags }
|
## Metadaten für Tags { #metadata-for-tags }
|
||||||
|
|
||||||
|
|
@ -58,7 +58,7 @@ Versuchen wir es mit einem Beispiel mit Tags für `users` und `items`.
|
||||||
|
|
||||||
Erstellen Sie Metadaten für Ihre Tags und übergeben Sie diese an den Parameter `openapi_tags`:
|
Erstellen Sie Metadaten für Ihre Tags und übergeben Sie diese an den Parameter `openapi_tags`:
|
||||||
|
|
||||||
{* ../../docs_src/metadata/tutorial004_py39.py hl[3:16,18] *}
|
{* ../../docs_src/metadata/tutorial004.py hl[3:16,18] *}
|
||||||
|
|
||||||
Beachten Sie, dass Sie Markdown innerhalb der Beschreibungen verwenden können. Zum Beispiel wird „login“ in Fettschrift (**login**) und „fancy“ in Kursivschrift (_fancy_) angezeigt.
|
Beachten Sie, dass Sie Markdown innerhalb der Beschreibungen verwenden können. Zum Beispiel wird „login“ in Fettschrift (**login**) und „fancy“ in Kursivschrift (_fancy_) angezeigt.
|
||||||
|
|
||||||
|
|
@ -72,7 +72,7 @@ Sie müssen nicht für alle von Ihnen verwendeten Tags Metadaten hinzufügen.
|
||||||
|
|
||||||
Verwenden Sie den Parameter `tags` mit Ihren *Pfadoperationen* (und `APIRouter`n), um diese verschiedenen Tags zuzuweisen:
|
Verwenden Sie den Parameter `tags` mit Ihren *Pfadoperationen* (und `APIRouter`n), um diese verschiedenen Tags zuzuweisen:
|
||||||
|
|
||||||
{* ../../docs_src/metadata/tutorial004_py39.py hl[21,26] *}
|
{* ../../docs_src/metadata/tutorial004.py hl[21,26] *}
|
||||||
|
|
||||||
/// info | Info
|
/// info | Info
|
||||||
|
|
||||||
|
|
@ -100,7 +100,7 @@ Sie können das aber mit dem Parameter `openapi_url` konfigurieren.
|
||||||
|
|
||||||
Um beispielsweise festzulegen, dass es unter `/api/v1/openapi.json` bereitgestellt wird:
|
Um beispielsweise festzulegen, dass es unter `/api/v1/openapi.json` bereitgestellt wird:
|
||||||
|
|
||||||
{* ../../docs_src/metadata/tutorial002_py39.py hl[3] *}
|
{* ../../docs_src/metadata/tutorial002.py hl[3] *}
|
||||||
|
|
||||||
Wenn Sie das OpenAPI-Schema vollständig deaktivieren möchten, können Sie `openapi_url=None` festlegen, wodurch auch die Dokumentationsbenutzeroberflächen deaktiviert werden, die es verwenden.
|
Wenn Sie das OpenAPI-Schema vollständig deaktivieren möchten, können Sie `openapi_url=None` festlegen, wodurch auch die Dokumentationsbenutzeroberflächen deaktiviert werden, die es verwenden.
|
||||||
|
|
||||||
|
|
@ -117,4 +117,4 @@ Sie können die beiden enthaltenen Dokumentationsbenutzeroberflächen konfigurie
|
||||||
|
|
||||||
Um beispielsweise Swagger UI so einzustellen, dass sie unter `/documentation` bereitgestellt wird, und ReDoc zu deaktivieren:
|
Um beispielsweise Swagger UI so einzustellen, dass sie unter `/documentation` bereitgestellt wird, und ReDoc zu deaktivieren:
|
||||||
|
|
||||||
{* ../../docs_src/metadata/tutorial003_py39.py hl[3] *}
|
{* ../../docs_src/metadata/tutorial003.py hl[3] *}
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ Die Middleware-Funktion erhält:
|
||||||
* Dann gibt es die von der entsprechenden *Pfadoperation* generierte `response` zurück.
|
* Dann gibt es die von der entsprechenden *Pfadoperation* generierte `response` zurück.
|
||||||
* Sie können die `response` dann weiter modifizieren, bevor Sie sie zurückgeben.
|
* Sie können die `response` dann weiter modifizieren, bevor Sie sie zurückgeben.
|
||||||
|
|
||||||
{* ../../docs_src/middleware/tutorial001_py39.py hl[8:9,11,14] *}
|
{* ../../docs_src/middleware/tutorial001.py hl[8:9,11,14] *}
|
||||||
|
|
||||||
/// tip | Tipp
|
/// tip | Tipp
|
||||||
|
|
||||||
|
|
@ -57,7 +57,7 @@ Und auch nachdem die `response` generiert wurde, bevor sie zurückgegeben wird.
|
||||||
|
|
||||||
Sie könnten beispielsweise einen benutzerdefinierten Header `X-Process-Time` hinzufügen, der die Zeit in Sekunden enthält, die benötigt wurde, um den Request zu verarbeiten und eine Response zu generieren:
|
Sie könnten beispielsweise einen benutzerdefinierten Header `X-Process-Time` hinzufügen, der die Zeit in Sekunden enthält, die benötigt wurde, um den Request zu verarbeiten und eine Response zu generieren:
|
||||||
|
|
||||||
{* ../../docs_src/middleware/tutorial001_py39.py hl[10,12:13] *}
|
{* ../../docs_src/middleware/tutorial001.py hl[10,12:13] *}
|
||||||
|
|
||||||
/// tip | Tipp
|
/// tip | Tipp
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,7 @@ In diesem Fall macht es Sinn, die Tags in einem `Enum` zu speichern.
|
||||||
|
|
||||||
**FastAPI** unterstützt das auf die gleiche Weise wie einfache Strings:
|
**FastAPI** unterstützt das auf die gleiche Weise wie einfache Strings:
|
||||||
|
|
||||||
{* ../../docs_src/path_operation_configuration/tutorial002b_py39.py hl[1,8:10,13,18] *}
|
{* ../../docs_src/path_operation_configuration/tutorial002b.py hl[1,8:10,13,18] *}
|
||||||
|
|
||||||
## Zusammenfassung und Beschreibung { #summary-and-description }
|
## Zusammenfassung und Beschreibung { #summary-and-description }
|
||||||
|
|
||||||
|
|
@ -92,7 +92,7 @@ Daher, wenn Sie keine vergeben, wird **FastAPI** automatisch eine für „Erfolg
|
||||||
|
|
||||||
Wenn Sie eine *Pfadoperation* als <abbr title="veraltet, obsolet: Es soll nicht mehr verwendet werden">deprecatet</abbr> kennzeichnen möchten, ohne sie zu entfernen, fügen Sie den Parameter `deprecated` hinzu:
|
Wenn Sie eine *Pfadoperation* als <abbr title="veraltet, obsolet: Es soll nicht mehr verwendet werden">deprecatet</abbr> kennzeichnen möchten, ohne sie zu entfernen, fügen Sie den Parameter `deprecated` hinzu:
|
||||||
|
|
||||||
{* ../../docs_src/path_operation_configuration/tutorial006_py39.py hl[16] *}
|
{* ../../docs_src/path_operation_configuration/tutorial006.py hl[16] *}
|
||||||
|
|
||||||
Sie wird in der interaktiven Dokumentation gut sichtbar als deprecatet markiert werden:
|
Sie wird in der interaktiven Dokumentation gut sichtbar als deprecatet markiert werden:
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,7 @@ Für **FastAPI** spielt es keine Rolle. Es erkennt die Parameter anhand ihrer Na
|
||||||
|
|
||||||
Sie können Ihre Funktion also so deklarieren:
|
Sie können Ihre Funktion also so deklarieren:
|
||||||
|
|
||||||
{* ../../docs_src/path_params_numeric_validations/tutorial002_py39.py hl[7] *}
|
{* ../../docs_src/path_params_numeric_validations/tutorial002.py hl[7] *}
|
||||||
|
|
||||||
Aber bedenken Sie, dass Sie dieses Problem nicht haben, wenn Sie `Annotated` verwenden, da es nicht darauf ankommt, dass Sie keine Funktionsparameter-Defaultwerte für `Query()` oder `Path()` verwenden.
|
Aber bedenken Sie, dass Sie dieses Problem nicht haben, wenn Sie `Annotated` verwenden, da es nicht darauf ankommt, dass Sie keine Funktionsparameter-Defaultwerte für `Query()` oder `Path()` verwenden.
|
||||||
|
|
||||||
|
|
@ -83,7 +83,7 @@ Wenn Sie:
|
||||||
|
|
||||||
Python wird nichts mit diesem `*` machen, aber es wird wissen, dass alle folgenden Parameter als Schlüsselwortargumente (Schlüssel-Wert-Paare) verwendet werden sollen, auch bekannt als <abbr title="Von: K-ey W-ord Arg-uments"><code>kwargs</code></abbr>. Selbst wenn diese keinen Defaultwert haben.
|
Python wird nichts mit diesem `*` machen, aber es wird wissen, dass alle folgenden Parameter als Schlüsselwortargumente (Schlüssel-Wert-Paare) verwendet werden sollen, auch bekannt als <abbr title="Von: K-ey W-ord Arg-uments"><code>kwargs</code></abbr>. Selbst wenn diese keinen Defaultwert haben.
|
||||||
|
|
||||||
{* ../../docs_src/path_params_numeric_validations/tutorial003_py39.py hl[7] *}
|
{* ../../docs_src/path_params_numeric_validations/tutorial003.py hl[7] *}
|
||||||
|
|
||||||
### Besser mit `Annotated` { #better-with-annotated }
|
### Besser mit `Annotated` { #better-with-annotated }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
Sie können Pfad-„Parameter“ oder -„Variablen“ mit der gleichen Syntax deklarieren, welche in Python-<abbr title="Formatstring – Formatierter String: Der String enthält Ausdrücke, die mit geschweiften Klammern umschlossen sind. Solche Stellen werden durch den Wert des Ausdrucks ersetzt">Formatstrings</abbr> verwendet wird:
|
Sie können Pfad-„Parameter“ oder -„Variablen“ mit der gleichen Syntax deklarieren, welche in Python-<abbr title="Formatstring – Formatierter String: Der String enthält Ausdrücke, die mit geschweiften Klammern umschlossen sind. Solche Stellen werden durch den Wert des Ausdrucks ersetzt">Formatstrings</abbr> verwendet wird:
|
||||||
|
|
||||||
{* ../../docs_src/path_params/tutorial001_py39.py hl[6:7] *}
|
{* ../../docs_src/path_params/tutorial001.py hl[6:7] *}
|
||||||
|
|
||||||
Der Wert des Pfad-Parameters `item_id` wird Ihrer Funktion als das Argument `item_id` übergeben.
|
Der Wert des Pfad-Parameters `item_id` wird Ihrer Funktion als das Argument `item_id` übergeben.
|
||||||
|
|
||||||
|
|
@ -16,7 +16,7 @@ Wenn Sie dieses Beispiel ausführen und auf <a href="http://127.0.0.1:8000/items
|
||||||
|
|
||||||
Sie können den Typ eines Pfad-Parameters in der Argumentliste der Funktion deklarieren, mit Standard-Python-Typannotationen:
|
Sie können den Typ eines Pfad-Parameters in der Argumentliste der Funktion deklarieren, mit Standard-Python-Typannotationen:
|
||||||
|
|
||||||
{* ../../docs_src/path_params/tutorial002_py39.py hl[7] *}
|
{* ../../docs_src/path_params/tutorial002.py hl[7] *}
|
||||||
|
|
||||||
In diesem Fall wird `item_id` als `int` deklariert, also als Ganzzahl.
|
In diesem Fall wird `item_id` als `int` deklariert, also als Ganzzahl.
|
||||||
|
|
||||||
|
|
@ -118,13 +118,13 @@ Und Sie haben auch einen Pfad `/users/{user_id}`, um Daten über einen spezifisc
|
||||||
|
|
||||||
Weil *Pfadoperationen* in ihrer Reihenfolge ausgewertet werden, müssen Sie sicherstellen, dass der Pfad `/users/me` vor `/users/{user_id}` deklariert wurde:
|
Weil *Pfadoperationen* in ihrer Reihenfolge ausgewertet werden, müssen Sie sicherstellen, dass der Pfad `/users/me` vor `/users/{user_id}` deklariert wurde:
|
||||||
|
|
||||||
{* ../../docs_src/path_params/tutorial003_py39.py hl[6,11] *}
|
{* ../../docs_src/path_params/tutorial003.py hl[6,11] *}
|
||||||
|
|
||||||
Ansonsten würde der Pfad für `/users/{user_id}` auch `/users/me` auswerten, und annehmen, dass ein Parameter `user_id` mit dem Wert `"me"` übergeben wurde.
|
Ansonsten würde der Pfad für `/users/{user_id}` auch `/users/me` auswerten, und annehmen, dass ein Parameter `user_id` mit dem Wert `"me"` übergeben wurde.
|
||||||
|
|
||||||
Sie können eine Pfadoperation auch nicht erneut definieren:
|
Sie können eine Pfadoperation auch nicht erneut definieren:
|
||||||
|
|
||||||
{* ../../docs_src/path_params/tutorial003b_py39.py hl[6,11] *}
|
{* ../../docs_src/path_params/tutorial003b.py hl[6,11] *}
|
||||||
|
|
||||||
Die erste Definition wird immer verwendet werden, da ihr Pfad zuerst übereinstimmt.
|
Die erste Definition wird immer verwendet werden, da ihr Pfad zuerst übereinstimmt.
|
||||||
|
|
||||||
|
|
@ -140,8 +140,13 @@ Indem Sie von `str` erben, weiß die API-Dokumentation, dass die Werte vom Typ `
|
||||||
|
|
||||||
Erstellen Sie dann Klassen-Attribute mit festgelegten Werten, welches die erlaubten Werte sein werden:
|
Erstellen Sie dann Klassen-Attribute mit festgelegten Werten, welches die erlaubten Werte sein werden:
|
||||||
|
|
||||||
{* ../../docs_src/path_params/tutorial005_py39.py hl[1,6:9] *}
|
{* ../../docs_src/path_params/tutorial005.py hl[1,6:9] *}
|
||||||
|
|
||||||
|
/// info | Info
|
||||||
|
|
||||||
|
<a href="https://docs.python.org/3/library/enum.html" class="external-link" target="_blank">Enumerationen (oder Enums)</a> gibt es in Python seit Version 3.4.
|
||||||
|
|
||||||
|
///
|
||||||
|
|
||||||
/// tip | Tipp
|
/// tip | Tipp
|
||||||
|
|
||||||
|
|
@ -153,7 +158,7 @@ Falls Sie sich fragen, was „AlexNet“, „ResNet“ und „LeNet“ ist, das
|
||||||
|
|
||||||
Dann erstellen Sie einen *Pfad-Parameter*, der als Typ die gerade erstellte Enum-Klasse hat (`ModelName`):
|
Dann erstellen Sie einen *Pfad-Parameter*, der als Typ die gerade erstellte Enum-Klasse hat (`ModelName`):
|
||||||
|
|
||||||
{* ../../docs_src/path_params/tutorial005_py39.py hl[16] *}
|
{* ../../docs_src/path_params/tutorial005.py hl[16] *}
|
||||||
|
|
||||||
### Die API-Dokumentation testen { #check-the-docs }
|
### Die API-Dokumentation testen { #check-the-docs }
|
||||||
|
|
||||||
|
|
@ -169,13 +174,13 @@ Der *Pfad-Parameter* wird ein *<abbr title="Member – Mitglied: Einer der mögl
|
||||||
|
|
||||||
Sie können ihn mit einem Member Ihrer Enumeration `ModelName` vergleichen:
|
Sie können ihn mit einem Member Ihrer Enumeration `ModelName` vergleichen:
|
||||||
|
|
||||||
{* ../../docs_src/path_params/tutorial005_py39.py hl[17] *}
|
{* ../../docs_src/path_params/tutorial005.py hl[17] *}
|
||||||
|
|
||||||
#### *Enumerations-Wert* erhalten { #get-the-enumeration-value }
|
#### *Enumerations-Wert* erhalten { #get-the-enumeration-value }
|
||||||
|
|
||||||
Den tatsächlichen Wert (in diesem Fall ein `str`) erhalten Sie via `model_name.value`, oder generell, `your_enum_member.value`:
|
Den tatsächlichen Wert (in diesem Fall ein `str`) erhalten Sie via `model_name.value`, oder generell, `your_enum_member.value`:
|
||||||
|
|
||||||
{* ../../docs_src/path_params/tutorial005_py39.py hl[20] *}
|
{* ../../docs_src/path_params/tutorial005.py hl[20] *}
|
||||||
|
|
||||||
/// tip | Tipp
|
/// tip | Tipp
|
||||||
|
|
||||||
|
|
@ -189,7 +194,7 @@ Sie können *Enum-Member* in ihrer *Pfadoperation* zurückgeben, sogar verschach
|
||||||
|
|
||||||
Diese werden zu ihren entsprechenden Werten konvertiert (in diesem Fall Strings), bevor sie zum Client übertragen werden:
|
Diese werden zu ihren entsprechenden Werten konvertiert (in diesem Fall Strings), bevor sie zum Client übertragen werden:
|
||||||
|
|
||||||
{* ../../docs_src/path_params/tutorial005_py39.py hl[18,21,23] *}
|
{* ../../docs_src/path_params/tutorial005.py hl[18,21,23] *}
|
||||||
|
|
||||||
In Ihrem Client erhalten Sie eine JSON-Response, wie etwa:
|
In Ihrem Client erhalten Sie eine JSON-Response, wie etwa:
|
||||||
|
|
||||||
|
|
@ -228,7 +233,7 @@ In diesem Fall ist der Name des Parameters `file_path`. Der letzte Teil, `:path`
|
||||||
|
|
||||||
Sie verwenden das also wie folgt:
|
Sie verwenden das also wie folgt:
|
||||||
|
|
||||||
{* ../../docs_src/path_params/tutorial004_py39.py hl[6] *}
|
{* ../../docs_src/path_params/tutorial004.py hl[6] *}
|
||||||
|
|
||||||
/// tip | Tipp
|
/// tip | Tipp
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,7 @@ q: str | None = None
|
||||||
|
|
||||||
////
|
////
|
||||||
|
|
||||||
//// tab | Python 3.9+
|
//// tab | Python 3.8+
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
q: Union[str, None] = None
|
q: Union[str, None] = None
|
||||||
|
|
@ -73,7 +73,7 @@ q: Annotated[str | None] = None
|
||||||
|
|
||||||
////
|
////
|
||||||
|
|
||||||
//// tab | Python 3.9+
|
//// tab | Python 3.8+
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
q: Annotated[Union[str, None]] = None
|
q: Annotated[Union[str, None]] = None
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
Wenn Sie in Ihrer Funktion andere Parameter deklarieren, die nicht Teil der Pfad-Parameter sind, dann werden diese automatisch als „Query“-Parameter interpretiert.
|
Wenn Sie in Ihrer Funktion andere Parameter deklarieren, die nicht Teil der Pfad-Parameter sind, dann werden diese automatisch als „Query“-Parameter interpretiert.
|
||||||
|
|
||||||
{* ../../docs_src/query_params/tutorial001_py39.py hl[9] *}
|
{* ../../docs_src/query_params/tutorial001.py hl[9] *}
|
||||||
|
|
||||||
Die <abbr title="Abfrage">Query</abbr> ist die Menge von Schlüssel-Wert-Paaren, die nach dem `?` in einer URL folgen und durch `&`-Zeichen getrennt sind.
|
Die <abbr title="Abfrage">Query</abbr> ist die Menge von Schlüssel-Wert-Paaren, die nach dem `?` in einer URL folgen und durch `&`-Zeichen getrennt sind.
|
||||||
|
|
||||||
|
|
@ -127,7 +127,7 @@ Wenn Sie keinen spezifischen Wert haben wollen, sondern der Parameter einfach op
|
||||||
|
|
||||||
Aber wenn Sie wollen, dass ein Query-Parameter erforderlich ist, vergeben Sie einfach keinen Defaultwert:
|
Aber wenn Sie wollen, dass ein Query-Parameter erforderlich ist, vergeben Sie einfach keinen Defaultwert:
|
||||||
|
|
||||||
{* ../../docs_src/query_params/tutorial005_py39.py hl[6:7] *}
|
{* ../../docs_src/query_params/tutorial005.py hl[6:7] *}
|
||||||
|
|
||||||
Hier ist `needy` ein erforderlicher Query-Parameter vom Typ `str`.
|
Hier ist `needy` ein erforderlicher Query-Parameter vom Typ `str`.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -183,7 +183,7 @@ Es kann Fälle geben, bei denen Sie etwas zurückgeben, das kein gültiges Pydan
|
||||||
|
|
||||||
Der häufigste Anwendungsfall ist, wenn Sie [eine Response direkt zurückgeben, wie es später im Handbuch für fortgeschrittene Benutzer erläutert wird](../advanced/response-directly.md){.internal-link target=_blank}.
|
Der häufigste Anwendungsfall ist, wenn Sie [eine Response direkt zurückgeben, wie es später im Handbuch für fortgeschrittene Benutzer erläutert wird](../advanced/response-directly.md){.internal-link target=_blank}.
|
||||||
|
|
||||||
{* ../../docs_src/response_model/tutorial003_02_py39.py hl[8,10:11] *}
|
{* ../../docs_src/response_model/tutorial003_02.py hl[8,10:11] *}
|
||||||
|
|
||||||
Dieser einfache Anwendungsfall wird automatisch von FastAPI gehandhabt, weil die Annotation des Rückgabetyps die Klasse (oder eine Unterklasse von) `Response` ist.
|
Dieser einfache Anwendungsfall wird automatisch von FastAPI gehandhabt, weil die Annotation des Rückgabetyps die Klasse (oder eine Unterklasse von) `Response` ist.
|
||||||
|
|
||||||
|
|
@ -193,7 +193,7 @@ Und Tools werden auch glücklich sein, weil sowohl `RedirectResponse` als auch `
|
||||||
|
|
||||||
Sie können auch eine Unterklasse von `Response` in der Typannotation verwenden.
|
Sie können auch eine Unterklasse von `Response` in der Typannotation verwenden.
|
||||||
|
|
||||||
{* ../../docs_src/response_model/tutorial003_03_py39.py hl[8:9] *}
|
{* ../../docs_src/response_model/tutorial003_03.py hl[8:9] *}
|
||||||
|
|
||||||
Das wird ebenfalls funktionieren, weil `RedirectResponse` eine Unterklasse von `Response` ist, und FastAPI sich um diesen einfachen Anwendungsfall automatisch kümmert.
|
Das wird ebenfalls funktionieren, weil `RedirectResponse` eine Unterklasse von `Response` ist, und FastAPI sich um diesen einfachen Anwendungsfall automatisch kümmert.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ Genauso wie Sie ein Responsemodell angeben können, können Sie auch den HTTP-St
|
||||||
* `@app.delete()`
|
* `@app.delete()`
|
||||||
* usw.
|
* usw.
|
||||||
|
|
||||||
{* ../../docs_src/response_status_code/tutorial001_py39.py hl[6] *}
|
{* ../../docs_src/response_status_code/tutorial001.py hl[6] *}
|
||||||
|
|
||||||
/// note | Hinweis
|
/// note | Hinweis
|
||||||
|
|
||||||
|
|
@ -74,7 +74,7 @@ Um mehr über die einzelnen Statuscodes zu erfahren und welcher wofür verwendet
|
||||||
|
|
||||||
Lassen Sie uns das vorherige Beispiel noch einmal anschauen:
|
Lassen Sie uns das vorherige Beispiel noch einmal anschauen:
|
||||||
|
|
||||||
{* ../../docs_src/response_status_code/tutorial001_py39.py hl[6] *}
|
{* ../../docs_src/response_status_code/tutorial001.py hl[6] *}
|
||||||
|
|
||||||
`201` ist der Statuscode für „Created“ („Erzeugt“).
|
`201` ist der Statuscode für „Created“ („Erzeugt“).
|
||||||
|
|
||||||
|
|
@ -82,7 +82,7 @@ Aber Sie müssen sich nicht merken, was jeder dieser Codes bedeutet.
|
||||||
|
|
||||||
Sie können die Annehmlichkeit von Variablen aus `fastapi.status` nutzen.
|
Sie können die Annehmlichkeit von Variablen aus `fastapi.status` nutzen.
|
||||||
|
|
||||||
{* ../../docs_src/response_status_code/tutorial002_py39.py hl[1,6] *}
|
{* ../../docs_src/response_status_code/tutorial002.py hl[1,6] *}
|
||||||
|
|
||||||
Diese sind nur eine Annehmlichkeit, sie enthalten dieselbe Zahl, aber so können Sie die Autovervollständigung Ihres Editors verwenden, um sie zu finden:
|
Diese sind nur eine Annehmlichkeit, sie enthalten dieselbe Zahl, aber so können Sie die Autovervollständigung Ihres Editors verwenden, um sie zu finden:
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -65,7 +65,7 @@ Es gibt ein paar Unterschiede:
|
||||||
|
|
||||||
* `Field(primary_key=True)` sagt SQLModel, dass die `id` der **Primärschlüssel** in der SQL-Datenbank ist (Sie können mehr über SQL-Primärschlüssel in der SQLModel-Dokumentation erfahren).
|
* `Field(primary_key=True)` sagt SQLModel, dass die `id` der **Primärschlüssel** in der SQL-Datenbank ist (Sie können mehr über SQL-Primärschlüssel in der SQLModel-Dokumentation erfahren).
|
||||||
|
|
||||||
**Hinweis:** Wir verwenden für das Primärschlüsselfeld `int | None`, damit wir im Python-Code *ein Objekt ohne `id` erstellen* können (`id=None`), in der Annahme, dass die Datenbank sie *beim Speichern generiert*. SQLModel versteht, dass die Datenbank die `id` bereitstellt, und *definiert die Spalte im Datenbankschema als ein Nicht-Null-`INTEGER`*. Siehe die <a href="https://sqlmodel.tiangolo.com/tutorial/create-db-and-table/#primary-key-id" class="external-link" target="_blank">SQLModel-Dokumentation zu Primärschlüsseln</a> für Details.
|
Durch das Festlegen des Typs als `int | None` wird SQLModel wissen, dass diese Spalte ein `INTEGER` in der SQL-Datenbank sein sollte und dass sie `NULLABLE` sein sollte.
|
||||||
|
|
||||||
* `Field(index=True)` sagt SQLModel, dass es einen **SQL-Index** für diese Spalte erstellen soll, was schnelleres Suchen in der Datenbank ermöglicht, wenn Daten mittels dieser Spalte gefiltert werden.
|
* `Field(index=True)` sagt SQLModel, dass es einen **SQL-Index** für diese Spalte erstellen soll, was schnelleres Suchen in der Datenbank ermöglicht, wenn Daten mittels dieser Spalte gefiltert werden.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ Mit `StaticFiles` können Sie statische Dateien aus einem Verzeichnis automatisc
|
||||||
* Importieren Sie `StaticFiles`.
|
* Importieren Sie `StaticFiles`.
|
||||||
* „Mounten“ Sie eine `StaticFiles()`-Instanz in einem bestimmten Pfad.
|
* „Mounten“ Sie eine `StaticFiles()`-Instanz in einem bestimmten Pfad.
|
||||||
|
|
||||||
{* ../../docs_src/static_files/tutorial001_py39.py hl[2,6] *}
|
{* ../../docs_src/static_files/tutorial001.py hl[2,6] *}
|
||||||
|
|
||||||
/// note | Technische Details
|
/// note | Technische Details
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ Verwenden Sie das `TestClient`-Objekt auf die gleiche Weise wie `httpx`.
|
||||||
|
|
||||||
Schreiben Sie einfache `assert`-Anweisungen mit den Standard-Python-Ausdrücken, die Sie überprüfen müssen (wiederum, Standard-`pytest`).
|
Schreiben Sie einfache `assert`-Anweisungen mit den Standard-Python-Ausdrücken, die Sie überprüfen müssen (wiederum, Standard-`pytest`).
|
||||||
|
|
||||||
{* ../../docs_src/app_testing/tutorial001_py39.py hl[2,12,15:18] *}
|
{* ../../docs_src/app_testing/tutorial001.py hl[2,12,15:18] *}
|
||||||
|
|
||||||
/// tip | Tipp
|
/// tip | Tipp
|
||||||
|
|
||||||
|
|
@ -76,7 +76,7 @@ Nehmen wir an, Sie haben eine Dateistruktur wie in [Größere Anwendungen](bigge
|
||||||
In der Datei `main.py` haben Sie Ihre **FastAPI**-Anwendung:
|
In der Datei `main.py` haben Sie Ihre **FastAPI**-Anwendung:
|
||||||
|
|
||||||
|
|
||||||
{* ../../docs_src/app_testing/app_a_py39/main.py *}
|
{* ../../docs_src/app_testing/main.py *}
|
||||||
|
|
||||||
|
|
||||||
### Testdatei { #testing-file }
|
### Testdatei { #testing-file }
|
||||||
|
|
@ -93,7 +93,7 @@ Dann könnten Sie eine Datei `test_main.py` mit Ihren Tests haben. Sie könnte s
|
||||||
|
|
||||||
Da sich diese Datei im selben Package befindet, können Sie relative Importe verwenden, um das Objekt `app` aus dem `main`-Modul (`main.py`) zu importieren:
|
Da sich diese Datei im selben Package befindet, können Sie relative Importe verwenden, um das Objekt `app` aus dem `main`-Modul (`main.py`) zu importieren:
|
||||||
|
|
||||||
{* ../../docs_src/app_testing/app_a_py39/test_main.py hl[3] *}
|
{* ../../docs_src/app_testing/test_main.py hl[3] *}
|
||||||
|
|
||||||
|
|
||||||
... und haben den Code für die Tests wie zuvor.
|
... und haben den Code für die Tests wie zuvor.
|
||||||
|
|
@ -122,13 +122,63 @@ Sie verfügt über eine `POST`-Operation, die mehrere Fehler zurückgeben könnt
|
||||||
|
|
||||||
Beide *Pfadoperationen* erfordern einen `X-Token`-Header.
|
Beide *Pfadoperationen* erfordern einen `X-Token`-Header.
|
||||||
|
|
||||||
{* ../../docs_src/app_testing/app_b_an_py310/main.py *}
|
//// tab | Python 3.10+
|
||||||
|
|
||||||
|
```Python
|
||||||
|
{!> ../../docs_src/app_testing/app_b_an_py310/main.py!}
|
||||||
|
```
|
||||||
|
|
||||||
|
////
|
||||||
|
|
||||||
|
//// tab | Python 3.9+
|
||||||
|
|
||||||
|
```Python
|
||||||
|
{!> ../../docs_src/app_testing/app_b_an_py39/main.py!}
|
||||||
|
```
|
||||||
|
|
||||||
|
////
|
||||||
|
|
||||||
|
//// tab | Python 3.8+
|
||||||
|
|
||||||
|
```Python
|
||||||
|
{!> ../../docs_src/app_testing/app_b_an/main.py!}
|
||||||
|
```
|
||||||
|
|
||||||
|
////
|
||||||
|
|
||||||
|
//// tab | Python 3.10+ nicht annotiert
|
||||||
|
|
||||||
|
/// tip | Tipp
|
||||||
|
|
||||||
|
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||||
|
|
||||||
|
///
|
||||||
|
|
||||||
|
```Python
|
||||||
|
{!> ../../docs_src/app_testing/app_b_py310/main.py!}
|
||||||
|
```
|
||||||
|
|
||||||
|
////
|
||||||
|
|
||||||
|
//// tab | Python 3.8+ nicht annotiert
|
||||||
|
|
||||||
|
/// tip | Tipp
|
||||||
|
|
||||||
|
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||||
|
|
||||||
|
///
|
||||||
|
|
||||||
|
```Python
|
||||||
|
{!> ../../docs_src/app_testing/app_b/main.py!}
|
||||||
|
```
|
||||||
|
|
||||||
|
////
|
||||||
|
|
||||||
### Erweiterte Testdatei { #extended-testing-file }
|
### Erweiterte Testdatei { #extended-testing-file }
|
||||||
|
|
||||||
Anschließend könnten Sie `test_main.py` mit den erweiterten Tests aktualisieren:
|
Anschließend könnten Sie `test_main.py` mit den erweiterten Tests aktualisieren:
|
||||||
|
|
||||||
{* ../../docs_src/app_testing/app_b_an_py310/test_main.py *}
|
{* ../../docs_src/app_testing/app_b/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.
|
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.
|
||||||
|
|
|
||||||
|
|
@ -242,26 +242,6 @@ $ python -m pip install --upgrade pip
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
/// tip | Tipp
|
|
||||||
|
|
||||||
Manchmal kann beim Versuch, `pip` zu aktualisieren, der Fehler **`No module named pip`** auftreten.
|
|
||||||
|
|
||||||
Wenn das passiert, installieren und aktualisieren Sie `pip` mit dem folgenden Befehl:
|
|
||||||
|
|
||||||
<div class="termy">
|
|
||||||
|
|
||||||
```console
|
|
||||||
$ python -m ensurepip --upgrade
|
|
||||||
|
|
||||||
---> 100%
|
|
||||||
```
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
Dieser Befehl installiert `pip`, falls es noch nicht installiert ist, und stellt außerdem sicher, dass die installierte Version von `pip` mindestens so aktuell ist wie die in `ensurepip` verfügbare.
|
|
||||||
|
|
||||||
///
|
|
||||||
|
|
||||||
## `.gitignore` hinzufügen { #add-gitignore }
|
## `.gitignore` hinzufügen { #add-gitignore }
|
||||||
|
|
||||||
Wenn Sie **Git** verwenden (was Sie sollten), fügen Sie eine `.gitignore`-Datei hinzu, um alles in Ihrem `.venv` von Git auszuschließen.
|
Wenn Sie **Git** verwenden (was Sie sollten), fügen Sie eine `.gitignore`-Datei hinzu, um alles in Ihrem `.venv` von Git auszuschließen.
|
||||||
|
|
|
||||||
|
|
@ -255,7 +255,6 @@ Below is a list of English terms and their preferred German translations, separa
|
||||||
* «the default value»: «der Defaultwert»
|
* «the default value»: «der Defaultwert»
|
||||||
* «the default value»: NOT «der Standardwert»
|
* «the default value»: NOT «der Standardwert»
|
||||||
* «the default declaration»: «die Default-Deklaration»
|
* «the default declaration»: «die Default-Deklaration»
|
||||||
* «the deployment»: «das Deployment»
|
|
||||||
* «the dict»: «das Dict»
|
* «the dict»: «das Dict»
|
||||||
* «the dictionary»: «das Dictionary»
|
* «the dictionary»: «das Dictionary»
|
||||||
* «the enumeration»: «die Enumeration»
|
* «the enumeration»: «die Enumeration»
|
||||||
|
|
@ -317,7 +316,6 @@ Below is a list of English terms and their preferred German translations, separa
|
||||||
* «the worker process»: «der Workerprozess»
|
* «the worker process»: «der Workerprozess»
|
||||||
* «the worker process»: NOT «der Arbeiterprozess»
|
* «the worker process»: NOT «der Arbeiterprozess»
|
||||||
* «to commit»: «committen»
|
* «to commit»: «committen»
|
||||||
* «to deploy» (in the cloud): «deployen»
|
|
||||||
* «to modify»: «ändern»
|
* «to modify»: «ändern»
|
||||||
* «to serve» (an application): «bereitstellen»
|
* «to serve» (an application): «bereitstellen»
|
||||||
* «to serve» (a response): «ausliefern»
|
* «to serve» (a response): «ausliefern»
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,247 @@
|
||||||
|
# 🌖 📨 🗄
|
||||||
|
|
||||||
|
/// warning
|
||||||
|
|
||||||
|
👉 👍 🏧 ❔.
|
||||||
|
|
||||||
|
🚥 👆 ▶️ ⏮️ **FastAPI**, 👆 💪 🚫 💪 👉.
|
||||||
|
|
||||||
|
///
|
||||||
|
|
||||||
|
👆 💪 📣 🌖 📨, ⏮️ 🌖 👔 📟, 🔉 🆎, 📛, ♒️.
|
||||||
|
|
||||||
|
👈 🌖 📨 🔜 🔌 🗄 🔗, 👫 🔜 😑 🛠️ 🩺.
|
||||||
|
|
||||||
|
✋️ 👈 🌖 📨 👆 ✔️ ⚒ 💭 👆 📨 `Response` 💖 `JSONResponse` 🔗, ⏮️ 👆 👔 📟 & 🎚.
|
||||||
|
|
||||||
|
## 🌖 📨 ⏮️ `model`
|
||||||
|
|
||||||
|
👆 💪 🚶♀️ 👆 *➡ 🛠️ 👨🎨* 🔢 `responses`.
|
||||||
|
|
||||||
|
⚫️ 📨 `dict`, 🔑 👔 📟 🔠 📨, 💖 `200`, & 💲 🎏 `dict`Ⓜ ⏮️ ℹ 🔠 👫.
|
||||||
|
|
||||||
|
🔠 👈 📨 `dict`Ⓜ 💪 ✔️ 🔑 `model`, ⚗ Pydantic 🏷, 💖 `response_model`.
|
||||||
|
|
||||||
|
**FastAPI** 🔜 ✊ 👈 🏷, 🏗 🚮 🎻 🔗 & 🔌 ⚫️ ☑ 🥉 🗄.
|
||||||
|
|
||||||
|
🖼, 📣 ➕1️⃣ 📨 ⏮️ 👔 📟 `404` & Pydantic 🏷 `Message`, 👆 💪 ✍:
|
||||||
|
|
||||||
|
{* ../../docs_src/additional_responses/tutorial001.py hl[18,22] *}
|
||||||
|
|
||||||
|
/// note
|
||||||
|
|
||||||
|
✔️ 🤯 👈 👆 ✔️ 📨 `JSONResponse` 🔗.
|
||||||
|
|
||||||
|
///
|
||||||
|
|
||||||
|
/// info
|
||||||
|
|
||||||
|
`model` 🔑 🚫 🍕 🗄.
|
||||||
|
|
||||||
|
**FastAPI** 🔜 ✊ Pydantic 🏷 ⚪️➡️ 📤, 🏗 `JSON Schema`, & 🚮 ⚫️ ☑ 🥉.
|
||||||
|
|
||||||
|
☑ 🥉:
|
||||||
|
|
||||||
|
* 🔑 `content`, 👈 ✔️ 💲 ➕1️⃣ 🎻 🎚 (`dict`) 👈 🔌:
|
||||||
|
* 🔑 ⏮️ 📻 🆎, ✅ `application/json`, 👈 🔌 💲 ➕1️⃣ 🎻 🎚, 👈 🔌:
|
||||||
|
* 🔑 `schema`, 👈 ✔️ 💲 🎻 🔗 ⚪️➡️ 🏷, 📥 ☑ 🥉.
|
||||||
|
* **FastAPI** 🚮 🔗 📥 🌐 🎻 🔗 ➕1️⃣ 🥉 👆 🗄 ↩️ ✅ ⚫️ 🔗. 👉 🌌, 🎏 🈸 & 👩💻 💪 ⚙️ 👈 🎻 🔗 🔗, 🚚 👻 📟 ⚡ 🧰, ♒️.
|
||||||
|
|
||||||
|
///
|
||||||
|
|
||||||
|
🏗 📨 🗄 👉 *➡ 🛠️* 🔜:
|
||||||
|
|
||||||
|
```JSON hl_lines="3-12"
|
||||||
|
{
|
||||||
|
"responses": {
|
||||||
|
"404": {
|
||||||
|
"description": "Additional Response",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/Message"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"200": {
|
||||||
|
"description": "Successful Response",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/Item"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"422": {
|
||||||
|
"description": "Validation Error",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/HTTPValidationError"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
🔗 🔗 ➕1️⃣ 🥉 🔘 🗄 🔗:
|
||||||
|
|
||||||
|
```JSON hl_lines="4-16"
|
||||||
|
{
|
||||||
|
"components": {
|
||||||
|
"schemas": {
|
||||||
|
"Message": {
|
||||||
|
"title": "Message",
|
||||||
|
"required": [
|
||||||
|
"message"
|
||||||
|
],
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"message": {
|
||||||
|
"title": "Message",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Item": {
|
||||||
|
"title": "Item",
|
||||||
|
"required": [
|
||||||
|
"id",
|
||||||
|
"value"
|
||||||
|
],
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"title": "Id",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"value": {
|
||||||
|
"title": "Value",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ValidationError": {
|
||||||
|
"title": "ValidationError",
|
||||||
|
"required": [
|
||||||
|
"loc",
|
||||||
|
"msg",
|
||||||
|
"type"
|
||||||
|
],
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"loc": {
|
||||||
|
"title": "Location",
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"msg": {
|
||||||
|
"title": "Message",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"type": {
|
||||||
|
"title": "Error Type",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"HTTPValidationError": {
|
||||||
|
"title": "HTTPValidationError",
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"detail": {
|
||||||
|
"title": "Detail",
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/components/schemas/ValidationError"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🌖 🔉 🆎 👑 📨
|
||||||
|
|
||||||
|
👆 💪 ⚙️ 👉 🎏 `responses` 🔢 🚮 🎏 🔉 🆎 🎏 👑 📨.
|
||||||
|
|
||||||
|
🖼, 👆 💪 🚮 🌖 📻 🆎 `image/png`, 📣 👈 👆 *➡ 🛠️* 💪 📨 🎻 🎚 (⏮️ 📻 🆎 `application/json`) ⚖️ 🇩🇴 🖼:
|
||||||
|
|
||||||
|
{* ../../docs_src/additional_responses/tutorial002.py hl[19:24,28] *}
|
||||||
|
|
||||||
|
/// note
|
||||||
|
|
||||||
|
👀 👈 👆 ✔️ 📨 🖼 ⚙️ `FileResponse` 🔗.
|
||||||
|
|
||||||
|
///
|
||||||
|
|
||||||
|
/// info
|
||||||
|
|
||||||
|
🚥 👆 ✔ 🎏 📻 🆎 🎯 👆 `responses` 🔢, FastAPI 🔜 🤔 📨 ✔️ 🎏 📻 🆎 👑 📨 🎓 (🔢 `application/json`).
|
||||||
|
|
||||||
|
✋️ 🚥 👆 ✔️ ✔ 🛃 📨 🎓 ⏮️ `None` 🚮 📻 🆎, FastAPI 🔜 ⚙️ `application/json` 🙆 🌖 📨 👈 ✔️ 👨💼 🏷.
|
||||||
|
|
||||||
|
///
|
||||||
|
|
||||||
|
## 🌀 ℹ
|
||||||
|
|
||||||
|
👆 💪 🌀 📨 ℹ ⚪️➡️ 💗 🥉, 🔌 `response_model`, `status_code`, & `responses` 🔢.
|
||||||
|
|
||||||
|
👆 💪 📣 `response_model`, ⚙️ 🔢 👔 📟 `200` (⚖️ 🛃 1️⃣ 🚥 👆 💪), & ⤴️ 📣 🌖 ℹ 👈 🎏 📨 `responses`, 🔗 🗄 🔗.
|
||||||
|
|
||||||
|
**FastAPI** 🔜 🚧 🌖 ℹ ⚪️➡️ `responses`, & 🌀 ⚫️ ⏮️ 🎻 🔗 ⚪️➡️ 👆 🏷.
|
||||||
|
|
||||||
|
🖼, 👆 💪 📣 📨 ⏮️ 👔 📟 `404` 👈 ⚙️ Pydantic 🏷 & ✔️ 🛃 `description`.
|
||||||
|
|
||||||
|
& 📨 ⏮️ 👔 📟 `200` 👈 ⚙️ 👆 `response_model`, ✋️ 🔌 🛃 `example`:
|
||||||
|
|
||||||
|
{* ../../docs_src/additional_responses/tutorial003.py hl[20:31] *}
|
||||||
|
|
||||||
|
⚫️ 🔜 🌐 🌀 & 🔌 👆 🗄, & 🎦 🛠️ 🩺:
|
||||||
|
|
||||||
|
<img src="/img/tutorial/additional-responses/image01.png">
|
||||||
|
|
||||||
|
## 🌀 🔢 📨 & 🛃 🕐
|
||||||
|
|
||||||
|
👆 💪 💚 ✔️ 🔁 📨 👈 ✔ 📚 *➡ 🛠️*, ✋️ 👆 💚 🌀 👫 ⏮️ 🛃 📨 💚 🔠 *➡ 🛠️*.
|
||||||
|
|
||||||
|
📚 💼, 👆 💪 ⚙️ 🐍 ⚒ "🏗" `dict` ⏮️ `**dict_to_unpack`:
|
||||||
|
|
||||||
|
```Python
|
||||||
|
old_dict = {
|
||||||
|
"old key": "old value",
|
||||||
|
"second old key": "second old value",
|
||||||
|
}
|
||||||
|
new_dict = {**old_dict, "new key": "new value"}
|
||||||
|
```
|
||||||
|
|
||||||
|
📥, `new_dict` 🔜 🔌 🌐 🔑-💲 👫 ⚪️➡️ `old_dict` ➕ 🆕 🔑-💲 👫:
|
||||||
|
|
||||||
|
```Python
|
||||||
|
{
|
||||||
|
"old key": "old value",
|
||||||
|
"second old key": "second old value",
|
||||||
|
"new key": "new value",
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
👆 💪 ⚙️ 👈 ⚒ 🏤-⚙️ 🔢 📨 👆 *➡ 🛠️* & 🌀 👫 ⏮️ 🌖 🛃 🕐.
|
||||||
|
|
||||||
|
🖼:
|
||||||
|
|
||||||
|
{* ../../docs_src/additional_responses/tutorial004.py hl[13:17,26] *}
|
||||||
|
|
||||||
|
## 🌖 ℹ 🔃 🗄 📨
|
||||||
|
|
||||||
|
👀 ⚫️❔ ⚫️❔ 👆 💪 🔌 📨, 👆 💪 ✅ 👉 📄 🗄 🔧:
|
||||||
|
|
||||||
|
* <a href="https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#responsesObject" class="external-link" target="_blank">🗄 📨 🎚</a>, ⚫️ 🔌 `Response Object`.
|
||||||
|
* <a href="https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#responseObject" class="external-link" target="_blank">🗄 📨 🎚</a>, 👆 💪 🔌 🕳 ⚪️➡️ 👉 🔗 🔠 📨 🔘 👆 `responses` 🔢. ✅ `description`, `headers`, `content` (🔘 👉 👈 👆 📣 🎏 🔉 🆎 & 🎻 🔗), & `links`.
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
# 🌖 👔 📟
|
||||||
|
|
||||||
|
🔢, **FastAPI** 🔜 📨 📨 ⚙️ `JSONResponse`, 🚮 🎚 👆 📨 ⚪️➡️ 👆 *➡ 🛠️* 🔘 👈 `JSONResponse`.
|
||||||
|
|
||||||
|
⚫️ 🔜 ⚙️ 🔢 👔 📟 ⚖️ 1️⃣ 👆 ⚒ 👆 *➡ 🛠️*.
|
||||||
|
|
||||||
|
## 🌖 👔 📟
|
||||||
|
|
||||||
|
🚥 👆 💚 📨 🌖 👔 📟 ↖️ ⚪️➡️ 👑 1️⃣, 👆 💪 👈 🛬 `Response` 🔗, 💖 `JSONResponse`, & ⚒ 🌖 👔 📟 🔗.
|
||||||
|
|
||||||
|
🖼, ➡️ 💬 👈 👆 💚 ✔️ *➡ 🛠️* 👈 ✔ ℹ 🏬, & 📨 🇺🇸🔍 👔 📟 2️⃣0️⃣0️⃣ "👌" 🕐❔ 🏆.
|
||||||
|
|
||||||
|
✋️ 👆 💚 ⚫️ 🚫 🆕 🏬. & 🕐❔ 🏬 🚫 🔀 ⏭, ⚫️ ✍ 👫, & 📨 🇺🇸🔍 👔 📟 2️⃣0️⃣1️⃣ "✍".
|
||||||
|
|
||||||
|
🏆 👈, 🗄 `JSONResponse`, & 📨 👆 🎚 📤 🔗, ⚒ `status_code` 👈 👆 💚:
|
||||||
|
|
||||||
|
{* ../../docs_src/additional_status_codes/tutorial001.py hl[4,25] *}
|
||||||
|
|
||||||
|
/// warning
|
||||||
|
|
||||||
|
🕐❔ 👆 📨 `Response` 🔗, 💖 🖼 🔛, ⚫️ 🔜 📨 🔗.
|
||||||
|
|
||||||
|
⚫️ 🏆 🚫 🎻 ⏮️ 🏷, ♒️.
|
||||||
|
|
||||||
|
⚒ 💭 ⚫️ ✔️ 📊 👆 💚 ⚫️ ✔️, & 👈 💲 ☑ 🎻 (🚥 👆 ⚙️ `JSONResponse`).
|
||||||
|
|
||||||
|
///
|
||||||
|
|
||||||
|
/// note | 📡 ℹ
|
||||||
|
|
||||||
|
👆 💪 ⚙️ `from starlette.responses import JSONResponse`.
|
||||||
|
|
||||||
|
**FastAPI** 🚚 🎏 `starlette.responses` `fastapi.responses` 🏪 👆, 👩💻. ✋️ 🌅 💪 📨 👟 🔗 ⚪️➡️ 💃. 🎏 ⏮️ `status`.
|
||||||
|
|
||||||
|
///
|
||||||
|
|
||||||
|
## 🗄 & 🛠️ 🩺
|
||||||
|
|
||||||
|
🚥 👆 📨 🌖 👔 📟 & 📨 🔗, 👫 🏆 🚫 🔌 🗄 🔗 (🛠️ 🩺), ↩️ FastAPI 🚫 ✔️ 🌌 💭 ⏪ ⚫️❔ 👆 🚶 📨.
|
||||||
|
|
||||||
|
✋️ 👆 💪 📄 👈 👆 📟, ⚙️: [🌖 📨](additional-responses.md){.internal-link target=_blank}.
|
||||||
|
|
@ -0,0 +1,65 @@
|
||||||
|
# 🏧 🔗
|
||||||
|
|
||||||
|
## 🔗 🔗
|
||||||
|
|
||||||
|
🌐 🔗 👥 ✔️ 👀 🔧 🔢 ⚖️ 🎓.
|
||||||
|
|
||||||
|
✋️ 📤 💪 💼 🌐❔ 👆 💚 💪 ⚒ 🔢 🔛 🔗, 🍵 ✔️ 📣 📚 🎏 🔢 ⚖️ 🎓.
|
||||||
|
|
||||||
|
➡️ 🌈 👈 👥 💚 ✔️ 🔗 👈 ✅ 🚥 🔢 🔢 `q` 🔌 🔧 🎚.
|
||||||
|
|
||||||
|
✋️ 👥 💚 💪 🔗 👈 🔧 🎚.
|
||||||
|
|
||||||
|
## "🇧🇲" 👐
|
||||||
|
|
||||||
|
🐍 📤 🌌 ⚒ 👐 🎓 "🇧🇲".
|
||||||
|
|
||||||
|
🚫 🎓 ⚫️ (❔ ⏪ 🇧🇲), ✋️ 👐 👈 🎓.
|
||||||
|
|
||||||
|
👈, 👥 📣 👩🔬 `__call__`:
|
||||||
|
|
||||||
|
{* ../../docs_src/dependencies/tutorial011.py hl[10] *}
|
||||||
|
|
||||||
|
👉 💼, 👉 `__call__` ⚫️❔ **FastAPI** 🔜 ⚙️ ✅ 🌖 🔢 & 🎧-🔗, & 👉 ⚫️❔ 🔜 🤙 🚶♀️ 💲 🔢 👆 *➡ 🛠️ 🔢* ⏪.
|
||||||
|
|
||||||
|
## 🔗 👐
|
||||||
|
|
||||||
|
& 🔜, 👥 💪 ⚙️ `__init__` 📣 🔢 👐 👈 👥 💪 ⚙️ "🔗" 🔗:
|
||||||
|
|
||||||
|
{* ../../docs_src/dependencies/tutorial011.py hl[7] *}
|
||||||
|
|
||||||
|
👉 💼, **FastAPI** 🏆 🚫 ⏱ 👆 ⚖️ 💅 🔃 `__init__`, 👥 🔜 ⚙️ ⚫️ 🔗 👆 📟.
|
||||||
|
|
||||||
|
## ✍ 👐
|
||||||
|
|
||||||
|
👥 💪 ✍ 👐 👉 🎓 ⏮️:
|
||||||
|
|
||||||
|
{* ../../docs_src/dependencies/tutorial011.py hl[16] *}
|
||||||
|
|
||||||
|
& 👈 🌌 👥 💪 "🔗" 👆 🔗, 👈 🔜 ✔️ `"bar"` 🔘 ⚫️, 🔢 `checker.fixed_content`.
|
||||||
|
|
||||||
|
## ⚙️ 👐 🔗
|
||||||
|
|
||||||
|
⤴️, 👥 💪 ⚙️ 👉 `checker` `Depends(checker)`, ↩️ `Depends(FixedContentQueryChecker)`, ↩️ 🔗 👐, `checker`, 🚫 🎓 ⚫️.
|
||||||
|
|
||||||
|
& 🕐❔ ❎ 🔗, **FastAPI** 🔜 🤙 👉 `checker` 💖:
|
||||||
|
|
||||||
|
```Python
|
||||||
|
checker(q="somequery")
|
||||||
|
```
|
||||||
|
|
||||||
|
...& 🚶♀️ ⚫️❔ 👈 📨 💲 🔗 👆 *➡ 🛠️ 🔢* 🔢 `fixed_content_included`:
|
||||||
|
|
||||||
|
{* ../../docs_src/dependencies/tutorial011.py hl[20] *}
|
||||||
|
|
||||||
|
/// tip
|
||||||
|
|
||||||
|
🌐 👉 💪 😑 🎭. & ⚫️ 💪 🚫 📶 🆑 ❔ ⚫️ ⚠.
|
||||||
|
|
||||||
|
👫 🖼 😫 🙅, ✋️ 🎦 ❔ ⚫️ 🌐 👷.
|
||||||
|
|
||||||
|
📃 🔃 💂♂, 📤 🚙 🔢 👈 🛠️ 👉 🎏 🌌.
|
||||||
|
|
||||||
|
🚥 👆 🤔 🌐 👉, 👆 ⏪ 💭 ❔ 👈 🚙 🧰 💂♂ 👷 🔘.
|
||||||
|
|
||||||
|
///
|
||||||
|
|
@ -0,0 +1,93 @@
|
||||||
|
# 🔁 💯
|
||||||
|
|
||||||
|
👆 ✔️ ⏪ 👀 ❔ 💯 👆 **FastAPI** 🈸 ⚙️ 🚚 `TestClient`. 🆙 🔜, 👆 ✔️ 🕴 👀 ❔ ✍ 🔁 💯, 🍵 ⚙️ `async` 🔢.
|
||||||
|
|
||||||
|
➖ 💪 ⚙️ 🔁 🔢 👆 💯 💪 ⚠, 🖼, 🕐❔ 👆 🔬 👆 💽 🔁. 🌈 👆 💚 💯 📨 📨 👆 FastAPI 🈸 & ⤴️ ✔ 👈 👆 👩💻 ⏪ ✍ ☑ 💽 💽, ⏪ ⚙️ 🔁 💽 🗃.
|
||||||
|
|
||||||
|
➡️ 👀 ❔ 👥 💪 ⚒ 👈 👷.
|
||||||
|
|
||||||
|
## pytest.mark.anyio
|
||||||
|
|
||||||
|
🚥 👥 💚 🤙 🔁 🔢 👆 💯, 👆 💯 🔢 ✔️ 🔁. AnyIO 🚚 👌 📁 👉, 👈 ✔ 👥 ✔ 👈 💯 🔢 🤙 🔁.
|
||||||
|
|
||||||
|
## 🇸🇲
|
||||||
|
|
||||||
|
🚥 👆 **FastAPI** 🈸 ⚙️ 😐 `def` 🔢 ↩️ `async def`, ⚫️ `async` 🈸 🔘.
|
||||||
|
|
||||||
|
`TestClient` 🔨 🎱 🔘 🤙 🔁 FastAPI 🈸 👆 😐 `def` 💯 🔢, ⚙️ 🐩 ✳. ✋️ 👈 🎱 🚫 👷 🚫🔜 🕐❔ 👥 ⚙️ ⚫️ 🔘 🔁 🔢. 🏃 👆 💯 🔁, 👥 💪 🙅♂ 📏 ⚙️ `TestClient` 🔘 👆 💯 🔢.
|
||||||
|
|
||||||
|
`TestClient` ⚓️ 🔛 <a href="https://www.python-httpx.org" class="external-link" target="_blank">🇸🇲</a>, & ↩️, 👥 💪 ⚙️ ⚫️ 🔗 💯 🛠️.
|
||||||
|
|
||||||
|
## 🖼
|
||||||
|
|
||||||
|
🙅 🖼, ➡️ 🤔 📁 📊 🎏 1️⃣ 🔬 [🦏 🈸](../tutorial/bigger-applications.md){.internal-link target=_blank} & [🔬](../tutorial/testing.md){.internal-link target=_blank}:
|
||||||
|
|
||||||
|
```
|
||||||
|
.
|
||||||
|
├── app
|
||||||
|
│ ├── __init__.py
|
||||||
|
│ ├── main.py
|
||||||
|
│ └── test_main.py
|
||||||
|
```
|
||||||
|
|
||||||
|
📁 `main.py` 🔜 ✔️:
|
||||||
|
|
||||||
|
{* ../../docs_src/async_tests/main.py *}
|
||||||
|
|
||||||
|
📁 `test_main.py` 🔜 ✔️ 💯 `main.py`, ⚫️ 💪 👀 💖 👉 🔜:
|
||||||
|
|
||||||
|
{* ../../docs_src/async_tests/test_main.py *}
|
||||||
|
|
||||||
|
## 🏃 ⚫️
|
||||||
|
|
||||||
|
👆 💪 🏃 👆 💯 🐌 📨:
|
||||||
|
|
||||||
|
<div class="termy">
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ pytest
|
||||||
|
|
||||||
|
---> 100%
|
||||||
|
```
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
## ℹ
|
||||||
|
|
||||||
|
📑 `@pytest.mark.anyio` 💬 ✳ 👈 👉 💯 🔢 🔜 🤙 🔁:
|
||||||
|
|
||||||
|
{* ../../docs_src/async_tests/test_main.py hl[7] *}
|
||||||
|
|
||||||
|
/// tip
|
||||||
|
|
||||||
|
🗒 👈 💯 🔢 🔜 `async def` ↩️ `def` ⏭ 🕐❔ ⚙️ `TestClient`.
|
||||||
|
|
||||||
|
///
|
||||||
|
|
||||||
|
⤴️ 👥 💪 ✍ `AsyncClient` ⏮️ 📱, & 📨 🔁 📨 ⚫️, ⚙️ `await`.
|
||||||
|
|
||||||
|
{* ../../docs_src/async_tests/test_main.py hl[9:12] *}
|
||||||
|
|
||||||
|
👉 🌓:
|
||||||
|
|
||||||
|
```Python
|
||||||
|
response = client.get('/')
|
||||||
|
```
|
||||||
|
|
||||||
|
...👈 👥 ⚙️ ⚒ 👆 📨 ⏮️ `TestClient`.
|
||||||
|
|
||||||
|
/// tip
|
||||||
|
|
||||||
|
🗒 👈 👥 ⚙️ 🔁/⌛ ⏮️ 🆕 `AsyncClient` - 📨 🔁.
|
||||||
|
|
||||||
|
///
|
||||||
|
|
||||||
|
## 🎏 🔁 🔢 🤙
|
||||||
|
|
||||||
|
🔬 🔢 🔜 🔁, 👆 💪 🔜 🤙 (& `await`) 🎏 `async` 🔢 ↖️ ⚪️➡️ 📨 📨 👆 FastAPI 🈸 👆 💯, ⚫️❔ 👆 🔜 🤙 👫 🙆 🙆 👆 📟.
|
||||||
|
|
||||||
|
/// tip
|
||||||
|
|
||||||
|
🚥 👆 ⚔ `RuntimeError: Task attached to a different loop` 🕐❔ 🛠️ 🔁 🔢 🤙 👆 💯 (✅ 🕐❔ ⚙️ <a href="https://stackoverflow.com/questions/41584243/runtimeerror-task-attached-to-a-different-loop" class="external-link" target="_blank">✳ MotorClient</a>) 💭 🔗 🎚 👈 💪 🎉 ➰ 🕴 🏞 🔁 🔢, ✅ `'@app.on_event("startup")` ⏲.
|
||||||
|
|
||||||
|
///
|
||||||
|
|
@ -0,0 +1,359 @@
|
||||||
|
# ⛅ 🗳
|
||||||
|
|
||||||
|
⚠, 👆 5️⃣📆 💪 ⚙️ **🗳** 💽 💖 Traefik ⚖️ 👌 ⏮️ 📳 👈 🚮 ➕ ➡ 🔡 👈 🚫 👀 👆 🈸.
|
||||||
|
|
||||||
|
👫 💼 👆 💪 ⚙️ `root_path` 🔗 👆 🈸.
|
||||||
|
|
||||||
|
`root_path` 🛠️ 🚚 🔫 🔧 (👈 FastAPI 🏗 🔛, 🔘 💃).
|
||||||
|
|
||||||
|
`root_path` ⚙️ 🍵 👫 🎯 💼.
|
||||||
|
|
||||||
|
& ⚫️ ⚙️ 🔘 🕐❔ 🗜 🎧-🈸.
|
||||||
|
|
||||||
|
## 🗳 ⏮️ 🎞 ➡ 🔡
|
||||||
|
|
||||||
|
✔️ 🗳 ⏮️ 🎞 ➡ 🔡, 👉 💼, ⛓ 👈 👆 💪 📣 ➡ `/app` 👆 📟, ✋️ ⤴️, 👆 🚮 🧽 🔛 🔝 (🗳) 👈 🔜 🚮 👆 **FastAPI** 🈸 🔽 ➡ 💖 `/api/v1`.
|
||||||
|
|
||||||
|
👉 💼, ⏮️ ➡ `/app` 🔜 🤙 🍦 `/api/v1/app`.
|
||||||
|
|
||||||
|
✋️ 🌐 👆 📟 ✍ 🤔 📤 `/app`.
|
||||||
|
|
||||||
|
& 🗳 🔜 **"❎"** **➡ 🔡** 🔛 ✈ ⏭ 📶 📨 Uvicorn, 🚧 👆 🈸 🤔 👈 ⚫️ 🍦 `/app`, 👈 👆 🚫 ✔️ ℹ 🌐 👆 📟 🔌 🔡 `/api/v1`.
|
||||||
|
|
||||||
|
🆙 📥, 🌐 🔜 👷 🛎.
|
||||||
|
|
||||||
|
✋️ ⤴️, 🕐❔ 👆 📂 🛠️ 🩺 🎚 (🕸), ⚫️ 🔜 ⌛ 🤚 🗄 🔗 `/openapi.json`, ↩️ `/api/v1/openapi.json`.
|
||||||
|
|
||||||
|
, 🕸 (👈 🏃 🖥) 🔜 🔄 🏆 `/openapi.json` & 🚫🔜 💪 🤚 🗄 🔗.
|
||||||
|
|
||||||
|
↩️ 👥 ✔️ 🗳 ⏮️ ➡ 🔡 `/api/v1` 👆 📱, 🕸 💪 ☕ 🗄 🔗 `/api/v1/openapi.json`.
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
graph LR
|
||||||
|
|
||||||
|
browser("Browser")
|
||||||
|
proxy["Proxy on http://0.0.0.0:9999/api/v1/app"]
|
||||||
|
server["Server on http://127.0.0.1:8000/app"]
|
||||||
|
|
||||||
|
browser --> proxy
|
||||||
|
proxy --> server
|
||||||
|
```
|
||||||
|
|
||||||
|
/// tip
|
||||||
|
|
||||||
|
📢 `0.0.0.0` 🛎 ⚙️ ⛓ 👈 📋 👂 🔛 🌐 📢 💪 👈 🎰/💽.
|
||||||
|
|
||||||
|
///
|
||||||
|
|
||||||
|
🩺 🎚 🔜 💪 🗄 🔗 📣 👈 👉 🛠️ `server` 🔎 `/api/v1` (⛅ 🗳). 🖼:
|
||||||
|
|
||||||
|
```JSON hl_lines="4-8"
|
||||||
|
{
|
||||||
|
"openapi": "3.0.2",
|
||||||
|
// More stuff here
|
||||||
|
"servers": [
|
||||||
|
{
|
||||||
|
"url": "/api/v1"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"paths": {
|
||||||
|
// More stuff here
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
👉 🖼, "🗳" 💪 🕳 💖 **Traefik**. & 💽 🔜 🕳 💖 **Uvicorn**, 🏃♂ 👆 FastAPI 🈸.
|
||||||
|
|
||||||
|
### 🚚 `root_path`
|
||||||
|
|
||||||
|
🏆 👉, 👆 💪 ⚙️ 📋 ⏸ 🎛 `--root-path` 💖:
|
||||||
|
|
||||||
|
<div class="termy">
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ uvicorn main:app --root-path /api/v1
|
||||||
|
|
||||||
|
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
|
||||||
|
```
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
🚥 👆 ⚙️ Hypercorn, ⚫️ ✔️ 🎛 `--root-path`.
|
||||||
|
|
||||||
|
/// note | 📡 ℹ
|
||||||
|
|
||||||
|
🔫 🔧 🔬 `root_path` 👉 ⚙️ 💼.
|
||||||
|
|
||||||
|
& `--root-path` 📋 ⏸ 🎛 🚚 👈 `root_path`.
|
||||||
|
|
||||||
|
///
|
||||||
|
|
||||||
|
### ✅ ⏮️ `root_path`
|
||||||
|
|
||||||
|
👆 💪 🤚 ⏮️ `root_path` ⚙️ 👆 🈸 🔠 📨, ⚫️ 🍕 `scope` 📖 (👈 🍕 🔫 🔌).
|
||||||
|
|
||||||
|
📥 👥 ✅ ⚫️ 📧 🎦 🎯.
|
||||||
|
|
||||||
|
{* ../../docs_src/behind_a_proxy/tutorial001.py hl[8] *}
|
||||||
|
|
||||||
|
⤴️, 🚥 👆 ▶️ Uvicorn ⏮️:
|
||||||
|
|
||||||
|
<div class="termy">
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ uvicorn main:app --root-path /api/v1
|
||||||
|
|
||||||
|
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
|
||||||
|
```
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
📨 🔜 🕳 💖:
|
||||||
|
|
||||||
|
```JSON
|
||||||
|
{
|
||||||
|
"message": "Hello World",
|
||||||
|
"root_path": "/api/v1"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### ⚒ `root_path` FastAPI 📱
|
||||||
|
|
||||||
|
👐, 🚥 👆 🚫 ✔️ 🌌 🚚 📋 ⏸ 🎛 💖 `--root-path` ⚖️ 🌓, 👆 💪 ⚒ `root_path` 🔢 🕐❔ 🏗 👆 FastAPI 📱:
|
||||||
|
|
||||||
|
{* ../../docs_src/behind_a_proxy/tutorial002.py hl[3] *}
|
||||||
|
|
||||||
|
🚶♀️ `root_path` `FastAPI` 🔜 🌓 🚶♀️ `--root-path` 📋 ⏸ 🎛 Uvicorn ⚖️ Hypercorn.
|
||||||
|
|
||||||
|
### 🔃 `root_path`
|
||||||
|
|
||||||
|
✔️ 🤯 👈 💽 (Uvicorn) 🏆 🚫 ⚙️ 👈 `root_path` 🕳 🙆 🌘 🚶♀️ ⚫️ 📱.
|
||||||
|
|
||||||
|
✋️ 🚥 👆 🚶 ⏮️ 👆 🖥 <a href="http://127.0.0.1:8000" class="external-link" target="_blank">http://127.0.0.1:8000/app</a> 👆 🔜 👀 😐 📨:
|
||||||
|
|
||||||
|
```JSON
|
||||||
|
{
|
||||||
|
"message": "Hello World",
|
||||||
|
"root_path": "/api/v1"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
, ⚫️ 🏆 🚫 ⌛ 🔐 `http://127.0.0.1:8000/api/v1/app`.
|
||||||
|
|
||||||
|
Uvicorn 🔜 ⌛ 🗳 🔐 Uvicorn `http://127.0.0.1:8000/app`, & ⤴️ ⚫️ 🔜 🗳 🎯 🚮 ➕ `/api/v1` 🔡 🔛 🔝.
|
||||||
|
|
||||||
|
## 🔃 🗳 ⏮️ 🎞 ➡ 🔡
|
||||||
|
|
||||||
|
✔️ 🤯 👈 🗳 ⏮️ 🎞 ➡ 🔡 🕴 1️⃣ 🌌 🔗 ⚫️.
|
||||||
|
|
||||||
|
🎲 📚 💼 🔢 🔜 👈 🗳 🚫 ✔️ 🏚 ➡ 🔡.
|
||||||
|
|
||||||
|
💼 💖 👈 (🍵 🎞 ➡ 🔡), 🗳 🔜 👂 🔛 🕳 💖 `https://myawesomeapp.com`, & ⤴️ 🚥 🖥 🚶 `https://myawesomeapp.com/api/v1/app` & 👆 💽 (✅ Uvicorn) 👂 🔛 `http://127.0.0.1:8000` 🗳 (🍵 🎞 ➡ 🔡) 🔜 🔐 Uvicorn 🎏 ➡: `http://127.0.0.1:8000/api/v1/app`.
|
||||||
|
|
||||||
|
## 🔬 🌐 ⏮️ Traefik
|
||||||
|
|
||||||
|
👆 💪 💪 🏃 🥼 🌐 ⏮️ 🎞 ➡ 🔡 ⚙️ <a href="https://docs.traefik.io/" class="external-link" target="_blank">Traefik</a>.
|
||||||
|
|
||||||
|
<a href="https://github.com/containous/traefik/releases" class="external-link" target="_blank">⏬ Traefik</a>, ⚫️ 👁 💱, 👆 💪 ⚗ 🗜 📁 & 🏃 ⚫️ 🔗 ⚪️➡️ 📶.
|
||||||
|
|
||||||
|
⤴️ ✍ 📁 `traefik.toml` ⏮️:
|
||||||
|
|
||||||
|
```TOML hl_lines="3"
|
||||||
|
[entryPoints]
|
||||||
|
[entryPoints.http]
|
||||||
|
address = ":9999"
|
||||||
|
|
||||||
|
[providers]
|
||||||
|
[providers.file]
|
||||||
|
filename = "routes.toml"
|
||||||
|
```
|
||||||
|
|
||||||
|
👉 💬 Traefik 👂 🔛 ⛴ 9️⃣9️⃣9️⃣9️⃣ & ⚙️ ➕1️⃣ 📁 `routes.toml`.
|
||||||
|
|
||||||
|
/// tip
|
||||||
|
|
||||||
|
👥 ⚙️ ⛴ 9️⃣9️⃣9️⃣9️⃣ ↩️ 🐩 🇺🇸🔍 ⛴ 8️⃣0️⃣ 👈 👆 🚫 ✔️ 🏃 ⚫️ ⏮️ 📡 (`sudo`) 😌.
|
||||||
|
|
||||||
|
///
|
||||||
|
|
||||||
|
🔜 ✍ 👈 🎏 📁 `routes.toml`:
|
||||||
|
|
||||||
|
```TOML hl_lines="5 12 20"
|
||||||
|
[http]
|
||||||
|
[http.middlewares]
|
||||||
|
|
||||||
|
[http.middlewares.api-stripprefix.stripPrefix]
|
||||||
|
prefixes = ["/api/v1"]
|
||||||
|
|
||||||
|
[http.routers]
|
||||||
|
|
||||||
|
[http.routers.app-http]
|
||||||
|
entryPoints = ["http"]
|
||||||
|
service = "app"
|
||||||
|
rule = "PathPrefix(`/api/v1`)"
|
||||||
|
middlewares = ["api-stripprefix"]
|
||||||
|
|
||||||
|
[http.services]
|
||||||
|
|
||||||
|
[http.services.app]
|
||||||
|
[http.services.app.loadBalancer]
|
||||||
|
[[http.services.app.loadBalancer.servers]]
|
||||||
|
url = "http://127.0.0.1:8000"
|
||||||
|
```
|
||||||
|
|
||||||
|
👉 📁 🔗 Traefik ⚙️ ➡ 🔡 `/api/v1`.
|
||||||
|
|
||||||
|
& ⤴️ ⚫️ 🔜 ❎ 🚮 📨 👆 Uvicorn 🏃♂ 🔛 `http://127.0.0.1:8000`.
|
||||||
|
|
||||||
|
🔜 ▶️ Traefik:
|
||||||
|
|
||||||
|
<div class="termy">
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ ./traefik --configFile=traefik.toml
|
||||||
|
|
||||||
|
INFO[0000] Configuration loaded from file: /home/user/awesomeapi/traefik.toml
|
||||||
|
```
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
& 🔜 ▶️ 👆 📱 ⏮️ Uvicorn, ⚙️ `--root-path` 🎛:
|
||||||
|
|
||||||
|
<div class="termy">
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ uvicorn main:app --root-path /api/v1
|
||||||
|
|
||||||
|
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
|
||||||
|
```
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
### ✅ 📨
|
||||||
|
|
||||||
|
🔜, 🚥 👆 🚶 📛 ⏮️ ⛴ Uvicorn: <a href="http://127.0.0.1:8000/app" class="external-link" target="_blank">http://127.0.0.1:8000/app</a>, 👆 🔜 👀 😐 📨:
|
||||||
|
|
||||||
|
```JSON
|
||||||
|
{
|
||||||
|
"message": "Hello World",
|
||||||
|
"root_path": "/api/v1"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
/// tip
|
||||||
|
|
||||||
|
👀 👈 ✋️ 👆 🔐 ⚫️ `http://127.0.0.1:8000/app` ⚫️ 🎦 `root_path` `/api/v1`, ✊ ⚪️➡️ 🎛 `--root-path`.
|
||||||
|
|
||||||
|
///
|
||||||
|
|
||||||
|
& 🔜 📂 📛 ⏮️ ⛴ Traefik, ✅ ➡ 🔡: <a href="http://127.0.0.1:9999/api/v1/app" class="external-link" target="_blank">http://127.0.0.1:9999/api/v1/app</a>.
|
||||||
|
|
||||||
|
👥 🤚 🎏 📨:
|
||||||
|
|
||||||
|
```JSON
|
||||||
|
{
|
||||||
|
"message": "Hello World",
|
||||||
|
"root_path": "/api/v1"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
✋️ 👉 🕰 📛 ⏮️ 🔡 ➡ 🚚 🗳: `/api/v1`.
|
||||||
|
|
||||||
|
↗️, 💭 📥 👈 👱 🔜 🔐 📱 🔘 🗳, ⏬ ⏮️ ➡ 🔡 `/app/v1` "☑" 1️⃣.
|
||||||
|
|
||||||
|
& ⏬ 🍵 ➡ 🔡 (`http://127.0.0.1:8000/app`), 🚚 Uvicorn 🔗, 🔜 🎯 _🗳_ (Traefik) 🔐 ⚫️.
|
||||||
|
|
||||||
|
👈 🎦 ❔ 🗳 (Traefik) ⚙️ ➡ 🔡 & ❔ 💽 (Uvicorn) ⚙️ `root_path` ⚪️➡️ 🎛 `--root-path`.
|
||||||
|
|
||||||
|
### ✅ 🩺 🎚
|
||||||
|
|
||||||
|
✋️ 📥 🎊 🍕. 👶
|
||||||
|
|
||||||
|
"🛂" 🌌 🔐 📱 🔜 🔘 🗳 ⏮️ ➡ 🔡 👈 👥 🔬. , 👥 🔜 ⌛, 🚥 👆 🔄 🩺 🎚 🍦 Uvicorn 🔗, 🍵 ➡ 🔡 📛, ⚫️ 🏆 🚫 👷, ↩️ ⚫️ ⌛ 🔐 🔘 🗳.
|
||||||
|
|
||||||
|
👆 💪 ✅ ⚫️ <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>:
|
||||||
|
|
||||||
|
<img src="/img/tutorial/behind-a-proxy/image01.png">
|
||||||
|
|
||||||
|
✋️ 🚥 👥 🔐 🩺 🎚 "🛂" 📛 ⚙️ 🗳 ⏮️ ⛴ `9999`, `/api/v1/docs`, ⚫️ 👷 ☑ ❗ 👶
|
||||||
|
|
||||||
|
👆 💪 ✅ ⚫️ <a href="http://127.0.0.1:9999/api/v1/docs" class="external-link" target="_blank">http://127.0.0.1:9999/api/v1/docs</a>:
|
||||||
|
|
||||||
|
<img src="/img/tutorial/behind-a-proxy/image02.png">
|
||||||
|
|
||||||
|
▶️️ 👥 💚 ⚫️. 👶 👶
|
||||||
|
|
||||||
|
👉 ↩️ FastAPI ⚙️ 👉 `root_path` ✍ 🔢 `server` 🗄 ⏮️ 📛 🚚 `root_path`.
|
||||||
|
|
||||||
|
## 🌖 💽
|
||||||
|
|
||||||
|
/// warning
|
||||||
|
|
||||||
|
👉 🌅 🏧 ⚙️ 💼. 💭 🆓 🚶 ⚫️.
|
||||||
|
|
||||||
|
///
|
||||||
|
|
||||||
|
🔢, **FastAPI** 🔜 ✍ `server` 🗄 🔗 ⏮️ 📛 `root_path`.
|
||||||
|
|
||||||
|
✋️ 👆 💪 🚚 🎏 🎛 `servers`, 🖼 🚥 👆 💚 *🎏* 🩺 🎚 🔗 ⏮️ 🏗 & 🏭 🌐.
|
||||||
|
|
||||||
|
🚥 👆 🚶♀️ 🛃 📇 `servers` & 📤 `root_path` (↩️ 👆 🛠️ 👨❤👨 ⛅ 🗳), **FastAPI** 🔜 📩 "💽" ⏮️ 👉 `root_path` ▶️ 📇.
|
||||||
|
|
||||||
|
🖼:
|
||||||
|
|
||||||
|
{* ../../docs_src/behind_a_proxy/tutorial003.py hl[4:7] *}
|
||||||
|
|
||||||
|
🔜 🏗 🗄 🔗 💖:
|
||||||
|
|
||||||
|
```JSON hl_lines="5-7"
|
||||||
|
{
|
||||||
|
"openapi": "3.0.2",
|
||||||
|
// More stuff here
|
||||||
|
"servers": [
|
||||||
|
{
|
||||||
|
"url": "/api/v1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://stag.example.com",
|
||||||
|
"description": "Staging environment"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://prod.example.com",
|
||||||
|
"description": "Production environment"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"paths": {
|
||||||
|
// More stuff here
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
/// tip
|
||||||
|
|
||||||
|
👀 🚘-🏗 💽 ⏮️ `url` 💲 `/api/v1`, ✊ ⚪️➡️ `root_path`.
|
||||||
|
|
||||||
|
///
|
||||||
|
|
||||||
|
🩺 🎚 <a href="http://127.0.0.1:9999/api/v1/docs" class="external-link" target="_blank">http://127.0.0.1:9999/api/v1/docs</a> ⚫️ 🔜 👀 💖:
|
||||||
|
|
||||||
|
<img src="/img/tutorial/behind-a-proxy/image03.png">
|
||||||
|
|
||||||
|
/// tip
|
||||||
|
|
||||||
|
🩺 🎚 🔜 🔗 ⏮️ 💽 👈 👆 🖊.
|
||||||
|
|
||||||
|
///
|
||||||
|
|
||||||
|
### ❎ 🏧 💽 ⚪️➡️ `root_path`
|
||||||
|
|
||||||
|
🚥 👆 🚫 💚 **FastAPI** 🔌 🏧 💽 ⚙️ `root_path`, 👆 💪 ⚙️ 🔢 `root_path_in_servers=False`:
|
||||||
|
|
||||||
|
{* ../../docs_src/behind_a_proxy/tutorial004.py hl[9] *}
|
||||||
|
|
||||||
|
& ⤴️ ⚫️ 🏆 🚫 🔌 ⚫️ 🗄 🔗.
|
||||||
|
|
||||||
|
## 🗜 🎧-🈸
|
||||||
|
|
||||||
|
🚥 👆 💪 🗻 🎧-🈸 (🔬 [🎧 🈸 - 🗻](sub-applications.md){.internal-link target=_blank}) ⏪ ⚙️ 🗳 ⏮️ `root_path`, 👆 💪 ⚫️ 🛎, 👆 🔜 ⌛.
|
||||||
|
|
||||||
|
FastAPI 🔜 🔘 ⚙️ `root_path` 🎆, ⚫️ 🔜 👷. 👶
|
||||||
|
|
@ -0,0 +1,303 @@
|
||||||
|
# 🛃 📨 - 🕸, 🎏, 📁, 🎏
|
||||||
|
|
||||||
|
🔢, **FastAPI** 🔜 📨 📨 ⚙️ `JSONResponse`.
|
||||||
|
|
||||||
|
👆 💪 🔐 ⚫️ 🛬 `Response` 🔗 👀 [📨 📨 🔗](response-directly.md){.internal-link target=_blank}.
|
||||||
|
|
||||||
|
✋️ 🚥 👆 📨 `Response` 🔗, 📊 🏆 🚫 🔁 🗜, & 🧾 🏆 🚫 🔁 🏗 (🖼, 🔌 🎯 "📻 🆎", 🇺🇸🔍 🎚 `Content-Type` 🍕 🏗 🗄).
|
||||||
|
|
||||||
|
✋️ 👆 💪 📣 `Response` 👈 👆 💚 ⚙️, *➡ 🛠️ 👨🎨*.
|
||||||
|
|
||||||
|
🎚 👈 👆 📨 ⚪️➡️ 👆 *➡ 🛠️ 🔢* 🔜 🚮 🔘 👈 `Response`.
|
||||||
|
|
||||||
|
& 🚥 👈 `Response` ✔️ 🎻 📻 🆎 (`application/json`), 💖 💼 ⏮️ `JSONResponse` & `UJSONResponse`, 💽 👆 📨 🔜 🔁 🗜 (& ⛽) ⏮️ 🙆 Pydantic `response_model` 👈 👆 📣 *➡ 🛠️ 👨🎨*.
|
||||||
|
|
||||||
|
/// note
|
||||||
|
|
||||||
|
🚥 👆 ⚙️ 📨 🎓 ⏮️ 🙅♂ 📻 🆎, FastAPI 🔜 ⌛ 👆 📨 ✔️ 🙅♂ 🎚, ⚫️ 🔜 🚫 📄 📨 📁 🚮 🏗 🗄 🩺.
|
||||||
|
|
||||||
|
///
|
||||||
|
|
||||||
|
## ⚙️ `ORJSONResponse`
|
||||||
|
|
||||||
|
🖼, 🚥 👆 ✊ 🎭, 👆 💪 ❎ & ⚙️ <a href="https://github.com/ijl/orjson" class="external-link" target="_blank">`orjson`</a> & ⚒ 📨 `ORJSONResponse`.
|
||||||
|
|
||||||
|
🗄 `Response` 🎓 (🎧-🎓) 👆 💚 ⚙️ & 📣 ⚫️ *➡ 🛠️ 👨🎨*.
|
||||||
|
|
||||||
|
⭕ 📨, 📨 `Response` 🔗 🌅 ⏩ 🌘 🛬 📖.
|
||||||
|
|
||||||
|
👉 ↩️ 🔢, FastAPI 🔜 ✔ 🔠 🏬 🔘 & ⚒ 💭 ⚫️ 🎻 ⏮️ 🎻, ⚙️ 🎏 [🎻 🔗 🔢](../tutorial/encoder.md){.internal-link target=_blank} 🔬 🔰. 👉 ⚫️❔ ✔ 👆 📨 **❌ 🎚**, 🖼 💽 🏷.
|
||||||
|
|
||||||
|
✋️ 🚥 👆 🎯 👈 🎚 👈 👆 🛬 **🎻 ⏮️ 🎻**, 👆 💪 🚶♀️ ⚫️ 🔗 📨 🎓 & ❎ ➕ 🌥 👈 FastAPI 🔜 ✔️ 🚶♀️ 👆 📨 🎚 🔘 `jsonable_encoder` ⏭ 🚶♀️ ⚫️ 📨 🎓.
|
||||||
|
|
||||||
|
{* ../../docs_src/custom_response/tutorial001b.py hl[2,7] *}
|
||||||
|
|
||||||
|
/// info
|
||||||
|
|
||||||
|
🔢 `response_class` 🔜 ⚙️ 🔬 "📻 🆎" 📨.
|
||||||
|
|
||||||
|
👉 💼, 🇺🇸🔍 🎚 `Content-Type` 🔜 ⚒ `application/json`.
|
||||||
|
|
||||||
|
& ⚫️ 🔜 📄 ✅ 🗄.
|
||||||
|
|
||||||
|
///
|
||||||
|
|
||||||
|
/// tip
|
||||||
|
|
||||||
|
`ORJSONResponse` ⏳ 🕴 💪 FastAPI, 🚫 💃.
|
||||||
|
|
||||||
|
///
|
||||||
|
|
||||||
|
## 🕸 📨
|
||||||
|
|
||||||
|
📨 📨 ⏮️ 🕸 🔗 ⚪️➡️ **FastAPI**, ⚙️ `HTMLResponse`.
|
||||||
|
|
||||||
|
* 🗄 `HTMLResponse`.
|
||||||
|
* 🚶♀️ `HTMLResponse` 🔢 `response_class` 👆 *➡ 🛠️ 👨🎨*.
|
||||||
|
|
||||||
|
{* ../../docs_src/custom_response/tutorial002.py hl[2,7] *}
|
||||||
|
|
||||||
|
/// info
|
||||||
|
|
||||||
|
🔢 `response_class` 🔜 ⚙️ 🔬 "📻 🆎" 📨.
|
||||||
|
|
||||||
|
👉 💼, 🇺🇸🔍 🎚 `Content-Type` 🔜 ⚒ `text/html`.
|
||||||
|
|
||||||
|
& ⚫️ 🔜 📄 ✅ 🗄.
|
||||||
|
|
||||||
|
///
|
||||||
|
|
||||||
|
### 📨 `Response`
|
||||||
|
|
||||||
|
👀 [📨 📨 🔗](response-directly.md){.internal-link target=_blank}, 👆 💪 🔐 📨 🔗 👆 *➡ 🛠️*, 🛬 ⚫️.
|
||||||
|
|
||||||
|
🎏 🖼 ⚪️➡️ 🔛, 🛬 `HTMLResponse`, 💪 👀 💖:
|
||||||
|
|
||||||
|
{* ../../docs_src/custom_response/tutorial003.py hl[2,7,19] *}
|
||||||
|
|
||||||
|
/// warning
|
||||||
|
|
||||||
|
`Response` 📨 🔗 👆 *➡ 🛠️ 🔢* 🏆 🚫 📄 🗄 (🖼, `Content-Type` 🏆 🚫 📄) & 🏆 🚫 ⭐ 🏧 🎓 🩺.
|
||||||
|
|
||||||
|
///
|
||||||
|
|
||||||
|
/// info
|
||||||
|
|
||||||
|
↗️, ☑ `Content-Type` 🎚, 👔 📟, ♒️, 🔜 👟 ⚪️➡️ `Response` 🎚 👆 📨.
|
||||||
|
|
||||||
|
///
|
||||||
|
|
||||||
|
### 📄 🗄 & 🔐 `Response`
|
||||||
|
|
||||||
|
🚥 👆 💚 🔐 📨 ⚪️➡️ 🔘 🔢 ✋️ 🎏 🕰 📄 "📻 🆎" 🗄, 👆 💪 ⚙️ `response_class` 🔢 & 📨 `Response` 🎚.
|
||||||
|
|
||||||
|
`response_class` 🔜 ⤴️ ⚙️ 🕴 📄 🗄 *➡ 🛠️*, ✋️ 👆 `Response` 🔜 ⚙️.
|
||||||
|
|
||||||
|
#### 📨 `HTMLResponse` 🔗
|
||||||
|
|
||||||
|
🖼, ⚫️ 💪 🕳 💖:
|
||||||
|
|
||||||
|
{* ../../docs_src/custom_response/tutorial004.py hl[7,21,23] *}
|
||||||
|
|
||||||
|
👉 🖼, 🔢 `generate_html_response()` ⏪ 🏗 & 📨 `Response` ↩️ 🛬 🕸 `str`.
|
||||||
|
|
||||||
|
🛬 🏁 🤙 `generate_html_response()`, 👆 ⏪ 🛬 `Response` 👈 🔜 🔐 🔢 **FastAPI** 🎭.
|
||||||
|
|
||||||
|
✋️ 👆 🚶♀️ `HTMLResponse` `response_class` 💁♂️, **FastAPI** 🔜 💭 ❔ 📄 ⚫️ 🗄 & 🎓 🩺 🕸 ⏮️ `text/html`:
|
||||||
|
|
||||||
|
<img src="/img/tutorial/custom-response/image01.png">
|
||||||
|
|
||||||
|
## 💪 📨
|
||||||
|
|
||||||
|
📥 💪 📨.
|
||||||
|
|
||||||
|
✔️ 🤯 👈 👆 💪 ⚙️ `Response` 📨 🕳 🙆, ⚖️ ✍ 🛃 🎧-🎓.
|
||||||
|
|
||||||
|
/// note | 📡 ℹ
|
||||||
|
|
||||||
|
👆 💪 ⚙️ `from starlette.responses import HTMLResponse`.
|
||||||
|
|
||||||
|
**FastAPI** 🚚 🎏 `starlette.responses` `fastapi.responses` 🏪 👆, 👩💻. ✋️ 🌅 💪 📨 👟 🔗 ⚪️➡️ 💃.
|
||||||
|
|
||||||
|
///
|
||||||
|
|
||||||
|
### `Response`
|
||||||
|
|
||||||
|
👑 `Response` 🎓, 🌐 🎏 📨 😖 ⚪️➡️ ⚫️.
|
||||||
|
|
||||||
|
👆 💪 📨 ⚫️ 🔗.
|
||||||
|
|
||||||
|
⚫️ 🚫 📄 🔢:
|
||||||
|
|
||||||
|
* `content` - `str` ⚖️ `bytes`.
|
||||||
|
* `status_code` - `int` 🇺🇸🔍 👔 📟.
|
||||||
|
* `headers` - `dict` 🎻.
|
||||||
|
* `media_type` - `str` 🤝 📻 🆎. 🤶 Ⓜ. `"text/html"`.
|
||||||
|
|
||||||
|
FastAPI (🤙 💃) 🔜 🔁 🔌 🎚-📐 🎚. ⚫️ 🔜 🔌 🎚-🆎 🎚, ⚓️ 🔛 = & 🔁 = ✍ 🆎.
|
||||||
|
|
||||||
|
{* ../../docs_src/response_directly/tutorial002.py hl[1,18] *}
|
||||||
|
|
||||||
|
### `HTMLResponse`
|
||||||
|
|
||||||
|
✊ ✍ ⚖️ 🔢 & 📨 🕸 📨, 👆 ✍ 🔛.
|
||||||
|
|
||||||
|
### `PlainTextResponse`
|
||||||
|
|
||||||
|
✊ ✍ ⚖️ 🔢 & 📨 ✅ ✍ 📨.
|
||||||
|
|
||||||
|
{* ../../docs_src/custom_response/tutorial005.py hl[2,7,9] *}
|
||||||
|
|
||||||
|
### `JSONResponse`
|
||||||
|
|
||||||
|
✊ 💽 & 📨 `application/json` 🗜 📨.
|
||||||
|
|
||||||
|
👉 🔢 📨 ⚙️ **FastAPI**, 👆 ✍ 🔛.
|
||||||
|
|
||||||
|
### `ORJSONResponse`
|
||||||
|
|
||||||
|
⏩ 🎛 🎻 📨 ⚙️ <a href="https://github.com/ijl/orjson" class="external-link" target="_blank">`orjson`</a>, 👆 ✍ 🔛.
|
||||||
|
|
||||||
|
### `UJSONResponse`
|
||||||
|
|
||||||
|
🎛 🎻 📨 ⚙️ <a href="https://github.com/ultrajson/ultrajson" class="external-link" target="_blank">`ujson`</a>.
|
||||||
|
|
||||||
|
/// warning
|
||||||
|
|
||||||
|
`ujson` 🌘 💛 🌘 🐍 🏗-🛠️ ❔ ⚫️ 🍵 📐-💼.
|
||||||
|
|
||||||
|
///
|
||||||
|
|
||||||
|
{* ../../docs_src/custom_response/tutorial001.py hl[2,7] *}
|
||||||
|
|
||||||
|
/// tip
|
||||||
|
|
||||||
|
⚫️ 💪 👈 `ORJSONResponse` 💪 ⏩ 🎛.
|
||||||
|
|
||||||
|
///
|
||||||
|
|
||||||
|
### `RedirectResponse`
|
||||||
|
|
||||||
|
📨 🇺🇸🔍 ❎. ⚙️ 3️⃣0️⃣7️⃣ 👔 📟 (🍕 ❎) 🔢.
|
||||||
|
|
||||||
|
👆 💪 📨 `RedirectResponse` 🔗:
|
||||||
|
|
||||||
|
{* ../../docs_src/custom_response/tutorial006.py hl[2,9] *}
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
⚖️ 👆 💪 ⚙️ ⚫️ `response_class` 🔢:
|
||||||
|
|
||||||
|
|
||||||
|
{* ../../docs_src/custom_response/tutorial006b.py hl[2,7,9] *}
|
||||||
|
|
||||||
|
🚥 👆 👈, ⤴️ 👆 💪 📨 📛 🔗 ⚪️➡️ 👆 *➡ 🛠️* 🔢.
|
||||||
|
|
||||||
|
👉 💼, `status_code` ⚙️ 🔜 🔢 1️⃣ `RedirectResponse`, ❔ `307`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
👆 💪 ⚙️ `status_code` 🔢 🌀 ⏮️ `response_class` 🔢:
|
||||||
|
|
||||||
|
{* ../../docs_src/custom_response/tutorial006c.py hl[2,7,9] *}
|
||||||
|
|
||||||
|
### `StreamingResponse`
|
||||||
|
|
||||||
|
✊ 🔁 🚂 ⚖️ 😐 🚂/🎻 & 🎏 📨 💪.
|
||||||
|
|
||||||
|
{* ../../docs_src/custom_response/tutorial007.py hl[2,14] *}
|
||||||
|
|
||||||
|
#### ⚙️ `StreamingResponse` ⏮️ 📁-💖 🎚
|
||||||
|
|
||||||
|
🚥 👆 ✔️ 📁-💖 🎚 (✅ 🎚 📨 `open()`), 👆 💪 ✍ 🚂 🔢 🔁 🤭 👈 📁-💖 🎚.
|
||||||
|
|
||||||
|
👈 🌌, 👆 🚫 ✔️ ✍ ⚫️ 🌐 🥇 💾, & 👆 💪 🚶♀️ 👈 🚂 🔢 `StreamingResponse`, & 📨 ⚫️.
|
||||||
|
|
||||||
|
👉 🔌 📚 🗃 🔗 ⏮️ ☁ 💾, 📹 🏭, & 🎏.
|
||||||
|
|
||||||
|
```{ .python .annotate hl_lines="2 10-12 14" }
|
||||||
|
{!../../docs_src/custom_response/tutorial008.py!}
|
||||||
|
```
|
||||||
|
|
||||||
|
1️⃣. 👉 🚂 🔢. ⚫️ "🚂 🔢" ↩️ ⚫️ 🔌 `yield` 📄 🔘.
|
||||||
|
2️⃣. ⚙️ `with` 🍫, 👥 ⚒ 💭 👈 📁-💖 🎚 📪 ⏮️ 🚂 🔢 🔨. , ⏮️ ⚫️ 🏁 📨 📨.
|
||||||
|
3️⃣. 👉 `yield from` 💬 🔢 🔁 🤭 👈 👜 🌟 `file_like`. & ⤴️, 🔠 🍕 🔁, 🌾 👈 🍕 👟 ⚪️➡️ 👉 🚂 🔢.
|
||||||
|
|
||||||
|
, ⚫️ 🚂 🔢 👈 📨 "🏭" 👷 🕳 🙆 🔘.
|
||||||
|
|
||||||
|
🔨 ⚫️ 👉 🌌, 👥 💪 🚮 ⚫️ `with` 🍫, & 👈 🌌, 🚚 👈 ⚫️ 📪 ⏮️ 🏁.
|
||||||
|
|
||||||
|
/// tip
|
||||||
|
|
||||||
|
👀 👈 📥 👥 ⚙️ 🐩 `open()` 👈 🚫 🐕🦺 `async` & `await`, 👥 📣 ➡ 🛠️ ⏮️ 😐 `def`.
|
||||||
|
|
||||||
|
///
|
||||||
|
|
||||||
|
### `FileResponse`
|
||||||
|
|
||||||
|
🔁 🎏 📁 📨.
|
||||||
|
|
||||||
|
✊ 🎏 ⚒ ❌ 🔗 🌘 🎏 📨 🆎:
|
||||||
|
|
||||||
|
* `path` - 📁 📁 🎏.
|
||||||
|
* `headers` - 🙆 🛃 🎚 🔌, 📖.
|
||||||
|
* `media_type` - 🎻 🤝 📻 🆎. 🚥 🔢, 📁 ⚖️ ➡ 🔜 ⚙️ 🔑 📻 🆎.
|
||||||
|
* `filename` - 🚥 ⚒, 👉 🔜 🔌 📨 `Content-Disposition`.
|
||||||
|
|
||||||
|
📁 📨 🔜 🔌 ☑ `Content-Length`, `Last-Modified` & `ETag` 🎚.
|
||||||
|
|
||||||
|
{* ../../docs_src/custom_response/tutorial009.py hl[2,10] *}
|
||||||
|
|
||||||
|
👆 💪 ⚙️ `response_class` 🔢:
|
||||||
|
|
||||||
|
{* ../../docs_src/custom_response/tutorial009b.py hl[2,8,10] *}
|
||||||
|
|
||||||
|
👉 💼, 👆 💪 📨 📁 ➡ 🔗 ⚪️➡️ 👆 *➡ 🛠️* 🔢.
|
||||||
|
|
||||||
|
## 🛃 📨 🎓
|
||||||
|
|
||||||
|
👆 💪 ✍ 👆 👍 🛃 📨 🎓, 😖 ⚪️➡️ `Response` & ⚙️ ⚫️.
|
||||||
|
|
||||||
|
🖼, ➡️ 💬 👈 👆 💚 ⚙️ <a href="https://github.com/ijl/orjson" class="external-link" target="_blank">`orjson`</a>, ✋️ ⏮️ 🛃 ⚒ 🚫 ⚙️ 🔌 `ORJSONResponse` 🎓.
|
||||||
|
|
||||||
|
➡️ 💬 👆 💚 ⚫️ 📨 🔂 & 📁 🎻, 👆 💚 ⚙️ Orjson 🎛 `orjson.OPT_INDENT_2`.
|
||||||
|
|
||||||
|
👆 💪 ✍ `CustomORJSONResponse`. 👑 👜 👆 ✔️ ✍ `Response.render(content)` 👩🔬 👈 📨 🎚 `bytes`:
|
||||||
|
|
||||||
|
{* ../../docs_src/custom_response/tutorial009c.py hl[9:14,17] *}
|
||||||
|
|
||||||
|
🔜 ↩️ 🛬:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{"message": "Hello World"}
|
||||||
|
```
|
||||||
|
|
||||||
|
...👉 📨 🔜 📨:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"message": "Hello World"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
↗️, 👆 🔜 🎲 🔎 🌅 👍 🌌 ✊ 📈 👉 🌘 ❕ 🎻. 👶
|
||||||
|
|
||||||
|
## 🔢 📨 🎓
|
||||||
|
|
||||||
|
🕐❔ 🏗 **FastAPI** 🎓 👐 ⚖️ `APIRouter` 👆 💪 ✔ ❔ 📨 🎓 ⚙️ 🔢.
|
||||||
|
|
||||||
|
🔢 👈 🔬 👉 `default_response_class`.
|
||||||
|
|
||||||
|
🖼 🔛, **FastAPI** 🔜 ⚙️ `ORJSONResponse` 🔢, 🌐 *➡ 🛠️*, ↩️ `JSONResponse`.
|
||||||
|
|
||||||
|
{* ../../docs_src/custom_response/tutorial010.py hl[2,4] *}
|
||||||
|
|
||||||
|
/// tip
|
||||||
|
|
||||||
|
👆 💪 🔐 `response_class` *➡ 🛠️* ⏭.
|
||||||
|
|
||||||
|
///
|
||||||
|
|
||||||
|
## 🌖 🧾
|
||||||
|
|
||||||
|
👆 💪 📣 📻 🆎 & 📚 🎏 ℹ 🗄 ⚙️ `responses`: [🌖 📨 🗄](additional-responses.md){.internal-link target=_blank}.
|
||||||
|
|
@ -0,0 +1,97 @@
|
||||||
|
# ⚙️ 🎻
|
||||||
|
|
||||||
|
FastAPI 🏗 🔛 🔝 **Pydantic**, & 👤 ✔️ 🌏 👆 ❔ ⚙️ Pydantic 🏷 📣 📨 & 📨.
|
||||||
|
|
||||||
|
✋️ FastAPI 🐕🦺 ⚙️ <a href="https://docs.python.org/3/library/dataclasses.html" class="external-link" target="_blank">`dataclasses`</a> 🎏 🌌:
|
||||||
|
|
||||||
|
{* ../../docs_src/dataclasses/tutorial001.py hl[1,7:12,19:20] *}
|
||||||
|
|
||||||
|
👉 🐕🦺 👏 **Pydantic**, ⚫️ ✔️ <a href="https://docs.pydantic.dev/latest/concepts/dataclasses/#use-of-stdlib-dataclasses-with-basemodel" class="external-link" target="_blank">🔗 🐕🦺 `dataclasses`</a>.
|
||||||
|
|
||||||
|
, ⏮️ 📟 🔛 👈 🚫 ⚙️ Pydantic 🎯, FastAPI ⚙️ Pydantic 🗜 📚 🐩 🎻 Pydantic 👍 🍛 🎻.
|
||||||
|
|
||||||
|
& ↗️, ⚫️ 🐕🦺 🎏:
|
||||||
|
|
||||||
|
* 💽 🔬
|
||||||
|
* 💽 🛠️
|
||||||
|
* 💽 🧾, ♒️.
|
||||||
|
|
||||||
|
👉 👷 🎏 🌌 ⏮️ Pydantic 🏷. & ⚫️ 🤙 🏆 🎏 🌌 🔘, ⚙️ Pydantic.
|
||||||
|
|
||||||
|
/// info
|
||||||
|
|
||||||
|
✔️ 🤯 👈 🎻 💪 🚫 🌐 Pydantic 🏷 💪.
|
||||||
|
|
||||||
|
, 👆 5️⃣📆 💪 ⚙️ Pydantic 🏷.
|
||||||
|
|
||||||
|
✋️ 🚥 👆 ✔️ 📚 🎻 🤥 🤭, 👉 👌 🎱 ⚙️ 👫 🏋️ 🕸 🛠️ ⚙️ FastAPI. 👶
|
||||||
|
|
||||||
|
///
|
||||||
|
|
||||||
|
## 🎻 `response_model`
|
||||||
|
|
||||||
|
👆 💪 ⚙️ `dataclasses` `response_model` 🔢:
|
||||||
|
|
||||||
|
{* ../../docs_src/dataclasses/tutorial002.py hl[1,7:13,19] *}
|
||||||
|
|
||||||
|
🎻 🔜 🔁 🗜 Pydantic 🎻.
|
||||||
|
|
||||||
|
👉 🌌, 🚮 🔗 🔜 🎦 🆙 🛠️ 🩺 👩💻 🔢:
|
||||||
|
|
||||||
|
<img src="/img/tutorial/dataclasses/image01.png">
|
||||||
|
|
||||||
|
## 🎻 🔁 📊 📊
|
||||||
|
|
||||||
|
👆 💪 🌀 `dataclasses` ⏮️ 🎏 🆎 ✍ ⚒ 🐦 📊 📊.
|
||||||
|
|
||||||
|
💼, 👆 💪 ✔️ ⚙️ Pydantic ⏬ `dataclasses`. 🖼, 🚥 👆 ✔️ ❌ ⏮️ 🔁 🏗 🛠️ 🧾.
|
||||||
|
|
||||||
|
👈 💼, 👆 💪 🎯 💱 🐩 `dataclasses` ⏮️ `pydantic.dataclasses`, ❔ 💧-♻:
|
||||||
|
|
||||||
|
```{ .python .annotate hl_lines="1 5 8-11 14-17 23-25 28" }
|
||||||
|
{!../../docs_src/dataclasses/tutorial003.py!}
|
||||||
|
```
|
||||||
|
|
||||||
|
1️⃣. 👥 🗄 `field` ⚪️➡️ 🐩 `dataclasses`.
|
||||||
|
|
||||||
|
2️⃣. `pydantic.dataclasses` 💧-♻ `dataclasses`.
|
||||||
|
|
||||||
|
3️⃣. `Author` 🎻 🔌 📇 `Item` 🎻.
|
||||||
|
|
||||||
|
4️⃣. `Author` 🎻 ⚙️ `response_model` 🔢.
|
||||||
|
|
||||||
|
5️⃣. 👆 💪 ⚙️ 🎏 🐩 🆎 ✍ ⏮️ 🎻 📨 💪.
|
||||||
|
|
||||||
|
👉 💼, ⚫️ 📇 `Item` 🎻.
|
||||||
|
|
||||||
|
6️⃣. 📥 👥 🛬 📖 👈 🔌 `items` ❔ 📇 🎻.
|
||||||
|
|
||||||
|
FastAPI 🎯 <abbr title="converting the data to a format that can be transmitted">✍</abbr> 💽 🎻.
|
||||||
|
|
||||||
|
7️⃣. 📥 `response_model` ⚙️ 🆎 ✍ 📇 `Author` 🎻.
|
||||||
|
|
||||||
|
🔄, 👆 💪 🌀 `dataclasses` ⏮️ 🐩 🆎 ✍.
|
||||||
|
|
||||||
|
8️⃣. 👀 👈 👉 *➡ 🛠️ 🔢* ⚙️ 🥔 `def` ↩️ `async def`.
|
||||||
|
|
||||||
|
🕧, FastAPI 👆 💪 🌀 `def` & `async def` 💪.
|
||||||
|
|
||||||
|
🚥 👆 💪 ↗️ 🔃 🕐❔ ⚙️ ❔, ✅ 👅 📄 _"🏃 ❓" _ 🩺 🔃 <a href="https://fastapi.tiangolo.com/async/#in-a-hurry" target="_blank" class="internal-link">`async` & `await`</a>.
|
||||||
|
|
||||||
|
9️⃣. 👉 *➡ 🛠️ 🔢* 🚫 🛬 🎻 (👐 ⚫️ 💪), ✋️ 📇 📖 ⏮️ 🔗 💽.
|
||||||
|
|
||||||
|
FastAPI 🔜 ⚙️ `response_model` 🔢 (👈 🔌 🎻) 🗜 📨.
|
||||||
|
|
||||||
|
👆 💪 🌀 `dataclasses` ⏮️ 🎏 🆎 ✍ 📚 🎏 🌀 📨 🏗 📊 📊.
|
||||||
|
|
||||||
|
✅-📟 ✍ 💁♂ 🔛 👀 🌅 🎯 ℹ.
|
||||||
|
|
||||||
|
## 💡 🌅
|
||||||
|
|
||||||
|
👆 💪 🌀 `dataclasses` ⏮️ 🎏 Pydantic 🏷, 😖 ⚪️➡️ 👫, 🔌 👫 👆 👍 🏷, ♒️.
|
||||||
|
|
||||||
|
💡 🌅, ✅ <a href="https://docs.pydantic.dev/latest/concepts/dataclasses/" class="external-link" target="_blank">Pydantic 🩺 🔃 🎻</a>.
|
||||||
|
|
||||||
|
## ⏬
|
||||||
|
|
||||||
|
👉 💪 ↩️ FastAPI ⏬ `0.67.0`. 👶
|
||||||
|
|
@ -0,0 +1,163 @@
|
||||||
|
# 🔆 🎉
|
||||||
|
|
||||||
|
👆 💪 🔬 ⚛ (📟) 👈 🔜 🛠️ ⏭ 🈸 **▶️ 🆙**. 👉 ⛓ 👈 👉 📟 🔜 🛠️ **🕐**, **⏭** 🈸 **▶️ 📨 📨**.
|
||||||
|
|
||||||
|
🎏 🌌, 👆 💪 🔬 ⚛ (📟) 👈 🔜 🛠️ 🕐❔ 🈸 **🤫 🔽**. 👉 💼, 👉 📟 🔜 🛠️ **🕐**, **⏮️** ✔️ 🍵 🎲 **📚 📨**.
|
||||||
|
|
||||||
|
↩️ 👉 📟 🛠️ ⏭ 🈸 **▶️** ✊ 📨, & ▶️️ ⏮️ ⚫️ **🏁** 🚚 📨, ⚫️ 📔 🎂 🈸 **🔆** (🔤 "🔆" 🔜 ⚠ 🥈 👶).
|
||||||
|
|
||||||
|
👉 💪 📶 ⚠ ⚒ 🆙 **ℹ** 👈 👆 💪 ⚙️ 🎂 📱, & 👈 **💰** 👪 📨, &/⚖️ 👈 👆 💪 **🧹 🆙** ⏮️. 🖼, 💽 🔗 🎱, ⚖️ 🚚 🔗 🎰 🏫 🏷.
|
||||||
|
|
||||||
|
## ⚙️ 💼
|
||||||
|
|
||||||
|
➡️ ▶️ ⏮️ 🖼 **⚙️ 💼** & ⤴️ 👀 ❔ ❎ ⚫️ ⏮️ 👉.
|
||||||
|
|
||||||
|
➡️ 🌈 👈 👆 ✔️ **🎰 🏫 🏷** 👈 👆 💚 ⚙️ 🍵 📨. 👶
|
||||||
|
|
||||||
|
🎏 🏷 🔗 👪 📨,, ⚫️ 🚫 1️⃣ 🏷 📍 📨, ⚖️ 1️⃣ 📍 👩💻 ⚖️ 🕳 🎏.
|
||||||
|
|
||||||
|
➡️ 🌈 👈 🚚 🏷 💪 **✊ 🕰**, ↩️ ⚫️ ✔️ ✍ 📚 **💽 ⚪️➡️ 💾**. 👆 🚫 💚 ⚫️ 🔠 📨.
|
||||||
|
|
||||||
|
👆 💪 📐 ⚫️ 🔝 🎚 🕹/📁, ✋️ 👈 🔜 ⛓ 👈 ⚫️ 🔜 **📐 🏷** 🚥 👆 🏃♂ 🙅 🏧 💯, ⤴️ 👈 💯 🔜 **🐌** ↩️ ⚫️ 🔜 ✔️ ⌛ 🏷 📐 ⏭ 💆♂ 💪 🏃 🔬 🍕 📟.
|
||||||
|
|
||||||
|
👈 ⚫️❔ 👥 🔜 ❎, ➡️ 📐 🏷 ⏭ 📨 🍵, ✋️ 🕴 ▶️️ ⏭ 🈸 ▶️ 📨 📨, 🚫 ⏪ 📟 ➖ 📐.
|
||||||
|
|
||||||
|
## 🔆
|
||||||
|
|
||||||
|
👆 💪 🔬 👉 *🕴* & *🤫* ⚛ ⚙️ `lifespan` 🔢 `FastAPI` 📱, & "🔑 👨💼" (👤 🔜 🎦 👆 ⚫️❔ 👈 🥈).
|
||||||
|
|
||||||
|
➡️ ▶️ ⏮️ 🖼 & ⤴️ 👀 ⚫️ ℹ.
|
||||||
|
|
||||||
|
👥 ✍ 🔁 🔢 `lifespan()` ⏮️ `yield` 💖 👉:
|
||||||
|
|
||||||
|
{* ../../docs_src/events/tutorial003.py hl[16,19] *}
|
||||||
|
|
||||||
|
📥 👥 ⚖ 😥 *🕴* 🛠️ 🚚 🏷 🚮 (❌) 🏷 🔢 📖 ⏮️ 🎰 🏫 🏷 ⏭ `yield`. 👉 📟 🔜 🛠️ **⏭** 🈸 **▶️ ✊ 📨**, ⏮️ *🕴*.
|
||||||
|
|
||||||
|
& ⤴️, ▶️️ ⏮️ `yield`, 👥 🚚 🏷. 👉 📟 🔜 🛠️ **⏮️** 🈸 **🏁 🚚 📨**, ▶️️ ⏭ *🤫*. 👉 💪, 🖼, 🚀 ℹ 💖 💾 ⚖️ 💻.
|
||||||
|
|
||||||
|
/// tip
|
||||||
|
|
||||||
|
`shutdown` 🔜 🔨 🕐❔ 👆 **⛔️** 🈸.
|
||||||
|
|
||||||
|
🎲 👆 💪 ▶️ 🆕 ⏬, ⚖️ 👆 🤚 🎡 🏃 ⚫️. 🤷
|
||||||
|
|
||||||
|
///
|
||||||
|
|
||||||
|
### 🔆 🔢
|
||||||
|
|
||||||
|
🥇 👜 👀, 👈 👥 ⚖ 🔁 🔢 ⏮️ `yield`. 👉 📶 🎏 🔗 ⏮️ `yield`.
|
||||||
|
|
||||||
|
{* ../../docs_src/events/tutorial003.py hl[14:19] *}
|
||||||
|
|
||||||
|
🥇 🍕 🔢, ⏭ `yield`, 🔜 🛠️ **⏭** 🈸 ▶️.
|
||||||
|
|
||||||
|
& 🍕 ⏮️ `yield` 🔜 🛠️ **⏮️** 🈸 ✔️ 🏁.
|
||||||
|
|
||||||
|
### 🔁 🔑 👨💼
|
||||||
|
|
||||||
|
🚥 👆 ✅, 🔢 🎀 ⏮️ `@asynccontextmanager`.
|
||||||
|
|
||||||
|
👈 🗜 🔢 🔘 🕳 🤙 "**🔁 🔑 👨💼**".
|
||||||
|
|
||||||
|
{* ../../docs_src/events/tutorial003.py hl[1,13] *}
|
||||||
|
|
||||||
|
**🔑 👨💼** 🐍 🕳 👈 👆 💪 ⚙️ `with` 📄, 🖼, `open()` 💪 ⚙️ 🔑 👨💼:
|
||||||
|
|
||||||
|
```Python
|
||||||
|
with open("file.txt") as file:
|
||||||
|
file.read()
|
||||||
|
```
|
||||||
|
|
||||||
|
⏮️ ⏬ 🐍, 📤 **🔁 🔑 👨💼**. 👆 🔜 ⚙️ ⚫️ ⏮️ `async with`:
|
||||||
|
|
||||||
|
```Python
|
||||||
|
async with lifespan(app):
|
||||||
|
await do_stuff()
|
||||||
|
```
|
||||||
|
|
||||||
|
🕐❔ 👆 ✍ 🔑 👨💼 ⚖️ 🔁 🔑 👨💼 💖 🔛, ⚫️❔ ⚫️ 🔨 👈, ⏭ 🛬 `with` 🍫, ⚫️ 🔜 🛠️ 📟 ⏭ `yield`, & ⏮️ ❎ `with` 🍫, ⚫️ 🔜 🛠️ 📟 ⏮️ `yield`.
|
||||||
|
|
||||||
|
👆 📟 🖼 🔛, 👥 🚫 ⚙️ ⚫️ 🔗, ✋️ 👥 🚶♀️ ⚫️ FastAPI ⚫️ ⚙️ ⚫️.
|
||||||
|
|
||||||
|
`lifespan` 🔢 `FastAPI` 📱 ✊ **🔁 🔑 👨💼**, 👥 💪 🚶♀️ 👆 🆕 `lifespan` 🔁 🔑 👨💼 ⚫️.
|
||||||
|
|
||||||
|
{* ../../docs_src/events/tutorial003.py hl[22] *}
|
||||||
|
|
||||||
|
## 🎛 🎉 (😢)
|
||||||
|
|
||||||
|
/// warning
|
||||||
|
|
||||||
|
👍 🌌 🍵 *🕴* & *🤫* ⚙️ `lifespan` 🔢 `FastAPI` 📱 🔬 🔛.
|
||||||
|
|
||||||
|
👆 💪 🎲 🚶 👉 🍕.
|
||||||
|
|
||||||
|
///
|
||||||
|
|
||||||
|
📤 🎛 🌌 🔬 👉 ⚛ 🛠️ ⏮️ *🕴* & ⏮️ *🤫*.
|
||||||
|
|
||||||
|
👆 💪 🔬 🎉 🐕🦺 (🔢) 👈 💪 🛠️ ⏭ 🈸 ▶️ 🆙, ⚖️ 🕐❔ 🈸 🤫 🔽.
|
||||||
|
|
||||||
|
👫 🔢 💪 📣 ⏮️ `async def` ⚖️ 😐 `def`.
|
||||||
|
|
||||||
|
### `startup` 🎉
|
||||||
|
|
||||||
|
🚮 🔢 👈 🔜 🏃 ⏭ 🈸 ▶️, 📣 ⚫️ ⏮️ 🎉 `"startup"`:
|
||||||
|
|
||||||
|
{* ../../docs_src/events/tutorial001.py hl[8] *}
|
||||||
|
|
||||||
|
👉 💼, `startup` 🎉 🐕🦺 🔢 🔜 🔢 🏬 "💽" ( `dict`) ⏮️ 💲.
|
||||||
|
|
||||||
|
👆 💪 🚮 🌅 🌘 1️⃣ 🎉 🐕🦺 🔢.
|
||||||
|
|
||||||
|
& 👆 🈸 🏆 🚫 ▶️ 📨 📨 ⏭ 🌐 `startup` 🎉 🐕🦺 ✔️ 🏁.
|
||||||
|
|
||||||
|
### `shutdown` 🎉
|
||||||
|
|
||||||
|
🚮 🔢 👈 🔜 🏃 🕐❔ 🈸 🤫 🔽, 📣 ⚫️ ⏮️ 🎉 `"shutdown"`:
|
||||||
|
|
||||||
|
{* ../../docs_src/events/tutorial002.py hl[6] *}
|
||||||
|
|
||||||
|
📥, `shutdown` 🎉 🐕🦺 🔢 🔜 ✍ ✍ ⏸ `"Application shutdown"` 📁 `log.txt`.
|
||||||
|
|
||||||
|
/// info
|
||||||
|
|
||||||
|
`open()` 🔢, `mode="a"` ⛓ "🎻",, ⏸ 🔜 🚮 ⏮️ ⚫️❔ 🔛 👈 📁, 🍵 📁 ⏮️ 🎚.
|
||||||
|
|
||||||
|
///
|
||||||
|
|
||||||
|
/// tip
|
||||||
|
|
||||||
|
👀 👈 👉 💼 👥 ⚙️ 🐩 🐍 `open()` 🔢 👈 🔗 ⏮️ 📁.
|
||||||
|
|
||||||
|
, ⚫️ 🔌 👤/🅾 (🔢/🔢), 👈 🚚 "⌛" 👜 ✍ 💾.
|
||||||
|
|
||||||
|
✋️ `open()` 🚫 ⚙️ `async` & `await`.
|
||||||
|
|
||||||
|
, 👥 📣 🎉 🐕🦺 🔢 ⏮️ 🐩 `def` ↩️ `async def`.
|
||||||
|
|
||||||
|
///
|
||||||
|
|
||||||
|
/// info
|
||||||
|
|
||||||
|
👆 💪 ✍ 🌅 🔃 👫 🎉 🐕🦺 <a href="https://www.starlette.dev/events/" class="external-link" target="_blank">💃 🎉' 🩺</a>.
|
||||||
|
|
||||||
|
///
|
||||||
|
|
||||||
|
### `startup` & `shutdown` 👯♂️
|
||||||
|
|
||||||
|
📤 ↕ 🤞 👈 ⚛ 👆 *🕴* & *🤫* 🔗, 👆 💪 💚 ▶️ 🕳 & ⤴️ 🏁 ⚫️, 📎 ℹ & ⤴️ 🚀 ⚫️, ♒️.
|
||||||
|
|
||||||
|
🔨 👈 👽 🔢 👈 🚫 💰 ⚛ ⚖️ 🔢 👯♂️ 🌅 ⚠ 👆 🔜 💪 🏪 💲 🌐 🔢 ⚖️ 🎏 🎱.
|
||||||
|
|
||||||
|
↩️ 👈, ⚫️ 🔜 👍 ↩️ ⚙️ `lifespan` 🔬 🔛.
|
||||||
|
|
||||||
|
## 📡 ℹ
|
||||||
|
|
||||||
|
📡 ℹ 😟 🤓. 👶
|
||||||
|
|
||||||
|
🔘, 🔫 📡 🔧, 👉 🍕 <a href="https://asgi.readthedocs.io/en/latest/specs/lifespan.html" class="external-link" target="_blank">🔆 🛠️</a>, & ⚫️ 🔬 🎉 🤙 `startup` & `shutdown`.
|
||||||
|
|
||||||
|
## 🎧 🈸
|
||||||
|
|
||||||
|
👶 ✔️ 🤯 👈 👫 🔆 🎉 (🕴 & 🤫) 🔜 🕴 🛠️ 👑 🈸, 🚫 [🎧 🈸 - 🗻](sub-applications.md){.internal-link target=_blank}.
|
||||||
|
|
@ -0,0 +1,238 @@
|
||||||
|
# 🏗 👩💻
|
||||||
|
|
||||||
|
**FastAPI** ⚓️ 🔛 🗄 🔧, 👆 🤚 🏧 🔗 ⏮️ 📚 🧰, 🔌 🏧 🛠️ 🩺 (🚚 🦁 🎚).
|
||||||
|
|
||||||
|
1️⃣ 🎯 📈 👈 🚫 🎯 ⭐ 👈 👆 💪 **🏗 👩💻** (🕣 🤙 <abbr title="Software Development Kits">**📱**</abbr> ) 👆 🛠️, 📚 🎏 **🛠️ 🇪🇸**.
|
||||||
|
|
||||||
|
## 🗄 👩💻 🚂
|
||||||
|
|
||||||
|
📤 📚 🧰 🏗 👩💻 ⚪️➡️ **🗄**.
|
||||||
|
|
||||||
|
⚠ 🧰 <a href="https://openapi-generator.tech/" class="external-link" target="_blank">🗄 🚂</a>.
|
||||||
|
|
||||||
|
🚥 👆 🏗 **🕸**, 📶 😌 🎛 <a href="https://github.com/hey-api/openapi-ts" class="external-link" target="_blank">🗄-📕-🇦🇪</a>.
|
||||||
|
|
||||||
|
## 🏗 📕 🕸 👩💻
|
||||||
|
|
||||||
|
➡️ ▶️ ⏮️ 🙅 FastAPI 🈸:
|
||||||
|
|
||||||
|
{* ../../docs_src/generate_clients/tutorial001.py hl[9:11,14:15,18,19,23] *}
|
||||||
|
|
||||||
|
👀 👈 *➡ 🛠️* 🔬 🏷 👫 ⚙️ 📨 🚀 & 📨 🚀, ⚙️ 🏷 `Item` & `ResponseMessage`.
|
||||||
|
|
||||||
|
### 🛠️ 🩺
|
||||||
|
|
||||||
|
🚥 👆 🚶 🛠️ 🩺, 👆 🔜 👀 👈 ⚫️ ✔️ **🔗** 📊 📨 📨 & 📨 📨:
|
||||||
|
|
||||||
|
<img src="/img/tutorial/generate-clients/image01.png">
|
||||||
|
|
||||||
|
👆 💪 👀 👈 🔗 ↩️ 👫 📣 ⏮️ 🏷 📱.
|
||||||
|
|
||||||
|
👈 ℹ 💪 📱 **🗄 🔗**, & ⤴️ 🎦 🛠️ 🩺 (🦁 🎚).
|
||||||
|
|
||||||
|
& 👈 🎏 ℹ ⚪️➡️ 🏷 👈 🔌 🗄 ⚫️❔ 💪 ⚙️ **🏗 👩💻 📟**.
|
||||||
|
|
||||||
|
### 🏗 📕 👩💻
|
||||||
|
|
||||||
|
🔜 👈 👥 ✔️ 📱 ⏮️ 🏷, 👥 💪 🏗 👩💻 📟 🕸.
|
||||||
|
|
||||||
|
#### ❎ `openapi-ts`
|
||||||
|
|
||||||
|
👆 💪 ❎ `openapi-ts` 👆 🕸 📟 ⏮️:
|
||||||
|
|
||||||
|
<div class="termy">
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ npm install @hey-api/openapi-ts --save-dev
|
||||||
|
|
||||||
|
---> 100%
|
||||||
|
```
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
#### 🏗 👩💻 📟
|
||||||
|
|
||||||
|
🏗 👩💻 📟 👆 💪 ⚙️ 📋 ⏸ 🈸 `openapi-ts` 👈 🔜 🔜 ❎.
|
||||||
|
|
||||||
|
↩️ ⚫️ ❎ 🇧🇿 🏗, 👆 🎲 🚫🔜 💪 🤙 👈 📋 🔗, ✋️ 👆 🔜 🚮 ⚫️ 🔛 👆 `package.json` 📁.
|
||||||
|
|
||||||
|
⚫️ 💪 👀 💖 👉:
|
||||||
|
|
||||||
|
```JSON hl_lines="7"
|
||||||
|
{
|
||||||
|
"name": "frontend-app",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "",
|
||||||
|
"main": "index.js",
|
||||||
|
"scripts": {
|
||||||
|
"generate-client": "openapi-ts --input http://localhost:8000/openapi.json --output ./src/client --client axios"
|
||||||
|
},
|
||||||
|
"author": "",
|
||||||
|
"license": "",
|
||||||
|
"devDependencies": {
|
||||||
|
"@hey-api/openapi-ts": "^0.27.38",
|
||||||
|
"typescript": "^4.6.2"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
⏮️ ✔️ 👈 ☕ `generate-client` ✍ 📤, 👆 💪 🏃 ⚫️ ⏮️:
|
||||||
|
|
||||||
|
<div class="termy">
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ npm run generate-client
|
||||||
|
|
||||||
|
frontend-app@1.0.0 generate-client /home/user/code/frontend-app
|
||||||
|
> openapi-ts --input http://localhost:8000/openapi.json --output ./src/client --client axios
|
||||||
|
```
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
👈 📋 🔜 🏗 📟 `./src/client` & 🔜 ⚙️ `axios` (🕸 🇺🇸🔍 🗃) 🔘.
|
||||||
|
|
||||||
|
### 🔄 👅 👩💻 📟
|
||||||
|
|
||||||
|
🔜 👆 💪 🗄 & ⚙️ 👩💻 📟, ⚫️ 💪 👀 💖 👉, 👀 👈 👆 🤚 ✍ 👩🔬:
|
||||||
|
|
||||||
|
<img src="/img/tutorial/generate-clients/image02.png">
|
||||||
|
|
||||||
|
👆 🔜 🤚 ✍ 🚀 📨:
|
||||||
|
|
||||||
|
<img src="/img/tutorial/generate-clients/image03.png">
|
||||||
|
|
||||||
|
/// tip
|
||||||
|
|
||||||
|
👀 ✍ `name` & `price`, 👈 🔬 FastAPI 🈸, `Item` 🏷.
|
||||||
|
|
||||||
|
///
|
||||||
|
|
||||||
|
👆 🔜 ✔️ ⏸ ❌ 📊 👈 👆 📨:
|
||||||
|
|
||||||
|
<img src="/img/tutorial/generate-clients/image04.png">
|
||||||
|
|
||||||
|
📨 🎚 🔜 ✔️ ✍:
|
||||||
|
|
||||||
|
<img src="/img/tutorial/generate-clients/image05.png">
|
||||||
|
|
||||||
|
## FastAPI 📱 ⏮️ 🔖
|
||||||
|
|
||||||
|
📚 💼 👆 FastAPI 📱 🔜 🦏, & 👆 🔜 🎲 ⚙️ 🔖 🎏 🎏 👪 *➡ 🛠️*.
|
||||||
|
|
||||||
|
🖼, 👆 💪 ✔️ 📄 **🏬** & ➕1️⃣ 📄 **👩💻**, & 👫 💪 👽 🔖:
|
||||||
|
|
||||||
|
|
||||||
|
{* ../../docs_src/generate_clients/tutorial002.py hl[23,28,36] *}
|
||||||
|
|
||||||
|
### 🏗 📕 👩💻 ⏮️ 🔖
|
||||||
|
|
||||||
|
🚥 👆 🏗 👩💻 FastAPI 📱 ⚙️ 🔖, ⚫️ 🔜 🛎 🎏 👩💻 📟 ⚓️ 🔛 🔖.
|
||||||
|
|
||||||
|
👉 🌌 👆 🔜 💪 ✔️ 👜 ✔ & 👪 ☑ 👩💻 📟:
|
||||||
|
|
||||||
|
<img src="/img/tutorial/generate-clients/image06.png">
|
||||||
|
|
||||||
|
👉 💼 👆 ✔️:
|
||||||
|
|
||||||
|
* `ItemsService`
|
||||||
|
* `UsersService`
|
||||||
|
|
||||||
|
### 👩💻 👩🔬 📛
|
||||||
|
|
||||||
|
▶️️ 🔜 🏗 👩🔬 📛 💖 `createItemItemsPost` 🚫 👀 📶 🧹:
|
||||||
|
|
||||||
|
```TypeScript
|
||||||
|
ItemsService.createItemItemsPost({name: "Plumbus", price: 5})
|
||||||
|
```
|
||||||
|
|
||||||
|
...👈 ↩️ 👩💻 🚂 ⚙️ 🗄 🔗 **🛠️ 🆔** 🔠 *➡ 🛠️*.
|
||||||
|
|
||||||
|
🗄 🚚 👈 🔠 🛠️ 🆔 😍 🤭 🌐 *➡ 🛠️*, FastAPI ⚙️ **🔢 📛**, **➡**, & **🇺🇸🔍 👩🔬/🛠️** 🏗 👈 🛠️ 🆔, ↩️ 👈 🌌 ⚫️ 💪 ⚒ 💭 👈 🛠️ 🆔 😍.
|
||||||
|
|
||||||
|
✋️ 👤 🔜 🎦 👆 ❔ 📉 👈 ⏭. 👶
|
||||||
|
|
||||||
|
## 🛃 🛠️ 🆔 & 👍 👩🔬 📛
|
||||||
|
|
||||||
|
👆 💪 **🔀** 🌌 👫 🛠️ 🆔 **🏗** ⚒ 👫 🙅 & ✔️ **🙅 👩🔬 📛** 👩💻.
|
||||||
|
|
||||||
|
👉 💼 👆 🔜 ✔️ 🚚 👈 🔠 🛠️ 🆔 **😍** 🎏 🌌.
|
||||||
|
|
||||||
|
🖼, 👆 💪 ⚒ 💭 👈 🔠 *➡ 🛠️* ✔️ 🔖, & ⤴️ 🏗 🛠️ 🆔 ⚓️ 🔛 **🔖** & *➡ 🛠️* **📛** (🔢 📛).
|
||||||
|
|
||||||
|
### 🛃 🏗 😍 🆔 🔢
|
||||||
|
|
||||||
|
FastAPI ⚙️ **😍 🆔** 🔠 *➡ 🛠️*, ⚫️ ⚙️ **🛠️ 🆔** & 📛 🙆 💪 🛃 🏷, 📨 ⚖️ 📨.
|
||||||
|
|
||||||
|
👆 💪 🛃 👈 🔢. ⚫️ ✊ `APIRoute` & 🔢 🎻.
|
||||||
|
|
||||||
|
🖼, 📥 ⚫️ ⚙️ 🥇 🔖 (👆 🔜 🎲 ✔️ 🕴 1️⃣ 🔖) & *➡ 🛠️* 📛 (🔢 📛).
|
||||||
|
|
||||||
|
👆 💪 ⤴️ 🚶♀️ 👈 🛃 🔢 **FastAPI** `generate_unique_id_function` 🔢:
|
||||||
|
|
||||||
|
{* ../../docs_src/generate_clients/tutorial003.py hl[8:9,12] *}
|
||||||
|
|
||||||
|
### 🏗 📕 👩💻 ⏮️ 🛃 🛠️ 🆔
|
||||||
|
|
||||||
|
🔜 🚥 👆 🏗 👩💻 🔄, 👆 🔜 👀 👈 ⚫️ ✔️ 📉 👩🔬 📛:
|
||||||
|
|
||||||
|
<img src="/img/tutorial/generate-clients/image07.png">
|
||||||
|
|
||||||
|
👆 👀, 👩🔬 📛 🔜 ✔️ 🔖 & ⤴️ 🔢 📛, 🔜 👫 🚫 🔌 ℹ ⚪️➡️ 📛 ➡ & 🇺🇸🔍 🛠️.
|
||||||
|
|
||||||
|
### 🗜 🗄 🔧 👩💻 🚂
|
||||||
|
|
||||||
|
🏗 📟 ✔️ **❎ ℹ**.
|
||||||
|
|
||||||
|
👥 ⏪ 💭 👈 👉 👩🔬 🔗 **🏬** ↩️ 👈 🔤 `ItemsService` (✊ ⚪️➡️ 🔖), ✋️ 👥 ✔️ 📛 🔡 👩🔬 📛 💁♂️. 👶
|
||||||
|
|
||||||
|
👥 🔜 🎲 💚 🚧 ⚫️ 🗄 🏢, 👈 🔜 🚚 👈 🛠️ 🆔 **😍**.
|
||||||
|
|
||||||
|
✋️ 🏗 👩💻 👥 💪 **🔀** 🗄 🛠️ 🆔 ▶️️ ⏭ 🏭 👩💻, ⚒ 👈 👩🔬 📛 👌 & **🧹**.
|
||||||
|
|
||||||
|
👥 💪 ⏬ 🗄 🎻 📁 `openapi.json` & ⤴️ 👥 💪 **❎ 👈 🔡 🔖** ⏮️ ✍ 💖 👉:
|
||||||
|
|
||||||
|
{* ../../docs_src/generate_clients/tutorial004.py *}
|
||||||
|
|
||||||
|
⏮️ 👈, 🛠️ 🆔 🔜 📁 ⚪️➡️ 👜 💖 `items-get_items` `get_items`, 👈 🌌 👩💻 🚂 💪 🏗 🙅 👩🔬 📛.
|
||||||
|
|
||||||
|
### 🏗 📕 👩💻 ⏮️ 🗜 🗄
|
||||||
|
|
||||||
|
🔜 🔚 🏁 📁 `openapi.json`, 👆 🔜 🔀 `package.json` ⚙️ 👈 🇧🇿 📁, 🖼:
|
||||||
|
|
||||||
|
```JSON hl_lines="7"
|
||||||
|
{
|
||||||
|
"name": "frontend-app",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "",
|
||||||
|
"main": "index.js",
|
||||||
|
"scripts": {
|
||||||
|
"generate-client": "openapi-ts --input ./openapi.json --output ./src/client --client axios"
|
||||||
|
},
|
||||||
|
"author": "",
|
||||||
|
"license": "",
|
||||||
|
"devDependencies": {
|
||||||
|
"@hey-api/openapi-ts": "^0.27.38",
|
||||||
|
"typescript": "^4.6.2"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
⏮️ 🏭 🆕 👩💻, 👆 🔜 🔜 ✔️ **🧹 👩🔬 📛**, ⏮️ 🌐 **✍**, **⏸ ❌**, ♒️:
|
||||||
|
|
||||||
|
<img src="/img/tutorial/generate-clients/image08.png">
|
||||||
|
|
||||||
|
## 💰
|
||||||
|
|
||||||
|
🕐❔ ⚙️ 🔁 🏗 👩💻 👆 🔜 **✍** :
|
||||||
|
|
||||||
|
* 👩🔬.
|
||||||
|
* 📨 🚀 💪, 🔢 🔢, ♒️.
|
||||||
|
* 📨 🚀.
|
||||||
|
|
||||||
|
👆 🔜 ✔️ **⏸ ❌** 🌐.
|
||||||
|
|
||||||
|
& 🕐❔ 👆 ℹ 👩💻 📟, & **♻** 🕸, ⚫️ 🔜 ✔️ 🙆 🆕 *➡ 🛠️* 💪 👩🔬, 🗝 🕐 ❎, & 🙆 🎏 🔀 🔜 🎨 🔛 🏗 📟. 👶
|
||||||
|
|
||||||
|
👉 ⛓ 👈 🚥 🕳 🔀 ⚫️ 🔜 **🎨** 🔛 👩💻 📟 🔁. & 🚥 👆 **🏗** 👩💻 ⚫️ 🔜 ❌ 👅 🚥 👆 ✔️ 🙆 **🔖** 📊 ⚙️.
|
||||||
|
|
||||||
|
, 👆 🔜 **🔍 📚 ❌** 📶 ⏪ 🛠️ 🛵 ↩️ ✔️ ⌛ ❌ 🎦 🆙 👆 🏁 👩💻 🏭 & ⤴️ 🔄 ℹ 🌐❔ ⚠. 👶
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
# 🏧 👩💻 🦮
|
||||||
|
|
||||||
|
## 🌖 ⚒
|
||||||
|
|
||||||
|
👑 [🔰 - 👩💻 🦮](../tutorial/index.md){.internal-link target=_blank} 🔜 🥃 🤝 👆 🎫 🔘 🌐 👑 ⚒ **FastAPI**.
|
||||||
|
|
||||||
|
⏭ 📄 👆 🔜 👀 🎏 🎛, 📳, & 🌖 ⚒.
|
||||||
|
|
||||||
|
/// tip
|
||||||
|
|
||||||
|
⏭ 📄 **🚫 🎯 "🏧"**.
|
||||||
|
|
||||||
|
& ⚫️ 💪 👈 👆 ⚙️ 💼, ⚗ 1️⃣ 👫.
|
||||||
|
|
||||||
|
///
|
||||||
|
|
||||||
|
## ✍ 🔰 🥇
|
||||||
|
|
||||||
|
👆 💪 ⚙️ 🏆 ⚒ **FastAPI** ⏮️ 💡 ⚪️➡️ 👑 [🔰 - 👩💻 🦮](../tutorial/index.md){.internal-link target=_blank}.
|
||||||
|
|
||||||
|
& ⏭ 📄 🤔 👆 ⏪ ✍ ⚫️, & 🤔 👈 👆 💭 👈 👑 💭.
|
||||||
|
|
||||||
|
## 🏎.🅾 ↗️
|
||||||
|
|
||||||
|
🚥 👆 🔜 💖 ✊ 🏧-🔰 ↗️ 🔗 👉 📄 🩺, 👆 💪 💚 ✅: <a href="https://testdriven.io/courses/tdd-fastapi/" class="external-link" target="_blank">💯-💾 🛠️ ⏮️ FastAPI & ☁</a> **🏎.🅾**.
|
||||||
|
|
||||||
|
👫 ⏳ 🩸 1️⃣0️⃣ 💯 🌐 💰 🛠️ **FastAPI**. 👶 👶
|
||||||
|
|
@ -0,0 +1,95 @@
|
||||||
|
# 🏧 🛠️
|
||||||
|
|
||||||
|
👑 🔰 👆 ✍ ❔ 🚮 [🛃 🛠️](../tutorial/middleware.md){.internal-link target=_blank} 👆 🈸.
|
||||||
|
|
||||||
|
& ⤴️ 👆 ✍ ❔ 🍵 [⚜ ⏮️ `CORSMiddleware`](../tutorial/cors.md){.internal-link target=_blank}.
|
||||||
|
|
||||||
|
👉 📄 👥 🔜 👀 ❔ ⚙️ 🎏 🛠️.
|
||||||
|
|
||||||
|
## ❎ 🔫 🛠️
|
||||||
|
|
||||||
|
**FastAPI** ⚓️ 🔛 💃 & 🛠️ <abbr title="Asynchronous Server Gateway Interface">🔫</abbr> 🔧, 👆 💪 ⚙️ 🙆 🔫 🛠️.
|
||||||
|
|
||||||
|
🛠️ 🚫 ✔️ ⚒ FastAPI ⚖️ 💃 👷, 📏 ⚫️ ⏩ 🔫 🔌.
|
||||||
|
|
||||||
|
🏢, 🔫 🛠️ 🎓 👈 ⌛ 📨 🔫 📱 🥇 ❌.
|
||||||
|
|
||||||
|
, 🧾 🥉-🥳 🔫 🛠️ 👫 🔜 🎲 💬 👆 🕳 💖:
|
||||||
|
|
||||||
|
```Python
|
||||||
|
from unicorn import UnicornMiddleware
|
||||||
|
|
||||||
|
app = SomeASGIApp()
|
||||||
|
|
||||||
|
new_app = UnicornMiddleware(app, some_config="rainbow")
|
||||||
|
```
|
||||||
|
|
||||||
|
✋️ FastAPI (🤙 💃) 🚚 🙅 🌌 ⚫️ 👈 ⚒ 💭 👈 🔗 🛠️ 🍵 💽 ❌ & 🛃 ⚠ 🐕🦺 👷 ☑.
|
||||||
|
|
||||||
|
👈, 👆 ⚙️ `app.add_middleware()` (🖼 ⚜).
|
||||||
|
|
||||||
|
```Python
|
||||||
|
from fastapi import FastAPI
|
||||||
|
from unicorn import UnicornMiddleware
|
||||||
|
|
||||||
|
app = FastAPI()
|
||||||
|
|
||||||
|
app.add_middleware(UnicornMiddleware, some_config="rainbow")
|
||||||
|
```
|
||||||
|
|
||||||
|
`app.add_middleware()` 📨 🛠️ 🎓 🥇 ❌ & 🙆 🌖 ❌ 🚶♀️ 🛠️.
|
||||||
|
|
||||||
|
## 🛠️ 🛠️
|
||||||
|
|
||||||
|
**FastAPI** 🔌 📚 🛠️ ⚠ ⚙️ 💼, 👥 🔜 👀 ⏭ ❔ ⚙️ 👫.
|
||||||
|
|
||||||
|
/// note | 📡 ℹ
|
||||||
|
|
||||||
|
⏭ 🖼, 👆 💪 ⚙️ `from starlette.middleware.something import SomethingMiddleware`.
|
||||||
|
|
||||||
|
**FastAPI** 🚚 📚 🛠️ `fastapi.middleware` 🏪 👆, 👩💻. ✋️ 🌅 💪 🛠️ 👟 🔗 ⚪️➡️ 💃.
|
||||||
|
|
||||||
|
///
|
||||||
|
|
||||||
|
## `HTTPSRedirectMiddleware`
|
||||||
|
|
||||||
|
🛠️ 👈 🌐 📨 📨 🔜 👯♂️ `https` ⚖️ `wss`.
|
||||||
|
|
||||||
|
🙆 📨 📨 `http` ⚖️ `ws` 🔜 ❎ 🔐 ⚖ ↩️.
|
||||||
|
|
||||||
|
{* ../../docs_src/advanced_middleware/tutorial001.py hl[2,6] *}
|
||||||
|
|
||||||
|
## `TrustedHostMiddleware`
|
||||||
|
|
||||||
|
🛠️ 👈 🌐 📨 📨 ✔️ ☑ ⚒ `Host` 🎚, ✔ 💂♂ 🛡 🇺🇸🔍 🦠 🎚 👊.
|
||||||
|
|
||||||
|
{* ../../docs_src/advanced_middleware/tutorial002.py hl[2,6:8] *}
|
||||||
|
|
||||||
|
📄 ❌ 🐕🦺:
|
||||||
|
|
||||||
|
* `allowed_hosts` - 📇 🆔 📛 👈 🔜 ✔ 📛. 🃏 🆔 ✅ `*.example.com` 🐕🦺 🎀 📁. ✔ 🙆 📛 👯♂️ ⚙️ `allowed_hosts=["*"]` ⚖️ 🚫 🛠️.
|
||||||
|
|
||||||
|
🚥 📨 📨 🔨 🚫 ✔ ☑ ⤴️ `400` 📨 🔜 📨.
|
||||||
|
|
||||||
|
## `GZipMiddleware`
|
||||||
|
|
||||||
|
🍵 🗜 📨 🙆 📨 👈 🔌 `"gzip"` `Accept-Encoding` 🎚.
|
||||||
|
|
||||||
|
🛠️ 🔜 🍵 👯♂️ 🐩 & 🎥 📨.
|
||||||
|
|
||||||
|
{* ../../docs_src/advanced_middleware/tutorial003.py hl[2,6] *}
|
||||||
|
|
||||||
|
📄 ❌ 🐕🦺:
|
||||||
|
|
||||||
|
* `minimum_size` - 🚫 🗜 📨 👈 🤪 🌘 👉 💯 📐 🔢. 🔢 `500`.
|
||||||
|
|
||||||
|
## 🎏 🛠️
|
||||||
|
|
||||||
|
📤 📚 🎏 🔫 🛠️.
|
||||||
|
|
||||||
|
🖼:
|
||||||
|
|
||||||
|
* <a href="https://github.com/encode/uvicorn/blob/master/uvicorn/middleware/proxy_headers.py" class="external-link" target="_blank">Uvicorn `ProxyHeadersMiddleware`</a>
|
||||||
|
* <a href="https://github.com/florimondmanca/msgpack-asgi" class="external-link" target="_blank">🇸🇲</a>
|
||||||
|
|
||||||
|
👀 🎏 💪 🛠️ ✅ <a href="https://www.starlette.dev/middleware/" class="external-link" target="_blank">💃 🛠️ 🩺</a> & <a href="https://github.com/florimondmanca/awesome-asgi" class="external-link" target="_blank">🔫 👌 📇</a>.
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue