Compare commits
185 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
79e08a2541 | ||
|
|
1c9c80ba93 | ||
|
|
25cb05c876 | ||
|
|
694fbab074 | ||
|
|
2fd28434dd | ||
|
|
d15556b152 | ||
|
|
38d8bab770 | ||
|
|
52f0f8657e | ||
|
|
aedf5c895a | ||
|
|
117f9e4abe | ||
|
|
604fea9fc1 | ||
|
|
994bfd4591 | ||
|
|
02722923b1 | ||
|
|
d63a93429b | ||
|
|
b93e216dc7 | ||
|
|
95a29b6e67 | ||
|
|
272f01a153 | ||
|
|
1a345ae7fc | ||
|
|
c5c138b8eb | ||
|
|
da20e33414 | ||
|
|
7fbe3737bc | ||
|
|
f63cec9c95 | ||
|
|
3063ad83ec | ||
|
|
78680e5bee | ||
|
|
55b9faeb48 | ||
|
|
72645dfeab | ||
|
|
3223de5598 | ||
|
|
1afa4e8e75 | ||
|
|
6fd3736da2 | ||
|
|
7e043e5e6f | ||
|
|
d1585c42b9 | ||
|
|
fc494e3527 | ||
|
|
b344cc9415 | ||
|
|
38b71a9298 | ||
|
|
769ee73240 | ||
|
|
1df2f14c64 | ||
|
|
eab9a0e139 | ||
|
|
b86ac6739a | ||
|
|
9840d9e59d | ||
|
|
0ec52157df | ||
|
|
f1c5330b65 | ||
|
|
306ec8de04 | ||
|
|
6d7c9893d4 | ||
|
|
6264709054 | ||
|
|
76c2077f47 | ||
|
|
a63b1efc29 | ||
|
|
9863c3fca8 | ||
|
|
6fb97f44cf | ||
|
|
f64c448329 | ||
|
|
df6cbc5ec6 | ||
|
|
0f0af751e4 | ||
|
|
6c9dca55bc | ||
|
|
d71e807401 | ||
|
|
7df9ddfe4e | ||
|
|
4170659359 | ||
|
|
2940a7fdfa | ||
|
|
dadd6650ed | ||
|
|
c5a21354af | ||
|
|
8bafe2a482 | ||
|
|
42f1716b48 | ||
|
|
6ab2841dbb | ||
|
|
0f54657377 | ||
|
|
79e5b36551 | ||
|
|
074868d77e | ||
|
|
3dd16a9458 | ||
|
|
62c23ab5fa | ||
|
|
11c05beece | ||
|
|
7b3ef43127 | ||
|
|
e0080e5f75 | ||
|
|
e1ba54bd12 | ||
|
|
7032dfb4f1 | ||
|
|
14e7f7c1f4 | ||
|
|
9ed6f1e419 | ||
|
|
b268c39758 | ||
|
|
4dd386b807 | ||
|
|
b7251f1654 | ||
|
|
780d3e65ad | ||
|
|
cc8cac200f | ||
|
|
e7be5c8ac5 | ||
|
|
8f52864899 | ||
|
|
47a630721a | ||
|
|
10ae6de111 | ||
|
|
2b47f3e56b | ||
|
|
d60dd1b60e | ||
|
|
2822f7ca64 | ||
|
|
ff6afeaf78 | ||
|
|
74852d406c | ||
|
|
921642dc7b | ||
|
|
5c01d44ee9 | ||
|
|
135704dcc8 | ||
|
|
88793bb6c2 | ||
|
|
70a51b3aff | ||
|
|
340a582be7 | ||
|
|
5f66b5466f | ||
|
|
d2169ee567 | ||
|
|
a5c03ba1b7 | ||
|
|
e4ea6426dc | ||
|
|
8bf7cd1dc6 | ||
|
|
92feb3ade7 | ||
|
|
d0e739d8f2 | ||
|
|
4efa6bd75e | ||
|
|
600f15faa0 | ||
|
|
250fa519f9 | ||
|
|
3c6dafcc8e | ||
|
|
8447000eee | ||
|
|
fe453f80ed | ||
|
|
3ff504f03f | ||
|
|
eea9ab6106 | ||
|
|
e9e07c41bb | ||
|
|
17a5e18f46 | ||
|
|
9148bd8b6f | ||
|
|
39766d0f96 | ||
|
|
2d9bca56b2 | ||
|
|
f158d95ce9 | ||
|
|
7a4164ef60 | ||
|
|
f3730a79af | ||
|
|
42eff23a79 | ||
|
|
25bc33350d | ||
|
|
b84d082005 | ||
|
|
1f01ce9615 | ||
|
|
352c5f5ecc | ||
|
|
e5594e860f | ||
|
|
50926faead | ||
|
|
a303afc0e5 | ||
|
|
12607e85e3 | ||
|
|
38fd363e89 | ||
|
|
7f62cfd231 | ||
|
|
c5168bd036 | ||
|
|
be472c5215 | ||
|
|
adac38ecea | ||
|
|
c8b634226e | ||
|
|
ca4cf7cc70 | ||
|
|
b87072bc12 | ||
|
|
04e2bfafbc | ||
|
|
181a32236a | ||
|
|
1f54a8e0a1 | ||
|
|
d63475bb7d | ||
|
|
5a3c5f1523 | ||
|
|
12bc9285f7 | ||
|
|
31df2ea940 | ||
|
|
50b90dd6a4 | ||
|
|
7dd881334d | ||
|
|
530fc8ff3f | ||
|
|
ef460b4d23 | ||
|
|
b591de2ace | ||
|
|
34c857b7cb | ||
|
|
c78bc0c82d | ||
|
|
194446e51a | ||
|
|
777e2151e6 | ||
|
|
5ce5bdba0b | ||
|
|
e4300769ac | ||
|
|
c6dd627bdd | ||
|
|
6576f724bb | ||
|
|
91a6736d0e | ||
|
|
8fb755703d | ||
|
|
748bedd37c | ||
|
|
bf58788f29 | ||
|
|
5f78ba4a31 | ||
|
|
db9f827263 | ||
|
|
dd9e94cf21 | ||
|
|
e482d74241 | ||
|
|
bd2acbcabb | ||
|
|
f913d469a8 | ||
|
|
66cb266641 | ||
|
|
74954894c5 | ||
|
|
ceedfccde0 | ||
|
|
2ee0eedf23 | ||
|
|
c0f3019764 | ||
|
|
dd6d0cb23c | ||
|
|
fe15620df3 | ||
|
|
6af857f206 | ||
|
|
7ce756f9dd | ||
|
|
c0b1fddb31 | ||
|
|
9aea85a84e | ||
|
|
fddd1c12de | ||
|
|
b13a4baf32 | ||
|
|
5ffa18f10f | ||
|
|
828915baf5 | ||
|
|
a071ddf3cd | ||
|
|
3651b8a30f | ||
|
|
0d73b9ff1c | ||
|
|
43235cf236 | ||
|
|
269a155583 | ||
|
|
12433d51dd | ||
|
|
3699e17212 |
7
.github/actions/get-artifact/Dockerfile
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
FROM python:3.7
|
||||
|
||||
RUN pip install httpx "pydantic==1.5.1"
|
||||
|
||||
COPY ./app /app
|
||||
|
||||
CMD ["python", "/app/main.py"]
|
||||
16
.github/actions/get-artifact/action.yml
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
name: "Get Artifact"
|
||||
description: "Get artifact, possibly uploaded by a PR, useful to deploy docs previews"
|
||||
author: "Sebastián Ramírez <tiangolo@gmail.com>"
|
||||
inputs:
|
||||
token:
|
||||
description: 'Token for the repo. Can be passed in using {{ secrets.GITHUB_TOKEN }}'
|
||||
required: true
|
||||
name:
|
||||
description: 'Artifact name'
|
||||
required: true
|
||||
path:
|
||||
description: 'Where to store the artifact'
|
||||
required: true
|
||||
runs:
|
||||
using: 'docker'
|
||||
image: 'Dockerfile'
|
||||
63
.github/actions/get-artifact/app/main.py
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
import logging
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
from typing import List, Optional
|
||||
|
||||
import httpx
|
||||
from pydantic import BaseModel, BaseSettings, SecretStr
|
||||
|
||||
github_api = "https://api.github.com"
|
||||
netlify_api = "https://api.netlify.com"
|
||||
|
||||
|
||||
class Settings(BaseSettings):
|
||||
input_name: str
|
||||
input_token: SecretStr
|
||||
input_path: str
|
||||
github_repository: str
|
||||
github_event_path: Path
|
||||
github_event_name: Optional[str] = None
|
||||
|
||||
|
||||
class Artifact(BaseModel):
|
||||
id: int
|
||||
node_id: str
|
||||
name: str
|
||||
size_in_bytes: int
|
||||
url: str
|
||||
archive_download_url: str
|
||||
expired: bool
|
||||
created_at: datetime
|
||||
updated_at: datetime
|
||||
|
||||
|
||||
class ArtifactResponse(BaseModel):
|
||||
total_count: int
|
||||
artifacts: List[Artifact]
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
settings = Settings()
|
||||
logging.info(f"Using config: {settings.json()}")
|
||||
github_headers = {
|
||||
"Authorization": f"token {settings.input_token.get_secret_value()}"
|
||||
}
|
||||
response = httpx.get(
|
||||
f"{github_api}/repos/{settings.github_repository}/actions/artifacts",
|
||||
headers=github_headers,
|
||||
)
|
||||
data = response.json()
|
||||
artifacts_response = ArtifactResponse.parse_obj(data)
|
||||
use_artifact: Optional[Artifact] = None
|
||||
for artifact in artifacts_response.artifacts:
|
||||
if artifact.name == settings.input_name:
|
||||
use_artifact = artifact
|
||||
break
|
||||
assert use_artifact
|
||||
file_response = httpx.get(
|
||||
use_artifact.archive_download_url, headers=github_headers, timeout=30
|
||||
)
|
||||
zip_file = Path(settings.input_path)
|
||||
zip_file.write_bytes(file_response.content)
|
||||
logging.info("Finished")
|
||||
7
.github/actions/watch-previews/Dockerfile
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
FROM python:3.7
|
||||
|
||||
RUN pip install httpx PyGithub "pydantic==1.5.1"
|
||||
|
||||
COPY ./app /app
|
||||
|
||||
CMD ["python", "/app/main.py"]
|
||||
10
.github/actions/watch-previews/action.yml
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
name: "Watch docs previews in PRs"
|
||||
description: "Check PRs and trigger new docs deploys"
|
||||
author: "Sebastián Ramírez <tiangolo@gmail.com>"
|
||||
inputs:
|
||||
token:
|
||||
description: 'Token for the repo. Can be passed in using {{ secrets.GITHUB_TOKEN }}'
|
||||
required: true
|
||||
runs:
|
||||
using: 'docker'
|
||||
image: 'Dockerfile'
|
||||
101
.github/actions/watch-previews/app/main.py
vendored
Normal file
@@ -0,0 +1,101 @@
|
||||
import logging
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
from typing import List, Optional
|
||||
|
||||
import httpx
|
||||
from github import Github
|
||||
from github.NamedUser import NamedUser
|
||||
from pydantic import BaseModel, BaseSettings, SecretStr
|
||||
|
||||
github_api = "https://api.github.com"
|
||||
netlify_api = "https://api.netlify.com"
|
||||
|
||||
|
||||
class Settings(BaseSettings):
|
||||
input_token: SecretStr
|
||||
github_repository: str
|
||||
github_event_path: Path
|
||||
github_event_name: Optional[str] = None
|
||||
|
||||
|
||||
class Artifact(BaseModel):
|
||||
id: int
|
||||
node_id: str
|
||||
name: str
|
||||
size_in_bytes: int
|
||||
url: str
|
||||
archive_download_url: str
|
||||
expired: bool
|
||||
created_at: datetime
|
||||
updated_at: datetime
|
||||
|
||||
|
||||
class ArtifactResponse(BaseModel):
|
||||
total_count: int
|
||||
artifacts: List[Artifact]
|
||||
|
||||
|
||||
def get_message(commit: str) -> str:
|
||||
return f"Docs preview for commit {commit} at"
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
settings = Settings()
|
||||
logging.info(f"Using config: {settings.json()}")
|
||||
g = Github(settings.input_token.get_secret_value())
|
||||
repo = g.get_repo(settings.github_repository)
|
||||
owner: NamedUser = repo.owner
|
||||
headers = {"Authorization": f"token {settings.input_token.get_secret_value()}"}
|
||||
prs = list(repo.get_pulls(state="open"))
|
||||
response = httpx.get(
|
||||
f"{github_api}/repos/{settings.github_repository}/actions/artifacts",
|
||||
headers=headers,
|
||||
)
|
||||
data = response.json()
|
||||
artifacts_response = ArtifactResponse.parse_obj(data)
|
||||
for pr in prs:
|
||||
logging.info("-----")
|
||||
logging.info(f"Processing PR #{pr.number}: {pr.title}")
|
||||
pr_comments = list(pr.get_issue_comments())
|
||||
pr_commits = list(pr.get_commits())
|
||||
last_commit = pr_commits[0]
|
||||
for pr_commit in pr_commits:
|
||||
if pr_commit.commit.author.date > last_commit.commit.author.date:
|
||||
last_commit = pr_commit
|
||||
commit = last_commit.commit.sha
|
||||
logging.info(f"Last commit: {commit}")
|
||||
message = get_message(commit)
|
||||
notified = False
|
||||
for pr_comment in pr_comments:
|
||||
if message in pr_comment.body:
|
||||
notified = True
|
||||
logging.info(f"Docs preview was notified: {notified}")
|
||||
if not notified:
|
||||
artifact_name = f"docs-zip-{commit}"
|
||||
use_artifact: Optional[Artifact] = None
|
||||
for artifact in artifacts_response.artifacts:
|
||||
if artifact.name == artifact_name:
|
||||
use_artifact = artifact
|
||||
break
|
||||
if not use_artifact:
|
||||
logging.info("Artifact not available")
|
||||
else:
|
||||
logging.info(f"Existing artifact: {use_artifact.name}")
|
||||
response = httpx.post(
|
||||
"https://api.github.com/repos/tiangolo/fastapi/actions/workflows/preview-docs.yml/dispatches",
|
||||
headers=headers,
|
||||
json={
|
||||
"ref": "master",
|
||||
"inputs": {
|
||||
"pr": f"{pr.number}",
|
||||
"name": artifact_name,
|
||||
"commit": commit,
|
||||
},
|
||||
},
|
||||
)
|
||||
logging.info(
|
||||
f"Trigger sent, response status: {response.status_code} - content: {response.content}"
|
||||
)
|
||||
logging.info("Finished")
|
||||
@@ -1,4 +1,4 @@
|
||||
name: Build and Deploy to Netlify
|
||||
name: Build Docs
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
@@ -7,6 +7,10 @@ jobs:
|
||||
build:
|
||||
runs-on: ubuntu-18.04
|
||||
steps:
|
||||
- name: Dump GitHub context
|
||||
env:
|
||||
GITHUB_CONTEXT: ${{ toJson(github) }}
|
||||
run: echo "$GITHUB_CONTEXT"
|
||||
- uses: actions/checkout@v2
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v1
|
||||
@@ -18,12 +22,21 @@ jobs:
|
||||
run: python3.7 -m flit install --extras doc
|
||||
- name: Build Docs
|
||||
run: python3.7 ./scripts/docs.py build-all
|
||||
- name: Zip docs
|
||||
if: github.event_name == 'pull_request'
|
||||
run: bash ./scripts/zip-docs.sh
|
||||
- uses: actions/upload-artifact@v2
|
||||
if: github.event_name == 'pull_request'
|
||||
with:
|
||||
name: docs-zip-${{ github.event.pull_request.head.sha }}
|
||||
path: ./docs.zip
|
||||
- name: Deploy to Netlify
|
||||
uses: nwtgck/actions-netlify@v1.0.3
|
||||
uses: nwtgck/actions-netlify@v1.1.5
|
||||
with:
|
||||
publish-dir: './site'
|
||||
production-branch: master
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
enable-commit-comment: false
|
||||
env:
|
||||
NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
|
||||
NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }}
|
||||
14
.github/workflows/pr-approvals.yml
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
name: Label approved pull requests
|
||||
on: pull_request_review
|
||||
jobs:
|
||||
labelWhenApproved:
|
||||
name: Label when approved
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Label when approved
|
||||
uses: pullreminders/label-when-approved-action@v1.0.7
|
||||
env:
|
||||
APPROVALS: "2"
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
ADD_LABEL: "approved-2"
|
||||
REMOVE_LABEL: "awaiting%20review"
|
||||
44
.github/workflows/preview-docs.yml
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
name: Preview Docs
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
pr:
|
||||
description: Pull Request number
|
||||
required: true
|
||||
name:
|
||||
description: Artifact name for zip file with docs
|
||||
required: true
|
||||
commit:
|
||||
description: Commit SHA hash
|
||||
required: true
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
runs-on: ubuntu-18.04
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: ./.github/actions/get-artifact
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
name: ${{ github.event.inputs.name }}
|
||||
path: ./archive.zip
|
||||
- name: Unzip docs
|
||||
run: bash ./scripts/unzip-docs.sh
|
||||
- name: Deploy to Netlify
|
||||
id: netlify
|
||||
uses: nwtgck/actions-netlify@v1.1.5
|
||||
with:
|
||||
publish-dir: './site'
|
||||
production-deploy: false
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
enable-commit-comment: false
|
||||
env:
|
||||
NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
|
||||
NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }}
|
||||
- name: Comment Deploy
|
||||
env:
|
||||
PR: "${{ github.event.inputs.pr }}"
|
||||
DEPLOY_URL: "${{ steps.netlify.outputs.deploy-url }}"
|
||||
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
|
||||
COMMIT: "${{ github.event.inputs.commit }}"
|
||||
run: bash ./scripts/docs-comment-deploy.sh
|
||||
39
.github/workflows/publish.yml
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
name: Publish
|
||||
|
||||
on:
|
||||
release:
|
||||
types:
|
||||
- created
|
||||
|
||||
jobs:
|
||||
publish:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Dump GitHub context
|
||||
env:
|
||||
GITHUB_CONTEXT: ${{ toJson(github) }}
|
||||
run: echo "$GITHUB_CONTEXT"
|
||||
- uses: actions/checkout@v2
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v1
|
||||
with:
|
||||
python-version: "3.6"
|
||||
- name: Install Flit
|
||||
run: pip install flit
|
||||
- name: Install Dependencies
|
||||
run: flit install --symlink
|
||||
- name: Publish
|
||||
env:
|
||||
FLIT_USERNAME: ${{ secrets.FLIT_USERNAME }}
|
||||
FLIT_PASSWORD: ${{ secrets.FLIT_PASSWORD }}
|
||||
run: bash scripts/publish.sh
|
||||
- name: Dump GitHub context
|
||||
env:
|
||||
GITHUB_CONTEXT: ${{ toJson(github) }}
|
||||
run: echo "$GITHUB_CONTEXT"
|
||||
- name: Notify
|
||||
env:
|
||||
GITTER_TOKEN: ${{ secrets.GITTER_TOKEN }}
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
TAG: ${{ github.event.release.name }}
|
||||
run: bash scripts/notify.sh
|
||||
29
.github/workflows/test.yml
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
name: Test
|
||||
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
types: [opened, synchronize]
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: [3.6, 3.7, 3.8]
|
||||
fail-fast: false
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v1
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
- name: Install Flit
|
||||
run: pip install flit
|
||||
- name: Install Dependencies
|
||||
run: flit install --symlink
|
||||
- name: Test
|
||||
run: bash scripts/test.sh
|
||||
- name: Upload coverage
|
||||
uses: codecov/codecov-action@v1
|
||||
13
.github/workflows/watch-docs-previews.yml
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
name: Watch Docs Previews
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0 * * * *"
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
runs-on: ubuntu-18.04
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: ./.github/actions/watch-previews
|
||||
with:
|
||||
token: ${{ secrets.ACTIONS_TOKEN }}
|
||||
7
.gitignore
vendored
@@ -16,3 +16,10 @@ Pipfile.lock
|
||||
env3.*
|
||||
env
|
||||
docs_build
|
||||
venv
|
||||
docs.zip
|
||||
archive.zip
|
||||
|
||||
# vim temporary files
|
||||
*~
|
||||
.*.sw?
|
||||
|
||||
32
.travis.yml
@@ -1,32 +0,0 @@
|
||||
dist: xenial
|
||||
|
||||
language: python
|
||||
|
||||
cache: pip
|
||||
|
||||
python:
|
||||
- "3.6"
|
||||
- "3.7"
|
||||
- "3.8"
|
||||
- "nightly"
|
||||
|
||||
matrix:
|
||||
allow_failures:
|
||||
- python: "nightly"
|
||||
|
||||
install:
|
||||
- pip install flit
|
||||
- flit install --symlink
|
||||
|
||||
script:
|
||||
- bash scripts/test.sh
|
||||
|
||||
after_script:
|
||||
- bash <(curl -s https://codecov.io/bash)
|
||||
|
||||
deploy:
|
||||
provider: script
|
||||
script: bash scripts/deploy.sh
|
||||
on:
|
||||
tags: true
|
||||
python: "3.6"
|
||||
26
README.md
@@ -5,14 +5,14 @@
|
||||
<em>FastAPI framework, high performance, easy to learn, fast to code, ready for production</em>
|
||||
</p>
|
||||
<p align="center">
|
||||
<a href="https://travis-ci.com/tiangolo/fastapi" target="_blank">
|
||||
<img src="https://travis-ci.com/tiangolo/fastapi.svg?branch=master" alt="Build Status">
|
||||
<a href="https://github.com/tiangolo/fastapi/actions?query=workflow%3ATest" target="_blank">
|
||||
<img src="https://github.com/tiangolo/fastapi/workflows/Test/badge.svg" alt="Test">
|
||||
</a>
|
||||
<a href="https://codecov.io/gh/tiangolo/fastapi" target="_blank">
|
||||
<img src="https://img.shields.io/codecov/c/github/tiangolo/fastapi" alt="Coverage">
|
||||
<img src="https://img.shields.io/codecov/c/github/tiangolo/fastapi?color=%2334D058" alt="Coverage">
|
||||
</a>
|
||||
<a href="https://pypi.org/project/fastapi" target="_blank">
|
||||
<img src="https://badge.fury.io/py/fastapi.svg" alt="Package version">
|
||||
<img src="https://img.shields.io/pypi/v/fastapi?color=%2334D058&label=pypi%20package" alt="Package version">
|
||||
</a>
|
||||
<a href="https://gitter.im/tiangolo/fastapi?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge" target="_blank">
|
||||
<img src="https://badges.gitter.im/tiangolo/fastapi.svg" alt="Join the chat at https://gitter.im/tiangolo/fastapi">
|
||||
@@ -131,6 +131,8 @@ $ pip install uvicorn
|
||||
* Create a file `main.py` with:
|
||||
|
||||
```Python
|
||||
from typing import Optional
|
||||
|
||||
from fastapi import FastAPI
|
||||
|
||||
app = FastAPI()
|
||||
@@ -142,7 +144,7 @@ def read_root():
|
||||
|
||||
|
||||
@app.get("/items/{item_id}")
|
||||
def read_item(item_id: int, q: str = None):
|
||||
def read_item(item_id: int, q: Optional[str] = None):
|
||||
return {"item_id": item_id, "q": q}
|
||||
```
|
||||
|
||||
@@ -151,7 +153,9 @@ def read_item(item_id: int, q: str = None):
|
||||
|
||||
If your code uses `async` / `await`, use `async def`:
|
||||
|
||||
```Python hl_lines="7 12"
|
||||
```Python hl_lines="9 14"
|
||||
from typing import Optional
|
||||
|
||||
from fastapi import FastAPI
|
||||
|
||||
app = FastAPI()
|
||||
@@ -163,7 +167,7 @@ async def read_root():
|
||||
|
||||
|
||||
@app.get("/items/{item_id}")
|
||||
async def read_item(item_id: int, q: str = None):
|
||||
async def read_item(item_id: int, q: Optional[str] = None):
|
||||
return {"item_id": item_id, "q": q}
|
||||
```
|
||||
|
||||
@@ -241,7 +245,9 @@ Now modify the file `main.py` to receive a body from a `PUT` request.
|
||||
|
||||
Declare the body using standard Python types, thanks to Pydantic.
|
||||
|
||||
```Python hl_lines="2 7 8 9 10 23 24 25"
|
||||
```Python hl_lines="4 9 10 11 12 25 26 27"
|
||||
from typing import Optional
|
||||
|
||||
from fastapi import FastAPI
|
||||
from pydantic import BaseModel
|
||||
|
||||
@@ -251,7 +257,7 @@ app = FastAPI()
|
||||
class Item(BaseModel):
|
||||
name: str
|
||||
price: float
|
||||
is_offer: bool = None
|
||||
is_offer: Optional[bool] = None
|
||||
|
||||
|
||||
@app.get("/")
|
||||
@@ -260,7 +266,7 @@ def read_root():
|
||||
|
||||
|
||||
@app.get("/items/{item_id}")
|
||||
def read_item(item_id: int, q: str = None):
|
||||
def read_item(item_id: int, q: Optional[str] = None):
|
||||
return {"item_id": item_id, "q": q}
|
||||
|
||||
|
||||
|
||||
230
docs/en/data/external_links.yml
Normal file
@@ -0,0 +1,230 @@
|
||||
articles:
|
||||
english:
|
||||
- link: https://medium.com/@williamhayes/fastapi-starlette-debug-vs-prod-5f7561db3a59
|
||||
title: FastAPI/Starlette debug vs prod
|
||||
author_link: https://medium.com/@williamhayes
|
||||
author: William Hayes
|
||||
- link: https://medium.com/data-rebels/fastapi-google-as-an-external-authentication-provider-3a527672cf33
|
||||
title: FastAPI — Google as an external authentication provider
|
||||
author_link: https://medium.com/@nilsdebruin
|
||||
author: Nils de Bruin
|
||||
- link: https://medium.com/data-rebels/fastapi-how-to-add-basic-and-cookie-authentication-a45c85ef47d3
|
||||
title: FastAPI — How to add basic and cookie authentication
|
||||
author_link: https://medium.com/@nilsdebruin
|
||||
author: Nils de Bruin
|
||||
- link: https://dev.to/errietta/introduction-to-the-fastapi-python-framework-2n10
|
||||
title: Introduction to the fastapi python framework
|
||||
author_link: https://dev.to/errietta
|
||||
author: Errieta Kostala
|
||||
- link: http://nickc1.github.io/api,/scikit-learn/2019/01/10/scikit-fastapi.html
|
||||
title: "FastAPI and Scikit-Learn: Easily Deploy Models"
|
||||
author_link: http://nickc1.github.io/
|
||||
author: Nick Cortale
|
||||
- link: https://medium.com/data-rebels/fastapi-authentication-revisited-enabling-api-key-authentication-122dc5975680
|
||||
title: "FastAPI authentication revisited: Enabling API key authentication"
|
||||
author_link: https://medium.com/@nilsdebruin
|
||||
author: Nils de Bruin
|
||||
- link: https://medium.com/@nico.axtmann95/deploying-a-scikit-learn-model-with-onnx-und-fastapi-1af398268915
|
||||
title: Deploying a scikit-learn model with ONNX and FastAPI
|
||||
author_link: https://www.linkedin.com/in/nico-axtmann
|
||||
author: Nico Axtmann
|
||||
- link: https://geekflare.com/python-asynchronous-web-frameworks/
|
||||
title: Top 5 Asynchronous Web Frameworks for Python
|
||||
author_link: https://geekflare.com/author/ankush/
|
||||
author: Ankush Thakur
|
||||
- link: https://medium.com/@gntrm/jwt-authentication-with-fastapi-and-aws-cognito-1333f7f2729e
|
||||
title: JWT Authentication with FastAPI and AWS Cognito
|
||||
author_link: https://twitter.com/gntrm
|
||||
author: Johannes Gontrum
|
||||
- link: https://towardsdatascience.com/how-to-deploy-a-machine-learning-model-dc51200fe8cf
|
||||
title: How to Deploy a Machine Learning Model
|
||||
author_link: https://www.linkedin.com/in/mgrootendorst/
|
||||
author: Maarten Grootendorst
|
||||
- link: https://eng.uber.com/ludwig-v0-2/
|
||||
title: "Uber: Ludwig v0.2 Adds New Features and Other Improvements to its Deep Learning Toolbox [including a FastAPI server]"
|
||||
author_link: https://eng.uber.com
|
||||
author: Uber Engineering
|
||||
- link: https://gitlab.com/euri10/fastapi_cheatsheet
|
||||
title: A FastAPI and Swagger UI visual cheatsheet
|
||||
author_link: https://gitlab.com/euri10
|
||||
author: "@euri10"
|
||||
- link: https://medium.com/@mike.p.moritz/using-docker-compose-to-deploy-a-lightweight-python-rest-api-with-a-job-queue-37e6072a209b
|
||||
title: Using Docker Compose to deploy a lightweight Python REST API with a job queue
|
||||
author_link: https://medium.com/@mike.p.moritz
|
||||
author: Mike Moritz
|
||||
- link: https://robwagner.dev/tortoise-fastapi-setup/
|
||||
title: Setting up Tortoise ORM with FastAPI
|
||||
author_link: https://robwagner.dev/
|
||||
author: Rob Wagner
|
||||
- link: https://dev.to/dbanty/why-i-m-leaving-flask-3ki6
|
||||
title: Why I'm Leaving Flask
|
||||
author_link: https://dev.to/dbanty
|
||||
author: Dylan Anthony
|
||||
- link: https://medium.com/python-data/how-to-deploy-tensorflow-2-0-models-as-an-api-service-with-fastapi-docker-128b177e81f3
|
||||
title: How To Deploy Tensorflow 2.0 Models As An API Service With FastAPI & Docker
|
||||
author_link: https://medium.com/@bbrenyah
|
||||
author: Bernard Brenyah
|
||||
- link: https://testdriven.io/blog/fastapi-crud/
|
||||
title: "TestDriven.io: Developing and Testing an Asynchronous API with FastAPI and Pytest"
|
||||
author_link: https://testdriven.io/authors/herman
|
||||
author: Michael Herman
|
||||
- link: https://towardsdatascience.com/deploying-iris-classifications-with-fastapi-and-docker-7c9b83fdec3a
|
||||
title: "Towards Data Science: Deploying Iris Classifications with FastAPI and Docker"
|
||||
author_link: https://towardsdatascience.com/@mandygu
|
||||
author: Mandy Gu
|
||||
- link: https://medium.com/analytics-vidhya/deploy-machine-learning-models-with-keras-fastapi-redis-and-docker-4940df614ece
|
||||
title: Deploy Machine Learning Models with Keras, FastAPI, Redis and Docker
|
||||
author_link: https://medium.com/@shane.soh
|
||||
author: Shane Soh
|
||||
- link: https://medium.com/@arthur393/another-boilerplate-to-fastapi-azure-pipeline-ci-pytest-3c8d9a4be0bb
|
||||
title: "Another Boilerplate to FastAPI: Azure Pipeline CI + Pytest"
|
||||
author_link: https://twitter.com/arthurheinrique
|
||||
author: Arthur Henrique
|
||||
- link: https://iwpnd.pw/articles/2020-01/deploy-fastapi-to-aws-lambda
|
||||
title: How to continuously deploy a FastAPI to AWS Lambda with AWS SAM
|
||||
author_link: https://iwpnd.pw
|
||||
author: Benjamin Ramser
|
||||
- link: https://www.tutlinks.com/create-and-deploy-fastapi-app-to-heroku/
|
||||
title: Create and Deploy FastAPI app to Heroku without using Docker
|
||||
author_link: https://www.linkedin.com/in/navule/
|
||||
author: Navule Pavan Kumar Rao
|
||||
- link: https://iwpnd.pw/articles/2020-03/apache-kafka-fastapi-geostream
|
||||
title: Apache Kafka producer and consumer with FastAPI and aiokafka
|
||||
author_link: https://iwpnd.pw
|
||||
author: Benjamin Ramser
|
||||
- link: https://wuilly.com/2019/10/real-time-notifications-with-python-and-postgres/
|
||||
title: Real-time Notifications with Python and Postgres
|
||||
author_link: https://wuilly.com/
|
||||
author: Guillermo Cruz
|
||||
- link: https://dev.to/paurakhsharma/microservice-in-python-using-fastapi-24cc
|
||||
title: Microservice in Python using FastAPI
|
||||
author_link: https://twitter.com/PaurakhSharma
|
||||
author: Paurakh Sharma Humagain
|
||||
- link: https://dev.to/cuongld2/build-simple-api-service-with-python-fastapi-part-1-581o
|
||||
title: Build simple API service with Python FastAPI — Part 1
|
||||
author_link: https://dev.to/cuongld2
|
||||
author: cuongld2
|
||||
- link: https://paulsec.github.io/posts/fastapi_plus_zeit_serverless_fu/
|
||||
title: FastAPI + Zeit.co = 🚀
|
||||
author_link: https://twitter.com/PaulWebSec
|
||||
author: Paul Sec
|
||||
- link: https://dev.to/tiangolo/build-a-web-api-from-scratch-with-fastapi-the-workshop-2ehe
|
||||
title: Build a web API from scratch with FastAPI - the workshop
|
||||
author_link: https://twitter.com/tiangolo
|
||||
author: Sebastián Ramírez (tiangolo)
|
||||
- link: https://www.twilio.com/blog/build-secure-twilio-webhook-python-fastapi
|
||||
title: Build a Secure Twilio Webhook with Python and FastAPI
|
||||
author_link: https://www.twilio.com
|
||||
author: Twilio
|
||||
- link: https://www.stavros.io/posts/fastapi-with-django/
|
||||
title: Using FastAPI with Django
|
||||
author_link: https://twitter.com/Stavros
|
||||
author: Stavros Korokithakis
|
||||
- link: https://netflixtechblog.com/introducing-dispatch-da4b8a2a8072
|
||||
title: Introducing Dispatch
|
||||
author_link: https://netflixtechblog.com/
|
||||
author: Netflix
|
||||
- link: https://davidefiocco.github.io/2020/06/27/streamlit-fastapi-ml-serving.html
|
||||
title: Machine learning model serving in Python using FastAPI and streamlit
|
||||
author_link: https://github.com/davidefiocco
|
||||
author: Davide Fiocco
|
||||
- link: https://www.tutlinks.com/deploy-fastapi-on-azure/
|
||||
title: Deploy FastAPI on Azure App Service
|
||||
author_link: https://www.linkedin.com/in/navule/
|
||||
author: Navule Pavan Kumar Rao
|
||||
- link: https://towardsdatascience.com/build-and-host-fast-data-science-applications-using-fastapi-823be8a1d6a0
|
||||
title: Build And Host Fast Data Science Applications Using FastAPI
|
||||
author_link: https://medium.com/@farhadmalik
|
||||
author: Farhad Malik
|
||||
japanese:
|
||||
- link: https://qiita.com/mtitg/items/47770e9a562dd150631d
|
||||
title: FastAPI|DB接続してCRUDするPython製APIサーバーを構築
|
||||
author_link: https://qiita.com/mtitg
|
||||
author: "@mtitg"
|
||||
- link: https://qiita.com/ryoryomaru/items/59958ed385b3571d50de
|
||||
title: python製の最新APIフレームワーク FastAPI を触ってみた
|
||||
author_link: https://qiita.com/ryoryomaru
|
||||
author: "@ryoryomaru"
|
||||
- link: https://qiita.com/angel_katayoku/items/0e1f5dbbe62efc612a78
|
||||
title: FastAPIでCORSを回避
|
||||
author_link: https://qiita.com/angel_katayoku
|
||||
author: "@angel_katayoku"
|
||||
- link: https://qiita.com/angel_katayoku/items/4fbc1a4e2b33fa2237d2
|
||||
title: FastAPIをMySQLと接続してDockerで管理してみる
|
||||
author_link: https://qiita.com/angel_katayoku
|
||||
author: "@angel_katayoku"
|
||||
- link: https://qiita.com/angel_katayoku/items/8a458a8952f50b73f420
|
||||
title: FastAPIでPOSTされたJSONのレスポンスbodyを受け取る
|
||||
author_link: https://qiita.com/angel_katayoku
|
||||
author: "@angel_katayoku"
|
||||
- link: https://qiita.com/hikarut/items/b178af2e2440c67c6ac4
|
||||
title: フロントエンド開発者向けのDockerによるPython開発環境構築
|
||||
author_link: https://qiita.com/hikarut
|
||||
author: Hikaru Takahashi
|
||||
- link: https://rightcode.co.jp/blog/information-technology/fastapi-tutorial-todo-apps-environment
|
||||
title: "【第1回】FastAPIチュートリアル: ToDoアプリを作ってみよう【環境構築編】"
|
||||
author_link: https://rightcode.co.jp/author/jun
|
||||
author: ライトコードメディア編集部
|
||||
- link: https://rightcode.co.jp/blog/information-technology/fastapi-tutorial-todo-apps-model-building
|
||||
title: "【第2回】FastAPIチュートリアル: ToDoアプリを作ってみよう【モデル構築編】"
|
||||
author_link: https://rightcode.co.jp/author/jun
|
||||
author: ライトコードメディア編集部
|
||||
- link: https://rightcode.co.jp/blog/information-technology/fastapi-tutorial-todo-apps-authentication-user-registration
|
||||
title: "【第3回】FastAPIチュートリアル: toDoアプリを作ってみよう【認証・ユーザ登録編】"
|
||||
author_link: https://rightcode.co.jp/author/jun
|
||||
author: ライトコードメディア編集部
|
||||
- link: https://rightcode.co.jp/blog/information-technology/fastapi-tutorial-todo-apps-admin-page-improvement
|
||||
title: "【第4回】FastAPIチュートリアル: toDoアプリを作ってみよう【管理者ページ改良編】"
|
||||
author_link: https://rightcode.co.jp/author/jun
|
||||
author: ライトコードメディア編集部
|
||||
- link: https://qiita.com/bee2/items/0ad260ab9835a2087dae
|
||||
title: PythonのWeb frameworkのパフォーマンス比較 (Django, Flask, responder, FastAPI, japronto)
|
||||
author_link: https://qiita.com/bee2
|
||||
author: "@bee2"
|
||||
- link: https://qiita.com/bee2/items/75d9c0d7ba20e7a4a0e9
|
||||
title: "[FastAPI] Python製のASGI Web フレームワーク FastAPIに入門する"
|
||||
author_link: https://qiita.com/bee2
|
||||
author: "@bee2"
|
||||
vietnamese:
|
||||
- link: https://fullstackstation.com/fastapi-trien-khai-bang-docker/
|
||||
title: "FASTAPI: TRIỂN KHAI BẰNG DOCKER"
|
||||
author_link: https://fullstackstation.com/author/figonking/
|
||||
author: Nguyễn Nhân
|
||||
russian:
|
||||
- link: https://habr.com/ru/post/454440/
|
||||
title: "Мелкая питонячая радость #2: Starlette - Солидная примочка – FastAPI"
|
||||
author_link: https://habr.com/ru/users/57uff3r/
|
||||
author: Andrey Korchak
|
||||
- link: https://habr.com/ru/post/478620/
|
||||
title: Почему Вы должны попробовать FastAPI?
|
||||
author_link: https://github.com/prostomarkeloff
|
||||
author: prostomarkeloff
|
||||
german:
|
||||
- link: https://blog.codecentric.de/2019/08/inbetriebnahme-eines-scikit-learn-modells-mit-onnx-und-fastapi/
|
||||
title: Inbetriebnahme eines scikit-learn-Modells mit ONNX und FastAPI
|
||||
author_link: https://twitter.com/_nicoax
|
||||
author: Nico Axtmann
|
||||
podcasts:
|
||||
english:
|
||||
- link: https://pythonbytes.fm/episodes/show/123/time-to-right-the-py-wrongs?time_in_sec=855
|
||||
title: FastAPI on PythonBytes
|
||||
author_link: https://pythonbytes.fm/
|
||||
author: Python Bytes FM
|
||||
- link: https://www.pythonpodcast.com/fastapi-web-application-framework-episode-259/
|
||||
title: "Build The Next Generation Of Python Web Applications With FastAPI - Episode 259 - interview to Sebastían Ramírez (tiangolo)"
|
||||
author_link: https://www.pythonpodcast.com/
|
||||
author: Podcast.`__init__`
|
||||
talks:
|
||||
english:
|
||||
- link: https://www.youtube.com/watch?v=3DLwPcrE5mA
|
||||
title: "PyCon UK 2019: FastAPI from the ground up"
|
||||
author_link: https://twitter.com/chriswithers13
|
||||
author: Chris Withers
|
||||
- link: https://www.youtube.com/watch?v=z9K5pwb0rt8
|
||||
title: "PyConBY 2020: Serve ML models easily with FastAPI"
|
||||
author_link: https://twitter.com/tiangolo
|
||||
author: "Sebastián Ramírez (tiangolo)"
|
||||
- link: https://www.youtube.com/watch?v=PnpTY1f4k2U
|
||||
title: "[VIRTUAL] Py.Amsterdam's flying Software Circus: Intro to FastAPI"
|
||||
author_link: https://twitter.com/tiangolo
|
||||
author: "Sebastián Ramírez (tiangolo)"
|
||||
@@ -168,7 +168,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="17 18 19 20 21 22 23 24 28"
|
||||
```Python hl_lines="19 20 21 22 23 24 28"
|
||||
{!../../../docs_src/additional_responses/tutorial002.py!}
|
||||
```
|
||||
|
||||
@@ -228,7 +228,7 @@ You can use that technique to re-use some predefined responses in your *path ope
|
||||
|
||||
For example:
|
||||
|
||||
```Python hl_lines="11 12 13 14 15 24"
|
||||
```Python hl_lines="13 14 15 16 17 26"
|
||||
{!../../../docs_src/additional_responses/tutorial004.py!}
|
||||
```
|
||||
|
||||
|
||||
@@ -14,7 +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:
|
||||
|
||||
```Python hl_lines="2 19"
|
||||
```Python hl_lines="4 23"
|
||||
{!../../../docs_src/additional_status_codes/tutorial001.py!}
|
||||
```
|
||||
|
||||
|
||||
100
docs/en/docs/advanced/async-tests.md
Normal file
@@ -0,0 +1,100 @@
|
||||
# Async Tests
|
||||
|
||||
You have already seen how to test your **FastAPI** applications using the provided `TestClient`, but with it, you can't test or run any other `async` function in your (synchronous) pytest functions.
|
||||
|
||||
Being able to use asynchronous functions in your tests could be useful, for example, when you're querying your database asynchronously. Imagine you want to test sending requests to your FastAPI application and then verify that your backend successfully wrote the correct data in the database, while using an async database library.
|
||||
|
||||
Let's look at how we can make that work.
|
||||
|
||||
## pytest-asyncio
|
||||
|
||||
If we want to call asynchronous functions in our tests, our test functions have to be asynchronous. Pytest provides a neat library for this, called `pytest-asyncio`, that allows us to specify that some test functions are to be called asynchronously.
|
||||
|
||||
You can install it via:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ pip install pytest-asyncio
|
||||
|
||||
---> 100%
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
## HTTPX
|
||||
|
||||
Even if your **FastAPI** application uses normal `def` functions instead of `async def`, it is still an `async` application underneath.
|
||||
|
||||
The `TestClient` does some magic inside to call the asynchronous FastAPI application in your normal `def` test functions, using standard pytest. But that magic doesn't work anymore when we're using it inside asynchronous functions. By running our tests asynchronously, we can no longer use the `TestClient` inside our test functions.
|
||||
|
||||
Luckily there's a nice alternative, called <a href="https://www.python-httpx.org/" class="external-link" target="_blank">HTTPX</a>.
|
||||
|
||||
HTTPX is an HTTP client for Python 3 that allows us to query our FastAPI application similarly to how we did it with the `TestClient`.
|
||||
|
||||
If you're familiar with the <a href="https://requests.readthedocs.io/en/master/" class="external-link" target="_blank">Requests</a> library, you'll find that the API of HTTPX is almost identical.
|
||||
|
||||
The important difference for us is that with HTTPX we are not limited to synchronous, but can also make asynchronous requests.
|
||||
|
||||
## Example
|
||||
|
||||
For a simple example, let's consider the following `main.py` module:
|
||||
|
||||
```Python
|
||||
{!../../../docs_src/async_tests/main.py!}
|
||||
```
|
||||
|
||||
The `test_main.py` module that contains the tests for `main.py` could look like this now:
|
||||
|
||||
```Python
|
||||
{!../../../docs_src/async_tests/test_main.py!}
|
||||
```
|
||||
|
||||
## Run it
|
||||
|
||||
You can run your tests as usual via:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ pytest
|
||||
|
||||
---> 100%
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
## In Detail
|
||||
|
||||
The marker `@pytest.mark.asyncio` tells pytest that this test function should be called asynchronously:
|
||||
|
||||
```Python hl_lines="7"
|
||||
{!../../../docs_src/async_tests/test_main.py!}
|
||||
```
|
||||
|
||||
!!! tip
|
||||
Note that the test function is now `async def` instead of just `def` as before when using the `TestClient`.
|
||||
|
||||
Then we can create an `AsyncClient` with the app, and send async requests to it, using `await`.
|
||||
|
||||
```Python hl_lines="9 10"
|
||||
{!../../../docs_src/async_tests/test_main.py!}
|
||||
```
|
||||
|
||||
This is the equivalent to:
|
||||
|
||||
```Python
|
||||
response = client.get('/')
|
||||
```
|
||||
|
||||
that we used to make our requests with the `TestClient`.
|
||||
|
||||
!!! tip
|
||||
Note that we're using async/await with the new `AsyncClient` - the request is asynchronous.
|
||||
|
||||
## Other Asynchronous Function Calls
|
||||
|
||||
As the testing function is now asynchronous, you can now also call (and `await`) other `async` functions apart from sending requests to your FastAPI application in your tests, exactly as you would call them anywhere else in your code.
|
||||
|
||||
!!! tip
|
||||
If you encounter a `RuntimeError: Task attached to a different loop` when integrating asynchronous function calls in your tests (e.g. when using <a href="https://stackoverflow.com/questions/41584243/runtimeerror-task-attached-to-a-different-loop" class="external-link" target="_blank">MongoDB's MotorClient</a>) check out <a href="https://github.com/pytest-dev/pytest-asyncio/issues/38#issuecomment-264418154" class="external-link" target="_blank">this issue</a> in the pytest-asyncio repository.
|
||||
@@ -42,16 +42,19 @@ proxy --> server
|
||||
!!! tip
|
||||
The IP `0.0.0.0` is commonly used to mean that the program listens on all the IPs available in that machine/server.
|
||||
|
||||
The docs UI would also need that the JSON payload with the OpenAPI schema has the path defined as `/api/v1/app` (behind the proxy) instead of `/app`. For example, something like:
|
||||
The docs UI would also need the OpenAPI schema to declare that this API `server` is located at `/api/v1` (behind the proxy). For example:
|
||||
|
||||
```JSON hl_lines="5"
|
||||
```JSON hl_lines="4 5 6 7 8"
|
||||
{
|
||||
"openapi": "3.0.2",
|
||||
// More stuff here
|
||||
"paths": {
|
||||
"/api/v1/app": {
|
||||
// More stuff here
|
||||
"servers": [
|
||||
{
|
||||
"url": "/api/v1"
|
||||
}
|
||||
],
|
||||
"paths": {
|
||||
// More stuff here
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -235,7 +238,7 @@ Now, if you go to the URL with the port for Uvicorn: <a href="http://127.0.0.1:8
|
||||
!!! tip
|
||||
Notice that even though you are accessing it at `http://127.0.0.1:8000/app` it shows the `root_path` of `/api/v1`, taken from the option `--root-path`.
|
||||
|
||||
And now open the URL with the port for Traefik, including the path prefix: <a href="http://127.0.0.1:9999/api/v1/app" class="external-link" target="_blank">http://127.0.0.1:9999/api/vi/app</a>.
|
||||
And now open the URL with the port for Traefik, including the path prefix: <a href="http://127.0.0.1:9999/api/v1/app" class="external-link" target="_blank">http://127.0.0.1:9999/api/v1/app</a>.
|
||||
|
||||
We get the same response:
|
||||
|
||||
@@ -264,16 +267,78 @@ You can check it at <a href="http://127.0.0.1:8000/docs" class="external-link" t
|
||||
|
||||
<img src="/img/tutorial/behind-a-proxy/image01.png">
|
||||
|
||||
But if we access the docs UI at the "official" URL using the proxy, at `/api/v1/docs`, it works correctly! 🎉
|
||||
|
||||
Right as we wanted it. ✔️
|
||||
|
||||
This is because FastAPI uses this `root_path` internally to tell the docs UI to use the URL for OpenAPI with the path prefix provided by `root_path`.
|
||||
But if we access the docs UI at the "official" URL using the proxy with port `9999`, at `/api/v1/docs`, it works correctly! 🎉
|
||||
|
||||
You can check it at <a href="http://127.0.0.1:9999/api/v1/docs" class="external-link" target="_blank">http://127.0.0.1:9999/api/v1/docs</a>:
|
||||
|
||||
<img src="/img/tutorial/behind-a-proxy/image02.png">
|
||||
|
||||
Right as we wanted it. ✔️
|
||||
|
||||
This is because FastAPI uses this `root_path` to create the default `server` in OpenAPI with the URL provided by `root_path`.
|
||||
|
||||
## Additional servers
|
||||
|
||||
!!! warning
|
||||
This is a more advanced use case. Feel free to skip it.
|
||||
|
||||
By default, **FastAPI** will create a `server` in the OpenAPI schema with the URL for the `root_path`.
|
||||
|
||||
But you can also provide other alternative `servers`, for example if you want *the same* docs UI to interact with a staging and production environments.
|
||||
|
||||
If you pass a custom list of `servers` and there's a `root_path` (because your API lives behind a proxy), **FastAPI** will insert a "server" with this `root_path` at the beginning of the list.
|
||||
|
||||
For example:
|
||||
|
||||
```Python hl_lines="4 5 6 7"
|
||||
{!../../../docs_src/behind_a_proxy/tutorial003.py!}
|
||||
```
|
||||
|
||||
Will generate an OpenAPI schema like:
|
||||
|
||||
```JSON hl_lines="5 6 7"
|
||||
{
|
||||
"openapi": "3.0.2",
|
||||
// More stuff here
|
||||
"servers": [
|
||||
{
|
||||
"url": "/api/v1"
|
||||
},
|
||||
{
|
||||
"url": "https://stag.example.com",
|
||||
"description": "Staging environment"
|
||||
},
|
||||
{
|
||||
"url": "https://prod.example.com",
|
||||
"description": "Production environment"
|
||||
}
|
||||
],
|
||||
"paths": {
|
||||
// More stuff here
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
!!! tip
|
||||
Notice the auto-generated server with a `url` value of `/api/v1`, taken from the `root_path`.
|
||||
|
||||
In the docs UI at <a href="http://127.0.0.1:9999/api/v1/docs" class="external-link" target="_blank">http://127.0.0.1:9999/api/v1/docs</a> it would look like:
|
||||
|
||||
<img src="/img/tutorial/behind-a-proxy/image03.png">
|
||||
|
||||
!!! tip
|
||||
The docs UI will interact with the server that you select.
|
||||
|
||||
### Disable automatic server from `root_path`
|
||||
|
||||
If you don't want **FastAPI** to include an automatic server using the `root_path`, you can use the parameter `root_path_in_servers=False`:
|
||||
|
||||
```Python hl_lines="9"
|
||||
{!../../../docs_src/behind_a_proxy/tutorial004.py!}
|
||||
```
|
||||
|
||||
and then it won't include it in the OpenAPI schema.
|
||||
|
||||
## Mounting a sub-application
|
||||
|
||||
If you need to mount a sub-application (as described in [Sub Applications - Mounts](./sub-applications.md){.internal-link target=_blank}) while also using a proxy with `root_path`, you can do it normally, as you would expect.
|
||||
|
||||
@@ -203,6 +203,21 @@ File responses will include appropriate `Content-Length`, `Last-Modified` and `E
|
||||
{!../../../docs_src/custom_response/tutorial009.py!}
|
||||
```
|
||||
|
||||
## Default response class
|
||||
|
||||
When creating a **FastAPI** class instance or an `APIRouter` you can specify which response class to use by default.
|
||||
|
||||
The parameter that defines this is `default_response_class`.
|
||||
|
||||
In the example below, **FastAPI** will use `ORJSONResponse` by default, in all *path operations*, instead of `JSONResponse`.
|
||||
|
||||
```Python hl_lines="2 4"
|
||||
{!../../../docs_src/custom_response/tutorial010.py!}
|
||||
```
|
||||
|
||||
!!! tip
|
||||
You can still override `response_class` in *path operations* as before.
|
||||
|
||||
## Additional documentation
|
||||
|
||||
You can also declare the media type and many other details in OpenAPI using `responses`: [Additional Responses in OpenAPI](additional-responses.md){.internal-link target=_blank}.
|
||||
|
||||
@@ -4,6 +4,9 @@ You can define event handlers (functions) that need to be executed before the ap
|
||||
|
||||
These functions can be declared with `async def` or normal `def`.
|
||||
|
||||
!!! warning
|
||||
Only event handlers for the main application will be executed, not for [Sub Applications - Mounts](./sub-applications.md){.internal-link target=_blank}.
|
||||
|
||||
## `startup` event
|
||||
|
||||
To add a function that should be run before the application starts, declare it with the event `"startup"`:
|
||||
@@ -41,4 +44,4 @@ Here, the `shutdown` event handler function will write a text line `"Application
|
||||
So, we declare the event handler function with standard `def` instead of `async def`.
|
||||
|
||||
!!! info
|
||||
You can read more about these event handlers in <a href="https://www.starlette.io/events/" class="external-link" target="_blank">Starlette's Events' docs</a>.
|
||||
You can read more about these event handlers in <a href="https://www.starlette.io/events/" class="external-link" target="_blank">Starlette's Events' docs</a>.
|
||||
|
||||
@@ -32,7 +32,6 @@ And that function `get_openapi()` receives as parameters:
|
||||
* `openapi_version`: The version of the OpenAPI specification used. By default, the latest: `3.0.2`.
|
||||
* `description`: The description of your API.
|
||||
* `routes`: A list of routes, these are each of the registered *path operations*. They are taken from `app.routes`.
|
||||
* `openapi_prefix`: The URL prefix to be used in your OpenAPI.
|
||||
|
||||
## Overriding the defaults
|
||||
|
||||
@@ -52,22 +51,15 @@ First, write all your **FastAPI** application as normally:
|
||||
|
||||
Then, use the same utility function to generate the OpenAPI schema, inside a `custom_openapi()` function:
|
||||
|
||||
```Python hl_lines="2 15 16 17 18 19 20 21"
|
||||
```Python hl_lines="2 15 16 17 18 19 20"
|
||||
{!../../../docs_src/extending_openapi/tutorial001.py!}
|
||||
```
|
||||
|
||||
!!! tip
|
||||
The `openapi_prefix` will contain any prefix needed for the generated OpenAPI *path operations*.
|
||||
|
||||
FastAPI will automatically use the `root_path` to pass it in the `openapi_prefix`.
|
||||
|
||||
But the important thing is that your function should receive that parameter `openapi_prefix` and pass it along.
|
||||
|
||||
### 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 23 24"
|
||||
```Python hl_lines="21 22 23"
|
||||
{!../../../docs_src/extending_openapi/tutorial001.py!}
|
||||
```
|
||||
|
||||
@@ -79,7 +71,7 @@ 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"
|
||||
```Python hl_lines="13 14 24 25"
|
||||
{!../../../docs_src/extending_openapi/tutorial001.py!}
|
||||
```
|
||||
|
||||
@@ -87,7 +79,7 @@ It will be generated only once, and then the same cached schema will be used for
|
||||
|
||||
Now you can replace the `.openapi()` method with your new function.
|
||||
|
||||
```Python hl_lines="29"
|
||||
```Python hl_lines="28"
|
||||
{!../../../docs_src/extending_openapi/tutorial001.py!}
|
||||
```
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ You can adapt it to any other NoSQL database like:
|
||||
|
||||
For now, don't pay attention to the rest, only the imports:
|
||||
|
||||
```Python hl_lines="6 7 8"
|
||||
```Python hl_lines="3 4 5"
|
||||
{!../../../docs_src/nosql_databases/tutorial001.py!}
|
||||
```
|
||||
|
||||
@@ -29,7 +29,7 @@ We will use it later as a fixed field `type` in our documents.
|
||||
|
||||
This is not required by Couchbase, but is a good practice that will help you afterwards.
|
||||
|
||||
```Python hl_lines="10"
|
||||
```Python hl_lines="9"
|
||||
{!../../../docs_src/nosql_databases/tutorial001.py!}
|
||||
```
|
||||
|
||||
@@ -54,7 +54,7 @@ This utility function will:
|
||||
* Set defaults for timeouts.
|
||||
* Return it.
|
||||
|
||||
```Python hl_lines="13 14 15 16 17 18 19 20 21 22"
|
||||
```Python hl_lines="12 13 14 15 16 17 18 19 20 21"
|
||||
{!../../../docs_src/nosql_databases/tutorial001.py!}
|
||||
```
|
||||
|
||||
@@ -66,7 +66,7 @@ As **Couchbase** "documents" are actually just "JSON objects", we can model them
|
||||
|
||||
First, let's create a `User` model:
|
||||
|
||||
```Python hl_lines="25 26 27 28 29"
|
||||
```Python hl_lines="24 25 26 27 28"
|
||||
{!../../../docs_src/nosql_databases/tutorial001.py!}
|
||||
```
|
||||
|
||||
@@ -80,7 +80,7 @@ This will have the data that is actually stored in the database.
|
||||
|
||||
We don't create it as a subclass of Pydantic's `BaseModel` but as a subclass of our own `User`, because it will have all the attributes in `User` plus a couple more:
|
||||
|
||||
```Python hl_lines="32 33 34"
|
||||
```Python hl_lines="31 32 33"
|
||||
{!../../../docs_src/nosql_databases/tutorial001.py!}
|
||||
```
|
||||
|
||||
@@ -100,7 +100,7 @@ Now create a function that will:
|
||||
|
||||
By creating a function that is only dedicated to getting your user from a `username` (or any other parameter) independent of your *path operation function*, you can more easily re-use it in multiple parts and also add <abbr title="Automated test, written in code, that checks if another piece of code is working correctly.">unit tests</abbr> for it:
|
||||
|
||||
```Python hl_lines="37 38 39 40 41 42 43"
|
||||
```Python hl_lines="36 37 38 39 40 41 42"
|
||||
{!../../../docs_src/nosql_databases/tutorial001.py!}
|
||||
```
|
||||
|
||||
@@ -135,7 +135,7 @@ UserInDB(username="johndoe", hashed_password="some_hash")
|
||||
|
||||
### Create the `FastAPI` app
|
||||
|
||||
```Python hl_lines="47"
|
||||
```Python hl_lines="46"
|
||||
{!../../../docs_src/nosql_databases/tutorial001.py!}
|
||||
```
|
||||
|
||||
@@ -145,7 +145,7 @@ As our code is calling Couchbase and we are not using the <a href="https://docs.
|
||||
|
||||
Also, Couchbase recommends not using a single `Bucket` object in multiple "<abbr title="A sequence of code being executed by the program, while at the same time, or at intervals, there can be others being executed too.">thread</abbr>s", so, we can get just get the bucket directly and pass it to our utility functions:
|
||||
|
||||
```Python hl_lines="50 51 52 53 54"
|
||||
```Python hl_lines="49 50 51 52 53"
|
||||
{!../../../docs_src/nosql_databases/tutorial001.py!}
|
||||
```
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ It will have a *path operation* that will receive an `Invoice` body, and a query
|
||||
|
||||
This part is pretty normal, most of the code is probably already familiar to you:
|
||||
|
||||
```Python hl_lines="8 9 10 11 12 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53"
|
||||
```Python hl_lines="10 11 12 13 14 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54"
|
||||
{!../../../docs_src/openapi_callbacks/tutorial001.py!}
|
||||
```
|
||||
|
||||
@@ -92,7 +92,7 @@ Because of that, you need to declare what will be the `default_response_class`,
|
||||
|
||||
But as we are never calling `app.include_router(some_router)`, we need to set the `default_response_class` during creation of the `APIRouter`.
|
||||
|
||||
```Python hl_lines="3 24"
|
||||
```Python hl_lines="5 26"
|
||||
{!../../../docs_src/openapi_callbacks/tutorial001.py!}
|
||||
```
|
||||
|
||||
@@ -105,7 +105,7 @@ It should look just like a normal FastAPI *path operation*:
|
||||
* It should probably have a declaration of the body it should receive, e.g. `body: InvoiceEvent`.
|
||||
* And it could also have a declaration of the response it should return, e.g. `response_model=InvoiceEventReceived`.
|
||||
|
||||
```Python hl_lines="15 16 17 20 21 27 28 29 30 31"
|
||||
```Python hl_lines="17 18 19 22 23 29 30 31 32 33"
|
||||
{!../../../docs_src/openapi_callbacks/tutorial001.py!}
|
||||
```
|
||||
|
||||
@@ -172,7 +172,7 @@ At this point you have the *callback path operation(s)* needed (the one(s) that
|
||||
|
||||
Now use the parameter `callbacks` in *your API's path operation decorator* to pass the attribute `.routes` (that's actually just a `list` of routes/*path operations*) from that callback router:
|
||||
|
||||
```Python hl_lines="34"
|
||||
```Python hl_lines="36"
|
||||
{!../../../docs_src/openapi_callbacks/tutorial001.py!}
|
||||
```
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ For example, you cannot put a Pydantic model in a `JSONResponse` without first c
|
||||
|
||||
For those cases, you can use the `jsonable_encoder` to convert your data before passing it to a response:
|
||||
|
||||
```Python hl_lines="4 6 20 21"
|
||||
```Python hl_lines="6 7 21 22"
|
||||
{!../../../docs_src/response_directly/tutorial001.py!}
|
||||
```
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@ They are normally used to declare specific security permissions, for example:
|
||||
|
||||
First, let's quickly see the parts that change from the examples in the main **Tutorial - User Guide** for [OAuth2 with Password (and hashing), Bearer with JWT tokens](../../tutorial/security/oauth2-jwt.md){.internal-link target=_blank}. Now using OAuth2 scopes:
|
||||
|
||||
```Python hl_lines="2 5 9 13 47 65 106 108 109 110 111 112 113 114 115 116 122 123 124 125 129 130 131 132 133 134 135 140 154"
|
||||
```Python hl_lines="2 4 8 12 46 64 105 107 108 109 110 111 112 113 114 115 121 122 123 124 128 129 130 131 132 133 134 139 153"
|
||||
{!../../../docs_src/security/tutorial005.py!}
|
||||
```
|
||||
|
||||
@@ -68,7 +68,7 @@ The first change is that now we are declaring the OAuth2 security scheme with tw
|
||||
|
||||
The `scopes` parameter receives a `dict` with each scope as a key and the description as the value:
|
||||
|
||||
```Python hl_lines="63 64 65 66"
|
||||
```Python hl_lines="62 63 64 65"
|
||||
{!../../../docs_src/security/tutorial005.py!}
|
||||
```
|
||||
|
||||
@@ -93,7 +93,7 @@ And we return the scopes as part of the JWT token.
|
||||
|
||||
But in your application, for security, you should make sure you only add the scopes that the user is actually able to have, or the ones you have predefined.
|
||||
|
||||
```Python hl_lines="155"
|
||||
```Python hl_lines="153"
|
||||
{!../../../docs_src/security/tutorial005.py!}
|
||||
```
|
||||
|
||||
@@ -118,7 +118,7 @@ In this case, it requires the scope `me` (it could require more than one scope).
|
||||
|
||||
We are doing it here to demonstrate how **FastAPI** handles scopes declared at different levels.
|
||||
|
||||
```Python hl_lines="5 140 167"
|
||||
```Python hl_lines="4 139 166"
|
||||
{!../../../docs_src/security/tutorial005.py!}
|
||||
```
|
||||
|
||||
@@ -143,7 +143,7 @@ We also declare a special parameter of type `SecurityScopes`, imported from `fas
|
||||
|
||||
This `SecurityScopes` class is similar to `Request` (`Request` was used to get the request object directly).
|
||||
|
||||
```Python hl_lines="9 106"
|
||||
```Python hl_lines="8 105"
|
||||
{!../../../docs_src/security/tutorial005.py!}
|
||||
```
|
||||
|
||||
@@ -159,7 +159,7 @@ We create an `HTTPException` that we can re-use (`raise`) later at several point
|
||||
|
||||
In this exception, we include the scopes required (if any) as a string separated by spaces (using `scope_str`). We put that string containing the scopes in in the `WWW-Authenticate` header (this is part of the spec).
|
||||
|
||||
```Python hl_lines="106 108 109 110 111 112 113 114 115 116"
|
||||
```Python hl_lines="105 107 108 109 110 111 112 113 114 115"
|
||||
{!../../../docs_src/security/tutorial005.py!}
|
||||
```
|
||||
|
||||
@@ -177,7 +177,7 @@ Instead of, for example, a `dict`, or something else, as it could break the appl
|
||||
|
||||
We also verify that we have a user with that username, and if not, we raise that same exception we created before.
|
||||
|
||||
```Python hl_lines="47 117 118 119 120 121 122 123 124 125 126 127 128"
|
||||
```Python hl_lines="46 116 117 118 119 120 121 122 123 124 125 126 127"
|
||||
{!../../../docs_src/security/tutorial005.py!}
|
||||
```
|
||||
|
||||
@@ -187,7 +187,7 @@ We now verify that all the scopes required, by this dependency and all the depen
|
||||
|
||||
For this, we use `security_scopes.scopes`, that contains a `list` with all these scopes as `str`.
|
||||
|
||||
```Python hl_lines="129 130 131 132 133 134 135"
|
||||
```Python hl_lines="128 129 130 131 132 133 134"
|
||||
{!../../../docs_src/security/tutorial005.py!}
|
||||
```
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ If you need to have two independent FastAPI applications, with their own indepen
|
||||
|
||||
## Mounting a **FastAPI** application
|
||||
|
||||
"Mounting" means adding a completely "independent" application in a specific path, that then takes care of handling all everything under that path, with the _path operations_ declared in that sub-application.
|
||||
"Mounting" means adding a completely "independent" application in a specific path, that then takes care of handling everything under that path, with the _path operations_ declared in that sub-application.
|
||||
|
||||
### Top-level application
|
||||
|
||||
|
||||
@@ -39,13 +39,16 @@ $ pip install aiofiles
|
||||
* Declare a `Request` parameter in the *path operation* that will return a template.
|
||||
* Use the `templates` you created to render and return a `TemplateResponse`, passing the `request` as one of the key-value pairs in the Jinja2 "context".
|
||||
|
||||
```Python hl_lines="3 10 14 15"
|
||||
```Python hl_lines="4 11 15 16"
|
||||
{!../../../docs_src/templates/tutorial001.py!}
|
||||
```
|
||||
|
||||
!!! note
|
||||
Notice that you have to pass the `request` as part of the key-value pairs in the context for Jinja2. So, you also have to declare it in your *path operation*.
|
||||
|
||||
!!! tip
|
||||
By declaring `response_class=HTMLResponse` the docs UI will be able to know that the response will be HTML.
|
||||
|
||||
!!! note "Technical Details"
|
||||
You could also use `from starlette.templating import Jinja2Templates`.
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ To override a dependency for testing, you put as a key the original dependency (
|
||||
|
||||
And then **FastAPI** will call that override instead of the original dependency.
|
||||
|
||||
```Python hl_lines="24 25 28"
|
||||
```Python hl_lines="26 27 30"
|
||||
{!../../../docs_src/dependency_testing/tutorial001.py!}
|
||||
```
|
||||
|
||||
|
||||
@@ -7,3 +7,6 @@ For this, you use the `TestClient` in a `with` statement, connecting to the WebS
|
||||
```Python hl_lines="27 28 29 30 31"
|
||||
{!../../../docs_src/app_testing/tutorial002.py!}
|
||||
```
|
||||
|
||||
!!! note
|
||||
For more details, check Starlette's documentation for <a href="https://www.starlette.io/testclient/#testing-websocket-sessions" class="external-link" target="_blank">testing WebSockets</a>.
|
||||
|
||||
@@ -51,38 +51,7 @@ In your WebSocket route you can `await` for messages and send messages.
|
||||
|
||||
You can receive and send binary, text, and JSON data.
|
||||
|
||||
## Using `Depends` and others
|
||||
|
||||
In WebSocket endpoints you can import from `fastapi` and use:
|
||||
|
||||
* `Depends`
|
||||
* `Security`
|
||||
* `Cookie`
|
||||
* `Header`
|
||||
* `Path`
|
||||
* `Query`
|
||||
|
||||
They work the same way as for other FastAPI endpoints/*path operations*:
|
||||
|
||||
```Python hl_lines="53 54 55 56 57 58 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76"
|
||||
{!../../../docs_src/websockets/tutorial002.py!}
|
||||
```
|
||||
|
||||
!!! info
|
||||
In a WebSocket it doesn't really make sense to raise an `HTTPException`. So it's better to close the WebSocket connection directly.
|
||||
|
||||
You can use a closing code from the <a href="https://tools.ietf.org/html/rfc6455#section-7.4.1" class="external-link" target="_blank">valid codes defined in the specification</a>.
|
||||
|
||||
In the future, there will be a `WebSocketException` that you will be able to `raise` from anywhere, and add exception handlers for it. It depends on the <a href="https://github.com/encode/starlette/pull/527" class="external-link" target="_blank">PR #527</a> in Starlette.
|
||||
|
||||
## More info
|
||||
|
||||
To learn more about the options, check Starlette's documentation for:
|
||||
|
||||
* <a href="https://www.starlette.io/websockets/" class="external-link" target="_blank">The `WebSocket` class</a>.
|
||||
* <a href="https://www.starlette.io/endpoints/#websocketendpoint" class="external-link" target="_blank">Class-based WebSocket handling</a>.
|
||||
|
||||
## Test it
|
||||
## Try it
|
||||
|
||||
If your file is named `main.py`, run your application with:
|
||||
|
||||
@@ -115,3 +84,62 @@ You can send (and receive) many messages:
|
||||
<img src="/img/tutorial/websockets/image04.png">
|
||||
|
||||
And all of them will use the same WebSocket connection.
|
||||
|
||||
## Using `Depends` and others
|
||||
|
||||
In WebSocket endpoints you can import from `fastapi` and use:
|
||||
|
||||
* `Depends`
|
||||
* `Security`
|
||||
* `Cookie`
|
||||
* `Header`
|
||||
* `Path`
|
||||
* `Query`
|
||||
|
||||
They work the same way as for other FastAPI endpoints/*path operations*:
|
||||
|
||||
```Python hl_lines="58 59 60 61 62 63 64 65 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83"
|
||||
{!../../../docs_src/websockets/tutorial002.py!}
|
||||
```
|
||||
|
||||
!!! info
|
||||
In a WebSocket it doesn't really make sense to raise an `HTTPException`. So it's better to close the WebSocket connection directly.
|
||||
|
||||
You can use a closing code from the <a href="https://tools.ietf.org/html/rfc6455#section-7.4.1" class="external-link" target="_blank">valid codes defined in the specification</a>.
|
||||
|
||||
In the future, there will be a `WebSocketException` that you will be able to `raise` from anywhere, and add exception handlers for it. It depends on the <a href="https://github.com/encode/starlette/pull/527" class="external-link" target="_blank">PR #527</a> in Starlette.
|
||||
|
||||
### Try the WebSockets with dependencies
|
||||
|
||||
If your file is named `main.py`, run your application with:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ uvicorn main:app --reload
|
||||
|
||||
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
Open your browser at <a href="http://127.0.0.1:8000" class="external-link" target="_blank">http://127.0.0.1:8000</a>.
|
||||
|
||||
There you can set:
|
||||
|
||||
* The "Item ID", used in the path.
|
||||
* The "Token" used as a query parameter.
|
||||
|
||||
!!! tip
|
||||
Notice that the query `token` will be handled by a dependency.
|
||||
|
||||
With that you can connect the WebSocket and then send and receive messages:
|
||||
|
||||
<img src="/img/tutorial/websockets/image05.png">
|
||||
|
||||
## More info
|
||||
|
||||
To learn more about the options, check Starlette's documentation for:
|
||||
|
||||
* <a href="https://www.starlette.io/websockets/" class="external-link" target="_blank">The `WebSocket` class</a>.
|
||||
* <a href="https://www.starlette.io/endpoints/#websocketendpoint" class="external-link" target="_blank">Class-based WebSocket handling</a>.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Including WSGI - Flask, Django, others
|
||||
|
||||
You can mount WSGI applications as you saw with [Sub Applications - Behind a Proxy, Mounts](./sub-applications-proxy.md){.internal-link target=_blank}.
|
||||
You can mount WSGI applications as you saw with [Sub Applications - Mounts](./sub-applications.md){.internal-link target=_blank}, [Behind a Proxy](./behind-a-proxy.md){.internal-link target=_blank}.
|
||||
|
||||
For that, you can use the `WSGIMiddleware` and use it to wrap your WSGI application, for example, Flask, Django, etc.
|
||||
|
||||
|
||||
@@ -499,13 +499,3 @@ $ bash scripts/test-cov-html.sh
|
||||
</div>
|
||||
|
||||
This command generates a directory `./htmlcov/`, if you open the file `./htmlcov/index.html` in your browser, you can explore interactively the regions of code that are covered by the tests, and notice if there is any region missing.
|
||||
|
||||
### Tests in your editor
|
||||
|
||||
If you want to use the integrated tests in your editor add `./docs_src` to your `PYTHONPATH` variable.
|
||||
|
||||
For example, in VS Code you can create a file `.env` with:
|
||||
|
||||
```env
|
||||
PYTHONPATH=./docs_src
|
||||
```
|
||||
|
||||
@@ -161,6 +161,8 @@ CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80"]
|
||||
* Create a `main.py` file with:
|
||||
|
||||
```Python
|
||||
from typing import Optional
|
||||
|
||||
from fastapi import FastAPI
|
||||
|
||||
app = FastAPI()
|
||||
@@ -172,7 +174,7 @@ def read_root():
|
||||
|
||||
|
||||
@app.get("/items/{item_id}")
|
||||
def read_item(item_id: int, q: str = None):
|
||||
def read_item(item_id: int, q: Optional[str] = None):
|
||||
return {"item_id": item_id, "q": q}
|
||||
```
|
||||
|
||||
|
||||
@@ -7,135 +7,72 @@ There are many posts, articles, tools, and projects, related to **FastAPI**.
|
||||
Here's an incomplete list of some of them.
|
||||
|
||||
!!! tip
|
||||
If you have an article, project, tool, or anything related to **FastAPI** that is not yet listed here, create a <a href="https://github.com/tiangolo/fastapi/edit/master/docs/external-links.md" class="external-link" target="_blank">Pull Request adding it</a>.
|
||||
If you have an article, project, tool, or anything related to **FastAPI** that is not yet listed here, create a <a href="https://github.com/tiangolo/fastapi/edit/master/docs/en/data/external_links.yml" class="external-link" target="_blank">Pull Request adding it</a>.
|
||||
|
||||
## Articles
|
||||
|
||||
### English
|
||||
|
||||
* <a href="https://medium.com/@williamhayes/fastapi-starlette-debug-vs-prod-5f7561db3a59" class="external-link" target="_blank">FastAPI/Starlette debug vs prod</a> by <a href="https://medium.com/@williamhayes" class="external-link" target="_blank">William Hayes</a>.
|
||||
{% if external_links %}
|
||||
{% for article in external_links.articles.english %}
|
||||
|
||||
* <a href="https://medium.com/data-rebels/fastapi-google-as-an-external-authentication-provider-3a527672cf33" class="external-link" target="_blank">FastAPI — Google as an external authentication provider</a> by <a href="https://medium.com/@nils_29588" class="external-link" target="_blank">Nils de Bruin</a>.
|
||||
|
||||
* <a href="https://medium.com/data-rebels/fastapi-how-to-add-basic-and-cookie-authentication-a45c85ef47d3" class="external-link" target="_blank">FastAPI — How to add basic and cookie authentication</a> by <a href="https://medium.com/@nils_29588" class="external-link" target="_blank">Nils de Bruin</a>.
|
||||
|
||||
* <a href="https://dev.to/errietta/introduction-to-the-fastapi-python-framework-2n10" class="external-link" target="_blank">Introduction to the fastapi python framework</a> by <a href="https://dev.to/errietta" class="external-link" target="_blank">Errieta Kostala</a>.
|
||||
|
||||
* <a href="http://nickc1.github.io/api,/scikit-learn/2019/01/10/scikit-fastapi.html" class="external-link" target="_blank">FastAPI and Scikit-Learn: Easily Deploy Models</a> by <a href="http://nickc1.github.io/" class="external-link" target="_blank">Nick Cortale</a>.
|
||||
|
||||
* <a href="https://medium.com/data-rebels/fastapi-authentication-revisited-enabling-api-key-authentication-122dc5975680" class="external-link" target="_blank">FastAPI authentication revisited: Enabling API key authentication</a> by <a href="https://medium.com/@nils_29588" class="external-link" target="_blank">Nils de Bruin</a>.
|
||||
|
||||
* <a href="https://blog.bartab.fr/fastapi-logging-on-the-fly/" class="external-link" target="_blank">FastAPI, a simple use case on logging</a> by <a href="https://blog.bartab.fr/" class="external-link" target="_blank">@euri10</a>.
|
||||
|
||||
* <a href="https://medium.com/@nico.axtmann95/deploying-a-scikit-learn-model-with-onnx-und-fastapi-1af398268915" class="external-link" target="_blank">Deploying a scikit-learn model with ONNX and FastAPI</a> by <a href="https://www.linkedin.com/in/nico-axtmann" class="external-link" target="_blank">Nico Axtmann</a>.
|
||||
|
||||
* <a href="https://geekflare.com/python-asynchronous-web-frameworks/" class="external-link" target="_blank">Top 5 Asynchronous Web Frameworks for Python</a> by <a href="https://geekflare.com/author/ankush/" class="external-link" target="_blank">Ankush Thakur</a> on <a href="https://geekflare.com" class="external-link" target="_blank">GeekFlare</a>.
|
||||
|
||||
* <a href="https://medium.com/@gntrm/jwt-authentication-with-fastapi-and-aws-cognito-1333f7f2729e" class="external-link" target="_blank">JWT Authentication with FastAPI and AWS Cognito</a> by <a href="https://twitter.com/gntrm" class="external-link" target="_blank">Johannes Gontrum</a>.
|
||||
|
||||
* <a href="https://towardsdatascience.com/how-to-deploy-a-machine-learning-model-dc51200fe8cf" class="external-link" target="_blank">How to Deploy a Machine Learning Model</a> by <a href="https://www.linkedin.com/in/mgrootendorst/" class="external-link" target="_blank">Maarten Grootendorst</a> on <a href="https://towardsdatascience.com/" class="external-link" target="_blank">Towards Data Science</a>.
|
||||
|
||||
* [Uber: Ludwig v0.2 Adds New Features and Other Improvements to its Deep Learning Toolbox [including a FastAPI server]](https://eng.uber.com/ludwig-v0-2/){.external-link target=_blank} on <a href="https://eng.uber.com" class="external-link" target="_blank">Uber Engineering</a>.
|
||||
|
||||
* <a href="https://gitlab.com/euri10/fastapi_cheatsheet" class="external-link" target="_blank">A FastAPI and Swagger UI visual cheatsheet</a> by <a href="https://gitlab.com/euri10" class="external-link" target="_blank">@euri10</a>
|
||||
|
||||
* <a href="https://medium.com/@mike.p.moritz/using-docker-compose-to-deploy-a-lightweight-python-rest-api-with-a-job-queue-37e6072a209b" class="external-link" target="_blank">Using Docker Compose to deploy a lightweight Python REST API with a job queue</a> by <a href="https://medium.com/@mike.p.moritz" class="external-link" target="_blank">Mike Moritz</a>.
|
||||
|
||||
* <a href="https://robwagner.dev/tortoise-fastapi-setup/" class="external-link" target="_blank">Setting up Tortoise ORM with FastAPI</a> by <a href="https://robwagner.dev/" class="external-link" target="_blank">Rob Wagner</a>.
|
||||
|
||||
* <a href="https://dev.to/dbanty/why-i-m-leaving-flask-3ki6" class="external-link" target="_blank">Why I'm Leaving Flask</a> by <a href="https://dev.to/dbanty" class="external-link" target="_blank">Dylan Anthony</a>.
|
||||
|
||||
* <a href="https://medium.com/python-data/how-to-deploy-tensorflow-2-0-models-as-an-api-service-with-fastapi-docker-128b177e81f3" class="external-link" target="_blank">How To Deploy Tensorflow 2.0 Models As An API Service With FastAPI & Docker</a> by <a href="https://medium.com/@bbrenyah" class="external-link" target="_blank">Bernard Brenyah</a>.
|
||||
|
||||
* <a href="https://testdriven.io/blog/fastapi-crud/" class="external-link" target="_blank">TestDriven.io: Developing and Testing an Asynchronous API with FastAPI and Pytest</a> by <a href="https://testdriven.io/authors/herman/" class="external-link" target="_blank">Michael Herman</a>.
|
||||
|
||||
* <a href="https://towardsdatascience.com/deploying-iris-classifications-with-fastapi-and-docker-7c9b83fdec3a" class="external-link" target="_blank">Towards Data Science: Deploying Iris Classifications with FastAPI and Docker</a> by <a href="https://towardsdatascience.com/@mandygu" class="external-link" target="_blank">Mandy Gu</a>.
|
||||
|
||||
* <a href="https://medium.com/analytics-vidhya/deploy-machine-learning-models-with-keras-fastapi-redis-and-docker-4940df614ece" class="external-link" target="_blank">Deploy Machine Learning Models with Keras, FastAPI, Redis and Docker</a> by <a href="https://medium.com/@shane.soh" class="external-link" target="_blank">Shane Soh</a>.
|
||||
|
||||
* <a href="https://medium.com/@arthur393/another-boilerplate-to-fastapi-azure-pipeline-ci-pytest-3c8d9a4be0bb" class="external-link" target="_blank">Another Boilerplate to FastAPI: Azure Pipeline CI + Pytest</a> by <a href="https://twitter.com/arthurheinrique" class="external-link" target="_blank">Arthur Henrique</a>.
|
||||
|
||||
* <a href="https://iwpnd.pw/articles/2020-01/deploy-fastapi-to-aws-lambda" class="external-link" target="_blank">How to continuously deploy a FastAPI to AWS Lambda with AWS SAM</a> by <a href="https://iwpnd.pw" class="external-link" target="_blank">Benjamin Ramser</a>.
|
||||
|
||||
* <a href="https://www.tutlinks.com/create-and-deploy-fastapi-app-to-heroku/" class="external-link" target="_blank">Create and Deploy FastAPI app to Heroku without using Docker</a> by <a href="https://www.linkedin.com/in/navule/" class="external-link" target="_blank">Navule Pavan Kumar Rao</a>.
|
||||
|
||||
* <a href="https://iwpnd.pw/articles/2020-03/apache-kafka-fastapi-geostream" class="external-link" target="_blank">Apache Kafka producer and consumer with FastAPI and aiokafka</a> by <a href="https://iwpnd.pw" class="external-link" target="_blank">Benjamin Ramser</a>.
|
||||
|
||||
* <a href="https://wuilly.com/2019/10/real-time-notifications-with-python-and-postgres/" class="external-link" target="_blank">Real-time Notifications with Python and Postgres</a> by <a href="https://wuilly.com/" class="external-link" target="_blank">Guillermo Cruz</a>.
|
||||
|
||||
* <a href="https://dev.to/paurakhsharma/microservice-in-python-using-fastapi-24cc" class="external-link" target="_blank">Microservice in Python using FastAPI</a> by <a href="https://twitter.com/PaurakhSharma" class="external-link" target="_blank">Paurakh Sharma Humagain</a>.
|
||||
|
||||
* <a href="https://dev.to/cuongld2/build-simple-api-service-with-python-fastapi-part-1-581o" class="external-link" target="_blank">Build simple API service with Python FastAPI — Part 1</a> by <a href="https://dev.to/cuongld2" class="external-link" target="_blank">cuongld2</a>.
|
||||
|
||||
* <a href="https://paulsec.github.io/posts/fastapi_plus_zeit_serverless_fu/" class="external-link" target="_blank">FastAPI + Zeit.co = 🚀
|
||||
</a> by <a href="https://twitter.com/PaulWebSec" class="external-link" target="_blank">Paul Sec</a>.
|
||||
|
||||
* <a href="https://dev.to/tiangolo/build-a-web-api-from-scratch-with-fastapi-the-workshop-2ehe" class="external-link" target="_blank">Build a web API from scratch with FastAPI - the workshop</a> by <a href="https://twitter.com/tiangolo" class="external-link" target="_blank">Sebastián Ramírez (tiangolo)</a>.
|
||||
|
||||
* <a href="https://www.twilio.com/blog/build-secure-twilio-webhook-python-fastapi" class="external-link" target="_blank">Build a Secure Twilio Webhook with Python and FastAPI</a> by <a href="https://www.twilio.com" class="external-link" target="_blank">Twilio</a>.
|
||||
|
||||
* <a href="https://www.stavros.io/posts/fastapi-with-django/" class="external-link" target="_blank">Using FastAPI with Django</a> by <a href="https://twitter.com/Stavros" class="external-link" target="_blank">Stavros Korokithakis</a>.
|
||||
|
||||
* <a href="https://netflixtechblog.com/introducing-dispatch-da4b8a2a8072" class="external-link" target="_blank">Introducing Dispatch</a> by <a href="https://netflixtechblog.com/" class="external-link" target="_blank">Netflix</a>.
|
||||
* <a href="{{ article.link }}" class="external-link" target="_blank">{{ article.title }}</a> by <a href="{{ article.author_link }}" class="external-link" target="_blank">{{ article.author }}</a>.
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
### Japanese
|
||||
|
||||
* <a href="https://qiita.com/mtitg/items/47770e9a562dd150631d" class="external-link" target="_blank">FastAPI|DB接続してCRUDするPython製APIサーバーを構築</a> by <a href="https://qiita.com/mtitg" class="external-link" target="_blank">@mtitg</a>.
|
||||
{% if external_links %}
|
||||
{% for article in external_links.articles.japanese %}
|
||||
|
||||
* <a href="https://qiita.com/ryoryomaru/items/59958ed385b3571d50de" class="external-link" target="_blank">python製の最新APIフレームワーク FastAPI を触ってみた</a> by <a href="https://qiita.com/ryoryomaru" class="external-link" target="_blank">@ryoryomaru</a>.
|
||||
|
||||
* <a href="https://qiita.com/angel_katayoku/items/0e1f5dbbe62efc612a78" class="external-link" target="_blank">FastAPIでCORSを回避</a> by <a href="https://qiita.com/angel_katayoku" class="external-link" target="_blank">@angel_katayoku</a>.
|
||||
|
||||
* <a href="https://qiita.com/angel_katayoku/items/4fbc1a4e2b33fa2237d2" class="external-link" target="_blank">FastAPIをMySQLと接続してDockerで管理してみる</a> by <a href="https://qiita.com/angel_katayoku" class="external-link" target="_blank">@angel_katayoku</a>.
|
||||
|
||||
* <a href="https://qiita.com/angel_katayoku/items/8a458a8952f50b73f420" class="external-link" target="_blank">FastAPIでPOSTされたJSONのレスポンスbodyを受け取る</a> by <a href="https://qiita.com/angel_katayoku" class="external-link" target="_blank">@angel_katayoku</a>.
|
||||
|
||||
* <a href="https://qiita.com/hikarut/items/b178af2e2440c67c6ac4" class="external-link" target="_blank">フロントエンド開発者向けのDockerによるPython開発環境構築</a> by <a href="https://qiita.com/hikarut" class="external-link" target="_blank">Hikaru Takahashi</a>.
|
||||
|
||||
* <a href="https://rightcode.co.jp/blog/information-technology/fastapi-tutorial-todo-apps-environment" class="external-link" target="_blank">【第1回】FastAPIチュートリアル: ToDoアプリを作ってみよう【環境構築編】</a> by <a href="https://rightcode.co.jp/author/jun" class="external-link" target="_blank">ライトコードメディア編集部</a>
|
||||
|
||||
* <a href="https://rightcode.co.jp/blog/information-technology/fastapi-tutorial-todo-apps-model-building" class="external-link" target="_blank">【第2回】FastAPIチュートリアル: ToDoアプリを作ってみよう【モデル構築編】</a> by <a href="https://rightcode.co.jp/author/jun" class="external-link" target="_blank">ライトコードメディア編集部</a>
|
||||
|
||||
* <a href="https://rightcode.co.jp/blog/information-technology/fastapi-tutorial-todo-apps-authentication-user-registration" class="external-link" target="_blank">【第3回】FastAPIチュートリアル: toDoアプリを作ってみよう【認証・ユーザ登録編】</a> by <a href="https://rightcode.co.jp/author/jun" class="external-link" target="_blank">ライトコードメディア編集部</a>
|
||||
|
||||
* <a href="https://rightcode.co.jp/blog/information-technology/fastapi-tutorial-todo-apps-admin-page-improvement" class="external-link" target="_blank">【第4回】FastAPIチュートリアル: toDoアプリを作ってみよう【管理者ページ改良編】</a> by <a href="https://rightcode.co.jp/author/jun" class="external-link" target="_blank">ライトコードメディア編集部</a>
|
||||
|
||||
* <a href="https://qiita.com/bee2/items/0ad260ab9835a2087dae" class="external-link" target="_blank">PythonのWeb frameworkのパフォーマンス比較 (Django, Flask, responder, FastAPI, japronto)</a> by <a href="https://qiita.com/bee2" class="external-link" target="_blank">@bee2</a>.
|
||||
|
||||
* <a href="https://qiita.com/bee2/items/75d9c0d7ba20e7a4a0e9" class="external-link" target="_blank">[FastAPI] Python製のASGI Web フレームワーク FastAPIに入門する</a> by <a href="https://qiita.com/bee2" class="external-link" target="_blank">@bee2</a>.
|
||||
|
||||
### Chinese
|
||||
|
||||
* <a href="https://cloud.tencent.com/developer/article/1431448" class="external-link" target="_blank">使用FastAPI框架快速构建高性能的api服务</a> by <a href="https://cloud.tencent.com/developer/user/5471722" class="external-link" target="_blank">逍遥散人</a>.
|
||||
|
||||
* <a href="https://wxq0309.github.io/" class="external-link" target="_blank">FastAPI框架中文文档</a> by <a href="https://wxq0309.github.io/" class="external-link" target="_blank">何大仙</a>.
|
||||
* <a href="{{ article.link }}" class="external-link" target="_blank">{{ article.title }}</a> by <a href="{{ article.author_link }}" class="external-link" target="_blank">{{ article.author }}</a>.
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
### Vietnamese
|
||||
|
||||
* <a href="https://fullstackstation.com/fastapi-trien-khai-bang-docker/" class="external-link" target="_blank">FASTAPI: TRIỂN KHAI BẰNG DOCKER</a> by <a href="https://fullstackstation.com/author/figonking/" class="external-link" target="_blank">Nguyễn Nhân</a>.
|
||||
{% if external_links %}
|
||||
{% for article in external_links.articles.vietnamese %}
|
||||
|
||||
* <a href="{{ article.link }}" class="external-link" target="_blank">{{ article.title }}</a> by <a href="{{ article.author_link }}" class="external-link" target="_blank">{{ article.author }}</a>.
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
### Russian
|
||||
|
||||
* <a href="https://habr.com/ru/post/454440/" class="external-link" target="_blank">Мелкая питонячая радость #2: Starlette - Солидная примочка – FastAPI</a> by <a href="https://habr.com/ru/users/57uff3r/" class="external-link" target="_blank">Andrey Korchak</a>.
|
||||
{% if external_links %}
|
||||
{% for article in external_links.articles.russian %}
|
||||
|
||||
* <a href="https://habr.com/ru/post/478620/" class="external-link" target="_blank">Почему Вы должны попробовать FastAPI?</a> by <a href="https://github.com/prostomarkeloff" class="external-link" target="_blank">prostomarkeloff</a>.
|
||||
* <a href="{{ article.link }}" class="external-link" target="_blank">{{ article.title }}</a> by <a href="{{ article.author_link }}" class="external-link" target="_blank">{{ article.author }}</a>.
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
### German
|
||||
|
||||
* <a href="https://blog.codecentric.de/2019/08/inbetriebnahme-eines-scikit-learn-modells-mit-onnx-und-fastapi/" class="external-link" target="_blank">Inbetriebnahme eines scikit-learn-Modells mit ONNX und FastAPI</a> by <a href="https://twitter.com/_nicoax" class="external-link" target="_blank">Nico Axtmann</a>.
|
||||
{% if external_links %}
|
||||
{% for article in external_links.articles.german %}
|
||||
|
||||
* <a href="{{ article.link }}" class="external-link" target="_blank">{{ article.title }}</a> by <a href="{{ article.author_link }}" class="external-link" target="_blank">{{ article.author }}</a>.
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
## Podcasts
|
||||
|
||||
* <a href="https://pythonbytes.fm/episodes/show/123/time-to-right-the-py-wrongs?time_in_sec=855" class="external-link" target="_blank">FastAPI on PythonBytes</a> by <a href="https://pythonbytes.fm/" class="external-link" target="_blank">Python Bytes FM</a>.
|
||||
* <a href="https://www.pythonpodcast.com/fastapi-web-application-framework-episode-259/" class="external-link" target="_blank">Build The Next Generation Of Python Web Applications With FastAPI - Episode 259 - interview to Sebastían Ramírez (tiangolo)</a> by <a href="https://www.pythonpodcast.com/" class="external-link" target="_blank">Podcast.`__init__`</a>.
|
||||
{% if external_links %}
|
||||
{% for article in external_links.podcasts.english %}
|
||||
|
||||
* <a href="{{ article.link }}" class="external-link" target="_blank">{{ article.title }}</a> by <a href="{{ article.author_link }}" class="external-link" target="_blank">{{ article.author }}</a>.
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
## Talks
|
||||
|
||||
* <a href="https://www.youtube.com/watch?v=3DLwPcrE5mA" class="external-link" target="_blank">PyCon UK 2019: FastAPI from the ground up</a> by <a href="https://twitter.com/chriswithers13" class="external-link" target="_blank">Chris Withers</a>.
|
||||
{% if external_links %}
|
||||
{% for article in external_links.talks.english %}
|
||||
|
||||
* <a href="https://www.youtube.com/watch?v=z9K5pwb0rt8" class="external-link" target="_blank">PyConBY 2020: Serve ML models easily with FastAPI</a> by <a href="https://twitter.com/tiangolo" class="external-link" target="_blank">Sebastián Ramírez (tiangolo)</a>.
|
||||
|
||||
* <a href="https://www.youtube.com/watch?v=PnpTY1f4k2U" class="external-link" target="_blank">[VIRTUAL] Py.Amsterdam's flying Software Circus: Intro to FastAPI</a> by <a href="https://twitter.com/tiangolo" class="external-link" target="_blank">Sebastián Ramírez (tiangolo)</a>.
|
||||
* <a href="{{ article.link }}" class="external-link" target="_blank">{{ article.title }}</a> by <a href="{{ article.author_link }}" class="external-link" target="_blank">{{ article.author }}</a>.
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
## Projects
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 80 KiB After Width: | Height: | Size: 71 KiB |
|
Before Width: | Height: | Size: 59 KiB After Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 61 KiB |
BIN
docs/en/docs/img/tutorial/behind-a-proxy/image03.png
Normal file
|
After Width: | Height: | Size: 72 KiB |
BIN
docs/en/docs/img/tutorial/metadata/image02.png
Normal file
|
After Width: | Height: | Size: 47 KiB |
|
Before Width: | Height: | Size: 79 KiB After Width: | Height: | Size: 88 KiB |
|
Before Width: | Height: | Size: 82 KiB After Width: | Height: | Size: 82 KiB |
|
Before Width: | Height: | Size: 79 KiB After Width: | Height: | Size: 80 KiB |
|
Before Width: | Height: | Size: 86 KiB After Width: | Height: | Size: 87 KiB |
|
Before Width: | Height: | Size: 79 KiB After Width: | Height: | Size: 76 KiB |
BIN
docs/en/docs/img/tutorial/websockets/image05.png
Normal file
|
After Width: | Height: | Size: 52 KiB |
@@ -5,14 +5,14 @@
|
||||
<em>FastAPI framework, high performance, easy to learn, fast to code, ready for production</em>
|
||||
</p>
|
||||
<p align="center">
|
||||
<a href="https://travis-ci.com/tiangolo/fastapi" target="_blank">
|
||||
<img src="https://travis-ci.com/tiangolo/fastapi.svg?branch=master" alt="Build Status">
|
||||
<a href="https://github.com/tiangolo/fastapi/actions?query=workflow%3ATest" target="_blank">
|
||||
<img src="https://github.com/tiangolo/fastapi/workflows/Test/badge.svg" alt="Test">
|
||||
</a>
|
||||
<a href="https://codecov.io/gh/tiangolo/fastapi" target="_blank">
|
||||
<img src="https://img.shields.io/codecov/c/github/tiangolo/fastapi" alt="Coverage">
|
||||
<img src="https://img.shields.io/codecov/c/github/tiangolo/fastapi?color=%2334D058" alt="Coverage">
|
||||
</a>
|
||||
<a href="https://pypi.org/project/fastapi" target="_blank">
|
||||
<img src="https://badge.fury.io/py/fastapi.svg" alt="Package version">
|
||||
<img src="https://img.shields.io/pypi/v/fastapi?color=%2334D058&label=pypi%20package" alt="Package version">
|
||||
</a>
|
||||
<a href="https://gitter.im/tiangolo/fastapi?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge" target="_blank">
|
||||
<img src="https://badges.gitter.im/tiangolo/fastapi.svg" alt="Join the chat at https://gitter.im/tiangolo/fastapi">
|
||||
@@ -131,6 +131,8 @@ $ pip install uvicorn
|
||||
* Create a file `main.py` with:
|
||||
|
||||
```Python
|
||||
from typing import Optional
|
||||
|
||||
from fastapi import FastAPI
|
||||
|
||||
app = FastAPI()
|
||||
@@ -142,7 +144,7 @@ def read_root():
|
||||
|
||||
|
||||
@app.get("/items/{item_id}")
|
||||
def read_item(item_id: int, q: str = None):
|
||||
def read_item(item_id: int, q: Optional[str] = None):
|
||||
return {"item_id": item_id, "q": q}
|
||||
```
|
||||
|
||||
@@ -151,7 +153,9 @@ def read_item(item_id: int, q: str = None):
|
||||
|
||||
If your code uses `async` / `await`, use `async def`:
|
||||
|
||||
```Python hl_lines="7 12"
|
||||
```Python hl_lines="9 14"
|
||||
from typing import Optional
|
||||
|
||||
from fastapi import FastAPI
|
||||
|
||||
app = FastAPI()
|
||||
@@ -163,7 +167,7 @@ async def read_root():
|
||||
|
||||
|
||||
@app.get("/items/{item_id}")
|
||||
async def read_item(item_id: int, q: str = None):
|
||||
async def read_item(item_id: int, q: Optional[str] = None):
|
||||
return {"item_id": item_id, "q": q}
|
||||
```
|
||||
|
||||
@@ -241,7 +245,9 @@ Now modify the file `main.py` to receive a body from a `PUT` request.
|
||||
|
||||
Declare the body using standard Python types, thanks to Pydantic.
|
||||
|
||||
```Python hl_lines="2 7 8 9 10 23 24 25"
|
||||
```Python hl_lines="4 9 10 11 12 25 26 27"
|
||||
from typing import Optional
|
||||
|
||||
from fastapi import FastAPI
|
||||
from pydantic import BaseModel
|
||||
|
||||
@@ -251,7 +257,7 @@ app = FastAPI()
|
||||
class Item(BaseModel):
|
||||
name: str
|
||||
price: float
|
||||
is_offer: bool = None
|
||||
is_offer: Optional[bool] = None
|
||||
|
||||
|
||||
@app.get("/")
|
||||
@@ -260,7 +266,7 @@ def read_root():
|
||||
|
||||
|
||||
@app.get("/items/{item_id}")
|
||||
def read_item(item_id: int, q: str = None):
|
||||
def read_item(item_id: int, q: Optional[str] = None):
|
||||
return {"item_id": item_id, "q": q}
|
||||
|
||||
|
||||
|
||||
@@ -2,6 +2,118 @@
|
||||
|
||||
## Latest changes
|
||||
|
||||
## 0.60.2
|
||||
|
||||
* Fix typo in docs for query parameters. PR [#1832](https://github.com/tiangolo/fastapi/pull/1832) by [@ycd](https://github.com/ycd).
|
||||
* Add docs about [Async Tests](https://fastapi.tiangolo.com/advanced/async-tests/). PR [#1619](https://github.com/tiangolo/fastapi/pull/1619) by [@empicano](https://github.com/empicano).
|
||||
* Raise an exception when using form data (`Form`, `File`) without having `python-multipart` installed.
|
||||
* Up to now the application would run, and raise an exception only when receiving a request with form data, the new behavior, raising early, will prevent from deploying applications with broken dependencies.
|
||||
* It also detects if the correct package `python-multipart` is installed instead of the incorrect `multipart` (both importable as `multipart`).
|
||||
* PR [#1851](https://github.com/tiangolo/fastapi/pull/1851) based on original PR [#1627](https://github.com/tiangolo/fastapi/pull/1627) by [@chrisngyn](https://github.com/chrisngyn), [@YKo20010](https://github.com/YKo20010), [@kx-chen](https://github.com/kx-chen).
|
||||
* Re-enable Gitter releases bot. PR [#1831](https://github.com/tiangolo/fastapi/pull/1831).
|
||||
* Add link to async SQL databases tutorial from main SQL tutorial. PR [#1813](https://github.com/tiangolo/fastapi/pull/1813) by [@short2strings](https://github.com/short2strings).
|
||||
* Fix typo in tutorial about behind a proxy. PR [#1807](https://github.com/tiangolo/fastapi/pull/1807) by [@toidi](https://github.com/toidi).
|
||||
* Fix typo in Portuguese docs. PR [#1795](https://github.com/tiangolo/fastapi/pull/1795) by [@izaguerreiro](https://github.com/izaguerreiro).
|
||||
* Add translations setup for Ukrainian. PR [#1830](https://github.com/tiangolo/fastapi/pull/1830).
|
||||
* Add external link [Build And Host Fast Data Science Applications Using FastAPI](https://towardsdatascience.com/build-and-host-fast-data-science-applications-using-fastapi-823be8a1d6a0). PR [#1786](https://github.com/tiangolo/fastapi/pull/1786) by [@Kludex](https://github.com/Kludex).
|
||||
* Fix encoding of Pydantic models that inherit from others models with custom `json_encoders`. PR [#1769](https://github.com/tiangolo/fastapi/pull/1769) by [@henrybetts](https://github.com/henrybetts).
|
||||
* Simplify and improve `jsonable_encoder`. PR [#1754](https://github.com/tiangolo/fastapi/pull/1754) by [@MashhadiNima](https://github.com/MashhadiNima).
|
||||
* Simplify internal code syntax in several points. PR [#1753](https://github.com/tiangolo/fastapi/pull/1753) by [@uriyyo](https://github.com/uriyyo).
|
||||
* Improve internal typing, declare `Optional` parameters. PR [#1731](https://github.com/tiangolo/fastapi/pull/1731) by [@MashhadiNima](https://github.com/MashhadiNima).
|
||||
* Add external link [Deploy FastAPI on Azure App Service](https://www.tutlinks.com/deploy-fastapi-on-azure/) to docs. PR [#1726](https://github.com/tiangolo/fastapi/pull/1726) by [@windson](https://github.com/windson).
|
||||
* Add link to Starlette docs about WebSocket testing. PR [#1717](https://github.com/tiangolo/fastapi/pull/1717) by [@hellocoldworld](https://github.com/hellocoldworld).
|
||||
* Refactor generating dependant, merge for loops. PR [#1714](https://github.com/tiangolo/fastapi/pull/1714) by [@Bloodielie](https://github.com/Bloodielie).
|
||||
* Update example for templates with Jinja to include HTML media type. PR [#1690](https://github.com/tiangolo/fastapi/pull/1690) by [@frafra](https://github.com/frafra).
|
||||
* Fix typos in docs for security. PR [#1678](https://github.com/tiangolo/fastapi/pull/1678) by [@nilslindemann](https://github.com/nilslindemann).
|
||||
* Fix typos in docs for dependencies. PR [#1675](https://github.com/tiangolo/fastapi/pull/1675) by [@nilslindemann](https://github.com/nilslindemann).
|
||||
* Fix type annotation for `**extra` parameters in `FastAPI`. PR [#1659](https://github.com/tiangolo/fastapi/pull/1659) by [@bharel](https://github.com/bharel).
|
||||
* Bump MkDocs Material to fix docs in browsers with dark mode. PR [#1789](https://github.com/tiangolo/fastapi/pull/1789) by [@adriencaccia](https://github.com/adriencaccia).
|
||||
* Remove docs preview comment from each commit. PR [#1826](https://github.com/tiangolo/fastapi/pull/1826).
|
||||
* Update GitHub context extraction for Gitter notification bot. PR [#1766](https://github.com/tiangolo/fastapi/pull/1766).
|
||||
|
||||
## 0.60.1
|
||||
|
||||
* Add debugging logs for GitHub actions to introspect GitHub hidden context. PR [#1764](https://github.com/tiangolo/fastapi/pull/1764).
|
||||
* Use OS preference theme for online docs. PR [#1760](https://github.com/tiangolo/fastapi/pull/1760) by [@adriencaccia](https://github.com/adriencaccia).
|
||||
* Upgrade Starlette to version `0.13.6` to handle a vulnerability when using static files in Windows. PR [#1759](https://github.com/tiangolo/fastapi/pull/1759) by [@jamesag26](https://github.com/jamesag26).
|
||||
* Pin Swagger UI temporarily, waiting for a fix for [swagger-api/swagger-ui#6249](https://github.com/swagger-api/swagger-ui/issues/6249). PR [#1763](https://github.com/tiangolo/fastapi/pull/1763).
|
||||
* Update GitHub Actions, use commit from PR for docs preview, not commit from pre-merge. PR [#1761](https://github.com/tiangolo/fastapi/pull/1761).
|
||||
* Update GitHub Actions, refactor Gitter bot. PR [#1746](https://github.com/tiangolo/fastapi/pull/1746).
|
||||
|
||||
## 0.60.0
|
||||
|
||||
* Add GitHub Action to watch for missing preview docs and trigger a preview deploy. PR [#1740](https://github.com/tiangolo/fastapi/pull/1740).
|
||||
* Add custom GitHub Action to get artifact with docs preview. PR [#1739](https://github.com/tiangolo/fastapi/pull/1739).
|
||||
* Add new GitHub Actions to preview docs from PRs. PR [#1738](https://github.com/tiangolo/fastapi/pull/1738).
|
||||
* Add XML test coverage to support GitHub Actions. PR [#1737](https://github.com/tiangolo/fastapi/pull/1737).
|
||||
* Update badges and remove Travis now that GitHub Actions is the main CI. PR [#1736](https://github.com/tiangolo/fastapi/pull/1736).
|
||||
* Add GitHub Actions for CI, move from Travis. PR [#1735](https://github.com/tiangolo/fastapi/pull/1735).
|
||||
* Add support for adding OpenAPI schema for GET requests with a body. PR [#1626](https://github.com/tiangolo/fastapi/pull/1626) by [@victorphoenix3](https://github.com/victorphoenix3).
|
||||
|
||||
## 0.59.0
|
||||
|
||||
* Fix typo in docstring for OAuth2 utils. PR [#1621](https://github.com/tiangolo/fastapi/pull/1621) by [@tomarv2](https://github.com/tomarv2).
|
||||
* Update JWT docs to use Python-jose instead of PyJWT. Initial PR [#1610](https://github.com/tiangolo/fastapi/pull/1610) by [@asheux](https://github.com/asheux).
|
||||
* Fix/re-enable search bar in docs. PR [#1703](https://github.com/tiangolo/fastapi/pull/1703).
|
||||
* Auto-generate a "server" in OpenAPI `servers` when there's a `root_path` instead of prefixing all the `paths`:
|
||||
* Add a new parameter for `FastAPI` classes: `root_path_in_servers` to disable the auto-generation of `servers`.
|
||||
* New docs about `root_path` and `servers` in [Additional Servers](https://fastapi.tiangolo.com/advanced/behind-a-proxy/#additional-servers).
|
||||
* Update OAuth2 examples to use a relative URL for `tokenUrl="token"` to make sure those examples keep working as-is even when behind a reverse proxy.
|
||||
* Initial PR [#1596](https://github.com/tiangolo/fastapi/pull/1596) by [@rkbeatss](https://github.com/rkbeatss).
|
||||
* Fix typo/link in External Links. PR [#1702](https://github.com/tiangolo/fastapi/pull/1702).
|
||||
* Update handling of [External Links](https://fastapi.tiangolo.com/external-links/) to use a data file and allow translating the headers without becoming obsolete quickly when new links are added. PR [#https://github.com/tiangolo/fastapi/pull/1701](https://github.com/tiangolo/fastapi/pull/1701).
|
||||
* Add external link [Machine learning model serving in Python using FastAPI and Streamlit](https://davidefiocco.github.io/2020/06/27/streamlit-fastapi-ml-serving.html) to docs. PR [#1669](https://github.com/tiangolo/fastapi/pull/1669) by [@davidefiocco](https://github.com/davidefiocco).
|
||||
* Add note in docs on order in Pydantic Unions. PR [#1591](https://github.com/tiangolo/fastapi/pull/1591) by [@kbanc](https://github.com/kbanc).
|
||||
* Improve support for tests in editor. PR [#1699](https://github.com/tiangolo/fastapi/pull/1699).
|
||||
* Pin dependencies. PR [#1697](https://github.com/tiangolo/fastapi/pull/1697).
|
||||
* Update isort to version 5.x.x. PR [#1670](https://github.com/tiangolo/fastapi/pull/1670) by [@asheux](https://github.com/asheux).
|
||||
|
||||
## 0.58.1
|
||||
|
||||
* Add link in docs to Pydantic data types. PR [#1612](https://github.com/tiangolo/fastapi/pull/1612) by [@tayoogunbiyi](https://github.com/tayoogunbiyi).
|
||||
* Fix link in warning logs for `openapi_prefix`. PR [#1611](https://github.com/tiangolo/fastapi/pull/1611) by [@bavaria95](https://github.com/bavaria95).
|
||||
* Fix bad link in docs. PR [#1603](https://github.com/tiangolo/fastapi/pull/1603) by [@molto0504](https://github.com/molto0504).
|
||||
* Add Vim temporary files to `.gitignore` for contributors using Vim. PR [#1590](https://github.com/tiangolo/fastapi/pull/1590) by [@asheux](https://github.com/asheux).
|
||||
* Fix typo in docs for sub-applications. PR [#1578](https://github.com/tiangolo/fastapi/pull/1578) by [@schlpbch](https://github.com/schlpbch).
|
||||
* Use `Optional` in all the examples in the docs. Original PR [#1574](https://github.com/tiangolo/fastapi/pull/1574) by [@chrisngyn](https://github.com/chrisngyn), [@kx-chen](https://github.com/kx-chen), [@YKo20010](https://github.com/YKo20010). Updated and merged PR [#1644](https://github.com/tiangolo/fastapi/pull/1644).
|
||||
* Update tests and handling of `response_model_by_alias`. PR [#1642](https://github.com/tiangolo/fastapi/pull/1642).
|
||||
* Add translation to Chinese for [Body - Fields - 请求体 - 字段](https://fastapi.tiangolo.com/zh/tutorial/body-fields/). PR [#1569](https://github.com/tiangolo/fastapi/pull/1569) by [@waynerv](https://github.com/waynerv).
|
||||
* Update Chinese translation of main page. PR [#1564](https://github.com/tiangolo/fastapi/pull/1564) by [@waynerv](https://github.com/waynerv).
|
||||
* Add translation to Chinese for [Body - Multiple Parameters - 请求体 - 多个参数](https://fastapi.tiangolo.com/zh/tutorial/body-multiple-params/). PR [#1532](https://github.com/tiangolo/fastapi/pull/1532) by [@waynerv](https://github.com/waynerv).
|
||||
* Add translation to Chinese for [Path Parameters and Numeric Validations - 路径参数和数值校验](https://fastapi.tiangolo.com/zh/tutorial/path-params-numeric-validations/). PR [#1506](https://github.com/tiangolo/fastapi/pull/1506) by [@waynerv](https://github.com/waynerv).
|
||||
* Add GitHub action to auto-label approved PRs (mainly for translations). PR [#1638](https://github.com/tiangolo/fastapi/pull/1638).
|
||||
|
||||
## 0.58.0
|
||||
|
||||
* Deep merge OpenAPI responses to preserve all the additional metadata. PR [#1577](https://github.com/tiangolo/fastapi/pull/1577).
|
||||
* Mention in docs that only main app events are run (not sub-apps). PR [#1554](https://github.com/tiangolo/fastapi/pull/1554) by [@amacfie](https://github.com/amacfie).
|
||||
* Fix body validation error response, do not include body variable when it is not embedded. PR [#1553](https://github.com/tiangolo/fastapi/pull/1553) by [@amacfie](https://github.com/amacfie).
|
||||
* Fix testing OAuth2 security scopes when using dependency overrides. PR [#1549](https://github.com/tiangolo/fastapi/pull/1549) by [@amacfie](https://github.com/amacfie).
|
||||
* Fix Model for JSON Schema keyword `not` as a JSON Schema instead of a list. PR [#1548](https://github.com/tiangolo/fastapi/pull/1548) by [@v-do](https://github.com/v-do).
|
||||
* Add support for OpenAPI `servers`. PR [#1547](https://github.com/tiangolo/fastapi/pull/1547) by [@mikaello](https://github.com/mikaello).
|
||||
|
||||
## 0.57.0
|
||||
|
||||
* Remove broken link from "External Links". PR [#1565](https://github.com/tiangolo/fastapi/pull/1565) by [@victorphoenix3](https://github.com/victorphoenix3).
|
||||
* Update/fix docs for [WebSockets with dependencies](https://fastapi.tiangolo.com/advanced/websockets/#using-depends-and-others). Original PR [#1540](https://github.com/tiangolo/fastapi/pull/1540) by [@ChihSeanHsu](https://github.com/ChihSeanHsu).
|
||||
* Add support for Python's `http.HTTPStatus` in `status_code` parameters. PR [#1534](https://github.com/tiangolo/fastapi/pull/1534) by [@retnikt](https://github.com/retnikt).
|
||||
* When using Pydantic models with `__root__`, use the internal value in `jsonable_encoder`. PR [#1524](https://github.com/tiangolo/fastapi/pull/1524) by [@patrickkwang](https://github.com/patrickkwang).
|
||||
* Update docs for path parameters. PR [#1521](https://github.com/tiangolo/fastapi/pull/1521) by [@yankeexe](https://github.com/yankeexe).
|
||||
* Update docs for first steps, links and rewording. PR [#1518](https://github.com/tiangolo/fastapi/pull/1518) by [@yankeexe](https://github.com/yankeexe).
|
||||
* Enable `showCommonExtensions` in Swagger UI to show additional validations like `maxLength`, etc. PR [#1466](https://github.com/tiangolo/fastapi/pull/1466) by [@TiewKH](https://github.com/TiewKH).
|
||||
* Make `OAuth2PasswordRequestFormStrict` importable directly from `fastapi.security`. PR [#1462](https://github.com/tiangolo/fastapi/pull/1462) by [@RichardHoekstra](https://github.com/RichardHoekstra).
|
||||
* Add docs about [Default response class](https://fastapi.tiangolo.com/advanced/custom-response/#default-response-class). PR [#1455](https://github.com/tiangolo/fastapi/pull/1455) by [@TezRomacH](https://github.com/TezRomacH).
|
||||
* Add note in docs about additional parameters `response_model_exclude_defaults` and `response_model_exclude_none` in [Response Model](https://fastapi.tiangolo.com/tutorial/response-model/#use-the-response_model_exclude_unset-parameter). PR [#1427](https://github.com/tiangolo/fastapi/pull/1427) by [@wshayes](https://github.com/wshayes).
|
||||
* Add note about [PyCharm Pydantic plugin](https://github.com/koxudaxi/pydantic-pycharm-plugin) to docs. PR [#1420](https://github.com/tiangolo/fastapi/pull/1420) by [@koxudaxi](https://github.com/koxudaxi).
|
||||
* Update and clarify testing function name. PR [#1395](https://github.com/tiangolo/fastapi/pull/1395) by [@chenl](https://github.com/chenl).
|
||||
* Fix duplicated headers created by indirect dependencies that use the request directly. PR [#1386](https://github.com/tiangolo/fastapi/pull/1386) by [@obataku](https://github.com/obataku) from tests by [@scottsmith2gmail](https://github.com/scottsmith2gmail).
|
||||
* Upgrade Starlette version to `0.13.4`. PR [#1361](https://github.com/tiangolo/fastapi/pull/1361) by [@rushton](https://github.com/rushton).
|
||||
* Improve error handling and feedback for requests with invalid JSON. PR [#1354](https://github.com/tiangolo/fastapi/pull/1354) by [@aviramha](https://github.com/aviramha).
|
||||
* Add support for declaring metadata for tags in OpenAPI. New docs at [Tutorial - Metadata and Docs URLs - Metadata for tags](https://fastapi.tiangolo.com/tutorial/metadata/#metadata-for-tags). PR [#1348](https://github.com/tiangolo/fastapi/pull/1348) by [@thomas-maschler](https://github.com/thomas-maschler).
|
||||
* Add basic setup for Russian translations. PR [#1566](https://github.com/tiangolo/fastapi/pull/1566).
|
||||
* Remove obsolete Chinese articles after adding official community translations. PR [#1510](https://github.com/tiangolo/fastapi/pull/1510) by [@waynerv](https://github.com/waynerv).
|
||||
* Add `__repr__` for *path operation function* parameter helpers (like `Query`, `Depends`, etc) to simplify debugging. PR [#1560](https://github.com/tiangolo/fastapi/pull/1560) by [@rkbeatss](https://github.com/rkbeatss) and [@victorphoenix3](https://github.com/victorphoenix3).
|
||||
|
||||
## 0.56.1
|
||||
|
||||
* Add link to advanced docs from tutorial. PR [#1512](https://github.com/tiangolo/fastapi/pull/1512) by [@kx-chen](https://github.com/kx-chen).
|
||||
|
||||
@@ -57,7 +57,7 @@ Using `BackgroundTasks` also works with the dependency injection system, you can
|
||||
|
||||
**FastAPI** knows what to do in each case and how to re-use the same object, so that all the background tasks are merged together and are run in the background afterwards:
|
||||
|
||||
```Python hl_lines="11 14 20 23"
|
||||
```Python hl_lines="13 15 22 25"
|
||||
{!../../../docs_src/background_tasks/tutorial002.py!}
|
||||
```
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ The same way you can declare additional validation and metadata in *path operati
|
||||
|
||||
First, you have to import it:
|
||||
|
||||
```Python hl_lines="2"
|
||||
```Python hl_lines="4"
|
||||
{!../../../docs_src/body_fields/tutorial001.py!}
|
||||
```
|
||||
|
||||
@@ -17,7 +17,7 @@ First, you have to import it:
|
||||
|
||||
You can then use `Field` with model attributes:
|
||||
|
||||
```Python hl_lines="9 10"
|
||||
```Python hl_lines="11 12 13 14"
|
||||
{!../../../docs_src/body_fields/tutorial001.py!}
|
||||
```
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ First, of course, you can mix `Path`, `Query` and request body parameter declara
|
||||
|
||||
And you can also declare body parameters as optional, by setting the default to `None`:
|
||||
|
||||
```Python hl_lines="17 18 19"
|
||||
```Python hl_lines="19 20 21"
|
||||
{!../../../docs_src/body_multiple_params/tutorial001.py!}
|
||||
```
|
||||
|
||||
@@ -30,7 +30,7 @@ In the previous example, the *path operations* would expect a JSON body with the
|
||||
|
||||
But you can also declare multiple body parameters, e.g. `item` and `user`:
|
||||
|
||||
```Python hl_lines="20"
|
||||
```Python hl_lines="22"
|
||||
{!../../../docs_src/body_multiple_params/tutorial002.py!}
|
||||
```
|
||||
|
||||
@@ -72,7 +72,7 @@ If you declare it as is, because it is a singular value, **FastAPI** will assume
|
||||
But you can instruct **FastAPI** to treat it as another body key using `Body`:
|
||||
|
||||
|
||||
```Python hl_lines="21"
|
||||
```Python hl_lines="23"
|
||||
{!../../../docs_src/body_multiple_params/tutorial003.py!}
|
||||
```
|
||||
|
||||
@@ -104,12 +104,12 @@ Of course, you can also declare additional query parameters whenever you need, a
|
||||
As, by default, singular values are interpreted as query parameters, you don't have to explicitly add a `Query`, you can just do:
|
||||
|
||||
```Python
|
||||
q: str = None
|
||||
q: Optional[str] = None
|
||||
```
|
||||
|
||||
as in:
|
||||
|
||||
```Python hl_lines="25"
|
||||
```Python hl_lines="27"
|
||||
{!../../../docs_src/body_multiple_params/tutorial004.py!}
|
||||
```
|
||||
|
||||
@@ -131,7 +131,7 @@ item: Item = Body(..., embed=True)
|
||||
|
||||
as in:
|
||||
|
||||
```Python hl_lines="15"
|
||||
```Python hl_lines="17"
|
||||
{!../../../docs_src/body_multiple_params/tutorial005.py!}
|
||||
```
|
||||
|
||||
|
||||
@@ -6,15 +6,15 @@ With **FastAPI**, you can define, validate, document, and use arbitrarily deeply
|
||||
|
||||
You can define an attribute to be a subtype. For example, a Python `list`:
|
||||
|
||||
```Python hl_lines="12"
|
||||
```Python hl_lines="14"
|
||||
{!../../../docs_src/body_nested_models/tutorial001.py!}
|
||||
```
|
||||
|
||||
This will make `tags` be a list of items. Although it doesn't declare the type of each of the items.
|
||||
|
||||
## List fields with subtype
|
||||
## List fields with type parameter
|
||||
|
||||
But Python has a specific way to declare lists with subtypes:
|
||||
But Python has a specific way to declare lists with internal types, or "type parameters":
|
||||
|
||||
### Import typing's `List`
|
||||
|
||||
@@ -24,12 +24,12 @@ First, import `List` from standard Python's `typing` module:
|
||||
{!../../../docs_src/body_nested_models/tutorial002.py!}
|
||||
```
|
||||
|
||||
### Declare a `List` with a subtype
|
||||
### Declare a `List` with a type parameter
|
||||
|
||||
To declare types that have subtypes, like `list`, `dict`, `tuple`:
|
||||
To declare types that have type parameters (internal types), like `list`, `dict`, `tuple`:
|
||||
|
||||
* Import them from the `typing` module
|
||||
* Pass the subtype(s) as "type arguments" using square brackets: `[` and `]`
|
||||
* Pass the internal type(s) as "type parameters" using square brackets: `[` and `]`
|
||||
|
||||
```Python
|
||||
from typing import List
|
||||
@@ -39,7 +39,7 @@ my_list: List[str]
|
||||
|
||||
That's all standard Python syntax for type declarations.
|
||||
|
||||
Use that same standard syntax for model attributes with subtypes.
|
||||
Use that same standard syntax for model attributes with internal types.
|
||||
|
||||
So, in our example, we can make `tags` be specifically a "list of strings":
|
||||
|
||||
@@ -71,7 +71,7 @@ Each attribute of a Pydantic model has a type.
|
||||
|
||||
But that type can itself be another Pydantic model.
|
||||
|
||||
So, you can declare deeply nested JSON `object`s with specific attribute names, types and validations.
|
||||
So, you can declare deeply nested JSON "objects" with specific attribute names, types and validations.
|
||||
|
||||
All that, arbitrarily nested.
|
||||
|
||||
@@ -174,7 +174,7 @@ You can define arbitrarily deeply nested models:
|
||||
```
|
||||
|
||||
!!! info
|
||||
Notice how `Offer` as a list of `Item`s, which in turn have an optional list of `Image`s
|
||||
Notice how `Offer` has a list of `Item`s, which in turn have an optional list of `Image`s
|
||||
|
||||
## Bodies of pure lists
|
||||
|
||||
|
||||
@@ -9,15 +9,17 @@ Your API almost always has to send a **response** body. But clients don't necess
|
||||
To declare a **request** body, you use <a href="https://pydantic-docs.helpmanual.io/" class="external-link" target="_blank">Pydantic</a> models with all their power and benefits.
|
||||
|
||||
!!! info
|
||||
You cannot send a request body using a `GET` operation (HTTP method).
|
||||
To send data, you should use one of: `POST` (the more common), `PUT`, `DELETE` or `PATCH`.
|
||||
|
||||
To send data, you have to use one of: `POST` (the more common), `PUT`, `DELETE` or `PATCH`.
|
||||
Sending a body with a `GET` request has an undefined behavior in the specifications, nevertheless, it is supported by FastAPI, only for very complex/extreme use cases.
|
||||
|
||||
As it is discouraged, the interactive docs with Swagger UI won't show the documentation for the body when using `GET`, and proxies in the middle might not support it.
|
||||
|
||||
## Import Pydantic's `BaseModel`
|
||||
|
||||
First, you need to import `BaseModel` from `pydantic`:
|
||||
|
||||
```Python hl_lines="2"
|
||||
```Python hl_lines="4"
|
||||
{!../../../docs_src/body/tutorial001.py!}
|
||||
```
|
||||
|
||||
@@ -27,7 +29,7 @@ Then you declare your data model as a class that inherits from `BaseModel`.
|
||||
|
||||
Use standard Python types for all the attributes:
|
||||
|
||||
```Python hl_lines="5 6 7 8 9"
|
||||
```Python hl_lines="7 8 9 10 11"
|
||||
{!../../../docs_src/body/tutorial001.py!}
|
||||
```
|
||||
|
||||
@@ -57,7 +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:
|
||||
|
||||
```Python hl_lines="16"
|
||||
```Python hl_lines="18"
|
||||
{!../../../docs_src/body/tutorial001.py!}
|
||||
```
|
||||
|
||||
@@ -108,11 +110,22 @@ But you would get the same editor support with <a href="https://www.jetbrains.co
|
||||
|
||||
<img src="/img/tutorial/body/image05.png">
|
||||
|
||||
!!! tip
|
||||
If you use <a href="https://www.jetbrains.com/pycharm/" class="external-link" target="_blank">PyCharm</a> as your editor, you can use the <a href="https://github.com/koxudaxi/pydantic-pycharm-plugin/" class="external-link" target="_blank">Pydantic PyCharm Plugin</a>.
|
||||
|
||||
It improves editor support for Pydantic models, with:
|
||||
|
||||
* auto-completion
|
||||
* type checks
|
||||
* refactoring
|
||||
* searching
|
||||
* inspections
|
||||
|
||||
## Use the model
|
||||
|
||||
Inside of the function, you can access all the attributes of the model object directly:
|
||||
|
||||
```Python hl_lines="19"
|
||||
```Python hl_lines="21"
|
||||
{!../../../docs_src/body/tutorial002.py!}
|
||||
```
|
||||
|
||||
@@ -122,7 +135,7 @@ You can declare path parameters and body requests 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**.
|
||||
|
||||
```Python hl_lines="15 16"
|
||||
```Python hl_lines="17 18"
|
||||
{!../../../docs_src/body/tutorial003.py!}
|
||||
```
|
||||
|
||||
@@ -132,7 +145,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.
|
||||
|
||||
```Python hl_lines="16"
|
||||
```Python hl_lines="18"
|
||||
{!../../../docs_src/body/tutorial004.py!}
|
||||
```
|
||||
|
||||
@@ -142,6 +155,11 @@ The function parameters will be recognized as follows:
|
||||
* If the parameter is of a **singular type** (like `int`, `float`, `str`, `bool`, etc) it will be interpreted as a **query** parameter.
|
||||
* If the parameter is declared to be of the type of a **Pydantic model**, it will be interpreted as a request **body**.
|
||||
|
||||
!!! note
|
||||
FastAPI will know that the value of `q` is not required because of the default value `= None`.
|
||||
|
||||
The `Optional` in `Optional[str]` is not used by FastAPI, but will allow your editor to give you better support and detect errors.
|
||||
|
||||
## Without Pydantic
|
||||
|
||||
If you don't want to use Pydantic models, you can also use **Body** parameters. See the docs for [Body - Multiple Parameters: Singular values in body](body-multiple-params.md#singular-values-in-body){.internal-link target=_blank}.
|
||||
|
||||
@@ -6,7 +6,7 @@ You can define Cookie parameters the same way you define `Query` and `Path` para
|
||||
|
||||
First import `Cookie`:
|
||||
|
||||
```Python hl_lines="1"
|
||||
```Python hl_lines="3"
|
||||
{!../../../docs_src/cookie_params/tutorial001.py!}
|
||||
```
|
||||
|
||||
@@ -16,7 +16,7 @@ Then declare the cookie parameters using the same structure as with `Path` and `
|
||||
|
||||
The first value is the default value, you can pass all the extra validation or annotation parameters:
|
||||
|
||||
```Python hl_lines="7"
|
||||
```Python hl_lines="9"
|
||||
{!../../../docs_src/cookie_params/tutorial001.py!}
|
||||
```
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ Before diving deeper into the **Dependency Injection** system, let's upgrade the
|
||||
|
||||
In the previous example, we were returning a `dict` from our dependency ("dependable"):
|
||||
|
||||
```Python hl_lines="7"
|
||||
```Python hl_lines="9"
|
||||
{!../../../docs_src/dependencies/tutorial001.py!}
|
||||
```
|
||||
|
||||
@@ -69,21 +69,21 @@ If you pass a "callable" as a dependency in **FastAPI**, it will analyze the par
|
||||
|
||||
That also applies to callables with no parameters at all. The same as it would be for *path operation functions* with no parameters.
|
||||
|
||||
Then, we can change the dependency "dependable" `common_parameters` from above to the class `CommonQueryParameters`:
|
||||
Then, we can change the dependency "dependable" `common_parameters` from above to the class `CommonQueryParams`:
|
||||
|
||||
```Python hl_lines="9 10 11 12 13"
|
||||
```Python hl_lines="11 12 13 14 15"
|
||||
{!../../../docs_src/dependencies/tutorial002.py!}
|
||||
```
|
||||
|
||||
Pay attention to the `__init__` method used to create the instance of the class:
|
||||
|
||||
```Python hl_lines="10"
|
||||
```Python hl_lines="12"
|
||||
{!../../../docs_src/dependencies/tutorial002.py!}
|
||||
```
|
||||
|
||||
...it has the same parameters as our previous `common_parameters`:
|
||||
|
||||
```Python hl_lines="6"
|
||||
```Python hl_lines="8"
|
||||
{!../../../docs_src/dependencies/tutorial001.py!}
|
||||
```
|
||||
|
||||
@@ -101,15 +101,15 @@ In both cases the data will be converted, validated, documented on the OpenAPI s
|
||||
|
||||
Now you can declare your dependency using this class.
|
||||
|
||||
And as when **FastAPI** calls that class the value that will be passed as `commons` to your function will be an "instance" of the class, you can declare that parameter `commons` to be of type of the class, `CommonQueryParams`.
|
||||
|
||||
```Python hl_lines="17"
|
||||
```Python hl_lines="19"
|
||||
{!../../../docs_src/dependencies/tutorial002.py!}
|
||||
```
|
||||
|
||||
**FastAPI** calls the `CommonQueryParams` class. This creates an "instance" of that class and the instance will be passed as the parameter `commons` to your function.
|
||||
|
||||
## Type annotation vs `Depends`
|
||||
|
||||
In the code above, you are declaring `commons` as:
|
||||
Notice how we write `CommonQueryParams` twice in the above code:
|
||||
|
||||
```Python
|
||||
commons: CommonQueryParams = Depends(CommonQueryParams)
|
||||
@@ -143,7 +143,7 @@ commons = Depends(CommonQueryParams)
|
||||
|
||||
..as in:
|
||||
|
||||
```Python hl_lines="17"
|
||||
```Python hl_lines="19"
|
||||
{!../../../docs_src/dependencies/tutorial003.py!}
|
||||
```
|
||||
|
||||
@@ -175,17 +175,17 @@ commons: CommonQueryParams = Depends(CommonQueryParams)
|
||||
commons: CommonQueryParams = Depends()
|
||||
```
|
||||
|
||||
So, you can declare the dependency as the type of the variable, and use `Depends()` as the "default" value (the value after the `=`) for that function's parameter, without any parameter, instead of having to write the full class *again* inside of `Depends(CommonQueryParams)`.
|
||||
You declare the dependency as the type of the parameter, and you use `Depends()` as its "default" value (that after the `=`) for that function's parameter, without any parameter in `Depends()`, instead of having to write the full class *again* inside of `Depends(CommonQueryParams)`.
|
||||
|
||||
So, the same example would look like:
|
||||
The same example would then look like:
|
||||
|
||||
```Python hl_lines="17"
|
||||
```Python hl_lines="19"
|
||||
{!../../../docs_src/dependencies/tutorial004.py!}
|
||||
```
|
||||
|
||||
...and **FastAPI** will know what to do.
|
||||
|
||||
!!! tip
|
||||
If all that seems more confusing than helpful, disregard it, you don't *need* it.
|
||||
|
||||
If that seems more confusing than helpful, disregard it, you don't *need* it.
|
||||
|
||||
It is just a shortcut. Because **FastAPI** cares about helping you minimize code repetition.
|
||||
|
||||
@@ -25,7 +25,7 @@ These dependencies will be executed/solved the same way normal dependencies. But
|
||||
|
||||
Using these `dependencies` in the *path operation decorator* you can make sure they are executed while avoiding editor/tooling errors.
|
||||
|
||||
It might also help avoiding confusion for new developers that see an un-used parameter in your code and could think it's unnecessary.
|
||||
It might also help avoid confusion for new developers that see an unused parameter in your code and could think it's unnecessary.
|
||||
|
||||
## Dependencies errors and return values
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ Let's first focus on the dependency.
|
||||
|
||||
It is just a function that can take all the same parameters that a *path operation function* can take:
|
||||
|
||||
```Python hl_lines="6 7"
|
||||
```Python hl_lines="8 9"
|
||||
{!../../../docs_src/dependencies/tutorial001.py!}
|
||||
```
|
||||
|
||||
@@ -39,7 +39,7 @@ That's it.
|
||||
|
||||
**2 lines**.
|
||||
|
||||
And it has the same shape and structure that all your *path operation functions*.
|
||||
And it has the same shape and structure that all your *path operation functions* have.
|
||||
|
||||
You can think of it as a *path operation function* without the "decorator" (without the `@app.get("/some-path")`).
|
||||
|
||||
@@ -55,7 +55,7 @@ And then it just returns a `dict` containing those values.
|
||||
|
||||
### Import `Depends`
|
||||
|
||||
```Python hl_lines="1"
|
||||
```Python hl_lines="3"
|
||||
{!../../../docs_src/dependencies/tutorial001.py!}
|
||||
```
|
||||
|
||||
@@ -63,7 +63,7 @@ And then it just returns a `dict` containing those values.
|
||||
|
||||
The same way you use `Body`, `Query`, etc. with your *path operation function* parameters, use `Depends` with a new parameter:
|
||||
|
||||
```Python hl_lines="11 16"
|
||||
```Python hl_lines="13 18"
|
||||
{!../../../docs_src/dependencies/tutorial001.py!}
|
||||
```
|
||||
|
||||
@@ -123,10 +123,9 @@ So, the interactive docs will have all the information from these dependencies t
|
||||
|
||||
<img src="/img/tutorial/dependencies/image01.png">
|
||||
|
||||
|
||||
## Simple usage
|
||||
|
||||
If you look at it, *path operation functions* are declared to be used whenever a *path* and *operation* matches, and then **FastAPI** takes care of calling the function with the correct parameters and use the response.
|
||||
If you look at it, *path operation functions* are declared to be used whenever a *path* and *operation* matches, and then **FastAPI** takes care of calling the function with the correct parameters, extracting the data from the request.
|
||||
|
||||
Actually, all (or most) of the web frameworks work in this same way.
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ They can be as **deep** as you need them to be.
|
||||
|
||||
You could create a first dependency ("dependable") like:
|
||||
|
||||
```Python hl_lines="6 7"
|
||||
```Python hl_lines="8 9"
|
||||
{!../../../docs_src/dependencies/tutorial005.py!}
|
||||
```
|
||||
|
||||
@@ -22,7 +22,7 @@ This is quite simple (not very useful), but will help us focus on how the sub-de
|
||||
|
||||
Then you can create another dependency function (a "dependable") that at the same time declares a dependency of its own (so it is a "dependant" too):
|
||||
|
||||
```Python hl_lines="11"
|
||||
```Python hl_lines="13"
|
||||
{!../../../docs_src/dependencies/tutorial005.py!}
|
||||
```
|
||||
|
||||
@@ -31,13 +31,13 @@ Let's focus on the parameters declared:
|
||||
* Even though this function is a dependency ("dependable") itself, it also declares another dependency (it "depends" on something else).
|
||||
* It depends on the `query_extractor`, and assigns the value returned by it to the parameter `q`.
|
||||
* It also declares an optional `last_query` cookie, as a `str`.
|
||||
* Let's imagine that if the user didn't provide any query `q`, we just use the last query used, that we had saved to a cookie before.
|
||||
* If the user didn't provide any query `q`, we use the last query used, which we saved to a cookie before.
|
||||
|
||||
### Use the dependency
|
||||
|
||||
Then we can use the dependency with:
|
||||
|
||||
```Python hl_lines="19"
|
||||
```Python hl_lines="21"
|
||||
{!../../../docs_src/dependencies/tutorial005.py!}
|
||||
```
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ You can use `jsonable_encoder` for that.
|
||||
|
||||
It receives an object, like a Pydantic model, and returns a JSON compatible version:
|
||||
|
||||
```Python hl_lines="4 21"
|
||||
```Python hl_lines="5 22"
|
||||
{!../../../docs_src/encoder/tutorial001.py!}
|
||||
```
|
||||
|
||||
|
||||
@@ -49,17 +49,18 @@ Here are some of the additional data types you can use:
|
||||
* `Decimal`:
|
||||
* Standard Python `Decimal`.
|
||||
* In requests and responses, handled the same as a `float`.
|
||||
* You can check all the valid pydantic data types here: <a href="https://pydantic-docs.helpmanual.io/usage/types" class="external-link" target="_blank">Pydantic data types</a>.
|
||||
|
||||
## Example
|
||||
|
||||
Here's an example *path operation* with parameters using some of the above types.
|
||||
|
||||
```Python hl_lines="1 2 11 12 13 14 15"
|
||||
```Python hl_lines="1 3 12 13 14 15 16"
|
||||
{!../../../docs_src/extra_data_types/tutorial001.py!}
|
||||
```
|
||||
|
||||
Note that the parameters inside the function have their natural data type, and you can, for example, perform normal date manipulations, like:
|
||||
|
||||
```Python hl_lines="17 18"
|
||||
```Python hl_lines="18 19"
|
||||
{!../../../docs_src/extra_data_types/tutorial001.py!}
|
||||
```
|
||||
|
||||
@@ -17,7 +17,7 @@ This is especially the case for user models, because:
|
||||
|
||||
Here's a general idea of how the models could look like with their password fields and the places where they are used:
|
||||
|
||||
```Python hl_lines="7 9 14 20 22 27 28 31 32 33 38 39"
|
||||
```Python hl_lines="9 11 16 22 24 29 30 33 34 35 40 41"
|
||||
{!../../../docs_src/extra_models/tutorial001.py!}
|
||||
```
|
||||
|
||||
@@ -150,7 +150,7 @@ All the data conversion, validation, documentation, etc. will still work as norm
|
||||
|
||||
That way, we can declare just the differences between the models (with plaintext `password`, with `hashed_password` and without password):
|
||||
|
||||
```Python hl_lines="7 13 14 17 18 21 22"
|
||||
```Python hl_lines="9 15 16 19 20 23 24"
|
||||
{!../../../docs_src/extra_models/tutorial002.py!}
|
||||
```
|
||||
|
||||
@@ -162,6 +162,9 @@ It will be defined in OpenAPI with `anyOf`.
|
||||
|
||||
To do that, use the standard Python type hint <a href="https://docs.python.org/3/library/typing.html#typing.Union" class="external-link" target="_blank">`typing.Union`</a>:
|
||||
|
||||
!!! note
|
||||
When defining a <a href="https://pydantic-docs.helpmanual.io/usage/types/#unions" class="external-link" target="_blank">`Union`</a>, include the most specific type first, followed by the less specific type. In the example below, the more specific `PlaneItem` comes before `CarItem` in `Union[PlaneItem, CarItem]`.
|
||||
|
||||
```Python hl_lines="1 14 15 18 19 20 33"
|
||||
{!../../../docs_src/extra_models/tutorial003.py!}
|
||||
```
|
||||
|
||||
@@ -71,13 +71,13 @@ You will see the alternative automatic documentation (provided by <a href="https
|
||||
|
||||
#### "Schema"
|
||||
|
||||
A "schema" is a definition or description of something. Not the code that implements it, but just the abstract description.
|
||||
A "schema" is a definition or description of something. Not the code that implements it, but just an abstract description.
|
||||
|
||||
#### API "schema"
|
||||
|
||||
In this case, OpenAPI is a specification that dictates how to define a schema of your API.
|
||||
In this case, <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank">OpenAPI</a> is a specification that dictates how to define a schema of your API.
|
||||
|
||||
This OpenAPI schema would include your API paths, the possible parameters they take, etc.
|
||||
This schema definition includes your API paths, the possible parameters they take, etc.
|
||||
|
||||
#### Data "schema"
|
||||
|
||||
@@ -91,7 +91,7 @@ OpenAPI defines an API schema for your API. And that schema includes definitions
|
||||
|
||||
#### Check the `openapi.json`
|
||||
|
||||
If you are curious about how the raw OpenAPI schema looks like, it is just an automatically generated JSON with the descriptions of all your API.
|
||||
If you are curious about how the raw OpenAPI schema looks like, FastAPI automatically generates a JSON (schema) with the descriptions of all your API.
|
||||
|
||||
You can see it directly at: <a href="http://127.0.0.1:8000/openapi.json" class="external-link" target="_blank">http://127.0.0.1:8000/openapi.json</a>.
|
||||
|
||||
@@ -120,7 +120,7 @@ It will show a JSON starting with something like:
|
||||
|
||||
#### What is OpenAPI for
|
||||
|
||||
This OpenAPI schema is what powers the 2 interactive documentation systems included.
|
||||
The OpenAPI schema is what powers the two interactive documentation systems included.
|
||||
|
||||
And there are dozens of alternatives, all based on OpenAPI. You could easily add any of those alternatives to your application built with **FastAPI**.
|
||||
|
||||
@@ -139,7 +139,7 @@ You could also use it to generate code automatically, for clients that communica
|
||||
!!! note "Technical Details"
|
||||
`FastAPI` is a class that inherits directly from `Starlette`.
|
||||
|
||||
You can use all the Starlette functionality with `FastAPI` too.
|
||||
You can use all the <a href="https://www.starlette.io/" class="external-link" target="_blank">Starlette</a> functionality with `FastAPI` too.
|
||||
|
||||
### Step 2: create a `FastAPI` "instance"
|
||||
|
||||
@@ -202,7 +202,7 @@ https://example.com/items/foo
|
||||
!!! info
|
||||
A "path" is also commonly called an "endpoint" or a "route".
|
||||
|
||||
Building an API, the "path" is the main way to separate "concerns" and "resources".
|
||||
While building an API, the "path" is the main way to separate "concerns" and "resources".
|
||||
|
||||
#### Operation
|
||||
|
||||
@@ -281,7 +281,7 @@ And the more exotic ones:
|
||||
|
||||
The information here is presented as a guideline, not a requirement.
|
||||
|
||||
For example, when using GraphQL you normally perform all the actions using only `post`.
|
||||
For example, when using GraphQL you normally perform all the actions using only `POST` operations.
|
||||
|
||||
### Step 4: define the **path operation function**
|
||||
|
||||
@@ -297,7 +297,7 @@ This is our "**path operation function**":
|
||||
|
||||
This is a Python function.
|
||||
|
||||
It will be called by **FastAPI** whenever it receives a request to the URL "`/`" using `GET`.
|
||||
It will be called by **FastAPI** whenever it receives a request to the URL "`/`" using a `GET` operation.
|
||||
|
||||
In this case, it is an `async` function.
|
||||
|
||||
|
||||
@@ -209,13 +209,12 @@ Now try sending an invalid item like:
|
||||
|
||||
You will receive a response telling you that the data is invalid containing the received body:
|
||||
|
||||
```JSON hl_lines="13 14 15 16"
|
||||
```JSON hl_lines="12 13 14 15"
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"loc": [
|
||||
"body",
|
||||
"item",
|
||||
"size"
|
||||
],
|
||||
"msg": "value is not a valid integer",
|
||||
|
||||
@@ -6,7 +6,7 @@ You can define Header parameters the same way you define `Query`, `Path` and `Co
|
||||
|
||||
First import `Header`:
|
||||
|
||||
```Python hl_lines="1"
|
||||
```Python hl_lines="3"
|
||||
{!../../../docs_src/header_params/tutorial001.py!}
|
||||
```
|
||||
|
||||
@@ -16,7 +16,7 @@ Then declare the header parameters using the same structure as with `Path`, `Que
|
||||
|
||||
The first value is the default value, you can pass all the extra validation or annotation parameters:
|
||||
|
||||
```Python hl_lines="7"
|
||||
```Python hl_lines="9"
|
||||
{!../../../docs_src/header_params/tutorial001.py!}
|
||||
```
|
||||
|
||||
@@ -44,7 +44,7 @@ So, you can use `user_agent` as you normally would in Python code, instead of ne
|
||||
|
||||
If for some reason you need to disable automatic conversion of underscores to hyphens, set the parameter `convert_underscores` of `Header` to `False`:
|
||||
|
||||
```Python hl_lines="7"
|
||||
```Python hl_lines="10"
|
||||
{!../../../docs_src/header_params/tutorial002.py!}
|
||||
```
|
||||
|
||||
|
||||
@@ -21,6 +21,58 @@ With this configuration, the automatic API docs would look like:
|
||||
|
||||
<img src="/img/tutorial/metadata/image01.png">
|
||||
|
||||
## Metadata for tags
|
||||
|
||||
You can also add additional metadata for the different tags used to group your path operations with the parameter `openapi_tags`.
|
||||
|
||||
It takes a list containing one dictionary for each tag.
|
||||
|
||||
Each dictionary can contain:
|
||||
|
||||
* `name` (**required**): a `str` with the same tag name you use in the `tags` parameter in your *path operations* and `APIRouter`s.
|
||||
* `description`: a `str` with a short description for the tag. It can have Markdown and will be shown in the docs UI.
|
||||
* `externalDocs`: a `dict` describing external documentation with:
|
||||
* `description`: a `str` with a short description for the external docs.
|
||||
* `url` (**required**): a `str` with the URL for the external documentation.
|
||||
|
||||
### Create metadata for tags
|
||||
|
||||
Let's try that in an example with tags for `users` and `items`.
|
||||
|
||||
Create metadata for your tags and pass it to the `openapi_tags` parameter:
|
||||
|
||||
```Python hl_lines="3 4 5 6 7 8 9 10 11 12 13 14 15 16 18"
|
||||
{!../../../docs_src/metadata/tutorial004.py!}
|
||||
```
|
||||
|
||||
Notice that you can use Markdown inside of the descriptions, for example "login" will be shown in bold (**login**) and "fancy" will be shown in italics (_fancy_).
|
||||
|
||||
!!! tip
|
||||
You don't have to add metadata for all the tags that you use.
|
||||
|
||||
### Use your tags
|
||||
|
||||
Use the `tags` parameter with your *path operations* (and `APIRouter`s) to assign them to different tags:
|
||||
|
||||
```Python hl_lines="21 26"
|
||||
{!../../../docs_src/metadata/tutorial004.py!}
|
||||
```
|
||||
|
||||
!!! info
|
||||
Read more about tags in [Path Operation Configuration](../path-operation-configuration/#tags){.internal-link target=_blank}.
|
||||
|
||||
### Check the docs
|
||||
|
||||
Now, if you check the docs, they will show all the additional metadata:
|
||||
|
||||
<img src="/img/tutorial/metadata/image02.png">
|
||||
|
||||
### Order of tags
|
||||
|
||||
The order of each tag metadata dictionary also defines the order shown in the docs UI.
|
||||
|
||||
For example, even though `users` would go after `items` in alphabetical order, it is shown before them, because we added their metadata as the first dictionary in the list.
|
||||
|
||||
## OpenAPI URL
|
||||
|
||||
By default, the OpenAPI schema is served at `/openapi.json`.
|
||||
|
||||
@@ -6,7 +6,7 @@ The same way you can declare more validations and metadata for query parameters
|
||||
|
||||
First, import `Path` from `fastapi`:
|
||||
|
||||
```Python hl_lines="1"
|
||||
```Python hl_lines="3"
|
||||
{!../../../docs_src/path_params_numeric_validations/tutorial001.py!}
|
||||
```
|
||||
|
||||
@@ -16,7 +16,7 @@ You can declare all the same parameters as for `Query`.
|
||||
|
||||
For example, to declare a `title` metadata value for the path parameter `item_id` you can type:
|
||||
|
||||
```Python hl_lines="8"
|
||||
```Python hl_lines="10"
|
||||
{!../../../docs_src/path_params_numeric_validations/tutorial001.py!}
|
||||
```
|
||||
|
||||
|
||||
@@ -85,7 +85,7 @@ And when you open your browser at <a href="http://127.0.0.1:8000/docs" class="ex
|
||||
|
||||
And because the generated schema is from the <a href="https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md" class="external-link" target="_blank">OpenAPI</a> standard, there are many compatible tools.
|
||||
|
||||
Because of this, **FastAPI** itself provides an alternative API documentation (using ReDoc):
|
||||
Because of this, **FastAPI** itself provides an alternative API documentation (using ReDoc), which you can access at <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a>:
|
||||
|
||||
<img src="/img/tutorial/path-params/image02.png">
|
||||
|
||||
@@ -125,7 +125,7 @@ Import `Enum` and create a sub-class that inherits from `str` and from `Enum`.
|
||||
|
||||
By inheriting from `str` the API docs will be able to know that the values must be of type `string` and will be able to render correctly.
|
||||
|
||||
And create class attributes with fixed values, those fixed values will be the available valid values:
|
||||
Then create class attributes with fixed values, which will be the available valid values:
|
||||
|
||||
```Python hl_lines="1 6 7 8 9"
|
||||
{!../../../docs_src/path_params/tutorial005.py!}
|
||||
@@ -147,7 +147,7 @@ Then create a *path parameter* with a type annotation using the enum class you c
|
||||
|
||||
### Check the docs
|
||||
|
||||
Because the available values for the *path parameter* are specified, the interactive docs can show them nicely:
|
||||
Because the available values for the *path parameter* are predefined, the interactive docs can show them nicely:
|
||||
|
||||
<img src="/img/tutorial/path-params/image03.png">
|
||||
|
||||
@@ -167,7 +167,7 @@ You can compare it with the *enumeration member* in your created enum `ModelName
|
||||
|
||||
You can get the actual value (a `str` in this case) using `model_name.value`, or in general, `your_enum_member.value`:
|
||||
|
||||
```Python hl_lines="19"
|
||||
```Python hl_lines="20"
|
||||
{!../../../docs_src/path_params/tutorial005.py!}
|
||||
```
|
||||
|
||||
@@ -178,12 +178,21 @@ You can get the actual value (a `str` in this case) using `model_name.value`, or
|
||||
|
||||
You can return *enum members* from your *path operation*, even nested in a JSON body (e.g. a `dict`).
|
||||
|
||||
They will be converted to their corresponding values before returning them to the client:
|
||||
They will be converted to their corresponding values (strings in this case) before returning them to the client:
|
||||
|
||||
```Python hl_lines="18 20 21"
|
||||
```Python hl_lines="18 21 23"
|
||||
{!../../../docs_src/path_params/tutorial005.py!}
|
||||
```
|
||||
|
||||
In your client you will get a JSON response like:
|
||||
|
||||
```JSON
|
||||
{
|
||||
"model_name": "alexnet",
|
||||
"message": "Deep Learning FTW!"
|
||||
}
|
||||
```
|
||||
|
||||
## Path parameters containing paths
|
||||
|
||||
Let's say you have a *path operation* with a path `/files/{file_path}`.
|
||||
|
||||
@@ -4,11 +4,16 @@
|
||||
|
||||
Let's take this application as example:
|
||||
|
||||
```Python hl_lines="7"
|
||||
```Python hl_lines="9"
|
||||
{!../../../docs_src/query_params_str_validations/tutorial001.py!}
|
||||
```
|
||||
|
||||
The query parameter `q` is of type `str`, and by default is `None`, so it is optional.
|
||||
The query parameter `q` is of type `Optional[str]`, that means that it's of type `str` but could also be `None`, and indeed, the default value is `None`, so FastAPI will know it's not required.
|
||||
|
||||
!!! note
|
||||
FastAPI will know that the value of `q` is not required because of the default value `= None`.
|
||||
|
||||
The `Optional` in `Optional[str]` is not used by FastAPI, but will allow your editor to give you better support and detect errors.
|
||||
|
||||
## Additional validation
|
||||
|
||||
@@ -18,7 +23,7 @@ We are going to enforce that even though `q` is optional, whenever it is provide
|
||||
|
||||
To achieve that, first import `Query` from `fastapi`:
|
||||
|
||||
```Python hl_lines="1"
|
||||
```Python hl_lines="3"
|
||||
{!../../../docs_src/query_params_str_validations/tutorial002.py!}
|
||||
```
|
||||
|
||||
@@ -26,7 +31,7 @@ To achieve that, first import `Query` from `fastapi`:
|
||||
|
||||
And now use it as the default value of your parameter, setting the parameter `max_length` to 50:
|
||||
|
||||
```Python hl_lines="7"
|
||||
```Python hl_lines="9"
|
||||
{!../../../docs_src/query_params_str_validations/tutorial002.py!}
|
||||
```
|
||||
|
||||
@@ -35,18 +40,35 @@ As we have to replace the default value `None` with `Query(None)`, the first par
|
||||
So:
|
||||
|
||||
```Python
|
||||
q: str = Query(None)
|
||||
q: Optional[str] = Query(None)
|
||||
```
|
||||
|
||||
...makes the parameter optional, the same as:
|
||||
|
||||
```Python
|
||||
q: str = None
|
||||
q: Optional[str] = None
|
||||
```
|
||||
|
||||
But it declares it explicitly as being a query parameter.
|
||||
|
||||
And then, we can pass more parameters to `Query`. In this case, the `max_length` parameter that applies to strings:
|
||||
!!! info
|
||||
Have in mind that FastAPI cares about the part:
|
||||
|
||||
```Python
|
||||
= None
|
||||
```
|
||||
|
||||
or the:
|
||||
|
||||
```Python
|
||||
= Query(None)
|
||||
```
|
||||
|
||||
and will use that `None` to detect that the query parameter is not required.
|
||||
|
||||
The `Optional` part is only to allow your editor to provide better support.
|
||||
|
||||
Then, we can pass more parameters to `Query`. In this case, the `max_length` parameter that applies to strings:
|
||||
|
||||
```Python
|
||||
q: str = Query(None, max_length=50)
|
||||
@@ -58,7 +80,7 @@ This will validate the data, show a clear error when the data is not valid, and
|
||||
|
||||
You can also add a parameter `min_length`:
|
||||
|
||||
```Python hl_lines="7"
|
||||
```Python hl_lines="9"
|
||||
{!../../../docs_src/query_params_str_validations/tutorial003.py!}
|
||||
```
|
||||
|
||||
@@ -66,7 +88,7 @@ You can also add a parameter `min_length`:
|
||||
|
||||
You can define a <abbr title="A regular expression, regex or regexp is a sequence of characters that define a search pattern for strings.">regular expression</abbr> that the parameter should match:
|
||||
|
||||
```Python hl_lines="8"
|
||||
```Python hl_lines="10"
|
||||
{!../../../docs_src/query_params_str_validations/tutorial004.py!}
|
||||
```
|
||||
|
||||
@@ -104,13 +126,13 @@ q: str
|
||||
instead of:
|
||||
|
||||
```Python
|
||||
q: str = None
|
||||
q: Optional[str] = None
|
||||
```
|
||||
|
||||
But we are now declaring it with `Query`, for example like:
|
||||
|
||||
```Python
|
||||
q: str = Query(None, min_length=3)
|
||||
q: Optional[str] = Query(None, min_length=3)
|
||||
```
|
||||
|
||||
So, when you need to declare a value as required while using `Query`, you can use `...` as the first argument:
|
||||
@@ -120,7 +142,7 @@ So, when you need to declare a value as required while using `Query`, you can us
|
||||
```
|
||||
|
||||
!!! info
|
||||
If you hadn't seen that `...` before: it is a a special single value, it is <a href="https://docs.python.org/3/library/constants.html#Ellipsis" class="external-link" target="_blank">part of Python and is called "Ellipsis"</a>.
|
||||
If you hadn't seen that `...` before: it is a special single value, it is <a href="https://docs.python.org/3/library/constants.html#Ellipsis" class="external-link" target="_blank">part of Python and is called "Ellipsis"</a>.
|
||||
|
||||
This will let **FastAPI** know that this parameter is required.
|
||||
|
||||
@@ -211,13 +233,13 @@ That information will be included in the generated OpenAPI and used by the docum
|
||||
|
||||
You can add a `title`:
|
||||
|
||||
```Python hl_lines="7"
|
||||
```Python hl_lines="10"
|
||||
{!../../../docs_src/query_params_str_validations/tutorial007.py!}
|
||||
```
|
||||
|
||||
And a `description`:
|
||||
|
||||
```Python hl_lines="11"
|
||||
```Python hl_lines="13"
|
||||
{!../../../docs_src/query_params_str_validations/tutorial008.py!}
|
||||
```
|
||||
|
||||
@@ -239,7 +261,7 @@ But you still need it to be exactly `item-query`...
|
||||
|
||||
Then you can declare an `alias`, and that alias is what will be used to find the parameter value:
|
||||
|
||||
```Python hl_lines="7"
|
||||
```Python hl_lines="9"
|
||||
{!../../../docs_src/query_params_str_validations/tutorial009.py!}
|
||||
```
|
||||
|
||||
@@ -251,7 +273,7 @@ You have to leave it there a while because there are clients using it, but you w
|
||||
|
||||
Then pass the parameter `deprecated=True` to `Query`:
|
||||
|
||||
```Python hl_lines="16"
|
||||
```Python hl_lines="18"
|
||||
{!../../../docs_src/query_params_str_validations/tutorial010.py!}
|
||||
```
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ The parameter values in your function will be:
|
||||
|
||||
The same way, you can declare optional query parameters, by setting their default to `None`:
|
||||
|
||||
```Python hl_lines="7"
|
||||
```Python hl_lines="9"
|
||||
{!../../../docs_src/query_params/tutorial002.py!}
|
||||
```
|
||||
|
||||
@@ -72,11 +72,16 @@ In this case, the function parameter `q` will be optional, and will be `None` by
|
||||
!!! check
|
||||
Also notice that **FastAPI** is smart enough to notice that the path parameter `item_id` is a path parameter and `q` is not, so, it's a query parameter.
|
||||
|
||||
!!! note
|
||||
FastAPI will know that `q` is optional because of the `= None`.
|
||||
|
||||
The `Optional` in `Optional[str]` is not used by FastAPI (FastAPI will only use the `str` part), but the `Optional[str]` will let your editor help you finding errors in your code.
|
||||
|
||||
## Query parameter type conversion
|
||||
|
||||
You can also declare `bool` types, and they will be converted:
|
||||
|
||||
```Python hl_lines="7"
|
||||
```Python hl_lines="9"
|
||||
{!../../../docs_src/query_params/tutorial003.py!}
|
||||
```
|
||||
|
||||
@@ -121,7 +126,7 @@ And you don't have to declare them in any specific order.
|
||||
|
||||
They will be detected by name:
|
||||
|
||||
```Python hl_lines="6 8"
|
||||
```Python hl_lines="8 10"
|
||||
{!../../../docs_src/query_params/tutorial004.py!}
|
||||
```
|
||||
|
||||
@@ -179,7 +184,7 @@ http://127.0.0.1:8000/items/foo-item?needy=sooooneedy
|
||||
|
||||
And of course, you can define some parameters as required, some as having a default value, and some entirely optional:
|
||||
|
||||
```Python hl_lines="7"
|
||||
```Python hl_lines="10"
|
||||
{!../../../docs_src/query_params/tutorial006.py!}
|
||||
```
|
||||
|
||||
@@ -191,36 +196,3 @@ In this case, there are 3 query parameters:
|
||||
|
||||
!!! tip
|
||||
You could also use `Enum`s the same way as with [Path Parameters](path-params.md#predefined-values){.internal-link target=_blank}.
|
||||
|
||||
## Optional type declarations
|
||||
|
||||
!!! warning
|
||||
This might be an advanced use case.
|
||||
|
||||
You might want to skip it.
|
||||
|
||||
If you are using `mypy` it could complain with type declarations like:
|
||||
|
||||
```Python
|
||||
limit: int = None
|
||||
```
|
||||
|
||||
With an error like:
|
||||
|
||||
```
|
||||
Incompatible types in assignment (expression has type "None", variable has type "int")
|
||||
```
|
||||
|
||||
In those cases you can use `Optional` to tell `mypy` that the value could be `None`, like:
|
||||
|
||||
```Python
|
||||
from typing import Optional
|
||||
|
||||
limit: Optional[int] = None
|
||||
```
|
||||
|
||||
In a *path operation* that could look like:
|
||||
|
||||
```Python hl_lines="9"
|
||||
{!../../../docs_src/query_params/tutorial007.py!}
|
||||
```
|
||||
|
||||
@@ -35,13 +35,13 @@ But most importantly:
|
||||
|
||||
Here we are declaring a `UserIn` model, it will contain a plaintext password:
|
||||
|
||||
```Python hl_lines="7 9"
|
||||
```Python hl_lines="9 11"
|
||||
{!../../../docs_src/response_model/tutorial002.py!}
|
||||
```
|
||||
|
||||
And we are using this model to declare our input and the same model to declare our output:
|
||||
|
||||
```Python hl_lines="15 16"
|
||||
```Python hl_lines="17 18"
|
||||
{!../../../docs_src/response_model/tutorial002.py!}
|
||||
```
|
||||
|
||||
@@ -58,19 +58,19 @@ But if we use the same model for another *path operation*, we could be sending o
|
||||
|
||||
We can instead create an input model with the plaintext password and an output model without it:
|
||||
|
||||
```Python hl_lines="7 9 14"
|
||||
```Python hl_lines="9 11 16"
|
||||
{!../../../docs_src/response_model/tutorial003.py!}
|
||||
```
|
||||
|
||||
Here, even though our *path operation function* is returning the same input user that contains the password:
|
||||
|
||||
```Python hl_lines="22"
|
||||
```Python hl_lines="24"
|
||||
{!../../../docs_src/response_model/tutorial003.py!}
|
||||
```
|
||||
|
||||
...we declared the `response_model` to be our model `UserOut`, that doesn't include the password:
|
||||
|
||||
```Python hl_lines="20"
|
||||
```Python hl_lines="22"
|
||||
{!../../../docs_src/response_model/tutorial003.py!}
|
||||
```
|
||||
|
||||
@@ -94,9 +94,9 @@ Your response model could have default values, like:
|
||||
{!../../../docs_src/response_model/tutorial004.py!}
|
||||
```
|
||||
|
||||
* `description: str = None` has a default of `None`.
|
||||
* `description: Optional[str] = None` has a default of `None`.
|
||||
* `tax: float = 10.5` has a default of `10.5`.
|
||||
* `tags: List[str] = []` has a default of an empty list: `[]`.
|
||||
* `tags: List[str] = []` as a default of an empty list: `[]`.
|
||||
|
||||
but you might want to omit them from the result if they were not actually stored.
|
||||
|
||||
@@ -124,6 +124,14 @@ So, if you send a request to that *path operation* for the item with ID `foo`, t
|
||||
!!! info
|
||||
FastAPI uses Pydantic model's `.dict()` with <a href="https://pydantic-docs.helpmanual.io/usage/exporting_models/#modeldict" class="external-link" target="_blank">its `exclude_unset` parameter</a> to achieve this.
|
||||
|
||||
!!! info
|
||||
You can also use:
|
||||
|
||||
* `response_model_exclude_defaults=True`
|
||||
* `response_model_exclude_none=True`
|
||||
|
||||
as described in <a href="https://pydantic-docs.helpmanual.io/usage/exporting_models/#modeldict" class="external-link" target="_blank">the Pydantic docs</a> for `exclude_defaults` and `exclude_none`.
|
||||
|
||||
#### Data with values for fields with defaults
|
||||
|
||||
But if your data has values for the model's fields with default values, like the item with ID `bar`:
|
||||
@@ -175,7 +183,9 @@ This can be used as a quick shortcut if you have only one Pydantic model and wan
|
||||
|
||||
This is because the JSON Schema generated in your app's OpenAPI (and the docs) will still be the one for the complete model, even if you use `response_model_include` or `response_model_exclude` to omit some attributes.
|
||||
|
||||
```Python hl_lines="29 35"
|
||||
This also applies to `response_model_by_alias` that works similarly.
|
||||
|
||||
```Python hl_lines="31 37"
|
||||
{!../../../docs_src/response_model/tutorial005.py!}
|
||||
```
|
||||
|
||||
@@ -188,7 +198,7 @@ This can be used as a quick shortcut if you have only one Pydantic model and wan
|
||||
|
||||
If you forget to use a `set` and use a `list` or `tuple` instead, FastAPI will still convert it to a `set` and it will work correctly:
|
||||
|
||||
```Python hl_lines="29 35"
|
||||
```Python hl_lines="31 37"
|
||||
{!../../../docs_src/response_model/tutorial006.py!}
|
||||
```
|
||||
|
||||
|
||||
@@ -17,6 +17,9 @@ The same way you can specify a response model, you can also declare the HTTP sta
|
||||
|
||||
The `status_code` parameter receives a number with the HTTP status code.
|
||||
|
||||
!!! info
|
||||
`status_code` can alternatively also receive an `IntEnum`, such as Python's <a href="https://docs.python.org/3/library/http.html#http.HTTPStatus" class="external-link" target="_blank">`http.HTTPStatus`</a>.
|
||||
|
||||
It will:
|
||||
|
||||
* Return that status code in the response.
|
||||
|
||||
@@ -10,7 +10,7 @@ There are several ways you can declare extra JSON Schema information.
|
||||
|
||||
You can declare an example for a Pydantic model using `Config` and `schema_extra`, as described in <a href="https://pydantic-docs.helpmanual.io/usage/schema/#schema-customization" class="external-link" target="_blank">Pydantic's docs: Schema customization</a>:
|
||||
|
||||
```Python hl_lines="13 14 15 16 17 18 19 20 21"
|
||||
```Python hl_lines="15 16 17 18 19 20 21 22 23"
|
||||
{!../../../docs_src/schema_extra_example/tutorial001.py!}
|
||||
```
|
||||
|
||||
@@ -20,7 +20,7 @@ That extra info will be added as-is to the output JSON Schema.
|
||||
|
||||
In `Field`, `Path`, `Query`, `Body` and others you'll see later, you can also declare extra info for the JSON Schema by passing any other arbitrary arguments to the function, for example, to add an `example`:
|
||||
|
||||
```Python hl_lines="2 8 9 10 11"
|
||||
```Python hl_lines="4 10 11 12 13"
|
||||
{!../../../docs_src/schema_extra_example/tutorial002.py!}
|
||||
```
|
||||
|
||||
@@ -33,7 +33,7 @@ The same way you can pass extra info to `Field`, you can do the same with `Path`
|
||||
|
||||
For example, you can pass an `example` for a body request to `Body`:
|
||||
|
||||
```Python hl_lines="19 20 21 22 23 24"
|
||||
```Python hl_lines="21 22 23 24 25 26"
|
||||
{!../../../docs_src/schema_extra_example/tutorial003.py!}
|
||||
```
|
||||
|
||||
|
||||
@@ -86,11 +86,11 @@ But in this case, the same **FastAPI** application will handle the API and the a
|
||||
So, let's review it from that simplified point of view:
|
||||
|
||||
* The user types his `username` and `password` in the frontend, and hits `Enter`.
|
||||
* The frontend (running in the user's browser) sends that `username` and `password` to a specific URL in our API.
|
||||
* The API checks that `username` and `password`, and responds with a "token".
|
||||
* The frontend (running in the user's browser) sends that `username` and `password` to a specific URL in our API (declared with `tokenUrl="token"`).
|
||||
* The API checks that `username` and `password`, and responds with a "token" (we haven't implemented any of this yet).
|
||||
* A "token" is just a string with some content that we can use later to verify this user.
|
||||
* Normally, a token is set to expire after some time.
|
||||
* So, the user will have to login again at some point later.
|
||||
* So, the user will have to log in again at some point later.
|
||||
* And if the token is stolen, the risk is less. It is not like a permanent key that will work forever (in most of the cases).
|
||||
* The frontend stores that token temporarily somewhere.
|
||||
* The user clicks in the frontend to go to another section of the frontend web app.
|
||||
@@ -103,7 +103,7 @@ So, let's review it from that simplified point of view:
|
||||
|
||||
**FastAPI** provides several tools, at different levels of abstraction, to implement these security features.
|
||||
|
||||
In this example we are going to use **OAuth2**, with the **Password** flow, using a **Bearer** token.
|
||||
In this example we are going to use **OAuth2**, with the **Password** flow, using a **Bearer** token. We do that using the `OAuth2PasswordBearer` class.
|
||||
|
||||
!!! info
|
||||
A "bearer" token is not the only option.
|
||||
@@ -114,13 +114,22 @@ In this example we are going to use **OAuth2**, with the **Password** flow, usin
|
||||
|
||||
In that case, **FastAPI** also provides you with the tools to build it.
|
||||
|
||||
`OAuth2PasswordBearer` is a class that we create passing a parameter of the URL in where the client (the frontend running in the user's browser) can use to send the `username` and `password` and get a token.
|
||||
When we create an instance of the `OAuth2PasswordBearer` class we pass in the `tokenUrl` parameter. This parameter contains the URL that the client (the frontend running in the user's browser) will use to send the `username` and `password` in order to get a token.
|
||||
|
||||
```Python hl_lines="6"
|
||||
{!../../../docs_src/security/tutorial001.py!}
|
||||
```
|
||||
|
||||
It doesn't create that endpoint / *path operation*, but declares that that URL is the one that the client should use to get the token. That information is used in OpenAPI, and then in the interactive API documentation systems.
|
||||
!!! tip
|
||||
here `tokenUrl="token"` refers to a relative URL `token` that we haven't created yet. As it's a relative URL, it's equivalent to `./token`.
|
||||
|
||||
Because we are using a relative URL, if your API was located at `https://example.com/`, then it would refer to `https://example.com/token`. But if your API was located at `https://example.com/api/v1/`, then it would refer to `https://example.com/api/v1/token`.
|
||||
|
||||
Using a relative URL is important to make sure your application keeps working even in an advanced use case like [Behind a Proxy](../../advanced/behind-a-proxy.md){.internal-link target=_blank}.
|
||||
|
||||
This parameter doesn't create that endpoint / *path operation*, but declares that the URL `/token` will be the one that the client should use to get the token. That information is used in OpenAPI, and then in the interactive API documentation systems.
|
||||
|
||||
We will soon also create the actual path operation.
|
||||
|
||||
!!! info
|
||||
If you are a very strict "Pythonista" you might dislike the style of the parameter name `tokenUrl` instead of `token_url`.
|
||||
|
||||
@@ -20,26 +20,35 @@ It is not encrypted, so, anyone could recover the information from the contents.
|
||||
|
||||
But it's signed. So, when you receive a token that you emitted, you can verify that you actually emitted it.
|
||||
|
||||
That way, you can create a token with an expiration of, let's say, 1 week. And then when the user comes back the next day with the token, you know she/he is still signed into your system.
|
||||
That way, you can create a token with an expiration of, let's say, 1 week. And then when the user comes back the next day with the token, you know she/he is still logged in to your system.
|
||||
|
||||
And after a week, the token will be expired and the user will not be authorized and will have to sign in again to get a new token. And if the user (or a third party) tried to modify the token to change the expiration, you would be able to discover it, because the signatures would not match.
|
||||
After a week, the token will be expired and the user will not be authorized and will have to sign in again to get a new token. And if the user (or a third party) tried to modify the token to change the expiration, you would be able to discover it, because the signatures would not match.
|
||||
|
||||
If you want to play with JWT tokens and see how they work, check <a href="https://jwt.io/" class="external-link" target="_blank">https://jwt.io</a>.
|
||||
|
||||
## Install `PyJWT`
|
||||
## Install `python-jose`
|
||||
|
||||
We need to install `PyJWT` to generate and verify the JWT tokens in Python:
|
||||
We need to install `python-jose` to generate and verify the JWT tokens in Python:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ pip install pyjwt
|
||||
$ pip install python-jose[cryptography]
|
||||
|
||||
---> 100%
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
<a href="https://github.com/mpdavis/python-jose" class="external-link" target="_blank">Python-jose</a> requires a cryptographic backend as an extra.
|
||||
|
||||
Here we are using the recommended one: <a href="http://cryptography.io/" class="external-link" target="_blank">pyca/cryptography</a>.
|
||||
|
||||
!!! tip
|
||||
This tutorial previously used <a href="https://pyjwt.readthedocs.io/" class="external-link" target="_blank">PyJWT</a>.
|
||||
|
||||
But it was updated to use Python-jose instead as it provides all the features from PyJWT plus some extras that you might need later when building integrations with other tools.
|
||||
|
||||
## Password hashing
|
||||
|
||||
"Hashing" means converting some content (a password in this case) into a sequence of bytes (just a string) that looks like gibberish.
|
||||
@@ -88,7 +97,7 @@ Import the tools we need from `passlib`.
|
||||
Create a PassLib "context". This is what will be used to hash and verify passwords.
|
||||
|
||||
!!! tip
|
||||
The PassLib context also has functionality to use different hashing algorithms, including deprecate old ones only to allow verifying them, etc.
|
||||
The PassLib context also has functionality to use different hashing algorithms, including deprecated old ones only to allow verifying them, etc.
|
||||
|
||||
For example, you could use it to read and verify passwords generated by another system (like Django) but hash any new passwords with a different algorithm like Bcrypt.
|
||||
|
||||
@@ -135,7 +144,7 @@ Define a Pydantic Model that will be used in the token endpoint for the response
|
||||
|
||||
Create a utility function to generate a new access token.
|
||||
|
||||
```Python hl_lines="3 6 12 13 14 28 29 30 78 79 80 81 82 83 84 85 86"
|
||||
```Python hl_lines="6 12 13 14 28 29 30 78 79 80 81 82 83 84 85 86"
|
||||
{!../../../docs_src/security/tutorial004.py!}
|
||||
```
|
||||
|
||||
@@ -167,13 +176,13 @@ The JWT specification says that there's a key `sub`, with the subject of the tok
|
||||
|
||||
It's optional to use it, but that's where you would put the user's identification, so we are using it here.
|
||||
|
||||
JWT might be used for other things apart from identifying a user and allowing him to perform operations directly on your API.
|
||||
JWT might be used for other things apart from identifying a user and allowing them to perform operations directly on your API.
|
||||
|
||||
For example, you could identify a "car" or a "blog post".
|
||||
|
||||
Then you could add permissions about that entity, like "drive" (for the car) or "edit" (for the blog).
|
||||
|
||||
And then, you could give that JWT token to a user (or bot), and he could use it to perform those actions (drive the car, or edit the blog post) without even needing to have an account, just with the JWT token your API generated for that.
|
||||
And then, you could give that JWT token to a user (or bot), and they could use it to perform those actions (drive the car, or edit the blog post) without even needing to have an account, just with the JWT token your API generated for that.
|
||||
|
||||
Using these ideas, JWT can be used for way more sophisticated scenarios.
|
||||
|
||||
@@ -247,7 +256,7 @@ Many packages that simplify it a lot have to make many compromises with the data
|
||||
|
||||
It gives you all the flexibility to choose the ones that fit your project the best.
|
||||
|
||||
And you can use directly many well maintained and widely used packages like `passlib` and `pyjwt`, because **FastAPI** doesn't require any complex mechanisms to integrate external packages.
|
||||
And you can use directly many well maintained and widely used packages like `passlib` and `python-jose`, because **FastAPI** doesn't require any complex mechanisms to integrate external packages.
|
||||
|
||||
But it provides you the tools to simplify the process as much as possible without compromising flexibility, robustness, or security.
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ They are normally used to declare specific security permissions, for example:
|
||||
In OAuth2 a "scope" is just a string that declares a specific permission required.
|
||||
|
||||
It doesn't matter if it has other characters like `:` or if it is a URL.
|
||||
|
||||
|
||||
Those details are implementation specific.
|
||||
|
||||
For OAuth2 they are just strings.
|
||||
@@ -47,9 +47,9 @@ Now let's use the utilities provided by **FastAPI** to handle this.
|
||||
|
||||
### `OAuth2PasswordRequestForm`
|
||||
|
||||
First, import `OAuth2PasswordRequestForm`, and use it as a dependency with `Depends` for the path `/token`:
|
||||
First, import `OAuth2PasswordRequestForm`, and use it as a dependency with `Depends` in the *path operation* for `/token`:
|
||||
|
||||
```Python hl_lines="2 74"
|
||||
```Python hl_lines="4 76"
|
||||
{!../../../docs_src/security/tutorial003.py!}
|
||||
```
|
||||
|
||||
@@ -90,7 +90,7 @@ If there is no such user, we return an error saying "incorrect username or passw
|
||||
|
||||
For the error, we use the exception `HTTPException`:
|
||||
|
||||
```Python hl_lines="1 75 76 77"
|
||||
```Python hl_lines="3 77 78 79"
|
||||
{!../../../docs_src/security/tutorial003.py!}
|
||||
```
|
||||
|
||||
@@ -118,7 +118,7 @@ If your database is stolen, the thief won't have your users' plaintext passwords
|
||||
|
||||
So, the thief won't be able to try to use those same passwords in another system (as many users use the same password everywhere, this would be dangerous).
|
||||
|
||||
```Python hl_lines="78 79 80 81"
|
||||
```Python hl_lines="80 81 82 83"
|
||||
{!../../../docs_src/security/tutorial003.py!}
|
||||
```
|
||||
|
||||
@@ -156,7 +156,7 @@ For this simple example, we are going to just be completely insecure and return
|
||||
|
||||
But for now, let's focus on the specific details we need.
|
||||
|
||||
```Python hl_lines="83"
|
||||
```Python hl_lines="85"
|
||||
{!../../../docs_src/security/tutorial003.py!}
|
||||
```
|
||||
|
||||
@@ -166,7 +166,7 @@ For this simple example, we are going to just be completely insecure and return
|
||||
This is something that you have to do yourself in your code, and make sure you use those JSON keys.
|
||||
|
||||
It's almost the only thing that you have to remember to do correctly yourself, to be compliant with the specifications.
|
||||
|
||||
|
||||
For the rest, **FastAPI** handles it for you.
|
||||
|
||||
## Update the dependencies
|
||||
@@ -177,11 +177,11 @@ We want to get the `current_user` *only* if this user is active.
|
||||
|
||||
So, we create an additional dependency `get_current_active_user` that in turn uses `get_current_user` as a dependency.
|
||||
|
||||
Both of these dependencies will just return an HTTP error if the user doesn't exists, or if is inactive.
|
||||
Both of these dependencies will just return an HTTP error if the user doesn't exist, or if is inactive.
|
||||
|
||||
So, in our endpoint, we will only get a user if the user exists, was correctly authenticated, and is active:
|
||||
|
||||
```Python hl_lines="56 57 58 59 60 61 62 63 64 65 67 68 69 70 88"
|
||||
```Python hl_lines="58 59 60 61 62 63 64 65 66 67 69 70 71 72 90"
|
||||
{!../../../docs_src/security/tutorial003.py!}
|
||||
```
|
||||
|
||||
|
||||
@@ -539,6 +539,9 @@ def read_user(user_id: int, db: Session = Depends(get_db)):
|
||||
...
|
||||
```
|
||||
|
||||
!!! info
|
||||
If you need to connect to your relational database asynchronously, see [Async SQL (Relational) Databases](../advanced/async-sql-databases.md){.internal-link target=_blank}.
|
||||
|
||||
!!! note "Very Technical Details"
|
||||
If you are curious and have a deep technical knowledge, you can check the very technical details of how this `async def` vs `def` is handled in the [Async](../async.md#very-technical-details){.internal-link target=_blank} docs.
|
||||
|
||||
|
||||
@@ -34,6 +34,9 @@ Write simple `assert` statements with the standard Python expressions that you n
|
||||
|
||||
**FastAPI** provides the same `starlette.testclient` as `fastapi.testclient` just as a convenience for you, the developer. But it comes directly from Starlette.
|
||||
|
||||
!!! tip
|
||||
If you want to call `async` functions in your tests apart from sending requests to your FastAPI application (e.g. asynchronous database functions), have a look at the [Async Tests](../advanced/async-tests.md){.internal-link target=_blank} in the advanced tutorial.
|
||||
|
||||
## Separating tests
|
||||
|
||||
In a real application, you probably would have your tests in a different file.
|
||||
|
||||
@@ -4,6 +4,7 @@ site_url: https://fastapi.tiangolo.com/
|
||||
theme:
|
||||
name: material
|
||||
palette:
|
||||
scheme: preference
|
||||
primary: teal
|
||||
accent: amber
|
||||
icon:
|
||||
@@ -17,6 +18,10 @@ edit_uri: ''
|
||||
google_analytics:
|
||||
- UA-133183413-1
|
||||
- auto
|
||||
plugins:
|
||||
- search
|
||||
- markdownextradata:
|
||||
data: data
|
||||
nav:
|
||||
- FastAPI: index.md
|
||||
- Languages:
|
||||
@@ -24,6 +29,8 @@ nav:
|
||||
- es: /es/
|
||||
- it: /it/
|
||||
- pt: /pt/
|
||||
- ru: /ru/
|
||||
- uk: /uk/
|
||||
- zh: /zh/
|
||||
- features.md
|
||||
- python-types.md
|
||||
@@ -104,6 +111,7 @@ nav:
|
||||
- advanced/testing-events.md
|
||||
- advanced/testing-dependencies.md
|
||||
- advanced/testing-database.md
|
||||
- advanced/async-tests.md
|
||||
- advanced/settings.md
|
||||
- advanced/conditional-openapi.md
|
||||
- advanced/extending-openapi.md
|
||||
|
||||
@@ -5,14 +5,14 @@
|
||||
<em>FastAPI framework, alto desempeño, fácil de aprender, rápido de programar, listo para producción</em>
|
||||
</p>
|
||||
<p align="center">
|
||||
<a href="https://travis-ci.com/tiangolo/fastapi" target="_blank">
|
||||
<img src="https://travis-ci.com/tiangolo/fastapi.svg?branch=master" alt="Build Status">
|
||||
<a href="https://github.com/tiangolo/fastapi/actions?query=workflow%3ATest" target="_blank">
|
||||
<img src="https://github.com/tiangolo/fastapi/workflows/Test/badge.svg" alt="Test">
|
||||
</a>
|
||||
<a href="https://codecov.io/gh/tiangolo/fastapi" target="_blank">
|
||||
<img src="https://img.shields.io/codecov/c/github/tiangolo/fastapi" alt="Coverage">
|
||||
<img src="https://img.shields.io/codecov/c/github/tiangolo/fastapi?color=%2334D058" alt="Coverage">
|
||||
</a>
|
||||
<a href="https://pypi.org/project/fastapi" target="_blank">
|
||||
<img src="https://badge.fury.io/py/fastapi.svg" alt="Package version">
|
||||
<img src="https://img.shields.io/pypi/v/fastapi?color=%2334D058&label=pypi%20package" alt="Package version">
|
||||
</a>
|
||||
<a href="https://gitter.im/tiangolo/fastapi?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge" target="_blank">
|
||||
<img src="https://badges.gitter.im/tiangolo/fastapi.svg" alt="Join the chat at https://gitter.im/tiangolo/fastapi">
|
||||
@@ -131,6 +131,7 @@ $ pip install uvicorn
|
||||
|
||||
```Python
|
||||
from fastapi import FastAPI
|
||||
from typing import Optional
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
@@ -141,7 +142,7 @@ def read_root():
|
||||
|
||||
|
||||
@app.get("/items/{item_id}")
|
||||
def read_item(item_id: int, q: str = None):
|
||||
def read_item(item_id: int, q: Optional[str] = None):
|
||||
return {"item_id": item_id, "q": q}
|
||||
```
|
||||
|
||||
@@ -152,6 +153,7 @@ Si tu código usa `async` / `await`, usa `async def`:
|
||||
|
||||
```Python hl_lines="7 12"
|
||||
from fastapi import FastAPI
|
||||
from typing import Optional
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
@@ -162,7 +164,7 @@ async def read_root():
|
||||
|
||||
|
||||
@app.get("/items/{item_id}")
|
||||
async def read_item(item_id: int, q: str = None):
|
||||
async def read_item(item_id: int, q: Optional[str] = None):
|
||||
return {"item_id": item_id, "q": q}
|
||||
```
|
||||
|
||||
@@ -243,6 +245,7 @@ Declara el body usando las declaraciones de tipo estándares de Python gracias a
|
||||
```Python hl_lines="2 7 8 9 10 23 24 25"
|
||||
from fastapi import FastAPI
|
||||
from pydantic import BaseModel
|
||||
from typing import Optional
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
@@ -250,7 +253,7 @@ app = FastAPI()
|
||||
class Item(BaseModel):
|
||||
name: str
|
||||
price: float
|
||||
is_offer: bool = None
|
||||
is_offer: Optional[bool] = None
|
||||
|
||||
|
||||
@app.get("/")
|
||||
@@ -259,7 +262,7 @@ def read_root():
|
||||
|
||||
|
||||
@app.get("/items/{item_id}")
|
||||
def read_item(item_id: int, q: str = None):
|
||||
def read_item(item_id: int, q: Optional[str] = None):
|
||||
return {"item_id": item_id, "q": q}
|
||||
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ site_url: https://fastapi.tiangolo.com/es/
|
||||
theme:
|
||||
name: material
|
||||
palette:
|
||||
scheme: preference
|
||||
primary: teal
|
||||
accent: amber
|
||||
icon:
|
||||
@@ -17,6 +18,10 @@ edit_uri: ''
|
||||
google_analytics:
|
||||
- UA-133183413-1
|
||||
- auto
|
||||
plugins:
|
||||
- search
|
||||
- markdownextradata:
|
||||
data: data
|
||||
nav:
|
||||
- FastAPI: index.md
|
||||
- Languages:
|
||||
@@ -24,6 +29,8 @@ nav:
|
||||
- es: /es/
|
||||
- it: /it/
|
||||
- pt: /pt/
|
||||
- ru: /ru/
|
||||
- uk: /uk/
|
||||
- zh: /zh/
|
||||
- features.md
|
||||
- python-types.md
|
||||
|
||||
@@ -136,6 +136,7 @@ $ pip install uvicorn
|
||||
|
||||
```Python
|
||||
from fastapi import FastAPI
|
||||
from typing import Optional
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
@@ -146,7 +147,7 @@ def read_root():
|
||||
|
||||
|
||||
@app.get("/items/{item_id}")
|
||||
def read_item(item_id: int, q: str = None):
|
||||
def read_item(item_id: int, q: str = Optional[None]):
|
||||
return {"item_id": item_id, "q": q}
|
||||
```
|
||||
|
||||
@@ -157,6 +158,7 @@ If your code uses `async` / `await`, use `async def`:
|
||||
|
||||
```Python hl_lines="7 12"
|
||||
from fastapi import FastAPI
|
||||
from typing import Optional
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
@@ -167,7 +169,7 @@ async def read_root():
|
||||
|
||||
|
||||
@app.get("/items/{item_id}")
|
||||
async def read_item(item_id: int, q: str = None):
|
||||
async def read_item(item_id: int, q: Optional[str] = None):
|
||||
return {"item_id": item_id, "q": q}
|
||||
```
|
||||
|
||||
@@ -248,6 +250,7 @@ Declare the body using standard Python types, thanks to Pydantic.
|
||||
```Python hl_lines="2 7 8 9 10 23 24 25"
|
||||
from fastapi import FastAPI
|
||||
from pydantic import BaseModel
|
||||
from typing import Optional
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
@@ -255,7 +258,7 @@ app = FastAPI()
|
||||
class Item(BaseModel):
|
||||
name: str
|
||||
price: float
|
||||
is_offer: bool = None
|
||||
is_offer: bool = Optional[None]
|
||||
|
||||
|
||||
@app.get("/")
|
||||
@@ -264,7 +267,7 @@ def read_root():
|
||||
|
||||
|
||||
@app.get("/items/{item_id}")
|
||||
def read_item(item_id: int, q: str = None):
|
||||
def read_item(item_id: int, q: Optional[str] = None):
|
||||
return {"item_id": item_id, "q": q}
|
||||
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ site_url: https://fastapi.tiangolo.com/it/
|
||||
theme:
|
||||
name: material
|
||||
palette:
|
||||
scheme: preference
|
||||
primary: teal
|
||||
accent: amber
|
||||
icon:
|
||||
@@ -17,6 +18,10 @@ edit_uri: ''
|
||||
google_analytics:
|
||||
- UA-133183413-1
|
||||
- auto
|
||||
plugins:
|
||||
- search
|
||||
- markdownextradata:
|
||||
data: data
|
||||
nav:
|
||||
- FastAPI: index.md
|
||||
- Languages:
|
||||
@@ -24,6 +29,8 @@ nav:
|
||||
- es: /es/
|
||||
- it: /it/
|
||||
- pt: /pt/
|
||||
- ru: /ru/
|
||||
- uk: /uk/
|
||||
- zh: /zh/
|
||||
markdown_extensions:
|
||||
- toc:
|
||||
|
||||
@@ -5,14 +5,14 @@
|
||||
<em>Framework FastAPI, alta performance, fácil de aprender, fácil de codar, pronto para produção</em>
|
||||
</p>
|
||||
<p align="center">
|
||||
<a href="https://travis-ci.com/tiangolo/fastapi" target="_blank">
|
||||
<img src="https://travis-ci.com/tiangolo/fastapi.svg?branch=master" alt="Build Status">
|
||||
<a href="https://github.com/tiangolo/fastapi/actions?query=workflow%3ATest" target="_blank">
|
||||
<img src="https://github.com/tiangolo/fastapi/workflows/Test/badge.svg" alt="Test">
|
||||
</a>
|
||||
<a href="https://codecov.io/gh/tiangolo/fastapi" target="_blank">
|
||||
<img src="https://img.shields.io/codecov/c/github/tiangolo/fastapi" alt="Coverage">
|
||||
<img src="https://img.shields.io/codecov/c/github/tiangolo/fastapi?color=%2334D058" alt="Coverage">
|
||||
</a>
|
||||
<a href="https://pypi.org/project/fastapi" target="_blank">
|
||||
<img src="https://badge.fury.io/py/fastapi.svg" alt="Package version">
|
||||
<img src="https://img.shields.io/pypi/v/fastapi?color=%2334D058&label=pypi%20package" alt="Package version">
|
||||
</a>
|
||||
<a href="https://gitter.im/tiangolo/fastapi?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge" target="_blank">
|
||||
<img src="https://badges.gitter.im/tiangolo/fastapi.svg" alt="Join the chat at https://gitter.im/tiangolo/fastapi">
|
||||
@@ -33,7 +33,7 @@ Os recursos chave são:
|
||||
|
||||
* **Rápido**: alta performance, equivalente a **NodeJS** e **Go** (graças ao Starlette e Pydantic). [Um dos frameworks mais rápidos disponíveis](#performance).
|
||||
* **Rápido para codar**: Aumenta a velocidade para desenvolver recursos entre 200% a 300%. *
|
||||
* **Poucos bugs**: Reduz cerca de 40% de erros iduzidos por humanos (desenvolvedores). *
|
||||
* **Poucos bugs**: Reduz cerca de 40% de erros induzidos por humanos (desenvolvedores). *
|
||||
* **Intuitivo**: Grande suporte a _IDEs_. <abbr title="também conhecido como _auto-complete_, _autocompletion_, _IntelliSense_">_Auto-Complete_</abbr> em todos os lugares. Menos tempo debugando.
|
||||
* **Fácil**: Projetado para ser fácil de aprender e usar. Menos tempo lendo documentação.
|
||||
* **Enxuto**: Minimize duplicação de código. Múltiplos recursos para cada declaração de parâmetro. Menos bugs.
|
||||
@@ -124,6 +124,8 @@ $ pip install uvicorn
|
||||
* Crie um arquivo `main.py` com:
|
||||
|
||||
```Python
|
||||
from typing import Optional
|
||||
|
||||
from fastapi import FastAPI
|
||||
|
||||
app = FastAPI()
|
||||
@@ -135,7 +137,7 @@ def read_root():
|
||||
|
||||
|
||||
@app.get("/items/{item_id}")
|
||||
def read_item(item_id: int, q: str = None):
|
||||
def read_item(item_id: int, q: Optional[str] = None):
|
||||
return {"item_id": item_id, "q": q}
|
||||
```
|
||||
|
||||
@@ -144,7 +146,9 @@ def read_item(item_id: int, q: str = None):
|
||||
|
||||
Se seu código utiliza `async` / `await`, use `async def`:
|
||||
|
||||
```Python hl_lines="7 12"
|
||||
```Python hl_lines="9 14"
|
||||
from typing import Optional
|
||||
|
||||
from fastapi import FastAPI
|
||||
|
||||
app = FastAPI()
|
||||
@@ -156,7 +160,7 @@ async def read_root():
|
||||
|
||||
|
||||
@app.get("/items/{item_id}")
|
||||
async def read_item(item_id: int, q: str = None):
|
||||
async def read_item(item_id: int, q: Optional[str] = None):
|
||||
return {"item_id": item_id, "q": q}
|
||||
```
|
||||
|
||||
@@ -234,7 +238,7 @@ Agora modifique o arquivo `main.py` para receber um corpo para uma requisição
|
||||
|
||||
Declare o corpo utilizando tipos padrão Python, graças ao Pydantic.
|
||||
|
||||
```Python hl_lines="2 7 8 9 10 23 24 25"
|
||||
```Python hl_lines="4 9 10 11 12 25 26 27"
|
||||
from fastapi import FastAPI
|
||||
from pydantic import BaseModel
|
||||
|
||||
@@ -244,7 +248,7 @@ app = FastAPI()
|
||||
class Item(BaseModel):
|
||||
name: str
|
||||
price: float
|
||||
is_offer: bool = None
|
||||
is_offer: Optional[bool] = None
|
||||
|
||||
|
||||
@app.get("/")
|
||||
@@ -253,7 +257,7 @@ def read_root():
|
||||
|
||||
|
||||
@app.get("/items/{item_id}")
|
||||
def read_item(item_id: int, q: str = None):
|
||||
def read_item(item_id: int, q: Optional[str] = None):
|
||||
return {"item_id": item_id, "q": q}
|
||||
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ site_url: https://fastapi.tiangolo.com/pt/
|
||||
theme:
|
||||
name: material
|
||||
palette:
|
||||
scheme: preference
|
||||
primary: teal
|
||||
accent: amber
|
||||
icon:
|
||||
@@ -17,6 +18,10 @@ edit_uri: ''
|
||||
google_analytics:
|
||||
- UA-133183413-1
|
||||
- auto
|
||||
plugins:
|
||||
- search
|
||||
- markdownextradata:
|
||||
data: data
|
||||
nav:
|
||||
- FastAPI: index.md
|
||||
- Languages:
|
||||
@@ -24,6 +29,8 @@ nav:
|
||||
- es: /es/
|
||||
- it: /it/
|
||||
- pt: /pt/
|
||||
- ru: /ru/
|
||||
- uk: /uk/
|
||||
- zh: /zh/
|
||||
- features.md
|
||||
- Tutorial - Guia de Usuário:
|
||||
|
||||
453
docs/ru/docs/index.md
Normal file
@@ -0,0 +1,453 @@
|
||||
|
||||
{!../../../docs/missing-translation.md!}
|
||||
|
||||
|
||||
<p align="center">
|
||||
<a href="https://fastapi.tiangolo.com"><img src="https://fastapi.tiangolo.com/img/logo-margin/logo-teal.png" alt="FastAPI"></a>
|
||||
</p>
|
||||
<p align="center">
|
||||
<em>FastAPI framework, high performance, easy to learn, fast to code, ready for production</em>
|
||||
</p>
|
||||
<p align="center">
|
||||
<a href="https://travis-ci.com/tiangolo/fastapi" target="_blank">
|
||||
<img src="https://travis-ci.com/tiangolo/fastapi.svg?branch=master" alt="Build Status">
|
||||
</a>
|
||||
<a href="https://codecov.io/gh/tiangolo/fastapi" target="_blank">
|
||||
<img src="https://img.shields.io/codecov/c/github/tiangolo/fastapi" alt="Coverage">
|
||||
</a>
|
||||
<a href="https://pypi.org/project/fastapi" target="_blank">
|
||||
<img src="https://badge.fury.io/py/fastapi.svg" alt="Package version">
|
||||
</a>
|
||||
<a href="https://gitter.im/tiangolo/fastapi?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge" target="_blank">
|
||||
<img src="https://badges.gitter.im/tiangolo/fastapi.svg" alt="Join the chat at https://gitter.im/tiangolo/fastapi">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
---
|
||||
|
||||
**Documentation**: <a href="https://fastapi.tiangolo.com" target="_blank">https://fastapi.tiangolo.com</a>
|
||||
|
||||
**Source Code**: <a href="https://github.com/tiangolo/fastapi" target="_blank">https://github.com/tiangolo/fastapi</a>
|
||||
|
||||
---
|
||||
|
||||
FastAPI is a modern, fast (high-performance), web framework for building APIs with Python 3.6+ based on standard Python type hints.
|
||||
|
||||
The key features are:
|
||||
|
||||
* **Fast**: Very high performance, on par with **NodeJS** and **Go** (thanks to Starlette and Pydantic). [One of the fastest Python frameworks available](#performance).
|
||||
|
||||
* **Fast to code**: Increase the speed to develop features by about 200% to 300%. *
|
||||
* **Fewer bugs**: Reduce about 40% of human (developer) induced errors. *
|
||||
* **Intuitive**: Great editor support. <abbr title="also known as auto-complete, autocompletion, IntelliSense">Completion</abbr> everywhere. Less time debugging.
|
||||
* **Easy**: Designed to be easy to use and learn. Less time reading docs.
|
||||
* **Short**: Minimize code duplication. Multiple features from each parameter declaration. Fewer bugs.
|
||||
* **Robust**: Get production-ready code. With automatic interactive documentation.
|
||||
* **Standards-based**: Based on (and fully compatible with) the open standards for APIs: <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank">OpenAPI</a> (previously known as Swagger) and <a href="http://json-schema.org/" class="external-link" target="_blank">JSON Schema</a>.
|
||||
|
||||
<small>* estimation based on tests on an internal development team, building production applications.</small>
|
||||
|
||||
## Opinions
|
||||
|
||||
"_[...] I'm using **FastAPI** a ton these days. [...] I'm actually planning to use it for all of my team's **ML services at Microsoft**. Some of them are getting integrated into the core **Windows** product and some **Office** products._"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Kabir Khan - <strong>Microsoft</strong> <a href="https://github.com/tiangolo/fastapi/pull/26" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
"_We adopted the **FastAPI** library to spawn a **REST** server that can be queried to obtain **predictions**. [for Ludwig]_"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Piero Molino, Yaroslav Dudin, and Sai Sumanth Miryala - <strong>Uber</strong> <a href="https://eng.uber.com/ludwig-v0-2/" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
"_**Netflix** is pleased to announce the open-source release of our **crisis management** orchestration framework: **Dispatch**! [built with **FastAPI**]_"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Kevin Glisson, Marc Vilanova, Forest Monsen - <strong>Netflix</strong> <a href="https://netflixtechblog.com/introducing-dispatch-da4b8a2a8072" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
"_I’m over the moon excited about **FastAPI**. It’s so fun!_"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Brian Okken - <strong><a href="https://pythonbytes.fm/episodes/show/123/time-to-right-the-py-wrongs?time_in_sec=855" target="_blank">Python Bytes</a> podcast host</strong> <a href="https://twitter.com/brianokken/status/1112220079972728832" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
"_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="http://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>
|
||||
|
||||
---
|
||||
|
||||
"_If you're looking to learn one **modern framework** for building REST APIs, check out **FastAPI** [...] It's fast, easy to use and easy to learn [...]_"
|
||||
|
||||
"_We've switched over to **FastAPI** for our **APIs** [...] I think you'll like it [...]_"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Ines Montani - Matthew Honnibal - <strong><a href="https://explosion.ai" target="_blank">Explosion AI</a> founders - <a href="https://spacy.io" target="_blank">spaCy</a> creators</strong> <a href="https://twitter.com/_inesmontani/status/1144173225322143744" target="_blank"><small>(ref)</small></a> - <a href="https://twitter.com/honnibal/status/1144031421859655680" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
## **Typer**, the FastAPI of CLIs
|
||||
|
||||
<a href="https://typer.tiangolo.com" target="_blank"><img src="https://typer.tiangolo.com/img/logo-margin/logo-margin-vector.svg" style="width: 20%;"></a>
|
||||
|
||||
If you are building a <abbr title="Command Line Interface">CLI</abbr> app to be used in the terminal instead of a web API, check out <a href="https://typer.tiangolo.com/" class="external-link" target="_blank">**Typer**</a>.
|
||||
|
||||
**Typer** is FastAPI's little sibling. And it's intended to be the **FastAPI of CLIs**. ⌨️ 🚀
|
||||
|
||||
## Requirements
|
||||
|
||||
Python 3.6+
|
||||
|
||||
FastAPI stands on the shoulders of giants:
|
||||
|
||||
* <a href="https://www.starlette.io/" class="external-link" target="_blank">Starlette</a> for the web parts.
|
||||
* <a href="https://pydantic-docs.helpmanual.io/" class="external-link" target="_blank">Pydantic</a> for the data parts.
|
||||
|
||||
## Installation
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ pip install fastapi
|
||||
|
||||
---> 100%
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
You will also need an ASGI server, for production such as <a href="http://www.uvicorn.org" class="external-link" target="_blank">Uvicorn</a> or <a href="https://gitlab.com/pgjones/hypercorn" class="external-link" target="_blank">Hypercorn</a>.
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ pip install uvicorn
|
||||
|
||||
---> 100%
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
## Example
|
||||
|
||||
### Create it
|
||||
|
||||
* Create a file `main.py` with:
|
||||
|
||||
```Python
|
||||
from typing import Optional
|
||||
|
||||
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: Optional[str] = None):
|
||||
return {"item_id": item_id, "q": q}
|
||||
```
|
||||
|
||||
<details markdown="1">
|
||||
<summary>Or use <code>async def</code>...</summary>
|
||||
|
||||
If your code uses `async` / `await`, use `async def`:
|
||||
|
||||
```Python hl_lines="9 14"
|
||||
from typing import Optional
|
||||
|
||||
from fastapi import FastAPI
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
|
||||
@app.get("/")
|
||||
async def read_root():
|
||||
return {"Hello": "World"}
|
||||
|
||||
|
||||
@app.get("/items/{item_id}")
|
||||
async def read_item(item_id: int, q: Optional[str] = None):
|
||||
return {"item_id": item_id, "q": q}
|
||||
```
|
||||
|
||||
**Note**:
|
||||
|
||||
If you don't know, check the _"In a hurry?"_ section about <a href="https://fastapi.tiangolo.com/async/#in-a-hurry" target="_blank">`async` and `await` in the docs</a>.
|
||||
|
||||
</details>
|
||||
|
||||
### Run it
|
||||
|
||||
Run the server with:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ uvicorn main:app --reload
|
||||
|
||||
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
|
||||
INFO: Started reloader process [28720]
|
||||
INFO: Started server process [28722]
|
||||
INFO: Waiting for application startup.
|
||||
INFO: Application startup complete.
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
<details markdown="1">
|
||||
<summary>About the command <code>uvicorn main:app --reload</code>...</summary>
|
||||
|
||||
The command `uvicorn main:app` refers to:
|
||||
|
||||
* `main`: the file `main.py` (the Python "module").
|
||||
* `app`: the object created inside of `main.py` with the line `app = FastAPI()`.
|
||||
* `--reload`: make the server restart after code changes. Only do this for development.
|
||||
|
||||
</details>
|
||||
|
||||
### Check it
|
||||
|
||||
Open your browser at <a href="http://127.0.0.1:8000/items/5?q=somequery" class="external-link" target="_blank">http://127.0.0.1:8000/items/5?q=somequery</a>.
|
||||
|
||||
You will see the JSON response as:
|
||||
|
||||
```JSON
|
||||
{"item_id": 5, "q": "somequery"}
|
||||
```
|
||||
|
||||
You already created an API that:
|
||||
|
||||
* Receives HTTP requests in the _paths_ `/` and `/items/{item_id}`.
|
||||
* Both _paths_ take `GET` <em>operations</em> (also known as HTTP _methods_).
|
||||
* The _path_ `/items/{item_id}` has a _path parameter_ `item_id` that should be an `int`.
|
||||
* The _path_ `/items/{item_id}` has an optional `str` _query parameter_ `q`.
|
||||
|
||||
### Interactive API docs
|
||||
|
||||
Now go to <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
|
||||
|
||||
You will see the automatic interactive API documentation (provided by <a href="https://github.com/swagger-api/swagger-ui" class="external-link" target="_blank">Swagger UI</a>):
|
||||
|
||||

|
||||
|
||||
### Alternative API docs
|
||||
|
||||
And now, go to <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a>.
|
||||
|
||||
You will see the alternative automatic documentation (provided by <a href="https://github.com/Rebilly/ReDoc" class="external-link" target="_blank">ReDoc</a>):
|
||||
|
||||

|
||||
|
||||
## Example upgrade
|
||||
|
||||
Now modify the file `main.py` to receive a body from a `PUT` request.
|
||||
|
||||
Declare the body using standard Python types, thanks to Pydantic.
|
||||
|
||||
```Python hl_lines="4 9 10 11 12 25 26 27"
|
||||
from typing import Optional
|
||||
|
||||
from fastapi import FastAPI
|
||||
from pydantic import BaseModel
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
|
||||
class Item(BaseModel):
|
||||
name: str
|
||||
price: float
|
||||
is_offer: Optional[bool] = None
|
||||
|
||||
|
||||
@app.get("/")
|
||||
def read_root():
|
||||
return {"Hello": "World"}
|
||||
|
||||
|
||||
@app.get("/items/{item_id}")
|
||||
def read_item(item_id: int, q: Optional[str] = None):
|
||||
return {"item_id": item_id, "q": q}
|
||||
|
||||
|
||||
@app.put("/items/{item_id}")
|
||||
def update_item(item_id: int, item: Item):
|
||||
return {"item_name": item.name, "item_id": item_id}
|
||||
```
|
||||
|
||||
The server should reload automatically (because you added `--reload` to the `uvicorn` command above).
|
||||
|
||||
### Interactive API docs upgrade
|
||||
|
||||
Now go to <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
|
||||
|
||||
* The interactive API documentation will be automatically updated, including the new body:
|
||||
|
||||

|
||||
|
||||
* Click on the button "Try it out", it allows you to fill the parameters and directly interact with the API:
|
||||
|
||||

|
||||
|
||||
* Then click on the "Execute" button, the user interface will communicate with your API, send the parameters, get the results and show them on the screen:
|
||||
|
||||

|
||||
|
||||
### Alternative API docs upgrade
|
||||
|
||||
And now, go to <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a>.
|
||||
|
||||
* The alternative documentation will also reflect the new query parameter and body:
|
||||
|
||||

|
||||
|
||||
### Recap
|
||||
|
||||
In summary, you declare **once** the types of parameters, body, etc. as function parameters.
|
||||
|
||||
You do that with standard modern Python types.
|
||||
|
||||
You don't have to learn a new syntax, the methods or classes of a specific library, etc.
|
||||
|
||||
Just standard **Python 3.6+**.
|
||||
|
||||
For example, for an `int`:
|
||||
|
||||
```Python
|
||||
item_id: int
|
||||
```
|
||||
|
||||
or for a more complex `Item` model:
|
||||
|
||||
```Python
|
||||
item: Item
|
||||
```
|
||||
|
||||
...and with that single declaration you get:
|
||||
|
||||
* Editor support, including:
|
||||
* Completion.
|
||||
* Type checks.
|
||||
* Validation of data:
|
||||
* Automatic and clear errors when the data is invalid.
|
||||
* Validation even for deeply nested JSON objects.
|
||||
* <abbr title="also known as: serialization, parsing, marshalling">Conversion</abbr> of input data: coming from the network to Python data and types. Reading from:
|
||||
* JSON.
|
||||
* Path parameters.
|
||||
* Query parameters.
|
||||
* Cookies.
|
||||
* Headers.
|
||||
* Forms.
|
||||
* Files.
|
||||
* <abbr title="also known as: serialization, parsing, marshalling">Conversion</abbr> of output data: converting from Python data and types to network data (as JSON):
|
||||
* Convert Python types (`str`, `int`, `float`, `bool`, `list`, etc).
|
||||
* `datetime` objects.
|
||||
* `UUID` objects.
|
||||
* Database models.
|
||||
* ...and many more.
|
||||
* Automatic interactive API documentation, including 2 alternative user interfaces:
|
||||
* Swagger UI.
|
||||
* ReDoc.
|
||||
|
||||
---
|
||||
|
||||
Coming back to the previous code example, **FastAPI** will:
|
||||
|
||||
* Validate that there is an `item_id` in the path for `GET` and `PUT` requests.
|
||||
* Validate that the `item_id` is of type `int` for `GET` and `PUT` requests.
|
||||
* If it is not, the client will see a useful, clear error.
|
||||
* Check if there is an optional query parameter named `q` (as in `http://127.0.0.1:8000/items/foo?q=somequery`) for `GET` requests.
|
||||
* As the `q` parameter is declared with `= None`, it is optional.
|
||||
* Without the `None` it would be required (as is the body in the case with `PUT`).
|
||||
* For `PUT` requests to `/items/{item_id}`, Read the body as JSON:
|
||||
* Check that it has a required attribute `name` that should be a `str`.
|
||||
* Check that it has a required attribute `price` that has to be a `float`.
|
||||
* Check that it has an optional attribute `is_offer`, that should be a `bool`, if present.
|
||||
* All this would also work for deeply nested JSON objects.
|
||||
* Convert from and to JSON automatically.
|
||||
* Document everything with OpenAPI, that can be used by:
|
||||
* Interactive documentation systems.
|
||||
* Automatic client code generation systems, for many languages.
|
||||
* Provide 2 interactive documentation web interfaces directly.
|
||||
|
||||
---
|
||||
|
||||
We just scratched the surface, but you already get the idea of how it all works.
|
||||
|
||||
Try changing the line with:
|
||||
|
||||
```Python
|
||||
return {"item_name": item.name, "item_id": item_id}
|
||||
```
|
||||
|
||||
...from:
|
||||
|
||||
```Python
|
||||
... "item_name": item.name ...
|
||||
```
|
||||
|
||||
...to:
|
||||
|
||||
```Python
|
||||
... "item_price": item.price ...
|
||||
```
|
||||
|
||||
...and see how your editor will auto-complete the attributes and know their types:
|
||||
|
||||

|
||||
|
||||
For a more complete example including more features, see the <a href="https://fastapi.tiangolo.com/tutorial/">Tutorial - User Guide</a>.
|
||||
|
||||
**Spoiler alert**: the tutorial - user guide includes:
|
||||
|
||||
* Declaration of **parameters** from other different places as: **headers**, **cookies**, **form fields** and **files**.
|
||||
* How to set **validation constraints** as `maximum_length` or `regex`.
|
||||
* A very powerful and easy to use **<abbr title="also known as components, resources, providers, services, injectables">Dependency Injection</abbr>** system.
|
||||
* Security and authentication, including support for **OAuth2** with **JWT tokens** and **HTTP Basic** auth.
|
||||
* More advanced (but equally easy) techniques for declaring **deeply nested JSON models** (thanks to Pydantic).
|
||||
* Many extra features (thanks to Starlette) as:
|
||||
* **WebSockets**
|
||||
* **GraphQL**
|
||||
* extremely easy tests based on `requests` and `pytest`
|
||||
* **CORS**
|
||||
* **Cookie Sessions**
|
||||
* ...and more.
|
||||
|
||||
## Performance
|
||||
|
||||
Independent TechEmpower benchmarks show **FastAPI** applications running under Uvicorn as <a href="https://www.techempower.com/benchmarks/#section=test&runid=7464e520-0dc2-473d-bd34-dbdfd7e85911&hw=ph&test=query&l=zijzen-7" class="external-link" target="_blank">one of the fastest Python frameworks available</a>, only below Starlette and Uvicorn themselves (used internally by FastAPI). (*)
|
||||
|
||||
To understand more about it, see the section <a href="https://fastapi.tiangolo.com/benchmarks/" class="internal-link" target="_blank">Benchmarks</a>.
|
||||
|
||||
## Optional Dependencies
|
||||
|
||||
Used by Pydantic:
|
||||
|
||||
* <a href="https://github.com/esnme/ultrajson" target="_blank"><code>ujson</code></a> - for faster JSON <abbr title="converting the string that comes from an HTTP request into Python data">"parsing"</abbr>.
|
||||
* <a href="https://github.com/JoshData/python-email-validator" target="_blank"><code>email_validator</code></a> - for email validation.
|
||||
|
||||
Used by Starlette:
|
||||
|
||||
* <a href="http://docs.python-requests.org" target="_blank"><code>requests</code></a> - Required if you want to use the `TestClient`.
|
||||
* <a href="https://github.com/Tinche/aiofiles" target="_blank"><code>aiofiles</code></a> - Required if you want to use `FileResponse` or `StaticFiles`.
|
||||
* <a href="http://jinja.pocoo.org" target="_blank"><code>jinja2</code></a> - Required if you want to use the default template configuration.
|
||||
* <a href="https://andrew-d.github.io/python-multipart/" target="_blank"><code>python-multipart</code></a> - Required if you want to support form <abbr title="converting the string that comes from an HTTP request into Python data">"parsing"</abbr>, with `request.form()`.
|
||||
* <a href="https://pythonhosted.org/itsdangerous/" target="_blank"><code>itsdangerous</code></a> - Required for `SessionMiddleware` support.
|
||||
* <a href="https://pyyaml.org/wiki/PyYAMLDocumentation" target="_blank"><code>pyyaml</code></a> - Required for Starlette's `SchemaGenerator` support (you probably don't need it with FastAPI).
|
||||
* <a href="https://graphene-python.org/" target="_blank"><code>graphene</code></a> - Required for `GraphQLApp` support.
|
||||
* <a href="https://github.com/esnme/ultrajson" target="_blank"><code>ujson</code></a> - Required if you want to use `UJSONResponse`.
|
||||
|
||||
Used by FastAPI / Starlette:
|
||||
|
||||
* <a href="http://www.uvicorn.org" target="_blank"><code>uvicorn</code></a> - for the server that loads and serves your application.
|
||||
* <a href="https://github.com/ijl/orjson" target="_blank"><code>orjson</code></a> - Required if you want to use `ORJSONResponse`.
|
||||
|
||||
You can install all of these with `pip install fastapi[all]`.
|
||||
|
||||
## License
|
||||
|
||||
This project is licensed under the terms of the MIT license.
|
||||
73
docs/ru/mkdocs.yml
Normal file
@@ -0,0 +1,73 @@
|
||||
site_name: FastAPI
|
||||
site_description: FastAPI framework, high performance, easy to learn, fast to code, ready for production
|
||||
site_url: https://fastapi.tiangolo.com/ru/
|
||||
theme:
|
||||
name: material
|
||||
palette:
|
||||
scheme: preference
|
||||
primary: teal
|
||||
accent: amber
|
||||
icon:
|
||||
repo: fontawesome/brands/github-alt
|
||||
logo: https://fastapi.tiangolo.com/img/icon-white.svg
|
||||
favicon: https://fastapi.tiangolo.com/img/favicon.png
|
||||
language: ru
|
||||
repo_name: tiangolo/fastapi
|
||||
repo_url: https://github.com/tiangolo/fastapi
|
||||
edit_uri: ''
|
||||
google_analytics:
|
||||
- UA-133183413-1
|
||||
- auto
|
||||
plugins:
|
||||
- search
|
||||
- markdownextradata:
|
||||
data: data
|
||||
nav:
|
||||
- FastAPI: index.md
|
||||
- Languages:
|
||||
- en: /
|
||||
- es: /es/
|
||||
- it: /it/
|
||||
- pt: /pt/
|
||||
- ru: /ru/
|
||||
- uk: /uk/
|
||||
- zh: /zh/
|
||||
markdown_extensions:
|
||||
- toc:
|
||||
permalink: true
|
||||
- markdown.extensions.codehilite:
|
||||
guess_lang: false
|
||||
- markdown_include.include:
|
||||
base_path: docs
|
||||
- admonition
|
||||
- codehilite
|
||||
- extra
|
||||
- pymdownx.superfences:
|
||||
custom_fences:
|
||||
- name: mermaid
|
||||
class: mermaid
|
||||
format: !!python/name:pymdownx.superfences.fence_div_format ''
|
||||
- pymdownx.tabbed
|
||||
extra:
|
||||
social:
|
||||
- icon: fontawesome/brands/github-alt
|
||||
link: https://github.com/tiangolo/typer
|
||||
- icon: fontawesome/brands/twitter
|
||||
link: https://twitter.com/tiangolo
|
||||
- icon: fontawesome/brands/linkedin
|
||||
link: https://www.linkedin.com/in/tiangolo
|
||||
- icon: fontawesome/brands/dev
|
||||
link: https://dev.to/tiangolo
|
||||
- icon: fontawesome/brands/medium
|
||||
link: https://medium.com/@tiangolo
|
||||
- icon: fontawesome/solid/globe
|
||||
link: https://tiangolo.com
|
||||
extra_css:
|
||||
- https://fastapi.tiangolo.com/css/termynal.css
|
||||
- https://fastapi.tiangolo.com/css/custom.css
|
||||
extra_javascript:
|
||||
- https://unpkg.com/mermaid@8.4.6/dist/mermaid.min.js
|
||||
- https://fastapi.tiangolo.com/js/termynal.js
|
||||
- https://fastapi.tiangolo.com/js/custom.js
|
||||
- https://fastapi.tiangolo.com/js/chat.js
|
||||
- https://sidecar.gitter.im/dist/sidecar.v1.js
|
||||
453
docs/uk/docs/index.md
Normal file
@@ -0,0 +1,453 @@
|
||||
|
||||
{!../../../docs/missing-translation.md!}
|
||||
|
||||
|
||||
<p align="center">
|
||||
<a href="https://fastapi.tiangolo.com"><img src="https://fastapi.tiangolo.com/img/logo-margin/logo-teal.png" alt="FastAPI"></a>
|
||||
</p>
|
||||
<p align="center">
|
||||
<em>FastAPI framework, high performance, easy to learn, fast to code, ready for production</em>
|
||||
</p>
|
||||
<p align="center">
|
||||
<a href="https://github.com/tiangolo/fastapi/actions?query=workflow%3ATest" target="_blank">
|
||||
<img src="https://github.com/tiangolo/fastapi/workflows/Test/badge.svg" alt="Test">
|
||||
</a>
|
||||
<a href="https://codecov.io/gh/tiangolo/fastapi" target="_blank">
|
||||
<img src="https://img.shields.io/codecov/c/github/tiangolo/fastapi?color=%2334D058" alt="Coverage">
|
||||
</a>
|
||||
<a href="https://pypi.org/project/fastapi" target="_blank">
|
||||
<img src="https://img.shields.io/pypi/v/fastapi?color=%2334D058&label=pypi%20package" alt="Package version">
|
||||
</a>
|
||||
<a href="https://gitter.im/tiangolo/fastapi?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge" target="_blank">
|
||||
<img src="https://badges.gitter.im/tiangolo/fastapi.svg" alt="Join the chat at https://gitter.im/tiangolo/fastapi">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
---
|
||||
|
||||
**Documentation**: <a href="https://fastapi.tiangolo.com" target="_blank">https://fastapi.tiangolo.com</a>
|
||||
|
||||
**Source Code**: <a href="https://github.com/tiangolo/fastapi" target="_blank">https://github.com/tiangolo/fastapi</a>
|
||||
|
||||
---
|
||||
|
||||
FastAPI is a modern, fast (high-performance), web framework for building APIs with Python 3.6+ based on standard Python type hints.
|
||||
|
||||
The key features are:
|
||||
|
||||
* **Fast**: Very high performance, on par with **NodeJS** and **Go** (thanks to Starlette and Pydantic). [One of the fastest Python frameworks available](#performance).
|
||||
|
||||
* **Fast to code**: Increase the speed to develop features by about 200% to 300%. *
|
||||
* **Fewer bugs**: Reduce about 40% of human (developer) induced errors. *
|
||||
* **Intuitive**: Great editor support. <abbr title="also known as auto-complete, autocompletion, IntelliSense">Completion</abbr> everywhere. Less time debugging.
|
||||
* **Easy**: Designed to be easy to use and learn. Less time reading docs.
|
||||
* **Short**: Minimize code duplication. Multiple features from each parameter declaration. Fewer bugs.
|
||||
* **Robust**: Get production-ready code. With automatic interactive documentation.
|
||||
* **Standards-based**: Based on (and fully compatible with) the open standards for APIs: <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank">OpenAPI</a> (previously known as Swagger) and <a href="http://json-schema.org/" class="external-link" target="_blank">JSON Schema</a>.
|
||||
|
||||
<small>* estimation based on tests on an internal development team, building production applications.</small>
|
||||
|
||||
## Opinions
|
||||
|
||||
"_[...] I'm using **FastAPI** a ton these days. [...] I'm actually planning to use it for all of my team's **ML services at Microsoft**. Some of them are getting integrated into the core **Windows** product and some **Office** products._"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Kabir Khan - <strong>Microsoft</strong> <a href="https://github.com/tiangolo/fastapi/pull/26" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
"_We adopted the **FastAPI** library to spawn a **REST** server that can be queried to obtain **predictions**. [for Ludwig]_"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Piero Molino, Yaroslav Dudin, and Sai Sumanth Miryala - <strong>Uber</strong> <a href="https://eng.uber.com/ludwig-v0-2/" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
"_**Netflix** is pleased to announce the open-source release of our **crisis management** orchestration framework: **Dispatch**! [built with **FastAPI**]_"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Kevin Glisson, Marc Vilanova, Forest Monsen - <strong>Netflix</strong> <a href="https://netflixtechblog.com/introducing-dispatch-da4b8a2a8072" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
"_I’m over the moon excited about **FastAPI**. It’s so fun!_"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Brian Okken - <strong><a href="https://pythonbytes.fm/episodes/show/123/time-to-right-the-py-wrongs?time_in_sec=855" target="_blank">Python Bytes</a> podcast host</strong> <a href="https://twitter.com/brianokken/status/1112220079972728832" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
"_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="http://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>
|
||||
|
||||
---
|
||||
|
||||
"_If you're looking to learn one **modern framework** for building REST APIs, check out **FastAPI** [...] It's fast, easy to use and easy to learn [...]_"
|
||||
|
||||
"_We've switched over to **FastAPI** for our **APIs** [...] I think you'll like it [...]_"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Ines Montani - Matthew Honnibal - <strong><a href="https://explosion.ai" target="_blank">Explosion AI</a> founders - <a href="https://spacy.io" target="_blank">spaCy</a> creators</strong> <a href="https://twitter.com/_inesmontani/status/1144173225322143744" target="_blank"><small>(ref)</small></a> - <a href="https://twitter.com/honnibal/status/1144031421859655680" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
## **Typer**, the FastAPI of CLIs
|
||||
|
||||
<a href="https://typer.tiangolo.com" target="_blank"><img src="https://typer.tiangolo.com/img/logo-margin/logo-margin-vector.svg" style="width: 20%;"></a>
|
||||
|
||||
If you are building a <abbr title="Command Line Interface">CLI</abbr> app to be used in the terminal instead of a web API, check out <a href="https://typer.tiangolo.com/" class="external-link" target="_blank">**Typer**</a>.
|
||||
|
||||
**Typer** is FastAPI's little sibling. And it's intended to be the **FastAPI of CLIs**. ⌨️ 🚀
|
||||
|
||||
## Requirements
|
||||
|
||||
Python 3.6+
|
||||
|
||||
FastAPI stands on the shoulders of giants:
|
||||
|
||||
* <a href="https://www.starlette.io/" class="external-link" target="_blank">Starlette</a> for the web parts.
|
||||
* <a href="https://pydantic-docs.helpmanual.io/" class="external-link" target="_blank">Pydantic</a> for the data parts.
|
||||
|
||||
## Installation
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ pip install fastapi
|
||||
|
||||
---> 100%
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
You will also need an ASGI server, for production such as <a href="http://www.uvicorn.org" class="external-link" target="_blank">Uvicorn</a> or <a href="https://gitlab.com/pgjones/hypercorn" class="external-link" target="_blank">Hypercorn</a>.
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ pip install uvicorn
|
||||
|
||||
---> 100%
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
## Example
|
||||
|
||||
### Create it
|
||||
|
||||
* Create a file `main.py` with:
|
||||
|
||||
```Python
|
||||
from typing import Optional
|
||||
|
||||
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: Optional[str] = None):
|
||||
return {"item_id": item_id, "q": q}
|
||||
```
|
||||
|
||||
<details markdown="1">
|
||||
<summary>Or use <code>async def</code>...</summary>
|
||||
|
||||
If your code uses `async` / `await`, use `async def`:
|
||||
|
||||
```Python hl_lines="9 14"
|
||||
from typing import Optional
|
||||
|
||||
from fastapi import FastAPI
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
|
||||
@app.get("/")
|
||||
async def read_root():
|
||||
return {"Hello": "World"}
|
||||
|
||||
|
||||
@app.get("/items/{item_id}")
|
||||
async def read_item(item_id: int, q: Optional[str] = None):
|
||||
return {"item_id": item_id, "q": q}
|
||||
```
|
||||
|
||||
**Note**:
|
||||
|
||||
If you don't know, check the _"In a hurry?"_ section about <a href="https://fastapi.tiangolo.com/async/#in-a-hurry" target="_blank">`async` and `await` in the docs</a>.
|
||||
|
||||
</details>
|
||||
|
||||
### Run it
|
||||
|
||||
Run the server with:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ uvicorn main:app --reload
|
||||
|
||||
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
|
||||
INFO: Started reloader process [28720]
|
||||
INFO: Started server process [28722]
|
||||
INFO: Waiting for application startup.
|
||||
INFO: Application startup complete.
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
<details markdown="1">
|
||||
<summary>About the command <code>uvicorn main:app --reload</code>...</summary>
|
||||
|
||||
The command `uvicorn main:app` refers to:
|
||||
|
||||
* `main`: the file `main.py` (the Python "module").
|
||||
* `app`: the object created inside of `main.py` with the line `app = FastAPI()`.
|
||||
* `--reload`: make the server restart after code changes. Only do this for development.
|
||||
|
||||
</details>
|
||||
|
||||
### Check it
|
||||
|
||||
Open your browser at <a href="http://127.0.0.1:8000/items/5?q=somequery" class="external-link" target="_blank">http://127.0.0.1:8000/items/5?q=somequery</a>.
|
||||
|
||||
You will see the JSON response as:
|
||||
|
||||
```JSON
|
||||
{"item_id": 5, "q": "somequery"}
|
||||
```
|
||||
|
||||
You already created an API that:
|
||||
|
||||
* Receives HTTP requests in the _paths_ `/` and `/items/{item_id}`.
|
||||
* Both _paths_ take `GET` <em>operations</em> (also known as HTTP _methods_).
|
||||
* The _path_ `/items/{item_id}` has a _path parameter_ `item_id` that should be an `int`.
|
||||
* The _path_ `/items/{item_id}` has an optional `str` _query parameter_ `q`.
|
||||
|
||||
### Interactive API docs
|
||||
|
||||
Now go to <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
|
||||
|
||||
You will see the automatic interactive API documentation (provided by <a href="https://github.com/swagger-api/swagger-ui" class="external-link" target="_blank">Swagger UI</a>):
|
||||
|
||||

|
||||
|
||||
### Alternative API docs
|
||||
|
||||
And now, go to <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a>.
|
||||
|
||||
You will see the alternative automatic documentation (provided by <a href="https://github.com/Rebilly/ReDoc" class="external-link" target="_blank">ReDoc</a>):
|
||||
|
||||

|
||||
|
||||
## Example upgrade
|
||||
|
||||
Now modify the file `main.py` to receive a body from a `PUT` request.
|
||||
|
||||
Declare the body using standard Python types, thanks to Pydantic.
|
||||
|
||||
```Python hl_lines="4 9 10 11 12 25 26 27"
|
||||
from typing import Optional
|
||||
|
||||
from fastapi import FastAPI
|
||||
from pydantic import BaseModel
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
|
||||
class Item(BaseModel):
|
||||
name: str
|
||||
price: float
|
||||
is_offer: Optional[bool] = None
|
||||
|
||||
|
||||
@app.get("/")
|
||||
def read_root():
|
||||
return {"Hello": "World"}
|
||||
|
||||
|
||||
@app.get("/items/{item_id}")
|
||||
def read_item(item_id: int, q: Optional[str] = None):
|
||||
return {"item_id": item_id, "q": q}
|
||||
|
||||
|
||||
@app.put("/items/{item_id}")
|
||||
def update_item(item_id: int, item: Item):
|
||||
return {"item_name": item.name, "item_id": item_id}
|
||||
```
|
||||
|
||||
The server should reload automatically (because you added `--reload` to the `uvicorn` command above).
|
||||
|
||||
### Interactive API docs upgrade
|
||||
|
||||
Now go to <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
|
||||
|
||||
* The interactive API documentation will be automatically updated, including the new body:
|
||||
|
||||

|
||||
|
||||
* Click on the button "Try it out", it allows you to fill the parameters and directly interact with the API:
|
||||
|
||||

|
||||
|
||||
* Then click on the "Execute" button, the user interface will communicate with your API, send the parameters, get the results and show them on the screen:
|
||||
|
||||

|
||||
|
||||
### Alternative API docs upgrade
|
||||
|
||||
And now, go to <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a>.
|
||||
|
||||
* The alternative documentation will also reflect the new query parameter and body:
|
||||
|
||||

|
||||
|
||||
### Recap
|
||||
|
||||
In summary, you declare **once** the types of parameters, body, etc. as function parameters.
|
||||
|
||||
You do that with standard modern Python types.
|
||||
|
||||
You don't have to learn a new syntax, the methods or classes of a specific library, etc.
|
||||
|
||||
Just standard **Python 3.6+**.
|
||||
|
||||
For example, for an `int`:
|
||||
|
||||
```Python
|
||||
item_id: int
|
||||
```
|
||||
|
||||
or for a more complex `Item` model:
|
||||
|
||||
```Python
|
||||
item: Item
|
||||
```
|
||||
|
||||
...and with that single declaration you get:
|
||||
|
||||
* Editor support, including:
|
||||
* Completion.
|
||||
* Type checks.
|
||||
* Validation of data:
|
||||
* Automatic and clear errors when the data is invalid.
|
||||
* Validation even for deeply nested JSON objects.
|
||||
* <abbr title="also known as: serialization, parsing, marshalling">Conversion</abbr> of input data: coming from the network to Python data and types. Reading from:
|
||||
* JSON.
|
||||
* Path parameters.
|
||||
* Query parameters.
|
||||
* Cookies.
|
||||
* Headers.
|
||||
* Forms.
|
||||
* Files.
|
||||
* <abbr title="also known as: serialization, parsing, marshalling">Conversion</abbr> of output data: converting from Python data and types to network data (as JSON):
|
||||
* Convert Python types (`str`, `int`, `float`, `bool`, `list`, etc).
|
||||
* `datetime` objects.
|
||||
* `UUID` objects.
|
||||
* Database models.
|
||||
* ...and many more.
|
||||
* Automatic interactive API documentation, including 2 alternative user interfaces:
|
||||
* Swagger UI.
|
||||
* ReDoc.
|
||||
|
||||
---
|
||||
|
||||
Coming back to the previous code example, **FastAPI** will:
|
||||
|
||||
* Validate that there is an `item_id` in the path for `GET` and `PUT` requests.
|
||||
* Validate that the `item_id` is of type `int` for `GET` and `PUT` requests.
|
||||
* If it is not, the client will see a useful, clear error.
|
||||
* Check if there is an optional query parameter named `q` (as in `http://127.0.0.1:8000/items/foo?q=somequery`) for `GET` requests.
|
||||
* As the `q` parameter is declared with `= None`, it is optional.
|
||||
* Without the `None` it would be required (as is the body in the case with `PUT`).
|
||||
* For `PUT` requests to `/items/{item_id}`, Read the body as JSON:
|
||||
* Check that it has a required attribute `name` that should be a `str`.
|
||||
* Check that it has a required attribute `price` that has to be a `float`.
|
||||
* Check that it has an optional attribute `is_offer`, that should be a `bool`, if present.
|
||||
* All this would also work for deeply nested JSON objects.
|
||||
* Convert from and to JSON automatically.
|
||||
* Document everything with OpenAPI, that can be used by:
|
||||
* Interactive documentation systems.
|
||||
* Automatic client code generation systems, for many languages.
|
||||
* Provide 2 interactive documentation web interfaces directly.
|
||||
|
||||
---
|
||||
|
||||
We just scratched the surface, but you already get the idea of how it all works.
|
||||
|
||||
Try changing the line with:
|
||||
|
||||
```Python
|
||||
return {"item_name": item.name, "item_id": item_id}
|
||||
```
|
||||
|
||||
...from:
|
||||
|
||||
```Python
|
||||
... "item_name": item.name ...
|
||||
```
|
||||
|
||||
...to:
|
||||
|
||||
```Python
|
||||
... "item_price": item.price ...
|
||||
```
|
||||
|
||||
...and see how your editor will auto-complete the attributes and know their types:
|
||||
|
||||

|
||||
|
||||
For a more complete example including more features, see the <a href="https://fastapi.tiangolo.com/tutorial/">Tutorial - User Guide</a>.
|
||||
|
||||
**Spoiler alert**: the tutorial - user guide includes:
|
||||
|
||||
* Declaration of **parameters** from other different places as: **headers**, **cookies**, **form fields** and **files**.
|
||||
* How to set **validation constraints** as `maximum_length` or `regex`.
|
||||
* A very powerful and easy to use **<abbr title="also known as components, resources, providers, services, injectables">Dependency Injection</abbr>** system.
|
||||
* Security and authentication, including support for **OAuth2** with **JWT tokens** and **HTTP Basic** auth.
|
||||
* More advanced (but equally easy) techniques for declaring **deeply nested JSON models** (thanks to Pydantic).
|
||||
* Many extra features (thanks to Starlette) as:
|
||||
* **WebSockets**
|
||||
* **GraphQL**
|
||||
* extremely easy tests based on `requests` and `pytest`
|
||||
* **CORS**
|
||||
* **Cookie Sessions**
|
||||
* ...and more.
|
||||
|
||||
## Performance
|
||||
|
||||
Independent TechEmpower benchmarks show **FastAPI** applications running under Uvicorn as <a href="https://www.techempower.com/benchmarks/#section=test&runid=7464e520-0dc2-473d-bd34-dbdfd7e85911&hw=ph&test=query&l=zijzen-7" class="external-link" target="_blank">one of the fastest Python frameworks available</a>, only below Starlette and Uvicorn themselves (used internally by FastAPI). (*)
|
||||
|
||||
To understand more about it, see the section <a href="https://fastapi.tiangolo.com/benchmarks/" class="internal-link" target="_blank">Benchmarks</a>.
|
||||
|
||||
## Optional Dependencies
|
||||
|
||||
Used by Pydantic:
|
||||
|
||||
* <a href="https://github.com/esnme/ultrajson" target="_blank"><code>ujson</code></a> - for faster JSON <abbr title="converting the string that comes from an HTTP request into Python data">"parsing"</abbr>.
|
||||
* <a href="https://github.com/JoshData/python-email-validator" target="_blank"><code>email_validator</code></a> - for email validation.
|
||||
|
||||
Used by Starlette:
|
||||
|
||||
* <a href="http://docs.python-requests.org" target="_blank"><code>requests</code></a> - Required if you want to use the `TestClient`.
|
||||
* <a href="https://github.com/Tinche/aiofiles" target="_blank"><code>aiofiles</code></a> - Required if you want to use `FileResponse` or `StaticFiles`.
|
||||
* <a href="http://jinja.pocoo.org" target="_blank"><code>jinja2</code></a> - Required if you want to use the default template configuration.
|
||||
* <a href="https://andrew-d.github.io/python-multipart/" target="_blank"><code>python-multipart</code></a> - Required if you want to support form <abbr title="converting the string that comes from an HTTP request into Python data">"parsing"</abbr>, with `request.form()`.
|
||||
* <a href="https://pythonhosted.org/itsdangerous/" target="_blank"><code>itsdangerous</code></a> - Required for `SessionMiddleware` support.
|
||||
* <a href="https://pyyaml.org/wiki/PyYAMLDocumentation" target="_blank"><code>pyyaml</code></a> - Required for Starlette's `SchemaGenerator` support (you probably don't need it with FastAPI).
|
||||
* <a href="https://graphene-python.org/" target="_blank"><code>graphene</code></a> - Required for `GraphQLApp` support.
|
||||
* <a href="https://github.com/esnme/ultrajson" target="_blank"><code>ujson</code></a> - Required if you want to use `UJSONResponse`.
|
||||
|
||||
Used by FastAPI / Starlette:
|
||||
|
||||
* <a href="http://www.uvicorn.org" target="_blank"><code>uvicorn</code></a> - for the server that loads and serves your application.
|
||||
* <a href="https://github.com/ijl/orjson" target="_blank"><code>orjson</code></a> - Required if you want to use `ORJSONResponse`.
|
||||
|
||||
You can install all of these with `pip install fastapi[all]`.
|
||||
|
||||
## License
|
||||
|
||||
This project is licensed under the terms of the MIT license.
|
||||
73
docs/uk/mkdocs.yml
Normal file
@@ -0,0 +1,73 @@
|
||||
site_name: FastAPI
|
||||
site_description: FastAPI framework, high performance, easy to learn, fast to code, ready for production
|
||||
site_url: https://fastapi.tiangolo.com/uk/
|
||||
theme:
|
||||
name: material
|
||||
palette:
|
||||
scheme: preference
|
||||
primary: teal
|
||||
accent: amber
|
||||
icon:
|
||||
repo: fontawesome/brands/github-alt
|
||||
logo: https://fastapi.tiangolo.com/img/icon-white.svg
|
||||
favicon: https://fastapi.tiangolo.com/img/favicon.png
|
||||
language: uk
|
||||
repo_name: tiangolo/fastapi
|
||||
repo_url: https://github.com/tiangolo/fastapi
|
||||
edit_uri: ''
|
||||
google_analytics:
|
||||
- UA-133183413-1
|
||||
- auto
|
||||
plugins:
|
||||
- search
|
||||
- markdownextradata:
|
||||
data: data
|
||||
nav:
|
||||
- FastAPI: index.md
|
||||
- Languages:
|
||||
- en: /
|
||||
- es: /es/
|
||||
- it: /it/
|
||||
- pt: /pt/
|
||||
- ru: /ru/
|
||||
- uk: /uk/
|
||||
- zh: /zh/
|
||||
markdown_extensions:
|
||||
- toc:
|
||||
permalink: true
|
||||
- markdown.extensions.codehilite:
|
||||
guess_lang: false
|
||||
- markdown_include.include:
|
||||
base_path: docs
|
||||
- admonition
|
||||
- codehilite
|
||||
- extra
|
||||
- pymdownx.superfences:
|
||||
custom_fences:
|
||||
- name: mermaid
|
||||
class: mermaid
|
||||
format: !!python/name:pymdownx.superfences.fence_div_format ''
|
||||
- pymdownx.tabbed
|
||||
extra:
|
||||
social:
|
||||
- icon: fontawesome/brands/github-alt
|
||||
link: https://github.com/tiangolo/typer
|
||||
- icon: fontawesome/brands/twitter
|
||||
link: https://twitter.com/tiangolo
|
||||
- icon: fontawesome/brands/linkedin
|
||||
link: https://www.linkedin.com/in/tiangolo
|
||||
- icon: fontawesome/brands/dev
|
||||
link: https://dev.to/tiangolo
|
||||
- icon: fontawesome/brands/medium
|
||||
link: https://medium.com/@tiangolo
|
||||
- icon: fontawesome/solid/globe
|
||||
link: https://tiangolo.com
|
||||
extra_css:
|
||||
- https://fastapi.tiangolo.com/css/termynal.css
|
||||
- https://fastapi.tiangolo.com/css/custom.css
|
||||
extra_javascript:
|
||||
- https://unpkg.com/mermaid@8.4.6/dist/mermaid.min.js
|
||||
- https://fastapi.tiangolo.com/js/termynal.js
|
||||
- https://fastapi.tiangolo.com/js/custom.js
|
||||
- https://fastapi.tiangolo.com/js/chat.js
|
||||
- https://sidecar.gitter.im/dist/sidecar.v1.js
|
||||
@@ -498,13 +498,3 @@ $ bash scripts/test-cov-html.sh
|
||||
</div>
|
||||
|
||||
该命令生成了一个 `./htmlcov/` 目录,如果你在浏览器中打开 `./htmlcov/index.html` 文件,你可以交互式地浏览被测试所覆盖的代码区块,并注意是否缺少了任何区块。
|
||||
|
||||
### 在编辑器中测试
|
||||
|
||||
如果你想要在编辑器中运行集成测试,请将 `./docs_src` 加入到你的 `PYTHONPATH` 变量中。
|
||||
|
||||
例如,在 VS Code 中你可以创建一个包含以下内容的 `.env` 文件:
|
||||
|
||||
```env
|
||||
PYTHONPATH=./docs_src
|
||||
```
|
||||
|
||||
@@ -162,6 +162,8 @@ CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80"]
|
||||
* 创建一个 `main.py` 文件,内容如下:
|
||||
|
||||
```Python
|
||||
from typing import Optional
|
||||
|
||||
from fastapi import FastAPI
|
||||
|
||||
app = FastAPI()
|
||||
@@ -173,7 +175,7 @@ def read_root():
|
||||
|
||||
|
||||
@app.get("/items/{item_id}")
|
||||
def read_item(item_id: int, q: str = None):
|
||||
def read_item(item_id: int, q: Optional[str] = None):
|
||||
return {"item_id": item_id, "q": q}
|
||||
```
|
||||
|
||||
|
||||
@@ -2,17 +2,17 @@
|
||||
<a href="https://fastapi.tiangolo.com"><img src="https://fastapi.tiangolo.com/img/logo-margin/logo-teal.png" alt="FastAPI"></a>
|
||||
</p>
|
||||
<p align="center">
|
||||
<em>FastAPI framework, high performance, easy to learn, fast to code, ready for production</em>
|
||||
<em>FastAPI 框架,高性能,易于学习,高效编码,生产可用</em>
|
||||
</p>
|
||||
<p align="center">
|
||||
<a href="https://travis-ci.com/tiangolo/fastapi" target="_blank">
|
||||
<img src="https://travis-ci.com/tiangolo/fastapi.svg?branch=master" alt="Build Status">
|
||||
<a href="https://github.com/tiangolo/fastapi/actions?query=workflow%3ATest" target="_blank">
|
||||
<img src="https://github.com/tiangolo/fastapi/workflows/Test/badge.svg" alt="Test">
|
||||
</a>
|
||||
<a href="https://codecov.io/gh/tiangolo/fastapi" target="_blank">
|
||||
<img src="https://img.shields.io/codecov/c/github/tiangolo/fastapi" alt="Coverage">
|
||||
<img src="https://img.shields.io/codecov/c/github/tiangolo/fastapi?color=%2334D058" alt="Coverage">
|
||||
</a>
|
||||
<a href="https://pypi.org/project/fastapi" target="_blank">
|
||||
<img src="https://badge.fury.io/py/fastapi.svg" alt="Package version">
|
||||
<img src="https://img.shields.io/pypi/v/fastapi?color=%2334D058&label=pypi%20package" alt="Package version">
|
||||
</a>
|
||||
<a href="https://gitter.im/tiangolo/fastapi?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge" target="_blank">
|
||||
<img src="https://badges.gitter.im/tiangolo/fastapi.svg" alt="Join the chat at https://gitter.im/tiangolo/fastapi">
|
||||
@@ -27,7 +27,7 @@
|
||||
|
||||
---
|
||||
|
||||
FastAPI 是一个用于构建 API 的现代、快速(高性能)的 web 框架,使用基于类型提示的 Python 3.6 及更高版本。
|
||||
FastAPI 是一个用于构建 API 的现代、快速(高性能)的 web 框架,使用 Python 3.6+ 并基于标准的 Python 类型提示。
|
||||
|
||||
关键特性:
|
||||
|
||||
@@ -36,54 +36,60 @@ FastAPI 是一个用于构建 API 的现代、快速(高性能)的 web 框
|
||||
* **高效编码**:提高功能开发速度约 200% 至 300%。*
|
||||
* **更少 bug**:减少约 40% 的人为(开发者)导致错误。*
|
||||
* **智能**:极佳的编辑器支持。处处皆可<abbr title="也被称为自动完成、智能感知">自动补全</abbr>,减少调试时间。
|
||||
* **简单**:设计的易于使用和学习,减少阅读文档时间。
|
||||
* **简短**:减少代码重复。通过不同的参数声明实现丰富功能。bug 更少。
|
||||
* **健壮**:生产可用级别的代码。以及自动生成的交互式文档。
|
||||
* **标准化**:基于 API 的相关开放标准并完全兼容:<a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank">OpenAPI</a> (以前被称为 Swagger) 和 <a href="http://json-schema.org/" class="external-link" target="_blank">JSON Schema</a>。
|
||||
* **简单**:设计的易于使用和学习,阅读文档的时间更短。
|
||||
* **简短**:使代码重复最小化。通过不同的参数声明实现丰富功能。bug 更少。
|
||||
* **健壮**:生产可用级别的代码。还有自动生成的交互式文档。
|
||||
* **标准化**:基于(并完全兼容)API 的相关开放标准:<a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank">OpenAPI</a> (以前被称为 Swagger) 和 <a href="http://json-schema.org/" class="external-link" target="_blank">JSON Schema</a>。
|
||||
|
||||
<small>* 根据对某个构建线上应用的内部开发团队所进行的测试估算得出。</small>
|
||||
|
||||
## 评价
|
||||
|
||||
"*[...] 最近我一直在使用 **FastAPI**。[...] 实际上我正在计划将其用于我所在的微软团队的所有**机器学习服务**。其中一些服务正被集成进 **Windows** 核心产品和一些 **Office** 产品。*"
|
||||
「_[...] 最近我一直在使用 **FastAPI**。[...] 实际上我正在计划将其用于我所在的**微软**团队的所有**机器学习服务**。其中一些服务正被集成进核心 **Windows** 产品和一些 **Office** 产品。_」
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Kabir Khan - <strong>微软</strong> <a href="https://github.com/tiangolo/fastapi/pull/26" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
"***FastAPI** 让我兴奋的欣喜若狂。它太棒了!*"
|
||||
「_我们选择了 **FastAPI** 来创建用于获取**预测结果**的 **REST** 服务。[用于 Ludwig]_」
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Piero Molino,Yaroslav Dudin 和 Sai Sumanth Miryala - <strong>Uber</strong> <a href="https://eng.uber.com/ludwig-v0-2/" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
「_**Netflix** 非常高兴地宣布,正式开源我们的**危机管理**编排框架:**Dispatch**![使用 **FastAPI** 构建]_」
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Kevin Glisson,Marc Vilanova,Forest Monsen - <strong>Netflix</strong> <a href="https://netflixtechblog.com/introducing-dispatch-da4b8a2a8072" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
「_**FastAPI** 让我兴奋的欣喜若狂。它太棒了!_」
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Brian Okken - <strong><a href="https://pythonbytes.fm/episodes/show/123/time-to-right-the-py-wrongs?time_in_sec=855" target="_blank">Python Bytes</a> 播客主持人</strong> <a href="https://twitter.com/brianokken/status/1112220079972728832" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
"*老实说,你的作品看起来非常可靠和优美。在很多方面,这就是我想让 **Hug** 成为的样子 - 看到有人实现了它真的很鼓舞人心。*"
|
||||
「_老实说,你的作品看起来非常可靠和优美。在很多方面,这就是我想让 **Hug** 成为的样子 - 看到有人实现了它真的很鼓舞人心。_」
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Timothy Crosley - <strong><a href="http://www.hug.rest/" target="_blank">Hug</a> 作者</strong> <a href="https://news.ycombinator.com/item?id=19455465" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
"*如果你正打算学习一个**现代框架**用来构建 REST API,来看下 **FastAPI** [...] 它快速、易用且易于学习 [...]*"
|
||||
「_如果你正打算学习一个**现代框架**用来构建 REST API,来看下 **FastAPI** [...] 它快速、易用且易于学习 [...]_」
|
||||
|
||||
"*我们已经将 **API** 服务切换到了 **FastAPI** [...] 我认为你会喜欢它的 [...]*"
|
||||
「_我们已经将 **API** 服务切换到了 **FastAPI** [...] 我认为你会喜欢它的 [...]_」
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Ines Montani - Matthew Honnibal - <strong><a href="https://explosion.ai" target="_blank">Explosion AI</a> 创始人 - <a href="https://spacy.io" target="_blank">spaCy</a> 作者</strong> <a href="https://twitter.com/_inesmontani/status/1144173225322143744" target="_blank"><small>(ref)</small></a> - <a href="https://twitter.com/honnibal/status/1144031421859655680" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
"*我们采用了 **FastAPI** 来创建用于获取**预测结果**的 **REST** 服务。[用于 Ludwig]*"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Piero Molino, Yaroslav Dudin 和 Sai Sumanth Miryala - <strong>Uber</strong> <a href="https://eng.uber.com/ludwig-v0-2/" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
## **Typer**,命令行中的 Fast API
|
||||
## **Typer**,命令行中的 FastAPI
|
||||
|
||||
<a href="https://typer.tiangolo.com" target="_blank"><img src="https://typer.tiangolo.com/img/logo-margin/logo-margin-vector.svg" style="width: 20%;"></a>
|
||||
|
||||
如果你正在开发一个在终端中运行的<abbr title="Command Line Interface">命令行</abbr>应用而不是 web API,不妨试下 <a href="https://typer.tiangolo.com/" class="external-link" target="_blank">**Typer**</a>。
|
||||
|
||||
**Typer** 是 FastAPI 的小伙伴。它打算成为**命令行中的 FastAPI**。 ⌨️ 🚀
|
||||
**Typer** 是 FastAPI 的小同胞。它想要成为**命令行中的 FastAPI**。 ⌨️ 🚀
|
||||
|
||||
## 依赖
|
||||
|
||||
@@ -91,8 +97,8 @@ Python 3.6 及更高版本
|
||||
|
||||
FastAPI 站在以下巨人的肩膀之上:
|
||||
|
||||
* <a href="https://www.starlette.io/" class="external-link" target="_blank">Starlette</a>负责 web 部分。
|
||||
* <a href="https://pydantic-docs.helpmanual.io/" class="external-link" target="_blank">Pydantic</a>负责数据部分。
|
||||
* <a href="https://www.starlette.io/" class="external-link" target="_blank">Starlette</a> 负责 web 部分。
|
||||
* <a href="https://pydantic-docs.helpmanual.io/" class="external-link" target="_blank">Pydantic</a> 负责数据部分。
|
||||
|
||||
## 安装
|
||||
|
||||
@@ -106,7 +112,7 @@ $ pip install fastapi
|
||||
|
||||
</div>
|
||||
|
||||
你还需要一个 ASGI 服务器,生产环境可以使用 <a href="http://www.uvicorn.org" class="external-link" target="_blank">Uvicorn</a> 或者 <a href="https://gitlab.com/pgjones/hypercorn" class="external-link" target="_blank">Hypercorn</a>。
|
||||
你还会需要一个 ASGI 服务器,生产环境可以使用 <a href="http://www.uvicorn.org" class="external-link" target="_blank">Uvicorn</a> 或者 <a href="https://gitlab.com/pgjones/hypercorn" class="external-link" target="_blank">Hypercorn</a>。
|
||||
|
||||
<div class="termy">
|
||||
|
||||
@@ -125,6 +131,8 @@ $ pip install uvicorn
|
||||
* 创建一个 `main.py` 文件并写入以下内容:
|
||||
|
||||
```Python
|
||||
from typing import Optional
|
||||
|
||||
from fastapi import FastAPI
|
||||
|
||||
app = FastAPI()
|
||||
@@ -136,16 +144,18 @@ def read_root():
|
||||
|
||||
|
||||
@app.get("/items/{item_id}")
|
||||
def read_item(item_id: int, q: str = None):
|
||||
def read_item(item_id: int, q: Optional[str] = None):
|
||||
return {"item_id": item_id, "q": q}
|
||||
```
|
||||
|
||||
<details markdown="1">
|
||||
<summary>或者使用 <code>async def</code>...</summary>
|
||||
|
||||
如果你的代码里会出现 `async` / `await`,应使用 `async def`:
|
||||
如果你的代码里会出现 `async` / `await`,请使用 `async def`:
|
||||
|
||||
```Python hl_lines="9 14"
|
||||
from typing import Optional
|
||||
|
||||
```Python hl_lines="7 12"
|
||||
from fastapi import FastAPI
|
||||
|
||||
app = FastAPI()
|
||||
@@ -157,7 +167,7 @@ async def read_root():
|
||||
|
||||
|
||||
@app.get("/items/{item_id}")
|
||||
async def read_item(item_id: int, q: str = None):
|
||||
async def read_item(item_id: int, q: Optional[str] = None):
|
||||
return {"item_id": item_id, "q": q}
|
||||
```
|
||||
|
||||
@@ -176,11 +186,11 @@ async def read_item(item_id: int, q: str = None):
|
||||
```console
|
||||
$ uvicorn main:app --reload
|
||||
|
||||
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
|
||||
<span style="color: green;">INFO</span>: Started reloader process [28720]
|
||||
<span style="color: green;">INFO</span>: Started server process [28722]
|
||||
<span style="color: green;">INFO</span>: Waiting for application startup.
|
||||
<span style="color: green;">INFO</span>: Application startup complete.
|
||||
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
|
||||
INFO: Started reloader process [28720]
|
||||
INFO: Started server process [28722]
|
||||
INFO: Waiting for application startup.
|
||||
INFO: Application startup complete.
|
||||
```
|
||||
|
||||
</div>
|
||||
@@ -221,21 +231,23 @@ $ uvicorn main:app --reload
|
||||
|
||||

|
||||
|
||||
### 备选 API 文档
|
||||
### 可选的 API 文档
|
||||
|
||||
访问 <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a>。
|
||||
|
||||
你会看到另一个自动生成的文档(由 <a href="https://github.com/Rebilly/ReDoc" class="external-link" target="_blank">ReDoc</a>)生成:
|
||||
你会看到另一个自动生成的文档(由 <a href="https://github.com/Rebilly/ReDoc" class="external-link" target="_blank">ReDoc</a> 生成):
|
||||
|
||||

|
||||
|
||||
## 升级示例
|
||||
## 示例升级
|
||||
|
||||
修改 `main.py` 文件来从 `PUT` 请求中接收请求体。
|
||||
现在修改 `main.py` 文件来从 `PUT` 请求中接收请求体。
|
||||
|
||||
我们借助 Pydantic 来使用标准的 Python 类型声明请求体。
|
||||
|
||||
```Python hl_lines="2 7 8 9 10 23 24 25"
|
||||
```Python hl_lines="4 9 10 11 12 25 26 27"
|
||||
from typing import Optional
|
||||
|
||||
from fastapi import FastAPI
|
||||
from pydantic import BaseModel
|
||||
|
||||
@@ -245,7 +257,7 @@ app = FastAPI()
|
||||
class Item(BaseModel):
|
||||
name: str
|
||||
price: float
|
||||
is_offer: bool = None
|
||||
is_offer: Optional[bool] = None
|
||||
|
||||
|
||||
@app.get("/")
|
||||
@@ -254,7 +266,7 @@ def read_root():
|
||||
|
||||
|
||||
@app.get("/items/{item_id}")
|
||||
def read_item(item_id: int, q: str = None):
|
||||
def read_item(item_id: int, q: Optional[str] = None):
|
||||
return {"item_id": item_id, "q": q}
|
||||
|
||||
|
||||
@@ -265,7 +277,7 @@ def update_item(item_id: int, item: Item):
|
||||
|
||||
服务器将会自动重载(因为在上面的步骤中你向 `uvicorn` 命令添加了 `--reload` 选项)。
|
||||
|
||||
### 升级交互式 API 文档
|
||||
### 交互式 API 文档升级
|
||||
|
||||
访问 <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>。
|
||||
|
||||
@@ -273,23 +285,23 @@ def update_item(item_id: int, item: Item):
|
||||
|
||||

|
||||
|
||||
* 点击 "Try it out" 按钮,之后你可以填写参数并直接调用 API:
|
||||
* 点击「Try it out」按钮,之后你可以填写参数并直接调用 API:
|
||||
|
||||

|
||||
|
||||
* 然后点击 "Execute" 按钮,用户界面将会和 API 进行通信,发送参数,获取结果并在屏幕上展示:
|
||||
* 然后点击「Execute」按钮,用户界面将会和 API 进行通信,发送参数,获取结果并在屏幕上展示:
|
||||
|
||||

|
||||
|
||||
### 升级备选文档
|
||||
### 可选文档升级
|
||||
|
||||
访问 <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a>。
|
||||
|
||||
* 备选文档同样会体现新加入的请求参数和请求体:
|
||||
* 可选文档同样会体现新加入的请求参数和请求体:
|
||||
|
||||

|
||||
|
||||
### 回顾
|
||||
### 总结
|
||||
|
||||
总的来说,你就像声明函数的参数类型一样只声明了**一次**请求参数、请求体等的类型。
|
||||
|
||||
@@ -403,7 +415,6 @@ item: Item
|
||||
|
||||
## 性能
|
||||
|
||||
|
||||
独立机构 TechEmpower 所作的基准测试结果显示,基于 Uvicorn 运行的 **FastAPI** 程序是 <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 web 框架之一</a>,仅次于 Starlette 和 Uvicorn 本身(FastAPI 内部使用了它们)。(*)
|
||||
|
||||
想了解更多,请查阅 <a href="https://fastapi.tiangolo.com/benchmarks/" class="internal-link" target="_blank">基准测试</a> 章节。
|
||||
@@ -412,7 +423,7 @@ item: Item
|
||||
|
||||
用于 Pydantic:
|
||||
|
||||
* <a href="https://github.com/esnme/ultrajson" target="_blank"><code>ujson</code></a> - 更快的 JSON <abbr title="将来自 HTTP 请求中的字符串转换为 Python 数据类型">"解析"</abbr>。
|
||||
* <a href="https://github.com/esnme/ultrajson" target="_blank"><code>ujson</code></a> - 更快的 JSON <abbr title="将来自 HTTP 请求中的字符串转换为 Python 数据类型">「解析」</abbr>。
|
||||
* <a href="https://github.com/JoshData/python-email-validator" target="_blank"><code>email_validator</code></a> - 用于 email 校验。
|
||||
|
||||
用于 Starlette:
|
||||
@@ -420,15 +431,15 @@ item: Item
|
||||
* <a href="http://docs.python-requests.org" target="_blank"><code>requests</code></a> - 使用 `TestClient` 时安装。
|
||||
* <a href="https://github.com/Tinche/aiofiles" target="_blank"><code>aiofiles</code></a> - 使用 `FileResponse` 或 `StaticFiles` 时安装。
|
||||
* <a href="http://jinja.pocoo.org" target="_blank"><code>jinja2</code></a> - 使用默认模板配置时安装。
|
||||
* <a href="https://andrew-d.github.io/python-multipart/" target="_blank"><code>python-multipart</code></a> - 需要通过 `request.form()` 对表单进行<abbr title="将来自 HTTP 请求中的字符串转换为 Python 数据类型">"解析"</abbr>时安装。
|
||||
* <a href="https://pythonhosted.org/itsdangerous/" target="_blank"><code>itsdangerous</code></a> - 提供 `SessionMiddleware` 支持。
|
||||
* <a href="https://andrew-d.github.io/python-multipart/" target="_blank"><code>python-multipart</code></a> - 需要通过 `request.form()` 对表单进行<abbr title="将来自 HTTP 请求中的字符串转换为 Python 数据类型">「解析」</abbr>时安装。
|
||||
* <a href="https://pythonhosted.org/itsdangerous/" target="_blank"><code>itsdangerous</code></a> - 需要 `SessionMiddleware` 支持时安装。
|
||||
* <a href="https://pyyaml.org/wiki/PyYAMLDocumentation" target="_blank"><code>pyyaml</code></a> - 使用 Starlette 提供的 `SchemaGenerator` 时安装(有 FastAPI 你可能并不需要它)。
|
||||
* <a href="https://graphene-python.org/" target="_blank"><code>graphene</code></a> - 需要 `GraphQLApp` 支持时安装。
|
||||
* <a href="https://github.com/esnme/ultrajson" target="_blank"><code>ujson</code></a> - 使用 `UJSONResponse` 时安装。
|
||||
|
||||
用于 FastAPI / Starlette:
|
||||
|
||||
* <a href="http://www.uvicorn.org" target="_blank"><code>uvicorn</code></a> - 用于加载和服务你的应用程序的服务器。
|
||||
* <a href="http://www.uvicorn.org" target="_blank"><code>uvicorn</code></a> - 用于加载和运行你的应用程序的服务器。
|
||||
* <a href="https://github.com/ijl/orjson" target="_blank"><code>orjson</code></a> - 使用 `ORJSONResponse` 时安装。
|
||||
|
||||
你可以通过 `pip install fastapi[all]` 命令来安装以上所有依赖。
|
||||
|
||||
48
docs/zh/docs/tutorial/body-fields.md
Normal file
@@ -0,0 +1,48 @@
|
||||
# 请求体 - 字段
|
||||
|
||||
与使用 `Query`、`Path` 和 `Body` 在*路径操作函数*中声明额外的校验和元数据的方式相同,你可以使用 Pydantic 的 `Field` 在 Pydantic 模型内部声明校验和元数据。
|
||||
|
||||
## 导入 `Field`
|
||||
|
||||
首先,你必须导入它:
|
||||
|
||||
```Python hl_lines="2"
|
||||
{!../../../docs_src/body_fields/tutorial001.py!}
|
||||
```
|
||||
|
||||
!!! warning
|
||||
注意,`Field` 是直接从 `pydantic` 导入的,而不是像其他的(`Query`,`Path`,`Body` 等)都从 `fastapi` 导入。
|
||||
|
||||
## 声明模型属性
|
||||
|
||||
然后,你可以对模型属性使用 `Field`:
|
||||
|
||||
```Python hl_lines="9 10"
|
||||
{!../../../docs_src/body_fields/tutorial001.py!}
|
||||
```
|
||||
|
||||
`Field` 的工作方式和 `Query`、`Path` 和 `Body` 相同,包括它们的参数等等也完全相同。
|
||||
|
||||
!!! note "技术细节"
|
||||
实际上,`Query`、`Path` 和其他你将在之后看到的类,创建的是由一个共同的 `Params` 类派生的子类的对象,该共同类本身又是 Pydantic 的 `FieldInfo` 类的子类。
|
||||
|
||||
Pydantic 的 `Field` 也会返回一个 `FieldInfo` 的实例。
|
||||
|
||||
`Body` 也直接返回 `FieldInfo` 的一个子类的对象。还有其他一些你之后会看到的类是 `Body` 类的子类。
|
||||
|
||||
请记住当你从 `fastapi` 导入 `Query`、`Path` 等对象时,他们实际上是返回特殊类的函数。
|
||||
|
||||
!!! tip
|
||||
注意每个模型属性如何使用类型、默认值和 `Field` 在代码结构上和*路径操作函数*的参数是相同的,区别是用 `Field` 替换`Path`、`Query` 和 `Body`。
|
||||
|
||||
## 添加额外信息
|
||||
|
||||
你可以在 `Field`、`Query`、`Body` 中声明额外的信息。这些信息将包含在生成的 JSON Schema 中。
|
||||
|
||||
你将在文档的后面部分学习声明示例时,了解到更多有关添加额外信息的知识。
|
||||
|
||||
## 总结
|
||||
|
||||
你可以使用 Pydantic 的 `Field` 为模型属性声明额外的校验和元数据。
|
||||
|
||||
你还可以使用额外的关键字参数来传递额外的 JSON Schema 元数据。
|
||||
170
docs/zh/docs/tutorial/body-multiple-params.md
Normal file
@@ -0,0 +1,170 @@
|
||||
# 请求体 - 多个参数
|
||||
|
||||
既然我们已经知道了如何使用 `Path` 和 `Query`,下面让我们来了解一下请求体声明的更高级用法。
|
||||
|
||||
## 混合使用 `Path`、`Query` 和请求体参数
|
||||
|
||||
首先,毫无疑问地,你可以随意地混合使用 `Path`、`Query` 和请求体参数声明,**FastAPI** 会知道该如何处理。
|
||||
|
||||
你还可以通过将默认值设置为 `None` 来将请求体参数声明为可选参数:
|
||||
|
||||
```Python hl_lines="17 18 19"
|
||||
{!../../../docs_src/body_multiple_params/tutorial001.py!}
|
||||
```
|
||||
|
||||
!!! note
|
||||
请注意,在这种情况下,将从请求体获取的 `item` 是可选的。因为它的默认值为 `None`。
|
||||
|
||||
## 多个请求体参数
|
||||
|
||||
在上面的示例中,*路径操作*将期望一个具有 `Item` 的属性的 JSON 请求体,就像:
|
||||
|
||||
```JSON
|
||||
{
|
||||
"name": "Foo",
|
||||
"description": "The pretender",
|
||||
"price": 42.0,
|
||||
"tax": 3.2
|
||||
}
|
||||
```
|
||||
|
||||
但是你也可以声明多个请求体参数,例如 `item` 和 `user`:
|
||||
|
||||
```Python hl_lines="20"
|
||||
{!../../../docs_src/body_multiple_params/tutorial002.py!}
|
||||
```
|
||||
|
||||
在这种情况下,**FastAPI** 将注意到该函数中有多个请求体参数(两个 Pydantic 模型参数)。
|
||||
|
||||
因此,它将使用参数名称作为请求体中的键(字段名称),并期望一个类似于以下内容的请求体:
|
||||
|
||||
```JSON
|
||||
{
|
||||
"item": {
|
||||
"name": "Foo",
|
||||
"description": "The pretender",
|
||||
"price": 42.0,
|
||||
"tax": 3.2
|
||||
},
|
||||
"user": {
|
||||
"username": "dave",
|
||||
"full_name": "Dave Grohl"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
!!! note
|
||||
请注意,即使 `item` 的声明方式与之前相同,但现在它被期望通过 `item` 键内嵌在请求体中。
|
||||
|
||||
|
||||
**FastAPI** 将自动对请求中的数据进行转换,因此 `item` 参数将接收指定的内容,`user` 参数也是如此。
|
||||
|
||||
它将执行对复合数据的校验,并且像现在这样为 OpenAPI 模式和自动化文档对其进行记录。
|
||||
|
||||
## 请求体中的单一值
|
||||
|
||||
与使用 `Query` 和 `Path` 为查询参数和路径参数定义额外数据的方式相同,**FastAPI** 提供了一个同等的 `Body`。
|
||||
|
||||
例如,为了扩展先前的模型,你可能决定除了 `item` 和 `user` 之外,还想在同一请求体中具有另一个键 `importance`。
|
||||
|
||||
如果你就按原样声明它,因为它是一个单一值,**FastAPI** 将假定它是一个查询参数。
|
||||
|
||||
但是你可以使用 `Body` 指示 **FastAPI** 将其作为请求体的另一个键进行处理。
|
||||
|
||||
|
||||
```Python hl_lines="21"
|
||||
{!../../../docs_src/body_multiple_params/tutorial003.py!}
|
||||
```
|
||||
|
||||
在这种情况下,**FastAPI** 将期望像这样的请求体:
|
||||
|
||||
|
||||
```JSON
|
||||
{
|
||||
"item": {
|
||||
"name": "Foo",
|
||||
"description": "The pretender",
|
||||
"price": 42.0,
|
||||
"tax": 3.2
|
||||
},
|
||||
"user": {
|
||||
"username": "dave",
|
||||
"full_name": "Dave Grohl"
|
||||
},
|
||||
"importance": 5
|
||||
}
|
||||
```
|
||||
|
||||
同样的,它将转换数据类型,校验,生成文档等。
|
||||
|
||||
## 多个请求体参数和查询参数
|
||||
|
||||
当然,除了请求体参数外,你还可以在任何需要的时候声明额外的查询参数。
|
||||
|
||||
由于默认情况下单一值被解释为查询参数,因此你不必显式地添加 `Query`,你可以仅执行以下操作:
|
||||
|
||||
```Python
|
||||
q: str = None
|
||||
```
|
||||
|
||||
比如:
|
||||
|
||||
```Python hl_lines="25"
|
||||
{!../../../docs_src/body_multiple_params/tutorial004.py!}
|
||||
```
|
||||
|
||||
!!! info
|
||||
`Body` 同样具有与 `Query`、`Path` 以及其他后面将看到的类完全相同的额外校验和元数据参数。
|
||||
|
||||
|
||||
## 嵌入单个请求体参数
|
||||
|
||||
假设你只有一个来自 Pydantic 模型 `Item` 的请求体参数 `item`。
|
||||
|
||||
默认情况下,**FastAPI** 将直接期望这样的请求体。
|
||||
|
||||
但是,如果你希望它期望一个拥有 `item` 键并在值中包含模型内容的 JSON,就像在声明额外的请求体参数时所做的那样,则可以使用一个特殊的 `Body` 参数 `embed`:
|
||||
|
||||
```Python
|
||||
item: Item = Body(..., embed=True)
|
||||
```
|
||||
|
||||
比如:
|
||||
|
||||
```Python hl_lines="15"
|
||||
{!../../../docs_src/body_multiple_params/tutorial005.py!}
|
||||
```
|
||||
|
||||
在这种情况下,**FastAPI** 将期望像这样的请求体:
|
||||
|
||||
```JSON hl_lines="2"
|
||||
{
|
||||
"item": {
|
||||
"name": "Foo",
|
||||
"description": "The pretender",
|
||||
"price": 42.0,
|
||||
"tax": 3.2
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
而不是:
|
||||
|
||||
```JSON
|
||||
{
|
||||
"name": "Foo",
|
||||
"description": "The pretender",
|
||||
"price": 42.0,
|
||||
"tax": 3.2
|
||||
}
|
||||
```
|
||||
|
||||
## 总结
|
||||
|
||||
你可以添加多个请求体参数到*路径操作函数*中,即使一个请求只能有一个请求体。
|
||||
|
||||
但是 **FastAPI** 会处理它,在函数中为你提供正确的数据,并在*路径操作*中校验并记录正确的模式。
|
||||
|
||||
你还可以声明将作为请求体的一部分所接收的单一值。
|
||||
|
||||
你还可以指示 **FastAPI** 在仅声明了一个请求体参数的情况下,将原本的请求体嵌入到一个键中。
|
||||
122
docs/zh/docs/tutorial/path-params-numeric-validations.md
Normal file
@@ -0,0 +1,122 @@
|
||||
# 路径参数和数值校验
|
||||
|
||||
与使用 `Query` 为查询参数声明更多的校验和元数据的方式相同,你也可以使用 `Path` 为路径参数声明相同类型的校验和元数据。
|
||||
|
||||
## 导入 Path
|
||||
|
||||
首先,从 `fastapi` 导入 `Path`:
|
||||
|
||||
```Python hl_lines="1"
|
||||
{!../../../docs_src/path_params_numeric_validations/tutorial001.py!}
|
||||
```
|
||||
|
||||
## 声明元数据
|
||||
|
||||
你可以声明与 `Query` 相同的所有参数。
|
||||
|
||||
例如,要声明路径参数 `item_id`的 `title` 元数据值,你可以输入:
|
||||
|
||||
```Python hl_lines="8"
|
||||
{!../../../docs_src/path_params_numeric_validations/tutorial001.py!}
|
||||
```
|
||||
|
||||
!!! note
|
||||
路径参数总是必需的,因为它必须是路径的一部分。
|
||||
|
||||
所以,你应该在声明时使用 `...` 将其标记为必需参数。
|
||||
|
||||
然而,即使你使用 `None` 声明路径参数或设置一个其他默认值也不会有任何影响,它依然会是必需参数。
|
||||
|
||||
## 按需对参数排序
|
||||
|
||||
假设你想要声明一个必需的 `str` 类型查询参数 `q`。
|
||||
|
||||
而且你不需要为该参数声明任何其他内容,所以实际上你并不需要使用 `Query`。
|
||||
|
||||
但是你仍然需要使用 `Path` 来声明路径参数 `item_id`。
|
||||
|
||||
如果你将带有「默认值」的参数放在没有「默认值」的参数之前,Python 将会报错。
|
||||
|
||||
但是你可以对其重新排序,并将不带默认值的值(查询参数 `q`)放到最前面。
|
||||
|
||||
对 **FastAPI** 来说这无关紧要。它将通过参数的名称、类型和默认值声明(`Query`、`Path` 等)来检测参数,而不在乎参数的顺序。
|
||||
|
||||
因此,你可以将函数声明为:
|
||||
|
||||
```Python hl_lines="8"
|
||||
{!../../../docs_src/path_params_numeric_validations/tutorial002.py!}
|
||||
```
|
||||
|
||||
## 按需对参数排序的技巧
|
||||
|
||||
如果你想不使用 `Query` 声明没有默认值的查询参数 `q`,同时使用 `Path` 声明路径参数 `item_id`,并使它们的顺序与上面不同,Python 对此有一些特殊的语法。
|
||||
|
||||
传递 `*` 作为函数的第一个参数。
|
||||
|
||||
Python 不会对该 `*` 做任何事情,但是它将知道之后的所有参数都应作为关键字参数(键值对),也被称为 <abbr title="来自:K-ey W-ord Arg-uments"><code>kwargs</code></abbr>,来调用。即使它们没有默认值。
|
||||
|
||||
```Python hl_lines="8"
|
||||
{!../../../docs_src/path_params_numeric_validations/tutorial003.py!}
|
||||
```
|
||||
|
||||
## 数值校验:大于等于
|
||||
|
||||
使用 `Query` 和 `Path`(以及你将在后面看到的其他类)可以声明字符串约束,但也可以声明数值约束。
|
||||
|
||||
像下面这样,添加 `ge=1` 后,`item_id` 将必须是一个大于(`g`reater than)或等于(`e`qual)`1` 的整数。
|
||||
|
||||
```Python hl_lines="8"
|
||||
{!../../../docs_src/path_params_numeric_validations/tutorial004.py!}
|
||||
```
|
||||
|
||||
## 数值校验:大于和小于等于
|
||||
|
||||
同样的规则适用于:
|
||||
|
||||
* `gt`:大于(`g`reater `t`han)
|
||||
* `le`:小于等于(`l`ess than or `e`qual)
|
||||
|
||||
```Python hl_lines="9"
|
||||
{!../../../docs_src/path_params_numeric_validations/tutorial005.py!}
|
||||
```
|
||||
|
||||
## 数值校验:浮点数、大于和小于
|
||||
|
||||
数值校验同样适用于 `float` 值。
|
||||
|
||||
能够声明 <abbr title="大于"><code>gt</code></abbr> 而不仅仅是 <abbr title="大于等于"><code>ge</code></abbr> 在这个前提下变得重要起来。例如,你可以要求一个值必须大于 `0`,即使它小于 `1`。
|
||||
|
||||
因此,`0.5` 将是有效值。但是 `0.0`或 `0` 不是。
|
||||
|
||||
对于 <abbr title="less than"><code>lt</code></abbr> 也是一样的。
|
||||
|
||||
```Python hl_lines="11"
|
||||
{!../../../docs_src/path_params_numeric_validations/tutorial006.py!}
|
||||
```
|
||||
|
||||
## 总结
|
||||
|
||||
你能够以与 [查询参数和字符串校验](query-params-str-validations.md){.internal-link target=_blank} 相同的方式使用 `Query`、`Path`(以及其他你还没见过的类)声明元数据和字符串校验。
|
||||
|
||||
而且你还可以声明数值校验:
|
||||
|
||||
* `gt`:大于(`g`reater `t`han)
|
||||
* `ge`:大于等于(`g`reater than or `e`qual)
|
||||
* `lt`:小于(`l`ess `t`han)
|
||||
* `le`:小于等于(`l`ess than or `e`qual)
|
||||
|
||||
!!! info
|
||||
`Query`、`Path` 以及你后面会看到的其他类继承自一个共同的 `Param` 类(不需要直接使用它)。
|
||||
|
||||
而且它们都共享相同的所有你已看到并用于添加额外校验和元数据的参数。
|
||||
|
||||
!!! note "技术细节"
|
||||
当你从 `fastapi` 导入 `Query`、`Path` 和其他同类对象时,它们实际上是函数。
|
||||
|
||||
当被调用时,它们返回同名类的实例。
|
||||
|
||||
如此,你导入 `Query` 这个函数。当你调用它时,它将返回一个同样命名为 `Query` 的类的实例。
|
||||
|
||||
因为使用了这些函数(而不是直接使用类),所以你的编辑器不会标记有关其类型的错误。
|
||||
|
||||
这样,你可以使用常规的编辑器和编码工具,而不必添加自定义配置来忽略这些错误。
|
||||
@@ -4,6 +4,7 @@ site_url: https://fastapi.tiangolo.com/zh/
|
||||
theme:
|
||||
name: material
|
||||
palette:
|
||||
scheme: preference
|
||||
primary: teal
|
||||
accent: amber
|
||||
icon:
|
||||
@@ -17,6 +18,10 @@ edit_uri: ''
|
||||
google_analytics:
|
||||
- UA-133183413-1
|
||||
- auto
|
||||
plugins:
|
||||
- search
|
||||
- markdownextradata:
|
||||
data: data
|
||||
nav:
|
||||
- FastAPI: index.md
|
||||
- Languages:
|
||||
@@ -24,6 +29,8 @@ nav:
|
||||
- es: /es/
|
||||
- it: /it/
|
||||
- pt: /pt/
|
||||
- ru: /ru/
|
||||
- uk: /uk/
|
||||
- zh: /zh/
|
||||
- features.md
|
||||
- python-types.md
|
||||
@@ -34,6 +41,9 @@ nav:
|
||||
- tutorial/query-params.md
|
||||
- tutorial/body.md
|
||||
- tutorial/query-params-str-validations.md
|
||||
- tutorial/path-params-numeric-validations.md
|
||||
- tutorial/body-multiple-params.md
|
||||
- tutorial/body-fields.md
|
||||
- deployment.md
|
||||
- contributing.md
|
||||
- help-fastapi.md
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
from typing import Optional
|
||||
|
||||
from fastapi import FastAPI
|
||||
from fastapi.responses import FileResponse
|
||||
from pydantic import BaseModel
|
||||
@@ -21,7 +23,7 @@ app = FastAPI()
|
||||
}
|
||||
},
|
||||
)
|
||||
async def read_item(item_id: str, img: bool = None):
|
||||
async def read_item(item_id: str, img: Optional[bool] = None):
|
||||
if img:
|
||||
return FileResponse("image.png", media_type="image/png")
|
||||
else:
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
from typing import Optional
|
||||
|
||||
from fastapi import FastAPI
|
||||
from fastapi.responses import FileResponse
|
||||
from pydantic import BaseModel
|
||||
@@ -23,7 +25,7 @@ app = FastAPI()
|
||||
response_model=Item,
|
||||
responses={**responses, 200: {"content": {"image/png": {}}}},
|
||||
)
|
||||
async def read_item(item_id: str, img: bool = None):
|
||||
async def read_item(item_id: str, img: Optional[bool] = None):
|
||||
if img:
|
||||
return FileResponse("image.png", media_type="image/png")
|
||||
else:
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
from typing import Optional
|
||||
|
||||
from fastapi import Body, FastAPI, status
|
||||
from fastapi.responses import JSONResponse
|
||||
|
||||
@@ -7,7 +9,9 @@ items = {"foo": {"name": "Fighters", "size": 6}, "bar": {"name": "Tenders", "siz
|
||||
|
||||
|
||||
@app.put("/items/{item_id}")
|
||||
async def upsert_item(item_id: str, name: str = Body(None), size: int = Body(None)):
|
||||
async def upsert_item(
|
||||
item_id: str, name: Optional[str] = Body(None), size: Optional[int] = Body(None)
|
||||
):
|
||||
if item_id in items:
|
||||
item = items[item_id]
|
||||
item["name"] = name
|
||||
|
||||