mirror of https://github.com/tiangolo/fastapi.git
Merge branch 'master' into simplify_deps_code
This commit is contained in:
commit
826cf946f3
|
|
@ -17,6 +17,7 @@ lang-all:
|
|||
- docs/*/docs/**
|
||||
- all-globs-to-all-files:
|
||||
- '!docs/en/docs/**'
|
||||
- '!docs/*/**/_*.md'
|
||||
- '!fastapi/**'
|
||||
- '!pyproject.toml'
|
||||
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ jobs:
|
|||
outputs:
|
||||
docs: ${{ steps.filter.outputs.docs }}
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v6
|
||||
# For pull requests it's not necessary to checkout the code but for the main branch it is
|
||||
- uses: dorny/paths-filter@v3
|
||||
id: filter
|
||||
|
|
@ -32,12 +32,9 @@ jobs:
|
|||
- docs/**
|
||||
- docs_src/**
|
||||
- requirements-docs.txt
|
||||
- requirements-docs-insiders.txt
|
||||
- pyproject.toml
|
||||
- mkdocs.yml
|
||||
- mkdocs.insiders.yml
|
||||
- mkdocs.maybe-insiders.yml
|
||||
- mkdocs.no-insiders.yml
|
||||
- mkdocs.env.yml
|
||||
- .github/workflows/build-docs.yml
|
||||
- .github/workflows/deploy-docs.yml
|
||||
- scripts/mkdocs_hooks.py
|
||||
|
|
@ -48,7 +45,7 @@ jobs:
|
|||
outputs:
|
||||
langs: ${{ steps.show-langs.outputs.langs }}
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v6
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
|
|
@ -63,12 +60,6 @@ jobs:
|
|||
pyproject.toml
|
||||
- name: Install docs extras
|
||||
run: uv pip install -r requirements-docs.txt
|
||||
# Install MkDocs Material Insiders here just to put it in the cache for the rest of the steps
|
||||
- name: Install Material for MkDocs Insiders
|
||||
if: ( github.event_name != 'pull_request' || github.secret_source == 'Actions' )
|
||||
run: uv pip install -r requirements-docs-insiders.txt
|
||||
env:
|
||||
TOKEN: ${{ secrets.FASTAPI_MKDOCS_MATERIAL_INSIDERS }}
|
||||
- name: Verify Docs
|
||||
run: python ./scripts/docs.py verify-docs
|
||||
- name: Export Language Codes
|
||||
|
|
@ -90,7 +81,7 @@ jobs:
|
|||
env:
|
||||
GITHUB_CONTEXT: ${{ toJson(github) }}
|
||||
run: echo "$GITHUB_CONTEXT"
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v6
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
|
|
@ -105,11 +96,6 @@ jobs:
|
|||
pyproject.toml
|
||||
- name: Install docs extras
|
||||
run: uv pip install -r requirements-docs.txt
|
||||
- name: Install Material for MkDocs Insiders
|
||||
if: ( github.event_name != 'pull_request' || github.secret_source == 'Actions' )
|
||||
run: uv pip install -r requirements-docs-insiders.txt
|
||||
env:
|
||||
TOKEN: ${{ secrets.FASTAPI_MKDOCS_MATERIAL_INSIDERS }}
|
||||
- name: Update Languages
|
||||
run: python ./scripts/docs.py update-languages
|
||||
- uses: actions/cache@v4
|
||||
|
|
@ -118,7 +104,7 @@ jobs:
|
|||
path: docs/${{ matrix.lang }}/.cache
|
||||
- name: Build Docs
|
||||
run: python ./scripts/docs.py build-lang ${{ matrix.lang }}
|
||||
- uses: actions/upload-artifact@v4
|
||||
- uses: actions/upload-artifact@v5
|
||||
with:
|
||||
name: docs-site-${{ matrix.lang }}
|
||||
path: ./site/**
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ jobs:
|
|||
env:
|
||||
GITHUB_CONTEXT: ${{ toJson(github) }}
|
||||
run: echo "$GITHUB_CONTEXT"
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v6
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ jobs:
|
|||
env:
|
||||
GITHUB_CONTEXT: ${{ toJson(github) }}
|
||||
run: echo "$GITHUB_CONTEXT"
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v6
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
|
|
@ -49,7 +49,7 @@ jobs:
|
|||
run: |
|
||||
rm -rf ./site
|
||||
mkdir ./site
|
||||
- uses: actions/download-artifact@v5
|
||||
- uses: actions/download-artifact@v6
|
||||
with:
|
||||
path: ./site/
|
||||
pattern: docs-site-*
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ jobs:
|
|||
env:
|
||||
GITHUB_CONTEXT: ${{ toJson(github) }}
|
||||
run: echo "$GITHUB_CONTEXT"
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v6
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
|
|
|
|||
|
|
@ -24,6 +24,8 @@ jobs:
|
|||
env:
|
||||
GITHUB_CONTEXT: ${{ toJson(github) }}
|
||||
run: echo "$GITHUB_CONTEXT"
|
||||
# pin to actions/checkout@v5 for compatibility with latest-changes
|
||||
# Ref: https://github.com/actions/checkout/issues/2313
|
||||
- uses: actions/checkout@v5
|
||||
with:
|
||||
# To allow latest-changes to commit to the main branch
|
||||
|
|
@ -34,7 +36,7 @@ jobs:
|
|||
if: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.debug_enabled == 'true' }}
|
||||
with:
|
||||
limit-access-to-actor: true
|
||||
- uses: tiangolo/latest-changes@0.4.0
|
||||
- uses: tiangolo/latest-changes@0.4.1
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
latest_changes_file: docs/en/docs/release-notes.md
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ jobs:
|
|||
env:
|
||||
GITHUB_CONTEXT: ${{ toJson(github) }}
|
||||
run: echo "$GITHUB_CONTEXT"
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v6
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ jobs:
|
|||
env:
|
||||
GITHUB_CONTEXT: ${{ toJson(github) }}
|
||||
run: echo "$GITHUB_CONTEXT"
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v6
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
|
|
|
|||
|
|
@ -0,0 +1,88 @@
|
|||
name: pre-commit
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types:
|
||||
- opened
|
||||
- synchronize
|
||||
|
||||
env:
|
||||
IS_FORK: ${{ github.event.pull_request.head.repo.full_name != github.repository }}
|
||||
|
||||
jobs:
|
||||
pre-commit:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Dump GitHub context
|
||||
env:
|
||||
GITHUB_CONTEXT: ${{ toJson(github) }}
|
||||
run: echo "$GITHUB_CONTEXT"
|
||||
- uses: actions/checkout@v5
|
||||
name: Checkout PR for own repo
|
||||
if: env.IS_FORK == 'false'
|
||||
with:
|
||||
# To be able to commit it needs more than the last commit
|
||||
ref: ${{ github.head_ref }}
|
||||
# A token other than the default GITHUB_TOKEN is needed to be able to trigger CI
|
||||
token: ${{ secrets.PRE_COMMIT }}
|
||||
# pre-commit lite ci needs the default checkout configs to work
|
||||
- uses: actions/checkout@v5
|
||||
name: Checkout PR for fork
|
||||
if: env.IS_FORK == 'true'
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: "3.14"
|
||||
- name: Setup uv
|
||||
uses: astral-sh/setup-uv@v7
|
||||
with:
|
||||
cache-dependency-glob: |
|
||||
requirements**.txt
|
||||
pyproject.toml
|
||||
uv.lock
|
||||
- name: Install Dependencies
|
||||
run: |
|
||||
uv venv
|
||||
uv pip install -r requirements.txt
|
||||
- name: Run pre-commit
|
||||
id: precommit
|
||||
run: |
|
||||
# Fetch the base branch for comparison
|
||||
git fetch origin ${{ github.base_ref }}
|
||||
uvx pre-commit run --from-ref origin/${{ github.base_ref }} --to-ref HEAD --show-diff-on-failure
|
||||
continue-on-error: true
|
||||
- name: Commit and push changes
|
||||
if: env.IS_FORK == 'false'
|
||||
run: |
|
||||
git config user.name "github-actions[bot]"
|
||||
git config user.email "github-actions[bot]@users.noreply.github.com"
|
||||
git add -A
|
||||
if git diff --staged --quiet; then
|
||||
echo "No changes to commit"
|
||||
else
|
||||
git commit -m "🎨 Auto format"
|
||||
git push
|
||||
fi
|
||||
- uses: pre-commit-ci/lite-action@v1.1.0
|
||||
if: env.IS_FORK == 'true'
|
||||
with:
|
||||
msg: 🎨 Auto format
|
||||
- name: Error out on pre-commit errors
|
||||
if: steps.precommit.outcome == 'failure'
|
||||
run: exit 1
|
||||
|
||||
# https://github.com/marketplace/actions/alls-green#why
|
||||
pre-commit-alls-green: # This job does nothing and is only used for the branch protection
|
||||
if: always()
|
||||
needs:
|
||||
- pre-commit
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Dump GitHub context
|
||||
env:
|
||||
GITHUB_CONTEXT: ${{ toJson(github) }}
|
||||
run: echo "$GITHUB_CONTEXT"
|
||||
- name: Decide whether the needed jobs succeeded or failed
|
||||
uses: re-actors/alls-green@release/v1
|
||||
with:
|
||||
jobs: ${{ toJSON(needs) }}
|
||||
|
|
@ -20,7 +20,7 @@ jobs:
|
|||
env:
|
||||
GITHUB_CONTEXT: ${{ toJson(github) }}
|
||||
run: echo "$GITHUB_CONTEXT"
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v6
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ jobs:
|
|||
env:
|
||||
GITHUB_CONTEXT: ${{ toJson(github) }}
|
||||
run: echo "$GITHUB_CONTEXT"
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: '3.9'
|
||||
|
|
@ -34,7 +34,7 @@ jobs:
|
|||
requirements**.txt
|
||||
pyproject.toml
|
||||
- run: uv pip install -r requirements-github-actions.txt
|
||||
- uses: actions/download-artifact@v5
|
||||
- uses: actions/download-artifact@v6
|
||||
with:
|
||||
name: coverage-html
|
||||
path: htmlcov
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ jobs:
|
|||
env:
|
||||
GITHUB_CONTEXT: ${{ toJson(github) }}
|
||||
run: echo "$GITHUB_CONTEXT"
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v6
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ jobs:
|
|||
env:
|
||||
GITHUB_CONTEXT: ${{ toJson(github) }}
|
||||
run: echo "$GITHUB_CONTEXT"
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v6
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ jobs:
|
|||
env:
|
||||
GITHUB_CONTEXT: ${{ toJson(github) }}
|
||||
run: echo "$GITHUB_CONTEXT"
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v6
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
|
|
@ -65,7 +65,7 @@ jobs:
|
|||
env:
|
||||
GITHUB_CONTEXT: ${{ toJson(github) }}
|
||||
run: echo "$GITHUB_CONTEXT"
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v6
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
|
|
@ -97,7 +97,7 @@ jobs:
|
|||
COVERAGE_FILE: coverage/.coverage.${{ runner.os }}-py${{ matrix.python-version }}
|
||||
CONTEXT: ${{ runner.os }}-py${{ matrix.python-version }}
|
||||
- name: Store coverage files
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v5
|
||||
with:
|
||||
name: coverage-${{ matrix.python-version }}-${{ matrix.pydantic-version }}
|
||||
path: coverage
|
||||
|
|
@ -111,7 +111,7 @@ jobs:
|
|||
env:
|
||||
GITHUB_CONTEXT: ${{ toJson(github) }}
|
||||
run: echo "$GITHUB_CONTEXT"
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: '3.8'
|
||||
|
|
@ -126,7 +126,7 @@ jobs:
|
|||
- name: Install Dependencies
|
||||
run: uv pip install -r requirements-tests.txt
|
||||
- name: Get coverage files
|
||||
uses: actions/download-artifact@v5
|
||||
uses: actions/download-artifact@v6
|
||||
with:
|
||||
pattern: coverage-*
|
||||
path: coverage
|
||||
|
|
@ -136,7 +136,7 @@ jobs:
|
|||
- run: coverage report
|
||||
- run: coverage html --title "Coverage for ${{ github.sha }}"
|
||||
- name: Store coverage HTML
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v5
|
||||
with:
|
||||
name: coverage-html
|
||||
path: htmlcov
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ jobs:
|
|||
env:
|
||||
GITHUB_CONTEXT: ${{ toJson(github) }}
|
||||
run: echo "$GITHUB_CONTEXT"
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v6
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ jobs:
|
|||
env:
|
||||
GITHUB_CONTEXT: ${{ toJson(github) }}
|
||||
run: echo "$GITHUB_CONTEXT"
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v6
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
|
|
|
|||
|
|
@ -28,3 +28,6 @@ archive.zip
|
|||
|
||||
# macOS
|
||||
.DS_Store
|
||||
|
||||
# Ignore while the setup still depends on requirements.txt files
|
||||
uv.lock
|
||||
|
|
|
|||
|
|
@ -1,9 +1,7 @@
|
|||
# See https://pre-commit.com for more information
|
||||
# See https://pre-commit.com/hooks.html for more hooks
|
||||
default_language_version:
|
||||
python: python3.10
|
||||
repos:
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: v6.0.0
|
||||
hooks:
|
||||
- id: check-added-large-files
|
||||
|
|
@ -13,13 +11,19 @@ repos:
|
|||
- --unsafe
|
||||
- id: end-of-file-fixer
|
||||
- id: trailing-whitespace
|
||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||
rev: v0.14.1
|
||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||
rev: v0.14.3
|
||||
hooks:
|
||||
- id: ruff
|
||||
args:
|
||||
- --fix
|
||||
- id: ruff-format
|
||||
ci:
|
||||
autofix_commit_msg: 🎨 [pre-commit.ci] Auto format from pre-commit.com hooks
|
||||
autoupdate_commit_msg: ⬆ [pre-commit.ci] pre-commit autoupdate
|
||||
- repo: local
|
||||
hooks:
|
||||
- id: local-script
|
||||
language: unsupported
|
||||
name: local script
|
||||
entry: uv run ./scripts/docs.py add-permalinks-pages
|
||||
args:
|
||||
- --update-existing
|
||||
files: ^docs/en/docs/.*\.md$
|
||||
|
|
|
|||
61
README.md
61
README.md
|
|
@ -40,11 +40,16 @@ The key features are:
|
|||
* **Robust**: Get production-ready code. With automatic interactive documentation.
|
||||
* **Standards-based**: Based on (and fully compatible with) the open standards for APIs: <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank">OpenAPI</a> (previously known as Swagger) and <a href="https://json-schema.org/" class="external-link" target="_blank">JSON Schema</a>.
|
||||
|
||||
<small>* estimation based on tests on an internal development team, building production applications.</small>
|
||||
<small>* estimation based on tests conducted by an internal development team, building production applications.</small>
|
||||
|
||||
## Sponsors
|
||||
|
||||
<!-- sponsors -->
|
||||
### Keystone Sponsor
|
||||
|
||||
<a href="https://fastapicloud.com" target="_blank" title="FastAPI Cloud. By the same team behind FastAPI. You code. We Cloud."><img src="https://fastapi.tiangolo.com/img/sponsors/fastapicloud.png"></a>
|
||||
|
||||
### Gold and Silver Sponsors
|
||||
|
||||
<a href="https://blockbee.io?ref=fastapi" target="_blank" title="BlockBee Cryptocurrency Payment Gateway"><img src="https://fastapi.tiangolo.com/img/sponsors/blockbee.png"></a>
|
||||
<a href="https://github.com/scalar/scalar/?utm_source=fastapi&utm_medium=website&utm_campaign=main-badge" target="_blank" title="Scalar: Beautiful Open-Source API References from Swagger/OpenAPI files"><img src="https://fastapi.tiangolo.com/img/sponsors/scalar.svg"></a>
|
||||
|
|
@ -55,6 +60,8 @@ The key features are:
|
|||
<a href="https://www.coderabbit.ai/?utm_source=fastapi&utm_medium=badge&utm_campaign=fastapi" target="_blank" title="Cut Code Review Time & Bugs in Half with CodeRabbit"><img src="https://fastapi.tiangolo.com/img/sponsors/coderabbit.png"></a>
|
||||
<a href="https://subtotal.com/?utm_source=fastapi&utm_medium=sponsorship&utm_campaign=open-source" target="_blank" title="The Gold Standard in Retail Account Linking"><img src="https://fastapi.tiangolo.com/img/sponsors/subtotal.svg"></a>
|
||||
<a href="https://docs.railway.com/guides/fastapi?utm_medium=integration&utm_source=docs&utm_campaign=fastapi" target="_blank" title="Deploy enterprise applications at startup speed"><img src="https://fastapi.tiangolo.com/img/sponsors/railway.png"></a>
|
||||
<a href="https://serpapi.com/?utm_source=fastapi_website" target="_blank" title="SerpApi: Web Search API"><img src="https://fastapi.tiangolo.com/img/sponsors/serpapi.png"></a>
|
||||
<a href="https://www.greptile.com/?utm_source=fastapi&utm_medium=sponsorship&utm_campaign=fastapi_sponsor_page" target="_blank" title="Greptile: The AI Code Reviewer"><img src="https://fastapi.tiangolo.com/img/sponsors/greptile.png"></a>
|
||||
<a href="https://databento.com/?utm_source=fastapi&utm_medium=sponsor&utm_content=display" target="_blank" title="Pay as you go for market data"><img src="https://fastapi.tiangolo.com/img/sponsors/databento.svg"></a>
|
||||
<a href="https://speakeasy.com/editor?utm_source=fastapi+repo&utm_medium=github+sponsorship" target="_blank" title="SDKs for your API | Speakeasy"><img src="https://fastapi.tiangolo.com/img/sponsors/speakeasy.png"></a>
|
||||
<a href="https://www.svix.com/" target="_blank" title="Svix - Webhooks as a service"><img src="https://fastapi.tiangolo.com/img/sponsors/svix.svg"></a>
|
||||
|
|
@ -446,6 +453,58 @@ For a more complete example including more features, see the <a href="https://fa
|
|||
* **Cookie Sessions**
|
||||
* ...and more.
|
||||
|
||||
### Deploy your app (optional)
|
||||
|
||||
You can optionally deploy your FastAPI app to <a href="https://fastapicloud.com" class="external-link" target="_blank">FastAPI Cloud</a>, go and join the waiting list if you haven't. 🚀
|
||||
|
||||
If you already have a **FastAPI Cloud** account (we invited you from the waiting list 😉), you can deploy your application with one command.
|
||||
|
||||
Before deploying, make sure you are logged in:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ fastapi login
|
||||
|
||||
You are logged in to FastAPI Cloud 🚀
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
Then deploy your app:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ fastapi deploy
|
||||
|
||||
Deploying to FastAPI Cloud...
|
||||
|
||||
✅ Deployment successful!
|
||||
|
||||
🐔 Ready the chicken! Your app is ready at https://myapp.fastapicloud.dev
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
That's it! Now you can access your app at that URL. ✨
|
||||
|
||||
#### About FastAPI Cloud
|
||||
|
||||
**<a href="https://fastapicloud.com" class="external-link" target="_blank">FastAPI Cloud</a>** is built by the same author and team behind **FastAPI**.
|
||||
|
||||
It streamlines the process of **building**, **deploying**, and **accessing** an API with minimal effort.
|
||||
|
||||
It brings the same **developer experience** of building apps with FastAPI to **deploying** them to the cloud. 🎉
|
||||
|
||||
FastAPI Cloud is the primary sponsor and funding provider for the *FastAPI and friends* open source projects. ✨
|
||||
|
||||
#### Deploy to other cloud providers
|
||||
|
||||
FastAPI is open source and based on standards. You can deploy FastAPI apps to any cloud provider you choose.
|
||||
|
||||
Follow your cloud provider's guides to deploy FastAPI apps with them. 🤓
|
||||
|
||||
## Performance
|
||||
|
||||
Independent TechEmpower benchmarks show **FastAPI** applications running under Uvicorn as <a href="https://www.techempower.com/benchmarks/#section=test&runid=7464e520-0dc2-473d-bd34-dbdfd7e85911&hw=ph&test=query&l=zijzen-7" class="external-link" target="_blank">one of the fastest Python frameworks available</a>, only below Starlette and Uvicorn themselves (used internally by FastAPI). (*)
|
||||
|
|
|
|||
|
|
@ -443,7 +443,7 @@ Für einige sprachspezifische Anweisungen, siehe z. B. den Abschnitt `### Headin
|
|||
* die Workload
|
||||
|
||||
* das Deployment
|
||||
* bereitstellen
|
||||
* deployen
|
||||
|
||||
* das SDK
|
||||
* das Software Development Kit
|
||||
|
|
|
|||
|
|
@ -70,12 +70,22 @@ Wenn Sie das hier alles verstanden haben, wissen Sie bereits, wie diese Sicherhe
|
|||
|
||||
Sie benötigen diese technischen Details höchstwahrscheinlich nicht.
|
||||
|
||||
Diese Details sind hauptsächlich nützlich, wenn Sie eine FastAPI-Anwendung haben, die älter als 0.118.0 ist, und Sie auf Probleme mit Abhängigkeiten mit `yield` stoßen.
|
||||
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.
|
||||
|
|
@ -134,7 +144,7 @@ Dies wurde in Version 0.110.0 geändert, um unbehandelten Speicherverbrauch durc
|
|||
|
||||
### Hintergrundtasks und Abhängigkeiten mit `yield`, Technische Details { #background-tasks-and-dependencies-with-yield-technical-details }
|
||||
|
||||
Vor FastAPI 0.106.0 war das Werfen von Exceptions nach `yield` nicht möglich, der Exit-Code in Abhängigkeiten mit `yield` wurde ausgeführt, nachdem die Response gesendet wurde, sodass [Exceptionhandler](../handling-errors.md#install-custom-exception-handlers){.internal-link target=_blank} bereits ausgeführt worden wären.
|
||||
Vor FastAPI 0.106.0 war das Werfen von Exceptions nach `yield` nicht möglich, der Exit-Code in Abhängigkeiten mit `yield` wurde ausgeführt, nachdem die Response gesendet wurde, sodass [Exceptionhandler](../tutorial/handling-errors.md#install-custom-exception-handlers){.internal-link target=_blank} bereits ausgeführt worden wären.
|
||||
|
||||
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.
|
||||
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ Wenn Sie mehr über HTTPS erfahren möchten, lesen Sie den Leitfaden [Über HTTP
|
|||
|
||||
///
|
||||
|
||||
### Wie Proxy-Forwarded-Header funktionieren
|
||||
### 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:
|
||||
|
||||
|
|
@ -228,7 +228,7 @@ Die Übergabe des `root_path` an `FastAPI` wäre das Äquivalent zur Übergabe d
|
|||
|
||||
Beachten Sie, dass der Server (Uvicorn) diesen `root_path` für nichts anderes verwendet als für die Weitergabe an die Anwendung.
|
||||
|
||||
Aber wenn Sie mit Ihrem Browser auf <a href="http://127.0.0.1:8000" class="external-link" target="_blank">http://127.0.0.1:8000/app</a> gehen, sehen Sie die normale Response:
|
||||
Aber wenn Sie mit Ihrem Browser auf <a href="http://127.0.0.1:8000/app" class="external-link" target="_blank">http://127.0.0.1:8000/app</a> gehen, sehen Sie die normale Response:
|
||||
|
||||
```JSON
|
||||
{
|
||||
|
|
@ -443,6 +443,14 @@ 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:
|
||||
|
|
|
|||
|
|
@ -1,16 +1,24 @@
|
|||
# FastAPI bei Cloudanbietern bereitstellen { #deploy-fastapi-on-cloud-providers }
|
||||
# FastAPI bei Cloudanbietern deployen { #deploy-fastapi-on-cloud-providers }
|
||||
|
||||
Sie können praktisch **jeden Cloudanbieter** verwenden, um Ihre FastAPI-Anwendung bereitzustellen.
|
||||
|
||||
In den meisten Fällen bieten die großen Cloudanbieter Anleitungen zum Bereitstellen von FastAPI an.
|
||||
In den meisten Fällen bieten die großen Cloudanbieter Anleitungen zum Deployment von FastAPI an.
|
||||
|
||||
## FastAPI Cloud { #fastapi-cloud }
|
||||
|
||||
**<a href="https://fastapicloud.com" class="external-link" target="_blank">FastAPI Cloud</a>** wurde vom selben Autor und Team hinter **FastAPI** entwickelt.
|
||||
|
||||
Es vereinfacht den Prozess des **Erstellens**, **Deployens** und **Zugreifens** auf eine API mit minimalem Aufwand.
|
||||
|
||||
Es bringt die gleiche **Developer-Experience** beim Erstellen von Apps mit FastAPI auch zum **Deployment** in der Cloud. 🎉
|
||||
|
||||
FastAPI Cloud ist der Hauptsponsor und Finanzierungsgeber für die *FastAPI and friends* Open-Source-Projekte. ✨
|
||||
|
||||
## Cloudanbieter – Sponsoren { #cloud-providers-sponsors }
|
||||
|
||||
Einige Cloudanbieter ✨ [**sponsern FastAPI**](../help-fastapi.md#sponsor-the-author){.internal-link target=_blank} ✨, dies stellt die kontinuierliche und gesunde **Entwicklung** von FastAPI und seinem **Ökosystem** sicher.
|
||||
Einige andere Cloudanbieter ✨ [**sponsern FastAPI**](../help-fastapi.md#sponsor-the-author){.internal-link target=_blank} ✨ ebenfalls. 🙇
|
||||
|
||||
Und es zeigt ihr wahres Engagement für FastAPI und seine **Community** (Sie), da sie Ihnen nicht nur einen **guten Service** bieten möchten, sondern auch sicherstellen möchten, dass Sie ein **gutes und gesundes Framework**, FastAPI, haben. 🙇
|
||||
|
||||
Vielleicht möchten Sie deren Dienste ausprobieren und deren Anleitungen folgen:
|
||||
Sie könnten diese ebenfalls in Betracht ziehen, deren Anleitungen folgen und ihre Dienste ausprobieren:
|
||||
|
||||
* <a href="https://docs.render.com/deploy-fastapi?utm_source=deploydoc&utm_medium=referral&utm_campaign=fastapi" class="external-link" target="_blank">Render</a>
|
||||
* <a href="https://docs.railway.com/guides/fastapi?utm_medium=integration&utm_source=docs&utm_campaign=fastapi" class="external-link" target="_blank">Railway</a>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# Deployment-Konzepte { #deployments-concepts }
|
||||
|
||||
Bei dem Deployment – der Bereitstellung – einer **FastAPI**-Anwendung, oder eigentlich jeder Art von Web-API, gibt es mehrere Konzepte, die Sie wahrscheinlich interessieren, und mithilfe der Sie die **am besten geeignete** Methode zur **Bereitstellung Ihrer Anwendung** finden können.
|
||||
Bei dem Deployment – der Bereitstellung – einer **FastAPI**-Anwendung, oder eigentlich jeder Art von Web-API, gibt es mehrere Konzepte, die Sie wahrscheinlich interessieren, und mithilfe der Sie die **am besten geeignete** Methode zum **Deployment Ihrer Anwendung** finden können.
|
||||
|
||||
Einige wichtige Konzepte sind:
|
||||
|
||||
|
|
@ -15,11 +15,11 @@ Wir werden sehen, wie diese sich auf das **Deployment** auswirken.
|
|||
|
||||
Letztendlich besteht das ultimative Ziel darin, **Ihre API-Clients** auf **sichere** Weise zu versorgen, um **Unterbrechungen** zu vermeiden und die **Rechenressourcen** (z. B. entfernte Server/virtuelle Maschinen) so effizient wie möglich zu nutzen. 🚀
|
||||
|
||||
Ich erzähle Ihnen hier etwas mehr über diese **Konzepte**, was Ihnen hoffentlich die **Intuition** gibt, die Sie benötigen, um zu entscheiden, wie Sie Ihre API in sehr unterschiedlichen Umgebungen bereitstellen, möglicherweise sogar in **zukünftigen**, die jetzt noch nicht existieren.
|
||||
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 der Bereitstellung **Ihrer eigenen APIs** **evaluieren und konzipieren**.
|
||||
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 die Bereitstellung von FastAPI-Anwendungen geben.
|
||||
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. 💡
|
||||
|
||||
|
|
@ -271,7 +271,7 @@ In diesem Fall müssen Sie sich darüber keine Sorgen machen. 🤷
|
|||
|
||||
### Beispiele für Strategien für Vorab-Schritte { #examples-of-previous-steps-strategies }
|
||||
|
||||
Es hängt **stark** davon ab, wie Sie **Ihr System bereitstellen**, und hängt wahrscheinlich mit der Art und Weise zusammen, wie Sie Programme starten, Neustarts durchführen, usw.
|
||||
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:
|
||||
|
||||
|
|
@ -307,7 +307,7 @@ Sie können einfache Tools wie `htop` verwenden, um die in Ihrem Server verwende
|
|||
|
||||
## Zusammenfassung { #recap }
|
||||
|
||||
Sie haben hier einige der wichtigsten Konzepte gelesen, die Sie wahrscheinlich berücksichtigen müssen, wenn Sie entscheiden, wie Sie Ihre Anwendung bereitstellen:
|
||||
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
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# FastAPI in Containern – Docker { #fastapi-in-containers-docker }
|
||||
|
||||
Beim Deployment von FastAPI-Anwendungen besteht ein gängiger Ansatz darin, ein **Linux-Containerimage** zu erstellen. Normalerweise erfolgt dies mit <a href="https://www.docker.com/" class="external-link" target="_blank">**Docker**</a>. Sie können dieses Containerimage dann auf eine von mehreren möglichen Arten bereitstellen.
|
||||
Beim Deployment von FastAPI-Anwendungen besteht ein gängiger Ansatz darin, ein **Linux-Containerimage** zu erstellen. Normalerweise erfolgt dies mit <a href="https://www.docker.com/" class="external-link" target="_blank">**Docker**</a>. Sie können dieses Containerimage dann auf eine von mehreren möglichen Arten deployen.
|
||||
|
||||
Die Verwendung von Linux-Containern bietet mehrere Vorteile, darunter **Sicherheit**, **Replizierbarkeit**, **Einfachheit** und andere.
|
||||
|
||||
|
|
@ -40,7 +40,7 @@ Linux-Container werden mit demselben Linux-Kernel des Hosts (Maschine, virtuelle
|
|||
|
||||
Auf diese Weise verbrauchen Container **wenig Ressourcen**, eine Menge vergleichbar mit der direkten Ausführung der Prozesse (eine virtuelle Maschine würde viel mehr verbrauchen).
|
||||
|
||||
Container verfügen außerdem über ihre eigenen **isoliert** laufenden Prozesse (üblicherweise nur einen Prozess), über ihr eigenes Dateisystem und ihr eigenes Netzwerk, was die Bereitstellung, Sicherheit, Entwicklung usw. vereinfacht.
|
||||
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 }
|
||||
|
||||
|
|
@ -598,7 +598,7 @@ Zum Beispiel:
|
|||
* 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 bereitstellt
|
||||
* Mit einem Cloud-Dienst, der Ihr Containerimage nimmt und es deployt
|
||||
|
||||
## Docker-Image mit `uv` { #docker-image-with-uv }
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,65 @@
|
|||
# FastAPI Cloud { #fastapi-cloud }
|
||||
|
||||
Sie können Ihre FastAPI-App in der <a href="https://fastapicloud.com" class="external-link" target="_blank">FastAPI Cloud</a> mit **einem einzigen Befehl** deployen – tragen Sie sich in die Warteliste ein, falls noch nicht geschehen. 🚀
|
||||
|
||||
## Anmelden { #login }
|
||||
|
||||
Stellen Sie sicher, dass Sie bereits ein **FastAPI-Cloud-Konto** haben (wir haben Sie von der Warteliste eingeladen 😉).
|
||||
|
||||
Melden Sie sich dann an:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ fastapi login
|
||||
|
||||
You are logged in to FastAPI Cloud 🚀
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
## Deployen { #deploy }
|
||||
|
||||
Stellen Sie Ihre App jetzt mit **einem einzigen Befehl** bereit:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ fastapi deploy
|
||||
|
||||
Deploying to FastAPI Cloud...
|
||||
|
||||
✅ Deployment successful!
|
||||
|
||||
🐔 Ready the chicken! Your app is ready at https://myapp.fastapicloud.dev
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
Das war’s! Jetzt können Sie Ihre App unter dieser URL aufrufen. ✨
|
||||
|
||||
## Über FastAPI Cloud { #about-fastapi-cloud }
|
||||
|
||||
**<a href="https://fastapicloud.com" class="external-link" target="_blank">FastAPI Cloud</a>** wird vom gleichen Autor und Team hinter **FastAPI** entwickelt.
|
||||
|
||||
Es vereinfacht den Prozess des **Erstellens**, **Deployens** und **Nutzens** einer API mit minimalem Aufwand.
|
||||
|
||||
Es bringt die gleiche **Developer-Experience** beim Erstellen von Apps mit FastAPI auch zum **Deployment** in der Cloud. 🎉
|
||||
|
||||
Es kümmert sich außerdem um das meiste, was beim Deployen einer App nötig ist, zum Beispiel:
|
||||
|
||||
* HTTPS
|
||||
* Replikation, mit Autoscaling basierend auf Requests
|
||||
* usw.
|
||||
|
||||
FastAPI Cloud ist Hauptsponsor und Finanzierer der Open-Source-Projekte *FastAPI and friends*. ✨
|
||||
|
||||
## Bei anderen Cloudanbietern deployen { #deploy-to-other-cloud-providers }
|
||||
|
||||
FastAPI ist Open Source und basiert auf Standards. Sie können FastAPI-Apps bei jedem Cloudanbieter Ihrer Wahl deployen.
|
||||
|
||||
Folgen Sie den Anleitungen Ihres Cloudanbieters, um dort FastAPI-Apps zu deployen. 🤓
|
||||
|
||||
## Auf den eigenen Server deployen { #deploy-your-own-server }
|
||||
|
||||
Ich werde Ihnen später in diesem **Deployment-Leitfaden** auch alle Details zeigen, sodass Sie verstehen, was passiert, was geschehen muss und wie Sie FastAPI-Apps selbst deployen können, auch auf Ihre eigenen Server. 🤓
|
||||
|
|
@ -14,7 +14,9 @@ Das steht im Gegensatz zu den **Entwicklungsphasen**, in denen Sie ständig den
|
|||
|
||||
Es gibt mehrere Möglichkeiten, dies zu tun, abhängig von Ihrem spezifischen Anwendungsfall und den von Ihnen verwendeten Tools.
|
||||
|
||||
Sie könnten mithilfe einer Kombination von Tools selbst **einen Server bereitstellen**, Sie könnten einen **Cloud-Dienst** nutzen, der einen Teil der Arbeit für Sie erledigt, oder andere mögliche Optionen.
|
||||
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, <a href="https://fastapicloud.com" class="external-link" target="_blank">**FastAPI Cloud**</a> entwickelt, um das Deployment von FastAPI-Apps in der Cloud so reibungslos wie möglich zu gestalten, mit derselben Developer-Experience wie beim Arbeiten mit FastAPI.
|
||||
|
||||
Ich zeige Ihnen einige der wichtigsten Konzepte, die Sie beim Deployment einer **FastAPI**-Anwendung wahrscheinlich berücksichtigen sollten (obwohl das meiste davon auch für jede andere Art von Webanwendung gilt).
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ Schauen wir uns die Deployment-Konzepte von früher noch einmal an:
|
|||
|
||||
Bis zu diesem Punkt, in allen Tutorials in der Dokumentation, haben Sie wahrscheinlich ein **Serverprogramm** ausgeführt, zum Beispiel mit dem `fastapi`-Befehl, der Uvicorn startet, und einen **einzelnen Prozess** ausführt.
|
||||
|
||||
Wenn Sie Anwendungen bereitstellen, möchten Sie wahrscheinlich eine gewisse **Replikation von Prozessen**, um **mehrere Kerne** zu nutzen und mehr <abbr title="Request – Anfrage: Daten, die der Client zum Server sendet">Requests</abbr> bearbeiten zu können.
|
||||
Wenn Sie Anwendungen deployen, möchten Sie wahrscheinlich eine gewisse **Replikation von Prozessen**, um **mehrere Kerne** zu nutzen und mehr <abbr title="Request – Anfrage: Daten, die der Client zum Server sendet">Requests</abbr> bearbeiten zu können.
|
||||
|
||||
Wie Sie im vorherigen Kapitel über [Deployment-Konzepte](concepts.md){.internal-link target=_blank} gesehen haben, gibt es mehrere Strategien, die Sie anwenden können.
|
||||
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ Das Ausführen von `fastapi run` startet FastAPI standardmäßig im Produktionsm
|
|||
|
||||
Standardmäßig ist **Autoreload** deaktiviert. Es horcht auch auf der IP-Adresse `0.0.0.0`, was alle verfügbaren IP-Adressen bedeutet, so wird es öffentlich zugänglich für jeden, der mit der Maschine kommunizieren kann. So würden Sie es normalerweise in der Produktion ausführen, beispielsweise in einem Container.
|
||||
|
||||
In den meisten Fällen würden (und sollten) Sie einen „Terminierungsproxy“ haben, der HTTPS für Sie verwaltet. Dies hängt davon ab, wie Sie Ihre Anwendung bereitstellen. Ihr Anbieter könnte dies für Sie erledigen, oder Sie müssen es selbst einrichten.
|
||||
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
|
||||
|
||||
|
|
|
|||
|
|
@ -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, <a href="https://datatracker.ietf.org/doc/html/rfc7235#section-3.1" class="external-link" target="_blank">RFC 7235</a>, <a href="https://datatracker.ietf.org/doc/html/rfc9110#name-401-unauthorized" class="external-link" target="_blank">RFC 9110</a>.
|
||||
|
||||
Aber falls Ihre Clients aus irgendeinem Grund vom alten Verhalten abhängen, können Sie darauf zurückgreifen, indem Sie in Ihren Sicherheitsklassen die Methode `make_not_authenticated_error` überschreiben.
|
||||
|
||||
Sie können beispielsweise eine Unterklasse von `HTTPBearer` erstellen, die einen Fehler `403 Forbidden` zurückgibt, statt des Default-`401 Unauthorized`-Fehlers:
|
||||
|
||||
{* ../../docs_src/authentication_error_status_code/tutorial001_an_py39.py hl[9:13] *}
|
||||
|
||||
/// tip | Tipp
|
||||
|
||||
Beachten Sie, dass die Funktion die Exception-Instanz zurückgibt; sie wirft sie nicht. Das Werfen erfolgt im restlichen internen Code.
|
||||
|
||||
///
|
||||
|
|
@ -46,20 +46,26 @@ Seine Schlüssel-Merkmale sind:
|
|||
* **Robust**: Erhalten Sie produktionsreifen Code. Mit automatischer, interaktiver Dokumentation.
|
||||
* **Standards-basiert**: Basierend auf (und vollständig kompatibel mit) den offenen Standards für APIs: <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank">OpenAPI</a> (früher bekannt als Swagger) und <a href="https://json-schema.org/" class="external-link" target="_blank">JSON Schema</a>.
|
||||
|
||||
<small>* Schätzung basierend auf Tests in einem internen Entwicklungsteam, das Produktionsanwendungen erstellt.</small>
|
||||
<small>* Schätzung basierend auf Tests, die von einem internen Entwicklungsteam durchgeführt wurden, das Produktionsanwendungen erstellt.</small>
|
||||
|
||||
## Sponsoren { #sponsors }
|
||||
|
||||
<!-- sponsors -->
|
||||
|
||||
{% if sponsors %}
|
||||
### Keystone-Sponsor
|
||||
|
||||
{% for sponsor in sponsors.keystone -%}
|
||||
<a href="{{ sponsor.url }}" target="_blank" title="{{ sponsor.title }}"><img src="{{ sponsor.img }}" style="border-radius:15px"></a>
|
||||
{% endfor -%}
|
||||
|
||||
### Gold- und Silber-Sponsoren
|
||||
|
||||
{% for sponsor in sponsors.gold -%}
|
||||
<a href="{{ sponsor.url }}" target="_blank" title="{{ sponsor.title }}"><img src="{{ sponsor.img }}" style="border-radius:15px"></a>
|
||||
{% endfor -%}
|
||||
{%- for sponsor in sponsors.silver -%}
|
||||
<a href="{{ sponsor.url }}" target="_blank" title="{{ sponsor.title }}"><img src="{{ sponsor.img }}" style="border-radius:15px"></a>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
<!-- /sponsors -->
|
||||
|
||||
|
|
@ -444,6 +450,58 @@ Für ein vollständigeres Beispiel, mit weiteren Funktionen, siehe das <a href="
|
|||
* **Cookie-Sessions**
|
||||
* ... und mehr.
|
||||
|
||||
### Ihre App deployen (optional) { #deploy-your-app-optional }
|
||||
|
||||
Optional können Sie Ihre FastAPI-App in die <a href="https://fastapicloud.com" class="external-link" target="_blank">FastAPI Cloud</a> deployen, treten Sie der Warteliste bei, falls noch nicht geschehen. 🚀
|
||||
|
||||
Wenn Sie bereits ein **FastAPI Cloud**-Konto haben (wir haben Sie von der Warteliste eingeladen 😉), können Sie Ihre Anwendung mit einem einzigen Befehl deployen.
|
||||
|
||||
Stellen Sie vor dem Deployen sicher, dass Sie eingeloggt sind:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ fastapi login
|
||||
|
||||
You are logged in to FastAPI Cloud 🚀
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
Stellen Sie dann Ihre App bereit:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ fastapi deploy
|
||||
|
||||
Deploying to FastAPI Cloud...
|
||||
|
||||
✅ Deployment successful!
|
||||
|
||||
🐔 Ready the chicken! Your app is ready at https://myapp.fastapicloud.dev
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
Das war’s! Jetzt können Sie unter dieser URL auf Ihre App zugreifen. ✨
|
||||
|
||||
#### Über FastAPI Cloud { #about-fastapi-cloud }
|
||||
|
||||
**<a href="https://fastapicloud.com" class="external-link" target="_blank">FastAPI Cloud</a>** wird vom selben Autor und Team hinter **FastAPI** entwickelt.
|
||||
|
||||
Es vereinfacht den Prozess des **Erstellens**, **Deployens** und **Zugreifens** auf eine API mit minimalem Aufwand.
|
||||
|
||||
Es bringt die gleiche **Developer-Experience** beim Erstellen von Apps mit FastAPI auch zum **Deployment** in der Cloud. 🎉
|
||||
|
||||
FastAPI Cloud ist der Hauptsponsor und Finanzierer der „FastAPI and friends“ Open-Source-Projekte. ✨
|
||||
|
||||
#### Bei anderen Cloudanbietern deployen { #deploy-to-other-cloud-providers }
|
||||
|
||||
FastAPI ist Open Source und basiert auf Standards. Sie können FastAPI-Apps bei jedem Cloudanbieter Ihrer Wahl deployen.
|
||||
|
||||
Folgen Sie den Anleitungen Ihres Cloudanbieters, um FastAPI-Apps dort bereitzustellen. 🤓
|
||||
|
||||
## Performanz { #performance }
|
||||
|
||||
Unabhängige TechEmpower-Benchmarks zeigen **FastAPI**-Anwendungen, die unter Uvicorn laufen, als <a href="https://www.techempower.com/benchmarks/#section=test&runid=7464e520-0dc2-473d-bd34-dbdfd7e85911&hw=ph&test=query&l=zijzen-7" class="external-link" target="_blank">eines der schnellsten verfügbaren Python-Frameworks</a>, nur hinter Starlette und Uvicorn selbst (intern von FastAPI verwendet). (*)
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ GitHub-Repository: <a href="https://github.com/tiangolo/full-stack-fastapi-templ
|
|||
- 💾 [PostgreSQL](https://www.postgresql.org) als SQL-Datenbank.
|
||||
- 🚀 [React](https://react.dev) für das Frontend.
|
||||
- 💃 Verwendung von TypeScript, Hooks, [Vite](https://vitejs.dev) und anderen Teilen eines modernen Frontend-Stacks.
|
||||
- 🎨 [Chakra UI](https://chakra-ui.com) für die Frontend-Komponenten.
|
||||
- 🎨 [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.
|
||||
- 🦇 Unterstützung des Dunkelmodus.
|
||||
|
|
@ -25,4 +25,4 @@ GitHub-Repository: <a href="https://github.com/tiangolo/full-stack-fastapi-templ
|
|||
- ✅ 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 (kontinuierliche Bereitstellung) basierend auf GitHub Actions.
|
||||
- 🏭 CI (kontinuierliche Integration) und CD (kontinuierliches Deployment) basierend auf GitHub Actions.
|
||||
|
|
|
|||
|
|
@ -184,6 +184,51 @@ Wenn Sie in dem Code der *Pfadoperation-Funktion* irgendeine Exception auslösen
|
|||
|
||||
///
|
||||
|
||||
## Frühes Beenden und `scope` { #early-exit-and-scope }
|
||||
|
||||
Normalerweise wird der Exit-Code von Abhängigkeiten mit `yield` ausgeführt **nachdem die Response** an den Client gesendet wurde.
|
||||
|
||||
Wenn Sie aber wissen, dass Sie die Abhängigkeit nach der Rückkehr aus der *Pfadoperation-Funktion* nicht mehr benötigen, können Sie `Depends(scope="function")` verwenden, um FastAPI mitzuteilen, dass es die Abhängigkeit nach der Rückkehr aus der *Pfadoperation-Funktion* schließen soll, jedoch **bevor** die **Response gesendet wird**.
|
||||
|
||||
{* ../../docs_src/dependencies/tutorial008e_an_py39.py hl[12,16] *}
|
||||
|
||||
`Depends()` erhält einen `scope`-Parameter, der sein kann:
|
||||
|
||||
* `"function"`: startet die Abhängigkeit vor der *Pfadoperation-Funktion*, die den Request bearbeitet, beendet die Abhängigkeit nach dem Ende der *Pfadoperation-Funktion*, aber **bevor** die Response an den Client zurückgesendet wird. Die Abhängigkeitsfunktion wird also **um** die *Pfadoperation-**Funktion*** **herum** ausgeführt.
|
||||
* `"request"`: startet die Abhängigkeit vor der *Pfadoperation-Funktion*, die den Request bearbeitet (ähnlich wie bei `"function"`), beendet sie jedoch **nachdem** die Response an den Client zurückgesendet wurde. Die Abhängigkeitsfunktion wird also **um** den **Request**- und Response-Zyklus **herum** ausgeführt.
|
||||
|
||||
Wenn nicht angegeben und die Abhängigkeit `yield` hat, hat sie standardmäßig einen `scope` von `"request"`.
|
||||
|
||||
### `scope` für Unterabhängigkeiten { #scope-for-sub-dependencies }
|
||||
|
||||
Wenn Sie eine Abhängigkeit mit `scope="request"` (dem Default) deklarieren, muss jede Unterabhängigkeit ebenfalls einen `scope` von `"request"` haben.
|
||||
|
||||
Eine Abhängigkeit mit `scope` von `"function"` kann jedoch Abhängigkeiten mit `scope` von `"function"` und `scope` von `"request"` haben.
|
||||
|
||||
Das liegt daran, dass jede Abhängigkeit in der Lage sein muss, ihren Exit-Code vor den Unterabhängigkeiten auszuführen, da sie diese während ihres Exit-Codes möglicherweise noch verwenden muss.
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
|
||||
participant client as Client
|
||||
participant dep_req as Abhängigkeit scope="request"
|
||||
participant dep_func as Abhängigkeit scope="function"
|
||||
participant operation as Pfadoperation
|
||||
|
||||
client ->> dep_req: Startet den Request
|
||||
Note over dep_req: Führt den Code bis zum yield aus
|
||||
dep_req ->> dep_func: Reicht Abhängigkeit weiter
|
||||
Note over dep_func: Führt den Code bis zum yield aus
|
||||
dep_func ->> operation: Führt Pfadoperation mit Abhängigkeit aus
|
||||
operation ->> dep_func: Kehrt aus Pfadoperation zurück
|
||||
Note over dep_func: Führt Code nach yield aus
|
||||
Note over dep_func: ✅ Abhängigkeit geschlossen
|
||||
dep_func ->> client: Sendet Response an Client
|
||||
Note over client: Response gesendet
|
||||
Note over dep_req: Führt Code nach yield aus
|
||||
Note over dep_req: ✅ Abhängigkeit geschlossen
|
||||
```
|
||||
|
||||
## Abhängigkeiten mit `yield`, `HTTPException`, `except` und Hintergrundtasks { #dependencies-with-yield-httpexception-except-and-background-tasks }
|
||||
|
||||
Abhängigkeiten mit `yield` haben sich im Laufe der Zeit weiterentwickelt, um verschiedene Anwendungsfälle abzudecken und einige Probleme zu beheben.
|
||||
|
|
|
|||
|
|
@ -143,6 +143,42 @@ Es gibt dutzende Alternativen, die alle auf OpenAPI basieren. Sie können jede d
|
|||
|
||||
Ebenfalls können Sie es verwenden, um automatisch Code für Clients zu generieren, die mit Ihrer API kommunizieren. Zum Beispiel für Frontend-, Mobile- oder IoT-Anwendungen.
|
||||
|
||||
### Ihre App deployen (optional) { #deploy-your-app-optional }
|
||||
|
||||
Sie können optional Ihre FastAPI-App in der <a href="https://fastapicloud.com" class="external-link" target="_blank">FastAPI Cloud</a> deployen, treten Sie der Warteliste bei, falls Sie es noch nicht getan haben. 🚀
|
||||
|
||||
Wenn Sie bereits ein **FastAPI Cloud**-Konto haben (wir haben Sie von der Warteliste eingeladen 😉), können Sie Ihre Anwendung mit einem Befehl deployen.
|
||||
|
||||
Vor dem Deployen, stellen Sie sicher, dass Sie eingeloggt sind:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ fastapi login
|
||||
|
||||
You are logged in to FastAPI Cloud 🚀
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
Dann stellen Sie Ihre App bereit:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ fastapi deploy
|
||||
|
||||
Deploying to FastAPI Cloud...
|
||||
|
||||
✅ Deployment successful!
|
||||
|
||||
🐔 Ready the chicken! Your app is ready at https://myapp.fastapicloud.dev
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
Das war's! Jetzt können Sie Ihre App unter dieser URL aufrufen. ✨
|
||||
|
||||
## Zusammenfassung, Schritt für Schritt { #recap-step-by-step }
|
||||
|
||||
### Schritt 1: `FastAPI` importieren { #step-1-import-fastapi }
|
||||
|
|
@ -314,6 +350,26 @@ 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 **<a href="https://fastapicloud.com" class="external-link" target="_blank">FastAPI Cloud</a>** mit einem Befehl bereit: `fastapi deploy`. 🎉
|
||||
|
||||
#### Über FastAPI Cloud { #about-fastapi-cloud }
|
||||
|
||||
**<a href="https://fastapicloud.com" class="external-link" target="_blank">FastAPI Cloud</a>** wird vom selben Autor und Team hinter **FastAPI** entwickelt.
|
||||
|
||||
Es vereinfacht den Prozess des Erstellens, Deployens und des Zugriffs auf eine API mit minimalem Aufwand.
|
||||
|
||||
Es bringt die gleiche **Developer-Experience** beim Erstellen von Apps mit FastAPI auch zum **Deployment** in der Cloud. 🎉
|
||||
|
||||
FastAPI Cloud ist der Hauptsponsor und Finanzierer der „FastAPI and friends“ Open-Source-Projekte. ✨
|
||||
|
||||
#### Zu anderen Cloudanbietern deployen { #deploy-to-other-cloud-providers }
|
||||
|
||||
FastAPI ist Open Source und basiert auf Standards. Sie können FastAPI-Apps bei jedem Cloudanbieter Ihrer Wahl deployen.
|
||||
|
||||
Folgen Sie den Anleitungen Ihres Cloudanbieters, um dort FastAPI-Apps bereitzustellen. 🤓
|
||||
|
||||
## Zusammenfassung { #recap }
|
||||
|
||||
* Importieren Sie `FastAPI`.
|
||||
|
|
@ -321,3 +377,4 @@ Es gibt viele andere Objekte und Modelle, die automatisch zu JSON konvertiert we
|
|||
* 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.
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ Es gibt ein paar Unterschiede:
|
|||
|
||||
* `Field(primary_key=True)` sagt SQLModel, dass die `id` der **Primärschlüssel** in der SQL-Datenbank ist (Sie können mehr über SQL-Primärschlüssel in der SQLModel-Dokumentation erfahren).
|
||||
|
||||
Durch das Festlegen des Typs als `int | None` wird SQLModel wissen, dass diese Spalte ein `INTEGER` in der SQL-Datenbank sein sollte und dass sie `NULLABLE` sein sollte.
|
||||
**Hinweis:** Wir verwenden für das Primärschlüsselfeld `int | None`, damit wir im Python-Code *ein Objekt ohne `id` erstellen* können (`id=None`), in der Annahme, dass die Datenbank sie *beim Speichern generiert*. SQLModel versteht, dass die Datenbank die `id` bereitstellt, und *definiert die Spalte im Datenbankschema als ein Nicht-Null-`INTEGER`*. Siehe die <a href="https://sqlmodel.tiangolo.com/tutorial/create-db-and-table/#primary-key-id" class="external-link" target="_blank">SQLModel-Dokumentation zu Primärschlüsseln</a> für Details.
|
||||
|
||||
* `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.
|
||||
|
||||
|
|
|
|||
|
|
@ -242,6 +242,26 @@ $ python -m pip install --upgrade pip
|
|||
|
||||
</div>
|
||||
|
||||
/// tip | Tipp
|
||||
|
||||
Manchmal kann beim Versuch, `pip` zu aktualisieren, der Fehler **`No module named pip`** auftreten.
|
||||
|
||||
Wenn das passiert, installieren und aktualisieren Sie `pip` mit dem folgenden Befehl:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ python -m ensurepip --upgrade
|
||||
|
||||
---> 100%
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
Dieser Befehl installiert `pip`, falls es noch nicht installiert ist, und stellt außerdem sicher, dass die installierte Version von `pip` mindestens so aktuell ist wie die in `ensurepip` verfügbare.
|
||||
|
||||
///
|
||||
|
||||
## `.gitignore` hinzufügen { #add-gitignore }
|
||||
|
||||
Wenn Sie **Git** verwenden (was Sie sollten), fügen Sie eine `.gitignore`-Datei hinzu, um alles in Ihrem `.venv` von Git auszuschließen.
|
||||
|
|
|
|||
|
|
@ -255,6 +255,7 @@ Below is a list of English terms and their preferred German translations, separa
|
|||
* «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»
|
||||
|
|
@ -316,6 +317,7 @@ Below is a list of English terms and their preferred German translations, separa
|
|||
* «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»
|
||||
|
|
|
|||
|
|
@ -1,21 +1,21 @@
|
|||
tiangolo:
|
||||
login: tiangolo
|
||||
count: 782
|
||||
count: 808
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4
|
||||
url: https://github.com/tiangolo
|
||||
dependabot:
|
||||
login: dependabot
|
||||
count: 117
|
||||
count: 130
|
||||
avatarUrl: https://avatars.githubusercontent.com/in/29110?v=4
|
||||
url: https://github.com/apps/dependabot
|
||||
alejsdev:
|
||||
login: alejsdev
|
||||
count: 52
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/90076947?u=447d12a1b347f466b35378bee4c7104cc9b2c571&v=4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/90076947?u=85ceac49fb87138aebe8d663912e359447329090&v=4
|
||||
url: https://github.com/alejsdev
|
||||
pre-commit-ci:
|
||||
login: pre-commit-ci
|
||||
count: 45
|
||||
count: 50
|
||||
avatarUrl: https://avatars.githubusercontent.com/in/68672?v=4
|
||||
url: https://github.com/apps/pre-commit-ci
|
||||
github-actions:
|
||||
|
|
@ -25,44 +25,44 @@ github-actions:
|
|||
url: https://github.com/apps/github-actions
|
||||
Kludex:
|
||||
login: Kludex
|
||||
count: 24
|
||||
count: 25
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=df8a3f06ba8f55ae1967a3e2d5ed882903a4e330&v=4
|
||||
url: https://github.com/Kludex
|
||||
YuriiMotov:
|
||||
login: YuriiMotov
|
||||
count: 20
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=b9b13d598dddfab529a52d264df80a900bfe7060&v=4
|
||||
url: https://github.com/YuriiMotov
|
||||
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
|
||||
svlandeg:
|
||||
login: svlandeg
|
||||
count: 14
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/8796347?u=556c97650c27021911b0b9447ec55e75987b0e8a&v=4
|
||||
url: https://github.com/svlandeg
|
||||
euri10:
|
||||
login: euri10
|
||||
count: 13
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1104190?u=321a2e953e6645a7d09b732786c7a8061e0f8a8b&v=4
|
||||
url: https://github.com/euri10
|
||||
nilslindemann:
|
||||
login: nilslindemann
|
||||
count: 13
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/6892179?u=1dca6a22195d6cd1ab20737c0e19a4c55d639472&v=4
|
||||
url: https://github.com/nilslindemann
|
||||
kantandane:
|
||||
login: kantandane
|
||||
count: 13
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/3978368?u=cccc199291f991a73b1ebba5abc735a948e0bd16&v=4
|
||||
url: https://github.com/kantandane
|
||||
svlandeg:
|
||||
login: svlandeg
|
||||
count: 11
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/8796347?u=556c97650c27021911b0b9447ec55e75987b0e8a&v=4
|
||||
url: https://github.com/svlandeg
|
||||
zhaohan-dong:
|
||||
login: zhaohan-dong
|
||||
count: 11
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/65422392?u=8260f8781f50248410ebfa4c9bf70e143fe5c9f2&v=4
|
||||
url: https://github.com/zhaohan-dong
|
||||
YuriiMotov:
|
||||
login: YuriiMotov
|
||||
count: 10
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=b9b13d598dddfab529a52d264df80a900bfe7060&v=4
|
||||
url: https://github.com/YuriiMotov
|
||||
mariacamilagl:
|
||||
login: mariacamilagl
|
||||
count: 9
|
||||
|
|
@ -103,6 +103,11 @@ 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
|
||||
|
|
@ -133,11 +138,6 @@ iudeen:
|
|||
count: 4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/10519440?u=f09cdd745e5bf16138f29b42732dd57c7f02bee1&v=4
|
||||
url: https://github.com/iudeen
|
||||
musicinmybrain:
|
||||
login: musicinmybrain
|
||||
count: 4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/6898909?u=9010312053e7141383b9bdf538036c7f37fbaba0&v=4
|
||||
url: https://github.com/musicinmybrain
|
||||
philipokiokio:
|
||||
login: philipokiokio
|
||||
count: 4
|
||||
|
|
@ -158,6 +158,11 @@ 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
|
||||
|
|
@ -191,7 +196,7 @@ Serrones:
|
|||
uriyyo:
|
||||
login: uriyyo
|
||||
count: 3
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/32038156?u=0c68019beb28381ce5205a838937c61e0fe3fee2&v=4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/32038156?u=c26ca9b821fcf6499b84db75f553d4980bf8d023&v=4
|
||||
url: https://github.com/uriyyo
|
||||
andrew222651:
|
||||
login: andrew222651
|
||||
|
|
@ -261,7 +266,7 @@ Nimitha-jagadeesha:
|
|||
lucaromagnoli:
|
||||
login: lucaromagnoli
|
||||
count: 3
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/38782977?u=e66396859f493b4ddcb3a837a1b2b2039c805417&v=4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/38782977?u=15df02e806a2293af40ac619fba11dbe3c0c4fd4&v=4
|
||||
url: https://github.com/lucaromagnoli
|
||||
salmantec:
|
||||
login: salmantec
|
||||
|
|
@ -328,11 +333,6 @@ svalouch:
|
|||
count: 2
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/54674660?v=4
|
||||
url: https://github.com/svalouch
|
||||
frankie567:
|
||||
login: frankie567
|
||||
count: 2
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1144727?u=f3e79acfe4ed207e15c2145161a8a9759925fcd2&v=4
|
||||
url: https://github.com/frankie567
|
||||
marier-nico:
|
||||
login: marier-nico
|
||||
count: 2
|
||||
|
|
@ -346,7 +346,7 @@ Dustyposa:
|
|||
aviramha:
|
||||
login: aviramha
|
||||
count: 2
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/41201924?u=6883cc4fc13a7b2e60d4deddd4be06f9c5287880&v=4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/41201924?u=ce5d3ea7037c2e6b3f82eff87e2217d4fb63214b&v=4
|
||||
url: https://github.com/aviramha
|
||||
iwpnd:
|
||||
login: iwpnd
|
||||
|
|
@ -483,6 +483,11 @@ 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
|
||||
|
|
|
|||
|
|
@ -381,6 +381,10 @@ Articles:
|
|||
title: 'Tutorial de FastAPI, ¿el mejor framework de Python?'
|
||||
Podcasts:
|
||||
English:
|
||||
- author: Behind the Commit
|
||||
author_link: https://www.youtube.com/@BehindtheCommit
|
||||
link: https://youtu.be/iaDRYUQ0OMM
|
||||
title: Why FastAPI Became Python’s Fastest‑Growing Framework – Chat with Sebastián Ramírez
|
||||
- author: Real Python
|
||||
author_link: https://realpython.com/
|
||||
link: https://realpython.com/podcasts/rpp/72/
|
||||
|
|
@ -399,6 +403,10 @@ Podcasts:
|
|||
title: FastAPI on PythonBytes
|
||||
Talks:
|
||||
English:
|
||||
- author: Sebastián Ramírez (tiangolo)
|
||||
author_link: https://x.com/tiangolo
|
||||
link: https://www.youtube.com/watch?v=mwvmfl8nN_U
|
||||
title: 'Keynote: Behind the scenes of FastAPI and friends for developers and builders — Sebastián Ramírez'
|
||||
- author: Jeny Sadadia
|
||||
author_link: https://github.com/JenySadadia
|
||||
link: https://www.youtube.com/watch?v=uZdTe8_Z6BQ
|
||||
|
|
|
|||
|
|
@ -14,15 +14,15 @@ sponsors:
|
|||
- login: coderabbitai
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/132028505?v=4
|
||||
url: https://github.com/coderabbitai
|
||||
- login: greptileai
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/140149887?v=4
|
||||
url: https://github.com/greptileai
|
||||
- login: subtotal
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/176449348?v=4
|
||||
url: https://github.com/subtotal
|
||||
- login: railwayapp
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/66716858?v=4
|
||||
url: https://github.com/railwayapp
|
||||
- login: scalar
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/301879?v=4
|
||||
url: https://github.com/scalar
|
||||
- - login: dribia
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/41189616?v=4
|
||||
url: https://github.com/dribia
|
||||
|
|
@ -41,13 +41,7 @@ sponsors:
|
|||
- login: permitio
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/71775833?v=4
|
||||
url: https://github.com/permitio
|
||||
- - login: marvin-robot
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/41086007?u=b9fcab402d0cd0aec738b6574fe60855cb0cd36d&v=4
|
||||
url: https://github.com/marvin-robot
|
||||
- login: mercedes-benz
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/34240465?v=4
|
||||
url: https://github.com/mercedes-benz
|
||||
- login: Ponte-Energy-Partners
|
||||
- - login: Ponte-Energy-Partners
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/114745848?v=4
|
||||
url: https://github.com/Ponte-Energy-Partners
|
||||
- login: LambdaTest-Inc
|
||||
|
|
@ -56,10 +50,16 @@ sponsors:
|
|||
- login: BoostryJP
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/57932412?v=4
|
||||
url: https://github.com/BoostryJP
|
||||
- login: requestly
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/12287519?v=4
|
||||
url: https://github.com/requestly
|
||||
- login: acsone
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/7601056?v=4
|
||||
url: https://github.com/acsone
|
||||
- - login: Trivie
|
||||
- - 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
|
||||
|
|
@ -68,27 +68,27 @@ sponsors:
|
|||
- login: Doist
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/2565372?v=4
|
||||
url: https://github.com/Doist
|
||||
- login: bholagabbar
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/11693595?v=4
|
||||
url: https://github.com/bholagabbar
|
||||
- - login: mainframeindustries
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/55092103?v=4
|
||||
url: https://github.com/mainframeindustries
|
||||
- login: yasyf
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/709645?u=f36736b3c6a85f578886ecc42a740e7b436e7a01&v=4
|
||||
url: https://github.com/yasyf
|
||||
- - 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: nilslindemann
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/6892179?u=1dca6a22195d6cd1ab20737c0e19a4c55d639472&v=4
|
||||
url: https://github.com/nilslindemann
|
||||
- login: upciti
|
||||
- - login: upciti
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/43346262?v=4
|
||||
url: https://github.com/upciti
|
||||
- login: thisisfixer
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/14433035?u=076d52a5b7891c764904af9f462bfb45428e25df&v=4
|
||||
url: https://github.com/thisisfixer
|
||||
- login: ChargeStorm
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/26000165?v=4
|
||||
url: https://github.com/ChargeStorm
|
||||
- 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
|
||||
|
|
@ -101,6 +101,9 @@ sponsors:
|
|||
- 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
|
||||
|
|
@ -113,21 +116,12 @@ sponsors:
|
|||
- login: Leay15
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/32212558?u=c4aa9c1737e515959382a5515381757b1fd86c53&v=4
|
||||
url: https://github.com/Leay15
|
||||
- login: kaoru0310
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/80977929?u=1b61d10142b490e56af932ddf08a390fae8ee94f&v=4
|
||||
url: https://github.com/kaoru0310
|
||||
- login: DelfinaCare
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/83734439?v=4
|
||||
url: https://github.com/DelfinaCare
|
||||
- login: Karine-Bauch
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/90465103?u=7feb1018abb1a5631cfd9a91fea723d1ceb5f49b&v=4
|
||||
url: https://github.com/Karine-Bauch
|
||||
- login: jugeeem
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/116043716?u=ae590d79c38ac79c91b9c5caa6887d061e865a3d&v=4
|
||||
url: https://github.com/jugeeem
|
||||
- login: dudikbender
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/53487583?u=3a57542938ebfd57579a0111db2b297e606d9681&v=4
|
||||
url: https://github.com/dudikbender
|
||||
- login: patsatsia
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/61111267?u=3271b85f7a37b479c8d0ae0a235182e83c166edf&v=4
|
||||
url: https://github.com/patsatsia
|
||||
|
|
@ -140,9 +134,12 @@ sponsors:
|
|||
- login: chickenandstats
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/79477966?u=ae2b894aa954070db1d7830dab99b49eba4e4567&v=4
|
||||
url: https://github.com/chickenandstats
|
||||
- login: dodo5522
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1362607?u=9bf1e0e520cccc547c046610c468ce6115bbcf9f&v=4
|
||||
url: https://github.com/dodo5522
|
||||
- login: kaoru0310
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/80977929?u=1b61d10142b490e56af932ddf08a390fae8ee94f&v=4
|
||||
url: https://github.com/kaoru0310
|
||||
- login: jstanden
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/63288?u=c3658d57d2862c607a0e19c2101c3c51876e36ad&v=4
|
||||
url: https://github.com/jstanden
|
||||
- login: knallgelb
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/2358812?u=c48cb6362b309d74cbf144bd6ad3aed3eb443e82&v=4
|
||||
url: https://github.com/knallgelb
|
||||
|
|
@ -170,12 +167,12 @@ sponsors:
|
|||
- login: Ryandaydev
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/4292423?u=679ff84cb7b988c5795a5fa583857f574a055763&v=4
|
||||
url: https://github.com/Ryandaydev
|
||||
- login: vincentkoc
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/25068?u=fbd5b2d51142daa4bdbc21e21953a3b8b8188a4a&v=4
|
||||
url: https://github.com/vincentkoc
|
||||
- login: jstanden
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/63288?u=c3658d57d2862c607a0e19c2101c3c51876e36ad&v=4
|
||||
url: https://github.com/jstanden
|
||||
- login: jaredtrog
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/4381365?v=4
|
||||
url: https://github.com/jaredtrog
|
||||
- login: oliverxchen
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/4471774?u=534191f25e32eeaadda22dfab4b0a428733d5489&v=4
|
||||
url: https://github.com/oliverxchen
|
||||
- login: paulcwatts
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/150269?u=1819e145d573b44f0ad74b87206d21cd60331d4e&v=4
|
||||
url: https://github.com/paulcwatts
|
||||
|
|
@ -197,6 +194,9 @@ sponsors:
|
|||
- login: mintuhouse
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/769950?u=ecfbd79a97d33177e0d093ddb088283cf7fe8444&v=4
|
||||
url: https://github.com/mintuhouse
|
||||
- login: dodo5522
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1362607?u=9bf1e0e520cccc547c046610c468ce6115bbcf9f&v=4
|
||||
url: https://github.com/dodo5522
|
||||
- login: wdwinslow
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/11562137?u=371272f2c69e680e0559a7b0a57385e83a5dc728&v=4
|
||||
url: https://github.com/wdwinslow
|
||||
|
|
@ -218,12 +218,6 @@ sponsors:
|
|||
- login: RaamEEIL
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/20320552?v=4
|
||||
url: https://github.com/RaamEEIL
|
||||
- login: jaredtrog
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/4381365?v=4
|
||||
url: https://github.com/jaredtrog
|
||||
- login: oliverxchen
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/4471774?u=534191f25e32eeaadda22dfab4b0a428733d5489&v=4
|
||||
url: https://github.com/oliverxchen
|
||||
- login: ternaus
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/5481618?u=513a26b02a39e7a28d587cd37c6cc877ea368e6e&v=4
|
||||
url: https://github.com/ternaus
|
||||
|
|
@ -278,9 +272,6 @@ sponsors:
|
|||
- login: petercool
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/37613029?u=75aa8c6729e6e8f85a300561c4dbeef9d65c8797&v=4
|
||||
url: https://github.com/petercool
|
||||
- login: JulioPeixoto
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/96303574?u=27d4614350cae33653f1be35cb47c92a12627ac9&v=4
|
||||
url: https://github.com/JulioPeixoto
|
||||
- login: johnl28
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/54412955?u=47dd06082d1c39caa90c752eb55566e4f3813957&v=4
|
||||
url: https://github.com/johnl28
|
||||
|
|
@ -290,21 +281,15 @@ sponsors:
|
|||
- login: PelicanQ
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/77930606?v=4
|
||||
url: https://github.com/PelicanQ
|
||||
- login: miguelgr
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1484589?u=54556072b8136efa12ae3b6902032ea2a39ace4b&v=4
|
||||
url: https://github.com/miguelgr
|
||||
- login: WillHogan
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1661551?u=8a80356e3e7d5a417157aba7ea565dabc8678327&v=4
|
||||
url: https://github.com/WillHogan
|
||||
- login: my3
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1825270?v=4
|
||||
url: https://github.com/my3
|
||||
- login: Alisa-lisa
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/4137964?u=e7e393504f554f4ff15863a1e01a5746863ef9ce&v=4
|
||||
url: https://github.com/Alisa-lisa
|
||||
- login: moonape1226
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/8532038?u=d9f8b855a429fff9397c3833c2ff83849ebf989d&v=4
|
||||
url: https://github.com/moonape1226
|
||||
- login: danielunderwood
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/4472301?v=4
|
||||
url: https://github.com/danielunderwood
|
||||
- login: ddanier
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/113563?u=ed1dc79de72f93bd78581f88ebc6952b62f472da&v=4
|
||||
url: https://github.com/ddanier
|
||||
|
|
@ -320,6 +305,9 @@ sponsors:
|
|||
- login: tochikuji
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/851759?v=4
|
||||
url: https://github.com/tochikuji
|
||||
- login: miguelgr
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1484589?u=54556072b8136efa12ae3b6902032ea2a39ace4b&v=4
|
||||
url: https://github.com/miguelgr
|
||||
- login: xncbf
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/9462045?u=a80a7bb349555b277645632ed66639ff43400614&v=4
|
||||
url: https://github.com/xncbf
|
||||
|
|
@ -329,9 +317,6 @@ sponsors:
|
|||
- login: hard-coders
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/9651103?u=95db33927bbff1ed1c07efddeb97ac2ff33068ed&v=4
|
||||
url: https://github.com/hard-coders
|
||||
- login: supdann
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/9986994?u=9671810f4ae9504c063227fee34fd47567ff6954&v=4
|
||||
url: https://github.com/supdann
|
||||
- login: mntolia
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/10390224?v=4
|
||||
url: https://github.com/mntolia
|
||||
|
|
@ -344,9 +329,6 @@ sponsors:
|
|||
- login: joshuatz
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/17817563?u=f1bf05b690d1fc164218f0b420cdd3acb7913e21&v=4
|
||||
url: https://github.com/joshuatz
|
||||
- login: danielunderwood
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/4472301?v=4
|
||||
url: https://github.com/danielunderwood
|
||||
- login: rangulvers
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/5235430?u=e254d4af4ace5a05fa58372ae677c7d26f0d5a53&v=4
|
||||
url: https://github.com/rangulvers
|
||||
|
|
@ -365,7 +347,13 @@ sponsors:
|
|||
- login: harsh183
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/7780198?v=4
|
||||
url: https://github.com/harsh183
|
||||
- - login: KOZ39
|
||||
- login: moonape1226
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/8532038?u=d9f8b855a429fff9397c3833c2ff83849ebf989d&v=4
|
||||
url: https://github.com/moonape1226
|
||||
- - login: andrecorumba
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/37807517?u=9b9be3b41da9bda60957da9ef37b50dbf65baa61&v=4
|
||||
url: https://github.com/andrecorumba
|
||||
- login: KOZ39
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/38822500?u=9dfc0a697df1c9628f08e20dc3fb17b1afc4e5a7&v=4
|
||||
url: https://github.com/KOZ39
|
||||
- login: rwxd
|
||||
|
|
@ -374,30 +362,27 @@ sponsors:
|
|||
- login: morzan1001
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/47593005?u=c30ab7230f82a12a9b938dcb54f84a996931409a&v=4
|
||||
url: https://github.com/morzan1001
|
||||
- login: azharthegeek
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/51288109?u=0987b2a9f39c21ccb071b6bdce0fc60d8492f8e8&v=4
|
||||
url: https://github.com/azharthegeek
|
||||
- login: Olegt0rr
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/25399456?u=3e87b5239a2f4600975ba13be73054f8567c6060&v=4
|
||||
url: https://github.com/Olegt0rr
|
||||
- login: dinoz0rg
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/32940067?u=739cda1eb123a2dd5e1db45c361396f239e23f8b&v=4
|
||||
url: https://github.com/dinoz0rg
|
||||
- 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: ChenPu2002
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/113831763?v=4
|
||||
url: https://github.com/ChenPu2002
|
||||
- login: hippoley
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/135493401?u=1164ef48a645a7c12664fabc1638fbb7e1c459b0&v=4
|
||||
url: https://github.com/hippoley
|
||||
- login: 4anklee
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/144109238?u=a79c0d581b2a3d8f3897e7ef4c012640a6c1eb3a&v=4
|
||||
url: https://github.com/4anklee
|
||||
- login: CoderDeltaLAN
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/152043745?u=4ff541efffb7d134e60c5fcf2dd1e343f90bb782&v=4
|
||||
url: https://github.com/CoderDeltaLAN
|
||||
- login: aghents
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/60949885?u=d8616ddf22cf998a712cdceefd6a0256a178fe9d&v=4
|
||||
url: https://github.com/aghents
|
||||
- login: 0ne-stone
|
||||
- login: onestn
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/62360849?u=746dd21c34e7e06eefb11b03e8bb01aaae3c2a4f&v=4
|
||||
url: https://github.com/0ne-stone
|
||||
url: https://github.com/onestn
|
||||
- login: nayasinghania
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/74111380?u=752e99a5e139389fdc0a0677122adc08438eb076&v=4
|
||||
url: https://github.com/nayasinghania
|
||||
|
|
|
|||
|
|
@ -1,3 +1,7 @@
|
|||
keystone:
|
||||
- url: https://fastapicloud.com
|
||||
title: FastAPI Cloud. By the same team behind FastAPI. You code. We Cloud.
|
||||
img: https://fastapi.tiangolo.com/img/sponsors/fastapicloud.png
|
||||
gold:
|
||||
- url: https://blockbee.io?ref=fastapi
|
||||
title: BlockBee Cryptocurrency Payment Gateway
|
||||
|
|
@ -26,6 +30,12 @@ gold:
|
|||
- url: https://docs.railway.com/guides/fastapi?utm_medium=integration&utm_source=docs&utm_campaign=fastapi
|
||||
title: Deploy enterprise applications at startup speed
|
||||
img: https://fastapi.tiangolo.com/img/sponsors/railway.png
|
||||
- url: https://serpapi.com/?utm_source=fastapi_website
|
||||
title: "SerpApi: Web Search API"
|
||||
img: https://fastapi.tiangolo.com/img/sponsors/serpapi.png
|
||||
- url: https://www.greptile.com/?utm_source=fastapi&utm_medium=sponsorship&utm_campaign=fastapi_sponsor_page
|
||||
title: "Greptile: The AI Code Reviewer"
|
||||
img: https://fastapi.tiangolo.com/img/sponsors/greptile.png
|
||||
silver:
|
||||
- url: https://databento.com/?utm_source=fastapi&utm_medium=sponsor&utm_content=display
|
||||
title: Pay as you go for market data
|
||||
|
|
|
|||
|
|
@ -47,3 +47,4 @@ logins:
|
|||
- railwayapp
|
||||
- subtotal
|
||||
- requestly
|
||||
- greptileai
|
||||
|
|
|
|||
|
|
@ -1,495 +1,495 @@
|
|||
- name: full-stack-fastapi-template
|
||||
html_url: https://github.com/fastapi/full-stack-fastapi-template
|
||||
stars: 38085
|
||||
stars: 39475
|
||||
owner_login: fastapi
|
||||
owner_html_url: https://github.com/fastapi
|
||||
- name: Hello-Python
|
||||
html_url: https://github.com/mouredev/Hello-Python
|
||||
stars: 32243
|
||||
stars: 33090
|
||||
owner_login: mouredev
|
||||
owner_html_url: https://github.com/mouredev
|
||||
- name: serve
|
||||
html_url: https://github.com/jina-ai/serve
|
||||
stars: 21754
|
||||
stars: 21798
|
||||
owner_login: jina-ai
|
||||
owner_html_url: https://github.com/jina-ai
|
||||
- name: HivisionIDPhotos
|
||||
html_url: https://github.com/Zeyi-Lin/HivisionIDPhotos
|
||||
stars: 19400
|
||||
stars: 20258
|
||||
owner_login: Zeyi-Lin
|
||||
owner_html_url: https://github.com/Zeyi-Lin
|
||||
- name: sqlmodel
|
||||
html_url: https://github.com/fastapi/sqlmodel
|
||||
stars: 16859
|
||||
stars: 17212
|
||||
owner_login: fastapi
|
||||
owner_html_url: https://github.com/fastapi
|
||||
- name: Douyin_TikTok_Download_API
|
||||
html_url: https://github.com/Evil0ctal/Douyin_TikTok_Download_API
|
||||
stars: 14452
|
||||
stars: 15145
|
||||
owner_login: Evil0ctal
|
||||
owner_html_url: https://github.com/Evil0ctal
|
||||
- name: fastapi-best-practices
|
||||
html_url: https://github.com/zhanymkanov/fastapi-best-practices
|
||||
stars: 13613
|
||||
stars: 14644
|
||||
owner_login: zhanymkanov
|
||||
owner_html_url: https://github.com/zhanymkanov
|
||||
- name: machine-learning-zoomcamp
|
||||
html_url: https://github.com/DataTalksClub/machine-learning-zoomcamp
|
||||
stars: 12320
|
||||
owner_login: DataTalksClub
|
||||
owner_html_url: https://github.com/DataTalksClub
|
||||
- name: fastapi_mcp
|
||||
html_url: https://github.com/tadata-org/fastapi_mcp
|
||||
stars: 10624
|
||||
stars: 11174
|
||||
owner_login: tadata-org
|
||||
owner_html_url: https://github.com/tadata-org
|
||||
- name: awesome-fastapi
|
||||
html_url: https://github.com/mjhea0/awesome-fastapi
|
||||
stars: 10415
|
||||
owner_login: mjhea0
|
||||
owner_html_url: https://github.com/mjhea0
|
||||
- name: FastUI
|
||||
html_url: https://github.com/pydantic/FastUI
|
||||
stars: 8879
|
||||
owner_login: pydantic
|
||||
owner_html_url: https://github.com/pydantic
|
||||
- name: XHS-Downloader
|
||||
html_url: https://github.com/JoeanAmier/XHS-Downloader
|
||||
stars: 8824
|
||||
owner_login: JoeanAmier
|
||||
owner_html_url: https://github.com/JoeanAmier
|
||||
- name: SurfSense
|
||||
html_url: https://github.com/MODSetter/SurfSense
|
||||
stars: 8257
|
||||
stars: 10858
|
||||
owner_login: MODSetter
|
||||
owner_html_url: https://github.com/MODSetter
|
||||
- name: FileCodeBox
|
||||
html_url: https://github.com/vastsa/FileCodeBox
|
||||
stars: 7367
|
||||
owner_login: vastsa
|
||||
owner_html_url: https://github.com/vastsa
|
||||
- name: awesome-fastapi
|
||||
html_url: https://github.com/mjhea0/awesome-fastapi
|
||||
stars: 10758
|
||||
owner_login: mjhea0
|
||||
owner_html_url: https://github.com/mjhea0
|
||||
- name: XHS-Downloader
|
||||
html_url: https://github.com/JoeanAmier/XHS-Downloader
|
||||
stars: 9313
|
||||
owner_login: JoeanAmier
|
||||
owner_html_url: https://github.com/JoeanAmier
|
||||
- name: FastUI
|
||||
html_url: https://github.com/pydantic/FastUI
|
||||
stars: 8915
|
||||
owner_login: pydantic
|
||||
owner_html_url: https://github.com/pydantic
|
||||
- name: polar
|
||||
html_url: https://github.com/polarsource/polar
|
||||
stars: 7291
|
||||
stars: 8339
|
||||
owner_login: polarsource
|
||||
owner_html_url: https://github.com/polarsource
|
||||
- name: FileCodeBox
|
||||
html_url: https://github.com/vastsa/FileCodeBox
|
||||
stars: 7721
|
||||
owner_login: vastsa
|
||||
owner_html_url: https://github.com/vastsa
|
||||
- name: nonebot2
|
||||
html_url: https://github.com/nonebot/nonebot2
|
||||
stars: 7065
|
||||
stars: 7170
|
||||
owner_login: nonebot
|
||||
owner_html_url: https://github.com/nonebot
|
||||
- name: hatchet
|
||||
html_url: https://github.com/hatchet-dev/hatchet
|
||||
stars: 6070
|
||||
stars: 6253
|
||||
owner_login: hatchet-dev
|
||||
owner_html_url: https://github.com/hatchet-dev
|
||||
- name: serge
|
||||
html_url: https://github.com/serge-chat/serge
|
||||
stars: 5754
|
||||
owner_login: serge-chat
|
||||
owner_html_url: https://github.com/serge-chat
|
||||
- name: fastapi-users
|
||||
html_url: https://github.com/fastapi-users/fastapi-users
|
||||
stars: 5599
|
||||
stars: 5849
|
||||
owner_login: fastapi-users
|
||||
owner_html_url: https://github.com/fastapi-users
|
||||
- name: serge
|
||||
html_url: https://github.com/serge-chat/serge
|
||||
stars: 5756
|
||||
owner_login: serge-chat
|
||||
owner_html_url: https://github.com/serge-chat
|
||||
- name: strawberry
|
||||
html_url: https://github.com/strawberry-graphql/strawberry
|
||||
stars: 4422
|
||||
stars: 4569
|
||||
owner_login: strawberry-graphql
|
||||
owner_html_url: https://github.com/strawberry-graphql
|
||||
- name: chatgpt-web-share
|
||||
html_url: https://github.com/chatpire/chatgpt-web-share
|
||||
stars: 4301
|
||||
stars: 4294
|
||||
owner_login: chatpire
|
||||
owner_html_url: https://github.com/chatpire
|
||||
- name: poem
|
||||
html_url: https://github.com/poem-web/poem
|
||||
stars: 4197
|
||||
stars: 4276
|
||||
owner_login: poem-web
|
||||
owner_html_url: https://github.com/poem-web
|
||||
- name: dynaconf
|
||||
html_url: https://github.com/dynaconf/dynaconf
|
||||
stars: 4144
|
||||
stars: 4202
|
||||
owner_login: dynaconf
|
||||
owner_html_url: https://github.com/dynaconf
|
||||
- name: atrilabs-engine
|
||||
html_url: https://github.com/Atri-Labs/atrilabs-engine
|
||||
stars: 4094
|
||||
stars: 4093
|
||||
owner_login: Atri-Labs
|
||||
owner_html_url: https://github.com/Atri-Labs
|
||||
- name: Kokoro-FastAPI
|
||||
html_url: https://github.com/remsky/Kokoro-FastAPI
|
||||
stars: 3739
|
||||
stars: 4019
|
||||
owner_login: remsky
|
||||
owner_html_url: https://github.com/remsky
|
||||
- name: logfire
|
||||
html_url: https://github.com/pydantic/logfire
|
||||
stars: 3614
|
||||
stars: 3805
|
||||
owner_login: pydantic
|
||||
owner_html_url: https://github.com/pydantic
|
||||
- name: LitServe
|
||||
html_url: https://github.com/Lightning-AI/LitServe
|
||||
stars: 3578
|
||||
stars: 3719
|
||||
owner_login: Lightning-AI
|
||||
owner_html_url: https://github.com/Lightning-AI
|
||||
- name: datamodel-code-generator
|
||||
html_url: https://github.com/koxudaxi/datamodel-code-generator
|
||||
stars: 3496
|
||||
owner_login: koxudaxi
|
||||
owner_html_url: https://github.com/koxudaxi
|
||||
- name: farfalle
|
||||
html_url: https://github.com/rashadphz/farfalle
|
||||
stars: 3459
|
||||
owner_login: rashadphz
|
||||
owner_html_url: https://github.com/rashadphz
|
||||
- name: fastapi-admin
|
||||
html_url: https://github.com/fastapi-admin/fastapi-admin
|
||||
stars: 3456
|
||||
stars: 3632
|
||||
owner_login: fastapi-admin
|
||||
owner_html_url: https://github.com/fastapi-admin
|
||||
- name: datamodel-code-generator
|
||||
html_url: https://github.com/koxudaxi/datamodel-code-generator
|
||||
stars: 3609
|
||||
owner_login: koxudaxi
|
||||
owner_html_url: https://github.com/koxudaxi
|
||||
- name: huma
|
||||
html_url: https://github.com/danielgtaylor/huma
|
||||
stars: 3447
|
||||
stars: 3603
|
||||
owner_login: danielgtaylor
|
||||
owner_html_url: https://github.com/danielgtaylor
|
||||
- name: farfalle
|
||||
html_url: https://github.com/rashadphz/farfalle
|
||||
stars: 3490
|
||||
owner_login: rashadphz
|
||||
owner_html_url: https://github.com/rashadphz
|
||||
- name: tracecat
|
||||
html_url: https://github.com/TracecatHQ/tracecat
|
||||
stars: 3254
|
||||
stars: 3379
|
||||
owner_login: TracecatHQ
|
||||
owner_html_url: https://github.com/TracecatHQ
|
||||
- name: opyrator
|
||||
html_url: https://github.com/ml-tooling/opyrator
|
||||
stars: 3134
|
||||
stars: 3135
|
||||
owner_login: ml-tooling
|
||||
owner_html_url: https://github.com/ml-tooling
|
||||
- name: docarray
|
||||
html_url: https://github.com/docarray/docarray
|
||||
stars: 3107
|
||||
stars: 3114
|
||||
owner_login: docarray
|
||||
owner_html_url: https://github.com/docarray
|
||||
- name: devpush
|
||||
html_url: https://github.com/hunvreus/devpush
|
||||
stars: 3097
|
||||
owner_login: hunvreus
|
||||
owner_html_url: https://github.com/hunvreus
|
||||
- name: fastapi-realworld-example-app
|
||||
html_url: https://github.com/nsidnev/fastapi-realworld-example-app
|
||||
stars: 2936
|
||||
stars: 3050
|
||||
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: 2804
|
||||
stars: 2911
|
||||
owner_login: tiangolo
|
||||
owner_html_url: https://github.com/tiangolo
|
||||
- name: best-of-web-python
|
||||
html_url: https://github.com/ml-tooling/best-of-web-python
|
||||
stars: 2610
|
||||
owner_login: ml-tooling
|
||||
owner_html_url: https://github.com/ml-tooling
|
||||
- name: mcp-context-forge
|
||||
html_url: https://github.com/IBM/mcp-context-forge
|
||||
stars: 2572
|
||||
stars: 2899
|
||||
owner_login: IBM
|
||||
owner_html_url: https://github.com/IBM
|
||||
- name: fastapi-react
|
||||
html_url: https://github.com/Buuntu/fastapi-react
|
||||
stars: 2451
|
||||
owner_login: Buuntu
|
||||
owner_html_url: https://github.com/Buuntu
|
||||
- name: RasaGPT
|
||||
html_url: https://github.com/paulpierre/RasaGPT
|
||||
stars: 2441
|
||||
owner_login: paulpierre
|
||||
owner_html_url: https://github.com/paulpierre
|
||||
- name: best-of-web-python
|
||||
html_url: https://github.com/ml-tooling/best-of-web-python
|
||||
stars: 2648
|
||||
owner_login: ml-tooling
|
||||
owner_html_url: https://github.com/ml-tooling
|
||||
- name: FastAPI-template
|
||||
html_url: https://github.com/s3rius/FastAPI-template
|
||||
stars: 2424
|
||||
stars: 2637
|
||||
owner_login: s3rius
|
||||
owner_html_url: https://github.com/s3rius
|
||||
- name: YC-Killer
|
||||
html_url: https://github.com/sahibzada-allahyar/YC-Killer
|
||||
stars: 2599
|
||||
owner_login: sahibzada-allahyar
|
||||
owner_html_url: https://github.com/sahibzada-allahyar
|
||||
- name: fastapi-react
|
||||
html_url: https://github.com/Buuntu/fastapi-react
|
||||
stars: 2569
|
||||
owner_login: Buuntu
|
||||
owner_html_url: https://github.com/Buuntu
|
||||
- name: Yuxi-Know
|
||||
html_url: https://github.com/xerrors/Yuxi-Know
|
||||
stars: 2563
|
||||
owner_login: xerrors
|
||||
owner_html_url: https://github.com/xerrors
|
||||
- name: sqladmin
|
||||
html_url: https://github.com/aminalaee/sqladmin
|
||||
stars: 2357
|
||||
stars: 2558
|
||||
owner_login: aminalaee
|
||||
owner_html_url: https://github.com/aminalaee
|
||||
- name: nextpy
|
||||
html_url: https://github.com/dot-agent/nextpy
|
||||
stars: 2324
|
||||
owner_login: dot-agent
|
||||
owner_html_url: https://github.com/dot-agent
|
||||
- name: RasaGPT
|
||||
html_url: https://github.com/paulpierre/RasaGPT
|
||||
stars: 2451
|
||||
owner_login: paulpierre
|
||||
owner_html_url: https://github.com/paulpierre
|
||||
- name: supabase-py
|
||||
html_url: https://github.com/supabase/supabase-py
|
||||
stars: 2236
|
||||
stars: 2344
|
||||
owner_login: supabase
|
||||
owner_html_url: https://github.com/supabase
|
||||
- name: nextpy
|
||||
html_url: https://github.com/dot-agent/nextpy
|
||||
stars: 2335
|
||||
owner_login: dot-agent
|
||||
owner_html_url: https://github.com/dot-agent
|
||||
- name: fastapi-utils
|
||||
html_url: https://github.com/fastapiutils/fastapi-utils
|
||||
stars: 2291
|
||||
owner_login: fastapiutils
|
||||
owner_html_url: https://github.com/fastapiutils
|
||||
- name: 30-Days-of-Python
|
||||
html_url: https://github.com/codingforentrepreneurs/30-Days-of-Python
|
||||
stars: 2210
|
||||
stars: 2220
|
||||
owner_login: codingforentrepreneurs
|
||||
owner_html_url: https://github.com/codingforentrepreneurs
|
||||
- name: langserve
|
||||
html_url: https://github.com/langchain-ai/langserve
|
||||
stars: 2171
|
||||
stars: 2215
|
||||
owner_login: langchain-ai
|
||||
owner_html_url: https://github.com/langchain-ai
|
||||
- name: fastapi-utils
|
||||
html_url: https://github.com/fastapiutils/fastapi-utils
|
||||
stars: 2164
|
||||
owner_login: fastapiutils
|
||||
owner_html_url: https://github.com/fastapiutils
|
||||
- name: solara
|
||||
html_url: https://github.com/widgetti/solara
|
||||
stars: 2102
|
||||
stars: 2122
|
||||
owner_login: widgetti
|
||||
owner_html_url: https://github.com/widgetti
|
||||
- name: Yuxi-Know
|
||||
html_url: https://github.com/xerrors/Yuxi-Know
|
||||
stars: 1995
|
||||
owner_login: xerrors
|
||||
owner_html_url: https://github.com/xerrors
|
||||
- name: mangum
|
||||
html_url: https://github.com/Kludex/mangum
|
||||
stars: 1989
|
||||
stars: 2029
|
||||
owner_login: Kludex
|
||||
owner_html_url: https://github.com/Kludex
|
||||
- name: python-week-2022
|
||||
html_url: https://github.com/rochacbruno/python-week-2022
|
||||
stars: 1816
|
||||
owner_login: rochacbruno
|
||||
owner_html_url: https://github.com/rochacbruno
|
||||
- name: agentkit
|
||||
html_url: https://github.com/BCG-X-Official/agentkit
|
||||
stars: 1789
|
||||
stars: 1912
|
||||
owner_login: BCG-X-Official
|
||||
owner_html_url: https://github.com/BCG-X-Official
|
||||
- name: manage-fastapi
|
||||
html_url: https://github.com/ycd/manage-fastapi
|
||||
stars: 1780
|
||||
stars: 1885
|
||||
owner_login: ycd
|
||||
owner_html_url: https://github.com/ycd
|
||||
- name: ormar
|
||||
html_url: https://github.com/collerek/ormar
|
||||
stars: 1777
|
||||
owner_login: collerek
|
||||
owner_html_url: https://github.com/collerek
|
||||
- name: openapi-python-client
|
||||
html_url: https://github.com/openapi-generators/openapi-python-client
|
||||
stars: 1707
|
||||
stars: 1862
|
||||
owner_login: openapi-generators
|
||||
owner_html_url: https://github.com/openapi-generators
|
||||
- name: piccolo
|
||||
html_url: https://github.com/piccolo-orm/piccolo
|
||||
stars: 1695
|
||||
stars: 1836
|
||||
owner_login: piccolo-orm
|
||||
owner_html_url: https://github.com/piccolo-orm
|
||||
- name: vue-fastapi-admin
|
||||
html_url: https://github.com/mizhexiaoxiao/vue-fastapi-admin
|
||||
stars: 1695
|
||||
stars: 1831
|
||||
owner_login: mizhexiaoxiao
|
||||
owner_html_url: https://github.com/mizhexiaoxiao
|
||||
- name: python-week-2022
|
||||
html_url: https://github.com/rochacbruno/python-week-2022
|
||||
stars: 1817
|
||||
owner_login: rochacbruno
|
||||
owner_html_url: https://github.com/rochacbruno
|
||||
- name: slowapi
|
||||
html_url: https://github.com/laurentS/slowapi
|
||||
stars: 1798
|
||||
owner_login: laurentS
|
||||
owner_html_url: https://github.com/laurentS
|
||||
- name: fastapi-cache
|
||||
html_url: https://github.com/long2ice/fastapi-cache
|
||||
stars: 1653
|
||||
stars: 1789
|
||||
owner_login: long2ice
|
||||
owner_html_url: https://github.com/long2ice
|
||||
- name: ormar
|
||||
html_url: https://github.com/collerek/ormar
|
||||
stars: 1783
|
||||
owner_login: collerek
|
||||
owner_html_url: https://github.com/collerek
|
||||
- name: termpair
|
||||
html_url: https://github.com/cs01/termpair
|
||||
stars: 1716
|
||||
owner_login: cs01
|
||||
owner_html_url: https://github.com/cs01
|
||||
- name: FastAPI-boilerplate
|
||||
html_url: https://github.com/benavlabs/FastAPI-boilerplate
|
||||
stars: 1660
|
||||
owner_login: benavlabs
|
||||
owner_html_url: https://github.com/benavlabs
|
||||
- name: fastapi-langgraph-agent-production-ready-template
|
||||
html_url: https://github.com/wassim249/fastapi-langgraph-agent-production-ready-template
|
||||
stars: 1638
|
||||
owner_login: wassim249
|
||||
owner_html_url: https://github.com/wassim249
|
||||
- name: langchain-serve
|
||||
html_url: https://github.com/jina-ai/langchain-serve
|
||||
stars: 1635
|
||||
owner_login: jina-ai
|
||||
owner_html_url: https://github.com/jina-ai
|
||||
- name: termpair
|
||||
html_url: https://github.com/cs01/termpair
|
||||
stars: 1624
|
||||
owner_login: cs01
|
||||
owner_html_url: https://github.com/cs01
|
||||
- name: slowapi
|
||||
html_url: https://github.com/laurentS/slowapi
|
||||
stars: 1620
|
||||
owner_login: laurentS
|
||||
owner_html_url: https://github.com/laurentS
|
||||
- name: coronavirus-tracker-api
|
||||
html_url: https://github.com/ExpDev07/coronavirus-tracker-api
|
||||
stars: 1576
|
||||
owner_login: ExpDev07
|
||||
owner_html_url: https://github.com/ExpDev07
|
||||
- name: fastapi-crudrouter
|
||||
html_url: https://github.com/awtkns/fastapi-crudrouter
|
||||
stars: 1546
|
||||
owner_login: awtkns
|
||||
owner_html_url: https://github.com/awtkns
|
||||
- name: FastAPI-boilerplate
|
||||
html_url: https://github.com/benavlabs/FastAPI-boilerplate
|
||||
stars: 1516
|
||||
owner_login: benavlabs
|
||||
owner_html_url: https://github.com/benavlabs
|
||||
- name: awesome-fastapi-projects
|
||||
html_url: https://github.com/Kludex/awesome-fastapi-projects
|
||||
stars: 1481
|
||||
stars: 1589
|
||||
owner_login: Kludex
|
||||
owner_html_url: https://github.com/Kludex
|
||||
- name: fastapi-pagination
|
||||
html_url: https://github.com/uriyyo/fastapi-pagination
|
||||
stars: 1453
|
||||
stars: 1585
|
||||
owner_login: uriyyo
|
||||
owner_html_url: https://github.com/uriyyo
|
||||
- name: coronavirus-tracker-api
|
||||
html_url: https://github.com/ExpDev07/coronavirus-tracker-api
|
||||
stars: 1574
|
||||
owner_login: ExpDev07
|
||||
owner_html_url: https://github.com/ExpDev07
|
||||
- name: fastapi-crudrouter
|
||||
html_url: https://github.com/awtkns/fastapi-crudrouter
|
||||
stars: 1559
|
||||
owner_login: awtkns
|
||||
owner_html_url: https://github.com/awtkns
|
||||
- name: bracket
|
||||
html_url: https://github.com/evroon/bracket
|
||||
stars: 1415
|
||||
stars: 1489
|
||||
owner_login: evroon
|
||||
owner_html_url: https://github.com/evroon
|
||||
- name: awesome-python-resources
|
||||
html_url: https://github.com/DjangoEx/awesome-python-resources
|
||||
stars: 1413
|
||||
owner_login: DjangoEx
|
||||
owner_html_url: https://github.com/DjangoEx
|
||||
- name: fastapi-boilerplate
|
||||
html_url: https://github.com/teamhide/fastapi-boilerplate
|
||||
stars: 1406
|
||||
owner_login: teamhide
|
||||
owner_html_url: https://github.com/teamhide
|
||||
- name: budgetml
|
||||
html_url: https://github.com/ebhy/budgetml
|
||||
stars: 1346
|
||||
owner_login: ebhy
|
||||
owner_html_url: https://github.com/ebhy
|
||||
- name: fastapi-amis-admin
|
||||
html_url: https://github.com/amisadmin/fastapi-amis-admin
|
||||
stars: 1342
|
||||
stars: 1475
|
||||
owner_login: amisadmin
|
||||
owner_html_url: https://github.com/amisadmin
|
||||
- name: fastapi-langgraph-agent-production-ready-template
|
||||
html_url: https://github.com/wassim249/fastapi-langgraph-agent-production-ready-template
|
||||
stars: 1334
|
||||
owner_login: wassim249
|
||||
owner_html_url: https://github.com/wassim249
|
||||
- name: fastapi-tutorial
|
||||
html_url: https://github.com/liaogx/fastapi-tutorial
|
||||
stars: 1303
|
||||
owner_login: liaogx
|
||||
owner_html_url: https://github.com/liaogx
|
||||
- name: fastapi_best_architecture
|
||||
html_url: https://github.com/fastapi-practices/fastapi_best_architecture
|
||||
stars: 1276
|
||||
owner_login: fastapi-practices
|
||||
owner_html_url: https://github.com/fastapi-practices
|
||||
- name: fastapi-boilerplate
|
||||
html_url: https://github.com/teamhide/fastapi-boilerplate
|
||||
stars: 1436
|
||||
owner_login: teamhide
|
||||
owner_html_url: https://github.com/teamhide
|
||||
- name: awesome-python-resources
|
||||
html_url: https://github.com/DjangoEx/awesome-python-resources
|
||||
stars: 1426
|
||||
owner_login: DjangoEx
|
||||
owner_html_url: https://github.com/DjangoEx
|
||||
- name: fastcrud
|
||||
html_url: https://github.com/benavlabs/fastcrud
|
||||
stars: 1272
|
||||
stars: 1414
|
||||
owner_login: benavlabs
|
||||
owner_html_url: https://github.com/benavlabs
|
||||
- name: fastapi-code-generator
|
||||
html_url: https://github.com/koxudaxi/fastapi-code-generator
|
||||
stars: 1253
|
||||
owner_login: koxudaxi
|
||||
owner_html_url: https://github.com/koxudaxi
|
||||
- name: prometheus-fastapi-instrumentator
|
||||
html_url: https://github.com/trallnag/prometheus-fastapi-instrumentator
|
||||
stars: 1246
|
||||
stars: 1388
|
||||
owner_login: trallnag
|
||||
owner_html_url: https://github.com/trallnag
|
||||
- name: bolt-python
|
||||
html_url: https://github.com/slackapi/bolt-python
|
||||
stars: 1221
|
||||
owner_login: slackapi
|
||||
owner_html_url: https://github.com/slackapi
|
||||
- name: bedrock-chat
|
||||
html_url: https://github.com/aws-samples/bedrock-chat
|
||||
stars: 1220
|
||||
owner_login: aws-samples
|
||||
owner_html_url: https://github.com/aws-samples
|
||||
- name: fastapi_production_template
|
||||
html_url: https://github.com/zhanymkanov/fastapi_production_template
|
||||
stars: 1202
|
||||
owner_login: zhanymkanov
|
||||
owner_html_url: https://github.com/zhanymkanov
|
||||
- name: fastapi-scaff
|
||||
html_url: https://github.com/atpuxiner/fastapi-scaff
|
||||
stars: 1193
|
||||
owner_login: atpuxiner
|
||||
owner_html_url: https://github.com/atpuxiner
|
||||
- name: langchain-extract
|
||||
html_url: https://github.com/langchain-ai/langchain-extract
|
||||
stars: 1164
|
||||
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: 1378
|
||||
owner_login: fastapi-practices
|
||||
owner_html_url: https://github.com/fastapi-practices
|
||||
- name: fastapi-code-generator
|
||||
html_url: https://github.com/koxudaxi/fastapi-code-generator
|
||||
stars: 1375
|
||||
owner_login: koxudaxi
|
||||
owner_html_url: https://github.com/koxudaxi
|
||||
- name: budgetml
|
||||
html_url: https://github.com/ebhy/budgetml
|
||||
stars: 1345
|
||||
owner_login: ebhy
|
||||
owner_html_url: https://github.com/ebhy
|
||||
- name: fastapi-tutorial
|
||||
html_url: https://github.com/liaogx/fastapi-tutorial
|
||||
stars: 1327
|
||||
owner_login: liaogx
|
||||
owner_html_url: https://github.com/liaogx
|
||||
- name: fastapi-alembic-sqlmodel-async
|
||||
html_url: https://github.com/jonra1993/fastapi-alembic-sqlmodel-async
|
||||
stars: 1149
|
||||
stars: 1259
|
||||
owner_login: jonra1993
|
||||
owner_html_url: https://github.com/jonra1993
|
||||
- name: odmantic
|
||||
html_url: https://github.com/art049/odmantic
|
||||
stars: 1133
|
||||
owner_login: art049
|
||||
owner_html_url: https://github.com/art049
|
||||
- name: fastapi-scaff
|
||||
html_url: https://github.com/atpuxiner/fastapi-scaff
|
||||
stars: 1255
|
||||
owner_login: atpuxiner
|
||||
owner_html_url: https://github.com/atpuxiner
|
||||
- name: bedrock-chat
|
||||
html_url: https://github.com/aws-samples/bedrock-chat
|
||||
stars: 1254
|
||||
owner_login: aws-samples
|
||||
owner_html_url: https://github.com/aws-samples
|
||||
- name: bolt-python
|
||||
html_url: https://github.com/slackapi/bolt-python
|
||||
stars: 1253
|
||||
owner_login: slackapi
|
||||
owner_html_url: https://github.com/slackapi
|
||||
- name: fastapi_production_template
|
||||
html_url: https://github.com/zhanymkanov/fastapi_production_template
|
||||
stars: 1217
|
||||
owner_login: zhanymkanov
|
||||
owner_html_url: https://github.com/zhanymkanov
|
||||
- name: langchain-extract
|
||||
html_url: https://github.com/langchain-ai/langchain-extract
|
||||
stars: 1176
|
||||
owner_login: langchain-ai
|
||||
owner_html_url: https://github.com/langchain-ai
|
||||
- name: restish
|
||||
html_url: https://github.com/rest-sh/restish
|
||||
stars: 1122
|
||||
stars: 1140
|
||||
owner_login: rest-sh
|
||||
owner_html_url: https://github.com/rest-sh
|
||||
- name: runhouse
|
||||
html_url: https://github.com/run-house/runhouse
|
||||
stars: 1047
|
||||
owner_login: run-house
|
||||
owner_html_url: https://github.com/run-house
|
||||
- name: flock
|
||||
html_url: https://github.com/Onelevenvy/flock
|
||||
stars: 1027
|
||||
owner_login: Onelevenvy
|
||||
owner_html_url: https://github.com/Onelevenvy
|
||||
- name: odmantic
|
||||
html_url: https://github.com/art049/odmantic
|
||||
stars: 1138
|
||||
owner_login: art049
|
||||
owner_html_url: https://github.com/art049
|
||||
- name: authx
|
||||
html_url: https://github.com/yezz123/authx
|
||||
stars: 999
|
||||
stars: 1119
|
||||
owner_login: yezz123
|
||||
owner_html_url: https://github.com/yezz123
|
||||
- name: autollm
|
||||
html_url: https://github.com/viddexa/autollm
|
||||
stars: 999
|
||||
owner_login: viddexa
|
||||
owner_html_url: https://github.com/viddexa
|
||||
- name: lanarky
|
||||
html_url: https://github.com/ajndkr/lanarky
|
||||
stars: 995
|
||||
owner_login: ajndkr
|
||||
owner_html_url: https://github.com/ajndkr
|
||||
- name: titiler
|
||||
html_url: https://github.com/developmentseed/titiler
|
||||
stars: 952
|
||||
owner_login: developmentseed
|
||||
owner_html_url: https://github.com/developmentseed
|
||||
- name: energy-forecasting
|
||||
html_url: https://github.com/iusztinpaul/energy-forecasting
|
||||
stars: 946
|
||||
owner_login: iusztinpaul
|
||||
owner_html_url: https://github.com/iusztinpaul
|
||||
- name: secure
|
||||
html_url: https://github.com/TypeError/secure
|
||||
stars: 944
|
||||
owner_login: TypeError
|
||||
owner_html_url: https://github.com/TypeError
|
||||
- name: langcorn
|
||||
html_url: https://github.com/msoedov/langcorn
|
||||
stars: 934
|
||||
owner_login: msoedov
|
||||
owner_html_url: https://github.com/msoedov
|
||||
- name: RuoYi-Vue3-FastAPI
|
||||
html_url: https://github.com/insistence/RuoYi-Vue3-FastAPI
|
||||
stars: 930
|
||||
owner_login: insistence
|
||||
owner_html_url: https://github.com/insistence
|
||||
- name: aktools
|
||||
html_url: https://github.com/akfamily/aktools
|
||||
stars: 916
|
||||
owner_login: akfamily
|
||||
owner_html_url: https://github.com/akfamily
|
||||
- name: every-pdf
|
||||
html_url: https://github.com/DDULDDUCK/every-pdf
|
||||
stars: 907
|
||||
owner_login: DDULDDUCK
|
||||
owner_html_url: https://github.com/DDULDDUCK
|
||||
- name: marker-api
|
||||
html_url: https://github.com/adithya-s-k/marker-api
|
||||
stars: 903
|
||||
owner_login: adithya-s-k
|
||||
owner_html_url: https://github.com/adithya-s-k
|
||||
- name: NoteDiscovery
|
||||
html_url: https://github.com/gamosoft/NoteDiscovery
|
||||
stars: 1107
|
||||
owner_login: gamosoft
|
||||
owner_html_url: https://github.com/gamosoft
|
||||
- name: flock
|
||||
html_url: https://github.com/Onelevenvy/flock
|
||||
stars: 1055
|
||||
owner_login: Onelevenvy
|
||||
owner_html_url: https://github.com/Onelevenvy
|
||||
- name: fastapi-observability
|
||||
html_url: https://github.com/blueswen/fastapi-observability
|
||||
stars: 902
|
||||
stars: 1038
|
||||
owner_login: blueswen
|
||||
owner_html_url: https://github.com/blueswen
|
||||
- name: fastapi-do-zero
|
||||
html_url: https://github.com/dunossauro/fastapi-do-zero
|
||||
stars: 900
|
||||
owner_login: dunossauro
|
||||
owner_html_url: https://github.com/dunossauro
|
||||
- name: aktools
|
||||
html_url: https://github.com/akfamily/aktools
|
||||
stars: 1027
|
||||
owner_login: akfamily
|
||||
owner_html_url: https://github.com/akfamily
|
||||
- name: RuoYi-Vue3-FastAPI
|
||||
html_url: https://github.com/insistence/RuoYi-Vue3-FastAPI
|
||||
stars: 1016
|
||||
owner_login: insistence
|
||||
owner_html_url: https://github.com/insistence
|
||||
- name: autollm
|
||||
html_url: https://github.com/viddexa/autollm
|
||||
stars: 1002
|
||||
owner_login: viddexa
|
||||
owner_html_url: https://github.com/viddexa
|
||||
- name: titiler
|
||||
html_url: https://github.com/developmentseed/titiler
|
||||
stars: 999
|
||||
owner_login: developmentseed
|
||||
owner_html_url: https://github.com/developmentseed
|
||||
- name: lanarky
|
||||
html_url: https://github.com/ajndkr/lanarky
|
||||
stars: 994
|
||||
owner_login: ajndkr
|
||||
owner_html_url: https://github.com/ajndkr
|
||||
- name: every-pdf
|
||||
html_url: https://github.com/DDULDDUCK/every-pdf
|
||||
stars: 985
|
||||
owner_login: DDULDDUCK
|
||||
owner_html_url: https://github.com/DDULDDUCK
|
||||
- name: enterprise-deep-research
|
||||
html_url: https://github.com/SalesforceAIResearch/enterprise-deep-research
|
||||
stars: 973
|
||||
owner_login: SalesforceAIResearch
|
||||
owner_html_url: https://github.com/SalesforceAIResearch
|
||||
- name: fastapi-mail
|
||||
html_url: https://github.com/sabuhish/fastapi-mail
|
||||
stars: 964
|
||||
owner_login: sabuhish
|
||||
owner_html_url: https://github.com/sabuhish
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ mattwang44:
|
|||
url: https://github.com/mattwang44
|
||||
tiangolo:
|
||||
login: tiangolo
|
||||
count: 55
|
||||
count: 56
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4
|
||||
url: https://github.com/tiangolo
|
||||
Laineyzhang55:
|
||||
|
|
@ -136,7 +136,7 @@ JavierSanchezCastro:
|
|||
alejsdev:
|
||||
login: alejsdev
|
||||
count: 37
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/90076947?u=447d12a1b347f466b35378bee4c7104cc9b2c571&v=4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/90076947?u=85ceac49fb87138aebe8d663912e359447329090&v=4
|
||||
url: https://github.com/alejsdev
|
||||
stlucasgarcia:
|
||||
login: stlucasgarcia
|
||||
|
|
@ -436,7 +436,7 @@ jburckel:
|
|||
peidrao:
|
||||
login: peidrao
|
||||
count: 13
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/32584628?u=64c634bb10381905038ff7faf3c8c3df47fb799a&v=4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/32584628?u=979c62398e16ff000cc0faa028e028efd679887c&v=4
|
||||
url: https://github.com/peidrao
|
||||
impocode:
|
||||
login: impocode
|
||||
|
|
@ -776,7 +776,7 @@ pablocm83:
|
|||
d2a-raudenaerde:
|
||||
login: d2a-raudenaerde
|
||||
count: 7
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/5213150?v=4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/5213150?u=e6d0ef65c571c7e544fc1c7ec151c7c0a72fb6bb&v=4
|
||||
url: https://github.com/d2a-raudenaerde
|
||||
valentinDruzhinin:
|
||||
login: valentinDruzhinin
|
||||
|
|
@ -1006,7 +1006,7 @@ takacs:
|
|||
anton2yakovlev:
|
||||
login: anton2yakovlev
|
||||
count: 5
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/44229180?u=bdd445ba99074b378e7298d23c4bf6d707d2c282&v=4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/44229180?u=ac245e57bc834ff80f08ca8128000bb650a77a3d&v=4
|
||||
url: https://github.com/anton2yakovlev
|
||||
ILoveSorasakiHina:
|
||||
login: ILoveSorasakiHina
|
||||
|
|
@ -1161,7 +1161,7 @@ cookie-byte217:
|
|||
AbolfazlKameli:
|
||||
login: AbolfazlKameli
|
||||
count: 4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/120686133?u=e41743da3c1820efafc59c5870cacd4f4425334c&v=4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/120686133?u=af8f025278cce0d489007071254e4055df60b78c&v=4
|
||||
url: https://github.com/AbolfazlKameli
|
||||
tyronedamasceno:
|
||||
login: tyronedamasceno
|
||||
|
|
@ -1196,7 +1196,7 @@ Xaraxx:
|
|||
Suyoung789:
|
||||
login: Suyoung789
|
||||
count: 3
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/31277231?u=744bd3e641413e19bfad6b06a90bb0887c3f9332&v=4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/31277231?u=1591aaf651eb860017231a36590050e154c026b6&v=4
|
||||
url: https://github.com/Suyoung789
|
||||
akagaeng:
|
||||
login: akagaeng
|
||||
|
|
@ -1206,7 +1206,7 @@ akagaeng:
|
|||
phamquanganh31101998:
|
||||
login: phamquanganh31101998
|
||||
count: 3
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/43257497?u=36fa4ee689415d869a98453083a7c4213d2136ee&v=4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/43257497?u=6b3419ea9e318c356c42a973fb947682590bd8d3&v=4
|
||||
url: https://github.com/phamquanganh31101998
|
||||
peebbv6364:
|
||||
login: peebbv6364
|
||||
|
|
@ -1806,7 +1806,7 @@ MrL8199:
|
|||
ivintoiu:
|
||||
login: ivintoiu
|
||||
count: 2
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1853336?u=5e3d0977f44661fb9712fa297cc8f7608ea6ce48&v=4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1853336?u=e3de5fd0ab17efc12256b4295285b504ca281440&v=4
|
||||
url: https://github.com/ivintoiu
|
||||
TechnoService2:
|
||||
login: TechnoService2
|
||||
|
|
@ -1841,7 +1841,7 @@ NavesSapnis:
|
|||
eqsdxr:
|
||||
login: eqsdxr
|
||||
count: 2
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/157279130?u=58fddf77ed76966eaa8c73eea9bea4bb0c53b673&v=4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/157279130?u=7927dc0366995334f9a18c3204a41d3a34d6d96f&v=4
|
||||
url: https://github.com/eqsdxr
|
||||
syedasamina56:
|
||||
login: syedasamina56
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
nilslindemann:
|
||||
login: nilslindemann
|
||||
count: 122
|
||||
count: 125
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/6892179?u=1dca6a22195d6cd1ab20737c0e19a4c55d639472&v=4
|
||||
url: https://github.com/nilslindemann
|
||||
jaystone776:
|
||||
|
|
@ -8,16 +8,16 @@ jaystone776:
|
|||
count: 46
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/11191137?u=299205a95e9b6817a43144a48b643346a5aac5cc&v=4
|
||||
url: https://github.com/jaystone776
|
||||
ceb10n:
|
||||
login: ceb10n
|
||||
count: 29
|
||||
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
|
||||
ceb10n:
|
||||
login: ceb10n
|
||||
count: 27
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/235213?u=edcce471814a1eba9f0cdaa4cd0de18921a940a6&v=4
|
||||
url: https://github.com/ceb10n
|
||||
tokusumi:
|
||||
login: tokusumi
|
||||
count: 23
|
||||
|
|
@ -103,6 +103,11 @@ pablocm83:
|
|||
count: 8
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/28315068?u=3310fbb05bb8bfc50d2c48b6cb64ac9ee4a14549&v=4
|
||||
url: https://github.com/pablocm83
|
||||
tiangolo:
|
||||
login: tiangolo
|
||||
count: 7
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4
|
||||
url: https://github.com/tiangolo
|
||||
ptt3199:
|
||||
login: ptt3199
|
||||
count: 7
|
||||
|
|
@ -118,11 +123,6 @@ batlopes:
|
|||
count: 6
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/33462923?u=0fb3d7acb316764616f11e4947faf080e49ad8d9&v=4
|
||||
url: https://github.com/batlopes
|
||||
tiangolo:
|
||||
login: tiangolo
|
||||
count: 6
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4
|
||||
url: https://github.com/tiangolo
|
||||
lucasbalieiro:
|
||||
login: lucasbalieiro
|
||||
count: 6
|
||||
|
|
@ -286,7 +286,7 @@ hsuanchi:
|
|||
alejsdev:
|
||||
login: alejsdev
|
||||
count: 3
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/90076947?u=447d12a1b347f466b35378bee4c7104cc9b2c571&v=4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/90076947?u=85ceac49fb87138aebe8d663912e359447329090&v=4
|
||||
url: https://github.com/alejsdev
|
||||
riroan:
|
||||
login: riroan
|
||||
|
|
@ -358,6 +358,11 @@ ruzia:
|
|||
count: 3
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/24503?v=4
|
||||
url: https://github.com/ruzia
|
||||
YuriiMotov:
|
||||
login: YuriiMotov
|
||||
count: 3
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=b9b13d598dddfab529a52d264df80a900bfe7060&v=4
|
||||
url: https://github.com/YuriiMotov
|
||||
izaguerreiro:
|
||||
login: izaguerreiro
|
||||
count: 2
|
||||
|
|
@ -543,8 +548,3 @@ EdmilsonRodrigues:
|
|||
count: 2
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/62777025?u=217d6f3cd6cc750bb8818a3af7726c8d74eb7c2d&v=4
|
||||
url: https://github.com/EdmilsonRodrigues
|
||||
YuriiMotov:
|
||||
login: YuriiMotov
|
||||
count: 2
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/109919500?u=b9b13d598dddfab529a52d264df80a900bfe7060&v=4
|
||||
url: https://github.com/YuriiMotov
|
||||
|
|
|
|||
|
|
@ -70,12 +70,22 @@ If you understood all this, you already know how those utility tools for securit
|
|||
|
||||
You most probably don't need these technical details.
|
||||
|
||||
These details are useful mainly if you had a FastAPI application older than 0.118.0 and you are facing issues with dependencies with `yield`.
|
||||
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.
|
||||
|
|
@ -134,7 +144,7 @@ This was changed in version 0.110.0 to fix unhandled memory consumption from for
|
|||
|
||||
### Background Tasks and Dependencies with `yield`, Technical Details { #background-tasks-and-dependencies-with-yield-technical-details }
|
||||
|
||||
Before FastAPI 0.106.0, raising exceptions after `yield` was not possible, the exit code in dependencies with `yield` was executed *after* the response was sent, so [Exception Handlers](../handling-errors.md#install-custom-exception-handlers){.internal-link target=_blank} would have already run.
|
||||
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){.internal-link target=_blank} would have already run.
|
||||
|
||||
This was designed this way mainly to allow using the same objects "yielded" by dependencies inside of background tasks, because the exit code would be executed after the background tasks were finished.
|
||||
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ If you want to learn more about HTTPS, check the guide [About HTTPS](../deployme
|
|||
|
||||
///
|
||||
|
||||
### How Proxy Forwarded Headers Work
|
||||
### 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**:
|
||||
|
||||
|
|
@ -228,7 +228,7 @@ Passing the `root_path` to `FastAPI` would be the equivalent of passing the `--r
|
|||
|
||||
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 <a href="http://127.0.0.1:8000" class="external-link" target="_blank">http://127.0.0.1:8000/app</a> you will see the normal response:
|
||||
But if you go with your browser to <a href="http://127.0.0.1:8000/app" class="external-link" target="_blank">http://127.0.0.1:8000/app</a> you will see the normal response:
|
||||
|
||||
```JSON
|
||||
{
|
||||
|
|
@ -443,6 +443,14 @@ 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`:
|
||||
|
|
|
|||
|
|
@ -1,3 +1,18 @@
|
|||
/* 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;
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@
|
|||
/* font-size: 18px; */
|
||||
font-size: 15px;
|
||||
/* font-family: 'Fira Mono', Consolas, Menlo, Monaco, 'Courier New', Courier, monospace; */
|
||||
font-family: 'Roboto Mono', '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;
|
||||
|
|
|
|||
|
|
@ -4,13 +4,21 @@ 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 }
|
||||
|
||||
**<a href="https://fastapicloud.com" class="external-link" target="_blank">FastAPI Cloud</a>** is built by the same author and team behind **FastAPI**.
|
||||
|
||||
It streamlines the process of **building**, **deploying**, and **accessing** an API with minimal effort.
|
||||
|
||||
It brings the same **developer experience** of building apps with FastAPI to **deploying** them to the cloud. 🎉
|
||||
|
||||
FastAPI Cloud is the primary sponsor and funding provider for the *FastAPI and friends* open source projects. ✨
|
||||
|
||||
## Cloud Providers - Sponsors { #cloud-providers-sponsors }
|
||||
|
||||
Some cloud providers ✨ [**sponsor FastAPI**](../help-fastapi.md#sponsor-the-author){.internal-link target=_blank} ✨, this ensures the continued and healthy **development** of FastAPI and its **ecosystem**.
|
||||
Some other cloud providers ✨ [**sponsor FastAPI**](../help-fastapi.md#sponsor-the-author){.internal-link target=_blank} ✨ too. 🙇
|
||||
|
||||
And it shows their true commitment to FastAPI and its **community** (you), as they not only want to provide you a **good service** but also want to make sure you have a **good and healthy framework**, FastAPI. 🙇
|
||||
|
||||
You might want to try their services and follow their guides:
|
||||
You might also want to consider them to follow their guides and try their services:
|
||||
|
||||
* <a href="https://docs.render.com/deploy-fastapi?utm_source=deploydoc&utm_medium=referral&utm_campaign=fastapi" class="external-link" target="_blank">Render</a>
|
||||
* <a href="https://docs.railway.com/guides/fastapi?utm_medium=integration&utm_source=docs&utm_campaign=fastapi" class="external-link" target="_blank">Railway</a>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,65 @@
|
|||
# FastAPI Cloud { #fastapi-cloud }
|
||||
|
||||
You can deploy your FastAPI app to <a href="https://fastapicloud.com" class="external-link" target="_blank">FastAPI Cloud</a> with **one command**, go and join the waiting list if you haven't. 🚀
|
||||
|
||||
## Login { #login }
|
||||
|
||||
Make sure you already have a **FastAPI Cloud** account (we invited you from the waiting list 😉).
|
||||
|
||||
Then log in:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ fastapi login
|
||||
|
||||
You are logged in to FastAPI Cloud 🚀
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
## Deploy { #deploy }
|
||||
|
||||
Now deploy your app, with **one command**:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ fastapi deploy
|
||||
|
||||
Deploying to FastAPI Cloud...
|
||||
|
||||
✅ Deployment successful!
|
||||
|
||||
🐔 Ready the chicken! Your app is ready at https://myapp.fastapicloud.dev
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
That's it! Now you can access your app at that URL. ✨
|
||||
|
||||
## About FastAPI Cloud { #about-fastapi-cloud }
|
||||
|
||||
**<a href="https://fastapicloud.com" class="external-link" target="_blank">FastAPI Cloud</a>** is built by the same author and team behind **FastAPI**.
|
||||
|
||||
It streamlines the process of **building**, **deploying**, and **accessing** an API with minimal effort.
|
||||
|
||||
It brings the same **developer experience** of building apps with FastAPI to **deploying** them to the cloud. 🎉
|
||||
|
||||
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. 🤓
|
||||
|
|
@ -16,6 +16,8 @@ There are several ways to do it depending on your specific use case and the tool
|
|||
|
||||
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 <a href="https://fastapicloud.com" class="external-link" target="_blank">**FastAPI Cloud**</a>, 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. ✨
|
||||
|
|
|
|||
|
|
@ -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, <a href="https://datatracker.ietf.org/doc/html/rfc7235#section-3.1" class="external-link" target="_blank">RFC 7235</a>, <a href="https://datatracker.ietf.org/doc/html/rfc9110#name-401-unauthorized" class="external-link" target="_blank">RFC 9110</a>.
|
||||
|
||||
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_py39.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.
|
||||
|
||||
///
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 16 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 7.1 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 7.2 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 6.3 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 10 KiB |
|
|
@ -46,20 +46,26 @@ The key features are:
|
|||
* **Robust**: Get production-ready code. With automatic interactive documentation.
|
||||
* **Standards-based**: Based on (and fully compatible with) the open standards for APIs: <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank">OpenAPI</a> (previously known as Swagger) and <a href="https://json-schema.org/" class="external-link" target="_blank">JSON Schema</a>.
|
||||
|
||||
<small>* estimation based on tests on an internal development team, building production applications.</small>
|
||||
<small>* estimation based on tests conducted by an internal development team, building production applications.</small>
|
||||
|
||||
## Sponsors { #sponsors }
|
||||
|
||||
<!-- sponsors -->
|
||||
|
||||
{% if sponsors %}
|
||||
### Keystone Sponsor
|
||||
|
||||
{% for sponsor in sponsors.keystone -%}
|
||||
<a href="{{ sponsor.url }}" target="_blank" title="{{ sponsor.title }}"><img src="{{ sponsor.img }}" style="border-radius:15px"></a>
|
||||
{% endfor -%}
|
||||
|
||||
### Gold and Silver Sponsors
|
||||
|
||||
{% for sponsor in sponsors.gold -%}
|
||||
<a href="{{ sponsor.url }}" target="_blank" title="{{ sponsor.title }}"><img src="{{ sponsor.img }}" style="border-radius:15px"></a>
|
||||
{% endfor -%}
|
||||
{%- for sponsor in sponsors.silver -%}
|
||||
<a href="{{ sponsor.url }}" target="_blank" title="{{ sponsor.title }}"><img src="{{ sponsor.img }}" style="border-radius:15px"></a>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
<!-- /sponsors -->
|
||||
|
||||
|
|
@ -444,6 +450,58 @@ For a more complete example including more features, see the <a href="https://fa
|
|||
* **Cookie Sessions**
|
||||
* ...and more.
|
||||
|
||||
### Deploy your app (optional) { #deploy-your-app-optional }
|
||||
|
||||
You can optionally deploy your FastAPI app to <a href="https://fastapicloud.com" class="external-link" target="_blank">FastAPI Cloud</a>, go and join the waiting list if you haven't. 🚀
|
||||
|
||||
If you already have a **FastAPI Cloud** account (we invited you from the waiting list 😉), you can deploy your application with one command.
|
||||
|
||||
Before deploying, make sure you are logged in:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ fastapi login
|
||||
|
||||
You are logged in to FastAPI Cloud 🚀
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
Then deploy your app:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ fastapi deploy
|
||||
|
||||
Deploying to FastAPI Cloud...
|
||||
|
||||
✅ Deployment successful!
|
||||
|
||||
🐔 Ready the chicken! Your app is ready at https://myapp.fastapicloud.dev
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
That's it! Now you can access your app at that URL. ✨
|
||||
|
||||
#### About FastAPI Cloud { #about-fastapi-cloud }
|
||||
|
||||
**<a href="https://fastapicloud.com" class="external-link" target="_blank">FastAPI Cloud</a>** is built by the same author and team behind **FastAPI**.
|
||||
|
||||
It streamlines the process of **building**, **deploying**, and **accessing** an API with minimal effort.
|
||||
|
||||
It brings the same **developer experience** of building apps with FastAPI to **deploying** them to the cloud. 🎉
|
||||
|
||||
FastAPI Cloud is the primary sponsor and funding provider for the *FastAPI and friends* open source projects. ✨
|
||||
|
||||
#### Deploy to other cloud providers { #deploy-to-other-cloud-providers }
|
||||
|
||||
FastAPI is open source and based on standards. You can deploy FastAPI apps to any cloud provider you choose.
|
||||
|
||||
Follow your cloud provider's guides to deploy FastAPI apps with them. 🤓
|
||||
|
||||
## Performance { #performance }
|
||||
|
||||
Independent TechEmpower benchmarks show **FastAPI** applications running under Uvicorn as <a href="https://www.techempower.com/benchmarks/#section=test&runid=7464e520-0dc2-473d-bd34-dbdfd7e85911&hw=ph&test=query&l=zijzen-7" class="external-link" target="_blank">one of the fastest Python frameworks available</a>, only below Starlette and Uvicorn themselves (used internally by FastAPI). (*)
|
||||
|
|
|
|||
|
|
@ -13,14 +13,14 @@ GitHub Repository: <a href="https://github.com/tiangolo/full-stack-fastapi-templ
|
|||
- 🔍 [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](https://vitejs.dev), and other parts of a modern frontend stack.
|
||||
- 🎨 [Chakra UI](https://chakra-ui.com) for the frontend components.
|
||||
- 💃 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 token authentication.
|
||||
- 🔑 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.
|
||||
|
|
|
|||
|
|
@ -7,6 +7,263 @@ hide:
|
|||
|
||||
## Latest Changes
|
||||
|
||||
### Docs
|
||||
|
||||
* 📝 Update tech stack in project generation docs. PR [#14472](https://github.com/fastapi/fastapi/pull/14472) by [@alejsdev](https://github.com/alejsdev).
|
||||
|
||||
## 0.124.0
|
||||
|
||||
### 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
|
||||
|
||||
### 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
|
||||
|
||||
### 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
|
||||
|
||||
### 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
|
||||
|
||||
### 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
|
||||
|
||||
### 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
|
||||
|
||||
### 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 condiitonal 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
|
||||
|
||||
### 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
|
||||
|
||||
### 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
|
||||
|
||||
### 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
|
||||
|
||||
### 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
|
||||
|
||||
### 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
|
||||
|
||||
### 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
|
||||
|
||||
### 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
|
||||
|
||||
### 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
|
||||
|
||||
### 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
|
||||
|
||||
### 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
|
||||
|
||||
* 📝 Upate 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
|
||||
|
||||
### 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
|
||||
|
||||
### 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
|
||||
|
||||
### 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
|
||||
|
||||
### 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
|
||||
|
||||
### 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
|
||||
|
||||
There are no major nor breaking changes in this release. ☕️
|
||||
|
|
|
|||
|
|
@ -184,6 +184,51 @@ If you raise any exception in the code from the *path operation function*, it wi
|
|||
|
||||
///
|
||||
|
||||
## Early exit and `scope` { #early-exit-and-scope }
|
||||
|
||||
Normally the exit code of dependencies with `yield` is executed **after the response** is sent to the client.
|
||||
|
||||
But if you know that you won't need to use the dependency after returning from the *path operation function*, you can use `Depends(scope="function")` to tell FastAPI that it should close the dependency after the *path operation function* returns, but **before** the **response is sent**.
|
||||
|
||||
{* ../../docs_src/dependencies/tutorial008e_an_py39.py hl[12,16] *}
|
||||
|
||||
`Depends()` receives a `scope` parameter that can be:
|
||||
|
||||
* `"function"`: start the dependency before the *path operation function* that handles the request, end the dependency after the *path operation function* ends, but **before** the response is sent back to the client. So, the dependency function will be executed **around** the *path operation **function***.
|
||||
* `"request"`: start the dependency before the *path operation function* that handles the request (similar to when using `"function"`), but end **after** the response is sent back to the client. So, the dependency function will be executed **around** the **request** and response cycle.
|
||||
|
||||
If not specified and the dependency has `yield`, it will have a `scope` of `"request"` by default.
|
||||
|
||||
### `scope` for sub-dependencies { #scope-for-sub-dependencies }
|
||||
|
||||
When you declare a dependency with a `scope="request"` (the default), any sub-dependency needs to also have a `scope` of `"request"`.
|
||||
|
||||
But a dependency with `scope` of `"function"` can have dependencies with `scope` of `"function"` and `scope` of `"request"`.
|
||||
|
||||
This is because any dependency needs to be able to run its exit code before the sub-dependencies, as it might need to still use them during its exit code.
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
|
||||
participant client as Client
|
||||
participant dep_req as Dep scope="request"
|
||||
participant dep_func as Dep scope="function"
|
||||
participant operation as Path Operation
|
||||
|
||||
client ->> dep_req: Start request
|
||||
Note over dep_req: Run code up to yield
|
||||
dep_req ->> dep_func: Pass dependency
|
||||
Note over dep_func: Run code up to yield
|
||||
dep_func ->> operation: Run path operation with dependency
|
||||
operation ->> dep_func: Return from path operation
|
||||
Note over dep_func: Run code after yield
|
||||
Note over dep_func: ✅ Dependency closed
|
||||
dep_func ->> client: Send response to client
|
||||
Note over client: Response sent
|
||||
Note over dep_req: Run code after yield
|
||||
Note over dep_req: ✅ Dependency closed
|
||||
```
|
||||
|
||||
## Dependencies with `yield`, `HTTPException`, `except` and Background Tasks { #dependencies-with-yield-httpexception-except-and-background-tasks }
|
||||
|
||||
Dependencies with `yield` have evolved over time to cover different use cases and fix some issues.
|
||||
|
|
|
|||
|
|
@ -143,6 +143,42 @@ And there are dozens of alternatives, all based on OpenAPI. You could easily add
|
|||
|
||||
You could also use it to generate code automatically, for clients that communicate with your API. For example, frontend, mobile or IoT applications.
|
||||
|
||||
### Deploy your app (optional) { #deploy-your-app-optional }
|
||||
|
||||
You can optionally deploy your FastAPI app to <a href="https://fastapicloud.com" class="external-link" target="_blank">FastAPI Cloud</a>, go and join the waiting list if you haven't. 🚀
|
||||
|
||||
If you already have a **FastAPI Cloud** account (we invited you from the waiting list 😉), you can deploy your application with one command.
|
||||
|
||||
Before deploying, make sure you are logged in:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ fastapi login
|
||||
|
||||
You are logged in to FastAPI Cloud 🚀
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
Then deploy your app:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ fastapi deploy
|
||||
|
||||
Deploying to FastAPI Cloud...
|
||||
|
||||
✅ Deployment successful!
|
||||
|
||||
🐔 Ready the chicken! Your app is ready at https://myapp.fastapicloud.dev
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
That's it! Now you can access your app at that URL. ✨
|
||||
|
||||
## Recap, step by step { #recap-step-by-step }
|
||||
|
||||
### Step 1: import `FastAPI` { #step-1-import-fastapi }
|
||||
|
|
@ -314,6 +350,26 @@ You can also return Pydantic models (you'll see more about that later).
|
|||
|
||||
There are many other objects and models that will be automatically converted to JSON (including ORMs, etc). Try using your favorite ones, it's highly probable that they are already supported.
|
||||
|
||||
### Step 6: Deploy it { #step-6-deploy-it }
|
||||
|
||||
Deploy your app to **<a href="https://fastapicloud.com" class="external-link" target="_blank">FastAPI Cloud</a>** with one command: `fastapi deploy`. 🎉
|
||||
|
||||
#### About FastAPI Cloud { #about-fastapi-cloud }
|
||||
|
||||
**<a href="https://fastapicloud.com" class="external-link" target="_blank">FastAPI Cloud</a>** is built by the same author and team behind **FastAPI**.
|
||||
|
||||
It streamlines the process of **building**, **deploying**, and **accessing** an API with minimal effort.
|
||||
|
||||
It brings the same **developer experience** of building apps with FastAPI to **deploying** them to the cloud. 🎉
|
||||
|
||||
FastAPI Cloud is the primary sponsor and funding provider for the *FastAPI and friends* open source projects. ✨
|
||||
|
||||
#### Deploy to other cloud providers { #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. 🤓
|
||||
|
||||
## Recap { #recap }
|
||||
|
||||
* Import `FastAPI`.
|
||||
|
|
@ -321,3 +377,4 @@ There are many other objects and models that will be automatically converted to
|
|||
* Write a **path operation decorator** using decorators like `@app.get("/")`.
|
||||
* Define a **path operation function**; for example, `def root(): ...`.
|
||||
* Run the development server using the command `fastapi dev`.
|
||||
* Optionally deploy your app with `fastapi deploy`.
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ There are a few differences:
|
|||
|
||||
* `Field(primary_key=True)` tells SQLModel that the `id` is the **primary key** in the SQL database (you can learn more about SQL primary keys in the SQLModel docs).
|
||||
|
||||
By having the type as `int | None`, SQLModel will know that this column should be an `INTEGER` in the SQL database and that it should be `NULLABLE`.
|
||||
**Note:** We use `int | None` for the primary key field so that in Python code we can *create an object without an `id`* (`id=None`), assuming the database will *generate it when saving*. SQLModel understands that the database will provide the `id` and *defines the column as a non-null `INTEGER`* in the database schema. See <a href="https://sqlmodel.tiangolo.com/tutorial/create-db-and-table/#primary-key-id" class="external-link" target="_blank">SQLModel docs on primary keys</a> for details.
|
||||
|
||||
* `Field(index=True)` tells SQLModel that it should create a **SQL index** for this column, that would allow faster lookups in the database when reading data filtered by this column.
|
||||
|
||||
|
|
|
|||
|
|
@ -242,6 +242,26 @@ $ python -m pip install --upgrade pip
|
|||
|
||||
</div>
|
||||
|
||||
/// tip
|
||||
|
||||
Sometimes, you might get a **`No module named pip`** error when trying to upgrade pip.
|
||||
|
||||
If this happens, install and upgrade pip using the command below:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ python -m ensurepip --upgrade
|
||||
|
||||
---> 100%
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
This command will install pip if it is not already installed and also ensures that the installed version of pip is at least as recent as the one available in `ensurepip`.
|
||||
|
||||
///
|
||||
|
||||
## Add `.gitignore` { #add-gitignore }
|
||||
|
||||
If you are using **Git** (you should), add a `.gitignore` file to exclude everything in your `.venv` from Git.
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
# Define this here and not in the main mkdocs.yml file because that one is auto
|
||||
# updated and written, and the script would remove the env var
|
||||
INHERIT: !ENV [INSIDERS_FILE, '../en/mkdocs.no-insiders.yml']
|
||||
markdown_extensions:
|
||||
pymdownx.highlight:
|
||||
linenums: !ENV [LINENUMS, false]
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
plugins:
|
||||
social:
|
||||
cards_layout_options:
|
||||
logo: ../en/docs/img/icon-white.svg
|
||||
typeset:
|
||||
markdown_extensions:
|
||||
material.extensions.preview:
|
||||
targets:
|
||||
include:
|
||||
- "*"
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
INHERIT: ../en/mkdocs.maybe-insiders.yml
|
||||
INHERIT: ../en/mkdocs.env.yml
|
||||
site_name: FastAPI
|
||||
site_description: FastAPI framework, high performance, easy to learn, fast to code, ready for production
|
||||
site_url: https://fastapi.tiangolo.com/
|
||||
|
|
@ -52,6 +52,10 @@ theme:
|
|||
repo_name: fastapi/fastapi
|
||||
repo_url: https://github.com/fastapi/fastapi
|
||||
plugins:
|
||||
social:
|
||||
cards_layout_options:
|
||||
logo: ../en/docs/img/icon-white.svg
|
||||
typeset:
|
||||
search: null
|
||||
macros:
|
||||
include_yaml:
|
||||
|
|
@ -192,6 +196,7 @@ nav:
|
|||
- Deployment:
|
||||
- deployment/index.md
|
||||
- deployment/versions.md
|
||||
- deployment/fastapicloud.md
|
||||
- deployment/https.md
|
||||
- deployment/manually.md
|
||||
- deployment/concepts.md
|
||||
|
|
@ -210,6 +215,7 @@ nav:
|
|||
- how-to/custom-docs-ui-assets.md
|
||||
- how-to/configure-swagger-ui.md
|
||||
- how-to/testing-database.md
|
||||
- how-to/authentication-error-status-code.md
|
||||
- Reference (Code API):
|
||||
- reference/index.md
|
||||
- reference/fastapi.md
|
||||
|
|
@ -252,6 +258,10 @@ nav:
|
|||
- management.md
|
||||
- release-notes.md
|
||||
markdown_extensions:
|
||||
material.extensions.preview:
|
||||
targets:
|
||||
include:
|
||||
- "*"
|
||||
abbr: null
|
||||
attr_list: null
|
||||
footnotes: null
|
||||
|
|
|
|||
|
|
@ -3,6 +3,13 @@
|
|||
{% block announce %}
|
||||
<div class="announce-wrapper">
|
||||
<div id="announce-left">
|
||||
<div class="item">
|
||||
<a class="announce-link" href="https://fastapicloud.com" target="_blank">
|
||||
<span class="twemoji">
|
||||
{% include ".icons/material/cloud-arrow-up.svg" %}
|
||||
</span> Join the <strong>FastAPI Cloud</strong> waiting list 🚀
|
||||
</a>
|
||||
</div>
|
||||
<div class="item">
|
||||
<a class="announce-link" href="https://x.com/fastapi" target="_blank">
|
||||
<span class="twemoji">
|
||||
|
|
@ -80,6 +87,18 @@
|
|||
<img class="sponsor-image" src="/img/sponsors/railway-banner.png" />
|
||||
</a>
|
||||
</div>
|
||||
<div class="item">
|
||||
<a title="SerpApi: Web Search API" style="display: block; position: relative;" href="https://serpapi.com/?utm_source=fastapi_website" target="_blank">
|
||||
<span class="sponsor-badge">sponsor</span>
|
||||
<img class="sponsor-image" src="/img/sponsors/serpapi-banner.png" />
|
||||
</a>
|
||||
</div>
|
||||
<div class="item">
|
||||
<a title="Greptile: The AI Code Reviewer" style="display: block; position: relative;" href="https://www.greptile.com/?utm_source=fastapi&utm_medium=sponsorship&utm_campaign=fastapi_sponsor_page" target="_blank">
|
||||
<span class="sponsor-badge">sponsor</span>
|
||||
<img class="sponsor-image" src="/img/sponsors/greptile-banner.png" />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
/// warning
|
||||
|
||||
The current page still doesn't have a translation for this language.
|
||||
This page hasn’t been translated into your language yet. 🌍
|
||||
|
||||
But you can help translating it: [Contributing](https://fastapi.tiangolo.com/contributing/){.internal-link target=_blank}.
|
||||
We’re currently switching to an automated translation system 🤖, which will help keep all translations complete and up to date.
|
||||
|
||||
Learn more: [Contributing – Translations](https://fastapi.tiangolo.com/contributing/#translations){.internal-link target=_blank}
|
||||
|
||||
///
|
||||
|
|
|
|||
|
|
@ -0,0 +1,503 @@
|
|||
# Arquivo de teste de LLM { #llm-test-file }
|
||||
|
||||
Este documento testa se o <abbr title="Large Language Model – Modelo de Linguagem de Grande Porte">LLM</abbr>, que traduz a documentação, entende o `general_prompt` em `scripts/translate.py` e o prompt específico do idioma em `docs/{language code}/llm-prompt.md`. O prompt específico do idioma é anexado ao `general_prompt`.
|
||||
|
||||
Os testes adicionados aqui serão vistos por todos os autores dos prompts específicos de idioma.
|
||||
|
||||
Use da seguinte forma:
|
||||
|
||||
* Tenha um prompt específico do idioma – `docs/{language code}/llm-prompt.md`.
|
||||
* Faça uma tradução nova deste documento para o seu idioma de destino (veja, por exemplo, o comando `translate-page` do `translate.py`). Isso criará a tradução em `docs/{language code}/docs/_llm-test.md`.
|
||||
* Verifique se está tudo certo na tradução.
|
||||
* Se necessário, melhore seu prompt específico do idioma, o prompt geral ou o documento em inglês.
|
||||
* Em seguida, corrija manualmente os problemas restantes na tradução, para que fique uma boa tradução.
|
||||
* Retraduzir, tendo a boa tradução no lugar. O resultado ideal seria que o LLM não fizesse mais mudanças na tradução. Isso significa que o prompt geral e o seu prompt específico do idioma estão tão bons quanto possível (às vezes fará algumas mudanças aparentemente aleatórias, a razão é que <a href="https://doublespeak.chat/#/handbook#deterministic-output" class="external-link" target="_blank">LLMs não são algoritmos determinísticos</a>).
|
||||
|
||||
Os testes:
|
||||
|
||||
## Trechos de código { #code-snippets}
|
||||
|
||||
//// tab | Teste
|
||||
|
||||
Este é um trecho de código: `foo`. E este é outro trecho de código: `bar`. E mais um: `baz quux`.
|
||||
|
||||
////
|
||||
|
||||
//// tab | Informações
|
||||
|
||||
O conteúdo dos trechos de código deve ser deixado como está.
|
||||
|
||||
Veja a seção `### Content of code snippets` no prompt geral em `scripts/translate.py`.
|
||||
|
||||
////
|
||||
|
||||
## Citações { #quotes }
|
||||
|
||||
//// tab | Teste
|
||||
|
||||
Ontem, meu amigo escreveu: "Se você soletrar incorretamente corretamente, você a soletrou incorretamente". Ao que respondi: "Correto, mas 'incorrectly' está incorretamente não '"incorrectly"'".
|
||||
|
||||
/// note | Nota
|
||||
|
||||
O LLM provavelmente vai traduzir isso errado. O interessante é apenas se ele mantém a tradução corrigida ao retraduzir.
|
||||
|
||||
///
|
||||
|
||||
////
|
||||
|
||||
//// tab | Informações
|
||||
|
||||
O autor do prompt pode escolher se deseja converter aspas neutras em aspas tipográficas. Também é aceitável deixá-las como estão.
|
||||
|
||||
Veja, por exemplo, a seção `### Quotes` em `docs/de/llm-prompt.md`.
|
||||
|
||||
////
|
||||
|
||||
## Citações em trechos de código { #quotes-in-code-snippets}
|
||||
|
||||
//// tab | Teste
|
||||
|
||||
`pip install "foo[bar]"`
|
||||
|
||||
Exemplos de literais de string em trechos de código: `"this"`, `'that'`.
|
||||
|
||||
Um exemplo difícil de literais de string em trechos de código: `f"I like {'oranges' if orange else "apples"}"`
|
||||
|
||||
Pesado: `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 | Informações
|
||||
|
||||
... No entanto, as aspas dentro de trechos de código devem permanecer como estão.
|
||||
|
||||
////
|
||||
|
||||
## Blocos de código { #code-blocks }
|
||||
|
||||
//// tab | Teste
|
||||
|
||||
Um exemplo de código Bash...
|
||||
|
||||
```bash
|
||||
# Imprimir uma saudação ao universo
|
||||
echo "Hello universe"
|
||||
```
|
||||
|
||||
...e um exemplo de código de console...
|
||||
|
||||
```console
|
||||
$ <font color="#4E9A06">fastapi</font> run <u style="text-decoration-style:solid">main.py</u>
|
||||
<span style="background-color:#009485"><font color="#D3D7CF"> FastAPI </font></span> Starting server
|
||||
Searching for package file structure
|
||||
```
|
||||
|
||||
...e outro exemplo de código de console...
|
||||
|
||||
```console
|
||||
// Crie um diretório "Code"
|
||||
$ mkdir code
|
||||
// Entre nesse diretório
|
||||
$ cd code
|
||||
```
|
||||
|
||||
...e um exemplo de código Python...
|
||||
|
||||
```Python
|
||||
wont_work() # Isto não vai funcionar 😱
|
||||
works(foo="bar") # Isto funciona 🎉
|
||||
```
|
||||
|
||||
...e é isso.
|
||||
|
||||
////
|
||||
|
||||
//// tab | Informações
|
||||
|
||||
O código em blocos de código não deve ser modificado, com exceção dos comentários.
|
||||
|
||||
Veja a seção `### Content of code blocks` no prompt geral em `scripts/translate.py`.
|
||||
|
||||
////
|
||||
|
||||
## Abas e caixas coloridas { #tabs-and-colored-boxes }
|
||||
|
||||
//// tab | Teste
|
||||
|
||||
/// info | Informação
|
||||
Algum texto
|
||||
///
|
||||
|
||||
/// note | Nota
|
||||
Algum texto
|
||||
///
|
||||
|
||||
/// note | Detalhes Técnicos
|
||||
Algum texto
|
||||
///
|
||||
|
||||
/// check | Verifique
|
||||
Algum texto
|
||||
///
|
||||
|
||||
/// tip | Dica
|
||||
Algum texto
|
||||
///
|
||||
|
||||
/// warning | Atenção
|
||||
Algum texto
|
||||
///
|
||||
|
||||
/// danger | Cuidado
|
||||
Algum texto
|
||||
///
|
||||
|
||||
////
|
||||
|
||||
//// tab | Informações
|
||||
|
||||
Abas e blocos `Info`/`Note`/`Warning`/etc. devem ter a tradução do seu título adicionada após uma barra vertical (`|`).
|
||||
|
||||
Veja as seções `### Special blocks` e `### Tab blocks` no prompt geral em `scripts/translate.py`.
|
||||
|
||||
////
|
||||
|
||||
## Links da Web e internos { #web-and-internal-links }
|
||||
|
||||
//// tab | Teste
|
||||
|
||||
O texto do link deve ser traduzido, o endereço do link deve permanecer inalterado:
|
||||
|
||||
* [Link para o título acima](#code-snippets)
|
||||
* [Link interno](index.md#installation){.internal-link target=_blank}
|
||||
* <a href="https://sqlmodel.tiangolo.com/" class="external-link" target="_blank">Link externo</a>
|
||||
* <a href="https://fastapi.tiangolo.com/css/styles.css" class="external-link" target="_blank">Link para um estilo</a>
|
||||
* <a href="https://fastapi.tiangolo.com/js/logic.js" class="external-link" target="_blank">Link para um script</a>
|
||||
* <a href="https://fastapi.tiangolo.com/img/foo.jpg" class="external-link" target="_blank">Link para uma imagem</a>
|
||||
|
||||
O texto do link deve ser traduzido, o endereço do link deve apontar para a tradução:
|
||||
|
||||
* <a href="https://fastapi.tiangolo.com/pt/" class="external-link" target="_blank">Link do FastAPI</a>
|
||||
|
||||
////
|
||||
|
||||
//// tab | Informações
|
||||
|
||||
Os links devem ser traduzidos, mas seus endereços devem permanecer inalterados. Uma exceção são links absolutos para páginas da documentação do FastAPI. Nesse caso, devem apontar para a tradução.
|
||||
|
||||
Veja a seção `### Links` no prompt geral em `scripts/translate.py`.
|
||||
|
||||
////
|
||||
|
||||
## Elementos HTML "abbr" { #html-abbr-elements }
|
||||
|
||||
//// tab | Teste
|
||||
|
||||
Aqui estão algumas coisas envolvidas em elementos HTML "abbr" (algumas são inventadas):
|
||||
|
||||
### O abbr fornece uma frase completa { #the-abbr-gives-a-full-phrase }
|
||||
|
||||
* <abbr title="Getting Things Done – Fazer as Coisas">GTD</abbr>
|
||||
* <abbr title="menos que"><code>lt</code></abbr>
|
||||
* <abbr title="XML Web Token – Token Web XML">XWT</abbr>
|
||||
* <abbr title="Parallel Server Gateway Interface – Interface de Gateway de Servidor Paralelo">PSGI</abbr>
|
||||
|
||||
### O abbr fornece uma explicação { #the-abbr-gives-an-explanation }
|
||||
|
||||
* <abbr title="Um grupo de máquinas configuradas para estarem conectadas e trabalharem juntas de alguma forma.">cluster</abbr>
|
||||
* <abbr title="Um método de aprendizado de máquina que usa redes neurais artificiais com numerosas camadas ocultas entre as camadas de entrada e saída, desenvolvendo assim uma estrutura interna abrangente">Aprendizado Profundo</abbr>
|
||||
|
||||
### O abbr fornece uma frase completa e uma explicação { #the-abbr-gives-a-full-phrase-and-an-explanation }
|
||||
|
||||
* <abbr title="Mozilla Developer Network – Rede de Desenvolvedores da Mozilla: documentação para desenvolvedores, escrita pelo pessoal do Firefox">MDN</abbr>
|
||||
* <abbr title="Input/Output – Entrada/Saída: leitura ou escrita em disco, comunicações de rede.">I/O</abbr>.
|
||||
|
||||
////
|
||||
|
||||
//// tab | Informações
|
||||
|
||||
Os atributos "title" dos elementos "abbr" são traduzidos seguindo algumas instruções específicas.
|
||||
|
||||
As traduções podem adicionar seus próprios elementos "abbr" que o LLM não deve remover. Por exemplo, para explicar palavras em inglês.
|
||||
|
||||
Veja a seção `### HTML abbr elements` no prompt geral em `scripts/translate.py`.
|
||||
|
||||
////
|
||||
|
||||
## Títulos { #headings }
|
||||
|
||||
//// tab | Teste
|
||||
|
||||
### Desenvolver uma aplicação web - um tutorial { #develop-a-webapp-a-tutorial }
|
||||
|
||||
Olá.
|
||||
|
||||
### Anotações de tipo e -anotações { #type-hints-and-annotations }
|
||||
|
||||
Olá novamente.
|
||||
|
||||
### Super- e subclasses { #super-and-subclasses }
|
||||
|
||||
Olá novamente.
|
||||
|
||||
////
|
||||
|
||||
//// tab | Informações
|
||||
|
||||
A única regra rígida para títulos é que o LLM deixe a parte do hash dentro de chaves inalterada, o que garante que os links não quebrem.
|
||||
|
||||
Veja a seção `### Headings` no prompt geral em `scripts/translate.py`.
|
||||
|
||||
Para algumas instruções específicas do idioma, veja, por exemplo, a seção `### Headings` em `docs/de/llm-prompt.md`.
|
||||
|
||||
////
|
||||
|
||||
## Termos usados na documentação { #terms-used-in-the-docs }
|
||||
|
||||
//// tab | Teste
|
||||
|
||||
* você
|
||||
* seu
|
||||
|
||||
* por exemplo
|
||||
* etc.
|
||||
|
||||
* `foo` como um `int`
|
||||
* `bar` como uma `str`
|
||||
* `baz` como uma `list`
|
||||
|
||||
* o Tutorial - Guia do Usuário
|
||||
* o Guia do Usuário Avançado
|
||||
* a documentação do SQLModel
|
||||
* a documentação da API
|
||||
* a documentação automática
|
||||
|
||||
* Ciência de Dados
|
||||
* Aprendizado Profundo
|
||||
* Aprendizado de Máquina
|
||||
* Injeção de Dependências
|
||||
* autenticação HTTP Basic
|
||||
* HTTP Digest
|
||||
* formato ISO
|
||||
* o padrão JSON Schema
|
||||
* o JSON schema
|
||||
* a definição do schema
|
||||
* Fluxo de Senha
|
||||
* Mobile
|
||||
|
||||
* descontinuado
|
||||
* projetado
|
||||
* inválido
|
||||
* dinamicamente
|
||||
* padrão
|
||||
* padrão predefinido
|
||||
* sensível a maiúsculas e minúsculas
|
||||
* não sensível a maiúsculas e minúsculas
|
||||
|
||||
* servir a aplicação
|
||||
* servir a página
|
||||
|
||||
* o app
|
||||
* a aplicação
|
||||
|
||||
* a requisição
|
||||
* a resposta
|
||||
* a resposta de erro
|
||||
|
||||
* a operação de rota
|
||||
* o decorador de operação de rota
|
||||
* a função de operação de rota
|
||||
|
||||
* o corpo
|
||||
* o corpo da requisição
|
||||
* o corpo da resposta
|
||||
* o corpo JSON
|
||||
* o corpo do formulário
|
||||
* o corpo do arquivo
|
||||
* o corpo da função
|
||||
|
||||
* o parâmetro
|
||||
* o parâmetro de corpo
|
||||
* o parâmetro de path
|
||||
* o parâmetro de query
|
||||
* o parâmetro de cookie
|
||||
* o parâmetro de header
|
||||
* o parâmetro de formulário
|
||||
* o parâmetro da função
|
||||
|
||||
* o evento
|
||||
* o evento de inicialização
|
||||
* a inicialização do servidor
|
||||
* o evento de encerramento
|
||||
* o evento de lifespan
|
||||
|
||||
* o manipulador
|
||||
* o manipulador de eventos
|
||||
* o manipulador de exceções
|
||||
* tratar
|
||||
|
||||
* o modelo
|
||||
* o modelo Pydantic
|
||||
* o modelo de dados
|
||||
* o modelo de banco de dados
|
||||
* o modelo de formulário
|
||||
* o objeto de modelo
|
||||
|
||||
* a classe
|
||||
* a classe base
|
||||
* a classe pai
|
||||
* a subclasse
|
||||
* a classe filha
|
||||
* a classe irmã
|
||||
* o método de classe
|
||||
|
||||
* o cabeçalho
|
||||
* os cabeçalhos
|
||||
* o cabeçalho de autorização
|
||||
* o cabeçalho `Authorization`
|
||||
* o cabeçalho encaminhado
|
||||
|
||||
* o sistema de injeção de dependências
|
||||
* a dependência
|
||||
* o dependable
|
||||
* o dependant
|
||||
|
||||
* limitado por I/O
|
||||
* limitado por CPU
|
||||
* concorrência
|
||||
* paralelismo
|
||||
* multiprocessamento
|
||||
|
||||
* a env var
|
||||
* a variável de ambiente
|
||||
* o `PATH`
|
||||
* a variável `PATH`
|
||||
|
||||
* a autenticação
|
||||
* o provedor de autenticação
|
||||
* a autorização
|
||||
* o formulário de autorização
|
||||
* o provedor de autorização
|
||||
* o usuário se autentica
|
||||
* o sistema autentica o usuário
|
||||
|
||||
* a CLI
|
||||
* a interface de linha de comando
|
||||
|
||||
* o servidor
|
||||
* o cliente
|
||||
|
||||
* o provedor de nuvem
|
||||
* o serviço de nuvem
|
||||
|
||||
* o desenvolvimento
|
||||
* as etapas de desenvolvimento
|
||||
|
||||
* o dict
|
||||
* o dicionário
|
||||
* a enumeração
|
||||
* o enum
|
||||
* o membro do enum
|
||||
|
||||
* o codificador
|
||||
* o decodificador
|
||||
* codificar
|
||||
* decodificar
|
||||
|
||||
* a exceção
|
||||
* lançar
|
||||
|
||||
* a expressão
|
||||
* a instrução
|
||||
|
||||
* o frontend
|
||||
* o backend
|
||||
|
||||
* a discussão do GitHub
|
||||
* a issue do GitHub
|
||||
|
||||
* o desempenho
|
||||
* a otimização de desempenho
|
||||
|
||||
* o tipo de retorno
|
||||
* o valor de retorno
|
||||
|
||||
* a segurança
|
||||
* o esquema de segurança
|
||||
|
||||
* a tarefa
|
||||
* a tarefa em segundo plano
|
||||
* a função da tarefa
|
||||
|
||||
* o template
|
||||
* o mecanismo de template
|
||||
|
||||
* a anotação de tipo
|
||||
* a anotação de tipo
|
||||
|
||||
* o worker de servidor
|
||||
* o worker do Uvicorn
|
||||
* o Worker do Gunicorn
|
||||
* o processo worker
|
||||
* a classe de worker
|
||||
* a carga de trabalho
|
||||
|
||||
* a implantação
|
||||
* implantar
|
||||
|
||||
* o SDK
|
||||
* o kit de desenvolvimento de software
|
||||
|
||||
* o `APIRouter`
|
||||
* o `requirements.txt`
|
||||
* o Bearer Token
|
||||
* a alteração com quebra de compatibilidade
|
||||
* o bug
|
||||
* o botão
|
||||
* o chamável
|
||||
* o código
|
||||
* o commit
|
||||
* o gerenciador de contexto
|
||||
* a corrotina
|
||||
* a sessão do banco de dados
|
||||
* o disco
|
||||
* o domínio
|
||||
* o mecanismo
|
||||
* o X falso
|
||||
* o método HTTP GET
|
||||
* o item
|
||||
* a biblioteca
|
||||
* o lifespan
|
||||
* o bloqueio
|
||||
* o middleware
|
||||
* a aplicação mobile
|
||||
* o módulo
|
||||
* a montagem
|
||||
* a rede
|
||||
* a origem
|
||||
* a sobrescrita
|
||||
* a carga útil
|
||||
* o processador
|
||||
* a propriedade
|
||||
* o proxy
|
||||
* o pull request
|
||||
* a consulta
|
||||
* a RAM
|
||||
* a máquina remota
|
||||
* o código de status
|
||||
* a string
|
||||
* a tag
|
||||
* o framework web
|
||||
* o curinga
|
||||
* retornar
|
||||
* validar
|
||||
|
||||
////
|
||||
|
||||
//// tab | Informações
|
||||
|
||||
Esta é uma lista não completa e não normativa de termos (principalmente) técnicos vistos na documentação. Pode ser útil para o autor do prompt descobrir para quais termos o LLM precisa de uma ajudinha. Por exemplo, quando ele continua revertendo uma boa tradução para uma tradução subótima. Ou quando tem problemas para conjugar/declinar um termo no seu idioma.
|
||||
|
||||
Veja, por exemplo, a seção `### List of English terms and their preferred German translations` em `docs/de/llm-prompt.md`.
|
||||
|
||||
////
|
||||
|
|
@ -1,3 +1,3 @@
|
|||
# Sobre
|
||||
# Sobre { #about }
|
||||
|
||||
Sobre o FastAPI, seus padrões, inspirações e muito mais. 🤓
|
||||
Sobre o FastAPI, seu design, inspiração e mais. 🤓
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# Retornos Adicionais no OpenAPI
|
||||
# Retornos Adicionais no OpenAPI { #additional-responses-in-openapi }
|
||||
|
||||
/// warning | Aviso
|
||||
/// warning | Atenção
|
||||
|
||||
Este é um tema bem avançado.
|
||||
|
||||
|
|
@ -14,7 +14,7 @@ Essas respostas adicionais serão incluídas no esquema do OpenAPI, e também ap
|
|||
|
||||
Porém para as respostas adicionais, você deve garantir que está retornando um `Response` como por exemplo o `JSONResponse` diretamente, junto com o código de status e o conteúdo.
|
||||
|
||||
## Retorno Adicional com `model`
|
||||
## Retorno Adicional com `model` { #additional-response-with-model }
|
||||
|
||||
Você pode fornecer o parâmetro `responses` aos seus *decoradores de caminho*.
|
||||
|
||||
|
|
@ -49,7 +49,7 @@ O local correto é:
|
|||
|
||||
///
|
||||
|
||||
O retorno gerado no OpenAI para esta *operação de caminho* será:
|
||||
O retorno gerado no OpenAPI para esta *operação de rota* será:
|
||||
|
||||
```JSON hl_lines="3-12"
|
||||
{
|
||||
|
|
@ -169,11 +169,11 @@ Os esquemas são referenciados em outro local dentro do esquema OpenAPI:
|
|||
}
|
||||
```
|
||||
|
||||
## Media types adicionais para o retorno principal
|
||||
## Media types adicionais para o retorno principal { #additional-media-types-for-the-main-response }
|
||||
|
||||
Você pode utilizar o mesmo parâmetro `responses` para adicionar diferentes media types para o mesmo retorno principal.
|
||||
|
||||
Por exemplo, você pode adicionar um media type adicional de `image/png`, declarando que a sua *operação de caminho* pode retornar um objeto JSON (com o media type `application/json`) ou uma imagem PNG:
|
||||
Por exemplo, você pode adicionar um media type adicional de `image/png`, declarando que a sua *operação de rota* pode retornar um objeto JSON (com o media type `application/json`) ou uma imagem PNG:
|
||||
|
||||
{* ../../docs_src/additional_responses/tutorial002.py hl[19:24,28] *}
|
||||
|
||||
|
|
@ -191,7 +191,7 @@ Porém se você especificou uma classe de retorno com o valor `None` como media
|
|||
|
||||
///
|
||||
|
||||
## Combinando informações
|
||||
## Combinando informações { #combining-information }
|
||||
|
||||
Você também pode combinar informações de diferentes lugares, incluindo os parâmetros `response_model`, `status_code`, e `responses`.
|
||||
|
||||
|
|
@ -209,9 +209,9 @@ Isso será combinado e incluído em seu OpenAPI, e disponibilizado na documenta
|
|||
|
||||
<img src="/img/tutorial/additional-responses/image01.png">
|
||||
|
||||
## Combinar retornos predefinidos e personalizados
|
||||
## Combinar retornos predefinidos e personalizados { #combine-predefined-responses-and-custom-ones }
|
||||
|
||||
Você pode querer possuir alguns retornos predefinidos que são aplicados para diversas *operações de caminho*, porém você deseja combinar com retornos personalizados que são necessários para cada *operação de caminho*.
|
||||
Você pode querer possuir alguns retornos predefinidos que são aplicados para diversas *operações de rota*, porém você deseja combinar com retornos personalizados que são necessários para cada *operação de rota*.
|
||||
|
||||
Para estes casos, você pode utilizar a técnica do Python de "desempacotamento" de um `dict` utilizando `**dict_to_unpack`:
|
||||
|
||||
|
|
@ -233,15 +233,15 @@ Aqui, o `new_dict` terá todos os pares de chave-valor do `old_dict` mais o novo
|
|||
}
|
||||
```
|
||||
|
||||
Você pode utilizar essa técnica para reutilizar alguns retornos predefinidos nas suas *operações de caminho* e combiná-las com personalizações adicionais.
|
||||
Você pode utilizar essa técnica para reutilizar alguns retornos predefinidos nas suas *operações de rota* e combiná-las com personalizações adicionais.
|
||||
|
||||
Por exemplo:
|
||||
|
||||
{* ../../docs_src/additional_responses/tutorial004.py hl[13:17,26] *}
|
||||
|
||||
## Mais informações sobre retornos OpenAPI
|
||||
## Mais informações sobre retornos OpenAPI { #more-information-about-openapi-responses }
|
||||
|
||||
Para verificar exatamente o que você pode incluir nos retornos, você pode conferir estas seções na especificação do OpenAPI:
|
||||
|
||||
* <a href="https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#responsesObject" class="external-link" target="_blank">Objeto de Retorno OpenAPI</a>, inclui o `Response Object`.
|
||||
* <a href="https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#responseObject" class="external-link" target="_blank">Objeto de Retorno OpenAPI</a>, você pode incluir qualquer coisa dele diretamente em cada retorno dentro do seu parâmetro `responses`. Incluindo `description`, `headers`, `content` (dentro dele que você declara diferentes media types e esquemas JSON), e `links`.
|
||||
* <a href="https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#responses-object" class="external-link" target="_blank">Objeto de Retorno OpenAPI</a>, inclui o `Response Object`.
|
||||
* <a href="https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#response-object" class="external-link" target="_blank">Objeto de Retorno OpenAPI</a>, você pode incluir qualquer coisa dele diretamente em cada retorno dentro do seu parâmetro `responses`. Incluindo `description`, `headers`, `content` (dentro dele que você declara diferentes media types e esquemas JSON), e `links`.
|
||||
|
|
|
|||
|
|
@ -1,22 +1,22 @@
|
|||
# Códigos de status adicionais
|
||||
# Códigos de status adicionais { #additional-status-codes }
|
||||
|
||||
Por padrão, o **FastAPI** retornará as respostas utilizando o `JSONResponse`, adicionando o conteúdo do retorno da sua *operação de caminho* dentro do `JSONResponse`.
|
||||
Por padrão, o **FastAPI** retornará as respostas utilizando o `JSONResponse`, adicionando o conteúdo do retorno da sua *operação de rota* dentro do `JSONResponse`.
|
||||
|
||||
Ele usará o código de status padrão ou o que você definir na sua *operação de caminho*.
|
||||
Ele usará o código de status padrão ou o que você definir na sua *operação de rota*.
|
||||
|
||||
## Códigos de status adicionais
|
||||
## Códigos de status adicionais { #additional-status-codes_1 }
|
||||
|
||||
Caso você queira retornar códigos de status adicionais além do código principal, você pode fazer isso retornando um `Response` diretamente, como por exemplo um `JSONResponse`, e definir os códigos de status adicionais diretamente.
|
||||
|
||||
Por exemplo, vamos dizer que você deseja ter uma *operação de caminho* que permita atualizar itens, e retornar um código de status HTTP 200 "OK" quando for bem sucedido.
|
||||
Por exemplo, vamos dizer que você deseja ter uma *operação de rota* que permita atualizar itens, e retornar um código de status HTTP 200 "OK" quando for bem sucedido.
|
||||
|
||||
Mas você também deseja aceitar novos itens. E quando os itens não existiam, ele os cria, e retorna o código de status HTTP 201 "Created.
|
||||
Mas você também deseja aceitar novos itens. E quando os itens não existiam, ele os cria, e retorna o código de status HTTP 201 "Created".
|
||||
|
||||
Para conseguir isso, importe `JSONResponse` e retorne o seu conteúdo diretamente, definindo o `status_code` que você deseja:
|
||||
|
||||
{* ../../docs_src/additional_status_codes/tutorial001_an_py310.py hl[4,25] *}
|
||||
|
||||
/// warning | Aviso
|
||||
/// warning | Atenção
|
||||
|
||||
Quando você retorna um `Response` diretamente, como no exemplo acima, ele será retornado diretamente.
|
||||
|
||||
|
|
@ -26,7 +26,7 @@ Garanta que ele tenha toda informação que você deseja, e que os valores sejam
|
|||
|
||||
///
|
||||
|
||||
/// note | Detalhes técnicos
|
||||
/// note | Detalhes Técnicos
|
||||
|
||||
Você também pode utilizar `from starlette.responses import JSONResponse`.
|
||||
|
||||
|
|
@ -34,7 +34,7 @@ O **FastAPI** disponibiliza o `starlette.responses` como `fastapi.responses` ape
|
|||
|
||||
///
|
||||
|
||||
## OpenAPI e documentação da API
|
||||
## OpenAPI e documentação da API { #openapi-and-api-docs }
|
||||
|
||||
Se você retorna códigos de status adicionais e retornos diretamente, eles não serão incluídos no esquema do OpenAPI (a documentação da API), porque o FastAPI não tem como saber de antemão o que será retornado.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# Dependências avançadas
|
||||
# Dependências avançadas { #advanced-dependencies }
|
||||
|
||||
## Dependências parametrizadas
|
||||
## Dependências parametrizadas { #parameterized-dependencies }
|
||||
|
||||
Todas as dependências que vimos até agora são funções ou classes fixas.
|
||||
|
||||
|
|
@ -10,7 +10,7 @@ Vamos imaginar que queremos ter uma dependência que verifica se o parâmetro de
|
|||
|
||||
Porém nós queremos poder parametrizar o conteúdo fixo.
|
||||
|
||||
## Uma instância "chamável"
|
||||
## Uma instância "chamável" { #a-callable-instance }
|
||||
|
||||
Em Python existe uma maneira de fazer com que uma instância de uma classe seja um "chamável".
|
||||
|
||||
|
|
@ -22,7 +22,7 @@ Para fazer isso, nós declaramos o método `__call__`:
|
|||
|
||||
Neste caso, o `__call__` é o que o **FastAPI** utilizará para verificar parâmetros adicionais e sub dependências, e isso é o que será chamado para passar o valor ao parâmetro na sua *função de operação de rota* posteriormente.
|
||||
|
||||
## Parametrizar a instância
|
||||
## Parametrizar a instância { #parameterize-the-instance }
|
||||
|
||||
E agora, nós podemos utilizar o `__init__` para declarar os parâmetros da instância que podemos utilizar para "parametrizar" a dependência:
|
||||
|
||||
|
|
@ -30,7 +30,7 @@ E agora, nós podemos utilizar o `__init__` para declarar os parâmetros da inst
|
|||
|
||||
Neste caso, o **FastAPI** nunca tocará ou se importará com o `__init__`, nós vamos utilizar diretamente em nosso código.
|
||||
|
||||
## Crie uma instância
|
||||
## Crie uma instância { #create-an-instance }
|
||||
|
||||
Nós poderíamos criar uma instância desta classe com:
|
||||
|
||||
|
|
@ -38,7 +38,7 @@ Nós poderíamos criar uma instância desta classe com:
|
|||
|
||||
E deste modo nós podemos "parametrizar" a nossa dependência, que agora possui `"bar"` dentro dele, como o atributo `checker.fixed_content`.
|
||||
|
||||
## Utilize a instância como dependência
|
||||
## Utilize a instância como dependência { #use-the-instance-as-a-dependency }
|
||||
|
||||
Então, nós podemos utilizar este `checker` em um `Depends(checker)`, no lugar de `Depends(FixedContentQueryChecker)`, porque a dependência é a instância, `checker`, e não a própria classe.
|
||||
|
||||
|
|
@ -63,3 +63,101 @@ Nos capítulos sobre segurança, existem funções utilitárias que são impleme
|
|||
Se você entendeu tudo isso, você já sabe como essas funções utilitárias para segurança funcionam por debaixo dos panos.
|
||||
|
||||
///
|
||||
|
||||
## Dependências com `yield`, `HTTPException`, `except` e Tarefas em Segundo Plano { #dependencies-with-yield-httpexception-except-and-background-tasks }
|
||||
|
||||
/// warning | Atenção
|
||||
|
||||
Muito provavelmente você não precisa desses detalhes técnicos.
|
||||
|
||||
Esses detalhes são úteis principalmente se você tinha uma aplicação FastAPI anterior à versão 0.121.0 e está enfrentando problemas com dependências com `yield`.
|
||||
|
||||
///
|
||||
|
||||
Dependências com `yield` evoluíram ao longo do tempo para contemplar diferentes casos de uso e corrigir alguns problemas, aqui está um resumo do que mudou.
|
||||
|
||||
### Dependências com `yield` e `scope` { #dependencies-with-yield-and-scope }
|
||||
|
||||
Na versão 0.121.0, o FastAPI adicionou suporte a `Depends(scope="function")` para dependências com `yield`.
|
||||
|
||||
Usando `Depends(scope="function")`, o código de saída após o `yield` é executado logo depois que a *função de operação de rota* termina, antes de a response ser enviada de volta ao cliente.
|
||||
|
||||
E ao usar `Depends(scope="request")` (o padrão), o código de saída após o `yield` é executado depois que a response é enviada.
|
||||
|
||||
Você pode ler mais na documentação em [Dependências com `yield` - Saída antecipada e `scope`](../tutorial/dependencies/dependencies-with-yield.md#early-exit-and-scope).
|
||||
|
||||
### Dependências com `yield` e `StreamingResponse`, Detalhes Técnicos { #dependencies-with-yield-and-streamingresponse-technical-details }
|
||||
|
||||
Antes do FastAPI 0.118.0, se você usasse uma dependência com `yield`, o código de saída (após o `yield`) rodaria depois que a *função de operação de rota* retornasse, mas logo antes de enviar a resposta.
|
||||
|
||||
A intenção era evitar manter recursos por mais tempo que o necessário, esperando a resposta percorrer a rede.
|
||||
|
||||
Essa mudança também significava que, se você retornasse um `StreamingResponse`, o código de saída da dependência com `yield` já teria sido executado.
|
||||
|
||||
Por exemplo, se você tivesse uma sessão de banco de dados em uma dependência com `yield`, o `StreamingResponse` não conseguiria usar essa sessão enquanto transmite dados, porque a sessão já teria sido fechada no código de saída após o `yield`.
|
||||
|
||||
Esse comportamento foi revertido na versão 0.118.0, para que o código de saída após o `yield` seja executado depois que a resposta for enviada.
|
||||
|
||||
/// info | Informação
|
||||
|
||||
Como você verá abaixo, isso é muito semelhante ao comportamento antes da versão 0.106.0, mas com várias melhorias e correções de bugs para casos extremos.
|
||||
|
||||
///
|
||||
|
||||
#### Casos de uso com código de saída antecipado { #use-cases-with-early-exit-code }
|
||||
|
||||
Há alguns casos de uso, com condições específicas, que poderiam se beneficiar do comportamento antigo de executar o código de saída das dependências com `yield` antes de enviar a resposta.
|
||||
|
||||
Por exemplo, imagine que você tem código que usa uma sessão de banco de dados em uma dependência com `yield` apenas para verificar um usuário, mas a sessão de banco de dados nunca é usada novamente na *função de operação de rota*, somente na dependência, e a resposta demora a ser enviada, como um `StreamingResponse` que envia dados lentamente, mas por algum motivo não usa o banco de dados.
|
||||
|
||||
Nesse caso, a sessão de banco de dados seria mantida até que a resposta termine de ser enviada, mas se você não a usa, então não seria necessário mantê-la.
|
||||
|
||||
Veja como poderia ser:
|
||||
|
||||
{* ../../docs_src/dependencies/tutorial013_an_py310.py *}
|
||||
|
||||
O código de saída, o fechamento automático da `Session` em:
|
||||
|
||||
{* ../../docs_src/dependencies/tutorial013_an_py310.py ln[19:21] *}
|
||||
|
||||
...seria executado depois que a resposta terminar de enviar os dados lentos:
|
||||
|
||||
{* ../../docs_src/dependencies/tutorial013_an_py310.py ln[30:38] hl[31:33] *}
|
||||
|
||||
Mas como `generate_stream()` não usa a sessão do banco de dados, não é realmente necessário manter a sessão aberta enquanto envia a resposta.
|
||||
|
||||
Se você tiver esse caso específico usando SQLModel (ou SQLAlchemy), você poderia fechar explicitamente a sessão depois que não precisar mais dela:
|
||||
|
||||
{* ../../docs_src/dependencies/tutorial014_an_py310.py ln[24:28] hl[28] *}
|
||||
|
||||
Dessa forma a sessão liberaria a conexão com o banco de dados, para que outras requisições pudessem usá-la.
|
||||
|
||||
Se você tiver um caso diferente que precise sair antecipadamente de uma dependência com `yield`, por favor crie uma <a href="https://github.com/fastapi/fastapi/discussions/new?category=questions" class="external-link" target="_blank">Pergunta no GitHub Discussions</a> com o seu caso específico e por que você se beneficiaria de ter o fechamento antecipado para dependências com `yield`.
|
||||
|
||||
Se houver casos de uso convincentes para fechamento antecipado em dependências com `yield`, considerarei adicionar uma nova forma de optar por esse fechamento antecipado.
|
||||
|
||||
### Dependências com `yield` e `except`, Detalhes Técnicos { #dependencies-with-yield-and-except-technical-details }
|
||||
|
||||
Antes do FastAPI 0.110.0, se você usasse uma dependência com `yield`, e então capturasse uma exceção com `except` nessa dependência, e você não relançasse a exceção, a exceção seria automaticamente levantada/encaminhada para quaisquer tratadores de exceção ou para o tratador de erro interno do servidor.
|
||||
|
||||
Isso foi alterado na versão 0.110.0 para corrigir consumo de memória não tratado decorrente de exceções encaminhadas sem um tratador (erros internos do servidor), e para torná-lo consistente com o comportamento do código Python regular.
|
||||
|
||||
### Tarefas em Segundo Plano e Dependências com `yield`, Detalhes Técnicos { #background-tasks-and-dependencies-with-yield-technical-details }
|
||||
|
||||
Antes do FastAPI 0.106.0, lançar exceções após o `yield` não era possível, o código de saída em dependências com `yield` era executado depois que a resposta era enviada, então [Tratadores de Exceções](../handling-errors.md#install-custom-exception-handlers){.internal-link target=_blank} já teriam sido executados.
|
||||
|
||||
Isso foi projetado assim principalmente para permitir o uso dos mesmos objetos "yielded" por dependências dentro de tarefas em segundo plano, porque o código de saída seria executado depois que as tarefas em segundo plano fossem concluídas.
|
||||
|
||||
Isso foi alterado no FastAPI 0.106.0 com a intenção de não manter recursos enquanto se espera a resposta percorrer a rede.
|
||||
|
||||
/// tip | Dica
|
||||
|
||||
Além disso, uma tarefa em segundo plano normalmente é um conjunto de lógica independente que deve ser tratado separadamente, com seus próprios recursos (por exemplo, sua própria conexão de banco de dados).
|
||||
|
||||
Assim, desta forma você provavelmente terá um código mais limpo.
|
||||
|
||||
///
|
||||
|
||||
Se você costumava depender desse comportamento, agora você deve criar os recursos para tarefas em segundo plano dentro da própria tarefa em segundo plano, e usar internamente apenas dados que não dependam dos recursos de dependências com `yield`.
|
||||
|
||||
Por exemplo, em vez de usar a mesma sessão de banco de dados, você criaria uma nova sessão de banco de dados dentro da tarefa em segundo plano, e obteria os objetos do banco de dados usando essa nova sessão. E então, em vez de passar o objeto do banco de dados como parâmetro para a função da tarefa em segundo plano, você passaria o ID desse objeto e então obteria o objeto novamente dentro da função da tarefa em segundo plano.
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
# Testes Assíncronos
|
||||
# Testes Assíncronos { #async-tests }
|
||||
|
||||
Você já viu como testar as suas aplicações **FastAPI** utilizando o `TestClient` que é fornecido. Até agora, você viu apenas como escrever testes síncronos, sem utilizar funções `async`.
|
||||
|
||||
|
|
@ -6,11 +6,11 @@ Ser capaz de utilizar funções assíncronas em seus testes pode ser útil, por
|
|||
|
||||
Vamos ver como nós podemos fazer isso funcionar.
|
||||
|
||||
## pytest.mark.anyio
|
||||
## pytest.mark.anyio { #pytest-mark-anyio }
|
||||
|
||||
Se quisermos chamar funções assíncronas em nossos testes, as nossas funções de teste precisam ser assíncronas. O AnyIO oferece um plugin bem legal para isso, que nos permite especificar que algumas das nossas funções de teste precisam ser chamadas de forma assíncrona.
|
||||
|
||||
## HTTPX
|
||||
## HTTPX { #httpx }
|
||||
|
||||
Mesmo que a sua aplicação **FastAPI** utilize funções normais com `def` no lugar de `async def`, ela ainda é uma aplicação `async` por baixo dos panos.
|
||||
|
||||
|
|
@ -18,7 +18,7 @@ O `TestClient` faz algumas mágicas para invocar a aplicação FastAPI assíncro
|
|||
|
||||
O `TestClient` é baseado no <a href="https://www.python-httpx.org" class="external-link" target="_blank">HTTPX</a>, e felizmente nós podemos utilizá-lo diretamente para testar a API.
|
||||
|
||||
## Exemplo
|
||||
## Exemplo { #example }
|
||||
|
||||
Para um exemplos simples, vamos considerar uma estrutura de arquivos semelhante ao descrito em [Bigger Applications](../tutorial/bigger-applications.md){.internal-link target=_blank} e [Testing](../tutorial/testing.md){.internal-link target=_blank}:
|
||||
|
||||
|
|
@ -38,7 +38,7 @@ O arquivo `test_main.py` teria os testes para para o arquivo `main.py`, ele pode
|
|||
|
||||
{* ../../docs_src/async_tests/test_main.py *}
|
||||
|
||||
## Executá-lo
|
||||
## Executá-lo { #run-it }
|
||||
|
||||
Você pode executar os seus testes normalmente via:
|
||||
|
||||
|
|
@ -52,7 +52,7 @@ $ pytest
|
|||
|
||||
</div>
|
||||
|
||||
## Em Detalhes
|
||||
## Em Detalhes { #in-detail }
|
||||
|
||||
O marcador `@pytest.mark.anyio` informa ao pytest que esta função de teste deve ser invocada de maneira assíncrona:
|
||||
|
||||
|
|
@ -82,18 +82,18 @@ Note que nós estamos utilizando async/await com o novo `AsyncClient` - a requis
|
|||
|
||||
///
|
||||
|
||||
/// warning | Aviso
|
||||
/// warning | Atenção
|
||||
|
||||
Se a sua aplicação depende dos eventos de vida útil (*lifespan*), o `AsyncClient` não acionará estes eventos. Para garantir que eles são acionados, utilize o `LifespanManager` do <a href="https://github.com/florimondmanca/asgi-lifespan#usage" class="external-link" target="_blank">florimondmanca/asgi-lifespan</a>.
|
||||
Se a sua aplicação depende de eventos de lifespan, o `AsyncClient` não acionará estes eventos. Para garantir que eles são acionados, utilize o `LifespanManager` do <a href="https://github.com/florimondmanca/asgi-lifespan#usage" class="external-link" target="_blank">florimondmanca/asgi-lifespan</a>.
|
||||
|
||||
///
|
||||
|
||||
## Outras Chamadas de Funções Assíncronas
|
||||
## Outras Chamadas de Funções Assíncronas { #other-asynchronous-function-calls }
|
||||
|
||||
Como a função de teste agora é assíncrona, você pode chamar (e `esperar`) outras funções `async` além de enviar requisições para a sua aplicação FastAPI em seus testes, exatamente como você as chamaria em qualquer outro lugar do seu código.
|
||||
Como a função de teste agora é assíncrona, você pode chamar (e `await`) outras funções `async` além de enviar requisições para a sua aplicação FastAPI em seus testes, exatamente como você as chamaria em qualquer outro lugar do seu código.
|
||||
|
||||
/// tip | Dica
|
||||
|
||||
Se você se deparar com um `RuntimeError: Task attached to a different loop` ao integrar funções assíncronas em seus testes (e.g. ao utilizar o <a href="https://stackoverflow.com/questions/41584243/runtimeerror-task-attached-to-a-different-loop" class="external-link" target="_blank">MotorClient do MongoDB</a>) Lembre-se de instanciar objetos que precisam de um loop de eventos (*event loop*) apenas em funções assíncronas, e.g. um *"callback"* `'@app.on_event("startup")`.
|
||||
Se você se deparar com um `RuntimeError: Task attached to a different loop` ao integrar funções assíncronas em seus testes (e.g. ao utilizar o <a href="https://stackoverflow.com/questions/41584243/runtimeerror-task-attached-to-a-different-loop" class="external-link" target="_blank">MotorClient do MongoDB</a>) Lembre-se de instanciar objetos que precisam de um loop de eventos (*event loop*) apenas em funções assíncronas, e.g. um callback `@app.on_event("startup")`.
|
||||
|
||||
///
|
||||
|
|
|
|||
|
|
@ -1,34 +1,131 @@
|
|||
# Atrás de um Proxy
|
||||
# Atrás de um Proxy { #behind-a-proxy }
|
||||
|
||||
Em algumas situações, você pode precisar usar um servidor **proxy** como Traefik ou Nginx com uma configuração que adiciona um prefixo de caminho extra que não é visto pela sua aplicação.
|
||||
Em muitas situações, você usaria um **proxy** como Traefik ou Nginx na frente da sua aplicação FastAPI.
|
||||
|
||||
Esses proxies podem lidar com certificados HTTPS e outras coisas.
|
||||
|
||||
## Headers Encaminhados pelo Proxy { #proxy-forwarded-headers }
|
||||
|
||||
Um **proxy** na frente da sua aplicação normalmente definiria alguns headers dinamicamente antes de enviar as requisições para o seu **servidor**, para informar ao servidor que a requisição foi **encaminhada** pelo proxy, informando a URL original (pública), incluindo o domínio, que está usando HTTPS, etc.
|
||||
|
||||
O programa do **servidor** (por exemplo, **Uvicorn** via **CLI do FastAPI**) é capaz de interpretar esses headers e então repassar essas informações para a sua aplicação.
|
||||
|
||||
Mas, por segurança, como o servidor não sabe que está atrás de um proxy confiável, ele não interpretará esses headers.
|
||||
|
||||
/// note | Detalhes Técnicos
|
||||
|
||||
Os headers do proxy são:
|
||||
|
||||
* <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Forwarded-For" class="external-link" target="_blank">X-Forwarded-For</a>
|
||||
* <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Forwarded-Proto" class="external-link" target="_blank">X-Forwarded-Proto</a>
|
||||
* <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Forwarded-Host" class="external-link" target="_blank">X-Forwarded-Host</a>
|
||||
|
||||
///
|
||||
|
||||
### Ativar headers encaminhados pelo proxy { #enable-proxy-forwarded-headers }
|
||||
|
||||
Você pode iniciar a CLI do FastAPI com a opção de linha de comando `--forwarded-allow-ips` e informar os endereços IP que devem ser confiáveis para ler esses headers encaminhados.
|
||||
|
||||
Se você definir como `--forwarded-allow-ips="*"`, ele confiará em todos os IPs de entrada.
|
||||
|
||||
Se o seu **servidor** estiver atrás de um **proxy** confiável e somente o proxy falar com ele, isso fará com que ele aceite seja qual for o IP desse **proxy**.
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ fastapi run --forwarded-allow-ips="*"
|
||||
|
||||
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
### Redirecionamentos com HTTPS { #redirects-with-https }
|
||||
|
||||
Por exemplo, suponha que você defina uma *operação de rota* `/items/`:
|
||||
|
||||
{* ../../docs_src/behind_a_proxy/tutorial001_01.py hl[6] *}
|
||||
|
||||
Se o cliente tentar ir para `/items`, por padrão, ele seria redirecionado para `/items/`.
|
||||
|
||||
Mas antes de definir a opção de linha de comando `--forwarded-allow-ips`, poderia redirecionar para `http://localhost:8000/items/`.
|
||||
|
||||
Mas talvez sua aplicação esteja hospedada em `https://mysuperapp.com`, e o redirecionamento deveria ser para `https://mysuperapp.com/items/`.
|
||||
|
||||
Ao definir `--proxy-headers`, agora o FastAPI conseguirá redirecionar para o local correto. 😎
|
||||
|
||||
```
|
||||
https://mysuperapp.com/items/
|
||||
```
|
||||
|
||||
/// tip | Dica
|
||||
|
||||
Se você quiser saber mais sobre HTTPS, confira o tutorial [Sobre HTTPS](../deployment/https.md){.internal-link target=_blank}.
|
||||
|
||||
///
|
||||
|
||||
### Como funcionam os headers encaminhados pelo proxy { #how-proxy-forwarded-headers-work }
|
||||
|
||||
Aqui está uma representação visual de como o **proxy** adiciona headers encaminhados entre o cliente e o **servidor da aplicação**:
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Client
|
||||
participant Proxy as Proxy/Load Balancer
|
||||
participant Server as FastAPI Server
|
||||
|
||||
Client->>Proxy: HTTPS Request<br/>Host: mysuperapp.com<br/>Path: /items
|
||||
|
||||
Note over Proxy: Proxy adds forwarded headers
|
||||
|
||||
Proxy->>Server: HTTP Request<br/>X-Forwarded-For: [client IP]<br/>X-Forwarded-Proto: https<br/>X-Forwarded-Host: mysuperapp.com<br/>Path: /items
|
||||
|
||||
Note over Server: Server interprets headers<br/>(if --forwarded-allow-ips is set)
|
||||
|
||||
Server->>Proxy: HTTP Response<br/>with correct HTTPS URLs
|
||||
|
||||
Proxy->>Client: HTTPS Response
|
||||
```
|
||||
|
||||
O **proxy** intercepta a requisição original do cliente e adiciona os headers especiais de encaminhamento (`X-Forwarded-*`) antes de repassar a requisição para o **servidor da aplicação**.
|
||||
|
||||
Esses headers preservam informações sobre a requisição original que, de outra forma, seriam perdidas:
|
||||
|
||||
* X-Forwarded-For: o endereço IP original do cliente
|
||||
* X-Forwarded-Proto: o protocolo original (`https`)
|
||||
* X-Forwarded-Host: o host original (`mysuperapp.com`)
|
||||
|
||||
Quando a **CLI do FastAPI** é configurada com `--forwarded-allow-ips`, ela confia nesses headers e os utiliza, por exemplo, para gerar as URLs corretas em redirecionamentos.
|
||||
|
||||
## Proxy com um prefixo de path removido { #proxy-with-a-stripped-path-prefix }
|
||||
|
||||
Você pode ter um proxy que adiciona um prefixo de path à sua aplicação.
|
||||
|
||||
Nesses casos, você pode usar `root_path` para configurar sua aplicação.
|
||||
|
||||
O `root_path` é um mecanismo fornecido pela especificação ASGI (que o FastAPI utiliza, através do Starlette).
|
||||
O `root_path` é um mecanismo fornecido pela especificação ASGI (na qual o FastAPI é construído, através do Starlette).
|
||||
|
||||
O `root_path` é usado para lidar com esses casos específicos.
|
||||
|
||||
E também é usado internamente ao montar sub-aplicações.
|
||||
|
||||
## Proxy com um prefixo de caminho removido
|
||||
Ter um proxy com um prefixo de path removido, nesse caso, significa que você poderia declarar um path em `/app` no seu código, mas então você adiciona uma camada no topo (o proxy) que colocaria sua aplicação **FastAPI** sob um path como `/api/v1`.
|
||||
|
||||
Ter um proxy com um prefixo de caminho removido, nesse caso, significa que você poderia declarar um caminho em `/app` no seu código, mas então, você adiciona uma camada no topo (o proxy) que colocaria sua aplicação **FastAPI** sob um caminho como `/api/v1`.
|
||||
|
||||
Nesse caso, o caminho original `/app` seria servido em `/api/v1/app`.
|
||||
Nesse caso, o path original `/app` seria servido em `/api/v1/app`.
|
||||
|
||||
Embora todo o seu código esteja escrito assumindo que existe apenas `/app`.
|
||||
|
||||
{* ../../docs_src/behind_a_proxy/tutorial001.py hl[6] *}
|
||||
|
||||
E o proxy estaria **"removendo"** o **prefixo do caminho** dinamicamente antes de transmitir a solicitação para o servidor da aplicação (provavelmente Uvicorn via CLI do FastAPI), mantendo sua aplicação convencida de que está sendo servida em `/app`, para que você não precise atualizar todo o seu código para incluir o prefixo `/api/v1`.
|
||||
E o proxy estaria **"removendo"** o **prefixo de path** dinamicamente antes de transmitir a solicitação para o servidor da aplicação (provavelmente Uvicorn via CLI do FastAPI), mantendo sua aplicação convencida de que está sendo servida em `/app`, para que você não precise atualizar todo o seu código para incluir o prefixo `/api/v1`.
|
||||
|
||||
Até aqui, tudo funcionaria normalmente.
|
||||
|
||||
Mas então, quando você abre a interface de documentação integrada (o frontend), ele esperaria obter o OpenAPI schema em `/openapi.json`, em vez de `/api/v1/openapi.json`.
|
||||
Mas então, quando você abre a interface de documentação integrada (o frontend), ela esperaria obter o OpenAPI schema em `/openapi.json`, em vez de `/api/v1/openapi.json`.
|
||||
|
||||
Então, o frontend (que roda no navegador) tentaria acessar `/openapi.json` e não conseguiria obter o OpenAPI schema.
|
||||
|
||||
Como temos um proxy com um prefixo de caminho de `/api/v1` para nossa aplicação, o frontend precisa buscar o OpenAPI schema em `/api/v1/openapi.json`.
|
||||
Como temos um proxy com um prefixo de path de `/api/v1` para nossa aplicação, o frontend precisa buscar o OpenAPI schema em `/api/v1/openapi.json`.
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
|
|
@ -47,7 +144,7 @@ O IP `0.0.0.0` é comumente usado para significar que o programa escuta em todos
|
|||
|
||||
///
|
||||
|
||||
A interface de documentação também precisaria do OpenAPI schema para declarar que API `server` está localizado em `/api/v1` (atrás do proxy). Por exemplo:
|
||||
A interface de documentação também precisaria do OpenAPI schema para declarar que este `server` da API está localizado em `/api/v1` (atrás do proxy). Por exemplo:
|
||||
|
||||
```JSON hl_lines="4-8"
|
||||
{
|
||||
|
|
@ -64,16 +161,16 @@ A interface de documentação também precisaria do OpenAPI schema para declarar
|
|||
}
|
||||
```
|
||||
|
||||
Neste exemplo, o "Proxy" poderia ser algo como **Traefik**. E o servidor seria algo como CLI do FastAPI com **Uvicorn**, executando sua aplicação FastAPI.
|
||||
Neste exemplo, o "Proxy" poderia ser algo como **Traefik**. E o servidor seria algo como a CLI do FastAPI com **Uvicorn**, executando sua aplicação FastAPI.
|
||||
|
||||
### Fornecendo o `root_path`
|
||||
### Fornecendo o `root_path` { #providing-the-root-path }
|
||||
|
||||
Para conseguir isso, você pode usar a opção de linha de comando `--root-path` assim:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ fastapi run main.py --root-path /api/v1
|
||||
$ fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1
|
||||
|
||||
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
|
||||
```
|
||||
|
|
@ -90,11 +187,11 @@ E a opção de linha de comando `--root-path` fornece esse `root_path`.
|
|||
|
||||
///
|
||||
|
||||
### Verificando o `root_path` atual
|
||||
### Verificando o `root_path` atual { #checking-the-current-root-path }
|
||||
|
||||
Você pode obter o `root_path` atual usado pela sua aplicação para cada solicitação, ele faz parte do dicionário `scope` (que faz parte da especificação ASGI).
|
||||
|
||||
Aqui estamos incluindo ele na mensagem apenas para fins de demonstração.
|
||||
Aqui estamos incluindo-o na mensagem apenas para fins de demonstração.
|
||||
|
||||
{* ../../docs_src/behind_a_proxy/tutorial001.py hl[8] *}
|
||||
|
||||
|
|
@ -103,7 +200,7 @@ Então, se você iniciar o Uvicorn com:
|
|||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ fastapi run main.py --root-path /api/v1
|
||||
$ fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1
|
||||
|
||||
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
|
||||
```
|
||||
|
|
@ -119,15 +216,15 @@ A resposta seria algo como:
|
|||
}
|
||||
```
|
||||
|
||||
### Configurando o `root_path` na aplicação FastAPI
|
||||
### Configurando o `root_path` na aplicação FastAPI { #setting-the-root-path-in-the-fastapi-app }
|
||||
|
||||
Alternativamente, se você não tiver uma maneira de fornecer uma opção de linha de comando como `--root-path` ou equivalente, você pode definir o parâmetro `--root-path` ao criar sua aplicação FastAPI:
|
||||
Alternativamente, se você não tiver uma maneira de fornecer uma opção de linha de comando como `--root-path` ou equivalente, você pode definir o parâmetro `root_path` ao criar sua aplicação FastAPI:
|
||||
|
||||
{* ../../docs_src/behind_a_proxy/tutorial002.py hl[3] *}
|
||||
|
||||
Passar o `root_path`h para `FastAPI` seria o equivalente a passar a opção de linha de comando `--root-path` para Uvicorn ou Hypercorn.
|
||||
Passar o `root_path` para `FastAPI` seria o equivalente a passar a opção de linha de comando `--root-path` para Uvicorn ou Hypercorn.
|
||||
|
||||
### Sobre `root_path`
|
||||
### Sobre `root_path` { #about-root-path }
|
||||
|
||||
Tenha em mente que o servidor (Uvicorn) não usará esse `root_path` para nada além de passá-lo para a aplicação.
|
||||
|
||||
|
|
@ -144,19 +241,19 @@ Portanto, ele não esperará ser acessado em `http://127.0.0.1:8000/api/v1/app`.
|
|||
|
||||
O Uvicorn esperará que o proxy acesse o Uvicorn em `http://127.0.0.1:8000/app`, e então seria responsabilidade do proxy adicionar o prefixo extra `/api/v1` no topo.
|
||||
|
||||
## Sobre proxies com um prefixo de caminho removido
|
||||
## Sobre proxies com um prefixo de path removido { #about-proxies-with-a-stripped-path-prefix }
|
||||
|
||||
Tenha em mente que um proxy com prefixo de caminho removido é apenas uma das maneiras de configurá-lo.
|
||||
Tenha em mente que um proxy com prefixo de path removido é apenas uma das maneiras de configurá-lo.
|
||||
|
||||
Provavelmente, em muitos casos, o padrão será que o proxy não tenha um prefixo de caminho removido.
|
||||
Provavelmente, em muitos casos, o padrão será que o proxy não tenha um prefixo de path removido.
|
||||
|
||||
Em um caso como esse (sem um prefixo de caminho removido), o proxy escutaria em algo como `https://myawesomeapp.com`, e então se o navegador acessar `https://myawesomeapp.com/api/v1/app` e seu servidor (por exemplo, Uvicorn) escutar em `http://127.0.0.1:8000` o proxy (sem um prefixo de caminho removido) acessaria o Uvicorn no mesmo caminho: `http://127.0.0.1:8000/api/v1/app`.
|
||||
Em um caso como esse (sem um prefixo de path removido), o proxy escutaria em algo como `https://myawesomeapp.com`, e então, se o navegador acessar `https://myawesomeapp.com/api/v1/app` e seu servidor (por exemplo, Uvicorn) escutar em `http://127.0.0.1:8000`, o proxy (sem um prefixo de path removido) acessaria o Uvicorn no mesmo path: `http://127.0.0.1:8000/api/v1/app`.
|
||||
|
||||
## Testando localmente com Traefik
|
||||
## Testando localmente com Traefik { #testing-locally-with-traefik }
|
||||
|
||||
Você pode facilmente executar o experimento localmente com um prefixo de caminho removido usando <a href="https://docs.traefik.io/" class="external-link" target="_blank">Traefik</a>.
|
||||
Você pode facilmente executar o experimento localmente com um prefixo de path removido usando <a href="https://docs.traefik.io/" class="external-link" target="_blank">Traefik</a>.
|
||||
|
||||
<a href="https://github.com/containous/traefik/releases" class="external-link" target="_blank">Faça o download do Traefik.</a>, Ele é um único binário e você pode extrair o arquivo compactado e executá-lo diretamente do terminal.
|
||||
<a href="https://github.com/containous/traefik/releases" class="external-link" target="_blank">Faça o download do Traefik</a>, ele é um único binário, você pode extrair o arquivo compactado e executá-lo diretamente do terminal.
|
||||
|
||||
Então, crie um arquivo `traefik.toml` com:
|
||||
|
||||
|
|
@ -203,9 +300,9 @@ Agora crie esse outro arquivo `routes.toml`:
|
|||
url = "http://127.0.0.1:8000"
|
||||
```
|
||||
|
||||
Esse arquivo configura o Traefik para usar o prefixo de caminho `/api/v1`.
|
||||
Esse arquivo configura o Traefik para usar o prefixo de path `/api/v1`.
|
||||
|
||||
E então ele redirecionará suas solicitações para seu Uvicorn rodando em `http://127.0.0.1:8000`.
|
||||
E então o Traefik redirecionará suas solicitações para seu Uvicorn rodando em `http://127.0.0.1:8000`.
|
||||
|
||||
Agora inicie o Traefik:
|
||||
|
||||
|
|
@ -224,14 +321,14 @@ E agora inicie sua aplicação, usando a opção `--root-path`:
|
|||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ fastapi run main.py --root-path /api/v1
|
||||
$ fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1
|
||||
|
||||
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
### Verifique as respostas
|
||||
### Verifique as respostas { #check-the-responses }
|
||||
|
||||
Agora, se você for ao URL com a porta para o Uvicorn: <a href="http://127.0.0.1:8000/app" class="external-link" target="_blank">http://127.0.0.1:8000/app</a>, você verá a resposta normal:
|
||||
|
||||
|
|
@ -248,7 +345,7 @@ Perceba que, mesmo acessando em `http://127.0.0.1:8000/app`, ele mostra o `root_
|
|||
|
||||
///
|
||||
|
||||
E agora abra o URL com a porta para o Traefik, incluindo o prefixo de caminho: <a href="http://127.0.0.1:9999/api/v1/app" class="external-link" target="_blank">http://127.0.0.1:9999/api/v1/app</a>.
|
||||
E agora abra o URL com a porta para o Traefik, incluindo o prefixo de path: <a href="http://127.0.0.1:9999/api/v1/app" class="external-link" target="_blank">http://127.0.0.1:9999/api/v1/app</a>.
|
||||
|
||||
Obtemos a mesma resposta:
|
||||
|
||||
|
|
@ -259,19 +356,19 @@ Obtemos a mesma resposta:
|
|||
}
|
||||
```
|
||||
|
||||
mas desta vez no URL com o prefixo de caminho fornecido pelo proxy: `/api/v1`.
|
||||
mas desta vez no URL com o prefixo de path fornecido pelo proxy: `/api/v1`.
|
||||
|
||||
Claro, a ideia aqui é que todos acessariam a aplicação através do proxy, então a versão com o prefixo de caminho `/api/v1` é a "correta".
|
||||
Claro, a ideia aqui é que todos acessariam a aplicação através do proxy, então a versão com o prefixo de path `/api/v1` é a "correta".
|
||||
|
||||
E a versão sem o prefixo de caminho (`http://127.0.0.1:8000/app`), fornecida diretamente pelo Uvicorn, seria exclusivamente para o _proxy_ (Traefik) acessá-la.
|
||||
E a versão sem o prefixo de path (`http://127.0.0.1:8000/app`), fornecida diretamente pelo Uvicorn, seria exclusivamente para o _proxy_ (Traefik) acessá-la.
|
||||
|
||||
Isso demonstra como o Proxy (Traefik) usa o prefixo de caminho e como o servidor (Uvicorn) usa o `root_path` da opção `--root-path`.
|
||||
Isso demonstra como o Proxy (Traefik) usa o prefixo de path e como o servidor (Uvicorn) usa o `root_path` da opção `--root-path`.
|
||||
|
||||
### Verifique a interface de documentação
|
||||
### Verifique a interface de documentação { #check-the-docs-ui }
|
||||
|
||||
Mas aqui está a parte divertida. ✨
|
||||
|
||||
A maneira "oficial" de acessar a aplicação seria através do proxy com o prefixo de caminho que definimos. Então, como esperaríamos, se você tentar a interface de documentação servida diretamente pelo Uvicorn, sem o prefixo de caminho no URL, ela não funcionará, porque espera ser acessada através do proxy.
|
||||
A maneira "oficial" de acessar a aplicação seria através do proxy com o prefixo de path que definimos. Então, como esperaríamos, se você tentar a interface de documentação servida diretamente pelo Uvicorn, sem o prefixo de path no URL, ela não funcionará, porque espera ser acessada através do proxy.
|
||||
|
||||
Você pode verificar em <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>:
|
||||
|
||||
|
|
@ -287,9 +384,9 @@ Exatamente como queríamos. ✔️
|
|||
|
||||
Isso porque o FastAPI usa esse `root_path` para criar o `server` padrão no OpenAPI com o URL fornecido pelo `root_path`.
|
||||
|
||||
## Servidores adicionais
|
||||
## Servidores adicionais { #additional-servers }
|
||||
|
||||
/// warning | Aviso
|
||||
/// warning | Atenção
|
||||
|
||||
Este é um caso de uso mais avançado. Sinta-se à vontade para pular.
|
||||
|
||||
|
|
@ -297,7 +394,7 @@ Este é um caso de uso mais avançado. Sinta-se à vontade para pular.
|
|||
|
||||
Por padrão, o **FastAPI** criará um `server` no OpenAPI schema com o URL para o `root_path`.
|
||||
|
||||
Mas você também pode fornecer outros `servers` alternativos, por exemplo, se quiser que a *mesma* interface de documentação interaja com ambientes de staging e produção.
|
||||
Mas você também pode fornecer outros `servers` alternativos, por exemplo, se quiser que a mesma interface de documentação interaja com ambientes de staging e produção.
|
||||
|
||||
Se você passar uma lista personalizada de `servers` e houver um `root_path` (porque sua API está atrás de um proxy), o **FastAPI** inserirá um "server" com esse `root_path` no início da lista.
|
||||
|
||||
|
|
@ -346,7 +443,7 @@ A interface de documentação interagirá com o servidor que você selecionar.
|
|||
|
||||
///
|
||||
|
||||
### Desabilitar servidor automático de `root_path`
|
||||
### Desabilitar servidor automático de `root_path` { #disable-automatic-server-from-root-path }
|
||||
|
||||
Se você não quiser que o **FastAPI** inclua um servidor automático usando o `root_path`, você pode usar o parâmetro `root_path_in_servers=False`:
|
||||
|
||||
|
|
@ -354,8 +451,8 @@ Se você não quiser que o **FastAPI** inclua um servidor automático usando o `
|
|||
|
||||
e então ele não será incluído no OpenAPI schema.
|
||||
|
||||
## Montando uma sub-aplicação
|
||||
## Montando uma sub-aplicação { #mounting-a-sub-application }
|
||||
|
||||
Se você precisar montar uma sub-aplicação (como descrito em [Sub Aplicações - Montagens](sub-applications.md){.internal-link target=_blank}) enquanto também usa um proxy com `root_path`, você pode fazer isso normalmente, como esperaria.
|
||||
Se você precisar montar uma sub-aplicação (como descrito em [Sub-aplicações - Montagens](sub-applications.md){.internal-link target=_blank}) enquanto também usa um proxy com `root_path`, você pode fazer isso normalmente, como esperaria.
|
||||
|
||||
O FastAPI usará internamente o `root_path` de forma inteligente, então tudo funcionará. ✨
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
# Resposta Personalizada - HTML, Stream, File e outras
|
||||
# Resposta Personalizada - HTML, Stream, File e outras { #custom-response-html-stream-file-others }
|
||||
|
||||
Por padrão, o **FastAPI** irá retornar respostas utilizando `JSONResponse`.
|
||||
|
||||
|
|
@ -8,9 +8,9 @@ Mas se você retornar uma `Response` diretamente (ou qualquer subclasse, como `J
|
|||
|
||||
Mas você também pode declarar a `Response` que você deseja utilizar (e.g. qualquer subclasse de `Response`), em um *decorador de operação de rota* utilizando o parâmetro `response_class`.
|
||||
|
||||
Os conteúdos que você retorna em sua *função de operador de rota* serão colocados dentro dessa `Response`.
|
||||
Os conteúdos que você retorna em sua *função de operação de rota* serão colocados dentro dessa `Response`.
|
||||
|
||||
E se a `Response` tiver um media type JSON (`application/json`), como é o caso com `JSONResponse` e `UJSONResponse`, os dados que você retornar serão automaticamente convertidos (e filtrados) com qualquer `response_model` do Pydantic que for declarado em sua *função de operador de rota*.
|
||||
E se a `Response` tiver um media type JSON (`application/json`), como é o caso com `JSONResponse` e `UJSONResponse`, os dados que você retornar serão automaticamente convertidos (e filtrados) com qualquer `response_model` do Pydantic que for declarado no decorador de operação de rota.
|
||||
|
||||
/// note | Nota
|
||||
|
||||
|
|
@ -18,7 +18,7 @@ Se você utilizar uma classe de Resposta sem media type, o FastAPI esperará que
|
|||
|
||||
///
|
||||
|
||||
## Utilizando `ORJSONResponse`
|
||||
## Utilizando `ORJSONResponse` { #use-orjsonresponse }
|
||||
|
||||
Por exemplo, se você precisa bastante de performance, você pode instalar e utilizar o <a href="https://github.com/ijl/orjson" class="external-link" target="_blank">`orjson`</a> e definir a resposta para ser uma `ORJSONResponse`.
|
||||
|
||||
|
|
@ -48,7 +48,7 @@ A `ORJSONResponse` está disponível apenas no FastAPI, e não no Starlette.
|
|||
|
||||
///
|
||||
|
||||
## Resposta HTML
|
||||
## Resposta HTML { #html-response }
|
||||
|
||||
Para retornar uma resposta com HTML diretamente do **FastAPI**, utilize `HTMLResponse`.
|
||||
|
||||
|
|
@ -67,7 +67,7 @@ E será documentado como tal no OpenAPI.
|
|||
|
||||
///
|
||||
|
||||
### Retornando uma `Response`
|
||||
### Retornando uma `Response` { #return-a-response }
|
||||
|
||||
Como visto em [Retornando uma Resposta Diretamente](response-directly.md){.internal-link target=_blank}, você também pode sobrescrever a resposta diretamente na sua *operação de rota*, ao retornar ela.
|
||||
|
||||
|
|
@ -75,7 +75,7 @@ O mesmo exemplo de antes, retornando uma `HTMLResponse`, poderia parecer com:
|
|||
|
||||
{* ../../docs_src/custom_response/tutorial003.py hl[2,7,19] *}
|
||||
|
||||
/// warning | Aviso
|
||||
/// warning | Atenção
|
||||
|
||||
Uma `Response` retornada diretamente em sua *função de operação de rota* não será documentada no OpenAPI (por exemplo, o `Content-Type` não será documentado) e não será visível na documentação interativa automática.
|
||||
|
||||
|
|
@ -87,13 +87,13 @@ Obviamente, o cabeçalho `Content-Type`, o código de status, etc, virão do obj
|
|||
|
||||
///
|
||||
|
||||
### Documentar no OpenAPI e sobrescrever `Response`
|
||||
### Documentar no OpenAPI e sobrescrever `Response` { #document-in-openapi-and-override-response }
|
||||
|
||||
Se você deseja sobrescrever a resposta dentro de uma função, mas ao mesmo tempo documentar o "media type" no OpenAPI, você pode utilizar o parâmetro `response_class` E retornar um objeto `Response`.
|
||||
|
||||
A `response_class` será usada apenas para documentar o OpenAPI da *operação de rota*, mas sua `Response` será usada como foi definida.
|
||||
|
||||
##### Retornando uma `HTMLResponse` diretamente
|
||||
#### Retornando uma `HTMLResponse` diretamente { #return-an-htmlresponse-directly }
|
||||
|
||||
Por exemplo, poderia ser algo como:
|
||||
|
||||
|
|
@ -107,7 +107,7 @@ Mas se você passasse uma `HTMLResponse` em `response_class` também, o **FastAP
|
|||
|
||||
<img src="/img/tutorial/custom-response/image01.png">
|
||||
|
||||
## Respostas disponíveis
|
||||
## Respostas disponíveis { #available-responses }
|
||||
|
||||
Aqui estão algumas dos tipos de resposta disponíveis.
|
||||
|
||||
|
|
@ -121,7 +121,7 @@ O **FastAPI** provê a mesma `starlette.responses` como `fastapi.responses` apen
|
|||
|
||||
///
|
||||
|
||||
### `Response`
|
||||
### `Response` { #response }
|
||||
|
||||
A classe principal de respostas, todas as outras respostas herdam dela.
|
||||
|
||||
|
|
@ -138,23 +138,23 @@ O FastAPI (Starlette, na verdade) irá incluir o cabeçalho Content-Length autom
|
|||
|
||||
{* ../../docs_src/response_directly/tutorial002.py hl[1,18] *}
|
||||
|
||||
### `HTMLResponse`
|
||||
### `HTMLResponse` { #htmlresponse }
|
||||
|
||||
Usa algum texto ou sequência de bytes e retorna uma resposta HTML. Como você leu acima.
|
||||
|
||||
### `PlainTextResponse`
|
||||
### `PlainTextResponse` { #plaintextresponse }
|
||||
|
||||
Usa algum texto ou sequência de bytes para retornar uma resposta de texto não formatado.
|
||||
|
||||
{* ../../docs_src/custom_response/tutorial005.py hl[2,7,9] *}
|
||||
|
||||
### `JSONResponse`
|
||||
### `JSONResponse` { #jsonresponse }
|
||||
|
||||
Pega alguns dados e retorna uma resposta com codificação `application/json`.
|
||||
|
||||
É a resposta padrão utilizada no **FastAPI**, como você leu acima.
|
||||
|
||||
### `ORJSONResponse`
|
||||
### `ORJSONResponse` { #orjsonresponse }
|
||||
|
||||
Uma alternativa mais rápida de resposta JSON utilizando o <a href="https://github.com/ijl/orjson" class="external-link" target="_blank">`orjson`</a>, como você leu acima.
|
||||
|
||||
|
|
@ -164,7 +164,7 @@ Essa resposta requer a instalação do pacote `orjson`, com o comando `pip insta
|
|||
|
||||
///
|
||||
|
||||
### `UJSONResponse`
|
||||
### `UJSONResponse` { #ujsonresponse }
|
||||
|
||||
Uma alternativa de resposta JSON utilizando a biblioteca <a href="https://github.com/ultrajson/ultrajson" class="external-link" target="_blank">`ujson`</a>.
|
||||
|
||||
|
|
@ -174,7 +174,7 @@ Essa resposta requer a instalação do pacote `ujson`, com o comando `pip instal
|
|||
|
||||
///
|
||||
|
||||
/// warning | Aviso
|
||||
/// warning | Atenção
|
||||
|
||||
`ujson` é menos cauteloso que a implementação nativa do Python na forma que os casos especiais são tratados
|
||||
|
||||
|
|
@ -188,7 +188,7 @@ Essa resposta requer a instalação do pacote `ujson`, com o comando `pip instal
|
|||
|
||||
///
|
||||
|
||||
### `RedirectResponse`
|
||||
### `RedirectResponse` { #redirectresponse }
|
||||
|
||||
Retorna um redirecionamento HTTP. Utiliza o código de status 307 (Redirecionamento Temporário) por padrão.
|
||||
|
||||
|
|
@ -212,26 +212,24 @@ Você também pode utilizar o parâmetro `status_code` combinado com o parâmetr
|
|||
|
||||
{* ../../docs_src/custom_response/tutorial006c.py hl[2,7,9] *}
|
||||
|
||||
### `StreamingResponse`
|
||||
### `StreamingResponse` { #streamingresponse }
|
||||
|
||||
Recebe uma gerador assíncrono ou um gerador/iterador comum e retorna o corpo da requisição continuamente (stream).
|
||||
Recebe um gerador assíncrono ou um gerador/iterador comum e retorna o corpo da resposta de forma contínua (stream).
|
||||
|
||||
{* ../../docs_src/custom_response/tutorial007.py hl[2,14] *}
|
||||
|
||||
#### Utilizando `StreamingResponse` com objetos semelhantes a arquivos
|
||||
#### Utilizando `StreamingResponse` com objetos semelhantes a arquivos { #using-streamingresponse-with-file-like-objects }
|
||||
|
||||
Se você tiver um objeto semelhante a um arquivo (e.g. o objeto retornado por `open()`), você pode criar uma função geradora para iterar sobre esse objeto.
|
||||
Se você tiver um objeto <a href="https://docs.python.org/3/glossary.html#term-file-like-object" class="external-link" target="_blank">semelhante a um arquivo</a> (e.g. o objeto retornado por `open()`), você pode criar uma função geradora para iterar sobre esse objeto.
|
||||
|
||||
Dessa forma, você não precisa ler todo o arquivo na memória primeiro, e você pode passar essa função geradora para `StreamingResponse` e retorná-la.
|
||||
|
||||
Isso inclui muitas bibliotecas que interagem com armazenamento em nuvem, processamento de vídeos, entre outras.
|
||||
|
||||
```{ .python .annotate hl_lines="2 10-12 14" }
|
||||
{!../../docs_src/custom_response/tutorial008.py!}
|
||||
```
|
||||
{* ../../docs_src/custom_response/tutorial008.py hl[2,10:12,14] *}
|
||||
|
||||
1. Essa é a função geradora. É definida como "função geradora" porque contém declarações `yield` nela.
|
||||
2. Ao utilizar o bloco `with`, nós garantimos que o objeto semelhante a um arquivo é fechado após a função geradora ser finalizada. Isto é, após a resposta terminar de ser enivada.
|
||||
2. Ao utilizar o bloco `with`, nós garantimos que o objeto semelhante a um arquivo é fechado após a função geradora ser finalizada. Isto é, após a resposta terminar de ser enviada.
|
||||
3. Essa declaração `yield from` informa a função para iterar sobre essa coisa nomeada de `file_like`. E então, para cada parte iterada, fornece essa parte como se viesse dessa função geradora (`iterfile`).
|
||||
|
||||
Então, é uma função geradora que transfere o trabalho de "geração" para alguma outra coisa interna.
|
||||
|
|
@ -244,10 +242,10 @@ Perceba que aqui estamos utilizando o `open()` da biblioteca padrão que não su
|
|||
|
||||
///
|
||||
|
||||
### `FileResponse`
|
||||
### `FileResponse` { #fileresponse }
|
||||
|
||||
Envia um arquivo de forma assíncrona e contínua (stream).
|
||||
*
|
||||
|
||||
Recebe um conjunto de argumentos do construtor diferente dos outros tipos de resposta:
|
||||
|
||||
* `path` - O caminho do arquivo que será transmitido
|
||||
|
|
@ -265,7 +263,7 @@ Você também pode usar o parâmetro `response_class`:
|
|||
|
||||
Nesse caso, você pode retornar o caminho do arquivo diretamente da sua *função de operação de rota*.
|
||||
|
||||
## Classe de resposta personalizada
|
||||
## Classe de resposta personalizada { #custom-response-class }
|
||||
|
||||
Você pode criar sua própria classe de resposta, herdando de `Response` e usando essa nova classe.
|
||||
|
||||
|
|
@ -273,7 +271,7 @@ Por exemplo, vamos supor que você queira utilizar o <a href="https://github.com
|
|||
|
||||
Vamos supor também que você queira retornar um JSON indentado e formatado, então você quer utilizar a opção `orjson.OPT_INDENT_2` do orjson.
|
||||
|
||||
Você poderia criar uma classe `CustomORJSONResponse`. A principal coisa a ser feita é sobrecarregar o método render da classe Response, `Response.render(content)`, que retorna o conteúdo em bytes, para retornar o conteúdo que você deseja:
|
||||
Você poderia criar uma classe `CustomORJSONResponse`. A principal coisa a ser feita é sobrecarregar o método render da classe Response, `Response.render(content)`, que retorna o conteúdo em bytes:
|
||||
|
||||
{* ../../docs_src/custom_response/tutorial009c.py hl[9:14,17] *}
|
||||
|
||||
|
|
@ -293,7 +291,7 @@ Agora em vez de retornar:
|
|||
|
||||
Obviamente, você provavelmente vai encontrar maneiras muito melhores de se aproveitar disso do que a formatação de JSON. 😉
|
||||
|
||||
## Classe de resposta padrão
|
||||
## Classe de resposta padrão { #default-response-class }
|
||||
|
||||
Quando você criar uma instância da classe **FastAPI** ou um `APIRouter` você pode especificar qual classe de resposta utilizar por padrão.
|
||||
|
||||
|
|
@ -309,6 +307,6 @@ Você ainda pode substituir `response_class` em *operações de rota* como antes
|
|||
|
||||
///
|
||||
|
||||
## Documentação adicional
|
||||
## Documentação adicional { #additional-documentation }
|
||||
|
||||
Você também pode declarar o media type e muitos outros detalhes no OpenAPI utilizando `responses`: [Retornos Adicionais no OpenAPI](additional-responses.md){.internal-link target=_blank}.
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
# Usando Dataclasses
|
||||
# Usando Dataclasses { #using-dataclasses }
|
||||
|
||||
FastAPI é construído em cima do **Pydantic**, e eu tenho mostrado como usar modelos Pydantic para declarar requisições e respostas.
|
||||
|
||||
|
|
@ -28,7 +28,7 @@ Mas se você tem um monte de dataclasses por aí, este é um truque legal para u
|
|||
|
||||
///
|
||||
|
||||
## Dataclasses em `response_model`
|
||||
## Dataclasses em `response_model` { #dataclasses-in-response-model }
|
||||
|
||||
Você também pode usar `dataclasses` no parâmetro `response_model`:
|
||||
|
||||
|
|
@ -40,7 +40,7 @@ Dessa forma, seu esquema aparecerá na interface de documentação da API:
|
|||
|
||||
<img src="/img/tutorial/dataclasses/image01.png">
|
||||
|
||||
## Dataclasses em Estruturas de Dados Aninhadas
|
||||
## Dataclasses em Estruturas de Dados Aninhadas { #dataclasses-in-nested-data-structures }
|
||||
|
||||
Você também pode combinar `dataclasses` com outras anotações de tipo para criar estruturas de dados aninhadas.
|
||||
|
||||
|
|
@ -48,9 +48,7 @@ Em alguns casos, você ainda pode ter que usar a versão do Pydantic das `datacl
|
|||
|
||||
Nesse caso, você pode simplesmente trocar as `dataclasses` padrão por `pydantic.dataclasses`, que é um substituto direto:
|
||||
|
||||
```{ .python .annotate hl_lines="1 5 8-11 14-17 23-25 28" }
|
||||
{!../../docs_src/dataclasses/tutorial003.py!}
|
||||
```
|
||||
{* ../../docs_src/dataclasses/tutorial003.py hl[1,5,8:11,14:17,23:25,28] *}
|
||||
|
||||
1. Ainda importamos `field` das `dataclasses` padrão.
|
||||
|
||||
|
|
@ -86,12 +84,12 @@ Você pode combinar `dataclasses` com outras anotações de tipo em muitas combi
|
|||
|
||||
Confira as dicas de anotação no código acima para ver mais detalhes específicos.
|
||||
|
||||
## Saiba Mais
|
||||
## Saiba Mais { #learn-more }
|
||||
|
||||
Você também pode combinar `dataclasses` com outros modelos Pydantic, herdar deles, incluí-los em seus próprios modelos, etc.
|
||||
|
||||
Para saber mais, confira a <a href="https://docs.pydantic.dev/latest/concepts/dataclasses/" class="external-link" target="_blank">documentação do Pydantic sobre dataclasses</a>.
|
||||
|
||||
## Versão
|
||||
## Versão { #version }
|
||||
|
||||
Isso está disponível desde a versão `0.67.0` do FastAPI. 🔖
|
||||
|
|
|
|||
|
|
@ -1,65 +1,64 @@
|
|||
# Eventos de vida útil
|
||||
# Eventos de lifespan { #lifespan-events }
|
||||
|
||||
Você pode definir a lógica (código) que poderia ser executada antes da aplicação **inicializar**. Isso significa que esse código será executado **uma vez**, **antes** da aplicação **começar a receber requisições**.
|
||||
Você pode definir a lógica (código) que deve ser executada antes da aplicação **inicializar**. Isso significa que esse código será executado **uma vez**, **antes** de a aplicação **começar a receber requisições**.
|
||||
|
||||
Do mesmo modo, você pode definir a lógica (código) que será executada quando a aplicação estiver sendo **encerrada**. Nesse caso, este código será executado **uma vez**, **depois** de ter possivelmente tratado **várias requisições**.
|
||||
Da mesma forma, você pode definir a lógica (código) que deve ser executada quando a aplicação estiver **encerrando**. Nesse caso, esse código será executado **uma vez**, **depois** de possivelmente ter tratado **várias requisições**.
|
||||
|
||||
Por conta desse código ser executado antes da aplicação **começar** a receber requisições, e logo após **terminar** de lidar com as requisições, ele cobre toda a **vida útil** (_lifespan_) da aplicação (o termo "vida útil" será importante em um segundo 😉).
|
||||
Como esse código é executado antes de a aplicação **começar** a receber requisições e logo depois que ela **termina** de lidar com as requisições, ele cobre todo o **lifespan** da aplicação (a palavra "lifespan" será importante em um segundo 😉).
|
||||
|
||||
Pode ser muito útil para configurar **recursos** que você precisa usar por toda aplicação, e que são **compartilhados** entre as requisições, e/ou que você precisa **limpar** depois. Por exemplo, o pool de uma conexão com o banco de dados ou carregamento de um modelo compartilhado de aprendizado de máquina (_machine learning_).
|
||||
Isso pode ser muito útil para configurar **recursos** que você precisa usar por toda a aplicação, e que são **compartilhados** entre as requisições e/ou que você precisa **limpar** depois. Por exemplo, um pool de conexões com o banco de dados ou o carregamento de um modelo de machine learning compartilhado.
|
||||
|
||||
## Caso de uso
|
||||
## Caso de uso { #use-case }
|
||||
|
||||
Vamos iniciar com um exemplo de **caso de uso** e então ver como resolvê-lo com isso.
|
||||
Vamos começar com um exemplo de **caso de uso** e então ver como resolvê-lo com isso.
|
||||
|
||||
Vamos imaginar que você tem alguns **modelos de _machine learning_** que deseja usar para lidar com as requisições. 🤖
|
||||
Vamos imaginar que você tem alguns **modelos de machine learning** que deseja usar para lidar com as requisições. 🤖
|
||||
|
||||
Os mesmos modelos são compartilhados entre as requisições, então não é um modelo por requisição, ou um por usuário ou algo parecido.
|
||||
Os mesmos modelos são compartilhados entre as requisições, então não é um modelo por requisição, ou um por usuário, ou algo parecido.
|
||||
|
||||
Vamos imaginar que o carregamento do modelo pode **demorar bastante tempo**, porque ele tem que ler muitos **dados do disco**. Então você não quer fazer isso a cada requisição.
|
||||
Vamos imaginar que o carregamento do modelo pode **demorar bastante tempo**, porque ele precisa ler muitos **dados do disco**. Então você não quer fazer isso a cada requisição.
|
||||
|
||||
Você poderia carregá-lo no nível mais alto do módulo/arquivo, mas isso também poderia significaria **carregar o modelo** mesmo se você estiver executando um simples teste automatizado, então esse teste poderia ser **lento** porque teria que esperar o carregamento do modelo antes de ser capaz de executar uma parte independente do código.
|
||||
Você poderia carregá-lo no nível mais alto do módulo/arquivo, mas isso também significaria **carregar o modelo** mesmo se você estivesse executando um teste automatizado simples; então esse teste poderia ser **lento** porque teria que esperar o carregamento do modelo antes de conseguir executar uma parte independente do código.
|
||||
|
||||
É isso que vamos resolver: vamos carregar o modelo antes de as requisições serem tratadas, mas apenas um pouco antes de a aplicação começar a receber requisições, não enquanto o código estiver sendo carregado.
|
||||
|
||||
Isso é que nós iremos resolver, vamos carregar o modelo antes das requisições serem manuseadas, mas apenas um pouco antes da aplicação começar a receber requisições, não enquanto o código estiver sendo carregado.
|
||||
## Lifespan { #lifespan }
|
||||
|
||||
## Vida útil (_Lifespan_)
|
||||
Você pode definir essa lógica de *inicialização* e *encerramento* usando o parâmetro `lifespan` da aplicação `FastAPI`, e um "gerenciador de contexto" (vou mostrar o que é isso em um segundo).
|
||||
|
||||
Você pode definir essa lógica de *inicialização* e *encerramento* usando os parâmetros de `lifespan` da aplicação `FastAPI`, e um "gerenciador de contexto" (te mostrarei o que é isso a seguir).
|
||||
Vamos começar com um exemplo e depois ver em detalhes.
|
||||
|
||||
Vamos iniciar com um exemplo e ver isso detalhadamente.
|
||||
|
||||
Nós criamos uma função assíncrona chamada `lifespan()` com `yield` como este:
|
||||
Nós criamos uma função assíncrona `lifespan()` com `yield` assim:
|
||||
|
||||
{* ../../docs_src/events/tutorial003.py hl[16,19] *}
|
||||
|
||||
Aqui nós estamos simulando a *inicialização* custosa do carregamento do modelo colocando a (falsa) função de modelo no dicionário com modelos de _machine learning_ antes do `yield`. Este código será executado **antes** da aplicação **começar a receber requisições**, durante a *inicialização*.
|
||||
Aqui estamos simulando a operação de *inicialização* custosa de carregar o modelo, colocando a (falsa) função do modelo no dicionário com modelos de machine learning antes do `yield`. Esse código será executado **antes** de a aplicação **começar a receber requisições**, durante a *inicialização*.
|
||||
|
||||
E então, logo após o `yield`, descarregaremos o modelo. Esse código será executado **após** a aplicação **terminar de lidar com as requisições**, pouco antes do *encerramento*. Isso poderia, por exemplo, liberar recursos como memória ou GPU.
|
||||
E então, logo após o `yield`, descarregamos o modelo. Esse código será executado **depois** de a aplicação **terminar de lidar com as requisições**, pouco antes do *encerramento*. Isso poderia, por exemplo, liberar recursos como memória ou uma GPU.
|
||||
|
||||
/// tip | Dica
|
||||
|
||||
O `shutdown` aconteceria quando você estivesse **encerrando** a aplicação.
|
||||
|
||||
Talvez você precise inicializar uma nova versão, ou apenas cansou de executá-la. 🤷
|
||||
Talvez você precise iniciar uma nova versão, ou apenas cansou de executá-la. 🤷
|
||||
|
||||
///
|
||||
|
||||
### Função _lifespan_
|
||||
### Função lifespan { #lifespan-function }
|
||||
|
||||
A primeira coisa a notar, é que estamos definindo uma função assíncrona com `yield`. Isso é muito semelhante à Dependências com `yield`.
|
||||
A primeira coisa a notar é que estamos definindo uma função assíncrona com `yield`. Isso é muito semelhante a Dependências com `yield`.
|
||||
|
||||
{* ../../docs_src/events/tutorial003.py hl[14:19] *}
|
||||
|
||||
A primeira parte da função, antes do `yield`, será executada **antes** da aplicação inicializar.
|
||||
A primeira parte da função, antes do `yield`, será executada **antes** de a aplicação iniciar.
|
||||
|
||||
E a parte posterior do `yield` irá executar **após** a aplicação ser encerrada.
|
||||
E a parte posterior ao `yield` será executada **depois** de a aplicação ter terminado.
|
||||
|
||||
### Gerenciador de Contexto Assíncrono
|
||||
### Gerenciador de contexto assíncrono { #async-context-manager }
|
||||
|
||||
Se você verificar, a função está decorada com um `@asynccontextmanager`.
|
||||
|
||||
Que converte a função em algo chamado de "**Gerenciador de Contexto Assíncrono**".
|
||||
Isso converte a função em algo chamado "**gerenciador de contexto assíncrono**".
|
||||
|
||||
{* ../../docs_src/events/tutorial003.py hl[1,13] *}
|
||||
|
||||
|
|
@ -70,97 +69,97 @@ with open("file.txt") as file:
|
|||
file.read()
|
||||
```
|
||||
|
||||
Nas versões mais recentes de Python, há também um **gerenciador de contexto assíncrono**. Você o usaria com `async with`:
|
||||
Em versões mais recentes do Python, há também um **gerenciador de contexto assíncrono**. Você o usaria com `async with`:
|
||||
|
||||
```Python
|
||||
async with lifespan(app):
|
||||
await do_stuff()
|
||||
```
|
||||
|
||||
Quando você cria um gerenciador de contexto ou um gerenciador de contexto assíncrono como mencionado acima, o que ele faz é que, antes de entrar no bloco `with`, ele irá executar o código anterior ao `yield`, e depois de sair do bloco `with`, ele irá executar o código depois do `yield`.
|
||||
Quando você cria um gerenciador de contexto ou um gerenciador de contexto assíncrono como acima, o que ele faz é: antes de entrar no bloco `with`, ele executa o código antes do `yield`, e após sair do bloco `with`, ele executa o código depois do `yield`.
|
||||
|
||||
No nosso exemplo de código acima, nós não usamos ele diretamente, mas nós passamos para o FastAPI para ele usá-lo.
|
||||
No nosso exemplo de código acima, não o usamos diretamente, mas passamos para o FastAPI para que ele o use.
|
||||
|
||||
O parâmetro `lifespan` da aplicação `FastAPI` usa um **Gerenciador de Contexto Assíncrono**, então nós podemos passar nosso novo gerenciador de contexto assíncrono do `lifespan` para ele.
|
||||
O parâmetro `lifespan` da aplicação `FastAPI` aceita um **gerenciador de contexto assíncrono**, então podemos passar para ele nosso novo gerenciador de contexto assíncrono `lifespan`.
|
||||
|
||||
{* ../../docs_src/events/tutorial003.py hl[22] *}
|
||||
|
||||
## Eventos alternativos (deprecados)
|
||||
## Eventos alternativos (descontinuados) { #alternative-events-deprecated }
|
||||
|
||||
/// warning | Aviso
|
||||
/// warning | Atenção
|
||||
|
||||
A maneira recomendada para lidar com a *inicialização* e o *encerramento* é usando o parâmetro `lifespan` da aplicação `FastAPI` como descrito acima.
|
||||
A forma recomendada de lidar com a *inicialização* e o *encerramento* é usando o parâmetro `lifespan` da aplicação `FastAPI`, como descrito acima. Se você fornecer um parâmetro `lifespan`, os manipuladores de eventos `startup` e `shutdown` não serão mais chamados. É tudo `lifespan` ou tudo por eventos, não ambos.
|
||||
|
||||
Você provavelmente pode pular essa parte.
|
||||
Você provavelmente pode pular esta parte.
|
||||
|
||||
///
|
||||
|
||||
Existe uma forma alternativa para definir a execução dessa lógica durante *inicialização* e durante *encerramento*.
|
||||
Existe uma forma alternativa de definir essa lógica para ser executada durante a *inicialização* e durante o *encerramento*.
|
||||
|
||||
Você pode definir manipuladores de eventos (funções) que precisam ser executadas antes da aplicação inicializar, ou quando a aplicação estiver encerrando.
|
||||
Você pode definir manipuladores de eventos (funções) que precisam ser executados antes de a aplicação iniciar ou quando a aplicação estiver encerrando.
|
||||
|
||||
Essas funções podem ser declaradas com `async def` ou `def` normal.
|
||||
|
||||
### Evento `startup`
|
||||
### Evento `startup` { #startup-event }
|
||||
|
||||
Para adicionar uma função que deve rodar antes da aplicação iniciar, declare-a com o evento `"startup"`:
|
||||
Para adicionar uma função que deve rodar antes de a aplicação iniciar, declare-a com o evento `"startup"`:
|
||||
|
||||
{* ../../docs_src/events/tutorial001.py hl[8] *}
|
||||
|
||||
Nesse caso, a função de manipulação de evento `startup` irá inicializar os itens do "banco de dados" (só um `dict`) com alguns valores.
|
||||
Nesse caso, a função de manipulador do evento `startup` inicializará os itens do "banco de dados" (apenas um `dict`) com alguns valores.
|
||||
|
||||
Você pode adicionar mais que uma função de manipulação de evento.
|
||||
Você pode adicionar mais de uma função de manipulador de eventos.
|
||||
|
||||
E sua aplicação não irá começar a receber requisições até que todos os manipuladores de eventos de `startup` sejam concluídos.
|
||||
E sua aplicação não começará a receber requisições até que todos os manipuladores de eventos `startup` sejam concluídos.
|
||||
|
||||
### Evento `shutdown`
|
||||
### Evento `shutdown` { #shutdown-event }
|
||||
|
||||
Para adicionar uma função que deve ser executada quando a aplicação estiver encerrando, declare ela com o evento `"shutdown"`:
|
||||
Para adicionar uma função que deve ser executada quando a aplicação estiver encerrando, declare-a com o evento `"shutdown"`:
|
||||
|
||||
{* ../../docs_src/events/tutorial002.py hl[6] *}
|
||||
|
||||
Aqui, a função de manipulação de evento `shutdown` irá escrever uma linha de texto `"Application shutdown"` no arquivo `log.txt`.
|
||||
Aqui, a função de manipulador do evento `shutdown` escreverá uma linha de texto `"Application shutdown"` no arquivo `log.txt`.
|
||||
|
||||
/// info | Informação
|
||||
|
||||
Na função `open()`, o `mode="a"` significa "acrescentar", então, a linha irá ser adicionada depois de qualquer coisa que esteja naquele arquivo, sem sobrescrever o conteúdo anterior.
|
||||
Na função `open()`, o `mode="a"` significa "acrescentar", então a linha será adicionada depois do que já estiver naquele arquivo, sem sobrescrever o conteúdo anterior.
|
||||
|
||||
///
|
||||
|
||||
/// tip | Dica
|
||||
|
||||
Perceba que nesse caso nós estamos usando a função padrão do Python `open()` que interage com um arquivo.
|
||||
Perceba que, nesse caso, estamos usando a função padrão do Python `open()` que interage com um arquivo.
|
||||
|
||||
Então, isso envolve I/O (input/output), que exige "esperar" que coisas sejam escritas em disco.
|
||||
Então, isso envolve I/O (input/output), que requer "esperar" que as coisas sejam escritas em disco.
|
||||
|
||||
Mas `open()` não usa `async` e `await`.
|
||||
|
||||
Então, nós declaramos uma função de manipulação de evento com o padrão `def` ao invés de `async def`.
|
||||
Assim, declaramos a função de manipulador de evento com `def` padrão em vez de `async def`.
|
||||
|
||||
///
|
||||
|
||||
### `startup` e `shutdown` juntos
|
||||
### `startup` e `shutdown` juntos { #startup-and-shutdown-together }
|
||||
|
||||
Há uma grande chance que a lógica para sua *inicialização* e *encerramento* esteja conectada, você pode querer iniciar alguma coisa e então finalizá-la, adquirir um recurso e então liberá-lo, etc.
|
||||
Há uma grande chance de que a lógica para sua *inicialização* e *encerramento* esteja conectada, você pode querer iniciar alguma coisa e então finalizá-la, adquirir um recurso e então liberá-lo, etc.
|
||||
|
||||
Fazendo isso em funções separadas que não compartilham lógica ou variáveis entre elas é mais difícil já que você precisa armazenar os valores em variáveis globais ou truques parecidos.
|
||||
Fazer isso em funções separadas que não compartilham lógica ou variáveis entre si é mais difícil, pois você precisaria armazenar valores em variáveis globais ou truques semelhantes.
|
||||
|
||||
Por causa disso, agora é recomendado em vez disso usar o `lifespan` como explicado acima.
|
||||
Por causa disso, agora é recomendado usar o `lifespan`, como explicado acima.
|
||||
|
||||
## Detalhes técnicos
|
||||
## Detalhes técnicos { #technical-details }
|
||||
|
||||
Só um detalhe técnico para nerds curiosos. 🤓
|
||||
Apenas um detalhe técnico para nerds curiosos. 🤓
|
||||
|
||||
Por baixo, na especificação técnica ASGI, essa é a parte do <a href="https://asgi.readthedocs.io/en/latest/specs/lifespan.html" class="external-link" target="_blank">Protocolo Lifespan</a>, e define eventos chamados `startup` e `shutdown`.
|
||||
Por baixo, na especificação técnica do ASGI, isso é parte do <a href="https://asgi.readthedocs.io/en/latest/specs/lifespan.html" class="external-link" target="_blank">Protocolo Lifespan</a>, e define eventos chamados `startup` e `shutdown`.
|
||||
|
||||
/// info | Informação
|
||||
|
||||
Você pode ler mais sobre o manipulador `lifespan` do Starlette na <a href="https://www.starlette.dev/lifespan/" class="external-link" target="_blank">Documentação do Lifespan Starlette</a>.
|
||||
Você pode ler mais sobre os manipuladores de `lifespan` do Starlette na <a href="https://www.starlette.dev/lifespan/" class="external-link" target="_blank">Documentação do Lifespan do Starlette</a>.
|
||||
|
||||
Incluindo como manipular estado do lifespan que pode ser usado em outras áreas do seu código.
|
||||
Incluindo como lidar com estado do lifespan que pode ser usado em outras áreas do seu código.
|
||||
|
||||
///
|
||||
|
||||
## Sub Aplicações
|
||||
## Sub Aplicações { #sub-applications }
|
||||
|
||||
🚨 Tenha em mente que esses eventos de lifespan (de inicialização e desligamento) irão somente ser executados para a aplicação principal, não para [Sub Aplicações - Montagem](sub-applications.md){.internal-link target=_blank}.
|
||||
🚨 Tenha em mente que esses eventos de lifespan (inicialização e encerramento) serão executados apenas para a aplicação principal, não para [Sub Aplicações - Montagem](sub-applications.md){.internal-link target=_blank}.
|
||||
|
|
|
|||
|
|
@ -1,115 +1,76 @@
|
|||
# Generate Clients
|
||||
# Gerando SDKs { #generating-sdks }
|
||||
|
||||
Como o **FastAPI** é baseado na especificação **OpenAPI**, você obtém compatibilidade automática com muitas ferramentas, incluindo a documentação automática da API (fornecida pelo Swagger UI).
|
||||
Como o **FastAPI** é baseado na especificação **OpenAPI**, suas APIs podem ser descritas em um formato padrão que muitas ferramentas entendem.
|
||||
|
||||
Uma vantagem particular que nem sempre é óbvia é que você pode **gerar clientes** (às vezes chamados de <abbr title="Software Development Kits">**SDKs**</abbr>) para a sua API, para muitas **linguagens de programação** diferentes.
|
||||
Isso facilita gerar **documentação** atualizada, bibliotecas clientes (<abbr title="Software Development Kits – Kits de Desenvolvimento de Software">**SDKs**</abbr>) em várias linguagens e **testes** ou **fluxos de trabalho de automação** que permanecem em sincronia com o seu código.
|
||||
|
||||
## Geradores de Clientes OpenAPI
|
||||
Neste guia, você aprenderá como gerar um **SDK em TypeScript** para o seu backend FastAPI.
|
||||
|
||||
Existem muitas ferramentas para gerar clientes a partir do **OpenAPI**.
|
||||
## Geradores de SDK de código aberto { #open-source-sdk-generators }
|
||||
|
||||
Uma ferramenta comum é o <a href="https://openapi-generator.tech/" class="external-link" target="_blank">OpenAPI Generator</a>.
|
||||
Uma opção versátil é o <a href="https://openapi-generator.tech/" class="external-link" target="_blank">OpenAPI Generator</a>, que suporta **muitas linguagens de programação** e pode gerar SDKs a partir da sua especificação OpenAPI.
|
||||
|
||||
Se voce está construindo um **frontend**, uma alternativa muito interessante é o <a href="https://github.com/hey-api/openapi-ts" class="external-link" target="_blank">openapi-ts</a>.
|
||||
Para **clientes TypeScript**, o <a href="https://heyapi.dev/" class="external-link" target="_blank">Hey API</a> é uma solução feita sob medida, oferecendo uma experiência otimizada para o ecossistema TypeScript.
|
||||
|
||||
## Geradores de Clientes e SDKs - Patrocinadores
|
||||
Você pode descobrir mais geradores de SDK em <a href="https://openapi.tools/#sdk" class="external-link" target="_blank">OpenAPI.Tools</a>.
|
||||
|
||||
Existem também alguns geradores de clientes e SDKs baseados na OpenAPI (FastAPI) **patrocinados por empresas**, em alguns casos eles podem oferecer **recursos adicionais** além de SDKs/clientes gerados de alta qualidade.
|
||||
/// tip | Dica
|
||||
|
||||
Alguns deles também ✨ [**patrocinam o FastAPI**](../help-fastapi.md#sponsor-the-author){.internal-link target=_blank} ✨, isso garante o **desenvolvimento** contínuo e saudável do FastAPI e seu **ecossistema**.
|
||||
O FastAPI gera automaticamente especificações **OpenAPI 3.1**, então qualquer ferramenta que você usar deve suportar essa versão.
|
||||
|
||||
E isso mostra o verdadeiro compromisso deles com o FastAPI e sua **comunidade** (você), pois eles não apenas querem fornecer um **bom serviço**, mas também querem garantir que você tenha um **framework bom e saudável**, o FastAPI. 🙇
|
||||
///
|
||||
|
||||
## Geradores de SDK dos patrocinadores do FastAPI { #sdk-generators-from-fastapi-sponsors }
|
||||
|
||||
Esta seção destaca soluções **financiadas por investimento** e **com suporte de empresas** que patrocinam o FastAPI. Esses produtos fornecem **funcionalidades adicionais** e **integrações** além de SDKs gerados com alta qualidade.
|
||||
|
||||
Ao ✨ [**patrocinar o FastAPI**](../help-fastapi.md#sponsor-the-author){.internal-link target=_blank} ✨, essas empresas ajudam a garantir que o framework e seu **ecossistema** continuem saudáveis e **sustentáveis**.
|
||||
|
||||
O patrocínio também demonstra um forte compromisso com a **comunidade** FastAPI (você), mostrando que elas se importam não apenas em oferecer um **ótimo serviço**, mas também em apoiar um **framework robusto e próspero**, o FastAPI. 🙇
|
||||
|
||||
Por exemplo, você pode querer experimentar:
|
||||
|
||||
* <a href="https://speakeasy.com/editor?utm_source=fastapi+repo&utm_medium=github+sponsorship" class="external-link" target="_blank">Speakeasy</a>
|
||||
* <a href="https://www.stainlessapi.com/?utm_source=fastapi&utm_medium=referral" class="external-link" target="_blank">Stainless</a>
|
||||
* <a href="https://developers.liblab.com/tutorials/sdk-for-fastapi/?utm_source=fastapi" class="external-link" target="_blank">liblab</a>
|
||||
* <a href="https://www.stainless.com/?utm_source=fastapi&utm_medium=referral" class="external-link" target="_blank">Stainless</a>
|
||||
* <a href="https://developers.liblab.com/tutorials/sdk-for-fastapi?utm_source=fastapi" class="external-link" target="_blank">liblab</a>
|
||||
|
||||
Existem também várias outras empresas que oferecem serviços semelhantes que você pode pesquisar e encontrar online. 🤓
|
||||
Algumas dessas soluções também podem ser open source ou oferecer planos gratuitos, para que você possa testá-las sem compromisso financeiro. Outros geradores comerciais de SDK estão disponíveis e podem ser encontrados online. 🤓
|
||||
|
||||
## Gerar um Cliente Frontend TypeScript
|
||||
## Crie um SDK em TypeScript { #create-a-typescript-sdk }
|
||||
|
||||
Vamos começar com um aplicativo **FastAPI** simples:
|
||||
Vamos começar com uma aplicação FastAPI simples:
|
||||
|
||||
{* ../../docs_src/generate_clients/tutorial001_py39.py hl[7:9,12:13,16:17,21] *}
|
||||
|
||||
Note que as *operações de rota* definem os modelos que usam para o corpo da requisição e o corpo da resposta, usando os modelos `Item` e `ResponseMessage`.
|
||||
|
||||
### Documentação da API
|
||||
### Documentação da API { #api-docs }
|
||||
|
||||
Se você acessar a documentação da API, verá que ela tem os **schemas** para os dados a serem enviados nas requisições e recebidos nas respostas:
|
||||
Se você for para `/docs`, verá que ela tem os **schemas** para os dados a serem enviados nas requisições e recebidos nas respostas:
|
||||
|
||||
<img src="/img/tutorial/generate-clients/image01.png">
|
||||
|
||||
Você pode ver esses schemas porque eles foram declarados com os modelos no app.
|
||||
|
||||
Essas informações estão disponíveis no **OpenAPI schema** do app e são mostradas na documentação da API (pelo Swagger UI).
|
||||
Essas informações estão disponíveis no **schema OpenAPI** do app e são mostradas na documentação da API.
|
||||
|
||||
E essas mesmas informações dos modelos que estão incluídas no OpenAPI são o que pode ser usado para **gerar o código do cliente**.
|
||||
|
||||
### Gerar um Cliente TypeScript
|
||||
### Hey API { #hey-api }
|
||||
|
||||
Agora que temos o app com os modelos, podemos gerar o código do cliente para o frontend.
|
||||
Depois que tivermos uma aplicação FastAPI com os modelos, podemos usar o Hey API para gerar um cliente TypeScript. A forma mais rápida é via npx.
|
||||
|
||||
#### Instalar o `openapi-ts`
|
||||
|
||||
Você pode instalar o `openapi-ts` no seu código frontend com:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ npm install @hey-api/openapi-ts --save-dev
|
||||
|
||||
---> 100%
|
||||
```sh
|
||||
npx @hey-api/openapi-ts -i http://localhost:8000/openapi.json -o src/client
|
||||
```
|
||||
|
||||
</div>
|
||||
Isso gerará um SDK TypeScript em `./src/client`.
|
||||
|
||||
#### Gerar o Código do Cliente
|
||||
Você pode aprender como <a href="https://heyapi.dev/openapi-ts/get-started" class="external-link" target="_blank">instalar `@hey-api/openapi-ts`</a> e ler sobre o <a href="https://heyapi.dev/openapi-ts/output" class="external-link" target="_blank">resultado gerado</a> no site deles.
|
||||
|
||||
Para gerar o código do cliente, você pode usar a aplicação de linha de comando `openapi-ts` que agora está instalada.
|
||||
### Usando o SDK { #using-the-sdk }
|
||||
|
||||
Como ela está instalada no projeto local, você provavelmente não conseguiria chamar esse comando diretamente, mas você o colocaria no seu arquivo `package.json`.
|
||||
|
||||
Poderia ser assim:
|
||||
|
||||
```JSON hl_lines="7"
|
||||
{
|
||||
"name": "frontend-app",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"generate-client": "openapi-ts --input http://localhost:8000/openapi.json --output ./src/client --client axios"
|
||||
},
|
||||
"author": "",
|
||||
"license": "",
|
||||
"devDependencies": {
|
||||
"@hey-api/openapi-ts": "^0.27.38",
|
||||
"typescript": "^4.6.2"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Depois de ter esse script NPM `generate-client` lá, você pode executá-lo com:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ npm run generate-client
|
||||
|
||||
frontend-app@1.0.0 generate-client /home/user/code/frontend-app
|
||||
> openapi-ts --input http://localhost:8000/openapi.json --output ./src/client --client axios
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
Esse comando gerará o código em `./src/client` e usará o `axios` (a biblioteca HTTP frontend) internamente.
|
||||
|
||||
### Experimente o Código do Cliente
|
||||
|
||||
Agora você pode importar e usar o código do cliente, ele poderia ser assim, observe que você obtém preenchimento automático para os métodos:
|
||||
Agora você pode importar e usar o código do cliente. Poderia ser assim, observe que você obtém preenchimento automático para os métodos:
|
||||
|
||||
<img src="/img/tutorial/generate-clients/image02.png">
|
||||
|
||||
|
|
@ -119,7 +80,7 @@ Você também obterá preenchimento automático para o corpo a ser enviado:
|
|||
|
||||
/// tip | Dica
|
||||
|
||||
Observe o preenchimento automático para `name` e `price`, que foi definido no aplicativo FastAPI, no modelo `Item`.
|
||||
Observe o preenchimento automático para `name` e `price`, que foi definido na aplicação FastAPI, no modelo `Item`.
|
||||
|
||||
///
|
||||
|
||||
|
|
@ -131,17 +92,17 @@ O objeto de resposta também terá preenchimento automático:
|
|||
|
||||
<img src="/img/tutorial/generate-clients/image05.png">
|
||||
|
||||
## App FastAPI com Tags
|
||||
## Aplicação FastAPI com Tags { #fastapi-app-with-tags }
|
||||
|
||||
Em muitos casos seu app FastAPI será maior, e você provavelmente usará tags para separar diferentes grupos de *operações de rota*.
|
||||
Em muitos casos, sua aplicação FastAPI será maior, e você provavelmente usará tags para separar diferentes grupos de *operações de rota*.
|
||||
|
||||
Por exemplo, você poderia ter uma seção para **items** e outra seção para **users**, e elas poderiam ser separadas por tags:
|
||||
|
||||
{* ../../docs_src/generate_clients/tutorial002_py39.py hl[21,26,34] *}
|
||||
|
||||
### Gerar um Cliente TypeScript com Tags
|
||||
### Gere um cliente TypeScript com Tags { #generate-a-typescript-client-with-tags }
|
||||
|
||||
Se você gerar um cliente para um app FastAPI usando tags, normalmente também separará o código do cliente com base nas tags.
|
||||
Se você gerar um cliente para uma aplicação FastAPI usando tags, normalmente também separará o código do cliente com base nas tags.
|
||||
|
||||
Dessa forma, você poderá ter as coisas ordenadas e agrupadas corretamente para o código do cliente:
|
||||
|
||||
|
|
@ -152,33 +113,33 @@ Nesse caso você tem:
|
|||
* `ItemsService`
|
||||
* `UsersService`
|
||||
|
||||
### Nomes dos Métodos do Cliente
|
||||
### Nomes dos métodos do cliente { #client-method-names }
|
||||
|
||||
Agora os nomes dos métodos gerados como `createItemItemsPost` não parecem muito "limpos":
|
||||
Agora os nomes dos métodos gerados como `createItemItemsPost` não parecem muito “limpos”:
|
||||
|
||||
```TypeScript
|
||||
ItemsService.createItemItemsPost({name: "Plumbus", price: 5})
|
||||
```
|
||||
|
||||
...isto ocorre porque o gerador de clientes usa o **operation ID** interno do OpenAPI para cada *operação de rota*.
|
||||
...isso ocorre porque o gerador de clientes usa o **ID de operação** interno do OpenAPI para cada *operação de rota*.
|
||||
|
||||
O OpenAPI exige que cada operation ID seja único em todas as *operações de rota*, então o FastAPI usa o **nome da função**, o **caminho** e o **método/operacao HTTP** para gerar esse operation ID, porque dessa forma ele pode garantir que os operation IDs sejam únicos.
|
||||
O OpenAPI exige que cada ID de operação seja único em todas as *operações de rota*, então o FastAPI usa o **nome da função**, o **path** e o **método/operação HTTP** para gerar esse ID de operação, porque dessa forma ele pode garantir que os IDs de operação sejam únicos.
|
||||
|
||||
Mas eu vou te mostrar como melhorar isso a seguir. 🤓
|
||||
|
||||
### IDs de Operação Personalizados e Melhores Nomes de Método
|
||||
## IDs de operação personalizados e nomes de métodos melhores { #custom-operation-ids-and-better-method-names }
|
||||
|
||||
Você pode **modificar** a maneira como esses IDs de operação são **gerados** para torná-los mais simples e ter **nomes de método mais simples** nos clientes.
|
||||
|
||||
Neste caso, você terá que garantir que cada ID de operação seja **único** de alguma outra maneira.
|
||||
|
||||
Por exemplo, você poderia garantir que cada *operação de rota* tenha uma tag, e então gerar o ID da operação com base na **tag** e no **nome** da *operação de rota* (o nome da função).
|
||||
Por exemplo, você poderia garantir que cada *operação de rota* tenha uma tag, e então gerar o ID de operação com base na **tag** e no **nome** da *operação de rota* (o nome da função).
|
||||
|
||||
### Função Personalizada para Gerar IDs de Operação Únicos
|
||||
### Função personalizada para gerar IDs exclusivos { #custom-generate-unique-id-function }
|
||||
|
||||
O FastAPI usa um **ID único** para cada *operação de rota*, ele é usado para o **ID da operação** e também para os nomes de quaisquer modelos personalizados necessários, para requisições ou respostas.
|
||||
O FastAPI usa um **ID exclusivo** para cada *operação de rota*, ele é usado para o **ID de operação** e também para os nomes de quaisquer modelos personalizados necessários, para requisições ou respostas.
|
||||
|
||||
Você pode personalizar essa função. Ela recebe uma `APIRoute` e gera uma string.
|
||||
Você pode personalizar essa função. Ela recebe uma `APIRoute` e retorna uma string.
|
||||
|
||||
Por exemplo, aqui está usando a primeira tag (você provavelmente terá apenas uma tag) e o nome da *operação de rota* (o nome da função).
|
||||
|
||||
|
|
@ -186,15 +147,15 @@ Você pode então passar essa função personalizada para o **FastAPI** como o p
|
|||
|
||||
{* ../../docs_src/generate_clients/tutorial003_py39.py hl[6:7,10] *}
|
||||
|
||||
### Gerar um Cliente TypeScript com IDs de Operação Personalizados
|
||||
### Gere um cliente TypeScript com IDs de operação personalizados { #generate-a-typescript-client-with-custom-operation-ids }
|
||||
|
||||
Agora, se você gerar o cliente novamente, verá que ele tem os nomes dos métodos melhorados:
|
||||
|
||||
<img src="/img/tutorial/generate-clients/image07.png">
|
||||
|
||||
Como você pode ver, os nomes dos métodos agora têm a tag e, em seguida, o nome da função. Agora eles não incluem informações do caminho da URL e da operação HTTP.
|
||||
Como você pode ver, os nomes dos métodos agora têm a tag e, em seguida, o nome da função. Agora eles não incluem informações do path da URL e da operação HTTP.
|
||||
|
||||
### Pré-processar a Especificação OpenAPI para o Gerador de Clientes
|
||||
### Pré-processar a especificação OpenAPI para o gerador de clientes { #preprocess-the-openapi-specification-for-the-client-generator }
|
||||
|
||||
O código gerado ainda tem algumas **informações duplicadas**.
|
||||
|
||||
|
|
@ -202,7 +163,7 @@ Nós já sabemos que esse método está relacionado aos **items** porque essa pa
|
|||
|
||||
Provavelmente ainda queremos mantê-lo para o OpenAPI em geral, pois isso garantirá que os IDs de operação sejam **únicos**.
|
||||
|
||||
Mas para o cliente gerado, poderíamos **modificar** os IDs de operação do OpenAPI logo antes de gerar os clientes, apenas para tornar esses nomes de método mais **simples**.
|
||||
Mas para o cliente gerado, poderíamos **modificar** os IDs de operação do OpenAPI logo antes de gerar os clientes, apenas para tornar esses nomes de método mais agradáveis e **limpos**.
|
||||
|
||||
Poderíamos baixar o JSON do OpenAPI para um arquivo `openapi.json` e então poderíamos **remover essa tag prefixada** com um script como este:
|
||||
|
||||
|
|
@ -218,44 +179,30 @@ Poderíamos baixar o JSON do OpenAPI para um arquivo `openapi.json` e então pod
|
|||
|
||||
Com isso, os IDs de operação seriam renomeados de coisas como `items-get_items` para apenas `get_items`, dessa forma o gerador de clientes pode gerar nomes de métodos mais simples.
|
||||
|
||||
### Gerar um Cliente TypeScript com o OpenAPI Pré-processado
|
||||
### Gere um cliente TypeScript com o OpenAPI pré-processado { #generate-a-typescript-client-with-the-preprocessed-openapi }
|
||||
|
||||
Agora, como o resultado final está em um arquivo `openapi.json`, você modificaria o `package.json` para usar esse arquivo local, por exemplo:
|
||||
Como o resultado final está agora em um arquivo `openapi.json`, você precisa atualizar o local de entrada:
|
||||
|
||||
```JSON hl_lines="7"
|
||||
{
|
||||
"name": "frontend-app",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"generate-client": "openapi-ts --input ./openapi.json --output ./src/client --client axios"
|
||||
},
|
||||
"author": "",
|
||||
"license": "",
|
||||
"devDependencies": {
|
||||
"@hey-api/openapi-ts": "^0.27.38",
|
||||
"typescript": "^4.6.2"
|
||||
}
|
||||
}
|
||||
```sh
|
||||
npx @hey-api/openapi-ts -i ./openapi.json -o src/client
|
||||
```
|
||||
|
||||
Depois de gerar o novo cliente, você teria agora **nomes de métodos "limpos"**, com todo o **preenchimento automático**, **erros em linha**, etc:
|
||||
Depois de gerar o novo cliente, você terá agora **nomes de métodos “limpos”**, com todo o **preenchimento automático**, **erros em linha**, etc:
|
||||
|
||||
<img src="/img/tutorial/generate-clients/image08.png">
|
||||
|
||||
## Benefícios
|
||||
## Benefícios { #benefits }
|
||||
|
||||
Ao usar os clientes gerados automaticamente, você teria **preenchimento automático** para:
|
||||
Ao usar os clientes gerados automaticamente, você terá **preenchimento automático** para:
|
||||
|
||||
* Métodos.
|
||||
* Corpo de requisições, parâmetros da query, etc.
|
||||
* Corpo de respostas.
|
||||
* Corpos de requisições, parâmetros de query, etc.
|
||||
* Corpos de respostas.
|
||||
|
||||
Você também teria **erros em linha** para tudo.
|
||||
Você também terá **erros em linha** para tudo.
|
||||
|
||||
E sempre que você atualizar o código do backend, e **regenerar** o frontend, ele teria quaisquer novas *operações de rota* disponíveis como métodos, as antigas removidas, e qualquer outra alteração seria refletida no código gerado. 🤓
|
||||
E sempre que você atualizar o código do backend e **regenerar** o frontend, ele terá quaisquer novas *operações de rota* disponíveis como métodos, as antigas removidas, e qualquer outra alteração será refletida no código gerado. 🤓
|
||||
|
||||
Isso também significa que se algo mudar, será **refletido** no código do cliente automaticamente. E se você **construir** o cliente, ele dará erro se houver alguma **incompatibilidade** nos dados usados.
|
||||
Isso também significa que, se algo mudou, será **refletido** no código do cliente automaticamente. E se você **construir** o cliente, ele falhará caso haja qualquer **incompatibilidade** nos dados usados.
|
||||
|
||||
Então, você **detectaria vários erros** muito cedo no ciclo de desenvolvimento, em vez de ter que esperar que os erros apareçam para seus usuários finais em produção e então tentar depurar onde está o problema. ✨
|
||||
Assim, você **detectará muitos erros** muito cedo no ciclo de desenvolvimento, em vez de ter que esperar que os erros apareçam para seus usuários finais em produção e então tentar depurar onde está o problema. ✨
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
# Guia de Usuário Avançado
|
||||
# Guia de Usuário Avançado { #advanced-user-guide }
|
||||
|
||||
## Recursos Adicionais
|
||||
## Recursos Adicionais { #additional-features }
|
||||
|
||||
O [Tutorial - Guia de Usuário](../tutorial/index.md){.internal-link target=_blank} deve ser o suficiente para dar a você um tour por todos os principais recursos do **FastAPI**.
|
||||
|
||||
Na próxima seção você verá outras opções, configurações, e recursos adicionais.
|
||||
Nas próximas seções você verá outras opções, configurações, e recursos adicionais.
|
||||
|
||||
/// tip | Dica
|
||||
|
||||
|
|
@ -14,14 +14,8 @@ E é possível que para seu caso de uso, a solução esteja em uma delas.
|
|||
|
||||
///
|
||||
|
||||
## Leia o Tutorial primeiro
|
||||
## Leia o Tutorial primeiro { #read-the-tutorial-first }
|
||||
|
||||
Você ainda pode usar a maior parte dos recursos no **FastAPI** com o conhecimento do [Tutorial - Guia de Usuário](../tutorial/index.md){.internal-link target=_blank}.
|
||||
|
||||
E as próximas seções assumem que você já leu ele, e que você conhece suas ideias principais.
|
||||
|
||||
## Curso TestDriven.io
|
||||
|
||||
Se você gostaria de fazer um curso avançado-iniciante para complementar essa seção da documentação, você pode querer conferir: <a href="https://testdriven.io/courses/tdd-fastapi/" class="external-link" target="_blank">Test-Driven Development com FastAPI e Docker</a> por **TestDriven.io**.
|
||||
|
||||
Eles estão atualmente doando 10% de todos os lucros para o desenvolvimento do **FastAPI**. 🎉 😄
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
# Middleware Avançado
|
||||
# Middleware Avançado { #advanced-middleware }
|
||||
|
||||
No tutorial principal você leu como adicionar [Middleware Personalizado](../tutorial/middleware.md){.internal-link target=_blank} à sua aplicação.
|
||||
|
||||
|
|
@ -6,9 +6,9 @@ E então você também leu como lidar com [CORS com o `CORSMiddleware`](../tutor
|
|||
|
||||
Nesta seção, veremos como usar outros middlewares.
|
||||
|
||||
## Adicionando middlewares ASGI
|
||||
## Adicionando middlewares ASGI { #adding-asgi-middlewares }
|
||||
|
||||
Como o **FastAPI** é baseado no Starlette e implementa a especificação <abbr title="Asynchronous Server Gateway Interface">ASGI</abbr>, você pode usar qualquer middleware ASGI.
|
||||
Como o **FastAPI** é baseado no Starlette e implementa a especificação <abbr title="Asynchronous Server Gateway Interface – Interface de Gateway de Servidor Assíncrona">ASGI</abbr>, você pode usar qualquer middleware ASGI.
|
||||
|
||||
O middleware não precisa ser feito para o FastAPI ou Starlette para funcionar, desde que siga a especificação ASGI.
|
||||
|
||||
|
|
@ -39,19 +39,19 @@ app.add_middleware(UnicornMiddleware, some_config="rainbow")
|
|||
|
||||
`app.add_middleware()` recebe uma classe de middleware como o primeiro argumento e quaisquer argumentos adicionais a serem passados para o middleware.
|
||||
|
||||
## Middlewares Integrados
|
||||
## Middlewares Integrados { #integrated-middlewares }
|
||||
|
||||
**FastAPI** inclui vários middlewares para casos de uso comuns, veremos a seguir como usá-los.
|
||||
|
||||
/// note | Detalhes Técnicos
|
||||
|
||||
Para o próximo exemplo, você também poderia usar `from starlette.middleware.something import SomethingMiddleware`.
|
||||
Para os próximos exemplos, você também poderia usar `from starlette.middleware.something import SomethingMiddleware`.
|
||||
|
||||
**FastAPI** fornece vários middlewares em `fastapi.middleware` apenas como uma conveniência para você, o desenvolvedor. Mas a maioria dos middlewares disponíveis vem diretamente do Starlette.
|
||||
|
||||
///
|
||||
|
||||
## `HTTPSRedirectMiddleware`
|
||||
## `HTTPSRedirectMiddleware` { #httpsredirectmiddleware }
|
||||
|
||||
Garante que todas as requisições devem ser `https` ou `wss`.
|
||||
|
||||
|
|
@ -59,7 +59,7 @@ Qualquer requisição para `http` ou `ws` será redirecionada para o esquema seg
|
|||
|
||||
{* ../../docs_src/advanced_middleware/tutorial001.py hl[2,6] *}
|
||||
|
||||
## `TrustedHostMiddleware`
|
||||
## `TrustedHostMiddleware` { #trustedhostmiddleware }
|
||||
|
||||
Garante que todas as requisições recebidas tenham um cabeçalho `Host` corretamente configurado, a fim de proteger contra ataques de cabeçalho de host HTTP.
|
||||
|
||||
|
|
@ -68,10 +68,11 @@ Garante que todas as requisições recebidas tenham um cabeçalho `Host` correta
|
|||
Os seguintes argumentos são suportados:
|
||||
|
||||
* `allowed_hosts` - Uma lista de nomes de domínio que são permitidos como nomes de host. Domínios com coringa, como `*.example.com`, são suportados para corresponder a subdomínios. Para permitir qualquer nome de host, use `allowed_hosts=["*"]` ou omita o middleware.
|
||||
* `www_redirect` - Se definido como True, as requisições para versões sem www dos hosts permitidos serão redirecionadas para suas versões com www. O padrão é `True`.
|
||||
|
||||
Se uma requisição recebida não for validada corretamente, uma resposta `400` será enviada.
|
||||
|
||||
## `GZipMiddleware`
|
||||
## `GZipMiddleware` { #gzipmiddleware }
|
||||
|
||||
Gerencia respostas GZip para qualquer requisição que inclua `"gzip"` no cabeçalho `Accept-Encoding`.
|
||||
|
||||
|
|
@ -84,7 +85,7 @@ Os seguintes argumentos são suportados:
|
|||
* `minimum_size` - Não comprima respostas menores que este tamanho mínimo em bytes. O padrão é `500`.
|
||||
* `compresslevel` - Usado durante a compressão GZip. É um inteiro variando de 1 a 9. O padrão é `9`. Um valor menor resulta em uma compressão mais rápida, mas em arquivos maiores, enquanto um valor maior resulta em uma compressão mais lenta, mas em arquivos menores.
|
||||
|
||||
## Outros middlewares
|
||||
## Outros middlewares { #other-middlewares }
|
||||
|
||||
Há muitos outros middlewares ASGI.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,29 +1,29 @@
|
|||
# Callbacks na OpenAPI
|
||||
# Callbacks na OpenAPI { #openapi-callbacks }
|
||||
|
||||
Você poderia criar uma API com uma *operação de rota* que poderia acionar uma solicitação a uma *API externa* criada por outra pessoa (provavelmente o mesmo desenvolvedor que estaria *usando* sua API).
|
||||
|
||||
O processo que acontece quando seu aplicativo de API chama a *API externa* é chamado de "callback". Porque o software que o desenvolvedor externo escreveu envia uma solicitação para sua API e então sua API *chama de volta*, enviando uma solicitação para uma *API externa* (que provavelmente foi criada pelo mesmo desenvolvedor).
|
||||
O processo que acontece quando sua aplicação de API chama a *API externa* é chamado de "callback". Porque o software que o desenvolvedor externo escreveu envia uma solicitação para sua API e então sua API *chama de volta*, enviando uma solicitação para uma *API externa* (que provavelmente foi criada pelo mesmo desenvolvedor).
|
||||
|
||||
Nesse caso, você poderia querer documentar como essa API externa *deveria* ser. Que *operação de rota* ela deveria ter, que corpo ela deveria esperar, que resposta ela deveria retornar, etc.
|
||||
|
||||
## Um aplicativo com callbacks
|
||||
## Um aplicativo com callbacks { #an-app-with-callbacks }
|
||||
|
||||
Vamos ver tudo isso com um exemplo.
|
||||
|
||||
Imagine que você tem um aplicativo que permite criar faturas.
|
||||
Imagine que você desenvolve um aplicativo que permite criar faturas.
|
||||
|
||||
Essas faturas terão um `id`, `title` (opcional), `customer` e `total`.
|
||||
|
||||
O usuário da sua API (um desenvolvedor externo) criará uma fatura em sua API com uma solicitação POST.
|
||||
O usuário da sua API (um desenvolvedor externo) criará uma fatura na sua API com uma solicitação POST.
|
||||
|
||||
Então sua API irá (vamos imaginar):
|
||||
|
||||
* Enviar uma solicitação de pagamento para o desenvolvedor externo.
|
||||
* Enviar a fatura para algum cliente do desenvolvedor externo.
|
||||
* Coletar o dinheiro.
|
||||
* Enviar a notificação de volta para o usuário da API (o desenvolvedor externo).
|
||||
* Isso será feito enviando uma solicitação POST (de *sua API*) para alguma *API externa* fornecida por esse desenvolvedor externo (este é o "callback").
|
||||
* Isso será feito enviando uma solicitação POST (de *sua API*) para alguma *API externa* fornecida por esse desenvolvedor externo (este é o "callback").
|
||||
|
||||
## O aplicativo **FastAPI** normal
|
||||
## O aplicativo **FastAPI** normal { #the-normal-fastapi-app }
|
||||
|
||||
Vamos primeiro ver como o aplicativo da API normal se pareceria antes de adicionar o callback.
|
||||
|
||||
|
|
@ -39,11 +39,11 @@ O parâmetro de consulta `callback_url` usa um tipo Pydantic <a href="https://do
|
|||
|
||||
///
|
||||
|
||||
A única coisa nova é o argumento `callbacks=invoices_callback_router.routes` no decorador da *operação de rota*. Veremos o que é isso a seguir.
|
||||
A única novidade é o `callbacks=invoices_callback_router.routes` como argumento do decorador da *operação de rota*. Veremos o que é isso a seguir.
|
||||
|
||||
## Documentando o callback
|
||||
## Documentando o callback { #documenting-the-callback }
|
||||
|
||||
O código real do callback dependerá muito do seu próprio aplicativo de API.
|
||||
O código real do callback dependerá muito da sua própria aplicação de API.
|
||||
|
||||
E provavelmente variará muito de um aplicativo para o outro.
|
||||
|
||||
|
|
@ -58,7 +58,7 @@ Mas possivelmente a parte mais importante do callback é garantir que o usuário
|
|||
|
||||
Então, o que faremos a seguir é adicionar o código para documentar como essa *API externa* deve ser para receber o callback de *sua API*.
|
||||
|
||||
A documentação aparecerá na interface do Swagger em `/docs` em sua API, e permitirá que os desenvolvedores externos saibam como construir a *API externa*.
|
||||
A documentação aparecerá na Swagger UI em `/docs` na sua API, e permitirá que os desenvolvedores externos saibam como construir a *API externa*.
|
||||
|
||||
Esse exemplo não implementa o callback em si (que poderia ser apenas uma linha de código), apenas a parte da documentação.
|
||||
|
||||
|
|
@ -66,11 +66,11 @@ Esse exemplo não implementa o callback em si (que poderia ser apenas uma linha
|
|||
|
||||
O callback real é apenas uma solicitação HTTP.
|
||||
|
||||
Quando implementando o callback por você mesmo, você pode usar algo como <a href="https://www.python-httpx.org" class="external-link" target="_blank">HTTPX</a> ou <a href="https://requests.readthedocs.io/" class="external-link" target="_blank">Requisições</a>.
|
||||
Ao implementar o callback por conta própria, você pode usar algo como <a href="https://www.python-httpx.org" class="external-link" target="_blank">HTTPX</a> ou <a href="https://requests.readthedocs.io/" class="external-link" target="_blank">Requests</a>.
|
||||
|
||||
///
|
||||
|
||||
## Escrevendo o código de documentação do callback
|
||||
## Escreva o código de documentação do callback { #write-the-callback-documentation-code }
|
||||
|
||||
Esse código não será executado em seu aplicativo, nós só precisamos dele para *documentar* como essa *API externa* deveria ser.
|
||||
|
||||
|
|
@ -80,37 +80,37 @@ Então vamos usar esse mesmo conhecimento para documentar como a *API externa* d
|
|||
|
||||
/// tip | Dica
|
||||
|
||||
Quando escrever o código para documentar um callback, pode ser útil imaginar que você é aquele *desenvolvedor externo*. E que você está atualmente implementando a *API externa*, não *sua API*.
|
||||
Ao escrever o código para documentar um callback, pode ser útil imaginar que você é aquele *desenvolvedor externo*. E que você está atualmente implementando a *API externa*, não *sua API*.
|
||||
|
||||
Adotar temporariamente esse ponto de vista (do *desenvolvedor externo*) pode ajudar a sentir que é mais óbvio onde colocar os parâmetros, o modelo Pydantic para o corpo, para a resposta, etc. para essa *API externa*.
|
||||
Adotar temporariamente esse ponto de vista (do *desenvolvedor externo*) pode ajudar a perceber mais facilmente onde colocar os parâmetros, o modelo Pydantic para o corpo, para a resposta, etc. para essa *API externa*.
|
||||
|
||||
///
|
||||
|
||||
### Criar um `APIRouter` para o callback
|
||||
### Crie um `APIRouter` de callback { #create-a-callback-apirouter }
|
||||
|
||||
Primeiramente crie um novo `APIRouter` que conterá um ou mais callbacks.
|
||||
Primeiro crie um novo `APIRouter` que conterá um ou mais callbacks.
|
||||
|
||||
{* ../../docs_src/openapi_callbacks/tutorial001.py hl[3,25] *}
|
||||
|
||||
### Crie a *operação de rota* do callback
|
||||
### Crie a *operação de rota* do callback { #create-the-callback-path-operation }
|
||||
|
||||
Para criar a *operação de rota* do callback, use o mesmo `APIRouter` que você criou acima.
|
||||
|
||||
Ele deve parecer exatamente como uma *operação de rota* normal do FastAPI:
|
||||
Ela deve parecer exatamente como uma *operação de rota* normal do FastAPI:
|
||||
|
||||
* Ele provavelmente deveria ter uma declaração do corpo que deveria receber, por exemplo. `body: InvoiceEvent`.
|
||||
* E também deveria ter uma declaração de um código de status de resposta, por exemplo. `response_model=InvoiceEventReceived`.
|
||||
* Ela provavelmente deveria ter uma declaração do corpo que deveria receber, por exemplo, `body: InvoiceEvent`.
|
||||
* E também poderia ter uma declaração da resposta que deveria retornar, por exemplo, `response_model=InvoiceEventReceived`.
|
||||
|
||||
{* ../../docs_src/openapi_callbacks/tutorial001.py hl[16:18,21:22,28:32] *}
|
||||
|
||||
Há 2 diferenças principais de uma *operação de rota* normal:
|
||||
|
||||
* Ela não necessita ter nenhum código real, porque seu aplicativo nunca chamará esse código. Ele é usado apenas para documentar a *API externa*. Então, a função poderia ter apenas `pass`.
|
||||
* A *rota* pode conter uma <a href="https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#key-expression" class="external-link" target="_blank">expressão OpenAPI 3</a> (veja mais abaixo) onde pode usar variáveis com parâmetros e partes da solicitação original enviada para *sua API*.
|
||||
* O *path* pode conter uma <a href="https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#key-expression" class="external-link" target="_blank">expressão OpenAPI 3</a> (veja mais abaixo) em que pode usar variáveis com parâmetros e partes da solicitação original enviada para *sua API*.
|
||||
|
||||
### A expressão do caminho do callback
|
||||
### A expressão do path do callback { #the-callback-path-expression }
|
||||
|
||||
A *rota* do callback pode ter uma <a href="https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#key-expression" class="external-link" target="_blank">expressão OpenAPI 3</a> que pode conter partes da solicitação original enviada para *sua API*.
|
||||
O *path* do callback pode ter uma <a href="https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#key-expression" class="external-link" target="_blank">expressão OpenAPI 3</a> que pode conter partes da solicitação original enviada para *sua API*.
|
||||
|
||||
Nesse caso, é a `str`:
|
||||
|
||||
|
|
@ -163,11 +163,11 @@ Perceba como a URL de callback usada contém a URL recebida como um parâmetro d
|
|||
|
||||
///
|
||||
|
||||
### Adicionar o roteador de callback
|
||||
### Adicione o roteador de callback { #add-the-callback-router }
|
||||
|
||||
Nesse ponto você tem a(s) *operação de rota de callback* necessária(s) (a(s) que o *desenvolvedor externo* deveria implementar na *API externa*) no roteador de callback que você criou acima.
|
||||
Nesse ponto você tem a(s) *operação(ões) de rota de callback* necessária(s) (a(s) que o *desenvolvedor externo* deveria implementar na *API externa*) no roteador de callback que você criou acima.
|
||||
|
||||
Agora use o parâmetro `callbacks` no decorador da *operação de rota de sua API* para passar o atributo `.routes` (que é na verdade apenas uma `list` de rotas/*operações de rota*) do roteador de callback que você criou acima:
|
||||
Agora use o parâmetro `callbacks` no decorador da *operação de rota da sua API* para passar o atributo `.routes` (que é na verdade apenas uma `list` de rotas/*operações de path*) do roteador de callback:
|
||||
|
||||
{* ../../docs_src/openapi_callbacks/tutorial001.py hl[35] *}
|
||||
|
||||
|
|
@ -177,7 +177,7 @@ Perceba que você não está passando o roteador em si (`invoices_callback_route
|
|||
|
||||
///
|
||||
|
||||
### Verifique a documentação
|
||||
### Verifique a documentação { #check-the-docs }
|
||||
|
||||
Agora você pode iniciar seu aplicativo e ir para <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
# Webhooks OpenAPI
|
||||
# Webhooks OpenAPI { #openapi-webhooks }
|
||||
|
||||
Existem situações onde você deseja informar os **usuários** da sua API que a sua aplicação pode chamar a aplicação *deles* (enviando uma requisição) com alguns dados, normalmente para **notificar** algum tipo de **evento**.
|
||||
|
||||
|
|
@ -6,7 +6,7 @@ Isso significa que no lugar do processo normal de seus usuários enviarem requis
|
|||
|
||||
Isso normalmente é chamado de **webhook**.
|
||||
|
||||
## Etapas dos Webhooks
|
||||
## Etapas dos webhooks { #webhooks-steps }
|
||||
|
||||
Normalmente, o processo é que **você define** em seu código qual é a mensagem que você irá mandar, o **corpo da sua requisição**.
|
||||
|
||||
|
|
@ -16,7 +16,7 @@ E os **seus usuários** definem de alguma forma (em algum painel por exemplo) a
|
|||
|
||||
Toda a **lógica** sobre como cadastrar as URLs para os webhooks e o código para enviar de fato as requisições cabe a você definir. Você escreve da maneira que você desejar no **seu próprio código**.
|
||||
|
||||
## Documentando webhooks com o FastAPI e OpenAPI
|
||||
## Documentando webhooks com o FastAPI e OpenAPI { #documenting-webhooks-with-fastapi-and-openapi }
|
||||
|
||||
Com o **FastAPI**, utilizando o OpenAPI, você pode definir os nomes destes webhooks, os tipos das operações HTTP que a sua aplicação pode enviar (e.g. `POST`, `PUT`, etc.) e os **corpos** da requisição que a sua aplicação enviaria.
|
||||
|
||||
|
|
@ -28,7 +28,7 @@ Webhooks estão disponíveis a partir do OpenAPI 3.1.0, e possui suporte do Fast
|
|||
|
||||
///
|
||||
|
||||
## Uma aplicação com webhooks
|
||||
## Uma aplicação com webhooks { #an-app-with-webhooks }
|
||||
|
||||
Quando você cria uma aplicação com o **FastAPI**, existe um atributo chamado `webhooks`, que você utilizar para defini-los da mesma maneira que você definiria as suas **operações de rotas**, utilizando por exemplo `@app.webhooks.post()`.
|
||||
|
||||
|
|
@ -42,11 +42,11 @@ O objeto `app.webhooks` é na verdade apenas um `APIRouter`, o mesmo tipo que vo
|
|||
|
||||
///
|
||||
|
||||
Note que utilizando webhooks você não está de fato declarando uma **rota** (como `/items/`), o texto que informa é apenas um **identificador** do webhook (o nome do evento), por exemplo em `@app.webhooks.post("new-subscription")`, o nome do webhook é `new-subscription`.
|
||||
Note que utilizando webhooks você não está de fato declarando um *path* (como `/items/`), o texto que informa é apenas um **identificador** do webhook (o nome do evento), por exemplo em `@app.webhooks.post("new-subscription")`, o nome do webhook é `new-subscription`.
|
||||
|
||||
Isto porque espera-se que os **seus usuários** definam o verdadeiro **caminho da URL** onde eles desejam receber a requisição do webhook de algum outra maneira. (e.g. um painel).
|
||||
Isto porque espera-se que os **seus usuários** definam o verdadeiro **URL path** onde eles desejam receber a requisição do webhook de algum outra maneira. (e.g. um painel).
|
||||
|
||||
### Confira a documentação
|
||||
### Confira a documentação { #check-the-docs }
|
||||
|
||||
Agora você pode iniciar a sua aplicação e ir até <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
# Configuração Avançada da Operação de Rota
|
||||
# Configuração Avançada da Operação de Rota { #path-operation-advanced-configuration }
|
||||
|
||||
## operationId do OpenAPI
|
||||
## operationId do OpenAPI { #openapi-operationid }
|
||||
|
||||
/// warning | Aviso
|
||||
/// warning | Atenção
|
||||
|
||||
Se você não é um "especialista" no OpenAPI, você provavelmente não precisa disso.
|
||||
|
||||
|
|
@ -14,13 +14,13 @@ Você precisa ter certeza que ele é único para cada operação.
|
|||
|
||||
{* ../../docs_src/path_operation_advanced_configuration/tutorial001.py hl[6] *}
|
||||
|
||||
### Utilizando o nome da *função de operação de rota* como o operationId
|
||||
### Utilizando o nome da *função de operação de rota* como o operationId { #using-the-path-operation-function-name-as-the-operationid }
|
||||
|
||||
Se você quiser utilizar o nome das funções da sua API como `operationId`s, você pode iterar sobre todos esses nomes e sobrescrever o `operationId` em cada *operação de rota* utilizando o `APIRoute.name` dela.
|
||||
|
||||
Você deve fazer isso depois de adicionar todas as suas *operações de rota*.
|
||||
|
||||
{* ../../docs_src/path_operation_advanced_configuration/tutorial002.py hl[2,12:21,24] *}
|
||||
{* ../../docs_src/path_operation_advanced_configuration/tutorial002.py hl[2, 12:21, 24] *}
|
||||
|
||||
/// tip | Dica
|
||||
|
||||
|
|
@ -28,7 +28,7 @@ Se você chamar `app.openapi()` manualmente, os `operationId`s devem ser atualiz
|
|||
|
||||
///
|
||||
|
||||
/// warning | Aviso
|
||||
/// warning | Atenção
|
||||
|
||||
Se você fizer isso, você tem que ter certeza de que cada uma das suas *funções de operação de rota* tem um nome único.
|
||||
|
||||
|
|
@ -36,13 +36,13 @@ Mesmo que elas estejam em módulos (arquivos Python) diferentes.
|
|||
|
||||
///
|
||||
|
||||
## Excluir do OpenAPI
|
||||
## Excluir do OpenAPI { #exclude-from-openapi }
|
||||
|
||||
Para excluir uma *operação de rota* do esquema OpenAPI gerado (e por consequência, dos sistemas de documentação automáticos), utilize o parâmetro `include_in_schema` e defina ele como `False`:
|
||||
|
||||
{* ../../docs_src/path_operation_advanced_configuration/tutorial003.py hl[6] *}
|
||||
|
||||
## Descrição avançada a partir de docstring
|
||||
## Descrição avançada a partir de docstring { #advanced-description-from-docstring }
|
||||
|
||||
Você pode limitar as linhas utilizadas a partir de uma docstring de uma *função de operação de rota* para o OpenAPI.
|
||||
|
||||
|
|
@ -52,7 +52,7 @@ Ele não será mostrado na documentação, mas outras ferramentas (como o Sphinx
|
|||
|
||||
{* ../../docs_src/path_operation_advanced_configuration/tutorial004.py hl[19:29] *}
|
||||
|
||||
## Respostas Adicionais
|
||||
## Respostas Adicionais { #additional-responses }
|
||||
|
||||
Você provavelmente já viu como declarar o `response_model` e `status_code` para uma *operação de rota*.
|
||||
|
||||
|
|
@ -62,11 +62,11 @@ Você também pode declarar respostas adicionais, com seus modelos, códigos de
|
|||
|
||||
Existe um capítulo inteiro da nossa documentação sobre isso, você pode ler em [Retornos Adicionais no OpenAPI](additional-responses.md){.internal-link target=_blank}.
|
||||
|
||||
## Extras do OpenAPI
|
||||
## Extras do OpenAPI { #openapi-extra }
|
||||
|
||||
Quando você declara uma *operação de rota* na sua aplicação, o **FastAPI** irá gerar os metadados relevantes da *operação de rota* automaticamente para serem incluídos no esquema do OpenAPI.
|
||||
|
||||
/// note | Nota
|
||||
/// note | Detalhes Técnicos
|
||||
|
||||
Na especificação do OpenAPI, isso é chamado de um <a href="https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#operation-object" class="external-link" target="_blank">Objeto de Operação</a>.
|
||||
|
||||
|
|
@ -88,7 +88,7 @@ Caso você só precise declarar respostas adicionais, uma forma conveniente de f
|
|||
|
||||
Você pode estender o esquema do OpenAPI para uma *operação de rota* utilizando o parâmetro `openapi_extra`.
|
||||
|
||||
### Extensões do OpenAPI
|
||||
### Extensões do OpenAPI { #openapi-extensions }
|
||||
|
||||
Esse parâmetro `openapi_extra` pode ser útil, por exemplo, para declarar [Extensões do OpenAPI](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#specificationExtensions):
|
||||
|
||||
|
|
@ -129,7 +129,7 @@ E se você olhar o esquema OpenAPI resultante (na rota `/openapi.json` da sua AP
|
|||
}
|
||||
```
|
||||
|
||||
### Esquema de *operação de rota* do OpenAPI personalizado
|
||||
### Esquema de *operação de rota* do OpenAPI personalizado { #custom-openapi-path-operation-schema }
|
||||
|
||||
O dicionário em `openapi_extra` vai ter todos os seus níveis mesclados dentro do esquema OpenAPI gerado automaticamente para a *operação de rota*.
|
||||
|
||||
|
|
@ -139,39 +139,39 @@ Por exemplo, você poderia optar por ler e validar a requisição com seu própr
|
|||
|
||||
Você pode fazer isso com `openapi_extra`:
|
||||
|
||||
{* ../../docs_src/path_operation_advanced_configuration/tutorial006.py hl[19:36,39:40] *}
|
||||
{* ../../docs_src/path_operation_advanced_configuration/tutorial006.py hl[19:36, 39:40] *}
|
||||
|
||||
Nesse exemplo, nós não declaramos nenhum modelo do Pydantic. Na verdade, o corpo da requisição não está nem mesmo <abbr title="convertido de um formato plano, como bytes, para objetos Python">analisado</abbr> como JSON, ele é lido diretamente como `bytes` e a função `magic_data_reader()` seria a responsável por analisar ele de alguma forma.
|
||||
|
||||
De toda forma, nós podemos declarar o esquema esperado para o corpo da requisição.
|
||||
|
||||
### Tipo de conteúdo do OpenAPI personalizado
|
||||
### Tipo de conteúdo do OpenAPI personalizado { #custom-openapi-content-type }
|
||||
|
||||
Utilizando esse mesmo truque, você pode utilizar um modelo Pydantic para definir o esquema JSON que é então incluído na seção do esquema personalizado do OpenAPI na *operação de rota*.
|
||||
Utilizando esse mesmo truque, você pode utilizar um modelo Pydantic para definir o JSON Schema que é então incluído na seção do esquema personalizado do OpenAPI na *operação de rota*.
|
||||
|
||||
E você pode fazer isso até mesmo quando os dados da requisição não seguem o formato JSON.
|
||||
|
||||
Por exemplo, nesta aplicação nós não usamos a funcionalidade integrada ao FastAPI de extrair o esquema JSON dos modelos Pydantic nem a validação automática do JSON. Na verdade, estamos declarando o tipo do conteúdo da requisição como YAML, em vez de JSON:
|
||||
Por exemplo, nesta aplicação nós não usamos a funcionalidade integrada ao FastAPI de extrair o JSON Schema dos modelos Pydantic nem a validação automática do JSON. Na verdade, estamos declarando o tipo do conteúdo da requisição como YAML, em vez de JSON:
|
||||
|
||||
//// tab | Pydantic v2
|
||||
|
||||
{* ../../docs_src/path_operation_advanced_configuration/tutorial007.py hl[17:22,24] *}
|
||||
{* ../../docs_src/path_operation_advanced_configuration/tutorial007.py hl[17:22, 24] *}
|
||||
|
||||
////
|
||||
|
||||
//// tab | Pydantic v1
|
||||
|
||||
{* ../../docs_src/path_operation_advanced_configuration/tutorial007_pv1.py hl[17:22,24] *}
|
||||
{* ../../docs_src/path_operation_advanced_configuration/tutorial007_pv1.py hl[17:22, 24] *}
|
||||
|
||||
////
|
||||
|
||||
/// info | Informação
|
||||
|
||||
Na versão 1 do Pydantic, o método para obter o esquema JSON de um modelo é `Item.schema()`, na versão 2 do Pydantic, o método é `Item.model_json_schema()`
|
||||
Na versão 1 do Pydantic, o método para obter o JSON Schema de um modelo é `Item.schema()`, na versão 2 do Pydantic, o método é `Item.model_json_schema()`.
|
||||
|
||||
///
|
||||
|
||||
Entretanto, mesmo que não utilizemos a funcionalidade integrada por padrão, ainda estamos usando um modelo Pydantic para gerar um esquema JSON manualmente para os dados que queremos receber no formato YAML.
|
||||
Entretanto, mesmo que não utilizemos a funcionalidade integrada por padrão, ainda estamos usando um modelo Pydantic para gerar um JSON Schema manualmente para os dados que queremos receber no formato YAML.
|
||||
|
||||
Então utilizamos a requisição diretamente, e extraímos o corpo como `bytes`. Isso significa que o FastAPI não vai sequer tentar analisar o corpo da requisição como JSON.
|
||||
|
||||
|
|
@ -195,7 +195,7 @@ Na versão 1 do Pydantic, o método para analisar e validar um objeto era `Item.
|
|||
|
||||
///
|
||||
|
||||
///tip | Dica
|
||||
/// tip | Dica
|
||||
|
||||
Aqui reutilizamos o mesmo modelo do Pydantic.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
# Retorno - Altere o Código de Status
|
||||
# Retorno - Altere o Código de Status { #response-change-status-code }
|
||||
|
||||
Você provavelmente leu anteriormente que você pode definir um [Código de Status do Retorno](../tutorial/response-status-code.md){.internal-link target=_blank} padrão.
|
||||
|
||||
Porém em alguns casos você precisa retornar um código de status diferente do padrão.
|
||||
|
||||
## Caso de uso
|
||||
## Caso de uso { #use-case }
|
||||
|
||||
Por exemplo, imagine que você deseja retornar um código de status HTTP de "OK" `200` por padrão.
|
||||
|
||||
|
|
@ -14,7 +14,7 @@ Mas você ainda quer ser capaz de filtrar e converter o dado que você retornar
|
|||
|
||||
Para estes casos, você pode utilizar um parâmetro `Response`.
|
||||
|
||||
## Use um parâmetro `Response`
|
||||
## Use um parâmetro `Response` { #use-a-response-parameter }
|
||||
|
||||
Você pode declarar um parâmetro do tipo `Response` em sua *função de operação de rota* (assim como você pode fazer para cookies e headers).
|
||||
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
# Cookies de Resposta
|
||||
# Cookies de Resposta { #response-cookies }
|
||||
|
||||
## Usando um parâmetro `Response`
|
||||
## Use um parâmetro `Response` { #use-a-response-parameter }
|
||||
|
||||
Você pode declarar um parâmetro do tipo `Response` na sua *função de operação de rota*.
|
||||
|
||||
E então você pode definir cookies nesse objeto de resposta *temporário*.
|
||||
|
||||
{* ../../docs_src/response_cookies/tutorial002.py hl[1,8:9] *}
|
||||
{* ../../docs_src/response_cookies/tutorial002.py hl[1, 8:9] *}
|
||||
|
||||
Em seguida, você pode retornar qualquer objeto que precise, como normalmente faria (um `dict`, um modelo de banco de dados, etc).
|
||||
|
||||
|
|
@ -16,11 +16,11 @@ E se você declarou um `response_model`, ele ainda será usado para filtrar e co
|
|||
|
||||
Você também pode declarar o parâmetro `Response` em dependências e definir cookies (e cabeçalhos) nelas.
|
||||
|
||||
## Retornando uma `Response` diretamente
|
||||
## Retorne uma `Response` diretamente { #return-a-response-directly }
|
||||
|
||||
Você também pode criar cookies ao retornar uma `Response` diretamente no seu código.
|
||||
|
||||
Para fazer isso, você pode criar uma resposta como descrito em [Retornando uma Resposta Diretamente](response-directly.md){.internal-link target=_blank}.
|
||||
Para fazer isso, você pode criar uma resposta como descrito em [Retorne uma Resposta Diretamente](response-directly.md){.internal-link target=_blank}.
|
||||
|
||||
Então, defina os cookies nela e a retorne:
|
||||
|
||||
|
|
@ -36,7 +36,7 @@ E também que você não esteja enviando nenhum dado que deveria ter sido filtra
|
|||
|
||||
///
|
||||
|
||||
### Mais informações
|
||||
### Mais informações { #more-info }
|
||||
|
||||
/// note | Detalhes Técnicos
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
# Retornando uma Resposta Diretamente
|
||||
# Retornando uma Resposta Diretamente { #return-a-response-directly }
|
||||
|
||||
Quando você cria uma *operação de rota* no **FastAPI** você pode retornar qualquer dado nela: um dicionário (`dict`), uma lista (`list`), um modelo do Pydantic ou do seu banco de dados, etc.
|
||||
|
||||
|
|
@ -10,7 +10,7 @@ Mas você pode retornar a `JSONResponse` diretamente nas suas *operações de ro
|
|||
|
||||
Pode ser útil para retornar cabeçalhos e cookies personalizados, por exemplo.
|
||||
|
||||
## Retornando uma `Response`
|
||||
## Retornando uma `Response` { #return-a-response }
|
||||
|
||||
Na verdade, você pode retornar qualquer `Response` ou subclasse dela.
|
||||
|
||||
|
|
@ -26,7 +26,7 @@ Ele não vai fazer conversões de dados com modelos do Pydantic, não irá conve
|
|||
|
||||
Isso te dá bastante flexibilidade. Você pode retornar qualquer tipo de dado, sobrescrever qualquer declaração e validação nos dados, etc.
|
||||
|
||||
## Utilizando o `jsonable_encoder` em uma `Response`
|
||||
## Utilizando o `jsonable_encoder` em uma `Response` { #using-the-jsonable-encoder-in-a-response }
|
||||
|
||||
Como o **FastAPI** não realiza nenhuma mudança na `Response` que você retorna, você precisa garantir que o conteúdo dela está pronto para uso.
|
||||
|
||||
|
|
@ -44,23 +44,22 @@ Você também pode utilizar `from starlette.responses import JSONResponse`.
|
|||
|
||||
///
|
||||
|
||||
## Retornando uma `Response`
|
||||
## Retornando uma `Response` personalizada { #returning-a-custom-response }
|
||||
|
||||
O exemplo acima mostra todas as partes que você precisa, mas ainda não é muito útil, já que você poderia ter retornado o `item` diretamente, e o **FastAPI** colocaria em uma `JSONResponse` para você, convertendo em um `dict`, etc. Tudo isso por padrão.
|
||||
|
||||
Agora, vamos ver como você pode usar isso para retornar uma resposta personalizada.
|
||||
|
||||
Vamos dizer quer retornar uma resposta <a href="https://pt.wikipedia.org/wiki/XML" class="external-link" target="_blank">XML</a>.
|
||||
Vamos dizer que você quer retornar uma resposta <a href="https://en.wikipedia.org/wiki/XML" class="external-link" target="_blank">XML</a>.
|
||||
|
||||
Você pode colocar o seu conteúdo XML em uma string, colocar em uma `Response`, e retorná-lo:
|
||||
|
||||
{* ../../docs_src/response_directly/tutorial002.py hl[1,18] *}
|
||||
|
||||
## Notas
|
||||
## Notas { #notes }
|
||||
|
||||
Quando você retorna uma `Response` diretamente os dados não são validados, convertidos (serializados) ou documentados automaticamente.
|
||||
|
||||
Mas você ainda pode documentar como descrito em [Retornos Adicionais no OpenAPI
|
||||
](additional-responses.md){.internal-link target=_blank}.
|
||||
Mas você ainda pode documentar como descrito em [Retornos Adicionais no OpenAPI](additional-responses.md){.internal-link target=_blank}.
|
||||
|
||||
Você pode ver nas próximas seções como usar/declarar essas `Responses` customizadas enquanto mantém a conversão e documentação automática dos dados.
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
# Cabeçalhos de resposta
|
||||
# Cabeçalhos de resposta { #response-headers }
|
||||
|
||||
## Usando um parâmetro `Response`
|
||||
## Use um parâmetro `Response` { #use-a-response-parameter }
|
||||
|
||||
Você pode declarar um parâmetro do tipo `Response` na sua *função de operação de rota* (assim como você pode fazer para cookies).
|
||||
|
||||
Então você pode definir os cabeçalhos nesse objeto de resposta *temporário*.
|
||||
|
||||
{* ../../docs_src/response_headers/tutorial002.py hl[1,7:8] *}
|
||||
{* ../../docs_src/response_headers/tutorial002.py hl[1, 7:8] *}
|
||||
|
||||
Em seguida você pode retornar qualquer objeto que precisar, da maneira que faria normalmente (um `dict`, um modelo de banco de dados, etc.).
|
||||
|
||||
|
|
@ -16,7 +16,7 @@ Se você declarou um `response_model`, ele ainda será utilizado para filtrar e
|
|||
|
||||
Você também pode declarar o parâmetro `Response` em dependências e definir cabeçalhos (e cookies) nelas.
|
||||
|
||||
## Retornar uma `Response` diretamente
|
||||
## Retorne uma `Response` diretamente { #return-a-response-directly }
|
||||
|
||||
Você também pode adicionar cabeçalhos quando retornar uma `Response` diretamente.
|
||||
|
||||
|
|
@ -24,7 +24,7 @@ Crie uma resposta conforme descrito em [Retornar uma resposta diretamente](respo
|
|||
|
||||
{* ../../docs_src/response_headers/tutorial001.py hl[10:12] *}
|
||||
|
||||
/// note | Detalhes técnicos
|
||||
/// note | Detalhes Técnicos
|
||||
|
||||
Você também pode usar `from starlette.responses import Response` ou `from starlette.responses import JSONResponse`.
|
||||
|
||||
|
|
@ -34,8 +34,8 @@ E como a `Response` pode ser usada frequentemente para definir cabeçalhos e coo
|
|||
|
||||
///
|
||||
|
||||
## Cabeçalhos personalizados
|
||||
## Cabeçalhos personalizados { #custom-headers }
|
||||
|
||||
Tenha em mente que cabeçalhos personalizados proprietários podem ser adicionados <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers" class="external-link" target="_blank">usando o prefixo 'X-'</a>.
|
||||
Tenha em mente que cabeçalhos personalizados proprietários podem ser adicionados <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers" class="external-link" target="_blank">usando o prefixo `X-`</a>.
|
||||
|
||||
Porém, se voce tiver cabeçalhos personalizados que deseja que um cliente no navegador possa ver, você precisa adicioná-los às suas configurações de CORS (saiba mais em [CORS (Cross-Origin Resource Sharing)](../tutorial/cors.md){.internal-link target=_blank}), usando o parâmetro `expose_headers` descrito na <a href="https://www.starlette.dev/middleware/#corsmiddleware" class="external-link" target="_blank">documentação de CORS do Starlette</a>.
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
# HTTP Basic Auth
|
||||
# HTTP Basic Auth { #http-basic-auth }
|
||||
|
||||
Para os casos mais simples, você pode utilizar o HTTP Basic Auth.
|
||||
|
||||
No HTTP Basic Auth, a aplicação espera um cabeçalho que contém um usuário e uma senha.
|
||||
|
||||
Caso ela não receba, ela retorna um erro HTTP 401 "Unauthorized" (*Não Autorizado*).
|
||||
Caso ela não receba, ela retorna um erro HTTP 401 "Unauthorized".
|
||||
|
||||
E retorna um cabeçalho `WWW-Authenticate` com o valor `Basic`, e um parâmetro opcional `realm`.
|
||||
|
||||
|
|
@ -12,7 +12,7 @@ Isso sinaliza ao navegador para mostrar o prompt integrado para um usuário e se
|
|||
|
||||
Então, quando você digitar o usuário e senha, o navegador os envia automaticamente no cabeçalho.
|
||||
|
||||
## HTTP Basic Auth Simples
|
||||
## HTTP Basic Auth Simples { #simple-http-basic-auth }
|
||||
|
||||
* Importe `HTTPBasic` e `HTTPBasicCredentials`.
|
||||
* Crie um "esquema `security`" utilizando `HTTPBasic`.
|
||||
|
|
@ -22,11 +22,11 @@ Então, quando você digitar o usuário e senha, o navegador os envia automatica
|
|||
|
||||
{* ../../docs_src/security/tutorial006_an_py39.py hl[4,8,12] *}
|
||||
|
||||
Quando você tentar abrir a URL pela primeira vez (ou clicar no botão "Executar" nos documentos) o navegador vai pedir pelo seu usuário e senha:
|
||||
Quando você tentar abrir a URL pela primeira vez (ou clicar no botão "Executar" na documentação) o navegador vai pedir pelo seu usuário e senha:
|
||||
|
||||
<img src="/img/tutorial/security/image12.png">
|
||||
|
||||
## Verifique o usuário
|
||||
## Verifique o usuário { #check-the-username }
|
||||
|
||||
Aqui está um exemplo mais completo.
|
||||
|
||||
|
|
@ -52,7 +52,7 @@ if not (credentials.username == "stanleyjobson") or not (credentials.password ==
|
|||
|
||||
Porém, ao utilizar o `secrets.compare_digest()`, isso estará seguro contra um tipo de ataque chamado "timing attacks" (ataques de temporização).
|
||||
|
||||
### Ataques de Temporização
|
||||
### Ataques de Temporização { #timing-attacks }
|
||||
|
||||
Mas o que é um "timing attack" (ataque de temporização)?
|
||||
|
||||
|
|
@ -80,19 +80,19 @@ if "stanleyjobsox" == "stanleyjobson" and "love123" == "swordfish":
|
|||
|
||||
O Python terá que comparar todo o `stanleyjobso` tanto em `stanleyjobsox` como em `stanleyjobson` antes de perceber que as strings não são a mesma. Então isso levará alguns microssegundos a mais para retornar "Usuário ou senha incorretos".
|
||||
|
||||
#### O tempo para responder ajuda os invasores
|
||||
#### O tempo para responder ajuda os invasores { #the-time-to-answer-helps-the-attackers }
|
||||
|
||||
Neste ponto, ao perceber que o servidor demorou alguns microssegundos a mais para enviar o retorno "Usuário ou senha incorretos", os invasores irão saber que eles acertaram _alguma coisa_, algumas das letras iniciais estavam certas.
|
||||
|
||||
E eles podem tentar de novo sabendo que provavelmente é algo mais parecido com `stanleyjobsox` do que com `johndoe`.
|
||||
|
||||
#### Um ataque "profissional"
|
||||
#### Um ataque "profissional" { #a-professional-attack }
|
||||
|
||||
Claro, os invasores não tentariam tudo isso de forma manual, eles escreveriam um programa para fazer isso, possivelmente com milhares ou milhões de testes por segundo. E obteriam apenas uma letra a mais por vez.
|
||||
|
||||
Mas fazendo isso, em alguns minutos ou horas os invasores teriam adivinhado o usuário e senha corretos, com a "ajuda" da nossa aplicação, apenas usando o tempo levado para responder.
|
||||
|
||||
#### Corrija com o `secrets.compare_digest()`
|
||||
#### Corrija com o `secrets.compare_digest()` { #fix-it-with-secrets-compare-digest }
|
||||
|
||||
Mas em nosso código já estamos utilizando o `secrets.compare_digest()`.
|
||||
|
||||
|
|
@ -100,8 +100,7 @@ Resumindo, levará o mesmo tempo para comparar `stanleyjobsox` com `stanleyjobso
|
|||
|
||||
Deste modo, ao utilizar `secrets.compare_digest()` no código de sua aplicação, ela estará a salvo contra toda essa gama de ataques de segurança.
|
||||
|
||||
|
||||
### Retorne o erro
|
||||
### Retorne o erro { #return-the-error }
|
||||
|
||||
Após detectar que as credenciais estão incorretas, retorne um `HTTPException` com o status 401 (o mesmo retornado quando nenhuma credencial foi informada) e adicione o cabeçalho `WWW-Authenticate` para fazer com que o navegador mostre o prompt de login novamente:
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# Segurança Avançada
|
||||
# Segurança Avançada { #advanced-security }
|
||||
|
||||
## Funcionalidades Adicionais
|
||||
## Funcionalidades Adicionais { #additional-features }
|
||||
|
||||
Existem algumas funcionalidades adicionais para lidar com segurança além das cobertas em [Tutorial - Guia de Usuário: Segurança](../../tutorial/security/index.md){.internal-link target=_blank}.
|
||||
|
||||
|
|
@ -12,7 +12,7 @@ E é possível que para o seu caso de uso, a solução está em uma delas.
|
|||
|
||||
///
|
||||
|
||||
## Leia o Tutorial primeiro
|
||||
## Leia o Tutorial primeiro { #read-the-tutorial-first }
|
||||
|
||||
As próximas seções pressupõem que você já leu o principal [Tutorial - Guia de Usuário: Segurança](../../tutorial/security/index.md){.internal-link target=_blank}.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
# Escopos OAuth2
|
||||
# Escopos OAuth2 { #oauth2-scopes }
|
||||
|
||||
Você pode utilizar escopos do OAuth2 diretamente com o **FastAPI**, eles são integrados para funcionar perfeitamente.
|
||||
|
||||
|
|
@ -10,7 +10,7 @@ Toda vez que você "se autentica com" Facebook, Google, GitHub, Microsoft, X (Tw
|
|||
|
||||
Nesta seção, você verá como gerenciar a autenticação e autorização com os mesmos escopos do OAuth2 em sua aplicação **FastAPI**.
|
||||
|
||||
/// warning | Aviso
|
||||
/// warning | Atenção
|
||||
|
||||
Isso é uma seção mais ou menos avançada. Se você está apenas começando, você pode pular.
|
||||
|
||||
|
|
@ -18,7 +18,7 @@ Você não necessariamente precisa de escopos do OAuth2, e você pode lidar com
|
|||
|
||||
Mas o OAuth2 com escopos pode ser integrado de maneira fácil em sua API (com OpenAPI) e a sua documentação de API.
|
||||
|
||||
No entando, você ainda aplica estes escopos, ou qualquer outro requisito de segurança/autorização, conforme necessário, em seu código.
|
||||
No entanto, você ainda aplica estes escopos, ou qualquer outro requisito de segurança/autorização, conforme necessário, em seu código.
|
||||
|
||||
Em muitos casos, OAuth2 com escopos pode ser um exagero.
|
||||
|
||||
|
|
@ -26,7 +26,7 @@ Mas se você sabe que precisa, ou está curioso, continue lendo.
|
|||
|
||||
///
|
||||
|
||||
## Escopos OAuth2 e OpenAPI
|
||||
## Escopos OAuth2 e OpenAPI { #oauth2-scopes-and-openapi }
|
||||
|
||||
A especificação OAuth2 define "escopos" como uma lista de strings separadas por espaços.
|
||||
|
||||
|
|
@ -58,15 +58,15 @@ Para o OAuth2, eles são apenas strings.
|
|||
|
||||
///
|
||||
|
||||
## Visão global
|
||||
## Visão global { #global-view }
|
||||
|
||||
Primeiro, vamos olhar rapidamente as partes que mudam dos exemplos do **Tutorial - Guia de Usuário** para [OAuth2 com Senha (e hash), Bearer com tokens JWT](../../tutorial/security/oauth2-jwt.md){.internal-link target=_blank}. Agora utilizando escopos OAuth2:
|
||||
|
||||
{* ../../docs_src/security/tutorial005_an_py310.py hl[5,9,13,47,65,106,108:116,122:125,129:135,140,156] *}
|
||||
{* ../../docs_src/security/tutorial005_an_py310.py hl[5,9,13,47,65,106,108:116,122:126,130:136,141,157] *}
|
||||
|
||||
Agora vamos revisar essas mudanças passo a passo.
|
||||
|
||||
## Esquema de segurança OAuth2
|
||||
## Esquema de segurança OAuth2 { #oauth2-security-scheme }
|
||||
|
||||
A primeira mudança é que agora nós estamos declarando o esquema de segurança OAuth2 com dois escopos disponíveis, `me` e `items`.
|
||||
|
||||
|
|
@ -82,9 +82,9 @@ Este é o mesmo mecanismo utilizado quando você adiciona permissões enquanto s
|
|||
|
||||
<img src="/img/tutorial/security/image11.png">
|
||||
|
||||
## Token JWT com escopos
|
||||
## Token JWT com escopos { #jwt-token-with-scopes }
|
||||
|
||||
Agora, modifique o *caminho de rota* para retornar os escopos solicitados.
|
||||
Agora, modifique a *operação de rota* do token para retornar os escopos solicitados.
|
||||
|
||||
Nós ainda estamos utilizando o mesmo `OAuth2PasswordRequestForm`. Ele inclui a propriedade `scopes` com uma `list` de `str`, com cada escopo que ele recebeu na requisição.
|
||||
|
||||
|
|
@ -98,15 +98,15 @@ Porém em sua aplicação, por segurança, você deve garantir que você apenas
|
|||
|
||||
///
|
||||
|
||||
{* ../../docs_src/security/tutorial005_an_py310.py hl[156] *}
|
||||
{* ../../docs_src/security/tutorial005_an_py310.py hl[157] *}
|
||||
|
||||
## Declare escopos em *operações de rota* e dependências
|
||||
## Declare escopos em *operações de rota* e dependências { #declare-scopes-in-path-operations-and-dependencies }
|
||||
|
||||
Agora nós declaramos que a *operação de rota* para `/users/me/items/` exige o escopo `items`.
|
||||
|
||||
Para isso, nós importamos e utilizamos `Security` de `fastapi`.
|
||||
|
||||
Você pode utilizar `Security` para declarar dependências (assim como `Depends`), porém o `Security` também recebe o parâmetros `scopes` com uma lista de escopos (strings).
|
||||
Você pode utilizar `Security` para declarar dependências (assim como `Depends`), porém o `Security` também recebe o parâmetro `scopes` com uma lista de escopos (strings).
|
||||
|
||||
Neste caso, nós passamos a função `get_current_active_user` como dependência para `Security` (da mesma forma que nós faríamos com `Depends`).
|
||||
|
||||
|
|
@ -124,9 +124,9 @@ Nós estamos fazendo isso aqui para demonstrar como o **FastAPI** lida com escop
|
|||
|
||||
///
|
||||
|
||||
{* ../../docs_src/security/tutorial005_an_py310.py hl[5,140,171] *}
|
||||
{* ../../docs_src/security/tutorial005_an_py310.py hl[5,141,172] *}
|
||||
|
||||
/// info | Informações Técnicas
|
||||
/// info | Detalhes Técnicos
|
||||
|
||||
`Security` é na verdade uma subclasse de `Depends`, e ele possui apenas um parâmetro extra que veremos depois.
|
||||
|
||||
|
|
@ -136,7 +136,7 @@ Mas quando você importa `Query`, `Path`, `Depends`, `Security` entre outros de
|
|||
|
||||
///
|
||||
|
||||
## Utilize `SecurityScopes`
|
||||
## Utilize `SecurityScopes` { #use-securityscopes }
|
||||
|
||||
Agora atualize a dependência `get_current_user`.
|
||||
|
||||
|
|
@ -152,7 +152,7 @@ A classe `SecurityScopes` é semelhante à classe `Request` (`Request` foi utili
|
|||
|
||||
{* ../../docs_src/security/tutorial005_an_py310.py hl[9,106] *}
|
||||
|
||||
## Utilize os `scopes`
|
||||
## Utilize os `scopes` { #use-the-scopes }
|
||||
|
||||
O parâmetro `security_scopes` será do tipo `SecurityScopes`.
|
||||
|
||||
|
|
@ -166,7 +166,7 @@ Nesta exceção, nós incluímos os escopos necessários (se houver algum) como
|
|||
|
||||
{* ../../docs_src/security/tutorial005_an_py310.py hl[106,108:116] *}
|
||||
|
||||
## Verifique o `username` e o formato dos dados
|
||||
## Verifique o `username` e o formato dos dados { #verify-the-username-and-data-shape }
|
||||
|
||||
Nós verificamos que nós obtemos um `username`, e extraímos os escopos.
|
||||
|
||||
|
|
@ -180,17 +180,17 @@ No lugar de, por exemplo, um `dict`, ou alguma outra coisa, que poderia quebrar
|
|||
|
||||
Nós também verificamos que nós temos um usuário com o "*username*", e caso contrário, nós levantamos a mesma exceção que criamos anteriormente.
|
||||
|
||||
{* ../../docs_src/security/tutorial005_an_py310.py hl[47,117:128] *}
|
||||
{* ../../docs_src/security/tutorial005_an_py310.py hl[47,117:129] *}
|
||||
|
||||
## Verifique os `scopes`
|
||||
## Verifique os `scopes` { #verify-the-scopes }
|
||||
|
||||
Nós verificamos agora que todos os escopos necessários, por essa dependência e todos os dependentes (incluindo as *operações de rota*) estão incluídas nos escopos fornecidos pelo token recebido, caso contrário, levantamos uma `HTTPException`.
|
||||
|
||||
Para isso, nós utilizamos `security_scopes.scopes`, que contém uma `list` com todos esses escopos como uma `str`.
|
||||
|
||||
{* ../../docs_src/security/tutorial005_an_py310.py hl[129:135] *}
|
||||
{* ../../docs_src/security/tutorial005_an_py310.py hl[130:136] *}
|
||||
|
||||
## Árvore de dependência e escopos
|
||||
## Árvore de dependência e escopos { #dependency-tree-and-scopes }
|
||||
|
||||
Vamos rever novamente essa árvore de dependência e os escopos.
|
||||
|
||||
|
|
@ -223,7 +223,7 @@ Tudo depende dos `scopes` declarados em cada *operação de rota* e cada depend
|
|||
|
||||
///
|
||||
|
||||
## Mais detalhes sobre `SecurityScopes`
|
||||
## Mais detalhes sobre `SecurityScopes` { #more-details-about-securityscopes }
|
||||
|
||||
Você pode utilizar `SecurityScopes` em qualquer lugar, e em diversos lugares. Ele não precisa estar na dependência "raiz".
|
||||
|
||||
|
|
@ -233,9 +233,9 @@ Porque o `SecurityScopes` terá todos os escopos declarados por dependentes, voc
|
|||
|
||||
Todos eles serão validados independentemente para cada *operação de rota*.
|
||||
|
||||
## Verifique
|
||||
## Verifique { #check-it }
|
||||
|
||||
Se você abrir os documentos da API, você pode antenticar e especificar quais escopos você quer autorizar.
|
||||
Se você abrir os documentos da API, você pode autenticar e especificar quais escopos você quer autorizar.
|
||||
|
||||
<img src="/img/tutorial/security/image11.png">
|
||||
|
||||
|
|
@ -245,9 +245,9 @@ E se você selecionar o escopo `me`, mas não o escopo `items`, você poderá ac
|
|||
|
||||
Isso é o que aconteceria se uma aplicação terceira que tentou acessar uma dessas *operações de rota* com um token fornecido por um usuário, dependendo de quantas permissões o usuário forneceu para a aplicação.
|
||||
|
||||
## Sobre integrações de terceiros
|
||||
## Sobre integrações de terceiros { #about-third-party-integrations }
|
||||
|
||||
Neste exemplos nós estamos utilizando o fluxo de senha do OAuth2.
|
||||
Neste exemplo nós estamos utilizando o fluxo de senha do OAuth2.
|
||||
|
||||
Isso é apropriado quando nós estamos autenticando em nossa própria aplicação, provavelmente com o nosso próprio "*frontend*".
|
||||
|
||||
|
|
@ -269,6 +269,6 @@ Mas no final, eles estão implementando o mesmo padrão OAuth2.
|
|||
|
||||
O **FastAPI** inclui utilitários para todos esses fluxos de autenticação OAuth2 em `fastapi.security.oauth2`.
|
||||
|
||||
## `Security` em docoradores de `dependências`
|
||||
## `Security` em decoradores de `dependencies` { #security-in-decorator-dependencies }
|
||||
|
||||
Da mesma forma que você pode definir uma `list` de `Depends` no parâmetro de `dependencias` do decorador (como explicado em [Dependências em decoradores de operações de rota](../../tutorial/dependencies/dependencies-in-path-operation-decorators.md){.internal-link target=_blank}), você também pode utilizar `Security` com escopos lá.
|
||||
Da mesma forma que você pode definir uma `list` de `Depends` no parâmetro `dependencies` do decorador (como explicado em [Dependências em decoradores de operações de rota](../../tutorial/dependencies/dependencies-in-path-operation-decorators.md){.internal-link target=_blank}), você também pode utilizar `Security` com escopos lá.
|
||||
|
|
|
|||
|
|
@ -1,148 +1,30 @@
|
|||
# Configurações e Variáveis de Ambiente
|
||||
# Configurações e Variáveis de Ambiente { #settings-and-environment-variables }
|
||||
|
||||
Em muitos casos a sua aplicação pode precisar de configurações externas, como chaves secretas, credenciais de banco de dados, credenciais para serviços de email, etc.
|
||||
Em muitos casos, sua aplicação pode precisar de configurações externas, por exemplo chaves secretas, credenciais de banco de dados, credenciais para serviços de e-mail, etc.
|
||||
|
||||
A maioria dessas configurações é variável (podem mudar), como URLs de bancos de dados. E muitas delas podem conter dados sensíveis, como tokens secretos.
|
||||
A maioria dessas configurações é variável (pode mudar), como URLs de banco de dados. E muitas podem ser sensíveis, como segredos.
|
||||
|
||||
Por isso é comum prover essas configurações como variáveis de ambiente que são utilizidas pela aplicação.
|
||||
|
||||
## Variáveis de Ambiente
|
||||
Por esse motivo, é comum fornecê-las em variáveis de ambiente lidas pela aplicação.
|
||||
|
||||
/// tip | Dica
|
||||
|
||||
Se você já sabe o que são variáveis de ambiente e como utilizá-las, sinta-se livre para avançar para o próximo tópico.
|
||||
Para entender variáveis de ambiente, você pode ler [Variáveis de Ambiente](../environment-variables.md){.internal-link target=_blank}.
|
||||
|
||||
///
|
||||
|
||||
Uma <a href="https://pt.wikipedia.org/wiki/Variável_de_ambiente" class="external-link" target="_blank">variável de ambiente</a> (abreviada em inglês para "env var") é uma variável definida fora do código Python, no sistema operacional, e pode ser lida pelo seu código Python (ou por outros programas).
|
||||
## Tipagem e validação { #types-and-validation }
|
||||
|
||||
Você pode criar e utilizar variáveis de ambiente no terminal, sem precisar utilizar Python:
|
||||
Essas variáveis de ambiente só conseguem lidar com strings de texto, pois são externas ao Python e precisam ser compatíveis com outros programas e com o resto do sistema (e até com diferentes sistemas operacionais, como Linux, Windows, macOS).
|
||||
|
||||
//// tab | Linux, macOS, Windows Bash
|
||||
Isso significa que qualquer valor lido em Python a partir de uma variável de ambiente será uma `str`, e qualquer conversão para um tipo diferente ou validação precisa ser feita em código.
|
||||
|
||||
<div class="termy">
|
||||
## Pydantic `Settings` { #pydantic-settings }
|
||||
|
||||
```console
|
||||
// Você pode criar uma env var MY_NAME usando
|
||||
$ export MY_NAME="Wade Wilson"
|
||||
Felizmente, o Pydantic fornece uma ótima utilidade para lidar com essas configurações vindas de variáveis de ambiente com <a href="https://docs.pydantic.dev/latest/concepts/pydantic_settings/" class="external-link" target="_blank">Pydantic: Settings management</a>.
|
||||
|
||||
// E utilizá-la em outros programas, como
|
||||
$ echo "Hello $MY_NAME"
|
||||
### Instalar `pydantic-settings` { #install-pydantic-settings }
|
||||
|
||||
Hello Wade Wilson
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
////
|
||||
|
||||
//// tab | Windows PowerShell
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
// Criando env var MY_NAME
|
||||
$ $Env:MY_NAME = "Wade Wilson"
|
||||
|
||||
// Usando em outros programas, como
|
||||
$ echo "Hello $Env:MY_NAME"
|
||||
|
||||
Hello Wade Wilson
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
////
|
||||
|
||||
### Lendo variáveis de ambiente com Python
|
||||
|
||||
Você também pode criar variáveis de ambiente fora do Python, no terminal (ou com qualquer outro método), e realizar a leitura delas no Python.
|
||||
|
||||
Por exemplo, você pode definir um arquivo `main.py` com o seguinte código:
|
||||
|
||||
```Python hl_lines="3"
|
||||
import os
|
||||
|
||||
name = os.getenv("MY_NAME", "World")
|
||||
print(f"Hello {name} from Python")
|
||||
```
|
||||
|
||||
/// tip | Dica
|
||||
|
||||
O segundo parâmetro em <a href="https://docs.python.org/3.8/library/os.html#os.getenv" class="external-link" target="_blank">`os.getenv()`</a> é o valor padrão para o retorno.
|
||||
|
||||
Se nenhum valor for informado, `None` é utilizado por padrão, aqui definimos `"World"` como o valor padrão a ser utilizado.
|
||||
|
||||
///
|
||||
|
||||
E depois você pode executar esse arquivo:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
// Aqui ainda não definimos a env var
|
||||
$ python main.py
|
||||
|
||||
// Por isso obtemos o valor padrão
|
||||
|
||||
Hello World from Python
|
||||
|
||||
// Mas se definirmos uma variável de ambiente primeiro
|
||||
$ export MY_NAME="Wade Wilson"
|
||||
|
||||
// E executarmos o programa novamente
|
||||
$ python main.py
|
||||
|
||||
// Agora ele pode ler a variável de ambiente
|
||||
|
||||
Hello Wade Wilson from Python
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
Como variáveis de ambiente podem ser definidas fora do código da aplicação, mas acessadas pela aplicação, e não precisam ser armazenadas (versionadas com `git`) junto dos outros arquivos, é comum utilizá-las para guardar configurações.
|
||||
|
||||
Você também pode criar uma variável de ambiente específica para uma invocação de um programa, que é acessível somente para esse programa, e somente enquanto ele estiver executando.
|
||||
|
||||
Para fazer isso, crie a variável imediatamente antes de iniciar o programa, na mesma linha:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
// Criando uma env var MY_NAME na mesma linha da execução do programa
|
||||
$ MY_NAME="Wade Wilson" python main.py
|
||||
|
||||
// Agora a aplicação consegue ler a variável de ambiente
|
||||
|
||||
Hello Wade Wilson from Python
|
||||
|
||||
// E a variável deixa de existir após isso
|
||||
$ python main.py
|
||||
|
||||
Hello World from Python
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
/// tip | Dica
|
||||
|
||||
Você pode ler mais sobre isso em: <a href="https://12factor.net/pt_br/config" class="external-link" target="_blank">The Twelve-Factor App: Configurações</a>.
|
||||
|
||||
///
|
||||
|
||||
### Tipagem e Validação
|
||||
|
||||
Essas variáveis de ambiente suportam apenas strings, por serem externas ao Python e por que precisam ser compatíveis com outros programas e o resto do sistema (e até mesmo com outros sistemas operacionais, como Linux, Windows e macOS).
|
||||
|
||||
Isso significa que qualquer valor obtido de uma variável de ambiente em Python terá o tipo `str`, e qualquer conversão para um tipo diferente ou validação deve ser realizada no código.
|
||||
|
||||
## Pydantic `Settings`
|
||||
|
||||
Por sorte, o Pydantic possui uma funcionalidade para lidar com essas configurações vindas de variáveis de ambiente utilizando <a href="https://docs.pydantic.dev/latest/usage/pydantic_settings/" class="external-link" target="_blank">Pydantic: Settings management</a>.
|
||||
|
||||
### Instalando `pydantic-settings`
|
||||
|
||||
Primeiro, instale o pacote `pydantic-settings`:
|
||||
Primeiro, certifique-se de criar seu [ambiente virtual](../virtual-environments.md){.internal-link target=_blank}, ativá-lo e então instalar o pacote `pydantic-settings`:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
|
|
@ -153,7 +35,7 @@ $ pip install pydantic-settings
|
|||
|
||||
</div>
|
||||
|
||||
Ele também está incluído no fastapi quando você instala com a opção `all`:
|
||||
Ele também vem incluído quando você instala os extras `all` com:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
|
|
@ -164,19 +46,19 @@ $ pip install "fastapi[all]"
|
|||
|
||||
</div>
|
||||
|
||||
/// info
|
||||
/// info | Informação
|
||||
|
||||
Na v1 do Pydantic ele estava incluído no pacote principal. Agora ele está distribuido como um pacote independente para que você possa optar por instalar ou não caso você não precise dessa funcionalidade.
|
||||
No Pydantic v1 ele vinha incluído no pacote principal. Agora é distribuído como um pacote independente para que você possa optar por instalá-lo ou não, caso não precise dessa funcionalidade.
|
||||
|
||||
///
|
||||
|
||||
### Criando o objeto `Settings`
|
||||
### Criar o objeto `Settings` { #create-the-settings-object }
|
||||
|
||||
Importe a classe `BaseSettings` do Pydantic e crie uma nova subclasse, de forma parecida com um modelo do Pydantic.
|
||||
Importe `BaseSettings` do Pydantic e crie uma subclasse, muito parecido com um modelo do Pydantic.
|
||||
|
||||
Os atributos da classe são declarados com anotações de tipo, e possíveis valores padrão, da mesma maneira que os modelos do Pydantic.
|
||||
Da mesma forma que com modelos do Pydantic, você declara atributos de classe com anotações de tipo e, possivelmente, valores padrão.
|
||||
|
||||
Você pode utilizar todas as ferramentas e funcionalidades de validação que são utilizadas nos modelos do Pydantic, como tipos de dados diferentes e validações adicionei com `Field()`.
|
||||
Você pode usar as mesmas funcionalidades e ferramentas de validação que usa em modelos do Pydantic, como diferentes tipos de dados e validações adicionais com `Field()`.
|
||||
|
||||
//// tab | Pydantic v2
|
||||
|
||||
|
|
@ -186,9 +68,9 @@ Você pode utilizar todas as ferramentas e funcionalidades de validação que s
|
|||
|
||||
//// tab | Pydantic v1
|
||||
|
||||
/// info
|
||||
/// info | Informação
|
||||
|
||||
Na versão 1 do Pydantic você importaria `BaseSettings` diretamente do módulo `pydantic` em vez do módulo `pydantic_settings`.
|
||||
No Pydantic v1 você importaria `BaseSettings` diretamente de `pydantic` em vez de `pydantic_settings`.
|
||||
|
||||
///
|
||||
|
||||
|
|
@ -198,23 +80,23 @@ Na versão 1 do Pydantic você importaria `BaseSettings` diretamente do módulo
|
|||
|
||||
/// tip | Dica
|
||||
|
||||
Se você quiser algo pronto para copiar e colar na sua aplicação, não use esse exemplo, mas sim o exemplo abaixo.
|
||||
Se você quer algo rápido para copiar e colar, não use este exemplo, use o último abaixo.
|
||||
|
||||
///
|
||||
|
||||
Portanto, quando você cria uma instância da classe `Settings` (nesse caso, o objeto `settings`), o Pydantic lê as variáveis de ambiente sem diferenciar maiúsculas e minúsculas, por isso, uma variável maiúscula `APP_NAME` será usada para o atributo `app_name`.
|
||||
Então, quando você cria uma instância dessa classe `Settings` (neste caso, no objeto `settings`), o Pydantic vai ler as variáveis de ambiente sem diferenciar maiúsculas de minúsculas; assim, uma variável em maiúsculas `APP_NAME` ainda será lida para o atributo `app_name`.
|
||||
|
||||
Depois ele irá converter e validar os dados. Assim, quando você utilizar aquele objeto `settings`, os dados terão o tipo que você declarou (e.g. `items_per_user` será do tipo `int`).
|
||||
Em seguida, ele converterá e validará os dados. Assim, quando você usar esse objeto `settings`, terá dados dos tipos que declarou (por exemplo, `items_per_user` será um `int`).
|
||||
|
||||
### Usando o objeto `settings`
|
||||
### Usar o `settings` { #use-the-settings }
|
||||
|
||||
Depois, Você pode utilizar o novo objeto `settings` na sua aplicação:
|
||||
Depois você pode usar o novo objeto `settings` na sua aplicação:
|
||||
|
||||
{* ../../docs_src/settings/tutorial001.py hl[18:20] *}
|
||||
|
||||
### Executando o servidor
|
||||
### Executar o servidor { #run-the-server }
|
||||
|
||||
No próximo passo, você pode inicializar o servidor passando as configurações em forma de variáveis de ambiente, por exemplo, você poderia definir `ADMIN_EMAIL` e `APP_NAME` da seguinte forma:
|
||||
Em seguida, você executaria o servidor passando as configurações como variáveis de ambiente, por exemplo, você poderia definir `ADMIN_EMAIL` e `APP_NAME` com:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
|
|
@ -228,110 +110,110 @@ $ ADMIN_EMAIL="deadpool@example.com" APP_NAME="ChimichangApp" fastapi run main.p
|
|||
|
||||
/// tip | Dica
|
||||
|
||||
Para definir múltiplas variáveis de ambiente para um único comando basta separá-las utilizando espaços, e incluir todas elas antes do comando.
|
||||
Para definir várias variáveis de ambiente para um único comando, basta separá-las com espaço e colocá-las todas antes do comando.
|
||||
|
||||
///
|
||||
|
||||
Assim, o atributo `admin_email` seria definido como `"deadpool@example.com"`.
|
||||
Então a configuração `admin_email` seria definida como `"deadpool@example.com"`.
|
||||
|
||||
`app_name` seria `"ChimichangApp"`.
|
||||
O `app_name` seria `"ChimichangApp"`.
|
||||
|
||||
E `items_per_user` manteria o valor padrão de `50`.
|
||||
E `items_per_user` manteria seu valor padrão de `50`.
|
||||
|
||||
## Configurações em um módulo separado
|
||||
## Configurações em outro módulo { #settings-in-another-module }
|
||||
|
||||
Você também pode incluir essas configurações em um arquivo de um módulo separado como visto em [Bigger Applications - Multiple Files](../tutorial/bigger-applications.md){.internal-link target=\_blank}.
|
||||
Você pode colocar essas configurações em outro arquivo de módulo como visto em [Aplicações Maiores - Múltiplos Arquivos](../tutorial/bigger-applications.md){.internal-link target=_blank}.
|
||||
|
||||
Por exemplo, você pode adicionar um arquivo `config.py` com:
|
||||
Por exemplo, você poderia ter um arquivo `config.py` com:
|
||||
|
||||
{* ../../docs_src/settings/app01/config.py *}
|
||||
|
||||
E utilizar essa configuração em `main.py`:
|
||||
E então usá-lo em um arquivo `main.py`:
|
||||
|
||||
{* ../../docs_src/settings/app01/main.py hl[3,11:13] *}
|
||||
|
||||
/// tip | Dica
|
||||
|
||||
Você também precisa incluir um arquivo `__init__.py` como visto em [Bigger Applications - Multiple Files](../tutorial/bigger-applications.md){.internal-link target=\_blank}.
|
||||
Você também precisaria de um arquivo `__init__.py` como visto em [Aplicações Maiores - Múltiplos Arquivos](../tutorial/bigger-applications.md){.internal-link target=_blank}.
|
||||
|
||||
///
|
||||
|
||||
## Configurações em uma dependência
|
||||
## Configurações em uma dependência { #settings-in-a-dependency }
|
||||
|
||||
Em certas ocasiões, pode ser útil fornecer essas configurações a partir de uma dependência, em vez de definir um objeto global `settings` que é utilizado em toda a aplicação.
|
||||
Em algumas ocasiões, pode ser útil fornecer as configurações a partir de uma dependência, em vez de ter um objeto global `settings` usado em todos os lugares.
|
||||
|
||||
Isso é especialmente útil durante os testes, já que é bastante simples sobrescrever uma dependência com suas configurações personalizadas.
|
||||
Isso pode ser especialmente útil durante os testes, pois é muito fácil sobrescrever uma dependência com suas próprias configurações personalizadas.
|
||||
|
||||
### O arquivo de configuração
|
||||
### O arquivo de configuração { #the-config-file }
|
||||
|
||||
Baseando-se no exemplo anterior, seu arquivo `config.py` seria parecido com isso:
|
||||
Vindo do exemplo anterior, seu arquivo `config.py` poderia ser assim:
|
||||
|
||||
{* ../../docs_src/settings/app02/config.py hl[10] *}
|
||||
|
||||
Perceba que dessa vez não criamos uma instância padrão `settings = Settings()`.
|
||||
Perceba que agora não criamos uma instância padrão `settings = Settings()`.
|
||||
|
||||
### O arquivo principal da aplicação
|
||||
### O arquivo principal da aplicação { #the-main-app-file }
|
||||
|
||||
Agora criamos a dependência que retorna um novo objeto `config.Settings()`.
|
||||
Agora criamos uma dependência que retorna um novo `config.Settings()`.
|
||||
|
||||
{* ../../docs_src/settings/app02_an_py39/main.py hl[6,12:13] *}
|
||||
|
||||
/// tip | Dica
|
||||
|
||||
Vamos discutir sobre `@lru_cache` logo mais.
|
||||
Vamos discutir o `@lru_cache` em breve.
|
||||
|
||||
Por enquanto, você pode considerar `get_settings()` como uma função normal.
|
||||
Por enquanto, você pode assumir que `get_settings()` é uma função normal.
|
||||
|
||||
///
|
||||
|
||||
E então podemos declarar essas configurações como uma dependência na função de operação da rota e utilizar onde for necessário.
|
||||
E então podemos exigi-la na *função de operação de rota* como dependência e usá-la onde for necessário.
|
||||
|
||||
{* ../../docs_src/settings/app02_an_py39/main.py hl[17,19:21] *}
|
||||
|
||||
### Configurações e testes
|
||||
### Configurações e testes { #settings-and-testing }
|
||||
|
||||
Então seria muito fácil fornecer uma configuração diferente durante a execução dos testes sobrescrevendo a dependência de `get_settings`:
|
||||
Então seria muito fácil fornecer um objeto de configurações diferente durante os testes criando uma sobrescrita de dependência para `get_settings`:
|
||||
|
||||
{* ../../docs_src/settings/app02/test_main.py hl[9:10,13,21] *}
|
||||
|
||||
Na sobrescrita da dependência, definimos um novo valor para `admin_email` quando instanciamos um novo objeto `Settings`, e então retornamos esse novo objeto.
|
||||
Na sobrescrita da dependência definimos um novo valor para `admin_email` ao criar o novo objeto `Settings`, e então retornamos esse novo objeto.
|
||||
|
||||
Após isso, podemos testar se o valor está sendo utilizado.
|
||||
Depois podemos testar que ele é usado.
|
||||
|
||||
## Lendo um arquivo `.env`
|
||||
## Lendo um arquivo `.env` { #reading-a-env-file }
|
||||
|
||||
Se você tiver muitas configurações que variem bastante, talvez em ambientes distintos, pode ser útil colocá-las em um arquivo e depois lê-las como se fossem variáveis de ambiente.
|
||||
Se você tiver muitas configurações que possivelmente mudam bastante, talvez em diferentes ambientes, pode ser útil colocá-las em um arquivo e então lê-las como se fossem variáveis de ambiente.
|
||||
|
||||
Essa prática é tão comum que possui um nome, essas variáveis de ambiente normalmente são colocadas em um arquivo `.env`, e esse arquivo é chamado de "dotenv".
|
||||
Essa prática é tão comum que tem um nome: essas variáveis de ambiente são comumente colocadas em um arquivo `.env`, e o arquivo é chamado de "dotenv".
|
||||
|
||||
/// tip | Dica
|
||||
|
||||
Um arquivo iniciando com um ponto final (`.`) é um arquivo oculto em sistemas baseados em Unix, como Linux e MacOS.
|
||||
Um arquivo começando com um ponto (`.`) é um arquivo oculto em sistemas tipo Unix, como Linux e macOS.
|
||||
|
||||
Mas um arquivo dotenv não precisa ter esse nome exato.
|
||||
Mas um arquivo dotenv não precisa ter exatamente esse nome de arquivo.
|
||||
|
||||
///
|
||||
|
||||
Pydantic suporta a leitura desses tipos de arquivos utilizando uma biblioteca externa. Você pode ler mais em <a href="https://docs.pydantic.dev/latest/concepts/pydantic_settings/#dotenv-env-support" class="external-link" target="_blank">Pydantic Settings: Dotenv (.env) support</a>.
|
||||
O Pydantic tem suporte para leitura desses tipos de arquivos usando uma biblioteca externa. Você pode ler mais em <a href="https://docs.pydantic.dev/latest/concepts/pydantic_settings/#dotenv-env-support" class="external-link" target="_blank">Pydantic Settings: Dotenv (.env) support</a>.
|
||||
|
||||
/// tip | Dica
|
||||
|
||||
Para que isso funcione você precisa executar `pip install python-dotenv`.
|
||||
Para isso funcionar, você precisa executar `pip install python-dotenv`.
|
||||
|
||||
///
|
||||
|
||||
### O arquivo `.env`
|
||||
### O arquivo `.env` { #the-env-file }
|
||||
|
||||
Você pode definir um arquivo `.env` com o seguinte conteúdo:
|
||||
Você poderia ter um arquivo `.env` com:
|
||||
|
||||
```bash
|
||||
ADMIN_EMAIL="deadpool@example.com"
|
||||
APP_NAME="ChimichangApp"
|
||||
```
|
||||
|
||||
### Obtendo configurações do `.env`
|
||||
### Ler configurações do `.env` { #read-settings-from-env }
|
||||
|
||||
E então adicionar o seguinte código em `config.py`:
|
||||
E então atualizar seu `config.py` com:
|
||||
|
||||
//// tab | Pydantic v2
|
||||
|
||||
|
|
@ -339,7 +221,7 @@ E então adicionar o seguinte código em `config.py`:
|
|||
|
||||
/// tip | Dica
|
||||
|
||||
O atributo `model_config` é usado apenas para configuração do Pydantic. Você pode ler mais em <a href="https://docs.pydantic.dev/latest/usage/model_config/" class="external-link" target="_blank">Pydantic Model Config</a>.
|
||||
O atributo `model_config` é usado apenas para configuração do Pydantic. Você pode ler mais em <a href="https://docs.pydantic.dev/latest/concepts/config/" class="external-link" target="_blank">Pydantic: Concepts: Configuration</a>.
|
||||
|
||||
///
|
||||
|
||||
|
|
@ -357,48 +239,48 @@ A classe `Config` é usada apenas para configuração do Pydantic. Você pode le
|
|||
|
||||
////
|
||||
|
||||
/// info
|
||||
/// info | Informação
|
||||
|
||||
Na versão 1 do Pydantic a configuração é realizada por uma classe interna `Config`, na versão 2 do Pydantic isso é feito com o atributo `model_config`. Esse atributo recebe um `dict`, para utilizar o autocomplete e checagem de erros do seu editor de texto você pode importar e utilizar `SettingsConfigDict` para definir esse `dict`.
|
||||
Na versão 1 do Pydantic a configuração era feita em uma classe interna `Config`, na versão 2 do Pydantic é feita em um atributo `model_config`. Esse atributo recebe um `dict`, e para ter autocompletar e erros inline você pode importar e usar `SettingsConfigDict` para definir esse `dict`.
|
||||
|
||||
///
|
||||
|
||||
Aqui definimos a configuração `env_file` dentro da classe `Settings` do Pydantic, e definimos o valor como o nome do arquivo dotenv que queremos utilizar.
|
||||
Aqui definimos a configuração `env_file` dentro da sua classe `Settings` do Pydantic e definimos o valor como o nome do arquivo dotenv que queremos usar.
|
||||
|
||||
### Declarando `Settings` apenas uma vez com `lru_cache`
|
||||
### Criando o `Settings` apenas uma vez com `lru_cache` { #creating-the-settings-only-once-with-lru-cache }
|
||||
|
||||
Ler o conteúdo de um arquivo em disco normalmente é uma operação custosa (lenta), então você provavelmente quer fazer isso apenas um vez e reutilizar o mesmo objeto settings depois, em vez de ler os valores a cada requisição.
|
||||
Ler um arquivo do disco normalmente é uma operação custosa (lenta), então você provavelmente vai querer fazer isso apenas uma vez e depois reutilizar o mesmo objeto de configurações, em vez de lê-lo a cada requisição.
|
||||
|
||||
Mas cada vez que fazemos:
|
||||
Mas toda vez que fizermos:
|
||||
|
||||
```Python
|
||||
Settings()
|
||||
```
|
||||
|
||||
um novo objeto `Settings` é instanciado, e durante a instanciação, o arquivo `.env` é lido novamente.
|
||||
um novo objeto `Settings` seria criado e, na criação, ele leria o arquivo `.env` novamente.
|
||||
|
||||
Se a função da dependência fosse apenas:
|
||||
Se a função de dependência fosse assim:
|
||||
|
||||
```Python
|
||||
def get_settings():
|
||||
return Settings()
|
||||
```
|
||||
|
||||
Iriamos criar um novo objeto a cada requisição, e estaríamos lendo o arquivo `.env` a cada requisição. ⚠️
|
||||
criaríamos esse objeto para cada requisição e leríamos o arquivo `.env` para cada requisição. ⚠️
|
||||
|
||||
Mas como estamos utilizando o decorador `@lru_cache` acima, o objeto `Settings` é criado apenas uma vez, na primeira vez que a função é chamada. ✔️
|
||||
Mas como estamos usando o decorador `@lru_cache` por cima, o objeto `Settings` será criado apenas uma vez, na primeira vez em que for chamado. ✔️
|
||||
|
||||
{* ../../docs_src/settings/app03_an_py39/main.py hl[1,11] *}
|
||||
|
||||
Dessa forma, todas as chamadas da função `get_settings()` nas dependências das próximas requisições, em vez de executar o código interno de `get_settings()` e instanciar um novo objeto `Settings`, irão retornar o mesmo objeto que foi retornado na primeira chamada, de novo e de novo.
|
||||
Em qualquer chamada subsequente de `get_settings()` nas dependências das próximas requisições, em vez de executar o código interno de `get_settings()` e criar um novo objeto `Settings`, ele retornará o mesmo objeto que foi retornado na primeira chamada, repetidamente.
|
||||
|
||||
#### Detalhes Técnicos de `lru_cache`
|
||||
#### Detalhes Técnicos do `lru_cache` { #lru-cache-technical-details }
|
||||
|
||||
`@lru_cache` modifica a função decorada para retornar o mesmo valor que foi retornado na primeira vez, em vez de calculá-lo novamente, executando o código da função toda vez.
|
||||
`@lru_cache` modifica a função que decora para retornar o mesmo valor que foi retornado na primeira vez, em vez de calculá-lo novamente executando o código da função todas as vezes.
|
||||
|
||||
Assim, a função abaixo do decorador é executada uma única vez para cada combinação dos argumentos passados. E os valores retornados para cada combinação de argumentos são sempre reutilizados para cada nova chamada da função com a mesma combinação de argumentos.
|
||||
Assim, a função abaixo dele será executada uma vez para cada combinação de argumentos. E então os valores retornados para cada uma dessas combinações de argumentos serão usados repetidamente sempre que a função for chamada com exatamente a mesma combinação de argumentos.
|
||||
|
||||
Por exemplo, se você definir uma função:
|
||||
Por exemplo, se você tiver uma função:
|
||||
|
||||
```Python
|
||||
@lru_cache
|
||||
|
|
@ -406,59 +288,59 @@ def say_hi(name: str, salutation: str = "Ms."):
|
|||
return f"Hello {salutation} {name}"
|
||||
```
|
||||
|
||||
Seu programa poderia executar dessa forma:
|
||||
seu programa poderia executar assim:
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
|
||||
participant code as Código
|
||||
participant code as Code
|
||||
participant function as say_hi()
|
||||
participant execute as Executar Função
|
||||
participant execute as Execute function
|
||||
|
||||
rect rgba(0, 255, 0, .1)
|
||||
code ->> function: say_hi(name="Camila")
|
||||
function ->> execute: executar código da função
|
||||
execute ->> code: retornar o resultado
|
||||
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: retornar resultado armazenado
|
||||
function ->> code: return stored result
|
||||
end
|
||||
|
||||
rect rgba(0, 255, 0, .1)
|
||||
code ->> function: say_hi(name="Rick")
|
||||
function ->> execute: executar código da função
|
||||
execute ->> code: retornar o resultado
|
||||
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: executar código da função
|
||||
execute ->> code: retornar o resultado
|
||||
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: retornar resultado armazenado
|
||||
function ->> code: return stored result
|
||||
end
|
||||
|
||||
rect rgba(0, 255, 255, .1)
|
||||
code ->> function: say_hi(name="Camila")
|
||||
function ->> code: retornar resultado armazenado
|
||||
function ->> code: return stored result
|
||||
end
|
||||
```
|
||||
|
||||
No caso da nossa dependência `get_settings()`, a função não recebe nenhum argumento, então ela sempre retorna o mesmo valor.
|
||||
No caso da nossa dependência `get_settings()`, a função nem recebe argumentos, então ela sempre retorna o mesmo valor.
|
||||
|
||||
Dessa forma, ela se comporta praticamente como uma variável global, mas ao ser utilizada como uma função de uma dependência, pode facilmente ser sobrescrita durante os testes.
|
||||
Dessa forma, ela se comporta quase como se fosse apenas uma variável global. Mas como usa uma função de dependência, podemos sobrescrevê-la facilmente para testes.
|
||||
|
||||
`@lru_cache` é definido no módulo `functools` que faz parte da biblioteca padrão do Python, você pode ler mais sobre esse decorador no link <a href="https://docs.python.org/3/library/functools.html#functools.lru_cache" class="external-link" target="_blank">Python Docs sobre `@lru_cache`</a>.
|
||||
`@lru_cache` faz parte de `functools`, que faz parte da biblioteca padrão do Python; você pode ler mais sobre isso na <a href="https://docs.python.org/3/library/functools.html#functools.lru_cache" class="external-link" target="_blank">documentação do Python para `@lru_cache`</a>.
|
||||
|
||||
## Recapitulando
|
||||
## Recapitulando { #recap }
|
||||
|
||||
Você pode usar o módulo Pydantic Settings para gerenciar as configurações de sua aplicação, utilizando todo o poder dos modelos Pydantic.
|
||||
Você pode usar Pydantic Settings para lidar com as configurações da sua aplicação, com todo o poder dos modelos Pydantic.
|
||||
|
||||
- Utilizar dependências simplifica os testes.
|
||||
- Você pode utilizar arquivos .env junto das configurações do Pydantic.
|
||||
- Utilizar o decorador `@lru_cache` evita que o arquivo .env seja lido de novo e de novo para cada requisição, enquanto permite que você sobrescreva durante os testes.
|
||||
* Usando uma dependência você pode simplificar os testes.
|
||||
* Você pode usar arquivos `.env` com ele.
|
||||
* Usar `@lru_cache` permite evitar ler o arquivo dotenv repetidamente a cada requisição, enquanto permite sobrescrevê-lo durante os testes.
|
||||
|
|
|
|||
|
|
@ -1,41 +1,41 @@
|
|||
# Sub Aplicações - Montagens
|
||||
# Sub Aplicações - Montagens { #sub-applications-mounts }
|
||||
|
||||
Se você precisar ter duas aplicações FastAPI independentes, cada uma com seu próprio OpenAPI e suas próprias interfaces de documentação, você pode ter um aplicativo principal e "montar" uma (ou mais) sub-aplicações.
|
||||
|
||||
## Montando uma aplicação **FastAPI**
|
||||
## Montando uma aplicação **FastAPI** { #mounting-a-fastapi-application }
|
||||
|
||||
"Montar" significa adicionar uma aplicação completamente "independente" em um caminho específico, que então se encarrega de lidar com tudo sob esse caminho, com as operações de rota declaradas nessa sub-aplicação.
|
||||
"Montar" significa adicionar uma aplicação completamente "independente" em um path específico, que então se encarrega de lidar com tudo sob esse path, com as _operações de rota_ declaradas nessa sub-aplicação.
|
||||
|
||||
### Aplicação de nível superior
|
||||
### Aplicação de nível superior { #top-level-application }
|
||||
|
||||
Primeiro, crie a aplicação principal, de nível superior, **FastAPI**, e suas *operações de rota*:
|
||||
|
||||
{* ../../docs_src/sub_applications/tutorial001.py hl[3,6:8] *}
|
||||
{* ../../docs_src/sub_applications/tutorial001.py hl[3, 6:8] *}
|
||||
|
||||
### Sub-aplicação
|
||||
### Sub-aplicação { #sub-application }
|
||||
|
||||
Em seguida, crie sua sub-aplicação e suas *operações de rota*.
|
||||
|
||||
Essa sub-aplicação é apenas outra aplicação FastAPI padrão, mas esta é a que será "montada":
|
||||
|
||||
{* ../../docs_src/sub_applications/tutorial001.py hl[11,14:16] *}
|
||||
{* ../../docs_src/sub_applications/tutorial001.py hl[11, 14:16] *}
|
||||
|
||||
### Monte a sub-aplicação
|
||||
### Monte a sub-aplicação { #mount-the-sub-application }
|
||||
|
||||
Na sua aplicação de nível superior, `app`, monte a sub-aplicação, `subapi`.
|
||||
|
||||
Neste caso, ela será montada no caminho `/subapi`:
|
||||
Neste caso, ela será montada no path `/subapi`:
|
||||
|
||||
{* ../../docs_src/sub_applications/tutorial001.py hl[11,19] *}
|
||||
{* ../../docs_src/sub_applications/tutorial001.py hl[11, 19] *}
|
||||
|
||||
### Verifique a documentação automática da API
|
||||
### Verifique a documentação automática da API { #check-the-automatic-api-docs }
|
||||
|
||||
Agora, execute `uvicorn` com a aplicação principal, se o seu arquivo for `main.py`, seria:
|
||||
Agora, execute o comando `fastapi` com o seu arquivo:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ uvicorn main:app --reload
|
||||
$ fastapi dev main.py
|
||||
|
||||
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
|
||||
```
|
||||
|
|
@ -50,17 +50,17 @@ Você verá a documentação automática da API para a aplicação principal, in
|
|||
|
||||
E então, abra a documentação para a sub-aplicação, em <a href="http://127.0.0.1:8000/subapi/docs" class="external-link" target="_blank">http://127.0.0.1:8000/subapi/docs</a>.
|
||||
|
||||
Você verá a documentação automática da API para a sub-aplicação, incluindo apenas suas próprias _operações de rota_, todas sob o prefixo de sub-caminho correto `/subapi`:
|
||||
Você verá a documentação automática da API para a sub-aplicação, incluindo apenas suas próprias _operações de rota_, todas sob o prefixo de sub-path correto `/subapi`:
|
||||
|
||||
<img src="/img/tutorial/sub-applications/image02.png">
|
||||
|
||||
Se você tentar interagir com qualquer uma das duas interfaces de usuário, elas funcionarão corretamente, porque o navegador será capaz de se comunicar com cada aplicação ou sub-aplicação específica.
|
||||
|
||||
### Detalhes Técnicos: `root_path`
|
||||
### Detalhes Técnicos: `root_path` { #technical-details-root-path }
|
||||
|
||||
Quando você monta uma sub-aplicação como descrito acima, o FastAPI se encarrega de comunicar o caminho de montagem para a sub-aplicação usando um mecanismo da especificação ASGI chamado `root_path`.
|
||||
Quando você monta uma sub-aplicação como descrito acima, o FastAPI se encarrega de comunicar o path de montagem para a sub-aplicação usando um mecanismo da especificação ASGI chamado `root_path`.
|
||||
|
||||
Dessa forma, a sub-aplicação saberá usar esse prefixo de caminho para a interface de documentação.
|
||||
Dessa forma, a sub-aplicação saberá usar esse prefixo de path para a interface de documentação.
|
||||
|
||||
E a sub-aplicação também poderia ter suas próprias sub-aplicações montadas e tudo funcionaria corretamente, porque o FastAPI lida com todos esses `root_path`s automaticamente.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
# Templates
|
||||
# Templates { #templates }
|
||||
|
||||
Você pode usar qualquer template engine com o **FastAPI**.
|
||||
|
||||
|
|
@ -6,28 +6,30 @@ Uma escolha comum é o Jinja2, o mesmo usado pelo Flask e outras ferramentas.
|
|||
|
||||
Existem utilitários para configurá-lo facilmente que você pode usar diretamente em sua aplicação **FastAPI** (fornecidos pelo Starlette).
|
||||
|
||||
## Instalação de dependências
|
||||
## Instalar dependências { #install-dependencies }
|
||||
|
||||
Para instalar o `jinja2`, siga o código abaixo:
|
||||
Certifique-se de criar um [ambiente virtual](../virtual-environments.md){.internal-link target=_blank}, ativá-lo e instalar `jinja2`:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ pip install jinja2
|
||||
|
||||
---> 100%
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
## Usando `Jinja2Templates`
|
||||
## Usando `Jinja2Templates` { #using-jinja2templates }
|
||||
|
||||
* Importe `Jinja2Templates`.
|
||||
* Crie um `templates` que você possa reutilizar posteriormente.
|
||||
* Crie um objeto `templates` que você possa reutilizar posteriormente.
|
||||
* Declare um parâmetro `Request` no *path operation* que retornará um template.
|
||||
* Use o `template` que você criou para renderizar e retornar uma `TemplateResponse`, passe o nome do template, o request object, e um "context" dict com pares chave-valor a serem usados dentro do template do Jinja2.
|
||||
* Use o `templates` que você criou para renderizar e retornar uma `TemplateResponse`, passe o nome do template, o objeto `request` e um dicionário "context" com pares chave-valor a serem usados dentro do template do Jinja2.
|
||||
|
||||
{* ../../docs_src/templates/tutorial001.py hl[4,11,15:18] *}
|
||||
|
||||
/// note
|
||||
/// note | Nota
|
||||
|
||||
Antes do FastAPI 0.108.0, Starlette 0.29.0, `name` era o primeiro parâmetro.
|
||||
|
||||
|
|
@ -49,7 +51,7 @@ Você também poderia usar `from starlette.templating import Jinja2Templates`.
|
|||
|
||||
///
|
||||
|
||||
## Escrevendo Templates
|
||||
## Escrevendo templates { #writing-templates }
|
||||
|
||||
Então você pode escrever um template em `templates/item.html`, por exemplo:
|
||||
|
||||
|
|
@ -57,7 +59,7 @@ Então você pode escrever um template em `templates/item.html`, por exemplo:
|
|||
{!../../docs_src/templates/templates/item.html!}
|
||||
```
|
||||
|
||||
### Interpolação de Valores no Template
|
||||
### Valores de contexto do template { #template-context-values }
|
||||
|
||||
No código HTML que contém:
|
||||
|
||||
|
|
@ -81,7 +83,7 @@ Por exemplo, dado um ID de valor `42`, aparecerá:
|
|||
Item ID: 42
|
||||
```
|
||||
|
||||
### Argumentos do `url_for`
|
||||
### Argumentos do `url_for` no template { #template-url-for-arguments }
|
||||
|
||||
Você também pode usar `url_for()` dentro do template, ele recebe como argumentos os mesmos argumentos que seriam usados pela sua *path operation function*.
|
||||
|
||||
|
|
@ -103,9 +105,9 @@ Por exemplo, com um ID de `42`, isso renderizará:
|
|||
<a href="/items/42">
|
||||
```
|
||||
|
||||
## Templates e Arquivos Estáticos
|
||||
## Templates e arquivos estáticos { #templates-and-static-files }
|
||||
|
||||
Você também pode usar `url_for()` dentro do template e usá-lo, por examplo, com o `StaticFiles` que você montou com o `name="static"`.
|
||||
Você também pode usar `url_for()` dentro do template e usá-lo, por exemplo, com o `StaticFiles` que você montou com o `name="static"`.
|
||||
|
||||
```jinja hl_lines="4"
|
||||
{!../../docs_src/templates/templates/item.html!}
|
||||
|
|
@ -117,8 +119,8 @@ Neste exemplo, ele seria vinculado a um arquivo CSS em `static/styles.css` com:
|
|||
{!../../docs_src/templates/static/styles.css!}
|
||||
```
|
||||
|
||||
E como você está usando `StaticFiles`, este arquivo CSS será automaticamente servido pela sua aplicação FastAPI na URL `/static/styles.css`.
|
||||
E como você está usando `StaticFiles`, este arquivo CSS será automaticamente servido pela sua aplicação **FastAPI** na URL `/static/styles.css`.
|
||||
|
||||
## Mais detalhes
|
||||
## Mais detalhes { #more-details }
|
||||
|
||||
Para obter mais detalhes, incluindo como testar templates, consulte a <a href="https://www.starlette.dev/templates/" class="external-link" target="_blank">documentação da Starlette sobre templates</a>.
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# Testando Dependências com Sobreposição (Overrides)
|
||||
# Testando Dependências com Sobreposições { #testing-dependencies-with-overrides }
|
||||
|
||||
## Sobrepondo dependências durante os testes
|
||||
## Sobrepondo dependências durante os testes { #overriding-dependencies-during-testing }
|
||||
|
||||
Existem alguns cenários onde você deseje sobrepor uma dependência durante os testes.
|
||||
|
||||
|
|
@ -8,7 +8,7 @@ Você não quer que a dependência original execute (e nenhuma das subdependênc
|
|||
|
||||
Em vez disso, você deseja fornecer uma dependência diferente que será usada somente durante os testes (possivelmente apenas para alguns testes específicos) e fornecerá um valor que pode ser usado onde o valor da dependência original foi usado.
|
||||
|
||||
### Casos de uso: serviço externo
|
||||
### Casos de uso: serviço externo { #use-cases-external-service }
|
||||
|
||||
Um exemplo pode ser que você possua um provedor de autenticação externo que você precisa chamar.
|
||||
|
||||
|
|
@ -20,7 +20,7 @@ Você provavelmente quer testar o provedor externo uma vez, mas não necessariam
|
|||
|
||||
Neste caso, você pode sobrepor (*override*) a dependência que chama o provedor, e utilizar uma dependência customizada que retorna um *mock* do usuário, apenas para os seus testes.
|
||||
|
||||
### Utilize o atributo `app.dependency_overrides`
|
||||
### Utilize o atributo `app.dependency_overrides` { #use-the-app-dependency-overrides-attribute }
|
||||
|
||||
Para estes casos, a sua aplicação **FastAPI** possui o atributo `app.dependency_overrides`. Ele é um simples `dict`.
|
||||
|
||||
|
|
@ -34,7 +34,7 @@ E então o **FastAPI** chamará a sobreposição no lugar da dependência origin
|
|||
|
||||
Você pode definir uma sobreposição de dependência para uma dependência que é utilizada em qualquer lugar da sua aplicação **FastAPI**.
|
||||
|
||||
A dependência original pode estar sendo utilizada em uma *função de operação de rota*, um *docorador de operação de rota* (quando você não utiliza o valor retornado), uma chamada ao `.include_router()`, etc.
|
||||
A dependência original pode estar sendo utilizada em uma *função de operação de rota*, um *decorador de operação de rota* (quando você não utiliza o valor retornado), uma chamada ao `.include_router()`, etc.
|
||||
|
||||
O FastAPI ainda poderá sobrescrevê-lo.
|
||||
|
||||
|
|
@ -48,6 +48,6 @@ app.dependency_overrides = {}
|
|||
|
||||
/// tip | Dica
|
||||
|
||||
Se você quer sobrepor uma dependência apenas para alguns testes, você pode definir a sobreposição no início do testes (dentro da função de teste) e reiniciá-la ao final (no final da função de teste).
|
||||
Se você quer sobrepor uma dependência apenas para alguns testes, você pode definir a sobreposição no início do teste (dentro da função de teste) e reiniciá-la ao final (no final da função de teste).
|
||||
|
||||
///
|
||||
|
|
|
|||
|
|
@ -1,5 +1,11 @@
|
|||
# Testando Eventos: inicialização - encerramento
|
||||
# Testando eventos: lifespan e inicialização - encerramento { #testing-events-lifespan-and-startup-shutdown }
|
||||
|
||||
Quando você precisa que os seus manipuladores de eventos (`startup` e `shutdown`) sejam executados em seus testes, você pode utilizar o `TestClient` usando a instrução `with`:
|
||||
Quando você precisa que o `lifespan` seja executado em seus testes, você pode utilizar o `TestClient` com a instrução `with`:
|
||||
|
||||
{* ../../docs_src/app_testing/tutorial004.py hl[9:15,18,27:28,30:32,41:43] *}
|
||||
|
||||
Você pode ler mais detalhes sobre o ["Executando lifespan em testes no site oficial da documentação do Starlette."](https://www.starlette.dev/lifespan/#running-lifespan-in-tests)
|
||||
|
||||
Para os eventos `startup` e `shutdown` descontinuados, você pode usar o `TestClient` da seguinte forma:
|
||||
|
||||
{* ../../docs_src/app_testing/tutorial003.py hl[9:12,20:24] *}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
# Testando WebSockets
|
||||
# Testando WebSockets { #testing-websockets }
|
||||
|
||||
Você pode usar o mesmo `TestClient` para testar WebSockets.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
# Utilizando o Request diretamente
|
||||
# Utilizando o Request diretamente { #using-the-request-directly }
|
||||
|
||||
Até agora você declarou as partes da requisição que você precisa utilizando os seus tipos.
|
||||
|
||||
Obtendo dados de:
|
||||
|
||||
* Os parâmetros das rotas.
|
||||
* O path como parâmetros.
|
||||
* Cabeçalhos (*Headers*).
|
||||
* Cookies.
|
||||
* etc.
|
||||
|
|
@ -13,7 +13,7 @@ E ao fazer isso, o **FastAPI** está validando as informações, convertendo-as
|
|||
|
||||
Porém há situações em que você possa precisar acessar o objeto `Request` diretamente.
|
||||
|
||||
## Detalhes sobre o objeto `Request`
|
||||
## Detalhes sobre o objeto `Request` { #details-about-the-request-object }
|
||||
|
||||
Como o **FastAPI** é na verdade o **Starlette** por baixo, com camadas de diversas funcionalidades por cima, você pode utilizar o objeto <a href="https://www.starlette.dev/requests/" class="external-link" target="_blank">`Request`</a> do Starlette diretamente quando precisar.
|
||||
|
||||
|
|
@ -23,7 +23,7 @@ Embora qualquer outro parâmetro declarado normalmente (o corpo da requisição
|
|||
|
||||
Mas há situações específicas onde é útil utilizar o objeto `Request`.
|
||||
|
||||
## Utilize o objeto `Request` diretamente
|
||||
## Utilize o objeto `Request` diretamente { #use-the-request-object-directly }
|
||||
|
||||
Vamos imaginar que você deseja obter o endereço de IP/host do cliente dentro da sua *função de operação de rota*.
|
||||
|
||||
|
|
@ -35,15 +35,15 @@ Ao declarar o parâmetro com o tipo sendo um `Request` em sua *função de opera
|
|||
|
||||
/// tip | Dica
|
||||
|
||||
Note que neste caso, nós estamos declarando o parâmetro da rota ao lado do parâmetro da requisição.
|
||||
Note que neste caso, nós estamos declarando o parâmetro de path ao lado do parâmetro da requisição.
|
||||
|
||||
Assim, o parâmetro da rota será extraído, validado, convertido para o tipo especificado e anotado com OpenAPI.
|
||||
Assim, o parâmetro de path será extraído, validado, convertido para o tipo especificado e anotado com OpenAPI.
|
||||
|
||||
Do mesmo jeito, você pode declarar qualquer outro parâmetro normalmente, e além disso, obter o `Request` também.
|
||||
|
||||
///
|
||||
|
||||
## Documentação do `Request`
|
||||
## Documentação do `Request` { #request-documentation }
|
||||
|
||||
Você pode ler mais sobre os detalhes do objeto <a href="https://www.starlette.dev/requests/" class="external-link" target="_blank">`Request` no site da documentação oficial do Starlette.</a>.
|
||||
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue