diff --git a/.github/DISCUSSION_TEMPLATE/questions.yml b/.github/DISCUSSION_TEMPLATE/questions.yml new file mode 100644 index 0000000000000..98424a341db7b --- /dev/null +++ b/.github/DISCUSSION_TEMPLATE/questions.yml @@ -0,0 +1,158 @@ +labels: [question] +body: + - type: markdown + attributes: + value: | + Thanks for your interest in FastAPI! 🚀 + + Please follow these instructions, fill every question, and do every step. 🙏 + + I'm asking this because answering questions and solving problems in GitHub is what consumes most of the time. + + I end up not being able to add new features, fix bugs, review pull requests, etc. as fast as I wish because I have to spend too much time handling questions. + + All that, on top of all the incredible help provided by a bunch of community members, the [FastAPI Experts](https://fastapi.tiangolo.com/fastapi-people/#experts), that give a lot of their time to come here and help others. + + That's a lot of work they are doing, but if more FastAPI users came to help others like them just a little bit more, it would be much less effort for them (and you and me 😅). + + By asking questions in a structured way (following this) it will be much easier to help you. + + And there's a high chance that you will find the solution along the way and you won't even have to submit it and wait for an answer. 😎 + + As there are too many questions, I'll have to discard and close the incomplete ones. That will allow me (and others) to focus on helping people like you that follow the whole process and help us help you. 🤓 + - type: checkboxes + id: checks + attributes: + label: First Check + description: Please confirm and check all the following options. + options: + - label: I added a very descriptive title here. + required: true + - label: I used the GitHub search to find a similar question and didn't find it. + required: true + - label: I searched the FastAPI documentation, with the integrated search. + required: true + - label: I already searched in Google "How to X in FastAPI" and didn't find any information. + required: true + - label: I already read and followed all the tutorial in the docs and didn't find an answer. + required: true + - label: I already checked if it is not related to FastAPI but to [Pydantic](https://github.com/pydantic/pydantic). + required: true + - label: I already checked if it is not related to FastAPI but to [Swagger UI](https://github.com/swagger-api/swagger-ui). + required: true + - label: I already checked if it is not related to FastAPI but to [ReDoc](https://github.com/Redocly/redoc). + required: true + - type: checkboxes + id: help + attributes: + label: Commit to Help + description: | + After submitting this, I commit to one of: + + * Read open questions until I find 2 where I can help someone and add a comment to help there. + * I already hit the "watch" button in this repository to receive notifications and I commit to help at least 2 people that ask questions in the future. + * Review one Pull Request by downloading the code and following [all the review process](https://fastapi.tiangolo.com/help-fastapi/#review-pull-requests). + + options: + - label: I commit to help with one of those options 👆 + required: true + - type: textarea + id: example + attributes: + label: Example Code + description: | + Please add a self-contained, [minimal, reproducible, example](https://stackoverflow.com/help/minimal-reproducible-example) with your use case. + + If I (or someone) can copy it, run it, and see it right away, there's a much higher chance I (or someone) will be able to help you. + + placeholder: | + from fastapi import FastAPI + + app = FastAPI() + + + @app.get("/") + def read_root(): + return {"Hello": "World"} + render: python + validations: + required: true + - type: textarea + id: description + attributes: + label: Description + description: | + What is the problem, question, or error? + + Write a short description telling me what you are doing, what you expect to happen, and what is currently happening. + placeholder: | + * Open the browser and call the endpoint `/`. + * It returns a JSON with `{"Hello": "World"}`. + * But I expected it to return `{"Hello": "Sara"}`. + validations: + required: true + - type: dropdown + id: os + attributes: + label: Operating System + description: What operating system are you on? + multiple: true + options: + - Linux + - Windows + - macOS + - Other + validations: + required: true + - type: textarea + id: os-details + attributes: + label: Operating System Details + description: You can add more details about your operating system here, in particular if you chose "Other". + - type: input + id: fastapi-version + attributes: + label: FastAPI Version + description: | + What FastAPI version are you using? + + You can find the FastAPI version with: + + ```bash + python -c "import fastapi; print(fastapi.__version__)" + ``` + validations: + required: true + - type: input + id: pydantic-version + attributes: + label: Pydantic Version + description: | + What Pydantic version are you using? + + You can find the Pydantic version with: + + ```bash + python -c "import pydantic; print(pydantic.version.VERSION)" + ``` + validations: + required: true + - type: input + id: python-version + attributes: + label: Python Version + description: | + What Python version are you using? + + You can find the Python version with: + + ```bash + python --version + ``` + validations: + required: true + - type: textarea + id: context + attributes: + label: Additional Context + description: Add any additional context information or screenshots you think are useful. diff --git a/.github/DISCUSSION_TEMPLATE/translations.yml b/.github/DISCUSSION_TEMPLATE/translations.yml new file mode 100644 index 0000000000000..16e304d9981e8 --- /dev/null +++ b/.github/DISCUSSION_TEMPLATE/translations.yml @@ -0,0 +1,45 @@ +labels: [lang-all] +body: + - type: markdown + attributes: + value: | + Thanks for your interest in helping translate the FastAPI docs! 🌍 + + Please follow these instructions carefully to propose a new language translation. 🙏 + + This structured process helps ensure translations can be properly maintained long-term. + - type: checkboxes + id: checks + attributes: + label: Initial Checks + description: Please confirm and check all the following options. + options: + - label: I checked that this language is not already being translated in FastAPI docs. + required: true + - label: I searched existing discussions to ensure no one else proposed this language. + required: true + - label: I am a native speaker of the language I want to help translate. + required: true + - type: input + id: language + attributes: + label: Target Language + description: What language do you want to translate the FastAPI docs into? + placeholder: e.g. Latin + validations: + required: true + - type: textarea + id: additional_info + attributes: + label: Additional Information + description: Any other relevant information about your translation proposal + - type: markdown + attributes: + value: | + Translations are automatized with AI and then reviewed by native speakers. 🤖 🙋 + + This allows us to keep them consistent and up-to-date. + + If there are several native speakers commenting on this discussion and + committing to help review new translations, the FastAPI team will review it + and potentially make it an official translation. 😎 diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md deleted file mode 100644 index f9dc6709dace5..0000000000000 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ /dev/null @@ -1,42 +0,0 @@ ---- -name: Bug report -about: Create a report to help us improve -title: "[BUG]" -labels: bug -assignees: '' - ---- - -**Describe the bug** -A clear and concise description of what the bug is. - -**To Reproduce** -Steps to reproduce the behavior: -1. Create a file with '...' -2. Add a path operation function with '....' -3. Open the browser and call it with a payload of '....' -4. See error - -**Expected behavior** -A clear and concise description of what you expected to happen. - -**Screenshots** -If applicable, add screenshots to help explain your problem. - -**Environment:** - - OS: [e.g. Linux / Windows / macOS] - - FastAPI Version [e.g. 0.3.0], get it with: - -```Python -import fastapi -print(fastapi.__version__) -``` - -- Python version, get it with: - -```bash -python --version -``` - -**Additional context** -Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000000000..fd9f3b11c5830 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,16 @@ +blank_issues_enabled: false +contact_links: + - name: Security Contact + about: Please report security vulnerabilities to security@tiangolo.com + - name: Question or Problem + about: Ask a question or ask about a problem in GitHub Discussions. + url: https://github.com/fastapi/fastapi/discussions/categories/questions + - name: Feature Request + about: To suggest an idea or ask about a feature, please start with a question saying what you would like to achieve. There might be a way to do it already. + url: https://github.com/fastapi/fastapi/discussions/categories/questions + - name: Show and tell + about: Show what you built with FastAPI or to be used with FastAPI. + url: https://github.com/fastapi/fastapi/discussions/categories/show-and-tell + - name: Translations + about: Coordinate translations in GitHub Discussions. + url: https://github.com/fastapi/fastapi/discussions/categories/translations diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md deleted file mode 100644 index 7481d47965d43..0000000000000 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -name: Feature request -about: Suggest an idea for this project -title: "[FEATURE]" -labels: enhancement -assignees: '' - ---- - -**Is your feature request related to a problem? Please describe.** -A clear and concise description of what the problem is. Ex. I want to be able to [...] but I can't because [...] - -**Describe the solution you'd like** -A clear and concise description of what you want to happen. - -**Describe alternatives you've considered** -A clear and concise description of any alternative solutions or features you've considered. - -**Additional context** -Add any other context or screenshots about the feature request here. diff --git a/.github/ISSUE_TEMPLATE/privileged.yml b/.github/ISSUE_TEMPLATE/privileged.yml new file mode 100644 index 0000000000000..2b85eb310b306 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/privileged.yml @@ -0,0 +1,22 @@ +name: Privileged +description: You are @tiangolo or he asked you directly to create an issue here. If not, check the other options. 👇 +body: + - type: markdown + attributes: + value: | + Thanks for your interest in FastAPI! 🚀 + + If you are not @tiangolo or he didn't ask you directly to create an issue here, please start the conversation in a [Question in GitHub Discussions](https://github.com/fastapi/fastapi/discussions/categories/questions) instead. + - type: checkboxes + id: privileged + attributes: + label: Privileged issue + description: Confirm that you are allowed to create an issue here. + options: + - label: I'm @tiangolo or he asked me directly to create an issue here. + required: true + - type: textarea + id: content + attributes: + label: Issue Content + description: Add the content of the issue here. diff --git a/.github/ISSUE_TEMPLATE/question.md b/.github/ISSUE_TEMPLATE/question.md deleted file mode 100644 index 24a9284e3a9e8..0000000000000 --- a/.github/ISSUE_TEMPLATE/question.md +++ /dev/null @@ -1,17 +0,0 @@ ---- -name: Question -about: Ask a question -title: "[QUESTION]" -labels: question -assignees: '' - ---- - -**Description** - -How can I [...]? - -Is it possible to [...]? - -**Additional context** -Add any other context or screenshots about the feature request here. diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000000000..95c9f07cb93e3 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,50 @@ +version: 2 +updates: + # GitHub Actions + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" + cooldown: + default-days: 7 + commit-message: + prefix: ⬆ + labels: + - "internal" + - "dependencies" + - "github_actions" + groups: + github-actions: + patterns: + - "*" + # Python + - package-ecosystem: "uv" + directory: "/" + schedule: + interval: "weekly" + cooldown: + default-days: 7 + commit-message: + prefix: ⬆ + groups: + python-packages: + dependency-type: "development" + patterns: + - "*" + # pre-commit + - package-ecosystem: "pre-commit" + directory: "/" + schedule: + interval: "weekly" + cooldown: + default-days: 7 + commit-message: + prefix: ⬆ + labels: + - "internal" + - "dependencies" + - "pre-commit" + groups: + pre-commit: + patterns: + - "*" diff --git a/.github/labeler.yml b/.github/labeler.yml new file mode 100644 index 0000000000000..3c0bf473e03a4 --- /dev/null +++ b/.github/labeler.yml @@ -0,0 +1,38 @@ +docs: + - all: + - changed-files: + - any-glob-to-any-file: + - docs/en/docs/** + - docs_src/** + - all-globs-to-all-files: + - '!fastapi/**' + - '!pyproject.toml' + - '!docs/en/data/sponsors.yml' + - '!docs/en/overrides/main.html' + +lang-all: + - all: + - changed-files: + - any-glob-to-any-file: + - docs/*/docs/** + - all-globs-to-all-files: + - '!docs/en/docs/**' + - '!docs/*/**/_*.md' + - '!fastapi/**' + - '!pyproject.toml' + +internal: + - all: + - changed-files: + - any-glob-to-any-file: + - .github/** + - scripts/** + - .gitignore + - .pre-commit-config.yaml + - uv.lock + - docs/en/data/sponsors.yml + - docs/en/overrides/main.html + - all-globs-to-all-files: + - '!docs/*/docs/**' + - '!fastapi/**' + - '!pyproject.toml' diff --git a/.github/workflows/add-to-project.yml b/.github/workflows/add-to-project.yml new file mode 100644 index 0000000000000..35d089860c073 --- /dev/null +++ b/.github/workflows/add-to-project.yml @@ -0,0 +1,21 @@ +name: Add to Project + +on: + pull_request_target: # zizmor: ignore[dangerous-triggers] + issues: + types: + - opened + - reopened + +permissions: {} + +jobs: + add-to-project: + name: Add to project + runs-on: ubuntu-latest + timeout-minutes: 5 + steps: + - uses: actions/add-to-project@5afcf98fcd03f1c2f92c3c83f58ae24323cc57fd # v2.0.0 + with: + project-url: https://github.com/orgs/fastapi/projects/2 + github-token: ${{ secrets.PROJECTS_TOKEN }} # zizmor: ignore[secrets-outside-env] diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml new file mode 100644 index 0000000000000..fe2a39c459bfb --- /dev/null +++ b/.github/workflows/build-docs.yml @@ -0,0 +1,137 @@ +name: Build Docs +on: + push: + branches: + - master + pull_request: +permissions: {} + +jobs: + changes: + runs-on: ubuntu-latest + # Required permissions + permissions: + pull-requests: read + timeout-minutes: 5 + # Set job outputs to values from filter step + outputs: + docs: ${{ steps.filter.outputs.docs }} + steps: + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + persist-credentials: false + # For pull requests it's not necessary to checkout the code but for the main branch it is + - uses: dorny/paths-filter@fbd0ab8f3e69293af611ebaee6363fc25e6d187d # v4.0.1 + id: filter + with: + filters: | + docs: + - README.md + - docs/** + - docs_src/** + - pyproject.toml + - uv.lock + - .github/workflows/build-docs.yml + - .github/workflows/deploy-docs.yml + - scripts/docs.py + langs: + needs: + - changes + if: ${{ needs.changes.outputs.docs == 'true' }} + runs-on: ubuntu-latest + timeout-minutes: 5 + outputs: + langs: ${{ steps.show-langs.outputs.langs }} + steps: + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + persist-credentials: false + - name: Set up Python + uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 + with: + python-version-file: ".python-version" + - name: Setup uv + uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0 + with: + # Before upgrading uv version, make sure astral-sh/setup-uv knows its checksum. + # See: https://github.com/astral-sh/setup-uv/issues/851#issuecomment-4282017837 + version: "0.11.18" + enable-cache: true + cache-dependency-glob: | + pyproject.toml + uv.lock + - name: Install docs extras + run: uv sync --locked --no-dev --group docs + - name: Export Language Codes + id: show-langs + run: | + echo "langs=$(uv run ./scripts/docs.py langs-json)" >> $GITHUB_OUTPUT + + build-docs: + needs: + - changes + - langs + if: ${{ needs.changes.outputs.docs == 'true' }} + runs-on: ubuntu-latest + timeout-minutes: 7 + strategy: + matrix: + lang: ${{ fromJson(needs.langs.outputs.langs) }} + steps: + - name: Dump GitHub context + env: + GITHUB_CONTEXT: ${{ toJson(github) }} + run: echo "$GITHUB_CONTEXT" + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + persist-credentials: false + - name: Set up Python + uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 + with: + python-version-file: ".python-version" + - name: Setup uv + uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0 + with: + # Before upgrading uv version, make sure astral-sh/setup-uv knows its checksum. + # See: https://github.com/astral-sh/setup-uv/issues/851#issuecomment-4282017837 + version: "0.11.18" + enable-cache: true + cache-dependency-glob: | + pyproject.toml + uv.lock + - name: Install docs extras + run: uv sync --locked --no-dev --group docs + - name: Update Languages + run: uv run ./scripts/docs.py update-languages + - uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 + with: + key: zensical-${{ matrix.lang }}-${{ github.ref }} + path: site_zensical_src/${{ matrix.lang }}/.cache + - name: Build Docs + run: | # zizmor: ignore[template-injection] - comes from trusted source + uv run ./scripts/docs.py build-lang ${{ matrix.lang }} + - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: docs-site-${{ matrix.lang }} + # English owns root static assets. Translated pages reference /img, /css, + # and /js, so omit duplicated language-local copies from artifacts. + path: | + ./site/** + !./site/${{ matrix.lang }}/img/** + !./site/${{ matrix.lang }}/css/** + !./site/${{ matrix.lang }}/js/** + include-hidden-files: true + + # https://github.com/marketplace/actions/alls-green#why + docs-all-green: # This job does nothing and is only used for the branch protection + if: always() + needs: + - langs + - build-docs + runs-on: ubuntu-latest + steps: + - name: Decide whether the needed jobs succeeded or failed + uses: re-actors/alls-green@05ac9388f0aebcb5727afa17fcccfecd6f8ec5fe # v1.2.2 + with: + jobs: ${{ toJSON(needs) }} + allowed-skips: langs, build-docs diff --git a/.github/workflows/contributors.yml b/.github/workflows/contributors.yml new file mode 100644 index 0000000000000..1d869e7b87284 --- /dev/null +++ b/.github/workflows/contributors.yml @@ -0,0 +1,56 @@ +name: FastAPI People Contributors + +on: + schedule: + - cron: "0 3 1 * *" + workflow_dispatch: + inputs: + debug_enabled: + description: "Run the build with tmate debugging enabled (https://github.com/marketplace/actions/debugging-with-tmate)" + required: false + default: "false" + +permissions: {} + +jobs: + job: + if: github.repository_owner == 'fastapi' + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - name: Dump GitHub context + env: + GITHUB_CONTEXT: ${{ toJson(github) }} + run: echo "$GITHUB_CONTEXT" + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + persist-credentials: true # Required for `git push` in `contributors.py` + - name: Set up Python + uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 + with: + python-version-file: ".python-version" + - name: Setup uv + uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0 + with: + # Before upgrading uv version, make sure astral-sh/setup-uv knows its checksum. + # See: https://github.com/astral-sh/setup-uv/issues/851#issuecomment-4282017837 + version: "0.11.18" + enable-cache: true + cache-dependency-glob: | + pyproject.toml + uv.lock + - name: Install Dependencies + run: uv sync --locked --no-dev --group github-actions + # Allow debugging with tmate + - name: Setup tmate session + uses: mxschmitt/action-tmate@35b54afac29c97fb54faba5b513f8fbd1882f113 # v3.24 + if: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.debug_enabled == 'true' }} + with: + limit-access-to-actor: true + env: + GITHUB_TOKEN: ${{ secrets.FASTAPI_PR_TOKEN }} # zizmor: ignore[secrets-outside-env] + - name: FastAPI People Contributors + run: uv run ./scripts/contributors.py + env: + GITHUB_TOKEN: ${{ secrets.FASTAPI_PR_TOKEN }} # zizmor: ignore[secrets-outside-env] diff --git a/.github/workflows/create-draft-release.yml b/.github/workflows/create-draft-release.yml new file mode 100644 index 0000000000000..e0af097e2a663 --- /dev/null +++ b/.github/workflows/create-draft-release.yml @@ -0,0 +1,56 @@ +name: Create Draft Release + +on: + pull_request: + types: + - closed + +permissions: {} + +jobs: + create-draft-release: + if: github.event.pull_request.merged == true && contains(github.event.pull_request.labels.*.name, 'release') + runs-on: ubuntu-latest + timeout-minutes: 5 + permissions: + contents: write + env: + PREPARE_RELEASE_VERSION_FILE: fastapi/__init__.py + PREPARE_RELEASE_RELEASE_NOTES_FILE: docs/en/docs/release-notes.md + steps: + - name: Dump GitHub context + env: + GITHUB_CONTEXT: ${{ toJson(github) }} + run: echo "$GITHUB_CONTEXT" + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + ref: ${{ github.event.repository.default_branch }} + persist-credentials: true + - name: Set up Python + uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 + with: + python-version-file: ".python-version" + - name: Install uv + uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0 + with: + # Before upgrading uv version, make sure astral-sh/setup-uv knows its checksum. + # See: https://github.com/astral-sh/setup-uv/issues/851#issuecomment-4282017837 + version: "0.11.18" + - name: Extract release details + id: release-details + run: | + set -euo pipefail + version="$(uv run python scripts/prepare_release.py current-version)" + uv run python scripts/prepare_release.py release-notes > draft-release-notes.md + echo "version=$version" >> "$GITHUB_OUTPUT" + - name: Create draft release + env: + GH_TOKEN: ${{ github.token }} + VERSION: ${{ steps.release-details.outputs.version }} + run: | + set -euo pipefail + gh release create "$VERSION" \ + --draft \ + --title "$VERSION" \ + --notes-file draft-release-notes.md \ + --target "$(git rev-parse HEAD)" diff --git a/.github/workflows/deploy-docs.yml b/.github/workflows/deploy-docs.yml new file mode 100644 index 0000000000000..d8353ad559ffe --- /dev/null +++ b/.github/workflows/deploy-docs.yml @@ -0,0 +1,86 @@ +name: Deploy Docs +on: + workflow_run: # zizmor: ignore[dangerous-triggers] + workflows: + - Build Docs + types: + - completed + +permissions: {} + +jobs: + deploy-docs: + runs-on: ubuntu-latest + permissions: + deployments: write + issues: write + pull-requests: write + statuses: write + timeout-minutes: 5 + steps: + - name: Dump GitHub context + env: + GITHUB_CONTEXT: ${{ toJson(github) }} + run: echo "$GITHUB_CONTEXT" + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + persist-credentials: false + - name: Set up Python + uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 + with: + python-version-file: ".python-version" + - name: Setup uv + uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0 + with: + # Before upgrading uv version, make sure astral-sh/setup-uv knows its checksum. + # See: https://github.com/astral-sh/setup-uv/issues/851#issuecomment-4282017837 + version: "0.11.18" + enable-cache: false + - name: Install GitHub Actions dependencies + run: uv sync --locked --no-dev --group github-actions + - name: Deploy Docs Status Pending + run: uv run ./scripts/deploy_docs_status.py + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + COMMIT_SHA: ${{ github.event.workflow_run.head_sha }} + RUN_ID: ${{ github.run_id }} + STATE: "pending" + - name: Clean site + run: | + rm -rf ./site + mkdir ./site + - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + path: ./site/ + pattern: docs-site-* + merge-multiple: true + github-token: ${{ secrets.GITHUB_TOKEN }} + run-id: ${{ github.event.workflow_run.id }} + - name: Deploy to Cloudflare Pages + # hashFiles returns an empty string if there are no files + if: hashFiles('./site/*') + id: deploy + env: + PROJECT_NAME: fastapitiangolo + BRANCH: ${{ ( github.event.workflow_run.head_repository.full_name == github.repository && github.event.workflow_run.head_branch == 'master' && 'main' ) || ( github.event.workflow_run.head_sha ) }} + uses: cloudflare/wrangler-action@ebbaa1584979971c8614a24965b4405ff95890e0 # v4.0.0 + with: + apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }} # zizmor: ignore[secrets-outside-env] + accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} # zizmor: ignore[secrets-outside-env] + command: pages deploy ./site --project-name=${{ env.PROJECT_NAME }} --branch=${{ env.BRANCH }} + - name: Deploy Docs Status Error + if: failure() + run: uv run ./scripts/deploy_docs_status.py + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + COMMIT_SHA: ${{ github.event.workflow_run.head_sha }} + RUN_ID: ${{ github.run_id }} + STATE: "error" + - name: Comment Deploy + run: uv run ./scripts/deploy_docs_status.py + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + DEPLOY_URL: ${{ steps.deploy.outputs.deployment-url }} + COMMIT_SHA: ${{ github.event.workflow_run.head_sha }} + RUN_ID: ${{ github.run_id }} + STATE: "success" diff --git a/.github/workflows/detect-conflicts.yml b/.github/workflows/detect-conflicts.yml new file mode 100644 index 0000000000000..ecd288ba19b3d --- /dev/null +++ b/.github/workflows/detect-conflicts.yml @@ -0,0 +1,22 @@ +name: "Conflict detector" +on: + push: + pull_request_target: # zizmor: ignore[dangerous-triggers] + types: [synchronize] + +permissions: {} + +jobs: + main: + permissions: + contents: read + pull-requests: write + runs-on: ubuntu-latest + timeout-minutes: 5 + steps: + - name: Check if PRs have merge conflicts + uses: eps1lon/actions-label-merge-conflict@0273be72a0bbd58fcd71d0d6c02c209b50d1e5e1 # v3.1.0 + with: + dirtyLabel: "conflicts" + repoToken: "${{ secrets.GITHUB_TOKEN }}" + commentOnDirty: "This pull request has a merge conflict that needs to be resolved." diff --git a/.github/workflows/guard-dependencies.yml b/.github/workflows/guard-dependencies.yml new file mode 100644 index 0000000000000..142c7e50edebb --- /dev/null +++ b/.github/workflows/guard-dependencies.yml @@ -0,0 +1,53 @@ +name: Guard Dependencies + +on: + pull_request_target: # zizmor: ignore[dangerous-triggers] -- This workflow only reads context.payload metadata, never checks out PR code + branches: [master] + paths: + - pyproject.toml + - uv.lock + +permissions: + contents: read + issues: write + pull-requests: write + +jobs: + check-author: + runs-on: ubuntu-latest + timeout-minutes: 5 + steps: + - name: Check if author is org member or allowed bot + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + with: + script: | + const pr = context.payload.pull_request; + const author = pr.user.login; + const assoc = pr.author_association; + + const botAllowlist = new Set(['dependabot[bot]']); + const orgAuthorAssociations = new Set(['MEMBER', 'OWNER']); + + const allowed = + botAllowlist.has(author) || + (assoc != null && orgAuthorAssociations.has(assoc)); + + if (!allowed) { + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.payload.pull_request.number, + body: `This PR modifies dependency files (\`pyproject.toml\` or \`uv.lock\`), which is restricted to members of the **${context.repo.owner}** organization on GitHub.\n\nIf you need a dependency change, please [open a discussion](https://github.com/${context.repo.owner}/${context.repo.repo}/discussions/new) describing what you need and why.\n\nClosing this PR automatically.` + }); + + await github.rest.pulls.update({ + owner: context.repo.owner, + repo: context.repo.repo, + pull_number: context.payload.pull_request.number, + state: 'closed' + }); + + core.setFailed('Dependency changes are restricted to organization members.'); + } else { + console.log(`Author ${author} (author_association=${assoc}) is allowed to make dependency changes.`); + } diff --git a/.github/workflows/issue-manager.yml b/.github/workflows/issue-manager.yml new file mode 100644 index 0000000000000..e7f3a5f539e93 --- /dev/null +++ b/.github/workflows/issue-manager.yml @@ -0,0 +1,34 @@ +name: Issue Manager + +on: + schedule: + - cron: "13 22 * * *" + issue_comment: + types: + - created + issues: + types: + - labeled + pull_request_target: # zizmor: ignore[dangerous-triggers] + types: + - labeled + workflow_dispatch: + +permissions: {} + +jobs: + issue-manager: + if: github.repository_owner == 'fastapi' + runs-on: ubuntu-latest + permissions: + issues: write + pull-requests: write + timeout-minutes: 5 + steps: + - name: Dump GitHub context + env: + GITHUB_CONTEXT: ${{ toJson(github) }} + run: echo "$GITHUB_CONTEXT" + - uses: tiangolo/issue-manager@dc846170c36eb62fb434b3d943b36399fe240fb5 # 0.8.1 + with: + token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/label-approved.yml b/.github/workflows/label-approved.yml new file mode 100644 index 0000000000000..6d4f2ef52e7fb --- /dev/null +++ b/.github/workflows/label-approved.yml @@ -0,0 +1,52 @@ +name: Label Approved + +on: + schedule: + - cron: "0 12 * * *" + workflow_dispatch: + +permissions: {} + +jobs: + label-approved: + if: github.repository_owner == 'fastapi' + runs-on: ubuntu-latest + permissions: + pull-requests: write + timeout-minutes: 7 + steps: + - name: Dump GitHub context + env: + GITHUB_CONTEXT: ${{ toJson(github) }} + run: echo "$GITHUB_CONTEXT" + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + persist-credentials: false + - name: Set up Python + uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 + with: + python-version-file: ".python-version" + - name: Setup uv + uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0 + with: + # Before upgrading uv version, make sure astral-sh/setup-uv knows its checksum. + # See: https://github.com/astral-sh/setup-uv/issues/851#issuecomment-4282017837 + version: "0.11.18" + enable-cache: true + cache-dependency-glob: | + pyproject.toml + uv.lock + - name: Install GitHub Actions dependencies + run: uv sync --locked --no-dev --group github-actions + - name: Label Approved + run: uv run ./scripts/label_approved.py + env: + TOKEN: ${{ secrets.GITHUB_TOKEN }} + CONFIG: > + { + "approved-1": + { + "number": 1, + "await_label": "awaiting-review" + } + } diff --git a/.github/workflows/labeler.yml b/.github/workflows/labeler.yml new file mode 100644 index 0000000000000..803160ef58004 --- /dev/null +++ b/.github/workflows/labeler.yml @@ -0,0 +1,37 @@ +name: Labels +on: + pull_request_target: # zizmor: ignore[dangerous-triggers] + types: + - opened + - synchronize + - reopened + # For label-checker + - labeled + - unlabeled + +permissions: {} + +jobs: + labeler: + permissions: + contents: read + pull-requests: write + runs-on: ubuntu-latest + timeout-minutes: 5 + steps: + - uses: actions/labeler@f27b608878404679385c85cfa523b85ccb86e213 # v6.1.0 + if: ${{ github.event.action != 'labeled' && github.event.action != 'unlabeled' }} + - run: echo "Done adding labels" + # Run this after labeler applied labels + check-labels: + needs: + - labeler + permissions: + pull-requests: read + runs-on: ubuntu-latest + timeout-minutes: 5 + steps: + - uses: agilepathway/label-checker@c3d16ad512e7cea5961df85ff2486bb774caf3c5 # v1.6.65 + with: + one_of: breaking,security,feature,bug,refactor,upgrade,docs,lang-all,internal,release + repo_token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/latest-changes.yml b/.github/workflows/latest-changes.yml new file mode 100644 index 0000000000000..be20c98ae9087 --- /dev/null +++ b/.github/workflows/latest-changes.yml @@ -0,0 +1,50 @@ +name: Latest Changes + +on: + pull_request_target: # zizmor: ignore[dangerous-triggers] + branches: + - master + types: + - closed + workflow_dispatch: + inputs: + number: + description: PR number + required: true + debug_enabled: + description: 'Run the build with tmate debugging enabled (https://github.com/marketplace/actions/debugging-with-tmate)' + required: false + default: 'false' + +permissions: {} + +jobs: + latest-changes: + runs-on: ubuntu-latest + if: github.event_name == 'workflow_dispatch' || github.event.pull_request.merged == true + timeout-minutes: 5 + steps: + - name: Dump GitHub context + env: + GITHUB_CONTEXT: ${{ toJson(github) }} + run: echo "$GITHUB_CONTEXT" + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + ref: ${{ github.event.repository.default_branch }} + # To allow latest-changes to commit to the main branch + token: ${{ secrets.FASTAPI_LATEST_CHANGES }} # zizmor: ignore[secrets-outside-env] + persist-credentials: true # required by tiangolo/latest-changes + # Allow debugging with tmate + - name: Setup tmate session + uses: mxschmitt/action-tmate@35b54afac29c97fb54faba5b513f8fbd1882f113 # v3.24 + if: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.debug_enabled == 'true' }} + with: + limit-access-to-actor: true + - uses: tiangolo/latest-changes@c9b73efbc8992ef1a401e4235ea307a8ca8a724b # 0.6.1 + with: + token: ${{ secrets.GITHUB_TOKEN }} + latest_changes_file: docs/en/docs/release-notes.md + latest_changes_header: '## Latest Changes' + end_regex: '^## ' + debug_logs: true + label_header_prefix: '### ' diff --git a/.github/workflows/notify-translations.yml b/.github/workflows/notify-translations.yml new file mode 100644 index 0000000000000..261be1a9852a1 --- /dev/null +++ b/.github/workflows/notify-translations.yml @@ -0,0 +1,66 @@ +name: Notify Translations + +on: + pull_request_target: # zizmor: ignore[dangerous-triggers] + types: + - labeled + - closed + branches: + - master + workflow_dispatch: + inputs: + number: + description: PR number + required: true + debug_enabled: + description: 'Run the build with tmate debugging enabled (https://github.com/marketplace/actions/debugging-with-tmate)' + required: false + default: 'false' + +permissions: {} + +jobs: + job: + runs-on: ubuntu-latest + permissions: + discussions: write + timeout-minutes: 5 + steps: + - name: Dump GitHub context + env: + GITHUB_CONTEXT: ${{ toJson(github) }} + run: echo "$GITHUB_CONTEXT" + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + ref: ${{ github.event.repository.default_branch }} + persist-credentials: false + - name: Set up Python + uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 + with: + python-version-file: ".python-version" + - name: Setup uv + uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0 + with: + # Before upgrading uv version, make sure astral-sh/setup-uv knows its checksum. + # See: https://github.com/astral-sh/setup-uv/issues/851#issuecomment-4282017837 + version: "0.11.18" + enable-cache: true + cache-dependency-glob: | + pyproject.toml + uv.lock + - name: Install Dependencies + run: uv sync --locked --no-dev --group github-actions + # Allow debugging with tmate + - name: Setup tmate session + uses: mxschmitt/action-tmate@35b54afac29c97fb54faba5b513f8fbd1882f113 # v3.24 + if: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.debug_enabled == 'true' }} + with: + limit-access-to-actor: true + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Notify Translations + run: uv run ./scripts/notify_translations.py + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + NUMBER: ${{ github.event.inputs.number || null }} + DEBUG: ${{ github.event.inputs.debug_enabled || 'false' }} diff --git a/.github/workflows/people.yml b/.github/workflows/people.yml new file mode 100644 index 0000000000000..2e48c9d70edd0 --- /dev/null +++ b/.github/workflows/people.yml @@ -0,0 +1,57 @@ +name: FastAPI People + +on: + schedule: + - cron: "0 14 1 * *" + workflow_dispatch: + inputs: + debug_enabled: + description: Run the build with tmate debugging enabled (https://github.com/marketplace/actions/debugging-with-tmate) + required: false + default: "false" + +permissions: {} + +jobs: + job: + if: github.repository_owner == 'fastapi' + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - name: Dump GitHub context + env: + GITHUB_CONTEXT: ${{ toJson(github) }} + run: echo "$GITHUB_CONTEXT" + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + persist-credentials: true # Required for `git push` in `people.py` + - name: Set up Python + uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 + with: + python-version-file: ".python-version" + - name: Setup uv + uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0 + with: + # Before upgrading uv version, make sure astral-sh/setup-uv knows its checksum. + # See: https://github.com/astral-sh/setup-uv/issues/851#issuecomment-4282017837 + version: "0.11.18" + enable-cache: true + cache-dependency-glob: | + pyproject.toml + uv.lock + - name: Install Dependencies + run: uv sync --locked --no-dev --group github-actions + # Allow debugging with tmate + - name: Setup tmate session + uses: mxschmitt/action-tmate@35b54afac29c97fb54faba5b513f8fbd1882f113 # v3.24 + if: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.debug_enabled == 'true' }} + with: + limit-access-to-actor: true + env: + GITHUB_TOKEN: ${{ secrets.FASTAPI_PEOPLE }} # zizmor: ignore[secrets-outside-env] + - name: FastAPI People Experts + run: uv run ./scripts/people.py + env: + GITHUB_TOKEN: ${{ secrets.FASTAPI_PEOPLE }} # zizmor: ignore[secrets-outside-env] + SLEEP_INTERVAL: ${{ vars.PEOPLE_SLEEP_INTERVAL }} diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml new file mode 100644 index 0000000000000..963fd68ab1733 --- /dev/null +++ b/.github/workflows/pre-commit.yml @@ -0,0 +1,95 @@ +name: pre-commit + +on: + pull_request: +permissions: {} + +env: + # Forks and Dependabot don't have access to secrets + HAS_SECRETS: ${{ secrets.PRE_COMMIT != '' }} + +jobs: + pre-commit: + runs-on: ubuntu-latest + timeout-minutes: 5 + steps: + - name: Dump GitHub context + env: + GITHUB_CONTEXT: ${{ toJson(github) }} + run: echo "$GITHUB_CONTEXT" + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + name: Checkout PR for own repo + if: env.HAS_SECRETS == 'true' + with: + # To be able to commit it needs to fetch the head of the branch, not the + # merge commit + ref: ${{ github.head_ref }} + # And it needs the full history to be able to compute diffs + fetch-depth: 0 + # A token other than the default GITHUB_TOKEN is needed to be able to trigger CI + token: ${{ secrets.PRE_COMMIT }} # zizmor: ignore[secrets-outside-env] + persist-credentials: true # Required for `git push` command + # pre-commit lite ci needs the default checkout configs to work + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + name: Checkout PR for fork + if: env.HAS_SECRETS == 'false' + with: + # To be able to commit it needs the head branch of the PR, the remote one + ref: ${{ github.event.pull_request.head.sha }} + fetch-depth: 0 + persist-credentials: false + - name: Set up Python + uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 + with: + python-version-file: ".python-version" + - name: Setup uv + uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0 + with: + # Before upgrading uv version, make sure astral-sh/setup-uv knows its checksum. + # See: https://github.com/astral-sh/setup-uv/issues/851#issuecomment-4282017837 + version: "0.11.18" + cache-dependency-glob: | + pyproject.toml + uv.lock + - name: Install Dependencies + run: uv sync --locked --extra all + - name: Run prek - pre-commit + id: precommit + run: uv run prek 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.HAS_SECRETS == 'true' + 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@5d6cc0eb514c891a40562a58a8e71576c5c7fb43 # v1.1.0 + if: env.HAS_SECRETS == 'false' + 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 + timeout-minutes: 5 + 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@05ac9388f0aebcb5727afa17fcccfecd6f8ec5fe # v1.2.2 + with: + jobs: ${{ toJSON(needs) }} diff --git a/.github/workflows/prepare-release.yml b/.github/workflows/prepare-release.yml new file mode 100644 index 0000000000000..5b241aa4f48fd --- /dev/null +++ b/.github/workflows/prepare-release.yml @@ -0,0 +1,80 @@ +name: Prepare Release + +on: + workflow_dispatch: + inputs: + bump: + description: Release bump + required: true + type: choice + options: + - patch + - minor + - major + date: + description: Release date in YYYY-MM-DD format. Defaults to today. + required: false + type: string + +permissions: {} + +jobs: + prepare-release: + runs-on: ubuntu-latest + timeout-minutes: 5 + permissions: + contents: write + issues: write + pull-requests: write + env: + PREPARE_RELEASE_VERSION_FILE: fastapi/__init__.py + PREPARE_RELEASE_RELEASE_NOTES_FILE: docs/en/docs/release-notes.md + steps: + - name: Dump GitHub context + env: + GITHUB_CONTEXT: ${{ toJson(github) }} + run: echo "$GITHUB_CONTEXT" + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + token: ${{ secrets.FASTAPI_LATEST_CHANGES }} # zizmor: ignore[secrets-outside-env] + persist-credentials: true + - name: Set up Python + uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 + with: + python-version-file: ".python-version" + - name: Install uv + uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0 + with: + # Before upgrading uv version, make sure astral-sh/setup-uv knows its checksum. + # See: https://github.com/astral-sh/setup-uv/issues/851#issuecomment-4282017837 + version: "0.11.18" + - name: Prepare release + env: + PREPARE_RELEASE_BUMP: ${{ inputs.bump }} + PREPARE_RELEASE_DATE: ${{ inputs.date }} + run: uv run python scripts/prepare_release.py prepare + - name: Get release version + id: release-version + run: | + version="$(uv run python scripts/prepare_release.py current-version)" + echo "$version" + echo "version=$version" >> "$GITHUB_OUTPUT" + - name: Create release pull request + env: + GH_TOKEN: ${{ secrets.FASTAPI_LATEST_CHANGES }} + VERSION: ${{ steps.release-version.outputs.version }} + run: | + set -euo pipefail + branch="release-${VERSION}-${GITHUB_RUN_ID}-${GITHUB_RUN_ATTEMPT}" + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + git switch -c "$branch" + git add $PREPARE_RELEASE_VERSION_FILE $PREPARE_RELEASE_RELEASE_NOTES_FILE + git commit -m "🔖 Release version ${VERSION}" + git push --set-upstream origin "$branch" + gh pr create \ + --base master \ + --head "$branch" \ + --title "🔖 Release version ${VERSION}" \ + --body "Prepare release ${VERSION}." \ + --label release diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 0000000000000..447ce8c334b74 --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,39 @@ +name: Publish + +on: + release: + types: + - published + +permissions: {} + +jobs: + publish: + runs-on: ubuntu-latest + permissions: + id-token: write + contents: read + timeout-minutes: 5 + steps: + - name: Dump GitHub context + env: + GITHUB_CONTEXT: ${{ toJson(github) }} + run: echo "$GITHUB_CONTEXT" + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + persist-credentials: false + - name: Set up Python + uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 + with: + python-version-file: ".python-version" + - name: Install uv + uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0 + with: + # Before upgrading uv version, make sure astral-sh/setup-uv knows its checksum. + # See: https://github.com/astral-sh/setup-uv/issues/851#issuecomment-4282017837 + version: "0.11.18" + enable-cache: "false" + - name: Build distribution + run: uv build + - name: Publish + run: uv publish diff --git a/.github/workflows/smokeshow.yml b/.github/workflows/smokeshow.yml new file mode 100644 index 0000000000000..41804cee90e18 --- /dev/null +++ b/.github/workflows/smokeshow.yml @@ -0,0 +1,61 @@ +name: Smokeshow + +on: + workflow_run: # zizmor: ignore[dangerous-triggers] + workflows: [Test] + types: [completed] + +permissions: {} + +jobs: + smokeshow: + runs-on: ubuntu-latest + permissions: + statuses: write + timeout-minutes: 5 + + steps: + - name: Dump GitHub context + env: + GITHUB_CONTEXT: ${{ toJson(github) }} + run: echo "$GITHUB_CONTEXT" + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + persist-credentials: false + - uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 + with: + python-version-file: ".python-version" + - name: Setup uv + uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0 + with: + # Before upgrading uv version, make sure astral-sh/setup-uv knows its checksum. + # See: https://github.com/astral-sh/setup-uv/issues/851#issuecomment-4282017837 + version: "0.11.18" + cache-dependency-glob: | + pyproject.toml + uv.lock + - run: uv sync --locked --no-dev --group github-actions + - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: coverage-html + path: htmlcov + github-token: ${{ secrets.GITHUB_TOKEN }} + run-id: ${{ github.event.workflow_run.id }} + # Try 5 times to upload coverage to smokeshow + - name: Upload coverage to Smokeshow + run: | + for i in 1 2 3 4 5; do + if uv run smokeshow upload htmlcov; then + echo "Smokeshow upload success!" + break + fi + echo "Smokeshow upload error, sleep 1 sec and try again." + sleep 1 + done + env: + SMOKESHOW_GITHUB_STATUS_DESCRIPTION: Coverage {coverage-percentage} + SMOKESHOW_GITHUB_COVERAGE_THRESHOLD: 100 + SMOKESHOW_GITHUB_CONTEXT: coverage + SMOKESHOW_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + SMOKESHOW_GITHUB_PR_HEAD_SHA: ${{ github.event.workflow_run.head_sha }} + SMOKESHOW_AUTH_KEY: ${{ secrets.SMOKESHOW_AUTH_KEY }} # zizmor: ignore[secrets-outside-env] diff --git a/.github/workflows/sponsors.yml b/.github/workflows/sponsors.yml new file mode 100644 index 0000000000000..a20dcaf05cbeb --- /dev/null +++ b/.github/workflows/sponsors.yml @@ -0,0 +1,56 @@ +name: FastAPI People Sponsors + +on: + schedule: + - cron: "0 6 1 * *" + workflow_dispatch: + inputs: + debug_enabled: + description: "Run the build with tmate debugging enabled (https://github.com/marketplace/actions/debugging-with-tmate)" + required: false + default: "false" + +permissions: {} + +jobs: + job: + if: github.repository_owner == 'fastapi' + runs-on: ubuntu-latest + permissions: + contents: write + timeout-minutes: 5 + steps: + - name: Dump GitHub context + env: + GITHUB_CONTEXT: ${{ toJson(github) }} + run: echo "$GITHUB_CONTEXT" + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + persist-credentials: true # Required for `git push` in `sponsors.py` + - name: Set up Python + uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 + with: + python-version-file: ".python-version" + - name: Setup uv + uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0 + with: + # Before upgrading uv version, make sure astral-sh/setup-uv knows its checksum. + # See: https://github.com/astral-sh/setup-uv/issues/851#issuecomment-4282017837 + version: "0.11.18" + enable-cache: true + cache-dependency-glob: | + pyproject.toml + uv.lock + - name: Install Dependencies + run: uv sync --locked --no-dev --group github-actions + # Allow debugging with tmate + - name: Setup tmate session + uses: mxschmitt/action-tmate@35b54afac29c97fb54faba5b513f8fbd1882f113 # v3.24 + if: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.debug_enabled == 'true' }} + with: + limit-access-to-actor: true + - name: FastAPI People Sponsors + run: uv run ./scripts/sponsors.py + env: + SPONSORS_TOKEN: ${{ secrets.SPONSORS_TOKEN }} # zizmor: ignore[secrets-outside-env] + PR_TOKEN: ${{ secrets.FASTAPI_PR_TOKEN }} # zizmor: ignore[secrets-outside-env] diff --git a/.github/workflows/test-redistribute.yml b/.github/workflows/test-redistribute.yml new file mode 100644 index 0000000000000..cffb9d8c87328 --- /dev/null +++ b/.github/workflows/test-redistribute.yml @@ -0,0 +1,62 @@ +name: Test Redistribute + +on: + push: + branches: + - master + pull_request: +permissions: {} + +jobs: + test-redistribute: + runs-on: ubuntu-latest + timeout-minutes: 5 + steps: + - name: Dump GitHub context + env: + GITHUB_CONTEXT: ${{ toJson(github) }} + run: echo "$GITHUB_CONTEXT" + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + persist-credentials: false + - name: Set up Python + uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 + with: + python-version-file: ".python-version" + - name: Install build dependencies + run: pip install build + - name: Build source distribution + run: python -m build --sdist + - name: Decompress source distribution + run: | + cd dist + tar xvf fastapi*.tar.gz + - name: Install test dependencies + run: | + cd dist/fastapi*/ + pip install --group tests --editable .[all] + - name: Run source distribution tests + run: | + cd dist/fastapi*/ + bash scripts/test.sh + - name: Build wheel distribution + run: | + cd dist + pip wheel --no-deps fastapi*.tar.gz + - name: Dump GitHub context + env: + GITHUB_CONTEXT: ${{ toJson(github) }} + run: echo "$GITHUB_CONTEXT" + + # https://github.com/marketplace/actions/alls-green#why + test-redistribute-alls-green: # This job does nothing and is only used for the branch protection + if: always() + needs: + - test-redistribute + runs-on: ubuntu-latest + timeout-minutes: 5 + steps: + - name: Decide whether the needed jobs succeeded or failed + uses: re-actors/alls-green@05ac9388f0aebcb5727afa17fcccfecd6f8ec5fe # v1.2.2 + with: + jobs: ${{ toJSON(needs) }} diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000000000..42725b3df31cc --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,262 @@ +name: Test + +on: + push: + branches: + - master + pull_request: + schedule: + # cron every week on monday + - cron: "0 0 * * 1" + +permissions: {} + +env: + UV_NO_SYNC: true + INLINE_SNAPSHOT_DEFAULT_FLAGS: review + +jobs: + changes: + runs-on: ubuntu-latest + # Required permissions + permissions: + pull-requests: read + # Set job outputs to values from filter step + timeout-minutes: 5 + outputs: + src: ${{ steps.filter.outputs.src }} + steps: + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + persist-credentials: false + # For pull requests it's not necessary to checkout the code but for the main branch it is + - uses: dorny/paths-filter@fbd0ab8f3e69293af611ebaee6363fc25e6d187d # v4.0.1 + id: filter + with: + filters: | + src: + - .github/workflows/test.yml + - docs_src/** + - fastapi/** + - scripts/** + - tests/** + - .python-version + - pyproject.toml + - uv.lock + + test: + needs: + - changes + if: needs.changes.outputs.src == 'true' || github.ref == 'refs/heads/master' + timeout-minutes: 10 + strategy: + matrix: + os: [ windows-latest, macos-latest ] + python-version: [ "3.14", "3.14t" ] + deprecated-tests: [ "no-deprecation" ] + uv-resolution: + - highest + starlette-src: + - starlette-pypi + - starlette-git + include: + - os: macos-latest + python-version: "3.10" + coverage: coverage + uv-resolution: lowest-direct + deprecated-tests: "no-deprecation" + - os: windows-latest + python-version: "3.12" + coverage: coverage + uv-resolution: lowest-direct + deprecated-tests: "no-deprecation" + - os: ubuntu-latest + python-version: "3.13" + coverage: coverage + uv-resolution: highest + deprecated-tests: "no-deprecation" + - os: ubuntu-latest + python-version: "3.13" + uv-resolution: highest + codspeed: codspeed + deprecated-tests: "no-deprecation" + - os: ubuntu-latest + python-version: "3.13" + uv-resolution: highest + deprecated-tests: "no-deprecation" + without-httpx2: true + - os: ubuntu-latest + python-version: "3.14" + coverage: coverage + uv-resolution: highest + starlette-src: starlette-git + deprecated-tests: "test-deprecation" + - os: ubuntu-latest + python-version: "3.14t" + coverage: coverage + uv-resolution: highest + deprecated-tests: "no-deprecation" + fail-fast: false + runs-on: ${{ matrix.os }} + env: + UV_PYTHON: ${{ matrix.python-version }} + UV_RESOLUTION: ${{ matrix.uv-resolution }} + STARLETTE_SRC: ${{ matrix.starlette-src }} + steps: + - name: Dump GitHub context + env: + GITHUB_CONTEXT: ${{ toJson(github) }} + run: echo "$GITHUB_CONTEXT" + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + persist-credentials: false + - name: Set up Python + uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 + with: + python-version: ${{ matrix.python-version }} + - name: Setup uv + uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0 + with: + # Before upgrading uv version, make sure astral-sh/setup-uv knows its checksum. + # See: https://github.com/astral-sh/setup-uv/issues/851#issuecomment-4282017837 + version: "0.11.18" + enable-cache: true + cache-dependency-glob: | + pyproject.toml + uv.lock + - name: Install Dependencies + run: uv sync --no-dev --group tests --extra all + - name: Ensure that we have the lowest supported Pydantic version + if: matrix.uv-resolution == 'lowest-direct' + run: uv pip install "pydantic==2.9.0" + - name: Install Starlette from source + if: matrix.starlette-src == 'starlette-git' + run: uv pip install "git+https://github.com/Kludex/starlette@main" + - name: Install deprecated libraries just for testing + if: matrix.deprecated-tests == 'test-deprecation' + run: uv pip install orjson ujson + - name: Uninstall httpx2 to run tests with httpx + if: matrix.without-httpx2 == 'true' + run: uv pip uninstall httpx2 + - name: Reinstall SQLAlchemy without Cython extensions + if: matrix.python-version == '3.14t' && matrix.os == 'ubuntu-latest' + run: "DISABLE_SQLALCHEMY_CEXT=1 uv pip install --force-reinstall --no-binary :all: sqlalchemy" + - run: mkdir coverage + - name: Test + run: uv run --no-sync bash scripts/test-cov.sh $PYTEST_OPTIONS + env: + COVERAGE_FILE: coverage/.coverage.${{ runner.os }}-py${{ matrix.python-version }}-${{ matrix.deprecated-tests}} + CONTEXT: ${{ runner.os }}-py${{ matrix.python-version }}-${{ matrix.deprecated-tests}} + PYTEST_OPTIONS: ${{ (matrix.without-httpx2 == 'true') && '-W ignore::UserWarning' || '' }} + # Do not store coverage for all possible combinations to avoid file size max errors in Smokeshow + - name: Store coverage files + if: matrix.coverage == 'coverage' + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: coverage-${{ runner.os }}-${{ matrix.python-version }}-${{ matrix.deprecated-tests}}-${{ hashFiles('**/coverage/.coverage.*') }} + path: coverage + include-hidden-files: true + + benchmark: + needs: + - changes + if: needs.changes.outputs.src == 'true' || github.ref == 'refs/heads/master' + runs-on: ubuntu-latest + timeout-minutes: 5 + env: + UV_PYTHON: "3.13" + UV_RESOLUTION: highest + steps: + - name: Dump GitHub context + env: + GITHUB_CONTEXT: ${{ toJson(github) }} + run: echo "$GITHUB_CONTEXT" + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + persist-credentials: false + - name: Set up Python + uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 + with: + python-version: "3.13" + - name: Setup uv + uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0 + with: + # Before upgrading uv version, make sure astral-sh/setup-uv knows its checksum. + # See: https://github.com/astral-sh/setup-uv/issues/851#issuecomment-4282017837 + version: "0.11.18" + enable-cache: true + cache-dependency-glob: | + pyproject.toml + uv.lock + - name: Install Dependencies + run: uv sync --no-dev --group tests --extra all + - name: CodSpeed benchmarks + uses: CodSpeedHQ/action@a4a36bb07c0638b0b4ca52bf1f3dad1b4289e52f # v4.18.1 + with: + mode: simulation + run: uv run --no-sync pytest tests/benchmarks --codspeed + + coverage-combine: + needs: + - test + runs-on: ubuntu-latest + timeout-minutes: 5 + steps: + - name: Dump GitHub context + env: + GITHUB_CONTEXT: ${{ toJson(github) }} + run: echo "$GITHUB_CONTEXT" + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + persist-credentials: false + - uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 + with: + python-version-file: ".python-version" + - name: Setup uv + uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0 + with: + # Before upgrading uv version, make sure astral-sh/setup-uv knows its checksum. + # See: https://github.com/astral-sh/setup-uv/issues/851#issuecomment-4282017837 + version: "0.11.18" + enable-cache: true + cache-dependency-glob: | + pyproject.toml + uv.lock + - name: Install Dependencies + run: uv sync --locked --no-dev --group tests --extra all + - name: Get coverage files + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + pattern: coverage-* + path: coverage + merge-multiple: true + - run: ls -la coverage + - run: uv run coverage combine coverage + - run: uv run coverage html --title "Coverage for ${{ github.sha }}" + - name: Store coverage HTML + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: coverage-html + path: htmlcov + include-hidden-files: true + - run: uv run coverage report --fail-under=100 + + # https://github.com/marketplace/actions/alls-green#why + test-alls-green: # This job does nothing and is only used for the branch protection + if: always() + needs: + - test + - coverage-combine + - benchmark + runs-on: ubuntu-latest + timeout-minutes: 5 + 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@05ac9388f0aebcb5727afa17fcccfecd6f8ec5fe # v1.2.2 + with: + jobs: ${{ toJSON(needs) }} + allowed-skips: coverage-combine,test,benchmark diff --git a/.github/workflows/topic-repos.yml b/.github/workflows/topic-repos.yml new file mode 100644 index 0000000000000..b0fb403986dd6 --- /dev/null +++ b/.github/workflows/topic-repos.yml @@ -0,0 +1,44 @@ +name: Update Topic Repos + +on: + schedule: + - cron: "0 12 1 * *" + workflow_dispatch: + +permissions: {} + +jobs: + topic-repos: + if: github.repository_owner == 'fastapi' + runs-on: ubuntu-latest + permissions: + contents: write + timeout-minutes: 5 + steps: + - name: Dump GitHub context + env: + GITHUB_CONTEXT: ${{ toJson(github) }} + run: echo "$GITHUB_CONTEXT" + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + persist-credentials: true # Required for `git push` in `topic_repos.py` + - name: Set up Python + uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 + with: + python-version-file: ".python-version" + - name: Setup uv + uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0 + with: + # Before upgrading uv version, make sure astral-sh/setup-uv knows its checksum. + # See: https://github.com/astral-sh/setup-uv/issues/851#issuecomment-4282017837 + version: "0.11.18" + enable-cache: true + cache-dependency-glob: | + pyproject.toml + uv.lock + - name: Install GitHub Actions dependencies + run: uv sync --locked --no-dev --group github-actions + - name: Update Topic Repos + run: uv run ./scripts/topic_repos.py + env: + GITHUB_TOKEN: ${{ secrets.FASTAPI_PR_TOKEN }} # zizmor: ignore[secrets-outside-env] diff --git a/.github/workflows/translate.yml b/.github/workflows/translate.yml new file mode 100644 index 0000000000000..7f96798da71c3 --- /dev/null +++ b/.github/workflows/translate.yml @@ -0,0 +1,134 @@ +name: Translate + +on: + schedule: + - cron: "0 5 1,15 * *" # Run at 05:00 on the 1st and 15th of every month + + workflow_dispatch: + inputs: + debug_enabled: + description: Run with tmate debugging enabled (https://github.com/marketplace/actions/debugging-with-tmate) + required: false + default: "false" + command: + description: Command to run + type: choice + options: + - translate-page + - translate-lang + - update-outdated + - add-missing + - update-and-add + - remove-removable + language: + description: Language to translate to as a letter code (e.g. "es" for Spanish) + type: string + required: false + default: "" + en_path: + description: File path in English to translate (e.g. docs/en/docs/index.md) + type: string + required: false + default: "" + commit_in_place: + description: Commit changes directly instead of making a PR + type: boolean + required: false + default: false + max: + description: Maximum number of items to translate (e.g. 10) + type: number + required: false + default: 10 + +permissions: {} + +jobs: + langs: + runs-on: ubuntu-latest + outputs: + langs: ${{ steps.show-langs.outputs.langs }} + commands: ${{ steps.show-langs.outputs.commands }} + steps: + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + persist-credentials: false + - name: Set up Python + uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 + with: + python-version-file: ".python-version" + - name: Setup uv + uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0 + with: + # Before upgrading uv version, make sure astral-sh/setup-uv knows its checksum. + # See: https://github.com/astral-sh/setup-uv/issues/851#issuecomment-4282017837 + version: "0.11.18" + cache-dependency-glob: | + pyproject.toml + uv.lock + - name: Install Dependencies + run: uv sync --locked --no-dev --group github-actions --group translations + - name: Export Language Codes + id: show-langs + run: | + echo "langs=$(uv run ./scripts/translate.py llm-translatable-json)" >> $GITHUB_OUTPUT + echo "commands=$(uv run ./scripts/translate.py commands-json)" >> $GITHUB_OUTPUT + env: + LANGUAGE: ${{ github.event.inputs.language }} + COMMAND: ${{ github.event.inputs.command }} + + translate: + if: github.repository_owner == 'fastapi' + needs: langs + runs-on: ubuntu-latest + permissions: + contents: write + strategy: + matrix: + lang: ${{ fromJson(needs.langs.outputs.langs) }} + command: ${{ fromJson(needs.langs.outputs.commands) }} + steps: + - name: Dump GitHub context + env: + GITHUB_CONTEXT: ${{ toJson(github) }} + run: echo "$GITHUB_CONTEXT" + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + fetch-depth: 0 + persist-credentials: true # Required for `git push` in `translate.py` + - name: Set up Python + uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 + with: + python-version-file: ".python-version" + - name: Setup uv + uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0 + with: + # Before upgrading uv version, make sure astral-sh/setup-uv knows its checksum. + # See: https://github.com/astral-sh/setup-uv/issues/851#issuecomment-4282017837 + version: "0.11.18" + cache-dependency-glob: | + pyproject.toml + uv.lock + - name: Install Dependencies + run: uv sync --locked --no-dev --group github-actions --group translations + # Allow debugging with tmate + - name: Setup tmate session + uses: mxschmitt/action-tmate@35b54afac29c97fb54faba5b513f8fbd1882f113 # v3.24 + if: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.debug_enabled == 'true' }} + with: + limit-access-to-actor: true + env: + GITHUB_TOKEN: ${{ secrets.FASTAPI_TRANSLATIONS }} # zizmor: ignore[secrets-outside-env] + OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} # zizmor: ignore[secrets-outside-env] + - name: FastAPI Translate + run: | + uv run ./scripts/translate.py "$COMMAND" + uv run ./scripts/translate.py make-pr + env: + GITHUB_TOKEN: ${{ secrets.FASTAPI_TRANSLATIONS }} # zizmor: ignore[secrets-outside-env] + OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} # zizmor: ignore[secrets-outside-env] + LANGUAGE: ${{ matrix.lang }} + EN_PATH: ${{ github.event.inputs.en_path }} + COMMAND: ${{ matrix.command }} + COMMIT_IN_PLACE: ${{ github.event.inputs.commit_in_place == 'true' && 'true' || '' }} + MAX: ${{ github.event.inputs.max }} diff --git a/.github/workflows/zizmor.yml b/.github/workflows/zizmor.yml new file mode 100644 index 0000000000000..11ecb8272b36c --- /dev/null +++ b/.github/workflows/zizmor.yml @@ -0,0 +1,25 @@ +name: Zizmor + +on: + push: + branches: + - main + pull_request: + workflow_dispatch: + +permissions: {} + +jobs: + zizmor: + name: Run zizmor + runs-on: ubuntu-latest + timeout-minutes: 5 + permissions: + security-events: write # Required for upload-sarif (used by zizmor-action) to upload SARIF files. + steps: + - name: Checkout repository + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + persist-credentials: false + - name: Run zizmor + uses: zizmorcore/zizmor-action@192e21d79ab29983730a13d1382995c2307fbcaa # v0.5.7 diff --git a/.gitignore b/.gitignore index a3df1d0546d02..2c0d859ad7da1 100644 --- a/.gitignore +++ b/.gitignore @@ -7,8 +7,27 @@ __pycache__ htmlcov dist site -.coverage +site_zensical_src +.coverage* coverage.xml .netlify test.db log.txt +Pipfile.lock +env3.* +env +docs_build +site_build +venv +docs.zip +archive.zip + +# vim temporary files +*~ +.*.sw? +.cache + +# macOS +.DS_Store + +.codspeed diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000000000..eb0762df500a4 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,108 @@ +# See https://pre-commit.com for more information +# See https://pre-commit.com/hooks.html for more hooks +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: 3e8a8703264a2f4a69428a0aa4dcb512790b2c8c # v6.0.0 + hooks: + - id: check-added-large-files + args: ['--maxkb=750'] + exclude: ^uv.lock$ + - id: check-toml + - id: check-yaml + args: + - --unsafe + - id: end-of-file-fixer + - id: trailing-whitespace + + - repo: https://github.com/crate-ci/typos + rev: 37bb98842b0d8c4ffebdb75301a13db0267cef89 # v1.47.2 + hooks: + - id: typos + args: [--force-exclude] + + - repo: local + hooks: + - id: local-ruff-check + name: ruff check + entry: uv run ruff check --force-exclude --fix --exit-non-zero-on-fix + require_serial: true + language: unsupported + types: [python] + + - id: local-ruff-format + name: ruff format + entry: uv run ruff format --force-exclude --exit-non-zero-on-format + require_serial: true + language: unsupported + types: [python] + + - id: local-mypy + name: mypy check + entry: uv run mypy fastapi + require_serial: true + language: unsupported + pass_filenames: false + + - id: local-ty + name: ty check + entry: uv run ty check + require_serial: true + language: unsupported + pass_filenames: false + + - id: add-permalinks-pages + language: unsupported + name: add-permalinks-pages + entry: uv run ./scripts/docs.py add-permalinks-pages + args: + - --update-existing + files: ^docs/en/docs/.*\.md$ + + - id: generate-readme + language: unsupported + name: generate README.md from index.md + entry: uv run ./scripts/docs.py generate-readme + files: ^docs/en/docs/index\.md|docs/en/data/sponsors\.yml|scripts/docs\.py$ + pass_filenames: false + + - id: render-banner-sponsors + language: unsupported + name: render sponsor banner partial + entry: uv run ./scripts/docs.py render-banner-sponsors + files: ^docs/en/data/sponsors\.yml|^docs/en/overrides/partials/banner-sponsors\.html|^scripts/docs\.py$ + pass_filenames: false + + - id: update-languages + language: unsupported + name: update languages + entry: uv run ./scripts/docs.py update-languages + files: ^docs/.*|scripts/docs\.py$ + pass_filenames: false + + - id: ensure-non-translated + language: unsupported + name: ensure non-translated files are not modified + entry: uv run ./scripts/docs.py ensure-non-translated + files: ^docs/(?!en/).*|^scripts/docs\.py$ + pass_filenames: false + + - id: fix-translations + language: unsupported + name: fix translations + entry: uv run ./scripts/translation_fixer.py fix-pages + files: ^docs/(?!en/).*/docs/.*\.md$ + + - id: add-release-date + language: unsupported + name: add date to latest release header + entry: uv run python scripts/add_latest_release_date.py + files: ^docs/en/docs/release-notes\.md$ + pass_filenames: false + + - id: zizmor + name: zizmor + language: python + entry: uv run zizmor . + files: ^\.github/workflows/|^uv\.lock$ + require_serial: true + pass_filenames: false diff --git a/.python-version b/.python-version new file mode 100644 index 0000000000000..2c0733315e415 --- /dev/null +++ b/.python-version @@ -0,0 +1 @@ +3.11 diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 8caa67fc4e826..0000000000000 --- a/.travis.yml +++ /dev/null @@ -1,26 +0,0 @@ -dist: xenial - -language: python - -cache: pip - -python: - - "3.6" - - "3.7" - -install: - - pip install flit - - flit install --symlink - -script: - - bash scripts/test.sh - -after_script: - - bash <(curl -s https://codecov.io/bash) - -deploy: - provider: script - script: bash scripts/deploy.sh - on: - tags: true - python: "3.6" diff --git a/CITATION.cff b/CITATION.cff new file mode 100644 index 0000000000000..f147003496280 --- /dev/null +++ b/CITATION.cff @@ -0,0 +1,24 @@ +# This CITATION.cff file was generated with cffinit. +# Visit https://bit.ly/cffinit to generate yours today! + +cff-version: 1.2.0 +title: FastAPI +message: >- + If you use this software, please cite it using the + metadata from this file. +type: software +authors: + - given-names: Sebastián + family-names: Ramírez + email: tiangolo@gmail.com +identifiers: +repository-code: 'https://github.com/fastapi/fastapi' +url: 'https://fastapi.tiangolo.com' +abstract: >- + FastAPI framework, high performance, easy to learn, fast to code, + ready for production +keywords: + - fastapi + - pydantic + - starlette +license: MIT diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md deleted file mode 100644 index 7b94527252b67..0000000000000 --- a/CONTRIBUTING.md +++ /dev/null @@ -1 +0,0 @@ -Please read the [Development - Contributing](https://fastapi.tiangolo.com/contributing/) guidelines in the documentation site. diff --git a/Pipfile b/Pipfile deleted file mode 100644 index 6cc3fbb3cf988..0000000000000 --- a/Pipfile +++ /dev/null @@ -1,37 +0,0 @@ -[[source]] -name = "pypi" -url = "https://pypi.org/simple" -verify_ssl = true - -[dev-packages] -mypy = "*" -black = "*" -jupyter = "*" -better-exceptions = "*" -pytest = "*" -pytest-cov = "*" -isort = "*" -requests = "*" -flit = "*" -mkdocs = "*" -mkdocs-material = "*" -markdown-include = "*" -autoflake = "*" -email-validator = "*" -ujson = "*" -flake8 = "*" -python-multipart = "*" -sqlalchemy = "*" -uvicorn = "*" - -[packages] -starlette = "==0.12.0" -pydantic = "==0.26.0" -databases = {extras = ["sqlite"],version = "*"} -hypercorn = "*" - -[requires] -python_version = "3.6" - -[pipenv] -allow_prereleases = true diff --git a/Pipfile.lock b/Pipfile.lock deleted file mode 100644 index 83b7f94c346ba..0000000000000 --- a/Pipfile.lock +++ /dev/null @@ -1,936 +0,0 @@ -{ - "_meta": { - "hash": { - "sha256": "4a33b47e814fa75533548874ffadbc6163b3058db4d1615ff633512366d72ccb" - }, - "pipfile-spec": 6, - "requires": { - "python_version": "3.6" - }, - "sources": [ - { - "name": "pypi", - "url": "https://pypi.org/simple", - "verify_ssl": true - } - ] - }, - "default": { - "aiocontextvars": { - "hashes": [ - "sha256:885daf8261818767d8f7cbd79f9d4482d118f024b6586ef6e67980236a27bfa3", - "sha256:f027372dc48641f683c559f247bd84962becaacdc9ba711d583c3871fb5652aa" - ], - "version": "==0.2.2" - }, - "aiosqlite": { - "hashes": [ - "sha256:ad84fbd7516ca7065d799504fc41d6845c938e5306d1b7dd960caaeda12e22a9" - ], - "version": "==0.10.0" - }, - "contextvars": { - "hashes": [ - "sha256:f38c908aaa59c14335eeea12abea5f443646216c4e29380d7bf34d2018e2c39e" - ], - "markers": "python_version < '3.7'", - "version": "==2.4" - }, - "databases": { - "extras": [ - "sqlite" - ], - "hashes": [ - "sha256:d365cff2035c5177ef5fd8c5abf6671da01189521da64848a01251c870daf48f" - ], - "index": "pypi", - "version": "==0.2.2" - }, - "dataclasses": { - "hashes": [ - "sha256:454a69d788c7fda44efd71e259be79577822f5e3f53f029a22d08004e951dc9f", - "sha256:6988bd2b895eef432d562370bb707d540f32f7360ab13da45340101bc2307d84" - ], - "markers": "python_version < '3.7'", - "version": "==0.6" - }, - "h11": { - "hashes": [ - "sha256:acca6a44cb52a32ab442b1779adf0875c443c689e9e028f8d831a3769f9c5208", - "sha256:f2b1ca39bfed357d1f19ac732913d5f9faa54a5062eca7d2ec3a916cfb7ae4c7" - ], - "version": "==0.8.1" - }, - "h2": { - "hashes": [ - "sha256:c8f387e0e4878904d4978cd688a3195f6b169d49b1ffa572a3d347d7adc5e09f", - "sha256:fd07e865a3272ac6ef195d8904de92dc7b38dc28297ec39cfa22716b6d62e6eb" - ], - "version": "==3.1.0" - }, - "hpack": { - "hashes": [ - "sha256:0edd79eda27a53ba5be2dfabf3b15780928a0dff6eb0c60a3d6767720e970c89", - "sha256:8eec9c1f4bfae3408a3f30500261f7e6a65912dc138526ea054f9ad98892e9d2" - ], - "version": "==3.0.0" - }, - "hypercorn": { - "hashes": [ - "sha256:cfe7811a93ab7bc22c8a0d5514a2a7a512e812c1e4ee13b9731b705b79d4d453", - "sha256:f2577806223fa44d57d6f136b6c37a046794f961252699aec8afb15f35d226d5" - ], - "index": "pypi", - "version": "==0.5.4" - }, - "hyperframe": { - "hashes": [ - "sha256:5187962cb16dcc078f23cb5a4b110098d546c3f41ff2d4038a9896893bbd0b40", - "sha256:a9f5c17f2cc3c719b917c4f33ed1c61bd1f8dfac4b1bd23b7c80b3400971b41f" - ], - "version": "==5.2.0" - }, - "immutables": { - "hashes": [ - "sha256:10861f2a2b86139f0c91d5073392d76117f37e84f912dc47c943c23a64008cc7", - "sha256:3e23eeb4bc55d57b2a97bef4c1a2891bbb731050b4167c855545797d45e84e45", - "sha256:4373876879f147986808f71e6ca02380192a279e8b8d45832f6fed4e7f717562", - "sha256:46f9122da033fecf84d7f4c6257aec780f370b20f3ce6bc521702b63ee3d99f7", - "sha256:5104db6102e53702af45c6b0af36e45a80970123b11a80c14e0fce48444cdbe3", - "sha256:59274bcb631f4fdc9731e9a4a96d16d96b3a17e29fd5e46516518f38406f678f", - "sha256:65a9c624e50ca5c50464dbf432996b5c4f056a411bcff5690ef4cab59f913f99", - "sha256:b64e0672497b884d21170ca61c693da8488d77f043650efa7911378cbbad0f2c", - "sha256:b70655dba00742b033310933066a2202e1cfbbb0f63841b4597cd8787974b242", - "sha256:c3d8c238a6f9b60355578579563773348674b6da63c1a0d7394384ed341f3d41", - "sha256:cd66bcd11b6a1c1a80fb8d90e25870ff2d5c705ab5eb9666355a33d3fef6ac70", - "sha256:d59310fc4f97c1ff8c3660cb98032db266ac0c285a86ca7a512e8e84a95f44c9", - "sha256:d71d1c822498646143270580dd6f743bb31ab89ae0ded8b2307c356d3a00f1c0", - "sha256:f53da698b42db83cfb1f5073560838051430798c8d8e34a57a27031edbc3041d", - "sha256:f958ba15745e30d3a38e3c9fcead8496037135bb21c78c0f925c104abba3a6fa", - "sha256:ff95e2aa618eed1a0ef4479938f18f3522c89562b9bbb59d677597c0337569dd" - ], - "version": "==0.9" - }, - "pydantic": { - "hashes": [ - "sha256:b72e0df2463cee746cf42639845d4106c19f30136375e779352d710e69617731", - "sha256:dab99d3070e040b8b2e987dfbe237350ab92d5d57a22d4e0e268ede2d85c7964" - ], - "index": "pypi", - "version": "==0.26.0" - }, - "pytoml": { - "hashes": [ - "sha256:ca2d0cb127c938b8b76a9a0d0f855cf930c1d50cc3a0af6d3595b566519a1013" - ], - "version": "==0.1.20" - }, - "sqlalchemy": { - "hashes": [ - "sha256:91c54ca8345008fceaec987e10924bf07dcab36c442925357e5a467b36a38319" - ], - "version": "==1.3.3" - }, - "starlette": { - "hashes": [ - "sha256:d313433ef5cc38e0a276b59688ca2b11b8f031c78808c1afdf9d55cb86f34590" - ], - "index": "pypi", - "version": "==0.12.0" - }, - "typing-extensions": { - "hashes": [ - "sha256:07b2c978670896022a43c4b915df8958bec4a6b84add7f2c87b2b728bda3ba64", - "sha256:f3f0e67e1d42de47b5c67c32c9b26641642e9170fe7e292991793705cd5fef7c", - "sha256:fb2cd053238d33a8ec939190f30cfd736c00653a85a2919415cecf7dc3d9da71" - ], - "version": "==3.7.2" - }, - "wsproto": { - "hashes": [ - "sha256:55c3da870460e8838b2fbe4d10f3accc0cea3a13d5e8dbbdc6da5d537d6d44dc", - "sha256:c7f35e0af250b9f25583b090039eb2159a079fbe71b7daf86cc3ddcd2f3a70b3" - ], - "version": "==0.14.0" - } - }, - "develop": { - "appdirs": { - "hashes": [ - "sha256:9e5896d1372858f8dd3344faf4e5014d21849c756c8d5701f78f8a103b372d92", - "sha256:d8b24664561d0d34ddfaec54636d502d7cea6e29c3eaf68f3df6180863e2166e" - ], - "version": "==1.4.3" - }, - "atomicwrites": { - "hashes": [ - "sha256:03472c30eb2c5d1ba9227e4c2ca66ab8287fbfbbda3888aa93dc2e28fc6811b4", - "sha256:75a9445bac02d8d058d5e1fe689654ba5a6556a1dfd8ce6ec55a0ed79866cfa6" - ], - "version": "==1.3.0" - }, - "attrs": { - "hashes": [ - "sha256:69c0dbf2ed392de1cb5ec704444b08a5ef81680a61cb899dc08127123af36a79", - "sha256:f0b870f674851ecbfbbbd364d6b5cbdff9dcedbc7f3f5e18a6891057f21fe399" - ], - "version": "==19.1.0" - }, - "autoflake": { - "hashes": [ - "sha256:6b59e5b9b82e30077499578856282debb81186d10b4f899e8c2e1d616cdef973" - ], - "index": "pypi", - "version": "==1.3" - }, - "backcall": { - "hashes": [ - "sha256:38ecd85be2c1e78f77fd91700c76e14667dc21e2713b63876c0eb901196e01e4", - "sha256:bbbf4b1e5cd2bdb08f915895b51081c041bac22394fdfcfdfbe9f14b77c08bf2" - ], - "version": "==0.1.0" - }, - "better-exceptions": { - "hashes": [ - "sha256:bf79c87659bc849989d726bf0e4a2100edefe7eded112d201f54fe08467fdf63", - "sha256:c196cad849de615abb9f6eb67ca1b83f33b938818f0e2fe8fa157b22aeb7b992" - ], - "index": "pypi", - "version": "==0.2.2" - }, - "black": { - "hashes": [ - "sha256:09a9dcb7c46ed496a9850b76e4e825d6049ecd38b611f1224857a79bd985a8cf", - "sha256:68950ffd4d9169716bcb8719a56c07a2f4485354fec061cdd5910aa07369731c" - ], - "index": "pypi", - "version": "==19.3b0" - }, - "bleach": { - "hashes": [ - "sha256:213336e49e102af26d9cde77dd2d0397afabc5a6bf2fed985dc35b5d1e285a16", - "sha256:3fdf7f77adcf649c9911387df51254b813185e32b2c6619f690b593a617e19fa" - ], - "version": "==3.1.0" - }, - "certifi": { - "hashes": [ - "sha256:59b7658e26ca9c7339e00f8f4636cdfe59d34fa37b9b04f6f9e9926b3cece1a5", - "sha256:b26104d6835d1f5e49452a26eb2ff87fe7090b89dfcaee5ea2212697e1e1d7ae" - ], - "version": "==2019.3.9" - }, - "chardet": { - "hashes": [ - "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae", - "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691" - ], - "version": "==3.0.4" - }, - "click": { - "hashes": [ - "sha256:2335065e6395b9e67ca716de5f7526736bfa6ceead690adf616d925bdc622b13", - "sha256:5b94b49521f6456670fdb30cd82a4eca9412788a93fa6dd6df72c94d5a8ff2d7" - ], - "version": "==7.0" - }, - "coverage": { - "hashes": [ - "sha256:0402b1822d513d0231589494bceddb067d20581f5083598c451b56c684b0e5d6", - "sha256:0644e28e8aea9d9d563607ee8b7071b07dd57a4a3de11f8684cd33c51c0d1b93", - "sha256:0874a283686803884ec0665018881130604956dbaa344f2539c46d82cbe29eda", - "sha256:0988c3837df4bc371189bb3425d5232cf150055452034c232dda9cbe04f9c38e", - "sha256:20bc3205b3100956bb72293fabb97f0ed972c81fed10b3251c90c70dcb0599ab", - "sha256:2cc9142a3367e74eb6b19d58c53ebb1dfd7336b91cdcc91a6a2888bf8c7af984", - "sha256:3ae9a0a59b058ce0761c3bd2c2d66ecb2ee2b8ac592620184370577f7a546fb3", - "sha256:3b2e30b835df58cb973f478d09f3d82e90c98c8e5059acc245a8e4607e023801", - "sha256:401e9b04894eb1498c639c6623ee78a646990ce5f095248e2440968aafd6e90e", - "sha256:41ec5812d5decdaa72708be3018e7443e90def4b5a71294236a4df192cf9eab9", - "sha256:475769b638a055e75b3d3219e054fe2a023c0b077ff15bff6c95aba7e93e6cac", - "sha256:61424f4e2e82c4129a4ba71e10ebacb32a9ecd6f80de2cd05bdead6ba75ed736", - "sha256:811969904d4dd0bee7d958898be8d9d75cef672d9b7e7db819dfeac3d20d2d0c", - "sha256:86224bb99abfd672bf2f9fcecad5e8d7a3fa94f7f71513f2210460a0350307cd", - "sha256:9a238a20a3af00665f8381f7e53e9c606f9bb652d2423f6b822f6cb790d887e8", - "sha256:a23b3fbc14d4e6182ecebfd22f3729beef0636d151d94764a1c28330d185e4e5", - "sha256:ac162b4ebe51b7a2b7f5e462c4402802633eb81e77c94f8a7c1ed8a556e72c75", - "sha256:b6187378726c84365bf297b5dcdae8789b6a5823b200bea23797777e5a63be09", - "sha256:bcd5723d905ed4a825f17410a53535f880b6d7548ae3d89078db7b1ceefcd853", - "sha256:c48a4f9c5fb385269bb7fbaf9c1326a94863b65ec7f5c96b2ea56b252f01ad08", - "sha256:cd40199d6f1c29c85b170d25589be9a97edff8ee7e62be180a2a137823896030", - "sha256:d1bc331a7d069485ac1d8c25a0ea1f6aab6cb2a87146fb652222481c1bddc9ff", - "sha256:d7e0cdc249aa0f94aa2e531b03999ddaf03a10b4fa090a894712d4c8066abd89", - "sha256:e9ee8fcd8e067fcc5d7276d46e07e863102b70a52545ef4254df1ff0893ce75f", - "sha256:eb313c23d983b7810504f42104e8dcd1c7ccdda8fbaab82aab92ab79fea19345", - "sha256:f9cfd478654b509941b85ed70f870f5e3c74678f566bec12fd26545e5340ba47", - "sha256:fae1fa144034d021a52cb9ea200eb8dedf91869c6df8202ad5d149b41ed91cc8" - ], - "version": "==5.0a5" - }, - "decorator": { - "hashes": [ - "sha256:86156361c50488b84a3f148056ea716ca587df2f0de1d34750d35c21312725de", - "sha256:f069f3a01830ca754ba5258fde2278454a0b5b79e0d7f5c13b3b97e57d4acff6" - ], - "version": "==4.4.0" - }, - "defusedxml": { - "hashes": [ - "sha256:6687150770438374ab581bb7a1b327a847dd9c5749e396102de3fad4e8a3ef93", - "sha256:f684034d135af4c6cbb949b8a4d2ed61634515257a67299e5f940fbaa34377f5" - ], - "version": "==0.6.0" - }, - "dnspython": { - "hashes": [ - "sha256:36c5e8e38d4369a08b6780b7f27d790a292b2b08eea01607865bf0936c558e01", - "sha256:f69c21288a962f4da86e56c4905b49d11aba7938d3d740e80d9e366ee4f1632d" - ], - "version": "==1.16.0" - }, - "docutils": { - "hashes": [ - "sha256:02aec4bd92ab067f6ff27a38a38a41173bf01bed8f89157768c1573f53e474a6", - "sha256:51e64ef2ebfb29cae1faa133b3710143496eca21c530f3f71424d77687764274", - "sha256:7a4bd47eaf6596e1295ecb11361139febe29b084a87bf005bf899f9a42edc3c6" - ], - "version": "==0.14" - }, - "email-validator": { - "hashes": [ - "sha256:79966e318d6d68fed359c90f8f19d242bcc178b724011f1c07145bd093da6cc7" - ], - "index": "pypi", - "version": "==1.0.4" - }, - "entrypoints": { - "hashes": [ - "sha256:589f874b313739ad35be6e0cd7efde2a4e9b6fea91edcc34e58ecbb8dbe56d19", - "sha256:c70dd71abe5a8c85e55e12c19bd91ccfeec11a6e99044204511f9ed547d48451" - ], - "version": "==0.3" - }, - "flake8": { - "hashes": [ - "sha256:859996073f341f2670741b51ec1e67a01da142831aa1fdc6242dbf88dffbe661", - "sha256:a796a115208f5c03b18f332f7c11729812c8c3ded6c46319c59b53efd3819da8" - ], - "index": "pypi", - "version": "==3.7.7" - }, - "flit": { - "hashes": [ - "sha256:1d93f7a833ed8a6e120ddc40db5c4763bc39bccc75c05081ec8285ece718aefb", - "sha256:6f6f0fb83c51ffa3a150fa41b5ac118df9ea4a87c2c06dff4ebf9adbe7b52b36" - ], - "index": "pypi", - "version": "==1.3" - }, - "h11": { - "hashes": [ - "sha256:acca6a44cb52a32ab442b1779adf0875c443c689e9e028f8d831a3769f9c5208", - "sha256:f2b1ca39bfed357d1f19ac732913d5f9faa54a5062eca7d2ec3a916cfb7ae4c7" - ], - "version": "==0.8.1" - }, - "httptools": { - "hashes": [ - "sha256:e00cbd7ba01ff748e494248183abc6e153f49181169d8a3d41bb49132ca01dfc" - ], - "version": "==0.0.13" - }, - "idna": { - "hashes": [ - "sha256:c357b3f628cf53ae2c4c05627ecc484553142ca23264e593d327bcde5e9c3407", - "sha256:ea8b7f6188e6fa117537c3df7da9fc686d485087abf6ac197f9c46432f7e4a3c" - ], - "version": "==2.8" - }, - "ipykernel": { - "hashes": [ - "sha256:346189536b88859937b5f4848a6fd85d1ad0729f01724a411de5cae9b618819c", - "sha256:f0e962052718068ad3b1d8bcc703794660858f58803c3798628817f492a8769c" - ], - "version": "==5.1.1" - }, - "ipython": { - "hashes": [ - "sha256:54c5a8aa1eadd269ac210b96923688ccf01ebb2d0f21c18c3c717909583579a8", - "sha256:e840810029224b56cd0d9e7719dc3b39cf84d577f8ac686547c8ba7a06eeab26" - ], - "markers": "python_version >= '3.3'", - "version": "==7.5.0" - }, - "ipython-genutils": { - "hashes": [ - "sha256:72dd37233799e619666c9f639a9da83c34013a73e8bbc79a7a6348d93c61fab8", - "sha256:eb2e116e75ecef9d4d228fdc66af54269afa26ab4463042e33785b887c628ba8" - ], - "version": "==0.2.0" - }, - "ipywidgets": { - "hashes": [ - "sha256:0f2b5cde9f272cb49d52f3f0889fdd1a7ae1e74f37b48dac35a83152780d2b7b", - "sha256:a3e224f430163f767047ab9a042fc55adbcab0c24bbe6cf9f306c4f89fdf0ba3" - ], - "version": "==7.4.2" - }, - "isort": { - "hashes": [ - "sha256:c40744b6bc5162bbb39c1257fe298b7a393861d50978b565f3ccd9cb9de0182a", - "sha256:f57abacd059dc3bd666258d1efb0377510a89777fda3e3274e3c01f7c03ae22d" - ], - "index": "pypi", - "version": "==4.3.20" - }, - "jedi": { - "hashes": [ - "sha256:2bb0603e3506f708e792c7f4ad8fc2a7a9d9c2d292a358fbbd58da531695595b", - "sha256:2c6bcd9545c7d6440951b12b44d373479bf18123a401a52025cf98563fbd826c" - ], - "version": "==0.13.3" - }, - "jinja2": { - "hashes": [ - "sha256:065c4f02ebe7f7cf559e49ee5a95fb800a9e4528727aec6f24402a5374c65013", - "sha256:14dd6caf1527abb21f08f86c784eac40853ba93edb79552aa1e4b8aef1b61c7b" - ], - "version": "==2.10.1" - }, - "jsonschema": { - "hashes": [ - "sha256:0c0a81564f181de3212efa2d17de1910f8732fa1b71c42266d983cd74304e20d", - "sha256:a5f6559964a3851f59040d3b961de5e68e70971afb88ba519d27e6a039efff1a" - ], - "version": "==3.0.1" - }, - "jupyter": { - "hashes": [ - "sha256:3e1f86076bbb7c8c207829390305a2b1fe836d471ed54be66a3b8c41e7f46cc7", - "sha256:5b290f93b98ffbc21c0c7e749f054b3267782166d72fa5e3ed1ed4eaf34a2b78", - "sha256:d9dc4b3318f310e34c82951ea5d6683f67bed7def4b259fafbfe4f1beb1d8e5f" - ], - "index": "pypi", - "version": "==1.0.0" - }, - "jupyter-client": { - "hashes": [ - "sha256:b5f9cb06105c1d2d30719db5ffb3ea67da60919fb68deaefa583deccd8813551", - "sha256:c44411eb1463ed77548bc2d5ec0d744c9b81c4a542d9637c7a52824e2121b987" - ], - "version": "==5.2.4" - }, - "jupyter-console": { - "hashes": [ - "sha256:308ce876354924fb6c540b41d5d6d08acfc946984bf0c97777c1ddcb42e0b2f5", - "sha256:cc80a97a5c389cbd30252ffb5ce7cefd4b66bde98219edd16bf5cb6f84bb3568" - ], - "version": "==6.0.0" - }, - "jupyter-core": { - "hashes": [ - "sha256:927d713ffa616ea11972534411544589976b2493fc7e09ad946e010aa7eb9970", - "sha256:ba70754aa680300306c699790128f6fbd8c306ee5927976cbe48adacf240c0b7" - ], - "version": "==4.4.0" - }, - "livereload": { - "hashes": [ - "sha256:78d55f2c268a8823ba499305dcac64e28ddeb9a92571e12d543cd304faf5817b", - "sha256:89254f78d7529d7ea0a3417d224c34287ebfe266b05e67e51facaf82c27f0f66" - ], - "version": "==2.6.1" - }, - "markdown": { - "hashes": [ - "sha256:2e50876bcdd74517e7b71f3e7a76102050edec255b3983403f1a63e7c8a41e7a", - "sha256:56a46ac655704b91e5b7e6326ce43d5ef72411376588afa1dd90e881b83c7e8c" - ], - "version": "==3.1.1" - }, - "markdown-include": { - "hashes": [ - "sha256:72a45461b589489a088753893bc95c5fa5909936186485f4ed55caa57d10250f" - ], - "index": "pypi", - "version": "==0.5.1" - }, - "markupsafe": { - "hashes": [ - "sha256:00bc623926325b26bb9605ae9eae8a215691f33cae5df11ca5424f06f2d1f473", - "sha256:09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161", - "sha256:09c4b7f37d6c648cb13f9230d847adf22f8171b1ccc4d5682398e77f40309235", - "sha256:1027c282dad077d0bae18be6794e6b6b8c91d58ed8a8d89a89d59693b9131db5", - "sha256:24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff", - "sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b", - "sha256:43a55c2930bbc139570ac2452adf3d70cdbb3cfe5912c71cdce1c2c6bbd9c5d1", - "sha256:46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e", - "sha256:500d4957e52ddc3351cabf489e79c91c17f6e0899158447047588650b5e69183", - "sha256:535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66", - "sha256:62fe6c95e3ec8a7fad637b7f3d372c15ec1caa01ab47926cfdf7a75b40e0eac1", - "sha256:6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1", - "sha256:717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e", - "sha256:79855e1c5b8da654cf486b830bd42c06e8780cea587384cf6545b7d9ac013a0b", - "sha256:7c1699dfe0cf8ff607dbdcc1e9b9af1755371f92a68f706051cc8c37d447c905", - "sha256:88e5fcfb52ee7b911e8bb6d6aa2fd21fbecc674eadd44118a9cc3863f938e735", - "sha256:8defac2f2ccd6805ebf65f5eeb132adcf2ab57aa11fdf4c0dd5169a004710e7d", - "sha256:98c7086708b163d425c67c7a91bad6e466bb99d797aa64f965e9d25c12111a5e", - "sha256:9add70b36c5666a2ed02b43b335fe19002ee5235efd4b8a89bfcf9005bebac0d", - "sha256:9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c", - "sha256:ade5e387d2ad0d7ebf59146cc00c8044acbd863725f887353a10df825fc8ae21", - "sha256:b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2", - "sha256:b1282f8c00509d99fef04d8ba936b156d419be841854fe901d8ae224c59f0be5", - "sha256:b2051432115498d3562c084a49bba65d97cf251f5a331c64a12ee7e04dacc51b", - "sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6", - "sha256:c8716a48d94b06bb3b2524c2b77e055fb313aeb4ea620c8dd03a105574ba704f", - "sha256:cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f", - "sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7" - ], - "version": "==1.1.1" - }, - "mccabe": { - "hashes": [ - "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42", - "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f" - ], - "version": "==0.6.1" - }, - "mistune": { - "hashes": [ - "sha256:59a3429db53c50b5c6bcc8a07f8848cb00d7dc8bdb431a4ab41920d201d4756e", - "sha256:88a1051873018da288eee8538d476dffe1262495144b33ecb586c4ab266bb8d4" - ], - "version": "==0.8.4" - }, - "mkdocs": { - "hashes": [ - "sha256:17d34329aad75d5de604b9ed4e31df3a4d235afefdc46ce7b1964fddb2e1e939", - "sha256:8cc8b38325456b9e942c981a209eaeb1e9f3f77b493ad755bfef889b9c8d356a" - ], - "index": "pypi", - "version": "==1.0.4" - }, - "mkdocs-material": { - "hashes": [ - "sha256:1c39b6af13a900d9f47ab2b8ac67b3258799f4570b552573e9d6868ad6a438e9", - "sha256:22073941cff7176e810b719aced6a90381e64a96d346b8a6803a06b7192b7ad5" - ], - "index": "pypi", - "version": "==4.3.0" - }, - "more-itertools": { - "hashes": [ - "sha256:2112d2ca570bb7c3e53ea1a35cd5df42bb0fd10c45f0fb97178679c3c03d64c7", - "sha256:c3e4748ba1aad8dba30a4886b0b1a2004f9a863837b8654e7059eebf727afa5a" - ], - "markers": "python_version > '2.7'", - "version": "==7.0.0" - }, - "mypy": { - "hashes": [ - "sha256:2afe51527b1f6cdc4a5f34fc90473109b22bf7f21086ba3e9451857cf11489e6", - "sha256:56a16df3e0abb145d8accd5dbb70eba6c4bd26e2f89042b491faa78c9635d1e2", - "sha256:5764f10d27b2e93c84f70af5778941b8f4aa1379b2430f85c827e0f5464e8714", - "sha256:5bbc86374f04a3aa817622f98e40375ccb28c4836f36b66706cf3c6ccce86eda", - "sha256:6a9343089f6377e71e20ca734cd8e7ac25d36478a9df580efabfe9059819bf82", - "sha256:6c9851bc4a23dc1d854d3f5dfd5f20a016f8da86bcdbb42687879bb5f86434b0", - "sha256:b8e85956af3fcf043d6f87c91cbe8705073fc67029ba6e22d3468bfee42c4823", - "sha256:b9a0af8fae490306bc112229000aa0c2ccc837b49d29a5c42e088c132a2334dd", - "sha256:bbf643528e2a55df2c1587008d6e3bda5c0445f1240dfa85129af22ae16d7a9a", - "sha256:c46ab3438bd21511db0f2c612d89d8344154c0c9494afc7fbc932de514cf8d15", - "sha256:f7a83d6bd805855ef83ec605eb01ab4fa42bcef254b13631e451cbb44914a9b0" - ], - "index": "pypi", - "version": "==0.701" - }, - "mypy-extensions": { - "hashes": [ - "sha256:37e0e956f41369209a3d5f34580150bcacfabaa57b33a15c0b25f4b5725e0812", - "sha256:b16cabe759f55e3409a7d231ebd2841378fb0c27a5d1994719e340e4f429ac3e" - ], - "version": "==0.4.1" - }, - "nbconvert": { - "hashes": [ - "sha256:138381baa41d83584459b5cfecfc38c800ccf1f37d9ddd0bd440783346a4c39c", - "sha256:4a978548d8383f6b2cfca4a3b0543afb77bc7cb5a96e8b424337ab58c12da9bc" - ], - "version": "==5.5.0" - }, - "nbformat": { - "hashes": [ - "sha256:b9a0dbdbd45bb034f4f8893cafd6f652ea08c8c1674ba83f2dc55d3955743b0b", - "sha256:f7494ef0df60766b7cabe0a3651556345a963b74dbc16bc7c18479041170d402" - ], - "version": "==4.4.0" - }, - "notebook": { - "hashes": [ - "sha256:573e0ae650c5d76b18b6e564ba6d21bf321d00847de1d215b418acb64f056eb8", - "sha256:f64fa6624d2323fbef6210a621817d6505a45d0d4a9367f1843b20a38a4666ee" - ], - "version": "==5.7.8" - }, - "pandocfilters": { - "hashes": [ - "sha256:b3dd70e169bb5449e6bc6ff96aea89c5eea8c5f6ab5e207fc2f521a2cf4a0da9" - ], - "version": "==1.4.2" - }, - "parso": { - "hashes": [ - "sha256:17cc2d7a945eb42c3569d4564cdf49bde221bc2b552af3eca9c1aad517dcdd33", - "sha256:2e9574cb12e7112a87253e14e2c380ce312060269d04bd018478a3c92ea9a376" - ], - "version": "==0.4.0" - }, - "pexpect": { - "hashes": [ - "sha256:2094eefdfcf37a1fdbfb9aa090862c1a4878e5c7e0e7e7088bdb511c558e5cd1", - "sha256:9e2c1fd0e6ee3a49b28f95d4b33bc389c89b20af6a1255906e90ff1262ce62eb" - ], - "markers": "sys_platform != 'win32'", - "version": "==4.7.0" - }, - "pickleshare": { - "hashes": [ - "sha256:87683d47965c1da65cdacaf31c8441d12b8044cdec9aca500cd78fc2c683afca", - "sha256:9649af414d74d4df115d5d718f82acb59c9d418196b7b4290ed47a12ce62df56" - ], - "version": "==0.7.5" - }, - "pluggy": { - "hashes": [ - "sha256:25a1bc1d148c9a640211872b4ff859878d422bccb59c9965e04eed468a0aa180", - "sha256:964cedd2b27c492fbf0b7f58b3284a09cf7f99b0f715941fb24a439b3af1bd1a" - ], - "version": "==0.11.0" - }, - "prometheus-client": { - "hashes": [ - "sha256:1b38b958750f66f208bcd9ab92a633c0c994d8859c831f7abc1f46724fcee490" - ], - "version": "==0.6.0" - }, - "prompt-toolkit": { - "hashes": [ - "sha256:11adf3389a996a6d45cc277580d0d53e8a5afd281d0c9ec71b28e6f121463780", - "sha256:2519ad1d8038fd5fc8e770362237ad0364d16a7650fb5724af6997ed5515e3c1", - "sha256:977c6583ae813a37dc1c2e1b715892461fcbdaa57f6fc62f33a528c4886c8f55" - ], - "version": "==2.0.9" - }, - "ptyprocess": { - "hashes": [ - "sha256:923f299cc5ad920c68f2bc0bc98b75b9f838b93b599941a6b63ddbc2476394c0", - "sha256:d7cc528d76e76342423ca640335bd3633420dc1366f258cb31d05e865ef5ca1f" - ], - "markers": "os_name != 'nt'", - "version": "==0.6.0" - }, - "py": { - "hashes": [ - "sha256:64f65755aee5b381cea27766a3a147c3f15b9b6b9ac88676de66ba2ae36793fa", - "sha256:dc639b046a6e2cff5bbe40194ad65936d6ba360b52b3c3fe1d08a82dd50b5e53" - ], - "version": "==1.8.0" - }, - "pycodestyle": { - "hashes": [ - "sha256:95a2219d12372f05704562a14ec30bc76b05a5b297b21a5dfe3f6fac3491ae56", - "sha256:e40a936c9a450ad81df37f549d676d127b1b66000a6c500caa2b085bc0ca976c" - ], - "version": "==2.5.0" - }, - "pyflakes": { - "hashes": [ - "sha256:17dbeb2e3f4d772725c777fabc446d5634d1038f234e77343108ce445ea69ce0", - "sha256:d976835886f8c5b31d47970ed689944a0262b5f3afa00a5a7b4dc81e5449f8a2" - ], - "version": "==2.1.1" - }, - "pygments": { - "hashes": [ - "sha256:31cba6ffb739f099a85e243eff8cb717089fdd3c7300767d9fc34cb8e1b065f5", - "sha256:5ad302949b3c98dd73f8d9fcdc7e9cb592f120e32a18e23efd7f3dc51194472b" - ], - "version": "==2.4.0" - }, - "pymdown-extensions": { - "hashes": [ - "sha256:25b0a7967fa697b5035e23340a48594e3e93acb10b06d74574218ace3347d1df", - "sha256:6cf0cf36b5a03b291ace22dc2f320f4789ce56fbdb6635a3be5fadbf5d7694dd" - ], - "version": "==6.0" - }, - "pyrsistent": { - "hashes": [ - "sha256:16692ee739d42cf5e39cef8d27649a8c1fdb7aa99887098f1460057c5eb75c3a" - ], - "version": "==0.15.2" - }, - "pytest": { - "hashes": [ - "sha256:1a8aa4fa958f8f451ac5441f3ac130d9fc86ea38780dd2715e6d5c5882700b24", - "sha256:b8bf138592384bd4e87338cb0f256bf5f615398a649d4bd83915f0e4047a5ca6" - ], - "index": "pypi", - "version": "==4.5.0" - }, - "pytest-cov": { - "hashes": [ - "sha256:2b097cde81a302e1047331b48cadacf23577e431b61e9c6f49a1170bbe3d3da6", - "sha256:e00ea4fdde970725482f1f35630d12f074e121a23801aabf2ae154ec6bdd343a" - ], - "index": "pypi", - "version": "==2.7.1" - }, - "python-dateutil": { - "hashes": [ - "sha256:7e6584c74aeed623791615e26efd690f29817a27c73085b78e4bad02493df2fb", - "sha256:c89805f6f4d64db21ed966fda138f8a5ed7a4fdbc1a8ee329ce1b74e3c74da9e" - ], - "version": "==2.8.0" - }, - "python-multipart": { - "hashes": [ - "sha256:f7bb5f611fc600d15fa47b3974c8aa16e93724513b49b5f95c81e6624c83fa43" - ], - "index": "pypi", - "version": "==0.0.5" - }, - "pytoml": { - "hashes": [ - "sha256:ca2d0cb127c938b8b76a9a0d0f855cf930c1d50cc3a0af6d3595b566519a1013" - ], - "version": "==0.1.20" - }, - "pyyaml": { - "hashes": [ - "sha256:1adecc22f88d38052fb787d959f003811ca858b799590a5eaa70e63dca50308c", - "sha256:436bc774ecf7c103814098159fbb84c2715d25980175292c648f2da143909f95", - "sha256:460a5a4248763f6f37ea225d19d5c205677d8d525f6a83357ca622ed541830c2", - "sha256:5a22a9c84653debfbf198d02fe592c176ea548cccce47553f35f466e15cf2fd4", - "sha256:7a5d3f26b89d688db27822343dfa25c599627bc92093e788956372285c6298ad", - "sha256:9372b04a02080752d9e6f990179a4ab840227c6e2ce15b95e1278456664cf2ba", - "sha256:a5dcbebee834eaddf3fa7366316b880ff4062e4bcc9787b78c7fbb4a26ff2dd1", - "sha256:aee5bab92a176e7cd034e57f46e9df9a9862a71f8f37cad167c6fc74c65f5b4e", - "sha256:c51f642898c0bacd335fc119da60baae0824f2cde95b0330b56c0553439f0673", - "sha256:c68ea4d3ba1705da1e0d85da6684ac657912679a649e8868bd850d2c299cce13", - "sha256:e23d0cc5299223dcc37885dae624f382297717e459ea24053709675a976a3e19" - ], - "version": "==5.1" - }, - "pyzmq": { - "hashes": [ - "sha256:1651e52ed91f0736afd6d94ef9f3259b5534ce8beddb054f3d5ca989c4ef7c4f", - "sha256:5ccb9b3d4cd20c000a9b75689d5add8cd3bce67fcbd0f8ae1b59345247d803af", - "sha256:5e120c4cd3872e332fb35d255ad5998ebcee32ace4387b1b337416b6b90436c7", - "sha256:5e2a3707c69a7281a9957f83718815fd74698cba31f6d69f9ed359921f662221", - "sha256:63d51add9af8d0442dc90f916baf98fdc04e3b0a32afec4bfc83f8d85e72959f", - "sha256:65c5a0bdc49e20f7d6b03a661f71e2fda7a99c51270cafe71598146d09810d0d", - "sha256:66828fabe911aa545d919028441a585edb7c9c77969a5fea6722ef6e6ece38ab", - "sha256:7d79427e82d9dad6e9b47c0b3e7ae5f9d489b1601e3a36ea629bb49501a4daf3", - "sha256:824ee5d3078c4eae737ffc500fbf32f2b14e6ec89b26b435b7834febd70120cf", - "sha256:89dc0a83cccec19ff3c62c091e43e66e0183d1e6b4658c16ee4e659518131494", - "sha256:8b319805f6f7c907b101c864c3ca6cefc9db8ce0791356f180b1b644c7347e4c", - "sha256:90facfb379ab47f94b19519c1ecc8ec8d10813b69d9c163117944948bdec5d15", - "sha256:a0a178c7420021fc0730180a914a4b4b3092ce9696ceb8e72d0f60f8ce1655dd", - "sha256:a7a89591ae315baccb8072f216614b3e59aed7385aef4393a6c741783d6ee9cf", - "sha256:ba2578f0ae582452c02ed9fac2dc477b08e80ce05d2c0885becf5fff6651ccb0", - "sha256:c69b0055c55702f5b0b6b354133e8325b9a56dbc80e1be2d240bead253fb9825", - "sha256:ca434e1858fe222380221ddeb81e86f45522773344c9da63c311d17161df5e06", - "sha256:d4b8ecfc3d92f114f04d5c40f60a65e5196198b827503341521dda12d8b14939", - "sha256:d706025c47b09a54f005953ebe206f6d07a22516776faa4f509aaff681cc5468", - "sha256:d8f27e958f8a2c0c8ffd4d8855c3ce8ac3fa1e105f0491ce31729aa2b3229740", - "sha256:dbd264298f76b9060ce537008eb989317ca787c857e23cbd1b3ddf89f190a9b1", - "sha256:e926d66f0df8fdbf03ba20583af0f215e475c667fb033d45fd031c66c63e34c9", - "sha256:efc3bd48237f973a749f7312f68062f1b4ca5c2032a0673ca3ea8e46aa77187b", - "sha256:f59bc782228777cbfe04555707a9c56d269c787ed25d6d28ed9d0fbb41cb1ad2", - "sha256:f8da5322f4ff5f667a0d5a27e871b560c6637153c81e318b35cb012b2a98835c" - ], - "version": "==18.0.1" - }, - "qtconsole": { - "hashes": [ - "sha256:a667558c7b1e1442a2e5bcef1686c55e096efd0b58d8b2a0a8415f4579991ee3", - "sha256:fdfc6002d9d2834c88f9c92e0f6f590284ff3740fa53016f188a62d58bcca6d8" - ], - "version": "==4.4.4" - }, - "requests": { - "hashes": [ - "sha256:11e007a8a2aa0323f5a921e9e6a2d7e4e67d9877e85773fba9ba6419025cbeb4", - "sha256:9cf5292fcd0f598c671cfc1e0d7d1a7f13bb8085e9a590f48c010551dc6c4b31" - ], - "index": "pypi", - "version": "==2.22.0" - }, - "send2trash": { - "hashes": [ - "sha256:60001cc07d707fe247c94f74ca6ac0d3255aabcb930529690897ca2a39db28b2", - "sha256:f1691922577b6fa12821234aeb57599d887c4900b9ca537948d2dac34aea888b" - ], - "version": "==1.5.0" - }, - "six": { - "hashes": [ - "sha256:3350809f0555b11f552448330d0b52d5f24c91a322ea4a15ef22629740f3761c", - "sha256:d16a0141ec1a18405cd4ce8b4613101da75da0e9a7aec5bdd4fa804d0e0eba73" - ], - "version": "==1.12.0" - }, - "sqlalchemy": { - "hashes": [ - "sha256:91c54ca8345008fceaec987e10924bf07dcab36c442925357e5a467b36a38319" - ], - "version": "==1.3.3" - }, - "terminado": { - "hashes": [ - "sha256:d9d012de63acb8223ac969c17c3043337c2fcfd28f3aea1ee429b345d01ef460", - "sha256:de08e141f83c3a0798b050ecb097ab6259c3f0331b2f7b7750c9075ced2c20c2" - ], - "version": "==0.8.2" - }, - "testpath": { - "hashes": [ - "sha256:46c89ebb683f473ffe2aab0ed9f12581d4d078308a3cb3765d79c6b2317b0109", - "sha256:b694b3d9288dbd81685c5d2e7140b81365d46c29f5db4bc659de5aa6b98780f8" - ], - "version": "==0.4.2" - }, - "toml": { - "hashes": [ - "sha256:229f81c57791a41d65e399fc06bf0848bab550a9dfd5ed66df18ce5f05e73d5c", - "sha256:235682dd292d5899d361a811df37e04a8828a5b1da3115886b73cf81ebc9100e" - ], - "version": "==0.10.0" - }, - "tornado": { - "hashes": [ - "sha256:1174dcb84d08887b55defb2cda1986faeeea715fff189ef3dc44cce99f5fca6b", - "sha256:2613fab506bd2aedb3722c8c64c17f8f74f4070afed6eea17f20b2115e445aec", - "sha256:44b82bc1146a24e5b9853d04c142576b4e8fa7a92f2e30bc364a85d1f75c4de2", - "sha256:457fcbee4df737d2defc181b9073758d73f54a6cfc1f280533ff48831b39f4a8", - "sha256:49603e1a6e24104961497ad0c07c799aec1caac7400a6762b687e74c8206677d", - "sha256:8c2f40b99a8153893793559919a355d7b74649a11e59f411b0b0a1793e160bc0", - "sha256:e1d897889c3b5a829426b7d52828fb37b28bc181cd598624e65c8be40ee3f7fa" - ], - "version": "==6.0.2" - }, - "traitlets": { - "hashes": [ - "sha256:9c4bd2d267b7153df9152698efb1050a5d84982d3384a37b2c1f7723ba3e7835", - "sha256:c6cb5e6f57c5a9bdaa40fa71ce7b4af30298fbab9ece9815b5d995ab6217c7d9" - ], - "version": "==4.3.2" - }, - "typed-ast": { - "hashes": [ - "sha256:132eae51d6ef3ff4a8c47c393a4ef5ebf0d1aecc96880eb5d6c8ceab7017cc9b", - "sha256:18141c1484ab8784006c839be8b985cfc82a2e9725837b0ecfa0203f71c4e39d", - "sha256:2baf617f5bbbfe73fd8846463f5aeafc912b5ee247f410700245d68525ec584a", - "sha256:3d90063f2cbbe39177e9b4d888e45777012652d6110156845b828908c51ae462", - "sha256:4304b2218b842d610aa1a1d87e1dc9559597969acc62ce717ee4dfeaa44d7eee", - "sha256:4983ede548ffc3541bae49a82675996497348e55bafd1554dc4e4a5d6eda541a", - "sha256:5315f4509c1476718a4825f45a203b82d7fdf2a6f5f0c8f166435975b1c9f7d4", - "sha256:6cdfb1b49d5345f7c2b90d638822d16ba62dc82f7616e9b4caa10b72f3f16649", - "sha256:7b325f12635598c604690efd7a0197d0b94b7d7778498e76e0710cd582fd1c7a", - "sha256:8d3b0e3b8626615826f9a626548057c5275a9733512b137984a68ba1598d3d2f", - "sha256:8f8631160c79f53081bd23446525db0bc4c5616f78d04021e6e434b286493fd7", - "sha256:912de10965f3dc89da23936f1cc4ed60764f712e5fa603a09dd904f88c996760", - "sha256:b010c07b975fe853c65d7bbe9d4ac62f1c69086750a574f6292597763781ba18", - "sha256:c908c10505904c48081a5415a1e295d8403e353e0c14c42b6d67f8f97fae6616", - "sha256:c94dd3807c0c0610f7c76f078119f4ea48235a953512752b9175f9f98f5ae2bd", - "sha256:ce65dee7594a84c466e79d7fb7d3303e7295d16a83c22c7c4037071b059e2c21", - "sha256:eaa9cfcb221a8a4c2889be6f93da141ac777eb8819f077e1d09fb12d00a09a93", - "sha256:f3376bc31bad66d46d44b4e6522c5c21976bf9bca4ef5987bb2bf727f4506cbb", - "sha256:f9202fa138544e13a4ec1a6792c35834250a85958fde1251b6a22e07d1260ae7" - ], - "version": "==1.3.5" - }, - "ujson": { - "hashes": [ - "sha256:f66073e5506e91d204ab0c614a148d5aa938bdbf104751be66f8ad7a222f5f86" - ], - "index": "pypi", - "version": "==1.35" - }, - "urllib3": { - "hashes": [ - "sha256:a53063d8b9210a7bdec15e7b272776b9d42b2fd6816401a0d43006ad2f9902db", - "sha256:d363e3607d8de0c220d31950a8f38b18d5ba7c0830facd71a1c6b1036b7ce06c" - ], - "version": "==1.25.2" - }, - "uvicorn": { - "hashes": [ - "sha256:c10da7a54a6552279870900c881a2f1726314e2dd6270d4d3f9251683c643783" - ], - "index": "pypi", - "version": "==0.7.1" - }, - "uvloop": { - "hashes": [ - "sha256:0fcd894f6fc3226a962ee7ad895c4f52e3f5c3c55098e21efb17c071849a0573", - "sha256:2f31de1742c059c96cb76b91c5275b22b22b965c886ee1fced093fa27dde9e64", - "sha256:459e4649fcd5ff719523de33964aa284898e55df62761e7773d088823ccbd3e0", - "sha256:67867aafd6e0bc2c30a079603a85d83b94f23c5593b3cc08ec7e58ac18bf48e5", - "sha256:8c200457e6847f28d8bb91c5e5039d301716f5f2fce25646f5fb3fd65eda4a26", - "sha256:958906b9ca39eb158414fbb7d6b8ef1b7aee4db5c8e8e5d00fcbb69a1ce9dca7", - "sha256:ac1dca3d8f3ef52806059e81042ee397ac939e5a86c8a3cea55d6b087db66115", - "sha256:b284c22d8938866318e3b9d178142b8be316c52d16fcfe1560685a686718a021", - "sha256:c48692bf4587ce281d641087658eca275a5ad3b63c78297bbded96570ae9ce8f", - "sha256:fefc3b2b947c99737c348887db2c32e539160dcbeb7af9aa6b53db7a283538fe" - ], - "version": "==0.12.2" - }, - "wcwidth": { - "hashes": [ - "sha256:3df37372226d6e63e1b1e1eda15c594bca98a22d33a23832a90998faa96bc65e", - "sha256:f4ebe71925af7b40a864553f761ed559b43544f8f71746c2d756c7fe788ade7c" - ], - "version": "==0.1.7" - }, - "webencodings": { - "hashes": [ - "sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78", - "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923" - ], - "version": "==0.5.1" - }, - "websockets": { - "hashes": [ - "sha256:04b42a1b57096ffa5627d6a78ea1ff7fad3bc2c0331ffc17bc32a4024da7fea0", - "sha256:08e3c3e0535befa4f0c4443824496c03ecc25062debbcf895874f8a0b4c97c9f", - "sha256:10d89d4326045bf5e15e83e9867c85d686b612822e4d8f149cf4840aab5f46e0", - "sha256:232fac8a1978fc1dead4b1c2fa27c7756750fb393eb4ac52f6bc87ba7242b2fa", - "sha256:4bf4c8097440eff22bc78ec76fe2a865a6e658b6977a504679aaf08f02c121da", - "sha256:51642ea3a00772d1e48fb0c492f0d3ae3b6474f34d20eca005a83f8c9c06c561", - "sha256:55d86102282a636e195dad68aaaf85b81d0bef449d7e2ef2ff79ac450bb25d53", - "sha256:564d2675682bd497b59907d2205031acbf7d3fadf8c763b689b9ede20300b215", - "sha256:5d13bf5197a92149dc0badcc2b699267ff65a867029f465accfca8abab95f412", - "sha256:5eda665f6789edb9b57b57a159b9c55482cbe5b046d7db458948370554b16439", - "sha256:5edb2524d4032be4564c65dc4f9d01e79fe8fad5f966e5b552f4e5164fef0885", - "sha256:79691794288bc51e2a3b8de2bc0272ca8355d0b8503077ea57c0716e840ebaef", - "sha256:7fcc8681e9981b9b511cdee7c580d5b005f3bb86b65bde2188e04a29f1d63317", - "sha256:8e447e05ec88b1b408a4c9cde85aa6f4b04f06aa874b9f0b8e8319faf51b1fee", - "sha256:90ea6b3e7787620bb295a4ae050d2811c807d65b1486749414f78cfd6fb61489", - "sha256:9e13239952694b8b831088431d15f771beace10edfcf9ef230cefea14f18508f", - "sha256:d40f081187f7b54d7a99d8a5c782eaa4edc335a057aa54c85059272ed826dc09", - "sha256:e1df1a58ed2468c7b7ce9a2f9752a32ad08eac2bcd56318625c3647c2cd2da6f", - "sha256:e98d0cec437097f09c7834a11c69d79fe6241729b23f656cfc227e93294fc242", - "sha256:f8d59627702d2ff27cb495ca1abdea8bd8d581de425c56e93bff6517134e0a9b", - "sha256:fc30cdf2e949a2225b012a7911d1d031df3d23e99b7eda7dfc982dc4a860dae9" - ], - "version": "==7.0" - }, - "widgetsnbextension": { - "hashes": [ - "sha256:14b2c65f9940c9a7d3b70adbe713dbd38b5ec69724eebaba034d1036cf3d4740", - "sha256:fa618be8435447a017fd1bf2c7ae922d0428056cfc7449f7a8641edf76b48265" - ], - "version": "==3.4.2" - } - } -} diff --git a/README.md b/README.md index 70d537bb039ab..36d262983b26b 100644 --- a/README.md +++ b/README.md @@ -5,94 +5,154 @@ FastAPI framework, high performance, easy to learn, fast to code, ready for production

- - Build Status + + Test - - Coverage + + Coverage - - Package version + + Package version - - Join the chat at https://gitter.im/tiangolo/fastapi + + Supported Python versions

--- -**Documentation**: https://fastapi.tiangolo.com +**Documentation**: [https://fastapi.tiangolo.com](https://fastapi.tiangolo.com) -**Source Code**: https://github.com/tiangolo/fastapi +**Source Code**: [https://github.com/fastapi/fastapi](https://github.com/fastapi/fastapi) --- -FastAPI is a modern, fast (high-performance), web framework for building APIs with Python 3.6+ based on standard Python type hints. +FastAPI is a modern, fast (high-performance), web framework for building APIs with Python based on standard Python type hints. The key features are: * **Fast**: Very high performance, on par with **NodeJS** and **Go** (thanks to Starlette and Pydantic). [One of the fastest Python frameworks available](#performance). - -* **Fast to code**: Increase the speed to develop features by about 200% to 300% *. +* **Fast to code**: Increase the speed to develop features by about 200% to 300%. * * **Fewer bugs**: Reduce about 40% of human (developer) induced errors. * -* **Intuitive**: Great editor support. Completion everywhere. Less time debugging. +* **Intuitive**: Great editor support. Completion everywhere. Less time debugging. * **Easy**: Designed to be easy to use and learn. Less time reading docs. * **Short**: Minimize code duplication. Multiple features from each parameter declaration. Fewer bugs. * **Robust**: Get production-ready code. With automatic interactive documentation. -* **Standards-based**: Based on (and fully compatible with) the open standards for APIs: OpenAPI (previously known as Swagger) and JSON Schema. +* **Standards-based**: Based on (and fully compatible with) the open standards for APIs: [OpenAPI](https://github.com/OAI/OpenAPI-Specification) (previously known as Swagger) and [JSON Schema](https://json-schema.org/). + +* estimation based on tests conducted by an internal development team, building production applications. + +## Sponsors + + +### Keystone Sponsor + + + +### Gold Sponsors + + + + + + + + + + +### Silver Sponsors + + + + + + + -* estimation based on tests on an internal development team, building production applications. + + +[Other sponsors](https://fastapi.tiangolo.com/fastapi-people/#sponsors) ## Opinions -"*[...] I'm using **FastAPI** a ton these days. [...] I'm actually planning to use it for all of my team's **ML services at Microsoft**. Some of them are getting integrated into the core **Windows** product and some **Office** products.*" -
Kabir Khan - Microsoft (ref)
+ +
+ +"_[...] I'm using **FastAPI** a ton these days. [...] I'm actually planning to use it for all of my team's **ML services at Microsoft**. Some of them are getting integrated into the core **Windows** product and some **Office** products._" + +
Kabir Khan - Microsoft (ref)
--- -"*I’m over the moon excited about **FastAPI**. It’s so fun!*" +"_We adopted the **FastAPI** library to spawn a **REST** server that can be queried to obtain **predictions**. [for Ludwig]_" -
Brian Okken - Python Bytes podcast host (ref)
+
Piero Molino, Yaroslav Dudin, and Sai Sumanth Miryala - Uber (ref)
--- -"*Honestly, what you've built looks super solid and polished. In many ways, it's what I wanted **Hug** to be - it's really inspiring to see someone build that.*" +"_**Netflix** is pleased to announce the open-source release of our **crisis management** orchestration framework: **Dispatch**! [built with **FastAPI**]_" -
Timothy Crosley - Hug creator (ref)
+
Kevin Glisson, Marc Vilanova, Forest Monsen - Netflix (ref)
--- +"_If anyone is looking to build a production Python API, I would highly recommend **FastAPI**. It is **beautifully designed**, **simple to use** and **highly scalable**, it has become a **key component** in our API first development strategy and is driving many automations and services such as our Virtual TAC Engineer._" +
Deon Pillsbury - Cisco (ref)
+--- -## Requirements +
-Python 3.6+ +## FastAPI Conf -FastAPI stands on the shoulders of giants: +[**FastAPI Conf '26**](https://fastapiconf.com) is happening on **October 28, 2026** in **Amsterdam, NL**. All about FastAPI, right from the source. 🎤 + +FastAPI Conf '26 - October 28, 2026 - Amsterdam, NL + +## FastAPI mini documentary -* Starlette for the web parts. -* Pydantic for the data parts. +There's a [FastAPI mini documentary](https://www.youtube.com/watch?v=mpR8ngthqiE) released at the end of 2025, you can watch it online: +FastAPI Mini Documentary + +## **Typer**, the FastAPI of CLIs + + + +If you are building a CLI app to be used in the terminal instead of a web API, check out [**Typer**](https://typer.tiangolo.com/). + +**Typer** is FastAPI's little sibling. And it's intended to be the **FastAPI of CLIs**. ⌨️ 🚀 + +## Requirements + +FastAPI stands on the shoulders of giants: + +* [Starlette](https://www.starlette.dev/) for the web parts. +* [Pydantic](https://docs.pydantic.dev/) for the data parts. ## Installation -```bash -$ pip install fastapi -``` +Create and activate a [virtual environment](https://fastapi.tiangolo.com/virtual-environments/) and then install FastAPI: + +
-You will also need an ASGI server, for production such as Uvicorn or Hypercorn. +```console +$ pip install "fastapi[standard]" -```bash -$ pip install uvicorn +---> 100% ``` +
+ +**Note**: Make sure you put `"fastapi[standard]"` in quotes to ensure it works in all terminals. + ## Example ### Create it -* Create a file `main.py` with: +Create a file `main.py` with: ```Python from fastapi import FastAPI @@ -106,15 +166,16 @@ def read_root(): @app.get("/items/{item_id}") -def read_item(item_id: int, q: str = None): +def read_item(item_id: int, q: str | None = None): return {"item_id": item_id, "q": q} ``` +
Or use async def... If your code uses `async` / `await`, use `async def`: -```Python hl_lines="7 12" +```Python hl_lines="7 12" from fastapi import FastAPI app = FastAPI() @@ -126,13 +187,13 @@ async def read_root(): @app.get("/items/{item_id}") -async def read_item(item_id: int, q: str = None): +async def read_item(item_id: int, q: str | None = None): return {"item_id": item_id, "q": q} ``` **Note**: - -If you don't know, check the _"In a hurry?"_ section about `async` and `await` in the docs. + +If you don't know, check the _"In a hurry?"_ section about [`async` and `await` in the docs](https://fastapi.tiangolo.com/async/#in-a-hurry).
@@ -140,24 +201,47 @@ If you don't know, check the _"In a hurry?"_ section about + +```console +$ fastapi dev + + ╭────────── FastAPI CLI - Development mode ───────────╮ + │ │ + │ Serving at: http://127.0.0.1:8000 │ + │ │ + │ API docs: http://127.0.0.1:8000/docs │ + │ │ + │ Running in development mode, for production use: │ + │ │ + │ fastapi run │ + │ │ + ╰─────────────────────────────────────────────────────╯ + +INFO: Will watch for changes in these directories: ['/home/user/code/awesomeapp'] +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +INFO: Started reloader process [2248755] using WatchFiles +INFO: Started server process [2248757] +INFO: Waiting for application startup. +INFO: Application startup complete. ``` + +
-About the command uvicorn main:app --reload... +About the command fastapi dev... -The command `uvicorn main:app` refers to: +The command `fastapi dev` reads your `main.py` file automatically, detects the **FastAPI** app in it, and starts a server using [Uvicorn](https://www.uvicorn.dev). -* `main`: the file `main.py` (the Python "module"). -* `app`: the object created inside of `main.py` with the line `app = FastAPI()`. -* `--reload`: make the server restart after code changes. Only do this for development. +By default, `fastapi dev` will start with auto-reload enabled for local development. + +You can read more about it in the [FastAPI CLI docs](https://fastapi.tiangolo.com/fastapi-cli/).
### Check it -Open your browser at
http://127.0.0.1:8000/items/5?q=somequery. +Open your browser at [http://127.0.0.1:8000/items/5?q=somequery](http://127.0.0.1:8000/items/5?q=somequery). You will see the JSON response as: @@ -174,18 +258,17 @@ You already created an API that: ### Interactive API docs -Now go to http://127.0.0.1:8000/docs. +Now go to [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs). -You will see the automatic interactive API documentation (provided by Swagger UI): +You will see the automatic interactive API documentation (provided by [Swagger UI](https://github.com/swagger-api/swagger-ui)): ![Swagger UI](https://fastapi.tiangolo.com/img/index/index-01-swagger-ui-simple.png) - ### Alternative API docs -And now, go to http://127.0.0.1:8000/redoc. +And now, go to [http://127.0.0.1:8000/redoc](http://127.0.0.1:8000/redoc). -You will see the alternative automatic documentation (provided by ReDoc): +You will see the alternative automatic documentation (provided by [ReDoc](https://github.com/Rebilly/ReDoc)): ![ReDoc](https://fastapi.tiangolo.com/img/index/index-02-redoc-simple.png) @@ -195,8 +278,7 @@ Now modify the file `main.py` to receive a body from a `PUT` request. Declare the body using standard Python types, thanks to Pydantic. - -```Python hl_lines="2 7 8 9 10 24" +```Python hl_lines="2 7-10 23-25" from fastapi import FastAPI from pydantic import BaseModel @@ -206,7 +288,7 @@ app = FastAPI() class Item(BaseModel): name: str price: float - is_offer: bool = None + is_offer: bool | None = None @app.get("/") @@ -215,7 +297,7 @@ def read_root(): @app.get("/items/{item_id}") -def read_item(item_id: int, q: str = None): +def read_item(item_id: int, q: str | None = None): return {"item_id": item_id, "q": q} @@ -224,11 +306,11 @@ def update_item(item_id: int, item: Item): return {"item_name": item.name, "item_id": item_id} ``` -The server should reload automatically (because you added `--reload` to the `uvicorn` command above). +The `fastapi dev` server should reload automatically. ### Interactive API docs upgrade -Now go to http://127.0.0.1:8000/docs. +Now go to [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs). * The interactive API documentation will be automatically updated, including the new body: @@ -242,25 +324,23 @@ Now go to http://127.0.0.1: ![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-05-swagger-04.png) - ### Alternative API docs upgrade -And now, go to http://127.0.0.1:8000/redoc. +And now, go to [http://127.0.0.1:8000/redoc](http://127.0.0.1:8000/redoc). * The alternative documentation will also reflect the new query parameter and body: ![ReDoc](https://fastapi.tiangolo.com/img/index/index-06-redoc-02.png) - ### Recap -In summary, you declare **once** the types of parameters, body, etc. as function parameters. +In summary, you declare **once** the types of parameters, body, etc. as function parameters. You do that with standard modern Python types. You don't have to learn a new syntax, the methods or classes of a specific library, etc. -Just standard **Python 3.6+**. +Just standard **Python**. For example, for an `int`: @@ -282,7 +362,7 @@ item: Item * Validation of data: * Automatic and clear errors when the data is invalid. * Validation even for deeply nested JSON objects. -* Conversion of input data: coming from the network to Python data and types. Reading from: +* Conversion of input data: coming from the network to Python data and types. Reading from: * JSON. * Path parameters. * Query parameters. @@ -290,7 +370,7 @@ item: Item * Headers. * Forms. * Files. -* Conversion of output data: converting from Python data and types to network data (as JSON): +* Conversion of output data: converting from Python data and types to network data (as JSON): * Convert Python types (`str`, `int`, `float`, `bool`, `list`, etc). * `datetime` objects. * `UUID` objects. @@ -310,9 +390,9 @@ Coming back to the previous code example, **FastAPI** will: * Check if there is an optional query parameter named `q` (as in `http://127.0.0.1:8000/items/foo?q=somequery`) for `GET` requests. * As the `q` parameter is declared with `= None`, it is optional. * Without the `None` it would be required (as is the body in the case with `PUT`). -* For `PUT` requests to `/items/{item_id}`, Read the body as JSON: - * Check that it has a required attribute `name` that should be a `str`. - * Check that is has a required attribute `price` that has to be a `float`. +* For `PUT` requests to `/items/{item_id}`, read the body as JSON: + * Check that it has a required attribute `name` that should be a `str`. + * Check that it has a required attribute `price` that has to be a `float`. * Check that it has an optional attribute `is_offer`, that should be a `bool`, if present. * All this would also work for deeply nested JSON objects. * Convert from and to JSON automatically. @@ -321,7 +401,6 @@ Coming back to the previous code example, **FastAPI** will: * Automatic client code generation systems, for many languages. * Provide 2 interactive documentation web interfaces directly. - --- We just scratched the surface, but you already get the idea of how it all works. @@ -348,55 +427,112 @@ Try changing the line with: ![editor support](https://fastapi.tiangolo.com/img/vscode-completion.png) - -For a more complete example including more features, see the Tutorial - User Guide. +For a more complete example including more features, see the Tutorial - User Guide. **Spoiler alert**: the tutorial - user guide includes: -* Declaration of **parameters** from other different places as: **headers**, **cookies**, **form fields** and **files**. -* How to set **validation constraints** as `maximum_length` or `regex`. -* A very powerful and easy to use **Dependency Injection** system. +* Declaration of **parameters** from other different places such as: **headers**, **cookies**, **form fields** and **files**. +* How to set **validation constraints** such as `maximum_length` or `regex`. +* A very powerful and easy to use **Dependency Injection** system. * Security and authentication, including support for **OAuth2** with **JWT tokens** and **HTTP Basic** auth. * More advanced (but equally easy) techniques for declaring **deeply nested JSON models** (thanks to Pydantic). -* Many extra features (thanks to Starlette) as: +* **GraphQL** integration with [Strawberry](https://strawberry.rocks) and other libraries. +* Many extra features (thanks to Starlette) such as: * **WebSockets** - * **GraphQL** - * extremely easy tests based on `requests` and `pytest` + * extremely easy tests based on HTTPX and `pytest` * **CORS** * **Cookie Sessions** * ...and more. +### Deploy your app (optional) + +You can optionally deploy your FastAPI app to [FastAPI Cloud](https://fastapicloud.com) with a single command. 🚀 + +
+ +```console +$ fastapi deploy + +Deploying to FastAPI Cloud... + +✅ Deployment successful! + +🐔 Ready the chicken! Your app is ready at https://myapp.fastapicloud.dev +``` + +
+ +The CLI will automatically detect your FastAPI application and deploy it to the cloud. If you are not logged in, your browser will open to complete the authentication process. + +That's it! Now you can access your app at that URL. ✨ + +#### About FastAPI Cloud + +**[FastAPI Cloud](https://fastapicloud.com)** 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 -Independent TechEmpower benchmarks show **FastAPI** applications running under Uvicorn as one of the fastest Python frameworks available, only below Starlette and Uvicorn themselves (used internally by FastAPI). (*) +Independent TechEmpower benchmarks show **FastAPI** applications running under Uvicorn as [one of the fastest Python frameworks available](https://www.techempower.com/benchmarks/#section=test&runid=7464e520-0dc2-473d-bd34-dbdfd7e85911&hw=ph&test=query&l=zijzen-7), only below Starlette and Uvicorn themselves (used internally by FastAPI). (*) -To understand more about it, see the section Benchmarks. +To understand more about it, see the section [Benchmarks](https://fastapi.tiangolo.com/benchmarks/). -## Optional Dependencies +## Dependencies -Used by Pydantic: +FastAPI depends on Pydantic and Starlette. + +### `standard` Dependencies -* ujson - for faster JSON "parsing". -* email_validator - for email validation. +When you install FastAPI with `pip install "fastapi[standard]"` it comes with the `standard` group of optional dependencies: + +Used by Pydantic: +* [`email-validator`](https://github.com/JoshData/python-email-validator) - for email validation. Used by Starlette: -* requests - Required if you want to use the `TestClient`. -* aiofiles - Required if you want to use `FileResponse` or `StaticFiles`. -* jinja2 - Required if you want to use the default template configuration. -* python-multipart - Required if you want to support form "parsing", with `request.form()`. -* itsdangerous - Required for `SessionMiddleware` support. -* pyyaml - Required for `SchemaGenerator` support. -* graphene - Required for `GraphQLApp` support. -* ujson - Required if you want to use `UJSONResponse`. +* [`httpx`](https://www.python-httpx.org) - Required if you want to use the `TestClient`. +* [`jinja2`](https://jinja.palletsprojects.com) - Required if you want to use the default template configuration. +* [`python-multipart`](https://github.com/Kludex/python-multipart) - Required if you want to support form "parsing", with `request.form()`. + +Used by FastAPI: + +* [`uvicorn`](https://www.uvicorn.dev) - for the server that loads and serves your application. This includes `uvicorn[standard]`, which includes some dependencies (e.g. `uvloop`) needed for high performance serving. +* `fastapi-cli[standard]` - to provide the `fastapi` command. + * This includes `fastapi-cloud-cli`, which allows you to deploy your FastAPI application to [FastAPI Cloud](https://fastapicloud.com). + +### Without `standard` Dependencies + +If you don't want to include the `standard` optional dependencies, you can install with `pip install fastapi` instead of `pip install "fastapi[standard]"`. + +### Without `fastapi-cloud-cli` + +If you want to install FastAPI with the standard dependencies but without the `fastapi-cloud-cli`, you can install with `pip install "fastapi[standard-no-fastapi-cloud-cli]"`. + +### Additional Optional Dependencies + +There are some additional dependencies you might want to install. + +Additional optional Pydantic dependencies: -Used by FastAPI / Starlette: +* [`pydantic-settings`](https://docs.pydantic.dev/latest/usage/pydantic_settings/) - for settings management. +* [`pydantic-extra-types`](https://docs.pydantic.dev/latest/usage/types/extra_types/extra_types/) - for extra types to be used with Pydantic. -* uvicorn - for the server that loads and serves your application. +Additional optional FastAPI dependencies: -You can install all of these with `pip3 install fastapi[all]`. +* [`orjson`](https://github.com/ijl/orjson) - Required if you want to use `ORJSONResponse`. +* [`ujson`](https://github.com/esnme/ultrajson) - Required if you want to use `UJSONResponse`. ## License diff --git a/docs/alternatives.md b/docs/alternatives.md deleted file mode 100644 index 1e873bb56cc43..0000000000000 --- a/docs/alternatives.md +++ /dev/null @@ -1,415 +0,0 @@ -What inspired **FastAPI**, how it compares to other alternatives and what it learned from them. - -## Intro - -**FastAPI** wouldn't exist if not for the previous work of others. - -There have been many tools created before that have helped inspire its creation. - -I have been avoiding the creation of a new framework for several years. First I tried to solve all the features covered by **FastAPI** using many different frameworks, plug-ins, and tools. - -But at some point, there was no other option than creating something that provided all these features, taking the best ideas from previous tools, and combining them in the best way possible, using language features that weren't even available before (Python 3.6+ type hints). - -## Previous tools - -### Django - -It's the most popular Python framework and is widely trusted. It is used to build systems like Instagram. - -It's relatively tightly coupled with relational databases (like MySQL or PostgreSQL), so, having a NoSQL database (like Couchbase, MongoDB, Cassandra, etc) as the main store engine is not very easy. - -It was created to generate the HTML in the backend, not to create APIs used by a modern frontend (like React, Vue.js and Angular) or by other systems (like IoT devices) communicating with it. - -### Django REST Framework - -Django REST framework was created to be a flexible toolkit for building Web APIs using Django underneath, to improve its API capabilities. - -It is used by many companies including Mozilla, Red Hat and Eventbrite. - -It was one of the first examples of **automatic API documentation**, and this was specifically one of the first ideas that inspired "the search for" **FastAPI**. - -!!! note - Django REST Framework was created by Tom Christie. The same creator of Starlette and Uvicorn, on which **FastAPI** is based. - - -!!! check "Inspired **FastAPI** to" - Have an automatic API documentation web user interface. - -### Flask - -Flask is a "microframework", it doesn't include database integrations nor many of the things that come by default in Django. - -This simplicity and flexibility allow doing things like using NoSQL databases as the main data storage system. - -As it is very simple, it's relatively intuitive to learn, although the documentation gets somewhat technical at some points. - -It is also commonly used for other applications that don't necessarily need a database, user management, or any of the many features that come pre-built in Django. Although many of these features can be added with plug-ins. - -This decoupling of parts, and being a "microframework" that could be extended to cover exactly what is needed was a key feature that I wanted to keep. - -Given the simplicity of Flask, it seemed like a good match for building APIs. The next thing to find was a "Django REST Framework" for Flask. - -!!! check "Inspired **FastAPI** to" - Be a micro-framework. Making it easy to mix and match the tools and parts needed. - - Have a simple and easy to use routing system. - - -### Requests - -**FastAPI** is not actually an alternative to **Requests**. Their scope is very different. - -It would actually be common to use Requests *inside* of a FastAPI application. - -But still, FastAPI got quite some inspiration from Requests. - -**Requests** is a library to *interact* with APIs (as a client), while **FastAPI** is a library to *build* APIs (as a server). - -They are, more or less, at opposite ends, complementing each other. - -Requests has a very simple and intuitive design, it's very easy to use, with sensible defaults. But at the same time, it's very powerful and customizable. - -That's why, as said in the official website: - -> Requests is one of the most downloaded Python packages of all time - -The way you use it is very simple. For example, to do a `GET` request, you would write: - -```Python -response = requests.get("http://example.com/some/url") -``` - -The FastAPI counterpart API path operation could look like: - -```Python hl_lines="1" -@app.get("/some/url") -def read_url(): - return {"message": "Hello World"} -``` - -See the similarities in `requests.get(...)` and `@app.get(...)`. - -!!! check "Inspired **FastAPI** to" - * Have a simple and intuitive API. - * Use HTTP method names (operations) directly, in a straightforward and intuitive way. - * Have sensible defaults, but powerful customizations. - - -### Swagger / OpenAPI - -The main feature I wanted from Django REST Framework was the automatic API documentation. - -Then I found that there was a standard to document APIs, using JSON (or YAML, an extension of JSON) called Swagger. - -And there was a web user interface for Swagger APIs already created. So, being able to generate Swagger documentation for an API would allow using this web user interface automatically. - -At some point, Swagger was given to the Linux Foundation, to be renamed OpenAPI. - -That's why when talking about version 2.0 it's common to say "Swagger", and for version 3+ "OpenAPI". - -!!! check "Inspired **FastAPI** to" - Adopt and use an open standard for API specifications, instead of a custom schema. - - And integrate standards-based user interface tools: - - * Swagger UI - * ReDoc - - These two were chosen for being fairly popular and stable, but doing a quick search, you could find dozens of additional alternative user interfaces for OpenAPI (that you can use with **FastAPI**). - -### Flask REST frameworks - -There are several Flask REST frameworks, but after investing the time and work into investigating them, I found that many are discontinued or abandoned, with several standing issues that made them unfit. - -### Marshmallow - -One of the main features needed by API systems is data "serialization" which is taking data from the code (Python) and converting it into something that can be sent through the network. For example, converting an object containing data from a database into a JSON object. Converting `datetime` objects into strings, etc. - -Another big feature needed by APIs is data validation, making sure that the data is valid, given certain parameters. For example, that some field is an `int`, and not some random string. This is especially useful for incoming data. - -Without a data validation system, you would have to do all the checks by hand, in code. - -These features are what Marshmallow was built to provide. It is a great library, and I have used it a lot before. - -But it was created before there existed Python type hints. So, to define every schema you need to use specific utils and classes provided by Marshmallow. - -!!! check "Inspired **FastAPI** to" - Use code to define "schemas" that provide data types and validation, automatically. - -### Webargs - -Another big feature required by APIs is parsing data from incoming requests. - -Webargs is a tool that was made to provide that on top of several frameworks, including Flask. - -It uses Marshmallow underneath to do the data validation. And it was created by the same guys. - -It's a great tool and I have used it a lot too, before having **FastAPI**. - -!!! info - Webargs was created by the same Marshmallow guys. - -!!! check "Inspired **FastAPI** to" - Have automatic validation of incoming request data. - -### APISpec - -Marshmallow and Webargs provide validation, parsing and serialization as plug-ins. - -But documentation is still missing. Then APISpec was created. - -It is a plug-in for many frameworks (and there's a plug-in for Starlette too). - -The way it works is that you write the definition of the schema using YAML format inside the docstring of each function handling a route. - -And it generates OpenAPI schemas. - -That's how it works in Flask, Starlette, Responder, etc. - -But then, we have again the problem of having a micro-syntax, inside of a Python string (a big YAML). - -The editor can't help much with that. And if we modify parameters or Marshmallow schemas and forget to also modify that YAML docstring, the generated schema would be obsolete. - -!!! info - APISpec was created by the same Marshmallow guys. - - -!!! check "Inspired **FastAPI** to" - Support the open standard for APIs, OpenAPI. - -### Flask-apispec - -It's a Flask plug-in, that ties together Webargs, Marshmallow and APISpec. - -It uses the information from Webargs and Marshmallow to automatically generate OpenAPI schemas, using APISpec. - -It's a great tool, very under-rated. It should be way more popular than many Flask plug-ins out there. It might be due to its documentation being too concise and abstract. - -This solved having to write YAML (another syntax) inside of Python docstrings. - -This combination of Flask, Flask-apispec with Marshmallow and Webargs was my favorite backend stack until building **FastAPI**. - -Using it led to the creation of several Flask full-stack generators. These are the main stack I (and several external teams) have been using up to now: - -* https://github.com/tiangolo/full-stack -* https://github.com/tiangolo/full-stack-flask-couchbase -* https://github.com/tiangolo/full-stack-flask-couchdb - -And these same full-stack generators were the base of the **FastAPI** project generator. - -!!! info - Flask-apispec was created by the same Marshmallow guys. - -!!! check "Inspired **FastAPI** to" - Generate the OpenAPI schema automatically, from the same code that defines serialization and validation. - -### NestJS (and Angular) - -This isn't even Python, NestJS is a JavaScript (TypeScript) NodeJS framework inspired by Angular. - -It achieves something somewhat similar to what can be done with Flask-apispec. - -It has an integrated dependency injection system, inspired by Angular two. It requires pre-registering the "injectables" (like all the other dependency injection systems I know), so, it adds to the verbosity and code repetition. - -As the parameters are described with TypeScript types (similar to Python type hints), editor support is quite good. - -But as TypeScript data is not preserved after compilation to JavaScript, it cannot rely on the types to define validation, serialization and documentation at the same time. Due to this and some design decisions, to get validation, serialization and automatic schema generation, it's needed to add decorators in many places. So, it becomes quite verbose. - -It can't handle nested models very well. So, if the JSON body in the request is a JSON object that has inner fields that in turn are nested JSON objects, it cannot be properly documented and validated. - -!!! check "Inspired **FastAPI** to" - Use Python types to have great editor support. - - Have a powerful dependency injection system. Find a way to minimize code repetition. - -### Sanic - -It was one of the first extremely fast Python frameworks based on `asyncio`. It was made to be very similar to Flask. - -!!! note "Technical Details" - It used `uvloop` instead of the default Python `asyncio` loop. That's what made it so fast. - - It still doesn't implement the ASGI spec for Python asynchronous web development, but it clearly inspired Uvicorn and Starlette, that are currently faster than Sanic in open benchmarks. - -!!! check "Inspired **FastAPI** to" - Find a way to have a crazy performance. - - That's why **FastAPI** is based on Starlette, as it is the fastest framework available (tested by third-party benchmarks). - -### Falcon - -Falcon is another high performance Python framework, it is designed to be minimal, and work as the foundation of other frameworks like Hug. - -It uses the previous standard for Python web frameworks (WSGI) which is synchronous, so it can't handle WebSockets and other use cases. Nevertheless, it also has a very good performance. - -It is designed to have functions that receive two parameters, one "request" and one "response". Then you "read" parts from the request, and "write" parts to the response. Because of this design, it is not possible to declare request parameters and bodies with standard Python type hints as function parameters. - -So, data validation, serialization, and documentation, have to be done in code, not automatically. Or they have to be implemented as a framework on top of Falcon, like Hug. This same distinction happens in other frameworks that are inspired by Falcon's design, of having one request object and one response object as parameters. - -!!! check "Inspired **FastAPI** to" - Find ways to get great performance. - - Along with Hug (as Hug is based on Falcon) inspired **FastAPI** to declare a `response` parameter in functions. - - Although in FastAPI it's optional, and is used mainly to set headers, cookies, and alternative status codes. - -### Molten - -I discovered Molten in the first stages of building **FastAPI**. And it has quite similar ideas: - -* Based on Python type hints. -* Validation and documentation from these types. -* Dependency Injection system. - -It doesn't use a data validation, serialization and documentation third-party library like Pydantic, it has its own. So, these data type definitions would not be reusable as easily. - -It requires a little bit more verbose configurations. And as it is based on WSGI (instead of ASGI), it is not designed to take advantage of the high-performance provided by tools like Uvicorn, Starlette and Sanic. - -The dependency injection system requires pre-registration of the dependencies and the dependencies are solved based on the declared types. So, it's not possible to declare more than one "component" that provides a certain type. - -Routes are declared in a single place, using functions declared in other places (instead of using decorators that can be placed right on top of the function that handles the endpoint). This is closer to how Django does it than to how Flask (and Starlette) does it. It separates in the code things that are relatively tightly coupled. - -!!! check "Inspired **FastAPI** to" - Define extra validations for data types using the "default" value of model attributes. This improves editor support, and it was not available in Pydantic before. - - This actually inspired updating parts of Pydantic, to support the same validation declaration style (all this functionality is now already available in Pydantic). - -### Hug - -Hug was one of the first frameworks to implement the declaration of API parameter types using Python type hints. This was a great idea that inspired other tools to do the same. - -It used custom types in its declarations instead of standard Python types, but it was still a huge step forward. - -It also was one of the first frameworks to generate a custom schema declaring the whole API in JSON. - -It was not based on a standard like OpenAPI and JSON Schema. So it wouldn't be straightforward to integrate it with other tools, like Swagger UI. But again, it was a very innovative idea. - -It has an interesting, uncommon feature: using the same framework, it's possible to create APIs and also CLIs. - -As it is based on the previous standard for synchronous Python web frameworks (WSGI), it can't handle Websockets and other things, although it still has high performance too. - -!!! info - Hug was created by Timothy Crosley, the same creator of `isort`, a great tool to automatically sort imports in Python files. - -!!! check "Ideas inspired in **FastAPI**" - Hug inspired parts of APIStar, and was one of the tools I found most promising, alongside APIStar. - - Hug helped inspiring **FastAPI** to use Python type hints to declare parameters, and to generate a schema defining the API automatically. - - Hug inspired **FastAPI** to declare a `response` parameter in functions to set headers and cookies. - -### APIStar (<= 0.5) - -Right before deciding to build **FastAPI** I found **APIStar** server. It had almost everything I was looking for and had a great design. - -It was one of the first implementations of a framework using Python type hints to declare parameters and requests that I ever saw (before NestJS and Molten). I found it more or less at the same time as Hug. But APIStar used the OpenAPI standard. - -It had automatic data validation, data serialization and OpenAPI schema generation based on the same type hints in several places. - -Body schema definitions didn't use the same Python type hints like Pydantic, it was a bit more similar to Marshmallow, so, editor support wouldn't be as good, but still, APIStar was the best available option. - -It had the best performance benchmarks at the time (only surpassed by Starlette). - -At first, it didn't have an automatic API documentation web UI, but I knew I could add Swagger UI to it. - -It had a dependency injection system. It required pre-registration of components, as other tools discussed above. But still, it was a great feature. - -I was never able to use it in a full project, as it didn't have security integration, so, I couldn't replace all the features I was having with the full-stack generators based on Flask-apispec. I had in my backlog of projects to create a pull request adding that functionality. - -But then, the project's focus shifted. - -It was no longer an API web framework, as the creator needed to focus on Starlette. - -Now APIStar is a set of tools to validate OpenAPI specifications, not a web framework. - -!!! info - APIStar was created by Tom Christie. The same guy that created: - - * Django REST Framework - * Starlette (in which **FastAPI** is based) - * Uvicorn (used by Starlette and **FastAPI**) - -!!! check "Inspired **FastAPI** to" - Exist. - - The idea of declaring multiple things (data validation, serialization and documentation) with the same Python types, that at the same time provided great editor support, was something I considered a brilliant idea. - - And after searching for a long time for a similar framework and testing many different alternatives, APIStar was the best option available. - - Then APIStar stopped to exist as a server and Starlette was created, and was a new better foundation for such a system. That was the final inspiration to build **FastAPI**. - - I consider **FastAPI** a "spiritual successor" to APIStar, while improving and increasing the features, typing system, and other parts, based on the learnings from all these previous tools. - -## Used by **FastAPI** - -### Pydantic - -Pydantic is a library to define data validation, serialization and documentation (using JSON Schema) based on Python type hints. - -That makes it extremely intuitive. - -It is comparable to Marshmallow. Although it's faster than Marshmallow in benchmarks. And as it is based on the same Python type hints, the editor support is great. - -!!! check "**FastAPI** uses it to" - Handle all the data validation, data serialization and automatic model documentation (based on JSON Schema). - - **FastAPI** then takes that JSON Schema data and puts it in OpenAPI, apart from all the other things it does. - -### Starlette - -Starlette is a lightweight ASGI framework/toolkit, which is ideal for building high-performance asyncio services. - -It is very simple and intuitive. It's designed to be easily extensible, and have modular components. - -It has: - -* Seriously impressive performance. -* WebSocket support. -* GraphQL support. -* In-process background tasks. -* Startup and shutdown events. -* Test client built on requests. -* CORS, GZip, Static Files, Streaming responses. -* Session and Cookie support. -* 100% test coverage. -* 100% type annotated codebase. -* Zero hard dependencies. - -Starlette is currently the fastest Python framework tested. Only surpassed by Uvicorn, which is not a framework, but a server. - -Starlette provides all the basic web microframework functionality. - -But it doesn't provide automatic data validation, serialization or documentation. - -That's one of the main things that **FastAPI** adds on top, all based on Python type hints (using Pydantic). That, plus the dependency injection system, security utilities, OpenAPI schema generation, etc. - -!!! note "Technical Details" - ASGI is a new "standard" being developed by Django core team members. It is still not a "Python standard" (a PEP), although they are in the process of doing that. - - Nevertheless, it is already being used as a "standard" by several tools. This greatly improves interoperability, as you could switch Uvicorn for any other ASGI server (like Daphne or Hypercorn), or you could add ASGI compatible tools, like `python-socketio`. - -!!! check "**FastAPI** uses it to" - Handle all the core web parts. Adding features on top. - - The class `FastAPI` itself inherits directly from the class `Starlette`. - - So, anything that you can do with Starlette, you can do it directly with **FastAPI**, as it is basically Starlette on steroids. - -### Uvicorn - -Uvicorn is a lightning-fast ASGI server, built on uvloop and httptools. - -It is not a web framework, but a server. For example, it doesn't provide tools for routing by paths. That's something that a framework like Starlette (or **FastAPI**) would provide on top. - -It is the recommended server for Starlette and **FastAPI**. - -!!! check "**FastAPI** recommends it as" - The main web server to run **FastAPI** applications. - - You can combine it with Gunicorn, to have an asynchronous multi-process server. - - Check more details in the Deployment section. - -## Benchmarks and speed - -To understand, compare, and see the difference between Uvicorn, Starlette and FastAPI, check the section about [Benchmarks](/benchmarks/). \ No newline at end of file diff --git a/docs/async.md b/docs/async.md deleted file mode 100644 index e55fe5fae2dbd..0000000000000 --- a/docs/async.md +++ /dev/null @@ -1,404 +0,0 @@ -Details about the `async def` syntax for path operation functions and some background about asynchronous code, concurrency, and parallelism. - - -## In a hurry? - -TL;DR: - -If you are using third party libraries that tell you to call them with `await`, like: - - -```Python -results = await some_library() -``` - -Then, declare your path operation functions with `async def` like: - -```Python hl_lines="2" -@app.get('/') -async def read_results(): - results = await some_library() - return results -``` - -!!! note - You can only use `await` inside of functions created with `async def`. - ---- - -If you are using a third party library that communicates with something (a database, an API, the file system, etc) and doesn't have support for using `await`, (this is currently the case for most database libraries), then declare your path operation functions as normally, with just `def`, like: - -```Python hl_lines="2" -@app.get('/') -def results(): - results = some_library() - return results -``` - ---- - -If your application (somehow) doesn't have to communicate with anything else and wait for it to respond, use `async def`. - ---- - -If you just don't know, use normal `def`. - ---- - -**Note**: you can mix `def` and `async def` in your path operation functions as much as you need and define each one using the best option for you. FastAPI will do the right thing with them. - -Anyway, in any of the cases above, FastAPI will still work asynchronously and be extremely fast. - -But by following the steps above, it will be able to do some performance optimizations. - - -## Technical Details - -Modern versions of Python have support for **"asynchronous code"** using something called **"coroutines"**, with **`async` and `await`** syntax. - -Let's see that phrase by parts in the sections below, below: - -* **Asynchronous Code** -* **`async` and `await`** -* **Coroutines** - - -## Asynchronous Code - -Asynchronous code just means that the language has a way to tell the computer / program that at some point in the code, he will have to wait for *something else* to finish somewhere else. Let's say that *something else* is called "slow-file". - -So, during that time, the computer can go and do some other work, while "slow-file" finishes. - -Then the computer / program will come back every time it has a chance because it's waiting again, or whenever he finished all the work he had at that point. And it will see if any of the tasks he was waiting for has already finished doing whatever it had to do. - -And then it takes the first task to finish (let's say, our "slow-file") and continues whatever it had to do with it. - -That "wait for something else" normally refers to I/O operations that are relatively "slow" (compared to the speed of the processor and the RAM memory), like waiting for: - -* the data from the client to be sent through the network -* the data sent by your program to be received by the client through the network -* the contents of a file in the disk to be read by the system and given to your program -* the contents your program gave to the system to be written to disk -* a remote API operation -* a database operation to finish -* a database query to return the results -* etc. - -As the execution time is consumed mostly by waiting for I/O operations, so they call them "I/O bound". - -It's called "asynchronous" because the computer / program doesn't have to be "synchronized" with the slow task, waiting for the exact moment that the task finishes, while doing nothing, to be able to take the task result and continue the work. - -Instead of that, by being an "asynchronous" system, once finished, the task can wait in line a little bit (some microseconds) for the computer / program to finish whatever it went to do, and then come back to take the results and continue working with them. - -For "synchronous" (contrary to "asynchronous") they commonly also use the term "sequential", because the computer / program follows all the steps in sequence before switching to a different task, even if those steps involve waiting. - - -### Concurrency and Burgers - -This idea of **asynchronous** code described above is also sometimes called **"concurrency"**. It is different from **"parallelism"**. - -**Concurrency** and **parallelism** both relate to "different things happening more or less at the same time". - -But the details between *concurrency* and *parallelism* are quite different. - -To see the difference, imagine the following story about burgers: - - -### Concurrent Burgers - -You go with your crush to get fast food, you stand in line while the cashier takes the orders from the people in front of you. - -Then it's your turn, you place your order of 2 very fancy burgers for your crush and you. - -You pay. - -The cashier says something to the guy in the kitchen so he knows he has to prepare your burgers (even though he is currently preparing the ones for the previous clients). - -The cashier gives you the number of your turn. - -While you are waiting, you go with your crush and pick a table, you sit and talk with your crush for a long time (as your burgers are very fancy and take some time to prepare). - -As you are seating on the table with your crush, while you wait for the burgers, you can spend that time admiring how awesome, cute and smart your crush is. - -While waiting and talking to your crush, from time to time, you check the number displayed on the counter to see if it's your turn already. - -Then at some point, it finally is your turn. You go to the counter, get your burgers and come back to the table. - -You and your crush eat the burgers and have a nice time. - ---- - -Imagine you are the computer / program in that story. - -While you are at the line, you are just idle, waiting for your turn, not doing anything very "productive". But the line is fast because the cashier is only taking the orders, so that's fine. - -Then, when it's your turn, you do actual "productive" work, you process the menu, decide what you want, get your crush's choice, pay, check that you give the correct bill or card, check that you are charged correctly, check that the order has the correct items, etc. - -But then, even though you still don't have your burgers, your work with the cashier is "on pause", because you have to wait for your burgers to be ready. - -But as you go away from the counter and seat on the table with a number for your turn, you can switch your attention to your crush, and "work" on that. Then you are again doing something very "productive", as is flirting with your crush. - -Then the cashier says "I'm finished with doing the burgers" by putting your number on the counter display, but you don't jump like crazy immediately when the displayed number changes to your turn number. You know no one will steal your burgers because you have the number of your turn, and they have theirs. - -So you wait for your crush to finish the story (finish the current work / task being processed), smile gently and say that you are going for the burgers. - -Then you go to the counter, to the initial task that is now finished, pick the burgers, say thanks and take them to the table. That finishes that step / task of interaction with the counter. That in turn, creates a new task, of "eating burgers", but the previous one of "getting burgers" is finished. - - -### Parallel Burgers - -You go with your crush to get parallel fast food. - -You stand in line while several (let's say 8) cashiers take the orders from the people in front of you. - -Everyone before you is waiting for their burgers to be ready before leaving the counter because each of the 8 cashiers goes himself and preparers the burger right away before getting the next order. - -Then it's finally your turn, you place your order of 2 very fancy burgers for your crush and you. - -You pay. - -The cashier goes to the kitchen. - -You wait, standing in front of the counter, so that no one else takes your burgers before you, as there are no numbers for turns. - -As you and your crush are busy not letting anyone get in front of you and take your burgers whenever they arrive, you cannot pay attention to your crush. - -This is "synchronous" work, you are "synchronized" with the cashier/cook. You have to wait and be there at the exact moment that the cashier/cook finishes the burgers and gives them to you, or otherwise, someone else might take them. - -Then your cashier/cook finally comes back with your burgers, after a long time waiting there in front of the counter. - -You take your burgers and go to the table with your crush. - -You just eat them, and you are done. - -There was not much talk or flirting as most of the time was spent waiting in front of the counter. - ---- - -In this scenario of the parallel burgers, you are a computer / program with two processors (you and your crush), both waiting and dedicating their attention to be "waiting on the counter" for a long time. - -The fast food store has 8 processors (cashiers/cooks). While the concurrent burgers store might have had only 2 (one cashier and one cook). - -But still, the final experience is not the best. - ---- - -This would be the parallel equivalent story for burgers. - -For a more "real life" example of this, imagine a bank. - -Up to recently, most of the banks had multiple cashiers and a big line. - -All of the cashiers doing all the work with one client after the other. - -And you have to wait in the line for a long time or you lose your turn. - -You probably wouldn't want to take your crush with you to do errands at the bank. - - -### Burger Conclusion - -In this scenario of "fast food burgers with your crush", as there is a lot of waiting, it makes a lot more sense to have a concurrent system. - -This is the case for most of the web applications. - -Many, many users, but your server is waiting for their not-so-good connection to send their requests. - -And then waiting again for the responses to come back. - -This "waiting" is measured in microseconds, but still, summing it all, it's a lot of waiting in the end. - -That's why it makes a lot of sense to use asynchronous code for web APIs. - -Most of the existing popular Python frameworks (including Flask and Django) were created before the new asynchronous features in Python existed. So, the ways they can be deployed support parallel execution and an older form of asynchronous execution that is not as powerful as the new capabilities. - -Even though the main specification for asynchronous web Python (ASGI) was developed at Django, to add support for WebSockets. - -That kind of asynchronicity is what made NodeJS popular (even though NodeJS is not parallel) and that's the strength of Go as a programing language. - -And that's the same level of performance you get with **FastAPI**. - -And as you can have parallelism and asynchronicity at the same time, you get higher performance than most of the tested NodeJS frameworks and on par with Go, which is a compiled language closer to C (all thanks to Starlette). - - -### Is concurrency better than parallelism? - -Nope! That's not the moral of the story. - -Concurrency is different than parallelism. And it is better on **specific** scenarios that involve a lot of waiting. Because of that, it generally is a lot better than parallelism for web application development. But not for everything. - -So, to balance that out, imagine the following short story: - -> You have to clean a big, dirty house. - -*Yep, that's the whole story*. - ---- - -There's no waiting anywhere, just a lot of work to be done, on multiple places of the house. - -You could have turns as in the burgers example, first the living room, then the kitchen, but as you are not waiting for anything, just cleaning and cleaning, the turns wouldn't affect anything. - -It would take the same amount of time to finish with or without turns (concurrency) and you would have done the same amount of work. - -But in this case, if you could bring the 8 ex-cashier/cooks/now-cleaners, and each one of them (plus you) could take a zone of the house to clean it, you could do all the work in **parallel**, with the extra help, and finish much sooner. - -In this scenario, each one of the cleaners (including you) would be a processor, doing their part of the job. - -And as most of the execution time is taken by actual work (instead of waiting), and the work in a computer is done by a CPU, they call these problems "CPU bound". - ---- - -Common examples of CPU bound operations are things that require complex math processing. - -For example: - -* **Audio** or **image processing** -* **Computer vision**: an image is composed of millions of pixels, each pixel has 3 values / colors, processing that normally requires computing something on those pixels, all at the same time) -* **Machine Learning**: it normally requires lots of "matrix" and "vector" multiplications. Think of a huge spreadsheet with numbers and multiplying all of them together at the same time. -* **Deep Learning**: this is a sub-field of Machine Learning, so, the same applies. It's just that there is not a single spreadsheet of numbers to multiply, but a huge set of them, and in many cases, you use a special processor to build and / or use those models. - - -### Concurrency + Parallelism: Web + Machine Learning - -With **FastAPI** you can take the advantage of concurrency that is very common for web development (the same main attractive of NodeJS). - -But you can also exploit the benefits of parallelism and multiprocessing (having multiple processes running in parallel) for **CPU bound** workloads like those in Machine Learning systems. - -That, plus the simple fact that Python is the main language for **Data Science**, Machine Learning and especially Deep Learning, make FastAPI a very good match for Data Science / Machine Learning web APIs and applications (among many others). - -To see how to achieve this parallelism in production see the section about [Deployment](deployment.md). - - -## `async` and `await` - -Modern versions of python have a very intuitive way to define asynchronous code. This makes it look just like normal "sequential" code and do the "awaiting" for you at the right moments. - -When there is an operation that will require waiting before giving the results and has support for these new Python features, you can code it like: - -```Python -burgers = await get_burgers(2) -``` - -The key here is the `await`. It tells Python that it has to wait for `get_burgers(2)` to finish doing its thing before storing the results in `burgers`. With that, Python will know that it can go and do something else in the meanwhile (like receiving another request). - -For `await` to work, it has to be inside a function that supports this asynchronicity. To do that, you just declare it with `async def`: - -```Python hl_lines="1" -async def get_burgers(number: int): - # Do some asynchronous stuff to create the burgers - return burgers -``` - -...instead of `def`: - -```Python hl_lines="2" -# This is not asynchronous -def get_sequential_burgers(number: int): - # Do some sequential stuff to create the burgers - return burgers -``` - -With `async def`, Python knows that, inside that function, it has to be aware of `await` expressions, and that it can "pause" the execution of that function and go do something else before coming back. - -When you want to call an `async def` function, you have to "await" it. So, this won't work: - -```Python -# This won't work, because get_burgers was defined with: async def -burgers = get_burgers(2) -``` - ---- - -So, if you are using a library that tells you that you can call it with `await`, you need to create the path operation functions that uses it with `async def`, like in: - -```Python hl_lines="2 3" -@app.get('/burgers') -async def read_burgers(): - burgers = await get_burgers(2) - return burgers -``` - -### More technical details - -You might have noticed that `await` can only be used inside of functions defined with `async def`. - -But at the same time, functions defined with `async def` have to be "awaited". So, functions with `async def` can only be called inside of functions defined with `async def` too. - -So, about the egg and the chicken, how do you call the first `async` function? - -If you are working with **FastAPI** you don't have to worry about that, because that "first" function will be your path operation function, and FastAPI will know how to do the right thing. - -But if you want to use `async` / `await` without FastAPI, check the official Python docs. - - -### Other forms of asynchronous code - -This style of using `async` and `await` is relatively new in the language. - -But it makes working with asynchronous code a lot easier. - -This same syntax (or almost identical) was also included recently in modern versions of JavaScript (in Browser and NodeJS). - -But before that, handling asynchronous code was quite more complex and difficult. - -In previous versions of Python, you could have used threads or Gevent. But the code is way more complex to understand, debug, and think about. - -In previous versions of NodeJS / Browser JavaScript, you would have used "callbacks". Which lead to callback hell. - - -## Coroutines - -**Coroutine** is just the very fancy term for the thing returned by an `async def` function. Python knows that it is something like a function that it can start and that it will end at some point, but that it might be paused internally too, whenever there is an `await` inside of it. - -But all this functionality of using asynchronous code with `async` and `await` is many times summarized as using "coroutines". It is comparable to the main key feature of Go, the "Goroutines". - -## Conclusion - -Let's see the same phrase from above: - -> Modern versions of Python have support for **"asynchronous code"** using something called **"coroutines"**, with **`async` and `await`** syntax. - -That should make more sense now. - -All that is what powers FastAPI (through Starlette) and what makes it have such an impressive performance. - - -## Very Technical Details - -!!! warning - You can probably skip this. - - These are very technical details of how **FastAPI** works underneath. - - If you have quite some technical knowledge (co-routines, threads, blocking, etc) and are curious about how FastAPI handles `async def` vs normal `def`, go ahead. - -### Path operation functions - -When you declare a *path operation function* with normal `def` instead of `async def`, it is run in an external threadpool that is then awaited, instead of being called directly (as it would block the server). - -If you are coming from another async framework that does not work in the way described above and you are used to define trivial compute-only *path operation functions* with plain `def` for a tiny performance gain (about 100 nanoseconds), please note that in **FastAPI** the effect would be quite opposite. In these cases, it's better to use `async def` unless your *path operation functions* use code that performs blocking IO. - -Still, in both situations, chances are that **FastAPI** will still be faster than (or at least comparable to) your previous framework. - -### Dependencies - -The same applies for dependencies. If a dependency is a standard `def` function instead of `async def`, it is run in the external threadpool. - -### Sub-dependencies - -You can have multiple dependencies and sub-dependencies requiring each other (as parameters of the function definitions), some of them might be created with `async def` and some with normal `def`. It would still work, and the ones created with normal `def` would be called on an external thread instead of being "awaited". - -### Other utility functions - -Any other utility function that you call directly can be created with normal `def` or `async def` and FastAPI won't affect the way you call it. - -This is in contrast to the functions that FastAPI calls for you: *path operation functions* and dependencies. - -If your utility function is a normal function with `def`, it will be called directly (as you write it in your code), not in a threadpool, if the function is created with `async def` then you should await for that function when you call it in your code. - ---- - -Again, these are very technical details that would probably be useful if you came searching for them. - -Otherwise, you should be good with the guidelines from the section above: In a hurry?. diff --git a/docs/benchmarks.md b/docs/benchmarks.md deleted file mode 100644 index 78d1fc2b7ff0a..0000000000000 --- a/docs/benchmarks.md +++ /dev/null @@ -1,32 +0,0 @@ -Independent TechEmpower benchmarks show **FastAPI** applications running under Uvicorn as one of the fastest Python frameworks available, only below Starlette and Uvicorn themselves (used internally by FastAPI). (*) - -But when checking benchmarks and comparisons you should have the following in mind. - -## Benchmarks and speed - -When you check the benchmarks, it is common to see several tools of different types compared as equivalent. - -Specifically, to see Uvicorn, Starlette and FastAPI compared together (among many other tools). - -The simplest the problem solved by the tool, the better performance it will get. And most of the benchmarks don't test the additional features provided by the tool. - -The hierarchy is like: - -* **Uvicorn**: an ASGI server - * **Starlette**: (uses Uvicorn) a web microframework - * **FastAPI**: (uses Starlette) an API microframework with several additional features for building APIs, with data validation, etc. - -* **Uvicorn**: - * Will have the best performance, as it doesn't have much extra code apart from the server itself. - * You wouldn't write an application in Uvicorn directly. That would mean that your code would have to include more or less, at least, all the code provided by Starlette (or **FastAPI**). And if you did that, your final application would have the same overhead as having used a framework and minimizing your app code and bugs. - * If you are comparing Uvicorn, compare it against Daphne, Hypercorn, uWSGI, etc. Application servers. -* **Starlette**: - * Will have the next best performance, after Uvicorn. In fact, Starlette uses Uvicorn to run. So, it probably can only get "slower" than Uvicorn by having to execute more code. - * But it provides you the tools to build simple web applications, with routing based on paths, etc. - * If you are comparing Starlette, compare it against Sanic, Flask, Django, etc. Web frameworks (or microframeworks). -* **FastAPI**: - * The same way that Starlette uses Uvicorn and cannot be faster than it, **FastAPI** uses Starlette, so it cannot be faster than it. - * FastAPI provides more features on top of Starlette. Features that you almost always need when building APIs, like data validation and serialization. And by using it, you get automatic documentation for free (the automatic documentation doesn't even add overhead to running applications, it is generated on startup). - * If you didn't use FastAPI and used Starlette directly (or another tool, like Sanic, Flask, Responder, etc) you would have to implement all the data validation and serialization yourself. So, your final application would still have the same overhead as if it was built using FastAPI. And in many cases, this data validation and serialization is the biggest amount of code written in applications. - * So, by using FastAPI you are saving development time, bugs, lines of code, and you would probably get the same performance (or better) you would if you didn't use it (as you would have to implement it all in your code). - * If you are comparing FastAPI, compare it against a web application framework (or set of tools) that provides data validation, serialization and documentation, like Flask-apispec, NestJS, Molten, etc. Frameworks with integrated automatic data validation, serialization and documentation. diff --git a/docs/contributing.md b/docs/contributing.md deleted file mode 100644 index beecef543ee19..0000000000000 --- a/docs/contributing.md +++ /dev/null @@ -1,123 +0,0 @@ -First, you might want to see the basic ways to help FastAPI and get help. - -## Developing - -If you already cloned the repository and you know that you need to deep dive in the code, here are some guidelines to set up your environment. - - -### Pipenv - -If you are using Pipenv, you can create a virtual environment and install the packages with: - -```bash -pipenv install --dev -``` - -Then you can activate that virtual environment with: - -```bash -pipenv shell -``` - - -### No Pipenv - -If you are not using Pipenv, you can create a virtual environment with your preferred tool, and install the packages listed in the file `Pipfile`. - - -### Flit - -**FastAPI** uses Flit to build, package and publish the project. - -If you installed the development dependencies with one of the methods above, you already have the `flit` command. - -To install your local version of FastAPI as a package in your local environment, run: - -```bash -flit install --symlink -``` - -It will install your local FastAPI in your local environment. - - -#### Using your local FastAPI - -If you create a Python file that imports and uses FastAPI, and run it with the Python from your local environment, it will use your local FastAPI source code. - -And if you update that local FastAPI source code, as it is installed with `--symlink`, when you run that Python file again, it will use the fresh version of FastAPI you just edited. - -That way, you don't have to "install" your local version to be able to test every change. - - -### Format - -There is a script that you can run that will format and clean all your code: - -```bash -bash scripts/lint.sh -``` - -It will also auto-sort all your imports. - -For it to sort them correctly, you need to have FastAPI installed locally in your environment, with the command in the section above: - -```bash -flit install --symlink -``` - - -### Docs - -The documentation uses MkDocs. - -All the documentation is in Markdown format in the directory `./docs`. - -Many of the tutorials have blocks of code. - -In most of the cases, these blocks of code are actual complete applications that can be run as is. - -In fact, those blocks of code are not written inside the Markdown, they are Python files in the `./docs/src/` directory. - -And those Python files are included/injected in the documentation when generating the site. - - -#### Docs for tests - -Most of the tests actually run against the example source files in the documentation. - -This helps making sure that: - -* The documentation is up to date. -* The documentation examples can be run as is. -* Most of the features are covered by the documentation, ensured by the coverage tests. - -During local development, there is a script that builds the site and checks for any changes, live-reloading: - -```bash -bash scripts/docs-live.sh -``` - -It will serve the documentation on `http://0.0.0.0:8008`. - -That way, you can edit the documentation/source files and see the changes live. - -#### Apps and docs at the same time - -And if you run the examples with, e.g.: - -```bash -uvicorn tutorial001:app --reload -``` - -as Uvicorn by default will use the port `8000`, the documentation on port `8008` won't clash. - - -### Tests - -There is a script that you can run locally to test all the code and generate coverage reports in HTML: - -```bash -bash scripts/test-cov-html.sh -``` - -This command generates a directory `./htmlcov/`, if you open the file `./htmlcov/index.html` in your browser, you can explore interactively the regions of code that are covered by the tests, and notice if there is any region missing. diff --git a/docs/de/docs/_llm-test.md b/docs/de/docs/_llm-test.md new file mode 100644 index 0000000000000..3fec41817ed4a --- /dev/null +++ b/docs/de/docs/_llm-test.md @@ -0,0 +1,495 @@ +# LLM-Testdatei { #llm-test-file } + +Dieses Dokument testet, ob das LLM, das die Dokumentation übersetzt, den `general_prompt` in `scripts/translate.py` und den sprachspezifischen Prompt in `docs/{language code}/llm-prompt.md` versteht. Der sprachspezifische Prompt wird an `general_prompt` angehängt. + +Hier hinzugefügte Tests werden von allen Erstellern sprachspezifischer Prompts gesehen. + +So verwenden: + +* Einen sprachspezifischen Prompt haben – `docs/{language code}/llm-prompt.md`. +* Eine frische Übersetzung dieses Dokuments in die gewünschte Zielsprache durchführen (siehe z. B. das Kommando `translate-page` der `translate.py`). Dadurch wird die Übersetzung unter `docs/{language code}/docs/_llm-test.md` erstellt. +* Prüfen Sie, ob in der Übersetzung alles in Ordnung ist. +* Verbessern Sie bei Bedarf Ihren sprachspezifischen Prompt, den allgemeinen Prompt oder das englische Dokument. +* Beheben Sie anschließend manuell die verbleibenden Probleme in der Übersetzung, sodass es eine gute Übersetzung ist. +* Übersetzen Sie erneut, nachdem die gute Übersetzung vorliegt. Das ideale Ergebnis wäre, dass das LLM an der Übersetzung keine Änderungen mehr vornimmt. Das bedeutet, dass der allgemeine Prompt und Ihr sprachspezifischer Prompt so gut sind, wie sie sein können (Es wird manchmal ein paar scheinbar zufällige Änderungen machen, der Grund ist, dass [LLMs keine deterministischen Algorithmen sind](https://doublespeak.chat/#/handbook#deterministic-output)). + +Die Tests: + +## Codeschnipsel { #code-snippets } + +//// tab | Test + +Dies ist ein Codeschnipsel: `foo`. Und dies ist ein weiteres Codeschnipsel: `bar`. Und noch eins: `baz quux`. + +//// + +//// tab | Info + +Der Inhalt von Codeschnipseln sollte unverändert bleiben. + +Siehe Abschnitt `### Content of code snippets` im allgemeinen Prompt in `scripts/translate.py`. + +//// + +## Anführungszeichen { #quotes } + +//// tab | Test + +Gestern schrieb mein Freund: „Wenn man ‚incorrectly‘ korrekt schreibt, hat man es falsch geschrieben“. Worauf ich antwortete: „Korrekt, aber ‚incorrectly‘ ist inkorrekterweise nicht ‚„incorrectly“‘“. + +/// note | Hinweis + +Das LLM wird dies wahrscheinlich falsch übersetzen. Interessant ist nur, ob es die korrigierte Übersetzung bei einer erneuten Übersetzung beibehält. + +/// + +//// + +//// tab | Info + +Der Promptdesigner kann entscheiden, ob neutrale Anführungszeichen in typografische Anführungszeichen umgewandelt werden sollen. Es ist in Ordnung, sie unverändert zu lassen. + +Siehe zum Beispiel den Abschnitt `### Quotes` in `docs/de/llm-prompt.md`. + +//// + +## Anführungszeichen in Codeschnipseln { #quotes-in-code-snippets } + +//// tab | Test + +`pip install "foo[bar]"` + +Beispiele für Stringliterale in Codeschnipseln: `"this"`, `'that'`. + +Ein schwieriges Beispiel für Stringliterale in Codeschnipseln: `f"I like {'oranges' if orange else "apples"}"` + +Hardcore: `Yesterday, my friend wrote: "If you spell incorrectly correctly, you have spelled it incorrectly". To which I answered: "Correct, but 'incorrectly' is incorrectly not '"incorrectly"'"` + +//// + +//// tab | Info + +... Allerdings müssen Anführungszeichen in Codeschnipseln unverändert bleiben. + +//// + +## Codeblöcke { #code-blocks } + +//// tab | Test + +Ein Bash-Codebeispiel ... + +```bash +# Eine Begrüßung an das Universum ausgeben +echo "Hello universe" +``` + +... und ein Konsolen-Codebeispiel ... + +```console +$ fastapi run main.py + FastAPI Starting server + Searching for package file structure +``` + +... und noch ein Konsolen-Codebeispiel ... + +```console +// Ein Verzeichnis "Code" erstellen +$ mkdir code +// In dieses Verzeichnis wechseln +$ cd code +``` + +... und ein Python-Codebeispiel ... + +```Python +wont_work() # Das wird nicht funktionieren 😱 +works(foo="bar") # Das funktioniert 🎉 +``` + +... und das war's. + +//// + +//// tab | Info + +Code in Codeblöcken sollte nicht verändert werden, mit Ausnahme von Kommentaren. + +Siehe Abschnitt `### Content of code blocks` im allgemeinen Prompt in `scripts/translate.py`. + +//// + +## Tabs und farbige Boxen { #tabs-and-colored-boxes } + +//// tab | Test + +/// note | Hinweis +Etwas Text +/// + +/// note | Technische Details +Etwas Text +/// + +/// tip | Tipp +Etwas Text +/// + +/// warning | Achtung +Etwas Text +/// + +/// danger | Gefahr +Etwas Text +/// + +//// + +//// tab | Info + +Tabs und `Info`/`Note`/`Warning`/usw. Blöcke sollten die Übersetzung ihres Titels nach einem vertikalen Strich (`|`) erhalten. + +Siehe die Abschnitte `### Special blocks` und `### Tab blocks` im allgemeinen Prompt in `scripts/translate.py`. + +//// + +## Web- und interne Links { #web-and-internal-links } + +//// tab | Test + +Der Linktext sollte übersetzt werden, die Linkadresse sollte unverändert bleiben: + +* [Link zur Überschrift oben](#code-snippets) +* [Interner Link](index.md#installation) +* [Externer Link](https://sqlmodel.tiangolo.com/) +* [Link zu einem Stil](https://fastapi.tiangolo.com/css/styles.css) +* [Link zu einem Skript](https://fastapi.tiangolo.com/js/logic.js) +* [Link zu einem Bild](https://fastapi.tiangolo.com/img/foo.jpg) + +Der Linktext sollte übersetzt werden, die Linkadresse sollte auf die Übersetzung zeigen: + +* [FastAPI-Link](https://fastapi.tiangolo.com/de/) + +//// + +//// tab | Info + +Links sollten übersetzt werden, aber ihre Adresse soll unverändert bleiben. Eine Ausnahme sind absolute Links zu Seiten der FastAPI-Dokumentation. In diesem Fall sollte auf die Übersetzung verlinkt werden. + +Siehe Abschnitt `### Links` im allgemeinen Prompt in `scripts/translate.py`. + +//// + +## HTML-„abbr“-Elemente { #html-abbr-elements } + +//// tab | Test + +Hier einige Dinge, die in HTML-„abbr“-Elemente gepackt sind (einige sind erfunden): + +### Das abbr gibt eine vollständige Phrase { #the-abbr-gives-a-full-phrase } + +* GTD +* lt +* XWT +* PSGI + +### Das abbr gibt eine vollständige Phrase und eine Erklärung { #the-abbr-gives-a-full-phrase-and-an-explanation } + +* MDN +* I/O. + +//// + +//// tab | Info + +„title“-Attribute von „abbr“-Elementen werden nach bestimmten Anweisungen übersetzt. + +Übersetzungen können eigene „abbr“-Elemente hinzufügen, die das LLM nicht entfernen soll. Z. B. um englische Wörter zu erklären. + +Siehe Abschnitt `### HTML abbr elements` im allgemeinen Prompt in `scripts/translate.py`. + +//// + +## HTML-„dfn“-Elemente { #html-dfn-elements } + +* Cluster +* Deep Learning + +## Überschriften { #headings } + +//// tab | Test + +### Eine Webapp entwickeln – ein Tutorial { #develop-a-webapp-a-tutorial } + +Hallo. + +### Typhinweise und -annotationen { #type-hints-and-annotations } + +Hallo wieder. + +### Super- und Subklassen { #super-and-subclasses } + +Hallo wieder. + +//// + +//// tab | Info + +Die einzige strenge Regel für Überschriften ist, dass das LLM den Hash-Teil in geschweiften Klammern unverändert lässt, damit Links nicht kaputtgehen. + +Siehe Abschnitt `### Headings` im allgemeinen Prompt in `scripts/translate.py`. + +Für einige sprachspezifische Anweisungen, siehe z. B. den Abschnitt `### Headings` in `docs/de/llm-prompt.md`. + +//// + +## In der Dokumentation verwendete Begriffe { #terms-used-in-the-docs } + +//// tab | Test + +* Sie +* Ihr + +* z. B. +* usw. + +* `foo` vom Typ `int` +* `bar` vom Typ `str` +* `baz` vom Typ `list` + +* das Tutorial – Benutzerhandbuch +* das Handbuch für fortgeschrittene Benutzer +* die SQLModel-Dokumentation +* die API-Dokumentation +* die automatische Dokumentation + +* Data Science +* Deep Learning +* Machine Learning +* Dependency Injection +* HTTP Basic-Authentifizierung +* HTTP Digest +* ISO-Format +* der JSON-Schema-Standard +* das JSON-Schema +* die Schema-Definition +* Password Flow +* Mobile + +* deprecatet +* designt +* ungültig +* on the fly +* Standard +* Default +* Groß-/Klein­schrei­bung ist relevant +* Groß-/Klein­schrei­bung ist nicht relevant + +* die Anwendung bereitstellen +* die Seite ausliefern + +* die App +* die Anwendung + +* der Request +* die Response +* die Error-Response + +* die Pfadoperation +* der Pfadoperation-Dekorator +* die Pfadoperation-Funktion + +* der Body +* der Requestbody +* der Responsebody +* der JSON-Body +* der Formularbody +* der Dateibody +* der Funktionskörper + +* der Parameter +* der Body-Parameter +* der Pfad-Parameter +* der Query-Parameter +* der Cookie-Parameter +* der Header-Parameter +* der Formular-Parameter +* der Funktionsparameter + +* das Event +* das Startup-Event +* das Hochfahren des Servers +* das Shutdown-Event +* das Lifespan-Event + +* der Handler +* der Eventhandler +* der Exceptionhandler +* handhaben + +* das Modell +* das Pydantic-Modell +* das Datenmodell +* das Datenbankmodell +* das Formularmodell +* das Modellobjekt + +* die Klasse +* die Basisklasse +* die Elternklasse +* die Subklasse +* die Kindklasse +* die Geschwisterklasse +* die Klassenmethode + +* der Header +* die Header +* der Autorisierungsheader +* der `Authorization`-Header +* der Forwarded-Header + +* das Dependency-Injection-System +* die Dependency +* das Dependable +* der Dependant + +* I/O-lastig +* CPU-lastig +* Nebenläufigkeit +* Parallelität +* Multiprocessing + +* die Umgebungsvariable +* die Umgebungsvariable +* der `PATH` +* die `PATH`-Variable + +* die Authentifizierung +* der Authentifizierungsanbieter +* die Autorisierung +* das Autorisierungsformular +* der Autorisierungsanbieter +* der Benutzer authentisiert sich +* das System authentifiziert den Benutzer + +* Das CLI +* Das Kommandozeileninterface + +* der Server +* der Client + +* der Cloudanbieter +* der Clouddienst + +* die Entwicklung +* die Entwicklungsphasen + +* das Dict +* das Dictionary +* die Enumeration +* das Enum +* das Enum-Member + +* der Encoder +* der Decoder +* kodieren +* dekodieren + +* die Exception +* werfen + +* der Ausdruck +* die Anweisung + +* das Frontend +* das Backend + +* die GitHub-Diskussion +* das GitHub-Issue + +* die Leistung +* die Leistungsoptimierung + +* der Rückgabetyp +* der Rückgabewert + +* die Sicherheit +* das Sicherheitsschema + +* der Task +* der Hintergrundtask +* die Taskfunktion + +* das Template +* die Template-Engine + +* die Typannotation +* der Typhinweis + +* der Serverworker +* der Uvicorn-Worker +* der Gunicorn-Worker +* der Workerprozess +* die Workerklasse +* die Workload + +* das Deployment +* deployen + +* das SDK +* das Software Development Kit + +* der `APIRouter` +* die `requirements.txt` +* das Bearer-Token +* der Breaking Change +* der Bug +* der Button +* das Callable +* der Code +* der Commit +* der Contextmanager +* die Coroutine +* die Datenbanksession +* die Festplatte +* die Domain +* die Engine +* das Fake-X +* die HTTP-GET-Methode +* das Item +* die Bibliothek +* der Lifespan +* der Lock +* die Middleware +* die Mobile-Anwendung +* das Modul +* das Mounten +* das Netzwerk +* das Origin +* Die Überschreibung +* die Payload +* der Prozessor +* die Property +* der Proxy +* der Pull Request +* die Query +* der RAM +* der entfernte Rechner +* der Statuscode +* der String +* der Tag +* das Webframework +* die Wildcard +* zurückgeben +* validieren + +//// + +//// tab | Info + +Dies ist eine nicht vollständige und nicht normative Liste von (meist) technischen Begriffen, die in der Dokumentation vorkommen. Sie kann dem Promptdesigner helfen herauszufinden, bei welchen Begriffen das LLM Unterstützung braucht. Zum Beispiel, wenn es eine gute Übersetzung immer wieder auf eine suboptimale Übersetzung zurücksetzt. Oder wenn es Probleme hat, einen Begriff in Ihrer Sprache zu konjugieren/deklinieren. + +Siehe z. B. den Abschnitt `### List of English terms and their preferred German translations` in `docs/de/llm-prompt.md`. + +//// diff --git a/docs/de/docs/about/index.md b/docs/de/docs/about/index.md new file mode 100644 index 0000000000000..5e9c6b6a0a069 --- /dev/null +++ b/docs/de/docs/about/index.md @@ -0,0 +1,3 @@ +# Über { #about } + +Über FastAPI, sein Design, seine Inspiration und mehr. 🤓 diff --git a/docs/de/docs/advanced/additional-responses.md b/docs/de/docs/advanced/additional-responses.md new file mode 100644 index 0000000000000..f2214713bc6a2 --- /dev/null +++ b/docs/de/docs/advanced/additional-responses.md @@ -0,0 +1,247 @@ +# Zusätzliche Responses in OpenAPI { #additional-responses-in-openapi } + +/// warning | Achtung + +Dies ist ein eher fortgeschrittenes Thema. + +Wenn Sie mit **FastAPI** beginnen, benötigen Sie dies möglicherweise nicht. + +/// + +Sie können zusätzliche Responses mit zusätzlichen Statuscodes, Medientypen, Beschreibungen, usw. deklarieren. + +Diese zusätzlichen Responses werden in das OpenAPI-Schema aufgenommen, sodass sie auch in der API-Dokumentation erscheinen. + +Für diese zusätzlichen Responses müssen Sie jedoch sicherstellen, dass Sie eine `Response`, wie etwa `JSONResponse`, direkt zurückgeben, mit Ihrem Statuscode und Inhalt. + +## Zusätzliche Response mit `model` { #additional-response-with-model } + +Sie können Ihren *Pfadoperation-Dekoratoren* einen Parameter `responses` übergeben. + +Der nimmt ein `dict` entgegen, die Schlüssel sind Statuscodes für jede Response, wie etwa `200`, und die Werte sind andere `dict`s mit den Informationen für jede Response. + +Jedes dieser Response-`dict`s kann einen Schlüssel `model` haben, welcher ein Pydantic-Modell enthält, genau wie `response_model`. + +**FastAPI** nimmt dieses Modell, generiert dessen JSON-Schema und fügt es an der richtigen Stelle in OpenAPI ein. + +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_py310.py hl[18,22] *} + +/// note | Hinweis + +Beachten Sie, dass Sie die `JSONResponse` direkt zurückgeben müssen. + +/// + +/// note | Hinweis + +Der `model`-Schlüssel ist nicht Teil von OpenAPI. + +**FastAPI** nimmt das Pydantic-Modell von dort, generiert das JSON-Schema und fügt es an der richtigen Stelle ein. + +Die richtige Stelle ist: + +* Im Schlüssel `content`, der als Wert ein weiteres JSON-Objekt (`dict`) hat, welches Folgendes enthält: + * Ein Schlüssel mit dem Medientyp, z. B. `application/json`, der als Wert ein weiteres JSON-Objekt hat, welches Folgendes enthält: + * Ein Schlüssel `schema`, der als Wert das JSON-Schema aus dem Modell hat, hier ist die richtige Stelle. + * **FastAPI** fügt hier eine Referenz auf die globalen JSON-Schemas an einer anderen Stelle in Ihrer OpenAPI hinzu, anstatt es direkt einzubinden. Auf diese Weise können andere Anwendungen und Clients diese JSON-Schemas direkt verwenden, bessere Tools zur Codegenerierung bereitstellen, usw. + +/// + +Die generierten Responses in der OpenAPI für diese *Pfadoperation* lauten: + +```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" + } + } + } + } + } +} +``` + +Die Schemas werden von einer anderen Stelle innerhalb des OpenAPI-Schemas referenziert: + +```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" + } + } + } + } + } + } +} +``` + +## Zusätzliche Medientypen für die Haupt-Response { #additional-media-types-for-the-main-response } + +Sie können denselben `responses`-Parameter verwenden, um verschiedene Medientypen für dieselbe Haupt-Response hinzuzufügen. + +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] *} + +/// note | Hinweis + +Beachten Sie, dass Sie das Bild direkt mit einer `FileResponse` zurückgeben müssen. + +/// + +/// note | Hinweis + +Sofern Sie in Ihrem Parameter `responses` nicht explizit einen anderen Medientyp angeben, geht FastAPI davon aus, dass die Response denselben Medientyp wie die Haupt-Response-Klasse hat (Standardmäßig `application/json`). + +Wenn Sie jedoch eine benutzerdefinierte Response-Klasse mit `None` als Medientyp angegeben haben, verwendet FastAPI `application/json` für jede zusätzliche Response, die über ein zugehöriges Modell verfügt. + +/// + +## Informationen kombinieren { #combining-information } + +Sie können auch Response-Informationen von mehreren Stellen kombinieren, einschließlich der Parameter `response_model`, `status_code` und `responses`. + +Sie können ein `response_model` deklarieren, indem Sie den Standardstatuscode `200` (oder bei Bedarf einen benutzerdefinierten) verwenden und dann zusätzliche Informationen für dieselbe Response in `responses` direkt im OpenAPI-Schema deklarieren. + +**FastAPI** behält die zusätzlichen Informationen aus `responses` und kombiniert sie mit dem JSON-Schema aus Ihrem Modell. + +Sie können beispielsweise eine Response mit dem Statuscode `404` deklarieren, die ein Pydantic-Modell verwendet und über eine benutzerdefinierte Beschreibung (`description`) verfügt. + +Und eine Response mit dem Statuscode `200`, die Ihr `response_model` verwendet, aber ein benutzerdefiniertes Beispiel (`example`) enthält: + +{* ../../docs_src/additional_responses/tutorial003_py310.py hl[20:31] *} + +Es wird alles kombiniert und in Ihre OpenAPI eingebunden und in der API-Dokumentation angezeigt: + + + +## Vordefinierte und benutzerdefinierte Responses kombinieren { #combine-predefined-responses-and-custom-ones } + +Möglicherweise möchten Sie einige vordefinierte Responses haben, die für viele *Pfadoperationen* gelten, Sie möchten diese jedoch mit benutzerdefinierten Responses kombinieren, die für jede *Pfadoperation* erforderlich sind. + +In diesen Fällen können Sie die Python-Technik zum „Entpacken“ eines `dict`s mit `**dict_to_unpack` verwenden: + +```Python +old_dict = { + "old key": "old value", + "second old key": "second old value", +} +new_dict = {**old_dict, "new key": "new value"} +``` + +Hier wird `new_dict` alle Schlüssel-Wert-Paare von `old_dict` plus das neue Schlüssel-Wert-Paar enthalten: + +```Python +{ + "old key": "old value", + "second old key": "second old value", + "new key": "new value", +} +``` + +Mit dieser Technik können Sie einige vordefinierte Responses in Ihren *Pfadoperationen* wiederverwenden und sie mit zusätzlichen benutzerdefinierten Responses kombinieren. + +Zum Beispiel: + +{* ../../docs_src/additional_responses/tutorial004_py310.py hl[11:15,24] *} + +## Weitere Informationen zu OpenAPI-Responses { #more-information-about-openapi-responses } + +Um zu sehen, was genau Sie in die Responses aufnehmen können, können Sie die folgenden Abschnitte in der OpenAPI-Spezifikation überprüfen: + +* [OpenAPI Responses Object](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#responses-object), enthält das `Response Object`. +* [OpenAPI Response Object](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#response-object), Sie können alles davon direkt in jede Response innerhalb Ihres `responses`-Parameter einfügen. Einschließlich `description`, `headers`, `content` (darin deklarieren Sie verschiedene Medientypen und JSON-Schemas) und `links`. diff --git a/docs/de/docs/advanced/additional-status-codes.md b/docs/de/docs/advanced/additional-status-codes.md new file mode 100644 index 0000000000000..6f0114cc1887c --- /dev/null +++ b/docs/de/docs/advanced/additional-status-codes.md @@ -0,0 +1,42 @@ +# Zusätzliche Statuscodes { #additional-status-codes } + + +Standardmäßig liefert **FastAPI** die Responses als `JSONResponse` zurück und fügt den Inhalt, den Sie aus Ihrer *Pfadoperation* zurückgeben, in diese `JSONResponse` ein. + +Es wird der Default-Statuscode oder derjenige verwendet, den Sie in Ihrer *Pfadoperation* festgelegt haben. + +## Zusätzliche Statuscodes { #additional-status-codes_1 } + +Wenn Sie neben dem Hauptstatuscode weitere Statuscodes zurückgeben möchten, können Sie dies tun, indem Sie direkt eine `Response` zurückgeben, wie etwa eine `JSONResponse`, und den zusätzlichen Statuscode direkt festlegen. + +Angenommen, Sie möchten eine *Pfadoperation* haben, die das Aktualisieren von Artikeln ermöglicht und bei Erfolg den HTTP-Statuscode 200 „OK“ zurückgibt. + +Sie möchten aber auch, dass sie neue Artikel akzeptiert. Und wenn die Artikel vorher nicht vorhanden waren, werden diese Artikel erstellt und der HTTP-Statuscode 201 „Created“ zurückgegeben. + +Um dies zu erreichen, importieren Sie `JSONResponse`, und geben Sie Ihren Inhalt direkt zurück, indem Sie den gewünschten `status_code` setzen: + +{* ../../docs_src/additional_status_codes/tutorial001_an_py310.py hl[4,25] *} + +/// warning | Achtung + +Wenn Sie eine `Response` direkt zurückgeben, wie im obigen Beispiel, wird sie direkt zurückgegeben. + +Sie wird nicht mit einem Modell usw. serialisiert. + +Stellen Sie sicher, dass sie die gewünschten Daten enthält und dass die Werte gültiges JSON sind (wenn Sie `JSONResponse` verwenden). + +/// + +/// note | Technische Details + +Sie können auch `from starlette.responses import JSONResponse` verwenden. + +**FastAPI** bietet dieselben `starlette.responses` auch via `fastapi.responses` an, als Annehmlichkeit für Sie, den Entwickler. Die meisten verfügbaren Responses kommen aber direkt von Starlette. Dasselbe gilt für `status`. + +/// + +## OpenAPI- und API-Dokumentation { #openapi-and-api-docs } + +Wenn Sie zusätzliche Statuscodes und Responses direkt zurückgeben, werden diese nicht in das OpenAPI-Schema (die API-Dokumentation) aufgenommen, da FastAPI keine Möglichkeit hat, im Voraus zu wissen, was Sie zurückgeben werden. + +Sie können das jedoch in Ihrem Code dokumentieren, indem Sie Folgendes verwenden: [Zusätzliche Responses](additional-responses.md). diff --git a/docs/de/docs/advanced/advanced-dependencies.md b/docs/de/docs/advanced/advanced-dependencies.md new file mode 100644 index 0000000000000..da06794a92fde --- /dev/null +++ b/docs/de/docs/advanced/advanced-dependencies.md @@ -0,0 +1,164 @@ +# Fortgeschrittene Abhängigkeiten { #advanced-dependencies } + + +## Parametrisierte Abhängigkeiten { #parameterized-dependencies } + +Alle Abhängigkeiten, die wir bisher gesehen haben, waren festgelegte Funktionen oder Klassen. + +Es kann jedoch Fälle geben, in denen Sie Parameter für eine Abhängigkeit festlegen möchten, ohne viele verschiedene Funktionen oder Klassen zu deklarieren. + +Stellen wir uns vor, wir möchten eine Abhängigkeit haben, die prüft, ob ein Query-Parameter `q` einen vordefinierten Inhalt hat. + +Aber wir wollen diesen vordefinierten Inhalt per Parameter festlegen können. + +## Eine „aufrufbare“ Instanz { #a-callable-instance } + +In Python gibt es eine Möglichkeit, eine Instanz einer Klasse „aufrufbar“ zu machen. + +Nicht die Klasse selbst (die bereits aufrufbar ist), sondern eine Instanz dieser Klasse. + +Dazu deklarieren wir eine Methode `__call__`: + +{* ../../docs_src/dependencies/tutorial011_an_py310.py hl[12] *} + +In diesem Fall ist dieses `__call__` das, was **FastAPI** verwendet, um nach zusätzlichen Parametern und Unterabhängigkeiten zu suchen, und das ist es auch, was später aufgerufen wird, um einen Wert an den Parameter in Ihrer *Pfadoperation-Funktion* zu übergeben. + +## Die Instanz parametrisieren { #parameterize-the-instance } + +Und jetzt können wir `__init__` verwenden, um die Parameter der Instanz zu deklarieren, die wir zum „Parametrisieren“ der Abhängigkeit verwenden können: + +{* ../../docs_src/dependencies/tutorial011_an_py310.py hl[9] *} + +In diesem Fall wird **FastAPI** `__init__` nie berühren oder sich darum kümmern, wir werden es direkt in unserem Code verwenden. + +## Eine Instanz erstellen { #create-an-instance } + +Wir könnten eine Instanz dieser Klasse erstellen mit: + +{* ../../docs_src/dependencies/tutorial011_an_py310.py hl[18] *} + +Und auf diese Weise können wir unsere Abhängigkeit „parametrisieren“, die jetzt `"bar"` enthält, als das Attribut `checker.fixed_content`. + +## Die Instanz als Abhängigkeit verwenden { #use-the-instance-as-a-dependency } + +Dann könnten wir diesen `checker` in einem `Depends(checker)` anstelle von `Depends(FixedContentQueryChecker)` verwenden, da die Abhängigkeit die Instanz `checker` und nicht die Klasse selbst ist. + +Und beim Auflösen der Abhängigkeit ruft **FastAPI** diesen `checker` wie folgt auf: + +```Python +checker(q="somequery") +``` + +... und übergibt, was immer das als Wert dieser Abhängigkeit in unserer *Pfadoperation-Funktion* zurückgibt, als den Parameter `fixed_content_included`: + +{* ../../docs_src/dependencies/tutorial011_an_py310.py hl[22] *} + +/// tip | Tipp + +Das alles mag gekünstelt wirken. Und es ist möglicherweise noch nicht ganz klar, welchen Nutzen das hat. + +Diese Beispiele sind bewusst einfach gehalten, zeigen aber, wie alles funktioniert. + +In den Kapiteln zum Thema Sicherheit gibt es Hilfsfunktionen, die auf die gleiche Weise implementiert werden. + +Wenn Sie das hier alles verstanden haben, wissen Sie bereits, wie diese Sicherheits-Hilfswerkzeuge unter der Haube funktionieren. + +/// + +## Abhängigkeiten mit `yield`, `HTTPException`, `except` und Hintergrundtasks { #dependencies-with-yield-httpexception-except-and-background-tasks } + +/// warning | Achtung + +Sie benötigen diese technischen Details höchstwahrscheinlich nicht. + +Diese Details sind hauptsächlich nützlich, wenn Sie eine FastAPI-Anwendung haben, die älter als 0.121.0 ist, und Sie auf Probleme mit Abhängigkeiten mit `yield` stoßen. + +/// + +Abhängigkeiten mit `yield` haben sich im Laufe der Zeit weiterentwickelt, um verschiedene Anwendungsfälle abzudecken und einige Probleme zu beheben, hier ist eine Zusammenfassung der Änderungen. + +### Abhängigkeiten mit `yield` und `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 } + +Vor FastAPI 0.118.0 wurde bei Verwendung einer Abhängigkeit mit `yield` der Exit-Code nach der *Pfadoperation-Funktion* ausgeführt, aber unmittelbar bevor die Response gesendet wurde. + +Die Absicht war, Ressourcen nicht länger als nötig zu halten, während darauf gewartet wird, dass die Response durchs Netzwerk reist. + +Diese Änderung bedeutete auch, dass bei Rückgabe einer `StreamingResponse` der Exit-Code der Abhängigkeit mit `yield` bereits ausgeführt worden wäre. + +Wenn Sie beispielsweise eine Datenbanksession in einer Abhängigkeit mit `yield` hatten, konnte die `StreamingResponse` diese Session während des Streamens von Daten nicht verwenden, weil die Session im Exit-Code nach `yield` bereits geschlossen worden wäre. + +Dieses Verhalten wurde in 0.118.0 zurückgenommen, sodass der Exit-Code nach `yield` ausgeführt wird, nachdem die Response gesendet wurde. + +/// note | Hinweis + +Wie Sie unten sehen werden, ähnelt dies sehr dem Verhalten vor Version 0.106.0, jedoch mit mehreren Verbesserungen und Bugfixes für Sonderfälle. + +/// + +#### Anwendungsfälle mit frühem Exit-Code { #use-cases-with-early-exit-code } + +Es gibt einige Anwendungsfälle mit spezifischen Bedingungen, die vom alten Verhalten profitieren könnten, den Exit-Code von Abhängigkeiten mit `yield` vor dem Senden der Response auszuführen. + +Stellen Sie sich zum Beispiel vor, Sie haben Code, der in einer Abhängigkeit mit `yield` eine Datenbanksession verwendet, nur um einen Benutzer zu verifizieren, die Datenbanksession wird aber in der *Pfadoperation-Funktion* nie wieder verwendet, sondern nur in der Abhängigkeit, und die Response benötigt lange, um gesendet zu werden, wie eine `StreamingResponse`, die Daten langsam sendet, aus irgendeinem Grund aber die Datenbank nicht verwendet. + +In diesem Fall würde die Datenbanksession gehalten, bis das Senden der Response abgeschlossen ist, aber wenn Sie sie nicht verwenden, wäre es nicht notwendig, sie zu halten. + +So könnte es aussehen: + +{* ../../docs_src/dependencies/tutorial013_an_py310.py *} + +Der Exit-Code, das automatische Schließen der `Session` in: + +{* ../../docs_src/dependencies/tutorial013_an_py310.py ln[19:21] *} + +... würde ausgeführt, nachdem die Response das langsame Senden der Daten beendet: + +{* ../../docs_src/dependencies/tutorial013_an_py310.py ln[30:38] hl[31:33] *} + +Da `generate_stream()` die Datenbanksession jedoch nicht verwendet, ist es nicht wirklich notwendig, die Session während des Sendens der Response offen zu halten. + +Wenn Sie diesen spezifischen Anwendungsfall mit SQLModel (oder SQLAlchemy) haben, könnten Sie die Session explizit schließen, nachdem Sie sie nicht mehr benötigen: + +{* ../../docs_src/dependencies/tutorial014_an_py310.py ln[24:28] hl[28] *} + +Auf diese Weise würde die Session die Datenbankverbindung freigeben, sodass andere Requests sie verwenden könnten. + +Wenn Sie einen anderen Anwendungsfall haben, der ein frühes Beenden aus einer Abhängigkeit mit `yield` benötigt, erstellen Sie bitte eine [GitHub-Diskussion-Frage](https://github.com/fastapi/fastapi/discussions/new?category=questions) mit Ihrem spezifischen Anwendungsfall und warum Sie von einem frühen Schließen für Abhängigkeiten mit `yield` profitieren würden. + +Wenn es überzeugende Anwendungsfälle für ein frühes Schließen bei Abhängigkeiten mit `yield` gibt, würde ich erwägen, eine neue Möglichkeit hinzuzufügen, um ein frühes Schließen optional zu aktivieren. + +### Abhängigkeiten mit `yield` und `except`, Technische Details { #dependencies-with-yield-and-except-technical-details } + +Vor FastAPI 0.110.0 war es so, dass wenn Sie eine Abhängigkeit mit `yield` verwendet und dann in dieser Abhängigkeit mit `except` eine Exception abgefangen haben und die Exception nicht erneut geworfen haben, die Exception automatisch an beliebige Exceptionhandler oder den Handler für interne Serverfehler weitergereicht/weitergeworfen wurde. + +Dies wurde in Version 0.110.0 geändert, um unbehandelten Speicherverbrauch durch weitergeleitete Exceptions ohne Handler (interne Serverfehler) zu beheben und um es mit dem Verhalten von normalem Python-Code konsistent zu machen. + +### Hintergrundtasks und Abhängigkeiten mit `yield`, Technische Details { #background-tasks-and-dependencies-with-yield-technical-details } + +Vor FastAPI 0.106.0 war das Werfen von Exceptions nach `yield` nicht möglich, der Exit-Code in Abhängigkeiten mit `yield` wurde ausgeführt, nachdem die Response gesendet wurde, sodass [Exceptionhandler](../tutorial/handling-errors.md#install-custom-exception-handlers) bereits ausgeführt worden wären. + +Dies war so designt, hauptsächlich um die Verwendung derselben von Abhängigkeiten „geyieldeten“ Objekte in Hintergrundtasks zu ermöglichen, da der Exit-Code erst ausgeführt wurde, nachdem die Hintergrundtasks abgeschlossen waren. + +Dies wurde in FastAPI 0.106.0 geändert mit der Absicht, keine Ressourcen zu halten, während darauf gewartet wird, dass die Response durchs Netzwerk reist. + +/// tip | Tipp + +Zusätzlich ist ein Hintergrundtask normalerweise ein unabhängiger Logikblock, der separat gehandhabt werden sollte, mit eigenen Ressourcen (z. B. eigener Datenbankverbindung). + +So haben Sie wahrscheinlich saubereren Code. + +/// + +Wenn Sie sich bisher auf dieses Verhalten verlassen haben, sollten Sie jetzt die Ressourcen für Hintergrundtasks innerhalb des Hintergrundtasks selbst erstellen und intern nur Daten verwenden, die nicht von den Ressourcen von Abhängigkeiten mit `yield` abhängen. + +Anstatt beispielsweise dieselbe Datenbanksession zu verwenden, würden Sie innerhalb des Hintergrundtasks eine neue Datenbanksession erstellen und die Objekte aus der Datenbank mithilfe dieser neuen Session beziehen. Und anstatt das Objekt aus der Datenbank als Parameter an die Hintergrundtask-Funktion zu übergeben, würden Sie die ID dieses Objekts übergeben und das Objekt dann innerhalb der Hintergrundtask-Funktion erneut beziehen. diff --git a/docs/de/docs/advanced/advanced-python-types.md b/docs/de/docs/advanced/advanced-python-types.md new file mode 100644 index 0000000000000..aed859ceff525 --- /dev/null +++ b/docs/de/docs/advanced/advanced-python-types.md @@ -0,0 +1,61 @@ +# Fortgeschrittene Python-Typen { #advanced-python-types } + +Hier sind einige zusätzliche Ideen, die beim Arbeiten mit Python-Typen nützlich sein könnten. + +## `Union` oder `Optional` verwenden { #using-union-or-optional } + +Wenn Ihr Code aus irgendeinem Grund nicht `|` verwenden kann, z. B. wenn es nicht in einer Typannotation ist, sondern in etwas wie `response_model=`, können Sie anstelle des senkrechten Strichs (`|`) `Union` aus `typing` verwenden. + +Zum Beispiel könnten Sie deklarieren, dass etwas ein `str` oder `None` sein könnte: + +```python +from typing import Union + + +def say_hi(name: Union[str, None]): + print(f"Hi {name}!") +``` + +`typing` hat außerdem eine Abkürzung, um zu deklarieren, dass etwas `None` sein könnte, mit `Optional`. + +Hier ist ein Tipp aus meiner sehr **subjektiven** Perspektive: + +* 🚨 Vermeiden Sie die Verwendung von `Optional[SomeType]` +* Verwenden Sie stattdessen ✨ **`Union[SomeType, None]`** ✨. + +Beides ist äquivalent und unter der Haube identisch, aber ich würde `Union` statt `Optional` empfehlen, weil das Wort „**optional**“ implizieren könnte, dass der Wert optional ist; tatsächlich bedeutet es jedoch „es kann `None` sein“, selbst wenn es nicht optional ist und weiterhin erforderlich bleibt. + +Ich finde, `Union[SomeType, None]` ist expliziter in dem, was es bedeutet. + +Es geht nur um Wörter und Namen. Aber diese Wörter können beeinflussen, wie Sie und Ihr Team über den Code denken. + +Als Beispiel nehmen wir diese Funktion: + +```python +from typing import Optional + + +def say_hi(name: Optional[str]): + print(f"Hey {name}!") +``` + +Der Parameter `name` ist als `Optional[str]` definiert, aber er ist **nicht optional**, Sie können die Funktion nicht ohne den Parameter aufrufen: + +```Python +say_hi() # Oh nein, das löst einen Fehler aus! 😱 +``` + +Der Parameter `name` ist **weiterhin erforderlich** (nicht *optional*), weil er keinen Defaultwert hat. Dennoch akzeptiert `name` den Wert `None`: + +```Python +say_hi(name=None) # Das funktioniert, None ist gültig 🎉 +``` + +Die gute Nachricht ist: In den meisten Fällen können Sie einfach `|` verwenden, um Unions von Typen zu definieren: + +```python +def say_hi(name: str | None): + print(f"Hey {name}!") +``` + +Sie müssen sich also normalerweise keine Gedanken über Namen wie `Optional` und `Union` machen. 😎 diff --git a/docs/de/docs/advanced/async-tests.md b/docs/de/docs/advanced/async-tests.md new file mode 100644 index 0000000000000..58c925ae6edfc --- /dev/null +++ b/docs/de/docs/advanced/async-tests.md @@ -0,0 +1,99 @@ +# Asynchrone Tests { #async-tests } + +Sie haben bereits gesehen, wie Sie Ihre **FastAPI**-Anwendungen mit dem bereitgestellten `TestClient` testen. Bisher haben Sie nur gesehen, wie man synchrone Tests schreibt, ohne `async`-Funktionen zu verwenden. + +Die Möglichkeit, in Ihren Tests asynchrone Funktionen zu verwenden, könnte beispielsweise nützlich sein, wenn Sie Ihre Datenbank asynchron abfragen. Stellen Sie sich vor, Sie möchten das Senden von Requests an Ihre FastAPI-Anwendung testen und dann überprüfen, ob Ihr Backend die richtigen Daten erfolgreich in die Datenbank geschrieben hat, während Sie eine asynchrone Datenbankbibliothek verwenden. + +Schauen wir uns an, wie wir das machen können. + +## pytest.mark.anyio { #pytest-mark-anyio } + +Wenn wir in unseren Tests asynchrone Funktionen aufrufen möchten, müssen unsere Testfunktionen asynchron sein. AnyIO stellt hierfür ein nettes Plugin zur Verfügung, mit dem wir festlegen können, dass einige Testfunktionen asynchron aufgerufen werden sollen. + +## HTTPX { #httpx } + +Auch wenn Ihre **FastAPI**-Anwendung normale `def`-Funktionen anstelle von `async def` verwendet, handelt es sich darunter immer noch um eine `async`-Anwendung. + +Der `TestClient` betreibt unter der Haube etwas Magie, um die asynchrone FastAPI-Anwendung in Ihren normalen `def`-Testfunktionen, mithilfe von Standard-Pytest aufzurufen. Aber diese Magie funktioniert nicht mehr, wenn wir sie in asynchronen Funktionen verwenden. Durch die asynchrone Ausführung unserer Tests können wir den `TestClient` nicht mehr in unseren Testfunktionen verwenden. + +Der `TestClient` basiert auf [HTTPX](https://www.python-httpx.org) und glücklicherweise können wir es direkt verwenden, um die API zu testen. + +## Beispiel { #example } + +Betrachten wir als einfaches Beispiel eine Dateistruktur ähnlich der in [Größere Anwendungen](../tutorial/bigger-applications.md) und [Testen](../tutorial/testing.md): + +``` +. +├── app +│   ├── __init__.py +│   ├── main.py +│   └── test_main.py +``` + +Die Datei `main.py` hätte als Inhalt: + +{* ../../docs_src/async_tests/app_a_py310/main.py *} + +Die Datei `test_main.py` hätte die Tests für `main.py`, das könnte jetzt so aussehen: + +{* ../../docs_src/async_tests/app_a_py310/test_main.py *} + +## Es ausführen { #run-it } + +Sie können Ihre Tests wie gewohnt ausführen mit: + +
+ +```console +$ pytest + +---> 100% +``` + +
+ +## Im Detail { #in-detail } + +Der Marker `@pytest.mark.anyio` teilt pytest mit, dass diese Testfunktion asynchron aufgerufen werden soll: + +{* ../../docs_src/async_tests/app_a_py310/test_main.py hl[7] *} + +/// tip | Tipp + +Beachten Sie, dass die Testfunktion jetzt `async def` ist und nicht nur `def` wie zuvor, wenn Sie den `TestClient` verwenden. + +/// + +Dann können wir einen `AsyncClient` mit der App erstellen und mit `await` asynchrone Requests an ihn senden. + +{* ../../docs_src/async_tests/app_a_py310/test_main.py hl[9:12] *} + +Das ist das Äquivalent zu: + +```Python +response = client.get('/') +``` + +... welches wir verwendet haben, um unsere Requests mit dem `TestClient` zu machen. + +/// tip | Tipp + +Beachten Sie, dass wir async/await mit dem neuen `AsyncClient` verwenden – der Request ist asynchron. + +/// + +/// warning | Achtung + +Falls Ihre Anwendung auf Lifespan-Events angewiesen ist, der `AsyncClient` löst diese Events nicht aus. Um sicherzustellen, dass sie ausgelöst werden, verwenden Sie `LifespanManager` von [florimondmanca/asgi-lifespan](https://github.com/florimondmanca/asgi-lifespan#usage). + +/// + +## Andere asynchrone Funktionsaufrufe { #other-asynchronous-function-calls } + +Da die Testfunktion jetzt asynchron ist, können Sie in Ihren Tests neben dem Senden von Requests an Ihre FastAPI-Anwendung jetzt auch andere `async`-Funktionen aufrufen (und `await`en), genau so, wie Sie diese an anderer Stelle in Ihrem Code aufrufen würden. + +/// tip | Tipp + +Wenn Sie einen `RuntimeError: Task attached to a different loop` erhalten, wenn Sie asynchrone Funktionsaufrufe in Ihre Tests integrieren (z. B. bei Verwendung von [MongoDBs MotorClient](https://stackoverflow.com/questions/41584243/runtimeerror-task-attached-to-a-different-loop)), dann denken Sie daran, Objekte zu instanziieren, die einen Event Loop nur innerhalb asynchroner Funktionen benötigen, z. B. einen `@app.on_event("startup")`-Callback. + +/// diff --git a/docs/de/docs/advanced/behind-a-proxy.md b/docs/de/docs/advanced/behind-a-proxy.md new file mode 100644 index 0000000000000..7260202198a1c --- /dev/null +++ b/docs/de/docs/advanced/behind-a-proxy.md @@ -0,0 +1,466 @@ +# Hinter einem Proxy { #behind-a-proxy } + +In vielen Situationen würden Sie einen **Proxy** wie Traefik oder Nginx vor Ihrer FastAPI-App verwenden. + +Diese Proxys könnten HTTPS-Zertifikate und andere Dinge handhaben. + +## Proxy-Forwarded-Header { #proxy-forwarded-headers } + +Ein **Proxy** vor Ihrer Anwendung würde normalerweise einige Header on-the-fly setzen, bevor er die Requests an den **Server** sendet, um den Server wissen zu lassen, dass der Request vom Proxy **weitergeleitet** wurde, einschließlich der ursprünglichen (öffentlichen) URL, inklusive der Domain, dass HTTPS verwendet wird, usw. + +Das **Server**-Programm (z. B. **Uvicorn** via **FastAPI CLI**) ist in der Lage, diese Header zu interpretieren und diese Information dann an Ihre Anwendung weiterzugeben. + +Aber aus Sicherheitsgründen, da der Server nicht weiß, dass er hinter einem vertrauenswürdigen Proxy läuft, wird er diese Header nicht interpretieren. + +/// note | Technische Details + +Die Proxy-Header sind: + +* [X-Forwarded-For](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Forwarded-For) +* [X-Forwarded-Proto](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Forwarded-Proto) +* [X-Forwarded-Host](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Forwarded-Host) + +/// + +### Proxy-Forwarded-Header aktivieren { #enable-proxy-forwarded-headers } + +Sie können FastAPI CLI mit der *CLI-Option* `--forwarded-allow-ips` starten und die IP-Adressen übergeben, denen vertraut werden soll, um diese Forwarded-Header zu lesen. + +Wenn Sie es auf `--forwarded-allow-ips="*"` setzen, würde es allen eingehenden IPs vertrauen. + +Wenn Ihr **Server** hinter einem vertrauenswürdigen **Proxy** sitzt und nur der Proxy mit ihm spricht, würde dies dazu führen, dass er die IP dieses **Proxys** akzeptiert, was auch immer sie ist. + +
+ +```console +$ fastapi run --forwarded-allow-ips="*" + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +### Weiterleitungen mit HTTPS { #redirects-with-https } + +Angenommen, Sie definieren eine *Pfadoperation* `/items/`: + +{* ../../docs_src/behind_a_proxy/tutorial001_01_py310.py hl[6] *} + +Wenn der Client versucht, zu `/items` zu gehen, würde er standardmäßig zu `/items/` umgeleitet. + +Aber bevor Sie die *CLI-Option* `--forwarded-allow-ips` setzen, könnte er zu `http://localhost:8000/items/` umleiten. + +Aber möglicherweise wird Ihre Anwendung unter `https://mysuperapp.com` gehostet, und die Weiterleitung sollte zu `https://mysuperapp.com/items/` erfolgen. + +Durch Setzen von `--proxy-headers` kann FastAPI jetzt an den richtigen Ort umleiten. 😎 + +``` +https://mysuperapp.com/items/ +``` + +/// tip | Tipp + +Wenn Sie mehr über HTTPS erfahren möchten, lesen Sie den Leitfaden [Über HTTPS](../deployment/https.md). + +/// + +### Wie Proxy-Forwarded-Header funktionieren { #how-proxy-forwarded-headers-work } + +Hier ist eine visuelle Darstellung, wie der **Proxy** weitergeleitete Header zwischen dem Client und dem **Anwendungsserver** hinzufügt: + +```mermaid +sequenceDiagram + participant Client + participant Proxy as Proxy/Loadbalancer + participant Server as FastAPI Server + + Client->>Proxy: HTTPS-Request
Host: mysuperapp.com
Pfad: /items + + Note over Proxy: Proxy fügt Forwarded-Header hinzu + + Proxy->>Server: HTTP-Request
X-Forwarded-For: [client IP]
X-Forwarded-Proto: https
X-Forwarded-Host: mysuperapp.com
Pfad: /items + + Note over Server: Server interpretiert die Header
(wenn --forwarded-allow-ips gesetzt ist) + + Server->>Proxy: HTTP-Response
mit correkten HTTPS-URLs + + Proxy->>Client: HTTPS-Response +``` + +Der **Proxy** fängt den ursprünglichen Client-Request ab und fügt die speziellen *Forwarded*-Header (`X-Forwarded-*`) hinzu, bevor er den Request an den **Anwendungsserver** weitergibt. + +Diese Header bewahren Informationen über den ursprünglichen Request, die sonst verloren gingen: + +* **X-Forwarded-For**: Die ursprüngliche IP-Adresse des Clients +* **X-Forwarded-Proto**: Das ursprüngliche Protokoll (`https`) +* **X-Forwarded-Host**: Der ursprüngliche Host (`mysuperapp.com`) + +Wenn **FastAPI CLI** mit `--forwarded-allow-ips` konfiguriert ist, vertraut es diesen Headern und verwendet sie, z. B. um die korrekten URLs in Weiterleitungen zu erzeugen. + +## Proxy mit einem abgetrennten Pfadpräfix { #proxy-with-a-stripped-path-prefix } + +Sie könnten einen Proxy haben, der Ihrer Anwendung ein Pfadpräfix hinzufügt. + +In diesen Fällen können Sie `root_path` verwenden, um Ihre Anwendung zu konfigurieren. + +Der `root_path` ist ein Mechanismus, der von der ASGI-Spezifikation bereitgestellt wird (auf der FastAPI via Starlette aufbaut). + +Der `root_path` wird verwendet, um diese speziellen Fälle zu handhaben. + +Und er wird auch intern beim Mounten von Unteranwendungen verwendet. + +Ein Proxy mit einem abgetrennten Pfadpräfix bedeutet in diesem Fall, dass Sie einen Pfad unter `/app` in Ihrem Code deklarieren könnten, dann aber, eine Ebene darüber, den Proxy hinzufügen, der Ihre **FastAPI**-Anwendung unter einem Pfad wie `/api/v1` platziert. + +In diesem Fall würde der ursprüngliche Pfad `/app` tatsächlich unter `/api/v1/app` bereitgestellt. + +Auch wenn Ihr gesamter Code unter der Annahme geschrieben ist, dass es nur `/app` gibt. + +{* ../../docs_src/behind_a_proxy/tutorial001_py310.py hl[6] *} + +Und der Proxy würde das **Pfadpräfix** on-the-fly **„entfernen“**, bevor er den Request an den Anwendungsserver (wahrscheinlich Uvicorn via FastAPI CLI) übermittelt, dafür sorgend, dass Ihre Anwendung davon überzeugt ist, dass sie unter `/app` bereitgestellt wird, sodass Sie nicht Ihren gesamten Code dahingehend aktualisieren müssen, das Präfix `/api/v1` zu verwenden. + +Bis hierher würde alles wie gewohnt funktionieren. + +Wenn Sie dann jedoch die Benutzeroberfläche der integrierten Dokumentation (das Frontend) öffnen, wird angenommen, dass sich das OpenAPI-Schema unter `/openapi.json` anstelle von `/api/v1/openapi.json` befindet. + +Also würde das Frontend (das im Browser läuft) versuchen, `/openapi.json` zu erreichen und wäre nicht in der Lage, das OpenAPI-Schema abzurufen. + +Da wir für unsere Anwendung einen Proxy mit dem Pfadpräfix `/api/v1` haben, muss das Frontend das OpenAPI-Schema unter `/api/v1/openapi.json` abrufen. + +```mermaid +graph LR + +browser("Browser") +proxy["Proxy auf http://0.0.0.0:9999/api/v1/app"] +server["Server auf http://127.0.0.1:8000/app"] + +browser --> proxy +proxy --> server +``` + +/// tip | Tipp + +Die IP `0.0.0.0` wird üblicherweise verwendet, um anzudeuten, dass das Programm alle auf diesem Computer/Server verfügbaren IPs abhört. + +/// + +Die Benutzeroberfläche der Dokumentation würde benötigen, dass das OpenAPI-Schema deklariert, dass sich dieser API-`server` unter `/api/v1` (hinter dem Proxy) befindet. Zum Beispiel: + +```JSON hl_lines="4-8" +{ + "openapi": "3.1.0", + // Hier mehr Einstellungen + "servers": [ + { + "url": "/api/v1" + } + ], + "paths": { + // Hier mehr Einstellungen + } +} +``` + +In diesem Beispiel könnte der „Proxy“ etwa **Traefik** sein. Und der Server wäre etwas wie FastAPI CLI mit **Uvicorn**, auf dem Ihre FastAPI-Anwendung ausgeführt wird. + +### Bereitstellung des `root_path` { #providing-the-root-path } + +Um dies zu erreichen, können Sie die Kommandozeilenoption `--root-path` wie folgt verwenden: + +
+ +```console +$ fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1 + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +Falls Sie Hypercorn verwenden, das hat auch die Option `--root-path`. + +/// note | Technische Details + +Die ASGI-Spezifikation definiert einen `root_path` für diesen Anwendungsfall. + +Und die Kommandozeilenoption `--root-path` stellt diesen `root_path` bereit. + +/// + +### Testen des aktuellen `root_path` { #checking-the-current-root-path } + +Sie können den aktuellen `root_path` abrufen, der von Ihrer Anwendung für jeden Request verwendet wird. Er ist Teil des `scope`-Dictionarys (das ist Teil der ASGI-Spezifikation). + +Hier fügen wir ihn, nur zu Demonstrationszwecken, in die Nachricht ein. + +{* ../../docs_src/behind_a_proxy/tutorial001_py310.py hl[8] *} + +Wenn Sie Uvicorn dann starten mit: + +
+ +```console +$ fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1 + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +wäre die Response etwa: + +```JSON +{ + "message": "Hello World", + "root_path": "/api/v1" +} +``` + +### Festlegen des `root_path` in der FastAPI-Anwendung { #setting-the-root-path-in-the-fastapi-app } + +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_py310.py hl[3] *} + +Die Übergabe des `root_path` an `FastAPI` wäre das Äquivalent zur Übergabe der `--root-path`-Kommandozeilenoption an Uvicorn oder Hypercorn. + +### Über `root_path` { #about-root-path } + +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 [http://127.0.0.1:8000/app](http://127.0.0.1:8000/app) gehen, sehen Sie die normale Response: + +```JSON +{ + "message": "Hello World", + "root_path": "/api/v1" +} +``` + +Es wird also nicht erwartet, dass unter `http://127.0.0.1:8000/api/v1/app` darauf zugegriffen wird. + +Uvicorn erwartet, dass der Proxy unter `http://127.0.0.1:8000/app` auf Uvicorn zugreift, und dann liegt es in der Verantwortung des Proxys, das zusätzliche `/api/v1`-Präfix darüber hinzuzufügen. + +## Über Proxys mit einem abgetrennten Pfadpräfix { #about-proxies-with-a-stripped-path-prefix } + +Bedenken Sie, dass ein Proxy mit abgetrenntem Pfadpräfix nur eine von vielen Konfigurationsmöglichkeiten ist. + +Wahrscheinlich wird in vielen Fällen die Standardeinstellung sein, dass der Proxy kein abgetrenntes Pfadpräfix hat. + +In einem solchen Fall (ohne ein abgetrenntes Pfadpräfix) würde der Proxy auf etwas wie `https://myawesomeapp.com` lauschen, und wenn der Browser dann zu `https://myawesomeapp.com/api/v1/app` wechselt, und Ihr Server (z. B. Uvicorn) auf `http://127.0.0.1:8000` lauscht, würde der Proxy (ohne ein abgetrenntes Pfadpräfix) über denselben Pfad auf Uvicorn zugreifen: `http://127.0.0.1:8000/api/v1/app`. + +## Lokal testen mit Traefik { #testing-locally-with-traefik } + +Sie können das Experiment mit einem abgetrennten Pfadpräfix einfach lokal ausführen, indem Sie [Traefik](https://docs.traefik.io/) verwenden. + +[Laden Sie Traefik herunter](https://github.com/containous/traefik/releases), es ist eine einzelne Binärdatei, Sie können die komprimierte Datei extrahieren und sie direkt vom Terminal aus ausführen. + +Dann erstellen Sie eine Datei `traefik.toml` mit: + +```TOML hl_lines="3" +[entryPoints] + [entryPoints.http] + address = ":9999" + +[providers] + [providers.file] + filename = "routes.toml" +``` + +Dadurch wird Traefik angewiesen, Port 9999 abzuhören und eine andere Datei `routes.toml` zu verwenden. + +/// tip | Tipp + +Wir verwenden Port 9999 anstelle des Standard-HTTP-Ports 80, damit Sie ihn nicht mit Administratorrechten (`sudo`) ausführen müssen. + +/// + +Erstellen Sie nun die andere Datei `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" +``` + +Diese Datei konfiguriert Traefik, das Pfadpräfix `/api/v1` zu verwenden. + +Und dann leitet Traefik seine Requests an Ihren Uvicorn weiter, der unter `http://127.0.0.1:8000` läuft. + +Starten Sie nun Traefik: + +
+ +```console +$ ./traefik --configFile=traefik.toml + +INFO[0000] Configuration loaded from file: /home/user/awesomeapi/traefik.toml +``` + +
+ +Und jetzt starten Sie Ihre Anwendung mit Uvicorn, indem Sie die Option `--root-path` verwenden: + +
+ +```console +$ fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1 + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +### Die Responses testen { #check-the-responses } + +Wenn Sie nun zur URL mit dem Port für Uvicorn gehen: [http://127.0.0.1:8000/app](http://127.0.0.1:8000/app), sehen Sie die normale Response: + +```JSON +{ + "message": "Hello World", + "root_path": "/api/v1" +} +``` + +/// tip | Tipp + +Beachten Sie, dass, obwohl Sie unter `http://127.0.0.1:8000/app` darauf zugreifen, als `root_path` angezeigt wird `/api/v1`, welches aus der Option `--root-path` stammt. + +/// + +Öffnen Sie nun die URL mit dem Port für Traefik, einschließlich des Pfadpräfixes: [http://127.0.0.1:9999/api/v1/app](http://127.0.0.1:9999/api/v1/app). + +Wir bekommen die gleiche Response: + +```JSON +{ + "message": "Hello World", + "root_path": "/api/v1" +} +``` + +Diesmal jedoch unter der URL mit dem vom Proxy bereitgestellten Präfixpfad: `/api/v1`. + +Die Idee hier ist natürlich, dass jeder über den Proxy auf die Anwendung zugreifen soll, daher ist die Version mit dem Pfadpräfix `/api/v1` die „korrekte“. + +Und die von Uvicorn direkt bereitgestellte Version ohne Pfadpräfix (`http://127.0.0.1:8000/app`) wäre ausschließlich für den Zugriff durch den _Proxy_ (Traefik) bestimmt. + +Dies demonstriert, wie der Proxy (Traefik) das Pfadpräfix verwendet und wie der Server (Uvicorn) den `root_path` aus der Option `--root-path` verwendet. + +### Es in der Dokumentationsoberfläche testen { #check-the-docs-ui } + +Jetzt folgt der spaßige Teil. ✨ + +Der „offizielle“ Weg, auf die Anwendung zuzugreifen, wäre über den Proxy mit dem von uns definierten Pfadpräfix. Wenn Sie also die von Uvicorn direkt bereitgestellte Dokumentationsoberfläche ohne das Pfadpräfix in der URL ausprobieren, wird es erwartungsgemäß nicht funktionieren, da erwartet wird, dass der Zugriff über den Proxy erfolgt. + +Sie können das unter [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs) sehen: + + + +Wenn wir jedoch unter der „offiziellen“ URL, über den Proxy mit Port `9999`, unter `/api/v1/docs`, auf die Dokumentationsoberfläche zugreifen, funktioniert es ordnungsgemäß! 🎉 + +Sie können das unter [http://127.0.0.1:9999/api/v1/docs](http://127.0.0.1:9999/api/v1/docs) testen: + + + +Genau so, wie wir es wollten. ✔️ + +Dies liegt daran, dass FastAPI diesen `root_path` verwendet, um den Default-`server` in OpenAPI mit der von `root_path` bereitgestellten URL zu erstellen. + +## Zusätzliche Server { #additional-servers } + +/// warning | Achtung + +Dies ist ein fortgeschrittener Anwendungsfall. Überspringen Sie das gerne. + +/// + +Standardmäßig erstellt **FastAPI** einen `server` im OpenAPI-Schema mit der URL für den `root_path`. + +Sie können aber auch andere alternative `servers` bereitstellen, beispielsweise wenn Sie möchten, dass *dieselbe* Dokumentationsoberfläche mit einer Staging- und Produktionsumgebung interagiert. + +Wenn Sie eine benutzerdefinierte Liste von Servern (`servers`) übergeben und es einen `root_path` gibt (da Ihre API hinter einem Proxy läuft), fügt **FastAPI** einen „Server“ mit diesem `root_path` am Anfang der Liste ein. + +Zum Beispiel: + +{* ../../docs_src/behind_a_proxy/tutorial003_py310.py hl[4:7] *} + +Erzeugt ein OpenAPI-Schema, wie: + +```JSON hl_lines="5-7" +{ + "openapi": "3.1.0", + // Hier mehr Einstellungen + "servers": [ + { + "url": "/api/v1" + }, + { + "url": "https://stag.example.com", + "description": "Staging environment" + }, + { + "url": "https://prod.example.com", + "description": "Production environment" + } + ], + "paths": { + // Hier mehr Einstellungen + } +} +``` + +/// tip | Tipp + +Beachten Sie den automatisch generierten Server mit dem `URL`-Wert `/api/v1`, welcher vom `root_path` stammt. + +/// + +In der Dokumentationsoberfläche unter [http://127.0.0.1:9999/api/v1/docs](http://127.0.0.1:9999/api/v1/docs) würde es so aussehen: + + + +/// tip | Tipp + +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 } + +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_py310.py hl[9] *} + +Dann wird er nicht in das OpenAPI-Schema aufgenommen. + +## Mounten einer Unteranwendung { #mounting-a-sub-application } + +Wenn Sie gleichzeitig eine Unteranwendung mounten (wie beschrieben in [Unteranwendungen – Mounts](sub-applications.md)) und einen Proxy mit `root_path` verwenden wollen, können Sie das normal tun, wie Sie es erwarten würden. + +FastAPI verwendet intern den `root_path` auf intelligente Weise, sodass es einfach funktioniert. ✨ diff --git a/docs/de/docs/advanced/custom-response.md b/docs/de/docs/advanced/custom-response.md new file mode 100644 index 0000000000000..377c7f569dadb --- /dev/null +++ b/docs/de/docs/advanced/custom-response.md @@ -0,0 +1,273 @@ +# Benutzerdefinierte Response – HTML, Stream, Datei, andere { #custom-response-html-stream-file-others } + +Standardmäßig gibt **FastAPI** JSON-Responses zurück. + +Sie können dies überschreiben, indem Sie direkt eine `Response` zurückgeben, wie in [Eine Response direkt zurückgeben](response-directly.md) gezeigt. + +Wenn Sie jedoch direkt eine `Response` (oder eine Unterklasse wie `JSONResponse`) zurückgeben, werden die Daten nicht automatisch konvertiert (selbst wenn Sie ein `response_model` deklarieren), und die Dokumentation wird nicht automatisch generiert (zum Beispiel einschließlich des spezifischen „Medientyps“ im HTTP-Header `Content-Type` als Teil der generierten OpenAPI). + +Sie können jedoch auch die `Response`, die Sie verwenden möchten (z. B. jede `Response`-Unterklasse), im *Pfadoperation-Dekorator* mit dem `response_class`-Parameter deklarieren. + +Der Inhalt, den Sie von Ihrer *Pfadoperation-Funktion* zurückgeben, wird in diese `Response` eingefügt. + +/// note | Hinweis + +Wenn Sie eine Response-Klasse ohne Medientyp verwenden, erwartet FastAPI, dass Ihre Response keinen Inhalt hat, und dokumentiert daher das Format der Response nicht in deren generierter OpenAPI-Dokumentation. + +/// + +## JSON-Responses { #json-responses } + +Standardmäßig gibt FastAPI JSON-Responses zurück. + +Wenn Sie ein [Responsemodell](../tutorial/response-model.md) deklarieren, verwendet FastAPI Pydantic, um die Daten zu JSON zu serialisieren. + +Wenn Sie kein Responsemodell deklarieren, verwendet FastAPI den `jsonable_encoder`, wie in [JSON-kompatibler Encoder](../tutorial/encoder.md) erklärt, und packt das Ergebnis in eine `JSONResponse`. + +Wenn Sie eine `response_class` mit einem JSON-Medientyp (`application/json`) deklarieren, wie es bei `JSONResponse` der Fall ist, werden die von Ihnen zurückgegebenen Daten automatisch mit jedem Pydantic-`response_model` (das Sie im *Pfadoperation-Dekorator* deklariert haben) konvertiert (und gefiltert). Aber die Daten werden nicht mit Pydantic zu JSON-Bytes serialisiert, stattdessen werden sie mit dem `jsonable_encoder` konvertiert und anschließend an die `JSONResponse`-Klasse übergeben, die sie dann mit der Standard-JSON-Bibliothek in Python in Bytes serialisiert. + +### JSON-Leistung { #json-performance } + +Kurz gesagt: Wenn Sie die maximale Leistung möchten, verwenden Sie ein [Responsemodell](../tutorial/response-model.md) und deklarieren Sie keine `response_class` im *Pfadoperation-Dekorator*. + +{* ../../docs_src/response_model/tutorial001_01_py310.py ln[15:17] hl[16] *} + +## HTML-Response { #html-response } + +Um eine Response mit HTML direkt von **FastAPI** zurückzugeben, verwenden Sie `HTMLResponse`. + +* Importieren Sie `HTMLResponse`. +* Übergeben Sie `HTMLResponse` als den Parameter `response_class` Ihres *Pfadoperation-Dekorators*. + +{* ../../docs_src/custom_response/tutorial002_py310.py hl[2,7] *} + +/// note | Hinweis + +Der Parameter `response_class` wird auch verwendet, um den „Medientyp“ der Response zu definieren. + +In diesem Fall wird der HTTP-Header `Content-Type` auf `text/html` gesetzt. + +Und er wird als solcher in OpenAPI dokumentiert. + +/// + +### Eine `Response` zurückgeben { #return-a-response } + +Wie in [Eine Response direkt zurückgeben](response-directly.md) gezeigt, können Sie die Response auch direkt in Ihrer *Pfadoperation* überschreiben, indem Sie diese zurückgeben. + +Das gleiche Beispiel von oben, das eine `HTMLResponse` zurückgibt, könnte so aussehen: + +{* ../../docs_src/custom_response/tutorial003_py310.py hl[2,7,19] *} + +/// warning | Achtung + +Eine `Response`, die direkt von Ihrer *Pfadoperation-Funktion* zurückgegeben wird, wird in OpenAPI nicht dokumentiert (zum Beispiel wird der `Content-Type` nicht dokumentiert) und ist in der automatischen interaktiven Dokumentation nicht sichtbar. + +/// + +/// note | Hinweis + +Natürlich stammen der eigentliche `Content-Type`-Header, der Statuscode, usw., aus dem `Response`-Objekt, das Sie zurückgegeben haben. + +/// + +### In OpenAPI dokumentieren und `Response` überschreiben { #document-in-openapi-and-override-response } + +Wenn Sie die Response innerhalb der Funktion überschreiben und gleichzeitig den „Medientyp“ in OpenAPI dokumentieren möchten, können Sie den `response_class`-Parameter verwenden UND ein `Response`-Objekt zurückgeben. + +Die `response_class` wird dann nur zur Dokumentation der OpenAPI-*Pfadoperation* verwendet, Ihre `Response` wird jedoch unverändert verwendet. + +#### Eine `HTMLResponse` direkt zurückgeben { #return-an-htmlresponse-directly } + +Es könnte zum Beispiel so etwas sein: + +{* ../../docs_src/custom_response/tutorial004_py310.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. + +Indem Sie das Ergebnis des Aufrufs von `generate_html_response()` zurückgeben, geben Sie bereits eine `Response` zurück, die das Standardverhalten von **FastAPI** überschreibt. + +Aber da Sie die `HTMLResponse` auch in der `response_class` übergeben haben, weiß **FastAPI**, dass sie in OpenAPI und der interaktiven Dokumentation als HTML mit `text/html` zu dokumentieren ist: + + + +## Verfügbare Responses { #available-responses } + +Hier sind einige der verfügbaren Responses. + +Bedenken Sie, dass Sie `Response` verwenden können, um alles andere zurückzugeben, oder sogar eine benutzerdefinierte Unterklasse zu erstellen. + +/// note | Technische Details + +Sie können auch `from starlette.responses import HTMLResponse` verwenden. + +**FastAPI** bietet dieselben `starlette.responses` auch via `fastapi.responses` an, als Annehmlichkeit für Sie, den Entwickler. Die meisten verfügbaren Responses kommen aber direkt von Starlette. + +/// + +### `Response` { #response } + +Die Hauptklasse `Response`, alle anderen Responses erben von ihr. + +Sie können sie direkt zurückgeben. + +Sie akzeptiert die folgenden Parameter: + +* `content` – Ein `str` oder `bytes`. +* `status_code` – Ein `int`-HTTP-Statuscode. +* `headers` – Ein `dict` von Strings. +* `media_type` – Ein `str`, der den Medientyp angibt. Z. B. `"text/html"`. + +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_py310.py hl[1,18] *} + +### `HTMLResponse` { #htmlresponse } + +Nimmt Text oder Bytes entgegen und gibt eine HTML-Response zurück, wie Sie oben gelesen haben. + +### `PlainTextResponse` { #plaintextresponse } + +Nimmt Text oder Bytes entgegen und gibt eine Plain-Text-Response zurück. + +{* ../../docs_src/custom_response/tutorial005_py310.py hl[2,7,9] *} + +### `JSONResponse` { #jsonresponse } + +Nimmt einige Daten entgegen und gibt eine `application/json`-codierte Response zurück. + +Dies ist die Standard-Response, die in **FastAPI** verwendet wird, wie Sie oben gelesen haben. + +/// note | Technische Details + +Wenn Sie jedoch ein Responsemodell oder einen Rückgabetyp deklarieren, wird dieser direkt verwendet, um die Daten zu JSON zu serialisieren, und eine Response mit dem richtigen Medientyp für JSON wird direkt zurückgegeben, ohne die `JSONResponse`-Klasse zu verwenden. + +Dies ist der ideale Weg, um die beste Leistung zu erzielen. + +/// + +### `RedirectResponse` { #redirectresponse } + +Gibt eine HTTP-Weiterleitung (HTTP-Redirect) zurück. Verwendet standardmäßig den Statuscode 307 – Temporäre Weiterleitung (Temporary Redirect). + +Sie können eine `RedirectResponse` direkt zurückgeben: + +{* ../../docs_src/custom_response/tutorial006_py310.py hl[2,9] *} + +--- + +Oder Sie können sie im Parameter `response_class` verwenden: + + +{* ../../docs_src/custom_response/tutorial006b_py310.py hl[2,7,9] *} + +Wenn Sie das tun, können Sie die URL direkt von Ihrer *Pfadoperation*-Funktion zurückgeben. + +In diesem Fall ist der verwendete `status_code` der Standardcode für die `RedirectResponse`, also `307`. + +--- + +Sie können den Parameter `status_code` auch in Kombination mit dem Parameter `response_class` verwenden: + +{* ../../docs_src/custom_response/tutorial006c_py310.py hl[2,7,9] *} + +### `StreamingResponse` { #streamingresponse } + +Nimmt einen asynchronen Generator oder einen normalen Generator/Iterator (eine Funktion mit `yield`) und streamt den Responsebody. + +{* ../../docs_src/custom_response/tutorial007_py310.py hl[3,16] *} + +/// note | Technische Details + +Ein `async`-Task kann nur abgebrochen werden, wenn er ein `await` erreicht. Wenn es kein `await` gibt, kann der Generator (Funktion mit `yield`) nicht ordnungsgemäß abgebrochen werden und könnte weiterlaufen, selbst nachdem der Abbruch angefordert wurde. + +Da dieses kleine Beispiel keine `await`-Anweisungen benötigt, fügen wir ein `await anyio.sleep(0)` hinzu, um dem Event Loop die Chance zu geben, den Abbruch zu verarbeiten. + +Dies wäre bei großen oder unendlichen Streams noch wichtiger. + +/// + +/// tip | Tipp + +Anstatt eine `StreamingResponse` direkt zurückzugeben, sollten Sie wahrscheinlich dem Stil in [Daten streamen](./stream-data.md) folgen. Das ist wesentlich bequemer und behandelt den Abbruch im Hintergrund für Sie. + +Wenn Sie JSON Lines streamen, folgen Sie dem Tutorial [JSON Lines streamen](../tutorial/stream-json-lines.md). + +/// + +### `FileResponse` { #fileresponse } + +Streamt eine Datei asynchron als Response. + +Nimmt zur Instanziierung einen anderen Satz von Argumenten entgegen als die anderen Response-Typen: + +* `path` – Der Dateipfad zur Datei, die gestreamt werden soll. +* `headers` – Alle benutzerdefinierten Header, die inkludiert werden sollen, als Dictionary. +* `media_type` – Ein String, der den Medientyp angibt. Wenn nicht gesetzt, wird der Dateiname oder Pfad verwendet, um auf einen Medientyp zu schließen. +* `filename` – Wenn gesetzt, wird das in der `Content-Disposition` der Response eingefügt. + +Datei-Responses enthalten die entsprechenden `Content-Length`-, `Last-Modified`- und `ETag`-Header. + +{* ../../docs_src/custom_response/tutorial009_py310.py hl[2,10] *} + +Sie können auch den Parameter `response_class` verwenden: + +{* ../../docs_src/custom_response/tutorial009b_py310.py hl[2,8,10] *} + +In diesem Fall können Sie den Dateipfad direkt von Ihrer *Pfadoperation*-Funktion zurückgeben. + +## Benutzerdefinierte Response-Klasse { #custom-response-class } + +Sie können Ihre eigene benutzerdefinierte Response-Klasse erstellen, die von `Response` erbt und diese verwendet. + +Nehmen wir zum Beispiel an, dass Sie [`orjson`](https://github.com/ijl/orjson) mit einigen Einstellungen verwenden möchten. + +Sie möchten etwa, dass Ihre Response eingerücktes und formatiertes JSON zurückgibt. Dafür möchten Sie die orjson-Option `orjson.OPT_INDENT_2` verwenden. + +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_py310.py hl[9:14,17] *} + +Anstatt Folgendes zurückzugeben: + +```json +{"message": "Hello World"} +``` + +... wird diese Response Folgendes zurückgeben: + +```json +{ + "message": "Hello World" +} +``` + +Natürlich werden Sie wahrscheinlich viel bessere Möglichkeiten finden, Vorteil daraus zu ziehen, als JSON zu formatieren. 😉 + +### `orjson` oder Responsemodell { #orjson-or-response-model } + +Wenn es Ihnen um Leistung geht, sind Sie wahrscheinlich mit einem [Responsemodell](../tutorial/response-model.md) besser beraten als mit einer `orjson`-Response. + +Mit einem Responsemodell verwendet FastAPI Pydantic, um die Daten ohne Zwischenschritte zu JSON zu serialisieren, also ohne sie z. B. erst mit `jsonable_encoder` zu konvertieren, was sonst der Fall wäre. + +Und unter der Haube verwendet Pydantic dieselben Rust-Mechanismen wie `orjson`, um nach JSON zu serialisieren. Sie erhalten mit einem Responsemodell also ohnehin die beste Leistung. + +## Standard-Response-Klasse { #default-response-class } + +Beim Erstellen einer **FastAPI**-Klasseninstanz oder eines `APIRouter`s können Sie angeben, welche Response-Klasse standardmäßig verwendet werden soll. + +Der Parameter, der das definiert, ist `default_response_class`. + +Im folgenden Beispiel verwendet **FastAPI** standardmäßig `HTMLResponse` in allen *Pfadoperationen*, anstelle von JSON. + +{* ../../docs_src/custom_response/tutorial010_py310.py hl[2,4] *} + +/// tip | Tipp + +Sie können dennoch weiterhin `response_class` in *Pfadoperationen* überschreiben, wie bisher. + +/// + +## Zusätzliche Dokumentation { #additional-documentation } + +Sie können auch den Medientyp und viele andere Details in OpenAPI mit `responses` deklarieren: [Zusätzliche Responses in OpenAPI](additional-responses.md). diff --git a/docs/de/docs/advanced/dataclasses.md b/docs/de/docs/advanced/dataclasses.md new file mode 100644 index 0000000000000..bacf9d1629aec --- /dev/null +++ b/docs/de/docs/advanced/dataclasses.md @@ -0,0 +1,96 @@ +# Datenklassen verwenden { #using-dataclasses } + + +FastAPI basiert auf **Pydantic**, und ich habe Ihnen gezeigt, wie Sie Pydantic-Modelle verwenden können, um Requests und Responses zu deklarieren. + +Aber FastAPI unterstützt auf die gleiche Weise auch die Verwendung von [`dataclasses`](https://docs.python.org/3/library/dataclasses.html): + +{* ../../docs_src/dataclasses_/tutorial001_py310.py hl[1,6:11,18:19] *} + +Das ist dank **Pydantic** ebenfalls möglich, da es [„`dataclasses` intern unterstützt“](https://docs.pydantic.dev/latest/concepts/dataclasses/#use-of-stdlib-dataclasses-with-basemodel). + +Auch wenn im obigen Code Pydantic nicht explizit vorkommt, verwendet FastAPI Pydantic, um diese Standard-Datenklassen in Pydantics eigene Variante von Datenklassen zu konvertieren. + +Und natürlich wird das gleiche unterstützt: + +* Datenvalidierung +* Datenserialisierung +* Datendokumentation, usw. + +Das funktioniert genauso wie mit Pydantic-Modellen. Und tatsächlich wird es unter der Haube mittels Pydantic auf die gleiche Weise bewerkstelligt. + +/// note | Hinweis + +Bedenken Sie, dass Datenklassen nicht alles können, was Pydantic-Modelle können. + +Daher müssen Sie möglicherweise weiterhin Pydantic-Modelle verwenden. + +Wenn Sie jedoch eine Menge Datenklassen herumliegen haben, ist dies ein guter Trick, um sie für eine Web-API mithilfe von FastAPI zu verwenden. 🤓 + +/// + +## Datenklassen in `response_model` { #dataclasses-in-response-model } + +Sie können `dataclasses` auch im Parameter `response_model` verwenden: + +{* ../../docs_src/dataclasses_/tutorial002_py310.py hl[1,6:12,18] *} + +Die Datenklasse wird automatisch in eine Pydantic-Datenklasse konvertiert. + +Auf diese Weise wird deren Schema in der Benutzeroberfläche der API-Dokumentation angezeigt: + + + +## Datenklassen in verschachtelten Datenstrukturen { #dataclasses-in-nested-data-structures } + +Sie können `dataclasses` auch mit anderen Typannotationen kombinieren, um verschachtelte Datenstrukturen zu erstellen. + +In einigen Fällen müssen Sie möglicherweise immer noch Pydantics Version von `dataclasses` verwenden. Zum Beispiel, wenn Sie Fehler in der automatisch generierten API-Dokumentation haben. + +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] *} + +1. Wir importieren `field` weiterhin von Standard-`dataclasses`. + +2. `pydantic.dataclasses` ist ein direkter Ersatz für `dataclasses`. + +3. Die Datenklasse `Author` enthält eine Liste von `Item`-Datenklassen. + +4. Die Datenklasse `Author` wird im `response_model`-Parameter verwendet. + +5. Sie können andere Standard-Typannotationen mit Datenklassen als Requestbody verwenden. + + In diesem Fall handelt es sich um eine Liste von `Item`-Datenklassen. + +6. Hier geben wir ein Dictionary zurück, das `items` enthält, welches eine Liste von Datenklassen ist. + + FastAPI ist weiterhin in der Lage, die Daten nach JSON zu Serialisieren. + +7. Hier verwendet das `response_model` als Typannotation eine Liste von `Author`-Datenklassen. + + Auch hier können Sie `dataclasses` mit Standard-Typannotationen kombinieren. + +8. Beachten Sie, dass diese *Pfadoperation-Funktion* reguläres `def` anstelle von `async def` verwendet. + + Wie immer können Sie in FastAPI `def` und `async def` beliebig kombinieren. + + Wenn Sie eine Auffrischung darüber benötigen, wann welche Anwendung sinnvoll ist, lesen Sie den Abschnitt „In Eile?“ in der Dokumentation zu [`async` und `await`](../async.md#in-a-hurry). + +9. Diese *Pfadoperation-Funktion* gibt keine Datenklassen zurück (obwohl dies möglich wäre), sondern eine Liste von Dictionarys mit internen Daten. + + FastAPI verwendet den Parameter `response_model` (der Datenklassen enthält), um die Response zu konvertieren. + +Sie können `dataclasses` mit anderen Typannotationen auf vielfältige Weise kombinieren, um komplexe Datenstrukturen zu bilden. + +Weitere Einzelheiten finden Sie in den Bemerkungen im Quellcode oben. + +## Mehr erfahren { #learn-more } + +Sie können `dataclasses` auch mit anderen Pydantic-Modellen kombinieren, von ihnen erben, sie in Ihre eigenen Modelle einbinden, usw. + +Weitere Informationen finden Sie in der [Pydantic-Dokumentation zu Datenklassen](https://docs.pydantic.dev/latest/concepts/dataclasses/). + +## Version { #version } + +Dies ist verfügbar seit FastAPI-Version `0.67.0`. 🔖 diff --git a/docs/de/docs/advanced/events.md b/docs/de/docs/advanced/events.md new file mode 100644 index 0000000000000..6efe968096574 --- /dev/null +++ b/docs/de/docs/advanced/events.md @@ -0,0 +1,165 @@ +# Lifespan-Events { #lifespan-events } + +Sie können Logik (Code) definieren, die ausgeführt werden soll, bevor die Anwendung **hochfährt**. Dies bedeutet, dass dieser Code **einmal** ausgeführt wird, **bevor** die Anwendung **beginnt, Requests entgegenzunehmen**. + +Auf die gleiche Weise können Sie Logik (Code) definieren, die ausgeführt werden soll, wenn die Anwendung **heruntergefahren** wird. In diesem Fall wird dieser Code **einmal** ausgeführt, **nachdem** möglicherweise **viele Requests** bearbeitet wurden. + +Da dieser Code ausgeführt wird, bevor die Anwendung **beginnt**, Requests entgegenzunehmen, und unmittelbar, nachdem sie die Bearbeitung von Requests **abgeschlossen hat**, deckt er den gesamten Anwendungs-**Lifespan** ab (das Wort „Lifespan“ wird gleich wichtig sein 😉). + +Dies kann sehr nützlich sein, um **Ressourcen** einzurichten, die Sie in der gesamten App verwenden wollen und die von Requests **gemeinsam genutzt** werden und/oder die Sie anschließend **aufräumen** müssen. Zum Beispiel ein Pool von Datenbankverbindungen oder das Laden eines gemeinsam genutzten Modells für maschinelles Lernen. + +## Anwendungsfall { #use-case } + +Beginnen wir mit einem Beispiel-**Anwendungsfall** und schauen uns dann an, wie wir ihn mit dieser Methode implementieren können. + +Stellen wir uns vor, Sie verfügen über einige **Modelle für maschinelles Lernen**, die Sie zur Bearbeitung von Requests verwenden möchten. 🤖 + +Die gleichen Modelle werden von den Requests gemeinsam genutzt, es handelt sich also nicht um ein Modell pro Request, pro Benutzer, oder ähnliches. + +Stellen wir uns vor, dass das Laden des Modells **eine ganze Weile dauern** kann, da viele **Daten von der Festplatte** gelesen werden müssen. Sie möchten das also nicht für jeden Request tun. + +Sie könnten das auf der obersten Ebene des Moduls/der Datei machen, aber das würde auch bedeuten, dass **das Modell geladen wird**, selbst wenn Sie nur einen einfachen automatisierten Test ausführen, dann wäre dieser Test **langsam**, weil er warten müsste, bis das Modell geladen ist, bevor er einen davon unabhängigen Teil des Codes ausführen könnte. + +Das wollen wir besser machen: Laden wir das Modell, bevor die Requests bearbeitet werden, aber unmittelbar bevor die Anwendung beginnt, Requests zu empfangen, und nicht, während der Code geladen wird. + +## Lifespan { #lifespan } + +Sie können diese Logik beim *Startup* und *Shutdown* mithilfe des `lifespan`-Parameters der `FastAPI`-App und eines „Kontextmanagers“ definieren (ich zeige Ihnen gleich, was das ist). + +Beginnen wir mit einem Beispiel und sehen es uns dann im Detail an. + +Wir erstellen eine asynchrone Funktion `lifespan()` mit `yield` wie folgt: + +{* ../../docs_src/events/tutorial003_py310.py hl[16,19] *} + +Hier simulieren wir den langsamen *Startup*, das Laden des Modells, indem wir die (Fake-)Modellfunktion vor dem `yield` in das Dictionary mit Modellen für maschinelles Lernen einfügen. Dieser Code wird ausgeführt, **bevor** die Anwendung **beginnt, Requests entgegenzunehmen**, während des *Startups*. + +Und dann, direkt nach dem `yield`, entladen wir das Modell. Dieser Code wird ausgeführt, **nachdem** die Anwendung **die Bearbeitung von Requests abgeschlossen hat**, direkt vor dem *Shutdown*. Dadurch könnten beispielsweise Ressourcen wie Arbeitsspeicher oder eine GPU freigegeben werden. + +/// tip | Tipp + +Das `shutdown` würde erfolgen, wenn Sie die Anwendung **stoppen**. + +Möglicherweise müssen Sie eine neue Version starten, oder Sie haben es einfach satt, sie auszuführen. 🤷 + +/// + +### Lifespan-Funktion { #lifespan-function } + +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_py310.py hl[14:19] *} + +Der erste Teil der Funktion, vor dem `yield`, wird ausgeführt **bevor** die Anwendung startet. + +Und der Teil nach `yield` wird ausgeführt, **nachdem** die Anwendung beendet ist. + +### Asynchroner Kontextmanager { #async-context-manager } + +Wie Sie sehen, ist die Funktion mit einem `@asynccontextmanager` versehen. + +Dadurch wird die Funktion in einen sogenannten „**asynchronen Kontextmanager**“ umgewandelt. + +{* ../../docs_src/events/tutorial003_py310.py hl[1,13] *} + +Ein **Kontextmanager** in Python ist etwas, das Sie in einer `with`-Anweisung verwenden können, zum Beispiel kann `open()` als Kontextmanager verwendet werden: + +```Python +with open("file.txt") as file: + file.read() +``` + +In neueren Versionen von Python gibt es auch einen **asynchronen Kontextmanager**. Sie würden ihn mit `async with` verwenden: + +```Python +async with lifespan(app): + await do_stuff() +``` + +Wenn Sie wie oben einen Kontextmanager oder einen asynchronen Kontextmanager erstellen, führt dieser vor dem Betreten des `with`-Blocks den Code vor dem `yield` aus, und nach dem Verlassen des `with`-Blocks wird er den Code nach dem `yield` ausführen. + +In unserem obigen Codebeispiel verwenden wir ihn nicht direkt, sondern übergeben ihn an FastAPI, damit es ihn verwenden kann. + +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_py310.py hl[22] *} + +## Alternative Events (deprecatet) { #alternative-events-deprecated } + +/// warning | Achtung + +Der empfohlene Weg, den *Startup* und *Shutdown* zu handhaben, ist die Verwendung des `lifespan`-Parameters der `FastAPI`-App, wie oben beschrieben. Wenn Sie einen `lifespan`-Parameter übergeben, werden die `startup`- und `shutdown`-Eventhandler nicht mehr aufgerufen. Es ist entweder alles `lifespan` oder alles Events, nicht beides. + +Sie können diesen Teil wahrscheinlich überspringen. + +/// + +Es gibt eine alternative Möglichkeit, diese Logik zu definieren, sodass sie beim *Startup* und beim *Shutdown* ausgeführt wird. + +Sie können Eventhandler (Funktionen) definieren, die ausgeführt werden sollen, bevor die Anwendung hochgefahren wird oder wenn die Anwendung heruntergefahren wird. + +Diese Funktionen können mit `async def` oder normalem `def` deklariert werden. + +### `startup`-Event { #startup-event } + +Um eine Funktion hinzuzufügen, die vor dem Start der Anwendung ausgeführt werden soll, deklarieren Sie diese mit dem Event `"startup"`: + +{* ../../docs_src/events/tutorial001_py310.py hl[8] *} + +In diesem Fall initialisiert die Eventhandler-Funktion `startup` die „Datenbank“ der Items (nur ein `dict`) mit einigen Werten. + +Sie können mehr als eine Eventhandler-Funktion hinzufügen. + +Und Ihre Anwendung empfängt erst dann Requests, wenn alle `startup`-Eventhandler abgeschlossen sind. + +### `shutdown`-Event { #shutdown-event } + +Um eine Funktion hinzuzufügen, die beim Shutdown der Anwendung ausgeführt werden soll, deklarieren Sie sie mit dem Event `"shutdown"`: + +{* ../../docs_src/events/tutorial002_py310.py hl[6] *} + +Hier schreibt die `shutdown`-Eventhandler-Funktion eine Textzeile `"Application shutdown"` in eine Datei `log.txt`. + +/// note | Hinweis + +In der Funktion `open()` bedeutet `mode="a"` „append“ („anhängen“), sodass die Zeile nach dem, was sich in dieser Datei befindet, hinzugefügt wird, ohne den vorherigen Inhalt zu überschreiben. + +/// + +/// tip | Tipp + +Beachten Sie, dass wir in diesem Fall eine Standard-Python-Funktion `open()` verwenden, die mit einer Datei interagiert. + +Es handelt sich also um I/O (Input/Output), welches „Warten“ erfordert, bis Dinge auf die Festplatte geschrieben werden. + +Aber `open()` verwendet nicht `async` und `await`. + +Daher deklarieren wir die Eventhandler-Funktion mit Standard-`def` statt mit `async def`. + +/// + +### `startup` und `shutdown` zusammen { #startup-and-shutdown-together } + +Es besteht eine hohe Wahrscheinlichkeit, dass die Logik für Ihr *Startup* und *Shutdown* miteinander verknüpft ist. Vielleicht möchten Sie etwas beginnen und es dann beenden, eine Ressource laden und sie dann freigeben usw. + +Bei getrennten Funktionen, die keine gemeinsame Logik oder Variablen haben, ist dies schwieriger, da Sie Werte in globalen Variablen speichern oder ähnliche Tricks verwenden müssen. + +Aus diesem Grund wird jetzt empfohlen, stattdessen `lifespan` wie oben erläutert zu verwenden. + +## Technische Details { #technical-details } + +Nur ein technisches Detail für die neugierigen Nerds. 🤓 + +In der technischen ASGI-Spezifikation ist dies Teil des [Lifespan-Protokolls](https://asgi.readthedocs.io/en/latest/specs/lifespan.html) und definiert Events namens `startup` und `shutdown`. + +/// note | Hinweis + +Weitere Informationen zu Starlettes `lifespan`-Handlern finden Sie in [Starlettes Lifespan-Dokumentation](https://www.starlette.dev/lifespan/). + +Einschließlich, wie man Lifespan-Zustand handhabt, der in anderen Bereichen Ihres Codes verwendet werden kann. + +/// + +## Unteranwendungen { #sub-applications } + +🚨 Beachten Sie, dass diese Lifespan-Events (Startup und Shutdown) nur für die Hauptanwendung ausgeführt werden, nicht für [Unteranwendungen – Mounts](sub-applications.md). diff --git a/docs/de/docs/advanced/generate-clients.md b/docs/de/docs/advanced/generate-clients.md new file mode 100644 index 0000000000000..d93641bd3bece --- /dev/null +++ b/docs/de/docs/advanced/generate-clients.md @@ -0,0 +1,192 @@ +# SDKs generieren { #generating-sdks } + +Da **FastAPI** auf der **OpenAPI**-Spezifikation basiert, können dessen APIs in einem standardisierten Format beschrieben werden, das viele Tools verstehen. + +Dies vereinfacht es, aktuelle **Dokumentation** und Client-Bibliotheken (**SDKs**) in verschiedenen Sprachen zu generieren sowie **Test-** oder **Automatisierungs-Workflows**, die mit Ihrem Code synchron bleiben. + +In diesem Leitfaden erfahren Sie, wie Sie ein **TypeScript-SDK** für Ihr FastAPI-Backend generieren. + +## Open Source SDK-Generatoren { #open-source-sdk-generators } + +Eine vielseitige Möglichkeit ist der [OpenAPI Generator](https://openapi-generator.tech/), der **viele Programmiersprachen** unterstützt und SDKs aus Ihrer OpenAPI-Spezifikation generieren kann. + +Für **TypeScript-Clients** ist [Hey API](https://heyapi.dev/) eine speziell entwickelte Lösung, die ein optimiertes Erlebnis für das TypeScript-Ökosystem bietet. + +Weitere SDK-Generatoren finden Sie auf [OpenAPI.Tools](https://openapi.tools/#sdk). + +/// tip | Tipp + +FastAPI generiert automatisch **OpenAPI 3.1**-Spezifikationen, daher muss jedes von Ihnen verwendete Tool diese Version unterstützen. + +/// + +## Ein TypeScript-SDK erstellen { #create-a-typescript-sdk } + +Beginnen wir mit einer einfachen FastAPI-Anwendung: + +{* ../../docs_src/generate_clients/tutorial001_py310.py hl[7:9,12:13,16:17,21] *} + +Beachten Sie, dass die *Pfadoperationen* die Modelle definieren, die sie für die Request- und Response-Payload verwenden, indem sie die Modelle `Item` und `ResponseMessage` verwenden. + +### API-Dokumentation { #api-docs } + +Wenn Sie zu `/docs` gehen, sehen Sie, dass es die **Schemas** für die Daten enthält, die in Requests gesendet und in Responses empfangen werden: + + + +Sie können diese Schemas sehen, da sie mit den Modellen in der App deklariert wurden. + +Diese Informationen sind im **OpenAPI-Schema** der Anwendung verfügbar und werden in der API-Dokumentation angezeigt. + +Diese Informationen aus den Modellen, die in OpenAPI enthalten sind, können verwendet werden, um **den Client-Code zu generieren**. + +### Hey API { #hey-api } + +Sobald wir eine FastAPI-App mit den Modellen haben, können wir Hey API verwenden, um einen TypeScript-Client zu generieren. Der schnellste Weg das zu tun, ist über npx. + +```sh +npx @hey-api/openapi-ts -i http://localhost:8000/openapi.json -o src/client +``` + +Dies generiert ein TypeScript-SDK in `./src/client`. + +Sie können lernen, wie man [`@hey-api/openapi-ts` installiert](https://heyapi.dev/openapi-ts/get-started) und über die [erzeugte Ausgabe](https://heyapi.dev/openapi-ts/output) auf deren Website lesen. + +### Das SDK verwenden { #using-the-sdk } + +Jetzt können Sie den Client-Code importieren und verwenden. Er könnte wie folgt aussehen, beachten Sie, dass Sie eine automatische Vervollständigung für die Methoden erhalten: + + + +Sie werden auch eine automatische Vervollständigung für die zu sendende Payload erhalten: + + + +/// tip | Tipp + +Beachten Sie die automatische Vervollständigung für `name` und `price`, die in der FastAPI-Anwendung im `Item`-Modell definiert wurden. + +/// + +Sie erhalten Inline-Fehlerberichte für die von Ihnen gesendeten Daten: + + + +Das Response-Objekt hat auch automatische Vervollständigung: + + + +## FastAPI-Anwendung mit Tags { #fastapi-app-with-tags } + +In vielen Fällen wird Ihre FastAPI-App größer sein und Sie werden wahrscheinlich Tags verwenden, um verschiedene Gruppen von *Pfadoperationen* zu separieren. + +Zum Beispiel könnten Sie einen Abschnitt für **Items** und einen weiteren Abschnitt für **Users** haben, und diese könnten durch Tags getrennt sein: + +{* ../../docs_src/generate_clients/tutorial002_py310.py hl[21,26,34] *} + +### Einen TypeScript-Client mit Tags generieren { #generate-a-typescript-client-with-tags } + +Wenn Sie einen Client für eine FastAPI-App generieren, die Tags verwendet, wird normalerweise der Client-Code auch anhand der Tags getrennt. + +Auf diese Weise können Sie die Dinge für den Client-Code richtig ordnen und gruppieren: + + + +In diesem Fall haben Sie: + +* `ItemsService` +* `UsersService` + +### Client-Methodennamen { #client-method-names } + +Im Moment sehen die generierten Methodennamen wie `createItemItemsPost` nicht sehr sauber aus: + +```TypeScript +ItemsService.createItemItemsPost({name: "Plumbus", price: 5}) +``` + +... das liegt daran, dass der Client-Generator für jede *Pfadoperation* die OpenAPI-interne **Operation-ID** verwendet. + +OpenAPI erfordert, dass jede Operation-ID innerhalb aller *Pfadoperationen* einzigartig ist. Daher verwendet FastAPI den **Funktionsnamen**, den **Pfad** und die **HTTP-Methode/-Operation**, um diese Operation-ID zu generieren. Denn so kann sichergestellt werden, dass die Operation-IDs einzigartig sind. + +Aber ich zeige Ihnen als Nächstes, wie Sie das verbessern können. 🤓 + +## Benutzerdefinierte Operation-IDs und bessere Methodennamen { #custom-operation-ids-and-better-method-names } + +Sie können die Art und Weise, wie diese Operation-IDs **generiert** werden, **ändern**, um sie einfacher zu machen und **einfachere Methodennamen** in den Clients zu haben. + +In diesem Fall müssen Sie auf andere Weise sicherstellen, dass jede Operation-ID **einzigartig** ist. + +Zum Beispiel könnten Sie sicherstellen, dass jede *Pfadoperation* einen Tag hat, und dann die Operation-ID basierend auf dem **Tag** und dem *Pfadoperation*-**Namen** (dem Funktionsnamen) generieren. + +### Eine benutzerdefinierte Funktion zur Erzeugung einer eindeutigen ID erstellen { #custom-generate-unique-id-function } + +FastAPI verwendet eine **eindeutige ID** für jede *Pfadoperation*, die für die **Operation-ID** und auch für die Namen aller benötigten benutzerdefinierten Modelle für Requests oder Responses verwendet wird. + +Sie können diese Funktion anpassen. Sie nimmt ein `APIRoute` und gibt einen String zurück. + +Hier verwendet sie beispielsweise den ersten Tag (Sie werden wahrscheinlich nur einen Tag haben) und den *Pfadoperation*-Namen (den Funktionsnamen). + +Anschließend können Sie diese benutzerdefinierte Funktion als `generate_unique_id_function`-Parameter an **FastAPI** übergeben: + +{* ../../docs_src/generate_clients/tutorial003_py310.py hl[6:7,10] *} + +### Einen TypeScript-Client mit benutzerdefinierten Operation-IDs generieren { #generate-a-typescript-client-with-custom-operation-ids } + +Wenn Sie nun den Client erneut generieren, werden Sie feststellen, dass er über die verbesserten Methodennamen verfügt: + + + +Wie Sie sehen, haben die Methodennamen jetzt den Tag und dann den Funktionsnamen, aber keine Informationen aus dem URL-Pfad und der HTTP-Operation. + +### Die OpenAPI-Spezifikation für den Client-Generator vorab modifizieren { #preprocess-the-openapi-specification-for-the-client-generator } + +Der generierte Code enthält immer noch einige **verdoppelte Informationen**. + +Wir wissen bereits, dass diese Methode mit den **Items** zusammenhängt, weil dieses Wort in `ItemsService` enthalten ist (vom Tag übernommen), aber wir haben den Tag-Namen dennoch im Methodennamen vorangestellt. 😕 + +Wir werden das wahrscheinlich weiterhin für OpenAPI allgemein beibehalten wollen, da dadurch sichergestellt wird, dass die Operation-IDs **einzigartig** sind. + +Aber für den generierten Client könnten wir die OpenAPI-Operation-IDs direkt vor der Generierung der Clients **modifizieren**, um diese Methodennamen schöner und **sauberer** zu machen. + +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_py310.py *} + +//// tab | Node.js + +```Javascript +{!> ../../docs_src/generate_clients/tutorial004.js!} +``` + +//// + +Damit würden die Operation-IDs von Dingen wie `items-get_items` in `get_items` umbenannt, sodass der Client-Generator einfachere Methodennamen generieren kann. + +### Einen TypeScript-Client mit der vorverarbeiteten OpenAPI generieren { #generate-a-typescript-client-with-the-preprocessed-openapi } + +Da das Endergebnis nun in einer `openapi.json`-Datei vorliegt, müssen Sie Ihren Eingabeort aktualisieren: + +```sh +npx @hey-api/openapi-ts -i ./openapi.json -o src/client +``` + +Nach der Generierung des neuen Clients haben Sie jetzt **saubere Methodennamen**, mit allen **Autovervollständigungen**, **Inline-Fehlerberichten**, usw.: + + + +## Vorteile { #benefits } + +Wenn Sie die automatisch generierten Clients verwenden, erhalten Sie **Autovervollständigung** für: + +* Methoden. +* Request-Payloads im Body, Query-Parameter, usw. +* Response-Payloads. + +Sie erhalten auch **Inline-Fehlerberichte** für alles. + +Und wann immer Sie den Backend-Code aktualisieren und **das Frontend neu generieren**, stehen alle neuen *Pfadoperationen* als Methoden zur Verfügung, die alten werden entfernt und alle anderen Änderungen werden im generierten Code reflektiert. 🤓 + +Das bedeutet auch, dass, wenn sich etwas ändert, dies automatisch im Client-Code **reflektiert** wird. Und wenn Sie den Client **erstellen**, wird eine Fehlermeldung ausgegeben, wenn die verwendeten Daten **nicht übereinstimmen**. + +Sie würden also **viele Fehler sehr früh** im Entwicklungszyklus erkennen, anstatt darauf warten zu müssen, dass die Fehler Ihren Endbenutzern in der Produktion angezeigt werden, und dann zu versuchen, zu debuggen, wo das Problem liegt. ✨ diff --git a/docs/de/docs/advanced/index.md b/docs/de/docs/advanced/index.md new file mode 100644 index 0000000000000..3886e963a616d --- /dev/null +++ b/docs/de/docs/advanced/index.md @@ -0,0 +1,21 @@ +# Handbuch für fortgeschrittene Benutzer { #advanced-user-guide } + +## Zusatzfunktionen { #additional-features } + +Das Haupt-[Tutorial – Benutzerhandbuch](../tutorial/index.md) sollte ausreichen, um Ihnen einen Überblick über alle Hauptfunktionen von **FastAPI** zu geben. + +In den nächsten Abschnitten sehen Sie weitere Optionen, Konfigurationen und zusätzliche Funktionen. + +/// tip | Tipp + +Die nächsten Abschnitte sind **nicht unbedingt „fortgeschritten“**. + +Und es ist möglich, dass für Ihren Anwendungsfall die Lösung in einem davon liegt. + +/// + +## Das Tutorial zuerst lesen { #read-the-tutorial-first } + +Sie können immer noch die meisten Funktionen in **FastAPI** mit den Kenntnissen aus dem Haupt-[Tutorial – Benutzerhandbuch](../tutorial/index.md) nutzen. + +Und die nächsten Abschnitte setzen voraus, dass Sie es bereits gelesen haben und dass Sie diese Hauptideen kennen. diff --git a/docs/de/docs/advanced/json-base64-bytes.md b/docs/de/docs/advanced/json-base64-bytes.md new file mode 100644 index 0000000000000..618bbd1a9e16c --- /dev/null +++ b/docs/de/docs/advanced/json-base64-bytes.md @@ -0,0 +1,63 @@ +# JSON mit Bytes als base64 { #json-with-bytes-as-base64 } + +Wenn Ihre App JSON-Daten empfangen und senden muss, Sie darin aber Binärdaten einschließen müssen, können Sie diese als base64 kodieren. + +## Base64 vs Dateien { #base64-vs-files } + +Prüfen Sie zunächst, ob Sie [Requestdateien](../tutorial/request-files.md) zum Hochladen von Binärdaten und [Benutzerdefinierte Response – FileResponse](./custom-response.md#fileresponse) zum Senden von Binärdaten verwenden können, anstatt sie in JSON zu kodieren. + +JSON kann nur UTF-8-kodierte Strings enthalten, es kann daher keine rohen Bytes enthalten. + +Base64 kann Binärdaten in Strings kodieren, dafür werden jedoch mehr Zeichen benötigt als in den ursprünglichen Binärdaten; es ist daher in der Regel weniger effizient als der Umgang mit normalen Dateien. + +Verwenden Sie base64 nur, wenn Sie Binärdaten unbedingt in JSON einbetten müssen und dafür keine Dateien verwenden können. + +## Pydantic `bytes` { #pydantic-bytes } + +Sie können ein Pydantic-Modell mit `bytes`-Feldern deklarieren und dann in der Modellkonfiguration `val_json_bytes` verwenden, um anzugeben, dass zur *Validierung* von eingehenden JSON-Daten base64 genutzt werden soll; im Rahmen dieser Validierung wird der base64-String in Bytes dekodiert. + +{* ../../docs_src/json_base64_bytes/tutorial001_py310.py ln[1:9,29:35] hl[9] *} + +Wenn Sie die `/docs` aufrufen, zeigt die Dokumentation, dass das Feld `data` base64-kodierte Bytes erwartet: + +
+ +
+ +Sie könnten einen Request wie folgt senden: + +```json +{ + "description": "Some data", + "data": "aGVsbG8=" +} +``` + +/// tip | Tipp + +`aGVsbG8=` ist die base64-Kodierung von `hello`. + +/// + +Anschließend dekodiert Pydantic den base64-String und stellt Ihnen die ursprünglichen Bytes im Feld `data` des Modells bereit. + +Sie erhalten eine Response wie: + +```json +{ + "description": "Some data", + "content": "hello" +} +``` + +## Pydantic `bytes` für Ausgabedaten { #pydantic-bytes-for-output-data } + +Sie können in der Modellkonfiguration für Ausgabedaten auch `bytes`-Felder mit `ser_json_bytes` verwenden; Pydantic wird die Bytes bei der Erzeugung der JSON-Response als base64 *serialisieren*. + +{* ../../docs_src/json_base64_bytes/tutorial001_py310.py ln[1:2,12:16,29,38:41] hl[16] *} + +## Pydantic `bytes` für Eingabe- und Ausgabedaten { #pydantic-bytes-for-input-and-output-data } + +Und selbstverständlich können Sie dasselbe Modell so konfigurieren, dass base64 sowohl für Eingaben (*validieren*) mit `val_json_bytes` als auch für Ausgaben (*serialisieren*) mit `ser_json_bytes` verwendet wird, wenn JSON-Daten empfangen und gesendet werden. + +{* ../../docs_src/json_base64_bytes/tutorial001_py310.py ln[1:2,19:26,29,44:46] hl[23:26] *} diff --git a/docs/de/docs/advanced/middleware.md b/docs/de/docs/advanced/middleware.md new file mode 100644 index 0000000000000..90a4e4ff28ce4 --- /dev/null +++ b/docs/de/docs/advanced/middleware.md @@ -0,0 +1,97 @@ +# Fortgeschrittene Middleware { #advanced-middleware } + +Im Haupttutorial haben Sie gelesen, wie Sie Ihrer Anwendung [benutzerdefinierte Middleware](../tutorial/middleware.md) hinzufügen können. + +Und dann auch, wie man [CORS mittels der `CORSMiddleware`](../tutorial/cors.md) handhabt. + +In diesem Abschnitt werden wir sehen, wie man andere Middlewares verwendet. + +## ASGI-Middleware hinzufügen { #adding-asgi-middlewares } + +Da **FastAPI** auf Starlette basiert und die ASGI-Spezifikation implementiert, können Sie jede ASGI-Middleware verwenden. + +Eine Middleware muss nicht speziell für FastAPI oder Starlette gemacht sein, um zu funktionieren, solange sie der ASGI-Spezifikation genügt. + +Im Allgemeinen handelt es sich bei ASGI-Middleware um Klassen, die als erstes Argument eine ASGI-Anwendung erwarten. + +In der Dokumentation für ASGI-Middlewares von Drittanbietern wird Ihnen wahrscheinlich gesagt, dass Sie etwa Folgendes tun sollen: + +```Python +from unicorn import UnicornMiddleware + +app = SomeASGIApp() + +new_app = UnicornMiddleware(app, some_config="rainbow") +``` + +Aber FastAPI (eigentlich Starlette) bietet eine einfachere Möglichkeit, welche sicherstellt, dass die internen Middlewares zur Behandlung von Serverfehlern und benutzerdefinierten Exceptionhandlern ordnungsgemäß funktionieren. + +Dazu verwenden Sie `app.add_middleware()` (wie schon im Beispiel für CORS gesehen). + +```Python +from fastapi import FastAPI +from unicorn import UnicornMiddleware + +app = FastAPI() + +app.add_middleware(UnicornMiddleware, some_config="rainbow") +``` + +`app.add_middleware()` empfängt eine Middleware-Klasse als erstes Argument und dann alle weiteren Argumente, die an die Middleware übergeben werden sollen. + +## Integrierte Middleware { #integrated-middlewares } + +**FastAPI** enthält mehrere Middlewares für gängige Anwendungsfälle. Wir werden als Nächstes sehen, wie man sie verwendet. + +/// note | Technische Details + +Für die nächsten Beispiele könnten Sie auch `from starlette.middleware.something import SomethingMiddleware` verwenden. + +**FastAPI** bietet mehrere Middlewares via `fastapi.middleware` an, als Annehmlichkeit für Sie, den Entwickler. Die meisten verfügbaren Middlewares kommen aber direkt von Starlette. + +/// + +## `HTTPSRedirectMiddleware` { #httpsredirectmiddleware } + +Erzwingt, dass alle eingehenden Requests entweder `https` oder `wss` sein müssen. + +Alle eingehenden Requests an `http` oder `ws` werden stattdessen an das sichere Schema umgeleitet. + +{* ../../docs_src/advanced_middleware/tutorial001_py310.py hl[2,6] *} + +## `TrustedHostMiddleware` { #trustedhostmiddleware } + +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_py310.py hl[2,6:8] *} + +Die folgenden Argumente werden unterstützt: + +* `allowed_hosts` – Eine Liste von Domain-Namen, die als Hostnamen zulässig sein sollten. Wildcard-Domains wie `*.example.com` werden unterstützt, um Subdomains zu matchen. Um jeden Hostnamen zu erlauben, verwenden Sie entweder `allowed_hosts=["*"]` oder lassen Sie diese Middleware weg. +* `www_redirect` – Wenn auf True gesetzt, werden Requests an Nicht-www-Versionen der erlaubten Hosts zu deren www-Gegenstücken umgeleitet. Der Defaultwert ist `True`. + +Wenn ein eingehender Request nicht korrekt validiert wird, wird eine `400`-Response gesendet. + +## `GZipMiddleware` { #gzipmiddleware } + +Verarbeitet GZip-Responses für alle Requests, die „gzip“ im `Accept-Encoding`-Header enthalten. + +Diese Middleware verarbeitet sowohl Standard- als auch Streaming-Responses. + +{* ../../docs_src/advanced_middleware/tutorial003_py310.py hl[2,6] *} + +Die folgenden Argumente werden unterstützt: + +* `minimum_size` – Responses, die kleiner als diese Mindestgröße in Bytes sind, nicht per GZip komprimieren. Der Defaultwert ist `500`. +* `compresslevel` – Wird während der GZip-Kompression verwendet. Es ist ein Ganzzahlwert zwischen 1 und 9. Der Defaultwert ist `9`. Ein niedrigerer Wert resultiert in schnellerer Kompression, aber größeren Dateigrößen, während ein höherer Wert langsamere Kompression, aber kleinere Dateigrößen zur Folge hat. + +## Andere Middlewares { #other-middlewares } + +Es gibt viele andere ASGI-Middlewares. + +Zum Beispiel: + +* [Uvicorns `ProxyHeadersMiddleware`](https://github.com/encode/uvicorn/blob/master/uvicorn/middleware/proxy_headers.py) +* [MessagePack](https://github.com/florimondmanca/msgpack-asgi) + +Um mehr über weitere verfügbare Middlewares herauszufinden, besuchen Sie [Starlettes Middleware-Dokumentation](https://www.starlette.dev/middleware/) und die [ASGI Awesome List](https://github.com/florimondmanca/awesome-asgi). diff --git a/docs/de/docs/advanced/openapi-callbacks.md b/docs/de/docs/advanced/openapi-callbacks.md new file mode 100644 index 0000000000000..b5d49c7e8edee --- /dev/null +++ b/docs/de/docs/advanced/openapi-callbacks.md @@ -0,0 +1,186 @@ +# OpenAPI-Callbacks { #openapi-callbacks } + +Sie könnten eine API mit einer *Pfadoperation* erstellen, die einen Request an eine *externe API* auslösen könnte, welche von jemand anderem erstellt wurde (wahrscheinlich derselbe Entwickler, der Ihre API *verwenden* würde). + +Der Vorgang, der stattfindet, wenn Ihre API-Anwendung die *externe API* aufruft, wird als „Callback“ bezeichnet. Denn die Software, die der externe Entwickler geschrieben hat, sendet einen Request an Ihre API und dann *ruft Ihre API zurück* (*calls back*) und sendet einen Request an eine *externe API* (die wahrscheinlich vom selben Entwickler erstellt wurde). + +In diesem Fall möchten Sie möglicherweise dokumentieren, wie diese externe API aussehen *sollte*. Welche *Pfadoperation* sie haben sollte, welchen Body sie erwarten sollte, welche Response sie zurückgeben sollte, usw. + +## Eine Anwendung mit Callbacks { #an-app-with-callbacks } + +Sehen wir uns das alles anhand eines Beispiels an. + +Stellen Sie sich vor, Sie entwickeln eine Anwendung, mit der Sie Rechnungen erstellen können. + +Diese Rechnungen haben eine `id`, einen `title` (optional), einen `customer` und ein `total`. + +Der Benutzer Ihrer API (ein externer Entwickler) erstellt mit einem POST-Request eine Rechnung in Ihrer API. + +Dann wird Ihre API (stellen wir uns vor): + +* die Rechnung an einen Kunden des externen Entwicklers senden. +* das Geld einsammeln. +* eine Benachrichtigung an den API-Benutzer (den externen Entwickler) zurücksenden. + * Dies erfolgt durch Senden eines POST-Requests (von *Ihrer API*) an eine *externe API*, die von diesem externen Entwickler bereitgestellt wird (das ist der „Callback“). + +## Die normale **FastAPI**-Anwendung { #the-normal-fastapi-app } + +Sehen wir uns zunächst an, wie die normale API-Anwendung aussehen würde, bevor wir den Callback hinzufügen. + +Sie verfügt über eine *Pfadoperation*, die einen `Invoice`-Body empfängt, und einen Query-Parameter `callback_url`, der die URL für den Callback enthält. + +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] *} + +/// tip | Tipp + +Der Query-Parameter `callback_url` verwendet einen Pydantic-[Url](https://docs.pydantic.dev/latest/api/networks/)-Typ. + +/// + +Das einzig Neue ist `callbacks=invoices_callback_router.routes` als Argument für den *Pfadoperation-Dekorator*. Wir werden als Nächstes sehen, was das ist. + +## Dokumentation des Callbacks { #documenting-the-callback } + +Der tatsächliche Callback-Code hängt stark von Ihrer eigenen API-Anwendung ab. + +Und er wird wahrscheinlich von Anwendung zu Anwendung sehr unterschiedlich sein. + +Es könnten nur eine oder zwei Codezeilen sein, wie zum Beispiel: + +```Python +callback_url = "https://example.com/api/v1/invoices/events/" +httpx.post(callback_url, json={"description": "Invoice paid", "paid": True}) +``` + +Der möglicherweise wichtigste Teil des Callbacks besteht jedoch darin, sicherzustellen, dass Ihr API-Benutzer (der externe Entwickler) die *externe API* korrekt implementiert, gemäß den Daten, die *Ihre API* im Requestbody des Callbacks senden wird, usw. + +Als Nächstes fügen wir den Code hinzu, um zu dokumentieren, wie diese *externe API* aussehen sollte, um den Callback von *Ihrer API* zu empfangen. + +Diese Dokumentation wird in der Swagger-Oberfläche unter `/docs` in Ihrer API angezeigt und zeigt externen Entwicklern, wie diese die *externe API* erstellen sollten. + +In diesem Beispiel wird nicht der Callback selbst implementiert (das könnte nur eine Codezeile sein), sondern nur der Dokumentationsteil. + +/// tip | Tipp + +Der eigentliche Callback ist nur ein HTTP-Request. + +Wenn Sie den Callback selbst implementieren, können Sie beispielsweise [HTTPX](https://www.python-httpx.org) oder [Requests](https://requests.readthedocs.io/) verwenden. + +/// + +## Schreiben des Codes, der den Callback dokumentiert { #write-the-callback-documentation-code } + +Dieser Code wird nicht in Ihrer Anwendung ausgeführt, wir benötigen ihn nur, um zu *dokumentieren*, wie diese *externe API* aussehen soll. + +Sie wissen jedoch bereits, wie Sie mit **FastAPI** ganz einfach eine automatische Dokumentation für eine API erstellen. + +Daher werden wir dasselbe Wissen nutzen, um zu dokumentieren, wie die *externe API* aussehen sollte ... indem wir die *Pfadoperation(en)* erstellen, welche die externe API implementieren soll (die, welche Ihre API aufruft). + +/// tip | Tipp + +Wenn Sie den Code zum Dokumentieren eines Callbacks schreiben, kann es hilfreich sein, sich vorzustellen, dass Sie dieser *externe Entwickler* sind. Und dass Sie derzeit die *externe API* implementieren, nicht *Ihre API*. + +Wenn Sie diese Sichtweise (des *externen Entwicklers*) vorübergehend übernehmen, wird es offensichtlicher, wo die Parameter, das Pydantic-Modell für den Body, die Response, usw. für diese *externe API* hingehören. + +/// + +### Einen Callback-`APIRouter` erstellen { #create-a-callback-apirouter } + +Erstellen Sie zunächst einen neuen `APIRouter`, der einen oder mehrere Callbacks enthält. + +{* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[1,23] *} + +### Die Callback-*Pfadoperation* erstellen { #create-the-callback-path-operation } + +Um die Callback-*Pfadoperation* zu erstellen, verwenden Sie denselben `APIRouter`, den Sie oben erstellt haben. + +Sie sollte wie eine normale FastAPI-*Pfadoperation* aussehen: + +* 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`. + +{* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[14:16,19:20,26:30] *} + +Es gibt zwei Hauptunterschiede zu einer normalen *Pfadoperation*: + +* Es muss kein tatsächlicher Code vorhanden sein, da Ihre Anwendung diesen Code niemals aufruft. Sie wird nur zur Dokumentation der *externen API* verwendet. Die Funktion könnte also einfach `pass` enthalten. +* Der *Pfad* kann einen [OpenAPI-3-Ausdruck](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#key-expression) enthalten (mehr dazu weiter unten), wo er Variablen mit Parametern und Teilen des ursprünglichen Requests verwenden kann, der an *Ihre API* gesendet wurde. + +### Der Callback-Pfadausdruck { #the-callback-path-expression } + +Der Callback-*Pfad* kann einen [OpenAPI-3-Ausdruck](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#key-expression) enthalten, welcher Teile des ursprünglichen Requests enthalten kann, der an *Ihre API* gesendet wurde. + +In diesem Fall ist es der `str`: + +```Python +"{$callback_url}/invoices/{$request.body.id}" +``` + +Wenn Ihr API-Benutzer (der externe Entwickler) also einen Request an *Ihre API* sendet, an: + +``` +https://yourapi.com/invoices/?callback_url=https://www.external.org/events +``` + +mit einem JSON-Body: + +```JSON +{ + "id": "2expen51ve", + "customer": "Mr. Richie Rich", + "total": "9999" +} +``` + +dann verarbeitet *Ihre API* die Rechnung und sendet irgendwann später einen Callback-Request an die `callback_url` (die *externe API*): + +``` +https://www.external.org/events/invoices/2expen51ve +``` + +mit einem JSON-Body, der etwa Folgendes enthält: + +```JSON +{ + "description": "Payment celebration", + "paid": true +} +``` + +und sie würde eine Response von dieser *externen API* mit einem JSON-Body wie dem folgenden erwarten: + +```JSON +{ + "ok": true +} +``` + +/// tip | Tipp + +Beachten Sie, dass die verwendete Callback-URL die URL enthält, die als Query-Parameter in `callback_url` (`https://www.external.org/events`) empfangen wurde, und auch die Rechnungs-`id` aus dem JSON-Body (`2expen51ve`). + +/// + +### Den Callback-Router hinzufügen { #add-the-callback-router } + +An diesem Punkt haben Sie die benötigte(n) *Callback-Pfadoperation(en)* (diejenige(n), die der *externe Entwickler* in der *externen API* implementieren sollte) im Callback-Router, den Sie oben erstellt haben. + +Verwenden Sie nun den Parameter `callbacks` im *Pfadoperation-Dekorator Ihrer API*, um das Attribut `.routes` dieses Callback-Routers zu übergeben: + +{* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[33] *} + +/// tip | Tipp + +Beachten Sie, dass Sie nicht den Router selbst (`invoices_callback_router`) an `callbacks=` übergeben, sondern dessen `.routes`, wie in `invoices_callback_router.routes`. FastAPI wird diese Routen verwenden, um die Callback-OpenAPI-Dokumentation zu generieren. + +/// + +### Es in der Dokumentation testen { #check-the-docs } + +Jetzt können Sie Ihre Anwendung starten und auf [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs) gehen. + +Sie sehen Ihre Dokumentation, einschließlich eines Abschnitts „Callbacks“ für Ihre *Pfadoperation*, der zeigt, wie die *externe API* aussehen sollte: + + diff --git a/docs/de/docs/advanced/openapi-webhooks.md b/docs/de/docs/advanced/openapi-webhooks.md new file mode 100644 index 0000000000000..fbec6996a5aee --- /dev/null +++ b/docs/de/docs/advanced/openapi-webhooks.md @@ -0,0 +1,55 @@ +# OpenAPI Webhooks { #openapi-webhooks } + +Es gibt Fälle, in denen Sie Ihren API-**Benutzern** mitteilen möchten, dass Ihre App *deren* App mit einigen Daten aufrufen (einen Request senden) könnte, normalerweise um über ein bestimmtes **Event** zu **benachrichtigen**. + +Das bedeutet, dass anstelle des normalen Prozesses, bei dem Ihre Benutzer Requests an Ihre API senden, **Ihre API** (oder Ihre App) **Requests an deren System** (an deren API, deren App) senden könnte. + +Das wird normalerweise als **Webhook** bezeichnet. + +## Webhooks-Schritte { #webhooks-steps } + +Der Prozess besteht normalerweise darin, dass **Sie in Ihrem Code definieren**, welche Nachricht Sie senden möchten, den **Requestbody**. + +Sie definieren auch auf irgendeine Weise, in welchen **Momenten** Ihre App diese Requests oder Events senden wird. + +Und **Ihre Benutzer** definieren auf irgendeine Weise (zum Beispiel irgendwo in einem Web-Dashboard) die **URL**, an die Ihre App diese Requests senden soll. + +Die gesamte **Logik** zur Registrierung der URLs für Webhooks und der Code zum tatsächlichen Senden dieser Requests liegt bei Ihnen. Sie schreiben es so, wie Sie möchten, in **Ihrem eigenen Code**. + +## Webhooks mit **FastAPI** und OpenAPI dokumentieren { #documenting-webhooks-with-fastapi-and-openapi } + +Mit **FastAPI**, mithilfe von OpenAPI, können Sie die Namen dieser Webhooks, die Arten von HTTP-Operationen, die Ihre App senden kann (z. B. `POST`, `PUT`, usw.) und die **Requestbodys** definieren, die Ihre App senden würde. + +Dies kann es Ihren Benutzern viel einfacher machen, **deren APIs zu implementieren**, um Ihre **Webhook**-Requests zu empfangen. Möglicherweise können diese sogar einen Teil ihres eigenen API-Codes automatisch generieren. + +/// note | Hinweis + +Webhooks sind in OpenAPI 3.1.0 und höher verfügbar und werden von FastAPI `0.99.0` und höher unterstützt. + +/// + +## Eine App mit Webhooks { #an-app-with-webhooks } + +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_py310.py hl[9:12,15:20] *} + +Die von Ihnen definierten Webhooks landen im **OpenAPI**-Schema und der automatischen **Dokumentations-Oberfläche**. + +/// note | Hinweis + +Das `app.webhooks`-Objekt ist eigentlich nur ein `APIRouter`, derselbe Typ, den Sie verwenden würden, wenn Sie Ihre App mit mehreren Dateien strukturieren. + +/// + +Beachten Sie, dass Sie bei Webhooks tatsächlich keinen *Pfad* (wie `/items/`) deklarieren, der Text, den Sie dort übergeben, ist lediglich eine **Kennzeichnung** des Webhooks (der Name des Events). Zum Beispiel ist in `@app.webhooks.post("new-subscription")` der Webhook-Name `new-subscription`. + +Das liegt daran, dass erwartet wird, dass **Ihre Benutzer** den tatsächlichen **URL-Pfad**, an dem sie den Webhook-Request empfangen möchten, auf andere Weise definieren (z. B. über ein Web-Dashboard). + +### Die Dokumentation testen { #check-the-docs } + +Jetzt können Sie Ihre App starten und auf [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs) gehen. + +Sie werden sehen, dass Ihre Dokumentation die normalen *Pfadoperationen* und jetzt auch einige **Webhooks** enthält: + + diff --git a/docs/de/docs/advanced/path-operation-advanced-configuration.md b/docs/de/docs/advanced/path-operation-advanced-configuration.md new file mode 100644 index 0000000000000..6899a582a71c8 --- /dev/null +++ b/docs/de/docs/advanced/path-operation-advanced-configuration.md @@ -0,0 +1,166 @@ +# Fortgeschrittene Konfiguration der Pfadoperation { #path-operation-advanced-configuration } + +## OpenAPI operationId { #openapi-operationid } + +/// warning | Achtung + +Wenn Sie kein „Experte“ für OpenAPI sind, brauchen Sie dies wahrscheinlich nicht. + +/// + +Mit dem Parameter `operation_id` können Sie die OpenAPI `operationId` festlegen, die in Ihrer *Pfadoperation* verwendet werden soll. + +Sie müssten sicherstellen, dass sie für jede Operation eindeutig ist. + +{* ../../docs_src/path_operation_advanced_configuration/tutorial001_py310.py hl[6] *} + +### Verwendung des Namens der *Pfadoperation-Funktion* als operationId { #using-the-path-operation-function-name-as-the-operationid } + +Wenn Sie die Funktionsnamen Ihrer APIs als `operationId`s verwenden möchten, können Sie `FastAPI` eine eigene `generate_unique_id_function` übergeben. + +Diese Funktion erhält jeweils die `APIRoute` und gibt die `operationId` zurück, die für diese Pfadoperation verwendet werden soll. + +{* ../../docs_src/path_operation_advanced_configuration/tutorial002_py310.py hl[2,5:6,9] *} + +/// warning | Achtung + +Wenn Sie dies tun, müssen Sie sicherstellen, dass jede Ihrer *Pfadoperation-Funktionen* einen eindeutigen Namen hat. + +Auch wenn diese sich in unterschiedlichen Modulen (Python-Dateien) befinden. + +/// + +## Von OpenAPI ausschließen { #exclude-from-openapi } + +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_py310.py hl[6] *} + +## Fortgeschrittene Beschreibung mittels Docstring { #advanced-description-from-docstring } + +Sie können die verwendeten Zeilen aus dem Docstring einer *Pfadoperation-Funktion* einschränken, die für OpenAPI verwendet werden. + +Das Hinzufügen eines `\f` (ein maskiertes „Form Feed“-Zeichen) führt dazu, dass **FastAPI** die für OpenAPI verwendete Ausgabe an dieser Stelle abschneidet. + +Sie wird nicht in der Dokumentation angezeigt, aber andere Tools (wie z. B. Sphinx) können den Rest verwenden. + +{* ../../docs_src/path_operation_advanced_configuration/tutorial004_py310.py hl[17:27] *} + +## Zusätzliche Responses { #additional-responses } + +Sie haben wahrscheinlich gesehen, wie man das `response_model` und den `status_code` für eine *Pfadoperation* deklariert. + +Das definiert die Metadaten der Haupt-Response einer *Pfadoperation*. + +Sie können auch zusätzliche Responses mit deren Modellen, Statuscodes usw. deklarieren. + +Es gibt hier in der Dokumentation ein ganzes Kapitel darüber, Sie können es unter [Zusätzliche Responses in OpenAPI](additional-responses.md) lesen. + +## OpenAPI-Extra { #openapi-extra } + +Wenn Sie in Ihrer Anwendung eine *Pfadoperation* deklarieren, generiert **FastAPI** automatisch die relevanten Metadaten dieser *Pfadoperation*, die in das OpenAPI-Schema aufgenommen werden sollen. + +/// note | Technische Details + +In der OpenAPI-Spezifikation wird es das [Operationsobjekt](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#operation-object) genannt. + +/// + +Es hat alle Informationen zur *Pfadoperation* und wird zur Erstellung der automatischen Dokumentation verwendet. + +Es enthält `tags`, `parameters`, `requestBody`, `responses`, usw. + +Dieses *Pfadoperation*-spezifische OpenAPI-Schema wird normalerweise automatisch von **FastAPI** generiert, Sie können es aber auch erweitern. + +/// tip | Tipp + +Dies ist ein Low-Level-Erweiterungspunkt. + +Wenn Sie nur zusätzliche Responses deklarieren müssen, können Sie dies bequemer mit [Zusätzliche Responses in OpenAPI](additional-responses.md) tun. + +/// + +Sie können das OpenAPI-Schema für eine *Pfadoperation* erweitern, indem Sie den Parameter `openapi_extra` verwenden. + +### OpenAPI-Erweiterungen { #openapi-extensions } + +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_py310.py hl[6] *} + +Wenn Sie die automatische API-Dokumentation öffnen, wird Ihre Erweiterung am Ende der spezifischen *Pfadoperation* angezeigt. + + + +Und wenn Sie die resultierende OpenAPI sehen (unter `/openapi.json` in Ihrer API), sehen Sie Ihre Erweiterung auch als Teil der spezifischen *Pfadoperation*: + +```JSON hl_lines="22" +{ + "openapi": "3.1.0", + "info": { + "title": "FastAPI", + "version": "0.1.0" + }, + "paths": { + "/items/": { + "get": { + "summary": "Read Items", + "operationId": "read_items_items__get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {} + } + } + } + }, + "x-aperture-labs-portal": "blue" + } + } + } +} +``` + +### Benutzerdefiniertes OpenAPI-*Pfadoperation*-Schema { #custom-openapi-path-operation-schema } + +Das Dictionary in `openapi_extra` wird mit dem automatisch generierten OpenAPI-Schema für die *Pfadoperation* zusammengeführt (mittels Deep Merge). + +Sie können dem automatisch generierten Schema also zusätzliche Daten hinzufügen. + +Sie könnten sich beispielsweise dafür entscheiden, den Request mit Ihrem eigenen Code zu lesen und zu validieren, ohne FastAPIs automatische Funktionen mit Pydantic zu verwenden, aber Sie könnten den Request trotzdem im OpenAPI-Schema definieren wollen. + +Das könnte man mit `openapi_extra` machen: + +{* ../../docs_src/path_operation_advanced_configuration/tutorial006_py310.py hl[19:36, 39:40] *} + +In diesem Beispiel haben wir kein Pydantic-Modell deklariert. Tatsächlich wird der Requestbody nicht einmal als JSON geparst, sondern direkt als `bytes` gelesen und die Funktion `magic_data_reader()` wäre dafür verantwortlich, ihn in irgendeiner Weise zu parsen. + +Dennoch können wir das zu erwartende Schema für den Requestbody deklarieren. + +### Benutzerdefinierter OpenAPI-Content-Type { #custom-openapi-content-type } + +Mit demselben Trick könnten Sie ein Pydantic-Modell verwenden, um das JSON-Schema zu definieren, das dann im benutzerdefinierten Abschnitt des OpenAPI-Schemas für die *Pfadoperation* enthalten ist. + +Und Sie könnten dies auch tun, wenn der Datentyp im Request nicht JSON ist. + +In der folgenden Anwendung verwenden wir beispielsweise weder FastAPIs integrierte Funktionalität zum Extrahieren des JSON-Schemas aus Pydantic-Modellen noch die automatische Validierung für JSON. Tatsächlich deklarieren wir den Request-Content-Type als YAML und nicht als JSON: + +{* ../../docs_src/path_operation_advanced_configuration/tutorial007_py310.py hl[15:20, 22] *} + +Obwohl wir nicht die standardmäßig integrierte Funktionalität verwenden, verwenden wir dennoch ein Pydantic-Modell, um das JSON-Schema für die Daten, die wir in YAML empfangen möchten, manuell zu generieren. + +Dann verwenden wir den Request direkt und extrahieren den Body als `bytes`. Das bedeutet, dass FastAPI nicht einmal versucht, die Request-Payload als JSON zu parsen. + +Und dann parsen wir in unserem Code diesen YAML-Inhalt direkt und verwenden dann wieder dasselbe Pydantic-Modell, um den YAML-Inhalt zu validieren: + +{* ../../docs_src/path_operation_advanced_configuration/tutorial007_py310.py hl[24:31] *} + +/// tip | Tipp + +Hier verwenden wir dasselbe Pydantic-Modell wieder. + +Aber genauso hätten wir es auch auf andere Weise validieren können. + +/// diff --git a/docs/de/docs/advanced/response-change-status-code.md b/docs/de/docs/advanced/response-change-status-code.md new file mode 100644 index 0000000000000..a334cc0bb712d --- /dev/null +++ b/docs/de/docs/advanced/response-change-status-code.md @@ -0,0 +1,32 @@ +# Response – Statuscode ändern { #response-change-status-code } + + +Sie haben wahrscheinlich schon vorher gelesen, dass Sie einen Default-[Response-Statuscode](../tutorial/response-status-code.md) festlegen können. + +In manchen Fällen müssen Sie jedoch einen anderen als den Default-Statuscode zurückgeben. + +## Anwendungsfall { #use-case } + +Stellen Sie sich zum Beispiel vor, Sie möchten standardmäßig den HTTP-Statuscode „OK“ `200` zurückgeben. + +Wenn die Daten jedoch nicht vorhanden sind, möchten Sie diese erstellen und den HTTP-Statuscode „CREATED“ `201` zurückgeben. + +Sie möchten aber dennoch in der Lage sein, die von Ihnen zurückgegebenen Daten mit einem `response_model` zu filtern und zu konvertieren. + +In diesen Fällen können Sie einen `Response`-Parameter verwenden. + +## Einen `Response`-Parameter verwenden { #use-a-response-parameter } + +Sie können einen Parameter vom Typ `Response` in Ihrer *Pfadoperation-Funktion* deklarieren (wie Sie es auch für Cookies und Header tun können). + +Anschließend können Sie den `status_code` in diesem *vorübergehenden* Response-Objekt festlegen. + +{* ../../docs_src/response_change_status_code/tutorial001_py310.py hl[1,9,12] *} + +Und dann können Sie jedes benötigte Objekt zurückgeben, wie Sie es normalerweise tun würden (ein `dict`, ein Datenbankmodell usw.). + +Und wenn Sie ein `response_model` deklariert haben, wird es weiterhin zum Filtern und Konvertieren des von Ihnen zurückgegebenen Objekts verwendet. + +**FastAPI** verwendet diese *vorübergehende* Response, um den Statuscode (auch Cookies und Header) zu extrahieren und fügt diese in die endgültige Response ein, die den von Ihnen zurückgegebenen Wert enthält, gefiltert nach einem beliebigen `response_model`. + +Sie können den Parameter `Response` auch in Abhängigkeiten deklarieren und den Statuscode darin festlegen. Bedenken Sie jedoch, dass der zuletzt gesetzte gewinnt. diff --git a/docs/de/docs/advanced/response-cookies.md b/docs/de/docs/advanced/response-cookies.md new file mode 100644 index 0000000000000..34eb6cfe9c5fe --- /dev/null +++ b/docs/de/docs/advanced/response-cookies.md @@ -0,0 +1,52 @@ +# Response-Cookies { #response-cookies } + + +## Einen `Response`-Parameter verwenden { #use-a-response-parameter } + +Sie können einen Parameter vom Typ `Response` in Ihrer *Pfadoperation-Funktion* deklarieren. + +Und dann können Sie Cookies in diesem *vorübergehenden* Response-Objekt setzen. + +{* ../../docs_src/response_cookies/tutorial002_py310.py hl[1, 8:9] *} + +Anschließend können Sie wie gewohnt jedes gewünschte Objekt zurückgeben (ein `dict`, ein Datenbankmodell, usw.). + +Und wenn Sie ein `response_model` deklariert haben, wird es weiterhin zum Filtern und Konvertieren des von Ihnen zurückgegebenen Objekts verwendet. + +**FastAPI** verwendet diese *vorübergehende* Response, um die Cookies (auch Header und Statuscode) zu extrahieren und fügt diese in die endgültige Response ein, die den von Ihnen zurückgegebenen Wert enthält, gefiltert nach einem beliebigen `response_model`. + +Sie können den `Response`-Parameter auch in Abhängigkeiten deklarieren und darin Cookies (und Header) setzen. + +## Eine `Response` direkt zurückgeben { #return-a-response-directly } + +Sie können Cookies auch erstellen, wenn Sie eine `Response` direkt in Ihrem Code zurückgeben. + +Dazu können Sie eine Response erstellen, wie unter [Eine Response direkt zurückgeben](response-directly.md) beschrieben. + +Setzen Sie dann Cookies darin und geben Sie sie dann zurück: + +{* ../../docs_src/response_cookies/tutorial001_py310.py hl[10:12] *} + +/// tip | Tipp + +Beachten Sie, dass, wenn Sie eine Response direkt zurückgeben, anstatt den `Response`-Parameter zu verwenden, FastAPI diese direkt zurückgibt. + +Sie müssen also sicherstellen, dass Ihre Daten vom richtigen Typ sind. Z. B. sollten diese mit JSON kompatibel sein, wenn Sie eine `JSONResponse` zurückgeben. + +Und auch, dass Sie keine Daten senden, die durch ein `response_model` hätten gefiltert werden sollen. + +/// + +### Mehr Informationen { #more-info } + +/// note | Technische Details + +Sie können auch `from starlette.responses import Response` oder `from starlette.responses import JSONResponse` verwenden. + +**FastAPI** bietet dieselben `starlette.responses` auch via `fastapi.responses` an, als Annehmlichkeit für Sie, den Entwickler. Die meisten verfügbaren Responses kommen aber direkt von Starlette. + +Und da die `Response` häufig zum Setzen von Headern und Cookies verwendet wird, stellt **FastAPI** diese auch unter `fastapi.Response` bereit. + +/// + +Um alle verfügbaren Parameter und Optionen anzuzeigen, sehen Sie sich deren [Dokumentation in Starlette](https://www.starlette.dev/responses/#set-cookie) an. diff --git a/docs/de/docs/advanced/response-directly.md b/docs/de/docs/advanced/response-directly.md new file mode 100644 index 0000000000000..fb5db473ce664 --- /dev/null +++ b/docs/de/docs/advanced/response-directly.md @@ -0,0 +1,83 @@ +# Eine Response direkt zurückgeben { #return-a-response-directly } + +Wenn Sie eine **FastAPI** *Pfadoperation* erstellen, können Sie normalerweise beliebige Daten davon zurückgeben: ein `dict`, eine `list`, ein Pydantic-Modell, ein Datenbankmodell, usw. + +Wenn Sie ein [Responsemodell](../tutorial/response-model.md) deklarieren, wird FastAPI es verwenden, um die Daten mithilfe von Pydantic nach JSON zu serialisieren. + +Wenn Sie kein Responsemodell deklarieren, verwendet FastAPI den `jsonable_encoder`, wie in [JSON-kompatibler Encoder](../tutorial/encoder.md) erläutert, und packt die Daten in eine `JSONResponse`. + +Sie könnten auch direkt eine `JSONResponse` erstellen und zurückgeben. + +/// tip | Tipp + +Normalerweise erzielen Sie eine deutlich bessere Leistung, wenn Sie ein [Responsemodell](../tutorial/response-model.md) verwenden, als wenn Sie direkt eine `JSONResponse` zurückgeben, da die Serialisierung der Daten dabei mit Pydantic in Rust erfolgt. + +/// + +## Eine `Response` zurückgeben { #return-a-response } + +Sie können eine `Response` oder jede Unterklasse davon zurückgeben. + +/// note | Hinweis + +`JSONResponse` selbst ist eine Unterklasse von `Response`. + +/// + +Und wenn Sie eine `Response` zurückgeben, wird **FastAPI** diese direkt weiterleiten. + +Es wird keine Datenkonvertierung mit Pydantic-Modellen durchführen, es wird den Inhalt nicht in irgendeinen Typ konvertieren, usw. + +Dadurch haben Sie viel Flexibilität. Sie können jeden Datentyp zurückgeben, jede Datendeklaration oder -validierung überschreiben, usw. + +Das bringt Ihnen aber auch viel Verantwortung. Sie müssen sicherstellen, dass die von Ihnen zurückgegebenen Daten korrekt sind, das richtige Format haben, serialisierbar sind, usw. + +## Verwendung des `jsonable_encoder` in einer `Response` { #using-the-jsonable-encoder-in-a-response } + +Da **FastAPI** keine Änderungen an einer von Ihnen zurückgegebenen `Response` vornimmt, müssen Sie sicherstellen, dass deren Inhalt dafür bereit ist. + +Sie können beispielsweise kein Pydantic-Modell in eine `JSONResponse` einfügen, ohne es zuvor in ein `dict` zu konvertieren, bei dem alle Datentypen (wie `datetime`, `UUID`, usw.) in JSON-kompatible Typen konvertiert wurden. + +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] *} + +/// note | Technische Details + +Sie könnten auch `from starlette.responses import JSONResponse` verwenden. + +**FastAPI** bietet dieselben `starlette.responses` auch via `fastapi.responses` an, als Annehmlichkeit für Sie, den Entwickler. Die meisten verfügbaren Responses kommen aber direkt von Starlette. + +/// + +## Eine benutzerdefinierte `Response` zurückgeben { #returning-a-custom-response } + +Das obige Beispiel zeigt alle Teile, die Sie benötigen, ist aber noch nicht sehr nützlich, da Sie das `item` einfach direkt hätten zurückgeben können, und **FastAPI** würde es für Sie in eine `JSONResponse` einfügen, es in ein `dict` konvertieren, usw. All das standardmäßig. + +Sehen wir uns nun an, wie Sie damit eine benutzerdefinierte Response zurückgeben können. + +Nehmen wir an, Sie möchten eine [XML](https://en.wikipedia.org/wiki/XML)-Response zurückgeben. + +Sie könnten Ihren XML-Inhalt als String in eine `Response` einfügen und sie zurückgeben: + +{* ../../docs_src/response_directly/tutorial002_py310.py hl[1,18] *} + +## Funktionsweise eines Responsemodells { #how-a-response-model-works } + +Wenn Sie in einer Pfadoperation ein [Responsemodell - Rückgabetyp](../tutorial/response-model.md) deklarieren, wird **FastAPI** es verwenden, um die Daten mithilfe von Pydantic nach JSON zu serialisieren. + +{* ../../docs_src/response_model/tutorial001_01_py310.py hl[16,21] *} + +Da dies auf der Rust-Seite geschieht, ist die Leistung deutlich besser, als wenn es mit normalem Python und der Klasse `JSONResponse` erfolgen würde. + +Wenn Sie ein `response_model` oder einen Rückgabetyp verwenden, nutzt FastAPI weder den `jsonable_encoder` (was langsamer wäre) zur Konvertierung der Daten noch die Klasse `JSONResponse`. + +Stattdessen nimmt es die von Pydantic mithilfe des Responsemodells (oder Rückgabetyps) generierten JSON-Bytes und gibt direkt eine `Response` mit dem richtigen Mediatyp für JSON (`application/json`) zurück. + +## Anmerkungen { #notes } + +Wenn Sie eine `Response` direkt zurücksenden, werden deren Daten weder validiert, konvertiert (serialisiert), noch automatisch dokumentiert. + +Sie können sie aber trotzdem wie unter [Zusätzliche Responses in OpenAPI](additional-responses.md) beschrieben dokumentieren. + +In späteren Abschnitten erfahren Sie, wie Sie diese benutzerdefinierten `Response`s verwenden/deklarieren und gleichzeitig über automatische Datenkonvertierung, Dokumentation, usw. verfügen. diff --git a/docs/de/docs/advanced/response-headers.md b/docs/de/docs/advanced/response-headers.md new file mode 100644 index 0000000000000..baf5715a39a2f --- /dev/null +++ b/docs/de/docs/advanced/response-headers.md @@ -0,0 +1,41 @@ +# Response-Header { #response-headers } + +## Einen `Response`-Parameter verwenden { #use-a-response-parameter } + +Sie können einen Parameter vom Typ `Response` in Ihrer *Pfadoperation-Funktion* deklarieren (wie Sie es auch für Cookies tun können). + +Und dann können Sie Header in diesem *vorübergehenden* Response-Objekt festlegen. + +{* ../../docs_src/response_headers/tutorial002_py310.py hl[1, 7:8] *} + +Anschließend können Sie wie gewohnt jedes gewünschte Objekt zurückgeben (ein `dict`, ein Datenbankmodell, usw.). + +Und wenn Sie ein `response_model` deklariert haben, wird es weiterhin zum Filtern und Konvertieren des von Ihnen zurückgegebenen Objekts verwendet. + +**FastAPI** verwendet diese *vorübergehende* Response, um die Header (auch Cookies und Statuscode) zu extrahieren und fügt diese in die endgültige Response ein, die den von Ihnen zurückgegebenen Wert enthält, gefiltert nach einem beliebigen `response_model`. + +Sie können den Parameter `Response` auch in Abhängigkeiten deklarieren und darin Header (und Cookies) festlegen. + +## Eine `Response` direkt zurückgeben { #return-a-response-directly } + +Sie können auch Header hinzufügen, wenn Sie eine `Response` direkt zurückgeben. + +Erstellen Sie eine Response wie in [Eine Response direkt zurückgeben](response-directly.md) beschrieben und übergeben Sie die Header als zusätzlichen Parameter: + +{* ../../docs_src/response_headers/tutorial001_py310.py hl[10:12] *} + +/// note | Technische Details + +Sie können auch `from starlette.responses import Response` oder `from starlette.responses import JSONResponse` verwenden. + +**FastAPI** bietet dieselben `starlette.responses` auch via `fastapi.responses` an, als Annehmlichkeit für Sie, den Entwickler. Die meisten verfügbaren Responses kommen aber direkt von Starlette. + +Und da die `Response` häufig zum Setzen von Headern und Cookies verwendet wird, stellt **FastAPI** diese auch unter `fastapi.Response` bereit. + +/// + +## Benutzerdefinierte Header { #custom-headers } + +Beachten Sie, dass benutzerdefinierte proprietäre Header [mit dem Präfix `X-`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers) hinzugefügt werden können. + +Wenn Sie jedoch benutzerdefinierte Header haben, die ein Client in einem Browser sehen können soll, müssen Sie diese zu Ihren CORS-Konfigurationen hinzufügen (weitere Informationen finden Sie unter [CORS (Cross-Origin Resource Sharing)](../tutorial/cors.md)), unter Verwendung des Parameters `expose_headers`, dokumentiert in [Starlettes CORS-Dokumentation](https://www.starlette.dev/middleware/#corsmiddleware). diff --git a/docs/de/docs/advanced/security/http-basic-auth.md b/docs/de/docs/advanced/security/http-basic-auth.md new file mode 100644 index 0000000000000..2b4baba309ea8 --- /dev/null +++ b/docs/de/docs/advanced/security/http-basic-auth.md @@ -0,0 +1,107 @@ +# HTTP Basic Auth { #http-basic-auth } + +Für die einfachsten Fälle können Sie HTTP Basic Auth verwenden. + +Bei HTTP Basic Auth erwartet die Anwendung einen Header, der einen Benutzernamen und ein Passwort enthält. + +Wenn sie diesen nicht empfängt, gibt sie den HTTP-Error 401 „Unauthorized“ zurück. + +Und gibt einen Header `WWW-Authenticate` mit dem Wert `Basic` und einem optionalen `realm`-Parameter zurück. + +Dadurch wird der Browser angewiesen, die integrierte Eingabeaufforderung für einen Benutzernamen und ein Passwort anzuzeigen. + +Wenn Sie dann den Benutzernamen und das Passwort eingeben, sendet der Browser diese automatisch im Header. + +## Einfaches HTTP Basic Auth { #simple-http-basic-auth } + +* Importieren Sie `HTTPBasic` und `HTTPBasicCredentials`. +* Erstellen Sie mit `HTTPBasic` ein „`security`-Schema“. +* Verwenden Sie dieses `security` mit einer Abhängigkeit in Ihrer *Pfadoperation*. +* Diese gibt ein Objekt vom Typ `HTTPBasicCredentials` zurück: + * Es enthält den gesendeten `username` und das gesendete `password`. + +{* ../../docs_src/security/tutorial006_an_py310.py hl[4,8,12] *} + +Wenn Sie versuchen, die URL zum ersten Mal zu öffnen (oder in der Dokumentation auf den Button „Execute“ zu klicken), wird der Browser Sie nach Ihrem Benutzernamen und Passwort fragen: + + + +## Den Benutzernamen überprüfen { #check-the-username } + +Hier ist ein vollständigeres Beispiel. + +Verwenden Sie eine Abhängigkeit, um zu überprüfen, ob Benutzername und Passwort korrekt sind. + +Verwenden Sie dazu das Python-Standardmodul [`secrets`](https://docs.python.org/3/library/secrets.html), um den Benutzernamen und das Passwort zu überprüfen. + +`secrets.compare_digest()` benötigt `bytes` oder einen `str`, welcher nur ASCII-Zeichen (solche der englischen Sprache) enthalten darf, das bedeutet, dass es nicht mit Zeichen wie `á`, wie in `Sebastián`, funktionieren würde. + +Um dies zu lösen, konvertieren wir zunächst den `username` und das `password` in UTF-8-codierte `bytes`. + +Dann können wir `secrets.compare_digest()` verwenden, um sicherzustellen, dass `credentials.username` `"stanleyjobson"` und `credentials.password` `"swordfish"` ist. + +{* ../../docs_src/security/tutorial007_an_py310.py hl[1,12:24] *} + +Dies wäre das gleiche wie: + +```Python +if not (credentials.username == "stanleyjobson") or not (credentials.password == "swordfish"): + # Einen Error zurückgeben + ... +``` + +Aber durch die Verwendung von `secrets.compare_digest()` ist dieser Code sicher vor einer Art von Angriffen, die „Timing-Angriffe“ genannt werden. + +### Timing-Angriffe { #timing-attacks } + +Aber was ist ein „Timing-Angriff“? + +Stellen wir uns vor, dass einige Angreifer versuchen, den Benutzernamen und das Passwort zu erraten. + +Und sie senden einen Request mit dem Benutzernamen `johndoe` und dem Passwort `love123`. + +Dann würde der Python-Code in Ihrer Anwendung etwa so aussehen: + +```Python +if "johndoe" == "stanleyjobson" and "love123" == "swordfish": + ... +``` + +Aber genau in dem Moment, in dem Python das erste `j` in `johndoe` mit dem ersten `s` in `stanleyjobson` vergleicht, gibt es `False` zurück, da es bereits weiß, dass diese beiden Strings nicht identisch sind, und denkt, „Es besteht keine Notwendigkeit, weitere Berechnungen mit dem Vergleich der restlichen Buchstaben zu verschwenden“. Und Ihre Anwendung wird zurückgeben „Incorrect username or password“. + +Doch dann versuchen es die Angreifer mit dem Benutzernamen `stanleyjobsox` und dem Passwort `love123`. + +Und Ihr Anwendungscode macht etwa Folgendes: + +```Python +if "stanleyjobsox" == "stanleyjobson" and "love123" == "swordfish": + ... +``` + +Python muss das gesamte `stanleyjobso` in `stanleyjobsox` und `stanleyjobson` vergleichen, bevor es erkennt, dass beide Zeichenfolgen nicht gleich sind. Daher wird es einige zusätzliche Mikrosekunden dauern, bis die Response „Incorrect username or password“ erfolgt. + +#### Die Zeit zum Antworten hilft den Angreifern { #the-time-to-answer-helps-the-attackers } + +Wenn die Angreifer zu diesem Zeitpunkt feststellen, dass der Server einige Mikrosekunden länger braucht, um die Response „Incorrect username or password“ zu senden, wissen sie, dass sie _etwas_ richtig gemacht haben, einige der Anfangsbuchstaben waren richtig. + +Und dann können sie es noch einmal versuchen, wohl wissend, dass es wahrscheinlich eher etwas mit `stanleyjobsox` als mit `johndoe` zu tun hat. + +#### Ein „professioneller“ Angriff { #a-professional-attack } + +Natürlich würden die Angreifer das alles nicht von Hand versuchen, sondern ein Programm dafür schreiben, möglicherweise mit Tausenden oder Millionen Tests pro Sekunde. Und würden jeweils nur einen zusätzlichen richtigen Buchstaben erhalten. + +Aber so hätten die Angreifer in wenigen Minuten oder Stunden mit der „Hilfe“ unserer Anwendung den richtigen Benutzernamen und das richtige Passwort erraten, indem sie die Zeitspanne zur Hilfe nehmen, die diese zur Beantwortung benötigt. + +#### Das Problem beheben mittels `secrets.compare_digest()` { #fix-it-with-secrets-compare-digest } + +Aber in unserem Code verwenden wir tatsächlich `secrets.compare_digest()`. + +Damit wird, kurz gesagt, der Vergleich von `stanleyjobsox` mit `stanleyjobson` genauso lange dauern wie der Vergleich von `johndoe` mit `stanleyjobson`. Und das Gleiche gilt für das Passwort. + +So ist Ihr Anwendungscode, dank der Verwendung von `secrets.compare_digest()`, vor dieser ganzen Klasse von Sicherheitsangriffen geschützt. + +### Den Error zurückgeben { #return-the-error } + +Nachdem Sie festgestellt haben, dass die Anmeldeinformationen falsch sind, geben Sie eine `HTTPException` mit dem Statuscode 401 zurück (derselbe, der auch zurückgegeben wird, wenn keine Anmeldeinformationen angegeben werden) und fügen den Header `WWW-Authenticate` hinzu, damit der Browser die Anmeldeaufforderung erneut anzeigt: + +{* ../../docs_src/security/tutorial007_an_py310.py hl[26:30] *} diff --git a/docs/de/docs/advanced/security/index.md b/docs/de/docs/advanced/security/index.md new file mode 100644 index 0000000000000..9884f2c1b76a8 --- /dev/null +++ b/docs/de/docs/advanced/security/index.md @@ -0,0 +1,19 @@ +# Fortgeschrittene Sicherheit { #advanced-security } + +## Zusatzfunktionen { #additional-features } + +Neben den in [Tutorial – Benutzerhandbuch: Sicherheit](../../tutorial/security/index.md) behandelten Funktionen gibt es noch einige zusätzliche Funktionen zur Handhabung der Sicherheit. + +/// tip | Tipp + +Die nächsten Abschnitte sind **nicht unbedingt „fortgeschritten“**. + +Und es ist möglich, dass für Ihren Anwendungsfall die Lösung in einem davon liegt. + +/// + +## Das Tutorial zuerst lesen { #read-the-tutorial-first } + +Die nächsten Abschnitte setzen voraus, dass Sie das Haupt-[Tutorial – Benutzerhandbuch: Sicherheit](../../tutorial/security/index.md) bereits gelesen haben. + +Sie basieren alle auf den gleichen Konzepten, ermöglichen jedoch einige zusätzliche Funktionalitäten. diff --git a/docs/de/docs/advanced/security/oauth2-scopes.md b/docs/de/docs/advanced/security/oauth2-scopes.md new file mode 100644 index 0000000000000..74457b40decb8 --- /dev/null +++ b/docs/de/docs/advanced/security/oauth2-scopes.md @@ -0,0 +1,274 @@ +# OAuth2-Scopes { #oauth2-scopes } + +Sie können OAuth2-Scopes direkt in **FastAPI** verwenden, sie sind nahtlos integriert. + +Das ermöglicht es Ihnen, ein feingranuliertes Berechtigungssystem nach dem OAuth2-Standard in Ihre OpenAPI-Anwendung (und deren API-Dokumentation) zu integrieren. + +OAuth2 mit Scopes ist der Mechanismus, der von vielen großen Authentifizierungsanbietern wie Facebook, Google, GitHub, Microsoft, X (Twitter) usw. verwendet wird. Sie verwenden ihn, um Benutzern und Anwendungen spezifische Berechtigungen zu erteilen. + +Jedes Mal, wenn Sie sich mit Facebook, Google, GitHub, Microsoft oder X (Twitter) anmelden („log in with“), verwendet die entsprechende Anwendung OAuth2 mit Scopes. + +In diesem Abschnitt erfahren Sie, wie Sie Authentifizierung und Autorisierung mit demselben OAuth2, mit Scopes in Ihrer **FastAPI**-Anwendung verwalten. + +/// warning | Achtung + +Dies ist ein mehr oder weniger fortgeschrittener Abschnitt. Wenn Sie gerade erst anfangen, können Sie ihn überspringen. + +Sie benötigen nicht unbedingt OAuth2-Scopes, und Sie können die Authentifizierung und Autorisierung handhaben wie Sie möchten. + +Aber OAuth2 mit Scopes kann bequem in Ihre API (mit OpenAPI) und deren API-Dokumentation integriert werden. + +Dennoch erzwingen Sie solche Scopes oder andere Sicherheits-/Autorisierungsanforderungen in Ihrem Code so, wie Sie es benötigen. + +In vielen Fällen kann OAuth2 mit Scopes ein Overkill sein. + +Aber wenn Sie wissen, dass Sie es brauchen oder neugierig sind, lesen Sie weiter. + +/// + +## OAuth2-Scopes und OpenAPI { #oauth2-scopes-and-openapi } + +Die OAuth2-Spezifikation definiert „Scopes“ als eine Liste von durch Leerzeichen getrennten Strings. + +Der Inhalt jedes dieser Strings kann ein beliebiges Format haben, sollte jedoch keine Leerzeichen enthalten. + +Diese Scopes stellen „Berechtigungen“ dar. + +In OpenAPI (z. B. der API-Dokumentation) können Sie „Sicherheitsschemas“ definieren. + +Wenn eines dieser Sicherheitsschemas OAuth2 verwendet, können Sie auch Scopes deklarieren und verwenden. + +Jeder „Scope“ ist nur ein String (ohne Leerzeichen). + +Er wird normalerweise verwendet, um bestimmte Sicherheitsberechtigungen zu deklarieren, zum Beispiel: + +* `users:read` oder `users:write` sind gängige Beispiele. +* `instagram_basic` wird von Facebook / Instagram verwendet. +* `https://www.googleapis.com/auth/drive` wird von Google verwendet. + +/// note | Hinweis + +In OAuth2 ist ein „Scope“ nur ein String, der eine bestimmte erforderliche Berechtigung deklariert. + +Es spielt keine Rolle, ob er andere Zeichen wie `:` enthält oder ob es eine URL ist. + +Diese Details sind implementierungsspezifisch. + +Für OAuth2 sind es einfach nur Strings. + +/// + +## Gesamtübersicht { #global-view } + +Sehen wir uns zunächst kurz die Teile an, die sich gegenüber den Beispielen im Haupt-**Tutorial – Benutzerhandbuch** für [OAuth2 mit Password (und Hashing), Bearer mit JWT-Tokens](../../tutorial/security/oauth2-jwt.md) ändern. Diesmal verwenden wir OAuth2-Scopes: + +{* ../../docs_src/security/tutorial005_an_py310.py hl[5,9,13,47,65,106,108:116,122:126,130:136,141,157] *} + +Sehen wir uns diese Änderungen nun Schritt für Schritt an. + +## OAuth2-Sicherheitsschema { #oauth2-security-scheme } + +Die erste Änderung ist, dass wir jetzt das OAuth2-Sicherheitsschema mit zwei verfügbaren Scopes deklarieren: `me` und `items`. + +Der `scopes`-Parameter erhält ein `dict` mit jedem Scope als Schlüssel und dessen Beschreibung als Wert: + +{* ../../docs_src/security/tutorial005_an_py310.py hl[63:66] *} + +Da wir diese Scopes jetzt deklarieren, werden sie in der API-Dokumentation angezeigt, wenn Sie sich einloggen/autorisieren. + +Und Sie können auswählen, auf welche Scopes Sie Zugriff haben möchten: `me` und `items`. + +Das ist derselbe Mechanismus, der verwendet wird, wenn Sie beim Anmelden mit Facebook, Google, GitHub, usw. Berechtigungen erteilen: + + + +## JWT-Token mit Scopes { #jwt-token-with-scopes } + +Ändern Sie nun die Token-*Pfadoperation*, um die angeforderten Scopes zurückzugeben. + +Wir verwenden immer noch dasselbe `OAuth2PasswordRequestForm`. Es enthält eine Eigenschaft `scopes` mit einer `list`e von `str`s für jeden Scope, den es im Request erhalten hat. + +Und wir geben die Scopes als Teil des JWT-Tokens zurück. + +/// danger | Gefahr + +Der Einfachheit halber fügen wir hier die empfangenen Scopes direkt zum Token hinzu. + +Aus Sicherheitsgründen sollten Sie jedoch sicherstellen, dass Sie in Ihrer Anwendung nur die Scopes hinzufügen, die der Benutzer tatsächlich haben kann, oder die Sie vordefiniert haben. + +/// + +{* ../../docs_src/security/tutorial005_an_py310.py hl[157] *} + +## Scopes in *Pfadoperationen* und Abhängigkeiten deklarieren { #declare-scopes-in-path-operations-and-dependencies } + +Jetzt deklarieren wir, dass die *Pfadoperation* für `/users/me/items/` den Scope `items` erfordert. + +Dazu importieren und verwenden wir `Security` von `fastapi`. + +Sie können `Security` verwenden, um Abhängigkeiten zu deklarieren (genau wie `Depends`), aber `Security` erhält auch einen Parameter `scopes` mit einer Liste von Scopes (Strings). + +In diesem Fall übergeben wir eine Abhängigkeitsfunktion `get_current_active_user` an `Security` (genauso wie wir es mit `Depends` tun würden). + +Wir übergeben aber auch eine `list`e von Scopes, in diesem Fall mit nur einem Scope: `items` (es könnten mehrere sein). + +Und die Abhängigkeitsfunktion `get_current_active_user` kann auch Unterabhängigkeiten deklarieren, nicht nur mit `Depends`, sondern auch mit `Security`. Ihre eigene Unterabhängigkeitsfunktion (`get_current_user`) und weitere Scope-Anforderungen deklarierend. + +In diesem Fall erfordert sie den Scope `me` (sie könnte mehr als einen Scope erfordern). + +/// note | Hinweis + +Sie müssen nicht unbedingt an verschiedenen Stellen verschiedene Scopes hinzufügen. + +Wir tun dies hier, um zu demonstrieren, wie **FastAPI** auf verschiedenen Ebenen deklarierte Scopes verarbeitet. + +/// + +{* ../../docs_src/security/tutorial005_an_py310.py hl[5,141,172] *} + +/// note | Technische Details + +`Security` ist tatsächlich eine Unterklasse von `Depends` und hat nur noch einen zusätzlichen Parameter, den wir später kennenlernen werden. + +Durch die Verwendung von `Security` anstelle von `Depends` weiß **FastAPI** jedoch, dass es Sicherheits-Scopes deklarieren, intern verwenden und die API mit OpenAPI dokumentieren kann. + +Wenn Sie jedoch `Query`, `Path`, `Depends`, `Security` und andere von `fastapi` importieren, handelt es sich tatsächlich um Funktionen, die spezielle Klassen zurückgeben. + +/// + +## `SecurityScopes` verwenden { #use-securityscopes } + +Aktualisieren Sie nun die Abhängigkeit `get_current_user`. + +Das ist diejenige, die von den oben genannten Abhängigkeiten verwendet wird. + +Hier verwenden wir dasselbe OAuth2-Schema, das wir zuvor erstellt haben, und deklarieren es als Abhängigkeit: `oauth2_scheme`. + +Da diese Abhängigkeitsfunktion selbst keine Scope-Anforderungen hat, können wir `Depends` mit `oauth2_scheme` verwenden. Wir müssen `Security` nicht verwenden, wenn wir keine Sicherheits-Scopes angeben müssen. + +Wir deklarieren auch einen speziellen Parameter vom Typ `SecurityScopes`, der aus `fastapi.security` importiert wird. + +Diese `SecurityScopes`-Klasse ähnelt `Request` (`Request` wurde verwendet, um das Request-Objekt direkt zu erhalten). + +{* ../../docs_src/security/tutorial005_an_py310.py hl[9,106] *} + +## Die `scopes` verwenden { #use-the-scopes } + +Der Parameter `security_scopes` wird vom Typ `SecurityScopes` sein. + +Dieses verfügt über ein Attribut `scopes` mit einer Liste, die alle von ihm selbst benötigten Scopes enthält und ferner alle Abhängigkeiten, die dieses als Unterabhängigkeit verwenden. Sprich, alle „Dependanten“ ... das mag verwirrend klingen, wird aber später noch einmal erklärt. + +Das `security_scopes`-Objekt (der Klasse `SecurityScopes`) stellt außerdem ein `scope_str`-Attribut mit einem einzelnen String bereit, der die durch Leerzeichen getrennten Scopes enthält (den werden wir verwenden). + +Wir erstellen eine `HTTPException`, die wir später an mehreren Stellen wiederverwenden (`raise`n) können. + +In diese Exception fügen wir (falls vorhanden) die erforderlichen Scopes als durch Leerzeichen getrennten String ein (unter Verwendung von `scope_str`). Wir fügen diesen String mit den Scopes in den Header `WWW-Authenticate` ein (das ist Teil der Spezifikation). + +{* ../../docs_src/security/tutorial005_an_py310.py hl[106,108:116] *} + +## Den `username` und das Format der Daten überprüfen { #verify-the-username-and-data-shape } + +Wir verifizieren, dass wir einen `username` erhalten, und extrahieren die Scopes. + +Und dann validieren wir diese Daten mit dem Pydantic-Modell (wobei wir die `ValidationError`-Exception abfangen), und wenn wir beim Lesen des JWT-Tokens oder beim Validieren der Daten mit Pydantic einen Fehler erhalten, lösen wir die zuvor erstellte `HTTPException` aus. + +Dazu aktualisieren wir das Pydantic-Modell `TokenData` mit einem neuen Attribut `scopes`. + +Durch die Validierung der Daten mit Pydantic können wir sicherstellen, dass wir beispielsweise präzise eine `list`e von `str`s mit den Scopes und einen `str` mit dem `username` haben. + +Anstelle beispielsweise eines `dict`s oder etwas anderem, was später in der Anwendung zu Fehlern führen könnte und darum ein Sicherheitsrisiko darstellt. + +Wir verifizieren auch, dass wir einen Benutzer mit diesem Benutzernamen haben, und wenn nicht, lösen wir dieselbe Exception aus, die wir zuvor erstellt haben. + +{* ../../docs_src/security/tutorial005_an_py310.py hl[47,117:129] *} + +## Die `scopes` verifizieren { #verify-the-scopes } + +Wir überprüfen nun, ob das empfangene Token alle Scopes enthält, die von dieser Abhängigkeit und deren Verwendern (einschließlich *Pfadoperationen*) gefordert werden. Andernfalls lösen wir eine `HTTPException` aus. + +Hierzu verwenden wir `security_scopes.scopes`, das eine `list`e mit allen diesen Scopes als `str` enthält. + +{* ../../docs_src/security/tutorial005_an_py310.py hl[130:136] *} + +## Abhängigkeitsbaum und Scopes { #dependency-tree-and-scopes } + +Sehen wir uns diesen Abhängigkeitsbaum und die Scopes noch einmal an. + +Da die Abhängigkeit `get_current_active_user` von `get_current_user` abhängt, wird der bei `get_current_active_user` deklarierte Scope `"me"` in die Liste der erforderlichen Scopes in `security_scopes.scopes` aufgenommen, das an `get_current_user` übergeben wird. + +Die *Pfadoperation* selbst deklariert auch einen Scope, `"items"`, sodass dieser auch in der Liste der `security_scopes.scopes` enthalten ist, die an `get_current_user` übergeben wird. + +So sieht die Hierarchie der Abhängigkeiten und Scopes aus: + +* Die *Pfadoperation* `read_own_items` hat: + * Erforderliche Scopes `["items"]` mit der Abhängigkeit: + * `get_current_active_user`: + * Die Abhängigkeitsfunktion `get_current_active_user` hat: + * Erforderliche Scopes `["me"]` mit der Abhängigkeit: + * `get_current_user`: + * Die Abhängigkeitsfunktion `get_current_user` hat: + * Selbst keine erforderlichen Scopes. + * Eine Abhängigkeit, die `oauth2_scheme` verwendet. + * Einen `security_scopes`-Parameter vom Typ `SecurityScopes`: + * Dieser `security_scopes`-Parameter hat ein Attribut `scopes` mit einer `list`e, die alle oben deklarierten Scopes enthält, sprich: + * `security_scopes.scopes` enthält `["me", "items"]` für die *Pfadoperation* `read_own_items`. + * `security_scopes.scopes` enthält `["me"]` für die *Pfadoperation* `read_users_me`, da das in der Abhängigkeit `get_current_active_user` deklariert ist. + * `security_scopes.scopes` wird `[]` (nichts) für die *Pfadoperation* `read_system_status` enthalten, da diese keine `Security` mit `scopes` deklariert hat, und deren Abhängigkeit `get_current_user` ebenfalls keinerlei `scopes` deklariert. + +/// tip | Tipp + +Das Wichtige und „Magische“ hier ist, dass `get_current_user` für jede *Pfadoperation* eine andere Liste von `scopes` hat, die überprüft werden. + +Alles hängt von den „Scopes“ ab, die in jeder *Pfadoperation* und jeder Abhängigkeit im Abhängigkeitsbaum für diese bestimmte *Pfadoperation* deklariert wurden. + +/// + +## Weitere Details zu `SecurityScopes` { #more-details-about-securityscopes } + +Sie können `SecurityScopes` an jeder Stelle und an mehreren Stellen verwenden, es muss sich nicht in der „Wurzel“-Abhängigkeit befinden. + +Es wird immer die Sicherheits-Scopes enthalten, die in den aktuellen `Security`-Abhängigkeiten deklariert sind und in allen Abhängigkeiten für **diese spezifische** *Pfadoperation* und **diesen spezifischen** Abhängigkeitsbaum. + +Da die `SecurityScopes` alle von den Verwendern der Abhängigkeiten deklarierten Scopes enthalten, können Sie damit überprüfen, ob ein Token in einer zentralen Abhängigkeitsfunktion über die erforderlichen Scopes verfügt, und dann unterschiedliche Scope-Anforderungen in unterschiedlichen *Pfadoperationen* deklarieren. + +Diese werden für jede *Pfadoperation* unabhängig überprüft. + +## Es testen { #check-it } + +Wenn Sie die API-Dokumentation öffnen, können Sie sich authentisieren und angeben, welche Scopes Sie autorisieren möchten. + + + +Wenn Sie keinen Scope auswählen, werden Sie „authentifiziert“, aber wenn Sie versuchen, auf `/users/me/` oder `/users/me/items/` zuzugreifen, wird eine Fehlermeldung angezeigt, die sagt, dass Sie nicht über genügend Berechtigungen verfügen. Sie können aber auf `/status/` zugreifen. + +Und wenn Sie den Scope `me`, aber nicht den Scope `items` auswählen, können Sie auf `/users/me/` zugreifen, aber nicht auf `/users/me/items/`. + +Das würde einer Drittanbieteranwendung passieren, die versucht, auf eine dieser *Pfadoperationen* mit einem Token zuzugreifen, das von einem Benutzer bereitgestellt wurde, abhängig davon, wie viele Berechtigungen der Benutzer dieser Anwendung erteilt hat. + +## Über Integrationen von Drittanbietern { #about-third-party-integrations } + +In diesem Beispiel verwenden wir den OAuth2-Flow „password“. + +Das ist angemessen, wenn wir uns bei unserer eigenen Anwendung anmelden, wahrscheinlich mit unserem eigenen Frontend. + +Weil wir darauf vertrauen können, dass es den `username` und das `password` erhält, welche wir kontrollieren. + +Wenn Sie jedoch eine OAuth2-Anwendung erstellen, mit der andere eine Verbindung herstellen würden (d.h. wenn Sie einen Authentifizierungsanbieter erstellen, der Facebook, Google, GitHub usw. entspricht), sollten Sie einen der anderen Flows verwenden. + +Am häufigsten ist der implicit Flow. + +Am sichersten ist der code Flow, die Implementierung ist jedoch komplexer, da mehr Schritte erforderlich sind. Da er komplexer ist, schlagen viele Anbieter letztendlich den implicit Flow vor. + +/// note | Hinweis + +Es ist üblich, dass jeder Authentifizierungsanbieter seine Flows anders benennt, um sie zu einem Teil seiner Marke zu machen. + +Aber am Ende implementieren sie denselben OAuth2-Standard. + +/// + +**FastAPI** enthält Werkzeuge für alle diese OAuth2-Authentifizierungs-Flows in `fastapi.security.oauth2`. + +## `Security` in Dekorator-`dependencies` { #security-in-decorator-dependencies } + +Auf die gleiche Weise können Sie eine `list`e von `Depends` im Parameter `dependencies` des Dekorators definieren (wie in [Abhängigkeiten in Pfadoperation-Dekoratoren](../../tutorial/dependencies/dependencies-in-path-operation-decorators.md) erläutert), Sie könnten auch dort `Security` mit `scopes` verwenden. diff --git a/docs/de/docs/advanced/settings.md b/docs/de/docs/advanced/settings.md new file mode 100644 index 0000000000000..993e5ae71800d --- /dev/null +++ b/docs/de/docs/advanced/settings.md @@ -0,0 +1,302 @@ +# Einstellungen und Umgebungsvariablen { #settings-and-environment-variables } + +In vielen Fällen benötigt Ihre Anwendung möglicherweise einige externe Einstellungen oder Konfigurationen, zum Beispiel geheime Schlüssel, Datenbank-Anmeldeinformationen, Anmeldeinformationen für E-Mail-Dienste, usw. + +Die meisten dieser Einstellungen sind variabel (können sich ändern), wie z. B. Datenbank-URLs. Und vieles könnten schützenswerte, geheime Daten sein. + +Aus diesem Grund werden diese üblicherweise in Umgebungsvariablen bereitgestellt, die von der Anwendung gelesen werden. + +/// tip | Tipp + +Um Umgebungsvariablen zu verstehen, können Sie [Umgebungsvariablen](../environment-variables.md) lesen. + +/// + +## Typen und Validierung { #types-and-validation } + +Diese Umgebungsvariablen können nur Text-Strings verarbeiten, da sie außerhalb von Python liegen und mit anderen Programmen und dem Rest des Systems (und sogar mit verschiedenen Betriebssystemen wie Linux, Windows, macOS) kompatibel sein müssen. + +Das bedeutet, dass jeder in Python aus einer Umgebungsvariablen gelesene Wert ein `str` ist und jede Konvertierung in einen anderen Typ oder jede Validierung im Code erfolgen muss. + +## Pydantic `Settings` { #pydantic-settings } + +Glücklicherweise bietet Pydantic ein großartiges Werkzeug zur Verarbeitung dieser Einstellungen, die von Umgebungsvariablen stammen, mit [Pydantic: Settings-Verwaltung](https://docs.pydantic.dev/latest/concepts/pydantic_settings/). + +### `pydantic-settings` installieren { #install-pydantic-settings } + +Stellen Sie zunächst sicher, dass Sie Ihre [virtuelle Umgebung](../virtual-environments.md) erstellt und aktiviert haben, und installieren Sie dann das Package `pydantic-settings`: + +
+ +```console +$ pip install pydantic-settings +---> 100% +``` + +
+ +Es ist bereits enthalten, wenn Sie die `all`-Extras installiert haben, mit: + +
+ +```console +$ pip install "fastapi[all]" +---> 100% +``` + +
+ +### Das `Settings`-Objekt erstellen { #create-the-settings-object } + +Importieren Sie `BaseSettings` aus Pydantic und erstellen Sie eine Unterklasse, ganz ähnlich wie bei einem Pydantic-Modell. + +Auf die gleiche Weise wie bei Pydantic-Modellen deklarieren Sie Klassenattribute mit Typannotationen und möglicherweise Defaultwerten. + +Sie können dieselben Validierungs-Funktionen und -Tools verwenden, die Sie für Pydantic-Modelle verwenden, z. B. verschiedene Datentypen und zusätzliche Validierungen mit `Field()`. + +{* ../../docs_src/settings/tutorial001_py310.py hl[2,5:8,11] *} + +/// tip | Tipp + +Für ein schnelles Copy-and-paste verwenden Sie nicht dieses Beispiel, sondern das letzte unten. + +/// + +Wenn Sie dann eine Instanz dieser `Settings`-Klasse erstellen (in diesem Fall als `settings`-Objekt), liest Pydantic die Umgebungsvariablen ohne Berücksichtigung der Groß- und Kleinschreibung. Eine Variable `APP_NAME` in Großbuchstaben wird also als Attribut `app_name` gelesen. + +Als Nächstes werden die Daten konvertiert und validiert. Wenn Sie also dieses `settings`-Objekt verwenden, verfügen Sie über Daten mit den von Ihnen deklarierten Typen (z. B. ist `items_per_user` ein `int`). + +### `settings` verwenden { #use-the-settings } + +Dann können Sie das neue `settings`-Objekt in Ihrer Anwendung verwenden: + +{* ../../docs_src/settings/tutorial001_py310.py hl[18:20] *} + +### Den Server ausführen { #run-the-server } + +Als Nächstes würden Sie den Server ausführen und die Konfigurationen als Umgebungsvariablen übergeben. Sie könnten beispielsweise `ADMIN_EMAIL` und `APP_NAME` festlegen mit: + +
+ +```console +$ ADMIN_EMAIL="deadpool@example.com" APP_NAME="ChimichangApp" fastapi run main.py + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +/// tip | Tipp + +Um mehrere Umgebungsvariablen für einen einzelnen Befehl festzulegen, trennen Sie diese einfach durch ein Leerzeichen und fügen Sie alle vor dem Befehl ein. + +/// + +Und dann würde die Einstellung `admin_email` auf `"deadpool@example.com"` gesetzt. + +Der `app_name` wäre `"ChimichangApp"`. + +Und `items_per_user` würde seinen Defaultwert von `50` behalten. + +## Einstellungen in einem anderen Modul { #settings-in-another-module } + +Sie könnten diese Einstellungen in eine andere Moduldatei einfügen, wie Sie in [Größere Anwendungen – mehrere Dateien](../tutorial/bigger-applications.md) gesehen haben. + +Sie könnten beispielsweise eine Datei `config.py` haben mit: + +{* ../../docs_src/settings/app01_py310/config.py *} + +Und dann verwenden Sie diese in einer Datei `main.py`: + +{* ../../docs_src/settings/app01_py310/main.py hl[3,11:13] *} + +/// tip | Tipp + +Sie benötigen außerdem eine Datei `__init__.py`, wie in [Größere Anwendungen – mehrere Dateien](../tutorial/bigger-applications.md) gesehen. + +/// + +## Einstellungen in einer Abhängigkeit { #settings-in-a-dependency } + +In manchen Fällen kann es nützlich sein, die Einstellungen mit einer Abhängigkeit bereitzustellen, anstatt ein globales Objekt `settings` zu haben, das überall verwendet wird. + +Dies könnte besonders beim Testen nützlich sein, da es sehr einfach ist, eine Abhängigkeit mit Ihren eigenen benutzerdefinierten Einstellungen zu überschreiben. + +### Die Konfigurationsdatei { #the-config-file } + +Ausgehend vom vorherigen Beispiel könnte Ihre Datei `config.py` so aussehen: + +{* ../../docs_src/settings/app02_an_py310/config.py hl[10] *} + +Beachten Sie, dass wir jetzt keine Defaultinstanz `settings = Settings()` erstellen. + +### Die Haupt-Anwendungsdatei { #the-main-app-file } + +Jetzt erstellen wir eine Abhängigkeit, die ein neues `config.Settings()` zurückgibt. + +{* ../../docs_src/settings/app02_an_py310/main.py hl[6,12:13] *} + +/// tip | Tipp + +Wir werden das `@lru_cache` in Kürze besprechen. + +Im Moment nehmen Sie an, dass `get_settings()` eine normale Funktion ist. + +/// + +Und dann können wir das von der *Pfadoperation-Funktion* als Abhängigkeit einfordern und es überall dort verwenden, wo wir es brauchen. + +{* ../../docs_src/settings/app02_an_py310/main.py hl[17,19:21] *} + +### Einstellungen und Tests { #settings-and-testing } + +Dann wäre es sehr einfach, beim Testen ein anderes Einstellungsobjekt bereitzustellen, indem man eine Abhängigkeitsüberschreibung für `get_settings` erstellt: + +{* ../../docs_src/settings/app02_an_py310/test_main.py hl[9:10,13,21] *} + +Bei der Abhängigkeitsüberschreibung legen wir einen neuen Wert für `admin_email` fest, wenn wir das neue `Settings`-Objekt erstellen, und geben dann dieses neue Objekt zurück. + +Dann können wir testen, ob das verwendet wird. + +## Eine `.env`-Datei lesen { #reading-a-env-file } + +Wenn Sie viele Einstellungen haben, die sich möglicherweise oft ändern, vielleicht in verschiedenen Umgebungen, kann es nützlich sein, diese in eine Datei zu schreiben und sie dann daraus zu lesen, als wären sie Umgebungsvariablen. + +Diese Praxis ist so weit verbreitet, dass sie einen Namen hat. Diese Umgebungsvariablen werden üblicherweise in einer Datei `.env` abgelegt und die Datei wird „dotenv“ genannt. + +/// tip | Tipp + +Eine Datei, die mit einem Punkt (`.`) beginnt, ist eine versteckte Datei in Unix-ähnlichen Systemen wie Linux und macOS. + +Aber eine dotenv-Datei muss nicht unbedingt genau diesen Dateinamen haben. + +/// + +Pydantic unterstützt das Lesen dieser Dateitypen mithilfe einer externen Bibliothek. Weitere Informationen finden Sie unter [Pydantic Settings: Dotenv (.env)-Unterstützung](https://docs.pydantic.dev/latest/concepts/pydantic_settings/#dotenv-env-support). + +/// tip | Tipp + +Damit das funktioniert, müssen Sie `pip install python-dotenv` ausführen. + +/// + +### Die `.env`-Datei { #the-env-file } + +Sie könnten eine `.env`-Datei haben, mit: + +```bash +ADMIN_EMAIL="deadpool@example.com" +APP_NAME="ChimichangApp" +``` + +### Einstellungen aus `.env` lesen { #read-settings-from-env } + +Und dann aktualisieren Sie Ihre `config.py` mit: + +{* ../../docs_src/settings/app03_an_py310/config.py hl[9] *} + +/// tip | Tipp + +Das Attribut `model_config` wird nur für die Pydantic-Konfiguration verwendet. Weitere Informationen finden Sie unter [Pydantic: Konzepte: Konfiguration](https://docs.pydantic.dev/latest/concepts/config/). + +/// + +Hier definieren wir die Konfiguration `env_file` innerhalb Ihrer Pydantic-`Settings`-Klasse und setzen den Wert auf den Dateinamen mit der dotenv-Datei, die wir verwenden möchten. + +### Die `Settings` nur einmal mittels `lru_cache` erstellen { #creating-the-settings-only-once-with-lru-cache } + +Das Lesen einer Datei von der Festplatte ist normalerweise ein kostspieliger (langsamer) Vorgang, daher möchten Sie ihn wahrscheinlich nur einmal ausführen und dann dasselbe Einstellungsobjekt erneut verwenden, anstatt es für jeden Request zu lesen. + +Aber jedes Mal, wenn wir ausführen: + +```Python +Settings() +``` + +würde ein neues `Settings`-Objekt erstellt und bei der Erstellung würde die `.env`-Datei erneut ausgelesen. + +Wenn die Abhängigkeitsfunktion wie folgt wäre: + +```Python +def get_settings(): + return Settings() +``` + +würden wir dieses Objekt für jeden Request erstellen und die `.env`-Datei für jeden Request lesen. ⚠️ + +Da wir jedoch den `@lru_cache`-Dekorator oben verwenden, wird das `Settings`-Objekt nur einmal erstellt, nämlich beim ersten Aufruf. ✔️ + +{* ../../docs_src/settings/app03_an_py310/main.py hl[1,11] *} + +Dann wird bei allen nachfolgenden Aufrufen von `get_settings()`, in den Abhängigkeiten für darauffolgende Requests, dasselbe Objekt zurückgegeben, das beim ersten Aufruf zurückgegeben wurde, anstatt den Code von `get_settings()` erneut auszuführen und ein neues `Settings`-Objekt zu erstellen. + +#### Technische Details zu `lru_cache` { #lru-cache-technical-details } + +`@lru_cache` ändert die Funktion, die es dekoriert, dahingehend, denselben Wert zurückzugeben, der beim ersten Mal zurückgegeben wurde, anstatt ihn erneut zu berechnen und den Code der Funktion jedes Mal auszuführen. + +Die darunter liegende Funktion wird also für jede Argumentkombination einmal ausgeführt. Und dann werden die von jeder dieser Argumentkombinationen zurückgegebenen Werte immer wieder verwendet, wenn die Funktion mit genau derselben Argumentkombination aufgerufen wird. + +Wenn Sie beispielsweise eine Funktion haben: + +```Python +@lru_cache +def say_hi(name: str, salutation: str = "Ms."): + return f"Hello {salutation} {name}" +``` + +könnte Ihr Programm so ausgeführt werden: + +```mermaid +sequenceDiagram + +participant code as Code +participant function as say_hi() +participant execute as Funktion ausführen + + rect rgba(0, 255, 0, .1) + code ->> function: say_hi(name="Camila") + function ->> execute: führe Code der Funktion aus + execute ->> code: gib das Resultat zurück + end + + rect rgba(0, 255, 255, .1) + code ->> function: say_hi(name="Camila") + function ->> code: gib das gespeicherte Resultat zurück + end + + rect rgba(0, 255, 0, .1) + code ->> function: say_hi(name="Rick") + function ->> execute: führe Code der Funktion aus + execute ->> code: gib das Resultat zurück + end + + rect rgba(0, 255, 0, .1) + code ->> function: say_hi(name="Rick", salutation="Mr.") + function ->> execute: führe Code der Funktion aus + execute ->> code: gib das Resultat zurück + end + + rect rgba(0, 255, 255, .1) + code ->> function: say_hi(name="Rick") + function ->> code: gib das gespeicherte Resultat zurück + end + + rect rgba(0, 255, 255, .1) + code ->> function: say_hi(name="Camila") + function ->> code: gib das gespeicherte Resultat zurück + end +``` + +Im Fall unserer Abhängigkeit `get_settings()` akzeptiert die Funktion nicht einmal Argumente, sodass sie immer den gleichen Wert zurückgibt. + +Auf diese Weise verhält es sich fast so, als wäre es nur eine globale Variable. Da es jedoch eine Abhängigkeitsfunktion verwendet, können wir diese zu Testzwecken problemlos überschreiben. + +`@lru_cache` ist Teil von `functools`, welches Teil von Pythons Standardbibliothek ist. Weitere Informationen dazu finden Sie in der [Python-Dokumentation für `@lru_cache`](https://docs.python.org/3/library/functools.html#functools.lru_cache). + +## Zusammenfassung { #recap } + +Mit Pydantic Settings können Sie die Einstellungen oder Konfigurationen für Ihre Anwendung verwalten und dabei die gesamte Leistungsfähigkeit der Pydantic-Modelle nutzen. + +* Durch die Verwendung einer Abhängigkeit können Sie das Testen vereinfachen. +* Sie können `.env`-Dateien damit verwenden. +* Durch die Verwendung von `@lru_cache` können Sie vermeiden, die dotenv-Datei bei jedem Request erneut zu lesen, während Sie sie während des Testens überschreiben können. diff --git a/docs/de/docs/advanced/stream-data.md b/docs/de/docs/advanced/stream-data.md new file mode 100644 index 0000000000000..16ff73e7819a8 --- /dev/null +++ b/docs/de/docs/advanced/stream-data.md @@ -0,0 +1,117 @@ +# Daten streamen { #stream-data } + +Wenn Sie Daten streamen möchten, die als JSON strukturiert werden können, sollten Sie [JSON Lines streamen](../tutorial/stream-json-lines.md). + +Wenn Sie jedoch **reine Binärdaten** oder Strings streamen möchten, so können Sie es machen. + +/// note | Hinweis + +Hinzugefügt in FastAPI 0.134.0. + +/// + +## Anwendungsfälle { #use-cases } + +Sie könnten dies verwenden, wenn Sie reine Strings streamen möchten, z. B. direkt aus der Ausgabe eines **AI-LLM**-Dienstes. + +Sie könnten es auch nutzen, um **große Binärdateien** zu streamen, wobei Sie jeden Datenchunk beim Lesen streamen, ohne alles auf einmal in den Speicher laden zu müssen. + +Sie könnten auf diese Weise auch **Video** oder **Audio** streamen, es könnte sogar beim Verarbeiten erzeugt und gesendet werden. + +## Eine `StreamingResponse` mit `yield` { #a-streamingresponse-with-yield } + +Wenn Sie in Ihrer *Pfadoperation-Funktion* ein `response_class=StreamingResponse` deklarieren, können Sie `yield` verwenden, um nacheinander jeden Datenchunk zu senden. + +{* ../../docs_src/stream_data/tutorial001_py310.py ln[1:23] hl[20,23] *} + +FastAPI übergibt jeden Datenchunk unverändert an die `StreamingResponse`, es wird nicht versucht, ihn in JSON oder etwas Ähnliches zu konvertieren. + +### Nicht-async-*Pfadoperation-Funktionen* { #non-async-path-operation-functions } + +Sie können auch reguläre `def`-Funktionen (ohne `async`) verwenden und `yield` auf die gleiche Weise einsetzen. + +{* ../../docs_src/stream_data/tutorial001_py310.py ln[26:29] hl[27] *} + +### Keine Annotation { #no-annotation } + +Sie müssen den Rückgabetyp für das Streamen von Binärdaten nicht wirklich annotieren. + +Da FastAPI die Daten nicht mit Pydantic in JSON umzuwandeln oder sie anderweitig zu serialisieren versucht, ist die Typannotation hier nur für Ihren Editor und Tools relevant, sie wird von FastAPI nicht verwendet. + +{* ../../docs_src/stream_data/tutorial001_py310.py ln[32:35] hl[33] *} + +Das bedeutet auch, dass Sie mit `StreamingResponse` die **Freiheit** und **Verantwortung** haben, die Datenbytes genau so zu erzeugen und zu encodieren, wie sie gesendet werden sollen, unabhängig von den Typannotationen. 🤓 + +### Bytes streamen { #stream-bytes } + +Einer der Hauptanwendungsfälle wäre, `bytes` statt Strings zu streamen, das können Sie selbstverständlich tun. + +{* ../../docs_src/stream_data/tutorial001_py310.py ln[44:47] hl[47] *} + +## Eine benutzerdefinierte `PNGStreamingResponse` { #a-custom-pngstreamingresponse } + +In den obigen Beispielen wurden die Datenbytes gestreamt, aber die Response hatte keinen `Content-Type`-Header, sodass der Client nicht wusste, welchen Datentyp er erhielt. + +Sie können eine benutzerdefinierte Unterklasse von `StreamingResponse` erstellen, die den `Content-Type`-Header auf den Typ der gestreamten Daten setzt. + +Zum Beispiel können Sie eine `PNGStreamingResponse` erstellen, die den `Content-Type`-Header mit dem Attribut `media_type` auf `image/png` setzt: + +{* ../../docs_src/stream_data/tutorial002_py310.py ln[6,19:20] hl[20] *} + +Dann können Sie diese neue Klasse mit `response_class=PNGStreamingResponse` in Ihrer *Pfadoperation-Funktion* verwenden: + +{* ../../docs_src/stream_data/tutorial002_py310.py ln[23:27] hl[23] *} + +### Eine Datei simulieren { #simulate-a-file } + +In diesem Beispiel simulieren wir eine Datei mit `io.BytesIO`, einem dateiähnlichen Objekt, das nur im Speicher lebt, uns aber dieselbe Schnittstelle nutzen lässt. + +Wir können z. B. darüber iterieren, um seinen Inhalt zu konsumieren, so wie bei einer Datei. + +{* ../../docs_src/stream_data/tutorial002_py310.py ln[1:27] hl[3,12:13,25] *} + +/// note | Technische Details + +Die anderen beiden Variablen, `image_base64` und `binary_image`, sind ein in Base64 encodiertes Bild, dann in Bytes konvertiert, um es anschließend an `io.BytesIO` zu übergeben. + +Nur damit es in derselben Datei leben kann, für dieses Beispiel, und Sie es unverändert kopieren und ausführen können. 🥚 + +/// + +Mit einem `with`-Block stellen wir sicher, dass das dateiähnliche Objekt geschlossen wird, nachdem die Generatorfunktion (die Funktion mit `yield`) fertig ist. Also nachdem die Response gesendet wurde. + +In diesem speziellen Beispiel wäre das nicht so wichtig, weil es sich um eine unechte In-Memory-Datei (mit `io.BytesIO`) handelt, aber bei einer echten Datei wäre es wichtig sicherzustellen, dass die Datei nach der Arbeit damit geschlossen wird. + +### Dateien und Async { #files-and-async } + +In den meisten Fällen sind dateiähnliche Objekte standardmäßig nicht mit async und await kompatibel. + +Beispielsweise haben sie kein `await file.read()` oder `async for chunk in file`. + +Und in vielen Fällen wäre das Lesen eine blockierende Operation (die die Event-Loop blockieren könnte), weil von der Festplatte oder aus dem Netzwerk gelesen wird. + +/// note | Hinweis + +Das obige Beispiel ist tatsächlich eine Ausnahme, weil sich das `io.BytesIO`-Objekt bereits im Speicher befindet, daher blockiert sein Lesen nichts. + +Aber in vielen Fällen würde das Lesen einer Datei oder eines dateiähnlichen Objekts blockieren. + +/// + +Um die Event-Loop nicht zu blockieren, können Sie die *Pfadoperation-Funktion* einfach mit normalem `def` statt `async def` deklarieren, dadurch führt FastAPI sie in einem Threadpool-Worker aus, um die Haupt-Event-Loop nicht zu blockieren. + +{* ../../docs_src/stream_data/tutorial002_py310.py ln[30:34] hl[31] *} + +/// tip | Tipp + +Wenn Sie blockierenden Code aus einer async-Funktion heraus aufrufen müssen, oder eine async-Funktion aus einer blockierenden Funktion, könnten Sie [Asyncer](https://asyncer.tiangolo.com), eine Schwesterbibliothek zu FastAPI, verwenden. + +/// + +### `yield from` { #yield-from } + +Wenn Sie über etwas iterieren, z. B. ein dateiähnliches Objekt, und dann für jedes Element `yield` verwenden, könnten Sie auch `yield from` verwenden, um jedes Element direkt weiterzugeben und die `for`-Schleife zu sparen. + +Das ist nichts Spezifisches an FastAPI, das ist einfach Python, aber ein netter Trick. 😎 + +{* ../../docs_src/stream_data/tutorial002_py310.py ln[37:40] hl[40] *} diff --git a/docs/de/docs/advanced/strict-content-type.md b/docs/de/docs/advanced/strict-content-type.md new file mode 100644 index 0000000000000..db9ab9f24210e --- /dev/null +++ b/docs/de/docs/advanced/strict-content-type.md @@ -0,0 +1,88 @@ +# Strikte Content-Type-Prüfung { #strict-content-type-checking } + +Standardmäßig verwendet **FastAPI** eine strikte Prüfung des `Content-Type`-Headers für JSON-Requestbodys. Das bedeutet, dass JSON-Requests einen gültigen `Content-Type`-Header (z. B. `application/json`) enthalten MÜSSEN, damit der Body als JSON geparst wird. + +## CSRF-Risiko { #csrf-risk } + +Dieses Standardverhalten schützt vor einer Klasse von **Cross-Site Request Forgery (CSRF)**-Angriffen in einem sehr spezifischen Szenario. + +Diese Angriffe nutzen aus, dass Browser Skripte Requests senden lassen, ohne einen CORS-Preflight-Check durchzuführen, wenn sie: + +* keinen `Content-Type`-Header haben (z. B. mit `fetch()` und einem `Blob`-Body) +* und keine Authentifizierungsdaten senden. + +Diese Art von Angriff ist vor allem relevant, wenn: + +* die Anwendung lokal läuft (z. B. auf `localhost`) oder in einem internen Netzwerk +* und die Anwendung keine Authentifizierung hat, sondern erwartet, dass jeder Request aus demselben Netzwerk vertrauenswürdig ist. + +## Beispielangriff { #example-attack } + +Stellen Sie sich vor, Sie bauen eine Möglichkeit, lokal einen KI-Agenten auszuführen. + +Er stellt eine API bereit unter + +``` +http://localhost:8000/v1/agents/multivac +``` + +Es gibt auch ein Frontend unter + +``` +http://localhost:8000 +``` + +/// tip | Tipp + +Beachten Sie, dass beide denselben Host haben. + +/// + +Dann können Sie über das Frontend den KI-Agenten Dinge in Ihrem Namen erledigen lassen. + +Da er **lokal** läuft und nicht im offenen Internet, entscheiden Sie sich, **keine Authentifizierung** einzurichten und vertrauen stattdessen einfach auf den Zugriff im lokalen Netzwerk. + +Dann könnte einer Ihrer Benutzer es installieren und lokal ausführen. + +Anschließend könnte er eine bösartige Website öffnen, z. B. so etwas wie + +``` +https://evilhackers.example.com +``` + +Und diese bösartige Website sendet Requests mit `fetch()` und einem `Blob`-Body an die lokale API unter + +``` +http://localhost:8000/v1/agents/multivac +``` + +Obwohl der Host der bösartigen Website und der lokalen App unterschiedlich ist, löst der Browser keinen CORS-Preflight-Request aus, weil: + +* sie ohne Authentifizierung läuft, es müssen keine Credentials gesendet werden. +* der Browser annimmt, dass kein JSON gesendet wird (wegen des fehlenden `Content-Type`-Headers). + +Dann könnte die bösartige Website den lokalen KI-Agenten dazu bringen, wütende Nachrichten an den Ex-Chef des Benutzers zu schicken ... oder Schlimmeres. 😅 + +## Offenes Internet { #open-internet } + +Wenn Ihre App im offenen Internet läuft, würden Sie nicht „dem Netzwerk vertrauen“ und jedem erlauben, privilegierte Requests ohne Authentifizierung zu senden. + +Angreifer könnten einfach ein Skript ausführen, um Requests an Ihre API zu senden, es ist keine Browserinteraktion nötig. Daher sichern Sie wahrscheinlich schon alle privilegierten Endpunkte. + +In diesem Fall gilt **dieser Angriff / dieses Risiko nicht für Sie**. + +Dieses Risiko und dieser Angriff sind vor allem relevant, wenn die App im **lokalen Netzwerk** läuft und das die **einzige angenommene Schutzmaßnahme** ist. + +## Requests ohne Content-Type erlauben { #allowing-requests-without-content-type } + +Wenn Sie Clients unterstützen müssen, die keinen `Content-Type`-Header senden, können Sie die strikte Prüfung deaktivieren, indem Sie `strict_content_type=False` setzen: + +{* ../../docs_src/strict_content_type/tutorial001_py310.py hl[4] *} + +Mit dieser Einstellung werden Requests ohne `Content-Type`-Header im Body als JSON geparst. Das entspricht dem Verhalten älterer FastAPI-Versionen. + +/// note | Hinweis + +Dieses Verhalten und diese Konfiguration wurden in FastAPI 0.132.0 hinzugefügt. + +/// diff --git a/docs/de/docs/advanced/sub-applications.md b/docs/de/docs/advanced/sub-applications.md new file mode 100644 index 0000000000000..206ee7b4996aa --- /dev/null +++ b/docs/de/docs/advanced/sub-applications.md @@ -0,0 +1,67 @@ +# Unteranwendungen – Mounts { #sub-applications-mounts } + +Wenn Sie zwei unabhängige FastAPI-Anwendungen mit deren eigenen unabhängigen OpenAPI und deren eigenen Dokumentationsoberflächen benötigen, können Sie eine Hauptanwendung haben und dann eine (oder mehrere) Unteranwendung(en) „mounten“. + +## Eine **FastAPI**-Anwendung mounten { #mounting-a-fastapi-application } + +„Mounten“ („Einhängen“) bedeutet das Hinzufügen einer völlig „unabhängigen“ Anwendung an einem bestimmten Pfad, die sich dann um die Handhabung aller unter diesem Pfad liegenden _Pfadoperationen_ kümmert, welche in dieser Unteranwendung deklariert sind. + +### Hauptanwendung { #top-level-application } + +Erstellen Sie zunächst die Hauptanwendung **FastAPI** und deren *Pfadoperationen*: + +{* ../../docs_src/sub_applications/tutorial001_py310.py hl[3, 6:8] *} + +### Unteranwendung { #sub-application } + +Erstellen Sie dann Ihre Unteranwendung und deren *Pfadoperationen*. + +Diese Unteranwendung ist nur eine weitere Standard-FastAPI-Anwendung, aber diese wird „gemountet“: + +{* ../../docs_src/sub_applications/tutorial001_py310.py hl[11, 14:16] *} + +### Die Unteranwendung mounten { #mount-the-sub-application } + +Mounten Sie in Ihrer Top-Level-Anwendung `app` die Unteranwendung `subapi`. + +In diesem Fall wird sie im Pfad `/subapi` gemountet: + +{* ../../docs_src/sub_applications/tutorial001_py310.py hl[11, 19] *} + +### Die automatische API-Dokumentation testen { #check-the-automatic-api-docs } + +Führen Sie nun den Befehl `fastapi` aus: + +
+ +```console +$ fastapi dev + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +Und öffnen Sie die Dokumentation unter [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs). + +Sie sehen die automatische API-Dokumentation für die Hauptanwendung, welche nur deren eigene _Pfadoperationen_ anzeigt: + + + +Öffnen Sie dann die Dokumentation für die Unteranwendung unter [http://127.0.0.1:8000/subapi/docs](http://127.0.0.1:8000/subapi/docs). + +Sie sehen die automatische API-Dokumentation für die Unteranwendung, welche nur deren eigene _Pfadoperationen_ anzeigt, alle unter dem korrekten Unterpfad-Präfix `/subapi`: + + + +Wenn Sie versuchen, mit einer der beiden Benutzeroberflächen zu interagieren, funktionieren diese ordnungsgemäß, da der Browser mit jeder spezifischen Anwendung oder Unteranwendung kommunizieren kann. + +### Technische Details: `root_path` { #technical-details-root-path } + +Wenn Sie eine Unteranwendung wie oben beschrieben mounten, kümmert sich FastAPI darum, den Mount-Pfad für die Unteranwendung zu kommunizieren, mithilfe eines Mechanismus aus der ASGI-Spezifikation namens `root_path`. + +Auf diese Weise weiß die Unteranwendung, dass sie dieses Pfadpräfix für die Benutzeroberfläche der Dokumentation verwenden soll. + +Und die Unteranwendung könnte auch ihre eigenen gemounteten Unteranwendungen haben und alles würde korrekt funktionieren, da FastAPI sich um alle diese `root_path`s automatisch kümmert. + +Mehr über den `root_path` und dessen explizite Verwendung erfahren Sie im Abschnitt [Hinter einem Proxy](behind-a-proxy.md). diff --git a/docs/de/docs/advanced/templates.md b/docs/de/docs/advanced/templates.md new file mode 100644 index 0000000000000..218b0437e436c --- /dev/null +++ b/docs/de/docs/advanced/templates.md @@ -0,0 +1,126 @@ +# Templates { #templates } + +Sie können jede gewünschte Template-Engine mit **FastAPI** verwenden. + +Eine häufige Wahl ist Jinja2, dasselbe, was auch von Flask und anderen Tools verwendet wird. + +Es gibt Werkzeuge zur einfachen Konfiguration, die Sie direkt in Ihrer **FastAPI**-Anwendung verwenden können (bereitgestellt von Starlette). + +## Abhängigkeiten installieren { #install-dependencies } + +Stellen Sie sicher, dass Sie eine [virtuelle Umgebung](../virtual-environments.md) erstellen, sie aktivieren und `jinja2` installieren: + +
+ +```console +$ pip install jinja2 + +---> 100% +``` + +
+ +## `Jinja2Templates` verwenden { #using-jinja2templates } + +* Importieren Sie `Jinja2Templates`. +* Erstellen Sie ein `templates`-Objekt, das Sie später wiederverwenden können. +* Deklarieren Sie einen `Request`-Parameter in der *Pfadoperation*, welcher ein Template zurückgibt. +* Verwenden Sie die von Ihnen erstellten `templates`, um eine `TemplateResponse` zu rendern und zurückzugeben, übergeben Sie den Namen des Templates, das Requestobjekt und ein „Kontext“-Dictionary mit Schlüssel-Wert-Paaren, die innerhalb des Jinja2-Templates verwendet werden sollen. + +{* ../../docs_src/templates/tutorial001_py310.py hl[4,11,15:18] *} + +/// note | Hinweis + +Vor FastAPI 0.108.0 und Starlette 0.29.0 war `name` der erste Parameter. + +Außerdem wurde in früheren Versionen das `request`-Objekt als Teil der Schlüssel-Wert-Paare im Kontext für Jinja2 übergeben. + +/// + +/// tip | Tipp + +Durch die Deklaration von `response_class=HTMLResponse` kann die Dokumentationsoberfläche erkennen, dass die Response HTML sein wird. + +/// + +/// note | Technische Details + +Sie können auch `from starlette.templating import Jinja2Templates` verwenden. + +**FastAPI** bietet dasselbe `starlette.templating` auch via `fastapi.templating` an, als Annehmlichkeit für Sie, den Entwickler. Aber die meisten der verfügbaren Responses kommen direkt von Starlette. Das Gleiche gilt für `Request` und `StaticFiles`. + +/// + +## Templates erstellen { #writing-templates } + +Dann können Sie unter `templates/item.html` ein Template erstellen, mit z. B. folgendem Inhalt: + +```jinja hl_lines="7" +{!../../docs_src/templates/templates/item.html!} +``` + +### Template-Kontextwerte { #template-context-values } + +Im HTML, welches enthält: + +{% raw %} + +```jinja +Item ID: {{ id }} +``` + +{% endraw %} + +... wird die `id` angezeigt, welche dem „Kontext“-`dict` entnommen wird, welches Sie übergeben haben: + +```Python +{"id": id} +``` + +Mit beispielsweise einer ID `42` würde das wie folgt gerendert werden: + +```html +Item ID: 42 +``` + +### Template-`url_for`-Argumente { #template-url-for-arguments } + +Sie können `url_for()` auch innerhalb des Templates verwenden, es nimmt als Argumente dieselben Argumente, die von Ihrer *Pfadoperation-Funktion* verwendet werden. + +Der Abschnitt mit: + +{% raw %} + +```jinja + +``` + +{% endraw %} + +... generiert also einen Link zu derselben URL, welche von der *Pfadoperation-Funktion* `read_item(id=id)` gehandhabt werden würde. + +Mit beispielsweise der ID `42` würde dies Folgendes ergeben: + +```html + +``` + +## Templates und statische Dateien { #templates-and-static-files } + +Sie können `url_for()` innerhalb des Templates auch beispielsweise mit den `StaticFiles` verwenden, die Sie mit `name="static"` gemountet haben. + +```jinja hl_lines="4" +{!../../docs_src/templates/templates/item.html!} +``` + +In diesem Beispiel würde das zu einer CSS-Datei unter `static/styles.css` verlinken, mit folgendem Inhalt: + +```CSS hl_lines="4" +{!../../docs_src/templates/static/styles.css!} +``` + +Und da Sie `StaticFiles` verwenden, wird diese CSS-Datei automatisch von Ihrer **FastAPI**-Anwendung unter der URL `/static/styles.css` ausgeliefert. + +## Mehr Details { #more-details } + +Weitere Informationen, einschließlich, wie man Templates testet, finden Sie in [Starlettes Dokumentation zu Templates](https://www.starlette.dev/templates/). diff --git a/docs/de/docs/advanced/testing-dependencies.md b/docs/de/docs/advanced/testing-dependencies.md new file mode 100644 index 0000000000000..4fc653f775ac2 --- /dev/null +++ b/docs/de/docs/advanced/testing-dependencies.md @@ -0,0 +1,54 @@ +# Testen mit Überschreibungen für Abhängigkeiten { #testing-dependencies-with-overrides } + +## Abhängigkeiten beim Testen überschreiben { #overriding-dependencies-during-testing } + +Es gibt einige Szenarien, in denen Sie beim Testen möglicherweise eine Abhängigkeit überschreiben möchten. + +Sie möchten nicht, dass die ursprüngliche Abhängigkeit ausgeführt wird (und auch keine der möglicherweise vorhandenen Unterabhängigkeiten). + +Stattdessen möchten Sie eine andere Abhängigkeit bereitstellen, die nur während Tests (möglicherweise nur bei einigen bestimmten Tests) verwendet wird und einen Wert bereitstellt, der dort verwendet werden kann, wo der Wert der ursprünglichen Abhängigkeit verwendet wurde. + +### Anwendungsfälle: Externer Service { #use-cases-external-service } + +Ein Beispiel könnte sein, dass Sie einen externen Authentifizierungsanbieter haben, mit dem Sie sich verbinden müssen. + +Sie senden ihm ein Token und er gibt einen authentifizierten Benutzer zurück. + +Dieser Anbieter berechnet Ihnen möglicherweise Gebühren pro Request, und der Aufruf könnte etwas länger dauern, als wenn Sie einen vordefinierten Mock-Benutzer für Tests hätten. + +Sie möchten den externen Anbieter wahrscheinlich einmal testen, ihn aber nicht unbedingt bei jedem weiteren ausgeführten Test aufrufen. + +In diesem Fall können Sie die Abhängigkeit, die diesen Anbieter aufruft, überschreiben und eine benutzerdefinierte Abhängigkeit verwenden, die einen Mock-Benutzer zurückgibt, nur für Ihre Tests. + +### Das Attribut `app.dependency_overrides` verwenden { #use-the-app-dependency-overrides-attribute } + +Für diese Fälle verfügt Ihre **FastAPI**-Anwendung über das Attribut `app.dependency_overrides`, bei diesem handelt sich um ein einfaches `dict`. + +Um eine Abhängigkeit für das Testen zu überschreiben, geben Sie als Schlüssel die ursprüngliche Abhängigkeit (eine Funktion) und als Wert Ihre Überschreibung der Abhängigkeit (eine andere Funktion) ein. + +Und dann ruft **FastAPI** diese Überschreibung anstelle der ursprünglichen Abhängigkeit auf. + +{* ../../docs_src/dependency_testing/tutorial001_an_py310.py hl[26:27,30] *} + +/// tip | Tipp + +Sie können eine Überschreibung für eine Abhängigkeit festlegen, die an einer beliebigen Stelle in Ihrer **FastAPI**-Anwendung verwendet wird. + +Die ursprüngliche Abhängigkeit könnte in einer *Pfadoperation-Funktion*, einem *Pfadoperation-Dekorator* (wenn Sie den Rückgabewert nicht verwenden), einem `.include_router()`-Aufruf, usw. verwendet werden. + +FastAPI kann sie in jedem Fall überschreiben. + +/// + +Anschließend können Sie Ihre Überschreibungen zurücksetzen (entfernen), indem Sie `app.dependency_overrides` auf ein leeres `dict` setzen: + +```Python +app.dependency_overrides = {} +``` + + +/// tip | Tipp + +Wenn Sie eine Abhängigkeit nur während einiger Tests überschreiben möchten, können Sie die Überschreibung zu Beginn des Tests (innerhalb der Testfunktion) festlegen und am Ende (am Ende der Testfunktion) zurücksetzen. + +/// diff --git a/docs/de/docs/advanced/testing-events.md b/docs/de/docs/advanced/testing-events.md new file mode 100644 index 0000000000000..053aeffc8a2ba --- /dev/null +++ b/docs/de/docs/advanced/testing-events.md @@ -0,0 +1,12 @@ +# Events testen: Lifespan und Startup – Shutdown { #testing-events-lifespan-and-startup-shutdown } + +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_py310.py hl[9:15,18,27:28,30:32,41:43] *} + + +Sie können mehr Details unter [„Lifespan in Tests ausführen in der offiziellen Starlette-Dokumentation.“](https://www.starlette.dev/lifespan/#running-lifespan-in-tests) nachlesen. + +Für die deprecateten Events `startup` und `shutdown` können Sie den `TestClient` wie folgt verwenden: + +{* ../../docs_src/app_testing/tutorial003_py310.py hl[9:12,20:24] *} diff --git a/docs/de/docs/advanced/testing-websockets.md b/docs/de/docs/advanced/testing-websockets.md new file mode 100644 index 0000000000000..3c06f193887f8 --- /dev/null +++ b/docs/de/docs/advanced/testing-websockets.md @@ -0,0 +1,13 @@ +# WebSockets testen { #testing-websockets } + +Sie können denselben `TestClient` zum Testen von WebSockets verwenden. + +Dazu verwenden Sie den `TestClient` in einer `with`-Anweisung, eine Verbindung zum WebSocket herstellend: + +{* ../../docs_src/app_testing/tutorial002_py310.py hl[27:31] *} + +/// note | Hinweis + +Weitere Informationen finden Sie in Starlettes Dokumentation zum [Testen von WebSockets](https://www.starlette.dev/testclient/#testing-websocket-sessions). + +/// diff --git a/docs/de/docs/advanced/using-request-directly.md b/docs/de/docs/advanced/using-request-directly.md new file mode 100644 index 0000000000000..623ddbb4bb099 --- /dev/null +++ b/docs/de/docs/advanced/using-request-directly.md @@ -0,0 +1,56 @@ +# Den Request direkt verwenden { #using-the-request-directly } + +Bisher haben Sie die Teile des Requests, die Sie benötigen, mithilfe von deren Typen deklariert. + +Daten nehmend von: + +* Dem Pfad als Parameter. +* Headern. +* Cookies. +* usw. + +Und indem Sie das tun, validiert **FastAPI** diese Daten, konvertiert sie und generiert automatisch Dokumentation für Ihre API. + +Es gibt jedoch Situationen, in denen Sie möglicherweise direkt auf das `Request`-Objekt zugreifen müssen. + +## Details zum `Request`-Objekt { #details-about-the-request-object } + +Da **FastAPI** unter der Haube eigentlich **Starlette** ist, mit einer Ebene von mehreren Tools darüber, können Sie Starlettes [`Request`](https://www.starlette.dev/requests/)-Objekt direkt verwenden, wenn Sie es benötigen. + +Das bedeutet allerdings auch, dass, wenn Sie Daten direkt vom `Request`-Objekt nehmen (z. B. dessen Body lesen), diese von FastAPI nicht validiert, konvertiert oder dokumentiert werden (mit OpenAPI, für die automatische API-Benutzeroberfläche). + +Obwohl jeder andere normal deklarierte Parameter (z. B. der Body, mit einem Pydantic-Modell) dennoch validiert, konvertiert, annotiert, usw. werden würde. + +Es gibt jedoch bestimmte Fälle, in denen es nützlich ist, auf das `Request`-Objekt zuzugreifen. + +## Das `Request`-Objekt direkt verwenden { #use-the-request-object-directly } + +Angenommen, Sie möchten auf die IP-Adresse/den Host des Clients in Ihrer *Pfadoperation-Funktion* zugreifen. + +Dazu müssen Sie direkt auf den Request zugreifen. + +{* ../../docs_src/using_request_directly/tutorial001_py310.py hl[1,7:8] *} + +Durch die Deklaration eines *Pfadoperation-Funktionsparameters*, dessen Typ der `Request` ist, weiß **FastAPI**, dass es den `Request` diesem Parameter übergeben soll. + +/// tip | Tipp + +Beachten Sie, dass wir in diesem Fall einen Pfad-Parameter zusätzlich zum Request-Parameter deklarieren. + +Der Pfad-Parameter wird also extrahiert, validiert, in den spezifizierten Typ konvertiert und mit OpenAPI annotiert. + +Auf die gleiche Weise können Sie wie gewohnt jeden anderen Parameter deklarieren und zusätzlich auch den `Request` erhalten. + +/// + +## `Request`-Dokumentation { #request-documentation } + +Weitere Details zum [`Request`-Objekt auf der offiziellen Starlette-Dokumentationsseite](https://www.starlette.dev/requests/). + +/// note | Technische Details + +Sie können auch `from starlette.requests import Request` verwenden. + +**FastAPI** stellt es direkt zur Verfügung, als Komfort für Sie, den Entwickler. Es kommt aber direkt von Starlette. + +/// diff --git a/docs/de/docs/advanced/websockets.md b/docs/de/docs/advanced/websockets.md new file mode 100644 index 0000000000000..a0f3a1f332222 --- /dev/null +++ b/docs/de/docs/advanced/websockets.md @@ -0,0 +1,186 @@ +# WebSockets { #websockets } + +Sie können [WebSockets](https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API) mit **FastAPI** verwenden. + +## `websockets` installieren { #install-websockets } + +Stellen Sie sicher, dass Sie eine [virtuelle Umgebung](../virtual-environments.md) erstellen, sie aktivieren und `websockets` installieren (eine Python-Bibliothek, die die Verwendung des „WebSocket“-Protokolls erleichtert): + +
+ +```console +$ pip install websockets + +---> 100% +``` + +
+ +## WebSockets-Client { #websockets-client } + +### In Produktion { #in-production } + +In Ihrem Produktionssystem haben Sie wahrscheinlich ein Frontend, das mit einem modernen Framework wie React, Vue.js oder Angular erstellt wurde. + +Und um über WebSockets mit Ihrem Backend zu kommunizieren, würden Sie wahrscheinlich die Werkzeuge Ihres Frontends verwenden. + +Oder Sie verfügen möglicherweise über eine native Mobile-Anwendung, die direkt in nativem Code mit Ihrem WebSocket-Backend kommuniziert. + +Oder Sie haben andere Möglichkeiten, mit dem WebSocket-Endpunkt zu kommunizieren. + +--- + +Für dieses Beispiel verwenden wir jedoch ein sehr einfaches HTML-Dokument mit etwas JavaScript, alles in einem langen String. + +Das ist natürlich nicht optimal und man würde das nicht in der Produktion machen. + +In der Produktion hätten Sie eine der oben genannten Optionen. + +Aber es ist der einfachste Weg, sich auf die Serverseite von WebSockets zu konzentrieren und ein funktionierendes Beispiel zu haben: + +{* ../../docs_src/websockets_/tutorial001_py310.py hl[2,6:38,41:43] *} + +## Einen `websocket` erstellen { #create-a-websocket } + +Erstellen Sie in Ihrer **FastAPI**-Anwendung einen `websocket`: + +{* ../../docs_src/websockets_/tutorial001_py310.py hl[1,46:47] *} + +/// note | Technische Details + +Sie könnten auch `from starlette.websockets import WebSocket` verwenden. + +**FastAPI** stellt den gleichen `WebSocket` direkt zur Verfügung, als Annehmlichkeit für Sie, den Entwickler. Er kommt aber direkt von Starlette. + +/// + +## Nachrichten erwarten und Nachrichten senden { #await-for-messages-and-send-messages } + +In Ihrer WebSocket-Route können Sie Nachrichten `await`en und Nachrichten senden. + +{* ../../docs_src/websockets_/tutorial001_py310.py hl[48:52] *} + +Sie können Binär-, Text- und JSON-Daten empfangen und senden. + +## Es ausprobieren { #try-it } + +Legen Sie Ihren Code in einer Datei `main.py` ab und führen Sie dann Ihre Anwendung aus: + +
+ +```console +$ fastapi dev + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +Öffnen Sie Ihren Browser unter [http://127.0.0.1:8000](http://127.0.0.1:8000). + +Sie sehen eine einfache Seite wie: + + + +Sie können Nachrichten in das Eingabefeld tippen und absenden: + + + +Und Ihre **FastAPI**-Anwendung mit WebSockets antwortet: + + + +Sie können viele Nachrichten senden (und empfangen): + + + +Und alle verwenden dieselbe WebSocket-Verbindung. + +## Verwendung von `Depends` und anderen { #using-depends-and-others } + +In WebSocket-Endpunkten können Sie Folgendes aus `fastapi` importieren und verwenden: + +* `Depends` +* `Security` +* `Cookie` +* `Header` +* `Path` +* `Query` + +Diese funktionieren auf die gleiche Weise wie für andere FastAPI-Endpunkte/*Pfadoperationen*: + +{* ../../docs_src/websockets_/tutorial002_an_py310.py hl[68:69,82] *} + +/// note | Hinweis + +Da es sich um einen WebSocket handelt, macht es keinen Sinn, eine `HTTPException` auszulösen, stattdessen lösen wir eine `WebSocketException` aus. + +Sie können einen „Closing“-Code verwenden, aus den [gültigen Codes, die in der Spezifikation definiert sind](https://tools.ietf.org/html/rfc6455#section-7.4.1). + +/// + +### WebSockets mit Abhängigkeiten ausprobieren { #try-the-websockets-with-dependencies } + +Führen Sie Ihre Anwendung aus: + +
+ +```console +$ fastapi dev + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +Öffnen Sie Ihren Browser unter [http://127.0.0.1:8000](http://127.0.0.1:8000). + +Dort können Sie einstellen: + +* Die „Item ID“, die im Pfad verwendet wird. +* Das „Token“, das als Query-Parameter verwendet wird. + +/// tip | Tipp + +Beachten Sie, dass die Query `token` von einer Abhängigkeit verarbeitet wird. + +/// + +Damit können Sie den WebSocket verbinden und dann Nachrichten senden und empfangen: + + + +## Verbindungsabbrüche und mehrere Clients handhaben { #handling-disconnections-and-multiple-clients } + +Wenn eine WebSocket-Verbindung geschlossen wird, löst `await websocket.receive_text()` eine `WebSocketDisconnect`-Exception aus, die Sie dann wie in folgendem Beispiel abfangen und behandeln können. + +{* ../../docs_src/websockets_/tutorial003_py310.py hl[79:81] *} + +Zum Ausprobieren: + +* Öffnen Sie die Anwendung mit mehreren Browser-Tabs. +* Schreiben Sie Nachrichten in den Tabs. +* Schließen Sie dann einen der Tabs. + +Das wird die Ausnahme `WebSocketDisconnect` auslösen und alle anderen Clients erhalten eine Nachricht wie: + +``` +Client #1596980209979 left the chat +``` + +/// tip | Tipp + +Die obige Anwendung ist ein minimales und einfaches Beispiel, das zeigt, wie Nachrichten verarbeitet und an mehrere WebSocket-Verbindungen gesendet werden. + +Beachten Sie jedoch, dass, da alles nur im Speicher in einer einzigen Liste verwaltet wird, es nur funktioniert, während der Prozess ausgeführt wird, und nur mit einem einzelnen Prozess. + +Wenn Sie etwas benötigen, das sich leicht in FastAPI integrieren lässt, aber robuster ist und von Redis, PostgreSQL und anderen unterstützt wird, sehen Sie sich [encode/broadcaster](https://github.com/encode/broadcaster) an. + +/// + +## Mehr Informationen { #more-info } + +Weitere Informationen zu Optionen finden Sie in der Dokumentation von Starlette: + +* [Die `WebSocket`-Klasse](https://www.starlette.dev/websockets/). +* [Klassen-basierte Handhabung von WebSockets](https://www.starlette.dev/endpoints/#websocketendpoint). diff --git a/docs/de/docs/advanced/wsgi.md b/docs/de/docs/advanced/wsgi.md new file mode 100644 index 0000000000000..353734a3a8002 --- /dev/null +++ b/docs/de/docs/advanced/wsgi.md @@ -0,0 +1,52 @@ +# WSGI inkludieren – Flask, Django und andere { #including-wsgi-flask-django-others } + + +Sie können WSGI-Anwendungen mounten, wie Sie es in [Unteranwendungen – Mounts](sub-applications.md), [Hinter einem Proxy](behind-a-proxy.md) gesehen haben. + +Dazu können Sie die `WSGIMiddleware` verwenden und damit Ihre WSGI-Anwendung wrappen, zum Beispiel Flask, Django usw. + +## `WSGIMiddleware` verwenden { #using-wsgimiddleware } + +/// note | Hinweis + +Dafür muss `a2wsgi` installiert sein, z. B. mit `pip install a2wsgi`. + +/// + +Sie müssen `WSGIMiddleware` aus `a2wsgi` importieren. + +Wrappen Sie dann die WSGI-Anwendung (z. B. Flask) mit der Middleware. + +Und dann mounten Sie das auf einem Pfad. + +{* ../../docs_src/wsgi/tutorial001_py310.py hl[1,3,23] *} + +/// note | Hinweis + +Früher wurde empfohlen, `WSGIMiddleware` aus `fastapi.middleware.wsgi` zu verwenden, dies ist jetzt deprecatet. + +Stattdessen wird empfohlen, das Paket `a2wsgi` zu verwenden. Die Nutzung bleibt gleich. + +Stellen Sie lediglich sicher, dass das Paket `a2wsgi` installiert ist und importieren Sie `WSGIMiddleware` korrekt aus `a2wsgi`. + +/// + +## Es testen { #check-it } + +Jetzt wird jeder Request unter dem Pfad `/v1/` von der Flask-Anwendung verarbeitet. + +Und der Rest wird von **FastAPI** gehandhabt. + +Wenn Sie das ausführen und auf [http://localhost:8000/v1/](http://localhost:8000/v1/) gehen, sehen Sie die Response von Flask: + +```txt +Hello, World from Flask! +``` + +Und wenn Sie auf [http://localhost:8000/v2](http://localhost:8000/v2) gehen, sehen Sie die Response von FastAPI: + +```JSON +{ + "message": "Hello World" +} +``` diff --git a/docs/de/docs/alternatives.md b/docs/de/docs/alternatives.md new file mode 100644 index 0000000000000..5a814cb5589d0 --- /dev/null +++ b/docs/de/docs/alternatives.md @@ -0,0 +1,485 @@ +# Alternativen, Inspiration und Vergleiche { #alternatives-inspiration-and-comparisons } + +Was hat **FastAPI** inspiriert, wie es sich im Vergleich zu Alternativen verhält und was es von ihnen gelernt hat. + +## Einführung { #intro } + +**FastAPI** würde ohne die frühere Arbeit anderer nicht existieren. + +Es wurden zuvor viele Tools entwickelt, die als Inspiration für seine Entwicklung dienten. + +Ich habe die Schaffung eines neuen Frameworks viele Jahre lang vermieden. Zuerst habe ich versucht, alle von **FastAPI** abgedeckten Funktionen mithilfe vieler verschiedener Frameworks, Plugins und Tools zu lösen. + +Aber irgendwann gab es keine andere Möglichkeit, als etwas zu schaffen, das all diese Funktionen bereitstellte, die besten Ideen früherer Tools aufnahm und diese auf die bestmögliche Weise kombinierte, wobei Sprachfunktionen verwendet wurden, die vorher noch nicht einmal verfügbar waren (Python 3.6+ Typhinweise). + +## Vorherige Tools { #previous-tools } + +### [Django](https://www.djangoproject.com/) { #django } + +Es ist das beliebteste Python-Framework und genießt großes Vertrauen. Es wird zum Aufbau von Systemen wie Instagram verwendet. + +Es ist relativ eng mit relationalen Datenbanken (wie MySQL oder PostgreSQL) gekoppelt, daher ist es nicht sehr einfach, eine NoSQL-Datenbank (wie Couchbase, MongoDB, Cassandra, usw.) als Hauptspeicherengine zu verwenden. + +Es wurde erstellt, um den HTML-Code im Backend zu generieren, nicht um APIs zu erstellen, die von einem modernen Frontend (wie React, Vue.js und Angular) oder von anderen Systemen (wie IoT-Geräten) verwendet werden, um mit ihm zu kommunizieren. + +### [Django REST Framework](https://www.django-rest-framework.org/) { #django-rest-framework } + +Das Django REST Framework wurde als flexibles Toolkit zum Erstellen von Web-APIs unter Verwendung von Django entwickelt, um dessen API-Möglichkeiten zu verbessern. + +Es wird von vielen Unternehmen verwendet, darunter Mozilla, Red Hat und Eventbrite. + +Es war eines der ersten Beispiele für **automatische API-Dokumentation**, und dies war insbesondere eine der ersten Ideen, welche „die Suche nach“ **FastAPI** inspirierten. + +/// note | Hinweis + +Das Django REST Framework wurde von Tom Christie erstellt. Derselbe Schöpfer von Starlette und Uvicorn, auf denen **FastAPI** basiert. + +/// + +/// tip | Inspirierte **FastAPI** dazu + +Eine automatische API-Dokumentationsoberfläche zu haben. + +/// + +### [Flask](https://flask.palletsprojects.com) { #flask } + +Flask ist ein „Mikroframework“, es enthält weder Datenbankintegration noch viele der Dinge, die standardmäßig in Django enthalten sind. + +Diese Einfachheit und Flexibilität ermöglichen beispielsweise die Verwendung von NoSQL-Datenbanken als Hauptdatenspeichersystem. + +Da es sehr einfach ist, ist es relativ intuitiv zu erlernen, obwohl die Dokumentation an einigen Stellen etwas technisch wird. + +Es wird auch häufig für andere Anwendungen verwendet, die nicht unbedingt eine Datenbank, Benutzerverwaltung oder eine der vielen in Django enthaltenen Funktionen benötigen. Obwohl viele dieser Funktionen mit Plugins hinzugefügt werden können. + +Diese Entkopplung der Teile und die Tatsache, dass es sich um ein „Mikroframework“ handelt, welches so erweitert werden kann, dass es genau das abdeckt, was benötigt wird, war ein Schlüsselmerkmal, das ich beibehalten wollte. + +Angesichts der Einfachheit von Flask schien es eine gute Ergänzung zum Erstellen von APIs zu sein. Als Nächstes musste ein „Django REST Framework“ für Flask gefunden werden. + +/// tip | Inspirierte **FastAPI** dazu + +Ein Mikroframework zu sein. Es einfach zu machen, die benötigten Tools und Teile zu kombinieren. + +Über ein einfaches und benutzerfreundliches Routingsystem zu verfügen. + +/// + +### [Requests](https://requests.readthedocs.io) { #requests } + +**FastAPI** ist eigentlich keine Alternative zu **Requests**. Der Umfang der beiden ist sehr unterschiedlich. + +Es wäre tatsächlich üblich, Requests *innerhalb* einer FastAPI-Anwendung zu verwenden. + +Dennoch erhielt FastAPI von Requests einiges an Inspiration. + +**Requests** ist eine Bibliothek zur *Interaktion* mit APIs (als Client), während **FastAPI** eine Bibliothek zum *Erstellen* von APIs (als Server) ist. + +Die beiden stehen mehr oder weniger an entgegengesetzten Enden und ergänzen sich. + +Requests hat ein sehr einfaches und intuitives Design, ist sehr einfach zu bedienen und verfügt über sinnvolle Standardeinstellungen. Aber gleichzeitig ist es sehr leistungsstark und anpassbar. + +Aus diesem Grund heißt es auf der offiziellen Website: + +> Requests ist eines der am häufigsten heruntergeladenen Python-Packages aller Zeiten + +Die Art und Weise, wie Sie es verwenden, ist sehr einfach. Um beispielsweise einen `GET`-Request zu machen, würden Sie schreiben: + +```Python +response = requests.get("http://example.com/some/url") +``` + +Die entsprechende *Pfadoperation* der FastAPI-API könnte wie folgt aussehen: + +```Python hl_lines="1" +@app.get("/some/url") +def read_url(): + return {"message": "Hello World"} +``` + +Sehen Sie sich die Ähnlichkeiten in `requests.get(...)` und `@app.get(...)` an. + +/// tip | Inspirierte **FastAPI** dazu + +* Über eine einfache und intuitive API zu verfügen. +* HTTP-Methodennamen (Operationen) direkt, auf einfache und intuitive Weise zu verwenden. +* Vernünftige Standardeinstellungen zu haben, aber auch mächtige Einstellungsmöglichkeiten. + +/// + +### [Swagger](https://swagger.io/) / [OpenAPI](https://github.com/OAI/OpenAPI-Specification/) { #swagger-openapi } + +Die Hauptfunktion, die ich vom Django REST Framework haben wollte, war die automatische API-Dokumentation. + +Dann fand ich heraus, dass es einen Standard namens Swagger gab, zur Dokumentation von APIs unter Verwendung von JSON (oder YAML, einer Erweiterung von JSON). + +Und es gab bereits eine Web-Oberfläche für Swagger-APIs. Die Möglichkeit, Swagger-Dokumentation für eine API zu generieren, würde die automatische Nutzung dieser Web-Oberfläche ermöglichen. + +Irgendwann wurde Swagger an die Linux Foundation übergeben und in OpenAPI umbenannt. + +Aus diesem Grund spricht man bei Version 2.0 häufig von „Swagger“ und ab Version 3 von „OpenAPI“. + +/// tip | Inspirierte **FastAPI** dazu + +Einen offenen Standard für API-Spezifikationen zu übernehmen und zu verwenden, anstelle eines benutzerdefinierten Schemas. + +Und Standard-basierte Tools für die Oberfläche zu integrieren: + +* [Swagger UI](https://github.com/swagger-api/swagger-ui) +* [ReDoc](https://github.com/Rebilly/ReDoc) + +Diese beiden wurden ausgewählt, weil sie ziemlich beliebt und stabil sind, aber bei einer schnellen Suche könnten Sie Dutzende alternativer Benutzeroberflächen für OpenAPI finden (welche Sie mit **FastAPI** verwenden können). + +/// + +### Flask REST Frameworks { #flask-rest-frameworks } + +Es gibt mehrere Flask REST Frameworks, aber nachdem ich die Zeit und Arbeit investiert habe, sie zu untersuchen, habe ich festgestellt, dass viele nicht mehr unterstützt werden oder abgebrochen wurden und dass mehrere fortbestehende Probleme sie unpassend machten. + +### [Marshmallow](https://marshmallow.readthedocs.io/en/stable/) { #marshmallow } + +Eine der von API-Systemen benötigten Hauptfunktionen ist die Daten-„Serialisierung“, welche Daten aus dem Code (Python) entnimmt und in etwas umwandelt, was durch das Netzwerk gesendet werden kann. Beispielsweise das Konvertieren eines Objekts, welches Daten aus einer Datenbank enthält, in ein JSON-Objekt. Konvertieren von `datetime`-Objekten in Strings, usw. + +Eine weitere wichtige Funktion, benötigt von APIs, ist die Datenvalidierung, welche sicherstellt, dass die Daten unter gegebenen Umständen gültig sind. Zum Beispiel, dass ein Feld ein `int` ist und kein zufälliger String. Das ist besonders nützlich für hereinkommende Daten. + +Ohne ein Datenvalidierungssystem müssten Sie alle Prüfungen manuell im Code durchführen. + +Für diese Funktionen wurde Marshmallow entwickelt. Es ist eine großartige Bibliothek und ich habe sie schon oft genutzt. + +Aber sie wurde erstellt, bevor Typhinweise in Python existierten. Um also ein Schema zu definieren, müssen Sie bestimmte Werkzeuge und Klassen verwenden, die von Marshmallow bereitgestellt werden. + +/// tip | Inspirierte **FastAPI** dazu + +Code zu verwenden, um „Schemas“ zu definieren, welche Datentypen und Validierung automatisch bereitstellen. + +/// + +### [Webargs](https://webargs.readthedocs.io/en/latest/) { #webargs } + +Eine weitere wichtige Funktion, die von APIs benötigt wird, ist das Parsen von Daten aus eingehenden Requests. + +Webargs wurde entwickelt, um dieses für mehrere Frameworks, einschließlich Flask, bereitzustellen. + +Es verwendet unter der Haube Marshmallow, um die Datenvalidierung durchzuführen. Und es wurde von denselben Entwicklern erstellt. + +Es ist ein großartiges Tool und ich habe es auch oft verwendet, bevor ich **FastAPI** hatte. + +/// note | Hinweis + +Webargs wurde von denselben Marshmallow-Entwicklern erstellt. + +/// + +/// tip | Inspirierte **FastAPI** dazu + +Eingehende Requestdaten automatisch zu validieren. + +/// + +### [APISpec](https://apispec.readthedocs.io/en/stable/) { #apispec } + +Marshmallow und Webargs bieten Validierung, Parsen und Serialisierung als Plugins. + +Es fehlt jedoch noch die Dokumentation. Dann wurde APISpec erstellt. + +Es ist ein Plugin für viele Frameworks (und es gibt auch ein Plugin für Starlette). + +Die Funktionsweise besteht darin, dass Sie die Definition des Schemas im YAML-Format im Docstring jeder Funktion schreiben, die eine Route verarbeitet. + +Und es generiert OpenAPI-Schemas. + +So funktioniert es in Flask, Starlette, Responder, usw. + +Aber dann haben wir wieder das Problem einer Mikrosyntax innerhalb eines Python-Strings (eines großen YAML). + +Der Texteditor kann dabei nicht viel helfen. Und wenn wir Parameter oder Marshmallow-Schemas ändern und vergessen, auch den YAML-Docstring zu ändern, wäre das generierte Schema veraltet. + +/// note | Hinweis + +APISpec wurde von denselben Marshmallow-Entwicklern erstellt. + +/// + +/// tip | Inspirierte **FastAPI** dazu + +Den offenen Standard für APIs, OpenAPI, zu unterstützen. + +/// + +### [Flask-apispec](https://flask-apispec.readthedocs.io/en/latest/) { #flask-apispec } + +Hierbei handelt es sich um ein Flask-Plugin, welches Webargs, Marshmallow und APISpec miteinander verbindet. + +Es nutzt die Informationen von Webargs und Marshmallow, um mithilfe von APISpec automatisch OpenAPI-Schemas zu generieren. + +Ein großartiges Tool, sehr unterbewertet. Es sollte weitaus populärer als viele andere Flask-Plugins sein. Möglicherweise liegt es daran, dass die Dokumentation zu kompakt und abstrakt ist. + +Das löste das Problem, YAML (eine andere Syntax) in Python-Docstrings schreiben zu müssen. + +Diese Kombination aus Flask, Flask-apispec mit Marshmallow und Webargs war bis zur Entwicklung von **FastAPI** mein Lieblings-Backend-Stack. + +Die Verwendung führte zur Entwicklung mehrerer Flask-Full-Stack-Generatoren. Dies sind die Hauptstacks, die ich (und mehrere externe Teams) bisher verwendet haben: + +* [https://github.com/tiangolo/full-stack](https://github.com/tiangolo/full-stack) +* [https://github.com/tiangolo/full-stack-flask-couchbase](https://github.com/tiangolo/full-stack-flask-couchbase) +* [https://github.com/tiangolo/full-stack-flask-couchdb](https://github.com/tiangolo/full-stack-flask-couchdb) + +Und dieselben Full-Stack-Generatoren bildeten die Basis der [**FastAPI**-Projektgeneratoren](project-generation.md). + +/// note | Hinweis + +Flask-apispec wurde von denselben Marshmallow-Entwicklern erstellt. + +/// + +/// tip | Inspirierte **FastAPI** dazu + +Das OpenAPI-Schema automatisch zu generieren, aus demselben Code, welcher die Serialisierung und Validierung definiert. + +/// + +### [NestJS](https://nestjs.com/) (und [Angular](https://angular.io/)) { #nestjs-and-angular } + +Dies ist nicht einmal Python, NestJS ist ein von Angular inspiriertes JavaScript (TypeScript) NodeJS Framework. + +Es erreicht etwas Ähnliches wie Flask-apispec. + +Es verfügt über ein integriertes Dependency Injection System, welches von Angular 2 inspiriert ist. Erfordert ein Vorab-Registrieren der „Injectables“ (wie alle anderen Dependency Injection Systeme, welche ich kenne), sodass der Code ausschweifender wird und es mehr Codeverdoppelung gibt. + +Da die Parameter mit TypeScript-Typen beschrieben werden (ähnlich den Python-Typhinweisen), ist die Editorunterstützung ziemlich gut. + +Da TypeScript-Daten jedoch nach der Kompilierung nach JavaScript nicht erhalten bleiben, können die Typen nicht gleichzeitig die Validierung, Serialisierung und Dokumentation definieren. Aus diesem Grund und aufgrund einiger Designentscheidungen ist es für die Validierung, Serialisierung und automatische Schemagenerierung erforderlich, an vielen Stellen Dekoratoren hinzuzufügen. Es wird also ziemlich ausführlich. + +Es kann nicht sehr gut mit verschachtelten Modellen umgehen. Wenn es sich beim JSON-Body im Request also um ein JSON-Objekt mit inneren Feldern handelt, die wiederum verschachtelte JSON-Objekte sind, kann er nicht richtig dokumentiert und validiert werden. + +/// tip | Inspirierte **FastAPI** dazu + +Python-Typen zu verwenden, um eine hervorragende Editorunterstützung zu erhalten. + +Über ein leistungsstarkes Dependency Injection System zu verfügen. Eine Möglichkeit zu finden, Codeverdoppelung zu minimieren. + +/// + +### [Sanic](https://sanic.readthedocs.io/en/latest/) { #sanic } + +Es war eines der ersten extrem schnellen Python-Frameworks, welches auf `asyncio` basierte. Es wurde so gestaltet, dass es Flask sehr ähnlich ist. + +/// note | Technische Details + +Es verwendete [`uvloop`](https://github.com/MagicStack/uvloop) anstelle der standardmäßigen Python-`asyncio`-Schleife. Das hat es so schnell gemacht. + +Hat eindeutig Uvicorn und Starlette inspiriert, welche derzeit in offenen Benchmarks schneller als Sanic sind. + +/// + +/// tip | Inspirierte **FastAPI** dazu + +Einen Weg zu finden, eine hervorragende Performanz zu haben. + +Aus diesem Grund basiert **FastAPI** auf Starlette, da dieses das schnellste verfügbare Framework ist (getestet in Benchmarks von Dritten). + +/// + +### [Falcon](https://falconframework.org/) { #falcon } + +Falcon ist ein weiteres leistungsstarkes Python-Framework. Es ist minimalistisch konzipiert und dient als Grundlage für andere Frameworks wie Hug. + +Es ist so konzipiert, dass es über Funktionen verfügt, welche zwei Parameter empfangen, einen „Request“ und eine „Response“. Dann „lesen“ Sie Teile des Requests und „schreiben“ Teile der Response. Aufgrund dieses Designs ist es nicht möglich, Request-Parameter und Requestbodys mit Standard-Python-Typhinweisen als Funktionsparameter zu deklarieren. + +Daher müssen Datenvalidierung, Serialisierung und Dokumentation im Code und nicht automatisch erfolgen. Oder sie müssen als Framework oberhalb von Falcon implementiert werden, so wie Hug. Dieselbe Unterscheidung findet auch in anderen Frameworks statt, die vom Design von Falcon inspiriert sind und ein Requestobjekt und ein Responseobjekt als Parameter haben. + +/// tip | Inspirierte **FastAPI** dazu + +Wege zu finden, eine großartige Performanz zu erzielen. + +Zusammen mit Hug (da Hug auf Falcon basiert), einen `response`-Parameter in Funktionen zu deklarieren. + +Obwohl er in FastAPI optional ist und hauptsächlich zum Festlegen von Headern, Cookies und alternativen Statuscodes verwendet wird. + +/// + +### [Molten](https://moltenframework.com/) { #molten } + +Ich habe Molten in den ersten Phasen der Entwicklung von **FastAPI** entdeckt. Und es hat ganz ähnliche Ideen: + +* Basierend auf Python-Typhinweisen. +* Validierung und Dokumentation aus diesen Typen. +* Dependency Injection System. + +Es verwendet keine Datenvalidierungs-, Serialisierungs- und Dokumentationsbibliothek eines Dritten wie Pydantic, sondern verfügt über eine eigene. Daher wären diese Datentyp-Definitionen nicht so einfach wiederverwendbar. + +Es erfordert eine etwas ausführlichere Konfiguration. Und da es auf WSGI (anstelle von ASGI) basiert, ist es nicht darauf ausgelegt, die hohe Leistung von Tools wie Uvicorn, Starlette und Sanic zu nutzen. + +Das Dependency Injection System erfordert eine Vorab-Registrierung der Abhängigkeiten und die Abhängigkeiten werden basierend auf den deklarierten Typen aufgelöst. Daher ist es nicht möglich, mehr als eine „Komponente“ zu deklarieren, welche einen bestimmten Typ bereitstellt. + +Routen werden an einer einzigen Stelle deklariert, indem Funktionen verwendet werden, die an anderen Stellen deklariert wurden (anstatt Dekoratoren zu verwenden, welche direkt über der Funktion platziert werden können, welche den Endpunkt verarbeitet). Dies ähnelt eher der Vorgehensweise von Django als der Vorgehensweise von Flask (und Starlette). Es trennt im Code Dinge, die relativ eng miteinander gekoppelt sind. + +/// tip | Inspirierte **FastAPI** dazu + +Zusätzliche Validierungen für Datentypen zu definieren, mithilfe des „Default“-Werts von Modellattributen. Dies verbessert die Editorunterstützung und war zuvor in Pydantic nicht verfügbar. + +Das hat tatsächlich dazu geführt, dass Teile von Pydantic aktualisiert wurden, um denselben Validierungsdeklarationsstil zu unterstützen (diese gesamte Funktionalität ist jetzt bereits in Pydantic verfügbar). + +/// + +### [Hug](https://github.com/hugapi/hug) { #hug } + +Hug war eines der ersten Frameworks, welches die Deklaration von API-Parametertypen mithilfe von Python-Typhinweisen implementierte. Das war eine großartige Idee, die andere Tools dazu inspirierte, dasselbe zu tun. + +Es verwendete benutzerdefinierte Typen in seinen Deklarationen anstelle von Standard-Python-Typen, es war aber dennoch ein großer Fortschritt. + +Außerdem war es eines der ersten Frameworks, welches ein benutzerdefiniertes Schema generierte, welches die gesamte API in JSON deklarierte. + +Es basierte nicht auf einem Standard wie OpenAPI und JSON Schema. Daher wäre es nicht einfach, es in andere Tools wie Swagger UI zu integrieren. Aber, nochmal, es war eine sehr innovative Idee. + +Es verfügt über eine interessante, ungewöhnliche Funktion: Mit demselben Framework ist es möglich, APIs und auch CLIs zu erstellen. + +Da es auf dem bisherigen Standard für synchrone Python-Webframeworks (WSGI) basiert, kann es nicht mit Websockets und anderen Dingen umgehen, verfügt aber dennoch über eine hohe Performanz. + +/// note | Hinweis + +Hug wurde von Timothy Crosley erstellt, demselben Schöpfer von [`isort`](https://github.com/timothycrosley/isort), einem großartigen Tool zum automatischen Sortieren von Importen in Python-Dateien. + +/// + +/// tip | Ideen, die **FastAPI** inspiriert haben + +Hug inspirierte Teile von APIStar und war eines der Tools, die ich am vielversprechendsten fand, neben APIStar. + +Hug hat dazu beigetragen, **FastAPI** dazu zu inspirieren, Python-Typhinweise zum Deklarieren von Parametern zu verwenden und ein Schema zu generieren, das die API automatisch definiert. + +Hug inspirierte **FastAPI** dazu, einen `response`-Parameter in Funktionen zu deklarieren, um Header und Cookies zu setzen. + +/// + +### [APIStar](https://github.com/encode/apistar) (<= 0.5) { #apistar-0-5 } + +Kurz bevor ich mich entschied, **FastAPI** zu erstellen, fand ich den **APIStar**-Server. Er hatte fast alles, was ich suchte, und ein tolles Design. + +Er war eine der ersten Implementierungen eines Frameworks, die ich je gesehen hatte (vor NestJS und Molten), das Python-Typhinweise zur Deklaration von Parametern und Requests verwendete. Ich habe ihn mehr oder weniger zeitgleich mit Hug gefunden. Aber APIStar nutzte den OpenAPI-Standard. + +Er verfügte an mehreren Stellen über automatische Datenvalidierung, Datenserialisierung und OpenAPI-Schemagenerierung, basierend auf denselben Typhinweisen. + +Body-Schemadefinitionen verwendeten nicht die gleichen Python-Typhinweise wie Pydantic, er war Marshmallow etwas ähnlicher, sodass die Editorunterstützung nicht so gut war, aber dennoch war APIStar die beste verfügbare Option. + +Er hatte zu dieser Zeit die besten Leistungsbenchmarks (nur übertroffen von Starlette). + +Anfangs gab es keine Web-Oberfläche für die automatische API-Dokumentation, aber ich wusste, dass ich Swagger UI hinzufügen konnte. + +Er verfügte über ein Dependency Injection System. Es erforderte eine Vorab-Registrierung der Komponenten, wie auch bei anderen oben besprochenen Tools. Aber dennoch, es war ein tolles Feature. + +Ich konnte ihn nie in einem vollständigen Projekt verwenden, da er keine Sicherheitsintegration hatte, sodass ich nicht alle Funktionen, die ich hatte, durch die auf Flask-apispec basierenden Full-Stack-Generatoren ersetzen konnte. Ich hatte in meinem Projekte-Backlog den Eintrag, einen Pull Request zu erstellen, welcher diese Funktionalität hinzufügte. + +Doch dann verlagerte sich der Schwerpunkt des Projekts. + +Es handelte sich nicht länger um ein API-Webframework, da sich der Entwickler auf Starlette konzentrieren musste. + +Jetzt handelt es sich bei APIStar um eine Reihe von Tools zur Validierung von OpenAPI-Spezifikationen, nicht um ein Webframework. + +/// note | Hinweis + +APIStar wurde von Tom Christie erstellt. Derselbe, welcher Folgendes erstellt hat: + +* Django REST Framework +* Starlette (auf welchem **FastAPI** basiert) +* Uvicorn (verwendet von Starlette und **FastAPI**) + +/// + +/// tip | Inspirierte **FastAPI** dazu + +Zu existieren. + +Die Idee, mehrere Dinge (Datenvalidierung, Serialisierung und Dokumentation) mit denselben Python-Typen zu deklarieren, welche gleichzeitig eine hervorragende Editorunterstützung bieten, hielt ich für eine brillante Idee. + +Und nach einer langen Suche nach einem ähnlichen Framework und dem Testen vieler verschiedener Alternativen, war APIStar die beste verfügbare Option. + +Dann hörte APIStar auf, als Server zu existieren, und Starlette wurde geschaffen, welches eine neue, bessere Grundlage für ein solches System bildete. Das war die finale Inspiration für die Entwicklung von **FastAPI**. + +Ich betrachte **FastAPI** als einen „spirituellen Nachfolger“ von APIStar, welcher die Funktionen, das Typsystem und andere Teile verbessert und erweitert, basierend auf den Erkenntnissen aus all diesen früheren Tools. + +/// + +## Verwendet von **FastAPI** { #used-by-fastapi } + +### [Pydantic](https://docs.pydantic.dev/) { #pydantic } + +Pydantic ist eine Bibliothek zum Definieren von Datenvalidierung, Serialisierung und Dokumentation (unter Verwendung von JSON Schema) basierend auf Python-Typhinweisen. + +Das macht es äußerst intuitiv. + +Es ist vergleichbar mit Marshmallow. Obwohl es in Benchmarks schneller als Marshmallow ist. Und da es auf den gleichen Python-Typhinweisen basiert, ist die Editorunterstützung großartig. + +/// tip | **FastAPI** verwendet es, um + +Die gesamte Datenvalidierung, Datenserialisierung und automatische Modelldokumentation (basierend auf JSON Schema) zu erledigen. + +**FastAPI** nimmt dann, abgesehen von all den anderen Dingen, die es tut, dieses JSON-Schema und fügt es in OpenAPI ein. + +/// + +### [Starlette](https://www.starlette.dev/) { #starlette } + +Starlette ist ein leichtgewichtiges ASGI-Framework/Toolkit, welches sich ideal für die Erstellung hochperformanter asynchroner Dienste eignet. + +Es ist sehr einfach und intuitiv. Es ist so konzipiert, dass es leicht erweiterbar ist und über modulare Komponenten verfügt. + +Es bietet: + +* Eine sehr beeindruckende Leistung. +* WebSocket-Unterstützung. +* Hintergrundtasks im selben Prozess. +* Startup- und Shutdown-Events. +* Testclient basierend auf HTTPX. +* CORS, GZip, statische Dateien, Responses streamen. +* Session- und Cookie-Unterstützung. +* 100 % Testabdeckung. +* 100 % typannotierte Codebasis. +* Wenige starke Abhängigkeiten. + +Starlette ist derzeit das schnellste getestete Python-Framework. Nur übertroffen von Uvicorn, welches kein Framework, sondern ein Server ist. + +Starlette bietet alle grundlegenden Funktionen eines Web-Microframeworks. + +Es bietet jedoch keine automatische Datenvalidierung, Serialisierung oder Dokumentation. + +Das ist eines der wichtigsten Dinge, welche **FastAPI** hinzufügt, alles basierend auf Python-Typhinweisen (mit Pydantic). Das, plus, das Dependency Injection System, Sicherheitswerkzeuge, OpenAPI-Schemagenerierung, usw. + +/// note | Technische Details + +ASGI ist ein neuer „Standard“, welcher von Mitgliedern des Django-Kernteams entwickelt wird. Es handelt sich immer noch nicht um einen „Python-Standard“ (ein PEP), obwohl sie gerade dabei sind, das zu tun. + +Dennoch wird es bereits von mehreren Tools als „Standard“ verwendet. Das verbessert die Interoperabilität erheblich, da Sie Uvicorn mit jedem anderen ASGI-Server (wie Daphne oder Hypercorn) tauschen oder ASGI-kompatible Tools wie `python-socketio` hinzufügen können. + +/// + +/// tip | **FastAPI** verwendet es, um + +Alle Kern-Webaspekte zu handhaben. Und fügt Funktionen obenauf. + +Die Klasse `FastAPI` selbst erbt direkt von der Klasse `Starlette`. + +Alles, was Sie also mit Starlette machen können, können Sie direkt mit **FastAPI** machen, da es sich im Grunde um Starlette auf Steroiden handelt. + +/// + +### [Uvicorn](https://www.uvicorn.dev/) { #uvicorn } + +Uvicorn ist ein blitzschneller ASGI-Server, der auf uvloop und httptools basiert. + +Es handelt sich nicht um ein Webframework, sondern um einen Server. Beispielsweise werden keine Tools für das Routing von Pfaden bereitgestellt. Das ist etwas, was ein Framework wie Starlette (oder **FastAPI**) zusätzlich bieten würde. + +Es ist der empfohlene Server für Starlette und **FastAPI**. + +/// tip | **FastAPI** empfiehlt es als + +Hauptwebserver zum Ausführen von **FastAPI**-Anwendungen. + +Sie können auch die Kommandozeilenoption `--workers` verwenden, um einen asynchronen Multiprozess-Server zu erhalten. + +Weitere Details finden Sie im Abschnitt [Deployment](deployment/index.md). + +/// + +## Benchmarks und Geschwindigkeit { #benchmarks-and-speed } + +Um den Unterschied zwischen Uvicorn, Starlette und FastAPI zu verstehen, zu vergleichen, und zu sehen, lesen Sie den Abschnitt über [Benchmarks](benchmarks.md). diff --git a/docs/de/docs/async.md b/docs/de/docs/async.md new file mode 100644 index 0000000000000..060e39bf9fcb5 --- /dev/null +++ b/docs/de/docs/async.md @@ -0,0 +1,444 @@ +# Nebenläufigkeit und async / await { #concurrency-and-async-await } + +Details zur `async def`-Syntax für *Pfadoperation-Funktionen* und Hintergrundinformationen zu asynchronem Code, Nebenläufigkeit und Parallelität. + +## In Eile? { #in-a-hurry } + +TL;DR: + +Wenn Sie Bibliotheken von Dritten verwenden, die mit `await` aufgerufen werden müssen, wie zum Beispiel: + +```Python +results = await some_library() +``` + +Dann deklarieren Sie Ihre *Pfadoperation-Funktionen* mit `async def`, wie in: + +```Python hl_lines="2" +@app.get('/') +async def read_results(): + results = await some_library() + return results +``` + +/// note | Hinweis + +Sie können `await` nur innerhalb von Funktionen verwenden, die mit `async def` erstellt wurden. + +/// + +--- + +Wenn Sie eine Bibliothek eines Dritten verwenden, die mit etwas kommuniziert (einer Datenbank, einer API, dem Dateisystem, usw.) und welche die Verwendung von `await` nicht unterstützt (dies ist derzeit bei den meisten Datenbankbibliotheken der Fall), dann deklarieren Sie Ihre *Pfadoperation-Funktionen* ganz normal nur mit `def`, wie in: + +```Python hl_lines="2" +@app.get('/') +def results(): + results = some_library() + return results +``` + +--- + +Wenn Ihre Anwendung (irgendwie) nicht mit etwas anderem kommunizieren und auf dessen Antwort warten muss, verwenden Sie `async def`, auch wenn Sie `await` im Inneren nicht verwenden müssen. + +--- + +Wenn Sie sich unsicher sind, verwenden Sie normales `def`. + +--- + +**Hinweis**: Sie können `def` und `async def` in Ihren *Pfadoperation-Funktionen* beliebig mischen, so wie Sie es benötigen, und jede einzelne Funktion in der für Sie besten Variante erstellen. FastAPI wird damit das Richtige tun. + +Wie dem auch sei, in jedem der oben genannten Fälle wird FastAPI immer noch asynchron arbeiten und extrem schnell sein. + +Wenn Sie jedoch den oben genannten Schritten folgen, können einige Performanz-Optimierungen vorgenommen werden. + +## Technische Details { #technical-details } + +Moderne Versionen von Python unterstützen **„asynchronen Code“** unter Verwendung sogenannter **„Coroutinen“** mithilfe der Syntax **`async` und `await`**. + +Nehmen wir obigen Satz in den folgenden Abschnitten Schritt für Schritt unter die Lupe: + +* **Asynchroner Code** +* **`async` und `await`** +* **Coroutinen** + +## Asynchroner Code { #asynchronous-code } + +Asynchroner Code bedeutet lediglich, dass die Sprache 💬 eine Möglichkeit hat, dem Computer / Programm 🤖 mitzuteilen, dass es 🤖 an einem bestimmten Punkt im Code darauf warten muss, dass *etwas anderes* irgendwo anders fertig wird. Nehmen wir an, *etwas anderes* ist hier „Langsam-Datei“ 📝. + +Während der Zeit, die „Langsam-Datei“ 📝 benötigt, kann das System also andere Aufgaben erledigen. + +Dann kommt der Computer / das Programm 🤖 bei jeder Gelegenheit zurück, weil es entweder wieder wartet oder wann immer es 🤖 die ganze Arbeit erledigt hat, die zu diesem Zeitpunkt zu tun war. Und es 🤖 wird nachschauen, ob eine der Aufgaben, auf die es gewartet hat, bereits fertig ist, und tun, was es zu tun hatte. + +Dann nimmt es 🤖 die erste erledigte Aufgabe (sagen wir, unsere „Langsam-Datei“ 📝) und bearbeitet sie weiter. + +Das „Warten auf etwas anderes“ bezieht sich normalerweise auf I/O-Operationen, die relativ „langsam“ sind (im Vergleich zur Geschwindigkeit des Prozessors und des Arbeitsspeichers), wie etwa das Warten darauf, dass: + +* die Daten des Clients über das Netzwerk empfangen wurden +* die von Ihrem Programm gesendeten Daten vom Client über das Netzwerk empfangen wurden +* der Inhalt einer Datei vom System von der Festplatte gelesen und an Ihr Programm übergeben wurde +* der Inhalt, den Ihr Programm dem System übergeben hat, auf die Festplatte geschrieben wurde +* eine Remote-API-Operation beendet wurde +* Eine Datenbankoperation abgeschlossen wurde +* eine Datenbankabfrage die Ergebnisse zurückgegeben hat +* usw. + +Da die Ausführungszeit hier hauptsächlich durch das Warten auf I/O-Operationen verbraucht wird, nennt man dies auch „I/O-lastige“ („I/O bound“) Operationen. + +„Asynchron“, sagt man, weil der Computer / das Programm nicht mit einer langsamen Aufgabe „synchronisiert“ werden muss und nicht auf den genauen Moment warten muss, in dem die Aufgabe beendet ist, ohne dabei etwas zu tun, um schließlich das Ergebnis der Aufgabe zu übernehmen und die Arbeit fortsetzen zu können. + +Da es sich stattdessen um ein „asynchrones“ System handelt, kann die Aufgabe nach Abschluss ein wenig (einige Mikrosekunden) in der Schlange warten, bis der Computer / das Programm seine anderen Dinge erledigt hat und zurückkommt, um die Ergebnisse entgegenzunehmen und mit ihnen weiterzuarbeiten. + +Für „synchron“ (im Gegensatz zu „asynchron“) wird auch oft der Begriff „sequentiell“ verwendet, da der Computer / das Programm alle Schritte in einer Sequenz („der Reihe nach“) ausführt, bevor es zu einer anderen Aufgabe wechselt, auch wenn diese Schritte mit Warten verbunden sind. + +### Nebenläufigkeit und Hamburger { #concurrency-and-burgers } + +Diese oben beschriebene Idee von **asynchronem** Code wird manchmal auch **„Nebenläufigkeit“** genannt. Sie unterscheidet sich von **„Parallelität“**. + +**Nebenläufigkeit** und **Parallelität** beziehen sich beide auf „verschiedene Dinge, die mehr oder weniger gleichzeitig passieren“. + +Aber die Details zwischen *Nebenläufigkeit* und *Parallelität* sind ziemlich unterschiedlich. + +Um den Unterschied zu erkennen, stellen Sie sich die folgende Geschichte über Hamburger vor: + +### Nebenläufige Hamburger { #concurrent-burgers } + +Sie gehen mit Ihrem Schwarm Fastfood holen, stehen in der Schlange, während der Kassierer die Bestellungen der Leute vor Ihnen entgegennimmt. 😍 + + + +Dann sind Sie an der Reihe und Sie bestellen zwei sehr schmackhafte Burger für Ihren Schwarm und Sie. 🍔🍔 + + + +Der Kassierer sagt etwas zum Koch in der Küche, damit dieser weiß, dass er Ihre Burger zubereiten muss (obwohl er gerade die für die vorherigen Kunden zubereitet). + + + +Sie bezahlen. 💸 + +Der Kassierer gibt Ihnen die Nummer Ihrer Bestellung. + + + +Während Sie warten, suchen Sie sich mit Ihrem Schwarm einen Tisch aus, Sie sitzen da und reden lange mit Ihrem Schwarm (da Ihre Burger sehr aufwändig sind und die Zubereitung einige Zeit dauert). + +Während Sie mit Ihrem Schwarm am Tisch sitzen und auf die Burger warten, können Sie die Zeit damit verbringen, zu bewundern, wie großartig, süß und klug Ihr Schwarm ist ✨😍✨. + + + +Während Sie warten und mit Ihrem Schwarm sprechen, überprüfen Sie von Zeit zu Zeit die auf dem Zähler angezeigte Nummer, um zu sehen, ob Sie bereits an der Reihe sind. + +Dann, irgendwann, sind Sie endlich an der Reihe. Sie gehen zur Theke, holen sich die Burger und kommen zurück an den Tisch. + + + +Sie und Ihr Schwarm essen die Burger und haben eine schöne Zeit. ✨ + + + +/// note | Hinweis + +Die wunderschönen Illustrationen stammen von [Ketrina Thompson](https://www.instagram.com/ketrinadrawsalot). 🎨 + +/// + +--- + +Stellen Sie sich vor, Sie wären der Computer / das Programm 🤖 in dieser Geschichte. + +Während Sie an der Schlange stehen, sind Sie einfach untätig 😴, warten darauf, dass Sie an die Reihe kommen, und tun nichts sehr „Produktives“. Aber die Schlange ist schnell abgearbeitet, weil der Kassierer nur die Bestellungen entgegennimmt (und nicht zubereitet), also ist das vertretbar. + +Wenn Sie dann an der Reihe sind, erledigen Sie tatsächliche „produktive“ Arbeit, Sie gehen das Menü durch, entscheiden sich, was Sie möchten, bekunden Ihre und die Wahl Ihres Schwarms, bezahlen, prüfen, ob Sie die richtige Menge Geld oder die richtige Karte geben, prüfen, ob die Rechnung korrekt ist, prüfen, dass die Bestellung die richtigen Artikel enthält, usw. + +Aber dann, auch wenn Sie Ihre Burger noch nicht haben, ist Ihre Interaktion mit dem Kassierer erst mal „auf Pause“ ⏸, weil Sie warten müssen 🕙, bis Ihre Burger fertig sind. + +Aber wenn Sie sich von der Theke entfernt haben und mit der Nummer für die Bestellung an einem Tisch sitzen, können Sie Ihre Aufmerksamkeit auf Ihren Schwarm lenken und an dieser Aufgabe „arbeiten“ ⏯ 🤓. Sie machen wieder etwas sehr „Produktives“ und flirten mit Ihrem Schwarm 😍. + +Dann sagt der Kassierer 💁 „Ich bin mit dem Burger fertig“, indem er Ihre Nummer auf dem Display über der Theke anzeigt, aber Sie springen nicht sofort wie verrückt auf, wenn das Display auf Ihre Nummer springt. Sie wissen, dass niemand Ihnen Ihre Burger wegnimmt, denn Sie haben die Nummer Ihrer Bestellung, und andere Leute haben andere Nummern. + +Also warten Sie darauf, dass Ihr Schwarm ihre Geschichte zu Ende erzählt (die aktuelle Arbeit ⏯ / bearbeitete Aufgabe beendet 🤓), lächeln sanft und sagen, dass Sie die Burger holen ⏸. + +Dann gehen Sie zur Theke 🔀, zur ursprünglichen Aufgabe, die nun erledigt ist ⏯, nehmen die Burger auf, sagen Danke, und bringen sie zum Tisch. Damit ist dieser Schritt / diese Aufgabe der Interaktion mit der Theke abgeschlossen ⏹. Das wiederum schafft eine neue Aufgabe, „Burger essen“ 🔀 ⏯, aber die vorherige Aufgabe „Burger holen“ ist erledigt ⏹. + +### Parallele Hamburger { #parallel-burgers } + +Stellen wir uns jetzt vor, dass es sich hierbei nicht um „nebenläufige Hamburger“, sondern um „parallele Hamburger“ handelt. + +Sie gehen los mit Ihrem Schwarm, um paralleles Fast Food zu bekommen. + +Sie stehen in der Schlange, während mehrere (sagen wir acht) Kassierer, die gleichzeitig Köche sind, die Bestellungen der Leute vor Ihnen entgegennehmen. + +Alle vor Ihnen warten darauf, dass ihre Burger fertig sind, bevor sie die Theke verlassen, denn jeder der 8 Kassierer geht los und bereitet den Burger sofort zu, bevor er die nächste Bestellung entgegennimmt. + + + +Dann sind Sie endlich an der Reihe und bestellen zwei sehr leckere Burger für Ihren Schwarm und Sie. + +Sie zahlen 💸. + + + +Der Kassierer geht in die Küche. + +Sie warten, vor der Theke stehend 🕙, damit niemand außer Ihnen Ihre Burger entgegennimmt, da es keine Nummern für die Reihenfolge gibt. + + + +Da Sie und Ihr Schwarm damit beschäftigt sind, niemanden vor sich zu lassen, der Ihre Burger nimmt, wenn sie ankommen, können Sie Ihrem Schwarm keine Aufmerksamkeit schenken. 😞 + +Das ist „synchrone“ Arbeit, Sie sind mit dem Kassierer/Koch „synchronisiert“ 👨‍🍳. Sie müssen warten 🕙 und genau in dem Moment da sein, in dem der Kassierer/Koch 👨‍🍳 die Burger zubereitet hat und Ihnen gibt, sonst könnte jemand anderes sie nehmen. + + + +Dann kommt Ihr Kassierer/Koch 👨‍🍳 endlich mit Ihren Burgern zurück, nachdem Sie lange vor der Theke gewartet 🕙 haben. + + + +Sie nehmen Ihre Burger und gehen mit Ihrem Schwarm an den Tisch. + +Sie essen sie und sind fertig. ⏹ + + + +Es wurde nicht viel geredet oder geflirtet, da die meiste Zeit mit Warten 🕙 vor der Theke verbracht wurde. 😞 + +/// note | Hinweis + +Die wunderschönen Illustrationen stammen von [Ketrina Thompson](https://www.instagram.com/ketrinadrawsalot). 🎨 + +/// + +--- + +In diesem Szenario der parallelen Hamburger sind Sie ein Computersystem / Programm 🤖 mit zwei Prozessoren (Sie und Ihr Schwarm), die beide warten 🕙 und ihre Aufmerksamkeit darauf verwenden, „lange Zeit vor der Theke zu warten“ 🕙. + +Der Fast-Food-Laden verfügt über 8 Prozessoren (Kassierer/Köche). Während der nebenläufige Burger-Laden nur zwei hatte (einen Kassierer und einen Koch). + +Dennoch ist das schlussendliche Benutzererlebnis nicht das Beste. 😞 + +--- + +Dies wäre die parallele äquivalente Geschichte für Hamburger. 🍔 + +Für ein „realeres“ Beispiel hierfür, stellen Sie sich eine Bank vor. + +Bis vor kurzem hatten die meisten Banken mehrere Kassierer 👨‍💼👨‍💼👨‍💼👨‍💼 und eine große Warteschlange 🕙🕙🕙🕙🕙🕙🕙🕙. + +Alle Kassierer erledigen die ganze Arbeit mit einem Kunden nach dem anderen 👨‍💼⏯. + +Und man muss lange in der Schlange warten 🕙 sonst kommt man nicht an die Reihe. + +Sie würden Ihren Schwarm 😍 wahrscheinlich nicht mitnehmen wollen, um Besorgungen bei der Bank zu erledigen 🏦. + +### Hamburger Schlussfolgerung { #burger-conclusion } + +In diesem Szenario „Fastfood-Burger mit Ihrem Schwarm“ ist es viel sinnvoller, ein nebenläufiges System zu haben ⏸🔀⏯, da viel gewartet wird 🕙. + +Das ist auch bei den meisten Webanwendungen der Fall. + +Viele, viele Benutzer, aber Ihr Server wartet 🕙 darauf, dass deren nicht so gute Internetverbindungen die Requests übermitteln. + +Und dann wieder warten 🕙, bis die Responses zurückkommen. + +Dieses „Warten“ 🕙 wird in Mikrosekunden gemessen, aber zusammenfassend lässt sich sagen, dass am Ende eine Menge gewartet wird. + +Deshalb ist es sehr sinnvoll, asynchronen ⏸🔀⏯ Code für Web-APIs zu verwenden. + +Diese Art der Asynchronität hat NodeJS populär gemacht (auch wenn NodeJS nicht parallel ist) und darin liegt die Stärke von Go als Programmiersprache. + +Und das ist das gleiche Leistungsniveau, das Sie mit **FastAPI** erhalten. + +Und da Sie Parallelität und Asynchronität gleichzeitig haben können, erzielen Sie eine höhere Performanz als die meisten getesteten NodeJS-Frameworks und sind mit Go auf Augenhöhe, einer kompilierten Sprache, die näher an C liegt [(alles dank Starlette)](https://www.techempower.com/benchmarks/#section=data-r17&hw=ph&test=query&l=zijmkf-1). + +### Ist Nebenläufigkeit besser als Parallelität? { #is-concurrency-better-than-parallelism } + +Nein! Das ist nicht die Moral der Geschichte. + +Nebenläufigkeit unterscheidet sich von Parallelität. Und sie ist besser bei **bestimmten** Szenarien, die viel Warten erfordern. Aus diesem Grund ist sie im Allgemeinen viel besser als Parallelität für die Entwicklung von Webanwendungen. Aber das stimmt nicht für alle Anwendungen. + +Um die Dinge auszugleichen, stellen Sie sich die folgende Kurzgeschichte vor: + +> Sie müssen ein großes, schmutziges Haus aufräumen. + +*Yup, das ist die ganze Geschichte*. + +--- + +Es gibt kein Warten 🕙, nur viel Arbeit an mehreren Stellen im Haus. + +Sie könnten wie im Hamburger-Beispiel hin- und herspringen, zuerst das Wohnzimmer, dann die Küche, aber da Sie auf nichts warten 🕙, sondern nur putzen und putzen, hätte das Hin- und Herspringen keine Auswirkungen. + +Es würde mit oder ohne Hin- und Herspringen (Nebenläufigkeit) die gleiche Zeit in Anspruch nehmen, um fertig zu werden, und Sie hätten die gleiche Menge an Arbeit erledigt. + +Aber wenn Sie in diesem Fall die acht Ex-Kassierer/Köche/jetzt Reinigungskräfte mitbringen würden und jeder von ihnen (plus Sie) würde einen Bereich des Hauses reinigen, könnten Sie die ganze Arbeit **parallel** erledigen, und würden mit dieser zusätzlichen Hilfe viel schneller fertig werden. + +In diesem Szenario wäre jede einzelne Reinigungskraft (einschließlich Ihnen) ein Prozessor, der seinen Teil der Arbeit erledigt. + +Und da die meiste Ausführungszeit durch tatsächliche Arbeit (anstatt durch Warten) in Anspruch genommen wird und die Arbeit in einem Computer von einer CPU erledigt wird, werden diese Probleme als „CPU-lastig“ („CPU bound“) bezeichnet. + +--- + +Typische Beispiele für CPU-lastige Vorgänge sind Dinge, die komplexe mathematische Berechnungen erfordern. + +Zum Beispiel: + +* **Audio-** oder **Bildbearbeitung**. +* **Computer Vision**: Ein Bild besteht aus Millionen von Pixeln, jedes Pixel hat 3 Werte / Farben, die Verarbeitung erfordert normalerweise, Berechnungen mit diesen Pixeln durchzuführen, alles zur gleichen Zeit. +* **Maschinelles Lernen**: Normalerweise sind viele „Matrix“- und „Vektor“-Multiplikationen erforderlich. Stellen Sie sich eine riesige Tabelle mit Zahlen vor, in der Sie alle Zahlen gleichzeitig multiplizieren. +* **Deep Learning**: Dies ist ein Teilgebiet des maschinellen Lernens, daher gilt das Gleiche. Es ist nur so, dass es nicht eine einzige Tabelle mit Zahlen zum Multiplizieren gibt, sondern eine riesige Menge davon, und in vielen Fällen verwendet man einen speziellen Prozessor, um diese Modelle zu erstellen und / oder zu verwenden. + +### Nebenläufigkeit + Parallelität: Web + maschinelles Lernen { #concurrency-parallelism-web-machine-learning } + +Mit **FastAPI** können Sie die Vorteile der Nebenläufigkeit nutzen, die in der Webentwicklung weit verbreitet ist (derselbe Hauptvorteil von NodeJS). + +Sie können aber auch die Vorteile von Parallelität und Multiprocessing (mehrere Prozesse werden parallel ausgeführt) für **CPU-lastige** Workloads wie in Systemen für maschinelles Lernen nutzen. + +Dies und die einfache Tatsache, dass Python die Hauptsprache für **Data Science**, maschinelles Lernen und insbesondere Deep Learning ist, machen FastAPI zu einem sehr passenden Werkzeug für Web-APIs und Anwendungen für Data Science / maschinelles Lernen (neben vielen anderen). + +Wie Sie diese Parallelität in der Produktion erreichen, erfahren Sie im Abschnitt über [Deployment](deployment/index.md). + +## `async` und `await` { #async-and-await } + +Moderne Versionen von Python verfügen über eine sehr intuitive Möglichkeit, asynchronen Code zu schreiben. Dadurch sieht es wie normaler „sequentieller“ Code aus und übernimmt im richtigen Moment das „Warten“ für Sie. + +Wenn es einen Vorgang gibt, der erfordert, dass gewartet wird, bevor die Ergebnisse zurückgegeben werden, und der diese neue Python-Funktionalität unterstützt, können Sie ihn wie folgt schreiben: + +```Python +burgers = await get_burgers(2) +``` + +Der Schlüssel hier ist das `await`. Es teilt Python mit, dass es warten ⏸ muss, bis `get_burgers(2)` seine Aufgabe erledigt hat 🕙, bevor die Ergebnisse in `burgers` gespeichert werden. Damit weiß Python, dass es in der Zwischenzeit etwas anderes tun kann 🔀 ⏯ (z. B. einen weiteren Request empfangen). + +Damit `await` funktioniert, muss es sich in einer Funktion befinden, die diese Asynchronität unterstützt. Dazu deklarieren Sie sie einfach mit `async def`: + +```Python hl_lines="1" +async def get_burgers(number: int): + # Mache hier etwas Asynchrones, um die Burger zu erstellen + return burgers +``` + +... statt mit `def`: + +```Python hl_lines="2" +# Dies ist nicht asynchron +def get_sequential_burgers(number: int): + # Mache hier etwas Sequentielles, um die Burger zu erstellen + return burgers +``` + +Mit `async def` weiß Python, dass es innerhalb dieser Funktion auf `await`-Ausdrücke achten muss und dass es die Ausführung dieser Funktion „anhalten“ ⏸ und etwas anderes tun kann 🔀, bevor es zurückkommt. + +Wenn Sie eine `async def`-Funktion aufrufen möchten, müssen Sie sie „erwarten“ („await“). Das folgende wird also nicht funktionieren: + +```Python +# Das funktioniert nicht, weil get_burgers definiert wurde mit: async def +burgers = get_burgers(2) +``` + +--- + +Wenn Sie also eine Bibliothek verwenden, die Ihnen sagt, dass Sie sie mit `await` aufrufen können, müssen Sie die *Pfadoperation-Funktionen*, die diese Bibliothek verwenden, mittels `async def` erstellen, wie in: + +```Python hl_lines="2-3" +@app.get('/burgers') +async def read_burgers(): + burgers = await get_burgers(2) + return burgers +``` + +### Weitere technische Details { #more-technical-details } + +Ihnen ist wahrscheinlich aufgefallen, dass `await` nur innerhalb von Funktionen verwendet werden kann, die mit `async def` definiert sind. + +Gleichzeitig müssen aber mit `async def` definierte Funktionen „erwartet“ („awaited“) werden. Daher können Funktionen mit `async def` nur innerhalb von Funktionen aufgerufen werden, die auch mit `async def` definiert sind. + +Daraus resultiert das Ei-und-Huhn-Problem: Wie ruft man die erste `async` Funktion auf? + +Wenn Sie mit **FastAPI** arbeiten, müssen Sie sich darüber keine Sorgen machen, da diese „erste“ Funktion Ihre *Pfadoperation-Funktion* sein wird und FastAPI weiß, was zu tun ist. + +Wenn Sie jedoch `async` / `await` ohne FastAPI verwenden möchten, können Sie dies auch tun. + +### Ihren eigenen asynchronen Code schreiben { #write-your-own-async-code } + +Starlette (und **FastAPI**) basieren auf [AnyIO](https://anyio.readthedocs.io/en/stable/), was bedeutet, dass es sowohl kompatibel mit der Python-Standardbibliothek [asyncio](https://docs.python.org/3/library/asyncio-task.html) als auch mit [Trio](https://trio.readthedocs.io/en/stable/) ist. + +Insbesondere können Sie [AnyIO](https://anyio.readthedocs.io/en/stable/) direkt verwenden für Ihre fortgeschrittenen nebenläufigen Anwendungsfälle, die fortgeschrittenere Muster in Ihrem eigenen Code erfordern. + +Und auch wenn Sie FastAPI nicht verwenden würden, könnten Sie Ihre eigenen asynchronen Anwendungen mit [AnyIO](https://anyio.readthedocs.io/en/stable/) schreiben, um hochkompatibel zu sein und dessen Vorteile zu nutzen (z. B. *strukturierte Nebenläufigkeit*). + +Ich habe eine weitere Bibliothek auf Basis von AnyIO erstellt, als dünne Schicht obendrauf, um die Typannotationen etwas zu verbessern und bessere **Autovervollständigung**, **Inline-Fehler** usw. zu erhalten. Sie hat auch eine freundliche Einführung und ein Tutorial, um Ihnen zu helfen, **Ihren eigenen asynchronen Code zu verstehen** und zu schreiben: [Asyncer](https://asyncer.tiangolo.com/). Sie ist insbesondere nützlich, wenn Sie **asynchronen Code mit regulärem** (blockierendem/synchronem) Code kombinieren müssen. + +### Andere Formen von asynchronem Code { #other-forms-of-asynchronous-code } + +Diese Art der Verwendung von `async` und `await` ist in der Sprache relativ neu. + +Aber sie erleichtert die Arbeit mit asynchronem Code erheblich. + +Die gleiche Syntax (oder fast identisch) wurde kürzlich auch in moderne Versionen von JavaScript (im Browser und in NodeJS) aufgenommen. + +Davor war der Umgang mit asynchronem Code jedoch deutlich komplexer und schwieriger. + +In früheren Versionen von Python hätten Sie Threads oder [Gevent](https://www.gevent.org/) verwenden können. Der Code ist jedoch viel komplexer zu verstehen, zu debuggen und nachzuvollziehen. + +In früheren Versionen von NodeJS / Browser JavaScript hätten Sie „Callbacks“ verwendet. Was zur „Callback-Hölle“ führt. + +## Coroutinen { #coroutines } + +**Coroutine** ist nur ein schicker Begriff für dasjenige, was von einer `async def`-Funktion zurückgegeben wird. Python weiß, dass es so etwas wie eine Funktion ist, die es starten kann und die irgendwann endet, aber auch dass sie pausiert ⏸ werden kann, wann immer darin ein `await` steht. + +Aber all diese Funktionalität der Verwendung von asynchronem Code mit `async` und `await` wird oft als Verwendung von „Coroutinen“ zusammengefasst. Es ist vergleichbar mit dem Hauptmerkmal von Go, den „Goroutinen“. + +## Fazit { #conclusion } + +Sehen wir uns den gleichen Satz von oben noch mal an: + +> Moderne Versionen von Python unterstützen **„asynchronen Code“** unter Verwendung sogenannter **„Coroutinen“** mithilfe der Syntax **`async` und `await`**. + +Das sollte jetzt mehr Sinn ergeben. ✨ + +All das ist es, was FastAPI (via Starlette) befeuert und es eine so beeindruckende Performanz haben lässt. + +## Sehr technische Details { #very-technical-details } + +/// warning | Achtung + +Das folgende können Sie wahrscheinlich überspringen. + +Dies sind sehr technische Details darüber, wie **FastAPI** unter der Haube funktioniert. + +Wenn Sie über gute technische Kenntnisse verfügen (Coroutinen, Threads, Blocking, usw.) und neugierig sind, wie FastAPI mit `async def`s im Vergleich zu normalen `def`s umgeht, fahren Sie fort. + +/// + +### Pfadoperation-Funktionen { #path-operation-functions } + +Wenn Sie eine *Pfadoperation-Funktion* mit normalem `def` anstelle von `async def` deklarieren, wird sie in einem externen Threadpool ausgeführt, der dann `await`et wird, anstatt direkt aufgerufen zu werden (da dies den Server blockieren würde). + +Wenn Sie von einem anderen asynchronen Framework kommen, das nicht auf die oben beschriebene Weise funktioniert, und Sie es gewohnt sind, triviale, nur-berechnende *Pfadoperation-Funktionen* mit einfachem `def` zu definieren, um einen geringfügigen Geschwindigkeitsgewinn (etwa 100 Nanosekunden) zu erzielen, beachten Sie bitte, dass der Effekt in **FastAPI** genau gegenteilig wäre. In solchen Fällen ist es besser, `async def` zu verwenden, es sei denn, Ihre *Pfadoperation-Funktionen* verwenden Code, der blockierende I/O-Operationen durchführt. + +Dennoch besteht in beiden Fällen eine gute Chance, dass **FastAPI** [immer noch schneller](index.md#performance) als Ihr bisheriges Framework (oder zumindest damit vergleichbar) ist. + +### Abhängigkeiten { #dependencies } + +Das Gleiche gilt für [Abhängigkeiten](tutorial/dependencies/index.md). Wenn eine Abhängigkeit eine normale `def`-Funktion anstelle einer `async def` ist, wird sie im externen Threadpool ausgeführt. + +### Unterabhängigkeiten { #sub-dependencies } + +Sie können mehrere Abhängigkeiten und [Unterabhängigkeiten](tutorial/dependencies/sub-dependencies.md) haben, die einander bedingen (als Parameter der Funktionsdefinitionen), einige davon könnten erstellt werden mit `async def` und einige mit normalem `def`. Es würde immer noch funktionieren, und diejenigen, die mit normalem `def` erstellt wurden, würden in einem externen Thread (vom Threadpool stammend) aufgerufen werden, anstatt `await`et zu werden. + +### Andere Hilfsfunktionen { #other-utility-functions } + +Jede andere Hilfsfunktion, die Sie direkt aufrufen, kann mit normalem `def` oder `async def` erstellt werden, und FastAPI beeinflusst nicht die Art und Weise, wie Sie sie aufrufen. + +Dies steht im Gegensatz zu den Funktionen, die FastAPI für Sie aufruft: *Pfadoperation-Funktionen* und Abhängigkeiten. + +Wenn Ihre Hilfsfunktion eine normale Funktion mit `def` ist, wird sie direkt aufgerufen (so wie Sie es in Ihrem Code schreiben), nicht in einem Threadpool. Wenn die Funktion mit `async def` erstellt wurde, sollten Sie sie `await`en, wenn Sie sie in Ihrem Code aufrufen. + +--- + +Nochmal, es handelt sich hier um sehr technische Details, die Ihnen helfen, falls Sie danach gesucht haben. + +Andernfalls liegen Sie richtig, wenn Sie sich an die Richtlinien aus dem obigen Abschnitt halten:
In Eile?. diff --git a/docs/de/docs/benchmarks.md b/docs/de/docs/benchmarks.md new file mode 100644 index 0000000000000..9421f80105194 --- /dev/null +++ b/docs/de/docs/benchmarks.md @@ -0,0 +1,34 @@ +# Benchmarks { #benchmarks } + +Unabhängige TechEmpower-Benchmarks zeigen **FastAPI**-Anwendungen, die unter Uvicorn ausgeführt werden, als [eines der schnellsten verfügbaren Python-Frameworks](https://www.techempower.com/benchmarks/#section=test&runid=7464e520-0dc2-473d-bd34-dbdfd7e85911&hw=ph&test=query&l=zijzen-7), nur unterhalb von Starlette und Uvicorn selbst (die intern von FastAPI verwendet werden). + +Aber bei der Betrachtung von Benchmarks und Vergleichen sollten Sie Folgendes beachten. + +## Benchmarks und Geschwindigkeit { #benchmarks-and-speed } + +Wenn Sie die Benchmarks ansehen, ist es üblich, dass mehrere Tools unterschiedlichen Typs als gleichwertig verglichen werden. + +Insbesondere dass Uvicorn, Starlette und FastAPI zusammen verglichen werden (neben vielen anderen Tools). + +Je einfacher das Problem, das durch das Tool gelöst wird, desto besser wird die Performanz sein. Und die meisten Benchmarks testen nicht die zusätzlichen Funktionen, die das Tool bietet. + +Die Hierarchie ist wie folgt: + +* **Uvicorn**: ein ASGI-Server + * **Starlette**: (verwendet Uvicorn) ein Web-Mikroframework + * **FastAPI**: (verwendet Starlette) ein API-Mikroframework mit mehreren zusätzlichen Funktionen zum Erstellen von APIs, mit Datenvalidierung, usw. + +* **Uvicorn**: + * Wird die beste Performanz haben, da außer dem Server selbst nicht viel zusätzlicher Code vorhanden ist. + * Sie würden eine Anwendung nicht direkt in Uvicorn schreiben. Das würde bedeuten, dass Ihr Code zumindest mehr oder weniger den gesamten von Starlette (oder **FastAPI**) bereitgestellten Code enthalten müsste. Und wenn Sie das täten, hätte Ihre endgültige Anwendung den gleichen Overhead wie bei der Verwendung eines Frameworks und der Minimierung Ihres Anwendungscodes und der Fehler. + * Wenn Sie Uvicorn vergleichen, vergleichen Sie es mit Anwendungsservern wie Daphne, Hypercorn, uWSGI, usw. +* **Starlette**: + * Wird nach Uvicorn die nächstbeste Performanz erbringen. Tatsächlich verwendet Starlette Uvicorn, um zu laufen. Daher kann es wahrscheinlich nur „langsamer“ als Uvicorn werden, weil mehr Code ausgeführt werden muss. + * Aber es bietet Ihnen die Werkzeuge, um einfache Webanwendungen zu erstellen, mit Routing basierend auf Pfaden, usw. + * Wenn Sie Starlette vergleichen, vergleichen Sie es mit Webframeworks (oder Mikroframeworks) wie Sanic, Flask, Django, usw. +* **FastAPI**: + * So wie Starlette Uvicorn verwendet und nicht schneller als dieses sein kann, verwendet **FastAPI** Starlette, sodass es nicht schneller als dieses sein kann. + * FastAPI bietet zusätzliche Funktionen auf Basis von Starlette. Funktionen, die Sie beim Erstellen von APIs fast immer benötigen, wie Datenvalidierung und Serialisierung. Und wenn Sie es verwenden, erhalten Sie kostenlose automatische Dokumentation (die automatische Dokumentation verursacht nicht einmal zusätzlichen Overhead für laufende Anwendungen, sie wird beim Starten generiert). + * Wenn Sie FastAPI nicht verwenden und stattdessen Starlette direkt (oder ein anderes Tool wie Sanic, Flask, Responder, usw.) verwenden würden, müssten Sie die gesamte Datenvalidierung und Serialisierung selbst implementieren. Ihre finale Anwendung hätte also immer noch den gleichen Overhead, als ob sie mit FastAPI erstellt worden wäre. Und in vielen Fällen ist diese Datenvalidierung und Serialisierung der größte Teil des in Anwendungen geschriebenen Codes. + * Durch die Verwendung von FastAPI sparen Sie also Entwicklungszeit, Fehler und Codezeilen und würden wahrscheinlich die gleiche Performanz (oder eine bessere) erzielen, die Sie hätten, wenn Sie es nicht verwenden würden (da Sie alles in Ihrem Code implementieren müssten). + * Wenn Sie FastAPI vergleichen, vergleichen Sie es mit einem Webanwendungs-Framework (oder einer Reihe von Tools), das Datenvalidierung, Serialisierung und Dokumentation bereitstellt, wie Flask-apispec, NestJS, Molten, usw. – Frameworks mit integrierter automatischer Datenvalidierung, Serialisierung und Dokumentation. diff --git a/docs/de/docs/deployment/cloud.md b/docs/de/docs/deployment/cloud.md new file mode 100644 index 0000000000000..75f7ef8817007 --- /dev/null +++ b/docs/de/docs/deployment/cloud.md @@ -0,0 +1,24 @@ +# FastAPI bei Cloudanbietern deployen { #deploy-fastapi-on-cloud-providers } + +Sie können praktisch **jeden Cloudanbieter** verwenden, um Ihre FastAPI-Anwendung zu deployen. + +In den meisten Fällen bieten die großen Cloudanbieter Anleitungen zum Deployment von FastAPI an. + +## FastAPI Cloud { #fastapi-cloud } + +**[FastAPI Cloud](https://fastapicloud.com)** 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 } + +Einige andere Cloudanbieter ✨ [**sponsern FastAPI**](https://github.com/sponsors/tiangolo) ✨ ebenfalls. 🙇 + +Sie könnten diese ebenfalls in Betracht ziehen, deren Anleitungen folgen und ihre Dienste ausprobieren: + +* [Render](https://docs.render.com/deploy-fastapi?utm_source=deploydoc&utm_medium=referral&utm_campaign=fastapi) +* [Railway](https://docs.railway.com/guides/fastapi?utm_medium=integration&utm_source=docs&utm_campaign=fastapi) diff --git a/docs/de/docs/deployment/concepts.md b/docs/de/docs/deployment/concepts.md new file mode 100644 index 0000000000000..487ad63928924 --- /dev/null +++ b/docs/de/docs/deployment/concepts.md @@ -0,0 +1,321 @@ +# Deployment-Konzepte { #deployments-concepts } + +Beim Deployment einer **FastAPI**-Anwendung, oder eigentlich jeder Art von Web-API, gibt es mehrere Konzepte, die Sie wahrscheinlich interessieren, und mithilfe derer Sie die **am besten geeignete** Methode zum **Deployment Ihrer Anwendung** finden können. + +Einige wichtige Konzepte sind: + +* Sicherheit – HTTPS +* Beim Hochfahren ausführen +* Neustarts +* Replikation (die Anzahl der laufenden Prozesse) +* Arbeitsspeicher +* Schritte vor dem Start + +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. 🚀 + +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. + +Durch die Berücksichtigung dieser Konzepte können Sie die beste Variante des Deployments **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. + +Aber schauen wir uns zunächst einmal diese grundlegenden **konzeptionellen Ideen** an. Diese Konzepte gelten auch für jede andere Art von Web-API. 💡 + +## Sicherheit – HTTPS { #security-https } + +Im [vorherigen Kapitel über HTTPS](https.md) haben wir erfahren, wie HTTPS Verschlüsselung für Ihre API bereitstellt. + +Wir haben auch gesehen, dass HTTPS normalerweise von einer Komponente **außerhalb** Ihres Anwendungsservers bereitgestellt wird, einem **TLS-Terminierungsproxy**. + +Und es muss etwas geben, das für die **Erneuerung der HTTPS-Zertifikate** zuständig ist, es könnte sich um dieselbe Komponente handeln oder um etwas anderes. + +### Beispieltools für HTTPS { #example-tools-for-https } + +Einige der Tools, die Sie als TLS-Terminierungsproxy verwenden können, sind: + +* Traefik + * Handhabt automatisch Zertifikat-Erneuerungen ✨ +* Caddy + * Handhabt automatisch Zertifikat-Erneuerungen ✨ +* Nginx + * Mit einer externen Komponente wie Certbot für Zertifikat-Erneuerungen +* HAProxy + * Mit einer externen Komponente wie Certbot für Zertifikat-Erneuerungen +* Kubernetes mit einem Ingress Controller wie Nginx + * Mit einer externen Komponente wie cert-manager für Zertifikat-Erneuerungen +* Es wird intern von einem Cloudanbieter als Teil seiner Dienste verwaltet (siehe unten 👇) + +Eine andere Möglichkeit besteht darin, dass Sie einen **Cloud-Dienst** verwenden, der den größten Teil der Arbeit übernimmt, einschließlich der Einrichtung von HTTPS. Er könnte einige Einschränkungen haben oder Ihnen mehr in Rechnung stellen, usw. In diesem Fall müssten Sie jedoch nicht selbst einen TLS-Terminierungsproxy einrichten. + +In den nächsten Kapiteln zeige ich Ihnen einige konkrete Beispiele. + +--- + +Die nächsten zu berücksichtigenden Konzepte drehen sich dann um das Programm, das Ihre eigentliche API ausführt (z. B. Uvicorn). + +## Programm und Prozess { #program-and-process } + +Wir werden viel über den laufenden „**Prozess**“ sprechen, daher ist es nützlich, Klarheit darüber zu haben, was das bedeutet und was der Unterschied zum Wort „**Programm**“ ist. + +### Was ein Programm ist { #what-is-a-program } + +Das Wort **Programm** wird häufig zur Beschreibung vieler Dinge verwendet: + +* Der **Code**, den Sie schreiben, die **Python-Dateien**. +* Die **Datei**, die vom Betriebssystem **ausgeführt** werden kann, zum Beispiel: `python`, `python.exe` oder `uvicorn`. +* Ein bestimmtes Programm, während es auf dem Betriebssystem **läuft**, die CPU nutzt und Dinge im Arbeitsspeicher ablegt. Dies wird auch als **Prozess** bezeichnet. + +### Was ein Prozess ist { #what-is-a-process } + +Das Wort **Prozess** wird normalerweise spezifischer verwendet und bezieht sich nur auf das, was im Betriebssystem ausgeführt wird (wie im letzten Punkt oben): + +* Ein bestimmtes Programm, während es auf dem Betriebssystem **ausgeführt** wird. + * Dies bezieht sich weder auf die Datei noch auf den Code, sondern **speziell** auf das, was vom Betriebssystem **ausgeführt** und verwaltet wird. +* Jedes Programm, jeder Code **kann nur dann Dinge tun**, wenn er **ausgeführt** wird. Also dann, wenn ein **Prozess läuft**. +* Der Prozess kann von Ihnen oder vom Betriebssystem **terminiert** („beendet“, „gekillt“) werden. An diesem Punkt hört er auf zu laufen/ausgeführt zu werden und kann **keine Dinge mehr tun**. +* Hinter jeder Anwendung, die Sie auf Ihrem Computer ausführen, steckt ein Prozess, jedes laufende Programm, jedes Fenster usw. Und normalerweise laufen viele Prozesse **gleichzeitig**, während ein Computer eingeschaltet ist. +* Es können **mehrere Prozesse** desselben **Programms** gleichzeitig ausgeführt werden. + +Wenn Sie sich den „Task-Manager“ oder „Systemmonitor“ (oder ähnliche Tools) in Ihrem Betriebssystem ansehen, können Sie viele dieser laufenden Prozesse sehen. + +Und Sie werden beispielsweise wahrscheinlich feststellen, dass mehrere Prozesse dasselbe Browserprogramm ausführen (Firefox, Chrome, Edge, usw.). Normalerweise führen diese einen Prozess pro Browsertab sowie einige andere zusätzliche Prozesse aus. + + + +--- + +Nachdem wir nun den Unterschied zwischen den Begriffen **Prozess** und **Programm** kennen, sprechen wir weiter über das Deployment. + +## Beim Hochfahren ausführen { #running-on-startup } + +Wenn Sie eine Web-API erstellen, möchten Sie in den meisten Fällen, dass diese **immer läuft**, ununterbrochen, damit Ihre Clients immer darauf zugreifen können. Es sei denn natürlich, Sie haben einen bestimmten Grund, warum Sie möchten, dass diese nur in bestimmten Situationen ausgeführt wird. Meistens möchten Sie jedoch, dass sie ständig ausgeführt wird und **verfügbar** ist. + +### Auf einem entfernten Server { #in-a-remote-server } + +Wenn Sie einen entfernten Server (einen Cloud-Server, eine virtuelle Maschine, usw.) einrichten, können Sie am einfachsten `fastapi run` (welches Uvicorn verwendet) oder etwas Ähnliches manuell ausführen, genau wie bei der lokalen Entwicklung. + +Und es wird funktionieren und **während der Entwicklung** nützlich sein. + +Wenn Ihre Verbindung zum Server jedoch unterbrochen wird, wird der **laufende Prozess** wahrscheinlich abstürzen. + +Und wenn der Server neu gestartet wird (z. B. nach Updates oder Migrationen vom Cloudanbieter), werden Sie das wahrscheinlich **nicht bemerken**. Und deshalb wissen Sie nicht einmal, dass Sie den Prozess manuell neu starten müssen. Ihre API bleibt also einfach tot. 😱 + +### Beim Hochfahren automatisch ausführen { #run-automatically-on-startup } + +Im Allgemeinen möchten Sie wahrscheinlich, dass das Serverprogramm (z. B. Uvicorn) beim Hochfahren des Servers automatisch gestartet wird und kein **menschliches Eingreifen** erforderlich ist, sodass immer ein Prozess mit Ihrer API ausgeführt wird (z. B. Uvicorn, welches Ihre FastAPI-Anwendung ausführt). + +### Separates Programm { #separate-program } + +Um dies zu erreichen, haben Sie normalerweise ein **separates Programm**, welches sicherstellt, dass Ihre Anwendung beim Hochfahren ausgeführt wird. Und in vielen Fällen würde es auch sicherstellen, dass auch andere Komponenten oder Anwendungen ausgeführt werden, beispielsweise eine Datenbank. + +### Beispieltools zur Ausführung beim Hochfahren { #example-tools-to-run-at-startup } + +Einige Beispiele für Tools, die diese Aufgabe übernehmen können, sind: + +* Docker +* Kubernetes +* Docker Compose +* Docker im Swarm-Modus +* Systemd +* Supervisor +* Es wird intern von einem Cloudanbieter im Rahmen seiner Dienste verwaltet +* Andere ... + +In den nächsten Kapiteln werde ich Ihnen konkretere Beispiele geben. + +## Neustart { #restarts } + +Ähnlich wie Sie sicherstellen möchten, dass Ihre Anwendung beim Hochfahren ausgeführt wird, möchten Sie wahrscheinlich auch sicherstellen, dass diese nach Fehlern **neu gestartet** wird. + +### Wir machen Fehler { #we-make-mistakes } + +Wir, als Menschen, machen ständig **Fehler**. Software hat fast *immer* **Bugs**, die an verschiedenen Stellen versteckt sind. 🐛 + +Und wir als Entwickler verbessern den Code ständig, wenn wir diese Bugs finden und neue Funktionen implementieren (und möglicherweise auch neue Bugs hinzufügen 😅). + +### Kleine Fehler automatisch handhaben { #small-errors-automatically-handled } + +Wenn beim Erstellen von Web-APIs mit FastAPI ein Fehler in unserem Code auftritt, wird FastAPI ihn normalerweise auf den einzelnen Request beschränken, der den Fehler ausgelöst hat. 🛡 + +Der Client erhält für diesen Request einen **500 Internal Server Error**, aber die Anwendung arbeitet bei den nächsten Requests weiter, anstatt einfach komplett abzustürzen. + +### Größere Fehler – Abstürze { #bigger-errors-crashes } + +Dennoch kann es vorkommen, dass wir Code schreiben, der **die gesamte Anwendung zum Absturz bringt** und so zum Absturz von Uvicorn und Python führt. 💥 + +Und dennoch möchten Sie wahrscheinlich nicht, dass die Anwendung tot bleibt, weil an einer Stelle ein Fehler aufgetreten ist. Sie möchten wahrscheinlich, dass sie zumindest für die *Pfadoperationen*, die nicht fehlerhaft sind, **weiterläuft**. + +### Neustart nach Absturz { #restart-after-crash } + +Aber in den Fällen mit wirklich schwerwiegenden Fehlern, die den laufenden **Prozess** zum Absturz bringen, benötigen Sie eine externe Komponente, die den Prozess **neu startet**, zumindest ein paar Mal ... + +/// tip | Tipp + +... Obwohl es wahrscheinlich keinen Sinn macht, sie immer wieder neu zu starten, wenn die gesamte Anwendung einfach **sofort abstürzt**. Aber in diesen Fällen werden Sie es wahrscheinlich während der Entwicklung oder zumindest direkt nach dem Deployment bemerken. + +Konzentrieren wir uns also auf die Hauptfälle, in denen die Anwendung in bestimmten Fällen **in der Zukunft** völlig abstürzen könnte und es dann dennoch sinnvoll ist, sie neu zu starten. + +/// + +Sie möchten wahrscheinlich, dass eine **externe Komponente** für den Neustart Ihrer Anwendung verantwortlich ist, da zu diesem Zeitpunkt dieselbe Anwendung mit Uvicorn und Python bereits abgestürzt ist und es daher nichts im selben Code derselben Anwendung gibt, was etwas dagegen tun kann. + +### Beispieltools zum automatischen Neustart { #example-tools-to-restart-automatically } + +In den meisten Fällen wird dasselbe Tool, das zum **Ausführen des Programms beim Hochfahren** verwendet wird, auch für automatische **Neustarts** verwendet. + +Dies könnte zum Beispiel erledigt werden durch: + +* Docker +* Kubernetes +* Docker Compose +* Docker im Swarm-Modus +* Systemd +* Supervisor +* Intern von einem Cloudanbieter im Rahmen seiner Dienste +* Andere ... + +## Replikation – Prozesse und Arbeitsspeicher { #replication-processes-and-memory } + +Wenn Sie eine FastAPI-Anwendung verwenden und ein Serverprogramm wie den `fastapi`-Befehl, der Uvicorn ausführt, kann die Ausführung in **einem Prozess** mehrere Clients gleichzeitig versorgen. + +In vielen Fällen möchten Sie jedoch mehrere Workerprozesse gleichzeitig ausführen. + +### Mehrere Prozesse – Worker { #multiple-processes-workers } + +Wenn Sie mehr Clients haben, als ein einzelner Prozess verarbeiten kann (z. B. wenn die virtuelle Maschine nicht sehr groß ist) und die CPU des Servers **mehrere Kerne** hat, dann könnten **mehrere Prozesse** gleichzeitig mit derselben Anwendung laufen und alle Requests unter sich verteilen. + +Wenn Sie mit **mehreren Prozessen** dasselbe API-Programm ausführen, werden diese üblicherweise als **Worker** bezeichnet. + +### Workerprozesse und Ports { #worker-processes-and-ports } + +Erinnern Sie sich aus der Dokumentation [Über HTTPS](https.md), dass nur ein Prozess auf einer Kombination aus Port und IP-Adresse auf einem Server lauschen kann? + +Das ist immer noch wahr. + +Um also **mehrere Prozesse** gleichzeitig zu haben, muss es einen **einzelnen Prozess geben, der einen Port überwacht**, welcher dann die Kommunikation auf irgendeine Weise an jeden Workerprozess überträgt. + +### Arbeitsspeicher pro Prozess { #memory-per-process } + +Wenn das Programm nun Dinge in den Arbeitsspeicher lädt, zum Beispiel ein Modell für maschinelles Lernen in einer Variablen oder den Inhalt einer großen Datei in einer Variablen, verbraucht das alles **einen Teil des Arbeitsspeichers (RAM – Random Access Memory)** des Servers. + +Und mehrere Prozesse **teilen sich normalerweise keinen Speicher**. Das bedeutet, dass jeder laufende Prozess seine eigenen Dinge, eigenen Variablen und eigenen Speicher hat. Und wenn Sie in Ihrem Code viel Speicher verbrauchen, verbraucht **jeder Prozess** die gleiche Menge Speicher. + +### Serverspeicher { #server-memory } + +Wenn Ihr Code beispielsweise ein Machine-Learning-Modell mit **1 GB Größe** lädt und Sie einen Prozess mit Ihrer API ausführen, verbraucht dieser mindestens 1 GB RAM. Und wenn Sie **4 Prozesse** (4 Worker) starten, verbraucht jeder 1 GB RAM. Insgesamt verbraucht Ihre API also **4 GB RAM**. + +Und wenn Ihr entfernter Server oder Ihre virtuelle Maschine nur über 3 GB RAM verfügt, führt der Versuch, mehr als 4 GB RAM zu laden, zu Problemen. 🚨 + +### Mehrere Prozesse – Ein Beispiel { #multiple-processes-an-example } + +Im folgenden Beispiel gibt es einen **Manager-Prozess**, welcher zwei **Workerprozesse** startet und steuert. + +Dieser Manager-Prozess wäre wahrscheinlich derjenige, welcher der IP am **Port** lauscht. Und er würde die gesamte Kommunikation an die Workerprozesse weiterleiten. + +Diese Workerprozesse würden Ihre Anwendung ausführen, sie würden die Hauptberechnungen durchführen, um einen **Request** entgegenzunehmen und eine **Response** zurückzugeben, und sie würden alles, was Sie in Variablen einfügen, in den RAM laden. + + + +Und natürlich würden auf derselben Maschine neben Ihrer Anwendung wahrscheinlich **andere Prozesse** laufen. + +Ein interessantes Detail ist dabei, dass der Prozentsatz der von jedem Prozess verwendeten **CPU** im Laufe der Zeit stark **variieren** kann, der **Arbeitsspeicher (RAM)** jedoch normalerweise mehr oder weniger **stabil** bleibt. + +Wenn Sie eine API haben, die jedes Mal eine vergleichbare Menge an Berechnungen durchführt, und Sie viele Clients haben, dann wird die **CPU-Auslastung** wahrscheinlich *ebenfalls stabil sein* (anstatt ständig schnell zu steigen und zu fallen). + +### Beispiele für Replikation-Tools und -Strategien { #examples-of-replication-tools-and-strategies } + +Es gibt mehrere Ansätze, um dies zu erreichen, und ich werde Ihnen in den nächsten Kapiteln mehr über bestimmte Strategien erzählen, beispielsweise wenn es um Docker und Container geht. + +Die wichtigste zu berücksichtigende Einschränkung besteht darin, dass es eine **einzelne** Komponente geben muss, welche die **öffentliche IP** auf dem **Port** verwaltet. Und dann muss diese irgendwie die Kommunikation **weiterleiten**, an die replizierten **Prozesse/Worker**. + +Hier sind einige mögliche Kombinationen und Strategien: + +* **Uvicorn** mit `--workers` + * Ein Uvicorn-**Prozessmanager** würde der **IP** am **Port** lauschen, und er würde **mehrere Uvicorn-Workerprozesse** starten. +* **Kubernetes** und andere verteilte **Containersysteme** + * Etwas in der **Kubernetes**-Ebene würde die **IP** und den **Port** abhören. Die Replikation hätte **mehrere Container**, in jedem wird jeweils **ein Uvicorn-Prozess** ausgeführt. +* **Cloud-Dienste**, welche das für Sie erledigen + * Der Cloud-Dienst wird wahrscheinlich **die Replikation für Sie übernehmen**. Er würde Sie möglicherweise **einen auszuführenden Prozess** oder ein **zu verwendendes Container-Image** definieren lassen, in jedem Fall wäre es höchstwahrscheinlich **ein einzelner Uvicorn-Prozess**, und der Cloud-Dienst wäre auch verantwortlich für die Replikation. + +/// tip | Tipp + +Machen Sie sich keine Sorgen, wenn einige dieser Punkte zu **Containern**, Docker oder Kubernetes noch nicht viel Sinn ergeben. + +Ich werde Ihnen in einem zukünftigen Kapitel mehr über Container-Images, Docker, Kubernetes, usw. erzählen: [FastAPI in Containern – Docker](docker.md). + +/// + +## Schritte vor dem Start { #previous-steps-before-starting } + +Es gibt viele Fälle, in denen Sie, **bevor Sie Ihre Anwendung starten**, einige Schritte ausführen möchten. + +Beispielsweise möchten Sie möglicherweise **Datenbankmigrationen** ausführen. + +In den meisten Fällen möchten Sie diese Schritte jedoch nur **einmal** ausführen. + +Sie möchten also einen **einzelnen Prozess** haben, um diese **Vorab-Schritte** auszuführen, bevor Sie die Anwendung starten. + +Und Sie müssen sicherstellen, dass es sich um einen einzelnen Prozess handelt, der die Vorab-Schritte ausführt, *auch* wenn Sie anschließend **mehrere Prozesse** (mehrere Worker) für die Anwendung selbst starten. Wenn diese Schritte von **mehreren Prozessen** ausgeführt würden, würden diese die Arbeit **verdoppeln**, indem sie sie **parallel** ausführen, und wenn es sich bei den Schritten um etwas Delikates wie eine Datenbankmigration handelt, könnte das miteinander Konflikte verursachen. + +Natürlich gibt es Fälle, in denen es kein Problem darstellt, die Vorab-Schritte mehrmals auszuführen. In diesem Fall ist die Handhabung viel einfacher. + +/// tip | Tipp + +Bedenken Sie außerdem, dass Sie, abhängig von Ihrer Einrichtung, in manchen Fällen **gar keine Vorab-Schritte** benötigen, bevor Sie die Anwendung starten. + +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 } + +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. + +Hier sind einige mögliche Ideen: + +* Ein „Init-Container“ in Kubernetes, der vor Ihrem Anwendungs-Container ausgeführt wird +* Ein Bash-Skript, das die Vorab-Schritte ausführt und dann Ihre Anwendung startet + * Sie benötigen immer noch eine Möglichkeit, *dieses* Bash-Skript zu starten/neu zu starten, Fehler zu erkennen, usw. + +/// tip | Tipp + +Konkretere Beispiele hierfür mit Containern gebe ich Ihnen in einem späteren Kapitel: [FastAPI in Containern – Docker](docker.md). + +/// + +## Ressourcennutzung { #resource-utilization } + +Ihr(e) Server ist (sind) eine **Ressource**, welche Sie mit Ihren Programmen, der Rechenzeit auf den CPUs und dem verfügbaren RAM-Speicher verbrauchen oder **nutzen** können. + +Wie viele Systemressourcen möchten Sie verbrauchen/nutzen? Sie mögen „nicht viel“ denken, aber in Wirklichkeit möchten Sie tatsächlich **so viel wie möglich ohne Absturz** verwenden. + +Wenn Sie für drei Server bezahlen, aber nur wenig von deren RAM und CPU nutzen, **verschwenden Sie wahrscheinlich Geld** 💸 und wahrscheinlich **Strom für den Server** 🌎, usw. + +In diesem Fall könnte es besser sein, nur zwei Server zu haben und einen höheren Prozentsatz von deren Ressourcen zu nutzen (CPU, Arbeitsspeicher, Festplatte, Netzwerkbandbreite, usw.). + +Wenn Sie andererseits über zwei Server verfügen und **100 % ihrer CPU und ihres RAM** nutzen, wird irgendwann ein Prozess nach mehr Speicher fragen und der Server muss die Festplatte als „Speicher“ verwenden (was tausendmal langsamer sein kann) oder er könnte sogar **abstürzen**. Oder ein Prozess muss möglicherweise einige Berechnungen durchführen und müsste warten, bis die CPU wieder frei ist. + +In diesem Fall wäre es besser, **einen zusätzlichen Server** zu besorgen und einige Prozesse darauf auszuführen, damit alle über **genug RAM und CPU-Zeit** verfügen. + +Es besteht auch die Möglichkeit, dass es aus irgendeinem Grund zu **Spitzen** in der Nutzung Ihrer API kommt. Vielleicht ist diese viral gegangen, oder vielleicht haben andere Dienste oder Bots damit begonnen, sie zu nutzen. Und vielleicht möchten Sie in solchen Fällen über zusätzliche Ressourcen verfügen, um auf der sicheren Seite zu sein. + +Sie können eine **beliebige Zahl** festlegen, um beispielsweise eine Ressourcenauslastung zwischen **50 % und 90 %** anzustreben. Der Punkt ist, dass dies wahrscheinlich die wichtigen Dinge sind, die Sie messen und verwenden sollten, um Ihre Deployments zu optimieren. + +Sie können einfache Tools wie `htop` verwenden, um die in Ihrem Server verwendete CPU und den RAM oder die von jedem Prozess verwendete Menge anzuzeigen. Oder Sie können komplexere Überwachungstools verwenden, die möglicherweise auf mehrere Server usw. verteilt sind. + +## 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: + +* Sicherheit – HTTPS +* Beim Hochfahren ausführen +* Neustarts +* Replikation (die Anzahl der laufenden Prozesse) +* Arbeitsspeicher +* Schritte vor dem Start + +Das Verständnis dieser Ideen und deren Anwendung sollte Ihnen die nötige Intuition vermitteln, um bei der Konfiguration und Optimierung Ihrer Deployments Entscheidungen zu treffen. 🤓 + +In den nächsten Abschnitten gebe ich Ihnen konkretere Beispiele für mögliche Strategien, die Sie verfolgen können. 🚀 diff --git a/docs/de/docs/deployment/docker.md b/docs/de/docs/deployment/docker.md new file mode 100644 index 0000000000000..0ab886c467dfa --- /dev/null +++ b/docs/de/docs/deployment/docker.md @@ -0,0 +1,618 @@ +# 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 [**Docker**](https://www.docker.com/). Sie können dieses Containerimage dann auf eine von mehreren möglichen Arten deployen. + +Die Verwendung von Linux-Containern bietet mehrere Vorteile, darunter **Sicherheit**, **Replizierbarkeit**, **Einfachheit** und andere. + +/// tip | Tipp + +Sie haben es eilig und kennen sich bereits aus? Springen Sie zum [`Dockerfile` unten 👇](#build-a-docker-image-for-fastapi). + +/// + +
+Dockerfile-Vorschau 👀 + +```Dockerfile +FROM python:3.14 + +WORKDIR /code + +COPY ./requirements.txt /code/requirements.txt + +RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt + +COPY ./app /code/app + +CMD ["fastapi", "run", "app/main.py", "--port", "80"] + +# Wenn Sie hinter einem Proxy wie Nginx oder Traefik sind, fügen Sie --proxy-headers hinzu +# CMD ["fastapi", "run", "app/main.py", "--port", "80", "--proxy-headers"] +``` + +
+ +## Was ist ein Container { #what-is-a-container } + +Container (hauptsächlich Linux-Container) sind eine sehr **leichtgewichtige** Möglichkeit, Anwendungen einschließlich aller ihrer Abhängigkeiten und erforderlichen Dateien zu verpacken und sie gleichzeitig von anderen Containern (anderen Anwendungen oder Komponenten) im selben System isoliert zu halten. + +Linux-Container werden mit demselben Linux-Kernel des Hosts (Maschine, virtueller Maschine, Cloud-Server usw.) ausgeführt. Das bedeutet einfach, dass sie sehr leichtgewichtig sind (im Vergleich zu vollständigen virtuellen Maschinen, die ein gesamtes Betriebssystem emulieren). + +Auf diese Weise verbrauchen Container **wenig Ressourcen**, eine Menge vergleichbar mit der direkten Ausführung der Prozesse (eine virtuelle Maschine würde viel mehr verbrauchen). + +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. + +## Was ist ein Containerimage { #what-is-a-container-image } + +Ein **Container** wird von einem **Containerimage** ausgeführt. + +Ein Containerimage ist eine **statische** Version aller Dateien, Umgebungsvariablen und des Standardbefehls/-programms, die in einem Container vorhanden sein sollten. **Statisch** bedeutet hier, dass das Container-**Image** nicht läuft, nicht ausgeführt wird, sondern nur die gepackten Dateien und Metadaten enthält. + +Im Gegensatz zu einem „**Containerimage**“, bei dem es sich um den gespeicherten statischen Inhalt handelt, bezieht sich ein „**Container**“ normalerweise auf die laufende Instanz, das Ding, das **ausgeführt** wird. + +Wenn der **Container** gestartet und ausgeführt wird (gestartet von einem **Containerimage**), kann er Dateien, Umgebungsvariablen usw. erstellen oder ändern. Diese Änderungen sind nur in diesem Container vorhanden, nicht im zugrunde liegenden Containerimage (werden nicht auf der Festplatte gespeichert). + +Ein Containerimage ist vergleichbar mit der **Programmdatei** und ihrem Inhalt, z. B. `python` und eine Datei `main.py`. + +Und der **Container** selbst (im Gegensatz zum **Containerimage**) ist die tatsächlich laufende Instanz des Images, vergleichbar mit einem **Prozess**. Tatsächlich läuft ein Container nur, wenn er einen **laufenden Prozess** hat (und normalerweise ist es nur ein einzelner Prozess). Der Container stoppt, wenn kein Prozess darin ausgeführt wird. + +## Containerimages { #container-images } + +Docker ist eines der wichtigsten Tools zum Erstellen und Verwalten von **Containerimages** und **Containern**. + +Und es gibt einen öffentlichen [Docker Hub](https://hub.docker.com/) mit vorgefertigten **offiziellen Containerimages** für viele Tools, Umgebungen, Datenbanken und Anwendungen. + +Beispielsweise gibt es ein offizielles [Python-Image](https://hub.docker.com/_/python). + +Und es gibt viele andere Images für verschiedene Dinge wie Datenbanken, zum Beispiel für: + +* [PostgreSQL](https://hub.docker.com/_/postgres) +* [MySQL](https://hub.docker.com/_/mysql) +* [MongoDB](https://hub.docker.com/_/mongo) +* [Redis](https://hub.docker.com/_/redis), usw. + +Durch die Verwendung eines vorgefertigten Containerimages ist es sehr einfach, verschiedene Tools zu **kombinieren** und zu verwenden. Zum Beispiel, um eine neue Datenbank auszuprobieren. In den meisten Fällen können Sie die **offiziellen Images** verwenden und diese einfach mit Umgebungsvariablen konfigurieren. + +Auf diese Weise können Sie in vielen Fällen etwas über Container und Docker lernen und dieses Wissen mit vielen verschiedenen Tools und Komponenten wiederverwenden. + +Sie würden also **mehrere Container** mit unterschiedlichen Dingen ausführen, wie einer Datenbank, einer Python-Anwendung, einem Webserver mit einer React-Frontend-Anwendung, und diese über ihr internes Netzwerk miteinander verbinden. + +In alle Containerverwaltungssysteme (wie Docker oder Kubernetes) sind diese Netzwerkfunktionen integriert. + +## Container und Prozesse { #containers-and-processes } + +Ein **Containerimage** enthält normalerweise in seinen Metadaten das Standardprogramm oder den Standardbefehl, der ausgeführt werden soll, wenn der **Container** gestartet wird, sowie die Parameter, die an dieses Programm übergeben werden sollen. Sehr ähnlich zu dem, was wäre, wenn es über die Befehlszeile gestartet werden würde. + +Wenn ein **Container** gestartet wird, führt er diesen Befehl/dieses Programm aus (Sie können ihn jedoch überschreiben und einen anderen Befehl/ein anderes Programm ausführen lassen). + +Ein Container läuft, solange der **Hauptprozess** (Befehl oder Programm) läuft. + +Ein Container hat normalerweise einen **einzelnen Prozess**, aber es ist auch möglich, Unterprozesse vom Hauptprozess aus zu starten, und auf diese Weise haben Sie **mehrere Prozesse** im selben Container. + +Es ist jedoch nicht möglich, einen laufenden Container ohne **mindestens einen laufenden Prozess** zu haben. Wenn der Hauptprozess stoppt, stoppt der Container. + +## Ein Docker-Image für FastAPI erstellen { #build-a-docker-image-for-fastapi } + +Okay, wollen wir jetzt etwas bauen! 🚀 + +Ich zeige Ihnen, wie Sie ein **Docker-Image** für FastAPI **von Grund auf** erstellen, basierend auf dem **offiziellen Python**-Image. + +Das ist, was Sie in **den meisten Fällen** tun möchten, zum Beispiel: + +* Bei Verwendung von **Kubernetes** oder ähnlichen Tools +* Beim Betrieb auf einem **Raspberry Pi** +* Bei Verwendung eines Cloud-Dienstes, der ein Containerimage für Sie ausführt, usw. + +### Paketanforderungen { #package-requirements } + +Normalerweise befinden sich die **Paketanforderungen** für Ihre Anwendung in einer Datei. + +Dies hängt hauptsächlich von dem Tool ab, mit dem Sie diese Anforderungen **installieren**. + +Die gebräuchlichste Methode besteht darin, eine Datei `requirements.txt` mit den Namen der Packages und deren Versionen zu erstellen, eine pro Zeile. + +Sie würden natürlich die gleichen Ideen verwenden, die Sie in [Über FastAPI-Versionen](versions.md) gelesen haben, um die Versionsbereiche festzulegen. + +Ihre `requirements.txt` könnte beispielsweise so aussehen: + +``` +fastapi[standard]>=0.113.0,<0.114.0 +pydantic>=2.7.0,<3.0.0 +``` + +Und normalerweise würden Sie diese Paketabhängigkeiten mit `pip` installieren, zum Beispiel: + +
+ +```console +$ pip install -r requirements.txt +---> 100% +Successfully installed fastapi pydantic +``` + +
+ +/// note | Hinweis + +Es gibt andere Formate und Tools zum Definieren und Installieren von Paketabhängigkeiten. + +/// + +### Den **FastAPI**-Code erstellen { #create-the-fastapi-code } + +* Erstellen Sie ein `app`-Verzeichnis und betreten Sie es. +* Erstellen Sie eine leere Datei `__init__.py`. +* Erstellen Sie eine `main.py`-Datei mit: + +```Python +from fastapi import FastAPI + +app = FastAPI() + + +@app.get("/") +def read_root(): + return {"Hello": "World"} + + +@app.get("/items/{item_id}") +def read_item(item_id: int, q: str | None = None): + return {"item_id": item_id, "q": q} +``` + +### Dockerfile { #dockerfile } + +Erstellen Sie nun im selben Projektverzeichnis eine Datei `Dockerfile` mit: + +```{ .dockerfile .annotate } +# (1)! +FROM python:3.14 + +# (2)! +WORKDIR /code + +# (3)! +COPY ./requirements.txt /code/requirements.txt + +# (4)! +RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt + +# (5)! +COPY ./app /code/app + +# (6)! +CMD ["fastapi", "run", "app/main.py", "--port", "80"] +``` + +1. Beginnen Sie mit dem offiziellen Python-Basisimage. + +2. Setzen Sie das aktuelle Arbeitsverzeichnis auf `/code`. + + Hier platzieren wir die Datei `requirements.txt` und das Verzeichnis `app`. + +3. Kopieren Sie die Datei mit den Paketanforderungen in das Verzeichnis `/code`. + + Kopieren Sie zuerst **nur** die Datei mit den Anforderungen, nicht den Rest des Codes. + + Da sich diese Datei **nicht oft ändert**, erkennt Docker das und verwendet den **Cache** für diesen Schritt, wodurch der Cache auch für den nächsten Schritt aktiviert wird. + +4. Installieren Sie die Paketabhängigkeiten aus der Anforderungsdatei. + + Die Option `--no-cache-dir` weist `pip` an, die heruntergeladenen Pakete nicht lokal zu speichern, da dies nur benötigt wird, sollte `pip` erneut ausgeführt werden, um dieselben Pakete zu installieren, aber das ist beim Arbeiten mit Containern nicht der Fall. + + /// note | Hinweis + + Das `--no-cache-dir` bezieht sich nur auf `pip`, es hat nichts mit Docker oder Containern zu tun. + + /// + + Die Option `--upgrade` weist `pip` an, die Packages zu aktualisieren, wenn sie bereits installiert sind. + + Da der vorherige Schritt des Kopierens der Datei vom **Docker-Cache** erkannt werden konnte, wird dieser Schritt auch **den Docker-Cache verwenden**, sofern verfügbar. + + Durch die Verwendung des Caches in diesem Schritt **sparen** Sie viel **Zeit**, wenn Sie das Image während der Entwicklung immer wieder erstellen, anstatt **jedes Mal** alle Abhängigkeiten **herunterzuladen und zu installieren**. + +5. Kopieren Sie das Verzeichnis `./app` in das Verzeichnis `/code`. + + Da hier der gesamte Code enthalten ist, der sich **am häufigsten ändert**, wird der Docker-**Cache** nicht ohne weiteres für diesen oder andere **folgende Schritte** verwendet. + + Daher ist es wichtig, dies **nahe dem Ende** des `Dockerfile`s zu platzieren, um die Erstellungszeiten des Containerimages zu optimieren. + +6. Legen Sie den **Befehl** fest, um `fastapi run` zu nutzen, welches Uvicorn darunter verwendet. + + `CMD` nimmt eine Liste von Zeichenfolgen entgegen. Jede dieser Zeichenfolgen entspricht dem, was Sie durch Leerzeichen getrennt in die Befehlszeile eingeben würden. + + Dieser Befehl wird aus dem **aktuellen Arbeitsverzeichnis** ausgeführt, dem gleichen `/code`-Verzeichnis, das Sie oben mit `WORKDIR /code` festgelegt haben. + +/// tip | Tipp + +Lernen Sie, was jede Zeile bewirkt, indem Sie auf die Zahlenblasen im Code klicken. 👆 + +/// + +/// warning | Achtung + +Stellen Sie sicher, dass Sie **immer** die **exec form** der Anweisung `CMD` verwenden, wie unten erläutert. + +/// + +#### `CMD` – Exec Form verwenden { #use-cmd-exec-form } + +Die [`CMD`](https://docs.docker.com/reference/dockerfile/#cmd) Docker-Anweisung kann in zwei Formen geschrieben werden: + +✅ **Exec** form: + +```Dockerfile +# ✅ Tun Sie das +CMD ["fastapi", "run", "app/main.py", "--port", "80"] +``` + +⛔️ **Shell** form: + +```Dockerfile +# ⛔️ Tun Sie das nicht +CMD fastapi run app/main.py --port 80 +``` + +Achten Sie darauf, stets die **exec** form zu verwenden, um sicherzustellen, dass FastAPI ordnungsgemäß heruntergefahren wird und [Lifespan-Events](../advanced/events.md) ausgelöst werden. + +Sie können mehr darüber in der [Docker-Dokumentation für Shell und Exec Form lesen](https://docs.docker.com/reference/dockerfile/#shell-and-exec-form). + +Dies kann insbesondere bei der Verwendung von `docker compose` deutlich spürbar sein. Sehen Sie sich diesen Abschnitt in der Docker Compose-FAQ für technische Details an: [Warum benötigen meine Dienste 10 Sekunden, um neu erstellt oder gestoppt zu werden?](https://docs.docker.com/compose/faq/#why-do-my-services-take-10-seconds-to-recreate-or-stop). + +#### Verzeichnisstruktur { #directory-structure } + +Sie sollten jetzt eine Verzeichnisstruktur wie diese haben: + +``` +. +├── app +│   ├── __init__.py +│ └── main.py +├── Dockerfile +└── requirements.txt +``` + +#### Hinter einem TLS-Terminierungsproxy { #behind-a-tls-termination-proxy } + +Wenn Sie Ihren Container hinter einem TLS-Terminierungsproxy (Load Balancer) wie Nginx oder Traefik ausführen, fügen Sie die Option `--proxy-headers` hinzu. Das sagt Uvicorn (durch das FastAPI CLI), den von diesem Proxy gesendeten Headern zu vertrauen und dass die Anwendung hinter HTTPS ausgeführt wird, usw. + +```Dockerfile +CMD ["fastapi", "run", "app/main.py", "--proxy-headers", "--port", "80"] +``` + +#### Docker-Cache { #docker-cache } + +In diesem `Dockerfile` gibt es einen wichtigen Trick: Wir kopieren zuerst die **Datei nur mit den Abhängigkeiten**, nicht den Rest des Codes. Lassen Sie mich Ihnen erklären, warum. + +```Dockerfile +COPY ./requirements.txt /code/requirements.txt +``` + +Docker und andere Tools **erstellen** diese Containerimages **inkrementell**, fügen **eine Ebene über der anderen** hinzu, beginnend am Anfang des `Dockerfile`s und fügen alle durch die einzelnen Anweisungen des `Dockerfile`s erstellten Dateien hinzu. + +Docker und ähnliche Tools verwenden beim Erstellen des Images auch einen **internen Cache**. Wenn sich eine Datei seit der letzten Erstellung des Containerimages nicht geändert hat, wird **dieselbe Ebene wiederverwendet**, die beim letzten Mal erstellt wurde, anstatt die Datei erneut zu kopieren und eine neue Ebene von Grund auf zu erstellen. + +Das bloße Vermeiden des Kopierens von Dateien führt nicht unbedingt zu einer großen Verbesserung, aber da der Cache für diesen Schritt verwendet wurde, kann **der Cache für den nächsten Schritt verwendet werden**. Beispielsweise könnte der Cache verwendet werden für die Anweisung, welche die Abhängigkeiten installiert mit: + +```Dockerfile +RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt +``` + +Die Datei mit den Paketanforderungen wird sich **nicht häufig ändern**. Wenn Docker also nur diese Datei kopiert, kann es für diesen Schritt **den Cache verwenden**. + +Und dann kann Docker **den Cache für den nächsten Schritt verwenden**, der diese Abhängigkeiten herunterlädt und installiert. Und hier **sparen wir viel Zeit**. ✨ ... und vermeiden die Langeweile beim Warten. 😪😆 + +Das Herunterladen und Installieren der Paketabhängigkeiten **könnte Minuten dauern**, aber die Verwendung des **Cache** würde höchstens **Sekunden** dauern. + +Und da Sie das Containerimage während der Entwicklung immer wieder erstellen würden, um zu überprüfen, ob Ihre Codeänderungen funktionieren, würde dies viel Zeit sparen. + +Dann, gegen Ende des `Dockerfile`s, kopieren wir den gesamten Code. Da sich der **am häufigsten ändert**, platzieren wir das am Ende, da fast immer alles nach diesem Schritt nicht mehr in der Lage sein wird, den Cache zu verwenden. + +```Dockerfile +COPY ./app /code/app +``` + +### Das Docker-Image erstellen { #build-the-docker-image } + +Nachdem nun alle Dateien vorhanden sind, erstellen wir das Containerimage. + +* Gehen Sie zum Projektverzeichnis (dort, wo sich Ihr `Dockerfile` und Ihr `app`-Verzeichnis befindet). +* Erstellen Sie Ihr FastAPI-Image: + +
+ +```console +$ docker build -t myimage . + +---> 100% +``` + +
+ +/// tip | Tipp + +Beachten Sie das `.` am Ende, es entspricht `./` und teilt Docker mit, welches Verzeichnis zum Erstellen des Containerimages verwendet werden soll. + +In diesem Case handelt es sich um dasselbe aktuelle Verzeichnis (`.`). + +/// + +### Den Docker-Container starten { #start-the-docker-container } + +* Führen Sie einen Container basierend auf Ihrem Image aus: + +
+ +```console +$ docker run -d --name mycontainer -p 80:80 myimage +``` + +
+ +## Es testen { #check-it } + +Sie sollten es in der URL Ihres Docker-Containers überprüfen können, zum Beispiel: [http://192.168.99.100/items/5?q=somequery](http://192.168.99.100/items/5?q=somequery) oder [http://127.0.0.1/items/5?q=somequery](http://127.0.0.1/items/5?q=somequery) (oder gleichwertig, unter Verwendung Ihres Docker-Hosts). + +Sie werden etwas sehen wie: + +```JSON +{"item_id": 5, "q": "somequery"} +``` + +## Interaktive API-Dokumentation { #interactive-api-docs } + +Jetzt können Sie auf [http://192.168.99.100/docs](http://192.168.99.100/docs) oder [http://127.0.0.1/docs](http://127.0.0.1/docs) gehen (oder ähnlich, unter Verwendung Ihres Docker-Hosts). + +Sie sehen die automatische interaktive API-Dokumentation (bereitgestellt von [Swagger UI](https://github.com/swagger-api/swagger-ui)): + +![Swagger-Oberfläche](https://fastapi.tiangolo.com/img/index/index-01-swagger-ui-simple.png) + +## Alternative API-Dokumentation { #alternative-api-docs } + +Sie können auch auf [http://192.168.99.100/redoc](http://192.168.99.100/redoc) oder [http://127.0.0.1/redoc](http://127.0.0.1/redoc) gehen (oder ähnlich, unter Verwendung Ihres Docker-Hosts). + +Sie sehen die alternative automatische Dokumentation (bereitgestellt von [ReDoc](https://github.com/Rebilly/ReDoc)): + +![ReDoc](https://fastapi.tiangolo.com/img/index/index-02-redoc-simple.png) + +## Ein Docker-Image mit einem Single-File-FastAPI erstellen { #build-a-docker-image-with-a-single-file-fastapi } + +Wenn Ihr FastAPI eine einzelne Datei ist, zum Beispiel `main.py` ohne ein `./app`-Verzeichnis, könnte Ihre Dateistruktur wie folgt aussehen: + +``` +. +├── Dockerfile +├── main.py +└── requirements.txt +``` + +Dann müssten Sie nur noch die entsprechenden Pfade ändern, um die Datei im `Dockerfile` zu kopieren: + +```{ .dockerfile .annotate hl_lines="10 13" } +FROM python:3.14 + +WORKDIR /code + +COPY ./requirements.txt /code/requirements.txt + +RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt + +# (1)! +COPY ./main.py /code/ + +# (2)! +CMD ["fastapi", "run", "main.py", "--port", "80"] +``` + +1. Kopieren Sie die Datei `main.py` direkt in das Verzeichnis `/code` (ohne ein Verzeichnis `./app`). + +2. Verwenden Sie `fastapi run`, um Ihre Anwendung in der einzelnen Datei `main.py` bereitzustellen. + +Indem Sie die Datei an `fastapi run` übergeben, wird automatisch erkannt, dass es sich um eine einzelne Datei handelt und nicht um den Teil eines Packages, und es wird wissen, wie es zu importieren ist und Ihre FastAPI-App bereitzustellen. 😎 + +## Deployment-Konzepte { #deployment-concepts } + +Lassen Sie uns noch einmal über einige der gleichen [Deployment-Konzepte](concepts.md) in Bezug auf Container sprechen. + +Container sind hauptsächlich ein Werkzeug, um den Prozess des **Erstellens und Deployments** einer Anwendung zu vereinfachen, sie erzwingen jedoch keinen bestimmten Ansatz für die Handhabung dieser **Deployment-Konzepte**, und es gibt mehrere mögliche Strategien. + +Die **gute Nachricht** ist, dass es mit jeder unterschiedlichen Strategie eine Möglichkeit gibt, alle Deployment-Konzepte abzudecken. 🎉 + +Sehen wir uns diese **Deployment-Konzepte** im Hinblick auf Container noch einmal an: + +* HTTPS +* Beim Hochfahren ausführen +* Neustarts +* Replikation (die Anzahl der laufenden Prozesse) +* Arbeitsspeicher +* Schritte vor dem Start + +## HTTPS { #https } + +Wenn wir uns nur auf das **Containerimage** für eine FastAPI-Anwendung (und später auf den laufenden **Container**) konzentrieren, würde HTTPS normalerweise **extern** von einem anderen Tool verarbeitet. + +Es könnte sich um einen anderen Container handeln, zum Beispiel mit [Traefik](https://traefik.io/), welcher **HTTPS** und **automatischen** Erwerb von **Zertifikaten** handhabt. + +/// tip | Tipp + +Traefik verfügt über Integrationen mit Docker, Kubernetes und anderen, sodass Sie damit ganz einfach HTTPS für Ihre Container einrichten und konfigurieren können. + +/// + +Alternativ könnte HTTPS von einem Cloudanbieter als einer seiner Dienste gehandhabt werden (während die Anwendung weiterhin in einem Container ausgeführt wird). + +## Beim Hochfahren ausführen und Neustarts { #running-on-startup-and-restarts } + +Normalerweise gibt es ein anderes Tool, das für das **Starten und Ausführen** Ihres Containers zuständig ist. + +Es könnte sich um **Docker** direkt, **Docker Compose**, **Kubernetes**, einen **Cloud-Dienst**, usw. handeln. + +In den meisten (oder allen) Fällen gibt es eine einfache Option, um die Ausführung des Containers beim Hochfahren und Neustarts bei Fehlern zu ermöglichen. In Docker ist es beispielsweise die Befehlszeilenoption `--restart`. + +Ohne die Verwendung von Containern kann es umständlich und schwierig sein, Anwendungen beim Hochfahren auszuführen und neu zu starten. Bei der **Arbeit mit Containern** ist diese Funktionalität jedoch in den meisten Fällen standardmäßig enthalten. ✨ + +## Replikation – Anzahl der Prozesse { #replication-number-of-processes } + +Wenn Sie einen Cluster von Maschinen mit **Kubernetes**, Docker Swarm Mode, Nomad verwenden, oder einem anderen, ähnlich komplexen System zur Verwaltung verteilter Container auf mehreren Maschinen, möchten Sie wahrscheinlich die **Replikation auf Cluster-Ebene abwickeln**, anstatt in jedem Container einen **Prozessmanager** (wie Uvicorn mit Workern) zu verwenden. + +Diese verteilten Containerverwaltungssysteme wie Kubernetes verfügen normalerweise über eine integrierte Möglichkeit, die **Replikation von Containern** zu handhaben und gleichzeitig **Load Balancing** für die eingehenden Requests zu unterstützen. Alles auf **Cluster-Ebene**. + +In diesen Fällen möchten Sie wahrscheinlich ein **Docker-Image von Grund auf** erstellen, wie [oben erklärt](#dockerfile), Ihre Abhängigkeiten installieren und **einen einzelnen Uvicorn-Prozess** ausführen, anstatt mehrere Uvicorn-Worker zu verwenden. + +### Load Balancer { #load-balancer } + +Bei der Verwendung von Containern ist normalerweise eine Komponente vorhanden, **die am Hauptport lauscht**. Es könnte sich um einen anderen Container handeln, der auch ein **TLS-Terminierungsproxy** ist, um **HTTPS** zu verarbeiten, oder ein ähnliches Tool. + +Da diese Komponente die **Last** an Requests aufnehmen und diese (hoffentlich) **ausgewogen** auf die Worker verteilen würde, wird sie üblicherweise auch **Load Balancer** genannt. + +/// tip | Tipp + +Die gleiche **TLS-Terminierungsproxy**-Komponente, die für HTTPS verwendet wird, wäre wahrscheinlich auch ein **Load Balancer**. + +/// + +Und wenn Sie mit Containern arbeiten, verfügt das gleiche System, mit dem Sie diese starten und verwalten, bereits über interne Tools, um die **Netzwerkkommunikation** (z. B. HTTP-Requests) von diesem **Load Balancer** (das könnte auch ein **TLS-Terminierungsproxy** sein) zu den Containern mit Ihrer Anwendung weiterzuleiten. + +### Ein Load Balancer – mehrere Workercontainer { #one-load-balancer-multiple-worker-containers } + +Bei der Arbeit mit **Kubernetes** oder ähnlichen verteilten Containerverwaltungssystemen würde die Verwendung ihrer internen Netzwerkmechanismen es dem einzelnen **Load Balancer**, der den Haupt-**Port** überwacht, ermöglichen, Kommunikation (Requests) an möglicherweise **mehrere Container** weiterzuleiten, in denen Ihre Anwendung ausgeführt wird. + +Jeder dieser Container, in denen Ihre Anwendung ausgeführt wird, verfügt normalerweise über **nur einen Prozess** (z. B. einen Uvicorn-Prozess, der Ihre FastAPI-Anwendung ausführt). Es wären alles **identische Container**, die das Gleiche ausführen, welche aber jeweils über einen eigenen Prozess, Speicher, usw. verfügen. Auf diese Weise würden Sie die **Parallelisierung** in **verschiedenen Kernen** der CPU nutzen. Oder sogar in **verschiedenen Maschinen**. + +Und das verteilte Containersystem mit dem **Load Balancer** würde **die Requests abwechselnd** an jeden einzelnen Container mit Ihrer Anwendung verteilen. Jeder Request könnte also von einem der mehreren **replizierten Container** verarbeitet werden, in denen Ihre Anwendung ausgeführt wird. + +Und normalerweise wäre dieser **Load Balancer** in der Lage, Requests zu verarbeiten, die an *andere* Anwendungen in Ihrem Cluster gerichtet sind (z. B. eine andere Domain oder unter einem anderen URL-Pfad-Präfix), und würde diese Kommunikation an die richtigen Container weiterleiten für *diese andere* Anwendung, die in Ihrem Cluster ausgeführt wird. + +### Ein Prozess pro Container { #one-process-per-container } + +In einem solchen Szenario möchten Sie wahrscheinlich **einen einzelnen (Uvicorn-)Prozess pro Container** haben, da Sie die Replikation bereits auf Cluster-Ebene durchführen würden. + +In diesem Fall möchten Sie also **nicht** mehrere Worker im Container haben, z. B. mit der `--workers`-Befehlszeilenoption. Sie möchten nur einen **einzelnen Uvicorn-Prozess** pro Container haben (wahrscheinlich aber mehrere Container). + +Ein weiterer Prozessmanager im Container (wie es bei mehreren Workern der Fall wäre) würde nur **unnötige Komplexität** hinzufügen, um welche Sie sich höchstwahrscheinlich bereits mit Ihrem Clustersystem kümmern. + +### Container mit mehreren Prozessen und Sonderfälle { #containers-with-multiple-processes-and-special-cases } + +Natürlich gibt es **Sonderfälle**, in denen Sie **einen Container** mit mehreren **Uvicorn-Workerprozessen** haben möchten. + +In diesen Fällen können Sie die `--workers`-Befehlszeilenoption verwenden, um die Anzahl der zu startenden Worker festzulegen: + +```{ .dockerfile .annotate } +FROM python:3.14 + +WORKDIR /code + +COPY ./requirements.txt /code/requirements.txt + +RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt + +COPY ./app /code/app + +# (1)! +CMD ["fastapi", "run", "app/main.py", "--port", "80", "--workers", "4"] +``` + +1. Hier verwenden wir die `--workers`-Befehlszeilenoption, um die Anzahl der Worker auf 4 festzulegen. + +Hier sind einige Beispiele, wann das sinnvoll sein könnte: + +#### Eine einfache Anwendung { #a-simple-app } + +Sie könnten einen Prozessmanager im Container haben wollen, wenn Ihre Anwendung **einfach genug** ist, sodass Sie es auf einem **einzelnen Server** ausführen können, nicht auf einem Cluster. + +#### Docker Compose { #docker-compose } + +Sie könnten das Deployment auf einem **einzelnen Server** (kein Cluster) mit **Docker Compose** durchführen, sodass Sie keine einfache Möglichkeit hätten, die Replikation von Containern (mit Docker Compose) zu verwalten und gleichzeitig das gemeinsame Netzwerk mit **Load Balancing** zu haben. + +Dann möchten Sie vielleicht **einen einzelnen Container** mit einem **Prozessmanager** haben, der darin **mehrere Workerprozesse** startet. + +--- + +Der Hauptpunkt ist, dass **keine** dieser Regeln **in Stein gemeißelt** ist, der man blind folgen muss. Sie können diese Ideen verwenden, um **I Ihren eigenen Anwendungsfall zu evaluieren**, zu entscheiden, welcher Ansatz für Ihr System am besten geeignet ist und herauszufinden, wie Sie folgende Konzepte verwalten: + +* Sicherheit – HTTPS +* Beim Hochfahren ausführen +* Neustarts +* Replikation (die Anzahl der laufenden Prozesse) +* Arbeitsspeicher +* Schritte vor dem Start + +## Arbeitsspeicher { #memory } + +Wenn Sie **einen einzelnen Prozess pro Container** ausführen, wird von jedem dieser Container (mehr als einer, wenn sie repliziert werden) eine mehr oder weniger klar definierte, stabile und begrenzte Menge an Arbeitsspeicher verbraucht. + +Und dann können Sie dieselben Speichergrenzen und -anforderungen in Ihren Konfigurationen für Ihr Container-Management-System festlegen (z. B. in **Kubernetes**). Auf diese Weise ist es in der Lage, die Container auf den **verfügbaren Maschinen** zu replizieren, wobei die von diesen benötigte Speichermenge und die auf den Maschinen im Cluster verfügbare Menge berücksichtigt werden. + +Wenn Ihre Anwendung **einfach** ist, wird dies wahrscheinlich **kein Problem darstellen** und Sie müssen möglicherweise keine festen Speichergrenzen angeben. Wenn Sie jedoch **viel Speicher verbrauchen** (z. B. bei **Modellen für maschinelles Lernen**), sollten Sie überprüfen, wie viel Speicher Sie verbrauchen, und die **Anzahl der Container** anpassen, die in **jeder Maschine** ausgeführt werden (und möglicherweise weitere Maschinen zu Ihrem Cluster hinzufügen). + +Wenn Sie **mehrere Prozesse pro Container** ausführen, müssen Sie sicherstellen, dass die Anzahl der gestarteten Prozesse nicht **mehr Speicher verbraucht** als verfügbar ist. + +## Schritte vor dem Start und Container { #previous-steps-before-starting-and-containers } + +Wenn Sie Container (z. B. Docker, Kubernetes) verwenden, können Sie hauptsächlich zwei Ansätze verwenden. + +### Mehrere Container { #multiple-containers } + +Wenn Sie **mehrere Container** haben, von denen wahrscheinlich jeder einen **einzelnen Prozess** ausführt (z. B. in einem **Kubernetes**-Cluster), dann möchten Sie wahrscheinlich einen **separaten Container** haben, welcher die Arbeit der **Vorab-Schritte** in einem einzelnen Container, mit einem einzelnen Prozess ausführt, **bevor** die replizierten Workercontainer ausgeführt werden. + +/// note | Hinweis + +Wenn Sie Kubernetes verwenden, wäre dies wahrscheinlich ein [Init-Container](https://kubernetes.io/docs/concepts/workloads/pods/init-containers/). + +/// + +Wenn es in Ihrem Anwendungsfall kein Problem darstellt, diese vorherigen Schritte **mehrmals parallel** auszuführen (z. B. wenn Sie keine Datenbankmigrationen ausführen, sondern nur prüfen, ob die Datenbank bereits bereit ist), können Sie sie auch einfach in jedem Container direkt vor dem Start des Hauptprozesses einfügen. + +### Einzelner Container { #single-container } + +Wenn Sie ein einfaches Setup mit einem **einzelnen Container** haben, welcher dann mehrere **Workerprozesse** (oder auch nur einen Prozess) startet, können Sie die Vorab-Schritte im selben Container direkt vor dem Starten des Prozesses mit der Anwendung ausführen. + +### Docker-Basisimage { #base-docker-image } + +Es gab ein offizielles FastAPI-Docker-Image: [tiangolo/uvicorn-gunicorn-fastapi](https://github.com/tiangolo/uvicorn-gunicorn-fastapi-docker). Dieses ist jedoch jetzt deprecatet. ⛔️ + +Sie sollten wahrscheinlich **nicht** dieses Basis-Docker-Image (oder ein anderes ähnliches) verwenden. + +Wenn Sie **Kubernetes** (oder andere) verwenden und bereits **Replikation** auf Cluster-Ebene mit mehreren **Containern** eingerichtet haben. In diesen Fällen ist es besser, **ein Image von Grund auf neu zu erstellen**, wie oben beschrieben: [Ein Docker-Image für FastAPI erstellen](#build-a-docker-image-for-fastapi). + +Und wenn Sie mehrere Worker benötigen, können Sie einfach die `--workers`-Befehlszeilenoption verwenden. + +/// note | Technische Details + +Das Docker-Image wurde erstellt, als Uvicorn das Verwalten und Neustarten von ausgefallenen Workern noch nicht unterstützte, weshalb es notwendig war, Gunicorn mit Uvicorn zu verwenden, was zu einer erheblichen Komplexität führte, nur damit Gunicorn die Uvicorn-Workerprozesse verwaltet und neu startet. + +Aber jetzt, da Uvicorn (und der `fastapi`-Befehl) die Verwendung von `--workers` unterstützen, gibt es keinen Grund, ein Basis-Docker-Image an Stelle eines eigenen (das praktisch denselben Code enthält 😅) zu verwenden. + +/// + +## Deployment des Containerimages { #deploy-the-container-image } + +Nachdem Sie ein Containerimage (Docker) haben, gibt es mehrere Möglichkeiten, es bereitzustellen. + +Zum Beispiel: + +* Mit **Docker Compose** auf einem einzelnen Server +* Mit einem **Kubernetes**-Cluster +* Mit einem Docker Swarm Mode-Cluster +* Mit einem anderen Tool wie Nomad +* Mit einem Cloud-Dienst, der Ihr Containerimage nimmt und es deployt + +## Docker-Image mit `uv` { #docker-image-with-uv } + +Wenn Sie [uv](https://github.com/astral-sh/uv) verwenden, um Ihr Projekt zu installieren und zu verwalten, können Sie deren [uv-Docker-Leitfaden](https://docs.astral.sh/uv/guides/integration/docker/) befolgen. + +## Zusammenfassung { #recap } + +Mithilfe von Containersystemen (z. B. mit **Docker** und **Kubernetes**) ist es ziemlich einfach, alle **Deployment-Konzepte** zu handhaben: + +* HTTPS +* Beim Hochfahren ausführen +* Neustarts +* Replikation (die Anzahl der laufenden Prozesse) +* Arbeitsspeicher +* Schritte vor dem Start + +In den meisten Fällen möchten Sie wahrscheinlich kein Basisimage verwenden und stattdessen **ein Containerimage von Grund auf erstellen**, eines basierend auf dem offiziellen Python-Docker-Image. + +Indem Sie auf die **Reihenfolge** der Anweisungen im `Dockerfile` und den **Docker-Cache** achten, können Sie **die Build-Zeiten minimieren**, um Ihre Produktivität zu erhöhen (und Langeweile zu vermeiden). 😎 diff --git a/docs/de/docs/deployment/fastapicloud.md b/docs/de/docs/deployment/fastapicloud.md new file mode 100644 index 0000000000000..d563fd8223349 --- /dev/null +++ b/docs/de/docs/deployment/fastapicloud.md @@ -0,0 +1,47 @@ +# FastAPI Cloud { #fastapi-cloud } + +Sie können Ihre FastAPI-App in der [FastAPI Cloud](https://fastapicloud.com) mit **einem einzigen Befehl** deployen. 🚀 + +
+ +```console +$ fastapi deploy + +Deploying to FastAPI Cloud... + +✅ Deployment successful! + +🐔 Ready the chicken! Your app is ready at https://myapp.fastapicloud.dev +``` + +
+ +Das CLI erkennt Ihre FastAPI-App automatisch und deployt sie in die Cloud. Wenn Sie nicht angemeldet sind, öffnet sich Ihr Browser, um den Authentifizierungsprozess abzuschließen. + +Das war’s! Jetzt können Sie Ihre App unter dieser URL aufrufen. ✨ + +## Über FastAPI Cloud { #about-fastapi-cloud } + +**[FastAPI Cloud](https://fastapicloud.com)** 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. 🤓 diff --git a/docs/de/docs/deployment/https.md b/docs/de/docs/deployment/https.md new file mode 100644 index 0000000000000..b4c49ff4dd7af --- /dev/null +++ b/docs/de/docs/deployment/https.md @@ -0,0 +1,231 @@ +# Über HTTPS { #about-https } + +Es ist leicht anzunehmen, dass HTTPS etwas ist, was einfach nur „aktiviert“ wird oder nicht. + +Aber es ist viel komplexer als das. + +/// tip | Tipp + +Wenn Sie es eilig haben oder es Ihnen egal ist, fahren Sie mit den nächsten Abschnitten fort, um Schritt-für-Schritt-Anleitungen für die Einrichtung der verschiedenen Technologien zu erhalten. + +/// + +Um **die Grundlagen von HTTPS** aus Sicht des Benutzers zu erlernen, schauen Sie sich [https://howhttps.works/](https://howhttps.works/) an. + +Aus **Sicht des Entwicklers** sollten Sie beim Nachdenken über HTTPS Folgendes beachten: + +* Für HTTPS muss **der Server** über von einem **Dritten** generierte **„Zertifikate“** verfügen. + * Diese Zertifikate werden tatsächlich vom Dritten **erworben** und nicht „generiert“. +* Zertifikate haben eine **Lebensdauer**. + * Sie **verfallen**. + * Und dann müssen sie vom Dritten **erneuert**, **erneut erworben** werden. +* Die Verschlüsselung der Verbindung erfolgt auf **TCP-Ebene**. + * Das ist eine Schicht **unter HTTP**. + * Die **Zertifikats- und Verschlüsselungs**-Handhabung erfolgt also **vor HTTP**. +* **TCP weiß nichts über „Domains“**. Nur über IP-Adressen. + * Die Informationen über die angeforderte **spezifische Domain** befinden sich in den **HTTP-Daten**. +* Die **HTTPS-Zertifikate** „zertifizieren“ eine **bestimmte Domain**, aber das Protokoll und die Verschlüsselung erfolgen auf TCP-Ebene, **bevor bekannt ist**, um welche Domain es sich handelt. +* **Standardmäßig** bedeutet das, dass Sie nur **ein HTTPS-Zertifikat pro IP-Adresse** haben können. + * Ganz gleich, wie groß Ihr Server ist oder wie klein die einzelnen Anwendungen darauf sind. + * Hierfür gibt es jedoch eine **Lösung**. +* Es gibt eine **Erweiterung** zum **TLS**-Protokoll (dasjenige, das die Verschlüsselung auf TCP-Ebene, vor HTTP, verwaltet) namens **[SNI](https://en.wikipedia.org/wiki/Server_Name_Indication)**. + * Mit dieser SNI-Erweiterung kann ein einzelner Server (mit einer **einzelnen IP-Adresse**) über **mehrere HTTPS-Zertifikate** verfügen und **mehrere HTTPS-Domains/Anwendungen bereitstellen**. + * Damit das funktioniert, muss eine **einzelne** Komponente (Programm), die auf dem Server ausgeführt wird und welche die **öffentliche IP-Adresse** überwacht, **alle HTTPS-Zertifikate** des Servers haben. +* **Nachdem** eine sichere Verbindung hergestellt wurde, ist das Kommunikationsprotokoll **immer noch HTTP**. + * Die Inhalte sind **verschlüsselt**, auch wenn sie mit dem **HTTP-Protokoll** gesendet werden. + +Es ist eine gängige Praxis, **ein Programm/HTTP-Server** auf dem Server (der Maschine, dem Host usw.) laufen zu lassen, welches **alle HTTPS-Aspekte verwaltet**: Empfangen der **verschlüsselten HTTPS-Requests**, Senden der **entschlüsselten HTTP-Requests** an die eigentliche HTTP-Anwendung die auf demselben Server läuft (in diesem Fall die **FastAPI**-Anwendung), entgegennehmen der **HTTP-Response** von der Anwendung, **verschlüsseln derselben** mithilfe des entsprechenden **HTTPS-Zertifikats** und Zurücksenden zum Client über **HTTPS**. Dieser Server wird oft als **[TLS-Terminierungsproxy](https://en.wikipedia.org/wiki/TLS_termination_proxy)** bezeichnet. + +Einige der Optionen, die Sie als TLS-Terminierungsproxy verwenden können, sind: + +* Traefik (kann auch Zertifikat-Erneuerungen durchführen) +* Caddy (kann auch Zertifikat-Erneuerungen durchführen) +* Nginx +* HAProxy + +## Let's Encrypt { #lets-encrypt } + +Vor Let's Encrypt wurden diese **HTTPS-Zertifikate** von vertrauenswürdigen Dritten verkauft. + +Der Prozess zum Erwerb eines dieser Zertifikate war früher umständlich, erforderte viel Papierarbeit und die Zertifikate waren ziemlich teuer. + +Aber dann wurde **[Let's Encrypt](https://letsencrypt.org/)** geschaffen. + +Es ist ein Projekt der Linux Foundation. Es stellt **kostenlose HTTPS-Zertifikate** automatisiert zur Verfügung. Diese Zertifikate nutzen standardmäßig die gesamte kryptografische Sicherheit und sind kurzlebig (circa 3 Monate), sodass die **Sicherheit tatsächlich besser ist**, aufgrund der kürzeren Lebensdauer. + +Die Domains werden sicher verifiziert und die Zertifikate werden automatisch generiert. Das ermöglicht auch die automatische Erneuerung dieser Zertifikate. + +Die Idee besteht darin, den Erwerb und die Erneuerung der Zertifikate zu automatisieren, sodass Sie **sicheres HTTPS, kostenlos und für immer** haben können. + +## HTTPS für Entwickler { #https-for-developers } + +Hier ist ein Beispiel, wie eine HTTPS-API aussehen könnte, Schritt für Schritt, wobei vor allem die für Entwickler wichtigen Ideen berücksichtigt werden. + +### Domainname { #domain-name } + +Alles beginnt wahrscheinlich damit, dass Sie einen **Domainnamen erwerben**. Anschließend konfigurieren Sie ihn in einem DNS-Server (wahrscheinlich beim selben Cloudanbieter). + +Sie würden wahrscheinlich einen Cloud-Server (eine virtuelle Maschine) oder etwas Ähnliches bekommen, und dieser hätte eine feste **öffentliche IP-Adresse**. + +In dem oder den DNS-Server(n) würden Sie einen Eintrag (einen „`A record`“) konfigurieren, um mit **Ihrer Domain** auf die öffentliche **IP-Adresse Ihres Servers** zu verweisen. + +Sie würden dies wahrscheinlich nur einmal tun, beim ersten Mal, wenn Sie alles einrichten. + +/// tip | Tipp + +Dieser Domainnamen-Aspekt liegt weit vor HTTPS, aber da alles von der Domain und der IP-Adresse abhängt, lohnt es sich, das hier zu erwähnen. + +/// + +### DNS { #dns } + +Konzentrieren wir uns nun auf alle tatsächlichen HTTPS-Aspekte. + +Zuerst würde der Browser mithilfe der **DNS-Server** herausfinden, welches die **IP für die Domain** ist, in diesem Fall `someapp.example.com`. + +Die DNS-Server geben dem Browser eine bestimmte **IP-Adresse** zurück. Das wäre die von Ihrem Server verwendete öffentliche IP-Adresse, die Sie in den DNS-Servern konfiguriert haben. + + + +### TLS-Handshake-Start { #tls-handshake-start } + +Der Browser kommuniziert dann mit dieser IP-Adresse über **Port 443** (den HTTPS-Port). + +Der erste Teil der Kommunikation besteht lediglich darin, die Verbindung zwischen dem Client und dem Server herzustellen und die zu verwendenden kryptografischen Schlüssel usw. zu vereinbaren. + + + +Diese Interaktion zwischen dem Client und dem Server zum Aufbau der TLS-Verbindung wird als **TLS-Handshake** bezeichnet. + +### TLS mit SNI-Erweiterung { #tls-with-sni-extension } + +**Nur ein Prozess** im Server kann an einem bestimmten **Port** einer bestimmten **IP-Adresse** lauschen. Möglicherweise gibt es andere Prozesse, die an anderen Ports dieselbe IP-Adresse abhören, jedoch nur einen für jede Kombination aus IP-Adresse und Port. + +TLS (HTTPS) verwendet standardmäßig den spezifischen Port `443`. Das ist also der Port, den wir brauchen. + +Da an diesem Port nur ein Prozess lauschen kann, wäre der Prozess, der dies tun würde, der **TLS-Terminierungsproxy**. + +Der TLS-Terminierungsproxy hätte Zugriff auf ein oder mehrere **TLS-Zertifikate** (HTTPS-Zertifikate). + +Mithilfe der oben beschriebenen **SNI-Erweiterung** würde der TLS-Terminierungsproxy herausfinden, welches der verfügbaren TLS-Zertifikate (HTTPS) er für diese Verbindung verwenden muss, und zwar das, welches mit der vom Client erwarteten Domain übereinstimmt. + +In diesem Fall würde er das Zertifikat für `someapp.example.com` verwenden. + + + +Der Client **vertraut** bereits der Entität, die das TLS-Zertifikat generiert hat (in diesem Fall Let's Encrypt, aber wir werden später mehr darüber erfahren), sodass er **verifizieren** kann, dass das Zertifikat gültig ist. + +Mithilfe des Zertifikats entscheiden der Client und der TLS-Terminierungsproxy dann, **wie der Rest der TCP-Kommunikation verschlüsselt werden soll**. Damit ist der **TLS-Handshake** abgeschlossen. + +Danach verfügen der Client und der Server über eine **verschlüsselte TCP-Verbindung**, via TLS. Und dann können sie diese Verbindung verwenden, um die eigentliche **HTTP-Kommunikation** zu beginnen. + +Und genau das ist **HTTPS**, es ist einfach **HTTP** innerhalb einer **sicheren TLS-Verbindung**, statt einer puren (unverschlüsselten) TCP-Verbindung. + +/// tip | Tipp + +Beachten Sie, dass die Verschlüsselung der Kommunikation auf der **TCP-Ebene** und nicht auf der HTTP-Ebene erfolgt. + +/// + +### HTTPS-Request { #https-request } + +Da Client und Server (sprich, der Browser und der TLS-Terminierungsproxy) nun über eine **verschlüsselte TCP-Verbindung** verfügen, können sie die **HTTP-Kommunikation** starten. + +Der Client sendet also einen **HTTPS-Request**. Das ist einfach ein HTTP-Request über eine verschlüsselte TLS-Verbindung. + + + +### Den Request entschlüsseln { #decrypt-the-request } + +Der TLS-Terminierungsproxy würde die vereinbarte Verschlüsselung zum **Entschlüsseln des Requests** verwenden und den **einfachen (entschlüsselten) HTTP-Request** an den Prozess weiterleiten, der die Anwendung ausführt (z. B. einen Prozess, bei dem Uvicorn die FastAPI-Anwendung ausführt). + + + +### HTTP-Response { #http-response } + +Die Anwendung würde den Request verarbeiten und eine **einfache (unverschlüsselte) HTTP-Response** an den TLS-Terminierungsproxy senden. + + + +### HTTPS-Response { #https-response } + +Der TLS-Terminierungsproxy würde dann die Response mithilfe der zuvor vereinbarten Kryptografie (als das Zertifikat für `someapp.example.com` verhandelt wurde) **verschlüsseln** und sie an den Browser zurücksenden. + +Als Nächstes überprüft der Browser, ob die Response gültig und mit dem richtigen kryptografischen Schlüssel usw. verschlüsselt ist. Anschließend **entschlüsselt er die Response** und verarbeitet sie. + + + +Der Client (Browser) weiß, dass die Response vom richtigen Server kommt, da dieser die Kryptografie verwendet, die zuvor mit dem **HTTPS-Zertifikat** vereinbart wurde. + +### Mehrere Anwendungen { #multiple-applications } + +Auf demselben Server (oder denselben Servern) könnten sich **mehrere Anwendungen** befinden, beispielsweise andere API-Programme oder eine Datenbank. + +Nur ein Prozess kann diese spezifische IP und den Port verarbeiten (in unserem Beispiel der TLS-Terminierungsproxy), aber die anderen Anwendungen/Prozesse können auch auf dem/den Server(n) ausgeführt werden, solange sie nicht versuchen, dieselbe **Kombination aus öffentlicher IP und Port** zu verwenden. + + + +Auf diese Weise könnte der TLS-Terminierungsproxy HTTPS und Zertifikate für **mehrere Domains**, für mehrere Anwendungen, verarbeiten und die Requests dann jeweils an die richtige Anwendung weiterleiten. + +### Verlängerung des Zertifikats { #certificate-renewal } + +Irgendwann in der Zukunft würde jedes Zertifikat **ablaufen** (etwa 3 Monate nach dem Erwerb). + +Und dann gäbe es ein anderes Programm (in manchen Fällen ist es ein anderes Programm, in manchen Fällen ist es derselbe TLS-Terminierungsproxy), das mit Let's Encrypt kommuniziert und das/die Zertifikat(e) erneuert. + + + +Die **TLS-Zertifikate** sind **einem Domainnamen zugeordnet**, nicht einer IP-Adresse. + +Um die Zertifikate zu erneuern, muss das erneuernde Programm der Behörde (Let's Encrypt) **nachweisen**, dass es diese Domain tatsächlich **besitzt und kontrolliert**. + +Um dies zu erreichen und den unterschiedlichen Anwendungsanforderungen gerecht zu werden, gibt es mehrere Möglichkeiten. Einige beliebte Methoden sind: + +* **Einige DNS-Einträge ändern**. + * Hierfür muss das erneuernde Programm die APIs des DNS-Anbieters unterstützen. Je nachdem, welchen DNS-Anbieter Sie verwenden, kann dies eine Option sein oder auch nicht. +* **Als Server ausführen** (zumindest während des Zertifikatserwerbsvorgangs), auf der öffentlichen IP-Adresse, die der Domain zugeordnet ist. + * Wie oben erwähnt, kann nur ein Prozess eine bestimmte IP und einen bestimmten Port überwachen. + * Das ist einer der Gründe, warum es sehr nützlich ist, wenn derselbe TLS-Terminierungsproxy auch den Zertifikats-Erneuerungsprozess übernimmt. + * Andernfalls müssen Sie möglicherweise den TLS-Terminierungsproxy vorübergehend stoppen, das Programm starten, welches die neuen Zertifikate beschafft, diese dann mit dem TLS-Terminierungsproxy konfigurieren und dann den TLS-Terminierungsproxy neu starten. Das ist nicht ideal, da Ihre Anwendung(en) während der Zeit, in der der TLS-Terminierungsproxy ausgeschaltet ist, nicht erreichbar ist/sind. + +Dieser ganze Erneuerungsprozess, während die Anwendung weiterhin bereitgestellt wird, ist einer der Hauptgründe, warum Sie ein **separates System zur Verarbeitung von HTTPS** mit einem TLS-Terminierungsproxy haben möchten, anstatt einfach die TLS-Zertifikate direkt mit dem Anwendungsserver zu verwenden (z. B. Uvicorn). + +## Proxy-Forwarded-Header { #proxy-forwarded-headers } + +Wenn Sie einen Proxy zur Verarbeitung von HTTPS verwenden, weiß Ihr **Anwendungsserver** (z. B. Uvicorn über das FastAPI CLI) nichts über den HTTPS-Prozess, er kommuniziert per einfachem HTTP mit dem **TLS-Terminierungsproxy**. + +Dieser **Proxy** würde normalerweise unmittelbar vor dem Übermitteln des Requests an den **Anwendungsserver** einige HTTP-Header dynamisch setzen, um dem Anwendungsserver mitzuteilen, dass der Request vom Proxy **weitergeleitet** wird. + +/// note | Technische Details + +Die Proxy-Header sind: + +* [X-Forwarded-For](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Forwarded-For) +* [X-Forwarded-Proto](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Forwarded-Proto) +* [X-Forwarded-Host](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Forwarded-Host) + +/// + +Trotzdem, da der **Anwendungsserver** nicht weiß, dass er sich hinter einem vertrauenswürdigen **Proxy** befindet, würde er diesen Headern standardmäßig nicht vertrauen. + +Sie können den **Anwendungsserver** jedoch so konfigurieren, dass er den vom **Proxy** gesendeten *Forwarded*-Headern vertraut. Wenn Sie das FastAPI CLI verwenden, können Sie die *CLI-Option* `--forwarded-allow-ips` nutzen, um anzugeben, von welchen IPs er diesen *Forwarded*-Headern vertrauen soll. + +Wenn der **Anwendungsserver** beispielsweise nur Kommunikation vom vertrauenswürdigen **Proxy** empfängt, können Sie `--forwarded-allow-ips="*"` setzen, um allen eingehenden IPs zu vertrauen, da er nur Requests von der vom **Proxy** verwendeten IP erhalten wird. + +Auf diese Weise kann die Anwendung ihre eigene öffentliche URL, ob sie HTTPS verwendet, die Domain, usw. erkennen. + +Das ist z. B. nützlich, um Redirects korrekt zu handhaben. + +/// tip | Tipp + +Mehr dazu finden Sie in der Dokumentation zu [Hinter einem Proxy – Proxy-Forwarded-Header aktivieren](../advanced/behind-a-proxy.md#enable-proxy-forwarded-headers) + +/// + +## Zusammenfassung { #recap } + +**HTTPS** zu haben ist sehr wichtig und in den meisten Fällen eine **kritische Anforderung**. Die meiste Arbeit, die Sie als Entwickler in Bezug auf HTTPS aufwenden müssen, besteht lediglich darin, **diese Konzepte zu verstehen** und wie sie funktionieren. + +Sobald Sie jedoch die grundlegenden Informationen zu **HTTPS für Entwickler** kennen, können Sie verschiedene Tools problemlos kombinieren und konfigurieren, um alles auf einfache Weise zu verwalten. + +In einigen der nächsten Kapitel zeige ich Ihnen einige konkrete Beispiele für die Einrichtung von **HTTPS** für **FastAPI**-Anwendungen. 🔒 diff --git a/docs/de/docs/deployment/index.md b/docs/de/docs/deployment/index.md new file mode 100644 index 0000000000000..dc3a92ba8e496 --- /dev/null +++ b/docs/de/docs/deployment/index.md @@ -0,0 +1,23 @@ +# Deployment { #deployment } + +Das Deployment einer **FastAPI**-Anwendung ist relativ einfach. + +## Was bedeutet Deployment { #what-does-deployment-mean } + +**Deployment** bedeutet, die notwendigen Schritte durchzuführen, um die Anwendung **für die Benutzer verfügbar** zu machen. + +Bei einer **Web-API** bedeutet das normalerweise, diese auf einem **entfernten Rechner** zu platzieren, mit einem **Serverprogramm**, welches gute Leistung, Stabilität, usw. bietet, damit Ihre **Benutzer** auf die Anwendung effizient und ohne Unterbrechungen oder Probleme **zugreifen** können. + +Das steht im Gegensatz zu den **Entwicklungsphasen**, in denen Sie ständig den Code ändern, kaputt machen, reparieren, den Entwicklungsserver stoppen und neu starten, usw. + +## Deployment-Strategien { #deployment-strategies } + +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. + +Zum Beispiel haben wir, das Team hinter FastAPI, [**FastAPI Cloud**](https://fastapicloud.com) 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). + +In den nächsten Abschnitten erfahren Sie mehr über die zu beachtenden Details und über die Techniken, das zu tun. ✨ diff --git a/docs/de/docs/deployment/manually.md b/docs/de/docs/deployment/manually.md new file mode 100644 index 0000000000000..fa8a9c9637b50 --- /dev/null +++ b/docs/de/docs/deployment/manually.md @@ -0,0 +1,156 @@ +# Einen Server manuell ausführen { #run-a-server-manually } + +## Den `fastapi run`-Befehl verwenden { #use-the-fastapi-run-command } + +Kurz gesagt, nutzen Sie `fastapi run`, um Ihre FastAPI-Anwendung bereitzustellen: + +
+ +```console +$ fastapi run main.py + + FastAPI Starting production server 🚀 + + Searching for package file structure from directories + with __init__.py files + Importing from /home/user/code/awesomeapp + + module 🐍 main.py + + code Importing the FastAPI app object from the module with + the following code: + + from main import app + + app Using import string: main:app + + server Server started at http://0.0.0.0:8000 + server Documentation at http://0.0.0.0:8000/docs + + Logs: + + INFO Started server process [2306215] + INFO Waiting for application startup. + INFO Application startup complete. + INFO Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C + to quit) +``` + +
+ +Das würde in den meisten Fällen funktionieren. 😎 + +Sie könnten diesen Befehl beispielsweise verwenden, um Ihre **FastAPI**-App in einem Container, auf einem Server usw. zu starten. + +## ASGI-Server { #asgi-servers } + +Lassen Sie uns ein wenig tiefer in die Details eintauchen. + +FastAPI verwendet einen Standard zum Erstellen von Python-Webframeworks und -Servern, der als ASGI bekannt ist. FastAPI ist ein ASGI-Webframework. + +Das Wichtigste, was Sie benötigen, um eine **FastAPI**-Anwendung (oder eine andere ASGI-Anwendung) auf einer entfernten Servermaschine auszuführen, ist ein ASGI-Serverprogramm wie **Uvicorn**, der standardmäßig im `fastapi`-Kommando enthalten ist. + +Es gibt mehrere Alternativen, einschließlich: + +* [Uvicorn](https://www.uvicorn.dev/): ein hochperformanter ASGI-Server. +* [Hypercorn](https://hypercorn.readthedocs.io/): ein ASGI-Server, der unter anderem kompatibel mit HTTP/2 und Trio ist. +* [Daphne](https://github.com/django/daphne): der für Django Channels entwickelte ASGI-Server. +* [Granian](https://github.com/emmett-framework/granian): Ein Rust-HTTP-Server für Python-Anwendungen. + +## Servermaschine und Serverprogramm { #server-machine-and-server-program } + +Es gibt ein kleines Detail bei den Namen, das Sie beachten sollten. 💡 + +Das Wort „**Server**“ wird häufig verwendet, um sowohl den entfernten/Cloud-Computer (die physische oder virtuelle Maschine) als auch das Programm zu bezeichnen, das auf dieser Maschine läuft (z. B. Uvicorn). + +Denken Sie einfach daran, dass sich „Server“ im Allgemeinen auf eines dieser beiden Dinge beziehen kann. + +Wenn man sich auf die entfernte Maschine bezieht, wird sie üblicherweise als **Server**, aber auch als **Maschine**, **VM** (virtuelle Maschine) oder **Knoten** bezeichnet. Diese Begriffe beziehen sich auf irgendeine Art von entferntem Rechner, normalerweise unter Linux, auf dem Sie Programme ausführen. + +## Das Serverprogramm installieren { #install-the-server-program } + +Wenn Sie FastAPI installieren, wird es mit einem Produktionsserver, Uvicorn, geliefert, und Sie können ihn mit dem `fastapi run`-Befehl starten. + +Aber Sie können auch ein ASGI-Serverprogramm manuell installieren. + +Stellen Sie sicher, dass Sie eine [virtuelle Umgebung](../virtual-environments.md) erstellen, sie aktivieren und dann die Serveranwendung installieren. + +Zum Beispiel, um Uvicorn zu installieren: + +
+ +```console +$ pip install "uvicorn[standard]" + +---> 100% +``` + +
+ +Ein ähnlicher Prozess würde für jedes andere ASGI-Serverprogramm gelten. + +/// tip | Tipp + +Durch das Hinzufügen von `standard` installiert und verwendet Uvicorn einige empfohlene zusätzliche Abhängigkeiten. + +Dazu gehört `uvloop`, der hochperformante Drop-in-Ersatz für `asyncio`, der den großen Nebenläufigkeits-Leistungsschub bietet. + +Wenn Sie FastAPI mit etwas wie `pip install "fastapi[standard]"` installieren, erhalten Sie auch `uvicorn[standard]`. + +/// + +## Das Serverprogramm ausführen { #run-the-server-program } + +Wenn Sie einen ASGI-Server manuell installiert haben, müssen Sie normalerweise einen Importstring in einem speziellen Format übergeben, damit er Ihre FastAPI-Anwendung importiert: + +
+ +```console +$ uvicorn main:app --host 0.0.0.0 --port 80 + +INFO: Uvicorn running on http://0.0.0.0:80 (Press CTRL+C to quit) +``` + +
+ +/// note | Hinweis + +Der Befehl `uvicorn main:app` bezieht sich auf: + +* `main`: die Datei `main.py` (das Python-„Modul“). +* `app`: das Objekt, das innerhalb von `main.py` mit der Zeile `app = FastAPI()` erstellt wurde. + +Es ist äquivalent zu: + +```Python +from main import app +``` + +/// + +Jedes alternative ASGI-Serverprogramm hätte einen ähnlichen Befehl, Sie können in deren jeweiligen Dokumentationen mehr lesen. + +/// warning | Achtung + +Uvicorn und andere Server unterstützen eine `--reload`-Option, die während der Entwicklung nützlich ist. + +Die `--reload`-Option verbraucht viel mehr Ressourcen, ist instabiler, usw. + +Sie hilft während der **Entwicklung**, Sie sollten sie jedoch **nicht** in der **Produktion** verwenden. + +/// + +## Deployment-Konzepte { #deployment-concepts } + +Diese Beispiele führen das Serverprogramm (z. B. Uvicorn) aus, starten **einen einzelnen Prozess** und überwachen alle IPs (`0.0.0.0`) an einem vordefinierten Port (z. B. `80`). + +Das ist die Grundidee. Aber Sie möchten sich wahrscheinlich um einige zusätzliche Dinge kümmern, wie zum Beispiel: + +* Sicherheit – HTTPS +* Beim Hochfahren ausführen +* Neustarts +* Replikation (die Anzahl der laufenden Prozesse) +* Speicher +* Schritte vor dem Start + +In den nächsten Kapiteln erzähle ich Ihnen mehr über jedes dieser Konzepte, wie Sie über diese nachdenken, und gebe Ihnen einige konkrete Beispiele mit Strategien für den Umgang damit. 🚀 diff --git a/docs/de/docs/deployment/server-workers.md b/docs/de/docs/deployment/server-workers.md new file mode 100644 index 0000000000000..6b0cc834edd01 --- /dev/null +++ b/docs/de/docs/deployment/server-workers.md @@ -0,0 +1,139 @@ +# Serverworker – Uvicorn mit Workern { #server-workers-uvicorn-with-workers } + +Schauen wir uns die Deployment-Konzepte von früher noch einmal an: + +* Sicherheit – HTTPS +* Beim Hochfahren ausführen +* Neustarts +* **Replikation (die Anzahl der laufenden Prozesse)** +* Arbeitsspeicher +* Schritte vor dem Start + +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 Requests bearbeiten zu können. + +Wie Sie im vorherigen Kapitel über [Deployment-Konzepte](concepts.md) gesehen haben, gibt es mehrere Strategien, die Sie anwenden können. + +Hier zeige ich Ihnen, wie Sie **Uvicorn** mit **Workerprozessen** verwenden, indem Sie den `fastapi`-Befehl oder den `uvicorn`-Befehl direkt verwenden. + +/// note | Hinweis + +Wenn Sie Container verwenden, beispielsweise mit Docker oder Kubernetes, erzähle ich Ihnen mehr darüber im nächsten Kapitel: [FastAPI in Containern – Docker](docker.md). + +Insbesondere wenn die Anwendung auf **Kubernetes** läuft, werden Sie wahrscheinlich **keine** Worker verwenden wollen, und stattdessen **einen einzelnen Uvicorn-Prozess pro Container** ausführen wollen, aber ich werde Ihnen später in diesem Kapitel mehr darüber erzählen. + +/// + +## Mehrere Worker { #multiple-workers } + +Sie können mehrere Worker mit der `--workers`-Befehlszeilenoption starten: + +//// tab | `fastapi` + +Wenn Sie den `fastapi`-Befehl verwenden: + +
+ +```console +$ fastapi run --workers 4 main.py + + FastAPI Starting production server 🚀 + + Searching for package file structure from directories with + __init__.py files + Importing from /home/user/code/awesomeapp + + module 🐍 main.py + + code Importing the FastAPI app object from the module with the + following code: + + from main import app + + app Using import string: main:app + + server Server started at http://0.0.0.0:8000 + server Documentation at http://0.0.0.0:8000/docs + + Logs: + + INFO Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to + quit) + INFO Started parent process [27365] + INFO Started server process [27368] + INFO Started server process [27369] + INFO Started server process [27370] + INFO Started server process [27367] + INFO Waiting for application startup. + INFO Waiting for application startup. + INFO Waiting for application startup. + INFO Waiting for application startup. + INFO Application startup complete. + INFO Application startup complete. + INFO Application startup complete. + INFO Application startup complete. +``` + +
+ +//// + +//// tab | `uvicorn` + +Wenn Sie den `uvicorn`-Befehl direkt verwenden möchten: + +
+ +```console +$ uvicorn main:app --host 0.0.0.0 --port 8080 --workers 4 +INFO: Uvicorn running on http://0.0.0.0:8080 (Press CTRL+C to quit) +INFO: Started parent process [27365] +INFO: Started server process [27368] +INFO: Waiting for application startup. +INFO: Application startup complete. +INFO: Started server process [27369] +INFO: Waiting for application startup. +INFO: Application startup complete. +INFO: Started server process [27370] +INFO: Waiting for application startup. +INFO: Application startup complete. +INFO: Started server process [27367] +INFO: Waiting for application startup. +INFO: Application startup complete. +``` + +
+ +//// + +Die einzige neue Option hier ist `--workers`, die Uvicorn anweist, 4 Workerprozesse zu starten. + +Sie können auch sehen, dass die **PID** jedes Prozesses angezeigt wird, `27365` für den übergeordneten Prozess (dies ist der **Prozessmanager**) und eine für jeden Workerprozess: `27368`, `27369`, `27370` und `27367`. + +## Deployment-Konzepte { #deployment-concepts } + +Hier haben Sie gesehen, wie Sie mehrere **Worker** verwenden, um die Ausführung der Anwendung zu **parallelisieren**, **mehrere Kerne** der CPU zu nutzen und in der Lage zu sein, **mehr Requests** zu bearbeiten. + +In der Liste der Deployment-Konzepte von oben würde die Verwendung von Workern hauptsächlich bei der **Replikation** und ein wenig bei **Neustarts** helfen, aber Sie müssen sich trotzdem um die anderen kümmern: + +* **Sicherheit – HTTPS** +* **Beim Hochfahren ausführen** +* ***Neustarts*** +* Replikation (die Anzahl der laufenden Prozesse) +* **Arbeitsspeicher** +* **Schritte vor dem Start** + +## Container und Docker { #containers-and-docker } + +Im nächsten Kapitel über [FastAPI in Containern – Docker](docker.md) werde ich einige Strategien erläutern, die Sie für den Umgang mit den anderen **Deployment-Konzepten** verwenden können. + +Ich zeige Ihnen, wie Sie **Ihr eigenes Image von Grund auf erstellen**, um einen einzelnen Uvicorn-Prozess auszuführen. Es ist ein einfacher Vorgang und wahrscheinlich das, was Sie tun möchten, wenn Sie ein verteiltes Containerverwaltungssystem wie **Kubernetes** verwenden. + +## Zusammenfassung { #recap } + +Sie können mehrere Workerprozesse mit der `--workers`-CLI-Option über die `fastapi`- oder `uvicorn`-Befehle nutzen, um **Multikern-CPUs** auszunutzen und **mehrere Prozesse parallel** auszuführen. + +Sie könnten diese Tools und Ideen nutzen, wenn Sie **Ihr eigenes Deployment-System** einrichten und sich dabei selbst um die anderen Deployment-Konzepte kümmern. + +Schauen Sie sich das nächste Kapitel an, um mehr über **FastAPI** mit Containern (z. B. Docker und Kubernetes) zu erfahren. Sie werden sehen, dass diese Tools auch einfache Möglichkeiten bieten, die anderen **Deployment-Konzepte** zu lösen. ✨ diff --git a/docs/de/docs/deployment/versions.md b/docs/de/docs/deployment/versions.md new file mode 100644 index 0000000000000..e4af5ad964cb4 --- /dev/null +++ b/docs/de/docs/deployment/versions.md @@ -0,0 +1,93 @@ +# Über FastAPI-Versionen { #about-fastapi-versions } + +**FastAPI** wird bereits in vielen Anwendungen und Systemen produktiv eingesetzt. Und die Testabdeckung wird bei 100 % gehalten. Aber seine Entwicklung geht immer noch schnell voran. + +Es werden regelmäßig neue Funktionen hinzugefügt, Fehler werden regelmäßig behoben und der Code wird weiterhin kontinuierlich verbessert. + +Aus diesem Grund sind die aktuellen Versionen immer noch `0.x.x`, was darauf hindeutet, dass jede Version möglicherweise nicht abwärtskompatible Änderungen haben könnte. Dies folgt den Konventionen der [Semantische Versionierung](https://semver.org/). + +Sie können jetzt Produktionsanwendungen mit **FastAPI** erstellen (und das tun Sie wahrscheinlich schon seit einiger Zeit), Sie müssen nur sicherstellen, dass Sie eine Version verwenden, die korrekt mit dem Rest Ihres Codes funktioniert. + +## Ihre `fastapi`-Version pinnen { #pin-your-fastapi-version } + +Als Erstes sollten Sie die Version von **FastAPI**, die Sie verwenden, an die höchste Version „pinnen“, von der Sie wissen, dass sie für Ihre Anwendung korrekt funktioniert. + +Angenommen, Sie verwenden in Ihrer App die Version `0.112.0`. + +Wenn Sie eine `requirements.txt`-Datei verwenden, können Sie die Version wie folgt angeben: + +```txt +fastapi[standard]==0.112.0 +``` + +Das würde bedeuten, dass Sie genau die Version `0.112.0` verwenden. + +Oder Sie können sie auch anpinnen mit: + +```txt +fastapi[standard]>=0.112.0,<0.113.0 +``` + +Das würde bedeuten, dass Sie eine Version `0.112.0` oder höher verwenden würden, aber kleiner als `0.113.0`, beispielsweise würde eine Version `0.112.2` immer noch akzeptiert. + +Wenn Sie zum Verwalten Ihrer Installationen andere Tools wie `uv`, Poetry, Pipenv oder andere verwenden, sie verfügen alle über eine Möglichkeit, bestimmte Versionen für Ihre Packages zu definieren. + +## Verfügbare Versionen { #available-versions } + +Die verfügbaren Versionen können Sie in den [Versionshinweisen](../release-notes.md) einsehen (z. B. um zu überprüfen, welches die neueste Version ist). + +## Über Versionen { #about-versions } + +Gemäß den Konventionen zur semantischen Versionierung könnte jede Version unter `1.0.0` potenziell nicht abwärtskompatible Änderungen hinzufügen. + +FastAPI folgt auch der Konvention, dass jede „PATCH“-Versionsänderung für Bugfixes und abwärtskompatible Änderungen gedacht ist. + +/// tip | Tipp + +Der „PATCH“ ist die letzte Zahl, zum Beispiel ist in `0.2.3` die PATCH-Version `3`. + +/// + +Sie sollten also in der Lage sein, eine Version wie folgt anzupinnen: + +```txt +fastapi>=0.45.0,<0.46.0 +``` + +Nicht abwärtskompatible Änderungen und neue Funktionen werden in „MINOR“-Versionen hinzugefügt. + +/// tip | Tipp + +„MINOR“ ist die Zahl in der Mitte, zum Beispiel ist in `0.2.3` die MINOR-Version `2`. + +/// + +## Upgrade der FastAPI-Versionen { #upgrading-the-fastapi-versions } + +Sie sollten Tests für Ihre App hinzufügen. + +Mit **FastAPI** ist das sehr einfach (dank Starlette), schauen Sie sich die Dokumentation an: [Testen](../tutorial/testing.md) + +Nachdem Sie Tests erstellt haben, können Sie die **FastAPI**-Version auf eine neuere Version aktualisieren und sicherstellen, dass Ihr gesamter Code ordnungsgemäß funktioniert, indem Sie Ihre Tests ausführen. + +Wenn alles funktioniert oder nachdem Sie die erforderlichen Änderungen vorgenommen haben und alle Ihre Tests bestehen, können Sie Ihr `fastapi` an die neue aktuelle Version pinnen. + +## Über Starlette { #about-starlette } + +Sie sollten die Version von `starlette` nicht pinnen. + +Verschiedene Versionen von **FastAPI** verwenden eine bestimmte neuere Version von Starlette. + +Sie können **FastAPI** also einfach die korrekte Starlette-Version verwenden lassen. + +## Über Pydantic { #about-pydantic } + +Pydantic integriert die Tests für **FastAPI** in seine eigenen Tests, sodass neue Versionen von Pydantic (über `1.0.0`) immer mit FastAPI kompatibel sind. + +Sie können Pydantic an jede für Sie geeignete Version über `1.0.0` anpinnen. + +Zum Beispiel: + +```txt +pydantic>=2.7.0,<3.0.0 +``` diff --git a/docs/de/docs/editor-support.md b/docs/de/docs/editor-support.md new file mode 100644 index 0000000000000..f93dd5346d446 --- /dev/null +++ b/docs/de/docs/editor-support.md @@ -0,0 +1,23 @@ +# Editor-Unterstützung { #editor-support } + +Die offizielle [FastAPI-Erweiterung](https://marketplace.visualstudio.com/items?itemName=FastAPILabs.fastapi-vscode) verbessert Ihren FastAPI-Entwicklungsworkflow mit *Pfadoperation*-Erkennung und -Navigation sowie FastAPI-Cloud-Deployment und Live-Logstreaming. + +Weitere Details zur Erweiterung finden Sie im README im [GitHub-Repository](https://github.com/fastapi/fastapi-vscode). + +## Einrichtung und Installation { #setup-and-installation } + +Die **FastAPI-Erweiterung** ist sowohl für [VS Code](https://code.visualstudio.com/) als auch für [Cursor](https://www.cursor.com/) verfügbar. Sie kann direkt über das Erweiterungen-Panel in jedem Editor installiert werden, indem Sie nach „FastAPI“ suchen und die von **FastAPI Labs** veröffentlichte Erweiterung auswählen. Die Erweiterung funktioniert auch in browserbasierten Editoren wie [vscode.dev](https://vscode.dev) und [github.dev](https://github.dev). + +### Anwendungserkennung { #application-discovery } + +Standardmäßig erkennt die Erweiterung FastAPI-Anwendungen in Ihrem Workspace automatisch, indem sie nach Dateien sucht, die `FastAPI()` instanziieren. Falls die automatische Erkennung mit Ihrer Projektstruktur nicht funktioniert, können Sie einen Entry-Point über `[tool.fastapi]` in `pyproject.toml` oder die VS-Code-Einstellung `fastapi.entryPoint` in Modulnotation angeben (z. B. `myapp.main:app`). + +## Funktionen { #features } + +- **Pfadoperation-Explorer** – Eine Baumansicht in der Seitenleiste aller *Pfadoperationen* in Ihrer Anwendung. Klicken Sie, um zu einer beliebigen Route- oder Router-Definition zu springen. +- **Routensuche** – Suchen Sie nach Pfad, Methode oder Namen mit Ctrl + Shift + E (unter macOS: Cmd + Shift + E). +- **CodeLens-Navigation** – Anklickbare Links oberhalb von Testclient-Aufrufen (z. B. `client.get('/items')`), die zur passenden *Pfadoperation* springen und so eine schnelle Navigation zwischen Tests und Implementierung ermöglichen. +- **Zu FastAPI Cloud deployen** – Deployment Ihrer App mit einem Klick auf [FastAPI Cloud](https://fastapicloud.com/). +- **Anwendungslogs streamen** – Echtzeit-Logstreaming Ihrer auf FastAPI Cloud deployten Anwendung mit Loglevel-Filterung und Textsuche. + +Wenn Sie sich mit den Funktionen der Erweiterung vertraut machen möchten, können Sie den Erweiterungs‑Walkthrough aufrufen, indem Sie die Befehlspalette öffnen (Ctrl + Shift + P oder unter macOS: Cmd + Shift + P) und „Welcome: Open walkthrough ...“ auswählen und anschließend den Walkthrough „Get started with FastAPI“ wählen. diff --git a/docs/de/docs/environment-variables.md b/docs/de/docs/environment-variables.md new file mode 100644 index 0000000000000..1678ead273e8c --- /dev/null +++ b/docs/de/docs/environment-variables.md @@ -0,0 +1,298 @@ +# Umgebungsvariablen { #environment-variables } + +/// tip | Tipp + +Wenn Sie bereits wissen, was „Umgebungsvariablen“ sind und wie man sie verwendet, können Sie dies überspringen. + +/// + +Eine Umgebungsvariable (auch bekannt als „**env var**“) ist eine Variable, die **außerhalb** des Python-Codes im **Betriebssystem** lebt und von Ihrem Python-Code (oder auch von anderen Programmen) gelesen werden kann. + +Umgebungsvariablen können nützlich sein, um **Einstellungen** der Anwendung zu handhaben, als Teil der **Installation** von Python usw. + +## Umgebungsvariablen erstellen und verwenden { #create-and-use-env-vars } + +Sie können Umgebungsvariablen in der **Shell (Terminal)** **erstellen** und verwenden, ohne Python zu benötigen: + +//// tab | Linux, macOS, Windows Bash + +
+ +```console +// Sie können eine Umgebungsvariable MY_NAME erstellen mit +$ export MY_NAME="Wade Wilson" + +// Dann können Sie sie mit anderen Programmen verwenden, etwa +$ echo "Hello $MY_NAME" + +Hello Wade Wilson +``` + +
+ +//// + +//// tab | Windows PowerShell + +
+ +```console +// Erstellen Sie eine Umgebungsvariable MY_NAME +$ $Env:MY_NAME = "Wade Wilson" + +// Verwenden Sie sie mit anderen Programmen, etwa +$ echo "Hello $Env:MY_NAME" + +Hello Wade Wilson +``` + +
+ +//// + +## Umgebungsvariablen in Python lesen { #read-env-vars-in-python } + +Sie können auch Umgebungsvariablen **außerhalb** von Python erstellen, im Terminal (oder mit jeder anderen Methode) und sie dann **in Python** lesen. + +Zum Beispiel könnten Sie eine Datei `main.py` haben mit: + +```Python hl_lines="3" +import os + +name = os.getenv("MY_NAME", "World") +print(f"Hello {name} from Python") +``` + +/// tip | Tipp + +Das zweite Argument von [`os.getenv()`](https://docs.python.org/3.8/library/os.html#os.getenv) ist der Defaultwert, der zurückgegeben wird. + +Wenn er nicht angegeben wird, ist er standardmäßig `None`. Hier geben wir `"World"` als den zu verwendenden Defaultwert an. + +/// + +Dann könnten Sie das Python-Programm aufrufen: + +//// tab | Linux, macOS, Windows Bash + +
+ +```console +// Hier setzen wir die Umgebungsvariable noch nicht +$ python main.py + +// Da wir die Umgebungsvariable nicht gesetzt haben, erhalten wir den Defaultwert + +Hello World from Python + +// Aber wenn wir zuerst eine Umgebungsvariable erstellen +$ export MY_NAME="Wade Wilson" + +// Und dann das Programm erneut aufrufen +$ python main.py + +// Jetzt kann es die Umgebungsvariable lesen + +Hello Wade Wilson from Python +``` + +
+ +//// + +//// tab | Windows PowerShell + +
+ +```console +// Hier setzen wir die Umgebungsvariable noch nicht +$ python main.py + +// Da wir die Umgebungsvariable nicht gesetzt haben, erhalten wir den Defaultwert + +Hello World from Python + +// Aber wenn wir zuerst eine Umgebungsvariable erstellen +$ $Env:MY_NAME = "Wade Wilson" + +// Und dann das Programm erneut aufrufen +$ python main.py + +// Jetzt kann es die Umgebungsvariable lesen + +Hello Wade Wilson from Python +``` + +
+ +//// + +Da Umgebungsvariablen außerhalb des Codes gesetzt werden können, aber vom Code gelesen werden können und nicht mit den restlichen Dateien gespeichert (in `git` committet) werden müssen, werden sie häufig für Konfigurationen oder **Einstellungen** verwendet. + +Sie können auch eine Umgebungsvariable nur für einen **spezifischen Programmaufruf** erstellen, die nur für dieses Programm und nur für dessen Dauer verfügbar ist. + +Um dies zu tun, erstellen Sie sie direkt vor dem Programmaufruf, in derselben Zeile: + +
+ +```console +// Erstellen Sie eine Umgebungsvariable MY_NAME in der Zeile für diesen Programmaufruf +$ MY_NAME="Wade Wilson" python main.py + +// Jetzt kann es die Umgebungsvariable lesen + +Hello Wade Wilson from Python + +// Die Umgebungsvariable existiert danach nicht mehr +$ python main.py + +Hello World from Python +``` + +
+ +/// tip | Tipp + +Sie können mehr darüber lesen auf [The Twelve-Factor App: Config](https://12factor.net/config). + +/// + +## Typen und Validierung { #types-and-validation } + +Diese Umgebungsvariablen können nur **Textstrings** handhaben, da sie extern zu Python sind und kompatibel mit anderen Programmen und dem Rest des Systems (und sogar mit verschiedenen Betriebssystemen, wie Linux, Windows, macOS) sein müssen. + +Das bedeutet, dass **jeder Wert**, der in Python von einer Umgebungsvariablen gelesen wird, **ein `str` sein wird**, und jede Konvertierung in einen anderen Typ oder jede Validierung muss im Code vorgenommen werden. + +Sie werden mehr darüber lernen, wie man Umgebungsvariablen zur Handhabung von **Anwendungseinstellungen** verwendet, im [Handbuch für fortgeschrittene Benutzer – Einstellungen und Umgebungsvariablen](./advanced/settings.md). + +## `PATH`-Umgebungsvariable { #path-environment-variable } + +Es gibt eine **spezielle** Umgebungsvariable namens **`PATH`**, die von den Betriebssystemen (Linux, macOS, Windows) verwendet wird, um Programme zu finden, die ausgeführt werden sollen. + +Der Wert der Variable `PATH` ist ein langer String, der aus Verzeichnissen besteht, die auf Linux und macOS durch einen Doppelpunkt `:` und auf Windows durch ein Semikolon `;` getrennt sind. + +Zum Beispiel könnte die `PATH`-Umgebungsvariable so aussehen: + +//// tab | Linux, macOS + +```plaintext +/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin +``` + +Das bedeutet, dass das System nach Programmen in den Verzeichnissen suchen sollte: + +* `/usr/local/bin` +* `/usr/bin` +* `/bin` +* `/usr/sbin` +* `/sbin` + +//// + +//// tab | Windows + +```plaintext +C:\Program Files\Python312\Scripts;C:\Program Files\Python312;C:\Windows\System32 +``` + +Das bedeutet, dass das System nach Programmen in den Verzeichnissen suchen sollte: + +* `C:\Program Files\Python312\Scripts` +* `C:\Program Files\Python312` +* `C:\Windows\System32` + +//// + +Wenn Sie einen **Befehl** im Terminal eingeben, **sucht** das Betriebssystem nach dem Programm in **jedem dieser Verzeichnisse**, die in der `PATH`-Umgebungsvariablen aufgeführt sind. + +Zum Beispiel, wenn Sie `python` im Terminal eingeben, sucht das Betriebssystem nach einem Programm namens `python` im **ersten Verzeichnis** in dieser Liste. + +Wenn es es findet, wird es **benutzt**. Andernfalls sucht es weiter in den **anderen Verzeichnissen**. + +### Python installieren und den `PATH` aktualisieren { #installing-python-and-updating-the-path } + +Wenn Sie Python installieren, könnten Sie gefragt werden, ob Sie die `PATH`-Umgebungsvariable aktualisieren möchten. + +//// tab | Linux, macOS + +Angenommen, Sie installieren Python und es landet in einem Verzeichnis `/opt/custompython/bin`. + +Wenn Sie erlauben, die `PATH`-Umgebungsvariable zu aktualisieren, fügt der Installer `/opt/custompython/bin` zur `PATH`-Umgebungsvariable hinzu. + +Das könnte so aussehen: + +```plaintext +/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/custompython/bin +``` + +Auf diese Weise, wenn Sie `python` im Terminal eingeben, findet das System das Python-Programm in `/opt/custompython/bin` (das letzte Verzeichnis) und verwendet dieses. + +//// + +//// tab | Windows + +Angenommen, Sie installieren Python und es landet in einem Verzeichnis `C:\opt\custompython\bin`. + +Wenn Sie erlauben, die `PATH`-Umgebungsvariable zu aktualisieren, fügt der Installer `C:\opt\custompython\bin` zur `PATH`-Umgebungsvariable hinzu. + +```plaintext +C:\Program Files\Python312\Scripts;C:\Program Files\Python312;C:\Windows\System32;C:\opt\custompython\bin +``` + +Auf diese Weise, wenn Sie `python` im Terminal eingeben, findet das System das Python-Programm in `C:\opt\custompython\bin` (das letzte Verzeichnis) und verwendet dieses. + +//// + +Also, wenn Sie tippen: + +
+ +```console +$ python +``` + +
+ +//// tab | Linux, macOS + +Das System wird das `python`-Programm in `/opt/custompython/bin` **finden** und es ausführen. + +Es wäre ungefähr gleichbedeutend mit der Eingabe von: + +
+ +```console +$ /opt/custompython/bin/python +``` + +
+ +//// + +//// tab | Windows + +Das System wird das `python`-Programm in `C:\opt\custompython\bin\python` **finden** und es ausführen. + +Es wäre ungefähr gleichbedeutend mit der Eingabe von: + +
+ +```console +$ C:\opt\custompython\bin\python +``` + +
+ +//// + +Diese Informationen werden nützlich sein, wenn Sie über [Virtuelle Umgebungen](virtual-environments.md) lernen. + +## Fazit { #conclusion } + +Mit diesem Wissen sollten Sie ein grundlegendes Verständnis davon haben, was **Umgebungsvariablen** sind und wie man sie in Python verwendet. + +Sie können auch mehr darüber in der [Wikipedia zu Umgebungsvariablen](https://en.wikipedia.org/wiki/Environment_variable) lesen. + +In vielen Fällen ist es nicht sehr offensichtlich, wie Umgebungsvariablen nützlich und sofort anwendbar sein könnten. Aber sie tauchen immer wieder in vielen verschiedenen Szenarien auf, wenn Sie entwickeln, deshalb ist es gut, darüber Bescheid zu wissen. + +Zum Beispiel werden Sie diese Informationen im nächsten Abschnitt über [Virtuelle Umgebungen](virtual-environments.md) benötigen. diff --git a/docs/de/docs/fastapi-cli.md b/docs/de/docs/fastapi-cli.md new file mode 100644 index 0000000000000..4202501bce477 --- /dev/null +++ b/docs/de/docs/fastapi-cli.md @@ -0,0 +1,134 @@ +# FastAPI CLI { #fastapi-cli } + +**FastAPI CLI** ist ein Kommandozeilenprogramm, mit dem Sie Ihre FastAPI-App bereitstellen, Ihr FastAPI-Projekt verwalten und mehr. + +Wenn Sie FastAPI installieren (z. B. mit `pip install "fastapi[standard]"`), erhalten Sie ein Kommandozeilenprogramm, das Sie im Terminal ausführen können. + +Um Ihre FastAPI-App für die Entwicklung auszuführen, können Sie den Befehl `fastapi dev` verwenden: + +
+ +```console +$ fastapi dev + + FastAPI Starting development server 🚀 + + Searching for package file structure from directories with + __init__.py files + Importing from /home/user/code/awesomeapp + + module 🐍 main.py + + code Importing the FastAPI app object from the module with the + following code: + + from main import app + + app Using import string: main:app + + server Server started at http://127.0.0.1:8000 + server Documentation at http://127.0.0.1:8000/docs + + tip Running in development mode, for production use: + fastapi run + + Logs: + + INFO Will watch for changes in these directories: + ['/home/user/code/awesomeapp'] + INFO Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to + quit) + INFO Started reloader process [383138] using WatchFiles + INFO Started server process [383153] + INFO Waiting for application startup. + INFO Application startup complete. +``` + +
+ +/// tip | Tipp + +Für die Produktion würden Sie statt `fastapi dev` `fastapi run` verwenden. 🚀 + +/// + +Intern verwendet das **FastAPI CLI** [Uvicorn](https://www.uvicorn.dev), einen leistungsstarken, produktionsreifen, ASGI-Server. 😎 + +Das `fastapi`-CLI versucht automatisch, die auszuführende FastAPI-App zu erkennen, und geht davon aus, dass es sich um ein Objekt namens `app` in einer Datei `main.py` handelt (oder ein paar weitere Varianten). + +Sie können aber auch explizit konfigurieren, welche App verwendet werden soll. + +## Den App-`entrypoint` in `pyproject.toml` konfigurieren { #configure-the-app-entrypoint-in-pyproject-toml } + +Sie können in einer `pyproject.toml`-Datei konfigurieren, wo sich Ihre App befindet, etwa so: + +```toml +[tool.fastapi] +entrypoint = "main:app" +``` + +Dieser `entrypoint` teilt dem Befehl `fastapi` mit, dass die App so importiert werden soll: + +```python +from main import app +``` + +Wenn Ihr Code so strukturiert wäre: + +``` +. +├── backend +│   ├── main.py +│   ├── __init__.py +``` + +Dann würden Sie den `entrypoint` wie folgt setzen: + +```toml +[tool.fastapi] +entrypoint = "backend.main:app" +``` + +was gleichbedeutend wäre mit: + +```python +from backend.main import app +``` + +### `fastapi dev` mit Pfad oder mit der CLI-Option `--entrypoint` { #fastapi-dev-with-path-or-with-entrypoint-cli-option } + +Sie können auch den Dateipfad an den Befehl `fastapi dev` übergeben, dann wird das zu verwendende FastAPI-App-Objekt erraten: + +```console +$ fastapi dev main.py +``` + +Oder Sie können auch die Option `--entrypoint` an den Befehl `fastapi dev` übergeben: + +```console +$ fastapi dev --entrypoint main:app +``` + +Aber Sie müssten sich merken, bei jedem Aufruf des `fastapi`-Befehls den korrekten Pfad\entrypoint zu übergeben. + +Zusätzlich könnten andere Tools sie nicht finden, z. B. die [VS Code Extension](editor-support.md) oder [FastAPI Cloud](https://fastapicloud.com), daher wird empfohlen, den `entrypoint` in `pyproject.toml` zu verwenden. + +## `fastapi dev` { #fastapi-dev } + +Das Ausführen von `fastapi dev` startet den Entwicklermodus. + +Standardmäßig ist **Autoreload** aktiviert, das den Server automatisch neu lädt, wenn Sie Änderungen an Ihrem Code vornehmen. Dies ist ressourcenintensiv und könnte weniger stabil sein als wenn es deaktiviert ist. Sie sollten es nur für die Entwicklung verwenden. Es horcht auch auf der IP-Adresse `127.0.0.1`, die die IP für Ihre Maschine ist, um nur mit sich selbst zu kommunizieren (`localhost`). + +## `fastapi run` { #fastapi-run } + +Das Ausführen von `fastapi run` startet FastAPI im Produktionsmodus. + +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. + +/// tip | Tipp + +Sie können mehr darüber in der [Deployment-Dokumentation](deployment/index.md) erfahren. + +/// diff --git a/docs/de/docs/features.md b/docs/de/docs/features.md new file mode 100644 index 0000000000000..f24ec24269c4c --- /dev/null +++ b/docs/de/docs/features.md @@ -0,0 +1,201 @@ +# Merkmale { #features } + +## FastAPI-Merkmale { #fastapi-features } + +**FastAPI** ermöglicht Ihnen Folgendes: + +### Auf offenen Standards basieren { #based-on-open-standards } + +* [**OpenAPI**](https://github.com/OAI/OpenAPI-Specification) für die Erstellung von APIs, inklusive Deklarationen von Pfad-Operationen, Parametern, Requestbodys, Sicherheit, usw. +* Automatische Dokumentation der Datenmodelle mit [**JSON Schema**](https://json-schema.org/) (da OpenAPI selbst auf JSON Schema basiert). +* Um diese Standards herum entworfen, nach sorgfältigem Studium. Statt einer nachträglichen Schicht darüber. +* Dies ermöglicht auch automatische **Client-Code-Generierung** in vielen Sprachen. + +### Automatische Dokumentation { #automatic-docs } + +Interaktive API-Dokumentation und erkundbare Web-Benutzeroberflächen. Da das Framework auf OpenAPI basiert, gibt es mehrere Optionen, zwei sind standardmäßig vorhanden. + +* [**Swagger UI**](https://github.com/swagger-api/swagger-ui), mit interaktiver Erkundung, rufen Sie Ihre API direkt vom Browser aus auf und testen Sie sie. + +![Swagger UI Interaktion](https://fastapi.tiangolo.com/img/index/index-03-swagger-02.png) + +* Alternative API-Dokumentation mit [**ReDoc**](https://github.com/Rebilly/ReDoc). + +![ReDoc](https://fastapi.tiangolo.com/img/index/index-06-redoc-02.png) + +### Nur modernes Python { #just-modern-python } + +Alles basiert auf Standard-**Python-Typ**deklarationen (dank Pydantic). Es muss keine neue Syntax gelernt werden, nur standardisiertes modernes Python. + +Wenn Sie eine zweiminütige Auffrischung benötigen, wie man Python-Typen verwendet (auch wenn Sie FastAPI nicht benutzen), schauen Sie sich das kurze Tutorial an: [Einführung in Python-Typen](python-types.md). + +Sie schreiben Standard-Python mit Typen: + +```Python +from datetime import date + +from pydantic import BaseModel + +# Deklarieren Sie eine Variable vom Typ str +# und bekommen Sie Editor-Unterstützung innerhalb der Funktion +def main(user_id: str): + return user_id + + +# Ein Pydantic-Modell +class User(BaseModel): + id: int + name: str + joined: date +``` + +Das kann nun wie folgt verwendet werden: + +```Python +my_user: User = User(id=3, name="John Doe", joined="2018-07-19") + +second_user_data = { + "id": 4, + "name": "Mary", + "joined": "2018-11-30", +} + +my_second_user: User = User(**second_user_data) +``` + +/// note | Hinweis + +`**second_user_data` bedeutet: + +Übergeben Sie die Schlüssel und Werte des `second_user_data` Dicts direkt als Schlüssel-Wert-Argumente, äquivalent zu: `User(id=4, name="Mary", joined="2018-11-30")` + +/// + +### Editorunterstützung { #editor-support } + +Das ganze Framework wurde so entworfen, dass es einfach und intuitiv zu benutzen ist; alle Entscheidungen wurden auf mehreren Editoren getestet, sogar vor der Implementierung, um die bestmögliche Entwicklererfahrung zu gewährleisten. + +In den Python-Entwickler-Umfragen wird klar, [dass die meist genutzte Funktion die „Autovervollständigung“ ist](https://www.jetbrains.com/research/python-developers-survey-2017/#tools-and-features). + +Das gesamte **FastAPI**-Framework ist darauf ausgelegt, das zu erfüllen. Autovervollständigung funktioniert überall. + +Sie werden selten noch mal in der Dokumentation nachschauen müssen. + +So kann Ihr Editor Sie unterstützen: + +* in [Visual Studio Code](https://code.visualstudio.com/): + +![Editorunterstützung](https://fastapi.tiangolo.com/img/vscode-completion.png) + +* in [PyCharm](https://www.jetbrains.com/pycharm/): + +![Editorunterstützung](https://fastapi.tiangolo.com/img/pycharm-completion.png) + +Sie bekommen sogar Autovervollständigung an Stellen, an denen Sie dies vorher nicht für möglich gehalten hätten. Zum Beispiel der `price`-Schlüssel innerhalb eines JSON-Bodys (dieser könnte auch verschachtelt sein), der aus einem Request kommt. + +Nie wieder falsche Schlüsselnamen tippen, Hin und Herhüpfen zwischen der Dokumentation, Hoch- und Runterscrollen, um herauszufinden, ob es `username` oder `user_name` war. + +### Kompakt { #short } + +Es gibt für alles sinnvolle **Defaultwerte**, mit optionaler Konfiguration überall. Alle Parameter können feinjustiert werden, damit sie tun, was Sie benötigen, und die API definieren, die Sie brauchen. + +Aber standardmäßig **„funktioniert einfach alles“**. + +### Validierung { #validation } + +* Validierung für die meisten (oder alle?) Python-**Datentypen**, hierzu gehören: + * JSON-Objekte (`dict`). + * JSON-Array (`list`), das Elementtypen definiert. + * String-Felder (`str`) mit definierter minimaler und maximaler Länge. + * Zahlen (`int`, `float`) mit Mindest- und Maximalwerten, usw. + +* Validierung für exotischere Typen, wie: + * URL. + * E-Mail. + * UUID. + * ... und andere. + +Die gesamte Validierung übernimmt das gut etablierte und robuste **Pydantic**. + +### Sicherheit und Authentifizierung { #security-and-authentication } + +Sicherheit und Authentifizierung sind integriert. Ohne Kompromisse bei Datenbanken oder Datenmodellen. + +Alle in OpenAPI definierten Sicherheitsschemas, inklusive: + +* HTTP Basic. +* **OAuth2** (auch mit **JWT-Tokens**). Siehe dazu das Tutorial zu [OAuth2 mit JWT](tutorial/security/oauth2-jwt.md). +* API-Schlüssel in: + * Headern. + * Query-Parametern. + * Cookies, usw. + +Zusätzlich alle Sicherheitsfunktionen von Starlette (inklusive **Session-Cookies**). + +Alles als wiederverwendbare Tools und Komponenten gebaut, die einfach in Ihre Systeme, Datenspeicher, relationale und NoSQL-Datenbanken, usw., integriert werden können. + +### Dependency Injection { #dependency-injection } + +FastAPI enthält ein extrem einfach zu verwendendes, aber extrem mächtiges Dependency Injection-System. + +* Selbst Abhängigkeiten können Abhängigkeiten haben, woraus eine Hierarchie oder ein **„Graph“ von Abhängigkeiten** entsteht. +* Alles **automatisch gehandhabt** durch das Framework. +* Alle Abhängigkeiten können Daten von Requests anfordern und die Einschränkungen der **Pfadoperationen** sowie die automatische Dokumentation **erweitern**. +* **Automatische Validierung** selbst für solche Parameter von *Pfadoperationen*, welche in Abhängigkeiten definiert sind. +* Unterstützung für komplexe Benutzerauthentifizierungssysteme, **Datenbankverbindungen**, usw. +* **Keine Kompromisse** bei Datenbanken, Frontends, usw., sondern einfache Integration mit allen. + +### Unbegrenzte „Plug-ins“ { #unlimited-plug-ins } + +Oder mit anderen Worten, sie werden nicht benötigt. Importieren und nutzen Sie den Code, den Sie brauchen. + +Jede Integration wurde so entworfen, dass sie so einfach zu nutzen ist (mit Abhängigkeiten), dass Sie ein „Plug-in“ für Ihre Anwendung mit nur 2 Zeilen Code erstellen können. Hierbei nutzen Sie die gleiche Struktur und Syntax, wie bei *Pfadoperationen*. + +### Getestet { #tested } + +* 100 % Testabdeckung. +* Zu 100 % typannotierte Codebasis. +* Verwendet in Produktionsanwendungen. + +## Starlette-Merkmale { #starlette-features } + +**FastAPI** ist vollkommen kompatibel (und basiert auf) [**Starlette**](https://www.starlette.dev/). Das bedeutet, wenn Sie eigenen Starlette-Quellcode haben, funktioniert dieser auch. + +`FastAPI` ist tatsächlich eine Unterklasse von `Starlette`. Wenn Sie also bereits Starlette kennen oder benutzen, das meiste funktioniert genau so. + +Mit **FastAPI** bekommen Sie alles von **Starlette** (da FastAPI nur Starlette auf Steroiden ist): + +* Schwer beeindruckende Performanz. Es ist [eines der schnellsten Python-Frameworks, auf Augenhöhe mit **NodeJS** und **Go**](https://github.com/encode/starlette#performance). +* **WebSocket**-Unterstützung. +* Hintergrundtasks im selben Prozess. +* Startup- und Shutdown-Events. +* Testclient basierend auf HTTPX. +* **CORS**, GZip, statische Dateien, Responses streamen. +* **Sitzungs- und Cookie**-Unterstützung. +* 100 % Testabdeckung. +* Zu 100 % typannotierte Codebasis. + +## Pydantic-Merkmale { #pydantic-features } + +**FastAPI** ist vollkommen kompatibel (und basiert auf) [**Pydantic**](https://docs.pydantic.dev/). Das bedeutet, wenn Sie eigenen Pydantic-Quellcode haben, funktioniert dieser auch. + +Inklusive externer Bibliotheken, die auf Pydantic basieren, wie ORMs, ODMs für Datenbanken. + +Daher können Sie in vielen Fällen das Objekt eines Requests **direkt zur Datenbank** schicken, weil alles automatisch validiert wird. + +Das gleiche gilt auch für die andere Richtung: Sie können in vielen Fällen das Objekt aus der Datenbank **direkt zum Client** senden. + +Mit **FastAPI** bekommen Sie alle Funktionen von **Pydantic** (da FastAPI für die gesamte Datenverarbeitung Pydantic nutzt): + +* **Kein Kopfzerbrechen**: + * Keine neue Schemadefinitions-Mikrosprache zu lernen. + * Wenn Sie Pythons Typen kennen, wissen Sie, wie man Pydantic verwendet. +* Gutes Zusammenspiel mit Ihrer/Ihrem **IDE/Linter/Gehirn**: + * Weil Pydantics Datenstrukturen einfach nur Instanzen ihrer definierten Klassen sind; Autovervollständigung, Linting, mypy und Ihre Intuition sollten alle einwandfrei mit Ihren validierten Daten funktionieren. +* Validierung von **komplexen Strukturen**: + * Benutzung von hierarchischen Pydantic-Modellen, Python-`typing`s `List` und `Dict`, usw. + * Die Validierer erlauben es, komplexe Datenschemas klar und einfach zu definieren, überprüft und dokumentiert als JSON Schema. + * Sie können tief **verschachtelte JSON**-Objekte haben, die alle validiert und annotiert sind. +* **Erweiterbar**: + * Pydantic erlaubt die Definition von eigenen Datentypen oder Sie können die Validierung mit Methoden in einem Modell erweitern, die mit dem Validator-Dekorator dekoriert sind. +* 100 % Testabdeckung. diff --git a/docs/de/docs/help-fastapi.md b/docs/de/docs/help-fastapi.md new file mode 100644 index 0000000000000..4a868756263f7 --- /dev/null +++ b/docs/de/docs/help-fastapi.md @@ -0,0 +1,88 @@ +# Helfen { #help } + + +Möchten Sie FastAPI helfen oder Hilfe zu FastAPI erhalten? + +Es gibt sehr einfache Möglichkeiten, zu helfen und Hilfe zu bekommen. + +## Newsletter abonnieren { #subscribe-to-the-newsletter } + +Sie können den (unregelmäßigen) [**FastAPI and friends**-Newsletter](newsletter.md) abonnieren, um über Folgendes informiert zu bleiben: + +* Neuigkeiten über FastAPI und Freunde 🚀 +* Anleitungen 📝 +* Funktionen ✨ +* Breaking Changes 🚨 +* Tipps und Tricks ✅ + +## FastAPI online folgen { #follow-fastapi-online } + +Sie können **FastAPI** an mehreren Orten online folgen: + +* [@fastapi auf **X / Twitter**](https://x.com/fastapi) +* [@fastapi.tiangolo.com auf **Bluesky**](https://bsky.app/profile/fastapi.tiangolo.com) +* [FastAPI auf **LinkedIn**](https://www.linkedin.com/company/fastapi/) + +## **FastAPI** auf GitHub einen Stern geben { #star-fastapi-in-github } + +Sie können FastAPI auf GitHub „starren“ (klicken Sie auf den Stern-Button oben rechts): [https://github.com/fastapi/fastapi](https://github.com/fastapi/fastapi). ⭐️ + +Durch das Hinzufügen eines Sterns können andere Benutzer es leichter finden und sehen, dass es für andere bereits nützlich war. + +## Das GitHub-Repository auf Releases beobachten { #watch-the-github-repository-for-releases } + +Sie können FastAPI auf GitHub „beobachten“ (klicken Sie auf den „Watch“-Button oben rechts): [https://github.com/fastapi/fastapi](https://github.com/fastapi/fastapi). 👀 + +Dort können Sie „Releases only“ auswählen. + +Auf diese Weise erhalten Sie Benachrichtigungen (per E‑Mail), wenn es ein neues Release (eine neue Version) von **FastAPI** mit Bugfixes und neuen Funktionen gibt. + +## Dem Autor folgen { #follow-the-author } + +Sie können [mir (Sebastián Ramírez / `tiangolo`)](https://tiangolo.com), dem Autor, an einigen Orten folgen, um mitzubekommen, wenn ich Neuigkeiten zu FastAPI und Freunden habe: + +* [@tiangolo auf **GitHub**](https://github.com/tiangolo). +* [@tiangolo auf **X (Twitter)**](https://x.com/tiangolo) +* [@tiangolo.com auf **Bluesky**](https://bsky.app/profile/tiangolo.com) +* [@tiangolo auf **LinkedIn**](https://www.linkedin.com/in/tiangolo/). + +## Anderen bei Fragen auf GitHub helfen { #help-others-with-questions-in-github } + +Sie können versuchen, anderen bei ihren Fragen in [GitHub-Diskussionen](https://github.com/fastapi/fastapi/discussions/categories/questions?discussions_q=category%3AQuestions+is%3Aunanswered) zu helfen. + +In vielen Fällen kennen Sie möglicherweise bereits die Antwort auf diese Fragen. 🤓 + +Wenn Sie vielen Menschen bei ihren Fragen helfen, werden Sie offizieller [FastAPI-Experte](fastapi-people.md#fastapi-experts). 🎉 + +Denken Sie daran, der wichtigste Punkt ist: Versuchen Sie, freundlich zu sein. 🤗 + +### So helfen { #how-to-help } + +Folgen Sie der [Anleitung, wie Sie helfen können](https://tiangolo.com/open-source/help/#help-others-with-questions-in-github) hier. + +## Fragen stellen { #ask-questions } + +Sie können im GitHub-Repository [eine neue Frage erstellen](https://github.com/fastapi/fastapi/discussions/new?category=questions), zum Beispiel um: + +* Eine **Frage** zu stellen oder nach einem **Problem** zu fragen. +* Eine neue **Funktionalität** vorzuschlagen. + +## Am Chat teilnehmen { #join-the-chat } + +Treten Sie dem 👥 [Discord-Chatserver](https://discord.gg/VQjSZaeJmf) 👥 bei und treffen Sie sich mit anderen Mitgliedern der FastAPI-Community. + +/// tip | Tipp + +Bei Fragen stellen Sie sie in GitHub-Diskussionen, dort besteht eine viel größere Chance, dass Sie Hilfe erhalten. + +Nutzen Sie den Chat nur für andere allgemeine Gespräche. + +/// + +### Den Chat nicht für Fragen verwenden { #dont-use-the-chat-for-questions } + +Bedenken Sie, dass Sie in Chats, die „freie Konversation“ erlauben, leicht Fragen stellen können, die zu allgemein und schwer zu beantworten sind, sodass Sie möglicherweise keine Antworten erhalten. + +Auf GitHub hilft Ihnen die Vorlage dabei, die richtige Frage zu stellen, sodass Sie leichter eine gute Antwort erhalten können, oder sogar das Problem selbst lösen, bevor Sie überhaupt fragen. + +Unterhaltungen in den Chat-Systemen sind auch nicht so leicht durchsuchbar wie auf GitHub, sie gehen verloren. diff --git a/docs/de/docs/history-design-future.md b/docs/de/docs/history-design-future.md new file mode 100644 index 0000000000000..5984274dba24b --- /dev/null +++ b/docs/de/docs/history-design-future.md @@ -0,0 +1,79 @@ +# Geschichte, Design und Zukunft { #history-design-and-future } + +Vor einiger Zeit fragte [ein **FastAPI**-Benutzer](https://github.com/fastapi/fastapi/issues/3#issuecomment-454956920): + +> Was ist die Geschichte dieses Projekts? Es scheint aus dem Nichts in ein paar Wochen zu etwas Großartigem geworden zu sein [...] + +Hier ist ein wenig über diese Geschichte. + +## Alternativen { #alternatives } + +Ich habe seit mehreren Jahren APIs mit komplexen Anforderungen (maschinelles Lernen, verteilte Systeme, asynchrone Jobs, NoSQL-Datenbanken, usw.) erstellt und leitete mehrere Entwicklerteams. + +Dabei musste ich viele Alternativen untersuchen, testen und nutzen. + +Die Geschichte von **FastAPI** ist zu einem großen Teil die Geschichte seiner Vorgänger. + +Wie im Abschnitt [Alternativen](alternatives.md) gesagt: + +
+ +**FastAPI** würde ohne die frühere Arbeit anderer nicht existieren. + +Es wurden zuvor viele Tools entwickelt, die als Inspiration für seine Entwicklung dienten. + +Ich habe die Schaffung eines neuen Frameworks viele Jahre lang vermieden. Zuerst habe ich versucht, alle von **FastAPI** abgedeckten Funktionen mithilfe vieler verschiedener Frameworks, Plugins und Tools zu lösen. + +Aber irgendwann gab es keine andere Möglichkeit, als etwas zu schaffen, das all diese Funktionen bereitstellte, die besten Ideen früherer Tools aufnahm und diese auf die bestmögliche Weise kombinierte, wobei Sprachfunktionen verwendet wurden, die vorher noch nicht einmal verfügbar waren (Python 3.6+ Typhinweise). + +
+ +## Untersuchung { #investigation } + +Durch die Nutzung all dieser vorherigen Alternativen hatte ich die Möglichkeit, von allen zu lernen, Ideen aufzunehmen und sie auf die beste Weise zu kombinieren, die ich für mich und die Entwicklerteams, mit denen ich zusammengearbeitet habe, finden konnte. + +Es war beispielsweise klar, dass es idealerweise auf Standard-Python-Typhinweisen basieren sollte. + +Der beste Ansatz bestand außerdem darin, bereits bestehende Standards zu nutzen. + +Bevor ich also überhaupt angefangen habe, **FastAPI** zu schreiben, habe ich mehrere Monate damit verbracht, die Spezifikationen für OpenAPI, JSON Schema, OAuth2, usw. zu studieren und deren Beziehungen, Überschneidungen und Unterschiede zu verstehen. + +## Design { #design } + +Dann habe ich einige Zeit damit verbracht, die Entwickler-„API“ zu entwerfen, die ich als Benutzer haben wollte (als Entwickler, welcher FastAPI verwendet). + +Ich habe mehrere Ideen in den beliebtesten Python-Editoren getestet: PyCharm, VS Code, Jedi-basierte Editoren. + +Laut der letzten [Python-Entwickler-Umfrage](https://www.jetbrains.com/research/python-developers-survey-2018/#development-tools) deckt das etwa 80 % der Benutzer ab. + +Das bedeutet, dass **FastAPI** speziell mit den Editoren getestet wurde, die von 80 % der Python-Entwickler verwendet werden. Und da die meisten anderen Editoren in der Regel ähnlich funktionieren, sollten alle diese Vorteile für praktisch alle Editoren funktionieren. + +Auf diese Weise konnte ich die besten Möglichkeiten finden, die Codeverdoppelung so weit wie möglich zu reduzieren, überall Autovervollständigung, Typ- und Fehlerprüfungen, usw. zu gewährleisten. + +Alles auf eine Weise, die allen Entwicklern das beste Entwicklungserlebnis bot. + +## Anforderungen { #requirements } + +Nachdem ich mehrere Alternativen getestet hatte, entschied ich, dass ich [**Pydantic**](https://docs.pydantic.dev/) wegen seiner Vorteile verwenden würde. + +Dann habe ich zu dessen Code beigetragen, um es vollständig mit JSON Schema kompatibel zu machen, und so verschiedene Möglichkeiten zum Definieren von einschränkenden Deklarationen (Constraints) zu unterstützen, und die Editorunterstützung (Typprüfungen, Codevervollständigung) zu verbessern, basierend auf den Tests in mehreren Editoren. + +Während der Entwicklung habe ich auch zu [**Starlette**](https://www.starlette.dev/) beigetragen, die andere Schlüsselanforderung. + +## Entwicklung { #development } + +Als ich mit der Erstellung von **FastAPI** selbst begann, waren die meisten Teile bereits vorhanden, das Design definiert, die Anforderungen und Tools bereit und das Wissen über die Standards und Spezifikationen klar und frisch. + +## Zukunft { #future } + +Zu diesem Zeitpunkt ist bereits klar, dass **FastAPI** mit seinen Ideen für viele Menschen nützlich ist. + +Es wird gegenüber früheren Alternativen gewählt, da es für viele Anwendungsfälle besser geeignet ist. + +Viele Entwickler und Teams verlassen sich bei ihren Projekten bereits auf **FastAPI** (einschließlich mir und meinem Team). + +Dennoch stehen uns noch viele Verbesserungen und Funktionen bevor. + +**FastAPI** hat eine große Zukunft vor sich. + +Und [Ihre Hilfe](help-fastapi.md) wird sehr geschätzt. diff --git a/docs/de/docs/how-to/authentication-error-status-code.md b/docs/de/docs/how-to/authentication-error-status-code.md new file mode 100644 index 0000000000000..02acef9f1d112 --- /dev/null +++ b/docs/de/docs/how-to/authentication-error-status-code.md @@ -0,0 +1,17 @@ +# 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, [RFC 7235](https://datatracker.ietf.org/doc/html/rfc7235#section-3.1), [RFC 9110](https://datatracker.ietf.org/doc/html/rfc9110#name-401-unauthorized). + +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_py310.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. + +/// diff --git a/docs/de/docs/how-to/conditional-openapi.md b/docs/de/docs/how-to/conditional-openapi.md new file mode 100644 index 0000000000000..dc873c9c93913 --- /dev/null +++ b/docs/de/docs/how-to/conditional-openapi.md @@ -0,0 +1,56 @@ +# Bedingte OpenAPI { #conditional-openapi } + +Bei Bedarf können Sie OpenAPI mithilfe von Einstellungen und Umgebungsvariablen abhängig von der Umgebung bedingt konfigurieren und sogar vollständig deaktivieren. + +## Über Sicherheit, APIs und Dokumentation { #about-security-apis-and-docs } + +Das Verstecken Ihrer Dokumentationsoberflächen in der Produktion *sollte nicht* die Methode sein, Ihre API zu schützen. + +Dadurch wird Ihrer API keine zusätzliche Sicherheit hinzugefügt, die *Pfadoperationen* sind weiterhin dort verfügbar, wo sie sich befinden. + +Wenn Ihr Code eine Sicherheitslücke aufweist, ist diese weiterhin vorhanden. + +Das Verstecken der Dokumentation macht es nur schwieriger zu verstehen, wie mit Ihrer API interagiert werden kann, und könnte es auch schwieriger machen, diese in der Produktion zu debuggen. Man könnte es einfach als eine Form von [Sicherheit durch Verschleierung](https://en.wikipedia.org/wiki/Security_through_obscurity) betrachten. + +Wenn Sie Ihre API sichern möchten, gibt es mehrere bessere Dinge, die Sie tun können, zum Beispiel: + +* Stellen Sie sicher, dass Sie über gut definierte Pydantic-Modelle für Ihre Requestbodys und Responses verfügen. +* Konfigurieren Sie alle erforderlichen Berechtigungen und Rollen mithilfe von Abhängigkeiten. +* Speichern Sie niemals Klartext-Passwörter, sondern nur Passwort-Hashes. +* Implementieren und verwenden Sie gängige kryptografische Tools wie pwdlib und JWT-Tokens, usw. +* Fügen Sie bei Bedarf detailliertere Berechtigungskontrollen mit OAuth2-Scopes hinzu. +* ... usw. + +Dennoch kann es sein, dass Sie einen ganz bestimmten Anwendungsfall haben, bei dem Sie die API-Dokumentation für eine bestimmte Umgebung (z. B. für die Produktion) oder abhängig von Konfigurationen aus Umgebungsvariablen wirklich deaktivieren müssen. + +## Bedingte OpenAPI aus Einstellungen und Umgebungsvariablen { #conditional-openapi-from-settings-and-env-vars } + +Sie können problemlos dieselben Pydantic-Einstellungen verwenden, um Ihre generierte OpenAPI und die Dokumentationsoberflächen zu konfigurieren. + +Zum Beispiel: + +{* ../../docs_src/conditional_openapi/tutorial001_py310.py hl[6,11] *} + +Hier deklarieren wir die Einstellung `openapi_url` mit dem gleichen Defaultwert `"/openapi.json"`. + +Und dann verwenden wir es beim Erstellen der `FastAPI`-App. + +Dann könnten Sie OpenAPI (einschließlich der Dokumentationsoberflächen) deaktivieren, indem Sie die Umgebungsvariable `OPENAPI_URL` auf einen leeren String setzen, wie zum Beispiel: + +
+ +```console +$ OPENAPI_URL= uvicorn main:app + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +Wenn Sie dann zu den URLs unter `/openapi.json`, `/docs` oder `/redoc` gehen, erhalten Sie lediglich einen `404 Not Found`-Fehler, wie: + +```JSON +{ + "detail": "Not Found" +} +``` diff --git a/docs/de/docs/how-to/configure-swagger-ui.md b/docs/de/docs/how-to/configure-swagger-ui.md new file mode 100644 index 0000000000000..d25062615672f --- /dev/null +++ b/docs/de/docs/how-to/configure-swagger-ui.md @@ -0,0 +1,70 @@ +# Swagger-Oberfläche konfigurieren { #configure-swagger-ui } + +Sie können einige zusätzliche [Parameter der Swagger-Oberfläche](https://swagger.io/docs/open-source-tools/swagger-ui/usage/configuration/) konfigurieren. + +Um diese zu konfigurieren, übergeben Sie das Argument `swagger_ui_parameters` beim Erstellen des `FastAPI()`-App-Objekts oder an die Funktion `get_swagger_ui_html()`. + +`swagger_ui_parameters` empfängt ein Dictionary mit den Konfigurationen, die direkt an die Swagger-Oberfläche übergeben werden. + +FastAPI konvertiert die Konfigurationen nach **JSON**, um diese mit JavaScript kompatibel zu machen, da die Swagger-Oberfläche das benötigt. + +## Syntaxhervorhebung deaktivieren { #disable-syntax-highlighting } + +Sie könnten beispielsweise die Syntaxhervorhebung in der Swagger-Oberfläche deaktivieren. + +Ohne Änderung der Einstellungen ist die Syntaxhervorhebung standardmäßig aktiviert: + + + +Sie können sie jedoch deaktivieren, indem Sie `syntaxHighlight` auf `False` setzen: + +{* ../../docs_src/configure_swagger_ui/tutorial001_py310.py hl[3] *} + +... und dann zeigt die Swagger-Oberfläche die Syntaxhervorhebung nicht mehr an: + + + +## Das Theme ändern { #change-the-theme } + +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_py310.py hl[3] *} + +Obige Konfiguration würde das Theme für die Farbe der Syntaxhervorhebung ändern: + + + +## Defaultparameter der Swagger-Oberfläche ändern { #change-default-swagger-ui-parameters } + +FastAPI enthält einige Defaultkonfigurationsparameter, die für die meisten Anwendungsfälle geeignet sind. + +Es umfasst die folgenden Defaultkonfigurationen: + +{* ../../fastapi/openapi/docs.py ln[9:24] hl[18:24] *} + +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: + +{* ../../docs_src/configure_swagger_ui/tutorial003_py310.py hl[3] *} + +## Andere Parameter der Swagger-Oberfläche { #other-swagger-ui-parameters } + +Um alle anderen möglichen Konfigurationen zu sehen, die Sie verwenden können, lesen Sie die offizielle [Dokumentation für die Parameter der Swagger-Oberfläche](https://swagger.io/docs/open-source-tools/swagger-ui/usage/configuration/). + +## Nur-JavaScript-Einstellungen { #javascript-only-settings } + +Die Swagger-Oberfläche erlaubt, dass andere Konfigurationen auch **Nur-JavaScript**-Objekte sein können (z. B. JavaScript-Funktionen). + +FastAPI umfasst auch diese Nur-JavaScript-`presets`-Einstellungen: + +```JavaScript +presets: [ + SwaggerUIBundle.presets.apis, + SwaggerUIBundle.SwaggerUIStandalonePreset +] +``` + +Dabei handelt es sich um **JavaScript**-Objekte, nicht um Strings, daher können Sie diese nicht direkt vom Python-Code aus übergeben. + +Wenn Sie solche Nur-JavaScript-Konfigurationen verwenden müssen, können Sie einen der früher genannten Wege verwenden. Überschreiben Sie die gesamte *Pfadoperation* der Swagger-Oberfläche und schreiben Sie manuell jedes benötigte JavaScript. diff --git a/docs/de/docs/how-to/custom-docs-ui-assets.md b/docs/de/docs/how-to/custom-docs-ui-assets.md new file mode 100644 index 0000000000000..c88b09d06d15c --- /dev/null +++ b/docs/de/docs/how-to/custom-docs-ui-assets.md @@ -0,0 +1,185 @@ +# Statische Assets der Dokumentationsoberfläche (Selbst-Hosting) { #custom-docs-ui-static-assets-self-hosting } + +Die API-Dokumentation verwendet **Swagger UI** und **ReDoc**, und jede dieser Dokumentationen benötigt einige JavaScript- und CSS-Dateien. + +Standardmäßig werden diese Dateien von einem CDN bereitgestellt. + +Es ist jedoch möglich, das anzupassen, ein bestimmtes CDN festzulegen oder die Dateien selbst bereitzustellen. + +## Benutzerdefiniertes CDN für JavaScript und CSS { #custom-cdn-for-javascript-and-css } + +Nehmen wir an, Sie möchten ein anderes CDN verwenden, zum Beispiel möchten Sie `https://unpkg.com/` verwenden. + +Das kann nützlich sein, wenn Sie beispielsweise in einem Land leben, in dem bestimmte URLs eingeschränkt sind. + +### Die automatische Dokumentation deaktivieren { #disable-the-automatic-docs } + +Der erste Schritt besteht darin, die automatische Dokumentation zu deaktivieren, da sie standardmäßig das Standard-CDN verwendet. + +Um sie zu deaktivieren, setzen Sie deren URLs beim Erstellen Ihrer `FastAPI`-App auf `None`: + +{* ../../docs_src/custom_docs_ui/tutorial001_py310.py hl[8] *} + +### Die benutzerdefinierte Dokumentation hinzufügen { #include-the-custom-docs } + +Jetzt können Sie die *Pfadoperationen* für die benutzerdefinierte Dokumentation erstellen. + +Sie können die internen Funktionen von FastAPI wiederverwenden, um die HTML-Seiten für die Dokumentation zu erstellen und ihnen die erforderlichen Argumente zu übergeben: + +* `openapi_url`: die URL, unter welcher die HTML-Seite für die Dokumentation das OpenAPI-Schema für Ihre API abrufen kann. Sie können hier das Attribut `app.openapi_url` verwenden. +* `title`: der Titel Ihrer API. +* `oauth2_redirect_url`: Sie können hier `app.swagger_ui_oauth2_redirect_url` verwenden, um die Standardeinstellung zu verwenden. +* `swagger_js_url`: die URL, unter welcher der HTML-Code für Ihre Swagger-UI-Dokumentation die **JavaScript**-Datei abrufen kann. Dies ist die benutzerdefinierte CDN-URL. +* `swagger_css_url`: die URL, unter welcher der HTML-Code für Ihre Swagger-UI-Dokumentation die **CSS**-Datei abrufen kann. Dies ist die benutzerdefinierte CDN-URL. + +Und ähnlich für ReDoc ... + +{* ../../docs_src/custom_docs_ui/tutorial001_py310.py hl[2:6,11:19,22:24,27:33] *} + +/// tip | Tipp + +Die *Pfadoperation* für `swagger_ui_redirect` ist ein Hilfsmittel bei der Verwendung von OAuth2. + +Wenn Sie Ihre API mit einem OAuth2-Anbieter integrieren, können Sie sich authentifizieren und mit den erworbenen Anmeldeinformationen zur API-Dokumentation zurückkehren. Und mit ihr interagieren, die echte OAuth2-Authentifizierung verwendend. + +Swagger UI erledigt das hinter den Kulissen für Sie, benötigt aber diesen „Umleitungs“-Helfer. + +/// + +### Eine *Pfadoperation* erstellen, um es zu testen { #create-a-path-operation-to-test-it } + +Um nun testen zu können, ob alles funktioniert, erstellen Sie eine *Pfadoperation*: + +{* ../../docs_src/custom_docs_ui/tutorial001_py310.py hl[36:38] *} + +### Es testen { #test-it } + +Jetzt sollten Sie in der Lage sein, zu Ihrer Dokumentation auf [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs) zu gehen und die Seite neu zu laden, die Assets werden nun vom neuen CDN geladen. + +## JavaScript und CSS für die Dokumentation selbst hosten { #self-hosting-javascript-and-css-for-docs } + +Das Selbst-Hosting von JavaScript und CSS kann nützlich sein, wenn Sie beispielsweise möchten, dass Ihre Anwendung auch offline, ohne bestehenden Internetzugang oder in einem lokalen Netzwerk weiter funktioniert. + +Hier erfahren Sie, wie Sie diese Dateien selbst in derselben FastAPI-App bereitstellen und die Dokumentation für deren Verwendung konfigurieren. + +### Projektdateistruktur { #project-file-structure } + +Nehmen wir an, die Dateistruktur Ihres Projekts sieht folgendermaßen aus: + +``` +. +├── app +│ ├── __init__.py +│ ├── main.py +``` + +Erstellen Sie jetzt ein Verzeichnis zum Speichern dieser statischen Dateien. + +Ihre neue Dateistruktur könnte so aussehen: + +``` +. +├── app +│   ├── __init__.py +│   ├── main.py +└── static/ +``` + +### Die Dateien herunterladen { #download-the-files } + +Laden Sie die für die Dokumentation benötigten statischen Dateien herunter und legen Sie diese im Verzeichnis `static/` ab. + +Sie können wahrscheinlich mit der rechten Maustaste auf jeden Link klicken und eine Option wie etwa „Link speichern unter ...“ auswählen. + +**Swagger UI** verwendet folgende Dateien: + +* [`swagger-ui-bundle.js`](https://cdn.jsdelivr.net/npm/swagger-ui-dist@5/swagger-ui-bundle.js) +* [`swagger-ui.css`](https://cdn.jsdelivr.net/npm/swagger-ui-dist@5/swagger-ui.css) + +Und **ReDoc** verwendet diese Datei: + +* [`redoc.standalone.js`](https://cdn.jsdelivr.net/npm/redoc@2/bundles/redoc.standalone.js) + +Danach könnte Ihre Dateistruktur wie folgt aussehen: + +``` +. +├── app +│   ├── __init__.py +│   ├── main.py +└── static + ├── redoc.standalone.js + ├── swagger-ui-bundle.js + └── swagger-ui.css +``` + +### Die statischen Dateien bereitstellen { #serve-the-static-files } + +* Importieren Sie `StaticFiles`. +* „Mounten“ Sie eine `StaticFiles()`-Instanz in einem bestimmten Pfad. + +{* ../../docs_src/custom_docs_ui/tutorial002_py310.py hl[7,11] *} + +### Die statischen Dateien testen { #test-the-static-files } + +Starten Sie Ihre Anwendung und gehen Sie auf [http://127.0.0.1:8000/static/redoc.standalone.js](http://127.0.0.1:8000/static/redoc.standalone.js). + +Sie sollten eine sehr lange JavaScript-Datei für **ReDoc** sehen. + +Sie könnte beginnen mit etwas wie: + +```JavaScript +/*! For license information please see redoc.standalone.js.LICENSE.txt */ +!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("null")): +... +``` + +Das zeigt, dass Sie statische Dateien aus Ihrer Anwendung bereitstellen können und dass Sie die statischen Dateien für die Dokumentation an der richtigen Stelle platziert haben. + +Jetzt können wir die Anwendung so konfigurieren, dass sie diese statischen Dateien für die Dokumentation verwendet. + +### Die automatische Dokumentation für statische Dateien deaktivieren { #disable-the-automatic-docs-for-static-files } + +Wie bei der Verwendung eines benutzerdefinierten CDN besteht der erste Schritt darin, die automatische Dokumentation zu deaktivieren, da sie standardmäßig das CDN verwendet. + +Um sie zu deaktivieren, setzen Sie deren URLs beim Erstellen Ihrer `FastAPI`-App auf `None`: + +{* ../../docs_src/custom_docs_ui/tutorial002_py310.py hl[9] *} + +### Die benutzerdefinierte Dokumentation für statische Dateien hinzufügen { #include-the-custom-docs-for-static-files } + +Und genau wie bei einem benutzerdefinierten CDN können Sie jetzt die *Pfadoperationen* für die benutzerdefinierte Dokumentation erstellen. + +Auch hier können Sie die internen Funktionen von FastAPI wiederverwenden, um die HTML-Seiten für die Dokumentation zu erstellen und ihnen die erforderlichen Argumente zu übergeben: + +* `openapi_url`: die URL, unter der die HTML-Seite für die Dokumentation das OpenAPI-Schema für Ihre API abrufen kann. Sie können hier das Attribut `app.openapi_url` verwenden. +* `title`: der Titel Ihrer API. +* `oauth2_redirect_url`: Sie können hier `app.swagger_ui_oauth2_redirect_url` verwenden, um die Standardeinstellung zu verwenden. +* `swagger_js_url`: die URL, unter welcher der HTML-Code für Ihre Swagger-UI-Dokumentation die **JavaScript**-Datei abrufen kann. **Das ist die, welche jetzt von Ihrer eigenen Anwendung bereitgestellt wird**. +* `swagger_css_url`: die URL, unter welcher der HTML-Code für Ihre Swagger-UI-Dokumentation die **CSS**-Datei abrufen kann. **Das ist die, welche jetzt von Ihrer eigenen Anwendung bereitgestellt wird**. + +Und ähnlich für ReDoc ... + +{* ../../docs_src/custom_docs_ui/tutorial002_py310.py hl[2:6,14:22,25:27,30:36] *} + +/// tip | Tipp + +Die *Pfadoperation* für `swagger_ui_redirect` ist ein Hilfsmittel bei der Verwendung von OAuth2. + +Wenn Sie Ihre API mit einem OAuth2-Anbieter integrieren, können Sie sich authentifizieren und mit den erworbenen Anmeldeinformationen zur API-Dokumentation zurückkehren. Und mit ihr interagieren, die echte OAuth2-Authentifizierung verwendend. + +Swagger UI erledigt das hinter den Kulissen für Sie, benötigt aber diesen „Umleitungs“-Helfer. + +/// + +### Eine *Pfadoperation* erstellen, um statische Dateien zu testen { #create-a-path-operation-to-test-static-files } + +Um nun testen zu können, ob alles funktioniert, erstellen Sie eine *Pfadoperation*: + +{* ../../docs_src/custom_docs_ui/tutorial002_py310.py hl[39:41] *} + +### Benutzeroberfläche mit statischen Dateien testen { #test-static-files-ui } + +Jetzt sollten Sie in der Lage sein, Ihr WLAN zu trennen, gehen Sie zu Ihrer Dokumentation unter [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs) und laden Sie die Seite neu. + +Und selbst ohne Internet können Sie die Dokumentation für Ihre API sehen und mit ihr interagieren. diff --git a/docs/de/docs/how-to/custom-request-and-route.md b/docs/de/docs/how-to/custom-request-and-route.md new file mode 100644 index 0000000000000..60fe71ed3cda0 --- /dev/null +++ b/docs/de/docs/how-to/custom-request-and-route.md @@ -0,0 +1,110 @@ +# Benutzerdefinierte Request- und APIRoute-Klasse { #custom-request-and-apiroute-class } + + +In einigen Fällen möchten Sie möglicherweise die von den Klassen `Request` und `APIRoute` verwendete Logik überschreiben. + +Das kann insbesondere eine gute Alternative zur Logik in einer Middleware sein. + +Wenn Sie beispielsweise den Requestbody lesen oder manipulieren möchten, bevor er von Ihrer Anwendung verarbeitet wird. + +/// danger | Gefahr + +Dies ist eine „fortgeschrittene“ Funktion. + +Wenn Sie gerade erst mit **FastAPI** beginnen, möchten Sie diesen Abschnitt vielleicht überspringen. + +/// + +## Anwendungsfälle { #use-cases } + +Einige Anwendungsfälle sind: + +* Konvertieren von Nicht-JSON-Requestbodys nach JSON (z. B. [`msgpack`](https://msgpack.org/index.html)). +* Dekomprimierung gzip-komprimierter Requestbodys. +* Automatisches Loggen aller Requestbodys. + +## Handhaben von benutzerdefinierten Requestbody-Kodierungen { #handling-custom-request-body-encodings } + +Sehen wir uns an, wie Sie eine benutzerdefinierte `Request`-Unterklasse verwenden, um gzip-Requests zu dekomprimieren. + +Und eine `APIRoute`-Unterklasse zur Verwendung dieser benutzerdefinierten Requestklasse. + +### Eine benutzerdefinierte `GzipRequest`-Klasse erstellen { #create-a-custom-gziprequest-class } + +/// tip | Tipp + +Dies ist nur ein einfaches Beispiel, um zu demonstrieren, wie es funktioniert. Wenn Sie Gzip-Unterstützung benötigen, können Sie die bereitgestellte [`GzipMiddleware`](../advanced/middleware.md#gzipmiddleware) verwenden. + +/// + +Zuerst erstellen wir eine `GzipRequest`-Klasse, welche die Methode `Request.body()` überschreibt, um den Body bei Vorhandensein eines entsprechenden Headers zu dekomprimieren. + +Wenn der Header kein `gzip` enthält, wird nicht versucht, den Body zu dekomprimieren. + +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] *} + +### Eine benutzerdefinierte `GzipRoute`-Klasse erstellen { #create-a-custom-gziproute-class } + +Als Nächstes erstellen wir eine benutzerdefinierte Unterklasse von `fastapi.routing.APIRoute`, welche `GzipRequest` nutzt. + +Dieses Mal wird die Methode `APIRoute.get_route_handler()` überschrieben. + +Diese Methode gibt eine Funktion zurück. Und diese Funktion empfängt einen Request und gibt eine Response zurück. + +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] *} + +/// note | Technische Details + +Ein `Request` hat ein `request.scope`-Attribut, welches einfach ein Python-`dict` ist, welches die mit dem Request verbundenen Metadaten enthält. + +Ein `Request` hat auch ein `request.receive`, welches eine Funktion ist, die den Body des Requests empfängt. + +Das `scope`-`dict` und die `receive`-Funktion sind beide Teil der ASGI-Spezifikation. + +Und diese beiden Dinge, `scope` und `receive`, werden benötigt, um eine neue `Request`-Instanz zu erstellen. + +Um mehr über den `Request` zu erfahren, schauen Sie sich [Starlettes Dokumentation zu Requests](https://www.starlette.dev/requests/) an. + +/// + +Das Einzige, was die von `GzipRequest.get_route_handler` zurückgegebene Funktion anders macht, ist die Konvertierung von `Request` in ein `GzipRequest`. + +Dabei kümmert sich unser `GzipRequest` um die Dekomprimierung der Daten (falls erforderlich), bevor diese an unsere *Pfadoperationen* weitergegeben werden. + +Danach ist die gesamte Verarbeitungslogik dieselbe. + +Aufgrund unserer Änderungen in `GzipRequest.body` wird der Requestbody jedoch bei Bedarf automatisch dekomprimiert, wenn er von **FastAPI** geladen wird. + +## Zugriff auf den Requestbody in einem Exceptionhandler { #accessing-the-request-body-in-an-exception-handler } + +/// tip | Tipp + +Um dasselbe Problem zu lösen, ist es wahrscheinlich viel einfacher, den `body` in einem benutzerdefinierten Handler für `RequestValidationError` zu verwenden ([Fehlerbehandlung](../tutorial/handling-errors.md#use-the-requestvalidationerror-body)). + +Dieses Beispiel ist jedoch immer noch gültig und zeigt, wie mit den internen Komponenten interagiert wird. + +/// + +Wir können denselben Ansatz auch verwenden, um in einem Exceptionhandler auf den Requestbody zuzugreifen. + +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] *} + +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] *} + +## Benutzerdefinierte `APIRoute`-Klasse in einem Router { #custom-apiroute-class-in-a-router } + +Sie können auch den Parameter `route_class` eines `APIRouter` festlegen: + +{* ../../docs_src/custom_request_and_route/tutorial003_py310.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: + +{* ../../docs_src/custom_request_and_route/tutorial003_py310.py hl[13:20] *} diff --git a/docs/de/docs/how-to/extending-openapi.md b/docs/de/docs/how-to/extending-openapi.md new file mode 100644 index 0000000000000..23824117edec0 --- /dev/null +++ b/docs/de/docs/how-to/extending-openapi.md @@ -0,0 +1,88 @@ +# OpenAPI erweitern { #extending-openapi } + +Es gibt einige Fälle, in denen Sie das generierte OpenAPI-Schema ändern müssen. + +In diesem Abschnitt erfahren Sie, wie. + +## Der normale Vorgang { #the-normal-process } + +Der normale (Standard-)Prozess ist wie folgt. + +Eine `FastAPI`-Anwendung (Instanz) verfügt über eine `.openapi()`-Methode, von der erwartet wird, dass sie das OpenAPI-Schema zurückgibt. + +Als Teil der Erstellung des Anwendungsobjekts wird eine *Pfadoperation* für `/openapi.json` (oder welcher Wert für den Parameter `openapi_url` gesetzt wurde) registriert. + +Diese gibt lediglich eine JSON-Response zurück, mit dem Ergebnis der Methode `.openapi()` der Anwendung. + +Standardmäßig überprüft die Methode `.openapi()` die Eigenschaft `.openapi_schema`, um zu sehen, ob diese Inhalt hat, und gibt diesen zurück. + +Ist das nicht der Fall, wird der Inhalt mithilfe der Hilfsfunktion unter `fastapi.openapi.utils.get_openapi` generiert. + +Diese Funktion `get_openapi()` erhält als Parameter: + +* `title`: Der OpenAPI-Titel, der in der Dokumentation angezeigt wird. +* `version`: Die Version Ihrer API, z. B. `2.5.0`. +* `openapi_version`: Die Version der verwendeten OpenAPI-Spezifikation. Standardmäßig die neueste Version: `3.1.0`. +* `summary`: Eine kurze Zusammenfassung der API. +* `description`: Die Beschreibung Ihrer API. Dies kann Markdown enthalten und wird in der Dokumentation angezeigt. +* `routes`: Die Routen der Anwendung, entnommen aus `app.routes`. FastAPI nutzt sie, um die registrierten *Pfadoperationen* zu sammeln, einschließlich derer aus eingebundenen Routern. + +/// tip | Technische Details + +`app.routes` ist eine Routenstruktur auf niedrigerer Ebene. Sie kann Routenkandidaten enthalten, die FastAPI intern für eingebundene Router verwendet, nicht nur endgültige `APIRoute`-Objekte. + +Sie können dennoch `app.routes` an `get_openapi()` übergeben. FastAPI durchläuft diesen Routenbaum, um die tatsächlich wirksamen Pfadoperationen zu sammeln. + +/// + +/// note | Hinweis + +Der Parameter `summary` ist in OpenAPI 3.1.0 und höher verfügbar und wird von FastAPI 0.99.0 und höher unterstützt. + +/// + +## Überschreiben der Standardeinstellungen { #overriding-the-defaults } + +Mithilfe der oben genannten Informationen können Sie dieselbe Hilfsfunktion verwenden, um das OpenAPI-Schema zu generieren und jeden benötigten Teil zu überschreiben. + +Fügen wir beispielsweise [ReDocs OpenAPI-Erweiterung zum Einbinden eines benutzerdefinierten Logos](https://github.com/Rebilly/ReDoc/blob/master/docs/redoc-vendor-extensions.md#x-logo) hinzu. + +### Normales **FastAPI** { #normal-fastapi } + +Schreiben Sie zunächst wie gewohnt Ihre ganze **FastAPI**-Anwendung: + +{* ../../docs_src/extending_openapi/tutorial001_py310.py hl[1,4,7:9] *} + +### Das OpenAPI-Schema generieren { #generate-the-openapi-schema } + +Verwenden Sie dann dieselbe Hilfsfunktion, um das OpenAPI-Schema innerhalb einer `custom_openapi()`-Funktion zu generieren: + +{* ../../docs_src/extending_openapi/tutorial001_py310.py hl[2,15:21] *} + +### 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: + +{* ../../docs_src/extending_openapi/tutorial001_py310.py hl[22:24] *} + +### Zwischenspeichern des OpenAPI-Schemas { #cache-the-openapi-schema } + +Sie können die Eigenschaft `.openapi_schema` als „Cache“ verwenden, um Ihr generiertes Schema zu speichern. + +Auf diese Weise muss Ihre Anwendung das Schema nicht jedes Mal generieren, wenn ein Benutzer Ihre API-Dokumentation öffnet. + +Es wird nur einmal generiert und dann wird dasselbe zwischengespeicherte Schema für die nächsten Requests verwendet. + +{* ../../docs_src/extending_openapi/tutorial001_py310.py hl[13:14,25:26] *} + +### Die Methode überschreiben { #override-the-method } + +Jetzt können Sie die Methode `.openapi()` durch Ihre neue Funktion ersetzen. + +{* ../../docs_src/extending_openapi/tutorial001_py310.py hl[29] *} + +### Es testen { #check-it } + +Sobald Sie auf [http://127.0.0.1:8000/redoc](http://127.0.0.1:8000/redoc) gehen, werden Sie sehen, dass Ihr benutzerdefiniertes Logo verwendet wird (in diesem Beispiel das Logo von **FastAPI**): + + diff --git a/docs/de/docs/how-to/general.md b/docs/de/docs/how-to/general.md new file mode 100644 index 0000000000000..593b79d3b4222 --- /dev/null +++ b/docs/de/docs/how-to/general.md @@ -0,0 +1,43 @@ +# Allgemeines – How-To – Rezepte { #general-how-to-recipes } + +Hier finden Sie mehrere Verweise auf andere Stellen in der Dokumentation, für allgemeine oder häufige Fragen. + +## Daten filtern – Sicherheit { #filter-data-security } + +Um sicherzustellen, dass Sie nicht mehr Daten zurückgeben, als Sie sollten, lesen Sie die Dokumentation unter [Tutorial – Responsemodell – Rückgabetyp](../tutorial/response-model.md). + +## Response-Leistung optimieren – Responsemodell – Rückgabetyp { #optimize-response-performance-response-model-return-type } + +Um die Leistung beim Zurückgeben von JSON-Daten zu optimieren, verwenden Sie einen Rückgabetyp oder ein Responsemodell. So übernimmt Pydantic die Serialisierung zu JSON auf der Rust-Seite, ohne den Umweg über Python. Mehr dazu in der Dokumentation unter [Tutorial – Responsemodell – Rückgabetyp](../tutorial/response-model.md). + +## Dokumentations-Tags – OpenAPI { #documentation-tags-openapi } + +Um Tags zu Ihren *Pfadoperationen* hinzuzufügen und diese in der Oberfläche der Dokumentation zu gruppieren, lesen Sie die Dokumentation unter [Tutorial – Pfadoperation-Konfiguration – Tags](../tutorial/path-operation-configuration.md#tags). + +## Zusammenfassung und Beschreibung in der Dokumentation – OpenAPI { #documentation-summary-and-description-openapi } + +Um Ihren *Pfadoperationen* eine Zusammenfassung und Beschreibung hinzuzufügen und diese in der Oberfläche der Dokumentation anzuzeigen, lesen Sie die Dokumentation unter [Tutorial – Pfadoperation-Konfiguration – Zusammenfassung und Beschreibung](../tutorial/path-operation-configuration.md#summary-and-description). + +## Beschreibung der Response in der Dokumentation – OpenAPI { #documentation-response-description-openapi } + +Um die Beschreibung der Response zu definieren, welche in der Oberfläche der Dokumentation angezeigt wird, lesen Sie die Dokumentation unter [Tutorial – Pfadoperation-Konfiguration – Beschreibung der Response](../tutorial/path-operation-configuration.md#response-description). + +## *Pfadoperation* in der Dokumentation deprecaten – OpenAPI { #documentation-deprecate-a-path-operation-openapi } + +Um eine *Pfadoperation* zu deprecaten und das in der Oberfläche der Dokumentation anzuzeigen, lesen Sie die Dokumentation unter [Tutorial – Pfadoperation-Konfiguration – Deprecaten](../tutorial/path-operation-configuration.md#deprecate-a-path-operation). + +## Daten in etwas JSON-kompatibles konvertieren { #convert-any-data-to-json-compatible } + +Um Daten in etwas JSON-kompatibles zu konvertieren, lesen Sie die Dokumentation unter [Tutorial – JSON-kompatibler Encoder](../tutorial/encoder.md). + +## OpenAPI-Metadaten – Dokumentation { #openapi-metadata-docs } + +Um Metadaten zu Ihrem OpenAPI-Schema hinzuzufügen, einschließlich einer Lizenz, Version, Kontakt, usw., lesen Sie die Dokumentation unter [Tutorial – Metadaten und URLs der Dokumentation](../tutorial/metadata.md). + +## Benutzerdefinierte OpenAPI-URL { #openapi-custom-url } + +Um die OpenAPI-URL anzupassen (oder zu entfernen), lesen Sie die Dokumentation unter [Tutorial – Metadaten und URLs der Dokumentation](../tutorial/metadata.md#openapi-url). + +## URLs der OpenAPI-Dokumentationen { #openapi-docs-urls } + +Um die URLs zu aktualisieren, die für die automatisch generierten Dokumentations-Oberflächen verwendet werden, lesen Sie die Dokumentation unter [Tutorial – Metadaten und URLs der Dokumentation](../tutorial/metadata.md#docs-urls). diff --git a/docs/de/docs/how-to/graphql.md b/docs/de/docs/how-to/graphql.md new file mode 100644 index 0000000000000..cb1891b633fb1 --- /dev/null +++ b/docs/de/docs/how-to/graphql.md @@ -0,0 +1,61 @@ +# GraphQL { #graphql } + + +Da **FastAPI** auf dem **ASGI**-Standard basiert, ist es sehr einfach, jede **GraphQL**-Bibliothek zu integrieren, die auch mit ASGI kompatibel ist. + +Sie können normale FastAPI-*Pfadoperationen* mit GraphQL in derselben Anwendung kombinieren. + +/// tip | Tipp + +**GraphQL** löst einige sehr spezifische Anwendungsfälle. + +Es hat **Vorteile** und **Nachteile** im Vergleich zu gängigen **Web-APIs**. + +Stellen Sie sicher, dass Sie prüfen, ob die **Vorteile** für Ihren Anwendungsfall die **Nachteile** ausgleichen. 🤓 + +/// + +## GraphQL-Bibliotheken { #graphql-libraries } + +Hier sind einige der **GraphQL**-Bibliotheken, die **ASGI**-Unterstützung haben. Sie könnten sie mit **FastAPI** verwenden: + +* [Strawberry](https://strawberry.rocks/) 🍓 + * Mit [Dokumentation für FastAPI](https://strawberry.rocks/docs/integrations/fastapi) +* [Ariadne](https://ariadnegraphql.org/) + * Mit [Dokumentation für FastAPI](https://ariadnegraphql.org/docs/fastapi-integration) +* [Tartiflette](https://tartiflette.io/) + * Mit [Tartiflette ASGI](https://tartiflette.github.io/tartiflette-asgi/) für ASGI-Integration +* [Graphene](https://graphene-python.org/) + * Mit [starlette-graphene3](https://github.com/ciscorn/starlette-graphene3) + +## GraphQL mit Strawberry { #graphql-with-strawberry } + +Wenn Sie mit **GraphQL** arbeiten möchten oder müssen, ist [**Strawberry**](https://strawberry.rocks/) die **empfohlene** Bibliothek, da deren Design **FastAPIs** Design am nächsten kommt und alles auf **Typannotationen** basiert. + +Abhängig von Ihrem Anwendungsfall könnten Sie eine andere Bibliothek vorziehen, aber wenn Sie mich fragen würden, würde ich Ihnen wahrscheinlich empfehlen, **Strawberry** auszuprobieren. + +Hier ist eine kleine Vorschau, wie Sie Strawberry mit FastAPI integrieren können: + +{* ../../docs_src/graphql_/tutorial001_py310.py hl[3,22,25] *} + +Weitere Informationen zu Strawberry finden Sie in der [Strawberry-Dokumentation](https://strawberry.rocks/). + +Und auch in der Dokumentation zu [Strawberry mit FastAPI](https://strawberry.rocks/docs/integrations/fastapi). + +## Ältere `GraphQLApp` von Starlette { #older-graphqlapp-from-starlette } + +Frühere Versionen von Starlette enthielten eine `GraphQLApp`-Klasse zur Integration mit [Graphene](https://graphene-python.org/). + +Das wurde von Starlette deprecatet, aber wenn Sie Code haben, der das verwendet, können Sie einfach zu [starlette-graphene3](https://github.com/ciscorn/starlette-graphene3) **migrieren**, das denselben Anwendungsfall abdeckt und eine **fast identische Schnittstelle** hat. + +/// tip | Tipp + +Wenn Sie GraphQL benötigen, würde ich Ihnen trotzdem empfehlen, sich [Strawberry](https://strawberry.rocks/) anzuschauen, da es auf Typannotationen basiert, statt auf benutzerdefinierten Klassen und Typen. + +/// + +## Mehr darüber lernen { #learn-more } + +Weitere Informationen zu **GraphQL** finden Sie in der [offiziellen GraphQL-Dokumentation](https://graphql.org/). + +Sie können auch mehr über jede der oben beschriebenen Bibliotheken in den jeweiligen Links lesen. diff --git a/docs/de/docs/how-to/index.md b/docs/de/docs/how-to/index.md new file mode 100644 index 0000000000000..c46bbfbdce183 --- /dev/null +++ b/docs/de/docs/how-to/index.md @@ -0,0 +1,13 @@ +# How-To – Rezepte { #how-to-recipes } + +Hier finden Sie verschiedene Rezepte und „How-To“-Anleitungen zu **verschiedenen Themen**. + +Die meisten dieser Ideen sind mehr oder weniger **unabhängig**, und in den meisten Fällen müssen Sie diese nur studieren, wenn sie direkt auf **Ihr Projekt** anwendbar sind. + +Wenn etwas für Ihr Projekt interessant und nützlich erscheint, lesen Sie es, andernfalls überspringen Sie es einfach. + +/// tip | Tipp + +Wenn Sie strukturiert **FastAPI lernen** möchten (empfohlen), lesen Sie stattdessen Kapitel für Kapitel das [Tutorial – Benutzerhandbuch](../tutorial/index.md). + +/// diff --git a/docs/de/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md b/docs/de/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md new file mode 100644 index 0000000000000..5ea3b9561e214 --- /dev/null +++ b/docs/de/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md @@ -0,0 +1,153 @@ +# Von Pydantic v1 zu Pydantic v2 migrieren { #migrate-from-pydantic-v1-to-pydantic-v2 } + +Wenn Sie eine ältere FastAPI-App haben, nutzen Sie möglicherweise Pydantic Version 1. + +FastAPI Version 0.100.0 unterstützte sowohl Pydantic v1 als auch v2. Es verwendete, was auch immer Sie installiert hatten. + +FastAPI Version 0.119.0 führte eine teilweise Unterstützung für Pydantic v1 innerhalb von Pydantic v2 (als `pydantic.v1`) ein, um die Migration zu v2 zu erleichtern. + +FastAPI 0.126.0 entfernte die Unterstützung für Pydantic v1, während `pydantic.v1` noch eine Weile unterstützt wurde. + +FastAPI 0.128.0 entfernte ebenfalls die Unterstützung für `pydantic.v1`, daher erfordern die neuesten Versionen von FastAPI Pydantic v2. + +/// warning | Achtung + +Das Pydantic-Team hat die Unterstützung für Pydantic v1 in den neuesten Python-Versionen eingestellt, beginnend mit **Python 3.14**. + +Dies schließt `pydantic.v1` ein, das unter Python 3.14 und höher nicht mehr unterstützt wird. + +Wenn Sie die neuesten Features von Python nutzen möchten, müssen Sie sicherstellen, dass Sie Pydantic v2 verwenden. + +/// + +Wenn Sie eine ältere FastAPI-App mit Pydantic v1 haben, zeige ich Ihnen hier, wie Sie sie zu Pydantic v2 migrieren, und die **Features in FastAPI 0.119.0**, die Ihnen bei einer schrittweisen Migration helfen. + +## Offizieller Leitfaden { #official-guide } + +Pydantic hat einen offiziellen [Migrationsleitfaden](https://docs.pydantic.dev/latest/migration/) von v1 zu v2. + +Er enthält auch, was sich geändert hat, wie Validierungen nun korrekter und strikter sind, mögliche Stolpersteine, usw. + +Sie können ihn lesen, um besser zu verstehen, was sich geändert hat. + +## Tests { #tests } + +Stellen Sie sicher, dass Sie [Tests](../tutorial/testing.md) für Ihre App haben und diese in Continuous Integration (CI) ausführen. + +Auf diese Weise können Sie das Update durchführen und sicherstellen, dass weiterhin alles wie erwartet funktioniert. + +## `bump-pydantic` { #bump-pydantic } + +In vielen Fällen, wenn Sie reguläre Pydantic-Modelle ohne Anpassungen verwenden, können Sie den Großteil des Prozesses der Migration von Pydantic v1 auf Pydantic v2 automatisieren. + +Sie können [`bump-pydantic`](https://github.com/pydantic/bump-pydantic) vom selben Pydantic-Team verwenden. + +Dieses Tool hilft Ihnen, den Großteil des zu ändernden Codes automatisch anzupassen. + +Danach können Sie die Tests ausführen und prüfen, ob alles funktioniert. Falls ja, sind Sie fertig. 😎 + +## Pydantic v1 in v2 { #pydantic-v1-in-v2 } + +Pydantic v2 enthält alles aus Pydantic v1 als Untermodul `pydantic.v1`. Dies wird aber in Versionen oberhalb von Python 3.13 nicht mehr unterstützt. + +Das bedeutet, Sie können die neueste Version von Pydantic v2 installieren und die alten Pydantic‑v1‑Komponenten aus diesem Untermodul importieren und verwenden, als hätten Sie das alte Pydantic v1 installiert. + +{* ../../docs_src/pydantic_v1_in_v2/tutorial001_an_py310.py hl[1,4] *} + +### FastAPI-Unterstützung für Pydantic v1 in v2 { #fastapi-support-for-pydantic-v1-in-v2 } + +/// warning | Achtung + +Diese FastAPI-Unterstützung für `pydantic.v1`-Modelle wurde in **FastAPI 0.119.0** hinzugefügt und in **FastAPI 0.128.0** entfernt. Sie war als temporäre Hilfe für die Migration zu Pydantic v2 gedacht. + +In aktuellen Versionen von FastAPI löst die Verwendung eines `pydantic.v1`-Modells in Ihrer App einen Fehler aus. + +Der Rest dieses Abschnitts beschreibt die temporäre Unterstützung, die nur in diesen älteren Versionen verfügbar ist. + +/// + +Seit FastAPI 0.119.0 gibt es außerdem eine teilweise Unterstützung für Pydantic v1 innerhalb von Pydantic v2, um die Migration auf v2 zu erleichtern. + +Sie könnten also Pydantic auf die neueste Version 2 aktualisieren und die Importe so ändern, dass das Untermodul `pydantic.v1` verwendet wird, und in vielen Fällen würde es einfach funktionieren. + +{* ../../docs_src/pydantic_v1_in_v2/tutorial002_an_py310.py hl[2,5,15] *} + +/// warning | Achtung + +Beachten Sie, dass, da das Pydantic‑Team Pydantic v1 in neueren Python‑Versionen nicht mehr unterstützt, beginnend mit Python 3.14, auch die Verwendung von `pydantic.v1` unter Python 3.14 und höher nicht unterstützt wird. + +/// + +### Pydantic v1 und v2 in derselben App { #pydantic-v1-and-v2-on-the-same-app } + +Es wird von Pydantic **nicht unterstützt**, dass ein Pydantic‑v2‑Modell Felder hat, die als Pydantic‑v1‑Modelle definiert sind, und umgekehrt. + +```mermaid +graph TB + subgraph "❌ Nicht unterstützt" + direction TB + subgraph V2["Pydantic-v2-Modell"] + V1Field["Pydantic-v1-Modell"] + end + subgraph V1["Pydantic-v1-Modell"] + V2Field["Pydantic-v2-Modell"] + end + end + + style V2 fill:#f9fff3 + style V1 fill:#fff6f0 + style V1Field fill:#fff6f0 + style V2Field fill:#f9fff3 +``` + +... aber Sie können getrennte Modelle, die Pydantic v1 bzw. v2 nutzen, in derselben App verwenden. + +```mermaid +graph TB + subgraph "✅ Unterstützt" + direction TB + subgraph V2["Pydantic-v2-Modell"] + V2Field["Pydantic-v2-Modell"] + end + subgraph V1["Pydantic-v1-Modell"] + V1Field["Pydantic-v1-Modell"] + end + end + + style V2 fill:#f9fff3 + style V1 fill:#fff6f0 + style V1Field fill:#fff6f0 + style V2Field fill:#f9fff3 +``` + +In einigen Fällen ist es sogar möglich, sowohl Pydantic‑v1‑ als auch Pydantic‑v2‑Modelle in derselben **Pfadoperation** Ihrer FastAPI‑App zu verwenden: + +{* ../../docs_src/pydantic_v1_in_v2/tutorial003_an_py310.py hl[2:3,6,12,21:22] *} + +Im obigen Beispiel ist das Eingabemodell ein Pydantic‑v1‑Modell, und das Ausgabemodell (definiert in `response_model=ItemV2`) ist ein Pydantic‑v2‑Modell. + +### Pydantic v1 Parameter { #pydantic-v1-parameters } + +Wenn Sie einige der FastAPI-spezifischen Tools für Parameter wie `Body`, `Query`, `Form`, usw. zusammen mit Pydantic‑v1‑Modellen verwenden müssen, können Sie die aus `fastapi.temp_pydantic_v1_params` importieren, während Sie die Migration zu Pydantic v2 abschließen: + +{* ../../docs_src/pydantic_v1_in_v2/tutorial004_an_py310.py hl[4,18] *} + +### In Schritten migrieren { #migrate-in-steps } + +/// warning | Achtung + +Die unten beschriebene schrittweise Migration mit sowohl Pydantic‑v1‑ als auch Pydantic‑v2‑Modellen in derselben App funktioniert nur in **FastAPI 0.119.0 bis 0.127.x**. Sie wurde in **FastAPI 0.128.0** entfernt, die neuesten Versionen erfordern **Pydantic‑v2**-Modelle. + +/// + +/// tip | Tipp + +Probieren Sie zuerst `bump-pydantic` aus. Wenn Ihre Tests erfolgreich sind und das funktioniert, sind Sie mit einem einzigen Befehl fertig. ✨ + +/// + +Wenn `bump-pydantic` für Ihren Anwendungsfall nicht funktioniert, können Sie die Unterstützung für Pydantic‑v1‑ und Pydantic‑v2‑Modelle in derselben App nutzen, um die Migration zu Pydantic v2 schrittweise durchzuführen. + +Sie könnten zuerst Pydantic auf die neueste Version 2 aktualisieren und die Importe so ändern, dass für all Ihre Modelle `pydantic.v1` verwendet wird. + +Anschließend können Sie beginnen, Ihre Modelle gruppenweise von Pydantic v1 auf v2 zu migrieren – in kleinen, schrittweisen Etappen. 🚶 diff --git a/docs/de/docs/how-to/separate-openapi-schemas.md b/docs/de/docs/how-to/separate-openapi-schemas.md new file mode 100644 index 0000000000000..ae1df61765bb3 --- /dev/null +++ b/docs/de/docs/how-to/separate-openapi-schemas.md @@ -0,0 +1,103 @@ +# Separate OpenAPI-Schemas für Eingabe und Ausgabe oder nicht { #separate-openapi-schemas-for-input-and-output-or-not } + + +Seit der Veröffentlichung von **Pydantic v2** ist die generierte OpenAPI etwas genauer und **korrekter** als zuvor. 😎 + +Tatsächlich gibt es in einigen Fällen sogar **zwei JSON-Schemas** in OpenAPI für dasselbe Pydantic-Modell, für Eingabe und Ausgabe, je nachdem, ob sie **Defaultwerte** haben. + +Sehen wir uns an, wie das funktioniert und wie Sie es bei Bedarf ändern können. + +## Pydantic-Modelle für Eingabe und Ausgabe { #pydantic-models-for-input-and-output } + +Nehmen wir an, Sie haben ein Pydantic-Modell mit Defaultwerten wie dieses: + +{* ../../docs_src/separate_openapi_schemas/tutorial001_py310.py ln[1:7] hl[7] *} + +### Modell für Eingabe { #model-for-input } + +Wenn Sie dieses Modell wie hier als Eingabe verwenden: + +{* ../../docs_src/separate_openapi_schemas/tutorial001_py310.py ln[1:15] hl[14] *} + +... dann ist das Feld `description` **nicht erforderlich**. Weil es den Defaultwert `None` hat. + +### Eingabemodell in der Dokumentation { #input-model-in-docs } + +Sie können überprüfen, dass das Feld `description` in der Dokumentation kein **rotes Sternchen** enthält, es ist nicht als erforderlich markiert: + +
+ +
+ +### Modell für die Ausgabe { #model-for-output } + +Wenn Sie jedoch dasselbe Modell als Ausgabe verwenden, wie hier: + +{* ../../docs_src/separate_openapi_schemas/tutorial001_py310.py hl[19] *} + +... dann, weil `description` einen Defaultwert hat, wird es, wenn Sie für dieses Feld **nichts zurückgeben**, immer noch diesen **Defaultwert** haben. + +### Modell für Ausgabe-Responsedaten { #model-for-output-response-data } + +Wenn Sie mit der Dokumentation interagieren und die Response überprüfen, enthält die JSON-Response den Defaultwert (`null`), obwohl der Code nichts in eines der `description`-Felder geschrieben hat: + +
+ +
+ +Das bedeutet, dass es **immer einen Wert** hat, der Wert kann jedoch manchmal `None` sein (oder `null` in JSON). + +Das bedeutet, dass Clients, die Ihre API verwenden, nicht prüfen müssen, ob der Wert vorhanden ist oder nicht. Sie können davon ausgehen, dass das Feld immer vorhanden ist. In einigen Fällen hat es jedoch nur den Defaultwert `None`. + +Um dies in OpenAPI zu kennzeichnen, markieren Sie dieses Feld als **erforderlich**, da es immer vorhanden sein wird. + +Aus diesem Grund kann das JSON-Schema für ein Modell unterschiedlich sein, je nachdem, ob es für **Eingabe oder Ausgabe** verwendet wird: + +* für die **Eingabe** ist `description` **nicht erforderlich** +* für die **Ausgabe** ist es **erforderlich** (und möglicherweise `None` oder, in JSON-Begriffen, `null`) + +### Ausgabemodell in der Dokumentation { #model-for-output-in-docs } + +Sie können das Ausgabemodell auch in der Dokumentation überprüfen. **Sowohl** `name` **als auch** `description` sind mit einem **roten Sternchen** als **erforderlich** markiert: + +
+ +
+ +### Eingabe- und Ausgabemodell in der Dokumentation { #model-for-input-and-output-in-docs } + +Und wenn Sie alle verfügbaren Schemas (JSON-Schemas) in OpenAPI überprüfen, werden Sie feststellen, dass es zwei gibt, ein `Item-Input` und ein `Item-Output`. + +Für `Item-Input` ist `description` **nicht erforderlich**, es hat kein rotes Sternchen. + +Aber für `Item-Output` ist `description` **erforderlich**, es hat ein rotes Sternchen. + +
+ +
+ +Mit dieser Funktion von **Pydantic v2** ist Ihre API-Dokumentation **präziser**, und wenn Sie über automatisch generierte Clients und SDKs verfügen, sind diese auch präziser, mit einer besseren **Entwicklererfahrung** und Konsistenz. 🎉 + +## Schemas nicht trennen { #do-not-separate-schemas } + +Nun gibt es einige Fälle, in denen Sie möglicherweise **dasselbe Schema für Eingabe und Ausgabe** haben möchten. + +Der Hauptanwendungsfall hierfür besteht wahrscheinlich darin, dass Sie das mal tun möchten, wenn Sie bereits über einige automatisch generierte Client-Codes/SDKs verfügen und im Moment nicht alle automatisch generierten Client-Codes/SDKs aktualisieren möchten, möglicherweise später, aber nicht jetzt. + +In diesem Fall können Sie diese Funktion in **FastAPI** mit dem Parameter `separate_input_output_schemas=False` deaktivieren. + +/// note | Hinweis + +Unterstützung für `separate_input_output_schemas` wurde in FastAPI `0.102.0` hinzugefügt. 🤓 + +/// + +{* ../../docs_src/separate_openapi_schemas/tutorial002_py310.py hl[10] *} + +### Gleiches Schema für Eingabe- und Ausgabemodelle in der Dokumentation { #same-schema-for-input-and-output-models-in-docs } + +Und jetzt wird es ein einziges Schema für die Eingabe und Ausgabe des Modells geben, nur `Item`, und es wird `description` als **nicht erforderlich** kennzeichnen: + +
+ +
diff --git a/docs/de/docs/how-to/testing-database.md b/docs/de/docs/how-to/testing-database.md new file mode 100644 index 0000000000000..e011f54779380 --- /dev/null +++ b/docs/de/docs/how-to/testing-database.md @@ -0,0 +1,7 @@ +# Eine Datenbank testen { #testing-a-database } + +Sie können sich über Datenbanken, SQL und SQLModel in der [SQLModel-Dokumentation](https://sqlmodel.tiangolo.com/) informieren. 🤓 + +Es gibt ein kurzes [Tutorial zur Verwendung von SQLModel mit FastAPI](https://sqlmodel.tiangolo.com/tutorial/fastapi/). ✨ + +Dieses Tutorial enthält einen Abschnitt über das [Testen von SQL-Datenbanken](https://sqlmodel.tiangolo.com/tutorial/fastapi/tests/). 😎 diff --git a/docs/de/docs/index.md b/docs/de/docs/index.md new file mode 100644 index 0000000000000..9922e76218072 --- /dev/null +++ b/docs/de/docs/index.md @@ -0,0 +1,585 @@ +--- +include_yaml: + sponsors: data/sponsors.yml +--- + +# FastAPI { #fastapi } + + + +

+ FastAPI +

+

+ FastAPI-Framework, hohe Performanz, leicht zu lernen, schnell zu entwickeln, produktionsreif +

+

+ + Test + + + Testabdeckung + + + Package-Version + + + Unterstützte Python-Versionen + +

+ +--- + +**Dokumentation**: [https://fastapi.tiangolo.com/de](https://fastapi.tiangolo.com/de) + +**Quellcode**: [https://github.com/fastapi/fastapi](https://github.com/fastapi/fastapi) + +--- + +FastAPI ist ein modernes, schnelles (hoch performantes) Webframework zur Erstellung von APIs mit Python auf Basis von Standard-Python-Typhinweisen. + +Seine Schlüssel-Merkmale sind: + +* **Schnell**: Sehr hohe Performanz, auf Augenhöhe mit **NodeJS** und **Go** (dank Starlette und Pydantic). [Eines der schnellsten verfügbaren Python-Frameworks](#performance). +* **Schnell zu entwickeln**: Erhöhen Sie die Geschwindigkeit bei der Entwicklung von Features um etwa 200 % bis 300 %. * +* **Weniger Bugs**: Verringern Sie die von Menschen (Entwicklern) verursachten Fehler um etwa 40 %. * +* **Intuitiv**: Hervorragende Editor-Unterstützung. Code-Vervollständigung überall. Weniger Zeit mit Debuggen verbringen. +* **Einfach**: So konzipiert, dass es einfach zu benutzen und zu erlernen ist. Weniger Zeit mit dem Lesen von Dokumentation verbringen. +* **Kurz**: Minimieren Sie die Verdoppelung von Code. Mehrere Features aus jeder Parameterdeklaration. Weniger Bugs. +* **Robust**: Erhalten Sie produktionsreifen Code. Mit automatischer, interaktiver Dokumentation. +* **Standards-basiert**: Basierend auf (und vollständig kompatibel mit) den offenen Standards für APIs: [OpenAPI](https://github.com/OAI/OpenAPI-Specification) (früher bekannt als Swagger) und [JSON Schema](https://json-schema.org/). + +* Schätzung basierend auf Tests, die von einem internen Entwicklungsteam durchgeführt wurden, das Produktionsanwendungen erstellt. + +## Sponsoren { #sponsors } + + + +### Keystone-Sponsor { #keystone-sponsor } + +
+{% for sponsor in sponsors.keystone -%} +{{ sponsor.title }} +{% endfor -%} +
+ +### Gold-Sponsoren { #gold-sponsors } + +
+{% for sponsor in sponsors.gold -%} +{{ sponsor.title }} +{% endfor -%} +
+ +### Silber-Sponsoren { #silver-sponsors } + +
+{% for sponsor in sponsors.silver -%} +{{ sponsor.title }} +{% endfor %} +
+ + + +[Andere Sponsoren](https://fastapi.tiangolo.com/de/fastapi-people/#sponsors) + +## Meinungen { #opinions } + + +
+
+ + + + +
+ +
+
„Ich verwende FastAPI heutzutage sehr oft. Ich plane tatsächlich, es für alle ML-Services meines Teams bei Microsoft zu verwenden. Einige davon werden in das Kernprodukt Windows und einige Office-Produkte integriert.“
+
— Kabir Khan, Microsoft (Ref.)
+
+ + + +
+ + +
+ +„_[...] Ich verwende **FastAPI** heutzutage sehr oft. [...] Ich habe tatsächlich vor, es für alle **ML-Services meines Teams bei Microsoft** zu verwenden. Einige davon werden in das Kernprodukt **Windows** und einige **Office**-Produkte integriert._“ + +
Kabir Khan – Microsoft (Ref.)
+ +--- + +„_Wir haben die **FastAPI**-Bibliothek übernommen, um einen **REST**-Server zu erstellen, der für **Vorhersagen** abgefragt werden kann. [für Ludwig]_“ + +
Piero Molino, Yaroslav Dudin, und Sai Sumanth Miryala – Uber (Ref.)
+ +--- + +„_**Netflix** freut sich, die Open-Source-Veröffentlichung unseres **Krisenmanagement**-Orchestrierungsframeworks bekannt zu geben: **Dispatch**! [erstellt mit **FastAPI**]_“ + +
Kevin Glisson, Marc Vilanova, Forest Monsen – Netflix (Ref.)
+ +--- + +„_Falls irgendjemand eine Produktions-Python-API erstellen möchte, kann ich **FastAPI** wärmstens empfehlen. Es ist **wunderschön konzipiert**, **einfach zu verwenden** und **hoch skalierbar**; es ist zu einer **Schlüsselkomponente** unserer API-First-Entwicklungsstrategie geworden und treibt viele Automatisierungen und Services an, wie etwa unseren Virtual TAC Engineer._“ + +
Deon Pillsbury – Cisco (Ref.)
+ +--- + +
+ +## FastAPI Conf { #fastapi-conf } + +[**FastAPI Conf ’26**](https://fastapiconf.com) findet am **28. Oktober 2026** in **Amsterdam, NL** statt. Alles über FastAPI, direkt von der Quelle. 🎤 + +FastAPI Conf ’26 - 28. Oktober 2026 - Amsterdam, NL + +## FastAPI Mini-Dokumentarfilm { #fastapi-mini-documentary } + +Es gibt einen [FastAPI-Mini-Dokumentarfilm](https://www.youtube.com/watch?v=mpR8ngthqiE), veröffentlicht Ende 2025, Sie können ihn online ansehen: + +FastAPI Mini-Dokumentarfilm + +## **Typer**, das FastAPI der CLIs { #typer-the-fastapi-of-clis } + + + +Wenn Sie eine CLI-Anwendung für das Terminal erstellen, anstelle einer Web-API, schauen Sie sich [**Typer**](https://typer.tiangolo.com/) an. + +**Typer** ist die kleine Schwester von FastAPI. Und es soll das **FastAPI der CLIs** sein. ⌨️ 🚀 + +## Anforderungen { #requirements } + +FastAPI steht auf den Schultern von Giganten: + +* [Starlette](https://www.starlette.dev/) für die Webanteile. +* [Pydantic](https://docs.pydantic.dev/) für die Datenanteile. + +## Installation { #installation } + +Erstellen und aktivieren Sie eine [virtuelle Umgebung](https://fastapi.tiangolo.com/de/virtual-environments/) und installieren Sie dann FastAPI: + +
+ +```console +$ pip install "fastapi[standard]" + +---> 100% +``` + +
+ +**Hinweis**: Stellen Sie sicher, dass Sie „fastapi[standard]“ in Anführungszeichen setzen, damit es in allen Terminals funktioniert. + +## Beispiel { #example } + +### Erstellung { #create-it } + +Erstellen Sie eine Datei `main.py` mit: + +```Python +from fastapi import FastAPI + +app = FastAPI() + + +@app.get("/") +def read_root(): + return {"Hello": "World"} + + +@app.get("/items/{item_id}") +def read_item(item_id: int, q: str | None = None): + return {"item_id": item_id, "q": q} +``` + +
+Oder verwenden Sie async def ... + +Wenn Ihr Code `async` / `await` verwendet, benutzen Sie `async def`: + +```Python hl_lines="7 12" +from fastapi import FastAPI + +app = FastAPI() + + +@app.get("/") +async def read_root(): + return {"Hello": "World"} + + +@app.get("/items/{item_id}") +async def read_item(item_id: int, q: str | None = None): + return {"item_id": item_id, "q": q} +``` + +**Hinweis**: + +Wenn Sie das nicht kennen, schauen Sie sich den Abschnitt _„In Eile?“_ über [`async` und `await` in der Dokumentation](https://fastapi.tiangolo.com/de/async/#in-a-hurry) an. + +
+ +### Starten { #run-it } + +Starten Sie den Server mit: + +
+ +```console +$ fastapi dev + + ╭────────── FastAPI CLI - Development mode ───────────╮ + │ │ + │ Serving at: http://127.0.0.1:8000 │ + │ │ + │ API docs: http://127.0.0.1:8000/docs │ + │ │ + │ Running in development mode, for production use: │ + │ │ + │ fastapi run │ + │ │ + ╰─────────────────────────────────────────────────────╯ + +INFO: Will watch for changes in these directories: ['/home/user/code/awesomeapp'] +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +INFO: Started reloader process [2248755] using WatchFiles +INFO: Started server process [2248757] +INFO: Waiting for application startup. +INFO: Application startup complete. +``` + +
+ +
+Über den Befehl fastapi dev ... + +Der Befehl `fastapi dev` liest Ihre `main.py`-Datei, erkennt die **FastAPI**-App darin und startet einen Server mit [Uvicorn](https://www.uvicorn.dev). + +Standardmäßig wird `fastapi dev` mit aktiviertem Auto-Reload für die lokale Entwicklung gestartet. + +Sie können mehr darüber in der [FastAPI CLI Dokumentation](https://fastapi.tiangolo.com/de/fastapi-cli/) lesen. + +
+ +### Es testen { #check-it } + +Öffnen Sie Ihren Browser unter [http://127.0.0.1:8000/items/5?q=somequery](http://127.0.0.1:8000/items/5?q=somequery). + +Sie sehen die JSON-Response als: + +```JSON +{"item_id": 5, "q": "somequery"} +``` + +Sie haben bereits eine API erstellt, welche: + +* HTTP-Requests auf den _Pfaden_ `/` und `/items/{item_id}` entgegennimmt. +* Beide _Pfade_ nehmen `GET` Operationen (auch bekannt als HTTP-_Methoden_) entgegen. +* Der _Pfad_ `/items/{item_id}` hat einen _Pfad-Parameter_ `item_id`, der ein `int` sein sollte. +* Der _Pfad_ `/items/{item_id}` hat einen optionalen `str`-_Query-Parameter_ `q`. + +### Interaktive API-Dokumentation { #interactive-api-docs } + +Gehen Sie nun auf [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs). + +Sie sehen die automatische interaktive API-Dokumentation (bereitgestellt von [Swagger UI](https://github.com/swagger-api/swagger-ui)): + +![Swagger UI](https://fastapi.tiangolo.com/img/index/index-01-swagger-ui-simple.png) + +### Alternative API-Dokumentation { #alternative-api-docs } + +Und jetzt gehen Sie auf [http://127.0.0.1:8000/redoc](http://127.0.0.1:8000/redoc). + +Sie sehen die alternative automatische Dokumentation (bereitgestellt von [ReDoc](https://github.com/Rebilly/ReDoc)): + +![ReDoc](https://fastapi.tiangolo.com/img/index/index-02-redoc-simple.png) + +## Beispielaktualisierung { #example-upgrade } + +Ändern Sie jetzt die Datei `main.py`, um den Body eines `PUT`-Requests zu empfangen. + +Deklarieren Sie den Body mit Standard-Python-Typen, dank Pydantic. + +```Python hl_lines="2 7-10 23-25" +from fastapi import FastAPI +from pydantic import BaseModel + +app = FastAPI() + + +class Item(BaseModel): + name: str + price: float + is_offer: bool | None = None + + +@app.get("/") +def read_root(): + return {"Hello": "World"} + + +@app.get("/items/{item_id}") +def read_item(item_id: int, q: str | None = None): + return {"item_id": item_id, "q": q} + + +@app.put("/items/{item_id}") +def update_item(item_id: int, item: Item): + return {"item_name": item.name, "item_id": item_id} +``` + +Der `fastapi dev`-Server sollte automatisch neu laden. + +### Interaktive API-Dokumentation aktualisieren { #interactive-api-docs-upgrade } + +Gehen Sie jetzt auf [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs). + +* Die interaktive API-Dokumentation wird automatisch aktualisiert, einschließlich des neuen Bodys: + +![Swagger UI](https://fastapi.tiangolo.com/img/index/index-03-swagger-02.png) + +* Klicken Sie auf den Button „Try it out“, damit können Sie die Parameter ausfüllen und direkt mit der API interagieren: + +![Swagger UI Interaktion](https://fastapi.tiangolo.com/img/index/index-04-swagger-03.png) + +* Klicken Sie dann auf den Button „Execute“, die Benutzeroberfläche wird mit Ihrer API kommunizieren, die Parameter senden, die Ergebnisse erhalten und sie auf dem Bildschirm anzeigen: + +![Swagger UI Interaktion](https://fastapi.tiangolo.com/img/index/index-05-swagger-04.png) + +### Alternative API-Dokumentation aktualisieren { #alternative-api-docs-upgrade } + +Und jetzt gehen Sie auf [http://127.0.0.1:8000/redoc](http://127.0.0.1:8000/redoc). + +* Die alternative Dokumentation wird ebenfalls den neuen Query-Parameter und Body widerspiegeln: + +![ReDoc](https://fastapi.tiangolo.com/img/index/index-06-redoc-02.png) + +### Zusammenfassung { #recap } + +Zusammengefasst deklarieren Sie **einmal** die Typen von Parametern, Body, usw. als Funktionsparameter. + +Das machen Sie mit modernen Standard-Python-Typen. + +Sie müssen keine neue Syntax, Methoden oder Klassen einer bestimmten Bibliothek usw. lernen. + +Nur Standard-**Python**. + +Zum Beispiel für ein `int`: + +```Python +item_id: int +``` + +oder für ein komplexeres `Item`-Modell: + +```Python +item: Item +``` + +... und mit dieser einen Deklaration erhalten Sie: + +* Editor-Unterstützung, einschließlich: + * Vervollständigung. + * Typprüfungen. +* Validierung von Daten: + * Automatische und eindeutige Fehler, wenn die Daten ungültig sind. + * Validierung sogar für tief verschachtelte JSON-Objekte. +* Konvertierung von Eingabedaten: Aus dem Netzwerk kommend, zu Python-Daten und -Typen. Lesen von: + * JSON. + * Pfad-Parametern. + * Query-Parametern. + * Cookies. + * Headern. + * Formularen. + * Dateien. +* Konvertierung von Ausgabedaten: Konvertierung von Python-Daten und -Typen zu Netzwerkdaten (als JSON): + * Konvertieren von Python-Typen (`str`, `int`, `float`, `bool`, `list`, usw.). + * `datetime`-Objekte. + * `UUID`-Objekte. + * Datenbankmodelle. + * ... und viele mehr. +* Automatische interaktive API-Dokumentation, einschließlich zwei alternativer Benutzeroberflächen: + * Swagger UI. + * ReDoc. + +--- + +Um auf das vorherige Codebeispiel zurückzukommen, **FastAPI** wird: + +* Validieren, dass es eine `item_id` im Pfad für `GET`- und `PUT`-Requests gibt. +* Validieren, ob die `item_id` vom Typ `int` für `GET`- und `PUT`-Requests ist. + * Falls nicht, sieht der Client einen hilfreichen, klaren Fehler. +* Prüfen, ob es einen optionalen Query-Parameter namens `q` (wie in `http://127.0.0.1:8000/items/foo?q=somequery`) für `GET`-Requests gibt. + * Da der `q`-Parameter mit `= None` deklariert ist, ist er optional. + * Ohne das `None` wäre er erforderlich (wie der Body im Fall von `PUT`). +* Bei `PUT`-Requests an `/items/{item_id}` den Body als JSON lesen: + * Prüfen, ob er ein erforderliches Attribut `name` hat, das ein `str` sein muss. + * Prüfen, ob er ein erforderliches Attribut `price` hat, das ein `float` sein muss. + * Prüfen, ob er ein optionales Attribut `is_offer` hat, das ein `bool` sein muss, falls vorhanden. + * All dies würde auch für tief verschachtelte JSON-Objekte funktionieren. +* Automatisch von und nach JSON konvertieren. +* Alles mit OpenAPI dokumentieren, welches verwendet werden kann von: + * Interaktiven Dokumentationssystemen. + * Automatisch Client-Code generierenden Systemen für viele Sprachen. +* Zwei interaktive Dokumentations-Weboberflächen direkt bereitstellen. + +--- + +Wir haben nur an der Oberfläche gekratzt, aber Sie bekommen schon eine Vorstellung davon, wie das Ganze funktioniert. + +Versuchen Sie, diese Zeile zu ändern: + +```Python + return {"item_name": item.name, "item_id": item_id} +``` + +... von: + +```Python + ... "item_name": item.name ... +``` + +... zu: + +```Python + ... "item_price": item.price ... +``` + +... und sehen Sie, wie Ihr Editor die Attribute automatisch vervollständigt und ihre Typen kennt: + +![Editor Unterstützung](https://fastapi.tiangolo.com/img/vscode-completion.png) + +Für ein vollständigeres Beispiel, mit weiteren Funktionen, siehe das Tutorial – Benutzerhandbuch. + +**Spoiler-Alarm**: Das Tutorial – Benutzerhandbuch enthält: + +* Deklaration von **Parametern** von anderen verschiedenen Stellen wie: **Header**, **Cookies**, **Formularfelder** und **Dateien**. +* Wie man **Validierungs-Constraints** wie `maximum_length` oder `regex` setzt. +* Ein sehr leistungsfähiges und einfach zu bedienendes System für **Dependency Injection**. +* Sicherheit und Authentifizierung, einschließlich Unterstützung für **OAuth2** mit **JWT-Tokens** und **HTTP Basic** Authentifizierung. +* Fortgeschrittenere (aber ebenso einfache) Techniken zur Deklaration **tief verschachtelter JSON-Modelle** (dank Pydantic). +* **GraphQL**-Integration mit [Strawberry](https://strawberry.rocks) und anderen Bibliotheken. +* Viele zusätzliche Features (dank Starlette) wie: + * **WebSockets** + * extrem einfache Tests auf Basis von HTTPX und `pytest` + * **CORS** + * **Cookie-Sessions** + * ... und mehr. + +### Ihre App deployen (optional) { #deploy-your-app-optional } + +Optional können Sie Ihre FastAPI-App mit einem einzigen Befehl in die [FastAPI Cloud](https://fastapicloud.com) deployen. 🚀 + +
+ +```console +$ fastapi deploy + +Deploying to FastAPI Cloud... + +✅ Deployment successful! + +🐔 Ready the chicken! Your app is ready at https://myapp.fastapicloud.dev +``` + +
+ +Das CLI erkennt Ihre FastAPI-Anwendung automatisch und deployt sie in die Cloud. Wenn Sie nicht eingeloggt sind, wird Ihr Browser geöffnet, um den Authentifizierungsprozess abzuschließen. + +Das war’s! Jetzt können Sie unter dieser URL auf Ihre App zugreifen. ✨ + +#### Über FastAPI Cloud { #about-fastapi-cloud } + +**[FastAPI Cloud](https://fastapicloud.com)** 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 } + +Unabhängige TechEmpower-Benchmarks zeigen **FastAPI**-Anwendungen, die unter Uvicorn laufen, als [eines der schnellsten verfügbaren Python-Frameworks](https://www.techempower.com/benchmarks/#section=test&runid=7464e520-0dc2-473d-bd34-dbdfd7e85911&hw=ph&test=query&l=zijzen-7), nur hinter Starlette und Uvicorn selbst (intern von FastAPI verwendet). (*) + +Um mehr darüber zu erfahren, siehe den Abschnitt [Benchmarks](https://fastapi.tiangolo.com/de/benchmarks/). + +## Abhängigkeiten { #dependencies } + +FastAPI hängt von Pydantic und Starlette ab. + +### `standard`-Abhängigkeiten { #standard-dependencies } + +Wenn Sie FastAPI mit `pip install "fastapi[standard]"` installieren, kommt es mit der `standard`-Gruppe optionaler Abhängigkeiten: + +Verwendet von Pydantic: + +* [`email-validator`](https://github.com/JoshData/python-email-validator) – für E-Mail-Validierung. + +Verwendet von Starlette: + +* [`httpx`](https://www.python-httpx.org) – erforderlich, wenn Sie den `TestClient` verwenden möchten. +* [`jinja2`](https://jinja.palletsprojects.com) – erforderlich, wenn Sie die Default-Template-Konfiguration verwenden möchten. +* [`python-multipart`](https://github.com/Kludex/python-multipart) – erforderlich, wenn Sie Formulare mittels `request.form()` „parsen“ möchten. + +Verwendet von FastAPI: + +* [`uvicorn`](https://www.uvicorn.dev) – für den Server, der Ihre Anwendung lädt und bereitstellt. Dies umfasst `uvicorn[standard]`, das einige Abhängigkeiten (z. B. `uvloop`) beinhaltet, die für eine Bereitstellung mit hoher Performanz benötigt werden. +* `fastapi-cli[standard]` – um den `fastapi`-Befehl bereitzustellen. + * Dies beinhaltet `fastapi-cloud-cli`, das es Ihnen ermöglicht, Ihre FastAPI-Anwendung auf [FastAPI Cloud](https://fastapicloud.com) bereitzustellen. + +### Ohne `standard`-Abhängigkeiten { #without-standard-dependencies } + +Wenn Sie die `standard` optionalen Abhängigkeiten nicht einschließen möchten, können Sie mit `pip install fastapi` statt `pip install "fastapi[standard]"` installieren. + +### Ohne `fastapi-cloud-cli` { #without-fastapi-cloud-cli } + +Wenn Sie FastAPI mit den Standardabhängigkeiten, aber ohne das `fastapi-cloud-cli` installieren möchten, können Sie mit `pip install "fastapi[standard-no-fastapi-cloud-cli]"` installieren. + +### Zusätzliche optionale Abhängigkeiten { #additional-optional-dependencies } + +Es gibt einige zusätzliche Abhängigkeiten, die Sie installieren möchten. + +Zusätzliche optionale Pydantic-Abhängigkeiten: + +* [`pydantic-settings`](https://docs.pydantic.dev/latest/usage/pydantic_settings/) – für die Verwaltung von Einstellungen. +* [`pydantic-extra-types`](https://docs.pydantic.dev/latest/usage/types/extra_types/extra_types/) – für zusätzliche Typen zur Verwendung mit Pydantic. + +Zusätzliche optionale FastAPI-Abhängigkeiten: + +* [`orjson`](https://github.com/ijl/orjson) – erforderlich, wenn Sie `ORJSONResponse` verwenden möchten. +* [`ujson`](https://github.com/esnme/ultrajson) – erforderlich, wenn Sie `UJSONResponse` verwenden möchten. + +## Lizenz { #license } + +Dieses Projekt ist unter den Bedingungen der MIT-Lizenz lizenziert. diff --git a/docs/de/docs/learn/index.md b/docs/de/docs/learn/index.md new file mode 100644 index 0000000000000..e1f583fb3801a --- /dev/null +++ b/docs/de/docs/learn/index.md @@ -0,0 +1,5 @@ +# Lernen { #learn } + +Hier sind die einführenden Abschnitte und Tutorials, um **FastAPI** zu lernen. + +Sie könnten dies als **Buch**, als **Kurs**, als **offizielle** und empfohlene Methode zum Erlernen von FastAPI betrachten. 😎 diff --git a/docs/de/docs/project-generation.md b/docs/de/docs/project-generation.md new file mode 100644 index 0000000000000..d2dbadbc92470 --- /dev/null +++ b/docs/de/docs/project-generation.md @@ -0,0 +1,28 @@ +# Full Stack FastAPI Template { #full-stack-fastapi-template } + +Vorlagen, die normalerweise mit einem bestimmten Setup geliefert werden, sind so konzipiert, dass sie flexibel und anpassbar sind. Dies ermöglicht es Ihnen, sie zu ändern und an die Anforderungen Ihres Projekts anzupassen und sie somit zu einem hervorragenden Ausgangspunkt zu machen. 🏁 + +Sie können diese Vorlage verwenden, um loszulegen, da sie bereits vieles der anfänglichen Einrichtung, Sicherheit, Datenbank und einige API-Endpunkte für Sie eingerichtet hat. + +GitHub-Repository: [Full Stack FastAPI Template](https://github.com/tiangolo/full-stack-fastapi-template) + +## 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. + - 🧰 [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. + - 💾 [PostgreSQL](https://www.postgresql.org) als SQL-Datenbank. +- 🚀 [React](https://react.dev) für das Frontend. + - 💃 Verwendung von TypeScript, Hooks, Vite und anderen Teilen eines modernen Frontend-Stacks. + - 🎨 [Tailwind CSS](https://tailwindcss.com) und [shadcn/ui](https://ui.shadcn.com) für die Frontend-Komponenten. + - 🤖 Ein automatisch generierter Frontend-Client. + - 🧪 [Playwright](https://playwright.dev) für End-to-End-Tests. + - 🦇 Dark-Mode-Unterstützung. +- 🐋 [Docker Compose](https://www.docker.com) für Entwicklung und Produktion. +- 🔒 Sicheres Passwort-Hashing standardmäßig. +- 🔑 JWT (JSON Web Token)-Authentifizierung. +- 📫 E-Mail-basierte Passwortwiederherstellung. +- ✅ Tests mit [Pytest](https://pytest.org). +- 📞 [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. +- 🏭 CI (kontinuierliche Integration) und CD (kontinuierliches Deployment) basierend auf GitHub Actions. diff --git a/docs/de/docs/python-types.md b/docs/de/docs/python-types.md new file mode 100644 index 0000000000000..a67b8b309437e --- /dev/null +++ b/docs/de/docs/python-types.md @@ -0,0 +1,348 @@ +# Einführung in Python-Typen { #python-types-intro } + +Python hat Unterstützung für optionale „Typhinweise“ (auch „Typannotationen“ genannt). + +Diese **„Typhinweise“** oder -Annotationen sind eine spezielle Syntax, die es erlaubt, den Typ einer Variablen zu deklarieren. + +Durch das Deklarieren von Typen für Ihre Variablen können Editoren und Tools bessere Unterstützung bieten. + +Dies ist lediglich eine **schnelle Anleitung / Auffrischung** über Pythons Typhinweise. Sie deckt nur das Minimum ab, das nötig ist, um diese mit **FastAPI** zu verwenden ... was tatsächlich sehr wenig ist. + +**FastAPI** basiert vollständig auf diesen Typhinweisen, sie geben der Anwendung viele Vorteile und Möglichkeiten. + +Aber selbst wenn Sie **FastAPI** nie verwenden, wird es für Sie nützlich sein, ein wenig darüber zu lernen. + +/// note | Hinweis + +Wenn Sie ein Python-Experte sind und bereits alles über Typhinweise wissen, überspringen Sie dieses Kapitel und fahren Sie mit dem nächsten fort. + +/// + +## Motivation { #motivation } + +Fangen wir mit einem einfachen Beispiel an: + +{* ../../docs_src/python_types/tutorial001_py310.py *} + +Dieses Programm gibt aus: + +``` +John Doe +``` + +Die Funktion macht Folgendes: + +* Nimmt einen `first_name` und `last_name`. +* Schreibt den ersten Buchstaben eines jeden Wortes groß, mithilfe von `title()`. +* Verkettet sie mit einem Leerzeichen in der Mitte. + +{* ../../docs_src/python_types/tutorial001_py310.py hl[2] *} + +### Es bearbeiten { #edit-it } + +Es ist ein sehr einfaches Programm. + +Aber nun stellen Sie sich vor, Sie würden es selbst schreiben. + +Irgendwann beginnen Sie, die Funktion zu definieren, und haben die Parameter bereit ... + +Aber dann müssen Sie „diese Methode aufrufen, die den ersten Buchstaben in Großbuchstaben umwandelt“. + +War es `upper`? War es `uppercase`? `first_uppercase`? `capitalize`? + +Dann versuchen Sie es mit dem langjährigen Freund des Programmierers, der Editor-Autovervollständigung. + +Sie geben den ersten Parameter der Funktion ein, `first_name`, dann einen Punkt (`.`) und drücken `Ctrl+Space`, um die Vervollständigung auszulösen. + +Aber leider erhalten Sie nichts Nützliches: + + + +### Typen hinzufügen { #add-types } + +Lassen Sie uns eine einzelne Zeile aus der vorherigen Version ändern. + +Wir ändern genau dieses Fragment, die Parameter der Funktion, von: + +```Python + first_name, last_name +``` + +zu: + +```Python + first_name: str, last_name: str +``` + +Das war's. + +Das sind die „Typhinweise“: + +{* ../../docs_src/python_types/tutorial002_py310.py hl[1] *} + +Das ist nicht das gleiche wie das Deklarieren von Defaultwerten, wie es hier der Fall ist: + +```Python + first_name="john", last_name="doe" +``` + +Das ist eine andere Sache. + +Wir verwenden Doppelpunkte (`:`), nicht Gleichheitszeichen (`=`). + +Und das Hinzufügen von Typhinweisen ändert normalerweise nichts an dem, was ohne sie passieren würde. + +Aber jetzt stellen Sie sich vor, Sie sind wieder mitten in der Erstellung dieser Funktion, aber mit Typhinweisen. + +An derselben Stelle versuchen Sie, die Autovervollständigung mit `Ctrl+Space` auszulösen, und Sie sehen: + + + +Hier können Sie durch die Optionen blättern, bis Sie diejenige finden, bei der es „Klick“ macht: + + + +## Mehr Motivation { #more-motivation } + +Sehen Sie sich diese Funktion an, sie hat bereits Typhinweise: + +{* ../../docs_src/python_types/tutorial003_py310.py hl[1] *} + +Da der Editor die Typen der Variablen kennt, erhalten Sie nicht nur Code-Vervollständigung, sondern auch eine Fehlerprüfung: + + + +Jetzt, da Sie wissen, dass Sie das reparieren müssen, konvertieren Sie `age` mittels `str(age)` in einen String: + +{* ../../docs_src/python_types/tutorial004_py310.py hl[2] *} + +## Typen deklarieren { #declaring-types } + +Sie haben gerade den Haupt-Einsatzort für die Deklaration von Typhinweisen gesehen. Als Funktionsparameter. + +Das ist auch meistens, wie sie in **FastAPI** verwendet werden. + +### Einfache Typen { #simple-types } + +Sie können alle Standard-Python-Typen deklarieren, nicht nur `str`. + +Zum Beispiel diese: + +* `int` +* `float` +* `bool` +* `bytes` + +{* ../../docs_src/python_types/tutorial005_py310.py hl[1] *} + +### `typing`-Modul { #typing-module } + +Für einige zusätzliche Anwendungsfälle müssen Sie möglicherweise Dinge aus dem Standardmodul `typing` importieren. Zum Beispiel, wenn Sie deklarieren möchten, dass etwas „jeden Typ“ haben kann, können Sie `Any` aus `typing` verwenden: + +```python +from typing import Any + + +def some_function(data: Any): + print(data) +``` + +### Generische Typen { #generic-types } + +Einige Typen können „Typ-Parameter“ in eckigen Klammern annehmen, um ihre inneren Typen zu definieren, z. B. eine „Liste von Strings“ würde als `list[str]` deklariert. + +Diese Typen, die Typ-Parameter annehmen können, werden **generische Typen** oder **Generics** genannt. + +Sie können dieselben eingebauten Typen als Generics verwenden (mit eckigen Klammern und Typen darin): + +* `list` +* `tuple` +* `set` +* `dict` + +#### Liste { #list } + +Definieren wir zum Beispiel eine Variable, die eine `list` von `str` – eine Liste von Strings – sein soll. + +Deklarieren Sie die Variable mit der gleichen Doppelpunkt-Syntax (`:`). + +Als Typ nehmen Sie `list`. + +Da die Liste ein Typ ist, welcher innere Typen enthält, werden diese von eckigen Klammern umfasst: + +{* ../../docs_src/python_types/tutorial006_py310.py hl[1] *} + +/// note | Hinweis + +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. + +/// + +Das bedeutet: „Die Variable `items` ist eine `list`, und jedes der Elemente in dieser Liste ist ein `str`“. + +Auf diese Weise kann Ihr Editor Sie auch bei der Bearbeitung von Einträgen aus der Liste unterstützen: + + + +Ohne Typen ist das fast unmöglich zu erreichen. + +Beachten Sie, dass die Variable `item` eines der Elemente in der Liste `items` ist. + +Und trotzdem weiß der Editor, dass es sich um ein `str` handelt, und bietet entsprechende Unterstützung. + +#### Tupel und Menge { #tuple-and-set } + +Das Gleiche gilt für die Deklaration eines Tupels – `tuple` – und einer Menge – `set`: + +{* ../../docs_src/python_types/tutorial007_py310.py hl[1] *} + +Das bedeutet: + +* Die Variable `items_t` ist ein `tuple` mit 3 Elementen, einem `int`, einem weiteren `int` und einem `str`. +* Die Variable `items_s` ist ein `set`, und jedes seiner Elemente ist vom Typ `bytes`. + +#### Dict { #dict } + +Um ein `dict` zu definieren, übergeben Sie zwei Typ-Parameter, getrennt durch Kommas. + +Der erste Typ-Parameter ist für die Schlüssel des `dict`. + +Der zweite Typ-Parameter ist für die Werte des `dict`: + +{* ../../docs_src/python_types/tutorial008_py310.py hl[1] *} + +Das bedeutet: + +* Die Variable `prices` ist ein `dict`: + * Die Schlüssel dieses `dict` sind vom Typ `str` (z. B. die Namen der einzelnen Artikel). + * Die Werte dieses `dict` sind vom Typ `float` (z. B. der Preis jedes Artikels). + +#### Union { #union } + +Sie können deklarieren, dass eine Variable einer von **verschiedenen Typen** sein kann, zum Beispiel ein `int` oder ein `str`. + +Um das zu definieren, verwenden Sie den vertikalen Balken (`|`), um beide Typen zu trennen. + +Das wird „Union“ genannt, weil die Variable etwas aus der Vereinigung dieser beiden Typmengen sein kann. + +```Python hl_lines="1" +{!> ../../docs_src/python_types/tutorial008b_py310.py!} +``` + +Das bedeutet, dass `item` ein `int` oder ein `str` sein könnte. + +#### Vielleicht `None` { #possibly-none } + +Sie können deklarieren, dass ein Wert einen Typ haben könnte, wie `str`, dass er aber auch `None` sein könnte. + +//// tab | Python 3.10+ + +```Python hl_lines="1" +{!> ../../docs_src/python_types/tutorial009_py310.py!} +``` + +//// + +Wenn Sie `str | None` anstelle von nur `str` verwenden, wird Ihr Editor Ihnen dabei helfen, Fehler zu erkennen, bei denen Sie annehmen könnten, dass ein Wert immer ein `str` ist, obwohl er auch `None` sein könnte. + +### Klassen als Typen { #classes-as-types } + +Sie können auch eine Klasse als Typ einer Variablen deklarieren. + +Nehmen wir an, Sie haben eine Klasse `Person`, mit einem Namen: + +{* ../../docs_src/python_types/tutorial010_py310.py hl[1:3] *} + +Dann können Sie eine Variable vom Typ `Person` deklarieren: + +{* ../../docs_src/python_types/tutorial010_py310.py hl[6] *} + +Und wiederum bekommen Sie die volle Editor-Unterstützung: + + + +Beachten Sie, dass das bedeutet: „`one_person` ist eine **Instanz** der Klasse `Person`“. + +Es bedeutet nicht: „`one_person` ist die **Klasse** namens `Person`“. + +## Pydantic-Modelle { #pydantic-models } + +[Pydantic](https://docs.pydantic.dev/) ist eine Python-Bibliothek für die Validierung von Daten. + +Sie deklarieren die „Form“ der Daten als Klassen mit Attributen. + +Und jedes Attribut hat einen Typ. + +Dann erzeugen Sie eine Instanz dieser Klasse mit einigen Werten, und Pydantic validiert die Werte, konvertiert sie in den passenden Typ (falls notwendig) und gibt Ihnen ein Objekt mit allen Daten. + +Und Sie erhalten volle Editor-Unterstützung für dieses Objekt. + +Ein Beispiel aus der offiziellen Pydantic-Dokumentation: + +{* ../../docs_src/python_types/tutorial011_py310.py *} + +/// note | Hinweis + +Um mehr über [Pydantic zu erfahren, schauen Sie sich dessen Dokumentation an](https://docs.pydantic.dev/). + +/// + +**FastAPI** basiert vollständig auf Pydantic. + +Viel mehr von all dem werden Sie in praktischer Anwendung im [Tutorial – Benutzerhandbuch](tutorial/index.md) sehen. + +## Typhinweise mit Metadaten-Annotationen { #type-hints-with-metadata-annotations } + +Python bietet auch die Möglichkeit, **zusätzliche Metadaten** in Typhinweisen unterzubringen, mittels `Annotated`. + +Sie können `Annotated` von `typing` importieren. + +{* ../../docs_src/python_types/tutorial013_py310.py hl[1,4] *} + +Python selbst macht nichts mit diesem `Annotated`. Für Editoren und andere Tools ist der Typ immer noch `str`. + +Aber Sie können diesen Platz in `Annotated` nutzen, um **FastAPI** zusätzliche Metadaten darüber bereitzustellen, wie sich Ihre Anwendung verhalten soll. + +Wichtig ist, dass **der erste *Typ-Parameter***, den Sie `Annotated` übergeben, der **tatsächliche Typ** ist. Der Rest sind nur Metadaten für andere Tools. + +Im Moment müssen Sie nur wissen, dass `Annotated` existiert, und dass es Standard-Python ist. 😎 + +Später werden Sie sehen, wie **mächtig** es sein kann. + +/// tip | Tipp + +Der Umstand, dass es **Standard-Python** ist, bedeutet, dass Sie immer noch die **bestmögliche Entwickler-Erfahrung** in Ihrem Editor haben, sowie mit den Tools, die Sie nutzen, um Ihren Code zu analysieren, zu refaktorisieren, usw. ✨ + +Und ebenfalls, dass Ihr Code sehr kompatibel mit vielen anderen Python-Tools und -Bibliotheken sein wird. 🚀 + +/// + +## Typhinweise in **FastAPI** { #type-hints-in-fastapi } + +**FastAPI** macht sich diese Typhinweise zunutze, um mehrere Dinge zu tun. + +Mit **FastAPI** deklarieren Sie Parameter mit Typhinweisen, und Sie erhalten: + +* **Editorunterstützung**. +* **Typ-Prüfungen**. + +... und **FastAPI** verwendet dieselben Deklarationen, um: + +* **Anforderungen** zu definieren: aus Request-Pfadparametern, Query-Parametern, Headern, Bodys, Abhängigkeiten, usw. +* **Daten umzuwandeln**: aus dem Request in den erforderlichen Typ. +* **Daten zu validieren**: aus jedem Request: + * **Automatische Fehler** generieren, die an den Client zurückgegeben werden, wenn die Daten ungültig sind. +* Die API mit OpenAPI zu **dokumentieren**: + * die dann von den Benutzeroberflächen der automatisch generierten interaktiven Dokumentation verwendet wird. + +Das mag alles abstrakt klingen. Machen Sie sich keine Sorgen. Sie werden all das in Aktion sehen im [Tutorial – Benutzerhandbuch](tutorial/index.md). + +Das Wichtigste ist, dass **FastAPI** durch die Verwendung von Standard-Python-Typen an einer einzigen Stelle (anstatt weitere Klassen, Dekoratoren usw. hinzuzufügen) einen Großteil der Arbeit für Sie erledigt. + +/// note | Hinweis + +Wenn Sie bereits das ganze Tutorial durchgearbeitet haben und mehr über Typen erfahren wollen, dann ist eine gute Ressource [der „Cheat Sheet“ von `mypy`](https://mypy.readthedocs.io/en/latest/cheat_sheet_py3.html). + +/// diff --git a/docs/de/docs/resources/index.md b/docs/de/docs/resources/index.md new file mode 100644 index 0000000000000..52b32b148023e --- /dev/null +++ b/docs/de/docs/resources/index.md @@ -0,0 +1,3 @@ +# Ressourcen { #resources } + +Zusätzliche Ressourcen, externe Links und mehr. ✈️ diff --git a/docs/de/docs/translation-banner.md b/docs/de/docs/translation-banner.md new file mode 100644 index 0000000000000..1801a019046e3 --- /dev/null +++ b/docs/de/docs/translation-banner.md @@ -0,0 +1,11 @@ +/// details | 🌐 Übersetzung durch KI und Menschen + +Diese Übersetzung wurde von KI erstellt, angeleitet von Menschen. 🤝 + +Sie könnte Fehler enthalten, etwa Missverständnisse des ursprünglichen Sinns oder unnatürliche Formulierungen, usw. 🤖 + +Sie können diese Übersetzung verbessern, indem Sie [uns helfen, die KI-LLM besser anzuleiten](https://fastapi.tiangolo.com/de/contributing/#translations). + +[Englische Version](ENGLISH_VERSION_URL) + +/// diff --git a/docs/de/docs/tutorial/background-tasks.md b/docs/de/docs/tutorial/background-tasks.md new file mode 100644 index 0000000000000..7d6c35a1c0170 --- /dev/null +++ b/docs/de/docs/tutorial/background-tasks.md @@ -0,0 +1,86 @@ +# Hintergrundtasks { #background-tasks } + +Sie können Hintergrundtasks definieren, die *nach* der Rückgabe einer Response ausgeführt werden sollen. + +Das ist nützlich für Vorgänge, die nach einem Request ausgeführt werden müssen, bei denen der Client jedoch nicht unbedingt auf den Abschluss des Vorgangs warten muss, bevor er die Response erhält. + +Hierzu zählen beispielsweise: + +* E-Mail-Benachrichtigungen, die nach dem Ausführen einer Aktion gesendet werden: + * Da die Verbindung zu einem E-Mail-Server und das Senden einer E-Mail in der Regel „langsam“ ist (einige Sekunden), können Sie die Response sofort zurücksenden und die E-Mail-Benachrichtigung im Hintergrund senden. +* Daten verarbeiten: + * Angenommen, Sie erhalten eine Datei, die einen langsamen Prozess durchlaufen muss. Sie können als Response „Accepted“ (HTTP 202) zurückgeben und die Datei im Hintergrund verarbeiten. + +## `BackgroundTasks` verwenden { #using-backgroundtasks } + +Importieren Sie zunächst `BackgroundTasks` und definieren Sie einen Parameter in Ihrer *Pfadoperation-Funktion* mit der Typdeklaration `BackgroundTasks`: + +{* ../../docs_src/background_tasks/tutorial001_py310.py hl[1,13] *} + +**FastAPI** erstellt für Sie das Objekt vom Typ `BackgroundTasks` und übergibt es als diesen Parameter. + +## Eine Taskfunktion erstellen { #create-a-task-function } + +Erstellen Sie eine Funktion, die als Hintergrundtask ausgeführt werden soll. + +Es handelt sich schlicht um eine Standard-Funktion, die Parameter empfangen kann. + +Es kann sich um eine `async def`- oder normale `def`-Funktion handeln. **FastAPI** weiß, wie damit zu verfahren ist. + +In diesem Fall schreibt die Taskfunktion in eine Datei (den Versand einer E-Mail simulierend). + +Und da der Schreibvorgang nicht `async` und `await` verwendet, definieren wir die Funktion mit normalem `def`: + +{* ../../docs_src/background_tasks/tutorial001_py310.py hl[6:9] *} + +## Den Hintergrundtask hinzufügen { #add-the-background-task } + +Übergeben Sie innerhalb Ihrer *Pfadoperation-Funktion* Ihre Taskfunktion mit der Methode `.add_task()` an das *Hintergrundtasks*-Objekt: + +{* ../../docs_src/background_tasks/tutorial001_py310.py hl[14] *} + +`.add_task()` erhält als Argumente: + +* Eine Taskfunktion, die im Hintergrund ausgeführt wird (`write_notification`). +* Eine beliebige Folge von Argumenten, die der Reihe nach an die Taskfunktion übergeben werden sollen (`email`). +* Alle Schlüsselwort-Argumente, die an die Taskfunktion übergeben werden sollen (`message="some notification"`). + +## Dependency Injection { #dependency-injection } + +Die Verwendung von `BackgroundTasks` funktioniert auch mit dem Dependency Injection System. Sie können einen Parameter vom Typ `BackgroundTasks` auf mehreren Ebenen deklarieren: in einer *Pfadoperation-Funktion*, in einer Abhängigkeit (Dependable), in einer Unterabhängigkeit usw. + +**FastAPI** weiß, was jeweils zu tun ist und wie dasselbe Objekt wiederverwendet werden kann, sodass alle Hintergrundtasks zusammengeführt und anschließend im Hintergrund ausgeführt werden: + + +{* ../../docs_src/background_tasks/tutorial002_an_py310.py hl[13,15,22,25] *} + + +In obigem Beispiel werden die Nachrichten, *nachdem* die Response gesendet wurde, in die Datei `log.txt` geschrieben. + +Wenn im Request ein Query-Parameter enthalten war, wird dieser in einem Hintergrundtask in das Log geschrieben. + +Und dann schreibt ein weiterer Hintergrundtask, der in der *Pfadoperation-Funktion* erstellt wird, eine Nachricht unter Verwendung des Pfad-Parameters `email`. + +## Technische Details { #technical-details } + +Die Klasse `BackgroundTasks` stammt direkt von [`starlette.background`](https://www.starlette.dev/background/). + +Sie wird direkt in FastAPI importiert/inkludiert, sodass Sie sie von `fastapi` importieren können und vermeiden, versehentlich das alternative `BackgroundTask` (ohne das `s` am Ende) von `starlette.background` zu importieren. + +Indem Sie nur `BackgroundTasks` (und nicht `BackgroundTask`) verwenden, ist es dann möglich, es als *Pfadoperation-Funktion*-Parameter zu verwenden und **FastAPI** den Rest für Sie erledigen zu lassen, genau wie bei der direkten Verwendung des `Request`-Objekts. + +Es ist immer noch möglich, `BackgroundTask` allein in FastAPI zu verwenden, aber Sie müssen das Objekt in Ihrem Code erstellen und eine Starlette-`Response` zurückgeben, die es enthält. + +Weitere Details finden Sie in [Starlettes offizieller Dokumentation für Hintergrundtasks](https://www.starlette.dev/background/). + +## Vorbehalt { #caveat } + +Wenn Sie umfangreiche Hintergrundberechnungen durchführen müssen und diese nicht unbedingt vom selben Prozess ausgeführt werden müssen (z. B. müssen Sie Speicher, Variablen, usw. nicht gemeinsam nutzen), könnte die Verwendung anderer größerer Tools wie z. B. [Celery](https://docs.celeryq.dev) von Vorteil sein. + +Sie erfordern in der Regel komplexere Konfigurationen und einen Nachrichten-/Job-Queue-Manager wie RabbitMQ oder Redis, ermöglichen Ihnen jedoch die Ausführung von Hintergrundtasks in mehreren Prozessen und insbesondere auf mehreren Servern. + +Wenn Sie jedoch über dieselbe **FastAPI**-App auf Variablen und Objekte zugreifen oder kleine Hintergrundtasks ausführen müssen (z. B. das Senden einer E-Mail-Benachrichtigung), können Sie einfach `BackgroundTasks` verwenden. + +## Zusammenfassung { #recap } + +Importieren und verwenden Sie `BackgroundTasks` mit Parametern in *Pfadoperation-Funktionen* und Abhängigkeiten, um Hintergrundtasks hinzuzufügen. diff --git a/docs/de/docs/tutorial/bigger-applications.md b/docs/de/docs/tutorial/bigger-applications.md new file mode 100644 index 0000000000000..119f3e8c02143 --- /dev/null +++ b/docs/de/docs/tutorial/bigger-applications.md @@ -0,0 +1,547 @@ +# Größere Anwendungen – mehrere Dateien { #bigger-applications-multiple-files } + +Wenn Sie eine Anwendung oder eine Web-API erstellen, ist es selten der Fall, dass Sie alles in einer einzigen Datei unterbringen können. + +**FastAPI** bietet ein praktisches Werkzeug zur Strukturierung Ihrer Anwendung bei gleichzeitiger Wahrung der Flexibilität. + +/// note | Hinweis + +Wenn Sie von Flask kommen, wäre dies das Äquivalent zu Flasks Blueprints. + +/// + +## Eine Beispiel-Dateistruktur { #an-example-file-structure } + +Nehmen wir an, Sie haben eine Dateistruktur wie diese: + +``` +. +├── app +│ ├── __init__.py +│ ├── main.py +│ ├── dependencies.py +│ └── routers +│ │ ├── __init__.py +│ │ ├── items.py +│ │ └── users.py +│ └── internal +│ ├── __init__.py +│ └── admin.py +``` + +/// tip | Tipp + +Es gibt mehrere `__init__.py`-Dateien: eine in jedem Verzeichnis oder Unterverzeichnis. + +Das ermöglicht den Import von Code aus einer Datei in eine andere. + +In `app/main.py` könnten Sie beispielsweise eine Zeile wie diese haben: + +``` +from app.routers import items +``` + +/// + +* Das Verzeichnis `app` enthält alles. Und es hat eine leere Datei `app/__init__.py`, es handelt sich also um ein „Python-Package“ (eine Sammlung von „Python-Modulen“): `app`. +* Es enthält eine Datei `app/main.py`. Da sie sich in einem Python-Package (einem Verzeichnis mit einer Datei `__init__.py`) befindet, ist sie ein „Modul“ dieses Packages: `app.main`. +* Es gibt auch eine Datei `app/dependencies.py`, genau wie `app/main.py` ist sie ein „Modul“: `app.dependencies`. +* Es gibt ein Unterverzeichnis `app/routers/` mit einer weiteren Datei `__init__.py`, es handelt sich also um ein „Python-Subpackage“: `app.routers`. +* Die Datei `app/routers/items.py` befindet sich in einem Package, `app/routers/`, also ist sie ein Submodul: `app.routers.items`. +* Das Gleiche gilt für `app/routers/users.py`, es ist ein weiteres Submodul: `app.routers.users`. +* Es gibt auch ein Unterverzeichnis `app/internal/` mit einer weiteren Datei `__init__.py`, es handelt sich also um ein weiteres „Python-Subpackage“: `app.internal`. +* Und die Datei `app/internal/admin.py` ist ein weiteres Submodul: `app.internal.admin`. + + + +Die gleiche Dateistruktur mit Kommentaren: + +```bash +. +├── app # "app" ist ein Python-Package +│   ├── __init__.py # diese Datei macht "app" zu einem "Python-Package" +│   ├── main.py # "main"-Modul, z. B. import app.main +│   ├── dependencies.py # "dependencies"-Modul, z. B. import app.dependencies +│   └── routers # "routers" ist ein "Python-Subpackage" +│   │ ├── __init__.py # macht "routers" zu einem "Python-Subpackage" +│   │ ├── items.py # "items"-Submodul, z. B. import app.routers.items +│   │ └── users.py # "users"-Submodul, z. B. import app.routers.users +│   └── internal # "internal" ist ein "Python-Subpackage" +│   ├── __init__.py # macht "internal" zu einem "Python-Subpackage" +│   └── admin.py # "admin"-Submodul, z. B. import app.internal.admin +``` + +## `APIRouter` { #apirouter } + +Nehmen wir an, die Datei, die nur für die Verwaltung von Benutzern zuständig ist, ist das Submodul unter `/app/routers/users.py`. + +Sie möchten die *Pfadoperationen* für Ihre Benutzer vom Rest des Codes trennen, um ihn organisiert zu halten. + +Aber es ist immer noch Teil derselben **FastAPI**-Anwendung/Web-API (es ist Teil desselben „Python-Packages“). + +Sie können die *Pfadoperationen* für dieses Modul mit `APIRouter` erstellen. + +### `APIRouter` importieren { #import-apirouter } + +Sie importieren ihn und erstellen eine „Instanz“ auf die gleiche Weise wie mit der Klasse `FastAPI`: + +{* ../../docs_src/bigger_applications/app_an_py310/routers/users.py hl[1,3] title["app/routers/users.py"] *} + +### *Pfadoperationen* mit `APIRouter` { #path-operations-with-apirouter } + +Und dann verwenden Sie ihn, um Ihre *Pfadoperationen* zu deklarieren. + +Verwenden Sie ihn auf die gleiche Weise wie die Klasse `FastAPI`: + +{* ../../docs_src/bigger_applications/app_an_py310/routers/users.py hl[6,11,16] title["app/routers/users.py"] *} + +Sie können sich `APIRouter` als eine „Mini-`FastAPI`“-Klasse vorstellen. + +Alle die gleichen Optionen werden unterstützt. + +Alle die gleichen `parameters`, `responses`, `dependencies`, `tags`, usw. + +/// tip | Tipp + +In diesem Beispiel heißt die Variable `router`, aber Sie können ihr einen beliebigen Namen geben. + +/// + +Wir werden diesen `APIRouter` in die Hauptanwendung `FastAPI` einbinden, aber zuerst kümmern wir uns um die Abhängigkeiten und einen anderen `APIRouter`. + +## Abhängigkeiten { #dependencies } + +Wir sehen, dass wir einige Abhängigkeiten benötigen, die an mehreren Stellen der Anwendung verwendet werden. + +Also fügen wir sie in ihr eigenes `dependencies`-Modul (`app/dependencies.py`) ein. + +Wir werden nun eine einfache Abhängigkeit verwenden, um einen benutzerdefinierten `X-Token`-Header zu lesen: + +{* ../../docs_src/bigger_applications/app_an_py310/dependencies.py hl[3,6:8] title["app/dependencies.py"] *} + +/// tip | Tipp + +Um dieses Beispiel zu vereinfachen, verwenden wir einen erfundenen Header. + +Aber in der Praxis werden Sie mit den integrierten [Sicherheits-Werkzeugen](security/index.md) bessere Ergebnisse erzielen. + +/// + +## Ein weiteres Modul mit `APIRouter` { #another-module-with-apirouter } + +Nehmen wir an, Sie haben im Modul unter `app/routers/items.py` auch die Endpunkte, die für die Verarbeitung von Artikeln („Items“) aus Ihrer Anwendung vorgesehen sind. + +Sie haben *Pfadoperationen* für: + +* `/items/` +* `/items/{item_id}` + +Es ist alles die gleiche Struktur wie bei `app/routers/users.py`. + +Aber wir wollen schlauer sein und den Code etwas vereinfachen. + +Wir wissen, dass alle *Pfadoperationen* in diesem Modul folgendes haben: + +* Pfad-`prefix`: `/items`. +* `tags`: (nur ein Tag: `items`). +* Zusätzliche `responses`. +* `dependencies`: Sie alle benötigen die von uns erstellte `X-Token`-Abhängigkeit. + +Anstatt also alles zu jeder *Pfadoperation* hinzuzufügen, können wir es dem `APIRouter` hinzufügen. + +{* ../../docs_src/bigger_applications/app_an_py310/routers/items.py hl[5:10,16,21] title["app/routers/items.py"] *} + +Da der Pfad jeder *Pfadoperation* mit `/` beginnen muss, wie in: + +```Python hl_lines="1" +@router.get("/{item_id}") +async def read_item(item_id: str): + ... +``` + +... darf das Präfix kein abschließendes `/` enthalten. + +Das Präfix lautet in diesem Fall also `/items`. + +Wir können auch eine Liste von `tags` und zusätzliche `responses` hinzufügen, die auf alle in diesem Router enthaltenen *Pfadoperationen* angewendet werden. + +Und wir können eine Liste von `dependencies` hinzufügen, die allen *Pfadoperationen* im Router hinzugefügt und für jeden an sie gerichteten Request ausgeführt/aufgelöst werden. + +/// tip | Tipp + +Beachten Sie, dass ähnlich wie bei [Abhängigkeiten in *Pfadoperation-Dekoratoren*](dependencies/dependencies-in-path-operation-decorators.md) kein Wert an Ihre *Pfadoperation-Funktion* übergeben wird. + +/// + +Das Endergebnis ist, dass die Pfade für diese Artikel jetzt wie folgt lauten: + +* `/items/` +* `/items/{item_id}` + +... wie wir es beabsichtigt hatten. + +* Sie werden mit einer Liste von Tags gekennzeichnet, die einen einzelnen String „items“ enthält. + * Diese „Tags“ sind besonders nützlich für die automatischen interaktiven Dokumentationssysteme (unter Verwendung von OpenAPI). +* Alle enthalten die vordefinierten `responses`. +* Für alle diese *Pfadoperationen* wird die Liste der `dependencies` ausgewertet/ausgeführt, bevor sie selbst ausgeführt werden. + * Wenn Sie außerdem Abhängigkeiten in einer bestimmten *Pfadoperation* deklarieren, **werden diese ebenfalls ausgeführt**. + * Zuerst werden die Router-Abhängigkeiten ausgeführt, dann die [`dependencies` im Dekorator](dependencies/dependencies-in-path-operation-decorators.md) und dann die normalen Parameterabhängigkeiten. + * Sie können auch [`Security`-Abhängigkeiten mit `scopes`](../advanced/security/oauth2-scopes.md) hinzufügen. + +/// tip | Tipp + +`dependencies` im `APIRouter` können beispielsweise verwendet werden, um eine Authentifizierung für eine ganze Gruppe von *Pfadoperationen* zu erfordern. Selbst wenn die Abhängigkeiten nicht jeder einzeln hinzugefügt werden. + +/// + +/// tip | Tipp + +Die Parameter `prefix`, `tags`, `responses` und `dependencies` sind (wie in vielen anderen Fällen) nur ein Feature von **FastAPI**, um Ihnen dabei zu helfen, Codeverdoppelung zu vermeiden. + +/// + +### Die Abhängigkeiten importieren { #import-the-dependencies } + +Der folgende Code befindet sich im Modul `app.routers.items`, also in der Datei `app/routers/items.py`. + +Und wir müssen die Abhängigkeitsfunktion aus dem Modul `app.dependencies` importieren, also aus der Datei `app/dependencies.py`. + +Daher verwenden wir einen relativen Import mit `..` für die Abhängigkeiten: + +{* ../../docs_src/bigger_applications/app_an_py310/routers/items.py hl[3] title["app/routers/items.py"] *} + +#### Wie relative Importe funktionieren { #how-relative-imports-work } + +/// tip | Tipp + +Wenn Sie genau wissen, wie Importe funktionieren, fahren Sie mit dem nächsten Abschnitt unten fort. + +/// + +Ein einzelner Punkt `.`, wie in: + +```Python +from .dependencies import get_token_header +``` + +würde bedeuten: + +* Beginnend im selben Package, in dem sich dieses Modul (die Datei `app/routers/items.py`) befindet (das Verzeichnis `app/routers/`) ... +* finde das Modul `dependencies` (eine imaginäre Datei unter `app/routers/dependencies.py`) ... +* und importiere daraus die Funktion `get_token_header`. + +Aber diese Datei existiert nicht, unsere Abhängigkeiten befinden sich in einer Datei unter `app/dependencies.py`. + +Erinnern Sie sich, wie unsere Anwendungs-/Dateistruktur aussieht: + + + +--- + +Die beiden Punkte `..`, wie in: + +```Python +from ..dependencies import get_token_header +``` + +bedeuten: + +* Beginnend im selben Package, in dem sich dieses Modul (die Datei `app/routers/items.py`) befindet (das Verzeichnis `app/routers/`) ... +* gehe zum übergeordneten Package (das Verzeichnis `app/`) ... +* und finde dort das Modul `dependencies` (die Datei unter `app/dependencies.py`) ... +* und importiere daraus die Funktion `get_token_header`. + +Das funktioniert korrekt! 🎉 + +--- + +Das Gleiche gilt, wenn wir drei Punkte `...` verwendet hätten, wie in: + +```Python +from ...dependencies import get_token_header +``` + +Das würde bedeuten: + +* Beginnend im selben Package, in dem sich dieses Modul (die Datei `app/routers/items.py`) befindet (das Verzeichnis `app/routers/`) ... +* gehe zum übergeordneten Package (das Verzeichnis `app/`) ... +* gehe dann zum übergeordneten Package dieses Packages (es gibt kein übergeordnetes Package, `app` ist die oberste Ebene 😱) ... +* und finde dort das Modul `dependencies` (die Datei unter `app/dependencies.py`) ... +* und importiere daraus die Funktion `get_token_header`. + +Das würde sich auf ein Paket oberhalb von `app/` beziehen, mit seiner eigenen Datei `__init__.py`, usw. Aber das haben wir nicht. Das würde in unserem Beispiel also einen Fehler auslösen. 🚨 + +Aber jetzt wissen Sie, wie es funktioniert, sodass Sie relative Importe in Ihren eigenen Anwendungen verwenden können, egal wie komplex diese sind. 🤓 + +### Einige benutzerdefinierte `tags`, `responses`, und `dependencies` hinzufügen { #add-some-custom-tags-responses-and-dependencies } + +Wir fügen weder das Präfix `/items` noch `tags=["items"]` zu jeder *Pfadoperation* hinzu, da wir sie zum `APIRouter` hinzugefügt haben. + +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_py310/routers/items.py hl[30:31] title["app/routers/items.py"] *} + +/// tip | Tipp + +Diese letzte Pfadoperation wird eine Kombination von Tags haben: `["items", "custom"]`. + +Und sie wird auch beide Responses in der Dokumentation haben, eine für `404` und eine für `403`. + +/// + +## Das Haupt-`FastAPI` { #the-main-fastapi } + +Sehen wir uns nun das Modul unter `app/main.py` an. + +Hier importieren und verwenden Sie die Klasse `FastAPI`. + +Dies wird die Hauptdatei Ihrer Anwendung sein, die alles zusammenfügt. + +Und da sich der Großteil Ihrer Logik jetzt in seinem eigenen spezifischen Modul befindet, wird die Hauptdatei recht einfach sein. + +### `FastAPI` importieren { #import-fastapi } + +Sie importieren und erstellen wie gewohnt eine `FastAPI`-Klasse. + +Und wir können sogar [globale Abhängigkeiten](dependencies/global-dependencies.md) deklarieren, die mit den Abhängigkeiten für jeden `APIRouter` kombiniert werden: + +{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[1,3,7] title["app/main.py"] *} + +### Den `APIRouter` importieren { #import-the-apirouter } + +Jetzt importieren wir die anderen Submodule, die `APIRouter` haben: + +{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[4:5] title["app/main.py"] *} + +Da es sich bei den Dateien `app/routers/users.py` und `app/routers/items.py` um Submodule handelt, die Teil desselben Python-Packages `app` sind, können wir einen einzelnen Punkt `.` verwenden, um sie mit „relativen Imports“ zu importieren. + +### Wie das Importieren funktioniert { #how-the-importing-works } + +Die Sektion: + +```Python +from .routers import items, users +``` + +bedeutet: + +* Beginnend im selben Package, in dem sich dieses Modul (die Datei `app/main.py`) befindet (das Verzeichnis `app/`) ... +* Suche nach dem Subpackage `routers` (das Verzeichnis unter `app/routers/`) ... +* und importiere daraus die Submodule `items` (die Datei unter `app/routers/items.py`) und `users` (die Datei unter `app/routers/users.py`) ... + +Das Modul `items` verfügt über eine Variable `router` (`items.router`). Das ist dieselbe, die wir in der Datei `app/routers/items.py` erstellt haben, es ist ein `APIRouter`-Objekt. + +Und dann machen wir das gleiche für das Modul `users`. + +Wir könnten sie auch wie folgt importieren: + +```Python +from app.routers import items, users +``` + +/// note | Hinweis + +Die erste Version ist ein „relativer Import“: + +```Python +from .routers import items, users +``` + +Die zweite Version ist ein „absoluter Import“: + +```Python +from app.routers import items, users +``` + +Um mehr über Python-Packages und -Module zu erfahren, lesen Sie [die offizielle Python-Dokumentation über Module](https://docs.python.org/3/tutorial/modules.html). + +/// + +### Namenskollisionen vermeiden { #avoid-name-collisions } + +Wir importieren das Submodul `items` direkt, anstatt nur seine Variable `router` zu importieren. + +Das liegt daran, dass wir im Submodul `users` auch eine weitere Variable namens `router` haben. + +Wenn wir eine nach der anderen importiert hätten, etwa: + +```Python +from .routers.items import router +from .routers.users import router +``` + +würde der `router` von `users` den von `items` überschreiben und wir könnten sie nicht gleichzeitig verwenden. + +Um also beide in derselben Datei verwenden zu können, importieren wir die Submodule direkt: + +{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[5] title["app/main.py"] *} + +### Die `APIRouter` für `users` und `items` inkludieren { #include-the-apirouters-for-users-and-items } + +Inkludieren wir nun die `router` aus diesen Submodulen `users` und `items`: + +{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[10:11] title["app/main.py"] *} + +/// note | Hinweis + +`users.router` enthält den `APIRouter` in der Datei `app/routers/users.py`. + +Und `items.router` enthält den `APIRouter` in der Datei `app/routers/items.py`. + +/// + +Mit `app.include_router()` können wir jeden `APIRouter` zur Hauptanwendung `FastAPI` hinzufügen. + +Es wird alle Routen von diesem Router als Teil von dieser inkludieren. + +/// note | Technische Details + +FastAPI behält den ursprünglichen `APIRouter` und seine `APIRoute`s aktiv, wenn der Router in die Hauptanwendung eingebunden wird. + +Das bedeutet, dass benutzerdefinierte Subklassen von `APIRouter` und `APIRoute` auch nach dem Einbinden weiterhin beteiligt sein können. + +/// + +/// tip | Tipp + +Bei der Einbindung von Routern müssen Sie sich keine Gedanken über die Leistung machen. + +Dies ist so konzipiert, dass es leichtgewichtig ist und keinen Overhead pro Request hinzufügt. + +Es hat also keinen Einfluss auf die Leistung. ⚡ + +/// + +### Einen `APIRouter` mit benutzerdefinierten `prefix`, `tags`, `responses` und `dependencies` einfügen { #include-an-apirouter-with-a-custom-prefix-tags-responses-and-dependencies } + +Stellen wir uns nun vor, dass Ihre Organisation Ihnen die Datei `app/internal/admin.py` gegeben hat. + +Sie enthält einen `APIRouter` mit einigen administrativen *Pfadoperationen*, die Ihre Organisation zwischen mehreren Projekten teilt. + +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_py310/internal/admin.py hl[3] title["app/internal/admin.py"] *} + +Aber wir möchten immer noch ein benutzerdefiniertes `prefix` festlegen, wenn wir den `APIRouter` einbinden, sodass alle seine *Pfadoperationen* mit `/admin` beginnen, wir möchten es mit den `dependencies` sichern, die wir bereits für dieses Projekt haben, und wir möchten `tags` und `responses` hinzufügen. + +Wir können das alles deklarieren, ohne den ursprünglichen `APIRouter` ändern zu müssen, indem wir diese Parameter an `app.include_router()` übergeben: + +{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[14:17] title["app/main.py"] *} + +Auf diese Weise bleibt der ursprüngliche `APIRouter` unverändert, sodass wir dieselbe `app/internal/admin.py`-Datei weiterhin mit anderen Projekten in der Organisation teilen können. + +Das Ergebnis ist, dass in unserer Anwendung jede der *Pfadoperationen* aus dem Modul `admin` Folgendes haben wird: + +* Das Präfix `/admin`. +* Den Tag `admin`. +* Die Abhängigkeit `get_token_header`. +* Die Response `418`. 🍵 + +Dies wirkt sich jedoch nur auf diesen `APIRouter` in unserer Anwendung aus, nicht auf anderen Code, der ihn verwendet. + +So könnten beispielsweise andere Projekte denselben `APIRouter` mit einer anderen Authentifizierungsmethode verwenden. + +### Eine *Pfadoperation* hinzufügen { #include-a-path-operation } + +Wir können *Pfadoperationen* auch direkt zur `FastAPI`-App hinzufügen. + +Hier machen wir es ... nur um zu zeigen, dass wir es können 🤷: + +{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[21:23] title["app/main.py"] *} + +und es wird korrekt funktionieren, zusammen mit allen anderen *Pfadoperationen*, die mit `app.include_router()` hinzugefügt wurden. + +/// note | Sehr technische Details + +**Hinweis**: Dies ist ein sehr technisches Detail, das Sie wahrscheinlich **einfach überspringen** können. + +--- + +Die `APIRouter` sind nicht „gemountet“, sie sind nicht vom Rest der Anwendung isoliert. + +Das liegt daran, dass wir ihre *Pfadoperationen* im OpenAPI-Schema und in den Benutzeroberflächen inkludieren möchten. + +FastAPI behält die ursprünglichen Router und Pfadoperationen aktiv und kombiniert Router-Präfixe, Abhängigkeiten, Tags, Responses und weitere Metadaten beim Bearbeiten von Requests und beim Generieren von OpenAPI. + +/// + +## Den `entrypoint` in `pyproject.toml` konfigurieren { #configure-the-entrypoint-in-pyproject-toml } + +Da Ihr FastAPI-`app`-Objekt in `app/main.py` liegt, können Sie den `entrypoint` in Ihrer `pyproject.toml`-Datei so konfigurieren: + +```toml +[tool.fastapi] +entrypoint = "app.main:app" +``` + +das entspricht einem Import wie: + +```python +from app.main import app +``` + +Auf diese Weise weiß der `fastapi`-Befehl, wo er Ihre App findet. + +/// Note | Hinweis + +Sie könnten auch den Pfad an den Befehl übergeben, etwa: + +```console +$ fastapi dev app/main.py +``` + +Aber dann müssten Sie sich jedes Mal, wenn Sie den `fastapi`-Befehl aufrufen, an den korrekten Pfad erinnern. + +Außerdem finden andere Tools Ihre App womöglich nicht, zum Beispiel die [VS Code-Erweiterung](../editor-support.md) oder [FastAPI Cloud](https://fastapicloud.com). Daher wird empfohlen, den `entrypoint` in `pyproject.toml` zu verwenden. + +/// + +## Die automatische API-Dokumentation prüfen { #check-the-automatic-api-docs } + +Führen Sie nun Ihre App aus: + +
+ +```console +$ fastapi dev + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +Und öffnen Sie die Dokumentation unter [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs). + +Sie sehen die automatische API-Dokumentation, einschließlich der Pfade aller Submodule, mit den richtigen Pfaden (und Präfixen) und den richtigen Tags: + + + +## Den gleichen Router mehrmals mit unterschiedlichem `prefix` inkludieren { #include-the-same-router-multiple-times-with-different-prefix } + +Sie können `.include_router()` auch mehrmals mit *demselben* Router und unterschiedlichen Präfixen verwenden. + +Dies könnte beispielsweise nützlich sein, um dieselbe API unter verschiedenen Präfixen verfügbar zu machen, z. B. `/api/v1` und `/api/latest`. + +Dies ist eine fortgeschrittene Verwendung, die Sie möglicherweise nicht wirklich benötigen, aber für den Fall, dass Sie sie benötigen, ist sie vorhanden. + +## Einen `APIRouter` in einen anderen einfügen { #include-an-apirouter-in-another } + +Auf die gleiche Weise, wie Sie einen `APIRouter` in eine `FastAPI`-Anwendung einbinden können, können Sie einen `APIRouter` in einen anderen `APIRouter` einbinden, indem Sie Folgendes verwenden: + +```Python +router.include_router(other_router) +``` + +Sie können dies vor oder nach dem Einbinden von `router` in die `FastAPI`-App tun. FastAPI inkludiert die *Pfadoperationen* von `other_router` dennoch in Routing und OpenAPI. + +Gleiches gilt für später zu den Routern hinzugefügte *Pfadoperationen*. Sie sind auch über die frühere Inklusion sichtbar. + +/// warning | Technische Details + +Vermeiden Sie es, `router.routes` direkt zu mutieren, nachdem ein Router inkludiert wurde. FastAPI behandelt Router-Inklusion als „live“, sodass der ursprüngliche Router und seine Routen Teil des Routings und der OpenAPI-Generierung bleiben. + +Verwenden Sie dokumentierte APIs wie Pfadoperation-Dekoratoren und `.include_router()`, um Routen und Router hinzuzufügen. + +Betrachten Sie `router.routes` als eine Low-Level-Routenstruktur, die sowohl Routendefinitionen als auch inkludierte Router enthalten kann, und verlassen Sie sich nicht darauf als flache Liste endgültiger Pfadoperationen. + +/// diff --git a/docs/de/docs/tutorial/body-fields.md b/docs/de/docs/tutorial/body-fields.md new file mode 100644 index 0000000000000..4edb22478bd31 --- /dev/null +++ b/docs/de/docs/tutorial/body-fields.md @@ -0,0 +1,59 @@ +# Body – Felder { #body-fields } + +So wie Sie zusätzliche Validierung und Metadaten in Parametern der *Pfadoperation-Funktion* mittels `Query`, `Path` und `Body` deklarieren, können Sie auch innerhalb von Pydantic-Modellen zusätzliche Validierung und Metadaten deklarieren, mittels Pydantics `Field`. + +## `Field` importieren { #import-field } + +Importieren Sie es zuerst: + +{* ../../docs_src/body_fields/tutorial001_an_py310.py hl[4] *} + +/// warning | Achtung + +Beachten Sie, dass `Field` direkt von `pydantic` importiert wird, nicht von `fastapi`, wie die anderen (`Query`, `Path`, `Body`, usw.) + +/// + +## Modellattribute deklarieren { #declare-model-attributes } + +Dann können Sie `Field` mit Modellattributen deklarieren: + +{* ../../docs_src/body_fields/tutorial001_an_py310.py hl[11:14] *} + +`Field` funktioniert genauso wie `Query`, `Path` und `Body`, es hat die gleichen Parameter, usw. + +/// note | Technische Details + +Tatsächlich erstellen `Query`, `Path` und andere, die Sie als nächstes sehen werden, Instanzen von Unterklassen einer allgemeinen Klasse `Param`, welche selbst eine Unterklasse von Pydantics `FieldInfo`-Klasse ist. + +Und Pydantics `Field` gibt ebenfalls eine Instanz von `FieldInfo` zurück. + +`Body` gibt auch direkt Instanzen einer Unterklasse von `FieldInfo` zurück. Später werden Sie andere sehen, die Unterklassen der `Body`-Klasse sind. + +Denken Sie daran, dass `Query`, `Path` und andere, wenn Sie sie von `fastapi` importieren, tatsächlich Funktionen sind, die spezielle Klassen zurückgeben. + +/// + +/// tip | Tipp + +Beachten Sie, wie jedes Attribut eines Modells mit einem Typ, Defaultwert und `Field` die gleiche Struktur hat wie ein Parameter einer *Pfadoperation-Funktion*, nur mit `Field` statt `Path`, `Query`, `Body`. + +/// + +## Zusätzliche Information hinzufügen { #add-extra-information } + +Sie können zusätzliche Information in `Field`, `Query`, `Body`, usw. deklarieren. Und es wird im generierten JSON-Schema untergebracht. + +Sie werden später in der Dokumentation mehr darüber lernen, wie man zusätzliche Information unterbringt, wenn Sie lernen, Beispiele zu deklarieren. + +/// warning | Achtung + +Extra-Schlüssel, die `Field` überreicht werden, werden auch im resultierenden OpenAPI-Schema Ihrer Anwendung gelistet. Da diese Schlüssel möglicherweise nicht Teil der OpenAPI-Spezifikation sind, könnten einige OpenAPI-Tools, wie etwa [der OpenAPI-Validator](https://validator.swagger.io/), nicht mit Ihrem generierten Schema funktionieren. + +/// + +## Zusammenfassung { #recap } + +Sie können Pydantics `Field` verwenden, um zusätzliche Validierungen und Metadaten für Modellattribute zu deklarieren. + +Sie können auch die zusätzlichen Schlüsselwortargumente verwenden, um zusätzliche JSON-Schema-Metadaten zu übergeben. diff --git a/docs/de/docs/tutorial/body-multiple-params.md b/docs/de/docs/tutorial/body-multiple-params.md new file mode 100644 index 0000000000000..2d5765dcddc39 --- /dev/null +++ b/docs/de/docs/tutorial/body-multiple-params.md @@ -0,0 +1,165 @@ +# Body – Mehrere Parameter { #body-multiple-parameters } + +Nun, da wir gesehen haben, wie `Path` und `Query` verwendet werden, schauen wir uns fortgeschrittenere Verwendungsmöglichkeiten von Requestbody-Deklarationen an. + +## `Path`-, `Query`- und Body-Parameter vermischen { #mix-path-query-and-body-parameters } + +Zuerst einmal, Sie können `Path`-, `Query`- und Requestbody-Parameter-Deklarationen frei mischen und **FastAPI** wird wissen, was zu tun ist. + +Und Sie können auch Body-Parameter als optional kennzeichnen, indem Sie den Defaultwert auf `None` setzen: + +{* ../../docs_src/body_multiple_params/tutorial001_an_py310.py hl[18:20] *} + +/// note | Hinweis + +Beachten Sie, dass in diesem Fall das `item`, welches vom Body genommen wird, optional ist. Da es `None` als Defaultwert hat. + +/// + +## Mehrere Body-Parameter { #multiple-body-parameters } + +Im vorherigen Beispiel erwarteten die *Pfadoperationen* einen JSON-Body mit den Attributen eines `Item`s, etwa: + +```JSON +{ + "name": "Foo", + "description": "The pretender", + "price": 42.0, + "tax": 3.2 +} +``` + +Aber Sie können auch mehrere Body-Parameter deklarieren, z. B. `item` und `user`: + +{* ../../docs_src/body_multiple_params/tutorial002_py310.py hl[20] *} + +In diesem Fall wird **FastAPI** bemerken, dass es mehr als einen Body-Parameter in der Funktion gibt (zwei Parameter, die Pydantic-Modelle sind). + +Es wird deshalb die Parameternamen als Schlüssel (Feldnamen) im Body verwenden und erwartet einen Body wie folgt: + +```JSON +{ + "item": { + "name": "Foo", + "description": "The pretender", + "price": 42.0, + "tax": 3.2 + }, + "user": { + "username": "dave", + "full_name": "Dave Grohl" + } +} +``` + +/// note | Hinweis + +Beachten Sie, dass, obwohl `item` wie zuvor deklariert wurde, es nun unter einem Schlüssel `item` im Body erwartet wird. + +/// + +**FastAPI** wird die automatische Konvertierung des Requests übernehmen, sodass der Parameter `item` seinen spezifischen Inhalt bekommt, und das Gleiche gilt für den Parameter `user`. + +Es wird die Validierung dieser zusammengesetzten Daten übernehmen, und diese im OpenAPI-Schema und der automatischen Dokumentation dokumentieren. + +## Einzelne Werte im Body { #singular-values-in-body } + +So wie `Query` und `Path` für Query- und Pfad-Parameter, stellt **FastAPI** das Äquivalent `Body` zur Verfügung, um Extra-Daten für Body-Parameter zu definieren. + +Zum Beispiel, das vorherige Modell erweiternd, könnten Sie entscheiden, dass Sie einen weiteren Schlüssel `importance` im selben Body haben möchten, neben `item` und `user`. + +Wenn Sie diesen Parameter einfach so hinzufügen, wird **FastAPI** annehmen, dass es ein Query-Parameter ist, da er ein einzelner Wert ist. + +Aber Sie können **FastAPI** instruieren, ihn als weiteren Body-Schlüssel zu erkennen, indem Sie `Body` verwenden: + +{* ../../docs_src/body_multiple_params/tutorial003_an_py310.py hl[23] *} + +In diesem Fall erwartet **FastAPI** einen Body wie: + +```JSON +{ + "item": { + "name": "Foo", + "description": "The pretender", + "price": 42.0, + "tax": 3.2 + }, + "user": { + "username": "dave", + "full_name": "Dave Grohl" + }, + "importance": 5 +} +``` + +Wiederum wird es die Datentypen konvertieren, validieren, dokumentieren, usw. + +## Mehrere Body-Parameter und Query-Parameter { #multiple-body-params-and-query } + +Natürlich können Sie auch, wann immer Sie das brauchen, weitere Query-Parameter hinzufügen, zusätzlich zu den Body-Parametern. + +Da einfache Werte standardmäßig als Query-Parameter interpretiert werden, müssen Sie `Query` nicht explizit hinzufügen, Sie können einfach schreiben: + +```Python +q: str | None = None +``` + +Zum Beispiel: + +{* ../../docs_src/body_multiple_params/tutorial004_an_py310.py hl[28] *} + +/// note | Hinweis + +`Body` hat die gleichen zusätzlichen Validierungs- und Metadaten-Parameter wie `Query`, `Path` und andere, die Sie später kennenlernen werden. + +/// + +## Einen einzelnen Body-Parameter einbetten { #embed-a-single-body-parameter } + +Nehmen wir an, Sie haben nur einen einzelnen `item`-Body-Parameter von einem Pydantic-Modell `Item`. + +Standardmäßig wird **FastAPI** dann seinen Body direkt erwarten. + +Aber wenn Sie möchten, dass es einen JSON-Body mit einem Schlüssel `item` erwartet, und darin den Inhalt des Modells, so wie es das tut, wenn Sie mehrere Body-Parameter deklarieren, dann können Sie den speziellen `Body`-Parameter `embed` setzen: + +```Python +item: Annotated[Item, Body(embed=True)] +``` + +so wie in: + +{* ../../docs_src/body_multiple_params/tutorial005_an_py310.py hl[17] *} + +In diesem Fall erwartet **FastAPI** einen Body wie: + +```JSON hl_lines="2" +{ + "item": { + "name": "Foo", + "description": "The pretender", + "price": 42.0, + "tax": 3.2 + } +} +``` + +statt: + +```JSON +{ + "name": "Foo", + "description": "The pretender", + "price": 42.0, + "tax": 3.2 +} +``` + +## Zusammenfassung { #recap } + +Sie können mehrere Body-Parameter zu Ihrer *Pfadoperation-Funktion* hinzufügen, obwohl ein Request nur einen einzigen Body enthalten kann. + +Aber **FastAPI** wird sich darum kümmern, Ihnen korrekte Daten in Ihrer Funktion zu überreichen, und das korrekte Schema in der *Pfadoperation* zu validieren und zu dokumentieren. + +Sie können auch einzelne Werte deklarieren, die als Teil des Bodys empfangen werden. + +Und Sie können **FastAPI** instruieren, den Body in einem Schlüssel unterzubringen, selbst wenn nur ein einzelner Body-Parameter deklariert ist. diff --git a/docs/de/docs/tutorial/body-nested-models.md b/docs/de/docs/tutorial/body-nested-models.md new file mode 100644 index 0000000000000..f95b65e574564 --- /dev/null +++ b/docs/de/docs/tutorial/body-nested-models.md @@ -0,0 +1,221 @@ +# Body – Verschachtelte Modelle { #body-nested-models } + +Mit **FastAPI** können Sie (dank Pydantic) beliebig tief verschachtelte Modelle definieren, validieren, dokumentieren und verwenden. + +## Listen als Felder { #list-fields } + +Sie können ein Attribut als Kindtyp definieren. Zum Beispiel eine Python-`list`: + +{* ../../docs_src/body_nested_models/tutorial001_py310.py hl[12] *} + +Das bewirkt, dass `tags` eine Liste ist, wenngleich es nichts über den Typ der Elemente der Liste aussagt. + +## Listen mit Typ-Parametern als Felder { #list-fields-with-type-parameter } + +Aber Python hat eine spezifische Möglichkeit, Listen mit inneren Typen, auch „Typ-Parameter“ genannt, zu deklarieren: + +### Eine `list` mit einem Typ-Parameter deklarieren { #declare-a-list-with-a-type-parameter } + +Um Typen zu deklarieren, die Typ-Parameter (innere Typen) haben, wie `list`, `dict`, `tuple`, +übergeben Sie den/die inneren Typ(en) als „Typ-Parameter“ in eckigen Klammern: `[` und `]` + +```Python +my_list: list[str] +``` + +Das ist alles Standard-Python-Syntax für Typdeklarationen. + +Verwenden Sie dieselbe Standardsyntax für Modellattribute mit inneren Typen. + +In unserem Beispiel können wir also bewirken, dass `tags` spezifisch eine „Liste von Strings“ ist: + +{* ../../docs_src/body_nested_models/tutorial002_py310.py hl[12] *} + +## Set-Typen { #set-types } + +Aber dann denken wir darüber nach und stellen fest, dass sich die Tags nicht wiederholen sollten, sie wären wahrscheinlich eindeutige Strings. + +Und Python hat einen speziellen Datentyp für Mengen eindeutiger Elemente, das `set`. + +Dann können wir `tags` als Set von Strings deklarieren: + +{* ../../docs_src/body_nested_models/tutorial003_py310.py hl[12] *} + +Damit wird, selbst wenn Sie einen Request mit duplizierten Daten erhalten, dieser zu einem Set eindeutiger Elemente konvertiert. + +Und wann immer Sie diese Daten ausgeben, selbst wenn die Quelle Duplikate hatte, wird es als Set von eindeutigen Elementen ausgegeben. + +Und es wird entsprechend annotiert / dokumentiert. + +## Verschachtelte Modelle { #nested-models } + +Jedes Attribut eines Pydantic-Modells hat einen Typ. + +Aber dieser Typ kann selbst ein anderes Pydantic-Modell sein. + +Sie können also tief verschachtelte JSON-„Objekte“ deklarieren, mit spezifischen Attributnamen, Typen und Validierungen. + +Alles das beliebig tief verschachtelt. + +### Ein Kindmodell definieren { #define-a-submodel } + +Zum Beispiel können wir ein `Image`-Modell definieren: + +{* ../../docs_src/body_nested_models/tutorial004_py310.py hl[7:9] *} + +### Das Kindmodell als Typ verwenden { #use-the-submodel-as-a-type } + +Und dann können wir es als Typ eines Attributes verwenden: + +{* ../../docs_src/body_nested_models/tutorial004_py310.py hl[18] *} + +Das würde bedeuten, dass **FastAPI** einen Body ähnlich dem folgenden erwartet: + +```JSON +{ + "name": "Foo", + "description": "The pretender", + "price": 42.0, + "tax": 3.2, + "tags": ["rock", "metal", "bar"], + "image": { + "url": "http://example.com/baz.jpg", + "name": "The Foo live" + } +} +``` + +Wiederum, nur mit dieser Deklaration erhalten Sie mit **FastAPI**: + +* Editor-Unterstützung (Codevervollständigung, usw.), selbst für verschachtelte Modelle +* Datenkonvertierung +* Datenvalidierung +* Automatische Dokumentation + +## Spezielle Typen und Validierungen { #special-types-and-validation } + +Abgesehen von normalen einfachen Typen wie `str`, `int`, `float`, usw. können Sie komplexere einfache Typen verwenden, die von `str` erben. + +Um alle Optionen kennenzulernen, die Sie haben, schauen Sie sich [Pydantics Typübersicht](https://docs.pydantic.dev/latest/concepts/types/) an. Sie werden einige Beispiele im nächsten Kapitel kennenlernen. + +Zum Beispiel, da wir im `Image`-Modell ein Feld `url` haben, können wir deklarieren, dass das eine Instanz von Pydantics `HttpUrl` sein soll, anstelle eines `str`: + +{* ../../docs_src/body_nested_models/tutorial005_py310.py hl[2,8] *} + +Es wird getestet, ob der String eine gültige URL ist, und als solche wird er in JSON Schema / OpenAPI dokumentiert. + +## Attribute mit Listen von Kindmodellen { #attributes-with-lists-of-submodels } + +Sie können Pydantic-Modelle auch als Kindtypen von `list`, `set`, usw. verwenden: + +{* ../../docs_src/body_nested_models/tutorial006_py310.py hl[18] *} + +Das wird einen JSON-Body erwarten (konvertieren, validieren, dokumentieren, usw.) wie: + +```JSON hl_lines="11" +{ + "name": "Foo", + "description": "The pretender", + "price": 42.0, + "tax": 3.2, + "tags": [ + "rock", + "metal", + "bar" + ], + "images": [ + { + "url": "http://example.com/baz.jpg", + "name": "The Foo live" + }, + { + "url": "http://example.com/dave.jpg", + "name": "The Baz" + } + ] +} +``` + +/// note | Hinweis + +Beachten Sie, dass der `images`-Schlüssel jetzt eine Liste von Bild-Objekten hat. + +/// + +## Tief verschachtelte Modelle { #deeply-nested-models } + +Sie können beliebig tief verschachtelte Modelle definieren: + +{* ../../docs_src/body_nested_models/tutorial007_py310.py hl[7,12,18,21,25] *} + +/// note | Hinweis + +Beachten Sie, wie `Offer` eine Liste von `Item`s hat, die ihrerseits eine optionale Liste von `Image`s haben + +/// + +## Bodys aus reinen Listen { #bodies-of-pure-lists } + +Wenn der Wert auf oberster Ebene des JSON-Bodys, den Sie erwarten, ein JSON-`array` (eine Python-`list`) ist, können Sie den Typ im Parameter der Funktion deklarieren, genau wie in Pydantic-Modellen: + +```Python +images: list[Image] +``` + +so wie in: + +{* ../../docs_src/body_nested_models/tutorial008_py310.py hl[13] *} + +## Editor-Unterstützung überall { #editor-support-everywhere } + +Und Sie erhalten Editor-Unterstützung überall. + +Selbst für Elemente innerhalb von Listen: + + + +Sie würden diese Art von Editor-Unterstützung nicht erhalten, wenn Sie direkt mit `dict`, statt mit Pydantic-Modellen arbeiten würden. + +Aber Sie müssen sich auch nicht um diese kümmern, hereinkommende Dicts werden automatisch konvertiert und Ihre Ausgabe wird ebenfalls automatisch nach JSON konvertiert. + +## Bodys mit beliebigen `dict`s { #bodies-of-arbitrary-dicts } + +Sie können einen Body auch als `dict` deklarieren, mit Schlüsseln eines Typs und Werten eines anderen Typs. + +So brauchen Sie vorher nicht zu wissen, wie die gültigen Feld-/Attributnamen lauten (wie es bei Pydantic-Modellen der Fall wäre). + +Das ist nützlich, wenn Sie Schlüssel empfangen wollen, die Sie nicht bereits kennen. + +--- + +Ein anderer nützlicher Anwendungsfall ist, wenn Sie Schlüssel eines anderen Typs haben wollen, z. B. `int`. + +Das schauen wir uns hier an. + +In diesem Fall akzeptieren Sie irgendein `dict`, solange es `int`-Schlüssel mit `float`-Werten hat: + +{* ../../docs_src/body_nested_models/tutorial009_py310.py hl[7] *} + +/// tip | Tipp + +Bedenken Sie, dass JSON nur `str` als Schlüssel unterstützt. + +Aber Pydantic hat automatische Datenkonvertierung. + +Das bedeutet, dass Ihre API-Clients zwar nur Strings als Schlüssel senden können, Pydantic diese aber konvertieren und validieren wird, solange diese Strings nur Ganzzahlen enthalten. + +Und das `dict`, welches Sie als `weights` erhalten, wird tatsächlich `int`-Schlüssel und `float`-Werte haben. + +/// + +## Zusammenfassung { #recap } + +Mit **FastAPI** haben Sie die maximale Flexibilität von Pydantic-Modellen, während Ihr Code einfach, kurz und elegant bleibt. + +Aber mit all den Vorzügen: + +* Editor-Unterstützung (Codevervollständigung überall!) +* Datenkonvertierung (auch bekannt als Parsen / Serialisierung) +* Datenvalidierung +* Schema-Dokumentation +* Automatische Dokumentation diff --git a/docs/de/docs/tutorial/body-updates.md b/docs/de/docs/tutorial/body-updates.md new file mode 100644 index 0000000000000..ef46f19f68e86 --- /dev/null +++ b/docs/de/docs/tutorial/body-updates.md @@ -0,0 +1,100 @@ +# Body – Aktualisierungen { #body-updates } + +## Ersetzendes Aktualisieren mit `PUT` { #update-replacing-with-put } + +Um einen Artikel zu aktualisieren, können Sie die [HTTP `PUT`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PUT) Operation verwenden. + +Sie können den `jsonable_encoder` verwenden, um die empfangenen Daten in etwas zu konvertieren, das als JSON gespeichert werden kann (z. B. in einer NoSQL-Datenbank). Zum Beispiel, um ein `datetime` in einen `str` zu konvertieren. + +{* ../../docs_src/body_updates/tutorial001_py310.py hl[28:33] *} + +`PUT` wird verwendet, um Daten zu empfangen, die die existierenden Daten ersetzen sollen. + +### Warnung bezüglich des Ersetzens { #warning-about-replacing } + +Das bedeutet, dass, wenn Sie den Artikel `bar` aktualisieren wollen, mittels `PUT` und folgendem Body: + +```Python +{ + "name": "Barz", + "price": 3, + "description": None, +} +``` + +weil das bereits gespeicherte Attribut `"tax": 20.2` nicht enthalten ist, das Eingabemodell den Defaultwert `"tax": 10.5` erhalten würde. + +Und die Daten würden mit diesem „neuen“ `tax` von `10.5` gespeichert werden. + +## Teil-Aktualisierungen mit `PATCH` { #partial-updates-with-patch } + +Sie können auch die [HTTP `PATCH`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PATCH) Operation verwenden, um Daten *teilweise* zu ersetzen. + +Das bedeutet, Sie senden nur die Daten, die Sie aktualisieren wollen, der Rest bleibt unverändert. + +/// note | Hinweis + +`PATCH` wird seltener verwendet und ist weniger bekannt als `PUT`. + +Und viele Teams verwenden ausschließlich `PUT`, selbst für nur Teil-Aktualisierungen. + +Es steht Ihnen **frei**, das zu verwenden, was Sie möchten, **FastAPI** legt Ihnen keine Einschränkungen auf. + +Aber dieser Leitfaden zeigt Ihnen mehr oder weniger, wie die beiden normalerweise verwendet werden. + +/// + +### Pydantics `exclude_unset`-Parameter verwenden { #using-pydantics-exclude-unset-parameter } + +Wenn Sie Teil-Aktualisierungen entgegennehmen, ist der `exclude_unset`-Parameter in der `.model_dump()`-Methode von Pydantic-Modellen sehr nützlich. + +Wie in `item.model_dump(exclude_unset=True)`. + +Das wird ein `dict` erstellen, mit nur den Daten, die gesetzt wurden, als das `item`-Modell erstellt wurde, Defaultwerte ausgeschlossen. + +Sie können das verwenden, um ein `dict` zu erstellen, das nur die (im Request) gesendeten Daten enthält, ohne Defaultwerte: + +{* ../../docs_src/body_updates/tutorial002_py310.py hl[32] *} + +### Pydantics `update`-Parameter verwenden { #using-pydantics-update-parameter } + +Jetzt können Sie eine Kopie des existierenden Modells mittels `.model_copy()` erstellen, wobei Sie dem `update`-Parameter ein `dict` mit den zu ändernden Daten übergeben. + +Wie in `stored_item_model.model_copy(update=update_data)`: + +{* ../../docs_src/body_updates/tutorial002_py310.py hl[33] *} + +### Rekapitulation zu Teil-Aktualisierungen { #partial-updates-recap } + +Zusammengefasst, um Teil-Aktualisierungen vorzunehmen: + +* (Optional) verwenden Sie `PATCH` statt `PUT`. +* Lesen Sie die bereits gespeicherten Daten aus. +* Fügen Sie diese in ein Pydantic-Modell ein. +* Erzeugen Sie aus dem empfangenen Modell ein `dict` ohne Defaultwerte (mittels `exclude_unset`). + * So ersetzen Sie nur die tatsächlich vom Benutzer gesetzten Werte, statt dass bereits gespeicherte Werte mit Defaultwerten des Modells überschrieben werden. +* Erzeugen Sie eine Kopie ihres gespeicherten Modells, wobei Sie die Attribute mit den empfangenen Teil-Ersetzungen aktualisieren (mittels des `update`-Parameters). +* Konvertieren Sie das kopierte Modell zu etwas, das in Ihrer Datenbank gespeichert werden kann (indem Sie beispielsweise `jsonable_encoder` verwenden). + * Das ist vergleichbar dazu, die `.model_dump()`-Methode des Modells erneut aufzurufen, aber es wird sicherstellen, dass die Werte zu Daten konvertiert werden, die ihrerseits zu JSON konvertiert werden können, zum Beispiel `datetime` zu `str`. +* Speichern Sie die Daten in Ihrer Datenbank. +* Geben Sie das aktualisierte Modell zurück. + +{* ../../docs_src/body_updates/tutorial002_py310.py hl[28:35] *} + +/// tip | Tipp + +Sie können tatsächlich die gleiche Technik mit einer HTTP `PUT` Operation verwenden. + +Aber dieses Beispiel verwendet `PATCH`, da dieses für solche Anwendungsfälle geschaffen wurde. + +/// + +/// note | Hinweis + +Beachten Sie, dass das hereinkommende Modell immer noch validiert wird. + +Wenn Sie also Teil-Aktualisierungen empfangen wollen, die alle Attribute auslassen können, müssen Sie ein Modell haben, dessen Attribute alle als optional gekennzeichnet sind (mit Defaultwerten oder `None`). + +Um zu unterscheiden zwischen Modellen für **Aktualisierungen**, mit lauter optionalen Werten, und solchen für die **Erzeugung**, mit benötigten Werten, können Sie die Techniken verwenden, die in [Extramodelle](extra-models.md) beschrieben wurden. + +/// diff --git a/docs/de/docs/tutorial/body.md b/docs/de/docs/tutorial/body.md new file mode 100644 index 0000000000000..6ced5f732ec32 --- /dev/null +++ b/docs/de/docs/tutorial/body.md @@ -0,0 +1,166 @@ +# Requestbody { #request-body } + +Wenn Sie Daten von einem Client (sagen wir, einem Browser) zu Ihrer API senden müssen, senden Sie sie als **Requestbody**. + +Ein **Request**body sind Daten, die vom Client zu Ihrer API gesendet werden. Ein **Response**body sind Daten, die Ihre API zum Client sendet. + +Ihre API muss fast immer einen **Response**body senden. Aber Clients müssen nicht unbedingt immer **Requestbodys** senden, manchmal fordern sie nur einen Pfad an, vielleicht mit einigen Query-Parametern, aber senden keinen Body. + +Um einen **Request**body zu deklarieren, verwenden Sie [Pydantic](https://docs.pydantic.dev/)-Modelle mit all deren Fähigkeiten und Vorzügen. + +/// note | Hinweis + +Um Daten zu senden, sollten Sie eines von: `POST` (meistverwendet), `PUT`, `DELETE` oder `PATCH` verwenden. + +Das Senden eines Bodys mit einem `GET`-Request hat ein undefiniertes Verhalten in den Spezifikationen, wird aber dennoch von FastAPI unterstützt, nur für sehr komplexe/extreme Anwendungsfälle. + +Da davon abgeraten wird, zeigt die interaktive Dokumentation mit Swagger UI die Dokumentation für den Body nicht an, wenn `GET` verwendet wird, und zwischengeschaltete Proxys unterstützen es möglicherweise nicht. + +/// + +## Pydantics `BaseModel` importieren { #import-pydantics-basemodel } + +Zuerst müssen Sie `BaseModel` von `pydantic` importieren: + +{* ../../docs_src/body/tutorial001_py310.py hl[2] *} + +## Ihr Datenmodell erstellen { #create-your-data-model } + +Dann deklarieren Sie Ihr Datenmodell als eine Klasse, die von `BaseModel` erbt. + +Verwenden Sie Standard-Python-Typen für alle Attribute: + +{* ../../docs_src/body/tutorial001_py310.py hl[5:9] *} + + +Wie auch bei der Deklaration von Query-Parametern gilt: Wenn ein Modellattribut einen Defaultwert hat, ist das Attribut nicht erforderlich. Andernfalls ist es erforderlich. Verwenden Sie `None`, um es einfach optional zu machen. + +Zum Beispiel deklariert das obige Modell ein JSON „`object`“ (oder Python-`dict`) wie dieses: + +```JSON +{ + "name": "Foo", + "description": "An optional description", + "price": 45.2, + "tax": 3.5 +} +``` + +... da `description` und `tax` optional sind (mit `None` als Defaultwert), wäre dieses JSON „`object`“ ebenfalls gültig: + +```JSON +{ + "name": "Foo", + "price": 45.2 +} +``` + +## Als Parameter deklarieren { #declare-it-as-a-parameter } + +Um es zu Ihrer *Pfadoperation* hinzuzufügen, deklarieren Sie es auf die gleiche Weise, wie Sie Pfad- und Query-Parameter deklariert haben: + +{* ../../docs_src/body/tutorial001_py310.py hl[16] *} + +... und deklarieren Sie dessen Typ als das Modell, welches Sie erstellt haben, `Item`. + +## Resultate { #results } + +Mit nur dieser Python-Typdeklaration wird **FastAPI**: + +* Den Requestbody als JSON lesen. +* Die entsprechenden Typen konvertieren (falls nötig). +* Diese Daten validieren. + * Wenn die Daten ungültig sind, wird ein klar lesbarer Fehler zurückgegeben, der genau anzeigt, wo und was die inkorrekten Daten sind. +* Ihnen die erhaltenen Daten im Parameter `item` übergeben. + * Da Sie ihn in der Funktion als vom Typ `Item` deklariert haben, erhalten Sie auch die volle Unterstützung des Editors (Autovervollständigung, usw.) für alle Attribute und deren Typen. +* [JSON Schema](https://json-schema.org)-Definitionen für Ihr Modell generieren, die Sie auch überall sonst verwenden können, wenn es für Ihr Projekt Sinn macht. +* Diese Schemas werden Teil des generierten OpenAPI-Schemas und werden von den UIs der automatischen Dokumentation genutzt. + +## Automatische Dokumentation { #automatic-docs } + +Die JSON-Schemas Ihrer Modelle werden Teil Ihres OpenAPI-generierten Schemas und in der interaktiven API-Dokumentation angezeigt: + + + +Und werden auch in der API-Dokumentation innerhalb jeder *Pfadoperation*, die sie benötigt, verwendet: + + + +## Editor-Unterstützung { #editor-support } + +In Ihrem Editor erhalten Sie innerhalb Ihrer Funktion Typhinweise und Code-Vervollständigung überall (was nicht der Fall wäre, wenn Sie ein `dict` anstelle eines Pydantic-Modells erhalten hätten): + + + +Sie bekommen auch Fehlermeldungen für inkorrekte Typoperationen: + + + +Das ist nicht zufällig so, das ganze Framework wurde um dieses Design herum aufgebaut. + +Und es wurde in der Designphase gründlich getestet, bevor irgendeine Implementierung stattfand, um sicherzustellen, dass es mit allen Editoren funktioniert. + +Es gab sogar einige Änderungen an Pydantic selbst, um dies zu unterstützen. + +Die vorherigen Screenshots wurden mit [Visual Studio Code](https://code.visualstudio.com) aufgenommen. + +Aber Sie würden die gleiche Editor-Unterstützung in [PyCharm](https://www.jetbrains.com/pycharm/) und den meisten anderen Python-Editoren erhalten: + + + +/// tip | Tipp + +Wenn Sie [PyCharm](https://www.jetbrains.com/pycharm/) als Ihren Editor verwenden, können Sie das [Pydantic PyCharm Plugin](https://github.com/koxudaxi/pydantic-pycharm-plugin/) verwenden. + +Es verbessert die Editor-Unterstützung für Pydantic-Modelle, mit: + +* Code-Vervollständigung +* Typüberprüfungen +* Refaktorisierung +* Suche +* Inspektionen + +/// + +## Das Modell verwenden { #use-the-model } + +Innerhalb der Funktion können Sie alle Attribute des Modellobjekts direkt verwenden: + +{* ../../docs_src/body/tutorial002_py310.py *} + +## Requestbody + Pfad-Parameter { #request-body-path-parameters } + +Sie können Pfad-Parameter und den Requestbody gleichzeitig deklarieren. + +**FastAPI** erkennt, dass Funktionsparameter, die mit Pfad-Parametern übereinstimmen, **vom Pfad genommen** werden sollen, und dass Funktionsparameter, welche Pydantic-Modelle sind, **vom Requestbody genommen** werden sollen. + +{* ../../docs_src/body/tutorial003_py310.py hl[15:16] *} + + +## Requestbody + Pfad- + Query-Parameter { #request-body-path-query-parameters } + +Sie können auch zur gleichen Zeit **Body-**, **Pfad-** und **Query-Parameter** deklarieren. + +**FastAPI** wird jeden von ihnen korrekt erkennen und die Daten vom richtigen Ort holen. + +{* ../../docs_src/body/tutorial004_py310.py hl[16] *} + +Die Funktionsparameter werden wie folgt erkannt: + +* Wenn der Parameter auch im **Pfad** deklariert wurde, wird er als Pfad-Parameter verwendet. +* Wenn der Parameter ein **einfacher Typ** ist (wie `int`, `float`, `str`, `bool`, usw.), wird er als **Query**-Parameter interpretiert. +* Wenn der Parameter vom Typ eines **Pydantic-Modells** ist, wird er als Request**body** interpretiert. + +/// note | Hinweis + +FastAPI weiß, dass der Wert von `q` nicht erforderlich ist, aufgrund des Defaultwertes `= None`. + +Das `str | None` wird von FastAPI nicht verwendet, um zu bestimmen, dass der Wert nicht erforderlich ist. FastAPI weiß, dass er nicht erforderlich ist, weil er einen Defaultwert von `= None` hat. + +Das Hinzufügen der Typannotationen ermöglicht jedoch Ihrem Editor, Ihnen eine bessere Unterstützung zu bieten und Fehler zu erkennen. + +/// + +## Ohne Pydantic { #without-pydantic } + +Wenn Sie keine Pydantic-Modelle verwenden möchten, können Sie auch **Body**-Parameter verwenden. Siehe die Dokumentation unter [Body – Mehrere Parameter: Einfache Werte im Body](body-multiple-params.md#singular-values-in-body). diff --git a/docs/de/docs/tutorial/cookie-param-models.md b/docs/de/docs/tutorial/cookie-param-models.md new file mode 100644 index 0000000000000..eb15a0bbf0420 --- /dev/null +++ b/docs/de/docs/tutorial/cookie-param-models.md @@ -0,0 +1,76 @@ +# Cookie-Parameter-Modelle { #cookie-parameter-models } + +Wenn Sie eine Gruppe von **Cookies** haben, die zusammengehören, können Sie ein **Pydantic-Modell** erstellen, um diese zu deklarieren. 🍪 + +Damit können Sie das Modell an **mehreren Stellen wiederverwenden** und auch Validierungen und Metadaten für alle Parameter gleichzeitig deklarieren. 😎 + +/// note | Hinweis + +Dies wird seit FastAPI Version `0.115.0` unterstützt. 🤓 + +/// + +/// tip | Tipp + +Diese gleiche Technik gilt für `Query`, `Cookie` und `Header`. 😎 + +/// + +## Cookies mit einem Pydantic-Modell { #cookies-with-a-pydantic-model } + +Deklarieren Sie die **Cookie**-Parameter, die Sie benötigen, in einem **Pydantic-Modell**, und deklarieren Sie dann den Parameter als `Cookie`: + +{* ../../docs_src/cookie_param_models/tutorial001_an_py310.py hl[9:12,16] *} + +**FastAPI** wird die Daten für **jedes Feld** aus den im Request empfangenen **Cookies** **extrahieren** und Ihnen das von Ihnen definierte Pydantic-Modell bereitstellen. + +## Die Dokumentation testen { #check-the-docs } + +Sie können die definierten Cookies in der Dokumentationsoberfläche unter `/docs` sehen: + +
+ +
+ +/// note | Hinweis + +Bitte beachten Sie, dass Browser Cookies auf spezielle Weise und im Hintergrund bearbeiten, sodass sie **nicht** leicht **JavaScript** erlauben, diese zu berühren. + +Wenn Sie zur **API-Dokumentationsoberfläche** unter `/docs` gehen, können Sie die **Dokumentation** für Cookies für Ihre *Pfadoperationen* sehen. + +Aber selbst wenn Sie die **Daten ausfüllen** und auf „Ausführen“ klicken, werden aufgrund der Tatsache, dass die Dokumentationsoberfläche mit **JavaScript** arbeitet, die Cookies nicht gesendet, und Sie werden eine **Fehlermeldung** sehen, als ob Sie keine Werte eingegeben hätten. + +/// + +## Zusätzliche Cookies verbieten { #forbid-extra-cookies } + +In einigen speziellen Anwendungsfällen (wahrscheinlich nicht sehr häufig) möchten Sie möglicherweise die Cookies, die Sie empfangen möchten, **einschränken**. + +Ihre API hat jetzt die Macht, ihre eigene Cookie-Einwilligung zu kontrollieren. 🤪🍪 + +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] *} + +Wenn ein Client versucht, einige **zusätzliche Cookies** zu senden, erhält er eine **Error-Response**. + +Arme Cookie-Banner, wie sie sich mühen, Ihre Einwilligung zu erhalten, dass die API sie ablehnen darf. 🍪 + +Wenn der Client beispielsweise versucht, ein `santa_tracker`-Cookie mit einem Wert von `good-list-please` zu senden, erhält der Client eine **Error-Response**, die ihm mitteilt, dass das `santa_tracker` Cookie nicht erlaubt ist: + +```json +{ + "detail": [ + { + "type": "extra_forbidden", + "loc": ["cookie", "santa_tracker"], + "msg": "Extra inputs are not permitted", + "input": "good-list-please", + } + ] +} +``` + +## Zusammenfassung { #summary } + +Sie können **Pydantic-Modelle** verwenden, um **Cookies** in **FastAPI** zu deklarieren. 😎 diff --git a/docs/de/docs/tutorial/cookie-params.md b/docs/de/docs/tutorial/cookie-params.md new file mode 100644 index 0000000000000..db5f3332c26c7 --- /dev/null +++ b/docs/de/docs/tutorial/cookie-params.md @@ -0,0 +1,45 @@ +# Cookie-Parameter { #cookie-parameters } + +Sie können Cookie-Parameter auf die gleiche Weise definieren wie `Query`- und `Path`-Parameter. + +## `Cookie` importieren { #import-cookie } + +Importieren Sie zuerst `Cookie`: + +{* ../../docs_src/cookie_params/tutorial001_an_py310.py hl[3] *} + +## `Cookie`-Parameter deklarieren { #declare-cookie-parameters } + +Deklarieren Sie dann die Cookie-Parameter mit derselben Struktur wie bei `Path` und `Query`. + +Sie können den Defaultwert sowie alle zusätzlichen Validierungen oder Annotierungsparameter definieren: + +{* ../../docs_src/cookie_params/tutorial001_an_py310.py hl[9] *} + +/// note | Technische Details + +`Cookie` ist eine „Schwester“-Klasse von `Path` und `Query`. Sie erbt auch von derselben gemeinsamen `Param`-Klasse. + +Aber denken Sie daran, dass, wenn Sie `Query`, `Path`, `Cookie` und andere von `fastapi` importieren, diese tatsächlich Funktionen sind, die spezielle Klassen zurückgeben. + +/// + +/// note | Hinweis + +Um Cookies zu deklarieren, müssen Sie `Cookie` verwenden, da die Parameter sonst als Query-Parameter interpretiert würden. + +/// + +/// note | Hinweis + +Beachten Sie, dass **Browser Cookies auf besondere Weise und hinter den Kulissen handhaben** und **JavaScript** **nicht** ohne Weiteres erlauben, auf sie zuzugreifen. + +Wenn Sie zur **API-Dokumentations-UI** unter `/docs` gehen, können Sie die **Dokumentation** zu Cookies für Ihre *Pfadoperationen* sehen. + +Aber selbst wenn Sie die **Daten ausfüllen** und auf „Execute“ klicken, da die Dokumentations-UI mit **JavaScript** arbeitet, werden die Cookies nicht gesendet, und Sie sehen eine **Fehler**-Meldung, als hätten Sie keine Werte eingegeben. + +/// + +## Zusammenfassung { #recap } + +Deklarieren Sie Cookies mit `Cookie` und verwenden Sie dabei das gleiche allgemeine Muster wie bei `Query` und `Path`. diff --git a/docs/de/docs/tutorial/cors.md b/docs/de/docs/tutorial/cors.md new file mode 100644 index 0000000000000..760aba49e69b1 --- /dev/null +++ b/docs/de/docs/tutorial/cors.md @@ -0,0 +1,88 @@ +# CORS (Cross-Origin Resource Sharing) { #cors-cross-origin-resource-sharing } + +[CORS oder „Cross-Origin Resource Sharing“](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) bezieht sich auf Situationen, in denen ein Frontend, das in einem Browser läuft, JavaScript-Code enthält, der mit einem Backend kommuniziert, und das Backend sich in einem anderen „Origin“ als das Frontend befindet. + +## Origin { #origin } + +Ein Origin ist die Kombination aus Protokoll (`http`, `https`), Domain (`myapp.com`, `localhost`, `localhost.tiangolo.com`) und Port (`80`, `443`, `8080`). + +Alle folgenden sind also unterschiedliche Origins: + +* `http://localhost` +* `https://localhost` +* `http://localhost:8080` + +Auch wenn sie alle in `localhost` sind, verwenden sie unterschiedliche Protokolle oder Ports, daher sind sie unterschiedliche „Origins“. + +## Schritte { #steps } + +Angenommen, Sie haben ein Frontend, das in Ihrem Browser unter `http://localhost:8080` läuft, und dessen JavaScript versucht, mit einem Backend zu kommunizieren, das unter `http://localhost` läuft (da wir keinen Port angegeben haben, geht der Browser vom Default-Port `80` aus). + +Dann wird der Browser ein HTTP-`OPTIONS`-Request an das `:80`-Backend senden, und wenn das Backend die entsprechenden Header sendet, die die Kommunikation von diesem anderen Origin (`http://localhost:8080`) autorisieren, lässt der `:8080`-Browser das JavaScript im Frontend seinen Request an das `:80`-Backend senden. + +Um dies zu erreichen, muss das `:80`-Backend eine Liste von „erlaubten Origins“ haben. + +In diesem Fall müsste die Liste `http://localhost:8080` enthalten, damit das `:8080`-Frontend korrekt funktioniert. + +## Wildcards { #wildcards } + +Es ist auch möglich, die Liste als `"*"` (ein „Wildcard“) zu deklarieren, um anzuzeigen, dass alle erlaubt sind. + +Aber das erlaubt nur bestimmte Arten der Kommunikation und schließt alles aus, was Anmeldeinformationen beinhaltet: Cookies, Autorisierungsheader wie die, die mit Bearer Tokens verwendet werden, usw. + +Um sicherzustellen, dass alles korrekt funktioniert, ist es besser, die erlaubten Origins explizit anzugeben. + +## `CORSMiddleware` verwenden { #use-corsmiddleware } + +Sie können das in Ihrer **FastAPI**-Anwendung mit der `CORSMiddleware` konfigurieren. + +* Importieren Sie `CORSMiddleware`. +* Erstellen Sie eine Liste der erlaubten Origins (als Strings). +* Fügen Sie es als „Middleware“ zu Ihrer **FastAPI**-Anwendung hinzu. + +Sie können auch angeben, ob Ihr Backend erlaubt: + +* Anmeldeinformationen (Autorisierungsheader, Cookies, usw.). +* Bestimmte HTTP-Methoden (`POST`, `PUT`) oder alle mit der Wildcard `"*"`. +* Bestimmte HTTP-Header oder alle mit der Wildcard `"*"`. + +{* ../../docs_src/cors/tutorial001_py310.py hl[2,6:11,13:19] *} + +Die von der `CORSMiddleware`-Implementierung verwendeten Defaultparameter sind standardmäßig restriktiv, daher müssen Sie bestimmte Origins, Methoden oder Header ausdrücklich aktivieren, damit Browser sie in einem Cross-Domain-Kontext verwenden dürfen. + +Die folgenden Argumente werden unterstützt: + +* `allow_origins` – Eine Liste von Origins, die Cross-Origin-Requests machen dürfen. z. B. `['https://example.org', 'https://www.example.org']`. Sie können `['*']` verwenden, um jedes Origin zuzulassen. +* `allow_origin_regex` – Ein Regex-String zum Abgleichen gegen Origins, die Cross-Origin-Requests machen dürfen. z. B. `'https://.*\.example\.org'`. +* `allow_methods` – Eine Liste von HTTP-Methoden, die für Cross-Origin-Requests erlaubt sein sollen. Standardmäßig `['GET']`. Sie können `['*']` verwenden, um alle Standardmethoden zu erlauben. +* `allow_headers` – Eine Liste von HTTP-Requestheadern, die für Cross-Origin-Requests unterstützt werden sollten. Standardmäßig `[]`. Sie können `['*']` verwenden, um alle Header zu erlauben. Die Header `Accept`, `Accept-Language`, `Content-Language` und `Content-Type` sind immer für [einfache CORS-Requests](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#simple_requests) erlaubt. +* `allow_credentials` – Anzeigen, dass Cookies für Cross-Origin-Requests unterstützt werden sollten. Standardmäßig `False`. + + Keines der `allow_origins`, `allow_methods` und `allow_headers` kann auf `['*']` gesetzt werden, wenn `allow_credentials` auf `True` gesetzt ist. Alle müssen [explizit angegeben](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#credentialed_requests_and_wildcards) werden. + +* `expose_headers` – Angabe der Responseheader, auf die der Browser zugreifen können soll. Standardmäßig `[]`. +* `max_age` – Legt eine maximale Zeit in Sekunden fest, die Browser CORS-Responses zwischenspeichern dürfen. Standardmäßig `600`. + +Die Middleware antwortet auf zwei besondere Arten von HTTP-Requests ... + +### CORS-Preflight-Requests { #cors-preflight-requests } + +Dies sind alle `OPTIONS`-Requests mit `Origin`- und `Access-Control-Request-Method`-Headern. + +In diesem Fall wird die Middleware den eingehenden Request abfangen und mit entsprechenden CORS-Headern, und entweder einer `200`- oder `400`-Response zu Informationszwecken antworten. + +### Einfache Requests { #simple-requests } + +Jeder Request mit einem `Origin`-Header. In diesem Fall wird die Middleware den Request wie gewohnt durchlassen, aber entsprechende CORS-Header in die Response aufnehmen. + +## Weitere Informationen { #more-info } + +Weitere Informationen zu CORS finden Sie in der [Mozilla CORS-Dokumentation](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS). + +/// note | Technische Details + +Sie könnten auch `from starlette.middleware.cors import CORSMiddleware` verwenden. + +**FastAPI** bietet mehrere Middlewares in `fastapi.middleware` nur als Komfort für Sie, den Entwickler. Aber die meisten der verfügbaren Middlewares stammen direkt von Starlette. + +/// diff --git a/docs/de/docs/tutorial/debugging.md b/docs/de/docs/tutorial/debugging.md new file mode 100644 index 0000000000000..f7949d027da67 --- /dev/null +++ b/docs/de/docs/tutorial/debugging.md @@ -0,0 +1,113 @@ +# Debugging { #debugging } + +Sie können den Debugger in Ihrem Editor verbinden, zum Beispiel mit Visual Studio Code oder PyCharm. + +## `uvicorn` aufrufen { #call-uvicorn } + +Importieren und führen Sie `uvicorn` direkt in Ihrer FastAPI-Anwendung aus: + +{* ../../docs_src/debugging/tutorial001_py310.py hl[1,15] *} + +### Über `__name__ == "__main__"` { #about-name-main } + +Der Hauptzweck von `__name__ == "__main__"` ist, dass Code ausgeführt wird, wenn Ihre Datei mit folgendem Befehl aufgerufen wird: + +
+ +```console +$ python myapp.py +``` + +
+ +aber nicht aufgerufen wird, wenn eine andere Datei sie importiert, wie in: + +```Python +from myapp import app +``` + +#### Weitere Details { #more-details } + +Angenommen, Ihre Datei heißt `myapp.py`. + +Wenn Sie sie mit folgendem Befehl ausführen: + +
+ +```console +$ python myapp.py +``` + +
+ +dann hat in Ihrer Datei die interne Variable `__name__`, die von Python automatisch erstellt wird, als Wert den String `"__main__"`. + +Daher wird der Abschnitt: + +```Python + uvicorn.run(app, host="0.0.0.0", port=8000) +``` + +ausgeführt. + +--- + +Dies wird nicht passieren, wenn Sie das Modul (die Datei) importieren. + +Wenn Sie also eine weitere Datei `importer.py` mit folgendem Inhalt haben: + +```Python +from myapp import app + +# Hier mehr Code +``` + +wird in diesem Fall in `myapp.py` die automatisch erstellte Variable `__name__` nicht den Wert `"__main__"` haben. + +Daher wird die Zeile: + +```Python + uvicorn.run(app, host="0.0.0.0", port=8000) +``` + +nicht ausgeführt. + +/// note | Hinweis + +Für weitere Informationen besuchen Sie bitte [die offizielle Python-Dokumentation](https://docs.python.org/3/library/__main__.html). + +/// + +## Ihren Code mit Ihrem Debugger ausführen { #run-your-code-with-your-debugger } + +Da Sie den Uvicorn-Server direkt aus Ihrem Code ausführen, können Sie Ihr Python-Programm (Ihre FastAPI-Anwendung) direkt aus dem Debugger aufrufen. + +--- + +Zum Beispiel können Sie in Visual Studio Code: + +* Zum „Debug“-Panel gehen. +* „Konfiguration hinzufügen ...“ auswählen. +* „Python“ auswählen. +* Den Debugger mit der Option „`Python: Current File (Integrated Terminal)`“ ausführen. + +Der Server wird dann mit Ihrem **FastAPI**-Code gestartet, an Ihren Haltepunkten angehalten, usw. + +So könnte es aussehen: + + + +--- + +Wenn Sie PyCharm verwenden, können Sie: + +* Das Menü „Run“ öffnen. +* Die Option „Debug ...“ auswählen. +* Ein Kontextmenü wird angezeigt. +* Die zu debuggende Datei auswählen (in diesem Fall `main.py`). + +Der Server wird dann mit Ihrem **FastAPI**-Code gestartet, an Ihren Haltepunkten angehalten, usw. + +So könnte es aussehen: + + diff --git a/docs/de/docs/tutorial/dependencies/classes-as-dependencies.md b/docs/de/docs/tutorial/dependencies/classes-as-dependencies.md new file mode 100644 index 0000000000000..4fd8d092fc110 --- /dev/null +++ b/docs/de/docs/tutorial/dependencies/classes-as-dependencies.md @@ -0,0 +1,288 @@ +# Klassen als Abhängigkeiten { #classes-as-dependencies } + +Bevor wir tiefer in das **Dependency Injection** System eintauchen, lassen Sie uns das vorherige Beispiel verbessern. + +## Ein `dict` aus dem vorherigen Beispiel { #a-dict-from-the-previous-example } + +Im vorherigen Beispiel haben wir ein `dict` von unserer Abhängigkeit („Dependable“) zurückgegeben: + +{* ../../docs_src/dependencies/tutorial001_an_py310.py hl[9] *} + +Aber dann haben wir ein `dict` im Parameter `commons` der *Pfadoperation-Funktion*. + +Und wir wissen, dass Editoren nicht viel Unterstützung (wie etwa Code-Vervollständigung) für `dict`s bieten können, weil sie ihre Schlüssel- und Werttypen nicht kennen. + +Das können wir besser machen ... + +## Was macht eine Abhängigkeit aus { #what-makes-a-dependency } + +Bisher haben Sie Abhängigkeiten gesehen, die als Funktionen deklariert wurden. + +Das ist jedoch nicht die einzige Möglichkeit, Abhängigkeiten zu deklarieren (obwohl es wahrscheinlich die gebräuchlichste ist). + +Der springende Punkt ist, dass eine Abhängigkeit aufrufbar („callable“) sein sollte. + +Ein „**Callable**“ in Python ist etwas, das wie eine Funktion aufgerufen werden kann („to call“). + +Wenn Sie also ein Objekt `something` haben (das möglicherweise _keine_ Funktion ist) und Sie es wie folgt aufrufen (ausführen) können: + +```Python +something() +``` + +oder + +```Python +something(some_argument, some_keyword_argument="foo") +``` + +dann ist das ein „Callable“ (ein „Aufrufbares“). + +## Klassen als Abhängigkeiten { #classes-as-dependencies_1 } + +Möglicherweise stellen Sie fest, dass Sie zum Erstellen einer Instanz einer Python-Klasse die gleiche Syntax verwenden. + +Zum Beispiel: + +```Python +class Cat: + def __init__(self, name: str): + self.name = name + + +fluffy = Cat(name="Mr Fluffy") +``` + +In diesem Fall ist `fluffy` eine Instanz der Klasse `Cat`. + +Und um `fluffy` zu erzeugen, rufen Sie `Cat` auf. + +Eine Python-Klasse ist also auch ein **Callable**. + +Darum können Sie in **FastAPI** auch eine Python-Klasse als Abhängigkeit verwenden. + +Was FastAPI tatsächlich prüft, ist, ob es sich um ein „Callable“ (Funktion, Klasse oder irgendetwas anderes) handelt und ob die Parameter definiert sind. + +Wenn Sie **FastAPI** ein „Callable“ als Abhängigkeit übergeben, analysiert es die Parameter dieses „Callables“ und verarbeitet sie auf die gleiche Weise wie die Parameter einer *Pfadoperation-Funktion*. Einschließlich Unterabhängigkeiten. + +Das gilt auch für Callables ohne Parameter. So wie es auch für *Pfadoperation-Funktionen* ohne Parameter gilt. + +Dann können wir das „Dependable“ `common_parameters` der Abhängigkeit von oben in die Klasse `CommonQueryParams` ändern: + +{* ../../docs_src/dependencies/tutorial002_an_py310.py hl[11:15] *} + +Achten Sie auf die Methode `__init__`, die zum Erstellen der Instanz der Klasse verwendet wird: + +{* ../../docs_src/dependencies/tutorial002_an_py310.py hl[12] *} + +... sie hat die gleichen Parameter wie unsere vorherige `common_parameters`: + +{* ../../docs_src/dependencies/tutorial001_an_py310.py hl[8] *} + +Diese Parameter werden von **FastAPI** verwendet, um die Abhängigkeit „aufzulösen“. + +In beiden Fällen wird sie haben: + +* Einen optionalen `q`-Query-Parameter, der ein `str` ist. +* Einen `skip`-Query-Parameter, der ein `int` ist, mit einem Defaultwert `0`. +* Einen `limit`-Query-Parameter, der ein `int` ist, mit einem Defaultwert `100`. + +In beiden Fällen werden die Daten konvertiert, validiert, im OpenAPI-Schema dokumentiert, usw. + +## Verwenden { #use-it } + +Jetzt können Sie Ihre Abhängigkeit mithilfe dieser Klasse deklarieren. + +{* ../../docs_src/dependencies/tutorial002_an_py310.py hl[19] *} + +**FastAPI** ruft die Klasse `CommonQueryParams` auf. Dadurch wird eine „Instanz“ dieser Klasse erstellt und die Instanz wird als Parameter `commons` an Ihre Funktion überreicht. + +## Typannotation vs. `Depends` { #type-annotation-vs-depends } + +Beachten Sie, wie wir `CommonQueryParams` im obigen Code zweimal schreiben: + +//// tab | Python 3.10+ + +```Python +commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)] +``` + +//// + +//// tab | Python 3.10+ nicht annotiert + +/// tip | Tipp + +Bevorzugen Sie die `Annotated`-Version, falls möglich. + +/// + +```Python +commons: CommonQueryParams = Depends(CommonQueryParams) +``` + +//// + +Das letzte `CommonQueryParams`, in: + +```Python +... Depends(CommonQueryParams) +``` + +... ist das, was **FastAPI** tatsächlich verwendet, um die Abhängigkeit zu ermitteln. + +Aus diesem extrahiert FastAPI die deklarierten Parameter, und dieses ist es, was FastAPI auch aufruft. + +--- + +In diesem Fall hat das erste `CommonQueryParams` in: + +//// tab | Python 3.10+ + +```Python +commons: Annotated[CommonQueryParams, ... +``` + +//// + +//// tab | Python 3.10+ nicht annotiert + +/// tip | Tipp + +Bevorzugen Sie die `Annotated`-Version, falls möglich. + +/// + +```Python +commons: CommonQueryParams ... +``` + +//// + +... keine besondere Bedeutung für **FastAPI**. FastAPI verwendet es nicht für die Datenkonvertierung, -validierung, usw. (da es dafür `Depends(CommonQueryParams)` verwendet). + +Sie könnten tatsächlich einfach schreiben: + +//// tab | Python 3.10+ + +```Python +commons: Annotated[Any, Depends(CommonQueryParams)] +``` + +//// + +//// tab | Python 3.10+ nicht annotiert + +/// tip | Tipp + +Bevorzugen Sie die `Annotated`-Version, falls möglich. + +/// + +```Python +commons = Depends(CommonQueryParams) +``` + +//// + +... wie in: + +{* ../../docs_src/dependencies/tutorial003_an_py310.py hl[19] *} + +Es wird jedoch empfohlen, den Typ zu deklarieren, da Ihr Editor so weiß, was als Parameter `commons` übergeben wird, und Ihnen dann bei der Codevervollständigung, Typprüfungen, usw. helfen kann: + + + +## Abkürzung { #shortcut } + +Aber Sie sehen, dass wir hier etwas Codeduplizierung haben, indem wir `CommonQueryParams` zweimal schreiben: + +//// tab | Python 3.10+ + +```Python +commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)] +``` + +//// + +//// tab | Python 3.10+ nicht annotiert + +/// tip | Tipp + +Bevorzugen Sie die `Annotated`-Version, falls möglich. + +/// + +```Python +commons: CommonQueryParams = Depends(CommonQueryParams) +``` + +//// + +**FastAPI** bietet eine Abkürzung für diese Fälle, wo die Abhängigkeit *speziell* eine Klasse ist, welche **FastAPI** aufruft, um eine Instanz der Klasse selbst zu erstellen. + +In diesem speziellen Fall können Sie Folgendes tun: + +Anstatt zu schreiben: + +//// tab | Python 3.10+ + +```Python +commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)] +``` + +//// + +//// tab | Python 3.10+ nicht annotiert + +/// tip | Tipp + +Bevorzugen Sie die `Annotated`-Version, falls möglich. + +/// + +```Python +commons: CommonQueryParams = Depends(CommonQueryParams) +``` + +//// + +... schreiben Sie: + +//// tab | Python 3.10+ + +```Python +commons: Annotated[CommonQueryParams, Depends()] +``` + +//// + +//// tab | Python 3.10+ nicht annotiert + +/// tip | Tipp + +Bevorzugen Sie die `Annotated`-Version, falls möglich. + +/// + +```Python +commons: CommonQueryParams = Depends() +``` + +//// + +Sie deklarieren die Abhängigkeit als Typ des Parameters und verwenden `Depends()` ohne Parameter, anstatt die vollständige Klasse *erneut* in `Depends(CommonQueryParams)` schreiben zu müssen. + +Dasselbe Beispiel würde dann so aussehen: + +{* ../../docs_src/dependencies/tutorial004_an_py310.py hl[19] *} + +... und **FastAPI** wird wissen, was zu tun ist. + +/// tip | Tipp + +Wenn Sie das eher verwirrt, als Ihnen zu helfen, ignorieren Sie es, Sie *brauchen* es nicht. + +Es ist nur eine Abkürzung. Es geht **FastAPI** darum, Ihnen dabei zu helfen, Codeverdoppelung zu minimieren. + +/// diff --git a/docs/de/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md b/docs/de/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md new file mode 100644 index 0000000000000..a3ef1d5a8808d --- /dev/null +++ b/docs/de/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md @@ -0,0 +1,69 @@ +# Abhängigkeiten in Pfadoperation-Dekoratoren { #dependencies-in-path-operation-decorators } + +Manchmal benötigen Sie den Rückgabewert einer Abhängigkeit innerhalb Ihrer *Pfadoperation-Funktion* nicht wirklich. + +Oder die Abhängigkeit gibt keinen Wert zurück. + +Aber Sie müssen sie trotzdem ausführen/auflösen. + +In diesen Fällen können Sie, anstatt einen Parameter der *Pfadoperation-Funktion* mit `Depends` zu deklarieren, eine `list` von `dependencies` zum *Pfadoperation-Dekorator* hinzufügen. + +## `dependencies` zum *Pfadoperation-Dekorator* hinzufügen { #add-dependencies-to-the-path-operation-decorator } + +Der *Pfadoperation-Dekorator* erhält ein optionales Argument `dependencies`. + +Es sollte eine `list` von `Depends()` sein: + +{* ../../docs_src/dependencies/tutorial006_an_py310.py hl[19] *} + +Diese Abhängigkeiten werden auf die gleiche Weise wie normale Abhängigkeiten ausgeführt/aufgelöst. Aber ihr Wert (falls sie einen zurückgeben) wird nicht an Ihre *Pfadoperation-Funktion* übergeben. + +/// tip | Tipp + +Einige Editoren prüfen, ob Funktionsparameter nicht verwendet werden, und zeigen das als Fehler an. + +Wenn Sie `dependencies` im *Pfadoperation-Dekorator* verwenden, stellen Sie sicher, dass sie ausgeführt werden, während gleichzeitig Ihr Editor/Ihre Tools keine Fehlermeldungen ausgeben. + +Damit wird auch vermieden, neue Entwickler möglicherweise zu verwirren, die einen nicht verwendeten Parameter in Ihrem Code sehen und ihn für unnötig halten könnten. + +/// + +/// note | Hinweis + +In diesem Beispiel verwenden wir zwei erfundene benutzerdefinierte Header `X-Key` und `X-Token`. + +Aber in realen Fällen würden Sie bei der Implementierung von Sicherheit mehr Vorteile durch die Verwendung der integrierten [Sicherheits-Werkzeuge (siehe nächstes Kapitel)](../security/index.md) erzielen. + +/// + +## Abhängigkeitsfehler und -Rückgabewerte { #dependencies-errors-and-return-values } + +Sie können dieselben Abhängigkeits-*Funktionen* verwenden, die Sie normalerweise verwenden. + +### Abhängigkeitsanforderungen { #dependency-requirements } + +Sie können Anforderungen für einen Request (wie Header) oder andere Unterabhängigkeiten deklarieren: + +{* ../../docs_src/dependencies/tutorial006_an_py310.py hl[8,13] *} + +### Exceptions auslösen { #raise-exceptions } + +Die Abhängigkeiten können Exceptions `raise`n, genau wie normale Abhängigkeiten: + +{* ../../docs_src/dependencies/tutorial006_an_py310.py hl[10,15] *} + +### Rückgabewerte { #return-values } + +Und sie können Werte zurückgeben oder nicht, die Werte werden nicht verwendet. + +Sie können also eine normale Abhängigkeit (die einen Wert zurückgibt), die Sie bereits an anderer Stelle verwenden, wiederverwenden, und auch wenn der Wert nicht verwendet wird, wird die Abhängigkeit ausgeführt: + +{* ../../docs_src/dependencies/tutorial006_an_py310.py hl[11,16] *} + +## Abhängigkeiten für eine Gruppe von *Pfadoperationen* { #dependencies-for-a-group-of-path-operations } + +Wenn Sie später lesen, wie Sie größere Anwendungen strukturieren ([Größere Anwendungen – Mehrere Dateien](../../tutorial/bigger-applications.md)), möglicherweise mit mehreren Dateien, lernen Sie, wie Sie einen einzelnen `dependencies`-Parameter für eine Gruppe von *Pfadoperationen* deklarieren. + +## Globale Abhängigkeiten { #global-dependencies } + +Als Nächstes werden wir sehen, wie man Abhängigkeiten zur gesamten `FastAPI`-Anwendung hinzufügt, sodass sie für jede *Pfadoperation* gelten. diff --git a/docs/de/docs/tutorial/dependencies/dependencies-with-yield.md b/docs/de/docs/tutorial/dependencies/dependencies-with-yield.md new file mode 100644 index 0000000000000..5bb8868fc1657 --- /dev/null +++ b/docs/de/docs/tutorial/dependencies/dependencies-with-yield.md @@ -0,0 +1,290 @@ +# Abhängigkeiten mit `yield` { #dependencies-with-yield } + +FastAPI unterstützt Abhängigkeiten, die einige zusätzliche Schritte nach Abschluss ausführen. + +Verwenden Sie dazu `yield` statt `return` und schreiben Sie die zusätzlichen Schritte (Code) danach. + +/// tip | Tipp + +Stellen Sie sicher, dass Sie `yield` nur einmal pro Abhängigkeit verwenden. + +/// + +/// note | Technische Details + +Jede Funktion, die dekoriert werden kann mit: + +* [`@contextlib.contextmanager`](https://docs.python.org/3/library/contextlib.html#contextlib.contextmanager) oder +* [`@contextlib.asynccontextmanager`](https://docs.python.org/3/library/contextlib.html#contextlib.asynccontextmanager) + +kann auch als gültige **FastAPI**-Abhängigkeit verwendet werden. + +Tatsächlich verwendet FastAPI diese beiden Dekoratoren intern. + +/// + +## Eine Datenbank-Abhängigkeit mit `yield` { #a-database-dependency-with-yield } + +Sie könnten damit beispielsweise eine Datenbanksession erstellen und diese nach Abschluss schließen. + +Nur der Code vor und einschließlich der `yield`-Anweisung wird ausgeführt, bevor eine Response erzeugt wird: + +{* ../../docs_src/dependencies/tutorial007_py310.py hl[2:4] *} + +Der ge`yield`ete Wert ist das, was in *Pfadoperationen* und andere Abhängigkeiten eingefügt wird: + +{* ../../docs_src/dependencies/tutorial007_py310.py hl[4] *} + +Der auf die `yield`-Anweisung folgende Code wird nach der Response ausgeführt: + +{* ../../docs_src/dependencies/tutorial007_py310.py hl[5:6] *} + +/// tip | Tipp + +Sie können `async`- oder reguläre Funktionen verwenden. + +**FastAPI** wird bei jeder das Richtige tun, so wie auch bei normalen Abhängigkeiten. + +/// + +## Eine Abhängigkeit mit `yield` und `try` { #a-dependency-with-yield-and-try } + +Wenn Sie einen `try`-Block in einer Abhängigkeit mit `yield` verwenden, empfangen Sie alle Exceptions, die bei Verwendung der Abhängigkeit geworfen wurden. + +Wenn beispielsweise ein Code irgendwann in der Mitte, in einer anderen Abhängigkeit oder in einer *Pfadoperation*, ein „Rollback“ einer Datenbanktransaktion macht oder eine andere Exception verursacht, empfangen Sie die Exception in Ihrer Abhängigkeit. + +Sie können also mit `except SomeException` diese bestimmte Exception innerhalb der Abhängigkeit handhaben. + +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_py310.py hl[3,5] *} + +## Unterabhängigkeiten mit `yield` { #sub-dependencies-with-yield } + +Sie können Unterabhängigkeiten und „Bäume“ von Unterabhängigkeiten beliebiger Größe und Form haben, und einige oder alle davon können `yield` verwenden. + +**FastAPI** stellt sicher, dass der „Exit-Code“ in jeder Abhängigkeit mit `yield` in der richtigen Reihenfolge ausgeführt wird. + +Beispielsweise kann `dependency_c` von `dependency_b` und `dependency_b` von `dependency_a` abhängen: + +{* ../../docs_src/dependencies/tutorial008_an_py310.py hl[6,14,22] *} + +Und alle können `yield` verwenden. + +In diesem Fall benötigt `dependency_c` zum Ausführen seines Exit-Codes, dass der Wert von `dependency_b` (hier `dep_b` genannt) verfügbar ist. + +Und wiederum benötigt `dependency_b` den Wert von `dependency_a` (hier `dep_a` genannt) für seinen Exit-Code. + +{* ../../docs_src/dependencies/tutorial008_an_py310.py hl[18:19,26:27] *} + +Auf die gleiche Weise könnten Sie einige Abhängigkeiten mit `yield` und einige andere Abhängigkeiten mit `return` haben, und einige davon von einigen der anderen abhängen lassen. + +Und Sie könnten eine einzelne Abhängigkeit haben, die auf mehreren ge`yield`eten Abhängigkeiten basiert, usw. + +Sie können beliebige Kombinationen von Abhängigkeiten haben. + +**FastAPI** stellt sicher, dass alles in der richtigen Reihenfolge ausgeführt wird. + +/// note | Technische Details + +Dieses funktioniert dank Pythons [Kontextmanager](https://docs.python.org/3/library/contextlib.html). + +**FastAPI** verwendet sie intern, um das zu erreichen. + +/// + +## Abhängigkeiten mit `yield` und `HTTPException` { #dependencies-with-yield-and-httpexception } + +Sie haben gesehen, dass Sie Abhängigkeiten mit `yield` verwenden und `try`-Blöcke haben können, die versuchen, irgendeinen Code auszuführen und dann, nach `finally`, Exit-Code ausführen. + +Sie können auch `except` verwenden, um die geworfene Exception abzufangen und damit etwas zu tun. + +Zum Beispiel können Sie eine andere Exception auslösen, wie `HTTPException`. + +/// tip | Tipp + +Dies ist eine etwas fortgeschrittene Technik, die Sie in den meisten Fällen nicht wirklich benötigen, da Sie Exceptions (einschließlich `HTTPException`) innerhalb des restlichen Anwendungscodes auslösen können, beispielsweise in der *Pfadoperation-Funktion*. + +Aber es ist für Sie da, wenn Sie es brauchen. 🤓 + +/// + +{* ../../docs_src/dependencies/tutorial008b_an_py310.py hl[18:22,31] *} + +Wenn Sie Exceptions abfangen und darauf basierend eine benutzerdefinierte Response erstellen möchten, erstellen Sie einen [benutzerdefinierten Exceptionhandler](../handling-errors.md#install-custom-exception-handlers). + +## Abhängigkeiten mit `yield` und `except` { #dependencies-with-yield-and-except } + +Wenn Sie eine Exception mit `except` in einer Abhängigkeit mit `yield` abfangen und sie nicht erneut auslösen (oder eine neue Exception auslösen), kann FastAPI nicht feststellen, dass es eine Exception gab, genau so wie es bei normalem Python der Fall wäre: + +{* ../../docs_src/dependencies/tutorial008c_an_py310.py hl[15:16] *} + +In diesem Fall sieht der Client eine *HTTP 500 Internal Server Error*-Response, wie es sein sollte, da wir keine `HTTPException` oder Ähnliches auslösen, aber der Server hat **keine Logs** oder einen anderen Hinweis darauf, was der Fehler war. 😱 + +### In Abhängigkeiten mit `yield` und `except` immer `raise` verwenden { #always-raise-in-dependencies-with-yield-and-except } + +Wenn Sie eine Exception in einer Abhängigkeit mit `yield` abfangen, sollten Sie – sofern Sie nicht eine andere `HTTPException` oder Ähnliches auslösen – **die ursprüngliche Exception erneut auslösen**. + +Sie können dieselbe Exception mit `raise` erneut auslösen: + +{* ../../docs_src/dependencies/tutorial008d_an_py310.py hl[17] *} + +Jetzt erhält der Client dieselbe *HTTP 500 Internal Server Error*-Response, aber der Server enthält unseren benutzerdefinierten `InternalError` in den Logs. 😎 + +## Ausführung von Abhängigkeiten mit `yield` { #execution-of-dependencies-with-yield } + +Die Ausführungsreihenfolge ähnelt mehr oder weniger dem folgenden Diagramm. Die Zeit verläuft von oben nach unten. Und jede Spalte ist einer der interagierenden oder Code-ausführenden Teilnehmer. + +```mermaid +sequenceDiagram + +participant client as Client +participant handler as Exceptionhandler +participant dep as Abhängigkeit mit yield +participant operation as Pfadoperation +participant tasks as Hintergrundtasks + + Note over client,operation: Kann Exceptions auslösen, inklusive HTTPException + client ->> dep: Startet den Request + Note over dep: Führt den Code bis zum yield aus + opt Löst Exception aus + dep -->> handler: Löst Exception aus + handler -->> client: HTTP-Error-Response + end + dep ->> operation: Führt Abhängigkeit aus, z. B. DB-Session + opt Löst aus + operation -->> dep: Löst Exception aus (z. B. HTTPException) + opt Handhabt + dep -->> dep: Kann Exception abfangen, eine neue HTTPException auslösen, andere Exception auslösen + end + handler -->> client: HTTP-Error-Response + end + + operation ->> client: Sendet Response an Client + Note over client,operation: Response wurde bereits gesendet, kann nicht mehr geändert werden + opt Tasks + operation -->> tasks: Sendet Hintergrundtasks + end + opt Löst andere Exception aus + tasks -->> tasks: Handhabt Exceptions im Hintergrundtask-Code + end +``` + +/// note | Hinweis + +Es wird nur **eine Response** an den Client gesendet. Es kann eine Error-Response oder die Response der *Pfadoperation* sein. + +Nachdem eine dieser Responses gesendet wurde, kann keine weitere Response gesendet werden. + +/// + +/// tip | Tipp + +Wenn Sie in dem Code der *Pfadoperation-Funktion* irgendeine Exception auslösen, wird sie an die Abhängigkeiten mit `yield` weitergegeben, einschließlich `HTTPException`. In den meisten Fällen sollten Sie dieselbe Exception oder eine neue aus der Abhängigkeit mit `yield` erneut auslösen, um sicherzustellen, dass sie korrekt gehandhabt wird. + +/// + +## 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_py310.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` haben sich im Laufe der Zeit weiterentwickelt, um verschiedene Anwendungsfälle abzudecken und einige Probleme zu beheben. + +Wenn Sie sehen möchten, was sich in verschiedenen Versionen von FastAPI geändert hat, lesen Sie mehr dazu im fortgeschrittenen Teil, unter [Fortgeschrittene Abhängigkeiten – Abhängigkeiten mit `yield`, `HTTPException`, `except` und Hintergrundtasks](../../advanced/advanced-dependencies.md#dependencies-with-yield-httpexception-except-and-background-tasks). + +## Kontextmanager { #context-managers } + +### Was sind „Kontextmanager“ { #what-are-context-managers } + +„Kontextmanager“ (Englisch „Context Manager“) sind bestimmte Python-Objekte, die Sie in einer `with`-Anweisung verwenden können. + +Beispielsweise können Sie [„with“ verwenden, um eine Datei auszulesen](https://docs.python.org/3/tutorial/inputoutput.html#reading-and-writing-files): + +```Python +with open("./somefile.txt") as f: + contents = f.read() + print(contents) +``` + +Im Hintergrund erstellt das `open("./somefile.txt")` ein Objekt, das als „Kontextmanager“ bezeichnet wird. + +Dieser stellt sicher, dass, wenn der `with`-Block beendet ist, die Datei geschlossen wird, auch wenn Exceptions geworfen wurden. + +Wenn Sie eine Abhängigkeit mit `yield` erstellen, erstellt **FastAPI** dafür intern einen Kontextmanager und kombiniert ihn mit einigen anderen zugehörigen Tools. + +### Kontextmanager in Abhängigkeiten mit `yield` verwenden { #using-context-managers-in-dependencies-with-yield } + +/// warning | Achtung + +Dies ist mehr oder weniger eine „fortgeschrittene“ Idee. + +Wenn Sie gerade erst mit **FastAPI** beginnen, möchten Sie das vielleicht vorerst überspringen. + +/// + +In Python können Sie Kontextmanager erstellen, indem Sie [eine Klasse mit zwei Methoden erzeugen: `__enter__()` und `__exit__()`](https://docs.python.org/3/reference/datamodel.html#context-managers). + +Sie können solche auch innerhalb von **FastAPI**-Abhängigkeiten mit `yield` verwenden, indem Sie +`with`- oder `async with`-Anweisungen innerhalb der Abhängigkeits-Funktion verwenden: + +{* ../../docs_src/dependencies/tutorial010_py310.py hl[1:9,13] *} + +/// tip | Tipp + +Eine weitere Möglichkeit, einen Kontextmanager zu erstellen, ist: + +* [`@contextlib.contextmanager`](https://docs.python.org/3/library/contextlib.html#contextlib.contextmanager) oder +* [`@contextlib.asynccontextmanager`](https://docs.python.org/3/library/contextlib.html#contextlib.asynccontextmanager) + +indem Sie damit eine Funktion dekorieren, die ein einziges `yield` hat. + +Das ist es auch, was **FastAPI** intern für Abhängigkeiten mit `yield` verwendet. + +Aber Sie müssen die Dekoratoren nicht für FastAPI-Abhängigkeiten verwenden (und das sollten Sie auch nicht). + +FastAPI erledigt das intern für Sie. + +/// diff --git a/docs/de/docs/tutorial/dependencies/global-dependencies.md b/docs/de/docs/tutorial/dependencies/global-dependencies.md new file mode 100644 index 0000000000000..ac52cf0bd280b --- /dev/null +++ b/docs/de/docs/tutorial/dependencies/global-dependencies.md @@ -0,0 +1,16 @@ +# Globale Abhängigkeiten { #global-dependencies } + +Bei einigen Anwendungstypen möchten Sie möglicherweise Abhängigkeiten zur gesamten Anwendung hinzufügen. + +Ähnlich wie Sie [`dependencies` zu den *Pfadoperation-Dekoratoren* hinzufügen](dependencies-in-path-operation-decorators.md) können, können Sie sie auch zur `FastAPI`-Anwendung hinzufügen. + +In diesem Fall werden sie auf alle *Pfadoperationen* in der Anwendung angewendet: + +{* ../../docs_src/dependencies/tutorial012_an_py310.py hl[17] *} + + +Und alle Ideen aus dem Abschnitt über das [Hinzufügen von `dependencies` zu den *Pfadoperation-Dekoratoren*](dependencies-in-path-operation-decorators.md) gelten weiterhin, aber in diesem Fall für alle *Pfadoperationen* in der App. + +## Abhängigkeiten für Gruppen von *Pfadoperationen* { #dependencies-for-groups-of-path-operations } + +Wenn Sie später lesen, wie Sie größere Anwendungen strukturieren ([Größere Anwendungen – mehrere Dateien](../../tutorial/bigger-applications.md)), möglicherweise mit mehreren Dateien, lernen Sie, wie Sie einen einzelnen `dependencies`-Parameter für eine Gruppe von *Pfadoperationen* deklarieren. diff --git a/docs/de/docs/tutorial/dependencies/index.md b/docs/de/docs/tutorial/dependencies/index.md new file mode 100644 index 0000000000000..e631e7863d3b2 --- /dev/null +++ b/docs/de/docs/tutorial/dependencies/index.md @@ -0,0 +1,249 @@ +# Abhängigkeiten { #dependencies } + +**FastAPI** hat ein sehr mächtiges, aber intuitives **Abhängigkeitsinjektion** System. + +Es ist so konzipiert, sehr einfach zu verwenden zu sein und es jedem Entwickler sehr leicht zu machen, andere Komponenten mit **FastAPI** zu integrieren. + +## Was ist „Dependency Injection“ { #what-is-dependency-injection } + +**„Dependency Injection“** bedeutet in der Programmierung, dass es für Ihren Code (in diesem Fall Ihre *Pfadoperation-Funktionen*) eine Möglichkeit gibt, Dinge zu deklarieren, die er verwenden möchte und die er zum Funktionieren benötigt: „Abhängigkeiten“ – „Dependencies“. + +Das System (in diesem Fall **FastAPI**) kümmert sich dann darum, Ihren Code mit den erforderlichen Abhängigkeiten zu versorgen („die Abhängigkeiten einfügen“ – „inject the dependencies“). + +Das ist sehr nützlich, wenn Sie: + +* Eine gemeinsame Logik haben (die gleiche Code-Logik immer und immer wieder). +* Datenbankverbindungen teilen. +* Sicherheit, Authentifizierung, Rollenanforderungen, usw. durchsetzen. +* Und viele andere Dinge ... + +All dies, während Sie Codeverdoppelung minimieren. + +## Erste Schritte { #first-steps } + +Sehen wir uns ein sehr einfaches Beispiel an. Es ist so einfach, dass es vorerst nicht sehr nützlich ist. + +Aber so können wir uns besser auf die Funktionsweise des **Dependency Injection** Systems konzentrieren. + +### Eine Abhängigkeit erstellen, oder „Dependable“ { #create-a-dependency-or-dependable } + +Konzentrieren wir uns zunächst auf die Abhängigkeit – die Dependency. + +Es handelt sich einfach um eine Funktion, die die gleichen Parameter entgegennimmt wie eine *Pfadoperation-Funktion*: +{* ../../docs_src/dependencies/tutorial001_an_py310.py hl[8:9] *} + +Das war's schon. + +**Zwei Zeilen**. + +Und sie hat die gleiche Form und Struktur wie alle Ihre *Pfadoperation-Funktionen*. + +Sie können sie sich als *Pfadoperation-Funktion* ohne den „Dekorator“ (ohne `@app.get("/some-path")`) vorstellen. + +Und sie kann alles zurückgeben, was Sie möchten. + +In diesem Fall erwartet diese Abhängigkeit: + +* Einen optionalen Query-Parameter `q`, der ein `str` ist. +* Einen optionalen Query-Parameter `skip`, der ein `int` ist und standardmäßig `0` ist. +* Einen optionalen Query-Parameter `limit`, der ein `int` ist und standardmäßig `100` ist. + +Und dann wird einfach ein `dict` zurückgegeben, welches diese Werte enthält. + +/// note | Hinweis + +FastAPI unterstützt (und empfiehlt die Verwendung von) `Annotated` seit Version 0.95.0. + +Wenn Sie eine ältere Version haben, werden Sie Fehler angezeigt bekommen, wenn Sie versuchen, `Annotated` zu verwenden. + +Bitte [aktualisieren Sie FastAPI](../../deployment/versions.md#upgrading-the-fastapi-versions) daher mindestens zu Version 0.95.1, bevor Sie `Annotated` verwenden. + +/// + +### `Depends` importieren { #import-depends } + +{* ../../docs_src/dependencies/tutorial001_an_py310.py hl[3] *} + +### Die Abhängigkeit im „Dependant“ deklarieren { #declare-the-dependency-in-the-dependant } + +So wie auch `Body`, `Query`, usw., verwenden Sie `Depends` mit den Parametern Ihrer *Pfadoperation-Funktion*: + +{* ../../docs_src/dependencies/tutorial001_an_py310.py hl[13,18] *} + +Obwohl Sie `Depends` in den Parametern Ihrer Funktion genauso verwenden wie `Body`, `Query`, usw., funktioniert `Depends` etwas anders. + +Sie übergeben `Depends` nur einen einzigen Parameter. + +Dieser Parameter muss so etwas wie eine Funktion sein. + +Sie **rufen diese nicht direkt auf** (fügen Sie am Ende keine Klammern hinzu), sondern übergeben sie einfach als Parameter an `Depends()`. + +Und diese Funktion akzeptiert Parameter auf die gleiche Weise wie *Pfadoperation-Funktionen*. + +/// tip | Tipp + +Im nächsten Kapitel erfahren Sie, welche anderen „Dinge“, außer Funktionen, Sie als Abhängigkeiten verwenden können. + +/// + +Immer wenn ein neuer Request eintrifft, kümmert sich **FastAPI** darum: + +* Ihre Abhängigkeitsfunktion („Dependable“) mit den richtigen Parametern aufzurufen. +* Sich das Ergebnis von dieser Funktion zu holen. +* Dieses Ergebnis dem Parameter Ihrer *Pfadoperation-Funktion* zuzuweisen. + +```mermaid +graph TB + +common_parameters(["common_parameters"]) +read_items["/items/"] +read_users["/users/"] + +common_parameters --> read_items +common_parameters --> read_users +``` + +Auf diese Weise schreiben Sie gemeinsam genutzten Code nur einmal, und **FastAPI** kümmert sich darum, ihn für Ihre *Pfadoperationen* aufzurufen. + +/// tip | Tipp + +Beachten Sie, dass Sie keine spezielle Klasse erstellen und diese irgendwo an **FastAPI** übergeben müssen, um sie zu „registrieren“ oder so ähnlich. + +Sie übergeben es einfach an `Depends` und **FastAPI** weiß, wie der Rest erledigt wird. + +/// + +## `Annotated`-Abhängigkeiten wiederverwenden { #share-annotated-dependencies } + +In den Beispielen oben sehen Sie, dass es ein kleines bisschen **Codeverdoppelung** gibt. + +Wenn Sie die Abhängigkeit `common_parameters()` verwenden, müssen Sie den gesamten Parameter mit der Typannotation und `Depends()` schreiben: + +```Python +commons: Annotated[dict, Depends(common_parameters)] +``` + +Da wir jedoch `Annotated` verwenden, können wir diesen `Annotated`-Wert in einer Variablen speichern und an mehreren Stellen verwenden: + +{* ../../docs_src/dependencies/tutorial001_02_an_py310.py hl[12,16,21] *} + +/// tip | Tipp + +Das ist schlicht Standard-Python, es wird als „Typalias“ bezeichnet und ist eigentlich nicht **FastAPI**-spezifisch. + +Da **FastAPI** jedoch auf Standard-Python, einschließlich `Annotated`, basiert, können Sie diesen Trick in Ihrem Code verwenden. 😎 + +/// + +Die Abhängigkeiten funktionieren weiterhin wie erwartet, und das **Beste daran** ist, dass die **Typinformationen erhalten bleiben**, was bedeutet, dass Ihr Editor Ihnen weiterhin **automatische Vervollständigung**, **Inline-Fehler**, usw. bieten kann. Das Gleiche gilt für andere Tools wie `mypy`. + +Das ist besonders nützlich, wenn Sie es in einer **großen Codebasis** verwenden, in der Sie in **vielen *Pfadoperationen*** immer wieder **dieselben Abhängigkeiten** verwenden. + +## `async` oder nicht `async` { #to-async-or-not-to-async } + +Da Abhängigkeiten auch von **FastAPI** aufgerufen werden (so wie Ihre *Pfadoperation-Funktionen*), gelten beim Definieren Ihrer Funktionen die gleichen Regeln. + +Sie können `async def` oder einfach `def` verwenden. + +Und Sie können Abhängigkeiten mit `async def` innerhalb normaler `def`-*Pfadoperation-Funktionen* oder `def`-Abhängigkeiten innerhalb von `async def`-*Pfadoperation-Funktionen*, usw. deklarieren. + +Es spielt keine Rolle. **FastAPI** weiß, was zu tun ist. + +/// note | Hinweis + +Wenn Ihnen das nichts sagt, lesen Sie den [Async: *„In Eile?“*](../../async.md#in-a-hurry)-Abschnitt über `async` und `await` in der Dokumentation. + +/// + +## Integriert in OpenAPI { #integrated-with-openapi } + +Alle Requestdeklarationen, -validierungen und -anforderungen Ihrer Abhängigkeiten (und Unterabhängigkeiten) werden in dasselbe OpenAPI-Schema integriert. + +Die interaktive Dokumentation enthält also auch alle Informationen aus diesen Abhängigkeiten: + + + +## Einfache Verwendung { #simple-usage } + +Näher betrachtet, werden *Pfadoperation-Funktionen* deklariert, um verwendet zu werden, wann immer ein *Pfad* und eine *Operation* übereinstimmen, und dann kümmert sich **FastAPI** darum, die Funktion mit den richtigen Parametern aufzurufen, die Daten aus dem Request extrahierend. + +Tatsächlich funktionieren alle (oder die meisten) Webframeworks auf die gleiche Weise. + +Sie rufen diese Funktionen niemals direkt auf. Sie werden von Ihrem Framework aufgerufen (in diesem Fall **FastAPI**). + +Mit dem Dependency Injection System können Sie **FastAPI** ebenfalls mitteilen, dass Ihre *Pfadoperation-Funktion* von etwas anderem „abhängt“, das vor Ihrer *Pfadoperation-Funktion* ausgeführt werden soll, und **FastAPI** kümmert sich darum, es auszuführen und die Ergebnisse zu „injizieren“. + +Andere gebräuchliche Begriffe für dieselbe Idee der „Abhängigkeitsinjektion“ sind: + +* Ressourcen +* Provider +* Services +* Injectables +* Komponenten + +## **FastAPI**-Plugins { #fastapi-plug-ins } + +Integrationen und „Plugins“ können mit dem **Dependency Injection** System erstellt werden. Aber tatsächlich besteht **keine Notwendigkeit, „Plugins“ zu erstellen**, da es durch die Verwendung von Abhängigkeiten möglich ist, eine unendliche Anzahl von Integrationen und Interaktionen zu deklarieren, die dann für Ihre *Pfadoperation-Funktionen* verfügbar sind. + +Und Abhängigkeiten können auf sehr einfache und intuitive Weise erstellt werden, sodass Sie einfach die benötigten Python-Packages importieren und sie in wenigen Codezeilen, *im wahrsten Sinne des Wortes*, mit Ihren API-Funktionen integrieren. + +Beispiele hierfür finden Sie in den nächsten Kapiteln zu relationalen und NoSQL-Datenbanken, Sicherheit usw. + +## **FastAPI**-Kompatibilität { #fastapi-compatibility } + +Die Einfachheit des Dependency Injection Systems macht **FastAPI** kompatibel mit: + +* allen relationalen Datenbanken +* NoSQL-Datenbanken +* externen Packages +* externen APIs +* Authentifizierungs- und Autorisierungssystemen +* API-Nutzungs-Überwachungssystemen +* Responsedaten-Injektionssystemen +* usw. + +## Einfach und leistungsstark { #simple-and-powerful } + +Obwohl das hierarchische Dependency Injection System sehr einfach zu definieren und zu verwenden ist, ist es dennoch sehr mächtig. + +Sie können Abhängigkeiten definieren, die selbst wiederum Abhängigkeiten definieren können. + +Am Ende wird ein hierarchischer Baum von Abhängigkeiten erstellt, und das **Dependency Injection** System kümmert sich darum, alle diese Abhängigkeiten (und deren Unterabhängigkeiten) für Sie aufzulösen und die Ergebnisse bei jedem Schritt einzubinden (zu injizieren). + +Nehmen wir zum Beispiel an, Sie haben vier API-Endpunkte (*Pfadoperationen*): + +* `/items/public/` +* `/items/private/` +* `/users/{user_id}/activate` +* `/items/pro/` + +Dann könnten Sie für jeden davon unterschiedliche Berechtigungsanforderungen hinzufügen, nur mit Abhängigkeiten und Unterabhängigkeiten: + +```mermaid +graph TB + +current_user(["current_user"]) +active_user(["active_user"]) +admin_user(["admin_user"]) +paying_user(["paying_user"]) + +public["/items/public/"] +private["/items/private/"] +activate_user["/users/{user_id}/activate"] +pro_items["/items/pro/"] + +current_user --> active_user +active_user --> admin_user +active_user --> paying_user + +current_user --> public +active_user --> private +admin_user --> activate_user +paying_user --> pro_items +``` + +## Integriert mit **OpenAPI** { #integrated-with-openapi_1 } + +Alle diese Abhängigkeiten, während sie ihre Anforderungen deklarieren, fügen auch Parameter, Validierungen, usw. zu Ihren *Pfadoperationen* hinzu. + +**FastAPI** kümmert sich darum, alles zum OpenAPI-Schema hinzuzufügen, damit es in den interaktiven Dokumentationssystemen angezeigt wird. diff --git a/docs/de/docs/tutorial/dependencies/sub-dependencies.md b/docs/de/docs/tutorial/dependencies/sub-dependencies.md new file mode 100644 index 0000000000000..d6a2056cdad88 --- /dev/null +++ b/docs/de/docs/tutorial/dependencies/sub-dependencies.md @@ -0,0 +1,105 @@ +# Unterabhängigkeiten { #sub-dependencies } + +Sie können Abhängigkeiten erstellen, die **Unterabhängigkeiten** haben. + +Diese können so **tief** verschachtelt sein, wie nötig. + +**FastAPI** kümmert sich darum, sie aufzulösen. + +## Erste Abhängigkeit, „Dependable“ { #first-dependency-dependable } + +Sie könnten eine erste Abhängigkeit („Dependable“) wie folgt erstellen: + +{* ../../docs_src/dependencies/tutorial005_an_py310.py hl[8:9] *} + +Diese deklariert einen optionalen Query-Parameter `q` vom Typ `str` und gibt ihn dann einfach zurück. + +Das ist recht einfach (nicht sehr nützlich), hilft uns aber dabei, uns auf die Funktionsweise der Unterabhängigkeiten zu konzentrieren. + +## Zweite Abhängigkeit, „Dependable“ und „Dependant“ { #second-dependency-dependable-and-dependant } + +Dann können Sie eine weitere Abhängigkeitsfunktion (ein „Dependable“) erstellen, die gleichzeitig eine eigene Abhängigkeit deklariert (also auch ein „Dependant“ ist): + +{* ../../docs_src/dependencies/tutorial005_an_py310.py hl[13] *} + +Betrachten wir die deklarierten Parameter: + +* Obwohl diese Funktion selbst eine Abhängigkeit ist („Dependable“, etwas hängt von ihr ab), deklariert sie auch eine andere Abhängigkeit („Dependant“, sie hängt von etwas anderem ab). + * Sie hängt von `query_extractor` ab und weist den von diesem zurückgegebenen Wert dem Parameter `q` zu. +* Sie deklariert außerdem ein optionales `last_query`-Cookie, ein `str`. + * Wenn der Benutzer keine Query `q` übermittelt hat, verwenden wir die zuletzt übermittelte Query, die wir zuvor in einem Cookie gespeichert haben. + +## Die Abhängigkeit verwenden { #use-the-dependency } + +Diese Abhängigkeit verwenden wir nun wie folgt: + +{* ../../docs_src/dependencies/tutorial005_an_py310.py hl[23] *} + +/// note | Hinweis + +Beachten Sie, dass wir in der *Pfadoperation-Funktion* nur eine einzige Abhängigkeit deklarieren, den `query_or_cookie_extractor`. + +Aber **FastAPI** wird wissen, dass es zuerst `query_extractor` auflösen muss, um dessen Resultat an `query_or_cookie_extractor` zu übergeben, wenn dieses aufgerufen wird. + +/// + +```mermaid +graph TB + +query_extractor(["query_extractor"]) +query_or_cookie_extractor(["query_or_cookie_extractor"]) + +read_query["/items/"] + +query_extractor --> query_or_cookie_extractor --> read_query +``` + +## Dieselbe Abhängigkeit mehrmals verwenden { #using-the-same-dependency-multiple-times } + +Wenn eine Ihrer Abhängigkeiten mehrmals für dieselbe *Pfadoperation* deklariert wird, beispielsweise wenn mehrere Abhängigkeiten eine gemeinsame Unterabhängigkeit haben, wird **FastAPI** diese Unterabhängigkeit nur einmal pro Request aufrufen. + +Und es speichert den zurückgegebenen Wert in einem „Cache“ und übergibt diesen gecachten Wert an alle „Dependanten“, die ihn in diesem spezifischen Request benötigen, anstatt die Abhängigkeit mehrmals für denselben Request aufzurufen. + +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.10+ + +```Python hl_lines="1" +async def needy_dependency(fresh_value: Annotated[str, Depends(get_value, use_cache=False)]): + return {"fresh_value": fresh_value} +``` + +//// + +//// tab | Python 3.10+ nicht annotiert + +/// tip | Tipp + +Bevorzugen Sie die `Annotated`-Version, falls möglich. + +/// + +```Python hl_lines="1" +async def needy_dependency(fresh_value: str = Depends(get_value, use_cache=False)): + return {"fresh_value": fresh_value} +``` + +//// + +## Zusammenfassung { #recap } + +Abgesehen von all den ausgefallenen Wörtern, die hier verwendet werden, ist das **Dependency Injection**-System recht simpel. + +Einfach Funktionen, die genauso aussehen wie *Pfadoperation-Funktionen*. + +Dennoch ist es sehr mächtig und ermöglicht Ihnen die Deklaration beliebig tief verschachtelter Abhängigkeits-„Graphen“ (Bäume). + +/// tip | Tipp + +All dies scheint angesichts dieser einfachen Beispiele möglicherweise nicht so nützlich zu sein. + +Aber Sie werden in den Kapiteln über **Sicherheit** sehen, wie nützlich das ist. + +Und Sie werden auch sehen, wie viel Code Sie dadurch einsparen. + +/// diff --git a/docs/de/docs/tutorial/encoder.md b/docs/de/docs/tutorial/encoder.md new file mode 100644 index 0000000000000..77a87f811c77d --- /dev/null +++ b/docs/de/docs/tutorial/encoder.md @@ -0,0 +1,35 @@ +# JSON-kompatibler Encoder { #json-compatible-encoder } + +Es gibt Fälle, da möchten Sie einen Datentyp (etwa ein Pydantic-Modell) in etwas konvertieren, das kompatibel mit JSON ist (etwa ein `dict`, eine `list`, usw.). + +Zum Beispiel, wenn Sie es in einer Datenbank speichern möchten. + +Dafür bietet **FastAPI** eine Funktion `jsonable_encoder()`. + +## `jsonable_encoder` verwenden { #using-the-jsonable-encoder } + +Stellen wir uns vor, Sie haben eine Datenbank `fake_db`, die nur JSON-kompatible Daten entgegennimmt. + +Sie akzeptiert zum Beispiel keine `datetime`-Objekte, da die nicht kompatibel mit JSON sind. + +Ein `datetime`-Objekt müsste also in einen `str` umgewandelt werden, der die Daten im [ISO-Format](https://en.wikipedia.org/wiki/ISO_8601) enthält. + +Genauso würde die Datenbank kein Pydantic-Modell (ein Objekt mit Attributen) akzeptieren, sondern nur ein `dict`. + +Sie können für diese Fälle `jsonable_encoder` verwenden. + +Es nimmt ein Objekt entgegen, wie etwa ein Pydantic-Modell, und gibt eine JSON-kompatible Version zurück: + +{* ../../docs_src/encoder/tutorial001_py310.py hl[4,21] *} + +In diesem Beispiel wird das Pydantic-Modell in ein `dict`, und das `datetime`-Objekt in ein `str` konvertiert. + +Das Resultat dieses Aufrufs ist etwas, das mit Pythons Standard-[`json.dumps()`](https://docs.python.org/3/library/json.html#json.dumps) kodiert werden kann. + +Es wird also kein großer `str` zurückgegeben, der die Daten im JSON-Format (als String) enthält. Es wird eine Python-Standarddatenstruktur (z. B. ein `dict`) zurückgegeben, mit Werten und Unterwerten, die alle mit JSON kompatibel sind. + +/// note | Hinweis + +`jsonable_encoder` wird tatsächlich von **FastAPI** intern verwendet, um Daten zu konvertieren. Aber es ist in vielen anderen Szenarien hilfreich. + +/// diff --git a/docs/de/docs/tutorial/extra-data-types.md b/docs/de/docs/tutorial/extra-data-types.md new file mode 100644 index 0000000000000..d1feab1a0a469 --- /dev/null +++ b/docs/de/docs/tutorial/extra-data-types.md @@ -0,0 +1,63 @@ +# Zusätzliche Datentypen { #extra-data-types } + + +Bisher haben Sie gängige Datentypen verwendet, wie zum Beispiel: + +* `int` +* `float` +* `str` +* `bool` + +Sie können aber auch komplexere Datentypen verwenden. + +Und Sie haben immer noch dieselbe Funktionalität wie bisher gesehen: + +* Großartige Editor-Unterstützung. +* Datenkonvertierung bei eingehenden Requests. +* Datenkonvertierung für Response-Daten. +* Datenvalidierung. +* Automatische Annotation und Dokumentation. + +## Andere Datentypen { #other-data-types } + +Hier sind einige der zusätzlichen Datentypen, die Sie verwenden können: + +* `UUID`: + * Ein standardmäßiger „universell eindeutiger Bezeichner“ („Universally Unique Identifier“), der in vielen Datenbanken und Systemen als ID üblich ist. + * Wird in Requests und Responses als `str` dargestellt. +* `datetime.datetime`: + * Ein Python-`datetime.datetime`. + * Wird in Requests und Responses als `str` im ISO 8601-Format dargestellt, etwa: `2008-09-15T15:53:00+05:00`. +* `datetime.date`: + * Python-`datetime.date`. + * Wird in Requests und Responses als `str` im ISO 8601-Format dargestellt, etwa: `2008-09-15`. +* `datetime.time`: + * Ein Python-`datetime.time`. + * Wird in Requests und Responses als `str` im ISO 8601-Format dargestellt, etwa: `14:23:55.003`. +* `datetime.timedelta`: + * Ein Python-`datetime.timedelta`. + * Wird in Requests und Responses als `float` der Gesamtsekunden dargestellt. + * Pydantic ermöglicht auch die Darstellung als „ISO 8601 Zeitdifferenz-Kodierung“, [siehe die Dokumentation für weitere Informationen](https://docs.pydantic.dev/latest/concepts/serialization/#custom-serializers). +* `frozenset`: + * Wird in Requests und Responses wie ein `set` behandelt: + * Bei Requests wird eine Liste gelesen, Duplikate entfernt und in ein `set` umgewandelt. + * Bei Responses wird das `set` in eine `list` umgewandelt. + * Das generierte Schema zeigt an, dass die `set`-Werte eindeutig sind (unter Verwendung von JSON Schemas `uniqueItems`). +* `bytes`: + * Standard-Python-`bytes`. + * In Requests und Responses werden sie als `str` behandelt. + * Das generierte Schema wird anzeigen, dass es sich um einen `str` mit `binary` „Format“ handelt. +* `Decimal`: + * Standard-Python-`Decimal`. + * In Requests und Responses wird es wie ein `float` behandelt. +* Sie können alle gültigen Pydantic-Datentypen hier überprüfen: [Pydantic-Datentypen](https://docs.pydantic.dev/latest/usage/types/types/). + +## Beispiel { #example } + +Hier ist ein Beispiel für eine *Pfadoperation* mit Parametern, die einige der oben genannten Typen verwenden. + +{* ../../docs_src/extra_data_types/tutorial001_an_py310.py hl[1,3,12:16] *} + +Beachten Sie, dass die Parameter innerhalb der Funktion ihren natürlichen Datentyp haben und Sie beispielsweise normale Datumsmanipulationen durchführen können, wie zum Beispiel: + +{* ../../docs_src/extra_data_types/tutorial001_an_py310.py hl[18:19] *} diff --git a/docs/de/docs/tutorial/extra-models.md b/docs/de/docs/tutorial/extra-models.md new file mode 100644 index 0000000000000..8e0b094ad5150 --- /dev/null +++ b/docs/de/docs/tutorial/extra-models.md @@ -0,0 +1,211 @@ +# Extramodelle { #extra-models } + +Im Anschluss an das vorherige Beispiel ist es üblich, mehr als ein zusammenhängendes Modell zu haben. + +Dies gilt insbesondere für Benutzermodelle, denn: + +* Das **Eingabemodell** muss ein Passwort enthalten können. +* Das **Ausgabemodell** sollte kein Passwort haben. +* Das **Datenbankmodell** müsste wahrscheinlich ein gehashtes Passwort haben. + +/// danger | Gefahr + +Speichern Sie niemals das Klartextpasswort eines Benutzers. Speichern Sie immer einen „sicheren Hash“, den Sie dann verifizieren können. + +Wenn Sie nicht wissen, was das ist, werden Sie in den [Sicherheitskapiteln](security/simple-oauth2.md#password-hashing) lernen, was ein „Passworthash“ ist. + +/// + +## Mehrere Modelle { #multiple-models } + +Hier ist eine allgemeine Idee, wie die Modelle mit ihren Passwortfeldern aussehen könnten und an welchen Stellen sie verwendet werden: + +{* ../../docs_src/extra_models/tutorial001_py310.py hl[7,9,14,20,22,27:28,31:33,38:39] *} + +### Über `**user_in.model_dump()` { #about-user-in-model-dump } + +#### Pydantics `.model_dump()` { #pydantics-model-dump } + +`user_in` ist ein Pydantic-Modell der Klasse `UserIn`. + +Pydantic-Modelle haben eine `.model_dump()`-Methode, die ein `dict` mit den Daten des Modells zurückgibt. + +Wenn wir also ein Pydantic-Objekt `user_in` erstellen, etwa so: + +```Python +user_in = UserIn(username="john", password="secret", email="john.doe@example.com") +``` + +und dann aufrufen: + +```Python +user_dict = user_in.model_dump() +``` + +haben wir jetzt ein `dict` mit den Daten in der Variablen `user_dict` (es ist ein `dict` statt eines Pydantic-Modellobjekts). + +Und wenn wir aufrufen: + +```Python +print(user_dict) +``` + +würden wir ein Python-`dict` erhalten mit: + +```Python +{ + 'username': 'john', + 'password': 'secret', + 'email': 'john.doe@example.com', + 'full_name': None, +} +``` + +#### Ein `dict` entpacken { #unpacking-a-dict } + +Wenn wir ein `dict` wie `user_dict` nehmen und es einer Funktion (oder Klasse) mit `**user_dict` übergeben, wird Python es „entpacken“. Es wird die Schlüssel und Werte von `user_dict` direkt als Schlüssel-Wert-Argumente übergeben. + +Setzen wir also das `user_dict` von oben ein: + +```Python +UserInDB(**user_dict) +``` + +so ist das äquivalent zu: + +```Python +UserInDB( + username="john", + password="secret", + email="john.doe@example.com", + full_name=None, +) +``` + +Oder genauer gesagt, dazu, `user_dict` direkt zu verwenden, mit welchen Inhalten es auch immer in der Zukunft haben mag: + +```Python +UserInDB( + username = user_dict["username"], + password = user_dict["password"], + email = user_dict["email"], + full_name = user_dict["full_name"], +) +``` + +#### Ein Pydantic-Modell aus dem Inhalt eines anderen { #a-pydantic-model-from-the-contents-of-another } + +Da wir im obigen Beispiel `user_dict` von `user_in.model_dump()` bekommen haben, wäre dieser Code: + +```Python +user_dict = user_in.model_dump() +UserInDB(**user_dict) +``` + +gleichwertig zu: + +```Python +UserInDB(**user_in.model_dump()) +``` + +... weil `user_in.model_dump()` ein `dict` ist, und dann lassen wir Python es „entpacken“, indem wir es an `UserInDB` mit vorangestelltem `**` übergeben. + +Auf diese Weise erhalten wir ein Pydantic-Modell aus den Daten eines anderen Pydantic-Modells. + +#### Ein `dict` entpacken und zusätzliche Schlüsselwort-Argumente { #unpacking-a-dict-and-extra-keywords } + +Und dann fügen wir das zusätzliche Schlüsselwort-Argument `hashed_password=hashed_password` hinzu, wie in: + +```Python +UserInDB(**user_in.model_dump(), hashed_password=hashed_password) +``` + +... was so ist wie: + +```Python +UserInDB( + username = user_dict["username"], + password = user_dict["password"], + email = user_dict["email"], + full_name = user_dict["full_name"], + hashed_password = hashed_password, +) +``` + +/// warning | Achtung + +Die unterstützenden zusätzlichen Funktionen `fake_password_hasher` und `fake_save_user` dienen nur zur Demo eines möglichen Datenflusses, bieten jedoch natürlich keine echte Sicherheit. + +/// + +## Verdopplung vermeiden { #reduce-duplication } + +Die Reduzierung von Code-Verdoppelung ist eine der Kernideen von **FastAPI**. + +Da die Verdopplung von Code die Wahrscheinlichkeit von Fehlern, Sicherheitsproblemen, Problemen mit der Desynchronisation des Codes (wenn Sie an einer Stelle, aber nicht an der anderen aktualisieren) usw. erhöht. + +Und diese Modelle teilen alle eine Menge der Daten und verdoppeln Attributnamen und -typen. + +Wir könnten es besser machen. + +Wir können ein `UserBase`-Modell deklarieren, das als Basis für unsere anderen Modelle dient. Und dann können wir Unterklassen dieses Modells erstellen, die seine Attribute (Typdeklarationen, Validierung usw.) erben. + +Die ganze Datenkonvertierung, -validierung, -dokumentation usw. wird immer noch wie gewohnt funktionieren. + +Auf diese Weise können wir nur die Unterschiede zwischen den Modellen (mit Klartext-`password`, mit `hashed_password` und ohne Passwort) deklarieren: + +{* ../../docs_src/extra_models/tutorial002_py310.py hl[7,13:14,17:18,21:22] *} + +## `Union` oder `anyOf` { #union-or-anyof } + +Sie können deklarieren, dass eine Response eine `Union` mehrerer Typen ist, das bedeutet, dass die Response einer von ihnen ist. + +Dies wird in OpenAPI mit `anyOf` definiert. + +Um das zu tun, verwenden Sie den Standard-Python-Typhinweis [`typing.Union`](https://docs.python.org/3/library/typing.html#typing.Union): + +/// note | Hinweis + +Wenn Sie eine [`Union`](https://docs.pydantic.dev/latest/concepts/types/#unions) definieren, listen Sie den spezifischeren Typ zuerst auf, gefolgt vom weniger spezifischen Typ. Im Beispiel unten steht `PlaneItem` vor `CarItem` in `Union[PlaneItem, CarItem]`. + +/// + +{* ../../docs_src/extra_models/tutorial003_py310.py hl[1,14:15,18:20,33] *} + +### `Union` in Python 3.10 { #union-in-python-3-10 } + +In diesem Beispiel übergeben wir `Union[PlaneItem, CarItem]` als Wert des Arguments `response_model`. + +Da wir es als **Wert an ein Argument übergeben**, anstatt es in einer **Typannotation** zu verwenden, müssen wir `Union` verwenden, sogar in Python 3.10. + +Wäre es eine Typannotation gewesen, hätten wir den vertikalen Strich verwenden können, wie in: + +```Python +some_variable: PlaneItem | CarItem +``` + +Aber wenn wir das in der Zuweisung `response_model=PlaneItem | CarItem` machen, würden wir einen Fehler erhalten, weil Python versuchen würde, eine **ungültige Operation** zwischen `PlaneItem` und `CarItem` auszuführen, anstatt es als Typannotation zu interpretieren. + +## Liste von Modellen { #list-of-models } + +Auf die gleiche Weise können Sie Responses von Listen von Objekten deklarieren. + +Dafür verwenden Sie Pythons Standard-`list`: + +{* ../../docs_src/extra_models/tutorial004_py310.py hl[18] *} + +## Response mit beliebigem `dict` { #response-with-arbitrary-dict } + +Sie können auch eine Response deklarieren, die ein einfaches beliebiges `dict` verwendet, indem Sie nur den Typ der Schlüssel und Werte deklarieren, ohne ein Pydantic-Modell zu verwenden. + +Dies ist nützlich, wenn Sie die gültigen Feld-/Attributnamen nicht im Voraus kennen (die für ein Pydantic-Modell benötigt werden würden). + +In diesem Fall können Sie `dict` verwenden: + +{* ../../docs_src/extra_models/tutorial005_py310.py hl[6] *} + +## Zusammenfassung { #recap } + +Verwenden Sie gerne mehrere Pydantic-Modelle und vererben Sie je nach Bedarf. + +Sie brauchen kein einzelnes Datenmodell pro Entität, wenn diese Entität in der Lage sein muss, verschiedene „Zustände“ zu haben. Die **Benutzer**-„Entität“ ist ein Beispiel, mit Zuständen, die `password`, `password_hash` oder kein Passwort umfassen. diff --git a/docs/de/docs/tutorial/first-steps.md b/docs/de/docs/tutorial/first-steps.md new file mode 100644 index 0000000000000..8e97b5b5d91b9 --- /dev/null +++ b/docs/de/docs/tutorial/first-steps.md @@ -0,0 +1,421 @@ +# Erste Schritte { #first-steps } + +Die einfachste FastAPI-Datei könnte wie folgt aussehen: + +{* ../../docs_src/first_steps/tutorial001_py310.py *} + +Kopieren Sie das in eine Datei `main.py`. + +Starten Sie den Live-Server: + +
+ +```console +$ fastapi dev + + FastAPI Starting development server 🚀 + + Searching for package file structure from directories + with __init__.py files + Importing from /home/user/code/awesomeapp + + module 🐍 main.py + + code Importing the FastAPI app object from the module with + the following code: + + from main import app + + app Using import string: main:app + + server Server started at http://127.0.0.1:8000 + server Documentation at http://127.0.0.1:8000/docs + + tip Running in development mode, for production use: + fastapi run + + Logs: + + INFO Will watch for changes in these directories: + ['/home/user/code/awesomeapp'] + INFO Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C + to quit) + INFO Started reloader process [383138] using WatchFiles + INFO Started server process [383153] + INFO Waiting for application startup. + INFO Application startup complete. +``` + +
+ +In der Konsolenausgabe sollte es eine Zeile geben, die ungefähr so aussieht: + +```hl_lines="4" +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +Diese Zeile zeigt die URL, unter der Ihre App auf Ihrem lokalen Computer bereitgestellt wird. + +### Es testen { #check-it } + +Öffnen Sie Ihren Browser unter [http://127.0.0.1:8000](http://127.0.0.1:8000). + +Sie werden die JSON-Response sehen: + +```JSON +{"message": "Hello World"} +``` + +### Interaktive API-Dokumentation { #interactive-api-docs } + +Gehen Sie als Nächstes auf [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs). + +Sie werden die automatisch erzeugte, interaktive API-Dokumentation sehen (bereitgestellt durch [Swagger UI](https://github.com/swagger-api/swagger-ui)): + +![Swagger UI](https://fastapi.tiangolo.com/img/index/index-01-swagger-ui-simple.png) + +### Alternative API-Dokumentation { #alternative-api-docs } + +Gehen Sie nun auf [http://127.0.0.1:8000/redoc](http://127.0.0.1:8000/redoc). + +Dort sehen Sie die alternative, automatische Dokumentation (bereitgestellt durch [ReDoc](https://github.com/Rebilly/ReDoc)): + +![ReDoc](https://fastapi.tiangolo.com/img/index/index-02-redoc-simple.png) + +### OpenAPI { #openapi } + +**FastAPI** generiert ein „Schema“ mit all Ihren APIs unter Verwendung des **OpenAPI**-Standards zur Definition von APIs. + +#### „Schema“ { #schema } + +Ein „Schema“ ist eine Definition oder Beschreibung von etwas. Nicht der eigentliche Code, der es implementiert, sondern lediglich eine abstrakte Beschreibung. + +#### API-„Schema“ { #api-schema } + +In diesem Fall ist [OpenAPI](https://github.com/OAI/OpenAPI-Specification) eine Spezifikation, die vorschreibt, wie ein Schema für Ihre API zu definieren ist. + +Diese Schemadefinition enthält Ihre API-Pfade, die möglichen Parameter, welche diese entgegennehmen, usw. + +#### Daten-„Schema“ { #data-schema } + +Der Begriff „Schema“ kann sich auch auf die Form von Daten beziehen, wie z. B. einen JSON-Inhalt. + +In diesem Fall sind die JSON-Attribute und deren Datentypen, usw. gemeint. + +#### OpenAPI und JSON Schema { #openapi-and-json-schema } + +OpenAPI definiert ein API-Schema für Ihre API. Dieses Schema enthält Definitionen (oder „Schemas“) der Daten, die von Ihrer API unter Verwendung von **JSON Schema**, dem Standard für JSON-Datenschemata, gesendet und empfangen werden. + +#### Die `openapi.json` testen { #check-the-openapi-json } + +Falls Sie wissen möchten, wie das rohe OpenAPI-Schema aussieht: FastAPI generiert automatisch ein JSON (Schema) mit den Beschreibungen Ihrer gesamten API. + +Sie können es direkt einsehen unter: [http://127.0.0.1:8000/openapi.json](http://127.0.0.1:8000/openapi.json). + +Es wird ein JSON angezeigt, welches ungefähr so aussieht: + +```JSON +{ + "openapi": "3.1.0", + "info": { + "title": "FastAPI", + "version": "0.1.0" + }, + "paths": { + "/items/": { + "get": { + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + + + +... +``` + +#### Wofür OpenAPI gedacht ist { #what-is-openapi-for } + +Das OpenAPI-Schema ist die Grundlage für die beiden enthaltenen interaktiven Dokumentationssysteme. + +Es gibt dutzende Alternativen, die alle auf OpenAPI basieren. Sie können jede dieser Alternativen problemlos zu Ihrer mit **FastAPI** erstellten Anwendung hinzufügen. + +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. + +### Den App-`entrypoint` in `pyproject.toml` konfigurieren { #configure-the-app-entrypoint-in-pyproject-toml } + +Sie können in einer `pyproject.toml`-Datei konfigurieren, wo sich Ihre App befindet, z. B.: + +```toml +[tool.fastapi] +entrypoint = "main:app" +``` + +Dieser `entrypoint` teilt dem `fastapi`-Befehl mit, dass er die App folgendermaßen importieren soll: + +```python +from main import app +``` + +Wenn Ihr Code so strukturiert wäre: + +``` +. +├── backend +│   ├── main.py +│   ├── __init__.py +``` + +Dann würden Sie den `entrypoint` so setzen: + +```toml +[tool.fastapi] +entrypoint = "backend.main:app" +``` + +was äquivalent wäre zu: + +```python +from backend.main import app +``` + +### `fastapi dev` mit Pfad oder mit der CLI-Option `--entrypoint` { #fastapi-dev-with-path-or-with-entrypoint-cli-option } + +Sie können auch den Dateipfad an den Befehl `fastapi dev` übergeben, und er wird das zu verwendende FastAPI-App-Objekt erraten: + +```console +$ fastapi dev main.py +``` + +Oder Sie können die Option `--entrypoint` an den Befehl `fastapi dev` übergeben: + +```console +$ fastapi dev --entrypoint main:app +``` + +Aber Sie müssten sich daran erinnern, bei jedem Aufruf des `fastapi`-Befehls den korrekten Pfad\entrypoint zu übergeben. + +Zusätzlich könnten andere Tools es nicht finden, z. B. die [VS Code-Erweiterung](../editor-support.md) oder [FastAPI Cloud](https://fastapicloud.com). Daher wird empfohlen, den `entrypoint` in `pyproject.toml` zu verwenden. + +### Ihre App deployen (optional) { #deploy-your-app-optional } + +Sie können optional Ihre FastAPI-App in der [FastAPI Cloud](https://fastapicloud.com) mit einem einzigen Befehl deployen. 🚀 + +
+ +```console +$ fastapi deploy + +Deploying to FastAPI Cloud... + +✅ Deployment successful! + +🐔 Ready the chicken! Your app is ready at https://myapp.fastapicloud.dev +``` + +
+ +Das CLI erkennt Ihre FastAPI-Anwendung automatisch und deployt sie in die Cloud. Wenn Sie nicht eingeloggt sind, wird Ihr Browser geöffnet, um die Authentifizierung abzuschließen. + +Das war's! Jetzt können Sie Ihre App unter dieser URL aufrufen. ✨ + +## Zusammenfassung, Schritt für Schritt { #recap-step-by-step } + +### Schritt 1: `FastAPI` importieren { #step-1-import-fastapi } + +{* ../../docs_src/first_steps/tutorial001_py310.py hl[1] *} + +`FastAPI` ist eine Python-Klasse, die die gesamte Funktionalität für Ihre API bereitstellt. + +/// note | Technische Details + +`FastAPI` ist eine Klasse, die direkt von `Starlette` erbt. + +Sie können alle [Starlette](https://www.starlette.dev/)-Funktionalitäten auch mit `FastAPI` nutzen. + +/// + +### Schritt 2: Eine `FastAPI`-„Instanz“ erstellen { #step-2-create-a-fastapi-instance } + +{* ../../docs_src/first_steps/tutorial001_py310.py hl[3] *} + +In diesem Beispiel ist die Variable `app` eine „Instanz“ der Klasse `FastAPI`. + +Dies wird der Hauptinteraktionspunkt für die Erstellung all Ihrer APIs sein. + +### Schritt 3: Eine *Pfadoperation* erstellen { #step-3-create-a-path-operation } + +#### Pfad { #path } + +„Pfad“ bezieht sich hier auf den letzten Teil der URL, beginnend mit dem ersten `/`. + +In einer URL wie: + +``` +https://example.com/items/foo +``` + +... wäre der Pfad folglich: + +``` +/items/foo +``` + +/// note | Hinweis + +Ein „Pfad“ wird häufig auch als „Endpunkt“ oder „Route“ bezeichnet. + +/// + +Bei der Erstellung einer API ist der „Pfad“ die wichtigste Möglichkeit zur Trennung von „Anliegen“ und „Ressourcen“. + +#### Operation { #operation } + +„Operation“ bezieht sich hier auf eine der HTTP-„Methoden“. + +Eine von diesen: + +* `POST` +* `GET` +* `PUT` +* `DELETE` + +... und die etwas Exotischeren: + +* `OPTIONS` +* `HEAD` +* `PATCH` +* `TRACE` + +Im HTTP-Protokoll können Sie mit jedem Pfad über eine (oder mehrere) dieser „Methoden“ kommunizieren. + +--- + +Bei der Erstellung von APIs verwenden Sie normalerweise diese spezifischen HTTP-Methoden, um eine bestimmte Aktion durchzuführen. + +Normalerweise verwenden Sie: + +* `POST`: um Daten zu erzeugen (create). +* `GET`: um Daten zu lesen (read). +* `PUT`: um Daten zu aktualisieren (update). +* `DELETE`: um Daten zu löschen (delete). + +In OpenAPI wird folglich jede dieser HTTP-Methoden als „Operation“ bezeichnet. + +Wir werden sie auch „**Operationen**“ nennen. + +#### Einen *Pfadoperation-Dekorator* definieren { #define-a-path-operation-decorator } + +{* ../../docs_src/first_steps/tutorial001_py310.py hl[6] *} + +Das `@app.get("/")` sagt **FastAPI**, dass die Funktion direkt darunter für die Bearbeitung von Requests zuständig ist, die an: + +* den Pfad `/` +* unter der Verwendung der get-Operation gehen + +/// note | `@decorator` Info + +Diese `@something`-Syntax wird in Python „Dekorator“ genannt. + +Sie platzieren ihn über einer Funktion. Wie ein hübscher, dekorativer Hut (daher kommt wohl der Begriff). + +Ein „Dekorator“ nimmt die darunter stehende Funktion und macht etwas damit. + +In unserem Fall teilt dieser Dekorator **FastAPI** mit, dass die folgende Funktion mit dem **Pfad** `/` und der **Operation** `get` zusammenhängt. + +Dies ist der „**Pfadoperation-Dekorator**“. + +/// + +Sie können auch die anderen Operationen verwenden: + +* `@app.post()` +* `@app.put()` +* `@app.delete()` + +Und die exotischeren: + +* `@app.options()` +* `@app.head()` +* `@app.patch()` +* `@app.trace()` + +/// tip | Tipp + +Es steht Ihnen frei, jede Operation (HTTP-Methode) so zu verwenden, wie Sie es möchten. + +**FastAPI** erzwingt keine bestimmte Bedeutung. + +Die hier aufgeführten Informationen dienen als Leitfaden und sind nicht verbindlich. + +Wenn Sie beispielsweise GraphQL verwenden, führen Sie normalerweise alle Aktionen nur mit „POST“-Operationen durch. + +/// + +### Schritt 4: Die **Pfadoperation-Funktion** definieren { #step-4-define-the-path-operation-function } + +Das ist unsere „**Pfadoperation-Funktion**“: + +* **Pfad**: ist `/`. +* **Operation**: ist `get`. +* **Funktion**: ist die Funktion direkt unter dem „Dekorator“ (unter `@app.get("/")`). + +{* ../../docs_src/first_steps/tutorial001_py310.py hl[7] *} + +Dies ist eine Python-Funktion. + +Sie wird von **FastAPI** immer dann aufgerufen, wenn sie einen Request an die URL „`/`“ mittels einer `GET`-Operation erhält. + +In diesem Fall handelt es sich um eine `async`-Funktion. + +--- + +Sie könnten sie auch als normale Funktion anstelle von `async def` definieren: + +{* ../../docs_src/first_steps/tutorial003_py310.py hl[7] *} + +/// note | Hinweis + +Wenn Sie den Unterschied nicht kennen, lesen Sie [Async: *„In Eile?“*](../async.md#in-a-hurry). + +/// + +### Schritt 5: den Inhalt zurückgeben { #step-5-return-the-content } + +{* ../../docs_src/first_steps/tutorial001_py310.py hl[8] *} + +Sie können ein `dict`, eine `list`, einzelne Werte wie `str`, `int`, usw. zurückgeben. + +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. + +### Schritt 6: Deployen { #step-6-deploy-it } + +Stellen Sie Ihre App in der **[FastAPI Cloud](https://fastapicloud.com)** mit einem Befehl bereit: `fastapi deploy`. 🎉 + +#### Über FastAPI Cloud { #about-fastapi-cloud } + +**[FastAPI Cloud](https://fastapicloud.com)** wird vom selben Autor und Team hinter **FastAPI** entwickelt. + +Es vereinfacht den Prozess des **Erstellens**, **Deployens** und des **Zugriffs** auf eine API mit minimalem Aufwand. + +Es 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 } + +* Importieren Sie `FastAPI`. +* Erstellen Sie eine `app`-Instanz. +* Schreiben Sie einen **Pfadoperation-Dekorator** unter Verwendung von Dekoratoren wie `@app.get("/")`. +* Definieren Sie eine **Pfadoperation-Funktion**, zum Beispiel `def root(): ...`. +* Starten Sie den Entwicklungsserver mit dem Befehl `fastapi dev`. +* Optional: Ihre App mit `fastapi deploy` deployen. diff --git a/docs/de/docs/tutorial/frontend.md b/docs/de/docs/tutorial/frontend.md new file mode 100644 index 0000000000000..9cd4644d915fb --- /dev/null +++ b/docs/de/docs/tutorial/frontend.md @@ -0,0 +1,133 @@ +# Frontend { #frontend } + +Sie können statische Frontend-Apps mit `app.frontend()` (oder `router.frontend()`) bereitstellen. + +Das ist nützlich für Frontend-Tools, die statische Dateien generieren, wie React mit Vite, TanStack Router, Astro, Vue, Svelte, Angular, Solid und andere. + +Mit diesen Tools haben Sie normalerweise einen Schritt, der das Frontend baut, mit einem Befehl wie: + +```bash +npm run build +``` + +Das würde ein Verzeichnis wie `./dist/` mit Ihren Frontend-Dateien generieren. + +Sie können `app.frontend()` verwenden, um dieses Verzeichnis gemäß den Konventionen bereitzustellen, die von diesen Frontend-Frameworks benötigt werden. + +**FastAPI** prüft zuerst *Pfadoperationen*. Die Frontend-Dateien werden nur geprüft, wenn keine normale Route gepasst hat, sodass Ihre API nicht beeinträchtigt wird. + +## Ein Frontend bereitstellen { #serve-a-frontend } + +Nachdem Sie Ihr Frontend gebaut haben, zum Beispiel mit `npm run build`, legen Sie die generierten Dateien in ein Verzeichnis, zum Beispiel `dist`. + +Ihre Projektstruktur könnte so aussehen: + +```text +. +├── pyproject.toml +├── app +│ ├── __init__.py +│ └── main.py +└── dist + ├── index.html + └── assets + └── app.js +``` + +Stellen Sie es dann mit `app.frontend()` bereit: + +{* ../../docs_src/frontend/tutorial001_py310.py hl[5] *} + +Damit kann ein Request für `/assets/app.js` `dist/assets/app.js` ausliefern. + +Wenn Sie außerdem eine **FastAPI**-*Pfadoperation* haben, gewinnt die *Pfadoperation*. + +## Clientseitiges Routing { #client-side-routing } + +Viele Frontend-Apps, einschließlich **Single-Page-Apps** (SPAs), verwenden clientseitiges Routing. Ein Pfad wie `/dashboard/settings` ist möglicherweise keine echte Datei, aber das Framework würde sich darum kümmern, ihn zu handhaben. + +Wenn also direkt auf diese URL zugegriffen wird (statt durch die App zu navigieren), sollte das Backend die Frontend-App von `index.html` bereitstellen, sodass das Frontend-Framework anschließend das clientseitige Routing handhaben kann. + +Verwenden Sie dafür `fallback="index.html"`: + +{* ../../docs_src/frontend/tutorial002_py310.py hl[5] *} + +**FastAPI** verwendet diesen Fallback nur für `GET`- und `HEAD`-Requests, die wie Browser-Navigation aussehen. Fehlende Dateien wie JavaScript, CSS und Bilder geben weiterhin `404` zurück. + +Requests mit anderen Methoden, wie `POST` oder `PUT`, an Pfade, die nur zum Frontend-Fallback passen, geben ebenfalls `404` zurück. Reguläre **FastAPI**-*Pfadoperationen* haben weiterhin eine höhere Priorität als Frontend-Routen. + +/// tip | Tipp + +Standardmäßig hat `fallback` einen Wert von `fallback="auto"`. In den meisten Fällen müssen Sie `fallback` nicht angeben. Lesen Sie weiter unten die Details. + +/// + +Das ist das, was Sie bei vielen Frontend-Apps möchten, die clientseitiges Routing verwenden, zum Beispiel React mit TanStack Router, Vue, Angular, SvelteKit oder Solid. + +## Benutzerdefinierte 404-Seite { #custom-404-page } + +Sie können auch eine statische `404.html`-Seite für fehlende Frontend-Pfade ausliefern: + +{* ../../docs_src/frontend/tutorial003_py310.py hl[5] *} + +Diese Response behält einen Statuscode von `404`. + +In diesem Fall liefert **FastAPI** für fehlende Frontend-Pfade nicht `index.html` aus. Stattdessen wird die Datei `404.html` zurückgegeben. + +/// tip | Tipp + +Standardmäßig hat `fallback` einen Wert von `fallback="auto"`. Damit wird, wenn eine `404.html`-Datei gefunden wird, diese automatisch als Fallback verwendet. + +Sie können das `fallback`-Argument also normalerweise weglassen. + +/// + +Das ist nützlich bei Frontend-Tools, die für jede Seite statische HTML-Dateien generieren, wie Astro. + +## Automatischer Fallback { #fallback-auto } + +Standardmäßig verwendet `app.frontend()` `fallback="auto"`. + +Wenn es im Frontend-Verzeichnis eine `404.html`-Datei gibt, liefern fehlende Frontend-Pfade diese Datei mit dem Statuscode `404` aus. + +Andernfalls, wenn es eine `index.html`-Datei gibt, liefern fehlende Browser-Navigationspfade `index.html` aus, was viele Frontend-Apps mit clientseitigem Routing erwarten. + +In den meisten Fällen können Sie also `app.frontend("/", directory="dist")` verwenden, ohne das `fallback`-Argument anzugeben. + +{* ../../docs_src/frontend/tutorial001_py310.py hl[5] *} + +## Fallback deaktivieren { #disable-fallback } + +Wenn Sie keine Fallback-Datei für fehlende Frontend-Pfade ausliefern möchten, verwenden Sie `fallback=None`: + +{* ../../docs_src/frontend/tutorial005_py310.py hl[5] *} + +Dann geben fehlende Frontend-Pfade das normale `404` zurück. + +## Verzeichnis prüfen { #check-directory } + +Standardmäßig prüft `app.frontend()`, dass das Verzeichnis existiert, wenn die App erstellt wird. + +Das hilft, Konfigurationsfehler früh zu erkennen. Wenn zum Beispiel das Output-Verzeichnis des Frontend-Builds fehlt, löst **FastAPI** beim Startup einen Fehler aus. + +Wenn Ihre Frontend-Dateien später erstellt werden, zum Beispiel durch einen separaten Build-Schritt, nachdem das App-Objekt erstellt wurde, setzen Sie `check_dir=False`: + +{* ../../docs_src/frontend/tutorial006_py310.py hl[5] *} + +Mit `check_dir=False` prüft **FastAPI** das Verzeichnis nicht, wenn die App erstellt wird. Wenn das konfigurierte Verzeichnis beim Verarbeiten eines Requests immer noch fehlt, löst **FastAPI** dann einen Fehler aus. + +## Mit `APIRouter` verwenden { #use-it-with-apirouter } + +Sie können Frontend-Dateien auch zu einem `APIRouter` hinzufügen und ihn mit einem Präfix einbinden: + +{* ../../docs_src/frontend/tutorial004_py310.py hl[6,7] *} + +In diesem Beispiel werden Frontend-Pfade unter `/app` bereitgestellt. + +Alle regulären *Pfadoperationen* in der App haben weiterhin Vorrang, auch in anderen Routern. + +## Nur statischer Build-Output { #static-build-output-only } + +`app.frontend()` liefert Dateien aus, die bereits von Ihrem Frontend-Build generiert wurden. + +Es führt kein serverseitiges Rendering aus. Es ist für Frontend-Frameworks gedacht, die statische Dateien generieren, nicht für Frameworks, die dynamisches Rendering auf dem Server für jeden Request benötigen. diff --git a/docs/de/docs/tutorial/handling-errors.md b/docs/de/docs/tutorial/handling-errors.md new file mode 100644 index 0000000000000..17e2767fef7b3 --- /dev/null +++ b/docs/de/docs/tutorial/handling-errors.md @@ -0,0 +1,244 @@ +# Fehler behandeln { #handling-errors } + +Es gibt viele Situationen, in denen Sie einem Client, der Ihre API nutzt, einen Fehler mitteilen müssen. + +Dieser Client könnte ein Browser mit einem Frontend sein, ein Code von jemand anderem, ein IoT-Gerät usw. + +Sie könnten dem Client mitteilen müssen, dass: + +* Der Client nicht genügend Berechtigungen für diese Operation hat. +* Der Client keinen Zugriff auf diese Ressource hat. +* Das Item, auf das der Client versucht hat zuzugreifen, nicht existiert. +* usw. + +In diesen Fällen würden Sie normalerweise einen **HTTP-Statuscode** im Bereich **400** (von 400 bis 499) zurückgeben. + +Dies ist vergleichbar mit den HTTP-Statuscodes im Bereich 200 (von 200 bis 299). Diese „200“-Statuscodes bedeuten, dass der Request irgendwie ein „Erfolg“ war. + +Die Statuscodes im Bereich 400 bedeuten hingegen, dass es einen Fehler seitens des Clients gab. + +Erinnern Sie sich an all diese **„404 Not Found“** Fehler (und Witze)? + +## `HTTPException` verwenden { #use-httpexception } + +Um HTTP-Responses mit Fehlern an den Client zurückzugeben, verwenden Sie `HTTPException`. + +### `HTTPException` importieren { #import-httpexception } + +{* ../../docs_src/handling_errors/tutorial001_py310.py hl[1] *} + +### Eine `HTTPException` in Ihrem Code auslösen { #raise-an-httpexception-in-your-code } + +`HTTPException` ist eine normale Python-Exception mit zusätzlichen Daten, die für APIs relevant sind. + +Weil es eine Python-Exception ist, geben Sie sie nicht zurück (`return`), sondern lösen sie aus (`raise`). + +Das bedeutet auch, wenn Sie sich innerhalb einer Hilfsfunktion befinden, die Sie innerhalb Ihrer *Pfadoperation-Funktion* aufrufen, und Sie die `HTTPException` aus dieser Hilfsfunktion heraus auslösen, wird der restliche Code in der *Pfadoperation-Funktion* nicht ausgeführt. Der Request wird sofort abgebrochen und der HTTP-Error der `HTTPException` wird an den Client gesendet. + +Der Vorteil des Auslösens einer Exception gegenüber dem Zurückgeben eines Wertes wird im Abschnitt über Abhängigkeiten und Sicherheit deutlicher werden. + +In diesem Beispiel lösen wir eine Exception mit einem Statuscode von `404` aus, wenn der Client ein Item mit einer nicht existierenden ID anfordert: + +{* ../../docs_src/handling_errors/tutorial001_py310.py hl[11] *} + +### Die resultierende Response { #the-resulting-response } + +Wenn der Client `http://example.com/items/foo` anfordert (ein `item_id` `"foo"`), erhält dieser Client einen HTTP-Statuscode 200 und diese JSON-Response: + +```JSON +{ + "item": "The Foo Wrestlers" +} +``` + +Aber wenn der Client `http://example.com/items/bar` anfordert (ein nicht-existierendes `item_id` `"bar"`), erhält er einen HTTP-Statuscode 404 (der „not found“-Error) und eine JSON-Response wie: + +```JSON +{ + "detail": "Item not found" +} +``` + +/// tip | Tipp + +Wenn Sie eine `HTTPException` auslösen, können Sie dem Parameter `detail` jeden Wert übergeben, der in JSON konvertiert werden kann, nicht nur `str`. + +Sie könnten ein `dict`, eine `list`, usw. übergeben. + +Diese werden von **FastAPI** automatisch gehandhabt und in JSON konvertiert. + +/// + +## Benutzerdefinierte Header hinzufügen { #add-custom-headers } + +Es gibt Situationen, in denen es nützlich ist, dem HTTP-Error benutzerdefinierte Header hinzuzufügen. Zum Beispiel für einige Arten von Sicherheit. + +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: + +{* ../../docs_src/handling_errors/tutorial002_py310.py hl[14] *} + +## Benutzerdefinierte Exceptionhandler installieren { #install-custom-exception-handlers } + +Sie können benutzerdefinierte Exceptionhandler mit [denselben Exception-Werkzeugen von Starlette](https://www.starlette.dev/exceptions/) hinzufügen. + +Angenommen, Sie haben eine benutzerdefinierte Exception `UnicornException`, die Sie (oder eine Bibliothek, die Sie verwenden) `raise`n könnten. + +Und Sie möchten diese Exception global mit FastAPI handhaben. + +Sie könnten einen benutzerdefinierten Exceptionhandler mit `@app.exception_handler()` hinzufügen: + +{* ../../docs_src/handling_errors/tutorial003_py310.py hl[5:7,13:18,24] *} + +Hier, wenn Sie `/unicorns/yolo` anfordern, wird die *Pfadoperation* eine `UnicornException` `raise`n. + +Aber diese wird von `unicorn_exception_handler` gehandhabt. + +Sie erhalten also einen sauberen Fehler mit einem HTTP-Statuscode von `418` und dem JSON-Inhalt: + +```JSON +{"message": "Oops! yolo did something. There goes a rainbow..."} +``` + +/// note | Technische Details + +Sie könnten auch `from starlette.requests import Request` und `from starlette.responses import JSONResponse` verwenden. + +**FastAPI** bietet dieselben `starlette.responses` auch via `fastapi.responses` an, nur als Annehmlichkeit für Sie, den Entwickler. Aber die meisten verfügbaren Responses kommen direkt von Starlette. Dasselbe gilt für `Request`. + +/// + +## Die Default-Exceptionhandler überschreiben { #override-the-default-exception-handlers } + +**FastAPI** hat einige Default-Exceptionhandler. + +Diese Handler sind dafür verantwortlich, die Default-JSON-Responses zurückzugeben, wenn Sie eine `HTTPException` `raise`n und wenn der Request ungültige Daten enthält. + +Sie können diese Exceptionhandler mit Ihren eigenen überschreiben. + +### Request-Validierungs-Exceptions überschreiben { #override-request-validation-exceptions } + +Wenn ein Request ungültige Daten enthält, löst **FastAPI** intern einen `RequestValidationError` aus. + +Und es enthält auch einen Default-Exceptionhandler für diesen. + +Um diesen zu überschreiben, importieren Sie den `RequestValidationError` und verwenden Sie ihn mit `@app.exception_handler(RequestValidationError)`, um den Exceptionhandler zu dekorieren. + +Der Exceptionhandler erhält einen `Request` und die Exception. + +{* ../../docs_src/handling_errors/tutorial004_py310.py hl[2,14:19] *} + +Wenn Sie nun zu `/items/foo` gehen, erhalten Sie anstelle des standardmäßigen JSON-Fehlers mit: + +```JSON +{ + "detail": [ + { + "loc": [ + "path", + "item_id" + ], + "msg": "value is not a valid integer", + "type": "type_error.integer" + } + ] +} +``` + +eine Textversion mit: + +``` +Validation errors: +Field: ('path', 'item_id'), Error: Input should be a valid integer, unable to parse string as an integer +``` + +### Den `HTTPException`-Fehlerhandler überschreiben { #override-the-httpexception-error-handler } + +Auf die gleiche Weise können Sie den `HTTPException`-Handler überschreiben. + +Zum Beispiel könnten Sie eine Klartext-Response statt JSON für diese Fehler zurückgeben wollen: + +{* ../../docs_src/handling_errors/tutorial004_py310.py hl[3:4,9:11,25] *} + +/// note | Technische Details + +Sie könnten auch `from starlette.responses import PlainTextResponse` verwenden. + +**FastAPI** bietet dieselben `starlette.responses` auch via `fastapi.responses` an, nur als Annehmlichkeit für Sie, den Entwickler. Aber die meisten verfügbaren Responses kommen direkt von Starlette. + +/// + +/// 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. + +/// + +### Den `RequestValidationError`-Body verwenden { #use-the-requestvalidationerror-body } + +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. + +{* ../../docs_src/handling_errors/tutorial005_py310.py hl[14] *} + +Versuchen Sie nun, ein ungültiges Item zu senden: + +```JSON +{ + "title": "towel", + "size": "XL" +} +``` + +Sie erhalten eine Response, die Ihnen sagt, dass die Daten ungültig sind, und die den empfangenen Body enthält: + +```JSON hl_lines="12-15" +{ + "detail": [ + { + "loc": [ + "body", + "size" + ], + "msg": "value is not a valid integer", + "type": "type_error.integer" + } + ], + "body": { + "title": "towel", + "size": "XL" + } +} +``` + +#### FastAPIs `HTTPException` vs. Starlettes `HTTPException` { #fastapis-httpexception-vs-starlettes-httpexception } + +**FastAPI** hat seine eigene `HTTPException`. + +Und die `HTTPException`-Fehlerklasse von **FastAPI** erbt von der `HTTPException`-Fehlerklasse von Starlette. + +Der einzige Unterschied besteht darin, dass die `HTTPException` von **FastAPI** beliebige JSON-konvertierbare Daten für das `detail`-Feld akzeptiert, während die `HTTPException` von Starlette nur Strings dafür akzeptiert. + +Sie können also weiterhin die `HTTPException` von **FastAPI** wie üblich in Ihrem Code auslösen. + +Aber wenn Sie einen Exceptionhandler registrieren, sollten Sie ihn für die `HTTPException` von Starlette registrieren. + +Auf diese Weise, wenn irgendein Teil des internen Codes von Starlette, oder eine Starlette-Erweiterung oder ein Plug-in, eine Starlette `HTTPException` auslöst, wird Ihr Handler in der Lage sein, diese abzufangen und zu handhaben. + +Um in diesem Beispiel beide `HTTPException`s im selben Code zu haben, wird die Exception von Starlette zu `StarletteHTTPException` umbenannt: + +```Python +from starlette.exceptions import HTTPException as StarletteHTTPException +``` + +### Die Exceptionhandler von **FastAPI** wiederverwenden { #reuse-fastapis-exception-handlers } + +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_py310.py hl[2:5,15,21] *} + +In diesem Beispiel geben Sie nur den Fehler mit einer sehr ausdrucksstarken Nachricht aus, aber Sie verstehen das Prinzip. Sie können die Exception verwenden und dann einfach die Default-Exceptionhandler wiederverwenden. diff --git a/docs/de/docs/tutorial/header-param-models.md b/docs/de/docs/tutorial/header-param-models.md new file mode 100644 index 0000000000000..8c1bf61aec889 --- /dev/null +++ b/docs/de/docs/tutorial/header-param-models.md @@ -0,0 +1,72 @@ +# Header-Parameter-Modelle { #header-parameter-models } + +Wenn Sie eine Gruppe verwandter **Header-Parameter** haben, können Sie ein **Pydantic-Modell** erstellen, um diese zu deklarieren. + +Dadurch können Sie das **Modell an mehreren Stellen wiederverwenden** und auch Validierungen und Metadaten für alle Parameter gleichzeitig deklarieren. 😎 + +/// note | Hinweis + +Dies wird seit FastAPI Version `0.115.0` unterstützt. 🤓 + +/// + +## Header-Parameter mit einem Pydantic-Modell { #header-parameters-with-a-pydantic-model } + +Deklarieren Sie die erforderlichen **Header-Parameter** in einem **Pydantic-Modell** und dann den Parameter als `Header`: + +{* ../../docs_src/header_param_models/tutorial001_an_py310.py hl[9:14,18] *} + +**FastAPI** wird die Daten für **jedes Feld** aus den **Headern** des Request extrahieren und Ihnen das von Ihnen definierte Pydantic-Modell geben. + +## Die Dokumentation testen { #check-the-docs } + +Sie können die erforderlichen Header in der Dokumentationsoberfläche unter `/docs` sehen: + +
+ +
+ +## Zusätzliche Header verbieten { #forbid-extra-headers } + +In einigen speziellen Anwendungsfällen (wahrscheinlich nicht sehr häufig) möchten Sie möglicherweise die **Header einschränken**, die Sie erhalten möchten. + +Sie können Pydantics Modellkonfiguration verwenden, um `extra` Felder zu verbieten (`forbid`): + +{* ../../docs_src/header_param_models/tutorial002_an_py310.py hl[10] *} + +Wenn ein Client versucht, einige **zusätzliche Header** zu senden, erhält er eine **Error-Response**. + +Zum Beispiel, wenn der Client versucht, einen `tool`-Header mit einem Wert von `plumbus` zu senden, erhält er eine **Error-Response**, die ihm mitteilt, dass der Header-Parameter `tool` nicht erlaubt ist: + +```json +{ + "detail": [ + { + "type": "extra_forbidden", + "loc": ["header", "tool"], + "msg": "Extra inputs are not permitted", + "input": "plumbus", + } + ] +} +``` + +## Automatische Umwandlung von Unterstrichen deaktivieren { #disable-convert-underscores } + +Ähnlich wie bei regulären Header-Parametern werden bei der Verwendung von Unterstrichen in den Parameternamen diese **automatisch in Bindestriche umgewandelt**. + +Wenn Sie beispielsweise einen Header-Parameter `save_data` im Code haben, wird der erwartete HTTP-Header `save-data` sein, und er wird auch so in der Dokumentation angezeigt. + +Falls Sie aus irgendeinem Grund diese automatische Umwandlung deaktivieren müssen, können Sie dies auch für Pydantic-Modelle für Header-Parameter tun. + +{* ../../docs_src/header_param_models/tutorial003_an_py310.py hl[19] *} + +/// warning | Achtung + +Bevor Sie `convert_underscores` auf `False` setzen, bedenken Sie, dass einige HTTP-Proxies und -Server die Verwendung von Headern mit Unterstrichen nicht zulassen. + +/// + +## Zusammenfassung { #summary } + +Sie können **Pydantic-Modelle** verwenden, um **Header** in **FastAPI** zu deklarieren. 😎 diff --git a/docs/de/docs/tutorial/header-params.md b/docs/de/docs/tutorial/header-params.md new file mode 100644 index 0000000000000..4876f00e2ed8f --- /dev/null +++ b/docs/de/docs/tutorial/header-params.md @@ -0,0 +1,91 @@ +# Header-Parameter { #header-parameters } + +Sie können Header-Parameter genauso definieren, wie Sie `Query`-, `Path`- und `Cookie`-Parameter definieren. + +## `Header` importieren { #import-header } + +Importieren Sie zuerst `Header`: + +{* ../../docs_src/header_params/tutorial001_an_py310.py hl[3] *} + +## `Header`-Parameter deklarieren { #declare-header-parameters } + +Deklarieren Sie dann die Header-Parameter mit derselben Struktur wie bei `Path`, `Query` und `Cookie`. + +Sie können den Defaultwert sowie alle zusätzlichen Validierungs- oder Annotationsparameter definieren: + +{* ../../docs_src/header_params/tutorial001_an_py310.py hl[9] *} + +/// note | Technische Details + +`Header` ist eine „Schwester“-Klasse von `Path`, `Query` und `Cookie`. Sie erbt ebenfalls von der gemeinsamen `Param`-Klasse. + +Aber denken Sie daran, dass bei der Nutzung von `Query`, `Path`, `Header` und anderen Importen aus `fastapi`, diese tatsächlich Funktionen sind, die spezielle Klassen zurückgeben. + +/// + +/// note | Hinweis + +Um Header zu deklarieren, müssen Sie `Header` verwenden, da die Parameter sonst als Query-Parameter interpretiert werden würden. + +/// + +## Automatische Konvertierung { #automatic-conversion } + +`Header` bietet etwas zusätzliche Funktionalität im Vergleich zu `Path`, `Query` und `Cookie`. + +Die meisten Standard-Header sind durch ein „Bindestrich“-Zeichen getrennt, auch bekannt als „Minus-Symbol“ (`-`). + +Aber eine Variable wie `user-agent` ist in Python ungültig. + +Daher wird `Header` standardmäßig die Zeichen des Parameter-Namens von Unterstrich (`_`) zu Bindestrich (`-`) konvertieren, um die Header zu extrahieren und zu dokumentieren. + +Außerdem ist Groß-/Klein­schrei­bung in HTTP-Headern nicht relevant, daher können Sie sie im Standard-Python-Stil (auch bekannt als „snake_case“) deklarieren. + +Sie können also `user_agent` verwenden, wie Sie es normalerweise im Python-Code tun würden, anstatt die Anfangsbuchstaben wie bei `User_Agent` großzuschreiben oder Ähnliches. + +Wenn Sie aus irgendeinem Grund die automatische Konvertierung von Unterstrichen zu Bindestrichen deaktivieren müssen, setzen Sie den Parameter `convert_underscores` von `Header` auf `False`: + +{* ../../docs_src/header_params/tutorial002_an_py310.py hl[10] *} + +/// warning | Achtung + +Bevor Sie `convert_underscores` auf `False` setzen, bedenken Sie, dass manche HTTP-Proxys und Server die Verwendung von Headern mit Unterstrichen nicht erlauben. + +/// + +## Doppelte Header { #duplicate-headers } + +Es ist möglich, doppelte Header zu empfangen. Damit ist gemeint, denselben Header mit mehreren Werten. + +Sie können solche Fälle definieren, indem Sie in der Typdeklaration eine Liste verwenden. + +Sie erhalten dann alle Werte von diesem doppelten Header als Python-`list`. + +Um beispielsweise einen `X-Token`-Header zu deklarieren, der mehrmals vorkommen kann, können Sie schreiben: + +{* ../../docs_src/header_params/tutorial003_an_py310.py hl[9] *} + +Wenn Sie mit dieser *Pfadoperation* kommunizieren und zwei HTTP-Header senden, wie: + +``` +X-Token: foo +X-Token: bar +``` + +Dann wäre die Response: + +```JSON +{ + "X-Token values": [ + "bar", + "foo" + ] +} +``` + +## Zusammenfassung { #recap } + +Deklarieren Sie Header mit `Header`, wobei Sie dasselbe gängige Muster wie bei `Query`, `Path` und `Cookie` verwenden. + +Und machen Sie sich keine Sorgen um Unterstriche in Ihren Variablen, **FastAPI** wird sich darum kümmern, sie zu konvertieren. diff --git a/docs/de/docs/tutorial/index.md b/docs/de/docs/tutorial/index.md new file mode 100644 index 0000000000000..c0f25c916d451 --- /dev/null +++ b/docs/de/docs/tutorial/index.md @@ -0,0 +1,102 @@ +# Tutorial – Benutzerhandbuch { #tutorial-user-guide } + + +Dieses Tutorial zeigt Ihnen Schritt für Schritt, wie Sie **FastAPI** mit den meisten seiner Funktionen verwenden können. + +Jeder Abschnitt baut schrittweise auf den vorhergehenden auf, ist jedoch in einzelne Themen gegliedert, sodass Sie direkt zu einem bestimmten Thema übergehen können, um Ihre spezifischen API-Anforderungen zu lösen. + +Es ist auch so gestaltet, dass es als zukünftige Referenz dient, sodass Sie jederzeit zurückkommen und genau das sehen, was Sie benötigen. + +## Den Code ausführen { #run-the-code } + +Alle Codeblöcke können kopiert und direkt verwendet werden (es sind tatsächlich getestete Python-Dateien). + +Um eines der Beispiele auszuführen, kopieren Sie den Code in eine Datei `main.py`, und starten Sie `fastapi dev`: + +
+ +```console +$ fastapi dev + + FastAPI Starting development server 🚀 + + Searching for package file structure from directories + with __init__.py files + Importing from /home/user/code/awesomeapp + + module 🐍 main.py + + code Importing the FastAPI app object from the module with + the following code: + + from main import app + + app Using import string: main:app + + server Server started at http://127.0.0.1:8000 + server Documentation at http://127.0.0.1:8000/docs + + tip Running in development mode, for production use: + fastapi run + + Logs: + + INFO Will watch for changes in these directories: + ['/home/user/code/awesomeapp'] + INFO Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C + to quit) + INFO Started reloader process [383138] using WatchFiles + INFO Started server process [383153] + INFO Waiting for application startup. + INFO Application startup complete. +``` + +
+ +Es wird **dringend empfohlen**, den Code zu schreiben oder zu kopieren, ihn zu bearbeiten und lokal auszuführen. + +Die Verwendung in Ihrem eigenen Editor zeigt Ihnen die Vorteile von FastAPI am besten, wenn Sie sehen, wie wenig Code Sie schreiben müssen, all die Typprüfungen, die automatische Vervollständigung usw. + +--- + +## FastAPI installieren { #install-fastapi } + +Der erste Schritt besteht darin, FastAPI zu installieren. + +Stellen Sie sicher, dass Sie eine [virtuelle Umgebung](../virtual-environments.md) erstellen, sie aktivieren und dann **FastAPI installieren**: + +
+ +```console +$ pip install "fastapi[standard]" + +---> 100% +``` + +
+ +/// note | Hinweis + +Wenn Sie mit `pip install "fastapi[standard]"` installieren, werden einige optionale Standard-Abhängigkeiten mit installiert, einschließlich `fastapi-cloud-cli`, welches Ihnen das Deployment in der [FastAPI Cloud](https://fastapicloud.com) ermöglicht. + +Wenn Sie diese optionalen Abhängigkeiten nicht haben möchten, können Sie stattdessen `pip install fastapi` installieren. + +Wenn Sie die Standard-Abhängigkeiten, aber ohne das `fastapi-cloud-cli` installieren möchten, können Sie mit `pip install "fastapi[standard-no-fastapi-cloud-cli]"` installieren. + +/// + +/// tip | Tipp + +FastAPI hat eine [offizielle Erweiterung für VS Code](https://marketplace.visualstudio.com/items?itemName=FastAPILabs.fastapi-vscode) (und Cursor), die viele Funktionen bereitstellt, darunter einen Pfadoperation-Explorer, eine Pfadoperation-Suche, CodeLens-Navigation in Tests (zur Definition aus Tests springen) sowie FastAPI-Cloud-Deployment und Logs – alles direkt aus Ihrem Editor. + +/// + +## Handbuch für fortgeschrittene Benutzer { #advanced-user-guide } + +Es gibt auch ein **Handbuch für fortgeschrittene Benutzer**, das Sie nach diesem **Tutorial – Benutzerhandbuch** lesen können. + +Das **Handbuch für fortgeschrittene Benutzer** baut hierauf auf, verwendet dieselben Konzepte und bringt Ihnen einige zusätzliche Funktionen bei. + +Sie sollten jedoch zuerst das **Tutorial – Benutzerhandbuch** lesen (was Sie gerade tun). + +Es ist so konzipiert, dass Sie mit dem **Tutorial – Benutzerhandbuch** eine vollständige Anwendung erstellen können und diese dann je nach Bedarf mit einigen der zusätzlichen Ideen aus dem **Handbuch für fortgeschrittene Benutzer** erweitern können. diff --git a/docs/de/docs/tutorial/metadata.md b/docs/de/docs/tutorial/metadata.md new file mode 100644 index 0000000000000..e6549aa3c0931 --- /dev/null +++ b/docs/de/docs/tutorial/metadata.md @@ -0,0 +1,120 @@ +# Metadaten und Dokumentations-URLs { #metadata-and-docs-urls } + +Sie können mehrere Metadaten-Konfigurationen in Ihrer **FastAPI**-Anwendung anpassen. + +## Metadaten für die API { #metadata-for-api } + +Sie können die folgenden Felder festlegen, die in der OpenAPI-Spezifikation und in den Benutzeroberflächen der automatischen API-Dokumentation verwendet werden: + +| Parameter | Typ | Beschreibung | +|------------|------|-------------| +| `title` | `str` | Der Titel der API. | +| `summary` | `str` | Eine kurze Zusammenfassung der API. Verfügbar seit OpenAPI 3.1.0, FastAPI 0.99.0. | +| `description` | `str` | Eine kurze Beschreibung der API. Kann Markdown verwenden. | +| `version` | `str` | Die Version der API. Das ist die Version Ihrer eigenen Anwendung, nicht die von OpenAPI. Zum Beispiel `2.5.0`. | +| `terms_of_service` | `str` | Eine URL zu den Nutzungsbedingungen für die API. Falls angegeben, muss es sich um eine URL handeln. | +| `contact` | `dict` | Die Kontaktinformationen für die freigegebene API. Kann mehrere Felder enthalten.
contact-Felder
ParameterTypBeschreibung
namestrDer identifizierende Name der Kontaktperson/Organisation.
urlstrDie URL, die auf die Kontaktinformationen verweist. MUSS im Format einer URL vorliegen.
emailstrDie E-Mail-Adresse der Kontaktperson/Organisation. MUSS im Format einer E-Mail-Adresse vorliegen.
| +| `license_info` | `dict` | Die Lizenzinformationen für die freigegebene API. Kann mehrere Felder enthalten.
license_info-Felder
ParameterTypBeschreibung
namestrERFORDERLICH (wenn eine license_info festgelegt ist). Der für die API verwendete Lizenzname.
identifierstrEin [SPDX](https://spdx.org/licenses/)-Lizenzausdruck für die API. Das Feld identifier und das Feld url schließen sich gegenseitig aus. Verfügbar seit OpenAPI 3.1.0, FastAPI 0.99.0.
urlstrEine URL zur Lizenz, die für die API verwendet wird. MUSS im Format einer URL vorliegen.
| + +Sie können diese wie folgt setzen: + +{* ../../docs_src/metadata/tutorial001_py310.py hl[3:16, 19:32] *} + +/// tip | Tipp + +Sie können Markdown im Feld `description` verwenden, und es wird in der Ausgabe gerendert. + +/// + +Mit dieser Konfiguration würde die automatische API-Dokumentation wie folgt aussehen: + + + +## Lizenzkennung { #license-identifier } + +Seit OpenAPI 3.1.0 und FastAPI 0.99.0 können Sie die `license_info` auch mit einem `identifier` anstelle einer `url` festlegen. + +Zum Beispiel: + +{* ../../docs_src/metadata/tutorial001_1_py310.py hl[31] *} + +## Metadaten für Tags { #metadata-for-tags } + +Sie können auch zusätzliche Metadaten für die verschiedenen Tags hinzufügen, die zum Gruppieren Ihrer Pfadoperationen verwendet werden, mit dem Parameter `openapi_tags`. + +Er nimmt eine Liste entgegen, die für jeden Tag ein Dictionary enthält. + +Jedes Dictionary kann Folgendes enthalten: + +* `name` (**erforderlich**): ein `str` mit demselben Tag-Namen, den Sie im Parameter `tags` in Ihren *Pfadoperationen* und `APIRouter`n verwenden. +* `description`: ein `str` mit einer kurzen Beschreibung für das Tag. Sie kann Markdown enthalten und wird in der Benutzeroberfläche der Dokumentation angezeigt. +* `externalDocs`: ein `dict`, das externe Dokumentation beschreibt mit: + * `description`: ein `str` mit einer kurzen Beschreibung für die externe Dokumentation. + * `url` (**erforderlich**): ein `str` mit der URL für die externe Dokumentation. + +### Metadaten für Tags erstellen { #create-metadata-for-tags } + +Versuchen wir es mit einem Beispiel mit Tags für `users` und `items`. + +Erstellen Sie Metadaten für Ihre Tags und übergeben Sie diese an den Parameter `openapi_tags`: + +{* ../../docs_src/metadata/tutorial004_py310.py hl[3:16,18] *} + +Beachten Sie, dass Sie Markdown innerhalb der Beschreibungen verwenden können. Zum Beispiel wird „login“ in Fettschrift (**login**) und „fancy“ in Kursivschrift (_fancy_) angezeigt. + +/// tip | Tipp + +Sie müssen nicht für alle von Ihnen verwendeten Tags Metadaten hinzufügen. + +/// + +### Ihre Tags verwenden { #use-your-tags } + +Verwenden Sie den Parameter `tags` mit Ihren *Pfadoperationen* (und `APIRouter`n), um diese verschiedenen Tags zuzuweisen: + +{* ../../docs_src/metadata/tutorial004_py310.py hl[21,26] *} + +/// note | Hinweis + +Lesen Sie mehr zu Tags unter [Pfadoperation-Konfiguration](path-operation-configuration.md#tags). + +/// + +### Die Dokumentation testen { #check-the-docs } + +Wenn Sie nun die Dokumentation ansehen, werden dort alle zusätzlichen Metadaten angezeigt: + + + +### Reihenfolge der Tags { #order-of-tags } + +Die Reihenfolge der Tag-Metadaten-Dictionarys definiert auch die Reihenfolge, in der diese in der Benutzeroberfläche der Dokumentation angezeigt werden. + +Auch wenn beispielsweise `users` im Alphabet nach `items` kommt, wird es vor diesen angezeigt, da wir deren Metadaten als erstes Dictionary der Liste hinzugefügt haben. + +## OpenAPI-URL { #openapi-url } + +Standardmäßig wird das OpenAPI-Schema unter `/openapi.json` bereitgestellt. + +Sie können das aber mit dem Parameter `openapi_url` konfigurieren. + +Um beispielsweise festzulegen, dass es unter `/api/v1/openapi.json` bereitgestellt wird: + +{* ../../docs_src/metadata/tutorial002_py310.py hl[3] *} + +Wenn Sie das OpenAPI-Schema vollständig deaktivieren möchten, können Sie `openapi_url=None` festlegen, wodurch auch die Dokumentationsbenutzeroberflächen deaktiviert werden, die es verwenden. + +## Dokumentations-URLs { #docs-urls } + +Sie können die beiden enthaltenen Dokumentationsbenutzeroberflächen konfigurieren: + +* **Swagger UI**: bereitgestellt unter `/docs`. + * Sie können deren URL mit dem Parameter `docs_url` festlegen. + * Sie können sie deaktivieren, indem Sie `docs_url=None` festlegen. +* **ReDoc**: bereitgestellt unter `/redoc`. + * Sie können deren URL mit dem Parameter `redoc_url` festlegen. + * Sie können sie deaktivieren, indem Sie `redoc_url=None` festlegen. + +Um beispielsweise Swagger UI so einzustellen, dass sie unter `/documentation` bereitgestellt wird, und ReDoc zu deaktivieren: + +{* ../../docs_src/metadata/tutorial003_py310.py hl[3] *} diff --git a/docs/de/docs/tutorial/middleware.md b/docs/de/docs/tutorial/middleware.md new file mode 100644 index 0000000000000..0e8da4dcefa52 --- /dev/null +++ b/docs/de/docs/tutorial/middleware.md @@ -0,0 +1,95 @@ +# Middleware { #middleware } + +Sie können Middleware zu **FastAPI**-Anwendungen hinzufügen. + +Eine „Middleware“ ist eine Funktion, die mit jedem **Request** arbeitet, bevor er von einer bestimmten *Pfadoperation* verarbeitet wird. Und auch mit jeder **Response**, bevor sie zurückgegeben wird. + +* Sie nimmt jeden **Request** entgegen, der an Ihre Anwendung gesendet wird. +* Sie kann dann etwas mit diesem **Request** tun oder beliebigen Code ausführen. +* Dann gibt sie den **Request** zur Verarbeitung durch den Rest der Anwendung weiter (durch eine bestimmte *Pfadoperation*). +* Sie nimmt dann die **Response** entgegen, die von der Anwendung generiert wurde (durch eine bestimmte *Pfadoperation*). +* Sie kann etwas mit dieser **Response** tun oder beliebigen Code ausführen. +* Dann gibt sie die **Response** zurück. + +/// note | Technische Details + +Wenn Sie Abhängigkeiten mit `yield` haben, wird der Exit-Code *nach* der Middleware ausgeführt. + +Wenn es Hintergrundtasks gab (dies wird später im [Hintergrundtasks](background-tasks.md)-Abschnitt behandelt), werden sie *nach* allen Middlewares ausgeführt. + +/// + +## Eine Middleware erstellen { #create-a-middleware } + +Um eine Middleware zu erstellen, verwenden Sie den Dekorator `@app.middleware("http")` über einer Funktion. + +Die Middleware-Funktion erhält: + +* Den `request`. +* Eine Funktion `call_next`, die den `request` als Parameter erhält. + * Diese Funktion gibt den `request` an die entsprechende *Pfadoperation* weiter. + * Dann gibt es die von der entsprechenden *Pfadoperation* generierte `response` zurück. +* Sie können die `response` dann weiter modifizieren, bevor Sie sie zurückgeben. + +{* ../../docs_src/middleware/tutorial001_py310.py hl[8:9,11,14] *} + +/// tip | Tipp + +Beachten Sie, dass benutzerdefinierte proprietäre Header hinzugefügt werden können [unter Verwendung des `X-`-Präfixes](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers). + +Wenn Sie jedoch benutzerdefinierte Header haben, die ein Client in einem Browser sehen soll, müssen Sie sie zu Ihrer CORS-Konfiguration ([CORS (Cross-Origin Resource Sharing)](cors.md)) hinzufügen, indem Sie den Parameter `expose_headers` verwenden, der in [Starlettes CORS-Dokumentation](https://www.starlette.dev/middleware/#corsmiddleware) dokumentiert ist. + +/// + +/// note | Technische Details + +Sie könnten auch `from starlette.requests import Request` verwenden. + +**FastAPI** bietet es als Komfort für Sie, den Entwickler, an. Aber es stammt direkt von Starlette. + +/// + +### Vor und nach der `response` { #before-and-after-the-response } + +Sie können Code hinzufügen, der mit dem `request` ausgeführt wird, bevor dieser von einer beliebigen *Pfadoperation* empfangen wird. + +Und auch nachdem die `response` generiert wurde, bevor sie zurückgegeben wird. + +Sie könnten beispielsweise einen benutzerdefinierten Header `X-Process-Time` hinzufügen, der die Zeit in Sekunden enthält, die benötigt wurde, um den Request zu verarbeiten und eine Response zu generieren: + +{* ../../docs_src/middleware/tutorial001_py310.py hl[10,12:13] *} + +/// tip | Tipp + +Hier verwenden wir [`time.perf_counter()`](https://docs.python.org/3/library/time.html#time.perf_counter) anstelle von `time.time()`, da es für diese Anwendungsfälle präziser sein kann. 🤓 + +/// + +## Ausführungsreihenfolge bei mehreren Middlewares { #multiple-middleware-execution-order } + +Wenn Sie mehrere Middlewares hinzufügen, entweder mit dem `@app.middleware()` Dekorator oder der Methode `app.add_middleware()`, umschließt jede neue Middleware die Anwendung und bildet einen Stapel. Die zuletzt hinzugefügte Middleware ist die *äußerste*, und die erste ist die *innerste*. + +Auf dem Requestpfad läuft die *äußerste* Middleware zuerst. + +Auf dem Responsepfad läuft sie zuletzt. + +Zum Beispiel: + +```Python +app.add_middleware(MiddlewareA) +app.add_middleware(MiddlewareB) +``` + +Dies führt zu folgender Ausführungsreihenfolge: + +* **Request**: MiddlewareB → MiddlewareA → Route + +* **Response**: Route → MiddlewareA → MiddlewareB + +Dieses Stapelverhalten stellt sicher, dass Middlewares in einer vorhersehbaren und kontrollierbaren Reihenfolge ausgeführt werden. + +## Andere Middlewares { #other-middlewares } + +Sie können später mehr über andere Middlewares im [Handbuch für fortgeschrittene Benutzer: Fortgeschrittene Middleware](../advanced/middleware.md) lesen. + +In der nächsten Sektion erfahren Sie, wie Sie CORS mit einer Middleware behandeln können. diff --git a/docs/de/docs/tutorial/path-operation-configuration.md b/docs/de/docs/tutorial/path-operation-configuration.md new file mode 100644 index 0000000000000..56c8a69e79abe --- /dev/null +++ b/docs/de/docs/tutorial/path-operation-configuration.md @@ -0,0 +1,107 @@ +# Pfadoperation-Konfiguration { #path-operation-configuration } + +Es gibt mehrere Parameter, die Sie Ihrem *Pfadoperation-Dekorator* übergeben können, um ihn zu konfigurieren. + +/// warning | Achtung + +Beachten Sie, dass diese Parameter direkt dem *Pfadoperation-Dekorator* übergeben werden, nicht der *Pfadoperation-Funktion*. + +/// + +## Response-Statuscode { #response-status-code } + +Sie können den (HTTP-)`status_code` definieren, der in der Response Ihrer *Pfadoperation* verwendet werden soll. + +Sie können direkt den `int`-Code übergeben, etwa `404`. + +Aber falls Sie sich nicht mehr erinnern, wofür jeder Nummerncode steht, können Sie die Abkürzungs-Konstanten in `status` verwenden: + +{* ../../docs_src/path_operation_configuration/tutorial001_py310.py hl[1,15] *} + +Dieser Statuscode wird in der Response verwendet und zum OpenAPI-Schema hinzugefügt. + +/// note | Technische Details + +Sie können auch `from starlette import status` verwenden. + +**FastAPI** bietet dieselben `starlette.status`-Codes auch via `fastapi.status` an, als Annehmlichkeit für Sie, den Entwickler. Sie kommen aber direkt von Starlette. + +/// + +## Tags { #tags } + +Sie können Ihrer *Pfadoperation* Tags hinzufügen, indem Sie dem Parameter `tags` eine `list`e von `str`s übergeben (in der Regel nur ein `str`): + +{* ../../docs_src/path_operation_configuration/tutorial002_py310.py hl[15,20,25] *} + +Diese werden zum OpenAPI-Schema hinzugefügt und von den automatischen Dokumentations-Benutzeroberflächen verwendet: + + + +### Tags mit Enums { #tags-with-enums } + +Wenn Sie eine große Anwendung haben, können sich am Ende **mehrere Tags** anhäufen, und Sie möchten sicherstellen, dass Sie für verwandte *Pfadoperationen* immer den **gleichen Tag** verwenden. + +In diesen Fällen kann es sinnvoll sein, die Tags in einem `Enum` zu speichern. + +**FastAPI** unterstützt das auf die gleiche Weise wie einfache Strings: + +{* ../../docs_src/path_operation_configuration/tutorial002b_py310.py hl[1,8:10,13,18] *} + +## Zusammenfassung und Beschreibung { #summary-and-description } + +Sie können eine `summary` und eine `description` hinzufügen: + +{* ../../docs_src/path_operation_configuration/tutorial003_py310.py hl[17:18] *} + +## Beschreibung mittels Docstring { #description-from-docstring } + +Da Beschreibungen oft mehrere Zeilen lang sind, können Sie die Beschreibung der *Pfadoperation* im Docstring der Funktion deklarieren, und **FastAPI** wird sie daraus auslesen. + +Sie können [Markdown](https://en.wikipedia.org/wiki/Markdown) im Docstring schreiben, es wird korrekt interpretiert und angezeigt (unter Berücksichtigung der Einrückung des Docstring). + +{* ../../docs_src/path_operation_configuration/tutorial004_py310.py hl[17:25] *} + +Es wird in der interaktiven Dokumentation verwendet: + + + +## Beschreibung der Response { #response-description } + +Sie können die Response mit dem Parameter `response_description` beschreiben: + +{* ../../docs_src/path_operation_configuration/tutorial005_py310.py hl[18] *} + +/// note | Hinweis + +Beachten Sie, dass sich `response_description` speziell auf die Response bezieht, während `description` sich generell auf die *Pfadoperation* bezieht. + +/// + +/// tip | Tipp + +OpenAPI verlangt, dass jede *Pfadoperation* über eine Beschreibung der Response verfügt. + +Daher, wenn Sie keine vergeben, wird **FastAPI** automatisch eine für „Erfolgreiche Response“ erstellen. + +/// + + + +## Eine *Pfadoperation* deprecaten { #deprecate-a-path-operation } + +Wenn Sie eine *Pfadoperation* als deprecatet kennzeichnen möchten, ohne sie zu entfernen, fügen Sie den Parameter `deprecated` hinzu: + +{* ../../docs_src/path_operation_configuration/tutorial006_py310.py hl[16] *} + +Sie wird in der interaktiven Dokumentation gut sichtbar als deprecatet markiert werden: + + + +Vergleichen Sie, wie deprecatete und nicht-deprecatete *Pfadoperationen* aussehen: + + + +## Zusammenfassung { #recap } + +Sie können Ihre *Pfadoperationen* einfach konfigurieren und Metadaten hinzufügen, indem Sie den *Pfadoperation-Dekoratoren* Parameter übergeben. diff --git a/docs/de/docs/tutorial/path-params-numeric-validations.md b/docs/de/docs/tutorial/path-params-numeric-validations.md new file mode 100644 index 0000000000000..59464ac8f6b7c --- /dev/null +++ b/docs/de/docs/tutorial/path-params-numeric-validations.md @@ -0,0 +1,154 @@ +# Pfad-Parameter und Validierung von Zahlen { #path-parameters-and-numeric-validations } + +So wie Sie mit `Query` für Query-Parameter zusätzliche Validierungen und Metadaten deklarieren können, können Sie mit `Path` die gleichen Validierungen und Metadaten für Pfad-Parameter deklarieren. + +## `Path` importieren { #import-path } + +Importieren Sie zuerst `Path` von `fastapi`, und importieren Sie `Annotated`: + +{* ../../docs_src/path_params_numeric_validations/tutorial001_an_py310.py hl[1,3] *} + +/// note | Hinweis + +FastAPI hat in Version 0.95.0 Unterstützung für `Annotated` hinzugefügt und es zur Verwendung empfohlen. + +Wenn Sie eine ältere Version haben, würden Fehler angezeigt werden, wenn Sie versuchen, `Annotated` zu verwenden. + +Stellen Sie sicher, dass Sie [FastAPI aktualisieren](../deployment/versions.md#upgrading-the-fastapi-versions), auf mindestens Version 0.95.1, bevor Sie `Annotated` verwenden. + +/// + +## Metadaten deklarieren { #declare-metadata } + +Sie können dieselben Parameter wie für `Query` deklarieren. + +Um zum Beispiel einen `title`-Metadaten-Wert für den Pfad-Parameter `item_id` zu deklarieren, können Sie schreiben: + +{* ../../docs_src/path_params_numeric_validations/tutorial001_an_py310.py hl[10] *} + +/// note | Hinweis + +Ein Pfad-Parameter ist immer erforderlich, da er Teil des Pfads sein muss. Selbst wenn Sie ihn mit `None` deklarieren oder einen Defaultwert setzen, würde das nichts ändern, er wäre dennoch immer erforderlich. + +/// + +## Die Parameter sortieren, wie Sie möchten { #order-the-parameters-as-you-need } + +/// tip | Tipp + +Das ist wahrscheinlich nicht so wichtig oder notwendig, wenn Sie `Annotated` verwenden. + +/// + +Angenommen, Sie möchten den Query-Parameter `q` als erforderlichen `str` deklarieren. + +Und Sie müssen sonst nichts anderes für diesen Parameter deklarieren, Sie brauchen also `Query` nicht wirklich. + +Aber Sie müssen dennoch `Path` für den `item_id`-Pfad-Parameter verwenden. Und aus irgendeinem Grund möchten Sie `Annotated` nicht verwenden. + +Python wird sich beschweren, wenn Sie einen Wert mit einem „Default“ vor einem Wert ohne „Default“ setzen. + +Aber Sie können die Reihenfolge ändern und den Wert ohne Default (den Query-Parameter `q`) zuerst setzen. + +Für **FastAPI** spielt es keine Rolle. Es erkennt die Parameter anhand ihrer Namen, Typen und Default-Deklarationen (`Query`, `Path`, usw.), es kümmert sich nicht um die Reihenfolge. + +Sie können Ihre Funktion also so deklarieren: + +{* ../../docs_src/path_params_numeric_validations/tutorial002_py310.py hl[7] *} + +Aber bedenken Sie, dass Sie dieses Problem nicht haben, wenn Sie `Annotated` verwenden, da es nicht darauf ankommt, dass Sie keine Funktionsparameter-Defaultwerte für `Query()` oder `Path()` verwenden. + +{* ../../docs_src/path_params_numeric_validations/tutorial002_an_py310.py *} + +## Die Parameter sortieren, wie Sie möchten: Tricks { #order-the-parameters-as-you-need-tricks } + +/// tip | Tipp + +Das ist wahrscheinlich nicht so wichtig oder notwendig, wenn Sie `Annotated` verwenden. + +/// + +Hier ist ein **kleiner Trick**, der nützlich sein kann, obwohl Sie ihn nicht oft benötigen werden. + +Wenn Sie: + +* den `q`-Query-Parameter sowohl ohne `Query` als auch ohne Defaultwert deklarieren +* den Pfad-Parameter `item_id` mit `Path` deklarieren +* sie in einer anderen Reihenfolge haben +* nicht `Annotated` verwenden + +... möchten, dann hat Python eine kleine Spezial-Syntax dafür. + +Übergeben Sie `*`, als den ersten Parameter der Funktion. + +Python wird nichts mit diesem `*` machen, aber es wird wissen, dass alle folgenden Parameter als Schlüsselwortargumente (Schlüssel-Wert-Paare) verwendet werden sollen, auch bekannt als kwargs. Selbst wenn diese keinen Defaultwert haben. + +{* ../../docs_src/path_params_numeric_validations/tutorial003_py310.py hl[7] *} + +### Besser mit `Annotated` { #better-with-annotated } + +Bedenken Sie, dass Sie, wenn Sie `Annotated` verwenden, da Sie keine Funktionsparameter-Defaultwerte verwenden, dieses Problem nicht haben werden und wahrscheinlich nicht `*` verwenden müssen. + +{* ../../docs_src/path_params_numeric_validations/tutorial003_an_py310.py hl[10] *} + +## Validierung von Zahlen: Größer oder gleich { #number-validations-greater-than-or-equal } + +Mit `Query` und `Path` (und anderen, die Sie später sehen werden) können Sie Zahlenbeschränkungen deklarieren. + +Hier, mit `ge=1`, muss `item_id` eine ganze Zahl sein, die „`g`reater than or `e`qual to“ (größer oder gleich) `1` ist. + +{* ../../docs_src/path_params_numeric_validations/tutorial004_an_py310.py hl[10] *} + +## Validierung von Zahlen: Größer und kleiner oder gleich { #number-validations-greater-than-and-less-than-or-equal } + +Das Gleiche gilt für: + +* `gt`: `g`reater `t`han (größer als) +* `le`: `l`ess than or `e`qual (kleiner oder gleich) + +{* ../../docs_src/path_params_numeric_validations/tutorial005_an_py310.py hl[10] *} + +## Validierung von Zahlen: Floats, größer und kleiner { #number-validations-floats-greater-than-and-less-than } + +Zahlenvalidierung funktioniert auch für `float`-Werte. + +Hier wird es wichtig, in der Lage zu sein, gt und nicht nur ge zu deklarieren. Da Sie mit dieser Option erzwingen können, dass ein Wert größer als `0` sein muss, selbst wenn er kleiner als `1` ist. + +Also wäre `0.5` ein gültiger Wert. Aber `0.0` oder `0` nicht. + +Und das Gleiche gilt für lt. + +{* ../../docs_src/path_params_numeric_validations/tutorial006_an_py310.py hl[13] *} + +## Zusammenfassung { #recap } + +Mit `Query`, `Path` (und anderen, die Sie noch nicht gesehen haben) können Sie Metadaten und Stringvalidierungen auf die gleichen Weisen deklarieren wie in [Query-Parameter und Stringvalidierungen](query-params-str-validations.md) beschrieben. + +Und Sie können auch Zahlenvalidierungen deklarieren: + +* `gt`: `g`reater `t`han (größer als) +* `ge`: `g`reater than or `e`qual (größer oder gleich) +* `lt`: `l`ess `t`han (kleiner als) +* `le`: `l`ess than or `e`qual (kleiner oder gleich) + +/// note | Hinweis + +`Query`, `Path`, und andere Klassen, die Sie später sehen werden, sind Unterklassen einer gemeinsamen `Param`-Klasse. + +Alle von ihnen teilen die gleichen Parameter für zusätzliche Validierung und Metadaten, die Sie gesehen haben. + +/// + +/// note | Technische Details + +Wenn Sie `Query`, `Path` und andere von `fastapi` importieren, sind sie tatsächlich Funktionen. + +Die, wenn sie aufgerufen werden, Instanzen von Klassen mit demselben Namen zurückgeben. + +Sie importieren also `Query`, was eine Funktion ist. Und wenn Sie sie aufrufen, gibt sie eine Instanz einer Klasse zurück, die auch `Query` genannt wird. + +Diese Funktionen existieren (statt die Klassen direkt zu verwenden), damit Ihr Editor keine Fehlermeldungen über ihre Typen ausgibt. + +Auf diese Weise können Sie Ihren normalen Editor und Ihre Programmier-Tools verwenden, ohne besondere Einstellungen vornehmen zu müssen, um diese Fehlermeldungen stummzuschalten. + +/// diff --git a/docs/de/docs/tutorial/path-params.md b/docs/de/docs/tutorial/path-params.md new file mode 100644 index 0000000000000..d462a74075df3 --- /dev/null +++ b/docs/de/docs/tutorial/path-params.md @@ -0,0 +1,251 @@ +# Pfad-Parameter { #path-parameters } + +Sie können Pfad-„Parameter“ oder -„Variablen“ mit der gleichen Syntax deklarieren, welche in Python-Formatstrings verwendet wird: + +{* ../../docs_src/path_params/tutorial001_py310.py hl[6:7] *} + +Der Wert des Pfad-Parameters `item_id` wird Ihrer Funktion als das Argument `item_id` übergeben. + +Wenn Sie dieses Beispiel ausführen und auf [http://127.0.0.1:8000/items/foo](http://127.0.0.1:8000/items/foo) gehen, sehen Sie als Response: + +```JSON +{"item_id":"foo"} +``` + +## Pfad-Parameter mit Typen { #path-parameters-with-types } + +Sie können den Typ eines Pfad-Parameters in der Argumentliste der Funktion deklarieren, mit Standard-Python-Typannotationen: + +{* ../../docs_src/path_params/tutorial002_py310.py hl[7] *} + +In diesem Fall wird `item_id` als `int` deklariert, also als Ganzzahl. + +/// tip | Tipp + +Dadurch erhalten Sie Editor-Unterstützung innerhalb Ihrer Funktion, mit Fehlerprüfungen, Codevervollständigung, usw. + +/// + +## Daten-Konversion { #data-conversion } + +Wenn Sie dieses Beispiel ausführen und Ihren Browser unter [http://127.0.0.1:8000/items/3](http://127.0.0.1:8000/items/3) öffnen, sehen Sie als Response: + +```JSON +{"item_id":3} +``` + +/// tip | Tipp + +Beachten Sie, dass der Wert, den Ihre Funktion erhält und zurückgibt, die Zahl `3` ist, also ein `int`. Nicht der String „3“, also ein `str`. + +Sprich, mit dieser Typdeklaration wird **FastAPI** den „parsen“. + +/// + +## Datenvalidierung { #data-validation } + +Wenn Sie aber im Browser [http://127.0.0.1:8000/items/foo](http://127.0.0.1:8000/items/foo) besuchen, erhalten Sie eine hübsche HTTP-Fehlermeldung: + +```JSON +{ + "detail": [ + { + "type": "int_parsing", + "loc": [ + "path", + "item_id" + ], + "msg": "Input should be a valid integer, unable to parse string as an integer", + "input": "foo" + } + ] +} +``` + +Der Pfad-Parameter `item_id` hatte den Wert „foo“, was kein `int` ist. + +Die gleiche Fehlermeldung würde angezeigt werden, wenn Sie ein `float` (also eine Kommazahl) statt eines `int`s übergeben würden, wie etwa in: [http://127.0.0.1:8000/items/4.2](http://127.0.0.1:8000/items/4.2) + +/// tip | Tipp + +Sprich, mit der gleichen Python-Typdeklaration gibt Ihnen **FastAPI** Datenvalidierung. + +Beachten Sie, dass die Fehlermeldung auch direkt die Stelle anzeigt, wo die Validierung nicht erfolgreich war. + +Das ist unglaublich hilfreich, wenn Sie Code entwickeln und debuggen, welcher mit Ihrer API interagiert. + +/// + +## Dokumentation { #documentation } + +Wenn Sie die Seite [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs) in Ihrem Browser öffnen, sehen Sie eine automatische, interaktive API-Dokumentation: + + + +/// tip | Tipp + +Wiederum, mit dieser gleichen Python-Typdeklaration gibt Ihnen **FastAPI** eine automatische, interaktive Dokumentation (verwendet die Swagger-Benutzeroberfläche). + +Beachten Sie, dass der Pfad-Parameter dort als Ganzzahl deklariert ist. + +/// + +## Nützliche Standards, alternative Dokumentation { #standards-based-benefits-alternative-documentation } + +Und weil das generierte Schema vom [OpenAPI](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md)-Standard kommt, gibt es viele kompatible Tools. + +Zum Beispiel bietet **FastAPI** selbst eine alternative API-Dokumentation (verwendet ReDoc), welche Sie unter [http://127.0.0.1:8000/redoc](http://127.0.0.1:8000/redoc) einsehen können: + + + +Und viele weitere kompatible Tools. Inklusive Codegenerierung für viele Sprachen. + +## Pydantic { #pydantic } + +Die ganze Datenvalidierung wird hinter den Kulissen von [Pydantic](https://docs.pydantic.dev/) durchgeführt, Sie profitieren also von dessen Vorteilen. Und Sie wissen, dass Sie in guten Händen sind. + +Sie können für Typdeklarationen auch `str`, `float`, `bool` und viele andere komplexe Datentypen verwenden. + +Mehrere davon werden wir in den nächsten Kapiteln erkunden. + +## Die Reihenfolge ist wichtig { #order-matters } + +Wenn Sie *Pfadoperationen* erstellen, haben Sie manchmal einen fixen Pfad. + +Etwa `/users/me`, um Daten über den aktuellen Benutzer zu erhalten. + +Und Sie haben auch einen Pfad `/users/{user_id}`, um Daten über einen spezifischen Benutzer zu erhalten, mittels einer Benutzer-ID. + +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_py310.py hl[6,11] *} + +Ansonsten würde der Pfad für `/users/{user_id}` auch `/users/me` auswerten, und annehmen, dass ein Parameter `user_id` mit dem Wert „me“ übergeben wurde. + +Sie können eine Pfadoperation auch nicht erneut definieren: + +{* ../../docs_src/path_params/tutorial003b_py310.py hl[6,11] *} + +Die erste Definition wird immer verwendet werden, da ihr Pfad zuerst übereinstimmt. + +## Vordefinierte Parameterwerte { #predefined-values } + +Wenn Sie eine *Pfadoperation* haben, welche einen *Pfad-Parameter* hat, aber Sie wollen, dass dessen gültige Werte vordefiniert sind, können Sie ein Standard-Python `Enum` verwenden. + +### Eine `Enum`-Klasse erstellen { #create-an-enum-class } + +Importieren Sie `Enum` und erstellen Sie eine Unterklasse, die von `str` und `Enum` erbt. + +Indem Sie von `str` erben, weiß die API-Dokumentation, dass die Werte vom Typ `str` sein müssen, und wird in der Lage sein, korrekt zu rendern. + +Erstellen Sie dann Klassen-Attribute mit festgelegten Werten, welches die erlaubten Werte sein werden: + +{* ../../docs_src/path_params/tutorial005_py310.py hl[1,6:9] *} + +/// tip | Tipp + +Falls Sie sich fragen, was „AlexNet“, „ResNet“ und „LeNet“ ist, das sind Namen von Modellen für maschinelles Lernen. + +/// + +### Einen *Pfad-Parameter* deklarieren { #declare-a-path-parameter } + +Dann erstellen Sie einen *Pfad-Parameter*, der als Typ die gerade erstellte Enum-Klasse hat (`ModelName`): + +{* ../../docs_src/path_params/tutorial005_py310.py hl[16] *} + +### Die API-Dokumentation testen { #check-the-docs } + +Weil die erlaubten Werte für den *Pfad-Parameter* nun vordefiniert sind, kann die interaktive Dokumentation sie als Auswahl-Drop-Down anzeigen: + + + +### Mit Python-*Enumerationen* arbeiten { #working-with-python-enumerations } + +Der *Pfad-Parameter* wird ein *Member einer Enumeration* sein. + +#### *Enumeration-Member* vergleichen { #compare-enumeration-members } + +Sie können ihn mit einem Member Ihrer Enumeration `ModelName` vergleichen: + +{* ../../docs_src/path_params/tutorial005_py310.py hl[17] *} + +#### *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`: + +{* ../../docs_src/path_params/tutorial005_py310.py hl[20] *} + +/// tip | Tipp + +Sie können den Wert `"lenet"` außerdem mittels `ModelName.lenet.value` abrufen. + +/// + +#### *Enumeration-Member* zurückgeben { #return-enumeration-members } + +Sie können *Enum-Member* in ihrer *Pfadoperation* zurückgeben, sogar verschachtelt in einem JSON-Body (z. B. als `dict`). + +Diese werden zu ihren entsprechenden Werten konvertiert (in diesem Fall Strings), bevor sie zum Client übertragen werden: + +{* ../../docs_src/path_params/tutorial005_py310.py hl[18,21,23] *} + +In Ihrem Client erhalten Sie eine JSON-Response, wie etwa: + +```JSON +{ + "model_name": "alexnet", + "message": "Deep Learning FTW!" +} +``` + +## Pfad-Parameter, die Pfade enthalten { #path-parameters-containing-paths } + +Angenommen, Sie haben eine *Pfadoperation* mit einem Pfad `/files/{file_path}`. + +Aber `file_path` soll selbst einen *Pfad* enthalten, etwa `home/johndoe/myfile.txt`. + +Sprich, die URL für diese Datei wäre etwas wie: `/files/home/johndoe/myfile.txt`. + +### OpenAPI-Unterstützung { #openapi-support } + +OpenAPI bietet nicht die Möglichkeit, dass ein *Pfad-Parameter* seinerseits einen *Pfad* enthalten kann, das würde zu Szenarios führen, die schwierig zu testen und zu definieren sind. + +Trotzdem können Sie das in **FastAPI** tun, indem Sie eines der internen Tools von Starlette verwenden. + +Die Dokumentation würde weiterhin funktionieren, allerdings wird nicht dokumentiert werden, dass der Parameter ein Pfad sein sollte. + +### Pfad-Konverter { #path-convertor } + +Mittels einer Option direkt von Starlette können Sie einen *Pfad-Parameter* deklarieren, der einen Pfad enthalten soll, indem Sie eine URL wie folgt definieren: + +``` +/files/{file_path:path} +``` + +In diesem Fall ist der Name des Parameters `file_path`. Der letzte Teil, `:path`, sagt aus, dass der Parameter ein *Pfad* sein soll. + +Sie verwenden das also wie folgt: + +{* ../../docs_src/path_params/tutorial004_py310.py hl[6] *} + +/// tip | Tipp + +Der Parameter könnte einen führenden Schrägstrich (`/`) haben, wie etwa in `/home/johndoe/myfile.txt`. + +In dem Fall wäre die URL: `/files//home/johndoe/myfile.txt`, mit einem doppelten Schrägstrich (`//`) zwischen `files` und `home`. + +/// + +## Zusammenfassung { #recap } + +In **FastAPI** erhalten Sie mittels kurzer, intuitiver Typdeklarationen: + +* Editor-Unterstützung: Fehlerprüfungen, Codevervollständigung, usw. +* Daten „parsen“ +* Datenvalidierung +* API-Annotationen und automatische Dokumentation + +Und Sie müssen sie nur einmal deklarieren. + +Das ist wahrscheinlich der sichtbarste Unterschied zwischen **FastAPI** und alternativen Frameworks (abgesehen von der reinen Performanz). diff --git a/docs/de/docs/tutorial/query-param-models.md b/docs/de/docs/tutorial/query-param-models.md new file mode 100644 index 0000000000000..7d3f2d32e87b1 --- /dev/null +++ b/docs/de/docs/tutorial/query-param-models.md @@ -0,0 +1,68 @@ +# Query-Parameter-Modelle { #query-parameter-models } + +Wenn Sie eine Gruppe von **Query-Parametern** haben, die miteinander in Beziehung stehen, können Sie ein **Pydantic-Modell** erstellen, um diese zu deklarieren. + +Dadurch können Sie das **Modell an mehreren Stellen wiederverwenden** und gleichzeitig Validierungen und Metadaten für alle Parameter auf einmal deklarieren. 😎 + +/// note | Hinweis + +Dies wird seit FastAPI Version `0.115.0` unterstützt. 🤓 + +/// + +## Query-Parameter mit einem Pydantic-Modell { #query-parameters-with-a-pydantic-model } + +Deklarieren Sie die benötigten **Query-Parameter** in einem **Pydantic-Modell** und dann den Parameter als `Query`: + +{* ../../docs_src/query_param_models/tutorial001_an_py310.py hl[9:13,17] *} + +**FastAPI** wird die Daten für **jedes Feld** aus den **Query-Parametern** des Request extrahieren und Ihnen das definierte Pydantic-Modell bereitstellen. + +## Die Dokumentation testen { #check-the-docs } + +Sie können die Query-Parameter in der Dokumentations-Oberfläche unter `/docs` einsehen: + +
+ +
+ +## Zusätzliche Query-Parameter verbieten { #forbid-extra-query-parameters } + +In einigen speziellen Anwendungsfällen (wahrscheinlich nicht sehr häufig) möchten Sie möglicherweise die Query-Parameter, die Sie empfangen möchten, **beschränken**. + +Sie können die Modellkonfiguration von Pydantic verwenden, um jegliche `extra` Felder zu `verbieten`: + +{* ../../docs_src/query_param_models/tutorial002_an_py310.py hl[10] *} + +Wenn ein Client versucht, einige **zusätzliche** Daten in den **Query-Parametern** zu senden, erhält er eine **Error-Response**. + +Wenn der Client beispielsweise versucht, einen `tool` Query-Parameter mit dem Wert `plumbus` zu senden, wie: + +```http +https://example.com/items/?limit=10&tool=plumbus +``` + +erhält er eine **Error-Response**, die ihm mitteilt, dass der Query-Parameter `tool` nicht erlaubt ist: + +```json +{ + "detail": [ + { + "type": "extra_forbidden", + "loc": ["query", "tool"], + "msg": "Extra inputs are not permitted", + "input": "plumbus" + } + ] +} +``` + +## Zusammenfassung { #summary } + +Sie können **Pydantic-Modelle** verwenden, um **Query-Parameter** in **FastAPI** zu deklarieren. 😎 + +/// tip | Tipp + +Spoiler-Alarm: Sie können auch Pydantic-Modelle verwenden, um Cookies und Header zu deklarieren, aber darüber werden Sie später im Tutorial lesen. 🤫 + +/// diff --git a/docs/de/docs/tutorial/query-params-str-validations.md b/docs/de/docs/tutorial/query-params-str-validations.md new file mode 100644 index 0000000000000..bec5f574a1bbf --- /dev/null +++ b/docs/de/docs/tutorial/query-params-str-validations.md @@ -0,0 +1,449 @@ +# Query-Parameter und String-Validierungen { #query-parameters-and-string-validations } + +**FastAPI** ermöglicht es Ihnen, zusätzliche Informationen und Validierungen für Ihre Parameter zu deklarieren. + +Nehmen wir diese Anwendung als Beispiel: + +{* ../../docs_src/query_params_str_validations/tutorial001_py310.py hl[7] *} + +Der Query-Parameter `q` hat den Typ `str | None`, das bedeutet, dass er vom Typ `str` sein kann, aber auch `None`, und tatsächlich ist der Defaultwert `None`, sodass FastAPI weiß, dass er nicht erforderlich ist. + +/// note | Hinweis + +FastAPI erkennt, dass der Wert von `q` nicht erforderlich ist, aufgrund des Defaultwertes `= None`. + +Die Verwendung von `str | None` ermöglicht es Ihrem Editor, Ihnen bessere Unterstützung zu bieten und Fehler zu erkennen. + +/// + +## Zusätzliche Validierung { #additional-validation } + +Wir werden sicherstellen, dass, obwohl `q` optional ist, wann immer es bereitgestellt wird, **seine Länge 50 Zeichen nicht überschreitet**. + +### `Query` und `Annotated` importieren { #import-query-and-annotated } + +Um dies zu erreichen, importieren Sie zuerst: + +* `Query` von `fastapi` +* `Annotated` von `typing` + +{* ../../docs_src/query_params_str_validations/tutorial002_an_py310.py hl[1,3] *} + +/// note | Hinweis + +FastAPI hat Unterstützung für `Annotated` hinzugefügt (und begonnen, es zu empfehlen) in der Version 0.95.0. + +Wenn Sie eine ältere Version haben, würden Sie Fehler erhalten, beim Versuch, `Annotated` zu verwenden. + +Stellen Sie sicher, dass Sie [die FastAPI-Version aktualisieren](../deployment/versions.md#upgrading-the-fastapi-versions), auf mindestens Version 0.95.1, bevor Sie `Annotated` verwenden. + +/// + +## `Annotated` im Typ für den `q`-Parameter verwenden { #use-annotated-in-the-type-for-the-q-parameter } + +Erinnern Sie sich, dass ich Ihnen zuvor in [Python-Typen-Intro](../python-types.md#type-hints-with-metadata-annotations) gesagt habe, dass `Annotated` verwendet werden kann, um Metadaten zu Ihren Parametern hinzuzufügen? + +Jetzt ist es soweit, dies mit FastAPI zu verwenden. 🚀 + +Wir hatten diese Typannotation: + +```Python +q: str | None = None +``` + +Was wir tun werden, ist, dies mit `Annotated` zu wrappen, sodass es zu: + +```Python +q: Annotated[str | None] = None +``` + +Beide dieser Versionen bedeuten dasselbe: `q` ist ein Parameter, der ein `str` oder `None` sein kann, und standardmäßig ist er `None`. + +Jetzt springen wir zu den spannenden Dingen. 🎉 + +## `Query` zu `Annotated` im `q`-Parameter hinzufügen { #add-query-to-annotated-in-the-q-parameter } + +Da wir nun `Annotated` haben, in das wir mehr Informationen (in diesem Fall einige zusätzliche Validierungen) einfügen können, fügen Sie `Query` innerhalb von `Annotated` hinzu und setzen Sie den Parameter `max_length` auf `50`: + +{* ../../docs_src/query_params_str_validations/tutorial002_an_py310.py hl[9] *} + +Beachten Sie, dass der Defaultwert weiterhin `None` ist, so dass der Parameter weiterhin optional ist. + +Aber jetzt, mit `Query(max_length=50)` innerhalb von `Annotated`, sagen wir FastAPI, dass wir eine **zusätzliche Validierung** für diesen Wert wünschen, wir wollen, dass er maximal 50 Zeichen hat. 😎 + +/// tip | Tipp + +Hier verwenden wir `Query()`, weil dies ein **Query-Parameter** ist. Später werden wir andere wie `Path()`, `Body()`, `Header()`, und `Cookie()` sehen, die auch dieselben Argumente wie `Query()` akzeptieren. + +/// + +FastAPI wird nun: + +* Die Daten **validieren**, um sicherzustellen, dass die Länge maximal 50 Zeichen beträgt +* Einen **klaren Fehler** für den Client anzeigen, wenn die Daten ungültig sind +* Den Parameter in der OpenAPI-Schema-*Pfadoperation* **dokumentieren** (sodass er in der **automatischen Dokumentationsoberfläche** angezeigt wird) + +## Alternative (alt): `Query` als Defaultwert { #alternative-old-query-as-the-default-value } + +Frühere Versionen von FastAPI (vor 0.95.0) erforderten, dass Sie `Query` als den Defaultwert Ihres Parameters verwendeten, anstatt es innerhalb von `Annotated` zu platzieren. Es besteht eine hohe Wahrscheinlichkeit, dass Sie Code sehen, der es so verwendet, also werde ich es Ihnen erklären. + +/// tip | Tipp + +Für neuen Code und wann immer es möglich ist, verwenden Sie `Annotated` wie oben erklärt. Es gibt mehrere Vorteile (unten erläutert) und keine Nachteile. 🍰 + +/// + +So würden Sie `Query()` als den Defaultwert Ihres Funktionsparameters verwenden und den Parameter `max_length` auf 50 setzen: + +{* ../../docs_src/query_params_str_validations/tutorial002_py310.py hl[7] *} + +Da wir in diesem Fall (ohne die Verwendung von `Annotated`) den Defaultwert `None` in der Funktion durch `Query()` ersetzen müssen, müssen wir nun den Defaultwert mit dem Parameter `Query(default=None)` setzen, er erfüllt den gleichen Zweck, diesen Defaultwert zu definieren (zumindest für FastAPI). + +Also: + +```Python +q: str | None = Query(default=None) +``` + +... macht den Parameter optional mit einem Defaultwert von `None`, genauso wie: + +```Python +q: str | None = None +``` + +Aber die `Query`-Version deklariert ihn explizit als Query-Parameter. + +Dann können wir mehr Parameter an `Query` übergeben. In diesem Fall den `max_length`-Parameter, der auf Strings angewendet wird: + +```Python +q: str | None = Query(default=None, max_length=50) +``` + +Dies wird die Daten validieren, einen klaren Fehler anzeigen, wenn die Daten nicht gültig sind, und den Parameter in der OpenAPI-Schema-*Pfadoperation* dokumentieren. + +### `Query` als Defaultwert oder in `Annotated` { #query-as-the-default-value-or-in-annotated } + +Beachten Sie, dass wenn Sie `Query` innerhalb von `Annotated` verwenden, Sie den `default`-Parameter für `Query` nicht verwenden dürfen. + +Setzen Sie stattdessen den tatsächlichen Defaultwert des Funktionsparameters. Andernfalls wäre es inkonsistent. + +Zum Beispiel ist das nicht erlaubt: + +```Python +q: Annotated[str, Query(default="rick")] = "morty" +``` + +... denn es ist nicht klar, ob der Defaultwert „rick“ oder „morty“ sein soll. + +Sie würden also (bevorzugt) schreiben: + +```Python +q: Annotated[str, Query()] = "rick" +``` + +... oder in älteren Codebasen finden Sie: + +```Python +q: str = Query(default="rick") +``` + +### Vorzüge von `Annotated` { #advantages-of-annotated } + +**Es wird empfohlen, `Annotated` zu verwenden**, anstelle des Defaultwertes in Funktionsparametern, es ist aus mehreren Gründen **besser**. 🤓 + +Der **Default**wert des **Funktionsparameters** ist der **tatsächliche Default**wert, das ist in der Regel intuitiver mit Python. 😌 + +Sie könnten **diese gleiche Funktion** in **anderen Stellen** ohne FastAPI **aufrufen**, und es würde **wie erwartet funktionieren**. Wenn es einen **erforderlichen** Parameter gibt (ohne Defaultwert), wird Ihr **Editor** Ihnen dies mit einem Fehler mitteilen, außerdem wird **Python** sich beschweren, wenn Sie es ausführen, ohne den erforderlichen Parameter zu übergeben. + +Wenn Sie `Annotated` nicht verwenden und stattdessen die **(alte) Defaultwert-Stilform** verwenden, müssen Sie sich daran **erinnern**, die Argumente der Funktion zu übergeben, wenn Sie diese Funktion ohne FastAPI in **anderen Stellen** aufrufen. Ansonsten sind die Werte anders als erwartet (z. B. `QueryInfo` oder etwas Ähnliches statt `str`). Ihr Editor kann Ihnen nicht helfen, und Python wird die Funktion ohne Klagen ausführen und sich nur beschweren wenn die Operationen innerhalb auf einen Fehler stoßen. + +Da `Annotated` mehr als eine Metadaten-Annotation haben kann, könnten Sie dieselbe Funktion sogar mit anderen Tools verwenden, wie z. B. [Typer](https://typer.tiangolo.com/). 🚀 + +## Mehr Validierungen hinzufügen { #add-more-validations } + +Sie können auch einen `min_length`-Parameter hinzufügen: + +{* ../../docs_src/query_params_str_validations/tutorial003_an_py310.py hl[10] *} + +## Reguläre Ausdrücke hinzufügen { #add-regular-expressions } + +Sie können einen regulären Ausdruck `pattern` definieren, mit dem der Parameter übereinstimmen muss: + +{* ../../docs_src/query_params_str_validations/tutorial004_an_py310.py hl[11] *} + +Dieses spezielle Suchmuster im regulären Ausdruck überprüft, dass der erhaltene Parameterwert: + +* `^`: mit den nachfolgenden Zeichen beginnt, keine Zeichen davor hat. +* `fixedquery`: den exakten Text `fixedquery` hat. +* `$`: dort endet, keine weiteren Zeichen nach `fixedquery` hat. + +Wenn Sie sich mit all diesen **„regulärer Ausdruck“**-Ideen verloren fühlen, keine Sorge. Sie sind ein schwieriges Thema für viele Menschen. Sie können noch viele Dinge tun, ohne reguläre Ausdrücke direkt zu benötigen. + +Nun wissen Sie, dass Sie sie in **FastAPI** immer dann verwenden können, wenn Sie sie brauchen. + +## Defaultwerte { #default-values } + +Natürlich können Sie Defaultwerte verwenden, die nicht `None` sind. + +Nehmen wir an, Sie möchten, dass der `q` Query-Parameter eine `min_length` von `3` hat und einen Defaultwert von „fixedquery“: + +{* ../../docs_src/query_params_str_validations/tutorial005_an_py310.py hl[9] *} + +/// note | Hinweis + +Ein Defaultwert irgendeines Typs, einschließlich `None`, macht den Parameter optional (nicht erforderlich). + +/// + +## Erforderliche Parameter { #required-parameters } + +Wenn wir keine weiteren Validierungen oder Metadaten deklarieren müssen, können wir den `q` Query-Parameter erforderlich machen, indem wir einfach keinen Defaultwert deklarieren, wie: + +```Python +q: str +``` + +statt: + +```Python +q: str | None = None +``` + +Aber jetzt deklarieren wir es mit `Query`, zum Beispiel so: + +```Python +q: Annotated[str | None, Query(min_length=3)] = None +``` + +Wenn Sie einen Wert als erforderlich deklarieren müssen, während Sie `Query` verwenden, deklarieren Sie einfach keinen Defaultwert: + +{* ../../docs_src/query_params_str_validations/tutorial006_an_py310.py hl[9] *} + +### Erforderlich, kann `None` sein { #required-can-be-none } + +Sie können deklarieren, dass ein Parameter `None` akzeptieren kann, aber trotzdem erforderlich ist. Dadurch müssten Clients den Wert senden, selbst wenn der Wert `None` ist. + +Um das zu tun, können Sie deklarieren, dass `None` ein gültiger Typ ist, einfach indem Sie keinen Defaultwert deklarieren: + +{* ../../docs_src/query_params_str_validations/tutorial006c_an_py310.py hl[9] *} + +## Query-Parameter-Liste / Mehrere Werte { #query-parameter-list-multiple-values } + +Wenn Sie einen Query-Parameter explizit mit `Query` definieren, können Sie ihn auch so deklarieren, dass er eine Liste von Werten empfängt, oder anders gesagt, dass er mehrere Werte empfangen kann. + +Um zum Beispiel einen Query-Parameter `q` zu deklarieren, der mehrmals in der URL vorkommen kann, schreiben Sie: + +{* ../../docs_src/query_params_str_validations/tutorial011_an_py310.py hl[9] *} + +Dann, mit einer URL wie: + +``` +http://localhost:8000/items/?q=foo&q=bar +``` + +würden Sie die mehreren `q`-*Query-Parameter*-Werte (`foo` und `bar`) in einer Python-`list` in Ihrer *Pfadoperation-Funktion* im *Funktionsparameter* `q` erhalten. + +So wäre die Response zu dieser URL: + +```JSON +{ + "q": [ + "foo", + "bar" + ] +} +``` + +/// tip | Tipp + +Um einen Query-Parameter mit einem Typ `list` zu deklarieren, wie im obigen Beispiel, müssen Sie explizit `Query` verwenden, da er andernfalls als Requestbody interpretiert würde. + +/// + +Die interaktive API-Dokumentation wird entsprechend aktualisiert, um mehrere Werte zu erlauben: + + + +### Query-Parameter-Liste / Mehrere Werte mit Defaults { #query-parameter-list-multiple-values-with-defaults } + +Sie können auch eine Default-`list` von Werten definieren, wenn keine bereitgestellt werden: + +{* ../../docs_src/query_params_str_validations/tutorial012_an_py310.py hl[9] *} + +Wenn Sie zu: + +``` +http://localhost:8000/items/ +``` + +gehen, wird der Defaultwert für `q` sein: `["foo", "bar"]`, und Ihre Response wird sein: + +```JSON +{ + "q": [ + "foo", + "bar" + ] +} +``` + +#### Nur `list` verwenden { #using-just-list } + +Sie können auch `list` direkt verwenden, anstelle von `list[str]`: + +{* ../../docs_src/query_params_str_validations/tutorial013_an_py310.py hl[9] *} + +/// note | Hinweis + +Beachten Sie, dass FastAPI in diesem Fall den Inhalt der Liste nicht überprüft. + +Zum Beispiel würde `list[int]` überprüfen (und dokumentieren), dass der Inhalt der Liste Ganzzahlen sind. Aber `list` alleine würde das nicht. + +/// + +## Mehr Metadaten deklarieren { #declare-more-metadata } + +Sie können mehr Informationen über den Parameter hinzufügen. + +Diese Informationen werden in das generierte OpenAPI aufgenommen und von den Dokumentationsoberflächen und externen Tools verwendet. + +/// note | Hinweis + +Beachten Sie, dass verschiedene Tools möglicherweise unterschiedliche Unterstützungslevels für OpenAPI haben. + +Einige davon könnten noch nicht alle zusätzlichen Informationen anzeigen, die Sie deklariert haben, obwohl in den meisten Fällen die fehlende Funktionalität bereits in der Entwicklung geplant ist. + +/// + +Sie können einen `title` hinzufügen: + +{* ../../docs_src/query_params_str_validations/tutorial007_an_py310.py hl[10] *} + +Und eine `description`: + +{* ../../docs_src/query_params_str_validations/tutorial008_an_py310.py hl[14] *} + +## Alias-Parameter { #alias-parameters } + +Stellen Sie sich vor, Sie möchten, dass der Parameter `item-query` ist. + +Wie in: + +``` +http://127.0.0.1:8000/items/?item-query=foobaritems +``` + +Aber `item-query` ist kein gültiger Name für eine Variable in Python. + +Am ähnlichsten wäre `item_query`. + +Aber Sie benötigen dennoch, dass er genau `item-query` ist ... + +Dann können Sie ein `alias` deklarieren, und dieser Alias wird verwendet, um den Parameterwert zu finden: + +{* ../../docs_src/query_params_str_validations/tutorial009_an_py310.py hl[9] *} + +## Parameter als deprecatet ausweisen { #deprecating-parameters } + +Nehmen wir an, Ihnen gefällt dieser Parameter nicht mehr. + +Sie müssen ihn eine Weile dort belassen, da es Clients gibt, die ihn verwenden, aber Sie möchten, dass die Dokumentation ihn klar als deprecatet anzeigt. + +Dann übergeben Sie den Parameter `deprecated=True` an `Query`: + +{* ../../docs_src/query_params_str_validations/tutorial010_an_py310.py hl[19] *} + +Die Dokumentation wird es so anzeigen: + + + +## Parameter von OpenAPI ausschließen { #exclude-parameters-from-openapi } + +Um einen Query-Parameter aus dem generierten OpenAPI-Schema auszuschließen (und somit aus den automatischen Dokumentationssystemen), setzen Sie den Parameter `include_in_schema` von `Query` auf `False`: + +{* ../../docs_src/query_params_str_validations/tutorial014_an_py310.py hl[10] *} + +## Benutzerdefinierte Validierung { #custom-validation } + +Es kann Fälle geben, in denen Sie eine **benutzerdefinierte Validierung** durchführen müssen, die nicht mit den oben gezeigten Parametern durchgeführt werden kann. + +In diesen Fällen können Sie eine **benutzerdefinierte Validierungsfunktion** verwenden, die nach der normalen Validierung angewendet wird (z. B. nach der Validierung, dass der Wert ein `str` ist). + +Sie können dies mit [Pydantics `AfterValidator`](https://docs.pydantic.dev/latest/concepts/validators/#field-after-validator) innerhalb von `Annotated` erreichen. + +/// tip | Tipp + +Pydantic unterstützt auch [`BeforeValidator`](https://docs.pydantic.dev/latest/concepts/validators/#field-before-validator) und andere. 🤓 + +/// + +Zum Beispiel überprüft dieser benutzerdefinierte Validator, ob die Artikel-ID mit `isbn-` für eine ISBN-Buchnummer oder mit `imdb-` für eine IMDB-Film-URL-ID beginnt: + +{* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py hl[5,16:19,24] *} + +/// note | Hinweis + +Dies ist verfügbar seit Pydantic Version 2 oder höher. 😎 + +/// + +/// tip | Tipp + +Wenn Sie irgendeine Art von Validierung durchführen müssen, die eine Kommunikation mit einer **externen Komponente** erfordert, wie z. B. einer Datenbank oder einer anderen API, sollten Sie stattdessen **FastAPI-Abhängigkeiten** verwenden. Sie werden diese später kennenlernen. + +Diese benutzerdefinierten Validatoren sind für Dinge gedacht, die einfach mit denselben **Daten** überprüft werden können, die im Request bereitgestellt werden. + +/// + +### Diesen Code verstehen { #understand-that-code } + +Der wichtige Punkt ist einfach die Verwendung von **`AfterValidator` mit einer Funktion innerhalb von `Annotated`**. Fühlen Sie sich frei, diesen Teil zu überspringen. 🤸 + +--- + +Aber wenn Sie neugierig auf dieses spezielle Codebeispiel sind und immer noch Spaß haben, hier sind einige zusätzliche Details. + +#### String mit `value.startswith()` { #string-with-value-startswith } + +Haben Sie bemerkt? Ein String mit `value.startswith()` kann ein Tuple übernehmen, und es wird jeden Wert im Tuple überprüfen: + +{* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py ln[16:19] hl[17] *} + +#### Ein zufälliges Item { #a-random-item } + +Mit `data.items()` erhalten wir ein iterierbares Objekt mit Tupeln, die Schlüssel und Wert für jedes Dictionary-Element enthalten. + +Wir konvertieren dieses iterierbare Objekt mit `list(data.items())` in eine richtige `list`. + +Dann können wir mit `random.choice()` einen **zufälligen Wert** aus der Liste erhalten, also bekommen wir ein Tuple mit `(id, name)`. Es wird etwas wie `("imdb-tt0371724", "The Hitchhiker's Guide to the Galaxy")` sein. + +Dann **weisen wir diese beiden Werte** des Tupels den Variablen `id` und `name` zu. + +Wenn der Benutzer also keine Artikel-ID bereitgestellt hat, erhält er trotzdem einen zufälligen Vorschlag. + +... wir tun all dies in einer **einzelnen einfachen Zeile**. 🤯 Lieben Sie nicht auch Python? 🐍 + +{* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py ln[22:30] hl[29] *} + +## Zusammenfassung { #recap } + +Sie können zusätzliche Validierungen und Metadaten für Ihre Parameter deklarieren. + +Allgemeine Validierungen und Metadaten: + +* `alias` +* `title` +* `description` +* `deprecated` + +Validierungen, die spezifisch für Strings sind: + +* `min_length` +* `max_length` +* `pattern` + +Benutzerdefinierte Validierungen mit `AfterValidator`. + +In diesen Beispielen haben Sie gesehen, wie Sie Validierungen für `str`-Werte deklarieren. + +Sehen Sie sich die nächsten Kapitel an, um zu erfahren, wie Sie Validierungen für andere Typen, wie z. B. Zahlen, deklarieren. diff --git a/docs/de/docs/tutorial/query-params.md b/docs/de/docs/tutorial/query-params.md new file mode 100644 index 0000000000000..86ec9f4abcf72 --- /dev/null +++ b/docs/de/docs/tutorial/query-params.md @@ -0,0 +1,188 @@ +# Query-Parameter { #query-parameters } + +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_py310.py hl[9] *} + +Die Query ist die Menge von Schlüssel-Wert-Paaren, die nach dem `?` in einer URL folgen und durch `&`-Zeichen getrennt sind. + +Zum Beispiel sind in der URL: + +``` +http://127.0.0.1:8000/items/?skip=0&limit=10 +``` + +... die Query-Parameter: + +* `skip`: mit dem Wert `0` +* `limit`: mit dem Wert `10` + +Da sie Teil der URL sind, sind sie „naturgemäß“ Strings. + +Aber wenn Sie sie mit Python-Typen deklarieren (im obigen Beispiel als `int`), werden sie zu diesem Typ konvertiert und gegen diesen validiert. + +Die gleichen Prozesse, die für Pfad-Parameter gelten, werden auch auf Query-Parameter angewendet: + +* Editor-Unterstützung (natürlich) +* Daten-„Parsen“ +* Datenvalidierung +* Automatische Dokumentation + +## Defaultwerte { #defaults } + +Da Query-Parameter kein fester Teil eines Pfades sind, können sie optional sein und Defaultwerte haben. + +Im obigen Beispiel haben sie die Defaultwerte `skip=0` und `limit=10`. + +Wenn Sie also zur URL: + +``` +http://127.0.0.1:8000/items/ +``` + +gehen, so ist das das gleiche wie die URL: + +``` +http://127.0.0.1:8000/items/?skip=0&limit=10 +``` + +Aber wenn Sie zum Beispiel zu: + +``` +http://127.0.0.1:8000/items/?skip=20 +``` + +gehen, werden die Parameterwerte Ihrer Funktion sein: + +* `skip=20`: da Sie das in der URL gesetzt haben +* `limit=10`: weil das der Defaultwert ist + +## Optionale Parameter { #optional-parameters } + +Auf die gleiche Weise können Sie optionale Query-Parameter deklarieren, indem Sie deren Defaultwert auf `None` setzen: + +{* ../../docs_src/query_params/tutorial002_py310.py hl[7] *} + +In diesem Fall wird der Funktionsparameter `q` optional und standardmäßig `None` sein. + +/// tip | Tipp + +Beachten Sie auch, dass **FastAPI** intelligent genug ist, um zu erkennen, dass der Pfad-Parameter `item_id` ein Pfad-Parameter ist und `q` keiner, daher muss letzteres ein Query-Parameter sein. + +/// + +## Typkonvertierung von Query-Parametern { #query-parameter-type-conversion } + +Sie können auch `bool`-Typen deklarieren, und sie werden konvertiert: + +{* ../../docs_src/query_params/tutorial003_py310.py hl[7] *} + +Wenn Sie in diesem Fall zu: + +``` +http://127.0.0.1:8000/items/foo?short=1 +``` + +oder + +``` +http://127.0.0.1:8000/items/foo?short=True +``` + +oder + +``` +http://127.0.0.1:8000/items/foo?short=true +``` + +oder + +``` +http://127.0.0.1:8000/items/foo?short=on +``` + +oder + +``` +http://127.0.0.1:8000/items/foo?short=yes +``` + +gehen, oder zu irgendeiner anderen Variante der Groß-/Kleinschreibung (Alles groß, Anfangsbuchstabe groß, usw.), dann wird Ihre Funktion den Parameter `short` mit dem `bool`-Wert `True` sehen, ansonsten mit dem Wert `False`. + + +## Mehrere Pfad- und Query-Parameter { #multiple-path-and-query-parameters } + +Sie können mehrere Pfad-Parameter und Query-Parameter gleichzeitig deklarieren, **FastAPI** weiß, welches welcher ist. + +Und Sie müssen sie auch nicht in einer spezifischen Reihenfolge deklarieren. + +Parameter werden anhand ihres Namens erkannt: + +{* ../../docs_src/query_params/tutorial004_py310.py hl[6,8] *} + +## Erforderliche Query-Parameter { #required-query-parameters } + +Wenn Sie einen Defaultwert für Nicht-Pfad-Parameter deklarieren (bis jetzt haben wir nur Query-Parameter gesehen), dann ist der Parameter nicht erforderlich. + +Wenn Sie keinen spezifischen Wert haben wollen, sondern der Parameter einfach optional sein soll, dann setzen Sie den Defaultwert auf `None`. + +Aber wenn Sie wollen, dass ein Query-Parameter erforderlich ist, vergeben Sie einfach keinen Defaultwert: + +{* ../../docs_src/query_params/tutorial005_py310.py hl[6:7] *} + +Hier ist der Query-Parameter `needy` ein erforderlicher Query-Parameter vom Typ `str`. + +Wenn Sie in Ihrem Browser eine URL wie: + +``` +http://127.0.0.1:8000/items/foo-item +``` + +... öffnen, ohne den erforderlichen Parameter `needy` hinzuzufügen, dann erhalten Sie einen Fehler wie den folgenden: + +```JSON +{ + "detail": [ + { + "type": "missing", + "loc": [ + "query", + "needy" + ], + "msg": "Field required", + "input": null + } + ] +} +``` + +Da `needy` ein erforderlicher Parameter ist, müssen Sie ihn in der URL setzen: + +``` +http://127.0.0.1:8000/items/foo-item?needy=sooooneedy +``` + +... das funktioniert: + +```JSON +{ + "item_id": "foo-item", + "needy": "sooooneedy" +} +``` + +Und natürlich können Sie einige Parameter als erforderlich, einige mit Defaultwert, und einige als vollständig optional definieren: + +{* ../../docs_src/query_params/tutorial006_py310.py hl[8] *} + +In diesem Fall gibt es 3 Query-Parameter: + +* `needy`, ein erforderlicher `str`. +* `skip`, ein `int` mit einem Defaultwert `0`. +* `limit`, ein optionales `int`. + +/// tip | Tipp + +Sie können auch `Enum`s verwenden, auf die gleiche Weise wie mit [Pfad-Parametern](path-params.md#predefined-values). + +/// diff --git a/docs/de/docs/tutorial/request-files.md b/docs/de/docs/tutorial/request-files.md new file mode 100644 index 0000000000000..7a344604aec7e --- /dev/null +++ b/docs/de/docs/tutorial/request-files.md @@ -0,0 +1,176 @@ +# Dateien im Request { #request-files } + +Sie können Dateien, die vom Client hochgeladen werden, mithilfe von `File` definieren. + +/// note | Hinweis + +Um hochgeladene Dateien zu empfangen, installieren Sie zuerst [`python-multipart`](https://github.com/Kludex/python-multipart). + +Stellen Sie sicher, dass Sie eine [virtuelle Umgebung](../virtual-environments.md) erstellen, sie aktivieren und dann das Paket installieren, zum Beispiel: + +```console +$ pip install python-multipart +``` + +Das liegt daran, dass hochgeladene Dateien als „Formulardaten“ gesendet werden. + +/// + +## `File` importieren { #import-file } + +Importieren Sie `File` und `UploadFile` von `fastapi`: + +{* ../../docs_src/request_files/tutorial001_an_py310.py hl[3] *} + +## `File`-Parameter definieren { #define-file-parameters } + +Erstellen Sie Datei-Parameter, so wie Sie es auch mit `Body` oder `Form` machen würden: + +{* ../../docs_src/request_files/tutorial001_an_py310.py hl[9] *} + +/// note | Hinweis + +`File` ist eine Klasse, die direkt von `Form` erbt. + +Aber erinnern Sie sich, dass, wenn Sie `Query`, `Path`, `File` und andere von `fastapi` importieren, diese tatsächlich Funktionen sind, welche spezielle Klassen zurückgeben. + +/// + +/// tip | Tipp + +Um Dateibodys zu deklarieren, müssen Sie `File` verwenden, da diese Parameter sonst als Query-Parameter oder Body (JSON)-Parameter interpretiert werden würden. + +/// + +Die Dateien werden als „Formulardaten“ hochgeladen. + +Wenn Sie den Typ des Parameters Ihrer *Pfadoperation-Funktion* als `bytes` deklarieren, wird **FastAPI** die Datei für Sie auslesen, und Sie erhalten den Inhalt als `bytes`. + +Bedenken Sie, dass das bedeutet, dass sich der gesamte Inhalt der Datei im Arbeitsspeicher befindet. Das wird für kleinere Dateien gut funktionieren. + +Aber es gibt viele Fälle, in denen Sie davon profitieren, `UploadFile` zu verwenden. + +## Datei-Parameter mit `UploadFile` { #file-parameters-with-uploadfile } + +Definieren Sie einen Datei-Parameter mit dem Typ `UploadFile`: + +{* ../../docs_src/request_files/tutorial001_an_py310.py hl[14] *} + +`UploadFile` zu verwenden, hat mehrere Vorzüge gegenüber `bytes`: + +* Sie müssen `File()` nicht als Parameter-Defaultwert verwenden. +* Es wird eine „gespoolte“ Datei verwendet: + * Eine Datei, die bis zu einem bestimmten Größen-Limit im Arbeitsspeicher behalten wird, und wenn das Limit überschritten wird, auf der Festplatte gespeichert wird. +* Das bedeutet, es wird für große Dateien wie Bilder, Videos, große Binärdateien, usw. gut funktionieren, ohne den ganzen Arbeitsspeicher aufzubrauchen. +* Sie können Metadaten aus der hochgeladenen Datei auslesen. +* Es hat eine [dateiartige](https://docs.python.org/3/glossary.html#term-file-like-object) `async`-Schnittstelle. +* Es stellt ein tatsächliches Python-[`SpooledTemporaryFile`](https://docs.python.org/3/library/tempfile.html#tempfile.SpooledTemporaryFile)-Objekt bereit, welches Sie direkt anderen Bibliotheken übergeben können, die ein dateiartiges Objekt erwarten. + +### `UploadFile` { #uploadfile } + +`UploadFile` hat die folgenden Attribute: + +* `filename`: Ein `str` mit dem ursprünglichen Namen der hochgeladenen Datei (z. B. `myimage.jpg`). +* `content_type`: Ein `str` mit dem Inhaltstyp (MIME-Typ / Medientyp) (z. B. `image/jpeg`). +* `file`: Ein [`SpooledTemporaryFile`](https://docs.python.org/3/library/tempfile.html#tempfile.SpooledTemporaryFile) (ein [dateiartiges](https://docs.python.org/3/glossary.html#term-file-like-object) Objekt). Das ist das tatsächliche Python-Dateiobjekt, das Sie direkt anderen Funktionen oder Bibliotheken übergeben können, welche ein „file-like“-Objekt erwarten. + +`UploadFile` hat die folgenden `async`-Methoden. Sie alle rufen die entsprechenden Methoden des darunterliegenden Datei-Objekts auf (wobei intern `SpooledTemporaryFile` verwendet wird). + +* `write(data)`: Schreibt `data` (`str` oder `bytes`) in die Datei. +* `read(size)`: Liest `size` (`int`) Bytes/Zeichen aus der Datei. +* `seek(offset)`: Geht zur Byte-Position `offset` (`int`) in der Datei. + * z. B. würde `await myfile.seek(0)` zum Anfang der Datei gehen. + * Das ist besonders dann nützlich, wenn Sie `await myfile.read()` einmal ausführen und dann diese Inhalte erneut auslesen müssen. +* `close()`: Schließt die Datei. + +Da alle diese Methoden `async`-Methoden sind, müssen Sie sie „await“en („erwarten“). + +Zum Beispiel können Sie innerhalb einer `async` *Pfadoperation-Funktion* den Inhalt wie folgt auslesen: + +```Python +contents = await myfile.read() +``` + +Wenn Sie sich innerhalb einer normalen `def`-*Pfadoperation-Funktion* befinden, können Sie direkt auf `UploadFile.file` zugreifen, zum Beispiel: + +```Python +contents = myfile.file.read() +``` + +/// note | Technische Details zu `async` + +Wenn Sie die `async`-Methoden verwenden, führt **FastAPI** die Datei-Methoden in einem Threadpool aus und erwartet sie. + +/// + +/// note | Technische Details zu Starlette + +**FastAPI**s `UploadFile` erbt direkt von **Starlette**s `UploadFile`, fügt aber ein paar notwendige Teile hinzu, um es kompatibel mit **Pydantic** und anderen Teilen von FastAPI zu machen. + +/// + +## Was sind „Formulardaten“ { #what-is-form-data } + +Der Weg, wie HTML-Formulare (`
`) die Daten zum Server senden, verwendet normalerweise eine „spezielle“ Kodierung für diese Daten. Diese unterscheidet sich von JSON. + +**FastAPI** stellt sicher, dass diese Daten von der richtigen Stelle ausgelesen werden, statt JSON zu erwarten. + +/// note | Technische Details + +Daten aus Formularen werden, wenn sie keine Dateien enthalten, normalerweise mit dem „media type“ `application/x-www-form-urlencoded` kodiert. + +Sollte das Formular aber Dateien enthalten, dann werden diese mit `multipart/form-data` kodiert. Wenn Sie `File` verwenden, wird **FastAPI** wissen, dass es die Dateien vom korrekten Teil des Bodys holen muss. + +Wenn Sie mehr über diese Kodierungen und Formularfelder lesen möchten, besuchen Sie die [MDN-Webdokumentation für `POST`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST). + +/// + +/// warning | Achtung + +Sie können mehrere `File`- und `Form`-Parameter in einer *Pfadoperation* deklarieren, aber Sie können nicht gleichzeitig auch `Body`-Felder deklarieren, welche Sie als JSON erwarten, da der Request den Body mittels `multipart/form-data` statt `application/json` kodiert. + +Das ist keine Limitation von **FastAPI**, sondern Teil des HTTP-Protokolls. + +/// + +## Optionaler Datei-Upload { #optional-file-upload } + +Sie können eine Datei optional machen, indem Sie Standard-Typannotationen verwenden und den Defaultwert auf `None` setzen: + +{* ../../docs_src/request_files/tutorial001_02_an_py310.py hl[9,17] *} + +## `UploadFile` mit zusätzlichen Metadaten { #uploadfile-with-additional-metadata } + +Sie können auch `File()` mit `UploadFile` verwenden, um zum Beispiel zusätzliche Metadaten zu setzen: + +{* ../../docs_src/request_files/tutorial001_03_an_py310.py hl[9,15] *} + +## Mehrere Datei-Uploads { #multiple-file-uploads } + +Es ist auch möglich, mehrere Dateien gleichzeitig hochzuladen. + +Diese werden demselben „Formularfeld“ zugeordnet, welches mittels „Formulardaten“ gesendet wird. + +Um das zu machen, deklarieren Sie eine Liste von `bytes` oder `UploadFile`s: + +{* ../../docs_src/request_files/tutorial002_an_py310.py hl[10,15] *} + +Sie erhalten, wie deklariert, eine `list` von `bytes` oder `UploadFile`s. + +/// note | Technische Details + +Sie können auch `from starlette.responses import HTMLResponse` verwenden. + +**FastAPI** bietet dieselben `starlette.responses` auch via `fastapi.responses` an, als Annehmlichkeit für Sie, den Entwickler. Die meisten verfügbaren Responses kommen aber direkt von Starlette. + +/// + +### Mehrere Datei-Uploads mit zusätzlichen Metadaten { #multiple-file-uploads-with-additional-metadata } + +Und so wie zuvor können Sie `File()` verwenden, um zusätzliche Parameter zu setzen, sogar für `UploadFile`: + +{* ../../docs_src/request_files/tutorial003_an_py310.py hl[11,18:20] *} + +## Zusammenfassung { #recap } + +Verwenden Sie `File`, `bytes` und `UploadFile`, um hochladbare Dateien im Request zu deklarieren, die als Formulardaten gesendet werden. diff --git a/docs/de/docs/tutorial/request-form-models.md b/docs/de/docs/tutorial/request-form-models.md new file mode 100644 index 0000000000000..b40d60d0bb3c3 --- /dev/null +++ b/docs/de/docs/tutorial/request-form-models.md @@ -0,0 +1,78 @@ +# Formularmodelle { #form-models } + +Sie können **Pydantic-Modelle** verwenden, um **Formularfelder** in FastAPI zu deklarieren. + +/// note | Hinweis + +Um Formulare zu verwenden, installieren Sie zuerst [`python-multipart`](https://github.com/Kludex/python-multipart). + +Stellen Sie sicher, dass Sie eine [Virtuelle Umgebung](../virtual-environments.md) erstellen, sie aktivieren und es dann installieren, zum Beispiel: + +```console +$ pip install python-multipart +``` + +/// + +/// note | Hinweis + +Dies wird seit FastAPI Version `0.113.0` unterstützt. 🤓 + +/// + +## Pydantic-Modelle für Formulare { #pydantic-models-for-forms } + +Sie müssen nur ein **Pydantic-Modell** mit den Feldern deklarieren, die Sie als **Formularfelder** erhalten möchten, und dann den Parameter als `Form` deklarieren: + +{* ../../docs_src/request_form_models/tutorial001_an_py310.py hl[9:11,15] *} + +**FastAPI** wird die Daten für **jedes Feld** aus den **Formulardaten** im Request **extrahieren** und Ihnen das von Ihnen definierte Pydantic-Modell übergeben. + +## Die Dokumentation testen { #check-the-docs } + +Sie können dies in der Dokumentations-UI unter `/docs` testen: + +
+ +
+ +## Zusätzliche Formularfelder verbieten { #forbid-extra-form-fields } + +In einigen speziellen Anwendungsfällen (wahrscheinlich nicht sehr häufig) möchten Sie möglicherweise die Formularfelder auf nur diejenigen beschränken, die im Pydantic-Modell deklariert sind, und jegliche **zusätzlichen** Felder **verbieten**. + +/// note | Hinweis + +Dies wird seit FastAPI Version `0.114.0` unterstützt. 🤓 + +/// + +Sie können die Modellkonfiguration von Pydantic verwenden, um jegliche `extra` Felder zu `verbieten`: + +{* ../../docs_src/request_form_models/tutorial002_an_py310.py hl[12] *} + +Wenn ein Client versucht, einige zusätzliche Daten zu senden, erhält er eine **Error-Response**. + +Zum Beispiel, wenn der Client versucht, folgende Formularfelder zu senden: + +* `username`: `Rick` +* `password`: `Portal Gun` +* `extra`: `Mr. Poopybutthole` + +erhält er eine Error-Response, die ihm mitteilt, dass das Feld `extra` nicht erlaubt ist: + +```json +{ + "detail": [ + { + "type": "extra_forbidden", + "loc": ["body", "extra"], + "msg": "Extra inputs are not permitted", + "input": "Mr. Poopybutthole" + } + ] +} +``` + +## Zusammenfassung { #summary } + +Sie können Pydantic-Modelle verwenden, um Formularfelder in FastAPI zu deklarieren. 😎 diff --git a/docs/de/docs/tutorial/request-forms-and-files.md b/docs/de/docs/tutorial/request-forms-and-files.md new file mode 100644 index 0000000000000..98e5428519e7b --- /dev/null +++ b/docs/de/docs/tutorial/request-forms-and-files.md @@ -0,0 +1,41 @@ +# Formulardaten und Dateien im Request { #request-forms-and-files } + +Sie können gleichzeitig Dateien und Formulardaten mit `File` und `Form` definieren. + +/// note | Hinweis + +Um hochgeladene Dateien und/oder Formulardaten zu empfangen, installieren Sie zuerst [`python-multipart`](https://github.com/Kludex/python-multipart). + +Stellen Sie sicher, dass Sie eine [virtuelle Umgebung](../virtual-environments.md) erstellen, diese aktivieren und es dann installieren, z. B.: + +```console +$ pip install python-multipart +``` + +/// + +## `File` und `Form` importieren { #import-file-and-form } + +{* ../../docs_src/request_forms_and_files/tutorial001_an_py310.py hl[3] *} + +## `File` und `Form`-Parameter definieren { #define-file-and-form-parameters } + +Erstellen Sie Datei- und Formularparameter, so wie Sie es auch mit `Body` oder `Query` machen würden: + +{* ../../docs_src/request_forms_and_files/tutorial001_an_py310.py hl[10:12] *} + +Die Datei- und Formularfelder werden als Formulardaten hochgeladen, und Sie erhalten diese Dateien und Formularfelder. + +Und Sie können einige der Dateien als `bytes` und einige als `UploadFile` deklarieren. + +/// warning | Achtung + +Sie können mehrere `File`- und `Form`-Parameter in einer *Pfadoperation* deklarieren, aber Sie können nicht auch `Body`-Felder deklarieren, die Sie als JSON erwarten, da der Body des Request mittels `multipart/form-data` statt `application/json` kodiert sein wird. + +Das ist keine Limitation von **FastAPI**, sondern Teil des HTTP-Protokolls. + +/// + +## Zusammenfassung { #recap } + +Verwenden Sie `File` und `Form` zusammen, wenn Sie Daten und Dateien zusammen im selben Request empfangen müssen. diff --git a/docs/de/docs/tutorial/request-forms.md b/docs/de/docs/tutorial/request-forms.md new file mode 100644 index 0000000000000..aedcd4a51fcab --- /dev/null +++ b/docs/de/docs/tutorial/request-forms.md @@ -0,0 +1,74 @@ +# Formulardaten { #form-data } + + +Wenn Sie Felder aus Formularen statt JSON empfangen müssen, können Sie `Form` verwenden. + +/// note | Hinweis + +Um Formulare zu verwenden, installieren Sie zuerst [`python-multipart`](https://github.com/Kludex/python-multipart). + +Erstellen Sie unbedingt eine [virtuelle Umgebung](../virtual-environments.md), aktivieren Sie diese und installieren Sie dann das Paket, zum Beispiel: + +```console +$ pip install python-multipart +``` + +/// + +## `Form` importieren { #import-form } + +Importieren Sie `Form` von `fastapi`: + +{* ../../docs_src/request_forms/tutorial001_an_py310.py hl[3] *} + +## `Form`-Parameter definieren { #define-form-parameters } + +Erstellen Sie Formular-Parameter, so wie Sie es auch mit `Body` oder `Query` machen würden: + +{* ../../docs_src/request_forms/tutorial001_an_py310.py hl[9] *} + +Zum Beispiel stellt eine der Möglichkeiten, die OAuth2-Spezifikation zu verwenden (genannt „password flow“), die Bedingung, einen `username` und ein `password` als Formularfelder zu senden. + +Die Spezifikation erfordert, dass die Felder exakt `username` und `password` genannt werden und als Formularfelder, nicht JSON, gesendet werden. + +Mit `Form` haben Sie die gleichen Konfigurationsmöglichkeiten wie mit `Body` (und `Query`, `Path`, `Cookie`), inklusive Validierung, Beispielen, einem Alias (z. B. `user-name` statt `username`), usw. + +/// note | Hinweis + +`Form` ist eine Klasse, die direkt von `Body` erbt. + +/// + +/// tip | Tipp + +Um Formularbodys zu deklarieren, verwenden Sie explizit `Form`, da diese Parameter sonst als Query-Parameter oder Body (JSON)-Parameter interpretiert werden würden. + +/// + +## Über „Formularfelder“ { #about-form-fields } + +HTML-Formulare (`
`) senden die Daten in einer „speziellen“ Kodierung zum Server, die sich von JSON unterscheidet. + +**FastAPI** stellt sicher, dass diese Daten korrekt ausgelesen werden, statt JSON zu erwarten. + +/// note | Technische Details + +Daten aus Formularen werden normalerweise mit dem „media type“ `application/x-www-form-urlencoded` kodiert. + +Wenn das Formular stattdessen Dateien enthält, werden diese mit `multipart/form-data` kodiert. Im nächsten Kapitel erfahren Sie mehr über die Handhabung von Dateien. + +Wenn Sie mehr über Formularfelder und ihre Kodierungen lesen möchten, besuchen Sie die [MDN-Webdokumentation für `POST`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST). + +/// + +/// warning | Achtung + +Sie können mehrere `Form`-Parameter in einer *Pfadoperation* deklarieren, aber Sie können nicht gleichzeitig auch `Body`-Felder deklarieren, welche Sie als JSON erwarten, da der Request den Body mittels `application/x-www-form-urlencoded` statt `application/json` kodiert. + +Das ist keine Limitation von **FastAPI**, sondern Teil des HTTP-Protokolls. + +/// + +## Zusammenfassung { #recap } + +Verwenden Sie `Form`, um Eingabe-Parameter für Formulardaten zu deklarieren. diff --git a/docs/de/docs/tutorial/response-model.md b/docs/de/docs/tutorial/response-model.md new file mode 100644 index 0000000000000..2b580bd6d50b1 --- /dev/null +++ b/docs/de/docs/tutorial/response-model.md @@ -0,0 +1,344 @@ +# Responsemodell – Rückgabetyp { #response-model-return-type } + +Sie können den Typ der Response deklarieren, indem Sie den **Rückgabetyp** der *Pfadoperation* annotieren. + +Hierbei können Sie **Typannotationen** genauso verwenden, wie Sie es bei Werten von Funktions-**Parametern** machen; verwenden Sie Pydantic-Modelle, Listen, Dicts und skalare Werte wie Nummern, Booleans, usw. + +{* ../../docs_src/response_model/tutorial001_01_py310.py hl[16,21] *} + +FastAPI wird diesen Rückgabetyp verwenden, um: + +* Die zurückzugebenden Daten zu **validieren**. + * Wenn die Daten ungültig sind (Sie haben z. B. ein Feld vergessen), bedeutet das, *Ihr* Anwendungscode ist fehlerhaft, er gibt nicht zurück, was er sollte, und daher wird ein Server-Error ausgegeben, statt falscher Daten. So können Sie und Ihre Clients sicher sein, dass diese die erwarteten Daten, in der richtigen Form erhalten. +* In der OpenAPI *Pfadoperation* ein **JSON-Schema** für die Response hinzuzufügen. + * Dieses wird von der **automatischen Dokumentation** verwendet. + * Es wird auch von automatisch Client-Code-generierenden Tools verwendet. +* Die zurückgegebenen Daten mit Pydantic zu **serialisieren** (zu JSON). Pydantic ist in **Rust** geschrieben und daher **viel schneller**. + +Aber am wichtigsten: + +* Es wird die Ausgabedaten auf das **limitieren und filtern**, was im Rückgabetyp definiert ist. + * Das ist insbesondere für die **Sicherheit** wichtig, mehr dazu unten. + +## `response_model`-Parameter { #response-model-parameter } + +Es gibt Fälle, da möchten oder müssen Sie Daten zurückgeben, die nicht genau dem entsprechen, was der Typ deklariert. + +Zum Beispiel könnten Sie **ein Dictionary zurückgeben** wollen, oder ein Datenbank-Objekt, aber **es als Pydantic-Modell deklarieren**. Auf diese Weise übernimmt das Pydantic-Modell alle Datendokumentation, -validierung, usw. für das Objekt, welches Sie zurückgeben (z. B. ein Dictionary oder ein Datenbank-Objekt). + +Würden Sie eine hierfür eine Rückgabetyp-Annotation verwenden, dann würden Tools und Editoren (korrekterweise) Fehler ausgeben, die Ihnen sagen, dass Ihre Funktion einen Typ zurückgibt (z. B. ein Dict), der sich unterscheidet von dem, was Sie deklariert haben (z. B. ein Pydantic-Modell). + +In solchen Fällen können Sie statt des Rückgabetyps den **Pfadoperation-Dekorator**-Parameter `response_model` verwenden. + +Sie können `response_model` in jeder möglichen *Pfadoperation* verwenden: + +* `@app.get()` +* `@app.post()` +* `@app.put()` +* `@app.delete()` +* usw. + +{* ../../docs_src/response_model/tutorial001_py310.py hl[17,22,24:27] *} + +/// note | Hinweis + +Beachten Sie, dass `response_model` ein Parameter der „Dekorator“-Methode ist (`get`, `post`, usw.). Nicht der *Pfadoperation-Funktion*, so wie die anderen Parameter und der Body. + +/// + +`response_model` nimmt denselben Typ entgegen, den Sie auch für ein Pydantic-Modellfeld deklarieren würden, also etwa ein Pydantic-Modell, aber es kann auch z. B. eine `list`e von Pydantic-Modellen sein, wie etwa `List[Item]`. + +FastAPI wird dieses `response_model` nehmen, um die Daten zu dokumentieren, validieren, usw. und auch, um **die Ausgabedaten** entsprechend der Typdeklaration **zu konvertieren und filtern**. + +/// tip | Tipp + +Wenn Sie in Ihrem Editor strikte Typchecks haben, mypy, usw., können Sie den Funktions-Rückgabetyp als `Any` deklarieren. + +So sagen Sie dem Editor, dass Sie absichtlich *irgendetwas* zurückgeben. Aber FastAPI wird trotzdem die Dokumentation, Validierung, Filterung, usw. der Daten übernehmen, via `response_model`. + +/// + +### `response_model`-Priorität { #response-model-priority } + +Wenn sowohl Rückgabetyp als auch `response_model` deklariert sind, hat `response_model` die Priorität und wird von FastAPI bevorzugt verwendet. + +So können Sie korrekte Typannotationen zu Ihrer Funktion hinzufügen, die von Ihrem Editor und Tools wie mypy verwendet werden. Und dennoch übernimmt FastAPI die Validierung und Dokumentation, usw., der Daten anhand von `response_model`. + +Sie können auch `response_model=None` verwenden, um das Erstellen eines Responsemodells für diese *Pfadoperation* zu unterbinden. Sie könnten das tun wollen, wenn Sie Dinge annotieren, die nicht gültige Pydantic-Felder sind. Ein Beispiel dazu werden Sie in einer der Abschnitte unten sehen. + +## Dieselben Eingabedaten zurückgeben { #return-the-same-input-data } + +Im Folgenden deklarieren wir ein `UserIn`-Modell; es enthält ein Klartext-Passwort: + +{* ../../docs_src/response_model/tutorial002_py310.py hl[7,9] *} + +/// note | Hinweis + +Um `EmailStr` zu verwenden, installieren Sie zuerst [`email-validator`](https://github.com/JoshData/python-email-validator). + +Stellen Sie sicher, dass Sie eine [virtuelle Umgebung](../virtual-environments.md) erstellen, sie aktivieren und es dann installieren, zum Beispiel: + +```console +$ pip install email-validator +``` + +oder mit: + +```console +$ pip install "pydantic[email]" +``` + +/// + +Wir verwenden dieses Modell, um sowohl unsere Eingabe- als auch Ausgabedaten zu deklarieren: + +{* ../../docs_src/response_model/tutorial002_py310.py hl[16] *} + +Immer wenn jetzt ein Browser einen Benutzer mit Passwort erzeugt, gibt die API dasselbe Passwort in der Response zurück. + +Hier ist das möglicherweise kein Problem, da es derselbe Benutzer ist, der das Passwort sendet. + +Aber wenn wir dasselbe Modell für eine andere *Pfadoperation* verwenden, könnten wir das Passwort dieses Benutzers zu jedem Client schicken. + +/// danger | Gefahr + +Speichern Sie niemals das Klartext-Passwort eines Benutzers, oder versenden Sie es in einer Response wie dieser, wenn Sie sich nicht der resultierenden Gefahren bewusst sind und nicht wissen, was Sie tun. + +/// + +## Ausgabemodell hinzufügen { #add-an-output-model } + +Wir können stattdessen ein Eingabemodell mit dem Klartext-Passwort, und ein Ausgabemodell ohne das Passwort erstellen: + +{* ../../docs_src/response_model/tutorial003_py310.py hl[9,11,16] *} + +Obwohl unsere *Pfadoperation-Funktion* hier denselben `user` von der Eingabe zurückgibt, der das Passwort enthält: + +{* ../../docs_src/response_model/tutorial003_py310.py hl[24] *} + +... haben wir deklariert, dass `response_model` das Modell `UserOut` ist, welches das Passwort nicht enthält: + +{* ../../docs_src/response_model/tutorial003_py310.py hl[22] *} + +Darum wird **FastAPI** sich darum kümmern, dass alle Daten, die nicht im Ausgabemodell deklariert sind, herausgefiltert werden (mittels Pydantic). + +### `response_model` oder Rückgabewert { #response-model-or-return-type } + +Da unsere zwei Modelle in diesem Fall unterschiedlich sind, würde, wenn wir den Rückgabewert der Funktion als `UserOut` deklarieren, der Editor sich beschweren, dass wir einen ungültigen Typ zurückgeben, weil das unterschiedliche Klassen sind. + +Darum müssen wir es in diesem Fall im `response_model`-Parameter deklarieren. + +... aber lesen Sie weiter, um zu sehen, wie man das anders lösen kann. + +## Rückgabewert und Datenfilterung { #return-type-and-data-filtering } + +Führen wir unser vorheriges Beispiel fort. Wir wollten **die Funktion mit einem Typ annotieren**, aber wir wollten in der Funktion tatsächlich etwas zurückgeben, das **mehr Daten** enthält. + +Wir möchten, dass FastAPI die Daten weiterhin mithilfe des Responsemodells **filtert**. Selbst wenn die Funktion mehr Daten zurückgibt, soll die Response nur die Felder enthalten, die im Responsemodell deklariert sind. + +Im vorherigen Beispiel mussten wir den `response_model`-Parameter verwenden, weil die Klassen unterschiedlich waren. Das bedeutet aber auch, wir bekommen keine Unterstützung vom Editor und anderen Tools, die den Funktions-Rückgabewert überprüfen. + +Aber in den meisten Fällen, wenn wir so etwas machen, wollen wir nur, dass das Modell einige der Daten **filtert/entfernt**, so wie in diesem Beispiel. + +Und in solchen Fällen können wir Klassen und Vererbung verwenden, um Vorteil aus den Typannotationen in der Funktion zu ziehen, was vom Editor und von Tools besser unterstützt wird, während wir gleichzeitig FastAPIs **Datenfilterung** behalten. + +{* ../../docs_src/response_model/tutorial003_01_py310.py hl[7:10,13:14,18] *} + +Damit erhalten wir Tool-Unterstützung, vom Editor und mypy, da dieser Code hinsichtlich der Typen korrekt ist, aber wir erhalten auch die Datenfilterung von FastAPI. + +Wie funktioniert das? Schauen wir uns das mal an. 🤓 + +### Typannotationen und Tooling { #type-annotations-and-tooling } + +Sehen wir uns zunächst an, wie Editor, mypy und andere Tools dies sehen würden. + +`BaseUser` verfügt über die Basis-Felder. Dann erbt `UserIn` von `BaseUser` und fügt das Feld `password` hinzu, sodass es nun alle Felder beider Modelle hat. + +Wir annotieren den Funktionsrückgabetyp als `BaseUser`, geben aber tatsächlich eine `UserIn`-Instanz zurück. + +Für den Editor, mypy und andere Tools ist das kein Problem, da `UserIn` eine Unterklasse von `BaseUser` ist (Salopp: `UserIn` ist ein `BaseUser`). Es handelt sich um einen *gültigen* Typ, solange irgendetwas überreicht wird, das ein `BaseUser` ist. + +### FastAPI Datenfilterung { #fastapi-data-filtering } + +FastAPI seinerseits wird den Rückgabetyp sehen und sicherstellen, dass das, was zurückgegeben wird, **nur** diejenigen Felder enthält, welche im Typ deklariert sind. + +FastAPI macht intern mehrere Dinge mit Pydantic, um sicherzustellen, dass obige Ähnlichkeitsregeln der Klassenvererbung nicht auf die Filterung der zurückgegebenen Daten angewendet werden, sonst könnten Sie am Ende mehr Daten zurückgeben als gewollt. + +Auf diese Weise erhalten Sie das beste beider Welten: Sowohl Typannotationen mit **Tool-Unterstützung** als auch **Datenfilterung**. + +## Anzeige in der Dokumentation { #see-it-in-the-docs } + +Wenn Sie sich die automatische Dokumentation betrachten, können Sie sehen, dass Eingabe- und Ausgabemodell beide ihr eigenes JSON-Schema haben: + + + +Und beide Modelle werden auch in der interaktiven API-Dokumentation verwendet: + + + +## Andere Rückgabetyp-Annotationen { #other-return-type-annotations } + +Es kann Fälle geben, bei denen Sie etwas zurückgeben, das kein gültiges Pydantic-Feld ist, und Sie annotieren es in der Funktion nur, um Unterstützung von Tools zu erhalten (Editor, mypy, usw.). + +### Eine Response direkt zurückgeben { #return-a-response-directly } + +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). + +{* ../../docs_src/response_model/tutorial003_02_py310.py hl[8,10:11] *} + +Dieser einfache Anwendungsfall wird automatisch von FastAPI gehandhabt, weil die Annotation des Rückgabetyps die Klasse (oder eine Unterklasse von) `Response` ist. + +Und Tools werden auch glücklich sein, weil sowohl `RedirectResponse` als auch `JSONResponse` Unterklassen von `Response` sind, die Typannotation ist daher korrekt. + +### Eine Unterklasse von Response annotieren { #annotate-a-response-subclass } + +Sie können auch eine Unterklasse von `Response` in der Typannotation verwenden. + +{* ../../docs_src/response_model/tutorial003_03_py310.py hl[8:9] *} + +Das wird ebenfalls funktionieren, weil `RedirectResponse` eine Unterklasse von `Response` ist, und FastAPI sich um diesen einfachen Anwendungsfall automatisch kümmert. + +### Ungültige Rückgabetyp-Annotationen { #invalid-return-type-annotations } + +Aber wenn Sie ein beliebiges anderes Objekt zurückgeben, das kein gültiger Pydantic-Typ ist (z. B. ein Datenbank-Objekt), und Sie annotieren es so in der Funktion, wird FastAPI versuchen, ein Pydantic-Responsemodell von dieser Typannotation zu erstellen, und scheitern. + +Das gleiche wird passieren, wenn Sie eine Union mehrerer Typen haben, und einer oder mehrere sind nicht gültige Pydantic-Typen. Zum Beispiel funktioniert folgendes nicht 💥: + +{* ../../docs_src/response_model/tutorial003_04_py310.py hl[8] *} + +... das scheitert, da die Typannotation kein Pydantic-Typ ist, und auch keine einzelne `Response`-Klasse, oder -Unterklasse, es ist eine Union (eines von beiden) von `Response` und `dict`. + +### Responsemodell deaktivieren { #disable-response-model } + +Beim Beispiel oben fortsetzend, mögen Sie vielleicht die standardmäßige Datenvalidierung, -Dokumentation, -Filterung, usw., die von FastAPI durchgeführt wird, nicht haben. + +Aber Sie möchten dennoch den Rückgabetyp in der Funktion annotieren, um Unterstützung von Editoren und Typcheckern (z. B. mypy) zu erhalten. + +In diesem Fall können Sie die Generierung des Responsemodells abschalten, indem Sie `response_model=None` setzen: + +{* ../../docs_src/response_model/tutorial003_05_py310.py hl[7] *} + +Das bewirkt, dass FastAPI die Generierung des Responsemodells unterlässt, und damit können Sie jede gewünschte Rückgabetyp-Annotation haben, ohne dass es Ihre FastAPI-Anwendung beeinflusst. 🤓 + +## Parameter für die Enkodierung des Responsemodells { #response-model-encoding-parameters } + +Ihr Responsemodell könnte Defaultwerte haben, wie: + +{* ../../docs_src/response_model/tutorial004_py310.py hl[9,11:12] *} + +* `description: Union[str, None] = None` (oder `str | None = None` in Python 3.10) hat einen Defaultwert `None`. +* `tax: float = 10.5` hat einen Defaultwert `10.5`. +* `tags: List[str] = []` hat eine leere Liste als Defaultwert: `[]`. + +Aber Sie möchten diese vielleicht vom Resultat ausschließen, wenn Sie gar nicht gesetzt wurden. + +Wenn Sie zum Beispiel Modelle mit vielen optionalen Attributen in einer NoSQL-Datenbank haben, und Sie möchten nicht ellenlange JSON-Responses voller Defaultwerte senden. + +### Den `response_model_exclude_unset`-Parameter verwenden { #use-the-response-model-exclude-unset-parameter } + +Sie können den *Pfadoperation-Dekorator*-Parameter `response_model_exclude_unset=True` setzen: + +{* ../../docs_src/response_model/tutorial004_py310.py hl[22] *} + +Die Defaultwerte werden dann nicht in der Response enthalten sein, sondern nur die tatsächlich gesetzten Werte. + +Wenn Sie also den Artikel mit der ID `foo` bei der *Pfadoperation* anfragen, wird (ohne die Defaultwerte) die Response sein: + +```JSON +{ + "name": "Foo", + "price": 50.2 +} +``` + +/// note | Hinweis + +Sie können auch: + +* `response_model_exclude_defaults=True` +* `response_model_exclude_none=True` + +verwenden, wie in der [Pydantic-Dokumentation](https://docs.pydantic.dev/1.10/usage/exporting_models/#modeldict) für `exclude_defaults` und `exclude_none` beschrieben. + +/// + +#### Daten mit Werten für Felder mit Defaultwerten { #data-with-values-for-fields-with-defaults } + +Aber wenn Ihre Daten Werte für Modellfelder mit Defaultwerten haben, wie etwa der Artikel mit der ID `bar`: + +```Python hl_lines="3 5" +{ + "name": "Bar", + "description": "The bartenders", + "price": 62, + "tax": 20.2 +} +``` + +dann werden diese Werte in der Response enthalten sein. + +#### Daten mit den gleichen Werten wie die Defaultwerte { #data-with-the-same-values-as-the-defaults } + +Wenn Daten die gleichen Werte haben wie ihre Defaultwerte, wie etwa der Artikel mit der ID `baz`: + +```Python hl_lines="3 5-6" +{ + "name": "Baz", + "description": None, + "price": 50.2, + "tax": 10.5, + "tags": [] +} +``` + +dann ist FastAPI klug genug (tatsächlich ist Pydantic klug genug) zu erkennen, dass, obwohl `description`, `tax`, und `tags` die gleichen Werte haben wie ihre Defaultwerte, sie explizit gesetzt wurden (statt dass sie von den Defaultwerten genommen wurden). + +Diese Felder werden also in der JSON-Response enthalten sein. + +/// tip | Tipp + +Beachten Sie, dass Defaultwerte alles Mögliche sein können, nicht nur `None`. + +Sie können eine Liste (`[]`), ein `float` `10.5`, usw. sein. + +/// + +### `response_model_include` und `response_model_exclude` { #response-model-include-and-response-model-exclude } + +Sie können auch die Parameter `response_model_include` und `response_model_exclude` im **Pfadoperation-Dekorator** verwenden. + +Diese nehmen ein `set` von `str`s entgegen, welches Namen von Attributen sind, die eingeschlossen (ohne die Anderen) oder ausgeschlossen (nur die Anderen) werden sollen. + +Das kann als schnelle Abkürzung verwendet werden, wenn Sie nur ein Pydantic-Modell haben und ein paar Daten von der Ausgabe ausschließen wollen. + +/// tip | Tipp + +Es wird dennoch empfohlen, dass Sie die Ideen von oben verwenden, also mehrere Klassen statt dieser Parameter. + +Der Grund ist, dass das das generierte JSON-Schema in der OpenAPI Ihrer Anwendung (und deren Dokumentation) dennoch das komplette Modell abbildet, selbst wenn Sie `response_model_include` oder `response_model_exclude` verwenden, um einige Attribute auszuschließen. + +Das trifft auch auf `response_model_by_alias` zu, welches ähnlich funktioniert. + +/// + +{* ../../docs_src/response_model/tutorial005_py310.py hl[29,35] *} + +/// tip | Tipp + +Die Syntax `{"name", "description"}` erzeugt ein `set` mit diesen zwei Werten. + +Äquivalent zu `set(["name", "description"])`. + +/// + +#### `list`en statt `set`s verwenden { #using-lists-instead-of-sets } + +Wenn Sie vergessen, ein `set` zu verwenden, und stattdessen eine `list`e oder ein `tuple` übergeben, wird FastAPI die dennoch in ein `set` konvertieren, und es wird korrekt funktionieren: + +{* ../../docs_src/response_model/tutorial006_py310.py hl[29,35] *} + +## Zusammenfassung { #recap } + +Verwenden Sie den Parameter `response_model` im *Pfadoperation-Dekorator*, um Responsemodelle zu definieren, und besonders, um private Daten herauszufiltern. + +Verwenden Sie `response_model_exclude_unset`, um nur explizit gesetzte Werte zurückzugeben. diff --git a/docs/de/docs/tutorial/response-status-code.md b/docs/de/docs/tutorial/response-status-code.md new file mode 100644 index 0000000000000..63962829ddeb3 --- /dev/null +++ b/docs/de/docs/tutorial/response-status-code.md @@ -0,0 +1,102 @@ +# Response-Statuscode { #response-status-code } + + +Genauso wie Sie ein Responsemodell angeben können, können Sie auch den HTTP-Statuscode für die Response mit dem Parameter `status_code` in jeder der *Pfadoperationen* deklarieren: + +* `@app.get()` +* `@app.post()` +* `@app.put()` +* `@app.delete()` +* usw. + +{* ../../docs_src/response_status_code/tutorial001_py310.py hl[6] *} + +/// note | Hinweis + +Beachten Sie, dass `status_code` ein Parameter der „Dekorator“-Methode ist (`get`, `post`, usw.). Nicht der *Pfadoperation-Funktion*, wie alle anderen Parameter und der Body. + +/// + +Dem `status_code`-Parameter wird eine Zahl mit dem HTTP-Statuscode übergeben. + +/// note | Hinweis + +Alternativ kann `status_code` auch ein `IntEnum` erhalten, wie etwa Pythons [`http.HTTPStatus`](https://docs.python.org/3/library/http.html#http.HTTPStatus). + +/// + +Dies wird: + +* Diesen Statuscode mit der Response zurücksenden. +* Diesen im OpenAPI-Schema dokumentieren (und somit in den Benutzeroberflächen): + + + +/// note | Hinweis + +Einige Responsecodes (siehe nächsten Abschnitt) kennzeichnen, dass die Response keinen Body hat. + +FastAPI erkennt dies und erstellt eine OpenAPI-Dokumentation, die zeigt, dass es keinen Responsebody gibt. + +/// + +## Über HTTP-Statuscodes { #about-http-status-codes } + +/// note | Hinweis + +Wenn Sie bereits wissen, was HTTP-Statuscodes sind, können Sie diesen Abschnitt überspringen und mit dem nächsten fortfahren. + +/// + +In HTTP senden Sie einen numerischen Statuscode mit 3 Ziffern als Teil der Response. + +Diese Statuscodes haben einen zugeordneten Namen, um sie leichter zu erkennen, aber der wichtige Teil ist die Zahl. + +Kurz gefasst: + +* `100 - 199` stehen für „Information“. Sie verwenden diese selten direkt. Responses mit diesen Statuscodes dürfen keinen Body haben. +* **`200 - 299`** stehen für „Successful“-Responses („Erfolgreich“). Diese werden Sie am häufigsten verwenden. + * `200` ist der Default-Statuscode, was bedeutet, alles ist „OK“. + * Ein weiteres Beispiel wäre `201`, „Created“ („Erzeugt“). Dieser wird üblicherweise verwendet, nachdem ein neuer Datensatz in der Datenbank erstellt wurde. + * Ein spezieller Fall ist `204`, „No Content“ („Kein Inhalt“). Diese Response wird verwendet, wenn es keinen Inhalt gibt, der an den Client zurückgeschickt werden soll, und diese Response darf daher keinen Body haben. +* **`300 - 399`** stehen für „Redirection“ („Umleitung“). Responses mit diesen Statuscodes können einen Body haben oder nicht, außer bei `304`, „Not Modified“ („Nicht verändert“), die keinen haben darf. +* **`400 - 499`** stehen für „Client error“-Responses („Client-Fehler“). Diese sind die zweithäufigsten, die Sie vermutlich verwenden werden. + * Ein Beispiel ist `404`, für eine „Not Found“-Response („Nicht gefunden“). + * Für allgemeine Fehler beim Client können Sie einfach `400` verwenden. +* `500 - 599` stehen für Server-Fehler. Diese verwenden Sie fast nie direkt. Wenn in Ihrem Anwendungscode oder Server etwas schiefgeht, wird automatisch einer dieser Fehler-Statuscodes zurückgegeben. + +/// tip | Tipp + +Um mehr über die einzelnen Statuscodes zu erfahren und welcher wofür verwendet wird, sehen Sie sich die [MDN Dokumentation über HTTP-Statuscodes](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status) an. + +/// + +## Abkürzung zur Erinnerung an die Namen { #shortcut-to-remember-the-names } + +Lassen Sie uns das vorherige Beispiel noch einmal anschauen: + +{* ../../docs_src/response_status_code/tutorial001_py310.py hl[6] *} + +`201` ist der Statuscode für „Created“ („Erzeugt“). + +Aber Sie müssen sich nicht merken, was jeder dieser Codes bedeutet. + +Sie können die Annehmlichkeit von Variablen aus `fastapi.status` nutzen. + +{* ../../docs_src/response_status_code/tutorial002_py310.py hl[1,6] *} + +Diese sind nur eine Annehmlichkeit, sie enthalten dieselbe Zahl, aber so können Sie die Autovervollständigung Ihres Editors verwenden, um sie zu finden: + + + +/// note | Technische Details + +Sie könnten auch `from starlette import status` verwenden. + +**FastAPI** bietet dieselben `starlette.status`-Codes auch via `fastapi.status` an, rein zu Ihrer Annehmlichkeit als Entwickler. Aber sie stammen direkt von Starlette. + +/// + +## Den Defaultwert ändern { #changing-the-default } + +Später im [Handbuch für fortgeschrittene Benutzer](../advanced/response-change-status-code.md) werden Sie sehen, wie Sie einen anderen Statuscode zurückgeben können, als den Default, den Sie hier deklarieren. diff --git a/docs/de/docs/tutorial/schema-extra-example.md b/docs/de/docs/tutorial/schema-extra-example.md new file mode 100644 index 0000000000000..9bf0eafecdc37 --- /dev/null +++ b/docs/de/docs/tutorial/schema-extra-example.md @@ -0,0 +1,202 @@ +# Beispiel-Request-Daten deklarieren { #declare-request-example-data } + +Sie können Beispiele für die Daten deklarieren, die Ihre App empfangen kann. + +Hier sind mehrere Möglichkeiten, das zu tun. + +## Zusätzliche JSON-Schemadaten in Pydantic-Modellen { #extra-json-schema-data-in-pydantic-models } + +Sie können `examples` („Beispiele“) für ein Pydantic-Modell deklarieren, welche dem generierten JSON-Schema hinzugefügt werden. + +{* ../../docs_src/schema_extra_example/tutorial001_py310.py hl[13:24] *} + +Diese zusätzlichen Informationen werden unverändert zum für dieses Modell ausgegebenen **JSON-Schema** hinzugefügt und in der API-Dokumentation verwendet. + +Sie können das Attribut `model_config` verwenden, das ein `dict` akzeptiert, wie beschrieben in [Pydantic-Dokumentation: Configuration](https://docs.pydantic.dev/latest/api/config/). + +Sie können `"json_schema_extra"` setzen, mit einem `dict`, das alle zusätzlichen Daten enthält, die im generierten JSON-Schema angezeigt werden sollen, einschließlich `examples`. + +/// tip | Tipp + +Mit derselben Technik können Sie das JSON-Schema erweitern und Ihre eigenen benutzerdefinierten Zusatzinformationen hinzufügen. + +Sie könnten das beispielsweise verwenden, um Metadaten für eine Frontend-Benutzeroberfläche usw. hinzuzufügen. + +/// + +/// note | Hinweis + +OpenAPI 3.1.0 (verwendet seit FastAPI 0.99.0) hat Unterstützung für `examples` hinzugefügt, was Teil des **JSON Schema** Standards ist. + +Zuvor unterstützte es nur das Schlüsselwort `example` mit einem einzigen Beispiel. Dieses wird weiterhin von OpenAPI 3.1.0 unterstützt, ist jedoch deprecatet und nicht Teil des JSON Schema Standards. Wir empfehlen Ihnen daher, von `example` nach `examples` zu migrieren. 🤓 + +Mehr erfahren Sie am Ende dieser Seite. + +/// + +## Zusätzliche Argumente für `Field` { #field-additional-arguments } + +Wenn Sie `Field()` mit Pydantic-Modellen verwenden, können Sie ebenfalls zusätzliche `examples` deklarieren: + +{* ../../docs_src/schema_extra_example/tutorial002_py310.py hl[2,8:11] *} + +## `examples` im JSON-Schema – OpenAPI { #examples-in-json-schema-openapi } + +Bei Verwendung von: + +* `Path()` +* `Query()` +* `Header()` +* `Cookie()` +* `Body()` +* `Form()` +* `File()` + +können Sie auch eine Gruppe von `examples` mit zusätzlichen Informationen deklarieren, die zu ihren **JSON-Schemas** innerhalb von **OpenAPI** hinzugefügt werden. + +### `Body` mit `examples` { #body-with-examples } + +Hier übergeben wir `examples`, welches ein einzelnes Beispiel für die in `Body()` erwarteten Daten enthält: + +{* ../../docs_src/schema_extra_example/tutorial003_an_py310.py hl[22:29] *} + +### Beispiel in der Dokumentations-Benutzeroberfläche { #example-in-the-docs-ui } + +Mit jeder der oben genannten Methoden würde es in `/docs` so aussehen: + + + +### `Body` mit mehreren `examples` { #body-with-multiple-examples } + +Sie können natürlich auch mehrere `examples` übergeben: + +{* ../../docs_src/schema_extra_example/tutorial004_an_py310.py hl[23:38] *} + +Wenn Sie das tun, werden die Beispiele Teil des internen **JSON-Schemas** für diese Body-Daten. + +Nichtsdestotrotz unterstützt Swagger UI, das für die Anzeige der Dokumentations-Benutzeroberfläche zuständige Tool, zum Zeitpunkt der Erstellung nicht die Anzeige mehrerer Beispiele für die Daten in **JSON Schema**. Aber lesen Sie unten für einen Workaround weiter. + +### OpenAPI-spezifische `examples` { #openapi-specific-examples } + +Schon bevor **JSON Schema** `examples` unterstützte, unterstützte OpenAPI ein anderes Feld, das auch `examples` genannt wurde. + +Diese **OpenAPI-spezifischen** `examples` finden sich in einem anderen Abschnitt der OpenAPI-Spezifikation. Sie sind **Details für jede *Pfadoperation***, nicht für jedes JSON-Schema. + +Und Swagger UI unterstützt dieses spezielle Feld `examples` schon seit einiger Zeit. Sie können es also verwenden, um verschiedene **Beispiele in der Benutzeroberfläche der Dokumentation anzuzeigen**. + +Das Format dieses OpenAPI-spezifischen Felds `examples` ist ein `dict` mit **mehreren Beispielen** (anstelle einer `list`), jedes mit zusätzlichen Informationen, die auch zu **OpenAPI** hinzugefügt werden. + +Dies erfolgt nicht innerhalb jedes in OpenAPI enthaltenen JSON-Schemas, sondern außerhalb, in der *Pfadoperation*. + +### Den Parameter `openapi_examples` verwenden { #using-the-openapi-examples-parameter } + +Sie können die OpenAPI-spezifischen `examples` in FastAPI mit dem Parameter `openapi_examples` deklarieren, für: + +* `Path()` +* `Query()` +* `Header()` +* `Cookie()` +* `Body()` +* `Form()` +* `File()` + +Die Schlüssel des `dict` identifizieren jedes Beispiel, und jeder Wert ist ein weiteres `dict`. + +Jedes spezifische Beispiel-`dict` in den `examples` kann Folgendes enthalten: + +* `summary`: Kurze Beschreibung für das Beispiel. +* `description`: Eine lange Beschreibung, die Markdown-Text enthalten kann. +* `value`: Dies ist das tatsächlich angezeigte Beispiel, z. B. ein `dict`. +* `externalValue`: Alternative zu `value`, eine URL, die auf das Beispiel verweist. Allerdings wird dies möglicherweise nicht von so vielen Tools unterstützt wie `value`. + +Sie können es so verwenden: + +{* ../../docs_src/schema_extra_example/tutorial005_an_py310.py hl[23:49] *} + +### OpenAPI-Beispiele in der Dokumentations-Benutzeroberfläche { #openapi-examples-in-the-docs-ui } + +Wenn `openapi_examples` zu `Body()` hinzugefügt wird, würde `/docs` so aussehen: + + + +## Technische Details { #technical-details } + +/// tip | Tipp + +Wenn Sie bereits **FastAPI** Version **0.99.0 oder höher** verwenden, können Sie diese Details wahrscheinlich **überspringen**. + +Sie sind für ältere Versionen relevanter, bevor OpenAPI 3.1.0 verfügbar war. + +Sie können dies als eine kurze **Geschichtsstunde** zu OpenAPI und JSON Schema betrachten. 🤓 + +/// + +/// warning | Achtung + +Dies sind sehr technische Details zu den Standards **JSON Schema** und **OpenAPI**. + +Wenn die oben genannten Ideen bereits für Sie funktionieren, reicht das möglicherweise aus und Sie benötigen diese Details wahrscheinlich nicht, überspringen Sie sie gerne. + +/// + +Vor OpenAPI 3.1.0 verwendete OpenAPI eine ältere und modifizierte Version von **JSON Schema**. + +JSON Schema hatte keine `examples`, daher fügte OpenAPI seiner eigenen modifizierten Version ein eigenes `example`-Feld hinzu. + +OpenAPI fügte auch die Felder `example` und `examples` zu anderen Teilen der Spezifikation hinzu: + +* [`Parameter Object` (in der Spezifikation)](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#parameter-object), das verwendet wurde von FastAPIs: + * `Path()` + * `Query()` + * `Header()` + * `Cookie()` +* [`Request Body Object` im Feld `content` des `Media Type Object`s (in der Spezifikation)](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#media-type-object), das verwendet wurde von FastAPIs: + * `Body()` + * `File()` + * `Form()` + +/// note | Hinweis + +Dieser alte, OpenAPI-spezifische `examples`-Parameter heißt seit FastAPI `0.103.0` jetzt `openapi_examples`. + +/// + +### JSON Schemas Feld `examples` { #json-schemas-examples-field } + +Aber dann fügte JSON Schema ein [`examples`](https://json-schema.org/draft/2019-09/json-schema-validation.html#rfc.section.9.5)-Feld zu einer neuen Version der Spezifikation hinzu. + +Und dann basierte das neue OpenAPI 3.1.0 auf der neuesten Version (JSON Schema 2020-12), die dieses neue Feld `examples` enthielt. + +Und jetzt hat dieses neue `examples`-Feld Vorrang vor dem alten (und benutzerdefinierten) `example`-Feld, im Singular, das jetzt deprecatet ist. + +Dieses neue `examples`-Feld in JSON Schema ist **nur eine `list`** von Beispielen, kein Dict mit zusätzlichen Metadaten wie an den anderen Stellen in OpenAPI (oben beschrieben). + +/// note | Hinweis + +Selbst, nachdem OpenAPI 3.1.0 veröffentlicht wurde, mit dieser neuen, einfacheren Integration mit JSON Schema, unterstützte Swagger UI, das Tool, das die automatische Dokumentation bereitstellt, eine Zeit lang OpenAPI 3.1.0 nicht (das tut es seit Version 5.0.0 🎉). + +Aus diesem Grund verwendeten Versionen von FastAPI vor 0.99.0 immer noch Versionen von OpenAPI vor 3.1.0. + +/// + +### Pydantic- und FastAPI-`examples` { #pydantic-and-fastapi-examples } + +Wenn Sie `examples` innerhalb eines Pydantic-Modells hinzufügen, indem Sie `schema_extra` oder `Field(examples=["something"])` verwenden, wird dieses Beispiel dem **JSON-Schema** für dieses Pydantic-Modell hinzugefügt. + +Und dieses **JSON-Schema** des Pydantic-Modells ist in der **OpenAPI** Ihrer API enthalten und wird dann in der Benutzeroberfläche der Dokumentation verwendet. + +In Versionen von FastAPI vor 0.99.0 (0.99.0 und höher verwenden das neuere OpenAPI 3.1.0), wenn Sie `example` oder `examples` mit einem der anderen Werkzeuge (`Query()`, `Body()`, usw.) verwendet haben, wurden diese Beispiele nicht zum JSON-Schema hinzugefügt, das diese Daten beschreibt (nicht einmal zur OpenAPI-eigenen Version von JSON Schema), sondern direkt zur *Pfadoperation*-Deklaration in OpenAPI (außerhalb der Teile von OpenAPI, die JSON Schema verwenden). + +Aber jetzt, da FastAPI 0.99.0 und höher, OpenAPI 3.1.0 verwendet, das JSON Schema 2020-12 verwendet, und Swagger UI 5.0.0 und höher, ist alles konsistenter und die Beispiele sind in JSON Schema enthalten. + +### Swagger UI und OpenAPI-spezifische `examples` { #swagger-ui-and-openapi-specific-examples } + +Da Swagger UI derzeit nicht mehrere JSON Schema Beispiele unterstützt (Stand: 26.08.2023), hatten Benutzer keine Möglichkeit, mehrere Beispiele in der Dokumentation anzuzeigen. + +Um dieses Problem zu lösen, hat FastAPI `0.103.0` **Unterstützung** für die Deklaration desselben alten **OpenAPI-spezifischen** `examples`-Felds mit dem neuen Parameter `openapi_examples` hinzugefügt. 🤓 + +### Zusammenfassung { #summary } + +Ich habe immer gesagt, dass ich Geschichte nicht so sehr mag ... und jetzt schauen Sie mich an, wie ich „Technikgeschichte“-Unterricht gebe. 😅 + +Kurz gesagt: **Aktualisieren Sie auf FastAPI 0.99.0 oder höher**, und die Dinge sind viel **einfacher, konsistenter und intuitiver**, und Sie müssen nicht alle diese historischen Details kennen. 😎 diff --git a/docs/de/docs/tutorial/security/first-steps.md b/docs/de/docs/tutorial/security/first-steps.md new file mode 100644 index 0000000000000..69e8abec0b6c9 --- /dev/null +++ b/docs/de/docs/tutorial/security/first-steps.md @@ -0,0 +1,206 @@ +# Sicherheit – Erste Schritte { #security-first-steps } + + +Stellen wir uns vor, dass Sie Ihre **Backend**-API auf einer Domain haben. + +Und Sie haben ein **Frontend** auf einer anderen Domain oder in einem anderen Pfad derselben Domain (oder in einer Mobile-Anwendung). + +Und Sie möchten eine Möglichkeit haben, dass sich das Frontend mithilfe eines **Benutzernamens** und eines **Passworts** beim Backend authentisieren kann. + +Wir können **OAuth2** verwenden, um das mit **FastAPI** zu erstellen. + +Aber ersparen wir Ihnen die Zeit, die gesamte lange Spezifikation zu lesen, nur um die kleinen Informationen zu finden, die Sie benötigen. + +Lassen Sie uns die von **FastAPI** bereitgestellten Tools verwenden, um Sicherheit zu gewährleisten. + +## Wie es aussieht { #how-it-looks } + +Lassen Sie uns zunächst einfach den Code verwenden und sehen, wie er funktioniert, und dann kommen wir zurück, um zu verstehen, was passiert. + +## `main.py` erstellen { #create-main-py } + +Kopieren Sie das Beispiel in eine Datei `main.py`: + +{* ../../docs_src/security/tutorial001_an_py310.py *} + +## Ausführen { #run-it } + +/// note | Hinweis + +Das Paket [`python-multipart`](https://github.com/Kludex/python-multipart) wird automatisch mit **FastAPI** installiert, wenn Sie den Befehl `pip install "fastapi[standard]"` ausführen. + +Wenn Sie jedoch den Befehl `pip install fastapi` verwenden, ist das Paket `python-multipart` nicht standardmäßig enthalten. + +Um es manuell zu installieren, stellen Sie sicher, dass Sie eine [virtuelle Umgebung](../../virtual-environments.md) erstellen, sie aktivieren und es dann mit: + +```console +$ pip install python-multipart +``` + +installieren. + +Das liegt daran, dass **OAuth2** „Formulardaten“ zum Senden von `username` und `password` verwendet. + +/// + +Führen Sie das Beispiel aus mit: + +
+ +```console +$ fastapi dev + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +## Es testen { #check-it } + +Gehen Sie zu der interaktiven Dokumentation unter: [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs). + +Sie werden etwa Folgendes sehen: + + + +/// tip | Authorize-Button! + +Sie haben bereits einen glänzenden, neuen „Authorize“-Button. + +Und Ihre *Pfadoperation* hat in der oberen rechten Ecke ein kleines Schloss, auf das Sie klicken können. + +/// + +Und wenn Sie darauf klicken, erhalten Sie ein kleines Anmeldeformular zur Eingabe eines `username` und `password` (und anderer optionaler Felder): + + + +/// note | Hinweis + +Es spielt keine Rolle, was Sie in das Formular eingeben, es wird noch nicht funktionieren. Wir kommen dahin. + +/// + +Dies ist natürlich nicht das Frontend für die Endbenutzer, aber es ist ein großartiges automatisches Tool, um Ihre gesamte API interaktiv zu dokumentieren. + +Es kann vom Frontend-Team verwendet werden (das auch Sie selbst sein können). + +Es kann von Anwendungen und Systemen Dritter verwendet werden. + +Und es kann auch von Ihnen selbst verwendet werden, um dieselbe Anwendung zu debuggen, zu prüfen und zu testen. + +## Der `password`-Flow { #the-password-flow } + +Lassen Sie uns nun etwas zurückgehen und verstehen, was das alles ist. + +Der `password`-„Flow“ ist eine der in OAuth2 definierten Wege („Flows“) zur Handhabung von Sicherheit und Authentifizierung. + +OAuth2 wurde so konzipiert, dass das Backend oder die API unabhängig vom Server sein kann, der den Benutzer authentifiziert. + +In diesem Fall handhabt jedoch dieselbe **FastAPI**-Anwendung sowohl die API als auch die Authentifizierung. + +Betrachten wir es also aus dieser vereinfachten Sicht: + +* Der Benutzer gibt den `username` und das `password` im Frontend ein und drückt `Enter`. +* Das Frontend (das im Browser des Benutzers läuft) sendet diesen `username` und das `password` an eine bestimmte URL in unserer API (deklariert mit `tokenUrl="token"`). +* Die API überprüft den `username` und das `password` und antwortet mit einem „Token“ (wir haben davon noch nichts implementiert). + * Ein „Token“ ist lediglich ein String mit einem Inhalt, den wir später verwenden können, um diesen Benutzer zu verifizieren. + * Normalerweise läuft ein Token nach einiger Zeit ab. + * Daher muss sich der Benutzer irgendwann später erneut anmelden. + * Und wenn der Token gestohlen wird, ist das Risiko geringer. Es handelt sich nicht um einen dauerhaften Schlüssel, der (in den meisten Fällen) für immer funktioniert. +* Das Frontend speichert diesen Token vorübergehend irgendwo. +* Der Benutzer klickt im Frontend, um zu einem anderen Abschnitt der Frontend-Web-Anwendung zu gelangen. +* Das Frontend muss weitere Daten von der API abrufen. + * Es benötigt jedoch eine Authentifizierung für diesen bestimmten Endpunkt. + * Um sich also bei unserer API zu authentifizieren, sendet es einen `Authorization`-Header mit dem Wert `Bearer ` plus dem Token. + * Wenn der Token `foobar` enthielte, wäre der Inhalt des `Authorization`-Headers: `Bearer foobar`. + +## **FastAPI**s `OAuth2PasswordBearer` { #fastapis-oauth2passwordbearer } + +**FastAPI** bietet mehrere Tools auf unterschiedlichen Abstraktionsebenen zur Implementierung dieser Sicherheitsfunktionen. + +In diesem Beispiel verwenden wir **OAuth2** mit dem **Password**-Flow und einem **Bearer**-Token. Wir machen das mit der Klasse `OAuth2PasswordBearer`. + +/// note | Hinweis + +Ein „Bearer“-Token ist nicht die einzige Option. + +Aber es ist die beste für unseren Anwendungsfall. + +Und es ist wahrscheinlich auch für die meisten anderen Anwendungsfälle die beste, es sei denn, Sie sind ein OAuth2-Experte und wissen genau, warum es eine andere Option gibt, die Ihren Anforderungen besser entspricht. + +In dem Fall gibt Ihnen **FastAPI** ebenfalls die Tools, die Sie zum Erstellen brauchen. + +/// + +Wenn wir eine Instanz der Klasse `OAuth2PasswordBearer` erstellen, übergeben wir den Parameter `tokenUrl`. Dieser Parameter enthält die URL, die der Client (das Frontend, das im Browser des Benutzers ausgeführt wird) verwendet, wenn er den `username` und das `password` sendet, um einen Token zu erhalten. + +{* ../../docs_src/security/tutorial001_an_py310.py hl[8] *} + +/// tip | Tipp + +Hier bezieht sich `tokenUrl="token"` auf eine relative URL `token`, die wir noch nicht erstellt haben. Da es sich um eine relative URL handelt, entspricht sie `./token`. + +Da wir eine relative URL verwenden, würde sich das, wenn sich Ihre API unter `https://example.com/` befindet, auf `https://example.com/token` beziehen. Wenn sich Ihre API jedoch unter `https://example.com/api/v1/` befände, würde es sich auf `https://example.com/api/v1/token` beziehen. + +Die Verwendung einer relativen URL ist wichtig, um sicherzustellen, dass Ihre Anwendung auch in einem fortgeschrittenen Anwendungsfall, wie [Hinter einem Proxy](../../advanced/behind-a-proxy.md), weiterhin funktioniert. + +/// + +Dieser Parameter erstellt nicht diesen Endpunkt / diese *Pfadoperation*, sondern deklariert, dass die URL `/token` diejenige sein wird, die der Client verwenden soll, um den Token abzurufen. Diese Information wird in OpenAPI und dann in den interaktiven API-Dokumentationssystemen verwendet. + +Wir werden demnächst auch die eigentliche Pfadoperation erstellen. + +/// note | Hinweis + +Wenn Sie ein sehr strenger „Pythonista“ sind, missfällt Ihnen möglicherweise die Schreibweise des Parameternamens `tokenUrl` anstelle von `token_url`. + +Das liegt daran, dass FastAPI denselben Namen wie in der OpenAPI-Spezifikation verwendet. Sodass Sie, wenn Sie mehr über eines dieser Sicherheitsschemas herausfinden möchten, den Namen einfach kopieren und einfügen können, um weitere Informationen darüber zu erhalten. + +/// + +Die Variable `oauth2_scheme` ist eine Instanz von `OAuth2PasswordBearer`, aber auch ein „Callable“. + +Es könnte wie folgt aufgerufen werden: + +```Python +oauth2_scheme(some, parameters) +``` + +Es kann also mit `Depends` verwendet werden. + +### Verwenden { #use-it } + +Jetzt können Sie dieses `oauth2_scheme` als Abhängigkeit `Depends` übergeben. + +{* ../../docs_src/security/tutorial001_an_py310.py hl[12] *} + +Diese Abhängigkeit stellt einen `str` bereit, der dem Parameter `token` der *Pfadoperation-Funktion* zugewiesen wird. + +**FastAPI** weiß, dass es diese Abhängigkeit verwenden kann, um ein „Sicherheitsschema“ im OpenAPI-Schema (und der automatischen API-Dokumentation) zu definieren. + +/// note | Technische Details + +**FastAPI** weiß, dass es die Klasse `OAuth2PasswordBearer` (deklariert in einer Abhängigkeit) verwenden kann, um das Sicherheitsschema in OpenAPI zu definieren, da es von `fastapi.security.oauth2.OAuth2` erbt, das wiederum von `fastapi.security.base.SecurityBase` erbt. + +Alle Sicherheits-Werkzeuge, die in OpenAPI integriert sind (und die automatische API-Dokumentation), erben von `SecurityBase`, so weiß **FastAPI**, wie es sie in OpenAPI integrieren muss. + +/// + +## Was es macht { #what-it-does } + +FastAPI wird im Request nach diesem `Authorization`-Header suchen, prüfen, ob der Wert `Bearer ` plus ein Token ist, und den Token als `str` zurückgeben. + +Wenn es keinen `Authorization`-Header sieht, oder der Wert keinen `Bearer `-Token hat, antwortet es direkt mit einem 401-Statuscode-Error (`UNAUTHORIZED`). + +Sie müssen nicht einmal prüfen, ob der Token existiert, um einen Fehler zurückzugeben. Seien Sie sicher, dass Ihre Funktion, wenn sie ausgeführt wird, ein `str` in diesem Token enthält. + +Sie können das bereits in der interaktiven Dokumentation ausprobieren: + + + +Wir überprüfen im Moment noch nicht die Gültigkeit des Tokens, aber das ist bereits ein Anfang. + +## Zusammenfassung { #recap } + +Mit nur drei oder vier zusätzlichen Zeilen haben Sie so bereits eine primitive Form der Sicherheit. diff --git a/docs/de/docs/tutorial/security/get-current-user.md b/docs/de/docs/tutorial/security/get-current-user.md new file mode 100644 index 0000000000000..1bcccfd82578c --- /dev/null +++ b/docs/de/docs/tutorial/security/get-current-user.md @@ -0,0 +1,105 @@ +# Aktuellen Benutzer abrufen { #get-current-user } + +Im vorherigen Kapitel hat das Sicherheitssystem (das auf dem Dependency Injection System basiert) der *Pfadoperation-Funktion* einen `token` vom Typ `str` überreicht: + +{* ../../docs_src/security/tutorial001_an_py310.py hl[12] *} + +Aber das ist immer noch nicht so nützlich. + +Lassen wir es uns den aktuellen Benutzer überreichen. + +## Ein Benutzermodell erstellen { #create-a-user-model } + +Erstellen wir zunächst ein Pydantic-Benutzermodell. + +So wie wir Pydantic zum Deklarieren von Bodys verwenden, können wir es auch überall sonst verwenden: + +{* ../../docs_src/security/tutorial002_an_py310.py hl[5,12:16] *} + +## Eine `get_current_user`-Abhängigkeit erstellen { #create-a-get-current-user-dependency } + +Erstellen wir eine Abhängigkeit `get_current_user`. + +Erinnern Sie sich, dass Abhängigkeiten Unterabhängigkeiten haben können? + +`get_current_user` wird seinerseits von `oauth2_scheme` abhängen, das wir zuvor erstellt haben. + +So wie wir es zuvor in der *Pfadoperation* direkt gemacht haben, erhält unsere neue Abhängigkeit `get_current_user` von der Unterabhängigkeit `oauth2_scheme` einen `token` vom Typ `str`: + +{* ../../docs_src/security/tutorial002_an_py310.py hl[25] *} + +## Den Benutzer abrufen { #get-the-user } + +`get_current_user` wird eine von uns erstellte (gefakte) Hilfsfunktion verwenden, welche einen Token vom Typ `str` entgegennimmt und unser Pydantic-`User`-Modell zurückgibt: + +{* ../../docs_src/security/tutorial002_an_py310.py hl[19:22,26:27] *} + +## Den aktuellen Benutzer einfügen { #inject-the-current-user } + +Und jetzt können wir wiederum `Depends` mit unserem `get_current_user` in der *Pfadoperation* verwenden: + +{* ../../docs_src/security/tutorial002_an_py310.py hl[31] *} + +Beachten Sie, dass wir als Typ von `current_user` das Pydantic-Modell `User` deklarieren. + +Das wird uns innerhalb der Funktion bei Codevervollständigung und Typprüfungen helfen. + +/// tip | Tipp + +Sie erinnern sich vielleicht, dass Requestbodys ebenfalls mit Pydantic-Modellen deklariert werden. + +Weil Sie `Depends` verwenden, wird **FastAPI** hier aber nicht verwirrt. + +/// + +/// tip | Tipp + +Die Art und Weise, wie dieses System von Abhängigkeiten konzipiert ist, ermöglicht es uns, verschiedene Abhängigkeiten (verschiedene „Dependables“) zu haben, die alle ein `User`-Modell zurückgeben. + +Wir sind nicht darauf beschränkt, nur eine Abhängigkeit zu haben, die diesen Typ von Daten zurückgeben kann. + +/// + +## Andere Modelle { #other-models } + +Sie können jetzt den aktuellen Benutzer direkt in den *Pfadoperation-Funktionen* abrufen und die Sicherheitsmechanismen auf **Dependency Injection** Ebene handhaben, mittels `Depends`. + +Und Sie können alle Modelle und Daten für die Sicherheitsanforderungen verwenden (in diesem Fall ein Pydantic-Modell `User`). + +Sie sind jedoch nicht auf die Verwendung von bestimmten Datenmodellen, Klassen, oder Typen beschränkt. + +Möchten Sie eine `id` und eine `email` und keinen `username` in Ihrem Modell haben? Kein Problem. Sie können dieselben Tools verwenden. + +Möchten Sie nur ein `str` haben? Oder nur ein `dict`? Oder direkt eine Instanz eines Modells einer Datenbank-Klasse? Es funktioniert alles auf die gleiche Weise. + +Sie haben eigentlich keine Benutzer, die sich bei Ihrer Anwendung anmelden, sondern Roboter, Bots oder andere Systeme, die nur über einen Zugriffstoken verfügen? Auch hier funktioniert alles gleich. + +Verwenden Sie einfach jede Art von Modell, jede Art von Klasse, jede Art von Datenbank, die Sie für Ihre Anwendung benötigen. **FastAPI** deckt das alles mit seinem Dependency Injection System ab. + +## Codegröße { #code-size } + +Dieses Beispiel mag ausführlich erscheinen. Bedenken Sie, dass wir Sicherheit, Datenmodelle, Hilfsfunktionen und *Pfadoperationen* in derselben Datei vermischen. + +Aber hier ist der entscheidende Punkt. + +Der Code für Sicherheit und Dependency Injection wird einmal geschrieben. + +Sie können es so komplex gestalten, wie Sie möchten. Und dennoch haben Sie es nur einmal geschrieben, an einer einzigen Stelle. Mit all der Flexibilität. + +Aber Sie können Tausende von Endpunkten (*Pfadoperationen*) haben, die dasselbe Sicherheitssystem verwenden. + +Und alle (oder beliebige Teile davon) können Vorteil ziehen aus der Wiederverwendung dieser und anderer von Ihnen erstellter Abhängigkeiten. + +Und alle diese Tausenden von *Pfadoperationen* können nur drei Zeilen lang sein: + +{* ../../docs_src/security/tutorial002_an_py310.py hl[30:32] *} + +## Zusammenfassung { #recap } + +Sie können jetzt den aktuellen Benutzer direkt in Ihrer *Pfadoperation-Funktion* abrufen. + +Wir haben bereits die Hälfte geschafft. + +Wir müssen jetzt nur noch eine *Pfadoperation* hinzufügen, mittels der der Benutzer/Client tatsächlich seinen `username` und `password` senden kann. + +Das kommt als nächstes. diff --git a/docs/de/docs/tutorial/security/index.md b/docs/de/docs/tutorial/security/index.md new file mode 100644 index 0000000000000..6330d3d9dc601 --- /dev/null +++ b/docs/de/docs/tutorial/security/index.md @@ -0,0 +1,106 @@ +# Sicherheit { #security } + +Es gibt viele Wege, Sicherheit, Authentifizierung und Autorisierung zu handhaben. + +Und normalerweise ist es ein komplexes und „schwieriges“ Thema. + +In vielen Frameworks und Systemen erfordert allein die Handhabung von Sicherheit und Authentifizierung viel Aufwand und Code (in vielen Fällen kann er 50 % oder mehr des gesamten geschriebenen Codes ausmachen). + +**FastAPI** bietet mehrere Tools, die Ihnen helfen, schnell und auf standardisierte Weise mit **Sicherheit** umzugehen, ohne alle Sicherheits-Spezifikationen studieren und erlernen zu müssen. + +Aber schauen wir uns zunächst ein paar kleine Konzepte an. + +## In Eile? { #in-a-hurry } + +Wenn Ihnen diese Begriffe egal sind und Sie einfach *jetzt* Sicherheit mit Authentifizierung basierend auf Benutzername und Passwort hinzufügen müssen, fahren Sie mit den nächsten Kapiteln fort. + +## OAuth2 { #oauth2 } + +OAuth2 ist eine Spezifikation, die verschiedene Möglichkeiten zur Handhabung von Authentifizierung und Autorisierung definiert. + +Es handelt sich um eine recht umfangreiche Spezifikation, und sie deckt mehrere komplexe Anwendungsfälle ab. + +Sie umfasst Möglichkeiten zur Authentifizierung mithilfe eines „Dritten“. + +Das ist es, was alle diese „Login mit Facebook, Google, X (Twitter), GitHub“-Systeme unter der Haube verwenden. + +### OAuth 1 { #oauth-1 } + +Es gab ein OAuth 1, das sich stark von OAuth2 unterscheidet und komplexer ist, da es direkte Spezifikationen enthält, wie die Kommunikation verschlüsselt wird. + +Heutzutage ist es nicht sehr populär und wird kaum verwendet. + +OAuth2 spezifiziert nicht, wie die Kommunikation verschlüsselt werden soll, sondern erwartet, dass Ihre Anwendung mit HTTPS bereitgestellt wird. + +/// tip | Tipp + +Im Abschnitt über **Deployment** erfahren Sie, wie Sie HTTPS mithilfe von Traefik und Let's Encrypt kostenlos einrichten. + +/// + +## OpenID Connect { #openid-connect } + +OpenID Connect ist eine weitere Spezifikation, die auf **OAuth2** basiert. + +Sie erweitert lediglich OAuth2, indem sie einige Dinge spezifiziert, die in OAuth2 relativ mehrdeutig sind, um zu versuchen, es interoperabler zu machen. + +Beispielsweise verwendet der Google Login OpenID Connect (welches seinerseits OAuth2 verwendet). + +Aber der Facebook Login unterstützt OpenID Connect nicht. Es hat seine eigene Variante von OAuth2. + +### OpenID (nicht „OpenID Connect“) { #openid-not-openid-connect } + +Es gab auch eine „OpenID“-Spezifikation. Sie versuchte das Gleiche zu lösen wie **OpenID Connect**, basierte aber nicht auf OAuth2. + +Es handelte sich also um ein komplett zusätzliches System. + +Heutzutage ist es nicht sehr populär und wird kaum verwendet. + +## OpenAPI { #openapi } + +OpenAPI (früher bekannt als Swagger) ist die offene Spezifikation zum Erstellen von APIs (jetzt Teil der Linux Foundation). + +**FastAPI** basiert auf **OpenAPI**. + +Das ist es, was erlaubt, mehrere automatische interaktive Dokumentations-Oberflächen, Codegenerierung, usw. zu haben. + +OpenAPI bietet die Möglichkeit, mehrere Sicherheits„systeme“ zu definieren. + +Durch deren Verwendung können Sie alle diese Standards-basierten Tools nutzen, einschließlich dieser interaktiven Dokumentationssysteme. + +OpenAPI definiert die folgenden Sicherheitsschemas: + +* `apiKey`: ein anwendungsspezifischer Schlüssel, der stammen kann von: + * Einem Query-Parameter. + * Einem Header. + * Einem Cookie. +* `http`: Standard-HTTP-Authentifizierungssysteme, einschließlich: + * `bearer`: ein Header `Authorization` mit dem Wert `Bearer ` plus einem Token. Dies wird von OAuth2 geerbt. + * HTTP Basic Authentication. + * HTTP Digest, usw. +* `oauth2`: Alle OAuth2-Methoden zum Umgang mit Sicherheit (genannt „Flows“). + * Mehrere dieser Flows eignen sich zum Aufbau eines OAuth 2.0-Authentifizierungsanbieters (wie Google, Facebook, X (Twitter), GitHub usw.): + * `implicit` + * `clientCredentials` + * `authorizationCode` + * Es gibt jedoch einen bestimmten „Flow“, der perfekt für die direkte Abwicklung der Authentifizierung in derselben Anwendung verwendet werden kann: + * `password`: Einige der nächsten Kapitel werden Beispiele dafür behandeln. +* `openIdConnect`: bietet eine Möglichkeit, zu definieren, wie OAuth2-Authentifizierungsdaten automatisch ermittelt werden können. + * Diese automatische Erkennung ist es, die in der OpenID Connect Spezifikation definiert ist. + + +/// tip | Tipp + +Auch die Integration anderer Authentifizierungs-/Autorisierungsanbieter wie Google, Facebook, X (Twitter), GitHub, usw. ist möglich und relativ einfach. + +Das komplexeste Problem besteht darin, einen Authentifizierungs-/Autorisierungsanbieter wie solche aufzubauen, aber **FastAPI** reicht Ihnen die Tools, das einfach zu erledigen, während Ihnen die schwere Arbeit abgenommen wird. + +/// + +## **FastAPI** Tools { #fastapi-utilities } + +FastAPI stellt für jedes dieser Sicherheitsschemas im Modul `fastapi.security` verschiedene Tools bereit, die die Verwendung dieser Sicherheitsmechanismen vereinfachen. + +In den nächsten Kapiteln erfahren Sie, wie Sie mit diesen von **FastAPI** bereitgestellten Tools Sicherheit zu Ihrer API hinzufügen. + +Und Sie werden auch sehen, wie dies automatisch in das interaktive Dokumentationssystem integriert wird. diff --git a/docs/de/docs/tutorial/security/oauth2-jwt.md b/docs/de/docs/tutorial/security/oauth2-jwt.md new file mode 100644 index 0000000000000..d04bd00d44f8f --- /dev/null +++ b/docs/de/docs/tutorial/security/oauth2-jwt.md @@ -0,0 +1,277 @@ +# OAuth2 mit Passwort (und Hashing), Bearer mit JWT-Tokens { #oauth2-with-password-and-hashing-bearer-with-jwt-tokens } + +Da wir nun über den gesamten Sicherheitsablauf verfügen, machen wir die Anwendung tatsächlich sicher, indem wir JWT-Tokens und sicheres Passwort-Hashing verwenden. + +Diesen Code können Sie tatsächlich in Ihrer Anwendung verwenden, die Passwort-Hashes in Ihrer Datenbank speichern, usw. + +Wir bauen auf dem vorherigen Kapitel auf und erweitern es. + +## Über JWT { #about-jwt } + +JWT bedeutet „JSON Web Tokens“. + +Es ist ein Standard, um ein JSON-Objekt in einem langen, kompakten String ohne Leerzeichen zu kodieren. Das sieht so aus: + +``` +eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c +``` + +Da er nicht verschlüsselt ist, kann jeder die Informationen aus dem Inhalt wiederherstellen. + +Aber er ist signiert. Wenn Sie also einen von Ihnen gesendeten Token zurückerhalten, können Sie überprüfen, ob Sie ihn tatsächlich gesendet haben. + +Auf diese Weise können Sie einen Token mit einer Gültigkeitsdauer von beispielsweise einer Woche erstellen. Und wenn der Benutzer am nächsten Tag mit dem Token zurückkommt, wissen Sie, dass der Benutzer immer noch bei Ihrem System angemeldet ist. + +Nach einer Woche läuft der Token ab und der Benutzer wird nicht autorisiert und muss sich erneut anmelden, um einen neuen Token zu erhalten. Und wenn der Benutzer (oder ein Dritter) versuchen würde, den Token zu ändern, um das Ablaufdatum zu ändern, würden Sie das entdecken, weil die Signaturen nicht übereinstimmen würden. + +Wenn Sie mit JWT-Tokens spielen und sehen möchten, wie sie funktionieren, schauen Sie sich [https://jwt.io](https://jwt.io/) an. + +## `PyJWT` installieren { #install-pyjwt } + +Wir müssen `PyJWT` installieren, um die JWT-Tokens in Python zu generieren und zu verifizieren. + +Stellen Sie sicher, dass Sie eine [virtuelle Umgebung](../../virtual-environments.md) erstellen, sie aktivieren und dann `pyjwt` installieren: + +
+ +```console +$ pip install pyjwt + +---> 100% +``` + +
+ +/// note | Hinweis + +Wenn Sie planen, digitale Signaturalgorithmen wie RSA oder ECDSA zu verwenden, sollten Sie die Kryptografie-Abhängigkeit `pyjwt[crypto]` installieren. + +Weitere Informationen finden Sie in der [PyJWT-Installationsdokumentation](https://pyjwt.readthedocs.io/en/latest/installation.html). + +/// + +## Passwort-Hashing { #password-hashing } + +„Hashing“ bedeutet: Konvertieren eines Inhalts (in diesem Fall eines Passworts) in eine Folge von Bytes (ein schlichter String), die wie Kauderwelsch aussieht. + +Immer wenn Sie genau den gleichen Inhalt (genau das gleiche Passwort) übergeben, erhalten Sie genau den gleichen Kauderwelsch. + +Sie können jedoch nicht vom Kauderwelsch zurück zum Passwort konvertieren. + +### Warum Passwort-Hashing verwenden { #why-use-password-hashing } + +Wenn Ihre Datenbank gestohlen wird, hat der Dieb nicht die Klartext-Passwörter Ihrer Benutzer, sondern nur die Hashes. + +Der Dieb kann also nicht versuchen, die gleichen Passwörter in einem anderen System zu verwenden (da viele Benutzer überall das gleiche Passwort verwenden, wäre dies gefährlich). + +## `pwdlib` installieren { #install-pwdlib } + +pwdlib ist ein großartiges Python-Package, um Passwort-Hashes zu handhaben. + +Es unterstützt viele sichere Hashing-Algorithmen und Werkzeuge, um mit diesen zu arbeiten. + +Der empfohlene Algorithmus ist „Argon2“. + +Stellen Sie sicher, dass Sie eine [virtuelle Umgebung](../../virtual-environments.md) erstellen, sie aktivieren, und installieren Sie dann pwdlib mit Argon2: + +
+ +```console +$ pip install "pwdlib[argon2]" + +---> 100% +``` + +
+ +/// tip | Tipp + +Mit `pwdlib` können Sie sogar konfigurieren, Passwörter zu lesen, die von **Django**, einem **Flask**-Sicherheits-Plugin, oder vielen anderen erstellt wurden. + +So könnten Sie beispielsweise die gleichen Daten aus einer Django-Anwendung in einer Datenbank mit einer FastAPI-Anwendung teilen. Oder schrittweise eine Django-Anwendung migrieren, während Sie dieselbe Datenbank verwenden. + +Und Ihre Benutzer könnten sich gleichzeitig über Ihre Django-Anwendung oder Ihre **FastAPI**-Anwendung anmelden. + +/// + +## Die Passwörter hashen und überprüfen { #hash-and-verify-the-passwords } + +Importieren Sie die benötigten Tools aus `pwdlib`. + +Erstellen Sie eine PasswordHash-Instanz mit empfohlenen Einstellungen – sie wird für das Hashen und Verifizieren von Passwörtern verwendet. + +/// tip | Tipp + +pwdlib unterstützt auch den bcrypt-Hashing-Algorithmus, enthält jedoch keine Legacy-Algorithmen – für die Arbeit mit veralteten Hashes wird die Verwendung der Bibliothek passlib empfohlen. + +Sie könnten sie beispielsweise verwenden, um von einem anderen System (wie Django) generierte Passwörter zu lesen und zu verifizieren, aber alle neuen Passwörter mit einem anderen Algorithmus wie Argon2 oder Bcrypt zu hashen. + +Und mit allen gleichzeitig kompatibel sein. + +/// + +Erstellen Sie eine Hilfsfunktion, um ein vom Benutzer stammendes Passwort zu hashen. + +Und eine weitere, um zu überprüfen, ob ein empfangenes Passwort mit dem gespeicherten Hash übereinstimmt. + +Und noch eine, um einen Benutzer zu authentifizieren und zurückzugeben. + +{* ../../docs_src/security/tutorial004_an_py310.py hl[8,49,51,58:59,62:63,72:79] *} + +Wenn `authenticate_user` mit einem Benutzernamen aufgerufen wird, der in der Datenbank nicht existiert, führen wir dennoch `verify_password` gegen einen Dummy-Hash aus. + +So stellt man sicher, dass der Endpunkt ungefähr gleich viel Zeit für die Antwort benötigt, unabhängig davon, ob der Benutzername gültig ist oder nicht. Dadurch werden **Timing-Angriffe** verhindert, mit denen vorhandene Benutzernamen ermittelt werden könnten. + +/// note | Hinweis + +Wenn Sie sich die neue (gefakte) Datenbank `fake_users_db` anschauen, sehen Sie, wie das gehashte Passwort jetzt aussieht: `"$argon2id$v=19$m=65536,t=3,p=4$wagCPXjifgvUFBzq4hqe3w$CYaIb8sB+wtD+Vu/P4uod1+Qof8h+1g7bbDlBID48Rc"`. + +/// + +## JWT-Token verarbeiten { #handle-jwt-tokens } + +Importieren Sie die installierten Module. + +Erstellen Sie einen zufälligen geheimen Schlüssel, der zum Signieren der JWT-Tokens verwendet wird. + +Um einen sicheren zufälligen geheimen Schlüssel zu generieren, verwenden Sie den folgenden Befehl: + +
+ +```console +$ openssl rand -hex 32 + +09d25e094faa6ca2556c818166b7a9563b93f7099f6f0f4caa6cf63b88e8d3e7 +``` + +
+ +Und kopieren Sie die Ausgabe in die Variable `SECRET_KEY` (verwenden Sie nicht die im Beispiel). + +Erstellen Sie eine Variable `ALGORITHM` für den Algorithmus, der zum Signieren des JWT-Tokens verwendet wird, und setzen Sie sie auf `"HS256"`. + +Erstellen Sie eine Variable für das Ablaufdatum des Tokens. + +Definieren Sie ein Pydantic-Modell, das im Token-Endpunkt für die Response verwendet wird. + +Erstellen Sie eine Hilfsfunktion, um einen neuen Zugriffstoken zu generieren. + +{* ../../docs_src/security/tutorial004_an_py310.py hl[4,7,13:15,29:31,82:90] *} + +## Die Abhängigkeiten aktualisieren { #update-the-dependencies } + +Aktualisieren Sie `get_current_user`, um den gleichen Token wie zuvor zu erhalten, dieses Mal jedoch unter Verwendung von JWT-Tokens. + +Dekodieren Sie den empfangenen Token, validieren Sie ihn und geben Sie den aktuellen Benutzer zurück. + +Wenn der Token ungültig ist, geben Sie sofort einen HTTP-Fehler zurück. + +{* ../../docs_src/security/tutorial004_an_py310.py hl[93:110] *} + +## Die `/token`-*Pfadoperation* aktualisieren { #update-the-token-path-operation } + +Erstellen Sie ein `timedelta` mit der Ablaufzeit des Tokens. + +Erstellen Sie einen echten JWT-Zugriffstoken und geben Sie ihn zurück. + +{* ../../docs_src/security/tutorial004_an_py310.py hl[121:136] *} + +### Technische Details zum JWT-„Subjekt“ `sub` { #technical-details-about-the-jwt-subject-sub } + +Die JWT-Spezifikation besagt, dass es einen Schlüssel `sub` mit dem Subjekt des Tokens gibt. + +Die Verwendung ist optional, aber dort würden Sie die Identifikation des Benutzers speichern, daher verwenden wir das hier. + +JWT kann auch für andere Dinge verwendet werden, abgesehen davon, einen Benutzer zu identifizieren und ihm zu erlauben, Operationen direkt auf Ihrer API auszuführen. + +Sie könnten beispielsweise ein „Auto“ oder einen „Blog-Beitrag“ identifizieren. + +Anschließend könnten Sie Berechtigungen für diese Entität hinzufügen, etwa „Fahren“ (für das Auto) oder „Bearbeiten“ (für den Blog). + +Und dann könnten Sie diesen JWT-Token einem Benutzer (oder Bot) geben und dieser könnte ihn verwenden, um diese Aktionen auszuführen (das Auto fahren oder den Blog-Beitrag bearbeiten), ohne dass er überhaupt ein Konto haben müsste, einfach mit dem JWT-Token, den Ihre API dafür generiert hat. + +Mit diesen Ideen kann JWT für weitaus anspruchsvollere Szenarien verwendet werden. + +In diesen Fällen könnten mehrere dieser Entitäten die gleiche ID haben, sagen wir `foo` (ein Benutzer `foo`, ein Auto `foo` und ein Blog-Beitrag `foo`). + +Deshalb, um ID-Kollisionen zu vermeiden, könnten Sie beim Erstellen des JWT-Tokens für den Benutzer, dem Wert des `sub`-Schlüssels ein Präfix, z. B. `username:` voranstellen. In diesem Beispiel hätte der Wert von `sub` also auch `username:johndoe` sein können. + +Der wesentliche Punkt ist, dass der `sub`-Schlüssel in der gesamten Anwendung eine eindeutige Kennung haben sollte, und er sollte ein String sein. + +## Es testen { #check-it } + +Führen Sie den Server aus und gehen Sie zur Dokumentation: [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs). + +Die Benutzeroberfläche sieht wie folgt aus: + + + +Melden Sie sich bei der Anwendung auf die gleiche Weise wie zuvor an. + +Verwenden Sie die Anmeldeinformationen: + +Benutzername: `johndoe` +Passwort: `secret` + +/// tip | Tipp + +Beachten Sie, dass im Code nirgendwo das Klartext-Passwort „`secret`“ steht, wir haben nur die gehashte Version. + +/// + + + +Rufen Sie den Endpunkt `/users/me/` auf, Sie erhalten die Response: + +```JSON +{ + "username": "johndoe", + "email": "johndoe@example.com", + "full_name": "John Doe", + "disabled": false +} +``` + + + +Wenn Sie die Developer Tools öffnen, können Sie sehen, dass die gesendeten Daten nur den Token enthalten. Das Passwort wird nur beim ersten Request gesendet, um den Benutzer zu authentisieren und diesen Zugriffstoken zu erhalten, aber nicht mehr danach: + + + +/// note | Hinweis + +Beachten Sie den Header `Authorization` mit einem Wert, der mit `Bearer ` beginnt. + +/// + +## Fortgeschrittene Verwendung mit `scopes` { #advanced-usage-with-scopes } + +OAuth2 hat ein Konzept von „Scopes“. + +Sie können diese verwenden, um einem JWT-Token einen bestimmten Satz von Berechtigungen zu übergeben. + +Anschließend können Sie diesen Token einem Benutzer direkt oder einem Dritten geben, damit diese mit einer Reihe von Einschränkungen mit Ihrer API interagieren können. + +Wie Sie sie verwenden und wie sie in **FastAPI** integriert sind, erfahren Sie später im **Handbuch für fortgeschrittene Benutzer**. + +## Zusammenfassung { #recap } + +Mit dem, was Sie bis hier gesehen haben, können Sie eine sichere **FastAPI**-Anwendung mithilfe von Standards wie OAuth2 und JWT einrichten. + +In fast jedem Framework wird die Handhabung der Sicherheit recht schnell zu einem ziemlich komplexen Thema. + +Viele Packages, die es stark vereinfachen, müssen viele Kompromisse beim Datenmodell, der Datenbank und den verfügbaren Funktionen eingehen. Und einige dieser Pakete, die die Dinge zu sehr vereinfachen, weisen tatsächlich Sicherheitslücken auf. + +--- + +**FastAPI** geht bei keiner Datenbank, keinem Datenmodell oder Tool Kompromisse ein. + +Es gibt Ihnen die volle Flexibilität, diejenigen auszuwählen, die am besten zu Ihrem Projekt passen. + +Und Sie können viele gut gepflegte und weit verbreitete Packages wie `pwdlib` und `PyJWT` direkt verwenden, da **FastAPI** keine komplexen Mechanismen zur Integration externer Pakete erfordert. + +Aber es bietet Ihnen die Werkzeuge, um den Prozess so weit wie möglich zu vereinfachen, ohne Kompromisse bei Flexibilität, Robustheit oder Sicherheit einzugehen. + +Und Sie können sichere Standardprotokolle wie OAuth2 auf relativ einfache Weise verwenden und implementieren. + +Im **Handbuch für fortgeschrittene Benutzer** erfahren Sie mehr darüber, wie Sie OAuth2-„Scopes“ für ein feingranuliertes Berechtigungssystem verwenden, das denselben Standards folgt. OAuth2 mit Scopes ist der Mechanismus, der von vielen großen Authentifizierungsanbietern wie Facebook, Google, GitHub, Microsoft, X (Twitter), usw. verwendet wird, um Drittanbieteranwendungen zu autorisieren, im Namen ihrer Benutzer mit ihren APIs zu interagieren. diff --git a/docs/de/docs/tutorial/security/simple-oauth2.md b/docs/de/docs/tutorial/security/simple-oauth2.md new file mode 100644 index 0000000000000..b7b041bc1e480 --- /dev/null +++ b/docs/de/docs/tutorial/security/simple-oauth2.md @@ -0,0 +1,289 @@ +# Einfaches OAuth2 mit Password und Bearer { #simple-oauth2-with-password-and-bearer } + +Lassen Sie uns nun auf dem vorherigen Kapitel aufbauen und die fehlenden Teile hinzufügen, um einen vollständigen Sicherheits-Flow zu erhalten. + +## `username` und `password` entgegennehmen { #get-the-username-and-password } + +Wir werden **FastAPIs** Sicherheits-Werkzeuge verwenden, um den `username` und das `password` entgegenzunehmen. + +OAuth2 spezifiziert, dass der Client/Benutzer bei Verwendung des „Password Flow“ (den wir verwenden) die Felder `username` und `password` als Formulardaten senden muss. + +Und die Spezifikation sagt, dass die Felder so benannt werden müssen. `user-name` oder `email` würde also nicht funktionieren. + +Aber keine Sorge, Sie können sie Ihren Endbenutzern im Frontend so anzeigen, wie Sie möchten. + +Und Ihre Datenbankmodelle können beliebige andere Namen verwenden. + +Aber für die Login-*Pfadoperation* müssen wir diese Namen verwenden, um mit der Spezifikation kompatibel zu sein (und beispielsweise das integrierte API-Dokumentationssystem verwenden zu können). + +Die Spezifikation besagt auch, dass `username` und `password` als Formulardaten gesendet werden müssen (hier also kein JSON). + +### `scope` { #scope } + +Ferner sagt die Spezifikation, dass der Client ein weiteres Formularfeld „`scope`“ senden kann. + +Der Name des Formularfelds lautet `scope` (im Singular), tatsächlich handelt es sich jedoch um einen langen String mit durch Leerzeichen getrennten „Scopes“. + +Jeder „Scope“ ist nur ein String (ohne Leerzeichen). + +Diese werden normalerweise verwendet, um bestimmte Sicherheitsberechtigungen zu deklarieren, zum Beispiel: + +* `users:read` oder `users:write` sind gängige Beispiele. +* `instagram_basic` wird von Facebook / Instagram verwendet. +* `https://www.googleapis.com/auth/drive` wird von Google verwendet. + +/// note | Hinweis + +In OAuth2 ist ein „Scope“ nur ein String, der eine bestimmte erforderliche Berechtigung deklariert. + +Es spielt keine Rolle, ob er andere Zeichen wie `:` enthält oder ob es eine URL ist. + +Diese Details sind implementierungsspezifisch. + +Für OAuth2 sind es einfach nur Strings. + +/// + +## Code, um `username` und `password` entgegenzunehmen { #code-to-get-the-username-and-password } + +Lassen Sie uns nun die von **FastAPI** bereitgestellten Werkzeuge verwenden, um das zu erledigen. + +### `OAuth2PasswordRequestForm` { #oauth2passwordrequestform } + +Importieren Sie zunächst `OAuth2PasswordRequestForm` und verwenden Sie es als Abhängigkeit mit `Depends` in der *Pfadoperation* für `/token`: + +{* ../../docs_src/security/tutorial003_an_py310.py hl[4,78] *} + +`OAuth2PasswordRequestForm` ist eine Klassenabhängigkeit, die einen Formularbody deklariert mit: + +* Dem `username`. +* Dem `password`. +* Einem optionalen `scope`-Feld als langem String, bestehend aus durch Leerzeichen getrennten Strings. +* Einem optionalen `grant_type`. + +/// tip | Tipp + +Die OAuth2-Spezifikation *erfordert* tatsächlich ein Feld `grant_type` mit dem festen Wert `password`, aber `OAuth2PasswordRequestForm` erzwingt dies nicht. + +Wenn Sie es erzwingen müssen, verwenden Sie `OAuth2PasswordRequestFormStrict` anstelle von `OAuth2PasswordRequestForm`. + +/// + +* Eine optionale `client_id` (benötigen wir für unser Beispiel nicht). +* Ein optionales `client_secret` (benötigen wir für unser Beispiel nicht). + +/// note | Hinweis + +`OAuth2PasswordRequestForm` ist keine spezielle Klasse für **FastAPI**, so wie `OAuth2PasswordBearer`. + +`OAuth2PasswordBearer` lässt **FastAPI** wissen, dass es sich um ein Sicherheitsschema handelt. Daher wird es auf diese Weise zu OpenAPI hinzugefügt. + +Aber `OAuth2PasswordRequestForm` ist nur eine Klassenabhängigkeit, die Sie selbst hätten schreiben können, oder Sie hätten `Form`ular-Parameter direkt deklarieren können. + +Da es sich jedoch um einen häufigen Anwendungsfall handelt, wird er zur Vereinfachung direkt von **FastAPI** bereitgestellt. + +/// + +### Die Formulardaten verwenden { #use-the-form-data } + +/// tip | Tipp + +Die Instanz der Klassenabhängigkeit `OAuth2PasswordRequestForm` verfügt, statt eines Attributs `scope` mit dem durch Leerzeichen getrennten langen String, über das Attribut `scopes` mit einer tatsächlichen Liste von Strings, einem für jeden gesendeten Scope. + +In diesem Beispiel verwenden wir keine `scopes`, aber die Funktionalität ist vorhanden, wenn Sie sie benötigen. + +/// + +Rufen Sie nun die Benutzerdaten aus der (gefakten) Datenbank ab, für diesen `username` aus dem Formularfeld. + +Wenn es keinen solchen Benutzer gibt, geben wir die Fehlermeldung „Incorrect username or password“ zurück. + +Für den Fehler verwenden wir die Exception `HTTPException`: + +{* ../../docs_src/security/tutorial003_an_py310.py hl[3,79:81] *} + +### Das Passwort überprüfen { #check-the-password } + +Zu diesem Zeitpunkt liegen uns die Benutzerdaten aus unserer Datenbank vor, das Passwort haben wir jedoch noch nicht überprüft. + +Lassen Sie uns diese Daten zunächst in das Pydantic-Modell `UserInDB` einfügen. + +Sie sollten niemals Klartext-Passwörter speichern, daher verwenden wir ein (gefaktes) Passwort-Hashing-System. + +Wenn die Passwörter nicht übereinstimmen, geben wir denselben Fehler zurück. + +#### Passwort-Hashing { #password-hashing } + +„Hashing“ bedeutet: Konvertieren eines Inhalts (in diesem Fall eines Passworts) in eine Folge von Bytes (ein schlichter String), die wie Kauderwelsch aussieht. + +Immer wenn Sie genau den gleichen Inhalt (genau das gleiche Passwort) übergeben, erhalten Sie genau den gleichen Kauderwelsch. + +Sie können jedoch nicht vom Kauderwelsch zurück zum Passwort konvertieren. + +##### Warum Passwort-Hashing verwenden { #why-use-password-hashing } + +Wenn Ihre Datenbank gestohlen wird, hat der Dieb nicht die Klartext-Passwörter Ihrer Benutzer, sondern nur die Hashes. + +Der Dieb kann also nicht versuchen, die gleichen Passwörter in einem anderen System zu verwenden (da viele Benutzer überall das gleiche Passwort verwenden, wäre dies gefährlich). + +{* ../../docs_src/security/tutorial003_an_py310.py hl[82:85] *} + +#### Über `**user_dict` { #about-user-dict } + +`UserInDB(**user_dict)` bedeutet: + +*Übergib die Schlüssel und Werte des `user_dict` direkt als Schlüssel-Wert-Argumente, äquivalent zu:* + +```Python +UserInDB( + username = user_dict["username"], + email = user_dict["email"], + full_name = user_dict["full_name"], + disabled = user_dict["disabled"], + hashed_password = user_dict["hashed_password"], +) +``` + +/// note | Hinweis + +Eine ausführlichere Erklärung von `**user_dict` finden Sie in [der Dokumentation für **Extra Modelle**](../extra-models.md#about-user-in-model-dump). + +/// + +## Den Token zurückgeben { #return-the-token } + +Die Response des `token`-Endpunkts muss ein JSON-Objekt sein. + +Es sollte einen `token_type` haben. Da wir in unserem Fall „Bearer“-Token verwenden, sollte der Token-Typ „`bearer`“ sein. + +Und es sollte einen `access_token` haben, mit einem String, der unseren Zugriffstoken enthält. + +In diesem einfachen Beispiel gehen wir einfach völlig unsicher vor und geben denselben `username` wie der Token zurück. + +/// tip | Tipp + +Im nächsten Kapitel sehen Sie eine wirklich sichere Implementierung mit Passwort-Hashing und JWT-Tokens. + +Aber konzentrieren wir uns zunächst auf die spezifischen Details, die wir benötigen. + +/// + +{* ../../docs_src/security/tutorial003_an_py310.py hl[87] *} + +/// tip | Tipp + +Gemäß der Spezifikation sollten Sie ein JSON mit einem `access_token` und einem `token_type` zurückgeben, genau wie in diesem Beispiel. + +Das müssen Sie selbst in Ihrem Code tun und sicherstellen, dass Sie diese JSON-Schlüssel verwenden. + +Es ist fast das Einzige, woran Sie denken müssen, es selbst richtigzumachen und die Spezifikationen einzuhalten. + +Den Rest erledigt **FastAPI** für Sie. + +/// + +## Die Abhängigkeiten aktualisieren { #update-the-dependencies } + +Jetzt werden wir unsere Abhängigkeiten aktualisieren. + +Wir möchten den `current_user` *nur* erhalten, wenn dieser Benutzer aktiv ist. + +Daher erstellen wir eine zusätzliche Abhängigkeit `get_current_active_user`, die wiederum `get_current_user` als Abhängigkeit verwendet. + +Beide Abhängigkeiten geben nur dann einen HTTP-Error zurück, wenn der Benutzer nicht existiert oder inaktiv ist. + +In unserem Endpunkt erhalten wir also nur dann einen Benutzer, wenn der Benutzer existiert, korrekt authentifiziert wurde und aktiv ist: + +{* ../../docs_src/security/tutorial003_an_py310.py hl[58:66,69:74,94] *} + +/// note | Hinweis + +Der zusätzliche Header `WWW-Authenticate` mit dem Wert `Bearer`, den wir hier zurückgeben, ist ebenfalls Teil der Spezifikation. + +Jeder HTTP-(Fehler-)Statuscode 401 „UNAUTHORIZED“ soll auch einen `WWW-Authenticate`-Header zurückgeben. + +Im Fall von Bearer-Tokens (in unserem Fall) sollte der Wert dieses Headers `Bearer` lauten. + +Sie können diesen zusätzlichen Header tatsächlich weglassen und es würde trotzdem funktionieren. + +Aber er wird hier bereitgestellt, um den Spezifikationen zu entsprechen. + +Außerdem gibt es möglicherweise Tools, die ihn erwarten und verwenden (jetzt oder in der Zukunft) und das könnte für Sie oder Ihre Benutzer jetzt oder in der Zukunft nützlich sein. + +Das ist der Vorteil von Standards ... + +/// + +## Es in Aktion sehen { #see-it-in-action } + +Öffnen Sie die interaktive Dokumentation: [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs). + +### Authentifizieren { #authenticate } + +Klicken Sie auf den Button „Authorize“. + +Verwenden Sie die Anmeldedaten: + +Benutzer: `johndoe` + +Passwort: `secret` + + + +Nach der Authentifizierung im System sehen Sie Folgendes: + + + +### Die eigenen Benutzerdaten ansehen { #get-your-own-user-data } + +Verwenden Sie nun die Operation `GET` mit dem Pfad `/users/me`. + +Sie erhalten Ihre Benutzerdaten: + +```JSON +{ + "username": "johndoe", + "email": "johndoe@example.com", + "full_name": "John Doe", + "disabled": false, + "hashed_password": "fakehashedsecret" +} +``` + + + +Wenn Sie auf das Schlosssymbol klicken und sich abmelden und dann den gleichen Vorgang nochmal versuchen, erhalten Sie einen HTTP 401 Error: + +```JSON +{ + "detail": "Not authenticated" +} +``` + +### Inaktiver Benutzer { #inactive-user } + +Versuchen Sie es nun mit einem inaktiven Benutzer und authentisieren Sie sich mit: + +Benutzer: `alice` + +Passwort: `secret2` + +Und versuchen Sie, die Operation `GET` mit dem Pfad `/users/me` zu verwenden. + +Sie erhalten die Fehlermeldung „Inactive user“: + +```JSON +{ + "detail": "Inactive user" +} +``` + +## Zusammenfassung { #recap } + +Sie verfügen jetzt über die Tools, um ein vollständiges Sicherheitssystem basierend auf `username` und `password` für Ihre API zu implementieren. + +Mit diesen Tools können Sie das Sicherheitssystem mit jeder Datenbank und jedem Benutzer oder Datenmodell kompatibel machen. + +Das einzige fehlende Detail ist, dass es noch nicht wirklich „sicher“ ist. + +Im nächsten Kapitel erfahren Sie, wie Sie eine sichere Passwort-Hashing-Bibliothek und JWT-Token verwenden. diff --git a/docs/de/docs/tutorial/server-sent-events.md b/docs/de/docs/tutorial/server-sent-events.md new file mode 100644 index 0000000000000..8e6f35c71d242 --- /dev/null +++ b/docs/de/docs/tutorial/server-sent-events.md @@ -0,0 +1,120 @@ +# Server-Sent Events (SSE) { #server-sent-events-sse } + +Sie können Daten mithilfe von **Server-Sent Events** (SSE) an den Client streamen. + +Das ist ähnlich wie [JSON Lines streamen](stream-json-lines.md), verwendet aber das Format `text/event-stream`, das von Browsern nativ mit der [`EventSource`-API](https://developer.mozilla.org/en-US/docs/Web/API/EventSource) unterstützt wird. + +/// note | Hinweis + +Hinzugefügt in FastAPI 0.135.0. + +/// + +## Was sind Server-Sent Events? { #what-are-server-sent-events } + +SSE ist ein Standard zum Streamen von Daten vom Server zum Client über HTTP. + +Jedes Event ist ein kleiner Textblock mit „Feldern“ wie `data`, `event`, `id` und `retry`, getrennt durch Leerzeilen. + +Das sieht so aus: + +``` +data: {"name": "Portal Gun", "price": 999.99} + +data: {"name": "Plumbus", "price": 32.99} + +``` + +SSE wird häufig für KI-Chat-Streaming, Live-Benachrichtigungen, Logs und Observability sowie andere Fälle verwendet, in denen der Server Updates an den Client pusht. + +/// tip | Tipp + +Wenn Sie Binärdaten streamen wollen, z. B. Video oder Audio, sehen Sie im Handbuch für fortgeschrittene Benutzer nach: [Daten streamen](../advanced/stream-data.md). + +/// + +## SSE mit FastAPI streamen { #stream-sse-with-fastapi } + +Um SSE mit FastAPI zu streamen, verwenden Sie `yield` in Ihrer *Pfadoperation-Funktion* und setzen Sie `response_class=EventSourceResponse`. + +Importieren Sie `EventSourceResponse` aus `fastapi.sse`: + +{* ../../docs_src/server_sent_events/tutorial001_py310.py ln[1:25] hl[4,22] *} + +Jedes mit `yield` zurückgegebene Element wird als JSON kodiert und im Feld `data:` eines SSE-Events gesendet. + +Wenn Sie den Rückgabetyp als `AsyncIterable[Item]` deklarieren, verwendet FastAPI ihn, um die Daten mit Pydantic zu **validieren**, zu **dokumentieren** und zu **serialisieren**. + +{* ../../docs_src/server_sent_events/tutorial001_py310.py ln[1:25] hl[10:12,23] *} + +/// tip | Tipp + +Da Pydantic es auf der **Rust**-Seite serialisiert, erhalten Sie eine deutlich höhere **Leistung**, als wenn Sie keinen Rückgabetyp deklarieren. + +/// + +### Nicht-async-*Pfadoperation-Funktionen* { #non-async-path-operation-functions } + +Sie können auch normale `def`-Funktionen (ohne `async`) verwenden und `yield` genauso einsetzen. + +FastAPI stellt sicher, dass sie korrekt ausgeführt wird, sodass sie die Event Loop nicht blockiert. + +Da die Funktion in diesem Fall nicht async ist, wäre der passende Rückgabetyp `Iterable[Item]`: + +{* ../../docs_src/server_sent_events/tutorial001_py310.py ln[28:31] hl[29] *} + +### Kein Rückgabetyp { #no-return-type } + +Sie können den Rückgabetyp auch weglassen. FastAPI verwendet dann den [`jsonable_encoder`](./encoder.md), um die Daten zu konvertieren und zu senden. + +{* ../../docs_src/server_sent_events/tutorial001_py310.py ln[34:37] hl[35] *} + +## `ServerSentEvent` { #serversentevent } + +Wenn Sie SSE-Felder wie `event`, `id`, `retry` oder `comment` setzen müssen, können Sie statt reiner Daten `ServerSentEvent`-Objekte yielden. + +Importieren Sie `ServerSentEvent` aus `fastapi.sse`: + +{* ../../docs_src/server_sent_events/tutorial002_py310.py hl[4,26] *} + +Das Feld `data` wird immer als JSON kodiert. Sie können jeden Wert übergeben, der als JSON serialisierbar ist, einschließlich Pydantic-Modellen. + +## Rohdaten { #raw-data } + +Wenn Sie Daten **ohne** JSON-Kodierung senden müssen, verwenden Sie `raw_data` statt `data`. + +Das ist nützlich zum Senden vorformatierter Texte, Logzeilen oder spezieller „Sentinel“-Werte wie `[DONE]`. + +{* ../../docs_src/server_sent_events/tutorial003_py310.py hl[17] *} + +/// note | Hinweis + +`data` und `raw_data` schließen sich gegenseitig aus. Sie können pro `ServerSentEvent` nur eines von beiden setzen. + +/// + +## Mit `Last-Event-ID` fortsetzen { #resuming-with-last-event-id } + +Wenn ein Browser nach einem Verbindungsabbruch erneut verbindet, sendet er die zuletzt empfangene `id` im Header `Last-Event-ID`. + +Sie können ihn als Header-Parameter einlesen und verwenden, um den Stream dort fortzusetzen, wo der Client aufgehört hat: + +{* ../../docs_src/server_sent_events/tutorial004_py310.py hl[25,27,31] *} + +## SSE mit POST { #sse-with-post } + +SSE funktioniert mit **jeder HTTP-Methode**, nicht nur mit `GET`. + +Das ist nützlich für Protokolle wie [MCP](https://modelcontextprotocol.io), die SSE über `POST` streamen: + +{* ../../docs_src/server_sent_events/tutorial005_py310.py hl[14] *} + +## Technische Details { #technical-details } + +FastAPI implementiert einige bewährte SSE-Praktiken direkt out of the box. + +- Einen **„keep alive“-`ping`-Kommentar** alle 15 Sekunden senden, wenn keine Nachricht gesendet wurde, um zu verhindern, dass einige Proxys die Verbindung schließen, wie in der [HTML-Spezifikation: Server-Sent Events](https://html.spec.whatwg.org/multipage/server-sent-events.html#authoring-notes) vorgeschlagen. +- Den Header `Cache-Control: no-cache` setzen, um **Caching** des Streams zu verhindern. +- Einen speziellen Header `X-Accel-Buffering: no` setzen, um **Buffering** in einigen Proxys wie Nginx zu verhindern. + +Sie müssen dafür nichts tun, das funktioniert out of the box. 🤓 diff --git a/docs/de/docs/tutorial/sql-databases.md b/docs/de/docs/tutorial/sql-databases.md new file mode 100644 index 0000000000000..3c7aabae3fdb1 --- /dev/null +++ b/docs/de/docs/tutorial/sql-databases.md @@ -0,0 +1,357 @@ +# SQL (Relationale) Datenbanken { #sql-relational-databases } + +**FastAPI** erfordert nicht, dass Sie eine SQL (relationale) Datenbank verwenden. Sondern Sie können **jede beliebige Datenbank** verwenden, die Sie möchten. + +Hier werden wir ein Beispiel mit [SQLModel](https://sqlmodel.tiangolo.com/) sehen. + +**SQLModel** basiert auf [SQLAlchemy](https://www.sqlalchemy.org/) und Pydantic. Es wurde vom selben Autor wie **FastAPI** entwickelt, um die perfekte Ergänzung für FastAPI-Anwendungen zu sein, die **SQL-Datenbanken** verwenden müssen. + +/// tip | Tipp + +Sie könnten jede andere SQL- oder NoSQL-Datenbankbibliothek verwenden, die Sie möchten (in einigen Fällen als „ORMs“ bezeichnet), FastAPI zwingt Sie nicht, irgendetwas zu verwenden. 😎 + +/// + +Da SQLModel auf SQLAlchemy basiert, können Sie problemlos **jede von SQLAlchemy unterstützte Datenbank** verwenden (was auch bedeutet, dass sie von SQLModel unterstützt werden), wie: + +* PostgreSQL +* MySQL +* SQLite +* Oracle +* Microsoft SQL Server, usw. + +In diesem Beispiel verwenden wir **SQLite**, da es eine einzelne Datei verwendet und Python integrierte Unterstützung bietet. Sie können also dieses Beispiel kopieren und direkt ausführen. + +Später, für Ihre Produktionsanwendung, möchten Sie möglicherweise einen Datenbankserver wie **PostgreSQL** verwenden. + +/// tip | Tipp + +Es gibt einen offiziellen Projektgenerator mit **FastAPI** und **PostgreSQL**, einschließlich eines Frontends und weiterer Tools: [https://github.com/fastapi/full-stack-fastapi-template](https://github.com/fastapi/full-stack-fastapi-template) + +/// + +Dies ist ein sehr einfaches und kurzes Tutorial. Wenn Sie mehr über Datenbanken im Allgemeinen, über SQL oder fortgeschrittenere Funktionen erfahren möchten, besuchen Sie die [SQLModel-Dokumentation](https://sqlmodel.tiangolo.com/). + +## `SQLModel` installieren { #install-sqlmodel } + +Stellen Sie zunächst sicher, dass Sie Ihre [virtuelle Umgebung](../virtual-environments.md) erstellen, sie aktivieren und dann `sqlmodel` installieren: + +
+ +```console +$ pip install sqlmodel +---> 100% +``` + +
+ +## Die App mit einem einzelnen Modell erstellen { #create-the-app-with-a-single-model } + +Wir erstellen zuerst die einfachste erste Version der App mit einem einzigen **SQLModel**-Modell. + +Später werden wir sie verbessern, indem wir unter der Haube **mehrere Modelle** verwenden, um Sicherheit und Vielseitigkeit zu erhöhen. 🤓 + +### Modelle erstellen { #create-models } + +Importieren Sie `SQLModel` und erstellen Sie ein Datenbankmodell: + +{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[1:11] hl[7:11] *} + +Die `Hero`-Klasse ist einem Pydantic-Modell sehr ähnlich (faktisch ist sie darunter tatsächlich *ein Pydantic-Modell*). + +Es gibt ein paar Unterschiede: + +* `table=True` sagt SQLModel, dass dies ein *Tabellenmodell* ist, es soll eine **Tabelle** in der SQL-Datenbank darstellen, es ist nicht nur ein *Datenmodell* (wie es jede andere reguläre Pydantic-Klasse wäre). + +* `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 [SQLModel-Dokumentation zu Primärschlüsseln](https://sqlmodel.tiangolo.com/tutorial/create-db-and-table/#primary-key-id) für Details. + +* `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. + + SQLModel wird verstehen, dass etwas, das als `str` deklariert ist, eine SQL-Spalte des Typs `TEXT` (oder `VARCHAR`, abhängig von der Datenbank) sein wird. + +### Eine Engine erstellen { #create-an-engine } + +Eine SQLModel-`engine` (darunter ist es tatsächlich eine SQLAlchemy-`engine`) ist das, was die **Verbindungen** zur Datenbank hält. + +Sie hätten **ein einziges `engine`-Objekt** für Ihren gesamten Code, um sich mit derselben Datenbank zu verbinden. + +{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[14:18] hl[14:15,17:18] *} + +Die Verwendung von `check_same_thread=False` erlaubt FastAPI, dieselbe SQLite-Datenbank in verschiedenen Threads zu verwenden. Dies ist notwendig, da **ein einzelner Request** **mehr als einen Thread** verwenden könnte (zum Beispiel in Abhängigkeiten). + +Keine Sorge, so wie der Code strukturiert ist, werden wir später sicherstellen, dass wir **eine einzige SQLModel-*Session* pro Request** verwenden, das ist eigentlich das, was `check_same_thread` erreichen möchte. + +### Die Tabellen erstellen { #create-the-tables } + +Dann fügen wir eine Funktion hinzu, die `SQLModel.metadata.create_all(engine)` verwendet, um die **Tabellen für alle *Tabellenmodelle* zu erstellen**. + +{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[21:22] hl[21:22] *} + +### Eine Session-Abhängigkeit erstellen { #create-a-session-dependency } + +Eine **`Session`** speichert die **Objekte im Speicher** und verfolgt alle Änderungen, die an den Daten vorgenommen werden müssen, dann **verwendet sie die `engine`**, um mit der Datenbank zu kommunizieren. + +Wir werden eine FastAPI **Abhängigkeit** mit `yield` erstellen, die eine neue `Session` für jeden Request bereitstellt. Das ist es, was sicherstellt, dass wir eine einzige Session pro Request verwenden. 🤓 + +Dann erstellen wir eine `Annotated`-Abhängigkeit `SessionDep`, um den Rest des Codes zu vereinfachen, der diese Abhängigkeit nutzen wird. + +{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[25:30] hl[25:27,30] *} + +### Die Datenbanktabellen beim Start erstellen { #create-database-tables-on-startup } + +Wir werden die Datenbanktabellen erstellen, wenn die Anwendung startet. + +{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[32:37] hl[35:37] *} + +Hier erstellen wir die Tabellen bei einem Anwendungsstart-Event. + +Für die Produktion würden Sie wahrscheinlich ein Migrationsskript verwenden, das ausgeführt wird, bevor Sie Ihre App starten. 🤓 + +/// tip | Tipp + +SQLModel wird Migrationstools haben, die Alembic wrappen, aber im Moment können Sie [Alembic](https://alembic.sqlalchemy.org/en/latest/) direkt verwenden. + +/// + +### Einen Helden erstellen { #create-a-hero } + +Da jedes SQLModel-Modell auch ein Pydantic-Modell ist, können Sie es in denselben **Typannotationen** verwenden, die Sie für Pydantic-Modelle verwenden könnten. + +Wenn Sie beispielsweise einen Parameter vom Typ `Hero` deklarieren, wird er aus dem **JSON-Body** gelesen. + +Auf die gleiche Weise können Sie es als **Rückgabetyp** der Funktion deklarieren, und dann wird die Form der Daten in der automatischen API-Dokumentations-UI angezeigt. + +{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[40:45] hl[40:45] *} + +Hier verwenden wir die `SessionDep`-Abhängigkeit (eine `Session`), um den neuen `Hero` zur `Session`-Instanz hinzuzufügen, die Änderungen an der Datenbank zu committen, die Daten im `hero` zu aktualisieren und ihn anschließend zurückzugeben. + +### Helden lesen { #read-heroes } + +Wir können `Hero`s aus der Datenbank mit einem `select()` **lesen**. Wir können ein `limit` und `offset` hinzufügen, um die Ergebnisse zu paginieren. + +{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[48:55] hl[51:52,54] *} + +### Einen Helden lesen { #read-one-hero } + +Wir können einen einzelnen `Hero` **lesen**. + +{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[58:63] hl[60] *} + +### Einen Helden löschen { #delete-a-hero } + +Wir können auch einen `Hero` **löschen**. + +{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[66:73] hl[71] *} + +### Die App ausführen { #run-the-app } + +Sie können die App ausführen: + +
+ +```console +$ fastapi dev + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +Gehen Sie dann zur `/docs`-UI, Sie werden sehen, dass **FastAPI** diese **Modelle** verwendet, um die API zu **dokumentieren**, und es wird sie auch verwenden, um die Daten zu **serialisieren** und zu **validieren**. + +
+ +
+ +## Die App mit mehreren Modellen aktualisieren { #update-the-app-with-multiple-models } + +Jetzt lassen Sie uns diese App ein wenig **refaktorisieren**, um die **Sicherheit** und **Vielseitigkeit** zu erhöhen. + +Wenn Sie die vorherige App überprüfen, können Sie in der UI sehen, dass sie bis jetzt dem Client erlaubt, die `id` des zu erstellenden `Hero` zu bestimmen. 😱 + +Das sollten wir nicht zulassen, sie könnten eine `id` überschreiben, die wir bereits in der DB zugewiesen haben. Die Entscheidung über die `id` sollte vom **Backend** oder der **Datenbank** getroffen werden, **nicht vom Client**. + +Außerdem erstellen wir einen `secret_name` für den Helden, aber bisher geben wir ihn überall zurück, das ist nicht sehr **geheim** ... 😅 + +Wir werden diese Dinge beheben, indem wir ein paar **zusätzliche Modelle** hinzufügen. Hier wird SQLModel glänzen. ✨ + +### Mehrere Modelle erstellen { #create-multiple-models } + +In **SQLModel** ist jede Modellklasse, die `table=True` hat, ein **Tabellenmodell**. + +Und jede Modellklasse, die `table=True` nicht hat, ist ein **Datenmodell**, diese sind tatsächlich nur Pydantic-Modelle (mit ein paar kleinen zusätzlichen Funktionen). 🤓 + +Mit SQLModel können wir **Vererbung** verwenden, um **doppelte Felder** in allen Fällen zu **vermeiden**. + +#### `HeroBase` – die Basisklasse { #herobase-the-base-class } + +Fangen wir mit einem `HeroBase`-Modell an, das alle **Felder hat, die von allen Modellen geteilt werden**: + +* `name` +* `age` + +{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[7:9] hl[7:9] *} + +#### `Hero` – das *Tabellenmodell* { #hero-the-table-model } + +Dann erstellen wir `Hero`, das tatsächliche *Tabellenmodell*, mit den **zusätzlichen Feldern**, die nicht immer in den anderen Modellen enthalten sind: + +* `id` +* `secret_name` + +Da `Hero` von `HeroBase` erbt, hat es **auch** die **Felder**, die in `HeroBase` deklariert sind, also sind alle Felder von `Hero`: + +* `id` +* `name` +* `age` +* `secret_name` + +{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[7:14] hl[12:14] *} + +#### `HeroPublic` – das öffentliche *Datenmodell* { #heropublic-the-public-data-model } + +Als nächstes erstellen wir ein `HeroPublic`-Modell, das an die API-Clients **zurückgegeben** wird. + +Es hat dieselben Felder wie `HeroBase`, sodass es `secret_name` nicht enthält. + +Endlich ist die Identität unserer Helden geschützt! 🥷 + +Es deklariert auch `id: int` erneut. Indem wir dies tun, machen wir einen **Vertrag** mit den API-Clients, damit sie immer damit rechnen können, dass die `id` vorhanden ist und ein `int` ist (sie wird niemals `None` sein). + +/// tip | Tipp + +Es ist sehr nützlich für die API-Clients, wenn das Rückgabemodell sicherstellt, dass ein Wert immer verfügbar und immer `int` (nicht `None`) ist, sie können viel einfacheren Code schreiben, wenn sie diese Sicherheit haben. + +Auch **automatisch generierte Clients** werden einfachere Schnittstellen haben, damit die Entwickler, die mit Ihrer API kommunizieren, viel mehr Freude an der Arbeit mit Ihrer API haben können. 😎 + +/// + +Alle Felder in `HeroPublic` sind dieselben wie in `HeroBase`, mit `id`, das als `int` (nicht `None`) deklariert ist: + +* `id` +* `name` +* `age` + +{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[7:18] hl[17:18] *} + +#### `HeroCreate` – das *Datenmodell* zum Erstellen eines Helden { #herocreate-the-data-model-to-create-a-hero } + +Nun erstellen wir ein `HeroCreate`-Modell, das die Daten der Clients **validiert**. + +Es hat dieselben Felder wie `HeroBase`, und es hat auch `secret_name`. + +Wenn die Clients **einen neuen Helden erstellen**, senden sie jetzt den `secret_name`, er wird in der Datenbank gespeichert, aber diese geheimen Namen werden den API-Clients nicht zurückgegeben. + +/// tip | Tipp + +So würden Sie **Passwörter** handhaben. Empfangen Sie sie, aber geben Sie sie nicht in der API zurück. + +Sie würden auch die Werte der Passwörter **hashen**, bevor Sie sie speichern, und sie **niemals im Klartext** speichern. + +/// + +Die Felder von `HeroCreate` sind: + +* `name` +* `age` +* `secret_name` + +{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[7:22] hl[21:22] *} + +#### `HeroUpdate` – das *Datenmodell* zum Aktualisieren eines Helden { #heroupdate-the-data-model-to-update-a-hero } + +In der vorherigen Version der App hatten wir keine Möglichkeit, einen Helden **zu aktualisieren**, aber jetzt mit **mehreren Modellen** können wir es. 🎉 + +Das `HeroUpdate`-*Datenmodell* ist etwas Besonderes, es hat **die selben Felder**, die benötigt werden, um einen neuen Helden zu erstellen, aber alle Felder sind **optional** (sie haben alle einen Defaultwert). Auf diese Weise, wenn Sie einen Helden aktualisieren, können Sie nur die Felder senden, die Sie aktualisieren möchten. + +Da sich tatsächlich **alle Felder ändern** (der Typ enthält jetzt `None` und sie haben jetzt einen Defaultwert von `None`), müssen wir sie erneut **deklarieren**. + +Wir müssen wirklich nicht von `HeroBase` erben, weil wir alle Felder neu deklarieren. Ich lasse es aus Konsistenzgründen erben, aber das ist nicht notwendig. Es ist mehr eine Frage des persönlichen Geschmacks. 🤷 + +Die Felder von `HeroUpdate` sind: + +* `name` +* `age` +* `secret_name` + +{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[7:28] hl[25:28] *} + +### Mit `HeroCreate` erstellen und ein `HeroPublic` zurückgeben { #create-with-herocreate-and-return-a-heropublic } + +Nun, da wir **mehrere Modelle** haben, können wir die Teile der App aktualisieren, die sie verwenden. + +Wir empfangen im Request ein `HeroCreate`-*Datenmodell* und daraus erstellen wir ein `Hero`-*Tabellenmodell*. + +Dieses neue *Tabellenmodell* `Hero` wird die vom Client gesendeten Felder haben und zusätzlich eine `id`, die von der Datenbank generiert wird. + +Dann geben wir das gleiche *Tabellenmodell* `Hero` von der Funktion zurück. Aber da wir das `response_model` mit dem `HeroPublic`-*Datenmodell* deklarieren, wird **FastAPI** `HeroPublic` verwenden, um die Daten zu validieren und zu serialisieren. + +{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[56:62] hl[56:58] *} + +/// tip | Tipp + +Jetzt verwenden wir `response_model=HeroPublic` anstelle der **Rückgabetyp-Annotation** `-> HeroPublic`, weil der Wert, den wir zurückgeben, tatsächlich *kein* `HeroPublic` ist. + +Wenn wir `-> HeroPublic` deklariert hätten, würden Ihr Editor und Linter (zu Recht) reklamieren, dass Sie ein `Hero` anstelle eines `HeroPublic` zurückgeben. + +Durch die Deklaration in `response_model` sagen wir **FastAPI**, dass es seine Aufgabe erledigen soll, ohne die Typannotationen und die Hilfe von Ihrem Editor und anderen Tools zu beeinträchtigen. + +/// + +### Helden mit `HeroPublic` lesen { #read-heroes-with-heropublic } + +Wir können dasselbe wie zuvor tun, um `Hero`s zu **lesen**, und erneut verwenden wir `response_model=list[HeroPublic]`, um sicherzustellen, dass die Daten ordnungsgemäß validiert und serialisiert werden. + +{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[65:72] hl[65] *} + +### Einen einzelnen Helden mit `HeroPublic` lesen { #read-one-hero-with-heropublic } + +Wir können einen einzelnen Helden **lesen**: + +{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[75:80] hl[77] *} + +### Einen Helden mit `HeroUpdate` aktualisieren { #update-a-hero-with-heroupdate } + +Wir können einen Helden **aktualisieren**. Dafür verwenden wir eine HTTP-`PATCH`-Operation. + +Und im Code erhalten wir ein `dict` mit allen Daten, die vom Client gesendet wurden, **nur die Daten, die vom Client gesendet wurden**, unter Ausschluss von Werten, die dort nur als Defaultwerte vorhanden wären. Um dies zu tun, verwenden wir `exclude_unset=True`. Das ist der Haupttrick. 🪄 + +Dann verwenden wir `hero_db.sqlmodel_update(hero_data)`, um die `hero_db` mit den Daten aus `hero_data` zu aktualisieren. + +{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[83:93] hl[83:84,88:89] *} + +### Einen Helden wieder löschen { #delete-a-hero-again } + +Das **Löschen** eines Helden bleibt ziemlich gleich. + +Wir werden dieses Mal nicht dem Wunsch nachgeben, alles zu refaktorisieren. 😅 + +{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[96:103] hl[101] *} + +### Die App erneut ausführen { #run-the-app-again } + +Sie können die App erneut ausführen: + +
+ +```console +$ fastapi dev + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +Wenn Sie zur `/docs`-API-UI gehen, werden Sie sehen, dass sie jetzt aktualisiert ist und nicht mehr erwarten wird, die `id` vom Client beim Erstellen eines Helden zu erhalten, usw. + +
+ +
+ +## Zusammenfassung { #recap } + +Sie können [**SQLModel**](https://sqlmodel.tiangolo.com/) verwenden, um mit einer SQL-Datenbank zu interagieren und den Code mit *Datenmodellen* und *Tabellenmodellen* zu vereinfachen. + +Sie können viel mehr in der **SQLModel**-Dokumentation lernen, es gibt ein längeres Mini-[Tutorial zur Verwendung von SQLModel mit **FastAPI**](https://sqlmodel.tiangolo.com/tutorial/fastapi/). 🚀 diff --git a/docs/de/docs/tutorial/static-files.md b/docs/de/docs/tutorial/static-files.md new file mode 100644 index 0000000000000..ef75ca91a0835 --- /dev/null +++ b/docs/de/docs/tutorial/static-files.md @@ -0,0 +1,48 @@ +# Statische Dateien { #static-files } + +Mit `StaticFiles` können Sie statische Dateien aus einem Verzeichnis automatisch bereitstellen. + +/// tip | Tipp + +Wenn Sie ein Frontend hosten müssen, verwenden Sie stattdessen `app.frontend()`; lesen Sie mehr dazu unter [Frontend](frontend.md). + +`app.frontend()` verwendet darunter `StaticFiles`, mit mehreren zusätzlichen Vorteilen für Frontends, wie der Handhabung von clientseitigem Routing. + +/// + +## `StaticFiles` verwenden { #use-staticfiles } + +* Importieren Sie `StaticFiles`. +* „Mounten“ Sie eine `StaticFiles()`-Instanz in einem bestimmten Pfad. + +{* ../../docs_src/static_files/tutorial001_py310.py hl[2,6] *} + +/// note | Technische Details + +Sie könnten auch `from starlette.staticfiles import StaticFiles` verwenden. + +**FastAPI** stellt dasselbe `starlette.staticfiles` auch via `fastapi.staticfiles` bereit, als Annehmlichkeit für Sie, den Entwickler. Es kommt aber tatsächlich direkt von Starlette. + +/// + +### Was ist „Mounten“ { #what-is-mounting } + +„Mounten“ bedeutet das Hinzufügen einer vollständigen „unabhängigen“ Anwendung an einem bestimmten Pfad, die sich dann um die Handhabung aller Unterpfade kümmert. + +Dies unterscheidet sich von der Verwendung eines `APIRouter`, da eine gemountete Anwendung völlig unabhängig ist. Die OpenAPI und Dokumentation Ihrer Hauptanwendung enthalten nichts von der gemounteten Anwendung, usw. + +Weitere Informationen hierzu finden Sie im [Handbuch für fortgeschrittene Benutzer](../advanced/index.md). + +## Einzelheiten { #details } + +Das erste `"/static"` bezieht sich auf den Unterpfad, auf dem diese „Unteranwendung“ „gemountet“ wird. Daher wird jeder Pfad, der mit `"/static"` beginnt, von ihr verarbeitet. + +Das `directory="static"` bezieht sich auf den Namen des Verzeichnisses, das Ihre statischen Dateien enthält. + +Das `name="static"` gibt dieser Unteranwendung einen Namen, der intern von **FastAPI** verwendet werden kann. + +Alle diese Parameter können anders als „`static`“ lauten, passen Sie sie an die Bedürfnisse und spezifischen Details Ihrer eigenen Anwendung an. + +## Weitere Informationen { #more-info } + +Weitere Details und Optionen finden Sie in [Starlettes Dokumentation zu statischen Dateien](https://www.starlette.dev/staticfiles/). diff --git a/docs/de/docs/tutorial/stream-json-lines.md b/docs/de/docs/tutorial/stream-json-lines.md new file mode 100644 index 0000000000000..61bf3fafa467d --- /dev/null +++ b/docs/de/docs/tutorial/stream-json-lines.md @@ -0,0 +1,111 @@ +# JSON Lines streamen { #stream-json-lines } + +Sie könnten eine Folge von Daten haben, die Sie in einem „Stream“ senden möchten, das können Sie mit **JSON Lines** tun. + +/// note | Hinweis + +Hinzugefügt in FastAPI 0.134.0. + +/// + +## Was ist ein Stream? { #what-is-a-stream } + +„Streaming“ von Daten bedeutet, dass Ihre App damit beginnt, Datenelemente an den Client zu senden, ohne darauf zu warten, dass die gesamte Folge von Elementen fertig ist. + +Sie sendet also das erste Element, der Client empfängt es und beginnt mit der Verarbeitung, und Sie erzeugen währenddessen möglicherweise bereits das nächste Element. + +```mermaid +sequenceDiagram + participant App + participant Client + + App->>App: Produce Item 1 + App->>Client: Send Item 1 + App->>App: Produce Item 2 + Client->>Client: Process Item 1 + App->>Client: Send Item 2 + App->>App: Produce Item 3 + Client->>Client: Process Item 2 + App->>Client: Send Item 3 + Client->>Client: Process Item 3 + Note over App: Keeps producing... + Note over Client: Keeps consuming... +``` + +Es könnte sogar ein unendlicher Stream sein, bei dem Sie kontinuierlich Daten senden. + +## JSON Lines { #json-lines } + +In diesen Fällen ist es üblich, „JSON Lines“ zu senden, das ist ein Format, bei dem Sie pro Zeile genau ein JSON-Objekt senden. + +Eine Response hätte einen Content-Type von `application/jsonl` (anstelle von `application/json`) und der Body sähe etwa so aus: + +```json +{"name": "Plumbus", "description": "A multi-purpose household device."} +{"name": "Portal Gun", "description": "A portal opening device."} +{"name": "Meeseeks Box", "description": "A box that summons a Meeseeks."} +``` + +Es ist einem JSON-Array (entspricht einer Python-Liste) sehr ähnlich, aber anstatt in `[]` eingeschlossen zu sein und `,` zwischen den Elementen zu haben, gibt es hier **ein JSON-Objekt pro Zeile**, sie sind durch ein Zeilenumbruchzeichen getrennt. + +/// note | Hinweis + +Der wichtige Punkt ist, dass Ihre App in der Lage ist, jede Zeile der Reihe nach zu erzeugen, während der Client die vorherigen Zeilen konsumiert. + +/// + +/// note | Technische Details + +Da jedes JSON-Objekt durch einen Zeilenumbruch getrennt wird, können sie keine wörtlichen Zeilenumbrüche in ihrem Inhalt enthalten, aber sie können escapte Zeilenumbrüche (`\n`) enthalten, das ist Teil des JSON-Standards. + +Normalerweise müssen Sie sich darum aber nicht kümmern, das geschieht automatisch, lesen Sie weiter. 🤓 + +/// + +## Anwendungsfälle { #use-cases } + +Sie könnten dies verwenden, um Daten von einem **AI LLM**-Service, aus **Logs** oder **Telemetrie**, oder aus anderen Typen von Daten zu streamen, die sich in **JSON**-Items strukturieren lassen. + +/// tip | Tipp + +Wenn Sie Binärdaten streamen möchten, zum Beispiel Video oder Audio, sehen Sie sich den erweiterten Leitfaden an: [Daten streamen](../advanced/stream-data.md). + +/// + +## JSON Lines mit FastAPI streamen { #stream-json-lines-with-fastapi } + +Um JSON Lines mit FastAPI zu streamen, können Sie anstelle von `return` in Ihrer *Pfadoperation-Funktion* `yield` verwenden, um jedes Element der Reihe nach zu erzeugen. + +{* ../../docs_src/stream_json_lines/tutorial001_py310.py ln[1:24] hl[24] *} + +Wenn jedes JSON-Item, das Sie zurücksenden möchten, vom Typ `Item` ist (ein Pydantic-Modell) und es sich um eine async-Funktion handelt, können Sie den Rückgabetyp als `AsyncIterable[Item]` deklarieren: + +{* ../../docs_src/stream_json_lines/tutorial001_py310.py ln[1:24] hl[9:11,22] *} + +Wenn Sie den Rückgabetyp deklarieren, wird FastAPI ihn verwenden, um die Daten zu **validieren**, sie in OpenAPI zu **dokumentieren**, sie zu **filtern** und sie mit Pydantic zu **serialisieren**. + +/// tip | Tipp + +Da Pydantic es auf der **Rust**-Seite serialisiert, erhalten Sie eine deutlich höhere **Leistung** als wenn Sie keinen Rückgabetyp deklarieren. + +/// + +### Nicht-async *Pfadoperation-Funktionen* { #non-async-path-operation-functions } + +Sie können auch normale `def`-Funktionen (ohne `async`) verwenden und `yield` auf die gleiche Weise einsetzen. + +FastAPI stellt sicher, dass sie korrekt ausgeführt werden, sodass der Event Loop nicht blockiert wird. + +Da die Funktion in diesem Fall nicht async ist, wäre der richtige Rückgabetyp `Iterable[Item]`: + +{* ../../docs_src/stream_json_lines/tutorial001_py310.py ln[27:30] hl[28] *} + +### Kein Rückgabetyp { #no-return-type } + +Sie können den Rückgabetyp auch weglassen. FastAPI verwendet dann den [`jsonable_encoder`](./encoder.md), um die Daten in etwas zu konvertieren, das zu JSON serialisiert werden kann, und sendet sie anschließend als JSON Lines. + +{* ../../docs_src/stream_json_lines/tutorial001_py310.py ln[33:36] hl[34] *} + +## Server-Sent Events (SSE) { #server-sent-events-sse } + +FastAPI hat außerdem erstklassige Unterstützung für Server-Sent Events (SSE), die dem sehr ähnlich sind, aber ein paar zusätzliche Details mitbringen. Sie können im nächsten Kapitel mehr darüber lernen: [Server-Sent Events (SSE)](server-sent-events.md). 🤓 diff --git a/docs/de/docs/tutorial/testing.md b/docs/de/docs/tutorial/testing.md new file mode 100644 index 0000000000000..59d0be6bb77f9 --- /dev/null +++ b/docs/de/docs/tutorial/testing.md @@ -0,0 +1,194 @@ +# Testen { #testing } + +Dank [Starlette](https://www.starlette.dev/testclient/) ist das Testen von **FastAPI**-Anwendungen einfach und macht Spaß. + +Es basiert auf [HTTPX](https://www.python-httpx.org), welches wiederum auf der Grundlage von Requests konzipiert wurde, es ist also sehr vertraut und intuitiv. + +Damit können Sie [pytest](https://docs.pytest.org/) direkt mit **FastAPI** verwenden. + +## `TestClient` verwenden { #using-testclient } + +/// note | Hinweis + +Um `TestClient` zu verwenden, installieren Sie zunächst [`httpx`](https://www.python-httpx.org). + +Erstellen Sie eine [virtuelle Umgebung](../virtual-environments.md), aktivieren Sie sie und installieren Sie es dann, z. B.: + +```console +$ pip install httpx +``` + +/// + +Importieren Sie `TestClient`. + +Erstellen Sie einen `TestClient`, indem Sie ihm Ihre **FastAPI**-Anwendung übergeben. + +Erstellen Sie Funktionen mit einem Namen, der mit `test_` beginnt (das ist eine Standard-`pytest`-Konvention). + +Verwenden Sie das `TestClient`-Objekt auf die gleiche Weise wie `httpx`. + +Schreiben Sie einfache `assert`-Anweisungen mit den Standard-Python-Ausdrücken, die Sie überprüfen müssen (wiederum, Standard-`pytest`). + +{* ../../docs_src/app_testing/tutorial001_py310.py hl[2,12,15:18] *} + +/// tip | Tipp + +Beachten Sie, dass die Testfunktionen normal `def` und nicht `async def` sind. + +Und die Aufrufe an den Client sind ebenfalls normale Aufrufe, die nicht `await` verwenden. + +Dadurch können Sie `pytest` ohne Komplikationen direkt nutzen. + +/// + +/// note | Technische Details + +Sie könnten auch `from starlette.testclient import TestClient` verwenden. + +**FastAPI** stellt denselben `starlette.testclient` auch via `fastapi.testclient` bereit, als Annehmlichkeit für Sie, den Entwickler. Es kommt aber tatsächlich direkt von Starlette. + +/// + +/// tip | Tipp + +Wenn Sie in Ihren Tests neben dem Senden von Requests an Ihre FastAPI-Anwendung auch `async`-Funktionen aufrufen möchten (z. B. asynchrone Datenbankfunktionen), werfen Sie einen Blick auf die [Async-Tests](../advanced/async-tests.md) im Handbuch für fortgeschrittene Benutzer. + +/// + +## Tests separieren { #separating-tests } + +In einer echten Anwendung würden Sie Ihre Tests wahrscheinlich in einer anderen Datei haben. + +Und Ihre **FastAPI**-Anwendung könnte auch aus mehreren Dateien/Modulen, usw. bestehen. + +### **FastAPI**-Anwendungsdatei { #fastapi-app-file } + +Nehmen wir an, Sie haben eine Dateistruktur wie in [Größere Anwendungen](bigger-applications.md) beschrieben: + +``` +. +├── app +│   ├── __init__.py +│   └── main.py +``` + +In der Datei `main.py` haben Sie Ihre **FastAPI**-Anwendung: + + +{* ../../docs_src/app_testing/app_a_py310/main.py *} + + +### Testdatei { #testing-file } + +Dann könnten Sie eine Datei `test_main.py` mit Ihren Tests haben. Sie könnte sich im selben Python-Package befinden (dasselbe Verzeichnis mit einer `__init__.py`-Datei): + +``` hl_lines="5" +. +├── app +│   ├── __init__.py +│   ├── main.py +│   └── test_main.py +``` + +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_py310/test_main.py hl[3] *} + + +... und haben den Code für die Tests wie zuvor. + +## Testen: erweitertes Beispiel { #testing-extended-example } + +Nun erweitern wir dieses Beispiel und fügen weitere Details hinzu, um zu sehen, wie verschiedene Teile getestet werden. + +### Erweiterte **FastAPI**-Anwendungsdatei { #extended-fastapi-app-file } + +Fahren wir mit der gleichen Dateistruktur wie zuvor fort: + +``` +. +├── app +│   ├── __init__.py +│   ├── main.py +│   └── test_main.py +``` + +Nehmen wir an, dass die Datei `main.py` mit Ihrer **FastAPI**-Anwendung jetzt einige andere **Pfadoperationen** hat. + +Sie verfügt über eine `GET`-Operation, die einen Fehler zurückgeben könnte. + +Sie verfügt über eine `POST`-Operation, die mehrere Fehler zurückgeben könnte. + +Beide *Pfadoperationen* erfordern einen `X-Token`-Header. + +{* ../../docs_src/app_testing/app_b_an_py310/main.py *} + +### Erweiterte Testdatei { #extended-testing-file } + +Anschließend könnten Sie `test_main.py` mit den erweiterten Tests aktualisieren: + +{* ../../docs_src/app_testing/app_b_an_py310/test_main.py *} + + +Immer wenn der Client Informationen im Request übergeben soll und Sie nicht wissen, wie, können Sie danach suchen (googeln), wie es mit `httpx` gemacht wird, oder sogar, wie es mit `requests` gemacht wird, da das Design von HTTPX auf dem Design von Requests basiert. + +Dann machen Sie in Ihren Tests einfach das gleiche. + +Z. B.: + +* Um einen *Pfad*- oder *Query*-Parameter zu übergeben, fügen Sie ihn der URL selbst hinzu. +* Um einen JSON-Body zu übergeben, übergeben Sie ein Python-Objekt (z. B. ein `dict`) an den Parameter `json`. +* Wenn Sie *Formulardaten* anstelle von JSON senden müssen, verwenden Sie stattdessen den `data`-Parameter. +* Um *Header* zu übergeben, verwenden Sie ein `dict` im `headers`-Parameter. +* Für *Cookies* ein `dict` im `cookies`-Parameter. + +Weitere Informationen zum Übergeben von Daten an das Backend (mithilfe von `httpx` oder dem `TestClient`) finden Sie in der [HTTPX-Dokumentation](https://www.python-httpx.org). + +/// note | Hinweis + +Beachten Sie, dass der `TestClient` Daten empfängt, die nach JSON konvertiert werden können, keine Pydantic-Modelle. + +Wenn Sie ein Pydantic-Modell in Ihrem Test haben und dessen Daten während des Testens an die Anwendung senden möchten, können Sie den `jsonable_encoder` verwenden, der in [JSON-kompatibler Encoder](encoder.md) beschrieben wird. + +/// + +## Tests ausführen { #run-it } + +Danach müssen Sie nur noch `pytest` installieren. + +Erstellen Sie eine [virtuelle Umgebung](../virtual-environments.md), aktivieren Sie sie und installieren Sie es dann, z. B.: + +
+ +```console +$ pip install pytest + +---> 100% +``` + +
+ +Es erkennt die Dateien und Tests automatisch, führt sie aus und berichtet Ihnen die Ergebnisse. + +Führen Sie die Tests aus, mit: + +
+ +```console +$ pytest + +================ test session starts ================ +platform linux -- Python 3.6.9, pytest-5.3.5, py-1.8.1, pluggy-0.13.1 +rootdir: /home/user/code/superawesome-cli/app +plugins: forked-1.1.3, xdist-1.31.0, cov-2.8.1 +collected 6 items + +---> 100% + +test_main.py ...... [100%] + +================= 1 passed in 0.03s ================= +``` + +
diff --git a/docs/de/docs/virtual-environments.md b/docs/de/docs/virtual-environments.md new file mode 100644 index 0000000000000..782d1cdcf03a5 --- /dev/null +++ b/docs/de/docs/virtual-environments.md @@ -0,0 +1,864 @@ +# Virtuelle Umgebungen { #virtual-environments } + +Wenn Sie an Python-Projekten arbeiten, sollten Sie wahrscheinlich eine **virtuelle Umgebung** (oder einen ähnlichen Mechanismus) verwenden, um die Packages, die Sie für jedes Projekt installieren, zu isolieren. + +/// note | Hinweis + +Wenn Sie bereits über virtuelle Umgebungen Bescheid wissen, wie man sie erstellt und verwendet, möchten Sie diesen Abschnitt vielleicht überspringen. 🤓 + +/// + +/// tip | Tipp + +Eine **virtuelle Umgebung** unterscheidet sich von einer **Umgebungsvariable**. + +Eine **Umgebungsvariable** ist eine Variable im System, die von Programmen verwendet werden kann. + +Eine **virtuelle Umgebung** ist ein Verzeichnis mit einigen Dateien darin. + +/// + +/// note | Hinweis + +Diese Seite wird Ihnen beibringen, wie Sie **virtuelle Umgebungen** verwenden und wie sie funktionieren. + +Wenn Sie bereit sind, ein **Tool zu verwenden, das alles für Sie verwaltet** (einschließlich der Installation von Python), probieren Sie [uv](https://github.com/astral-sh/uv). + +/// + +## Ein Projekt erstellen { #create-a-project } + +Erstellen Sie zuerst ein Verzeichnis für Ihr Projekt. + +Was ich normalerweise mache, ist, dass ich ein Verzeichnis namens `code` in meinem Home/Benutzerverzeichnis erstelle. + +Und darin erstelle ich ein Verzeichnis pro Projekt. + +
+ +```console +// Gehe zum Home-Verzeichnis +$ cd +// Erstelle ein Verzeichnis für alle Ihre Code-Projekte +$ mkdir code +// Gehe in dieses Code-Verzeichnis +$ cd code +// Erstelle ein Verzeichnis für dieses Projekt +$ mkdir awesome-project +// Gehe in dieses Projektverzeichnis +$ cd awesome-project +``` + +
+ +## Eine virtuelle Umgebung erstellen { #create-a-virtual-environment } + +Wenn Sie zum **ersten Mal** an einem Python-Projekt arbeiten, erstellen Sie eine virtuelle Umgebung **innerhalb Ihres Projekts**. + +/// tip | Tipp + +Sie müssen dies nur **einmal pro Projekt** tun, nicht jedes Mal, wenn Sie daran arbeiten. + +/// + +//// tab | `venv` + +Um eine virtuelle Umgebung zu erstellen, können Sie das `venv`-Modul verwenden, das mit Python geliefert wird. + +
+ +```console +$ python -m venv .venv +``` + +
+ +/// details | Was dieser Befehl bedeutet + +* `python`: das Programm namens `python` verwenden +* `-m`: ein Modul als Skript aufrufen, wir geben als nächstes an, welches Modul +* `venv`: das Modul namens `venv` verwenden, das normalerweise mit Python installiert wird +* `.venv`: die virtuelle Umgebung im neuen Verzeichnis `.venv` erstellen + +/// + +//// + +//// tab | `uv` + +Wenn Sie [`uv`](https://github.com/astral-sh/uv) installiert haben, können Sie es verwenden, um eine virtuelle Umgebung zu erstellen. + +
+ +```console +$ uv venv +``` + +
+ +/// tip | Tipp + +Standardmäßig erstellt `uv` eine virtuelle Umgebung in einem Verzeichnis namens `.venv`. + +Aber Sie könnten es anpassen, indem Sie ein zusätzliches Argument mit dem Verzeichnisnamen übergeben. + +/// + +//// + +Dieser Befehl erstellt eine neue virtuelle Umgebung in einem Verzeichnis namens `.venv`. + +/// details | `.venv` oder ein anderer Name + +Sie könnten die virtuelle Umgebung in einem anderen Verzeichnis erstellen, aber es ist eine Konvention, sie `.venv` zu nennen. + +/// + +## Die virtuelle Umgebung aktivieren { #activate-the-virtual-environment } + +Aktivieren Sie die neue virtuelle Umgebung, damit jeder Python-Befehl, den Sie ausführen oder jedes Paket, das Sie installieren, diese Umgebung verwendet. + +/// tip | Tipp + +Tun Sie dies **jedes Mal**, wenn Sie eine **neue Terminalsitzung** starten, um an dem Projekt zu arbeiten. + +/// + +//// tab | Linux, macOS + +
+ +```console +$ source .venv/bin/activate +``` + +
+ +//// + +//// tab | Windows PowerShell + +
+ +```console +$ .venv\Scripts\Activate.ps1 +``` + +
+ +//// + +//// tab | Windows Bash + +Oder wenn Sie Bash für Windows verwenden (z. B. [Git Bash](https://gitforwindows.org/)): + +
+ +```console +$ source .venv/Scripts/activate +``` + +
+ +//// + +/// tip | Tipp + +Jedes Mal, wenn Sie ein **neues Paket** in dieser Umgebung installieren, aktivieren Sie die Umgebung erneut. + +So stellen Sie sicher, dass, wenn Sie ein **Terminalprogramm (CLI)** verwenden, das durch dieses Paket installiert wurde, Sie das aus Ihrer virtuellen Umgebung verwenden und nicht eines, das global installiert ist, wahrscheinlich mit einer anderen Version als der, die Sie benötigen. + +/// + +## Testen, ob die virtuelle Umgebung aktiv ist { #check-the-virtual-environment-is-active } + +Testen Sie, dass die virtuelle Umgebung aktiv ist (der vorherige Befehl funktioniert hat). + +/// tip | Tipp + +Dies ist **optional**, aber es ist eine gute Möglichkeit, **zu überprüfen**, ob alles wie erwartet funktioniert und Sie die beabsichtigte virtuelle Umgebung verwenden. + +/// + +//// tab | Linux, macOS, Windows Bash + +
+ +```console +$ which python + +/home/user/code/awesome-project/.venv/bin/python +``` + +
+ +Wenn es das `python`-Binary in `.venv/bin/python` anzeigt, innerhalb Ihres Projekts (in diesem Fall `awesome-project`), dann hat es funktioniert. 🎉 + +//// + +//// tab | Windows PowerShell + +
+ +```console +$ Get-Command python + +C:\Users\user\code\awesome-project\.venv\Scripts\python +``` + +
+ +Wenn es das `python`-Binary in `.venv\Scripts\python` anzeigt, innerhalb Ihres Projekts (in diesem Fall `awesome-project`), dann hat es funktioniert. 🎉 + +//// + +## `pip` aktualisieren { #upgrade-pip } + +/// tip | Tipp + +Wenn Sie [`uv`](https://github.com/astral-sh/uv) verwenden, würden Sie das verwenden, um Dinge zu installieren anstelle von `pip`, sodass Sie `pip` nicht aktualisieren müssen. 😎 + +/// + +Wenn Sie `pip` verwenden, um Pakete zu installieren (es wird standardmäßig mit Python geliefert), sollten Sie es auf die neueste Version **aktualisieren**. + +Viele exotische Fehler beim Installieren eines Pakets werden einfach dadurch gelöst, dass zuerst `pip` aktualisiert wird. + +/// tip | Tipp + +Normalerweise würden Sie dies **einmal** tun, unmittelbar nachdem Sie die virtuelle Umgebung erstellt haben. + +/// + +Stellen Sie sicher, dass die virtuelle Umgebung aktiv ist (mit dem obigen Befehl) und führen Sie dann aus: + +
+ +```console +$ python -m pip install --upgrade pip + +---> 100% +``` + +
+ +/// 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: + +
+ +```console +$ python -m ensurepip --upgrade + +---> 100% +``` + +
+ +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 } + +Wenn Sie **Git** verwenden (was Sie sollten), fügen Sie eine `.gitignore`-Datei hinzu, um alles in Ihrem `.venv` von Git auszuschließen. + +/// tip | Tipp + +Wenn Sie [`uv`](https://github.com/astral-sh/uv) verwendet haben, um die virtuelle Umgebung zu erstellen, hat es dies bereits für Sie getan, Sie können diesen Schritt überspringen. 😎 + +/// + +/// tip | Tipp + +Tun Sie dies **einmal**, unmittelbar nachdem Sie die virtuelle Umgebung erstellt haben. + +/// + +
+ +```console +$ echo "*" > .venv/.gitignore +``` + +
+ +/// details | Was dieser Befehl bedeutet + +* `echo "*"`: wird den Text `*` im Terminal „drucken“ (der nächste Teil ändert das ein wenig) +* `>`: alles, was durch den Befehl links von `>` im Terminal ausgegeben wird, sollte nicht gedruckt, sondern stattdessen in die Datei geschrieben werden, die rechts von `>` kommt +* `.gitignore`: der Name der Datei, in die der Text geschrieben werden soll + +Und `*` bedeutet für Git „alles“. Also wird alles im `.venv`-Verzeichnis ignoriert. + +Dieser Befehl erstellt eine Datei `.gitignore` mit dem Inhalt: + +```gitignore +* +``` + +/// + +## Pakete installieren { #install-packages } + +Nachdem Sie die Umgebung aktiviert haben, können Sie Pakete darin installieren. + +/// tip | Tipp + +Tun Sie dies **einmal**, wenn Sie die Pakete installieren oder aktualisieren, die Ihr Projekt benötigt. + +Wenn Sie eine Version aktualisieren oder ein neues Paket hinzufügen müssen, würden Sie **dies erneut tun**. + +/// + +### Pakete direkt installieren { #install-packages-directly } + +Wenn Sie es eilig haben und keine Datei verwenden möchten, um die Paketanforderungen Ihres Projekts zu deklarieren, können Sie sie direkt installieren. + +/// tip | Tipp + +Es ist eine (sehr) gute Idee, die Pakete und Versionen, die Ihr Programm benötigt, in einer Datei zu speichern (zum Beispiel `requirements.txt` oder `pyproject.toml`). + +/// + +//// tab | `pip` + +
+ +```console +$ pip install "fastapi[standard]" + +---> 100% +``` + +
+ +//// + +//// tab | `uv` + +Wenn Sie [`uv`](https://github.com/astral-sh/uv) haben: + +
+ +```console +$ uv pip install "fastapi[standard]" +---> 100% +``` + +
+ +//// + +### Installation von `requirements.txt` { #install-from-requirements-txt } + +Wenn Sie eine `requirements.txt` haben, können Sie diese nun verwenden, um deren Pakete zu installieren. + +//// tab | `pip` + +
+ +```console +$ pip install -r requirements.txt +---> 100% +``` + +
+ +//// + +//// tab | `uv` + +Wenn Sie [`uv`](https://github.com/astral-sh/uv) haben: + +
+ +```console +$ uv pip install -r requirements.txt +---> 100% +``` + +
+ +//// + +/// details | `requirements.txt` + +Eine `requirements.txt` mit einigen Paketen könnte folgendermaßen aussehen: + +```requirements.txt +fastapi[standard]==0.113.0 +pydantic==2.8.0 +``` + +/// + +## Ihr Programm ausführen { #run-your-program } + +Nachdem Sie die virtuelle Umgebung aktiviert haben, können Sie Ihr Programm ausführen, und es wird das Python innerhalb Ihrer virtuellen Umgebung mit den Paketen verwenden, die Sie dort installiert haben. + +
+ +```console +$ python main.py + +Hello World +``` + +
+ +## Ihren Editor konfigurieren { #configure-your-editor } + +Sie würden wahrscheinlich einen Editor verwenden, stellen Sie sicher, dass Sie ihn so konfigurieren, dass er dieselbe virtuelle Umgebung verwendet, die Sie erstellt haben (er wird sie wahrscheinlich automatisch erkennen), sodass Sie Autovervollständigungen und Inline-Fehler erhalten können. + +Zum Beispiel: + +* [VS Code](https://code.visualstudio.com/docs/python/environments#_select-and-activate-an-environment) +* [PyCharm](https://www.jetbrains.com/help/pycharm/creating-virtual-environment.html) + +/// tip | Tipp + +Normalerweise müssen Sie dies nur **einmal** tun, wenn Sie die virtuelle Umgebung erstellen. + +/// + +## Die virtuelle Umgebung deaktivieren { #deactivate-the-virtual-environment } + +Sobald Sie mit der Arbeit an Ihrem Projekt fertig sind, können Sie die virtuelle Umgebung **deaktivieren**. + +
+ +```console +$ deactivate +``` + +
+ +Auf diese Weise, wenn Sie `python` ausführen, wird nicht versucht, es aus dieser virtuellen Umgebung mit den dort installierten Paketen auszuführen. + +## Bereit zu arbeiten { #ready-to-work } + +Jetzt sind Sie bereit, mit Ihrem Projekt zu arbeiten. + + + +/// tip | Tipp + +Möchten Sie verstehen, was das alles oben bedeutet? + +Lesen Sie weiter. 👇🤓 + +/// + +## Warum virtuelle Umgebungen { #why-virtual-environments } + +Um mit FastAPI zu arbeiten, müssen Sie [Python](https://www.python.org/) installieren. + +Danach müssen Sie FastAPI und alle anderen **Pakete**, die Sie verwenden möchten, **installieren**. + +Um Pakete zu installieren, würden Sie normalerweise den `pip`-Befehl verwenden, der mit Python geliefert wird (oder ähnliche Alternativen). + +Wenn Sie jedoch `pip` direkt verwenden, werden die Pakete in Ihrer **globalen Python-Umgebung** (der globalen Installation von Python) installiert. + +### Das Problem { #the-problem } + +Was ist also das Problem beim Installieren von Paketen in der globalen Python-Umgebung? + +Irgendwann werden Sie wahrscheinlich viele verschiedene Programme schreiben, die von **verschiedenen Paketen** abhängen. Und einige dieser Projekte, an denen Sie arbeiten, werden von **verschiedenen Versionen** desselben Pakets abhängen. 😱 + +Zum Beispiel könnten Sie ein Projekt namens `philosophers-stone` erstellen, dieses Programm hängt von einem anderen Paket namens **`harry`, Version `1`** ab. Also müssen Sie `harry` installieren. + +```mermaid +flowchart LR + stone(philosophers-stone) -->|benötigt| harry-1[harry v1] +``` + +Dann erstellen Sie zu einem späteren Zeitpunkt ein weiteres Projekt namens `prisoner-of-azkaban`, und dieses Projekt hängt ebenfalls von `harry` ab, aber dieses Projekt benötigt **`harry` Version `3`**. + +```mermaid +flowchart LR + azkaban(prisoner-of-azkaban) --> |benötigt| harry-3[harry v3] +``` + +Aber jetzt ist das Problem, wenn Sie die Pakete global (in der globalen Umgebung) installieren anstatt in einer lokalen **virtuellen Umgebung**, müssen Sie wählen, welche Version von `harry` zu installieren ist. + +Wenn Sie `philosophers-stone` ausführen möchten, müssen Sie zuerst `harry` Version `1` installieren, zum Beispiel mit: + +
+ +```console +$ pip install "harry==1" +``` + +
+ +Und dann hätten Sie `harry` Version `1` in Ihrer globalen Python-Umgebung installiert. + +```mermaid +flowchart LR + subgraph global[globale Umgebung] + harry-1[harry v1] + end + subgraph stone-project[philosophers-stone-Projekt] + stone(philosophers-stone) -->|benötigt| harry-1 + end +``` + +Aber dann, wenn Sie `prisoner-of-azkaban` ausführen möchten, müssen Sie `harry` Version `1` deinstallieren und `harry` Version `3` installieren (oder einfach die Version `3` installieren, was die Version `1` automatisch deinstallieren würde). + +
+ +```console +$ pip install "harry==3" +``` + +
+ +Und dann hätten Sie `harry` Version `3` in Ihrer globalen Python-Umgebung installiert. + +Und wenn Sie versuchen, `philosophers-stone` erneut auszuführen, besteht die Möglichkeit, dass es **nicht funktioniert**, weil es `harry` Version `1` benötigt. + +```mermaid +flowchart LR + subgraph global[globale Umgebung] + harry-1[harry v1] + style harry-1 fill:#ccc,stroke-dasharray: 5 5 + harry-3[harry v3] + end + subgraph stone-project[philosophers-stone-Projekt] + stone(philosophers-stone) -.-x|⛔️| harry-1 + end + subgraph azkaban-project[prisoner-of-azkaban-Projekt] + azkaban(prisoner-of-azkaban) --> |benötigt| harry-3 + end +``` + +/// tip | Tipp + +Es ist sehr üblich in Python-Paketen, alles zu versuchen, **Breaking Changes** in **neuen Versionen** zu vermeiden, aber es ist besser, auf Nummer sicher zu gehen und neue Versionen absichtlich zu installieren und wenn Sie die Tests ausführen können, sicherzustellen, dass alles korrekt funktioniert. + +/// + +Stellen Sie sich das jetzt mit **vielen** anderen **Paketen** vor, von denen alle Ihre **Projekte abhängen**. Das ist sehr schwierig zu verwalten. Und Sie würden wahrscheinlich einige Projekte mit einigen **inkompatiblen Versionen** der Pakete ausführen und nicht wissen, warum etwas nicht funktioniert. + +Darüber hinaus könnte es je nach Ihrem Betriebssystem (z. B. Linux, Windows, macOS) bereits mit installiertem Python geliefert worden sein. Und in diesem Fall hatte es wahrscheinlich einige Pakete mit bestimmten Versionen **installiert**, die von Ihrem System benötigt werden. Wenn Sie Pakete in der globalen Python-Umgebung installieren, könnten Sie einige der Programme, die mit Ihrem Betriebssystem geliefert wurden, **kaputtmachen**. + +## Wo werden Pakete installiert { #where-are-packages-installed } + +Wenn Sie Python installieren, werden einige Verzeichnisse mit einigen Dateien auf Ihrem Rechner erstellt. + +Einige dieser Verzeichnisse sind dafür zuständig, alle Pakete, die Sie installieren, aufzunehmen. + +Wenn Sie ausführen: + +
+ +```console +// Führen Sie dies jetzt nicht aus, es ist nur ein Beispiel 🤓 +$ pip install "fastapi[standard]" +---> 100% +``` + +
+ +Das lädt eine komprimierte Datei mit dem FastAPI-Code herunter, normalerweise von [PyPI](https://pypi.org/project/fastapi/). + +Es wird auch Dateien für andere Pakete **herunterladen**, von denen FastAPI abhängt. + +Dann wird es all diese Dateien **extrahieren** und sie in ein Verzeichnis auf Ihrem Rechner legen. + +Standardmäßig werden diese heruntergeladenen und extrahierten Dateien in das Verzeichnis gelegt, das mit Ihrer Python-Installation kommt, das ist die **globale Umgebung**. + +## Was sind virtuelle Umgebungen { #what-are-virtual-environments } + +Die Lösung für die Probleme, alle Pakete in der globalen Umgebung zu haben, besteht darin, eine **virtuelle Umgebung für jedes Projekt** zu verwenden, an dem Sie arbeiten. + +Eine virtuelle Umgebung ist ein **Verzeichnis**, sehr ähnlich zu dem globalen, in dem Sie die Pakete für ein Projekt installieren können. + +Auf diese Weise hat jedes Projekt seine eigene virtuelle Umgebung (`.venv`-Verzeichnis) mit seinen eigenen Paketen. + +```mermaid +flowchart TB + subgraph stone-project[philosophers-stone-Projekt] + stone(philosophers-stone) --->|benötigt| harry-1 + subgraph venv1[.venv] + harry-1[harry v1] + end + end + subgraph azkaban-project[prisoner-of-azkaban-Projekt] + azkaban(prisoner-of-azkaban) --->|benötigt| harry-3 + subgraph venv2[.venv] + harry-3[harry v3] + end + end + stone-project ~~~ azkaban-project +``` + +## Was bedeutet das Aktivieren einer virtuellen Umgebung { #what-does-activating-a-virtual-environment-mean } + +Wenn Sie eine virtuelle Umgebung aktivieren, zum Beispiel mit: + +//// tab | Linux, macOS + +
+ +```console +$ source .venv/bin/activate +``` + +
+ +//// + +//// tab | Windows PowerShell + +
+ +```console +$ .venv\Scripts\Activate.ps1 +``` + +
+ +//// + +//// tab | Windows Bash + +Oder wenn Sie Bash für Windows verwenden (z. B. [Git Bash](https://gitforwindows.org/)): + +
+ +```console +$ source .venv/Scripts/activate +``` + +
+ +//// + +Dieser Befehl erstellt oder ändert einige [Umgebungsvariablen](environment-variables.md), die für die nächsten Befehle verfügbar sein werden. + +Eine dieser Variablen ist die `PATH`-Variable. + +/// tip | Tipp + +Sie können mehr über die `PATH`-Umgebungsvariable im Abschnitt [Umgebungsvariablen](environment-variables.md#path-environment-variable) erfahren. + +/// + +Das Aktivieren einer virtuellen Umgebung fügt deren Pfad `.venv/bin` (auf Linux und macOS) oder `.venv\Scripts` (auf Windows) zur `PATH`-Umgebungsvariable hinzu. + +Angenommen, die `PATH`-Variable sah vor dem Aktivieren der Umgebung so aus: + +//// tab | Linux, macOS + +```plaintext +/usr/bin:/bin:/usr/sbin:/sbin +``` + +Das bedeutet, dass das System nach Programmen sucht in: + +* `/usr/bin` +* `/bin` +* `/usr/sbin` +* `/sbin` + +//// + +//// tab | Windows + +```plaintext +C:\Windows\System32 +``` + +Das bedeutet, dass das System nach Programmen sucht in: + +* `C:\Windows\System32` + +//// + +Nach dem Aktivieren der virtuellen Umgebung würde die `PATH`-Variable folgendermaßen aussehen: + +//// tab | Linux, macOS + +```plaintext +/home/user/code/awesome-project/.venv/bin:/usr/bin:/bin:/usr/sbin:/sbin +``` + +Das bedeutet, dass das System nun zuerst nach Programmen sucht in: + +```plaintext +/home/user/code/awesome-project/.venv/bin +``` + +bevor es in den anderen Verzeichnissen sucht. + +Wenn Sie also `python` im Terminal eingeben, wird das System das Python-Programm in + +```plaintext +/home/user/code/awesome-project/.venv/bin/python +``` + +finden und dieses verwenden. + +//// + +//// tab | Windows + +```plaintext +C:\Users\user\code\awesome-project\.venv\Scripts;C:\Windows\System32 +``` + +Das bedeutet, dass das System nun zuerst nach Programmen sucht in: + +```plaintext +C:\Users\user\code\awesome-project\.venv\Scripts +``` + +bevor es in den anderen Verzeichnissen sucht. + +Wenn Sie also `python` im Terminal eingeben, wird das System das Python-Programm in + +```plaintext +C:\Users\user\code\awesome-project\.venv\Scripts\python +``` + +finden und dieses verwenden. + +//// + +Ein wichtiger Punkt ist, dass es den Pfad der virtuellen Umgebung am **Anfang** der `PATH`-Variable platziert. Das System wird es **vor** allen anderen verfügbaren Pythons finden. Auf diese Weise, wenn Sie `python` ausführen, wird das Python **aus der virtuellen Umgebung** verwendet anstelle eines anderen `python` (zum Beispiel, einem `python` aus einer globalen Umgebung). + +Das Aktivieren einer virtuellen Umgebung ändert auch ein paar andere Dinge, aber dies ist eines der wichtigsten Dinge, die es tut. + +## Testen einer virtuellen Umgebung { #checking-a-virtual-environment } + +Wenn Sie testen, ob eine virtuelle Umgebung aktiv ist, zum Beispiel mit: + +//// tab | Linux, macOS, Windows Bash + +
+ +```console +$ which python + +/home/user/code/awesome-project/.venv/bin/python +``` + +
+ +//// + +//// tab | Windows PowerShell + +
+ +```console +$ Get-Command python + +C:\Users\user\code\awesome-project\.venv\Scripts\python +``` + +
+ +//// + +bedeutet das, dass das `python`-Programm, das verwendet wird, das in der **virtuellen Umgebung** ist. + +Sie verwenden `which` auf Linux und macOS und `Get-Command` in Windows PowerShell. + +So funktioniert dieser Befehl: Er wird in der `PATH`-Umgebungsvariable nachsehen und **jeden Pfad in der Reihenfolge durchgehen**, um das Programm namens `python` zu finden. Sobald er es findet, wird er Ihnen **den Pfad** zu diesem Programm anzeigen. + +Der wichtigste Punkt ist, dass, wenn Sie `python` aufrufen, genau dieses „`python`“ ausgeführt wird. + +So können Sie überprüfen, ob Sie sich in der richtigen virtuellen Umgebung befinden. + +/// tip | Tipp + +Es ist einfach, eine virtuelle Umgebung zu aktivieren, ein Python zu bekommen und dann **zu einem anderen Projekt zu wechseln**. + +Und das zweite Projekt **würde nicht funktionieren**, weil Sie das **falsche Python** verwenden, aus einer virtuellen Umgebung für ein anderes Projekt. + +Es ist nützlich, überprüfen zu können, welches `python` verwendet wird. 🤓 + +/// + +## Warum eine virtuelle Umgebung deaktivieren { #why-deactivate-a-virtual-environment } + +Zum Beispiel könnten Sie an einem Projekt `philosophers-stone` arbeiten, diese virtuelle Umgebung **aktivieren**, Pakete installieren und mit dieser Umgebung arbeiten. + +Und dann möchten Sie an **einem anderen Projekt** `prisoner-of-azkaban` arbeiten. + +Sie gehen zu diesem Projekt: + +
+ +```console +$ cd ~/code/prisoner-of-azkaban +``` + +
+ +Wenn Sie die virtuelle Umgebung für `philosophers-stone` nicht deaktivieren, wird beim Ausführen von `python` im Terminal versucht, das Python von `philosophers-stone` zu verwenden. + +
+ +```console +$ cd ~/code/prisoner-of-azkaban + +$ python main.py + +// Fehler beim Importieren von sirius, es ist nicht installiert 😱 +Traceback (most recent call last): + File "main.py", line 1, in + import sirius +``` + +
+ +Wenn Sie jedoch die virtuelle Umgebung deaktivieren und die neue für `prisoner-of-azkaban` aktivieren, wird beim Ausführen von `python` das Python aus der virtuellen Umgebung in `prisoner-of-azkaban` verwendet. + +
+ +```console +$ cd ~/code/prisoner-of-azkaban + +// Sie müssen nicht im alten Verzeichnis sein, um zu deaktivieren, Sie können dies überall tun, sogar nachdem Sie zum anderen Projekt gewechselt haben 😎 +$ deactivate + +// Die virtuelle Umgebung in prisoner-of-azkaban/.venv 🚀 aktivieren +$ source .venv/bin/activate + +// Jetzt, wenn Sie python ausführen, wird das Paket sirius in dieser virtuellen Umgebung gefunden ✨ +$ python main.py + +I solemnly swear 🐺 +``` + +
+ +## Alternativen { #alternatives } + +Dies ist ein einfacher Leitfaden, um Ihnen den Einstieg zu erleichtern und Ihnen beizubringen, wie alles **unter der Haube** funktioniert. + +Es gibt viele **Alternativen** zur Verwaltung von virtuellen Umgebungen, Paketabhängigkeiten (Anforderungen), Projekten. + +Sobald Sie bereit sind und ein Tool verwenden möchten, das **das gesamte Projekt verwaltet**, Paketabhängigkeiten, virtuelle Umgebungen usw., würde ich Ihnen vorschlagen, [uv](https://github.com/astral-sh/uv) auszuprobieren. + +`uv` kann viele Dinge tun, es kann: + +* **Python für Sie installieren**, einschließlich verschiedener Versionen +* Die **virtuelle Umgebung** für Ihre Projekte verwalten +* **Pakete installieren** +* Paket**abhängigkeiten und Versionen** für Ihr Projekt verwalten +* Sicherstellen, dass Sie eine **exakte** Menge an Paketen und Versionen zur Installation haben, einschließlich ihrer Abhängigkeiten, damit Sie sicher sein können, dass Sie Ihr Projekt in der Produktionsumgebung genauso ausführen können wie auf Ihrem Rechner während der Entwicklung, dies wird **Locking** genannt +* Und viele andere Dinge + +## Fazit { #conclusion } + +Wenn Sie das alles gelesen und verstanden haben, wissen Sie jetzt **viel mehr** über virtuelle Umgebungen als viele Entwickler da draußen. 🤓 + +Das Wissen über diese Details wird in Zukunft wahrscheinlich nützlich sein, wenn Sie etwas debuggen, das komplex erscheint, aber Sie werden wissen, **wie alles unter der Haube funktioniert**. 😎 diff --git a/docs/de/llm-prompt.md b/docs/de/llm-prompt.md new file mode 100644 index 0000000000000..2d345bf6d1209 --- /dev/null +++ b/docs/de/llm-prompt.md @@ -0,0 +1,324 @@ +### Target language + +Translate to German (Deutsch). + +Language code: de. + +### Grammar to use when talking to the reader + +Use the formal grammar (use `Sie` instead of `Du`). + +### Quotes + +1) Convert neutral double quotes (`"`) to German double typographic quotes (`„` and `“`). Convert neutral single quotes (`'`) to German single typographic quotes (`‚` and `‘`). + +Do NOT convert quotes in code snippets and code blocks to their German typographic equivalents. + +Examples: + +Source (English): + +``` +"Hello world" +“Hello Universe” +"He said: 'Hello'" +“my name is ‘Nils’” +`"__main__"` +`"items"` +``` + +Result (German): + +``` +„Hallo Welt“ +„Hallo Universum“ +„Er sagte: ‚Hallo‘“ +„Mein Name ist ‚Nils‘“ +`"__main__"` +`"items"` +``` + +### Ellipsis + +- Make sure there is a space between an ellipsis and a word following or preceding the ellipsis. + +Examples: + +Source (English): + +``` +...as we intended. +...this would work: +...etc. +others... +More to come... +``` + +Result (German): + +``` +... wie wir es beabsichtigt hatten. +... das würde funktionieren: +... usw. +Andere ... +Später mehr ... +``` + +- This does not apply in URLs, code blocks, and code snippets. Do not remove or add spaces there. + +### Headings + +- Translate headings using the infinite form. + +Examples: + +Source (English): + +``` +## Create a Project { #create-a-project } +``` + +Result (German): + +``` +## Ein Projekt erstellen { #create-a-project } +``` + +Do NOT translate with (German): + +``` +## Erstellen Sie ein Projekt { #create-a-project } +``` + +Source (English): + +``` +# Install Packages { #install-packages } +``` + +Translate with (German): + +``` +# Pakete installieren { #install-packages } +``` + +Do NOT translate with (German): + +``` +# Installieren Sie Pakete { #install-packages } +``` + +Source (English): + +``` +### Run Your Program { #run-your-program } +``` + +Translate with (German): + +``` +### Ihr Programm ausführen { #run-your-program } +``` + +Do NOT translate with (German): + +``` +### Führen Sie Ihr Programm aus { #run-your-program } +``` + +- Make sure that the translated part of the heading does not end with a period. + +Example: + +Source (English): + +``` +## Another module with `APIRouter` { #another-module-with-apirouter } +``` + +Translate with (German): + +``` +## Ein weiteres Modul mit `APIRouter` { #another-module-with-apirouter } +``` + +Do NOT translate with (German) – notice the added period: + +``` +## Ein weiteres Modul mit `APIRouter`. { #another-module-with-apirouter } +``` + +- Replace occurrences of literal ` - ` (a space followed by a hyphen followed by a space) with ` – ` (a space followed by a dash followed by a space) in the translated part of the heading. + +Example: + +Source (English): + +``` +# FastAPI in Containers - Docker { #fastapi-in-containers-docker } +``` + +Translate with (German) – notice the dash: + +``` +# FastAPI in Containern – Docker { #fastapi-in-containers-docker } +``` + +Do NOT translate with (German) – notice the hyphen: + +``` +# FastAPI in Containern - Docker { #fastapi-in-containers-docker } +``` + +- Do not apply rule 3 when there is no space before or no space after the hyphen. + +Example: + +Source (English): + +``` +## Type hints and annotations { #type-hints-and-annotations } +``` + +Translate with (German) - notice the hyphen: + +``` +## Typhinweise und -annotationen { #type-hints-and-annotations } +``` + +Do NOT translate with (German) - notice the dash: + +``` +## Typhinweise und –annotationen { #type-hints-and-annotations } +``` + +- Do not modify the hyphens in the content in headers inside of curly braces, which you shall not translate. + +### German instructions, when to use and when not to use hyphens in words (written in first person, which is you). + +In der Regel versuche ich so weit wie möglich Worte zusammenzuschreiben, also ohne Bindestrich, es sei denn, es ist Konkretesding-Klassevondingen, etwa «Pydantic-Modell» (aber: «Datenbankmodell»), «Python-Modul» (aber: «Standardmodul»). Ich setze auch einen Bindestrich, wenn er die gleichen Buchstaben verbindet, etwa «Enum-Member», «Cloud-Dienst», «Template-Engine». Oder wenn das Wort sonst einfach zu lang wird, etwa, «Performance-Optimierung». Oder um etwas visuell besser zu dokumentieren, etwa «Pfadoperation-Dekorator», «Pfadoperation-Funktion». + + +### German instructions about difficult to translate technical terms (written in first person, which is you) + +Ich versuche nicht, alles einzudeutschen. Das bezieht sich besonders auf Begriffe aus dem Bereich der Programmierung. Ich wandele zwar korrekt in Großschreibung um und setze Bindestriche, wo notwendig, aber ansonsten lasse ich solch ein Wort unverändert. Beispielsweise wird aus dem englischen Wort «string» in der deutschen Übersetzung «String», aber nicht «Zeichenkette». Oder aus dem englischen Wort «request body» wird in der deutschen Übersetzung «Requestbody», aber nicht «Anfragekörper». Oder aus dem englischen «response» wird im Deutschen «Response», aber nicht «Antwort». + +### List of English terms and their preferred German translations + +Below is a list of English terms and their preferred German translations, separated by a colon (:). Use these translations, do not use your own. If an existing translation does not use these terms, update it to use them. In the below list, a term or a translation may be followed by an explanation in brackets, which explains when to translate the term this way. If a translation is preceded by `NOT`, then that means: do NOT use this translation for this term. English nouns, starting with the word `the`, have the German genus – `der`, `die`, `das` – prepended to their German translation, to help you to grammatically decline them in the translation. They are given in singular case, unless they have `(plural)` attached, which means they are given in plural case. Verbs are given in the full infinitive – starting with the word `to`. + +* /// check: /// check | Testen +* /// danger: /// danger | Gefahr +* /// info: /// info | Info +* /// note | Technical Details: /// note | Technische Details +* /// note: /// note | Hinweis +* /// tip: /// tip | Tipp +* /// warning: /// warning | Achtung +* you: Sie +* your: Ihr +* e.g: z. B. +* etc.: usw. +* ref: Ref. +* the Tutorial - User guide: das Tutorial – Benutzerhandbuch +* the Advanced User Guide: das Handbuch für fortgeschrittene Benutzer +* the SQLModel docs: die SQLModel-Dokumentation +* the docs: die Dokumentation (use singular case) +* the env var: die Umgebungsvariable +* the `PATH` environment variable: die `PATH`-Umgebungsvariable +* the `PATH`: der `PATH` +* the `requirements.txt`: die `requirements.txt` +* the API Router: der API-Router +* the Authorization-Header: der Autorisierungsheader +* the `Authorization`-Header: der `Authorization`-Header +* the background task: der Hintergrundtask +* the button: der Button +* the cloud provider: der Cloudanbieter +* the CLI: Das CLI +* the coverage: Die Testabdeckung +* the command line interface: Das Kommandozeileninterface +* the default value: der Defaultwert +* the default value: NOT der Standardwert +* the default declaration: die Default-Deklaration +* the deployment: das Deployment +* the dict: das Dict +* the dictionary: das Dictionary +* the enumeration: die Enumeration +* the enum: das Enum +* the engine: die Engine +* the error response: die Error-Response +* the event: das Event +* the exception: die Exception +* the exception handler: der Exceptionhandler +* the form model: das Formularmodell +* the form body: der Formularbody +* the header: der Header +* the headers (plural): die Header +* in headers (plural): in Headern +* the forwarded header: der Forwarded-Header +* the lifespan event: das Lifespan-Event +* the lock: der Lock +* the locking: das Locking +* the mobile application: die Mobile-Anwendung +* the model object: das Modellobjekt +* the mounting: das Mounten +* mounted: gemountet +* the origin: das Origin +* the override: Die Überschreibung +* the parameter: der Parameter +* the parameters (plural): die Parameter +* the function parameter: der Funktionsparameter +* the default parameter: der Defaultparameter +* the body parameter: der Body-Parameter +* the request body parameter: der Requestbody-Parameter +* the path parameter: der Pfad-Parameter +* the query parameter: der Query-Parameter +* the cookie parameter: der Cookie-Parameter +* the header parameter: der Header-Parameter +* the form parameter: der Formular-Parameter +* the payload: die Payload +* the performance: NOT die Performance +* the query: die Query +* the recap: die Zusammenfassung +* the request (what the client sends to the server): der Request +* the request body: der Requestbody +* the request bodies (plural): die Requestbodys +* the response (what the server sends back to the client): die Response +* the return type: der Rückgabetyp +* the return value: der Rückgabewert +* the startup (the event of the app): der Startup +* the shutdown (the event of the app): der Shutdown +* the startup event: das Startup-Event +* the shutdown event: das Shutdown-Event +* the startup (of the server): das Hochfahren +* the startup (the company): das Startup +* the SDK: das SDK +* the tag: der Tag +* the type annotation: die Typannotation +* the type hint: der Typhinweis +* the wildcard: die Wildcard +* the worker class: die Workerklasse +* the worker class: NOT die Arbeiterklasse +* the worker process: der Workerprozess +* the worker process: NOT der Arbeiterprozess +* to commit: committen +* to deploy (in the cloud): deployen +* to modify: ändern +* to serve (an application): bereitstellen +* to serve (a response): ausliefern +* to serve: NOT bedienen +* to upgrade: aktualisieren +* to wrap: wrappen +* to wrap: NOT hüllen +* `foo` as a `type`: `foo` vom Typ `type` +* `foo` as a `type`: `foo`, ein `type` +* FastAPI's X: FastAPIs X +* Starlette's Y: Starlettes Y +* X is case-sensitive: Groß-/Klein­schrei­bung ist relevant in X +* X is case-insensitive: Groß-/Klein­schrei­bung ist nicht relevant in X +* standard Python: Standard-Python +* deprecated: deprecatet + + +### Other rules + +Preserve indentation. Keep emojis. Encode in utf-8. Use Linux line breaks (LF). diff --git a/docs/deployment.md b/docs/deployment.md deleted file mode 100644 index 4f9c94a3947d8..0000000000000 --- a/docs/deployment.md +++ /dev/null @@ -1,274 +0,0 @@ -You can use **Docker** for deployment. It has several advantages like security, replicability, development simplicity, etc. - -In this section you'll see instructions and links to guides to know how to: - -* Make your **FastAPI** application a Docker image/container with maximum performance. In about **5 min**. -* (Optionally) understand what you, as a developer, need to know about HTTPS. -* Set up a Docker Swarm mode cluster with automatic HTTPS, even on a simple $5 USD/month server. In about **20 min**. -* Generate and deploy a full **FastAPI** application, using your Docker Swarm cluster, with HTTPS, etc. In about **10 min**. - ---- - -You can also easily use **FastAPI** in a standard server directly too (without Docker). - - -## Docker - -If you are using Docker, you can use the official Docker image: - -### tiangolo/uvicorn-gunicorn-fastapi - -This image has an "auto-tuning" mechanism included, so that you can just add your code and get very high performance automatically. And without making sacrifices. - -But you can still change and update all the configurations with environment variables or configuration files. - -!!! tip - To see all the configurations and options, go to the Docker image page: tiangolo/uvicorn-gunicorn-fastapi. - - -### Create a `Dockerfile` - -* Go to your project directory. -* Create a `Dockerfile` with: - -```Dockerfile -FROM tiangolo/uvicorn-gunicorn-fastapi:python3.7 - -COPY ./app /app -``` - -#### Bigger Applications - -If you followed the section about creating Bigger Applications with Multiple Files -, your `Dockerfile` might instead look like: - -```Dockerfile -FROM tiangolo/uvicorn-gunicorn-fastapi:python3.7 - -COPY ./app /app/app -``` - -#### Raspberry Pi and other architectures - -If you are running Docker in a Raspberry Pi (that has an ARM processor) or any other architecture, you can create a `Dockerfile` from scratch, based on a Python base image (that is multi-architecture) and use Uvicorn alone. - -In this case, your `Dockerfile` could look like: - -```Dockerfile -FROM python:3.7 - -RUN pip install fastapi uvicorn - -EXPOSE 80 - -COPY ./app /app - -CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80"] -``` - -### Create the **FastAPI** Code - -* Create an `app` directory and enter in it. -* Create a `main.py` file with: - -```Python -from fastapi import FastAPI - -app = FastAPI() - - -@app.get("/") -def read_root(): - return {"Hello": "World"} - - -@app.get("/items/{item_id}") -def read_item(item_id: int, q: str = None): - return {"item_id": item_id, "q": q} -``` - -* You should now have a directory structure like: - -``` -. -├── app -│ └── main.py -└── Dockerfile -``` - -### Build the Docker image - -* Go to the project directory (in where your `Dockerfile` is, containing your `app` directory). -* Build your FastAPI image: - -```bash -docker build -t myimage . -``` - -### Start the Docker container - -* Run a container based on your image: - -```bash -docker run -d --name mycontainer -p 80:80 myimage -``` - -Now you have an optimized FastAPI server in a Docker container. Auto-tuned for your current server (and number of CPU cores). - - -### Check it - -You should be able to check it in your Docker container's URL, for example: http://192.168.99.100/items/5?q=somequery or http://127.0.0.1/items/5?q=somequery (or equivalent, using your Docker host). - -You will see something like: - -```JSON -{"item_id": 5, "q": "somequery"} -``` - - -### Interactive API docs - -Now you can go to http://192.168.99.100/docs or http://127.0.0.1/docs (or equivalent, using your Docker host). - -You will see the automatic interactive API documentation (provided by Swagger UI): - -![Swagger UI](https://fastapi.tiangolo.com/img/index/index-01-swagger-ui-simple.png) - - -### Alternative API docs - -And you can also go to http://192.168.99.100/redoc or http://127.0.0.1/redoc (or equivalent, using your Docker host). - -You will see the alternative automatic documentation (provided by ReDoc): - -![ReDoc](https://fastapi.tiangolo.com/img/index/index-02-redoc-simple.png) - - -## HTTPS - -### About HTTPS - -It is easy to assume that HTTPS is something that is just "enabled" or not. - -But it is way more complex than that. - -!!! tip - If you are in a hurry or don't care, continue with the next section for step by step instructions to set everything up. - -To learn the basics of HTTPS, from a consumer perspective, check https://howhttps.works/. - -Now, from a developer's perspective, here are several things to have in mind while thinking about HTTPS: - -* For HTTPS, the server needs to have "certificates" generated by a third party. - * Those certificates are actually acquired from the third-party, not "generated". -* Certificates have a lifetime. - * They expire. - * And then they need to be renewed, acquired again from the third party. -* The encryption of the connection happens at the TCP level. - * That's one layer below HTTP. - * So, the certificate and encryption handling is done before HTTP. -* TCP doesn't know about "domains". Only about IP addresses. - * The information about the specific domain requested goes in the HTTP data. -* The HTTPS certificates "certificate" a certain domain, but the protocol and encryption happen at the TCP level, before knowing which domain is being dealt with. -* By default, that would mean that you can only have one HTTPS certificate per IP address. - * No matter how big is your server and how small each application you have there might be. But... -* There's an extension to the TLS protocol (the one handling the encryption at the TCP level, before HTTP) called SNI. - * This SNI extension allows one single server (with a single IP address) to have several HTTPS certificates and server multiple HTTPS domains/applications. - * For this to work, a single component (program) running in the server, listening in the public IP address, must have all the HTTPS certificates in the server. -* After having a secure connection, the communication protocol is the same HTTP. - * It goes encrypted, but the encrypted contents are the same HTTP protocol. - - -It is a common practice to have one program/HTTP server running in the server (the machine, host, etc) and managing all the HTTPS parts, sending the decrypted HTTP requests to the actual HTTP application running in the same server (the **FastAPI** application, in this case), take the HTTP response from the application, encrypt it using the appropriate certificate and sending it back to the client using HTTPS. This server is ofter called a TLS Termination Proxy. - - -### Let's Encrypt - -Up to some years ago, these HTTPS certificates were sold by trusted third-parties. - -The process to acquire one of these certificates used to be cumbersome, require quite some paperwork and the certificates were quite expensive. - -But then Let's Encrypt was created. - -It is a project from the Linux Foundation. It provides HTTPS certificates for free. In an automated way. These certificates use all the standard cryptographic security, and are short lived (about 3 months), so, the security is actually increased, by reducing their lifespan. - -The domain's are securely verified and the certificates are generated automatically. This also allows automatizing the renewal of these certificates. - -The idea is to automatize the acquisition and renewal of these certificates, so that you can have secure HTTPS, free, forever. - - -### Traefik - -Traefik is a high performance reverse proxy / load balancer. It can do the "TLS Termination Proxy" job (apart from other features). - -It has integration with Let's Encrypt. So, it can handle all the HTTPS parts, including certificate acquisition and renewal. - -It also has integrations with Docker. So, you can declare your domains in each application configurations and have it read those configurations, generate the HTTPS certificates and serve HTTPS to your application, all automatically. Without requiring any change in its configuration. - ---- - -With this information and tools, continue with the next section to combine everything. - - -## Docker Swarm mode cluster with Traefik and HTTPS - -You can have a Docker Swarm mode cluster set up in minutes (about 20 min) with a main Traefik handling HTTPS (including certificate acquisition and renewal). - -By using Docker Swarm mode, you can start with a "cluster" of a single machine (it can even be a $5 USD / month server) and then you can grow as much as you need adding more servers. - -To set up a Docker Swarm Mode cluster with Traefik and HTTPS handling, follow this guide: - -### Docker Swarm Mode and Traefik for an HTTPS cluster. - - -### Deploy a FastAPI application - -The easiest way to set everything up, would be using the FastAPI project generator. - -It is designed to be integrated with this Docker Swarm cluster with Traefik and HTTPS described above. - -You can generate a project in about 2 min. - -The generated project has instructions to deploy it, doing it takes other 2 min. - - -## Alternatively, deploy **FastAPI** without Docker - -You can deploy **FastAPI** directly without Docker too. - -You just need to install an ASGI compatible server like: - -* Uvicorn, a lightning-fast ASGI server, built on uvloop and httptools. - -```bash -pip install uvicorn -``` - -* Hypercorn, an ASGI server also compatible with HTTP/2. - -```bash -pip install hypercorn -``` - -...or any other ASGI server. - -And run your application the same way you have done in the tutorials, but without the `--reload` option, e.g.: - -```bash -uvicorn main:app --host 0.0.0.0 --port 80 -``` - -or with Hypercorn: - -```bash -hypercorn main:app --bind 0.0.0.0:80 -``` - -You might want to set up some tooling to make sure it is restarted automatically if it stops. - -You might also want to install Gunicorn and use it as a manager for Uvicorn, or use Hypercorn with multiple workers. - -Making sure to fine-tune the number of workers, etc. - -But if you are doing all that, you might just use the Docker image that does it automatically. diff --git a/docs/en/data/contributors.yml b/docs/en/data/contributors.yml new file mode 100644 index 0000000000000..b22e0975b273a --- /dev/null +++ b/docs/en/data/contributors.yml @@ -0,0 +1,595 @@ +tiangolo: + login: tiangolo + count: 1005 + avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 + url: https://github.com/tiangolo +dependabot: + login: dependabot + count: 221 + avatarUrl: https://avatars.githubusercontent.com/in/29110?v=4 + url: https://github.com/apps/dependabot +YuriiMotov: + login: YuriiMotov + count: 82 + avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=bc48be95c429989224786106b027f3c5e40cc354&v=4 + url: https://github.com/YuriiMotov +alejsdev: + login: alejsdev + count: 57 + avatarUrl: https://avatars.githubusercontent.com/u/90076947?u=0facffe3abf87f57a1f05fa773d1119cc5c2f6a5&v=4 + url: https://github.com/alejsdev +pre-commit-ci: + login: pre-commit-ci + count: 50 + avatarUrl: https://avatars.githubusercontent.com/in/68672?v=4 + url: https://github.com/apps/pre-commit-ci +github-actions: + login: github-actions + count: 26 + avatarUrl: https://avatars.githubusercontent.com/in/15368?v=4 + url: https://github.com/apps/github-actions +Kludex: + login: Kludex + count: 25 + avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=df8a3f06ba8f55ae1967a3e2d5ed882903a4e330&v=4 + url: https://github.com/Kludex +svlandeg: + login: svlandeg + count: 24 + avatarUrl: https://avatars.githubusercontent.com/u/8796347?u=556c97650c27021911b0b9447ec55e75987b0e8a&v=4 + url: https://github.com/svlandeg +dmontagu: + login: dmontagu + count: 17 + avatarUrl: https://avatars.githubusercontent.com/u/35119617?u=540f30c937a6450812628b9592a1dfe91bbe148e&v=4 + url: https://github.com/dmontagu +nilslindemann: + login: nilslindemann + count: 15 + avatarUrl: https://avatars.githubusercontent.com/u/6892179?u=1dca6a22195d6cd1ab20737c0e19a4c55d639472&v=4 + url: https://github.com/nilslindemann +euri10: + login: euri10 + count: 13 + avatarUrl: https://avatars.githubusercontent.com/u/1104190?u=321a2e953e6645a7d09b732786c7a8061e0f8a8b&v=4 + url: https://github.com/euri10 +kantandane: + login: kantandane + count: 13 + avatarUrl: https://avatars.githubusercontent.com/u/3978368?u=cccc199291f991a73b1ebba5abc735a948e0bd16&v=4 + url: https://github.com/kantandane +zhaohan-dong: + login: zhaohan-dong + count: 11 + avatarUrl: https://avatars.githubusercontent.com/u/65422392?u=8260f8781f50248410ebfa4c9bf70e143fe5c9f2&v=4 + url: https://github.com/zhaohan-dong +mariacamilagl: + login: mariacamilagl + count: 9 + avatarUrl: https://avatars.githubusercontent.com/u/11489395?u=4adb6986bf3debfc2b8216ae701f2bd47d73da7d&v=4 + url: https://github.com/mariacamilagl +handabaldeep: + login: handabaldeep + count: 9 + avatarUrl: https://avatars.githubusercontent.com/u/12239103?u=6c39ef15d14c6d5211f5dd775cc4842f8d7f2f3a&v=4 + url: https://github.com/handabaldeep +vishnuvskvkl: + login: vishnuvskvkl + count: 8 + avatarUrl: https://avatars.githubusercontent.com/u/84698110?u=8af5de0520dd4fa195f53c2850a26f57c0f6bc64&v=4 + url: https://github.com/vishnuvskvkl +alissadb: + login: alissadb + count: 6 + avatarUrl: https://avatars.githubusercontent.com/u/96190409?u=be42d85938c241be781505a5a872575be28b2906&v=4 + url: https://github.com/alissadb +alv2017: + login: alv2017 + count: 6 + avatarUrl: https://avatars.githubusercontent.com/u/31544722?v=4 + url: https://github.com/alv2017 +wshayes: + login: wshayes + count: 5 + avatarUrl: https://avatars.githubusercontent.com/u/365303?u=07ca03c5ee811eb0920e633cc3c3db73dbec1aa5&v=4 + url: https://github.com/wshayes +samuelcolvin: + login: samuelcolvin + count: 5 + avatarUrl: https://avatars.githubusercontent.com/u/4039449?u=42eb3b833047c8c4b4f647a031eaef148c16d93f&v=4 + url: https://github.com/samuelcolvin +waynerv: + login: waynerv + count: 5 + avatarUrl: https://avatars.githubusercontent.com/u/39515546?u=ec35139777597cdbbbddda29bf8b9d4396b429a9&v=4 + url: https://github.com/waynerv +musicinmybrain: + login: musicinmybrain + count: 5 + avatarUrl: https://avatars.githubusercontent.com/u/6898909?u=9010312053e7141383b9bdf538036c7f37fbaba0&v=4 + url: https://github.com/musicinmybrain +krishnamadhavan: + login: krishnamadhavan + count: 5 + avatarUrl: https://avatars.githubusercontent.com/u/31798870?u=950693b28f3ae01105fd545c046e46ca3d31ab06&v=4 + url: https://github.com/krishnamadhavan +jekirl: + login: jekirl + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/2546697?u=a027452387d85bd4a14834e19d716c99255fb3b7&v=4 + url: https://github.com/jekirl +hitrust: + login: hitrust + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/3360631?u=5fa1f475ad784d64eb9666bdd43cc4d285dcc773&v=4 + url: https://github.com/hitrust +ShahriyarR: + login: ShahriyarR + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/3852029?u=2dc6402d9053ee53f7afc407089cbab21c68f21d&v=4 + url: https://github.com/ShahriyarR +adriangb: + login: adriangb + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/1755071?u=612704256e38d6ac9cbed24f10e4b6ac2da74ecb&v=4 + url: https://github.com/adriangb +iudeen: + login: iudeen + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/10519440?u=f09cdd745e5bf16138f29b42732dd57c7f02bee1&v=4 + url: https://github.com/iudeen +philipokiokio: + login: philipokiokio + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/55271518?u=d30994d339aaaf1f6bf1b8fc810132016fbd4fdc&v=4 + url: https://github.com/philipokiokio +AlexWendland: + login: AlexWendland + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/3949212?u=c4c0c615e0ea33d00bfe16b779cf6ebc0f58071c&v=4 + url: https://github.com/AlexWendland +valentinDruzhinin: + login: valentinDruzhinin + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/12831905?u=aae1ebc675c91e8fa582df4fcc4fc4128106344d&v=4 + url: https://github.com/valentinDruzhinin +divums: + login: divums + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/1397556?v=4 + url: https://github.com/divums +prostomarkeloff: + login: prostomarkeloff + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/28061158?u=6918e39a1224194ba636e897461a02a20126d7ad&v=4 + url: https://github.com/prostomarkeloff +frankie567: + login: frankie567 + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/1144727?u=f3e79acfe4ed207e15c2145161a8a9759925fcd2&v=4 + url: https://github.com/frankie567 +nsidnev: + login: nsidnev + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/22559461?u=a9cc3238217e21dc8796a1a500f01b722adb082c&v=4 + url: https://github.com/nsidnev +pawamoy: + login: pawamoy + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/3999221?u=b030e4c89df2f3a36bc4710b925bdeb6745c9856&v=4 + url: https://github.com/pawamoy +patrickmckenna: + login: patrickmckenna + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/3589536?u=53aef07250d226d35e526768e26891964907b41a&v=4 + url: https://github.com/patrickmckenna +hukkin: + login: hukkin + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/3275109?u=77bb83759127965eacbfe67e2ca983066e964fde&v=4 + url: https://github.com/hukkin +marcosmmb: + login: marcosmmb + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/6181089?u=03c50eec631857d84df5232890780d00a3f76903&v=4 + url: https://github.com/marcosmmb +Serrones: + login: Serrones + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/22691749?u=4795b880e13ca33a73e52fc0ef7dc9c60c8fce47&v=4 + url: https://github.com/Serrones +uriyyo: + login: uriyyo + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/32038156?u=c26ca9b821fcf6499b84db75f553d4980bf8d023&v=4 + url: https://github.com/uriyyo +andrew222651: + login: andrew222651 + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/889657?u=d70187989940b085bcbfa3bedad8dbc5f3ab1fe7&v=4 + url: https://github.com/andrew222651 +rkbeatss: + login: rkbeatss + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/23391143?u=56ab6bff50be950fa8cae5cf736f2ae66e319ff3&v=4 + url: https://github.com/rkbeatss +asheux: + login: asheux + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/22955146?u=4553ebf5b5a7c7fe031a46182083aa224faba2e1&v=4 + url: https://github.com/asheux +blkst8: + login: blkst8 + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/49960770?u=7d8a6d5f0a75a5e9a865a2527edfd48895ea27ae&v=4 + url: https://github.com/blkst8 +ghandic: + login: ghandic + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/23500353?u=e2e1d736f924d9be81e8bfc565b6d8836ba99773&v=4 + url: https://github.com/ghandic +TeoZosa: + login: TeoZosa + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/13070236?u=96fdae85800ef85dcfcc4b5f8281dc8778c8cb7d&v=4 + url: https://github.com/TeoZosa +graingert: + login: graingert + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/413772?v=4 + url: https://github.com/graingert +jaystone776: + login: jaystone776 + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/11191137?u=299205a95e9b6817a43144a48b643346a5aac5cc&v=4 + url: https://github.com/jaystone776 +zanieb: + login: zanieb + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/2586601?u=e5c86f7ff3b859e7e183187ac2b17fd6ee32b3ab&v=4 + url: https://github.com/zanieb +MicaelJarniac: + login: MicaelJarniac + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/19514231?u=158c91874ea98d6e9e6f0c6db37ee2ce60c55ff2&v=4 + url: https://github.com/MicaelJarniac +papb: + login: papb + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/20914054?u=890511fae7ea90d887e2a65ce44a1775abba38d5&v=4 + url: https://github.com/papb +tamird: + login: tamird + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/1535036?v=4 + url: https://github.com/tamird +Nimitha-jagadeesha: + login: Nimitha-jagadeesha + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/58389915?v=4 + url: https://github.com/Nimitha-jagadeesha +lucaromagnoli: + login: lucaromagnoli + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/38782977?u=a09a2e916625fa035f9dfa25ebc58e07aac8ec36&v=4 + url: https://github.com/lucaromagnoli +salmantec: + login: salmantec + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/41512228?u=443551b893ff2425c59d5d021644f098cf7c68d5&v=4 + url: https://github.com/salmantec +OCE1960: + login: OCE1960 + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/45076670?u=0e9a44712b92ffa89ddfbaa83c112f3f8e1d68e2&v=4 + url: https://github.com/OCE1960 +hamidrasti: + login: hamidrasti + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/43915620?v=4 + url: https://github.com/hamidrasti +kkinder: + login: kkinder + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/1115018?u=c5e90284a9f5c5049eae1bb029e3655c7dc913ed&v=4 + url: https://github.com/kkinder +kabirkhan: + login: kabirkhan + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/13891834?u=e0eabf792376443ac853e7dca6f550db4166fe35&v=4 + url: https://github.com/kabirkhan +zamiramir: + login: zamiramir + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/40475662?v=4 + url: https://github.com/zamiramir +trim21: + login: trim21 + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/13553903?u=3cadf0f02095c9621aa29df6875f53a80ca4fbfb&v=4 + url: https://github.com/trim21 +koxudaxi: + login: koxudaxi + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/630670?u=507d8577b4b3670546b449c4c2ccbc5af40d72f7&v=4 + url: https://github.com/koxudaxi +pablogamboa: + login: pablogamboa + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/12892536?u=326a57059ee0c40c4eb1b38413957236841c631b&v=4 + url: https://github.com/pablogamboa +dconathan: + login: dconathan + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/15098095?v=4 + url: https://github.com/dconathan +Jamim: + login: Jamim + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/5607572?u=9ce0b6a6d1a5124e28b3c04d8d26827ca328713a&v=4 + url: https://github.com/Jamim +svalouch: + login: svalouch + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/54674660?v=4 + url: https://github.com/svalouch +marier-nico: + login: marier-nico + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/30477068?u=c7df6af853c8f4163d1517814f3e9a0715c82713&v=4 + url: https://github.com/marier-nico +Dustyposa: + login: Dustyposa + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/27180793?u=5cf2877f50b3eb2bc55086089a78a36f07042889&v=4 + url: https://github.com/Dustyposa +aviramha: + login: aviramha + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/41201924?u=ce5d3ea7037c2e6b3f82eff87e2217d4fb63214b&v=4 + url: https://github.com/aviramha +iwpnd: + login: iwpnd + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/6152183?u=ec59396e9437fff488791c5ecdf6d23f1f1ebf3a&v=4 + url: https://github.com/iwpnd +raphaelauv: + login: raphaelauv + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/10202690?u=e6f86f5c0c3026a15d6b51792fa3e532b12f1371&v=4 + url: https://github.com/raphaelauv +windson: + login: windson + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/1826682?u=8b28dcd716c46289f191f8828e01d74edd058bef&v=4 + url: https://github.com/windson +sm-Fifteen: + login: sm-Fifteen + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/516999?u=437c0c5038558c67e887ccd863c1ba0f846c03da&v=4 + url: https://github.com/sm-Fifteen +sattosan: + login: sattosan + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/20574756?u=b0d8474d2938189c6954423ae8d81d91013f80a8&v=4 + url: https://github.com/sattosan +michaeloliverx: + login: michaeloliverx + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/55017335?u=efb0cb6e261ff64d862fafb91ee80fc2e1f8a2ed&v=4 + url: https://github.com/michaeloliverx +voegtlel: + login: voegtlel + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/5764745?u=db8df3d70d427928ab6d7dbfc395a4a7109c1d1b&v=4 + url: https://github.com/voegtlel +HarshaLaxman: + login: HarshaLaxman + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/19939186?u=a112f38b0f6b4d4402dc8b51978b5a0b2e5c5970&v=4 + url: https://github.com/HarshaLaxman +RunningIkkyu: + login: RunningIkkyu + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/31848542?u=494ecc298e3f26197495bb357ad0f57cfd5f7a32&v=4 + url: https://github.com/RunningIkkyu +cassiobotaro: + login: cassiobotaro + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/3127847?u=a08022b191ddbd0a6159b2981d9d878b6d5bb71f&v=4 + url: https://github.com/cassiobotaro +chenl: + login: chenl + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/1677651?u=c618508eaad6d596cea36c8ea784b424288f6857&v=4 + url: https://github.com/chenl +retnikt: + login: retnikt + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/24581770?v=4 + url: https://github.com/retnikt +yankeexe: + login: yankeexe + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/13623913?u=f970e66421775a8d3cdab89c0c752eaead186f6d&v=4 + url: https://github.com/yankeexe +patrickkwang: + login: patrickkwang + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/1263870?u=4bf74020e15be490f19ef8322a76eec882220b96&v=4 + url: https://github.com/patrickkwang +victorphoenix3: + login: victorphoenix3 + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/48182195?u=e4875bd088623cb4ddeb7be194ec54b453aff035&v=4 + url: https://github.com/victorphoenix3 +davidefiocco: + login: davidefiocco + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/4547987?v=4 + url: https://github.com/davidefiocco +adriencaccia: + login: adriencaccia + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/19605940?u=9a59081f46bfc9d839886a49d5092cf572879049&v=4 + url: https://github.com/adriencaccia +jamescurtin: + login: jamescurtin + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/10189269?u=0b491fc600ca51f41cf1d95b49fa32a3eba1de57&v=4 + url: https://github.com/jamescurtin +jmriebold: + login: jmriebold + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/6983392?u=4efdc97bf2422dcc7e9ff65b9ff80087c8eb2a20&v=4 + url: https://github.com/jmriebold +nukopy: + login: nukopy + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/42367320?u=6061be0bd060506f6d564a8df3ae73fab048cdfe&v=4 + url: https://github.com/nukopy +imba-tjd: + login: imba-tjd + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/24759802?u=01e901a4fe004b4b126549d3ff1c4000fe3720b5&v=4 + url: https://github.com/imba-tjd +johnthagen: + login: johnthagen + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/10340167?u=47147fc4e4db1f573bee3fe428deeacb3197bc5f&v=4 + url: https://github.com/johnthagen +paxcodes: + login: paxcodes + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/13646646?u=e7429cc7ab11211ef762f4cd3efea7db6d9ef036&v=4 + url: https://github.com/paxcodes +kaustubhgupta: + login: kaustubhgupta + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/43691873?u=8dd738718ac7ffad4ef31e86b5d780a1141c695d&v=4 + url: https://github.com/kaustubhgupta +kinuax: + login: kinuax + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/13321374?u=22dc9873d6d9f2c7e4fc44c6480c3505efb1531f&v=4 + url: https://github.com/kinuax +wakabame: + login: wakabame + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/35513518?u=41ef6b0a55076e5c540620d68fb006e386c2ddb0&v=4 + url: https://github.com/wakabame +nzig: + login: nzig + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/7372858?u=e769add36ed73c778cdb136eb10bf96b1e119671&v=4 + url: https://github.com/nzig +kristjanvalur: + login: kristjanvalur + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/6009543?u=1419f20bbfff8f031be8cb470962e7e62de2595e&v=4 + url: https://github.com/kristjanvalur +yezz123: + login: yezz123 + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/52716203?u=21b53ce4115062b1e20cb513e64ca0000c2ef127&v=4 + url: https://github.com/yezz123 +softwarebloat: + login: softwarebloat + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/16540684?v=4 + url: https://github.com/softwarebloat +Lancetnik: + login: Lancetnik + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/44573917?u=6eaa0cdd35259fba40a76b82e4903440cba03fa9&v=4 + url: https://github.com/Lancetnik +joakimnordling: + login: joakimnordling + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/6637576?u=df5d99db9b899b399effd429f4358baaa6f7199c&v=4 + url: https://github.com/joakimnordling +AhsanSheraz: + login: AhsanSheraz + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/51913596?u=b5aa3c3a004cc0112e56c54f6901941836d8c26b&v=4 + url: https://github.com/AhsanSheraz +yogabonito: + login: yogabonito + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/7026269?v=4 + url: https://github.com/yogabonito +s111d: + login: s111d + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/4954856?v=4 + url: https://github.com/s111d +estebanx64: + login: estebanx64 + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/10840422?u=2ca073ee47a625e495a9573bd374ddcd7be5ec91&v=4 + url: https://github.com/estebanx64 +ndimares: + login: ndimares + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/6267663?u=cfb27efde7a7212be8142abb6c058a1aeadb41b1&v=4 + url: https://github.com/ndimares +rabinlamadong: + login: rabinlamadong + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/170439781?v=4 + url: https://github.com/rabinlamadong +AyushSinghal1794: + login: AyushSinghal1794 + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/89984761?v=4 + url: https://github.com/AyushSinghal1794 +gsheni: + login: gsheni + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/8726321?u=ee3bd9ff6320f4715d1dd9671a3d55cccb65b984&v=4 + url: https://github.com/gsheni +chailandau: + login: chailandau + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/112015853?u=2e6aaf2b1647db43834aabeae8d8282b4ec01873&v=4 + url: https://github.com/chailandau +DanielKusyDev: + login: DanielKusyDev + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/36250676?u=411f1f5923596480b896d160e23c908318f39003&v=4 + url: https://github.com/DanielKusyDev +Viicos: + login: Viicos + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/65306057?u=fcd677dc1b9bef12aa103613e5ccb3f8ce305af9&v=4 + url: https://github.com/Viicos +DanielYang59: + login: DanielYang59 + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/80093591?u=63873f701c7c74aac83c906800a1dddc0bc8c92f&v=4 + url: https://github.com/DanielYang59 +blueswen: + login: blueswen + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/1564148?u=6d6b8cc8f2b5cef715e68d6175154a8a94d518ee&v=4 + url: https://github.com/blueswen +Taoup: + login: Taoup + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/22348542?v=4 + url: https://github.com/Taoup +zadevhub: + login: zadevhub + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/138465437?v=4 + url: https://github.com/zadevhub +savannahostrowski: + login: savannahostrowski + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/8949415?u=e4bb61b9ebaa406274d2f2629cd33179a432a2a7&v=4 + url: https://github.com/savannahostrowski +jonathan-fulton: + login: jonathan-fulton + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/4665111?u=bda1c12e5137bd7771a6aa24d9515b87c11da150&v=4 + url: https://github.com/jonathan-fulton diff --git a/docs/en/data/github_sponsors.yml b/docs/en/data/github_sponsors.yml new file mode 100644 index 0000000000000..971687d8a987e --- /dev/null +++ b/docs/en/data/github_sponsors.yml @@ -0,0 +1,388 @@ +sponsors: +- - login: renderinc + avatarUrl: https://avatars.githubusercontent.com/u/36424661?v=4 + url: https://github.com/renderinc + - login: subtotal + avatarUrl: https://avatars.githubusercontent.com/u/176449348?v=4 + url: https://github.com/subtotal + - login: greptileai + avatarUrl: https://avatars.githubusercontent.com/u/140149887?v=4 + url: https://github.com/greptileai + - login: coderabbitai + avatarUrl: https://avatars.githubusercontent.com/u/132028505?v=4 + url: https://github.com/coderabbitai + - login: zuplo + avatarUrl: https://avatars.githubusercontent.com/u/85497839?v=4 + url: https://github.com/zuplo + - login: blockbee-io + avatarUrl: https://avatars.githubusercontent.com/u/115143449?u=1b8620c2d6567c4df2111a371b85a51f448f9b85&v=4 + url: https://github.com/blockbee-io + - login: andrew-propelauth + avatarUrl: https://avatars.githubusercontent.com/u/89474256?u=c98993dec8553c09d424ede67bbe86e5c35f48c9&v=4 + url: https://github.com/andrew-propelauth + - login: railwayapp + avatarUrl: https://avatars.githubusercontent.com/u/66716858?v=4 + url: https://github.com/railwayapp +- - login: speakeasy-api + avatarUrl: https://avatars.githubusercontent.com/u/91446104?v=4 + url: https://github.com/speakeasy-api + - login: stainless-api + avatarUrl: https://avatars.githubusercontent.com/u/88061651?v=4 + url: https://github.com/stainless-api + - login: svix + avatarUrl: https://avatars.githubusercontent.com/u/80175132?v=4 + url: https://github.com/svix + - login: permitio + avatarUrl: https://avatars.githubusercontent.com/u/71775833?v=4 + url: https://github.com/permitio + - login: databento + avatarUrl: https://avatars.githubusercontent.com/u/64141749?v=4 + url: https://github.com/databento +- - login: LambdaTest-Inc + avatarUrl: https://avatars.githubusercontent.com/u/171592363?u=96606606a45fa170427206199014f2a5a2a4920b&v=4 + url: https://github.com/LambdaTest-Inc + - login: Ponte-Energy-Partners + avatarUrl: https://avatars.githubusercontent.com/u/114745848?v=4 + url: https://github.com/Ponte-Energy-Partners + - login: BoostryJP + avatarUrl: https://avatars.githubusercontent.com/u/57932412?v=4 + url: https://github.com/BoostryJP + - login: acsone + avatarUrl: https://avatars.githubusercontent.com/u/7601056?v=4 + url: https://github.com/acsone +- - login: scalar + avatarUrl: https://avatars.githubusercontent.com/u/301879?v=4 + url: https://github.com/scalar + - login: Trivie + avatarUrl: https://avatars.githubusercontent.com/u/8161763?v=4 + url: https://github.com/Trivie +- - login: takashi-yoneya + avatarUrl: https://avatars.githubusercontent.com/u/33813153?u=2d0522bceba0b8b69adf1f2db866503bd96f944e&v=4 + url: https://github.com/takashi-yoneya + - login: Doist + avatarUrl: https://avatars.githubusercontent.com/u/2565372?v=4 + url: https://github.com/Doist +- - login: mainframeindustries + avatarUrl: https://avatars.githubusercontent.com/u/55092103?v=4 + url: https://github.com/mainframeindustries +- - login: alixlahuec + avatarUrl: https://avatars.githubusercontent.com/u/29543316?u=44357eb2a93bccf30fb9d389b8befe94a3d00985&v=4 + url: https://github.com/alixlahuec +- - login: primer-io + avatarUrl: https://avatars.githubusercontent.com/u/62146168?v=4 + url: https://github.com/primer-io +- - login: upciti + avatarUrl: https://avatars.githubusercontent.com/u/43346262?v=4 + url: https://github.com/upciti + - login: ChargeStorm + avatarUrl: https://avatars.githubusercontent.com/u/26000165?v=4 + url: https://github.com/ChargeStorm + - login: ibrahimpelumi6142 + avatarUrl: https://avatars.githubusercontent.com/u/113442282?v=4 + url: https://github.com/ibrahimpelumi6142 + - login: nilslindemann + avatarUrl: https://avatars.githubusercontent.com/u/6892179?u=1dca6a22195d6cd1ab20737c0e19a4c55d639472&v=4 + url: https://github.com/nilslindemann +- - login: samuelcolvin + avatarUrl: https://avatars.githubusercontent.com/u/4039449?u=42eb3b833047c8c4b4f647a031eaef148c16d93f&v=4 + url: https://github.com/samuelcolvin + - login: otosky + avatarUrl: https://avatars.githubusercontent.com/u/42260747?u=69d089387c743d89427aa4ad8740cfb34045a9e0&v=4 + url: https://github.com/otosky + - login: ramonalmeidam + avatarUrl: https://avatars.githubusercontent.com/u/45269580?u=3358750b3a5854d7c3ed77aaca7dd20a0f529d32&v=4 + url: https://github.com/ramonalmeidam + - login: roboflow + avatarUrl: https://avatars.githubusercontent.com/u/53104118?v=4 + url: https://github.com/roboflow + - login: dudikbender + avatarUrl: https://avatars.githubusercontent.com/u/53487583?u=3a57542938ebfd57579a0111db2b297e606d9681&v=4 + url: https://github.com/dudikbender + - login: ehaca + avatarUrl: https://avatars.githubusercontent.com/u/25950317?u=cec1a3e0643b785288ae8260cc295a85ab344995&v=4 + url: https://github.com/ehaca + - login: raphaellaude + avatarUrl: https://avatars.githubusercontent.com/u/28026311?u=91e1c00d9ac4f8045527e13de8050d504531cbc0&v=4 + url: https://github.com/raphaellaude + - login: timlrx + avatarUrl: https://avatars.githubusercontent.com/u/28362229?u=9a745ca31372ee324af682715ae88ce8522f9094&v=4 + url: https://github.com/timlrx + - login: Leay15 + avatarUrl: https://avatars.githubusercontent.com/u/32212558?u=c4aa9c1737e515959382a5515381757b1fd86c53&v=4 + url: https://github.com/Leay15 + - login: jugeeem + avatarUrl: https://avatars.githubusercontent.com/u/116043716?u=ae590d79c38ac79c91b9c5caa6887d061e865a3d&v=4 + url: https://github.com/jugeeem + - login: Karine-Bauch + avatarUrl: https://avatars.githubusercontent.com/u/90465103?u=7feb1018abb1a5631cfd9a91fea723d1ceb5f49b&v=4 + url: https://github.com/Karine-Bauch + - login: kaoru0310 + avatarUrl: https://avatars.githubusercontent.com/u/80977929?u=1b61d10142b490e56af932ddf08a390fae8ee94f&v=4 + url: https://github.com/kaoru0310 + - login: chickenandstats + avatarUrl: https://avatars.githubusercontent.com/u/79477966?u=ae2b894aa954070db1d7830dab99b49eba4e4567&v=4 + url: https://github.com/chickenandstats + - login: patricioperezv + avatarUrl: https://avatars.githubusercontent.com/u/73832292?u=5f471f156e19ee7920e62ae0f4a47b95580e61cf&v=4 + url: https://github.com/patricioperezv + - login: anthonycepeda + avatarUrl: https://avatars.githubusercontent.com/u/72019805?u=60bdf46240cff8fca482ff0fc07d963fd5e1a27c&v=4 + url: https://github.com/anthonycepeda + - login: AalbatrossGuy + avatarUrl: https://avatars.githubusercontent.com/u/68378354?u=0bdeea9356d24f638244131f6d8d1e2d2f3601ca&v=4 + url: https://github.com/AalbatrossGuy + - login: patsatsia + avatarUrl: https://avatars.githubusercontent.com/u/61111267?u=3271b85f7a37b479c8d0ae0a235182e83c166edf&v=4 + url: https://github.com/patsatsia + - login: oliverxchen + avatarUrl: https://avatars.githubusercontent.com/u/4471774?u=534191f25e32eeaadda22dfab4b0a428733d5489&v=4 + url: https://github.com/oliverxchen + - login: jaredtrog + avatarUrl: https://avatars.githubusercontent.com/u/4381365?v=4 + url: https://github.com/jaredtrog + - login: Ryandaydev + avatarUrl: https://avatars.githubusercontent.com/u/4292423?u=679ff84cb7b988c5795a5fa583857f574a055763&v=4 + url: https://github.com/Ryandaydev + - login: gorhack + avatarUrl: https://avatars.githubusercontent.com/u/4141690?u=ec119ebc4bdf00a7bc84657a71aa17834f4f27f3&v=4 + url: https://github.com/gorhack + - login: mj0331 + avatarUrl: https://avatars.githubusercontent.com/u/3890353?u=1c627ac1a024515b4871de5c3ebbfaa1a57f65d4&v=4 + url: https://github.com/mj0331 + - login: anomaly + avatarUrl: https://avatars.githubusercontent.com/u/3654837?v=4 + url: https://github.com/anomaly + - login: aacayaco + avatarUrl: https://avatars.githubusercontent.com/u/3634801?u=eaadda178c964178fcb64886f6c732172c8f8219&v=4 + url: https://github.com/aacayaco + - login: kennywakeland + avatarUrl: https://avatars.githubusercontent.com/u/3631417?u=7c8f743f1ae325dfadea7c62bbf1abd6a824fc55&v=4 + url: https://github.com/kennywakeland + - login: zsinx6 + avatarUrl: https://avatars.githubusercontent.com/u/3532625?u=ba75a5dc744d1116ccfeaaf30d41cb2fe81fe8dd&v=4 + url: https://github.com/zsinx6 + - login: dblackrun + avatarUrl: https://avatars.githubusercontent.com/u/3528486?v=4 + url: https://github.com/dblackrun + - login: knallgelb + avatarUrl: https://avatars.githubusercontent.com/u/2358812?u=c48cb6362b309d74cbf144bd6ad3aed3eb443e82&v=4 + url: https://github.com/knallgelb + - login: dodo5522 + avatarUrl: https://avatars.githubusercontent.com/u/1362607?u=9bf1e0e520cccc547c046610c468ce6115bbcf9f&v=4 + url: https://github.com/dodo5522 + - login: mintuhouse + avatarUrl: https://avatars.githubusercontent.com/u/769950?u=ecfbd79a97d33177e0d093ddb088283cf7fe8444&v=4 + url: https://github.com/mintuhouse + - login: falkben + avatarUrl: https://avatars.githubusercontent.com/u/653031?u=ad9838e089058c9e5a0bab94c0eec7cc181e0cd0&v=4 + url: https://github.com/falkben + - login: koxudaxi + avatarUrl: https://avatars.githubusercontent.com/u/630670?u=507d8577b4b3670546b449c4c2ccbc5af40d72f7&v=4 + url: https://github.com/koxudaxi + - login: wshayes + avatarUrl: https://avatars.githubusercontent.com/u/365303?u=07ca03c5ee811eb0920e633cc3c3db73dbec1aa5&v=4 + url: https://github.com/wshayes + - login: pamelafox + avatarUrl: https://avatars.githubusercontent.com/u/297042?v=4 + url: https://github.com/pamelafox + - login: robintw + avatarUrl: https://avatars.githubusercontent.com/u/296686?v=4 + url: https://github.com/robintw + - login: jstanden + avatarUrl: https://avatars.githubusercontent.com/u/63288?u=c3658d57d2862c607a0e19c2101c3c51876e36ad&v=4 + url: https://github.com/jstanden + - login: RaamEEIL + avatarUrl: https://avatars.githubusercontent.com/u/20320552?v=4 + url: https://github.com/RaamEEIL + - login: ashi-agrawal + avatarUrl: https://avatars.githubusercontent.com/u/17105294?u=99c7a854035e5398d8e7b674f2d42baae6c957f8&v=4 + url: https://github.com/ashi-agrawal + - login: mjohnsey + avatarUrl: https://avatars.githubusercontent.com/u/16784016?u=38fad2e6b411244560b3af99c5f5a4751bc81865&v=4 + url: https://github.com/mjohnsey + - login: khadrawy + avatarUrl: https://avatars.githubusercontent.com/u/13686061?u=59f25ef42ecf04c22657aac4238ce0e2d3d30304&v=4 + url: https://github.com/khadrawy + - login: dannywade + avatarUrl: https://avatars.githubusercontent.com/u/13680237?u=418ee985bd41577b20fde81417fb2d901e875e8a&v=4 + url: https://github.com/dannywade + - login: jsoques + avatarUrl: https://avatars.githubusercontent.com/u/12414216?u=620921d94196546cc8b9eae2cc4cbc3f95bab42f&v=4 + url: https://github.com/jsoques + - login: wdwinslow + avatarUrl: https://avatars.githubusercontent.com/u/11562137?u=371272f2c69e680e0559a7b0a57385e83a5dc728&v=4 + url: https://github.com/wdwinslow + - login: hiancdtrsnm + avatarUrl: https://avatars.githubusercontent.com/u/7343177?v=4 + url: https://github.com/hiancdtrsnm + - login: Rehket + avatarUrl: https://avatars.githubusercontent.com/u/7015688?u=3afb0ba200feebbc7f958950e92db34df2a3c172&v=4 + url: https://github.com/Rehket + - login: FernandoCelmer + avatarUrl: https://avatars.githubusercontent.com/u/6262214?u=58ba6d5888fa7f355934e52db19f950e20b38162&v=4 + url: https://github.com/FernandoCelmer + - login: eseglem + avatarUrl: https://avatars.githubusercontent.com/u/5920492?u=208d419cf667b8ac594c82a8db01932c7e50d057&v=4 + url: https://github.com/eseglem + - login: ternaus + avatarUrl: https://avatars.githubusercontent.com/u/5481618?u=513a26b02a39e7a28d587cd37c6cc877ea368e6e&v=4 + url: https://github.com/ternaus +- - login: Artur-Galstyan + avatarUrl: https://avatars.githubusercontent.com/u/63471891?u=e8691f386037e51a737cc0ba866cd8c89e5cf109&v=4 + url: https://github.com/Artur-Galstyan + - login: manoelpqueiroz + avatarUrl: https://avatars.githubusercontent.com/u/23669137?u=b12e84b28a84369ab5b30bd5a79e5788df5a0756&v=4 + url: https://github.com/manoelpqueiroz +- - login: pawamoy + avatarUrl: https://avatars.githubusercontent.com/u/3999221?u=b030e4c89df2f3a36bc4710b925bdeb6745c9856&v=4 + url: https://github.com/pawamoy + - login: siavashyj + avatarUrl: https://avatars.githubusercontent.com/u/43583410?u=562005ddc7901cd27a1219a118a2363817b14977&v=4 + url: https://github.com/siavashyj + - login: mobyw + avatarUrl: https://avatars.githubusercontent.com/u/44370805?v=4 + url: https://github.com/mobyw + - login: ArtyomVancyan + avatarUrl: https://avatars.githubusercontent.com/u/44609997?v=4 + url: https://github.com/ArtyomVancyan + - login: caviri + avatarUrl: https://avatars.githubusercontent.com/u/45425937?u=5f3d66ea5edea94c028c51ebf1c0f3b37e6c3db5&v=4 + url: https://github.com/caviri + - login: hgalytoby + avatarUrl: https://avatars.githubusercontent.com/u/50397689?u=6cc9028f3db63f8f60ad21c17b1ce4b88c4e2e60&v=4 + url: https://github.com/hgalytoby + - login: johnl28 + avatarUrl: https://avatars.githubusercontent.com/u/54412955?u=47dd06082d1c39caa90c752eb55566e4f3813957&v=4 + url: https://github.com/johnl28 + - login: danielunderwood + avatarUrl: https://avatars.githubusercontent.com/u/4472301?v=4 + url: https://github.com/danielunderwood + - login: hoenie-ams + avatarUrl: https://avatars.githubusercontent.com/u/25708487?u=cda07434f0509ac728d9edf5e681117c0f6b818b&v=4 + url: https://github.com/hoenie-ams + - login: joerambo + avatarUrl: https://avatars.githubusercontent.com/u/26282974?v=4 + url: https://github.com/joerambo + - login: engineerjoe440 + avatarUrl: https://avatars.githubusercontent.com/u/33275230?u=eb223cad27017bb1e936ee9b429b450d092d0236&v=4 + url: https://github.com/engineerjoe440 + - login: bnkc + avatarUrl: https://avatars.githubusercontent.com/u/34930566?u=4771ac4e64066f0847d40e5b29910adabd9b2372&v=4 + url: https://github.com/bnkc + - login: petercool + avatarUrl: https://avatars.githubusercontent.com/u/37613029?u=75aa8c6729e6e8f85a300561c4dbeef9d65c8797&v=4 + url: https://github.com/petercool + - login: PelicanQ + avatarUrl: https://avatars.githubusercontent.com/u/77930606?v=4 + url: https://github.com/PelicanQ + - login: PunRabbit + avatarUrl: https://avatars.githubusercontent.com/u/70463212?u=1a835cfbc99295a60c8282f6aa6199d1b42241a5&v=4 + url: https://github.com/PunRabbit + - login: my3 + avatarUrl: https://avatars.githubusercontent.com/u/1825270?v=4 + url: https://github.com/my3 + - login: WillHogan + avatarUrl: https://avatars.githubusercontent.com/u/1661551?u=8a80356e3e7d5a417157aba7ea565dabc8678327&v=4 + url: https://github.com/WillHogan + - login: miguelgr + avatarUrl: https://avatars.githubusercontent.com/u/1484589?u=54556072b8136efa12ae3b6902032ea2a39ace4b&v=4 + url: https://github.com/miguelgr + - login: tochikuji + avatarUrl: https://avatars.githubusercontent.com/u/851759?v=4 + url: https://github.com/tochikuji + - login: ceb10n + avatarUrl: https://avatars.githubusercontent.com/u/235213?u=edcce471814a1eba9f0cdaa4cd0de18921a940a6&v=4 + url: https://github.com/ceb10n + - login: slafs + avatarUrl: https://avatars.githubusercontent.com/u/210173?v=4 + url: https://github.com/slafs + - login: bryanculbertson + avatarUrl: https://avatars.githubusercontent.com/u/144028?u=defda4f90e93429221cc667500944abde60ebe4a&v=4 + url: https://github.com/bryanculbertson + - login: ddanier + avatarUrl: https://avatars.githubusercontent.com/u/113563?u=ed1dc79de72f93bd78581f88ebc6952b62f472da&v=4 + url: https://github.com/ddanier + - login: nisutec + avatarUrl: https://avatars.githubusercontent.com/u/25281462?u=e562484c451fdfc59053163f64405f8eb262b8b0&v=4 + url: https://github.com/nisutec + - login: joshuatz + avatarUrl: https://avatars.githubusercontent.com/u/17817563?u=f1bf05b690d1fc164218f0b420cdd3acb7913e21&v=4 + url: https://github.com/joshuatz + - login: TheR1D + avatarUrl: https://avatars.githubusercontent.com/u/16740832?u=b0dfdbdb27b79729430c71c6128962f77b7b53f7&v=4 + url: https://github.com/TheR1D + - login: Zuzah + avatarUrl: https://avatars.githubusercontent.com/u/10934846?u=1ef43e075ddc87bd1178372bf4d95ee6175cae27&v=4 + url: https://github.com/Zuzah + - login: mntolia + avatarUrl: https://avatars.githubusercontent.com/u/10390224?v=4 + url: https://github.com/mntolia + - login: hard-coders + avatarUrl: https://avatars.githubusercontent.com/u/9651103?u=78d12d1acdf853c817700145e73de7fd9e5d068b&v=4 + url: https://github.com/hard-coders + - login: DMantis + avatarUrl: https://avatars.githubusercontent.com/u/9536869?u=652dd0d49717803c0cbcbf44f7740e53cf2d4892&v=4 + url: https://github.com/DMantis + - login: xncbf + avatarUrl: https://avatars.githubusercontent.com/u/9462045?u=a80a7bb349555b277645632ed66639ff43400614&v=4 + url: https://github.com/xncbf + - login: moonape1226 + avatarUrl: https://avatars.githubusercontent.com/u/8532038?u=d9f8b855a429fff9397c3833c2ff83849ebf989d&v=4 + url: https://github.com/moonape1226 + - login: harsh183 + avatarUrl: https://avatars.githubusercontent.com/u/7780198?v=4 + url: https://github.com/harsh183 + - login: katnoria + avatarUrl: https://avatars.githubusercontent.com/u/7674948?u=09767eb13e07e09496c5fee4e5ce21d9eac34a56&v=4 + url: https://github.com/katnoria + - login: KentShikama + avatarUrl: https://avatars.githubusercontent.com/u/6329898?u=8b236810db9b96333230430837e1f021f9246da1&v=4 + url: https://github.com/KentShikama + - login: Baghdady92 + avatarUrl: https://avatars.githubusercontent.com/u/5708590?v=4 + url: https://github.com/Baghdady92 + - login: sdevkota + avatarUrl: https://avatars.githubusercontent.com/u/5250987?u=4ed9a120c89805a8aefda1cbdc0cf6512e64d1b4&v=4 + url: https://github.com/sdevkota + - login: rangulvers + avatarUrl: https://avatars.githubusercontent.com/u/5235430?u=e254d4af4ace5a05fa58372ae677c7d26f0d5a53&v=4 + url: https://github.com/rangulvers +- - login: KOZ39 + avatarUrl: https://avatars.githubusercontent.com/u/38822500?u=9dfc0a697df1c9628f08e20dc3fb17b1afc4e5a7&v=4 + url: https://github.com/KOZ39 + - login: rwxd + avatarUrl: https://avatars.githubusercontent.com/u/40308458?u=cd04a39e3655923be4f25c2ba8a5a07b3da3230a&v=4 + url: https://github.com/rwxd + - login: morzan1001 + avatarUrl: https://avatars.githubusercontent.com/u/47593005?u=c30ab7230f82a12a9b938dcb54f84a996931409a&v=4 + url: https://github.com/morzan1001 + - login: Olegt0rr + avatarUrl: https://avatars.githubusercontent.com/u/25399456?u=3e87b5239a2f4600975ba13be73054f8567c6060&v=4 + url: https://github.com/Olegt0rr + - login: larsyngvelundin + avatarUrl: https://avatars.githubusercontent.com/u/34173819?u=74958599695bf83ac9f1addd935a51548a10c6b0&v=4 + url: https://github.com/larsyngvelundin + - login: andrecorumba + avatarUrl: https://avatars.githubusercontent.com/u/37807517?u=9b9be3b41da9bda60957da9ef37b50dbf65baa61&v=4 + url: https://github.com/andrecorumba + - login: CoderDeltaLAN + avatarUrl: https://avatars.githubusercontent.com/u/152043745?u=4ff541efffb7d134e60c5fcf2dd1e343f90bb782&v=4 + url: https://github.com/CoderDeltaLAN + - login: hippoley + avatarUrl: https://avatars.githubusercontent.com/u/135493401?u=1164ef48a645a7c12664fabc1638fbb7e1c459b0&v=4 + url: https://github.com/hippoley + - login: nayasinghania + avatarUrl: https://avatars.githubusercontent.com/u/74111380?u=752e99a5e139389fdc0a0677122adc08438eb076&v=4 + url: https://github.com/nayasinghania + - login: onestn + avatarUrl: https://avatars.githubusercontent.com/u/62360849?u=746dd21c34e7e06eefb11b03e8bb01aaae3c2a4f&v=4 + url: https://github.com/onestn + - login: Toothwitch + avatarUrl: https://avatars.githubusercontent.com/u/1710406?u=5eebb23b46cd26e48643b9e5179536cad491c17a&v=4 + url: https://github.com/Toothwitch + - login: andreagrandi + avatarUrl: https://avatars.githubusercontent.com/u/636391?u=13d90cb8ec313593a5b71fbd4e33b78d6da736f5&v=4 + url: https://github.com/andreagrandi + - login: msserpa + avatarUrl: https://avatars.githubusercontent.com/u/6334934?u=82c4489eb1559d88d2990d60001901b14f722bbb&v=4 + url: https://github.com/msserpa diff --git a/docs/en/data/members.yml b/docs/en/data/members.yml new file mode 100644 index 0000000000000..7ec16e917eac3 --- /dev/null +++ b/docs/en/data/members.yml @@ -0,0 +1,22 @@ +members: +- login: tiangolo + avatar_url: https://avatars.githubusercontent.com/u/1326112 + url: https://github.com/tiangolo +- login: Kludex + avatar_url: https://avatars.githubusercontent.com/u/7353520 + url: https://github.com/Kludex +- login: alejsdev + avatar_url: https://avatars.githubusercontent.com/u/90076947 + url: https://github.com/alejsdev +- login: svlandeg + avatar_url: https://avatars.githubusercontent.com/u/8796347 + url: https://github.com/svlandeg +- login: YuriiMotov + avatar_url: https://avatars.githubusercontent.com/u/109919500 + url: https://github.com/YuriiMotov +- login: patrick91 + avatar_url: https://avatars.githubusercontent.com/u/667029 + url: https://github.com/patrick91 +- login: luzzodev + avatar_url: https://avatars.githubusercontent.com/u/27291415 + url: https://github.com/luzzodev diff --git a/docs/en/data/people.yml b/docs/en/data/people.yml new file mode 100644 index 0000000000000..b22d5371b2d67 --- /dev/null +++ b/docs/en/data/people.yml @@ -0,0 +1,774 @@ +maintainers: +- login: tiangolo + answers: 1931 + avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 + url: https://github.com/tiangolo +experts: +- login: tiangolo + count: 1931 + avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 + url: https://github.com/tiangolo +- login: YuriiMotov + count: 1198 + avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=bc48be95c429989224786106b027f3c5e40cc354&v=4 + url: https://github.com/YuriiMotov +- login: github-actions + count: 770 + avatarUrl: https://avatars.githubusercontent.com/in/15368?v=4 + url: https://github.com/apps/github-actions +- login: Kludex + count: 656 + avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=df8a3f06ba8f55ae1967a3e2d5ed882903a4e330&v=4 + url: https://github.com/Kludex +- login: jgould22 + count: 263 + avatarUrl: https://avatars.githubusercontent.com/u/4335847?u=ed77f67e0bb069084639b24d812dbb2a2b1dc554&v=4 + url: https://github.com/jgould22 +- login: dmontagu + count: 240 + avatarUrl: https://avatars.githubusercontent.com/u/35119617?u=540f30c937a6450812628b9592a1dfe91bbe148e&v=4 + url: https://github.com/dmontagu +- login: Mause + count: 219 + avatarUrl: https://avatars.githubusercontent.com/u/1405026?v=4 + url: https://github.com/Mause +- login: ycd + count: 216 + avatarUrl: https://avatars.githubusercontent.com/u/62724709?u=f1e7bae394a315da950912c92dc861a8eaf95d4c&v=4 + url: https://github.com/ycd +- login: JarroVGIT + count: 192 + avatarUrl: https://avatars.githubusercontent.com/u/13659033?u=e8bea32d07a5ef72f7dde3b2079ceb714923ca05&v=4 + url: https://github.com/JarroVGIT +- login: euri10 + count: 153 + avatarUrl: https://avatars.githubusercontent.com/u/1104190?u=321a2e953e6645a7d09b732786c7a8061e0f8a8b&v=4 + url: https://github.com/euri10 +- login: iudeen + count: 128 + avatarUrl: https://avatars.githubusercontent.com/u/10519440?u=f09cdd745e5bf16138f29b42732dd57c7f02bee1&v=4 + url: https://github.com/iudeen +- login: phy25 + count: 125 + avatarUrl: https://avatars.githubusercontent.com/u/331403?v=4 + url: https://github.com/phy25 +- login: JavierSanchezCastro + count: 110 + avatarUrl: https://avatars.githubusercontent.com/u/72013291?u=ae5679e6bd971d9d98cd5e76e8683f83642ba950&v=4 + url: https://github.com/JavierSanchezCastro +- login: luzzodev + count: 109 + avatarUrl: https://avatars.githubusercontent.com/u/27291415?u=5607ae1ce75c5f54f09500ca854227f7bfd2033b&v=4 + url: https://github.com/luzzodev +- login: raphaelauv + count: 83 + avatarUrl: https://avatars.githubusercontent.com/u/10202690?u=e6f86f5c0c3026a15d6b51792fa3e532b12f1371&v=4 + url: https://github.com/raphaelauv +- login: ArcLightSlavik + count: 71 + avatarUrl: https://avatars.githubusercontent.com/u/31127044?u=b0f2c37142f4b762e41ad65dc49581813422bd71&v=4 + url: https://github.com/ArcLightSlavik +- login: ghandic + count: 71 + avatarUrl: https://avatars.githubusercontent.com/u/23500353?u=e2e1d736f924d9be81e8bfc565b6d8836ba99773&v=4 + url: https://github.com/ghandic +- login: n8sty + count: 67 + avatarUrl: https://avatars.githubusercontent.com/u/2964996?v=4 + url: https://github.com/n8sty +- login: falkben + count: 59 + avatarUrl: https://avatars.githubusercontent.com/u/653031?u=ad9838e089058c9e5a0bab94c0eec7cc181e0cd0&v=4 + url: https://github.com/falkben +- login: yinziyan1206 + count: 55 + avatarUrl: https://avatars.githubusercontent.com/u/37829370?u=da44ca53aefd5c23f346fab8e9fd2e108294c179&v=4 + url: https://github.com/yinziyan1206 +- login: acidjunk + count: 50 + avatarUrl: https://avatars.githubusercontent.com/u/685002?u=b5094ab4527fc84b006c0ac9ff54367bdebb2267&v=4 + url: https://github.com/acidjunk +- login: sm-Fifteen + count: 49 + avatarUrl: https://avatars.githubusercontent.com/u/516999?u=437c0c5038558c67e887ccd863c1ba0f846c03da&v=4 + url: https://github.com/sm-Fifteen +- login: adriangb + count: 46 + avatarUrl: https://avatars.githubusercontent.com/u/1755071?u=612704256e38d6ac9cbed24f10e4b6ac2da74ecb&v=4 + url: https://github.com/adriangb +- login: insomnes + count: 45 + avatarUrl: https://avatars.githubusercontent.com/u/16958893?u=f8be7088d5076d963984a21f95f44e559192d912&v=4 + url: https://github.com/insomnes +- login: Dustyposa + count: 45 + avatarUrl: https://avatars.githubusercontent.com/u/27180793?u=5cf2877f50b3eb2bc55086089a78a36f07042889&v=4 + url: https://github.com/Dustyposa +- login: frankie567 + count: 43 + avatarUrl: https://avatars.githubusercontent.com/u/1144727?u=f3e79acfe4ed207e15c2145161a8a9759925fcd2&v=4 + url: https://github.com/frankie567 +- login: odiseo0 + count: 43 + avatarUrl: https://avatars.githubusercontent.com/u/87550035?u=75e754b9bd12ce6dfe90ad68e82e6f5255c7ac09&v=4 + url: https://github.com/odiseo0 +- login: sinisaos + count: 41 + avatarUrl: https://avatars.githubusercontent.com/u/30960668?v=4 + url: https://github.com/sinisaos +- login: includeamin + count: 40 + avatarUrl: https://avatars.githubusercontent.com/u/11836741?u=8bd5ef7e62fe6a82055e33c4c0e0a7879ff8cfb6&v=4 + url: https://github.com/includeamin +- login: chbndrhnns + count: 37 + avatarUrl: https://avatars.githubusercontent.com/u/7534547?v=4 + url: https://github.com/chbndrhnns +- login: STeveShary + count: 37 + avatarUrl: https://avatars.githubusercontent.com/u/5167622?u=de8f597c81d6336fcebc37b32dfd61a3f877160c&v=4 + url: https://github.com/STeveShary +- login: krishnardt + count: 35 + avatarUrl: https://avatars.githubusercontent.com/u/31960541?u=47f4829c77f4962ab437ffb7995951e41eeebe9b&v=4 + url: https://github.com/krishnardt +- login: panla + count: 32 + avatarUrl: https://avatars.githubusercontent.com/u/41326348?u=ba2fda6b30110411ecbf406d187907e2b420ac19&v=4 + url: https://github.com/panla +- login: valentinDruzhinin + count: 31 + avatarUrl: https://avatars.githubusercontent.com/u/12831905?u=aae1ebc675c91e8fa582df4fcc4fc4128106344d&v=4 + url: https://github.com/valentinDruzhinin +- login: prostomarkeloff + count: 28 + avatarUrl: https://avatars.githubusercontent.com/u/28061158?u=6918e39a1224194ba636e897461a02a20126d7ad&v=4 + url: https://github.com/prostomarkeloff +- login: alv2017 + count: 27 + avatarUrl: https://avatars.githubusercontent.com/u/31544722?v=4 + url: https://github.com/alv2017 +- login: hasansezertasan + count: 27 + avatarUrl: https://avatars.githubusercontent.com/u/13135006?u=d36995e41a00590da64e6204cfd112e0484ac1ca&v=4 + url: https://github.com/hasansezertasan +- login: dbanty + count: 26 + avatarUrl: https://avatars.githubusercontent.com/u/43723790?u=9d726785d08e50b1e1cd96505800c8ea8405bce2&v=4 + url: https://github.com/dbanty +- login: wshayes + count: 25 + avatarUrl: https://avatars.githubusercontent.com/u/365303?u=07ca03c5ee811eb0920e633cc3c3db73dbec1aa5&v=4 + url: https://github.com/wshayes +- login: SirTelemak + count: 23 + avatarUrl: https://avatars.githubusercontent.com/u/9435877?u=719327b7d2c4c62212456d771bfa7c6b8dbb9eac&v=4 + url: https://github.com/SirTelemak +- login: connebs + count: 22 + avatarUrl: https://avatars.githubusercontent.com/u/9054108?u=e151d5f545a3395136d711c227c22032fda67cfa&v=4 + url: https://github.com/connebs +- login: nymous + count: 22 + avatarUrl: https://avatars.githubusercontent.com/u/4216559?u=360a36fb602cded27273cbfc0afc296eece90662&v=4 + url: https://github.com/nymous +- login: chrisK824 + count: 22 + avatarUrl: https://avatars.githubusercontent.com/u/79946379?u=03d85b22d696a58a9603e55fbbbe2de6b0f4face&v=4 + url: https://github.com/chrisK824 +- login: ceb10n + count: 21 + avatarUrl: https://avatars.githubusercontent.com/u/235213?u=edcce471814a1eba9f0cdaa4cd0de18921a940a6&v=4 + url: https://github.com/ceb10n +- login: rafsaf + count: 21 + avatarUrl: https://avatars.githubusercontent.com/u/51059348?u=5fe59a56e1f2f9ccd8005d71752a8276f133ae1a&v=4 + url: https://github.com/rafsaf +- login: ebottos94 + count: 20 + avatarUrl: https://avatars.githubusercontent.com/u/100039558?u=8b91053b3abe4a9209375e3651e1c1ef192d884b&v=4 + url: https://github.com/ebottos94 +- login: nsidnev + count: 20 + avatarUrl: https://avatars.githubusercontent.com/u/22559461?u=a9cc3238217e21dc8796a1a500f01b722adb082c&v=4 + url: https://github.com/nsidnev +- login: chris-allnutt + count: 20 + avatarUrl: https://avatars.githubusercontent.com/u/565544?v=4 + url: https://github.com/chris-allnutt +- login: estebanx64 + count: 19 + avatarUrl: https://avatars.githubusercontent.com/u/10840422?u=2ca073ee47a625e495a9573bd374ddcd7be5ec91&v=4 + url: https://github.com/estebanx64 +- login: sehraramiz + count: 18 + avatarUrl: https://avatars.githubusercontent.com/u/14166324?u=8fac65e84dfff24245d304a5b5b09f7b5bd69dc9&v=4 + url: https://github.com/sehraramiz +- login: retnikt + count: 18 + avatarUrl: https://avatars.githubusercontent.com/u/24581770?v=4 + url: https://github.com/retnikt +- login: zoliknemet + count: 18 + avatarUrl: https://avatars.githubusercontent.com/u/22326718?u=31ba446ac290e23e56eea8e4f0c558aaf0b40779&v=4 + url: https://github.com/zoliknemet +- login: caeser1996 + count: 17 + avatarUrl: https://avatars.githubusercontent.com/u/16540232?u=05d2beb8e034d584d0a374b99d8826327bd7f614&v=4 + url: https://github.com/caeser1996 +- login: Hultner + count: 17 + avatarUrl: https://avatars.githubusercontent.com/u/2669034?u=115e53df959309898ad8dc9443fbb35fee71df07&v=4 + url: https://github.com/Hultner +- login: harunyasar + count: 17 + avatarUrl: https://avatars.githubusercontent.com/u/1765494?u=5b1ab7c582db4b4016fa31affe977d10af108ad4&v=4 + url: https://github.com/harunyasar +- login: nkhitrov + count: 17 + avatarUrl: https://avatars.githubusercontent.com/u/28262306?u=e19427d8dc296d6950e9c424adacc92d37496fe9&v=4 + url: https://github.com/nkhitrov +- login: dstlny + count: 16 + avatarUrl: https://avatars.githubusercontent.com/u/41964673?u=9f2174f9d61c15c6e3a4c9e3aeee66f711ce311f&v=4 + url: https://github.com/dstlny +- login: pythonweb2 + count: 16 + avatarUrl: https://avatars.githubusercontent.com/u/32141163?v=4 + url: https://github.com/pythonweb2 +- login: jonatasoli + count: 16 + avatarUrl: https://avatars.githubusercontent.com/u/26334101?u=f601c3f111f2148bd9244c2cb3ebbd57b592e674&v=4 + url: https://github.com/jonatasoli +- login: abhint + count: 15 + avatarUrl: https://avatars.githubusercontent.com/u/25699289?u=b5d219277b4d001ac26fb8be357fddd88c29d51b&v=4 + url: https://github.com/abhint +last_month_experts: +- login: YuriiMotov + count: 21 + avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=bc48be95c429989224786106b027f3c5e40cc354&v=4 + url: https://github.com/YuriiMotov +- login: Raphasha27 + count: 6 + avatarUrl: https://avatars.githubusercontent.com/u/220842167?u=a9e66fe06965e3830aecb82be4a442874950babe&v=4 + url: https://github.com/Raphasha27 +- login: svlandeg + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/8796347?u=556c97650c27021911b0b9447ec55e75987b0e8a&v=4 + url: https://github.com/svlandeg +- login: sueun-dev + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/57546981?u=0b0483bdcc7d521e85c06f28d2fc64e258bd466f&v=4 + url: https://github.com/sueun-dev +- login: tiangolo + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 + url: https://github.com/tiangolo +- login: vincere-mori + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/57835745?u=37d4cd4a763163dd03f29eff4975c2f1fa2a2d72&v=4 + url: https://github.com/vincere-mori +- login: thanos07 + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/68923656?u=dab6d4d9a6800f7d44d8c6df0b9904e17c2ecdb7&v=4 + url: https://github.com/thanos07 +- login: luzzodev + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/27291415?u=5607ae1ce75c5f54f09500ca854227f7bfd2033b&v=4 + url: https://github.com/luzzodev +- login: MajorDallas + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/79329882?u=e611ed986e4a37fd16ab69116a4600d95bfff294&v=4 + url: https://github.com/MajorDallas +- login: Francis1998 + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/66462431?u=20bdf51356ee7d99a8c8755c09460950d2b84fd0&v=4 + url: https://github.com/Francis1998 +- login: abdurrahman310303 + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/121820588?u=73c72a59ca082ceb8507bb1e2b559e59bdf2358f&v=4 + url: https://github.com/abdurrahman310303 +- login: Hassanmahmood4 + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/193066885?u=0e05f82009f99c53b16781d06a7f8d5fea8cc433&v=4 + url: https://github.com/Hassanmahmood4 +three_months_experts: +- login: YuriiMotov + count: 47 + avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=bc48be95c429989224786106b027f3c5e40cc354&v=4 + url: https://github.com/YuriiMotov +- login: Firatasi + count: 7 + avatarUrl: https://avatars.githubusercontent.com/u/112112161?u=3219914a49a4a604b3626007823db7de049b6d66&v=4 + url: https://github.com/Firatasi +- login: Raphasha27 + count: 6 + avatarUrl: https://avatars.githubusercontent.com/u/220842167?u=a9e66fe06965e3830aecb82be4a442874950babe&v=4 + url: https://github.com/Raphasha27 +- login: yudin-s + count: 6 + avatarUrl: https://avatars.githubusercontent.com/u/781481?u=8c1ab221edbe051eb55310747ebe39574e808118&v=4 + url: https://github.com/yudin-s +- login: svlandeg + count: 5 + avatarUrl: https://avatars.githubusercontent.com/u/8796347?u=556c97650c27021911b0b9447ec55e75987b0e8a&v=4 + url: https://github.com/svlandeg +- login: tiangolo + count: 5 + avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 + url: https://github.com/tiangolo +- login: luzzodev + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/27291415?u=5607ae1ce75c5f54f09500ca854227f7bfd2033b&v=4 + url: https://github.com/luzzodev +- login: sueun-dev + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/57546981?u=0b0483bdcc7d521e85c06f28d2fc64e258bd466f&v=4 + url: https://github.com/sueun-dev +- login: cookesan + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/6601329?u=7bfc9b017198a9fa50929ae8ae0a787632424ffd&v=4 + url: https://github.com/cookesan +- login: ericgitangu + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/11472845?u=9d916cf0f5c80e63cb1d753b8b50dcb8ced3b883&v=4 + url: https://github.com/ericgitangu +- login: BitWeaverDev + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/288751066?u=60ef471e6d3822b99c9a3e7624d510b911004434&v=4 + url: https://github.com/BitWeaverDev +- login: vincere-mori + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/57835745?u=37d4cd4a763163dd03f29eff4975c2f1fa2a2d72&v=4 + url: https://github.com/vincere-mori +- login: Zawwarsami16 + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/105767627?u=5bb2b7a639a9207a5ded536f963a4c7bd6d04d21&v=4 + url: https://github.com/Zawwarsami16 +- login: thanos07 + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/68923656?u=dab6d4d9a6800f7d44d8c6df0b9904e17c2ecdb7&v=4 + url: https://github.com/thanos07 +- login: MajorDallas + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/79329882?u=e611ed986e4a37fd16ab69116a4600d95bfff294&v=4 + url: https://github.com/MajorDallas +- login: Francis1998 + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/66462431?u=20bdf51356ee7d99a8c8755c09460950d2b84fd0&v=4 + url: https://github.com/Francis1998 +- login: RichieB2B + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/1461970?u=edaa57d1077705244ea5c9244f4783d94ff11f12&v=4 + url: https://github.com/RichieB2B +- login: abdurrahman310303 + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/121820588?u=73c72a59ca082ceb8507bb1e2b559e59bdf2358f&v=4 + url: https://github.com/abdurrahman310303 +- login: Hassanmahmood4 + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/193066885?u=0e05f82009f99c53b16781d06a7f8d5fea8cc433&v=4 + url: https://github.com/Hassanmahmood4 +- login: mg1986jp + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/20254686?u=6da9cdad3ecf8a4f3cbc33a518c3998ed0ac685a&v=4 + url: https://github.com/mg1986jp +- login: Bogdusik + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/166155258?u=11440b02966a3f5e5eeebc21d67b7bbb7d370487&v=4 + url: https://github.com/Bogdusik +- login: coleifer + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/119974?u=b3a546c94ee1105e792e0acad2c4743d800e7975&v=4 + url: https://github.com/coleifer +- login: Bahtya + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/34988899?u=b8e3c0cf26f4bd1faea265d2f5f66f564af63463&v=4 + url: https://github.com/Bahtya +- login: DoctorJohn + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/14076775?u=ec43fe79a98dbc864b428afc7220753e25ca3af2&v=4 + url: https://github.com/DoctorJohn +six_months_experts: +- login: YuriiMotov + count: 127 + avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=bc48be95c429989224786106b027f3c5e40cc354&v=4 + url: https://github.com/YuriiMotov +- login: JavierSanchezCastro + count: 10 + avatarUrl: https://avatars.githubusercontent.com/u/72013291?u=ae5679e6bd971d9d98cd5e76e8683f83642ba950&v=4 + url: https://github.com/JavierSanchezCastro +- login: tiangolo + count: 10 + avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 + url: https://github.com/tiangolo +- login: luzzodev + count: 7 + avatarUrl: https://avatars.githubusercontent.com/u/27291415?u=5607ae1ce75c5f54f09500ca854227f7bfd2033b&v=4 + url: https://github.com/luzzodev +- login: Firatasi + count: 7 + avatarUrl: https://avatars.githubusercontent.com/u/112112161?u=3219914a49a4a604b3626007823db7de049b6d66&v=4 + url: https://github.com/Firatasi +- login: Raphasha27 + count: 6 + avatarUrl: https://avatars.githubusercontent.com/u/220842167?u=a9e66fe06965e3830aecb82be4a442874950babe&v=4 + url: https://github.com/Raphasha27 +- login: yudin-s + count: 6 + avatarUrl: https://avatars.githubusercontent.com/u/781481?u=8c1ab221edbe051eb55310747ebe39574e808118&v=4 + url: https://github.com/yudin-s +- login: svlandeg + count: 5 + avatarUrl: https://avatars.githubusercontent.com/u/8796347?u=556c97650c27021911b0b9447ec55e75987b0e8a&v=4 + url: https://github.com/svlandeg +- login: sueun-dev + count: 5 + avatarUrl: https://avatars.githubusercontent.com/u/57546981?u=0b0483bdcc7d521e85c06f28d2fc64e258bd466f&v=4 + url: https://github.com/sueun-dev +- login: Toygarmetu + count: 5 + avatarUrl: https://avatars.githubusercontent.com/u/92878791?u=538530cb6d5554e71f9c28709d794db9a74d23d9&v=4 + url: https://github.com/Toygarmetu +- login: ceb10n + count: 5 + avatarUrl: https://avatars.githubusercontent.com/u/235213?u=edcce471814a1eba9f0cdaa4cd0de18921a940a6&v=4 + url: https://github.com/ceb10n +- login: RichieB2B + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/1461970?u=edaa57d1077705244ea5c9244f4783d94ff11f12&v=4 + url: https://github.com/RichieB2B +- login: cookesan + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/6601329?u=7bfc9b017198a9fa50929ae8ae0a787632424ffd&v=4 + url: https://github.com/cookesan +- login: ericgitangu + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/11472845?u=9d916cf0f5c80e63cb1d753b8b50dcb8ced3b883&v=4 + url: https://github.com/ericgitangu +- login: BitWeaverDev + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/288751066?u=60ef471e6d3822b99c9a3e7624d510b911004434&v=4 + url: https://github.com/BitWeaverDev +- login: vincere-mori + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/57835745?u=37d4cd4a763163dd03f29eff4975c2f1fa2a2d72&v=4 + url: https://github.com/vincere-mori +- login: valentinDruzhinin + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/12831905?u=aae1ebc675c91e8fa582df4fcc4fc4128106344d&v=4 + url: https://github.com/valentinDruzhinin +- login: Zawwarsami16 + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/105767627?u=5bb2b7a639a9207a5ded536f963a4c7bd6d04d21&v=4 + url: https://github.com/Zawwarsami16 +- login: EmmanuelNiyonshuti + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/142030687?u=ab131d5ad4670280a978f489babe71c9bf9c1097&v=4 + url: https://github.com/EmmanuelNiyonshuti +- login: thanos07 + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/68923656?u=dab6d4d9a6800f7d44d8c6df0b9904e17c2ecdb7&v=4 + url: https://github.com/thanos07 +- login: MajorDallas + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/79329882?u=e611ed986e4a37fd16ab69116a4600d95bfff294&v=4 + url: https://github.com/MajorDallas +- login: Francis1998 + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/66462431?u=20bdf51356ee7d99a8c8755c09460950d2b84fd0&v=4 + url: https://github.com/Francis1998 +- login: abdurrahman310303 + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/121820588?u=73c72a59ca082ceb8507bb1e2b559e59bdf2358f&v=4 + url: https://github.com/abdurrahman310303 +- login: Hassanmahmood4 + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/193066885?u=0e05f82009f99c53b16781d06a7f8d5fea8cc433&v=4 + url: https://github.com/Hassanmahmood4 +- login: Kludex + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=df8a3f06ba8f55ae1967a3e2d5ed882903a4e330&v=4 + url: https://github.com/Kludex +- login: mg1986jp + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/20254686?u=6da9cdad3ecf8a4f3cbc33a518c3998ed0ac685a&v=4 + url: https://github.com/mg1986jp +- login: Bogdusik + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/166155258?u=11440b02966a3f5e5eeebc21d67b7bbb7d370487&v=4 + url: https://github.com/Bogdusik +- login: sachinh35 + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/21972708?u=8560b97b8b41e175f476270b56de8a493b84f302&v=4 + url: https://github.com/sachinh35 +- login: coleifer + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/119974?u=b3a546c94ee1105e792e0acad2c4743d800e7975&v=4 + url: https://github.com/coleifer +- login: Bahtya + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/34988899?u=b8e3c0cf26f4bd1faea265d2f5f66f564af63463&v=4 + url: https://github.com/Bahtya +- login: saitarrun + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/116748905?u=3433afbaf06676a482ebf4ba33b08ddb3fc5c5bf&v=4 + url: https://github.com/saitarrun +- login: christiansousadev + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/103544118?u=690f3f76d1dc4d0929de5020679d5604f860acbc&v=4 + url: https://github.com/christiansousadev +- login: DoctorJohn + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/14076775?u=ec43fe79a98dbc864b428afc7220753e25ca3af2&v=4 + url: https://github.com/DoctorJohn +- login: gaardhus + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/46934916?u=18d7aacc6ce59f054749209645d11cfe77b52f90&v=4 + url: https://github.com/gaardhus +- login: dotmitsu + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/42657211?u=3bccc9a2f386a3f24230ec393080f8904fe2a5b2&v=4 + url: https://github.com/dotmitsu +one_year_experts: +- login: YuriiMotov + count: 344 + avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=bc48be95c429989224786106b027f3c5e40cc354&v=4 + url: https://github.com/YuriiMotov +- login: tiangolo + count: 34 + avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 + url: https://github.com/tiangolo +- login: luzzodev + count: 31 + avatarUrl: https://avatars.githubusercontent.com/u/27291415?u=5607ae1ce75c5f54f09500ca854227f7bfd2033b&v=4 + url: https://github.com/luzzodev +- login: valentinDruzhinin + count: 19 + avatarUrl: https://avatars.githubusercontent.com/u/12831905?u=aae1ebc675c91e8fa582df4fcc4fc4128106344d&v=4 + url: https://github.com/valentinDruzhinin +- login: JavierSanchezCastro + count: 17 + avatarUrl: https://avatars.githubusercontent.com/u/72013291?u=ae5679e6bd971d9d98cd5e76e8683f83642ba950&v=4 + url: https://github.com/JavierSanchezCastro +- login: svlandeg + count: 10 + avatarUrl: https://avatars.githubusercontent.com/u/8796347?u=556c97650c27021911b0b9447ec55e75987b0e8a&v=4 + url: https://github.com/svlandeg +- login: RichieB2B + count: 7 + avatarUrl: https://avatars.githubusercontent.com/u/1461970?u=edaa57d1077705244ea5c9244f4783d94ff11f12&v=4 + url: https://github.com/RichieB2B +- login: Firatasi + count: 7 + avatarUrl: https://avatars.githubusercontent.com/u/112112161?u=3219914a49a4a604b3626007823db7de049b6d66&v=4 + url: https://github.com/Firatasi +- login: Raphasha27 + count: 6 + avatarUrl: https://avatars.githubusercontent.com/u/220842167?u=a9e66fe06965e3830aecb82be4a442874950babe&v=4 + url: https://github.com/Raphasha27 +- login: yudin-s + count: 6 + avatarUrl: https://avatars.githubusercontent.com/u/781481?u=8c1ab221edbe051eb55310747ebe39574e808118&v=4 + url: https://github.com/yudin-s +- login: sueun-dev + count: 5 + avatarUrl: https://avatars.githubusercontent.com/u/57546981?u=0b0483bdcc7d521e85c06f28d2fc64e258bd466f&v=4 + url: https://github.com/sueun-dev +- login: sachinh35 + count: 5 + avatarUrl: https://avatars.githubusercontent.com/u/21972708?u=8560b97b8b41e175f476270b56de8a493b84f302&v=4 + url: https://github.com/sachinh35 +- login: Toygarmetu + count: 5 + avatarUrl: https://avatars.githubusercontent.com/u/92878791?u=538530cb6d5554e71f9c28709d794db9a74d23d9&v=4 + url: https://github.com/Toygarmetu +- login: ceb10n + count: 5 + avatarUrl: https://avatars.githubusercontent.com/u/235213?u=edcce471814a1eba9f0cdaa4cd0de18921a940a6&v=4 + url: https://github.com/ceb10n +- login: yinziyan1206 + count: 5 + avatarUrl: https://avatars.githubusercontent.com/u/37829370?u=da44ca53aefd5c23f346fab8e9fd2e108294c179&v=4 + url: https://github.com/yinziyan1206 +- login: JunjieAraoXiong + count: 5 + avatarUrl: https://avatars.githubusercontent.com/u/167785867?u=b69afe090c8bf5fd73f2d23fc3a887b28f68f192&v=4 + url: https://github.com/JunjieAraoXiong +- login: WilliamDEdwards + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/12184311?u=9b29d5d1d71f5f1a7ef9e439963ad3529e3b33a4&v=4 + url: https://github.com/WilliamDEdwards +- login: ArmanShirzad + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/68951175?u=1f1efae2fa5d0d17c38a1a8413bedca5e538cedb&v=4 + url: https://github.com/ArmanShirzad +- login: CodeKraken-cmd + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/48470371?u=e7c0e7ec8e35ca5fb3ae40a586ed5e788fd0fe6d&v=4 + url: https://github.com/CodeKraken-cmd +- login: krylosov-aa + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/242901957?u=4c9c7b468203b09bca64936fb464620e32cdd252&v=4 + url: https://github.com/krylosov-aa +- login: isgin01 + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/157279130?u=16d6466476cf7dbc55a4cd575b6ea920ebdd81e1&v=4 + url: https://github.com/isgin01 +- login: cookesan + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/6601329?u=7bfc9b017198a9fa50929ae8ae0a787632424ffd&v=4 + url: https://github.com/cookesan +- login: ericgitangu + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/11472845?u=9d916cf0f5c80e63cb1d753b8b50dcb8ced3b883&v=4 + url: https://github.com/ericgitangu +- login: BitWeaverDev + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/288751066?u=60ef471e6d3822b99c9a3e7624d510b911004434&v=4 + url: https://github.com/BitWeaverDev +- login: vincere-mori + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/57835745?u=37d4cd4a763163dd03f29eff4975c2f1fa2a2d72&v=4 + url: https://github.com/vincere-mori +- login: Kludex + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=df8a3f06ba8f55ae1967a3e2d5ed882903a4e330&v=4 + url: https://github.com/Kludex +- login: Zawwarsami16 + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/105767627?u=5bb2b7a639a9207a5ded536f963a4c7bd6d04d21&v=4 + url: https://github.com/Zawwarsami16 +- login: EmmanuelNiyonshuti + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/142030687?u=ab131d5ad4670280a978f489babe71c9bf9c1097&v=4 + url: https://github.com/EmmanuelNiyonshuti +- login: dolfinus + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/4661021?u=ed5ddadcf36d9b943ebe61febe0b96ee34e5425d&v=4 + url: https://github.com/dolfinus +- login: simone-trubian + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/5606840?u=65703af3c605feca61ce49e4009bb4e26495b425&v=4 + url: https://github.com/simone-trubian +- login: mahimairaja + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/81288263?u=4eef6b4a36b96e84bd666fc1937aa589036ccb9a&v=4 + url: https://github.com/mahimairaja +- login: pankeshpatel + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/1482917?u=666f39197a88cfa38b8bd78d39ef04d95c948b6b&v=4 + url: https://github.com/pankeshpatel +- login: Jelle-tenB + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/210023470?u=c25d66addf36a747bd9fab773c4a6e7b238f45d4&v=4 + url: https://github.com/Jelle-tenB +- login: thanos07 + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/68923656?u=dab6d4d9a6800f7d44d8c6df0b9904e17c2ecdb7&v=4 + url: https://github.com/thanos07 +- login: MajorDallas + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/79329882?u=e611ed986e4a37fd16ab69116a4600d95bfff294&v=4 + url: https://github.com/MajorDallas +- login: Francis1998 + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/66462431?u=20bdf51356ee7d99a8c8755c09460950d2b84fd0&v=4 + url: https://github.com/Francis1998 +- login: Garrett-R + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/6614695?u=c128fd775002882f6e391bda5a89d1bdc5bdf45f&v=4 + url: https://github.com/Garrett-R +- login: abdurrahman310303 + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/121820588?u=73c72a59ca082ceb8507bb1e2b559e59bdf2358f&v=4 + url: https://github.com/abdurrahman310303 +- login: Hassanmahmood4 + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/193066885?u=0e05f82009f99c53b16781d06a7f8d5fea8cc433&v=4 + url: https://github.com/Hassanmahmood4 +- login: mg1986jp + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/20254686?u=6da9cdad3ecf8a4f3cbc33a518c3998ed0ac685a&v=4 + url: https://github.com/mg1986jp +- login: Bogdusik + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/166155258?u=11440b02966a3f5e5eeebc21d67b7bbb7d370487&v=4 + url: https://github.com/Bogdusik +- login: coleifer + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/119974?u=b3a546c94ee1105e792e0acad2c4743d800e7975&v=4 + url: https://github.com/coleifer +- login: Bahtya + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/34988899?u=b8e3c0cf26f4bd1faea265d2f5f66f564af63463&v=4 + url: https://github.com/Bahtya +- login: saitarrun + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/116748905?u=3433afbaf06676a482ebf4ba33b08ddb3fc5c5bf&v=4 + url: https://github.com/saitarrun +- login: cepedus + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/26345924?u=38495abbdbb8695dd76478cae5963bf994c498bc&v=4 + url: https://github.com/cepedus +- login: christiansousadev + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/103544118?u=690f3f76d1dc4d0929de5020679d5604f860acbc&v=4 + url: https://github.com/christiansousadev +- login: DoctorJohn + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/14076775?u=ec43fe79a98dbc864b428afc7220753e25ca3af2&v=4 + url: https://github.com/DoctorJohn +- login: gaardhus + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/46934916?u=18d7aacc6ce59f054749209645d11cfe77b52f90&v=4 + url: https://github.com/gaardhus +- login: y2kbugger + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/6101677?u=1d50077e29582dc01fcbdff846f04fe7ec73fe2e&v=4 + url: https://github.com/y2kbugger +- login: stan-dot + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/56644812?u=a7dd773084f1c17c5f05019cc25a984e24873691&v=4 + url: https://github.com/stan-dot +- login: huynguyengl99 + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/49433085?u=7b626115686c5d97a2a32a03119f5300e425cc9f&v=4 + url: https://github.com/huynguyengl99 +- login: davidbrochart + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/4711805?u=d39696d995a9e02ec3613ffb2f62b20b14f92f26&v=4 + url: https://github.com/davidbrochart +- login: CharlieReitzel + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/20848272?v=4 + url: https://github.com/CharlieReitzel +- login: kiranzo + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/1070878?u=68f78a891c9751dd87571ac712a6309090c4bc01&v=4 + url: https://github.com/kiranzo +- login: dotmitsu + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/42657211?u=3bccc9a2f386a3f24230ec393080f8904fe2a5b2&v=4 + url: https://github.com/dotmitsu +- login: usiqwerty + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/37992525?u=0c6e91d7b3887aa558755f4225ce74a003cbe852&v=4 + url: https://github.com/usiqwerty +- login: skion + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/532192?v=4 + url: https://github.com/skion +- login: florentx + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/142113?u=bf10f10080026346b092633c380977b61cee0d9c&v=4 + url: https://github.com/florentx +- login: jc-louis + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/51329768?v=4 + url: https://github.com/jc-louis +- login: bughuntr7 + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/236391583?u=7f51ff690e3a5711f845a115903c39e21c8af938&v=4 + url: https://github.com/bughuntr7 diff --git a/docs/en/data/skip_users.yml b/docs/en/data/skip_users.yml new file mode 100644 index 0000000000000..cf24003af8ac5 --- /dev/null +++ b/docs/en/data/skip_users.yml @@ -0,0 +1,5 @@ +- tiangolo +- codecov +- github-actions +- pre-commit-ci +- dependabot diff --git a/docs/en/data/sponsors.yml b/docs/en/data/sponsors.yml new file mode 100644 index 0000000000000..f2e5df57170b0 --- /dev/null +++ b/docs/en/data/sponsors.yml @@ -0,0 +1,66 @@ +keystone: + - url: https://fastapicloud.com + title: FastAPI Cloud. By the same team behind FastAPI. You code. We Cloud. + img: /img/sponsors/fastapicloud.png +gold: + - url: https://blockbee.io?ref=fastapi + title: BlockBee Cryptocurrency Payment Gateway + img: /img/sponsors/blockbee.png + banner_img: /img/sponsors/blockbee-banner.png + - url: https://www.propelauth.com/?utm_source=fastapi&utm_campaign=1223&utm_medium=mainbadge + title: Auth, user management and more for your B2B product + img: /img/sponsors/propelauth.png + banner_url: https://www.propelauth.com/?utm_source=fastapi&utm_campaign=1223&utm_medium=topbanner + banner_img: /img/sponsors/propelauth-banner.png + - url: https://docs.render.com/deploy-fastapi?utm_source=deploydoc&utm_medium=referral&utm_campaign=fastapi + title: Deploy & scale any full-stack web app on Render. Focus on building apps, not infra. + img: /img/sponsors/render.svg + banner_img: /img/sponsors/render-banner.svg + - url: https://www.coderabbit.ai/?utm_source=fastapi&utm_medium=badge&utm_campaign=fastapi + title: Cut Code Review Time & Bugs in Half with CodeRabbit + img: /img/sponsors/coderabbit.png + banner_url: https://www.coderabbit.ai/?utm_source=fastapi&utm_medium=banner&utm_campaign=fastapi + banner_img: /img/sponsors/coderabbit-banner.png + - url: https://subtotal.com/?utm_source=fastapi&utm_medium=sponsorship&utm_campaign=open-source + title: The Gold Standard in Retail Account Linking + img: /img/sponsors/subtotal.svg + banner_title: Making Retail Purchases Actionable for Brands and Developers + banner_img: /img/sponsors/subtotal-banner.svg + - url: https://docs.railway.com/guides/fastapi?utm_medium=integration&utm_source=docs&utm_campaign=fastapi + title: Deploy enterprise applications at startup speed + img: /img/sponsors/railway.png + banner_img: /img/sponsors/railway-banner.png + - url: https://serpapi.com/?utm_source=fastapi_website + title: "SerpApi: Web Search API" + img: /img/sponsors/serpapi.png + banner_img: /img/sponsors/serpapi-banner.png + - url: https://www.greptile.com/?utm_source=fastapi&utm_medium=sponsorship&utm_campaign=fastapi_sponsor_page + title: "Greptile: The AI Code Reviewer" + img: /img/sponsors/greptile.png + banner_img: /img/sponsors/greptile-banner.png +silver: + - url: https://databento.com/?utm_source=fastapi&utm_medium=sponsor&utm_content=display + title: Pay as you go for market data + img: /img/sponsors/databento.svg + - url: https://www.svix.com/ + title: Svix - Webhooks as a service + img: /img/sponsors/svix.svg + - url: https://www.permit.io/blog/implement-authorization-in-fastapi?utm_source=github&utm_medium=referral&utm_campaign=fastapi + title: Fine-Grained Authorization for FastAPI + img: /img/sponsors/permit.png + - url: https://dribia.com/en/ + title: Dribia - Data Science within your reach + img: /img/sponsors/dribia.png + - url: https://www.bairesdev.com/ + title: "BairesDev | Nearshore Software Development & Staff Augmentation Company" + img: /img/sponsors/bairesdev.svg + - url: https://tutorcruncher.com/?utm_source=fastapi + title: TutorCruncher + img: /img/sponsors/tutorcruncher.png +bronze: + # - url: https://testdriven.io/courses/tdd-fastapi/ + # title: Learn to build high-quality web apps with best practices + # img: /img/sponsors/testdriven.svg + - url: https://www.testmu.ai/?utm_source=fastapi&utm_medium=partner&utm_campaign=sponsor&utm_term=opensource&utm_content=webpage + title: TestMu AI. The Native AI-Agentic Cloud Platform to Supercharge Quality Engineering. + img: /img/sponsors/testmu.png diff --git a/docs/en/data/sponsors_badge.yml b/docs/en/data/sponsors_badge.yml new file mode 100644 index 0000000000000..d2fd7029f3f8c --- /dev/null +++ b/docs/en/data/sponsors_badge.yml @@ -0,0 +1,52 @@ +logins: + - jina-ai + - deta + - investsuite + - mikeckennedy + - deepset-ai + - cryptapi + - xoflare + - DropbaseHQ + - VincentParedes + - BLUE-DEVIL1134 + - ObliviousAI + - Doist + - nihpo + - armand-sauzay + - databento-bot + - databento + - nanram22 + - Flint-company + - porter-dev + - fern-api + - ndimares + - svixhq + - Alek99 + - codacy + - zanfaruqui + - scalar + - bump-sh + - andrew-propelauth + - svix + - zuplo-oss + - zuplo + - Kong + - speakeasy-api + - jess-render + - blockbee-io + - liblaber + - render-sponsorships + - renderinc + - stainless-api + - snapit-cypher + - coderabbitai + - permitio + - LambdaTest-Inc + - dribia + - madisonredtfeldt + - railwayapp + - subtotal + - requestly + - greptileai + - talorelowen + - tutorcruncher diff --git a/docs/en/data/topic_repos.yml b/docs/en/data/topic_repos.yml new file mode 100644 index 0000000000000..ecfad6cb44f16 --- /dev/null +++ b/docs/en/data/topic_repos.yml @@ -0,0 +1,495 @@ +- name: headroom + html_url: https://github.com/headroomlabs-ai/headroom + stars: 55017 + owner_login: headroomlabs-ai + owner_html_url: https://github.com/headroomlabs-ai +- name: full-stack-fastapi-template + html_url: https://github.com/fastapi/full-stack-fastapi-template + stars: 43994 + owner_login: fastapi + owner_html_url: https://github.com/fastapi +- name: Hello-Python + html_url: https://github.com/mouredev/Hello-Python + stars: 36226 + owner_login: mouredev + owner_html_url: https://github.com/mouredev +- name: serve + html_url: https://github.com/jina-ai/serve + stars: 21862 + owner_login: jina-ai + owner_html_url: https://github.com/jina-ai +- name: HivisionIDPhotos + html_url: https://github.com/Zeyi-Lin/HivisionIDPhotos + stars: 21212 + owner_login: Zeyi-Lin + owner_html_url: https://github.com/Zeyi-Lin +- name: Douyin_TikTok_Download_API + html_url: https://github.com/Evil0ctal/Douyin_TikTok_Download_API + stars: 18599 + owner_login: Evil0ctal + owner_html_url: https://github.com/Evil0ctal +- name: sqlmodel + html_url: https://github.com/fastapi/sqlmodel + stars: 18156 + owner_login: fastapi + owner_html_url: https://github.com/fastapi +- name: fastapi-best-practices + html_url: https://github.com/zhanymkanov/fastapi-best-practices + stars: 17608 + owner_login: zhanymkanov + owner_html_url: https://github.com/zhanymkanov +- name: SurfSense + html_url: https://github.com/MODSetter/SurfSense + stars: 15161 + owner_login: MODSetter + owner_html_url: https://github.com/MODSetter +- name: machine-learning-zoomcamp + html_url: https://github.com/DataTalksClub/machine-learning-zoomcamp + stars: 13445 + owner_login: DataTalksClub + owner_html_url: https://github.com/DataTalksClub +- name: peewee + html_url: https://github.com/coleifer/peewee + stars: 11976 + owner_login: coleifer + owner_html_url: https://github.com/coleifer +- name: fastapi_mcp + html_url: https://github.com/tadata-org/fastapi_mcp + stars: 11932 + owner_login: tadata-org + owner_html_url: https://github.com/tadata-org +- name: XHS-Downloader + html_url: https://github.com/JoeanAmier/XHS-Downloader + stars: 11768 + owner_login: JoeanAmier + owner_html_url: https://github.com/JoeanAmier +- name: awesome-fastapi + html_url: https://github.com/mjhea0/awesome-fastapi + stars: 11478 + owner_login: mjhea0 + owner_html_url: https://github.com/mjhea0 +- name: polar + html_url: https://github.com/polarsource/polar + stars: 9999 + owner_login: polarsource + owner_html_url: https://github.com/polarsource +- name: pycaret + html_url: https://github.com/pycaret/pycaret + stars: 9818 + owner_login: pycaret + owner_html_url: https://github.com/pycaret +- name: FastUI + html_url: https://github.com/pydantic/FastUI + stars: 8970 + owner_login: pydantic + owner_html_url: https://github.com/pydantic +- name: FileCodeBox + html_url: https://github.com/vastsa/FileCodeBox + stars: 8376 + owner_login: vastsa + owner_html_url: https://github.com/vastsa +- name: nonebot2 + html_url: https://github.com/nonebot/nonebot2 + stars: 7593 + owner_login: nonebot + owner_html_url: https://github.com/nonebot +- name: hatchet + html_url: https://github.com/hatchet-dev/hatchet + stars: 7441 + owner_login: hatchet-dev + owner_html_url: https://github.com/hatchet-dev +- name: fastapi-users + html_url: https://github.com/fastapi-users/fastapi-users + stars: 6182 + owner_login: fastapi-users + owner_html_url: https://github.com/fastapi-users +- name: Yuxi + html_url: https://github.com/xerrors/Yuxi + stars: 5926 + owner_login: xerrors + owner_html_url: https://github.com/xerrors +- name: serge + html_url: https://github.com/serge-chat/serge + stars: 5723 + owner_login: serge-chat + owner_html_url: https://github.com/serge-chat +- name: honcho + html_url: https://github.com/plastic-labs/honcho + stars: 5680 + owner_login: plastic-labs + owner_html_url: https://github.com/plastic-labs +- name: Kokoro-FastAPI + html_url: https://github.com/remsky/Kokoro-FastAPI + stars: 5085 + owner_login: remsky + owner_html_url: https://github.com/remsky +- name: devpush + html_url: https://github.com/hunvreus/devpush + stars: 4693 + owner_login: hunvreus + owner_html_url: https://github.com/hunvreus +- name: strawberry + html_url: https://github.com/strawberry-graphql/strawberry + stars: 4677 + owner_login: strawberry-graphql + owner_html_url: https://github.com/strawberry-graphql +- name: poem + html_url: https://github.com/poem-web/poem + stars: 4415 + owner_login: poem-web + owner_html_url: https://github.com/poem-web +- name: logfire + html_url: https://github.com/pydantic/logfire + stars: 4340 + owner_login: pydantic + owner_html_url: https://github.com/pydantic +- name: dynaconf + html_url: https://github.com/dynaconf/dynaconf + stars: 4310 + owner_login: dynaconf + owner_html_url: https://github.com/dynaconf +- name: chatgpt-web-share + html_url: https://github.com/chatpire/chatgpt-web-share + stars: 4269 + owner_login: chatpire + owner_html_url: https://github.com/chatpire +- name: huma + html_url: https://github.com/danielgtaylor/huma + stars: 4203 + owner_login: danielgtaylor + owner_html_url: https://github.com/danielgtaylor +- name: atrilabs-engine + html_url: https://github.com/Atri-Labs/atrilabs-engine + stars: 4071 + owner_login: Atri-Labs + owner_html_url: https://github.com/Atri-Labs +- name: mcp-context-forge + html_url: https://github.com/IBM/mcp-context-forge + stars: 3989 + owner_login: IBM + owner_html_url: https://github.com/IBM +- name: datamodel-code-generator + html_url: https://github.com/koxudaxi/datamodel-code-generator + stars: 3952 + owner_login: koxudaxi + owner_html_url: https://github.com/koxudaxi +- name: LitServe + html_url: https://github.com/Lightning-AI/LitServe + stars: 3901 + owner_login: Lightning-AI + owner_html_url: https://github.com/Lightning-AI +- name: fastapi-admin + html_url: https://github.com/fastapi-admin/fastapi-admin + stars: 3799 + owner_login: fastapi-admin + owner_html_url: https://github.com/fastapi-admin +- name: tracecat + html_url: https://github.com/TracecatHQ/tracecat + stars: 3703 + owner_login: TracecatHQ + owner_html_url: https://github.com/TracecatHQ +- name: farfalle + html_url: https://github.com/rashadphz/farfalle + stars: 3535 + owner_login: rashadphz + owner_html_url: https://github.com/rashadphz +- name: Rapid-MLX + html_url: https://github.com/raullenchai/Rapid-MLX + stars: 3155 + owner_login: raullenchai + owner_html_url: https://github.com/raullenchai +- name: opyrator + html_url: https://github.com/ml-tooling/opyrator + stars: 3133 + owner_login: ml-tooling + owner_html_url: https://github.com/ml-tooling +- name: docarray + html_url: https://github.com/docarray/docarray + stars: 3121 + owner_login: docarray + owner_html_url: https://github.com/docarray +- name: fastapi-realworld-example-app + html_url: https://github.com/nsidnev/fastapi-realworld-example-app + stars: 3109 + owner_login: nsidnev + owner_html_url: https://github.com/nsidnev +- name: uvicorn-gunicorn-fastapi-docker + html_url: https://github.com/tiangolo/uvicorn-gunicorn-fastapi-docker + stars: 2914 + owner_login: tiangolo + owner_html_url: https://github.com/tiangolo +- name: any-auto-register + html_url: https://github.com/lxf746/any-auto-register + stars: 2832 + owner_login: lxf746 + owner_html_url: https://github.com/lxf746 +- name: FastAPI-template + html_url: https://github.com/s3rius/FastAPI-template + stars: 2810 + owner_login: s3rius + owner_html_url: https://github.com/s3rius +- name: YC-Killer + html_url: https://github.com/sahibzada-allahyar/YC-Killer + stars: 2779 + owner_login: sahibzada-allahyar + owner_html_url: https://github.com/sahibzada-allahyar +- name: sqladmin + html_url: https://github.com/smithyhq/sqladmin + stars: 2759 + owner_login: smithyhq + owner_html_url: https://github.com/smithyhq +- name: best-of-web-python + html_url: https://github.com/ml-tooling/best-of-web-python + stars: 2731 + owner_login: ml-tooling + owner_html_url: https://github.com/ml-tooling +- name: NoteDiscovery + html_url: https://github.com/gamosoft/NoteDiscovery + stars: 2595 + owner_login: gamosoft + owner_html_url: https://github.com/gamosoft +- name: fastapi-react + html_url: https://github.com/Buuntu/fastapi-react + stars: 2588 + owner_login: Buuntu + owner_html_url: https://github.com/Buuntu +- name: supabase-py + html_url: https://github.com/supabase/supabase-py + stars: 2530 + owner_login: supabase + owner_html_url: https://github.com/supabase +- name: 30-Days-of-Python + html_url: https://github.com/codingforentrepreneurs/30-Days-of-Python + stars: 2483 + owner_login: codingforentrepreneurs + owner_html_url: https://github.com/codingforentrepreneurs +- name: RasaGPT + html_url: https://github.com/paulpierre/RasaGPT + stars: 2462 + owner_login: paulpierre + owner_html_url: https://github.com/paulpierre +- name: fastapi-langgraph-agent-production-ready-template + html_url: https://github.com/wassim249/fastapi-langgraph-agent-production-ready-template + stars: 2456 + owner_login: wassim249 + owner_html_url: https://github.com/wassim249 +- name: AIstudioProxyAPI + html_url: https://github.com/CJackHwang/AIstudioProxyAPI + stars: 2445 + owner_login: CJackHwang + owner_html_url: https://github.com/CJackHwang +- name: nextpy + html_url: https://github.com/dot-agent/nextpy + stars: 2341 + owner_login: dot-agent + owner_html_url: https://github.com/dot-agent +- name: langserve + html_url: https://github.com/langchain-ai/langserve + stars: 2329 + owner_login: langchain-ai + owner_html_url: https://github.com/langchain-ai +- name: fastapi-best-architecture + html_url: https://github.com/fastapi-practices/fastapi-best-architecture + stars: 2318 + owner_login: fastapi-practices + owner_html_url: https://github.com/fastapi-practices +- name: fastapi-utils + html_url: https://github.com/fastapiutils/fastapi-utils + stars: 2308 + owner_login: fastapiutils + owner_html_url: https://github.com/fastapiutils +- name: vue-fastapi-admin + html_url: https://github.com/mizhexiaoxiao/vue-fastapi-admin + stars: 2184 + owner_login: mizhexiaoxiao + owner_html_url: https://github.com/mizhexiaoxiao +- name: solara + html_url: https://github.com/widgetti/solara + stars: 2166 + owner_login: widgetti + owner_html_url: https://github.com/widgetti +- name: mangum + html_url: https://github.com/Kludex/mangum + stars: 2125 + owner_login: Kludex + owner_html_url: https://github.com/Kludex +- name: codex-lb + html_url: https://github.com/Soju06/codex-lb + stars: 2122 + owner_login: Soju06 + owner_html_url: https://github.com/Soju06 +- name: kiro-gateway + html_url: https://github.com/jwadow/kiro-gateway + stars: 2068 + owner_login: jwadow + owner_html_url: https://github.com/jwadow +- name: open-wearables + html_url: https://github.com/the-momentum/open-wearables + stars: 2036 + owner_login: the-momentum + owner_html_url: https://github.com/the-momentum +- name: slowapi + html_url: https://github.com/laurentS/slowapi + stars: 2022 + owner_login: laurentS + owner_html_url: https://github.com/laurentS +- name: xhs_ai_publisher + html_url: https://github.com/BetaStreetOmnis/xhs_ai_publisher + stars: 2004 + owner_login: BetaStreetOmnis + owner_html_url: https://github.com/BetaStreetOmnis +- name: FastAPI-boilerplate + html_url: https://github.com/benavlabs/FastAPI-boilerplate + stars: 1984 + owner_login: benavlabs + owner_html_url: https://github.com/benavlabs +- name: openapi-python-client + html_url: https://github.com/openapi-generators/openapi-python-client + stars: 1967 + owner_login: openapi-generators + owner_html_url: https://github.com/openapi-generators +- name: agentkit + html_url: https://github.com/BCG-X-Official/agentkit + stars: 1944 + owner_login: BCG-X-Official + owner_html_url: https://github.com/BCG-X-Official +- name: piccolo + html_url: https://github.com/piccolo-orm/piccolo + stars: 1922 + owner_login: piccolo-orm + owner_html_url: https://github.com/piccolo-orm +- name: manage-fastapi + html_url: https://github.com/ycd/manage-fastapi + stars: 1905 + owner_login: ycd + owner_html_url: https://github.com/ycd +- name: fastapi-cache + html_url: https://github.com/long2ice/fastapi-cache + stars: 1866 + owner_login: long2ice + owner_html_url: https://github.com/long2ice +- name: ormar + html_url: https://github.com/ormar-orm/ormar + stars: 1806 + owner_login: ormar-orm + owner_html_url: https://github.com/ormar-orm +- name: python-week-2022 + html_url: https://github.com/rochacbruno/python-week-2022 + stars: 1806 + owner_login: rochacbruno + owner_html_url: https://github.com/rochacbruno +- name: WebRPA + html_url: https://github.com/pmh1314520/WebRPA + stars: 1781 + owner_login: pmh1314520 + owner_html_url: https://github.com/pmh1314520 +- name: termpair + html_url: https://github.com/cs01/termpair + stars: 1735 + owner_login: cs01 + owner_html_url: https://github.com/cs01 +- name: fastapi-crudrouter + html_url: https://github.com/awtkns/fastapi-crudrouter + stars: 1694 + owner_login: awtkns + owner_html_url: https://github.com/awtkns +- name: bracket + html_url: https://github.com/evroon/bracket + stars: 1694 + owner_login: evroon + owner_html_url: https://github.com/evroon +- name: fastapi-pagination + html_url: https://github.com/uriyyo/fastapi-pagination + stars: 1670 + owner_login: uriyyo + owner_html_url: https://github.com/uriyyo +- name: langchain-serve + html_url: https://github.com/jina-ai/langchain-serve + stars: 1640 + owner_login: jina-ai + owner_html_url: https://github.com/jina-ai +- name: awesome-fastapi-projects + html_url: https://github.com/Kludex/awesome-fastapi-projects + stars: 1608 + owner_login: Kludex + owner_html_url: https://github.com/Kludex +- name: coronavirus-tracker-api + html_url: https://github.com/ExpDev07/coronavirus-tracker-api + stars: 1568 + owner_login: ExpDev07 + owner_html_url: https://github.com/ExpDev07 +- name: fastapi-amis-admin + html_url: https://github.com/amisadmin/fastapi-amis-admin + stars: 1559 + owner_login: amisadmin + owner_html_url: https://github.com/amisadmin +- name: fastcrud + html_url: https://github.com/benavlabs/fastcrud + stars: 1531 + owner_login: benavlabs + owner_html_url: https://github.com/benavlabs +- name: tavily-key-generator + html_url: https://github.com/skernelx/tavily-key-generator + stars: 1526 + owner_login: skernelx + owner_html_url: https://github.com/skernelx +- name: fastapi-boilerplate + html_url: https://github.com/teamhide/fastapi-boilerplate + stars: 1491 + owner_login: teamhide + owner_html_url: https://github.com/teamhide +- name: full-stack-ai-agent-template + html_url: https://github.com/vstorm-co/full-stack-ai-agent-template + stars: 1484 + owner_login: vstorm-co + owner_html_url: https://github.com/vstorm-co +- name: prometheus-fastapi-instrumentator + html_url: https://github.com/trallnag/prometheus-fastapi-instrumentator + stars: 1471 + owner_login: trallnag + owner_html_url: https://github.com/trallnag +- name: awesome-python-resources + html_url: https://github.com/DjangoEx/awesome-python-resources + stars: 1451 + owner_login: DjangoEx + owner_html_url: https://github.com/DjangoEx +- name: aktools + html_url: https://github.com/akfamily/aktools + stars: 1431 + owner_login: akfamily + owner_html_url: https://github.com/akfamily +- name: RuoYi-Vue3-FastAPI + html_url: https://github.com/insistence/RuoYi-Vue3-FastAPI + stars: 1419 + owner_login: insistence + owner_html_url: https://github.com/insistence +- name: fastapi-tutorial + html_url: https://github.com/liaogx/fastapi-tutorial + stars: 1418 + owner_login: liaogx + owner_html_url: https://github.com/liaogx +- name: fastapi-code-generator + html_url: https://github.com/koxudaxi/fastapi-code-generator + stars: 1396 + owner_login: koxudaxi + owner_html_url: https://github.com/koxudaxi +- name: yubal + html_url: https://github.com/guillevc/yubal + stars: 1388 + owner_login: guillevc + owner_html_url: https://github.com/guillevc +- name: budgetml + html_url: https://github.com/ebhy/budgetml + stars: 1343 + owner_login: ebhy + owner_html_url: https://github.com/ebhy +- name: Chatterbox-TTS-Server + html_url: https://github.com/devnen/Chatterbox-TTS-Server + stars: 1328 + owner_login: devnen + owner_html_url: https://github.com/devnen +- name: restish + html_url: https://github.com/rest-sh/restish + stars: 1321 + owner_login: rest-sh + owner_html_url: https://github.com/rest-sh diff --git a/docs/en/data/translation_reviewers.yml b/docs/en/data/translation_reviewers.yml new file mode 100644 index 0000000000000..ccc4d604f0f79 --- /dev/null +++ b/docs/en/data/translation_reviewers.yml @@ -0,0 +1,1885 @@ +s111d: + login: s111d + count: 147 + avatarUrl: https://avatars.githubusercontent.com/u/4954856?v=4 + url: https://github.com/s111d +Xewus: + login: Xewus + count: 140 + avatarUrl: https://avatars.githubusercontent.com/u/85196001?u=f8e2dc7e5104f109cef944af79050ea8d1b8f914&v=4 + url: https://github.com/Xewus +sodaMelon: + login: sodaMelon + count: 128 + avatarUrl: https://avatars.githubusercontent.com/u/66295123?u=be939db90f1119efee9e6110cc05066ff1f40f00&v=4 + url: https://github.com/sodaMelon +ceb10n: + login: ceb10n + count: 119 + avatarUrl: https://avatars.githubusercontent.com/u/235213?u=edcce471814a1eba9f0cdaa4cd0de18921a940a6&v=4 + url: https://github.com/ceb10n +tokusumi: + login: tokusumi + count: 104 + avatarUrl: https://avatars.githubusercontent.com/u/41147016?u=55010621aece725aa702270b54fed829b6a1fe60&v=4 + url: https://github.com/tokusumi +hard-coders: + login: hard-coders + count: 102 + avatarUrl: https://avatars.githubusercontent.com/u/9651103?u=78d12d1acdf853c817700145e73de7fd9e5d068b&v=4 + url: https://github.com/hard-coders +YuriiMotov: + login: YuriiMotov + count: 95 + avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=bc48be95c429989224786106b027f3c5e40cc354&v=4 + url: https://github.com/YuriiMotov +hasansezertasan: + login: hasansezertasan + count: 95 + avatarUrl: https://avatars.githubusercontent.com/u/13135006?u=d36995e41a00590da64e6204cfd112e0484ac1ca&v=4 + url: https://github.com/hasansezertasan +alv2017: + login: alv2017 + count: 88 + avatarUrl: https://avatars.githubusercontent.com/u/31544722?v=4 + url: https://github.com/alv2017 +nazarepiedady: + login: nazarepiedady + count: 87 + avatarUrl: https://avatars.githubusercontent.com/u/31008635?u=f69ddc4ea8bda3bdfac7aa0e2ea38de282e6ee2d&v=4 + url: https://github.com/nazarepiedady +tiangolo: + login: tiangolo + count: 83 + avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 + url: https://github.com/tiangolo +AlertRED: + login: AlertRED + count: 81 + avatarUrl: https://avatars.githubusercontent.com/u/15695000?u=f5a4944c6df443030409c88da7d7fa0b7ead985c&v=4 + url: https://github.com/AlertRED +Alexandrhub: + login: Alexandrhub + count: 68 + avatarUrl: https://avatars.githubusercontent.com/u/119126536?u=9fc0d48f3307817bafecc5861eb2168401a6cb04&v=4 + url: https://github.com/Alexandrhub +nilslindemann: + login: nilslindemann + count: 67 + avatarUrl: https://avatars.githubusercontent.com/u/6892179?u=1dca6a22195d6cd1ab20737c0e19a4c55d639472&v=4 + url: https://github.com/nilslindemann +cassiobotaro: + login: cassiobotaro + count: 65 + avatarUrl: https://avatars.githubusercontent.com/u/3127847?u=a08022b191ddbd0a6159b2981d9d878b6d5bb71f&v=4 + url: https://github.com/cassiobotaro +waynerv: + login: waynerv + count: 63 + avatarUrl: https://avatars.githubusercontent.com/u/39515546?u=ec35139777597cdbbbddda29bf8b9d4396b429a9&v=4 + url: https://github.com/waynerv +mattwang44: + login: mattwang44 + count: 61 + avatarUrl: https://avatars.githubusercontent.com/u/24987826?u=58e37fb3927b9124b458945ac4c97aa0f1062d85&v=4 + url: https://github.com/mattwang44 +Laineyzhang55: + login: Laineyzhang55 + count: 48 + avatarUrl: https://avatars.githubusercontent.com/u/59285379?v=4 + url: https://github.com/Laineyzhang55 +Kludex: + login: Kludex + count: 47 + avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=df8a3f06ba8f55ae1967a3e2d5ed882903a4e330&v=4 + url: https://github.com/Kludex +komtaki: + login: komtaki + count: 45 + avatarUrl: https://avatars.githubusercontent.com/u/39375566?u=260ad6b1a4b34c07dbfa728da5e586f16f6d1824&v=4 + url: https://github.com/komtaki +svlandeg: + login: svlandeg + count: 43 + avatarUrl: https://avatars.githubusercontent.com/u/8796347?u=556c97650c27021911b0b9447ec55e75987b0e8a&v=4 + url: https://github.com/svlandeg +rostik1410: + login: rostik1410 + count: 42 + avatarUrl: https://avatars.githubusercontent.com/u/11443899?u=e26a635c2ba220467b308a326a579b8ccf4a8701&v=4 + url: https://github.com/rostik1410 +alperiox: + login: alperiox + count: 42 + avatarUrl: https://avatars.githubusercontent.com/u/34214152?u=2c5acad3461d4dbc2d48371ba86cac56ae9b25cc&v=4 + url: https://github.com/alperiox +Rishat-F: + login: Rishat-F + count: 42 + avatarUrl: https://avatars.githubusercontent.com/u/66554797?v=4 + url: https://github.com/Rishat-F +Winand: + login: Winand + count: 40 + avatarUrl: https://avatars.githubusercontent.com/u/53390?u=bb0e71a2fc3910a8e0ee66da67c33de40ea695f8&v=4 + url: https://github.com/Winand +solomein-sv: + login: solomein-sv + count: 38 + avatarUrl: https://avatars.githubusercontent.com/u/46193920?u=789927ee09cfabd752d3bd554fa6baf4850d2777&v=4 + url: https://github.com/solomein-sv +mezgoodle: + login: mezgoodle + count: 38 + avatarUrl: https://avatars.githubusercontent.com/u/41520940?u=b9f71909a70223d623afa9c2b848a14649daa07d&v=4 + url: https://github.com/mezgoodle +JavierSanchezCastro: + login: JavierSanchezCastro + count: 38 + avatarUrl: https://avatars.githubusercontent.com/u/72013291?u=ae5679e6bd971d9d98cd5e76e8683f83642ba950&v=4 + url: https://github.com/JavierSanchezCastro +alejsdev: + login: alejsdev + count: 37 + avatarUrl: https://avatars.githubusercontent.com/u/90076947?u=0facffe3abf87f57a1f05fa773d1119cc5c2f6a5&v=4 + url: https://github.com/alejsdev +stlucasgarcia: + login: stlucasgarcia + count: 36 + avatarUrl: https://avatars.githubusercontent.com/u/61513630?u=c22d8850e9dc396a8820766a59837f967e14f9a0&v=4 + url: https://github.com/stlucasgarcia +SwftAlpc: + login: SwftAlpc + count: 36 + avatarUrl: https://avatars.githubusercontent.com/u/52768429?u=6a3aa15277406520ad37f6236e89466ed44bc5b8&v=4 + url: https://github.com/SwftAlpc +timothy-jeong: + login: timothy-jeong + count: 36 + avatarUrl: https://avatars.githubusercontent.com/u/53824764?u=db3d0cea2f5fab64d810113c5039a369699a2774&v=4 + url: https://github.com/timothy-jeong +rjNemo: + login: rjNemo + count: 34 + avatarUrl: https://avatars.githubusercontent.com/u/56785022?u=d5c3a02567c8649e146fcfc51b6060ccaf8adef8&v=4 + url: https://github.com/rjNemo +yychanlee: + login: yychanlee + count: 34 + avatarUrl: https://avatars.githubusercontent.com/u/103817302?u=3a042740dc0ff58615da0d8679230966fd7693e8&v=4 + url: https://github.com/yychanlee +Vincy1230: + login: Vincy1230 + count: 34 + avatarUrl: https://avatars.githubusercontent.com/u/81342412?u=ab5e256a4077a4a91f3f9cd2115ba80780454cbe&v=4 + url: https://github.com/Vincy1230 +akarev0: + login: akarev0 + count: 33 + avatarUrl: https://avatars.githubusercontent.com/u/53393089?u=6e528bb4789d56af887ce6fe237bea4010885406&v=4 + url: https://github.com/akarev0 +romashevchenko: + login: romashevchenko + count: 32 + avatarUrl: https://avatars.githubusercontent.com/u/132477732?v=4 + url: https://github.com/romashevchenko +LorhanSohaky: + login: LorhanSohaky + count: 30 + avatarUrl: https://avatars.githubusercontent.com/u/16273730?u=095b66f243a2cd6a0aadba9a095009f8aaf18393&v=4 + url: https://github.com/LorhanSohaky +black-redoc: + login: black-redoc + count: 29 + avatarUrl: https://avatars.githubusercontent.com/u/18581590?u=7b6336166d0797fbbd44ea70c1c3ecadfc89af9e&v=4 + url: https://github.com/black-redoc +pedabraham: + login: pedabraham + count: 28 + avatarUrl: https://avatars.githubusercontent.com/u/16860088?u=abf922a7b920bf8fdb7867d8b43e091f1e796178&v=4 + url: https://github.com/pedabraham +Smlep: + login: Smlep + count: 28 + avatarUrl: https://avatars.githubusercontent.com/u/16785985?u=ffe99fa954c8e774ef1117e58d34aece92051e27&v=4 + url: https://github.com/Smlep +dedkot01: + login: dedkot01 + count: 28 + avatarUrl: https://avatars.githubusercontent.com/u/26196675?u=e2966887124e67932853df4f10f86cb526edc7b0&v=4 + url: https://github.com/dedkot01 +hsuanchi: + login: hsuanchi + count: 28 + avatarUrl: https://avatars.githubusercontent.com/u/24913710?u=7d25a398e478b6e63503bf6f26c54efa9e0da07b&v=4 + url: https://github.com/hsuanchi +dpinezich: + login: dpinezich + count: 28 + avatarUrl: https://avatars.githubusercontent.com/u/3204540?u=a2e1465e3ee10d537614d513589607eddefde09f&v=4 + url: https://github.com/dpinezich +maoyibo: + login: maoyibo + count: 27 + avatarUrl: https://avatars.githubusercontent.com/u/7887703?v=4 + url: https://github.com/maoyibo +0417taehyun: + login: 0417taehyun + count: 27 + avatarUrl: https://avatars.githubusercontent.com/u/63915557?u=47debaa860fd52c9b98c97ef357ddcec3b3fb399&v=4 + url: https://github.com/0417taehyun +BilalAlpaslan: + login: BilalAlpaslan + count: 26 + avatarUrl: https://avatars.githubusercontent.com/u/47563997?u=63ed66e304fe8d765762c70587d61d9196e5c82d&v=4 + url: https://github.com/BilalAlpaslan +junah201: + login: junah201 + count: 26 + avatarUrl: https://avatars.githubusercontent.com/u/75025529?u=2451c256e888fa2a06bcfc0646d09b87ddb6a945&v=4 + url: https://github.com/junah201 +zy7y: + login: zy7y + count: 25 + avatarUrl: https://avatars.githubusercontent.com/u/67154681?u=5d634834cc514028ea3f9115f7030b99a1f4d5a4&v=4 + url: https://github.com/zy7y +mycaule: + login: mycaule + count: 25 + avatarUrl: https://avatars.githubusercontent.com/u/6161385?u=e3cec75bd6d938a0d73fae0dc5534d1ab2ed1b0e&v=4 + url: https://github.com/mycaule +Aruelius: + login: Aruelius + count: 25 + avatarUrl: https://avatars.githubusercontent.com/u/25380989?u=574f8cfcda3ea77a3f81884f6b26a97068e36a9d&v=4 + url: https://github.com/Aruelius +wisderfin: + login: wisderfin + count: 24 + avatarUrl: https://avatars.githubusercontent.com/u/77553770?u=9a23740d520d65dc0051cdc1ecd87f31cb900313&v=4 + url: https://github.com/wisderfin +OzgunCaglarArslan: + login: OzgunCaglarArslan + count: 24 + avatarUrl: https://avatars.githubusercontent.com/u/86166426?v=4 + url: https://github.com/OzgunCaglarArslan +ycd: + login: ycd + count: 23 + avatarUrl: https://avatars.githubusercontent.com/u/62724709?u=f1e7bae394a315da950912c92dc861a8eaf95d4c&v=4 + url: https://github.com/ycd +sh0nk: + login: sh0nk + count: 23 + avatarUrl: https://avatars.githubusercontent.com/u/6478810?u=af15d724875cec682ed8088a86d36b2798f981c0&v=4 + url: https://github.com/sh0nk +axel584: + login: axel584 + count: 23 + avatarUrl: https://avatars.githubusercontent.com/u/1334088?u=9667041f5b15dc002b6f9665fda8c0412933ac04&v=4 + url: https://github.com/axel584 +DianaTrufanova: + login: DianaTrufanova + count: 23 + avatarUrl: https://avatars.githubusercontent.com/u/119067607?u=1cd55f841b68b4a187fa6d06a7dafa5f070195aa&v=4 + url: https://github.com/DianaTrufanova +AGolicyn: + login: AGolicyn + count: 21 + avatarUrl: https://avatars.githubusercontent.com/u/86262613?u=3c21606ab8d210a061a1673decff1e7d5592b380&v=4 + url: https://github.com/AGolicyn +Attsun1031: + login: Attsun1031 + count: 20 + avatarUrl: https://avatars.githubusercontent.com/u/1175560?v=4 + url: https://github.com/Attsun1031 +delhi09: + login: delhi09 + count: 20 + avatarUrl: https://avatars.githubusercontent.com/u/63476957?u=6c86e59b48e0394d4db230f37fc9ad4d7e2c27c7&v=4 + url: https://github.com/delhi09 +rogerbrinkmann: + login: rogerbrinkmann + count: 20 + avatarUrl: https://avatars.githubusercontent.com/u/5690226?u=a1fe0aee927d33ce9db8c455eabc40c1cdf2bb65&v=4 + url: https://github.com/rogerbrinkmann +DevDae: + login: DevDae + count: 20 + avatarUrl: https://avatars.githubusercontent.com/u/87962045?u=08e10fa516e844934f4b3fc7c38b33c61697e4a1&v=4 + url: https://github.com/DevDae +sattosan: + login: sattosan + count: 19 + avatarUrl: https://avatars.githubusercontent.com/u/20574756?u=b0d8474d2938189c6954423ae8d81d91013f80a8&v=4 + url: https://github.com/sattosan +maru0123-2004: + login: maru0123-2004 + count: 19 + avatarUrl: https://avatars.githubusercontent.com/u/43961566?u=16ed8603a4d6a4665cb6c53a7aece6f31379b769&v=4 + url: https://github.com/maru0123-2004 +yes0ng: + login: yes0ng + count: 19 + avatarUrl: https://avatars.githubusercontent.com/u/25501794?u=3aed18b0d491e0220a167a1e9e58bea3638c6707&v=4 + url: https://github.com/yes0ng +ComicShrimp: + login: ComicShrimp + count: 18 + avatarUrl: https://avatars.githubusercontent.com/u/43503750?u=d2fbf412e7730183ce91686ca48d4147e1b7dc74&v=4 + url: https://github.com/ComicShrimp +simatheone: + login: simatheone + count: 18 + avatarUrl: https://avatars.githubusercontent.com/u/78508673?u=1b9658d9ee0bde33f56130dd52275493ddd38690&v=4 + url: https://github.com/simatheone +ivan-abc: + login: ivan-abc + count: 18 + avatarUrl: https://avatars.githubusercontent.com/u/36765187?u=c6e0ba571c1ccb6db9d94e62e4b8b5eda811a870&v=4 + url: https://github.com/ivan-abc +Limsunoh: + login: Limsunoh + count: 18 + avatarUrl: https://avatars.githubusercontent.com/u/90311848?u=f456e0c5709fd50c8cd2898b551558eda14e5f21&v=4 + url: https://github.com/Limsunoh +SofiiaTrufanova: + login: SofiiaTrufanova + count: 18 + avatarUrl: https://avatars.githubusercontent.com/u/63260929?u=483e0b64fabc76343b3be39b7e1dcb930a95e1bb&v=4 + url: https://github.com/SofiiaTrufanova +bezaca: + login: bezaca + count: 17 + avatarUrl: https://avatars.githubusercontent.com/u/69092910?u=4ac58eab99bd37d663f3d23551df96d4fbdbf760&v=4 + url: https://github.com/bezaca +lbmendes: + login: lbmendes + count: 17 + avatarUrl: https://avatars.githubusercontent.com/u/80999926?u=646619e2f07ac5a7c3f65fe7834197461a4fff9f&v=4 + url: https://github.com/lbmendes +spacesphere: + login: spacesphere + count: 17 + avatarUrl: https://avatars.githubusercontent.com/u/34628304?u=cde91f6002dd33156e1bf8005f11a7a3ed76b790&v=4 + url: https://github.com/spacesphere +panko: + login: panko + count: 17 + avatarUrl: https://avatars.githubusercontent.com/u/1569515?u=a84a5d255621ed82f8e1ca052f5f2eeb75997da2&v=4 + url: https://github.com/panko +jeison-araya: + login: jeison-araya + count: 17 + avatarUrl: https://avatars.githubusercontent.com/u/57369279?u=17001e68af7d8e5b8c343e5e9df4050f419998d5&v=4 + url: https://github.com/jeison-araya +yanever: + login: yanever + count: 16 + avatarUrl: https://avatars.githubusercontent.com/u/21978760?v=4 + url: https://github.com/yanever +mastizada: + login: mastizada + count: 16 + avatarUrl: https://avatars.githubusercontent.com/u/1975818?u=0751a06d7271c8bf17cb73b1b845644ab4d2c6dc&v=4 + url: https://github.com/mastizada +waketzheng: + login: waketzheng + count: 16 + avatarUrl: https://avatars.githubusercontent.com/u/35413830?u=df19e4fd5bb928e7d086e053ef26a46aad23bf84&v=4 + url: https://github.com/waketzheng +Joao-Pedro-P-Holanda: + login: Joao-Pedro-P-Holanda + count: 16 + avatarUrl: https://avatars.githubusercontent.com/u/110267046?u=331bd016326dac4cf3df4848f6db2dbbf8b5f978&v=4 + url: https://github.com/Joao-Pedro-P-Holanda +JaeHyuckSa: + login: JaeHyuckSa + count: 16 + avatarUrl: https://avatars.githubusercontent.com/u/104830931?u=f3b4a2baea550f428a4c602a30ebee6721c1e3df&v=4 + url: https://github.com/JaeHyuckSa +Jedore: + login: Jedore + count: 15 + avatarUrl: https://avatars.githubusercontent.com/u/17944025?u=81d503e1c800eb666b3861ca47a3a773bbc3f539&v=4 + url: https://github.com/Jedore +kim-sangah: + login: kim-sangah + count: 15 + avatarUrl: https://avatars.githubusercontent.com/u/173775778?v=4 + url: https://github.com/kim-sangah +PandaHun: + login: PandaHun + count: 14 + avatarUrl: https://avatars.githubusercontent.com/u/13096845?u=646eba44db720e37d0dbe8e98e77ab534ea78a20&v=4 + url: https://github.com/PandaHun +dukkee: + login: dukkee + count: 14 + avatarUrl: https://avatars.githubusercontent.com/u/36825394?u=ccfd86e6a4f2d093dad6f7544cc875af67fa2df8&v=4 + url: https://github.com/dukkee +BORA040126: + login: BORA040126 + count: 14 + avatarUrl: https://avatars.githubusercontent.com/u/88664069?u=98e382727a485971e04aaa7c873d9a75a17ee3be&v=4 + url: https://github.com/BORA040126 +mattkoehne: + login: mattkoehne + count: 14 + avatarUrl: https://avatars.githubusercontent.com/u/80362153?v=4 + url: https://github.com/mattkoehne +jovicon: + login: jovicon + count: 13 + avatarUrl: https://avatars.githubusercontent.com/u/21287303?u=b049eac3e51a4c0473c2efe66b4d28a7d8f2b572&v=4 + url: https://github.com/jovicon +izaguerreiro: + login: izaguerreiro + count: 13 + avatarUrl: https://avatars.githubusercontent.com/u/2241504?v=4 + url: https://github.com/izaguerreiro +jburckel: + login: jburckel + count: 13 + avatarUrl: https://avatars.githubusercontent.com/u/11768758?u=044462e4130e086a0621f4abb45f0d7a289ab7fa&v=4 + url: https://github.com/jburckel +peidrao: + login: peidrao + count: 13 + avatarUrl: https://avatars.githubusercontent.com/u/32584628?u=979c62398e16ff000cc0faa028e028efd679887c&v=4 + url: https://github.com/peidrao +impocode: + login: impocode + count: 13 + avatarUrl: https://avatars.githubusercontent.com/u/109408819?u=9cdfc5ccb31a2094c520f41b6087012fa9048982&v=4 + url: https://github.com/impocode +wesinalves: + login: wesinalves + count: 13 + avatarUrl: https://avatars.githubusercontent.com/u/13563128?u=9eb17ed50645dd684bfec47e75dba4e9772ec9c1&v=4 + url: https://github.com/wesinalves +andersonrocha0: + login: andersonrocha0 + count: 13 + avatarUrl: https://avatars.githubusercontent.com/u/22346169?u=93a1359c8c5461d894802c0cc65bcd09217e7a02&v=4 + url: https://github.com/andersonrocha0 +NastasiaSaby: + login: NastasiaSaby + count: 12 + avatarUrl: https://avatars.githubusercontent.com/u/8245071?u=b3afd005f9e4bf080c219ef61a592b3a8004b764&v=4 + url: https://github.com/NastasiaSaby +oandersonmagalhaes: + login: oandersonmagalhaes + count: 12 + avatarUrl: https://avatars.githubusercontent.com/u/83456692?u=daf5f302a59b950efc6d21129314af207e35441f&v=4 + url: https://github.com/oandersonmagalhaes +mkdir700: + login: mkdir700 + count: 12 + avatarUrl: https://avatars.githubusercontent.com/u/56359329?u=818e5f4b4dcc1a6ffb3e5aaa08fd827e5a726dfd&v=4 + url: https://github.com/mkdir700 +batlopes: + login: batlopes + count: 12 + avatarUrl: https://avatars.githubusercontent.com/u/33462923?u=0fb3d7acb316764616f11e4947faf080e49ad8d9&v=4 + url: https://github.com/batlopes +joonas-yoon: + login: joonas-yoon + count: 12 + avatarUrl: https://avatars.githubusercontent.com/u/9527681?u=0166d22ef4749e617c6516e79f833cd8d73f1949&v=4 + url: https://github.com/joonas-yoon +baseplate-admin: + login: baseplate-admin + count: 12 + avatarUrl: https://avatars.githubusercontent.com/u/61817579?u=ce4c268fa949ae9a0290996e7949195302055812&v=4 + url: https://github.com/baseplate-admin +KaniKim: + login: KaniKim + count: 12 + avatarUrl: https://avatars.githubusercontent.com/u/19832624?u=296dbdd490e0eb96e3d45a2608c065603b17dc31&v=4 + url: https://github.com/KaniKim +gitgernit: + login: gitgernit + count: 12 + avatarUrl: https://avatars.githubusercontent.com/u/129539613?u=d04f10143ab32c93f563ea14bf242d1d2bc991b0&v=4 + url: https://github.com/gitgernit +kwang1215: + login: kwang1215 + count: 12 + avatarUrl: https://avatars.githubusercontent.com/u/74170199?u=2a63ff6692119dde3f5e5693365b9fcd6f977b08&v=4 + url: https://github.com/kwang1215 +AdrianDeAnda: + login: AdrianDeAnda + count: 11 + avatarUrl: https://avatars.githubusercontent.com/u/1024932?u=b2ea249c6b41ddf98679c8d110d0f67d4a3ebf93&v=4 + url: https://github.com/AdrianDeAnda +blt232018: + login: blt232018 + count: 11 + avatarUrl: https://avatars.githubusercontent.com/u/43393471?u=172b0e0391db1aa6c1706498d6dfcb003c8a4857&v=4 + url: https://github.com/blt232018 +NinaHwang: + login: NinaHwang + count: 11 + avatarUrl: https://avatars.githubusercontent.com/u/79563565?u=241f2cb6d38a2d379536608a8ea5a22ed4b1a3ea&v=4 + url: https://github.com/NinaHwang +glsglsgls: + login: glsglsgls + count: 11 + avatarUrl: https://avatars.githubusercontent.com/u/76133879?v=4 + url: https://github.com/glsglsgls +k94-ishi: + login: k94-ishi + count: 11 + avatarUrl: https://avatars.githubusercontent.com/u/32672580?u=bc7c5c07af0656be9fe4f1784a444af8d81ded89&v=4 + url: https://github.com/k94-ishi +codespearhead: + login: codespearhead + count: 11 + avatarUrl: https://avatars.githubusercontent.com/u/72931357?u=0fce6b82219b604d58adb614a761556425579cb5&v=4 + url: https://github.com/codespearhead +emrhnsyts: + login: emrhnsyts + count: 11 + avatarUrl: https://avatars.githubusercontent.com/u/42899027?u=ad26798e3f8feed2041c5dd5f87e58933d6c3283&v=4 + url: https://github.com/emrhnsyts +Lufa1u: + login: Lufa1u + count: 11 + avatarUrl: https://avatars.githubusercontent.com/u/112495876?u=087658920ed9e74311597bdd921d8d2de939d276&v=4 + url: https://github.com/Lufa1u +KNChiu: + login: KNChiu + count: 11 + avatarUrl: https://avatars.githubusercontent.com/u/36751646?v=4 + url: https://github.com/KNChiu +Zhongheng-Cheng: + login: Zhongheng-Cheng + count: 11 + avatarUrl: https://avatars.githubusercontent.com/u/95612344?u=a0f7730a3cc7486827965e01a119ad610bda4b0a&v=4 + url: https://github.com/Zhongheng-Cheng +Pyth3rEx: + login: Pyth3rEx + count: 11 + avatarUrl: https://avatars.githubusercontent.com/u/26427764?u=087724f74d813c95925d51e354554bd4b6d6bb60&v=4 + url: https://github.com/Pyth3rEx +ABcDexter: + login: ABcDexter + count: 11 + avatarUrl: https://avatars.githubusercontent.com/u/7236257?u=baa7e62eb4d0014b5854bfd0d5c2b20bd9617e0d&v=4 + url: https://github.com/ABcDexter +mariacamilagl: + login: mariacamilagl + count: 10 + avatarUrl: https://avatars.githubusercontent.com/u/11489395?u=4adb6986bf3debfc2b8216ae701f2bd47d73da7d&v=4 + url: https://github.com/mariacamilagl +ryuckel: + login: ryuckel + count: 10 + avatarUrl: https://avatars.githubusercontent.com/u/36391432?u=094eec0cfddd5013f76f31e55e56147d78b19553&v=4 + url: https://github.com/ryuckel +umitkaanusta: + login: umitkaanusta + count: 10 + avatarUrl: https://avatars.githubusercontent.com/u/53405015?v=4 + url: https://github.com/umitkaanusta +kty4119: + login: kty4119 + count: 10 + avatarUrl: https://avatars.githubusercontent.com/u/49435654?v=4 + url: https://github.com/kty4119 +RobotToI: + login: RobotToI + count: 10 + avatarUrl: https://avatars.githubusercontent.com/u/44951382?u=e41dbc19191ce7abed86694b1a44ea0523e1c60e&v=4 + url: https://github.com/RobotToI +vitumenezes: + login: vitumenezes + count: 10 + avatarUrl: https://avatars.githubusercontent.com/u/9680878?u=05fd25cfafdc09382bf8907c37293a696c205754&v=4 + url: https://github.com/vitumenezes +fcrozetta: + login: fcrozetta + count: 10 + avatarUrl: https://avatars.githubusercontent.com/u/8006246?u=fa2a743e803de2c3a84d3ed8042faefed16c5e43&v=4 + url: https://github.com/fcrozetta +sUeharaE4: + login: sUeharaE4 + count: 10 + avatarUrl: https://avatars.githubusercontent.com/u/44468359?v=4 + url: https://github.com/sUeharaE4 +Ernilia: + login: Ernilia + count: 10 + avatarUrl: https://avatars.githubusercontent.com/u/125735800?u=13bfaac417a53fd5b5cf992efea363ca72598813&v=4 + url: https://github.com/Ernilia +socket-socket: + login: socket-socket + count: 10 + avatarUrl: https://avatars.githubusercontent.com/u/121552599?u=104df6503242e8d762fe293e7036f7260f245d49&v=4 + url: https://github.com/socket-socket +nick-cjyx9: + login: nick-cjyx9 + count: 10 + avatarUrl: https://avatars.githubusercontent.com/u/119087246?u=5fc07fc3db727b3c00393d0a3739fb2b6e896a1b&v=4 + url: https://github.com/nick-cjyx9 +marcelomarkus: + login: marcelomarkus + count: 10 + avatarUrl: https://avatars.githubusercontent.com/u/20115018?u=dda090ce9160ef0cd2ff69b1e5ea741283425cba&v=4 + url: https://github.com/marcelomarkus +lucasbalieiro: + login: lucasbalieiro + count: 10 + avatarUrl: https://avatars.githubusercontent.com/u/37416577?u=d144221c34c08adac8b20e1833d776ffa1c4b1d0&v=4 + url: https://github.com/lucasbalieiro +RunningIkkyu: + login: RunningIkkyu + count: 9 + avatarUrl: https://avatars.githubusercontent.com/u/31848542?u=494ecc298e3f26197495bb357ad0f57cfd5f7a32&v=4 + url: https://github.com/RunningIkkyu +JulianMaurin: + login: JulianMaurin + count: 9 + avatarUrl: https://avatars.githubusercontent.com/u/63545168?u=b7d15ac865268cbefc2d739e2f23d9aeeac1a622&v=4 + url: https://github.com/JulianMaurin +JeongHyeongKim: + login: JeongHyeongKim + count: 9 + avatarUrl: https://avatars.githubusercontent.com/u/26577800?u=77f060f4686f32c248907b81b16ee2b3177ca44c&v=4 + url: https://github.com/JeongHyeongKim +arthurio: + login: arthurio + count: 9 + avatarUrl: https://avatars.githubusercontent.com/u/950449?u=76b997138273ce5e1990b971c4f27c9aff979fd5&v=4 + url: https://github.com/arthurio +Lenclove: + login: Lenclove + count: 9 + avatarUrl: https://avatars.githubusercontent.com/u/32355298?u=d0065e01650c63c2b2413f42d983634b2ea85481&v=4 + url: https://github.com/Lenclove +eVery1337: + login: eVery1337 + count: 9 + avatarUrl: https://avatars.githubusercontent.com/u/84917945?u=7af243f05ecfba59191199a70d8ba365c1327768&v=4 + url: https://github.com/eVery1337 +aykhans: + login: aykhans + count: 9 + avatarUrl: https://avatars.githubusercontent.com/u/88669260?u=2760f6f6728ed11108b56265682bcf68d46067a5&v=4 + url: https://github.com/aykhans +riroan: + login: riroan + count: 9 + avatarUrl: https://avatars.githubusercontent.com/u/33053284?u=2d18e3771506ee874b66d6aa2b3b1107fd95c38f&v=4 + url: https://github.com/riroan +MinLee0210: + login: MinLee0210 + count: 9 + avatarUrl: https://avatars.githubusercontent.com/u/57653278?u=9fef84dd2f7497e8b43db01ba517a5b2bd66ad88&v=4 + url: https://github.com/MinLee0210 +yodai-yodai: + login: yodai-yodai + count: 9 + avatarUrl: https://avatars.githubusercontent.com/u/7031039?u=4f3593f5931892b931a745cfab846eff6e9332e7&v=4 + url: https://github.com/yodai-yodai +JoaoGustavoRogel: + login: JoaoGustavoRogel + count: 9 + avatarUrl: https://avatars.githubusercontent.com/u/29525510?u=a0a91251f5e43e132608d55d28ccb8645c5ea405&v=4 + url: https://github.com/JoaoGustavoRogel +valentinDruzhinin: + login: valentinDruzhinin + count: 9 + avatarUrl: https://avatars.githubusercontent.com/u/12831905?u=aae1ebc675c91e8fa582df4fcc4fc4128106344d&v=4 + url: https://github.com/valentinDruzhinin +Yarous: + login: Yarous + count: 9 + avatarUrl: https://avatars.githubusercontent.com/u/61277193?u=5b462347458a373b2d599c6f416d2b75eddbffad&v=4 + url: https://github.com/Yarous +dimaqq: + login: dimaqq + count: 8 + avatarUrl: https://avatars.githubusercontent.com/u/662249?u=15313dec91bae789685e4abb3c2152251de41948&v=4 + url: https://github.com/dimaqq +julianofischer: + login: julianofischer + count: 8 + avatarUrl: https://avatars.githubusercontent.com/u/158303?u=d91662eb949d4cc7368831cf37a5cdfd90b7010c&v=4 + url: https://github.com/julianofischer +bnzone: + login: bnzone + count: 8 + avatarUrl: https://avatars.githubusercontent.com/u/39371503?u=c16f00c41d88479fa2d57b0d7d233b758eacce2d&v=4 + url: https://github.com/bnzone +shamosishen: + login: shamosishen + count: 8 + avatarUrl: https://avatars.githubusercontent.com/u/9498321?u=c83c20c79e019a0b555a125adf20fc4fb7a882c8&v=4 + url: https://github.com/shamosishen +mertssmnoglu: + login: mertssmnoglu + count: 8 + avatarUrl: https://avatars.githubusercontent.com/u/61623638?u=59dd885b68ff1832f9ab3b4a4446896358c23442&v=4 + url: https://github.com/mertssmnoglu +mahone3297: + login: mahone3297 + count: 8 + avatarUrl: https://avatars.githubusercontent.com/u/1701379?u=20588ff0e456d13e8017333eb237595d11410234&v=4 + url: https://github.com/mahone3297 +KimJoonSeo: + login: KimJoonSeo + count: 8 + avatarUrl: https://avatars.githubusercontent.com/u/17760162?u=a58cdc77ae1c069a64166f7ecc4d42eecfd9a468&v=4 + url: https://github.com/KimJoonSeo +camigomezdev: + login: camigomezdev + count: 8 + avatarUrl: https://avatars.githubusercontent.com/u/16061815?u=25b5ebc042fff53fa03dc107ded10e36b1b7a5b9&v=4 + url: https://github.com/camigomezdev +minaton-ru: + login: minaton-ru + count: 8 + avatarUrl: https://avatars.githubusercontent.com/u/53541518?u=67336ca11a85493f75031508aade588dad3b9910&v=4 + url: https://github.com/minaton-ru +sungchan1: + login: sungchan1 + count: 8 + avatarUrl: https://avatars.githubusercontent.com/u/28076127?u=fadbf24840186aca639d344bb3e0ecf7ff3441cf&v=4 + url: https://github.com/sungchan1 +EdmilsonRodrigues: + login: EdmilsonRodrigues + count: 8 + avatarUrl: https://avatars.githubusercontent.com/u/62777025?u=217d6f3cd6cc750bb8818a3af7726c8d74eb7c2d&v=4 + url: https://github.com/EdmilsonRodrigues +roli2py: + login: roli2py + count: 8 + avatarUrl: https://avatars.githubusercontent.com/u/61126128?u=d20921080d6b9499b39ef3431e850432fe68f903&v=4 + url: https://github.com/roli2py +Serrones: + login: Serrones + count: 7 + avatarUrl: https://avatars.githubusercontent.com/u/22691749?u=4795b880e13ca33a73e52fc0ef7dc9c60c8fce47&v=4 + url: https://github.com/Serrones +israteneda: + login: israteneda + count: 7 + avatarUrl: https://avatars.githubusercontent.com/u/20668624?u=67574648f89019d1c73b16a6a009da659557f9e5&v=4 + url: https://github.com/israteneda +krocdort: + login: krocdort + count: 7 + avatarUrl: https://avatars.githubusercontent.com/u/34248814?v=4 + url: https://github.com/krocdort +anthonycepeda: + login: anthonycepeda + count: 7 + avatarUrl: https://avatars.githubusercontent.com/u/72019805?u=60bdf46240cff8fca482ff0fc07d963fd5e1a27c&v=4 + url: https://github.com/anthonycepeda +fabioueno: + login: fabioueno + count: 7 + avatarUrl: https://avatars.githubusercontent.com/u/14273852?u=a3d546449cdc96621c32bcc26cf74be6e4390209&v=4 + url: https://github.com/fabioueno +cfraboulet: + login: cfraboulet + count: 7 + avatarUrl: https://avatars.githubusercontent.com/u/62244267?u=ed0e286ba48fa1dafd64a08e50f3364b8e12df34&v=4 + url: https://github.com/cfraboulet +HiemalBeryl: + login: HiemalBeryl + count: 7 + avatarUrl: https://avatars.githubusercontent.com/u/63165207?u=276f4af2829baf28b912c718675852bfccb0e7b4&v=4 + url: https://github.com/HiemalBeryl +pablocm83: + login: pablocm83 + count: 7 + avatarUrl: https://avatars.githubusercontent.com/u/28315068?u=3310fbb05bb8bfc50d2c48b6cb64ac9ee4a14549&v=4 + url: https://github.com/pablocm83 +d2a-raudenaerde: + login: d2a-raudenaerde + count: 7 + avatarUrl: https://avatars.githubusercontent.com/u/5213150?u=e6d0ef65c571c7e544fc1c7ec151c7c0a72fb6bb&v=4 + url: https://github.com/d2a-raudenaerde +Zerohertz: + login: Zerohertz + count: 7 + avatarUrl: https://avatars.githubusercontent.com/u/42334717?u=5ebf4d33e73b1ad373154f6cdee44f7cab4d05ba&v=4 + url: https://github.com/Zerohertz +deniscapeto: + login: deniscapeto + count: 6 + avatarUrl: https://avatars.githubusercontent.com/u/12864353?u=20c5b2300b264a585a8381acf3cef44bcfcc1ead&v=4 + url: https://github.com/deniscapeto +bsab: + login: bsab + count: 6 + avatarUrl: https://avatars.githubusercontent.com/u/9799799?u=c4a09b1abb794cd8280c4793d43d0e2eb963ecda&v=4 + url: https://github.com/bsab +ArcLightSlavik: + login: ArcLightSlavik + count: 6 + avatarUrl: https://avatars.githubusercontent.com/u/31127044?u=b0f2c37142f4b762e41ad65dc49581813422bd71&v=4 + url: https://github.com/ArcLightSlavik +Cajuteq: + login: Cajuteq + count: 6 + avatarUrl: https://avatars.githubusercontent.com/u/26676532?u=8ee0422981810e51480855de1c0d67b6b79cd3f2&v=4 + url: https://github.com/Cajuteq +emmrichard: + login: emmrichard + count: 6 + avatarUrl: https://avatars.githubusercontent.com/u/1328018?u=8114d8fc0e8e42a092e4283013a1c54b792c466b&v=4 + url: https://github.com/emmrichard +wakabame: + login: wakabame + count: 6 + avatarUrl: https://avatars.githubusercontent.com/u/35513518?u=41ef6b0a55076e5c540620d68fb006e386c2ddb0&v=4 + url: https://github.com/wakabame +mawassk: + login: mawassk + count: 6 + avatarUrl: https://avatars.githubusercontent.com/u/84179197?v=4 + url: https://github.com/mawassk +diogoduartec: + login: diogoduartec + count: 6 + avatarUrl: https://avatars.githubusercontent.com/u/31852339?u=7514a5f05fcbeccc62f8c5dc25879efeb1ef9335&v=4 + url: https://github.com/diogoduartec +aqcool: + login: aqcool + count: 6 + avatarUrl: https://avatars.githubusercontent.com/u/52229895?v=4 + url: https://github.com/aqcool +'1320555911': + login: '1320555911' + count: 6 + avatarUrl: https://avatars.githubusercontent.com/u/58590086?u=6d8f4fbf08d5ac72c1c895892c461c5e0b013dc3&v=4 + url: https://github.com/1320555911 +mcthesw: + login: mcthesw + count: 6 + avatarUrl: https://avatars.githubusercontent.com/u/61224072?u=82a1b106298348f060c3f4f39817e0cae5ce2b7c&v=4 + url: https://github.com/mcthesw +xzmeng: + login: xzmeng + count: 6 + avatarUrl: https://avatars.githubusercontent.com/u/40202897?v=4 + url: https://github.com/xzmeng +negadive: + login: negadive + count: 6 + avatarUrl: https://avatars.githubusercontent.com/u/47322392?u=c1be2e9b9b346b4a77d9157da2a5739ab25ce0f8&v=4 + url: https://github.com/negadive +mbroton: + login: mbroton + count: 6 + avatarUrl: https://avatars.githubusercontent.com/u/50829834?u=a48610bf1bffaa9c75d03228926e2eb08a2e24ee&v=4 + url: https://github.com/mbroton +Kirilex: + login: Kirilex + count: 6 + avatarUrl: https://avatars.githubusercontent.com/u/100281552?v=4 + url: https://github.com/Kirilex +arunppsg: + login: arunppsg + count: 6 + avatarUrl: https://avatars.githubusercontent.com/u/26398753?v=4 + url: https://github.com/arunppsg +dimastbk: + login: dimastbk + count: 6 + avatarUrl: https://avatars.githubusercontent.com/u/3132181?u=66587398d43466a1dc75c238df5f048e0afc77ed&v=4 + url: https://github.com/dimastbk +dudyaosuplayer: + login: dudyaosuplayer + count: 6 + avatarUrl: https://avatars.githubusercontent.com/u/62661898?u=7864cc5f01b1c845ae8ad49acf45dec6faca0c57&v=4 + url: https://github.com/dudyaosuplayer +talhaumer: + login: talhaumer + count: 6 + avatarUrl: https://avatars.githubusercontent.com/u/46643702?u=5d1fd7057ea9534fb3221931b809a3d750157212&v=4 + url: https://github.com/talhaumer +bankofsardine: + login: bankofsardine + count: 6 + avatarUrl: https://avatars.githubusercontent.com/u/44944207?u=0368e1b698ffab6bf29e202f9fd2dddd352429f1&v=4 + url: https://github.com/bankofsardine +Rekl0w: + login: Rekl0w + count: 6 + avatarUrl: https://avatars.githubusercontent.com/u/91488737?u=7d2b7791665e04a12695150776a1d516a6ea7d21&v=4 + url: https://github.com/Rekl0w +rsip22: + login: rsip22 + count: 5 + avatarUrl: https://avatars.githubusercontent.com/u/16676222?v=4 + url: https://github.com/rsip22 +jessicapaz: + login: jessicapaz + count: 5 + avatarUrl: https://avatars.githubusercontent.com/u/20428941?u=6ffdaab5a85bf77a2d8870dade5e53555f34577b&v=4 + url: https://github.com/jessicapaz +mohsen-mahmoodi: + login: mohsen-mahmoodi + count: 5 + avatarUrl: https://avatars.githubusercontent.com/u/2872586?u=3a9fc1aa16a3a0ab93a1f8550de82a940592857d&v=4 + url: https://github.com/mohsen-mahmoodi +jeesang7: + login: jeesang7 + count: 5 + avatarUrl: https://avatars.githubusercontent.com/u/30719956?u=35fc8bca04d32d3c4ce085956f0636b959ba30f6&v=4 + url: https://github.com/jeesang7 +TemaSpb: + login: TemaSpb + count: 5 + avatarUrl: https://avatars.githubusercontent.com/u/20205738?u=d7dce0718720a7107803a573d628d8dd3d5c2fb4&v=4 + url: https://github.com/TemaSpb +BugLight: + login: BugLight + count: 5 + avatarUrl: https://avatars.githubusercontent.com/u/13618366?u=7d733749f80e5f7e66a434cf42aedcfc60340f43&v=4 + url: https://github.com/BugLight +0x4Dark: + login: 0x4Dark + count: 5 + avatarUrl: https://avatars.githubusercontent.com/u/7569289?v=4 + url: https://github.com/0x4Dark +Wuerike: + login: Wuerike + count: 5 + avatarUrl: https://avatars.githubusercontent.com/u/35462243?u=80c753dedf4a78db12ef66316dbdebbe6d84a2b9&v=4 + url: https://github.com/Wuerike +jvmazagao: + login: jvmazagao + count: 5 + avatarUrl: https://avatars.githubusercontent.com/u/22477816?u=2b57addf5830906bf6ae5f25cd4c8c2fa5c2d68e&v=4 + url: https://github.com/jvmazagao +cun3yt: + login: cun3yt + count: 5 + avatarUrl: https://avatars.githubusercontent.com/u/24409240?u=06abfd77786db859b0602d5369d2ae18c932c17c&v=4 + url: https://github.com/cun3yt +Mordson: + login: Mordson + count: 5 + avatarUrl: https://avatars.githubusercontent.com/u/39025897?u=b94ea96ef35bbe43bc85359cfb31d28ac16d470c&v=4 + url: https://github.com/Mordson +aminkhani: + login: aminkhani + count: 5 + avatarUrl: https://avatars.githubusercontent.com/u/51851950?u=051896c4933816bc61d11091d887f6e8dfd1d27b&v=4 + url: https://github.com/aminkhani +nifadyev: + login: nifadyev + count: 5 + avatarUrl: https://avatars.githubusercontent.com/u/36514612?u=e101da8641d5a09901d2155255a93f8ab3d9c468&v=4 + url: https://github.com/nifadyev +LaurEars: + login: LaurEars + count: 5 + avatarUrl: https://avatars.githubusercontent.com/u/4914725?v=4 + url: https://github.com/LaurEars +Chushine: + login: Chushine + count: 5 + avatarUrl: https://avatars.githubusercontent.com/u/135534400?v=4 + url: https://github.com/Chushine +ChuyuChoyeon: + login: ChuyuChoyeon + count: 5 + avatarUrl: https://avatars.githubusercontent.com/u/129537877?u=f0c76f3327817a8b86b422d62e04a34bf2827f2b&v=4 + url: https://github.com/ChuyuChoyeon +frwl404: + login: frwl404 + count: 5 + avatarUrl: https://avatars.githubusercontent.com/u/42642656?u=8395a3d991d9fac86901277d76f0f70857b56ec5&v=4 + url: https://github.com/frwl404 +esrefzeki: + login: esrefzeki + count: 5 + avatarUrl: https://avatars.githubusercontent.com/u/54935247?u=193cf5a169ca05fc54995a4dceabc82c7dc6e5ea&v=4 + url: https://github.com/esrefzeki +dtleal: + login: dtleal + count: 5 + avatarUrl: https://avatars.githubusercontent.com/u/31096951?u=704664ec74ab655485e5c909b25de3fa09a922ba&v=4 + url: https://github.com/dtleal +art3xa: + login: art3xa + count: 5 + avatarUrl: https://avatars.githubusercontent.com/u/92092049?v=4 + url: https://github.com/art3xa +SamuelBFavarin: + login: SamuelBFavarin + count: 5 + avatarUrl: https://avatars.githubusercontent.com/u/17628602?u=5aac13ae492fa9a86e397a70803ac723dba2efe7&v=4 + url: https://github.com/SamuelBFavarin +takacs: + login: takacs + count: 5 + avatarUrl: https://avatars.githubusercontent.com/u/44911031?u=f6c6b70b3ba86ceb93b0f9bcab609bf9328b2305&v=4 + url: https://github.com/takacs +anton2yakovlev: + login: anton2yakovlev + count: 5 + avatarUrl: https://avatars.githubusercontent.com/u/44229180?u=ac245e57bc834ff80f08ca8128000bb650a77a3d&v=4 + url: https://github.com/anton2yakovlev +ILoveSorasakiHina: + login: ILoveSorasakiHina + count: 5 + avatarUrl: https://avatars.githubusercontent.com/u/114038930?u=3d3ed8dc3bf57e641d1b26badee5bc79ef34f25b&v=4 + url: https://github.com/ILoveSorasakiHina +devluisrodrigues: + login: devluisrodrigues + count: 5 + avatarUrl: https://avatars.githubusercontent.com/u/103431660?u=d9674a3249edc4601d2c712cdebf899918503c3a&v=4 + url: https://github.com/devluisrodrigues +11kkw: + login: 11kkw + count: 5 + avatarUrl: https://avatars.githubusercontent.com/u/21125286?v=4 + url: https://github.com/11kkw +lpdswing: + login: lpdswing + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/20874036?u=7a4fc3e4d0719e37b305deb7af234a7b63200787&v=4 + url: https://github.com/lpdswing +SepehrRasouli: + login: SepehrRasouli + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/81516241?u=3987e880c77d653dd85963302150e07bb7c0ef99&v=4 + url: https://github.com/SepehrRasouli +Zxilly: + login: Zxilly + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/31370133?u=c5359b8d9d80a7cdc23d5295d179ed90174996c8&v=4 + url: https://github.com/Zxilly +eavv: + login: eavv + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/18273429?u=c05e8b4ea62810ee7889ca049e510cdd0a66fd26&v=4 + url: https://github.com/eavv +AlexandreBiguet: + login: AlexandreBiguet + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/1483079?u=ff926455cd4cab03c6c49441aa5dc2b21df3e266&v=4 + url: https://github.com/AlexandreBiguet +FelipeSilva93: + login: FelipeSilva93 + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/66804965?u=e7cb4b580e46f2e04ecb4cd4d7a12acdddd3c6c1&v=4 + url: https://github.com/FelipeSilva93 +peacekimjapan: + login: peacekimjapan + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/33534175?u=e4219bcebc3773a7068cc34c3eb268ef77cec31b&v=4 + url: https://github.com/peacekimjapan +bas-baskara: + login: bas-baskara + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/41407847?u=cdabfaff7481c3323f24a76d9350393b964f2b89&v=4 + url: https://github.com/bas-baskara +odiseo0: + login: odiseo0 + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/87550035?u=75e754b9bd12ce6dfe90ad68e82e6f5255c7ac09&v=4 + url: https://github.com/odiseo0 +eryknn: + login: eryknn + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/87120651?v=4 + url: https://github.com/eryknn +personage-hub: + login: personage-hub + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/76659786?v=4 + url: https://github.com/personage-hub +aminalaee: + login: aminalaee + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/19784933?v=4 + url: https://github.com/aminalaee +erfan-rfmhr: + login: erfan-rfmhr + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/98986056?u=0acda1ff1df0989f3f3eb79977baa35da4cb6c8c&v=4 + url: https://github.com/erfan-rfmhr +Scorpionchiques: + login: Scorpionchiques + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/15703294?v=4 + url: https://github.com/Scorpionchiques +lordqyxz: + login: lordqyxz + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/31722468?u=974553c0ba53526d9be7e9876544283291be3b0d&v=4 + url: https://github.com/lordqyxz +heysaeid: + login: heysaeid + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/63112273?u=5397ead391319a147a18b70cc04d1a334f235ef3&v=4 + url: https://github.com/heysaeid +Yois4101: + login: Yois4101 + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/119609381?v=4 + url: https://github.com/Yois4101 +tamtam-fitness: + login: tamtam-fitness + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/62091034?u=8da19a6bd3d02f5d6ba30c7247d5b46c98dd1403&v=4 + url: https://github.com/tamtam-fitness +mpmeleshko: + login: mpmeleshko + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/34425664?v=4 + url: https://github.com/mpmeleshko +SonnyYou: + login: SonnyYou + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/18657569?v=4 + url: https://github.com/SonnyYou +matiasbertani: + login: matiasbertani + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/65260383?u=d5edd86a6e2ab4fb1aab7751931fe045a963afd7&v=4 + url: https://github.com/matiasbertani +thiennc254: + login: thiennc254 + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/97406628?u=1b2860679694b9a552764d0fa81dbd7a016322ec&v=4 + url: https://github.com/thiennc254 +javillegasna: + login: javillegasna + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/38879192?u=df9ab0d628f8c1f1c849db7b3c0939337f42c3f1&v=4 + url: https://github.com/javillegasna +9zimin9: + login: 9zimin9 + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/174453744?v=4 + url: https://github.com/9zimin9 +ilhamfadillah: + login: ilhamfadillah + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/20577838?u=c56192cf99b55affcaad408b240259c62e633450&v=4 + url: https://github.com/ilhamfadillah +gerry-sabar: + login: gerry-sabar + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/1120123?v=4 + url: https://github.com/gerry-sabar +cookie-byte217: + login: cookie-byte217 + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/57880178?v=4 + url: https://github.com/cookie-byte217 +AbolfazlKameli: + login: AbolfazlKameli + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/120686133?u=af8f025278cce0d489007071254e4055df60b78c&v=4 + url: https://github.com/AbolfazlKameli +SBillion: + login: SBillion + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/1070649?u=3ab493dfc88b39da0eb1600e3b8e7df1c90a5dee&v=4 + url: https://github.com/SBillion +seuthootDev: + login: seuthootDev + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/175179350?u=7c2cbc48ab43b52e0c86592111d92e013d72ea4d&v=4 + url: https://github.com/seuthootDev +tyronedamasceno: + login: tyronedamasceno + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/12273721?u=913bca6bab96d9416ad8c9874c80de0833782050&v=4 + url: https://github.com/tyronedamasceno +LikoIlya: + login: LikoIlya + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/15039930?v=4 + url: https://github.com/LikoIlya +ss-o-furda: + login: ss-o-furda + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/56111536?u=d2326baa464a3778c280ed85fd14c00f87eb1080&v=4 + url: https://github.com/ss-o-furda +Frans06: + login: Frans06 + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/5842109?u=77529d5517ae80438249b1a45f2d59372a31a212&v=4 + url: https://github.com/Frans06 +Jefidev: + login: Jefidev + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/9964497?u=1da6eee587a8b425ca4afbfdfc6c3a639fe85d02&v=4 + url: https://github.com/Jefidev +Xaraxx: + login: Xaraxx + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/29824698?u=dde2e233e22bb5ca1f8bb0c6e353ccd0d06e6066&v=4 + url: https://github.com/Xaraxx +Suyoung789: + login: Suyoung789 + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/31277231?u=1591aaf651eb860017231a36590050e154c026b6&v=4 + url: https://github.com/Suyoung789 +akagaeng: + login: akagaeng + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/17076841?u=9ada2eb6a33dc705ba96d58f802c787dea3859b8&v=4 + url: https://github.com/akagaeng +phamquanganh31101998: + login: phamquanganh31101998 + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/43257497?u=6b3419ea9e318c356c42a973fb947682590bd8d3&v=4 + url: https://github.com/phamquanganh31101998 +peebbv6364: + login: peebbv6364 + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/26784747?u=3bf07017eb4f4fa3639ba8d4ed19980a34bf8f90&v=4 + url: https://github.com/peebbv6364 +mrparalon: + login: mrparalon + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/19637629?u=6339508ceb665717cae862a4d33816ac874cbb8f&v=4 + url: https://github.com/mrparalon +creyD: + login: creyD + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/15138480?u=51cd2873cd93807beb578af8e23975856fdbc945&v=4 + url: https://github.com/creyD +zhoonit: + login: zhoonit + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/17230883?u=698cb26dcce4770374b592aad3b7489e91c07fc6&v=4 + url: https://github.com/zhoonit +Sefank: + login: Sefank + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/12670778?u=ca16995c68a82cabc7435c54ac0564930f62dd59&v=4 + url: https://github.com/Sefank +RuslanTer: + login: RuslanTer + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/48125303?v=4 + url: https://github.com/RuslanTer +FedorGN: + login: FedorGN + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/66411909?u=22382380e7d66ee57ffbfc2ae6bd5efd0cdb672e&v=4 + url: https://github.com/FedorGN +rafsaf: + login: rafsaf + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/51059348?u=5fe59a56e1f2f9ccd8005d71752a8276f133ae1a&v=4 + url: https://github.com/rafsaf +frnsimoes: + login: frnsimoes + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/66239468?u=c86ceed4afa180477e28b9ff0019ab894a1e1eb9&v=4 + url: https://github.com/frnsimoes +lieryan: + login: lieryan + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/1006989?v=4 + url: https://github.com/lieryan +ValeryVal: + login: ValeryVal + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/85856176?v=4 + url: https://github.com/ValeryVal +chesstrian: + login: chesstrian + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/3923412?u=8ea9bea6cfb5e6c64dc81be65ac2a9aaf23c5d47&v=4 + url: https://github.com/chesstrian +PabloEmidio: + login: PabloEmidio + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/69937719?u=f4d04cb78da68bb93a641f0b793ff665162e712a&v=4 + url: https://github.com/PabloEmidio +PraveenNanda124: + login: PraveenNanda124 + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/116082827?u=b40c4f23c191692e88f676dc3bf33fc7f315edd4&v=4 + url: https://github.com/PraveenNanda124 +guites: + login: guites + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/71985299?u=5dab5eb82b0a67fe709fc893f47a423df4de5d46&v=4 + url: https://github.com/guites +Junhyung21: + login: Junhyung21 + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/138214497?u=66377988eaad4f57004decb183f396560407a73f&v=4 + url: https://github.com/Junhyung21 +rinaatt: + login: rinaatt + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/6111202?u=9f62ebd2a72879db54d0b51c07c1d1e7203a4813&v=4 + url: https://github.com/rinaatt +Slijeff: + login: Slijeff + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/31459252?u=083776331690bbcf427766071e33ac28bb8d271d&v=4 + url: https://github.com/Slijeff +GeorchW: + login: GeorchW + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/8687777?u=ae4160f1d88f32692760003f3be9b5fc40a6e00d&v=4 + url: https://github.com/GeorchW +Vlad0395: + login: Vlad0395 + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/37487589?u=57dc6660b9904cc0bc59b73569bbfb1ac871a4a1&v=4 + url: https://github.com/Vlad0395 +bisibuka: + login: bisibuka + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/221887?v=4 + url: https://github.com/bisibuka +aimasheraz1: + login: aimasheraz1 + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/132935019?v=4 + url: https://github.com/aimasheraz1 +whysage: + login: whysage + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/67018871?u=a05d63a1b315dcf56a4c0dda3c0ca84ce3d6c87f&v=4 + url: https://github.com/whysage +Chake9928: + login: Chake9928 + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/62596047?u=7aa2c0aad46911934ce3d22f83a895d05fa54e09&v=4 + url: https://github.com/Chake9928 +qaerial: + login: qaerial + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/41595550?v=4 + url: https://github.com/qaerial +bluefish6: + login: bluefish6 + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/3324881?u=d107f6d0017927191644829fb845a8ceb8ac20ee&v=4 + url: https://github.com/bluefish6 +Sion99: + login: Sion99 + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/82511301?v=4 + url: https://github.com/Sion99 +nymous: + login: nymous + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/4216559?u=360a36fb602cded27273cbfc0afc296eece90662&v=4 + url: https://github.com/nymous +EpsilonRationes: + login: EpsilonRationes + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/148639079?u=5dd6c4a3f570dea44d208465fd10b709bcdfa69a&v=4 + url: https://github.com/EpsilonRationes +SametEmin: + login: SametEmin + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/115692383?u=bda9052f698e50b0df6657fb9436d07e8496fe2f&v=4 + url: https://github.com/SametEmin +fhabers21: + login: fhabers21 + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/58401847?v=4 + url: https://github.com/fhabers21 +kohiry: + login: kohiry + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/57669492?u=f6ab0a062740261e882879269a41a47788c84043&v=4 + url: https://github.com/kohiry +ptt3199: + login: ptt3199 + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/51350651?u=2c3d947a80283e32bf616d4c3af139a6be69680f&v=4 + url: https://github.com/ptt3199 +arynoot: + login: arynoot + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/73756088?v=4 + url: https://github.com/arynoot +GDemay: + login: GDemay + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/7033942?u=bbdcb4e2a67df4ec9caa2440362d8cebc44d65e8&v=4 + url: https://github.com/GDemay +maxscheijen: + login: maxscheijen + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/47034840?v=4 + url: https://github.com/maxscheijen +celestywang: + login: celestywang + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/184830753?v=4 + url: https://github.com/celestywang +RyaWcksn: + login: RyaWcksn + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/42831964?u=0cb4265faf3e3425a89e59b6fddd3eb2de180af0&v=4 + url: https://github.com/RyaWcksn +tienduong-21: + login: tienduong-21 + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/80129618?v=4 + url: https://github.com/tienduong-21 +zbellos: + login: zbellos + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/204500646?v=4 + url: https://github.com/zbellos +Mohammad222PR: + login: Mohammad222PR + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/116789737?u=25810a5fe049d2f1618e2e7417cea011cc353ce4&v=4 + url: https://github.com/Mohammad222PR +crr004: + login: crr004 + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/110995013?u=b1a0cd6b11043dafa7caa1ab6e151c8e063476bc&v=4 + url: https://github.com/crr004 +blaisep: + login: blaisep + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/254456?u=97d584b7c0a6faf583aa59975df4f993f671d121&v=4 + url: https://github.com/blaisep +SirTelemak: + login: SirTelemak + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/9435877?u=719327b7d2c4c62212456d771bfa7c6b8dbb9eac&v=4 + url: https://github.com/SirTelemak +ovezovs: + login: ovezovs + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/44060682?u=9cb4d738b15e64157cb65afbe2e31bd0c8f3f6e6&v=4 + url: https://github.com/ovezovs +neatek: + login: neatek + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/3075678?u=3001e778e4aa0bf6d3142d09f0b9d13b2c55066f&v=4 + url: https://github.com/neatek +sprytnyk: + login: sprytnyk + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/16718258?u=4893ea96bfebfbdbde8abd9e06851eca12b01bc9&v=4 + url: https://github.com/sprytnyk +wfpinedar: + login: wfpinedar + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/5309214?u=4af7b6b3907b015699a9994d0808137dd68f7658&v=4 + url: https://github.com/wfpinedar +italopenaforte: + login: italopenaforte + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/7786881?u=e64a8f24b1ba95eb82f283be8ab90892e40c5465&v=4 + url: https://github.com/italopenaforte +hackerneocom: + login: hackerneocom + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/67042948?u=ca365045bd261cec5a64059aa23cf80065148c3c&v=4 + url: https://github.com/hackerneocom +dmas-at-wiris: + login: dmas-at-wiris + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/24917162?u=0df147936a375b4b64232c650de31a227a6b59a0&v=4 + url: https://github.com/dmas-at-wiris +TorhamDev: + login: TorhamDev + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/87639984?u=07e5429fbd9c5d63c5ca55a0f31ef541216f0ce6&v=4 + url: https://github.com/TorhamDev +jaystone776: + login: jaystone776 + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/11191137?u=299205a95e9b6817a43144a48b643346a5aac5cc&v=4 + url: https://github.com/jaystone776 +AaronDewes: + login: AaronDewes + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/67546953?v=4 + url: https://github.com/AaronDewes +kunansy: + login: kunansy + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/20476946?u=d8321cd00787d5ee29bfdd8ff6fde23ad783a581&v=4 + url: https://github.com/kunansy +TimorChow: + login: TimorChow + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/18365403?u=bcbb357be0a447bc682a161932eab5032cede4af&v=4 + url: https://github.com/TimorChow +ataberkciftlikli: + login: ataberkciftlikli + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/64265169?u=ca7c1348242559f70bc1dc027a4be277c464676f&v=4 + url: https://github.com/ataberkciftlikli +leandrodesouzadev: + login: leandrodesouzadev + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/85115541?u=4eb25f43f1fe23727d61e986cf83b73b86e2a95a&v=4 + url: https://github.com/leandrodesouzadev +dutkiewicz: + login: dutkiewicz + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/6649846?u=e941be6e1ab2ffdf41cea227a73f0ffbef20628f&v=4 + url: https://github.com/dutkiewicz +mirusu400: + login: mirusu400 + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/25397908?u=deda776115e4ee6f76fa526bb5127bd1a6c4b231&v=4 + url: https://github.com/mirusu400 +its0x08: + login: its0x08 + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/15280042?u=d7c2058f29d4e8fbdae09b194e04c5e410350211&v=4 + url: https://github.com/its0x08 +linsein: + login: linsein + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/23748021?u=4db169ce262b69aa7292f82b785436544f69fb88&v=4 + url: https://github.com/linsein +0xflotus: + login: 0xflotus + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/26602940?u=3c52ce6393bb547c97e6380ccdee03e0c64152c6&v=4 + url: https://github.com/0xflotus +jonatasoli: + login: jonatasoli + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/26334101?u=f601c3f111f2148bd9244c2cb3ebbd57b592e674&v=4 + url: https://github.com/jonatasoli +tyzh-dev: + login: tyzh-dev + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/51972581?u=ba3882da7c009918a8e2d6b9ead31c89f09c922d&v=4 + url: https://github.com/tyzh-dev +yurkevich-dev: + login: yurkevich-dev + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/45145188?u=db2de8c186073d95693279dcf085fcebffab57d0&v=4 + url: https://github.com/yurkevich-dev +emp7yhead: + login: emp7yhead + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/20521260?u=9494c74cb9e1601d734b1f2726e292e257777d98&v=4 + url: https://github.com/emp7yhead +BartoszCki: + login: BartoszCki + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/17833351?u=40025e1182c32a9664834baec268dadad127703d&v=4 + url: https://github.com/BartoszCki +hakancelikdev: + login: hakancelikdev + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/19157033?u=095ea8e0af1de642edd92e5f806c70359e00c977&v=4 + url: https://github.com/hakancelikdev +KaterinaSolovyeva: + login: KaterinaSolovyeva + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/85114725?u=1fe81463cb6b1fd01ac047172fa4895e2a3cecaa&v=4 + url: https://github.com/KaterinaSolovyeva +zhanymkanov: + login: zhanymkanov + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/22341602?u=aa1c47285a4f5692d165ccb2a441c5553f23ef83&v=4 + url: https://github.com/zhanymkanov +felipebpl: + login: felipebpl + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/62957465?u=3c05f0f358b9575503c03122daefb115b6ac1414&v=4 + url: https://github.com/felipebpl +iudeen: + login: iudeen + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/10519440?u=f09cdd745e5bf16138f29b42732dd57c7f02bee1&v=4 + url: https://github.com/iudeen +dwisulfahnur: + login: dwisulfahnur + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/12431528?v=4 + url: https://github.com/dwisulfahnur +ayr-ton: + login: ayr-ton + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/1090517?u=5cf70a0e0f0dbf084e074e494aa94d7c91a46ba6&v=4 + url: https://github.com/ayr-ton +Kadermiyanyedi: + login: Kadermiyanyedi + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/48386782?u=08c0f1594c5baf28b6fab7520a848cb9c3806c8e&v=4 + url: https://github.com/Kadermiyanyedi +raphaelauv: + login: raphaelauv + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/10202690?u=e6f86f5c0c3026a15d6b51792fa3e532b12f1371&v=4 + url: https://github.com/raphaelauv +Fahad-Md-Kamal: + login: Fahad-Md-Kamal + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/34704464?u=0b1da22a9b88b14d99e7e4368eadde7ecd695366&v=4 + url: https://github.com/Fahad-Md-Kamal +zxcq544: + login: zxcq544 + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/5781268?u=25959ea03803742c3b28220b27fc07923a491dcb&v=4 + url: https://github.com/zxcq544 +AlexandrMaltsevYDX: + login: AlexandrMaltsevYDX + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/109986802?u=ed275d72bfcdb4d15abdd54e7be026adbb9ca098&v=4 + url: https://github.com/AlexandrMaltsevYDX +realFranco: + login: realFranco + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/45880759?u=22fea3007d3e2d4c8c82d6ccfbde71454c4c6dd8&v=4 + url: https://github.com/realFranco +piaria: + login: piaria + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/110835535?u=5af3d56254faa05bbca4258a46c5723489480f90&v=4 + url: https://github.com/piaria +mojtabapaso: + login: mojtabapaso + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/121169359?u=ced1d5ad673bcd9e949ebf967a4ab50185637443&v=4 + url: https://github.com/mojtabapaso +eghbalpoorMH: + login: eghbalpoorMH + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/36267498?v=4 + url: https://github.com/eghbalpoorMH +Tiazen: + login: Tiazen + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/16170159?u=0ce5e32f76e3f10733c8f25d97db9e31b753838c&v=4 + url: https://github.com/Tiazen +jfunez: + login: jfunez + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/805749?v=4 + url: https://github.com/jfunez +s-rigaud: + login: s-rigaud + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/46346622?u=eee0adaa9fdff9e312d52526fbd4020dd6860c27&v=4 + url: https://github.com/s-rigaud +Artem4es: + login: Artem4es + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/110793967?u=0f9d4e80e055adc1aa8b548e951f6b4989fa2e78&v=4 + url: https://github.com/Artem4es +sulemanhelp: + login: sulemanhelp + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/22400366?u=3e8e68750655c7f5b2e0ba1d54f5779ee526707d&v=4 + url: https://github.com/sulemanhelp +theRealNonso: + login: theRealNonso + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/29557286?u=6f062680edccfeb4c802daf3b1d8b2a9e21ae013&v=4 + url: https://github.com/theRealNonso +AhsanSheraz: + login: AhsanSheraz + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/51913596?u=b5aa3c3a004cc0112e56c54f6901941836d8c26b&v=4 + url: https://github.com/AhsanSheraz +HealerNguyen: + login: HealerNguyen + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/29653304?u=6ab095689054c63b1f4ceb26dd66847450225c87&v=4 + url: https://github.com/HealerNguyen +isulim: + login: isulim + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/30448496?u=44c47838defa48a16606b895dce08890fca8482f&v=4 + url: https://github.com/isulim +siavashyj: + login: siavashyj + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/43583410?u=562005ddc7901cd27a1219a118a2363817b14977&v=4 + url: https://github.com/siavashyj +Ramin-RX7: + login: Ramin-RX7 + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/52785580?u=b3678f779ad0ee9cd9dca9e50ccb804b5eb990a5&v=4 + url: https://github.com/Ramin-RX7 +DevSpace88: + login: DevSpace88 + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/102557040?u=103e454f0d4d2d357bd66e9931e57f0bf267526a&v=4 + url: https://github.com/DevSpace88 +Yum-git: + login: Yum-git + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/56100888?u=7c6ae21af081488b5fb703ab096fb1926025fd50&v=4 + url: https://github.com/Yum-git +oubush: + login: oubush + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/7489099?u=c86448bc61f5e7f03a1f14a768beeb09c33899d4&v=4 + url: https://github.com/oubush +KAZAMA-DREAM: + login: KAZAMA-DREAM + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/73453137?u=5108c757a3842733a448d9a16cdc65d82899eee1&v=4 + url: https://github.com/KAZAMA-DREAM +aprilcoskun: + login: aprilcoskun + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/17393603?u=18177d5bdba3a4567b8664587c882fb734e5fa09&v=4 + url: https://github.com/aprilcoskun +zhiquanchi: + login: zhiquanchi + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/29973289?u=744c74bc2635f839235ec32a0a934c5cef9a156d&v=4 + url: https://github.com/zhiquanchi +Jamim: + login: Jamim + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/5607572?u=9ce0b6a6d1a5124e28b3c04d8d26827ca328713a&v=4 + url: https://github.com/Jamim +alvinkhalil: + login: alvinkhalil + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/84583022?u=ab0eeb9ce6ffe93fd9bb23daf782b9867b864149&v=4 + url: https://github.com/alvinkhalil +leylaeminova: + login: leylaeminova + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/100516839?u=0b0dab9e31742076b22812b14a39b4e6d8f6de4a&v=4 + url: https://github.com/leylaeminova +UN-9BOT: + login: UN-9BOT + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/111110804?u=39e158937ed795972c2d0400fc521c50e9bfb9e7&v=4 + url: https://github.com/UN-9BOT +flasonme: + login: flasonme + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/30571019?v=4 + url: https://github.com/flasonme +gustavoprezoto: + login: gustavoprezoto + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/62812585?u=2e936a0c6a2f11ecf3a735ebd33386100bcfebf8&v=4 + url: https://github.com/gustavoprezoto +johnny630: + login: johnny630 + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/2870590?v=4 + url: https://github.com/johnny630 +JCTrapero: + login: JCTrapero + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/109148166?u=bea607a04058176c4c2ae0d7c2e9ec647ccef002&v=4 + url: https://github.com/JCTrapero +ZhibangYue: + login: ZhibangYue + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/93324586?u=20fb23e3718e0364bb217966470d35e0637dd4fe&v=4 + url: https://github.com/ZhibangYue +saeye: + login: saeye + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/62229734?u=312d619db2588b60d5d5bde65260a2f44fdc6c76&v=4 + url: https://github.com/saeye +Heumhub: + login: Heumhub + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/173761521?v=4 + url: https://github.com/Heumhub +manumolina: + login: manumolina + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/2404208?u=fdc5502910f8dec814b2477f89587b9e45fac846&v=4 + url: https://github.com/manumolina +logan2d5: + login: logan2d5 + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/146642263?u=dbd6621f8b0330d6919f6a7131277b92e26fbe87&v=4 + url: https://github.com/logan2d5 +guspan-tanadi: + login: guspan-tanadi + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/36249910?v=4 + url: https://github.com/guspan-tanadi +tiaggo16: + login: tiaggo16 + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/62227573?u=359f4e2c51a4b13c8553ac5af405d635b07bb61f&v=4 + url: https://github.com/tiaggo16 +kiharito: + login: kiharito + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/38311245?u=531bd2230b752826edc01dc9d950f2f36017a6f0&v=4 + url: https://github.com/kiharito +t4f1d: + login: t4f1d + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/4054172?u=463d5ce0ec8ad8582f6e9351bb8c9a5105b39bb7&v=4 + url: https://github.com/t4f1d +J-Fuji: + login: J-Fuji + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/101452903?v=4 + url: https://github.com/J-Fuji +MrL8199: + login: MrL8199 + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/39489075?u=3fc4f89c86973e40b5970d838c801bdbc13ac828&v=4 + url: https://github.com/MrL8199 +ivintoiu: + login: ivintoiu + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/1853336?u=e3de5fd0ab17efc12256b4295285b504ca281440&v=4 + url: https://github.com/ivintoiu +TechnoService2: + login: TechnoService2 + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/142113388?v=4 + url: https://github.com/TechnoService2 +EgorOnishchuk: + login: EgorOnishchuk + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/120256301?v=4 + url: https://github.com/EgorOnishchuk +iamantonreznik: + login: iamantonreznik + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/112612414?u=b9ba8d9b4d3940198bc3a4353dfce70c044a39b1&v=4 + url: https://github.com/iamantonreznik +Azazul123: + login: Azazul123 + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/102759111?u=b48ce6e30a81a23467cc30e0c011bcc57f0326ab&v=4 + url: https://github.com/Azazul123 +ykertytsky: + login: ykertytsky + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/83857001?u=1f303eb73189f78cff376c13bd46db65f90ee314&v=4 + url: https://github.com/ykertytsky +NavesSapnis: + login: NavesSapnis + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/79222417?u=b5b10291b8e9130ca84fd20f0a641e04ed94b6b1&v=4 + url: https://github.com/NavesSapnis +isgin01: + login: isgin01 + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/157279130?u=16d6466476cf7dbc55a4cd575b6ea920ebdd81e1&v=4 + url: https://github.com/isgin01 +syedasamina56: + login: syedasamina56 + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/183273097?v=4 + url: https://github.com/syedasamina56 diff --git a/docs/en/data/translators.yml b/docs/en/data/translators.yml new file mode 100644 index 0000000000000..ccad6767fafd3 --- /dev/null +++ b/docs/en/data/translators.yml @@ -0,0 +1,555 @@ +nilslindemann: + login: nilslindemann + count: 130 + avatarUrl: https://avatars.githubusercontent.com/u/6892179?u=1dca6a22195d6cd1ab20737c0e19a4c55d639472&v=4 + url: https://github.com/nilslindemann +tiangolo: + login: tiangolo + count: 100 + avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 + url: https://github.com/tiangolo +jaystone776: + login: jaystone776 + count: 46 + avatarUrl: https://avatars.githubusercontent.com/u/11191137?u=299205a95e9b6817a43144a48b643346a5aac5cc&v=4 + url: https://github.com/jaystone776 +ceb10n: + login: ceb10n + count: 30 + avatarUrl: https://avatars.githubusercontent.com/u/235213?u=edcce471814a1eba9f0cdaa4cd0de18921a940a6&v=4 + url: https://github.com/ceb10n +valentinDruzhinin: + login: valentinDruzhinin + count: 29 + avatarUrl: https://avatars.githubusercontent.com/u/12831905?u=aae1ebc675c91e8fa582df4fcc4fc4128106344d&v=4 + url: https://github.com/valentinDruzhinin +YuriiMotov: + login: YuriiMotov + count: 24 + avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=bc48be95c429989224786106b027f3c5e40cc354&v=4 + url: https://github.com/YuriiMotov +tokusumi: + login: tokusumi + count: 23 + avatarUrl: https://avatars.githubusercontent.com/u/41147016?u=55010621aece725aa702270b54fed829b6a1fe60&v=4 + url: https://github.com/tokusumi +SwftAlpc: + login: SwftAlpc + count: 23 + avatarUrl: https://avatars.githubusercontent.com/u/52768429?u=6a3aa15277406520ad37f6236e89466ed44bc5b8&v=4 + url: https://github.com/SwftAlpc +hasansezertasan: + login: hasansezertasan + count: 22 + avatarUrl: https://avatars.githubusercontent.com/u/13135006?u=d36995e41a00590da64e6204cfd112e0484ac1ca&v=4 + url: https://github.com/hasansezertasan +waynerv: + login: waynerv + count: 20 + avatarUrl: https://avatars.githubusercontent.com/u/39515546?u=ec35139777597cdbbbddda29bf8b9d4396b429a9&v=4 + url: https://github.com/waynerv +hard-coders: + login: hard-coders + count: 16 + avatarUrl: https://avatars.githubusercontent.com/u/9651103?u=78d12d1acdf853c817700145e73de7fd9e5d068b&v=4 + url: https://github.com/hard-coders +AlertRED: + login: AlertRED + count: 16 + avatarUrl: https://avatars.githubusercontent.com/u/15695000?u=f5a4944c6df443030409c88da7d7fa0b7ead985c&v=4 + url: https://github.com/AlertRED +Joao-Pedro-P-Holanda: + login: Joao-Pedro-P-Holanda + count: 14 + avatarUrl: https://avatars.githubusercontent.com/u/110267046?u=331bd016326dac4cf3df4848f6db2dbbf8b5f978&v=4 + url: https://github.com/Joao-Pedro-P-Holanda +yychanlee: + login: yychanlee + count: 14 + avatarUrl: https://avatars.githubusercontent.com/u/103817302?u=3a042740dc0ff58615da0d8679230966fd7693e8&v=4 + url: https://github.com/yychanlee +Xewus: + login: Xewus + count: 13 + avatarUrl: https://avatars.githubusercontent.com/u/85196001?u=f8e2dc7e5104f109cef944af79050ea8d1b8f914&v=4 + url: https://github.com/Xewus +Zhongheng-Cheng: + login: Zhongheng-Cheng + count: 13 + avatarUrl: https://avatars.githubusercontent.com/u/95612344?u=a0f7730a3cc7486827965e01a119ad610bda4b0a&v=4 + url: https://github.com/Zhongheng-Cheng +Smlep: + login: Smlep + count: 11 + avatarUrl: https://avatars.githubusercontent.com/u/16785985?u=ffe99fa954c8e774ef1117e58d34aece92051e27&v=4 + url: https://github.com/Smlep +marcelomarkus: + login: marcelomarkus + count: 11 + avatarUrl: https://avatars.githubusercontent.com/u/20115018?u=dda090ce9160ef0cd2ff69b1e5ea741283425cba&v=4 + url: https://github.com/marcelomarkus +KaniKim: + login: KaniKim + count: 10 + avatarUrl: https://avatars.githubusercontent.com/u/19832624?u=296dbdd490e0eb96e3d45a2608c065603b17dc31&v=4 + url: https://github.com/KaniKim +Vincy1230: + login: Vincy1230 + count: 9 + avatarUrl: https://avatars.githubusercontent.com/u/81342412?u=ab5e256a4077a4a91f3f9cd2115ba80780454cbe&v=4 + url: https://github.com/Vincy1230 +rjNemo: + login: rjNemo + count: 8 + avatarUrl: https://avatars.githubusercontent.com/u/56785022?u=d5c3a02567c8649e146fcfc51b6060ccaf8adef8&v=4 + url: https://github.com/rjNemo +xzmeng: + login: xzmeng + count: 8 + avatarUrl: https://avatars.githubusercontent.com/u/40202897?v=4 + url: https://github.com/xzmeng +pablocm83: + login: pablocm83 + count: 8 + avatarUrl: https://avatars.githubusercontent.com/u/28315068?u=3310fbb05bb8bfc50d2c48b6cb64ac9ee4a14549&v=4 + url: https://github.com/pablocm83 +ptt3199: + login: ptt3199 + count: 7 + avatarUrl: https://avatars.githubusercontent.com/u/51350651?u=2c3d947a80283e32bf616d4c3af139a6be69680f&v=4 + url: https://github.com/ptt3199 +NinaHwang: + login: NinaHwang + count: 6 + avatarUrl: https://avatars.githubusercontent.com/u/79563565?u=241f2cb6d38a2d379536608a8ea5a22ed4b1a3ea&v=4 + url: https://github.com/NinaHwang +batlopes: + login: batlopes + count: 6 + avatarUrl: https://avatars.githubusercontent.com/u/33462923?u=0fb3d7acb316764616f11e4947faf080e49ad8d9&v=4 + url: https://github.com/batlopes +lucasbalieiro: + login: lucasbalieiro + count: 6 + avatarUrl: https://avatars.githubusercontent.com/u/37416577?u=d144221c34c08adac8b20e1833d776ffa1c4b1d0&v=4 + url: https://github.com/lucasbalieiro +Alexandrhub: + login: Alexandrhub + count: 6 + avatarUrl: https://avatars.githubusercontent.com/u/119126536?u=9fc0d48f3307817bafecc5861eb2168401a6cb04&v=4 + url: https://github.com/Alexandrhub +Serrones: + login: Serrones + count: 5 + avatarUrl: https://avatars.githubusercontent.com/u/22691749?u=4795b880e13ca33a73e52fc0ef7dc9c60c8fce47&v=4 + url: https://github.com/Serrones +RunningIkkyu: + login: RunningIkkyu + count: 5 + avatarUrl: https://avatars.githubusercontent.com/u/31848542?u=494ecc298e3f26197495bb357ad0f57cfd5f7a32&v=4 + url: https://github.com/RunningIkkyu +Attsun1031: + login: Attsun1031 + count: 5 + avatarUrl: https://avatars.githubusercontent.com/u/1175560?v=4 + url: https://github.com/Attsun1031 +rostik1410: + login: rostik1410 + count: 5 + avatarUrl: https://avatars.githubusercontent.com/u/11443899?u=e26a635c2ba220467b308a326a579b8ccf4a8701&v=4 + url: https://github.com/rostik1410 +alv2017: + login: alv2017 + count: 5 + avatarUrl: https://avatars.githubusercontent.com/u/31544722?v=4 + url: https://github.com/alv2017 +komtaki: + login: komtaki + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/39375566?u=260ad6b1a4b34c07dbfa728da5e586f16f6d1824&v=4 + url: https://github.com/komtaki +JulianMaurin: + login: JulianMaurin + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/63545168?u=b7d15ac865268cbefc2d739e2f23d9aeeac1a622&v=4 + url: https://github.com/JulianMaurin +stlucasgarcia: + login: stlucasgarcia + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/61513630?u=c22d8850e9dc396a8820766a59837f967e14f9a0&v=4 + url: https://github.com/stlucasgarcia +ComicShrimp: + login: ComicShrimp + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/43503750?u=d2fbf412e7730183ce91686ca48d4147e1b7dc74&v=4 + url: https://github.com/ComicShrimp +BilalAlpaslan: + login: BilalAlpaslan + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/47563997?u=63ed66e304fe8d765762c70587d61d9196e5c82d&v=4 + url: https://github.com/BilalAlpaslan +axel584: + login: axel584 + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/1334088?u=9667041f5b15dc002b6f9665fda8c0412933ac04&v=4 + url: https://github.com/axel584 +tamtam-fitness: + login: tamtam-fitness + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/62091034?u=8da19a6bd3d02f5d6ba30c7247d5b46c98dd1403&v=4 + url: https://github.com/tamtam-fitness +Limsunoh: + login: Limsunoh + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/90311848?u=f456e0c5709fd50c8cd2898b551558eda14e5f21&v=4 + url: https://github.com/Limsunoh +kwang1215: + login: kwang1215 + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/74170199?u=2a63ff6692119dde3f5e5693365b9fcd6f977b08&v=4 + url: https://github.com/kwang1215 +k94-ishi: + login: k94-ishi + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/32672580?u=bc7c5c07af0656be9fe4f1784a444af8d81ded89&v=4 + url: https://github.com/k94-ishi +Mohammad222PR: + login: Mohammad222PR + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/116789737?u=25810a5fe049d2f1618e2e7417cea011cc353ce4&v=4 + url: https://github.com/Mohammad222PR +NavesSapnis: + login: NavesSapnis + count: 4 + avatarUrl: https://avatars.githubusercontent.com/u/79222417?u=b5b10291b8e9130ca84fd20f0a641e04ed94b6b1&v=4 + url: https://github.com/NavesSapnis +jfunez: + login: jfunez + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/805749?v=4 + url: https://github.com/jfunez +ycd: + login: ycd + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/62724709?u=f1e7bae394a315da950912c92dc861a8eaf95d4c&v=4 + url: https://github.com/ycd +mariacamilagl: + login: mariacamilagl + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/11489395?u=4adb6986bf3debfc2b8216ae701f2bd47d73da7d&v=4 + url: https://github.com/mariacamilagl +maoyibo: + login: maoyibo + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/7887703?v=4 + url: https://github.com/maoyibo +blt232018: + login: blt232018 + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/43393471?u=172b0e0391db1aa6c1706498d6dfcb003c8a4857&v=4 + url: https://github.com/blt232018 +magiskboy: + login: magiskboy + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/13352088?u=18b6d672523f9e9d98401f31dd50e28bb27d826f&v=4 + url: https://github.com/magiskboy +luccasmmg: + login: luccasmmg + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/11317382?u=65099a5a0d492b89119471f8a7014637cc2e04da&v=4 + url: https://github.com/luccasmmg +lbmendes: + login: lbmendes + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/80999926?u=646619e2f07ac5a7c3f65fe7834197461a4fff9f&v=4 + url: https://github.com/lbmendes +Zssaer: + login: Zssaer + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/45691504?u=4c0c195f25cb5ac6af32acfb0ab35427682938d2&v=4 + url: https://github.com/Zssaer +ChuyuChoyeon: + login: ChuyuChoyeon + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/129537877?u=f0c76f3327817a8b86b422d62e04a34bf2827f2b&v=4 + url: https://github.com/ChuyuChoyeon +ivan-abc: + login: ivan-abc + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/36765187?u=c6e0ba571c1ccb6db9d94e62e4b8b5eda811a870&v=4 + url: https://github.com/ivan-abc +mojtabapaso: + login: mojtabapaso + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/121169359?u=ced1d5ad673bcd9e949ebf967a4ab50185637443&v=4 + url: https://github.com/mojtabapaso +hsuanchi: + login: hsuanchi + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/24913710?u=7d25a398e478b6e63503bf6f26c54efa9e0da07b&v=4 + url: https://github.com/hsuanchi +alejsdev: + login: alejsdev + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/90076947?u=0facffe3abf87f57a1f05fa773d1119cc5c2f6a5&v=4 + url: https://github.com/alejsdev +riroan: + login: riroan + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/33053284?u=2d18e3771506ee874b66d6aa2b3b1107fd95c38f&v=4 + url: https://github.com/riroan +nayeonkinn: + login: nayeonkinn + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/98254573?u=64a75ac99b320d4935eff8d1fceea9680fa07473&v=4 + url: https://github.com/nayeonkinn +p3bri4n: + login: p3bri4n + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/1783138?u=7e6242eb9e85bcf673fa88bbac9dd6dc3f03b1b5&v=4 + url: https://github.com/p3bri4n +maxscheijen: + login: maxscheijen + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/47034840?v=4 + url: https://github.com/maxscheijen +ilacftemp: + login: ilacftemp + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/159066669?v=4 + url: https://github.com/ilacftemp +devluisrodrigues: + login: devluisrodrigues + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/103431660?u=d9674a3249edc4601d2c712cdebf899918503c3a&v=4 + url: https://github.com/devluisrodrigues +devfernandoa: + login: devfernandoa + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/28360583?u=c4308abd62e8847c9e572e1bb9fe6b9dc9ef8e50&v=4 + url: https://github.com/devfernandoa +kim-sangah: + login: kim-sangah + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/173775778?v=4 + url: https://github.com/kim-sangah +9zimin9: + login: 9zimin9 + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/174453744?v=4 + url: https://github.com/9zimin9 +nahyunkeem: + login: nahyunkeem + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/174440096?u=e12401d492eee58570f8914d0872b52e421a776e&v=4 + url: https://github.com/nahyunkeem +timothy-jeong: + login: timothy-jeong + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/53824764?u=db3d0cea2f5fab64d810113c5039a369699a2774&v=4 + url: https://github.com/timothy-jeong +gerry-sabar: + login: gerry-sabar + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/1120123?v=4 + url: https://github.com/gerry-sabar +Rishat-F: + login: Rishat-F + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/66554797?v=4 + url: https://github.com/Rishat-F +ruzia: + login: ruzia + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/24503?u=abce66d26c9611818720f11e6ae6773a6e0928f8&v=4 + url: https://github.com/ruzia +izaguerreiro: + login: izaguerreiro + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/2241504?v=4 + url: https://github.com/izaguerreiro +Xaraxx: + login: Xaraxx + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/29824698?u=dde2e233e22bb5ca1f8bb0c6e353ccd0d06e6066&v=4 + url: https://github.com/Xaraxx +sh0nk: + login: sh0nk + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/6478810?u=af15d724875cec682ed8088a86d36b2798f981c0&v=4 + url: https://github.com/sh0nk +dukkee: + login: dukkee + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/36825394?u=ccfd86e6a4f2d093dad6f7544cc875af67fa2df8&v=4 + url: https://github.com/dukkee +oandersonmagalhaes: + login: oandersonmagalhaes + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/83456692?u=daf5f302a59b950efc6d21129314af207e35441f&v=4 + url: https://github.com/oandersonmagalhaes +leandrodesouzadev: + login: leandrodesouzadev + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/85115541?u=4eb25f43f1fe23727d61e986cf83b73b86e2a95a&v=4 + url: https://github.com/leandrodesouzadev +kty4119: + login: kty4119 + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/49435654?v=4 + url: https://github.com/kty4119 +ASpathfinder: + login: ASpathfinder + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/31813636?u=2090bd1b7abb65cfeff0c618f99f11afa82c0548&v=4 + url: https://github.com/ASpathfinder +jujumilk3: + login: jujumilk3 + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/41659814?u=538f7dfef03b59f25e43f10d59a31c19ef538a0c&v=4 + url: https://github.com/jujumilk3 +ayr-ton: + login: ayr-ton + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/1090517?u=5cf70a0e0f0dbf084e074e494aa94d7c91a46ba6&v=4 + url: https://github.com/ayr-ton +Kadermiyanyedi: + login: Kadermiyanyedi + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/48386782?u=08c0f1594c5baf28b6fab7520a848cb9c3806c8e&v=4 + url: https://github.com/Kadermiyanyedi +KdHyeon0661: + login: KdHyeon0661 + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/20253352?u=5ae1aae34b091a39f22cbe60a02b79dcbdbea031&v=4 + url: https://github.com/KdHyeon0661 +LorhanSohaky: + login: LorhanSohaky + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/16273730?u=095b66f243a2cd6a0aadba9a095009f8aaf18393&v=4 + url: https://github.com/LorhanSohaky +cfraboulet: + login: cfraboulet + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/62244267?u=ed0e286ba48fa1dafd64a08e50f3364b8e12df34&v=4 + url: https://github.com/cfraboulet +dedkot01: + login: dedkot01 + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/26196675?u=e2966887124e67932853df4f10f86cb526edc7b0&v=4 + url: https://github.com/dedkot01 +AGolicyn: + login: AGolicyn + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/86262613?u=3c21606ab8d210a061a1673decff1e7d5592b380&v=4 + url: https://github.com/AGolicyn +fhabers21: + login: fhabers21 + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/58401847?v=4 + url: https://github.com/fhabers21 +TabarakoAkula: + login: TabarakoAkula + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/113298631?u=add801e370dbc502cd94ce6d3484760d7fef5406&v=4 + url: https://github.com/TabarakoAkula +AhsanSheraz: + login: AhsanSheraz + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/51913596?u=b5aa3c3a004cc0112e56c54f6901941836d8c26b&v=4 + url: https://github.com/AhsanSheraz +ArtemKhymenko: + login: ArtemKhymenko + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/14346625?u=f2fa553d9e5ec5e0f05d66bd649f7be347169631&v=4 + url: https://github.com/ArtemKhymenko +hasnatsajid: + login: hasnatsajid + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/86589885?u=a1f0d462a558e4fc7271bfcdc7e5e7de92b9e10b&v=4 + url: https://github.com/hasnatsajid +alperiox: + login: alperiox + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/34214152?u=2c5acad3461d4dbc2d48371ba86cac56ae9b25cc&v=4 + url: https://github.com/alperiox +emrhnsyts: + login: emrhnsyts + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/42899027?u=ad26798e3f8feed2041c5dd5f87e58933d6c3283&v=4 + url: https://github.com/emrhnsyts +vusallyv: + login: vusallyv + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/85983771?u=620ce103dcdc47953c952bb8d402a9cf8199014d&v=4 + url: https://github.com/vusallyv +jackleeio: + login: jackleeio + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/20477587?u=c5184dab6d021733d10c8f975b20e391856303d6&v=4 + url: https://github.com/jackleeio +choi-haram: + login: choi-haram + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/62204475?v=4 + url: https://github.com/choi-haram +imtiaz101325: + login: imtiaz101325 + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/54007087?u=61e79c4c39798cd4d339788045dc44d4c6252bde&v=4 + url: https://github.com/imtiaz101325 +fabianfalon: + login: fabianfalon + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/3700760?u=95f69e31280b17ac22299cdcd345323b142fe0af&v=4 + url: https://github.com/fabianfalon +waketzheng: + login: waketzheng + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/35413830?u=df19e4fd5bb928e7d086e053ef26a46aad23bf84&v=4 + url: https://github.com/waketzheng +billzhong: + login: billzhong + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/1644011?v=4 + url: https://github.com/billzhong +chaoless: + login: chaoless + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/64477804?v=4 + url: https://github.com/chaoless +logan2d5: + login: logan2d5 + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/146642263?u=dbd6621f8b0330d6919f6a7131277b92e26fbe87&v=4 + url: https://github.com/logan2d5 +andersonrocha0: + login: andersonrocha0 + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/22346169?u=93a1359c8c5461d894802c0cc65bcd09217e7a02&v=4 + url: https://github.com/andersonrocha0 +saeye: + login: saeye + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/62229734?u=312d619db2588b60d5d5bde65260a2f44fdc6c76&v=4 + url: https://github.com/saeye +11kkw: + login: 11kkw + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/21125286?v=4 + url: https://github.com/11kkw +yes0ng: + login: yes0ng + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/25501794?u=3aed18b0d491e0220a167a1e9e58bea3638c6707&v=4 + url: https://github.com/yes0ng +EgorOnishchuk: + login: EgorOnishchuk + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/120256301?v=4 + url: https://github.com/EgorOnishchuk +EdmilsonRodrigues: + login: EdmilsonRodrigues + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/62777025?u=217d6f3cd6cc750bb8818a3af7726c8d74eb7c2d&v=4 + url: https://github.com/EdmilsonRodrigues diff --git a/docs/en/docs/_llm-test.md b/docs/en/docs/_llm-test.md new file mode 100644 index 0000000000000..603474cfc652c --- /dev/null +++ b/docs/en/docs/_llm-test.md @@ -0,0 +1,495 @@ +# LLM test file { #llm-test-file } + +This document tests if the LLM, which translates the documentation, understands the `general_prompt` in `scripts/translate.py` and the language specific prompt in `docs/{language code}/llm-prompt.md`. The language specific prompt is appended to `general_prompt`. + +Tests added here will be seen by all designers of language specific prompts. + +Use as follows: + +* Have a language specific prompt - `docs/{language code}/llm-prompt.md`. +* Do a fresh translation of this document into your desired target language (see e.g. the `translate-page` command of the `translate.py`). This will create the translation under `docs/{language code}/docs/_llm-test.md`. +* Check if things are okay in the translation. +* If necessary, improve your language specific prompt, the general prompt, or the English document. +* Then manually fix the remaining issues in the translation, so that it is a good translation. +* Retranslate, having the good translation in place. The ideal result would be that the LLM makes no changes anymore to the translation. That means that the general prompt and your language specific prompt are as good as they can be (It will sometimes make a few seemingly random changes, the reason is that [LLMs are not deterministic algorithms](https://doublespeak.chat/#/handbook#deterministic-output)). + +The tests: + +## Code snippets { #code-snippets } + +//// tab | Test + +This is a code snippet: `foo`. And this is another code snippet: `bar`. And another one: `baz quux`. + +//// + +//// tab | Info + +Content of code snippets should be left as is. + +See section `### Content of code snippets` in the general prompt in `scripts/translate.py`. + +//// + +## Quotes { #quotes } + +//// tab | Test + +Yesterday, my friend wrote: "If you spell incorrectly correctly, you have spelled it incorrectly". To which I answered: "Correct, but 'incorrectly' is incorrectly not '"incorrectly"'". + +/// note + +The LLM will probably translate this wrong. Interesting is only if it keeps the fixed translation when retranslating. + +/// + +//// + +//// tab | Info + +The prompt designer may choose if they want to convert neutral quotes to typographic quotes. It is okay to leave them as is. + +See for example section `### Quotes` in `docs/de/llm-prompt.md`. + +//// + +## Quotes in code snippets { #quotes-in-code-snippets } + +//// tab | Test + +`pip install "foo[bar]"` + +Examples for string literals in code snippets: `"this"`, `'that'`. + +A difficult example for string literals in code snippets: `f"I like {'oranges' if orange else "apples"}"` + +Hardcore: `Yesterday, my friend wrote: "If you spell incorrectly correctly, you have spelled it incorrectly". To which I answered: "Correct, but 'incorrectly' is incorrectly not '"incorrectly"'"` + +//// + +//// tab | Info + +... However, quotes inside code snippets must stay as is. + +//// + +## code blocks { #code-blocks } + +//// tab | Test + +A Bash code example... + +```bash +# Print a greeting to the universe +echo "Hello universe" +``` + +...and a console code example... + +```console +$ fastapi run main.py + FastAPI Starting server + Searching for package file structure +``` + +...and another console code example... + +```console +// Create a directory "Code" +$ mkdir code +// Switch into that directory +$ cd code +``` + +...and a Python code example... + +```Python +wont_work() # This won't work 😱 +works(foo="bar") # This works 🎉 +``` + +...and that's it. + +//// + +//// tab | Info + +Code in code blocks should not be modified, with the exception of comments. + +See section `### Content of code blocks` in the general prompt in `scripts/translate.py`. + +//// + +## Tabs and colored boxes { #tabs-and-colored-boxes } + +//// tab | Test + +/// note +Some text +/// + +/// note | Technical details +Some text +/// + +/// tip +Some text +/// + +/// warning +Some text +/// + +/// danger +Some text +/// + +//// + +//// tab | Info + +Tabs and `Info`/`Note`/`Warning`/etc. blocks should have the translation of their title added after a vertical bar (`|`). + +See sections `### Special blocks` and `### Tab blocks` in the general prompt in `scripts/translate.py`. + +//// + +## Web- and internal links { #web-and-internal-links } + +//// tab | Test + +The link text should get translated, the link address should remain unchanged: + +* [Link to heading above](#code-snippets) +* [Internal link](index.md#installation) +* [External link](https://sqlmodel.tiangolo.com/) +* [Link to a style](https://fastapi.tiangolo.com/css/styles.css) +* [Link to a script](https://fastapi.tiangolo.com/js/logic.js) +* [Link to an image](https://fastapi.tiangolo.com/img/foo.jpg) + +The link text should get translated, the link address should point to the translation: + +* [FastAPI link](https://fastapi.tiangolo.com/) + +//// + +//// tab | Info + +Links should be translated, but their address shall remain unchanged. An exception are absolute links to pages of the FastAPI documentation. In that case it should link to the translation. + +See section `### Links` in the general prompt in `scripts/translate.py`. + +//// + +## HTML "abbr" elements { #html-abbr-elements } + +//// tab | Test + +Here are some things wrapped in HTML "abbr" elements (Some are invented): + +### The abbr gives a full phrase { #the-abbr-gives-a-full-phrase } + +* GTD +* lt +* XWT +* PSGI + +### The abbr gives a full phrase and an explanation { #the-abbr-gives-a-full-phrase-and-an-explanation } + +* MDN +* I/O. + +//// + +//// tab | Info + +"title" attributes of "abbr" elements are translated following some specific instructions. + +Translations can add their own "abbr" elements which the LLM should not remove. E.g. to explain English words. + +See section `### HTML abbr elements` in the general prompt in `scripts/translate.py`. + +//// + +## HTML "dfn" elements { #html-dfn-elements } + +* cluster +* Deep Learning + +## Headings { #headings } + +//// tab | Test + +### Develop a webapp - a tutorial { #develop-a-webapp-a-tutorial } + +Hello. + +### Type hints and -annotations { #type-hints-and-annotations } + +Hello again. + +### Super- and subclasses { #super-and-subclasses } + +Hello again. + +//// + +//// tab | Info + +The only hard rule for headings is that the LLM leaves the hash part inside curly brackets unchanged, which ensures that links do not break. + +See section `### Headings` in the general prompt in `scripts/translate.py`. + +For some language specific instructions, see e.g. section `### Headings` in `docs/de/llm-prompt.md`. + +//// + +## Terms used in the docs { #terms-used-in-the-docs } + +//// tab | Test + +* you +* your + +* e.g. +* etc. + +* `foo` as an `int` +* `bar` as a `str` +* `baz` as a `list` + +* the Tutorial - User guide +* the Advanced User Guide +* the SQLModel docs +* the API docs +* the automatic docs + +* Data Science +* Deep Learning +* Machine Learning +* Dependency Injection +* HTTP Basic authentication +* HTTP Digest +* ISO format +* the JSON Schema standard +* the JSON schema +* the schema definition +* Password Flow +* Mobile + +* deprecated +* designed +* invalid +* on the fly +* standard +* default +* case-sensitive +* case-insensitive + +* to serve the application +* to serve the page + +* the app +* the application + +* the request +* the response +* the error response + +* the path operation +* the path operation decorator +* the path operation function + +* the body +* the request body +* the response body +* the JSON body +* the form body +* the file body +* the function body + +* the parameter +* the body parameter +* the path parameter +* the query parameter +* the cookie parameter +* the header parameter +* the form parameter +* the function parameter + +* the event +* the startup event +* the startup of the server +* the shutdown event +* the lifespan event + +* the handler +* the event handler +* the exception handler +* to handle + +* the model +* the Pydantic model +* the data model +* the database model +* the form model +* the model object + +* the class +* the base class +* the parent class +* the subclass +* the child class +* the sibling class +* the class method + +* the header +* the headers +* the authorization header +* the `Authorization` header +* the forwarded header + +* the dependency injection system +* the dependency +* the dependable +* the dependant + +* I/O bound +* CPU bound +* concurrency +* parallelism +* multiprocessing + +* the env var +* the environment variable +* the `PATH` +* the `PATH` variable + +* the authentication +* the authentication provider +* the authorization +* the authorization form +* the authorization provider +* the user authenticates +* the system authenticates the user + +* the CLI +* the command line interface + +* the server +* the client + +* the cloud provider +* the cloud service + +* the development +* the development stages + +* the dict +* the dictionary +* the enumeration +* the enum +* the enum member + +* the encoder +* the decoder +* to encode +* to decode + +* the exception +* to raise + +* the expression +* the statement + +* the frontend +* the backend + +* the GitHub discussion +* the GitHub issue + +* the performance +* the performance optimization + +* the return type +* the return value + +* the security +* the security scheme + +* the task +* the background task +* the task function + +* the template +* the template engine + +* the type annotation +* the type hint + +* the server worker +* the Uvicorn worker +* the Gunicorn Worker +* the worker process +* the worker class +* the workload + +* the deployment +* to deploy + +* the SDK +* the software development kit + +* the `APIRouter` +* the `requirements.txt` +* the Bearer Token +* the breaking change +* the bug +* the button +* the callable +* the code +* the commit +* the context manager +* the coroutine +* the database session +* the disk +* the domain +* the engine +* the fake X +* the HTTP GET method +* the item +* the library +* the lifespan +* the lock +* the middleware +* the mobile application +* the module +* the mounting +* the network +* the origin +* the override +* the payload +* the processor +* the property +* the proxy +* the pull request +* the query +* the RAM +* the remote machine +* the status code +* the string +* the tag +* the web framework +* the wildcard +* to return +* to validate + +//// + +//// tab | Info + +This is neither a complete nor a normative list of (mostly) technical terms seen in the docs. It may be helpful for the prompt designer to figure out for which terms the LLM needs a helping hand. For example when it keeps reverting a good translation to a suboptimal translation. Or when it has problems conjugating/declinating a term in your language. + +See e.g. section `### List of English terms and their preferred German translations` in `docs/de/llm-prompt.md`. + +//// diff --git a/docs/en/docs/about/index.md b/docs/en/docs/about/index.md new file mode 100644 index 0000000000000..d178dfec75b23 --- /dev/null +++ b/docs/en/docs/about/index.md @@ -0,0 +1,3 @@ +# About { #about } + +About FastAPI, its design, inspiration and more. 🤓 diff --git a/docs/en/docs/advanced/additional-responses.md b/docs/en/docs/advanced/additional-responses.md new file mode 100644 index 0000000000000..494143b07acca --- /dev/null +++ b/docs/en/docs/advanced/additional-responses.md @@ -0,0 +1,247 @@ +# Additional Responses in OpenAPI { #additional-responses-in-openapi } + +/// warning + +This is a rather advanced topic. + +If you are starting with **FastAPI**, you might not need this. + +/// + +You can declare additional responses, with additional status codes, media types, descriptions, etc. + +Those additional responses will be included in the OpenAPI schema, so they will also appear in the API docs. + +But for those additional responses you have to make sure you return a `Response` like `JSONResponse` directly, with your status code and content. + +## Additional Response with `model` { #additional-response-with-model } + +You can pass to your *path operation decorators* a parameter `responses`. + +It receives a `dict`: the keys are status codes for each response (like `200`), and the values are other `dict`s with the information for each of them. + +Each of those response `dict`s can have a key `model`, containing a Pydantic model, just like `response_model`. + +**FastAPI** will take that model, generate its JSON Schema and include it in the correct place in OpenAPI. + +For example, to declare another response with a status code `404` and a Pydantic model `Message`, you can write: + +{* ../../docs_src/additional_responses/tutorial001_py310.py hl[18,22] *} + +/// note + +Keep in mind that you have to return the `JSONResponse` directly. + +/// + +/// note + +The `model` key is not part of OpenAPI. + +**FastAPI** will take the Pydantic model from there, generate the JSON Schema, and put it in the correct place. + +The correct place is: + +* In the key `content`, that has as value another JSON object (`dict`) that contains: + * A key with the media type, e.g. `application/json`, that contains as value another JSON object, that contains: + * A key `schema`, that has as the value the JSON Schema from the model, here's the correct place. + * **FastAPI** adds a reference here to the global JSON Schemas in another place in your OpenAPI instead of including it directly. This way, other applications and clients can use those JSON Schemas directly, provide better code generation tools, etc. + +/// + +The generated responses in the OpenAPI for this *path operation* will be: + +```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" + } + } + } + } + } +} +``` + +The schemas are referenced to another place inside the OpenAPI schema: + +```JSON hl_lines="4-16" +{ + "components": { + "schemas": { + "Message": { + "title": "Message", + "required": [ + "message" + ], + "type": "object", + "properties": { + "message": { + "title": "Message", + "type": "string" + } + } + }, + "Item": { + "title": "Item", + "required": [ + "id", + "value" + ], + "type": "object", + "properties": { + "id": { + "title": "Id", + "type": "string" + }, + "value": { + "title": "Value", + "type": "string" + } + } + }, + "ValidationError": { + "title": "ValidationError", + "required": [ + "loc", + "msg", + "type" + ], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "type": "string" + } + }, + "msg": { + "title": "Message", + "type": "string" + }, + "type": { + "title": "Error Type", + "type": "string" + } + } + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + } + } + } + } + } + } +} +``` + +## Additional media types for the main response { #additional-media-types-for-the-main-response } + +You can use this same `responses` parameter to add different media types for the same main response. + +For example, you can add an additional media type of `image/png`, declaring that your *path operation* can return a JSON object (with media type `application/json`) or a PNG image: + +{* ../../docs_src/additional_responses/tutorial002_py310.py hl[17:22,26] *} + +/// note + +Notice that you have to return the image using a `FileResponse` directly. + +/// + +/// note + +Unless you specify a different media type explicitly in your `responses` parameter, FastAPI will assume the response has the same media type as the main response class (default `application/json`). + +But if you have specified a custom response class with `None` as its media type, FastAPI will use `application/json` for any additional response that has an associated model. + +/// + +## Combining information { #combining-information } + +You can also combine response information from multiple places, including the `response_model`, `status_code`, and `responses` parameters. + +You can declare a `response_model`, using the default status code `200` (or a custom one if you need), and then declare additional information for that same response in `responses`, directly in the OpenAPI schema. + +**FastAPI** will keep the additional information from `responses`, and combine it with the JSON Schema from your model. + +For example, you can declare a response with a status code `404` that uses a Pydantic model and has a custom `description`. + +And a response with a status code `200` that uses your `response_model`, but includes a custom `example`: + +{* ../../docs_src/additional_responses/tutorial003_py310.py hl[20:31] *} + +It will all be combined and included in your OpenAPI, and shown in the API docs: + + + +## Combine predefined responses and custom ones { #combine-predefined-responses-and-custom-ones } + +You might want to have some predefined responses that apply to many *path operations*, but you want to combine them with custom responses needed by each *path operation*. + +For those cases, you can use the Python technique of "unpacking" a `dict` with `**dict_to_unpack`: + +```Python +old_dict = { + "old key": "old value", + "second old key": "second old value", +} +new_dict = {**old_dict, "new key": "new value"} +``` + +Here, `new_dict` will contain all the key-value pairs from `old_dict` plus the new key-value pair: + +```Python +{ + "old key": "old value", + "second old key": "second old value", + "new key": "new value", +} +``` + +You can use that technique to reuse some predefined responses in your *path operations* and combine them with additional custom ones. + +For example: + +{* ../../docs_src/additional_responses/tutorial004_py310.py hl[11:15,24] *} + +## More information about OpenAPI responses { #more-information-about-openapi-responses } + +To see what exactly you can include in the responses, you can check these sections in the OpenAPI specification: + +* [OpenAPI Responses Object](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#responses-object), it includes the `Response Object`. +* [OpenAPI Response Object](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#response-object), you can include anything from this directly in each response inside your `responses` parameter. Including `description`, `headers`, `content` (inside of this is that you declare different media types and JSON Schemas), and `links`. diff --git a/docs/en/docs/advanced/additional-status-codes.md b/docs/en/docs/advanced/additional-status-codes.md new file mode 100644 index 0000000000000..c4f1bf3896482 --- /dev/null +++ b/docs/en/docs/advanced/additional-status-codes.md @@ -0,0 +1,41 @@ +# Additional Status Codes { #additional-status-codes } + +By default, **FastAPI** will return the responses using a `JSONResponse`, putting the content you return from your *path operation* inside of that `JSONResponse`. + +It will use the default status code or the one you set in your *path operation*. + +## Additional status codes { #additional-status-codes_1 } + +If you want to return additional status codes apart from the main one, you can do that by returning a `Response` directly, like a `JSONResponse`, and set the additional status code directly. + +For example, let's say that you want to have a *path operation* that allows updating items, and returns HTTP status codes of 200 "OK" when successful. + +But you also want it to accept new items. And when the items didn't exist before, it creates them, and returns an HTTP status code of 201 "Created". + +To achieve that, import `JSONResponse`, and return your content there directly, setting the `status_code` that you want: + +{* ../../docs_src/additional_status_codes/tutorial001_an_py310.py hl[4,25] *} + +/// warning + +When you return a `Response` directly, like in the example above, it will be returned directly. + +It won't be serialized with a model, etc. + +Make sure it has the data you want it to have, and that the values are valid JSON (if you are using `JSONResponse`). + +/// + +/// note | Technical Details + +You could also use `from starlette.responses import JSONResponse`. + +**FastAPI** provides the same `starlette.responses` as `fastapi.responses` just as a convenience for you, the developer. But most of the available responses come directly from Starlette. The same with `status`. + +/// + +## OpenAPI and API docs { #openapi-and-api-docs } + +If you return additional status codes and responses directly, they won't be included in the OpenAPI schema (the API docs), because FastAPI doesn't have a way to know beforehand what you are going to return. + +But you can document that in your code, using: [Additional Responses](additional-responses.md). diff --git a/docs/en/docs/advanced/advanced-dependencies.md b/docs/en/docs/advanced/advanced-dependencies.md new file mode 100644 index 0000000000000..e039788aeded7 --- /dev/null +++ b/docs/en/docs/advanced/advanced-dependencies.md @@ -0,0 +1,163 @@ +# Advanced Dependencies { #advanced-dependencies } + +## Parameterized dependencies { #parameterized-dependencies } + +All the dependencies we have seen are a fixed function or class. + +But there could be cases where you want to be able to set parameters on the dependency, without having to declare many different functions or classes. + +Let's imagine that we want to have a dependency that checks if the query parameter `q` contains some fixed content. + +But we want to be able to parameterize that fixed content. + +## A "callable" instance { #a-callable-instance } + +In Python there's a way to make an instance of a class a "callable". + +Not the class itself (which is already a callable), but an instance of that class. + +To do that, we declare a method `__call__`: + +{* ../../docs_src/dependencies/tutorial011_an_py310.py hl[12] *} + +In this case, this `__call__` is what **FastAPI** will use to check for additional parameters and sub-dependencies, and this is what will be called to pass a value to the parameter in your *path operation function* later. + +## Parameterize the instance { #parameterize-the-instance } + +And now, we can use `__init__` to declare the parameters of the instance that we can use to "parameterize" the dependency: + +{* ../../docs_src/dependencies/tutorial011_an_py310.py hl[9] *} + +In this case, **FastAPI** won't ever touch or care about `__init__`, we will use it directly in our code. + +## Create an instance { #create-an-instance } + +We could create an instance of this class with: + +{* ../../docs_src/dependencies/tutorial011_an_py310.py hl[18] *} + +And that way we are able to "parameterize" our dependency, that now has `"bar"` inside of it, as the attribute `checker.fixed_content`. + +## Use the instance as a dependency { #use-the-instance-as-a-dependency } + +Then, we could use this `checker` in a `Depends(checker)`, instead of `Depends(FixedContentQueryChecker)`, because the dependency is the instance, `checker`, not the class itself. + +And when solving the dependency, **FastAPI** will call this `checker` like: + +```Python +checker(q="somequery") +``` + +...and pass whatever that returns as the value of the dependency in our *path operation function* as the parameter `fixed_content_included`: + +{* ../../docs_src/dependencies/tutorial011_an_py310.py hl[22] *} + +/// tip + +All this might seem contrived. And it might not be very clear how it is useful yet. + +These examples are intentionally simple, but show how it all works. + +In the chapters about security, there are utility functions that are implemented in this same way. + +If you understood all this, you already know how those utility tools for security work underneath. + +/// + +## Dependencies with `yield`, `HTTPException`, `except` and Background Tasks { #dependencies-with-yield-httpexception-except-and-background-tasks } + +/// warning + +You most probably don't need these technical details. + +These details are useful mainly if you had a FastAPI application older than 0.121.0 and you are facing issues with dependencies with `yield`. + +/// + +Dependencies with `yield` have evolved over time to account for the different use cases and to fix some issues, here's a summary of what has changed. + +### Dependencies with `yield` and `scope` { #dependencies-with-yield-and-scope } + +In version 0.121.0, FastAPI added support for `Depends(scope="function")` for dependencies with `yield`. + +Using `Depends(scope="function")`, the exit code after `yield` is executed right after the *path operation function* is finished, before the response is sent back to the client. + +And when using `Depends(scope="request")` (the default), the exit code after `yield` is executed after the response is sent. + +You can read more about it in the docs for [Dependencies with `yield` - Early exit and `scope`](../tutorial/dependencies/dependencies-with-yield.md#early-exit-and-scope). + +### Dependencies with `yield` and `StreamingResponse`, Technical Details { #dependencies-with-yield-and-streamingresponse-technical-details } + +Before FastAPI 0.118.0, if you used a dependency with `yield`, it would run the exit code after the *path operation function* returned but right before sending the response. + +The intention was to avoid holding resources for longer than necessary, waiting for the response to travel through the network. + +This change also meant that if you returned a `StreamingResponse`, the exit code of the dependency with `yield` would have been already run. + +For example, if you had a database session in a dependency with `yield`, the `StreamingResponse` would not be able to use that session while streaming data because the session would have already been closed in the exit code after `yield`. + +This behavior was reverted in 0.118.0, to make the exit code after `yield` be executed after the response is sent. + +/// note + +As you will see below, this is very similar to the behavior before version 0.106.0, but with several improvements and bug fixes for corner cases. + +/// + +#### Use Cases with Early Exit Code { #use-cases-with-early-exit-code } + +There are some use cases with specific conditions that could benefit from the old behavior of running the exit code of dependencies with `yield` before sending the response. + +For example, imagine you have code that uses a database session in a dependency with `yield` only to verify a user, but the database session is never used again in the *path operation function*, only in the dependency, **and** the response takes a long time to be sent, like a `StreamingResponse` that sends data slowly, but for some reason doesn't use the database. + +In this case, the database session would be held until the response is finished being sent, but if you don't use it, then it wouldn't be necessary to hold it. + +Here's how it could look: + +{* ../../docs_src/dependencies/tutorial013_an_py310.py *} + +The exit code, the automatic closing of the `Session` in: + +{* ../../docs_src/dependencies/tutorial013_an_py310.py ln[19:21] *} + +...would be run after the response finishes sending the slow data: + +{* ../../docs_src/dependencies/tutorial013_an_py310.py ln[30:38] hl[31:33] *} + +But as `generate_stream()` doesn't use the database session, it is not really necessary to keep the session open while sending the response. + +If you have this specific use case using SQLModel (or SQLAlchemy), you could explicitly close the session after you don't need it anymore: + +{* ../../docs_src/dependencies/tutorial014_an_py310.py ln[24:28] hl[28] *} + +That way the session would release the database connection, so other requests could use it. + +If you have a different use case that needs to exit early from a dependency with `yield`, please create a [GitHub Discussion Question](https://github.com/fastapi/fastapi/discussions/new?category=questions) with your specific use case and why you would benefit from having early closing for dependencies with `yield`. + +If there are compelling use cases for early closing in dependencies with `yield`, I would consider adding a new way to opt in to early closing. + +### Dependencies with `yield` and `except`, Technical Details { #dependencies-with-yield-and-except-technical-details } + +Before FastAPI 0.110.0, if you used a dependency with `yield`, and then you captured an exception with `except` in that dependency, and you didn't raise the exception again, the exception would be automatically raised/forwarded to any exception handlers or the internal server error handler. + +This was changed in version 0.110.0 to fix unhandled memory consumption from forwarded exceptions without a handler (internal server errors), and to make it consistent with the behavior of regular Python code. + +### Background Tasks and Dependencies with `yield`, Technical Details { #background-tasks-and-dependencies-with-yield-technical-details } + +Before FastAPI 0.106.0, raising exceptions after `yield` was not possible, the exit code in dependencies with `yield` was executed *after* the response was sent, so [Exception Handlers](../tutorial/handling-errors.md#install-custom-exception-handlers) would have already run. + +This was designed this way mainly to allow using the same objects "yielded" by dependencies inside of background tasks, because the exit code would be executed after the background tasks were finished. + +This was changed in FastAPI 0.106.0 with the intention to not hold resources while waiting for the response to travel through the network. + +/// tip + +Additionally, a background task is normally an independent set of logic that should be handled separately, with its own resources (e.g. its own database connection). + +So, this way you will probably have cleaner code. + +/// + +If you used to rely on this behavior, now you should create the resources for background tasks inside the background task itself, and use internally only data that doesn't depend on the resources of dependencies with `yield`. + +For example, instead of using the same database session, you would create a new database session inside of the background task, and you would obtain the objects from the database using this new session. And then instead of passing the object from the database as a parameter to the background task function, you would pass the ID of that object and then obtain the object again inside the background task function. diff --git a/docs/en/docs/advanced/advanced-python-types.md b/docs/en/docs/advanced/advanced-python-types.md new file mode 100644 index 0000000000000..6495cbe443238 --- /dev/null +++ b/docs/en/docs/advanced/advanced-python-types.md @@ -0,0 +1,61 @@ +# Advanced Python Types { #advanced-python-types } + +Here are some additional ideas that might be useful when working with Python types. + +## Using `Union` or `Optional` { #using-union-or-optional } + +If your code for some reason can't use `|`, for example if it's not in a type annotation but in something like `response_model=`, instead of using the vertical bar (`|`) you can use `Union` from `typing`. + +For example, you could declare that something could be a `str` or `None`: + +```python +from typing import Union + + +def say_hi(name: Union[str, None]): + print(f"Hi {name}!") +``` + +`typing` also has a shortcut to declare that something could be `None`, with `Optional`. + +Here's a tip from my very **subjective** point of view: + +* 🚨 Avoid using `Optional[SomeType]` +* Instead ✨ **use `Union[SomeType, None]`** ✨. + +Both are equivalent and underneath they are the same, but I would recommend `Union` instead of `Optional` because the word "**optional**" would seem to imply that the value is optional, and it actually means "it can be `None`", even if it's not optional and is still required. + +I think `Union[SomeType, None]` is more explicit about what it means. + +It's just about the words and names. But those words can affect how you and your teammates think about the code. + +As an example, let's take this function: + +```python +from typing import Optional + + +def say_hi(name: Optional[str]): + print(f"Hey {name}!") +``` + +The parameter `name` is defined as `Optional[str]`, but it is **not optional**, you cannot call the function without the parameter: + +```Python +say_hi() # Oh, no, this throws an error! 😱 +``` + +The `name` parameter is **still required** (not *optional*) because it doesn't have a default value. Still, `name` accepts `None` as the value: + +```Python +say_hi(name=None) # This works, None is valid 🎉 +``` + +The good news is, in most cases, you will be able to simply use `|` to define unions of types: + +```python +def say_hi(name: str | None): + print(f"Hey {name}!") +``` + +So, normally you don't have to worry about names like `Optional` and `Union`. 😎 diff --git a/docs/en/docs/advanced/async-tests.md b/docs/en/docs/advanced/async-tests.md new file mode 100644 index 0000000000000..c7ec5e9e2905f --- /dev/null +++ b/docs/en/docs/advanced/async-tests.md @@ -0,0 +1,99 @@ +# Async Tests { #async-tests } + +You have already seen how to test your **FastAPI** applications using the provided `TestClient`. Up to now, you have only seen how to write synchronous tests, without using `async` functions. + +Being able to use asynchronous functions in your tests could be useful, for example, when you're querying your database asynchronously. Imagine you want to test sending requests to your FastAPI application and then verify that your backend successfully wrote the correct data in the database, while using an async database library. + +Let's look at how we can make that work. + +## pytest.mark.anyio { #pytest-mark-anyio } + +If we want to call asynchronous functions in our tests, our test functions have to be asynchronous. AnyIO provides a neat plugin for this, that allows us to specify that some test functions are to be called asynchronously. + +## HTTPX { #httpx } + +Even if your **FastAPI** application uses normal `def` functions instead of `async def`, it is still an `async` application underneath. + +The `TestClient` does some magic inside to call the asynchronous FastAPI application in your normal `def` test functions, using standard pytest. But that magic doesn't work anymore when we're using it inside asynchronous functions. By running our tests asynchronously, we can no longer use the `TestClient` inside our test functions. + +The `TestClient` is based on [HTTPX](https://www.python-httpx.org), and luckily, we can use it directly to test the API. + +## Example { #example } + +For a simple example, let's consider a file structure similar to the one described in [Bigger Applications](../tutorial/bigger-applications.md) and [Testing](../tutorial/testing.md): + +``` +. +├── app +│   ├── __init__.py +│   ├── main.py +│   └── test_main.py +``` + +The file `main.py` would have: + +{* ../../docs_src/async_tests/app_a_py310/main.py *} + +The file `test_main.py` would have the tests for `main.py`, it could look like this now: + +{* ../../docs_src/async_tests/app_a_py310/test_main.py *} + +## Run it { #run-it } + +You can run your tests as usual via: + +
+ +```console +$ pytest + +---> 100% +``` + +
+ +## In Detail { #in-detail } + +The marker `@pytest.mark.anyio` tells pytest that this test function should be called asynchronously: + +{* ../../docs_src/async_tests/app_a_py310/test_main.py hl[7] *} + +/// tip + +Note that the test function is now `async def` instead of just `def` as before when using the `TestClient`. + +/// + +Then we can create an `AsyncClient` with the app, and send async requests to it, using `await`. + +{* ../../docs_src/async_tests/app_a_py310/test_main.py hl[9:12] *} + +This is the equivalent to: + +```Python +response = client.get('/') +``` + +...that we used to make our requests with the `TestClient`. + +/// tip + +Note that we're using async/await with the new `AsyncClient` - the request is asynchronous. + +/// + +/// warning + +If your application relies on lifespan events, the `AsyncClient` won't trigger these events. To ensure they are triggered, use `LifespanManager` from [florimondmanca/asgi-lifespan](https://github.com/florimondmanca/asgi-lifespan#usage). + +/// + +## Other Asynchronous Function Calls { #other-asynchronous-function-calls } + +As the testing function is now asynchronous, you can now also call (and `await`) other `async` functions apart from sending requests to your FastAPI application in your tests, exactly as you would call them anywhere else in your code. + +/// tip + +If you encounter a `RuntimeError: Task attached to a different loop` when integrating asynchronous function calls in your tests (e.g. when using [MongoDB's MotorClient](https://stackoverflow.com/questions/41584243/runtimeerror-task-attached-to-a-different-loop)), remember to instantiate objects that need an event loop only within async functions, e.g. an `@app.on_event("startup")` callback. + +/// diff --git a/docs/en/docs/advanced/behind-a-proxy.md b/docs/en/docs/advanced/behind-a-proxy.md new file mode 100644 index 0000000000000..c413fccdfe152 --- /dev/null +++ b/docs/en/docs/advanced/behind-a-proxy.md @@ -0,0 +1,466 @@ +# Behind a Proxy { #behind-a-proxy } + +In many situations, you would use a **proxy** like Traefik or Nginx in front of your FastAPI app. + +These proxies could handle HTTPS certificates and other things. + +## Proxy Forwarded Headers { #proxy-forwarded-headers } + +A **proxy** in front of your application would normally set some headers on the fly before sending the requests to your **server** to let the server know that the request was **forwarded** by the proxy, letting it know the original (public) URL, including the domain, that it is using HTTPS, etc. + +The **server** program (for example **Uvicorn** via **FastAPI CLI**) is capable of interpreting these headers, and then passing that information to your application. + +But for security, as the server doesn't know it is behind a trusted proxy, it won't interpret those headers. + +/// note | Technical Details + +The proxy headers are: + +* [X-Forwarded-For](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Forwarded-For) +* [X-Forwarded-Proto](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Forwarded-Proto) +* [X-Forwarded-Host](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Forwarded-Host) + +/// + +### Enable Proxy Forwarded Headers { #enable-proxy-forwarded-headers } + +You can start FastAPI CLI with the *CLI Option* `--forwarded-allow-ips` and pass the IP addresses that should be trusted to read those forwarded headers. + +If you set it to `--forwarded-allow-ips="*"` it would trust all the incoming IPs. + +If your **server** is behind a trusted **proxy** and only the proxy talks to it, this would make it accept whatever is the IP of that **proxy**. + +
+ +```console +$ fastapi run --forwarded-allow-ips="*" + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +### Redirects with HTTPS { #redirects-with-https } + +For example, let's say you define a *path operation* `/items/`: + +{* ../../docs_src/behind_a_proxy/tutorial001_01_py310.py hl[6] *} + +If the client tries to go to `/items`, by default, it would be redirected to `/items/`. + +But before setting the *CLI Option* `--forwarded-allow-ips` it could redirect to `http://localhost:8000/items/`. + +But maybe your application is hosted at `https://mysuperapp.com`, and the redirection should be to `https://mysuperapp.com/items/`. + +By setting `--proxy-headers` now FastAPI would be able to redirect to the right location. 😎 + +``` +https://mysuperapp.com/items/ +``` + +/// tip + +If you want to learn more about HTTPS, check the guide [About HTTPS](../deployment/https.md). + +/// + +### How Proxy Forwarded Headers Work { #how-proxy-forwarded-headers-work } + +Here's a visual representation of how the **proxy** adds forwarded headers between the client and the **application server**: + +```mermaid +sequenceDiagram + participant Client + participant Proxy as Proxy/Load Balancer + participant Server as FastAPI Server + + Client->>Proxy: HTTPS Request
Host: mysuperapp.com
Path: /items + + Note over Proxy: Proxy adds forwarded headers + + Proxy->>Server: HTTP Request
X-Forwarded-For: [client IP]
X-Forwarded-Proto: https
X-Forwarded-Host: mysuperapp.com
Path: /items + + Note over Server: Server interprets headers
(if --forwarded-allow-ips is set) + + Server->>Proxy: HTTP Response
with correct HTTPS URLs + + Proxy->>Client: HTTPS Response +``` + +The **proxy** intercepts the original client request and adds the special *forwarded* headers (`X-Forwarded-*`) before passing the request to the **application server**. + +These headers preserve information about the original request that would otherwise be lost: + +* **X-Forwarded-For**: The original client's IP address +* **X-Forwarded-Proto**: The original protocol (`https`) +* **X-Forwarded-Host**: The original host (`mysuperapp.com`) + +When **FastAPI CLI** is configured with `--forwarded-allow-ips`, it trusts these headers and uses them, for example to generate the correct URLs in redirects. + +## Proxy with a stripped path prefix { #proxy-with-a-stripped-path-prefix } + +You could have a proxy that adds a path prefix to your application. + +In these cases you can use `root_path` to configure your application. + +The `root_path` is a mechanism provided by the ASGI specification (that FastAPI is built on, through Starlette). + +The `root_path` is used to handle these specific cases. + +And it's also used internally when mounting sub-applications. + +Having a proxy with a stripped path prefix, in this case, means that you could declare a path at `/app` in your code, but then, you add a layer on top (the proxy) that would put your **FastAPI** application under a path like `/api/v1`. + +In this case, the original path `/app` would actually be served at `/api/v1/app`. + +Even though all your code is written assuming there's just `/app`. + +{* ../../docs_src/behind_a_proxy/tutorial001_py310.py hl[6] *} + +And the proxy would be **"stripping"** the **path prefix** on the fly before transmitting the request to the app server (probably Uvicorn via FastAPI CLI), keeping your application convinced that it is being served at `/app`, so that you don't have to update all your code to include the prefix `/api/v1`. + +Up to here, everything would work as normally. + +But then, when you open the integrated docs UI (the frontend), it would expect to get the OpenAPI schema at `/openapi.json`, instead of `/api/v1/openapi.json`. + +So, the frontend (that runs in the browser) would try to reach `/openapi.json` and wouldn't be able to get the OpenAPI schema. + +Because we have a proxy with a path prefix of `/api/v1` for our app, the frontend needs to fetch the OpenAPI schema at `/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 + +The IP `0.0.0.0` is commonly used to mean that the program listens on all the IPs available in that machine/server. + +/// + +The docs UI would also need the OpenAPI schema to declare that this API `server` is located at `/api/v1` (behind the proxy). For example: + +```JSON hl_lines="4-8" +{ + "openapi": "3.1.0", + // More stuff here + "servers": [ + { + "url": "/api/v1" + } + ], + "paths": { + // More stuff here + } +} +``` + +In this example, the "Proxy" could be something like **Traefik**. And the server would be something like FastAPI CLI with **Uvicorn**, running your FastAPI application. + +### Providing the `root_path` { #providing-the-root-path } + +To achieve this, you can use the command line option `--root-path` like: + +
+ +```console +$ fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1 + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +If you use Hypercorn, it also has the option `--root-path`. + +/// note | Technical Details + +The ASGI specification defines a `root_path` for this use case. + +And the `--root-path` command line option provides that `root_path`. + +/// + +### Checking the current `root_path` { #checking-the-current-root-path } + +You can get the current `root_path` used by your application for each request, it is part of the `scope` dictionary (that's part of the ASGI spec). + +Here we are including it in the message just for demonstration purposes. + +{* ../../docs_src/behind_a_proxy/tutorial001_py310.py hl[8] *} + +Then, if you start Uvicorn with: + +
+ +```console +$ fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1 + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +The response would be something like: + +```JSON +{ + "message": "Hello World", + "root_path": "/api/v1" +} +``` + +### Setting the `root_path` in the FastAPI app { #setting-the-root-path-in-the-fastapi-app } + +Alternatively, if you don't have a way to provide a command line option like `--root-path` or equivalent, you can set the `root_path` parameter when creating your FastAPI app: + +{* ../../docs_src/behind_a_proxy/tutorial002_py310.py hl[3] *} + +Passing the `root_path` to `FastAPI` would be the equivalent of passing the `--root-path` command line option to Uvicorn or Hypercorn. + +### About `root_path` { #about-root-path } + +Keep in mind that the server (Uvicorn) won't use that `root_path` for anything else than passing it to the app. + +But if you go with your browser to [http://127.0.0.1:8000/app](http://127.0.0.1:8000/app) you will see the normal response: + +```JSON +{ + "message": "Hello World", + "root_path": "/api/v1" +} +``` + +So, it won't expect to be accessed at `http://127.0.0.1:8000/api/v1/app`. + +Uvicorn will expect the proxy to access Uvicorn at `http://127.0.0.1:8000/app`, and then it would be the proxy's responsibility to add the extra `/api/v1` prefix on top. + +## About proxies with a stripped path prefix { #about-proxies-with-a-stripped-path-prefix } + +Keep in mind that a proxy with stripped path prefix is only one of the ways to configure it. + +Probably in many cases the default will be that the proxy doesn't have a stripped path prefix. + +In a case like that (without a stripped path prefix), the proxy would listen on something like `https://myawesomeapp.com`, and then if the browser goes to `https://myawesomeapp.com/api/v1/app` and your server (e.g. Uvicorn) listens on `http://127.0.0.1:8000` the proxy (without a stripped path prefix) would access Uvicorn at the same path: `http://127.0.0.1:8000/api/v1/app`. + +## Testing locally with Traefik { #testing-locally-with-traefik } + +You can easily run the experiment locally with a stripped path prefix using [Traefik](https://docs.traefik.io/). + +[Download Traefik](https://github.com/containous/traefik/releases), it's a single binary, you can extract the compressed file and run it directly from the terminal. + +Then create a file `traefik.toml` with: + +```TOML hl_lines="3" +[entryPoints] + [entryPoints.http] + address = ":9999" + +[providers] + [providers.file] + filename = "routes.toml" +``` + +This tells Traefik to listen on port 9999 and to use another file `routes.toml`. + +/// tip + +We are using port 9999 instead of the standard HTTP port 80 so that you don't have to run it with admin (`sudo`) privileges. + +/// + +Now create that other file `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" +``` + +This file configures Traefik to use the path prefix `/api/v1`. + +And then Traefik will redirect its requests to your Uvicorn running on `http://127.0.0.1:8000`. + +Now start Traefik: + +
+ +```console +$ ./traefik --configFile=traefik.toml + +INFO[0000] Configuration loaded from file: /home/user/awesomeapi/traefik.toml +``` + +
+ +And now start your app, using the `--root-path` option: + +
+ +```console +$ fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1 + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +### Check the responses { #check-the-responses } + +Now, if you go to the URL with the port for Uvicorn: [http://127.0.0.1:8000/app](http://127.0.0.1:8000/app), you will see the normal response: + +```JSON +{ + "message": "Hello World", + "root_path": "/api/v1" +} +``` + +/// tip + +Notice that even though you are accessing it at `http://127.0.0.1:8000/app` it shows the `root_path` of `/api/v1`, taken from the option `--root-path`. + +/// + +And now open the URL with the port for Traefik, including the path prefix: [http://127.0.0.1:9999/api/v1/app](http://127.0.0.1:9999/api/v1/app). + +We get the same response: + +```JSON +{ + "message": "Hello World", + "root_path": "/api/v1" +} +``` + +but this time at the URL with the prefix path provided by the proxy: `/api/v1`. + +Of course, the idea here is that everyone would access the app through the proxy, so the version with the path prefix `/api/v1` is the "correct" one. + +And the version without the path prefix (`http://127.0.0.1:8000/app`), provided by Uvicorn directly, would be exclusively for the _proxy_ (Traefik) to access it. + +That demonstrates how the Proxy (Traefik) uses the path prefix and how the server (Uvicorn) uses the `root_path` from the option `--root-path`. + +### Check the docs UI { #check-the-docs-ui } + +But here's the fun part. ✨ + +The "official" way to access the app would be through the proxy with the path prefix that we defined. So, as we would expect, if you try the docs UI served by Uvicorn directly, without the path prefix in the URL, it won't work, because it expects to be accessed through the proxy. + +You can check it at [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs): + + + +But if we access the docs UI at the "official" URL using the proxy with port `9999`, at `/api/v1/docs`, it works correctly! 🎉 + +You can check it at [http://127.0.0.1:9999/api/v1/docs](http://127.0.0.1:9999/api/v1/docs): + + + +Right as we wanted it. ✔️ + +This is because FastAPI uses this `root_path` to create the default `server` in OpenAPI with the URL provided by `root_path`. + +## Additional servers { #additional-servers } + +/// warning + +This is a more advanced use case. Feel free to skip it. + +/// + +By default, **FastAPI** will create a `server` in the OpenAPI schema with the URL for the `root_path`. + +But you can also provide other alternative `servers`, for example if you want *the same* docs UI to interact with both a staging and a production environment. + +If you pass a custom list of `servers` and there's a `root_path` (because your API lives behind a proxy), **FastAPI** will insert a "server" with this `root_path` at the beginning of the list. + +For example: + +{* ../../docs_src/behind_a_proxy/tutorial003_py310.py hl[4:7] *} + +Will generate an OpenAPI schema like: + +```JSON hl_lines="5-7" +{ + "openapi": "3.1.0", + // More stuff here + "servers": [ + { + "url": "/api/v1" + }, + { + "url": "https://stag.example.com", + "description": "Staging environment" + }, + { + "url": "https://prod.example.com", + "description": "Production environment" + } + ], + "paths": { + // More stuff here + } +} +``` + +/// tip + +Notice the auto-generated server with a `url` value of `/api/v1`, taken from the `root_path`. + +/// + +In the docs UI at [http://127.0.0.1:9999/api/v1/docs](http://127.0.0.1:9999/api/v1/docs) it would look like: + + + +/// tip + +The docs UI will interact with the server that you select. + +/// + +/// note | Technical Details + +The `servers` property in the OpenAPI specification is optional. + +If you don't specify the `servers` parameter and `root_path` is equal to `/`, the `servers` property in the generated OpenAPI schema will be omitted entirely by default, which is the equivalent of a single server with a `url` value of `/`. + +/// + +### Disable automatic server from `root_path` { #disable-automatic-server-from-root-path } + +If you don't want **FastAPI** to include an automatic server using the `root_path`, you can use the parameter `root_path_in_servers=False`: + +{* ../../docs_src/behind_a_proxy/tutorial004_py310.py hl[9] *} + +and then it won't include it in the OpenAPI schema. + +## Mounting a sub-application { #mounting-a-sub-application } + +If you need to mount a sub-application (as described in [Sub Applications - Mounts](sub-applications.md)) while also using a proxy with `root_path`, you can do it normally, as you would expect. + +FastAPI will internally use the `root_path` smartly, so it will just work. ✨ diff --git a/docs/en/docs/advanced/custom-response.md b/docs/en/docs/advanced/custom-response.md new file mode 100644 index 0000000000000..016868fe70b36 --- /dev/null +++ b/docs/en/docs/advanced/custom-response.md @@ -0,0 +1,273 @@ +# Custom Response - HTML, Stream, File, others { #custom-response-html-stream-file-others } + +By default, **FastAPI** will return JSON responses. + +You can override it by returning a `Response` directly as seen in [Return a Response directly](response-directly.md). + +But if you return a `Response` directly (or any subclass, like `JSONResponse`), the data won't be automatically converted (even if you declare a `response_model`), and the documentation won't be automatically generated (for example, including the specific "media type", in the HTTP header `Content-Type` as part of the generated OpenAPI). + +But you can also declare the `Response` that you want to be used (e.g. any `Response` subclass), in the *path operation decorator* using the `response_class` parameter. + +The contents that you return from your *path operation function* will be put inside of that `Response`. + +/// note + +If you use a response class with no media type, FastAPI will expect your response to have no content, so it will not document the response format in its generated OpenAPI docs. + +/// + +## JSON Responses { #json-responses } + +By default FastAPI returns JSON responses. + +If you declare a [Response Model](../tutorial/response-model.md) FastAPI will use it to serialize the data to JSON, using Pydantic. + +If you don't declare a response model, FastAPI will use the `jsonable_encoder` explained in [JSON Compatible Encoder](../tutorial/encoder.md) and put it in a `JSONResponse`. + +If you declare a `response_class` with a JSON media type (`application/json`), like is the case with the `JSONResponse`, the data you return will be automatically converted (and filtered) with any Pydantic `response_model` that you declared in the *path operation decorator*. But the data won't be serialized to JSON bytes with Pydantic, instead it will be converted with the `jsonable_encoder` and then passed to the `JSONResponse` class, which will serialize it to bytes using the standard JSON library in Python. + +### JSON Performance { #json-performance } + +In short, if you want the maximum performance, use a [Response Model](../tutorial/response-model.md) and don't declare a `response_class` in the *path operation decorator*. + +{* ../../docs_src/response_model/tutorial001_01_py310.py ln[15:17] hl[16] *} + +## HTML Response { #html-response } + +To return a response with HTML directly from **FastAPI**, use `HTMLResponse`. + +* Import `HTMLResponse`. +* Pass `HTMLResponse` as the parameter `response_class` of your *path operation decorator*. + +{* ../../docs_src/custom_response/tutorial002_py310.py hl[2,7] *} + +/// note + +The parameter `response_class` will also be used to define the "media type" of the response. + +In this case, the HTTP header `Content-Type` will be set to `text/html`. + +And it will be documented as such in OpenAPI. + +/// + +### Return a `Response` { #return-a-response } + +As seen in [Return a Response directly](response-directly.md), you can also override the response directly in your *path operation*, by returning it. + +The same example from above, returning an `HTMLResponse`, could look like: + +{* ../../docs_src/custom_response/tutorial003_py310.py hl[2,7,19] *} + +/// warning + +A `Response` returned directly by your *path operation function* won't be documented in OpenAPI (for example, the `Content-Type` won't be documented) and won't be visible in the automatic interactive docs. + +/// + +/// note + +Of course, the actual `Content-Type` header, status code, etc, will come from the `Response` object you returned. + +/// + +### Document in OpenAPI and override `Response` { #document-in-openapi-and-override-response } + +If you want to override the response from inside of the function but at the same time document the "media type" in OpenAPI, you can use the `response_class` parameter AND return a `Response` object. + +The `response_class` will then be used only to document the OpenAPI *path operation*, but your `Response` will be used as is. + +#### Return an `HTMLResponse` directly { #return-an-htmlresponse-directly } + +For example, it could be something like: + +{* ../../docs_src/custom_response/tutorial004_py310.py hl[7,21,23] *} + +In this example, the function `generate_html_response()` already generates and returns a `Response` instead of returning the HTML in a `str`. + +By returning the result of calling `generate_html_response()`, you are already returning a `Response` that will override the default **FastAPI** behavior. + +But as you passed the `HTMLResponse` in the `response_class` too, **FastAPI** will know how to document it in OpenAPI and the interactive docs as HTML with `text/html`: + + + +## Available responses { #available-responses } + +Here are some of the available responses. + +Keep in mind that you can use `Response` to return anything else, or even create a custom sub-class. + +/// note | Technical Details + +You could also use `from starlette.responses import HTMLResponse`. + +**FastAPI** provides the same `starlette.responses` as `fastapi.responses` just as a convenience for you, the developer. But most of the available responses come directly from Starlette. + +/// + +### `Response` { #response } + +The main `Response` class, all the other responses inherit from it. + +You can return it directly. + +It accepts the following parameters: + +* `content` - A `str` or `bytes`. +* `status_code` - An `int` HTTP status code. +* `headers` - A `dict` of strings. +* `media_type` - A `str` giving the media type. E.g. `"text/html"`. + +FastAPI (actually Starlette) will automatically include a Content-Length header. It will also include a Content-Type header, based on the `media_type` and appending a charset for text types. + +{* ../../docs_src/response_directly/tutorial002_py310.py hl[1,18] *} + +### `HTMLResponse` { #htmlresponse } + +Takes some text or bytes and returns an HTML response, as you read above. + +### `PlainTextResponse` { #plaintextresponse } + +Takes some text or bytes and returns a plain text response. + +{* ../../docs_src/custom_response/tutorial005_py310.py hl[2,7,9] *} + +### `JSONResponse` { #jsonresponse } + +Takes some data and returns an `application/json` encoded response. + +This is the default response used in **FastAPI**, as you read above. + +/// note | Technical Details + +But if you declare a response model or return type, that will be used directly to serialize the data to JSON, and a response with the right media type for JSON will be returned directly, without using the `JSONResponse` class. + +This is the ideal way to get the best performance. + +/// + +### `RedirectResponse` { #redirectresponse } + +Returns an HTTP redirect. Uses a 307 status code (Temporary Redirect) by default. + +You can return a `RedirectResponse` directly: + +{* ../../docs_src/custom_response/tutorial006_py310.py hl[2,9] *} + +--- + +Or you can use it in the `response_class` parameter: + + +{* ../../docs_src/custom_response/tutorial006b_py310.py hl[2,7,9] *} + +If you do that, then you can return the URL directly from your *path operation* function. + +In this case, the `status_code` used will be the default one for the `RedirectResponse`, which is `307`. + +--- + +You can also use the `status_code` parameter combined with the `response_class` parameter: + +{* ../../docs_src/custom_response/tutorial006c_py310.py hl[2,7,9] *} + +### `StreamingResponse` { #streamingresponse } + +Takes an async generator or a normal generator/iterator (a function with `yield`) and streams the response body. + +{* ../../docs_src/custom_response/tutorial007_py310.py hl[3,16] *} + +/// note | Technical Details + +An `async` task can only be cancelled when it reaches an `await`. If there is no `await`, the generator (function with `yield`) can not be cancelled properly and may keep running even after cancellation is requested. + +Since this small example does not need any `await` statements, we add an `await anyio.sleep(0)` to give the event loop a chance to handle cancellation. + +This would be even more important with large or infinite streams. + +/// + +/// tip + +Instead of returning a `StreamingResponse` directly, you should probably follow the style in [Stream Data](./stream-data.md), it's much more convenient and handles cancellation behind the scenes for you. + +If you are streaming JSON Lines, follow the [Stream JSON Lines](../tutorial/stream-json-lines.md) tutorial. + +/// + +### `FileResponse` { #fileresponse } + +Asynchronously streams a file as the response. + +Takes a different set of arguments to instantiate than the other response types: + +* `path` - The file path to the file to stream. +* `headers` - Any custom headers to include, as a dictionary. +* `media_type` - A string giving the media type. If unset, the filename or path will be used to infer a media type. +* `filename` - If set, this will be included in the response `Content-Disposition`. + +File responses will include appropriate `Content-Length`, `Last-Modified` and `ETag` headers. + +{* ../../docs_src/custom_response/tutorial009_py310.py hl[2,10] *} + +You can also use the `response_class` parameter: + +{* ../../docs_src/custom_response/tutorial009b_py310.py hl[2,8,10] *} + +In this case, you can return the file path directly from your *path operation* function. + +## Custom response class { #custom-response-class } + +You can create your own custom response class, inheriting from `Response` and using it. + +For example, let's say that you want to use [`orjson`](https://github.com/ijl/orjson) with some settings. + +Let's say you want it to return indented and formatted JSON, so you want to use the orjson option `orjson.OPT_INDENT_2`. + +You could create a `CustomORJSONResponse`. The main thing you have to do is create a `Response.render(content)` method that returns the content as `bytes`: + +{* ../../docs_src/custom_response/tutorial009c_py310.py hl[9:14,17] *} + +Now instead of returning: + +```json +{"message": "Hello World"} +``` + +...this response will return: + +```json +{ + "message": "Hello World" +} +``` + +Of course, you will probably find much better ways to take advantage of this than formatting JSON. 😉 + +### `orjson` or Response Model { #orjson-or-response-model } + +If what you are looking for is performance, you are probably better off using a [Response Model](../tutorial/response-model.md) than an `orjson` response. + +With a response model, FastAPI will use Pydantic to serialize the data to JSON, without using intermediate steps, like converting it with `jsonable_encoder`, which would happen in any other case. + +And under the hood, Pydantic uses the same underlying Rust mechanisms as `orjson` to serialize to JSON, so you will already get the best performance with a response model. + +## Default response class { #default-response-class } + +When creating a **FastAPI** class instance or an `APIRouter` you can specify which response class to use by default. + +The parameter that defines this is `default_response_class`. + +In the example below, **FastAPI** will use `HTMLResponse` by default, in all *path operations*, instead of JSON. + +{* ../../docs_src/custom_response/tutorial010_py310.py hl[2,4] *} + +/// tip + +You can still override `response_class` in *path operations* as before. + +/// + +## Additional documentation { #additional-documentation } + +You can also declare the media type and many other details in OpenAPI using `responses`: [Additional Responses in OpenAPI](additional-responses.md). diff --git a/docs/en/docs/advanced/dataclasses.md b/docs/en/docs/advanced/dataclasses.md new file mode 100644 index 0000000000000..fbabe0c872ad6 --- /dev/null +++ b/docs/en/docs/advanced/dataclasses.md @@ -0,0 +1,95 @@ +# Using Dataclasses { #using-dataclasses } + +FastAPI is built on top of **Pydantic**, and I have been showing you how to use Pydantic models to declare requests and responses. + +But FastAPI also supports using [`dataclasses`](https://docs.python.org/3/library/dataclasses.html) the same way: + +{* ../../docs_src/dataclasses_/tutorial001_py310.py hl[1,6:11,18:19] *} + +This is still supported thanks to **Pydantic**, as it has [internal support for `dataclasses`](https://docs.pydantic.dev/latest/concepts/dataclasses/#use-of-stdlib-dataclasses-with-basemodel). + +So, even with the code above that doesn't use Pydantic explicitly, FastAPI is using Pydantic to convert those standard dataclasses to Pydantic's own flavor of dataclasses. + +And of course, it supports the same: + +* data validation +* data serialization +* data documentation, etc. + +This works the same way as with Pydantic models. And it is actually achieved in the same way underneath, using Pydantic. + +/// note + +Keep in mind that dataclasses can't do everything Pydantic models can do. + +So, you might still need to use Pydantic models. + +But if you have a bunch of dataclasses lying around, this is a nice trick to use them to power a web API using FastAPI. 🤓 + +/// + +## Dataclasses in `response_model` { #dataclasses-in-response-model } + +You can also use `dataclasses` in the `response_model` parameter: + +{* ../../docs_src/dataclasses_/tutorial002_py310.py hl[1,6:12,18] *} + +The dataclass will be automatically converted to a Pydantic dataclass. + +This way, its schema will show up in the API docs user interface: + + + +## Dataclasses in Nested Data Structures { #dataclasses-in-nested-data-structures } + +You can also combine `dataclasses` with other type annotations to make nested data structures. + +In some cases, you might still have to use Pydantic's version of `dataclasses`. For example, if you have errors with the automatically generated API documentation. + +In that case, you can simply swap the standard `dataclasses` with `pydantic.dataclasses`, which is a drop-in replacement: + +{* ../../docs_src/dataclasses_/tutorial003_py310.py hl[1,4,7:10,13:16,22:24,27] *} + +1. We still import `field` from standard `dataclasses`. + +2. `pydantic.dataclasses` is a drop-in replacement for `dataclasses`. + +3. The `Author` dataclass includes a list of `Item` dataclasses. + +4. The `Author` dataclass is used as the `response_model` parameter. + +5. You can use other standard type annotations with dataclasses as the request body. + + In this case, it's a list of `Item` dataclasses. + +6. Here we are returning a dictionary that contains `items` which is a list of dataclasses. + + FastAPI is still capable of serializing the data to JSON. + +7. Here the `response_model` is using a type annotation of a list of `Author` dataclasses. + + Again, you can combine `dataclasses` with standard type annotations. + +8. Notice that this *path operation function* uses regular `def` instead of `async def`. + + As always, in FastAPI you can combine `def` and `async def` as needed. + + If you need a refresher about when to use which, check out the section _"In a hurry?"_ in the docs about [`async` and `await`](../async.md#in-a-hurry). + +9. This *path operation function* is not returning dataclasses (although it could), but a list of dictionaries with internal data. + + FastAPI will use the `response_model` parameter (that includes dataclasses) to convert the response. + +You can combine `dataclasses` with other type annotations in many different combinations to form complex data structures. + +Check the in-code annotation tips above to see more specific details. + +## Learn More { #learn-more } + +You can also combine `dataclasses` with other Pydantic models, inherit from them, include them in your own models, etc. + +To learn more, check the [Pydantic docs about dataclasses](https://docs.pydantic.dev/latest/concepts/dataclasses/). + +## Version { #version } + +This is available since FastAPI version `0.67.0`. 🔖 diff --git a/docs/en/docs/advanced/events.md b/docs/en/docs/advanced/events.md new file mode 100644 index 0000000000000..8f8cdb0176f4d --- /dev/null +++ b/docs/en/docs/advanced/events.md @@ -0,0 +1,165 @@ +# Lifespan Events { #lifespan-events } + +You can define logic (code) that should be executed before the application **starts up**. This means that this code will be executed **once**, **before** the application **starts receiving requests**. + +The same way, you can define logic (code) that should be executed when the application is **shutting down**. In this case, this code will be executed **once**, **after** having handled possibly **many requests**. + +Because this code is executed before the application **starts** taking requests, and right after it **finishes** handling requests, it covers the whole application **lifespan** (the word "lifespan" will be important in a second 😉). + +This can be very useful for setting up **resources** that you need to use for the whole app, and that are **shared** among requests, and/or that you need to **clean up** afterwards. For example, a database connection pool, or loading a shared machine learning model. + +## Use Case { #use-case } + +Let's start with an example **use case** and then see how to solve it with this. + +Let's imagine that you have some **machine learning models** that you want to use to handle requests. 🤖 + +The same models are shared among requests, so, it's not one model per request, or one per user or something similar. + +Let's imagine that loading the model can **take quite some time**, because it has to read a lot of **data from disk**. So you don't want to do it for every request. + +You could load it at the top level of the module/file, but that would also mean that it would **load the model** even if you are just running a simple automated test, then that test would be **slow** because it would have to wait for the model to load before being able to run an independent part of the code. + +That's what we'll solve, let's load the model before the requests are handled, but only right before the application starts receiving requests, not while the code is being loaded. + +## Lifespan { #lifespan } + +You can define this *startup* and *shutdown* logic using the `lifespan` parameter of the `FastAPI` app, and a "context manager" (I'll show you what that is in a second). + +Let's start with an example and then see it in detail. + +We create an async function `lifespan()` with `yield` like this: + +{* ../../docs_src/events/tutorial003_py310.py hl[16,19] *} + +Here we are simulating the expensive *startup* operation of loading the model by putting the (fake) model function in the dictionary with machine learning models before the `yield`. This code will be executed **before** the application **starts taking requests**, during the *startup*. + +And then, right after the `yield`, we unload the model. This code will be executed **after** the application **finishes handling requests**, right before the *shutdown*. This could, for example, release resources like memory or a GPU. + +/// tip + +The `shutdown` would happen when you are **stopping** the application. + +Maybe you need to start a new version, or you just got tired of running it. 🤷 + +/// + +### Lifespan function { #lifespan-function } + +The first thing to notice, is that we are defining an async function with `yield`. This is very similar to Dependencies with `yield`. + +{* ../../docs_src/events/tutorial003_py310.py hl[14:19] *} + +The first part of the function, before the `yield`, will be executed **before** the application starts. + +And the part after the `yield` will be executed **after** the application has finished. + +### Async Context Manager { #async-context-manager } + +If you check, the function is decorated with an `@asynccontextmanager`. + +That converts the function into something called an "**async context manager**". + +{* ../../docs_src/events/tutorial003_py310.py hl[1,13] *} + +A **context manager** in Python is something that you can use in a `with` statement, for example, `open()` can be used as a context manager: + +```Python +with open("file.txt") as file: + file.read() +``` + +In recent versions of Python, there's also an **async context manager**. You would use it with `async with`: + +```Python +async with lifespan(app): + await do_stuff() +``` + +When you create a context manager or an async context manager like above, what it does is that, before entering the `with` block, it will execute the code before the `yield`, and after exiting the `with` block, it will execute the code after the `yield`. + +In our code example above, we don't use it directly, but we pass it to FastAPI for it to use it. + +The `lifespan` parameter of the `FastAPI` app takes an **async context manager**, so we can pass our new `lifespan` async context manager to it. + +{* ../../docs_src/events/tutorial003_py310.py hl[22] *} + +## Alternative Events (deprecated) { #alternative-events-deprecated } + +/// warning + +The recommended way to handle the *startup* and *shutdown* is using the `lifespan` parameter of the `FastAPI` app as described above. If you provide a `lifespan` parameter, `startup` and `shutdown` event handlers will no longer be called. It's all `lifespan` or all events, not both. + +You can probably skip this part. + +/// + +There's an alternative way to define this logic to be executed during *startup* and during *shutdown*. + +You can define event handlers (functions) that need to be executed before the application starts up, or when the application is shutting down. + +These functions can be declared with `async def` or normal `def`. + +### `startup` event { #startup-event } + +To add a function that should be run before the application starts, declare it with the event `"startup"`: + +{* ../../docs_src/events/tutorial001_py310.py hl[8] *} + +In this case, the `startup` event handler function will initialize the items "database" (just a `dict`) with some values. + +You can add more than one event handler function. + +And your application won't start receiving requests until all the `startup` event handlers have completed. + +### `shutdown` event { #shutdown-event } + +To add a function that should be run when the application is shutting down, declare it with the event `"shutdown"`: + +{* ../../docs_src/events/tutorial002_py310.py hl[6] *} + +Here, the `shutdown` event handler function will write a text line `"Application shutdown"` to a file `log.txt`. + +/// note + +In the `open()` function, the `mode="a"` means "append", so, the line will be added after whatever is on that file, without overwriting the previous contents. + +/// + +/// tip + +Notice that in this case we are using a standard Python `open()` function that interacts with a file. + +So, it involves I/O (input/output), that requires "waiting" for things to be written to disk. + +But `open()` doesn't use `async` and `await`. + +So, we declare the event handler function with standard `def` instead of `async def`. + +/// + +### `startup` and `shutdown` together { #startup-and-shutdown-together } + +There's a high chance that the logic for your *startup* and *shutdown* is connected, you might want to start something and then finish it, acquire a resource and then release it, etc. + +Doing that in separate functions that don't share logic or variables together is more difficult as you would need to store values in global variables or similar tricks. + +Because of that, it's now recommended to instead use the `lifespan` as explained above. + +## Technical Details { #technical-details } + +Just a technical detail for the curious nerds. 🤓 + +Underneath, in the ASGI technical specification, this is part of the [Lifespan Protocol](https://asgi.readthedocs.io/en/latest/specs/lifespan.html), and it defines events called `startup` and `shutdown`. + +/// note + +You can read more about the Starlette `lifespan` handlers in [Starlette's Lifespan' docs](https://www.starlette.dev/lifespan/). + +Including how to handle lifespan state that can be used in other areas of your code. + +/// + +## Sub Applications { #sub-applications } + +🚨 Keep in mind that these lifespan events (startup and shutdown) will only be executed for the main application, not for [Sub Applications - Mounts](sub-applications.md). diff --git a/docs/en/docs/advanced/generate-clients.md b/docs/en/docs/advanced/generate-clients.md new file mode 100644 index 0000000000000..67dfe736fdc98 --- /dev/null +++ b/docs/en/docs/advanced/generate-clients.md @@ -0,0 +1,192 @@ +# Generating SDKs { #generating-sdks } + +Because **FastAPI** is based on the **OpenAPI** specification, its APIs can be described in a standard format that many tools understand. + +This makes it easy to generate up-to-date **documentation**, client libraries (**SDKs**) in multiple languages, and **testing** or **automation workflows** that stay in sync with your code. + +In this guide, you'll learn how to generate a **TypeScript SDK** for your FastAPI backend. + +## Open Source SDK Generators { #open-source-sdk-generators } + +A versatile option is the [OpenAPI Generator](https://openapi-generator.tech/), which supports **many programming languages** and can generate SDKs from your OpenAPI specification. + +For **TypeScript clients**, [Hey API](https://heyapi.dev/) is a purpose-built solution, providing an optimized experience for the TypeScript ecosystem. + +You can discover more SDK generators on [OpenAPI.Tools](https://openapi.tools/#sdk). + +/// tip + +FastAPI automatically generates **OpenAPI 3.1** specifications, so any tool you use must support this version. + +/// + +## Create a TypeScript SDK { #create-a-typescript-sdk } + +Let's start with a simple FastAPI application: + +{* ../../docs_src/generate_clients/tutorial001_py310.py hl[7:9,12:13,16:17,21] *} + +Notice that the *path operations* define the models they use for request payload and response payload, using the models `Item` and `ResponseMessage`. + +### API Docs { #api-docs } + +If you go to `/docs`, you will see that it has the **schemas** for the data to be sent in requests and received in responses: + + + +You can see those schemas because they were declared with the models in the app. + +That information is available in the app's **OpenAPI schema**, and then shown in the API docs. + +That same information from the models that is included in OpenAPI is what can be used to **generate the client code**. + +### Hey API { #hey-api } + +Once we have a FastAPI app with the models, we can use Hey API to generate a TypeScript client. The fastest way to do that is via npx. + +```sh +npx @hey-api/openapi-ts -i http://localhost:8000/openapi.json -o src/client +``` + +This will generate a TypeScript SDK in `./src/client`. + +You can learn how to [install `@hey-api/openapi-ts`](https://heyapi.dev/openapi-ts/get-started) and read about the [generated output](https://heyapi.dev/openapi-ts/output) on their website. + +### Using the SDK { #using-the-sdk } + +Now you can import and use the client code. It could look like this, notice that you get autocompletion for the methods: + + + +You will also get autocompletion for the payload to send: + + + +/// tip + +Notice the autocompletion for `name` and `price`, that was defined in the FastAPI application, in the `Item` model. + +/// + +You will have inline errors for the data that you send: + + + +The response object will also have autocompletion: + + + +## FastAPI App with Tags { #fastapi-app-with-tags } + +In many cases, your FastAPI app will be bigger, and you will probably use tags to separate different groups of *path operations*. + +For example, you could have a section for **items** and another section for **users**, and they could be separated by tags: + +{* ../../docs_src/generate_clients/tutorial002_py310.py hl[21,26,34] *} + +### Generate a TypeScript Client with Tags { #generate-a-typescript-client-with-tags } + +If you generate a client for a FastAPI app using tags, it will normally also separate the client code based on the tags. + +This way, you will be able to have things ordered and grouped correctly for the client code: + + + +In this case, you have: + +* `ItemsService` +* `UsersService` + +### Client Method Names { #client-method-names } + +Right now, the generated method names like `createItemItemsPost` don't look very clean: + +```TypeScript +ItemsService.createItemItemsPost({name: "Plumbus", price: 5}) +``` + +...that's because the client generator uses the OpenAPI internal **operation ID** for each *path operation*. + +OpenAPI requires that each operation ID is unique across all the *path operations*, so FastAPI uses the **function name**, the **path**, and the **HTTP method/operation** to generate that operation ID, because that way it can make sure that the operation IDs are unique. + +But I'll show you how to improve that next. 🤓 + +## Custom Operation IDs and Better Method Names { #custom-operation-ids-and-better-method-names } + +You can **modify** the way these operation IDs are **generated** to make them simpler and have **simpler method names** in the clients. + +In this case, you will have to ensure that each operation ID is **unique** in some other way. + +For example, you could make sure that each *path operation* has a tag, and then generate the operation ID based on the **tag** and the *path operation* **name** (the function name). + +### Custom Generate Unique ID Function { #custom-generate-unique-id-function } + +FastAPI uses a **unique ID** for each *path operation*, which is used for the **operation ID** and also for the names of any needed custom models, for requests or responses. + +You can customize that function. It takes an `APIRoute` and outputs a string. + +For example, here it is using the first tag (you will probably have only one tag) and the *path operation* name (the function name). + +You can then pass that custom function to **FastAPI** as the `generate_unique_id_function` parameter: + +{* ../../docs_src/generate_clients/tutorial003_py310.py hl[6:7,10] *} + +### Generate a TypeScript Client with Custom Operation IDs { #generate-a-typescript-client-with-custom-operation-ids } + +Now, if you generate the client again, you will see that it has the improved method names: + + + +As you see, the method names now have the tag and then the function name, now they don't include information from the URL path and the HTTP operation. + +### Preprocess the OpenAPI Specification for the Client Generator { #preprocess-the-openapi-specification-for-the-client-generator } + +The generated code still has some **duplicated information**. + +We already know that this method is related to the **items** because that word is in the `ItemsService` (taken from the tag), but we still have the tag name prefixed in the method name too. 😕 + +We will probably still want to keep it for OpenAPI in general, as that will ensure that the operation IDs are **unique**. + +But for the generated client, we could **modify** the OpenAPI operation IDs right before generating the clients, just to make those method names nicer and **cleaner**. + +We could download the OpenAPI JSON to a file `openapi.json` and then we could **remove that prefixed tag** with a script like this: + +{* ../../docs_src/generate_clients/tutorial004_py310.py *} + +//// tab | Node.js + +```Javascript +{!> ../../docs_src/generate_clients/tutorial004.js!} +``` + +//// + +With that, the operation IDs would be renamed from things like `items-get_items` to just `get_items`, that way the client generator can generate simpler method names. + +### Generate a TypeScript Client with the Preprocessed OpenAPI { #generate-a-typescript-client-with-the-preprocessed-openapi } + +Since the end result is now in an `openapi.json` file, you need to update your input location: + +```sh +npx @hey-api/openapi-ts -i ./openapi.json -o src/client +``` + +After generating the new client, you would now have **clean method names**, with all the **autocompletion**, **inline errors**, etc: + + + +## Benefits { #benefits } + +When using the automatically generated clients, you would get **autocompletion** for: + +* Methods. +* Request payloads in the body, query parameters, etc. +* Response payloads. + +You would also have **inline errors** for everything. + +And whenever you update the backend code, and **regenerate** the frontend, it would have any new *path operations* available as methods, the old ones removed, and any other change would be reflected on the generated code. 🤓 + +This also means that if something changed, it will be **reflected** on the client code automatically. And if you **build** the client, it will error out if you have any **mismatch** in the data used. + +So, you would **detect many errors** very early in the development cycle instead of having to wait for the errors to show up to your final users in production and then trying to debug where the problem is. ✨ diff --git a/docs/en/docs/advanced/index.md b/docs/en/docs/advanced/index.md new file mode 100644 index 0000000000000..c8056ab54f6d6 --- /dev/null +++ b/docs/en/docs/advanced/index.md @@ -0,0 +1,21 @@ +# Advanced User Guide { #advanced-user-guide } + +## Additional Features { #additional-features } + +The main [Tutorial - User Guide](../tutorial/index.md) should be enough to give you a tour through all the main features of **FastAPI**. + +In the next sections you will see other options, configurations, and additional features. + +/// tip + +The next sections are **not necessarily "advanced"**. + +And it's possible that for your use case, the solution is in one of them. + +/// + +## Read the Tutorial first { #read-the-tutorial-first } + +You could still use most of the features in **FastAPI** with the knowledge from the main [Tutorial - User Guide](../tutorial/index.md). + +And the next sections assume you already read it, and assume that you know those main ideas. diff --git a/docs/en/docs/advanced/json-base64-bytes.md b/docs/en/docs/advanced/json-base64-bytes.md new file mode 100644 index 0000000000000..55f4a99b409d3 --- /dev/null +++ b/docs/en/docs/advanced/json-base64-bytes.md @@ -0,0 +1,63 @@ +# JSON with Bytes as Base64 { #json-with-bytes-as-base64 } + +If your app needs to receive and send JSON data, but you need to include binary data in it, you can encode it as base64. + +## Base64 vs Files { #base64-vs-files } + +Consider first if you can use [Request Files](../tutorial/request-files.md) for uploading binary data and [Custom Response - FileResponse](./custom-response.md#fileresponse) for sending binary data, instead of encoding it in JSON. + +JSON can only contain UTF-8 encoded strings, so it can't contain raw bytes. + +Base64 can encode binary data in strings, but to do it, it needs to use more characters than the original binary data, so it would normally be less efficient than regular files. + +Use base64 only if you definitely need to include binary data in JSON, and you can't use files for that. + +## Pydantic `bytes` { #pydantic-bytes } + +You can declare a Pydantic model with `bytes` fields, and then use `val_json_bytes` in the model config to tell it to use base64 to *validate* input JSON data, as part of that validation it will decode the base64 string into bytes. + +{* ../../docs_src/json_base64_bytes/tutorial001_py310.py ln[1:9,29:35] hl[9] *} + +If you check the `/docs`, they will show that the field `data` expects base64 encoded bytes: + +
+ +
+ +You could send a request like: + +```json +{ + "description": "Some data", + "data": "aGVsbG8=" +} +``` + +/// tip + +`aGVsbG8=` is the base64 encoding of `hello`. + +/// + +And then Pydantic will decode the base64 string and give you the original bytes in the `data` field of the model. + +You will receive a response like: + +```json +{ + "description": "Some data", + "content": "hello" +} +``` + +## Pydantic `bytes` for Output Data { #pydantic-bytes-for-output-data } + +You can also use `bytes` fields with `ser_json_bytes` in the model config for output data, and Pydantic will *serialize* the bytes as base64 when generating the JSON response. + +{* ../../docs_src/json_base64_bytes/tutorial001_py310.py ln[1:2,12:16,29,38:41] hl[16] *} + +## Pydantic `bytes` for Input and Output Data { #pydantic-bytes-for-input-and-output-data } + +And of course, you can use the same model configured to use base64 to handle both input (*validate*) with `val_json_bytes` and output (*serialize*) with `ser_json_bytes` when receiving and sending JSON data. + +{* ../../docs_src/json_base64_bytes/tutorial001_py310.py ln[1:2,19:26,29,44:46] hl[23:26] *} diff --git a/docs/en/docs/advanced/middleware.md b/docs/en/docs/advanced/middleware.md new file mode 100644 index 0000000000000..65f9438c95f23 --- /dev/null +++ b/docs/en/docs/advanced/middleware.md @@ -0,0 +1,97 @@ +# Advanced Middleware { #advanced-middleware } + +In the main tutorial you read how to add [Custom Middleware](../tutorial/middleware.md) to your application. + +And then you also read how to handle [CORS with the `CORSMiddleware`](../tutorial/cors.md). + +In this section we'll see how to use other middlewares. + +## Adding ASGI middlewares { #adding-asgi-middlewares } + +As **FastAPI** is based on Starlette and implements the ASGI specification, you can use any ASGI middleware. + +A middleware doesn't have to be made for FastAPI or Starlette to work, as long as it follows the ASGI spec. + +In general, ASGI middlewares are classes that expect to receive an ASGI app as the first argument. + +So, in the documentation for third-party ASGI middlewares they will probably tell you to do something like: + +```Python +from unicorn import UnicornMiddleware + +app = SomeASGIApp() + +new_app = UnicornMiddleware(app, some_config="rainbow") +``` + +But FastAPI (actually Starlette) provides a simpler way to do it that makes sure that the internal middlewares handle server errors and custom exception handlers work properly. + +For that, you use `app.add_middleware()` (as in the example for CORS). + +```Python +from fastapi import FastAPI +from unicorn import UnicornMiddleware + +app = FastAPI() + +app.add_middleware(UnicornMiddleware, some_config="rainbow") +``` + +`app.add_middleware()` receives a middleware class as the first argument and any additional arguments to be passed to the middleware. + +## Integrated middlewares { #integrated-middlewares } + +**FastAPI** includes several middlewares for common use cases, we'll see next how to use them. + +/// note | Technical Details + +For the next examples, you could also use `from starlette.middleware.something import SomethingMiddleware`. + +**FastAPI** provides several middlewares in `fastapi.middleware` just as a convenience for you, the developer. But most of the available middlewares come directly from Starlette. + +/// + +## `HTTPSRedirectMiddleware` { #httpsredirectmiddleware } + +Enforces that all incoming requests must either be `https` or `wss`. + +Any incoming request to `http` or `ws` will be redirected to the secure scheme instead. + +{* ../../docs_src/advanced_middleware/tutorial001_py310.py hl[2,6] *} + +## `TrustedHostMiddleware` { #trustedhostmiddleware } + +Enforces that all incoming requests have a correctly set `Host` header, in order to guard against HTTP Host Header attacks. + +{* ../../docs_src/advanced_middleware/tutorial002_py310.py hl[2,6:8] *} + +The following arguments are supported: + +* `allowed_hosts` - A list of domain names that should be allowed as hostnames. Wildcard domains such as `*.example.com` are supported for matching subdomains. To allow any hostname either use `allowed_hosts=["*"]` or omit the middleware. +* `www_redirect` - If set to True, requests to non-www versions of the allowed hosts will be redirected to their www counterparts. Defaults to `True`. + +If an incoming request does not validate correctly then a `400` response will be sent. + +## `GZipMiddleware` { #gzipmiddleware } + +Handles GZip responses for any request that includes `"gzip"` in the `Accept-Encoding` header. + +The middleware will handle both standard and streaming responses. + +{* ../../docs_src/advanced_middleware/tutorial003_py310.py hl[2,6] *} + +The following arguments are supported: + +* `minimum_size` - Do not GZip responses that are smaller than this minimum size in bytes. Defaults to `500`. +* `compresslevel` - Used during GZip compression. It is an integer ranging from 1 to 9. Defaults to `9`. Lower value results in faster compression but larger file sizes, while higher value results in slower compression but smaller file sizes. + +## Other middlewares { #other-middlewares } + +There are many other ASGI middlewares. + +For example: + +* [Uvicorn's `ProxyHeadersMiddleware`](https://github.com/encode/uvicorn/blob/master/uvicorn/middleware/proxy_headers.py) +* [MessagePack](https://github.com/florimondmanca/msgpack-asgi) + +To see other available middlewares check [Starlette's Middleware docs](https://www.starlette.dev/middleware/) and the [ASGI Awesome List](https://github.com/florimondmanca/awesome-asgi). diff --git a/docs/en/docs/advanced/openapi-callbacks.md b/docs/en/docs/advanced/openapi-callbacks.md new file mode 100644 index 0000000000000..17910e1cfcb05 --- /dev/null +++ b/docs/en/docs/advanced/openapi-callbacks.md @@ -0,0 +1,186 @@ +# OpenAPI Callbacks { #openapi-callbacks } + +You could create an API with a *path operation* that could trigger a request to an *external API* created by someone else (probably the same developer that would be *using* your API). + +The process that happens when your API app calls the *external API* is named a "callback". Because the software that the external developer wrote sends a request to your API and then your API *calls back*, sending a request to an *external API* (that was probably created by the same developer). + +In this case, you could want to document how that external API *should* look. What *path operation* it should have, what body it should expect, what response it should return, etc. + +## An app with callbacks { #an-app-with-callbacks } + +Let's see all this with an example. + +Imagine you develop an app that allows creating invoices. + +These invoices will have an `id`, `title` (optional), `customer`, and `total`. + +The user of your API (an external developer) will create an invoice in your API with a POST request. + +Then your API will (let's imagine): + +* Send the invoice to some customer of the external developer. +* Collect the money. +* Send a notification back to the API user (the external developer). + * This will be done by sending a POST request (from *your API*) to some *external API* provided by that external developer (this is the "callback"). + +## The normal **FastAPI** app { #the-normal-fastapi-app } + +Let's first see how the normal API app would look before adding the callback. + +It will have a *path operation* that will receive an `Invoice` body, and a query parameter `callback_url` that will contain the URL for the callback. + +This part is pretty normal, most of the code is probably already familiar to you: + +{* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[7:11,34:51] *} + +/// tip + +The `callback_url` query parameter uses a Pydantic [Url](https://docs.pydantic.dev/latest/api/networks/) type. + +/// + +The only new thing is the `callbacks=invoices_callback_router.routes` as an argument to the *path operation decorator*. We'll see what that is next. + +## Documenting the callback { #documenting-the-callback } + +The actual callback code will depend heavily on your own API app. + +And it will probably vary a lot from one app to the next. + +It could be just one or two lines of code, like: + +```Python +callback_url = "https://example.com/api/v1/invoices/events/" +httpx.post(callback_url, json={"description": "Invoice paid", "paid": True}) +``` + +But possibly the most important part of the callback is making sure that your API user (the external developer) implements the *external API* correctly, according to the data that *your API* is going to send in the request body of the callback, etc. + +So, what we will do next is add the code to document how that *external API* should look to receive the callback from *your API*. + +That documentation will show up in the Swagger UI at `/docs` in your API, and it will let external developers know how to build the *external API*. + +This example doesn't implement the callback itself (that could be just a line of code), only the documentation part. + +/// tip + +The actual callback is just an HTTP request. + +When implementing the callback yourself, you could use something like [HTTPX](https://www.python-httpx.org) or [Requests](https://requests.readthedocs.io/). + +/// + +## Write the callback documentation code { #write-the-callback-documentation-code } + +This code won't be executed in your app, we only need it to *document* how that *external API* should look. + +But, you already know how to easily create automatic documentation for an API with **FastAPI**. + +So we are going to use that same knowledge to document how the *external API* should look... by creating the *path operation(s)* that the external API should implement (the ones your API will call). + +/// tip + +When writing the code to document a callback, it might be useful to imagine that you are that *external developer*. And that you are currently implementing the *external API*, not *your API*. + +Temporarily adopting this point of view (of the *external developer*) can help you feel like it's more obvious where to put the parameters, the Pydantic model for the body, for the response, etc. for that *external API*. + +/// + +### Create a callback `APIRouter` { #create-a-callback-apirouter } + +First create a new `APIRouter` that will contain one or more callbacks. + +{* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[1,23] *} + +### Create the callback *path operation* { #create-the-callback-path-operation } + +To create the callback *path operation* use the same `APIRouter` you created above. + +It should look just like a normal FastAPI *path operation*: + +* It should probably have a declaration of the body it should receive, e.g. `body: InvoiceEvent`. +* And it could also have a declaration of the response it should return, e.g. `response_model=InvoiceEventReceived`. + +{* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[14:16,19:20,26:30] *} + +There are 2 main differences from a normal *path operation*: + +* It doesn't need to have any actual code, because your app will never call this code. It's only used to document the *external API*. So, the function could just have `pass`. +* The *path* can contain an [OpenAPI 3 expression](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#key-expression) (see more below) where it can use variables with parameters and parts of the original request sent to *your API*. + +### The callback path expression { #the-callback-path-expression } + +The callback *path* can have an [OpenAPI 3 expression](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#key-expression) that can contain parts of the original request sent to *your API*. + +In this case, it's the `str`: + +```Python +"{$callback_url}/invoices/{$request.body.id}" +``` + +So, if your API user (the external developer) sends a request to *your API* to: + +``` +https://yourapi.com/invoices/?callback_url=https://www.external.org/events +``` + +with a JSON body of: + +```JSON +{ + "id": "2expen51ve", + "customer": "Mr. Richie Rich", + "total": "9999" +} +``` + +then *your API* will process the invoice, and at some point later, send a callback request to the `callback_url` (the *external API*): + +``` +https://www.external.org/events/invoices/2expen51ve +``` + +with a JSON body containing something like: + +```JSON +{ + "description": "Payment celebration", + "paid": true +} +``` + +and it would expect a response from that *external API* with a JSON body like: + +```JSON +{ + "ok": true +} +``` + +/// tip + +Notice how the callback URL used contains the URL received as a query parameter in `callback_url` (`https://www.external.org/events`) and also the invoice `id` from inside of the JSON body (`2expen51ve`). + +/// + +### Add the callback router { #add-the-callback-router } + +At this point you have the *callback path operation(s)* needed (the one(s) that the *external developer* should implement in the *external API*) in the callback router you created above. + +Now use the parameter `callbacks` in *your API's path operation decorator* to pass the attribute `.routes` from that callback router: + +{* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[33] *} + +/// tip + +Notice that you are not passing the router itself (`invoices_callback_router`) to `callbacks=`, but its `.routes`, as in `invoices_callback_router.routes`. FastAPI will use those routes to generate the callback OpenAPI documentation. + +/// + +### Check the docs { #check-the-docs } + +Now you can start your app and go to [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs). + +You will see your docs including a "Callbacks" section for your *path operation* that shows how the *external API* should look: + + diff --git a/docs/en/docs/advanced/openapi-webhooks.md b/docs/en/docs/advanced/openapi-webhooks.md new file mode 100644 index 0000000000000..abcbe8ce2eb4c --- /dev/null +++ b/docs/en/docs/advanced/openapi-webhooks.md @@ -0,0 +1,55 @@ +# OpenAPI Webhooks { #openapi-webhooks } + +There are cases where you want to tell your API **users** that your app could call *their* app (sending a request) with some data, normally to **notify** of some type of **event**. + +This means that instead of the normal process of your users sending requests to your API, it's **your API** (or your app) that could **send requests to their system** (to their API, their app). + +This is normally called a **webhook**. + +## Webhooks steps { #webhooks-steps } + +The process normally is that **you define** in your code what is the message that you will send, the **body of the request**. + +You also define in some way at which **moments** your app will send those requests or events. + +And **your users** define in some way (for example in a web dashboard somewhere) the **URL** where your app should send those requests. + +All the **logic** about how to register the URLs for webhooks and the code to actually send those requests is up to you. You write it however you want to in **your own code**. + +## Documenting webhooks with **FastAPI** and OpenAPI { #documenting-webhooks-with-fastapi-and-openapi } + +With **FastAPI**, using OpenAPI, you can define the names of these webhooks, the types of HTTP operations that your app can send (e.g. `POST`, `PUT`, etc.) and the request **bodies** that your app would send. + +This can make it a lot easier for your users to **implement their APIs** to receive your **webhook** requests, they might even be able to autogenerate some of their own API code. + +/// note + +Webhooks are available in OpenAPI 3.1.0 and above, supported by FastAPI `0.99.0` and above. + +/// + +## An app with webhooks { #an-app-with-webhooks } + +When you create a **FastAPI** application, there is a `webhooks` attribute that you can use to define *webhooks*, the same way you would define *path operations*, for example with `@app.webhooks.post()`. + +{* ../../docs_src/openapi_webhooks/tutorial001_py310.py hl[9:12,15:20] *} + +The webhooks that you define will end up in the **OpenAPI** schema and the automatic **docs UI**. + +/// note + +The `app.webhooks` object is actually just an `APIRouter`, the same type you would use when structuring your app with multiple files. + +/// + +Notice that with webhooks you are actually not declaring a *path* (like `/items/`), the text you pass there is just an **identifier** of the webhook (the name of the event), for example in `@app.webhooks.post("new-subscription")`, the webhook name is `new-subscription`. + +This is because it is expected that **your users** would define the actual **URL path** where they want to receive the webhook request in some other way (e.g. a web dashboard). + +### Check the docs { #check-the-docs } + +Now you can start your app and go to [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs). + +You will see your docs have the normal *path operations* and now also some **webhooks**: + + diff --git a/docs/en/docs/advanced/path-operation-advanced-configuration.md b/docs/en/docs/advanced/path-operation-advanced-configuration.md new file mode 100644 index 0000000000000..9dca4d712369a --- /dev/null +++ b/docs/en/docs/advanced/path-operation-advanced-configuration.md @@ -0,0 +1,166 @@ +# Path Operation Advanced Configuration { #path-operation-advanced-configuration } + +## OpenAPI operationId { #openapi-operationid } + +/// warning + +If you are not an "expert" in OpenAPI, you probably don't need this. + +/// + +You can set the OpenAPI `operationId` to be used in your *path operation* with the parameter `operation_id`. + +You would have to make sure that it is unique for each operation. + +{* ../../docs_src/path_operation_advanced_configuration/tutorial001_py310.py hl[6] *} + +### Using the *path operation function* name as the operationId { #using-the-path-operation-function-name-as-the-operationid } + +If you want to use your APIs' function names as `operationId`s, you can pass a custom `generate_unique_id_function` to `FastAPI`. + +The function receives each `APIRoute` and returns the `operationId` to use for that path operation. + +{* ../../docs_src/path_operation_advanced_configuration/tutorial002_py310.py hl[2,5:6,9] *} + +/// warning + +If you do this, you have to make sure each one of your *path operation functions* has a unique name. + +Even if they are in different modules (Python files). + +/// + +## Exclude from OpenAPI { #exclude-from-openapi } + +To exclude a *path operation* from the generated OpenAPI schema (and thus, from the automatic documentation systems), use the parameter `include_in_schema` and set it to `False`: + +{* ../../docs_src/path_operation_advanced_configuration/tutorial003_py310.py hl[6] *} + +## Advanced description from docstring { #advanced-description-from-docstring } + +You can limit the lines used from the docstring of a *path operation function* for OpenAPI. + +Adding an `\f` (an escaped "form feed" character) causes **FastAPI** to truncate the output used for OpenAPI at this point. + +It won't show up in the documentation, but other tools (such as Sphinx) will be able to use the rest. + +{* ../../docs_src/path_operation_advanced_configuration/tutorial004_py310.py hl[17:27] *} + +## Additional Responses { #additional-responses } + +You probably have seen how to declare the `response_model` and `status_code` for a *path operation*. + +That defines the metadata about the main response of a *path operation*. + +You can also declare additional responses with their models, status codes, etc. + +There's a whole chapter here in the documentation about it, you can read it at [Additional Responses in OpenAPI](additional-responses.md). + +## OpenAPI Extra { #openapi-extra } + +When you declare a *path operation* in your application, **FastAPI** automatically generates the relevant metadata about that *path operation* to be included in the OpenAPI schema. + +/// note | Technical details + +In the OpenAPI specification it is called the [Operation Object](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#operation-object). + +/// + +It has all the information about the *path operation* and is used to generate the automatic documentation. + +It includes the `tags`, `parameters`, `requestBody`, `responses`, etc. + +This *path operation*-specific OpenAPI schema is normally generated automatically by **FastAPI**, but you can also extend it. + +/// tip + +This is a low level extension point. + +If you only need to declare additional responses, a more convenient way to do it is with [Additional Responses in OpenAPI](additional-responses.md). + +/// + +You can extend the OpenAPI schema for a *path operation* using the parameter `openapi_extra`. + +### OpenAPI Extensions { #openapi-extensions } + +This `openapi_extra` can be helpful, for example, to declare [OpenAPI Extensions](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#specificationExtensions): + +{* ../../docs_src/path_operation_advanced_configuration/tutorial005_py310.py hl[6] *} + +If you open the automatic API docs, your extension will show up at the bottom of the specific *path operation*. + + + +And if you see the resulting OpenAPI (at `/openapi.json` in your API), you will see your extension as part of the specific *path operation* too: + +```JSON hl_lines="22" +{ + "openapi": "3.1.0", + "info": { + "title": "FastAPI", + "version": "0.1.0" + }, + "paths": { + "/items/": { + "get": { + "summary": "Read Items", + "operationId": "read_items_items__get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {} + } + } + } + }, + "x-aperture-labs-portal": "blue" + } + } + } +} +``` + +### Custom OpenAPI *path operation* schema { #custom-openapi-path-operation-schema } + +The dictionary in `openapi_extra` will be deeply merged with the automatically generated OpenAPI schema for the *path operation*. + +So, you could add additional data to the automatically generated schema. + +For example, you could decide to read and validate the request with your own code, without using the automatic features of FastAPI with Pydantic, but you could still want to define the request in the OpenAPI schema. + +You could do that with `openapi_extra`: + +{* ../../docs_src/path_operation_advanced_configuration/tutorial006_py310.py hl[19:36, 39:40] *} + +In this example, we didn't declare any Pydantic model. In fact, the request body is not even parsed as JSON, it is read directly as `bytes`, and the function `magic_data_reader()` would be in charge of parsing it in some way. + +Nevertheless, we can declare the expected schema for the request body. + +### Custom OpenAPI content type { #custom-openapi-content-type } + +Using this same trick, you could use a Pydantic model to define the JSON Schema that is then included in the custom OpenAPI schema section for the *path operation*. + +And you could do this even if the data type in the request is not JSON. + +For example, in this application we don't use FastAPI's integrated functionality to extract the JSON Schema from Pydantic models nor the automatic validation for JSON. In fact, we are declaring the request content type as YAML, not JSON: + +{* ../../docs_src/path_operation_advanced_configuration/tutorial007_py310.py hl[15:20, 22] *} + +Nevertheless, although we are not using the default integrated functionality, we are still using a Pydantic model to manually generate the JSON Schema for the data that we want to receive in YAML. + +Then we use the request directly, and extract the body as `bytes`. This means that FastAPI won't even try to parse the request payload as JSON. + +And then in our code, we parse that YAML content directly, and then we are again using the same Pydantic model to validate the YAML content: + +{* ../../docs_src/path_operation_advanced_configuration/tutorial007_py310.py hl[24:31] *} + +/// tip + +Here we reuse the same Pydantic model. + +But the same way, we could have validated it in some other way. + +/// diff --git a/docs/en/docs/advanced/response-change-status-code.md b/docs/en/docs/advanced/response-change-status-code.md new file mode 100644 index 0000000000000..747016722c67e --- /dev/null +++ b/docs/en/docs/advanced/response-change-status-code.md @@ -0,0 +1,31 @@ +# Response - Change Status Code { #response-change-status-code } + +You probably read before that you can set a default [Response Status Code](../tutorial/response-status-code.md). + +But in some cases you need to return a different status code than the default. + +## Use case { #use-case } + +For example, imagine that you want to return an HTTP status code of "OK" `200` by default. + +But if the data didn't exist, you want to create it, and return an HTTP status code of "CREATED" `201`. + +But you still want to be able to filter and convert the data you return with a `response_model`. + +For those cases, you can use a `Response` parameter. + +## Use a `Response` parameter { #use-a-response-parameter } + +You can declare a parameter of type `Response` in your *path operation function* (as you can do for cookies and headers). + +And then you can set the `status_code` in that *temporary* response object. + +{* ../../docs_src/response_change_status_code/tutorial001_py310.py hl[1,9,12] *} + +And then you can return any object you need, as you normally would (a `dict`, a database model, etc). + +And if you declared a `response_model`, it will still be used to filter and convert the object you returned. + +**FastAPI** will use that *temporary* response to extract the status code (also cookies and headers), and will put them in the final response that contains the value you returned, filtered by any `response_model`. + +You can also declare the `Response` parameter in dependencies, and set the status code in them. But keep in mind that the last one to be set will win. diff --git a/docs/en/docs/advanced/response-cookies.md b/docs/en/docs/advanced/response-cookies.md new file mode 100644 index 0000000000000..f523a5c63cdaf --- /dev/null +++ b/docs/en/docs/advanced/response-cookies.md @@ -0,0 +1,51 @@ +# Response Cookies { #response-cookies } + +## Use a `Response` parameter { #use-a-response-parameter } + +You can declare a parameter of type `Response` in your *path operation function*. + +And then you can set cookies in that *temporary* response object. + +{* ../../docs_src/response_cookies/tutorial002_py310.py hl[1, 8:9] *} + +And then you can return any object you need, as you normally would (a `dict`, a database model, etc). + +And if you declared a `response_model`, it will still be used to filter and convert the object you returned. + +**FastAPI** will use that *temporary* response to extract the cookies (also headers and status code), and will put them in the final response that contains the value you returned, filtered by any `response_model`. + +You can also declare the `Response` parameter in dependencies, and set cookies (and headers) in them. + +## Return a `Response` directly { #return-a-response-directly } + +You can also create cookies when returning a `Response` directly in your code. + +To do that, you can create a response as described in [Return a Response Directly](response-directly.md). + +Then set Cookies in it, and then return it: + +{* ../../docs_src/response_cookies/tutorial001_py310.py hl[10:12] *} + +/// tip + +Keep in mind that if you return a response directly instead of using the `Response` parameter, FastAPI will return it directly. + +So, you will have to make sure your data is of the correct type. E.g. it is compatible with JSON, if you are returning a `JSONResponse`. + +And also that you are not sending any data that should have been filtered by a `response_model`. + +/// + +### More info { #more-info } + +/// note | Technical Details + +You could also use `from starlette.responses import Response` or `from starlette.responses import JSONResponse`. + +**FastAPI** provides the same `starlette.responses` as `fastapi.responses` just as a convenience for you, the developer. But most of the available responses come directly from Starlette. + +And as the `Response` can be used frequently to set headers and cookies, **FastAPI** also provides it at `fastapi.Response`. + +/// + +To see all the available parameters and options, check the [documentation in Starlette](https://www.starlette.dev/responses/#set-cookie). diff --git a/docs/en/docs/advanced/response-directly.md b/docs/en/docs/advanced/response-directly.md new file mode 100644 index 0000000000000..9dd50a62da762 --- /dev/null +++ b/docs/en/docs/advanced/response-directly.md @@ -0,0 +1,83 @@ +# Return a Response Directly { #return-a-response-directly } + +When you create a **FastAPI** *path operation* you can normally return any data from it: a `dict`, a `list`, a Pydantic model, a database model, etc. + +If you declare a [Response Model](../tutorial/response-model.md) FastAPI will use it to serialize the data to JSON, using Pydantic. + +If you don't declare a response model, FastAPI will use the `jsonable_encoder` explained in [JSON Compatible Encoder](../tutorial/encoder.md) and put it in a `JSONResponse`. + +You could also create a `JSONResponse` directly and return it. + +/// tip + +You will normally have much better performance using a [Response Model](../tutorial/response-model.md) than returning a `JSONResponse` directly, as that way it serializes the data using Pydantic, in Rust. + +/// + +## Return a `Response` { #return-a-response } + +You can return a `Response` or any sub-class of it. + +/// note + +`JSONResponse` itself is a sub-class of `Response`. + +/// + +And when you return a `Response`, **FastAPI** will pass it directly. + +It won't do any data conversion with Pydantic models, it won't convert the contents to any type, etc. + +This gives you a lot of **flexibility**. You can return any data type, override any data declaration or validation, etc. + +It also gives you a lot of **responsibility**. You have to make sure that the data you return is correct, in the correct format, that it can be serialized, etc. + +## Using the `jsonable_encoder` in a `Response` { #using-the-jsonable-encoder-in-a-response } + +Because **FastAPI** doesn't make any changes to a `Response` you return, you have to make sure its contents are ready for it. + +For example, you cannot put a Pydantic model in a `JSONResponse` without first converting it to a `dict` with all the data types (like `datetime`, `UUID`, etc) converted to JSON-compatible types. + +For those cases, you can use the `jsonable_encoder` to convert your data before passing it to a response: + +{* ../../docs_src/response_directly/tutorial001_py310.py hl[5:6,20:21] *} + +/// note | Technical Details + +You could also use `from starlette.responses import JSONResponse`. + +**FastAPI** provides the same `starlette.responses` as `fastapi.responses` just as a convenience for you, the developer. But most of the available responses come directly from Starlette. + +/// + +## Returning a custom `Response` { #returning-a-custom-response } + +The example above shows all the parts you need, but it's not very useful yet, as you could have just returned the `item` directly, and **FastAPI** would put it in a `JSONResponse` for you, converting it to a `dict`, etc. All that by default. + +Now, let's see how you could use that to return a custom response. + +Let's say that you want to return an [XML](https://en.wikipedia.org/wiki/XML) response. + +You could put your XML content in a string, put that in a `Response`, and return it: + +{* ../../docs_src/response_directly/tutorial002_py310.py hl[1,18] *} + +## How a Response Model Works { #how-a-response-model-works } + +When you declare a [Response Model - Return Type](../tutorial/response-model.md) in a path operation, **FastAPI** will use it to serialize the data to JSON, using Pydantic. + +{* ../../docs_src/response_model/tutorial001_01_py310.py hl[16,21] *} + +As that will happen on the Rust side, the performance will be much better than if it was done with regular Python and the `JSONResponse` class. + +When using a `response_model` or return type, FastAPI won't use the `jsonable_encoder` to convert the data (which would be slower) nor the `JSONResponse` class. + +Instead it takes the JSON bytes generated with Pydantic using the response model (or return type) and returns a `Response` with the right media type for JSON directly (`application/json`). + +## Notes { #notes } + +When you return a `Response` directly its data is not validated, converted (serialized), or documented automatically. + +But you can still document it as described in [Additional Responses in OpenAPI](additional-responses.md). + +You can see in later sections how to use/declare these custom `Response`s while still having automatic data conversion, documentation, etc. diff --git a/docs/en/docs/advanced/response-headers.md b/docs/en/docs/advanced/response-headers.md new file mode 100644 index 0000000000000..cbc28e4959f89 --- /dev/null +++ b/docs/en/docs/advanced/response-headers.md @@ -0,0 +1,41 @@ +# Response Headers { #response-headers } + +## Use a `Response` parameter { #use-a-response-parameter } + +You can declare a parameter of type `Response` in your *path operation function* (as you can do for cookies). + +And then you can set headers in that *temporary* response object. + +{* ../../docs_src/response_headers/tutorial002_py310.py hl[1, 7:8] *} + +And then you can return any object you need, as you normally would (a `dict`, a database model, etc). + +And if you declared a `response_model`, it will still be used to filter and convert the object you returned. + +**FastAPI** will use that *temporary* response to extract the headers (also cookies and status code), and will put them in the final response that contains the value you returned, filtered by any `response_model`. + +You can also declare the `Response` parameter in dependencies, and set headers (and cookies) in them. + +## Return a `Response` directly { #return-a-response-directly } + +You can also add headers when you return a `Response` directly. + +Create a response as described in [Return a Response Directly](response-directly.md) and pass the headers as an additional parameter: + +{* ../../docs_src/response_headers/tutorial001_py310.py hl[10:12] *} + +/// note | Technical Details + +You could also use `from starlette.responses import Response` or `from starlette.responses import JSONResponse`. + +**FastAPI** provides the same `starlette.responses` as `fastapi.responses` just as a convenience for you, the developer. But most of the available responses come directly from Starlette. + +And as the `Response` can be used frequently to set headers and cookies, **FastAPI** also provides it at `fastapi.Response`. + +/// + +## Custom Headers { #custom-headers } + +Keep in mind that custom proprietary headers can be added [using the `X-` prefix](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers). + +But if you have custom headers that you want a client in a browser to be able to see, you need to add them to your CORS configurations (read more in [CORS (Cross-Origin Resource Sharing)](../tutorial/cors.md)), using the parameter `expose_headers` documented in [Starlette's CORS docs](https://www.starlette.dev/middleware/#corsmiddleware). diff --git a/docs/en/docs/advanced/security/http-basic-auth.md b/docs/en/docs/advanced/security/http-basic-auth.md new file mode 100644 index 0000000000000..01693e0a016a1 --- /dev/null +++ b/docs/en/docs/advanced/security/http-basic-auth.md @@ -0,0 +1,107 @@ +# HTTP Basic Auth { #http-basic-auth } + +For the simplest cases, you can use HTTP Basic Auth. + +In HTTP Basic Auth, the application expects a header that contains a username and a password. + +If it doesn't receive it, it returns an HTTP 401 "Unauthorized" error. + +And returns a header `WWW-Authenticate` with a value of `Basic`, and an optional `realm` parameter. + +That tells the browser to show the integrated prompt for a username and password. + +Then, when you type that username and password, the browser sends them in the header automatically. + +## Simple HTTP Basic Auth { #simple-http-basic-auth } + +* Import `HTTPBasic` and `HTTPBasicCredentials`. +* Create a "`security` scheme" using `HTTPBasic`. +* Use that `security` with a dependency in your *path operation*. +* It returns an object of type `HTTPBasicCredentials`: + * It contains the `username` and `password` sent. + +{* ../../docs_src/security/tutorial006_an_py310.py hl[4,8,12] *} + +When you try to open the URL for the first time (or click the "Execute" button in the docs) the browser will ask you for your username and password: + + + +## Check the username { #check-the-username } + +Here's a more complete example. + +Use a dependency to check if the username and password are correct. + +For this, use the Python standard module [`secrets`](https://docs.python.org/3/library/secrets.html) to check the username and password. + +`secrets.compare_digest()` needs to take `bytes` or a `str` that only contains ASCII characters (the ones in English), this means it wouldn't work with characters like `á`, as in `Sebastián`. + +To handle that, we first convert the `username` and `password` to `bytes` encoding them with UTF-8. + +Then we can use `secrets.compare_digest()` to ensure that `credentials.username` is `"stanleyjobson"`, and that `credentials.password` is `"swordfish"`. + +{* ../../docs_src/security/tutorial007_an_py310.py hl[1,12:24] *} + +This would be similar to: + +```Python +if not (credentials.username == "stanleyjobson") or not (credentials.password == "swordfish"): + # Return some error + ... +``` + +But by using the `secrets.compare_digest()` it will be secure against a type of attacks called "timing attacks". + +### Timing Attacks { #timing-attacks } + +But what's a "timing attack"? + +Let's imagine some attackers are trying to guess the username and password. + +And they send a request with a username `johndoe` and a password `love123`. + +Then the Python code in your application would be equivalent to something like: + +```Python +if "johndoe" == "stanleyjobson" and "love123" == "swordfish": + ... +``` + +But right at the moment Python compares the first `j` in `johndoe` to the first `s` in `stanleyjobson`, it will return `False`, because it already knows that those two strings are not the same, thinking that "there's no need to waste more computation comparing the rest of the letters". And your application will say "Incorrect username or password". + +But then the attackers try with username `stanleyjobsox` and password `love123`. + +And your application code does something like: + +```Python +if "stanleyjobsox" == "stanleyjobson" and "love123" == "swordfish": + ... +``` + +Python will have to compare the whole `stanleyjobso` in both `stanleyjobsox` and `stanleyjobson` before realizing that both strings are not the same. So it will take some extra microseconds to reply back "Incorrect username or password". + +#### The time to answer helps the attackers { #the-time-to-answer-helps-the-attackers } + +At that point, by noticing that the server took some microseconds longer to send the "Incorrect username or password" response, the attackers will know that they got _something_ right, some of the initial letters were right. + +And then they can try again knowing that it's probably something more similar to `stanleyjobsox` than to `johndoe`. + +#### A "professional" attack { #a-professional-attack } + +Of course, the attackers would not try all this by hand, they would write a program to do it, possibly with thousands or millions of tests per second. And they would get just one extra correct letter at a time. + +But doing that, in some minutes or hours the attackers would have guessed the correct username and password, with the "help" of our application, just using the time taken to answer. + +#### Fix it with `secrets.compare_digest()` { #fix-it-with-secrets-compare-digest } + +But in our code we are actually using `secrets.compare_digest()`. + +In short, it will take the same time to compare `stanleyjobsox` to `stanleyjobson` than it takes to compare `johndoe` to `stanleyjobson`. And the same for the password. + +That way, using `secrets.compare_digest()` in your application code, it will be safe against this whole range of security attacks. + +### Return the error { #return-the-error } + +After detecting that the credentials are incorrect, return an `HTTPException` with a status code 401 (the same returned when no credentials are provided) and add the header `WWW-Authenticate` to make the browser show the login prompt again: + +{* ../../docs_src/security/tutorial007_an_py310.py hl[26:30] *} diff --git a/docs/en/docs/advanced/security/index.md b/docs/en/docs/advanced/security/index.md new file mode 100644 index 0000000000000..4f6959a9a4c70 --- /dev/null +++ b/docs/en/docs/advanced/security/index.md @@ -0,0 +1,19 @@ +# Advanced Security { #advanced-security } + +## Additional Features { #additional-features } + +There are some extra features to handle security apart from the ones covered in the [Tutorial - User Guide: Security](../../tutorial/security/index.md). + +/// tip + +The next sections are **not necessarily "advanced"**. + +And it's possible that for your use case, the solution is in one of them. + +/// + +## Read the Tutorial first { #read-the-tutorial-first } + +The next sections assume you already read the main [Tutorial - User Guide: Security](../../tutorial/security/index.md). + +They are all based on the same concepts, but allow some extra functionalities. diff --git a/docs/en/docs/advanced/security/oauth2-scopes.md b/docs/en/docs/advanced/security/oauth2-scopes.md new file mode 100644 index 0000000000000..60e900d2cde7e --- /dev/null +++ b/docs/en/docs/advanced/security/oauth2-scopes.md @@ -0,0 +1,274 @@ +# OAuth2 scopes { #oauth2-scopes } + +You can use OAuth2 scopes directly with **FastAPI**, they are integrated to work seamlessly. + +This would allow you to have a more fine-grained permission system, following the OAuth2 standard, integrated into your OpenAPI application (and the API docs). + +OAuth2 with scopes is the mechanism used by many big authentication providers, like Facebook, Google, GitHub, Microsoft, X (Twitter), etc. They use it to provide specific permissions to users and applications. + +Every time you "log in with" Facebook, Google, GitHub, Microsoft, X (Twitter), that application is using OAuth2 with scopes. + +In this section you will see how to manage authentication and authorization with the same OAuth2 with scopes in your **FastAPI** application. + +/// warning + +This is a more or less advanced section. If you are just starting, you can skip it. + +You don't necessarily need OAuth2 scopes, and you can handle authentication and authorization however you want. + +But OAuth2 with scopes can be nicely integrated into your API (with OpenAPI) and your API docs. + +Nevertheless, you still enforce those scopes, or any other security/authorization requirement, however you need, in your code. + +In many cases, OAuth2 with scopes can be an overkill. + +But if you know you need it, or you are curious, keep reading. + +/// + +## OAuth2 scopes and OpenAPI { #oauth2-scopes-and-openapi } + +The OAuth2 specification defines "scopes" as a list of strings separated by spaces. + +The content of each of these strings can have any format, but should not contain spaces. + +These scopes represent "permissions". + +In OpenAPI (e.g. the API docs), you can define "security schemes". + +When one of these security schemes uses OAuth2, you can also declare and use scopes. + +Each "scope" is just a string (without spaces). + +They are normally used to declare specific security permissions, for example: + +* `users:read` or `users:write` are common examples. +* `instagram_basic` is used by Facebook / Instagram. +* `https://www.googleapis.com/auth/drive` is used by Google. + +/// note + +In OAuth2 a "scope" is just a string that declares a specific permission required. + +It doesn't matter if it has other characters like `:` or if it is a URL. + +Those details are implementation specific. + +For OAuth2 they are just strings. + +/// + +## Global view { #global-view } + +First, let's quickly see the parts that change from the examples in the main **Tutorial - User Guide** for [OAuth2 with Password (and hashing), Bearer with JWT tokens](../../tutorial/security/oauth2-jwt.md). Now using OAuth2 scopes: + +{* ../../docs_src/security/tutorial005_an_py310.py hl[5,9,13,47,65,106,108:116,122:126,130:136,141,157] *} + +Now let's review those changes step by step. + +## OAuth2 Security scheme { #oauth2-security-scheme } + +The first change is that now we are declaring the OAuth2 security scheme with two available scopes, `me` and `items`. + +The `scopes` parameter receives a `dict` with each scope as a key and the description as the value: + +{* ../../docs_src/security/tutorial005_an_py310.py hl[63:66] *} + +Because we are now declaring those scopes, they will show up in the API docs when you log-in/authorize. + +And you will be able to select which scopes you want to give access to: `me` and `items`. + +This is the same mechanism used when you give permissions while logging in with Facebook, Google, GitHub, etc: + + + +## JWT token with scopes { #jwt-token-with-scopes } + +Now, modify the token *path operation* to return the scopes requested. + +We are still using the same `OAuth2PasswordRequestForm`. It includes a property `scopes` with a `list` of `str`, with each scope it received in the request. + +And we return the scopes as part of the JWT token. + +/// danger + +For simplicity, here we are just adding the scopes received directly to the token. + +But in your application, for security, you should make sure you only add the scopes that the user is actually able to have, or the ones you have predefined. + +/// + +{* ../../docs_src/security/tutorial005_an_py310.py hl[157] *} + +## Declare scopes in *path operations* and dependencies { #declare-scopes-in-path-operations-and-dependencies } + +Now we declare that the *path operation* for `/users/me/items/` requires the scope `items`. + +For this, we import and use `Security` from `fastapi`. + +You can use `Security` to declare dependencies (just like `Depends`), but `Security` also receives a parameter `scopes` with a list of scopes (strings). + +In this case, we pass a dependency function `get_current_active_user` to `Security` (the same way we would do with `Depends`). + +But we also pass a `list` of scopes, in this case with just one scope: `items` (it could have more). + +And the dependency function `get_current_active_user` can also declare sub-dependencies, not only with `Depends` but also with `Security`. Declaring its own sub-dependency function (`get_current_user`), and more scope requirements. + +In this case, it requires the scope `me` (it could require more than one scope). + +/// note + +You don't necessarily need to add different scopes in different places. + +We are doing it here to demonstrate how **FastAPI** handles scopes declared at different levels. + +/// + +{* ../../docs_src/security/tutorial005_an_py310.py hl[5,141,172] *} + +/// note | Technical Details + +`Security` is actually a subclass of `Depends`, and it has just one extra parameter that we'll see later. + +But by using `Security` instead of `Depends`, **FastAPI** will know that it can declare security scopes, use them internally, and document the API with OpenAPI. + +But when you import `Query`, `Path`, `Depends`, `Security` and others from `fastapi`, those are actually functions that return special classes. + +/// + +## Use `SecurityScopes` { #use-securityscopes } + +Now update the dependency `get_current_user`. + +This is the one used by the dependencies above. + +Here's where we are using the same OAuth2 scheme we created before, declaring it as a dependency: `oauth2_scheme`. + +Because this dependency function doesn't have any scope requirements itself, we can use `Depends` with `oauth2_scheme`, we don't have to use `Security` when we don't need to specify security scopes. + +We also declare a special parameter of type `SecurityScopes`, imported from `fastapi.security`. + +This `SecurityScopes` class is similar to `Request` (`Request` was used to get the request object directly). + +{* ../../docs_src/security/tutorial005_an_py310.py hl[9,106] *} + +## Use the `scopes` { #use-the-scopes } + +The parameter `security_scopes` will be of type `SecurityScopes`. + +It will have a property `scopes` with a list containing all the scopes required by itself and all the dependencies that use this as a sub-dependency. That means, all the "dependants"... this might sound confusing, it is explained again later below. + +The `security_scopes` object (of class `SecurityScopes`) also provides a `scope_str` attribute with a single string, containing those scopes separated by spaces (we are going to use it). + +We create an `HTTPException` that we can reuse (`raise`) later at several points. + +In this exception, we include the scopes required (if any) as a string separated by spaces (using `scope_str`). We put that string containing the scopes in the `WWW-Authenticate` header (this is part of the spec). + +{* ../../docs_src/security/tutorial005_an_py310.py hl[106,108:116] *} + +## Verify the `username` and data shape { #verify-the-username-and-data-shape } + +We verify that we get a `username`, and extract the scopes. + +And then we validate that data with the Pydantic model (catching the `ValidationError` exception), and if we get an error reading the JWT token or validating the data with Pydantic, we raise the `HTTPException` we created before. + +For that, we update the Pydantic model `TokenData` with a new property `scopes`. + +By validating the data with Pydantic we can make sure that we have, for example, exactly a `list` of `str` with the scopes and a `str` with the `username`. + +Instead of, for example, a `dict`, or something else, as it could break the application at some point later, making it a security risk. + +We also verify that we have a user with that username, and if not, we raise that same exception we created before. + +{* ../../docs_src/security/tutorial005_an_py310.py hl[47,117:129] *} + +## Verify the `scopes` { #verify-the-scopes } + +We now verify that all the scopes required, by this dependency and all the dependants (including *path operations*), are included in the scopes provided in the token received, otherwise raise an `HTTPException`. + +For this, we use `security_scopes.scopes`, that contains a `list` with all these scopes as `str`. + +{* ../../docs_src/security/tutorial005_an_py310.py hl[130:136] *} + +## Dependency tree and scopes { #dependency-tree-and-scopes } + +Let's review again this dependency tree and the scopes. + +As the `get_current_active_user` dependency has `get_current_user` as a sub-dependency, the scope `"me"` declared at `get_current_active_user` will be included in the list of required scopes in the `security_scopes.scopes` passed to `get_current_user`. + +The *path operation* itself also declares a scope, `"items"`, so this will also be in the list of `security_scopes.scopes` passed to `get_current_user`. + +Here's what the hierarchy of dependencies and scopes looks like: + +* The *path operation* `read_own_items` has: + * Required scopes `["items"]` with the dependency: + * `get_current_active_user`: + * The dependency function `get_current_active_user` has: + * Required scopes `["me"]` with the dependency: + * `get_current_user`: + * The dependency function `get_current_user` has: + * No scopes required by itself. + * A dependency using `oauth2_scheme`. + * A `security_scopes` parameter of type `SecurityScopes`: + * This `security_scopes` parameter has a property `scopes` with a `list` containing all these scopes declared above, so: + * `security_scopes.scopes` will contain `["me", "items"]` for the *path operation* `read_own_items`. + * `security_scopes.scopes` will contain `["me"]` for the *path operation* `read_users_me`, because it is declared in the dependency `get_current_active_user`. + * `security_scopes.scopes` will contain `[]` (nothing) for the *path operation* `read_system_status`, because it didn't declare any `Security` with `scopes`, and its dependency, `get_current_user`, doesn't declare any `scopes` either. + +/// tip + +The important and "magic" thing here is that `get_current_user` will have a different list of `scopes` to check for each *path operation*. + +All depending on the `scopes` declared in each *path operation* and each dependency in the dependency tree for that specific *path operation*. + +/// + +## More details about `SecurityScopes` { #more-details-about-securityscopes } + +You can use `SecurityScopes` at any point, and in multiple places, it doesn't have to be at the "root" dependency. + +It will always have the security scopes declared in the current `Security` dependencies and all the dependants for **that specific** *path operation* and **that specific** dependency tree. + +Because the `SecurityScopes` will have all the scopes declared by dependants, you can use it to verify that a token has the required scopes in a central dependency function, and then declare different scope requirements in different *path operations*. + +They will be checked independently for each *path operation*. + +## Check it { #check-it } + +If you open the API docs, you can authenticate and specify which scopes you want to authorize. + + + +If you don't select any scope, you will be "authenticated", but when you try to access `/users/me/` or `/users/me/items/` you will get an error saying that you don't have enough permissions. You will still be able to access `/status/`. + +And if you select the scope `me` but not the scope `items`, you will be able to access `/users/me/` but not `/users/me/items/`. + +That's what would happen to a third party application that tried to access one of these *path operations* with a token provided by a user, depending on how many permissions the user gave the application. + +## About third party integrations { #about-third-party-integrations } + +In this example we are using the OAuth2 "password" flow. + +This is appropriate when we are logging in to our own application, probably with our own frontend. + +Because we can trust it to receive the `username` and `password`, as we control it. + +But if you are building an OAuth2 application that others would connect to (i.e., if you are building an authentication provider equivalent to Facebook, Google, GitHub, etc.) you should use one of the other flows. + +The most common is the implicit flow. + +The most secure is the code flow, but it's more complex to implement as it requires more steps. As it is more complex, many providers end up suggesting the implicit flow. + +/// note + +It's common that each authentication provider names their flows in a different way, to make it part of their brand. + +But in the end, they are implementing the same OAuth2 standard. + +/// + +**FastAPI** includes utilities for all these OAuth2 authentication flows in `fastapi.security.oauth2`. + +## `Security` in decorator `dependencies` { #security-in-decorator-dependencies } + +The same way you can define a `list` of `Depends` in the decorator's `dependencies` parameter (as explained in [Dependencies in path operation decorators](../../tutorial/dependencies/dependencies-in-path-operation-decorators.md)), you could also use `Security` with `scopes` there. diff --git a/docs/en/docs/advanced/settings.md b/docs/en/docs/advanced/settings.md new file mode 100644 index 0000000000000..ff313f0881eb9 --- /dev/null +++ b/docs/en/docs/advanced/settings.md @@ -0,0 +1,302 @@ +# Settings and Environment Variables { #settings-and-environment-variables } + +In many cases your application could need some external settings or configurations, for example secret keys, database credentials, credentials for email services, etc. + +Most of these settings are variable (can change), like database URLs. And many could be sensitive, like secrets. + +For this reason it's common to provide them in environment variables that are read by the application. + +/// tip + +To understand environment variables you can read [Environment Variables](../environment-variables.md). + +/// + +## Types and validation { #types-and-validation } + +These environment variables can only handle text strings, as they are external to Python and have to be compatible with other programs and the rest of the system (and even with different operating systems, such as Linux, Windows, and macOS). + +That means that any value read in Python from an environment variable will be a `str`, and any conversion to a different type or any validation has to be done in code. + +## Pydantic `Settings` { #pydantic-settings } + +Fortunately, Pydantic provides a great utility to handle these settings coming from environment variables with [Pydantic: Settings management](https://docs.pydantic.dev/latest/concepts/pydantic_settings/). + +### Install `pydantic-settings` { #install-pydantic-settings } + +First, make sure you create your [virtual environment](../virtual-environments.md), activate it, and then install the `pydantic-settings` package: + +
+ +```console +$ pip install pydantic-settings +---> 100% +``` + +
+ +It also comes included when you install the `all` extras with: + +
+ +```console +$ pip install "fastapi[all]" +---> 100% +``` + +
+ +### Create the `Settings` object { #create-the-settings-object } + +Import `BaseSettings` from Pydantic and create a sub-class, very much like with a Pydantic model. + +The same way as with Pydantic models, you declare class attributes with type annotations, and possibly default values. + +You can use all the same validation features and tools you use for Pydantic models, like different data types and additional validations with `Field()`. + +{* ../../docs_src/settings/tutorial001_py310.py hl[2,5:8,11] *} + +/// tip + +If you want something quick to copy and paste, don't use this example, use the last one below. + +/// + +Then, when you create an instance of that `Settings` class (in this case, in the `settings` object), Pydantic will read the environment variables in a case-insensitive way, so, an upper-case variable `APP_NAME` will still be read for the attribute `app_name`. + +Next it will convert and validate the data. So, when you use that `settings` object, you will have data of the types you declared (e.g. `items_per_user` will be an `int`). + +### Use the `settings` { #use-the-settings } + +Then you can use the new `settings` object in your application: + +{* ../../docs_src/settings/tutorial001_py310.py hl[18:20] *} + +### Run the server { #run-the-server } + +Next, you would run the server passing the configurations as environment variables, for example you could set an `ADMIN_EMAIL` and `APP_NAME` with: + +
+ +```console +$ ADMIN_EMAIL="deadpool@example.com" APP_NAME="ChimichangApp" fastapi run main.py + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +/// tip + +To set multiple env vars for a single command just separate them with a space, and put them all before the command. + +/// + +And then the `admin_email` setting would be set to `"deadpool@example.com"`. + +The `app_name` would be `"ChimichangApp"`. + +And the `items_per_user` would keep its default value of `50`. + +## Settings in another module { #settings-in-another-module } + +You could put those settings in another module file as you saw in [Bigger Applications - Multiple Files](../tutorial/bigger-applications.md). + +For example, you could have a file `config.py` with: + +{* ../../docs_src/settings/app01_py310/config.py *} + +And then use it in a file `main.py`: + +{* ../../docs_src/settings/app01_py310/main.py hl[3,11:13] *} + +/// tip + +You would also need a file `__init__.py` as you saw in [Bigger Applications - Multiple Files](../tutorial/bigger-applications.md). + +/// + +## Settings in a dependency { #settings-in-a-dependency } + +In some occasions it might be useful to provide the settings from a dependency, instead of having a global object with `settings` that is used everywhere. + +This could be especially useful during testing, as it's very easy to override a dependency with your own custom settings. + +### The config file { #the-config-file } + +Coming from the previous example, your `config.py` file could look like: + +{* ../../docs_src/settings/app02_an_py310/config.py hl[10] *} + +Notice that now we don't create a default instance `settings = Settings()`. + +### The main app file { #the-main-app-file } + +Now we create a dependency that returns a new `config.Settings()`. + +{* ../../docs_src/settings/app02_an_py310/main.py hl[6,12:13] *} + +/// tip + +We'll discuss the `@lru_cache` in a bit. + +For now you can assume `get_settings()` is a normal function. + +/// + +And then we can require it from the *path operation function* as a dependency and use it anywhere we need it. + +{* ../../docs_src/settings/app02_an_py310/main.py hl[17,19:21] *} + +### Settings and testing { #settings-and-testing } + +Then it would be very easy to provide a different settings object during testing by creating a dependency override for `get_settings`: + +{* ../../docs_src/settings/app02_an_py310/test_main.py hl[9:10,13,21] *} + +In the dependency override we set a new value for the `admin_email` when creating the new `Settings` object, and then we return that new object. + +Then we can test that it is used. + +## Reading a `.env` file { #reading-a-env-file } + +If you have many settings that possibly change a lot, maybe in different environments, it might be useful to put them on a file and then read them from it as if they were environment variables. + +This practice is common enough that it has a name, these environment variables are commonly placed in a file `.env`, and the file is called a "dotenv". + +/// tip + +A file starting with a dot (`.`) is a hidden file in Unix-like systems, like Linux and macOS. + +But a dotenv file doesn't really have to have that exact filename. + +/// + +Pydantic has support for reading from these types of files using an external library. You can read more at [Pydantic Settings: Dotenv (.env) support](https://docs.pydantic.dev/latest/concepts/pydantic_settings/#dotenv-env-support). + +/// tip + +For this to work, you need to `pip install python-dotenv`. + +/// + +### The `.env` file { #the-env-file } + +You could have a `.env` file with: + +```bash +ADMIN_EMAIL="deadpool@example.com" +APP_NAME="ChimichangApp" +``` + +### Read settings from `.env` { #read-settings-from-env } + +And then update your `config.py` with: + +{* ../../docs_src/settings/app03_an_py310/config.py hl[9] *} + +/// tip + +The `model_config` attribute is used just for Pydantic configuration. You can read more at [Pydantic: Concepts: Configuration](https://docs.pydantic.dev/latest/concepts/config/). + +/// + +Here we define the config `env_file` inside of your Pydantic `Settings` class, and set the value to the filename with the dotenv file we want to use. + +### Creating the `Settings` only once with `lru_cache` { #creating-the-settings-only-once-with-lru-cache } + +Reading a file from disk is normally a costly (slow) operation, so you probably want to do it only once and then reuse the same settings object, instead of reading it for each request. + +But every time we do: + +```Python +Settings() +``` + +a new `Settings` object would be created, and at creation it would read the `.env` file again. + +If the dependency function was just like: + +```Python +def get_settings(): + return Settings() +``` + +we would create that object for each request, and we would be reading the `.env` file for each request. ⚠️ + +But as we are using the `@lru_cache` decorator on top, the `Settings` object will be created only once, the first time it's called. ✔️ + +{* ../../docs_src/settings/app03_an_py310/main.py hl[1,11] *} + +Then for any subsequent call of `get_settings()` in the dependencies for the next requests, instead of executing the internal code of `get_settings()` and creating a new `Settings` object, it will return the same object that was returned on the first call, again and again. + +#### `lru_cache` Technical Details { #lru-cache-technical-details } + +`@lru_cache` modifies the function it decorates to return the same value that was returned the first time, instead of computing it again, executing the code of the function every time. + +So, the function below it will be executed once for each combination of arguments. And then the values returned by each of those combinations of arguments will be used again and again whenever the function is called with exactly the same combination of arguments. + +For example, if you have a function: + +```Python +@lru_cache +def say_hi(name: str, salutation: str = "Ms."): + return f"Hello {salutation} {name}" +``` + +your program could execute like this: + +```mermaid +sequenceDiagram + +participant code as Code +participant function as say_hi() +participant execute as Execute function + + rect rgba(0, 255, 0, .1) + code ->> function: say_hi(name="Camila") + function ->> execute: execute function code + execute ->> code: return the result + end + + rect rgba(0, 255, 255, .1) + code ->> function: say_hi(name="Camila") + function ->> code: return stored result + end + + rect rgba(0, 255, 0, .1) + code ->> function: say_hi(name="Rick") + function ->> execute: execute function code + execute ->> code: return the result + end + + rect rgba(0, 255, 0, .1) + code ->> function: say_hi(name="Rick", salutation="Mr.") + function ->> execute: execute function code + execute ->> code: return the result + end + + rect rgba(0, 255, 255, .1) + code ->> function: say_hi(name="Rick") + function ->> code: return stored result + end + + rect rgba(0, 255, 255, .1) + code ->> function: say_hi(name="Camila") + function ->> code: return stored result + end +``` + +In the case of our dependency `get_settings()`, the function doesn't even take any arguments, so it always returns the same value. + +That way, it behaves almost as if it was just a global variable. But as it uses a dependency function, then we can override it easily for testing. + +`@lru_cache` is part of `functools` which is part of Python's standard library, you can read more about it in the [Python docs for `@lru_cache`](https://docs.python.org/3/library/functools.html#functools.lru_cache). + +## Recap { #recap } + +You can use Pydantic Settings to handle the settings or configurations for your application, with all the power of Pydantic models. + +* By using a dependency you can simplify testing. +* You can use `.env` files with it. +* Using `@lru_cache` lets you avoid reading the dotenv file again and again for each request, while allowing you to override it during testing. diff --git a/docs/en/docs/advanced/stream-data.md b/docs/en/docs/advanced/stream-data.md new file mode 100644 index 0000000000000..40ea3374344d5 --- /dev/null +++ b/docs/en/docs/advanced/stream-data.md @@ -0,0 +1,117 @@ +# Stream Data { #stream-data } + +If you want to stream data that can be structured as JSON, you should [Stream JSON Lines](../tutorial/stream-json-lines.md). + +But if you want to **stream pure binary data** or strings, here's how you can do it. + +/// note + +Added in FastAPI 0.134.0. + +/// + +## Use Cases { #use-cases } + +You could use this if you want to stream pure strings, for example directly from the output of an **AI LLM** service. + +You could also use it to stream **large binary files**, where you stream each chunk of data as you read it, without having to read it all into memory at once. + +You could also stream **video** or **audio** this way, it could even be generated as you process and send it. + +## A `StreamingResponse` with `yield` { #a-streamingresponse-with-yield } + +If you declare a `response_class=StreamingResponse` in your *path operation function*, you can use `yield` to send each chunk of data in turn. + +{* ../../docs_src/stream_data/tutorial001_py310.py ln[1:23] hl[20,23] *} + +FastAPI will give each chunk of data to the `StreamingResponse` as is, it won't try to convert it to JSON or anything similar. + +### Non-async *path operation functions* { #non-async-path-operation-functions } + +You can also use regular `def` functions (without `async`), and use `yield` the same way. + +{* ../../docs_src/stream_data/tutorial001_py310.py ln[26:29] hl[27] *} + +### No Annotation { #no-annotation } + +You don't really need to declare the return type annotation for streaming binary data. + +As FastAPI will not try to convert the data to JSON with Pydantic or serialize it in any way, in this case, the type annotation is only for your editor and tools to use, it won't be used by FastAPI. + +{* ../../docs_src/stream_data/tutorial001_py310.py ln[32:35] hl[33] *} + +This also means that with `StreamingResponse` you have the **freedom** and **responsibility** to produce and encode the data bytes exactly as you need them to be sent, independent of the type annotations. 🤓 + +### Stream Bytes { #stream-bytes } + +One of the main use cases would be to stream `bytes` instead of strings, you can of course do it. + +{* ../../docs_src/stream_data/tutorial001_py310.py ln[44:47] hl[47] *} + +## A Custom `PNGStreamingResponse` { #a-custom-pngstreamingresponse } + +In the examples above, the data bytes were streamed, but the response didn't have a `Content-Type` header, so the client didn't know what type of data it was receiving. + +You can create a custom sub-class of `StreamingResponse` that sets the `Content-Type` header to the type of data you're streaming. + +For example, you can create a `PNGStreamingResponse` that sets the `Content-Type` header to `image/png` using the `media_type` attribute: + +{* ../../docs_src/stream_data/tutorial002_py310.py ln[6,19:20] hl[20] *} + +Then you can use this new class in `response_class=PNGStreamingResponse` in your *path operation function*: + +{* ../../docs_src/stream_data/tutorial002_py310.py ln[23:27] hl[23] *} + +### Simulate a File { #simulate-a-file } + +In this example, we are simulating a file with `io.BytesIO`, which is a file-like object that lives only in memory, but lets us use the same interface. + +For example, we can iterate over it to consume its contents, as we could with a file. + +{* ../../docs_src/stream_data/tutorial002_py310.py ln[1:27] hl[3,12:13,25] *} + +/// note | Technical Details + +The other two variables, `image_base64` and `binary_image`, are an image encoded in Base64, and then converted to bytes, to then pass it to `io.BytesIO`. + +Only so that it can live in the same file for this example and you can copy it and run it as is. 🥚 + +/// + +By using a `with` block, we make sure that the file-like object is closed after the generator function (the function with `yield`) is done. So, after it finishes sending the response. + +It wouldn't be that important in this specific example because it's a fake in-memory file (with `io.BytesIO`), but with a real file, it would be important to make sure the file is closed after the work with it is done. + +### Files and Async { #files-and-async } + +In most cases, file-like objects are not compatible with async and await by default. + +For example, they don't have an `await file.read()`, or `async for chunk in file`. + +And in many cases, reading them would be a blocking operation (that could block the event loop), because they are read from disk or from the network. + +/// note + +The example above is actually an exception, because the `io.BytesIO` object is already in memory, so reading it won't block anything. + +But in many cases reading a file or a file-like object would block. + +/// + +To avoid blocking the event loop, you can simply declare the *path operation function* with regular `def` instead of `async def`, that way FastAPI will run it on a threadpool worker, to avoid blocking the main loop. + +{* ../../docs_src/stream_data/tutorial002_py310.py ln[30:34] hl[31] *} + +/// tip + +If you need to call blocking code from inside of an async function, or an async function from inside of a blocking function, you could use [Asyncer](https://asyncer.tiangolo.com), a sibling library to FastAPI. + +/// + +### `yield from` { #yield-from } + +When you are iterating over something, like a file-like object, and then you are doing `yield` for each item, you could also use `yield from` to yield each item directly and skip the `for` loop. + +This is not particular to FastAPI, it's just Python, but it's a nice trick to know. 😎 + +{* ../../docs_src/stream_data/tutorial002_py310.py ln[37:40] hl[40] *} diff --git a/docs/en/docs/advanced/strict-content-type.md b/docs/en/docs/advanced/strict-content-type.md new file mode 100644 index 0000000000000..a0d9a142384eb --- /dev/null +++ b/docs/en/docs/advanced/strict-content-type.md @@ -0,0 +1,88 @@ +# Strict Content-Type Checking { #strict-content-type-checking } + +By default, **FastAPI** uses strict `Content-Type` header checking for JSON request bodies, this means that JSON requests **must** include a valid `Content-Type` header (e.g. `application/json`) in order for the body to be parsed as JSON. + +## CSRF Risk { #csrf-risk } + +This default behavior provides protection against a class of **Cross-Site Request Forgery (CSRF)** attacks in a very specific scenario. + +These attacks exploit the fact that browsers allow scripts to send requests without doing any CORS preflight check when they: + +* don't have a `Content-Type` header (e.g. using `fetch()` with a `Blob` body) +* and don't send any authentication credentials. + +This type of attack is mainly relevant when: + +* the application is running locally (e.g. on `localhost`) or in an internal network +* and the application doesn't have any authentication, it expects that any request from the same network can be trusted. + +## Example Attack { #example-attack } + +Imagine you build a way to run a local AI agent. + +It provides an API at + +``` +http://localhost:8000/v1/agents/multivac +``` + +There's also a frontend at + +``` +http://localhost:8000 +``` + +/// tip + +Note that both have the same host. + +/// + +Then using the frontend you can make the AI agent do things on your behalf. + +As it's running **locally**, and not in the open internet, you decide to **not have any authentication** set up, just trusting the access to the local network. + +Then one of your users could install it and run it locally. + +Then they could open a malicious website, e.g. something like + +``` +https://evilhackers.example.com +``` + +And that malicious website sends requests using `fetch()` with a `Blob` body to the local API at + +``` +http://localhost:8000/v1/agents/multivac +``` + +Even though the host of the malicious website and the local app is different, the browser won't trigger a CORS preflight request because: + +* It's running without any authentication, it doesn't have to send any credentials. +* The browser thinks it's not sending JSON (because of the missing `Content-Type` header). + +Then the malicious website could make the local AI agent send angry messages to the user's ex-boss... or worse. 😅 + +## Open Internet { #open-internet } + +If your app is in the open internet, you wouldn't "trust the network" and let anyone send privileged requests without authentication. + +Attackers could simply run a script to send requests to your API, no need for browser interaction, so you are probably already securing any privileged endpoints. + +In that case **this attack / risk doesn't apply to you**. + +This risk and attack is mainly relevant when the app runs on the **local network** and that is the **only assumed protection**. + +## Allowing Requests Without Content-Type { #allowing-requests-without-content-type } + +If you need to support clients that don't send a `Content-Type` header, you can disable strict checking by setting `strict_content_type=False`: + +{* ../../docs_src/strict_content_type/tutorial001_py310.py hl[4] *} + +With this setting, requests without a `Content-Type` header will have their body parsed as JSON, which is the same behavior as older versions of FastAPI. + +/// note + +This behavior and configuration was added in FastAPI 0.132.0. + +/// diff --git a/docs/en/docs/advanced/sub-applications.md b/docs/en/docs/advanced/sub-applications.md new file mode 100644 index 0000000000000..a391c7c24569b --- /dev/null +++ b/docs/en/docs/advanced/sub-applications.md @@ -0,0 +1,67 @@ +# Sub Applications - Mounts { #sub-applications-mounts } + +If you need to have two independent FastAPI applications, with their own independent OpenAPI and their own docs UIs, you can have a main app and "mount" one (or more) sub-application(s). + +## Mounting a **FastAPI** application { #mounting-a-fastapi-application } + +"Mounting" means adding a completely "independent" application in a specific path, that then takes care of handling everything under that path, with the _path operations_ declared in that sub-application. + +### Top-level application { #top-level-application } + +First, create the main, top-level, **FastAPI** application, and its *path operations*: + +{* ../../docs_src/sub_applications/tutorial001_py310.py hl[3, 6:8] *} + +### Sub-application { #sub-application } + +Then, create your sub-application, and its *path operations*. + +This sub-application is just another standard FastAPI application, but this is the one that will be "mounted": + +{* ../../docs_src/sub_applications/tutorial001_py310.py hl[11, 14:16] *} + +### Mount the sub-application { #mount-the-sub-application } + +In your top-level application, `app`, mount the sub-application, `subapi`. + +In this case, it will be mounted at the path `/subapi`: + +{* ../../docs_src/sub_applications/tutorial001_py310.py hl[11, 19] *} + +### Check the automatic API docs { #check-the-automatic-api-docs } + +Now, run the `fastapi` command: + +
+ +```console +$ fastapi dev + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +And open the docs at [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs). + +You will see the automatic API docs for the main app, including only its own _path operations_: + + + +And then, open the docs for the sub-application, at [http://127.0.0.1:8000/subapi/docs](http://127.0.0.1:8000/subapi/docs). + +You will see the automatic API docs for the sub-application, including only its own _path operations_, all under the correct sub-path prefix `/subapi`: + + + +If you try interacting with any of the two user interfaces, they will work correctly, because the browser will be able to talk to each specific app or sub-app. + +### Technical Details: `root_path` { #technical-details-root-path } + +When you mount a sub-application as described above, FastAPI will take care of communicating the mount path for the sub-application using a mechanism from the ASGI specification called a `root_path`. + +That way, the sub-application will know to use that path prefix for the docs UI. + +And the sub-application could also have its own mounted sub-applications and everything would work correctly, because FastAPI handles all these `root_path`s automatically. + +You will learn more about the `root_path` and how to use it explicitly in the section about [Behind a Proxy](behind-a-proxy.md). diff --git a/docs/en/docs/advanced/templates.md b/docs/en/docs/advanced/templates.md new file mode 100644 index 0000000000000..6570865e27ed0 --- /dev/null +++ b/docs/en/docs/advanced/templates.md @@ -0,0 +1,126 @@ +# Templates { #templates } + +You can use any template engine you want with **FastAPI**. + +A common choice is Jinja2, the same one used by Flask and other tools. + +There are utilities to configure it easily that you can use directly in your **FastAPI** application (provided by Starlette). + +## Install dependencies { #install-dependencies } + +Make sure you create a [virtual environment](../virtual-environments.md), activate it, and install `jinja2`: + +
+ +```console +$ pip install jinja2 + +---> 100% +``` + +
+ +## Using `Jinja2Templates` { #using-jinja2templates } + +* Import `Jinja2Templates`. +* Create a `templates` object that you can reuse later. +* Declare a `Request` parameter in the *path operation* that will return a template. +* Use the `templates` you created to render and return a `TemplateResponse`, pass the name of the template, the request object, and a "context" dictionary with key-value pairs to be used inside of the Jinja2 template. + +{* ../../docs_src/templates/tutorial001_py310.py hl[4,11,15:18] *} + +/// note + +Before FastAPI 0.108.0, Starlette 0.29.0, the `name` was the first parameter. + +Also, before that, in previous versions, the `request` object was passed as part of the key-value pairs in the context for Jinja2. + +/// + +/// tip + +By declaring `response_class=HTMLResponse` the docs UI will be able to know that the response will be HTML. + +/// + +/// note | Technical Details + +You could also use `from starlette.templating import Jinja2Templates`. + +**FastAPI** provides the same `starlette.templating` as `fastapi.templating` just as a convenience for you, the developer. But most of the available responses come directly from Starlette. The same with `Request` and `StaticFiles`. + +/// + +## Writing templates { #writing-templates } + +Then you can write a template at `templates/item.html` with, for example: + +```jinja hl_lines="7" +{!../../docs_src/templates/templates/item.html!} +``` + +### Template Context Values { #template-context-values } + +In the HTML that contains: + +{% raw %} + +```jinja +Item ID: {{ id }} +``` + +{% endraw %} + +...it will show the `id` taken from the "context" `dict` you passed: + +```Python +{"id": id} +``` + +For example, with an ID of `42`, this would render: + +```html +Item ID: 42 +``` + +### Template `url_for` Arguments { #template-url-for-arguments } + +You can also use `url_for()` inside of the template, it takes as arguments the same arguments that would be used by your *path operation function*. + +So, the section with: + +{% raw %} + +```jinja + +``` + +{% endraw %} + +...will generate a link to the same URL that would be handled by the *path operation function* `read_item(id=id)`. + +For example, with an ID of `42`, this would render: + +```html + +``` + +## Templates and static files { #templates-and-static-files } + +You can also use `url_for()` inside of the template, and use it, for example, with the `StaticFiles` you mounted with the `name="static"`. + +```jinja hl_lines="4" +{!../../docs_src/templates/templates/item.html!} +``` + +In this example, it would link to a CSS file at `static/styles.css` with: + +```CSS hl_lines="4" +{!../../docs_src/templates/static/styles.css!} +``` + +And because you are using `StaticFiles`, that CSS file would be served automatically by your **FastAPI** application at the URL `/static/styles.css`. + +## More details { #more-details } + +For more details, including how to test templates, check [Starlette's docs on templates](https://www.starlette.dev/templates/). diff --git a/docs/en/docs/advanced/testing-dependencies.md b/docs/en/docs/advanced/testing-dependencies.md new file mode 100644 index 0000000000000..b52b47c969df8 --- /dev/null +++ b/docs/en/docs/advanced/testing-dependencies.md @@ -0,0 +1,53 @@ +# Testing Dependencies with Overrides { #testing-dependencies-with-overrides } + +## Overriding dependencies during testing { #overriding-dependencies-during-testing } + +There are some scenarios where you might want to override a dependency during testing. + +You don't want the original dependency to run (nor any of the sub-dependencies it might have). + +Instead, you want to provide a different dependency that will be used only during tests (possibly only some specific tests), and will provide a value that can be used where the value of the original dependency was used. + +### Use cases: external service { #use-cases-external-service } + +An example could be that you have an external authentication provider that you need to call. + +You send it a token and it returns an authenticated user. + +This provider might be charging you per request, and calling it might take some extra time than if you had a fixed mock user for tests. + +You probably want to test the external provider once, but not necessarily call it for every test that runs. + +In this case, you can override the dependency that calls that provider, and use a custom dependency that returns a mock user, only for your tests. + +### Use the `app.dependency_overrides` attribute { #use-the-app-dependency-overrides-attribute } + +For these cases, your **FastAPI** application has an attribute `app.dependency_overrides`, it is a simple `dict`. + +To override a dependency for testing, you put as a key the original dependency (a function), and as the value, your dependency override (another function). + +And then **FastAPI** will call that override instead of the original dependency. + +{* ../../docs_src/dependency_testing/tutorial001_an_py310.py hl[26:27,30] *} + +/// tip + +You can set a dependency override for a dependency used anywhere in your **FastAPI** application. + +The original dependency could be used in a *path operation function*, a *path operation decorator* (when you don't use the return value), a `.include_router()` call, etc. + +FastAPI will still be able to override it. + +/// + +Then you can reset your overrides (remove them) by setting `app.dependency_overrides` to be an empty `dict`: + +```Python +app.dependency_overrides = {} +``` + +/// tip + +If you want to override a dependency only during some tests, you can set the override at the beginning of the test (inside the test function) and reset it at the end (at the end of the test function). + +/// diff --git a/docs/en/docs/advanced/testing-events.md b/docs/en/docs/advanced/testing-events.md new file mode 100644 index 0000000000000..ba42e716952c0 --- /dev/null +++ b/docs/en/docs/advanced/testing-events.md @@ -0,0 +1,12 @@ +# Testing Events: lifespan and startup - shutdown { #testing-events-lifespan-and-startup-shutdown } + +When you need `lifespan` to run in your tests, you can use the `TestClient` with a `with` statement: + +{* ../../docs_src/app_testing/tutorial004_py310.py hl[9:15,18,27:28,30:32,41:43] *} + + +You can read more details about the ["Running lifespan in tests in the official Starlette documentation site."](https://www.starlette.dev/lifespan/#running-lifespan-in-tests) + +For the deprecated `startup` and `shutdown` events, you can use the `TestClient` as follows: + +{* ../../docs_src/app_testing/tutorial003_py310.py hl[9:12,20:24] *} diff --git a/docs/en/docs/advanced/testing-websockets.md b/docs/en/docs/advanced/testing-websockets.md new file mode 100644 index 0000000000000..040f8e3b0790c --- /dev/null +++ b/docs/en/docs/advanced/testing-websockets.md @@ -0,0 +1,13 @@ +# Testing WebSockets { #testing-websockets } + +You can use the same `TestClient` to test WebSockets. + +For this, you use the `TestClient` in a `with` statement, connecting to the WebSocket: + +{* ../../docs_src/app_testing/tutorial002_py310.py hl[27:31] *} + +/// note + +For more details, check Starlette's documentation for [testing WebSockets](https://www.starlette.dev/testclient/#testing-websocket-sessions). + +/// diff --git a/docs/en/docs/advanced/using-request-directly.md b/docs/en/docs/advanced/using-request-directly.md new file mode 100644 index 0000000000000..75d859f830985 --- /dev/null +++ b/docs/en/docs/advanced/using-request-directly.md @@ -0,0 +1,56 @@ +# Using the Request Directly { #using-the-request-directly } + +Up to now, you have been declaring the parts of the request that you need with their types. + +Taking data from: + +* The path as parameters. +* Headers. +* Cookies. +* etc. + +And by doing so, **FastAPI** is validating that data, converting it and generating documentation for your API automatically. + +But there are situations where you might need to access the `Request` object directly. + +## Details about the `Request` object { #details-about-the-request-object } + +As **FastAPI** is actually **Starlette** underneath, with a layer of several tools on top, you can use Starlette's [`Request`](https://www.starlette.dev/requests/) object directly when you need to. + +It would also mean that if you get data from the `Request` object directly (for example, read the body) it won't be validated, converted or documented (with OpenAPI, for the automatic API user interface) by FastAPI. + +Although any other parameter declared normally (for example, the body with a Pydantic model) would still be validated, converted, annotated, etc. + +But there are specific cases where it's useful to get the `Request` object. + +## Use the `Request` object directly { #use-the-request-object-directly } + +Let's imagine you want to get the client's IP address/host inside of your *path operation function*. + +For that you need to access the request directly. + +{* ../../docs_src/using_request_directly/tutorial001_py310.py hl[1,7:8] *} + +By declaring a *path operation function* parameter with the type being the `Request` **FastAPI** will know to pass the `Request` in that parameter. + +/// tip + +Note that in this case, we are declaring a path parameter beside the request parameter. + +So, the path parameter will be extracted, validated, converted to the specified type and annotated with OpenAPI. + +The same way, you can declare any other parameter as normally, and additionally, get the `Request` too. + +/// + +## `Request` documentation { #request-documentation } + +You can read more details about the [`Request` object in the official Starlette documentation site](https://www.starlette.dev/requests/). + +/// note | Technical Details + +You could also use `from starlette.requests import Request`. + +**FastAPI** provides it directly just as a convenience for you, the developer. But it comes directly from Starlette. + +/// diff --git a/docs/en/docs/advanced/websockets.md b/docs/en/docs/advanced/websockets.md new file mode 100644 index 0000000000000..6f4603e6ac3c9 --- /dev/null +++ b/docs/en/docs/advanced/websockets.md @@ -0,0 +1,186 @@ +# WebSockets { #websockets } + +You can use [WebSockets](https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API) with **FastAPI**. + +## Install `websockets` { #install-websockets } + +Make sure you create a [virtual environment](../virtual-environments.md), activate it, and install `websockets` (a Python library that makes it easy to use the "WebSocket" protocol): + +
+ +```console +$ pip install websockets + +---> 100% +``` + +
+ +## WebSockets client { #websockets-client } + +### In production { #in-production } + +In your production system, you probably have a frontend created with a modern framework like React, Vue.js or Angular. + +And to communicate using WebSockets with your backend you would probably use your frontend's utilities. + +Or you might have a native mobile application that communicates with your WebSocket backend directly, in native code. + +Or you might have any other way to communicate with the WebSocket endpoint. + +--- + +But for this example, we'll use a very simple HTML document with some JavaScript, all inside a long string. + +This, of course, is not optimal and you wouldn't use it for production. + +In production you would have one of the options above. + +But it's the simplest way to focus on the server-side of WebSockets and have a working example: + +{* ../../docs_src/websockets_/tutorial001_py310.py hl[2,6:38,41:43] *} + +## Create a `websocket` { #create-a-websocket } + +In your **FastAPI** application, create a `websocket`: + +{* ../../docs_src/websockets_/tutorial001_py310.py hl[1,46:47] *} + +/// note | Technical Details + +You could also use `from starlette.websockets import WebSocket`. + +**FastAPI** provides the same `WebSocket` directly just as a convenience for you, the developer. But it comes directly from Starlette. + +/// + +## Await for messages and send messages { #await-for-messages-and-send-messages } + +In your WebSocket route you can `await` for messages and send messages. + +{* ../../docs_src/websockets_/tutorial001_py310.py hl[48:52] *} + +You can receive and send binary, text, and JSON data. + +## Try it { #try-it } + +Put your code in a file `main.py` and then run your application: + +
+ +```console +$ fastapi dev + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +Open your browser at [http://127.0.0.1:8000](http://127.0.0.1:8000). + +You will see a simple page like: + + + +You can type messages in the input box, and send them: + + + +And your **FastAPI** application with WebSockets will respond back: + + + +You can send (and receive) many messages: + + + +And all of them will use the same WebSocket connection. + +## Using `Depends` and others { #using-depends-and-others } + +In WebSocket endpoints you can import from `fastapi` and use: + +* `Depends` +* `Security` +* `Cookie` +* `Header` +* `Path` +* `Query` + +They work the same way as for other FastAPI endpoints/*path operations*: + +{* ../../docs_src/websockets_/tutorial002_an_py310.py hl[68:69,82] *} + +/// note + +As this is a WebSocket it doesn't really make sense to raise an `HTTPException`, instead we raise a `WebSocketException`. + +You can use a closing code from the [valid codes defined in the specification](https://tools.ietf.org/html/rfc6455#section-7.4.1). + +/// + +### Try the WebSockets with dependencies { #try-the-websockets-with-dependencies } + +Run your application: + +
+ +```console +$ fastapi dev + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +Open your browser at [http://127.0.0.1:8000](http://127.0.0.1:8000). + +There you can set: + +* The "Item ID", used in the path. +* The "Token" used as a query parameter. + +/// tip + +Notice that the query `token` will be handled by a dependency. + +/// + +With that you can connect the WebSocket and then send and receive messages: + + + +## Handling disconnections and multiple clients { #handling-disconnections-and-multiple-clients } + +When a WebSocket connection is closed, the `await websocket.receive_text()` will raise a `WebSocketDisconnect` exception, which you can then catch and handle like in this example. + +{* ../../docs_src/websockets_/tutorial003_py310.py hl[79:81] *} + +To try it out: + +* Open the app with several browser tabs. +* Write messages from them. +* Then close one of the tabs. + +That will raise the `WebSocketDisconnect` exception, and all the other clients will receive a message like: + +``` +Client #1596980209979 left the chat +``` + +/// tip + +The app above is a minimal and simple example to demonstrate how to handle and broadcast messages to several WebSocket connections. + +But keep in mind that, as everything is handled in memory, in a single list, it will only work while the process is running, and will only work with a single process. + +If you need something easy to integrate with FastAPI but that is more robust, supported by Redis, PostgreSQL or others, check [encode/broadcaster](https://github.com/encode/broadcaster). + +/// + +## More info { #more-info } + +To learn more about the options, check Starlette's documentation for: + +* [The `WebSocket` class](https://www.starlette.dev/websockets/). +* [Class-based WebSocket handling](https://www.starlette.dev/endpoints/#websocketendpoint). diff --git a/docs/en/docs/advanced/wsgi.md b/docs/en/docs/advanced/wsgi.md new file mode 100644 index 0000000000000..8dcc3c4010441 --- /dev/null +++ b/docs/en/docs/advanced/wsgi.md @@ -0,0 +1,51 @@ +# Including WSGI - Flask, Django, others { #including-wsgi-flask-django-others } + +You can mount WSGI applications as you saw with [Sub Applications - Mounts](sub-applications.md), [Behind a Proxy](behind-a-proxy.md). + +For that, you can use the `WSGIMiddleware` and use it to wrap your WSGI application, for example, Flask, Django, etc. + +## Using `WSGIMiddleware` { #using-wsgimiddleware } + +/// note + +This requires installing `a2wsgi` for example with `pip install a2wsgi`. + +/// + +You need to import `WSGIMiddleware` from `a2wsgi`. + +Then wrap the WSGI (e.g. Flask) app with the middleware. + +And then mount that under a path. + +{* ../../docs_src/wsgi/tutorial001_py310.py hl[1,3,23] *} + +/// note + +Previously, it was recommended to use `WSGIMiddleware` from `fastapi.middleware.wsgi`, but it is now deprecated. + +It's advised to use the `a2wsgi` package instead. The usage remains the same. + +Just ensure that you have the `a2wsgi` package installed and import `WSGIMiddleware` correctly from `a2wsgi`. + +/// + +## Check it { #check-it } + +Now, every request under the path `/v1/` will be handled by the Flask application. + +And the rest will be handled by **FastAPI**. + +If you run it and go to [http://localhost:8000/v1/](http://localhost:8000/v1/) you will see the response from Flask: + +```txt +Hello, World from Flask! +``` + +And if you go to [http://localhost:8000/v2](http://localhost:8000/v2) you will see the response from FastAPI: + +```JSON +{ + "message": "Hello World" +} +``` diff --git a/docs/en/docs/alternatives.md b/docs/en/docs/alternatives.md new file mode 100644 index 0000000000000..d4942a37bd0ac --- /dev/null +++ b/docs/en/docs/alternatives.md @@ -0,0 +1,485 @@ +# Alternatives, Inspiration and Comparisons { #alternatives-inspiration-and-comparisons } + +What inspired **FastAPI**, how it compares to alternatives and what it learned from them. + +## Intro { #intro } + +**FastAPI** wouldn't exist if not for the previous work of others. + +There have been many tools created before that have helped inspire its creation. + +I have been avoiding the creation of a new framework for several years. First I tried to solve all the features covered by **FastAPI** using many different frameworks, plug-ins, and tools. + +But at some point, there was no other option than creating something that provided all these features, taking the best ideas from previous tools, and combining them in the best way possible, using language features that weren't even available before (Python 3.6+ type hints). + +## Previous tools { #previous-tools } + +### [Django](https://www.djangoproject.com/) { #django } + +It's the most popular Python framework and is widely trusted. It is used to build systems like Instagram. + +It's relatively tightly coupled with relational databases (like MySQL or PostgreSQL), so, having a NoSQL database (like Couchbase, MongoDB, Cassandra, etc) as the main store engine is not very easy. + +It was created to generate the HTML in the backend, not to create APIs used by a modern frontend (like React, Vue.js and Angular) or by other systems (like IoT devices) communicating with it. + +### [Django REST Framework](https://www.django-rest-framework.org/) { #django-rest-framework } + +Django REST Framework was created to be a flexible toolkit for building Web APIs using Django underneath, to improve its API capabilities. + +It is used by many companies including Mozilla, Red Hat and Eventbrite. + +It was one of the first examples of **automatic API documentation**, and this was specifically one of the first ideas that inspired "the search for" **FastAPI**. + +/// note + +Django REST Framework was created by Tom Christie. The same creator of Starlette and Uvicorn, on which **FastAPI** is based. + +/// + +/// tip | Inspired **FastAPI** to + +Have an automatic API documentation web user interface. + +/// + +### [Flask](https://flask.palletsprojects.com) { #flask } + +Flask is a "microframework", it doesn't include database integrations nor many of the things that come by default in Django. + +This simplicity and flexibility allow doing things like using NoSQL databases as the main data storage system. + +As it is very simple, it's relatively intuitive to learn, although the documentation gets somewhat technical at some points. + +It is also commonly used for other applications that don't necessarily need a database, user management, or any of the many features that come pre-built in Django. Although many of these features can be added with plug-ins. + +This decoupling of parts, and being a "microframework" that could be extended to cover exactly what is needed was a key feature that I wanted to keep. + +Given the simplicity of Flask, it seemed like a good match for building APIs. The next thing to find was a "Django REST Framework" for Flask. + +/// tip | Inspired **FastAPI** to + +Be a micro-framework. Making it easy to mix and match the tools and parts needed. + +Have a simple and easy to use routing system. + +/// + +### [Requests](https://requests.readthedocs.io) { #requests } + +**FastAPI** is not actually an alternative to **Requests**. Their scope is very different. + +It would actually be common to use Requests *inside* of a FastAPI application. + +But still, FastAPI got quite some inspiration from Requests. + +**Requests** is a library to *interact* with APIs (as a client), while **FastAPI** is a library to *build* APIs (as a server). + +They are, more or less, at opposite ends, complementing each other. + +Requests has a very simple and intuitive design, it's very easy to use, with sensible defaults. But at the same time, it's very powerful and customizable. + +That's why, as said in the official website: + +> Requests is one of the most downloaded Python packages of all time + +The way you use it is very simple. For example, to do a `GET` request, you would write: + +```Python +response = requests.get("http://example.com/some/url") +``` + +The FastAPI counterpart API *path operation* could look like: + +```Python hl_lines="1" +@app.get("/some/url") +def read_url(): + return {"message": "Hello World"} +``` + +See the similarities in `requests.get(...)` and `@app.get(...)`. + +/// tip | Inspired **FastAPI** to + +* Have a simple and intuitive API. +* Use HTTP method names (operations) directly, in a straightforward and intuitive way. +* Have sensible defaults, but powerful customizations. + +/// + +### [Swagger](https://swagger.io/) / [OpenAPI](https://github.com/OAI/OpenAPI-Specification/) { #swagger-openapi } + +The main feature I wanted from Django REST Framework was the automatic API documentation. + +Then I found that there was a standard to document APIs, using JSON (or YAML, an extension of JSON) called Swagger. + +And there was a web user interface for Swagger APIs already created. So, being able to generate Swagger documentation for an API would allow using this web user interface automatically. + +At some point, Swagger was given to the Linux Foundation, to be renamed OpenAPI. + +That's why when talking about version 2.0 it's common to say "Swagger", and for version 3+ "OpenAPI". + +/// tip | Inspired **FastAPI** to + +Adopt and use an open standard for API specifications, instead of a custom schema. + +And integrate standards-based user interface tools: + +* [Swagger UI](https://github.com/swagger-api/swagger-ui) +* [ReDoc](https://github.com/Rebilly/ReDoc) + +These two were chosen for being fairly popular and stable, but doing a quick search, you could find dozens of alternative user interfaces for OpenAPI (that you can use with **FastAPI**). + +/// + +### Flask REST frameworks { #flask-rest-frameworks } + +There are several Flask REST frameworks, but after investing the time and work into investigating them, I found that many are discontinued or abandoned, with several standing issues that made them unfit. + +### [Marshmallow](https://marshmallow.readthedocs.io/en/stable/) { #marshmallow } + +One of the main features needed by API systems is data "serialization" which is taking data from the code (Python) and converting it into something that can be sent through the network. For example, converting an object containing data from a database into a JSON object. Converting `datetime` objects into strings, etc. + +Another big feature needed by APIs is data validation, making sure that the data is valid, given certain parameters. For example, that some field is an `int`, and not some random string. This is especially useful for incoming data. + +Without a data validation system, you would have to do all the checks by hand, in code. + +These features are what Marshmallow was built to provide. It is a great library, and I have used it a lot before. + +But it was created before there existed Python type hints. So, to define every schema you need to use specific utils and classes provided by Marshmallow. + +/// tip | Inspired **FastAPI** to + +Use code to define "schemas" that provide data types and validation, automatically. + +/// + +### [Webargs](https://webargs.readthedocs.io/en/latest/) { #webargs } + +Another big feature required by APIs is parsing data from incoming requests. + +Webargs is a tool that was made to provide that on top of several frameworks, including Flask. + +It uses Marshmallow underneath to do the data validation. And it was created by the same developers. + +It's a great tool and I have used it a lot too, before having **FastAPI**. + +/// note + +Webargs was created by the same Marshmallow developers. + +/// + +/// tip | Inspired **FastAPI** to + +Have automatic validation of incoming request data. + +/// + +### [APISpec](https://apispec.readthedocs.io/en/stable/) { #apispec } + +Marshmallow and Webargs provide validation, parsing and serialization as plug-ins. + +But documentation is still missing. Then APISpec was created. + +It is a plug-in for many frameworks (and there's a plug-in for Starlette too). + +The way it works is that you write the definition of the schema using YAML format inside the docstring of each function handling a route. + +And it generates OpenAPI schemas. + +That's how it works in Flask, Starlette, Responder, etc. + +But then, we have again the problem of having a micro-syntax, inside of a Python string (a big YAML). + +The editor can't help much with that. And if we modify parameters or Marshmallow schemas and forget to also modify that YAML docstring, the generated schema would be obsolete. + +/// note + +APISpec was created by the same Marshmallow developers. + +/// + +/// tip | Inspired **FastAPI** to + +Support the open standard for APIs, OpenAPI. + +/// + +### [Flask-apispec](https://flask-apispec.readthedocs.io/en/latest/) { #flask-apispec } + +It's a Flask plug-in, that ties together Webargs, Marshmallow and APISpec. + +It uses the information from Webargs and Marshmallow to automatically generate OpenAPI schemas, using APISpec. + +It's a great tool, very underrated. It should be way more popular than many Flask plug-ins out there. It might be due to its documentation being too concise and abstract. + +This solved having to write YAML (another syntax) inside of Python docstrings. + +This combination of Flask, Flask-apispec with Marshmallow and Webargs was my favorite backend stack until building **FastAPI**. + +Using it led to the creation of several Flask full-stack generators. These are the main stacks I (and several external teams) have been using up to now: + +* [https://github.com/tiangolo/full-stack](https://github.com/tiangolo/full-stack) +* [https://github.com/tiangolo/full-stack-flask-couchbase](https://github.com/tiangolo/full-stack-flask-couchbase) +* [https://github.com/tiangolo/full-stack-flask-couchdb](https://github.com/tiangolo/full-stack-flask-couchdb) + +And these same full-stack generators were the base of the [**FastAPI** Project Generators](project-generation.md). + +/// note + +Flask-apispec was created by the same Marshmallow developers. + +/// + +/// tip | Inspired **FastAPI** to + +Generate the OpenAPI schema automatically, from the same code that defines serialization and validation. + +/// + +### [NestJS](https://nestjs.com/) (and [Angular](https://angular.io/)) { #nestjs-and-angular } + +This isn't even Python, NestJS is a JavaScript (TypeScript) NodeJS framework inspired by Angular. + +It achieves something somewhat similar to what can be done with Flask-apispec. + +It has an integrated dependency injection system, inspired by Angular 2. It requires pre-registering the "injectables" (like all the other dependency injection systems I know), so, it adds to the verbosity and code repetition. + +As the parameters are described with TypeScript types (similar to Python type hints), editor support is quite good. + +But as TypeScript data is not preserved after compilation to JavaScript, it cannot rely on the types to define validation, serialization and documentation at the same time. Due to this and some design decisions, to get validation, serialization and automatic schema generation, it's needed to add decorators in many places. So, it becomes quite verbose. + +It can't handle nested models very well. So, if the JSON body in the request is a JSON object that has inner fields that in turn are nested JSON objects, it cannot be properly documented and validated. + +/// tip | Inspired **FastAPI** to + +Use Python types to have great editor support. + +Have a powerful dependency injection system. Find a way to minimize code repetition. + +/// + +### [Sanic](https://sanic.readthedocs.io/en/latest/) { #sanic } + +It was one of the first extremely fast Python frameworks based on `asyncio`. It was made to be very similar to Flask. + +/// note | Technical Details + +It used [`uvloop`](https://github.com/MagicStack/uvloop) instead of the default Python `asyncio` loop. That's what made it so fast. + +It clearly inspired Uvicorn and Starlette, that are currently faster than Sanic in open benchmarks. + +/// + +/// tip | Inspired **FastAPI** to + +Find a way to have a crazy performance. + +That's why **FastAPI** is based on Starlette, as it is the fastest framework available (tested by third-party benchmarks). + +/// + +### [Falcon](https://falconframework.org/) { #falcon } + +Falcon is another high performance Python framework, it is designed to be minimal, and work as the foundation of other frameworks like Hug. + +It is designed to have functions that receive two parameters, one "request" and one "response". Then you "read" parts from the request, and "write" parts to the response. Because of this design, it is not possible to declare request parameters and bodies with standard Python type hints as function parameters. + +So, data validation, serialization, and documentation, have to be done in code, not automatically. Or they have to be implemented as a framework on top of Falcon, like Hug. This same distinction happens in other frameworks that are inspired by Falcon's design, of having one request object and one response object as parameters. + +/// tip | Inspired **FastAPI** to + +Find ways to get great performance. + +Along with Hug (as Hug is based on Falcon) inspired **FastAPI** to declare a `response` parameter in functions. + +Although in FastAPI it's optional, and is used mainly to set headers, cookies, and alternative status codes. + +/// + +### [Molten](https://moltenframework.com/) { #molten } + +I discovered Molten in the first stages of building **FastAPI**. And it has quite similar ideas: + +* Based on Python type hints. +* Validation and documentation from these types. +* Dependency Injection system. + +It doesn't use a data validation, serialization and documentation third-party library like Pydantic, it has its own. So, these data type definitions would not be reusable as easily. + +It requires a little bit more verbose configurations. And as it is based on WSGI (instead of ASGI), it is not designed to take advantage of the high performance provided by tools like Uvicorn, Starlette and Sanic. + +The dependency injection system requires pre-registration of the dependencies and the dependencies are solved based on the declared types. So, it's not possible to declare more than one "component" that provides a certain type. + +Routes are declared in a single place, using functions declared in other places (instead of using decorators that can be placed right on top of the function that handles the endpoint). This is closer to how Django does it than to how Flask (and Starlette) does it. It separates in the code things that are relatively tightly coupled. + +/// tip | Inspired **FastAPI** to + +Define extra validations for data types using the "default" value of model attributes. This improves editor support, and it was not available in Pydantic before. + +This actually inspired updating parts of Pydantic, to support the same validation declaration style (all this functionality is now already available in Pydantic). + +/// + +### [Hug](https://github.com/hugapi/hug) { #hug } + +Hug was one of the first frameworks to implement the declaration of API parameter types using Python type hints. This was a great idea that inspired other tools to do the same. + +It used custom types in its declarations instead of standard Python types, but it was still a huge step forward. + +It also was one of the first frameworks to generate a custom schema declaring the whole API in JSON. + +It was not based on a standard like OpenAPI and JSON Schema. So it wouldn't be straightforward to integrate it with other tools, like Swagger UI. But again, it was a very innovative idea. + +It has an interesting, uncommon feature: using the same framework, it's possible to create APIs and also CLIs. + +As it is based on the previous standard for synchronous Python web frameworks (WSGI), it can't handle Websockets and other things, although it still has high performance too. + +/// note + +Hug was created by Timothy Crosley, the same creator of [`isort`](https://github.com/timothycrosley/isort), a great tool to automatically sort imports in Python files. + +/// + +/// tip | Ideas inspiring **FastAPI** + +Hug inspired parts of APIStar, and was one of the tools I found most promising, alongside APIStar. + +Hug helped inspire **FastAPI** to use Python type hints to declare parameters, and to generate a schema defining the API automatically. + +Hug inspired **FastAPI** to declare a `response` parameter in functions to set headers and cookies. + +/// + +### [APIStar](https://github.com/encode/apistar) (<= 0.5) { #apistar-0-5 } + +Right before deciding to build **FastAPI** I found **APIStar** server. It had almost everything I was looking for and had a great design. + +It was one of the first implementations of a framework using Python type hints to declare parameters and requests that I ever saw (before NestJS and Molten). I found it more or less at the same time as Hug. But APIStar used the OpenAPI standard. + +It had automatic data validation, data serialization and OpenAPI schema generation based on the same type hints in several places. + +Body schema definitions didn't use the same Python type hints like Pydantic, it was a bit more similar to Marshmallow, so, editor support wouldn't be as good, but still, APIStar was the best available option. + +It had the best performance benchmarks at the time (only surpassed by Starlette). + +At first, it didn't have an automatic API documentation web UI, but I knew I could add Swagger UI to it. + +It had a dependency injection system. It required pre-registration of components, as other tools discussed above. But still, it was a great feature. + +I was never able to use it in a full project, as it didn't have security integration, so, I couldn't replace all the features I was having with the full-stack generators based on Flask-apispec. I had in my backlog of projects to create a pull request adding that functionality. + +But then, the project's focus shifted. + +It was no longer an API web framework, as the creator needed to focus on Starlette. + +Now APIStar is a set of tools to validate OpenAPI specifications, not a web framework. + +/// note + +APIStar was created by Tom Christie. The same guy that created: + +* Django REST Framework +* Starlette (on which **FastAPI** is based) +* Uvicorn (used by Starlette and **FastAPI**) + +/// + +/// tip | Inspired **FastAPI** to + +Exist. + +The idea of declaring multiple things (data validation, serialization and documentation) with the same Python types, that at the same time provided great editor support, was something I considered a brilliant idea. + +And after searching for a long time for a similar framework and testing many different alternatives, APIStar was the best option available. + +Then APIStar stopped existing as a server and Starlette was created, and was a new better foundation for such a system. That was the final inspiration to build **FastAPI**. + +I consider **FastAPI** a "spiritual successor" to APIStar, while improving and increasing the features, typing system, and other parts, based on the learnings from all these previous tools. + +/// + +## Used by **FastAPI** { #used-by-fastapi } + +### [Pydantic](https://docs.pydantic.dev/) { #pydantic } + +Pydantic is a library to define data validation, serialization and documentation (using JSON Schema) based on Python type hints. + +That makes it extremely intuitive. + +It is comparable to Marshmallow. Although it's faster than Marshmallow in benchmarks. And as it is based on the same Python type hints, the editor support is great. + +/// tip | **FastAPI** uses it to + +Handle all the data validation, data serialization and automatic model documentation (based on JSON Schema). + +**FastAPI** then takes that JSON Schema data and puts it in OpenAPI, apart from all the other things it does. + +/// + +### [Starlette](https://www.starlette.dev/) { #starlette } + +Starlette is a lightweight ASGI framework/toolkit, which is ideal for building high-performance asyncio services. + +It is very simple and intuitive. It's designed to be easily extensible, and have modular components. + +It has: + +* Seriously impressive performance. +* WebSocket support. +* In-process background tasks. +* Startup and shutdown events. +* Test client built on HTTPX. +* CORS, GZip, Static Files, Streaming responses. +* Session and Cookie support. +* 100% test coverage. +* 100% type annotated codebase. +* Few hard dependencies. + +Starlette is currently the fastest Python framework tested. Only surpassed by Uvicorn, which is not a framework, but a server. + +Starlette provides all the basic web microframework functionality. + +But it doesn't provide automatic data validation, serialization or documentation. + +That's one of the main things that **FastAPI** adds on top, all based on Python type hints (using Pydantic). That, plus the dependency injection system, security utilities, OpenAPI schema generation, etc. + +/// note | Technical Details + +ASGI is a new "standard" being developed by Django core team members. It is still not a "Python standard" (a PEP), although they are in the process of doing that. + +Nevertheless, it is already being used as a "standard" by several tools. This greatly improves interoperability, as you could switch Uvicorn for any other ASGI server (like Daphne or Hypercorn), or you could add ASGI compatible tools, like `python-socketio`. + +/// + +/// tip | **FastAPI** uses it to + +Handle all the core web parts. Adding features on top. + +The class `FastAPI` itself inherits directly from the class `Starlette`. + +So, anything that you can do with Starlette, you can do it directly with **FastAPI**, as it is basically Starlette on steroids. + +/// + +### [Uvicorn](https://www.uvicorn.dev/) { #uvicorn } + +Uvicorn is a lightning-fast ASGI server, built on uvloop and httptools. + +It is not a web framework, but a server. For example, it doesn't provide tools for routing by paths. That's something that a framework like Starlette (or **FastAPI**) would provide on top. + +It is the recommended server for Starlette and **FastAPI**. + +/// tip | **FastAPI** recommends it as + +The main web server to run **FastAPI** applications. + +You can also use the `--workers` command line option to have an asynchronous multi-process server. + +Check more details in the [Deployment](deployment/index.md) section. + +/// + +## Benchmarks and speed { #benchmarks-and-speed } + +To understand, compare, and see the difference between Uvicorn, Starlette and FastAPI, check the section about [Benchmarks](benchmarks.md). diff --git a/docs/en/docs/async.md b/docs/en/docs/async.md new file mode 100644 index 0000000000000..d975ddb53997c --- /dev/null +++ b/docs/en/docs/async.md @@ -0,0 +1,444 @@ +# Concurrency and async / await { #concurrency-and-async-await } + +Details about the `async def` syntax for *path operation functions* and some background about asynchronous code, concurrency, and parallelism. + +## In a hurry? { #in-a-hurry } + +TL;DR: + +If you are using third party libraries that tell you to call them with `await`, like: + +```Python +results = await some_library() +``` + +Then, declare your *path operation functions* with `async def` like: + +```Python hl_lines="2" +@app.get('/') +async def read_results(): + results = await some_library() + return results +``` + +/// note + +You can only use `await` inside of functions created with `async def`. + +/// + +--- + +If you are using a third party library that communicates with something (a database, an API, the file system, etc.) and doesn't have support for using `await`, (this is currently the case for most database libraries), then declare your *path operation functions* as normally, with just `def`, like: + +```Python hl_lines="2" +@app.get('/') +def results(): + results = some_library() + return results +``` + +--- + +If your application (somehow) doesn't have to communicate with anything else and wait for it to respond, use `async def`, even if you don't need to use `await` inside. + +--- + +If you just don't know, use normal `def`. + +--- + +**Note**: You can mix `def` and `async def` in your *path operation functions* as much as you need and define each one using the best option for you. FastAPI will do the right thing with them. + +Anyway, in any of the cases above, FastAPI will still work asynchronously and be extremely fast. + +But by following the steps above, it will be able to do some performance optimizations. + +## Technical Details { #technical-details } + +Modern versions of Python have support for **"asynchronous code"** using something called **"coroutines"**, with **`async` and `await`** syntax. + +Let's see that phrase by parts in the sections below: + +* **Asynchronous Code** +* **`async` and `await`** +* **Coroutines** + +## Asynchronous Code { #asynchronous-code } + +Asynchronous code just means that the language 💬 has a way to tell the computer / program 🤖 that at some point in the code, it 🤖 will have to wait for *something else* to finish somewhere else. Let's say that *something else* is called "slow-file" 📝. + +So, during that time, the computer can go and do some other work, while "slow-file" 📝 finishes. + +Then the computer / program 🤖 will come back every time it has a chance because it's waiting again, or whenever it 🤖 finishes all the work it had at that point. And it 🤖 will see if any of the tasks it was waiting for have already finished, doing whatever it had to do. + +Next, it 🤖 takes the first task to finish (let's say, our "slow-file" 📝) and continues whatever it had to do with it. + +That "wait for something else" normally refers to I/O operations that are relatively "slow" (compared to the speed of the processor and the RAM memory), like waiting for: + +* the data from the client to be sent through the network +* the data sent by your program to be received by the client through the network +* the contents of a file on the disk to be read by the system and given to your program +* the contents your program gave to the system to be written to disk +* a remote API operation +* a database operation to finish +* a database query to return the results +* etc. + +As the execution time is consumed mostly by waiting for I/O operations, they call them "I/O bound" operations. + +It's called "asynchronous" because the computer / program doesn't have to be "synchronized" with the slow task, waiting for the exact moment that the task finishes, while doing nothing, to be able to take the task result and continue the work. + +Instead of that, by being an "asynchronous" system, once finished, the task can wait in line a little bit (some microseconds) for the computer / program to finish whatever it went to do, and then come back to take the results and continue working with them. + +For "synchronous" (contrary to "asynchronous") they commonly also use the term "sequential", because the computer / program follows all the steps in sequence before switching to a different task, even if those steps involve waiting. + +### Concurrency and Burgers { #concurrency-and-burgers } + +This idea of **asynchronous** code described above is also sometimes called **"concurrency"**. It is different from **"parallelism"**. + +**Concurrency** and **parallelism** both relate to "different things happening more or less at the same time". + +But the details between *concurrency* and *parallelism* are quite different. + +To see the difference, imagine the following story about burgers: + +### Concurrent Burgers { #concurrent-burgers } + +You go with your crush to get fast food, you stand in line while the cashier takes the orders from the people in front of you. 😍 + + + +Then it's your turn, you place your order of 2 very fancy burgers for your crush and you. 🍔🍔 + + + +The cashier says something to the cook in the kitchen so they know they have to prepare your burgers (even though they are currently preparing the ones for the previous clients). + + + +You pay. 💸 + +The cashier gives you the number of your turn. + + + +While you are waiting, you go with your crush and pick a table, you sit and talk with your crush for a long time (as your burgers are very fancy and take some time to prepare). + +As you are sitting at the table with your crush, while you wait for the burgers, you can spend that time admiring how awesome, cute and smart your crush is ✨😍✨. + + + +While waiting and talking to your crush, from time to time, you check the number displayed on the counter to see if it's your turn already. + +Then at some point, it finally is your turn. You go to the counter, get your burgers and come back to the table. + + + +You and your crush eat the burgers and have a nice time. ✨ + + + +/// note + +Beautiful illustrations by [Ketrina Thompson](https://www.instagram.com/ketrinadrawsalot). 🎨 + +/// + +--- + +Imagine you are the computer / program 🤖 in that story. + +While you are at the line, you are just idle 😴, waiting for your turn, not doing anything very "productive". But the line is fast because the cashier is only taking the orders (not preparing them), so that's fine. + +Then, when it's your turn, you do actual "productive" work, you process the menu, decide what you want, get your crush's choice, pay, check that you give the correct bill or card, check that you are charged correctly, check that the order has the correct items, etc. + +But then, even though you still don't have your burgers, your work with the cashier is "on pause" ⏸, because you have to wait 🕙 for your burgers to be ready. + +But as you go away from the counter and sit at the table with a number for your turn, you can switch 🔀 your attention to your crush, and "work" ⏯ 🤓 on that. Then you are again doing something very "productive" as is flirting with your crush 😍. + +Then the cashier 💁 says "I'm finished with doing the burgers" by putting your number on the counter's display, but you don't jump like crazy immediately when the displayed number changes to your turn number. You know no one will steal your burgers because you have the number of your turn, and they have theirs. + +So you wait for your crush to finish the story (finish the current work ⏯ / task being processed 🤓), smile gently and say that you are going for the burgers ⏸. + +Then you go to the counter 🔀, to the initial task that is now finished ⏯, pick the burgers, say thanks and take them to the table. That finishes that step / task of interaction with the counter ⏹. That in turn, creates a new task, of "eating burgers" 🔀 ⏯, but the previous one of "getting burgers" is finished ⏹. + +### Parallel Burgers { #parallel-burgers } + +Now let's imagine these aren't "Concurrent Burgers", but "Parallel Burgers". + +You go with your crush to get parallel fast food. + +You stand in line while several (let's say 8) cashiers that at the same time are cooks take the orders from the people in front of you. + +Everyone before you is waiting for their burgers to be ready before leaving the counter because each of the 8 cashiers goes and prepares the burger right away before getting the next order. + + + +Then it's finally your turn, you place your order of 2 very fancy burgers for your crush and you. + +You pay 💸. + + + +The cashier goes to the kitchen. + +You wait, standing in front of the counter 🕙, so that no one else takes your burgers before you do, as there are no numbers for turns. + + + +As you and your crush are busy not letting anyone get in front of you and take your burgers whenever they arrive, you cannot pay attention to your crush. 😞 + +This is "synchronous" work, you are "synchronized" with the cashier/cook 👨‍🍳. You have to wait 🕙 and be there at the exact moment that the cashier/cook 👨‍🍳 finishes the burgers and gives them to you, or otherwise, someone else might take them. + + + +Then your cashier/cook 👨‍🍳 finally comes back with your burgers, after a long time waiting 🕙 there in front of the counter. + + + +You take your burgers and go to the table with your crush. + +You just eat them, and you are done. ⏹ + + + +There was not much talk or flirting as most of the time was spent waiting 🕙 in front of the counter. 😞 + +/// note + +Beautiful illustrations by [Ketrina Thompson](https://www.instagram.com/ketrinadrawsalot). 🎨 + +/// + +--- + +In this scenario of the parallel burgers, you are a computer / program 🤖 with two processors (you and your crush), both waiting 🕙 and dedicating their attention ⏯ to be "waiting on the counter" 🕙 for a long time. + +The fast food store has 8 processors (cashiers/cooks). While the concurrent burgers store might have had only 2 (one cashier and one cook). + +But still, the final experience is not the best. 😞 + +--- + +This would be the parallel equivalent story for burgers. 🍔 + +For a more "real life" example of this, imagine a bank. + +Up to recently, most of the banks had multiple cashiers 👨‍💼👨‍💼👨‍💼👨‍💼 and a big line 🕙🕙🕙🕙🕙🕙🕙🕙. + +All of the cashiers doing all the work with one client after the other 👨‍💼⏯. + +And you have to wait 🕙 in the line for a long time or you lose your turn. + +You probably wouldn't want to take your crush 😍 with you to run errands at the bank 🏦. + +### Burger Conclusion { #burger-conclusion } + +In this scenario of "fast food burgers with your crush", as there is a lot of waiting 🕙, it makes a lot more sense to have a concurrent system ⏸🔀⏯. + +This is the case for most of the web applications. + +Many, many users, but your server is waiting 🕙 for their not-so-good connection to send their requests. + +And then waiting 🕙 again for the responses to come back. + +This "waiting" 🕙 is measured in microseconds, but still, summing it all, it's a lot of waiting in the end. + +That's why it makes a lot of sense to use asynchronous ⏸🔀⏯ code for web APIs. + +This kind of asynchronicity is what made NodeJS popular (even though NodeJS is not parallel) and that's the strength of Go as a programming language. + +And that's the same level of performance you get with **FastAPI**. + +And as you can have parallelism and asynchronicity at the same time, you get higher performance than most of the tested NodeJS frameworks and on par with Go, which is a compiled language closer to C [(all thanks to Starlette)](https://www.techempower.com/benchmarks/#section=data-r17&hw=ph&test=query&l=zijmkf-1). + +### Is concurrency better than parallelism? { #is-concurrency-better-than-parallelism } + +Nope! That's not the moral of the story. + +Concurrency is different than parallelism. And it is better in **specific** scenarios that involve a lot of waiting. Because of that, it generally is a lot better than parallelism for web application development. But not for everything. + +So, to balance that out, imagine the following short story: + +> You have to clean a big, dirty house. + +*Yep, that's the whole story*. + +--- + +There's no waiting 🕙 anywhere, just a lot of work to be done, in multiple places of the house. + +You could have turns as in the burgers example, first the living room, then the kitchen, but as you are not waiting 🕙 for anything, just cleaning and cleaning, the turns wouldn't affect anything. + +It would take the same amount of time to finish with or without turns (concurrency) and you would have done the same amount of work. + +But in this case, if you could bring the 8 ex-cashier/cooks/now-cleaners, and each one of them (plus you) could take a zone of the house to clean it, you could do all the work in **parallel**, with the extra help, and finish much sooner. + +In this scenario, each one of the cleaners (including you) would be a processor, doing their part of the job. + +And as most of the execution time is taken by actual work (instead of waiting), and the work in a computer is done by a CPU, they call these problems "CPU bound". + +--- + +Common examples of CPU bound operations are things that require complex math processing. + +For example: + +* **Audio** or **image processing**. +* **Computer vision**: an image is composed of millions of pixels, each pixel has 3 values / colors, processing that normally requires computing something on those pixels, all at the same time. +* **Machine Learning**: it normally requires lots of "matrix" and "vector" multiplications. Think of a huge spreadsheet with numbers and multiplying all of them together at the same time. +* **Deep Learning**: this is a sub-field of Machine Learning, so, the same applies. It's just that there is not a single spreadsheet of numbers to multiply, but a huge set of them, and in many cases, you use a special processor to build and / or use those models. + +### Concurrency + Parallelism: Web + Machine Learning { #concurrency-parallelism-web-machine-learning } + +With **FastAPI** you can take advantage of concurrency that is very common for web development (the same main attraction of NodeJS). + +But you can also exploit the benefits of parallelism and multiprocessing (having multiple processes running in parallel) for **CPU bound** workloads like those in Machine Learning systems. + +That, plus the simple fact that Python is the main language for **Data Science**, Machine Learning and especially Deep Learning, makes FastAPI a very good match for Data Science / Machine Learning web APIs and applications (among many others). + +To see how to achieve this parallelism in production see the section about [Deployment](deployment/index.md). + +## `async` and `await` { #async-and-await } + +Modern versions of Python have a very intuitive way to define asynchronous code. This makes it look just like normal "sequential" code and do the "awaiting" for you at the right moments. + +When there is an operation that will require waiting before giving the results and has support for these new Python features, you can code it like: + +```Python +burgers = await get_burgers(2) +``` + +The key here is the `await`. It tells Python that it has to wait ⏸ for `get_burgers(2)` to finish doing its thing 🕙 before storing the results in `burgers`. With that, Python will know that it can go and do something else 🔀 ⏯ in the meanwhile (like receiving another request). + +For `await` to work, it has to be inside a function that supports this asynchronicity. To do that, you just declare it with `async def`: + +```Python hl_lines="1" +async def get_burgers(number: int): + # Do some asynchronous stuff to create the burgers + return burgers +``` + +...instead of `def`: + +```Python hl_lines="2" +# This is not asynchronous +def get_sequential_burgers(number: int): + # Do some sequential stuff to create the burgers + return burgers +``` + +With `async def`, Python knows that, inside that function, it has to be aware of `await` expressions, and that it can "pause" ⏸ the execution of that function and go do something else 🔀 before coming back. + +When you want to call an `async def` function, you have to "await" it. So, this won't work: + +```Python +# This won't work, because get_burgers was defined with: async def +burgers = get_burgers(2) +``` + +--- + +So, if you are using a library that tells you that you can call it with `await`, you need to create the *path operation functions* that use it with `async def`, like in: + +```Python hl_lines="2-3" +@app.get('/burgers') +async def read_burgers(): + burgers = await get_burgers(2) + return burgers +``` + +### More technical details { #more-technical-details } + +You might have noticed that `await` can only be used inside of functions defined with `async def`. + +But at the same time, functions defined with `async def` have to be "awaited". So, functions with `async def` can only be called inside of functions defined with `async def` too. + +So, about the egg and the chicken, how do you call the first `async` function? + +If you are working with **FastAPI** you don't have to worry about that, because that "first" function will be your *path operation function*, and FastAPI will know how to do the right thing. + +But if you want to use `async` / `await` without FastAPI, you can do it as well. + +### Write your own async code { #write-your-own-async-code } + +Starlette (and **FastAPI**) are based on [AnyIO](https://anyio.readthedocs.io/en/stable/), which makes it compatible with both Python's standard library [asyncio](https://docs.python.org/3/library/asyncio-task.html) and [Trio](https://trio.readthedocs.io/en/stable/). + +In particular, you can directly use [AnyIO](https://anyio.readthedocs.io/en/stable/) for your advanced concurrency use cases that require more advanced patterns in your own code. + +And even if you were not using FastAPI, you could also write your own async applications with [AnyIO](https://anyio.readthedocs.io/en/stable/) to be highly compatible and get its benefits (e.g. *structured concurrency*). + +I created another library on top of AnyIO, as a thin layer on top, to improve a bit the type annotations and get better **autocompletion**, **inline errors**, etc. It also has a friendly introduction and tutorial to help you **understand** and write **your own async code**: [Asyncer](https://asyncer.tiangolo.com/). It would be particularly useful if you need to **combine async code with regular** (blocking/synchronous) code. + +### Other forms of asynchronous code { #other-forms-of-asynchronous-code } + +This style of using `async` and `await` is relatively new in the language. + +But it makes working with asynchronous code a lot easier. + +This same syntax (or almost identical) was also included recently in modern versions of JavaScript (in Browser and NodeJS). + +But before that, handling asynchronous code was quite more complex and difficult. + +In previous versions of Python, you could have used threads or [Gevent](https://www.gevent.org/). But the code is way more complex to understand, debug, and think about. + +In previous versions of NodeJS / Browser JavaScript, you would have used "callbacks". Which leads to "callback hell". + +## Coroutines { #coroutines } + +**Coroutine** is just the very fancy term for the thing returned by an `async def` function. Python knows that it is something like a function, that it can start and that it will end at some point, but that it might be paused ⏸ internally too, whenever there is an `await` inside of it. + +But all this functionality of using asynchronous code with `async` and `await` is many times summarized as using "coroutines". It is comparable to the main key feature of Go, the "Goroutines". + +## Conclusion { #conclusion } + +Let's see the same phrase from above: + +> Modern versions of Python have support for **"asynchronous code"** using something called **"coroutines"**, with **`async` and `await`** syntax. + +That should make more sense now. ✨ + +All that is what powers FastAPI (through Starlette) and what makes it have such an impressive performance. + +## Very Technical Details { #very-technical-details } + +/// warning + +You can probably skip this. + +These are very technical details of how **FastAPI** works underneath. + +If you have quite some technical knowledge (coroutines, threads, blocking, etc.) and are curious about how FastAPI handles `async def` vs normal `def`, go ahead. + +/// + +### Path operation functions { #path-operation-functions } + +When you declare a *path operation function* with normal `def` instead of `async def`, it is run in an external threadpool that is then awaited, instead of being called directly (as it would block the server). + +If you are coming from another async framework that does not work in the way described above and you are used to defining trivial compute-only *path operation functions* with plain `def` for a tiny performance gain (about 100 nanoseconds), please note that in **FastAPI** the effect would be quite opposite. In these cases, it's better to use `async def` unless your *path operation functions* use code that performs blocking I/O. + +Still, in both situations, chances are that **FastAPI** will [still be faster](index.md#performance) than (or at least comparable to) your previous framework. + +### Dependencies { #dependencies } + +The same applies for [dependencies](tutorial/dependencies/index.md). If a dependency is a standard `def` function instead of `async def`, it is run in the external threadpool. + +### Sub-dependencies { #sub-dependencies } + +You can have multiple dependencies and [sub-dependencies](tutorial/dependencies/sub-dependencies.md) requiring each other (as parameters of the function definitions), some of them might be created with `async def` and some with normal `def`. It would still work, and the ones created with normal `def` would be called on an external thread (from the threadpool) instead of being "awaited". + +### Other utility functions { #other-utility-functions } + +Any other utility function that you call directly can be created with normal `def` or `async def` and FastAPI won't affect the way you call it. + +This is in contrast to the functions that FastAPI calls for you: *path operation functions* and dependencies. + +If your utility function is a normal function with `def`, it will be called directly (as you write it in your code), not in a threadpool, if the function is created with `async def` then you should `await` that function when you call it in your code. + +--- + +Again, these are very technical details that would probably be useful if you came searching for them. + +Otherwise, you should be good with the guidelines from the section above:
In a hurry?. diff --git a/docs/en/docs/benchmarks.md b/docs/en/docs/benchmarks.md new file mode 100644 index 0000000000000..5b37877b32963 --- /dev/null +++ b/docs/en/docs/benchmarks.md @@ -0,0 +1,34 @@ +# Benchmarks { #benchmarks } + +Independent TechEmpower benchmarks show **FastAPI** applications running under Uvicorn as [one of the fastest Python frameworks available](https://www.techempower.com/benchmarks/#section=test&runid=7464e520-0dc2-473d-bd34-dbdfd7e85911&hw=ph&test=query&l=zijzen-7), only below Starlette and Uvicorn themselves (used internally by FastAPI). + +But when checking benchmarks and comparisons you should keep the following in mind. + +## Benchmarks and speed { #benchmarks-and-speed } + +When you check the benchmarks, it is common to see several tools of different types compared as equivalent. + +Specifically, to see Uvicorn, Starlette and FastAPI compared together (among many other tools). + +The simpler the problem solved by the tool, the better performance it will get. And most of the benchmarks don't test the additional features provided by the tool. + +The hierarchy is like: + +* **Uvicorn**: an ASGI server + * **Starlette**: (uses Uvicorn) a web microframework + * **FastAPI**: (uses Starlette) an API microframework with several additional features for building APIs, with data validation, etc. + +* **Uvicorn**: + * Will have the best performance, as it doesn't have much extra code apart from the server itself. + * You wouldn't write an application in Uvicorn directly. That would mean that your code would have to include more or less, at least, all the code provided by Starlette (or **FastAPI**). And if you did that, your final application would have the same overhead as having used a framework and minimizing your app code and bugs. + * If you are comparing Uvicorn, compare it against Daphne, Hypercorn, uWSGI, etc. Application servers. +* **Starlette**: + * Will have the next best performance, after Uvicorn. In fact, Starlette uses Uvicorn to run. So, it probably can only get "slower" than Uvicorn by having to execute more code. + * But it provides you the tools to build simple web applications, with routing based on paths, etc. + * If you are comparing Starlette, compare it against Sanic, Flask, Django, etc. Web frameworks (or microframeworks). +* **FastAPI**: + * The same way that Starlette uses Uvicorn and cannot be faster than it, **FastAPI** uses Starlette, so it cannot be faster than it. + * FastAPI provides more features on top of Starlette. Features that you almost always need when building APIs, like data validation and serialization. And by using it, you get automatic documentation for free (the automatic documentation doesn't even add overhead to running applications, it is generated on startup). + * If you didn't use FastAPI and used Starlette directly (or another tool, like Sanic, Flask, Responder, etc) you would have to implement all the data validation and serialization yourself. So, your final application would still have the same overhead as if it was built using FastAPI. And in many cases, this data validation and serialization is the biggest amount of code written in applications. + * So, by using FastAPI you are saving development time, bugs, lines of code, and you would probably get the same performance (or better) you would if you didn't use it (as you would have to implement it all in your code). + * If you are comparing FastAPI, compare it against a web application framework (or set of tools) that provides data validation, serialization and documentation, like Flask-apispec, NestJS, Molten, etc. Frameworks with integrated automatic data validation, serialization and documentation. diff --git a/docs/en/docs/contributing.md b/docs/en/docs/contributing.md new file mode 100644 index 0000000000000..384168e67a8ee --- /dev/null +++ b/docs/en/docs/contributing.md @@ -0,0 +1,7 @@ +# Contributing + +First, you might want to see the basic ways to [help FastAPI and get help](help-fastapi.md). + +## Developing + +To contribute code to the project, please follow the guidelines in [tiangolo.com - Contributing](https://tiangolo.com/open-source/contributing/). diff --git a/docs/en/docs/css/custom.css b/docs/en/docs/css/custom.css new file mode 100644 index 0000000000000..147181c489e60 --- /dev/null +++ b/docs/en/docs/css/custom.css @@ -0,0 +1,452 @@ +/* Fira Code, including characters used by Rich output, like the "heavy right-pointing angle bracket ornament", not included in Google Fonts */ +@import url(https://cdn.jsdelivr.net/npm/firacode@6.2.0/distr/fira_code.css); +/* Noto Color Emoji for emoji support with the same font everywhere */ +@import url(https://fonts.googleapis.com/css2?family=Noto+Color+Emoji&display=swap); + +/* Override default code font in Material for MkDocs to Fira Code */ +:root { + --md-code-font: "Fira Code", monospace, "Noto Color Emoji"; +} + +/* Override default regular font in Material for MkDocs to include Noto Color Emoji */ +:root { + --md-text-font: "Roboto", "Noto Color Emoji"; +} + +.termynal-comment { + color: #4a968f; + font-style: italic; + display: block; +} + +.termy { + /* For right to left languages */ + direction: ltr; +} + +.termy [data-termynal] { + white-space: pre-wrap; +} + +.termy .linenos { + display: none; +} + +/* External links: detected by JS comparing origin to site origin + JS sets data-external-link on links pointing outside the site + Skip image links, .no-link-icon, and .announce-link */ +a[data-external-link]:not(:has(img)):not(.no-link-icon):not(.announce-link) { + /* For right to left languages */ + direction: ltr; + display: inline-block; +} + +a[data-external-link]:not(:has(img)):not(.no-link-icon):not(.announce-link)::after { + content: ""; + display: inline-block; + width: 0.75em; + height: 0.75em; + margin-left: 0.25em; + vertical-align: middle; + opacity: 0.55; + background: currentColor; + -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6'/%3E%3Cpolyline points='15 3 21 3 21 9'/%3E%3Cline x1='10' y1='14' x2='21' y2='3'/%3E%3C/svg%3E"); + -webkit-mask-size: contain; + -webkit-mask-repeat: no-repeat; + mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6'/%3E%3Cpolyline points='15 3 21 3 21 9'/%3E%3Cline x1='10' y1='14' x2='21' y2='3'/%3E%3C/svg%3E"); + mask-size: contain; + mask-repeat: no-repeat; +} + +a[data-external-link]:not(:has(img)):not(.no-link-icon):not(.announce-link):hover::after { + opacity: 0.85; +} + +/* Internal links opening in new tab: same-origin links with target=_blank + JS sets data-internal-link on links pointing to the same site origin + Skip image links, .no-link-icon, and .announce-link */ +a[data-internal-link][target="_blank"]:not(:has(img)):not(.no-link-icon):not(.announce-link) { + /* For right to left languages */ + direction: ltr; + display: inline-block; +} + +a[data-internal-link][target="_blank"]:not(:has(img)):not(.no-link-icon):not(.announce-link)::after { + content: ""; + display: inline-block; + width: 0.75em; + height: 0.75em; + margin-left: 0.25em; + vertical-align: middle; + opacity: 0.55; + background: currentColor; + -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='7' width='14' height='14' rx='2'/%3E%3Cpath d='M7 3h14v14'/%3E%3C/svg%3E"); + -webkit-mask-size: contain; + -webkit-mask-repeat: no-repeat; + mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='7' width='14' height='14' rx='2'/%3E%3Cpath d='M7 3h14v14'/%3E%3C/svg%3E"); + mask-size: contain; + mask-repeat: no-repeat; +} + +a[data-internal-link][target="_blank"]:not(:has(img)):not(.no-link-icon):not(.announce-link):hover::after { + opacity: 0.85; +} + +/* Disable link icons in footer and header nav */ +.md-footer a::after, +.md-header a::after { + content: none !important; +} + +.shadow { + box-shadow: 5px 5px 10px #999; +} + +/* Give space to lower icons so Gitter chat doesn't get on top of them */ +.md-footer-meta { + padding-bottom: 2em; +} + +.md-footer-meta .md-social { + padding-right: 4rem; +} + +.user-list { + display: flex; + flex-wrap: wrap; + margin-bottom: 2rem; +} + +.user-list-center { + justify-content: space-evenly; +} + +.user { + margin: 1em; + min-width: 7em; +} + +.user .avatar-wrapper { + width: 80px; + height: 80px; + margin: 10px auto; + overflow: hidden; + border-radius: 50%; + position: relative; +} + +.user .avatar-wrapper img { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); +} + +.user .title { + text-align: center; +} + +.user .count { + font-size: 80%; + text-align: center; +} + +a.announce-link:link, +a.announce-link:visited { + color: #fff; +} + +a.announce-link:hover { + color: var(--md-accent-fg-color); +} + +.announce-wrapper { + display: flex; + justify-content: space-between; + flex-wrap: wrap; + align-items: center; +} + +.announce-wrapper #announce-left div.item { + display: none; +} + +.announce-wrapper #announce-right { + display: none; +} + +.announce-wrapper #announce-right div.item { + display: none; +} + +.announce-wrapper .sponsor-badge { + display: block; + position: absolute; + top: -10px; + right: 0; + font-size: 0.5rem; + color: #e6e6e6; + background-color: #666; + border-radius: 10px; + padding: 0 10px; + z-index: 10; +} + +.announce-wrapper .sponsor-image { + display: block; + border-radius: 20px; +} + +.announce-wrapper>div { + min-height: 40px; + display: flex; + align-items: center; +} + +.twitter { + color: #00acee; +} + +/* Right to left languages */ +code { + direction: ltr; + display: inline-block; +} + +.illustration { + margin-top: 2em; + margin-bottom: 2em; +} + +/* Screenshots */ +/* +Simulate a browser window frame. +Inspired by Termynal's CSS tricks with modifications +*/ + +.screenshot { + display: block; + background-color: #d3e0de; + border-radius: 4px; + padding: 45px 5px 5px; + position: relative; + -webkit-box-sizing: border-box; + box-sizing: border-box; +} + +.screenshot img { + display: block; + border-radius: 2px; +} + +.screenshot:before { + content: ''; + position: absolute; + top: 15px; + left: 15px; + display: inline-block; + width: 15px; + height: 15px; + border-radius: 50%; + /* A little hack to display the window buttons in one pseudo element. */ + background: #d9515d; + -webkit-box-shadow: 25px 0 0 #f4c025, 50px 0 0 #3ec930; + box-shadow: 25px 0 0 #f4c025, 50px 0 0 #3ec930; +} + +.doc-param-details .highlight { + overflow-x: auto; + width: 0; + min-width: 100%; +} + +.md-typeset dfn { + border-bottom: .05rem dotted var(--md-default-fg-color--light); + cursor: help; +} + +/* Opinions: interactive logo tabs */ +.fastapi-opinions { + margin: 1.5rem 0 2rem; +} +.fastapi-opinions__tabs { + display: grid; + grid-template-columns: repeat(4, 1fr); + gap: 0.25rem; + margin-bottom: 1.5rem; + border-bottom: 1px solid var(--md-default-fg-color--lightest); +} +.fastapi-opinions__tab { + position: relative; + appearance: none; + background: none; + border: 0; + padding: 0.625rem 0.5rem; + margin: 0; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + color: inherit; + font: inherit; + min-height: 40px; + min-width: 0; +} +.fastapi-opinions__tab::after { + content: ""; + position: absolute; + left: 50%; + right: 50%; + bottom: -1px; + height: 2px; + background-color: var(--md-primary-fg-color); + opacity: 0; + transition: left 0.2s ease, right 0.2s ease, opacity 0.2s ease; +} +.fastapi-opinions__tab[aria-selected="true"]::after { + left: 12%; + right: 12%; + opacity: 1; +} +.fastapi-opinions__tab:focus-visible { + outline: 2px solid var(--md-primary-fg-color); + outline-offset: 2px; + border-radius: 4px; +} +.fastapi-opinions__mark { + display: flex; + align-items: center; + justify-content: center; + height: 22px; + max-width: 100%; + filter: grayscale(1); + opacity: 0.5; + transition: filter 0.2s, opacity 0.2s; +} +.fastapi-opinions__mark img { + height: 100%; + width: auto; + max-width: 100%; + object-fit: contain; + display: block; +} +.fastapi-opinions__tab:hover .fastapi-opinions__mark { + filter: grayscale(0.3); + opacity: 0.85; +} +.fastapi-opinions__tab[aria-selected="true"] .fastapi-opinions__mark { + filter: grayscale(0); + opacity: 1; +} + +/* Dark mode: brighten dark wordmarks so they read on slate */ +[data-md-color-scheme="slate"] .fastapi-opinions__mark { + filter: grayscale(1) invert(0.85); +} +[data-md-color-scheme="slate"] .fastapi-opinions__tab:hover .fastapi-opinions__mark { + filter: grayscale(0.3) invert(0.4); +} +[data-md-color-scheme="slate"] .fastapi-opinions__tab[aria-selected="true"] .fastapi-opinions__mark { + filter: none; +} + +.fastapi-opinions__panel { + position: relative; + padding: 0.5rem 1rem 0.5rem 3rem; +} +.fastapi-opinions__panel::before { + content: "\201C"; + position: absolute; + top: -0.75rem; + left: 0.25rem; + font-family: Georgia, "Times New Roman", serif; + font-size: 4rem; + line-height: 1; + color: var(--md-primary-fg-color); + opacity: 0.18; + pointer-events: none; +} +.md-typeset blockquote.fastapi-opinions__quote { + margin: 0; + font-size: 1rem; + font-style: italic; + line-height: 1.65; + color: var(--md-default-fg-color); + border-left: 0; + padding-left: 0; +} +.fastapi-opinions__quote strong { font-style: normal; } +.fastapi-opinions__attr { + margin-top: 0.875rem; + font-size: 0.8rem; + color: var(--md-default-fg-color--light); +} +.fastapi-opinions__attr strong { color: var(--md-default-fg-color); } +.fastapi-opinions__attr a { + color: var(--md-primary-fg-color); + text-decoration: none; + font-size: 0.75rem; + margin-left: 0.25rem; +} +.fastapi-opinions__attr a:hover { text-decoration: underline; } + +@media (prefers-reduced-motion: reduce) { + .fastapi-opinions__tab::after { transition: none; } +} + +@media (max-width: 600px) { + .fastapi-opinions__tabs { gap: 0.125rem; } + .fastapi-opinions__mark { height: 18px; } + .fastapi-opinions__panel { padding-left: 2.25rem; } + .fastapi-opinions__panel::before { font-size: 3rem; } +} + +.fastapi-sponsors { + display: flex; + flex-wrap: wrap; + justify-content: center; + align-items: center; + gap: 1rem 1.25rem; + margin: 1rem 0 2rem; +} + +.fastapi-sponsors__card { + transition: transform 0.15s ease; +} + +.fastapi-sponsors__card:hover { + transform: translateY(-1px); +} + +.fastapi-sponsors__card--keystone { + width: 100%; + max-width: 560px; +} + +.fastapi-sponsors__banner { + display: block; + border-radius: 12px; +} + +.fastapi-sponsors__card--keystone .fastapi-sponsors__banner { width: 100%; } +.fastapi-sponsors__card--gold .fastapi-sponsors__banner { height: 80px; } +.fastapi-sponsors__card--silver .fastapi-sponsors__banner { height: 60px; } + +@media (max-width: 600px) { + .fastapi-sponsors__card--gold .fastapi-sponsors__banner { height: 64px; } + .fastapi-sponsors__card--silver .fastapi-sponsors__banner { height: 50px; } +} + +.fastapi-feature-banner { + display: block; + max-width: 680px; + margin: 1rem auto 1.5rem; +} +.fastapi-feature-banner img { + display: block; + width: 100%; + border-radius: 12px; +} + +/* Hidden in MkDocs; rendered on GitHub (which doesn't load this stylesheet) */ +.only-github { display: none; } diff --git a/docs/en/docs/css/termynal.css b/docs/en/docs/css/termynal.css new file mode 100644 index 0000000000000..a2564e2860a4b --- /dev/null +++ b/docs/en/docs/css/termynal.css @@ -0,0 +1,111 @@ +/** + * termynal.js + * + * @author Ines Montani + * @version 0.0.1 + * @license MIT + */ + +:root { + --color-bg: #252a33; + --color-text: #eee; + --color-text-subtle: #a2a2a2; +} + +[data-termynal] { + width: 750px; + max-width: 100%; + background: var(--color-bg); + color: var(--color-text); + /* font-size: 18px; */ + font-size: 15px; + /* font-family: 'Fira Mono', Consolas, Menlo, Monaco, 'Courier New', Courier, monospace; */ + font-family: var(--md-code-font-family), 'Roboto Mono', 'Fira Mono', Consolas, Menlo, Monaco, 'Courier New', Courier, monospace; + border-radius: 4px; + padding: 75px 45px 35px; + position: relative; + -webkit-box-sizing: border-box; + box-sizing: border-box; + /* Custom line-height */ + line-height: 1.2; +} + +[data-termynal]:before { + content: ''; + position: absolute; + top: 15px; + left: 15px; + display: inline-block; + width: 15px; + height: 15px; + border-radius: 50%; + /* A little hack to display the window buttons in one pseudo element. */ + background: #d9515d; + -webkit-box-shadow: 25px 0 0 #f4c025, 50px 0 0 #3ec930; + box-shadow: 25px 0 0 #f4c025, 50px 0 0 #3ec930; +} + +[data-termynal]:after { + content: 'bash'; + position: absolute; + color: var(--color-text-subtle); + top: 5px; + left: 0; + width: 100%; + text-align: center; +} + +a[data-terminal-control] { + text-align: right; + display: block; + color: #aebbff; +} + +[data-ty] { + display: block; + line-height: 2; +} + +[data-ty]:before { + /* Set up defaults and ensure empty lines are displayed. */ + content: ''; + display: inline-block; + vertical-align: middle; +} + +[data-ty="input"]:before, +[data-ty-prompt]:before { + margin-right: 0.75em; + color: var(--color-text-subtle); +} + +[data-ty="input"]:before { + content: '$'; +} + +[data-ty][data-ty-prompt]:before { + content: attr(data-ty-prompt); +} + +[data-ty-cursor]:after { + content: attr(data-ty-cursor); + font-family: monospace; + margin-left: 0.5em; + -webkit-animation: blink 1s infinite; + animation: blink 1s infinite; +} + + +/* Cursor animation */ + +@-webkit-keyframes blink { + 50% { + opacity: 0; + } +} + +@keyframes blink { + 50% { + opacity: 0; + } +} diff --git a/docs/en/docs/deployment/cloud.md b/docs/en/docs/deployment/cloud.md new file mode 100644 index 0000000000000..7bdef253e3ff3 --- /dev/null +++ b/docs/en/docs/deployment/cloud.md @@ -0,0 +1,24 @@ +# Deploy FastAPI on Cloud Providers { #deploy-fastapi-on-cloud-providers } + +You can use virtually **any cloud provider** to deploy your FastAPI application. + +In most of the cases, the main cloud providers have guides to deploy FastAPI with them. + +## FastAPI Cloud { #fastapi-cloud } + +**[FastAPI Cloud](https://fastapicloud.com)** 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. ✨ + +## Cloud Providers - Sponsors { #cloud-providers-sponsors } + +Some other cloud providers ✨ [**sponsor FastAPI**](https://github.com/sponsors/tiangolo) ✨ too. 🙇 + +You might also want to consider them to follow their guides and try their services: + +* [Render](https://docs.render.com/deploy-fastapi?utm_source=deploydoc&utm_medium=referral&utm_campaign=fastapi) +* [Railway](https://docs.railway.com/guides/fastapi?utm_medium=integration&utm_source=docs&utm_campaign=fastapi) diff --git a/docs/en/docs/deployment/concepts.md b/docs/en/docs/deployment/concepts.md new file mode 100644 index 0000000000000..fc99c2247e176 --- /dev/null +++ b/docs/en/docs/deployment/concepts.md @@ -0,0 +1,321 @@ +# Deployments Concepts { #deployments-concepts } + +When deploying a **FastAPI** application, or actually, any type of web API, there are several concepts that you probably care about, and using them you can find the **most appropriate** way to **deploy your application**. + +Some of the important concepts are: + +* Security - HTTPS +* Running on startup +* Restarts +* Replication (the number of processes running) +* Memory +* Previous steps before starting + +We'll see how they would affect **deployments**. + +In the end, the ultimate objective is to be able to **serve your API clients** in a way that is **secure**, to **avoid disruptions**, and to use the **compute resources** (for example remote servers/virtual machines) as efficiently as possible. 🚀 + +I'll tell you a bit more about these **concepts** here, and that would hopefully give you the **intuition** you would need to decide how to deploy your API in very different environments, possibly even in **future** ones that don't exist yet. + +By considering these concepts, you will be able to **evaluate and design** the best way to deploy **your own APIs**. + +In the next chapters, I'll give you more **concrete recipes** to deploy FastAPI applications. + +But for now, let's check these important **conceptual ideas**. These concepts also apply to any other type of web API. 💡 + +## Security - HTTPS { #security-https } + +In the [previous chapter about HTTPS](https.md) we learned about how HTTPS provides encryption for your API. + +We also saw that HTTPS is normally provided by a component **external** to your application server, a **TLS Termination Proxy**. + +And there has to be something in charge of **renewing the HTTPS certificates**, it could be the same component or it could be something different. + +### Example Tools for HTTPS { #example-tools-for-https } + +Some of the tools you could use as a TLS Termination Proxy are: + +* Traefik + * Automatically handles certificate renewals ✨ +* Caddy + * Automatically handles certificate renewals ✨ +* Nginx + * With an external component like Certbot for certificate renewals +* HAProxy + * With an external component like Certbot for certificate renewals +* Kubernetes with an Ingress Controller like Nginx + * With an external component like cert-manager for certificate renewals +* Handled internally by a cloud provider as part of their services (read below 👇) + +Another option is that you could use a **cloud service** that does more of the work including setting up HTTPS. It could have some restrictions or charge you more, etc. But in that case, you wouldn't have to set up a TLS Termination Proxy yourself. + +I'll show you some concrete examples in the next chapters. + +--- + +Then the next concepts to consider are all about the program running your actual API (e.g. Uvicorn). + +## Program and Process { #program-and-process } + +We will talk a lot about the running "**process**", so it's useful to have clarity about what it means, and what's the difference with the word "**program**". + +### What is a Program { #what-is-a-program } + +The word **program** is commonly used to describe many things: + +* The **code** that you write, the **Python files**. +* The **file** that can be **executed** by the operating system, for example: `python`, `python.exe` or `uvicorn`. +* A particular program while it is **running** on the operating system, using the CPU, and storing things in memory. This is also called a **process**. + +### What is a Process { #what-is-a-process } + +The word **process** is normally used in a more specific way, only referring to the thing that is running in the operating system (like in the last point above): + +* A particular program while it is **running** on the operating system. + * This doesn't refer to the file, nor to the code, it refers **specifically** to the thing that is being **executed** and managed by the operating system. +* Any program, any code, **can only do things** when it is being **executed**. So, when there's a **process running**. +* The process can be **terminated** (or "killed") by you, or by the operating system. At that point, it stops running/being executed, and it can **no longer do things**. +* Each application that you have running on your computer has some process behind it, each running program, each window, etc. And there are normally many processes running **at the same time** while a computer is on. +* There can be **multiple processes** of the **same program** running at the same time. + +If you check out the "task manager" or "system monitor" (or similar tools) in your operating system, you will be able to see many of those processes running. + +And, for example, you will probably see that there are multiple processes running the same browser program (Firefox, Chrome, Edge, etc). They normally run one process per tab, plus some other extra processes. + + + +--- + +Now that we know the difference between the terms **process** and **program**, let's continue talking about deployments. + +## Running on Startup { #running-on-startup } + +In most cases, when you create a web API, you want it to be **always running**, uninterrupted, so that your clients can always access it. This is of course, unless you have a specific reason why you want it to run only in certain situations, but most of the time you want it constantly running and **available**. + +### In a Remote Server { #in-a-remote-server } + +When you set up a remote server (a cloud server, a virtual machine, etc.) the simplest thing you can do is use `fastapi run` (which uses Uvicorn) or something similar, manually, the same way you do when developing locally. + +And it will work and will be useful **during development**. + +But if your connection to the server is lost, the **running process** will probably die. + +And if the server is restarted (for example after updates, or migrations from the cloud provider) you probably **won't notice it**. And because of that, you won't even know that you have to restart the process manually. So, your API will just stay dead. 😱 + +### Run Automatically on Startup { #run-automatically-on-startup } + +In general, you will probably want the server program (e.g. Uvicorn) to be started automatically on server startup, and without needing any **human intervention**, to have a process always running with your API (e.g. Uvicorn running your FastAPI app). + +### Separate Program { #separate-program } + +To achieve this, you will normally have a **separate program** that would make sure your application is run on startup. And in many cases, it would also make sure other components or applications are also run, for example, a database. + +### Example Tools to Run at Startup { #example-tools-to-run-at-startup } + +Some examples of the tools that can do this job are: + +* Docker +* Kubernetes +* Docker Compose +* Docker in Swarm Mode +* Systemd +* Supervisor +* Handled internally by a cloud provider as part of their services +* Others... + +I'll give you more concrete examples in the next chapters. + +## Restarts { #restarts } + +Similar to making sure your application is run on startup, you probably also want to make sure it is **restarted** after failures. + +### We Make Mistakes { #we-make-mistakes } + +We, as humans, make **mistakes**, all the time. Software almost *always* has **bugs** hidden in different places. 🐛 + +And we as developers keep improving the code as we find those bugs and as we implement new features (possibly adding new bugs too 😅). + +### Small Errors Automatically Handled { #small-errors-automatically-handled } + +When building web APIs with FastAPI, if there's an error in our code, FastAPI will normally contain it to the single request that triggered the error. 🛡 + +The client will get a **500 Internal Server Error** for that request, but the application will continue working for the next requests instead of just crashing completely. + +### Bigger Errors - Crashes { #bigger-errors-crashes } + +Nevertheless, there might be cases where we write some code that **crashes the entire application** making Uvicorn and Python crash. 💥 + +And still, you would probably not want the application to stay dead because there was an error in one place, you probably want it to **continue running** at least for the *path operations* that are not broken. + +### Restart After Crash { #restart-after-crash } + +But in those cases with really bad errors that crash the running **process**, you would want an external component that is in charge of **restarting** the process, at least a couple of times... + +/// tip + +...Although if the whole application is just **crashing immediately** it probably doesn't make sense to keep restarting it forever. But in those cases, you will probably notice it during development, or at least right after deployment. + +So let's focus on the main cases, where it could crash entirely in some particular cases **in the future**, and it still makes sense to restart it. + +/// + +You would probably want to have the thing in charge of restarting your application as an **external component**, because by that point, the same application with Uvicorn and Python already crashed, so there's nothing in the same code of the same app that could do anything about it. + +### Example Tools to Restart Automatically { #example-tools-to-restart-automatically } + +In most cases, the same tool that is used to **run the program on startup** is also used to handle automatic **restarts**. + +For example, this could be handled by: + +* Docker +* Kubernetes +* Docker Compose +* Docker in Swarm Mode +* Systemd +* Supervisor +* Handled internally by a cloud provider as part of their services +* Others... + +## Replication - Processes and Memory { #replication-processes-and-memory } + +With a FastAPI application, using a server program like the `fastapi` command that runs Uvicorn, running it once in **one process** can serve multiple clients concurrently. + +But in many cases, you will want to run several worker processes at the same time. + +### Multiple Processes - Workers { #multiple-processes-workers } + +If you have more clients than what a single process can handle (for example if the virtual machine is not too big) and you have **multiple cores** in the server's CPU, then you could have **multiple processes** running with the same application at the same time, and distribute all the requests among them. + +When you run **multiple processes** of the same API program, they are commonly called **workers**. + +### Worker Processes and Ports { #worker-processes-and-ports } + +Remember from the docs [About HTTPS](https.md) that only one process can be listening on one combination of port and IP address in a server? + +This is still true. + +So, to be able to have **multiple processes** at the same time, there has to be a **single process listening on a port** that then transmits the communication to each worker process in some way. + +### Memory per Process { #memory-per-process } + +Now, when the program loads things in memory, for example, a machine learning model in a variable, or the contents of a large file in a variable, all that **consumes a bit of the memory (RAM)** of the server. + +And multiple processes normally **don't share any memory**. This means that each running process has its own things, variables, and memory. And if you are consuming a large amount of memory in your code, **each process** will consume an equivalent amount of memory. + +### Server Memory { #server-memory } + +For example, if your code loads a Machine Learning model with **1 GB in size**, when you run one process with your API, it will consume at least 1 GB of RAM. And if you start **4 processes** (4 workers), each will consume 1 GB of RAM. So in total, your API will consume **4 GB of RAM**. + +And if your remote server or virtual machine only has 3 GB of RAM, trying to load more than 4 GB of RAM will cause problems. 🚨 + +### Multiple Processes - An Example { #multiple-processes-an-example } + +In this example, there's a **Manager Process** that starts and controls two **Worker Processes**. + +This Manager Process would probably be the one listening on the **port** in the IP. And it would transmit all the communication to the worker processes. + +Those worker processes would be the ones running your application, they would perform the main computations to receive a **request** and return a **response**, and they would load anything you put in variables in RAM. + + + +And of course, the same machine would probably have **other processes** running as well, apart from your application. + +An interesting detail is that the percentage of the **CPU used** by each process can **vary** a lot over time, but the **memory (RAM)** normally stays more or less **stable**. + +If you have an API that does a comparable amount of computations every time and you have a lot of clients, then the **CPU utilization** will probably *also be stable* (instead of constantly going up and down quickly). + +### Examples of Replication Tools and Strategies { #examples-of-replication-tools-and-strategies } + +There can be several approaches to achieve this, and I'll tell you more about specific strategies in the next chapters, for example when talking about Docker and containers. + +The main constraint to consider is that there has to be a **single** component handling the **port** in the **public IP**. And then it has to have a way to **transmit** the communication to the replicated **processes/workers**. + +Here are some possible combinations and strategies: + +* **Uvicorn** with `--workers` + * One Uvicorn **process manager** would listen on the **IP** and **port**, and it would start **multiple Uvicorn worker processes**. +* **Kubernetes** and other distributed **container systems** + * Something in the **Kubernetes** layer would listen on the **IP** and **port**. The replication would be by having **multiple containers**, each with **one Uvicorn process** running. +* **Cloud services** that handle this for you + * The cloud service will probably **handle replication for you**. It would possibly let you define **a process to run**, or a **container image** to use, in any case, it would most probably be **a single Uvicorn process**, and the cloud service would be in charge of replicating it. + +/// tip + +Don't worry if some of these items about **containers**, Docker, or Kubernetes don't make a lot of sense yet. + +I'll tell you more about container images, Docker, Kubernetes, etc. in a future chapter: [FastAPI in Containers - Docker](docker.md). + +/// + +## Previous Steps Before Starting { #previous-steps-before-starting } + +There are many cases where you want to perform some steps **before starting** your application. + +For example, you might want to run **database migrations**. + +But in most cases, you will want to perform these steps only **once**. + +So, you will want to have a **single process** to perform those **previous steps**, before starting the application. + +And you will have to make sure that it's a single process running those previous steps *even* if afterwards, you start **multiple processes** (multiple workers) for the application itself. If those steps were run by **multiple processes**, they would **duplicate** the work by running it in **parallel**, and if the steps were something delicate like a database migration, they could cause conflicts with each other. + +Of course, there are some cases where there's no problem in running the previous steps multiple times, in that case, it's a lot easier to handle. + +/// tip + +Also, keep in mind that depending on your setup, in some cases you **might not even need any previous steps** before starting your application. + +In that case, you wouldn't have to worry about any of this. 🤷 + +/// + +### Examples of Previous Steps Strategies { #examples-of-previous-steps-strategies } + +This will **depend heavily** on the way you **deploy your system**, and it would probably be connected to the way you start programs, handling restarts, etc. + +Here are some possible ideas: + +* An "Init Container" in Kubernetes that runs before your app container +* A bash script that runs the previous steps and then starts your application + * You would still need a way to start/restart *that* bash script, detect errors, etc. + +/// tip + +I'll give you more concrete examples for doing this with containers in a future chapter: [FastAPI in Containers - Docker](docker.md). + +/// + +## Resource Utilization { #resource-utilization } + +Your server(s) is (are) a **resource**, you can consume or **utilize**, with your programs, the computation time on the CPUs, and the RAM memory available. + +How much of the system resources do you want to be consuming/utilizing? It might be easy to think "not much", but in reality, you will probably want to consume **as much as possible without crashing**. + +If you are paying for 3 servers but you are using only a little bit of their RAM and CPU, you are probably **wasting money** 💸, and probably **wasting server electric power** 🌎, etc. + +In that case, it could be better to have only 2 servers and use a higher percentage of their resources (CPU, memory, disk, network bandwidth, etc). + +On the other hand, if you have 2 servers and you are using **100% of their CPU and RAM**, at some point one process will ask for more memory, and the server will have to use the disk as "memory" (which can be thousands of times slower), or even **crash**. Or one process might need to do some computation and would have to wait until the CPU is free again. + +In this case, it would be better to get **one extra server** and run some processes on it so that they all have **enough RAM and CPU time**. + +There's also the chance that for some reason you have a **spike** of usage of your API. Maybe it went viral, or maybe some other services or bots start using it. And you might want to have extra resources to be safe in those cases. + +You could put an **arbitrary number** to target, for example, something **between 50% to 90%** of resource utilization. The point is that those are probably the main things you will want to measure and use to tweak your deployments. + +You can use simple tools like `htop` to see the CPU and RAM used in your server or the amount used by each process. Or you can use more complex monitoring tools, which may be distributed across servers, etc. + +## Recap { #recap } + +You have been reading here some of the main concepts that you would probably need to keep in mind when deciding how to deploy your application: + +* Security - HTTPS +* Running on startup +* Restarts +* Replication (the number of processes running) +* Memory +* Previous steps before starting + +Understanding these ideas and how to apply them should give you the intuition necessary to take any decisions when configuring and tweaking your deployments. 🤓 + +In the next sections, I'll give you more concrete examples of possible strategies you can follow. 🚀 diff --git a/docs/en/docs/deployment/docker.md b/docs/en/docs/deployment/docker.md new file mode 100644 index 0000000000000..bdc0351d03029 --- /dev/null +++ b/docs/en/docs/deployment/docker.md @@ -0,0 +1,618 @@ +# FastAPI in Containers - Docker { #fastapi-in-containers-docker } + +When deploying FastAPI applications a common approach is to build a **Linux container image**. It's normally done using [**Docker**](https://www.docker.com/). You can then deploy that container image in one of a few possible ways. + +Using Linux containers has several advantages including **security**, **replicability**, **simplicity**, and others. + +/// tip + +In a hurry and already know this stuff? Jump to the [`Dockerfile` below 👇](#build-a-docker-image-for-fastapi). + +/// + +
+Dockerfile Preview 👀 + +```Dockerfile +FROM python:3.14 + +WORKDIR /code + +COPY ./requirements.txt /code/requirements.txt + +RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt + +COPY ./app /code/app + +CMD ["fastapi", "run", "app/main.py", "--port", "80"] + +# If running behind a proxy like Nginx or Traefik add --proxy-headers +# CMD ["fastapi", "run", "app/main.py", "--port", "80", "--proxy-headers"] +``` + +
+ +## What is a Container { #what-is-a-container } + +Containers (mainly Linux containers) are a very **lightweight** way to package applications including all their dependencies and necessary files while keeping them isolated from other containers (other applications or components) in the same system. + +Linux containers run using the same Linux kernel of the host (machine, virtual machine, cloud server, etc). This just means that they are very lightweight (compared to full virtual machines emulating an entire operating system). + +This way, containers consume **little resources**, an amount comparable to running the processes directly (a virtual machine would consume much more). + +Containers also have their own **isolated** running processes (commonly just one process), file system, and network, simplifying deployment, security, development, etc. + +## What is a Container Image { #what-is-a-container-image } + +A **container** is run from a **container image**. + +A container image is a **static** version of all the files, environment variables, and the default command/program that should be present in a container. **Static** here means that the container **image** is not running, it's not being executed, it's only the packaged files and metadata. + +In contrast to a "**container image**" that is the stored static contents, a "**container**" normally refers to the running instance, the thing that is being **executed**. + +When the **container** is started and running (started from a **container image**) it could create or change files, environment variables, etc. Those changes will exist only in that container, but would not persist in the underlying container image (would not be saved to disk). + +A container image is comparable to the **program** file and contents, e.g. `python` and some file `main.py`. + +And the **container** itself (in contrast to the **container image**) is the actual running instance of the image, comparable to a **process**. In fact, a container is running only when it has a **process running** (and normally it's only a single process). The container stops when there's no process running in it. + +## Container Images { #container-images } + +Docker has been one of the main tools to create and manage **container images** and **containers**. + +And there's a public [Docker Hub](https://hub.docker.com/) with pre-made **official container images** for many tools, environments, databases, and applications. + +For example, there's an official [Python Image](https://hub.docker.com/_/python). + +And there are many other images for different things like databases, for example for: + +* [PostgreSQL](https://hub.docker.com/_/postgres) +* [MySQL](https://hub.docker.com/_/mysql) +* [MongoDB](https://hub.docker.com/_/mongo) +* [Redis](https://hub.docker.com/_/redis), etc. + +By using a pre-made container image it's very easy to **combine** and use different tools. For example, to try out a new database. In most cases, you can use the **official images**, and just configure them with environment variables. + +That way, in many cases you can learn about containers and Docker and reuse that knowledge with many different tools and components. + +So, you would run **multiple containers** with different things, like a database, a Python application, a web server with a React frontend application, and connect them together via their internal network. + +All the container management systems (like Docker or Kubernetes) have these networking features integrated into them. + +## Containers and Processes { #containers-and-processes } + +A **container image** normally includes in its metadata the default program or command that should be run when the **container** is started and the parameters to be passed to that program. Very similar to what would be if it was in the command line. + +When a **container** is started, it will run that command/program (although you can override it and make it run a different command/program). + +A container is running as long as the **main process** (command or program) is running. + +A container normally has a **single process**, but it's also possible to start subprocesses from the main process, and that way you will have **multiple processes** in the same container. + +But it's not possible to have a running container without **at least one running process**. If the main process stops, the container stops. + +## Build a Docker Image for FastAPI { #build-a-docker-image-for-fastapi } + +Okay, let's build something now! 🚀 + +I'll show you how to build a **Docker image** for FastAPI **from scratch**, based on the **official Python** image. + +This is what you would want to do in **most cases**, for example: + +* Using **Kubernetes** or similar tools +* When running on a **Raspberry Pi** +* Using a cloud service that would run a container image for you, etc. + +### Package Requirements { #package-requirements } + +You would normally have the **package requirements** for your application in some file. + +It would depend mainly on the tool you use to **install** those requirements. + +The most common way to do it is to have a file `requirements.txt` with the package names and their versions, one per line. + +You would of course use the same ideas you read in [About FastAPI versions](versions.md) to set the ranges of versions. + +For example, your `requirements.txt` could look like: + +``` +fastapi[standard]>=0.113.0,<0.114.0 +pydantic>=2.7.0,<3.0.0 +``` + +And you would normally install those package dependencies with `pip`, for example: + +
+ +```console +$ pip install -r requirements.txt +---> 100% +Successfully installed fastapi pydantic +``` + +
+ +/// note + +There are other formats and tools to define and install package dependencies. + +/// + +### Create the **FastAPI** Code { #create-the-fastapi-code } + +* Create an `app` directory and enter it. +* Create an empty file `__init__.py`. +* Create a `main.py` file with: + +```Python +from fastapi import FastAPI + +app = FastAPI() + + +@app.get("/") +def read_root(): + return {"Hello": "World"} + + +@app.get("/items/{item_id}") +def read_item(item_id: int, q: str | None = None): + return {"item_id": item_id, "q": q} +``` + +### Dockerfile { #dockerfile } + +Now in the same project directory create a file `Dockerfile` with: + +```{ .dockerfile .annotate } +# (1)! +FROM python:3.14 + +# (2)! +WORKDIR /code + +# (3)! +COPY ./requirements.txt /code/requirements.txt + +# (4)! +RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt + +# (5)! +COPY ./app /code/app + +# (6)! +CMD ["fastapi", "run", "app/main.py", "--port", "80"] +``` + +1. Start from the official Python base image. + +2. Set the current working directory to `/code`. + + This is where we'll put the `requirements.txt` file and the `app` directory. + +3. Copy the file with the requirements to the `/code` directory. + + Copy **only** the file with the requirements first, not the rest of the code. + + As this file **doesn't change often**, Docker will detect it and use the **cache** for this step, enabling the cache for the next step too. + +4. Install the package dependencies in the requirements file. + + The `--no-cache-dir` option tells `pip` to not save the downloaded packages locally, as that is only if `pip` was going to be run again to install the same packages, but that's not the case when working with containers. + + /// note + + The `--no-cache-dir` is only related to `pip`, it has nothing to do with Docker or containers. + + /// + + The `--upgrade` option tells `pip` to upgrade the packages if they are already installed. + + Because the previous step copying the file could be detected by the **Docker cache**, this step will also **use the Docker cache** when available. + + Using the cache in this step will **save** you a lot of **time** when building the image again and again during development, instead of **downloading and installing** all the dependencies **every time**. + +5. Copy the `./app` directory inside the `/code` directory. + + As this has all the code which is what **changes most frequently** the Docker **cache** won't be used for this or any **following steps** easily. + + So, it's important to put this **near the end** of the `Dockerfile`, to optimize the container image build times. + +6. Set the **command** to use `fastapi run`, which uses Uvicorn underneath. + + `CMD` takes a list of strings, each of these strings is what you would type in the command line separated by spaces. + + This command will be run from the **current working directory**, the same `/code` directory you set above with `WORKDIR /code`. + +/// tip + +Review what each line does by clicking each number bubble in the code. 👆 + +/// + +/// warning + +Make sure to **always** use the **exec form** of the `CMD` instruction, as explained below. + +/// + +#### Use `CMD` - Exec Form { #use-cmd-exec-form } + +The [`CMD`](https://docs.docker.com/reference/dockerfile/#cmd) Docker instruction can be written using two forms: + +✅ **Exec** form: + +```Dockerfile +# ✅ Do this +CMD ["fastapi", "run", "app/main.py", "--port", "80"] +``` + +⛔️ **Shell** form: + +```Dockerfile +# ⛔️ Don't do this +CMD fastapi run app/main.py --port 80 +``` + +Make sure to always use the **exec** form to ensure that FastAPI can shutdown gracefully and [lifespan events](../advanced/events.md) are triggered. + +You can read more about it in the [Docker docs for shell and exec form](https://docs.docker.com/reference/dockerfile/#shell-and-exec-form). + +This can be quite noticeable when using `docker compose`. See this Docker Compose FAQ section for more technical details: [Why do my services take 10 seconds to recreate or stop?](https://docs.docker.com/compose/faq/#why-do-my-services-take-10-seconds-to-recreate-or-stop). + +#### Directory Structure { #directory-structure } + +You should now have a directory structure like: + +``` +. +├── app +│   ├── __init__.py +│ └── main.py +├── Dockerfile +└── requirements.txt +``` + +#### Behind a TLS Termination Proxy { #behind-a-tls-termination-proxy } + +If you are running your container behind a TLS Termination Proxy (load balancer) like Nginx or Traefik, add the option `--proxy-headers`, this will tell Uvicorn (through the FastAPI CLI) to trust the headers sent by that proxy telling it that the application is running behind HTTPS, etc. + +```Dockerfile +CMD ["fastapi", "run", "app/main.py", "--proxy-headers", "--port", "80"] +``` + +#### Docker Cache { #docker-cache } + +There's an important trick in this `Dockerfile`, we first copy the **file with the dependencies alone**, not the rest of the code. Let me tell you why that is. + +```Dockerfile +COPY ./requirements.txt /code/requirements.txt +``` + +Docker and other tools **build** these container images **incrementally**, adding **one layer on top of the other**, starting from the top of the `Dockerfile` and adding any files created by each of the instructions of the `Dockerfile`. + +Docker and similar tools also use an **internal cache** when building the image, if a file hasn't changed since the last time building the container image, then it will **reuse the same layer** created the last time, instead of copying the file again and creating a new layer from scratch. + +Just avoiding the copy of files doesn't necessarily improve things too much, but because it used the cache for that step, it can **use the cache for the next step**. For example, it could use the cache for the instruction that installs dependencies with: + +```Dockerfile +RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt +``` + +The file with the package requirements **won't change frequently**. So, by copying only that file, Docker will be able to **use the cache** for that step. + +And then, Docker will be able to **use the cache for the next step** that downloads and installs those dependencies. And here's where we **save a lot of time**. ✨ ...and avoid boredom waiting. 😪😆 + +Downloading and installing the package dependencies **could take minutes**, but using the **cache** would **take seconds** at most. + +And as you would be building the container image again and again during development to check that your code changes are working, there's a lot of accumulated time this would save. + +Then, near the end of the `Dockerfile`, we copy all the code. As this is what **changes most frequently**, we put it near the end, because almost always, anything after this step will not be able to use the cache. + +```Dockerfile +COPY ./app /code/app +``` + +### Build the Docker Image { #build-the-docker-image } + +Now that all the files are in place, let's build the container image. + +* Go to the project directory (in where your `Dockerfile` is, containing your `app` directory). +* Build your FastAPI image: + +
+ +```console +$ docker build -t myimage . + +---> 100% +``` + +
+ +/// tip + +Notice the `.` at the end, it's equivalent to `./`, it tells Docker the directory to use to build the container image. + +In this case, it's the same current directory (`.`). + +/// + +### Start the Docker Container { #start-the-docker-container } + +* Run a container based on your image: + +
+ +```console +$ docker run -d --name mycontainer -p 80:80 myimage +``` + +
+ +## Check it { #check-it } + +You should be able to check it in your Docker container's URL, for example: [http://192.168.99.100/items/5?q=somequery](http://192.168.99.100/items/5?q=somequery) or [http://127.0.0.1/items/5?q=somequery](http://127.0.0.1/items/5?q=somequery) (or equivalent, using your Docker host). + +You will see something like: + +```JSON +{"item_id": 5, "q": "somequery"} +``` + +## Interactive API docs { #interactive-api-docs } + +Now you can go to [http://192.168.99.100/docs](http://192.168.99.100/docs) or [http://127.0.0.1/docs](http://127.0.0.1/docs) (or equivalent, using your Docker host). + +You will see the automatic interactive API documentation (provided by [Swagger UI](https://github.com/swagger-api/swagger-ui)): + +![Swagger UI](https://fastapi.tiangolo.com/img/index/index-01-swagger-ui-simple.png) + +## Alternative API docs { #alternative-api-docs } + +And you can also go to [http://192.168.99.100/redoc](http://192.168.99.100/redoc) or [http://127.0.0.1/redoc](http://127.0.0.1/redoc) (or equivalent, using your Docker host). + +You will see the alternative automatic documentation (provided by [ReDoc](https://github.com/Rebilly/ReDoc)): + +![ReDoc](https://fastapi.tiangolo.com/img/index/index-02-redoc-simple.png) + +## Build a Docker Image with a Single-File FastAPI { #build-a-docker-image-with-a-single-file-fastapi } + +If your FastAPI is a single file, for example, `main.py` without an `./app` directory, your file structure could look like this: + +``` +. +├── Dockerfile +├── main.py +└── requirements.txt +``` + +Then you would just have to change the corresponding paths to copy the file inside the `Dockerfile`: + +```{ .dockerfile .annotate hl_lines="10 13" } +FROM python:3.14 + +WORKDIR /code + +COPY ./requirements.txt /code/requirements.txt + +RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt + +# (1)! +COPY ./main.py /code/ + +# (2)! +CMD ["fastapi", "run", "main.py", "--port", "80"] +``` + +1. Copy the `main.py` file to the `/code` directory directly (without any `./app` directory). + +2. Use `fastapi run` to serve your application in the single file `main.py`. + +When you pass the file to `fastapi run` it will detect automatically that it is a single file and not part of a package and will know how to import it and serve your FastAPI app. 😎 + +## Deployment Concepts { #deployment-concepts } + +Let's talk again about some of the same [Deployment Concepts](concepts.md) in terms of containers. + +Containers are mainly a tool to simplify the process of **building and deploying** an application, but they don't enforce a particular approach to handle these **deployment concepts**, and there are several possible strategies. + +The **good news** is that with each different strategy there's a way to cover all of the deployment concepts. 🎉 + +Let's review these **deployment concepts** in terms of containers: + +* HTTPS +* Running on startup +* Restarts +* Replication (the number of processes running) +* Memory +* Previous steps before starting + +## HTTPS { #https } + +If we focus just on the **container image** for a FastAPI application (and later the running **container**), HTTPS normally would be handled **externally** by another tool. + +It could be another container, for example with [Traefik](https://traefik.io/), handling **HTTPS** and **automatic** acquisition of **certificates**. + +/// tip + +Traefik has integrations with Docker, Kubernetes, and others, so it's very easy to set up and configure HTTPS for your containers with it. + +/// + +Alternatively, HTTPS could be handled by a cloud provider as one of their services (while still running the application in a container). + +## Running on Startup and Restarts { #running-on-startup-and-restarts } + +There is normally another tool in charge of **starting and running** your container. + +It could be **Docker** directly, **Docker Compose**, **Kubernetes**, a **cloud service**, etc. + +In most (or all) cases, there's a simple option to enable running the container on startup and enabling restarts on failures. For example, in Docker, it's the command line option `--restart`. + +Without using containers, making applications run on startup and with restarts can be cumbersome and difficult. But when **working with containers** in most cases that functionality is included by default. ✨ + +## Replication - Number of Processes { #replication-number-of-processes } + +If you have a cluster of machines with **Kubernetes**, Docker Swarm Mode, Nomad, or another similar complex system to manage distributed containers on multiple machines, then you will probably want to **handle replication** at the **cluster level** instead of using a **process manager** (like Uvicorn with workers) in each container. + +One of those distributed container management systems like Kubernetes normally has some integrated way of handling **replication of containers** while still supporting **load balancing** for the incoming requests. All at the **cluster level**. + +In those cases, you would probably want to build a **Docker image from scratch** as [explained above](#dockerfile), installing your dependencies, and running **a single Uvicorn process** instead of using multiple Uvicorn workers. + +### Load Balancer { #load-balancer } + +When using containers, you would normally have some component **listening on the main port**. It could possibly be another container that is also a **TLS Termination Proxy** to handle **HTTPS** or some similar tool. + +As this component would take the **load** of requests and distribute that among the workers in a (hopefully) **balanced** way, it is also commonly called a **Load Balancer**. + +/// tip + +The same **TLS Termination Proxy** component used for HTTPS would probably also be a **Load Balancer**. + +/// + +And when working with containers, the same system you use to start and manage them would already have internal tools to transmit the **network communication** (e.g. HTTP requests) from that **load balancer** (that could also be a **TLS Termination Proxy**) to the container(s) with your app. + +### One Load Balancer - Multiple Worker Containers { #one-load-balancer-multiple-worker-containers } + +When working with **Kubernetes** or similar distributed container management systems, using their internal networking mechanisms would allow the single **load balancer** that is listening on the main **port** to transmit communication (requests) to possibly **multiple containers** running your app. + +Each of these containers running your app would normally have **just one process** (e.g. a Uvicorn process running your FastAPI application). They would all be **identical containers**, running the same thing, but each with its own process, memory, etc. That way you would take advantage of **parallelization** in **different cores** of the CPU, or even in **different machines**. + +And the distributed container system with the **load balancer** would **distribute the requests** to each one of the containers with your app **in turns**. So, each request could be handled by one of the multiple **replicated containers** running your app. + +And normally this **load balancer** would be able to handle requests that go to *other* apps in your cluster (e.g. to a different domain, or under a different URL path prefix), and would transmit that communication to the right containers for *that other* application running in your cluster. + +### One Process per Container { #one-process-per-container } + +In this type of scenario, you probably would want to have **a single (Uvicorn) process per container**, as you would already be handling replication at the cluster level. + +So, in this case, you **would not** want to have multiple workers in the container, for example with the `--workers` command line option. You would want to have just a **single Uvicorn process** per container (but probably multiple containers). + +Having another process manager inside the container (as would be with multiple workers) would only add **unnecessary complexity** that you are most probably already taking care of with your cluster system. + +### Containers with Multiple Processes and Special Cases { #containers-with-multiple-processes-and-special-cases } + +Of course, there are **special cases** where you could want to have **a container** with several **Uvicorn worker processes** inside. + +In those cases, you can use the `--workers` command line option to set the number of workers that you want to run: + +```{ .dockerfile .annotate } +FROM python:3.14 + +WORKDIR /code + +COPY ./requirements.txt /code/requirements.txt + +RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt + +COPY ./app /code/app + +# (1)! +CMD ["fastapi", "run", "app/main.py", "--port", "80", "--workers", "4"] +``` + +1. Here we use the `--workers` command line option to set the number of workers to 4. + +Here are some examples of when that could make sense: + +#### A Simple App { #a-simple-app } + +You could want a process manager in the container if your application is **simple enough** that you can run it on a **single server**, not a cluster. + +#### Docker Compose { #docker-compose } + +You could be deploying to a **single server** (not a cluster) with **Docker Compose**, so you wouldn't have an easy way to manage replication of containers (with Docker Compose) while preserving the shared network and **load balancing**. + +Then you could want to have **a single container** with a **process manager** starting **several worker processes** inside. + +--- + +The main point is, **none** of these are **rules written in stone** that you have to blindly follow. You can use these ideas to **evaluate your own use case** and decide what is the best approach for your system, checking out how to manage the concepts of: + +* Security - HTTPS +* Running on startup +* Restarts +* Replication (the number of processes running) +* Memory +* Previous steps before starting + +## Memory { #memory } + +If you run **a single process per container** you will have a more or less well-defined, stable, and limited amount of memory consumed by each of those containers (more than one if they are replicated). + +And then you can set those same memory limits and requirements in your configurations for your container management system (for example in **Kubernetes**). That way it will be able to **replicate the containers** in the **available machines** taking into account the amount of memory needed by them, and the amount available in the machines in the cluster. + +If your application is **simple**, this will probably **not be a problem**, and you might not need to specify hard memory limits. But if you are **using a lot of memory** (for example with **machine learning** models), you should check how much memory you are consuming and adjust the **number of containers** that run on **each machine** (and maybe add more machines to your cluster). + +If you run **multiple processes per container** you will have to make sure that the number of processes started doesn't **consume more memory** than what is available. + +## Previous Steps Before Starting and Containers { #previous-steps-before-starting-and-containers } + +If you are using containers (e.g. Docker, Kubernetes), then there are two main approaches you can use. + +### Multiple Containers { #multiple-containers } + +If you have **multiple containers**, probably each one running a **single process** (for example, in a **Kubernetes** cluster), then you would probably want to have a **separate container** doing the work of the **previous steps** in a single container, running a single process, **before** running the replicated worker containers. + +/// note + +If you are using Kubernetes, this would probably be an [Init Container](https://kubernetes.io/docs/concepts/workloads/pods/init-containers/). + +/// + +If in your use case there's no problem in running those previous steps **multiple times in parallel** (for example if you are not running database migrations, but just checking if the database is ready yet), then you could also just put them in each container right before starting the main process. + +### Single Container { #single-container } + +If you have a simple setup, with a **single container** that then starts multiple **worker processes** (or also just one process), then you could run those previous steps in the same container, right before starting the process with the app. + +### Base Docker Image { #base-docker-image } + +There used to be an official FastAPI Docker image: [tiangolo/uvicorn-gunicorn-fastapi](https://github.com/tiangolo/uvicorn-gunicorn-fastapi-docker). But it is now deprecated. ⛔️ + +You should probably **not** use this base Docker image (or any other similar one). + +If you are using **Kubernetes** (or others) and you are already setting **replication** at the cluster level, with multiple **containers**. In those cases, you are better off **building an image from scratch** as described above: [Build a Docker Image for FastAPI](#build-a-docker-image-for-fastapi). + +And if you need to have multiple workers, you can simply use the `--workers` command line option. + +/// note | Technical Details + +The Docker image was created when Uvicorn didn't support managing and restarting dead workers, so it was needed to use Gunicorn with Uvicorn, which added quite some complexity, just to have Gunicorn manage and restart the Uvicorn worker processes. + +But now that Uvicorn (and the `fastapi` command) support using `--workers`, there's no reason to use a base Docker image instead of building your own (it's pretty much the same amount of code 😅). + +/// + +## Deploy the Container Image { #deploy-the-container-image } + +After having a Container (Docker) Image there are several ways to deploy it. + +For example: + +* With **Docker Compose** in a single server +* With a **Kubernetes** cluster +* With a Docker Swarm Mode cluster +* With another tool like Nomad +* With a cloud service that takes your container image and deploys it + +## Docker Image with `uv` { #docker-image-with-uv } + +If you are using [uv](https://github.com/astral-sh/uv) to install and manage your project, you can follow their [uv Docker guide](https://docs.astral.sh/uv/guides/integration/docker/). + +## Recap { #recap } + +Using container systems (e.g. with **Docker** and **Kubernetes**) it becomes fairly straightforward to handle all the **deployment concepts**: + +* HTTPS +* Running on startup +* Restarts +* Replication (the number of processes running) +* Memory +* Previous steps before starting + +In most cases, you probably won't want to use any base image, and instead **build a container image from scratch** based on the official Python Docker image. + +Taking care of the **order** of instructions in the `Dockerfile` and the **Docker cache** you can **minimize build times**, to maximize your productivity (and avoid boredom). 😎 diff --git a/docs/en/docs/deployment/fastapicloud.md b/docs/en/docs/deployment/fastapicloud.md new file mode 100644 index 0000000000000..dbc44f41a3665 --- /dev/null +++ b/docs/en/docs/deployment/fastapicloud.md @@ -0,0 +1,47 @@ +# FastAPI Cloud { #fastapi-cloud } + +You can deploy your FastAPI app to [FastAPI Cloud](https://fastapicloud.com) with just **one command**. 🚀 + +
+ +```console +$ fastapi deploy + +Deploying to FastAPI Cloud... + +✅ Deployment successful! + +🐔 Ready the chicken! Your app is ready at https://myapp.fastapicloud.dev +``` + +
+ +The CLI will automatically detect your FastAPI application and deploy it to the cloud. If you are not logged in, your browser will open to complete the authentication process. + +That's it! Now you can access your app at that URL. ✨ + +## About FastAPI Cloud { #about-fastapi-cloud } + +**[FastAPI Cloud](https://fastapicloud.com)** 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. 🎉 + +It will also take care of most of the things you would need when deploying an app, like: + +* HTTPS +* Replication, with autoscaling based on requests +* etc. + +FastAPI Cloud is the primary sponsor and funding provider for the *FastAPI and friends* open source projects. ✨ + +## Deploy to other cloud providers { #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. 🤓 + +## Deploy your own server { #deploy-your-own-server } + +I will also teach you later in this **Deployment** guide all the details, so you can understand what is going on, what needs to happen, or how to deploy FastAPI apps on your own, also with your own servers. 🤓 diff --git a/docs/en/docs/deployment/https.md b/docs/en/docs/deployment/https.md new file mode 100644 index 0000000000000..8280c1173dd49 --- /dev/null +++ b/docs/en/docs/deployment/https.md @@ -0,0 +1,231 @@ +# About HTTPS { #about-https } + +It is easy to assume that HTTPS is something that is just "enabled" or not. + +But it is way more complex than that. + +/// tip + +If you are in a hurry or don't care, continue with the next sections for step by step instructions to set everything up with different techniques. + +/// + +To **learn the basics of HTTPS**, from a consumer perspective, check [https://howhttps.works/](https://howhttps.works/). + +Now, from a **developer's perspective**, here are several things to keep in mind while thinking about HTTPS: + +* For HTTPS, **the server** needs to **have "certificates"** generated by a **third party**. + * Those certificates are actually **acquired** from the third party, not "generated". +* Certificates have a **lifetime**. + * They **expire**. + * And then they need to be **renewed**, **acquired again** from the third party. +* The encryption of the connection happens at the **TCP level**. + * That's one layer **below HTTP**. + * So, the **certificate and encryption** handling is done **before HTTP**. +* **TCP doesn't know about "domains"**. Only about IP addresses. + * The information about the **specific domain** requested goes in the **HTTP data**. +* The **HTTPS certificates** "certify" a **certain domain**, but the protocol and encryption happen at the TCP level, **before knowing** which domain is being dealt with. +* **By default**, that would mean that you can only have **one HTTPS certificate per IP address**. + * No matter how big your server is or how small each application you have on it might be. + * There is a **solution** to this, however. +* There's an **extension** to the **TLS** protocol (the one handling the encryption at the TCP level, before HTTP) called **[SNI](https://en.wikipedia.org/wiki/Server_Name_Indication)**. + * This SNI extension allows one single server (with a **single IP address**) to have **several HTTPS certificates** and serve **multiple HTTPS domains/applications**. + * For this to work, a **single** component (program) running on the server, listening on the **public IP address**, must have **all the HTTPS certificates** in the server. +* **After** obtaining a secure connection, the communication protocol is **still HTTP**. + * The contents are **encrypted**, even though they are being sent with the **HTTP protocol**. + +It is a common practice to have **one program/HTTP server** running on the server (the machine, host, etc.) and **managing all the HTTPS parts**: receiving the **encrypted HTTPS requests**, sending the **decrypted HTTP requests** to the actual HTTP application running in the same server (the **FastAPI** application, in this case), take the **HTTP response** from the application, **encrypt it** using the appropriate **HTTPS certificate** and sending it back to the client using **HTTPS**. This server is often called a **[TLS Termination Proxy](https://en.wikipedia.org/wiki/TLS_termination_proxy)**. + +Some of the options you could use as a TLS Termination Proxy are: + +* Traefik (that can also handle certificate renewals) +* Caddy (that can also handle certificate renewals) +* Nginx +* HAProxy + +## Let's Encrypt { #lets-encrypt } + +Before Let's Encrypt, these **HTTPS certificates** were sold by trusted third parties. + +The process to acquire one of these certificates used to be cumbersome, require quite some paperwork and the certificates were quite expensive. + +But then **[Let's Encrypt](https://letsencrypt.org/)** was created. + +It is a project from the Linux Foundation. It provides **HTTPS certificates for free**, in an automated way. These certificates use all the standard cryptographic security, and are short-lived (about 3 months), so the **security is actually better** because of their reduced lifespan. + +The domains are securely verified and the certificates are generated automatically. This also allows automating the renewal of these certificates. + +The idea is to automate the acquisition and renewal of these certificates so that you can have **secure HTTPS, for free, forever**. + +## HTTPS for Developers { #https-for-developers } + +Here's an example of how an HTTPS API could look, step by step, paying attention mainly to the ideas important for developers. + +### Domain Name { #domain-name } + +It would probably all start by you **acquiring** some **domain name**. Then, you would configure it in a DNS server (possibly your same cloud provider). + +You would probably get a cloud server (a virtual machine) or something similar, and it would have a fixed **public IP address**. + +In the DNS server(s) you would configure a record (an "`A record`") to point **your domain** to the public **IP address of your server**. + +You would probably do this just once, the first time, when setting everything up. + +/// tip + +This Domain Name part is way before HTTPS, but as everything depends on the domain and the IP address, it's worth mentioning it here. + +/// + +### DNS { #dns } + +Now let's focus on all the actual HTTPS parts. + +First, the browser would check with the **DNS servers** what is the **IP for the domain**, in this case, `someapp.example.com`. + +The DNS servers would tell the browser to use some specific **IP address**. That would be the public IP address used by your server, that you configured in the DNS servers. + + + +### TLS Handshake Start { #tls-handshake-start } + +The browser would then communicate with that IP address on **port 443** (the HTTPS port). + +The first part of the communication is just to establish the connection between the client and the server and to decide the cryptographic keys they will use, etc. + + + +This interaction between the client and the server to establish the TLS connection is called the **TLS handshake**. + +### TLS with SNI Extension { #tls-with-sni-extension } + +**Only one process** in the server can be listening on a specific **port** in a specific **IP address**. There could be other processes listening on other ports in the same IP address, but only one for each combination of IP address and port. + +TLS (HTTPS) uses the specific port `443` by default. So that's the port we would need. + +As only one process can be listening on this port, the process that would do it would be the **TLS Termination Proxy**. + +The TLS Termination Proxy would have access to one or more **TLS certificates** (HTTPS certificates). + +Using the **SNI extension** discussed above, the TLS Termination Proxy would check which of the TLS (HTTPS) certificates available it should use for this connection, using the one that matches the domain expected by the client. + +In this case, it would use the certificate for `someapp.example.com`. + + + +The client already **trusts** the entity that generated that TLS certificate (in this case Let's Encrypt, but we'll see about that later), so it can **verify** that the certificate is valid. + +Then, using the certificate, the client and the TLS Termination Proxy **decide how to encrypt** the rest of the **TCP communication**. This completes the **TLS Handshake** part. + +After this, the client and the server have an **encrypted TCP connection**, this is what TLS provides. And then they can use that connection to start the actual **HTTP communication**. + +And that's what **HTTPS** is, it's just plain **HTTP** inside a **secure TLS connection** instead of a pure (unencrypted) TCP connection. + +/// tip + +Notice that the encryption of the communication happens at the **TCP level**, not at the HTTP level. + +/// + +### HTTPS Request { #https-request } + +Now that the client and server (specifically the browser and the TLS Termination Proxy) have an **encrypted TCP connection**, they can start the **HTTP communication**. + +So, the client sends an **HTTPS request**. This is just an HTTP request through an encrypted TLS connection. + + + +### Decrypt the Request { #decrypt-the-request } + +The TLS Termination Proxy would use the encryption agreed to **decrypt the request**, and would transmit the **plain (decrypted) HTTP request** to the process running the application (for example a process with Uvicorn running the FastAPI application). + + + +### HTTP Response { #http-response } + +The application would process the request and send a **plain (unencrypted) HTTP response** to the TLS Termination Proxy. + + + +### HTTPS Response { #https-response } + +The TLS Termination Proxy would then **encrypt the response** using the cryptography agreed before (that started with the certificate for `someapp.example.com`), and send it back to the browser. + +Next, the browser would verify that the response is valid and encrypted with the right cryptographic key, etc. It would then **decrypt the response** and process it. + + + +The client (browser) will know that the response comes from the correct server because it is using the cryptography they agreed using the **HTTPS certificate** before. + +### Multiple Applications { #multiple-applications } + +In the same server (or servers), there could be **multiple applications**, for example, other API programs or a database. + +Only one process can be handling the specific IP and port (the TLS Termination Proxy in our example) but the other applications/processes can be running on the server(s) too, as long as they don't try to use the same **combination of public IP and port**. + + + +That way, the TLS Termination Proxy could handle HTTPS and certificates for **multiple domains**, for multiple applications, and then transmit the requests to the right application in each case. + +### Certificate Renewal { #certificate-renewal } + +At some point in the future, each certificate would **expire** (about 3 months after acquiring it). + +And then, there would be another program (in some cases it's another program, in some cases it could be the same TLS Termination Proxy) that would talk to Let's Encrypt, and renew the certificate(s). + + + +The **TLS certificates** are **associated with a domain name**, not with an IP address. + +So, to renew the certificates, the renewal program needs to **prove** to the authority (Let's Encrypt) that it indeed **"owns" and controls that domain**. + +To do that, and to accommodate different application needs, there are several ways it can do it. Some popular ways are: + +* **Modify some DNS records**. + * For this, the renewal program needs to support the APIs of the DNS provider, so, depending on the DNS provider you are using, this might or might not be an option. +* **Run as a server** (at least during the certificate acquisition process) on the public IP address associated with the domain. + * As we said above, only one process can be listening on a specific IP and port. + * This is one of the reasons why it's very useful when the same TLS Termination Proxy also takes care of the certificate renewal process. + * Otherwise, you might have to stop the TLS Termination Proxy momentarily, start the renewal program to acquire the certificates, then configure them with the TLS Termination Proxy, and then restart the TLS Termination Proxy. This is not ideal, as your app(s) will not be available during the time that the TLS Termination Proxy is off. + +All this renewal process, while still serving the app, is one of the main reasons why you would want to have a **separate system to handle HTTPS** with a TLS Termination Proxy instead of just using the TLS certificates with the application server directly (e.g. Uvicorn). + +## Proxy Forwarded Headers { #proxy-forwarded-headers } + +When using a proxy to handle HTTPS, your **application server** (for example Uvicorn via FastAPI CLI) doesn't know anything about the HTTPS process, it communicates with plain HTTP with the **TLS Termination Proxy**. + +This **proxy** would normally set some HTTP headers on the fly before transmitting the request to the **application server**, to let the application server know that the request is being **forwarded** by the proxy. + +/// note | Technical Details + +The proxy headers are: + +* [X-Forwarded-For](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Forwarded-For) +* [X-Forwarded-Proto](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Forwarded-Proto) +* [X-Forwarded-Host](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Forwarded-Host) + +/// + +Nevertheless, as the **application server** doesn't know it is behind a trusted **proxy**, by default, it wouldn't trust those headers. + +But you can configure the **application server** to trust the *forwarded* headers sent by the **proxy**. If you are using FastAPI CLI, you can use the *CLI Option* `--forwarded-allow-ips` to tell it from which IPs it should trust those *forwarded* headers. + +For example, if the **application server** is only receiving communication from the trusted **proxy**, you can set it to `--forwarded-allow-ips="*"` to make it trust all incoming IPs, as it will only receive requests from whatever is the IP used by the **proxy**. + +This way the application would be able to know what is its own public URL, if it is using HTTPS, the domain, etc. + +This would be useful for example to properly handle redirects. + +/// tip + +You can learn more about this in the documentation for [Behind a Proxy - Enable Proxy Forwarded Headers](../advanced/behind-a-proxy.md#enable-proxy-forwarded-headers) + +/// + +## Recap { #recap } + +Having **HTTPS** is very important, and quite **critical** in most cases. Most of the effort you as a developer have to put around HTTPS is just about **understanding these concepts** and how they work. + +But once you know the basic information of **HTTPS for developers** you can easily combine and configure different tools to help you manage everything in a simple way. + +In some of the next chapters, I'll show you several concrete examples of how to set up **HTTPS** for **FastAPI** applications. 🔒 diff --git a/docs/en/docs/deployment/index.md b/docs/en/docs/deployment/index.md new file mode 100644 index 0000000000000..973d81151f613 --- /dev/null +++ b/docs/en/docs/deployment/index.md @@ -0,0 +1,23 @@ +# Deployment { #deployment } + +Deploying a **FastAPI** application is relatively easy. + +## What Does Deployment Mean { #what-does-deployment-mean } + +To **deploy** an application means to perform the necessary steps to make it **available to the users**. + +For a **web API**, it normally involves putting it in a **remote machine**, with a **server program** that provides good performance, stability, etc, so that your **users** can **access** the application efficiently and without interruptions or problems. + +This is in contrast to the **development** stages, where you are constantly changing the code, breaking it and fixing it, stopping and restarting the development server, etc. + +## Deployment Strategies { #deployment-strategies } + +There are several ways to do it depending on your specific use case and the tools that you use. + +You could **deploy a server** yourself using a combination of tools, you could use a **cloud service** that does part of the work for you, or other possible options. + +For example, we, the team behind FastAPI, built [**FastAPI Cloud**](https://fastapicloud.com), to make deploying FastAPI apps to the cloud as streamlined as possible, with the same developer experience of working with FastAPI. + +I will show you some of the main concepts you should probably keep in mind when deploying a **FastAPI** application (although most of it applies to any other type of web application). + +You will see more details to keep in mind and some of the techniques to do it in the next sections. ✨ diff --git a/docs/en/docs/deployment/manually.md b/docs/en/docs/deployment/manually.md new file mode 100644 index 0000000000000..ed49aa00ac9b0 --- /dev/null +++ b/docs/en/docs/deployment/manually.md @@ -0,0 +1,156 @@ +# Run a Server Manually { #run-a-server-manually } + +## Use the `fastapi run` Command { #use-the-fastapi-run-command } + +In short, use `fastapi run` to serve your FastAPI application: + +
+ +```console +$ fastapi run main.py + + FastAPI Starting production server 🚀 + + Searching for package file structure from directories + with __init__.py files + Importing from /home/user/code/awesomeapp + + module 🐍 main.py + + code Importing the FastAPI app object from the module with + the following code: + + from main import app + + app Using import string: main:app + + server Server started at http://0.0.0.0:8000 + server Documentation at http://0.0.0.0:8000/docs + + Logs: + + INFO Started server process [2306215] + INFO Waiting for application startup. + INFO Application startup complete. + INFO Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C + to quit) +``` + +
+ +That would work for most of the cases. 😎 + +You could use that command for example to start your **FastAPI** app in a container, in a server, etc. + +## ASGI Servers { #asgi-servers } + +Let's go a little deeper into the details. + +FastAPI uses a standard for building Python web frameworks and servers called ASGI. FastAPI is an ASGI web framework. + +The main thing you need to run a **FastAPI** application (or any other ASGI application) in a remote server machine is an ASGI server program like **Uvicorn**, this is the one that comes by default in the `fastapi` command. + +There are several alternatives, including: + +* [Uvicorn](https://www.uvicorn.dev/): a high performance ASGI server. +* [Hypercorn](https://hypercorn.readthedocs.io/): an ASGI server compatible with HTTP/2 and Trio among other features. +* [Daphne](https://github.com/django/daphne): the ASGI server built for Django Channels. +* [Granian](https://github.com/emmett-framework/granian): A Rust HTTP server for Python applications. + +## Server Machine and Server Program { #server-machine-and-server-program } + +There's a small detail about names to keep in mind. 💡 + +The word "**server**" is commonly used to refer to both the remote/cloud computer (the physical or virtual machine) and also the program that is running on that machine (e.g. Uvicorn). + +Just keep in mind that when you read "server" in general, it could refer to one of those two things. + +When referring to the remote machine, it's common to call it **server**, but also **machine**, **VM** (virtual machine), **node**. Those all refer to some type of remote machine, normally running Linux, where you run programs. + +## Install the Server Program { #install-the-server-program } + +When you install FastAPI, it comes with a production server, Uvicorn, and you can start it with the `fastapi run` command. + +But you can also install an ASGI server manually. + +Make sure you create a [virtual environment](../virtual-environments.md), activate it, and then you can install the server application. + +For example, to install Uvicorn: + +
+ +```console +$ pip install "uvicorn[standard]" + +---> 100% +``` + +
+ +A similar process would apply to any other ASGI server program. + +/// tip + +By adding the `standard`, Uvicorn will install and use some recommended extra dependencies. + +That includes `uvloop`, the high-performance drop-in replacement for `asyncio`, that provides the big concurrency performance boost. + +When you install FastAPI with something like `pip install "fastapi[standard]"` you already get `uvicorn[standard]` as well. + +/// + +## Run the Server Program { #run-the-server-program } + +If you installed an ASGI server manually, you would normally need to pass an import string in a special format for it to import your FastAPI application: + +
+ +```console +$ uvicorn main:app --host 0.0.0.0 --port 80 + +INFO: Uvicorn running on http://0.0.0.0:80 (Press CTRL+C to quit) +``` + +
+ +/// note + +The command `uvicorn main:app` refers to: + +* `main`: the file `main.py` (the Python "module"). +* `app`: the object created inside of `main.py` with the line `app = FastAPI()`. + +It is equivalent to: + +```Python +from main import app +``` + +/// + +Each alternative ASGI server program would have a similar command, you can read more in their respective documentation. + +/// warning + +Uvicorn and other servers support a `--reload` option that is useful during development. + +The `--reload` option consumes much more resources, is more unstable, etc. + +It helps a lot during **development**, but you **shouldn't** use it in **production**. + +/// + +## Deployment Concepts { #deployment-concepts } + +These examples run the server program (e.g Uvicorn), starting **a single process**, listening on all the IPs (`0.0.0.0`) on a predefined port (e.g. `80`). + +This is the basic idea. But you will probably want to take care of some additional things, like: + +* Security - HTTPS +* Running on startup +* Restarts +* Replication (the number of processes running) +* Memory +* Previous steps before starting + +I'll tell you more about each of these concepts, how to think about them, and some concrete examples with strategies to handle them in the next chapters. 🚀 diff --git a/docs/en/docs/deployment/server-workers.md b/docs/en/docs/deployment/server-workers.md new file mode 100644 index 0000000000000..fb0741acb2127 --- /dev/null +++ b/docs/en/docs/deployment/server-workers.md @@ -0,0 +1,139 @@ +# Server Workers - Uvicorn with Workers { #server-workers-uvicorn-with-workers } + +Let's check back those deployment concepts from before: + +* Security - HTTPS +* Running on startup +* Restarts +* **Replication (the number of processes running)** +* Memory +* Previous steps before starting + +Up to this point, with all the tutorials in the docs, you have probably been running a **server program**, for example, using the `fastapi` command, that runs Uvicorn, running a **single process**. + +When deploying applications you will probably want to have some **replication of processes** to take advantage of **multiple cores** and to be able to handle more requests. + +As you saw in the previous chapter about [Deployment Concepts](concepts.md), there are multiple strategies you can use. + +Here I'll show you how to use **Uvicorn** with **worker processes** using the `fastapi` command or the `uvicorn` command directly. + +/// note + +If you are using containers, for example with Docker or Kubernetes, I'll tell you more about that in the next chapter: [FastAPI in Containers - Docker](docker.md). + +In particular, when running on **Kubernetes** you will probably **not** want to use workers and instead run **a single Uvicorn process per container**, but I'll tell you about it later in that chapter. + +/// + +## Multiple Workers { #multiple-workers } + +You can start multiple workers with the `--workers` command line option: + +//// tab | `fastapi` + +If you use the `fastapi` command: + +
+ +```console +$ fastapi run --workers 4 main.py + + FastAPI Starting production server 🚀 + + Searching for package file structure from directories with + __init__.py files + Importing from /home/user/code/awesomeapp + + module 🐍 main.py + + code Importing the FastAPI app object from the module with the + following code: + + from main import app + + app Using import string: main:app + + server Server started at http://0.0.0.0:8000 + server Documentation at http://0.0.0.0:8000/docs + + Logs: + + INFO Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to + quit) + INFO Started parent process [27365] + INFO Started server process [27368] + INFO Started server process [27369] + INFO Started server process [27370] + INFO Started server process [27367] + INFO Waiting for application startup. + INFO Waiting for application startup. + INFO Waiting for application startup. + INFO Waiting for application startup. + INFO Application startup complete. + INFO Application startup complete. + INFO Application startup complete. + INFO Application startup complete. +``` + +
+ +//// + +//// tab | `uvicorn` + +If you prefer to use the `uvicorn` command directly: + +
+ +```console +$ uvicorn main:app --host 0.0.0.0 --port 8080 --workers 4 +INFO: Uvicorn running on http://0.0.0.0:8080 (Press CTRL+C to quit) +INFO: Started parent process [27365] +INFO: Started server process [27368] +INFO: Waiting for application startup. +INFO: Application startup complete. +INFO: Started server process [27369] +INFO: Waiting for application startup. +INFO: Application startup complete. +INFO: Started server process [27370] +INFO: Waiting for application startup. +INFO: Application startup complete. +INFO: Started server process [27367] +INFO: Waiting for application startup. +INFO: Application startup complete. +``` + +
+ +//// + +The only new option here is `--workers` telling Uvicorn to start 4 worker processes. + +You can also see that it shows the **PID** of each process, `27365` for the parent process (this is the **process manager**) and one for each worker process: `27368`, `27369`, `27370`, and `27367`. + +## Deployment Concepts { #deployment-concepts } + +Here you saw how to use multiple **workers** to **parallelize** the execution of the application, take advantage of **multiple cores** in the CPU, and be able to serve **more requests**. + +From the list of deployment concepts from above, using workers would mainly help with the **replication** part, and a little bit with the **restarts**, but you still need to take care of the others: + +* **Security - HTTPS** +* **Running on startup** +* ***Restarts*** +* Replication (the number of processes running) +* **Memory** +* **Previous steps before starting** + +## Containers and Docker { #containers-and-docker } + +In the next chapter about [FastAPI in Containers - Docker](docker.md) I'll explain some strategies you could use to handle the other **deployment concepts**. + +I'll show you how to **build your own image from scratch** to run a single Uvicorn process. It is a simple process and is probably what you would want to do when using a distributed container management system like **Kubernetes**. + +## Recap { #recap } + +You can use multiple worker processes with the `--workers` CLI option with the `fastapi` or `uvicorn` commands to take advantage of **multi-core CPUs**, to run **multiple processes in parallel**. + +You could use these tools and ideas if you are setting up **your own deployment system** while taking care of the other deployment concepts yourself. + +Check out the next chapter to learn about **FastAPI** with containers (e.g. Docker and Kubernetes). You will see that those tools have simple ways to solve the other **deployment concepts** as well. ✨ diff --git a/docs/en/docs/deployment/versions.md b/docs/en/docs/deployment/versions.md new file mode 100644 index 0000000000000..6c03fac39c122 --- /dev/null +++ b/docs/en/docs/deployment/versions.md @@ -0,0 +1,93 @@ +# About FastAPI versions { #about-fastapi-versions } + +**FastAPI** is already being used in production in many applications and systems. And the test coverage is kept at 100%. But its development is still moving quickly. + +New features are added frequently, bugs are fixed regularly, and the code is still continuously improving. + +That's why the current versions are still `0.x.x`, this reflects that each version could potentially have breaking changes. This follows the [Semantic Versioning](https://semver.org/) conventions. + +You can create production applications with **FastAPI** right now (and you have probably been doing it for some time), you just have to make sure that you use a version that works correctly with the rest of your code. + +## Pin your `fastapi` version { #pin-your-fastapi-version } + +The first thing you should do is to "pin" the version of **FastAPI** you are using to the specific latest version that you know works correctly for your application. + +For example, let's say you are using version `0.112.0` in your app. + +If you use a `requirements.txt` file you could specify the version with: + +```txt +fastapi[standard]==0.112.0 +``` + +that would mean that you would use exactly the version `0.112.0`. + +Or you could also pin it with: + +```txt +fastapi[standard]>=0.112.0,<0.113.0 +``` + +that would mean that you would use the versions `0.112.0` or above, but less than `0.113.0`, for example, a version `0.112.2` would still be accepted. + +If you use any other tool to manage your installations, like `uv`, Poetry, Pipenv, or others, they all have a way that you can use to define specific versions for your packages. + +## Available versions { #available-versions } + +You can see the available versions (e.g. to check what is the current latest) in the [Release Notes](../release-notes.md). + +## About versions { #about-versions } + +Following the Semantic Versioning conventions, any version below `1.0.0` could potentially add breaking changes. + +FastAPI also follows the convention that any "PATCH" version change is for bug fixes and non-breaking changes. + +/// tip + +The "PATCH" is the last number, for example, in `0.2.3`, the PATCH version is `3`. + +/// + +So, you should be able to pin to a version like: + +```txt +fastapi>=0.45.0,<0.46.0 +``` + +Breaking changes and new features are added in "MINOR" versions. + +/// tip + +The "MINOR" is the number in the middle, for example, in `0.2.3`, the MINOR version is `2`. + +/// + +## Upgrading the FastAPI versions { #upgrading-the-fastapi-versions } + +You should add tests for your app. + +With **FastAPI** it's very easy (thanks to Starlette), check the docs: [Testing](../tutorial/testing.md) + +After you have tests, then you can upgrade the **FastAPI** version to a more recent one, and make sure that all your code is working correctly by running your tests. + +If everything is working, or after you make the necessary changes, and all your tests are passing, then you can pin your `fastapi` to that new recent version. + +## About Starlette { #about-starlette } + +You shouldn't pin the version of `starlette`. + +Different versions of **FastAPI** will use a specific newer version of Starlette. + +So, you can just let **FastAPI** use the correct Starlette version. + +## About Pydantic { #about-pydantic } + +Pydantic includes the tests for **FastAPI** with its own tests, so new versions of Pydantic (above `1.0.0`) are always compatible with FastAPI. + +You can pin Pydantic to any version above `1.0.0` that works for you. + +For example: + +```txt +pydantic>=2.7.0,<3.0.0 +``` diff --git a/docs/en/docs/editor-support.md b/docs/en/docs/editor-support.md new file mode 100644 index 0000000000000..0936456ebe688 --- /dev/null +++ b/docs/en/docs/editor-support.md @@ -0,0 +1,23 @@ +# Editor Support { #editor-support } + +The official [FastAPI Extension](https://marketplace.visualstudio.com/items?itemName=FastAPILabs.fastapi-vscode) enhances your FastAPI development workflow with *path operation* discovery, navigation, as well as FastAPI Cloud deployment, and live log streaming. + +For more details about the extension, refer to the README on the [GitHub repository](https://github.com/fastapi/fastapi-vscode). + +## Setup and Installation { #setup-and-installation } + +The **FastAPI Extension** is available for both [VS Code](https://code.visualstudio.com/) and [Cursor](https://www.cursor.com/). It can be installed directly from the Extensions panel in each editor by searching for "FastAPI" and selecting the extension published by **FastAPI Labs**. The extension also works in browser-based editors such as [vscode.dev](https://vscode.dev) and [github.dev](https://github.dev). + +### Application Discovery { #application-discovery } + +By default, the extension will automatically discover FastAPI applications in your workspace by scanning for files that instantiate `FastAPI()`. If auto-detection doesn't work for your project structure, you can specify an entrypoint via `[tool.fastapi]` in `pyproject.toml` or the `fastapi.entryPoint` VS Code setting using module notation (e.g. `myapp.main:app`). + +## Features { #features } + +- **Path Operation Explorer** - A sidebar tree view of all *path operations* in your application. Click to jump to any route or router definition. +- **Route Search** - Search by path, method, or name with Ctrl + Shift + E (on macOS: Cmd + Shift + E). +- **CodeLens Navigation** - Clickable links above test client calls (e.g. `client.get('/items')`) that jump to the matching *path operation* for quick navigation between tests and implementation. +- **Deploy to FastAPI Cloud** - One-click deployment of your app to [FastAPI Cloud](https://fastapicloud.com/). +- **Stream Application Logs** - Real-time log streaming from your FastAPI Cloud-deployed application with level filtering and text search. + +If you'd like to familiarize yourself with the extension's features, you can check out the extension walkthrough by opening the Command Palette (Ctrl + Shift + P or on macOS: Cmd + Shift + P) and selecting "Welcome: Open walkthrough..." and then choosing the "Get started with FastAPI" walkthrough. diff --git a/docs/en/docs/environment-variables.md b/docs/en/docs/environment-variables.md new file mode 100644 index 0000000000000..b123694318b82 --- /dev/null +++ b/docs/en/docs/environment-variables.md @@ -0,0 +1,298 @@ +# Environment Variables { #environment-variables } + +/// tip + +If you already know what "environment variables" are and how to use them, feel free to skip this. + +/// + +An environment variable (also known as "**env var**") is a variable that lives **outside** of the Python code, in the **operating system**, and could be read by your Python code (or by other programs as well). + +Environment variables could be useful for handling application **settings**, as part of the **installation** of Python, etc. + +## Create and Use Env Vars { #create-and-use-env-vars } + +You can **create** and use environment variables in the **shell (terminal)**, without needing Python: + +//// tab | Linux, macOS, Windows Bash + +
+ +```console +// You could create an env var MY_NAME with +$ export MY_NAME="Wade Wilson" + +// Then you could use it with other programs, like +$ echo "Hello $MY_NAME" + +Hello Wade Wilson +``` + +
+ +//// + +//// tab | Windows PowerShell + +
+ +```console +// Create an env var MY_NAME +$ $Env:MY_NAME = "Wade Wilson" + +// Use it with other programs, like +$ echo "Hello $Env:MY_NAME" + +Hello Wade Wilson +``` + +
+ +//// + +## Read env vars in Python { #read-env-vars-in-python } + +You could also create environment variables **outside** of Python, in the terminal (or with any other method), and then **read them in Python**. + +For example you could have a file `main.py` with: + +```Python hl_lines="3" +import os + +name = os.getenv("MY_NAME", "World") +print(f"Hello {name} from Python") +``` + +/// tip + +The second argument to [`os.getenv()`](https://docs.python.org/3.8/library/os.html#os.getenv) is the default value to return. + +If not provided, it's `None` by default, here we provide `"World"` as the default value to use. + +/// + +Then you could call that Python program: + +//// tab | Linux, macOS, Windows Bash + +
+ +```console +// Here we don't set the env var yet +$ python main.py + +// As we didn't set the env var, we get the default value + +Hello World from Python + +// But if we create an environment variable first +$ export MY_NAME="Wade Wilson" + +// And then call the program again +$ python main.py + +// Now it can read the environment variable + +Hello Wade Wilson from Python +``` + +
+ +//// + +//// tab | Windows PowerShell + +
+ +```console +// Here we don't set the env var yet +$ python main.py + +// As we didn't set the env var, we get the default value + +Hello World from Python + +// But if we create an environment variable first +$ $Env:MY_NAME = "Wade Wilson" + +// And then call the program again +$ python main.py + +// Now it can read the environment variable + +Hello Wade Wilson from Python +``` + +
+ +//// + +As environment variables can be set outside of the code, but can be read by the code, and don't have to be stored (committed to `git`) with the rest of the files, it's common to use them for configurations or **settings**. + +You can also create an environment variable only for a **specific program invocation**, that is only available to that program, and only for its duration. + +To do that, create it right before the program itself, on the same line: + +
+ +```console +// Create an env var MY_NAME in line for this program call +$ MY_NAME="Wade Wilson" python main.py + +// Now it can read the environment variable + +Hello Wade Wilson from Python + +// The env var no longer exists afterwards +$ python main.py + +Hello World from Python +``` + +
+ +/// tip + +You can read more about it at [The Twelve-Factor App: Config](https://12factor.net/config). + +/// + +## Types and Validation { #types-and-validation } + +These environment variables can only handle **text strings**, as they are external to Python and have to be compatible with other programs and the rest of the system (and even with different operating systems, such as Linux, Windows, and macOS). + +That means that **any value** read in Python from an environment variable **will be a `str`**, and any conversion to a different type or any validation has to be done in code. + +You will learn more about using environment variables for handling **application settings** in the [Advanced User Guide - Settings and Environment Variables](./advanced/settings.md). + +## `PATH` Environment Variable { #path-environment-variable } + +There is a **special** environment variable called **`PATH`** that is used by the operating systems (Linux, macOS, Windows) to find programs to run. + +The value of the variable `PATH` is a long string that is made of directories separated by a colon `:` on Linux and macOS, and by a semicolon `;` on Windows. + +For example, the `PATH` environment variable could look like this: + +//// tab | Linux, macOS + +```plaintext +/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin +``` + +This means that the system should look for programs in the directories: + +* `/usr/local/bin` +* `/usr/bin` +* `/bin` +* `/usr/sbin` +* `/sbin` + +//// + +//// tab | Windows + +```plaintext +C:\Program Files\Python312\Scripts;C:\Program Files\Python312;C:\Windows\System32 +``` + +This means that the system should look for programs in the directories: + +* `C:\Program Files\Python312\Scripts` +* `C:\Program Files\Python312` +* `C:\Windows\System32` + +//// + +When you type a **command** in the terminal, the operating system **looks for** the program in **each of those directories** listed in the `PATH` environment variable. + +For example, when you type `python` in the terminal, the operating system looks for a program called `python` in the **first directory** in that list. + +If it finds it, then it will **use it**. Otherwise it keeps looking in the **other directories**. + +### Installing Python and Updating the `PATH` { #installing-python-and-updating-the-path } + +When you install Python, you might be asked if you want to update the `PATH` environment variable. + +//// tab | Linux, macOS + +Let's say you install Python and it ends up in a directory `/opt/custompython/bin`. + +If you say yes to update the `PATH` environment variable, then the installer will add `/opt/custompython/bin` to the `PATH` environment variable. + +It could look like this: + +```plaintext +/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/custompython/bin +``` + +This way, when you type `python` in the terminal, the system will find the Python program in `/opt/custompython/bin` (the last directory) and use that one. + +//// + +//// tab | Windows + +Let's say you install Python and it ends up in a directory `C:\opt\custompython\bin`. + +If you say yes to update the `PATH` environment variable, then the installer will add `C:\opt\custompython\bin` to the `PATH` environment variable. + +```plaintext +C:\Program Files\Python312\Scripts;C:\Program Files\Python312;C:\Windows\System32;C:\opt\custompython\bin +``` + +This way, when you type `python` in the terminal, the system will find the Python program in `C:\opt\custompython\bin` (the last directory) and use that one. + +//// + +So, if you type: + +
+ +```console +$ python +``` + +
+ +//// tab | Linux, macOS + +The system will **find** the `python` program in `/opt/custompython/bin` and run it. + +It would be roughly equivalent to typing: + +
+ +```console +$ /opt/custompython/bin/python +``` + +
+ +//// + +//// tab | Windows + +The system will **find** the `python` program in `C:\opt\custompython\bin\python` and run it. + +It would be roughly equivalent to typing: + +
+ +```console +$ C:\opt\custompython\bin\python +``` + +
+ +//// + +This information will be useful when learning about [Virtual Environments](virtual-environments.md). + +## Conclusion { #conclusion } + +With this you should have a basic understanding of what **environment variables** are and how to use them in Python. + +You can also read more about them in the [Wikipedia for Environment Variable](https://en.wikipedia.org/wiki/Environment_variable). + +In many cases it's not very obvious how environment variables would be useful and applicable right away. But they keep showing up in many different scenarios when you are developing, so it's good to know about them. + +For example, you will need this information in the next section, about [Virtual Environments](virtual-environments.md). diff --git a/docs/en/docs/external-links.md b/docs/en/docs/external-links.md new file mode 100644 index 0000000000000..d614c64eb62f8 --- /dev/null +++ b/docs/en/docs/external-links.md @@ -0,0 +1,30 @@ +--- +include_yaml: + topic_repos: data/topic_repos.yml +--- + +# External Links + +**FastAPI** has a great community constantly growing. + +There are many posts, articles, tools, and projects related to **FastAPI**. + +You could easily use a search engine or video platform to find many resources related to FastAPI. + +/// note + +Before, this page used to list links to external articles. + +But now that FastAPI is the backend framework with the most GitHub stars across languages, and the most starred and used framework in Python, it no longer makes sense to attempt to list all articles written about it. + +/// + +## GitHub Repositories + +Most starred [GitHub repositories with the topic `fastapi`](https://github.com/topics/fastapi): + +{% for repo in topic_repos %} + +★ {{repo.stars}} - {{repo.name}} by @{{repo.owner_login}}. + +{% endfor %} diff --git a/docs/en/docs/fastapi-cli.md b/docs/en/docs/fastapi-cli.md new file mode 100644 index 0000000000000..9d8f415d9babf --- /dev/null +++ b/docs/en/docs/fastapi-cli.md @@ -0,0 +1,134 @@ +# FastAPI CLI { #fastapi-cli } + +**FastAPI CLI** is a command line program that you can use to serve your FastAPI app, manage your FastAPI project, and more. + +When you install FastAPI (e.g. with `pip install "fastapi[standard]"`), it comes with a command line program you can run in the terminal. + +To run your FastAPI app for development, you can use the `fastapi dev` command: + +
+ +```console +$ fastapi dev + + FastAPI Starting development server 🚀 + + Searching for package file structure from directories with + __init__.py files + Importing from /home/user/code/awesomeapp + + module 🐍 main.py + + code Importing the FastAPI app object from the module with the + following code: + + from main import app + + app Using import string: main:app + + server Server started at http://127.0.0.1:8000 + server Documentation at http://127.0.0.1:8000/docs + + tip Running in development mode, for production use: + fastapi run + + Logs: + + INFO Will watch for changes in these directories: + ['/home/user/code/awesomeapp'] + INFO Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to + quit) + INFO Started reloader process [383138] using WatchFiles + INFO Started server process [383153] + INFO Waiting for application startup. + INFO Application startup complete. +``` + +
+ +/// tip + +For production you would use `fastapi run` instead of `fastapi dev`. 🚀 + +/// + +Internally, **FastAPI CLI** uses [Uvicorn](https://www.uvicorn.dev), a high-performance, production-ready, ASGI server. 😎 + +The `fastapi` CLI will try to detect automatically the FastAPI app to run, assuming it's an object called `app` in a file `main.py` (or a couple other variants). + +But you can configure explicitly the app to use. + +## Configure the app `entrypoint` in `pyproject.toml` { #configure-the-app-entrypoint-in-pyproject-toml } + +You can configure where your app is located in a `pyproject.toml` file like: + +```toml +[tool.fastapi] +entrypoint = "main:app" +``` + +That `entrypoint` will tell the `fastapi` command that it should import the app like: + +```python +from main import app +``` + +If your code was structured like: + +``` +. +├── backend +│   ├── main.py +│   ├── __init__.py +``` + +Then you would set the `entrypoint` as: + +```toml +[tool.fastapi] +entrypoint = "backend.main:app" +``` + +which would be equivalent to: + +```python +from backend.main import app +``` + +### `fastapi dev` with path or with `--entrypoint` CLI option { #fastapi-dev-with-path-or-with-entrypoint-cli-option } + +You can also pass the file path to the `fastapi dev` command, and it will guess the FastAPI app object to use: + +```console +$ fastapi dev main.py +``` + +Or, you can also pass the `--entrypoint` option to the `fastapi dev` command: + +```console +$ fastapi dev --entrypoint main:app +``` + +But you would have to remember to pass the correct path\entrypoint every time you call the `fastapi` command. + +Additionally, other tools might not be able to find it, for example the [VS Code Extension](editor-support.md) or [FastAPI Cloud](https://fastapicloud.com), so it is recommended to use the `entrypoint` in `pyproject.toml`. + +## `fastapi dev` { #fastapi-dev } + +Running `fastapi dev` initiates development mode. + +By default, **auto-reload** is enabled, automatically reloading the server when you make changes to your code. This is resource-intensive and could be less stable than when it's disabled. You should only use it for development. It also listens on the IP address `127.0.0.1`, which is the IP for your machine to communicate with itself alone (`localhost`). + +## `fastapi run` { #fastapi-run } + +Executing `fastapi run` starts FastAPI in production mode. + +By default, **auto-reload** is disabled. It also listens on the IP address `0.0.0.0`, which means all the available IP addresses, this way it will be publicly accessible to anyone that can communicate with the machine. This is how you would normally run it in production, for example, in a container. + +In most cases you would (and should) have a "termination proxy" handling HTTPS for you on top, this will depend on how you deploy your application, your provider might do this for you, or you might need to set it up yourself. + +/// tip + +You can learn more about it in the [deployment documentation](deployment/index.md). + +/// diff --git a/docs/en/docs/fastapi-people.md b/docs/en/docs/fastapi-people.md new file mode 100644 index 0000000000000..e79928fb324b3 --- /dev/null +++ b/docs/en/docs/fastapi-people.md @@ -0,0 +1,294 @@ +--- +hide: + - navigation + +include_yaml: + github_sponsors: data/github_sponsors.yml + people: data/people.yml + contributors: data/contributors.yml + translation_reviewers: data/translation_reviewers.yml + skip_users: data/skip_users.yml + members: data/members.yml + sponsors_badge: data/sponsors_badge.yml + sponsors: data/sponsors.yml +--- + +# FastAPI People + +FastAPI has an amazing community that welcomes people from all backgrounds. + +## Creator + +Hey! 👋 + +This is me: + +
+{% for user in people.maintainers %} + +
@{{ contributors.tiangolo.login }}
Answers: {{ user.answers }}
Pull Requests: {{ contributors.tiangolo.count }}
+{% endfor %} + +
+ +I'm the creator of **FastAPI**. You can read more about that in [Help FastAPI - Follow the author](help-fastapi.md#follow-the-author). + +...But here I want to show you the community. + +--- + +**FastAPI** receives a lot of support from the community. And I want to highlight their contributions. + +These are the people that: + +* [Help others with questions in GitHub](help-fastapi.md#help-others-with-questions-in-github). +* Create or review Pull Requests. +* Help [manage the repository](https://tiangolo.com/open-source/management-tasks/) (team members). + +All these tasks help maintain the repository. + +A round of applause to them. 👏 🙇 + +## Team + +This is the current list of team members. 😎 + +They have different levels of involvement and permissions, they can perform [repository management tasks](https://tiangolo.com/open-source/management-tasks/) and together we [manage the FastAPI repository](./management.md). + +
+ +{% for user in members["members"] %} + + + +{% endfor %} + +
+ +Although the team members have the permissions to perform privileged tasks, all the help from others maintaining FastAPI is very much appreciated! 🙇‍♂️ + +## FastAPI Experts + +These are the users that have been [helping others the most with questions in GitHub](help-fastapi.md#help-others-with-questions-in-github). 🙇 + +They have proven to be **FastAPI Experts** by helping many others. ✨ + +/// tip + +You could become an official FastAPI Expert too! + +Just [help others with questions in GitHub](help-fastapi.md#help-others-with-questions-in-github). 🤓 + +/// + +You can see the **FastAPI Experts** for: + +* [Last Month](#fastapi-experts-last-month) 🤓 +* [3 Months](#fastapi-experts-3-months) 😎 +* [6 Months](#fastapi-experts-6-months) 🧐 +* [1 Year](#fastapi-experts-1-year) 🧑‍🔬 +* [**All Time**](#fastapi-experts-all-time) 🧙 + +### FastAPI Experts - Last Month + +These are the users that have been [helping others the most with questions in GitHub](help-fastapi.md#help-others-with-questions-in-github) during the last month. 🤓 + +
+ +{% for user in people.last_month_experts[:10] %} + +{% if user.login not in skip_users %} + +
@{{ user.login }}
Questions replied: {{ user.count }}
+ +{% endif %} + +{% endfor %} + +
+ +### FastAPI Experts - 3 Months + +These are the users that have been [helping others the most with questions in GitHub](help-fastapi.md#help-others-with-questions-in-github) during the last 3 months. 😎 + +
+ +{% for user in people.three_months_experts[:10] %} + +{% if user.login not in skip_users %} + +
@{{ user.login }}
Questions replied: {{ user.count }}
+ +{% endif %} + +{% endfor %} + +
+ +### FastAPI Experts - 6 Months + +These are the users that have been [helping others the most with questions in GitHub](help-fastapi.md#help-others-with-questions-in-github) during the last 6 months. 🧐 + +
+ +{% for user in people.six_months_experts[:10] %} + +{% if user.login not in skip_users %} + +
@{{ user.login }}
Questions replied: {{ user.count }}
+ +{% endif %} + +{% endfor %} + +
+ +### FastAPI Experts - 1 Year + +These are the users that have been [helping others the most with questions in GitHub](help-fastapi.md#help-others-with-questions-in-github) during the last year. 🧑‍🔬 + +
+ +{% for user in people.one_year_experts[:20] %} + +{% if user.login not in skip_users %} + +
@{{ user.login }}
Questions replied: {{ user.count }}
+ +{% endif %} + +{% endfor %} + +
+ +### FastAPI Experts - All Time + +Here are the all time **FastAPI Experts**. 🤓🤯 + +These are the users that have [helped others the most with questions in GitHub](help-fastapi.md#help-others-with-questions-in-github) through *all time*. 🧙 + +
+ +{% for user in people.experts[:50] %} + +{% if user.login not in skip_users %} + +
@{{ user.login }}
Questions replied: {{ user.count }}
+ +{% endif %} + +{% endfor %} + +
+ +## Top Contributors + +Here are the **Top Contributors**. 👷 + +These users have created the most Pull Requests that have been *merged*. + +They have contributed source code, documentation, etc. 📦 + +
+ +{% for user in (contributors.values() | list)[:50] %} + +{% if user.login not in skip_users %} + +
@{{ user.login }}
Pull Requests: {{ user.count }}
+ +{% endif %} + +{% endfor %} + +
+ +There are hundreds of other contributors, you can see them all in the [FastAPI GitHub Contributors page](https://github.com/fastapi/fastapi/graphs/contributors). 👷 + +## Top Translation Reviewers + +These users are the **Top Translation Reviewers**. 🕵️ + +Translation reviewers have the **power to approve translations** of the documentation. Without them, there wouldn't be documentation in several other languages. + +
+{% for user in (translation_reviewers.values() | list)[:50] %} + +{% if user.login not in skip_users %} + +
@{{ user.login }}
Reviews: {{ user.count }}
+ +{% endif %} + +{% endfor %} + +
+ +## Sponsors + +These are the **Sponsors**. 😎 + +They are supporting my work with **FastAPI** (and others), mainly through [GitHub Sponsors](https://github.com/sponsors/tiangolo). + +{% if sponsors %} + +{% if sponsors.gold %} + +### Gold Sponsors + +{% for sponsor in sponsors.gold -%} + +{% endfor %} +{% endif %} + +{% if sponsors.silver %} + +### Silver Sponsors + +{% for sponsor in sponsors.silver -%} + +{% endfor %} +{% endif %} + +{% if sponsors.bronze %} + +### Bronze Sponsors + +{% for sponsor in sponsors.bronze -%} + +{% endfor %} +{% endif %} + +{% endif %} + +### Individual Sponsors + +{% if github_sponsors %} +{% for group in github_sponsors.sponsors %} + +
+ +{% for user in group %} +{% if user.login not in sponsors_badge.logins %} + + + +{% endif %} +{% endfor %} + +
+ +{% endfor %} +{% endif %} + +## About the data - technical details + +The main intention of this page is to highlight the effort of the community to help others. + +Especially including efforts that are normally less visible, and in many cases more arduous, like helping others with questions and reviewing Pull Requests with translations. + +The data is calculated each month, you can read the [source code here](https://github.com/fastapi/fastapi/blob/master/scripts/). + +Here I'm also highlighting contributions from sponsors. + +I also reserve the right to update the algorithm, sections, thresholds, etc (just in case 🤷). diff --git a/docs/en/docs/features.md b/docs/en/docs/features.md new file mode 100644 index 0000000000000..b4cafd00a779d --- /dev/null +++ b/docs/en/docs/features.md @@ -0,0 +1,201 @@ +# Features { #features } + +## FastAPI features { #fastapi-features } + +**FastAPI** gives you the following: + +### Based on open standards { #based-on-open-standards } + +* [**OpenAPI**](https://github.com/OAI/OpenAPI-Specification) for API creation, including declarations of path operations, parameters, request bodies, security, etc. +* Automatic data model documentation with [**JSON Schema**](https://json-schema.org/) (as OpenAPI itself is based on JSON Schema). +* Designed around these standards, after a meticulous study. Instead of an afterthought layer on top. +* This also allows using automatic **client code generation** in many languages. + +### Automatic docs { #automatic-docs } + +Interactive API documentation and exploration web user interfaces. As the framework is based on OpenAPI, there are multiple options, 2 included by default. + +* [**Swagger UI**](https://github.com/swagger-api/swagger-ui), with interactive exploration, call and test your API directly from the browser. + +![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-03-swagger-02.png) + +* Alternative API documentation with [**ReDoc**](https://github.com/Rebilly/ReDoc). + +![ReDoc](https://fastapi.tiangolo.com/img/index/index-06-redoc-02.png) + +### Just Modern Python { #just-modern-python } + +It's all based on standard **Python type** declarations (thanks to Pydantic). No new syntax to learn. Just standard modern Python. + +If you need a 2 minute refresher of how to use Python types (even if you don't use FastAPI), check the short tutorial: [Python Types](python-types.md). + +You write standard Python with types: + +```Python +from datetime import date + +from pydantic import BaseModel + +# Declare a variable as a str +# and get editor support inside the function +def main(user_id: str): + return user_id + + +# A Pydantic model +class User(BaseModel): + id: int + name: str + joined: date +``` + +That can then be used like: + +```Python +my_user: User = User(id=3, name="John Doe", joined="2018-07-19") + +second_user_data = { + "id": 4, + "name": "Mary", + "joined": "2018-11-30", +} + +my_second_user: User = User(**second_user_data) +``` + +/// note + +`**second_user_data` means: + +Pass the keys and values of the `second_user_data` dict directly as key-value arguments, equivalent to: `User(id=4, name="Mary", joined="2018-11-30")` + +/// + +### Editor support { #editor-support } + +The whole framework was designed to be easy and intuitive to use, all the decisions were tested on multiple editors even before starting development, to ensure the best development experience. + +In the Python developer surveys, it's clear [that one of the most used features is "autocompletion"](https://www.jetbrains.com/research/python-developers-survey-2017/#tools-and-features). + +The whole **FastAPI** framework is designed to satisfy that. Autocompletion works everywhere. + +You will rarely need to come back to the docs. + +Here's how your editor might help you: + +* in [Visual Studio Code](https://code.visualstudio.com/): + +![editor support](https://fastapi.tiangolo.com/img/vscode-completion.png) + +* in [PyCharm](https://www.jetbrains.com/pycharm/): + +![editor support](https://fastapi.tiangolo.com/img/pycharm-completion.png) + +You will get completion in code you might even consider impossible before. As for example, the `price` key inside a JSON body (that could have been nested) that comes from a request. + +No more typing the wrong key names, coming back and forth between docs, or scrolling up and down to find if you finally used `username` or `user_name`. + +### Short { #short } + +It has sensible **defaults** for everything, with optional configurations everywhere. All the parameters can be fine-tuned to do what you need and to define the API you need. + +But by default, it all **"just works"**. + +### Validation { #validation } + +* Validation for most (or all?) Python **data types**, including: + * JSON objects (`dict`). + * JSON array (`list`) defining item types. + * String (`str`) fields, defining min and max lengths. + * Numbers (`int`, `float`) with min and max values, etc. + +* Validation for more exotic types, like: + * URL. + * Email. + * UUID. + * ...and others. + +All the validation is handled by the well-established and robust **Pydantic**. + +### Security and authentication { #security-and-authentication } + +Security and authentication integrated. Without any compromise with databases or data models. + +All the security schemes defined in OpenAPI, including: + +* HTTP Basic. +* **OAuth2** (also with **JWT tokens**). Check the tutorial on [OAuth2 with JWT](tutorial/security/oauth2-jwt.md). +* API keys in: + * Headers. + * Query parameters. + * Cookies, etc. + +Plus all the security features from Starlette (including **session cookies**). + +All built as reusable tools and components that are easy to integrate with your systems, data stores, relational and NoSQL databases, etc. + +### Dependency Injection { #dependency-injection } + +FastAPI includes an extremely easy to use, but extremely powerful Dependency Injection system. + +* Even dependencies can have dependencies, creating a hierarchy or **"graph" of dependencies**. +* All **automatically handled** by the framework. +* All the dependencies can require data from requests and **augment the path operation** constraints and automatic documentation. +* **Automatic validation** even for *path operation* parameters defined in dependencies. +* Support for complex user authentication systems, **database connections**, etc. +* **No compromise** with databases, frontends, etc. But easy integration with all of them. + +### Unlimited "plug-ins" { #unlimited-plug-ins } + +Or, in other words, no need for them, import and use the code you need. + +Any integration is designed to be so simple to use (with dependencies) that you can create a "plug-in" for your application in 2 lines of code using the same structure and syntax used for your *path operations*. + +### Tested { #tested } + +* 100% test coverage. +* 100% type annotated code base. +* Used in production applications. + +## Starlette features { #starlette-features } + +**FastAPI** is fully compatible with (and based on) [**Starlette**](https://www.starlette.dev/). So, any additional Starlette code you have, will also work. + +`FastAPI` is actually a sub-class of `Starlette`. So, if you already know or use Starlette, most of the functionality will work the same way. + +With **FastAPI** you get all of **Starlette**'s features (as FastAPI is just Starlette on steroids): + +* Seriously impressive performance. It is [one of the fastest Python frameworks available, on par with **NodeJS** and **Go**](https://github.com/encode/starlette#performance). +* **WebSocket** support. +* In-process background tasks. +* Startup and shutdown events. +* Test client built on HTTPX. +* **CORS**, GZip, Static Files, Streaming responses. +* **Session and Cookie** support. +* 100% test coverage. +* 100% type annotated codebase. + +## Pydantic features { #pydantic-features } + +**FastAPI** is fully compatible with (and based on) [**Pydantic**](https://docs.pydantic.dev/). So, any additional Pydantic code you have, will also work. + +Including external libraries also based on Pydantic, such as ORMs and ODMs for databases. + +This also means that in many cases you can pass the same object you get from a request **directly to the database**, as everything is validated automatically. + +The same applies the other way around, in many cases you can just pass the object you get from the database **directly to the client**. + +With **FastAPI** you get all of **Pydantic**'s features (as FastAPI is based on Pydantic for all the data handling): + +* **No brainfuck**: + * No new schema definition micro-language to learn. + * If you know Python types you know how to use Pydantic. +* Plays nicely with your **IDE/linter/brain**: + * Because pydantic data structures are just instances of classes you define; auto-completion, linting, mypy and your intuition should all work properly with your validated data. +* Validate **complex structures**: + * Use of hierarchical Pydantic models, Python `typing`’s `List` and `Dict`, etc. + * And validators allow complex data schemas to be clearly and easily defined, checked and documented as JSON Schema. + * You can have deeply **nested JSON** objects and have them all validated and annotated. +* **Extensible**: + * Pydantic allows custom data types to be defined or you can extend validation with methods on a model decorated with the validator decorator. +* 100% test coverage. diff --git a/docs/en/docs/help-fastapi.md b/docs/en/docs/help-fastapi.md new file mode 100644 index 0000000000000..14bd056460c24 --- /dev/null +++ b/docs/en/docs/help-fastapi.md @@ -0,0 +1,87 @@ +# Help { #help } + +Would you like to help FastAPI or get help about FastAPI? + +There are very simple ways to help and get help. + +## Subscribe to the newsletter { #subscribe-to-the-newsletter } + +You can subscribe to the (infrequent) [**FastAPI and friends** newsletter](newsletter.md) to stay updated about: + +* News about FastAPI and friends 🚀 +* Guides 📝 +* Features ✨ +* Breaking changes 🚨 +* Tips and tricks ✅ + +## Follow FastAPI online { #follow-fastapi-online } + +You can follow **FastAPI** online in several places: + +* [@fastapi on **X / Twitter**](https://x.com/fastapi) +* [@fastapi.tiangolo.com on **Bluesky**](https://bsky.app/profile/fastapi.tiangolo.com) +* [FastAPI on **LinkedIn**](https://www.linkedin.com/company/fastapi/) + +## Star **FastAPI** in GitHub { #star-fastapi-in-github } + +You can "star" FastAPI in GitHub (clicking the star button at the top right): [https://github.com/fastapi/fastapi](https://github.com/fastapi/fastapi). ⭐️ + +By adding a star, other users will be able to find it more easily and see that it has already been useful for others. + +## Watch the GitHub repository for releases { #watch-the-github-repository-for-releases } + +You can "watch" FastAPI in GitHub (clicking the "watch" button at the top right): [https://github.com/fastapi/fastapi](https://github.com/fastapi/fastapi). 👀 + +There you can select "Releases only". + +By doing it, you will receive notifications (in your email) whenever there's a new release (a new version) of **FastAPI** with bug fixes and new features. + +## Follow the author { #follow-the-author } + +You can follow [me (Sebastián Ramírez / `tiangolo`)](https://tiangolo.com), the author in a few places, to hear when I have news to share about FastAPI and friends: + +* [@tiangolo on **GitHub**](https://github.com/tiangolo). +* [@tiangolo on **X (Twitter)**](https://x.com/tiangolo) +* [@tiangolo.com on **Bluesky**](https://bsky.app/profile/tiangolo.com) +* [@tiangolo on **LinkedIn**](https://www.linkedin.com/in/tiangolo/). + +## Help others with questions in GitHub { #help-others-with-questions-in-github } + +You can try and help others with their questions in [GitHub Discussions](https://github.com/fastapi/fastapi/discussions/categories/questions?discussions_q=category%3AQuestions+is%3Aunanswered). + +In many cases you might already know the answer for those questions. 🤓 + +If you are helping a lot of people with their questions, you will become an official [FastAPI Expert](fastapi-people.md#fastapi-experts). 🎉 + +Just remember, the most important point is: try to be kind. 🤗 + +### How to Help { #how-to-help } + +Follow the [guide on how to help](https://tiangolo.com/open-source/help/#help-others-with-questions-in-github) here. + +## Ask Questions { #ask-questions } + +You can [create a new question](https://github.com/fastapi/fastapi/discussions/new?category=questions) in the GitHub repository, for example to: + +* Ask a **question** or ask about a **problem**. +* Suggest a new **feature**. + +## Join the Chat { #join-the-chat } + +Join the 👥 [Discord chat server](https://discord.gg/VQjSZaeJmf) 👥 and hang out with others in the FastAPI community. + +/// tip + +For questions, ask them in GitHub Discussions, there's a much better chance you will receive help. + +Use the chat only for other general conversations. + +/// + +### Don't use the Chat for Questions { #dont-use-the-chat-for-questions } + +Keep in mind that as chats allow more "free conversation", it's easy to ask questions that are too general and more difficult to answer, so, you might not receive answers. + +In GitHub, the template will guide you to write the right question so that you can more easily get a good answer, or even solve the problem yourself even before asking. + +Conversations in the chat systems are also not as easily searchable as in GitHub, they get lost. diff --git a/docs/en/docs/history-design-future.md b/docs/en/docs/history-design-future.md new file mode 100644 index 0000000000000..b9a7fa6eced89 --- /dev/null +++ b/docs/en/docs/history-design-future.md @@ -0,0 +1,79 @@ +# History, Design and Future { #history-design-and-future } + +Some time ago, [a **FastAPI** user asked](https://github.com/fastapi/fastapi/issues/3#issuecomment-454956920): + +> What’s the history of this project? It seems to have come from nowhere to awesome in a few weeks [...] + +Here's a little bit of that history. + +## Alternatives { #alternatives } + +I have been creating APIs with complex requirements for several years (Machine Learning, distributed systems, asynchronous jobs, NoSQL databases, etc), leading several teams of developers. + +As part of that, I needed to investigate, test and use many alternatives. + +The history of **FastAPI** is in great part the history of its predecessors. + +As said in the section [Alternatives](alternatives.md): + +
+ +**FastAPI** wouldn't exist if not for the previous work of others. + +There have been many tools created before that have helped inspire its creation. + +I have been avoiding the creation of a new framework for several years. First I tried to solve all the features covered by **FastAPI** using many different frameworks, plug-ins, and tools. + +But at some point, there was no other option than creating something that provided all these features, taking the best ideas from previous tools, and combining them in the best way possible, using language features that weren't even available before (Python 3.6+ type hints). + +
+ +## Investigation { #investigation } + +By using all the previous alternatives I had the chance to learn from all of them, take ideas, and combine them in the best way I could find for myself and the teams of developers I have worked with. + +For example, it was clear that ideally it should be based on standard Python type hints. + +Also, the best approach was to use already existing standards. + +So, before even starting to code **FastAPI**, I spent several months studying the specs for OpenAPI, JSON Schema, OAuth2, etc. Understanding their relationship, overlap, and differences. + +## Design { #design } + +Then I spent some time designing the developer "API" I wanted to have as a user (as a developer using FastAPI). + +I tested several ideas in the most popular Python editors: PyCharm, VS Code, Jedi based editors. + +By the last [Python Developer Survey](https://www.jetbrains.com/research/python-developers-survey-2018/#development-tools), that covers about 80% of the users. + +It means that **FastAPI** was specifically tested with the editors used by 80% of the Python developers. And as most of the other editors tend to work similarly, all its benefits should work for virtually all editors. + +That way I could find the best ways to reduce code duplication as much as possible, to have completion everywhere, type and error checks, etc. + +All in a way that provided the best development experience for all the developers. + +## Requirements { #requirements } + +After testing several alternatives, I decided that I was going to use [**Pydantic**](https://docs.pydantic.dev/) for its advantages. + +Then I contributed to it, to make it fully compliant with JSON Schema, to support different ways to define constraint declarations, and to improve editor support (type checks, autocompletion) based on the tests in several editors. + +During the development, I also contributed to [**Starlette**](https://www.starlette.dev/), the other key requirement. + +## Development { #development } + +By the time I started creating **FastAPI** itself, most of the pieces were already in place, the design was defined, the requirements and tools were ready, and the knowledge about the standards and specifications was clear and fresh. + +## Future { #future } + +By this point, it's already clear that **FastAPI** with its ideas is being useful for many people. + +It is being chosen over previous alternatives for suiting many use cases better. + +Many developers and teams already depend on **FastAPI** for their projects (including me and my team). + +But still, there are many improvements and features to come. + +**FastAPI** has a great future ahead. + +And [your help](help-fastapi.md) is greatly appreciated. diff --git a/docs/en/docs/how-to/authentication-error-status-code.md b/docs/en/docs/how-to/authentication-error-status-code.md new file mode 100644 index 0000000000000..83b974e2dac01 --- /dev/null +++ b/docs/en/docs/how-to/authentication-error-status-code.md @@ -0,0 +1,17 @@ +# Use Old 403 Authentication Error Status Codes { #use-old-403-authentication-error-status-codes } + +Before FastAPI version `0.122.0`, when the integrated security utilities returned an error to the client after a failed authentication, they used the HTTP status code `403 Forbidden`. + +Starting with FastAPI version `0.122.0`, they use the more appropriate HTTP status code `401 Unauthorized`, and return a sensible `WWW-Authenticate` header in the response, following the HTTP specifications, [RFC 7235](https://datatracker.ietf.org/doc/html/rfc7235#section-3.1), [RFC 9110](https://datatracker.ietf.org/doc/html/rfc9110#name-401-unauthorized). + +But if for some reason your clients depend on the old behavior, you can revert to it by overriding the method `make_not_authenticated_error` in your security classes. + +For example, you can create a subclass of `HTTPBearer` that returns a `403 Forbidden` error instead of the default `401 Unauthorized` error: + +{* ../../docs_src/authentication_error_status_code/tutorial001_an_py310.py hl[9:13] *} + +/// tip + +Notice that the function returns the exception instance, it doesn't raise it. The raising is done in the rest of the internal code. + +/// diff --git a/docs/en/docs/how-to/conditional-openapi.md b/docs/en/docs/how-to/conditional-openapi.md new file mode 100644 index 0000000000000..2c0edf87f4d25 --- /dev/null +++ b/docs/en/docs/how-to/conditional-openapi.md @@ -0,0 +1,56 @@ +# Conditional OpenAPI { #conditional-openapi } + +If you needed to, you could use settings and environment variables to configure OpenAPI conditionally depending on the environment, and even disable it entirely. + +## About security, APIs, and docs { #about-security-apis-and-docs } + +Hiding your documentation user interfaces in production *shouldn't* be the way to protect your API. + +That doesn't add any extra security to your API, the *path operations* will still be available where they are. + +If there's a security flaw in your code, it will still exist. + +Hiding the documentation just makes it more difficult to understand how to interact with your API, and could make it more difficult for you to debug it in production. It could be considered simply a form of [Security through obscurity](https://en.wikipedia.org/wiki/Security_through_obscurity). + +If you want to secure your API, there are several better things you can do, for example: + +* Make sure you have well defined Pydantic models for your request bodies and responses. +* Configure any required permissions and roles using dependencies. +* Never store plaintext passwords, only password hashes. +* Implement and use well-known cryptographic tools, like pwdlib and JWT tokens, etc. +* Add more granular permission controls with OAuth2 scopes where needed. +* ...etc. + +Nevertheless, you might have a very specific use case where you really need to disable the API docs for some environment (e.g. for production) or depending on configurations from environment variables. + +## Conditional OpenAPI from settings and env vars { #conditional-openapi-from-settings-and-env-vars } + +You can easily use the same Pydantic settings to configure your generated OpenAPI and the docs UIs. + +For example: + +{* ../../docs_src/conditional_openapi/tutorial001_py310.py hl[6,11] *} + +Here we declare the setting `openapi_url` with the same default of `"/openapi.json"`. + +And then we use it when creating the `FastAPI` app. + +Then you could disable OpenAPI (including the UI docs) by setting the environment variable `OPENAPI_URL` to the empty string, like: + +
+ +```console +$ OPENAPI_URL= uvicorn main:app + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +Then if you go to the URLs at `/openapi.json`, `/docs`, or `/redoc` you will just get a `404 Not Found` error like: + +```JSON +{ + "detail": "Not Found" +} +``` diff --git a/docs/en/docs/how-to/configure-swagger-ui.md b/docs/en/docs/how-to/configure-swagger-ui.md new file mode 100644 index 0000000000000..c7cacd97e135c --- /dev/null +++ b/docs/en/docs/how-to/configure-swagger-ui.md @@ -0,0 +1,70 @@ +# Configure Swagger UI { #configure-swagger-ui } + +You can configure some extra [Swagger UI parameters](https://swagger.io/docs/open-source-tools/swagger-ui/usage/configuration/). + +To configure them, pass the `swagger_ui_parameters` argument when creating the `FastAPI()` app object or to the `get_swagger_ui_html()` function. + +`swagger_ui_parameters` receives a dictionary with the configurations passed to Swagger UI directly. + +FastAPI converts the configurations to **JSON** to make them compatible with JavaScript, as that's what Swagger UI needs. + +## Disable Syntax Highlighting { #disable-syntax-highlighting } + +For example, you could disable syntax highlighting in Swagger UI. + +Without changing the settings, syntax highlighting is enabled by default: + + + +But you can disable it by setting `syntaxHighlight` to `False`: + +{* ../../docs_src/configure_swagger_ui/tutorial001_py310.py hl[3] *} + +...and then Swagger UI won't show the syntax highlighting anymore: + + + +## Change the Theme { #change-the-theme } + +The same way you could set the syntax highlighting theme with the key `"syntaxHighlight.theme"` (notice that it has a dot in the middle): + +{* ../../docs_src/configure_swagger_ui/tutorial002_py310.py hl[3] *} + +That configuration would change the syntax highlighting color theme: + + + +## Change Default Swagger UI Parameters { #change-default-swagger-ui-parameters } + +FastAPI includes some default configuration parameters appropriate for most of the use cases. + +It includes these default configurations: + +{* ../../fastapi/openapi/docs.py ln[9:24] hl[18:24] *} + +You can override any of them by setting a different value in the argument `swagger_ui_parameters`. + +For example, to disable `deepLinking` you could pass these settings to `swagger_ui_parameters`: + +{* ../../docs_src/configure_swagger_ui/tutorial003_py310.py hl[3] *} + +## Other Swagger UI Parameters { #other-swagger-ui-parameters } + +To see all the other possible configurations you can use, read the official [docs for Swagger UI parameters](https://swagger.io/docs/open-source-tools/swagger-ui/usage/configuration/). + +## JavaScript-only settings { #javascript-only-settings } + +Swagger UI also allows other configurations to be **JavaScript-only** objects (for example, JavaScript functions). + +FastAPI also includes these JavaScript-only `presets` settings: + +```JavaScript +presets: [ + SwaggerUIBundle.presets.apis, + SwaggerUIBundle.SwaggerUIStandalonePreset +] +``` + +These are **JavaScript** objects, not strings, so you can't pass them from Python code directly. + +If you need to use JavaScript-only configurations like those, you can use one of the methods above. Override the whole Swagger UI *path operation* and manually write any JavaScript you need. diff --git a/docs/en/docs/how-to/custom-docs-ui-assets.md b/docs/en/docs/how-to/custom-docs-ui-assets.md new file mode 100644 index 0000000000000..c9e5d8a152a72 --- /dev/null +++ b/docs/en/docs/how-to/custom-docs-ui-assets.md @@ -0,0 +1,185 @@ +# Custom Docs UI Static Assets (Self-Hosting) { #custom-docs-ui-static-assets-self-hosting } + +The API docs use **Swagger UI** and **ReDoc**, and each of those need some JavaScript and CSS files. + +By default, those files are served from a CDN. + +But it's possible to customize it, you can set a specific CDN, or serve the files yourself. + +## Custom CDN for JavaScript and CSS { #custom-cdn-for-javascript-and-css } + +Let's say that you want to use a different CDN, for example you want to use `https://unpkg.com/`. + +This could be useful if for example you live in a country that restricts some URLs. + +### Disable the automatic docs { #disable-the-automatic-docs } + +The first step is to disable the automatic docs, as by default, those use the default CDN. + +To disable them, set their URLs to `None` when creating your `FastAPI` app: + +{* ../../docs_src/custom_docs_ui/tutorial001_py310.py hl[8] *} + +### Include the custom docs { #include-the-custom-docs } + +Now you can create the *path operations* for the custom docs. + +You can reuse FastAPI's internal functions to create the HTML pages for the docs, and pass them the needed arguments: + +* `openapi_url`: the URL where the HTML page for the docs can get the OpenAPI schema for your API. You can use here the attribute `app.openapi_url`. +* `title`: the title of your API. +* `oauth2_redirect_url`: you can use `app.swagger_ui_oauth2_redirect_url` here to use the default. +* `swagger_js_url`: the URL where the HTML for your Swagger UI docs can get the **JavaScript** file. This is the custom CDN URL. +* `swagger_css_url`: the URL where the HTML for your Swagger UI docs can get the **CSS** file. This is the custom CDN URL. + +And similarly for ReDoc... + +{* ../../docs_src/custom_docs_ui/tutorial001_py310.py hl[2:6,11:19,22:24,27:33] *} + +/// tip + +The *path operation* for `swagger_ui_redirect` is a helper for when you use OAuth2. + +If you integrate your API with an OAuth2 provider, you will be able to authenticate and come back to the API docs with the acquired credentials. And interact with it using the real OAuth2 authentication. + +Swagger UI will handle it behind the scenes for you, but it needs this "redirect" helper. + +/// + +### Create a *path operation* to test it { #create-a-path-operation-to-test-it } + +Now, to be able to test that everything works, create a *path operation*: + +{* ../../docs_src/custom_docs_ui/tutorial001_py310.py hl[36:38] *} + +### Test it { #test-it } + +Now, you should be able to go to your docs at [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs), and reload the page, it will load those assets from the new CDN. + +## Self-hosting JavaScript and CSS for docs { #self-hosting-javascript-and-css-for-docs } + +Self-hosting the JavaScript and CSS could be useful if, for example, you need your app to keep working even while offline, without open Internet access, or in a local network. + +Here you'll see how to serve those files yourself, in the same FastAPI app, and configure the docs to use them. + +### Project file structure { #project-file-structure } + +Let's say your project file structure looks like this: + +``` +. +├── app +│ ├── __init__.py +│ ├── main.py +``` + +Now create a directory to store those static files. + +Your new file structure could look like this: + +``` +. +├── app +│   ├── __init__.py +│   ├── main.py +└── static/ +``` + +### Download the files { #download-the-files } + +Download the static files needed for the docs and put them on that `static/` directory. + +You can probably right-click each link and select an option similar to "Save link as...". + +**Swagger UI** uses the files: + +* [`swagger-ui-bundle.js`](https://cdn.jsdelivr.net/npm/swagger-ui-dist@5/swagger-ui-bundle.js) +* [`swagger-ui.css`](https://cdn.jsdelivr.net/npm/swagger-ui-dist@5/swagger-ui.css) + +And **ReDoc** uses the file: + +* [`redoc.standalone.js`](https://cdn.jsdelivr.net/npm/redoc@2/bundles/redoc.standalone.js) + +After that, your file structure could look like: + +``` +. +├── app +│   ├── __init__.py +│   ├── main.py +└── static + ├── redoc.standalone.js + ├── swagger-ui-bundle.js + └── swagger-ui.css +``` + +### Serve the static files { #serve-the-static-files } + +* Import `StaticFiles`. +* "Mount" a `StaticFiles()` instance in a specific path. + +{* ../../docs_src/custom_docs_ui/tutorial002_py310.py hl[7,11] *} + +### Test the static files { #test-the-static-files } + +Start your application and go to [http://127.0.0.1:8000/static/redoc.standalone.js](http://127.0.0.1:8000/static/redoc.standalone.js). + +You should see a very long JavaScript file for **ReDoc**. + +It could start with something like: + +```JavaScript +/*! For license information please see redoc.standalone.js.LICENSE.txt */ +!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("null")): +... +``` + +That confirms that you are being able to serve static files from your app, and that you placed the static files for the docs in the correct place. + +Now we can configure the app to use those static files for the docs. + +### Disable the automatic docs for static files { #disable-the-automatic-docs-for-static-files } + +The same as when using a custom CDN, the first step is to disable the automatic docs, as those use the CDN by default. + +To disable them, set their URLs to `None` when creating your `FastAPI` app: + +{* ../../docs_src/custom_docs_ui/tutorial002_py310.py hl[9] *} + +### Include the custom docs for static files { #include-the-custom-docs-for-static-files } + +And the same way as with a custom CDN, now you can create the *path operations* for the custom docs. + +Again, you can reuse FastAPI's internal functions to create the HTML pages for the docs, and pass them the needed arguments: + +* `openapi_url`: the URL where the HTML page for the docs can get the OpenAPI schema for your API. You can use here the attribute `app.openapi_url`. +* `title`: the title of your API. +* `oauth2_redirect_url`: you can use `app.swagger_ui_oauth2_redirect_url` here to use the default. +* `swagger_js_url`: the URL where the HTML for your Swagger UI docs can get the **JavaScript** file. **This is the one that your own app is now serving**. +* `swagger_css_url`: the URL where the HTML for your Swagger UI docs can get the **CSS** file. **This is the one that your own app is now serving**. + +And similarly for ReDoc... + +{* ../../docs_src/custom_docs_ui/tutorial002_py310.py hl[2:6,14:22,25:27,30:36] *} + +/// tip + +The *path operation* for `swagger_ui_redirect` is a helper for when you use OAuth2. + +If you integrate your API with an OAuth2 provider, you will be able to authenticate and come back to the API docs with the acquired credentials. And interact with it using the real OAuth2 authentication. + +Swagger UI will handle it behind the scenes for you, but it needs this "redirect" helper. + +/// + +### Create a *path operation* to test static files { #create-a-path-operation-to-test-static-files } + +Now, to be able to test that everything works, create a *path operation*: + +{* ../../docs_src/custom_docs_ui/tutorial002_py310.py hl[39:41] *} + +### Test Static Files UI { #test-static-files-ui } + +Now, you should be able to disconnect your WiFi, go to your docs at [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs), and reload the page. + +And even without Internet, you would be able to see the docs for your API and interact with it. diff --git a/docs/en/docs/how-to/custom-request-and-route.md b/docs/en/docs/how-to/custom-request-and-route.md new file mode 100644 index 0000000000000..2b353d9b46e1a --- /dev/null +++ b/docs/en/docs/how-to/custom-request-and-route.md @@ -0,0 +1,109 @@ +# Custom Request and APIRoute class { #custom-request-and-apiroute-class } + +In some cases, you may want to override the logic used by the `Request` and `APIRoute` classes. + +In particular, this may be a good alternative to logic in a middleware. + +For example, if you want to read or manipulate the request body before it is processed by your application. + +/// danger + +This is an "advanced" feature. + +If you are just starting with **FastAPI** you might want to skip this section. + +/// + +## Use cases { #use-cases } + +Some use cases include: + +* Converting non-JSON request bodies to JSON (e.g. [`msgpack`](https://msgpack.org/index.html)). +* Decompressing gzip-compressed request bodies. +* Automatically logging all request bodies. + +## Handling custom request body encodings { #handling-custom-request-body-encodings } + +Let's see how to make use of a custom `Request` subclass to decompress gzip requests. + +And an `APIRoute` subclass to use that custom request class. + +### Create a custom `GzipRequest` class { #create-a-custom-gziprequest-class } + +/// tip + +This is a toy example to demonstrate how it works, if you need Gzip support, you can use the provided [`GzipMiddleware`](../advanced/middleware.md#gzipmiddleware). + +/// + +First, we create a `GzipRequest` class, which will overwrite the `Request.body()` method to decompress the body in the presence of an appropriate header. + +If there's no `gzip` in the header, it will not try to decompress the body. + +That way, the same route class can handle gzip compressed or uncompressed requests. + +{* ../../docs_src/custom_request_and_route/tutorial001_an_py310.py hl[9:16] *} + +### Create a custom `GzipRoute` class { #create-a-custom-gziproute-class } + +Next, we create a custom subclass of `fastapi.routing.APIRoute` that will make use of the `GzipRequest`. + +This time, it will overwrite the method `APIRoute.get_route_handler()`. + +This method returns a function. And that function is what will receive a request and return a response. + +Here we use it to create a `GzipRequest` from the original request. + +{* ../../docs_src/custom_request_and_route/tutorial001_an_py310.py hl[19:27] *} + +/// note | Technical Details + +A `Request` has a `request.scope` attribute, that's just a Python `dict` containing the metadata related to the request. + +A `Request` also has a `request.receive`, that's a function to "receive" the body of the request. + +The `scope` `dict` and `receive` function are both part of the ASGI specification. + +And those two things, `scope` and `receive`, are what is needed to create a new `Request` instance. + +To learn more about the `Request` check [Starlette's docs about Requests](https://www.starlette.dev/requests/). + +/// + +The only thing the function returned by `GzipRequest.get_route_handler` does differently is convert the `Request` to a `GzipRequest`. + +Doing this, our `GzipRequest` will take care of decompressing the data (if necessary) before passing it to our *path operations*. + +After that, all of the processing logic is the same. + +But because of our changes in `GzipRequest.body`, the request body will be automatically decompressed when it is loaded by **FastAPI** when needed. + +## Accessing the request body in an exception handler { #accessing-the-request-body-in-an-exception-handler } + +/// tip + +To solve this same problem, it's probably a lot easier to use the `body` in a custom handler for `RequestValidationError` ([Handling Errors](../tutorial/handling-errors.md#use-the-requestvalidationerror-body)). + +But this example is still valid and it shows how to interact with the internal components. + +/// + +We can also use this same approach to access the request body in an exception handler. + +All we need to do is handle the request inside a `try`/`except` block: + +{* ../../docs_src/custom_request_and_route/tutorial002_an_py310.py hl[14,16] *} + +If an exception occurs, the `Request` instance will still be in scope, so we can read and make use of the request body when handling the error: + +{* ../../docs_src/custom_request_and_route/tutorial002_an_py310.py hl[17:19] *} + +## Custom `APIRoute` class in a router { #custom-apiroute-class-in-a-router } + +You can also set the `route_class` parameter of an `APIRouter`: + +{* ../../docs_src/custom_request_and_route/tutorial003_py310.py hl[26] *} + +In this example, the *path operations* under the `router` will use the custom `TimedRoute` class, and will have an extra `X-Response-Time` header in the response with the time it took to generate the response: + +{* ../../docs_src/custom_request_and_route/tutorial003_py310.py hl[13:20] *} diff --git a/docs/en/docs/how-to/extending-openapi.md b/docs/en/docs/how-to/extending-openapi.md new file mode 100644 index 0000000000000..8368eea5060ef --- /dev/null +++ b/docs/en/docs/how-to/extending-openapi.md @@ -0,0 +1,88 @@ +# Extending OpenAPI { #extending-openapi } + +There are some cases where you might need to modify the generated OpenAPI schema. + +In this section you will see how. + +## The normal process { #the-normal-process } + +The normal (default) process, is as follows. + +A `FastAPI` application (instance) has an `.openapi()` method that is expected to return the OpenAPI schema. + +As part of the application object creation, a *path operation* for `/openapi.json` (or for whatever you set your `openapi_url`) is registered. + +It just returns a JSON response with the result of the application's `.openapi()` method. + +By default, what the method `.openapi()` does is check the property `.openapi_schema` to see if it has contents and return them. + +If it doesn't, it generates them using the utility function at `fastapi.openapi.utils.get_openapi`. + +And that function `get_openapi()` receives as parameters: + +* `title`: The OpenAPI title, shown in the docs. +* `version`: The version of your API, e.g. `2.5.0`. +* `openapi_version`: The version of the OpenAPI specification used. By default, the latest: `3.1.0`. +* `summary`: A short summary of the API. +* `description`: The description of your API, this can include markdown and will be shown in the docs. +* `routes`: The routes from the application, taken from `app.routes`. FastAPI uses them to collect the registered *path operations*, including those from included routers. + +/// tip | Technical Details + +`app.routes` is a lower-level route tree. It can include route candidates that FastAPI uses internally for included routers, not only final `APIRoute` objects. + +You can still pass `app.routes` to `get_openapi()`. FastAPI will traverse that route tree to collect the effective path operations. + +/// + +/// note + +The parameter `summary` is available in OpenAPI 3.1.0 and above, supported by FastAPI 0.99.0 and above. + +/// + +## Overriding the defaults { #overriding-the-defaults } + +Using the information above, you can use the same utility function to generate the OpenAPI schema and override each part that you need. + +For example, let's add [ReDoc's OpenAPI extension to include a custom logo](https://github.com/Rebilly/ReDoc/blob/master/docs/redoc-vendor-extensions.md#x-logo). + +### Normal **FastAPI** { #normal-fastapi } + +First, write all your **FastAPI** application as normally: + +{* ../../docs_src/extending_openapi/tutorial001_py310.py hl[1,4,7:9] *} + +### Generate the OpenAPI schema { #generate-the-openapi-schema } + +Then, use the same utility function to generate the OpenAPI schema, inside a `custom_openapi()` function: + +{* ../../docs_src/extending_openapi/tutorial001_py310.py hl[2,15:21] *} + +### Modify the OpenAPI schema { #modify-the-openapi-schema } + +Now you can add the ReDoc extension, adding a custom `x-logo` to the `info` "object" in the OpenAPI schema: + +{* ../../docs_src/extending_openapi/tutorial001_py310.py hl[22:24] *} + +### Cache the OpenAPI schema { #cache-the-openapi-schema } + +You can use the property `.openapi_schema` as a "cache", to store your generated schema. + +That way, your application won't have to generate the schema every time a user opens your API docs. + +It will be generated only once, and then the same cached schema will be used for the next requests. + +{* ../../docs_src/extending_openapi/tutorial001_py310.py hl[13:14,25:26] *} + +### Override the method { #override-the-method } + +Now you can replace the `.openapi()` method with your new function. + +{* ../../docs_src/extending_openapi/tutorial001_py310.py hl[29] *} + +### Check it { #check-it } + +Once you go to [http://127.0.0.1:8000/redoc](http://127.0.0.1:8000/redoc) you will see that you are using your custom logo (in this example, **FastAPI**'s logo): + + diff --git a/docs/en/docs/how-to/general.md b/docs/en/docs/how-to/general.md new file mode 100644 index 0000000000000..da6738eb9b1ff --- /dev/null +++ b/docs/en/docs/how-to/general.md @@ -0,0 +1,43 @@ +# General - How To - Recipes { #general-how-to-recipes } + +Here are several pointers to other places in the docs, for general or frequent questions. + +## Filter Data - Security { #filter-data-security } + +To ensure that you don't return more data than you should, read the docs for [Tutorial - Response Model - Return Type](../tutorial/response-model.md). + +## Optimize Response Performance - Response Model - Return Type { #optimize-response-performance-response-model-return-type } + +To optimize performance when returning JSON data, use a return type or response model, that way Pydantic will handle the serialization to JSON on the Rust side, without going through Python. Read more in the docs for [Tutorial - Response Model - Return Type](../tutorial/response-model.md). + +## Documentation Tags - OpenAPI { #documentation-tags-openapi } + +To add tags to your *path operations*, and group them in the docs UI, read the docs for [Tutorial - Path Operation Configurations - Tags](../tutorial/path-operation-configuration.md#tags). + +## Documentation Summary and Description - OpenAPI { #documentation-summary-and-description-openapi } + +To add a summary and description to your *path operations*, and show them in the docs UI, read the docs for [Tutorial - Path Operation Configurations - Summary and Description](../tutorial/path-operation-configuration.md#summary-and-description). + +## Documentation Response description - OpenAPI { #documentation-response-description-openapi } + +To define the description of the response, shown in the docs UI, read the docs for [Tutorial - Path Operation Configurations - Response description](../tutorial/path-operation-configuration.md#response-description). + +## Documentation Deprecate a *Path Operation* - OpenAPI { #documentation-deprecate-a-path-operation-openapi } + +To deprecate a *path operation*, and show it in the docs UI, read the docs for [Tutorial - Path Operation Configurations - Deprecation](../tutorial/path-operation-configuration.md#deprecate-a-path-operation). + +## Convert any Data to JSON-compatible { #convert-any-data-to-json-compatible } + +To convert any data to JSON-compatible, read the docs for [Tutorial - JSON Compatible Encoder](../tutorial/encoder.md). + +## OpenAPI Metadata - Docs { #openapi-metadata-docs } + +To add metadata to your OpenAPI schema, including a license, version, contact, etc, read the docs for [Tutorial - Metadata and Docs URLs](../tutorial/metadata.md). + +## OpenAPI Custom URL { #openapi-custom-url } + +To customize the OpenAPI URL (or remove it), read the docs for [Tutorial - Metadata and Docs URLs](../tutorial/metadata.md#openapi-url). + +## OpenAPI Docs URLs { #openapi-docs-urls } + +To update the URLs used for the automatically generated docs user interfaces, read the docs for [Tutorial - Metadata and Docs URLs](../tutorial/metadata.md#docs-urls). diff --git a/docs/en/docs/how-to/graphql.md b/docs/en/docs/how-to/graphql.md new file mode 100644 index 0000000000000..de149a74a8a02 --- /dev/null +++ b/docs/en/docs/how-to/graphql.md @@ -0,0 +1,60 @@ +# GraphQL { #graphql } + +As **FastAPI** is based on the **ASGI** standard, it's very easy to integrate any **GraphQL** library also compatible with ASGI. + +You can combine normal FastAPI *path operations* with GraphQL on the same application. + +/// tip + +**GraphQL** solves some very specific use cases. + +It has **advantages** and **disadvantages** when compared to common **web APIs**. + +Make sure you evaluate if the **benefits** for your use case compensate the **drawbacks**. 🤓 + +/// + +## GraphQL Libraries { #graphql-libraries } + +Here are some of the **GraphQL** libraries that have **ASGI** support. You could use them with **FastAPI**: + +* [Strawberry](https://strawberry.rocks/) 🍓 + * With [docs for FastAPI](https://strawberry.rocks/docs/integrations/fastapi) +* [Ariadne](https://ariadnegraphql.org/) + * With [docs for FastAPI](https://ariadnegraphql.org/docs/fastapi-integration) +* [Tartiflette](https://tartiflette.io/) + * With [Tartiflette ASGI](https://tartiflette.github.io/tartiflette-asgi/) to provide ASGI integration +* [Graphene](https://graphene-python.org/) + * With [starlette-graphene3](https://github.com/ciscorn/starlette-graphene3) + +## GraphQL with Strawberry { #graphql-with-strawberry } + +If you need or want to work with **GraphQL**, [**Strawberry**](https://strawberry.rocks/) is the **recommended** library as it has the design closest to **FastAPI's** design, it's all based on **type annotations**. + +Depending on your use case, you might prefer to use a different library, but if you asked me, I would probably suggest you try **Strawberry**. + +Here's a small preview of how you could integrate Strawberry with FastAPI: + +{* ../../docs_src/graphql_/tutorial001_py310.py hl[3,22,25] *} + +You can learn more about Strawberry in the [Strawberry documentation](https://strawberry.rocks/). + +And also the docs about [Strawberry with FastAPI](https://strawberry.rocks/docs/integrations/fastapi). + +## Older `GraphQLApp` from Starlette { #older-graphqlapp-from-starlette } + +Previous versions of Starlette included a `GraphQLApp` class to integrate with [Graphene](https://graphene-python.org/). + +It was deprecated from Starlette, but if you have code that used it, you can easily **migrate** to [starlette-graphene3](https://github.com/ciscorn/starlette-graphene3), that covers the same use case and has an **almost identical interface**. + +/// tip + +If you need GraphQL, I still would recommend you check out [Strawberry](https://strawberry.rocks/), as it's based on type annotations instead of custom classes and types. + +/// + +## Learn More { #learn-more } + +You can learn more about **GraphQL** in the [official GraphQL documentation](https://graphql.org/). + +You can also read more about each of those libraries described above in their links. diff --git a/docs/en/docs/how-to/index.md b/docs/en/docs/how-to/index.md new file mode 100644 index 0000000000000..3d3696671ccd5 --- /dev/null +++ b/docs/en/docs/how-to/index.md @@ -0,0 +1,13 @@ +# How To - Recipes { #how-to-recipes } + +Here you will see different recipes or "how to" guides for **several topics**. + +Most of these ideas would be more or less **independent**, and in most cases you should only need to study them if they apply directly to **your project**. + +If something seems interesting and useful to your project, go ahead and check it, but otherwise, you might probably just skip them. + +/// tip + +If you want to **learn FastAPI** in a structured way (recommended), go and read the [Tutorial - User Guide](../tutorial/index.md) chapter by chapter instead. + +/// diff --git a/docs/en/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md b/docs/en/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md new file mode 100644 index 0000000000000..816cf54f543e4 --- /dev/null +++ b/docs/en/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md @@ -0,0 +1,153 @@ +# Migrate from Pydantic v1 to Pydantic v2 { #migrate-from-pydantic-v1-to-pydantic-v2 } + +If you have an old FastAPI app, you might be using Pydantic version 1. + +FastAPI version 0.100.0 had support for either Pydantic v1 or v2. It would use whichever you had installed. + +FastAPI version 0.119.0 introduced partial support for Pydantic v1 from inside of Pydantic v2 (as `pydantic.v1`), to facilitate the migration to v2. + +FastAPI 0.126.0 dropped support for Pydantic v1, while still supporting `pydantic.v1` for a little while. + +FastAPI 0.128.0 dropped support for `pydantic.v1` as well, so the latest versions of FastAPI require Pydantic v2. + +/// warning + +The Pydantic team stopped support for Pydantic v1 for the latest versions of Python, starting with **Python 3.14**. + +This includes `pydantic.v1`, which is no longer supported in Python 3.14 and above. + +If you want to use the latest features of Python, you will need to make sure you use Pydantic v2. + +/// + +If you have an old FastAPI app with Pydantic v1, here I'll show you how to migrate it to Pydantic v2, and the **features in FastAPI 0.119.0** to help you with a gradual migration. + +## Official Guide { #official-guide } + +Pydantic has an official [Migration Guide](https://docs.pydantic.dev/latest/migration/) from v1 to v2. + +It also includes what has changed, how validations are now more correct and strict, possible caveats, etc. + +You can read it to understand better what has changed. + +## Tests { #tests } + +Make sure you have [tests](../tutorial/testing.md) for your app and you run them on continuous integration (CI). + +This way, you can do the upgrade and make sure everything is still working as expected. + +## `bump-pydantic` { #bump-pydantic } + +In many cases, when you use regular Pydantic models without customizations, you will be able to automate most of the process of migrating from Pydantic v1 to Pydantic v2. + +You can use [`bump-pydantic`](https://github.com/pydantic/bump-pydantic) from the same Pydantic team. + +This tool will help you to automatically change most of the code that needs to be changed. + +After this, you can run the tests and check if everything works. If it does, you are done. 😎 + +## Pydantic v1 in v2 { #pydantic-v1-in-v2 } + +Pydantic v2 includes everything from Pydantic v1 as a submodule `pydantic.v1`. But this is no longer supported in versions above Python 3.13. + +This means that you can install the latest version of Pydantic v2 and import and use the old Pydantic v1 components from this submodule, as if you had the old Pydantic v1 installed. + +{* ../../docs_src/pydantic_v1_in_v2/tutorial001_an_py310.py hl[1,4] *} + +### FastAPI support for Pydantic v1 in v2 { #fastapi-support-for-pydantic-v1-in-v2 } + +/// warning + +This FastAPI support for `pydantic.v1` models was added in **FastAPI 0.119.0** and removed in **FastAPI 0.128.0**. It was meant to be a temporary aid for the migration to Pydantic v2. + +In current versions of FastAPI, using a `pydantic.v1` model in your app will raise an error. + +The rest of this section describes the temporary support available only in those older versions. + +/// + +Since FastAPI 0.119.0, there's also partial support for Pydantic v1 from inside of Pydantic v2, to facilitate the migration to v2. + +So, you could upgrade Pydantic to the latest version 2, and change the imports to use the `pydantic.v1` submodule, and in many cases it would just work. + +{* ../../docs_src/pydantic_v1_in_v2/tutorial002_an_py310.py hl[2,5,15] *} + +/// warning + +Have in mind that as the Pydantic team no longer supports Pydantic v1 in recent versions of Python, starting from Python 3.14, using `pydantic.v1` is also not supported in Python 3.14 and above. + +/// + +### Pydantic v1 and v2 on the same app { #pydantic-v1-and-v2-on-the-same-app } + +It's **not supported** by Pydantic to have a model of Pydantic v2 with its own fields defined as Pydantic v1 models or vice versa. + +```mermaid +graph TB + subgraph "❌ Not Supported" + direction TB + subgraph V2["Pydantic v2 Model"] + V1Field["Pydantic v1 Model"] + end + subgraph V1["Pydantic v1 Model"] + V2Field["Pydantic v2 Model"] + end + end + + style V2 fill:#f9fff3 + style V1 fill:#fff6f0 + style V1Field fill:#fff6f0 + style V2Field fill:#f9fff3 +``` + +...but you can have separate models, some using Pydantic v1 and others using Pydantic v2, in the same app. + +```mermaid +graph TB + subgraph "✅ Supported" + direction TB + subgraph V2["Pydantic v2 Model"] + V2Field["Pydantic v2 Model"] + end + subgraph V1["Pydantic v1 Model"] + V1Field["Pydantic v1 Model"] + end + end + + style V2 fill:#f9fff3 + style V1 fill:#fff6f0 + style V1Field fill:#fff6f0 + style V2Field fill:#f9fff3 +``` + +In some cases, it's even possible to have both Pydantic v1 and v2 models in the same **path operation** in your FastAPI app: + +{* ../../docs_src/pydantic_v1_in_v2/tutorial003_an_py310.py hl[2:3,6,12,21:22] *} + +In this example above, the input model is a Pydantic v1 model, and the output model (defined in `response_model=ItemV2`) is a Pydantic v2 model. + +### Pydantic v1 parameters { #pydantic-v1-parameters } + +If you need to use some of the FastAPI-specific tools for parameters like `Body`, `Query`, `Form`, etc. with Pydantic v1 models, you can import them from `fastapi.temp_pydantic_v1_params` while you finish the migration to Pydantic v2: + +{* ../../docs_src/pydantic_v1_in_v2/tutorial004_an_py310.py hl[4,18] *} + +### Migrate in steps { #migrate-in-steps } + +/// warning + +The gradual migration using both Pydantic v1 and v2 models in the same app described below only works in **FastAPI 0.119.0 to 0.127.x**. It was removed in **FastAPI 0.128.0**, the latest versions require **Pydantic v2** models. + +/// + +/// tip + +First try with `bump-pydantic`, if your tests pass and that works, then you're done in one command. ✨ + +/// + +If `bump-pydantic` doesn't work for your use case, you can use the support for both Pydantic v1 and v2 models in the same app to do the migration to Pydantic v2 gradually. + +You could first upgrade Pydantic to use the latest version 2, and change the imports to use `pydantic.v1` for all your models. + +Then, you can start migrating your models from Pydantic v1 to v2 in groups, in gradual steps. 🚶 diff --git a/docs/en/docs/how-to/separate-openapi-schemas.md b/docs/en/docs/how-to/separate-openapi-schemas.md new file mode 100644 index 0000000000000..66755f8b7a02f --- /dev/null +++ b/docs/en/docs/how-to/separate-openapi-schemas.md @@ -0,0 +1,102 @@ +# Separate OpenAPI Schemas for Input and Output or Not { #separate-openapi-schemas-for-input-and-output-or-not } + +Since **Pydantic v2** was released, the generated OpenAPI is a bit more exact and **correct** than before. 😎 + +In fact, in some cases, it will even have **two JSON Schemas** in OpenAPI for the same Pydantic model, for input and output, depending on if they have **default values**. + +Let's see how that works and how to change it if you need to do that. + +## Pydantic Models for Input and Output { #pydantic-models-for-input-and-output } + +Let's say you have a Pydantic model with default values, like this one: + +{* ../../docs_src/separate_openapi_schemas/tutorial001_py310.py ln[1:7] hl[7] *} + +### Model for Input { #model-for-input } + +If you use this model as an input like here: + +{* ../../docs_src/separate_openapi_schemas/tutorial001_py310.py ln[1:15] hl[14] *} + +...then the `description` field will **not be required**. Because it has a default value of `None`. + +### Input Model in Docs { #input-model-in-docs } + +You can confirm that in the docs, the `description` field doesn't have a **red asterisk**, it's not marked as required: + +
+ +
+ +### Model for Output { #model-for-output } + +But if you use the same model as an output, like here: + +{* ../../docs_src/separate_openapi_schemas/tutorial001_py310.py hl[19] *} + +...then because `description` has a default value, if you **don't return anything** for that field, it will still have that **default value**. + +### Model for Output Response Data { #model-for-output-response-data } + +If you interact with the docs and check the response, even though the code didn't add anything in one of the `description` fields, the JSON response contains the default value (`null`): + +
+ +
+ +This means that it will **always have a value**, it's just that sometimes the value could be `None` (or `null` in JSON). + +That means that clients using your API don't have to check if the value exists or not, they can **assume the field will always be there**, but just that in some cases it will have the default value of `None`. + +The way to describe this in OpenAPI, is to mark that field as **required**, because it will always be there. + +Because of that, the JSON Schema for a model can be different depending on if it's used for **input or output**: + +* for **input** the `description` will **not be required** +* for **output** it will be **required** (and possibly `None`, or in JSON terms, `null`) + +### Model for Output in Docs { #model-for-output-in-docs } + +You can check the output model in the docs too, **both** `name` and `description` are marked as **required** with a **red asterisk**: + +
+ +
+ +### Model for Input and Output in Docs { #model-for-input-and-output-in-docs } + +And if you check all the available Schemas (JSON Schemas) in OpenAPI, you will see that there are two, one `Item-Input` and one `Item-Output`. + +For `Item-Input`, `description` is **not required**, it doesn't have a red asterisk. + +But for `Item-Output`, `description` is **required**, it has a red asterisk. + +
+ +
+ +With this feature from **Pydantic v2**, your API documentation is more **precise**, and if you have autogenerated clients and SDKs, they will be more precise too, with a better **developer experience** and consistency. 🎉 + +## Do not Separate Schemas { #do-not-separate-schemas } + +Now, there are some cases where you might want to have the **same schema for input and output**. + +Probably the main use case for this is if you already have some autogenerated client code/SDKs and you don't want to update all the autogenerated client code/SDKs yet, you probably will want to do it at some point, but maybe not right now. + +In that case, you can disable this feature in **FastAPI**, with the parameter `separate_input_output_schemas=False`. + +/// note + +Support for `separate_input_output_schemas` was added in FastAPI `0.102.0`. 🤓 + +/// + +{* ../../docs_src/separate_openapi_schemas/tutorial002_py310.py hl[10] *} + +### Same Schema for Input and Output Models in Docs { #same-schema-for-input-and-output-models-in-docs } + +And now there will be one single schema for input and output for the model, only `Item`, and it will have `description` as **not required**: + +
+ +
diff --git a/docs/en/docs/how-to/testing-database.md b/docs/en/docs/how-to/testing-database.md new file mode 100644 index 0000000000000..a8e183ce0fabb --- /dev/null +++ b/docs/en/docs/how-to/testing-database.md @@ -0,0 +1,7 @@ +# Testing a Database { #testing-a-database } + +You can study about databases, SQL, and SQLModel in the [SQLModel docs](https://sqlmodel.tiangolo.com/). 🤓 + +There's a mini [tutorial on using SQLModel with FastAPI](https://sqlmodel.tiangolo.com/tutorial/fastapi/). ✨ + +That tutorial includes a section about [testing SQL databases](https://sqlmodel.tiangolo.com/tutorial/fastapi/tests/). 😎 diff --git a/docs/en/docs/img/async/concurrent-burgers/concurrent-burgers-01.png b/docs/en/docs/img/async/concurrent-burgers/concurrent-burgers-01.png new file mode 100644 index 0000000000000..e0e77d3fcec50 Binary files /dev/null and b/docs/en/docs/img/async/concurrent-burgers/concurrent-burgers-01.png differ diff --git a/docs/en/docs/img/async/concurrent-burgers/concurrent-burgers-02.png b/docs/en/docs/img/async/concurrent-burgers/concurrent-burgers-02.png new file mode 100644 index 0000000000000..27f6e127179cb Binary files /dev/null and b/docs/en/docs/img/async/concurrent-burgers/concurrent-burgers-02.png differ diff --git a/docs/en/docs/img/async/concurrent-burgers/concurrent-burgers-03.png b/docs/en/docs/img/async/concurrent-burgers/concurrent-burgers-03.png new file mode 100644 index 0000000000000..27472a8e02e5a Binary files /dev/null and b/docs/en/docs/img/async/concurrent-burgers/concurrent-burgers-03.png differ diff --git a/docs/en/docs/img/async/concurrent-burgers/concurrent-burgers-04.png b/docs/en/docs/img/async/concurrent-burgers/concurrent-burgers-04.png new file mode 100644 index 0000000000000..cf1d8dd454f91 Binary files /dev/null and b/docs/en/docs/img/async/concurrent-burgers/concurrent-burgers-04.png differ diff --git a/docs/en/docs/img/async/concurrent-burgers/concurrent-burgers-05.png b/docs/en/docs/img/async/concurrent-burgers/concurrent-burgers-05.png new file mode 100644 index 0000000000000..ab6e036694bc8 Binary files /dev/null and b/docs/en/docs/img/async/concurrent-burgers/concurrent-burgers-05.png differ diff --git a/docs/en/docs/img/async/concurrent-burgers/concurrent-burgers-06.png b/docs/en/docs/img/async/concurrent-burgers/concurrent-burgers-06.png new file mode 100644 index 0000000000000..4bbf247c0f3b5 Binary files /dev/null and b/docs/en/docs/img/async/concurrent-burgers/concurrent-burgers-06.png differ diff --git a/docs/en/docs/img/async/concurrent-burgers/concurrent-burgers-07.png b/docs/en/docs/img/async/concurrent-burgers/concurrent-burgers-07.png new file mode 100644 index 0000000000000..7a0f4092d9a38 Binary files /dev/null and b/docs/en/docs/img/async/concurrent-burgers/concurrent-burgers-07.png differ diff --git a/docs/en/docs/img/async/parallel-burgers/parallel-burgers-01.png b/docs/en/docs/img/async/parallel-burgers/parallel-burgers-01.png new file mode 100644 index 0000000000000..92fc1a8a0d89c Binary files /dev/null and b/docs/en/docs/img/async/parallel-burgers/parallel-burgers-01.png differ diff --git a/docs/en/docs/img/async/parallel-burgers/parallel-burgers-02.png b/docs/en/docs/img/async/parallel-burgers/parallel-burgers-02.png new file mode 100644 index 0000000000000..9583b84dc239e Binary files /dev/null and b/docs/en/docs/img/async/parallel-burgers/parallel-burgers-02.png differ diff --git a/docs/en/docs/img/async/parallel-burgers/parallel-burgers-03.png b/docs/en/docs/img/async/parallel-burgers/parallel-burgers-03.png new file mode 100644 index 0000000000000..bea9ff0d8039d Binary files /dev/null and b/docs/en/docs/img/async/parallel-burgers/parallel-burgers-03.png differ diff --git a/docs/en/docs/img/async/parallel-burgers/parallel-burgers-04.png b/docs/en/docs/img/async/parallel-burgers/parallel-burgers-04.png new file mode 100644 index 0000000000000..b5c8a60bbeb4a Binary files /dev/null and b/docs/en/docs/img/async/parallel-burgers/parallel-burgers-04.png differ diff --git a/docs/en/docs/img/async/parallel-burgers/parallel-burgers-05.png b/docs/en/docs/img/async/parallel-burgers/parallel-burgers-05.png new file mode 100644 index 0000000000000..45aca8e217fee Binary files /dev/null and b/docs/en/docs/img/async/parallel-burgers/parallel-burgers-05.png differ diff --git a/docs/en/docs/img/async/parallel-burgers/parallel-burgers-06.png b/docs/en/docs/img/async/parallel-burgers/parallel-burgers-06.png new file mode 100644 index 0000000000000..c91c4b472e3d8 Binary files /dev/null and b/docs/en/docs/img/async/parallel-burgers/parallel-burgers-06.png differ diff --git a/docs/en/docs/img/deployment/concepts/image01.png b/docs/en/docs/img/deployment/concepts/image01.png new file mode 100644 index 0000000000000..fdce75e983509 Binary files /dev/null and b/docs/en/docs/img/deployment/concepts/image01.png differ diff --git a/docs/en/docs/img/deployment/concepts/process-ram.drawio.svg b/docs/en/docs/img/deployment/concepts/process-ram.drawio.svg new file mode 100644 index 0000000000000..a6a5c81d03ad0 --- /dev/null +++ b/docs/en/docs/img/deployment/concepts/process-ram.drawio.svg @@ -0,0 +1,297 @@ + + + + + + + + + + + + + +
+
+
+ + + Server + + +
+
+
+
+ + Server + +
+
+
+ + + + + + + + + + +
+
+
+ + + RAM + +
+
+
+
+
+
+ + RAM + +
+
+
+ + + + + + + + + + +
+
+
+ + + CPU + +
+
+
+
+
+
+ + CPU + +
+
+
+ + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + + Process + + + + Manager + + +
+
+
+
+ + Process Manager + +
+
+
+ + + + + + + + + + +
+
+
+ + + Worker Process + + +
+
+
+
+ + Worker Process + +
+
+
+ + + + + + + + + + + + + +
+
+
+ + + Worker Process + + +
+
+
+
+ + Worker Process + +
+
+
+ + + + + + + + + + + + + +
+
+
+ + + Another Process + + +
+
+
+
+ + Another Process + +
+
+
+ + + + + + + + + + + + + + + + + + + +
+
+
+ + 1 GB + +
+
+
+
+ + 1 GB + +
+
+
+ + + + + + + +
+
+
+ + 1 GB + +
+
+
+
+ + 1 GB + +
+
+
+ + + + + + +
+ + + + + Text is not SVG - cannot display + + + +
diff --git a/docs/en/docs/img/deployment/deta/image01.png b/docs/en/docs/img/deployment/deta/image01.png new file mode 100644 index 0000000000000..f2e058b580376 Binary files /dev/null and b/docs/en/docs/img/deployment/deta/image01.png differ diff --git a/docs/en/docs/img/deployment/deta/image02.png b/docs/en/docs/img/deployment/deta/image02.png new file mode 100644 index 0000000000000..897ec41fb1197 Binary files /dev/null and b/docs/en/docs/img/deployment/deta/image02.png differ diff --git a/docs/en/docs/img/deployment/deta/image03.png b/docs/en/docs/img/deployment/deta/image03.png new file mode 100644 index 0000000000000..232355658f54d Binary files /dev/null and b/docs/en/docs/img/deployment/deta/image03.png differ diff --git a/docs/en/docs/img/deployment/deta/image04.png b/docs/en/docs/img/deployment/deta/image04.png new file mode 100644 index 0000000000000..88898e0f2614e Binary files /dev/null and b/docs/en/docs/img/deployment/deta/image04.png differ diff --git a/docs/en/docs/img/deployment/deta/image05.png b/docs/en/docs/img/deployment/deta/image05.png new file mode 100644 index 0000000000000..590f6f5e407ed Binary files /dev/null and b/docs/en/docs/img/deployment/deta/image05.png differ diff --git a/docs/en/docs/img/deployment/deta/image06.png b/docs/en/docs/img/deployment/deta/image06.png new file mode 100644 index 0000000000000..f5828bfda66e8 Binary files /dev/null and b/docs/en/docs/img/deployment/deta/image06.png differ diff --git a/docs/en/docs/img/deployment/https/https.drawio.svg b/docs/en/docs/img/deployment/https/https.drawio.svg new file mode 100644 index 0000000000000..c2a65b69ff98d --- /dev/null +++ b/docs/en/docs/img/deployment/https/https.drawio.svg @@ -0,0 +1,907 @@ + + + + + + + + + + + + + + + + + + + +
+
+
+ + + Server(s) + + +
+
+
+
+ + Server(s) + +
+
+
+ + + + + + + + + + + +
+
+
+ + DNS Servers + +
+
+
+
+ + DNS Servers + +
+
+
+ + + + + + + + + + +
+
+
+ + + TLS Termination Proxy + +
+
+
+
+
+
+ + TLS Termination Proxy + +
+
+
+ + + + + + + + + + + + + + + +
+
+
+ + Cert Renovation Program + +
+
+
+
+ + Cert Renovation Program + +
+
+
+ + + + + + + + + + + +
+
+
+ + Let's Encrypt + +
+
+
+
+ + Let's Encrypt + +
+
+
+ + + + + + + + + + + + + + + +
+
+
+ + + FastAPI + + + app for: someapp.example.com + + +
+
+
+
+ + FastAPI app for: someapp.example.com + +
+
+
+ + + + + + + +
+
+
+ + + Another app + + + : another.example.com + + +
+
+
+
+ + Another app: another.example.com + +
+
+
+ + + + + + + +
+
+
+ + + One more app + + + : onemore.example.com + + +
+
+
+
+ + One more app: onemore.example.com + +
+
+
+ + + + + + + +
+
+
+ + + A Database + + +
+
+
+
+ + A Database + +
+
+
+ + + + + + + + + + + + + +
+
+
+ + + Plain response from: someapp.example.com + + +
+
+
+
+ + Plain response from: someapp.example.com + +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ + Port 443 (HTTPS) + +
+
+
+
+ + Port 443 (HTTPS) + +
+
+
+ + + + + + + + + + + + + + +
+
+
+ + + Encrypted request for: someapp.example.com + + +
+
+
+
+ + Encrypted request for: someapp.example.com + +
+
+
+ + + + + + + +
+
+
+ + + Who is: someapp.example.com + + +
+
+
+
+ + Who is: someapp.example.com + +
+
+
+ + + + + + + +
+
+
+ + + IP: + +
+ + 123.124.125.126 + +
+
+
+
+
+ + IP:... + +
+
+
+ + + + + + + +
+
+
+ + + Renew HTTPS cert for: someapp.example.com + + +
+
+
+
+ + Renew HTTPS cert for: someapp.example.com + +
+
+
+ + + + + + + +
+
+
+ + + New HTTPS cert for: someapp.example.com + + +
+
+
+
+ + New HTTPS cert for: someapp.example.com + +
+
+
+ + + + + + + + + + +
+
+
+ + + TLS Handshake + + +
+
+
+
+ + TLS Handshake + +
+
+
+ + + + + + + + + + +
+
+
+ + + Encrypted response from: someapp.example.com + + +
+
+
+
+ + Encrypted response from: someapp.example.com + +
+
+
+ + + + + + + + + + + + + +
+
+
+ + + HTTPS certificates + +
+
+
+
+
+
+ + HTTPS certificates + +
+
+
+ + + + + + + +
+
+
+ + + + someapp.example.com + + +
+
+
+
+
+
+ + someapp.example.com + +
+
+
+ + + + + + + +
+
+
+ + + + another.example.net + + +
+
+
+
+
+
+ + another.example.net + +
+
+
+ + + + + + + +
+
+
+ + + + onemore.example.org + + +
+
+
+
+
+
+ + onemore.example.org + +
+
+
+ + + + + + + +
+
+
+ + + + IP: + +
+ + 123.124.125.126 + +
+
+
+
+
+
+
+ + IP:... + +
+
+
+ + + + + + + +
+
+
+ + + Decrypted request for: someapp.example.com + + +
+
+
+
+ + Decrypted request for: someapp.example.com + +
+
+
+ + + + + + + + + + +
+
+
+ + https://someapp.example.com + +
+
+
+
+ + https://someapp.example.com + +
+
+
+
+ + + + + Text is not SVG - cannot display + + + +
diff --git a/docs/en/docs/img/deployment/https/https01.drawio.svg b/docs/en/docs/img/deployment/https/https01.drawio.svg new file mode 100644 index 0000000000000..ea128daf821bd --- /dev/null +++ b/docs/en/docs/img/deployment/https/https01.drawio.svg @@ -0,0 +1,131 @@ + + + + + + + + + + + + + + + + + + +
+
+
+ + DNS Servers + +
+
+
+
+ + DNS Servers + +
+
+
+ + + + + + + + + + + + + + + + + +
+
+
+ + + Who is: someapp.example.com + + +
+
+
+
+ + Who is: someapp.example.com + +
+
+
+ + + + + + + +
+
+
+ + + IP: + +
+ + 123.124.125.126 + +
+
+
+
+
+ + IP:... + +
+
+
+ + + + + + + +
+
+
+ + https://someapp.example.com + +
+
+
+
+ + https://someapp.example.com + +
+
+
+
+ + + + + Text is not SVG - cannot display + + + +
diff --git a/docs/en/docs/img/deployment/https/https02.drawio.svg b/docs/en/docs/img/deployment/https/https02.drawio.svg new file mode 100644 index 0000000000000..c29d59356890a --- /dev/null +++ b/docs/en/docs/img/deployment/https/https02.drawio.svg @@ -0,0 +1,245 @@ + + + + + + + + + + + + + + + + + +
+
+
+ + + Server(s) + + +
+
+
+
+ + Server(s) + +
+
+
+ + + + + + + + + + + +
+
+
+ + DNS Servers + +
+
+
+
+ + DNS Servers + +
+
+
+ + + + + + + + + + + + + + + + + +
+
+
+ + Port 443 (HTTPS) + +
+
+
+
+ + Port 443 (HTTPS) + +
+
+
+ + + + + + + +
+
+
+ + + + IP: + +
+ + 123.124.125.126 + +
+
+
+
+
+
+
+ + IP:... + +
+
+
+ + + + + + + +
+
+
+ + + Who is: someapp.example.com + + +
+
+
+
+ + Who is: someapp.example.com + +
+
+
+ + + + + + + +
+
+
+ + + IP: + +
+ + 123.124.125.126 + +
+
+
+
+
+ + IP:... + +
+
+
+ + + + + + + + + + +
+
+
+ + + TLS Handshake + + +
+
+
+
+ + TLS Handshake + +
+
+
+ + + + + + + + + + +
+
+
+ + https://someapp.example.com + +
+
+
+
+ + https://someapp.example.com + +
+
+
+
+ + + + + Text is not SVG - cannot display + + + +
diff --git a/docs/en/docs/img/deployment/https/https03.drawio.svg b/docs/en/docs/img/deployment/https/https03.drawio.svg new file mode 100644 index 0000000000000..6971e4c9c23e7 --- /dev/null +++ b/docs/en/docs/img/deployment/https/https03.drawio.svg @@ -0,0 +1,715 @@ + + + + + + + + + + + + + + + + + + + +
+
+
+ + + Server(s) + + +
+
+
+
+ + Server(s) + +
+
+
+ + + + + + + + + + + +
+
+
+ + DNS Servers + +
+
+
+
+ + DNS Servers + +
+
+
+ + + + + + + + + + +
+
+
+ + + TLS Termination Proxy + +
+
+
+
+
+
+ + TLS Termination Proxy + +
+
+
+ + + + + + + + + + + + + + + + + +
+
+
+ + Port 443 (HTTPS) + +
+
+
+
+ + Port 443 (HTTPS) + +
+
+
+ + + + + + + +
+
+
+ + + Who is: someapp.example.com + + +
+
+
+
+ + Who is: someapp.example.com + +
+
+
+ + + + + + + +
+
+
+ + + IP: + +
+ + 123.124.125.126 + +
+
+
+
+
+ + IP:... + +
+
+
+ + + + + + + + + + +
+
+
+ + + TLS Handshake + + +
+
+
+
+ + TLS Handshake + +
+
+
+ + + + + + + + + + + + + +
+
+
+ + + HTTPS certificates + +
+
+
+
+
+
+ + HTTPS certificates + +
+
+
+ + + + + + + +
+
+
+ + + + someapp.example.com + + +
+
+
+
+
+
+ + someapp.example.com + +
+
+
+ + + + + + + +
+
+
+ + + + another.example.net + + +
+
+
+
+
+
+ + another.example.net + +
+
+
+ + + + + + + +
+
+
+ + + + onemore.example.org + + +
+
+
+
+
+
+ + onemore.example.org + +
+
+
+ + + + + + + +
+
+
+ + + + IP: + +
+ + 123.124.125.126 + +
+
+
+
+
+
+
+ + IP:... + +
+
+
+ + + + + + + +
+
+
+ + https://someapp.example.com + +
+
+
+
+ + https://someapp.example.com + +
+
+
+
+ + + + + Text is not SVG - cannot display + + + +
diff --git a/docs/en/docs/img/deployment/https/https04.drawio.svg b/docs/en/docs/img/deployment/https/https04.drawio.svg new file mode 100644 index 0000000000000..7e32bcdfe3ad6 --- /dev/null +++ b/docs/en/docs/img/deployment/https/https04.drawio.svg @@ -0,0 +1,419 @@ + + + + + + + + + + + + + + + + + +
+
+
+ + + Server(s) + + +
+
+
+
+ + Server(s) + +
+
+
+ + + + + + + + + + + +
+
+
+ + DNS Servers + +
+
+
+
+ + DNS Servers + +
+
+
+ + + + + + + + + + +
+
+
+ + + TLS Termination Proxy + +
+
+
+
+
+
+ + TLS Termination Proxy + +
+
+
+ + + + + + + + + + + + + + + + + +
+
+
+ + Port 443 (HTTPS) + +
+
+
+
+ + Port 443 (HTTPS) + +
+
+
+ + + + + + + + + + + + + + +
+
+
+ + + Encrypted request for: someapp.example.com + + +
+
+
+
+ + Encrypted request for: someapp.example.com + +
+
+
+ + + + + + + +
+
+
+ + + Who is: someapp.example.com + + +
+
+
+
+ + Who is: someapp.example.com + +
+
+
+ + + + + + + +
+
+
+ + + IP: + +
+ + 123.124.125.126 + +
+
+
+
+
+ + IP:... + +
+
+
+ + + + + + + + + + +
+
+
+ + + TLS Handshake + + +
+
+
+
+ + TLS Handshake + +
+
+
+ + + + + + + + + + + + + +
+
+
+ + + HTTPS certificates + +
+
+
+
+
+
+ + HTTPS certificates + +
+
+
+ + + + + + + +
+
+
+ + + + someapp.example.com + + +
+
+
+
+
+
+ + someapp.example.com + +
+
+
+ + + + + + + +
+
+
+ + + + another.example.net + + +
+
+
+
+
+
+ + another.example.net + +
+
+
+ + + + + + + +
+
+
+ + + + onemore.example.org + + +
+
+
+
+
+
+ + onemore.example.org + +
+
+
+ + + + + + + +
+
+
+ + + + IP: + +
+ + 123.124.125.126 + +
+
+
+
+
+
+
+ + IP:... + +
+
+
+ + + + + + + +
+
+
+ + https://someapp.example.com + +
+
+
+
+ + https://someapp.example.com + +
+
+
+
+ + + + + Text is not SVG - cannot display + + + +
diff --git a/docs/en/docs/img/deployment/https/https05.drawio.svg b/docs/en/docs/img/deployment/https/https05.drawio.svg new file mode 100644 index 0000000000000..fed2fad1695ed --- /dev/null +++ b/docs/en/docs/img/deployment/https/https05.drawio.svg @@ -0,0 +1,641 @@ + + + + + + + + + + + + + + + + + + + +
+
+
+ + + Server(s) + + +
+
+
+
+ + Server(s) + +
+
+
+ + + + + + + + + + + +
+
+
+ + DNS Servers + +
+
+
+
+ + DNS Servers + +
+
+
+ + + + + + + + + + +
+
+
+ + + TLS Termination Proxy + +
+
+
+
+
+
+ + TLS Termination Proxy + +
+
+
+ + + + + + + +
+
+
+ + + FastAPI + + + app for: someapp.example.com + + +
+
+
+
+ + FastAPI app for: someapp.example.com + +
+
+
+ + + + + + + + + + + +
+
+
+ + + Decrypted request for: someapp.example.com + + +
+
+
+
+ + Decrypted request for: someapp.example.com + +
+
+
+ + + + + + + + + + + + + + + + + +
+
+
+ + Port 443 (HTTPS) + +
+
+
+
+ + Port 443 (HTTPS) + +
+
+
+ + + + + + + + + + + + + + +
+
+
+ + + Encrypted request for: someapp.example.com + + +
+
+
+
+ + Encrypted request for: someapp.example.com + +
+
+
+ + + + + + + +
+
+
+ + + Who is: someapp.example.com + + +
+
+
+
+ + Who is: someapp.example.com + +
+
+
+ + + + + + + +
+
+
+ + + IP: + +
+ + 123.124.125.126 + +
+
+
+
+
+ + IP:... + +
+
+
+ + + + + + + + + + +
+
+
+ + + TLS Handshake + + +
+
+
+
+ + TLS Handshake + +
+
+
+ + + + + + + + + + + + + +
+
+
+ + + HTTPS certificates + +
+
+
+
+
+
+ + HTTPS certificates + +
+
+
+ + + + + + + +
+
+
+ + + + someapp.example.com + + +
+
+
+
+
+
+ + someapp.example.com + +
+
+
+ + + + + + + +
+
+
+ + + + another.example.net + + +
+
+
+
+
+
+ + another.example.net + +
+
+
+ + + + + + + +
+
+
+ + + + onemore.example.org + + +
+
+
+
+
+
+ + onemore.example.org + +
+
+
+ + + + + + + +
+
+
+ + + + IP: + +
+ + 123.124.125.126 + +
+
+
+
+
+
+
+ + IP:... + +
+
+
+ + + + + + + +
+
+
+ + https://someapp.example.com + +
+
+
+
+ + https://someapp.example.com + +
+
+
+
+ + + + + Text is not SVG - cannot display + + + +
diff --git a/docs/en/docs/img/deployment/https/https06.drawio.svg b/docs/en/docs/img/deployment/https/https06.drawio.svg new file mode 100644 index 0000000000000..e0bd9bc6e3548 --- /dev/null +++ b/docs/en/docs/img/deployment/https/https06.drawio.svg @@ -0,0 +1,673 @@ + + + + + + + + + + + + + + + + + + + +
+
+
+ + + Server(s) + + +
+
+
+
+ + Server(s) + +
+
+
+ + + + + + + + + + + +
+
+
+ + DNS Servers + +
+
+
+
+ + DNS Servers + +
+
+
+ + + + + + + + + + +
+
+
+ + + TLS Termination Proxy + +
+
+
+
+
+
+ + TLS Termination Proxy + +
+
+
+ + + + + + + + + + + +
+
+
+ + + FastAPI + + + app for: someapp.example.com + + +
+
+
+
+ + FastAPI app for: someapp.example.com + +
+
+
+ + + + + + + +
+
+
+ + + Plain response from: someapp.example.com + + +
+
+
+
+ + Plain response from: someapp.example.com + +
+
+
+ + + + + + + + + + + + + + +
+
+
+ + + Decrypted request for: someapp.example.com + + +
+
+
+
+ + Decrypted request for: someapp.example.com + +
+
+
+ + + + + + + + + + + + + + + + + +
+
+
+ + Port 443 (HTTPS) + +
+
+
+
+ + Port 443 (HTTPS) + +
+
+
+ + + + + + + + + + + + + + +
+
+
+ + + Encrypted request for: someapp.example.com + + +
+
+
+
+ + Encrypted request for: someapp.example.com + +
+
+
+ + + + + + + +
+
+
+ + + Who is: someapp.example.com + + +
+
+
+
+ + Who is: someapp.example.com + +
+
+
+ + + + + + + +
+
+
+ + + IP: + +
+ + 123.124.125.126 + +
+
+
+
+
+ + IP:... + +
+
+
+ + + + + + + + + + +
+
+
+ + + TLS Handshake + + +
+
+
+
+ + TLS Handshake + +
+
+
+ + + + + + + + + + + + + +
+
+
+ + + HTTPS certificates + +
+
+
+
+
+
+ + HTTPS certificates + +
+
+
+ + + + + + + +
+
+
+ + + + someapp.example.com + + +
+
+
+
+
+
+ + someapp.example.com + +
+
+
+ + + + + + + +
+
+
+ + + + another.example.net + + +
+
+
+
+
+
+ + another.example.net + +
+
+
+ + + + + + + +
+
+
+ + + + onemore.example.org + + +
+
+
+
+
+
+ + onemore.example.org + +
+
+
+ + + + + + + +
+
+
+ + + + IP: + +
+ + 123.124.125.126 + +
+
+
+
+
+
+
+ + IP:... + +
+
+
+ + + + + + + +
+
+
+ + https://someapp.example.com + +
+
+
+
+ + https://someapp.example.com + +
+
+
+
+ + + + + Text is not SVG - cannot display + + + +
diff --git a/docs/en/docs/img/deployment/https/https07.drawio.svg b/docs/en/docs/img/deployment/https/https07.drawio.svg new file mode 100644 index 0000000000000..b74b338078763 --- /dev/null +++ b/docs/en/docs/img/deployment/https/https07.drawio.svg @@ -0,0 +1,540 @@ + + + + + + + + + + + + + + + + + +
+
+
+ + + Server(s) + + +
+
+
+
+ + Server(s) + +
+
+
+ + + + + + + + + + + +
+
+
+ + DNS Servers + +
+
+
+
+ + DNS Servers + +
+
+
+ + + + + + + + + + +
+
+
+ + + TLS Termination Proxy + +
+
+
+
+
+
+ + TLS Termination Proxy + +
+
+
+ + + + + + + + + + + +
+
+
+ + + FastAPI + + + app for: someapp.example.com + + +
+
+
+
+ + FastAPI app for: someapp.example.com + +
+
+
+ + + + + + + +
+
+
+ + + Plain response from: someapp.example.com + + +
+
+
+
+ + Plain response from: someapp.example.com + +
+
+
+ + + + + + + + + + + + + + +
+
+
+ + + Decrypted request for: someapp.example.com + + +
+
+
+
+ + Decrypted request for: someapp.example.com + +
+
+
+ + + + + + + + + + + + + + + + + + + + + +
+
+
+ + Port 443 (HTTPS) + +
+
+
+
+ + Port 443 (HTTPS) + +
+
+
+ + + + + + + + + + + + + + +
+
+
+ + + Encrypted request for: someapp.example.com + + +
+
+
+
+ + Encrypted request for: someapp.example.com + +
+
+
+ + + + + + + +
+
+
+ + + Who is: someapp.example.com + + +
+
+
+
+ + Who is: someapp.example.com + +
+
+
+ + + + + + + +
+
+
+ + + IP: + +
+ + 123.124.125.126 + +
+
+
+
+
+ + IP:... + +
+
+
+ + + + + + + + + + +
+
+
+ + + TLS Handshake + + +
+
+
+
+ + TLS Handshake + +
+
+
+ + + + + + + + + + +
+
+
+ + + Encrypted response from: someapp.example.com + + +
+
+
+
+ + Encrypted response from: someapp.example.com + +
+
+
+ + + + + + + + + + + + + +
+
+
+ + + HTTPS certificates + +
+
+
+
+
+
+ + HTTPS certificates + +
+
+
+ + + + + + + +
+
+
+ + + + someapp.example.com + + +
+
+
+
+
+
+ + someapp.example.com + +
+
+
+ + + + + + + +
+
+
+ + + + another.example.net + + +
+
+
+
+
+
+ + another.example.net + +
+
+
+ + + + + + + +
+
+
+ + + + onemore.example.org + + +
+
+
+
+
+
+ + onemore.example.org + +
+
+
+ + + + + + + +
+
+
+ + + + IP: + +
+ + 123.124.125.126 + +
+
+
+
+
+
+
+ + IP:... + +
+
+
+ + + + + + + +
+
+
+ + https://someapp.example.com + +
+
+
+
+ + https://someapp.example.com + +
+
+
+
+ + + + + Text is not SVG - cannot display + + + +
diff --git a/docs/en/docs/img/deployment/https/https08.drawio.svg b/docs/en/docs/img/deployment/https/https08.drawio.svg new file mode 100644 index 0000000000000..8fc0b31ecbfc2 --- /dev/null +++ b/docs/en/docs/img/deployment/https/https08.drawio.svg @@ -0,0 +1,625 @@ + + + + + + + + + + + + + + + + + +
+
+
+ + + Server(s) + + +
+
+
+
+ + Server(s) + +
+
+
+ + + + + + + + + + + +
+
+
+ + DNS Servers + +
+
+
+
+ + DNS Servers + +
+
+
+ + + + + + + + + + +
+
+
+ + + TLS Termination Proxy + +
+
+
+
+
+
+ + TLS Termination Proxy + +
+
+
+ + + + + + + + + + + + + + + +
+
+
+ + + FastAPI + + + app for: someapp.example.com + + +
+
+
+
+ + FastAPI app for: someapp.example.com + +
+
+
+ + + + + + + +
+
+
+ + + Another app + + + : another.example.com + + +
+
+
+
+ + Another app: another.example.com + +
+
+
+ + + + + + + +
+
+
+ + + One more app + + + : onemore.example.com + + +
+
+
+
+ + One more app: onemore.example.com + +
+
+
+ + + + + + + +
+
+
+ + + A Database + + +
+
+
+
+ + A Database + +
+
+
+ + + + + + + +
+
+
+ + + Plain response from: someapp.example.com + + +
+
+
+
+ + Plain response from: someapp.example.com + +
+
+
+ + + + + + + + + + + + + + +
+
+
+ + + Decrypted request for: someapp.example.com + + +
+
+
+
+ + Decrypted request for: someapp.example.com + +
+
+
+ + + + + + + + + + + + + + + + + + + + + +
+
+
+ + Port 443 (HTTPS) + +
+
+
+
+ + Port 443 (HTTPS) + +
+
+
+ + + + + + + + + + + + + + +
+
+
+ + + Encrypted request for: someapp.example.com + + +
+
+
+
+ + Encrypted request for: someapp.example.com + +
+
+
+ + + + + + + +
+
+
+ + + Who is: someapp.example.com + + +
+
+
+
+ + Who is: someapp.example.com + +
+
+
+ + + + + + + +
+
+
+ + + IP: + +
+ + 123.124.125.126 + +
+
+
+
+
+ + IP:... + +
+
+
+ + + + + + + + + + +
+
+
+ + + TLS Handshake + + +
+
+
+
+ + TLS Handshake + +
+
+
+ + + + + + + + + + +
+
+
+ + + Encrypted response from: someapp.example.com + + +
+
+
+
+ + Encrypted response from: someapp.example.com + +
+
+
+ + + + + + + + + + + + + +
+
+
+ + + HTTPS certificates + +
+
+
+
+
+
+ + HTTPS certificates + +
+
+
+ + + + + + + +
+
+
+ + + + someapp.example.com + + +
+
+
+
+
+
+ + someapp.example.com + +
+
+
+ + + + + + + +
+
+
+ + + + another.example.net + + +
+
+
+
+
+
+ + another.example.net + +
+
+
+ + + + + + + +
+
+
+ + + + onemore.example.org + + +
+
+
+
+
+
+ + onemore.example.org + +
+
+
+ + + + + + + +
+
+
+ + + + IP: + +
+ + 123.124.125.126 + +
+
+
+
+
+
+
+ + IP:... + +
+
+
+ + + + + + + +
+
+
+ + https://someapp.example.com + +
+
+
+
+ + https://someapp.example.com + +
+
+
+
+ + + + + Text is not SVG - cannot display + + + +
diff --git a/docs/en/docs/img/fastapi-conf.jpeg b/docs/en/docs/img/fastapi-conf.jpeg new file mode 100644 index 0000000000000..14e77b997ffa7 Binary files /dev/null and b/docs/en/docs/img/fastapi-conf.jpeg differ diff --git a/docs/en/docs/img/fastapi-documentary.jpg b/docs/en/docs/img/fastapi-documentary.jpg new file mode 100644 index 0000000000000..3ddbfdb389794 Binary files /dev/null and b/docs/en/docs/img/fastapi-documentary.jpg differ diff --git a/docs/en/docs/img/favicon.png b/docs/en/docs/img/favicon.png new file mode 100644 index 0000000000000..e5b7c3ada7d09 Binary files /dev/null and b/docs/en/docs/img/favicon.png differ diff --git a/docs/en/docs/img/github-social-preview.png b/docs/en/docs/img/github-social-preview.png new file mode 100644 index 0000000000000..4c299c1d6a1ac Binary files /dev/null and b/docs/en/docs/img/github-social-preview.png differ diff --git a/docs/en/docs/img/github-social-preview.svg b/docs/en/docs/img/github-social-preview.svg new file mode 100644 index 0000000000000..f03a0eefde8e4 --- /dev/null +++ b/docs/en/docs/img/github-social-preview.svg @@ -0,0 +1,75 @@ + + + + + + + image/svg+xml + + + + + + + + + + + FastAPI + + High performance, easy to learn,fast to code, ready for production + diff --git a/docs/en/docs/img/icon-white.svg b/docs/en/docs/img/icon-white.svg new file mode 100644 index 0000000000000..19f0825cc245a --- /dev/null +++ b/docs/en/docs/img/icon-white.svg @@ -0,0 +1,34 @@ + + + + + + + image/svg+xml + + + + + + + diff --git a/docs/img/index/index-01-swagger-ui-simple.png b/docs/en/docs/img/index/index-01-swagger-ui-simple.png similarity index 100% rename from docs/img/index/index-01-swagger-ui-simple.png rename to docs/en/docs/img/index/index-01-swagger-ui-simple.png diff --git a/docs/img/index/index-02-redoc-simple.png b/docs/en/docs/img/index/index-02-redoc-simple.png similarity index 100% rename from docs/img/index/index-02-redoc-simple.png rename to docs/en/docs/img/index/index-02-redoc-simple.png diff --git a/docs/img/index/index-03-swagger-02.png b/docs/en/docs/img/index/index-03-swagger-02.png similarity index 100% rename from docs/img/index/index-03-swagger-02.png rename to docs/en/docs/img/index/index-03-swagger-02.png diff --git a/docs/img/index/index-04-swagger-03.png b/docs/en/docs/img/index/index-04-swagger-03.png similarity index 100% rename from docs/img/index/index-04-swagger-03.png rename to docs/en/docs/img/index/index-04-swagger-03.png diff --git a/docs/img/index/index-05-swagger-04.png b/docs/en/docs/img/index/index-05-swagger-04.png similarity index 100% rename from docs/img/index/index-05-swagger-04.png rename to docs/en/docs/img/index/index-05-swagger-04.png diff --git a/docs/img/index/index-06-redoc-02.png b/docs/en/docs/img/index/index-06-redoc-02.png similarity index 100% rename from docs/img/index/index-06-redoc-02.png rename to docs/en/docs/img/index/index-06-redoc-02.png diff --git a/docs/en/docs/img/logo-margin/logo-teal-vector.svg b/docs/en/docs/img/logo-margin/logo-teal-vector.svg new file mode 100644 index 0000000000000..3eb945c7e5ad7 --- /dev/null +++ b/docs/en/docs/img/logo-margin/logo-teal-vector.svg @@ -0,0 +1,55 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + diff --git a/docs/en/docs/img/logo-margin/logo-teal.png b/docs/en/docs/img/logo-margin/logo-teal.png new file mode 100644 index 0000000000000..f08144cd92e7a Binary files /dev/null and b/docs/en/docs/img/logo-margin/logo-teal.png differ diff --git a/docs/en/docs/img/logo-margin/logo-teal.svg b/docs/en/docs/img/logo-margin/logo-teal.svg new file mode 100644 index 0000000000000..ce9db533b0e76 --- /dev/null +++ b/docs/en/docs/img/logo-margin/logo-teal.svg @@ -0,0 +1,59 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + diff --git a/docs/en/docs/img/logo-margin/logo-white-bg.png b/docs/en/docs/img/logo-margin/logo-white-bg.png new file mode 100644 index 0000000000000..b84fd285ee52d Binary files /dev/null and b/docs/en/docs/img/logo-margin/logo-white-bg.png differ diff --git a/docs/en/docs/img/logo-teal-vector.svg b/docs/en/docs/img/logo-teal-vector.svg new file mode 100644 index 0000000000000..d3dad4bec8b31 --- /dev/null +++ b/docs/en/docs/img/logo-teal-vector.svg @@ -0,0 +1,51 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + diff --git a/docs/en/docs/img/logo-teal.svg b/docs/en/docs/img/logo-teal.svg new file mode 100644 index 0000000000000..bc699860fc478 --- /dev/null +++ b/docs/en/docs/img/logo-teal.svg @@ -0,0 +1,56 @@ + + + + + + + image/svg+xml + + + + + + + + + + + FastAPI + + + diff --git a/docs/en/docs/img/logos/cisco.svg b/docs/en/docs/img/logos/cisco.svg new file mode 100644 index 0000000000000..b1f6ae27b1e50 --- /dev/null +++ b/docs/en/docs/img/logos/cisco.svg @@ -0,0 +1,35 @@ + + + + + + + + + + + diff --git a/docs/en/docs/img/logos/microsoft.svg b/docs/en/docs/img/logos/microsoft.svg new file mode 100644 index 0000000000000..e77821b28f72b --- /dev/null +++ b/docs/en/docs/img/logos/microsoft.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/docs/en/docs/img/logos/netflix.svg b/docs/en/docs/img/logos/netflix.svg new file mode 100644 index 0000000000000..3c015f960b36a --- /dev/null +++ b/docs/en/docs/img/logos/netflix.svg @@ -0,0 +1 @@ + diff --git a/docs/en/docs/img/logos/uber.svg b/docs/en/docs/img/logos/uber.svg new file mode 100644 index 0000000000000..bc0bd54d82695 --- /dev/null +++ b/docs/en/docs/img/logos/uber.svg @@ -0,0 +1,39 @@ + + + + + + + + + + + diff --git a/docs/img/pycharm-completion.png b/docs/en/docs/img/pycharm-completion.png similarity index 100% rename from docs/img/pycharm-completion.png rename to docs/en/docs/img/pycharm-completion.png diff --git a/docs/img/python-types/image01.png b/docs/en/docs/img/python-types/image01.png similarity index 100% rename from docs/img/python-types/image01.png rename to docs/en/docs/img/python-types/image01.png diff --git a/docs/img/python-types/image02.png b/docs/en/docs/img/python-types/image02.png similarity index 100% rename from docs/img/python-types/image02.png rename to docs/en/docs/img/python-types/image02.png diff --git a/docs/img/python-types/image03.png b/docs/en/docs/img/python-types/image03.png similarity index 100% rename from docs/img/python-types/image03.png rename to docs/en/docs/img/python-types/image03.png diff --git a/docs/img/python-types/image04.png b/docs/en/docs/img/python-types/image04.png similarity index 100% rename from docs/img/python-types/image04.png rename to docs/en/docs/img/python-types/image04.png diff --git a/docs/img/python-types/image05.png b/docs/en/docs/img/python-types/image05.png similarity index 100% rename from docs/img/python-types/image05.png rename to docs/en/docs/img/python-types/image05.png diff --git a/docs/img/python-types/image06.png b/docs/en/docs/img/python-types/image06.png similarity index 100% rename from docs/img/python-types/image06.png rename to docs/en/docs/img/python-types/image06.png diff --git a/docs/en/docs/img/sponsors/bairesdev.svg b/docs/en/docs/img/sponsors/bairesdev.svg new file mode 100644 index 0000000000000..c982d4e0e8843 --- /dev/null +++ b/docs/en/docs/img/sponsors/bairesdev.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/docs/en/docs/img/sponsors/blockbee-banner.png b/docs/en/docs/img/sponsors/blockbee-banner.png new file mode 100644 index 0000000000000..074b36031244e Binary files /dev/null and b/docs/en/docs/img/sponsors/blockbee-banner.png differ diff --git a/docs/en/docs/img/sponsors/blockbee.png b/docs/en/docs/img/sponsors/blockbee.png new file mode 100644 index 0000000000000..6d2fcf7019c88 Binary files /dev/null and b/docs/en/docs/img/sponsors/blockbee.png differ diff --git a/docs/en/docs/img/sponsors/budget-insight.svg b/docs/en/docs/img/sponsors/budget-insight.svg new file mode 100644 index 0000000000000..d753727a1f8a5 --- /dev/null +++ b/docs/en/docs/img/sponsors/budget-insight.svg @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/en/docs/img/sponsors/bump-sh-banner.png b/docs/en/docs/img/sponsors/bump-sh-banner.png new file mode 100755 index 0000000000000..e75c0facd30ac Binary files /dev/null and b/docs/en/docs/img/sponsors/bump-sh-banner.png differ diff --git a/docs/en/docs/img/sponsors/bump-sh-banner.svg b/docs/en/docs/img/sponsors/bump-sh-banner.svg new file mode 100644 index 0000000000000..c8ec7675a7df5 --- /dev/null +++ b/docs/en/docs/img/sponsors/bump-sh-banner.svg @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/en/docs/img/sponsors/bump-sh.png b/docs/en/docs/img/sponsors/bump-sh.png new file mode 100755 index 0000000000000..61817e86fa106 Binary files /dev/null and b/docs/en/docs/img/sponsors/bump-sh.png differ diff --git a/docs/en/docs/img/sponsors/bump-sh.svg b/docs/en/docs/img/sponsors/bump-sh.svg new file mode 100644 index 0000000000000..053e54b1da4fb --- /dev/null +++ b/docs/en/docs/img/sponsors/bump-sh.svg @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/en/docs/img/sponsors/calmcode.jpg b/docs/en/docs/img/sponsors/calmcode.jpg new file mode 100644 index 0000000000000..59e68dd073578 Binary files /dev/null and b/docs/en/docs/img/sponsors/calmcode.jpg differ diff --git a/docs/en/docs/img/sponsors/classiq-banner.png b/docs/en/docs/img/sponsors/classiq-banner.png new file mode 100644 index 0000000000000..8a0d6ac741907 Binary files /dev/null and b/docs/en/docs/img/sponsors/classiq-banner.png differ diff --git a/docs/en/docs/img/sponsors/classiq.png b/docs/en/docs/img/sponsors/classiq.png new file mode 100644 index 0000000000000..189c6bbe8a4ad Binary files /dev/null and b/docs/en/docs/img/sponsors/classiq.png differ diff --git a/docs/en/docs/img/sponsors/codacy.png b/docs/en/docs/img/sponsors/codacy.png new file mode 100644 index 0000000000000..baa615c2a8364 Binary files /dev/null and b/docs/en/docs/img/sponsors/codacy.png differ diff --git a/docs/en/docs/img/sponsors/coderabbit-banner.png b/docs/en/docs/img/sponsors/coderabbit-banner.png new file mode 100644 index 0000000000000..da3bb348204a3 Binary files /dev/null and b/docs/en/docs/img/sponsors/coderabbit-banner.png differ diff --git a/docs/en/docs/img/sponsors/coderabbit.png b/docs/en/docs/img/sponsors/coderabbit.png new file mode 100644 index 0000000000000..1fb74569be3ef Binary files /dev/null and b/docs/en/docs/img/sponsors/coderabbit.png differ diff --git a/docs/en/docs/img/sponsors/coherence-banner.png b/docs/en/docs/img/sponsors/coherence-banner.png new file mode 100644 index 0000000000000..1d495965920e7 Binary files /dev/null and b/docs/en/docs/img/sponsors/coherence-banner.png differ diff --git a/docs/en/docs/img/sponsors/coherence.png b/docs/en/docs/img/sponsors/coherence.png new file mode 100644 index 0000000000000..d48c4edc4df96 Binary files /dev/null and b/docs/en/docs/img/sponsors/coherence.png differ diff --git a/docs/en/docs/img/sponsors/cryptapi-banner.svg b/docs/en/docs/img/sponsors/cryptapi-banner.svg new file mode 100644 index 0000000000000..29cd772da1408 --- /dev/null +++ b/docs/en/docs/img/sponsors/cryptapi-banner.svg @@ -0,0 +1,1375 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/en/docs/img/sponsors/cryptapi.svg b/docs/en/docs/img/sponsors/cryptapi.svg new file mode 100644 index 0000000000000..db4e09347b7a9 --- /dev/null +++ b/docs/en/docs/img/sponsors/cryptapi.svg @@ -0,0 +1,1216 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/en/docs/img/sponsors/databento.svg b/docs/en/docs/img/sponsors/databento.svg new file mode 100644 index 0000000000000..dfdd9bee6d194 --- /dev/null +++ b/docs/en/docs/img/sponsors/databento.svg @@ -0,0 +1,144 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/en/docs/img/sponsors/deta-banner.svg b/docs/en/docs/img/sponsors/deta-banner.svg new file mode 100644 index 0000000000000..e9b344ad302b7 --- /dev/null +++ b/docs/en/docs/img/sponsors/deta-banner.svg @@ -0,0 +1,125 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/en/docs/img/sponsors/deta.svg b/docs/en/docs/img/sponsors/deta.svg new file mode 100644 index 0000000000000..066d6be7a8451 --- /dev/null +++ b/docs/en/docs/img/sponsors/deta.svg @@ -0,0 +1,65 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + diff --git a/docs/en/docs/img/sponsors/docarray-top-banner.svg b/docs/en/docs/img/sponsors/docarray-top-banner.svg new file mode 100644 index 0000000000000..b2eca354437e6 --- /dev/null +++ b/docs/en/docs/img/sponsors/docarray-top-banner.svg @@ -0,0 +1 @@ + diff --git a/docs/en/docs/img/sponsors/docarray.svg b/docs/en/docs/img/sponsors/docarray.svg new file mode 100644 index 0000000000000..f18df247e833f --- /dev/null +++ b/docs/en/docs/img/sponsors/docarray.svg @@ -0,0 +1 @@ + diff --git a/docs/en/docs/img/sponsors/doist-banner.svg b/docs/en/docs/img/sponsors/doist-banner.svg new file mode 100644 index 0000000000000..3a4d9a2954e37 --- /dev/null +++ b/docs/en/docs/img/sponsors/doist-banner.svg @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/en/docs/img/sponsors/doist.svg b/docs/en/docs/img/sponsors/doist.svg new file mode 100644 index 0000000000000..b55855f0673d0 --- /dev/null +++ b/docs/en/docs/img/sponsors/doist.svg @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/en/docs/img/sponsors/dribia.png b/docs/en/docs/img/sponsors/dribia.png new file mode 100644 index 0000000000000..f40e140863503 Binary files /dev/null and b/docs/en/docs/img/sponsors/dribia.png differ diff --git a/docs/en/docs/img/sponsors/dropbase-banner.svg b/docs/en/docs/img/sponsors/dropbase-banner.svg new file mode 100644 index 0000000000000..d65abf1d9a22f --- /dev/null +++ b/docs/en/docs/img/sponsors/dropbase-banner.svg @@ -0,0 +1,117 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/en/docs/img/sponsors/dropbase.svg b/docs/en/docs/img/sponsors/dropbase.svg new file mode 100644 index 0000000000000..d0defb4df2d62 --- /dev/null +++ b/docs/en/docs/img/sponsors/dropbase.svg @@ -0,0 +1,124 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/en/docs/img/sponsors/exoflare.png b/docs/en/docs/img/sponsors/exoflare.png new file mode 100644 index 0000000000000..b5977d80bedb2 Binary files /dev/null and b/docs/en/docs/img/sponsors/exoflare.png differ diff --git a/docs/en/docs/img/sponsors/fastapi-course-bundle-banner.png b/docs/en/docs/img/sponsors/fastapi-course-bundle-banner.png new file mode 100644 index 0000000000000..220d0863882d1 Binary files /dev/null and b/docs/en/docs/img/sponsors/fastapi-course-bundle-banner.png differ diff --git a/docs/en/docs/img/sponsors/fastapi-course-bundle-banner.svg b/docs/en/docs/img/sponsors/fastapi-course-bundle-banner.svg new file mode 100644 index 0000000000000..5dd89b212a2e4 --- /dev/null +++ b/docs/en/docs/img/sponsors/fastapi-course-bundle-banner.svg @@ -0,0 +1,293 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/en/docs/img/sponsors/fastapicloud.png b/docs/en/docs/img/sponsors/fastapicloud.png new file mode 100644 index 0000000000000..c23dec220951c Binary files /dev/null and b/docs/en/docs/img/sponsors/fastapicloud.png differ diff --git a/docs/en/docs/img/sponsors/fern-banner.png b/docs/en/docs/img/sponsors/fern-banner.png new file mode 100644 index 0000000000000..1b70ab96d9548 Binary files /dev/null and b/docs/en/docs/img/sponsors/fern-banner.png differ diff --git a/docs/en/docs/img/sponsors/fern-banner.svg b/docs/en/docs/img/sponsors/fern-banner.svg new file mode 100644 index 0000000000000..e05ccc3a47aec --- /dev/null +++ b/docs/en/docs/img/sponsors/fern-banner.svg @@ -0,0 +1 @@ + diff --git a/docs/en/docs/img/sponsors/fern.png b/docs/en/docs/img/sponsors/fern.png new file mode 100644 index 0000000000000..4c6e54b0d517f Binary files /dev/null and b/docs/en/docs/img/sponsors/fern.png differ diff --git a/docs/en/docs/img/sponsors/fern.svg b/docs/en/docs/img/sponsors/fern.svg new file mode 100644 index 0000000000000..ad3842fe03eae --- /dev/null +++ b/docs/en/docs/img/sponsors/fern.svg @@ -0,0 +1 @@ + diff --git a/docs/en/docs/img/sponsors/fine-banner.png b/docs/en/docs/img/sponsors/fine-banner.png new file mode 100644 index 0000000000000..57d8e52c71b06 Binary files /dev/null and b/docs/en/docs/img/sponsors/fine-banner.png differ diff --git a/docs/en/docs/img/sponsors/fine.png b/docs/en/docs/img/sponsors/fine.png new file mode 100644 index 0000000000000..ed770f21240df Binary files /dev/null and b/docs/en/docs/img/sponsors/fine.png differ diff --git a/docs/en/docs/img/sponsors/flint.png b/docs/en/docs/img/sponsors/flint.png new file mode 100644 index 0000000000000..761cc334c241f Binary files /dev/null and b/docs/en/docs/img/sponsors/flint.png differ diff --git a/docs/en/docs/img/sponsors/greptile-banner.png b/docs/en/docs/img/sponsors/greptile-banner.png new file mode 100644 index 0000000000000..e0909b39d1d42 Binary files /dev/null and b/docs/en/docs/img/sponsors/greptile-banner.png differ diff --git a/docs/en/docs/img/sponsors/greptile.png b/docs/en/docs/img/sponsors/greptile.png new file mode 100644 index 0000000000000..ae3d78cbdcffe Binary files /dev/null and b/docs/en/docs/img/sponsors/greptile.png differ diff --git a/docs/en/docs/img/sponsors/haystack-fastapi.svg b/docs/en/docs/img/sponsors/haystack-fastapi.svg new file mode 100644 index 0000000000000..6303ba61fbdf5 --- /dev/null +++ b/docs/en/docs/img/sponsors/haystack-fastapi.svg @@ -0,0 +1,192 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/en/docs/img/sponsors/imgwhale-banner.svg b/docs/en/docs/img/sponsors/imgwhale-banner.svg new file mode 100644 index 0000000000000..db87cc4c99329 --- /dev/null +++ b/docs/en/docs/img/sponsors/imgwhale-banner.svg @@ -0,0 +1,14 @@ + + + + + + + + + + ImgWhale + The ultimate solution to unlimited and forevercloud storage. + + diff --git a/docs/en/docs/img/sponsors/imgwhale.svg b/docs/en/docs/img/sponsors/imgwhale.svg new file mode 100644 index 0000000000000..46aefd9305adb --- /dev/null +++ b/docs/en/docs/img/sponsors/imgwhale.svg @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + ImgWhale + + The ultimate solution to unlimited and forever cloud storage. + + The ultimate solution to unlimited and forever cloud storage. + + + + diff --git a/docs/en/docs/img/sponsors/ines-course.jpg b/docs/en/docs/img/sponsors/ines-course.jpg new file mode 100644 index 0000000000000..05158b3872caa Binary files /dev/null and b/docs/en/docs/img/sponsors/ines-course.jpg differ diff --git a/docs/en/docs/img/sponsors/interviewpal.png b/docs/en/docs/img/sponsors/interviewpal.png new file mode 100644 index 0000000000000..e40ed01fd4f9c Binary files /dev/null and b/docs/en/docs/img/sponsors/interviewpal.png differ diff --git a/docs/en/docs/img/sponsors/investsuite.svg b/docs/en/docs/img/sponsors/investsuite.svg new file mode 100644 index 0000000000000..66455dbbe68fa --- /dev/null +++ b/docs/en/docs/img/sponsors/investsuite.svg @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + Wealthtech jobs with FastAPI + diff --git a/docs/en/docs/img/sponsors/jina-ai-banner.png b/docs/en/docs/img/sponsors/jina-ai-banner.png new file mode 100644 index 0000000000000..3ac6b44adcf4b Binary files /dev/null and b/docs/en/docs/img/sponsors/jina-ai-banner.png differ diff --git a/docs/en/docs/img/sponsors/jina-ai.png b/docs/en/docs/img/sponsors/jina-ai.png new file mode 100644 index 0000000000000..d6b0bfb4ec24a Binary files /dev/null and b/docs/en/docs/img/sponsors/jina-ai.png differ diff --git a/docs/en/docs/img/sponsors/jina-banner.svg b/docs/en/docs/img/sponsors/jina-banner.svg new file mode 100644 index 0000000000000..ebde273eedcb9 --- /dev/null +++ b/docs/en/docs/img/sponsors/jina-banner.svg @@ -0,0 +1,233 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/en/docs/img/sponsors/jina-top-banner.svg b/docs/en/docs/img/sponsors/jina-top-banner.svg new file mode 100644 index 0000000000000..8b62cd61978d2 --- /dev/null +++ b/docs/en/docs/img/sponsors/jina-top-banner.svg @@ -0,0 +1 @@ + diff --git a/docs/en/docs/img/sponsors/jina.svg b/docs/en/docs/img/sponsors/jina.svg new file mode 100644 index 0000000000000..3dda4fe3cde13 --- /dev/null +++ b/docs/en/docs/img/sponsors/jina.svg @@ -0,0 +1,1981 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/en/docs/img/sponsors/jina2.svg b/docs/en/docs/img/sponsors/jina2.svg new file mode 100644 index 0000000000000..6a48677baa98e --- /dev/null +++ b/docs/en/docs/img/sponsors/jina2.svg @@ -0,0 +1 @@ + diff --git a/docs/en/docs/img/sponsors/kong-banner.png b/docs/en/docs/img/sponsors/kong-banner.png new file mode 100644 index 0000000000000..9f5b55a0fe8bc Binary files /dev/null and b/docs/en/docs/img/sponsors/kong-banner.png differ diff --git a/docs/en/docs/img/sponsors/kong.png b/docs/en/docs/img/sponsors/kong.png new file mode 100644 index 0000000000000..e54cdac2cfc3a Binary files /dev/null and b/docs/en/docs/img/sponsors/kong.png differ diff --git a/docs/en/docs/img/sponsors/lambdatest.png b/docs/en/docs/img/sponsors/lambdatest.png new file mode 100644 index 0000000000000..674cbcb893dfe Binary files /dev/null and b/docs/en/docs/img/sponsors/lambdatest.png differ diff --git a/docs/en/docs/img/sponsors/liblab-banner.png b/docs/en/docs/img/sponsors/liblab-banner.png new file mode 100644 index 0000000000000..299ff816b8b97 Binary files /dev/null and b/docs/en/docs/img/sponsors/liblab-banner.png differ diff --git a/docs/en/docs/img/sponsors/liblab.png b/docs/en/docs/img/sponsors/liblab.png new file mode 100644 index 0000000000000..ee461d7bcad65 Binary files /dev/null and b/docs/en/docs/img/sponsors/liblab.png differ diff --git a/docs/en/docs/img/sponsors/mobbai-banner.png b/docs/en/docs/img/sponsors/mobbai-banner.png new file mode 100644 index 0000000000000..1f59294abe86b Binary files /dev/null and b/docs/en/docs/img/sponsors/mobbai-banner.png differ diff --git a/docs/en/docs/img/sponsors/mobbai.png b/docs/en/docs/img/sponsors/mobbai.png new file mode 100644 index 0000000000000..b519fd885770c Binary files /dev/null and b/docs/en/docs/img/sponsors/mobbai.png differ diff --git a/docs/en/docs/img/sponsors/mongodb-banner.png b/docs/en/docs/img/sponsors/mongodb-banner.png new file mode 100755 index 0000000000000..25bc85eaae908 Binary files /dev/null and b/docs/en/docs/img/sponsors/mongodb-banner.png differ diff --git a/docs/en/docs/img/sponsors/mongodb.png b/docs/en/docs/img/sponsors/mongodb.png new file mode 100755 index 0000000000000..113ca478582b2 Binary files /dev/null and b/docs/en/docs/img/sponsors/mongodb.png differ diff --git a/docs/en/docs/img/sponsors/permit.png b/docs/en/docs/img/sponsors/permit.png new file mode 100644 index 0000000000000..4f07f22e27326 Binary files /dev/null and b/docs/en/docs/img/sponsors/permit.png differ diff --git a/docs/en/docs/img/sponsors/platform-sh-banner.png b/docs/en/docs/img/sponsors/platform-sh-banner.png new file mode 100644 index 0000000000000..f9f4580fac519 Binary files /dev/null and b/docs/en/docs/img/sponsors/platform-sh-banner.png differ diff --git a/docs/en/docs/img/sponsors/platform-sh.png b/docs/en/docs/img/sponsors/platform-sh.png new file mode 100644 index 0000000000000..fb4e07becdb89 Binary files /dev/null and b/docs/en/docs/img/sponsors/platform-sh.png differ diff --git a/docs/en/docs/img/sponsors/porter-banner.png b/docs/en/docs/img/sponsors/porter-banner.png new file mode 100755 index 0000000000000..fa2e741c0cbb3 Binary files /dev/null and b/docs/en/docs/img/sponsors/porter-banner.png differ diff --git a/docs/en/docs/img/sponsors/porter.png b/docs/en/docs/img/sponsors/porter.png new file mode 100755 index 0000000000000..582a15156470b Binary files /dev/null and b/docs/en/docs/img/sponsors/porter.png differ diff --git a/docs/en/docs/img/sponsors/powens.png b/docs/en/docs/img/sponsors/powens.png new file mode 100644 index 0000000000000..07fc6fa37f9c1 Binary files /dev/null and b/docs/en/docs/img/sponsors/powens.png differ diff --git a/docs/en/docs/img/sponsors/propelauth-banner.png b/docs/en/docs/img/sponsors/propelauth-banner.png new file mode 100644 index 0000000000000..7a1bb2580395a Binary files /dev/null and b/docs/en/docs/img/sponsors/propelauth-banner.png differ diff --git a/docs/en/docs/img/sponsors/propelauth.png b/docs/en/docs/img/sponsors/propelauth.png new file mode 100644 index 0000000000000..8234d631f6b67 Binary files /dev/null and b/docs/en/docs/img/sponsors/propelauth.png differ diff --git a/docs/en/docs/img/sponsors/railway-banner.png b/docs/en/docs/img/sponsors/railway-banner.png new file mode 100644 index 0000000000000..f6146a7c1fc50 Binary files /dev/null and b/docs/en/docs/img/sponsors/railway-banner.png differ diff --git a/docs/en/docs/img/sponsors/railway.png b/docs/en/docs/img/sponsors/railway.png new file mode 100644 index 0000000000000..dc6ccacc4a867 Binary files /dev/null and b/docs/en/docs/img/sponsors/railway.png differ diff --git a/docs/en/docs/img/sponsors/rapidproxy.png b/docs/en/docs/img/sponsors/rapidproxy.png new file mode 100644 index 0000000000000..efc2ba7d3b37e Binary files /dev/null and b/docs/en/docs/img/sponsors/rapidproxy.png differ diff --git a/docs/en/docs/img/sponsors/reflex-banner.png b/docs/en/docs/img/sponsors/reflex-banner.png new file mode 100644 index 0000000000000..3095c3a7b4090 Binary files /dev/null and b/docs/en/docs/img/sponsors/reflex-banner.png differ diff --git a/docs/en/docs/img/sponsors/reflex.png b/docs/en/docs/img/sponsors/reflex.png new file mode 100644 index 0000000000000..59c46a1104140 Binary files /dev/null and b/docs/en/docs/img/sponsors/reflex.png differ diff --git a/docs/en/docs/img/sponsors/render-banner.svg b/docs/en/docs/img/sponsors/render-banner.svg new file mode 100644 index 0000000000000..b8b1ed2e9b6f3 --- /dev/null +++ b/docs/en/docs/img/sponsors/render-banner.svg @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/en/docs/img/sponsors/render.svg b/docs/en/docs/img/sponsors/render.svg new file mode 100644 index 0000000000000..4a830482da88d --- /dev/null +++ b/docs/en/docs/img/sponsors/render.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/en/docs/img/sponsors/requestly.png b/docs/en/docs/img/sponsors/requestly.png new file mode 100644 index 0000000000000..a167aa017441d Binary files /dev/null and b/docs/en/docs/img/sponsors/requestly.png differ diff --git a/docs/en/docs/img/sponsors/scalar-banner.svg b/docs/en/docs/img/sponsors/scalar-banner.svg new file mode 100644 index 0000000000000..bab74e2d7c0e3 --- /dev/null +++ b/docs/en/docs/img/sponsors/scalar-banner.svg @@ -0,0 +1 @@ + diff --git a/docs/en/docs/img/sponsors/scalar.svg b/docs/en/docs/img/sponsors/scalar.svg new file mode 100644 index 0000000000000..174c57ee23c3e --- /dev/null +++ b/docs/en/docs/img/sponsors/scalar.svg @@ -0,0 +1 @@ + diff --git a/docs/en/docs/img/sponsors/serpapi-banner.png b/docs/en/docs/img/sponsors/serpapi-banner.png new file mode 100644 index 0000000000000..3c3fd629eb08f Binary files /dev/null and b/docs/en/docs/img/sponsors/serpapi-banner.png differ diff --git a/docs/en/docs/img/sponsors/serpapi.png b/docs/en/docs/img/sponsors/serpapi.png new file mode 100644 index 0000000000000..d7258ef70a4f3 Binary files /dev/null and b/docs/en/docs/img/sponsors/serpapi.png differ diff --git a/docs/en/docs/img/sponsors/speakeasy.png b/docs/en/docs/img/sponsors/speakeasy.png new file mode 100644 index 0000000000000..7bb9c3a18e1ef Binary files /dev/null and b/docs/en/docs/img/sponsors/speakeasy.png differ diff --git a/docs/en/docs/img/sponsors/stainless.png b/docs/en/docs/img/sponsors/stainless.png new file mode 100644 index 0000000000000..0f99c1d32c644 Binary files /dev/null and b/docs/en/docs/img/sponsors/stainless.png differ diff --git a/docs/en/docs/img/sponsors/striveworks-banner.png b/docs/en/docs/img/sponsors/striveworks-banner.png new file mode 100644 index 0000000000000..5206744b7a6e4 Binary files /dev/null and b/docs/en/docs/img/sponsors/striveworks-banner.png differ diff --git a/docs/en/docs/img/sponsors/striveworks.png b/docs/en/docs/img/sponsors/striveworks.png new file mode 100644 index 0000000000000..435ac536c14ea Binary files /dev/null and b/docs/en/docs/img/sponsors/striveworks.png differ diff --git a/docs/en/docs/img/sponsors/striveworks2.png b/docs/en/docs/img/sponsors/striveworks2.png new file mode 100644 index 0000000000000..bed9cb0a773a4 Binary files /dev/null and b/docs/en/docs/img/sponsors/striveworks2.png differ diff --git a/docs/en/docs/img/sponsors/subtotal-banner.svg b/docs/en/docs/img/sponsors/subtotal-banner.svg new file mode 100644 index 0000000000000..3d6c98dfc6878 --- /dev/null +++ b/docs/en/docs/img/sponsors/subtotal-banner.svg @@ -0,0 +1,133 @@ + + + + + sponsorship-banner + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/en/docs/img/sponsors/subtotal.svg b/docs/en/docs/img/sponsors/subtotal.svg new file mode 100644 index 0000000000000..b944c1b2c3525 --- /dev/null +++ b/docs/en/docs/img/sponsors/subtotal.svg @@ -0,0 +1,31 @@ + + + sponsorship-badge + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/en/docs/img/sponsors/svix.svg b/docs/en/docs/img/sponsors/svix.svg new file mode 100644 index 0000000000000..845a860a22901 --- /dev/null +++ b/docs/en/docs/img/sponsors/svix.svg @@ -0,0 +1,178 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/en/docs/img/sponsors/talkpython-v2.jpg b/docs/en/docs/img/sponsors/talkpython-v2.jpg new file mode 100644 index 0000000000000..adb0152489fa8 Binary files /dev/null and b/docs/en/docs/img/sponsors/talkpython-v2.jpg differ diff --git a/docs/en/docs/img/sponsors/talkpython.png b/docs/en/docs/img/sponsors/talkpython.png new file mode 100644 index 0000000000000..922d822c334fb Binary files /dev/null and b/docs/en/docs/img/sponsors/talkpython.png differ diff --git a/docs/en/docs/img/sponsors/talordata.png b/docs/en/docs/img/sponsors/talordata.png new file mode 100644 index 0000000000000..53906ee6e8e84 Binary files /dev/null and b/docs/en/docs/img/sponsors/talordata.png differ diff --git a/docs/en/docs/img/sponsors/testdriven.svg b/docs/en/docs/img/sponsors/testdriven.svg new file mode 100644 index 0000000000000..6ba2daa3b9d4d --- /dev/null +++ b/docs/en/docs/img/sponsors/testdriven.svg @@ -0,0 +1 @@ + diff --git a/docs/en/docs/img/sponsors/testmu.png b/docs/en/docs/img/sponsors/testmu.png new file mode 100644 index 0000000000000..5603b04faed5e Binary files /dev/null and b/docs/en/docs/img/sponsors/testmu.png differ diff --git a/docs/en/docs/img/sponsors/tutorcruncher.png b/docs/en/docs/img/sponsors/tutorcruncher.png new file mode 100644 index 0000000000000..aae58b2f5e78d Binary files /dev/null and b/docs/en/docs/img/sponsors/tutorcruncher.png differ diff --git a/docs/en/docs/img/sponsors/vimso.png b/docs/en/docs/img/sponsors/vimso.png new file mode 100644 index 0000000000000..d20791760768a Binary files /dev/null and b/docs/en/docs/img/sponsors/vimso.png differ diff --git a/docs/en/docs/img/sponsors/wetransfer.svg b/docs/en/docs/img/sponsors/wetransfer.svg new file mode 100644 index 0000000000000..793d043bade27 --- /dev/null +++ b/docs/en/docs/img/sponsors/wetransfer.svg @@ -0,0 +1,118 @@ + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + We deal in big ideas. You in? + + + + + + + + + + + + + + + + diff --git a/docs/en/docs/img/sponsors/zuplo-banner.png b/docs/en/docs/img/sponsors/zuplo-banner.png new file mode 100644 index 0000000000000..a730f2cf2d339 Binary files /dev/null and b/docs/en/docs/img/sponsors/zuplo-banner.png differ diff --git a/docs/en/docs/img/sponsors/zuplo.png b/docs/en/docs/img/sponsors/zuplo.png new file mode 100644 index 0000000000000..6a4ed233e9edc Binary files /dev/null and b/docs/en/docs/img/sponsors/zuplo.png differ diff --git a/docs/en/docs/img/tutorial/additional-responses/image01.png b/docs/en/docs/img/tutorial/additional-responses/image01.png new file mode 100644 index 0000000000000..c348d07cbd305 Binary files /dev/null and b/docs/en/docs/img/tutorial/additional-responses/image01.png differ diff --git a/docs/img/tutorial/async-sql-databases/image01.png b/docs/en/docs/img/tutorial/async-sql-databases/image01.png similarity index 100% rename from docs/img/tutorial/async-sql-databases/image01.png rename to docs/en/docs/img/tutorial/async-sql-databases/image01.png diff --git a/docs/en/docs/img/tutorial/behind-a-proxy/image01.png b/docs/en/docs/img/tutorial/behind-a-proxy/image01.png new file mode 100644 index 0000000000000..8012031401c83 Binary files /dev/null and b/docs/en/docs/img/tutorial/behind-a-proxy/image01.png differ diff --git a/docs/en/docs/img/tutorial/behind-a-proxy/image02.png b/docs/en/docs/img/tutorial/behind-a-proxy/image02.png new file mode 100644 index 0000000000000..95c207fcf86b8 Binary files /dev/null and b/docs/en/docs/img/tutorial/behind-a-proxy/image02.png differ diff --git a/docs/en/docs/img/tutorial/behind-a-proxy/image03.png b/docs/en/docs/img/tutorial/behind-a-proxy/image03.png new file mode 100644 index 0000000000000..278bd07c8ea1f Binary files /dev/null and b/docs/en/docs/img/tutorial/behind-a-proxy/image03.png differ diff --git a/docs/en/docs/img/tutorial/bigger-applications/image01.png b/docs/en/docs/img/tutorial/bigger-applications/image01.png new file mode 100644 index 0000000000000..faba6628e765a Binary files /dev/null and b/docs/en/docs/img/tutorial/bigger-applications/image01.png differ diff --git a/docs/en/docs/img/tutorial/bigger-applications/package.drawio.svg b/docs/en/docs/img/tutorial/bigger-applications/package.drawio.svg new file mode 100644 index 0000000000000..7e28f4a684615 --- /dev/null +++ b/docs/en/docs/img/tutorial/bigger-applications/package.drawio.svg @@ -0,0 +1,420 @@ + + + + + + + + + + + + + + + + +
+
+
+ + Package app +
+ app/__init__.py +
+
+
+
+
+ + Package app... + +
+
+
+ + + + + + + +
+
+
+ + + Module app.main + +
+ + app/main.py + +
+
+
+
+
+ + Module app.main... + +
+
+
+ + + + + + + +
+
+
+ + + Module app.dependencies + +
+ + app/dependencies.py + +
+
+
+
+
+ + Module app.dependencies... + +
+
+
+ + + + + + + + + + +
+
+
+ + + Subpackage app.internal +
+
+ + app/internal/__init__.py + +
+ +
+
+
+
+
+
+ + Subpackage app.internal... + +
+
+
+ + + + + + + +
+
+
+ + + Module app.internal.admin + +
+ + app/internal/admin.py + +
+
+
+
+
+ + Module app.internal.admin... + +
+
+
+ + + + + + + + + + +
+
+
+ + + Subpackage app.routers +
+ app/routers/__init__.py +
+
+
+
+
+
+
+ + Subpackage app.routers... + +
+
+
+ + + + + + + +
+
+
+ + + Module app.routers.items + +
+ + app/routers/items.py + +
+
+
+
+
+ + Module app.routers.items... + +
+
+
+ + + + + + + +
+
+
+ + + Module app.routers.users + +
+ + app/routers/users.py + +
+
+
+
+
+ + Module app.routers.users... + +
+
+
+
+ + + + + Text is not SVG - cannot display + + + +
diff --git a/docs/img/tutorial/body-schema/image01.png b/docs/en/docs/img/tutorial/body-fields/image01.png similarity index 100% rename from docs/img/tutorial/body-schema/image01.png rename to docs/en/docs/img/tutorial/body-fields/image01.png diff --git a/docs/en/docs/img/tutorial/body-fields/image02.png b/docs/en/docs/img/tutorial/body-fields/image02.png new file mode 100644 index 0000000000000..f307bb8ecd30d Binary files /dev/null and b/docs/en/docs/img/tutorial/body-fields/image02.png differ diff --git a/docs/en/docs/img/tutorial/body-nested-models/image01.png b/docs/en/docs/img/tutorial/body-nested-models/image01.png new file mode 100644 index 0000000000000..1f7e07cfef9b0 Binary files /dev/null and b/docs/en/docs/img/tutorial/body-nested-models/image01.png differ diff --git a/docs/img/tutorial/body/image01.png b/docs/en/docs/img/tutorial/body/image01.png similarity index 100% rename from docs/img/tutorial/body/image01.png rename to docs/en/docs/img/tutorial/body/image01.png diff --git a/docs/img/tutorial/body/image02.png b/docs/en/docs/img/tutorial/body/image02.png similarity index 100% rename from docs/img/tutorial/body/image02.png rename to docs/en/docs/img/tutorial/body/image02.png diff --git a/docs/img/tutorial/body/image03.png b/docs/en/docs/img/tutorial/body/image03.png similarity index 100% rename from docs/img/tutorial/body/image03.png rename to docs/en/docs/img/tutorial/body/image03.png diff --git a/docs/img/tutorial/body/image04.png b/docs/en/docs/img/tutorial/body/image04.png similarity index 100% rename from docs/img/tutorial/body/image04.png rename to docs/en/docs/img/tutorial/body/image04.png diff --git a/docs/img/tutorial/body/image05.png b/docs/en/docs/img/tutorial/body/image05.png similarity index 100% rename from docs/img/tutorial/body/image05.png rename to docs/en/docs/img/tutorial/body/image05.png diff --git a/docs/en/docs/img/tutorial/cookie-param-models/image01.png b/docs/en/docs/img/tutorial/cookie-param-models/image01.png new file mode 100644 index 0000000000000..85c370f80a42e Binary files /dev/null and b/docs/en/docs/img/tutorial/cookie-param-models/image01.png differ diff --git a/docs/img/tutorial/custom-response/image01.png b/docs/en/docs/img/tutorial/custom-response/image01.png similarity index 100% rename from docs/img/tutorial/custom-response/image01.png rename to docs/en/docs/img/tutorial/custom-response/image01.png diff --git a/docs/en/docs/img/tutorial/dataclasses/image01.png b/docs/en/docs/img/tutorial/dataclasses/image01.png new file mode 100644 index 0000000000000..7815f40adf065 Binary files /dev/null and b/docs/en/docs/img/tutorial/dataclasses/image01.png differ diff --git a/docs/img/tutorial/debugging/image01.png b/docs/en/docs/img/tutorial/debugging/image01.png similarity index 100% rename from docs/img/tutorial/debugging/image01.png rename to docs/en/docs/img/tutorial/debugging/image01.png diff --git a/docs/en/docs/img/tutorial/debugging/image02.png b/docs/en/docs/img/tutorial/debugging/image02.png new file mode 100644 index 0000000000000..8394f50e2d12d Binary files /dev/null and b/docs/en/docs/img/tutorial/debugging/image02.png differ diff --git a/docs/img/tutorial/dependencies/image01.png b/docs/en/docs/img/tutorial/dependencies/image01.png similarity index 100% rename from docs/img/tutorial/dependencies/image01.png rename to docs/en/docs/img/tutorial/dependencies/image01.png diff --git a/docs/img/tutorial/dependencies/image02.png b/docs/en/docs/img/tutorial/dependencies/image02.png similarity index 100% rename from docs/img/tutorial/dependencies/image02.png rename to docs/en/docs/img/tutorial/dependencies/image02.png diff --git a/docs/img/tutorial/extending-openapi/image01.png b/docs/en/docs/img/tutorial/extending-openapi/image01.png similarity index 100% rename from docs/img/tutorial/extending-openapi/image01.png rename to docs/en/docs/img/tutorial/extending-openapi/image01.png diff --git a/docs/en/docs/img/tutorial/extending-openapi/image02.png b/docs/en/docs/img/tutorial/extending-openapi/image02.png new file mode 100644 index 0000000000000..91453fb56f687 Binary files /dev/null and b/docs/en/docs/img/tutorial/extending-openapi/image02.png differ diff --git a/docs/en/docs/img/tutorial/extending-openapi/image03.png b/docs/en/docs/img/tutorial/extending-openapi/image03.png new file mode 100644 index 0000000000000..e45a77d519071 Binary files /dev/null and b/docs/en/docs/img/tutorial/extending-openapi/image03.png differ diff --git a/docs/en/docs/img/tutorial/extending-openapi/image04.png b/docs/en/docs/img/tutorial/extending-openapi/image04.png new file mode 100644 index 0000000000000..394d2bb431ab5 Binary files /dev/null and b/docs/en/docs/img/tutorial/extending-openapi/image04.png differ diff --git a/docs/en/docs/img/tutorial/generate-clients/image01.png b/docs/en/docs/img/tutorial/generate-clients/image01.png new file mode 100644 index 0000000000000..f23d57773c8f4 Binary files /dev/null and b/docs/en/docs/img/tutorial/generate-clients/image01.png differ diff --git a/docs/en/docs/img/tutorial/generate-clients/image02.png b/docs/en/docs/img/tutorial/generate-clients/image02.png new file mode 100644 index 0000000000000..f991352eb3199 Binary files /dev/null and b/docs/en/docs/img/tutorial/generate-clients/image02.png differ diff --git a/docs/en/docs/img/tutorial/generate-clients/image03.png b/docs/en/docs/img/tutorial/generate-clients/image03.png new file mode 100644 index 0000000000000..e2514b0481a81 Binary files /dev/null and b/docs/en/docs/img/tutorial/generate-clients/image03.png differ diff --git a/docs/en/docs/img/tutorial/generate-clients/image04.png b/docs/en/docs/img/tutorial/generate-clients/image04.png new file mode 100644 index 0000000000000..777a695bbb1e3 Binary files /dev/null and b/docs/en/docs/img/tutorial/generate-clients/image04.png differ diff --git a/docs/en/docs/img/tutorial/generate-clients/image05.png b/docs/en/docs/img/tutorial/generate-clients/image05.png new file mode 100644 index 0000000000000..e1e53179dcc2b Binary files /dev/null and b/docs/en/docs/img/tutorial/generate-clients/image05.png differ diff --git a/docs/en/docs/img/tutorial/generate-clients/image06.png b/docs/en/docs/img/tutorial/generate-clients/image06.png new file mode 100644 index 0000000000000..0e9a100ea4e8b Binary files /dev/null and b/docs/en/docs/img/tutorial/generate-clients/image06.png differ diff --git a/docs/en/docs/img/tutorial/generate-clients/image07.png b/docs/en/docs/img/tutorial/generate-clients/image07.png new file mode 100644 index 0000000000000..27884960fea7f Binary files /dev/null and b/docs/en/docs/img/tutorial/generate-clients/image07.png differ diff --git a/docs/en/docs/img/tutorial/generate-clients/image08.png b/docs/en/docs/img/tutorial/generate-clients/image08.png new file mode 100644 index 0000000000000..509fbd34079f0 Binary files /dev/null and b/docs/en/docs/img/tutorial/generate-clients/image08.png differ diff --git a/docs/img/tutorial/graphql/image01.png b/docs/en/docs/img/tutorial/graphql/image01.png similarity index 100% rename from docs/img/tutorial/graphql/image01.png rename to docs/en/docs/img/tutorial/graphql/image01.png diff --git a/docs/en/docs/img/tutorial/header-param-models/image01.png b/docs/en/docs/img/tutorial/header-param-models/image01.png new file mode 100644 index 0000000000000..849dea3d8b6fd Binary files /dev/null and b/docs/en/docs/img/tutorial/header-param-models/image01.png differ diff --git a/docs/en/docs/img/tutorial/json-base64-bytes/image01.png b/docs/en/docs/img/tutorial/json-base64-bytes/image01.png new file mode 100644 index 0000000000000..996732b7499a9 Binary files /dev/null and b/docs/en/docs/img/tutorial/json-base64-bytes/image01.png differ diff --git a/docs/en/docs/img/tutorial/metadata/image01.png b/docs/en/docs/img/tutorial/metadata/image01.png new file mode 100644 index 0000000000000..4146a8607b5b4 Binary files /dev/null and b/docs/en/docs/img/tutorial/metadata/image01.png differ diff --git a/docs/en/docs/img/tutorial/metadata/image02.png b/docs/en/docs/img/tutorial/metadata/image02.png new file mode 100644 index 0000000000000..7f3ab0a10dc51 Binary files /dev/null and b/docs/en/docs/img/tutorial/metadata/image02.png differ diff --git a/docs/en/docs/img/tutorial/openapi-callbacks/image01.png b/docs/en/docs/img/tutorial/openapi-callbacks/image01.png new file mode 100644 index 0000000000000..45e6366ab939d Binary files /dev/null and b/docs/en/docs/img/tutorial/openapi-callbacks/image01.png differ diff --git a/docs/en/docs/img/tutorial/openapi-webhooks/image01.png b/docs/en/docs/img/tutorial/openapi-webhooks/image01.png new file mode 100644 index 0000000000000..25ced48186d83 Binary files /dev/null and b/docs/en/docs/img/tutorial/openapi-webhooks/image01.png differ diff --git a/docs/en/docs/img/tutorial/path-operation-advanced-configuration/image01.png b/docs/en/docs/img/tutorial/path-operation-advanced-configuration/image01.png new file mode 100644 index 0000000000000..554e7c45664e4 Binary files /dev/null and b/docs/en/docs/img/tutorial/path-operation-advanced-configuration/image01.png differ diff --git a/docs/img/tutorial/path-operation-configuration/image01.png b/docs/en/docs/img/tutorial/path-operation-configuration/image01.png similarity index 100% rename from docs/img/tutorial/path-operation-configuration/image01.png rename to docs/en/docs/img/tutorial/path-operation-configuration/image01.png diff --git a/docs/img/tutorial/path-operation-configuration/image02.png b/docs/en/docs/img/tutorial/path-operation-configuration/image02.png similarity index 100% rename from docs/img/tutorial/path-operation-configuration/image02.png rename to docs/en/docs/img/tutorial/path-operation-configuration/image02.png diff --git a/docs/img/tutorial/path-operation-configuration/image03.png b/docs/en/docs/img/tutorial/path-operation-configuration/image03.png similarity index 100% rename from docs/img/tutorial/path-operation-configuration/image03.png rename to docs/en/docs/img/tutorial/path-operation-configuration/image03.png diff --git a/docs/img/tutorial/path-operation-configuration/image04.png b/docs/en/docs/img/tutorial/path-operation-configuration/image04.png similarity index 100% rename from docs/img/tutorial/path-operation-configuration/image04.png rename to docs/en/docs/img/tutorial/path-operation-configuration/image04.png diff --git a/docs/img/tutorial/path-operation-configuration/image05.png b/docs/en/docs/img/tutorial/path-operation-configuration/image05.png similarity index 100% rename from docs/img/tutorial/path-operation-configuration/image05.png rename to docs/en/docs/img/tutorial/path-operation-configuration/image05.png diff --git a/docs/img/tutorial/path-params/image01.png b/docs/en/docs/img/tutorial/path-params/image01.png similarity index 100% rename from docs/img/tutorial/path-params/image01.png rename to docs/en/docs/img/tutorial/path-params/image01.png diff --git a/docs/img/tutorial/path-params/image02.png b/docs/en/docs/img/tutorial/path-params/image02.png similarity index 100% rename from docs/img/tutorial/path-params/image02.png rename to docs/en/docs/img/tutorial/path-params/image02.png diff --git a/docs/en/docs/img/tutorial/path-params/image03.png b/docs/en/docs/img/tutorial/path-params/image03.png new file mode 100644 index 0000000000000..080e9e67dcb3d Binary files /dev/null and b/docs/en/docs/img/tutorial/path-params/image03.png differ diff --git a/docs/en/docs/img/tutorial/query-param-models/image01.png b/docs/en/docs/img/tutorial/query-param-models/image01.png new file mode 100644 index 0000000000000..e7a61b61fb4f6 Binary files /dev/null and b/docs/en/docs/img/tutorial/query-param-models/image01.png differ diff --git a/docs/img/tutorial/query-params-str-validations/image01.png b/docs/en/docs/img/tutorial/query-params-str-validations/image01.png similarity index 100% rename from docs/img/tutorial/query-params-str-validations/image01.png rename to docs/en/docs/img/tutorial/query-params-str-validations/image01.png diff --git a/docs/img/tutorial/query-params-str-validations/image02.png b/docs/en/docs/img/tutorial/query-params-str-validations/image02.png similarity index 100% rename from docs/img/tutorial/query-params-str-validations/image02.png rename to docs/en/docs/img/tutorial/query-params-str-validations/image02.png diff --git a/docs/en/docs/img/tutorial/request-form-models/image01.png b/docs/en/docs/img/tutorial/request-form-models/image01.png new file mode 100644 index 0000000000000..3fe32c03d589e Binary files /dev/null and b/docs/en/docs/img/tutorial/request-form-models/image01.png differ diff --git a/docs/img/tutorial/response-model/image01.png b/docs/en/docs/img/tutorial/response-model/image01.png similarity index 100% rename from docs/img/tutorial/response-model/image01.png rename to docs/en/docs/img/tutorial/response-model/image01.png diff --git a/docs/img/tutorial/response-model/image02.png b/docs/en/docs/img/tutorial/response-model/image02.png similarity index 100% rename from docs/img/tutorial/response-model/image02.png rename to docs/en/docs/img/tutorial/response-model/image02.png diff --git a/docs/img/tutorial/response-status-code/image01.png b/docs/en/docs/img/tutorial/response-status-code/image01.png similarity index 100% rename from docs/img/tutorial/response-status-code/image01.png rename to docs/en/docs/img/tutorial/response-status-code/image01.png diff --git a/docs/en/docs/img/tutorial/response-status-code/image02.png b/docs/en/docs/img/tutorial/response-status-code/image02.png new file mode 100644 index 0000000000000..44a29813eec57 Binary files /dev/null and b/docs/en/docs/img/tutorial/response-status-code/image02.png differ diff --git a/docs/img/tutorial/security/image01.png b/docs/en/docs/img/tutorial/security/image01.png similarity index 100% rename from docs/img/tutorial/security/image01.png rename to docs/en/docs/img/tutorial/security/image01.png diff --git a/docs/en/docs/img/tutorial/security/image02.png b/docs/en/docs/img/tutorial/security/image02.png new file mode 100644 index 0000000000000..a437ac0e710f5 Binary files /dev/null and b/docs/en/docs/img/tutorial/security/image02.png differ diff --git a/docs/img/tutorial/security/image03.png b/docs/en/docs/img/tutorial/security/image03.png similarity index 100% rename from docs/img/tutorial/security/image03.png rename to docs/en/docs/img/tutorial/security/image03.png diff --git a/docs/en/docs/img/tutorial/security/image04.png b/docs/en/docs/img/tutorial/security/image04.png new file mode 100644 index 0000000000000..231c53d2ef1e3 Binary files /dev/null and b/docs/en/docs/img/tutorial/security/image04.png differ diff --git a/docs/en/docs/img/tutorial/security/image05.png b/docs/en/docs/img/tutorial/security/image05.png new file mode 100644 index 0000000000000..cd4525f5717f6 Binary files /dev/null and b/docs/en/docs/img/tutorial/security/image05.png differ diff --git a/docs/img/tutorial/security/image06.png b/docs/en/docs/img/tutorial/security/image06.png similarity index 100% rename from docs/img/tutorial/security/image06.png rename to docs/en/docs/img/tutorial/security/image06.png diff --git a/docs/img/tutorial/security/image07.png b/docs/en/docs/img/tutorial/security/image07.png similarity index 100% rename from docs/img/tutorial/security/image07.png rename to docs/en/docs/img/tutorial/security/image07.png diff --git a/docs/en/docs/img/tutorial/security/image08.png b/docs/en/docs/img/tutorial/security/image08.png new file mode 100644 index 0000000000000..5289afce28862 Binary files /dev/null and b/docs/en/docs/img/tutorial/security/image08.png differ diff --git a/docs/img/tutorial/security/image09.png b/docs/en/docs/img/tutorial/security/image09.png similarity index 100% rename from docs/img/tutorial/security/image09.png rename to docs/en/docs/img/tutorial/security/image09.png diff --git a/docs/img/tutorial/security/image10.png b/docs/en/docs/img/tutorial/security/image10.png similarity index 100% rename from docs/img/tutorial/security/image10.png rename to docs/en/docs/img/tutorial/security/image10.png diff --git a/docs/en/docs/img/tutorial/security/image11.png b/docs/en/docs/img/tutorial/security/image11.png new file mode 100644 index 0000000000000..278f049400fa4 Binary files /dev/null and b/docs/en/docs/img/tutorial/security/image11.png differ diff --git a/docs/img/tutorial/security/image12.png b/docs/en/docs/img/tutorial/security/image12.png similarity index 100% rename from docs/img/tutorial/security/image12.png rename to docs/en/docs/img/tutorial/security/image12.png diff --git a/docs/en/docs/img/tutorial/separate-openapi-schemas/image01.png b/docs/en/docs/img/tutorial/separate-openapi-schemas/image01.png new file mode 100644 index 0000000000000..aa085f88df45e Binary files /dev/null and b/docs/en/docs/img/tutorial/separate-openapi-schemas/image01.png differ diff --git a/docs/en/docs/img/tutorial/separate-openapi-schemas/image02.png b/docs/en/docs/img/tutorial/separate-openapi-schemas/image02.png new file mode 100644 index 0000000000000..672ef1d2b71df Binary files /dev/null and b/docs/en/docs/img/tutorial/separate-openapi-schemas/image02.png differ diff --git a/docs/en/docs/img/tutorial/separate-openapi-schemas/image03.png b/docs/en/docs/img/tutorial/separate-openapi-schemas/image03.png new file mode 100644 index 0000000000000..81340fbece942 Binary files /dev/null and b/docs/en/docs/img/tutorial/separate-openapi-schemas/image03.png differ diff --git a/docs/en/docs/img/tutorial/separate-openapi-schemas/image04.png b/docs/en/docs/img/tutorial/separate-openapi-schemas/image04.png new file mode 100644 index 0000000000000..fc2302aa77ce2 Binary files /dev/null and b/docs/en/docs/img/tutorial/separate-openapi-schemas/image04.png differ diff --git a/docs/en/docs/img/tutorial/separate-openapi-schemas/image05.png b/docs/en/docs/img/tutorial/separate-openapi-schemas/image05.png new file mode 100644 index 0000000000000..674dd0b2e2730 Binary files /dev/null and b/docs/en/docs/img/tutorial/separate-openapi-schemas/image05.png differ diff --git a/docs/en/docs/img/tutorial/sql-databases/image01.png b/docs/en/docs/img/tutorial/sql-databases/image01.png new file mode 100644 index 0000000000000..bfcdb57a0743c Binary files /dev/null and b/docs/en/docs/img/tutorial/sql-databases/image01.png differ diff --git a/docs/en/docs/img/tutorial/sql-databases/image02.png b/docs/en/docs/img/tutorial/sql-databases/image02.png new file mode 100644 index 0000000000000..7bcad83783af8 Binary files /dev/null and b/docs/en/docs/img/tutorial/sql-databases/image02.png differ diff --git a/docs/img/tutorial/sub-applications/image01.png b/docs/en/docs/img/tutorial/sub-applications/image01.png similarity index 100% rename from docs/img/tutorial/sub-applications/image01.png rename to docs/en/docs/img/tutorial/sub-applications/image01.png diff --git a/docs/img/tutorial/sub-applications/image02.png b/docs/en/docs/img/tutorial/sub-applications/image02.png similarity index 100% rename from docs/img/tutorial/sub-applications/image02.png rename to docs/en/docs/img/tutorial/sub-applications/image02.png diff --git a/docs/img/tutorial/websockets/image01.png b/docs/en/docs/img/tutorial/websockets/image01.png similarity index 100% rename from docs/img/tutorial/websockets/image01.png rename to docs/en/docs/img/tutorial/websockets/image01.png diff --git a/docs/img/tutorial/websockets/image02.png b/docs/en/docs/img/tutorial/websockets/image02.png similarity index 100% rename from docs/img/tutorial/websockets/image02.png rename to docs/en/docs/img/tutorial/websockets/image02.png diff --git a/docs/img/tutorial/websockets/image03.png b/docs/en/docs/img/tutorial/websockets/image03.png similarity index 100% rename from docs/img/tutorial/websockets/image03.png rename to docs/en/docs/img/tutorial/websockets/image03.png diff --git a/docs/img/tutorial/websockets/image04.png b/docs/en/docs/img/tutorial/websockets/image04.png similarity index 100% rename from docs/img/tutorial/websockets/image04.png rename to docs/en/docs/img/tutorial/websockets/image04.png diff --git a/docs/en/docs/img/tutorial/websockets/image05.png b/docs/en/docs/img/tutorial/websockets/image05.png new file mode 100644 index 0000000000000..00b0c52202b37 Binary files /dev/null and b/docs/en/docs/img/tutorial/websockets/image05.png differ diff --git a/docs/img/vscode-completion.png b/docs/en/docs/img/vscode-completion.png similarity index 100% rename from docs/img/vscode-completion.png rename to docs/en/docs/img/vscode-completion.png diff --git a/docs/en/docs/index.md b/docs/en/docs/index.md new file mode 100644 index 0000000000000..7baeaab2620ea --- /dev/null +++ b/docs/en/docs/index.md @@ -0,0 +1,585 @@ +--- +include_yaml: + sponsors: data/sponsors.yml +--- + +# FastAPI { #fastapi } + + + +

+ FastAPI +

+

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

+

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

+ +--- + +**Documentation**: [https://fastapi.tiangolo.com](https://fastapi.tiangolo.com) + +**Source Code**: [https://github.com/fastapi/fastapi](https://github.com/fastapi/fastapi) + +--- + +FastAPI is a modern, fast (high-performance), web framework for building APIs with Python based on standard Python type hints. + +The key features are: + +* **Fast**: Very high performance, on par with **NodeJS** and **Go** (thanks to Starlette and Pydantic). [One of the fastest Python frameworks available](#performance). +* **Fast to code**: Increase the speed to develop features by about 200% to 300%. * +* **Fewer bugs**: Reduce about 40% of human (developer) induced errors. * +* **Intuitive**: Great editor support. Completion everywhere. Less time debugging. +* **Easy**: Designed to be easy to use and learn. Less time reading docs. +* **Short**: Minimize code duplication. Multiple features from each parameter declaration. Fewer bugs. +* **Robust**: Get production-ready code. With automatic interactive documentation. +* **Standards-based**: Based on (and fully compatible with) the open standards for APIs: [OpenAPI](https://github.com/OAI/OpenAPI-Specification) (previously known as Swagger) and [JSON Schema](https://json-schema.org/). + +* estimation based on tests conducted by an internal development team, building production applications. + +## Sponsors { #sponsors } + + + +### Keystone Sponsor { #keystone-sponsor } + +
+{% for sponsor in sponsors.keystone -%} +{{ sponsor.title }} +{% endfor -%} +
+ +### Gold Sponsors { #gold-sponsors } + +
+{% for sponsor in sponsors.gold -%} +{{ sponsor.title }} +{% endfor -%} +
+ +### Silver Sponsors { #silver-sponsors } + +
+{% for sponsor in sponsors.silver -%} +{{ sponsor.title }} +{% endfor %} +
+ + + +[Other sponsors](https://fastapi.tiangolo.com/fastapi-people/#sponsors) + +## Opinions { #opinions } + + +
+
+ + + + +
+ +
+
"I'm using FastAPI a ton these days. I'm actually planning to use it for all of my team's ML services at Microsoft. Some of them are getting integrated into the core Windows product and some Office products."
+
— Kabir Khan, Microsoft (ref)
+
+ + + +
+ + +
+ +"_[...] I'm using **FastAPI** a ton these days. [...] I'm actually planning to use it for all of my team's **ML services at Microsoft**. Some of them are getting integrated into the core **Windows** product and some **Office** products._" + +
Kabir Khan - Microsoft (ref)
+ +--- + +"_We adopted the **FastAPI** library to spawn a **REST** server that can be queried to obtain **predictions**. [for Ludwig]_" + +
Piero Molino, Yaroslav Dudin, and Sai Sumanth Miryala - Uber (ref)
+ +--- + +"_**Netflix** is pleased to announce the open-source release of our **crisis management** orchestration framework: **Dispatch**! [built with **FastAPI**]_" + +
Kevin Glisson, Marc Vilanova, Forest Monsen - Netflix (ref)
+ +--- + +"_If anyone is looking to build a production Python API, I would highly recommend **FastAPI**. It is **beautifully designed**, **simple to use** and **highly scalable**, it has become a **key component** in our API first development strategy and is driving many automations and services such as our Virtual TAC Engineer._" + +
Deon Pillsbury - Cisco (ref)
+ +--- + +
+ +## FastAPI Conf { #fastapi-conf } + +[**FastAPI Conf '26**](https://fastapiconf.com) is happening on **October 28, 2026** in **Amsterdam, NL**. All about FastAPI, right from the source. 🎤 + +FastAPI Conf '26 - October 28, 2026 - Amsterdam, NL + +## FastAPI mini documentary { #fastapi-mini-documentary } + +There's a [FastAPI mini documentary](https://www.youtube.com/watch?v=mpR8ngthqiE) released at the end of 2025, you can watch it online: + +FastAPI Mini Documentary + +## **Typer**, the FastAPI of CLIs { #typer-the-fastapi-of-clis } + + + +If you are building a CLI app to be used in the terminal instead of a web API, check out [**Typer**](https://typer.tiangolo.com/). + +**Typer** is FastAPI's little sibling. And it's intended to be the **FastAPI of CLIs**. ⌨️ 🚀 + +## Requirements { #requirements } + +FastAPI stands on the shoulders of giants: + +* [Starlette](https://www.starlette.dev/) for the web parts. +* [Pydantic](https://docs.pydantic.dev/) for the data parts. + +## Installation { #installation } + +Create and activate a [virtual environment](https://fastapi.tiangolo.com/virtual-environments/) and then install FastAPI: + +
+ +```console +$ pip install "fastapi[standard]" + +---> 100% +``` + +
+ +**Note**: Make sure you put `"fastapi[standard]"` in quotes to ensure it works in all terminals. + +## Example { #example } + +### Create it { #create-it } + +Create a file `main.py` with: + +```Python +from fastapi import FastAPI + +app = FastAPI() + + +@app.get("/") +def read_root(): + return {"Hello": "World"} + + +@app.get("/items/{item_id}") +def read_item(item_id: int, q: str | None = None): + return {"item_id": item_id, "q": q} +``` + +
+Or use async def... + +If your code uses `async` / `await`, use `async def`: + +```Python hl_lines="7 12" +from fastapi import FastAPI + +app = FastAPI() + + +@app.get("/") +async def read_root(): + return {"Hello": "World"} + + +@app.get("/items/{item_id}") +async def read_item(item_id: int, q: str | None = None): + return {"item_id": item_id, "q": q} +``` + +**Note**: + +If you don't know, check the _"In a hurry?"_ section about [`async` and `await` in the docs](https://fastapi.tiangolo.com/async/#in-a-hurry). + +
+ +### Run it { #run-it } + +Run the server with: + +
+ +```console +$ fastapi dev + + ╭────────── FastAPI CLI - Development mode ───────────╮ + │ │ + │ Serving at: http://127.0.0.1:8000 │ + │ │ + │ API docs: http://127.0.0.1:8000/docs │ + │ │ + │ Running in development mode, for production use: │ + │ │ + │ fastapi run │ + │ │ + ╰─────────────────────────────────────────────────────╯ + +INFO: Will watch for changes in these directories: ['/home/user/code/awesomeapp'] +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +INFO: Started reloader process [2248755] using WatchFiles +INFO: Started server process [2248757] +INFO: Waiting for application startup. +INFO: Application startup complete. +``` + +
+ +
+About the command fastapi dev... + +The command `fastapi dev` reads your `main.py` file automatically, detects the **FastAPI** app in it, and starts a server using [Uvicorn](https://www.uvicorn.dev). + +By default, `fastapi dev` will start with auto-reload enabled for local development. + +You can read more about it in the [FastAPI CLI docs](https://fastapi.tiangolo.com/fastapi-cli/). + +
+ +### Check it { #check-it } + +Open your browser at [http://127.0.0.1:8000/items/5?q=somequery](http://127.0.0.1:8000/items/5?q=somequery). + +You will see the JSON response as: + +```JSON +{"item_id": 5, "q": "somequery"} +``` + +You already created an API that: + +* Receives HTTP requests in the _paths_ `/` and `/items/{item_id}`. +* Both _paths_ take `GET` operations (also known as HTTP _methods_). +* The _path_ `/items/{item_id}` has a _path parameter_ `item_id` that should be an `int`. +* The _path_ `/items/{item_id}` has an optional `str` _query parameter_ `q`. + +### Interactive API docs { #interactive-api-docs } + +Now go to [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs). + +You will see the automatic interactive API documentation (provided by [Swagger UI](https://github.com/swagger-api/swagger-ui)): + +![Swagger UI](https://fastapi.tiangolo.com/img/index/index-01-swagger-ui-simple.png) + +### Alternative API docs { #alternative-api-docs } + +And now, go to [http://127.0.0.1:8000/redoc](http://127.0.0.1:8000/redoc). + +You will see the alternative automatic documentation (provided by [ReDoc](https://github.com/Rebilly/ReDoc)): + +![ReDoc](https://fastapi.tiangolo.com/img/index/index-02-redoc-simple.png) + +## Example upgrade { #example-upgrade } + +Now modify the file `main.py` to receive a body from a `PUT` request. + +Declare the body using standard Python types, thanks to Pydantic. + +```Python hl_lines="2 7-10 23-25" +from fastapi import FastAPI +from pydantic import BaseModel + +app = FastAPI() + + +class Item(BaseModel): + name: str + price: float + is_offer: bool | None = None + + +@app.get("/") +def read_root(): + return {"Hello": "World"} + + +@app.get("/items/{item_id}") +def read_item(item_id: int, q: str | None = None): + return {"item_id": item_id, "q": q} + + +@app.put("/items/{item_id}") +def update_item(item_id: int, item: Item): + return {"item_name": item.name, "item_id": item_id} +``` + +The `fastapi dev` server should reload automatically. + +### Interactive API docs upgrade { #interactive-api-docs-upgrade } + +Now go to [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs). + +* The interactive API documentation will be automatically updated, including the new body: + +![Swagger UI](https://fastapi.tiangolo.com/img/index/index-03-swagger-02.png) + +* Click on the button "Try it out", it allows you to fill the parameters and directly interact with the API: + +![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-04-swagger-03.png) + +* Then click on the "Execute" button, the user interface will communicate with your API, send the parameters, get the results and show them on the screen: + +![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-05-swagger-04.png) + +### Alternative API docs upgrade { #alternative-api-docs-upgrade } + +And now, go to [http://127.0.0.1:8000/redoc](http://127.0.0.1:8000/redoc). + +* The alternative documentation will also reflect the new query parameter and body: + +![ReDoc](https://fastapi.tiangolo.com/img/index/index-06-redoc-02.png) + +### Recap { #recap } + +In summary, you declare **once** the types of parameters, body, etc. as function parameters. + +You do that with standard modern Python types. + +You don't have to learn a new syntax, the methods or classes of a specific library, etc. + +Just standard **Python**. + +For example, for an `int`: + +```Python +item_id: int +``` + +or for a more complex `Item` model: + +```Python +item: Item +``` + +...and with that single declaration you get: + +* Editor support, including: + * Completion. + * Type checks. +* Validation of data: + * Automatic and clear errors when the data is invalid. + * Validation even for deeply nested JSON objects. +* Conversion of input data: coming from the network to Python data and types. Reading from: + * JSON. + * Path parameters. + * Query parameters. + * Cookies. + * Headers. + * Forms. + * Files. +* Conversion of output data: converting from Python data and types to network data (as JSON): + * Convert Python types (`str`, `int`, `float`, `bool`, `list`, etc). + * `datetime` objects. + * `UUID` objects. + * Database models. + * ...and many more. +* Automatic interactive API documentation, including 2 alternative user interfaces: + * Swagger UI. + * ReDoc. + +--- + +Coming back to the previous code example, **FastAPI** will: + +* Validate that there is an `item_id` in the path for `GET` and `PUT` requests. +* Validate that the `item_id` is of type `int` for `GET` and `PUT` requests. + * If it is not, the client will see a useful, clear error. +* Check if there is an optional query parameter named `q` (as in `http://127.0.0.1:8000/items/foo?q=somequery`) for `GET` requests. + * As the `q` parameter is declared with `= None`, it is optional. + * Without the `None` it would be required (as is the body in the case with `PUT`). +* For `PUT` requests to `/items/{item_id}`, read the body as JSON: + * Check that it has a required attribute `name` that should be a `str`. + * Check that it has a required attribute `price` that has to be a `float`. + * Check that it has an optional attribute `is_offer`, that should be a `bool`, if present. + * All this would also work for deeply nested JSON objects. +* Convert from and to JSON automatically. +* Document everything with OpenAPI, that can be used by: + * Interactive documentation systems. + * Automatic client code generation systems, for many languages. +* Provide 2 interactive documentation web interfaces directly. + +--- + +We just scratched the surface, but you already get the idea of how it all works. + +Try changing the line with: + +```Python + return {"item_name": item.name, "item_id": item_id} +``` + +...from: + +```Python + ... "item_name": item.name ... +``` + +...to: + +```Python + ... "item_price": item.price ... +``` + +...and see how your editor will auto-complete the attributes and know their types: + +![editor support](https://fastapi.tiangolo.com/img/vscode-completion.png) + +For a more complete example including more features, see the Tutorial - User Guide. + +**Spoiler alert**: the tutorial - user guide includes: + +* Declaration of **parameters** from other different places such as: **headers**, **cookies**, **form fields** and **files**. +* How to set **validation constraints** such as `maximum_length` or `regex`. +* A very powerful and easy to use **Dependency Injection** system. +* Security and authentication, including support for **OAuth2** with **JWT tokens** and **HTTP Basic** auth. +* More advanced (but equally easy) techniques for declaring **deeply nested JSON models** (thanks to Pydantic). +* **GraphQL** integration with [Strawberry](https://strawberry.rocks) and other libraries. +* Many extra features (thanks to Starlette) such as: + * **WebSockets** + * extremely easy tests based on HTTPX and `pytest` + * **CORS** + * **Cookie Sessions** + * ...and more. + +### Deploy your app (optional) { #deploy-your-app-optional } + +You can optionally deploy your FastAPI app to [FastAPI Cloud](https://fastapicloud.com) with a single command. 🚀 + +
+ +```console +$ fastapi deploy + +Deploying to FastAPI Cloud... + +✅ Deployment successful! + +🐔 Ready the chicken! Your app is ready at https://myapp.fastapicloud.dev +``` + +
+ +The CLI will automatically detect your FastAPI application and deploy it to the cloud. If you are not logged in, your browser will open to complete the authentication process. + +That's it! Now you can access your app at that URL. ✨ + +#### About FastAPI Cloud { #about-fastapi-cloud } + +**[FastAPI Cloud](https://fastapicloud.com)** 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 { #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 [one of the fastest Python frameworks available](https://www.techempower.com/benchmarks/#section=test&runid=7464e520-0dc2-473d-bd34-dbdfd7e85911&hw=ph&test=query&l=zijzen-7), only below Starlette and Uvicorn themselves (used internally by FastAPI). (*) + +To understand more about it, see the section [Benchmarks](https://fastapi.tiangolo.com/benchmarks/). + +## Dependencies { #dependencies } + +FastAPI depends on Pydantic and Starlette. + +### `standard` Dependencies { #standard-dependencies } + +When you install FastAPI with `pip install "fastapi[standard]"` it comes with the `standard` group of optional dependencies: + +Used by Pydantic: + +* [`email-validator`](https://github.com/JoshData/python-email-validator) - for email validation. + +Used by Starlette: + +* [`httpx`](https://www.python-httpx.org) - Required if you want to use the `TestClient`. +* [`jinja2`](https://jinja.palletsprojects.com) - Required if you want to use the default template configuration. +* [`python-multipart`](https://github.com/Kludex/python-multipart) - Required if you want to support form "parsing", with `request.form()`. + +Used by FastAPI: + +* [`uvicorn`](https://www.uvicorn.dev) - for the server that loads and serves your application. This includes `uvicorn[standard]`, which includes some dependencies (e.g. `uvloop`) needed for high performance serving. +* `fastapi-cli[standard]` - to provide the `fastapi` command. + * This includes `fastapi-cloud-cli`, which allows you to deploy your FastAPI application to [FastAPI Cloud](https://fastapicloud.com). + +### Without `standard` Dependencies { #without-standard-dependencies } + +If you don't want to include the `standard` optional dependencies, you can install with `pip install fastapi` instead of `pip install "fastapi[standard]"`. + +### Without `fastapi-cloud-cli` { #without-fastapi-cloud-cli } + +If you want to install FastAPI with the standard dependencies but without the `fastapi-cloud-cli`, you can install with `pip install "fastapi[standard-no-fastapi-cloud-cli]"`. + +### Additional Optional Dependencies { #additional-optional-dependencies } + +There are some additional dependencies you might want to install. + +Additional optional Pydantic dependencies: + +* [`pydantic-settings`](https://docs.pydantic.dev/latest/usage/pydantic_settings/) - for settings management. +* [`pydantic-extra-types`](https://docs.pydantic.dev/latest/usage/types/extra_types/extra_types/) - for extra types to be used with Pydantic. + +Additional optional FastAPI dependencies: + +* [`orjson`](https://github.com/ijl/orjson) - Required if you want to use `ORJSONResponse`. +* [`ujson`](https://github.com/esnme/ultrajson) - Required if you want to use `UJSONResponse`. + +## License { #license } + +This project is licensed under the terms of the MIT license. diff --git a/docs/en/docs/js/custom.js b/docs/en/docs/js/custom.js new file mode 100644 index 0000000000000..a4db853f5cc61 --- /dev/null +++ b/docs/en/docs/js/custom.js @@ -0,0 +1,250 @@ +function setupTermynal() { + document.querySelectorAll(".use-termynal").forEach(node => { + node.style.display = "block"; + new Termynal(node, { + lineDelay: 500 + }); + }); + const progressLiteralStart = "---> 100%"; + const promptLiteralStart = "$ "; + const customPromptLiteralStart = "# "; + const termynalActivateClass = "termy"; + let termynals = []; + + function createTermynals() { + document + .querySelectorAll(`.${termynalActivateClass} .highlight code`) + .forEach(node => { + const text = node.textContent; + const lines = text.split("\n"); + const useLines = []; + let buffer = []; + function saveBuffer() { + if (buffer.length) { + let isBlankSpace = true; + buffer.forEach(line => { + if (line) { + isBlankSpace = false; + } + }); + dataValue = {}; + if (isBlankSpace) { + dataValue["delay"] = 0; + } + if (buffer[buffer.length - 1] === "") { + // A last single
won't have effect + // so put an additional one + buffer.push(""); + } + const bufferValue = buffer.join("
"); + dataValue["value"] = bufferValue; + useLines.push(dataValue); + buffer = []; + } + } + for (let line of lines) { + if (line === progressLiteralStart) { + saveBuffer(); + useLines.push({ + type: "progress" + }); + } else if (line.startsWith(promptLiteralStart)) { + saveBuffer(); + const value = line.replace(promptLiteralStart, "").trimEnd(); + useLines.push({ + type: "input", + value: value + }); + } else if (line.startsWith("// ")) { + saveBuffer(); + const value = "💬 " + line.replace("// ", "").trimEnd(); + useLines.push({ + value: value, + class: "termynal-comment", + delay: 0 + }); + } else if (line.startsWith(customPromptLiteralStart)) { + saveBuffer(); + const promptStart = line.indexOf(promptLiteralStart); + if (promptStart === -1) { + console.error("Custom prompt found but no end delimiter", line) + } + const prompt = line.slice(0, promptStart).replace(customPromptLiteralStart, "") + let value = line.slice(promptStart + promptLiteralStart.length); + useLines.push({ + type: "input", + value: value, + prompt: prompt + }); + } else { + buffer.push(line); + } + } + saveBuffer(); + const inputCommands = useLines + .filter(line => line.type === "input") + .map(line => line.value) + .join("\n"); + node.textContent = inputCommands; + const div = document.createElement("div"); + node.style.display = "none"; + node.after(div); + const termynal = new Termynal(div, { + lineData: useLines, + noInit: true, + lineDelay: 500 + }); + termynals.push(termynal); + }); + } + + function loadVisibleTermynals() { + termynals = termynals.filter(termynal => { + if (termynal.container.getBoundingClientRect().top - innerHeight <= 0) { + termynal.init(); + return false; + } + return true; + }); + } + window.addEventListener("scroll", loadVisibleTermynals); + createTermynals(); + loadVisibleTermynals(); +} + +function shuffle(array) { + var currentIndex = array.length, temporaryValue, randomIndex; + while (0 !== currentIndex) { + randomIndex = Math.floor(Math.random() * currentIndex); + currentIndex -= 1; + temporaryValue = array[currentIndex]; + array[currentIndex] = array[randomIndex]; + array[randomIndex] = temporaryValue; + } + return array; +} + +async function showRandomAnnouncement(groupId, timeInterval) { + const announceFastAPI = document.getElementById(groupId); + if (announceFastAPI) { + let children = [].slice.call(announceFastAPI.children); + children = shuffle(children) + let index = 0 + const announceRandom = () => { + children.forEach((el, i) => { el.style.display = "none" }); + children[index].style.display = "block" + index = (index + 1) % children.length + } + announceRandom() + setInterval(announceRandom, timeInterval + ) + } +} + +function handleSponsorImages() { + const announceRight = document.getElementById('announce-right'); + if(!announceRight) return; + + const sponsorImages = document.querySelectorAll('.sponsor-image'); + + const imagePromises = Array.from(sponsorImages).map(img => { + return new Promise((resolve, reject) => { + if (img.complete && img.naturalHeight !== 0) { + resolve(); + } else { + img.addEventListener('load', () => { + if (img.naturalHeight !== 0) { + resolve(); + } else { + reject(); + } + }); + img.addEventListener('error', reject); + } + }); + }); + + Promise.all(imagePromises) + .then(() => { + announceRight.style.display = 'block'; + showRandomAnnouncement('announce-right', 10000); + }) + .catch(() => { + // do nothing + }); +} + +function openLinksInNewTab() { + const siteUrl = document.querySelector("link[rel='canonical']")?.href + || window.location.origin; + const siteOrigin = new URL(siteUrl).origin; + document.querySelectorAll(".md-content a[href]").forEach(a => { + if (a.getAttribute("target") === "_self") return; + const href = a.getAttribute("href"); + if (!href) return; + try { + const url = new URL(href, window.location.href); + // Skip same-page anchor links (only the hash differs) + if (url.origin === window.location.origin + && url.pathname === window.location.pathname + && url.search === window.location.search) return; + if (!a.hasAttribute("target")) { + a.setAttribute("target", "_blank"); + a.setAttribute("rel", "noopener"); + } + if (url.origin !== siteOrigin) { + a.dataset.externalLink = ""; + } else { + a.dataset.internalLink = ""; + } + } catch (_) {} + }); +} + +function setupOpinionsTabs() { + const root = document.querySelector('.fastapi-opinions'); + if (!root) return; + const tabs = Array.from(root.querySelectorAll('[role="tab"]')); + const panels = Array.from(root.querySelectorAll('[role="tabpanel"]')); + if (!tabs.length) return; + + function activate(tab, focus) { + tabs.forEach(t => { + const selected = t === tab; + t.setAttribute('aria-selected', selected ? 'true' : 'false'); + t.setAttribute('tabindex', selected ? '0' : '-1'); + }); + const targetId = tab.getAttribute('aria-controls'); + panels.forEach(p => { + if (p.id === targetId) p.removeAttribute('hidden'); + else p.setAttribute('hidden', ''); + }); + if (focus) tab.focus(); + } + + tabs.forEach((tab, i) => { + tab.addEventListener('click', () => activate(tab, false)); + tab.addEventListener('keydown', (e) => { + let next = null; + if (e.key === 'ArrowRight') next = tabs[(i + 1) % tabs.length]; + else if (e.key === 'ArrowLeft') next = tabs[(i - 1 + tabs.length) % tabs.length]; + else if (e.key === 'Home') next = tabs[0]; + else if (e.key === 'End') next = tabs[tabs.length - 1]; + if (next) { + e.preventDefault(); + activate(next, true); + } + }); + }); +} + +async function main() { + setupTermynal(); + showRandomAnnouncement('announce-left', 5000) + handleSponsorImages(); + openLinksInNewTab(); + setupOpinionsTabs(); +} +document$.subscribe(() => { + main() +}) diff --git a/docs/en/docs/js/init_kapa_widget.js b/docs/en/docs/js/init_kapa_widget.js new file mode 100644 index 0000000000000..eaf123bf3f519 --- /dev/null +++ b/docs/en/docs/js/init_kapa_widget.js @@ -0,0 +1,29 @@ +document.addEventListener("DOMContentLoaded", function () { + var script = document.createElement("script"); + script.src = "https://widget.kapa.ai/kapa-widget.bundle.js"; + script.setAttribute("data-website-id", "91f47f27-b405-4299-bf5f-a1c0ec07b3cc"); + script.setAttribute("data-project-name", "FastAPI"); + script.setAttribute("data-project-color", "#009485"); + script.setAttribute("data-project-logo", "https://fastapi.tiangolo.com/img/favicon.png"); + script.setAttribute("data-bot-protection-mechanism", "hcaptcha"); + script.setAttribute("data-button-height", "3rem"); + script.setAttribute("data-button-width", "3rem"); + script.setAttribute("data-button-border-radius", "50%"); + script.setAttribute("data-button-padding", "0"); + script.setAttribute("data-button-image", "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 8V4H8'/%3E%3Crect width='16' height='12' x='4' y='8' rx='2'/%3E%3Cpath d='M2 14h2'/%3E%3Cpath d='M20 14h2'/%3E%3Cpath d='M15 13v2'/%3E%3Cpath d='M9 13v2'/%3E%3C/svg%3E"); + script.setAttribute("data-button-image-height", "20px"); + script.setAttribute("data-button-image-width", "20px"); + script.setAttribute("data-button-text", "Ask AI"); + script.setAttribute("data-button-text-font-size", "0.5rem"); + script.setAttribute("data-button-text-font-family", "Roboto, sans-serif"); + script.setAttribute("data-button-text-color", "#FFFFFF"); + script.setAttribute("data-modal-border-radius", "0.5rem"); + script.setAttribute("data-modal-header-bg-color", "#009485"); + script.setAttribute("data-modal-title", "FastAPI AI Assistant"); + script.setAttribute("data-modal-title-color", "#FFFFFF"); + script.setAttribute("data-modal-title-font-family", "Roboto, sans-serif"); + script.setAttribute("data-modal-example-questions", "How to define a route?,How to validate models?,How to handle responses?,How to deploy FastAPI?"); + script.setAttribute("data-modal-disclaimer", "AI-generated answers based on FastAPI [documentation](https://fastapi.tiangolo.com/) and [community discussions](https://github.com/fastapi/fastapi/discussions). Always verify important information."); + script.async = true; + document.head.appendChild(script); +}); diff --git a/docs/en/docs/js/termynal.js b/docs/en/docs/js/termynal.js new file mode 100644 index 0000000000000..82d04e2d0b1b3 --- /dev/null +++ b/docs/en/docs/js/termynal.js @@ -0,0 +1,264 @@ +/** + * termynal.js + * A lightweight, modern and extensible animated terminal window, using + * async/await. + * + * @author Ines Montani + * @version 0.0.1 + * @license MIT + */ + +'use strict'; + +/** Generate a terminal widget. */ +class Termynal { + /** + * Construct the widget's settings. + * @param {(string|Node)=} container - Query selector or container element. + * @param {Object=} options - Custom settings. + * @param {string} options.prefix - Prefix to use for data attributes. + * @param {number} options.startDelay - Delay before animation, in ms. + * @param {number} options.typeDelay - Delay between each typed character, in ms. + * @param {number} options.lineDelay - Delay between each line, in ms. + * @param {number} options.progressLength - Number of characters displayed as progress bar. + * @param {string} options.progressChar – Character to use for progress bar, defaults to █. + * @param {number} options.progressPercent - Max percent of progress. + * @param {string} options.cursor – Character to use for cursor, defaults to ▋. + * @param {Object[]} lineData - Dynamically loaded line data objects. + * @param {boolean} options.noInit - Don't initialise the animation. + */ + constructor(container = '#termynal', options = {}) { + this.container = (typeof container === 'string') ? document.querySelector(container) : container; + this.pfx = `data-${options.prefix || 'ty'}`; + this.originalStartDelay = this.startDelay = options.startDelay + || parseFloat(this.container.getAttribute(`${this.pfx}-startDelay`)) || 600; + this.originalTypeDelay = this.typeDelay = options.typeDelay + || parseFloat(this.container.getAttribute(`${this.pfx}-typeDelay`)) || 90; + this.originalLineDelay = this.lineDelay = options.lineDelay + || parseFloat(this.container.getAttribute(`${this.pfx}-lineDelay`)) || 1500; + this.progressLength = options.progressLength + || parseFloat(this.container.getAttribute(`${this.pfx}-progressLength`)) || 40; + this.progressChar = options.progressChar + || this.container.getAttribute(`${this.pfx}-progressChar`) || '█'; + this.progressPercent = options.progressPercent + || parseFloat(this.container.getAttribute(`${this.pfx}-progressPercent`)) || 100; + this.cursor = options.cursor + || this.container.getAttribute(`${this.pfx}-cursor`) || '▋'; + this.lineData = this.lineDataToElements(options.lineData || []); + this.loadLines() + if (!options.noInit) this.init() + } + + loadLines() { + // Load all the lines and create the container so that the size is fixed + // Otherwise it would be changing and the user viewport would be constantly + // moving as she/he scrolls + const finish = this.generateFinish() + finish.style.visibility = 'hidden' + this.container.appendChild(finish) + // Appends dynamically loaded lines to existing line elements. + this.lines = [...this.container.querySelectorAll(`[${this.pfx}]`)].concat(this.lineData); + for (let line of this.lines) { + line.style.visibility = 'hidden' + this.container.appendChild(line) + } + const restart = this.generateRestart() + restart.style.visibility = 'hidden' + this.container.appendChild(restart) + this.container.setAttribute('data-termynal', ''); + } + + /** + * Initialise the widget, get lines, clear container and start animation. + */ + init() { + /** + * Calculates width and height of Termynal container. + * If container is empty and lines are dynamically loaded, defaults to browser `auto` or CSS. + */ + const containerStyle = getComputedStyle(this.container); + this.container.style.width = containerStyle.width !== '0px' ? + containerStyle.width : undefined; + this.container.style.minHeight = containerStyle.height !== '0px' ? + containerStyle.height : undefined; + + this.container.setAttribute('data-termynal', ''); + this.container.innerHTML = ''; + for (let line of this.lines) { + line.style.visibility = 'visible' + } + this.start(); + } + + /** + * Start the animation and rener the lines depending on their data attributes. + */ + async start() { + this.addFinish() + await this._wait(this.startDelay); + + for (let line of this.lines) { + const type = line.getAttribute(this.pfx); + const delay = line.getAttribute(`${this.pfx}-delay`) || this.lineDelay; + + if (type == 'input') { + line.setAttribute(`${this.pfx}-cursor`, this.cursor); + await this.type(line); + await this._wait(delay); + } + + else if (type == 'progress') { + await this.progress(line); + await this._wait(delay); + } + + else { + this.container.appendChild(line); + await this._wait(delay); + } + + line.removeAttribute(`${this.pfx}-cursor`); + } + this.addRestart() + this.finishElement.style.visibility = 'hidden' + this.lineDelay = this.originalLineDelay + this.typeDelay = this.originalTypeDelay + this.startDelay = this.originalStartDelay + } + + generateRestart() { + const restart = document.createElement('a') + restart.onclick = (e) => { + e.preventDefault() + this.container.innerHTML = '' + this.init() + } + restart.href = "javascript:void(0)" + restart.setAttribute('data-terminal-control', '') + restart.innerHTML = "restart ↻" + return restart + } + + generateFinish() { + const finish = document.createElement('a') + finish.onclick = (e) => { + e.preventDefault() + this.lineDelay = 0 + this.typeDelay = 0 + this.startDelay = 0 + } + finish.href = "javascript:void(0)" + finish.setAttribute('data-terminal-control', '') + finish.innerHTML = "fast →" + this.finishElement = finish + return finish + } + + addRestart() { + const restart = this.generateRestart() + this.container.appendChild(restart) + } + + addFinish() { + const finish = this.generateFinish() + this.container.appendChild(finish) + } + + /** + * Animate a typed line. + * @param {Node} line - The line element to render. + */ + async type(line) { + const chars = [...line.textContent]; + line.textContent = ''; + this.container.appendChild(line); + + for (let char of chars) { + const delay = line.getAttribute(`${this.pfx}-typeDelay`) || this.typeDelay; + await this._wait(delay); + line.textContent += char; + } + } + + /** + * Animate a progress bar. + * @param {Node} line - The line element to render. + */ + async progress(line) { + const progressLength = line.getAttribute(`${this.pfx}-progressLength`) + || this.progressLength; + const progressChar = line.getAttribute(`${this.pfx}-progressChar`) + || this.progressChar; + const chars = progressChar.repeat(progressLength); + const progressPercent = line.getAttribute(`${this.pfx}-progressPercent`) + || this.progressPercent; + line.textContent = ''; + this.container.appendChild(line); + + for (let i = 1; i < chars.length + 1; i++) { + await this._wait(this.typeDelay); + const percent = Math.round(i / chars.length * 100); + line.textContent = `${chars.slice(0, i)} ${percent}%`; + if (percent>progressPercent) { + break; + } + } + } + + /** + * Helper function for animation delays, called with `await`. + * @param {number} time - Timeout, in ms. + */ + _wait(time) { + return new Promise(resolve => setTimeout(resolve, time)); + } + + /** + * Converts line data objects into line elements. + * + * @param {Object[]} lineData - Dynamically loaded lines. + * @param {Object} line - Line data object. + * @returns {Element[]} - Array of line elements. + */ + lineDataToElements(lineData) { + return lineData.map(line => { + let div = document.createElement('div'); + div.innerHTML = `${line.value || ''}`; + + return div.firstElementChild; + }); + } + + /** + * Helper function for generating attributes string. + * + * @param {Object} line - Line data object. + * @returns {string} - String of attributes. + */ + _attributes(line) { + let attrs = ''; + for (let prop in line) { + // Custom add class + if (prop === 'class') { + attrs += ` class=${line[prop]} ` + continue + } + if (prop === 'type') { + attrs += `${this.pfx}="${line[prop]}" ` + } else if (prop !== 'value') { + attrs += `${this.pfx}-${prop}="${line[prop]}" ` + } + } + + return attrs; + } +} + +/** +* HTML API: If current script has container(s) specified, initialise Termynal. +*/ +if (document.currentScript.hasAttribute('data-termynal-container')) { + const containers = document.currentScript.getAttribute('data-termynal-container'); + containers.split('|') + .forEach(container => new Termynal(container)) +} diff --git a/docs/en/docs/learn/index.md b/docs/en/docs/learn/index.md new file mode 100644 index 0000000000000..21e54009b6af6 --- /dev/null +++ b/docs/en/docs/learn/index.md @@ -0,0 +1,5 @@ +# Learn { #learn } + +Here are the introductory sections and the tutorials to learn **FastAPI**. + +You could consider this a **book**, a **course**, the **official** and recommended way to learn FastAPI. 😎 diff --git a/docs/en/docs/management.md b/docs/en/docs/management.md new file mode 100644 index 0000000000000..7404947684781 --- /dev/null +++ b/docs/en/docs/management.md @@ -0,0 +1,25 @@ +# Repository Management + +Here's a short description of how the FastAPI repository is managed and maintained. + +## Owner + +I, [@tiangolo](https://github.com/tiangolo), am the creator and owner of the FastAPI repository. 🤓 + +I normally give the final review to each PR before merging them. I make the final decisions on the project, I'm the [BDFL](https://en.wikipedia.org/wiki/Benevolent_dictator_for_life). 😅 + +## Team + +There's a team of people that help manage and maintain the project. 😎 + +Learn more about it in [tiangolo.com - GitHub FastAPI](https://tiangolo.com/github-fastapi/). + +## FastAPI Experts + +The people that help others the most in GitHub Discussions can become [**FastAPI Experts**](./fastapi-people.md#fastapi-experts). + +This is normally the best way to contribute to the project. + +## External Help + +External help is very much appreciated. There are many ways to [help](./help-fastapi.md). ☕️ diff --git a/docs/en/docs/newsletter.md b/docs/en/docs/newsletter.md new file mode 100644 index 0000000000000..29b777a670748 --- /dev/null +++ b/docs/en/docs/newsletter.md @@ -0,0 +1,5 @@ +# FastAPI and friends newsletter + + + + diff --git a/docs/en/docs/project-generation.md b/docs/en/docs/project-generation.md new file mode 100644 index 0000000000000..ab6e87527b6d4 --- /dev/null +++ b/docs/en/docs/project-generation.md @@ -0,0 +1,28 @@ +# Full Stack FastAPI Template { #full-stack-fastapi-template } + +Templates, while they typically come with a specific setup, are designed to be flexible and customizable. This allows you to modify and adapt them to your project's requirements, making them an excellent starting point. 🏁 + +You can use this template to get started, as it includes a lot of the initial setup, security, database and some API endpoints already done for you. + +GitHub Repository: [Full Stack FastAPI Template](https://github.com/tiangolo/full-stack-fastapi-template) + +## Full Stack FastAPI Template - Technology Stack and Features { #full-stack-fastapi-template-technology-stack-and-features } + +- ⚡ [**FastAPI**](https://fastapi.tiangolo.com) for the Python backend API. + - 🧰 [SQLModel](https://sqlmodel.tiangolo.com) for the Python SQL database interactions (ORM). + - 🔍 [Pydantic](https://docs.pydantic.dev), used by FastAPI, for the data validation and settings management. + - 💾 [PostgreSQL](https://www.postgresql.org) as the SQL database. +- 🚀 [React](https://react.dev) for the frontend. + - 💃 Using TypeScript, hooks, Vite, and other parts of a modern frontend stack. + - 🎨 [Tailwind CSS](https://tailwindcss.com) and [shadcn/ui](https://ui.shadcn.com) for the frontend components. + - 🤖 An automatically generated frontend client. + - 🧪 [Playwright](https://playwright.dev) for End-to-End testing. + - 🦇 Dark mode support. +- 🐋 [Docker Compose](https://www.docker.com) for development and production. +- 🔒 Secure password hashing by default. +- 🔑 JWT (JSON Web Token) authentication. +- 📫 Email based password recovery. +- ✅ Tests with [Pytest](https://pytest.org). +- 📞 [Traefik](https://traefik.io) as a reverse proxy / load balancer. +- 🚢 Deployment instructions using Docker Compose, including how to set up a frontend Traefik proxy to handle automatic HTTPS certificates. +- 🏭 CI (continuous integration) and CD (continuous deployment) based on GitHub Actions. diff --git a/docs/en/docs/python-types.md b/docs/en/docs/python-types.md new file mode 100644 index 0000000000000..c8d9bf41c9ee0 --- /dev/null +++ b/docs/en/docs/python-types.md @@ -0,0 +1,348 @@ +# Python Types Intro { #python-types-intro } + +Python has support for optional "type hints" (also called "type annotations"). + +These **"type hints"** or annotations are a special syntax that allows declaring the type of a variable. + +By declaring types for your variables, editors and tools can give you better support. + +This is just a **quick tutorial / refresher** about Python type hints. It covers only the minimum necessary to use them with **FastAPI**... which is actually very little. + +**FastAPI** is all based on these type hints, they give it many advantages and benefits. + +But even if you never use **FastAPI**, you would benefit from learning a bit about them. + +/// note + +If you are a Python expert, and you already know everything about type hints, skip to the next chapter. + +/// + +## Motivation { #motivation } + +Let's start with a simple example: + +{* ../../docs_src/python_types/tutorial001_py310.py *} + +Calling this program outputs: + +``` +John Doe +``` + +The function does the following: + +* Takes a `first_name` and `last_name`. +* Converts the first letter of each one to upper case with `title()`. +* Concatenates them with a space in the middle. + +{* ../../docs_src/python_types/tutorial001_py310.py hl[2] *} + +### Edit it { #edit-it } + +It's a very simple program. + +But now imagine that you were writing it from scratch. + +At some point you start defining the function, and you have the parameters ready... + +But then you have to call "that method that converts the first letter to upper case". + +Was it `upper`? Was it `uppercase`? `first_uppercase`? `capitalize`? + +Then, you try with the old programmer's friend, editor autocompletion. + +You type the first parameter of the function, `first_name`, then a dot (`.`) and then hit `Ctrl+Space` to trigger the completion. + +But, sadly, you get nothing useful: + + + +### Add types { #add-types } + +Let's modify a single line from the previous version. + +We will change exactly this fragment, the parameters of the function, from: + +```Python + first_name, last_name +``` + +to: + +```Python + first_name: str, last_name: str +``` + +That's it. + +Those are the "type hints": + +{* ../../docs_src/python_types/tutorial002_py310.py hl[1] *} + +That is not the same as declaring default values like it would be with: + +```Python + first_name="john", last_name="doe" +``` + +It's a different thing. + +We are using colons (`:`), not equals (`=`). + +And adding type hints normally doesn't change what happens from what would happen without them. + +But now, imagine you are again in the middle of creating that function, but with type hints. + +At the same point, you try to trigger the autocomplete with `Ctrl+Space` and you see: + + + +With that, you can scroll, seeing the options, until you find the one that "rings a bell": + + + +## More motivation { #more-motivation } + +Check this function, it already has type hints: + +{* ../../docs_src/python_types/tutorial003_py310.py hl[1] *} + +Because the editor knows the types of the variables, you don't only get completion, you also get error checks: + + + +Now you know that you have to fix it, convert `age` to a string with `str(age)`: + +{* ../../docs_src/python_types/tutorial004_py310.py hl[2] *} + +## Declaring types { #declaring-types } + +You just saw the main place to declare type hints. As function parameters. + +This is also the main place you would use them with **FastAPI**. + +### Simple types { #simple-types } + +You can declare all the standard Python types, not only `str`. + +You can use, for example: + +* `int` +* `float` +* `bool` +* `bytes` + +{* ../../docs_src/python_types/tutorial005_py310.py hl[1] *} + +### `typing` module { #typing-module } + +For some additional use cases, you might need to import some things from the standard library `typing` module, for example when you want to declare that something has "any type", you can use `Any` from `typing`: + +```python +from typing import Any + + +def some_function(data: Any): + print(data) +``` + +### Generic types { #generic-types } + +Some types can take "type parameters" in square brackets, to define their internal types, for example a "list of strings" would be declared `list[str]`. + +These types that can take type parameters are called **Generic types** or **Generics**. + +You can use the same builtin types as generics (with square brackets and types inside): + +* `list` +* `tuple` +* `set` +* `dict` + +#### List { #list } + +For example, let's define a variable to be a `list` of `str`. + +Declare the variable, with the same colon (`:`) syntax. + +As the type, put `list`. + +As the list is a type that contains some internal types, you put them in square brackets: + +{* ../../docs_src/python_types/tutorial006_py310.py hl[1] *} + +/// note + +Those internal types in the square brackets are called "type parameters". + +In this case, `str` is the type parameter passed to `list`. + +/// + +That means: "the variable `items` is a `list`, and each of the items in this list is a `str`". + +By doing that, your editor can provide support even while processing items from the list: + + + +Without types, that's almost impossible to achieve. + +Notice that the variable `item` is one of the elements in the list `items`. + +And still, the editor knows it is a `str`, and provides support for that. + +#### Tuple and Set { #tuple-and-set } + +You would do the same to declare `tuple`s and `set`s: + +{* ../../docs_src/python_types/tutorial007_py310.py hl[1] *} + +This means: + +* The variable `items_t` is a `tuple` with 3 items, an `int`, another `int`, and a `str`. +* The variable `items_s` is a `set`, and each of its items is of type `bytes`. + +#### Dict { #dict } + +To define a `dict`, you pass 2 type parameters, separated by commas. + +The first type parameter is for the keys of the `dict`. + +The second type parameter is for the values of the `dict`: + +{* ../../docs_src/python_types/tutorial008_py310.py hl[1] *} + +This means: + +* The variable `prices` is a `dict`: + * The keys of this `dict` are of type `str` (let's say, the name of each item). + * The values of this `dict` are of type `float` (let's say, the price of each item). + +#### Union { #union } + +You can declare that a variable can be any of **several types**, for example, an `int` or a `str`. + +To define it you use the vertical bar (`|`) to separate both types. + +This is called a "union", because the variable can be anything in the union of those two sets of types. + +```Python hl_lines="1" +{!> ../../docs_src/python_types/tutorial008b_py310.py!} +``` + +This means that `item` could be an `int` or a `str`. + +#### Possibly `None` { #possibly-none } + +You can declare that a value could have a type, like `str`, but that it could also be `None`. + +//// tab | Python 3.10+ + +```Python hl_lines="1" +{!> ../../docs_src/python_types/tutorial009_py310.py!} +``` + +//// + +Using `str | None` instead of just `str` will let the editor help you detect errors where you could be assuming that a value is always a `str`, when it could actually be `None` too. + +### Classes as types { #classes-as-types } + +You can also declare a class as the type of a variable. + +Let's say you have a class `Person`, with a name: + +{* ../../docs_src/python_types/tutorial010_py310.py hl[1:3] *} + +Then you can declare a variable to be of type `Person`: + +{* ../../docs_src/python_types/tutorial010_py310.py hl[6] *} + +And then, again, you get all the editor support: + + + +Notice that this means "`one_person` is an **instance** of the class `Person`". + +It doesn't mean "`one_person` is the **class** called `Person`". + +## Pydantic models { #pydantic-models } + +[Pydantic](https://docs.pydantic.dev/) is a Python library to perform data validation. + +You declare the "shape" of the data as classes with attributes. + +And each attribute has a type. + +Then you create an instance of that class with some values and it will validate the values, convert them to the appropriate type (if that's the case) and give you an object with all the data. + +And you get all the editor support with that resulting object. + +An example from the official Pydantic docs: + +{* ../../docs_src/python_types/tutorial011_py310.py *} + +/// note + +To learn more about [Pydantic, check its docs](https://docs.pydantic.dev/). + +/// + +**FastAPI** is all based on Pydantic. + +You will see a lot more of all this in practice in the [Tutorial - User Guide](tutorial/index.md). + +## Type Hints with Metadata Annotations { #type-hints-with-metadata-annotations } + +Python also has a feature that allows putting **additional metadata** in these type hints using `Annotated`. + +You can import `Annotated` from `typing`. + +{* ../../docs_src/python_types/tutorial013_py310.py hl[1,4] *} + +Python itself doesn't do anything with this `Annotated`. And for editors and other tools, the type is still `str`. + +But you can use this space in `Annotated` to provide **FastAPI** with additional metadata about how you want your application to behave. + +The important thing to remember is that **the first *type parameter*** you pass to `Annotated` is the **actual type**. The rest, is just metadata for other tools. + +For now, you just need to know that `Annotated` exists, and that it's standard Python. 😎 + +Later you will see how **powerful** it can be. + +/// tip + +The fact that this is **standard Python** means that you will still get the **best possible developer experience** in your editor, with the tools you use to analyze and refactor your code, etc. ✨ + +And also that your code will be very compatible with many other Python tools and libraries. 🚀 + +/// + +## Type hints in **FastAPI** { #type-hints-in-fastapi } + +**FastAPI** takes advantage of these type hints to do several things. + +With **FastAPI** you declare parameters with type hints and you get: + +* **Editor support**. +* **Type checks**. + +...and **FastAPI** uses the same declarations to: + +* **Define requirements**: from request path parameters, query parameters, headers, bodies, dependencies, etc. +* **Convert data**: from the request to the required type. +* **Validate data**: coming from each request: + * Generating **automatic errors** returned to the client when the data is invalid. +* **Document** the API using OpenAPI: + * which is then used by the automatic interactive documentation user interfaces. + +This might all sound abstract. Don't worry. You'll see all this in action in the [Tutorial - User Guide](tutorial/index.md). + +The important thing is that by using standard Python types, in a single place (instead of adding more classes, decorators, etc), **FastAPI** will do a lot of the work for you. + +/// note + +If you already went through all the tutorial and came back to see more about types, a good resource is [the "cheat sheet" from `mypy`](https://mypy.readthedocs.io/en/latest/cheat_sheet_py3.html). + +/// diff --git a/docs/en/docs/reference/apirouter.md b/docs/en/docs/reference/apirouter.md new file mode 100644 index 0000000000000..819366dfba773 --- /dev/null +++ b/docs/en/docs/reference/apirouter.md @@ -0,0 +1,25 @@ +# `APIRouter` class + +Here's the reference information for the `APIRouter` class, with all its parameters, attributes and methods. + +You can import the `APIRouter` class directly from `fastapi`: + +```python +from fastapi import APIRouter +``` + +::: fastapi.APIRouter + options: + members: + - websocket + - include_router + - frontend + - get + - put + - post + - delete + - options + - head + - patch + - trace + - on_event diff --git a/docs/en/docs/reference/background.md b/docs/en/docs/reference/background.md new file mode 100644 index 0000000000000..f65619590ecee --- /dev/null +++ b/docs/en/docs/reference/background.md @@ -0,0 +1,11 @@ +# Background Tasks - `BackgroundTasks` + +You can declare a parameter in a *path operation function* or dependency function with the type `BackgroundTasks`, and then you can use it to schedule the execution of background tasks after the response is sent. + +You can import it directly from `fastapi`: + +```python +from fastapi import BackgroundTasks +``` + +::: fastapi.BackgroundTasks diff --git a/docs/en/docs/reference/dependencies.md b/docs/en/docs/reference/dependencies.md new file mode 100644 index 0000000000000..2959a21daebc1 --- /dev/null +++ b/docs/en/docs/reference/dependencies.md @@ -0,0 +1,29 @@ +# Dependencies - `Depends()` and `Security()` + +## `Depends()` + +Dependencies are handled mainly with the special function `Depends()` that takes a callable. + +Here is the reference for it and its parameters. + +You can import it directly from `fastapi`: + +```python +from fastapi import Depends +``` + +::: fastapi.Depends + +## `Security()` + +For many scenarios, you can handle security (authorization, authentication, etc.) with dependencies, using `Depends()`. + +But when you want to also declare OAuth2 scopes, you can use `Security()` instead of `Depends()`. + +You can import `Security()` directly from `fastapi`: + +```python +from fastapi import Security +``` + +::: fastapi.Security diff --git a/docs/en/docs/reference/encoders.md b/docs/en/docs/reference/encoders.md new file mode 100644 index 0000000000000..28df2e43a2786 --- /dev/null +++ b/docs/en/docs/reference/encoders.md @@ -0,0 +1,3 @@ +# Encoders - `jsonable_encoder` + +::: fastapi.encoders.jsonable_encoder diff --git a/docs/en/docs/reference/exceptions.md b/docs/en/docs/reference/exceptions.md new file mode 100644 index 0000000000000..1392d2a80e3cf --- /dev/null +++ b/docs/en/docs/reference/exceptions.md @@ -0,0 +1,20 @@ +# Exceptions - `HTTPException` and `WebSocketException` + +These are the exceptions that you can raise to show errors to the client. + +When you raise an exception, as would happen with normal Python, the rest of the execution is aborted. This way you can raise these exceptions from anywhere in the code to abort a request and show the error to the client. + +You can use: + +* `HTTPException` +* `WebSocketException` + +These exceptions can be imported directly from `fastapi`: + +```python +from fastapi import HTTPException, WebSocketException +``` + +::: fastapi.HTTPException + +::: fastapi.WebSocketException diff --git a/docs/en/docs/reference/fastapi.md b/docs/en/docs/reference/fastapi.md new file mode 100644 index 0000000000000..e8ec991e5d3c4 --- /dev/null +++ b/docs/en/docs/reference/fastapi.md @@ -0,0 +1,32 @@ +# `FastAPI` class + +Here's the reference information for the `FastAPI` class, with all its parameters, attributes and methods. + +You can import the `FastAPI` class directly from `fastapi`: + +```python +from fastapi import FastAPI +``` + +::: fastapi.FastAPI + options: + members: + - openapi_version + - webhooks + - state + - dependency_overrides + - openapi + - websocket + - include_router + - frontend + - get + - put + - post + - delete + - options + - head + - patch + - trace + - on_event + - middleware + - exception_handler diff --git a/docs/en/docs/reference/httpconnection.md b/docs/en/docs/reference/httpconnection.md new file mode 100644 index 0000000000000..b7b87871a80c9 --- /dev/null +++ b/docs/en/docs/reference/httpconnection.md @@ -0,0 +1,11 @@ +# `HTTPConnection` class + +When you want to define dependencies that should be compatible with both HTTP and WebSockets, you can define a parameter that takes an `HTTPConnection` instead of a `Request` or a `WebSocket`. + +You can import it from `fastapi.requests`: + +```python +from fastapi.requests import HTTPConnection +``` + +::: fastapi.requests.HTTPConnection diff --git a/docs/en/docs/reference/index.md b/docs/en/docs/reference/index.md new file mode 100644 index 0000000000000..b6dfdd063b8cd --- /dev/null +++ b/docs/en/docs/reference/index.md @@ -0,0 +1,7 @@ +# Reference + +Here's the reference or code API, the classes, functions, parameters, attributes, and +all the FastAPI parts you can use in your applications. + +If you want to **learn FastAPI** you are much better off reading the +[FastAPI Tutorial](https://fastapi.tiangolo.com/tutorial/). diff --git a/docs/en/docs/reference/middleware.md b/docs/en/docs/reference/middleware.md new file mode 100644 index 0000000000000..48ff85158dd0f --- /dev/null +++ b/docs/en/docs/reference/middleware.md @@ -0,0 +1,37 @@ +# Middleware + +There are several middlewares available provided by Starlette directly. + +Read more about them in the [FastAPI docs for Middleware](https://fastapi.tiangolo.com/advanced/middleware/). + +::: fastapi.middleware.cors.CORSMiddleware + +It can be imported from `fastapi`: + +```python +from fastapi.middleware.cors import CORSMiddleware +``` + +::: fastapi.middleware.gzip.GZipMiddleware + +It can be imported from `fastapi`: + +```python +from fastapi.middleware.gzip import GZipMiddleware +``` + +::: fastapi.middleware.httpsredirect.HTTPSRedirectMiddleware + +It can be imported from `fastapi`: + +```python +from fastapi.middleware.httpsredirect import HTTPSRedirectMiddleware +``` + +::: fastapi.middleware.trustedhost.TrustedHostMiddleware + +It can be imported from `fastapi`: + +```python +from fastapi.middleware.trustedhost import TrustedHostMiddleware +``` diff --git a/docs/en/docs/reference/openapi/docs.md b/docs/en/docs/reference/openapi/docs.md new file mode 100644 index 0000000000000..ab620833ec99a --- /dev/null +++ b/docs/en/docs/reference/openapi/docs.md @@ -0,0 +1,11 @@ +# OpenAPI `docs` + +Utilities to handle OpenAPI automatic UI documentation, including Swagger UI (by default at `/docs`) and ReDoc (by default at `/redoc`). + +::: fastapi.openapi.docs.get_swagger_ui_html + +::: fastapi.openapi.docs.get_redoc_html + +::: fastapi.openapi.docs.get_swagger_ui_oauth2_redirect_html + +::: fastapi.openapi.docs.swagger_ui_default_parameters diff --git a/docs/en/docs/reference/openapi/index.md b/docs/en/docs/reference/openapi/index.md new file mode 100644 index 0000000000000..e2b313f1509a1 --- /dev/null +++ b/docs/en/docs/reference/openapi/index.md @@ -0,0 +1,5 @@ +# OpenAPI + +There are several utilities to handle OpenAPI. + +You normally don't need to use them unless you have a specific advanced use case that requires it. diff --git a/docs/en/docs/reference/openapi/models.md b/docs/en/docs/reference/openapi/models.md new file mode 100644 index 0000000000000..4a6b0770edca0 --- /dev/null +++ b/docs/en/docs/reference/openapi/models.md @@ -0,0 +1,5 @@ +# OpenAPI `models` + +OpenAPI Pydantic models used to generate and validate the generated OpenAPI. + +::: fastapi.openapi.models diff --git a/docs/en/docs/reference/parameters.md b/docs/en/docs/reference/parameters.md new file mode 100644 index 0000000000000..d304c013c7a4e --- /dev/null +++ b/docs/en/docs/reference/parameters.md @@ -0,0 +1,35 @@ +# Request Parameters + +Here's the reference information for the request parameters. + +These are the special functions that you can put in *path operation function* parameters or dependency functions with `Annotated` to get data from the request. + +It includes: + +* `Query()` +* `Path()` +* `Body()` +* `Cookie()` +* `Header()` +* `Form()` +* `File()` + +You can import them all directly from `fastapi`: + +```python +from fastapi import Body, Cookie, File, Form, Header, Path, Query +``` + +::: fastapi.Query + +::: fastapi.Path + +::: fastapi.Body + +::: fastapi.Cookie + +::: fastapi.Header + +::: fastapi.Form + +::: fastapi.File diff --git a/docs/en/docs/reference/request.md b/docs/en/docs/reference/request.md new file mode 100644 index 0000000000000..7994bf8a88e0a --- /dev/null +++ b/docs/en/docs/reference/request.md @@ -0,0 +1,19 @@ +# `Request` class + +You can declare a parameter in a *path operation function* or dependency to be of type `Request` and then you can access the raw request object directly, without any validation, etc. + +Read more about it in the [FastAPI docs about using Request directly](https://fastapi.tiangolo.com/advanced/using-request-directly/) + +You can import it directly from `fastapi`: + +```python +from fastapi import Request +``` + +/// tip + +When you want to define dependencies that should be compatible with both HTTP and WebSockets, you can define a parameter that takes an `HTTPConnection` instead of a `Request` or a `WebSocket`. + +/// + +::: fastapi.Request diff --git a/docs/en/docs/reference/response.md b/docs/en/docs/reference/response.md new file mode 100644 index 0000000000000..c9085766c92c6 --- /dev/null +++ b/docs/en/docs/reference/response.md @@ -0,0 +1,15 @@ +# `Response` class + +You can declare a parameter in a *path operation function* or dependency to be of type `Response` and then you can set data for the response like headers or cookies. + +You can also use it directly to create an instance of it and return it from your *path operations*. + +Read more about it in the [FastAPI docs about returning a custom Response](https://fastapi.tiangolo.com/advanced/response-directly/#returning-a-custom-response) + +You can import it directly from `fastapi`: + +```python +from fastapi import Response +``` + +::: fastapi.Response diff --git a/docs/en/docs/reference/responses.md b/docs/en/docs/reference/responses.md new file mode 100644 index 0000000000000..2df53e9701797 --- /dev/null +++ b/docs/en/docs/reference/responses.md @@ -0,0 +1,172 @@ +# Custom Response Classes - File, HTML, Redirect, Streaming, etc. + +There are several custom response classes you can use to create an instance and return them directly from your *path operations*. + +Read more about it in the [FastAPI docs for Custom Response - HTML, Stream, File, others](https://fastapi.tiangolo.com/advanced/custom-response/). + +You can import them directly from `fastapi.responses`: + +```python +from fastapi.responses import ( + FileResponse, + HTMLResponse, + JSONResponse, + ORJSONResponse, + PlainTextResponse, + RedirectResponse, + Response, + StreamingResponse, + UJSONResponse, +) +``` + +## FastAPI Responses + +There were a couple of custom FastAPI response classes that were intended to optimize JSON performance. + +However, they are now deprecated as you will now get better performance by using a [Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/). + +That way, Pydantic will serialize the data into JSON bytes on the Rust side, which will achieve better performance than these custom JSON responses. + +Read more about it in [Custom Response - HTML, Stream, File, others - `orjson` or Response Model](https://fastapi.tiangolo.com/advanced/custom-response/#orjson-or-response-model). + +::: fastapi.responses.UJSONResponse + options: + members: + - charset + - status_code + - media_type + - body + - background + - raw_headers + - render + - init_headers + - headers + - set_cookie + - delete_cookie + +::: fastapi.responses.ORJSONResponse + options: + members: + - charset + - status_code + - media_type + - body + - background + - raw_headers + - render + - init_headers + - headers + - set_cookie + - delete_cookie + +## Starlette Responses + +You can read more about all of them in the [FastAPI docs for Custom Response](https://fastapi.tiangolo.com/advanced/custom-response/) and in the [Starlette docs about Responses](https://starlette.dev/responses/). + +::: fastapi.responses.FileResponse + options: + members: + - chunk_size + - charset + - status_code + - media_type + - body + - background + - raw_headers + - render + - init_headers + - headers + - set_cookie + - delete_cookie + +::: fastapi.responses.HTMLResponse + options: + members: + - charset + - status_code + - media_type + - body + - background + - raw_headers + - render + - init_headers + - headers + - set_cookie + - delete_cookie + +::: fastapi.responses.JSONResponse + options: + members: + - charset + - status_code + - media_type + - body + - background + - raw_headers + - render + - init_headers + - headers + - set_cookie + - delete_cookie + +::: fastapi.responses.PlainTextResponse + options: + members: + - charset + - status_code + - media_type + - body + - background + - raw_headers + - render + - init_headers + - headers + - set_cookie + - delete_cookie + +::: fastapi.responses.RedirectResponse + options: + members: + - charset + - status_code + - media_type + - body + - background + - raw_headers + - render + - init_headers + - headers + - set_cookie + - delete_cookie + +::: fastapi.responses.Response + options: + members: + - charset + - status_code + - media_type + - body + - background + - raw_headers + - render + - init_headers + - headers + - set_cookie + - delete_cookie + +::: fastapi.responses.StreamingResponse + options: + members: + - body_iterator + - charset + - status_code + - media_type + - body + - background + - raw_headers + - render + - init_headers + - headers + - set_cookie + - delete_cookie diff --git a/docs/en/docs/reference/security/index.md b/docs/en/docs/reference/security/index.md new file mode 100644 index 0000000000000..8163aa2df2821 --- /dev/null +++ b/docs/en/docs/reference/security/index.md @@ -0,0 +1,75 @@ +# Security Tools + +When you need to declare dependencies with OAuth2 scopes you use `Security()`. + +But you still need to define what is the dependable, the callable that you pass as a parameter to `Depends()` or `Security()`. + +There are multiple tools that you can use to create those dependables, and they get integrated into OpenAPI so they are shown in the automatic docs UI, they can be used by automatically generated clients and SDKs, etc. + +You can import them from `fastapi.security`: + +```python +from fastapi.security import ( + APIKeyCookie, + APIKeyHeader, + APIKeyQuery, + HTTPAuthorizationCredentials, + HTTPBasic, + HTTPBasicCredentials, + HTTPBearer, + HTTPDigest, + OAuth2, + OAuth2AuthorizationCodeBearer, + OAuth2PasswordBearer, + OAuth2PasswordRequestForm, + OAuth2PasswordRequestFormStrict, + OpenIdConnect, + SecurityScopes, +) +``` + +Read more about them in the [FastAPI docs about Security](https://fastapi.tiangolo.com/tutorial/security/). + +## API Key Security Schemes + +::: fastapi.security.APIKeyCookie + +::: fastapi.security.APIKeyHeader + +::: fastapi.security.APIKeyQuery + +## HTTP Authentication Schemes + +::: fastapi.security.HTTPBasic + +::: fastapi.security.HTTPBearer + +::: fastapi.security.HTTPDigest + +## HTTP Credentials + +::: fastapi.security.HTTPAuthorizationCredentials + +::: fastapi.security.HTTPBasicCredentials + +## OAuth2 Authentication + +::: fastapi.security.OAuth2 + +::: fastapi.security.OAuth2AuthorizationCodeBearer + +::: fastapi.security.OAuth2PasswordBearer + +## OAuth2 Password Form + +::: fastapi.security.OAuth2PasswordRequestForm + +::: fastapi.security.OAuth2PasswordRequestFormStrict + +## OAuth2 Security Scopes in Dependencies + +::: fastapi.security.SecurityScopes + +## OpenID Connect + +::: fastapi.security.OpenIdConnect diff --git a/docs/en/docs/reference/staticfiles.md b/docs/en/docs/reference/staticfiles.md new file mode 100644 index 0000000000000..2712310783c62 --- /dev/null +++ b/docs/en/docs/reference/staticfiles.md @@ -0,0 +1,13 @@ +# Static Files - `StaticFiles` + +You can use the `StaticFiles` class to serve static files, like JavaScript, CSS, images, etc. + +Read more about it in the [FastAPI docs for Static Files](https://fastapi.tiangolo.com/tutorial/static-files/). + +You can import it directly from `fastapi.staticfiles`: + +```python +from fastapi.staticfiles import StaticFiles +``` + +::: fastapi.staticfiles.StaticFiles diff --git a/docs/en/docs/reference/status.md b/docs/en/docs/reference/status.md new file mode 100644 index 0000000000000..16af90e0fd06f --- /dev/null +++ b/docs/en/docs/reference/status.md @@ -0,0 +1,36 @@ +# Status Codes + +You can import the `status` module from `fastapi`: + +```python +from fastapi import status +``` + +`status` is provided directly by Starlette. + +It contains a group of named constants (variables) with integer status codes. + +For example: + +* 200: `status.HTTP_200_OK` +* 403: `status.HTTP_403_FORBIDDEN` +* etc. + +It can be convenient to quickly access HTTP (and WebSocket) status codes in your app, using autocompletion for the name without having to memorize the integer status codes. + +Read more about it in the [FastAPI docs about Response Status Code](https://fastapi.tiangolo.com/tutorial/response-status-code/). + +## Example + +```python +from fastapi import FastAPI, status + +app = FastAPI() + + +@app.get("/items/", status_code=status.HTTP_418_IM_A_TEAPOT) +def read_items(): + return [{"name": "Plumbus"}, {"name": "Portal Gun"}] +``` + +::: fastapi.status diff --git a/docs/en/docs/reference/templating.md b/docs/en/docs/reference/templating.md new file mode 100644 index 0000000000000..eedfe44d54d70 --- /dev/null +++ b/docs/en/docs/reference/templating.md @@ -0,0 +1,13 @@ +# Templating - `Jinja2Templates` + +You can use the `Jinja2Templates` class to render Jinja templates. + +Read more about it in the [FastAPI docs for Templates](https://fastapi.tiangolo.com/advanced/templates/). + +You can import it directly from `fastapi.templating`: + +```python +from fastapi.templating import Jinja2Templates +``` + +::: fastapi.templating.Jinja2Templates diff --git a/docs/en/docs/reference/testclient.md b/docs/en/docs/reference/testclient.md new file mode 100644 index 0000000000000..2966ed792ccf9 --- /dev/null +++ b/docs/en/docs/reference/testclient.md @@ -0,0 +1,13 @@ +# Test Client - `TestClient` + +You can use the `TestClient` class to test FastAPI applications without creating an actual HTTP and socket connection, just communicating directly with the FastAPI code. + +Read more about it in the [FastAPI docs for Testing](https://fastapi.tiangolo.com/tutorial/testing/). + +You can import it directly from `fastapi.testclient`: + +```python +from fastapi.testclient import TestClient +``` + +::: fastapi.testclient.TestClient diff --git a/docs/en/docs/reference/uploadfile.md b/docs/en/docs/reference/uploadfile.md new file mode 100644 index 0000000000000..43a75373036c5 --- /dev/null +++ b/docs/en/docs/reference/uploadfile.md @@ -0,0 +1,22 @@ +# `UploadFile` class + +You can define *path operation function* parameters to be of the type `UploadFile` to receive files from the request. + +You can import it directly from `fastapi`: + +```python +from fastapi import UploadFile +``` + +::: fastapi.UploadFile + options: + members: + - file + - filename + - size + - headers + - content_type + - read + - write + - seek + - close diff --git a/docs/en/docs/reference/websockets.md b/docs/en/docs/reference/websockets.md new file mode 100644 index 0000000000000..b1158b3878bb7 --- /dev/null +++ b/docs/en/docs/reference/websockets.md @@ -0,0 +1,73 @@ +# WebSockets + +When defining WebSockets, you normally declare a parameter of type `WebSocket` and with it you can read data from the client and send data to it. + +Read more about it in the [FastAPI docs for WebSockets](https://fastapi.tiangolo.com/advanced/websockets/) + +It is provided directly by Starlette, but you can import it from `fastapi`: + +```python +from fastapi import WebSocket +``` + +/// tip + +When you want to define dependencies that should be compatible with both HTTP and WebSockets, you can define a parameter that takes an `HTTPConnection` instead of a `Request` or a `WebSocket`. + +/// + +::: fastapi.WebSocket + options: + members: + - scope + - app + - url + - base_url + - headers + - query_params + - path_params + - cookies + - client + - state + - url_for + - client_state + - application_state + - receive + - send + - accept + - receive_text + - receive_bytes + - receive_json + - iter_text + - iter_bytes + - iter_json + - send_text + - send_bytes + - send_json + - close + +## WebSockets - additional classes + +Additional classes for handling WebSockets. + +Provided directly by Starlette, but you can import them from `fastapi`: + +```python +from fastapi.websockets import WebSocketDisconnect, WebSocketState +``` + +::: fastapi.websockets.WebSocketDisconnect + +When a client disconnects, a `WebSocketDisconnect` exception is raised, you can catch it. + +You can import it directly from `fastapi`: + +```python +from fastapi import WebSocketDisconnect +``` + +Read more about it in the [FastAPI docs for WebSockets](https://fastapi.tiangolo.com/advanced/websockets/#handling-disconnections-and-multiple-clients) + +::: fastapi.websockets.WebSocketState + +`WebSocketState` is an enumeration of the possible states of a WebSocket connection. diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md new file mode 100644 index 0000000000000..3cc2548db5afc --- /dev/null +++ b/docs/en/docs/release-notes.md @@ -0,0 +1,7173 @@ +--- +hide: + - navigation +--- + +# Release Notes + +## Latest Changes + +### Translations + +* 🌐 Update translations for hi (add-missing). PR [#15797](https://github.com/fastapi/fastapi/pull/15797) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update `llm-prompt.md` for Hindi. PR [#15810](https://github.com/fastapi/fastapi/pull/15810) by [@YuriiMotov](https://github.com/YuriiMotov). +* 🌐 Fix language-specific translation prompt for Russian language. PR [#15924](https://github.com/fastapi/fastapi/pull/15924) by [@YuriiMotov](https://github.com/YuriiMotov). + +### Internal + +* ⬆ Bump CodSpeedHQ/action from 4.17.6 to 4.18.1 in the github-actions group. PR [#15950](https://github.com/fastapi/fastapi/pull/15950) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump the python-packages group with 8 updates. PR [#15952](https://github.com/fastapi/fastapi/pull/15952) by [@dependabot[bot]](https://github.com/apps/dependabot). +* 🔧 Update sponsors: add TutorCruncher. PR [#15947](https://github.com/fastapi/fastapi/pull/15947) by [@tiangolo](https://github.com/tiangolo). +* 👷 Fix notify translations checkout target. PR [#15933](https://github.com/fastapi/fastapi/pull/15933) by [@tiangolo](https://github.com/tiangolo). +* 👷 Fix latest-changes checkout target. PR [#15932](https://github.com/fastapi/fastapi/pull/15932) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Update sponsors: remove RapidProxy. PR [#15929](https://github.com/fastapi/fastapi/pull/15929) by [@tiangolo](https://github.com/tiangolo). +* ⬆️ Update issue-manager to 0.8.1. PR [#15928](https://github.com/fastapi/fastapi/pull/15928) by [@tiangolo](https://github.com/tiangolo). +* ⬆️ Update latest-changes to 0.6.1. PR [#15926](https://github.com/fastapi/fastapi/pull/15926) by [@tiangolo](https://github.com/tiangolo). + +## 0.139.0 (2026-07-01) + +### Features + +* ✨ Support dependencies in `app.frontend()`, e.g. for automatic cookie authentication for the frontend. PR [#15908](https://github.com/fastapi/fastapi/pull/15908) by [@tiangolo](https://github.com/tiangolo). + +### Translations + +* 🌐 Update translations for fr (update-outdated). PR [#15897](https://github.com/fastapi/fastapi/pull/15897) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for ja (update-outdated). PR [#15895](https://github.com/fastapi/fastapi/pull/15895) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for zh-hant (update-outdated). PR [#15896](https://github.com/fastapi/fastapi/pull/15896) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for de (update-outdated). PR [#15899](https://github.com/fastapi/fastapi/pull/15899) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for es (update-outdated). PR [#15892](https://github.com/fastapi/fastapi/pull/15892) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for tr (update-outdated). PR [#15891](https://github.com/fastapi/fastapi/pull/15891) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for pt (update-outdated). PR [#15893](https://github.com/fastapi/fastapi/pull/15893) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for zh (update-outdated). PR [#15898](https://github.com/fastapi/fastapi/pull/15898) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for uk (update-outdated). PR [#15900](https://github.com/fastapi/fastapi/pull/15900) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for ko (update-outdated). PR [#15890](https://github.com/fastapi/fastapi/pull/15890) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for ru (update-outdated). PR [#15894](https://github.com/fastapi/fastapi/pull/15894) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for ko (add-missing). PR [#15888](https://github.com/fastapi/fastapi/pull/15888) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for es (add-missing). PR [#15880](https://github.com/fastapi/fastapi/pull/15880) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for zh-hant (add-missing). PR [#15889](https://github.com/fastapi/fastapi/pull/15889) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for pt (add-missing). PR [#15883](https://github.com/fastapi/fastapi/pull/15883) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for zh (add-missing). PR [#15885](https://github.com/fastapi/fastapi/pull/15885) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for ja (add-missing). PR [#15882](https://github.com/fastapi/fastapi/pull/15882) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for tr (add-missing). PR [#15887](https://github.com/fastapi/fastapi/pull/15887) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for uk (add-missing). PR [#15886](https://github.com/fastapi/fastapi/pull/15886) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for fr (add-missing). PR [#15881](https://github.com/fastapi/fastapi/pull/15881) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for de (add-missing). PR [#15884](https://github.com/fastapi/fastapi/pull/15884) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for ru (add-missing). PR [#15879](https://github.com/fastapi/fastapi/pull/15879) by [@tiangolo](https://github.com/tiangolo). + +### Internal + +* 👥 Update FastAPI People - Experts. PR [#15909](https://github.com/fastapi/fastapi/pull/15909) by [@tiangolo](https://github.com/tiangolo). +* 👥 Update FastAPI GitHub topic repositories. PR [#15906](https://github.com/fastapi/fastapi/pull/15906) by [@tiangolo](https://github.com/tiangolo). +* 👥 Update FastAPI People - Contributors and Translators. PR [#15878](https://github.com/fastapi/fastapi/pull/15878) by [@tiangolo](https://github.com/tiangolo). +* 👷 Remove not needed `allow-unsafe-pr-checkout: true`. PR [#15876](https://github.com/fastapi/fastapi/pull/15876) by [@YuriiMotov](https://github.com/YuriiMotov). +* ⬆ Bump the github-actions group with 5 updates. PR [#15872](https://github.com/fastapi/fastapi/pull/15872) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump the python-packages group across 1 directory with 10 updates. PR [#15870](https://github.com/fastapi/fastapi/pull/15870) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump CodSpeedHQ/action from 4.17.0 to 4.17.5 in the github-actions group. PR [#15826](https://github.com/fastapi/fastapi/pull/15826) by [@dependabot[bot]](https://github.com/apps/dependabot). + +## 0.138.2 (2026-06-29) + +### Refactors + +* ♻️ Make `app.frontend()` return 404 for methods other than `GET` or `HEAD` with no static file matches. PR [#15863](https://github.com/fastapi/fastapi/pull/15863) by [@tiangolo](https://github.com/tiangolo). + +### Internal + +* 🔧 Update sponsors: remove Stainless. PR [#15862](https://github.com/fastapi/fastapi/pull/15862) by [@tiangolo](https://github.com/tiangolo). +* ♻️ Refactor how sponsors data is handled for banners. PR [#15852](https://github.com/fastapi/fastapi/pull/15852) by [@tiangolo](https://github.com/tiangolo). + +## 0.138.1 (2026-06-25) + +### Refactors + +* ♻️ Refactor Library Skills, make info easier to find for agents. PR [#15841](https://github.com/fastapi/fastapi/pull/15841) by [@tiangolo](https://github.com/tiangolo). + +### Internal + +* 👷 Simplify pull request workflow triggers. PR [#15836](https://github.com/fastapi/fastapi/pull/15836) by [@tiangolo](https://github.com/tiangolo). +* 👷 Update issue-manager to 0.7.1. PR [#15833](https://github.com/fastapi/fastapi/pull/15833) by [@tiangolo](https://github.com/tiangolo). +* ⬆️ Update issue-manager to 0.7.0. PR [#15831](https://github.com/fastapi/fastapi/pull/15831) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Update sponsors: Add TestMu again. PR [#15830](https://github.com/fastapi/fastapi/pull/15830) by [@tiangolo](https://github.com/tiangolo). +* 🔒️ Update zizmor workflow security checks. PR [#15820](https://github.com/fastapi/fastapi/pull/15820) by [@tiangolo](https://github.com/tiangolo). +* ⬆ Bump pydantic-settings from 2.14.1 to 2.14.2. PR [#15799](https://github.com/fastapi/fastapi/pull/15799) by [@dependabot[bot]](https://github.com/apps/dependabot). + +## 0.138.0 (2026-06-20) + +### Features + +* ✨ Add support for `app.frontend("/", directory="dist")` and `router.frontend("/", directory="dist")`. PR [#15800](https://github.com/fastapi/fastapi/pull/15800) by [@tiangolo](https://github.com/tiangolo). + * Read the docs: [Frontend](https://fastapi.tiangolo.com/tutorial/frontend/). + +### Docs + +* 📝 Fix typo in release notes. PR [#15807](https://github.com/fastapi/fastapi/pull/15807) by [@tiangolo](https://github.com/tiangolo). +* 📝 Add `app.frontend()` instructions to Agent Library Skill. PR [#15805](https://github.com/fastapi/fastapi/pull/15805) by [@tiangolo](https://github.com/tiangolo). +* 📝 Update release notes link. PR [#15802](https://github.com/fastapi/fastapi/pull/15802) by [@tiangolo](https://github.com/tiangolo). +* ✏️ Update white space characters in bigger apps. PR [#15801](https://github.com/fastapi/fastapi/pull/15801) by [@tiangolo](https://github.com/tiangolo). +* ✏️ Fix grammar, typos, and broken links in docs. PR [#15694](https://github.com/fastapi/fastapi/pull/15694) by [@YuriiMotov](https://github.com/YuriiMotov). + +### Translations + +* 🌐 Enable Hindi docs translations. PR [#15554](https://github.com/fastapi/fastapi/pull/15554) by [@YuriiMotov](https://github.com/YuriiMotov). + +### Internal + +* 🐛 Fix failing test, update format for raised errors. PR [#15804](https://github.com/fastapi/fastapi/pull/15804) by [@tiangolo](https://github.com/tiangolo). +* 👷 Fix test-alls-green. PR [#15803](https://github.com/fastapi/fastapi/pull/15803) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Enable checking `release-notes.md` for typos. PR [#15796](https://github.com/fastapi/fastapi/pull/15796) by [@YuriiMotov](https://github.com/YuriiMotov). +* 📝 Tweak wording about deploying to FastAPI Cloud. PR [#15793](https://github.com/fastapi/fastapi/pull/15793) by [@tiangolo](https://github.com/tiangolo). +* 🔨 Use `gpt-5.5` model in `translate.py`, specify `-chat` to avoid warnings. PR [#15792](https://github.com/fastapi/fastapi/pull/15792) by [@YuriiMotov](https://github.com/YuriiMotov). + +## 0.137.2 (2026-06-18) + +### Features + +* ✨ Add `iter_route_contexts()` for advanced use cases that used to use `router.routes` (e.g. Jupyverse). PR [#15785](https://github.com/fastapi/fastapi/pull/15785) by [@tiangolo](https://github.com/tiangolo). + +### Translations + +* 🌐 Fix broken Markdown in Korean custom response docs. PR [#15774](https://github.com/fastapi/fastapi/pull/15774) by [@kooqooo](https://github.com/kooqooo). +* 🌐 Update translations for fr (update-outdated). PR [#15761](https://github.com/fastapi/fastapi/pull/15761) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for zh-hant (update-outdated). PR [#15760](https://github.com/fastapi/fastapi/pull/15760) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for de (update-outdated). PR [#15759](https://github.com/fastapi/fastapi/pull/15759) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for ko (update-outdated). PR [#15757](https://github.com/fastapi/fastapi/pull/15757) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for uk (update-outdated). PR [#15756](https://github.com/fastapi/fastapi/pull/15756) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for zh (update-outdated). PR [#15755](https://github.com/fastapi/fastapi/pull/15755) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for tr (update-outdated). PR [#15754](https://github.com/fastapi/fastapi/pull/15754) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for pt (update-outdated). PR [#15753](https://github.com/fastapi/fastapi/pull/15753) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for es (update-outdated). PR [#15752](https://github.com/fastapi/fastapi/pull/15752) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for ja (update-outdated). PR [#15751](https://github.com/fastapi/fastapi/pull/15751) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for ru (update-outdated). PR [#15758](https://github.com/fastapi/fastapi/pull/15758) by [@tiangolo](https://github.com/tiangolo). + +### Internal + +* 🔧 Update sponsors: add BairesDev. PR [#15787](https://github.com/fastapi/fastapi/pull/15787) by [@tiangolo](https://github.com/tiangolo). +* 🔨 Update sponsors script to simplify previews. PR [#15786](https://github.com/fastapi/fastapi/pull/15786) by [@tiangolo](https://github.com/tiangolo). +* ⬆ Bump the python-packages group across 1 directory with 7 updates. PR [#15777](https://github.com/fastapi/fastapi/pull/15777) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump cryptography from 46.0.7 to 48.0.1. PR [#15779](https://github.com/fastapi/fastapi/pull/15779) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump aiohttp from 3.14.0 to 3.14.1. PR [#15781](https://github.com/fastapi/fastapi/pull/15781) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump starlette from 1.2.1 to 1.3.1. PR [#15780](https://github.com/fastapi/fastapi/pull/15780) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump astral-sh/setup-uv from 8.1.0 to 8.2.0 in the github-actions group. PR [#15776](https://github.com/fastapi/fastapi/pull/15776) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump https://github.com/crate-ci/typos from v1.47.1 to v1.47.2 in the pre-commit group. PR [#15775](https://github.com/fastapi/fastapi/pull/15775) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump python-multipart from 0.0.30 to 0.0.32. PR [#15778](https://github.com/fastapi/fastapi/pull/15778) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⏪️ Revert removing scripts, only remove `coverage.sh`. PR [#15772](https://github.com/fastapi/fastapi/pull/15772) by [@tiangolo](https://github.com/tiangolo). +* 🔥 Remove unused scripts. PR [#15771](https://github.com/fastapi/fastapi/pull/15771) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Add ty configs to check docs sources. PR [#15770](https://github.com/fastapi/fastapi/pull/15770) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Add ty configs to check docs sources. PR [#15769](https://github.com/fastapi/fastapi/pull/15769) by [@tiangolo](https://github.com/tiangolo). + +## 0.137.1 (2026-06-15) + +### Fixes + +* 🚨 Fix typing checks for APIRoute. PR [#15765](https://github.com/fastapi/fastapi/pull/15765) by [@tiangolo](https://github.com/tiangolo). +* 🐛 Fix bug, allow empty path in path operation in prefixless router. PR [#15763](https://github.com/fastapi/fastapi/pull/15763) by [@tiangolo](https://github.com/tiangolo). + +## 0.137.0 (2026-06-14) + +### Breaking Changes + +* ♻️ Refactor internals to preserve `APIRouter` and `APIRoute` instances. PR [#15745](https://github.com/fastapi/fastapi/pull/15745) by [@tiangolo](https://github.com/tiangolo). + +Unblocks ✨ SO MANY THINGS ✨ + +Before this, `router.include_router(other_router)` would take each path operation from `other_router` and "clone" it, or recreate it from scratch. + +This would mean that in the end there was only one top level router, part of the app. + +The way it is structured here is that there are a few additional classes to handle intermediate metadata for router and route inclusion. That way the information of "router X includes Y and Y includes Z" is stored somewhere, without affecting (recreating / cloning) the final route. + +#### Non Objectives + +Dependencies for 404: previously I intended to support dependencies that would be executed even for 404, but that would conflict with the fact that a router could _not_ find a match, but the next router _did_ find a match. Executing dependencies in the router that did not find a match would not make sense, they could consume the request, body, etc. This original idea was discarded. + +#### Specific Breaking Changes + +Now `router.routes` is no longer a plain list of `APIRoute` objects, it can contain these intermediate objects that can contain additional routers, forming a tree. + +Any logic that depended on iterating on the `router.routes` directly would be affected, that logic cannot expect to be able to extract data from a plain list of routes, as it's no longer a plain list but a tree. + +Additionally, any logic that iterated on `router.routes` to modify them would now also see these new objects, and would not see all the routes in the app. + +`router.routes` should be considered an internal implementation detail, only passed around to the FastAPI functions that need it. + +#### Features + +* Adding routes (path operations) after a router is included now works, they are reflected as they are not copied. +* Including `subrouter` in `mainrouter` can be done before adding routes (path operations) to `subrouter`, because now the entire object is stored instead of copying the routes. +* As routes are not copied, in some cases that might save some memory. + +#### Alpha Features + +This is not documented yet, so it's not officially supported yet and could change in the future. + +But, as `APIRoute` and `APIRouter` instances are now preserved, they could be customized. + +`APIRouter` has two new methods, `.matches()` and `.handle()`, counterpart to the existing ones in `APIRoute`. With this a router could customize how it matches and handles requests. For example, it could match only requests that include some specific header, for example for handling versions in headers. + +Still, for now, consider this very experimental and potentially changing and breaking in the future. + +#### Future Features Enabled + +* Custom `APIRoute` subclasses (undocumented, but already works as described above) +* Custom `APIRouter` subclasses (undocumented, but already works as described above) +* Dependencies per router +* Exception handlers per router +* Middleware per router +* Other features planned + +### Docs + +* 📝 Update release notes. PR [#15747](https://github.com/fastapi/fastapi/pull/15747) by [@tiangolo](https://github.com/tiangolo). +* 📝 Update FastAPI Cloud deployment instructions. PR [#15724](https://github.com/fastapi/fastapi/pull/15724) by [@alejsdev](https://github.com/alejsdev). +* ✏️ Use `Annotated` in inline example in `docs/en/docs/tutorial/body-multiple-params.md`. PR [#15591](https://github.com/fastapi/fastapi/pull/15591) by [@TheArchons](https://github.com/TheArchons). +* 📝 Remove "NGINX Unit" from the list of ASGI-servers in docs. PR [#15475](https://github.com/fastapi/fastapi/pull/15475) by [@angryfoxx](https://github.com/angryfoxx). +* 📝 Update `docs/en/docs/tutorial/security/oauth2-jwt.md`. PR [#14781](https://github.com/fastapi/fastapi/pull/14781) by [@zadevhub](https://github.com/zadevhub). + +### Translations + +* 🌐 Update translations for zh-hant (update-outdated). PR [#15671](https://github.com/fastapi/fastapi/pull/15671) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for es (update-outdated). PR [#15670](https://github.com/fastapi/fastapi/pull/15670) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for fr (update-outdated). PR [#15669](https://github.com/fastapi/fastapi/pull/15669) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for ja (update-outdated). PR [#15668](https://github.com/fastapi/fastapi/pull/15668) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for pt (update-outdated). PR [#15667](https://github.com/fastapi/fastapi/pull/15667) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for tr (update-outdated). PR [#15666](https://github.com/fastapi/fastapi/pull/15666) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for zh (update-outdated). PR [#15665](https://github.com/fastapi/fastapi/pull/15665) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for ko (update-outdated). PR [#15664](https://github.com/fastapi/fastapi/pull/15664) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for de (update-outdated). PR [#15673](https://github.com/fastapi/fastapi/pull/15673) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for uk (update-outdated). PR [#15672](https://github.com/fastapi/fastapi/pull/15672) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for ru (update-outdated). PR [#15674](https://github.com/fastapi/fastapi/pull/15674) by [@tiangolo](https://github.com/tiangolo). + +### Internal + +* 🔧 Update sponsors: remove TalorData. PR [#15744](https://github.com/fastapi/fastapi/pull/15744) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Update sponsors: remove ExoFlare. PR [#15736](https://github.com/fastapi/fastapi/pull/15736) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Update sponsors: remove InterviewPal. PR [#15735](https://github.com/fastapi/fastapi/pull/15735) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Update sponsors: remove Liblab. PR [#15731](https://github.com/fastapi/fastapi/pull/15731) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Update sponsors: remove Scalar. PR [#15730](https://github.com/fastapi/fastapi/pull/15730) by [@tiangolo](https://github.com/tiangolo). +* ⬆ Bump the python-packages group across 1 directory with 6 updates. PR [#15721](https://github.com/fastapi/fastapi/pull/15721) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump python-multipart from 0.0.29 to 0.0.30. PR [#15723](https://github.com/fastapi/fastapi/pull/15723) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump the github-actions group with 3 updates. PR [#15720](https://github.com/fastapi/fastapi/pull/15720) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump starlette from 1.1.0 to 1.2.1. PR [#15722](https://github.com/fastapi/fastapi/pull/15722) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump https://github.com/crate-ci/typos from v1.46.0 to v1.47.1 in the pre-commit group. PR [#15719](https://github.com/fastapi/fastapi/pull/15719) by [@dependabot[bot]](https://github.com/apps/dependabot). +* 🔧 Update sponsors, add Rapidproxy. PR [#15689](https://github.com/fastapi/fastapi/pull/15689) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Update sponsors: Remove TestMu. PR [#15688](https://github.com/fastapi/fastapi/pull/15688) by [@tiangolo](https://github.com/tiangolo). +* ⬆ Bump the python-packages group across 1 directory with 11 updates. PR [#15683](https://github.com/fastapi/fastapi/pull/15683) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump aiohttp from 3.13.4 to 3.14.0. PR [#15681](https://github.com/fastapi/fastapi/pull/15681) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump the github-actions group with 2 updates. PR [#15682](https://github.com/fastapi/fastapi/pull/15682) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump starlette from 1.0.0 to 1.1.0. PR [#15684](https://github.com/fastapi/fastapi/pull/15684) by [@dependabot[bot]](https://github.com/apps/dependabot). +* 👥 Update FastAPI People - Experts. PR [#15677](https://github.com/fastapi/fastapi/pull/15677) by [@tiangolo](https://github.com/tiangolo). +* 👥 Update FastAPI GitHub topic repositories. PR [#15675](https://github.com/fastapi/fastapi/pull/15675) by [@tiangolo](https://github.com/tiangolo). +* 👥 Update FastAPI People - Contributors and Translators. PR [#15662](https://github.com/fastapi/fastapi/pull/15662) by [@tiangolo](https://github.com/tiangolo). +* 👷 Automate release preparation. PR [#15661](https://github.com/fastapi/fastapi/pull/15661) by [@tiangolo](https://github.com/tiangolo). +* 🔥 Remove slim package stub, deprecated for a while. PR [#15649](https://github.com/fastapi/fastapi/pull/15649) by [@tiangolo](https://github.com/tiangolo). +* ⬆ Bump authlib from 1.6.11 to 1.7.2. PR [#15512](https://github.com/fastapi/fastapi/pull/15512) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump pymdown-extensions from 10.21.2 to 10.21.3. PR [#15569](https://github.com/fastapi/fastapi/pull/15569) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump CodSpeedHQ/action from 4.14.0 to 4.15.1. PR [#15513](https://github.com/fastapi/fastapi/pull/15513) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump python-multipart from 0.0.26 to 0.0.29. PR [#15595](https://github.com/fastapi/fastapi/pull/15595) by [@dependabot[bot]](https://github.com/apps/dependabot). +* 🔒️ Improve GitHub actions security. PR [#15607](https://github.com/fastapi/fastapi/pull/15607) by [@YuriiMotov](https://github.com/YuriiMotov). +* ⚰️ Remove ruff and coverage ignores for non-existing files. PR [#15610](https://github.com/fastapi/fastapi/pull/15610) by [@YuriiMotov](https://github.com/YuriiMotov). +* ✅ Use custom `changing_dir` instead of `CLIRunner.isolated_filesystem` to set working dir. PR [#15616](https://github.com/fastapi/fastapi/pull/15616) by [@YuriiMotov](https://github.com/YuriiMotov). +* ✅ Add `httpx2` test dependency to avoid deprecation warning. PR [#15603](https://github.com/fastapi/fastapi/pull/15603) by [@YuriiMotov](https://github.com/YuriiMotov). +* ⬆ Bump the python-packages group with 15 updates. PR [#15594](https://github.com/fastapi/fastapi/pull/15594) by [@dependabot[bot]](https://github.com/apps/dependabot). +* 👷 Configure Dependabot to group updates and update weekly. PR [#15560](https://github.com/fastapi/fastapi/pull/15560) by [@YuriiMotov](https://github.com/YuriiMotov). + +## 0.136.3 (2026-05-23) + +### Refactors + +* ♻️ Do not accept underscore headers when using `convert_underscores=True` (the default). PR [#15589](https://github.com/fastapi/fastapi/pull/15589) by [@tiangolo](https://github.com/tiangolo). + +## 0.136.2 (2026-05-23) + +### Refactors + +* ♻️ Validate Server Sent Event fields to avoid applications from sending broken data. PR [#15588](https://github.com/fastapi/fastapi/pull/15588) by [@tiangolo](https://github.com/tiangolo). + +### Docs + +* 📝 Document `--entrypoint` CLI option. PR [#15464](https://github.com/fastapi/fastapi/pull/15464) by [@YuriiMotov](https://github.com/YuriiMotov). +* 📝 Update and simplify docs about help and management. PR [#15583](https://github.com/fastapi/fastapi/pull/15583) by [@tiangolo](https://github.com/tiangolo). +* 📝 Add docs references to central contributing docs. PR [#15580](https://github.com/fastapi/fastapi/pull/15580) by [@tiangolo](https://github.com/tiangolo). +* 📝 Update security policy. PR [#15577](https://github.com/fastapi/fastapi/pull/15577) by [@tiangolo](https://github.com/tiangolo). +* 🍱 Update sponsors: TalorData image. PR [#15562](https://github.com/fastapi/fastapi/pull/15562) by [@tiangolo](https://github.com/tiangolo). +* 📝 Update docs, simplify usage of admonitions, only default ones. PR [#15553](https://github.com/fastapi/fastapi/pull/15553) by [@tiangolo](https://github.com/tiangolo). +* 📝 Fix image URLs in `index.md`. PR [#15534](https://github.com/fastapi/fastapi/pull/15534) by [@YuriiMotov](https://github.com/YuriiMotov). +* ✏️ Fix Azkaban spelling typo in `virtual-environments.md‎`. PR [#15463](https://github.com/fastapi/fastapi/pull/15463) by [@isaacbernat](https://github.com/isaacbernat). +* 💄 Improve layout and styling. PR [#15462](https://github.com/fastapi/fastapi/pull/15462) by [@alejsdev](https://github.com/alejsdev). +* 💄 Refactor opinions section with interactive tabs and new logos. PR [#15458](https://github.com/fastapi/fastapi/pull/15458) by [@alejsdev](https://github.com/alejsdev). +* 📝 Add FastAPI Conf '26 announcement to docs. PR [#15457](https://github.com/fastapi/fastapi/pull/15457) by [@alejsdev](https://github.com/alejsdev). + +### Translations + +* 🌐 Improve translation consistency in `‎docs/pt/docs/advanced/generate-clients.md‎`. PR [#15456](https://github.com/fastapi/fastapi/pull/15456) by [@Will-thom](https://github.com/Will-thom). +* 🌐 Update translations for ja (update-outdated). PR [#15530](https://github.com/fastapi/fastapi/pull/15530) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for uk (update-outdated). PR [#15529](https://github.com/fastapi/fastapi/pull/15529) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for pt (update-outdated). PR [#15528](https://github.com/fastapi/fastapi/pull/15528) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for de (update-outdated). PR [#15527](https://github.com/fastapi/fastapi/pull/15527) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for tr (update-outdated). PR [#15526](https://github.com/fastapi/fastapi/pull/15526) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for ko (update-outdated). PR [#15525](https://github.com/fastapi/fastapi/pull/15525) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for zh-hant (update-outdated). PR [#15524](https://github.com/fastapi/fastapi/pull/15524) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for fr (update-outdated). PR [#15522](https://github.com/fastapi/fastapi/pull/15522) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for es (update-outdated). PR [#15523](https://github.com/fastapi/fastapi/pull/15523) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for zh (update-outdated). PR [#15520](https://github.com/fastapi/fastapi/pull/15520) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for ru (update-outdated). PR [#15521](https://github.com/fastapi/fastapi/pull/15521) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Fix typos in Spanish LLM-prompt. PR [#15472](https://github.com/fastapi/fastapi/pull/15472) by [@crr004](https://github.com/crr004). + +### Internal + +* ✅ Update tests, don't double dispose the engine. PR [#15587](https://github.com/fastapi/fastapi/pull/15587) by [@tiangolo](https://github.com/tiangolo). +* ⚡️ Speed up test suite via caching and fixture scopes to make it ~24% faster. PR [#13583](https://github.com/fastapi/fastapi/pull/13583) by [@dikos1337](https://github.com/dikos1337). +* 🔥 Remove config files now in central GitHub repo. PR [#15585](https://github.com/fastapi/fastapi/pull/15585) by [@tiangolo](https://github.com/tiangolo). +* ⬆ Bump urllib3 from 2.6.3 to 2.7.0. PR [#15502](https://github.com/fastapi/fastapi/pull/15502) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump idna from 3.11 to 3.15. PR [#15565](https://github.com/fastapi/fastapi/pull/15565) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump cloudflare/wrangler-action from 3.15.0 to 4.0.0. PR [#15571](https://github.com/fastapi/fastapi/pull/15571) by [@dependabot[bot]](https://github.com/apps/dependabot). +* 🔧 Migrate docs from MkDocs to Zensical. PR [#15563](https://github.com/fastapi/fastapi/pull/15563) by [@tiangolo](https://github.com/tiangolo). +* 🔒️ Only allow team members to modify dependencies. PR [#15548](https://github.com/fastapi/fastapi/pull/15548) by [@svlandeg](https://github.com/svlandeg). +* ⬆ Bump actions/add-to-project from 1.0.2 to 2.0.0. PR [#15490](https://github.com/fastapi/fastapi/pull/15490) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump actions/labeler from 6.0.1 to 6.1.0. PR [#15507](https://github.com/fastapi/fastapi/pull/15507) by [@dependabot[bot]](https://github.com/apps/dependabot). +* 🔧 Remove Ruff ignored rule for tabs. PR [#15533](https://github.com/fastapi/fastapi/pull/15533) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Update sponsors badge. PR [#15532](https://github.com/fastapi/fastapi/pull/15532) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Add sponsor: TalorData. PR [#15531](https://github.com/fastapi/fastapi/pull/15531) by [@tiangolo](https://github.com/tiangolo). +* ⬆ Bump ty from 0.0.21 to 0.0.34. PR [#15443](https://github.com/fastapi/fastapi/pull/15443) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump pydantic from 2.13.2 to 2.13.3. PR [#15444](https://github.com/fastapi/fastapi/pull/15444) by [@dependabot[bot]](https://github.com/apps/dependabot). +* 👷 Add pre-commit to check typos. PR [#15482](https://github.com/fastapi/fastapi/pull/15482) by [@tiangolo](https://github.com/tiangolo). +* 👥 Update FastAPI GitHub topic repositories. PR [#15470](https://github.com/fastapi/fastapi/pull/15470) by [@tiangolo](https://github.com/tiangolo). +* 👥 Update FastAPI People - Experts. PR [#15471](https://github.com/fastapi/fastapi/pull/15471) by [@tiangolo](https://github.com/tiangolo). +* 👥 Update FastAPI People - Contributors and Translators. PR [#15467](https://github.com/fastapi/fastapi/pull/15467) by [@tiangolo](https://github.com/tiangolo). +* 👷 Fix missing credentials issue in `translate` workflow. PR [#15468](https://github.com/fastapi/fastapi/pull/15468) by [@YuriiMotov](https://github.com/YuriiMotov). +* ⬆ Bump sqlmodel from 0.0.32 to 0.0.38. PR [#15437](https://github.com/fastapi/fastapi/pull/15437) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump CodSpeedHQ/action from 4.12.1 to 4.14.0. PR [#15436](https://github.com/fastapi/fastapi/pull/15436) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump pydantic from 2.12.5 to 2.13.2. PR [#15439](https://github.com/fastapi/fastapi/pull/15439) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump pydantic-ai from 1.63.0 to 1.83.0. PR [#15417](https://github.com/fastapi/fastapi/pull/15417) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump prek from 0.3.2 to 0.3.9. PR [#15418](https://github.com/fastapi/fastapi/pull/15418) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump fastar from 0.9.0 to 0.11.0. PR [#15419](https://github.com/fastapi/fastapi/pull/15419) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump astral-sh/setup-uv from 7.6.0 to 8.1.0. PR [#15415](https://github.com/fastapi/fastapi/pull/15415) by [@dependabot[bot]](https://github.com/apps/dependabot). + +## 0.136.1 (2026-04-23) + +### Upgrades + +* ⬆️ Update Pydantic v2 code to address deprecations. PR [#15101](https://github.com/fastapi/fastapi/pull/15101) by [@svlandeg](https://github.com/svlandeg). + +### Internal + +* 🔨 Tweak translation script. PR [#15174](https://github.com/fastapi/fastapi/pull/15174) by [@YuriiMotov](https://github.com/YuriiMotov). +* ⬆ Bump mkdocs-material from 9.7.1 to 9.7.6. PR [#15408](https://github.com/fastapi/fastapi/pull/15408) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump inline-snapshot from 0.31.1 to 0.32.6. PR [#15409](https://github.com/fastapi/fastapi/pull/15409) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump pytest-codspeed from 4.3.0 to 4.4.0. PR [#15407](https://github.com/fastapi/fastapi/pull/15407) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump pytest-cov from 7.0.0 to 7.1.0. PR [#15406](https://github.com/fastapi/fastapi/pull/15406) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump cloudflare/wrangler-action from 3.14.1 to 3.15.0. PR [#15405](https://github.com/fastapi/fastapi/pull/15405) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump mypy from 1.19.1 to 1.20.1. PR [#15410](https://github.com/fastapi/fastapi/pull/15410) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump python-dotenv from 1.2.1 to 1.2.2. PR [#15400](https://github.com/fastapi/fastapi/pull/15400) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump starlette from 0.52.1 to 1.0.0. PR [#15397](https://github.com/fastapi/fastapi/pull/15397) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump pygithub from 2.8.1 to 2.9.1. PR [#15396](https://github.com/fastapi/fastapi/pull/15396) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump pyjwt from 2.12.0 to 2.12.1. PR [#15393](https://github.com/fastapi/fastapi/pull/15393) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump zizmor from 1.23.1 to 1.24.1. PR [#15394](https://github.com/fastapi/fastapi/pull/15394) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump strawberry-graphql from 0.312.3 to 0.314.3. PR [#15395](https://github.com/fastapi/fastapi/pull/15395) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump python-multipart from 0.0.22 to 0.0.26. PR [#15360](https://github.com/fastapi/fastapi/pull/15360) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump authlib from 1.6.9 to 1.6.11. PR [#15373](https://github.com/fastapi/fastapi/pull/15373) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump aiohttp from 3.13.3 to 3.13.4. PR [#15282](https://github.com/fastapi/fastapi/pull/15282) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump pygments from 2.19.2 to 2.20.0. PR [#15263](https://github.com/fastapi/fastapi/pull/15263) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump pymdown-extensions from 10.20.1 to 10.21.2. PR [#15391](https://github.com/fastapi/fastapi/pull/15391) by [@YuriiMotov](https://github.com/YuriiMotov). +* ⬆ Bump pillow from 12.1.1 to 12.2.0. PR [#15333](https://github.com/fastapi/fastapi/pull/15333) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump pytest from 9.0.2 to 9.0.3. PR [#15334](https://github.com/fastapi/fastapi/pull/15334) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump actions/upload-artifact from 7.0.0 to 7.0.1. PR [#15374](https://github.com/fastapi/fastapi/pull/15374) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump actions/cache from 5.0.4 to 5.0.5. PR [#15385](https://github.com/fastapi/fastapi/pull/15385) by [@dependabot[bot]](https://github.com/apps/dependabot). +* 🔧 Update sponsors: remove Zuplo. PR [#15369](https://github.com/fastapi/fastapi/pull/15369) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Update sponsors: remove Speakeasy. PR [#15368](https://github.com/fastapi/fastapi/pull/15368) by [@tiangolo](https://github.com/tiangolo). +* 🔒️ Add zizmor and fix audit findings. PR [#15316](https://github.com/fastapi/fastapi/pull/15316) by [@YuriiMotov](https://github.com/YuriiMotov). + +## 0.136.0 (2026-04-16) + +### Upgrades + +* ⬆️ Support free-threaded Python 3.14t. PR [#15149](https://github.com/fastapi/fastapi/pull/15149) by [@svlandeg](https://github.com/svlandeg). + +## 0.135.4 (2026-04-16) + +### Refactors + +* 🔥 Remove April Fool's `@app.vibe()` 🤪. PR [#15363](https://github.com/fastapi/fastapi/pull/15363) by [@tiangolo](https://github.com/tiangolo). + +### Internal + +* ⬆ Bump cryptography from 46.0.5 to 46.0.7. PR [#15314](https://github.com/fastapi/fastapi/pull/15314) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump strawberry-graphql from 0.307.1 to 0.312.3. PR [#15309](https://github.com/fastapi/fastapi/pull/15309) by [@dependabot[bot]](https://github.com/apps/dependabot). +* 🔨 Add pre-commit hook to ensure latest release header has date. PR [#15293](https://github.com/fastapi/fastapi/pull/15293) by [@YuriiMotov](https://github.com/YuriiMotov). + +## 0.135.3 (2026-04-01) + +### Features + +* ✨ Add support for `@app.vibe()`. PR [#15280](https://github.com/fastapi/fastapi/pull/15280) by [@tiangolo](https://github.com/tiangolo). + * New docs: [Vibe Coding](https://fastapi.tiangolo.com/advanced/vibe/). + +### Docs + +* ✏️ Fix typo for `client_secret` in OAuth2 form docstrings. PR [#14946](https://github.com/fastapi/fastapi/pull/14946) by [@bysiber](https://github.com/bysiber). + +### Internal + +* 👥 Update FastAPI People - Experts. PR [#15279](https://github.com/fastapi/fastapi/pull/15279) by [@tiangolo](https://github.com/tiangolo). +* ⬆ Bump orjson from 3.11.7 to 3.11.8. PR [#15276](https://github.com/fastapi/fastapi/pull/15276) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump ruff from 0.15.0 to 0.15.8. PR [#15277](https://github.com/fastapi/fastapi/pull/15277) by [@dependabot[bot]](https://github.com/apps/dependabot). +* 👥 Update FastAPI GitHub topic repositories. PR [#15274](https://github.com/fastapi/fastapi/pull/15274) by [@tiangolo](https://github.com/tiangolo). +* ⬆ Bump fastmcp from 2.14.5 to 3.2.0. PR [#15267](https://github.com/fastapi/fastapi/pull/15267) by [@dependabot[bot]](https://github.com/apps/dependabot). +* 👥 Update FastAPI People - Contributors and Translators. PR [#15270](https://github.com/fastapi/fastapi/pull/15270) by [@tiangolo](https://github.com/tiangolo). +* ⬆ Bump requests from 2.32.5 to 2.33.0. PR [#15228](https://github.com/fastapi/fastapi/pull/15228) by [@dependabot[bot]](https://github.com/apps/dependabot). +* 👷 Add ty check to `lint.sh`. PR [#15136](https://github.com/fastapi/fastapi/pull/15136) by [@svlandeg](https://github.com/svlandeg). + +## 0.135.2 (2026-03-01) + +### Upgrades + +* ⬆️ Increase lower bound to `pydantic >=2.9.0.` and fix the test suite. PR [#15139](https://github.com/fastapi/fastapi/pull/15139) by [@svlandeg](https://github.com/svlandeg). + +### Docs + +* 📝 Add missing last release notes dates. PR [#15202](https://github.com/fastapi/fastapi/pull/15202) by [@tiangolo](https://github.com/tiangolo). +* 📝 Update docs for contributors and team members regarding translation PRs. PR [#15200](https://github.com/fastapi/fastapi/pull/15200) by [@YuriiMotov](https://github.com/YuriiMotov). +* 💄 Fix code blocks in reference docs overflowing table width. PR [#15094](https://github.com/fastapi/fastapi/pull/15094) by [@YuriiMotov](https://github.com/YuriiMotov). +* 📝 Fix duplicated words in docstrings. PR [#15116](https://github.com/fastapi/fastapi/pull/15116) by [@AhsanSheraz](https://github.com/AhsanSheraz). +* 📝 Add docs for `pyproject.toml` with `entrypoint`. PR [#15075](https://github.com/fastapi/fastapi/pull/15075) by [@tiangolo](https://github.com/tiangolo). +* 📝 Update links in docs to no longer use the classes external-link and internal-link. PR [#15061](https://github.com/fastapi/fastapi/pull/15061) by [@tiangolo](https://github.com/tiangolo). +* 🔨 Add JS and CSS handling for automatic `target=_blank` for links in docs. PR [#15063](https://github.com/fastapi/fastapi/pull/15063) by [@tiangolo](https://github.com/tiangolo). +* 💄 Update styles for internal and external links in new tab. PR [#15058](https://github.com/fastapi/fastapi/pull/15058) by [@tiangolo](https://github.com/tiangolo). +* 📝 Add documentation for the FastAPI VS Code extension. PR [#15008](https://github.com/fastapi/fastapi/pull/15008) by [@savannahostrowski](https://github.com/savannahostrowski). +* 📝 Fix doctrings for `max_digits` and `decimal_places`. PR [#14944](https://github.com/fastapi/fastapi/pull/14944) by [@YuriiMotov](https://github.com/YuriiMotov). +* 📝 Add dates to release notes. PR [#15001](https://github.com/fastapi/fastapi/pull/15001) by [@YuriiMotov](https://github.com/YuriiMotov). + +### Translations + +* 🌐 Update translations for zh (update-outdated). PR [#15177](https://github.com/fastapi/fastapi/pull/15177) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for zh-hant (update-outdated). PR [#15178](https://github.com/fastapi/fastapi/pull/15178) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for zh-hant (add-missing). PR [#15176](https://github.com/fastapi/fastapi/pull/15176) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for zh (add-missing). PR [#15175](https://github.com/fastapi/fastapi/pull/15175) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for ja (update-outdated). PR [#15171](https://github.com/fastapi/fastapi/pull/15171) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for ko (update-outdated). PR [#15170](https://github.com/fastapi/fastapi/pull/15170) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for tr (update-outdated). PR [#15172](https://github.com/fastapi/fastapi/pull/15172) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for ko (add-missing). PR [#15168](https://github.com/fastapi/fastapi/pull/15168) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for ja (add-missing). PR [#15167](https://github.com/fastapi/fastapi/pull/15167) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for tr (add-missing). PR [#15169](https://github.com/fastapi/fastapi/pull/15169) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for fr (update-outdated). PR [#15165](https://github.com/fastapi/fastapi/pull/15165) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for fr (add-missing). PR [#15163](https://github.com/fastapi/fastapi/pull/15163) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for uk (update-outdated). PR [#15160](https://github.com/fastapi/fastapi/pull/15160) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for uk (add-missing). PR [#15158](https://github.com/fastapi/fastapi/pull/15158) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for pt (add-missing). PR [#15157](https://github.com/fastapi/fastapi/pull/15157) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for pt (update-outdated). PR [#15159](https://github.com/fastapi/fastapi/pull/15159) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for es (update-outdated). PR [#15155](https://github.com/fastapi/fastapi/pull/15155) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for es (add-missing). PR [#15154](https://github.com/fastapi/fastapi/pull/15154) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for de (update-outdated). PR [#15156](https://github.com/fastapi/fastapi/pull/15156) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for ru (update-and-add). PR [#15152](https://github.com/fastapi/fastapi/pull/15152) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for de (add-missing). PR [#15153](https://github.com/fastapi/fastapi/pull/15153) by [@tiangolo](https://github.com/tiangolo). + +### Internal + +* 🔨 Exclude spam comments from statistics in `scripts/people.py`. PR [#15088](https://github.com/fastapi/fastapi/pull/15088) by [@YuriiMotov](https://github.com/YuriiMotov). +* ⬆ Bump authlib from 1.6.7 to 1.6.9. PR [#15128](https://github.com/fastapi/fastapi/pull/15128) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump pyasn1 from 0.6.2 to 0.6.3. PR [#15143](https://github.com/fastapi/fastapi/pull/15143) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump ujson from 5.11.0 to 5.12.0. PR [#15150](https://github.com/fastapi/fastapi/pull/15150) by [@dependabot[bot]](https://github.com/apps/dependabot). +* 🔨 Tweak translation workflow and translation fixer tool. PR [#15166](https://github.com/fastapi/fastapi/pull/15166) by [@YuriiMotov](https://github.com/YuriiMotov). +* 🔨 Fix `commit_in_place` passed via env variable in `translate.yml` workflow. PR [#15151](https://github.com/fastapi/fastapi/pull/15151) by [@YuriiMotov](https://github.com/YuriiMotov). +* 🔨 Update translation general prompt to enforce link style in translation matches the original link style. PR [#15148](https://github.com/fastapi/fastapi/pull/15148) by [@YuriiMotov](https://github.com/YuriiMotov). +* 👷 Re-enable translation workflow run by cron in CI (twice a month). PR [#15145](https://github.com/fastapi/fastapi/pull/15145) by [@YuriiMotov](https://github.com/YuriiMotov). +* 👷 Add `ty` to precommit. PR [#15091](https://github.com/fastapi/fastapi/pull/15091) by [@svlandeg](https://github.com/svlandeg). +* ⬆ Bump dorny/paths-filter from 3 to 4. PR [#15106](https://github.com/fastapi/fastapi/pull/15106) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump cairosvg from 2.8.2 to 2.9.0. PR [#15108](https://github.com/fastapi/fastapi/pull/15108) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump pyjwt from 2.11.0 to 2.12.0. PR [#15110](https://github.com/fastapi/fastapi/pull/15110) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump black from 26.1.0 to 26.3.1. PR [#15100](https://github.com/fastapi/fastapi/pull/15100) by [@dependabot[bot]](https://github.com/apps/dependabot). +* 🔨 Update script to autofix permalinks to account for headers with Markdown links. PR [#15062](https://github.com/fastapi/fastapi/pull/15062) by [@tiangolo](https://github.com/tiangolo). +* 📌 Pin Click for MkDocs live reload. PR [#15057](https://github.com/fastapi/fastapi/pull/15057) by [@tiangolo](https://github.com/tiangolo). +* ⬆ Bump werkzeug from 3.1.5 to 3.1.6. PR [#14948](https://github.com/fastapi/fastapi/pull/14948) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump pydantic-ai from 1.62.0 to 1.63.0. PR [#15035](https://github.com/fastapi/fastapi/pull/15035) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump pytest-codspeed from 4.2.0 to 4.3.0. PR [#15034](https://github.com/fastapi/fastapi/pull/15034) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump strawberry-graphql from 0.291.2 to 0.307.1. PR [#15033](https://github.com/fastapi/fastapi/pull/15033) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump typer from 0.21.1 to 0.24.1. PR [#15032](https://github.com/fastapi/fastapi/pull/15032) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump actions/download-artifact from 7 to 8. PR [#15020](https://github.com/fastapi/fastapi/pull/15020) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump actions/upload-artifact from 6 to 7. PR [#15019](https://github.com/fastapi/fastapi/pull/15019) by [@dependabot[bot]](https://github.com/apps/dependabot). + +## 0.135.1 (2026-03-01) + +### Fixes + +* 🐛 Fix, avoid yield from a TaskGroup, only as an async context manager, closed in the request async exit stack. PR [#15038](https://github.com/fastapi/fastapi/pull/15038) by [@tiangolo](https://github.com/tiangolo). + +### Docs + +* ✏️ Fix typo in `docs/en/docs/_llm-test.md`. PR [#15007](https://github.com/fastapi/fastapi/pull/15007) by [@adityagiri3600](https://github.com/adityagiri3600). +* 📝 Update Skill, optimize context, trim and refactor into references. PR [#15031](https://github.com/fastapi/fastapi/pull/15031) by [@tiangolo](https://github.com/tiangolo). + +### Internal + +* 👥 Update FastAPI People - Experts. PR [#15037](https://github.com/fastapi/fastapi/pull/15037) by [@tiangolo](https://github.com/tiangolo). +* 👥 Update FastAPI People - Contributors and Translators. PR [#15029](https://github.com/fastapi/fastapi/pull/15029) by [@tiangolo](https://github.com/tiangolo). +* 👥 Update FastAPI GitHub topic repositories. PR [#15036](https://github.com/fastapi/fastapi/pull/15036) by [@tiangolo](https://github.com/tiangolo). + +## 0.135.0 (2026-03-01) + +### Features + +* ✨ Add support for Server Sent Events. PR [#15030](https://github.com/fastapi/fastapi/pull/15030) by [@tiangolo](https://github.com/tiangolo). + * New docs: [Server-Sent Events (SSE)](https://fastapi.tiangolo.com/tutorial/server-sent-events/). + +## 0.134.0 (2026-02-27) + +### Features + +* ✨ Add support for streaming JSON Lines and binary data with `yield`. PR [#15022](https://github.com/fastapi/fastapi/pull/15022) by [@tiangolo](https://github.com/tiangolo). + * This also upgrades Starlette from `>=0.40.0` to `>=0.46.0`, as it's needed to properly unwrap and re-raise exceptions from exception groups. + * New docs: [Stream JSON Lines](https://fastapi.tiangolo.com/tutorial/stream-json-lines/). + * And new docs: [Stream Data](https://fastapi.tiangolo.com/advanced/stream-data/). + +### Docs + +* 📝 Update Library Agent Skill with streaming responses. PR [#15024](https://github.com/fastapi/fastapi/pull/15024) by [@tiangolo](https://github.com/tiangolo). +* 📝 Update docs for responses and new stream with `yield`. PR [#15023](https://github.com/fastapi/fastapi/pull/15023) by [@tiangolo](https://github.com/tiangolo). +* 📝 Add `await` in `StreamingResponse` code example to allow cancellation. PR [#14681](https://github.com/fastapi/fastapi/pull/14681) by [@casperdcl](https://github.com/casperdcl). +* 📝 Rename `docs_src/websockets` to `docs_src/websockets_` to avoid import errors. PR [#14979](https://github.com/fastapi/fastapi/pull/14979) by [@YuriiMotov](https://github.com/YuriiMotov). + +### Internal + +* 🔨 Run tests with `pytest-xdist` and `pytest-cov`. PR [#14992](https://github.com/fastapi/fastapi/pull/14992) by [@YuriiMotov](https://github.com/YuriiMotov). + +## 0.133.1 (2026-02-25) + +### Features + +* 🔧 Add FastAPI Agents Skill. PR [#14982](https://github.com/fastapi/fastapi/pull/14982) by [@tiangolo](https://github.com/tiangolo). + * Read more about it in [Library Agent Skills](https://tiangolo.com/ideas/library-agent-skills/). + +### Internal + +* ✅ Fix all tests are skipped on Windows. PR [#14994](https://github.com/fastapi/fastapi/pull/14994) by [@YuriiMotov](https://github.com/YuriiMotov). + +## 0.133.0 (2026-02-24) + +### Upgrades + +* ⬆️ Add support for Starlette 1.0.0+. PR [#14987](https://github.com/fastapi/fastapi/pull/14987) by [@tiangolo](https://github.com/tiangolo). + +## 0.132.1 (2026-02-24) + +### Refactors + +* ♻️ Refactor logic to handle OpenAPI and Swagger UI escaping data. PR [#14986](https://github.com/fastapi/fastapi/pull/14986) by [@tiangolo](https://github.com/tiangolo). + +### Internal + +* 👥 Update FastAPI People - Experts. PR [#14972](https://github.com/fastapi/fastapi/pull/14972) by [@tiangolo](https://github.com/tiangolo). +* 👷 Allow skipping `benchmark` job in `test` workflow. PR [#14974](https://github.com/fastapi/fastapi/pull/14974) by [@YuriiMotov](https://github.com/YuriiMotov). + +## 0.132.0 (2026-02-23) + +### Breaking Changes + +* 🔒️ Add `strict_content_type` checking for JSON requests. PR [#14978](https://github.com/fastapi/fastapi/pull/14978) by [@tiangolo](https://github.com/tiangolo). + * Now FastAPI checks, by default, that JSON requests have a `Content-Type` header with a valid JSON value, like `application/json`, and rejects requests that don't. + * If the clients for your app don't send a valid `Content-Type` header you can disable this with `strict_content_type=False`. + * Check the new docs: [Strict Content-Type Checking](https://fastapi.tiangolo.com/advanced/strict-content-type/). + +### Internal + +* ⬆ Bump flask from 3.1.2 to 3.1.3. PR [#14949](https://github.com/fastapi/fastapi/pull/14949) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Update all dependencies to use `griffelib` instead of `griffe`. PR [#14973](https://github.com/fastapi/fastapi/pull/14973) by [@svlandeg](https://github.com/svlandeg). +* 🔨 Fix `FastAPI People` workflow. PR [#14951](https://github.com/fastapi/fastapi/pull/14951) by [@YuriiMotov](https://github.com/YuriiMotov). +* 👷 Do not run codspeed with coverage as it's not tracked. PR [#14966](https://github.com/fastapi/fastapi/pull/14966) by [@tiangolo](https://github.com/tiangolo). +* 👷 Do not include benchmark tests in coverage to speed up coverage processing. PR [#14965](https://github.com/fastapi/fastapi/pull/14965) by [@tiangolo](https://github.com/tiangolo). + +## 0.131.0 (2026-02-22) + +### Breaking Changes + +* 🗑️ Deprecate `ORJSONResponse` and `UJSONResponse`. PR [#14964](https://github.com/fastapi/fastapi/pull/14964) by [@tiangolo](https://github.com/tiangolo). + +## 0.130.0 (2026-02-22) + +### Features + +* ✨ Serialize JSON response with Pydantic (in Rust), when there's a Pydantic return type or response model. PR [#14962](https://github.com/fastapi/fastapi/pull/14962) by [@tiangolo](https://github.com/tiangolo). + * This results in 2x (or more) performance increase for JSON responses. + * New docs: [Custom Response - JSON Performance](https://fastapi.tiangolo.com/advanced/custom-response/#json-performance). + +## 0.129.2 (2026-02-21) + +### Internal + +* ⬆️ Upgrade pytest. PR [#14959](https://github.com/fastapi/fastapi/pull/14959) by [@tiangolo](https://github.com/tiangolo). +* 👷 Fix CI, do not attempt to publish `fastapi-slim`. PR [#14958](https://github.com/fastapi/fastapi/pull/14958) by [@tiangolo](https://github.com/tiangolo). +* ➖ Drop support for `fastapi-slim`, no more versions will be released, use only `"fastapi[standard]"` or `fastapi`. PR [#14957](https://github.com/fastapi/fastapi/pull/14957) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Update pyproject.toml, remove unneeded lines. PR [#14956](https://github.com/fastapi/fastapi/pull/14956) by [@tiangolo](https://github.com/tiangolo). + +## 0.129.1 (2026-02-21) + +### Fixes + +* ♻️ Fix JSON Schema for bytes, use `"contentMediaType": "application/octet-stream"` instead of `"format": "binary"`. PR [#14953](https://github.com/fastapi/fastapi/pull/14953) by [@tiangolo](https://github.com/tiangolo). + +### Docs + +* 🔨 Add Kapa.ai widget (AI chatbot). PR [#14938](https://github.com/fastapi/fastapi/pull/14938) by [@tiangolo](https://github.com/tiangolo). +* 🔥 Remove Python 3.9 specific files, no longer needed after updating translations. PR [#14931](https://github.com/fastapi/fastapi/pull/14931) by [@tiangolo](https://github.com/tiangolo). +* 📝 Update docs for JWT to prevent timing attacks. PR [#14908](https://github.com/fastapi/fastapi/pull/14908) by [@tiangolo](https://github.com/tiangolo). + +### Translations + +* ✏️ Fix several typos in ru translations. PR [#14934](https://github.com/fastapi/fastapi/pull/14934) by [@argoarsiks](https://github.com/argoarsiks). +* 🌐 Update translations for ko (update-all and add-missing). PR [#14923](https://github.com/fastapi/fastapi/pull/14923) by [@YuriiMotov](https://github.com/YuriiMotov). +* 🌐 Update translations for uk (add-missing). PR [#14922](https://github.com/fastapi/fastapi/pull/14922) by [@YuriiMotov](https://github.com/YuriiMotov). +* 🌐 Update translations for zh-hant (update-all and add-missing). PR [#14921](https://github.com/fastapi/fastapi/pull/14921) by [@YuriiMotov](https://github.com/YuriiMotov). +* 🌐 Update translations for fr (update-all and add-missing). PR [#14920](https://github.com/fastapi/fastapi/pull/14920) by [@YuriiMotov](https://github.com/YuriiMotov). +* 🌐 Update translations for de (update-all) . PR [#14910](https://github.com/fastapi/fastapi/pull/14910) by [@YuriiMotov](https://github.com/YuriiMotov). +* 🌐 Update translations for ja (update-all). PR [#14916](https://github.com/fastapi/fastapi/pull/14916) by [@YuriiMotov](https://github.com/YuriiMotov). +* 🌐 Update translations for pt (update-all). PR [#14912](https://github.com/fastapi/fastapi/pull/14912) by [@YuriiMotov](https://github.com/YuriiMotov). +* 🌐 Update translations for es (update-all and add-missing). PR [#14911](https://github.com/fastapi/fastapi/pull/14911) by [@YuriiMotov](https://github.com/YuriiMotov). +* 🌐 Update translations for zh (update-all). PR [#14917](https://github.com/fastapi/fastapi/pull/14917) by [@YuriiMotov](https://github.com/YuriiMotov). +* 🌐 Update translations for uk (update-all). PR [#14914](https://github.com/fastapi/fastapi/pull/14914) by [@YuriiMotov](https://github.com/YuriiMotov). +* 🌐 Update translations for tr (update-all). PR [#14913](https://github.com/fastapi/fastapi/pull/14913) by [@YuriiMotov](https://github.com/YuriiMotov). +* 🌐 Update translations for ru (update-outdated). PR [#14909](https://github.com/fastapi/fastapi/pull/14909) by [@YuriiMotov](https://github.com/YuriiMotov). + +### Internal + +* 👷 Always run tests on push to `master` branch and when run by scheduler. PR [#14940](https://github.com/fastapi/fastapi/pull/14940) by [@YuriiMotov](https://github.com/YuriiMotov). +* 🎨 Upgrade typing syntax for Python 3.10. PR [#14932](https://github.com/fastapi/fastapi/pull/14932) by [@tiangolo](https://github.com/tiangolo). +* ⬆ Bump cryptography from 46.0.4 to 46.0.5. PR [#14892](https://github.com/fastapi/fastapi/pull/14892) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump pillow from 12.1.0 to 12.1.1. PR [#14899](https://github.com/fastapi/fastapi/pull/14899) by [@dependabot[bot]](https://github.com/apps/dependabot). + +## 0.129.0 (2026-02-12) + +### Breaking Changes + +* ➖ Drop support for Python 3.9. PR [#14897](https://github.com/fastapi/fastapi/pull/14897) by [@tiangolo](https://github.com/tiangolo). + +### Refactors + +* 🎨 Update internal types for Python 3.10. PR [#14898](https://github.com/fastapi/fastapi/pull/14898) by [@tiangolo](https://github.com/tiangolo). + +### Docs + +* 📝 Update highlights in webhooks docs. PR [#14905](https://github.com/fastapi/fastapi/pull/14905) by [@tiangolo](https://github.com/tiangolo). +* 📝 Update source examples and docs from Python 3.9 to 3.10. PR [#14900](https://github.com/fastapi/fastapi/pull/14900) by [@tiangolo](https://github.com/tiangolo). + +### Internal + +* 🔨 Update docs.py scripts to migrate Python 3.9 to Python 3.10. PR [#14906](https://github.com/fastapi/fastapi/pull/14906) by [@tiangolo](https://github.com/tiangolo). + +## 0.128.8 (2026-02-11) + +### Docs + +* 📝 Fix grammar in `docs/en/docs/tutorial/first-steps.md`. PR [#14708](https://github.com/fastapi/fastapi/pull/14708) by [@SanjanaS10](https://github.com/SanjanaS10). + +### Internal + +* 🔨 Tweak PDM hook script. PR [#14895](https://github.com/fastapi/fastapi/pull/14895) by [@tiangolo](https://github.com/tiangolo). +* ♻️ Update build setup for `fastapi-slim`, deprecate it, and make it only depend on `fastapi`. PR [#14894](https://github.com/fastapi/fastapi/pull/14894) by [@tiangolo](https://github.com/tiangolo). + +## 0.128.7 (2026-02-10) + +### Features + +* ✨ Show a clear error on attempt to include router into itself. PR [#14258](https://github.com/fastapi/fastapi/pull/14258) by [@JavierSanchezCastro](https://github.com/JavierSanchezCastro). +* ✨ Replace `dict` by `Mapping` on `HTTPException.headers`. PR [#12997](https://github.com/fastapi/fastapi/pull/12997) by [@rijenkii](https://github.com/rijenkii). + +### Refactors + +* ♻️ Simplify reading files in memory, do it sequentially instead of (fake) parallel. PR [#14884](https://github.com/fastapi/fastapi/pull/14884) by [@tiangolo](https://github.com/tiangolo). + +### Docs + +* 📝 Use `dfn` tag for definitions instead of `abbr` in docs. PR [#14744](https://github.com/fastapi/fastapi/pull/14744) by [@YuriiMotov](https://github.com/YuriiMotov). + +### Internal + +* ✅ Tweak comment in test to reference PR. PR [#14885](https://github.com/fastapi/fastapi/pull/14885) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Update LLM-prompt for `abbr` and `dfn` tags. PR [#14747](https://github.com/fastapi/fastapi/pull/14747) by [@YuriiMotov](https://github.com/YuriiMotov). +* ✅ Test order for the submitted byte Files. PR [#14828](https://github.com/fastapi/fastapi/pull/14828) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). +* 🔧 Configure `test` workflow to run tests with `inline-snapshot=review`. PR [#14876](https://github.com/fastapi/fastapi/pull/14876) by [@YuriiMotov](https://github.com/YuriiMotov). + +## 0.128.6 (2026-02-09) + +### Fixes + +* 🐛 Fix `on_startup` and `on_shutdown` parameters of `APIRouter`. PR [#14873](https://github.com/fastapi/fastapi/pull/14873) by [@YuriiMotov](https://github.com/YuriiMotov). + +### Translations + +* 🌐 Update translations for zh (update-outdated). PR [#14843](https://github.com/fastapi/fastapi/pull/14843) by [@tiangolo](https://github.com/tiangolo). + +### Internal + +* ✅ Fix parameterized tests with snapshots. PR [#14875](https://github.com/fastapi/fastapi/pull/14875) by [@YuriiMotov](https://github.com/YuriiMotov). + +## 0.128.5 (2026-02-08) + +### Refactors + +* ♻️ Refactor and simplify Pydantic v2 (and v1) compatibility internal utils. PR [#14862](https://github.com/fastapi/fastapi/pull/14862) by [@tiangolo](https://github.com/tiangolo). + +### Internal + +* ✅ Add inline snapshot tests for OpenAPI before changes from Pydantic v2. PR [#14864](https://github.com/fastapi/fastapi/pull/14864) by [@tiangolo](https://github.com/tiangolo). + +## 0.128.4 (2026-02-07) + +### Refactors + +* ♻️ Refactor internals, simplify Pydantic v2/v1 utils, `create_model_field`, better types for `lenient_issubclass`. PR [#14860](https://github.com/fastapi/fastapi/pull/14860) by [@tiangolo](https://github.com/tiangolo). +* ♻️ Simplify internals, remove Pydantic v1 only logic, no longer needed. PR [#14857](https://github.com/fastapi/fastapi/pull/14857) by [@tiangolo](https://github.com/tiangolo). +* ♻️ Refactor internals, cleanup unneeded Pydantic v1 specific logic. PR [#14856](https://github.com/fastapi/fastapi/pull/14856) by [@tiangolo](https://github.com/tiangolo). + +### Translations + +* 🌐 Update translations for fr (outdated pages). PR [#14839](https://github.com/fastapi/fastapi/pull/14839) by [@YuriiMotov](https://github.com/YuriiMotov). +* 🌐 Update translations for tr (outdated and missing). PR [#14838](https://github.com/fastapi/fastapi/pull/14838) by [@YuriiMotov](https://github.com/YuriiMotov). + +### Internal + +* ⬆️ Upgrade development dependencies. PR [#14854](https://github.com/fastapi/fastapi/pull/14854) by [@tiangolo](https://github.com/tiangolo). + +## 0.128.3 (2026-02-06) + +### Refactors + +* ♻️ Re-implement `on_event` in FastAPI for compatibility with the next Starlette, while keeping backwards compatibility. PR [#14851](https://github.com/fastapi/fastapi/pull/14851) by [@tiangolo](https://github.com/tiangolo). + +### Upgrades + +* ⬆️ Upgrade Starlette supported version range to `starlette>=0.40.0,<1.0.0`. PR [#14853](https://github.com/fastapi/fastapi/pull/14853) by [@tiangolo](https://github.com/tiangolo). + +### Translations + +* 🌐 Update translations for ru (update-outdated). PR [#14834](https://github.com/fastapi/fastapi/pull/14834) by [@tiangolo](https://github.com/tiangolo). + +### Internal + +* 👷 Run tests with Starlette from git. PR [#14849](https://github.com/fastapi/fastapi/pull/14849) by [@tiangolo](https://github.com/tiangolo). +* 👷 Run tests with lower bound uv sync, upgrade `fastapi[all]` minimum dependencies: `ujson >=5.8.0`, `orjson >=3.9.3`. PR [#14846](https://github.com/fastapi/fastapi/pull/14846) by [@tiangolo](https://github.com/tiangolo). + +## 0.128.2 (2026-02-05) + +### Features + +* ✨ Add support for PEP695 `TypeAliasType`. PR [#13920](https://github.com/fastapi/fastapi/pull/13920) by [@cstruct](https://github.com/cstruct). +* ✨ Allow `Response` type hint as dependency annotation. PR [#14794](https://github.com/fastapi/fastapi/pull/14794) by [@jonathan-fulton](https://github.com/jonathan-fulton). + +### Fixes + +* 🐛 Fix using `Json[list[str]]` type (issue #10997). PR [#14616](https://github.com/fastapi/fastapi/pull/14616) by [@mkanetsuna](https://github.com/mkanetsuna). + +### Docs + +* 📝 Update docs for translations. PR [#14830](https://github.com/fastapi/fastapi/pull/14830) by [@tiangolo](https://github.com/tiangolo). +* 📝 Fix duplicate word in `advanced-dependencies.md`. PR [#14815](https://github.com/fastapi/fastapi/pull/14815) by [@Rayyan-Oumlil](https://github.com/Rayyan-Oumlil). + +### Translations + +* 🌐 Enable Traditional Chinese translations. PR [#14842](https://github.com/fastapi/fastapi/pull/14842) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Enable French docs translations. PR [#14841](https://github.com/fastapi/fastapi/pull/14841) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for fr (translate-page). PR [#14837](https://github.com/fastapi/fastapi/pull/14837) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for de (update-outdated). PR [#14836](https://github.com/fastapi/fastapi/pull/14836) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for pt (update-outdated). PR [#14833](https://github.com/fastapi/fastapi/pull/14833) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for ko (update-outdated). PR [#14835](https://github.com/fastapi/fastapi/pull/14835) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for es (update-outdated). PR [#14832](https://github.com/fastapi/fastapi/pull/14832) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for tr (update-outdated). PR [#14831](https://github.com/fastapi/fastapi/pull/14831) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for tr (add-missing). PR [#14790](https://github.com/fastapi/fastapi/pull/14790) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for fr (update-outdated). PR [#14826](https://github.com/fastapi/fastapi/pull/14826) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for zh-hant (update-outdated). PR [#14825](https://github.com/fastapi/fastapi/pull/14825) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for uk (update-outdated). PR [#14822](https://github.com/fastapi/fastapi/pull/14822) by [@tiangolo](https://github.com/tiangolo). +* 🔨 Update docs and translations scripts, enable Turkish. PR [#14824](https://github.com/fastapi/fastapi/pull/14824) by [@tiangolo](https://github.com/tiangolo). + +### Internal + +* 🔨 Add max pages to translate to configs. PR [#14840](https://github.com/fastapi/fastapi/pull/14840) by [@tiangolo](https://github.com/tiangolo). + +## 0.128.1 (2026-02-04) + +### Features + +* ✨ Add `viewport` meta tag to improve Swagger UI on mobile devices. PR [#14777](https://github.com/fastapi/fastapi/pull/14777) by [@Joab0](https://github.com/Joab0). +* 🚸 Improve error message for invalid query parameter type annotations. PR [#14479](https://github.com/fastapi/fastapi/pull/14479) by [@retwish](https://github.com/retwish). + +### Fixes + +* 🐛 Update `ValidationError` schema to include `input` and `ctx`. PR [#14791](https://github.com/fastapi/fastapi/pull/14791) by [@jonathan-fulton](https://github.com/jonathan-fulton). +* 🐛 Fix TYPE_CHECKING annotations for Python 3.14 (PEP 649). PR [#14789](https://github.com/fastapi/fastapi/pull/14789) by [@mgu](https://github.com/mgu). +* 🐛 Strip whitespaces from `Authorization` header credentials. PR [#14786](https://github.com/fastapi/fastapi/pull/14786) by [@WaveTheory1](https://github.com/WaveTheory1). +* 🐛 Fix OpenAPI duplication of `anyOf` refs for app-level responses with specified `content` and `model` as `Union`. PR [#14463](https://github.com/fastapi/fastapi/pull/14463) by [@DJMcoder](https://github.com/DJMcoder). + +### Refactors + +* 🎨 Tweak types for mypy. PR [#14816](https://github.com/fastapi/fastapi/pull/14816) by [@tiangolo](https://github.com/tiangolo). +* 🏷️ Re-export `IncEx` type from Pydantic instead of duplicating it. PR [#14641](https://github.com/fastapi/fastapi/pull/14641) by [@mvanderlee](https://github.com/mvanderlee). +* 💡 Update comment for Pydantic internals. PR [#14814](https://github.com/fastapi/fastapi/pull/14814) by [@tiangolo](https://github.com/tiangolo). + +### Docs + +* 📝 Update docs for contributing translations, simplify title. PR [#14817](https://github.com/fastapi/fastapi/pull/14817) by [@tiangolo](https://github.com/tiangolo). +* 📝 Fix typing issue in `docs_src/app_testing/app_b` code example. PR [#14573](https://github.com/fastapi/fastapi/pull/14573) by [@timakaa](https://github.com/timakaa). +* 📝 Fix example of license identifier in documentation. PR [#14492](https://github.com/fastapi/fastapi/pull/14492) by [@johnson-earls](https://github.com/johnson-earls). +* 📝 Add banner to translated pages. PR [#14809](https://github.com/fastapi/fastapi/pull/14809) by [@YuriiMotov](https://github.com/YuriiMotov). +* 📝 Add links to related sections of docs to docstrings. PR [#14776](https://github.com/fastapi/fastapi/pull/14776) by [@YuriiMotov](https://github.com/YuriiMotov). +* 📝 Update embedded code examples to Python 3.10 syntax. PR [#14758](https://github.com/fastapi/fastapi/pull/14758) by [@YuriiMotov](https://github.com/YuriiMotov). +* 📝 Fix dependency installation command in `docs/en/docs/contributing.md`. PR [#14757](https://github.com/fastapi/fastapi/pull/14757) by [@YuriiMotov](https://github.com/YuriiMotov). +* 📝 Use return type annotation instead of `response_model` when possible. PR [#14753](https://github.com/fastapi/fastapi/pull/14753) by [@YuriiMotov](https://github.com/YuriiMotov). +* 📝 Use `WSGIMiddleware` from `a2wsgi` instead of deprecated `fastapi.middleware.wsgi.WSGIMiddleware`. PR [#14756](https://github.com/fastapi/fastapi/pull/14756) by [@YuriiMotov](https://github.com/YuriiMotov). +* 📝 Fix minor typos in release notes. PR [#14780](https://github.com/fastapi/fastapi/pull/14780) by [@whyvineet](https://github.com/whyvineet). +* 🐛 Fix copy button in custom.js. PR [#14722](https://github.com/fastapi/fastapi/pull/14722) by [@fcharrier](https://github.com/fcharrier). +* 📝 Add contribution instructions about LLM generated code and comments and automated tools for PRs. PR [#14706](https://github.com/fastapi/fastapi/pull/14706) by [@tiangolo](https://github.com/tiangolo). +* 📝 Update docs for management tasks. PR [#14705](https://github.com/fastapi/fastapi/pull/14705) by [@tiangolo](https://github.com/tiangolo). +* 📝 Update docs about managing translations. PR [#14704](https://github.com/fastapi/fastapi/pull/14704) by [@tiangolo](https://github.com/tiangolo). +* 📝 Update docs for contributing with translations. PR [#14701](https://github.com/fastapi/fastapi/pull/14701) by [@tiangolo](https://github.com/tiangolo). +* 📝 Specify language code for code block. PR [#14656](https://github.com/fastapi/fastapi/pull/14656) by [@YuriiMotov](https://github.com/YuriiMotov). + +### Translations + +* 🌐 Improve LLM prompt of `uk` documentation. PR [#14795](https://github.com/fastapi/fastapi/pull/14795) by [@roli2py](https://github.com/roli2py). +* 🌐 Update translations for ja (update-outdated). PR [#14588](https://github.com/fastapi/fastapi/pull/14588) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for uk (update outdated, found by fixer tool). PR [#14739](https://github.com/fastapi/fastapi/pull/14739) by [@YuriiMotov](https://github.com/YuriiMotov). +* 🌐 Update translations for tr (update-outdated). PR [#14745](https://github.com/fastapi/fastapi/pull/14745) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update `llm-prompt.md` for Korean language. PR [#14763](https://github.com/fastapi/fastapi/pull/14763) by [@seuthootDev](https://github.com/seuthootDev). +* 🌐 Update translations for ko (update outdated, found by fixer tool). PR [#14738](https://github.com/fastapi/fastapi/pull/14738) by [@YuriiMotov](https://github.com/YuriiMotov). +* 🌐 Update translations for de (update-outdated). PR [#14690](https://github.com/fastapi/fastapi/pull/14690) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update LLM prompt for Russian translations. PR [#14733](https://github.com/fastapi/fastapi/pull/14733) by [@YuriiMotov](https://github.com/YuriiMotov). +* 🌐 Update translations for ru (update-outdated). PR [#14693](https://github.com/fastapi/fastapi/pull/14693) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for pt (update-outdated). PR [#14724](https://github.com/fastapi/fastapi/pull/14724) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update Korean LLM prompt. PR [#14740](https://github.com/fastapi/fastapi/pull/14740) by [@hard-coders](https://github.com/hard-coders). +* 🌐 Improve LLM prompt for Turkish translations. PR [#14728](https://github.com/fastapi/fastapi/pull/14728) by [@Kadermiyanyedi](https://github.com/Kadermiyanyedi). +* 🌐 Update portuguese llm-prompt.md. PR [#14702](https://github.com/fastapi/fastapi/pull/14702) by [@ceb10n](https://github.com/ceb10n). +* 🌐 Update LLM prompt instructions file for French. PR [#14618](https://github.com/fastapi/fastapi/pull/14618) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for ko (add-missing). PR [#14699](https://github.com/fastapi/fastapi/pull/14699) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for ko (update-outdated). PR [#14589](https://github.com/fastapi/fastapi/pull/14589) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for uk (update-outdated). PR [#14587](https://github.com/fastapi/fastapi/pull/14587) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for es (update-outdated). PR [#14686](https://github.com/fastapi/fastapi/pull/14686) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Add LLM prompt file for Turkish, generated from the existing translations. PR [#14547](https://github.com/fastapi/fastapi/pull/14547) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Add LLM prompt file for Traditional Chinese, generated from the existing translations. PR [#14550](https://github.com/fastapi/fastapi/pull/14550) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Add LLM prompt file for Simplified Chinese, generated from the existing translations. PR [#14549](https://github.com/fastapi/fastapi/pull/14549) by [@tiangolo](https://github.com/tiangolo). + +### Internal + +* ⬇️ Downgrade LLM translations model to GPT-5 to reduce mistakes. PR [#14823](https://github.com/fastapi/fastapi/pull/14823) by [@tiangolo](https://github.com/tiangolo). +* 🐛 Fix translation script commit in place. PR [#14818](https://github.com/fastapi/fastapi/pull/14818) by [@tiangolo](https://github.com/tiangolo). +* 🔨 Update translation script to retry if LLM-response doesn't pass validation with Translation Fixer tool. PR [#14749](https://github.com/fastapi/fastapi/pull/14749) by [@YuriiMotov](https://github.com/YuriiMotov). +* 👷 Run tests only on relevant code changes (not on docs). PR [#14813](https://github.com/fastapi/fastapi/pull/14813) by [@tiangolo](https://github.com/tiangolo). +* 👷 Run mypy by pre-commit. PR [#14806](https://github.com/fastapi/fastapi/pull/14806) by [@YuriiMotov](https://github.com/YuriiMotov). +* ⬆ Bump ruff from 0.14.3 to 0.14.14. PR [#14798](https://github.com/fastapi/fastapi/pull/14798) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump pyasn1 from 0.6.1 to 0.6.2. PR [#14804](https://github.com/fastapi/fastapi/pull/14804) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump sqlmodel from 0.0.27 to 0.0.31. PR [#14802](https://github.com/fastapi/fastapi/pull/14802) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump mkdocs-macros-plugin from 1.4.1 to 1.5.0. PR [#14801](https://github.com/fastapi/fastapi/pull/14801) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump gitpython from 3.1.45 to 3.1.46. PR [#14800](https://github.com/fastapi/fastapi/pull/14800) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump typer from 0.16.0 to 0.21.1. PR [#14799](https://github.com/fastapi/fastapi/pull/14799) by [@dependabot[bot]](https://github.com/apps/dependabot). +* 👥 Update FastAPI GitHub topic repositories. PR [#14803](https://github.com/fastapi/fastapi/pull/14803) by [@tiangolo](https://github.com/tiangolo). +* 👥 Update FastAPI People - Contributors and Translators. PR [#14796](https://github.com/fastapi/fastapi/pull/14796) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Ensure that an edit to `uv.lock` gets the `internal` label. PR [#14759](https://github.com/fastapi/fastapi/pull/14759) by [@svlandeg](https://github.com/svlandeg). +* 🔧 Update sponsors: remove Requestly. PR [#14735](https://github.com/fastapi/fastapi/pull/14735) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Update sponsors, LambdaTest changes to TestMu AI. PR [#14734](https://github.com/fastapi/fastapi/pull/14734) by [@tiangolo](https://github.com/tiangolo). +* ⬆ Bump actions/cache from 4 to 5. PR [#14511](https://github.com/fastapi/fastapi/pull/14511) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump actions/upload-artifact from 5 to 6. PR [#14525](https://github.com/fastapi/fastapi/pull/14525) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump actions/download-artifact from 6 to 7. PR [#14526](https://github.com/fastapi/fastapi/pull/14526) by [@dependabot[bot]](https://github.com/apps/dependabot). +* 👷 Tweak CI input names. PR [#14688](https://github.com/fastapi/fastapi/pull/14688) by [@tiangolo](https://github.com/tiangolo). +* 🔨 Refactor translation script to allow committing in place. PR [#14687](https://github.com/fastapi/fastapi/pull/14687) by [@tiangolo](https://github.com/tiangolo). +* 🐛 Fix translation script path. PR [#14685](https://github.com/fastapi/fastapi/pull/14685) by [@tiangolo](https://github.com/tiangolo). +* ✅ Enable tests in CI for scripts. PR [#14684](https://github.com/fastapi/fastapi/pull/14684) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Add pre-commit local script to fix language translations. PR [#14683](https://github.com/fastapi/fastapi/pull/14683) by [@tiangolo](https://github.com/tiangolo). +* ⬆️ Migrate to uv. PR [#14676](https://github.com/fastapi/fastapi/pull/14676) by [@DoctorJohn](https://github.com/DoctorJohn). +* 🔨 Add LLM translations tool fixer. PR [#14652](https://github.com/fastapi/fastapi/pull/14652) by [@YuriiMotov](https://github.com/YuriiMotov). +* 👥 Update FastAPI People - Sponsors. PR [#14626](https://github.com/fastapi/fastapi/pull/14626) by [@tiangolo](https://github.com/tiangolo). +* 👥 Update FastAPI GitHub topic repositories. PR [#14630](https://github.com/fastapi/fastapi/pull/14630) by [@tiangolo](https://github.com/tiangolo). +* 👥 Update FastAPI People - Contributors and Translators. PR [#14625](https://github.com/fastapi/fastapi/pull/14625) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translation prompts. PR [#14619](https://github.com/fastapi/fastapi/pull/14619) by [@tiangolo](https://github.com/tiangolo). +* 🔨 Update LLM translation script to guide reviewers to change the prompt. PR [#14614](https://github.com/fastapi/fastapi/pull/14614) by [@tiangolo](https://github.com/tiangolo). +* 👷 Do not run translations on cron while finishing updating existing languages. PR [#14613](https://github.com/fastapi/fastapi/pull/14613) by [@tiangolo](https://github.com/tiangolo). +* 🔥 Remove test variants for Pydantic v1 in test_request_params. PR [#14612](https://github.com/fastapi/fastapi/pull/14612) by [@tiangolo](https://github.com/tiangolo). +* 🔥 Remove Pydantic v1 specific test variants. PR [#14611](https://github.com/fastapi/fastapi/pull/14611) by [@tiangolo](https://github.com/tiangolo). + +## 0.128.0 (2025-12-27) + +### Breaking Changes + +* ➖ Drop support for `pydantic.v1`. PR [#14609](https://github.com/fastapi/fastapi/pull/14609) by [@tiangolo](https://github.com/tiangolo). + +### Internal + +* ✅ Run performance tests only on Pydantic v2. PR [#14608](https://github.com/fastapi/fastapi/pull/14608) by [@tiangolo](https://github.com/tiangolo). + +## 0.127.1 (2025-12-26) + +### Refactors + +* 🔊 Add a custom `FastAPIDeprecationWarning`. PR [#14605](https://github.com/fastapi/fastapi/pull/14605) by [@tiangolo](https://github.com/tiangolo). + +### Docs + +* 📝 Add documentary to website. PR [#14600](https://github.com/fastapi/fastapi/pull/14600) by [@tiangolo](https://github.com/tiangolo). + +### Translations + +* 🌐 Update translations for de (update-outdated). PR [#14602](https://github.com/fastapi/fastapi/pull/14602) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Update translations for de (update-outdated). PR [#14581](https://github.com/fastapi/fastapi/pull/14581) by [@nilslindemann](https://github.com/nilslindemann). + +### Internal + +* 🔧 Update pre-commit to use local Ruff instead of hook. PR [#14604](https://github.com/fastapi/fastapi/pull/14604) by [@tiangolo](https://github.com/tiangolo). +* ✅ Add missing tests for code examples. PR [#14569](https://github.com/fastapi/fastapi/pull/14569) by [@YuriiMotov](https://github.com/YuriiMotov). +* 👷 Remove `lint` job from `test` CI workflow. PR [#14593](https://github.com/fastapi/fastapi/pull/14593) by [@YuriiMotov](https://github.com/YuriiMotov). +* 👷 Update secrets check. PR [#14592](https://github.com/fastapi/fastapi/pull/14592) by [@tiangolo](https://github.com/tiangolo). +* 👷 Run CodSpeed tests in parallel to other tests to speed up CI. PR [#14586](https://github.com/fastapi/fastapi/pull/14586) by [@tiangolo](https://github.com/tiangolo). +* 🔨 Update scripts and pre-commit to autofix files. PR [#14585](https://github.com/fastapi/fastapi/pull/14585) by [@tiangolo](https://github.com/tiangolo). + +## 0.127.0 (2025-12-21) + +### Breaking Changes + +* 🔊 Add deprecation warnings when using `pydantic.v1`. PR [#14583](https://github.com/fastapi/fastapi/pull/14583) by [@tiangolo](https://github.com/tiangolo). + +### Translations + +* 🔧 Add LLM prompt file for Korean, generated from the existing translations. PR [#14546](https://github.com/fastapi/fastapi/pull/14546) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Add LLM prompt file for Japanese, generated from the existing translations. PR [#14545](https://github.com/fastapi/fastapi/pull/14545) by [@tiangolo](https://github.com/tiangolo). + +### Internal + +* ⬆️ Upgrade OpenAI model for translations to gpt-5.2. PR [#14579](https://github.com/fastapi/fastapi/pull/14579) by [@tiangolo](https://github.com/tiangolo). + +## 0.126.0 (2025-12-20) + +### Upgrades + +* ➖ Drop support for Pydantic v1, keeping short temporary support for Pydantic v2's `pydantic.v1`. PR [#14575](https://github.com/fastapi/fastapi/pull/14575) by [@tiangolo](https://github.com/tiangolo). + * The minimum version of Pydantic installed is now `pydantic >=2.7.0`. + * The `standard` dependencies now include `pydantic-settings >=2.0.0` and `pydantic-extra-types >=2.0.0`. + +### Docs + +* 📝 Fix duplicated variable in `docs_src/python_types/tutorial005_py39.py`. PR [#14565](https://github.com/fastapi/fastapi/pull/14565) by [@paras-verma7454](https://github.com/paras-verma7454). + +### Translations + +* 🔧 Add LLM prompt file for Ukrainian, generated from the existing translations. PR [#14548](https://github.com/fastapi/fastapi/pull/14548) by [@tiangolo](https://github.com/tiangolo). + +### Internal + +* 🔧 Tweak pre-commit to allow committing release-notes. PR [#14577](https://github.com/fastapi/fastapi/pull/14577) by [@tiangolo](https://github.com/tiangolo). +* ⬆️ Use prek as a pre-commit alternative. PR [#14572](https://github.com/fastapi/fastapi/pull/14572) by [@tiangolo](https://github.com/tiangolo). +* 👷 Add performance tests with CodSpeed. PR [#14558](https://github.com/fastapi/fastapi/pull/14558) by [@tiangolo](https://github.com/tiangolo). + +## 0.125.0 (2025-12-17) + +### Breaking Changes + +* 🔧 Drop support for Python 3.8. PR [#14563](https://github.com/fastapi/fastapi/pull/14563) by [@tiangolo](https://github.com/tiangolo). + * This would actually not be a _breaking_ change as no code would really break. Any Python 3.8 installer would just refuse to install the latest version of FastAPI and would only install 0.124.4. Only marking it as a "breaking change" to make it visible. + +### Refactors + +* ♻️ Upgrade internal syntax to Python 3.9+ 🎉. PR [#14564](https://github.com/fastapi/fastapi/pull/14564) by [@tiangolo](https://github.com/tiangolo). + +### Docs + +* ⚰️ Remove Python 3.8 from CI and remove Python 3.8 examples from source docs. PR [#14559](https://github.com/fastapi/fastapi/pull/14559) by [@YuriiMotov](https://github.com/YuriiMotov) and [@tiangolo](https://github.com/tiangolo). + +### Translations + +* 🌐 Update translations for pt (add-missing). PR [#14539](https://github.com/fastapi/fastapi/pull/14539) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Add LLM prompt file for French, generated from the existing French docs. PR [#14544](https://github.com/fastapi/fastapi/pull/14544) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Sync Portuguese docs (pages found with script). PR [#14554](https://github.com/fastapi/fastapi/pull/14554) by [@YuriiMotov](https://github.com/YuriiMotov). +* 🌐 Sync Spanish docs (outdated pages found with script). PR [#14553](https://github.com/fastapi/fastapi/pull/14553) by [@YuriiMotov](https://github.com/YuriiMotov). +* 🌐 Sync German docs. PR [#14519](https://github.com/fastapi/fastapi/pull/14519) by [@nilslindemann](https://github.com/nilslindemann). +* 🔥 Remove inactive/scarce translations to Vietnamese. PR [#14543](https://github.com/fastapi/fastapi/pull/14543) by [@tiangolo](https://github.com/tiangolo). +* 🔥 Remove inactive/scarce translations to Persian. PR [#14542](https://github.com/fastapi/fastapi/pull/14542) by [@tiangolo](https://github.com/tiangolo). +* 🔥 Remove translation to emoji to simplify the new setup with LLM autotranslations. PR [#14541](https://github.com/fastapi/fastapi/pull/14541) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for pt (update-outdated). PR [#14537](https://github.com/fastapi/fastapi/pull/14537) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for es (update-outdated). PR [#14532](https://github.com/fastapi/fastapi/pull/14532) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update translations for es (add-missing). PR [#14533](https://github.com/fastapi/fastapi/pull/14533) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Remove translations for removed docs. PR [#14516](https://github.com/fastapi/fastapi/pull/14516) by [@tiangolo](https://github.com/tiangolo). + +### Internal + +* ⬆ Bump `markdown-include-variants` from 0.0.7 to 0.0.8. PR [#14556](https://github.com/fastapi/fastapi/pull/14556) by [@YuriiMotov](https://github.com/YuriiMotov). +* 🔧 Temporarily disable translations still in progress, being migrated to the new LLM setup. PR [#14555](https://github.com/fastapi/fastapi/pull/14555) by [@YuriiMotov](https://github.com/YuriiMotov). +* 🔧 Update test workflow config, remove commented code. PR [#14540](https://github.com/fastapi/fastapi/pull/14540) by [@tiangolo](https://github.com/tiangolo). +* 👷 Configure coverage, error on main tests, don't wait for Smokeshow. PR [#14536](https://github.com/fastapi/fastapi/pull/14536) by [@tiangolo](https://github.com/tiangolo). +* 👷 Run Smokeshow always, even on test failures. PR [#14538](https://github.com/fastapi/fastapi/pull/14538) by [@tiangolo](https://github.com/tiangolo). +* 👷 Make Pydantic versions customizable in CI. PR [#14535](https://github.com/fastapi/fastapi/pull/14535) by [@tiangolo](https://github.com/tiangolo). +* 👷 Fix checkout GitHub Action fetch-depth for LLM translations, enable cron monthly. PR [#14531](https://github.com/fastapi/fastapi/pull/14531) by [@tiangolo](https://github.com/tiangolo). +* 👷 Fix Typer command for CI LLM translations. PR [#14530](https://github.com/fastapi/fastapi/pull/14530) by [@tiangolo](https://github.com/tiangolo). +* 👷 Update LLM translation CI, add language matrix and extra commands, prepare for scheduled run. PR [#14529](https://github.com/fastapi/fastapi/pull/14529) by [@tiangolo](https://github.com/tiangolo). +* 👷 Update github-actions user for GitHub Actions workflows. PR [#14528](https://github.com/fastapi/fastapi/pull/14528) by [@tiangolo](https://github.com/tiangolo). +* ➕ Add requirements for translations. PR [#14515](https://github.com/fastapi/fastapi/pull/14515) by [@tiangolo](https://github.com/tiangolo). + +## 0.124.4 (2025-12-12) + +### Fixes + +* 🐛 Fix parameter aliases. PR [#14371](https://github.com/fastapi/fastapi/pull/14371) by [@YuriiMotov](https://github.com/YuriiMotov). + +## 0.124.3 (2025-12-12) + +### Fixes + +* 🐛 Fix support for tagged union with discriminator inside of `Annotated` with `Body()`. PR [#14512](https://github.com/fastapi/fastapi/pull/14512) by [@tiangolo](https://github.com/tiangolo). + +### Refactors + +* ✅ Add set of tests for request parameters and alias. PR [#14358](https://github.com/fastapi/fastapi/pull/14358) by [@YuriiMotov](https://github.com/YuriiMotov). + +### Docs + +* 📝 Tweak links format. PR [#14505](https://github.com/fastapi/fastapi/pull/14505) by [@tiangolo](https://github.com/tiangolo). +* 📝 Update docs about re-raising validation errors, do not include string as is to not leak information. PR [#14487](https://github.com/fastapi/fastapi/pull/14487) by [@tiangolo](https://github.com/tiangolo). +* 🔥 Remove external links section. PR [#14486](https://github.com/fastapi/fastapi/pull/14486) by [@tiangolo](https://github.com/tiangolo). + +### Translations + +* 🌐 Sync Russian docs. PR [#14509](https://github.com/fastapi/fastapi/pull/14509) by [@YuriiMotov](https://github.com/YuriiMotov). +* 🌐 Sync German docs. PR [#14488](https://github.com/fastapi/fastapi/pull/14488) by [@nilslindemann](https://github.com/nilslindemann). + +### Internal + +* 👷 Tweak coverage to not pass Smokeshow max file size limit. PR [#14507](https://github.com/fastapi/fastapi/pull/14507) by [@tiangolo](https://github.com/tiangolo). +* ✅ Expand test matrix to include Windows and MacOS. PR [#14171](https://github.com/fastapi/fastapi/pull/14171) by [@svlandeg](https://github.com/svlandeg). + +## 0.124.2 (2025-12-10) + +### Fixes + +* 🐛 Fix support for `if TYPE_CHECKING`, non-evaluated stringified annotations. PR [#14485](https://github.com/fastapi/fastapi/pull/14485) by [@tiangolo](https://github.com/tiangolo). + +## 0.124.1 (2025-12-10) + +### Fixes + +* 🐛 Fix handling arbitrary types when using `arbitrary_types_allowed=True`. PR [#14482](https://github.com/fastapi/fastapi/pull/14482) by [@tiangolo](https://github.com/tiangolo). + +### Docs + +* 📝 Add variants for code examples in "Advanced User Guide". PR [#14413](https://github.com/fastapi/fastapi/pull/14413) by [@YuriiMotov](https://github.com/YuriiMotov). +* 📝 Update tech stack in project generation docs. PR [#14472](https://github.com/fastapi/fastapi/pull/14472) by [@alejsdev](https://github.com/alejsdev). + +### Internal + +* ✅ Add test for Pydantic v2, dataclasses, UUID, and `__annotations__`. PR [#14477](https://github.com/fastapi/fastapi/pull/14477) by [@tiangolo](https://github.com/tiangolo). + +## 0.124.0 (2025-12-06) + +### Features + +* 🚸 Improve tracebacks by adding endpoint metadata. PR [#14306](https://github.com/fastapi/fastapi/pull/14306) by [@savannahostrowski](https://github.com/savannahostrowski). + +### Internal + +* ✏️ Fix typo in `scripts/mkdocs_hooks.py`. PR [#14457](https://github.com/fastapi/fastapi/pull/14457) by [@yujiteshima](https://github.com/yujiteshima). + +## 0.123.10 (2025-12-05) + +### Fixes + +* 🐛 Fix using class (not instance) dependency that has `__call__` method. PR [#14458](https://github.com/fastapi/fastapi/pull/14458) by [@YuriiMotov](https://github.com/YuriiMotov). +* 🐛 Fix `separate_input_output_schemas=False` with `computed_field`. PR [#14453](https://github.com/fastapi/fastapi/pull/14453) by [@YuriiMotov](https://github.com/YuriiMotov). + +## 0.123.9 (2025-12-04) + +### Fixes + +* 🐛 Fix OAuth2 scopes in OpenAPI in extra corner cases, parent dependency with scopes, sub-dependency security scheme without scopes. PR [#14459](https://github.com/fastapi/fastapi/pull/14459) by [@tiangolo](https://github.com/tiangolo). + +## 0.123.8 (2025-12-04) + +### Fixes + +* 🐛 Fix OpenAPI security scheme OAuth2 scopes declaration, deduplicate security schemes with different scopes. PR [#14455](https://github.com/fastapi/fastapi/pull/14455) by [@tiangolo](https://github.com/tiangolo). + +## 0.123.7 (2025-12-04) + +### Fixes + +* 🐛 Fix evaluating stringified annotations in Python 3.10. PR [#11355](https://github.com/fastapi/fastapi/pull/11355) by [@chaen](https://github.com/chaen). + +## 0.123.6 (2025-12-04) + +### Fixes + +* 🐛 Fix support for functools wraps and partial combined, for async and regular functions and classes in path operations and dependencies. PR [#14448](https://github.com/fastapi/fastapi/pull/14448) by [@tiangolo](https://github.com/tiangolo). + +## 0.123.5 (2025-12-02) + +### Features + +* ✨ Allow using dependables with `functools.partial()`. PR [#9753](https://github.com/fastapi/fastapi/pull/9753) by [@lieryan](https://github.com/lieryan). +* ✨ Add support for wrapped functions (e.g. `@functools.wraps()`) used with forward references. PR [#5077](https://github.com/fastapi/fastapi/pull/5077) by [@lucaswiman](https://github.com/lucaswiman). +* ✨ Handle wrapped dependencies. PR [#9555](https://github.com/fastapi/fastapi/pull/9555) by [@phy1729](https://github.com/phy1729). + +### Fixes + +* 🐛 Fix optional sequence handling with new union syntax from Python 3.10. PR [#14430](https://github.com/fastapi/fastapi/pull/14430) by [@Viicos](https://github.com/Viicos). + +### Refactors + +* 🔥 Remove dangling extra conditional no longer needed. PR [#14435](https://github.com/fastapi/fastapi/pull/14435) by [@tiangolo](https://github.com/tiangolo). +* ♻️ Refactor internals, update `is_coroutine` check to reuse internal supported variants (unwrap, check class). PR [#14434](https://github.com/fastapi/fastapi/pull/14434) by [@tiangolo](https://github.com/tiangolo). + +### Translations + +* 🌐 Sync German docs. PR [#14367](https://github.com/fastapi/fastapi/pull/14367) by [@nilslindemann](https://github.com/nilslindemann). + +## 0.123.4 (2025-12-02) + +### Fixes + +* 🐛 Fix OpenAPI schema support for computed fields when using `separate_input_output_schemas=False`. PR [#13207](https://github.com/fastapi/fastapi/pull/13207) by [@vgrafe](https://github.com/vgrafe). + +### Docs + +* 📝 Fix docstring of `servers` parameter. PR [#14405](https://github.com/fastapi/fastapi/pull/14405) by [@YuriiMotov](https://github.com/YuriiMotov). + +## 0.123.3 (2025-12-02) + +### Fixes + +* 🐛 Fix Query\Header\Cookie parameter model alias. PR [#14360](https://github.com/fastapi/fastapi/pull/14360) by [@YuriiMotov](https://github.com/YuriiMotov). +* 🐛 Fix optional sequence handling in `serialize sequence value` with Pydantic V2. PR [#14297](https://github.com/fastapi/fastapi/pull/14297) by [@YuriiMotov](https://github.com/YuriiMotov). + +## 0.123.2 (2025-12-02) + +### Fixes + +* 🐛 Fix unformatted `{type_}` in FastAPIError. PR [#14416](https://github.com/fastapi/fastapi/pull/14416) by [@Just-Helpful](https://github.com/Just-Helpful). +* 🐛 Fix parsing extra non-body parameter list. PR [#14356](https://github.com/fastapi/fastapi/pull/14356) by [@YuriiMotov](https://github.com/YuriiMotov). +* 🐛 Fix parsing extra `Form` parameter list. PR [#14303](https://github.com/fastapi/fastapi/pull/14303) by [@YuriiMotov](https://github.com/YuriiMotov). +* 🐛 Fix support for form values with empty strings interpreted as missing (`None` if that's the default), for compatibility with HTML forms. PR [#13537](https://github.com/fastapi/fastapi/pull/13537) by [@MarinPostma](https://github.com/MarinPostma). + +### Docs + +* 📝 Add tip on how to install `pip` in case of `No module named pip` error in `virtual-environments.md`. PR [#14211](https://github.com/fastapi/fastapi/pull/14211) by [@zadevhub](https://github.com/zadevhub). +* 📝 Update Primary Key notes for the SQL databases tutorial to avoid confusion. PR [#14120](https://github.com/fastapi/fastapi/pull/14120) by [@FlaviusRaducu](https://github.com/FlaviusRaducu). +* 📝 Clarify estimation note in documentation. PR [#14070](https://github.com/fastapi/fastapi/pull/14070) by [@SaisakthiM](https://github.com/SaisakthiM). + +## 0.123.1 (2025-12-02) + +### Fixes + +* 🐛 Avoid accessing non-existing "$ref" key for Pydantic v2 compat remapping. PR [#14361](https://github.com/fastapi/fastapi/pull/14361) by [@svlandeg](https://github.com/svlandeg). +* 🐛 Fix `TypeError` when encoding a decimal with a `NaN` or `Infinity` value. PR [#12935](https://github.com/fastapi/fastapi/pull/12935) by [@kentwelcome](https://github.com/kentwelcome). + +### Internal + +* 🐛 Fix Windows UnicodeEncodeError in CLI test. PR [#14295](https://github.com/fastapi/fastapi/pull/14295) by [@hemanth-thirthahalli](https://github.com/hemanth-thirthahalli). +* 🔧 Update sponsors: add Greptile. PR [#14429](https://github.com/fastapi/fastapi/pull/14429) by [@tiangolo](https://github.com/tiangolo). +* 👥 Update FastAPI GitHub topic repositories. PR [#14426](https://github.com/fastapi/fastapi/pull/14426) by [@tiangolo](https://github.com/tiangolo). +* ⬆ Bump markdown-include-variants from 0.0.6 to 0.0.7. PR [#14423](https://github.com/fastapi/fastapi/pull/14423) by [@YuriiMotov](https://github.com/YuriiMotov). +* 👥 Update FastAPI People - Sponsors. PR [#14422](https://github.com/fastapi/fastapi/pull/14422) by [@tiangolo](https://github.com/tiangolo). +* 👥 Update FastAPI People - Contributors and Translators. PR [#14420](https://github.com/fastapi/fastapi/pull/14420) by [@tiangolo](https://github.com/tiangolo). + +## 0.123.0 (2025-11-30) + +### Fixes + +* 🐛 Cache dependencies that don't use scopes and don't have sub-dependencies with scopes. PR [#14419](https://github.com/fastapi/fastapi/pull/14419) by [@tiangolo](https://github.com/tiangolo). + +## 0.122.1 (2025-11-30) + +### Fixes + +* 🐛 Fix hierarchical security scope propagation. PR [#5624](https://github.com/fastapi/fastapi/pull/5624) by [@kristjanvalur](https://github.com/kristjanvalur). + +### Docs + +* 💅 Update CSS to explicitly use emoji font. PR [#14415](https://github.com/fastapi/fastapi/pull/14415) by [@tiangolo](https://github.com/tiangolo). + +### Internal + +* ⬆ Bump markdown-include-variants from 0.0.5 to 0.0.6. PR [#14418](https://github.com/fastapi/fastapi/pull/14418) by [@YuriiMotov](https://github.com/YuriiMotov). + +## 0.122.0 (2025-11-24) + +### Fixes + +* 🐛 Use `401` status code in security classes when credentials are missing. PR [#13786](https://github.com/fastapi/fastapi/pull/13786) by [@YuriiMotov](https://github.com/YuriiMotov). + * If your code depended on these classes raising the old (less correct) `403` status code, check the new docs about how to override the classes, to use the same old behavior: [Use Old 403 Authentication Error Status Codes](https://fastapi.tiangolo.com/how-to/authentication-error-status-code/). + +### Internal + +* 🔧 Configure labeler to exclude files that start from underscore for `lang-all` label. PR [#14213](https://github.com/fastapi/fastapi/pull/14213) by [@YuriiMotov](https://github.com/YuriiMotov). +* 👷 Add pre-commit config with local script for permalinks. PR [#14398](https://github.com/fastapi/fastapi/pull/14398) by [@tiangolo](https://github.com/tiangolo). +* 💄 Use font Fira Code to fix display of Rich panels in docs in Windows. PR [#14387](https://github.com/fastapi/fastapi/pull/14387) by [@tiangolo](https://github.com/tiangolo). +* 👷 Add custom pre-commit CI. PR [#14397](https://github.com/fastapi/fastapi/pull/14397) by [@tiangolo](https://github.com/tiangolo). +* ⬆ Bump actions/checkout from 5 to 6. PR [#14381](https://github.com/fastapi/fastapi/pull/14381) by [@dependabot[bot]](https://github.com/apps/dependabot). +* 👷 Upgrade `latest-changes` GitHub Action and pin `actions/checkout@v5`. PR [#14403](https://github.com/fastapi/fastapi/pull/14403) by [@svlandeg](https://github.com/svlandeg). +* 🛠️ Add `add-permalinks` and `add-permalinks-page` to `scripts/docs.py`. PR [#14033](https://github.com/fastapi/fastapi/pull/14033) by [@YuriiMotov](https://github.com/YuriiMotov). +* 🔧 Upgrade Material for MkDocs and remove insiders. PR [#14375](https://github.com/fastapi/fastapi/pull/14375) by [@tiangolo](https://github.com/tiangolo). + +## 0.121.3 (2025-11-19) + +### Refactors + +* ♻️ Make the result of `Depends()` and `Security()` hashable, as a workaround for other tools interacting with these internal parts. PR [#14372](https://github.com/fastapi/fastapi/pull/14372) by [@tiangolo](https://github.com/tiangolo). + +### Upgrades + +* ⬆️ Bump Starlette to <`0.51.0`. PR [#14282](https://github.com/fastapi/fastapi/pull/14282) by [@musicinmybrain](https://github.com/musicinmybrain). + +### Docs + +* 📝 Add missing hash part. PR [#14369](https://github.com/fastapi/fastapi/pull/14369) by [@nilslindemann](https://github.com/nilslindemann). +* 📝 Fix typos in code comments. PR [#14364](https://github.com/fastapi/fastapi/pull/14364) by [@Edge-Seven](https://github.com/Edge-Seven). +* 📝 Add docs for using FastAPI Cloud. PR [#14359](https://github.com/fastapi/fastapi/pull/14359) by [@tiangolo](https://github.com/tiangolo). + +## 0.121.2 (2025-11-13) + +### Fixes + +* 🐛 Fix handling of JSON Schema attributes named "$ref". PR [#14349](https://github.com/fastapi/fastapi/pull/14349) by [@tiangolo](https://github.com/tiangolo). + +### Docs + +* 📝 Add EuroPython talk & podcast episode with Sebastián Ramírez. PR [#14260](https://github.com/fastapi/fastapi/pull/14260) by [@clytaemnestra](https://github.com/clytaemnestra). +* ✏️ Fix links and add missing permalink in docs. PR [#14217](https://github.com/fastapi/fastapi/pull/14217) by [@YuriiMotov](https://github.com/YuriiMotov). + +### Translations + +* 🌐 Update Portuguese translations with LLM prompt. PR [#14228](https://github.com/fastapi/fastapi/pull/14228) by [@ceb10n](https://github.com/ceb10n). +* 🔨 Add Portuguese translations LLM prompt. PR [#14208](https://github.com/fastapi/fastapi/pull/14208) by [@ceb10n](https://github.com/ceb10n). +* 🌐 Sync Russian docs. PR [#14331](https://github.com/fastapi/fastapi/pull/14331) by [@YuriiMotov](https://github.com/YuriiMotov). +* 🌐 Sync German docs. PR [#14317](https://github.com/fastapi/fastapi/pull/14317) by [@nilslindemann](https://github.com/nilslindemann). + +## 0.121.1 (2025-11-08) + +### Fixes + +* 🐛 Fix `Depends(func, scope='function')` for top level (parameterless) dependencies. PR [#14301](https://github.com/fastapi/fastapi/pull/14301) by [@luzzodev](https://github.com/luzzodev). + +### Docs + +* 📝 Update docs for advanced dependencies with `yield`, noting the changes in 0.121.0, adding `scope`. PR [#14287](https://github.com/fastapi/fastapi/pull/14287) by [@tiangolo](https://github.com/tiangolo). + +### Internal + +* ⬆ Bump ruff from 0.13.2 to 0.14.3. PR [#14276](https://github.com/fastapi/fastapi/pull/14276) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#14289](https://github.com/fastapi/fastapi/pull/14289) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). + +## 0.121.0 (2025-11-03) + +### Features + +* ✨ Add support for dependencies with scopes, support `scope="request"` for dependencies with `yield` that exit before the response is sent. PR [#14262](https://github.com/fastapi/fastapi/pull/14262) by [@tiangolo](https://github.com/tiangolo). + * New docs: [Dependencies with `yield` - Early exit and `scope`](https://fastapi.tiangolo.com/tutorial/dependencies/dependencies-with-yield/#early-exit-and-scope). + +### Internal + +* 👥 Update FastAPI People - Contributors and Translators. PR [#14273](https://github.com/fastapi/fastapi/pull/14273) by [@tiangolo](https://github.com/tiangolo). +* 👥 Update FastAPI People - Sponsors. PR [#14274](https://github.com/fastapi/fastapi/pull/14274) by [@tiangolo](https://github.com/tiangolo). +* 👥 Update FastAPI GitHub topic repositories. PR [#14280](https://github.com/fastapi/fastapi/pull/14280) by [@tiangolo](https://github.com/tiangolo). +* ⬆ Bump mkdocs-macros-plugin from 1.4.0 to 1.4.1. PR [#14277](https://github.com/fastapi/fastapi/pull/14277) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump mkdocstrings[python] from 0.26.1 to 0.30.1. PR [#14279](https://github.com/fastapi/fastapi/pull/14279) by [@dependabot[bot]](https://github.com/apps/dependabot). + +## 0.120.4 (2025-10-31) + +### Fixes + +* 🐛 Fix security schemes in OpenAPI when added at the top level app. PR [#14266](https://github.com/fastapi/fastapi/pull/14266) by [@YuriiMotov](https://github.com/YuriiMotov). + +## 0.120.3 (2025-10-30) + +### Refactors + +* ♻️ Reduce internal cyclic recursion in dependencies, from 2 functions calling each other to 1 calling itself. PR [#14256](https://github.com/fastapi/fastapi/pull/14256) by [@tiangolo](https://github.com/tiangolo). +* ♻️ Refactor internals of dependencies, simplify code and remove `get_param_sub_dependant`. PR [#14255](https://github.com/fastapi/fastapi/pull/14255) by [@tiangolo](https://github.com/tiangolo). +* ♻️ Refactor internals of dependencies, simplify using dataclasses. PR [#14254](https://github.com/fastapi/fastapi/pull/14254) by [@tiangolo](https://github.com/tiangolo). + +### Docs + +* 📝 Update note for untranslated pages. PR [#14257](https://github.com/fastapi/fastapi/pull/14257) by [@YuriiMotov](https://github.com/YuriiMotov). + +## 0.120.2 (2025-10-29) + +### Fixes + +* 🐛 Fix separation of schemas with nested models introduced in 0.119.0. PR [#14246](https://github.com/fastapi/fastapi/pull/14246) by [@tiangolo](https://github.com/tiangolo). + +### Internal + +* 🔧 Add sponsor: SerpApi. PR [#14248](https://github.com/fastapi/fastapi/pull/14248) by [@tiangolo](https://github.com/tiangolo). +* ⬆ Bump actions/download-artifact from 5 to 6. PR [#14236](https://github.com/fastapi/fastapi/pull/14236) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#14237](https://github.com/fastapi/fastapi/pull/14237) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). +* ⬆ Bump actions/upload-artifact from 4 to 5. PR [#14235](https://github.com/fastapi/fastapi/pull/14235) by [@dependabot[bot]](https://github.com/apps/dependabot). + +## 0.120.1 (2025-10-27) + +### Upgrades + +* ⬆️ Bump Starlette to <`0.50.0`. PR [#14234](https://github.com/fastapi/fastapi/pull/14234) by [@YuriiMotov](https://github.com/YuriiMotov). + +### Internal + +* 🔧 Add `license` and `license-files` to `pyproject.toml`, remove `License` from `classifiers`. PR [#14230](https://github.com/fastapi/fastapi/pull/14230) by [@YuriiMotov](https://github.com/YuriiMotov). + +## 0.120.0 (2025-10-23) + +There are no major nor breaking changes in this release. ☕️ + +The internal reference documentation now uses `annotated_doc.Doc` instead of `typing_extensions.Doc`, this adds a new (very small) dependency on [`annotated-doc`](https://github.com/fastapi/annotated-doc), a package made just to provide that `Doc` documentation utility class. + +I would expect `typing_extensions.Doc` to be deprecated and then removed at some point from `typing_extensions`, for that reason there's the new `annotated-doc` micro-package. If you are curious about this, you can read more in the repo for [`annotated-doc`](https://github.com/fastapi/annotated-doc). + +This new version `0.120.0` only contains that transition to the new home package for that utility class `Doc`. + +### Translations + +* 🌐 Sync German docs. PR [#14188](https://github.com/fastapi/fastapi/pull/14188) by [@nilslindemann](https://github.com/nilslindemann). + +### Internal + +* ➕ Migrate internal reference documentation from `typing_extensions.Doc` to `annotated_doc.Doc`. PR [#14222](https://github.com/fastapi/fastapi/pull/14222) by [@tiangolo](https://github.com/tiangolo). +* 🛠️ Update German LLM prompt and test file. PR [#14189](https://github.com/fastapi/fastapi/pull/14189) by [@nilslindemann](https://github.com/nilslindemann). +* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#14181](https://github.com/fastapi/fastapi/pull/14181) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). + +## 0.119.1 (2025-10-20) + +### Fixes + +* 🐛 Fix internal Pydantic v1 compatibility (warnings) for Python 3.14 and Pydantic 2.12.1. PR [#14186](https://github.com/fastapi/fastapi/pull/14186) by [@svlandeg](https://github.com/svlandeg). + +### Docs + +* 📝 Replace `starlette.io` by `starlette.dev` and `uvicorn.org` by `uvicorn.dev`. PR [#14176](https://github.com/fastapi/fastapi/pull/14176) by [@Kludex](https://github.com/Kludex). + +### Internal + +* 🔧 Add sponsor Requestly. PR [#14205](https://github.com/fastapi/fastapi/pull/14205) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Configure reminder for `waiting` label in `issue-manager`. PR [#14156](https://github.com/fastapi/fastapi/pull/14156) by [@YuriiMotov](https://github.com/YuriiMotov). + +## 0.119.0 (2025-10-11) + +FastAPI now (temporarily) supports both Pydantic v2 models and `pydantic.v1` models at the same time in the same app, to make it easier for any FastAPI apps still using Pydantic v1 to gradually but quickly **migrate to Pydantic v2**. + +```Python +from fastapi import FastAPI +from pydantic import BaseModel as BaseModelV2 +from pydantic.v1 import BaseModel + + +class Item(BaseModel): + name: str + description: str | None = None + + +class ItemV2(BaseModelV2): + title: str + summary: str | None = None + + +app = FastAPI() + + +@app.post("/items/", response_model=ItemV2) +def create_item(item: Item): + return {"title": item.name, "summary": item.description} +``` + +Adding this feature was a big effort with the main objective of making it easier for the few applications still stuck in Pydantic v1 to migrate to Pydantic v2. + +And with this, support for **Pydantic v1 is now deprecated** and will be **removed** from FastAPI in a future version soon. + +**Note**: have in mind that the Pydantic team already stopped supporting Pydantic v1 for recent versions of Python, starting with Python 3.14. + +You can read in the docs more about how to [Migrate from Pydantic v1 to Pydantic v2](https://fastapi.tiangolo.com/how-to/migrate-from-pydantic-v1-to-pydantic-v2/). + +### Features + +* ✨ Add support for `from pydantic.v1 import BaseModel`, mixed Pydantic v1 and v2 models in the same app. PR [#14168](https://github.com/fastapi/fastapi/pull/14168) by [@tiangolo](https://github.com/tiangolo). + +## 0.118.3 (2025-10-10) + +### Upgrades + +* ⬆️ Add support for Python 3.14. PR [#14165](https://github.com/fastapi/fastapi/pull/14165) by [@svlandeg](https://github.com/svlandeg). + +## 0.118.2 (2025-10-08) + +### Fixes + +* 🐛 Fix tagged discriminated union not recognized as body field. PR [#12942](https://github.com/fastapi/fastapi/pull/12942) by [@frankie567](https://github.com/frankie567). + +### Internal + +* ⬆ Bump astral-sh/setup-uv from 6 to 7. PR [#14167](https://github.com/fastapi/fastapi/pull/14167) by [@dependabot[bot]](https://github.com/apps/dependabot). + +## 0.118.1 (2025-10-08) + +### Upgrades + +* 👽️ Ensure compatibility with Pydantic 2.12.0. PR [#14036](https://github.com/fastapi/fastapi/pull/14036) by [@cjwatson](https://github.com/cjwatson). + +### Docs + +* 📝 Add External Link: Getting started with logging in FastAPI. PR [#14152](https://github.com/fastapi/fastapi/pull/14152) by [@itssimon](https://github.com/itssimon). + +### Translations + +* 🔨 Add Russian translations LLM prompt. PR [#13936](https://github.com/fastapi/fastapi/pull/13936) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Sync German docs. PR [#14149](https://github.com/fastapi/fastapi/pull/14149) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add Russian translations for missing pages (LLM-generated). PR [#14135](https://github.com/fastapi/fastapi/pull/14135) by [@YuriiMotov](https://github.com/YuriiMotov). +* 🌐 Update Russian translations for existing pages (LLM-generated). PR [#14123](https://github.com/fastapi/fastapi/pull/14123) by [@YuriiMotov](https://github.com/YuriiMotov). +* 🌐 Remove configuration files for inactive translations. PR [#14130](https://github.com/fastapi/fastapi/pull/14130) by [@tiangolo](https://github.com/tiangolo). + +### Internal + +* 🔨 Move local coverage logic to its own script. PR [#14166](https://github.com/fastapi/fastapi/pull/14166) by [@tiangolo](https://github.com/tiangolo). +* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#14161](https://github.com/fastapi/fastapi/pull/14161) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). +* ⬆ Bump griffe-typingdoc from 0.2.8 to 0.2.9. PR [#14144](https://github.com/fastapi/fastapi/pull/14144) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump mkdocs-macros-plugin from 1.3.9 to 1.4.0. PR [#14145](https://github.com/fastapi/fastapi/pull/14145) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump markdown-include-variants from 0.0.4 to 0.0.5. PR [#14146](https://github.com/fastapi/fastapi/pull/14146) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#14126](https://github.com/fastapi/fastapi/pull/14126) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). +* 👥 Update FastAPI GitHub topic repositories. PR [#14150](https://github.com/fastapi/fastapi/pull/14150) by [@tiangolo](https://github.com/tiangolo). +* 👥 Update FastAPI People - Sponsors. PR [#14139](https://github.com/fastapi/fastapi/pull/14139) by [@tiangolo](https://github.com/tiangolo). +* 👥 Update FastAPI People - Contributors and Translators. PR [#14138](https://github.com/fastapi/fastapi/pull/14138) by [@tiangolo](https://github.com/tiangolo). +* ⬆ Bump ruff from 0.12.7 to 0.13.2. PR [#14147](https://github.com/fastapi/fastapi/pull/14147) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump sqlmodel from 0.0.24 to 0.0.25. PR [#14143](https://github.com/fastapi/fastapi/pull/14143) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump tiangolo/issue-manager from 0.5.1 to 0.6.0. PR [#14148](https://github.com/fastapi/fastapi/pull/14148) by [@dependabot[bot]](https://github.com/apps/dependabot). +* 👷 Update docs previews comment, single comment, add failure status. PR [#14129](https://github.com/fastapi/fastapi/pull/14129) by [@tiangolo](https://github.com/tiangolo). +* 🔨 Modify `mkdocs_hooks.py` to add `title` to page's metadata (remove permalinks in social cards). PR [#14125](https://github.com/fastapi/fastapi/pull/14125) by [@YuriiMotov](https://github.com/YuriiMotov). + +## 0.118.0 (2025-09-29) + +### Fixes + +* 🐛 Fix support for `StreamingResponse`s with dependencies with `yield` or `UploadFile`s, close after the response is done. PR [#14099](https://github.com/fastapi/fastapi/pull/14099) by [@tiangolo](https://github.com/tiangolo). + +Before FastAPI 0.118.0, if you used a dependency with `yield`, it would run the exit code after the *path operation function* returned but right before sending the response. + +This change also meant that if you returned a `StreamingResponse`, the exit code of the dependency with `yield` would have been already run. + +For example, if you had a database session in a dependency with `yield`, the `StreamingResponse` would not be able to use that session while streaming data because the session would have already been closed in the exit code after `yield`. + +This behavior was reverted in 0.118.0, to make the exit code after `yield` be executed after the response is sent. + +You can read more about it in the docs for [Advanced Dependencies - Dependencies with `yield`, `HTTPException`, `except` and Background Tasks](https://fastapi.tiangolo.com/advanced/advanced-dependencies#dependencies-with-yield-httpexception-except-and-background-tasks). Including what you could do if you wanted to close a database session earlier, before returning the response to the client. + +### Docs + +* 📝 Update `tutorial/security/oauth2-jwt/` to use `pwdlib` with Argon2 instead of `passlib`. PR [#13917](https://github.com/fastapi/fastapi/pull/13917) by [@Neizvestnyj](https://github.com/Neizvestnyj). +* ✏️ Fix typos in OAuth2 password request forms. PR [#14112](https://github.com/fastapi/fastapi/pull/14112) by [@alv2017](https://github.com/alv2017). +* 📝 Update contributing guidelines for installing requirements. PR [#14095](https://github.com/fastapi/fastapi/pull/14095) by [@alejsdev](https://github.com/alejsdev). + +### Translations + +* 🌐 Sync German docs. PR [#14098](https://github.com/fastapi/fastapi/pull/14098) by [@nilslindemann](https://github.com/nilslindemann). + +### Internal + +* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#14103](https://github.com/fastapi/fastapi/pull/14103) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). +* ♻️ Refactor sponsor image handling. PR [#14102](https://github.com/fastapi/fastapi/pull/14102) by [@alejsdev](https://github.com/alejsdev). +* 🐛 Fix sponsor display issue by hiding element on image error. PR [#14097](https://github.com/fastapi/fastapi/pull/14097) by [@alejsdev](https://github.com/alejsdev). +* 🐛 Hide sponsor badge when sponsor image is not displayed. PR [#14096](https://github.com/fastapi/fastapi/pull/14096) by [@alejsdev](https://github.com/alejsdev). + +## 0.117.1 (2025-09-20) + +### Fixes + +* 🐛 Fix validation error when `File` is declared after `Form` parameter. PR [#11194](https://github.com/fastapi/fastapi/pull/11194) by [@thomasleveil](https://github.com/thomasleveil). + +## 0.117.0 (2025-09-20) + +### Features + +* ✨ Allow `None` as return type for bodiless responses. PR [#9425](https://github.com/fastapi/fastapi/pull/9425) by [@hofrob](https://github.com/hofrob). +* ✨ Allow array values for OpenAPI schema `type` field. PR [#13639](https://github.com/fastapi/fastapi/pull/13639) by [@sammasak](https://github.com/sammasak). +* ✨ Add OpenAPI `external_docs` parameter to `FastAPI`. PR [#13713](https://github.com/fastapi/fastapi/pull/13713) by [@cmtoro](https://github.com/cmtoro). + +### Fixes + +* ⚡️ Fix `default_factory` for response model field with Pydantic V1. PR [#9704](https://github.com/fastapi/fastapi/pull/9704) by [@vvanglro](https://github.com/vvanglro). +* 🐛 Fix inconsistent processing of model docstring formfeed char with Pydantic V1. PR [#6039](https://github.com/fastapi/fastapi/pull/6039) by [@MaxwellPayne](https://github.com/MaxwellPayne). +* 🐛 Fix `jsonable_encoder` alters `json_encoders` of Pydantic v1 objects. PR [#4972](https://github.com/fastapi/fastapi/pull/4972) by [@aboubacs](https://github.com/aboubacs). +* 🐛 Reenable `allow_arbitrary_types` when only 1 argument is used on the API endpoint. PR [#13694](https://github.com/fastapi/fastapi/pull/13694) by [@rmawatson](https://github.com/rmawatson). +* 🐛 Fix `inspect.getcoroutinefunction()` can break testing with `unittest.mock.patch()`. PR [#14022](https://github.com/fastapi/fastapi/pull/14022) by [@secrett2633](https://github.com/secrett2633). + +### Refactors + +* ♻️ Create `dependency-cache` dict in `solve_dependencies` only if `None` (don't re-create if empty). PR [#13689](https://github.com/fastapi/fastapi/pull/13689) by [@bokshitsky](https://github.com/bokshitsky). +* ✅ Enable test case for duplicated headers in `test_tutorial/test_header_params/test_tutorial003.py`. PR [#13864](https://github.com/fastapi/fastapi/pull/13864) by [@Amogha-ark](https://github.com/Amogha-ark). +* 📌 Pin `httpx` to `>=0.23.0,<1.0.0`. PR [#14086](https://github.com/fastapi/fastapi/pull/14086) by [@YuriiMotov](https://github.com/YuriiMotov). + +### Docs + +* 📝 Add note about Cookies and JavaScript on `tutorial/cookie-params.md`. PR [#13510](https://github.com/fastapi/fastapi/pull/13510) by [@Kludex](https://github.com/Kludex). +* 📝 Remove outdated formatting from `path-params-numeric-validations.md` for languages `en`, `es` and `uk`.. PR [#14059](https://github.com/fastapi/fastapi/pull/14059) by [@svlandeg](https://github.com/svlandeg). +* 📝 Fix and Improve English Documentation. PR [#14048](https://github.com/fastapi/fastapi/pull/14048) by [@nilslindemann](https://github.com/nilslindemann). + +### Translations + +* 📝 Update prompts and German translation. PR [#14015](https://github.com/fastapi/fastapi/pull/14015) by [@nilslindemann](https://github.com/nilslindemann). + +### Internal + +* ✅ Simplify tests for response_model. PR [#14062](https://github.com/fastapi/fastapi/pull/14062) by [@dynamicy](https://github.com/dynamicy). +* 🚨 Install pydantic.mypy plugin. PR [#14081](https://github.com/fastapi/fastapi/pull/14081) by [@svlandeg](https://github.com/svlandeg). +* ✅ Add LLM test file. PR [#14049](https://github.com/fastapi/fastapi/pull/14049) by [@nilslindemann](https://github.com/nilslindemann). +* 🔨 Update translations script. PR [#13968](https://github.com/fastapi/fastapi/pull/13968) by [@YuriiMotov](https://github.com/YuriiMotov). +* 🛠️ Update `docs.py generate-readme` command to remove permalinks from headers. PR [#14055](https://github.com/fastapi/fastapi/pull/14055) by [@YuriiMotov](https://github.com/YuriiMotov). +* ⬆️ Update mypy to 1.14.1. PR [#12970](https://github.com/fastapi/fastapi/pull/12970) by [@tamird](https://github.com/tamird). + +## 0.116.2 (2025-09-16) + +### Upgrades + +* ⬆️ Upgrade Starlette supported version range to >=0.40.0,<0.49.0. PR [#14077](https://github.com/fastapi/fastapi/pull/14077) by [@musicinmybrain](https://github.com/musicinmybrain). + +### Docs + +* 📝 Add documentation for Behind a Proxy - Proxy Forwarded Headers, using `--forwarded-allow-ips="*"`. PR [#14028](https://github.com/fastapi/fastapi/pull/14028) by [@tiangolo](https://github.com/tiangolo). +* 📝 Add deprecation info block about `dict()` in `docs/tutorial/body.md`. PR [#13906](https://github.com/fastapi/fastapi/pull/13906) by [@jomkv](https://github.com/jomkv). +* 📝 Fix Twitter to be X (Twitter) everywhere in documentation. PR [#13809](https://github.com/fastapi/fastapi/pull/13809) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). +* 🐛 Prevent scroll-to-top on restart/fast buttons in `termynal.js`. PR [#13714](https://github.com/fastapi/fastapi/pull/13714) by [@Ashish-Pandey62](https://github.com/Ashish-Pandey62). +* 📝 Update testing events documentation. PR [#13259](https://github.com/fastapi/fastapi/pull/13259) by [@z0z0r4](https://github.com/z0z0r4). +* 📝 Remove obsolete `url` field in error responses in docs. PR [#13655](https://github.com/fastapi/fastapi/pull/13655) by [@Taoup](https://github.com/Taoup). +* 📝 Bring the `scope` claim in line with the standard in `docs_src/security/tutorial005.py`. PR [#11189](https://github.com/fastapi/fastapi/pull/11189) by [@DurandA](https://github.com/DurandA). +* 📝 Update TrustedHostMiddleware Documentation. PR [#11441](https://github.com/fastapi/fastapi/pull/11441) by [@soulee-dev](https://github.com/soulee-dev). +* 📝 Remove links to site callbackhell.com that doesn't exist anymore. PR [#14006](https://github.com/fastapi/fastapi/pull/14006) by [@dennybiasiolli](https://github.com/dennybiasiolli). +* 📝 Add permalinks to headers in English docs. PR [#13993](https://github.com/fastapi/fastapi/pull/13993) by [@YuriiMotov](https://github.com/YuriiMotov). +* 📝 Update `docs/en/docs/advanced/generate-clients.md`. PR [#13793](https://github.com/fastapi/fastapi/pull/13793) by [@mrlubos](https://github.com/mrlubos). +* 📝 Add discussion template for new language translation requests. PR [#13535](https://github.com/fastapi/fastapi/pull/13535) by [@alejsdev](https://github.com/alejsdev). + +### Translations + +* 📝 Fix code include for Pydantic models example in `docs/zh/docs/python-types.md`. PR [#13997](https://github.com/fastapi/fastapi/pull/13997) by [@anfreshman](https://github.com/anfreshman). +* 🌐 Update Portuguese Translation for `docs/pt/docs/async.md`. PR [#13863](https://github.com/fastapi/fastapi/pull/13863) by [@EdmilsonRodrigues](https://github.com/EdmilsonRodrigues). +* 📝 Fix highlight line in `docs/ja/docs/tutorial/body.md`. PR [#13927](https://github.com/fastapi/fastapi/pull/13927) by [@KoyoMiyazaki](https://github.com/KoyoMiyazaki). +* 🌐 Add Persian translation for `docs/fa/docs/environment-variables.md`. PR [#13923](https://github.com/fastapi/fastapi/pull/13923) by [@Mohammad222PR](https://github.com/Mohammad222PR). +* 🌐 Add Persian translation for `docs/fa/docs/python-types.md`. PR [#13524](https://github.com/fastapi/fastapi/pull/13524) by [@Mohammad222PR](https://github.com/Mohammad222PR). +* 🌐 Update Portuguese Translation for `docs/pt/docs/project-generation.md`. PR [#13875](https://github.com/fastapi/fastapi/pull/13875) by [@EdmilsonRodrigues](https://github.com/EdmilsonRodrigues). +* 🌐 Add Persian translation for `docs/fa/docs/async.md`. PR [#13541](https://github.com/fastapi/fastapi/pull/13541) by [@Mohammad222PR](https://github.com/Mohammad222PR). +* 🌐 Add Bengali translation for `docs/bn/about/index.md`. PR [#13882](https://github.com/fastapi/fastapi/pull/13882) by [@sajjadrahman56](https://github.com/sajjadrahman56). + +### Internal + +* ⬆ Bump pyjwt from 2.8.0 to 2.9.0. PR [#13960](https://github.com/fastapi/fastapi/pull/13960) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#14080](https://github.com/fastapi/fastapi/pull/14080) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). +* ⬆ Bump actions/setup-python from 5 to 6. PR [#14042](https://github.com/fastapi/fastapi/pull/14042) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump actions/labeler from 5 to 6. PR [#14046](https://github.com/fastapi/fastapi/pull/14046) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#14056](https://github.com/fastapi/fastapi/pull/14056) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). +* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#14035](https://github.com/fastapi/fastapi/pull/14035) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). +* ⬆ Bump pypa/gh-action-pypi-publish from 1.12.4 to 1.13.0. PR [#14041](https://github.com/fastapi/fastapi/pull/14041) by [@dependabot[bot]](https://github.com/apps/dependabot). +* 👥 Update FastAPI People - Contributors and Translators. PR [#14029](https://github.com/fastapi/fastapi/pull/14029) by [@tiangolo](https://github.com/tiangolo). +* 👥 Update FastAPI People - Sponsors. PR [#14030](https://github.com/fastapi/fastapi/pull/14030) by [@tiangolo](https://github.com/tiangolo). +* 👥 Update FastAPI GitHub topic repositories. PR [#14031](https://github.com/fastapi/fastapi/pull/14031) by [@tiangolo](https://github.com/tiangolo). +* 👥 Update FastAPI People - Experts. PR [#14034](https://github.com/fastapi/fastapi/pull/14034) by [@tiangolo](https://github.com/tiangolo). +* 👷 Detect and label merge conflicts on PRs automatically. PR [#14045](https://github.com/fastapi/fastapi/pull/14045) by [@svlandeg](https://github.com/svlandeg). +* 🔧 Update sponsors: remove Platform.sh. PR [#14027](https://github.com/fastapi/fastapi/pull/14027) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Update sponsors: remove Mobb. PR [#14026](https://github.com/fastapi/fastapi/pull/14026) by [@tiangolo](https://github.com/tiangolo). +* 🛠️ Update `mkdocs_hooks` to handle headers with permalinks when building docs. PR [#14025](https://github.com/fastapi/fastapi/pull/14025) by [@tiangolo](https://github.com/tiangolo). +* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#14016](https://github.com/fastapi/fastapi/pull/14016) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). +* ⬆ Bump `mkdocs-macros-plugin` from 1.3.7 to 1.3.9. PR [#14003](https://github.com/fastapi/fastapi/pull/14003) by [@YuriiMotov](https://github.com/YuriiMotov). +* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13999](https://github.com/fastapi/fastapi/pull/13999) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). +* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13983](https://github.com/fastapi/fastapi/pull/13983) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). +* ⬆ Bump actions/checkout from 4 to 5. PR [#13986](https://github.com/fastapi/fastapi/pull/13986) by [@dependabot[bot]](https://github.com/apps/dependabot). +* 🔧 Update Speakeasy sponsor graphic. PR [#13971](https://github.com/fastapi/fastapi/pull/13971) by [@chailandau](https://github.com/chailandau). +* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13969](https://github.com/fastapi/fastapi/pull/13969) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). +* ⬆ Bump actions/download-artifact from 4 to 5. PR [#13975](https://github.com/fastapi/fastapi/pull/13975) by [@dependabot[bot]](https://github.com/apps/dependabot). +* 👥 Update FastAPI People - Experts. PR [#13963](https://github.com/fastapi/fastapi/pull/13963) by [@tiangolo](https://github.com/tiangolo). +* ⬆ Bump ruff from 0.11.2 to 0.12.7. PR [#13957](https://github.com/fastapi/fastapi/pull/13957) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump cairosvg from 2.7.1 to 2.8.2. PR [#13959](https://github.com/fastapi/fastapi/pull/13959) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump pydantic-ai from 0.0.30 to 0.4.10. PR [#13958](https://github.com/fastapi/fastapi/pull/13958) by [@dependabot[bot]](https://github.com/apps/dependabot). +* 👥 Update FastAPI GitHub topic repositories. PR [#13962](https://github.com/fastapi/fastapi/pull/13962) by [@tiangolo](https://github.com/tiangolo). +* ⬆ Bump mkdocs-material from 9.6.15 to 9.6.16. PR [#13961](https://github.com/fastapi/fastapi/pull/13961) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump tiangolo/latest-changes from 0.3.2 to 0.4.0. PR [#13952](https://github.com/fastapi/fastapi/pull/13952) by [@dependabot[bot]](https://github.com/apps/dependabot). +* 👥 Update FastAPI People - Sponsors. PR [#13956](https://github.com/fastapi/fastapi/pull/13956) by [@tiangolo](https://github.com/tiangolo). +* 👥 Update FastAPI People - Contributors and Translators. PR [#13955](https://github.com/fastapi/fastapi/pull/13955) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Update sponsors: Databento link and sponsors_badge data. PR [#13954](https://github.com/fastapi/fastapi/pull/13954) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Update sponsors: Add Railway. PR [#13953](https://github.com/fastapi/fastapi/pull/13953) by [@tiangolo](https://github.com/tiangolo). +* ⚒️ Update translate script, update prompt to minimize generated diff. PR [#13947](https://github.com/fastapi/fastapi/pull/13947) by [@YuriiMotov](https://github.com/YuriiMotov). +* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13943](https://github.com/fastapi/fastapi/pull/13943) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). +* ⚒️ Tweak translate script and CI. PR [#13939](https://github.com/fastapi/fastapi/pull/13939) by [@tiangolo](https://github.com/tiangolo). +* 👷 Add CI to translate with LLMs. PR [#13937](https://github.com/fastapi/fastapi/pull/13937) by [@tiangolo](https://github.com/tiangolo). +* ⚒️ Update translate script, show and update outdated translations. PR [#13933](https://github.com/fastapi/fastapi/pull/13933) by [@tiangolo](https://github.com/tiangolo). +* 🔨 Refactor translate script with extra feedback (prints). PR [#13932](https://github.com/fastapi/fastapi/pull/13932) by [@tiangolo](https://github.com/tiangolo). +* 🔨 Update translations script to remove old (removed) files. PR [#13928](https://github.com/fastapi/fastapi/pull/13928) by [@tiangolo](https://github.com/tiangolo). +* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13894](https://github.com/fastapi/fastapi/pull/13894) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). +* ⬆ Update httpx requirement to >=0.23.0,<0.29.0. PR [#13114](https://github.com/fastapi/fastapi/pull/13114) by [@yan12125](https://github.com/yan12125). +* 🔧 Update sponsors: Add Mobb. PR [#13916](https://github.com/fastapi/fastapi/pull/13916) by [@tiangolo](https://github.com/tiangolo). +* 👥 Update FastAPI People - Experts. PR [#13889](https://github.com/fastapi/fastapi/pull/13889) by [@tiangolo](https://github.com/tiangolo). +* 🔨 Update FastAPI People sleep interval, use external settings. PR [#13888](https://github.com/fastapi/fastapi/pull/13888) by [@tiangolo](https://github.com/tiangolo). + +## 0.116.1 (2025-07-11) + +### Upgrades + +* ⬆️ Upgrade Starlette supported version range to `>=0.40.0,<0.48.0`. PR [#13884](https://github.com/fastapi/fastapi/pull/13884) by [@tiangolo](https://github.com/tiangolo). + +### Docs + +* 📝 Add notification about impending changes in Translations to `docs/en/docs/contributing.md`. PR [#13886](https://github.com/fastapi/fastapi/pull/13886) by [@YuriiMotov](https://github.com/YuriiMotov). + +### Internal + +* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13871](https://github.com/fastapi/fastapi/pull/13871) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). + +## 0.116.0 (2025-07-07) + +### Features + +* ✨ Add support for deploying to FastAPI Cloud with `fastapi deploy`. PR [#13870](https://github.com/fastapi/fastapi/pull/13870) by [@tiangolo](https://github.com/tiangolo). + +Installing `fastapi[standard]` now includes `fastapi-cloud-cli`. + +This will allow you to deploy to [FastAPI Cloud](https://fastapicloud.com) with the `fastapi deploy` command. + +If you want to install `fastapi` with the standard dependencies but without `fastapi-cloud-cli`, you can install instead `fastapi[standard-no-fastapi-cloud-cli]`. + +### Translations + +* 🌐 Add Russian translation for `docs/ru/docs/advanced/response-directly.md`. PR [#13801](https://github.com/fastapi/fastapi/pull/13801) by [@NavesSapnis](https://github.com/NavesSapnis). +* 🌐 Add Russian translation for `docs/ru/docs/advanced/additional-status-codes.md`. PR [#13799](https://github.com/fastapi/fastapi/pull/13799) by [@NavesSapnis](https://github.com/NavesSapnis). +* 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/body-updates.md`. PR [#13804](https://github.com/fastapi/fastapi/pull/13804) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). + +### Internal + +* ⬆ Bump pillow from 11.1.0 to 11.3.0. PR [#13852](https://github.com/fastapi/fastapi/pull/13852) by [@dependabot[bot]](https://github.com/apps/dependabot). +* 👥 Update FastAPI People - Sponsors. PR [#13846](https://github.com/fastapi/fastapi/pull/13846) by [@tiangolo](https://github.com/tiangolo). +* 👥 Update FastAPI GitHub topic repositories. PR [#13848](https://github.com/fastapi/fastapi/pull/13848) by [@tiangolo](https://github.com/tiangolo). +* ⬆ Bump mkdocs-material from 9.6.1 to 9.6.15. PR [#13849](https://github.com/fastapi/fastapi/pull/13849) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13843](https://github.com/fastapi/fastapi/pull/13843) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). +* 👥 Update FastAPI People - Contributors and Translators. PR [#13845](https://github.com/fastapi/fastapi/pull/13845) by [@tiangolo](https://github.com/tiangolo). + +## 0.115.14 (2025-06-26) + +### Fixes + +* 🐛 Fix support for unions when using `Form`. PR [#13827](https://github.com/fastapi/fastapi/pull/13827) by [@patrick91](https://github.com/patrick91). + +### Docs + +* ✏️ Fix grammar mistake in `docs/en/docs/advanced/response-directly.md`. PR [#13800](https://github.com/fastapi/fastapi/pull/13800) by [@NavesSapnis](https://github.com/NavesSapnis). +* 📝 Update Speakeasy URL to Speakeasy Sandbox. PR [#13697](https://github.com/fastapi/fastapi/pull/13697) by [@ndimares](https://github.com/ndimares). + +### Translations + +* 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/response-model.md`. PR [#13792](https://github.com/fastapi/fastapi/pull/13792) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). +* 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/security/index.md`. PR [#13805](https://github.com/fastapi/fastapi/pull/13805) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). +* ✏️ Fix typo in `docs/ja/docs/tutorial/encoder.md`. PR [#13815](https://github.com/fastapi/fastapi/pull/13815) by [@ruzia](https://github.com/ruzia). +* ✏️ Fix typo in `docs/ja/docs/tutorial/handling-errors.md`. PR [#13814](https://github.com/fastapi/fastapi/pull/13814) by [@ruzia](https://github.com/ruzia). +* ✏️ Fix typo in `docs/ja/docs/tutorial/body-fields.md`. PR [#13802](https://github.com/fastapi/fastapi/pull/13802) by [@ruzia](https://github.com/ruzia). +* 🌐 Add Russian translation for `docs/ru/docs/advanced/index.md`. PR [#13797](https://github.com/fastapi/fastapi/pull/13797) by [@NavesSapnis](https://github.com/NavesSapnis). + +### Internal + +* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13823](https://github.com/fastapi/fastapi/pull/13823) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). + +## 0.115.13 (2025-06-17) + +### Fixes + +* 🐛 Fix truncating the model's description with form feed (`\f`) character for Pydantic V2. PR [#13698](https://github.com/fastapi/fastapi/pull/13698) by [@YuriiMotov](https://github.com/YuriiMotov). + +### Refactors + +* ✨ Add `refreshUrl` parameter in `OAuth2PasswordBearer`. PR [#11460](https://github.com/fastapi/fastapi/pull/11460) by [@snosratiershad](https://github.com/snosratiershad). +* 🚸 Set format to password for fields `password` and `client_secret` in `OAuth2PasswordRequestForm`, make docs show password fields for passwords. PR [#11032](https://github.com/fastapi/fastapi/pull/11032) by [@Thodoris1999](https://github.com/Thodoris1999). +* ✅ Simplify tests for `settings`. PR [#13505](https://github.com/fastapi/fastapi/pull/13505) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). +* ✅ Simplify tests for `validate_response_recursive`. PR [#13507](https://github.com/fastapi/fastapi/pull/13507) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). + +### Upgrades + +* ⬆️ Update ReDoc to version 2.x. PR [#9700](https://github.com/fastapi/fastapi/pull/9700) by [@joakimnordling](https://github.com/joakimnordling). + +### Docs + +* 📝 Add annotations to HTTP middleware example. PR [#11530](https://github.com/fastapi/fastapi/pull/11530) by [@Kilo59](https://github.com/Kilo59). +* 📝 Clarify in CORS docs that wildcards and credentials are mutually exclusive. PR [#9829](https://github.com/fastapi/fastapi/pull/9829) by [@dfioravanti](https://github.com/dfioravanti). +* ✏️ Fix typo in docstring. PR [#13532](https://github.com/fastapi/fastapi/pull/13532) by [@comp64](https://github.com/comp64). +* 📝 Clarify guidance on using `async def` without `await`. PR [#13642](https://github.com/fastapi/fastapi/pull/13642) by [@swastikpradhan1999](https://github.com/swastikpradhan1999). +* 📝 Update exclude-parameters-from-openapi documentation links. PR [#13600](https://github.com/fastapi/fastapi/pull/13600) by [@timonrieger](https://github.com/timonrieger). +* 📝 Clarify the middleware execution order in docs. PR [#13699](https://github.com/fastapi/fastapi/pull/13699) by [@YuriiMotov](https://github.com/YuriiMotov). +* 🍱 Update Drawio diagrams SVGs, single file per diagram, sans-serif font. PR [#13706](https://github.com/fastapi/fastapi/pull/13706) by [@tiangolo](https://github.com/tiangolo). +* 📝 Update docs for "Help FastAPI", simplify and reduce "sponsor" section. PR [#13670](https://github.com/fastapi/fastapi/pull/13670) by [@tiangolo](https://github.com/tiangolo). +* 📝 Remove unnecessary bullet from docs. PR [#13641](https://github.com/fastapi/fastapi/pull/13641) by [@Adamowoc](https://github.com/Adamowoc). +* ✏️ Fix syntax error in `docs/en/docs/tutorial/handling-errors.md`. PR [#13623](https://github.com/fastapi/fastapi/pull/13623) by [@gsheni](https://github.com/gsheni). +* 📝 Fix typo in documentation. PR [#13599](https://github.com/fastapi/fastapi/pull/13599) by [@Taoup](https://github.com/Taoup). +* 📝 Fix liblab client generation doc link. PR [#13571](https://github.com/fastapi/fastapi/pull/13571) by [@EFord36](https://github.com/EFord36). +* ✏️ Fix talk information typo. PR [#13544](https://github.com/fastapi/fastapi/pull/13544) by [@blueswen](https://github.com/blueswen). +* 📝 Add External Link: Taiwanese talk on FastAPI with observability . PR [#13527](https://github.com/fastapi/fastapi/pull/13527) by [@blueswen](https://github.com/blueswen). + +### Translations + +* 🌐 Add Russian Translation for `docs/ru/docs/advanced/response-change-status-code.md`. PR [#13791](https://github.com/fastapi/fastapi/pull/13791) by [@NavesSapnis](https://github.com/NavesSapnis). +* 🌐 Add Persian translation for `docs/fa/docs/learn/index.md`. PR [#13518](https://github.com/fastapi/fastapi/pull/13518) by [@Mohammad222PR](https://github.com/Mohammad222PR). +* 🌐 Add Korean translation for `docs/ko/docs/advanced/sub-applications.md`. PR [#4543](https://github.com/fastapi/fastapi/pull/4543) by [@NinaHwang](https://github.com/NinaHwang). +* 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/schema-extra-example.md`. PR [#13769](https://github.com/fastapi/fastapi/pull/13769) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). +* ✏️ Remove redundant words in docs/zh/docs/python-types.md. PR [#13774](https://github.com/fastapi/fastapi/pull/13774) by [@CharleeWa](https://github.com/CharleeWa). +* 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/query-param-models.md`. PR [#13748](https://github.com/fastapi/fastapi/pull/13748) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). +* 🌐 Add Bengali translation for `docs/bn/docs/environment-variables.md`. PR [#13629](https://github.com/fastapi/fastapi/pull/13629) by [@SakibSibly](https://github.com/SakibSibly). +* 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/query-params-str-validations.md` page. PR [#13546](https://github.com/fastapi/fastapi/pull/13546) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). +* 🌐 Add Russian translation for `docs/ru/docs/tutorial/cookie-param-models.md`. PR [#13616](https://github.com/fastapi/fastapi/pull/13616) by [@EgorOnishchuk](https://github.com/EgorOnishchuk). +* 🌐 Add Korean translation for `docs/ko/docs/tutorial/extra-models.md`. PR [#13063](https://github.com/fastapi/fastapi/pull/13063) by [@timothy-jeong](https://github.com/timothy-jeong). +* 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/path-params-numeric-validations.md` page. PR [#13548](https://github.com/fastapi/fastapi/pull/13548) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). +* 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/middleware.md` page. PR [#13520](https://github.com/fastapi/fastapi/pull/13520) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). +* 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/background-tasks.md` page. PR [#13502](https://github.com/fastapi/fastapi/pull/13502) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). +* 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/cors.md` page. PR [#13519](https://github.com/fastapi/fastapi/pull/13519) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). +* 🌐 Update Korean translation for `docs/ko/docs/advanced/events.md`. PR [#13487](https://github.com/fastapi/fastapi/pull/13487) by [@bom1215](https://github.com/bom1215). +* 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/handling-errors.md` page. PR [#13420](https://github.com/fastapi/fastapi/pull/13420) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). +* 🌐 Add Russian translation for `docs/ru/docs/tutorial/request-form-models.md`. PR [#13552](https://github.com/fastapi/fastapi/pull/13552) by [@EgorOnishchuk](https://github.com/EgorOnishchuk). +* 📝 Fix internal anchor link in Spanish deployment docs. PR [#13737](https://github.com/fastapi/fastapi/pull/13737) by [@fabianfalon](https://github.com/fabianfalon). +* 🌐 Update Korean translation for `docs/ko/docs/virtual-environments.md`. PR [#13630](https://github.com/fastapi/fastapi/pull/13630) by [@sungchan1](https://github.com/sungchan1). +* 🌐 Add Russian translation for `docs/ru/docs/tutorial/header-param-models.md`. PR [#13526](https://github.com/fastapi/fastapi/pull/13526) by [@minaton-ru](https://github.com/minaton-ru). +* 🌐 Update Chinese translation for `docs/zh/docs/tutorial/index.md`. PR [#13374](https://github.com/fastapi/fastapi/pull/13374) by [@Zhongheng-Cheng](https://github.com/Zhongheng-Cheng). +* 🌐 Update Chinese translation for `docs/zh/docs/deployment/manually.md`. PR [#13324](https://github.com/fastapi/fastapi/pull/13324) by [@Zhongheng-Cheng](https://github.com/Zhongheng-Cheng). +* 🌐 Update Chinese translation for `docs/zh/docs/deployment/server-workers.md`. PR [#13292](https://github.com/fastapi/fastapi/pull/13292) by [@Zhongheng-Cheng](https://github.com/Zhongheng-Cheng). +* 🌐 Update Chinese translation for `docs/zh/docs/tutorial/first-steps.md`. PR [#13348](https://github.com/fastapi/fastapi/pull/13348) by [@Zhongheng-Cheng](https://github.com/Zhongheng-Cheng). + +### Internal + +* 🔨 Resolve Pydantic deprecation warnings in internal script. PR [#13696](https://github.com/fastapi/fastapi/pull/13696) by [@emmanuel-ferdman](https://github.com/emmanuel-ferdman). +* 🔧 Update sponsors: remove Porter. PR [#13783](https://github.com/fastapi/fastapi/pull/13783) by [@tiangolo](https://github.com/tiangolo). +* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13781](https://github.com/fastapi/fastapi/pull/13781) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). +* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13757](https://github.com/fastapi/fastapi/pull/13757) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). +* ⬆ Bump griffe-typingdoc from 0.2.7 to 0.2.8. PR [#13751](https://github.com/fastapi/fastapi/pull/13751) by [@dependabot[bot]](https://github.com/apps/dependabot). +* 🍱 Update sponsors: Dribia badge size. PR [#13773](https://github.com/fastapi/fastapi/pull/13773) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Update sponsors: add Dribia. PR [#13771](https://github.com/fastapi/fastapi/pull/13771) by [@tiangolo](https://github.com/tiangolo). +* ⬆ Bump typer from 0.15.3 to 0.16.0. PR [#13752](https://github.com/fastapi/fastapi/pull/13752) by [@dependabot[bot]](https://github.com/apps/dependabot). +* 👥 Update FastAPI GitHub topic repositories. PR [#13754](https://github.com/fastapi/fastapi/pull/13754) by [@tiangolo](https://github.com/tiangolo). +* 👥 Update FastAPI People - Sponsors. PR [#13750](https://github.com/fastapi/fastapi/pull/13750) by [@tiangolo](https://github.com/tiangolo). +* 👥 Update FastAPI People - Contributors and Translators. PR [#13749](https://github.com/fastapi/fastapi/pull/13749) by [@tiangolo](https://github.com/tiangolo). +* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13736](https://github.com/fastapi/fastapi/pull/13736) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). +* 🔧 Update sponsors: Add InterviewPal. PR [#13728](https://github.com/fastapi/fastapi/pull/13728) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Remove Google Analytics. PR [#13727](https://github.com/fastapi/fastapi/pull/13727) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Update sponsors: remove MongoDB. PR [#13725](https://github.com/fastapi/fastapi/pull/13725) by [@tiangolo](https://github.com/tiangolo). +* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13711](https://github.com/fastapi/fastapi/pull/13711) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). +* 🔧 Update sponsors: add Subtotal. PR [#13701](https://github.com/fastapi/fastapi/pull/13701) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Update sponsors: remove deepset / Haystack. PR [#13700](https://github.com/fastapi/fastapi/pull/13700) by [@tiangolo](https://github.com/tiangolo). +* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13688](https://github.com/fastapi/fastapi/pull/13688) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). +* 👥 Update FastAPI People - Experts. PR [#13671](https://github.com/fastapi/fastapi/pull/13671) by [@tiangolo](https://github.com/tiangolo). +* ⬆ Bump typer from 0.12.5 to 0.15.3. PR [#13666](https://github.com/fastapi/fastapi/pull/13666) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump sqlmodel from 0.0.23 to 0.0.24. PR [#13665](https://github.com/fastapi/fastapi/pull/13665) by [@dependabot[bot]](https://github.com/apps/dependabot). +* 🔧 Update Sponsors: Zuplo logo and alt text. PR [#13645](https://github.com/fastapi/fastapi/pull/13645) by [@martyndavies](https://github.com/martyndavies). +* 👥 Update FastAPI GitHub topic repositories. PR [#13667](https://github.com/fastapi/fastapi/pull/13667) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Update links for LinkedIn and bottom. PR [#13669](https://github.com/fastapi/fastapi/pull/13669) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Update sponsors: remove Bump.sh and Coherence. PR [#13668](https://github.com/fastapi/fastapi/pull/13668) by [@tiangolo](https://github.com/tiangolo). +* 👥 Update FastAPI People - Sponsors. PR [#13664](https://github.com/fastapi/fastapi/pull/13664) by [@tiangolo](https://github.com/tiangolo). +* 👥 Update FastAPI People - Contributors and Translators. PR [#13662](https://github.com/fastapi/fastapi/pull/13662) by [@tiangolo](https://github.com/tiangolo). +* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13656](https://github.com/fastapi/fastapi/pull/13656) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). +* ✅ Use `inline-snapshot` to support different Pydantic versions in the test suite. PR [#12534](https://github.com/fastapi/fastapi/pull/12534) by [@15r10nk](https://github.com/15r10nk). +* ⬆ Bump astral-sh/setup-uv from 5 to 6. PR [#13648](https://github.com/fastapi/fastapi/pull/13648) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13634](https://github.com/fastapi/fastapi/pull/13634) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). +* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13619](https://github.com/fastapi/fastapi/pull/13619) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). +* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13594](https://github.com/fastapi/fastapi/pull/13594) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). +* 👥 Update FastAPI People - Experts. PR [#13568](https://github.com/fastapi/fastapi/pull/13568) by [@tiangolo](https://github.com/tiangolo). +* 👥 Update FastAPI GitHub topic repositories. PR [#13565](https://github.com/fastapi/fastapi/pull/13565) by [@tiangolo](https://github.com/tiangolo). +* 👥 Update FastAPI People - Sponsors. PR [#13559](https://github.com/fastapi/fastapi/pull/13559) by [@tiangolo](https://github.com/tiangolo). +* 👥 Update FastAPI People - Contributors and Translators. PR [#13558](https://github.com/fastapi/fastapi/pull/13558) by [@tiangolo](https://github.com/tiangolo). +* ⬆ Bump dirty-equals from 0.8.0 to 0.9.0. PR [#13561](https://github.com/fastapi/fastapi/pull/13561) by [@dependabot[bot]](https://github.com/apps/dependabot). +* 🔧 Clean up `docs/en/mkdocs.yml` configuration file. PR [#13542](https://github.com/fastapi/fastapi/pull/13542) by [@svlandeg](https://github.com/svlandeg). +* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#12986](https://github.com/fastapi/fastapi/pull/12986) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). + +## 0.115.12 (2025-03-23) + +### Fixes + +* 🐛 Fix `convert_underscores=False` for header Pydantic models. PR [#13515](https://github.com/fastapi/fastapi/pull/13515) by [@tiangolo](https://github.com/tiangolo). + +### Docs + +* 📝 Update `docs/en/docs/tutorial/middleware.md`. PR [#13444](https://github.com/fastapi/fastapi/pull/13444) by [@Rishat-F](https://github.com/Rishat-F). +* 👥 Update FastAPI People - Experts. PR [#13493](https://github.com/fastapi/fastapi/pull/13493) by [@tiangolo](https://github.com/tiangolo). + +### Translations + +* 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/metadata.md` page. PR [#13459](https://github.com/fastapi/fastapi/pull/13459) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). +* 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/response-status-code.md` page. PR [#13462](https://github.com/fastapi/fastapi/pull/13462) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). +* 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/cookie-param-models.md` page. PR [#13460](https://github.com/fastapi/fastapi/pull/13460) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). +* 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/header-param-models.md` page. PR [#13461](https://github.com/fastapi/fastapi/pull/13461) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). +* 🌐 Add Japanese translation for `docs/ja/docs/virtual-environments.md`. PR [#13304](https://github.com/fastapi/fastapi/pull/13304) by [@k94-ishi](https://github.com/k94-ishi). +* 🌐 Add Korean translation for `docs/ko/docs/tutorial/security/oauth2-jwt.md`. PR [#13333](https://github.com/fastapi/fastapi/pull/13333) by [@yes0ng](https://github.com/yes0ng). +* 🌐 Add Vietnamese translation for `docs/vi/docs/deployment/cloud.md`. PR [#13407](https://github.com/fastapi/fastapi/pull/13407) by [@ptt3199](https://github.com/ptt3199). + +### Internal + +* ⬆ Bump pydantic-ai from 0.0.15 to 0.0.30. PR [#13438](https://github.com/fastapi/fastapi/pull/13438) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump sqlmodel from 0.0.22 to 0.0.23. PR [#13437](https://github.com/fastapi/fastapi/pull/13437) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump black from 24.10.0 to 25.1.0. PR [#13436](https://github.com/fastapi/fastapi/pull/13436) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump ruff to 0.9.4. PR [#13299](https://github.com/fastapi/fastapi/pull/13299) by [@dependabot[bot]](https://github.com/apps/dependabot). +* 🔧 Update sponsors: pause TestDriven. PR [#13446](https://github.com/fastapi/fastapi/pull/13446) by [@tiangolo](https://github.com/tiangolo). + +## 0.115.11 (2025-03-01) + +### Fixes + +* 🐛 Add docs examples and tests (support) for `Annotated` custom validations, like `AfterValidator`, revert [#13440](https://github.com/fastapi/fastapi/pull/13440). PR [#13442](https://github.com/fastapi/fastapi/pull/13442) by [@tiangolo](https://github.com/tiangolo). + * New docs: [Query Parameters and String Validations - Custom Validation](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#custom-validation). + +### Translations + +* 🌐 Add Russian translation for `docs/ru/docs/tutorial/middleware.md`. PR [#13412](https://github.com/fastapi/fastapi/pull/13412) by [@alv2017](https://github.com/alv2017). + +### Internal + +* 👥 Update FastAPI GitHub topic repositories. PR [#13439](https://github.com/fastapi/fastapi/pull/13439) by [@tiangolo](https://github.com/tiangolo). +* 👥 Update FastAPI People - Contributors and Translators. PR [#13432](https://github.com/fastapi/fastapi/pull/13432) by [@tiangolo](https://github.com/tiangolo). +* 👥 Update FastAPI People - Sponsors. PR [#13433](https://github.com/fastapi/fastapi/pull/13433) by [@tiangolo](https://github.com/tiangolo). + +## 0.115.10 (2025-02-28) + +### Fixes + +* ♻️ Update internal annotation usage for compatibility with Pydantic 2.11. PR [#13314](https://github.com/fastapi/fastapi/pull/13314) by [@Viicos](https://github.com/Viicos). + +### Upgrades + +* ⬆️ Bump Starlette to allow up to 0.46.0: `>=0.40.0,<0.47.0`. PR [#13426](https://github.com/fastapi/fastapi/pull/13426) by [@musicinmybrain](https://github.com/musicinmybrain). + +### Translations + +* 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/debugging.md`. PR [#13370](https://github.com/fastapi/fastapi/pull/13370) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). +* 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/query-params.md`. PR [#13362](https://github.com/fastapi/fastapi/pull/13362) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). +* 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/path-params.md`. PR [#13354](https://github.com/fastapi/fastapi/pull/13354) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). +* 🌐 Add Japanese translation for `docs/ja/docs/tutorial/cookie-param-models.md`. PR [#13330](https://github.com/fastapi/fastapi/pull/13330) by [@k94-ishi](https://github.com/k94-ishi). +* 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/body-multiple-params.md`. PR [#13408](https://github.com/fastapi/fastapi/pull/13408) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). +* 🌐 Add Japanese translation for `docs/ja/docs/tutorial/query-param-models.md`. PR [#13323](https://github.com/fastapi/fastapi/pull/13323) by [@k94-ishi](https://github.com/k94-ishi). +* 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/body-nested-models.md`. PR [#13409](https://github.com/fastapi/fastapi/pull/13409) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). +* 🌐 Add Vietnamese translation for `docs/vi/docs/deployment/versions.md`. PR [#13406](https://github.com/fastapi/fastapi/pull/13406) by [@ptt3199](https://github.com/ptt3199). +* 🌐 Add Vietnamese translation for `docs/vi/docs/deployment/index.md`. PR [#13405](https://github.com/fastapi/fastapi/pull/13405) by [@ptt3199](https://github.com/ptt3199). +* 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/request-forms.md`. PR [#13383](https://github.com/fastapi/fastapi/pull/13383) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). +* 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/testing.md`. PR [#13371](https://github.com/fastapi/fastapi/pull/13371) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). + +## 0.115.9 (2025-02-27) + +### Fixes + +* 🐛 Ensure that `HTTPDigest` only raises an exception when `auto_error is True`. PR [#2939](https://github.com/fastapi/fastapi/pull/2939) by [@arthurio](https://github.com/arthurio). + +### Refactors + +* ✅ Simplify tests for `query_params_str_validations`. PR [#13218](https://github.com/fastapi/fastapi/pull/13218) by [@alv2017](https://github.com/alv2017). +* ✅ Simplify tests for `app_testing`. PR [#13220](https://github.com/fastapi/fastapi/pull/13220) by [@alv2017](https://github.com/alv2017). +* ✅ Simplify tests for `dependency_testing`. PR [#13223](https://github.com/fastapi/fastapi/pull/13223) by [@alv2017](https://github.com/alv2017). + +### Docs + +* 🍱 Update sponsors: CodeRabbit logo. PR [#13424](https://github.com/fastapi/fastapi/pull/13424) by [@tiangolo](https://github.com/tiangolo). +* 🩺 Unify the badges across all tutorial translations. PR [#13329](https://github.com/fastapi/fastapi/pull/13329) by [@svlandeg](https://github.com/svlandeg). +* 📝 Fix typos in virtual environments documentation. PR [#13396](https://github.com/fastapi/fastapi/pull/13396) by [@bullet-ant](https://github.com/bullet-ant). +* 🐛 Fix issue with Swagger theme change example in the official tutorial. PR [#13289](https://github.com/fastapi/fastapi/pull/13289) by [@Zerohertz](https://github.com/Zerohertz). +* 📝 Add more precise description of HTTP status code range in docs. PR [#13347](https://github.com/fastapi/fastapi/pull/13347) by [@DanielYang59](https://github.com/DanielYang59). +* 🔥 Remove manual type annotations in JWT tutorial to avoid typing expectations (JWT doesn't provide more types). PR [#13378](https://github.com/fastapi/fastapi/pull/13378) by [@tiangolo](https://github.com/tiangolo). +* 📝 Update docs for Query Params and String Validations, remove obsolete Ellipsis docs (`...`). PR [#13377](https://github.com/fastapi/fastapi/pull/13377) by [@tiangolo](https://github.com/tiangolo). +* ✏️ Remove duplicate title in docs `body-multiple-params`. PR [#13345](https://github.com/fastapi/fastapi/pull/13345) by [@DanielYang59](https://github.com/DanielYang59). +* 📝 Fix test badge. PR [#13313](https://github.com/fastapi/fastapi/pull/13313) by [@esadek](https://github.com/esadek). + +### Translations + +* 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/header-params.md`. PR [#13381](https://github.com/fastapi/fastapi/pull/13381) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). +* 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/request-files.md`. PR [#13395](https://github.com/fastapi/fastapi/pull/13395) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). +* 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/request-form-models.md`. PR [#13384](https://github.com/fastapi/fastapi/pull/13384) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). +* 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/request-forms-and-files.md`. PR [#13386](https://github.com/fastapi/fastapi/pull/13386) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). +* 🌐 Update Korean translation for `docs/ko/docs/help-fastapi.md`. PR [#13262](https://github.com/fastapi/fastapi/pull/13262) by [@Zerohertz](https://github.com/Zerohertz). +* 🌐 Add Korean translation for `docs/ko/docs/advanced/custom-response.md`. PR [#13265](https://github.com/fastapi/fastapi/pull/13265) by [@11kkw](https://github.com/11kkw). +* 🌐 Update Korean translation for `docs/ko/docs/tutorial/security/simple-oauth2.md`. PR [#13335](https://github.com/fastapi/fastapi/pull/13335) by [@yes0ng](https://github.com/yes0ng). +* 🌐 Add Russian translation for `docs/ru/docs/advanced/response-cookies.md`. PR [#13327](https://github.com/fastapi/fastapi/pull/13327) by [@Stepakinoyan](https://github.com/Stepakinoyan). +* 🌐 Add Vietnamese translation for `docs/vi/docs/tutorial/static-files.md`. PR [#11291](https://github.com/fastapi/fastapi/pull/11291) by [@ptt3199](https://github.com/ptt3199). +* 🌐 Add Korean translation for `docs/ko/docs/tutorial/dependencies/dependencies-with-yield.md`. PR [#13257](https://github.com/fastapi/fastapi/pull/13257) by [@11kkw](https://github.com/11kkw). +* 🌐 Add Vietnamese translation for `docs/vi/docs/virtual-environments.md`. PR [#13282](https://github.com/fastapi/fastapi/pull/13282) by [@ptt3199](https://github.com/ptt3199). +* 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/static-files.md`. PR [#13285](https://github.com/fastapi/fastapi/pull/13285) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). +* 🌐 Add Vietnamese translation for `docs/vi/docs/environment-variables.md`. PR [#13287](https://github.com/fastapi/fastapi/pull/13287) by [@ptt3199](https://github.com/ptt3199). +* 🌐 Add Vietnamese translation for `docs/vi/docs/fastapi-cli.md`. PR [#13294](https://github.com/fastapi/fastapi/pull/13294) by [@ptt3199](https://github.com/ptt3199). +* 🌐 Add Ukrainian translation for `docs/uk/docs/features.md`. PR [#13308](https://github.com/fastapi/fastapi/pull/13308) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). +* 🌐 Add Ukrainian translation for `docs/uk/docs/learn/index.md`. PR [#13306](https://github.com/fastapi/fastapi/pull/13306) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). +* 🌐 Update Portuguese Translation for `docs/pt/docs/deployment/https.md`. PR [#13317](https://github.com/fastapi/fastapi/pull/13317) by [@Joao-Pedro-P-Holanda](https://github.com/Joao-Pedro-P-Holanda). +* 🌐 Update Portuguese Translation for `docs/pt/docs/index.md`. PR [#13328](https://github.com/fastapi/fastapi/pull/13328) by [@ceb10n](https://github.com/ceb10n). +* 🌐 Add Russian translation for `docs/ru/docs/advanced/websockets.md`. PR [#13279](https://github.com/fastapi/fastapi/pull/13279) by [@Rishat-F](https://github.com/Rishat-F). + +### Internal + +* ✅ Fix a minor bug in the test `tests/test_modules_same_name_body/test_main.py`. PR [#13411](https://github.com/fastapi/fastapi/pull/13411) by [@alv2017](https://github.com/alv2017). +* 👷 Use `wrangler-action` v3. PR [#13415](https://github.com/fastapi/fastapi/pull/13415) by [@joakimnordling](https://github.com/joakimnordling). +* 🔧 Update sponsors: add CodeRabbit. PR [#13402](https://github.com/fastapi/fastapi/pull/13402) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Update team: Add Ludovico. PR [#13390](https://github.com/fastapi/fastapi/pull/13390) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Update sponsors: Add LambdaTest. PR [#13389](https://github.com/fastapi/fastapi/pull/13389) by [@tiangolo](https://github.com/tiangolo). +* ⬆ Bump cloudflare/wrangler-action from 3.13 to 3.14. PR [#13350](https://github.com/fastapi/fastapi/pull/13350) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump mkdocs-material from 9.5.18 to 9.6.1. PR [#13301](https://github.com/fastapi/fastapi/pull/13301) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump pillow from 11.0.0 to 11.1.0. PR [#13300](https://github.com/fastapi/fastapi/pull/13300) by [@dependabot[bot]](https://github.com/apps/dependabot). +* 👥 Update FastAPI People - Sponsors. PR [#13295](https://github.com/fastapi/fastapi/pull/13295) by [@tiangolo](https://github.com/tiangolo). +* 👥 Update FastAPI People - Experts. PR [#13303](https://github.com/fastapi/fastapi/pull/13303) by [@tiangolo](https://github.com/tiangolo). +* 👥 Update FastAPI GitHub topic repositories. PR [#13302](https://github.com/fastapi/fastapi/pull/13302) by [@tiangolo](https://github.com/tiangolo). +* 👥 Update FastAPI People - Contributors and Translators. PR [#13293](https://github.com/fastapi/fastapi/pull/13293) by [@tiangolo](https://github.com/tiangolo). +* ⬆ Bump inline-snapshot from 0.18.1 to 0.19.3. PR [#13298](https://github.com/fastapi/fastapi/pull/13298) by [@dependabot[bot]](https://github.com/apps/dependabot). +* 🔧 Update sponsors, add Permit. PR [#13288](https://github.com/fastapi/fastapi/pull/13288) by [@tiangolo](https://github.com/tiangolo). + +## 0.115.8 (2025-01-30) + +### Fixes + +* 🐛 Fix `OAuth2PasswordRequestForm` and `OAuth2PasswordRequestFormStrict` fixed `grant_type` "password" RegEx. PR [#9783](https://github.com/fastapi/fastapi/pull/9783) by [@skarfie123](https://github.com/skarfie123). + +### Refactors + +* ✅ Simplify tests for body_multiple_params . PR [#13237](https://github.com/fastapi/fastapi/pull/13237) by [@alejsdev](https://github.com/alejsdev). +* ♻️ Move duplicated code portion to a static method in the `APIKeyBase` super class. PR [#3142](https://github.com/fastapi/fastapi/pull/3142) by [@ShahriyarR](https://github.com/ShahriyarR). +* ✅ Simplify tests for request_files. PR [#13182](https://github.com/fastapi/fastapi/pull/13182) by [@alejsdev](https://github.com/alejsdev). + +### Docs + +* 📝 Change the word "unwrap" to "unpack" in `docs/en/docs/tutorial/extra-models.md`. PR [#13061](https://github.com/fastapi/fastapi/pull/13061) by [@timothy-jeong](https://github.com/timothy-jeong). +* 📝 Update Request Body's `tutorial002` to deal with `tax=0` case. PR [#13230](https://github.com/fastapi/fastapi/pull/13230) by [@togogh](https://github.com/togogh). +* 👥 Update FastAPI People - Experts. PR [#13269](https://github.com/fastapi/fastapi/pull/13269) by [@tiangolo](https://github.com/tiangolo). + +### Translations + +* 🌐 Add Japanese translation for `docs/ja/docs/environment-variables.md`. PR [#13226](https://github.com/fastapi/fastapi/pull/13226) by [@k94-ishi](https://github.com/k94-ishi). +* 🌐 Add Russian translation for `docs/ru/docs/advanced/async-tests.md`. PR [#13227](https://github.com/fastapi/fastapi/pull/13227) by [@Rishat-F](https://github.com/Rishat-F). +* 🌐 Update Russian translation for `docs/ru/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md`. PR [#13252](https://github.com/fastapi/fastapi/pull/13252) by [@Rishat-F](https://github.com/Rishat-F). +* 🌐 Add Russian translation for `docs/ru/docs/tutorial/bigger-applications.md`. PR [#13154](https://github.com/fastapi/fastapi/pull/13154) by [@alv2017](https://github.com/alv2017). + +### Internal + +* ⬆️ Add support for Python 3.13. PR [#13274](https://github.com/fastapi/fastapi/pull/13274) by [@tiangolo](https://github.com/tiangolo). +* ⬆️ Upgrade AnyIO max version for tests, new range: `>=3.2.1,<5.0.0`. PR [#13273](https://github.com/fastapi/fastapi/pull/13273) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Update Sponsors badges. PR [#13271](https://github.com/fastapi/fastapi/pull/13271) by [@tiangolo](https://github.com/tiangolo). +* ♻️ Fix `notify_translations.py` empty env var handling for PR label events vs workflow_dispatch. PR [#13272](https://github.com/fastapi/fastapi/pull/13272) by [@tiangolo](https://github.com/tiangolo). +* ♻️ Refactor and move `scripts/notify_translations.py`, no need for a custom GitHub Action. PR [#13270](https://github.com/fastapi/fastapi/pull/13270) by [@tiangolo](https://github.com/tiangolo). +* 🔨 Update FastAPI People Experts script, refactor and optimize data fetching to handle rate limits. PR [#13267](https://github.com/fastapi/fastapi/pull/13267) by [@tiangolo](https://github.com/tiangolo). +* ⬆ Bump pypa/gh-action-pypi-publish from 1.12.3 to 1.12.4. PR [#13251](https://github.com/fastapi/fastapi/pull/13251) by [@dependabot[bot]](https://github.com/apps/dependabot). + +## 0.115.7 (2025-01-22) + +### Upgrades + +* ⬆️ Upgrade `python-multipart` to >=0.0.18. PR [#13219](https://github.com/fastapi/fastapi/pull/13219) by [@DanielKusyDev](https://github.com/DanielKusyDev). +* ⬆️ Bump Starlette to allow up to 0.45.0: `>=0.40.0,<0.46.0`. PR [#13117](https://github.com/fastapi/fastapi/pull/13117) by [@Kludex](https://github.com/Kludex). +* ⬆️ Upgrade `jinja2` to >=3.1.5. PR [#13194](https://github.com/fastapi/fastapi/pull/13194) by [@DanielKusyDev](https://github.com/DanielKusyDev). + +### Refactors + +* ✅ Simplify tests for websockets. PR [#13202](https://github.com/fastapi/fastapi/pull/13202) by [@alejsdev](https://github.com/alejsdev). +* ✅ Simplify tests for request_form_models . PR [#13183](https://github.com/fastapi/fastapi/pull/13183) by [@alejsdev](https://github.com/alejsdev). +* ✅ Simplify tests for separate_openapi_schemas. PR [#13201](https://github.com/fastapi/fastapi/pull/13201) by [@alejsdev](https://github.com/alejsdev). +* ✅ Simplify tests for security. PR [#13200](https://github.com/fastapi/fastapi/pull/13200) by [@alejsdev](https://github.com/alejsdev). +* ✅ Simplify tests for schema_extra_example. PR [#13197](https://github.com/fastapi/fastapi/pull/13197) by [@alejsdev](https://github.com/alejsdev). +* ✅ Simplify tests for request_model. PR [#13195](https://github.com/fastapi/fastapi/pull/13195) by [@alejsdev](https://github.com/alejsdev). +* ✅ Simplify tests for request_forms_and_files. PR [#13185](https://github.com/fastapi/fastapi/pull/13185) by [@alejsdev](https://github.com/alejsdev). +* ✅ Simplify tests for request_forms. PR [#13184](https://github.com/fastapi/fastapi/pull/13184) by [@alejsdev](https://github.com/alejsdev). +* ✅ Simplify tests for path_query_params. PR [#13181](https://github.com/fastapi/fastapi/pull/13181) by [@alejsdev](https://github.com/alejsdev). +* ✅ Simplify tests for path_operation_configurations. PR [#13180](https://github.com/fastapi/fastapi/pull/13180) by [@alejsdev](https://github.com/alejsdev). +* ✅ Simplify tests for header_params. PR [#13179](https://github.com/fastapi/fastapi/pull/13179) by [@alejsdev](https://github.com/alejsdev). +* ✅ Simplify tests for extra_models. PR [#13178](https://github.com/fastapi/fastapi/pull/13178) by [@alejsdev](https://github.com/alejsdev). +* ✅ Simplify tests for extra_data_types. PR [#13177](https://github.com/fastapi/fastapi/pull/13177) by [@alejsdev](https://github.com/alejsdev). +* ✅ Simplify tests for cookie_params. PR [#13176](https://github.com/fastapi/fastapi/pull/13176) by [@alejsdev](https://github.com/alejsdev). +* ✅ Simplify tests for dependencies. PR [#13174](https://github.com/fastapi/fastapi/pull/13174) by [@alejsdev](https://github.com/alejsdev). +* ✅ Simplify tests for body_updates. PR [#13172](https://github.com/fastapi/fastapi/pull/13172) by [@alejsdev](https://github.com/alejsdev). +* ✅ Simplify tests for body_nested_models. PR [#13171](https://github.com/fastapi/fastapi/pull/13171) by [@alejsdev](https://github.com/alejsdev). +* ✅ Simplify tests for body_multiple_params. PR [#13170](https://github.com/fastapi/fastapi/pull/13170) by [@alejsdev](https://github.com/alejsdev). +* ✅ Simplify tests for body_fields. PR [#13169](https://github.com/fastapi/fastapi/pull/13169) by [@alejsdev](https://github.com/alejsdev). +* ✅ Simplify tests for body. PR [#13168](https://github.com/fastapi/fastapi/pull/13168) by [@alejsdev](https://github.com/alejsdev). +* ✅ Simplify tests for bigger_applications. PR [#13167](https://github.com/fastapi/fastapi/pull/13167) by [@alejsdev](https://github.com/alejsdev). +* ✅ Simplify tests for background_tasks. PR [#13166](https://github.com/fastapi/fastapi/pull/13166) by [@alejsdev](https://github.com/alejsdev). +* ✅ Simplify tests for additional_status_codes. PR [#13149](https://github.com/fastapi/fastapi/pull/13149) by [@tiangolo](https://github.com/tiangolo). + +### Docs + +* ✏️ Update Strawberry integration docs. PR [#13155](https://github.com/fastapi/fastapi/pull/13155) by [@kinuax](https://github.com/kinuax). +* 🔥 Remove unused Peewee tutorial files. PR [#13158](https://github.com/fastapi/fastapi/pull/13158) by [@alejsdev](https://github.com/alejsdev). +* 📝 Update image in body-nested-model docs. PR [#11063](https://github.com/fastapi/fastapi/pull/11063) by [@untilhamza](https://github.com/untilhamza). +* 📝 Update `fastapi-cli` UI examples in docs. PR [#13107](https://github.com/fastapi/fastapi/pull/13107) by [@Zhongheng-Cheng](https://github.com/Zhongheng-Cheng). +* 👷 Add new GitHub Action to update contributors, translators, and translation reviewers. PR [#13136](https://github.com/fastapi/fastapi/pull/13136) by [@tiangolo](https://github.com/tiangolo). +* ✏️ Fix typo in `docs/en/docs/virtual-environments.md`. PR [#13124](https://github.com/fastapi/fastapi/pull/13124) by [@tiangolo](https://github.com/tiangolo). +* ✏️ Fix error in `docs/en/docs/contributing.md`. PR [#12899](https://github.com/fastapi/fastapi/pull/12899) by [@kingsubin](https://github.com/kingsubin). +* 📝 Minor corrections in `docs/en/docs/tutorial/sql-databases.md`. PR [#13081](https://github.com/fastapi/fastapi/pull/13081) by [@alv2017](https://github.com/alv2017). +* 📝 Update includes in `docs/ru/docs/tutorial/query-param-models.md`. PR [#12994](https://github.com/fastapi/fastapi/pull/12994) by [@alejsdev](https://github.com/alejsdev). +* ✏️ Fix typo in README installation instructions. PR [#13011](https://github.com/fastapi/fastapi/pull/13011) by [@dave-hay](https://github.com/dave-hay). +* 📝 Update docs for `fastapi-cli`. PR [#13031](https://github.com/fastapi/fastapi/pull/13031) by [@tiangolo](https://github.com/tiangolo). + +### Translations + +* 🌐 Update Portuguese Translation for `docs/pt/docs/tutorial/request-forms.md`. PR [#13216](https://github.com/fastapi/fastapi/pull/13216) by [@Joao-Pedro-P-Holanda](https://github.com/Joao-Pedro-P-Holanda). +* 🌐 Update Portuguese translation for `docs/pt/docs/advanced/settings.md`. PR [#13209](https://github.com/fastapi/fastapi/pull/13209) by [@ceb10n](https://github.com/ceb10n). +* 🌐 Add Portuguese translation for `docs/pt/docs/tutorial/security/oauth2-jwt.md`. PR [#13205](https://github.com/fastapi/fastapi/pull/13205) by [@ceb10n](https://github.com/ceb10n). +* 🌐 Add Indonesian translation for `docs/id/docs/index.md`. PR [#13191](https://github.com/fastapi/fastapi/pull/13191) by [@gerry-sabar](https://github.com/gerry-sabar). +* 🌐 Add Indonesian translation for `docs/id/docs/tutorial/static-files.md`. PR [#13092](https://github.com/fastapi/fastapi/pull/13092) by [@guspan-tanadi](https://github.com/guspan-tanadi). +* 🌐 Add Portuguese translation for `docs/pt/docs/tutorial/security/get-current-user.md`. PR [#13188](https://github.com/fastapi/fastapi/pull/13188) by [@ceb10n](https://github.com/ceb10n). +* 🌐 Remove Wrong Portuguese translations location for `docs/pt/docs/advanced/benchmarks.md`. PR [#13187](https://github.com/fastapi/fastapi/pull/13187) by [@ceb10n](https://github.com/ceb10n). +* 🌐 Update Portuguese translations. PR [#13156](https://github.com/fastapi/fastapi/pull/13156) by [@nillvitor](https://github.com/nillvitor). +* 🌐 Update Russian translation for `docs/ru/docs/tutorial/security/first-steps.md`. PR [#13159](https://github.com/fastapi/fastapi/pull/13159) by [@Yarous](https://github.com/Yarous). +* ✏️ Delete unnecessary backspace in `docs/ja/docs/tutorial/path-params-numeric-validations.md`. PR [#12238](https://github.com/fastapi/fastapi/pull/12238) by [@FakeDocument](https://github.com/FakeDocument). +* 🌐 Update Chinese translation for `docs/zh/docs/fastapi-cli.md`. PR [#13102](https://github.com/fastapi/fastapi/pull/13102) by [@Zhongheng-Cheng](https://github.com/Zhongheng-Cheng). +* 🌐 Add new Spanish translations for all docs with new LLM-assisted system using PydanticAI. PR [#13122](https://github.com/fastapi/fastapi/pull/13122) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update existing Spanish translations using the new LLM-assisted system using PydanticAI. PR [#13118](https://github.com/fastapi/fastapi/pull/13118) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update Chinese translation for `docs/zh/docs/advanced/security/oauth2-scopes.md`. PR [#13110](https://github.com/fastapi/fastapi/pull/13110) by [@ChenPu2002](https://github.com/ChenPu2002). +* 🌐 Add Indonesian translation for `docs/id/docs/tutorial/path-params.md`. PR [#13086](https://github.com/fastapi/fastapi/pull/13086) by [@gerry-sabar](https://github.com/gerry-sabar). +* 🌐 Add Korean translation for `docs/ko/docs/tutorial/sql-databases.md`. PR [#13093](https://github.com/fastapi/fastapi/pull/13093) by [@GeumBinLee](https://github.com/GeumBinLee). +* 🌐 Update Chinese translation for `docs/zh/docs/async.md`. PR [#13095](https://github.com/fastapi/fastapi/pull/13095) by [@Zhongheng-Cheng](https://github.com/Zhongheng-Cheng). +* 🌐 Add Chinese translation for `docs/zh/docs/advanced/openapi-webhooks.md`. PR [#13091](https://github.com/fastapi/fastapi/pull/13091) by [@Zhongheng-Cheng](https://github.com/Zhongheng-Cheng). +* 🌐 Add Chinese translation for `docs/zh/docs/advanced/async-tests.md`. PR [#13074](https://github.com/fastapi/fastapi/pull/13074) by [@Zhongheng-Cheng](https://github.com/Zhongheng-Cheng). +* 🌐 Add Ukrainian translation for `docs/uk/docs/fastapi-cli.md`. PR [#13020](https://github.com/fastapi/fastapi/pull/13020) by [@ykertytsky](https://github.com/ykertytsky). +* 🌐 Add Chinese translation for `docs/zh/docs/advanced/events.md`. PR [#12512](https://github.com/fastapi/fastapi/pull/12512) by [@ZhibangYue](https://github.com/ZhibangYue). +* 🌐 Add Russian translation for `/docs/ru/docs/tutorial/sql-databases.md`. PR [#13079](https://github.com/fastapi/fastapi/pull/13079) by [@alv2017](https://github.com/alv2017). +* 🌐 Update Chinese translation for `docs/zh/docs/advanced/testing-dependencies.md`. PR [#13066](https://github.com/fastapi/fastapi/pull/13066) by [@Zhongheng-Cheng](https://github.com/Zhongheng-Cheng). +* 🌐 Update Traditional Chinese translation for `docs/zh-hant/docs/tutorial/index.md`. PR [#13075](https://github.com/fastapi/fastapi/pull/13075) by [@codingjenny](https://github.com/codingjenny). +* 🌐 Add Chinese translation for `docs/zh/docs/tutorial/sql-databases.md`. PR [#13051](https://github.com/fastapi/fastapi/pull/13051) by [@Zhongheng-Cheng](https://github.com/Zhongheng-Cheng). +* 🌐 Update Chinese translation for `docs/zh/docs/tutorial/query-params-str-validations.md`. PR [#12928](https://github.com/fastapi/fastapi/pull/12928) by [@Vincy1230](https://github.com/Vincy1230). +* 🌐 Add Chinese translation for `docs/zh/docs/tutorial/header-param-models.md`. PR [#13040](https://github.com/fastapi/fastapi/pull/13040) by [@Zhongheng-Cheng](https://github.com/Zhongheng-Cheng). +* 🌐 Update Chinese translation for `docs/zh/docs/tutorial/path-params.md`. PR [#12926](https://github.com/fastapi/fastapi/pull/12926) by [@Vincy1230](https://github.com/Vincy1230). +* 🌐 Update Chinese translation for `docs/zh/docs/tutorial/first-steps.md`. PR [#12923](https://github.com/fastapi/fastapi/pull/12923) by [@Vincy1230](https://github.com/Vincy1230). +* 🌐 Update Russian translation for `docs/ru/docs/deployment/docker.md`. PR [#13048](https://github.com/fastapi/fastapi/pull/13048) by [@anklav24](https://github.com/anklav24). +* 🌐 Add Portuguese translation for `docs/pt/docs/advanced/generate-clients.md`. PR [#13030](https://github.com/fastapi/fastapi/pull/13030) by [@vitumenezes](https://github.com/vitumenezes). +* 🌐 Add Indonesian translation for `docs/id/docs/tutorial/first-steps.md`. PR [#13042](https://github.com/fastapi/fastapi/pull/13042) by [@gerry-sabar](https://github.com/gerry-sabar). +* 🌐 Add Chinese translation for `docs/zh/docs/tutorial/cookie-param-models.md`. PR [#13038](https://github.com/fastapi/fastapi/pull/13038) by [@Zhongheng-Cheng](https://github.com/Zhongheng-Cheng). +* 🌐 Add Chinese translation for `docs/zh/docs/tutorial/request-form-models.md`. PR [#13045](https://github.com/fastapi/fastapi/pull/13045) by [@Zhongheng-Cheng](https://github.com/Zhongheng-Cheng). +* 🌐 Add Russian translation for `docs/ru/docs/virtual-environments.md`. PR [#13026](https://github.com/fastapi/fastapi/pull/13026) by [@alv2017](https://github.com/alv2017). +* 🌐 Add Korean translation for `docs/ko/docs/tutorial/testing.md`. PR [#12968](https://github.com/fastapi/fastapi/pull/12968) by [@jts8257](https://github.com/jts8257). +* 🌐 Add Korean translation for `docs/ko/docs/advanced/async-test.md`. PR [#12918](https://github.com/fastapi/fastapi/pull/12918) by [@icehongssii](https://github.com/icehongssii). +* 🌐 Add Russian translation for `docs/ru/docs/tutorial/security/oauth2-jwt.md`. PR [#10601](https://github.com/fastapi/fastapi/pull/10601) by [@AlertRED](https://github.com/AlertRED). +* 🌐 Add Russian translation for `docs/ru/docs/tutorial/security/simple-oauth2.md`. PR [#10599](https://github.com/fastapi/fastapi/pull/10599) by [@AlertRED](https://github.com/AlertRED). +* 🌐 Add Russian translation for `docs/ru/docs/tutorial/security/get-current-user.md`. PR [#10594](https://github.com/fastapi/fastapi/pull/10594) by [@AlertRED](https://github.com/AlertRED). +* 🌐 Add Traditional Chinese translation for `docs/zh-hant/docs/features.md`. PR [#12441](https://github.com/fastapi/fastapi/pull/12441) by [@codingjenny](https://github.com/codingjenny). +* 🌐 Add Traditional Chinese translation for `docs/zh-hant/docs/virtual-environments.md`. PR [#12791](https://github.com/fastapi/fastapi/pull/12791) by [@Vincy1230](https://github.com/Vincy1230). +* 🌐 Add Korean translation for `docs/ko/docs/advanced/templates.md`. PR [#12726](https://github.com/fastapi/fastapi/pull/12726) by [@Heumhub](https://github.com/Heumhub). +* 🌐 Add Russian translation for `docs/ru/docs/fastapi-cli.md`. PR [#13041](https://github.com/fastapi/fastapi/pull/13041) by [@alv2017](https://github.com/alv2017). +* 🌐 Add Korean translation for `docs/ko/docs/tutorial/cookie-param-models.md`. PR [#13000](https://github.com/fastapi/fastapi/pull/13000) by [@hard-coders](https://github.com/hard-coders). +* 🌐 Add Korean translation for `docs/ko/docs/tutorial/header-param-models.md`. PR [#13001](https://github.com/fastapi/fastapi/pull/13001) by [@hard-coders](https://github.com/hard-coders). +* 🌐 Add Korean translation for `docs/ko/docs/tutorial/request-form-models.md`. PR [#13002](https://github.com/fastapi/fastapi/pull/13002) by [@hard-coders](https://github.com/hard-coders). +* 🌐 Add Korean translation for `docs/ko/docs/tutorial/request-forms.md`. PR [#13003](https://github.com/fastapi/fastapi/pull/13003) by [@hard-coders](https://github.com/hard-coders). +* 🌐 Add Korean translation for `docs/ko/docs/resources/index.md`. PR [#13004](https://github.com/fastapi/fastapi/pull/13004) by [@hard-coders](https://github.com/hard-coders). +* 🌐 Add Korean translation for `docs/ko/docs/how-to/configure-swagger-ui.md`. PR [#12898](https://github.com/fastapi/fastapi/pull/12898) by [@nahyunkeem](https://github.com/nahyunkeem). +* 🌐 Add Korean translation to `docs/ko/docs/advanced/additional-status-codes.md`. PR [#12715](https://github.com/fastapi/fastapi/pull/12715) by [@nahyunkeem](https://github.com/nahyunkeem). +* 🌐 Add Traditional Chinese translation for `docs/zh-hant/docs/tutorial/first-steps.md`. PR [#12467](https://github.com/fastapi/fastapi/pull/12467) by [@codingjenny](https://github.com/codingjenny). + +### Internal + +* 🔧 Add Pydantic 2 trove classifier. PR [#13199](https://github.com/fastapi/fastapi/pull/13199) by [@johnthagen](https://github.com/johnthagen). +* 👥 Update FastAPI People - Sponsors. PR [#13231](https://github.com/fastapi/fastapi/pull/13231) by [@tiangolo](https://github.com/tiangolo). +* 👷 Refactor FastAPI People Sponsors to use 2 tokens. PR [#13228](https://github.com/fastapi/fastapi/pull/13228) by [@tiangolo](https://github.com/tiangolo). +* 👷 Update token for FastAPI People - Sponsors. PR [#13225](https://github.com/fastapi/fastapi/pull/13225) by [@tiangolo](https://github.com/tiangolo). +* 👷 Add independent CI automation for FastAPI People - Sponsors. PR [#13221](https://github.com/fastapi/fastapi/pull/13221) by [@tiangolo](https://github.com/tiangolo). +* 👷 Add retries to Smokeshow. PR [#13151](https://github.com/fastapi/fastapi/pull/13151) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Update Speakeasy sponsor graphic. PR [#13147](https://github.com/fastapi/fastapi/pull/13147) by [@chailandau](https://github.com/chailandau). +* 👥 Update FastAPI GitHub topic repositories. PR [#13146](https://github.com/fastapi/fastapi/pull/13146) by [@tiangolo](https://github.com/tiangolo). +* 👷‍♀️ Add script for GitHub Topic Repositories and update External Links. PR [#13135](https://github.com/fastapi/fastapi/pull/13135) by [@alejsdev](https://github.com/alejsdev). +* 👥 Update FastAPI People - Contributors and Translators. PR [#13145](https://github.com/fastapi/fastapi/pull/13145) by [@tiangolo](https://github.com/tiangolo). +* ⬆ Bump markdown-include-variants from 0.0.3 to 0.0.4. PR [#13129](https://github.com/fastapi/fastapi/pull/13129) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump inline-snapshot from 0.14.0 to 0.18.1. PR [#13132](https://github.com/fastapi/fastapi/pull/13132) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump mkdocs-macros-plugin from 1.0.5 to 1.3.7. PR [#13133](https://github.com/fastapi/fastapi/pull/13133) by [@dependabot[bot]](https://github.com/apps/dependabot). +* 🔨 Add internal scripts to generate language translations with PydanticAI, include Spanish prompt. PR [#13123](https://github.com/fastapi/fastapi/pull/13123) by [@tiangolo](https://github.com/tiangolo). +* ⬆ Bump astral-sh/setup-uv from 4 to 5. PR [#13096](https://github.com/fastapi/fastapi/pull/13096) by [@dependabot[bot]](https://github.com/apps/dependabot). +* 🔧 Update sponsors: rename CryptAPI to BlockBee. PR [#13078](https://github.com/fastapi/fastapi/pull/13078) by [@tiangolo](https://github.com/tiangolo). +* ⬆ Bump pypa/gh-action-pypi-publish from 1.12.2 to 1.12.3. PR [#13055](https://github.com/fastapi/fastapi/pull/13055) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump types-ujson from 5.7.0.1 to 5.10.0.20240515. PR [#13018](https://github.com/fastapi/fastapi/pull/13018) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump black from 24.3.0 to 24.10.0. PR [#13014](https://github.com/fastapi/fastapi/pull/13014) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump inline-snapshot from 0.13.0 to 0.14.0. PR [#13017](https://github.com/fastapi/fastapi/pull/13017) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump dirty-equals from 0.6.0 to 0.8.0. PR [#13015](https://github.com/fastapi/fastapi/pull/13015) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump cloudflare/wrangler-action from 3.12 to 3.13. PR [#12996](https://github.com/fastapi/fastapi/pull/12996) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump astral-sh/setup-uv from 3 to 4. PR [#12982](https://github.com/fastapi/fastapi/pull/12982) by [@dependabot[bot]](https://github.com/apps/dependabot). +* 🔧 Remove duplicate actions/checkout in `notify-translations.yml`. PR [#12915](https://github.com/fastapi/fastapi/pull/12915) by [@tinyboxvk](https://github.com/tinyboxvk). +* 🔧 Update team members. PR [#13033](https://github.com/fastapi/fastapi/pull/13033) by [@tiangolo](https://github.com/tiangolo). +* 📝 Update sponsors: remove Codacy. PR [#13032](https://github.com/fastapi/fastapi/pull/13032) by [@tiangolo](https://github.com/tiangolo). + +## 0.115.6 (2024-12-03) + +### Fixes + +* 🐛 Preserve traceback when an exception is raised in sync dependency with `yield`. PR [#5823](https://github.com/fastapi/fastapi/pull/5823) by [@sombek](https://github.com/sombek). + +### Refactors + +* ♻️ Update tests and internals for compatibility with Pydantic >=2.10. PR [#12971](https://github.com/fastapi/fastapi/pull/12971) by [@tamird](https://github.com/tamird). + +### Docs + +* 📝 Update includes format in docs with an automated script. PR [#12950](https://github.com/fastapi/fastapi/pull/12950) by [@tiangolo](https://github.com/tiangolo). +* 📝 Update includes for `docs/de/docs/advanced/using-request-directly.md`. PR [#12685](https://github.com/fastapi/fastapi/pull/12685) by [@alissadb](https://github.com/alissadb). +* 📝 Update includes for `docs/de/docs/how-to/conditional-openapi.md`. PR [#12689](https://github.com/fastapi/fastapi/pull/12689) by [@alissadb](https://github.com/alissadb). + +### Translations + +* 🌐 Add Traditional Chinese translation for `docs/zh-hant/docs/async.md`. PR [#12990](https://github.com/fastapi/fastapi/pull/12990) by [@ILoveSorasakiHina](https://github.com/ILoveSorasakiHina). +* 🌐 Add Traditional Chinese translation for `docs/zh-hant/docs/tutorial/query-param-models.md`. PR [#12932](https://github.com/fastapi/fastapi/pull/12932) by [@Vincy1230](https://github.com/Vincy1230). +* 🌐 Add Korean translation for `docs/ko/docs/advanced/testing-dependencies.md`. PR [#12992](https://github.com/fastapi/fastapi/pull/12992) by [@Limsunoh](https://github.com/Limsunoh). +* 🌐 Add Korean translation for `docs/ko/docs/advanced/websockets.md`. PR [#12991](https://github.com/fastapi/fastapi/pull/12991) by [@kwang1215](https://github.com/kwang1215). +* 🌐 Add Portuguese translation for `docs/pt/docs/tutorial/response-model.md`. PR [#12933](https://github.com/fastapi/fastapi/pull/12933) by [@AndreBBM](https://github.com/AndreBBM). +* 🌐 Add Korean translation for `docs/ko/docs/advanced/middlewares.md`. PR [#12753](https://github.com/fastapi/fastapi/pull/12753) by [@nahyunkeem](https://github.com/nahyunkeem). +* 🌐 Add Korean translation for `docs/ko/docs/advanced/openapi-webhooks.md`. PR [#12752](https://github.com/fastapi/fastapi/pull/12752) by [@saeye](https://github.com/saeye). +* 🌐 Add Chinese translation for `docs/zh/docs/tutorial/query-param-models.md`. PR [#12931](https://github.com/fastapi/fastapi/pull/12931) by [@Vincy1230](https://github.com/Vincy1230). +* 🌐 Add Russian translation for `docs/ru/docs/tutorial/query-param-models.md`. PR [#12445](https://github.com/fastapi/fastapi/pull/12445) by [@gitgernit](https://github.com/gitgernit). +* 🌐 Add Korean translation for `docs/ko/docs/tutorial/query-param-models.md`. PR [#12940](https://github.com/fastapi/fastapi/pull/12940) by [@jts8257](https://github.com/jts8257). +* 🔥 Remove obsolete tutorial translation to Chinese for `docs/zh/docs/tutorial/sql-databases.md`, it references files that are no longer on the repo. PR [#12949](https://github.com/fastapi/fastapi/pull/12949) by [@tiangolo](https://github.com/tiangolo). + +### Internal + +* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#12954](https://github.com/fastapi/fastapi/pull/12954) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). + +## 0.115.5 (2024-11-12) + +### Refactors + +* ♻️ Update internal checks to support Pydantic 2.10. PR [#12914](https://github.com/fastapi/fastapi/pull/12914) by [@tiangolo](https://github.com/tiangolo). + +### Docs + +* 📝 Update includes for `docs/en/docs/tutorial/body.md`. PR [#12757](https://github.com/fastapi/fastapi/pull/12757) by [@gsheni](https://github.com/gsheni). +* 📝 Update includes in `docs/en/docs/advanced/testing-dependencies.md`. PR [#12647](https://github.com/fastapi/fastapi/pull/12647) by [@AyushSinghal1794](https://github.com/AyushSinghal1794). +* 📝 Update includes for `docs/en/docs/tutorial/metadata.md`. PR [#12773](https://github.com/fastapi/fastapi/pull/12773) by [@Nimitha-jagadeesha](https://github.com/Nimitha-jagadeesha). +* 📝 Update `docs/en/docs/tutorial/dependencies/dependencies-with-yield.md`. PR [#12045](https://github.com/fastapi/fastapi/pull/12045) by [@xuvjso](https://github.com/xuvjso). +* 📝 Update includes for `docs/en/docs/tutorial/dependencies/global-dependencies.md`. PR [#12653](https://github.com/fastapi/fastapi/pull/12653) by [@vishnuvskvkl](https://github.com/vishnuvskvkl). +* 📝 Update includes for `docs/en/docs/tutorial/body-updates.md`. PR [#12712](https://github.com/fastapi/fastapi/pull/12712) by [@davioc](https://github.com/davioc). +* 📝 Remove mention of Celery in the project generators. PR [#12742](https://github.com/fastapi/fastapi/pull/12742) by [@david-caro](https://github.com/david-caro). +* 📝 Update includes in `docs/en/docs/tutorial/header-param-models.md`. PR [#12814](https://github.com/fastapi/fastapi/pull/12814) by [@zhaohan-dong](https://github.com/zhaohan-dong). +* 📝 Update `contributing.md` docs, include note to not translate this page. PR [#12841](https://github.com/fastapi/fastapi/pull/12841) by [@tiangolo](https://github.com/tiangolo). +* 📝 Update includes in `docs/en/docs/tutorial/request-forms.md`. PR [#12648](https://github.com/fastapi/fastapi/pull/12648) by [@vishnuvskvkl](https://github.com/vishnuvskvkl). +* 📝 Update includes in `docs/en/docs/tutorial/request-form-models.md`. PR [#12649](https://github.com/fastapi/fastapi/pull/12649) by [@vishnuvskvkl](https://github.com/vishnuvskvkl). +* 📝 Update includes in `docs/en/docs/tutorial/security/oauth2-jwt.md`. PR [#12650](https://github.com/fastapi/fastapi/pull/12650) by [@OCE1960](https://github.com/OCE1960). +* 📝 Update includes in `docs/vi/docs/tutorial/first-steps.md`. PR [#12754](https://github.com/fastapi/fastapi/pull/12754) by [@MxPy](https://github.com/MxPy). +* 📝 Update includes for `docs/pt/docs/advanced/wsgi.md`. PR [#12769](https://github.com/fastapi/fastapi/pull/12769) by [@Nimitha-jagadeesha](https://github.com/Nimitha-jagadeesha). +* 📝 Update includes for `docs/en/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md`. PR [#12815](https://github.com/fastapi/fastapi/pull/12815) by [@handabaldeep](https://github.com/handabaldeep). +* 📝 Update includes for `docs/en/docs/tutorial/dependencies/classes-as-dependencies.md`. PR [#12813](https://github.com/fastapi/fastapi/pull/12813) by [@handabaldeep](https://github.com/handabaldeep). +* ✏️ Fix error in `docs/en/docs/tutorial/middleware.md`. PR [#12819](https://github.com/fastapi/fastapi/pull/12819) by [@alejsdev](https://github.com/alejsdev). +* 📝 Update includes for `docs/en/docs/tutorial/security/get-current-user.md`. PR [#12645](https://github.com/fastapi/fastapi/pull/12645) by [@OCE1960](https://github.com/OCE1960). +* 📝 Update includes for `docs/en/docs/tutorial/security/first-steps.md`. PR [#12643](https://github.com/fastapi/fastapi/pull/12643) by [@OCE1960](https://github.com/OCE1960). +* 📝 Update includes in `docs/de/docs/advanced/additional-responses.md`. PR [#12821](https://github.com/fastapi/fastapi/pull/12821) by [@zhaohan-dong](https://github.com/zhaohan-dong). +* 📝 Update includes in `docs/en/docs/advanced/generate-clients.md`. PR [#12642](https://github.com/fastapi/fastapi/pull/12642) by [@AyushSinghal1794](https://github.com/AyushSinghal1794). +* 📝 Fix admonition double quotes with new syntax. PR [#12835](https://github.com/fastapi/fastapi/pull/12835) by [@tiangolo](https://github.com/tiangolo). +* 📝 Update includes in `docs/zh/docs/advanced/additional-responses.md`. PR [#12828](https://github.com/fastapi/fastapi/pull/12828) by [@zhaohan-dong](https://github.com/zhaohan-dong). +* 📝 Update includes in `docs/en/docs/tutorial/path-params-numeric-validations.md`. PR [#12825](https://github.com/fastapi/fastapi/pull/12825) by [@zhaohan-dong](https://github.com/zhaohan-dong). +* 📝 Update includes for `docs/en/docs/advanced/testing-websockets.md`. PR [#12761](https://github.com/fastapi/fastapi/pull/12761) by [@hamidrasti](https://github.com/hamidrasti). +* 📝 Update includes for `docs/en/docs/advanced/using-request-directly.md`. PR [#12760](https://github.com/fastapi/fastapi/pull/12760) by [@hamidrasti](https://github.com/hamidrasti). +* 📝 Update includes for `docs/advanced/wsgi.md`. PR [#12758](https://github.com/fastapi/fastapi/pull/12758) by [@hamidrasti](https://github.com/hamidrasti). +* 📝 Update includes in `docs/de/docs/tutorial/middleware.md`. PR [#12729](https://github.com/fastapi/fastapi/pull/12729) by [@paintdog](https://github.com/paintdog). +* 📝 Update includes for `docs/en/docs/tutorial/schema-extra-example.md`. PR [#12822](https://github.com/fastapi/fastapi/pull/12822) by [@tiangolo](https://github.com/tiangolo). +* 📝 Update includes in `docs/fr/docs/advanced/additional-responses.md`. PR [#12634](https://github.com/fastapi/fastapi/pull/12634) by [@fegmorte](https://github.com/fegmorte). +* 📝 Update includes in `docs/fr/docs/advanced/path-operation-advanced-configuration.md`. PR [#12633](https://github.com/fastapi/fastapi/pull/12633) by [@kantandane](https://github.com/kantandane). +* 📝 Update includes in `docs/fr/docs/advanced/response-directly.md`. PR [#12632](https://github.com/fastapi/fastapi/pull/12632) by [@kantandane](https://github.com/kantandane). +* 📝 Update includes for `docs/en/docs/tutorial/header-params.md`. PR [#12640](https://github.com/fastapi/fastapi/pull/12640) by [@vishnuvskvkl](https://github.com/vishnuvskvkl). +* 📝 Update includes in `docs/en/docs/tutorial/cookie-param-models.md`. PR [#12639](https://github.com/fastapi/fastapi/pull/12639) by [@vishnuvskvkl](https://github.com/vishnuvskvkl). +* 📝 Update includes for `docs/en/docs/tutorial/extra-models.md`. PR [#12638](https://github.com/fastapi/fastapi/pull/12638) by [@vishnuvskvkl](https://github.com/vishnuvskvkl). +* 📝 Update includes for `docs/en/docs/tutorial/cors.md`. PR [#12637](https://github.com/fastapi/fastapi/pull/12637) by [@vishnuvskvkl](https://github.com/vishnuvskvkl). +* 📝 Update includes for `docs/en/docs/tutorial/dependencies/sub-dependencies.md`. PR [#12810](https://github.com/fastapi/fastapi/pull/12810) by [@handabaldeep](https://github.com/handabaldeep). +* 📝 Update includes in `docs/en/docs/tutorial/body-nested-models.md`. PR [#12812](https://github.com/fastapi/fastapi/pull/12812) by [@zhaohan-dong](https://github.com/zhaohan-dong). +* 📝 Update includes in `docs/en/docs/tutorial/path-operation-configuration.md`. PR [#12809](https://github.com/fastapi/fastapi/pull/12809) by [@AlexWendland](https://github.com/AlexWendland). +* 📝 Update includes in `docs/en/docs/tutorial/request-files.md`. PR [#12818](https://github.com/fastapi/fastapi/pull/12818) by [@zhaohan-dong](https://github.com/zhaohan-dong). +* 📝 Update includes for `docs/en/docs/tutorial/query-param-models.md`. PR [#12817](https://github.com/fastapi/fastapi/pull/12817) by [@handabaldeep](https://github.com/handabaldeep). +* 📝 Update includes in `docs/en/docs/tutorial/path-params.md`. PR [#12811](https://github.com/fastapi/fastapi/pull/12811) by [@AlexWendland](https://github.com/AlexWendland). +* 📝 Update includes in `docs/en/docs/tutorial/response-model.md`. PR [#12621](https://github.com/fastapi/fastapi/pull/12621) by [@kantandane](https://github.com/kantandane). +* 📝 Update includes in `docs/en/docs/advanced/websockets.md`. PR [#12606](https://github.com/fastapi/fastapi/pull/12606) by [@vishnuvskvkl](https://github.com/vishnuvskvkl). +* 📝 Updates include for `docs/en/docs/tutorial/cookie-params.md`. PR [#12808](https://github.com/fastapi/fastapi/pull/12808) by [@handabaldeep](https://github.com/handabaldeep). +* 📝 Update includes in `docs/en/docs/tutorial/middleware.md`. PR [#12807](https://github.com/fastapi/fastapi/pull/12807) by [@AlexWendland](https://github.com/AlexWendland). +* 📝 Update includes in `docs/en/docs/advanced/sub-applications.md`. PR [#12806](https://github.com/fastapi/fastapi/pull/12806) by [@zhaohan-dong](https://github.com/zhaohan-dong). +* 📝 Update includes in `docs/en/docs/advanced/response-headers.md`. PR [#12805](https://github.com/fastapi/fastapi/pull/12805) by [@zhaohan-dong](https://github.com/zhaohan-dong). +* 📝 Update includes in `docs/fr/docs/tutorial/first-steps.md`. PR [#12594](https://github.com/fastapi/fastapi/pull/12594) by [@kantandane](https://github.com/kantandane). +* 📝 Update includes in `docs/en/docs/advanced/response-cookies.md`. PR [#12804](https://github.com/fastapi/fastapi/pull/12804) by [@zhaohan-dong](https://github.com/zhaohan-dong). +* 📝 Update includes in `docs/en/docs/advanced/path-operation-advanced-configuration.md`. PR [#12802](https://github.com/fastapi/fastapi/pull/12802) by [@zhaohan-dong](https://github.com/zhaohan-dong). +* 📝 Update includes for `docs/en/docs/advanced/response-directly.md`. PR [#12803](https://github.com/fastapi/fastapi/pull/12803) by [@handabaldeep](https://github.com/handabaldeep). +* 📝 Update includes in `docs/zh/docs/tutorial/background-tasks.md`. PR [#12798](https://github.com/fastapi/fastapi/pull/12798) by [@zhaohan-dong](https://github.com/zhaohan-dong). +* 📝 Update includes for `docs/de/docs/tutorial/body-multiple-params.md`. PR [#12699](https://github.com/fastapi/fastapi/pull/12699) by [@alissadb](https://github.com/alissadb). +* 📝 Update includes in `docs/em/docs/tutorial/body-updates.md`. PR [#12799](https://github.com/fastapi/fastapi/pull/12799) by [@AlexWendland](https://github.com/AlexWendland). +* 📝 Update includes `docs/en/docs/advanced/response-change-status-code.md`. PR [#12801](https://github.com/fastapi/fastapi/pull/12801) by [@handabaldeep](https://github.com/handabaldeep). +* 📝 Update includes `docs/en/docs/advanced/openapi-callbacks.md`. PR [#12800](https://github.com/fastapi/fastapi/pull/12800) by [@handabaldeep](https://github.com/handabaldeep). +* 📝 Update includes in `docs/fr/docs/tutorial/body-multiple-params.md`. PR [#12598](https://github.com/fastapi/fastapi/pull/12598) by [@kantandane](https://github.com/kantandane). +* 📝 Update includes in `docs/en/docs/tutorial/body-multiple-params.md`. PR [#12593](https://github.com/fastapi/fastapi/pull/12593) by [@Tashanam-Shahbaz](https://github.com/Tashanam-Shahbaz). +* 📝 Update includes in `docs/pt/docs/tutorial/background-tasks.md`. PR [#12736](https://github.com/fastapi/fastapi/pull/12736) by [@bhunao](https://github.com/bhunao). +* 📝 Update includes for `docs/en/docs/advanced/custom-response.md`. PR [#12797](https://github.com/fastapi/fastapi/pull/12797) by [@handabaldeep](https://github.com/handabaldeep). +* 📝 Update includes for `docs/pt/docs/python-types.md`. PR [#12671](https://github.com/fastapi/fastapi/pull/12671) by [@ceb10n](https://github.com/ceb10n). +* 📝 Update includes for `docs/de/docs/python-types.md`. PR [#12660](https://github.com/fastapi/fastapi/pull/12660) by [@alissadb](https://github.com/alissadb). +* 📝 Update includes for `docs/de/docs/advanced/dataclasses.md`. PR [#12658](https://github.com/fastapi/fastapi/pull/12658) by [@alissadb](https://github.com/alissadb). +* 📝 Update includes in `docs/fr/docs/tutorial/path-params.md`. PR [#12592](https://github.com/fastapi/fastapi/pull/12592) by [@kantandane](https://github.com/kantandane). +* 📝 Update includes for `docs/de/docs/how-to/configure-swagger-ui.md`. PR [#12690](https://github.com/fastapi/fastapi/pull/12690) by [@alissadb](https://github.com/alissadb). +* 📝 Update includes in `docs/en/docs/advanced/security/oauth2-scopes.md`. PR [#12572](https://github.com/fastapi/fastapi/pull/12572) by [@krishnamadhavan](https://github.com/krishnamadhavan). +* 📝 Update includes for `docs/en/docs/how-to/conditional-openapi.md`. PR [#12624](https://github.com/fastapi/fastapi/pull/12624) by [@rabinlamadong](https://github.com/rabinlamadong). +* 📝 Update includes in `docs/en/docs/tutorial/dependencies/index.md`. PR [#12615](https://github.com/fastapi/fastapi/pull/12615) by [@bharara](https://github.com/bharara). +* 📝 Update includes in `docs/en/docs/tutorial/response-status-code.md`. PR [#12620](https://github.com/fastapi/fastapi/pull/12620) by [@kantandane](https://github.com/kantandane). +* 📝 Update includes in `docs/en/docs/how-to/custom-docs-ui-assets.md`. PR [#12623](https://github.com/fastapi/fastapi/pull/12623) by [@rabinlamadong](https://github.com/rabinlamadong). +* 📝 Update includes in `docs/en/docs/advanced/openapi-webhooks.md`. PR [#12605](https://github.com/fastapi/fastapi/pull/12605) by [@salmantec](https://github.com/salmantec). +* 📝 Update includes in `docs/en/docs/advanced/events.md`. PR [#12604](https://github.com/fastapi/fastapi/pull/12604) by [@salmantec](https://github.com/salmantec). +* 📝 Update includes in `docs/en/docs/advanced/dataclasses.md`. PR [#12603](https://github.com/fastapi/fastapi/pull/12603) by [@salmantec](https://github.com/salmantec). +* 📝 Update includes in `docs/es/docs/tutorial/cookie-params.md`. PR [#12602](https://github.com/fastapi/fastapi/pull/12602) by [@antonyare93](https://github.com/antonyare93). +* 📝 Update includes in `docs/fr/docs/tutorial/path-params-numeric-validations.md`. PR [#12601](https://github.com/fastapi/fastapi/pull/12601) by [@kantandane](https://github.com/kantandane). +* 📝 Update includes in `docs/fr/docs/tutorial/background-tasks.md`. PR [#12600](https://github.com/fastapi/fastapi/pull/12600) by [@kantandane](https://github.com/kantandane). +* 📝 Update includes in `docs/en/docs/tutorial/encoder.md`. PR [#12597](https://github.com/fastapi/fastapi/pull/12597) by [@tonyjly](https://github.com/tonyjly). +* 📝 Update includes in `docs/en/docs/how-to/custom-docs-ui-assets.md`. PR [#12557](https://github.com/fastapi/fastapi/pull/12557) by [@philipokiokio](https://github.com/philipokiokio). +* 🎨 Adjust spacing. PR [#12635](https://github.com/fastapi/fastapi/pull/12635) by [@alejsdev](https://github.com/alejsdev). +* 📝 Update includes in `docs/en/docs/how-to/custom-request-and-route.md`. PR [#12560](https://github.com/fastapi/fastapi/pull/12560) by [@philipokiokio](https://github.com/philipokiokio). + +### Translations + +* 🌐 Add Korean translation for `docs/ko/docs/advanced/testing-websockets.md`. PR [#12739](https://github.com/fastapi/fastapi/pull/12739) by [@Limsunoh](https://github.com/Limsunoh). +* 🌐 Add Traditional Chinese translation for `docs/zh-hant/docs/environment-variables.md`. PR [#12785](https://github.com/fastapi/fastapi/pull/12785) by [@Vincy1230](https://github.com/Vincy1230). +* 🌐 Add Chinese translation for `docs/zh/docs/environment-variables.md`. PR [#12784](https://github.com/fastapi/fastapi/pull/12784) by [@Vincy1230](https://github.com/Vincy1230). +* 🌐 Add Korean translation for `ko/docs/advanced/response-headers.md`. PR [#12740](https://github.com/fastapi/fastapi/pull/12740) by [@kwang1215](https://github.com/kwang1215). +* 🌐 Add Chinese translation for `docs/zh/docs/virtual-environments.md`. PR [#12790](https://github.com/fastapi/fastapi/pull/12790) by [@Vincy1230](https://github.com/Vincy1230). +* 🌐 Add Korean translation for `/docs/ko/docs/environment-variables.md`. PR [#12526](https://github.com/fastapi/fastapi/pull/12526) by [@Tolerblanc](https://github.com/Tolerblanc). +* 🌐 Add Korean translation for `docs/ko/docs/history-design-future.md`. PR [#12646](https://github.com/fastapi/fastapi/pull/12646) by [@saeye](https://github.com/saeye). +* 🌐 Add Korean translation for `docs/ko/docs/advanced/advanced-dependencies.md`. PR [#12675](https://github.com/fastapi/fastapi/pull/12675) by [@kim-sangah](https://github.com/kim-sangah). +* 🌐 Add Korean translation for `docs/ko/docs/how-to/conditional-openapi.md`. PR [#12731](https://github.com/fastapi/fastapi/pull/12731) by [@sptcnl](https://github.com/sptcnl). +* 🌐 Add Korean translation for `docs/ko/docs/advanced/using_request_directly.md`. PR [#12738](https://github.com/fastapi/fastapi/pull/12738) by [@kwang1215](https://github.com/kwang1215). +* 🌐 Add Korean translation for `docs/ko/docs/advanced/testing-events.md`. PR [#12741](https://github.com/fastapi/fastapi/pull/12741) by [@9zimin9](https://github.com/9zimin9). +* 🌐 Add Korean translation for `docs/ko/docs/security/index.md`. PR [#12743](https://github.com/fastapi/fastapi/pull/12743) by [@kim-sangah](https://github.com/kim-sangah). +* 🌐 Add Portuguese translation for `docs/pt/docs/advanced/path-operation-advanced-configuration.md`. PR [#12762](https://github.com/fastapi/fastapi/pull/12762) by [@Joao-Pedro-P-Holanda](https://github.com/Joao-Pedro-P-Holanda). +* 🌐 Add Korean translation for `docs/ko/docs/advanced/wsgi.md`. PR [#12659](https://github.com/fastapi/fastapi/pull/12659) by [@Limsunoh](https://github.com/Limsunoh). +* 🌐 Add Portuguese translation for `docs/pt/docs/advanced/websockets.md`. PR [#12703](https://github.com/fastapi/fastapi/pull/12703) by [@devfernandoa](https://github.com/devfernandoa). +* 🌐 Add Portuguese translation for `docs/pt/docs/tutorial/security/simple-oauth2.md`. PR [#12520](https://github.com/fastapi/fastapi/pull/12520) by [@LidiaDomingos](https://github.com/LidiaDomingos). +* 🌐 Add Korean translation for `docs/ko/docs/advanced/response-directly.md`. PR [#12674](https://github.com/fastapi/fastapi/pull/12674) by [@9zimin9](https://github.com/9zimin9). +* 🌐 Add Portuguese translation for `docs/pt/docs/advanced/middleware.md`. PR [#12704](https://github.com/fastapi/fastapi/pull/12704) by [@devluisrodrigues](https://github.com/devluisrodrigues). +* 🌐 Add Portuguese translation for `docs/pt/docs/advanced/openapi-callbacks.md`. PR [#12705](https://github.com/fastapi/fastapi/pull/12705) by [@devfernandoa](https://github.com/devfernandoa). +* 🌐 Add Portuguese translation for `docs/pt/docs/tutorial/request-files.md`. PR [#12706](https://github.com/fastapi/fastapi/pull/12706) by [@devluisrodrigues](https://github.com/devluisrodrigues). +* 🌐 Add Portuguese Translation for `docs/pt/docs/advanced/custom-response.md`. PR [#12631](https://github.com/fastapi/fastapi/pull/12631) by [@Joao-Pedro-P-Holanda](https://github.com/Joao-Pedro-P-Holanda). +* 🌐 Add Portuguese translation for `docs/pt/docs/tutorial/metadata.md`. PR [#12538](https://github.com/fastapi/fastapi/pull/12538) by [@LinkolnR](https://github.com/LinkolnR). +* 🌐 Add Korean translation for `docs/ko/docs/tutorial/metadata.md`. PR [#12541](https://github.com/fastapi/fastapi/pull/12541) by [@kwang1215](https://github.com/kwang1215). +* 🌐 Add Korean Translation for `docs/ko/docs/advanced/response-cookies.md`. PR [#12546](https://github.com/fastapi/fastapi/pull/12546) by [@kim-sangah](https://github.com/kim-sangah). +* 🌐 Add Korean translation for `docs/ko/docs/fastapi-cli.md`. PR [#12515](https://github.com/fastapi/fastapi/pull/12515) by [@dhdld](https://github.com/dhdld). +* 🌐 Add Korean Translation for `docs/ko/docs/advanced/response-change-status-code.md`. PR [#12547](https://github.com/fastapi/fastapi/pull/12547) by [@9zimin9](https://github.com/9zimin9). + +### Internal + +* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#12907](https://github.com/fastapi/fastapi/pull/12907) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). +* 🔨 Update docs preview script to show previous version and English version. PR [#12856](https://github.com/fastapi/fastapi/pull/12856) by [@tiangolo](https://github.com/tiangolo). +* ⬆ Bump tiangolo/latest-changes from 0.3.1 to 0.3.2. PR [#12794](https://github.com/fastapi/fastapi/pull/12794) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump pypa/gh-action-pypi-publish from 1.12.0 to 1.12.2. PR [#12788](https://github.com/fastapi/fastapi/pull/12788) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump pypa/gh-action-pypi-publish from 1.11.0 to 1.12.0. PR [#12781](https://github.com/fastapi/fastapi/pull/12781) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump cloudflare/wrangler-action from 3.11 to 3.12. PR [#12777](https://github.com/fastapi/fastapi/pull/12777) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#12766](https://github.com/fastapi/fastapi/pull/12766) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). +* ⬆ Bump pypa/gh-action-pypi-publish from 1.10.3 to 1.11.0. PR [#12721](https://github.com/fastapi/fastapi/pull/12721) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Update pre-commit requirement from <4.0.0,>=2.17.0 to >=2.17.0,<5.0.0. PR [#12749](https://github.com/fastapi/fastapi/pull/12749) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump typer from 0.12.3 to 0.12.5. PR [#12748](https://github.com/fastapi/fastapi/pull/12748) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Update flask requirement from <3.0.0,>=1.1.2 to >=1.1.2,<4.0.0. PR [#12747](https://github.com/fastapi/fastapi/pull/12747) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump pillow from 10.4.0 to 11.0.0. PR [#12746](https://github.com/fastapi/fastapi/pull/12746) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Update pytest requirement from <8.0.0,>=7.1.3 to >=7.1.3,<9.0.0. PR [#12745](https://github.com/fastapi/fastapi/pull/12745) by [@dependabot[bot]](https://github.com/apps/dependabot). +* 🔧 Update sponsors: add Render. PR [#12733](https://github.com/fastapi/fastapi/pull/12733) by [@tiangolo](https://github.com/tiangolo). +* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#12707](https://github.com/fastapi/fastapi/pull/12707) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). + +## 0.115.4 (2024-10-27) + +### Refactors + +* ♻️ Update logic to import and check `python-multipart` for compatibility with newer version. PR [#12627](https://github.com/fastapi/fastapi/pull/12627) by [@tiangolo](https://github.com/tiangolo). + +### Docs + +* 📝 Update includes in `docs/fr/docs/tutorial/body.md`. PR [#12596](https://github.com/fastapi/fastapi/pull/12596) by [@kantandane](https://github.com/kantandane). +* 📝 Update includes in `docs/fr/docs/tutorial/debugging.md`. PR [#12595](https://github.com/fastapi/fastapi/pull/12595) by [@kantandane](https://github.com/kantandane). +* 📝 Update includes in `docs/fr/docs/tutorial/query-params-str-validations.md`. PR [#12591](https://github.com/fastapi/fastapi/pull/12591) by [@kantandane](https://github.com/kantandane). +* 📝 Update includes in `docs/fr/docs/tutorial/query-params.md`. PR [#12589](https://github.com/fastapi/fastapi/pull/12589) by [@kantandane](https://github.com/kantandane). +* 📝 Update includes in `docs/en/tutorial/body-fields.md`. PR [#12588](https://github.com/fastapi/fastapi/pull/12588) by [@lucaromagnoli](https://github.com/lucaromagnoli). +* 📝 Update includes in `docs/de/docs/tutorial/response-status-code.md`. PR [#12585](https://github.com/fastapi/fastapi/pull/12585) by [@abejaranoh](https://github.com/abejaranoh). +* 📝 Update includes in `docs/en/docs/tutorial/body.md`. PR [#12586](https://github.com/fastapi/fastapi/pull/12586) by [@lucaromagnoli](https://github.com/lucaromagnoli). +* 📝 Update includes in `docs/en/docs/advanced/behind-a-proxy.md`. PR [#12583](https://github.com/fastapi/fastapi/pull/12583) by [@imjuanleonard](https://github.com/imjuanleonard). +* 📝 Update includes syntax for `docs/pl/docs/tutorial/first-steps.md`. PR [#12584](https://github.com/fastapi/fastapi/pull/12584) by [@sebkozlo](https://github.com/sebkozlo). +* 📝 Update includes in `docs/en/docs/advanced/middleware.md`. PR [#12582](https://github.com/fastapi/fastapi/pull/12582) by [@montanarograziano](https://github.com/montanarograziano). +* 📝 Update includes in `docs/en/docs/advanced/additional-status-codes.md`. PR [#12577](https://github.com/fastapi/fastapi/pull/12577) by [@krishnamadhavan](https://github.com/krishnamadhavan). +* 📝 Update includes in `docs/en/docs/advanced/advanced-dependencies.md`. PR [#12578](https://github.com/fastapi/fastapi/pull/12578) by [@krishnamadhavan](https://github.com/krishnamadhavan). +* 📝 Update includes in `docs/en/docs/advanced/additional-responses.md`. PR [#12576](https://github.com/fastapi/fastapi/pull/12576) by [@krishnamadhavan](https://github.com/krishnamadhavan). +* 📝 Update includes in `docs/en/docs/tutorial/static-files.md`. PR [#12575](https://github.com/fastapi/fastapi/pull/12575) by [@lucaromagnoli](https://github.com/lucaromagnoli). +* 📝 Update includes in `docs/en/docs/advanced/async-tests.md`. PR [#12568](https://github.com/fastapi/fastapi/pull/12568) by [@krishnamadhavan](https://github.com/krishnamadhavan). +* 📝 Update includes in `docs/pt/docs/advanced/behind-a-proxy.md`. PR [#12563](https://github.com/fastapi/fastapi/pull/12563) by [@asmioglou](https://github.com/asmioglou). +* 📝 Update includes in `docs/de/docs/advanced/security/http-basic-auth.md`. PR [#12561](https://github.com/fastapi/fastapi/pull/12561) by [@Nimitha-jagadeesha](https://github.com/Nimitha-jagadeesha). +* 📝 Update includes in `docs/en/docs/tutorial/background-tasks.md`. PR [#12559](https://github.com/fastapi/fastapi/pull/12559) by [@FarhanAliRaza](https://github.com/FarhanAliRaza). +* 📝 Update includes in `docs/fr/docs/python-types.md`. PR [#12558](https://github.com/fastapi/fastapi/pull/12558) by [@Ismailtlem](https://github.com/Ismailtlem). +* 📝 Update includes in `docs/en/docs/how-to/graphql.md`. PR [#12564](https://github.com/fastapi/fastapi/pull/12564) by [@philipokiokio](https://github.com/philipokiokio). +* 📝 Update includes in `docs/en/docs/how-to/extending-openapi.md`. PR [#12562](https://github.com/fastapi/fastapi/pull/12562) by [@philipokiokio](https://github.com/philipokiokio). +* 📝 Update includes for `docs/en/docs/how-to/configure-swagger-ui.md`. PR [#12556](https://github.com/fastapi/fastapi/pull/12556) by [@tiangolo](https://github.com/tiangolo). +* 📝 Update includes for `docs/en/docs/how-to/separate-openapi-schemas.md`. PR [#12555](https://github.com/fastapi/fastapi/pull/12555) by [@tiangolo](https://github.com/tiangolo). +* 📝 Update includes for `docs/en/docs/advanced/security/http-basic-auth.md`. PR [#12553](https://github.com/fastapi/fastapi/pull/12553) by [@tiangolo](https://github.com/tiangolo). +* 📝 Update includes in `docs/en/docs/tutorial/first-steps.md`. PR [#12552](https://github.com/fastapi/fastapi/pull/12552) by [@tiangolo](https://github.com/tiangolo). +* 📝 Update includes in `docs/en/docs/python-types.md`. PR [#12551](https://github.com/fastapi/fastapi/pull/12551) by [@tiangolo](https://github.com/tiangolo). +* 📝 Fix link in OAuth2 docs. PR [#12550](https://github.com/fastapi/fastapi/pull/12550) by [@tiangolo](https://github.com/tiangolo). +* 📝 Add External Link: FastAPI do Zero. PR [#12533](https://github.com/fastapi/fastapi/pull/12533) by [@rennerocha](https://github.com/rennerocha). +* 📝 Fix minor typos. PR [#12516](https://github.com/fastapi/fastapi/pull/12516) by [@kkirsche](https://github.com/kkirsche). +* 🌐 Fix rendering issue in translations. PR [#12509](https://github.com/fastapi/fastapi/pull/12509) by [@alejsdev](https://github.com/alejsdev). + +### Translations + +* 📝 Update includes in `docs/de/docs/advanced/async-tests.md`. PR [#12567](https://github.com/fastapi/fastapi/pull/12567) by [@imjuanleonard](https://github.com/imjuanleonard). +* 🌐 Add Portuguese translation for `docs/pt/docs/tutorial/sql-databases.md`. PR [#12530](https://github.com/fastapi/fastapi/pull/12530) by [@ilacftemp](https://github.com/ilacftemp). +* 🌐 Add Korean translation for `docs/ko/docs/benchmarks.md`. PR [#12540](https://github.com/fastapi/fastapi/pull/12540) by [@Limsunoh](https://github.com/Limsunoh). +* 🌐 Add Portuguese translation for `docs/pt/docs/how-to/separate-openapi-schemas.md`. PR [#12518](https://github.com/fastapi/fastapi/pull/12518) by [@ilacftemp](https://github.com/ilacftemp). +* 🌐 Update Traditional Chinese translation for `docs/zh-hant/docs/deployment/index.md`. PR [#12521](https://github.com/fastapi/fastapi/pull/12521) by [@codingjenny](https://github.com/codingjenny). +* 🌐 Update Traditional Chinese translation for `docs/zh-hant/docs/deployment/cloud.md`. PR [#12522](https://github.com/fastapi/fastapi/pull/12522) by [@codingjenny](https://github.com/codingjenny). +* 🌐 Update Traditional Chinese translation for `docs/zh-hant/docs/how-to/index.md`. PR [#12523](https://github.com/fastapi/fastapi/pull/12523) by [@codingjenny](https://github.com/codingjenny). +* 🌐 Update Traditional Chinese translation for `docs/zh-hant/docs/tutorial/index.md`. PR [#12524](https://github.com/fastapi/fastapi/pull/12524) by [@codingjenny](https://github.com/codingjenny). +* 🌐 Add Traditional Chinese translation for `docs/zh-hant/docs/how-to/index.md`. PR [#12468](https://github.com/fastapi/fastapi/pull/12468) by [@codingjenny](https://github.com/codingjenny). +* 🌐 Add Traditional Chinese translation for `docs/zh-hant/docs/tutorial/index.md`. PR [#12466](https://github.com/fastapi/fastapi/pull/12466) by [@codingjenny](https://github.com/codingjenny). +* 🌐 Add Portuguese translation for `docs/pt/docs/tutorial/header-param-models.md`. PR [#12437](https://github.com/fastapi/fastapi/pull/12437) by [@Joao-Pedro-P-Holanda](https://github.com/Joao-Pedro-P-Holanda). +* 🌐 Add Portuguese translation for `docs/pt/docs/how-to/extending-openapi.md`. PR [#12470](https://github.com/fastapi/fastapi/pull/12470) by [@ilacftemp](https://github.com/ilacftemp). +* 🌐 Add Portuguese translation for `docs/pt/docs/advanced/dataclasses.md`. PR [#12475](https://github.com/fastapi/fastapi/pull/12475) by [@leoscarlato](https://github.com/leoscarlato). +* 🌐 Add Portuguese translation for `docs/pt/docs/how-to/custom-request-and-route.md`. PR [#12483](https://github.com/fastapi/fastapi/pull/12483) by [@devfernandoa](https://github.com/devfernandoa). + +### Internal + +* ⬆ Bump cloudflare/wrangler-action from 3.9 to 3.11. PR [#12544](https://github.com/fastapi/fastapi/pull/12544) by [@dependabot[bot]](https://github.com/apps/dependabot). +* 👷 Update GitHub Action to deploy docs previews to handle missing deploy comments. PR [#12527](https://github.com/fastapi/fastapi/pull/12527) by [@tiangolo](https://github.com/tiangolo). +* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#12505](https://github.com/fastapi/fastapi/pull/12505) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). + +## 0.115.3 (2024-10-22) + +### Upgrades + +* ⬆️ Upgrade Starlette to `>=0.40.0,<0.42.0`. PR [#12469](https://github.com/fastapi/fastapi/pull/12469) by [@defnull](https://github.com/defnull). + +### Docs + +* 📝 Fix broken link in docs. PR [#12495](https://github.com/fastapi/fastapi/pull/12495) by [@eltonjncorreia](https://github.com/eltonjncorreia). + +### Translations + +* 🌐 Add Traditional Chinese translation for `docs/zh-hant/docs/fastapi-cli.md`. PR [#12444](https://github.com/fastapi/fastapi/pull/12444) by [@codingjenny](https://github.com/codingjenny). +* 🌐 Add Traditional Chinese translation for `docs/zh-hant/docs/deployment/index.md`. PR [#12439](https://github.com/fastapi/fastapi/pull/12439) by [@codingjenny](https://github.com/codingjenny). +* 🌐 Add Portuguese translation for `docs/pt/docs/how-to/testing-database.md`. PR [#12472](https://github.com/fastapi/fastapi/pull/12472) by [@GuilhermeRameh](https://github.com/GuilhermeRameh). +* 🌐 Add Portuguese translation for `docs/pt/docs/how-to/custom-docs-ui-assets.md`. PR [#12473](https://github.com/fastapi/fastapi/pull/12473) by [@devluisrodrigues](https://github.com/devluisrodrigues). +* 🌐 Add Portuguese translation for `docs/pt/docs/advanced/response-headers.md`. PR [#12458](https://github.com/fastapi/fastapi/pull/12458) by [@leonardopaloschi](https://github.com/leonardopaloschi). +* 🌐 Add Traditional Chinese translation for `docs/zh-hant/docs/deployment/cloud.md`. PR [#12440](https://github.com/fastapi/fastapi/pull/12440) by [@codingjenny](https://github.com/codingjenny). +* 🌐 Update Portuguese translation for `docs/pt/docs/python-types.md`. PR [#12428](https://github.com/fastapi/fastapi/pull/12428) by [@ceb10n](https://github.com/ceb10n). +* 🌐 Add Russian translation for `docs/ru/docs/environment-variables.md`. PR [#12436](https://github.com/fastapi/fastapi/pull/12436) by [@wisderfin](https://github.com/wisderfin). +* 🌐 Add Traditional Chinese translation for `docs/zh-hant/docs/resources/index.md`. PR [#12443](https://github.com/fastapi/fastapi/pull/12443) by [@codingjenny](https://github.com/codingjenny). +* 🌐 Add Traditional Chinese translation for `docs/zh-hant/docs/about/index.md`. PR [#12438](https://github.com/fastapi/fastapi/pull/12438) by [@codingjenny](https://github.com/codingjenny). +* 🌐 Add Portuguese translation for `docs/pt/docs/tutorial/query-param-models.md`. PR [#12414](https://github.com/fastapi/fastapi/pull/12414) by [@ceb10n](https://github.com/ceb10n). +* 🌐 Remove Portuguese translation for `docs/pt/docs/deployment.md`. PR [#12427](https://github.com/fastapi/fastapi/pull/12427) by [@ceb10n](https://github.com/ceb10n). +* 🌐 Add Portuguese translation for `docs/pt/docs/tutorial/body-updates.md`. PR [#12381](https://github.com/fastapi/fastapi/pull/12381) by [@andersonrocha0](https://github.com/andersonrocha0). +* 🌐 Add Portuguese translation for `docs/pt/docs/advanced/response-cookies.md`. PR [#12417](https://github.com/fastapi/fastapi/pull/12417) by [@Paulofalcao2002](https://github.com/Paulofalcao2002). + +### Internal + +* 👷 Update issue manager workflow . PR [#12457](https://github.com/fastapi/fastapi/pull/12457) by [@alejsdev](https://github.com/alejsdev). +* 🔧 Update team, include YuriiMotov 🚀. PR [#12453](https://github.com/fastapi/fastapi/pull/12453) by [@tiangolo](https://github.com/tiangolo). +* 👷 Refactor label-approved, make it an internal script instead of an external GitHub Action. PR [#12280](https://github.com/fastapi/fastapi/pull/12280) by [@tiangolo](https://github.com/tiangolo). +* 👷 Fix smokeshow, checkout files on CI. PR [#12434](https://github.com/fastapi/fastapi/pull/12434) by [@tiangolo](https://github.com/tiangolo). +* 👷 Use uv in CI. PR [#12281](https://github.com/fastapi/fastapi/pull/12281) by [@tiangolo](https://github.com/tiangolo). +* ⬆ Update httpx requirement from <0.25.0,>=0.23.0 to >=0.23.0,<0.28.0. PR [#11509](https://github.com/fastapi/fastapi/pull/11509) by [@dependabot[bot]](https://github.com/apps/dependabot). + +## 0.115.2 (2024-10-12) + +### Upgrades + +* ⬆️ Upgrade Starlette to `>=0.37.2,<0.41.0`. PR [#12431](https://github.com/fastapi/fastapi/pull/12431) by [@tiangolo](https://github.com/tiangolo). + +## 0.115.1 (2024-10-12) + +### Fixes + +* 🐛 Fix openapi generation with responses kwarg. PR [#10895](https://github.com/fastapi/fastapi/pull/10895) by [@flxdot](https://github.com/flxdot). +* 🐛 Remove `Required` shadowing from fastapi using Pydantic v2. PR [#12197](https://github.com/fastapi/fastapi/pull/12197) by [@pachewise](https://github.com/pachewise). + +### Refactors + +* ♻️ Update type annotations for improved `python-multipart`. PR [#12407](https://github.com/fastapi/fastapi/pull/12407) by [@tiangolo](https://github.com/tiangolo). + +### Docs + +* ✨ Add new tutorial for SQL databases with SQLModel. PR [#12285](https://github.com/fastapi/fastapi/pull/12285) by [@tiangolo](https://github.com/tiangolo). +* 📝 Add External Link: How to profile a FastAPI asynchronous request. PR [#12389](https://github.com/fastapi/fastapi/pull/12389) by [@brouberol](https://github.com/brouberol). +* 🔧 Remove `base_path` for `mdx_include` Markdown extension in MkDocs. PR [#12391](https://github.com/fastapi/fastapi/pull/12391) by [@tiangolo](https://github.com/tiangolo). +* 📝 Update link to Swagger UI configuration docs. PR [#12264](https://github.com/fastapi/fastapi/pull/12264) by [@makisukurisu](https://github.com/makisukurisu). +* 📝 Adding links for Playwright and Vite in `docs/project-generation.md`. PR [#12274](https://github.com/fastapi/fastapi/pull/12274) by [@kayqueGovetri](https://github.com/kayqueGovetri). +* 📝 Fix small typos in the documentation. PR [#12213](https://github.com/fastapi/fastapi/pull/12213) by [@svlandeg](https://github.com/svlandeg). + +### Translations + +* 🌐 Add Portuguese translation for `docs/pt/docs/tutorial/cookie-param-models.md`. PR [#12298](https://github.com/fastapi/fastapi/pull/12298) by [@ceb10n](https://github.com/ceb10n). +* 🌐 Add Portuguese translation for `docs/pt/docs/how-to/graphql.md`. PR [#12215](https://github.com/fastapi/fastapi/pull/12215) by [@AnandaCampelo](https://github.com/AnandaCampelo). +* 🌐 Add Portuguese translation for `docs/pt/docs/advanced/security/oauth2-scopes.md`. PR [#12263](https://github.com/fastapi/fastapi/pull/12263) by [@ceb10n](https://github.com/ceb10n). +* 🌐 Add Portuguese translation for `docs/pt/docs/deployment/concepts.md`. PR [#12219](https://github.com/fastapi/fastapi/pull/12219) by [@marcelomarkus](https://github.com/marcelomarkus). +* 🌐 Add Portuguese translation for `docs/pt/docs/how-to/conditional-openapi.md`. PR [#12221](https://github.com/fastapi/fastapi/pull/12221) by [@marcelomarkus](https://github.com/marcelomarkus). +* 🌐 Add Portuguese translation for `docs/pt/docs/advanced/response-directly.md`. PR [#12266](https://github.com/fastapi/fastapi/pull/12266) by [@Joao-Pedro-P-Holanda](https://github.com/Joao-Pedro-P-Holanda). +* 🌐 Update Portuguese translation for `docs/pt/docs/tutorial/cookie-params.md`. PR [#12297](https://github.com/fastapi/fastapi/pull/12297) by [@ceb10n](https://github.com/ceb10n). +* 🌐 Fix Korean translation for `docs/ko/docs/tutorial/index.md`. PR [#12278](https://github.com/fastapi/fastapi/pull/12278) by [@kkotipy](https://github.com/kkotipy). +* 🌐 Update Portuguese translation for `docs/pt/docs/advanced/security/http-basic-auth.md`. PR [#12275](https://github.com/fastapi/fastapi/pull/12275) by [@andersonrocha0](https://github.com/andersonrocha0). +* 🌐 Add Portuguese translation for `docs/pt/docs/deployment/cloud.md`. PR [#12217](https://github.com/fastapi/fastapi/pull/12217) by [@marcelomarkus](https://github.com/marcelomarkus). +* ✏️ Fix typo in `docs/es/docs/python-types.md`. PR [#12235](https://github.com/fastapi/fastapi/pull/12235) by [@JavierSanchezCastro](https://github.com/JavierSanchezCastro). +* 🌐 Add Dutch translation for `docs/nl/docs/environment-variables.md`. PR [#12200](https://github.com/fastapi/fastapi/pull/12200) by [@maxscheijen](https://github.com/maxscheijen). +* 🌐 Add Portuguese translation for `docs/pt/docs/deployment/manually.md`. PR [#12210](https://github.com/fastapi/fastapi/pull/12210) by [@JoaoGustavoRogel](https://github.com/JoaoGustavoRogel). +* 🌐 Add Portuguese translation for `docs/pt/docs/deployment/server-workers.md`. PR [#12220](https://github.com/fastapi/fastapi/pull/12220) by [@marcelomarkus](https://github.com/marcelomarkus). +* 🌐 Add Portuguese translation for `docs/pt/docs/how-to/configure-swagger-ui.md`. PR [#12222](https://github.com/fastapi/fastapi/pull/12222) by [@marcelomarkus](https://github.com/marcelomarkus). + +### Internal + +* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#12396](https://github.com/fastapi/fastapi/pull/12396) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). +* 🔨 Add script to generate variants of files. PR [#12405](https://github.com/fastapi/fastapi/pull/12405) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Add speakeasy-api to `sponsors_badge.yml`. PR [#12404](https://github.com/fastapi/fastapi/pull/12404) by [@tiangolo](https://github.com/tiangolo). +* ➕ Add docs dependency: markdown-include-variants. PR [#12399](https://github.com/fastapi/fastapi/pull/12399) by [@tiangolo](https://github.com/tiangolo). +* 📝 Fix extra mdx-base-path paths. PR [#12397](https://github.com/fastapi/fastapi/pull/12397) by [@tiangolo](https://github.com/tiangolo). +* 👷 Tweak labeler to not override custom labels. PR [#12398](https://github.com/fastapi/fastapi/pull/12398) by [@tiangolo](https://github.com/tiangolo). +* 👷 Update workflow deploy-docs-notify URL. PR [#12392](https://github.com/fastapi/fastapi/pull/12392) by [@tiangolo](https://github.com/tiangolo). +* 👷 Update Cloudflare GitHub Action. PR [#12387](https://github.com/fastapi/fastapi/pull/12387) by [@tiangolo](https://github.com/tiangolo). +* ⬆ Bump pypa/gh-action-pypi-publish from 1.10.1 to 1.10.3. PR [#12386](https://github.com/fastapi/fastapi/pull/12386) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump mkdocstrings[python] from 0.25.1 to 0.26.1. PR [#12371](https://github.com/fastapi/fastapi/pull/12371) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump griffe-typingdoc from 0.2.6 to 0.2.7. PR [#12370](https://github.com/fastapi/fastapi/pull/12370) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#12331](https://github.com/fastapi/fastapi/pull/12331) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). +* 🔧 Update sponsors, remove Fine.dev. PR [#12271](https://github.com/fastapi/fastapi/pull/12271) by [@tiangolo](https://github.com/tiangolo). +* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#12253](https://github.com/fastapi/fastapi/pull/12253) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). +* ✏️ Fix docstring typos in http security. PR [#12223](https://github.com/fastapi/fastapi/pull/12223) by [@albertvillanova](https://github.com/albertvillanova). + +## 0.115.0 (2024-09-17) + +### Highlights + +Now you can declare `Query`, `Header`, and `Cookie` parameters with Pydantic models. 🎉 + +#### `Query` Parameter Models + +Use Pydantic models for `Query` parameters: + +```python +from typing import Annotated, Literal + +from fastapi import FastAPI, Query +from pydantic import BaseModel, Field + +app = FastAPI() + + +class FilterParams(BaseModel): + limit: int = Field(100, gt=0, le=100) + offset: int = Field(0, ge=0) + order_by: Literal["created_at", "updated_at"] = "created_at" + tags: list[str] = [] + + +@app.get("/items/") +async def read_items(filter_query: Annotated[FilterParams, Query()]): + return filter_query +``` + +Read the new docs: [Query Parameter Models](https://fastapi.tiangolo.com/tutorial/query-param-models/). + +#### `Header` Parameter Models + +Use Pydantic models for `Header` parameters: + +```python +from typing import Annotated + +from fastapi import FastAPI, Header +from pydantic import BaseModel + +app = FastAPI() + + +class CommonHeaders(BaseModel): + host: str + save_data: bool + if_modified_since: str | None = None + traceparent: str | None = None + x_tag: list[str] = [] + + +@app.get("/items/") +async def read_items(headers: Annotated[CommonHeaders, Header()]): + return headers +``` + +Read the new docs: [Header Parameter Models](https://fastapi.tiangolo.com/tutorial/header-param-models/). + +#### `Cookie` Parameter Models + +Use Pydantic models for `Cookie` parameters: + +```python +from typing import Annotated + +from fastapi import Cookie, FastAPI +from pydantic import BaseModel + +app = FastAPI() + + +class Cookies(BaseModel): + session_id: str + fatebook_tracker: str | None = None + googall_tracker: str | None = None + + +@app.get("/items/") +async def read_items(cookies: Annotated[Cookies, Cookie()]): + return cookies +``` + +Read the new docs: [Cookie Parameter Models](https://fastapi.tiangolo.com/tutorial/cookie-param-models/). + +#### Forbid Extra Query (Cookie, Header) Parameters + +Use Pydantic models to restrict extra values for `Query` parameters (also applies to `Header` and `Cookie` parameters). + +To achieve it, use Pydantic's `model_config = {"extra": "forbid"}`: + +```python +from typing import Annotated, Literal + +from fastapi import FastAPI, Query +from pydantic import BaseModel, Field + +app = FastAPI() + + +class FilterParams(BaseModel): + model_config = {"extra": "forbid"} + + limit: int = Field(100, gt=0, le=100) + offset: int = Field(0, ge=0) + order_by: Literal["created_at", "updated_at"] = "created_at" + tags: list[str] = [] + + +@app.get("/items/") +async def read_items(filter_query: Annotated[FilterParams, Query()]): + return filter_query +``` + +This applies to `Query`, `Header`, and `Cookie` parameters, read the new docs: + +* [Forbid Extra Query Parameters](https://fastapi.tiangolo.com/tutorial/query-param-models/#forbid-extra-query-parameters) +* [Forbid Extra Headers](https://fastapi.tiangolo.com/tutorial/header-param-models/#forbid-extra-headers) +* [Forbid Extra Cookies](https://fastapi.tiangolo.com/tutorial/cookie-param-models/#forbid-extra-cookies) + +### Features + +* ✨ Add support for Pydantic models for parameters using `Query`, `Cookie`, `Header`. PR [#12199](https://github.com/fastapi/fastapi/pull/12199) by [@tiangolo](https://github.com/tiangolo). + +### Translations + +* 🌐 Add Portuguese translation for `docs/pt/docs/advanced/security/http-basic-auth.md`. PR [#12195](https://github.com/fastapi/fastapi/pull/12195) by [@ceb10n](https://github.com/ceb10n). + +### Internal + +* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#12204](https://github.com/fastapi/fastapi/pull/12204) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). + +## 0.114.2 (2024-09-13) + +### Fixes + +* 🐛 Fix form field regression with `alias`. PR [#12194](https://github.com/fastapi/fastapi/pull/12194) by [@Wurstnase](https://github.com/Wurstnase). + +### Translations + +* 🌐 Add Portuguese translation for `docs/pt/docs/tutorial/request-form-models.md`. PR [#12175](https://github.com/fastapi/fastapi/pull/12175) by [@ceb10n](https://github.com/ceb10n). +* 🌐 Add Chinese translation for `docs/zh/docs/project-generation.md`. PR [#12170](https://github.com/fastapi/fastapi/pull/12170) by [@waketzheng](https://github.com/waketzheng). +* 🌐 Add Dutch translation for `docs/nl/docs/python-types.md`. PR [#12158](https://github.com/fastapi/fastapi/pull/12158) by [@maxscheijen](https://github.com/maxscheijen). + +### Internal + +* 💡 Add comments with instructions for Playwright screenshot scripts. PR [#12193](https://github.com/fastapi/fastapi/pull/12193) by [@tiangolo](https://github.com/tiangolo). +* ➕ Add inline-snapshot for tests. PR [#12189](https://github.com/fastapi/fastapi/pull/12189) by [@tiangolo](https://github.com/tiangolo). + +## 0.114.1 (2024-09-11) + +### Refactors + +* ⚡️ Improve performance in request body parsing with a cache for internal model fields. PR [#12184](https://github.com/fastapi/fastapi/pull/12184) by [@tiangolo](https://github.com/tiangolo). + +### Docs + +* 📝 Remove duplicate line in docs for `docs/en/docs/environment-variables.md`. PR [#12169](https://github.com/fastapi/fastapi/pull/12169) by [@prometek](https://github.com/prometek). + +### Translations + +* 🌐 Add Portuguese translation for `docs/pt/docs/virtual-environments.md`. PR [#12163](https://github.com/fastapi/fastapi/pull/12163) by [@marcelomarkus](https://github.com/marcelomarkus). +* 🌐 Add Portuguese translation for `docs/pt/docs/environment-variables.md`. PR [#12162](https://github.com/fastapi/fastapi/pull/12162) by [@marcelomarkus](https://github.com/marcelomarkus). +* 🌐 Add Portuguese translation for `docs/pt/docs/tutorial/testing.md`. PR [#12164](https://github.com/fastapi/fastapi/pull/12164) by [@marcelomarkus](https://github.com/marcelomarkus). +* 🌐 Add Portuguese translation for `docs/pt/docs/tutorial/debugging.md`. PR [#12165](https://github.com/fastapi/fastapi/pull/12165) by [@marcelomarkus](https://github.com/marcelomarkus). +* 🌐 Add Korean translation for `docs/ko/docs/project-generation.md`. PR [#12157](https://github.com/fastapi/fastapi/pull/12157) by [@BORA040126](https://github.com/BORA040126). + +### Internal + +* ⬆ Bump tiangolo/issue-manager from 0.5.0 to 0.5.1. PR [#12173](https://github.com/fastapi/fastapi/pull/12173) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#12176](https://github.com/fastapi/fastapi/pull/12176) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). +* 👷 Update `issue-manager.yml`. PR [#12159](https://github.com/fastapi/fastapi/pull/12159) by [@tiangolo](https://github.com/tiangolo). +* ✏️ Fix typo in `fastapi/params.py`. PR [#12143](https://github.com/fastapi/fastapi/pull/12143) by [@surreal30](https://github.com/surreal30). + +## 0.114.0 (2024-09-06) + +You can restrict form fields to only include those declared in a Pydantic model and forbid any extra field sent in the request using Pydantic's `model_config = {"extra": "forbid"}`: + +```python +from typing import Annotated + +from fastapi import FastAPI, Form +from pydantic import BaseModel + +app = FastAPI() + + +class FormData(BaseModel): + username: str + password: str + model_config = {"extra": "forbid"} + + +@app.post("/login/") +async def login(data: Annotated[FormData, Form()]): + return data +``` + +Read the new docs: [Form Models - Forbid Extra Form Fields](https://fastapi.tiangolo.com/tutorial/request-form-models/#forbid-extra-form-fields). + +### Features + +* ✨ Add support for forbidding extra form fields with Pydantic models. PR [#12134](https://github.com/fastapi/fastapi/pull/12134) by [@tiangolo](https://github.com/tiangolo). + +### Docs + +* 📝 Update docs, Form Models section title, to match config name. PR [#12152](https://github.com/fastapi/fastapi/pull/12152) by [@tiangolo](https://github.com/tiangolo). + +### Internal + +* ✅ Update internal tests for latest Pydantic, including CI tweaks to install the latest Pydantic. PR [#12147](https://github.com/fastapi/fastapi/pull/12147) by [@tiangolo](https://github.com/tiangolo). + +## 0.113.0 (2024-09-05) + +Now you can declare form fields with Pydantic models: + +```python +from typing import Annotated + +from fastapi import FastAPI, Form +from pydantic import BaseModel + +app = FastAPI() + + +class FormData(BaseModel): + username: str + password: str + + +@app.post("/login/") +async def login(data: Annotated[FormData, Form()]): + return data +``` + +Read the new docs: [Form Models](https://fastapi.tiangolo.com/tutorial/request-form-models/). + +### Features + +* ✨ Add support for Pydantic models in `Form` parameters. PR [#12129](https://github.com/fastapi/fastapi/pull/12129) by [@tiangolo](https://github.com/tiangolo). + +### Internal + +* 🔧 Update sponsors: Coherence link. PR [#12130](https://github.com/fastapi/fastapi/pull/12130) by [@tiangolo](https://github.com/tiangolo). + +## 0.112.4 (2024-09-05) + +This release is mainly a big internal refactor to enable adding support for Pydantic models for `Form` fields, but that feature comes in the next release. + +This release shouldn't affect apps using FastAPI in any way. You don't even have to upgrade to this version yet. It's just a checkpoint. 🤓 + +### Refactors + +* ♻️ Refactor deciding if `embed` body fields, do not overwrite fields, compute once per router, refactor internals in preparation for Pydantic models in `Form`, `Query` and others. PR [#12117](https://github.com/fastapi/fastapi/pull/12117) by [@tiangolo](https://github.com/tiangolo). + +### Internal + +* ⏪️ Temporarily revert "✨ Add support for Pydantic models in `Form` parameters" to make a checkpoint release. PR [#12128](https://github.com/fastapi/fastapi/pull/12128) by [@tiangolo](https://github.com/tiangolo). Restored by PR [#12129](https://github.com/fastapi/fastapi/pull/12129). +* ✨ Add support for Pydantic models in `Form` parameters. PR [#12127](https://github.com/fastapi/fastapi/pull/12127) by [@tiangolo](https://github.com/tiangolo). Reverted by PR [#12128](https://github.com/fastapi/fastapi/pull/12128) to make a checkpoint release with only refactors. Restored by PR [#12129](https://github.com/fastapi/fastapi/pull/12129). + +## 0.112.3 (2024-09-05) + +This release is mainly internal refactors, it shouldn't affect apps using FastAPI in any way. You don't even have to upgrade to this version yet. There are a few bigger releases coming right after. 🚀 + +### Refactors + +* ♻️ Refactor internal `check_file_field()`, rename to `ensure_multipart_is_installed()` to clarify its purpose. PR [#12106](https://github.com/fastapi/fastapi/pull/12106) by [@tiangolo](https://github.com/tiangolo). +* ♻️ Rename internal `create_response_field()` to `create_model_field()` as it's used for more than response models. PR [#12103](https://github.com/fastapi/fastapi/pull/12103) by [@tiangolo](https://github.com/tiangolo). +* ♻️ Refactor and simplify internal data from `solve_dependencies()` using dataclasses. PR [#12100](https://github.com/fastapi/fastapi/pull/12100) by [@tiangolo](https://github.com/tiangolo). +* ♻️ Refactor and simplify internal `analyze_param()` to structure data with dataclasses instead of tuple. PR [#12099](https://github.com/fastapi/fastapi/pull/12099) by [@tiangolo](https://github.com/tiangolo). +* ♻️ Refactor and simplify dependencies data structures with dataclasses. PR [#12098](https://github.com/fastapi/fastapi/pull/12098) by [@tiangolo](https://github.com/tiangolo). + +### Docs + +* 📝 Add External Link: Techniques and applications of SQLAlchemy global filters in FastAPI. PR [#12109](https://github.com/fastapi/fastapi/pull/12109) by [@TheShubhendra](https://github.com/TheShubhendra). +* 📝 Add note about `time.perf_counter()` in middlewares. PR [#12095](https://github.com/fastapi/fastapi/pull/12095) by [@tiangolo](https://github.com/tiangolo). +* 📝 Tweak middleware code sample `time.time()` to `time.perf_counter()`. PR [#11957](https://github.com/fastapi/fastapi/pull/11957) by [@domdent](https://github.com/domdent). +* 🔧 Update sponsors: Coherence. PR [#12093](https://github.com/fastapi/fastapi/pull/12093) by [@tiangolo](https://github.com/tiangolo). +* 📝 Fix async test example not to trigger DeprecationWarning. PR [#12084](https://github.com/fastapi/fastapi/pull/12084) by [@marcinsulikowski](https://github.com/marcinsulikowski). +* 📝 Update `docs_src/path_params_numeric_validations/tutorial006.py`. PR [#11478](https://github.com/fastapi/fastapi/pull/11478) by [@MuhammadAshiqAmeer](https://github.com/MuhammadAshiqAmeer). +* 📝 Update comma in `docs/en/docs/async.md`. PR [#12062](https://github.com/fastapi/fastapi/pull/12062) by [@Alec-Gillis](https://github.com/Alec-Gillis). +* 📝 Update docs about serving FastAPI: ASGI servers, Docker containers, etc.. PR [#12069](https://github.com/fastapi/fastapi/pull/12069) by [@tiangolo](https://github.com/tiangolo). +* 📝 Clarify `response_class` parameter, validations, and returning a response directly. PR [#12067](https://github.com/fastapi/fastapi/pull/12067) by [@tiangolo](https://github.com/tiangolo). +* 📝 Fix minor typos and issues in the documentation. PR [#12063](https://github.com/fastapi/fastapi/pull/12063) by [@svlandeg](https://github.com/svlandeg). +* 📝 Add note in Docker docs about ensuring graceful shutdowns and lifespan events with `CMD` exec form. PR [#11960](https://github.com/fastapi/fastapi/pull/11960) by [@GPla](https://github.com/GPla). + +### Translations + +* 🌐 Add Dutch translation for `docs/nl/docs/features.md`. PR [#12101](https://github.com/fastapi/fastapi/pull/12101) by [@maxscheijen](https://github.com/maxscheijen). +* 🌐 Add Portuguese translation for `docs/pt/docs/advanced/testing-events.md`. PR [#12108](https://github.com/fastapi/fastapi/pull/12108) by [@ceb10n](https://github.com/ceb10n). +* 🌐 Add Portuguese translation for `docs/pt/docs/advanced/security/index.md`. PR [#12114](https://github.com/fastapi/fastapi/pull/12114) by [@ceb10n](https://github.com/ceb10n). +* 🌐 Add Dutch translation for `docs/nl/docs/index.md`. PR [#12042](https://github.com/fastapi/fastapi/pull/12042) by [@svlandeg](https://github.com/svlandeg). +* 🌐 Update Chinese translation for `docs/zh/docs/how-to/index.md`. PR [#12070](https://github.com/fastapi/fastapi/pull/12070) by [@synthpop123](https://github.com/synthpop123). + +### Internal + +* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#12115](https://github.com/fastapi/fastapi/pull/12115) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). +* ⬆ Bump pypa/gh-action-pypi-publish from 1.10.0 to 1.10.1. PR [#12120](https://github.com/fastapi/fastapi/pull/12120) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump pillow from 10.3.0 to 10.4.0. PR [#12105](https://github.com/fastapi/fastapi/pull/12105) by [@dependabot[bot]](https://github.com/apps/dependabot). +* 💚 Set `include-hidden-files` to `True` when using the `upload-artifact` GH action. PR [#12118](https://github.com/fastapi/fastapi/pull/12118) by [@svlandeg](https://github.com/svlandeg). +* ⬆ Bump pypa/gh-action-pypi-publish from 1.9.0 to 1.10.0. PR [#12112](https://github.com/fastapi/fastapi/pull/12112) by [@dependabot[bot]](https://github.com/apps/dependabot). +* 🔧 Update sponsors link: Coherence. PR [#12097](https://github.com/fastapi/fastapi/pull/12097) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Update labeler config to handle sponsorships data. PR [#12096](https://github.com/fastapi/fastapi/pull/12096) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Update sponsors, remove Kong. PR [#12085](https://github.com/fastapi/fastapi/pull/12085) by [@tiangolo](https://github.com/tiangolo). +* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#12076](https://github.com/fastapi/fastapi/pull/12076) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). +* 👷 Update `latest-changes` GitHub Action. PR [#12073](https://github.com/fastapi/fastapi/pull/12073) by [@tiangolo](https://github.com/tiangolo). + +## 0.112.2 (2024-08-24) + +### Fixes + +* 🐛 Fix `allow_inf_nan` option for Param and Body classes. PR [#11867](https://github.com/fastapi/fastapi/pull/11867) by [@giunio-prc](https://github.com/giunio-prc). +* 🐛 Ensure that `app.include_router` merges nested lifespans. PR [#9630](https://github.com/fastapi/fastapi/pull/9630) by [@Lancetnik](https://github.com/Lancetnik). + +### Refactors + +* 🎨 Fix typing annotation for semi-internal `FastAPI.add_api_route()`. PR [#10240](https://github.com/fastapi/fastapi/pull/10240) by [@ordinary-jamie](https://github.com/ordinary-jamie). +* ⬆️ Upgrade version of Ruff and reformat. PR [#12032](https://github.com/fastapi/fastapi/pull/12032) by [@tiangolo](https://github.com/tiangolo). + +### Docs + +* 📝 Fix a typo in `docs/en/docs/virtual-environments.md`. PR [#12064](https://github.com/fastapi/fastapi/pull/12064) by [@aymenkrifa](https://github.com/aymenkrifa). +* 📝 Add docs about Environment Variables and Virtual Environments. PR [#12054](https://github.com/fastapi/fastapi/pull/12054) by [@tiangolo](https://github.com/tiangolo). +* 📝 Add Asyncer mention in async docs. PR [#12037](https://github.com/fastapi/fastapi/pull/12037) by [@tiangolo](https://github.com/tiangolo). +* 📝 Move the Features docs to the top level to improve the main page menu. PR [#12036](https://github.com/fastapi/fastapi/pull/12036) by [@tiangolo](https://github.com/tiangolo). +* ✏️ Fix import typo in reference example for `Security`. PR [#11168](https://github.com/fastapi/fastapi/pull/11168) by [@0shah0](https://github.com/0shah0). +* 📝 Highlight correct line in tutorial `docs/en/docs/tutorial/body-multiple-params.md`. PR [#11978](https://github.com/fastapi/fastapi/pull/11978) by [@svlandeg](https://github.com/svlandeg). +* 🔥 Remove Sentry link from Advanced Middleware docs. PR [#12031](https://github.com/fastapi/fastapi/pull/12031) by [@alejsdev](https://github.com/alejsdev). +* 📝 Clarify management tasks for translations, multiples files in one PR. PR [#12030](https://github.com/fastapi/fastapi/pull/12030) by [@tiangolo](https://github.com/tiangolo). +* 📝 Edit the link to the OpenAPI "Responses Object" and "Response Object" sections in the "Additional Responses in OpenAPI" section. PR [#11996](https://github.com/fastapi/fastapi/pull/11996) by [@VaitoSoi](https://github.com/VaitoSoi). +* 🔨 Specify `email-validator` dependency with dash. PR [#11515](https://github.com/fastapi/fastapi/pull/11515) by [@jirikuncar](https://github.com/jirikuncar). +* 🌐 Add Spanish translation for `docs/es/docs/project-generation.md`. PR [#11947](https://github.com/fastapi/fastapi/pull/11947) by [@alejsdev](https://github.com/alejsdev). +* 📝 Fix minor typo. PR [#12026](https://github.com/fastapi/fastapi/pull/12026) by [@MicaelJarniac](https://github.com/MicaelJarniac). +* 📝 Several docs improvements, tweaks, and clarifications. PR [#11390](https://github.com/fastapi/fastapi/pull/11390) by [@nilslindemann](https://github.com/nilslindemann). +* 📝 Add missing `compresslevel` parameter on docs for `GZipMiddleware`. PR [#11350](https://github.com/fastapi/fastapi/pull/11350) by [@junah201](https://github.com/junah201). +* 📝 Fix inconsistent response code when item already exists in docs for testing. PR [#11818](https://github.com/fastapi/fastapi/pull/11818) by [@lokomilo](https://github.com/lokomilo). +* 📝 Update `docs/en/docs/tutorial/body.md` with Python 3.10 union type example. PR [#11415](https://github.com/fastapi/fastapi/pull/11415) by [@rangzen](https://github.com/rangzen). + +### Translations + +* 🌐 Add Portuguese translation for `docs/pt/docs/tutorial/request_file.md`. PR [#12018](https://github.com/fastapi/fastapi/pull/12018) by [@Joao-Pedro-P-Holanda](https://github.com/Joao-Pedro-P-Holanda). +* 🌐 Add Japanese translation for `docs/ja/docs/learn/index.md`. PR [#11592](https://github.com/fastapi/fastapi/pull/11592) by [@ukwhatn](https://github.com/ukwhatn). +* 📝 Update Spanish translation docs for consistency. PR [#12044](https://github.com/fastapi/fastapi/pull/12044) by [@alejsdev](https://github.com/alejsdev). +* 🌐 Update Chinese translation for `docs/zh/docs/tutorial/dependencies/dependencies-with-yield.md`. PR [#12028](https://github.com/fastapi/fastapi/pull/12028) by [@xuvjso](https://github.com/xuvjso). +* 📝 Update FastAPI People, do not translate to have the most recent info. PR [#12034](https://github.com/fastapi/fastapi/pull/12034) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Update Urdu translation for `docs/ur/docs/benchmarks.md`. PR [#10046](https://github.com/fastapi/fastapi/pull/10046) by [@AhsanSheraz](https://github.com/AhsanSheraz). + +### Internal + +* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#12046](https://github.com/fastapi/fastapi/pull/12046) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). +* 🔧 Update coverage config files. PR [#12035](https://github.com/fastapi/fastapi/pull/12035) by [@tiangolo](https://github.com/tiangolo). +* 🔨 Standardize shebang across shell scripts. PR [#11942](https://github.com/fastapi/fastapi/pull/11942) by [@gitworkflows](https://github.com/gitworkflows). +* ⬆ Update sqlalchemy requirement from <1.4.43,>=1.3.18 to >=1.3.18,<2.0.33. PR [#11979](https://github.com/fastapi/fastapi/pull/11979) by [@dependabot[bot]](https://github.com/apps/dependabot). +* 🔊 Remove old ignore warnings. PR [#11950](https://github.com/fastapi/fastapi/pull/11950) by [@tiangolo](https://github.com/tiangolo). +* ⬆️ Upgrade griffe-typingdoc for the docs. PR [#12029](https://github.com/fastapi/fastapi/pull/12029) by [@tiangolo](https://github.com/tiangolo). +* 🙈 Add .coverage* to `.gitignore`. PR [#11940](https://github.com/fastapi/fastapi/pull/11940) by [@gitworkflows](https://github.com/gitworkflows). +* ⚙️ Record and show test coverage contexts (what test covers which line). PR [#11518](https://github.com/fastapi/fastapi/pull/11518) by [@slafs](https://github.com/slafs). + +## 0.112.1 (2024-08-15) + +### Upgrades + +* ⬆️ Allow Starlette 0.38.x, update the pin to `>=0.37.2,<0.39.0`. PR [#11876](https://github.com/fastapi/fastapi/pull/11876) by [@musicinmybrain](https://github.com/musicinmybrain). + +### Docs + +* 📝 Update docs section about "Don't Translate these Pages". PR [#12022](https://github.com/fastapi/fastapi/pull/12022) by [@tiangolo](https://github.com/tiangolo). +* 📝 Add documentation for non-translated pages and scripts to verify them. PR [#12020](https://github.com/fastapi/fastapi/pull/12020) by [@tiangolo](https://github.com/tiangolo). +* 📝 Update docs about discussions questions. PR [#11985](https://github.com/fastapi/fastapi/pull/11985) by [@tiangolo](https://github.com/tiangolo). + +### Translations + +* 🌐 Add Portuguese translation for `docs/pt/docs/tutorial/bigger-applications.md`. PR [#11971](https://github.com/fastapi/fastapi/pull/11971) by [@marcelomarkus](https://github.com/marcelomarkus). +* 🌐 Add Portuguese translation for `docs/pt/docs/advanced/testing-websockets.md`. PR [#11994](https://github.com/fastapi/fastapi/pull/11994) by [@ceb10n](https://github.com/ceb10n). +* 🌐 Add Portuguese translation for `docs/pt/docs/advanced/testing-dependencies.md`. PR [#11995](https://github.com/fastapi/fastapi/pull/11995) by [@ceb10n](https://github.com/ceb10n). +* 🌐 Add Portuguese translation for `docs/pt/docs/advanced/using-request-directly.md`. PR [#11956](https://github.com/fastapi/fastapi/pull/11956) by [@ceb10n](https://github.com/ceb10n). +* 🌐 Add French translation for `docs/fr/docs/tutorial/body-multiple-params.md`. PR [#11796](https://github.com/fastapi/fastapi/pull/11796) by [@pe-brian](https://github.com/pe-brian). +* 🌐 Update Chinese translation for `docs/zh/docs/tutorial/query-params.md`. PR [#11557](https://github.com/fastapi/fastapi/pull/11557) by [@caomingpei](https://github.com/caomingpei). +* 🌐 Update typo in Chinese translation for `docs/zh/docs/advanced/testing-dependencies.md`. PR [#11944](https://github.com/fastapi/fastapi/pull/11944) by [@bestony](https://github.com/bestony). +* 🌐 Add Portuguese translation for `docs/pt/docs/advanced/sub-applications.md` and `docs/pt/docs/advanced/behind-a-proxy.md`. PR [#11856](https://github.com/fastapi/fastapi/pull/11856) by [@marcelomarkus](https://github.com/marcelomarkus). +* 🌐 Add Portuguese translation for `docs/pt/docs/tutorial/cors.md` and `docs/pt/docs/tutorial/middleware.md`. PR [#11916](https://github.com/fastapi/fastapi/pull/11916) by [@wesinalves](https://github.com/wesinalves). +* 🌐 Add French translation for `docs/fr/docs/tutorial/path-params-numeric-validations.md`. PR [#11788](https://github.com/fastapi/fastapi/pull/11788) by [@pe-brian](https://github.com/pe-brian). + +### Internal + +* ⬆ Bump pypa/gh-action-pypi-publish from 1.8.14 to 1.9.0. PR [#11727](https://github.com/fastapi/fastapi/pull/11727) by [@dependabot[bot]](https://github.com/apps/dependabot). +* 🔧 Add changelog URL to `pyproject.toml`, shows in PyPI. PR [#11152](https://github.com/fastapi/fastapi/pull/11152) by [@Pierre-VF](https://github.com/Pierre-VF). +* 👷 Do not sync labels as it overrides manually added labels. PR [#12024](https://github.com/fastapi/fastapi/pull/12024) by [@tiangolo](https://github.com/tiangolo). +* 👷🏻 Update Labeler GitHub Actions. PR [#12019](https://github.com/fastapi/fastapi/pull/12019) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Update configs for MkDocs for languages and social cards. PR [#12016](https://github.com/fastapi/fastapi/pull/12016) by [@tiangolo](https://github.com/tiangolo). +* 👷 Update permissions and config for labeler GitHub Action. PR [#12008](https://github.com/fastapi/fastapi/pull/12008) by [@tiangolo](https://github.com/tiangolo). +* 👷🏻 Add GitHub Action label-checker. PR [#12005](https://github.com/fastapi/fastapi/pull/12005) by [@tiangolo](https://github.com/tiangolo). +* 👷 Add label checker GitHub Action. PR [#12004](https://github.com/fastapi/fastapi/pull/12004) by [@tiangolo](https://github.com/tiangolo). +* 👷 Update GitHub Action add-to-project. PR [#12002](https://github.com/fastapi/fastapi/pull/12002) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Update labeler GitHub Action. PR [#12001](https://github.com/fastapi/fastapi/pull/12001) by [@tiangolo](https://github.com/tiangolo). +* 👷 Add GitHub Action labeler. PR [#12000](https://github.com/fastapi/fastapi/pull/12000) by [@tiangolo](https://github.com/tiangolo). +* 👷 Add GitHub Action add-to-project. PR [#11999](https://github.com/fastapi/fastapi/pull/11999) by [@tiangolo](https://github.com/tiangolo). +* 📝 Update admonitions in docs missing. PR [#11998](https://github.com/fastapi/fastapi/pull/11998) by [@tiangolo](https://github.com/tiangolo). +* 🔨 Update docs.py script to enable dirty reload conditionally. PR [#11986](https://github.com/fastapi/fastapi/pull/11986) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Update MkDocs instant previews. PR [#11982](https://github.com/fastapi/fastapi/pull/11982) by [@tiangolo](https://github.com/tiangolo). +* 🐛 Fix deploy docs previews script to handle mkdocs.yml files. PR [#11984](https://github.com/fastapi/fastapi/pull/11984) by [@tiangolo](https://github.com/tiangolo). +* 💡 Add comment about custom Termynal line-height. PR [#11976](https://github.com/fastapi/fastapi/pull/11976) by [@tiangolo](https://github.com/tiangolo). +* 👷 Add alls-green for test-redistribute. PR [#11974](https://github.com/fastapi/fastapi/pull/11974) by [@tiangolo](https://github.com/tiangolo). +* 👷 Update docs-previews to handle no docs changes. PR [#11975](https://github.com/fastapi/fastapi/pull/11975) by [@tiangolo](https://github.com/tiangolo). +* 🔨 Refactor script `deploy_docs_status.py` to account for deploy URLs with or without trailing slash. PR [#11965](https://github.com/fastapi/fastapi/pull/11965) by [@tiangolo](https://github.com/tiangolo). +* 🔒️ Update permissions for deploy-docs action. PR [#11964](https://github.com/fastapi/fastapi/pull/11964) by [@tiangolo](https://github.com/tiangolo). +* 👷🏻 Add deploy docs status and preview links to PRs. PR [#11961](https://github.com/fastapi/fastapi/pull/11961) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Update docs setup with latest configs and plugins. PR [#11953](https://github.com/fastapi/fastapi/pull/11953) by [@tiangolo](https://github.com/tiangolo). +* 🔇 Ignore warning from attrs in Trio. PR [#11949](https://github.com/fastapi/fastapi/pull/11949) by [@tiangolo](https://github.com/tiangolo). + +## 0.112.0 (2024-08-02) + +### Breaking Changes + +* ♻️ Add support for `pip install "fastapi[standard]"` with standard dependencies and `python -m fastapi`. PR [#11935](https://github.com/fastapi/fastapi/pull/11935) by [@tiangolo](https://github.com/tiangolo). + +#### Summary + +Install with: + +```bash +pip install "fastapi[standard]" +``` + +#### Other Changes + +* This adds support for calling the CLI as: + +```bash +python -m fastapi +``` + +* And it upgrades `fastapi-cli[standard] >=0.0.5`. + +#### Technical Details + +Before this, `fastapi` would include the standard dependencies, with Uvicorn and the `fastapi-cli`, etc. + +And `fastapi-slim` would not include those standard dependencies. + +Now `fastapi` doesn't include those standard dependencies unless you install with `pip install "fastapi[standard]"`. + +Before, you would install `pip install fastapi`, now you should include the `standard` optional dependencies (unless you want to exclude one of those): `pip install "fastapi[standard]"`. + +This change is because having the standard optional dependencies installed by default was being inconvenient to several users, and having to install instead `fastapi-slim` was not being a feasible solution. + +Discussed here: [#11522](https://github.com/fastapi/fastapi/pull/11522) and here: [#11525](https://github.com/fastapi/fastapi/discussions/11525) + +### Docs + +* ✏️ Fix typos in docs. PR [#11926](https://github.com/fastapi/fastapi/pull/11926) by [@jianghuyiyuan](https://github.com/jianghuyiyuan). +* 📝 Tweak management docs. PR [#11918](https://github.com/fastapi/fastapi/pull/11918) by [@tiangolo](https://github.com/tiangolo). +* 🚚 Rename GitHub links from tiangolo/fastapi to fastapi/fastapi. PR [#11913](https://github.com/fastapi/fastapi/pull/11913) by [@tiangolo](https://github.com/tiangolo). +* 📝 Add docs about FastAPI team and project management. PR [#11908](https://github.com/tiangolo/fastapi/pull/11908) by [@tiangolo](https://github.com/tiangolo). +* 📝 Re-structure docs main menu. PR [#11904](https://github.com/tiangolo/fastapi/pull/11904) by [@tiangolo](https://github.com/tiangolo). +* 📝 Update Speakeasy URL. PR [#11871](https://github.com/tiangolo/fastapi/pull/11871) by [@ndimares](https://github.com/ndimares). + +### Translations + +* 🌐 Update Portuguese translation for `docs/pt/docs/alternatives.md`. PR [#11931](https://github.com/fastapi/fastapi/pull/11931) by [@ceb10n](https://github.com/ceb10n). +* 🌐 Add Russian translation for `docs/ru/docs/tutorial/dependencies/sub-dependencies.md`. PR [#10515](https://github.com/tiangolo/fastapi/pull/10515) by [@AlertRED](https://github.com/AlertRED). +* 🌐 Add Portuguese translation for `docs/pt/docs/advanced/response-change-status-code.md`. PR [#11863](https://github.com/tiangolo/fastapi/pull/11863) by [@ceb10n](https://github.com/ceb10n). +* 🌐 Add Portuguese translation for `docs/pt/docs/reference/background.md`. PR [#11849](https://github.com/tiangolo/fastapi/pull/11849) by [@lucasbalieiro](https://github.com/lucasbalieiro). +* 🌐 Add Portuguese translation for `docs/pt/docs/tutorial/dependencies/dependencies-with-yield.md`. PR [#11848](https://github.com/tiangolo/fastapi/pull/11848) by [@Joao-Pedro-P-Holanda](https://github.com/Joao-Pedro-P-Holanda). +* 🌐 Add Portuguese translation for `docs/pt/docs/reference/apirouter.md`. PR [#11843](https://github.com/tiangolo/fastapi/pull/11843) by [@lucasbalieiro](https://github.com/lucasbalieiro). + +### Internal + +* 🔧 Update sponsors: add liblab. PR [#11934](https://github.com/fastapi/fastapi/pull/11934) by [@tiangolo](https://github.com/tiangolo). +* 👷 Update GitHub Action label-approved permissions. PR [#11933](https://github.com/fastapi/fastapi/pull/11933) by [@tiangolo](https://github.com/tiangolo). +* 👷 Refactor GitHub Action to comment docs deployment URLs and update token. PR [#11925](https://github.com/fastapi/fastapi/pull/11925) by [@tiangolo](https://github.com/tiangolo). +* 👷 Update tokens for GitHub Actions. PR [#11924](https://github.com/fastapi/fastapi/pull/11924) by [@tiangolo](https://github.com/tiangolo). +* 👷 Update token permissions to comment deployment URL in docs. PR [#11917](https://github.com/fastapi/fastapi/pull/11917) by [@tiangolo](https://github.com/tiangolo). +* 👷 Update token permissions for GitHub Actions. PR [#11915](https://github.com/fastapi/fastapi/pull/11915) by [@tiangolo](https://github.com/tiangolo). +* 👷 Update GitHub Actions token usage. PR [#11914](https://github.com/fastapi/fastapi/pull/11914) by [@tiangolo](https://github.com/tiangolo). +* 👷 Update GitHub Action to notify translations with label `approved-1`. PR [#11907](https://github.com/tiangolo/fastapi/pull/11907) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Update sponsors, remove Reflex. PR [#11875](https://github.com/tiangolo/fastapi/pull/11875) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Update sponsors: remove TalkPython. PR [#11861](https://github.com/tiangolo/fastapi/pull/11861) by [@tiangolo](https://github.com/tiangolo). +* 🔨 Update docs Termynal scripts to not include line nums for local dev. PR [#11854](https://github.com/tiangolo/fastapi/pull/11854) by [@tiangolo](https://github.com/tiangolo). + +## 0.111.1 (2024-07-14) + +### Upgrades + +* ➖ Remove `orjson` and `ujson` from default dependencies. PR [#11842](https://github.com/tiangolo/fastapi/pull/11842) by [@tiangolo](https://github.com/tiangolo). + * These dependencies are still installed when you install with `pip install "fastapi[all]"`. But they are not included in `pip install fastapi`. +* 📝 Restored Swagger-UI links to use the latest version possible. PR [#11459](https://github.com/tiangolo/fastapi/pull/11459) by [@UltimateLobster](https://github.com/UltimateLobster). + +### Docs + +* ✏️ Rewording in `docs/en/docs/fastapi-cli.md`. PR [#11716](https://github.com/tiangolo/fastapi/pull/11716) by [@alejsdev](https://github.com/alejsdev). +* 📝 Update Hypercorn links in all the docs. PR [#11744](https://github.com/tiangolo/fastapi/pull/11744) by [@kittydoor](https://github.com/kittydoor). +* 📝 Update docs with Ariadne reference from Starlette to FastAPI. PR [#11797](https://github.com/tiangolo/fastapi/pull/11797) by [@DamianCzajkowski](https://github.com/DamianCzajkowski). +* 📝 Update fastapi instrumentation external link. PR [#11317](https://github.com/tiangolo/fastapi/pull/11317) by [@softwarebloat](https://github.com/softwarebloat). +* ✏️ Fix links to alembic example repo in docs. PR [#11628](https://github.com/tiangolo/fastapi/pull/11628) by [@augiwan](https://github.com/augiwan). +* ✏️ Update `docs/en/docs/fastapi-cli.md`. PR [#11715](https://github.com/tiangolo/fastapi/pull/11715) by [@alejsdev](https://github.com/alejsdev). +* 📝 Update External Links . PR [#11500](https://github.com/tiangolo/fastapi/pull/11500) by [@devon2018](https://github.com/devon2018). +* 📝 Add External Link: Tutorial de FastAPI, ¿el mejor framework de Python?. PR [#11618](https://github.com/tiangolo/fastapi/pull/11618) by [@EduardoZepeda](https://github.com/EduardoZepeda). +* 📝 Fix typo in `docs/en/docs/tutorial/body-multiple-params.md`. PR [#11698](https://github.com/tiangolo/fastapi/pull/11698) by [@mwb-u](https://github.com/mwb-u). +* 📝 Add External Link: Deploy a Serverless FastAPI App with Neon Postgres and AWS App Runner at any scale. PR [#11633](https://github.com/tiangolo/fastapi/pull/11633) by [@ananis25](https://github.com/ananis25). +* 📝 Update `security/first-steps.md`. PR [#11674](https://github.com/tiangolo/fastapi/pull/11674) by [@alejsdev](https://github.com/alejsdev). +* 📝 Update `security/first-steps.md`. PR [#11673](https://github.com/tiangolo/fastapi/pull/11673) by [@alejsdev](https://github.com/alejsdev). +* 📝 Update note in `path-params-numeric-validations.md`. PR [#11672](https://github.com/tiangolo/fastapi/pull/11672) by [@alejsdev](https://github.com/alejsdev). +* 📝 Tweak intro docs about `Annotated` and `Query()` params. PR [#11664](https://github.com/tiangolo/fastapi/pull/11664) by [@tiangolo](https://github.com/tiangolo). +* 📝 Update JWT auth documentation to use PyJWT instead of python-jose. PR [#11589](https://github.com/tiangolo/fastapi/pull/11589) by [@estebanx64](https://github.com/estebanx64). +* 📝 Update docs. PR [#11603](https://github.com/tiangolo/fastapi/pull/11603) by [@alejsdev](https://github.com/alejsdev). +* ✏️ Fix typo: convert every 're-use' to 'reuse'.. PR [#11598](https://github.com/tiangolo/fastapi/pull/11598) by [@hasansezertasan](https://github.com/hasansezertasan). +* ✏️ Fix typo in `fastapi/applications.py`. PR [#11593](https://github.com/tiangolo/fastapi/pull/11593) by [@petarmaric](https://github.com/petarmaric). +* ✏️ Fix link in `fastapi-cli.md`. PR [#11524](https://github.com/tiangolo/fastapi/pull/11524) by [@svlandeg](https://github.com/svlandeg). + +### Translations + +* 🌐 Add Spanish translation for `docs/es/docs/how-to/graphql.md`. PR [#11697](https://github.com/tiangolo/fastapi/pull/11697) by [@camigomezdev](https://github.com/camigomezdev). +* 🌐 Add Portuguese translation for `docs/pt/docs/reference/index.md`. PR [#11840](https://github.com/tiangolo/fastapi/pull/11840) by [@lucasbalieiro](https://github.com/lucasbalieiro). +* 🌐 Fix link in German translation. PR [#11836](https://github.com/tiangolo/fastapi/pull/11836) by [@anitahammer](https://github.com/anitahammer). +* 🌐 Add Portuguese translation for `docs/pt/docs/tutorial/dependencies/sub-dependencies.md`. PR [#11792](https://github.com/tiangolo/fastapi/pull/11792) by [@Joao-Pedro-P-Holanda](https://github.com/Joao-Pedro-P-Holanda). +* 🌐 Add Turkish translation for `docs/tr/docs/tutorial/request-forms.md`. PR [#11553](https://github.com/tiangolo/fastapi/pull/11553) by [@hasansezertasan](https://github.com/hasansezertasan). +* 🌐 Add Portuguese translation for `docs/pt/docs/reference/exceptions.md`. PR [#11834](https://github.com/tiangolo/fastapi/pull/11834) by [@lucasbalieiro](https://github.com/lucasbalieiro). +* 🌐 Add Portuguese translation for `docs/pt/docs/tutorial/dependencies/global-dependencies.md`. PR [#11826](https://github.com/tiangolo/fastapi/pull/11826) by [@Joao-Pedro-P-Holanda](https://github.com/Joao-Pedro-P-Holanda). +* 🌐 Add Portuguese translation for `docs/pt/docs/how-to/general.md`. PR [#11825](https://github.com/tiangolo/fastapi/pull/11825) by [@lucasbalieiro](https://github.com/lucasbalieiro). +* 🌐 Add Portuguese translation for `docs/pt/docs/advanced/async-tests.md`. PR [#11808](https://github.com/tiangolo/fastapi/pull/11808) by [@ceb10n](https://github.com/ceb10n). +* 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/first-steps.md`. PR [#11809](https://github.com/tiangolo/fastapi/pull/11809) by [@vkhoroshchak](https://github.com/vkhoroshchak). +* 🌐 Add Portuguese translation for `docs/pt/docs/tutorial/dependencies/dependencies-in-path-operation-operators.md`. PR [#11804](https://github.com/tiangolo/fastapi/pull/11804) by [@Joao-Pedro-P-Holanda](https://github.com/Joao-Pedro-P-Holanda). +* 🌐 Add Chinese translation for `docs/zh/docs/fastapi-cli.md`. PR [#11786](https://github.com/tiangolo/fastapi/pull/11786) by [@logan2d5](https://github.com/logan2d5). +* 🌐 Add Portuguese translation for `docs/pt/docs/advanced/openapi-webhooks.md`. PR [#11791](https://github.com/tiangolo/fastapi/pull/11791) by [@ceb10n](https://github.com/ceb10n). +* 🌐 Update Chinese translation for `docs/tutorial/security/oauth2-jwt.md`. PR [#11781](https://github.com/tiangolo/fastapi/pull/11781) by [@logan2d5](https://github.com/logan2d5). +* 📝 Fix image missing in French translation for `docs/fr/docs/async.md` . PR [#11787](https://github.com/tiangolo/fastapi/pull/11787) by [@pe-brian](https://github.com/pe-brian). +* 🌐 Add Portuguese translation for `docs/pt/docs/advanced/advanced-dependencies.md`. PR [#11775](https://github.com/tiangolo/fastapi/pull/11775) by [@ceb10n](https://github.com/ceb10n). +* 🌐 Add Portuguese translation for `docs/pt/docs/tutorial/dependencies/classes-as-dependencies.md`. PR [#11768](https://github.com/tiangolo/fastapi/pull/11768) by [@Joao-Pedro-P-Holanda](https://github.com/Joao-Pedro-P-Holanda). +* 🌐 Add Portuguese translation for `docs/pt/docs/advanced/additional-status-codes.md`. PR [#11753](https://github.com/tiangolo/fastapi/pull/11753) by [@ceb10n](https://github.com/ceb10n). +* 🌐 Add Portuguese translation for `docs/pt/docs/tutorial/dependencies/index.md`. PR [#11757](https://github.com/tiangolo/fastapi/pull/11757) by [@Joao-Pedro-P-Holanda](https://github.com/Joao-Pedro-P-Holanda). +* 🌐 Add Portuguese translation for `docs/pt/docs/advanced/settings.md`. PR [#11739](https://github.com/tiangolo/fastapi/pull/11739) by [@Joao-Pedro-P-Holanda](https://github.com/Joao-Pedro-P-Holanda). +* 🌐 Add French translation for `docs/fr/docs/learn/index.md`. PR [#11712](https://github.com/tiangolo/fastapi/pull/11712) by [@benjaminvandammeholberton](https://github.com/benjaminvandammeholberton). +* 🌐 Add Portuguese translation for `docs/pt/docs/how-to/index.md`. PR [#11731](https://github.com/tiangolo/fastapi/pull/11731) by [@vhsenna](https://github.com/vhsenna). +* 🌐 Add Portuguese translation for `docs/pt/docs/advanced/additional-responses.md`. PR [#11736](https://github.com/tiangolo/fastapi/pull/11736) by [@ceb10n](https://github.com/ceb10n). +* 🌐 Add Portuguese translation for `docs/pt/docs/advanced/benchmarks.md`. PR [#11713](https://github.com/tiangolo/fastapi/pull/11713) by [@ceb10n](https://github.com/ceb10n). +* 🌐 Fix Korean translation for `docs/ko/docs/tutorial/response-status-code.md`. PR [#11718](https://github.com/tiangolo/fastapi/pull/11718) by [@nayeonkinn](https://github.com/nayeonkinn). +* 🌐 Add Korean translation for `docs/ko/docs/tutorial/extra-data-types.md`. PR [#11711](https://github.com/tiangolo/fastapi/pull/11711) by [@nayeonkinn](https://github.com/nayeonkinn). +* 🌐 Fix Korean translation for `docs/ko/docs/tutorial/body-nested-models.md`. PR [#11710](https://github.com/tiangolo/fastapi/pull/11710) by [@nayeonkinn](https://github.com/nayeonkinn). +* 🌐 Add Portuguese translation for `docs/pt/docs/advanced/fastapi-cli.md`. PR [#11641](https://github.com/tiangolo/fastapi/pull/11641) by [@ayr-ton](https://github.com/ayr-ton). +* 🌐 Add Traditional Chinese translation for `docs/zh-hant/docs/fastapi-people.md`. PR [#11639](https://github.com/tiangolo/fastapi/pull/11639) by [@hsuanchi](https://github.com/hsuanchi). +* 🌐 Add Turkish translation for `docs/tr/docs/advanced/index.md`. PR [#11606](https://github.com/tiangolo/fastapi/pull/11606) by [@hasansezertasan](https://github.com/hasansezertasan). +* 🌐 Add Turkish translation for `docs/tr/docs/deployment/cloud.md`. PR [#11610](https://github.com/tiangolo/fastapi/pull/11610) by [@hasansezertasan](https://github.com/hasansezertasan). +* 🌐 Add Turkish translation for `docs/tr/docs/advanced/security/index.md`. PR [#11609](https://github.com/tiangolo/fastapi/pull/11609) by [@hasansezertasan](https://github.com/hasansezertasan). +* 🌐 Add Turkish translation for `docs/tr/docs/advanced/testing-websockets.md`. PR [#11608](https://github.com/tiangolo/fastapi/pull/11608) by [@hasansezertasan](https://github.com/hasansezertasan). +* 🌐 Add Turkish translation for `docs/tr/docs/how-to/general.md`. PR [#11607](https://github.com/tiangolo/fastapi/pull/11607) by [@hasansezertasan](https://github.com/hasansezertasan). +* 🌐 Update Chinese translation for `docs/zh/docs/advanced/templates.md`. PR [#11620](https://github.com/tiangolo/fastapi/pull/11620) by [@chaoless](https://github.com/chaoless). +* 🌐 Add Turkish translation for `docs/tr/docs/deployment/index.md`. PR [#11605](https://github.com/tiangolo/fastapi/pull/11605) by [@hasansezertasan](https://github.com/hasansezertasan). +* 🌐 Add Turkish translation for `docs/tr/docs/tutorial/static-files.md`. PR [#11599](https://github.com/tiangolo/fastapi/pull/11599) by [@hasansezertasan](https://github.com/hasansezertasan). +* 🌐 Polish translation for `docs/pl/docs/fastapi-people.md`. PR [#10196](https://github.com/tiangolo/fastapi/pull/10196) by [@isulim](https://github.com/isulim). +* 🌐 Add Turkish translation for `docs/tr/docs/advanced/wsgi.md`. PR [#11575](https://github.com/tiangolo/fastapi/pull/11575) by [@hasansezertasan](https://github.com/hasansezertasan). +* 🌐 Add Turkish translation for `docs/tr/docs/tutorial/cookie-params.md`. PR [#11561](https://github.com/tiangolo/fastapi/pull/11561) by [@hasansezertasan](https://github.com/hasansezertasan). +* 🌐 Add Russian translation for `docs/ru/docs/about/index.md`. PR [#10961](https://github.com/tiangolo/fastapi/pull/10961) by [@s111d](https://github.com/s111d). +* 🌐 Update Chinese translation for `docs/zh/docs/tutorial/sql-databases.md`. PR [#11539](https://github.com/tiangolo/fastapi/pull/11539) by [@chaoless](https://github.com/chaoless). +* 🌐 Add Chinese translation for `docs/zh/docs/how-to/configure-swagger-ui.md`. PR [#11501](https://github.com/tiangolo/fastapi/pull/11501) by [@Lucas-lyh](https://github.com/Lucas-lyh). +* 🌐 Update Chinese translation for `/docs/advanced/security/http-basic-auth.md`. PR [#11512](https://github.com/tiangolo/fastapi/pull/11512) by [@nick-cjyx9](https://github.com/nick-cjyx9). + +### Internal + +* ♻️ Simplify internal docs script. PR [#11777](https://github.com/tiangolo/fastapi/pull/11777) by [@gitworkflows](https://github.com/gitworkflows). +* 🔧 Update sponsors: add Fine. PR [#11784](https://github.com/tiangolo/fastapi/pull/11784) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Tweak sponsors: Kong URL. PR [#11765](https://github.com/tiangolo/fastapi/pull/11765) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Tweak sponsors: Kong URL. PR [#11764](https://github.com/tiangolo/fastapi/pull/11764) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Update sponsors, add Stainless. PR [#11763](https://github.com/tiangolo/fastapi/pull/11763) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Update sponsors, add Zuplo. PR [#11729](https://github.com/tiangolo/fastapi/pull/11729) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Update Sponsor link: Coherence. PR [#11730](https://github.com/tiangolo/fastapi/pull/11730) by [@tiangolo](https://github.com/tiangolo). +* 👥 Update FastAPI People. PR [#11669](https://github.com/tiangolo/fastapi/pull/11669) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Add sponsor Kong. PR [#11662](https://github.com/tiangolo/fastapi/pull/11662) by [@tiangolo](https://github.com/tiangolo). +* 👷 Update Smokeshow, fix sync download artifact and smokeshow configs. PR [#11563](https://github.com/tiangolo/fastapi/pull/11563) by [@tiangolo](https://github.com/tiangolo). +* 👷 Update Smokeshow download artifact GitHub Action. PR [#11562](https://github.com/tiangolo/fastapi/pull/11562) by [@tiangolo](https://github.com/tiangolo). +* 👷 Update GitHub actions to download and upload artifacts to v4, for docs and coverage. PR [#11550](https://github.com/tiangolo/fastapi/pull/11550) by [@tamird](https://github.com/tamird). +* 👷 Tweak CI for test-redistribute, add needed env vars for slim. PR [#11549](https://github.com/tiangolo/fastapi/pull/11549) by [@tiangolo](https://github.com/tiangolo). +* 👥 Update FastAPI People. PR [#11511](https://github.com/tiangolo/fastapi/pull/11511) by [@tiangolo](https://github.com/tiangolo). + +## 0.111.0 (2024-05-03) + +### Features + +* ✨ Add FastAPI CLI, the new `fastapi` command. PR [#11522](https://github.com/tiangolo/fastapi/pull/11522) by [@tiangolo](https://github.com/tiangolo). + * New docs: [FastAPI CLI](https://fastapi.tiangolo.com/fastapi-cli/). + +Try it out with: + +```console +$ pip install --upgrade fastapi + +$ fastapi dev main.py + + + ╭────────── FastAPI CLI - Development mode ───────────╮ + │ │ + │ Serving at: http://127.0.0.1:8000 │ + │ │ + │ API docs: http://127.0.0.1:8000/docs │ + │ │ + │ Running in development mode, for production use: │ + │ │ + │ fastapi run │ + │ │ + ╰─────────────────────────────────────────────────────╯ + +INFO: Will watch for changes in these directories: ['/home/user/code/awesomeapp'] +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +INFO: Started reloader process [2248755] using WatchFiles +INFO: Started server process [2248757] +INFO: Waiting for application startup. +INFO: Application startup complete. +``` + +### Refactors + +* 🔧 Add configs and setup for `fastapi-slim` including optional extras `fastapi-slim[standard]`, and `fastapi` including by default the same `standard` extras. PR [#11503](https://github.com/tiangolo/fastapi/pull/11503) by [@tiangolo](https://github.com/tiangolo). + +## 0.110.3 (2024-04-30) + +### Docs + +* 📝 Update references to Python version, FastAPI supports all the current versions, no need to make the version explicit. PR [#11496](https://github.com/tiangolo/fastapi/pull/11496) by [@tiangolo](https://github.com/tiangolo). +* ✏️ Fix typo in `fastapi/security/api_key.py`. PR [#11481](https://github.com/tiangolo/fastapi/pull/11481) by [@ch33zer](https://github.com/ch33zer). +* ✏️ Fix typo in `security/http.py`. PR [#11455](https://github.com/tiangolo/fastapi/pull/11455) by [@omarmoo5](https://github.com/omarmoo5). + +### Translations + +* 🌐 Add Traditional Chinese translation for `docs/zh-hant/benchmarks.md`. PR [#11484](https://github.com/tiangolo/fastapi/pull/11484) by [@KNChiu](https://github.com/KNChiu). +* 🌐 Update Chinese translation for `docs/zh/docs/fastapi-people.md`. PR [#11476](https://github.com/tiangolo/fastapi/pull/11476) by [@billzhong](https://github.com/billzhong). +* 🌐 Add Chinese translation for `docs/zh/docs/how-to/index.md` and `docs/zh/docs/how-to/general.md`. PR [#11443](https://github.com/tiangolo/fastapi/pull/11443) by [@billzhong](https://github.com/billzhong). +* 🌐 Add Spanish translation for cookie-params `docs/es/docs/tutorial/cookie-params.md`. PR [#11410](https://github.com/tiangolo/fastapi/pull/11410) by [@fabianfalon](https://github.com/fabianfalon). + +### Internal + +* ⬆ Bump mkdocstrings[python] from 0.23.0 to 0.24.3. PR [#11469](https://github.com/tiangolo/fastapi/pull/11469) by [@dependabot[bot]](https://github.com/apps/dependabot). +* 🔨 Update internal scripts and remove unused ones. PR [#11499](https://github.com/tiangolo/fastapi/pull/11499) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Migrate from Hatch to PDM for the internal build. PR [#11498](https://github.com/tiangolo/fastapi/pull/11498) by [@tiangolo](https://github.com/tiangolo). +* ⬆️ Upgrade MkDocs Material and re-enable cards. PR [#11466](https://github.com/tiangolo/fastapi/pull/11466) by [@tiangolo](https://github.com/tiangolo). +* ⬆ Bump pillow from 10.2.0 to 10.3.0. PR [#11403](https://github.com/tiangolo/fastapi/pull/11403) by [@dependabot[bot]](https://github.com/apps/dependabot). +* 🔧 Ungroup dependabot updates. PR [#11465](https://github.com/tiangolo/fastapi/pull/11465) by [@tiangolo](https://github.com/tiangolo). + +## 0.110.2 (2024-04-19) + +### Fixes + +* 🐛 Fix support for query parameters with list types, handle JSON encoding Pydantic `UndefinedType`. PR [#9929](https://github.com/tiangolo/fastapi/pull/9929) by [@arjwilliams](https://github.com/arjwilliams). + +### Refactors + +* ♻️ Simplify Pydantic configs in OpenAPI models in `fastapi/openapi/models.py`. PR [#10886](https://github.com/tiangolo/fastapi/pull/10886) by [@JoeTanto2](https://github.com/JoeTanto2). +* ✨ Add support for Pydantic's 2.7 new deprecated Field parameter, remove URL from validation errors response. PR [#11461](https://github.com/tiangolo/fastapi/pull/11461) by [@tiangolo](https://github.com/tiangolo). + +### Docs + +* 📝 Fix types in examples under `docs_src/extra_data_types`. PR [#10535](https://github.com/tiangolo/fastapi/pull/10535) by [@nilslindemann](https://github.com/nilslindemann). +* 📝 Update references to UJSON. PR [#11464](https://github.com/tiangolo/fastapi/pull/11464) by [@tiangolo](https://github.com/tiangolo). +* 📝 Tweak docs and translations links, typos, format. PR [#11389](https://github.com/tiangolo/fastapi/pull/11389) by [@nilslindemann](https://github.com/nilslindemann). +* 📝 Fix typo in `docs/es/docs/async.md`. PR [#11400](https://github.com/tiangolo/fastapi/pull/11400) by [@fabianfalon](https://github.com/fabianfalon). +* 📝 Update OpenAPI client generation docs to use `@hey-api/openapi-ts`. PR [#11339](https://github.com/tiangolo/fastapi/pull/11339) by [@jordanshatford](https://github.com/jordanshatford). + +### Translations + +* 🌐 Update Chinese translation for `docs/zh/docs/index.html`. PR [#11430](https://github.com/tiangolo/fastapi/pull/11430) by [@waketzheng](https://github.com/waketzheng). +* 🌐 Add Russian translation for `docs/ru/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md`. PR [#11411](https://github.com/tiangolo/fastapi/pull/11411) by [@anton2yakovlev](https://github.com/anton2yakovlev). +* 🌐 Add Portuguese translations for `learn/index.md` `resources/index.md` `help/index.md` `about/index.md`. PR [#10807](https://github.com/tiangolo/fastapi/pull/10807) by [@nazarepiedady](https://github.com/nazarepiedady). +* 🌐 Update Russian translations for deployments docs. PR [#11271](https://github.com/tiangolo/fastapi/pull/11271) by [@Lufa1u](https://github.com/Lufa1u). +* 🌐 Add Bengali translations for `docs/bn/docs/python-types.md`. PR [#11376](https://github.com/tiangolo/fastapi/pull/11376) by [@imtiaz101325](https://github.com/imtiaz101325). +* 🌐 Add Korean translation for `docs/ko/docs/tutorial/security/simple-oauth2.md`. PR [#5744](https://github.com/tiangolo/fastapi/pull/5744) by [@KdHyeon0661](https://github.com/KdHyeon0661). +* 🌐 Add Korean translation for `docs/ko/docs/help-fastapi.md`. PR [#4139](https://github.com/tiangolo/fastapi/pull/4139) by [@kty4119](https://github.com/kty4119). +* 🌐 Add Korean translation for `docs/ko/docs/advanced/events.md`. PR [#5087](https://github.com/tiangolo/fastapi/pull/5087) by [@pers0n4](https://github.com/pers0n4). +* 🌐 Add Japanese translation for `docs/ja/docs/tutorial/path-operation-configuration.md`. PR [#1954](https://github.com/tiangolo/fastapi/pull/1954) by [@SwftAlpc](https://github.com/SwftAlpc). +* 🌐 Add Japanese translation for `docs/ja/docs/tutorial/request-forms-and-files.md`. PR [#1946](https://github.com/tiangolo/fastapi/pull/1946) by [@SwftAlpc](https://github.com/SwftAlpc). +* 🌐 Add Russian translation for `docs/ru/docs/tutorial/dependencies/dependencies-with-yield.md`. PR [#10532](https://github.com/tiangolo/fastapi/pull/10532) by [@AlertRED](https://github.com/AlertRED). +* 🌐 Add Korean translation for `docs/ko/docs/tutorial/debugging.md`. PR [#5695](https://github.com/tiangolo/fastapi/pull/5695) by [@JungWooGeon](https://github.com/JungWooGeon). + +### Internal + +* ⬆️ Upgrade version of typer for docs. PR [#11393](https://github.com/tiangolo/fastapi/pull/11393) by [@tiangolo](https://github.com/tiangolo). + +## 0.110.1 (2024-04-02) + +### Fixes + +* 🐛 Fix parameterless `Depends()` with generics. PR [#9479](https://github.com/tiangolo/fastapi/pull/9479) by [@nzig](https://github.com/nzig). + +### Refactors + +* ♻️ Update mypy. PR [#11049](https://github.com/tiangolo/fastapi/pull/11049) by [@k0t3n](https://github.com/k0t3n). +* ♻️ Simplify string format with f-strings in `fastapi/applications.py`. PR [#11335](https://github.com/tiangolo/fastapi/pull/11335) by [@igeni](https://github.com/igeni). + +### Upgrades + +* ⬆️ Upgrade Starlette to >=0.37.2,<0.38.0, remove Starlette filterwarning for internal tests. PR [#11266](https://github.com/tiangolo/fastapi/pull/11266) by [@nothielf](https://github.com/nothielf). + +### Docs + +* 📝 Tweak docs and translations links and remove old docs translations. PR [#11381](https://github.com/tiangolo/fastapi/pull/11381) by [@tiangolo](https://github.com/tiangolo). +* ✏️ Fix typo in `fastapi/security/oauth2.py`. PR [#11368](https://github.com/tiangolo/fastapi/pull/11368) by [@shandongbinzhou](https://github.com/shandongbinzhou). +* 📝 Update links to Pydantic docs to point to new website. PR [#11328](https://github.com/tiangolo/fastapi/pull/11328) by [@alejsdev](https://github.com/alejsdev). +* ✏️ Fix typo in `docs/en/docs/tutorial/extra-models.md`. PR [#11329](https://github.com/tiangolo/fastapi/pull/11329) by [@alejsdev](https://github.com/alejsdev). +* 📝 Update `project-generation.md`. PR [#11326](https://github.com/tiangolo/fastapi/pull/11326) by [@alejsdev](https://github.com/alejsdev). +* 📝 Update External Links. PR [#11327](https://github.com/tiangolo/fastapi/pull/11327) by [@alejsdev](https://github.com/alejsdev). +* 🔥 Remove link to Pydantic's benchmark, on other i18n pages.. PR [#11224](https://github.com/tiangolo/fastapi/pull/11224) by [@hirotoKirimaru](https://github.com/hirotoKirimaru). +* ✏️ Fix typos in docstrings. PR [#11295](https://github.com/tiangolo/fastapi/pull/11295) by [@davidhuser](https://github.com/davidhuser). +* 🛠️ Improve Node.js script in docs to generate TypeScript clients. PR [#11293](https://github.com/tiangolo/fastapi/pull/11293) by [@alejsdev](https://github.com/alejsdev). +* 📝 Update examples for tests to replace "inexistent" for "nonexistent". PR [#11220](https://github.com/tiangolo/fastapi/pull/11220) by [@Homesteady](https://github.com/Homesteady). +* 📝 Update `python-multipart` GitHub link in all docs from `https://andrew-d.github.io/python-multipart/` to `https://github.com/Kludex/python-multipart`. PR [#11239](https://github.com/tiangolo/fastapi/pull/11239) by [@joshjhans](https://github.com/joshjhans). + +### Translations + +* 🌐 Add German translation for `docs/de/docs/tutorial/response-status-code.md`. PR [#10357](https://github.com/tiangolo/fastapi/pull/10357) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Update Chinese translation for `docs/zh/docs/tutorial/query-params.md`. PR [#3480](https://github.com/tiangolo/fastapi/pull/3480) by [@jaystone776](https://github.com/jaystone776). +* 🌐 Update Chinese translation for `docs/zh/docs/tutorial/body.md`. PR [#3481](https://github.com/tiangolo/fastapi/pull/3481) by [@jaystone776](https://github.com/jaystone776). +* 🌐 Update Chinese translation for `docs/zh/docs/tutorial/path-params.md`. PR [#3479](https://github.com/tiangolo/fastapi/pull/3479) by [@jaystone776](https://github.com/jaystone776). +* 🌐 Update Chinese translation for `docs/tutorial/body-fields.md`. PR [#3496](https://github.com/tiangolo/fastapi/pull/3496) by [@jaystone776](https://github.com/jaystone776). +* 🌐 Update Chinese translation for `docs/tutorial/extra-models.md`. PR [#3497](https://github.com/tiangolo/fastapi/pull/3497) by [@jaystone776](https://github.com/jaystone776). +* 🌐 Add Japanese translation for `docs/ja/docs/tutorial/metadata.md`. PR [#2667](https://github.com/tiangolo/fastapi/pull/2667) by [@tokusumi](https://github.com/tokusumi). +* 🌐 Add German translation for `docs/de/docs/contributing.md`. PR [#10487](https://github.com/tiangolo/fastapi/pull/10487) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Update Japanese translation of `docs/ja/docs/tutorial/query-params.md`. PR [#10808](https://github.com/tiangolo/fastapi/pull/10808) by [@urushio](https://github.com/urushio). +* 🌐 Update Chinese translation for `docs/zh/docs/tutorial/security/get-current-user.md`. PR [#3842](https://github.com/tiangolo/fastapi/pull/3842) by [@jaystone776](https://github.com/jaystone776). +* 🌐 Add Chinese translation for `docs/zh/docs/advanced/openapi-callbacks.md`. PR [#3825](https://github.com/tiangolo/fastapi/pull/3825) by [@jaystone776](https://github.com/jaystone776). +* 🌐 Add Chinese translation for `docs/zh/docs/advanced/extending-openapi.md`. PR [#3823](https://github.com/tiangolo/fastapi/pull/3823) by [@jaystone776](https://github.com/jaystone776). +* 🌐 Add Chinese translation for `docs/zh/docs/advanced/testing-dependencies.md`. PR [#3819](https://github.com/tiangolo/fastapi/pull/3819) by [@jaystone776](https://github.com/jaystone776). +* 🌐 Add Chinese translation for `docs/zh/docs/advanced/custom-request-and-route.md`. PR [#3816](https://github.com/tiangolo/fastapi/pull/3816) by [@jaystone776](https://github.com/jaystone776). +* 🌐 Add Chinese translation for `docs/zh/docs/external-links.md`. PR [#3833](https://github.com/tiangolo/fastapi/pull/3833) by [@jaystone776](https://github.com/jaystone776). +* 🌐 Add Chinese translation for `docs/zh/docs/advanced/templates.md`. PR [#3812](https://github.com/tiangolo/fastapi/pull/3812) by [@jaystone776](https://github.com/jaystone776). +* 🌐 Add Chinese translation for `docs/zh/docs/advanced/sub-applications.md`. PR [#3811](https://github.com/tiangolo/fastapi/pull/3811) by [@jaystone776](https://github.com/jaystone776). +* 🌐 Add Chinese translation for `docs/zh/docs/advanced/async-sql-databases.md`. PR [#3805](https://github.com/tiangolo/fastapi/pull/3805) by [@jaystone776](https://github.com/jaystone776). +* 🌐 Add Chinese translation for `docs/zh/docs/advanced/middleware.md`. PR [#3804](https://github.com/tiangolo/fastapi/pull/3804) by [@jaystone776](https://github.com/jaystone776). +* 🌐 Add Chinese translation for `docs/zh/docs/advanced/dataclasses.md`. PR [#3803](https://github.com/tiangolo/fastapi/pull/3803) by [@jaystone776](https://github.com/jaystone776). +* 🌐 Add Chinese translation for `docs/zh/docs/advanced/using-request-directly.md`. PR [#3802](https://github.com/tiangolo/fastapi/pull/3802) by [@jaystone776](https://github.com/jaystone776). +* 🌐 Add Chinese translation for `docs/zh/docs/advanced/security/http-basic-auth.md`. PR [#3801](https://github.com/tiangolo/fastapi/pull/3801) by [@jaystone776](https://github.com/jaystone776). +* 🌐 Add Chinese translation for `docs/zh/docs/advanced/security/oauth2-scopes.md`. PR [#3800](https://github.com/tiangolo/fastapi/pull/3800) by [@jaystone776](https://github.com/jaystone776). +* 🌐 Update Chinese translation for `docs/zh/docs/tutorial/cookie-params.md`. PR [#3486](https://github.com/tiangolo/fastapi/pull/3486) by [@jaystone776](https://github.com/jaystone776). +* 🌐 Update Chinese translation for `docs/zh/docs/tutorial/header-params.md`. PR [#3487](https://github.com/tiangolo/fastapi/pull/3487) by [@jaystone776](https://github.com/jaystone776). +* 🌐 Update Chinese translation for `docs/tutorial/response-status-code.md`. PR [#3498](https://github.com/tiangolo/fastapi/pull/3498) by [@jaystone776](https://github.com/jaystone776). +* 🌐 Add German translation for `docs/de/docs/tutorial/security/first-steps.md`. PR [#10432](https://github.com/tiangolo/fastapi/pull/10432) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/advanced/events.md`. PR [#10693](https://github.com/tiangolo/fastapi/pull/10693) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/deployment/cloud.md`. PR [#10746](https://github.com/tiangolo/fastapi/pull/10746) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/advanced/behind-a-proxy.md`. PR [#10675](https://github.com/tiangolo/fastapi/pull/10675) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/help-fastapi.md`. PR [#10455](https://github.com/tiangolo/fastapi/pull/10455) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Update German translation for `docs/de/docs/python-types.md`. PR [#10287](https://github.com/tiangolo/fastapi/pull/10287) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/tutorial/path-params.md`. PR [#10290](https://github.com/tiangolo/fastapi/pull/10290) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/tutorial/handling-errors.md`. PR [#10379](https://github.com/tiangolo/fastapi/pull/10379) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Update German translation for `docs/de/docs/index.md`. PR [#10283](https://github.com/tiangolo/fastapi/pull/10283) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/advanced/security/http-basic-auth.md`. PR [#10651](https://github.com/tiangolo/fastapi/pull/10651) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/tutorial/bigger-applications.md`. PR [#10554](https://github.com/tiangolo/fastapi/pull/10554) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/advanced/path-operation-advanced-configuration.md`. PR [#10612](https://github.com/tiangolo/fastapi/pull/10612) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/tutorial/static-files.md`. PR [#10584](https://github.com/tiangolo/fastapi/pull/10584) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/tutorial/security/oauth2-jwt.md`. PR [#10522](https://github.com/tiangolo/fastapi/pull/10522) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/tutorial/response-model.md`. PR [#10345](https://github.com/tiangolo/fastapi/pull/10345) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/tutorial/extra-models.md`. PR [#10351](https://github.com/tiangolo/fastapi/pull/10351) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/tutorial/body-updates.md`. PR [#10396](https://github.com/tiangolo/fastapi/pull/10396) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/alternatives.md`. PR [#10855](https://github.com/tiangolo/fastapi/pull/10855) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/advanced/templates.md`. PR [#10678](https://github.com/tiangolo/fastapi/pull/10678) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/advanced/security/oauth2-scopes.md`. PR [#10643](https://github.com/tiangolo/fastapi/pull/10643) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/advanced/async-tests.md`. PR [#10708](https://github.com/tiangolo/fastapi/pull/10708) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/tutorial/metadata.md`. PR [#10581](https://github.com/tiangolo/fastapi/pull/10581) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/tutorial/testing.md`. PR [#10586](https://github.com/tiangolo/fastapi/pull/10586) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/tutorial/schema-extra-example.md`. PR [#10597](https://github.com/tiangolo/fastapi/pull/10597) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/advanced/index.md`. PR [#10611](https://github.com/tiangolo/fastapi/pull/10611) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/advanced/response-directly.md`. PR [#10618](https://github.com/tiangolo/fastapi/pull/10618) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/advanced/additional-responses.md`. PR [#10626](https://github.com/tiangolo/fastapi/pull/10626) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/advanced/response-cookies.md`. PR [#10627](https://github.com/tiangolo/fastapi/pull/10627) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/advanced/response-headers.md`. PR [#10628](https://github.com/tiangolo/fastapi/pull/10628) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/advanced/response-change-status-code.md`. PR [#10632](https://github.com/tiangolo/fastapi/pull/10632) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/advanced/advanced-dependencies.md`. PR [#10633](https://github.com/tiangolo/fastapi/pull/10633) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/advanced/security/index.md`. PR [#10635](https://github.com/tiangolo/fastapi/pull/10635) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/advanced/using-request-directly.md`. PR [#10653](https://github.com/tiangolo/fastapi/pull/10653) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/advanced/dataclasses.md`. PR [#10667](https://github.com/tiangolo/fastapi/pull/10667) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/advanced/middleware.md`. PR [#10668](https://github.com/tiangolo/fastapi/pull/10668) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/advanced/sub-applications.md`. PR [#10671](https://github.com/tiangolo/fastapi/pull/10671) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/advanced/websockets.md`. PR [#10687](https://github.com/tiangolo/fastapi/pull/10687) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/advanced/testing-websockets.md`. PR [#10703](https://github.com/tiangolo/fastapi/pull/10703) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/advanced/testing-events.md`. PR [#10704](https://github.com/tiangolo/fastapi/pull/10704) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/advanced/testing-dependencies.md`. PR [#10706](https://github.com/tiangolo/fastapi/pull/10706) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/advanced/openapi-callbacks.md`. PR [#10710](https://github.com/tiangolo/fastapi/pull/10710) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/advanced/settings.md`. PR [#10709](https://github.com/tiangolo/fastapi/pull/10709) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/advanced/wsgi.md`. PR [#10713](https://github.com/tiangolo/fastapi/pull/10713) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/deployment/index.md`. PR [#10733](https://github.com/tiangolo/fastapi/pull/10733) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/deployment/https.md`. PR [#10737](https://github.com/tiangolo/fastapi/pull/10737) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/deployment/manually.md`. PR [#10738](https://github.com/tiangolo/fastapi/pull/10738) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/deployment/concepts.md`. PR [#10744](https://github.com/tiangolo/fastapi/pull/10744) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Update German translation for `docs/de/docs/features.md`. PR [#10284](https://github.com/tiangolo/fastapi/pull/10284) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/deployment/server-workers.md`. PR [#10747](https://github.com/tiangolo/fastapi/pull/10747) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/deployment/docker.md`. PR [#10759](https://github.com/tiangolo/fastapi/pull/10759) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/how-to/index.md`. PR [#10769](https://github.com/tiangolo/fastapi/pull/10769) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/how-to/general.md`. PR [#10770](https://github.com/tiangolo/fastapi/pull/10770) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/how-to/graphql.md`. PR [#10788](https://github.com/tiangolo/fastapi/pull/10788) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/how-to/custom-request-and-route.md`. PR [#10789](https://github.com/tiangolo/fastapi/pull/10789) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/how-to/conditional-openapi.md`. PR [#10790](https://github.com/tiangolo/fastapi/pull/10790) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/how-to/separate-openapi-schemas.md`. PR [#10796](https://github.com/tiangolo/fastapi/pull/10796) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/how-to/configure-swagger-ui.md`. PR [#10804](https://github.com/tiangolo/fastapi/pull/10804) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/how-to/custom-docs-ui-assets.md`. PR [#10803](https://github.com/tiangolo/fastapi/pull/10803) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/reference/parameters.md`. PR [#10814](https://github.com/tiangolo/fastapi/pull/10814) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/reference/status.md`. PR [#10815](https://github.com/tiangolo/fastapi/pull/10815) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/reference/uploadfile.md`. PR [#10816](https://github.com/tiangolo/fastapi/pull/10816) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/reference/exceptions.md`. PR [#10817](https://github.com/tiangolo/fastapi/pull/10817) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/reference/dependencies.md`. PR [#10818](https://github.com/tiangolo/fastapi/pull/10818) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/reference/apirouter.md`. PR [#10819](https://github.com/tiangolo/fastapi/pull/10819) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/reference/websockets.md`. PR [#10822](https://github.com/tiangolo/fastapi/pull/10822) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/reference/httpconnection.md`. PR [#10823](https://github.com/tiangolo/fastapi/pull/10823) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/reference/response.md`. PR [#10824](https://github.com/tiangolo/fastapi/pull/10824) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/reference/middleware.md`. PR [#10837](https://github.com/tiangolo/fastapi/pull/10837) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/reference/openapi/*.md`. PR [#10838](https://github.com/tiangolo/fastapi/pull/10838) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/reference/security/index.md`. PR [#10839](https://github.com/tiangolo/fastapi/pull/10839) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/reference/staticfiles.md`. PR [#10841](https://github.com/tiangolo/fastapi/pull/10841) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/reference/testclient.md`. PR [#10843](https://github.com/tiangolo/fastapi/pull/10843) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/project-generation.md`. PR [#10851](https://github.com/tiangolo/fastapi/pull/10851) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/history-design-future.md`. PR [#10865](https://github.com/tiangolo/fastapi/pull/10865) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/tutorial/dependencies/dependencies-with-yield.md`. PR [#10422](https://github.com/tiangolo/fastapi/pull/10422) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/tutorial/dependencies/global-dependencies.md`. PR [#10420](https://github.com/tiangolo/fastapi/pull/10420) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Update German translation for `docs/de/docs/fastapi-people.md`. PR [#10285](https://github.com/tiangolo/fastapi/pull/10285) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/tutorial/dependencies/sub-dependencies.md`. PR [#10409](https://github.com/tiangolo/fastapi/pull/10409) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/tutorial/security/index.md`. PR [#10429](https://github.com/tiangolo/fastapi/pull/10429) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md`. PR [#10411](https://github.com/tiangolo/fastapi/pull/10411) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/tutorial/extra-data-types.md`. PR [#10534](https://github.com/tiangolo/fastapi/pull/10534) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/tutorial/security/simple-oauth2.md`. PR [#10504](https://github.com/tiangolo/fastapi/pull/10504) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/tutorial/security/get-current-user.md`. PR [#10439](https://github.com/tiangolo/fastapi/pull/10439) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/tutorial/request-forms-and-files.md`. PR [#10368](https://github.com/tiangolo/fastapi/pull/10368) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/tutorial/encoder.md`. PR [#10385](https://github.com/tiangolo/fastapi/pull/10385) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/tutorial/request-forms.md`. PR [#10361](https://github.com/tiangolo/fastapi/pull/10361) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/deployment/versions.md`. PR [#10491](https://github.com/tiangolo/fastapi/pull/10491) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/async.md`. PR [#10449](https://github.com/tiangolo/fastapi/pull/10449) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/tutorial/cookie-params.md`. PR [#10323](https://github.com/tiangolo/fastapi/pull/10323) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/tutorial/dependencies/classes-as-dependencies.md`. PR [#10407](https://github.com/tiangolo/fastapi/pull/10407) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/tutorial/dependencies/index.md`. PR [#10399](https://github.com/tiangolo/fastapi/pull/10399) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/tutorial/header-params.md`. PR [#10326](https://github.com/tiangolo/fastapi/pull/10326) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/tutorial/path-params-numeric-validations.md`. PR [#10307](https://github.com/tiangolo/fastapi/pull/10307) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/tutorial/query-params-str-validations.md`. PR [#10304](https://github.com/tiangolo/fastapi/pull/10304) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/tutorial/request-files.md`. PR [#10364](https://github.com/tiangolo/fastapi/pull/10364) by [@nilslindemann](https://github.com/nilslindemann). +* :globe_with_meridians: Add Portuguese translation for `docs/pt/docs/advanced/templates.md`. PR [#11338](https://github.com/tiangolo/fastapi/pull/11338) by [@SamuelBFavarin](https://github.com/SamuelBFavarin). +* 🌐 Add Bengali translations for `docs/bn/docs/learn/index.md`. PR [#11337](https://github.com/tiangolo/fastapi/pull/11337) by [@imtiaz101325](https://github.com/imtiaz101325). +* 🌐 Fix Korean translation for `docs/ko/docs/index.md`. PR [#11296](https://github.com/tiangolo/fastapi/pull/11296) by [@choi-haram](https://github.com/choi-haram). +* 🌐 Add Korean translation for `docs/ko/docs/about/index.md`. PR [#11299](https://github.com/tiangolo/fastapi/pull/11299) by [@choi-haram](https://github.com/choi-haram). +* 🌐 Add Korean translation for `docs/ko/docs/advanced/index.md`. PR [#9613](https://github.com/tiangolo/fastapi/pull/9613) by [@ElliottLarsen](https://github.com/ElliottLarsen). +* 🌐 Add German translation for `docs/de/docs/how-to/extending-openapi.md`. PR [#10794](https://github.com/tiangolo/fastapi/pull/10794) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Update Chinese translation for `docs/zh/docs/tutorial/metadata.md`. PR [#11286](https://github.com/tiangolo/fastapi/pull/11286) by [@jackleeio](https://github.com/jackleeio). +* 🌐 Update Chinese translation for `docs/zh/docs/contributing.md`. PR [#10887](https://github.com/tiangolo/fastapi/pull/10887) by [@Aruelius](https://github.com/Aruelius). +* 🌐 Add Azerbaijani translation for `docs/az/docs/fastapi-people.md`. PR [#11195](https://github.com/tiangolo/fastapi/pull/11195) by [@vusallyv](https://github.com/vusallyv). +* 🌐 Add Russian translation for `docs/ru/docs/tutorial/dependencies/index.md`. PR [#11223](https://github.com/tiangolo/fastapi/pull/11223) by [@kohiry](https://github.com/kohiry). +* 🌐 Update Chinese translation for `docs/zh/docs/tutorial/query-params.md`. PR [#11242](https://github.com/tiangolo/fastapi/pull/11242) by [@jackleeio](https://github.com/jackleeio). +* 🌐 Add Azerbaijani translation for `docs/az/learn/index.md`. PR [#11192](https://github.com/tiangolo/fastapi/pull/11192) by [@vusallyv](https://github.com/vusallyv). + +### Internal + +* 👥 Update FastAPI People. PR [#11387](https://github.com/tiangolo/fastapi/pull/11387) by [@tiangolo](https://github.com/tiangolo). +* ⬆ Bump actions/cache from 3 to 4. PR [#10988](https://github.com/tiangolo/fastapi/pull/10988) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump pypa/gh-action-pypi-publish from 1.8.11 to 1.8.14. PR [#11318](https://github.com/tiangolo/fastapi/pull/11318) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump pillow from 10.1.0 to 10.2.0. PR [#11011](https://github.com/tiangolo/fastapi/pull/11011) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump black from 23.3.0 to 24.3.0. PR [#11325](https://github.com/tiangolo/fastapi/pull/11325) by [@dependabot[bot]](https://github.com/apps/dependabot). +* 👷 Add cron to run test once a week on monday. PR [#11377](https://github.com/tiangolo/fastapi/pull/11377) by [@estebanx64](https://github.com/estebanx64). +* ➕ Replace mkdocs-markdownextradata-plugin with mkdocs-macros-plugin. PR [#11383](https://github.com/tiangolo/fastapi/pull/11383) by [@tiangolo](https://github.com/tiangolo). +* 👷 Disable MkDocs insiders social plugin while an issue in MkDocs Material is handled. PR [#11373](https://github.com/tiangolo/fastapi/pull/11373) by [@tiangolo](https://github.com/tiangolo). +* 👷 Fix logic for when to install and use MkDocs Insiders. PR [#11372](https://github.com/tiangolo/fastapi/pull/11372) by [@tiangolo](https://github.com/tiangolo). +* 👷 Do not use Python packages cache for publish. PR [#11366](https://github.com/tiangolo/fastapi/pull/11366) by [@tiangolo](https://github.com/tiangolo). +* 👷 Add CI to test sdists for redistribution (e.g. Linux distros). PR [#11365](https://github.com/tiangolo/fastapi/pull/11365) by [@tiangolo](https://github.com/tiangolo). +* 👷 Update build-docs GitHub Action path filter. PR [#11354](https://github.com/tiangolo/fastapi/pull/11354) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Update Ruff config, add extra ignore rule from SQLModel. PR [#11353](https://github.com/tiangolo/fastapi/pull/11353) by [@tiangolo](https://github.com/tiangolo). +* ⬆️ Upgrade configuration for Ruff v0.2.0. PR [#11075](https://github.com/tiangolo/fastapi/pull/11075) by [@charliermarsh](https://github.com/charliermarsh). +* 🔧 Update sponsors, add MongoDB. PR [#11346](https://github.com/tiangolo/fastapi/pull/11346) by [@tiangolo](https://github.com/tiangolo). +* ⬆ Bump dorny/paths-filter from 2 to 3. PR [#11028](https://github.com/tiangolo/fastapi/pull/11028) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump dawidd6/action-download-artifact from 3.0.0 to 3.1.4. PR [#11310](https://github.com/tiangolo/fastapi/pull/11310) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ♻️ Refactor computing FastAPI People, include 3 months, 6 months, 1 year, based on comment date, not discussion date. PR [#11304](https://github.com/tiangolo/fastapi/pull/11304) by [@tiangolo](https://github.com/tiangolo). +* 👥 Update FastAPI People. PR [#11228](https://github.com/tiangolo/fastapi/pull/11228) by [@tiangolo](https://github.com/tiangolo). +* 🔥 Remove Jina AI QA Bot from the docs. PR [#11268](https://github.com/tiangolo/fastapi/pull/11268) by [@nan-wang](https://github.com/nan-wang). +* 🔧 Update sponsors, remove Jina, remove Powens, move TestDriven.io. PR [#11213](https://github.com/tiangolo/fastapi/pull/11213) by [@tiangolo](https://github.com/tiangolo). + +## 0.110.0 (2024-02-24) + +### Breaking Changes + +* 🐛 Fix unhandled growing memory for internal server errors, refactor dependencies with `yield` and `except` to require raising again as in regular Python. PR [#11191](https://github.com/tiangolo/fastapi/pull/11191) by [@tiangolo](https://github.com/tiangolo). + * This is a breaking change (and only slightly) if you used dependencies with `yield`, used `except` in those dependencies, and didn't raise again. + * This was reported internally by [@rushilsrivastava](https://github.com/rushilsrivastava) as a memory leak when the server had unhandled exceptions that would produce internal server errors, the memory allocated before that point would not be released. + * Read the new docs: [Dependencies with `yield` and `except`](https://fastapi.tiangolo.com/tutorial/dependencies/dependencies-with-yield/#dependencies-with-yield-and-except). + +In short, if you had dependencies that looked like: + +```Python +def my_dep(): + try: + yield + except SomeException: + pass +``` + +Now you need to make sure you raise again after `except`, just as you would in regular Python: + +```Python +def my_dep(): + try: + yield + except SomeException: + raise +``` + +### Docs + +* ✏️ Fix minor typos in `docs/ko/docs/`. PR [#11126](https://github.com/tiangolo/fastapi/pull/11126) by [@KaniKim](https://github.com/KaniKim). +* ✏️ Fix minor typo in `fastapi/applications.py`. PR [#11099](https://github.com/tiangolo/fastapi/pull/11099) by [@JacobHayes](https://github.com/JacobHayes). + +### Translations + +* 🌐 Add German translation for `docs/de/docs/reference/background.md`. PR [#10820](https://github.com/tiangolo/fastapi/pull/10820) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/reference/templating.md`. PR [#10842](https://github.com/tiangolo/fastapi/pull/10842) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/external-links.md`. PR [#10852](https://github.com/tiangolo/fastapi/pull/10852) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Update Turkish translation for `docs/tr/docs/tutorial/query-params.md`. PR [#11162](https://github.com/tiangolo/fastapi/pull/11162) by [@hasansezertasan](https://github.com/hasansezertasan). +* 🌐 Add German translation for `docs/de/docs/reference/encoders.md`. PR [#10840](https://github.com/tiangolo/fastapi/pull/10840) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/reference/responses.md`. PR [#10825](https://github.com/tiangolo/fastapi/pull/10825) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/reference/request.md`. PR [#10821](https://github.com/tiangolo/fastapi/pull/10821) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add Turkish translation for `docs/tr/docs/tutorial/query-params.md`. PR [#11078](https://github.com/tiangolo/fastapi/pull/11078) by [@emrhnsyts](https://github.com/emrhnsyts). +* 🌐 Add German translation for `docs/de/docs/reference/fastapi.md`. PR [#10813](https://github.com/tiangolo/fastapi/pull/10813) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/newsletter.md`. PR [#10853](https://github.com/tiangolo/fastapi/pull/10853) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add Traditional Chinese translation for `docs/zh-hant/docs/learn/index.md`. PR [#11142](https://github.com/tiangolo/fastapi/pull/11142) by [@hsuanchi](https://github.com/hsuanchi). +* 🌐 Add Korean translation for `/docs/ko/docs/tutorial/dependencies/global-dependencies.md`. PR [#11123](https://github.com/tiangolo/fastapi/pull/11123) by [@riroan](https://github.com/riroan). +* 🌐 Add Korean translation for `/docs/ko/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md`. PR [#11124](https://github.com/tiangolo/fastapi/pull/11124) by [@riroan](https://github.com/riroan). +* 🌐 Add Korean translation for `/docs/ko/docs/tutorial/schema-extra-example.md`. PR [#11121](https://github.com/tiangolo/fastapi/pull/11121) by [@KaniKim](https://github.com/KaniKim). +* 🌐 Add Korean translation for `/docs/ko/docs/tutorial/body-fields.md`. PR [#11112](https://github.com/tiangolo/fastapi/pull/11112) by [@KaniKim](https://github.com/KaniKim). +* 🌐 Add Korean translation for `/docs/ko/docs/tutorial/cookie-params.md`. PR [#11118](https://github.com/tiangolo/fastapi/pull/11118) by [@riroan](https://github.com/riroan). +* 🌐 Update Korean translation for `/docs/ko/docs/dependencies/index.md`. PR [#11114](https://github.com/tiangolo/fastapi/pull/11114) by [@KaniKim](https://github.com/KaniKim). +* 🌐 Update Korean translation for `/docs/ko/docs/deployment/docker.md`. PR [#11113](https://github.com/tiangolo/fastapi/pull/11113) by [@KaniKim](https://github.com/KaniKim). +* 🌐 Update Turkish translation for `docs/tr/docs/tutorial/first-steps.md`. PR [#11094](https://github.com/tiangolo/fastapi/pull/11094) by [@hasansezertasan](https://github.com/hasansezertasan). +* 🌐 Add Spanish translation for `docs/es/docs/advanced/security/index.md`. PR [#2278](https://github.com/tiangolo/fastapi/pull/2278) by [@Xaraxx](https://github.com/Xaraxx). +* 🌐 Add Spanish translation for `docs/es/docs/advanced/response-headers.md`. PR [#2276](https://github.com/tiangolo/fastapi/pull/2276) by [@Xaraxx](https://github.com/Xaraxx). +* 🌐 Add Spanish translation for `docs/es/docs/deployment/index.md` and `~/deployment/versions.md`. PR [#9669](https://github.com/tiangolo/fastapi/pull/9669) by [@pabloperezmoya](https://github.com/pabloperezmoya). +* 🌐 Add Spanish translation for `docs/es/docs/benchmarks.md`. PR [#10928](https://github.com/tiangolo/fastapi/pull/10928) by [@pablocm83](https://github.com/pablocm83). +* 🌐 Add Spanish translation for `docs/es/docs/advanced/response-change-status-code.md`. PR [#11100](https://github.com/tiangolo/fastapi/pull/11100) by [@alejsdev](https://github.com/alejsdev). + +## 0.109.2 (2024-02-04) + +### Upgrades + +* ⬆️ Upgrade version of Starlette to `>= 0.36.3`. PR [#11086](https://github.com/tiangolo/fastapi/pull/11086) by [@tiangolo](https://github.com/tiangolo). + +### Translations + +* 🌐 Update Turkish translation for `docs/tr/docs/fastapi-people.md`. PR [#10547](https://github.com/tiangolo/fastapi/pull/10547) by [@alperiox](https://github.com/alperiox). + +### Internal + +* 🍱 Add new FastAPI logo. PR [#11090](https://github.com/tiangolo/fastapi/pull/11090) by [@tiangolo](https://github.com/tiangolo). + +## 0.109.1 (2024-02-03) + +### Security fixes + +* ⬆️ Upgrade minimum version of `python-multipart` to `>=0.0.7` to fix a vulnerability when using form data with a ReDoS attack. You can also simply upgrade `python-multipart`. + +Read more in the [advisory: Content-Type Header ReDoS](https://github.com/tiangolo/fastapi/security/advisories/GHSA-qf9m-vfgh-m389). + +### Features + +* ✨ Include HTTP 205 in status codes with no body. PR [#10969](https://github.com/tiangolo/fastapi/pull/10969) by [@tiangolo](https://github.com/tiangolo). + +### Refactors + +* ✅ Refactor tests for duplicate operation ID generation for compatibility with other tools running the FastAPI test suite. PR [#10876](https://github.com/tiangolo/fastapi/pull/10876) by [@emmettbutler](https://github.com/emmettbutler). +* ♻️ Simplify string format with f-strings in `fastapi/utils.py`. PR [#10576](https://github.com/tiangolo/fastapi/pull/10576) by [@eukub](https://github.com/eukub). +* 🔧 Fix Ruff configuration unintentionally enabling and re-disabling mccabe complexity check. PR [#10893](https://github.com/tiangolo/fastapi/pull/10893) by [@jiridanek](https://github.com/jiridanek). +* ✅ Re-enable test in `tests/test_tutorial/test_header_params/test_tutorial003.py` after fix in Starlette. PR [#10904](https://github.com/tiangolo/fastapi/pull/10904) by [@ooknimm](https://github.com/ooknimm). + +### Docs + +* 📝 Tweak wording in `help-fastapi.md`. PR [#11040](https://github.com/tiangolo/fastapi/pull/11040) by [@tiangolo](https://github.com/tiangolo). +* 📝 Tweak docs for Behind a Proxy. PR [#11038](https://github.com/tiangolo/fastapi/pull/11038) by [@tiangolo](https://github.com/tiangolo). +* 📝 Add External Link: 10 Tips for adding SQLAlchemy to FastAPI. PR [#11036](https://github.com/tiangolo/fastapi/pull/11036) by [@Donnype](https://github.com/Donnype). +* 📝 Add External Link: Tips on migrating from Flask to FastAPI and vice-versa. PR [#11029](https://github.com/tiangolo/fastapi/pull/11029) by [@jtemporal](https://github.com/jtemporal). +* 📝 Deprecate old tutorials: Peewee, Couchbase, encode/databases. PR [#10979](https://github.com/tiangolo/fastapi/pull/10979) by [@tiangolo](https://github.com/tiangolo). +* ✏️ Fix typo in `fastapi/security/oauth2.py`. PR [#10972](https://github.com/tiangolo/fastapi/pull/10972) by [@RafalSkolasinski](https://github.com/RafalSkolasinski). +* 📝 Update `HTTPException` details in `docs/en/docs/tutorial/handling-errors.md`. PR [#5418](https://github.com/tiangolo/fastapi/pull/5418) by [@papb](https://github.com/papb). +* ✏️ A few tweaks in `docs/de/docs/tutorial/first-steps.md`. PR [#10959](https://github.com/tiangolo/fastapi/pull/10959) by [@nilslindemann](https://github.com/nilslindemann). +* ✏️ Fix link in `docs/en/docs/advanced/async-tests.md`. PR [#10960](https://github.com/tiangolo/fastapi/pull/10960) by [@nilslindemann](https://github.com/nilslindemann). +* ✏️ Fix typos for Spanish documentation. PR [#10957](https://github.com/tiangolo/fastapi/pull/10957) by [@jlopezlira](https://github.com/jlopezlira). +* 📝 Add warning about lifespan functions and backwards compatibility with events. PR [#10734](https://github.com/tiangolo/fastapi/pull/10734) by [@jacob-indigo](https://github.com/jacob-indigo). +* ✏️ Fix broken link in `docs/tutorial/sql-databases.md` in several languages. PR [#10716](https://github.com/tiangolo/fastapi/pull/10716) by [@theoohoho](https://github.com/theoohoho). +* ✏️ Remove broken links from `external_links.yml`. PR [#10943](https://github.com/tiangolo/fastapi/pull/10943) by [@Torabek](https://github.com/Torabek). +* 📝 Update template docs with more info about `url_for`. PR [#5937](https://github.com/tiangolo/fastapi/pull/5937) by [@EzzEddin](https://github.com/EzzEddin). +* 📝 Update usage of Token model in security docs. PR [#9313](https://github.com/tiangolo/fastapi/pull/9313) by [@piotrszacilowski](https://github.com/piotrszacilowski). +* ✏️ Update highlighted line in `docs/en/docs/tutorial/bigger-applications.md`. PR [#5490](https://github.com/tiangolo/fastapi/pull/5490) by [@papb](https://github.com/papb). +* 📝 Add External Link: Explore How to Effectively Use JWT With FastAPI. PR [#10212](https://github.com/tiangolo/fastapi/pull/10212) by [@aanchlia](https://github.com/aanchlia). +* 📝 Add hyperlink to `docs/en/docs/tutorial/static-files.md`. PR [#10243](https://github.com/tiangolo/fastapi/pull/10243) by [@hungtsetse](https://github.com/hungtsetse). +* 📝 Add External Link: Instrument a FastAPI service adding tracing with OpenTelemetry and send/show traces in Grafana Tempo. PR [#9440](https://github.com/tiangolo/fastapi/pull/9440) by [@softwarebloat](https://github.com/softwarebloat). +* 📝 Review and rewording of `en/docs/contributing.md`. PR [#10480](https://github.com/tiangolo/fastapi/pull/10480) by [@nilslindemann](https://github.com/nilslindemann). +* 📝 Add External Link: ML serving and monitoring with FastAPI and Evidently. PR [#9701](https://github.com/tiangolo/fastapi/pull/9701) by [@mnrozhkov](https://github.com/mnrozhkov). +* 📝 Reword in docs, from "have in mind" to "keep in mind". PR [#10376](https://github.com/tiangolo/fastapi/pull/10376) by [@malicious](https://github.com/malicious). +* 📝 Add External Link: Talk by Jeny Sadadia. PR [#10265](https://github.com/tiangolo/fastapi/pull/10265) by [@JenySadadia](https://github.com/JenySadadia). +* 📝 Add location info to `tutorial/bigger-applications.md`. PR [#10552](https://github.com/tiangolo/fastapi/pull/10552) by [@nilslindemann](https://github.com/nilslindemann). +* ✏️ Fix Pydantic method name in `docs/en/docs/advanced/path-operation-advanced-configuration.md`. PR [#10826](https://github.com/tiangolo/fastapi/pull/10826) by [@ahmedabdou14](https://github.com/ahmedabdou14). + +### Translations + +* 🌐 Add Spanish translation for `docs/es/docs/external-links.md`. PR [#10933](https://github.com/tiangolo/fastapi/pull/10933) by [@pablocm83](https://github.com/pablocm83). +* 🌐 Update Korean translation for `docs/ko/docs/tutorial/first-steps.md`, `docs/ko/docs/tutorial/index.md`, `docs/ko/docs/tutorial/path-params.md`, and `docs/ko/docs/tutorial/query-params.md`. PR [#4218](https://github.com/tiangolo/fastapi/pull/4218) by [@SnowSuno](https://github.com/SnowSuno). +* 🌐 Add Chinese translation for `docs/zh/docs/tutorial/dependencies/dependencies-with-yield.md`. PR [#10870](https://github.com/tiangolo/fastapi/pull/10870) by [@zhiquanchi](https://github.com/zhiquanchi). +* 🌐 Add Chinese translation for `docs/zh/docs/deployment/concepts.md`. PR [#10282](https://github.com/tiangolo/fastapi/pull/10282) by [@xzmeng](https://github.com/xzmeng). +* 🌐 Add Azerbaijani translation for `docs/az/docs/index.md`. PR [#11047](https://github.com/tiangolo/fastapi/pull/11047) by [@aykhans](https://github.com/aykhans). +* 🌐 Add Korean translation for `docs/ko/docs/tutorial/middleware.md`. PR [#2829](https://github.com/tiangolo/fastapi/pull/2829) by [@JeongHyeongKim](https://github.com/JeongHyeongKim). +* 🌐 Add German translation for `docs/de/docs/tutorial/body-nested-models.md`. PR [#10313](https://github.com/tiangolo/fastapi/pull/10313) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add Persian translation for `docs/fa/docs/tutorial/middleware.md`. PR [#9695](https://github.com/tiangolo/fastapi/pull/9695) by [@mojtabapaso](https://github.com/mojtabapaso). +* 🌐 Update Farsi translation for `docs/fa/docs/index.md`. PR [#10216](https://github.com/tiangolo/fastapi/pull/10216) by [@theonlykingpin](https://github.com/theonlykingpin). +* 🌐 Add German translation for `docs/de/docs/tutorial/body-fields.md`. PR [#10310](https://github.com/tiangolo/fastapi/pull/10310) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/tutorial/body.md`. PR [#10295](https://github.com/tiangolo/fastapi/pull/10295) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/tutorial/body-multiple-params.md`. PR [#10308](https://github.com/tiangolo/fastapi/pull/10308) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add Japanese translation for `docs/ja/docs/tutorial/security/get-current-user.md`. PR [#2681](https://github.com/tiangolo/fastapi/pull/2681) by [@sh0nk](https://github.com/sh0nk). +* 🌐 Add Chinese translation for `docs/zh/docs/advanced/advanced-dependencies.md`. PR [#3798](https://github.com/tiangolo/fastapi/pull/3798) by [@jaystone776](https://github.com/jaystone776). +* 🌐 Add Chinese translation for `docs/zh/docs/advanced/events.md`. PR [#3815](https://github.com/tiangolo/fastapi/pull/3815) by [@jaystone776](https://github.com/jaystone776). +* 🌐 Add Chinese translation for `docs/zh/docs/advanced/behind-a-proxy.md`. PR [#3820](https://github.com/tiangolo/fastapi/pull/3820) by [@jaystone776](https://github.com/jaystone776). +* 🌐 Add Chinese translation for `docs/zh/docs/advanced/testing-events.md`. PR [#3818](https://github.com/tiangolo/fastapi/pull/3818) by [@jaystone776](https://github.com/jaystone776). +* 🌐 Add Chinese translation for `docs/zh/docs/advanced/testing-websockets.md`. PR [#3817](https://github.com/tiangolo/fastapi/pull/3817) by [@jaystone776](https://github.com/jaystone776). +* 🌐 Add Chinese translation for `docs/zh/docs/advanced/testing-database.md`. PR [#3821](https://github.com/tiangolo/fastapi/pull/3821) by [@jaystone776](https://github.com/jaystone776). +* 🌐 Add Chinese translation for `docs/zh/docs/deployment/deta.md`. PR [#3837](https://github.com/tiangolo/fastapi/pull/3837) by [@jaystone776](https://github.com/jaystone776). +* 🌐 Add Chinese translation for `docs/zh/docs/history-design-future.md`. PR [#3832](https://github.com/tiangolo/fastapi/pull/3832) by [@jaystone776](https://github.com/jaystone776). +* 🌐 Add Chinese translation for `docs/zh/docs/project-generation.md`. PR [#3831](https://github.com/tiangolo/fastapi/pull/3831) by [@jaystone776](https://github.com/jaystone776). +* 🌐 Add Chinese translation for `docs/zh/docs/deployment/docker.md`. PR [#10296](https://github.com/tiangolo/fastapi/pull/10296) by [@xzmeng](https://github.com/xzmeng). +* 🌐 Update Spanish translation for `docs/es/docs/features.md`. PR [#10884](https://github.com/tiangolo/fastapi/pull/10884) by [@pablocm83](https://github.com/pablocm83). +* 🌐 Add Spanish translation for `docs/es/docs/newsletter.md`. PR [#10922](https://github.com/tiangolo/fastapi/pull/10922) by [@pablocm83](https://github.com/pablocm83). +* 🌐 Add Korean translation for `docs/ko/docs/tutorial/background-tasks.md`. PR [#5910](https://github.com/tiangolo/fastapi/pull/5910) by [@junah201](https://github.com/junah201). +* :globe_with_meridians: Add Turkish translation for `docs/tr/docs/alternatives.md`. PR [#10502](https://github.com/tiangolo/fastapi/pull/10502) by [@alperiox](https://github.com/alperiox). +* 🌐 Add Korean translation for `docs/ko/docs/tutorial/dependencies/index.md`. PR [#10989](https://github.com/tiangolo/fastapi/pull/10989) by [@KaniKim](https://github.com/KaniKim). +* 🌐 Add Korean translation for `/docs/ko/docs/tutorial/body.md`. PR [#11000](https://github.com/tiangolo/fastapi/pull/11000) by [@KaniKim](https://github.com/KaniKim). +* 🌐 Add Portuguese translation for `docs/pt/docs/tutorial/schema-extra-example.md`. PR [#4065](https://github.com/tiangolo/fastapi/pull/4065) by [@luccasmmg](https://github.com/luccasmmg). +* 🌐 Add Turkish translation for `docs/tr/docs/history-design-future.md`. PR [#11012](https://github.com/tiangolo/fastapi/pull/11012) by [@hasansezertasan](https://github.com/hasansezertasan). +* 🌐 Add Turkish translation for `docs/tr/docs/resources/index.md`. PR [#11020](https://github.com/tiangolo/fastapi/pull/11020) by [@hasansezertasan](https://github.com/hasansezertasan). +* 🌐 Add Turkish translation for `docs/tr/docs/how-to/index.md`. PR [#11021](https://github.com/tiangolo/fastapi/pull/11021) by [@hasansezertasan](https://github.com/hasansezertasan). +* 🌐 Add German translation for `docs/de/docs/tutorial/query-params.md`. PR [#10293](https://github.com/tiangolo/fastapi/pull/10293) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/benchmarks.md`. PR [#10866](https://github.com/tiangolo/fastapi/pull/10866) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add Turkish translation for `docs/tr/docs/learn/index.md`. PR [#11014](https://github.com/tiangolo/fastapi/pull/11014) by [@hasansezertasan](https://github.com/hasansezertasan). +* 🌐 Add Persian translation for `docs/fa/docs/tutorial/security/index.md`. PR [#9945](https://github.com/tiangolo/fastapi/pull/9945) by [@mojtabapaso](https://github.com/mojtabapaso). +* 🌐 Add Turkish translation for `docs/tr/docs/help/index.md`. PR [#11013](https://github.com/tiangolo/fastapi/pull/11013) by [@hasansezertasan](https://github.com/hasansezertasan). +* 🌐 Add Turkish translation for `docs/tr/docs/about/index.md`. PR [#11006](https://github.com/tiangolo/fastapi/pull/11006) by [@hasansezertasan](https://github.com/hasansezertasan). +* 🌐 Update Turkish translation for `docs/tr/docs/benchmarks.md`. PR [#11005](https://github.com/tiangolo/fastapi/pull/11005) by [@hasansezertasan](https://github.com/hasansezertasan). +* 🌐 Add Italian translation for `docs/it/docs/index.md`. PR [#5233](https://github.com/tiangolo/fastapi/pull/5233) by [@matteospanio](https://github.com/matteospanio). +* 🌐 Add Korean translation for `docs/ko/docs/help/index.md`. PR [#10983](https://github.com/tiangolo/fastapi/pull/10983) by [@KaniKim](https://github.com/KaniKim). +* 🌐 Add Korean translation for `docs/ko/docs/features.md`. PR [#10976](https://github.com/tiangolo/fastapi/pull/10976) by [@KaniKim](https://github.com/KaniKim). +* 🌐 Add Korean translation for `docs/ko/docs/tutorial/security/get-current-user.md`. PR [#5737](https://github.com/tiangolo/fastapi/pull/5737) by [@KdHyeon0661](https://github.com/KdHyeon0661). +* 🌐 Add Russian translation for `docs/ru/docs/tutorial/security/first-steps.md`. PR [#10541](https://github.com/tiangolo/fastapi/pull/10541) by [@AlertRED](https://github.com/AlertRED). +* 🌐 Add Russian translation for `docs/ru/docs/tutorial/handling-errors.md`. PR [#10375](https://github.com/tiangolo/fastapi/pull/10375) by [@AlertRED](https://github.com/AlertRED). +* 🌐 Add Russian translation for `docs/ru/docs/tutorial/encoder.md`. PR [#10374](https://github.com/tiangolo/fastapi/pull/10374) by [@AlertRED](https://github.com/AlertRED). +* 🌐 Add Russian translation for `docs/ru/docs/tutorial/body-updates.md`. PR [#10373](https://github.com/tiangolo/fastapi/pull/10373) by [@AlertRED](https://github.com/AlertRED). +* 🌐 Russian translation: updated `fastapi-people.md`.. PR [#10255](https://github.com/tiangolo/fastapi/pull/10255) by [@NiKuma0](https://github.com/NiKuma0). +* 🌐 Add Japanese translation for `docs/ja/docs/tutorial/security/index.md`. PR [#5798](https://github.com/tiangolo/fastapi/pull/5798) by [@3w36zj6](https://github.com/3w36zj6). +* 🌐 Add German translation for `docs/de/docs/advanced/generate-clients.md`. PR [#10725](https://github.com/tiangolo/fastapi/pull/10725) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/advanced/openapi-webhooks.md`. PR [#10712](https://github.com/tiangolo/fastapi/pull/10712) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/advanced/custom-response.md`. PR [#10624](https://github.com/tiangolo/fastapi/pull/10624) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/advanced/additional-status-codes.md`. PR [#10617](https://github.com/tiangolo/fastapi/pull/10617) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add German translation for `docs/de/docs/tutorial/middleware.md`. PR [#10391](https://github.com/tiangolo/fastapi/pull/10391) by [@JohannesJungbluth](https://github.com/JohannesJungbluth). +* 🌐 Add German translation for introduction documents. PR [#10497](https://github.com/tiangolo/fastapi/pull/10497) by [@nilslindemann](https://github.com/nilslindemann). +* 🌐 Add Japanese translation for `docs/ja/docs/tutorial/encoder.md`. PR [#1955](https://github.com/tiangolo/fastapi/pull/1955) by [@SwftAlpc](https://github.com/SwftAlpc). +* 🌐 Add Japanese translation for `docs/ja/docs/tutorial/extra-data-types.md`. PR [#1932](https://github.com/tiangolo/fastapi/pull/1932) by [@SwftAlpc](https://github.com/SwftAlpc). +* 🌐 Add Turkish translation for `docs/tr/docs/async.md`. PR [#5191](https://github.com/tiangolo/fastapi/pull/5191) by [@BilalAlpaslan](https://github.com/BilalAlpaslan). +* 🌐 Add Turkish translation for `docs/tr/docs/project-generation.md`. PR [#5192](https://github.com/tiangolo/fastapi/pull/5192) by [@BilalAlpaslan](https://github.com/BilalAlpaslan). +* 🌐 Add Korean translation for `docs/ko/docs/deployment/docker.md`. PR [#5657](https://github.com/tiangolo/fastapi/pull/5657) by [@nearnear](https://github.com/nearnear). +* 🌐 Add Korean translation for `docs/ko/docs/deployment/server-workers.md`. PR [#4935](https://github.com/tiangolo/fastapi/pull/4935) by [@jujumilk3](https://github.com/jujumilk3). +* 🌐 Add Korean translation for `docs/ko/docs/deployment/index.md`. PR [#4561](https://github.com/tiangolo/fastapi/pull/4561) by [@jujumilk3](https://github.com/jujumilk3). +* 🌐 Add Korean translation for `docs/ko/docs/tutorial/path-operation-configuration.md`. PR [#3639](https://github.com/tiangolo/fastapi/pull/3639) by [@jungsu-kwon](https://github.com/jungsu-kwon). +* 🌐 Modify the description of `zh` - Traditional Chinese. PR [#10889](https://github.com/tiangolo/fastapi/pull/10889) by [@cherinyy](https://github.com/cherinyy). +* 🌐 Add Korean translation for `docs/ko/docs/tutorial/static-files.md`. PR [#2957](https://github.com/tiangolo/fastapi/pull/2957) by [@jeesang7](https://github.com/jeesang7). +* 🌐 Add Korean translation for `docs/ko/docs/tutorial/response-model.md`. PR [#2766](https://github.com/tiangolo/fastapi/pull/2766) by [@hard-coders](https://github.com/hard-coders). +* 🌐 Add Korean translation for `docs/ko/docs/tutorial/body-multiple-params.md`. PR [#2461](https://github.com/tiangolo/fastapi/pull/2461) by [@PandaHun](https://github.com/PandaHun). +* 🌐 Add Korean translation for `docs/ko/docs/tutorial/query-params-str-validations.md`. PR [#2415](https://github.com/tiangolo/fastapi/pull/2415) by [@hard-coders](https://github.com/hard-coders). +* 🌐 Add Korean translation for `docs/ko/docs/python-types.md`. PR [#2267](https://github.com/tiangolo/fastapi/pull/2267) by [@jrim](https://github.com/jrim). +* 🌐 Add Korean translation for `docs/ko/docs/tutorial/body-nested-models.md`. PR [#2506](https://github.com/tiangolo/fastapi/pull/2506) by [@hard-coders](https://github.com/hard-coders). +* 🌐 Add Korean translation for `docs/ko/docs/learn/index.md`. PR [#10977](https://github.com/tiangolo/fastapi/pull/10977) by [@KaniKim](https://github.com/KaniKim). +* 🌐 Initialize translations for Traditional Chinese. PR [#10505](https://github.com/tiangolo/fastapi/pull/10505) by [@hsuanchi](https://github.com/hsuanchi). +* ✏️ Tweak the german translation of `docs/de/docs/tutorial/index.md`. PR [#10962](https://github.com/tiangolo/fastapi/pull/10962) by [@nilslindemann](https://github.com/nilslindemann). +* ✏️ Fix typo error in `docs/ko/docs/tutorial/path-params.md`. PR [#10758](https://github.com/tiangolo/fastapi/pull/10758) by [@2chanhaeng](https://github.com/2chanhaeng). +* 🌐 Add Japanese translation for `docs/ja/docs/tutorial/dependencies/dependencies-with-yield.md`. PR [#1961](https://github.com/tiangolo/fastapi/pull/1961) by [@SwftAlpc](https://github.com/SwftAlpc). +* 🌐 Add Japanese translation for `docs/ja/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md`. PR [#1960](https://github.com/tiangolo/fastapi/pull/1960) by [@SwftAlpc](https://github.com/SwftAlpc). +* 🌐 Add Japanese translation for `docs/ja/docs/tutorial/dependencies/sub-dependencies.md`. PR [#1959](https://github.com/tiangolo/fastapi/pull/1959) by [@SwftAlpc](https://github.com/SwftAlpc). +* 🌐 Add Japanese translation for `docs/ja/docs/tutorial/background-tasks.md`. PR [#2668](https://github.com/tiangolo/fastapi/pull/2668) by [@tokusumi](https://github.com/tokusumi). +* 🌐 Add Japanese translation for `docs/ja/docs/tutorial/dependencies/index.md` and `docs/ja/docs/tutorial/dependencies/classes-as-dependencies.md`. PR [#1958](https://github.com/tiangolo/fastapi/pull/1958) by [@SwftAlpc](https://github.com/SwftAlpc). +* 🌐 Add Japanese translation for `docs/ja/docs/tutorial/response-model.md`. PR [#1938](https://github.com/tiangolo/fastapi/pull/1938) by [@SwftAlpc](https://github.com/SwftAlpc). +* 🌐 Add Japanese translation for `docs/ja/docs/tutorial/body-multiple-params.md`. PR [#1903](https://github.com/tiangolo/fastapi/pull/1903) by [@SwftAlpc](https://github.com/SwftAlpc). +* 🌐 Add Japanese translation for `docs/ja/docs/tutorial/path-params-numeric-validations.md`. PR [#1902](https://github.com/tiangolo/fastapi/pull/1902) by [@SwftAlpc](https://github.com/SwftAlpc). +* 🌐 Add Japanese translation for `docs/ja/docs/python-types.md`. PR [#1899](https://github.com/tiangolo/fastapi/pull/1899) by [@SwftAlpc](https://github.com/SwftAlpc). +* 🌐 Add Japanese translation for `docs/ja/docs/tutorial/handling-errors.md`. PR [#1953](https://github.com/tiangolo/fastapi/pull/1953) by [@SwftAlpc](https://github.com/SwftAlpc). +* 🌐 Add Japanese translation for `docs/ja/docs/tutorial/response-status-code.md`. PR [#1942](https://github.com/tiangolo/fastapi/pull/1942) by [@SwftAlpc](https://github.com/SwftAlpc). +* 🌐 Add Japanese translation for `docs/ja/docs/tutorial/extra-models.md`. PR [#1941](https://github.com/tiangolo/fastapi/pull/1941) by [@SwftAlpc](https://github.com/SwftAlpc). +* 🌐 Add Japanese translation for `docs/ja/docs/tutorial/schema-extra-example.md`. PR [#1931](https://github.com/tiangolo/fastapi/pull/1931) by [@SwftAlpc](https://github.com/SwftAlpc). +* 🌐 Add Japanese translation for `docs/ja/docs/tutorial/body-nested-models.md`. PR [#1930](https://github.com/tiangolo/fastapi/pull/1930) by [@SwftAlpc](https://github.com/SwftAlpc). +* 🌐 Add Japanese translation for `docs/ja/docs/tutorial/body-fields.md`. PR [#1923](https://github.com/tiangolo/fastapi/pull/1923) by [@SwftAlpc](https://github.com/SwftAlpc). +* 🌐 Add German translation for `docs/de/docs/tutorial/index.md`. PR [#9502](https://github.com/tiangolo/fastapi/pull/9502) by [@fhabers21](https://github.com/fhabers21). +* 🌐 Add German translation for `docs/de/docs/tutorial/background-tasks.md`. PR [#10566](https://github.com/tiangolo/fastapi/pull/10566) by [@nilslindemann](https://github.com/nilslindemann). +* ✏️ Fix typo in `docs/ru/docs/index.md`. PR [#10672](https://github.com/tiangolo/fastapi/pull/10672) by [@Delitel-WEB](https://github.com/Delitel-WEB). +* ✏️ Fix typos in `docs/zh/docs/tutorial/extra-data-types.md`. PR [#10727](https://github.com/tiangolo/fastapi/pull/10727) by [@HiemalBeryl](https://github.com/HiemalBeryl). +* 🌐 Add Russian translation for `docs/ru/docs/tutorial/dependencies/classes-as-dependencies.md`. PR [#10410](https://github.com/tiangolo/fastapi/pull/10410) by [@AlertRED](https://github.com/AlertRED). + +### Internal + +* 👥 Update FastAPI People. PR [#11074](https://github.com/tiangolo/fastapi/pull/11074) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Update sponsors: add Coherence. PR [#11066](https://github.com/tiangolo/fastapi/pull/11066) by [@tiangolo](https://github.com/tiangolo). +* 👷 Upgrade GitHub Action issue-manager. PR [#11056](https://github.com/tiangolo/fastapi/pull/11056) by [@tiangolo](https://github.com/tiangolo). +* 🍱 Update sponsors: TalkPython badge. PR [#11052](https://github.com/tiangolo/fastapi/pull/11052) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Update sponsors: TalkPython badge image. PR [#11048](https://github.com/tiangolo/fastapi/pull/11048) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Update sponsors, remove Deta. PR [#11041](https://github.com/tiangolo/fastapi/pull/11041) by [@tiangolo](https://github.com/tiangolo). +* 💄 Fix CSS breaking RTL languages (erroneously introduced by a previous RTL PR). PR [#11039](https://github.com/tiangolo/fastapi/pull/11039) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Add Italian to `mkdocs.yml`. PR [#11016](https://github.com/tiangolo/fastapi/pull/11016) by [@alejsdev](https://github.com/alejsdev). +* 🔨 Verify `mkdocs.yml` languages in CI, update `docs.py`. PR [#11009](https://github.com/tiangolo/fastapi/pull/11009) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Update config in `label-approved.yml` to accept translations with 1 reviewer. PR [#11007](https://github.com/tiangolo/fastapi/pull/11007) by [@alejsdev](https://github.com/alejsdev). +* 👷 Add changes-requested handling in GitHub Action issue manager. PR [#10971](https://github.com/tiangolo/fastapi/pull/10971) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Group dependencies on dependabot updates. PR [#10952](https://github.com/tiangolo/fastapi/pull/10952) by [@Kludex](https://github.com/Kludex). +* ⬆ Bump actions/setup-python from 4 to 5. PR [#10764](https://github.com/tiangolo/fastapi/pull/10764) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump pypa/gh-action-pypi-publish from 1.8.10 to 1.8.11. PR [#10731](https://github.com/tiangolo/fastapi/pull/10731) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump dawidd6/action-download-artifact from 2.28.0 to 3.0.0. PR [#10777](https://github.com/tiangolo/fastapi/pull/10777) by [@dependabot[bot]](https://github.com/apps/dependabot). +* 🔧 Add support for translations to languages with a longer code name, like `zh-hant`. PR [#10950](https://github.com/tiangolo/fastapi/pull/10950) by [@tiangolo](https://github.com/tiangolo). + +## 0.109.0 (2024-01-11) + +### Features + +* ✨ Add support for Python 3.12. PR [#10666](https://github.com/tiangolo/fastapi/pull/10666) by [@Jamim](https://github.com/Jamim). + +### Upgrades + +* ⬆️ Upgrade Starlette to >=0.35.0,<0.36.0. PR [#10938](https://github.com/tiangolo/fastapi/pull/10938) by [@tiangolo](https://github.com/tiangolo). + +### Docs + +* ✏️ Fix typo in `docs/en/docs/alternatives.md`. PR [#10931](https://github.com/tiangolo/fastapi/pull/10931) by [@s111d](https://github.com/s111d). +* 📝 Replace `email` with `username` in `docs_src/security/tutorial007` code examples. PR [#10649](https://github.com/tiangolo/fastapi/pull/10649) by [@nilslindemann](https://github.com/nilslindemann). +* 📝 Add VS Code tutorial link. PR [#10592](https://github.com/tiangolo/fastapi/pull/10592) by [@nilslindemann](https://github.com/nilslindemann). +* 📝 Add notes about Pydantic v2's new `.model_dump()`. PR [#10929](https://github.com/tiangolo/fastapi/pull/10929) by [@tiangolo](https://github.com/tiangolo). +* 📝 Fix broken link in `docs/en/docs/tutorial/sql-databases.md`. PR [#10765](https://github.com/tiangolo/fastapi/pull/10765) by [@HurSungYun](https://github.com/HurSungYun). +* 📝 Add External Link: FastAPI application monitoring made easy. PR [#10917](https://github.com/tiangolo/fastapi/pull/10917) by [@tiangolo](https://github.com/tiangolo). +* ✨ Generate automatic language names for docs translations. PR [#5354](https://github.com/tiangolo/fastapi/pull/5354) by [@jakul](https://github.com/jakul). +* ✏️ Fix typos in `docs/en/docs/alternatives.md` and `docs/en/docs/tutorial/dependencies/index.md`. PR [#10906](https://github.com/tiangolo/fastapi/pull/10906) by [@s111d](https://github.com/s111d). +* ✏️ Fix typos in `docs/en/docs/tutorial/dependencies/dependencies-with-yield.md`. PR [#10834](https://github.com/tiangolo/fastapi/pull/10834) by [@Molkree](https://github.com/Molkree). +* 📝 Add article: "Building a RESTful API with FastAPI: Secure Signup and Login Functionality Included". PR [#9733](https://github.com/tiangolo/fastapi/pull/9733) by [@dxphilo](https://github.com/dxphilo). +* 📝 Add warning about lifecycle events with `AsyncClient`. PR [#4167](https://github.com/tiangolo/fastapi/pull/4167) by [@andrew-chang-dewitt](https://github.com/andrew-chang-dewitt). +* ✏️ Fix typos in `/docs/reference/exceptions.md` and `/en/docs/reference/status.md`. PR [#10809](https://github.com/tiangolo/fastapi/pull/10809) by [@clarencepenz](https://github.com/clarencepenz). +* ✏️ Fix typo in `openapi-callbacks.md`. PR [#10673](https://github.com/tiangolo/fastapi/pull/10673) by [@kayjan](https://github.com/kayjan). +* ✏️ Fix typo in `fastapi/routing.py` . PR [#10520](https://github.com/tiangolo/fastapi/pull/10520) by [@sepsh](https://github.com/sepsh). +* 📝 Replace HTTP code returned in case of existing user error in docs for testing. PR [#4482](https://github.com/tiangolo/fastapi/pull/4482) by [@TristanMarion](https://github.com/TristanMarion). +* 📝 Add blog for FastAPI & Supabase. PR [#6018](https://github.com/tiangolo/fastapi/pull/6018) by [@theinfosecguy](https://github.com/theinfosecguy). +* 📝 Update example source files for SQL databases with SQLAlchemy. PR [#9508](https://github.com/tiangolo/fastapi/pull/9508) by [@s-mustafa](https://github.com/s-mustafa). +* 📝 Update code examples in docs for body, replace name `create_item` with `update_item` when appropriate. PR [#5913](https://github.com/tiangolo/fastapi/pull/5913) by [@OttoAndrey](https://github.com/OttoAndrey). +* ✏️ Fix typo in dependencies with yield source examples. PR [#10847](https://github.com/tiangolo/fastapi/pull/10847) by [@tiangolo](https://github.com/tiangolo). + +### Translations + +* 🌐 Add Bengali translation for `docs/bn/docs/index.md`. PR [#9177](https://github.com/tiangolo/fastapi/pull/9177) by [@Fahad-Md-Kamal](https://github.com/Fahad-Md-Kamal). +* ✏️ Update Python version in `index.md` in several languages. PR [#10711](https://github.com/tiangolo/fastapi/pull/10711) by [@tamago3keran](https://github.com/tamago3keran). +* 🌐 Add Russian translation for `docs/ru/docs/tutorial/request-forms-and-files.md`. PR [#10347](https://github.com/tiangolo/fastapi/pull/10347) by [@AlertRED](https://github.com/AlertRED). +* 🌐 Add Ukrainian translation for `docs/uk/docs/index.md`. PR [#10362](https://github.com/tiangolo/fastapi/pull/10362) by [@rostik1410](https://github.com/rostik1410). +* ✏️ Update Python version in `docs/ko/docs/index.md`. PR [#10680](https://github.com/tiangolo/fastapi/pull/10680) by [@Eeap](https://github.com/Eeap). +* 🌐 Add Persian translation for `docs/fa/docs/features.md`. PR [#5887](https://github.com/tiangolo/fastapi/pull/5887) by [@amirilf](https://github.com/amirilf). +* 🌐 Add Chinese translation for `docs/zh/docs/advanced/additional-responses.md`. PR [#10325](https://github.com/tiangolo/fastapi/pull/10325) by [@ShuibeiC](https://github.com/ShuibeiC). +* 🌐 Fix typos in Russian translations for `docs/ru/docs/tutorial/background-tasks.md`, `docs/ru/docs/tutorial/body-nested-models.md`, `docs/ru/docs/tutorial/debugging.md`, `docs/ru/docs/tutorial/testing.md`. PR [#10311](https://github.com/tiangolo/fastapi/pull/10311) by [@AlertRED](https://github.com/AlertRED). +* 🌐 Add Russian translation for `docs/ru/docs/tutorial/request-files.md`. PR [#10332](https://github.com/tiangolo/fastapi/pull/10332) by [@AlertRED](https://github.com/AlertRED). +* 🌐 Add Chinese translation for `docs/zh/docs/deployment/server-workers.md`. PR [#10292](https://github.com/tiangolo/fastapi/pull/10292) by [@xzmeng](https://github.com/xzmeng). +* 🌐 Add Chinese translation for `docs/zh/docs/deployment/cloud.md`. PR [#10291](https://github.com/tiangolo/fastapi/pull/10291) by [@xzmeng](https://github.com/xzmeng). +* 🌐 Add Chinese translation for `docs/zh/docs/deployment/manually.md`. PR [#10279](https://github.com/tiangolo/fastapi/pull/10279) by [@xzmeng](https://github.com/xzmeng). +* 🌐 Add Chinese translation for `docs/zh/docs/deployment/https.md`. PR [#10277](https://github.com/tiangolo/fastapi/pull/10277) by [@xzmeng](https://github.com/xzmeng). +* 🌐 Add Chinese translation for `docs/zh/docs/deployment/index.md`. PR [#10275](https://github.com/tiangolo/fastapi/pull/10275) by [@xzmeng](https://github.com/xzmeng). +* 🌐 Add German translation for `docs/de/docs/tutorial/first-steps.md`. PR [#9530](https://github.com/tiangolo/fastapi/pull/9530) by [@fhabers21](https://github.com/fhabers21). +* 🌐 Update Turkish translation for `docs/tr/docs/index.md`. PR [#10444](https://github.com/tiangolo/fastapi/pull/10444) by [@hasansezertasan](https://github.com/hasansezertasan). +* 🌐 Add Chinese translation for `docs/zh/docs/learn/index.md`. PR [#10479](https://github.com/tiangolo/fastapi/pull/10479) by [@KAZAMA-DREAM](https://github.com/KAZAMA-DREAM). +* 🌐 Add Russian translation for `docs/ru/docs/learn/index.md`. PR [#10539](https://github.com/tiangolo/fastapi/pull/10539) by [@AlertRED](https://github.com/AlertRED). +* 🌐 Update SQLAlchemy instruction in Chinese translation `docs/zh/docs/tutorial/sql-databases.md`. PR [#9712](https://github.com/tiangolo/fastapi/pull/9712) by [@Royc30ne](https://github.com/Royc30ne). +* 🌐 Add Turkish translation for `docs/tr/docs/external-links.md`. PR [#10549](https://github.com/tiangolo/fastapi/pull/10549) by [@hasansezertasan](https://github.com/hasansezertasan). +* 🌐 Add Spanish translation for `docs/es/docs/learn/index.md`. PR [#10885](https://github.com/tiangolo/fastapi/pull/10885) by [@pablocm83](https://github.com/pablocm83). +* 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/body-fields.md`. PR [#10670](https://github.com/tiangolo/fastapi/pull/10670) by [@ArtemKhymenko](https://github.com/ArtemKhymenko). +* 🌐 Add Hungarian translation for `/docs/hu/docs/index.md`. PR [#10812](https://github.com/tiangolo/fastapi/pull/10812) by [@takacs](https://github.com/takacs). +* 🌐 Add Turkish translation for `docs/tr/docs/newsletter.md`. PR [#10550](https://github.com/tiangolo/fastapi/pull/10550) by [@hasansezertasan](https://github.com/hasansezertasan). +* 🌐 Add Spanish translation for `docs/es/docs/help/index.md`. PR [#10907](https://github.com/tiangolo/fastapi/pull/10907) by [@pablocm83](https://github.com/pablocm83). +* 🌐 Add Spanish translation for `docs/es/docs/about/index.md`. PR [#10908](https://github.com/tiangolo/fastapi/pull/10908) by [@pablocm83](https://github.com/pablocm83). +* 🌐 Add Spanish translation for `docs/es/docs/resources/index.md`. PR [#10909](https://github.com/tiangolo/fastapi/pull/10909) by [@pablocm83](https://github.com/pablocm83). + +### Internal + +* 👥 Update FastAPI People. PR [#10871](https://github.com/tiangolo/fastapi/pull/10871) by [@tiangolo](https://github.com/tiangolo). +* 👷 Upgrade custom GitHub Action comment-docs-preview-in-pr. PR [#10916](https://github.com/tiangolo/fastapi/pull/10916) by [@tiangolo](https://github.com/tiangolo). +* ⬆️ Upgrade GitHub Action latest-changes. PR [#10915](https://github.com/tiangolo/fastapi/pull/10915) by [@tiangolo](https://github.com/tiangolo). +* 👷 Upgrade GitHub Action label-approved. PR [#10913](https://github.com/tiangolo/fastapi/pull/10913) by [@tiangolo](https://github.com/tiangolo). +* ⬆️ Upgrade GitHub Action label-approved. PR [#10905](https://github.com/tiangolo/fastapi/pull/10905) by [@tiangolo](https://github.com/tiangolo). + +## 0.108.0 (2023-12-26) + +### Upgrades + +* ⬆️ Upgrade Starlette to `>=0.29.0,<0.33.0`, update docs and usage of templates with new Starlette arguments. Remove pin of AnyIO `>=3.7.1,<4.0.0`, add support for AnyIO 4.x.x. PR [#10846](https://github.com/tiangolo/fastapi/pull/10846) by [@tiangolo](https://github.com/tiangolo). + +## 0.107.0 (2023-12-26) + +### Upgrades + +* ⬆️ Upgrade Starlette to 0.28.0. PR [#9636](https://github.com/tiangolo/fastapi/pull/9636) by [@adriangb](https://github.com/adriangb). + +### Docs + +* 📝 Add docs: Node.js script alternative to update OpenAPI for generated clients. PR [#10845](https://github.com/tiangolo/fastapi/pull/10845) by [@alejsdev](https://github.com/alejsdev). +* 📝 Restructure Docs section in Contributing page. PR [#10844](https://github.com/tiangolo/fastapi/pull/10844) by [@alejsdev](https://github.com/alejsdev). + +## 0.106.0 (2023-12-25) + +### Breaking Changes + +Using resources from dependencies with `yield` in background tasks is no longer supported. + +This change is what supports the new features, read below. 🤓 + +### Dependencies with `yield`, `HTTPException` and Background Tasks + +Dependencies with `yield` now can raise `HTTPException` and other exceptions after `yield`. 🎉 + +Read the new docs here: [Dependencies with `yield` and `HTTPException`](https://fastapi.tiangolo.com/tutorial/dependencies/dependencies-with-yield/#dependencies-with-yield-and-httpexception). + +```Python +from fastapi import Depends, FastAPI, HTTPException +from typing_extensions import Annotated + +app = FastAPI() + + +data = { + "plumbus": {"description": "Freshly pickled plumbus", "owner": "Morty"}, + "portal-gun": {"description": "Gun to create portals", "owner": "Rick"}, +} + + +class OwnerError(Exception): + pass + + +def get_username(): + try: + yield "Rick" + except OwnerError as e: + raise HTTPException(status_code=400, detail=f"Owner error: {e}") + + +@app.get("/items/{item_id}") +def get_item(item_id: str, username: Annotated[str, Depends(get_username)]): + if item_id not in data: + raise HTTPException(status_code=404, detail="Item not found") + item = data[item_id] + if item["owner"] != username: + raise OwnerError(username) + return item +``` + +--- + +Before FastAPI 0.106.0, raising exceptions after `yield` was not possible, the exit code in dependencies with `yield` was executed *after* the response was sent, so [Exception Handlers](https://fastapi.tiangolo.com/tutorial/handling-errors/#install-custom-exception-handlers) would have already run. + +This was designed this way mainly to allow using the same objects "yielded" by dependencies inside of background tasks, because the exit code would be executed after the background tasks were finished. + +Nevertheless, as this would mean waiting for the response to travel through the network while unnecessarily holding a resource in a dependency with yield (for example a database connection), this was changed in FastAPI 0.106.0. + +Additionally, a background task is normally an independent set of logic that should be handled separately, with its own resources (e.g. its own database connection). + +If you used to rely on this behavior, now you should create the resources for background tasks inside the background task itself, and use internally only data that doesn't depend on the resources of dependencies with `yield`. + +For example, instead of using the same database session, you would create a new database session inside of the background task, and you would obtain the objects from the database using this new session. And then instead of passing the object from the database as a parameter to the background task function, you would pass the ID of that object and then obtain the object again inside the background task function. + +The sequence of execution before FastAPI 0.106.0 was like this diagram: + +Time flows from top to bottom. And each column is one of the parts interacting or executing code. + +```mermaid +sequenceDiagram + +participant client as Client +participant handler as Exception handler +participant dep as Dep with yield +participant operation as Path Operation +participant tasks as Background tasks + + Note over client,tasks: Can raise exception for dependency, handled after response is sent + Note over client,operation: Can raise HTTPException and can change the response + client ->> dep: Start request + Note over dep: Run code up to yield + opt raise + dep -->> handler: Raise HTTPException + handler -->> client: HTTP error response + dep -->> dep: Raise other exception + end + dep ->> operation: Run dependency, e.g. DB session + opt raise + operation -->> dep: Raise HTTPException + dep -->> handler: Auto forward exception + handler -->> client: HTTP error response + operation -->> dep: Raise other exception + dep -->> handler: Auto forward exception + end + operation ->> client: Return response to client + Note over client,operation: Response is already sent, can't change it anymore + opt Tasks + operation -->> tasks: Send background tasks + end + opt Raise other exception + tasks -->> dep: Raise other exception + end + Note over dep: After yield + opt Handle other exception + dep -->> dep: Handle exception, can't change response. E.g. close DB session. + end +``` + +The new execution flow can be found in the docs: [Execution of dependencies with `yield`](https://fastapi.tiangolo.com/tutorial/dependencies/dependencies-with-yield/#execution-of-dependencies-with-yield). + +### Features + +* ✨ Add support for raising exceptions (including `HTTPException`) in dependencies with `yield` in the exit code, do not support them in background tasks. PR [#10831](https://github.com/tiangolo/fastapi/pull/10831) by [@tiangolo](https://github.com/tiangolo). + +### Internal + +* 👥 Update FastAPI People. PR [#10567](https://github.com/tiangolo/fastapi/pull/10567) by [@tiangolo](https://github.com/tiangolo). + +## 0.105.0 (2023-12-12) + +### Features + +* ✨ Add support for multiple Annotated annotations, e.g. `Annotated[str, Field(), Query()]`. PR [#10773](https://github.com/tiangolo/fastapi/pull/10773) by [@tiangolo](https://github.com/tiangolo). + +### Refactors + +* 🔥 Remove unused NoneType. PR [#10774](https://github.com/tiangolo/fastapi/pull/10774) by [@tiangolo](https://github.com/tiangolo). + +### Docs + +* 📝 Tweak default suggested configs for generating clients. PR [#10736](https://github.com/tiangolo/fastapi/pull/10736) by [@tiangolo](https://github.com/tiangolo). + +### Internal + +* 🔧 Update sponsors, add Scalar. PR [#10728](https://github.com/tiangolo/fastapi/pull/10728) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Update sponsors, add PropelAuth. PR [#10760](https://github.com/tiangolo/fastapi/pull/10760) by [@tiangolo](https://github.com/tiangolo). +* 👷 Update build docs, verify README on CI. PR [#10750](https://github.com/tiangolo/fastapi/pull/10750) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Update sponsors, remove Fern. PR [#10729](https://github.com/tiangolo/fastapi/pull/10729) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Update sponsors, add Codacy. PR [#10677](https://github.com/tiangolo/fastapi/pull/10677) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Update sponsors, add Reflex. PR [#10676](https://github.com/tiangolo/fastapi/pull/10676) by [@tiangolo](https://github.com/tiangolo). +* 📝 Update release notes, move and check latest-changes. PR [#10588](https://github.com/tiangolo/fastapi/pull/10588) by [@tiangolo](https://github.com/tiangolo). +* 👷 Upgrade latest-changes GitHub Action. PR [#10587](https://github.com/tiangolo/fastapi/pull/10587) by [@tiangolo](https://github.com/tiangolo). + +## 0.104.1 (2023-10-30) + +### Fixes + +* 📌 Pin Swagger UI version to 5.9.0 temporarily to handle a bug crashing it in 5.9.1. PR [#10529](https://github.com/tiangolo/fastapi/pull/10529) by [@alejandraklachquin](https://github.com/alejandraklachquin). + * This is not really a bug in FastAPI but in Swagger UI, nevertheless pinning the version will work while a solution is found on the [Swagger UI side](https://github.com/swagger-api/swagger-ui/issues/9337). + +### Docs + +* 📝 Update data structure and render for external-links. PR [#10495](https://github.com/tiangolo/fastapi/pull/10495) by [@tiangolo](https://github.com/tiangolo). +* ✏️ Fix link to SPDX license identifier in `docs/en/docs/tutorial/metadata.md`. PR [#10433](https://github.com/tiangolo/fastapi/pull/10433) by [@worldworm](https://github.com/worldworm). +* 📝 Update example validation error from Pydantic v1 to match Pydantic v2 in `docs/en/docs/tutorial/path-params.md`. PR [#10043](https://github.com/tiangolo/fastapi/pull/10043) by [@giuliowaitforitdavide](https://github.com/giuliowaitforitdavide). +* ✏️ Fix typos in emoji docs and in some source examples. PR [#10438](https://github.com/tiangolo/fastapi/pull/10438) by [@afuetterer](https://github.com/afuetterer). +* ✏️ Fix typo in `docs/en/docs/reference/dependencies.md`. PR [#10465](https://github.com/tiangolo/fastapi/pull/10465) by [@suravshresth](https://github.com/suravshresth). +* ✏️ Fix typos and rewordings in `docs/en/docs/tutorial/body-nested-models.md`. PR [#10468](https://github.com/tiangolo/fastapi/pull/10468) by [@yogabonito](https://github.com/yogabonito). +* 📝 Update docs, remove references to removed `pydantic.Required` in `docs/en/docs/tutorial/query-params-str-validations.md`. PR [#10469](https://github.com/tiangolo/fastapi/pull/10469) by [@yogabonito](https://github.com/yogabonito). +* ✏️ Fix typo in `docs/en/docs/reference/index.md`. PR [#10467](https://github.com/tiangolo/fastapi/pull/10467) by [@tarsil](https://github.com/tarsil). +* 🔥 Remove unnecessary duplicated docstrings. PR [#10484](https://github.com/tiangolo/fastapi/pull/10484) by [@tiangolo](https://github.com/tiangolo). + +### Internal + +* ✏️ Update Pydantic links to dotenv support. PR [#10511](https://github.com/tiangolo/fastapi/pull/10511) by [@White-Mask](https://github.com/White-Mask). +* ✏️ Update links in `docs/en/docs/async.md` and `docs/zh/docs/async.md` to make them relative. PR [#10498](https://github.com/tiangolo/fastapi/pull/10498) by [@hasnatsajid](https://github.com/hasnatsajid). +* ✏️ Fix links in `docs/em/docs/async.md`. PR [#10507](https://github.com/tiangolo/fastapi/pull/10507) by [@hasnatsajid](https://github.com/hasnatsajid). +* ✏️ Fix typo in `docs/em/docs/index.md`, Python 3.8. PR [#10521](https://github.com/tiangolo/fastapi/pull/10521) by [@kerriop](https://github.com/kerriop). +* ⬆ Bump pillow from 9.5.0 to 10.1.0. PR [#10446](https://github.com/tiangolo/fastapi/pull/10446) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Update mkdocs-material requirement from <9.0.0,>=8.1.4 to >=8.1.4,<10.0.0. PR [#5862](https://github.com/tiangolo/fastapi/pull/5862) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump mkdocs-material from 9.1.21 to 9.4.7. PR [#10545](https://github.com/tiangolo/fastapi/pull/10545) by [@dependabot[bot]](https://github.com/apps/dependabot). +* 👷 Install MkDocs Material Insiders only when secrets are available, for Dependabot. PR [#10544](https://github.com/tiangolo/fastapi/pull/10544) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Update sponsors badges, Databento. PR [#10519](https://github.com/tiangolo/fastapi/pull/10519) by [@tiangolo](https://github.com/tiangolo). +* 👷 Adopt Ruff format. PR [#10517](https://github.com/tiangolo/fastapi/pull/10517) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Add `CITATION.cff` file for academic citations. PR [#10496](https://github.com/tiangolo/fastapi/pull/10496) by [@tiangolo](https://github.com/tiangolo). +* 🐛 Fix overriding MKDocs theme lang in hook. PR [#10490](https://github.com/tiangolo/fastapi/pull/10490) by [@tiangolo](https://github.com/tiangolo). +* 🔥 Drop/close Gitter chat. Questions should go to GitHub Discussions, free conversations to Discord.. PR [#10485](https://github.com/tiangolo/fastapi/pull/10485) by [@tiangolo](https://github.com/tiangolo). + +## 0.104.0 (2023-10-18) + +## Features + +* ✨ Add reference (code API) docs with PEP 727, add subclass with custom docstrings for `BackgroundTasks`, refactor docs structure. PR [#10392](https://github.com/tiangolo/fastapi/pull/10392) by [@tiangolo](https://github.com/tiangolo). New docs at [FastAPI Reference - Code API](https://fastapi.tiangolo.com/reference/). + +## Upgrades + +* ⬆️ Drop support for Python 3.7, require Python 3.8 or above. PR [#10442](https://github.com/tiangolo/fastapi/pull/10442) by [@tiangolo](https://github.com/tiangolo). + +### Internal + +* ⬆ Bump dawidd6/action-download-artifact from 2.27.0 to 2.28.0. PR [#10268](https://github.com/tiangolo/fastapi/pull/10268) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump actions/checkout from 3 to 4. PR [#10208](https://github.com/tiangolo/fastapi/pull/10208) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump pypa/gh-action-pypi-publish from 1.8.6 to 1.8.10. PR [#10061](https://github.com/tiangolo/fastapi/pull/10061) by [@dependabot[bot]](https://github.com/apps/dependabot). +* 🔧 Update sponsors, Bump.sh images. PR [#10381](https://github.com/tiangolo/fastapi/pull/10381) by [@tiangolo](https://github.com/tiangolo). +* 👥 Update FastAPI People. PR [#10363](https://github.com/tiangolo/fastapi/pull/10363) by [@tiangolo](https://github.com/tiangolo). + +## 0.103.2 (2023-09-28) + +### Refactors + +* ⬆️ Upgrade compatibility with Pydantic v2.4, new renamed functions and JSON Schema input/output models with default values. PR [#10344](https://github.com/tiangolo/fastapi/pull/10344) by [@tiangolo](https://github.com/tiangolo). + +### Translations + +* 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/extra-data-types.md`. PR [#10132](https://github.com/tiangolo/fastapi/pull/10132) by [@ArtemKhymenko](https://github.com/ArtemKhymenko). +* 🌐 Fix typos in French translations for `docs/fr/docs/advanced/path-operation-advanced-configuration.md`, `docs/fr/docs/alternatives.md`, `docs/fr/docs/async.md`, `docs/fr/docs/features.md`, `docs/fr/docs/help-fastapi.md`, `docs/fr/docs/index.md`, `docs/fr/docs/python-types.md`, `docs/fr/docs/tutorial/body.md`, `docs/fr/docs/tutorial/first-steps.md`, `docs/fr/docs/tutorial/query-params.md`. PR [#10154](https://github.com/tiangolo/fastapi/pull/10154) by [@s-rigaud](https://github.com/s-rigaud). +* 🌐 Add Chinese translation for `docs/zh/docs/async.md`. PR [#5591](https://github.com/tiangolo/fastapi/pull/5591) by [@mkdir700](https://github.com/mkdir700). +* 🌐 Update Chinese translation for `docs/tutorial/security/simple-oauth2.md`. PR [#3844](https://github.com/tiangolo/fastapi/pull/3844) by [@jaystone776](https://github.com/jaystone776). +* 🌐 Add Korean translation for `docs/ko/docs/deployment/cloud.md`. PR [#10191](https://github.com/tiangolo/fastapi/pull/10191) by [@Sion99](https://github.com/Sion99). +* 🌐 Add Japanese translation for `docs/ja/docs/deployment/https.md`. PR [#10298](https://github.com/tiangolo/fastapi/pull/10298) by [@tamtam-fitness](https://github.com/tamtam-fitness). +* 🌐 Fix typo in Russian translation for `docs/ru/docs/tutorial/body-fields.md`. PR [#10224](https://github.com/tiangolo/fastapi/pull/10224) by [@AlertRED](https://github.com/AlertRED). +* 🌐 Add Polish translation for `docs/pl/docs/help-fastapi.md`. PR [#10121](https://github.com/tiangolo/fastapi/pull/10121) by [@romabozhanovgithub](https://github.com/romabozhanovgithub). +* 🌐 Add Russian translation for `docs/ru/docs/tutorial/header-params.md`. PR [#10226](https://github.com/tiangolo/fastapi/pull/10226) by [@AlertRED](https://github.com/AlertRED). +* 🌐 Add Chinese translation for `docs/zh/docs/deployment/versions.md`. PR [#10276](https://github.com/tiangolo/fastapi/pull/10276) by [@xzmeng](https://github.com/xzmeng). + +### Internal + +* 🔧 Update sponsors, remove Flint. PR [#10349](https://github.com/tiangolo/fastapi/pull/10349) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Rename label "awaiting review" to "awaiting-review" to simplify search queries. PR [#10343](https://github.com/tiangolo/fastapi/pull/10343) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Update sponsors, enable Svix (revert #10228). PR [#10253](https://github.com/tiangolo/fastapi/pull/10253) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Update sponsors, remove Svix. PR [#10228](https://github.com/tiangolo/fastapi/pull/10228) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Update sponsors, add Bump.sh. PR [#10227](https://github.com/tiangolo/fastapi/pull/10227) by [@tiangolo](https://github.com/tiangolo). + +## 0.103.1 (2023-09-02) + +### Fixes + +* 📌 Pin AnyIO to < 4.0.0 to handle an incompatibility while upgrading to Starlette 0.31.1. PR [#10194](https://github.com/tiangolo/fastapi/pull/10194) by [@tiangolo](https://github.com/tiangolo). + +### Docs + +* ✏️ Fix validation parameter name in docs, from `regex` to `pattern`. PR [#10085](https://github.com/tiangolo/fastapi/pull/10085) by [@pablodorrio](https://github.com/pablodorrio). +* ✏️ Fix indent format in `docs/en/docs/deployment/server-workers.md`. PR [#10066](https://github.com/tiangolo/fastapi/pull/10066) by [@tamtam-fitness](https://github.com/tamtam-fitness). +* ✏️ Fix Pydantic examples in tutorial for Python types. PR [#9961](https://github.com/tiangolo/fastapi/pull/9961) by [@rahulsalgare](https://github.com/rahulsalgare). +* ✏️ Fix link to Pydantic docs in `docs/en/docs/tutorial/extra-data-types.md`. PR [#10155](https://github.com/tiangolo/fastapi/pull/10155) by [@hasnatsajid](https://github.com/hasnatsajid). +* ✏️ Fix typo in `docs/en/docs/tutorial/handling-errors.md`. PR [#10170](https://github.com/tiangolo/fastapi/pull/10170) by [@poupapaa](https://github.com/poupapaa). +* ✏️ Fix typo in `docs/en/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md`. PR [#10172](https://github.com/tiangolo/fastapi/pull/10172) by [@ragul-kachiappan](https://github.com/ragul-kachiappan). + +### Translations + +* 🌐 Remove duplicate line in translation for `docs/pt/docs/tutorial/path-params.md`. PR [#10126](https://github.com/tiangolo/fastapi/pull/10126) by [@LecoOliveira](https://github.com/LecoOliveira). +* 🌐 Add Yoruba translation for `docs/yo/docs/index.md`. PR [#10033](https://github.com/tiangolo/fastapi/pull/10033) by [@AfolabiOlaoluwa](https://github.com/AfolabiOlaoluwa). +* 🌐 Add Ukrainian translation for `docs/uk/docs/python-types.md`. PR [#10080](https://github.com/tiangolo/fastapi/pull/10080) by [@rostik1410](https://github.com/rostik1410). +* 🌐 Add Vietnamese translations for `docs/vi/docs/tutorial/first-steps.md` and `docs/vi/docs/tutorial/index.md`. PR [#10088](https://github.com/tiangolo/fastapi/pull/10088) by [@magiskboy](https://github.com/magiskboy). +* 🌐 Add Ukrainian translation for `docs/uk/docs/alternatives.md`. PR [#10060](https://github.com/tiangolo/fastapi/pull/10060) by [@whysage](https://github.com/whysage). +* 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/index.md`. PR [#10079](https://github.com/tiangolo/fastapi/pull/10079) by [@rostik1410](https://github.com/rostik1410). +* ✏️ Fix typos in `docs/en/docs/how-to/separate-openapi-schemas.md` and `docs/en/docs/tutorial/schema-extra-example.md`. PR [#10189](https://github.com/tiangolo/fastapi/pull/10189) by [@xzmeng](https://github.com/xzmeng). +* 🌐 Add Chinese translation for `docs/zh/docs/advanced/generate-clients.md`. PR [#9883](https://github.com/tiangolo/fastapi/pull/9883) by [@funny-cat-happy](https://github.com/funny-cat-happy). + +### Refactors + +* ✏️ Fix typos in comment in `fastapi/applications.py`. PR [#10045](https://github.com/tiangolo/fastapi/pull/10045) by [@AhsanSheraz](https://github.com/AhsanSheraz). +* ✅ Add missing test for OpenAPI examples, it was missing in coverage. PR [#10188](https://github.com/tiangolo/fastapi/pull/10188) by [@tiangolo](https://github.com/tiangolo). + +### Internal + +* 👥 Update FastAPI People. PR [#10186](https://github.com/tiangolo/fastapi/pull/10186) by [@tiangolo](https://github.com/tiangolo). + +## 0.103.0 (2023-08-26) + +### Features + +* ✨ Add support for `openapi_examples` in all FastAPI parameters. PR [#10152](https://github.com/tiangolo/fastapi/pull/10152) by [@tiangolo](https://github.com/tiangolo). + * New docs: [OpenAPI-specific examples](https://fastapi.tiangolo.com/tutorial/schema-extra-example/#openapi-specific-examples). + +### Docs + +* 📝 Add note to docs about Separate Input and Output Schemas with FastAPI version. PR [#10150](https://github.com/tiangolo/fastapi/pull/10150) by [@tiangolo](https://github.com/tiangolo). + +## 0.102.0 (2023-08-25) + +### Features + +* ✨ Add support for disabling the separation of input and output JSON Schemas in OpenAPI with Pydantic v2 with `separate_input_output_schemas=False`. PR [#10145](https://github.com/tiangolo/fastapi/pull/10145) by [@tiangolo](https://github.com/tiangolo). + * New docs [Separate OpenAPI Schemas for Input and Output or Not](https://fastapi.tiangolo.com/how-to/separate-openapi-schemas/). + * This PR also includes a new setup (internal tools) for generating screenshots for the docs. + +### Refactors + +* ♻️ Refactor tests for new Pydantic 2.2.1. PR [#10115](https://github.com/tiangolo/fastapi/pull/10115) by [@tiangolo](https://github.com/tiangolo). + +### Docs + +* 📝 Add new docs section, How To - Recipes, move docs that don't have to be read by everyone to How To. PR [#10114](https://github.com/tiangolo/fastapi/pull/10114) by [@tiangolo](https://github.com/tiangolo). +* 📝 Update Advanced docs, add links to sponsor courses. PR [#10113](https://github.com/tiangolo/fastapi/pull/10113) by [@tiangolo](https://github.com/tiangolo). +* 📝 Update docs for generating clients. PR [#10112](https://github.com/tiangolo/fastapi/pull/10112) by [@tiangolo](https://github.com/tiangolo). +* 📝 Tweak MkDocs and add redirects. PR [#10111](https://github.com/tiangolo/fastapi/pull/10111) by [@tiangolo](https://github.com/tiangolo). +* 📝 Restructure docs for cloud providers, include links to sponsors. PR [#10110](https://github.com/tiangolo/fastapi/pull/10110) by [@tiangolo](https://github.com/tiangolo). + +### Internal + +* 🔧 Update sponsors, add Speakeasy. PR [#10098](https://github.com/tiangolo/fastapi/pull/10098) by [@tiangolo](https://github.com/tiangolo). + +## 0.101.1 (2023-08-14) + +### Fixes + +* ✨ Add `ResponseValidationError` printable details, to show up in server error logs. PR [#10078](https://github.com/tiangolo/fastapi/pull/10078) by [@tiangolo](https://github.com/tiangolo). + +### Refactors + +* ✏️ Fix typo in deprecation warnings in `fastapi/params.py`. PR [#9854](https://github.com/tiangolo/fastapi/pull/9854) by [@russbiggs](https://github.com/russbiggs). +* ✏️ Fix typos in comments on internal code in `fastapi/concurrency.py` and `fastapi/routing.py`. PR [#9590](https://github.com/tiangolo/fastapi/pull/9590) by [@ElliottLarsen](https://github.com/ElliottLarsen). + +### Docs + +* ✏️ Fix typo in release notes. PR [#9835](https://github.com/tiangolo/fastapi/pull/9835) by [@francisbergin](https://github.com/francisbergin). +* 📝 Add external article: Build an SMS Spam Classifier Serverless Database with FaunaDB and FastAPI. PR [#9847](https://github.com/tiangolo/fastapi/pull/9847) by [@adejumoridwan](https://github.com/adejumoridwan). +* 📝 Fix typo in `docs/en/docs/contributing.md`. PR [#9878](https://github.com/tiangolo/fastapi/pull/9878) by [@VicenteMerino](https://github.com/VicenteMerino). +* 📝 Fix code highlighting in `docs/en/docs/tutorial/bigger-applications.md`. PR [#9806](https://github.com/tiangolo/fastapi/pull/9806) by [@theonlykingpin](https://github.com/theonlykingpin). + +### Translations + +* 🌐 Add Japanese translation for `docs/ja/docs/deployment/concepts.md`. PR [#10062](https://github.com/tiangolo/fastapi/pull/10062) by [@tamtam-fitness](https://github.com/tamtam-fitness). +* 🌐 Add Japanese translation for `docs/ja/docs/deployment/server-workers.md`. PR [#10064](https://github.com/tiangolo/fastapi/pull/10064) by [@tamtam-fitness](https://github.com/tamtam-fitness). +* 🌐 Update Japanese translation for `docs/ja/docs/deployment/docker.md`. PR [#10073](https://github.com/tiangolo/fastapi/pull/10073) by [@tamtam-fitness](https://github.com/tamtam-fitness). +* 🌐 Add Ukrainian translation for `docs/uk/docs/fastapi-people.md`. PR [#10059](https://github.com/tiangolo/fastapi/pull/10059) by [@rostik1410](https://github.com/rostik1410). +* 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/cookie-params.md`. PR [#10032](https://github.com/tiangolo/fastapi/pull/10032) by [@rostik1410](https://github.com/rostik1410). +* 🌐 Add Russian translation for `docs/ru/docs/deployment/docker.md`. PR [#9971](https://github.com/tiangolo/fastapi/pull/9971) by [@Xewus](https://github.com/Xewus). +* 🌐 Add Vietnamese translation for `docs/vi/docs/python-types.md`. PR [#10047](https://github.com/tiangolo/fastapi/pull/10047) by [@magiskboy](https://github.com/magiskboy). +* 🌐 Add Russian translation for `docs/ru/docs/tutorial/dependencies/global-dependencies.md`. PR [#9970](https://github.com/tiangolo/fastapi/pull/9970) by [@dudyaosuplayer](https://github.com/dudyaosuplayer). +* 🌐 Add Urdu translation for `docs/ur/docs/benchmarks.md`. PR [#9974](https://github.com/tiangolo/fastapi/pull/9974) by [@AhsanSheraz](https://github.com/AhsanSheraz). + +### Internal + +* 🔧 Add sponsor Porter. PR [#10051](https://github.com/tiangolo/fastapi/pull/10051) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Update sponsors, add Jina back as bronze sponsor. PR [#10050](https://github.com/tiangolo/fastapi/pull/10050) by [@tiangolo](https://github.com/tiangolo). +* ⬆ Bump mypy from 1.4.0 to 1.4.1. PR [#9756](https://github.com/tiangolo/fastapi/pull/9756) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump mkdocs-material from 9.1.17 to 9.1.21. PR [#9960](https://github.com/tiangolo/fastapi/pull/9960) by [@dependabot[bot]](https://github.com/apps/dependabot). + +## 0.101.0 (2023-08-04) + +### Features + +* ✨ Enable Pydantic's serialization mode for responses, add support for Pydantic's `computed_field`, better OpenAPI for response models, proper required attributes, better generated clients. PR [#10011](https://github.com/tiangolo/fastapi/pull/10011) by [@tiangolo](https://github.com/tiangolo). + +### Refactors + +* ✅ Fix tests for compatibility with pydantic 2.1.1. PR [#9943](https://github.com/tiangolo/fastapi/pull/9943) by [@dmontagu](https://github.com/dmontagu). +* ✅ Fix test error in Windows for `jsonable_encoder`. PR [#9840](https://github.com/tiangolo/fastapi/pull/9840) by [@iudeen](https://github.com/iudeen). + +### Upgrades + +* 📌 Do not allow Pydantic 2.1.0 that breaks (require 2.1.1). PR [#10012](https://github.com/tiangolo/fastapi/pull/10012) by [@tiangolo](https://github.com/tiangolo). + +### Translations + +* 🌐 Add Russian translation for `docs/ru/docs/tutorial/security/index.md`. PR [#9963](https://github.com/tiangolo/fastapi/pull/9963) by [@eVery1337](https://github.com/eVery1337). +* 🌐 Remove Vietnamese note about missing translation. PR [#9957](https://github.com/tiangolo/fastapi/pull/9957) by [@tiangolo](https://github.com/tiangolo). + +### Internal + +* 👷 Add GitHub Actions step dump context to debug external failures. PR [#10008](https://github.com/tiangolo/fastapi/pull/10008) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Restore MkDocs Material pin after the fix. PR [#10001](https://github.com/tiangolo/fastapi/pull/10001) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Update the Question template to ask for the Pydantic version. PR [#10000](https://github.com/tiangolo/fastapi/pull/10000) by [@tiangolo](https://github.com/tiangolo). +* 📍 Update MkDocs Material dependencies. PR [#9986](https://github.com/tiangolo/fastapi/pull/9986) by [@tiangolo](https://github.com/tiangolo). +* 👥 Update FastAPI People. PR [#9999](https://github.com/tiangolo/fastapi/pull/9999) by [@tiangolo](https://github.com/tiangolo). +* 🐳 Update Dockerfile with compatibility versions, to upgrade later. PR [#9998](https://github.com/tiangolo/fastapi/pull/9998) by [@tiangolo](https://github.com/tiangolo). +* ➕ Add pydantic-settings to FastAPI People dependencies. PR [#9988](https://github.com/tiangolo/fastapi/pull/9988) by [@tiangolo](https://github.com/tiangolo). +* ♻️ Update FastAPI People logic with new Pydantic. PR [#9985](https://github.com/tiangolo/fastapi/pull/9985) by [@tiangolo](https://github.com/tiangolo). +* 🍱 Update sponsors, Fern badge. PR [#9982](https://github.com/tiangolo/fastapi/pull/9982) by [@tiangolo](https://github.com/tiangolo). +* 👷 Deploy docs to Cloudflare Pages. PR [#9978](https://github.com/tiangolo/fastapi/pull/9978) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Update sponsor Fern. PR [#9979](https://github.com/tiangolo/fastapi/pull/9979) by [@tiangolo](https://github.com/tiangolo). +* 👷 Update CI debug mode with Tmate. PR [#9977](https://github.com/tiangolo/fastapi/pull/9977) by [@tiangolo](https://github.com/tiangolo). + +## 0.100.1 (2023-07-27) + +### Fixes + +* 🐛 Replace `MultHostUrl` to `AnyUrl` for compatibility with older versions of Pydantic v1. PR [#9852](https://github.com/tiangolo/fastapi/pull/9852) by [@Kludex](https://github.com/Kludex). + +### Docs + +* 📝 Update links for self-hosted Swagger UI, point to v5, for OpenAPI 31.0. PR [#9834](https://github.com/tiangolo/fastapi/pull/9834) by [@tiangolo](https://github.com/tiangolo). + +### Translations + +* 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/body.md`. PR [#4574](https://github.com/tiangolo/fastapi/pull/4574) by [@ss-o-furda](https://github.com/ss-o-furda). +* 🌐 Add Vietnamese translation for `docs/vi/docs/features.md` and `docs/vi/docs/index.md`. PR [#3006](https://github.com/tiangolo/fastapi/pull/3006) by [@magiskboy](https://github.com/magiskboy). +* 🌐 Add Korean translation for `docs/ko/docs/async.md`. PR [#4179](https://github.com/tiangolo/fastapi/pull/4179) by [@NinaHwang](https://github.com/NinaHwang). +* 🌐 Add Chinese translation for `docs/zh/docs/tutorial/background-tasks.md`. PR [#9812](https://github.com/tiangolo/fastapi/pull/9812) by [@wdh99](https://github.com/wdh99). +* 🌐 Add French translation for `docs/fr/docs/tutorial/query-params-str-validations.md`. PR [#4075](https://github.com/tiangolo/fastapi/pull/4075) by [@Smlep](https://github.com/Smlep). +* 🌐 Add French translation for `docs/fr/docs/tutorial/index.md`. PR [#2234](https://github.com/tiangolo/fastapi/pull/2234) by [@JulianMaurin](https://github.com/JulianMaurin). +* 🌐 Add French translation for `docs/fr/docs/contributing.md`. PR [#2132](https://github.com/tiangolo/fastapi/pull/2132) by [@JulianMaurin](https://github.com/JulianMaurin). +* 🌐 Add French translation for `docs/fr/docs/benchmarks.md`. PR [#2155](https://github.com/tiangolo/fastapi/pull/2155) by [@clemsau](https://github.com/clemsau). +* 🌐 Update Chinese translations with new source files. PR [#9738](https://github.com/tiangolo/fastapi/pull/9738) by [@mahone3297](https://github.com/mahone3297). +* 🌐 Add Russian translation for `docs/ru/docs/tutorial/request-forms.md`. PR [#9841](https://github.com/tiangolo/fastapi/pull/9841) by [@dedkot01](https://github.com/dedkot01). +* 🌐 Update Chinese translation for `docs/zh/docs/tutorial/handling-errors.md`. PR [#9485](https://github.com/tiangolo/fastapi/pull/9485) by [@Creat55](https://github.com/Creat55). + +### Internal + +* 🔧 Update sponsors, add Fern. PR [#9956](https://github.com/tiangolo/fastapi/pull/9956) by [@tiangolo](https://github.com/tiangolo). +* 👷 Update FastAPI People token. PR [#9844](https://github.com/tiangolo/fastapi/pull/9844) by [@tiangolo](https://github.com/tiangolo). +* 👥 Update FastAPI People. PR [#9775](https://github.com/tiangolo/fastapi/pull/9775) by [@tiangolo](https://github.com/tiangolo). +* 👷 Update MkDocs Material token. PR [#9843](https://github.com/tiangolo/fastapi/pull/9843) by [@tiangolo](https://github.com/tiangolo). +* 👷 Update token for latest changes. PR [#9842](https://github.com/tiangolo/fastapi/pull/9842) by [@tiangolo](https://github.com/tiangolo). + +## 0.100.0 (2023-07-07) + +✨ Support for **Pydantic v2** ✨ + +Pydantic version 2 has the **core** re-written in **Rust** and includes a lot of improvements and features, for example: + +* Improved **correctness** in corner cases. +* **Safer** types. +* Better **performance** and **less energy** consumption. +* Better **extensibility**. +* etc. + +...all this while keeping the **same Python API**. In most of the cases, for simple models, you can simply upgrade the Pydantic version and get all the benefits. 🚀 + +In some cases, for pure data validation and processing, you can get performance improvements of **20x** or more. This means 2,000% or more. 🤯 + +When you use **FastAPI**, there's a lot more going on, processing the request and response, handling dependencies, executing **your own code**, and particularly, **waiting for the network**. But you will probably still get some nice performance improvements just from the upgrade. + +The focus of this release is **compatibility** with Pydantic v1 and v2, to make sure your current apps keep working. Later there will be more focus on refactors, correctness, code improvements, and then **performance** improvements. Some third-party early beta testers that ran benchmarks on the beta releases of FastAPI reported improvements of **2x - 3x**. Which is not bad for just doing `pip install --upgrade fastapi pydantic`. This was not an official benchmark and I didn't check it myself, but it's a good sign. + +### Migration + +Check out the [Pydantic migration guide](https://docs.pydantic.dev/2.0/migration/). + +For the things that need changes in your Pydantic models, the Pydantic team built [`bump-pydantic`](https://github.com/pydantic/bump-pydantic). + +A command line tool that will **process your code** and update most of the things **automatically** for you. Make sure you have your code in git first, and review each of the changes to make sure everything is correct before committing the changes. + +### Pydantic v1 + +**This version of FastAPI still supports Pydantic v1**. And although Pydantic v1 will be deprecated at some point, it will still be supported for a while. + +This means that you can install the new Pydantic v2, and if something fails, you can install Pydantic v1 while you fix any problems you might have, but having the latest FastAPI. + +There are **tests for both Pydantic v1 and v2**, and test **coverage** is kept at **100%**. + +### Changes + +* There are **new parameter** fields supported by Pydantic `Field()` for: + + * `Path()` + * `Query()` + * `Header()` + * `Cookie()` + * `Body()` + * `Form()` + * `File()` + +* The new parameter fields are: + + * `default_factory` + * `alias_priority` + * `validation_alias` + * `serialization_alias` + * `discriminator` + * `strict` + * `multiple_of` + * `allow_inf_nan` + * `max_digits` + * `decimal_places` + * `json_schema_extra` + +...you can read about them in the Pydantic docs. + +* The parameter `regex` has been deprecated and replaced by `pattern`. + * You can read more about it in the docs for [Query Parameters and String Validations: Add regular expressions](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#add-regular-expressions). +* New Pydantic models use an improved and simplified attribute `model_config` that takes a simple dict instead of an internal class `Config` for their configuration. + * You can read more about it in the docs for [Declare Request Example Data](https://fastapi.tiangolo.com/tutorial/schema-extra-example/). +* The attribute `schema_extra` for the internal class `Config` has been replaced by the key `json_schema_extra` in the new `model_config` dict. + * You can read more about it in the docs for [Declare Request Example Data](https://fastapi.tiangolo.com/tutorial/schema-extra-example/). +* When you install `"fastapi[all]"` it now also includes: + * [`pydantic-settings`](https://docs.pydantic.dev/latest/usage/pydantic_settings/) - for settings management. + * [`pydantic-extra-types`](https://docs.pydantic.dev/latest/usage/types/extra_types/extra_types/) - for extra types to be used with Pydantic. +* Now Pydantic Settings is an additional optional package (included in `"fastapi[all]"`). To use settings you should now import `from pydantic_settings import BaseSettings` instead of importing from `pydantic` directly. + * You can read more about it in the docs for [Settings and Environment Variables](https://fastapi.tiangolo.com/advanced/settings/). + +* PR [#9816](https://github.com/tiangolo/fastapi/pull/9816) by [@tiangolo](https://github.com/tiangolo), included all the work done (in multiple PRs) on the beta branch (`main-pv2`). + +## 0.99.1 (2023-07-02) + +### Fixes + +* 🐛 Fix JSON Schema accepting bools as valid JSON Schemas, e.g. `additionalProperties: false`. PR [#9781](https://github.com/tiangolo/fastapi/pull/9781) by [@tiangolo](https://github.com/tiangolo). + +### Docs + +* 📝 Update source examples to use new JSON Schema examples field. PR [#9776](https://github.com/tiangolo/fastapi/pull/9776) by [@tiangolo](https://github.com/tiangolo). + +## 0.99.0 (2023-06-30) + +### Features + +* ✨ Add support for OpenAPI 3.1.0. PR [#9770](https://github.com/tiangolo/fastapi/pull/9770) by [@tiangolo](https://github.com/tiangolo). + * New support for documenting **webhooks**, read the new docs here: [Advanced User Guide: OpenAPI Webhooks](https://fastapi.tiangolo.com/advanced/openapi-webhooks/). + * Upgrade OpenAPI 3.1.0, this uses JSON Schema 2020-12. + * Upgrade Swagger UI to version 5.x.x, that supports OpenAPI 3.1.0. + * Updated `examples` field in `Query()`, `Cookie()`, `Body()`, etc. based on the latest JSON Schema and OpenAPI. Now it takes a list of examples and they are included directly in the JSON Schema, not outside. Read more about it (including the historical technical details) in the updated docs: [Tutorial: Declare Request Example Data](https://fastapi.tiangolo.com/tutorial/schema-extra-example/). + +* ✨ Add support for `deque` objects and children in `jsonable_encoder`. PR [#9433](https://github.com/tiangolo/fastapi/pull/9433) by [@cranium](https://github.com/cranium). + +### Docs + +* 📝 Fix form for the FastAPI and friends newsletter. PR [#9749](https://github.com/tiangolo/fastapi/pull/9749) by [@tiangolo](https://github.com/tiangolo). + +### Translations + +* 🌐 Add Persian translation for `docs/fa/docs/advanced/sub-applications.md`. PR [#9692](https://github.com/tiangolo/fastapi/pull/9692) by [@mojtabapaso](https://github.com/mojtabapaso). +* 🌐 Add Russian translation for `docs/ru/docs/tutorial/response-model.md`. PR [#9675](https://github.com/tiangolo/fastapi/pull/9675) by [@glsglsgls](https://github.com/glsglsgls). + +### Internal + +* 🔨 Enable linenums in MkDocs Material during local live development to simplify highlighting code. PR [#9769](https://github.com/tiangolo/fastapi/pull/9769) by [@tiangolo](https://github.com/tiangolo). +* ⬆ Update httpx requirement from <0.24.0,>=0.23.0 to >=0.23.0,<0.25.0. PR [#9724](https://github.com/tiangolo/fastapi/pull/9724) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump mkdocs-material from 9.1.16 to 9.1.17. PR [#9746](https://github.com/tiangolo/fastapi/pull/9746) by [@dependabot[bot]](https://github.com/apps/dependabot). +* 🔥 Remove missing translation dummy pages, no longer necessary. PR [#9751](https://github.com/tiangolo/fastapi/pull/9751) by [@tiangolo](https://github.com/tiangolo). +* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#9259](https://github.com/tiangolo/fastapi/pull/9259) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). +* ✨ Add Material for MkDocs Insiders features and cards. PR [#9748](https://github.com/tiangolo/fastapi/pull/9748) by [@tiangolo](https://github.com/tiangolo). +* 🔥 Remove languages without translations. PR [#9743](https://github.com/tiangolo/fastapi/pull/9743) by [@tiangolo](https://github.com/tiangolo). +* ✨ Refactor docs for building scripts, use MkDocs hooks, simplify (remove) configs for languages. PR [#9742](https://github.com/tiangolo/fastapi/pull/9742) by [@tiangolo](https://github.com/tiangolo). +* 🔨 Add MkDocs hook that renames sections based on the first index file. PR [#9737](https://github.com/tiangolo/fastapi/pull/9737) by [@tiangolo](https://github.com/tiangolo). +* 👷 Make cron jobs run only on main repo, not on forks, to avoid error notifications from missing tokens. PR [#9735](https://github.com/tiangolo/fastapi/pull/9735) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Update MkDocs for other languages. PR [#9734](https://github.com/tiangolo/fastapi/pull/9734) by [@tiangolo](https://github.com/tiangolo). +* 👷 Refactor Docs CI, run in multiple workers with a dynamic matrix to optimize speed. PR [#9732](https://github.com/tiangolo/fastapi/pull/9732) by [@tiangolo](https://github.com/tiangolo). +* 🔥 Remove old internal GitHub Action watch-previews that is no longer needed. PR [#9730](https://github.com/tiangolo/fastapi/pull/9730) by [@tiangolo](https://github.com/tiangolo). +* ⬆️ Upgrade MkDocs and MkDocs Material. PR [#9729](https://github.com/tiangolo/fastapi/pull/9729) by [@tiangolo](https://github.com/tiangolo). +* 👷 Build and deploy docs only on docs changes. PR [#9728](https://github.com/tiangolo/fastapi/pull/9728) by [@tiangolo](https://github.com/tiangolo). + +## 0.98.0 (2023-06-22) + +### Features + +* ✨ Allow disabling `redirect_slashes` at the FastAPI app level. PR [#3432](https://github.com/tiangolo/fastapi/pull/3432) by [@cyberlis](https://github.com/cyberlis). + +### Docs + +* 📝 Update docs on Pydantic using ujson internally. PR [#5804](https://github.com/tiangolo/fastapi/pull/5804) by [@mvasilkov](https://github.com/mvasilkov). +* ✏ Rewording in `docs/en/docs/tutorial/debugging.md`. PR [#9581](https://github.com/tiangolo/fastapi/pull/9581) by [@ivan-abc](https://github.com/ivan-abc). +* 📝 Add german blog post (Domain-driven Design mit Python und FastAPI). PR [#9261](https://github.com/tiangolo/fastapi/pull/9261) by [@msander](https://github.com/msander). +* ✏️ Tweak wording in `docs/en/docs/tutorial/security/index.md`. PR [#9561](https://github.com/tiangolo/fastapi/pull/9561) by [@jyothish-mohan](https://github.com/jyothish-mohan). +* 📝 Update `Annotated` notes in `docs/en/docs/tutorial/schema-extra-example.md`. PR [#9620](https://github.com/tiangolo/fastapi/pull/9620) by [@Alexandrhub](https://github.com/Alexandrhub). +* ✏️ Fix typo `Annotation` -> `Annotated` in `docs/en/docs/tutorial/query-params-str-validations.md`. PR [#9625](https://github.com/tiangolo/fastapi/pull/9625) by [@mccricardo](https://github.com/mccricardo). +* 📝 Use in memory database for testing SQL in docs. PR [#1223](https://github.com/tiangolo/fastapi/pull/1223) by [@HarshaLaxman](https://github.com/HarshaLaxman). + +### Translations + +* 🌐 Add Russian translation for `docs/ru/docs/tutorial/metadata.md`. PR [#9681](https://github.com/tiangolo/fastapi/pull/9681) by [@TabarakoAkula](https://github.com/TabarakoAkula). +* 🌐 Fix typo in Spanish translation for `docs/es/docs/tutorial/first-steps.md`. PR [#9571](https://github.com/tiangolo/fastapi/pull/9571) by [@lilidl-nft](https://github.com/lilidl-nft). +* 🌐 Add Russian translation for `docs/tutorial/path-operation-configuration.md`. PR [#9696](https://github.com/tiangolo/fastapi/pull/9696) by [@TabarakoAkula](https://github.com/TabarakoAkula). +* 🌐 Add Chinese translation for `docs/zh/docs/advanced/security/index.md`. PR [#9666](https://github.com/tiangolo/fastapi/pull/9666) by [@lordqyxz](https://github.com/lordqyxz). +* 🌐 Add Chinese translations for `docs/zh/docs/advanced/settings.md`. PR [#9652](https://github.com/tiangolo/fastapi/pull/9652) by [@ChoyeonChern](https://github.com/ChoyeonChern). +* 🌐 Add Chinese translations for `docs/zh/docs/advanced/websockets.md`. PR [#9651](https://github.com/tiangolo/fastapi/pull/9651) by [@ChoyeonChern](https://github.com/ChoyeonChern). +* 🌐 Add Chinese translation for `docs/zh/docs/tutorial/testing.md`. PR [#9641](https://github.com/tiangolo/fastapi/pull/9641) by [@wdh99](https://github.com/wdh99). +* 🌐 Add Russian translation for `docs/tutorial/extra-models.md`. PR [#9619](https://github.com/tiangolo/fastapi/pull/9619) by [@ivan-abc](https://github.com/ivan-abc). +* 🌐 Add Russian translation for `docs/tutorial/cors.md`. PR [#9608](https://github.com/tiangolo/fastapi/pull/9608) by [@ivan-abc](https://github.com/ivan-abc). +* 🌐 Add Polish translation for `docs/pl/docs/features.md`. PR [#5348](https://github.com/tiangolo/fastapi/pull/5348) by [@mbroton](https://github.com/mbroton). +* 🌐 Add Russian translation for `docs/ru/docs/tutorial/body-nested-models.md`. PR [#9605](https://github.com/tiangolo/fastapi/pull/9605) by [@Alexandrhub](https://github.com/Alexandrhub). + +### Internal + +* ⬆ Bump ruff from 0.0.272 to 0.0.275. PR [#9721](https://github.com/tiangolo/fastapi/pull/9721) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Update uvicorn[standard] requirement from <0.21.0,>=0.12.0 to >=0.12.0,<0.23.0. PR [#9463](https://github.com/tiangolo/fastapi/pull/9463) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump mypy from 1.3.0 to 1.4.0. PR [#9719](https://github.com/tiangolo/fastapi/pull/9719) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Update pre-commit requirement from <3.0.0,>=2.17.0 to >=2.17.0,<4.0.0. PR [#9251](https://github.com/tiangolo/fastapi/pull/9251) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump pypa/gh-action-pypi-publish from 1.8.5 to 1.8.6. PR [#9482](https://github.com/tiangolo/fastapi/pull/9482) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ✏️ Fix tooltips for light/dark theme toggler in docs. PR [#9588](https://github.com/tiangolo/fastapi/pull/9588) by [@pankaj1707k](https://github.com/pankaj1707k). +* 🔧 Set minimal hatchling version needed to build the package. PR [#9240](https://github.com/tiangolo/fastapi/pull/9240) by [@mgorny](https://github.com/mgorny). +* 📝 Add repo link to PyPI. PR [#9559](https://github.com/tiangolo/fastapi/pull/9559) by [@JacobCoffee](https://github.com/JacobCoffee). +* ✏️ Fix typos in data for tests. PR [#4958](https://github.com/tiangolo/fastapi/pull/4958) by [@ryanrussell](https://github.com/ryanrussell). +* 🔧 Update sponsors, add Flint. PR [#9699](https://github.com/tiangolo/fastapi/pull/9699) by [@tiangolo](https://github.com/tiangolo). +* 👷 Lint in CI only once, only with one version of Python, run tests with all of them. PR [#9686](https://github.com/tiangolo/fastapi/pull/9686) by [@tiangolo](https://github.com/tiangolo). + +## 0.97.0 (2023-06-11) + +### Features + +* ✨ Add support for `dependencies` in WebSocket routes. PR [#4534](https://github.com/tiangolo/fastapi/pull/4534) by [@paulo-raca](https://github.com/paulo-raca). +* ✨ Add exception handler for `WebSocketRequestValidationError` (which also allows to override it). PR [#6030](https://github.com/tiangolo/fastapi/pull/6030) by [@kristjanvalur](https://github.com/kristjanvalur). + +### Refactors + +* ⬆️ Upgrade and fully migrate to Ruff, remove isort, includes a couple of tweaks suggested by the new version of Ruff. PR [#9660](https://github.com/tiangolo/fastapi/pull/9660) by [@tiangolo](https://github.com/tiangolo). +* ♻️ Update internal type annotations and upgrade mypy. PR [#9658](https://github.com/tiangolo/fastapi/pull/9658) by [@tiangolo](https://github.com/tiangolo). +* ♻️ Simplify `AsyncExitStackMiddleware` as without Python 3.6 `AsyncExitStack` is always available. PR [#9657](https://github.com/tiangolo/fastapi/pull/9657) by [@tiangolo](https://github.com/tiangolo). + +### Upgrades + +* ⬆️ Upgrade Black. PR [#9661](https://github.com/tiangolo/fastapi/pull/9661) by [@tiangolo](https://github.com/tiangolo). + +### Internal + +* 💚 Update CI cache to fix installs when dependencies change. PR [#9659](https://github.com/tiangolo/fastapi/pull/9659) by [@tiangolo](https://github.com/tiangolo). +* ⬇️ Separate requirements for development into their own requirements.txt files, they shouldn't be extras. PR [#9655](https://github.com/tiangolo/fastapi/pull/9655) by [@tiangolo](https://github.com/tiangolo). + +## 0.96.1 (2023-06-10) + +### Fixes + +* 🐛 Fix `HTTPException` header type annotations. PR [#9648](https://github.com/tiangolo/fastapi/pull/9648) by [@tiangolo](https://github.com/tiangolo). +* 🐛 Fix OpenAPI model fields int validations, `gte` to `ge`. PR [#9635](https://github.com/tiangolo/fastapi/pull/9635) by [@tiangolo](https://github.com/tiangolo). + +### Upgrades + +* 📌 Update minimum version of Pydantic to >=1.7.4. This fixes an issue when trying to use an old version of Pydantic. PR [#9567](https://github.com/tiangolo/fastapi/pull/9567) by [@Kludex](https://github.com/Kludex). + +### Refactors + +* ♻ Remove `media_type` from `ORJSONResponse` as it's inherited from the parent class. PR [#5805](https://github.com/tiangolo/fastapi/pull/5805) by [@Kludex](https://github.com/Kludex). +* ♻ Instantiate `HTTPException` only when needed, optimization refactor. PR [#5356](https://github.com/tiangolo/fastapi/pull/5356) by [@pawamoy](https://github.com/pawamoy). + +### Docs + +* 🔥 Remove link to Pydantic's benchmark, as it was removed there. PR [#5811](https://github.com/tiangolo/fastapi/pull/5811) by [@Kludex](https://github.com/Kludex). + +### Translations + +* 🌐 Fix spelling in Indonesian translation of `docs/id/docs/tutorial/index.md`. PR [#5635](https://github.com/tiangolo/fastapi/pull/5635) by [@purwowd](https://github.com/purwowd). +* 🌐 Add Russian translation for `docs/ru/docs/tutorial/index.md`. PR [#5896](https://github.com/tiangolo/fastapi/pull/5896) by [@Wilidon](https://github.com/Wilidon). +* 🌐 Add Chinese translations for `docs/zh/docs/advanced/response-change-status-code.md` and `docs/zh/docs/advanced/response-headers.md`. PR [#9544](https://github.com/tiangolo/fastapi/pull/9544) by [@ChoyeonChern](https://github.com/ChoyeonChern). +* 🌐 Add Russian translation for `docs/ru/docs/tutorial/schema-extra-example.md`. PR [#9621](https://github.com/tiangolo/fastapi/pull/9621) by [@Alexandrhub](https://github.com/Alexandrhub). + +### Internal + +* 🔧 Add sponsor Platform.sh. PR [#9650](https://github.com/tiangolo/fastapi/pull/9650) by [@tiangolo](https://github.com/tiangolo). +* 👷 Add custom token to Smokeshow and Preview Docs for download-artifact, to prevent API rate limits. PR [#9646](https://github.com/tiangolo/fastapi/pull/9646) by [@tiangolo](https://github.com/tiangolo). +* 👷 Add custom tokens for GitHub Actions to avoid rate limits. PR [#9647](https://github.com/tiangolo/fastapi/pull/9647) by [@tiangolo](https://github.com/tiangolo). + +## 0.96.0 (2023-06-03) + +### Features + +* ⚡ Update `create_cloned_field` to use a global cache and improve startup performance. PR [#4645](https://github.com/tiangolo/fastapi/pull/4645) by [@madkinsz](https://github.com/madkinsz) and previous original PR by [@huonw](https://github.com/huonw). + +### Docs + +* 📝 Update Deta deployment tutorial for compatibility with Deta Space. PR [#6004](https://github.com/tiangolo/fastapi/pull/6004) by [@mikBighne98](https://github.com/mikBighne98). +* ✏️ Fix typo in Deta deployment tutorial. PR [#9501](https://github.com/tiangolo/fastapi/pull/9501) by [@lemonyte](https://github.com/lemonyte). + +### Translations + +* 🌐 Add Russian translation for `docs/tutorial/body.md`. PR [#3885](https://github.com/tiangolo/fastapi/pull/3885) by [@solomein-sv](https://github.com/solomein-sv). +* 🌐 Add Russian translation for `docs/ru/docs/tutorial/static-files.md`. PR [#9580](https://github.com/tiangolo/fastapi/pull/9580) by [@Alexandrhub](https://github.com/Alexandrhub). +* 🌐 Add Russian translation for `docs/ru/docs/tutorial/query-params.md`. PR [#9584](https://github.com/tiangolo/fastapi/pull/9584) by [@Alexandrhub](https://github.com/Alexandrhub). +* 🌐 Add Russian translation for `docs/ru/docs/tutorial/first-steps.md`. PR [#9471](https://github.com/tiangolo/fastapi/pull/9471) by [@AGolicyn](https://github.com/AGolicyn). +* 🌐 Add Russian translation for `docs/ru/docs/tutorial/debugging.md`. PR [#9579](https://github.com/tiangolo/fastapi/pull/9579) by [@Alexandrhub](https://github.com/Alexandrhub). +* 🌐 Add Russian translation for `docs/ru/docs/tutorial/path-params.md`. PR [#9519](https://github.com/tiangolo/fastapi/pull/9519) by [@AGolicyn](https://github.com/AGolicyn). +* 🌐 Add Chinese translation for `docs/zh/docs/tutorial/static-files.md`. PR [#9436](https://github.com/tiangolo/fastapi/pull/9436) by [@wdh99](https://github.com/wdh99). +* 🌐 Update Spanish translation including new illustrations in `docs/es/docs/async.md`. PR [#9483](https://github.com/tiangolo/fastapi/pull/9483) by [@andresbermeoq](https://github.com/andresbermeoq). +* 🌐 Add Russian translation for `docs/ru/docs/tutorial/path-params-numeric-validations.md`. PR [#9563](https://github.com/tiangolo/fastapi/pull/9563) by [@ivan-abc](https://github.com/ivan-abc). +* 🌐 Add Russian translation for `docs/ru/docs/deployment/concepts.md`. PR [#9577](https://github.com/tiangolo/fastapi/pull/9577) by [@Xewus](https://github.com/Xewus). +* 🌐 Add Russian translation for `docs/ru/docs/tutorial/body-multiple-params.md`. PR [#9586](https://github.com/tiangolo/fastapi/pull/9586) by [@Alexandrhub](https://github.com/Alexandrhub). + +### Internal + +* 👥 Update FastAPI People. PR [#9602](https://github.com/tiangolo/fastapi/pull/9602) by [@github-actions[bot]](https://github.com/apps/github-actions). +* 🔧 Update sponsors, remove InvestSuite. PR [#9612](https://github.com/tiangolo/fastapi/pull/9612) by [@tiangolo](https://github.com/tiangolo). + +## 0.95.2 (2023-05-16) + +* ⬆️ Upgrade Starlette version to `>=0.27.0` for a security release. PR [#9541](https://github.com/tiangolo/fastapi/pull/9541) by [@tiangolo](https://github.com/tiangolo). Details on [Starlette's security advisory](https://github.com/encode/starlette/security/advisories/GHSA-v5gw-mw7f-84px). + +### Translations + +* 🌐 Add Portuguese translation for `docs/pt/docs/advanced/events.md`. PR [#9326](https://github.com/tiangolo/fastapi/pull/9326) by [@oandersonmagalhaes](https://github.com/oandersonmagalhaes). +* 🌐 Add Russian translation for `docs/ru/docs/deployment/manually.md`. PR [#9417](https://github.com/tiangolo/fastapi/pull/9417) by [@Xewus](https://github.com/Xewus). +* 🌐 Add setup for translations to Lao. PR [#9396](https://github.com/tiangolo/fastapi/pull/9396) by [@TheBrown](https://github.com/TheBrown). +* 🌐 Add Russian translation for `docs/ru/docs/tutorial/testing.md`. PR [#9403](https://github.com/tiangolo/fastapi/pull/9403) by [@Xewus](https://github.com/Xewus). +* 🌐 Add Russian translation for `docs/ru/docs/deployment/https.md`. PR [#9428](https://github.com/tiangolo/fastapi/pull/9428) by [@Xewus](https://github.com/Xewus). +* ✏ Fix command to install requirements in Windows. PR [#9445](https://github.com/tiangolo/fastapi/pull/9445) by [@MariiaRomanuik](https://github.com/MariiaRomanuik). +* 🌐 Add French translation for `docs/fr/docs/advanced/response-directly.md`. PR [#9415](https://github.com/tiangolo/fastapi/pull/9415) by [@axel584](https://github.com/axel584). +* 🌐 Initiate Czech translation setup. PR [#9288](https://github.com/tiangolo/fastapi/pull/9288) by [@3p1463k](https://github.com/3p1463k). +* ✏ Fix typo in Portuguese docs for `docs/pt/docs/index.md`. PR [#9337](https://github.com/tiangolo/fastapi/pull/9337) by [@lucasbalieiro](https://github.com/lucasbalieiro). +* 🌐 Add Russian translation for `docs/ru/docs/tutorial/response-status-code.md`. PR [#9370](https://github.com/tiangolo/fastapi/pull/9370) by [@nadia3373](https://github.com/nadia3373). + +### Internal + +* 🐛 Fix `flask.escape` warning for internal tests. PR [#9468](https://github.com/tiangolo/fastapi/pull/9468) by [@samuelcolvin](https://github.com/samuelcolvin). +* ✅ Refactor 2 tests, for consistency and simplification. PR [#9504](https://github.com/tiangolo/fastapi/pull/9504) by [@tiangolo](https://github.com/tiangolo). +* ✅ Refactor OpenAPI tests, prepare for Pydantic v2. PR [#9503](https://github.com/tiangolo/fastapi/pull/9503) by [@tiangolo](https://github.com/tiangolo). +* ⬆ Bump dawidd6/action-download-artifact from 2.26.0 to 2.27.0. PR [#9394](https://github.com/tiangolo/fastapi/pull/9394) by [@dependabot[bot]](https://github.com/apps/dependabot). +* 💚 Disable setup-python pip cache in CI. PR [#9438](https://github.com/tiangolo/fastapi/pull/9438) by [@tiangolo](https://github.com/tiangolo). +* ⬆ Bump pypa/gh-action-pypi-publish from 1.6.4 to 1.8.5. PR [#9346](https://github.com/tiangolo/fastapi/pull/9346) by [@dependabot[bot]](https://github.com/apps/dependabot). + +## 0.95.1 (2023-04-13) + +### Fixes + +* 🐛 Fix using `Annotated` in routers or path operations decorated multiple times. PR [#9315](https://github.com/tiangolo/fastapi/pull/9315) by [@sharonyogev](https://github.com/sharonyogev). + +### Docs + +* 🌐 🔠 📄 🐢 Translate docs to Emoji 🥳 🎉 💥 🤯 🤯. PR [#5385](https://github.com/tiangolo/fastapi/pull/5385) by [@LeeeeT](https://github.com/LeeeeT). +* 📝 Add notification message warning about old versions of FastAPI not supporting `Annotated`. PR [#9298](https://github.com/tiangolo/fastapi/pull/9298) by [@grdworkin](https://github.com/grdworkin). +* 📝 Fix typo in `docs/en/docs/advanced/behind-a-proxy.md`. PR [#5681](https://github.com/tiangolo/fastapi/pull/5681) by [@Leommjr](https://github.com/Leommjr). +* ✏ Fix wrong import from typing module in Persian translations for `docs/fa/docs/index.md`. PR [#6083](https://github.com/tiangolo/fastapi/pull/6083) by [@Kimiaattaei](https://github.com/Kimiaattaei). +* ✏️ Fix format, remove unnecessary asterisks in `docs/en/docs/help-fastapi.md`. PR [#9249](https://github.com/tiangolo/fastapi/pull/9249) by [@armgabrielyan](https://github.com/armgabrielyan). +* ✏ Fix typo in `docs/en/docs/tutorial/query-params-str-validations.md`. PR [#9272](https://github.com/tiangolo/fastapi/pull/9272) by [@nicornk](https://github.com/nicornk). +* ✏ Fix typo/bug in inline code example in `docs/en/docs/tutorial/query-params-str-validations.md`. PR [#9273](https://github.com/tiangolo/fastapi/pull/9273) by [@tim-habitat](https://github.com/tim-habitat). +* ✏ Fix typo in `docs/en/docs/tutorial/path-params-numeric-validations.md`. PR [#9282](https://github.com/tiangolo/fastapi/pull/9282) by [@aadarsh977](https://github.com/aadarsh977). +* ✏ Fix typo: 'wll' to 'will' in `docs/en/docs/tutorial/query-params-str-validations.md`. PR [#9380](https://github.com/tiangolo/fastapi/pull/9380) by [@dasstyxx](https://github.com/dasstyxx). + +### Translations + +* 🌐 Add French translation for `docs/fr/docs/advanced/index.md`. PR [#5673](https://github.com/tiangolo/fastapi/pull/5673) by [@axel584](https://github.com/axel584). +* 🌐 Add Portuguese translation for `docs/pt/docs/tutorial/body-nested-models.md`. PR [#4053](https://github.com/tiangolo/fastapi/pull/4053) by [@luccasmmg](https://github.com/luccasmmg). +* 🌐 Add Russian translation for `docs/ru/docs/alternatives.md`. PR [#5994](https://github.com/tiangolo/fastapi/pull/5994) by [@Xewus](https://github.com/Xewus). +* 🌐 Add Portuguese translation for `docs/pt/docs/tutorial/extra-models.md`. PR [#5912](https://github.com/tiangolo/fastapi/pull/5912) by [@LorhanSohaky](https://github.com/LorhanSohaky). +* 🌐 Add Portuguese translation for `docs/pt/docs/tutorial/path-operation-configuration.md`. PR [#5936](https://github.com/tiangolo/fastapi/pull/5936) by [@LorhanSohaky](https://github.com/LorhanSohaky). +* 🌐 Add Russian translation for `docs/ru/docs/contributing.md`. PR [#6002](https://github.com/tiangolo/fastapi/pull/6002) by [@stigsanek](https://github.com/stigsanek). +* 🌐 Add Korean translation for `docs/tutorial/dependencies/classes-as-dependencies.md`. PR [#9176](https://github.com/tiangolo/fastapi/pull/9176) by [@sehwan505](https://github.com/sehwan505). +* 🌐 Add Russian translation for `docs/ru/docs/project-generation.md`. PR [#9243](https://github.com/tiangolo/fastapi/pull/9243) by [@Xewus](https://github.com/Xewus). +* 🌐 Add French translation for `docs/fr/docs/index.md`. PR [#9265](https://github.com/tiangolo/fastapi/pull/9265) by [@frabc](https://github.com/frabc). +* 🌐 Add Russian translation for `docs/ru/docs/tutorial/query-params-str-validations.md`. PR [#9267](https://github.com/tiangolo/fastapi/pull/9267) by [@dedkot01](https://github.com/dedkot01). +* 🌐 Add Russian translation for `docs/ru/docs/benchmarks.md`. PR [#9271](https://github.com/tiangolo/fastapi/pull/9271) by [@Xewus](https://github.com/Xewus). + +### Internal + +* 🔧 Update sponsors: remove Jina. PR [#9388](https://github.com/tiangolo/fastapi/pull/9388) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Update sponsors, add databento, remove Ines's course and StriveWorks. PR [#9351](https://github.com/tiangolo/fastapi/pull/9351) by [@tiangolo](https://github.com/tiangolo). + +## 0.95.0 (2023-03-18) + +### Highlights + +This release adds support for dependencies and parameters using `Annotated` and recommends its usage. ✨ + +This has **several benefits**, one of the main ones is that now the parameters of your functions with `Annotated` would **not be affected** at all. + +If you call those functions in **other places in your code**, the actual **default values** will be kept, your editor will help you notice missing **required arguments**, Python will require you to pass required arguments at **runtime**, you will be able to **use the same functions** for different things and with different libraries (e.g. **Typer** will soon support `Annotated` too, then you could use the same function for an API and a CLI), etc. + +Because `Annotated` is **standard Python**, you still get all the **benefits** from editors and tools, like **autocompletion**, **inline errors**, etc. + +One of the **biggest benefits** is that now you can create `Annotated` dependencies that are then shared by multiple *path operation functions*, this will allow you to **reduce** a lot of **code duplication** in your codebase, while keeping all the support from editors and tools. + +For example, you could have code like this: + +```Python +def get_current_user(token: str): + # authenticate user + return User() + + +@app.get("/items/") +def read_items(user: User = Depends(get_current_user)): + ... + + +@app.post("/items/") +def create_item(*, user: User = Depends(get_current_user), item: Item): + ... + + +@app.get("/items/{item_id}") +def read_item(*, user: User = Depends(get_current_user), item_id: int): + ... + + +@app.delete("/items/{item_id}") +def delete_item(*, user: User = Depends(get_current_user), item_id: int): + ... +``` + +There's a bit of code duplication for the dependency: + +```Python +user: User = Depends(get_current_user) +``` + +...the bigger the codebase, the more noticeable it is. + +Now you can create an annotated dependency once, like this: + +```Python +CurrentUser = Annotated[User, Depends(get_current_user)] +``` + +And then you can reuse this `Annotated` dependency: + +```Python +CurrentUser = Annotated[User, Depends(get_current_user)] + + +@app.get("/items/") +def read_items(user: CurrentUser): + ... + + +@app.post("/items/") +def create_item(user: CurrentUser, item: Item): + ... + + +@app.get("/items/{item_id}") +def read_item(user: CurrentUser, item_id: int): + ... + + +@app.delete("/items/{item_id}") +def delete_item(user: CurrentUser, item_id: int): + ... +``` + +...and `CurrentUser` has all the typing information as `User`, so your editor will work as expected (autocompletion and everything), and **FastAPI** will be able to understand the dependency defined in `Annotated`. 😎 + +Roughly **all the docs** have been rewritten to use `Annotated` as the main way to declare **parameters** and **dependencies**. All the **examples** in the docs now include a version with `Annotated` and a version without it, for each of the specific Python versions (when there are small differences/improvements in more recent versions). There were around 23K new lines added between docs, examples, and tests. 🚀 + +The key updated docs are: + +* Python Types Intro: + * [Type Hints with Metadata Annotations](https://fastapi.tiangolo.com/python-types/#type-hints-with-metadata-annotations). +* Tutorial: + * [Query Parameters and String Validations - Additional validation](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#additional-validation) + * [Advantages of `Annotated`](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#advantages-of-annotated) + * [Path Parameters and Numeric Validations - Order the parameters as you need, tricks](https://fastapi.tiangolo.com/tutorial/path-params-numeric-validations/#order-the-parameters-as-you-need-tricks) + * [Better with `Annotated`](https://fastapi.tiangolo.com/tutorial/path-params-numeric-validations/#better-with-annotated) + * [Dependencies - First Steps - Share `Annotated` dependencies](https://fastapi.tiangolo.com/tutorial/dependencies/#share-annotated-dependencies) + +Special thanks to [@nzig](https://github.com/nzig) for the core implementation and to [@adriangb](https://github.com/adriangb) for the inspiration and idea with [Xpresso](https://github.com/adriangb/xpresso)! 🚀 + +### Features + +* ✨Add support for PEP-593 `Annotated` for specifying dependencies and parameters. PR [#4871](https://github.com/tiangolo/fastapi/pull/4871) by [@nzig](https://github.com/nzig). + +### Docs + +* 📝 Tweak tip recommending `Annotated` in docs. PR [#9270](https://github.com/tiangolo/fastapi/pull/9270) by [@tiangolo](https://github.com/tiangolo). +* 📝 Update order of examples, latest Python version first, and simplify version tab names. PR [#9269](https://github.com/tiangolo/fastapi/pull/9269) by [@tiangolo](https://github.com/tiangolo). +* 📝 Update all docs to use `Annotated` as the main recommendation, with new examples and tests. PR [#9268](https://github.com/tiangolo/fastapi/pull/9268) by [@tiangolo](https://github.com/tiangolo). + +## 0.94.1 (2023-03-14) + +### Fixes + +* 🎨 Fix types for lifespan, upgrade Starlette to 0.26.1. PR [#9245](https://github.com/tiangolo/fastapi/pull/9245) by [@tiangolo](https://github.com/tiangolo). + +## 0.94.0 (2023-03-10) + +### Upgrades + +* ⬆ Upgrade python-multipart to support 0.0.6. PR [#9212](https://github.com/tiangolo/fastapi/pull/9212) by [@musicinmybrain](https://github.com/musicinmybrain). +* ⬆️ Upgrade Starlette version, support new `lifespan` with state. PR [#9239](https://github.com/tiangolo/fastapi/pull/9239) by [@tiangolo](https://github.com/tiangolo). + +### Docs + +* 📝 Update Sentry link in docs. PR [#9218](https://github.com/tiangolo/fastapi/pull/9218) by [@smeubank](https://github.com/smeubank). + +### Translations + +* 🌐 Add Russian translation for `docs/ru/docs/history-design-future.md`. PR [#5986](https://github.com/tiangolo/fastapi/pull/5986) by [@Xewus](https://github.com/Xewus). + +### Internal + +* ➕ Add `pydantic` to PyPI classifiers. PR [#5914](https://github.com/tiangolo/fastapi/pull/5914) by [@yezz123](https://github.com/yezz123). +* ⬆ Bump black from 22.10.0 to 23.1.0. PR [#5953](https://github.com/tiangolo/fastapi/pull/5953) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump types-ujson from 5.6.0.0 to 5.7.0.1. PR [#6027](https://github.com/tiangolo/fastapi/pull/6027) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump dawidd6/action-download-artifact from 2.24.3 to 2.26.0. PR [#6034](https://github.com/tiangolo/fastapi/pull/6034) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#5709](https://github.com/tiangolo/fastapi/pull/5709) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). + +## 0.93.0 (2023-03-07) + +### Features + +* ✨ Add support for `lifespan` async context managers (superseding `startup` and `shutdown` events). Initial PR [#2944](https://github.com/tiangolo/fastapi/pull/2944) by [@uSpike](https://github.com/uSpike). + +Now, instead of using independent `startup` and `shutdown` events, you can define that logic in a single function with `yield` decorated with `@asynccontextmanager` (an async context manager). + +For example: + +```Python +from contextlib import asynccontextmanager + +from fastapi import FastAPI + + +def fake_answer_to_everything_ml_model(x: float): + return x * 42 + + +ml_models = {} + + +@asynccontextmanager +async def lifespan(app: FastAPI): + # Load the ML model + ml_models["answer_to_everything"] = fake_answer_to_everything_ml_model + yield + # Clean up the ML models and release the resources + ml_models.clear() + + +app = FastAPI(lifespan=lifespan) + + +@app.get("/predict") +async def predict(x: float): + result = ml_models["answer_to_everything"](x) + return {"result": result} +``` + +**Note**: This is the recommended way going forward, instead of using `startup` and `shutdown` events. + +Read more about it in the new docs: [Advanced User Guide: Lifespan Events](https://fastapi.tiangolo.com/advanced/events/). + +### Docs + +* ✏ Fix formatting in `docs/en/docs/tutorial/metadata.md` for `ReDoc`. PR [#6005](https://github.com/tiangolo/fastapi/pull/6005) by [@eykamp](https://github.com/eykamp). + +### Translations + +* 🌐 Tamil translations - initial setup. PR [#5564](https://github.com/tiangolo/fastapi/pull/5564) by [@gusty1g](https://github.com/gusty1g). +* 🌐 Add French translation for `docs/fr/docs/advanced/path-operation-advanced-configuration.md`. PR [#9221](https://github.com/tiangolo/fastapi/pull/9221) by [@axel584](https://github.com/axel584). +* 🌐 Add French translation for `docs/tutorial/debugging.md`. PR [#9175](https://github.com/tiangolo/fastapi/pull/9175) by [@frabc](https://github.com/frabc). +* 🌐 Initiate Armenian translation setup. PR [#5844](https://github.com/tiangolo/fastapi/pull/5844) by [@har8](https://github.com/har8). +* 🌐 Add French translation for `deployment/manually.md`. PR [#3693](https://github.com/tiangolo/fastapi/pull/3693) by [@rjNemo](https://github.com/rjNemo). + +### Internal + +* 👷 Update translation bot messages. PR [#9206](https://github.com/tiangolo/fastapi/pull/9206) by [@tiangolo](https://github.com/tiangolo). +* 👷 Update translations bot to use Discussions, and notify when a PR is done. PR [#9183](https://github.com/tiangolo/fastapi/pull/9183) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Update sponsors-badges. PR [#9182](https://github.com/tiangolo/fastapi/pull/9182) by [@tiangolo](https://github.com/tiangolo). +* 👥 Update FastAPI People. PR [#9181](https://github.com/tiangolo/fastapi/pull/9181) by [@github-actions[bot]](https://github.com/apps/github-actions). +* 🔊 Log GraphQL errors in FastAPI People, because it returns 200, with a payload with an error. PR [#9171](https://github.com/tiangolo/fastapi/pull/9171) by [@tiangolo](https://github.com/tiangolo). +* 💚 Fix/workaround GitHub Actions in Docker with git for FastAPI People. PR [#9169](https://github.com/tiangolo/fastapi/pull/9169) by [@tiangolo](https://github.com/tiangolo). +* ♻️ Refactor FastAPI Experts to use only discussions now that questions are migrated. PR [#9165](https://github.com/tiangolo/fastapi/pull/9165) by [@tiangolo](https://github.com/tiangolo). +* ⬆️ Upgrade analytics. PR [#6025](https://github.com/tiangolo/fastapi/pull/6025) by [@tiangolo](https://github.com/tiangolo). +* ⬆️ Upgrade and re-enable installing Typer-CLI. PR [#6008](https://github.com/tiangolo/fastapi/pull/6008) by [@tiangolo](https://github.com/tiangolo). + +## 0.92.0 (2023-02-14) + +🚨 This is a security fix. Please upgrade as soon as possible. + +### Upgrades + +* ⬆️ Upgrade Starlette to 0.25.0. PR [#5996](https://github.com/tiangolo/fastapi/pull/5996) by [@tiangolo](https://github.com/tiangolo). + * This solves a vulnerability that could allow denial of service attacks by using many small multipart fields/files (parts), consuming high CPU and memory. + * Only applications using forms (e.g. file uploads) could be affected. + * For most cases, upgrading won't have any breaking changes. + +## 0.91.0 (2023-02-10) + +### Upgrades + +* ⬆️ Upgrade Starlette version to `0.24.0` and refactor internals for compatibility. PR [#5985](https://github.com/tiangolo/fastapi/pull/5985) by [@tiangolo](https://github.com/tiangolo). + * This can solve nuanced errors when using middlewares. Before Starlette `0.24.0`, a new instance of each middleware class would be created when a new middleware was added. That normally was not a problem, unless the middleware class expected to be created only once, with only one instance, that happened in some cases. This upgrade would solve those cases (thanks [@adriangb](https://github.com/adriangb)! Starlette PR [#2017](https://github.com/encode/starlette/pull/2017)). Now the middleware class instances are created once, right before the first request (the first time the app is called). + * If you depended on that previous behavior, you might need to update your code. As always, make sure your tests pass before merging the upgrade. + +## 0.90.1 (2023-02-09) + +### Upgrades + +* ⬆️ Upgrade Starlette range to allow 0.23.1. PR [#5980](https://github.com/tiangolo/fastapi/pull/5980) by [@tiangolo](https://github.com/tiangolo). + +### Docs + +* ✏ Tweak wording to clarify `docs/en/docs/project-generation.md`. PR [#5930](https://github.com/tiangolo/fastapi/pull/5930) by [@chandra-deb](https://github.com/chandra-deb). +* ✏ Update Pydantic GitHub URLs. PR [#5952](https://github.com/tiangolo/fastapi/pull/5952) by [@yezz123](https://github.com/yezz123). +* 📝 Add opinion from Cisco. PR [#5981](https://github.com/tiangolo/fastapi/pull/5981) by [@tiangolo](https://github.com/tiangolo). + +### Translations + +* 🌐 Add Russian translation for `docs/ru/docs/tutorial/cookie-params.md`. PR [#5890](https://github.com/tiangolo/fastapi/pull/5890) by [@bnzone](https://github.com/bnzone). + +### Internal + +* ✏ Update `zip-docs.sh` internal script, remove extra space. PR [#5931](https://github.com/tiangolo/fastapi/pull/5931) by [@JuanPerdomo00](https://github.com/JuanPerdomo00). + +## 0.90.0 (2023-02-08) + +### Upgrades + +* ⬆️ Bump Starlette from 0.22.0 to 0.23.0. Initial PR [#5739](https://github.com/tiangolo/fastapi/pull/5739) by [@Kludex](https://github.com/Kludex). + +### Docs + +* 📝 Add article "Tortoise ORM / FastAPI 整合快速筆記" to External Links. PR [#5496](https://github.com/tiangolo/fastapi/pull/5496) by [@Leon0824](https://github.com/Leon0824). +* 👥 Update FastAPI People. PR [#5954](https://github.com/tiangolo/fastapi/pull/5954) by [@github-actions[bot]](https://github.com/apps/github-actions). +* 📝 Micro-tweak help docs. PR [#5960](https://github.com/tiangolo/fastapi/pull/5960) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Update new issue chooser to direct to GitHub Discussions. PR [#5948](https://github.com/tiangolo/fastapi/pull/5948) by [@tiangolo](https://github.com/tiangolo). +* 📝 Recommend GitHub Discussions for questions. PR [#5944](https://github.com/tiangolo/fastapi/pull/5944) by [@tiangolo](https://github.com/tiangolo). + +### Translations + +* 🌐 Add Russian translation for `docs/ru/docs/tutorial/body-fields.md`. PR [#5898](https://github.com/tiangolo/fastapi/pull/5898) by [@simatheone](https://github.com/simatheone). +* 🌐 Add Russian translation for `docs/ru/docs/help-fastapi.md`. PR [#5970](https://github.com/tiangolo/fastapi/pull/5970) by [@tiangolo](https://github.com/tiangolo). +* 🌐 Add Portuguese translation for `docs/pt/docs/tutorial/static-files.md`. PR [#5858](https://github.com/tiangolo/fastapi/pull/5858) by [@batlopes](https://github.com/batlopes). +* 🌐 Add Portuguese translation for `docs/pt/docs/tutorial/encoder.md`. PR [#5525](https://github.com/tiangolo/fastapi/pull/5525) by [@felipebpl](https://github.com/felipebpl). +* 🌐 Add Russian translation for `docs/ru/docs/contributing.md`. PR [#5870](https://github.com/tiangolo/fastapi/pull/5870) by [@Xewus](https://github.com/Xewus). + +### Internal + +* ⬆️ Upgrade Ubuntu version for docs workflow. PR [#5971](https://github.com/tiangolo/fastapi/pull/5971) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Update sponsors badges. PR [#5943](https://github.com/tiangolo/fastapi/pull/5943) by [@tiangolo](https://github.com/tiangolo). +* ✨ Compute FastAPI Experts including GitHub Discussions. PR [#5941](https://github.com/tiangolo/fastapi/pull/5941) by [@tiangolo](https://github.com/tiangolo). +* ⬆️ Upgrade isort and update pre-commit. PR [#5940](https://github.com/tiangolo/fastapi/pull/5940) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Add template for questions in Discussions. PR [#5920](https://github.com/tiangolo/fastapi/pull/5920) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Update Sponsor Budget Insight to Powens. PR [#5916](https://github.com/tiangolo/fastapi/pull/5916) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Update GitHub Sponsors badge data. PR [#5915](https://github.com/tiangolo/fastapi/pull/5915) by [@tiangolo](https://github.com/tiangolo). + +## 0.89.1 (2023-01-10) + +### Fixes + +* 🐛 Ignore Response classes on return annotation. PR [#5855](https://github.com/tiangolo/fastapi/pull/5855) by [@Kludex](https://github.com/Kludex). See the new docs in the PR below. + +### Docs + +* 📝 Update docs and examples for Response Model with Return Type Annotations, and update runtime error. PR [#5873](https://github.com/tiangolo/fastapi/pull/5873) by [@tiangolo](https://github.com/tiangolo). New docs at [Response Model - Return Type: Other Return Type Annotations](https://fastapi.tiangolo.com/tutorial/response-model/#other-return-type-annotations). +* 📝 Add External Link: FastAPI lambda container: serverless simplified. PR [#5784](https://github.com/tiangolo/fastapi/pull/5784) by [@rafrasenberg](https://github.com/rafrasenberg). + +### Translations + +* 🌐 Add Turkish translation for `docs/tr/docs/tutorial/first_steps.md`. PR [#5691](https://github.com/tiangolo/fastapi/pull/5691) by [@Kadermiyanyedi](https://github.com/Kadermiyanyedi). + +## 0.89.0 (2023-01-07) + +### Features + +* ✨ Add support for function return type annotations to declare the `response_model`. Initial PR [#1436](https://github.com/tiangolo/fastapi/pull/1436) by [@uriyyo](https://github.com/uriyyo). + +Now you can declare the return type / `response_model` in the function return type annotation: + +```python +from fastapi import FastAPI +from pydantic import BaseModel + +app = FastAPI() + + +class Item(BaseModel): + name: str + price: float + + +@app.get("/items/") +async def read_items() -> list[Item]: + return [ + Item(name="Portal Gun", price=42.0), + Item(name="Plumbus", price=32.0), + ] +``` + +FastAPI will use the return type annotation to perform: + +* Data validation +* Automatic documentation + * It could power automatic client generators +* **Data filtering** + +Before this version it was only supported via the `response_model` parameter. + +Read more about it in the new docs: [Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/). + +### Docs + +* 📝 Add External Link: Authorization on FastAPI with Casbin. PR [#5712](https://github.com/tiangolo/fastapi/pull/5712) by [@Xhy-5000](https://github.com/Xhy-5000). +* ✏ Fix typo in `docs/en/docs/async.md`. PR [#5785](https://github.com/tiangolo/fastapi/pull/5785) by [@Kingdageek](https://github.com/Kingdageek). +* ✏ Fix typo in `docs/en/docs/deployment/concepts.md`. PR [#5824](https://github.com/tiangolo/fastapi/pull/5824) by [@kelbyfaessler](https://github.com/kelbyfaessler). + +### Translations + +* 🌐 Add Russian translation for `docs/ru/docs/fastapi-people.md`. PR [#5577](https://github.com/tiangolo/fastapi/pull/5577) by [@Xewus](https://github.com/Xewus). +* 🌐 Fix typo in Chinese translation for `docs/zh/docs/benchmarks.md`. PR [#4269](https://github.com/tiangolo/fastapi/pull/4269) by [@15027668g](https://github.com/15027668g). +* 🌐 Add Korean translation for `docs/tutorial/cors.md`. PR [#3764](https://github.com/tiangolo/fastapi/pull/3764) by [@NinaHwang](https://github.com/NinaHwang). + +### Internal + +* ⬆ Update coverage[toml] requirement from <7.0,>=6.5.0 to >=6.5.0,<8.0. PR [#5801](https://github.com/tiangolo/fastapi/pull/5801) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Update uvicorn[standard] requirement from <0.19.0,>=0.12.0 to >=0.12.0,<0.21.0 for development. PR [#5795](https://github.com/tiangolo/fastapi/pull/5795) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump dawidd6/action-download-artifact from 2.24.2 to 2.24.3. PR [#5842](https://github.com/tiangolo/fastapi/pull/5842) by [@dependabot[bot]](https://github.com/apps/dependabot). +* 👥 Update FastAPI People. PR [#5825](https://github.com/tiangolo/fastapi/pull/5825) by [@github-actions[bot]](https://github.com/apps/github-actions). +* ⬆ Bump types-ujson from 5.5.0 to 5.6.0.0. PR [#5735](https://github.com/tiangolo/fastapi/pull/5735) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump pypa/gh-action-pypi-publish from 1.5.2 to 1.6.4. PR [#5750](https://github.com/tiangolo/fastapi/pull/5750) by [@dependabot[bot]](https://github.com/apps/dependabot). +* 👷 Add GitHub Action gate/check. PR [#5492](https://github.com/tiangolo/fastapi/pull/5492) by [@webknjaz](https://github.com/webknjaz). +* 🔧 Update sponsors, add Svix. PR [#5848](https://github.com/tiangolo/fastapi/pull/5848) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Remove Doist sponsor. PR [#5847](https://github.com/tiangolo/fastapi/pull/5847) by [@tiangolo](https://github.com/tiangolo). +* ⬆ Update sqlalchemy requirement from <=1.4.41,>=1.3.18 to >=1.3.18,<1.4.43. PR [#5540](https://github.com/tiangolo/fastapi/pull/5540) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump nwtgck/actions-netlify from 1.2.4 to 2.0.0. PR [#5757](https://github.com/tiangolo/fastapi/pull/5757) by [@dependabot[bot]](https://github.com/apps/dependabot). +* 👷 Refactor CI artifact upload/download for docs previews. PR [#5793](https://github.com/tiangolo/fastapi/pull/5793) by [@tiangolo](https://github.com/tiangolo). +* ⬆ Bump pypa/gh-action-pypi-publish from 1.5.1 to 1.5.2. PR [#5714](https://github.com/tiangolo/fastapi/pull/5714) by [@dependabot[bot]](https://github.com/apps/dependabot). +* 👥 Update FastAPI People. PR [#5722](https://github.com/tiangolo/fastapi/pull/5722) by [@github-actions[bot]](https://github.com/apps/github-actions). +* 🔧 Update sponsors, disable course bundle. PR [#5713](https://github.com/tiangolo/fastapi/pull/5713) by [@tiangolo](https://github.com/tiangolo). +* ⬆ Update typer[all] requirement from <0.7.0,>=0.6.1 to >=0.6.1,<0.8.0. PR [#5639](https://github.com/tiangolo/fastapi/pull/5639) by [@dependabot[bot]](https://github.com/apps/dependabot). + +## 0.88.0 (2022-11-27) + +### Upgrades + +* ⬆ Bump Starlette to version `0.22.0` to fix bad encoding for query parameters in new `TestClient`. PR [#5659](https://github.com/tiangolo/fastapi/pull/5659) by [@azogue](https://github.com/azogue). + +### Docs + +* ✏️ Fix typo in docs for `docs/en/docs/advanced/middleware.md`. PR [#5376](https://github.com/tiangolo/fastapi/pull/5376) by [@rifatrakib](https://github.com/rifatrakib). + +### Translations + +* 🌐 Add Portuguese translation for `docs/pt/docs/deployment/docker.md`. PR [#5663](https://github.com/tiangolo/fastapi/pull/5663) by [@ayr-ton](https://github.com/ayr-ton). + +### Internal + +* 👷 Tweak build-docs to improve CI performance. PR [#5699](https://github.com/tiangolo/fastapi/pull/5699) by [@tiangolo](https://github.com/tiangolo). +* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#5566](https://github.com/tiangolo/fastapi/pull/5566) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). +* ⬆️ Upgrade Ruff. PR [#5698](https://github.com/tiangolo/fastapi/pull/5698) by [@tiangolo](https://github.com/tiangolo). +* 👷 Remove pip cache for Smokeshow as it depends on a requirements.txt. PR [#5700](https://github.com/tiangolo/fastapi/pull/5700) by [@tiangolo](https://github.com/tiangolo). +* 💚 Fix pip cache for Smokeshow. PR [#5697](https://github.com/tiangolo/fastapi/pull/5697) by [@tiangolo](https://github.com/tiangolo). +* 👷 Fix and tweak CI cache handling. PR [#5696](https://github.com/tiangolo/fastapi/pull/5696) by [@tiangolo](https://github.com/tiangolo). +* 👷 Update `setup-python` action in tests to use new caching feature. PR [#5680](https://github.com/tiangolo/fastapi/pull/5680) by [@madkinsz](https://github.com/madkinsz). +* ⬆ Bump black from 22.8.0 to 22.10.0. PR [#5569](https://github.com/tiangolo/fastapi/pull/5569) by [@dependabot[bot]](https://github.com/apps/dependabot). + +## 0.87.0 (2022-11-13) + +Highlights of this release: + +* [Upgraded Starlette](https://github.com/encode/starlette/releases/tag/0.21.0) + * Now the `TestClient` is based on HTTPX instead of Requests. 🚀 + * There are some possible **breaking changes** in the `TestClient` usage, but [@Kludex](https://github.com/Kludex) built [bump-testclient](https://github.com/Kludex/bump-testclient) to help you automatize migrating your tests. Make sure you are using Git and that you can undo any unnecessary changes (false positive changes, etc) before using `bump-testclient`. +* New [WebSocketException (and docs)](https://fastapi.tiangolo.com/advanced/websockets/#using-depends-and-others), re-exported from Starlette. +* Upgraded and relaxed dependencies for package extras `all` (including new Uvicorn version), when you install `"fastapi[all]"`. +* New docs about how to [**Help Maintain FastAPI**](https://fastapi.tiangolo.com/help-fastapi/#help-maintain-fastapi). + +### Features + +* ⬆️ Upgrade and relax dependencies for extras "all". PR [#5634](https://github.com/tiangolo/fastapi/pull/5634) by [@tiangolo](https://github.com/tiangolo). +* ✨ Re-export Starlette's `WebSocketException` and add it to docs. PR [#5629](https://github.com/tiangolo/fastapi/pull/5629) by [@tiangolo](https://github.com/tiangolo). +* 📝 Update references to Requests for tests to HTTPX, and add HTTPX to extras. PR [#5628](https://github.com/tiangolo/fastapi/pull/5628) by [@tiangolo](https://github.com/tiangolo). +* ⬆ Upgrade Starlette to `0.21.0`, including the new [`TestClient` based on HTTPX](https://github.com/encode/starlette/releases/tag/0.21.0). PR [#5471](https://github.com/tiangolo/fastapi/pull/5471) by [@pawelrubin](https://github.com/pawelrubin). + +### Docs + +* ✏️ Tweak Help FastAPI from PR review after merging. PR [#5633](https://github.com/tiangolo/fastapi/pull/5633) by [@tiangolo](https://github.com/tiangolo). +* ✏️ Clarify docs on CORS. PR [#5627](https://github.com/tiangolo/fastapi/pull/5627) by [@paxcodes](https://github.com/paxcodes). +* 📝 Update Help FastAPI: Help Maintain FastAPI. PR [#5632](https://github.com/tiangolo/fastapi/pull/5632) by [@tiangolo](https://github.com/tiangolo). + +### Translations + +* 🌐 Fix highlight lines for Japanese translation for `docs/tutorial/query-params.md`. PR [#2969](https://github.com/tiangolo/fastapi/pull/2969) by [@ftnext](https://github.com/ftnext). +* 🌐 Add French translation for `docs/fr/docs/advanced/additional-status-code.md`. PR [#5477](https://github.com/tiangolo/fastapi/pull/5477) by [@axel584](https://github.com/axel584). +* 🌐 Add Portuguese translation for `docs/pt/docs/tutorial/request-forms-and-files.md`. PR [#5579](https://github.com/tiangolo/fastapi/pull/5579) by [@batlopes](https://github.com/batlopes). +* 🌐 Add Japanese translation for `docs/ja/docs/advanced/websockets.md`. PR [#4983](https://github.com/tiangolo/fastapi/pull/4983) by [@xryuseix](https://github.com/xryuseix). + +### Internal + +* ✨ Use Ruff for linting. PR [#5630](https://github.com/tiangolo/fastapi/pull/5630) by [@tiangolo](https://github.com/tiangolo). +* 🛠 Add Arabic issue number to Notify Translations GitHub Action. PR [#5610](https://github.com/tiangolo/fastapi/pull/5610) by [@tiangolo](https://github.com/tiangolo). +* ⬆ Bump dawidd6/action-download-artifact from 2.24.1 to 2.24.2. PR [#5609](https://github.com/tiangolo/fastapi/pull/5609) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump dawidd6/action-download-artifact from 2.24.0 to 2.24.1. PR [#5603](https://github.com/tiangolo/fastapi/pull/5603) by [@dependabot[bot]](https://github.com/apps/dependabot). +* 📝 Update coverage badge to use Samuel Colvin's Smokeshow. PR [#5585](https://github.com/tiangolo/fastapi/pull/5585) by [@tiangolo](https://github.com/tiangolo). + +## 0.86.0 (2022-11-03) + +### Features + +* ⬆ Add Python 3.11 to the officially supported versions. PR [#5587](https://github.com/tiangolo/fastapi/pull/5587) by [@tiangolo](https://github.com/tiangolo). +* ✅ Enable tests for Python 3.11. PR [#4881](https://github.com/tiangolo/fastapi/pull/4881) by [@tiangolo](https://github.com/tiangolo). + +### Fixes + +* 🐛 Close FormData (uploaded files) after the request is done. PR [#5465](https://github.com/tiangolo/fastapi/pull/5465) by [@adriangb](https://github.com/adriangb). + +### Docs + +* ✏ Fix typo in `docs/en/docs/tutorial/security/oauth2-jwt.md`. PR [#5584](https://github.com/tiangolo/fastapi/pull/5584) by [@vivekashok1221](https://github.com/vivekashok1221). + +### Translations + +* 🌐 Update wording in Chinese translation for `docs/zh/docs/python-types.md`. PR [#5416](https://github.com/tiangolo/fastapi/pull/5416) by [@supercaizehua](https://github.com/supercaizehua). +* 🌐 Add Russian translation for `docs/ru/docs/deployment/index.md`. PR [#5336](https://github.com/tiangolo/fastapi/pull/5336) by [@Xewus](https://github.com/Xewus). +* 🌐 Update Chinese translation for `docs/tutorial/security/oauth2-jwt.md`. PR [#3846](https://github.com/tiangolo/fastapi/pull/3846) by [@jaystone776](https://github.com/jaystone776). + +### Internal + +* 👷 Update FastAPI People to exclude bots: pre-commit-ci, dependabot. PR [#5586](https://github.com/tiangolo/fastapi/pull/5586) by [@tiangolo](https://github.com/tiangolo). +* 🎨 Format OpenAPI JSON in `test_starlette_exception.py`. PR [#5379](https://github.com/tiangolo/fastapi/pull/5379) by [@iudeen](https://github.com/iudeen). +* 👷 Switch from Codecov to Smokeshow plus pytest-cov to pure coverage for internal tests. PR [#5583](https://github.com/tiangolo/fastapi/pull/5583) by [@tiangolo](https://github.com/tiangolo). +* 👥 Update FastAPI People. PR [#5571](https://github.com/tiangolo/fastapi/pull/5571) by [@github-actions[bot]](https://github.com/apps/github-actions). + +## 0.85.2 (2022-10-31) + +### Docs + +* ✏ Fix grammar and add helpful links to dependencies in `docs/en/docs/async.md`. PR [#5432](https://github.com/tiangolo/fastapi/pull/5432) by [@pamelafox](https://github.com/pamelafox). +* ✏ Fix broken link in `alternatives.md`. PR [#5455](https://github.com/tiangolo/fastapi/pull/5455) by [@su-shubham](https://github.com/su-shubham). +* ✏ Fix typo in docs about contributing, for compatibility with `pip` in Zsh. PR [#5523](https://github.com/tiangolo/fastapi/pull/5523) by [@zhangbo2012](https://github.com/zhangbo2012). +* 📝 Fix typo in docs with examples for Python 3.10 instead of 3.9. PR [#5545](https://github.com/tiangolo/fastapi/pull/5545) by [@feliciss](https://github.com/feliciss). + +### Translations + +* 🌐 Add Portuguese translation for `docs/pt/docs/tutorial/request-forms.md`. PR [#4934](https://github.com/tiangolo/fastapi/pull/4934) by [@batlopes](https://github.com/batlopes). +* 🌐 Add Chinese translation for `docs/zh/docs/tutorial/dependencies/classes-as-dependencies.md`. PR [#4971](https://github.com/tiangolo/fastapi/pull/4971) by [@Zssaer](https://github.com/Zssaer). +* 🌐 Add French translation for `deployment/deta.md`. PR [#3692](https://github.com/tiangolo/fastapi/pull/3692) by [@rjNemo](https://github.com/rjNemo). +* 🌐 Update Chinese translation for `docs/zh/docs/tutorial/query-params-str-validations.md`. PR [#5255](https://github.com/tiangolo/fastapi/pull/5255) by [@hjlarry](https://github.com/hjlarry). +* 🌐 Add Chinese translation for `docs/zh/docs/tutorial/sql-databases.md`. PR [#4999](https://github.com/tiangolo/fastapi/pull/4999) by [@Zssaer](https://github.com/Zssaer). +* 🌐 Add Chinese translation for `docs/zh/docs/advanced/wsgi.md`. PR [#4505](https://github.com/tiangolo/fastapi/pull/4505) by [@ASpathfinder](https://github.com/ASpathfinder). +* 🌐 Add Portuguese translation for `docs/pt/docs/tutorial/body-multiple-params.md`. PR [#4111](https://github.com/tiangolo/fastapi/pull/4111) by [@lbmendes](https://github.com/lbmendes). +* 🌐 Add Portuguese translation for `docs/pt/docs/tutorial/path-params-numeric-validations.md`. PR [#4099](https://github.com/tiangolo/fastapi/pull/4099) by [@lbmendes](https://github.com/lbmendes). +* 🌐 Add French translation for `deployment/versions.md`. PR [#3690](https://github.com/tiangolo/fastapi/pull/3690) by [@rjNemo](https://github.com/rjNemo). +* 🌐 Add French translation for `docs/fr/docs/help-fastapi.md`. PR [#2233](https://github.com/tiangolo/fastapi/pull/2233) by [@JulianMaurin](https://github.com/JulianMaurin). +* 🌐 Fix typo in Chinese translation for `docs/zh/docs/tutorial/security/first-steps.md`. PR [#5530](https://github.com/tiangolo/fastapi/pull/5530) by [@yuki1sntSnow](https://github.com/yuki1sntSnow). +* 🌐 Add Portuguese translation for `docs/pt/docs/tutorial/response-status-code.md`. PR [#4922](https://github.com/tiangolo/fastapi/pull/4922) by [@batlopes](https://github.com/batlopes). +* 🔧 Add config for Tamil translations. PR [#5563](https://github.com/tiangolo/fastapi/pull/5563) by [@tiangolo](https://github.com/tiangolo). + +### Internal + +* ⬆ Bump internal dependency mypy from 0.971 to 0.982. PR [#5541](https://github.com/tiangolo/fastapi/pull/5541) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump nwtgck/actions-netlify from 1.2.3 to 1.2.4. PR [#5507](https://github.com/tiangolo/fastapi/pull/5507) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump internal dependency types-ujson from 5.4.0 to 5.5.0. PR [#5537](https://github.com/tiangolo/fastapi/pull/5537) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Bump dawidd6/action-download-artifact from 2.23.0 to 2.24.0. PR [#5508](https://github.com/tiangolo/fastapi/pull/5508) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ Update internal dependency pytest-cov requirement from <4.0.0,>=2.12.0 to >=2.12.0,<5.0.0. PR [#5539](https://github.com/tiangolo/fastapi/pull/5539) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#5536](https://github.com/tiangolo/fastapi/pull/5536) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). +* 🐛 Fix internal Trio test warnings. PR [#5547](https://github.com/tiangolo/fastapi/pull/5547) by [@samuelcolvin](https://github.com/samuelcolvin). +* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#5408](https://github.com/tiangolo/fastapi/pull/5408) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). +* ⬆️ Upgrade Typer to include Rich in scripts for docs. PR [#5502](https://github.com/tiangolo/fastapi/pull/5502) by [@tiangolo](https://github.com/tiangolo). +* 🐛 Fix calling `mkdocs` for languages as a subprocess to fix/enable MkDocs Material search plugin. PR [#5501](https://github.com/tiangolo/fastapi/pull/5501) by [@tiangolo](https://github.com/tiangolo). + +## 0.85.1 (2022-10-14) + +### Fixes + +* 🐛 Fix support for strings in OpenAPI status codes: `default`, `1XX`, `2XX`, `3XX`, `4XX`, `5XX`. PR [#5187](https://github.com/tiangolo/fastapi/pull/5187) by [@JarroVGIT](https://github.com/JarroVGIT). + +### Docs + +* 📝 Add WayScript x FastAPI Tutorial to External Links section. PR [#5407](https://github.com/tiangolo/fastapi/pull/5407) by [@moneeka](https://github.com/moneeka). + +### Internal + +* 👥 Update FastAPI People. PR [#5447](https://github.com/tiangolo/fastapi/pull/5447) by [@github-actions[bot]](https://github.com/apps/github-actions). +* 🔧 Disable Material for MkDocs search plugin. PR [#5495](https://github.com/tiangolo/fastapi/pull/5495) by [@tiangolo](https://github.com/tiangolo). +* 🔇 Ignore Trio warning in tests for CI. PR [#5483](https://github.com/tiangolo/fastapi/pull/5483) by [@samuelcolvin](https://github.com/samuelcolvin). + +## 0.85.0 (2022-09-15) + +### Features + +* ⬆ Upgrade version required of Starlette from `0.19.1` to `0.20.4`. Initial PR [#4820](https://github.com/tiangolo/fastapi/pull/4820) by [@Kludex](https://github.com/Kludex). + * This includes several bug fixes in Starlette. +* ⬆️ Upgrade Uvicorn max version in public extras: all. From `>=0.12.0,<0.18.0` to `>=0.12.0,<0.19.0`. PR [#5401](https://github.com/tiangolo/fastapi/pull/5401) by [@tiangolo](https://github.com/tiangolo). + +### Internal + +* ⬆️ Upgrade dependencies for doc and dev internal extras: Typer, Uvicorn. PR [#5400](https://github.com/tiangolo/fastapi/pull/5400) by [@tiangolo](https://github.com/tiangolo). +* ⬆️ Upgrade test dependencies: Black, HTTPX, databases, types-ujson. PR [#5399](https://github.com/tiangolo/fastapi/pull/5399) by [@tiangolo](https://github.com/tiangolo). +* ⬆️ Upgrade mypy and tweak internal type annotations. PR [#5398](https://github.com/tiangolo/fastapi/pull/5398) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Update test dependencies, upgrade Pytest, move dependencies from dev to test. PR [#5396](https://github.com/tiangolo/fastapi/pull/5396) by [@tiangolo](https://github.com/tiangolo). + +## 0.84.0 (2022-09-14) + +### Breaking Changes + +This version of FastAPI drops support for Python 3.6. 🔥 Please upgrade to a supported version of Python (3.7 or above), Python 3.6 reached the end-of-life a long time ago. 😅☠ + +* 🔧 Update package metadata, drop support for Python 3.6, move build internals from Flit to Hatch. PR [#5240](https://github.com/tiangolo/fastapi/pull/5240) by [@ofek](https://github.com/ofek). + +## 0.83.0 (2022-09-11) + +🚨 This is probably the last release (or one of the last releases) to support Python 3.6. 🔥 + +Python 3.6 reached the [end-of-life and is no longer supported by Python](https://www.python.org/downloads/release/python-3615/) since around a year ago. + +You hopefully updated to a supported version of Python a while ago. If you haven't, you really should. + +### Features + +* ✨ Add support in `jsonable_encoder` for include and exclude with dataclasses. PR [#4923](https://github.com/tiangolo/fastapi/pull/4923) by [@DCsunset](https://github.com/DCsunset). + +### Fixes + +* 🐛 Fix `RuntimeError` raised when `HTTPException` has a status code with no content. PR [#5365](https://github.com/tiangolo/fastapi/pull/5365) by [@iudeen](https://github.com/iudeen). +* 🐛 Fix empty response body when default `status_code` is empty but the `Response` parameter with `response.status_code` is set. PR [#5360](https://github.com/tiangolo/fastapi/pull/5360) by [@tmeckel](https://github.com/tmeckel). + +### Docs + +* 📝 Update `SECURITY.md`. PR [#5377](https://github.com/tiangolo/fastapi/pull/5377) by [@Kludex](https://github.com/Kludex). + +### Internal + +* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#5352](https://github.com/tiangolo/fastapi/pull/5352) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). + +## 0.82.0 (2022-09-04) + +🚨 This is probably the last release (or one of the last releases) to support Python 3.6. 🔥 + +Python 3.6 reached the [end-of-life and is no longer supported by Python](https://www.python.org/downloads/release/python-3615/) since around a year ago. + +You hopefully updated to a supported version of Python a while ago. If you haven't, you really should. + +### Features + +* ✨ Export `WebSocketState` in `fastapi.websockets`. PR [#4376](https://github.com/tiangolo/fastapi/pull/4376) by [@matiuszka](https://github.com/matiuszka). +* ✨ Support Python internal description on Pydantic model's docstring. PR [#3032](https://github.com/tiangolo/fastapi/pull/3032) by [@Kludex](https://github.com/Kludex). +* ✨ Update `ORJSONResponse` to support non `str` keys and serializing Numpy arrays. PR [#3892](https://github.com/tiangolo/fastapi/pull/3892) by [@baby5](https://github.com/baby5). + +### Fixes + +* 🐛 Allow exit code for dependencies with `yield` to always execute, by removing capacity limiter for them, to e.g. allow closing DB connections without deadlocks. PR [#5122](https://github.com/tiangolo/fastapi/pull/5122) by [@adriangb](https://github.com/adriangb). +* 🐛 Fix FastAPI People GitHub Action: set HTTPX timeout for GraphQL query request. PR [#5222](https://github.com/tiangolo/fastapi/pull/5222) by [@iudeen](https://github.com/iudeen). +* 🐛 Make sure a parameter defined as required is kept required in OpenAPI even if defined as optional in another dependency. PR [#4319](https://github.com/tiangolo/fastapi/pull/4319) by [@cd17822](https://github.com/cd17822). +* 🐛 Fix support for path parameters in WebSockets. PR [#3879](https://github.com/tiangolo/fastapi/pull/3879) by [@davidbrochart](https://github.com/davidbrochart). + +### Docs + +* ✏ Update Hypercorn link, now pointing to GitHub. PR [#5346](https://github.com/tiangolo/fastapi/pull/5346) by [@baconfield](https://github.com/baconfield). +* ✏ Tweak wording in `docs/en/docs/advanced/dataclasses.md`. PR [#3698](https://github.com/tiangolo/fastapi/pull/3698) by [@pfackeldey](https://github.com/pfackeldey). +* 📝 Add note about Python 3.10 `X | Y` operator in explanation about Response Models. PR [#5307](https://github.com/tiangolo/fastapi/pull/5307) by [@MendyLanda](https://github.com/MendyLanda). +* 📝 Add link to New Relic article: "How to monitor FastAPI application performance using Python agent". PR [#5260](https://github.com/tiangolo/fastapi/pull/5260) by [@sjyothi54](https://github.com/sjyothi54). +* 📝 Update docs for `ORJSONResponse` with details about improving performance. PR [#2615](https://github.com/tiangolo/fastapi/pull/2615) by [@falkben](https://github.com/falkben). +* 📝 Add docs for creating a custom Response class. PR [#5331](https://github.com/tiangolo/fastapi/pull/5331) by [@tiangolo](https://github.com/tiangolo). +* 📝 Add tip about using alias for form data fields. PR [#5329](https://github.com/tiangolo/fastapi/pull/5329) by [@tiangolo](https://github.com/tiangolo). + +### Translations + +* 🌐 Add Russian translation for `docs/ru/docs/features.md`. PR [#5315](https://github.com/tiangolo/fastapi/pull/5315) by [@Xewus](https://github.com/Xewus). +* 🌐 Update Chinese translation for `docs/zh/docs/tutorial/request-files.md`. PR [#4529](https://github.com/tiangolo/fastapi/pull/4529) by [@ASpathfinder](https://github.com/ASpathfinder). +* 🌐 Add Chinese translation for `docs/zh/docs/tutorial/encoder.md`. PR [#4969](https://github.com/tiangolo/fastapi/pull/4969) by [@Zssaer](https://github.com/Zssaer). +* 🌐 Fix MkDocs file line for Portuguese translation of `background-task.md`. PR [#5242](https://github.com/tiangolo/fastapi/pull/5242) by [@ComicShrimp](https://github.com/ComicShrimp). + +### Internal + +* 👥 Update FastAPI People. PR [#5347](https://github.com/tiangolo/fastapi/pull/5347) by [@github-actions[bot]](https://github.com/apps/github-actions). +* ⬆ Bump dawidd6/action-download-artifact from 2.22.0 to 2.23.0. PR [#5321](https://github.com/tiangolo/fastapi/pull/5321) by [@dependabot[bot]](https://github.com/apps/dependabot). +* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#5318](https://github.com/tiangolo/fastapi/pull/5318) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). +* ✏ Fix a small code highlight line error. PR [#5256](https://github.com/tiangolo/fastapi/pull/5256) by [@hjlarry](https://github.com/hjlarry). +* ♻ Internal small refactor, move `operation_id` parameter position in delete method for consistency with the code. PR [#4474](https://github.com/tiangolo/fastapi/pull/4474) by [@hiel](https://github.com/hiel). +* 🔧 Update sponsors, disable ImgWhale. PR [#5338](https://github.com/tiangolo/fastapi/pull/5338) by [@tiangolo](https://github.com/tiangolo). + +## 0.81.0 (2022-08-26) + +### Features + +* ✨ Add ReDoc `