mirror of
https://github.com/fastapi/fastapi.git
synced 2025-12-26 15:51:02 -05:00
Compare commits
142 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
31887b1cc6 | ||
|
|
b270ff1e5e | ||
|
|
b31cbbf5f5 | ||
|
|
aee7674ed2 | ||
|
|
4e6b1acccd | ||
|
|
9b1e5f29e6 | ||
|
|
60aba0261c | ||
|
|
2a4cf1736d | ||
|
|
453f559934 | ||
|
|
af269cd131 | ||
|
|
5e8f1f96eb | ||
|
|
9f44a5dd36 | ||
|
|
ba77d114f6 | ||
|
|
cd37dfe533 | ||
|
|
47b4e1a517 | ||
|
|
503ece76d6 | ||
|
|
5a0e13794b | ||
|
|
75af54babd | ||
|
|
083fbc8a73 | ||
|
|
3783341eb8 | ||
|
|
f0ad433e01 | ||
|
|
5b1963db49 | ||
|
|
5d99a42688 | ||
|
|
f5a10c1c7d | ||
|
|
fe60afff0e | ||
|
|
dc7cf0f14f | ||
|
|
9106cae8a8 | ||
|
|
dc22bdf5a4 | ||
|
|
0f8d03ef85 | ||
|
|
55aa76faad | ||
|
|
ed45eca1a8 | ||
|
|
b24b4fd6a8 | ||
|
|
dfdecfd9c9 | ||
|
|
4b9e76bde2 | ||
|
|
27e7fcefe8 | ||
|
|
48f88edf0d | ||
|
|
91eb00854b | ||
|
|
e00efb5569 | ||
|
|
909204ec54 | ||
|
|
b87eb8a0e1 | ||
|
|
92bc3d7e0c | ||
|
|
13f3dd2111 | ||
|
|
4f5349445d | ||
|
|
4ae5fab050 | ||
|
|
1fbbf9ca6c | ||
|
|
a1572b52de | ||
|
|
50c6f80117 | ||
|
|
aec5219fe0 | ||
|
|
092da9a8a3 | ||
|
|
128c96dc9a | ||
|
|
8d928def2e | ||
|
|
44cfb2f4f5 | ||
|
|
162a32cc2f | ||
|
|
d93e431505 | ||
|
|
28e97b2651 | ||
|
|
6e85909311 | ||
|
|
68d0a0412e | ||
|
|
63c3eacf43 | ||
|
|
442692fef4 | ||
|
|
56bc9a5eb4 | ||
|
|
71fcafd13c | ||
|
|
ea88ab6cf1 | ||
|
|
89f06da526 | ||
|
|
d60c52bc32 | ||
|
|
fd95b4ae65 | ||
|
|
a498582bb4 | ||
|
|
55bcab6d75 | ||
|
|
548f938280 | ||
|
|
ec9b066e0b | ||
|
|
cf65c423d1 | ||
|
|
e2d77a9e42 | ||
|
|
86fe251507 | ||
|
|
b5021a4c84 | ||
|
|
ff5f076011 | ||
|
|
b144221ad5 | ||
|
|
7b03fa7e0c | ||
|
|
2f2c877d51 | ||
|
|
6ede04f876 | ||
|
|
e7533b92b3 | ||
|
|
593385d1c3 | ||
|
|
8081d2302e | ||
|
|
2d43a8a2a3 | ||
|
|
21fc89976d | ||
|
|
59efc69bec | ||
|
|
136c48bda6 | ||
|
|
fb4b6b7cbe | ||
|
|
c9337b54f0 | ||
|
|
69cc3161fc | ||
|
|
13c57834a5 | ||
|
|
92df4e7903 | ||
|
|
c1f91a0403 | ||
|
|
180e72b193 | ||
|
|
d5a0456084 | ||
|
|
396c0f6aab | ||
|
|
bbcee4db19 | ||
|
|
cb74448bd9 | ||
|
|
94fafa5030 | ||
|
|
c519614b45 | ||
|
|
9c794c9c0d | ||
|
|
c4f8143dea | ||
|
|
45822d31f2 | ||
|
|
4c1a1938bc | ||
|
|
5afa6d7066 | ||
|
|
f0b5f8adf7 | ||
|
|
b0761c2552 | ||
|
|
53d90074e5 | ||
|
|
7038bedc5d | ||
|
|
48849f8a11 | ||
|
|
b7fb8eb656 | ||
|
|
ac3c2dd965 | ||
|
|
febf6b6a52 | ||
|
|
71f2be2387 | ||
|
|
50639525bf | ||
|
|
80ba3fc5db | ||
|
|
d7942aea2d | ||
|
|
12c188b311 | ||
|
|
9b09974cfc | ||
|
|
0507458504 | ||
|
|
be03a7313e | ||
|
|
111ced53af | ||
|
|
d63f0d60ba | ||
|
|
4d8d092925 | ||
|
|
33cd8bbcc5 | ||
|
|
73546a68e6 | ||
|
|
c9f11c2b73 | ||
|
|
e58c185526 | ||
|
|
923d44de35 | ||
|
|
7148584ac4 | ||
|
|
38f65c033f | ||
|
|
5f998ee55a | ||
|
|
7358ed246e | ||
|
|
d4e183da3f | ||
|
|
0e4dc88bd7 | ||
|
|
b887d434db | ||
|
|
766a14ddff | ||
|
|
6384f730f7 | ||
|
|
84ef149f83 | ||
|
|
495d90161b | ||
|
|
ac6c08c71f | ||
|
|
a30eb6f517 | ||
|
|
3347f0dde5 | ||
|
|
91672fb9ed |
40
.github/workflows/build-docs.yml
vendored
40
.github/workflows/build-docs.yml
vendored
@@ -7,6 +7,10 @@ on:
|
||||
types:
|
||||
- opened
|
||||
- synchronize
|
||||
|
||||
env:
|
||||
UV_SYSTEM_PYTHON: 1
|
||||
|
||||
jobs:
|
||||
changes:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -48,18 +52,20 @@ jobs:
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "3.11"
|
||||
- uses: actions/cache@v4
|
||||
id: cache
|
||||
- name: Setup uv
|
||||
uses: astral-sh/setup-uv@v3
|
||||
with:
|
||||
path: ${{ env.pythonLocation }}
|
||||
key: ${{ runner.os }}-python-docs-${{ env.pythonLocation }}-${{ hashFiles('pyproject.toml', 'requirements-docs.txt', 'requirements-docs-insiders.txt', 'requirements-docs-tests.txt') }}-v08
|
||||
version: "0.4.15"
|
||||
enable-cache: true
|
||||
cache-dependency-glob: |
|
||||
requirements**.txt
|
||||
pyproject.toml
|
||||
- name: Install docs extras
|
||||
if: steps.cache.outputs.cache-hit != 'true'
|
||||
run: pip install -r requirements-docs.txt
|
||||
run: uv pip install -r requirements-docs.txt
|
||||
# Install MkDocs Material Insiders here just to put it in the cache for the rest of the steps
|
||||
- name: Install Material for MkDocs Insiders
|
||||
if: ( github.event_name != 'pull_request' || github.secret_source == 'Actions' ) && steps.cache.outputs.cache-hit != 'true'
|
||||
run: pip install -r requirements-docs-insiders.txt
|
||||
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
|
||||
@@ -88,17 +94,19 @@ jobs:
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "3.11"
|
||||
- uses: actions/cache@v4
|
||||
id: cache
|
||||
- name: Setup uv
|
||||
uses: astral-sh/setup-uv@v3
|
||||
with:
|
||||
path: ${{ env.pythonLocation }}
|
||||
key: ${{ runner.os }}-python-docs-${{ env.pythonLocation }}-${{ hashFiles('pyproject.toml', 'requirements-docs.txt', 'requirements-docs-insiders.txt', 'requirements-docs-tests.txt') }}-v08
|
||||
version: "0.4.15"
|
||||
enable-cache: true
|
||||
cache-dependency-glob: |
|
||||
requirements**.txt
|
||||
pyproject.toml
|
||||
- name: Install docs extras
|
||||
if: steps.cache.outputs.cache-hit != 'true'
|
||||
run: pip install -r requirements-docs.txt
|
||||
run: uv pip install -r requirements-docs.txt
|
||||
- name: Install Material for MkDocs Insiders
|
||||
if: ( github.event_name != 'pull_request' || github.secret_source == 'Actions' ) && steps.cache.outputs.cache-hit != 'true'
|
||||
run: pip install -r requirements-docs-insiders.txt
|
||||
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
|
||||
|
||||
23
.github/workflows/deploy-docs.yml
vendored
23
.github/workflows/deploy-docs.yml
vendored
@@ -12,6 +12,9 @@ permissions:
|
||||
pull-requests: write
|
||||
statuses: write
|
||||
|
||||
env:
|
||||
UV_SYSTEM_PYTHON: 1
|
||||
|
||||
jobs:
|
||||
deploy-docs:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -25,21 +28,22 @@ jobs:
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "3.11"
|
||||
- uses: actions/cache@v4
|
||||
id: cache
|
||||
- name: Setup uv
|
||||
uses: astral-sh/setup-uv@v3
|
||||
with:
|
||||
path: ${{ env.pythonLocation }}
|
||||
key: ${{ runner.os }}-python-github-actions-${{ env.pythonLocation }}-${{ hashFiles('requirements-github-actions.txt') }}-v01
|
||||
version: "0.4.15"
|
||||
enable-cache: true
|
||||
cache-dependency-glob: |
|
||||
requirements**.txt
|
||||
pyproject.toml
|
||||
- name: Install GitHub Actions dependencies
|
||||
if: steps.cache.outputs.cache-hit != 'true'
|
||||
run: pip install -r requirements-github-actions.txt
|
||||
run: uv pip install -r requirements-github-actions.txt
|
||||
- name: Deploy Docs Status Pending
|
||||
run: python ./scripts/deploy_docs_status.py
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
COMMIT_SHA: ${{ github.event.workflow_run.head_sha }}
|
||||
RUN_ID: ${{ github.run_id }}
|
||||
|
||||
- name: Clean site
|
||||
run: |
|
||||
rm -rf ./site
|
||||
@@ -58,7 +62,10 @@ jobs:
|
||||
env:
|
||||
PROJECT_NAME: fastapitiangolo
|
||||
BRANCH: ${{ ( github.event.workflow_run.head_repository.full_name == github.repository && github.event.workflow_run.head_branch == 'master' && 'main' ) || ( github.event.workflow_run.head_sha ) }}
|
||||
uses: cloudflare/wrangler-action@v3
|
||||
# TODO: Use v3 when it's fixed, probably in v3.11
|
||||
# https://github.com/cloudflare/wrangler-action/issues/307
|
||||
uses: cloudflare/wrangler-action@v3.11
|
||||
# uses: cloudflare/wrangler-action@v3
|
||||
with:
|
||||
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
|
||||
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
|
||||
|
||||
4
.github/workflows/issue-manager.yml
vendored
4
.github/workflows/issue-manager.yml
vendored
@@ -39,5 +39,9 @@ jobs:
|
||||
"waiting": {
|
||||
"delay": 2628000,
|
||||
"message": "As this PR has been waiting for the original user for a while but seems to be inactive, it's now going to be closed. But if there's anyone interested, feel free to create a new PR."
|
||||
},
|
||||
"invalid": {
|
||||
"delay": 0,
|
||||
"message": "This was marked as invalid and will be closed now. If this is an error, please provide additional details."
|
||||
}
|
||||
}
|
||||
|
||||
25
.github/workflows/label-approved.yml
vendored
25
.github/workflows/label-approved.yml
vendored
@@ -8,6 +8,9 @@ on:
|
||||
permissions:
|
||||
pull-requests: write
|
||||
|
||||
env:
|
||||
UV_SYSTEM_PYTHON: 1
|
||||
|
||||
jobs:
|
||||
label-approved:
|
||||
if: github.repository_owner == 'fastapi'
|
||||
@@ -17,10 +20,26 @@ jobs:
|
||||
env:
|
||||
GITHUB_CONTEXT: ${{ toJson(github) }}
|
||||
run: echo "$GITHUB_CONTEXT"
|
||||
- uses: docker://tiangolo/label-approved:0.0.4
|
||||
- uses: actions/checkout@v4
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
config: >
|
||||
python-version: "3.11"
|
||||
- name: Setup uv
|
||||
uses: astral-sh/setup-uv@v3
|
||||
with:
|
||||
version: "0.4.15"
|
||||
enable-cache: true
|
||||
cache-dependency-glob: |
|
||||
requirements**.txt
|
||||
pyproject.toml
|
||||
- name: Install GitHub Actions dependencies
|
||||
run: uv pip install -r requirements-github-actions.txt
|
||||
- name: Label Approved
|
||||
run: python ./scripts/label_approved.py
|
||||
env:
|
||||
TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
CONFIG: >
|
||||
{
|
||||
"approved-1":
|
||||
{
|
||||
|
||||
16
.github/workflows/notify-translations.yml
vendored
16
.github/workflows/notify-translations.yml
vendored
@@ -18,6 +18,9 @@ on:
|
||||
permissions:
|
||||
discussions: write
|
||||
|
||||
env:
|
||||
UV_SYSTEM_PYTHON: 1
|
||||
|
||||
jobs:
|
||||
notify-translations:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -27,6 +30,19 @@ jobs:
|
||||
GITHUB_CONTEXT: ${{ toJson(github) }}
|
||||
run: echo "$GITHUB_CONTEXT"
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v4
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "3.11"
|
||||
- name: Setup uv
|
||||
uses: astral-sh/setup-uv@v3
|
||||
with:
|
||||
version: "0.4.15"
|
||||
enable-cache: true
|
||||
cache-dependency-glob: |
|
||||
requirements**.txt
|
||||
pyproject.toml
|
||||
# Allow debugging with tmate
|
||||
- name: Setup tmate session
|
||||
uses: mxschmitt/action-tmate@v3
|
||||
|
||||
17
.github/workflows/smokeshow.yml
vendored
17
.github/workflows/smokeshow.yml
vendored
@@ -8,6 +8,9 @@ on:
|
||||
permissions:
|
||||
statuses: write
|
||||
|
||||
env:
|
||||
UV_SYSTEM_PYTHON: 1
|
||||
|
||||
jobs:
|
||||
smokeshow:
|
||||
if: ${{ github.event.workflow_run.conclusion == 'success' }}
|
||||
@@ -18,19 +21,25 @@ jobs:
|
||||
env:
|
||||
GITHUB_CONTEXT: ${{ toJson(github) }}
|
||||
run: echo "$GITHUB_CONTEXT"
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.9'
|
||||
|
||||
- run: pip install smokeshow
|
||||
|
||||
- name: Setup uv
|
||||
uses: astral-sh/setup-uv@v3
|
||||
with:
|
||||
version: "0.4.15"
|
||||
enable-cache: true
|
||||
cache-dependency-glob: |
|
||||
requirements**.txt
|
||||
pyproject.toml
|
||||
- run: uv pip install -r requirements-github-actions.txt
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: coverage-html
|
||||
path: htmlcov
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
run-id: ${{ github.event.workflow_run.id }}
|
||||
|
||||
- run: smokeshow upload htmlcov
|
||||
env:
|
||||
SMOKESHOW_GITHUB_STATUS_DESCRIPTION: Coverage {coverage-percentage}
|
||||
|
||||
57
.github/workflows/test.yml
vendored
57
.github/workflows/test.yml
vendored
@@ -12,6 +12,9 @@ on:
|
||||
# cron every week on monday
|
||||
- cron: "0 0 * * 1"
|
||||
|
||||
env:
|
||||
UV_SYSTEM_PYTHON: 1
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -25,19 +28,18 @@ jobs:
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "3.11"
|
||||
# Issue ref: https://github.com/actions/setup-python/issues/436
|
||||
# cache: "pip"
|
||||
# cache-dependency-path: pyproject.toml
|
||||
- uses: actions/cache@v4
|
||||
id: cache
|
||||
- name: Setup uv
|
||||
uses: astral-sh/setup-uv@v3
|
||||
with:
|
||||
path: ${{ env.pythonLocation }}
|
||||
key: ${{ runner.os }}-python-${{ env.pythonLocation }}-pydantic-v2-${{ hashFiles('pyproject.toml', 'requirements-tests.txt', 'requirements-docs-tests.txt') }}-test-v08
|
||||
version: "0.4.15"
|
||||
enable-cache: true
|
||||
cache-dependency-glob: |
|
||||
requirements**.txt
|
||||
pyproject.toml
|
||||
- name: Install Dependencies
|
||||
if: steps.cache.outputs.cache-hit != 'true'
|
||||
run: pip install -r requirements-tests.txt
|
||||
run: uv pip install -r requirements-tests.txt
|
||||
- name: Install Pydantic v2
|
||||
run: pip install --upgrade "pydantic>=2.0.2,<3.0.0"
|
||||
run: uv pip install --upgrade "pydantic>=2.0.2,<3.0.0"
|
||||
- name: Lint
|
||||
run: bash scripts/lint.sh
|
||||
|
||||
@@ -63,23 +65,22 @@ jobs:
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
# Issue ref: https://github.com/actions/setup-python/issues/436
|
||||
# cache: "pip"
|
||||
# cache-dependency-path: pyproject.toml
|
||||
- uses: actions/cache@v4
|
||||
id: cache
|
||||
- name: Setup uv
|
||||
uses: astral-sh/setup-uv@v3
|
||||
with:
|
||||
path: ${{ env.pythonLocation }}
|
||||
key: ${{ runner.os }}-python-${{ env.pythonLocation }}-${{ matrix.pydantic-version }}-${{ hashFiles('pyproject.toml', 'requirements-tests.txt', 'requirements-docs-tests.txt') }}-test-v08
|
||||
version: "0.4.15"
|
||||
enable-cache: true
|
||||
cache-dependency-glob: |
|
||||
requirements**.txt
|
||||
pyproject.toml
|
||||
- name: Install Dependencies
|
||||
if: steps.cache.outputs.cache-hit != 'true'
|
||||
run: pip install -r requirements-tests.txt
|
||||
run: uv pip install -r requirements-tests.txt
|
||||
- name: Install Pydantic v1
|
||||
if: matrix.pydantic-version == 'pydantic-v1'
|
||||
run: pip install "pydantic>=1.10.0,<2.0.0"
|
||||
run: uv pip install "pydantic>=1.10.0,<2.0.0"
|
||||
- name: Install Pydantic v2
|
||||
if: matrix.pydantic-version == 'pydantic-v2'
|
||||
run: pip install --upgrade "pydantic>=2.0.2,<3.0.0"
|
||||
run: uv pip install --upgrade "pydantic>=2.0.2,<3.0.0"
|
||||
- run: mkdir coverage
|
||||
- name: Test
|
||||
run: bash scripts/test.sh
|
||||
@@ -105,16 +106,22 @@ jobs:
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.8'
|
||||
# Issue ref: https://github.com/actions/setup-python/issues/436
|
||||
# cache: "pip"
|
||||
# cache-dependency-path: pyproject.toml
|
||||
- name: Setup uv
|
||||
uses: astral-sh/setup-uv@v3
|
||||
with:
|
||||
version: "0.4.15"
|
||||
enable-cache: true
|
||||
cache-dependency-glob: |
|
||||
requirements**.txt
|
||||
pyproject.toml
|
||||
- name: Install Dependencies
|
||||
run: uv pip install -r requirements-tests.txt
|
||||
- name: Get coverage files
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
pattern: coverage-*
|
||||
path: coverage
|
||||
merge-multiple: true
|
||||
- run: pip install coverage[toml]
|
||||
- run: ls -la coverage
|
||||
- run: coverage combine coverage
|
||||
- run: coverage report
|
||||
|
||||
@@ -14,7 +14,7 @@ repos:
|
||||
- id: end-of-file-fixer
|
||||
- id: trailing-whitespace
|
||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||
rev: v0.6.9
|
||||
rev: v0.7.0
|
||||
hooks:
|
||||
- id: ruff
|
||||
args:
|
||||
|
||||
@@ -95,7 +95,7 @@ The key features are:
|
||||
|
||||
"_Honestly, what you've built looks super solid and polished. In many ways, it's what I wanted **Hug** to be - it's really inspiring to see someone build that._"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Timothy Crosley - <strong><a href="https://www.hug.rest/" target="_blank">Hug</a> creator</strong> <a href="https://news.ycombinator.com/item?id=19455465" target="_blank"><small>(ref)</small></a></div>
|
||||
<div style="text-align: right; margin-right: 10%;">Timothy Crosley - <strong><a href="https://github.com/hugapi/hug" target="_blank">Hug</a> creator</strong> <a href="https://news.ycombinator.com/item?id=19455465" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -87,7 +87,7 @@ FastAPI Python ilə API yaratmaq üçün standart Python <abbr title="Tip Məsl
|
||||
|
||||
"_Düzünü desəm, sizin qurduğunuz şey həqiqətən möhkəm və peşəkar görünür. Bir çox cəhətdən **Hug**-un olmasını istədiyim kimdir - kiminsə belə bir şey qurduğunu görmək həqiqətən ruhlandırıcıdır._"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Timothy Crosley - <strong><a href="https://www.hug.rest/" target="_blank">Hug</a> creator</strong> <a href="https://news.ycombinator.com/item?id=19455465" target="_blank"><small>(ref)</small></a></div>
|
||||
<div style="text-align: right; margin-right: 10%;">Timothy Crosley - <strong><a href="https://github.com/hugapi/hug" target="_blank">Hug</a> creator</strong> <a href="https://news.ycombinator.com/item?id=19455465" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -85,7 +85,7 @@ FastAPI একটি আধুনিক, দ্রুত ( বেশি ক্
|
||||
|
||||
"\_সত্যিই, আপনি যা তৈরি করেছেন তা খুব মজবুত এবং পরিপূর্ন৷ অনেক উপায়ে, আমি যা **Hug** এ করতে চেয়েছিলাম - তা কাউকে তৈরি করতে দেখে আমি সত্যিই অনুপ্রানিত৷\_"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">টিমোথি ক্রসলে - <strong><a href="https://www.hug.rest/" target="_blank">Hug</a> স্রষ্টা</strong> <a href="https://news.ycombinator.com/item?id=19455465" target="_blank"><small>(ref)</small></a></div>
|
||||
<div style="text-align: right; margin-right: 10%;">টিমোথি ক্রসলে - <strong><a href="https://github.com/hugapi/hug" target="_blank">Hug</a> স্রষ্টা</strong> <a href="https://news.ycombinator.com/item?id=19455465" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -60,9 +60,7 @@ $ pytest
|
||||
|
||||
Der Marker `@pytest.mark.anyio` teilt pytest mit, dass diese Testfunktion asynchron aufgerufen werden soll:
|
||||
|
||||
```Python hl_lines="7"
|
||||
{!../../docs_src/async_tests/test_main.py!}
|
||||
```
|
||||
{* ../../docs_src/async_tests/test_main.py hl[7] *}
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
@@ -72,9 +70,7 @@ Beachten Sie, dass die Testfunktion jetzt `async def` ist und nicht nur `def` wi
|
||||
|
||||
Dann können wir einen `AsyncClient` mit der App erstellen und mit `await` asynchrone Requests an ihn senden.
|
||||
|
||||
```Python hl_lines="9-12"
|
||||
{!../../docs_src/async_tests/test_main.py!}
|
||||
```
|
||||
{* ../../docs_src/async_tests/test_main.py hl[9:12] *}
|
||||
|
||||
Das ist das Äquivalent zu:
|
||||
|
||||
|
||||
@@ -20,36 +20,7 @@ Wenn Sie dann den Benutzernamen und das Passwort eingeben, sendet der Browser di
|
||||
* Diese gibt ein Objekt vom Typ `HTTPBasicCredentials` zurück:
|
||||
* Es enthält den gesendeten `username` und das gesendete `password`.
|
||||
|
||||
//// tab | Python 3.9+
|
||||
|
||||
```Python hl_lines="4 8 12"
|
||||
{!> ../../docs_src/security/tutorial006_an_py39.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="2 7 11"
|
||||
{!> ../../docs_src/security/tutorial006_an.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+ nicht annotiert
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="2 6 10"
|
||||
{!> ../../docs_src/security/tutorial006.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
{* ../../docs_src/security/tutorial006_an_py39.py hl[4,8,12] *}
|
||||
Wenn Sie versuchen, die URL zum ersten Mal zu öffnen (oder in der Dokumentation auf den Button „Execute“ zu klicken), wird der Browser Sie nach Ihrem Benutzernamen und Passwort fragen:
|
||||
|
||||
<img src="/img/tutorial/security/image12.png">
|
||||
@@ -68,35 +39,7 @@ Um dies zu lösen, konvertieren wir zunächst den `username` und das `password`
|
||||
|
||||
Dann können wir `secrets.compare_digest()` verwenden, um sicherzustellen, dass `credentials.username` `"stanleyjobson"` und `credentials.password` `"swordfish"` ist.
|
||||
|
||||
//// tab | Python 3.9+
|
||||
|
||||
```Python hl_lines="1 12-24"
|
||||
{!> ../../docs_src/security/tutorial007_an_py39.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="1 12-24"
|
||||
{!> ../../docs_src/security/tutorial007_an.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+ nicht annotiert
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="1 11-21"
|
||||
{!> ../../docs_src/security/tutorial007.py!}
|
||||
```
|
||||
|
||||
////
|
||||
{* ../../docs_src/security/tutorial007_an_py39.py hl[1,12:24] *}
|
||||
|
||||
Dies wäre das gleiche wie:
|
||||
|
||||
@@ -160,32 +103,4 @@ So ist Ihr Anwendungscode, dank der Verwendung von `secrets.compare_digest()`, v
|
||||
|
||||
Nachdem Sie festgestellt haben, dass die Anmeldeinformationen falsch sind, geben Sie eine `HTTPException` mit dem Statuscode 401 zurück (derselbe, der auch zurückgegeben wird, wenn keine Anmeldeinformationen angegeben werden) und fügen den Header `WWW-Authenticate` hinzu, damit der Browser die Anmeldeaufforderung erneut anzeigt:
|
||||
|
||||
//// tab | Python 3.9+
|
||||
|
||||
```Python hl_lines="26-30"
|
||||
{!> ../../docs_src/security/tutorial007_an_py39.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="26-30"
|
||||
{!> ../../docs_src/security/tutorial007_an.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+ nicht annotiert
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="23-27"
|
||||
{!> ../../docs_src/security/tutorial007.py!}
|
||||
```
|
||||
|
||||
////
|
||||
{* ../../docs_src/security/tutorial007_an_py39.py hl[26:30] *}
|
||||
|
||||
@@ -321,7 +321,7 @@ Das hat tatsächlich dazu geführt, dass Teile von Pydantic aktualisiert wurden,
|
||||
|
||||
///
|
||||
|
||||
### <a href="https://www.hug.rest/" class="external-link" target="_blank">Hug</a>
|
||||
### <a href="https://github.com/hugapi/hug" class="external-link" target="_blank">Hug</a>
|
||||
|
||||
Hug war eines der ersten Frameworks, welches die Deklaration von API-Parametertypen mithilfe von Python-Typhinweisen implementierte. Das war eine großartige Idee, die andere Tools dazu inspirierte, dasselbe zu tun.
|
||||
|
||||
|
||||
@@ -94,7 +94,7 @@ Seine Schlüssel-Merkmale sind:
|
||||
|
||||
„_Ehrlich, was Du gebaut hast, sieht super solide und poliert aus. In vielerlei Hinsicht ist es so, wie ich **Hug** haben wollte – es ist wirklich inspirierend, jemanden so etwas bauen zu sehen._“
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Timothy Crosley - <strong>Autor von <a href="https://www.hug.rest/" target="_blank">Hug</a></strong> <a href="https://news.ycombinator.com/item?id=19455465" target="_blank"><small>(Ref)</small></a></div>
|
||||
<div style="text-align: right; margin-right: 10%;">Timothy Crosley - <strong>Autor von <a href="https://github.com/hugapi/hug" target="_blank">Hug</a></strong> <a href="https://news.ycombinator.com/item?id=19455465" target="_blank"><small>(Ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -8,9 +8,7 @@ So wie ein Responsemodell, können Sie auch einen HTTP-Statuscode für die Respo
|
||||
* `@app.delete()`
|
||||
* usw.
|
||||
|
||||
```Python hl_lines="6"
|
||||
{!../../docs_src/response_status_code/tutorial001.py!}
|
||||
```
|
||||
{* ../../docs_src/response_status_code/tutorial001.py hl[6] *}
|
||||
|
||||
/// note | "Hinweis"
|
||||
|
||||
@@ -76,9 +74,7 @@ Um mehr über Statuscodes zu lernen, und welcher wofür verwendet wird, lesen Si
|
||||
|
||||
Schauen wir uns das vorherige Beispiel noch einmal an:
|
||||
|
||||
```Python hl_lines="6"
|
||||
{!../../docs_src/response_status_code/tutorial001.py!}
|
||||
```
|
||||
{* ../../docs_src/response_status_code/tutorial001.py hl[6] *}
|
||||
|
||||
`201` ist der Statuscode für „Created“ („Erzeugt“).
|
||||
|
||||
@@ -86,9 +82,7 @@ Aber Sie müssen sich nicht daran erinnern, welcher dieser Codes was bedeutet.
|
||||
|
||||
Sie können die Hilfsvariablen von `fastapi.status` verwenden.
|
||||
|
||||
```Python hl_lines="1 6"
|
||||
{!../../docs_src/response_status_code/tutorial002.py!}
|
||||
```
|
||||
{* ../../docs_src/response_status_code/tutorial002.py hl[1,6] *}
|
||||
|
||||
Diese sind nur eine Annehmlichkeit und enthalten dieselbe Nummer, aber auf diese Weise können Sie die Autovervollständigung Ihres Editors verwenden, um sie zu finden:
|
||||
|
||||
|
||||
@@ -321,7 +321,7 @@ APISpec ✍ 🎏 🍭 👩💻.
|
||||
|
||||
///
|
||||
|
||||
### <a href="https://www.hug.rest/" class="external-link" target="_blank">🤗</a>
|
||||
### <a href="https://github.com/hugapi/hug" class="external-link" target="_blank">🤗</a>
|
||||
|
||||
🤗 🕐 🥇 🛠️ 🛠️ 📄 🛠️ 🔢 🆎 ⚙️ 🐍 🆎 🔑. 👉 👑 💭 👈 😮 🎏 🧰 🎏.
|
||||
|
||||
|
||||
@@ -93,7 +93,7 @@ FastAPI 🏛, ⏩ (↕-🎭), 🕸 🛠️ 🏗 🛠️ ⏮️ 🐍 3️⃣.8️
|
||||
|
||||
"_🤙, ⚫️❔ 👆 ✔️ 🏗 👀 💎 💠 & 🇵🇱. 📚 🌌, ⚫️ ⚫️❔ 👤 💚 **🤗** - ⚫️ 🤙 😍 👀 👱 🏗 👈._"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">✡ 🗄 - <strong><a href="https://www.hug.rest/" target="_blank">🤗</a> 👼</strong> <a href="https://news.ycombinator.com/item?id=19455465" target="_blank"><small>(🇦🇪)</small></a></div>
|
||||
<div style="text-align: right; margin-right: 10%;">✡ 🗄 - <strong><a href="https://github.com/hugapi/hug" target="_blank">🤗</a> 👼</strong> <a href="https://news.ycombinator.com/item?id=19455465" target="_blank"><small>(🇦🇪)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -339,6 +339,10 @@ Articles:
|
||||
link: https://qiita.com/mtitg/items/47770e9a562dd150631d
|
||||
title: FastAPI|DB接続してCRUDするPython製APIサーバーを構築
|
||||
Portuguese:
|
||||
- author: Eduardo Mendes
|
||||
author_link: https://bolha.us/@dunossauro
|
||||
link: https://fastapidozero.dunossauro.com/
|
||||
title: FastAPI do ZERO
|
||||
- author: Jessica Temporal
|
||||
author_link: https://jtemporal.com/socials
|
||||
link: https://jtemporal.com/dicas-para-migrar-de-flask-para-fastapi-e-vice-versa/
|
||||
|
||||
@@ -11,6 +11,9 @@ members:
|
||||
- login: svlandeg
|
||||
avatar_url: https://avatars.githubusercontent.com/u/8796347
|
||||
url: https://github.com/svlandeg
|
||||
- login: YuriiMotov
|
||||
avatar_url: https://avatars.githubusercontent.com/u/109919500
|
||||
url: https://github.com/YuriiMotov
|
||||
- login: estebanx64
|
||||
avatar_url: https://avatars.githubusercontent.com/u/10840422
|
||||
url: https://github.com/estebanx64
|
||||
|
||||
@@ -26,9 +26,7 @@ Each of those response `dict`s can have a key `model`, containing a Pydantic mod
|
||||
|
||||
For example, to declare another response with a status code `404` and a Pydantic model `Message`, you can write:
|
||||
|
||||
```Python hl_lines="18 22"
|
||||
{!../../docs_src/additional_responses/tutorial001.py!}
|
||||
```
|
||||
{* ../../docs_src/additional_responses/tutorial001.py hl[18,22] *}
|
||||
|
||||
/// note
|
||||
|
||||
@@ -177,9 +175,7 @@ You can use this same `responses` parameter to add different media types for the
|
||||
|
||||
For example, you can add an additional media type of `image/png`, declaring that your *path operation* can return a JSON object (with media type `application/json`) or a PNG image:
|
||||
|
||||
```Python hl_lines="19-24 28"
|
||||
{!../../docs_src/additional_responses/tutorial002.py!}
|
||||
```
|
||||
{* ../../docs_src/additional_responses/tutorial002.py hl[19:24,28] *}
|
||||
|
||||
/// note
|
||||
|
||||
@@ -207,9 +203,7 @@ For example, you can declare a response with a status code `404` that uses a Pyd
|
||||
|
||||
And a response with a status code `200` that uses your `response_model`, but includes a custom `example`:
|
||||
|
||||
```Python hl_lines="20-31"
|
||||
{!../../docs_src/additional_responses/tutorial003.py!}
|
||||
```
|
||||
{* ../../docs_src/additional_responses/tutorial003.py hl[20:31] *}
|
||||
|
||||
It will all be combined and included in your OpenAPI, and shown in the API docs:
|
||||
|
||||
@@ -243,9 +237,7 @@ You can use that technique to reuse some predefined responses in your *path oper
|
||||
|
||||
For example:
|
||||
|
||||
```Python hl_lines="13-17 26"
|
||||
{!../../docs_src/additional_responses/tutorial004.py!}
|
||||
```
|
||||
{* ../../docs_src/additional_responses/tutorial004.py hl[13:17,26] *}
|
||||
|
||||
## More information about OpenAPI responses
|
||||
|
||||
|
||||
@@ -14,57 +14,7 @@ But you also want it to accept new items. And when the items didn't exist before
|
||||
|
||||
To achieve that, import `JSONResponse`, and return your content there directly, setting the `status_code` that you want:
|
||||
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="4 25"
|
||||
{!> ../../docs_src/additional_status_codes/tutorial001_an_py310.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.9+
|
||||
|
||||
```Python hl_lines="4 25"
|
||||
{!> ../../docs_src/additional_status_codes/tutorial001_an_py39.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="4 26"
|
||||
{!> ../../docs_src/additional_status_codes/tutorial001_an.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.10+ non-Annotated
|
||||
|
||||
/// tip
|
||||
|
||||
Prefer to use the `Annotated` version if possible.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="2 23"
|
||||
{!> ../../docs_src/additional_status_codes/tutorial001_py310.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+ non-Annotated
|
||||
|
||||
/// tip
|
||||
|
||||
Prefer to use the `Annotated` version if possible.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="4 25"
|
||||
{!> ../../docs_src/additional_status_codes/tutorial001.py!}
|
||||
```
|
||||
|
||||
////
|
||||
{* ../../docs_src/additional_status_codes/tutorial001_an_py310.py hl[4,25] *}
|
||||
|
||||
/// warning
|
||||
|
||||
|
||||
@@ -18,35 +18,7 @@ Not the class itself (which is already a callable), but an instance of that clas
|
||||
|
||||
To do that, we declare a method `__call__`:
|
||||
|
||||
//// tab | Python 3.9+
|
||||
|
||||
```Python hl_lines="12"
|
||||
{!> ../../docs_src/dependencies/tutorial011_an_py39.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="11"
|
||||
{!> ../../docs_src/dependencies/tutorial011_an.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+ non-Annotated
|
||||
|
||||
/// tip
|
||||
|
||||
Prefer to use the `Annotated` version if possible.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="10"
|
||||
{!> ../../docs_src/dependencies/tutorial011.py!}
|
||||
```
|
||||
|
||||
////
|
||||
{* ../../docs_src/dependencies/tutorial011_an_py39.py hl[12] *}
|
||||
|
||||
In this case, this `__call__` is what **FastAPI** will use to check for additional parameters and sub-dependencies, and this is what will be called to pass a value to the parameter in your *path operation function* later.
|
||||
|
||||
@@ -54,35 +26,7 @@ In this case, this `__call__` is what **FastAPI** will use to check for addition
|
||||
|
||||
And now, we can use `__init__` to declare the parameters of the instance that we can use to "parameterize" the dependency:
|
||||
|
||||
//// tab | Python 3.9+
|
||||
|
||||
```Python hl_lines="9"
|
||||
{!> ../../docs_src/dependencies/tutorial011_an_py39.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="8"
|
||||
{!> ../../docs_src/dependencies/tutorial011_an.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+ non-Annotated
|
||||
|
||||
/// tip
|
||||
|
||||
Prefer to use the `Annotated` version if possible.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="7"
|
||||
{!> ../../docs_src/dependencies/tutorial011.py!}
|
||||
```
|
||||
|
||||
////
|
||||
{* ../../docs_src/dependencies/tutorial011_an_py39.py hl[9] *}
|
||||
|
||||
In this case, **FastAPI** won't ever touch or care about `__init__`, we will use it directly in our code.
|
||||
|
||||
@@ -90,35 +34,7 @@ In this case, **FastAPI** won't ever touch or care about `__init__`, we will use
|
||||
|
||||
We could create an instance of this class with:
|
||||
|
||||
//// tab | Python 3.9+
|
||||
|
||||
```Python hl_lines="18"
|
||||
{!> ../../docs_src/dependencies/tutorial011_an_py39.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="17"
|
||||
{!> ../../docs_src/dependencies/tutorial011_an.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+ non-Annotated
|
||||
|
||||
/// tip
|
||||
|
||||
Prefer to use the `Annotated` version if possible.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="16"
|
||||
{!> ../../docs_src/dependencies/tutorial011.py!}
|
||||
```
|
||||
|
||||
////
|
||||
{* ../../docs_src/dependencies/tutorial011_an_py39.py hl[18] *}
|
||||
|
||||
And that way we are able to "parameterize" our dependency, that now has `"bar"` inside of it, as the attribute `checker.fixed_content`.
|
||||
|
||||
@@ -134,35 +50,7 @@ checker(q="somequery")
|
||||
|
||||
...and pass whatever that returns as the value of the dependency in our *path operation function* as the parameter `fixed_content_included`:
|
||||
|
||||
//// tab | Python 3.9+
|
||||
|
||||
```Python hl_lines="22"
|
||||
{!> ../../docs_src/dependencies/tutorial011_an_py39.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="21"
|
||||
{!> ../../docs_src/dependencies/tutorial011_an.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+ non-Annotated
|
||||
|
||||
/// tip
|
||||
|
||||
Prefer to use the `Annotated` version if possible.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="20"
|
||||
{!> ../../docs_src/dependencies/tutorial011.py!}
|
||||
```
|
||||
|
||||
////
|
||||
{* ../../docs_src/dependencies/tutorial011_an_py39.py hl[22] *}
|
||||
|
||||
/// tip
|
||||
|
||||
|
||||
@@ -32,15 +32,11 @@ For a simple example, let's consider a file structure similar to the one describ
|
||||
|
||||
The file `main.py` would have:
|
||||
|
||||
```Python
|
||||
{!../../docs_src/async_tests/main.py!}
|
||||
```
|
||||
{* ../../docs_src/async_tests/main.py *}
|
||||
|
||||
The file `test_main.py` would have the tests for `main.py`, it could look like this now:
|
||||
|
||||
```Python
|
||||
{!../../docs_src/async_tests/test_main.py!}
|
||||
```
|
||||
{* ../../docs_src/async_tests/test_main.py *}
|
||||
|
||||
## Run it
|
||||
|
||||
@@ -60,9 +56,7 @@ $ pytest
|
||||
|
||||
The marker `@pytest.mark.anyio` tells pytest that this test function should be called asynchronously:
|
||||
|
||||
```Python hl_lines="7"
|
||||
{!../../docs_src/async_tests/test_main.py!}
|
||||
```
|
||||
{* ../../docs_src/async_tests/test_main.py hl[7] *}
|
||||
|
||||
/// tip
|
||||
|
||||
@@ -72,9 +66,7 @@ Note that the test function is now `async def` instead of just `def` as before w
|
||||
|
||||
Then we can create an `AsyncClient` with the app, and send async requests to it, using `await`.
|
||||
|
||||
```Python hl_lines="9-12"
|
||||
{!../../docs_src/async_tests/test_main.py!}
|
||||
```
|
||||
{* ../../docs_src/async_tests/test_main.py hl[9:12] *}
|
||||
|
||||
This is the equivalent to:
|
||||
|
||||
|
||||
@@ -18,9 +18,7 @@ In this case, the original path `/app` would actually be served at `/api/v1/app`
|
||||
|
||||
Even though all your code is written assuming there's just `/app`.
|
||||
|
||||
```Python hl_lines="6"
|
||||
{!../../docs_src/behind_a_proxy/tutorial001.py!}
|
||||
```
|
||||
{* ../../docs_src/behind_a_proxy/tutorial001.py hl[6] *}
|
||||
|
||||
And the proxy would be **"stripping"** the **path prefix** on the fly before transmitting the request to the app server (probably Uvicorn via FastAPI CLI), keeping your application convinced that it is being served at `/app`, so that you don't have to update all your code to include the prefix `/api/v1`.
|
||||
|
||||
@@ -98,9 +96,7 @@ You can get the current `root_path` used by your application for each request, i
|
||||
|
||||
Here we are including it in the message just for demonstration purposes.
|
||||
|
||||
```Python hl_lines="8"
|
||||
{!../../docs_src/behind_a_proxy/tutorial001.py!}
|
||||
```
|
||||
{* ../../docs_src/behind_a_proxy/tutorial001.py hl[8] *}
|
||||
|
||||
Then, if you start Uvicorn with:
|
||||
|
||||
@@ -127,9 +123,7 @@ The response would be something like:
|
||||
|
||||
Alternatively, if you don't have a way to provide a command line option like `--root-path` or equivalent, you can set the `root_path` parameter when creating your FastAPI app:
|
||||
|
||||
```Python hl_lines="3"
|
||||
{!../../docs_src/behind_a_proxy/tutorial002.py!}
|
||||
```
|
||||
{* ../../docs_src/behind_a_proxy/tutorial002.py hl[3] *}
|
||||
|
||||
Passing the `root_path` to `FastAPI` would be the equivalent of passing the `--root-path` command line option to Uvicorn or Hypercorn.
|
||||
|
||||
@@ -309,9 +303,7 @@ If you pass a custom list of `servers` and there's a `root_path` (because your A
|
||||
|
||||
For example:
|
||||
|
||||
```Python hl_lines="4-7"
|
||||
{!../../docs_src/behind_a_proxy/tutorial003.py!}
|
||||
```
|
||||
{* ../../docs_src/behind_a_proxy/tutorial003.py hl[4:7] *}
|
||||
|
||||
Will generate an OpenAPI schema like:
|
||||
|
||||
@@ -358,9 +350,7 @@ The docs UI will interact with the server that you select.
|
||||
|
||||
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`:
|
||||
|
||||
```Python hl_lines="9"
|
||||
{!../../docs_src/behind_a_proxy/tutorial004.py!}
|
||||
```
|
||||
{* ../../docs_src/behind_a_proxy/tutorial004.py hl[9] *}
|
||||
|
||||
and then it won't include it in the OpenAPI schema.
|
||||
|
||||
|
||||
@@ -57,17 +57,13 @@ Enforces that all incoming requests must either be `https` or `wss`.
|
||||
|
||||
Any incoming request to `http` or `ws` will be redirected to the secure scheme instead.
|
||||
|
||||
```Python hl_lines="2 6"
|
||||
{!../../docs_src/advanced_middleware/tutorial001.py!}
|
||||
```
|
||||
{* ../../docs_src/advanced_middleware/tutorial001.py hl[2,6] *}
|
||||
|
||||
## `TrustedHostMiddleware`
|
||||
|
||||
Enforces that all incoming requests have a correctly set `Host` header, in order to guard against HTTP Host Header attacks.
|
||||
|
||||
```Python hl_lines="2 6-8"
|
||||
{!../../docs_src/advanced_middleware/tutorial002.py!}
|
||||
```
|
||||
{* ../../docs_src/advanced_middleware/tutorial002.py hl[2,6:8] *}
|
||||
|
||||
The following arguments are supported:
|
||||
|
||||
@@ -81,9 +77,7 @@ Handles GZip responses for any request that includes `"gzip"` in the `Accept-Enc
|
||||
|
||||
The middleware will handle both standard and streaming responses.
|
||||
|
||||
```Python hl_lines="2 6"
|
||||
{!../../docs_src/advanced_middleware/tutorial003.py!}
|
||||
```
|
||||
{* ../../docs_src/advanced_middleware/tutorial003.py hl[2,6] *}
|
||||
|
||||
The following arguments are supported:
|
||||
|
||||
|
||||
@@ -20,35 +20,7 @@ Then, when you type that username and password, the browser sends them in the he
|
||||
* It returns an object of type `HTTPBasicCredentials`:
|
||||
* It contains the `username` and `password` sent.
|
||||
|
||||
//// tab | Python 3.9+
|
||||
|
||||
```Python hl_lines="4 8 12"
|
||||
{!> ../../docs_src/security/tutorial006_an_py39.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="2 7 11"
|
||||
{!> ../../docs_src/security/tutorial006_an.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+ non-Annotated
|
||||
|
||||
/// tip
|
||||
|
||||
Prefer to use the `Annotated` version if possible.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="2 6 10"
|
||||
{!> ../../docs_src/security/tutorial006.py!}
|
||||
```
|
||||
|
||||
////
|
||||
{* ../../docs_src/security/tutorial006_an_py39.py hl[4,8,12] *}
|
||||
|
||||
When you try to open the URL for the first time (or click the "Execute" button in the docs) the browser will ask you for your username and password:
|
||||
|
||||
@@ -68,35 +40,7 @@ To handle that, we first convert the `username` and `password` to `bytes` encodi
|
||||
|
||||
Then we can use `secrets.compare_digest()` to ensure that `credentials.username` is `"stanleyjobson"`, and that `credentials.password` is `"swordfish"`.
|
||||
|
||||
//// tab | Python 3.9+
|
||||
|
||||
```Python hl_lines="1 12-24"
|
||||
{!> ../../docs_src/security/tutorial007_an_py39.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="1 12-24"
|
||||
{!> ../../docs_src/security/tutorial007_an.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+ non-Annotated
|
||||
|
||||
/// tip
|
||||
|
||||
Prefer to use the `Annotated` version if possible.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="1 11-21"
|
||||
{!> ../../docs_src/security/tutorial007.py!}
|
||||
```
|
||||
|
||||
////
|
||||
{* ../../docs_src/security/tutorial007_an_py39.py hl[1,12:24] *}
|
||||
|
||||
This would be similar to:
|
||||
|
||||
@@ -160,32 +104,4 @@ That way, using `secrets.compare_digest()` in your application code, it will be
|
||||
|
||||
After detecting that the credentials are incorrect, return an `HTTPException` with a status code 401 (the same returned when no credentials are provided) and add the header `WWW-Authenticate` to make the browser show the login prompt again:
|
||||
|
||||
//// tab | Python 3.9+
|
||||
|
||||
```Python hl_lines="26-30"
|
||||
{!> ../../docs_src/security/tutorial007_an_py39.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="26-30"
|
||||
{!> ../../docs_src/security/tutorial007_an.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+ non-Annotated
|
||||
|
||||
/// tip
|
||||
|
||||
Prefer to use the `Annotated` version if possible.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="23-27"
|
||||
{!> ../../docs_src/security/tutorial007.py!}
|
||||
```
|
||||
|
||||
////
|
||||
{* ../../docs_src/security/tutorial007_an_py39.py hl[26:30] *}
|
||||
|
||||
@@ -321,7 +321,7 @@ This actually inspired updating parts of Pydantic, to support the same validatio
|
||||
|
||||
///
|
||||
|
||||
### <a href="https://www.hug.rest/" class="external-link" target="_blank">Hug</a>
|
||||
### <a href="https://github.com/hugapi/hug" class="external-link" target="_blank">Hug</a>
|
||||
|
||||
Hug was one of the first frameworks to implement the declaration of API parameter types using Python type hints. This was a great idea that inspired other tools to do the same.
|
||||
|
||||
|
||||
@@ -18,9 +18,7 @@ Without changing the settings, syntax highlighting is enabled by default:
|
||||
|
||||
But you can disable it by setting `syntaxHighlight` to `False`:
|
||||
|
||||
```Python hl_lines="3"
|
||||
{!../../docs_src/configure_swagger_ui/tutorial001.py!}
|
||||
```
|
||||
{* ../../docs_src/configure_swagger_ui/tutorial001.py hl[3] *}
|
||||
|
||||
...and then Swagger UI won't show the syntax highlighting anymore:
|
||||
|
||||
@@ -30,9 +28,7 @@ But you can disable it by setting `syntaxHighlight` to `False`:
|
||||
|
||||
The same way you could set the syntax highlighting theme with the key `"syntaxHighlight.theme"` (notice that it has a dot in the middle):
|
||||
|
||||
```Python hl_lines="3"
|
||||
{!../../docs_src/configure_swagger_ui/tutorial002.py!}
|
||||
```
|
||||
{* ../../docs_src/configure_swagger_ui/tutorial002.py hl[3] *}
|
||||
|
||||
That configuration would change the syntax highlighting color theme:
|
||||
|
||||
@@ -44,17 +40,13 @@ FastAPI includes some default configuration parameters appropriate for most of t
|
||||
|
||||
It includes these default configurations:
|
||||
|
||||
```Python
|
||||
{!../../fastapi/openapi/docs.py[ln:7-23]!}
|
||||
```
|
||||
{* ../../fastapi/openapi/docs.py ln[8:23] hl[17:23] *}
|
||||
|
||||
You can override any of them by setting a different value in the argument `swagger_ui_parameters`.
|
||||
|
||||
For example, to disable `deepLinking` you could pass these settings to `swagger_ui_parameters`:
|
||||
|
||||
```Python hl_lines="3"
|
||||
{!../../docs_src/configure_swagger_ui/tutorial003.py!}
|
||||
```
|
||||
{* ../../docs_src/configure_swagger_ui/tutorial003.py hl[3] *}
|
||||
|
||||
## Other Swagger UI Parameters
|
||||
|
||||
|
||||
@@ -43,25 +43,24 @@ For example, let's add <a href="https://github.com/Rebilly/ReDoc/blob/master/doc
|
||||
|
||||
First, write all your **FastAPI** application as normally:
|
||||
|
||||
```Python hl_lines="1 4 7-9"
|
||||
{!../../docs_src/extending_openapi/tutorial001.py!}
|
||||
```
|
||||
{* ../../docs_src/extending_openapi/tutorial001.py hl[1,4,7:9] *}
|
||||
|
||||
|
||||
### Generate the OpenAPI schema
|
||||
|
||||
Then, use the same utility function to generate the OpenAPI schema, inside a `custom_openapi()` function:
|
||||
|
||||
```Python hl_lines="2 15-21"
|
||||
{!../../docs_src/extending_openapi/tutorial001.py!}
|
||||
```
|
||||
|
||||
|
||||
{* ../../docs_src/extending_openapi/tutorial001.py hl[2,15:21] *}
|
||||
|
||||
|
||||
### Modify the OpenAPI schema
|
||||
|
||||
Now you can add the ReDoc extension, adding a custom `x-logo` to the `info` "object" in the OpenAPI schema:
|
||||
|
||||
```Python hl_lines="22-24"
|
||||
{!../../docs_src/extending_openapi/tutorial001.py!}
|
||||
```
|
||||
{* ../../docs_src/extending_openapi/tutorial001.py hl[22:24] *}
|
||||
|
||||
|
||||
### Cache the OpenAPI schema
|
||||
|
||||
@@ -71,17 +70,18 @@ That way, your application won't have to generate the schema every time a user o
|
||||
|
||||
It will be generated only once, and then the same cached schema will be used for the next requests.
|
||||
|
||||
```Python hl_lines="13-14 25-26"
|
||||
{!../../docs_src/extending_openapi/tutorial001.py!}
|
||||
```
|
||||
|
||||
{* ../../docs_src/extending_openapi/tutorial001.py hl[13:14,25:26] *}
|
||||
|
||||
|
||||
### Override the method
|
||||
|
||||
Now you can replace the `.openapi()` method with your new function.
|
||||
|
||||
```Python hl_lines="29"
|
||||
{!../../docs_src/extending_openapi/tutorial001.py!}
|
||||
```
|
||||
|
||||
|
||||
{* ../../docs_src/extending_openapi/tutorial001.py hl[29] *}
|
||||
|
||||
|
||||
### Check it
|
||||
|
||||
|
||||
@@ -35,9 +35,9 @@ Depending on your use case, you might prefer to use a different library, but if
|
||||
|
||||
Here's a small preview of how you could integrate Strawberry with FastAPI:
|
||||
|
||||
```Python hl_lines="3 22 25-26"
|
||||
{!../../docs_src/graphql/tutorial001.py!}
|
||||
```
|
||||
|
||||
{* ../../docs_src/graphql/tutorial001.py hl[3,22,25:26] *}
|
||||
|
||||
|
||||
You can learn more about Strawberry in the <a href="https://strawberry.rocks/" class="external-link" target="_blank">Strawberry documentation</a>.
|
||||
|
||||
|
||||
@@ -10,123 +10,13 @@ Let's see how that works and how to change it if you need to do that.
|
||||
|
||||
Let's say you have a Pydantic model with default values, like this one:
|
||||
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="7"
|
||||
{!> ../../docs_src/separate_openapi_schemas/tutorial001_py310.py[ln:1-7]!}
|
||||
|
||||
# Code below omitted 👇
|
||||
```
|
||||
|
||||
<details>
|
||||
<summary>👀 Full file preview</summary>
|
||||
|
||||
```Python
|
||||
{!> ../../docs_src/separate_openapi_schemas/tutorial001_py310.py!}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.9+
|
||||
|
||||
```Python hl_lines="9"
|
||||
{!> ../../docs_src/separate_openapi_schemas/tutorial001_py39.py[ln:1-9]!}
|
||||
|
||||
# Code below omitted 👇
|
||||
```
|
||||
|
||||
<details>
|
||||
<summary>👀 Full file preview</summary>
|
||||
|
||||
```Python
|
||||
{!> ../../docs_src/separate_openapi_schemas/tutorial001_py39.py!}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="9"
|
||||
{!> ../../docs_src/separate_openapi_schemas/tutorial001.py[ln:1-9]!}
|
||||
|
||||
# Code below omitted 👇
|
||||
```
|
||||
|
||||
<details>
|
||||
<summary>👀 Full file preview</summary>
|
||||
|
||||
```Python
|
||||
{!> ../../docs_src/separate_openapi_schemas/tutorial001.py!}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
////
|
||||
{* ../../docs_src/separate_openapi_schemas/tutorial001_py310.py ln[1:7] hl[7] *}
|
||||
|
||||
### Model for Input
|
||||
|
||||
If you use this model as an input like here:
|
||||
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="14"
|
||||
{!> ../../docs_src/separate_openapi_schemas/tutorial001_py310.py[ln:1-15]!}
|
||||
|
||||
# Code below omitted 👇
|
||||
```
|
||||
|
||||
<details>
|
||||
<summary>👀 Full file preview</summary>
|
||||
|
||||
```Python
|
||||
{!> ../../docs_src/separate_openapi_schemas/tutorial001_py310.py!}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.9+
|
||||
|
||||
```Python hl_lines="16"
|
||||
{!> ../../docs_src/separate_openapi_schemas/tutorial001_py39.py[ln:1-17]!}
|
||||
|
||||
# Code below omitted 👇
|
||||
```
|
||||
|
||||
<details>
|
||||
<summary>👀 Full file preview</summary>
|
||||
|
||||
```Python
|
||||
{!> ../../docs_src/separate_openapi_schemas/tutorial001_py39.py!}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="16"
|
||||
{!> ../../docs_src/separate_openapi_schemas/tutorial001.py[ln:1-17]!}
|
||||
|
||||
# Code below omitted 👇
|
||||
```
|
||||
|
||||
<details>
|
||||
<summary>👀 Full file preview</summary>
|
||||
|
||||
```Python
|
||||
{!> ../../docs_src/separate_openapi_schemas/tutorial001.py!}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
////
|
||||
{* ../../docs_src/separate_openapi_schemas/tutorial001_py310.py ln[1:15] hl[14] *}
|
||||
|
||||
...then the `description` field will **not be required**. Because it has a default value of `None`.
|
||||
|
||||
@@ -142,29 +32,7 @@ You can confirm that in the docs, the `description` field doesn't have a **red a
|
||||
|
||||
But if you use the same model as an output, like here:
|
||||
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="19"
|
||||
{!> ../../docs_src/separate_openapi_schemas/tutorial001_py310.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.9+
|
||||
|
||||
```Python hl_lines="21"
|
||||
{!> ../../docs_src/separate_openapi_schemas/tutorial001_py39.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="21"
|
||||
{!> ../../docs_src/separate_openapi_schemas/tutorial001.py!}
|
||||
```
|
||||
|
||||
////
|
||||
{* ../../docs_src/separate_openapi_schemas/tutorial001_py310.py hl[19] *}
|
||||
|
||||
...then because `description` has a default value, if you **don't return anything** for that field, it will still have that **default value**.
|
||||
|
||||
@@ -223,29 +91,7 @@ Support for `separate_input_output_schemas` was added in FastAPI `0.102.0`. 🤓
|
||||
|
||||
///
|
||||
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="10"
|
||||
{!> ../../docs_src/separate_openapi_schemas/tutorial002_py310.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.9+
|
||||
|
||||
```Python hl_lines="12"
|
||||
{!> ../../docs_src/separate_openapi_schemas/tutorial002_py39.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="12"
|
||||
{!> ../../docs_src/separate_openapi_schemas/tutorial002.py!}
|
||||
```
|
||||
|
||||
////
|
||||
{* ../../docs_src/separate_openapi_schemas/tutorial002_py310.py hl[10] *}
|
||||
|
||||
### Same Schema for Input and Output Models in Docs
|
||||
|
||||
|
||||
@@ -93,7 +93,7 @@ The key features are:
|
||||
|
||||
"_Honestly, what you've built looks super solid and polished. In many ways, it's what I wanted **Hug** to be - it's really inspiring to see someone build that._"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Timothy Crosley - <strong><a href="https://www.hug.rest/" target="_blank">Hug</a> creator</strong> <a href="https://news.ycombinator.com/item?id=19455465" target="_blank"><small>(ref)</small></a></div>
|
||||
<div style="text-align: right; margin-right: 10%;">Timothy Crosley - <strong><a href="https://github.com/hugapi/hug" target="_blank">Hug</a> creator</strong> <a href="https://news.ycombinator.com/item?id=19455465" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -22,9 +22,7 @@ If you are a Python expert, and you already know everything about type hints, sk
|
||||
|
||||
Let's start with a simple example:
|
||||
|
||||
```Python
|
||||
{!../../docs_src/python_types/tutorial001.py!}
|
||||
```
|
||||
{* ../../docs_src/python_types/tutorial001.py *}
|
||||
|
||||
Calling this program outputs:
|
||||
|
||||
@@ -38,9 +36,7 @@ The function does the following:
|
||||
* Converts the first letter of each one to upper case with `title()`.
|
||||
* <abbr title="Puts them together, as one. With the contents of one after the other.">Concatenates</abbr> them with a space in the middle.
|
||||
|
||||
```Python hl_lines="2"
|
||||
{!../../docs_src/python_types/tutorial001.py!}
|
||||
```
|
||||
{* ../../docs_src/python_types/tutorial001.py hl[2] *}
|
||||
|
||||
### Edit it
|
||||
|
||||
@@ -82,9 +78,7 @@ That's it.
|
||||
|
||||
Those are the "type hints":
|
||||
|
||||
```Python hl_lines="1"
|
||||
{!../../docs_src/python_types/tutorial002.py!}
|
||||
```
|
||||
{* ../../docs_src/python_types/tutorial002.py hl[1] *}
|
||||
|
||||
That is not the same as declaring default values like would be with:
|
||||
|
||||
@@ -112,9 +106,7 @@ With that, you can scroll, seeing the options, until you find the one that "ring
|
||||
|
||||
Check this function, it already has type hints:
|
||||
|
||||
```Python hl_lines="1"
|
||||
{!../../docs_src/python_types/tutorial003.py!}
|
||||
```
|
||||
{* ../../docs_src/python_types/tutorial003.py hl[1] *}
|
||||
|
||||
Because the editor knows the types of the variables, you don't only get completion, you also get error checks:
|
||||
|
||||
@@ -122,9 +114,7 @@ Because the editor knows the types of the variables, you don't only get completi
|
||||
|
||||
Now you know that you have to fix it, convert `age` to a string with `str(age)`:
|
||||
|
||||
```Python hl_lines="2"
|
||||
{!../../docs_src/python_types/tutorial004.py!}
|
||||
```
|
||||
{* ../../docs_src/python_types/tutorial004.py hl[2] *}
|
||||
|
||||
## Declaring types
|
||||
|
||||
@@ -143,9 +133,7 @@ You can use, for example:
|
||||
* `bool`
|
||||
* `bytes`
|
||||
|
||||
```Python hl_lines="1"
|
||||
{!../../docs_src/python_types/tutorial005.py!}
|
||||
```
|
||||
{* ../../docs_src/python_types/tutorial005.py hl[1] *}
|
||||
|
||||
### Generic types with type parameters
|
||||
|
||||
@@ -369,9 +357,7 @@ It's just about the words and names. But those words can affect how you and your
|
||||
|
||||
As an example, let's take this function:
|
||||
|
||||
```Python hl_lines="1 4"
|
||||
{!../../docs_src/python_types/tutorial009c.py!}
|
||||
```
|
||||
{* ../../docs_src/python_types/tutorial009c.py hl[1,4] *}
|
||||
|
||||
The parameter `name` is defined as `Optional[str]`, but it is **not optional**, you cannot call the function without the parameter:
|
||||
|
||||
@@ -387,9 +373,7 @@ say_hi(name=None) # This works, None is valid 🎉
|
||||
|
||||
The good news is, once you are on Python 3.10 you won't have to worry about that, as you will be able to simply use `|` to define unions of types:
|
||||
|
||||
```Python hl_lines="1 4"
|
||||
{!../../docs_src/python_types/tutorial009c_py310.py!}
|
||||
```
|
||||
{* ../../docs_src/python_types/tutorial009c_py310.py hl[1,4] *}
|
||||
|
||||
And then you won't have to worry about names like `Optional` and `Union`. 😎
|
||||
|
||||
@@ -451,15 +435,11 @@ You can also declare a class as the type of a variable.
|
||||
|
||||
Let's say you have a class `Person`, with a name:
|
||||
|
||||
```Python hl_lines="1-3"
|
||||
{!../../docs_src/python_types/tutorial010.py!}
|
||||
```
|
||||
{* ../../docs_src/python_types/tutorial010.py hl[1:3] *}
|
||||
|
||||
Then you can declare a variable to be of type `Person`:
|
||||
|
||||
```Python hl_lines="6"
|
||||
{!../../docs_src/python_types/tutorial010.py!}
|
||||
```
|
||||
{* ../../docs_src/python_types/tutorial010.py hl[6] *}
|
||||
|
||||
And then, again, you get all the editor support:
|
||||
|
||||
|
||||
@@ -7,6 +7,104 @@ hide:
|
||||
|
||||
## Latest Changes
|
||||
|
||||
## 0.115.4
|
||||
|
||||
### Refactors
|
||||
|
||||
* ♻️ Update logic to import and check `python-multipart` for compatibility with newer version. PR [#12627](https://github.com/fastapi/fastapi/pull/12627) by [@tiangolo](https://github.com/tiangolo).
|
||||
|
||||
### Docs
|
||||
|
||||
* 📝 Update includes in `docs/fr/docs/tutorial/body.md`. PR [#12596](https://github.com/fastapi/fastapi/pull/12596) by [@kantandane](https://github.com/kantandane).
|
||||
* 📝 Update includes in `docs/fr/docs/tutorial/debugging.md`. PR [#12595](https://github.com/fastapi/fastapi/pull/12595) by [@kantandane](https://github.com/kantandane).
|
||||
* 📝 Update includes in `docs/fr/docs/tutorial/query-params-str-validations.md`. PR [#12591](https://github.com/fastapi/fastapi/pull/12591) by [@kantandane](https://github.com/kantandane).
|
||||
* 📝 Update includes in `docs/fr/docs/tutorial/query-params.md`. PR [#12589](https://github.com/fastapi/fastapi/pull/12589) by [@kantandane](https://github.com/kantandane).
|
||||
* 📝 Update includes in `docs/en/tutorial/body-fields.md`. PR [#12588](https://github.com/fastapi/fastapi/pull/12588) by [@lucaromagnoli](https://github.com/lucaromagnoli).
|
||||
* 📝 Update includes in `docs/de/docs/tutorial/response-status-code.md`. PR [#12585](https://github.com/fastapi/fastapi/pull/12585) by [@abejaranoh](https://github.com/abejaranoh).
|
||||
* 📝 Update includes in `docs/en/docs/tutorial/body.md`. PR [#12586](https://github.com/fastapi/fastapi/pull/12586) by [@lucaromagnoli](https://github.com/lucaromagnoli).
|
||||
* 📝 Update includes in `docs/en/docs/advanced/behind-a-proxy.md`. PR [#12583](https://github.com/fastapi/fastapi/pull/12583) by [@imjuanleonard](https://github.com/imjuanleonard).
|
||||
* 📝 Update includes syntax for `docs/pl/docs/tutorial/first-steps.md`. PR [#12584](https://github.com/fastapi/fastapi/pull/12584) by [@sebkozlo](https://github.com/sebkozlo).
|
||||
* 📝 Update includes in `docs/en/docs/advanced/middleware.md`. PR [#12582](https://github.com/fastapi/fastapi/pull/12582) by [@montanarograziano](https://github.com/montanarograziano).
|
||||
* 📝 Update includes in `docs/en/docs/advanced/additional-status-codes.md`. PR [#12577](https://github.com/fastapi/fastapi/pull/12577) by [@krishnamadhavan](https://github.com/krishnamadhavan).
|
||||
* 📝 Update includes in `docs/en/docs/advanced/advanced-dependencies.md`. PR [#12578](https://github.com/fastapi/fastapi/pull/12578) by [@krishnamadhavan](https://github.com/krishnamadhavan).
|
||||
* 📝 Update includes in `docs/en/docs/advanced/additional-responses.md`. PR [#12576](https://github.com/fastapi/fastapi/pull/12576) by [@krishnamadhavan](https://github.com/krishnamadhavan).
|
||||
* 📝 Update includes in `docs/en/docs/tutorial/static-files.md`. PR [#12575](https://github.com/fastapi/fastapi/pull/12575) by [@lucaromagnoli](https://github.com/lucaromagnoli).
|
||||
* 📝 Update includes in `docs/en/docs/advanced/async-tests.md`. PR [#12568](https://github.com/fastapi/fastapi/pull/12568) by [@krishnamadhavan](https://github.com/krishnamadhavan).
|
||||
* 📝 Update includes in `docs/pt/docs/advanced/behind-a-proxy.md`. PR [#12563](https://github.com/fastapi/fastapi/pull/12563) by [@asmioglou](https://github.com/asmioglou).
|
||||
* 📝 Update includes in `docs/de/docs/advanced/security/http-basic-auth.md`. PR [#12561](https://github.com/fastapi/fastapi/pull/12561) by [@Nimitha-jagadeesha](https://github.com/Nimitha-jagadeesha).
|
||||
* 📝 Update includes in `docs/en/docs/tutorial/background-tasks.md`. PR [#12559](https://github.com/fastapi/fastapi/pull/12559) by [@FarhanAliRaza](https://github.com/FarhanAliRaza).
|
||||
* 📝 Update includes in `docs/fr/docs/python-types.md`. PR [#12558](https://github.com/fastapi/fastapi/pull/12558) by [@Ismailtlem](https://github.com/Ismailtlem).
|
||||
* 📝 Update includes in `docs/en/docs/how-to/graphql.md`. PR [#12564](https://github.com/fastapi/fastapi/pull/12564) by [@philipokiokio](https://github.com/philipokiokio).
|
||||
* 📝 Update includes in `docs/en/docs/how-to/extending-openapi.md`. PR [#12562](https://github.com/fastapi/fastapi/pull/12562) by [@philipokiokio](https://github.com/philipokiokio).
|
||||
* 📝 Update includes for `docs/en/docs/how-to/configure-swagger-ui.md`. PR [#12556](https://github.com/fastapi/fastapi/pull/12556) by [@tiangolo](https://github.com/tiangolo).
|
||||
* 📝 Update includes for `docs/en/docs/how-to/separate-openapi-schemas.md`. PR [#12555](https://github.com/fastapi/fastapi/pull/12555) by [@tiangolo](https://github.com/tiangolo).
|
||||
* 📝 Update includes for `docs/en/docs/advanced/security/http-basic-auth.md`. PR [#12553](https://github.com/fastapi/fastapi/pull/12553) by [@tiangolo](https://github.com/tiangolo).
|
||||
* 📝 Update includes in `docs/en/docs/tutorial/first-steps.md`. PR [#12552](https://github.com/fastapi/fastapi/pull/12552) by [@tiangolo](https://github.com/tiangolo).
|
||||
* 📝 Update includes in `docs/en/docs/python-types.md`. PR [#12551](https://github.com/fastapi/fastapi/pull/12551) by [@tiangolo](https://github.com/tiangolo).
|
||||
* 📝 Fix link in OAuth2 docs. PR [#12550](https://github.com/fastapi/fastapi/pull/12550) by [@tiangolo](https://github.com/tiangolo).
|
||||
* 📝 Add External Link: FastAPI do Zero. PR [#12533](https://github.com/fastapi/fastapi/pull/12533) by [@rennerocha](https://github.com/rennerocha).
|
||||
* 📝 Fix minor typos. PR [#12516](https://github.com/fastapi/fastapi/pull/12516) by [@kkirsche](https://github.com/kkirsche).
|
||||
* 🌐 Fix rendering issue in translations. PR [#12509](https://github.com/fastapi/fastapi/pull/12509) by [@alejsdev](https://github.com/alejsdev).
|
||||
|
||||
### Translations
|
||||
|
||||
* 📝 Update includes in `docs/de/docs/advanced/async-tests.md`. PR [#12567](https://github.com/fastapi/fastapi/pull/12567) by [@imjuanleonard](https://github.com/imjuanleonard).
|
||||
* 🌐 Add Portuguese translation for `docs/pt/docs/tutorial/sql-databases.md`. PR [#12530](https://github.com/fastapi/fastapi/pull/12530) by [@ilacftemp](https://github.com/ilacftemp).
|
||||
* 🌐 Add Korean translation for `docs/ko/docs/benchmarks.md`. PR [#12540](https://github.com/fastapi/fastapi/pull/12540) by [@Limsunoh](https://github.com/Limsunoh).
|
||||
* 🌐 Add Portuguese translation for `docs/pt/docs/how-to/separate-openapi-schemas.md`. PR [#12518](https://github.com/fastapi/fastapi/pull/12518) by [@ilacftemp](https://github.com/ilacftemp).
|
||||
* 🌐 Update Traditional Chinese translation for `docs/zh-hant/docs/deployment/index.md`. PR [#12521](https://github.com/fastapi/fastapi/pull/12521) by [@codingjenny](https://github.com/codingjenny).
|
||||
* 🌐 Update Traditional Chinese translation for `docs/zh-hant/docs/deployment/cloud.md`. PR [#12522](https://github.com/fastapi/fastapi/pull/12522) by [@codingjenny](https://github.com/codingjenny).
|
||||
* 🌐 Update Traditional Chinese translation for `docs/zh-hant/docs/how-to/index.md`. PR [#12523](https://github.com/fastapi/fastapi/pull/12523) by [@codingjenny](https://github.com/codingjenny).
|
||||
* 🌐 Update Traditional Chinese translation for `docs/zh-hant/docs/tutorial/index.md`. PR [#12524](https://github.com/fastapi/fastapi/pull/12524) by [@codingjenny](https://github.com/codingjenny).
|
||||
* 🌐 Add Traditional Chinese translation for `docs/zh-hant/docs/how-to/index.md`. PR [#12468](https://github.com/fastapi/fastapi/pull/12468) by [@codingjenny](https://github.com/codingjenny).
|
||||
* 🌐 Add Traditional Chinese translation for `docs/zh-hant/docs/tutorial/index.md`. PR [#12466](https://github.com/fastapi/fastapi/pull/12466) by [@codingjenny](https://github.com/codingjenny).
|
||||
* 🌐 Add Portuguese translation for `docs/pt/docs/tutorial/header-param-models.md`. PR [#12437](https://github.com/fastapi/fastapi/pull/12437) by [@Joao-Pedro-P-Holanda](https://github.com/Joao-Pedro-P-Holanda).
|
||||
* 🌐 Add Portuguese translation for `docs/pt/docs/how-to/extending-openapi.md`. PR [#12470](https://github.com/fastapi/fastapi/pull/12470) by [@ilacftemp](https://github.com/ilacftemp).
|
||||
* 🌐 Add Portuguese translation for `docs/pt/docs/advanced/dataclasses.md`. PR [#12475](https://github.com/fastapi/fastapi/pull/12475) by [@leoscarlato](https://github.com/leoscarlato).
|
||||
* 🌐 Add Portuguese translation for `docs/pt/docs/how-to/custom-request-and-route.md`. PR [#12483](https://github.com/fastapi/fastapi/pull/12483) by [@devfernandoa](https://github.com/devfernandoa).
|
||||
|
||||
### Internal
|
||||
|
||||
* ⬆ Bump cloudflare/wrangler-action from 3.9 to 3.11. PR [#12544](https://github.com/fastapi/fastapi/pull/12544) by [@dependabot[bot]](https://github.com/apps/dependabot).
|
||||
* 👷 Update GitHub Action to deploy docs previews to handle missing deploy comments. PR [#12527](https://github.com/fastapi/fastapi/pull/12527) by [@tiangolo](https://github.com/tiangolo).
|
||||
* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#12505](https://github.com/fastapi/fastapi/pull/12505) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci).
|
||||
|
||||
## 0.115.3
|
||||
|
||||
### Upgrades
|
||||
|
||||
* ⬆️ Upgrade Starlette to `>=0.40.0,<0.42.0`. PR [#12469](https://github.com/fastapi/fastapi/pull/12469) by [@defnull](https://github.com/defnull).
|
||||
|
||||
### Docs
|
||||
|
||||
* 📝 Fix broken link in docs. PR [#12495](https://github.com/fastapi/fastapi/pull/12495) by [@eltonjncorreia](https://github.com/eltonjncorreia).
|
||||
|
||||
### Translations
|
||||
|
||||
* 🌐 Add Traditional Chinese translation for `docs/zh-hant/docs/fastapi-cli.md`. PR [#12444](https://github.com/fastapi/fastapi/pull/12444) by [@codingjenny](https://github.com/codingjenny).
|
||||
* 🌐 Add Traditional Chinese translation for `docs/zh-hant/docs/deployment/index.md`. PR [#12439](https://github.com/fastapi/fastapi/pull/12439) by [@codingjenny](https://github.com/codingjenny).
|
||||
* 🌐 Add Portuguese translation for `docs/pt/docs/how-to/testing-database.md`. PR [#12472](https://github.com/fastapi/fastapi/pull/12472) by [@GuilhermeRameh](https://github.com/GuilhermeRameh).
|
||||
* 🌐 Add Portuguese translation for `docs/pt/docs/how-to/custom-docs-ui-assets.md`. PR [#12473](https://github.com/fastapi/fastapi/pull/12473) by [@devluisrodrigues](https://github.com/devluisrodrigues).
|
||||
* 🌐 Add Portuguese translation for `docs/pt/docs/advanced/response-headers.md`. PR [#12458](https://github.com/fastapi/fastapi/pull/12458) by [@leonardopaloschi](https://github.com/leonardopaloschi).
|
||||
* 🌐 Add Traditional Chinese translation for `docs/zh-hant/docs/deployment/cloud.md`. PR [#12440](https://github.com/fastapi/fastapi/pull/12440) by [@codingjenny](https://github.com/codingjenny).
|
||||
* 🌐 Update Portuguese translation for `docs/pt/docs/python-types.md`. PR [#12428](https://github.com/fastapi/fastapi/pull/12428) by [@ceb10n](https://github.com/ceb10n).
|
||||
* 🌐 Add Russian translation for `docs/ru/docs/environment-variables.md`. PR [#12436](https://github.com/fastapi/fastapi/pull/12436) by [@wisderfin](https://github.com/wisderfin).
|
||||
* 🌐 Add Traditional Chinese translation for `docs/zh-hant/docs/resources/index.md`. PR [#12443](https://github.com/fastapi/fastapi/pull/12443) by [@codingjenny](https://github.com/codingjenny).
|
||||
* 🌐 Add Traditional Chinese translation for `docs/zh-hant/docs/about/index.md`. PR [#12438](https://github.com/fastapi/fastapi/pull/12438) by [@codingjenny](https://github.com/codingjenny).
|
||||
* 🌐 Add Portuguese translation for `docs/pt/docs/tutorial/query-param-models.md`. PR [#12414](https://github.com/fastapi/fastapi/pull/12414) by [@ceb10n](https://github.com/ceb10n).
|
||||
* 🌐 Remove Portuguese translation for `docs/pt/docs/deployment.md`. PR [#12427](https://github.com/fastapi/fastapi/pull/12427) by [@ceb10n](https://github.com/ceb10n).
|
||||
* 🌐 Add Portuguese translation for `docs/pt/docs/tutorial/body-updates.md`. PR [#12381](https://github.com/fastapi/fastapi/pull/12381) by [@andersonrocha0](https://github.com/andersonrocha0).
|
||||
* 🌐 Add Portuguese translation for `docs/pt/docs/advanced/response-cookies.md`. PR [#12417](https://github.com/fastapi/fastapi/pull/12417) by [@Paulofalcao2002](https://github.com/Paulofalcao2002).
|
||||
|
||||
### Internal
|
||||
|
||||
* 👷 Update issue manager workflow . PR [#12457](https://github.com/fastapi/fastapi/pull/12457) by [@alejsdev](https://github.com/alejsdev).
|
||||
* 🔧 Update team, include YuriiMotov 🚀. PR [#12453](https://github.com/fastapi/fastapi/pull/12453) by [@tiangolo](https://github.com/tiangolo).
|
||||
* 👷 Refactor label-approved, make it an internal script instead of an external GitHub Action. PR [#12280](https://github.com/fastapi/fastapi/pull/12280) by [@tiangolo](https://github.com/tiangolo).
|
||||
* 👷 Fix smokeshow, checkout files on CI. PR [#12434](https://github.com/fastapi/fastapi/pull/12434) by [@tiangolo](https://github.com/tiangolo).
|
||||
* 👷 Use uv in CI. PR [#12281](https://github.com/fastapi/fastapi/pull/12281) by [@tiangolo](https://github.com/tiangolo).
|
||||
* ⬆ Update httpx requirement from <0.25.0,>=0.23.0 to >=0.23.0,<0.28.0. PR [#11509](https://github.com/fastapi/fastapi/pull/11509) by [@dependabot[bot]](https://github.com/apps/dependabot).
|
||||
|
||||
## 0.115.2
|
||||
|
||||
### Upgrades
|
||||
|
||||
@@ -15,9 +15,7 @@ This includes, for example:
|
||||
|
||||
First, import `BackgroundTasks` and define a parameter in your *path operation function* with a type declaration of `BackgroundTasks`:
|
||||
|
||||
```Python hl_lines="1 13"
|
||||
{!../../docs_src/background_tasks/tutorial001.py!}
|
||||
```
|
||||
{* ../../docs_src/background_tasks/tutorial001.py hl[1,13] *}
|
||||
|
||||
**FastAPI** will create the object of type `BackgroundTasks` for you and pass it as that parameter.
|
||||
|
||||
@@ -33,17 +31,13 @@ In this case, the task function will write to a file (simulating sending an emai
|
||||
|
||||
And as the write operation doesn't use `async` and `await`, we define the function with normal `def`:
|
||||
|
||||
```Python hl_lines="6-9"
|
||||
{!../../docs_src/background_tasks/tutorial001.py!}
|
||||
```
|
||||
{* ../../docs_src/background_tasks/tutorial001.py hl[6:9] *}
|
||||
|
||||
## Add the background task
|
||||
|
||||
Inside of your *path operation function*, pass your task function to the *background tasks* object with the method `.add_task()`:
|
||||
|
||||
```Python hl_lines="14"
|
||||
{!../../docs_src/background_tasks/tutorial001.py!}
|
||||
```
|
||||
{* ../../docs_src/background_tasks/tutorial001.py hl[14] *}
|
||||
|
||||
`.add_task()` receives as arguments:
|
||||
|
||||
@@ -57,57 +51,9 @@ Using `BackgroundTasks` also works with the dependency injection system, you can
|
||||
|
||||
**FastAPI** knows what to do in each case and how to reuse the same object, so that all the background tasks are merged together and are run in the background afterwards:
|
||||
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="13 15 22 25"
|
||||
{!> ../../docs_src/background_tasks/tutorial002_an_py310.py!}
|
||||
```
|
||||
{* ../../docs_src/background_tasks/tutorial002_an_py310.py hl[13,15,22,25] *}
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.9+
|
||||
|
||||
```Python hl_lines="13 15 22 25"
|
||||
{!> ../../docs_src/background_tasks/tutorial002_an_py39.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="14 16 23 26"
|
||||
{!> ../../docs_src/background_tasks/tutorial002_an.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.10+ non-Annotated
|
||||
|
||||
/// tip
|
||||
|
||||
Prefer to use the `Annotated` version if possible.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="11 13 20 23"
|
||||
{!> ../../docs_src/background_tasks/tutorial002_py310.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+ non-Annotated
|
||||
|
||||
/// tip
|
||||
|
||||
Prefer to use the `Annotated` version if possible.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="13 15 22 25"
|
||||
{!> ../../docs_src/background_tasks/tutorial002.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
In this example, the messages will be written to the `log.txt` file *after* the response is sent.
|
||||
|
||||
|
||||
@@ -6,57 +6,8 @@ The same way you can declare additional validation and metadata in *path operati
|
||||
|
||||
First, you have to import it:
|
||||
|
||||
//// tab | Python 3.10+
|
||||
{* ../../docs_src/body_fields/tutorial001_an_py310.py hl[4] *}
|
||||
|
||||
```Python hl_lines="4"
|
||||
{!> ../../docs_src/body_fields/tutorial001_an_py310.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.9+
|
||||
|
||||
```Python hl_lines="4"
|
||||
{!> ../../docs_src/body_fields/tutorial001_an_py39.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="4"
|
||||
{!> ../../docs_src/body_fields/tutorial001_an.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.10+ non-Annotated
|
||||
|
||||
/// tip
|
||||
|
||||
Prefer to use the `Annotated` version if possible.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="2"
|
||||
{!> ../../docs_src/body_fields/tutorial001_py310.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+ non-Annotated
|
||||
|
||||
/// tip
|
||||
|
||||
Prefer to use the `Annotated` version if possible.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="4"
|
||||
{!> ../../docs_src/body_fields/tutorial001.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
/// warning
|
||||
|
||||
@@ -68,57 +19,7 @@ Notice that `Field` is imported directly from `pydantic`, not from `fastapi` as
|
||||
|
||||
You can then use `Field` with model attributes:
|
||||
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="11-14"
|
||||
{!> ../../docs_src/body_fields/tutorial001_an_py310.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.9+
|
||||
|
||||
```Python hl_lines="11-14"
|
||||
{!> ../../docs_src/body_fields/tutorial001_an_py39.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="12-15"
|
||||
{!> ../../docs_src/body_fields/tutorial001_an.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.10+ non-Annotated
|
||||
|
||||
/// tip
|
||||
|
||||
Prefer to use the `Annotated` version if possible.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="9-12"
|
||||
{!> ../../docs_src/body_fields/tutorial001_py310.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+ non-Annotated
|
||||
|
||||
/// tip
|
||||
|
||||
Prefer to use the `Annotated` version if possible.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="11-14"
|
||||
{!> ../../docs_src/body_fields/tutorial001.py!}
|
||||
```
|
||||
|
||||
////
|
||||
{* ../../docs_src/body_fields/tutorial001_an_py310.py hl[11:14] *}
|
||||
|
||||
`Field` works the same way as `Query`, `Path` and `Body`, it has all the same parameters, etc.
|
||||
|
||||
|
||||
@@ -22,21 +22,7 @@ As it is discouraged, the interactive docs with Swagger UI won't show the docume
|
||||
|
||||
First, you need to import `BaseModel` from `pydantic`:
|
||||
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="2"
|
||||
{!> ../../docs_src/body/tutorial001_py310.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="4"
|
||||
{!> ../../docs_src/body/tutorial001.py!}
|
||||
```
|
||||
|
||||
////
|
||||
{* ../../docs_src/body/tutorial001_py310.py hl[2] *}
|
||||
|
||||
## Create your data model
|
||||
|
||||
@@ -44,21 +30,8 @@ Then you declare your data model as a class that inherits from `BaseModel`.
|
||||
|
||||
Use standard Python types for all the attributes:
|
||||
|
||||
//// tab | Python 3.10+
|
||||
{* ../../docs_src/body/tutorial001_py310.py hl[5:9] *}
|
||||
|
||||
```Python hl_lines="5-9"
|
||||
{!> ../../docs_src/body/tutorial001_py310.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="7-11"
|
||||
{!> ../../docs_src/body/tutorial001.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
The same as when declaring query parameters, when a model attribute has a default value, it is not required. Otherwise, it is required. Use `None` to make it just optional.
|
||||
|
||||
@@ -86,21 +59,7 @@ For example, this model above declares a JSON "`object`" (or Python `dict`) like
|
||||
|
||||
To add it to your *path operation*, declare it the same way you declared path and query parameters:
|
||||
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="16"
|
||||
{!> ../../docs_src/body/tutorial001_py310.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="18"
|
||||
{!> ../../docs_src/body/tutorial001.py!}
|
||||
```
|
||||
|
||||
////
|
||||
{* ../../docs_src/body/tutorial001_py310.py hl[16] *}
|
||||
|
||||
...and declare its type as the model you created, `Item`.
|
||||
|
||||
@@ -167,21 +126,7 @@ It improves editor support for Pydantic models, with:
|
||||
|
||||
Inside of the function, you can access all the attributes of the model object directly:
|
||||
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="19"
|
||||
{!> ../../docs_src/body/tutorial002_py310.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="21"
|
||||
{!> ../../docs_src/body/tutorial002.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
## Request body + path parameters
|
||||
|
||||
@@ -189,21 +134,8 @@ You can declare path parameters and request body at the same time.
|
||||
|
||||
**FastAPI** will recognize that the function parameters that match path parameters should be **taken from the path**, and that function parameters that are declared to be Pydantic models should be **taken from the request body**.
|
||||
|
||||
//// tab | Python 3.10+
|
||||
{* ../../docs_src/body/tutorial003_py310.py hl[15:16] *}
|
||||
|
||||
```Python hl_lines="15-16"
|
||||
{!> ../../docs_src/body/tutorial003_py310.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="17-18"
|
||||
{!> ../../docs_src/body/tutorial003.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
## Request body + path + query parameters
|
||||
|
||||
@@ -211,21 +143,7 @@ You can also declare **body**, **path** and **query** parameters, all at the sam
|
||||
|
||||
**FastAPI** will recognize each of them and take the data from the correct place.
|
||||
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="16"
|
||||
{!> ../../docs_src/body/tutorial004_py310.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="18"
|
||||
{!> ../../docs_src/body/tutorial004.py!}
|
||||
```
|
||||
|
||||
////
|
||||
{* ../../docs_src/body/tutorial004_py310.py hl[16] *}
|
||||
|
||||
The function parameters will be recognized as follows:
|
||||
|
||||
|
||||
@@ -2,9 +2,7 @@
|
||||
|
||||
The simplest FastAPI file could look like this:
|
||||
|
||||
```Python
|
||||
{!../../docs_src/first_steps/tutorial001.py!}
|
||||
```
|
||||
{* ../../docs_src/first_steps/tutorial001.py *}
|
||||
|
||||
Copy that to a file `main.py`.
|
||||
|
||||
@@ -157,9 +155,7 @@ You could also use it to generate code automatically, for clients that communica
|
||||
|
||||
### Step 1: import `FastAPI`
|
||||
|
||||
```Python hl_lines="1"
|
||||
{!../../docs_src/first_steps/tutorial001.py!}
|
||||
```
|
||||
{* ../../docs_src/first_steps/tutorial001.py hl[1] *}
|
||||
|
||||
`FastAPI` is a Python class that provides all the functionality for your API.
|
||||
|
||||
@@ -173,9 +169,7 @@ You can use all the <a href="https://www.starlette.io/" class="external-link" ta
|
||||
|
||||
### Step 2: create a `FastAPI` "instance"
|
||||
|
||||
```Python hl_lines="3"
|
||||
{!../../docs_src/first_steps/tutorial001.py!}
|
||||
```
|
||||
{* ../../docs_src/first_steps/tutorial001.py hl[3] *}
|
||||
|
||||
Here the `app` variable will be an "instance" of the class `FastAPI`.
|
||||
|
||||
@@ -244,9 +238,7 @@ We are going to call them "**operations**" too.
|
||||
|
||||
#### Define a *path operation decorator*
|
||||
|
||||
```Python hl_lines="6"
|
||||
{!../../docs_src/first_steps/tutorial001.py!}
|
||||
```
|
||||
{* ../../docs_src/first_steps/tutorial001.py hl[6] *}
|
||||
|
||||
The `@app.get("/")` tells **FastAPI** that the function right below is in charge of handling requests that go to:
|
||||
|
||||
@@ -300,9 +292,7 @@ This is our "**path operation function**":
|
||||
* **operation**: is `get`.
|
||||
* **function**: is the function below the "decorator" (below `@app.get("/")`).
|
||||
|
||||
```Python hl_lines="7"
|
||||
{!../../docs_src/first_steps/tutorial001.py!}
|
||||
```
|
||||
{* ../../docs_src/first_steps/tutorial001.py hl[7] *}
|
||||
|
||||
This is a Python function.
|
||||
|
||||
@@ -314,9 +304,7 @@ In this case, it is an `async` function.
|
||||
|
||||
You could also define it as a normal function instead of `async def`:
|
||||
|
||||
```Python hl_lines="7"
|
||||
{!../../docs_src/first_steps/tutorial003.py!}
|
||||
```
|
||||
{* ../../docs_src/first_steps/tutorial003.py hl[7] *}
|
||||
|
||||
/// note
|
||||
|
||||
@@ -326,9 +314,7 @@ If you don't know the difference, check the [Async: *"In a hurry?"*](../async.md
|
||||
|
||||
### Step 5: return the content
|
||||
|
||||
```Python hl_lines="8"
|
||||
{!../../docs_src/first_steps/tutorial001.py!}
|
||||
```
|
||||
{* ../../docs_src/first_steps/tutorial001.py hl[8] *}
|
||||
|
||||
You can return a `dict`, `list`, singular values as `str`, `int`, etc.
|
||||
|
||||
|
||||
@@ -72,7 +72,7 @@ It supports many secure hashing algorithms and utilities to work with them.
|
||||
|
||||
The recommended algorithm is "Bcrypt".
|
||||
|
||||
Make sure you create a [virtual environment](../virtual-environments.md){.internal-link target=_blank}, activate it, and then install PassLib with Bcrypt:
|
||||
Make sure you create a [virtual environment](../../virtual-environments.md){.internal-link target=_blank}, activate it, and then install PassLib with Bcrypt:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
|
||||
@@ -7,9 +7,7 @@ You can serve static files automatically from a directory using `StaticFiles`.
|
||||
* Import `StaticFiles`.
|
||||
* "Mount" a `StaticFiles()` instance in a specific path.
|
||||
|
||||
```Python hl_lines="2 6"
|
||||
{!../../docs_src/static_files/tutorial001.py!}
|
||||
```
|
||||
{* ../../docs_src/static_files/tutorial001.py hl[2,6] *}
|
||||
|
||||
/// note | "Technical Details"
|
||||
|
||||
|
||||
@@ -266,7 +266,6 @@ markdown_extensions:
|
||||
|
||||
# Python Markdown Extensions
|
||||
pymdownx.betterem:
|
||||
smart_enable: all
|
||||
pymdownx.caret:
|
||||
pymdownx.highlight:
|
||||
line_spans: __span
|
||||
|
||||
@@ -90,7 +90,7 @@ Sus características principales son:
|
||||
|
||||
"_Honestly, what you've built looks super solid and polished. In many ways, it's what I wanted **Hug** to be - it's really inspiring to see someone build that._"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Timothy Crosley - <strong><a href="https://www.hug.rest/" target="_blank">Hug</a> creator</strong> <a href="https://news.ycombinator.com/item?id=19455465" target="_blank"><small>(ref)</small></a></div>
|
||||
<div style="text-align: right; margin-right: 10%;">Timothy Crosley - <strong><a href="https://github.com/hugapi/hug" target="_blank">Hug</a> creator</strong> <a href="https://news.ycombinator.com/item?id=19455465" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -90,7 +90,7 @@ FastAPI یک وب فریمورک مدرن و سریع (با کارایی با
|
||||
|
||||
<div style="text-align: left; direction: ltr;">"<em>Honestly, what you've built looks super solid and polished. In many ways, it's what I wanted <strong>Hug</strong> to be - it's really inspiring to see someone build that."</em></div>
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Timothy Crosley - <strong><a href="https://www.hug.rest/" target="_blank">Hug</a> creator</strong> <a href="https://news.ycombinator.com/item?id=19455465" target="_blank"><small>(ref)</small></a></div>
|
||||
<div style="text-align: right; margin-right: 10%;">Timothy Crosley - <strong><a href="https://github.com/hugapi/hug" target="_blank">Hug</a> creator</strong> <a href="https://news.ycombinator.com/item?id=19455465" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -351,7 +351,7 @@ Cela a en fait inspiré la mise à jour de certaines parties de Pydantic, afin d
|
||||
|
||||
///
|
||||
|
||||
### <a href="https://www.hug.rest/" class="external-link" target="_blank">Hug</a>
|
||||
### <a href="https://github.com/hugapi/hug" class="external-link" target="_blank">Hug</a>
|
||||
|
||||
Hug a été l'un des premiers frameworks à implémenter la déclaration des types de paramètres d'API en utilisant les type hints Python. C'était une excellente idée qui a inspiré d'autres outils à faire de même.
|
||||
|
||||
|
||||
@@ -93,7 +93,7 @@ Les principales fonctionnalités sont :
|
||||
|
||||
"_Honnêtement, ce que vous avez construit a l'air super solide et élégant. A bien des égards, c'est comme ça que je voulais que **Hug** soit - c'est vraiment inspirant de voir quelqu'un construire ça._"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Timothy Crosley - <strong> Créateur de <a href="https://www.hug.rest/" target="_blank">Hug</a></strong> <a href="https://news.ycombinator.com/item?id=19455465" target="_blank"><small>(ref)</small></a></div>
|
||||
<div style="text-align: right; margin-right: 10%;">Timothy Crosley - <strong> Créateur de <a href="https://github.com/hugapi/hug" target="_blank">Hug</a></strong> <a href="https://news.ycombinator.com/item?id=19455465" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -23,9 +23,7 @@ Si vous êtes un expert Python, et que vous savez déjà **tout** sur les annota
|
||||
|
||||
Prenons un exemple simple :
|
||||
|
||||
```Python
|
||||
{!../../docs_src/python_types/tutorial001.py!}
|
||||
```
|
||||
{*../../docs_src/python_types/tutorial001.py*}
|
||||
|
||||
Exécuter ce programe affiche :
|
||||
|
||||
@@ -39,9 +37,7 @@ La fonction :
|
||||
* Convertit la première lettre de chaque paramètre en majuscules grâce à `title()`.
|
||||
* Concatène les résultats avec un espace entre les deux.
|
||||
|
||||
```Python hl_lines="2"
|
||||
{!../../docs_src/python_types/tutorial001.py!}
|
||||
```
|
||||
{*../../docs_src/python_types/tutorial001.py hl[2] *}
|
||||
|
||||
### Limitations
|
||||
|
||||
@@ -84,9 +80,7 @@ C'est tout.
|
||||
|
||||
Ce sont des annotations de types :
|
||||
|
||||
```Python hl_lines="1"
|
||||
{!../../docs_src/python_types/tutorial002.py!}
|
||||
```
|
||||
{*../../docs_src/python_types/tutorial002.py hl[1] *}
|
||||
|
||||
À ne pas confondre avec la déclaration de valeurs par défaut comme ici :
|
||||
|
||||
@@ -114,9 +108,7 @@ Vous pouvez donc dérouler les options jusqu'à trouver la méthode à laquelle
|
||||
|
||||
Cette fonction possède déjà des annotations de type :
|
||||
|
||||
```Python hl_lines="1"
|
||||
{!../../docs_src/python_types/tutorial003.py!}
|
||||
```
|
||||
{*../../docs_src/python_types/tutorial003.py hl[1] *}
|
||||
|
||||
Comme l'éditeur connaît le type des variables, vous n'avez pas seulement l'auto-complétion, mais aussi de la détection d'erreurs :
|
||||
|
||||
@@ -124,9 +116,7 @@ Comme l'éditeur connaît le type des variables, vous n'avez pas seulement l'aut
|
||||
|
||||
Maintenant que vous avez connaissance du problème, convertissez `age` en <abbr title="string">chaîne de caractères</abbr> grâce à `str(age)` :
|
||||
|
||||
```Python hl_lines="2"
|
||||
{!../../docs_src/python_types/tutorial004.py!}
|
||||
```
|
||||
{*../../docs_src/python_types/tutorial004.py hl[2] *}
|
||||
|
||||
## Déclarer des types
|
||||
|
||||
@@ -145,9 +135,7 @@ Comme par exemple :
|
||||
* `bool`
|
||||
* `bytes`
|
||||
|
||||
```Python hl_lines="1"
|
||||
{!../../docs_src/python_types/tutorial005.py!}
|
||||
```
|
||||
{*../../docs_src/python_types/tutorial005.py hl[1] *}
|
||||
|
||||
### Types génériques avec des paramètres de types
|
||||
|
||||
@@ -163,9 +151,7 @@ Par exemple, définissons une variable comme `list` de `str`.
|
||||
|
||||
Importez `List` (avec un `L` majuscule) depuis `typing`.
|
||||
|
||||
```Python hl_lines="1"
|
||||
{!../../docs_src/python_types/tutorial006.py!}
|
||||
```
|
||||
{*../../docs_src/python_types/tutorial006.py hl[1] *}
|
||||
|
||||
Déclarez la variable, en utilisant la syntaxe des deux-points (`:`).
|
||||
|
||||
@@ -173,9 +159,7 @@ Et comme type, mettez `List`.
|
||||
|
||||
Les listes étant un type contenant des types internes, mettez ces derniers entre crochets (`[`, `]`) :
|
||||
|
||||
```Python hl_lines="4"
|
||||
{!../../docs_src/python_types/tutorial006.py!}
|
||||
```
|
||||
{*../../docs_src/python_types/tutorial006.py hl[4] *}
|
||||
|
||||
/// tip | "Astuce"
|
||||
|
||||
@@ -201,9 +185,7 @@ Et pourtant, l'éditeur sait qu'elle est de type `str` et pourra donc vous aider
|
||||
|
||||
C'est le même fonctionnement pour déclarer un `tuple` ou un `set` :
|
||||
|
||||
```Python hl_lines="1 4"
|
||||
{!../../docs_src/python_types/tutorial007.py!}
|
||||
```
|
||||
{*../../docs_src/python_types/tutorial007.py hl[1,4] *}
|
||||
|
||||
Dans cet exemple :
|
||||
|
||||
@@ -216,9 +198,7 @@ Pour définir un `dict`, il faut lui passer 2 paramètres, séparés par une vir
|
||||
|
||||
Le premier paramètre de type est pour les clés et le second pour les valeurs du dictionnaire (`dict`).
|
||||
|
||||
```Python hl_lines="1 4"
|
||||
{!../../docs_src/python_types/tutorial008.py!}
|
||||
```
|
||||
{*../../docs_src/python_types/tutorial008.py hl[1,4] *}
|
||||
|
||||
Dans cet exemple :
|
||||
|
||||
@@ -230,9 +210,7 @@ Dans cet exemple :
|
||||
|
||||
Vous pouvez aussi utiliser `Optional` pour déclarer qu'une variable a un type, comme `str` mais qu'il est "optionnel" signifiant qu'il pourrait aussi être `None`.
|
||||
|
||||
```Python hl_lines="1 4"
|
||||
{!../../docs_src/python_types/tutorial009.py!}
|
||||
```
|
||||
{*../../docs_src/python_types/tutorial009.py hl[1,4] *}
|
||||
|
||||
Utiliser `Optional[str]` plutôt que `str` permettra à l'éditeur de vous aider à détecter les erreurs où vous supposeriez qu'une valeur est toujours de type `str`, alors qu'elle pourrait aussi être `None`.
|
||||
|
||||
@@ -255,15 +233,12 @@ Vous pouvez aussi déclarer une classe comme type d'une variable.
|
||||
|
||||
Disons que vous avez une classe `Person`, avec une variable `name` :
|
||||
|
||||
```Python hl_lines="1-3"
|
||||
{!../../docs_src/python_types/tutorial010.py!}
|
||||
```
|
||||
{*../../docs_src/python_types/tutorial010.py hl[1:3] *}
|
||||
|
||||
|
||||
Vous pouvez ensuite déclarer une variable de type `Person` :
|
||||
|
||||
```Python hl_lines="6"
|
||||
{!../../docs_src/python_types/tutorial010.py!}
|
||||
```
|
||||
{*../../docs_src/python_types/tutorial010.py hl[6] *}
|
||||
|
||||
Et vous aurez accès, encore une fois, au support complet offert par l'éditeur :
|
||||
|
||||
@@ -283,9 +258,7 @@ Ainsi, votre éditeur vous offrira un support adapté pour l'objet résultant.
|
||||
|
||||
Extrait de la documentation officielle de **Pydantic** :
|
||||
|
||||
```Python
|
||||
{!../../docs_src/python_types/tutorial011.py!}
|
||||
```
|
||||
{*../../docs_src/python_types/tutorial011.py*}
|
||||
|
||||
/// info
|
||||
|
||||
|
||||
@@ -22,9 +22,7 @@ Ceci étant découragé, la documentation interactive générée par Swagger UI
|
||||
|
||||
Commencez par importer la classe `BaseModel` du module `pydantic` :
|
||||
|
||||
```Python hl_lines="4"
|
||||
{!../../docs_src/body/tutorial001.py!}
|
||||
```
|
||||
{* ../../docs_src/body/tutorial001.py hl[4] *}
|
||||
|
||||
## Créez votre modèle de données
|
||||
|
||||
@@ -32,9 +30,7 @@ Déclarez ensuite votre modèle de données en tant que classe qui hérite de `B
|
||||
|
||||
Utilisez les types Python standard pour tous les attributs :
|
||||
|
||||
```Python hl_lines="7-11"
|
||||
{!../../docs_src/body/tutorial001.py!}
|
||||
```
|
||||
{* ../../docs_src/body/tutorial001.py hl[7:11] *}
|
||||
|
||||
Tout comme pour la déclaration de paramètres de requête, quand un attribut de modèle a une valeur par défaut, il n'est pas nécessaire. Sinon, cet attribut doit être renseigné dans le corps de la requête. Pour rendre ce champ optionnel simplement, utilisez `None` comme valeur par défaut.
|
||||
|
||||
@@ -62,9 +58,7 @@ Par exemple, le modèle ci-dessus déclare un "objet" JSON (ou `dict` Python) te
|
||||
|
||||
Pour l'ajouter à votre *opération de chemin*, déclarez-le comme vous déclareriez des paramètres de chemin ou de requête :
|
||||
|
||||
```Python hl_lines="18"
|
||||
{!../../docs_src/body/tutorial001.py!}
|
||||
```
|
||||
{* ../../docs_src/body/tutorial001.py hl[18] *}
|
||||
|
||||
...et déclarez que son type est le modèle que vous avez créé : `Item`.
|
||||
|
||||
@@ -131,9 +125,7 @@ Ce qui améliore le support pour les modèles Pydantic avec :
|
||||
|
||||
Dans la fonction, vous pouvez accéder à tous les attributs de l'objet du modèle directement :
|
||||
|
||||
```Python hl_lines="21"
|
||||
{!../../docs_src/body/tutorial002.py!}
|
||||
```
|
||||
{* ../../docs_src/body/tutorial002.py hl[21] *}
|
||||
|
||||
## Corps de la requête + paramètres de chemin
|
||||
|
||||
@@ -141,9 +133,7 @@ Vous pouvez déclarer des paramètres de chemin et un corps de requête pour la
|
||||
|
||||
**FastAPI** est capable de reconnaître que les paramètres de la fonction qui correspondent aux paramètres de chemin doivent être **récupérés depuis le chemin**, et que les paramètres de fonctions déclarés comme modèles Pydantic devraient être **récupérés depuis le corps de la requête**.
|
||||
|
||||
```Python hl_lines="17-18"
|
||||
{!../../docs_src/body/tutorial003.py!}
|
||||
```
|
||||
{* ../../docs_src/body/tutorial003.py hl[17:18] *}
|
||||
|
||||
## Corps de la requête + paramètres de chemin et de requête
|
||||
|
||||
@@ -151,9 +141,7 @@ Vous pouvez aussi déclarer un **corps**, et des paramètres de **chemin** et de
|
||||
|
||||
**FastAPI** saura reconnaître chacun d'entre eux et récupérer la bonne donnée au bon endroit.
|
||||
|
||||
```Python hl_lines="18"
|
||||
{!../../docs_src/body/tutorial004.py!}
|
||||
```
|
||||
{* ../../docs_src/body/tutorial004.py hl[18] *}
|
||||
|
||||
Les paramètres de la fonction seront reconnus comme tel :
|
||||
|
||||
|
||||
@@ -6,9 +6,7 @@ Vous pouvez connecter le <abbr title="En anglais: debugger">débogueur</abbr> da
|
||||
|
||||
Dans votre application FastAPI, importez et exécutez directement `uvicorn` :
|
||||
|
||||
```Python hl_lines="1 15"
|
||||
{!../../docs_src/debugging/tutorial001.py!}
|
||||
```
|
||||
{* ../../docs_src/debugging/tutorial001.py hl[1,15] *}
|
||||
|
||||
### À propos de `__name__ == "__main__"`
|
||||
|
||||
|
||||
@@ -4,9 +4,7 @@
|
||||
|
||||
Commençons avec cette application pour exemple :
|
||||
|
||||
```Python hl_lines="9"
|
||||
{!../../docs_src/query_params_str_validations/tutorial001.py!}
|
||||
```
|
||||
{* ../../docs_src/query_params_str_validations/tutorial001.py hl[9] *}
|
||||
|
||||
Le paramètre de requête `q` a pour type `Union[str, None]` (ou `str | None` en Python 3.10), signifiant qu'il est de type `str` mais pourrait aussi être égal à `None`, et bien sûr, la valeur par défaut est `None`, donc **FastAPI** saura qu'il n'est pas requis.
|
||||
|
||||
@@ -26,17 +24,13 @@ Nous allons imposer que bien que `q` soit un paramètre optionnel, dès qu'il es
|
||||
|
||||
Pour cela, importez d'abord `Query` depuis `fastapi` :
|
||||
|
||||
```Python hl_lines="3"
|
||||
{!../../docs_src/query_params_str_validations/tutorial002.py!}
|
||||
```
|
||||
{* ../../docs_src/query_params_str_validations/tutorial002.py hl[3] *}
|
||||
|
||||
## Utiliser `Query` comme valeur par défaut
|
||||
|
||||
Construisez ensuite la valeur par défaut de votre paramètre avec `Query`, en choisissant 50 comme `max_length` :
|
||||
|
||||
```Python hl_lines="9"
|
||||
{!../../docs_src/query_params_str_validations/tutorial002.py!}
|
||||
```
|
||||
{* ../../docs_src/query_params_str_validations/tutorial002.py hl[9] *}
|
||||
|
||||
Comme nous devons remplacer la valeur par défaut `None` dans la fonction par `Query()`, nous pouvons maintenant définir la valeur par défaut avec le paramètre `Query(default=None)`, il sert le même objectif qui est de définir cette valeur par défaut.
|
||||
|
||||
@@ -86,17 +80,13 @@ Cela va valider les données, montrer une erreur claire si ces dernières ne son
|
||||
|
||||
Vous pouvez aussi rajouter un second paramètre `min_length` :
|
||||
|
||||
```Python hl_lines="9"
|
||||
{!../../docs_src/query_params_str_validations/tutorial003.py!}
|
||||
```
|
||||
{* ../../docs_src/query_params_str_validations/tutorial003.py hl[9] *}
|
||||
|
||||
## Ajouter des validations par expressions régulières
|
||||
|
||||
On peut définir une <abbr title="Une expression régulière, regex ou regexp est une suite de caractères qui définit un pattern de correspondance pour les chaînes de caractères.">expression régulière</abbr> à laquelle le paramètre doit correspondre :
|
||||
|
||||
```Python hl_lines="10"
|
||||
{!../../docs_src/query_params_str_validations/tutorial004.py!}
|
||||
```
|
||||
{* ../../docs_src/query_params_str_validations/tutorial004.py hl[10] *}
|
||||
|
||||
Cette expression régulière vérifie que la valeur passée comme paramètre :
|
||||
|
||||
@@ -114,9 +104,7 @@ De la même façon que vous pouvez passer `None` comme premier argument pour l'u
|
||||
|
||||
Disons que vous déclarez le paramètre `q` comme ayant une longueur minimale de `3`, et une valeur par défaut étant `"fixedquery"` :
|
||||
|
||||
```Python hl_lines="7"
|
||||
{!../../docs_src/query_params_str_validations/tutorial005.py!}
|
||||
```
|
||||
{* ../../docs_src/query_params_str_validations/tutorial005.py hl[7] *}
|
||||
|
||||
/// note | "Rappel"
|
||||
|
||||
@@ -146,9 +134,7 @@ q: Union[str, None] = Query(default=None, min_length=3)
|
||||
|
||||
Donc pour déclarer une valeur comme requise tout en utilisant `Query`, il faut utiliser `...` comme premier argument :
|
||||
|
||||
```Python hl_lines="7"
|
||||
{!../../docs_src/query_params_str_validations/tutorial006.py!}
|
||||
```
|
||||
{* ../../docs_src/query_params_str_validations/tutorial006.py hl[7] *}
|
||||
|
||||
/// info
|
||||
|
||||
@@ -164,9 +150,7 @@ Quand on définit un paramètre de requête explicitement avec `Query` on peut a
|
||||
|
||||
Par exemple, pour déclarer un paramètre de requête `q` qui peut apparaître plusieurs fois dans une URL, on écrit :
|
||||
|
||||
```Python hl_lines="9"
|
||||
{!../../docs_src/query_params_str_validations/tutorial011.py!}
|
||||
```
|
||||
{* ../../docs_src/query_params_str_validations/tutorial011.py hl[9] *}
|
||||
|
||||
Ce qui fait qu'avec une URL comme :
|
||||
|
||||
@@ -201,9 +185,7 @@ La documentation sera donc mise à jour automatiquement pour autoriser plusieurs
|
||||
|
||||
Et l'on peut aussi définir une liste de valeurs par défaut si aucune n'est fournie :
|
||||
|
||||
```Python hl_lines="9"
|
||||
{!../../docs_src/query_params_str_validations/tutorial012.py!}
|
||||
```
|
||||
{* ../../docs_src/query_params_str_validations/tutorial012.py hl[9] *}
|
||||
|
||||
Si vous allez à :
|
||||
|
||||
@@ -228,9 +210,7 @@ et la réponse sera :
|
||||
|
||||
Il est aussi possible d'utiliser directement `list` plutôt que `List[str]` :
|
||||
|
||||
```Python hl_lines="7"
|
||||
{!../../docs_src/query_params_str_validations/tutorial013.py!}
|
||||
```
|
||||
{* ../../docs_src/query_params_str_validations/tutorial013.py hl[7] *}
|
||||
|
||||
/// note
|
||||
|
||||
@@ -256,15 +236,11 @@ Il se peut donc que certains d'entre eux n'utilisent pas toutes les métadonnée
|
||||
|
||||
Vous pouvez ajouter un `title` :
|
||||
|
||||
```Python hl_lines="10"
|
||||
{!../../docs_src/query_params_str_validations/tutorial007.py!}
|
||||
```
|
||||
{* ../../docs_src/query_params_str_validations/tutorial007.py hl[10] *}
|
||||
|
||||
Et une `description` :
|
||||
|
||||
```Python hl_lines="13"
|
||||
{!../../docs_src/query_params_str_validations/tutorial008.py!}
|
||||
```
|
||||
{* ../../docs_src/query_params_str_validations/tutorial008.py hl[13] *}
|
||||
|
||||
## Alias de paramètres
|
||||
|
||||
@@ -284,9 +260,7 @@ Mais vous avez vraiment envie que ce soit exactement `item-query`...
|
||||
|
||||
Pour cela vous pouvez déclarer un `alias`, et cet alias est ce qui sera utilisé pour trouver la valeur du paramètre :
|
||||
|
||||
```Python hl_lines="9"
|
||||
{!../../docs_src/query_params_str_validations/tutorial009.py!}
|
||||
```
|
||||
{* ../../docs_src/query_params_str_validations/tutorial009.py hl[9] *}
|
||||
|
||||
## Déprécier des paramètres
|
||||
|
||||
@@ -296,9 +270,7 @@ Il faut qu'il continue à exister pendant un certain temps car vos clients l'uti
|
||||
|
||||
On utilise alors l'argument `deprecated=True` de `Query` :
|
||||
|
||||
```Python hl_lines="18"
|
||||
{!../../docs_src/query_params_str_validations/tutorial010.py!}
|
||||
```
|
||||
{* ../../docs_src/query_params_str_validations/tutorial010.py hl[18] *}
|
||||
|
||||
La documentation le présentera comme il suit :
|
||||
|
||||
|
||||
@@ -2,9 +2,7 @@
|
||||
|
||||
Quand vous déclarez des paramètres dans votre fonction de chemin qui ne font pas partie des paramètres indiqués dans le chemin associé, ces paramètres sont automatiquement considérés comme des paramètres de "requête".
|
||||
|
||||
```Python hl_lines="9"
|
||||
{!../../docs_src/query_params/tutorial001.py!}
|
||||
```
|
||||
{* ../../docs_src/query_params/tutorial001.py hl[9] *}
|
||||
|
||||
La partie appelée requête (ou **query**) dans une URL est l'ensemble des paires clés-valeurs placées après le `?` , séparées par des `&`.
|
||||
|
||||
@@ -63,9 +61,7 @@ Les valeurs des paramètres de votre fonction seront :
|
||||
|
||||
De la même façon, vous pouvez définir des paramètres de requête comme optionnels, en leur donnant comme valeur par défaut `None` :
|
||||
|
||||
```Python hl_lines="9"
|
||||
{!../../docs_src/query_params/tutorial002.py!}
|
||||
```
|
||||
{* ../../docs_src/query_params/tutorial002.py hl[9] *}
|
||||
|
||||
Ici, le paramètre `q` sera optionnel, et aura `None` comme valeur par défaut.
|
||||
|
||||
@@ -87,9 +83,7 @@ Le `Optional` dans `Optional[str]` n'est pas utilisé par **FastAPI** (**FastAPI
|
||||
|
||||
Vous pouvez aussi déclarer des paramètres de requête comme booléens (`bool`), **FastAPI** les convertira :
|
||||
|
||||
```Python hl_lines="9"
|
||||
{!../../docs_src/query_params/tutorial003.py!}
|
||||
```
|
||||
{* ../../docs_src/query_params/tutorial003.py hl[9] *}
|
||||
|
||||
Avec ce code, en allant sur :
|
||||
|
||||
@@ -131,9 +125,7 @@ Et vous n'avez pas besoin de les déclarer dans un ordre spécifique.
|
||||
|
||||
Ils seront détectés par leurs noms :
|
||||
|
||||
```Python hl_lines="8 10"
|
||||
{!../../docs_src/query_params/tutorial004.py!}
|
||||
```
|
||||
{* ../../docs_src/query_params/tutorial004.py hl[8,10] *}
|
||||
|
||||
## Paramètres de requête requis
|
||||
|
||||
@@ -143,9 +135,7 @@ Si vous ne voulez pas leur donner de valeur par défaut mais juste les rendre op
|
||||
|
||||
Mais si vous voulez rendre un paramètre de requête obligatoire, vous pouvez juste ne pas y affecter de valeur par défaut :
|
||||
|
||||
```Python hl_lines="6-7"
|
||||
{!../../docs_src/query_params/tutorial005.py!}
|
||||
```
|
||||
{* ../../docs_src/query_params/tutorial005.py hl[6:7] *}
|
||||
|
||||
Ici le paramètre `needy` est un paramètre requis (ou obligatoire) de type `str`.
|
||||
|
||||
@@ -189,9 +179,7 @@ http://127.0.0.1:8000/items/foo-item?needy=sooooneedy
|
||||
|
||||
Et bien sur, vous pouvez définir certains paramètres comme requis, certains avec des valeurs par défaut et certains entièrement optionnels :
|
||||
|
||||
```Python hl_lines="10"
|
||||
{!../../docs_src/query_params/tutorial006.py!}
|
||||
```
|
||||
{* ../../docs_src/query_params/tutorial006.py hl[10] *}
|
||||
|
||||
Ici, on a donc 3 paramètres de requête :
|
||||
|
||||
|
||||
@@ -94,7 +94,7 @@ FastAPI היא תשתית רשת מודרנית ומהירה (ביצועים ג
|
||||
|
||||
"_Honestly, what you've built looks super solid and polished. In many ways, it's what I wanted **Hug** to be - it's really inspiring to see someone build that._"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Timothy Crosley - <strong><a href="https://www.hug.rest/" target="_blank">Hug</a> creator</strong> <a href="https://news.ycombinator.com/item?id=19455465" target="_blank"><small>(ref)</small></a></div>
|
||||
<div style="text-align: right; margin-right: 10%;">Timothy Crosley - <strong><a href="https://github.com/hugapi/hug" target="_blank">Hug</a> creator</strong> <a href="https://news.ycombinator.com/item?id=19455465" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -87,7 +87,7 @@ Kulcs funkciók:
|
||||
|
||||
"_Honestly, what you've built looks super solid and polished. In many ways, it's what I wanted **Hug** to be - it's really inspiring to see someone build that._"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Timothy Crosley - <strong><a href="https://www.hug.rest/" target="_blank">Hug</a> creator</strong> <a href="https://news.ycombinator.com/item?id=19455465" target="_blank"><small>(ref)</small></a></div>
|
||||
<div style="text-align: right; margin-right: 10%;">Timothy Crosley - <strong><a href="https://github.com/hugapi/hug" target="_blank">Hug</a> creator</strong> <a href="https://news.ycombinator.com/item?id=19455465" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -84,7 +84,7 @@ Le sue caratteristiche principali sono:
|
||||
|
||||
"_Honestly, what you've built looks super solid and polished. In many ways, it's what I wanted **Hug** to be - it's really inspiring to see someone build that._"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Timothy Crosley - <strong><a href="https://www.hug.rest/" target="_blank">Hug</a> creator</strong> <a href="https://news.ycombinator.com/item?id=19455465" target="_blank"><small>(ref)</small></a></div>
|
||||
<div style="text-align: right; margin-right: 10%;">Timothy Crosley - <strong><a href="https://github.com/hugapi/hug" target="_blank">Hug</a> creator</strong> <a href="https://news.ycombinator.com/item?id=19455465" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -91,7 +91,7 @@ FastAPI は、Pythonの標準である型ヒントに基づいてPython 以降
|
||||
|
||||
"_正直、超堅実で洗練されているように見えます。いろんな意味で、それは私がハグしたかったものです。_"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Timothy Crosley - <strong><a href="https://www.hug.rest/" target="_blank">Hug</a> creator</strong> <a href="https://news.ycombinator.com/item?id=19455465" target="_blank"><small>(ref)</small></a></div>
|
||||
<div style="text-align: right; margin-right: 10%;">Timothy Crosley - <strong><a href="https://github.com/hugapi/hug" target="_blank">Hug</a> creator</strong> <a href="https://news.ycombinator.com/item?id=19455465" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
|
||||
34
docs/ko/docs/benchmarks.md
Normal file
34
docs/ko/docs/benchmarks.md
Normal file
@@ -0,0 +1,34 @@
|
||||
# 벤치마크
|
||||
|
||||
독립적인 TechEmpower 벤치마크에 따르면 **FastAPI** 애플리케이션이 Uvicorn을 사용하여 <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">가장 빠른 Python 프레임워크 중 하나</a>로 실행되며, Starlette와 Uvicorn 자체(내부적으로 FastAPI가 사용하는 도구)보다 조금 아래에 위치합니다.
|
||||
|
||||
그러나 벤치마크와 비교를 확인할 때 다음 사항을 염두에 두어야 합니다.
|
||||
|
||||
## 벤치마크와 속도
|
||||
|
||||
벤치마크를 확인할 때, 일반적으로 여러 가지 유형의 도구가 동등한 것으로 비교되는 것을 볼 수 있습니다.
|
||||
|
||||
특히, Uvicorn, Starlette, FastAPI가 함께 비교되는 경우가 많습니다(다른 여러 도구와 함께).
|
||||
|
||||
도구가 해결하는 문제가 단순할수록 성능이 더 좋아집니다. 그리고 대부분의 벤치마크는 도구가 제공하는 추가 기능을 테스트하지 않습니다.
|
||||
|
||||
계층 구조는 다음과 같습니다:
|
||||
|
||||
* **Uvicorn**: ASGI 서버
|
||||
* **Starlette**: (Uvicorn 사용) 웹 마이크로 프레임워크
|
||||
* **FastAPI**: (Starlette 사용) API 구축을 위한 데이터 검증 등 여러 추가 기능이 포함된 API 마이크로 프레임워크
|
||||
|
||||
* **Uvicorn**:
|
||||
* 서버 자체 외에는 많은 추가 코드가 없기 때문에 최고의 성능을 발휘합니다.
|
||||
* 직접 Uvicorn으로 응용 프로그램을 작성하지는 않을 것입니다. 즉, 사용자의 코드에는 적어도 Starlette(또는 **FastAPI**)에서 제공하는 모든 코드가 포함되어야 합니다. 그렇게 하면 최종 응용 프로그램은 프레임워크를 사용하고 앱 코드와 버그를 최소화하는 것과 동일한 오버헤드를 갖게 됩니다.
|
||||
* Uvicorn을 비교할 때는 Daphne, Hypercorn, uWSGI 등의 응용 프로그램 서버와 비교하세요.
|
||||
* **Starlette**:
|
||||
* Uvicorn 다음으로 좋은 성능을 발휘합니다. 사실 Starlette는 Uvicorn을 사용하여 실행됩니다. 따라서 더 많은 코드를 실행해야 하기 때문에 Uvicorn보다 "느려질" 수밖에 없습니다.
|
||||
* 하지만 경로 기반 라우팅 등 간단한 웹 응용 프로그램을 구축할 수 있는 도구를 제공합니다.
|
||||
* Starlette를 비교할 때는 Sanic, Flask, Django 등의 웹 프레임워크(또는 마이크로 프레임워크)와 비교하세요.
|
||||
* **FastAPI**:
|
||||
* Starlette가 Uvicorn을 사용하므로 Uvicorn보다 빨라질 수 없는 것과 마찬가지로, **FastAPI**는 Starlette를 사용하므로 더 빠를 수 없습니다.
|
||||
* FastAPI는 Starlette에 추가적으로 더 많은 기능을 제공합니다. API를 구축할 때 거의 항상 필요한 데이터 검증 및 직렬화와 같은 기능들이 포함되어 있습니다. 그리고 이를 사용하면 문서 자동화 기능도 제공됩니다(문서 자동화는 응용 프로그램 실행 시 오버헤드를 추가하지 않고 시작 시 생성됩니다).
|
||||
* FastAPI를 사용하지 않고 직접 Starlette(또는 Sanic, Flask, Responder 등)를 사용했다면 데이터 검증 및 직렬화를 직접 구현해야 합니다. 따라서 최종 응용 프로그램은 FastAPI를 사용한 것과 동일한 오버헤드를 가지게 될 것입니다. 많은 경우 데이터 검증 및 직렬화가 응용 프로그램에서 작성된 코드 중 가장 많은 부분을 차지합니다.
|
||||
* 따라서 FastAPI를 사용함으로써 개발 시간, 버그, 코드 라인을 줄일 수 있으며, FastAPI를 사용하지 않았을 때와 동일하거나 더 나은 성능을 얻을 수 있습니다(코드에서 모두 구현해야 하기 때문에).
|
||||
* FastAPI를 비교할 때는 Flask-apispec, NestJS, Molten 등 데이터 검증, 직렬화 및 문서화가 통합된 자동 데이터 검증, 직렬화 및 문서화를 제공하는 웹 응용 프로그램 프레임워크(또는 도구 집합)와 비교하세요.
|
||||
@@ -93,7 +93,7 @@ De belangrijkste kenmerken zijn:
|
||||
|
||||
"_Wat je hebt gebouwd ziet er echt super solide en gepolijst uit. In veel opzichten is het wat ik wilde dat **Hug** kon zijn - het is echt inspirerend om iemand dit te zien bouwen._"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Timothy Crosley - <strong><a href="https://www.hug.rest/" target="_blank">Hug</a> creator</strong> <a href="https://news.ycombinator.com/item?id=19455465" target="_blank"><small>(ref)</small></a></div>
|
||||
<div style="text-align: right; margin-right: 10%;">Timothy Crosley - <strong><a href="https://github.com/hugapi/hug" target="_blank">Hug</a> creator</strong> <a href="https://news.ycombinator.com/item?id=19455465" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -90,7 +90,7 @@ Kluczowe cechy:
|
||||
|
||||
"_Honestly, what you've built looks super solid and polished. In many ways, it's what I wanted **Hug** to be - it's really inspiring to see someone build that._"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Timothy Crosley - <strong><a href="https://www.hug.rest/" target="_blank">Hug</a> creator</strong> <a href="https://news.ycombinator.com/item?id=19455465" target="_blank"><small>(ref)</small></a></div>
|
||||
<div style="text-align: right; margin-right: 10%;">Timothy Crosley - <strong><a href="https://github.com/hugapi/hug" target="_blank">Hug</a> creator</strong> <a href="https://news.ycombinator.com/item?id=19455465" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -2,9 +2,7 @@
|
||||
|
||||
Najprostszy plik FastAPI może wyglądać tak:
|
||||
|
||||
```Python
|
||||
{!../../docs_src/first_steps/tutorial001.py!}
|
||||
```
|
||||
{* ../../docs_src/first_steps/tutorial001.py *}
|
||||
|
||||
Skopiuj to do pliku `main.py`.
|
||||
|
||||
@@ -133,9 +131,7 @@ Możesz go również użyć do automatycznego generowania kodu dla klientów, kt
|
||||
|
||||
### Krok 1: zaimportuj `FastAPI`
|
||||
|
||||
```Python hl_lines="1"
|
||||
{!../../docs_src/first_steps/tutorial001.py!}
|
||||
```
|
||||
{* ../../docs_src/first_steps/tutorial001.py hl[1] *}
|
||||
|
||||
`FastAPI` jest klasą, która zapewnia wszystkie funkcjonalności Twojego API.
|
||||
|
||||
@@ -149,9 +145,7 @@ Oznacza to, że możesz korzystać ze wszystkich funkcjonalności <a href="https
|
||||
|
||||
### Krok 2: utwórz instancję `FastAPI`
|
||||
|
||||
```Python hl_lines="3"
|
||||
{!../../docs_src/first_steps/tutorial001.py!}
|
||||
```
|
||||
{*../../docs_src/first_steps/tutorial001.py hl[3] *}
|
||||
|
||||
Zmienna `app` będzie tutaj "instancją" klasy `FastAPI`.
|
||||
|
||||
@@ -171,9 +165,7 @@ $ uvicorn main:app --reload
|
||||
|
||||
Jeśli stworzysz swoją aplikację, np.:
|
||||
|
||||
```Python hl_lines="3"
|
||||
{!../../docs_src/first_steps/tutorial002.py!}
|
||||
```
|
||||
{* ../../docs_src/first_steps/tutorial002.py hl[3] *}
|
||||
|
||||
I umieścisz to w pliku `main.py`, to będziesz mógł tak wywołać `uvicorn`:
|
||||
|
||||
@@ -250,9 +242,7 @@ Będziemy je również nazywali "**operacjami**".
|
||||
|
||||
#### Zdefiniuj *dekorator operacji na ścieżce*
|
||||
|
||||
```Python hl_lines="6"
|
||||
{!../../docs_src/first_steps/tutorial001.py!}
|
||||
```
|
||||
{* ../../docs_src/first_steps/tutorial001.py hl[6] *}
|
||||
|
||||
`@app.get("/")` mówi **FastAPI** że funkcja poniżej odpowiada za obsługę żądań, które trafiają do:
|
||||
|
||||
@@ -306,9 +296,7 @@ To jest nasza "**funkcja obsługująca ścieżkę**":
|
||||
* **operacja**: to `get`.
|
||||
* **funkcja**: to funkcja poniżej "dekoratora" (poniżej `@app.get("/")`).
|
||||
|
||||
```Python hl_lines="7"
|
||||
{!../../docs_src/first_steps/tutorial001.py!}
|
||||
```
|
||||
{* ../../docs_src/first_steps/tutorial001.py hl[7] *}
|
||||
|
||||
Jest to funkcja Python.
|
||||
|
||||
@@ -320,9 +308,7 @@ W tym przypadku jest to funkcja "asynchroniczna".
|
||||
|
||||
Możesz również zdefiniować to jako normalną funkcję zamiast `async def`:
|
||||
|
||||
```Python hl_lines="7"
|
||||
{!../../docs_src/first_steps/tutorial003.py!}
|
||||
```
|
||||
{* ../../docs_src/first_steps/tutorial003.py hl[7] *}
|
||||
|
||||
/// note
|
||||
|
||||
@@ -332,9 +318,7 @@ Jeśli nie znasz różnicy, sprawdź [Async: *"In a hurry?"*](../async.md#in-a-h
|
||||
|
||||
### Krok 5: zwróć zawartość
|
||||
|
||||
```Python hl_lines="8"
|
||||
{!../../docs_src/first_steps/tutorial001.py!}
|
||||
```
|
||||
{* ../../docs_src/first_steps/tutorial001.py hl[8] *}
|
||||
|
||||
Możesz zwrócić `dict`, `list`, pojedynczą wartość jako `str`, `int`, itp.
|
||||
|
||||
|
||||
@@ -18,9 +18,7 @@ Nesse caso, o caminho original `/app` seria servido em `/api/v1/app`.
|
||||
|
||||
Embora todo o seu código esteja escrito assumindo que existe apenas `/app`.
|
||||
|
||||
```Python hl_lines="6"
|
||||
{!../../docs_src/behind_a_proxy/tutorial001.py!}
|
||||
```
|
||||
{* ../../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`.
|
||||
|
||||
@@ -98,9 +96,7 @@ Você pode obter o `root_path` atual usado pela sua aplicação para cada solici
|
||||
|
||||
Aqui estamos incluindo ele na mensagem apenas para fins de demonstração.
|
||||
|
||||
```Python hl_lines="8"
|
||||
{!../../docs_src/behind_a_proxy/tutorial001.py!}
|
||||
```
|
||||
{* ../../docs_src/behind_a_proxy/tutorial001.py hl[8] *}
|
||||
|
||||
Então, se você iniciar o Uvicorn com:
|
||||
|
||||
@@ -127,9 +123,7 @@ A resposta seria algo como:
|
||||
|
||||
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:
|
||||
|
||||
```Python hl_lines="3"
|
||||
{!../../docs_src/behind_a_proxy/tutorial002.py!}
|
||||
```
|
||||
{* ../../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.
|
||||
|
||||
@@ -309,9 +303,7 @@ Se você passar uma lista personalizada de `servers` e houver um `root_path` (po
|
||||
|
||||
Por exemplo:
|
||||
|
||||
```Python hl_lines="4-7"
|
||||
{!../../docs_src/behind_a_proxy/tutorial003.py!}
|
||||
```
|
||||
{* ../../docs_src/behind_a_proxy/tutorial003.py hl[4:7] *}
|
||||
|
||||
Gerará um OpenAPI schema como:
|
||||
|
||||
@@ -358,9 +350,7 @@ A interface de documentação interagirá com o servidor que você selecionar.
|
||||
|
||||
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`:
|
||||
|
||||
```Python hl_lines="9"
|
||||
{!../../docs_src/behind_a_proxy/tutorial004.py!}
|
||||
```
|
||||
{* ../../docs_src/behind_a_proxy/tutorial004.py hl[9] *}
|
||||
|
||||
e então ele não será incluído no OpenAPI schema.
|
||||
|
||||
|
||||
101
docs/pt/docs/advanced/dataclasses.md
Normal file
101
docs/pt/docs/advanced/dataclasses.md
Normal file
@@ -0,0 +1,101 @@
|
||||
# Usando Dataclasses
|
||||
|
||||
FastAPI é construído em cima do **Pydantic**, e eu tenho mostrado como usar modelos Pydantic para declarar requisições e respostas.
|
||||
|
||||
Mas o FastAPI também suporta o uso de <a href="https://docs.python.org/3/library/dataclasses.html" class="external-link" target="_blank">`dataclasses`</a> da mesma forma:
|
||||
|
||||
```Python hl_lines="1 7-12 19-20"
|
||||
{!../../docs_src/dataclasses/tutorial001.py!}
|
||||
```
|
||||
|
||||
Isso ainda é suportado graças ao **Pydantic**, pois ele tem <a href="https://docs.pydantic.dev/latest/concepts/dataclasses/#use-of-stdlib-dataclasses-with-basemodel" class="external-link" target="_blank">suporte interno para `dataclasses`</a>.
|
||||
|
||||
Então, mesmo com o código acima que não usa Pydantic explicitamente, o FastAPI está usando Pydantic para converter essas dataclasses padrão para a versão do Pydantic.
|
||||
|
||||
E claro, ele suporta o mesmo:
|
||||
|
||||
* validação de dados
|
||||
* serialização de dados
|
||||
* documentação de dados, etc.
|
||||
|
||||
Isso funciona da mesma forma que com os modelos Pydantic. E na verdade é alcançado da mesma maneira por baixo dos panos, usando Pydantic.
|
||||
|
||||
/// info | Informação
|
||||
|
||||
Lembre-se de que dataclasses não podem fazer tudo o que os modelos Pydantic podem fazer.
|
||||
|
||||
Então, você ainda pode precisar usar modelos Pydantic.
|
||||
|
||||
Mas se você tem um monte de dataclasses por aí, este é um truque legal para usá-las para alimentar uma API web usando FastAPI. 🤓
|
||||
|
||||
///
|
||||
|
||||
## Dataclasses em `response_model`
|
||||
|
||||
Você também pode usar `dataclasses` no parâmetro `response_model`:
|
||||
|
||||
```Python hl_lines="1 7-13 19"
|
||||
{!../../docs_src/dataclasses/tutorial002.py!}
|
||||
```
|
||||
|
||||
A dataclass será automaticamente convertida para uma dataclass Pydantic.
|
||||
|
||||
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
|
||||
|
||||
Você também pode combinar `dataclasses` com outras anotações de tipo para criar estruturas de dados aninhadas.
|
||||
|
||||
Em alguns casos, você ainda pode ter que usar a versão do Pydantic das `dataclasses`. Por exemplo, se você tiver erros com a documentação da API gerada automaticamente.
|
||||
|
||||
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!}
|
||||
```
|
||||
|
||||
1. Ainda importamos `field` das `dataclasses` padrão.
|
||||
|
||||
2. `pydantic.dataclasses` é um substituto direto para `dataclasses`.
|
||||
|
||||
3. A dataclass `Author` inclui uma lista de dataclasses `Item`.
|
||||
|
||||
4. A dataclass `Author` é usada como o parâmetro `response_model`.
|
||||
|
||||
5. Você pode usar outras anotações de tipo padrão com dataclasses como o corpo da requisição.
|
||||
|
||||
Neste caso, é uma lista de dataclasses `Item`.
|
||||
|
||||
6. Aqui estamos retornando um dicionário que contém `items`, que é uma lista de dataclasses.
|
||||
|
||||
O FastAPI ainda é capaz de <abbr title="converter os dados para um formato que pode ser transmitido">serializar</abbr> os dados para JSON.
|
||||
|
||||
7. Aqui o `response_model` está usando uma anotação de tipo de uma lista de dataclasses `Author`.
|
||||
|
||||
Novamente, você pode combinar `dataclasses` com anotações de tipo padrão.
|
||||
|
||||
8. Note que esta *função de operação de rota* usa `def` regular em vez de `async def`.
|
||||
|
||||
Como sempre, no FastAPI você pode combinar `def` e `async def` conforme necessário.
|
||||
|
||||
Se você precisar de uma atualização sobre quando usar qual, confira a seção _"Com pressa?"_ na documentação sobre [`async` e `await`](../async.md#in-a-hurry){.internal-link target=_blank}.
|
||||
|
||||
9. Esta *função de operação de rota* não está retornando dataclasses (embora pudesse), mas uma lista de dicionários com dados internos.
|
||||
|
||||
O FastAPI usará o parâmetro `response_model` (que inclui dataclasses) para converter a resposta.
|
||||
|
||||
Você pode combinar `dataclasses` com outras anotações de tipo em muitas combinações diferentes para formar estruturas de dados complexas.
|
||||
|
||||
Confira as dicas de anotação no código acima para ver mais detalhes específicos.
|
||||
|
||||
## Saiba Mais
|
||||
|
||||
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
|
||||
|
||||
Isso está disponível desde a versão `0.67.0` do FastAPI. 🔖
|
||||
55
docs/pt/docs/advanced/response-cookies.md
Normal file
55
docs/pt/docs/advanced/response-cookies.md
Normal file
@@ -0,0 +1,55 @@
|
||||
# Cookies de Resposta
|
||||
|
||||
## Usando um parâmetro `Response`
|
||||
|
||||
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*.
|
||||
|
||||
```Python hl_lines="1 8-9"
|
||||
{!../../docs_src/response_cookies/tutorial002.py!}
|
||||
```
|
||||
|
||||
Em seguida, você pode retornar qualquer objeto que precise, como normalmente faria (um `dict`, um modelo de banco de dados, etc).
|
||||
|
||||
E se você declarou um `response_model`, ele ainda será usado para filtrar e converter o objeto que você retornou.
|
||||
|
||||
**FastAPI** usará essa resposta *temporária* para extrair os cookies (também os cabeçalhos e código de status) e os colocará na resposta final que contém o valor que você retornou, filtrado por qualquer `response_model`.
|
||||
|
||||
Você também pode declarar o parâmetro `Response` em dependências e definir cookies (e cabeçalhos) nelas.
|
||||
|
||||
## Retornando uma `Response` diretamente
|
||||
|
||||
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}.
|
||||
|
||||
Então, defina os cookies nela e a retorne:
|
||||
|
||||
```Python hl_lines="10-12"
|
||||
{!../../docs_src/response_cookies/tutorial001.py!}
|
||||
```
|
||||
|
||||
/// tip | Dica
|
||||
|
||||
Lembre-se de que se você retornar uma resposta diretamente em vez de usar o parâmetro `Response`, FastAPI a retornará diretamente.
|
||||
|
||||
Portanto, você terá que garantir que seus dados sejam do tipo correto. E.g. será compatível com JSON se você estiver retornando um `JSONResponse`.
|
||||
|
||||
E também que você não esteja enviando nenhum dado que deveria ter sido filtrado por um `response_model`.
|
||||
|
||||
///
|
||||
|
||||
### Mais informações
|
||||
|
||||
/// note | "Detalhes Técnicos"
|
||||
|
||||
Você também poderia usar `from starlette.responses import Response` ou `from starlette.responses import JSONResponse`.
|
||||
|
||||
**FastAPI** fornece as mesmas `starlette.responses` em `fastapi.responses` apenas como uma conveniência para você, o desenvolvedor. Mas a maioria das respostas disponíveis vem diretamente do Starlette.
|
||||
|
||||
E como o `Response` pode ser usado frequentemente para definir cabeçalhos e cookies, o **FastAPI** também o fornece em `fastapi.Response`.
|
||||
|
||||
///
|
||||
|
||||
Para ver todos os parâmetros e opções disponíveis, verifique a <a href="https://www.starlette.io/responses/#set-cookie" class="external-link" target="_blank">documentação no Starlette</a>.
|
||||
45
docs/pt/docs/advanced/response-headers.md
Normal file
45
docs/pt/docs/advanced/response-headers.md
Normal file
@@ -0,0 +1,45 @@
|
||||
# Cabeçalhos de resposta
|
||||
|
||||
## Usando um parâmetro `Response`
|
||||
|
||||
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*.
|
||||
|
||||
```Python hl_lines="1 7-8"
|
||||
{!../../docs_src/response_headers/tutorial002.py!}
|
||||
```
|
||||
|
||||
Em seguida você pode retornar qualquer objeto que precisar, da maneira que faria normalmente (um `dict`, um modelo de banco de dados, etc.).
|
||||
|
||||
Se você declarou um `response_model`, ele ainda será utilizado para filtrar e converter o objeto que você retornou.
|
||||
|
||||
**FastAPI** usará essa resposta *temporária* para extrair os cabeçalhos (cookies e código de status também) e os colocará na resposta final que contém o valor que você retornou, filtrado por qualquer `response_model`.
|
||||
|
||||
Você também pode declarar o parâmetro `Response` em dependências e definir cabeçalhos (e cookies) nelas.
|
||||
|
||||
## Retornar uma `Response` diretamente
|
||||
|
||||
Você também pode adicionar cabeçalhos quando retornar uma `Response` diretamente.
|
||||
|
||||
Crie uma resposta conforme descrito em [Retornar uma resposta diretamente](response-directly.md){.internal-link target=_blank} e passe os cabeçalhos como um parâmetro adicional:
|
||||
|
||||
```Python hl_lines="10-12"
|
||||
{!../../docs_src/response_headers/tutorial001.py!}
|
||||
```
|
||||
|
||||
/// note | "Detalhes técnicos"
|
||||
|
||||
Você também pode usar `from starlette.responses import Response` ou `from starlette.responses import JSONResponse`.
|
||||
|
||||
**FastAPI** fornece as mesmas `starlette.responses` como `fastapi.responses` apenas como uma conveniência para você, desenvolvedor. Mas a maioria das respostas disponíveis vem diretamente do Starlette.
|
||||
|
||||
E como a `Response` pode ser usada frequentemente para definir cabeçalhos e cookies, **FastAPI** também a fornece em `fastapi.Response`.
|
||||
|
||||
///
|
||||
|
||||
## Cabeçalhos personalizados
|
||||
|
||||
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.io/middleware/#corsmiddleware" class="external-link" target="_blank">documentação de CORS do Starlette</a>.
|
||||
@@ -323,7 +323,7 @@ Isso na verdade inspirou a atualização de partes do Pydantic, para dar suporte
|
||||
|
||||
///
|
||||
|
||||
### <a href="https://www.hug.rest/" class="external-link" target="_blank">Hug</a>
|
||||
### <a href="https://github.com/hugapi/hug" class="external-link" target="_blank">Hug</a>
|
||||
|
||||
Hug foi um dos primeiros frameworks a implementar a declaração de tipos de parâmetros usando Python _type hints_. Isso foi uma ótima idéia que inspirou outras ferramentas a fazer o mesmo.
|
||||
|
||||
|
||||
@@ -1,414 +0,0 @@
|
||||
# Implantação
|
||||
|
||||
Implantar uma aplicação **FastAPI** é relativamente fácil.
|
||||
|
||||
Existem vários modos de realizar o _deploy_ dependendo de seu caso de uso específico e as ferramentas que você utiliza.
|
||||
|
||||
Você verá mais sobre alguns modos de fazer o _deploy_ nas próximas seções.
|
||||
|
||||
## Versões do FastAPI
|
||||
|
||||
**FastAPI** já está sendo utilizado em produção em muitas aplicações e sistemas. E a cobertura de teste é mantida a 100%. Mas seu desenvolvimento continua andando rapidamente.
|
||||
|
||||
Novos recursos são adicionados frequentemente, _bugs_ são corrigidos regularmente, e o código está continuamente melhorando.
|
||||
|
||||
É por isso que as versões atuais estão ainda no `0.x.x`, isso reflete que cada versão poderia ter potencialmente alterações que podem quebrar. Isso segue as convenções de <a href="https://semver.org/" class="external-link" target="_blank">Versionamento Semântico</a>.
|
||||
|
||||
Você pode criar aplicações para produção com **FastAPI** bem agora (e você provavelmente já faça isso por um tempo), você tem que ter certeza de utilizar uma versão que funcione corretamente com o resto do seu código.
|
||||
|
||||
### Anote sua versão `fastapi`
|
||||
|
||||
A primeira coisa que você deve fazer é "fixar" a versão do **FastAPI** que está utilizando para a última versão específica que você sabe que funciona corretamente para a sua aplicação.
|
||||
|
||||
Por exemplo, vamos dizer que você esteja utilizando a versão `0.45.0` no seu _app_.
|
||||
|
||||
Se você usa um arquivo `requirements.txt`, dá para especificar a versão assim:
|
||||
|
||||
```txt
|
||||
fastapi==0.45.0
|
||||
```
|
||||
|
||||
isso significa que você pode usar exatamente a versão `0.45.0`.
|
||||
|
||||
Ou você poderia fixar assim:
|
||||
|
||||
```txt
|
||||
fastapi>=0.45.0,<0.46.0
|
||||
```
|
||||
|
||||
o que significa que você pode usar as versões `0.45.0` ou acima, mas menor que `0.46.0`. Por exemplo, a versão `0.45.2` poderia ser aceita.
|
||||
|
||||
Se você usa qualquer outra ferramenta para gerenciar suas instalações, como Poetry, Pipenv ou outro, todos terão um modo que você possa usar para definir versões específicas para seus pacotes.
|
||||
|
||||
### Versões disponíveis
|
||||
|
||||
Você pode ver as versões disponíveis (por exemplo, para verificar qual é a versão atual) nas [Notas de Lançamento](release-notes.md){.internal-link target=_blank}.
|
||||
|
||||
### Sobre as versões
|
||||
|
||||
Seguindo as convenções do Versionamento Semântico, qualquer versão abaixo de `1.0.0` pode potencialmente adicionar mudanças que quebrem.
|
||||
|
||||
FastAPI também segue a convenção que qualquer versão de _"PATCH"_ seja para ajustes de _bugs_ e mudanças que não quebrem a aplicação.
|
||||
|
||||
/// tip
|
||||
|
||||
O _"PATCH"_ é o último número, por exemplo, em `0.2.3`, a versão do _PATCH_ é `3`.
|
||||
|
||||
///
|
||||
|
||||
Então, você poderia ser capaz de fixar para uma versão como:
|
||||
|
||||
```txt
|
||||
fastapi>=0.45.0,<0.46.0
|
||||
```
|
||||
|
||||
Mudanças que quebram e novos recursos são adicionados em versões _"MINOR"_.
|
||||
|
||||
/// tip
|
||||
|
||||
O _"MINOR"_ é o número do meio, por exemplo, em `0.2.3`, a versão _MINOR_ é `2`.
|
||||
|
||||
///
|
||||
|
||||
### Atualizando as versões FastAPI
|
||||
|
||||
Você pode adicionar testes em sua aplicação.
|
||||
|
||||
Com o **FastAPI** é muito fácil (graças ao Starlette), verifique a documentação: [Testando](tutorial/testing.md){.internal-link target=_blank}
|
||||
|
||||
Após você ter os testes, então você pode fazer o _upgrade_ da versão **FastAPI** para uma mais recente, e ter certeza que todo seu código esteja funcionando corretamente rodando seus testes.
|
||||
|
||||
Se tudo estiver funcionando, ou após você fazer as alterações necessárias, e todos seus testes estiverem passando, então você poderá fixar o `fastapi` para a versão mais recente.
|
||||
|
||||
### Sobre Starlette
|
||||
|
||||
Você não deve fixar a versão do `starlette`.
|
||||
|
||||
Versões diferentes do **FastAPI** irão utilizar uma versão mais nova específica do Starlette.
|
||||
|
||||
Então, você pode deixar que o **FastAPI** use a versão correta do Starlette.
|
||||
|
||||
### Sobre Pydantic
|
||||
|
||||
Pydantic inclui os testes para **FastAPI** em seus próprios testes, então novas versões do Pydantic (acima de `1.0.0`) são sempre compatíveis com FastAPI.
|
||||
|
||||
Você pode fixar o Pydantic para qualquer versão acima de `1.0.0` e abaixo de `2.0.0` que funcionará.
|
||||
|
||||
Por exemplo:
|
||||
|
||||
```txt
|
||||
pydantic>=1.2.0,<2.0.0
|
||||
```
|
||||
|
||||
## Docker
|
||||
|
||||
Nessa seção você verá instruções e _links_ para guias de saber como:
|
||||
|
||||
* Fazer uma imagem/container da sua aplicação **FastAPI** com máxima performance. Em aproximadamente **5 min**.
|
||||
* (Opcionalmente) entender o que você, como desenvolvedor, precisa saber sobre HTTPS.
|
||||
* Inicializar um _cluster_ Docker Swarm Mode com HTTPS automático, mesmo em um simples servidor de $5 dólares/mês. Em aproximadamente **20 min**.
|
||||
* Gere e implante uma aplicação **FastAPI** completa, usando seu _cluster_ Docker Swarm, com HTTPS etc. Em aproxiamadamente **10 min**.
|
||||
|
||||
Você pode usar <a href="https://www.docker.com/" class="external-link" target="_blank">**Docker**</a> para implantação. Ele tem várias vantagens como segurança, replicabilidade, desenvolvimento simplificado etc.
|
||||
|
||||
Se você está usando Docker, você pode utilizar a imagem Docker oficial:
|
||||
|
||||
### <a href="https://github.com/tiangolo/uvicorn-gunicorn-fastapi-docker" class="external-link" target="_blank">tiangolo/uvicorn-gunicorn-fastapi</a>
|
||||
|
||||
Essa imagem tem um mecanismo incluído de "auto-ajuste", para que você possa apenas adicionar seu código e ter uma alta performance automaticamente. E sem fazer sacrifícios.
|
||||
|
||||
Mas você pode ainda mudar e atualizar todas as configurações com variáveis de ambiente ou arquivos de configuração.
|
||||
|
||||
/// tip
|
||||
|
||||
Para ver todas as configurações e opções, vá para a página da imagem do Docker: <a href="https://github.com/tiangolo/uvicorn-gunicorn-fastapi-docker" class="external-link" target="_blank">tiangolo/uvicorn-gunicorn-fastapi</a>.
|
||||
|
||||
///
|
||||
|
||||
### Crie um `Dockerfile`
|
||||
|
||||
* Vá para o diretório de seu projeto.
|
||||
* Crie um `Dockerfile` com:
|
||||
|
||||
```Dockerfile
|
||||
FROM tiangolo/uvicorn-gunicorn-fastapi:python3.7
|
||||
|
||||
COPY ./app /app
|
||||
```
|
||||
|
||||
#### Grandes aplicações
|
||||
|
||||
Se você seguiu a seção sobre criação de [Grandes Aplicações com Múltiplos Arquivos](tutorial/bigger-applications.md){.internal-link target=_blank}, seu `Dockerfile` poderia parecer como:
|
||||
|
||||
```Dockerfile
|
||||
FROM tiangolo/uvicorn-gunicorn-fastapi:python3.7
|
||||
|
||||
COPY ./app /app/app
|
||||
```
|
||||
|
||||
#### Raspberry Pi e outras arquiteturas
|
||||
|
||||
Se você estiver rodando Docker em um Raspberry Pi (que possui um processador ARM) ou qualquer outra arquitetura, você pode criar um `Dockerfile` do zero, baseado em uma imagem base Python (que é multi-arquitetural) e utilizar Uvicorn sozinho.
|
||||
|
||||
Nesse caso, seu `Dockerfile` poderia parecer assim:
|
||||
|
||||
```Dockerfile
|
||||
FROM python:3.7
|
||||
|
||||
RUN pip install fastapi uvicorn
|
||||
|
||||
EXPOSE 80
|
||||
|
||||
COPY ./app /app
|
||||
|
||||
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80"]
|
||||
```
|
||||
|
||||
### Crie o código **FastAPI**
|
||||
|
||||
* Crie um diretório `app` e entre nele.
|
||||
* Crie um arquivo `main.py` com:
|
||||
|
||||
```Python
|
||||
from fastapi import FastAPI
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
|
||||
@app.get("/")
|
||||
def read_root():
|
||||
return {"Hello": "World"}
|
||||
|
||||
|
||||
@app.get("/items/{item_id}")
|
||||
def read_item(item_id: int, q: str = None):
|
||||
return {"item_id": item_id, "q": q}
|
||||
```
|
||||
|
||||
* Você deve ter uma estrutura de diretórios assim:
|
||||
|
||||
```
|
||||
.
|
||||
├── app
|
||||
│ └── main.py
|
||||
└── Dockerfile
|
||||
```
|
||||
|
||||
### Construa a imagem Docker
|
||||
|
||||
* Vá para o diretório do projeto (onde seu `Dockerfile` está, contendo seu diretório `app`.
|
||||
* Construa sua imagem FastAPI:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ docker build -t myimage .
|
||||
|
||||
---> 100%
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
### Inicie o container Docker
|
||||
|
||||
* Rode um container baseado em sua imagem:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ docker run -d --name mycontainer -p 80:80 myimage
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
Agora você tem um servidor FastAPI otimizado em um container Docker. Auto-ajustado para seu servidor atual (e número de núcleos de CPU).
|
||||
|
||||
### Verifique
|
||||
|
||||
Você deve ser capaz de verificar na URL de seu container Docker, por exemplo: <a href="http://192.168.99.100/items/5?q=somequery" class="external-link" target="_blank">http://192.168.99.100/items/5?q=somequery</a> ou <a href="http://127.0.0.1/items/5?q=somequery" class="external-link" target="_blank">http://127.0.0.1/items/5?q=somequery</a> (ou equivalente, usando seu _host_ Docker).
|
||||
|
||||
Você verá algo como:
|
||||
|
||||
```JSON
|
||||
{"item_id": 5, "q": "somequery"}
|
||||
```
|
||||
|
||||
### API interativa de documetação
|
||||
|
||||
Agora você pode ir para <a href="http://192.168.99.100/docs" class="external-link" target="_blank">http://192.168.99.100/docs</a> ou <a href="http://127.0.0.1/docs" class="external-link" target="_blank">http://127.0.0.1/docs</a> (ou equivalente, usando seu _host_ Docker).
|
||||
|
||||
Você verá a API interativa de documentação (fornecida por <a href="https://github.com/swagger-api/swagger-ui" class="external-link" target="_blank">Swagger UI</a>):
|
||||
|
||||

|
||||
|
||||
### APIs alternativas de documentação
|
||||
|
||||
E você pode também ir para <a href="http://192.168.99.100/redoc" class="external-link" target="_blank">http://192.168.99.100/redoc</a> ou <a href="http://127.0.0.1/redoc" class="external-link" target="_blank">http://127.0.0.1/redoc</a> (ou equivalente, usando seu _host_ Docker).
|
||||
|
||||
Você verá a documentação automática alternativa (fornecida por <a href="https://github.com/Rebilly/ReDoc" class="external-link" target="_blank">ReDoc</a>):
|
||||
|
||||

|
||||
|
||||
## HTTPS
|
||||
|
||||
### Sobre HTTPS
|
||||
|
||||
É fácil assumir que HTTPS seja algo que esteja apenas "habilitado" ou não.
|
||||
|
||||
Mas ele é um pouquinho mais complexo do que isso.
|
||||
|
||||
/// tip
|
||||
|
||||
Se você está com pressa ou não se importa, continue na próxima seção com instruções passo a passo para configurar tudo.
|
||||
|
||||
///
|
||||
|
||||
Para aprender o básico de HTTPS, pela perspectiva de um consumidor, verifique <a href="https://howhttps.works/" class="external-link" target="_blank">https://howhttps.works/</a>.
|
||||
|
||||
Agora, pela perspectiva de um desenvolvedor, aqui estão algumas coisas para se ter em mente enquanto se pensa sobre HTTPS:
|
||||
|
||||
* Para HTTPS, o servidor precisa ter "certificados" gerados por terceiros.
|
||||
* Esses certificados são na verdade adquiridos por terceiros, não "gerados".
|
||||
* Certificados tem um prazo de uso.
|
||||
* Eles expiram.
|
||||
* E então eles precisam ser renovados, adquiridos novamente por terceiros.
|
||||
* A encriptação da conexão acontece no nível TCP.
|
||||
* TCP é uma camada abaixo do HTTP.
|
||||
* Então, o controle de certificado e encriptação é feito antes do HTTP.
|
||||
* TCP não conhece nada sobre "domínios". Somente sobre endereços IP.
|
||||
* A informação sobre o domínio requisitado vai nos dados HTTP.
|
||||
* Os certificados HTTPS "certificam" um certo domínio, mas o protocolo e a encriptação acontecem no nível TCP, antes de saber qual domínio está sendo lidado.
|
||||
* Por padrão, isso significa que você pode ter somente um certificado HTTPS por endereço IP.
|
||||
* Não importa quão grande é seu servidor ou quão pequena cada aplicação que você tenha possar ser.
|
||||
* No entanto, existe uma solução para isso.
|
||||
* Existe uma extensão para o protocolo TLS (o que controla a encriptação no nível TCP, antes do HTTP) chamada <a href="https://en.wikipedia.org/wiki/Server_Name_Indication" class="external-link" target="_blank"><abbr title="Server Name Indication">SNI</abbr></a>.
|
||||
* Essa extensão SNI permite um único servidor (com um único endereço IP) a ter vários certificados HTTPS e servir múltiplas aplicações/domínios HTTPS.
|
||||
* Para que isso funcione, um único componente (programa) rodando no servidor, ouvindo no endereço IP público, deve ter todos os certificados HTTPS no servidor.
|
||||
* Após obter uma conexão segura, o protocolo de comunicação ainda é HTTP.
|
||||
* O conteúdo está encriptado, mesmo embora ele esteja sendo enviado com o protocolo HTTP.
|
||||
|
||||
É uma prática comum ter um servidor HTTP/programa rodando no servidor (a máquina, _host_ etc.) e gerenciar todas as partes HTTP: enviar as requisições HTTP decriptadas para a aplicação HTTP rodando no mesmo servidor (a aplicação **FastAPI**, nesse caso), pega a resposta HTTP da aplicação, encripta utilizando o certificado apropriado e enviando de volta para o cliente usando HTTPS. Esse servidor é frequentemente chamado <a href="https://en.wikipedia.org/wiki/TLS_termination_proxy" class="external-link" target="_blank">TLS _Termination Proxy_</a>.
|
||||
|
||||
### Vamos encriptar
|
||||
|
||||
Antes de encriptar, esses certificados HTTPS foram vendidos por terceiros de confiança.
|
||||
|
||||
O processo para adquirir um desses certificados costumava ser chato, exigia muita papelada e eram bem caros.
|
||||
|
||||
Mas então <a href="https://letsencrypt.org/" class="external-link" target="_blank">_Let's Encrypt_</a> foi criado.
|
||||
|
||||
É um projeto da Fundação Linux.Ele fornece certificados HTTPS de graça. De um jeito automatizado. Esses certificados utilizam todos os padrões de segurança criptográfica, e tem vida curta (cerca de 3 meses), para que a segurança seja melhor devido ao seu curto período de vida.
|
||||
|
||||
Os domínios são seguramente verificados e os certificados são gerados automaticamente. Isso também permite automatizar a renovação desses certificados.
|
||||
|
||||
A idéia é automatizar a aquisição e renovação desses certificados, para que você possa ter um HTTPS seguro, grátis, para sempre.
|
||||
|
||||
### Traefik
|
||||
|
||||
<a href="https://traefik.io/" class="external-link" target="_blank">Traefik</a> é um _proxy_ reverso / _load balancer_ de alta performance. Ele pode fazer o trabalho do _"TLS Termination Proxy"_ (à parte de outros recursos).
|
||||
|
||||
Ele tem integração com _Let's Encrypt_. Assim, ele pode controlar todas as partes HTTPS, incluindo a aquisição e renovação de certificados.
|
||||
|
||||
Ele também tem integrações com Docker. Assim, você pode declarar seus domínios em cada configuração de aplicação e leitura dessas configurações, gerando os certificados HTTPS e servindo o HTTPS para sua aplicação automaticamente, sem exigir qualquer mudança em sua configuração.
|
||||
|
||||
---
|
||||
|
||||
Com essas ferramentas e informações, continue com a próxima seção para combinar tudo.
|
||||
|
||||
## _Cluster_ de Docker Swarm Mode com Traefik e HTTPS
|
||||
|
||||
Você pode ter um _cluster_ de Docker Swarm Mode configurado em minutos (cerca de 20) com o Traefik controlando HTTPS (incluindo aquisição e renovação de certificados).
|
||||
|
||||
Utilizando o Docker Swarm Mode, você pode iniciar com um _"cluster"_ de apenas uma máquina (que pode até ser um servidor por 5 dólares / mês) e então você pode aumentar conforme a necessidade adicionando mais servidores.
|
||||
|
||||
Para configurar um _cluster_ Docker Swarm Mode com Traefik controlando HTTPS, siga essa orientação:
|
||||
|
||||
### <a href="https://medium.com/@tiangolo/docker-swarm-mode-and-traefik-for-a-https-cluster-20328dba6232" class="external-link" target="_blank">Docker Swarm Mode and Traefik for an HTTPS cluster</a>
|
||||
|
||||
### Faça o _deploy_ de uma aplicação FastAPI
|
||||
|
||||
O jeito mais fácil de configurar tudo pode ser utilizando o [Gerador de Projetos **FastAPI**](project-generation.md){.internal-link target=_blank}.
|
||||
|
||||
Ele é designado para ser integrado com esse _cluster_ Docker Swarm com Traefik e HTTPS descrito acima.
|
||||
|
||||
Você pode gerar um projeto em cerca de 2 minutos.
|
||||
|
||||
O projeto gerado tem instruções para fazer o _deploy_, fazendo isso leva outros 2 minutos.
|
||||
|
||||
## Alternativamente, faça o _deploy_ **FastAPI** sem Docker
|
||||
|
||||
Você pode fazer o _deploy_ do **FastAPI** diretamente sem o Docker também.
|
||||
|
||||
Você apenas precisa instalar um servidor ASGI compatível como:
|
||||
|
||||
//// tab | Uvicorn
|
||||
|
||||
* <a href="https://www.uvicorn.org/" class="external-link" target="_blank">Uvicorn</a>, um servidor ASGI peso leve, construído sobre uvloop e httptools.
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ pip install "uvicorn[standard]"
|
||||
|
||||
---> 100%
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
////
|
||||
|
||||
//// tab | Hypercorn
|
||||
|
||||
* <a href="https://github.com/pgjones/hypercorn" class="external-link" target="_blank">Hypercorn</a>, um servidor ASGI também compatível com HTTP/2.
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ pip install hypercorn
|
||||
|
||||
---> 100%
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
...ou qualquer outro servidor ASGI.
|
||||
|
||||
////
|
||||
|
||||
E rode sua applicação do mesmo modo que você tem feito nos tutoriais, mas sem a opção `--reload`, por exemplo:
|
||||
|
||||
//// tab | Uvicorn
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ uvicorn main:app --host 0.0.0.0 --port 80
|
||||
|
||||
<span style="color: green;">INFO</span>: Uvicorn running on http://0.0.0.0:80 (Press CTRL+C to quit)
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
////
|
||||
|
||||
//// tab | Hypercorn
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ hypercorn main:app --bind 0.0.0.0:80
|
||||
|
||||
Running on 0.0.0.0:8080 over http (CTRL + C to quit)
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
////
|
||||
|
||||
Você deve querer configurar mais algumas ferramentas para ter certeza que ele seja reinicializado automaticamante se ele parar.
|
||||
|
||||
Você também deve querer instalar <a href="https://gunicorn.org/" class="external-link" target="_blank">Gunicorn</a> e <a href="https://www.uvicorn.org/#running-with-gunicorn" class="external-link" target="_blank">utilizar ele como um gerenciador para o Uvicorn</a>, ou usar Hypercorn com múltiplos _workers_.
|
||||
|
||||
Tenha certeza de ajustar o número de _workers_ etc.
|
||||
|
||||
Mas se você estiver fazendo tudo isso, você pode apenas usar uma imagem Docker que fará isso automaticamente.
|
||||
205
docs/pt/docs/how-to/custom-docs-ui-assets.md
Normal file
205
docs/pt/docs/how-to/custom-docs-ui-assets.md
Normal file
@@ -0,0 +1,205 @@
|
||||
# Recursos Estáticos Personalizados para a UI de Documentação (Hospedagem Própria)
|
||||
|
||||
A documentação da API usa **Swagger UI** e **ReDoc**, e cada um deles precisa de alguns arquivos JavaScript e CSS.
|
||||
|
||||
Por padrão, esses arquivos são fornecidos por um <abbr title="Content Delivery Network: Um serviço, normalmente composto por vários servidores, que fornece arquivos estáticos, como JavaScript e CSS. É comumente usado para providenciar esses arquivos do servidor mais próximo do cliente, melhorando o desempenho.">CDN</abbr>.
|
||||
|
||||
Mas é possível personalizá-los, você pode definir um CDN específico ou providenciar os arquivos você mesmo.
|
||||
|
||||
## CDN Personalizado para JavaScript e CSS
|
||||
|
||||
Vamos supor que você deseja usar um <abbr title="Content Delivery Network">CDN</abbr> diferente, por exemplo, você deseja usar `https://unpkg.com/`.
|
||||
|
||||
Isso pode ser útil se, por exemplo, você mora em um país que restringe algumas URLs.
|
||||
|
||||
### Desativar a documentação automática
|
||||
|
||||
O primeiro passo é desativar a documentação automática, pois por padrão, ela usa o CDN padrão.
|
||||
|
||||
Para desativá-los, defina suas URLs como `None` ao criar seu aplicativo `FastAPI`:
|
||||
|
||||
```Python hl_lines="8"
|
||||
{!../../docs_src/custom_docs_ui/tutorial001.py!}
|
||||
```
|
||||
|
||||
### Incluir a documentação personalizada
|
||||
|
||||
Agora você pode criar as *operações de rota* para a documentação personalizada.
|
||||
|
||||
Você pode reutilizar as funções internas do FastAPI para criar as páginas HTML para a documentação e passar os argumentos necessários:
|
||||
|
||||
* `openapi_url`: a URL onde a página HTML para a documentação pode obter o esquema OpenAPI para a sua API. Você pode usar aqui o atributo `app.openapi_url`.
|
||||
* `title`: o título da sua API.
|
||||
* `oauth2_redirect_url`: você pode usar `app.swagger_ui_oauth2_redirect_url` aqui para usar o padrão.
|
||||
* `swagger_js_url`: a URL onde a página HTML para a sua documentação do Swagger UI pode obter o arquivo **JavaScript**. Este é o URL do CDN personalizado.
|
||||
* `swagger_css_url`: a URL onde a página HTML para a sua documentação do Swagger UI pode obter o arquivo **CSS**. Este é o URL do CDN personalizado.
|
||||
|
||||
E de forma semelhante para o ReDoc...
|
||||
|
||||
```Python hl_lines="2-6 11-19 22-24 27-33"
|
||||
{!../../docs_src/custom_docs_ui/tutorial001.py!}
|
||||
```
|
||||
|
||||
/// tip | Dica
|
||||
|
||||
A *operação de rota* para `swagger_ui_redirect` é um auxiliar para quando você usa OAuth2.
|
||||
|
||||
Se você integrar sua API com um provedor OAuth2, você poderá autenticar e voltar para a documentação da API com as credenciais adquiridas. E interagir com ela usando a autenticação OAuth2 real.
|
||||
|
||||
Swagger UI lidará com isso nos bastidores para você, mas ele precisa desse auxiliar de "redirecionamento".
|
||||
|
||||
///
|
||||
|
||||
### Criar uma *operação de rota* para testar
|
||||
|
||||
Agora, para poder testar se tudo funciona, crie uma *operação de rota*:
|
||||
|
||||
```Python hl_lines="36-38"
|
||||
{!../../docs_src/custom_docs_ui/tutorial001.py!}
|
||||
```
|
||||
|
||||
### Teste
|
||||
|
||||
Agora, você deve ser capaz de ir para a documentação em <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>, e recarregar a página, ela carregará esses recursos do novo CDN.
|
||||
|
||||
## Hospedagem Própria de JavaScript e CSS para a documentação
|
||||
|
||||
Hospedar o JavaScript e o CSS pode ser útil se, por exemplo, você precisa que seu aplicativo continue funcionando mesmo offline, sem acesso aberto à Internet, ou em uma rede local.
|
||||
|
||||
Aqui você verá como providenciar esses arquivos você mesmo, no mesmo aplicativo FastAPI, e configurar a documentação para usá-los.
|
||||
|
||||
### Estrutura de Arquivos do Projeto
|
||||
|
||||
Vamos supor que a estrutura de arquivos do seu projeto se pareça com isso:
|
||||
|
||||
```
|
||||
.
|
||||
├── app
|
||||
│ ├── __init__.py
|
||||
│ ├── main.py
|
||||
```
|
||||
|
||||
Agora crie um diretório para armazenar esses arquivos estáticos.
|
||||
|
||||
Sua nova estrutura de arquivos poderia se parecer com isso:
|
||||
|
||||
```
|
||||
.
|
||||
├── app
|
||||
│ ├── __init__.py
|
||||
│ ├── main.py
|
||||
└── static/
|
||||
```
|
||||
|
||||
### Baixe os arquivos
|
||||
|
||||
Baixe os arquivos estáticos necessários para a documentação e coloque-os no diretório `static/`.
|
||||
|
||||
Você provavelmente pode clicar com o botão direito em cada link e selecionar uma opção semelhante a `Salvar link como...`.
|
||||
|
||||
**Swagger UI** usa os arquivos:
|
||||
|
||||
* <a href="https://cdn.jsdelivr.net/npm/swagger-ui-dist@5/swagger-ui-bundle.js" class="external-link" target="_blank">`swagger-ui-bundle.js`</a>
|
||||
* <a href="https://cdn.jsdelivr.net/npm/swagger-ui-dist@5/swagger-ui.css" class="external-link" target="_blank">`swagger-ui.css`</a>
|
||||
|
||||
E o **ReDoc** usa os arquivos:
|
||||
|
||||
* <a href="https://cdn.jsdelivr.net/npm/redoc@next/bundles/redoc.standalone.js" class="external-link" target="_blank">`redoc.standalone.js`</a>
|
||||
|
||||
Depois disso, sua estrutura de arquivos deve se parecer com:
|
||||
|
||||
```
|
||||
.
|
||||
├── app
|
||||
│ ├── __init__.py
|
||||
│ ├── main.py
|
||||
└── static
|
||||
├── redoc.standalone.js
|
||||
├── swagger-ui-bundle.js
|
||||
└── swagger-ui.css
|
||||
```
|
||||
|
||||
### Prover os arquivos estáticos
|
||||
|
||||
* Importe `StaticFiles`.
|
||||
* "Monte" a instância `StaticFiles()` em um caminho específico.
|
||||
|
||||
```Python hl_lines="7 11"
|
||||
{!../../docs_src/custom_docs_ui/tutorial002.py!}
|
||||
```
|
||||
|
||||
### Teste os arquivos estáticos
|
||||
|
||||
Inicialize seu aplicativo e vá para <a href="http://127.0.0.1:8000/static/redoc.standalone.js" class="external-link" target="_blank">http://127.0.0.1:8000/static/redoc.standalone.js</a>.
|
||||
|
||||
Você deverá ver um arquivo JavaScript muito longo para o **ReDoc**.
|
||||
|
||||
Esse arquivo pode começar com algo como:
|
||||
|
||||
```JavaScript
|
||||
/*!
|
||||
* ReDoc - OpenAPI/Swagger-generated API Reference Documentation
|
||||
* -------------------------------------------------------------
|
||||
* Version: "2.0.0-rc.18"
|
||||
* Repo: https://github.com/Redocly/redoc
|
||||
*/
|
||||
!function(e,t){"object"==typeof exports&&"object"==typeof m
|
||||
|
||||
...
|
||||
```
|
||||
|
||||
Isso confirma que você está conseguindo fornecer arquivos estáticos do seu aplicativo e que você colocou os arquivos estáticos para a documentação no local correto.
|
||||
|
||||
Agora, podemos configurar o aplicativo para usar esses arquivos estáticos para a documentação.
|
||||
|
||||
### Desativar a documentação automática para arquivos estáticos
|
||||
|
||||
Da mesma forma que ao usar um CDN personalizado, o primeiro passo é desativar a documentação automática, pois ela usa o CDN padrão.
|
||||
|
||||
Para desativá-los, defina suas URLs como `None` ao criar seu aplicativo `FastAPI`:
|
||||
|
||||
```Python hl_lines="9"
|
||||
{!../../docs_src/custom_docs_ui/tutorial002.py!}
|
||||
```
|
||||
|
||||
### Incluir a documentação personalizada para arquivos estáticos
|
||||
|
||||
E da mesma forma que com um CDN personalizado, agora você pode criar as *operações de rota* para a documentação personalizada.
|
||||
|
||||
Novamente, você pode reutilizar as funções internas do FastAPI para criar as páginas HTML para a documentação e passar os argumentos necessários:
|
||||
|
||||
* `openapi_url`: a URL onde a página HTML para a documentação pode obter o esquema OpenAPI para a sua API. Você pode usar aqui o atributo `app.openapi_url`.
|
||||
* `title`: o título da sua API.
|
||||
* `oauth2_redirect_url`: Você pode usar `app.swagger_ui_oauth2_redirect_url` aqui para usar o padrão.
|
||||
* `swagger_js_url`: a URL onde a página HTML para a sua documentação do Swagger UI pode obter o arquivo **JavaScript**. Este é o URL do CDN personalizado. **Este é o URL que seu aplicativo está fornecendo**.
|
||||
* `swagger_css_url`: a URL onde a página HTML para a sua documentação do Swagger UI pode obter o arquivo **CSS**. **Esse é o que seu aplicativo está fornecendo**.
|
||||
|
||||
E de forma semelhante para o ReDoc...
|
||||
|
||||
```Python hl_lines="2-6 14-22 25-27 30-36"
|
||||
{!../../docs_src/custom_docs_ui/tutorial002.py!}
|
||||
```
|
||||
|
||||
/// tip | Dica
|
||||
|
||||
A *operação de rota* para `swagger_ui_redirect` é um auxiliar para quando você usa OAuth2.
|
||||
|
||||
Se você integrar sua API com um provedor OAuth2, você poderá autenticar e voltar para a documentação da API com as credenciais adquiridas. E, então, interagir com ela usando a autenticação OAuth2 real.
|
||||
|
||||
Swagger UI lidará com isso nos bastidores para você, mas ele precisa desse auxiliar de "redirect".
|
||||
|
||||
///
|
||||
|
||||
### Criar uma *operação de rota* para testar arquivos estáticos
|
||||
|
||||
Agora, para poder testar se tudo funciona, crie uma *operação de rota*:
|
||||
|
||||
```Python hl_lines="39-41"
|
||||
{!../../docs_src/custom_docs_ui/tutorial002.py!}
|
||||
```
|
||||
|
||||
### Teste a UI de Arquivos Estáticos
|
||||
|
||||
Agora, você deve ser capaz de desconectar o WiFi, ir para a documentação em <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>, e recarregar a página.
|
||||
|
||||
E mesmo sem Internet, você será capaz de ver a documentação da sua API e interagir com ela.
|
||||
121
docs/pt/docs/how-to/custom-request-and-route.md
Normal file
121
docs/pt/docs/how-to/custom-request-and-route.md
Normal file
@@ -0,0 +1,121 @@
|
||||
# Requisições Personalizadas e Classes da APIRoute
|
||||
|
||||
Em algum casos, você pode querer sobreescrever a lógica usada pelas classes `Request`e `APIRoute`.
|
||||
|
||||
Em particular, isso pode ser uma boa alternativa para uma lógica em um middleware
|
||||
|
||||
Por exemplo, se você quiser ler ou manipular o corpo da requisição antes que ele seja processado pela sua aplicação.
|
||||
|
||||
/// danger | Perigo
|
||||
|
||||
Isso é um recurso "avançado".
|
||||
|
||||
Se você for um iniciante em **FastAPI** você deve considerar pular essa seção.
|
||||
|
||||
///
|
||||
|
||||
## Casos de Uso
|
||||
|
||||
Alguns casos de uso incluem:
|
||||
|
||||
* Converter requisições não-JSON para JSON (por exemplo, <a href="https://msgpack.org/index.html" class="external-link" target="_blank">`msgpack`</a>).
|
||||
* Descomprimir corpos de requisição comprimidos com gzip.
|
||||
* Registrar automaticamente todos os corpos de requisição.
|
||||
|
||||
## Manipulando codificações de corpo de requisição personalizadas
|
||||
|
||||
Vamos ver como usar uma subclasse personalizada de `Request` para descomprimir requisições gzip.
|
||||
|
||||
E uma subclasse de `APIRoute` para usar essa classe de requisição personalizada.
|
||||
|
||||
### Criar uma classe `GzipRequest` personalizada
|
||||
|
||||
/// tip | Dica
|
||||
|
||||
Isso é um exemplo de brincadeira para demonstrar como funciona, se você precisar de suporte para Gzip, você pode usar o [`GzipMiddleware`](../advanced/middleware.md#gzipmiddleware){.internal-link target=_blank} fornecido.
|
||||
|
||||
///
|
||||
|
||||
Primeiro, criamos uma classe `GzipRequest`, que irá sobrescrever o método `Request.body()` para descomprimir o corpo na presença de um cabeçalho apropriado.
|
||||
|
||||
Se não houver `gzip` no cabeçalho, ele não tentará descomprimir o corpo.
|
||||
|
||||
Dessa forma, a mesma classe de rota pode lidar com requisições comprimidas ou não comprimidas.
|
||||
|
||||
```Python hl_lines="8-15"
|
||||
{!../../docs_src/custom_request_and_route/tutorial001.py!}
|
||||
```
|
||||
|
||||
### Criar uma classe `GzipRoute` personalizada
|
||||
|
||||
Em seguida, criamos uma subclasse personalizada de `fastapi.routing.APIRoute` que fará uso do `GzipRequest`.
|
||||
|
||||
Dessa vez, ele irá sobrescrever o método `APIRoute.get_route_handler()`.
|
||||
|
||||
Esse método retorna uma função. E essa função é o que irá receber uma requisição e retornar uma resposta.
|
||||
|
||||
Aqui nós usamos para criar um `GzipRequest` a partir da requisição original.
|
||||
|
||||
```Python hl_lines="18-26"
|
||||
{!../../docs_src/custom_request_and_route/tutorial001.py!}
|
||||
```
|
||||
|
||||
/// note | Detalhes Técnicos
|
||||
|
||||
Um `Request` também tem um `request.receive`, que é uma função para "receber" o corpo da requisição.
|
||||
|
||||
Um `Request` também tem um `request.receive`, que é uma função para "receber" o corpo da requisição.
|
||||
|
||||
O dicionário `scope` e a função `receive` são ambos parte da especificação ASGI.
|
||||
|
||||
E essas duas coisas, `scope` e `receive`, são o que é necessário para criar uma nova instância de `Request`.
|
||||
|
||||
Para aprender mais sobre o `Request` confira a <a href="https://www.starlette.io/requests/" class="external-link" target="_blank">documentação do Starlette sobre Requests</a>.
|
||||
|
||||
///
|
||||
|
||||
A única coisa que a função retornada por `GzipRequest.get_route_handler` faz de diferente é converter o `Request` para um `GzipRequest`.
|
||||
|
||||
Fazendo isso, nosso `GzipRequest` irá cuidar de descomprimir os dados (se necessário) antes de passá-los para nossas *operações de rota*.
|
||||
|
||||
Depois disso, toda a lógica de processamento é a mesma.
|
||||
|
||||
Mas por causa das nossas mudanças em `GzipRequest.body`, o corpo da requisição será automaticamente descomprimido quando for carregado pelo **FastAPI** quando necessário.
|
||||
|
||||
## Acessando o corpo da requisição em um manipulador de exceção
|
||||
|
||||
/// tip | Dica
|
||||
|
||||
Para resolver esse mesmo problema, é provavelmente muito mais fácil usar o `body` em um manipulador personalizado para `RequestValidationError` ([Tratando Erros](../tutorial/handling-errors.md#use-the-requestvalidationerror-body){.internal-link target=_blank}).
|
||||
|
||||
Mas esse exemplo ainda é valido e mostra como interagir com os componentes internos.
|
||||
|
||||
///
|
||||
|
||||
Também podemos usar essa mesma abordagem para acessar o corpo da requisição em um manipulador de exceção.
|
||||
|
||||
Tudo que precisamos fazer é manipular a requisição dentro de um bloco `try`/`except`:
|
||||
|
||||
```Python hl_lines="13 15"
|
||||
{!../../docs_src/custom_request_and_route/tutorial002.py!}
|
||||
```
|
||||
|
||||
Se uma exceção ocorrer, a instância `Request` ainda estará em escopo, então podemos ler e fazer uso do corpo da requisição ao lidar com o erro:
|
||||
|
||||
```Python hl_lines="16-18"
|
||||
{!../../docs_src/custom_request_and_route/tutorial002.py!}
|
||||
```
|
||||
|
||||
## Classe `APIRoute` personalizada em um router
|
||||
|
||||
você também pode definir o parametro `route_class` de uma `APIRouter`;
|
||||
|
||||
```Python hl_lines="26"
|
||||
{!../../docs_src/custom_request_and_route/tutorial003.py!}
|
||||
```
|
||||
|
||||
Nesse exemplo, as *operações de rota* sob o `router` irão usar a classe `TimedRoute` personalizada, e terão um cabeçalho extra `X-Response-Time` na resposta com o tempo que levou para gerar a resposta:
|
||||
|
||||
```Python hl_lines="13-20"
|
||||
{!../../docs_src/custom_request_and_route/tutorial003.py!}
|
||||
```
|
||||
91
docs/pt/docs/how-to/extending-openapi.md
Normal file
91
docs/pt/docs/how-to/extending-openapi.md
Normal file
@@ -0,0 +1,91 @@
|
||||
|
||||
# Extendendo o OpenAPI
|
||||
|
||||
Existem alguns casos em que pode ser necessário modificar o esquema OpenAPI gerado.
|
||||
|
||||
Nesta seção, você verá como fazer isso.
|
||||
|
||||
## O processo normal
|
||||
|
||||
O processo normal (padrão) é o seguinte:
|
||||
|
||||
Uma aplicação (instância) do `FastAPI` possui um método `.openapi()` que deve retornar o esquema OpenAPI.
|
||||
|
||||
Como parte da criação do objeto de aplicação, uma *operação de rota* para `/openapi.json` (ou para o que você definir como `openapi_url`) é registrada.
|
||||
|
||||
Ela apenas retorna uma resposta JSON com o resultado do método `.openapi()` da aplicação.
|
||||
|
||||
Por padrão, o que o método `.openapi()` faz é verificar se a propriedade `.openapi_schema` tem conteúdo e retorná-lo.
|
||||
|
||||
Se não tiver, ele gera o conteúdo usando a função utilitária em `fastapi.openapi.utils.get_openapi`.
|
||||
|
||||
E essa função `get_openapi()` recebe como parâmetros:
|
||||
|
||||
* `title`: O título do OpenAPI, exibido na documentação.
|
||||
* `version`: A versão da sua API, por exemplo, `2.5.0`.
|
||||
* `openapi_version`: A versão da especificação OpenAPI utilizada. Por padrão, a mais recente: `3.1.0`.
|
||||
* `summary`: Um resumo curto da API.
|
||||
* `description`: A descrição da sua API, que pode incluir markdown e será exibida na documentação.
|
||||
* `routes`: Uma lista de rotas, que são cada uma das *operações de rota* registradas. Elas são obtidas de `app.routes`.
|
||||
|
||||
/// info | Informação
|
||||
|
||||
O parâmetro `summary` está disponível no OpenAPI 3.1.0 e superior, suportado pelo FastAPI 0.99.0 e superior.
|
||||
|
||||
///
|
||||
|
||||
## Sobrescrevendo os padrões
|
||||
|
||||
Com as informações acima, você pode usar a mesma função utilitária para gerar o esquema OpenAPI e sobrescrever cada parte que precisar.
|
||||
|
||||
Por exemplo, vamos adicionar <a href="https://github.com/Rebilly/ReDoc/blob/master/docs/redoc-vendor-extensions.md#x-logo" class="external-link" target="_blank">Extensão OpenAPI do ReDoc para incluir um logo personalizado</a>.
|
||||
|
||||
### **FastAPI** Normal
|
||||
|
||||
Primeiro, escreva toda a sua aplicação **FastAPI** normalmente:
|
||||
|
||||
```Python hl_lines="1 4 7-9"
|
||||
{!../../docs_src/extending_openapi/tutorial001.py!}
|
||||
```
|
||||
|
||||
### Gerar o esquema OpenAPI
|
||||
|
||||
Em seguida, use a mesma função utilitária para gerar o esquema OpenAPI, dentro de uma função `custom_openapi()`:
|
||||
|
||||
```Python hl_lines="2 15-21"
|
||||
{!../../docs_src/extending_openapi/tutorial001.py!}
|
||||
```
|
||||
|
||||
### Modificar o esquema OpenAPI
|
||||
|
||||
Agora, você pode adicionar a extensão do ReDoc, incluindo um `x-logo` personalizado ao "objeto" `info` no esquema OpenAPI:
|
||||
|
||||
```Python hl_lines="22-24"
|
||||
{!../../docs_src/extending_openapi/tutorial001.py!}
|
||||
```
|
||||
|
||||
### Armazenar em cache o esquema OpenAPI
|
||||
|
||||
Você pode usar a propriedade `.openapi_schema` como um "cache" para armazenar o esquema gerado.
|
||||
|
||||
Dessa forma, sua aplicação não precisará gerar o esquema toda vez que um usuário abrir a documentação da sua API.
|
||||
|
||||
Ele será gerado apenas uma vez, e o mesmo esquema armazenado em cache será utilizado nas próximas requisições.
|
||||
|
||||
```Python hl_lines="13-14 25-26"
|
||||
{!../../docs_src/extending_openapi/tutorial001.py!}
|
||||
```
|
||||
|
||||
### Sobrescrever o método
|
||||
|
||||
Agora, você pode substituir o método `.openapi()` pela sua nova função.
|
||||
|
||||
```Python hl_lines="29"
|
||||
{!../../docs_src/extending_openapi/tutorial001.py!}
|
||||
```
|
||||
|
||||
### Verificar
|
||||
|
||||
Uma vez que você acessar <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a>, verá que está usando seu logo personalizado (neste exemplo, o logo do **FastAPI**):
|
||||
|
||||
<img src="/docs/en/docs/img/tutorial/extending-openapi/image01.png">
|
||||
258
docs/pt/docs/how-to/separate-openapi-schemas.md
Normal file
258
docs/pt/docs/how-to/separate-openapi-schemas.md
Normal file
@@ -0,0 +1,258 @@
|
||||
# Esquemas OpenAPI Separados para Entrada e Saída ou Não
|
||||
|
||||
Ao usar **Pydantic v2**, o OpenAPI gerado é um pouco mais exato e **correto** do que antes. 😎
|
||||
|
||||
Inclusive, em alguns casos, ele terá até **dois JSON Schemas** no OpenAPI para o mesmo modelo Pydantic, para entrada e saída, dependendo se eles possuem **valores padrão**.
|
||||
|
||||
Vamos ver como isso funciona e como alterar se for necessário.
|
||||
|
||||
## Modelos Pydantic para Entrada e Saída
|
||||
|
||||
Digamos que você tenha um modelo Pydantic com valores padrão, como este:
|
||||
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="7"
|
||||
{!> ../../docs_src/separate_openapi_schemas/tutorial001_py310.py[ln:1-7]!}
|
||||
|
||||
# Code below omitted 👇
|
||||
```
|
||||
|
||||
<details>
|
||||
<summary>👀 Visualização completa do arquivo</summary>
|
||||
|
||||
```Python
|
||||
{!> ../../docs_src/separate_openapi_schemas/tutorial001_py310.py!}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.9+
|
||||
|
||||
```Python hl_lines="9"
|
||||
{!> ../../docs_src/separate_openapi_schemas/tutorial001_py39.py[ln:1-9]!}
|
||||
|
||||
# Code below omitted 👇
|
||||
```
|
||||
|
||||
<details>
|
||||
<summary>👀 Visualização completa do arquivo</summary>
|
||||
|
||||
```Python
|
||||
{!> ../../docs_src/separate_openapi_schemas/tutorial001_py39.py!}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="9"
|
||||
{!> ../../docs_src/separate_openapi_schemas/tutorial001.py[ln:1-9]!}
|
||||
|
||||
# Code below omitted 👇
|
||||
```
|
||||
|
||||
<details>
|
||||
<summary>👀 Visualização completa do arquivo</summary>
|
||||
|
||||
```Python
|
||||
{!> ../../docs_src/separate_openapi_schemas/tutorial001.py!}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
////
|
||||
|
||||
### Modelo para Entrada
|
||||
|
||||
Se você usar esse modelo como entrada, como aqui:
|
||||
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="14"
|
||||
{!> ../../docs_src/separate_openapi_schemas/tutorial001_py310.py[ln:1-15]!}
|
||||
|
||||
# Code below omitted 👇
|
||||
```
|
||||
|
||||
<details>
|
||||
<summary>👀 Visualização completa do arquivo</summary>
|
||||
|
||||
```Python
|
||||
{!> ../../docs_src/separate_openapi_schemas/tutorial001_py310.py!}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.9+
|
||||
|
||||
```Python hl_lines="16"
|
||||
{!> ../../docs_src/separate_openapi_schemas/tutorial001_py39.py[ln:1-17]!}
|
||||
|
||||
# Code below omitted 👇
|
||||
```
|
||||
|
||||
<details>
|
||||
<summary>👀 Visualização completa do arquivo</summary>
|
||||
|
||||
```Python
|
||||
{!> ../../docs_src/separate_openapi_schemas/tutorial001_py39.py!}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="16"
|
||||
{!> ../../docs_src/separate_openapi_schemas/tutorial001.py[ln:1-17]!}
|
||||
|
||||
# Code below omitted 👇
|
||||
```
|
||||
|
||||
<details>
|
||||
<summary>👀 Visualização completa do arquivo</summary>
|
||||
|
||||
```Python
|
||||
{!> ../../docs_src/separate_openapi_schemas/tutorial001.py!}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
////
|
||||
|
||||
... então o campo `description` não será obrigatório. Porque ele tem um valor padrão de `None`.
|
||||
|
||||
### Modelo de Entrada na Documentação
|
||||
|
||||
Você pode confirmar que na documentação, o campo `description` não tem um **asterisco vermelho**, não é marcado como obrigatório:
|
||||
|
||||
<div class="screenshot">
|
||||
<img src="/img/tutorial/separate-openapi-schemas/image01.png">
|
||||
</div>
|
||||
|
||||
### Modelo para Saída
|
||||
|
||||
Mas se você usar o mesmo modelo como saída, como aqui:
|
||||
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="19"
|
||||
{!> ../../docs_src/separate_openapi_schemas/tutorial001_py310.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.9+
|
||||
|
||||
```Python hl_lines="21"
|
||||
{!> ../../docs_src/separate_openapi_schemas/tutorial001_py39.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="21"
|
||||
{!> ../../docs_src/separate_openapi_schemas/tutorial001.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
... então, como `description` tem um valor padrão, se você **não retornar nada** para esse campo, ele ainda terá o **valor padrão**.
|
||||
|
||||
### Modelo para Dados de Resposta de Saída
|
||||
|
||||
Se você interagir com a documentação e verificar a resposta, mesmo que o código não tenha adicionado nada em um dos campos `description`, a resposta JSON contém o valor padrão (`null`):
|
||||
|
||||
<div class="screenshot">
|
||||
<img src="/img/tutorial/separate-openapi-schemas/image02.png">
|
||||
</div>
|
||||
|
||||
Isso significa que ele **sempre terá um valor**, só que às vezes o valor pode ser `None` (ou `null` em termos de JSON).
|
||||
|
||||
Isso quer dizer que, os clientes que usam sua API não precisam verificar se o valor existe ou não, eles podem **assumir que o campo sempre estará lá**, mas que em alguns casos terá o valor padrão de `None`.
|
||||
|
||||
A maneira de descrever isso no OpenAPI é marcar esse campo como **obrigatório**, porque ele sempre estará lá.
|
||||
|
||||
Por causa disso, o JSON Schema para um modelo pode ser diferente dependendo se ele é usado para **entrada ou saída**:
|
||||
|
||||
* para **entrada**, o `description` **não será obrigatório**
|
||||
* para **saída**, ele será **obrigatório** (e possivelmente `None`, ou em termos de JSON, `null`)
|
||||
|
||||
### Modelo para Saída na Documentação
|
||||
|
||||
Você pode verificar o modelo de saída na documentação também, ambos `name` e `description` são marcados como **obrigatórios** com um **asterisco vermelho**:
|
||||
|
||||
<div class="screenshot">
|
||||
<img src="/img/tutorial/separate-openapi-schemas/image03.png">
|
||||
</div>
|
||||
|
||||
### Modelo para Entrada e Saída na Documentação
|
||||
|
||||
E se você verificar todos os Schemas disponíveis (JSON Schemas) no OpenAPI, verá que há dois, um `Item-Input` e um `Item-Output`.
|
||||
|
||||
Para `Item-Input`, `description` **não é obrigatório**, não tem um asterisco vermelho.
|
||||
|
||||
Mas para `Item-Output`, `description` **é obrigatório**, tem um asterisco vermelho.
|
||||
|
||||
<div class="screenshot">
|
||||
<img src="/img/tutorial/separate-openapi-schemas/image04.png">
|
||||
</div>
|
||||
|
||||
Com esse recurso do **Pydantic v2**, sua documentação da API fica mais **precisa**, e se você tiver clientes e SDKs gerados automaticamente, eles serão mais precisos também, proporcionando uma melhor **experiência para desenvolvedores** e consistência. 🎉
|
||||
|
||||
## Não Separe Schemas
|
||||
|
||||
Agora, há alguns casos em que você pode querer ter o **mesmo esquema para entrada e saída**.
|
||||
|
||||
Provavelmente, o principal caso de uso para isso é se você já tem algum código de cliente/SDK gerado automaticamente e não quer atualizar todo o código de cliente/SDK gerado ainda, você provavelmente vai querer fazer isso em algum momento, mas talvez não agora.
|
||||
|
||||
Nesse caso, você pode desativar esse recurso no **FastAPI**, com o parâmetro `separate_input_output_schemas=False`.
|
||||
|
||||
/// info | Informação
|
||||
|
||||
O suporte para `separate_input_output_schemas` foi adicionado no FastAPI `0.102.0`. 🤓
|
||||
|
||||
///
|
||||
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="10"
|
||||
{!> ../../docs_src/separate_openapi_schemas/tutorial002_py310.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.9+
|
||||
|
||||
```Python hl_lines="12"
|
||||
{!> ../../docs_src/separate_openapi_schemas/tutorial002_py39.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="12"
|
||||
{!> ../../docs_src/separate_openapi_schemas/tutorial002.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
### Mesmo Esquema para Modelos de Entrada e Saída na Documentação
|
||||
|
||||
E agora haverá um único esquema para entrada e saída para o modelo, apenas `Item`, e `description` **não será obrigatório**:
|
||||
|
||||
<div class="screenshot">
|
||||
<img src="/img/tutorial/separate-openapi-schemas/image05.png">
|
||||
</div>
|
||||
|
||||
Esse é o mesmo comportamento do Pydantic v1. 🤓
|
||||
7
docs/pt/docs/how-to/testing-database.md
Normal file
7
docs/pt/docs/how-to/testing-database.md
Normal file
@@ -0,0 +1,7 @@
|
||||
# Testando a Base de Dados
|
||||
|
||||
Você pode estudar sobre bases de dados, SQL e SQLModel na <a href="https://sqlmodel.tiangolo.com/" class="external-link" target="_blank">documentação de SQLModel</a>. 🤓
|
||||
|
||||
Aqui tem um mini <a href="https://sqlmodel.tiangolo.com/tutorial/fastapi/" class="external-link" target="_blank">tutorial de como usar SQLModel com FastAPI</a>. ✨
|
||||
|
||||
Esse tutorial inclui uma sessão sobre <a href="https://sqlmodel.tiangolo.com/tutorial/fastapi/tests/" class="external-link" target="_blank">testar bases de dados SQL</a>. 😎
|
||||
@@ -78,7 +78,7 @@ Os recursos chave são:
|
||||
|
||||
"*Honestamente, o que você construiu parece super sólido e rebuscado. De muitas formas, eu queria que o **Hug** fosse assim - é realmente inspirador ver alguém que construiu ele.*"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Timothy Crosley - <strong>criador do<a href="https://www.hug.rest/" target="_blank">Hug</a></strong> <a href="https://news.ycombinator.com/item?id=19455465" target="_blank"><small>(ref)</small></a></div>
|
||||
<div style="text-align: right; margin-right: 10%;">Timothy Crosley - <strong>criador do<a href="https://github.com/hugapi/hug" target="_blank">Hug</a></strong> <a href="https://news.ycombinator.com/item?id=19455465" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
# Introdução aos tipos Python
|
||||
|
||||
**Python 3.6 +** tem suporte para "type hints" opcionais.
|
||||
O Python possui suporte para "dicas de tipo" ou "type hints" (também chamado de "anotações de tipo" ou "type annotations")
|
||||
|
||||
Esses **"type hints"** são uma nova sintaxe (desde Python 3.6+) que permite declarar o <abbr title = "por exemplo: str, int, float, bool"> tipo </abbr> de uma variável.
|
||||
Esses **"type hints"** são uma sintaxe especial que permite declarar o <abbr title = "por exemplo: str, int, float, bool">tipo</abbr> de uma variável.
|
||||
|
||||
Ao declarar tipos para suas variáveis, editores e ferramentas podem oferecer um melhor suporte.
|
||||
|
||||
Este é apenas um **tutorial rápido / atualização** sobre type hints Python. Ele cobre apenas o mínimo necessário para usá-los com o **FastAPI** ... que é realmente muito pouco.
|
||||
Este é apenas um **tutorial rápido / atualização** sobre type hints do Python. Ele cobre apenas o mínimo necessário para usá-los com o **FastAPI**... que é realmente muito pouco.
|
||||
|
||||
O **FastAPI** é baseado nesses type hints, eles oferecem muitas vantagens e benefícios.
|
||||
|
||||
Mas mesmo que você nunca use o **FastAPI**, você se beneficiaria de aprender um pouco sobre eles.
|
||||
|
||||
/// note | "Nota"
|
||||
/// note | Nota
|
||||
|
||||
Se você é um especialista em Python e já sabe tudo sobre type hints, pule para o próximo capítulo.
|
||||
|
||||
@@ -35,8 +35,8 @@ John Doe
|
||||
A função faz o seguinte:
|
||||
|
||||
* Pega um `first_name` e `last_name`.
|
||||
* Converte a primeira letra de cada uma em maiúsculas com `title ()`.
|
||||
* <abbr title = "Agrupa-os, como um. Com o conteúdo de um após o outro."> Concatena </abbr> com um espaço no meio.
|
||||
* Converte a primeira letra de cada uma em maiúsculas com `title()`.
|
||||
* <abbr title = "Agrupa-os, como um. Com o conteúdo de um após o outro.">Concatena</abbr> com um espaço no meio.
|
||||
|
||||
```Python hl_lines="2"
|
||||
{!../../docs_src/python_types/tutorial001.py!}
|
||||
@@ -48,7 +48,7 @@ A função faz o seguinte:
|
||||
|
||||
Mas agora imagine que você estava escrevendo do zero.
|
||||
|
||||
Em algum momento você teria iniciado a definição da função, já tinha os parâmetros prontos ...
|
||||
Em algum momento você teria iniciado a definição da função, já tinha os parâmetros prontos...
|
||||
|
||||
Mas então você deve chamar "esse método que converte a primeira letra em maiúscula".
|
||||
|
||||
@@ -96,37 +96,37 @@ Isso não é o mesmo que declarar valores padrão como seria com:
|
||||
|
||||
Estamos usando dois pontos (`:`), não é igual a (`=`).
|
||||
|
||||
E adicionar type hints normalmente não muda o que acontece do que aconteceria sem elas.
|
||||
E adicionar type hints normalmente não muda o que acontece do que aconteceria sem eles.
|
||||
|
||||
Mas agora, imagine que você está novamente no meio da criação dessa função, mas com type hints.
|
||||
|
||||
No mesmo ponto, você tenta acionar o preenchimento automático com o `Ctrl Space` e vê:
|
||||
No mesmo ponto, você tenta acionar o preenchimento automático com o `Ctrl+Space` e vê:
|
||||
|
||||
<img src="/img/python-types/image02.png">
|
||||
|
||||
Com isso, você pode rolar, vendo as opções, até encontrar o que "toca uma campainha":
|
||||
Com isso, você pode rolar, vendo as opções, até encontrar o que "soa familiar":
|
||||
|
||||
<img src="/img/python-types/image03.png">
|
||||
|
||||
## Mais motivação
|
||||
|
||||
Marque esta função, ela já possui type hints:
|
||||
Verifique esta função, ela já possui type hints:
|
||||
|
||||
```Python hl_lines="1"
|
||||
{!../../docs_src/python_types/tutorial003.py!}
|
||||
```
|
||||
|
||||
Como o editor conhece os tipos de variáveis, você não apenas obtém a conclusão, mas também as verificações de erro:
|
||||
Como o editor conhece os tipos de variáveis, você não obtém apenas o preenchimento automático, mas também as verificações de erro:
|
||||
|
||||
<img src="/img/python-types/image04.png">
|
||||
|
||||
Agora você sabe que precisa corrigí-lo, converta `age` em uma string com `str (age)`:
|
||||
Agora você sabe que precisa corrigí-lo, converta `age` em uma string com `str(age)`:
|
||||
|
||||
```Python hl_lines="2"
|
||||
{!../../docs_src/python_types/tutorial004.py!}
|
||||
```
|
||||
|
||||
## Tipos de declaração
|
||||
## Declarando Tipos
|
||||
|
||||
Você acabou de ver o local principal para declarar type hints. Como parâmetros de função.
|
||||
|
||||
@@ -151,39 +151,77 @@ Você pode usar, por exemplo:
|
||||
|
||||
Existem algumas estruturas de dados que podem conter outros valores, como `dict`, `list`, `set` e `tuple`. E os valores internos também podem ter seu próprio tipo.
|
||||
|
||||
Para declarar esses tipos e os tipos internos, você pode usar o módulo Python padrão `typing`.
|
||||
Estes tipos que possuem tipos internos são chamados de tipos "**genéricos**". E é possível declará-los mesmo com os seus tipos internos.
|
||||
|
||||
Ele existe especificamente para suportar esses type hints.
|
||||
Para declarar esses tipos e os tipos internos, você pode usar o módulo Python padrão `typing`. Ele existe especificamente para suportar esses type hints.
|
||||
|
||||
#### `List`
|
||||
#### Versões mais recentes do Python
|
||||
|
||||
Por exemplo, vamos definir uma variável para ser uma `lista` de `str`.
|
||||
A sintaxe utilizando `typing` é **compatível** com todas as versões, desde o Python 3.6 até as últimas, incluindo o Python 3.9, 3.10, etc.
|
||||
|
||||
Em `typing`, importe `List` (com um `L` maiúsculo):
|
||||
Conforme o Python evolui, **novas versões** chegam com suporte melhorado para esses type annotations, e em muitos casos, você não precisará nem importar e utilizar o módulo `typing` para declarar os type annotations.
|
||||
|
||||
Se você pode escolher uma versão mais recente do Python para o seu projeto, você poderá aproveitar isso ao seu favor.
|
||||
|
||||
Em todos os documentos existem exemplos compatíveis com cada versão do Python (quando existem diferenças).
|
||||
|
||||
Por exemplo, "**Python 3.6+**" significa que é compatível com o Python 3.6 ou superior (incluindo o 3.7, 3.8, 3.9, 3.10, etc). E "**Python 3.9+**" significa que é compatível com o Python 3.9 ou mais recente (incluindo o 3.10, etc).
|
||||
|
||||
Se você pode utilizar a **versão mais recente do Python**, utilize os exemplos para as últimas versões. Eles terão as **melhores e mais simples sintaxes**, como por exemplo, "**Python 3.10+**".
|
||||
|
||||
#### List
|
||||
|
||||
Por exemplo, vamos definir uma variável para ser uma `list` de `str`.
|
||||
|
||||
//// tab | Python 3.9+
|
||||
|
||||
Declare uma variável com a mesma sintaxe com dois pontos (`:`)
|
||||
|
||||
Como tipo, coloque `list`.
|
||||
|
||||
Como a lista é o tipo que contém algum tipo interno, você coloca o tipo dentro de colchetes:
|
||||
|
||||
```Python hl_lines="1"
|
||||
{!../../docs_src/python_types/tutorial006.py!}
|
||||
{!> ../../docs_src/python_types/tutorial006_py39.py!}
|
||||
```
|
||||
|
||||
Declare a variável com a mesma sintaxe de dois pontos (`:`).
|
||||
////
|
||||
|
||||
Como o tipo, coloque a `List`.
|
||||
//// tab | Python 3.8+
|
||||
|
||||
Como a lista é um tipo que contém alguns tipos internos, você os coloca entre colchetes:
|
||||
De `typing`, importe `List` (com o `L` maiúsculo):
|
||||
|
||||
```Python hl_lines="1"
|
||||
{!> ../../docs_src/python_types/tutorial006.py!}
|
||||
```
|
||||
|
||||
Declare uma variável com a mesma sintaxe com dois pontos (`:`)
|
||||
|
||||
Como tipo, coloque o `List` que você importou de `typing`.
|
||||
|
||||
Como a lista é o tipo que contém algum tipo interno, você coloca o tipo dentro de colchetes:
|
||||
|
||||
```Python hl_lines="4"
|
||||
{!../../docs_src/python_types/tutorial006.py!}
|
||||
{!> ../../docs_src/python_types/tutorial006.py!}
|
||||
```
|
||||
|
||||
/// tip | "Dica"
|
||||
////
|
||||
|
||||
Esses tipos internos entre colchetes são chamados de "parâmetros de tipo".
|
||||
/// info | Informação
|
||||
|
||||
Nesse caso, `str` é o parâmetro de tipo passado para `List`.
|
||||
Estes tipos internos dentro dos colchetes são chamados "parâmetros de tipo" (type parameters).
|
||||
|
||||
Neste caso, `str` é o parâmetro de tipo passado para `List` (ou `list` no Python 3.9 ou superior).
|
||||
|
||||
///
|
||||
|
||||
Isso significa que: "a variável `items` é uma `list`, e cada um dos itens desta lista é uma `str`".
|
||||
Isso significa: "a variável `items` é uma `list`, e cada um dos itens desta lista é uma `str`".
|
||||
|
||||
/// tip | Dica
|
||||
|
||||
Se você usa o Python 3.9 ou superior, você não precisa importar `List` de `typing`. Você pode utilizar o mesmo tipo `list` no lugar.
|
||||
|
||||
///
|
||||
|
||||
Ao fazer isso, seu editor pode fornecer suporte mesmo durante o processamento de itens da lista:
|
||||
|
||||
@@ -195,20 +233,32 @@ Observe que a variável `item` é um dos elementos da lista `items`.
|
||||
|
||||
E, ainda assim, o editor sabe que é um `str` e fornece suporte para isso.
|
||||
|
||||
#### `Tuple` e `Set`
|
||||
#### Tuple e Set
|
||||
|
||||
Você faria o mesmo para declarar `tuple`s e `set`s:
|
||||
|
||||
```Python hl_lines="1 4"
|
||||
{!../../docs_src/python_types/tutorial007.py!}
|
||||
//// tab | Python 3.9+
|
||||
|
||||
```Python hl_lines="1"
|
||||
{!> ../../docs_src/python_types/tutorial007_py39.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="1 4"
|
||||
{!> ../../docs_src/python_types/tutorial007.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
Isso significa que:
|
||||
|
||||
* A variável `items_t` é uma `tuple` com 3 itens, um `int`, outro `int` e uma `str`.
|
||||
* A variável `items_s` é um `set`, e cada um de seus itens é do tipo `bytes`.
|
||||
|
||||
#### `Dict`
|
||||
#### Dict
|
||||
|
||||
Para definir um `dict`, você passa 2 parâmetros de tipo, separados por vírgulas.
|
||||
|
||||
@@ -216,38 +266,185 @@ O primeiro parâmetro de tipo é para as chaves do `dict`.
|
||||
|
||||
O segundo parâmetro de tipo é para os valores do `dict`:
|
||||
|
||||
```Python hl_lines="1 4"
|
||||
{!../../docs_src/python_types/tutorial008.py!}
|
||||
//// tab | Python 3.9+
|
||||
|
||||
```Python hl_lines="1"
|
||||
{!> ../../docs_src/python_types/tutorial008_py39.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="1 4"
|
||||
{!> ../../docs_src/python_types/tutorial008.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
Isso significa que:
|
||||
|
||||
* A variável `prices` é um dict`:
|
||||
* As chaves deste `dict` são do tipo `str` (digamos, o nome de cada item).
|
||||
* Os valores deste `dict` são do tipo `float` (digamos, o preço de cada item).
|
||||
|
||||
#### `Opcional`
|
||||
#### Union
|
||||
|
||||
Você também pode usar o `Opcional` para declarar que uma variável tem um tipo, como `str`, mas que é "opcional", o que significa que também pode ser `None`:
|
||||
Você pode declarar que uma variável pode ser de qualquer um dentre **diversos tipos**. Por exemplo, um `int` ou um `str`.
|
||||
|
||||
No Python 3.6 e superior (incluindo o Python 3.10), você pode utilizar o tipo `Union` de `typing`, e colocar dentro dos colchetes os possíveis tipos aceitáveis.
|
||||
|
||||
No Python 3.10 também existe uma **nova sintaxe** onde você pode colocar os possívels tipos separados por uma <abbr title='também chamado de "bitwise ou operador", mas o significado é irrelevante aqui'>barra vertical (`|`)</abbr>.
|
||||
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="1"
|
||||
{!> ../../docs_src/python_types/tutorial008b_py310.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="1 4"
|
||||
{!> ../../docs_src/python_types/tutorial008b.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
Em ambos os casos, isso significa que `item` poderia ser um `int` ou um `str`.
|
||||
|
||||
|
||||
#### Possívelmente `None`
|
||||
|
||||
Você pode declarar que um valor pode ter um tipo, como `str`, mas que ele também pode ser `None`.
|
||||
|
||||
No Python 3.6 e superior (incluindo o Python 3.10) você pode declará-lo importando e utilizando `Optional` do módulo `typing`.
|
||||
|
||||
```Python hl_lines="1 4"
|
||||
{!../../docs_src/python_types/tutorial009.py!}
|
||||
```
|
||||
|
||||
O uso de `Opcional [str]` em vez de apenas `str` permitirá que o editor o ajude a detectar erros, onde você pode estar assumindo que um valor é sempre um `str`, quando na verdade também pode ser `None`.
|
||||
O uso de `Optional[str]` em vez de apenas `str` permitirá que o editor o ajude a detectar erros, onde você pode estar assumindo que um valor é sempre um `str`, quando na verdade também pode ser `None`.
|
||||
|
||||
`Optional[Something]` é na verdade um atalho para `Union[Something, None]`, eles são equivalentes.
|
||||
|
||||
Isso também significa que no Python 3.10, você pode utilizar `Something | None`:
|
||||
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="1"
|
||||
{!> ../../docs_src/python_types/tutorial009_py310.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="1 4"
|
||||
{!> ../../docs_src/python_types/tutorial009.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+ alternative
|
||||
|
||||
```Python hl_lines="1 4"
|
||||
{!> ../../docs_src/python_types/tutorial009b.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
#### Utilizando `Union` ou `Optional`
|
||||
|
||||
Se você está utilizando uma versão do Python abaixo da 3.10, aqui vai uma dica do meu ponto de vista bem **subjetivo**:
|
||||
|
||||
* 🚨 Evite utilizar `Optional[SomeType]`
|
||||
* No lugar, ✨ **use `Union[SomeType, None]`** ✨.
|
||||
|
||||
Ambos são equivalentes, e no final das contas, eles são o mesmo. Mas eu recomendaria o `Union` ao invés de `Optional` porque a palavra **Optional** parece implicar que o valor é opcional, quando na verdade significa "isso pode ser `None`", mesmo que ele não seja opcional e ainda seja obrigatório.
|
||||
|
||||
Eu penso que `Union[SomeType, None]` é mais explícito sobre o que ele significa.
|
||||
|
||||
Isso é apenas sobre palavras e nomes. Mas estas palavras podem afetar como os seus colegas de trabalho pensam sobre o código.
|
||||
|
||||
Por exemplo, vamos pegar esta função:
|
||||
|
||||
```Python hl_lines="1 4"
|
||||
{!../../docs_src/python_types/tutorial009c.py!}
|
||||
```
|
||||
|
||||
O paâmetro `name` é definido como `Optional[str]`, mas ele **não é opcional**, você não pode chamar a função sem o parâmetro:
|
||||
|
||||
```Python
|
||||
say_hi() # Oh, no, this throws an error! 😱
|
||||
```
|
||||
|
||||
O parâmetro `name` **ainda é obrigatório** (não *opicional*) porque ele não possui um valor padrão. Mesmo assim, `name` aceita `None` como valor:
|
||||
|
||||
```Python
|
||||
say_hi(name=None) # This works, None is valid 🎉
|
||||
```
|
||||
|
||||
A boa notícia é, quando você estiver no Python 3.10 você não precisará se preocupar mais com isso, pois você poderá simplesmente utilizar o `|` para definir uniões de tipos:
|
||||
|
||||
```Python hl_lines="1 4"
|
||||
{!../../docs_src/python_types/tutorial009c_py310.py!}
|
||||
```
|
||||
|
||||
E então você não precisará mais se preocupar com nomes como `Optional` e `Union`. 😎
|
||||
|
||||
#### Tipos genéricos
|
||||
|
||||
Esses tipos que usam parâmetros de tipo entre colchetes, como:
|
||||
Esses tipos que usam parâmetros de tipo entre colchetes são chamados **tipos genéricos** ou **genéricos**. Por exemplo:
|
||||
|
||||
//// tab | Python 3.10+
|
||||
|
||||
Você pode utilizar os mesmos tipos internos como genéricos (com colchetes e tipos dentro):
|
||||
|
||||
* `list`
|
||||
* `tuple`
|
||||
* `set`
|
||||
* `dict`
|
||||
|
||||
E o mesmo como no Python 3.8, do módulo `typing`:
|
||||
|
||||
* `Union`
|
||||
* `Optional` (o mesmo que com o 3.8)
|
||||
* ...entro outros.
|
||||
|
||||
No Python 3.10, como uma alternativa para a utilização dos genéricos `Union` e `Optional`, você pode usar a <abbr title='também chamado de "bitwise ou operador", mas o significado não é relevante aqui'>barra vertical (`|`)</abbr> para declarar uniões de tipos. Isso é muito melhor e mais simples.
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.9+
|
||||
|
||||
Você pode utilizar os mesmos tipos internos como genéricos (com colchetes e tipos dentro):
|
||||
|
||||
* `list`
|
||||
* `tuple`
|
||||
* `set`
|
||||
* `dict`
|
||||
|
||||
E o mesmo como no Python 3.8, do módulo `typing`:
|
||||
|
||||
* `Union`
|
||||
* `Optional`
|
||||
* ...entro outros.
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+
|
||||
|
||||
* `List`
|
||||
* `Tuple`
|
||||
* `Set`
|
||||
* `Dict`
|
||||
* `Opcional`
|
||||
* ...e outros.
|
||||
* `Union`
|
||||
* `Optional`
|
||||
* ...entro outros.
|
||||
|
||||
são chamados **tipos genéricos** ou **genéricos**.
|
||||
////
|
||||
|
||||
### Classes como tipos
|
||||
|
||||
@@ -255,7 +452,7 @@ Você também pode declarar uma classe como o tipo de uma variável.
|
||||
|
||||
Digamos que você tenha uma classe `Person`, com um nome:
|
||||
|
||||
```Python hl_lines="1 2 3"
|
||||
```Python hl_lines="1-3"
|
||||
{!../../docs_src/python_types/tutorial010.py!}
|
||||
```
|
||||
|
||||
@@ -269,9 +466,13 @@ E então, novamente, você recebe todo o suporte do editor:
|
||||
|
||||
<img src="/img/python-types/image06.png">
|
||||
|
||||
Perceba que isso significa que "`one_person` é uma **instância** da classe `Person`".
|
||||
|
||||
Isso não significa que "`one_person` é a **classe** chamada `Person`".
|
||||
|
||||
## Modelos Pydantic
|
||||
|
||||
<a href="https://docs.pydantic.dev/" class="external-link" target="_blank"> Pydantic </a> é uma biblioteca Python para executar a validação de dados.
|
||||
O <a href="https://docs.pydantic.dev/" class="external-link" target="_blank">Pydantic</a> é uma biblioteca Python para executar a validação de dados.
|
||||
|
||||
Você declara a "forma" dos dados como classes com atributos.
|
||||
|
||||
@@ -283,21 +484,93 @@ E você recebe todo o suporte do editor com esse objeto resultante.
|
||||
|
||||
Retirado dos documentos oficiais dos Pydantic:
|
||||
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python
|
||||
{!../../docs_src/python_types/tutorial011.py!}
|
||||
{!> ../../docs_src/python_types/tutorial011_py310.py!}
|
||||
```
|
||||
|
||||
/// info | "Informação"
|
||||
////
|
||||
|
||||
Para saber mais sobre o <a href="https://docs.pydantic.dev/" class="external-link" target="_blank"> Pydantic, verifique seus documentos </a>.
|
||||
//// tab | Python 3.9+
|
||||
|
||||
```Python
|
||||
{!> ../../docs_src/python_types/tutorial011_py39.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python
|
||||
{!> ../../docs_src/python_types/tutorial011.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
/// info | Informação
|
||||
|
||||
Para saber mais sobre o <a href="https://docs.pydantic.dev/" class="external-link" target="_blank">Pydantic, verifique a sua documentação</a>.
|
||||
|
||||
///
|
||||
|
||||
**FastAPI** é todo baseado em Pydantic.
|
||||
O **FastAPI** é todo baseado em Pydantic.
|
||||
|
||||
Você verá muito mais disso na prática no [Tutorial - Guia do usuário](tutorial/index.md){.internal-link target=_blank}.
|
||||
|
||||
## Type hints em **FastAPI**
|
||||
/// tip | Dica
|
||||
|
||||
O Pydantic tem um comportamento especial quando você usa `Optional` ou `Union[Something, None]` sem um valor padrão. Você pode ler mais sobre isso na documentação do Pydantic sobre <a href="https://docs.pydantic.dev/2.3/usage/models/#required-fields" class="external-link" target="_blank">campos Opcionais Obrigatórios</a>.
|
||||
|
||||
///
|
||||
|
||||
|
||||
## Type Hints com Metadados de Anotações
|
||||
|
||||
O Python possui uma funcionalidade que nos permite incluir **<abbr title="Informação sobre a informação, neste caso, informação sobre o tipo, e.g. uma descrição.">metadados</abbr> adicionais** nos type hints utilizando `Annotated`.
|
||||
|
||||
//// tab | Python 3.9+
|
||||
|
||||
No Python 3.9, `Annotated` é parte da biblioteca padrão, então você pode importá-lo de `typing`.
|
||||
|
||||
```Python hl_lines="1 4"
|
||||
{!> ../../docs_src/python_types/tutorial013_py39.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+
|
||||
|
||||
Em versões abaixo do Python 3.9, você importa `Annotated` de `typing_extensions`.
|
||||
|
||||
Ele já estará instalado com o **FastAPI**.
|
||||
|
||||
```Python hl_lines="1 4"
|
||||
{!> ../../docs_src/python_types/tutorial013.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
O Python em si não faz nada com este `Annotated`. E para editores e outras ferramentas, o tipo ainda é `str`.
|
||||
|
||||
Mas você pode utilizar este espaço dentro do `Annotated` para fornecer ao **FastAPI** metadata adicional sobre como você deseja que a sua aplicação se comporte.
|
||||
|
||||
O importante aqui de se lembrar é que **o primeiro *type parameter*** que você informar ao `Annotated` é o **tipo de fato**. O resto é apenas metadado para outras ferramentas.
|
||||
|
||||
Por hora, você precisa apenas saber que o `Annotated` existe, e que ele é Python padrão. 😎
|
||||
|
||||
Mais tarde você verá o quão **poderoso** ele pode ser.
|
||||
|
||||
/// tip | Dica
|
||||
|
||||
O fato de que isso é **Python padrão** significa que você ainda obtém a **melhor experiência de desenvolvedor possível** no seu editor, com as ferramentas que você utiliza para analisar e refatorar o seu código, etc. ✨
|
||||
|
||||
E também que o seu código será muito compatível com diversas outras ferramentas e bibliotecas Python. 🚀
|
||||
|
||||
///
|
||||
|
||||
|
||||
## Type hints no **FastAPI**
|
||||
|
||||
O **FastAPI** aproveita esses type hints para fazer várias coisas.
|
||||
|
||||
@@ -306,20 +579,20 @@ Com o **FastAPI**, você declara parâmetros com type hints e obtém:
|
||||
* **Suporte ao editor**.
|
||||
* **Verificações de tipo**.
|
||||
|
||||
... e **FastAPI** usa as mesmas declarações para:
|
||||
... e o **FastAPI** usa as mesmas declarações para:
|
||||
|
||||
* **Definir requisitos**: dos parâmetros do caminho da solicitação, parâmetros da consulta, cabeçalhos, corpos, dependências, etc.
|
||||
* **Definir requisitos**: dos parâmetros de rota, parâmetros da consulta, cabeçalhos, corpos, dependências, etc.
|
||||
* **Converter dados**: da solicitação para o tipo necessário.
|
||||
* **Validar dados**: provenientes de cada solicitação:
|
||||
* A geração de **erros automáticos** retornou ao cliente quando os dados são inválidos.
|
||||
* **Documente** a API usando OpenAPI:
|
||||
* Gerando **erros automáticos** retornados ao cliente quando os dados são inválidos.
|
||||
* **Documentar** a API usando OpenAPI:
|
||||
* que é usado pelas interfaces de usuário da documentação interativa automática.
|
||||
|
||||
Tudo isso pode parecer abstrato. Não se preocupe. Você verá tudo isso em ação no [Tutorial - Guia do usuário](tutorial/index.md){.internal-link target=_blank}.
|
||||
|
||||
O importante é que, usando tipos padrão de Python, em um único local (em vez de adicionar mais classes, decoradores, etc.), o **FastAPI** fará muito trabalho para você.
|
||||
|
||||
/// info | "Informação"
|
||||
/// info | Informação
|
||||
|
||||
Se você já passou por todo o tutorial e voltou para ver mais sobre os tipos, um bom recurso é <a href = "https://mypy.readthedocs.io/en/latest/cheat_sheet_py3.html" class = "external-link "target =" _ blank "> a "cheat sheet" do `mypy` </a>.
|
||||
|
||||
|
||||
204
docs/pt/docs/tutorial/body-updates.md
Normal file
204
docs/pt/docs/tutorial/body-updates.md
Normal file
@@ -0,0 +1,204 @@
|
||||
# Corpo - Atualizações
|
||||
|
||||
## Atualização de dados existentes com `PUT`
|
||||
|
||||
Para atualizar um item, você pode usar a operação <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PUT" class="external-link" target="_blank">HTTP `PUT`</a>.
|
||||
|
||||
Você pode usar `jsonable_encoder` para converter os dados de entrada em dados que podem ser armazenados como JSON (por exemplo, com um banco de dados NoSQL). Por exemplo, convertendo `datetime` em `str`.
|
||||
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="28-33"
|
||||
{!> ../../../docs_src/body_updates/tutorial001_py310.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.9+
|
||||
|
||||
```Python hl_lines="30-35"
|
||||
{!> ../../../docs_src/body_updates/tutorial001_py39.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="30-35"
|
||||
{!> ../../../docs_src/body_updates/tutorial001.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
`PUT` é usado para receber dados que devem substituir os dados existentes.
|
||||
|
||||
### Aviso sobre a substituição
|
||||
|
||||
Isso significa que, se você quiser atualizar o item `bar` usando `PUT` com um corpo contendo:
|
||||
|
||||
```Python
|
||||
{
|
||||
"name": "Barz",
|
||||
"price": 3,
|
||||
"description": None,
|
||||
}
|
||||
```
|
||||
|
||||
Como ele não inclui o atributo já armazenado `"tax": 20.2`, o modelo de entrada assumiria o valor padrão de `"tax": 10.5`.
|
||||
|
||||
E os dados seriam salvos com esse "novo" `tax` de `10.5`.
|
||||
|
||||
## Atualizações parciais com `PATCH`
|
||||
|
||||
Você também pode usar a operação <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PATCH" class="external-link" target="_blank">HTTP `PATCH`</a> para *atualizar* parcialmente os dados.
|
||||
|
||||
Isso significa que você pode enviar apenas os dados que deseja atualizar, deixando o restante intacto.
|
||||
|
||||
/// note | Nota
|
||||
|
||||
`PATCH` é menos comumente usado e conhecido do que `PUT`.
|
||||
|
||||
E muitas equipes usam apenas `PUT`, mesmo para atualizações parciais.
|
||||
|
||||
Você é **livre** para usá-los como preferir, **FastAPI** não impõe restrições.
|
||||
|
||||
Mas este guia te dá uma ideia de como eles são destinados a serem usados.
|
||||
|
||||
///
|
||||
|
||||
### Usando o parâmetro `exclude_unset` do Pydantic
|
||||
|
||||
Se você quiser receber atualizações parciais, é muito útil usar o parâmetro `exclude_unset` no método `.model_dump()` do modelo do Pydantic.
|
||||
|
||||
Como `item.model_dump(exclude_unset=True)`.
|
||||
|
||||
/// info | Informação
|
||||
|
||||
No Pydantic v1, o método que era chamado `.dict()` e foi depreciado (mas ainda suportado) no Pydantic v2. Agora, deve-se usar o método `.model_dump()`.
|
||||
|
||||
Os exemplos aqui usam `.dict()` para compatibilidade com o Pydantic v1, mas você deve usar `.model_dump()` a partir do Pydantic v2.
|
||||
|
||||
///
|
||||
|
||||
Isso gera um `dict` com apenas os dados definidos ao criar o modelo `item`, excluindo os valores padrão.
|
||||
|
||||
Então, você pode usar isso para gerar um `dict` com apenas os dados definidos (enviados na solicitação), omitindo valores padrão:
|
||||
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="32"
|
||||
{!> ../../../docs_src/body_updates/tutorial002_py310.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.9+
|
||||
|
||||
```Python hl_lines="34"
|
||||
{!> ../../../docs_src/body_updates/tutorial002_py39.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="34"
|
||||
{!> ../../../docs_src/body_updates/tutorial002.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
### Usando o parâmetro `update` do Pydantic
|
||||
|
||||
Agora, você pode criar uma cópia do modelo existente usando `.model_copy()`, e passar o parâmetro `update` com um `dict` contendo os dados para atualizar.
|
||||
|
||||
/// info | Informação
|
||||
|
||||
No Pydantic v1, o método era chamado `.copy()`, ele foi depreciado (mas ainda suportado) no Pydantic v2, e renomeado para `.model_copy()`.
|
||||
|
||||
Os exemplos aqui usam `.copy()` para compatibilidade com o Pydantic v1, mas você deve usar `.model_copy()` com o Pydantic v2.
|
||||
|
||||
///
|
||||
|
||||
Como `stored_item_model.model_copy(update=update_data)`:
|
||||
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="33"
|
||||
{!> ../../../docs_src/body_updates/tutorial002_py310.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.9+
|
||||
|
||||
```Python hl_lines="35"
|
||||
{!> ../../../docs_src/body_updates/tutorial002_py39.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="35"
|
||||
{!> ../../../docs_src/body_updates/tutorial002.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
### Recapitulando as atualizações parciais
|
||||
|
||||
Resumindo, para aplicar atualizações parciais você pode:
|
||||
|
||||
* (Opcionalmente) usar `PATCH` em vez de `PUT`.
|
||||
* Recuperar os dados armazenados.
|
||||
* Colocar esses dados em um modelo do Pydantic.
|
||||
* Gerar um `dict` sem valores padrão a partir do modelo de entrada (usando `exclude_unset`).
|
||||
* Dessa forma, você pode atualizar apenas os valores definidos pelo usuário, em vez de substituir os valores já armazenados com valores padrão em seu modelo.
|
||||
* Criar uma cópia do modelo armazenado, atualizando seus atributos com as atualizações parciais recebidas (usando o parâmetro `update`).
|
||||
* Converter o modelo copiado em algo que possa ser armazenado no seu banco de dados (por exemplo, usando o `jsonable_encoder`).
|
||||
* Isso é comparável ao uso do método `.model_dump()`, mas garante (e converte) os valores para tipos de dados que possam ser convertidos em JSON, por exemplo, `datetime` para `str`.
|
||||
* Salvar os dados no seu banco de dados.
|
||||
* Retornar o modelo atualizado.
|
||||
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="28-35"
|
||||
{!> ../../../docs_src/body_updates/tutorial002_py310.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.9+
|
||||
|
||||
```Python hl_lines="30-37"
|
||||
{!> ../../../docs_src/body_updates/tutorial002_py39.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="30-37"
|
||||
{!> ../../../docs_src/body_updates/tutorial002.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
/// tip | Dica
|
||||
|
||||
Você pode realmente usar essa mesma técnica com uma operação HTTP `PUT`.
|
||||
|
||||
Mas o exemplo aqui usa `PATCH` porque foi criado para esses casos de uso.
|
||||
|
||||
///
|
||||
|
||||
/// note | Nota
|
||||
|
||||
Observe que o modelo de entrada ainda é validado.
|
||||
|
||||
Portanto, se você quiser receber atualizações parciais que possam omitir todos os atributos, precisará ter um modelo com todos os atributos marcados como opcionais (com valores padrão ou `None`).
|
||||
|
||||
Para distinguir os modelos com todos os valores opcionais para **atualizações** e modelos com valores obrigatórios para **criação**, você pode usar as ideias descritas em [Modelos Adicionais](extra-models.md){.internal-link target=_blank}.
|
||||
|
||||
///
|
||||
184
docs/pt/docs/tutorial/header-param-models.md
Normal file
184
docs/pt/docs/tutorial/header-param-models.md
Normal file
@@ -0,0 +1,184 @@
|
||||
# Modelos de Parâmetros do Cabeçalho
|
||||
|
||||
Se você possui um grupo de **parâmetros de cabeçalho** relacionados, você pode criar um **modelo do Pydantic** para declará-los.
|
||||
|
||||
Isso vai lhe permitir **reusar o modelo** em **múltiplos lugares** e também declarar validações e metadadados para todos os parâmetros de uma vez. 😎
|
||||
|
||||
/// note | Nota
|
||||
|
||||
Isso é possível desde a versão `0.115.0` do FastAPI. 🤓
|
||||
|
||||
///
|
||||
|
||||
## Parâmetros do Cabeçalho com um Modelo Pydantic
|
||||
|
||||
Declare os **parâmetros de cabeçalho** que você precisa em um **modelo do Pydantic**, e então declare o parâmetro como `Header`:
|
||||
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="9-14 18"
|
||||
{!> ../../docs_src/header_param_models/tutorial001_an_py310.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.9+
|
||||
|
||||
```Python hl_lines="9-14 18"
|
||||
{!> ../../docs_src/header_param_models/tutorial001_an_py39.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="10-15 19"
|
||||
{!> ../../docs_src/header_param_models/tutorial001_an.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.10+ non-Annotated
|
||||
|
||||
/// tip | Dica
|
||||
|
||||
Utilize a versão com `Annotated` se possível.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="7-12 16"
|
||||
{!> ../../docs_src/header_param_models/tutorial001_py310.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.9+ non-Annotated
|
||||
|
||||
/// tip | Dica
|
||||
|
||||
Utilize a versão com `Annotated` se possível.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="9-14 18"
|
||||
{!> ../../docs_src/header_param_models/tutorial001_py39.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+ non-Annotated
|
||||
|
||||
/// tip | Dica
|
||||
|
||||
Utilize a versão com `Annotated` se possível.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="7-12 16"
|
||||
{!> ../../docs_src/header_param_models/tutorial001_py310.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
O **FastAPI** irá **extrair** os dados de **cada campo** a partir dos **cabeçalhos** da requisição e te retornará o modelo do Pydantic que você definiu.
|
||||
|
||||
### Checando a documentação
|
||||
|
||||
Você pode ver os headers necessários na interface gráfica da documentação em `/docs`:
|
||||
|
||||
<div class="screenshot">
|
||||
<img src="/img/tutorial/header-param-models/image01.png">
|
||||
</div>
|
||||
|
||||
### Proibindo Cabeçalhos adicionais
|
||||
|
||||
Em alguns casos de uso especiais (provavelmente não muito comuns), você pode querer **restringir** os cabeçalhos que você quer receber.
|
||||
|
||||
Você pode usar a configuração dos modelos do Pydantic para proibir (`forbid`) quaisquer campos `extra`:
|
||||
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="10"
|
||||
{!> ../../docs_src/header_param_models/tutorial002_an_py310.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.9+
|
||||
|
||||
```Python hl_lines="10"
|
||||
{!> ../../docs_src/header_param_models/tutorial002_an_py39.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="11"
|
||||
{!> ../../docs_src/header_param_models/tutorial002_an.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.10+ non-Annotated
|
||||
|
||||
/// tip | Dica
|
||||
|
||||
Utilize a versão com `Annotated` se possível.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="8"
|
||||
{!> ../../docs_src/header_param_models/tutorial002_py310.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.9+ non-Annotated
|
||||
|
||||
/// tip | Dica
|
||||
|
||||
Utilize a versão com `Annotated` se possível.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="10"
|
||||
{!> ../../docs_src/header_param_models/tutorial002_py39.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+ non-Annotated
|
||||
|
||||
/// tip | Dica
|
||||
|
||||
Utilize a versão com `Annotated` se possível.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="10"
|
||||
{!> ../../docs_src/header_param_models/tutorial002.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
Se um cliente tentar enviar alguns **cabeçalhos extra**, eles irão receber uma resposta de **erro**.
|
||||
|
||||
Por exemplo, se o cliente tentar enviar um cabeçalho `tool` com o valor `plumbus`, ele irá receber uma resposta de **erro** informando que o parâmetro do cabeçalho `tool` não é permitido:
|
||||
|
||||
```json
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"type": "extra_forbidden",
|
||||
"loc": ["header", "tool"],
|
||||
"msg": "Extra inputs are not permitted",
|
||||
"input": "plumbus",
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## Resumo
|
||||
|
||||
Você pode utilizar **modelos do Pydantic** para declarar **cabeçalhos** no **FastAPI**. 😎
|
||||
197
docs/pt/docs/tutorial/query-param-models.md
Normal file
197
docs/pt/docs/tutorial/query-param-models.md
Normal file
@@ -0,0 +1,197 @@
|
||||
# Modelos de Parâmetros de Consulta
|
||||
|
||||
Se você possui um grupo de **parâmetros de consultas** que são relacionados, você pode criar um **modelo Pydantic** para declará-los.
|
||||
|
||||
Isso permitiria que você **reutilizasse o modelo** em **diversos lugares**, e também declarasse validações e metadados de todos os parâmetros de uma única vez. 😎
|
||||
|
||||
/// note | Nota
|
||||
|
||||
Isso é suportado desde o FastAPI versão `0.115.0`. 🤓
|
||||
|
||||
///
|
||||
|
||||
## Parâmetros de Consulta com um Modelo Pydantic
|
||||
|
||||
Declare os **parâmetros de consulta** que você precisa em um **modelo Pydantic**, e então declare o parâmetro como `Query`:
|
||||
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="9-13 17"
|
||||
{!> ../../docs_src/query_param_models/tutorial001_an_py310.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.9+
|
||||
|
||||
```Python hl_lines="8-12 16"
|
||||
{!> ../../docs_src/query_param_models/tutorial001_an_py39.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="10-14 18"
|
||||
{!> ../../docs_src/query_param_models/tutorial001_an.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.10+ non-Annotated
|
||||
|
||||
/// tip | Dica
|
||||
|
||||
Prefira utilizar a versão `Annotated` se possível.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="9-13 17"
|
||||
{!> ../../docs_src/query_param_models/tutorial001_py310.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.9+ non-Annotated
|
||||
|
||||
/// tip | Dica
|
||||
|
||||
Prefira utilizar a versão `Annotated` se possível.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="8-12 16"
|
||||
{!> ../../docs_src/query_param_models/tutorial001_py39.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+ non-Annotated
|
||||
|
||||
/// tip | Dica
|
||||
|
||||
Prefira utilizar a versão `Annotated` se possível.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="9-13 17"
|
||||
{!> ../../docs_src/query_param_models/tutorial001_py310.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
O **FastAPI** **extrairá** os dados para **cada campo** dos **parâmetros de consulta** presentes na requisição, e fornecerá o modelo Pydantic que você definiu.
|
||||
|
||||
|
||||
## Verifique os Documentos
|
||||
|
||||
Você pode ver os parâmetros de consulta nos documentos de IU em `/docs`:
|
||||
|
||||
<div class="screenshot">
|
||||
<img src="/img/tutorial/query-param-models/image01.png">
|
||||
</div>
|
||||
|
||||
## Restrinja Parâmetros de Consulta Extras
|
||||
|
||||
Em alguns casos especiais (provavelmente não muito comuns), você queira **restrinjir** os parâmetros de consulta que deseja receber.
|
||||
|
||||
Você pode usar a configuração do modelo Pydantic para `forbid` (proibir) qualquer campo `extra`:
|
||||
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="10"
|
||||
{!> ../../docs_src/query_param_models/tutorial002_an_py310.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.9+
|
||||
|
||||
```Python hl_lines="9"
|
||||
{!> ../../docs_src/query_param_models/tutorial002_an_py39.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="11"
|
||||
{!> ../../docs_src/query_param_models/tutorial002_an.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.10+ non-Annotated
|
||||
|
||||
/// tip | Dica
|
||||
|
||||
Prefira utilizar a versão `Annotated` se possível.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="10"
|
||||
{!> ../../docs_src/query_param_models/tutorial002_py310.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.9+ non-Annotated
|
||||
|
||||
/// tip | Dica
|
||||
|
||||
Prefira utilizar a versão `Annotated` se possível.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="9"
|
||||
{!> ../../docs_src/query_param_models/tutorial002_py39.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+ non-Annotated
|
||||
|
||||
/// tip | Dica
|
||||
|
||||
Prefira utilizar a versão `Annotated` se possível.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="11"
|
||||
{!> ../../docs_src/query_param_models/tutorial002.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
Caso um cliente tente enviar alguns dados **extras** nos **parâmetros de consulta**, eles receberão um retorno de **erro**.
|
||||
|
||||
Por exemplo, se o cliente tentar enviar um parâmetro de consulta `tool` com o valor `plumbus`, como:
|
||||
|
||||
```http
|
||||
https://example.com/items/?limit=10&tool=plumbus
|
||||
```
|
||||
|
||||
Eles receberão um retorno de **erro** informando-os que o parâmentro de consulta `tool` não é permitido:
|
||||
|
||||
```json
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"type": "extra_forbidden",
|
||||
"loc": ["query", "tool"],
|
||||
"msg": "Extra inputs are not permitted",
|
||||
"input": "plumbus"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## Resumo
|
||||
|
||||
Você pode utilizar **modelos Pydantic** para declarar **parâmetros de consulta** no **FastAPI**. 😎
|
||||
|
||||
/// tip | Dica
|
||||
|
||||
Alerta de spoiler: você também pode utilizar modelos Pydantic para declarar cookies e cabeçalhos, mas você irá ler sobre isso mais a frente no tutorial. 🤫
|
||||
|
||||
///
|
||||
359
docs/pt/docs/tutorial/sql-databases.md
Normal file
359
docs/pt/docs/tutorial/sql-databases.md
Normal file
@@ -0,0 +1,359 @@
|
||||
# Bancos de Dados SQL (Relacionais)
|
||||
|
||||
**FastAPI** não exige que você use um banco de dados SQL (relacional). Mas você pode usar **qualquer banco de dados** que quiser.
|
||||
|
||||
Aqui veremos um exemplo usando <a href="https://sqlmodel.tiangolo.com/" class="external-link" target="_blank">SQLModel</a>.
|
||||
|
||||
**SQLModel** é construído sobre <a href="https://www.sqlalchemy.org/" class="external-link" target="_blank">SQLAlchemy</a> e Pydantic. Ele foi criado pelo mesmo autor do **FastAPI** para ser o par perfeito para aplicações **FastAPI** que precisam usar **bancos de dados SQL**.
|
||||
|
||||
/// tip | Dica
|
||||
|
||||
Você pode usar qualquer outra biblioteca de banco de dados SQL ou NoSQL que quiser (em alguns casos chamadas de <abbr title="Object Relational Mapper, um termo sofisticado para uma biblioteca onde algumas classes representam tabelas SQL e instâncias representam linhas nessas tabelas">"ORMs"</abbr>), o FastAPI não obriga você a usar nada. 😎
|
||||
|
||||
///
|
||||
|
||||
Como o SQLModel é baseado no SQLAlchemy, você pode facilmente usar **qualquer banco de dados suportado** pelo SQLAlchemy (o que também os torna suportados pelo SQLModel), como:
|
||||
|
||||
* PostgreSQL
|
||||
* MySQL
|
||||
* SQLite
|
||||
* Oracle
|
||||
* Microsoft SQL Server, etc.
|
||||
|
||||
Neste exemplo, usaremos **SQLite**, porque ele usa um único arquivo e o Python tem suporte integrado. Assim, você pode copiar este exemplo e executá-lo como está.
|
||||
|
||||
Mais tarde, para sua aplicação em produção, você pode querer usar um servidor de banco de dados como o **PostgreSQL**.
|
||||
|
||||
/// tip | Dica
|
||||
|
||||
Existe um gerador de projetos oficial com **FastAPI** e **PostgreSQL** incluindo um frontend e mais ferramentas: <a href="https://github.com/fastapi/full-stack-fastapi-template" class="external-link" target="_blank">https://github.com/fastapi/full-stack-fastapi-template</a>
|
||||
|
||||
///
|
||||
|
||||
Este é um tutorial muito simples e curto, se você quiser aprender sobre bancos de dados em geral, sobre SQL ou recursos mais avançados, acesse a <a href="https://sqlmodel.tiangolo.com/" class="external-link" target="_blank">documentação do SQLModel</a>.
|
||||
|
||||
## Instalar o `SQLModel`
|
||||
|
||||
Primeiro, certifique-se de criar seu [ambiente virtual](../virtual-environments.md){.internal-link target=_blank}, ativá-lo e, em seguida, instalar o `sqlmodel`:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ pip install sqlmodel
|
||||
---> 100%
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
## Criar o App com um Único Modelo
|
||||
|
||||
Vamos criar a primeira versão mais simples do app com um único modelo **SQLModel**.
|
||||
|
||||
Depois, vamos melhorá-lo aumentando a segurança e versatilidade com **múltiplos modelos** abaixo. 🤓
|
||||
|
||||
### Criar Modelos
|
||||
|
||||
Importe o `SQLModel` e crie um modelo de banco de dados:
|
||||
|
||||
{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[1:11] hl[7:11] *}
|
||||
|
||||
A classe `Hero` é muito semelhante a um modelo Pydantic (na verdade, por baixo dos panos, ela *é um modelo Pydantic*).
|
||||
|
||||
Existem algumas diferenças:
|
||||
|
||||
* `table=True` informa ao SQLModel que este é um *modelo de tabela*, ele deve representar uma **tabela** no banco de dados SQL, não é apenas um *modelo de dados* (como seria qualquer outra classe Pydantic comum).
|
||||
|
||||
* `Field(primary_key=True)` informa ao SQLModel que o `id` é a **chave primária** no banco de dados SQL (você pode aprender mais sobre chaves primárias SQL na documentação do SQLModel).
|
||||
|
||||
Ao ter o tipo como `int | None`, o SQLModel saberá que essa coluna deve ser um `INTEGER` no banco de dados SQL e que ela deve ser `NULLABLE`.
|
||||
|
||||
* `Field(index=True)` informa ao SQLModel que ele deve criar um **índice SQL** para essa coluna, o que permitirá buscas mais rápidas no banco de dados ao ler dados filtrados por essa coluna.
|
||||
|
||||
O SQLModel saberá que algo declarado como `str` será uma coluna SQL do tipo `TEXT` (ou `VARCHAR`, dependendo do banco de dados).
|
||||
|
||||
### Criar um Engine
|
||||
Um `engine` SQLModel (por baixo dos panos, ele é na verdade um `engine` do SQLAlchemy) é o que **mantém as conexões** com o banco de dados.
|
||||
|
||||
Você teria **um único objeto `engine`** para todo o seu código se conectar ao mesmo banco de dados.
|
||||
|
||||
{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[14:18] hl[14:15,17:18] *}
|
||||
|
||||
Usar `check_same_thread=False` permite que o FastAPI use o mesmo banco de dados SQLite em diferentes threads. Isso é necessário, pois **uma única requisição** pode usar **mais de uma thread** (por exemplo, em dependências).
|
||||
|
||||
Não se preocupe, com a forma como o código está estruturado, garantiremos que usamos **uma única *sessão* SQLModel por requisição** mais tarde, isso é realmente o que o `check_same_thread` está tentando conseguir.
|
||||
|
||||
### Criar as Tabelas
|
||||
|
||||
Em seguida, adicionamos uma função que usa `SQLModel.metadata.create_all(engine)` para **criar as tabelas** para todos os *modelos de tabela*.
|
||||
|
||||
{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[21:22] hl[21:22] *}
|
||||
|
||||
### Criar uma Dependência de Sessão
|
||||
|
||||
Uma **`Session`** é o que armazena os **objetos na memória** e acompanha as alterações necessárias nos dados, para então **usar o `engine`** para se comunicar com o banco de dados.
|
||||
|
||||
Vamos criar uma **dependência** do FastAPI com `yield` que fornecerá uma nova `Session` para cada requisição. Isso é o que garante que usamos uma única sessão por requisição. 🤓
|
||||
|
||||
Então, criamos uma dependência `Annotated` chamada `SessionDep` para simplificar o restante do código que usará essa dependência.
|
||||
|
||||
{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[25:30] hl[25:27,30] *}
|
||||
|
||||
### Criar Tabelas de Banco de Dados na Inicialização
|
||||
|
||||
Vamos criar as tabelas do banco de dados quando o aplicativo for iniciado.
|
||||
|
||||
{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[32:37] hl[35:37] *}
|
||||
|
||||
Aqui, criamos as tabelas em um evento de inicialização do aplicativo.
|
||||
|
||||
Para produção, você provavelmente usaria um script de migração que é executado antes de iniciar seu app. 🤓
|
||||
|
||||
/// tip | Dica
|
||||
|
||||
O SQLModel terá utilitários de migração envolvendo o Alembic, mas por enquanto, você pode usar o <a href="https://alembic.sqlalchemy.org/en/latest/" class="external-link" target="_blank">Alembic</a> diretamente.
|
||||
|
||||
///
|
||||
|
||||
### Criar um Hero
|
||||
|
||||
Como cada modelo SQLModel também é um modelo Pydantic, você pode usá-lo nas mesmas **anotações de tipo** que usaria para modelos Pydantic.
|
||||
|
||||
Por exemplo, se você declarar um parâmetro do tipo `Hero`, ele será lido do **corpo JSON**.
|
||||
|
||||
Da mesma forma, você pode declará-lo como o **tipo de retorno** da função, e então o formato dos dados aparecerá na interface de documentação automática da API.
|
||||
|
||||
{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[40:45] hl[40:45] *}
|
||||
|
||||
</details>
|
||||
|
||||
Aqui, usamos a dependência `SessionDep` (uma `Session`) para adicionar o novo `Hero` à instância `Session`, fazer commit das alterações no banco de dados, atualizar os dados no `hero` e então retorná-lo.
|
||||
|
||||
### Ler Heroes
|
||||
|
||||
Podemos **ler** `Hero`s do banco de dados usando um `select()`. Podemos incluir um `limit` e `offset` para paginar os resultados.
|
||||
|
||||
{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[48:55] hl[51:52,54] *}
|
||||
|
||||
### Ler um Único Hero
|
||||
|
||||
Podemos **ler** um único `Hero`.
|
||||
|
||||
{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[58:63] hl[60] *}
|
||||
|
||||
### Deletar um Hero
|
||||
|
||||
Também podemos **deletar** um `Hero`.
|
||||
|
||||
{* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[66:73] hl[71] *}
|
||||
|
||||
### Executar o App
|
||||
|
||||
Você pode executar o app:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ fastapi dev main.py
|
||||
|
||||
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
Então, vá para a interface `/docs`, você verá que o **FastAPI** está usando esses **modelos** para **documentar** a API, e ele também os usará para **serializar** e **validar** os dados.
|
||||
|
||||
<div class="screenshot">
|
||||
<img src="/img/tutorial/sql-databases/image01.png">
|
||||
</div>
|
||||
|
||||
## Atualizar o App com Múltiplos Modelos
|
||||
|
||||
Agora vamos **refatorar** este app um pouco para aumentar a **segurança** e **versatilidade**.
|
||||
|
||||
Se você verificar o app anterior, na interface você pode ver que, até agora, ele permite que o cliente decida o `id` do `Hero` a ser criado. 😱
|
||||
|
||||
Não deveríamos deixar isso acontecer, eles poderiam sobrescrever um `id` que já atribuimos na base de dados. Decidir o `id` deve ser feito pelo **backend** ou pelo **banco de dados**, **não pelo cliente**.
|
||||
|
||||
Além disso, criamos um `secret_name` para o hero, mas até agora estamos retornando ele em todos os lugares, isso não é muito **secreto**... 😅
|
||||
|
||||
Vamos corrigir essas coisas adicionando alguns **modelos extras**. Aqui é onde o SQLModel vai brilhar. ✨
|
||||
|
||||
### Criar Múltiplos Modelos
|
||||
|
||||
No **SQLModel**, qualquer classe de modelo que tenha `table=True` é um **modelo de tabela**.
|
||||
|
||||
E qualquer classe de modelo que não tenha `table=True` é um **modelo de dados**, esses são na verdade apenas modelos Pydantic (com alguns recursos extras pequenos). 🤓
|
||||
|
||||
Com o SQLModel, podemos usar a **herança** para **evitar duplicação** de todos os campos em todos os casos.
|
||||
|
||||
#### `HeroBase` - a classe base
|
||||
|
||||
Vamos começar com um modelo `HeroBase` que tem todos os **campos compartilhados** por todos os modelos:
|
||||
|
||||
* `name`
|
||||
* `age`
|
||||
|
||||
{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[7:9] hl[7:9] *}
|
||||
|
||||
#### `Hero` - o *modelo de tabela*
|
||||
|
||||
Em seguida, vamos criar `Hero`, o verdadeiro *modelo de tabela*, com os **campos extras** que nem sempre estão nos outros modelos:
|
||||
|
||||
* `id`
|
||||
* `secret_name`
|
||||
|
||||
Como `Hero` herda de `HeroBase`, ele **também** tem os **campos** declarados em `HeroBase`, então todos os campos para `Hero` são:
|
||||
|
||||
* `id`
|
||||
* `name`
|
||||
* `age`
|
||||
* `secret_name`
|
||||
|
||||
{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[7:14] hl[12:14] *}
|
||||
|
||||
#### `HeroPublic` - o *modelo de dados* público
|
||||
|
||||
Em seguida, criamos um modelo `HeroPublic`, que será **retornado** para os clientes da API.
|
||||
|
||||
Ele tem os mesmos campos que `HeroBase`, então não incluirá `secret_name`.
|
||||
|
||||
Finalmente, a identidade dos nossos heróis está protegida! 🥷
|
||||
|
||||
Ele também declara novamente `id: int`. Ao fazer isso, estamos fazendo um **contrato** com os clientes da API, para que eles possam sempre esperar que o `id` estará lá e será um `int` (nunca será `None`).
|
||||
|
||||
/// tip | Dica
|
||||
|
||||
Fazer com que o modelo de retorno garanta que um valor esteja sempre disponível e sempre seja um `int` (não `None`) é muito útil para os clientes da API, eles podem escrever código muito mais simples com essa certeza.
|
||||
|
||||
Além disso, **clientes gerados automaticamente** terão interfaces mais simples, para que os desenvolvedores que se comunicam com sua API possam ter uma experiência muito melhor trabalhando com sua API. 😎
|
||||
|
||||
///
|
||||
|
||||
Todos os campos em `HeroPublic` são os mesmos que em `HeroBase`, com `id` declarado como `int` (não `None`):
|
||||
|
||||
* `id`
|
||||
* `name`
|
||||
* `age`
|
||||
* `secret_name`
|
||||
|
||||
{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[7:18] hl[17:18] *}
|
||||
|
||||
#### `HeroCreate` - o *modelo de dados* para criar um hero
|
||||
|
||||
Agora criamos um modelo `HeroCreate`, este é o que **validará** os dados dos clientes.
|
||||
|
||||
Ele tem os mesmos campos que `HeroBase`, e também tem `secret_name`.
|
||||
|
||||
Agora, quando os clientes **criarem um novo hero**, eles enviarão o `secret_name`, ele será armazenado no banco de dados, mas esses nomes secretos não serão retornados na API para os clientes.
|
||||
|
||||
/// tip | Dica
|
||||
|
||||
É assim que você trataria **senhas**. Receba-as, mas não as retorne na API.
|
||||
|
||||
Você também faria um **hash** com os valores das senhas antes de armazená-los, **nunca os armazene em texto simples**.
|
||||
|
||||
///
|
||||
|
||||
Os campos de `HeroCreate` são:
|
||||
|
||||
* `name`
|
||||
* `age`
|
||||
* `secret_name`
|
||||
|
||||
{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[7:22] hl[21:22] *}
|
||||
|
||||
#### `HeroUpdate` - o *modelo de dados* para atualizar um hero
|
||||
|
||||
Não tínhamos uma maneira de **atualizar um hero** na versão anterior do app, mas agora com **múltiplos modelos**, podemos fazer isso. 🎉
|
||||
|
||||
O *modelo de dados* `HeroUpdate` é um pouco especial, ele tem **todos os mesmos campos** que seriam necessários para criar um novo hero, mas todos os campos são **opcionais** (todos têm um valor padrão). Dessa forma, quando você atualizar um hero, poderá enviar apenas os campos que deseja atualizar.
|
||||
|
||||
Como todos os **campos realmente mudam** (o tipo agora inclui `None` e eles agora têm um valor padrão de `None`), precisamos **declarar novamente** todos eles.
|
||||
|
||||
Não precisamos herdar de `HeroBase`, pois estamos redeclarando todos os campos. Vou deixá-lo herdando apenas por consistência, mas isso não é necessário. É mais uma questão de gosto pessoal. 🤷
|
||||
|
||||
Os campos de `HeroUpdate` são:
|
||||
|
||||
* `name`
|
||||
* `age`
|
||||
* `secret_name`
|
||||
|
||||
{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[7:28] hl[25:28] *}
|
||||
|
||||
### Criar com `HeroCreate` e retornar um `HeroPublic`
|
||||
|
||||
Agora que temos **múltiplos modelos**, podemos atualizar as partes do app que os utilizam.
|
||||
|
||||
Recebemos na requisição um *modelo de dados* `HeroCreate`, e a partir dele, criamos um *modelo de tabela* `Hero`.
|
||||
|
||||
Esse novo *modelo de tabela* `Hero` terá os campos enviados pelo cliente, e também terá um `id` gerado pelo banco de dados.
|
||||
|
||||
Em seguida, retornamos o mesmo *modelo de tabela* `Hero` como está na função. Mas como declaramos o `response_model` com o *modelo de dados* `HeroPublic`, o **FastAPI** usará `HeroPublic` para validar e serializar os dados.
|
||||
|
||||
{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[56:62] hl[56:58] *}
|
||||
|
||||
/// tip | Dica
|
||||
|
||||
Agora usamos `response_model=HeroPublic` em vez da **anotação de tipo de retorno** `-> HeroPublic` porque o valor que estamos retornando na verdade *não* é um `HeroPublic`.
|
||||
|
||||
Se tivéssemos declarado `-> HeroPublic`, seu editor e o linter reclamariam (com razão) que você está retornando um `Hero` em vez de um `HeroPublic`.
|
||||
|
||||
Ao declará-lo no `response_model`, estamos dizendo ao **FastAPI** para fazer o seu trabalho, sem interferir nas anotações de tipo e na ajuda do seu editor e de outras ferramentas.
|
||||
|
||||
///
|
||||
|
||||
### Ler Heroes com `HeroPublic`
|
||||
|
||||
Podemos fazer o mesmo que antes para **ler** `Hero`s, novamente, usamos `response_model=list[HeroPublic]` para garantir que os dados sejam validados e serializados corretamente.
|
||||
|
||||
{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[65:72] hl[65] *}
|
||||
|
||||
### Ler Um Hero com `HeroPublic`
|
||||
|
||||
Podemos **ler** um único herói:
|
||||
|
||||
{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[75:80] hl[77] *}
|
||||
|
||||
### Atualizar um Hero com `HeroUpdate`
|
||||
|
||||
Podemos **atualizar um hero**. Para isso, usamos uma operação HTTP `PATCH`.
|
||||
|
||||
E no código, obtemos um `dict` com todos os dados enviados pelo cliente, **apenas os dados enviados pelo cliente**, excluindo quaisquer valores que estariam lá apenas por serem os valores padrão. Para fazer isso, usamos `exclude_unset=True`. Este é o truque principal. 🪄
|
||||
|
||||
Em seguida, usamos `hero_db.sqlmodel_update(hero_data)` para atualizar o `hero_db` com os dados de `hero_data`.
|
||||
|
||||
{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[83:93] hl[83:84,88:89] *}
|
||||
|
||||
### Deletar um Hero Novamente
|
||||
|
||||
**Deletar** um hero permanece praticamente o mesmo.
|
||||
|
||||
Não vamos satisfazer o desejo de refatorar tudo neste aqui. 😅
|
||||
|
||||
{* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[96:103] hl[101] *}
|
||||
|
||||
### Executar o App Novamente
|
||||
|
||||
Você pode executar o app novamente:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ fastapi dev main.py
|
||||
|
||||
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
If you go to the `/docs` API UI, you will see that it is now updated, and it won't expect to receive the `id` from the client when creating a hero, etc.
|
||||
|
||||
<div class="screenshot">
|
||||
<img src="/img/tutorial/sql-databases/image02.png">
|
||||
</div>
|
||||
|
||||
## Recapitulando
|
||||
|
||||
Você pode usar <a href="https://sqlmodel.tiangolo.com/" class="external-link" target="_blank">**SQLModel**</a> para interagir com um banco de dados SQL e simplificar o código com *modelos de dados* e *modelos de tabela*.
|
||||
|
||||
Você pode aprender muito mais na documentação do **SQLModel**, há um mini <a href="https://sqlmodel.tiangolo.com/tutorial/fastapi/" class="external-link" target="_blank">tutorial sobre como usar SQLModel com **FastAPI**</a> mais longo. 🚀
|
||||
@@ -357,7 +357,7 @@ Molten мне попался на начальной стадии написан
|
||||
|
||||
///
|
||||
|
||||
### <a href="https://www.hug.rest/" class="external-link" target="_blank">Hug</a>
|
||||
### <a href="https://github.com/hugapi/hug" class="external-link" target="_blank">Hug</a>
|
||||
|
||||
Hug был одним из первых фреймворков, реализовавших объявление параметров API с использованием подсказок типов Python.
|
||||
Эта отличная идея была использована и другими инструментами.
|
||||
|
||||
297
docs/ru/docs/environment-variables.md
Normal file
297
docs/ru/docs/environment-variables.md
Normal file
@@ -0,0 +1,297 @@
|
||||
# Переменные окружения
|
||||
|
||||
/// tip
|
||||
|
||||
Если вы уже знаете, что такое «переменные окружения» и как их использовать, можете пропустить это.
|
||||
|
||||
///
|
||||
|
||||
Переменная окружения (также известная как «**env var**») - это переменная, которая живет **вне** кода Python, в **операционной системе**, и может быть прочитана вашим кодом Python (или другими программами).
|
||||
|
||||
Переменные окружения могут быть полезны для работы с **настройками** приложений, как часть **установки** Python и т.д.
|
||||
|
||||
## Создание и использование переменных окружения
|
||||
|
||||
Можно **создавать** и использовать переменные окружения в **оболочке (терминале)**, не прибегая к помощи Python:
|
||||
|
||||
//// tab | Linux, macOS, Windows Bash
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
// Вы можете создать переменную окружения MY_NAME с помощью
|
||||
$ export MY_NAME="Wade Wilson"
|
||||
|
||||
// Затем её можно использовать в других программах, например
|
||||
$ echo "Hello $MY_NAME"
|
||||
|
||||
Hello Wade Wilson
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
////
|
||||
|
||||
//// tab | Windows PowerShell
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
// Создайте переменную окружения MY_NAME
|
||||
$ $Env:MY_NAME = "Wade Wilson"
|
||||
|
||||
// Используйте её с другими программами, например
|
||||
$ echo "Hello $Env:MY_NAME"
|
||||
|
||||
Hello Wade Wilson
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
////
|
||||
|
||||
## Чтение переменных окружения в python
|
||||
|
||||
Так же существует возможность создания переменных окружения **вне** Python, в терминале (или любым другим способом), а затем **чтения их в Python**.
|
||||
|
||||
Например, у вас есть файл `main.py`:
|
||||
|
||||
```Python hl_lines="3"
|
||||
import os
|
||||
|
||||
name = os.getenv("MY_NAME", "World")
|
||||
print(f"Hello {name} from Python")
|
||||
```
|
||||
|
||||
/// tip
|
||||
|
||||
Второй аргумент <a href=«https://docs.python.org/3.8/library/os.html#os.getenv» class=«external-link» target=«_blank»>`os.getenv()`</a> - это возвращаемое по умолчанию значение.
|
||||
|
||||
Если значение не указано, то по умолчанию оно равно `None`. В данном случае мы указываем `«World»` в качестве значения по умолчанию.
|
||||
///
|
||||
|
||||
Затем можно запустить эту программу на Python:
|
||||
|
||||
//// tab | Linux, macOS, Windows Bash
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
// Здесь мы еще не устанавливаем переменную окружения
|
||||
$ python main.py
|
||||
|
||||
// Поскольку мы не задали переменную окружения, мы получим значение по умолчанию
|
||||
|
||||
Hello World from Python
|
||||
|
||||
// Но если мы сначала создадим переменную окружения
|
||||
$ export MY_NAME="Wade Wilson"
|
||||
|
||||
// А затем снова запустим программу
|
||||
$ python main.py
|
||||
|
||||
// Теперь она прочитает переменную окружения
|
||||
|
||||
Hello Wade Wilson from Python
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
////
|
||||
|
||||
//// tab | Windows PowerShell
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
// Здесь мы еще не устанавливаем переменную окружения
|
||||
$ python main.py
|
||||
|
||||
// Поскольку мы не задали переменную окружения, мы получим значение по умолчанию
|
||||
|
||||
Hello World from Python
|
||||
|
||||
// Но если мы сначала создадим переменную окружения
|
||||
$ $Env:MY_NAME = "Wade Wilson"
|
||||
|
||||
// А затем снова запустим программу
|
||||
$ python main.py
|
||||
|
||||
// Теперь она может прочитать переменную окружения
|
||||
|
||||
Hello Wade Wilson from Python
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
////
|
||||
|
||||
Поскольку переменные окружения могут быть установлены вне кода, но могут быть прочитаны кодом, и их не нужно хранить (фиксировать в `git`) вместе с остальными файлами, их принято использовать для конфигураций или **настроек**.
|
||||
|
||||
Вы также можете создать переменную окружения только для **конкретного вызова программы**, которая будет доступна только для этой программы и только на время ее выполнения.
|
||||
|
||||
Для этого создайте её непосредственно перед самой программой, в той же строке:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
// Создайте переменную окружения MY_NAME в строке для этого вызова программы
|
||||
$ MY_NAME="Wade Wilson" python main.py
|
||||
|
||||
// Теперь она может прочитать переменную окружения
|
||||
|
||||
Hello Wade Wilson from Python
|
||||
|
||||
// После этого переменная окружения больше не существует
|
||||
$ python main.py
|
||||
|
||||
Hello World from Python
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
/// tip
|
||||
|
||||
Подробнее об этом можно прочитать на сайте <a href="https://12factor.net/config" class="external-link" target="_blank">The Twelve-Factor App: Config</a>.
|
||||
|
||||
///
|
||||
|
||||
## Типизация и Валидация
|
||||
|
||||
Эти переменные окружения могут работать только с **текстовыми строками**, поскольку они являются внешними по отношению к Python и должны быть совместимы с другими программами и остальной системой (и даже с различными операционными системами, такими как Linux, Windows, macOS).
|
||||
|
||||
Это означает, что **любое значение**, считанное в Python из переменной окружения, **будет `str`**, и любое преобразование к другому типу или любая проверка должны быть выполнены в коде.
|
||||
|
||||
Подробнее об использовании переменных окружения для работы с **настройками приложения** вы узнаете в [Расширенное руководство пользователя - Настройки и переменные среды](./advanced/settings.md){.internal-link target=_blank}.
|
||||
|
||||
## Переменная окружения `PATH`
|
||||
|
||||
Существует **специальная** переменная окружения **`PATH`**, которая используется операционными системами (Linux, macOS, Windows) для поиска программ для запуска.
|
||||
|
||||
Значение переменной `PATH` - это длинная строка, состоящая из каталогов, разделенных двоеточием `:` в Linux и macOS, и точкой с запятой `;` в Windows.
|
||||
|
||||
Например, переменная окружения `PATH` может выглядеть следующим образом:
|
||||
|
||||
//// tab | Linux, macOS
|
||||
|
||||
```plaintext
|
||||
/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
|
||||
```
|
||||
|
||||
Это означает, что система должна искать программы в каталогах:
|
||||
|
||||
* `/usr/local/bin`
|
||||
* `/usr/bin`
|
||||
* `/bin`
|
||||
* `/usr/sbin`
|
||||
* `/sbin`
|
||||
|
||||
////
|
||||
|
||||
//// tab | Windows
|
||||
|
||||
```plaintext
|
||||
C:\Program Files\Python312\Scripts;C:\Program Files\Python312;C:\Windows\System32
|
||||
```
|
||||
|
||||
Это означает, что система должна искать программы в каталогах:
|
||||
|
||||
* `C:\Program Files\Python312\Scripts`
|
||||
* `C:\Program Files\Python312`
|
||||
* `C:\Windows\System32`
|
||||
|
||||
////
|
||||
|
||||
Когда вы вводите **команду** в терминале, операционная система **ищет** программу в **каждой из тех директорий**, которые перечислены в переменной окружения `PATH`.
|
||||
|
||||
Например, когда вы вводите `python` в терминале, операционная система ищет программу под названием `python` в **первой директории** в этом списке.
|
||||
|
||||
Если она ее находит, то **использует ее**. В противном случае она продолжает искать в **других каталогах**.
|
||||
|
||||
### Установка Python и обновление `PATH`
|
||||
|
||||
При установке Python вас могут спросить, нужно ли обновить переменную окружения `PATH`.
|
||||
|
||||
//// tab | Linux, macOS
|
||||
|
||||
Допустим, вы устанавливаете Python, и он оказывается в каталоге `/opt/custompython/bin`.
|
||||
|
||||
Если вы скажете «да», чтобы обновить переменную окружения `PATH`, то программа установки добавит `/opt/custompython/bin` в переменную окружения `PATH`.
|
||||
|
||||
Это может выглядеть следующим образом:
|
||||
|
||||
```plaintext
|
||||
/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/custompython/bin
|
||||
```
|
||||
|
||||
Таким образом, когда вы набираете `python` в терминале, система найдет программу Python в `/opt/custompython/bin` (последний каталог) и использует ее.
|
||||
|
||||
////
|
||||
|
||||
//// tab | Windows
|
||||
|
||||
Допустим, вы устанавливаете Python, и он оказывается в каталоге `C:\opt\custompython\bin`.
|
||||
|
||||
Если вы согласитесь обновить переменную окружения `PATH`, то программа установки добавит `C:\opt\custompython\bin` в переменную окружения `PATH`.
|
||||
|
||||
```plaintext
|
||||
C:\Program Files\Python312\Scripts;C:\Program Files\Python312;C:\Windows\System32;C:\opt\custompython\bin
|
||||
```
|
||||
|
||||
Таким образом, когда вы набираете `python` в терминале, система найдет программу Python в `C:\opt\custompython\bin` (последний каталог) и использует ее.
|
||||
|
||||
////
|
||||
|
||||
Итак, если вы напечатаете:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ python
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
//// tab | Linux, macOS
|
||||
|
||||
Система **найдет** программу `python` в `/opt/custompython/bin` и запустит ее.
|
||||
|
||||
Это примерно эквивалентно набору текста:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ /opt/custompython/bin/python
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
////
|
||||
|
||||
//// tab | Windows
|
||||
|
||||
Система **найдет** программу `python` в каталоге `C:\opt\custompython\bin\python` и запустит ее.
|
||||
|
||||
Это примерно эквивалентно набору текста:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ C:\opt\custompython\bin\python
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
////
|
||||
|
||||
Эта информация будет полезна при изучении [Виртуальных окружений](virtual-environments.md){.internal-link target=_blank}.
|
||||
|
||||
## Вывод
|
||||
|
||||
Благодаря этому вы должны иметь базовое представление о том, что такое **переменные окружения** и как использовать их в Python.
|
||||
|
||||
Подробнее о них вы также можете прочитать в <a href="https://en.wikipedia.org/wiki/Environment_variable" class="external-link" target="_blank">статье о переменных окружения на википедии</a>.
|
||||
|
||||
Во многих случаях не всегда очевидно, как переменные окружения могут быть полезны и применимы. Но они постоянно появляются в различных сценариях разработки, поэтому знать о них полезно.
|
||||
|
||||
Например, эта информация понадобится вам в следующем разделе, посвященном [Виртуальным окружениям](virtual-environments.md).
|
||||
@@ -93,7 +93,7 @@ FastAPI — это современный, быстрый (высокопрои
|
||||
|
||||
"_Честно говоря, то, что вы создали, выглядит очень солидно и отполировано. Во многих смыслах я хотел, чтобы **Hug** был именно таким — это действительно вдохновляет, когда кто-то создаёт такое._"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Timothy Crosley - <strong><a href="https://www.hug.rest/" target="_blank">Hug</a> creator</strong> <a href="https://news.ycombinator.com/item?id=19455465" target="_blank"><small>(ref)</small></a></div>
|
||||
<div style="text-align: right; margin-right: 10%;">Timothy Crosley - <strong><a href="https://github.com/hugapi/hug" target="_blank">Hug</a> creator</strong> <a href="https://news.ycombinator.com/item?id=19455465" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -319,7 +319,7 @@ Bu aslında Pydantic'in de aynı doğrulama stiline geçmesinde ilham kaynağı
|
||||
|
||||
///
|
||||
|
||||
### <a href="https://www.hug.rest/" class="external-link" target="_blank">Hug</a>
|
||||
### <a href="https://github.com/hugapi/hug" class="external-link" target="_blank">Hug</a>
|
||||
|
||||
Hug, Python tip belirteçlerini kullanarak API parametrelerinin tipini belirlemeyi uygulayan ilk framework'lerdendi. Bu, diğer araçlara da ilham kaynağı olan harika bir fikirdi.
|
||||
|
||||
|
||||
@@ -321,7 +321,7 @@ Falcon — ще один високопродуктивний фреймворк
|
||||
|
||||
///
|
||||
|
||||
### <a href="https://www.hug.rest/" class="external-link" target="_blank">Hug</a>
|
||||
### <a href="https://github.com/hugapi/hug" class="external-link" target="_blank">Hug</a>
|
||||
|
||||
Hug був одним із перших фреймворків, який реалізував оголошення типів параметрів API за допомогою підказок типу Python. Це була чудова ідея, яка надихнула інші інструменти зробити те саме.
|
||||
|
||||
|
||||
@@ -88,7 +88,7 @@ FastAPI - це сучасний, швидкий (високопродуктив
|
||||
|
||||
"_Honestly, what you've built looks super solid and polished. In many ways, it's what I wanted **Hug** to be - it's really inspiring to see someone build that._"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Timothy Crosley - <strong><a href="https://www.hug.rest/" target="_blank">Hug</a> creator</strong> <a href="https://news.ycombinator.com/item?id=19455465" target="_blank"><small>(ref)</small></a></div>
|
||||
<div style="text-align: right; margin-right: 10%;">Timothy Crosley - <strong><a href="https://github.com/hugapi/hug" target="_blank">Hug</a> creator</strong> <a href="https://news.ycombinator.com/item?id=19455465" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -93,7 +93,7 @@ Những tính năng như:
|
||||
|
||||
"_Thành thật, những gì bạn đã xây dựng nhìn siêu chắc chắn và bóng bẩy. Theo nhiều cách, nó là những gì tôi đã muốn Hug trở thành - thật sự truyền cảm hứng để thấy ai đó xây dựng nó._"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Timothy Crosley - người tạo ra <strong><a href="https://www.hug.rest/" target="_blank">Hug</a></strong> <a href="https://news.ycombinator.com/item?id=19455465" target="_blank"><small>(ref)</small></a></div>
|
||||
<div style="text-align: right; margin-right: 10%;">Timothy Crosley - người tạo ra <strong><a href="https://github.com/hugapi/hug" target="_blank">Hug</a></strong> <a href="https://news.ycombinator.com/item?id=19455465" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -93,7 +93,7 @@ FastAPI jẹ́ ìgbàlódé, tí ó yára (iṣẹ-giga), ìlànà wẹ́ẹ́b
|
||||
|
||||
"_Ní tòótọ́, ohun tí o kọ dára ó sì tún dán. Ní ọ̀pọ̀lọpọ̀ ọ̀nà, ohun tí mo fẹ́ kí **Hug** jẹ́ nìyẹn - ó wúni lórí gan-an láti rí ẹnìkan tí ó kọ́ nǹkan bí èyí._"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Timothy Crosley - <strong><a href="https://www.hug.rest/" target="_blank">Hug</a> creator</strong> <a href="https://news.ycombinator.com/item?id=19455465" target="_blank"><small>(ref)</small></a></div>
|
||||
<div style="text-align: right; margin-right: 10%;">Timothy Crosley - <strong><a href="https://github.com/hugapi/hug" target="_blank">Hug</a> creator</strong> <a href="https://news.ycombinator.com/item?id=19455465" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
|
||||
3
docs/zh-hant/docs/about/index.md
Normal file
3
docs/zh-hant/docs/about/index.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# 關於 FastAPI
|
||||
|
||||
關於 FastAPI、其設計、靈感來源等更多資訊。 🤓
|
||||
17
docs/zh-hant/docs/deployment/cloud.md
Normal file
17
docs/zh-hant/docs/deployment/cloud.md
Normal file
@@ -0,0 +1,17 @@
|
||||
# 在雲端部署 FastAPI
|
||||
|
||||
你幾乎可以使用**任何雲端供應商**來部署你的 FastAPI 應用程式。
|
||||
|
||||
在大多數情況下,主要的雲端供應商都有部署 FastAPI 的指南。
|
||||
|
||||
## 雲端供應商 - 贊助商
|
||||
|
||||
一些雲端供應商 ✨ [**贊助 FastAPI**](../help-fastapi.md#sponsor-the-author){.internal-link target=_blank} ✨,這確保了 FastAPI 及其**生態系統**持續健康地**發展**。
|
||||
|
||||
這也展現了他們對 FastAPI 和其**社群**(包括你)的真正承諾,他們不僅希望為你提供**優質的服務**,還希望確保你擁有一個**良好且健康的框架**:FastAPI。🙇
|
||||
|
||||
你可能會想嘗試他們的服務,以下有他們的指南:
|
||||
|
||||
* <a href="https://docs.platform.sh/languages/python.html?utm_source=fastapi-signup&utm_medium=banner&utm_campaign=FastAPI-signup-June-2023" class="external-link" target="_blank" >Platform.sh</a>
|
||||
* <a href="https://docs.porter.run/language-specific-guides/fastapi" class="external-link" target="_blank">Porter</a>
|
||||
* <a href="https://docs.withcoherence.com/" class="external-link" target="_blank">Coherence</a>
|
||||
21
docs/zh-hant/docs/deployment/index.md
Normal file
21
docs/zh-hant/docs/deployment/index.md
Normal file
@@ -0,0 +1,21 @@
|
||||
# 部署
|
||||
|
||||
部署 **FastAPI** 應用程式相對容易。
|
||||
|
||||
## 部署是什麼意思
|
||||
|
||||
**部署**應用程式指的是執行一系列必要的步驟,使其能夠**讓使用者存取和使用**。
|
||||
|
||||
對於一個 **Web API**,部署通常涉及將其放置在**遠端伺服器**上,並使用性能優良且穩定的**伺服器程式**,確保使用者能夠高效、無中斷地存取應用程式,且不會遇到問題。
|
||||
|
||||
這與**開發**階段形成鮮明對比,在**開發**階段,你會不斷更改程式碼、破壞程式碼、修復程式碼,然後停止和重新啟動伺服器等。
|
||||
|
||||
## 部署策略
|
||||
|
||||
根據你的使用場景和使用工具,有多種方法可以實現此目的。
|
||||
|
||||
你可以使用一些工具自行**部署伺服器**,你也可以使用能為你完成部分工作的**雲端服務**,或其他可能的選項。
|
||||
|
||||
我將向你展示在部署 **FastAPI** 應用程式時你可能應該記住的一些主要概念(儘管其中大部分適用於任何其他類型的 Web 應用程式)。
|
||||
|
||||
在接下來的部分中,你將看到更多需要記住的細節以及一些技巧。 ✨
|
||||
83
docs/zh-hant/docs/fastapi-cli.md
Normal file
83
docs/zh-hant/docs/fastapi-cli.md
Normal file
@@ -0,0 +1,83 @@
|
||||
# FastAPI CLI
|
||||
|
||||
**FastAPI CLI** 是一個命令列程式,能用來運行你的 FastAPI 應用程式、管理你的 FastAPI 專案等。
|
||||
|
||||
當你安裝 FastAPI(例如使用 `pip install "fastapi[standard]"`),它會包含一個叫做 `fastapi-cli` 的套件,這個套件提供了 `fastapi` 命令。
|
||||
|
||||
要運行你的 FastAPI 應用程式來進行開發,你可以使用 `fastapi dev` 命令:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ <font color="#4E9A06">fastapi</font> dev <u style="text-decoration-style:single">main.py</u>
|
||||
<font color="#3465A4">INFO </font> Using path <font color="#3465A4">main.py</font>
|
||||
<font color="#3465A4">INFO </font> Resolved absolute path <font color="#75507B">/home/user/code/awesomeapp/</font><font color="#AD7FA8">main.py</font>
|
||||
<font color="#3465A4">INFO </font> Searching for package file structure from directories with <font color="#3465A4">__init__.py</font> files
|
||||
<font color="#3465A4">INFO </font> Importing from <font color="#75507B">/home/user/code/</font><font color="#AD7FA8">awesomeapp</font>
|
||||
|
||||
╭─ <font color="#8AE234"><b>Python module file</b></font> ─╮
|
||||
│ │
|
||||
│ 🐍 main.py │
|
||||
│ │
|
||||
╰──────────────────────╯
|
||||
|
||||
<font color="#3465A4">INFO </font> Importing module <font color="#4E9A06">main</font>
|
||||
<font color="#3465A4">INFO </font> Found importable FastAPI app
|
||||
|
||||
╭─ <font color="#8AE234"><b>Importable FastAPI app</b></font> ─╮
|
||||
│ │
|
||||
│ <span style="background-color:#272822"><font color="#FF4689">from</font></span><span style="background-color:#272822"><font color="#F8F8F2"> main </font></span><span style="background-color:#272822"><font color="#FF4689">import</font></span><span style="background-color:#272822"><font color="#F8F8F2"> app</font></span><span style="background-color:#272822"> </span> │
|
||||
│ │
|
||||
╰──────────────────────────╯
|
||||
|
||||
<font color="#3465A4">INFO </font> Using import string <font color="#8AE234"><b>main:app</b></font>
|
||||
|
||||
<span style="background-color:#C4A000"><font color="#2E3436">╭────────── FastAPI CLI - Development mode ───────────╮</font></span>
|
||||
<span style="background-color:#C4A000"><font color="#2E3436">│ │</font></span>
|
||||
<span style="background-color:#C4A000"><font color="#2E3436">│ Serving at: http://127.0.0.1:8000 │</font></span>
|
||||
<span style="background-color:#C4A000"><font color="#2E3436">│ │</font></span>
|
||||
<span style="background-color:#C4A000"><font color="#2E3436">│ API docs: http://127.0.0.1:8000/docs │</font></span>
|
||||
<span style="background-color:#C4A000"><font color="#2E3436">│ │</font></span>
|
||||
<span style="background-color:#C4A000"><font color="#2E3436">│ Running in development mode, for production use: │</font></span>
|
||||
<span style="background-color:#C4A000"><font color="#2E3436">│ │</font></span>
|
||||
<span style="background-color:#C4A000"><font color="#2E3436">│ </font></span><span style="background-color:#C4A000"><font color="#555753"><b>fastapi run</b></font></span><span style="background-color:#C4A000"><font color="#2E3436"> │</font></span>
|
||||
<span style="background-color:#C4A000"><font color="#2E3436">│ │</font></span>
|
||||
<span style="background-color:#C4A000"><font color="#2E3436">╰─────────────────────────────────────────────────────╯</font></span>
|
||||
|
||||
<font color="#4E9A06">INFO</font>: Will watch for changes in these directories: ['/home/user/code/awesomeapp']
|
||||
<font color="#4E9A06">INFO</font>: Uvicorn running on <b>http://127.0.0.1:8000</b> (Press CTRL+C to quit)
|
||||
<font color="#4E9A06">INFO</font>: Started reloader process [<font color="#34E2E2"><b>2265862</b></font>] using <font color="#34E2E2"><b>WatchFiles</b></font>
|
||||
<font color="#4E9A06">INFO</font>: Started server process [<font color="#06989A">2265873</font>]
|
||||
<font color="#4E9A06">INFO</font>: Waiting for application startup.
|
||||
<font color="#4E9A06">INFO</font>: Application startup complete.
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
`fastapi` 命令列程式就是 **FastAPI CLI**。
|
||||
|
||||
FastAPI CLI 接收你的 Python 程式路徑(例如 `main.py`),並自動檢測 FastAPI 實例(通常命名為 `app`),確定正確的引入模組流程,然後運行該應用程式。
|
||||
|
||||
在生產環境,你應該使用 `fastapi run` 命令。 🚀
|
||||
|
||||
**FastAPI CLI** 內部使用了 <a href="https://www.uvicorn.org" class="external-link" target="_blank">Uvicorn</a>,這是一個高效能、適合生產環境的 ASGI 伺服器。 😎
|
||||
|
||||
## `fastapi dev`
|
||||
|
||||
執行 `fastapi dev` 會啟動開發模式。
|
||||
|
||||
預設情況下,**auto-reload** 功能是啟用的,當你對程式碼進行修改時,伺服器會自動重新載入。這會消耗較多資源,並且可能比禁用時更不穩定。因此,你應該只在開發環境中使用此功能。它也會在 IP 位址 `127.0.0.1` 上監聽,這是用於你的機器與自身通訊的 IP 位址(`localhost`)。
|
||||
|
||||
## `fastapi run`
|
||||
|
||||
執行 `fastapi run` 會以生產模式啟動 FastAPI。
|
||||
|
||||
預設情況下,**auto-reload** 功能是禁用的。它也會在 IP 位址 `0.0.0.0` 上監聽,表示會監聽所有可用的 IP 地址,這樣任何能與該機器通訊的人都可以公開存取它。這通常是你在生產環境中運行應用程式的方式,例如在容器中運行時。
|
||||
|
||||
在大多數情況下,你會(也應該)有一個「終止代理」來處理 HTTPS,這取決於你如何部署你的應用程式,你的服務供應商可能會為你做這件事,或者你需要自己設置它。
|
||||
|
||||
/// tip
|
||||
|
||||
你可以在[部署文件](deployment/index.md){.internal-link target=_blank}中了解更多相關資訊。
|
||||
|
||||
///
|
||||
13
docs/zh-hant/docs/how-to/index.md
Normal file
13
docs/zh-hant/docs/how-to/index.md
Normal file
@@ -0,0 +1,13 @@
|
||||
# 使用指南 - 範例集
|
||||
|
||||
在這裡,你將會看到**不同主題**的範例或「如何使用」的指南。
|
||||
|
||||
大多數這些想法都是**獨立**的,在大多數情況下,你只需要研究那些直接適用於**你的專案**的東西。
|
||||
|
||||
如果有些東西看起來很有趣且對你的專案很有用的話再去讀它,否則你可能可以跳過它們。
|
||||
|
||||
/// tip
|
||||
|
||||
如果你想要以結構化的方式**學習 FastAPI**(推薦),請前往[教學 - 使用者指南](../tutorial/index.md){.internal-link target=_blank}逐章閱讀。
|
||||
|
||||
///
|
||||
@@ -87,7 +87,7 @@ FastAPI 是一個現代、快速(高效能)的 web 框架,用於 Python
|
||||
|
||||
"_老實說,你建造的東西看起來非常堅固和精緻。在很多方面,這就是我想要的,看到有人建造它真的很鼓舞人心。_"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Timothy Crosley - <strong><a href="https://www.hug.rest/" target="_blank">Hug</a> creator</strong> <a href="https://news.ycombinator.com/item?id=19455465" target="_blank"><small>(ref)</small></a></div>
|
||||
<div style="text-align: right; margin-right: 10%;">Timothy Crosley - <strong><a href="https://github.com/hugapi/hug" target="_blank">Hug</a> creator</strong> <a href="https://news.ycombinator.com/item?id=19455465" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
|
||||
3
docs/zh-hant/docs/resources/index.md
Normal file
3
docs/zh-hant/docs/resources/index.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# 資源
|
||||
|
||||
額外的資源、外部連結、文章等。 ✈️
|
||||
102
docs/zh-hant/docs/tutorial/index.md
Normal file
102
docs/zh-hant/docs/tutorial/index.md
Normal file
@@ -0,0 +1,102 @@
|
||||
# 教學 - 使用者指南
|
||||
|
||||
本教學將一步一步展示如何使用 **FastAPI** 及其大多數功能。
|
||||
|
||||
每個部分都是在前一部分的基礎上逐步建置的,但內容結構是按主題分開的,因此你可以直接跳到任何特定的部分,解決你具體的 API 需求。
|
||||
|
||||
它也被設計成可作為未來的參考,讓你隨時回來查看所需的內容。
|
||||
|
||||
## 運行程式碼
|
||||
|
||||
所有程式碼區塊都可以直接複製和使用(它們實際上是經過測試的 Python 檔案)。
|
||||
|
||||
要運行任何範例,請將程式碼複製到 `main.py` 檔案,並使用以下命令啟動 `fastapi dev`:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ <font color="#4E9A06">fastapi</font> dev <u style="text-decoration-style:single">main.py</u>
|
||||
<font color="#3465A4">INFO </font> Using path <font color="#3465A4">main.py</font>
|
||||
<font color="#3465A4">INFO </font> Resolved absolute path <font color="#75507B">/home/user/code/awesomeapp/</font><font color="#AD7FA8">main.py</font>
|
||||
<font color="#3465A4">INFO </font> Searching for package file structure from directories with <font color="#3465A4">__init__.py</font> files
|
||||
<font color="#3465A4">INFO </font> Importing from <font color="#75507B">/home/user/code/</font><font color="#AD7FA8">awesomeapp</font>
|
||||
|
||||
╭─ <font color="#8AE234"><b>Python module file</b></font> ─╮
|
||||
│ │
|
||||
│ 🐍 main.py │
|
||||
│ │
|
||||
╰──────────────────────╯
|
||||
|
||||
<font color="#3465A4">INFO </font> Importing module <font color="#4E9A06">main</font>
|
||||
<font color="#3465A4">INFO </font> Found importable FastAPI app
|
||||
|
||||
╭─ <font color="#8AE234"><b>Importable FastAPI app</b></font> ─╮
|
||||
│ │
|
||||
│ <span style="background-color:#272822"><font color="#FF4689">from</font></span><span style="background-color:#272822"><font color="#F8F8F2"> main </font></span><span style="background-color:#272822"><font color="#FF4689">import</font></span><span style="background-color:#272822"><font color="#F8F8F2"> app</font></span><span style="background-color:#272822"> </span> │
|
||||
│ │
|
||||
╰──────────────────────────╯
|
||||
|
||||
<font color="#3465A4">INFO </font> Using import string <font color="#8AE234"><b>main:app</b></font>
|
||||
|
||||
<span style="background-color:#C4A000"><font color="#2E3436">╭────────── FastAPI CLI - Development mode ───────────╮</font></span>
|
||||
<span style="background-color:#C4A000"><font color="#2E3436">│ │</font></span>
|
||||
<span style="background-color:#C4A000"><font color="#2E3436">│ Serving at: http://127.0.0.1:8000 │</font></span>
|
||||
<span style="background-color:#C4A000"><font color="#2E3436">│ │</font></span>
|
||||
<span style="background-color:#C4A000"><font color="#2E3436">│ API docs: http://127.0.0.1:8000/docs │</font></span>
|
||||
<span style="background-color:#C4A000"><font color="#2E3436">│ │</font></span>
|
||||
<span style="background-color:#C4A000"><font color="#2E3436">│ Running in development mode, for production use: │</font></span>
|
||||
<span style="background-color:#C4A000"><font color="#2E3436">│ │</font></span>
|
||||
<span style="background-color:#C4A000"><font color="#2E3436">│ </font></span><span style="background-color:#C4A000"><font color="#555753"><b>fastapi run</b></font></span><span style="background-color:#C4A000"><font color="#2E3436"> │</font></span>
|
||||
<span style="background-color:#C4A000"><font color="#2E3436">│ │</font></span>
|
||||
<span style="background-color:#C4A000"><font color="#2E3436">╰─────────────────────────────────────────────────────╯</font></span>
|
||||
|
||||
<font color="#4E9A06">INFO</font>: Will watch for changes in these directories: ['/home/user/code/awesomeapp']
|
||||
<font color="#4E9A06">INFO</font>: Uvicorn running on <b>http://127.0.0.1:8000</b> (Press CTRL+C to quit)
|
||||
<font color="#4E9A06">INFO</font>: Started reloader process [<font color="#34E2E2"><b>2265862</b></font>] using <font color="#34E2E2"><b>WatchFiles</b></font>
|
||||
<font color="#4E9A06">INFO</font>: Started server process [<font color="#06989A">2265873</font>]
|
||||
<font color="#4E9A06">INFO</font>: Waiting for application startup.
|
||||
<font color="#4E9A06">INFO</font>: Application startup complete.
|
||||
</pre>
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
**強烈建議**你編寫或複製程式碼、進行修改並在本地端運行。
|
||||
|
||||
在編輯器中使用它,才能真正體會到 FastAPI 的好處,可以看到你只需編寫少量程式碼,以及所有的型別檢查、自動補齊等功能。
|
||||
|
||||
---
|
||||
|
||||
## 安裝 FastAPI
|
||||
|
||||
第一步是安裝 FastAPI。
|
||||
|
||||
確保你建立一個[虛擬環境](../virtual-environments.md){.internal-link target=_blank},啟用它,然後**安裝 FastAPI**:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ pip install "fastapi[standard]"
|
||||
|
||||
---> 100%
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
/// note
|
||||
|
||||
當你使用 `pip install "fastapi[standard]"` 安裝時,會包含一些預設的可選標準相依項。
|
||||
|
||||
如果你不想包含那些可選的相依項,你可以使用 `pip install fastapi` 來安裝。
|
||||
|
||||
///
|
||||
|
||||
## 進階使用者指南
|
||||
|
||||
還有一個**進階使用者指南**你可以稍後閱讀。
|
||||
|
||||
**進階使用者指南**建立在這個教學之上,使用相同的概念,並教你一些額外的功能。
|
||||
|
||||
但首先你應該閱讀**教學 - 使用者指南**(你正在閱讀的內容)。
|
||||
|
||||
它被設計成你可以使用**教學 - 使用者指南**來建立一個完整的應用程式,然後根據你的需求,使用一些額外的想法來擴展它。
|
||||
@@ -94,7 +94,7 @@ FastAPI 是一个用于构建 API 的现代、快速(高性能)的 web 框
|
||||
|
||||
「_老实说,你的作品看起来非常可靠和优美。在很多方面,这就是我想让 **Hug** 成为的样子 - 看到有人实现了它真的很鼓舞人心。_」
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Timothy Crosley - <strong><a href="https://www.hug.rest/" target="_blank">Hug</a> 作者</strong> <a href="https://news.ycombinator.com/item?id=19455465" target="_blank"><small>(ref)</small></a></div>
|
||||
<div style="text-align: right; margin-right: 10%;">Timothy Crosley - <strong><a href="https://github.com/hugapi/hug" target="_blank">Hug</a> 作者</strong> <a href="https://news.ycombinator.com/item?id=19455465" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"""FastAPI framework, high performance, easy to learn, fast to code, ready for production"""
|
||||
|
||||
__version__ = "0.115.2"
|
||||
__version__ = "0.115.4"
|
||||
|
||||
from starlette import status as status
|
||||
|
||||
|
||||
@@ -90,21 +90,29 @@ multipart_incorrect_install_error = (
|
||||
|
||||
def ensure_multipart_is_installed() -> None:
|
||||
try:
|
||||
# __version__ is available in both multiparts, and can be mocked
|
||||
from multipart import __version__
|
||||
from python_multipart import __version__
|
||||
|
||||
assert __version__
|
||||
# Import an attribute that can be mocked/deleted in testing
|
||||
assert __version__ > "0.0.12"
|
||||
except (ImportError, AssertionError):
|
||||
try:
|
||||
# parse_options_header is only available in the right multipart
|
||||
from multipart.multipart import parse_options_header
|
||||
# __version__ is available in both multiparts, and can be mocked
|
||||
from multipart import __version__ # type: ignore[no-redef,import-untyped]
|
||||
|
||||
assert parse_options_header # type: ignore[truthy-function]
|
||||
assert __version__
|
||||
try:
|
||||
# parse_options_header is only available in the right multipart
|
||||
from multipart.multipart import ( # type: ignore[import-untyped]
|
||||
parse_options_header,
|
||||
)
|
||||
|
||||
assert parse_options_header
|
||||
except ImportError:
|
||||
logger.error(multipart_incorrect_install_error)
|
||||
raise RuntimeError(multipart_incorrect_install_error) from None
|
||||
except ImportError:
|
||||
logger.error(multipart_incorrect_install_error)
|
||||
raise RuntimeError(multipart_incorrect_install_error) from None
|
||||
except ImportError:
|
||||
logger.error(multipart_not_installed_error)
|
||||
raise RuntimeError(multipart_not_installed_error) from None
|
||||
logger.error(multipart_not_installed_error)
|
||||
raise RuntimeError(multipart_not_installed_error) from None
|
||||
|
||||
|
||||
def get_param_sub_dependant(
|
||||
|
||||
@@ -2298,7 +2298,7 @@ def Security( # noqa: N802
|
||||
dependency.
|
||||
|
||||
The term "scope" comes from the OAuth2 specification, it seems to be
|
||||
intentionaly vague and interpretable. It normally refers to permissions,
|
||||
intentionally vague and interpretable. It normally refers to permissions,
|
||||
in cases to roles.
|
||||
|
||||
These scopes are integrated with OpenAPI (and the API docs at `/docs`).
|
||||
|
||||
@@ -52,7 +52,7 @@ class OAuth2PasswordRequestForm:
|
||||
```
|
||||
|
||||
Note that for OAuth2 the scope `items:read` is a single scope in an opaque string.
|
||||
You could have custom internal logic to separate it by colon caracters (`:`) or
|
||||
You could have custom internal logic to separate it by colon characters (`:`) or
|
||||
similar, and get the two parts `items` and `read`. Many applications do that to
|
||||
group and organize permissions, you could do it as well in your application, just
|
||||
know that that it is application specific, it's not part of the specification.
|
||||
@@ -194,7 +194,7 @@ class OAuth2PasswordRequestFormStrict(OAuth2PasswordRequestForm):
|
||||
```
|
||||
|
||||
Note that for OAuth2 the scope `items:read` is a single scope in an opaque string.
|
||||
You could have custom internal logic to separate it by colon caracters (`:`) or
|
||||
You could have custom internal logic to separate it by colon characters (`:`) or
|
||||
similar, and get the two parts `items` and `read`. Many applications do that to
|
||||
group and organize permissions, you could do it as well in your application, just
|
||||
know that that it is application specific, it's not part of the specification.
|
||||
|
||||
@@ -41,7 +41,7 @@ classifiers = [
|
||||
"Topic :: Internet :: WWW/HTTP",
|
||||
]
|
||||
dependencies = [
|
||||
"starlette>=0.37.2,<0.41.0",
|
||||
"starlette>=0.40.0,<0.42.0",
|
||||
"pydantic>=1.7.4,!=1.8,!=1.8.1,!=2.0.0,!=2.0.1,!=2.1.0,<3.0.0",
|
||||
"typing-extensions>=4.8.0",
|
||||
]
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# For mkdocstrings and tests
|
||||
httpx >=0.23.0,<0.25.0
|
||||
httpx >=0.23.0,<0.28.0
|
||||
# For linting and generating docs versions
|
||||
ruff ==0.6.4
|
||||
|
||||
@@ -2,3 +2,4 @@ PyGithub>=2.3.0,<3.0.0
|
||||
pydantic>=2.5.3,<3.0.0
|
||||
pydantic-settings>=2.1.0,<3.0.0
|
||||
httpx>=0.27.0,<0.28.0
|
||||
smokeshow
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user