Compare commits
431 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
79f52c76cf | ||
|
|
b725e9eb45 | ||
|
|
787e54b096 | ||
|
|
15fd60b29a | ||
|
|
edf6b2d61f | ||
|
|
7eb17fc874 | ||
|
|
7e4bfaf0e9 | ||
|
|
e1d4fc5325 | ||
|
|
faec748ef6 | ||
|
|
afec8c4580 | ||
|
|
8a1f0aa3b6 | ||
|
|
f784644510 | ||
|
|
710a2f745c | ||
|
|
bd230fe473 | ||
|
|
9c5b000956 | ||
|
|
a9f2a25feb | ||
|
|
c00c2d1ecf | ||
|
|
dd7bbae837 | ||
|
|
0a84d48a82 | ||
|
|
e5d0b97dee | ||
|
|
811c3f873f | ||
|
|
662fc81544 | ||
|
|
5e2f2d541d | ||
|
|
8116d8158b | ||
|
|
e6836781d5 | ||
|
|
098088c763 | ||
|
|
4bf9a52043 | ||
|
|
eb6f964ede | ||
|
|
4473a9bcbf | ||
|
|
fdc7c96ece | ||
|
|
a694be81ae | ||
|
|
0abb743e9c | ||
|
|
acda3f06b0 | ||
|
|
3127bc4e05 | ||
|
|
18b24df9c8 | ||
|
|
b27758fe13 | ||
|
|
a0b2006230 | ||
|
|
bd143ffa5a | ||
|
|
77c1988a8b | ||
|
|
26a36f79fa | ||
|
|
97d8d4016b | ||
|
|
246e80512d | ||
|
|
fc6827d68a | ||
|
|
4d91f978d2 | ||
|
|
aabe2c7d66 | ||
|
|
377234ad8e | ||
|
|
38b785813f | ||
|
|
fa7e3c996e | ||
|
|
90120dd6e8 | ||
|
|
36772548b7 | ||
|
|
40bb0c5f36 | ||
|
|
60918d25a1 | ||
|
|
3afce2c4b8 | ||
|
|
9f6f25d54c | ||
|
|
d5b09cd958 | ||
|
|
aece74982d | ||
|
|
2b1e5b9f82 | ||
|
|
43df5d05ed | ||
|
|
eaa49ebd20 | ||
|
|
a6293397bc | ||
|
|
b890bd1dc5 | ||
|
|
3819a11b5f | ||
|
|
4aed0411e9 | ||
|
|
04ac466748 | ||
|
|
d75126a4ce | ||
|
|
c654e8384b | ||
|
|
7c9d0168ff | ||
|
|
e956ba4d4a | ||
|
|
85b32f51ff | ||
|
|
08fabb7b2e | ||
|
|
273b2cd646 | ||
|
|
de1a5125f8 | ||
|
|
da86791224 | ||
|
|
c646eaa6bb | ||
|
|
bf44b428dd | ||
|
|
c2907b189c | ||
|
|
75317d230b | ||
|
|
e662654c49 | ||
|
|
2a67321130 | ||
|
|
8d9d2c0d3f | ||
|
|
dc6a78c357 | ||
|
|
73d1def114 | ||
|
|
3dc74ba29f | ||
|
|
d9d6031db5 | ||
|
|
6135417789 | ||
|
|
6d138f218b | ||
|
|
e10a4375f9 | ||
|
|
3e32eb55f0 | ||
|
|
b3f139c0d9 | ||
|
|
3b4c692534 | ||
|
|
05c859f324 | ||
|
|
48a33b0453 | ||
|
|
70746a7bf0 | ||
|
|
69e3c6e3d3 | ||
|
|
388e5c0c25 | ||
|
|
61db5ebcc2 | ||
|
|
23845979ea | ||
|
|
83f7a36d05 | ||
|
|
462014e296 | ||
|
|
5da5ae5554 | ||
|
|
f3a985cb81 | ||
|
|
22528373bb | ||
|
|
ce0ec06e8a | ||
|
|
10397ddc30 | ||
|
|
6f72a27632 | ||
|
|
2783667f80 | ||
|
|
d8c1d040d4 | ||
|
|
7f037f1bdc | ||
|
|
f31104585f | ||
|
|
5934a75ddd | ||
|
|
650abf091b | ||
|
|
66f18e9282 | ||
|
|
f044f13121 | ||
|
|
0250cfa398 | ||
|
|
f4ce2510f3 | ||
|
|
8f0a604a37 | ||
|
|
0f4c2b6ee0 | ||
|
|
368d314e11 | ||
|
|
4e79cb0be4 | ||
|
|
973595b3cb | ||
|
|
fa779017d2 | ||
|
|
b2e27de2fc | ||
|
|
31a7bfd227 | ||
|
|
47dde41c6c | ||
|
|
413a86998e | ||
|
|
36721d4362 | ||
|
|
c09e950bd2 | ||
|
|
4d208b2b90 | ||
|
|
071c6a17dd | ||
|
|
4ab79c679b | ||
|
|
33be5fc8ba | ||
|
|
a7a353e1f5 | ||
|
|
c153d9b83e | ||
|
|
2875d88ccf | ||
|
|
9e0cca828d | ||
|
|
5dc3ec4a65 | ||
|
|
bda392cba6 | ||
|
|
f22137346a | ||
|
|
f108741a82 | ||
|
|
8433e8efe2 | ||
|
|
e6a1a9e193 | ||
|
|
bbb22813e6 | ||
|
|
f0f8e287ec | ||
|
|
0af6cbe990 | ||
|
|
9e9e068762 | ||
|
|
9fda0149da | ||
|
|
95a713b3e2 | ||
|
|
2da3d62d37 | ||
|
|
7dd2e92d7e | ||
|
|
6d06e13284 | ||
|
|
a2199c545b | ||
|
|
08cbc6c8ff | ||
|
|
f730160037 | ||
|
|
20360c207e | ||
|
|
568a54dff2 | ||
|
|
91cacc9c92 | ||
|
|
b3899333f4 | ||
|
|
6b6a310e54 | ||
|
|
cb2dce03c0 | ||
|
|
7122687f25 | ||
|
|
af6fcf1413 | ||
|
|
cd8b90a5a4 | ||
|
|
c88fb2eef0 | ||
|
|
17781e3596 | ||
|
|
a381642558 | ||
|
|
5828043b69 | ||
|
|
909a81f88a | ||
|
|
faec713e0d | ||
|
|
60addbcdd5 | ||
|
|
a27a1bc53c | ||
|
|
41f291524d | ||
|
|
6b3bc7384e | ||
|
|
561bbfb5d2 | ||
|
|
8ce1c81398 | ||
|
|
cb40e27db2 | ||
|
|
f031973848 | ||
|
|
307d37d85c | ||
|
|
bf290fa5f0 | ||
|
|
26f313d524 | ||
|
|
73021d7261 | ||
|
|
f54fb88ad5 | ||
|
|
b3d2f47bc8 | ||
|
|
52f170b3fe | ||
|
|
9442845ca5 | ||
|
|
fe31b0caae | ||
|
|
d2ca3df033 | ||
|
|
838ea752b2 | ||
|
|
2b49b8c70a | ||
|
|
05b024d61b | ||
|
|
c7742e3c56 | ||
|
|
4f9104ce97 | ||
|
|
07a8f7b5b5 | ||
|
|
f2a28f4b5b | ||
|
|
5a4a61ca67 | ||
|
|
71ac76c3cd | ||
|
|
68dca8f42d | ||
|
|
a38e6f4e2c | ||
|
|
ca26f2274c | ||
|
|
8108cd89bb | ||
|
|
8560151090 | ||
|
|
91805cdf03 | ||
|
|
48cba16578 | ||
|
|
7098e3b150 | ||
|
|
a7cc25eb11 | ||
|
|
d2eb4a71ee | ||
|
|
54eeb3161f | ||
|
|
4fabcfa3ab | ||
|
|
5c29daadcc | ||
|
|
5614b94ccc | ||
|
|
e170c86412 | ||
|
|
180bdf31ac | ||
|
|
1e58a3e44c | ||
|
|
dfe3f614ed | ||
|
|
97c747fe54 | ||
|
|
fdb6c9ccc5 | ||
|
|
4fdcdf341c | ||
|
|
e2a6341c60 | ||
|
|
7046d80a23 | ||
|
|
9f89399f5e | ||
|
|
ed0fe9f369 | ||
|
|
6e9b771abf | ||
|
|
4a93562a3d | ||
|
|
3f478b7733 | ||
|
|
c660d96dce | ||
|
|
6de9f5890d | ||
|
|
a16ecf2f91 | ||
|
|
7a2c5526d4 | ||
|
|
d6b5bc9401 | ||
|
|
e6f8aa8756 | ||
|
|
f0a14a9ab6 | ||
|
|
c3dbf4ef7c | ||
|
|
52dd5924d7 | ||
|
|
a960c42178 | ||
|
|
436b023fe4 | ||
|
|
f1759297c7 | ||
|
|
f1ca8da6e1 | ||
|
|
478f157013 | ||
|
|
5c8b41abf2 | ||
|
|
4236c99b7f | ||
|
|
1a816fd6a0 | ||
|
|
02b7d988ae | ||
|
|
1b70a1cbf6 | ||
|
|
259c55f7cd | ||
|
|
6a05f1774e | ||
|
|
6189aacd0f | ||
|
|
9e6b069c09 | ||
|
|
6ffc8a547f | ||
|
|
51e920e2fc | ||
|
|
c27b9dcf9d | ||
|
|
c7e137c6e0 | ||
|
|
7e4d7fe895 | ||
|
|
2c57ea57bf | ||
|
|
be7d15ce3a | ||
|
|
afc2bb0801 | ||
|
|
313bbe802f | ||
|
|
d550738fa2 | ||
|
|
cc99e23e82 | ||
|
|
dbdcf86a11 | ||
|
|
2434980968 | ||
|
|
ee27f7790f | ||
|
|
d2cc2627ba | ||
|
|
f6a285c13c | ||
|
|
8af0b136b1 | ||
|
|
159a61d2b0 | ||
|
|
94fe5495fa | ||
|
|
8cc3ac1329 | ||
|
|
6b49f67d11 | ||
|
|
9972b76efa | ||
|
|
410da16a14 | ||
|
|
8997f96540 | ||
|
|
b8331b13d7 | ||
|
|
7a3c244c07 | ||
|
|
7a692d2c7b | ||
|
|
b53c443a06 | ||
|
|
7d7289aeb8 | ||
|
|
24b638faf6 | ||
|
|
2561a17225 | ||
|
|
d8cfa8ac87 | ||
|
|
76083559f0 | ||
|
|
df56655361 | ||
|
|
2e67f2fa6d | ||
|
|
ac073b2f5f | ||
|
|
4bcdbc5673 | ||
|
|
97adeca0a4 | ||
|
|
ac99792762 | ||
|
|
d01e0a10d8 | ||
|
|
de0f466ef8 | ||
|
|
77f7447ee8 | ||
|
|
48827eb7fc | ||
|
|
5786d2ef78 | ||
|
|
166088775a | ||
|
|
1052914c20 | ||
|
|
7bdc86b6b4 | ||
|
|
733218f199 | ||
|
|
3fb6d2982f | ||
|
|
b323726d86 | ||
|
|
2db2381b68 | ||
|
|
d31648c82e | ||
|
|
e6c2343691 | ||
|
|
ab0379ee52 | ||
|
|
790fa217f7 | ||
|
|
b892b5e028 | ||
|
|
39eedb31f7 | ||
|
|
8355832c7c | ||
|
|
5821ea8a69 | ||
|
|
3dbdc74366 | ||
|
|
939acef803 | ||
|
|
22a5960d36 | ||
|
|
8c5efe0b4b | ||
|
|
730ded2870 | ||
|
|
1a000d7e5f | ||
|
|
104ee630fc | ||
|
|
ea69c373ac | ||
|
|
9118749128 | ||
|
|
87ad6a46e8 | ||
|
|
75c64b6e4c | ||
|
|
ccd3b97f03 | ||
|
|
074d39fa17 | ||
|
|
f1419322b3 | ||
|
|
b8e6d18385 | ||
|
|
82a1300257 | ||
|
|
13d9de4a49 | ||
|
|
f931dd0717 | ||
|
|
24d2226326 | ||
|
|
0c895f1eaf | ||
|
|
c041c52d91 | ||
|
|
cc9e6b3484 | ||
|
|
dfcc6bc154 | ||
|
|
7e708f7411 | ||
|
|
e09646441d | ||
|
|
1631f981af | ||
|
|
4ce18167e7 | ||
|
|
a676899557 | ||
|
|
b299792ebf | ||
|
|
9fcec3abe9 | ||
|
|
5df00f3ec4 | ||
|
|
20ba6e8b97 | ||
|
|
a42c690496 | ||
|
|
bed0f065fa | ||
|
|
76632fcf24 | ||
|
|
32a010394f | ||
|
|
8d572faa24 | ||
|
|
f495d98fae | ||
|
|
3702cef08d | ||
|
|
9474706ec2 | ||
|
|
e1755f4fa6 | ||
|
|
c75c13c3b0 | ||
|
|
8673e1c127 | ||
|
|
360868fe25 | ||
|
|
b46b3f00bf | ||
|
|
c6e950dc9c | ||
|
|
4e74d40736 | ||
|
|
612d114f3a | ||
|
|
f88ffd1a0b | ||
|
|
cdf0f8a933 | ||
|
|
8650dee4bc | ||
|
|
dca9cc3ec5 | ||
|
|
d6f37b2138 | ||
|
|
5a13f78078 | ||
|
|
d625963cc5 | ||
|
|
142710a0f3 | ||
|
|
47fcacd4d6 | ||
|
|
00104c9259 | ||
|
|
8386e61f17 | ||
|
|
9b7125f66b | ||
|
|
68dc9bd5ac | ||
|
|
7a02d862aa | ||
|
|
479e87e467 | ||
|
|
1ea24e1813 | ||
|
|
492c0924c4 | ||
|
|
048355f01d | ||
|
|
fe889f38e8 | ||
|
|
1dd2bc7675 | ||
|
|
91ffa0ed27 | ||
|
|
6ab0f89858 | ||
|
|
bfc9733660 | ||
|
|
9c00618710 | ||
|
|
beedd199e8 | ||
|
|
ae580deaea | ||
|
|
e1231eeef1 | ||
|
|
8a1ebb38e2 | ||
|
|
e9413f2711 | ||
|
|
7434d2bec7 | ||
|
|
f2c565d8e4 | ||
|
|
cb55d7cdde | ||
|
|
d513680005 | ||
|
|
a5ee4d93d2 | ||
|
|
3a2d4434ce | ||
|
|
d1dfc812f1 | ||
|
|
0b76b675db | ||
|
|
5a776fbff5 | ||
|
|
7667605520 | ||
|
|
642762564d | ||
|
|
78ead585f8 | ||
|
|
48bf243050 | ||
|
|
0e920e6f02 | ||
|
|
afac22dfd2 | ||
|
|
2836e10e2d | ||
|
|
aa62d9212f | ||
|
|
620bffc2b4 | ||
|
|
b56cf6c08f | ||
|
|
cead6ba887 | ||
|
|
23772f3c49 | ||
|
|
45304562a6 | ||
|
|
3d767008df | ||
|
|
5c6811c4ef | ||
|
|
25e1a2602d | ||
|
|
b6272a36af | ||
|
|
db91255ede | ||
|
|
ab52e1c7e4 | ||
|
|
4924d08e7e | ||
|
|
a7c65271ac | ||
|
|
030f1f2ae2 | ||
|
|
74f13e522b | ||
|
|
a4f88f74f2 | ||
|
|
3826129b16 | ||
|
|
636f06cd6b | ||
|
|
c8365bd339 | ||
|
|
df38e53723 | ||
|
|
c606407929 | ||
|
|
f59f85d755 | ||
|
|
42bb15de22 | ||
|
|
e96b002599 | ||
|
|
75b83ce3aa | ||
|
|
ad5aa33864 | ||
|
|
952cd736ac | ||
|
|
026039cae2 | ||
|
|
e2609dff95 | ||
|
|
8486b41349 | ||
|
|
1701930c86 | ||
|
|
9cc4428de3 |
1
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@@ -0,0 +1 @@
|
||||
blank_issues_enabled: false
|
||||
@@ -1,6 +1,6 @@
|
||||
FROM python:3.7
|
||||
|
||||
RUN pip install httpx "pydantic==1.5.1"
|
||||
RUN pip install httpx "pydantic==1.5.1" pygithub
|
||||
|
||||
COPY ./app /app
|
||||
|
||||
13
.github/actions/comment-docs-preview-in-pr/action.yml
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
name: Comment Docs Preview in PR
|
||||
description: Comment with the docs URL preview in the PR
|
||||
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
|
||||
deploy_url:
|
||||
description: The deployment URL to comment in the PR
|
||||
required: true
|
||||
runs:
|
||||
using: docker
|
||||
image: Dockerfile
|
||||
70
.github/actions/comment-docs-preview-in-pr/app/main.py
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
import logging
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from typing import Optional
|
||||
|
||||
import httpx
|
||||
from github import Github
|
||||
from github.PullRequest import PullRequest
|
||||
from pydantic import BaseModel, BaseSettings, SecretStr, ValidationError
|
||||
|
||||
github_api = "https://api.github.com"
|
||||
|
||||
|
||||
class Settings(BaseSettings):
|
||||
github_repository: str
|
||||
github_event_path: Path
|
||||
github_event_name: Optional[str] = None
|
||||
input_token: SecretStr
|
||||
input_deploy_url: str
|
||||
|
||||
|
||||
class PartialGithubEventHeadCommit(BaseModel):
|
||||
id: str
|
||||
|
||||
|
||||
class PartialGithubEventWorkflowRun(BaseModel):
|
||||
head_commit: PartialGithubEventHeadCommit
|
||||
|
||||
|
||||
class PartialGithubEvent(BaseModel):
|
||||
workflow_run: PartialGithubEventWorkflowRun
|
||||
|
||||
|
||||
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)
|
||||
try:
|
||||
event = PartialGithubEvent.parse_file(settings.github_event_path)
|
||||
except ValidationError as e:
|
||||
logging.error(f"Error parsing event file: {e.errors()}")
|
||||
sys.exit(0)
|
||||
use_pr: Optional[PullRequest] = None
|
||||
for pr in repo.get_pulls():
|
||||
if pr.head.sha == event.workflow_run.head_commit.id:
|
||||
use_pr = pr
|
||||
break
|
||||
if not use_pr:
|
||||
logging.error(
|
||||
f"No PR found for hash: {event.workflow_run.head_commit.id}"
|
||||
)
|
||||
sys.exit(0)
|
||||
github_headers = {
|
||||
"Authorization": f"token {settings.input_token.get_secret_value()}"
|
||||
}
|
||||
url = f"{github_api}/repos/{settings.github_repository}/issues/{use_pr.number}/comments"
|
||||
logging.info(f"Using comments URL: {url}")
|
||||
response = httpx.post(
|
||||
url,
|
||||
headers=github_headers,
|
||||
json={
|
||||
"body": f"📝 Docs preview for commit {use_pr.head.sha} at: {settings.input_deploy_url}"
|
||||
},
|
||||
)
|
||||
if not (200 <= response.status_code <= 300):
|
||||
logging.error(f"Error posting comment: {response.text}")
|
||||
sys.exit(1)
|
||||
logging.info("Finished")
|
||||
16
.github/actions/get-artifact/action.yml
vendored
@@ -1,16 +0,0 @@
|
||||
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
@@ -1,63 +0,0 @@
|
||||
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/people/Dockerfile
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
FROM python:3.7
|
||||
|
||||
RUN pip install httpx PyGithub "pydantic==1.5.1" "pyyaml>=5.3.1,<6.0.0"
|
||||
|
||||
COPY ./app /app
|
||||
|
||||
CMD ["python", "/app/main.py"]
|
||||
13
.github/actions/people/action.yml
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
name: "Generate FastAPI People"
|
||||
description: "Generate the data for the FastAPI People page"
|
||||
author: "Sebastián Ramírez <tiangolo@gmail.com>"
|
||||
inputs:
|
||||
token:
|
||||
description: 'User token, to read the GitHub API. Can be passed in using {{ secrets.ACTION_TOKEN }}'
|
||||
required: true
|
||||
standard_token:
|
||||
description: 'Default GitHub Action token, used for the PR. Can be passed in using {{ secrets.GITHUB_TOKEN }}'
|
||||
required: true
|
||||
runs:
|
||||
using: 'docker'
|
||||
image: 'Dockerfile'
|
||||
529
.github/actions/people/app/main.py
vendored
Normal file
@@ -0,0 +1,529 @@
|
||||
import logging
|
||||
import subprocess
|
||||
import sys
|
||||
from collections import Counter, defaultdict
|
||||
from datetime import datetime, timedelta, timezone
|
||||
from pathlib import Path
|
||||
from typing import Container, DefaultDict, Dict, List, Optional, Set
|
||||
|
||||
import httpx
|
||||
import yaml
|
||||
from github import Github
|
||||
from pydantic import BaseModel, BaseSettings, SecretStr
|
||||
|
||||
github_graphql_url = "https://api.github.com/graphql"
|
||||
|
||||
issues_query = """
|
||||
query Q($after: String) {
|
||||
repository(name: "fastapi", owner: "tiangolo") {
|
||||
issues(first: 100, after: $after) {
|
||||
edges {
|
||||
cursor
|
||||
node {
|
||||
number
|
||||
author {
|
||||
login
|
||||
avatarUrl
|
||||
url
|
||||
}
|
||||
title
|
||||
createdAt
|
||||
state
|
||||
comments(first: 100) {
|
||||
nodes {
|
||||
createdAt
|
||||
author {
|
||||
login
|
||||
avatarUrl
|
||||
url
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
"""
|
||||
|
||||
prs_query = """
|
||||
query Q($after: String) {
|
||||
repository(name: "fastapi", owner: "tiangolo") {
|
||||
pullRequests(first: 100, after: $after) {
|
||||
edges {
|
||||
cursor
|
||||
node {
|
||||
number
|
||||
labels(first: 100) {
|
||||
nodes {
|
||||
name
|
||||
}
|
||||
}
|
||||
author {
|
||||
login
|
||||
avatarUrl
|
||||
url
|
||||
}
|
||||
title
|
||||
createdAt
|
||||
state
|
||||
comments(first: 100) {
|
||||
nodes {
|
||||
createdAt
|
||||
author {
|
||||
login
|
||||
avatarUrl
|
||||
url
|
||||
}
|
||||
}
|
||||
}
|
||||
reviews(first:100) {
|
||||
nodes {
|
||||
author {
|
||||
login
|
||||
avatarUrl
|
||||
url
|
||||
}
|
||||
state
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
"""
|
||||
|
||||
sponsors_query = """
|
||||
query Q($after: String) {
|
||||
user(login: "tiangolo") {
|
||||
sponsorshipsAsMaintainer(first: 100, after: $after) {
|
||||
edges {
|
||||
cursor
|
||||
node {
|
||||
sponsorEntity {
|
||||
... on Organization {
|
||||
login
|
||||
avatarUrl
|
||||
url
|
||||
}
|
||||
... on User {
|
||||
login
|
||||
avatarUrl
|
||||
url
|
||||
}
|
||||
}
|
||||
tier {
|
||||
name
|
||||
monthlyPriceInDollars
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
"""
|
||||
|
||||
|
||||
class Author(BaseModel):
|
||||
login: str
|
||||
avatarUrl: str
|
||||
url: str
|
||||
|
||||
|
||||
class CommentsNode(BaseModel):
|
||||
createdAt: datetime
|
||||
author: Optional[Author] = None
|
||||
|
||||
|
||||
class Comments(BaseModel):
|
||||
nodes: List[CommentsNode]
|
||||
|
||||
|
||||
class IssuesNode(BaseModel):
|
||||
number: int
|
||||
author: Optional[Author] = None
|
||||
title: str
|
||||
createdAt: datetime
|
||||
state: str
|
||||
comments: Comments
|
||||
|
||||
|
||||
class IssuesEdge(BaseModel):
|
||||
cursor: str
|
||||
node: IssuesNode
|
||||
|
||||
|
||||
class Issues(BaseModel):
|
||||
edges: List[IssuesEdge]
|
||||
|
||||
|
||||
class IssuesRepository(BaseModel):
|
||||
issues: Issues
|
||||
|
||||
|
||||
class IssuesResponseData(BaseModel):
|
||||
repository: IssuesRepository
|
||||
|
||||
|
||||
class IssuesResponse(BaseModel):
|
||||
data: IssuesResponseData
|
||||
|
||||
|
||||
class LabelNode(BaseModel):
|
||||
name: str
|
||||
|
||||
|
||||
class Labels(BaseModel):
|
||||
nodes: List[LabelNode]
|
||||
|
||||
|
||||
class ReviewNode(BaseModel):
|
||||
author: Optional[Author] = None
|
||||
state: str
|
||||
|
||||
|
||||
class Reviews(BaseModel):
|
||||
nodes: List[ReviewNode]
|
||||
|
||||
|
||||
class PullRequestNode(BaseModel):
|
||||
number: int
|
||||
labels: Labels
|
||||
author: Optional[Author] = None
|
||||
title: str
|
||||
createdAt: datetime
|
||||
state: str
|
||||
comments: Comments
|
||||
reviews: Reviews
|
||||
|
||||
|
||||
class PullRequestEdge(BaseModel):
|
||||
cursor: str
|
||||
node: PullRequestNode
|
||||
|
||||
|
||||
class PullRequests(BaseModel):
|
||||
edges: List[PullRequestEdge]
|
||||
|
||||
|
||||
class PRsRepository(BaseModel):
|
||||
pullRequests: PullRequests
|
||||
|
||||
|
||||
class PRsResponseData(BaseModel):
|
||||
repository: PRsRepository
|
||||
|
||||
|
||||
class PRsResponse(BaseModel):
|
||||
data: PRsResponseData
|
||||
|
||||
|
||||
class SponsorEntity(BaseModel):
|
||||
login: str
|
||||
avatarUrl: str
|
||||
url: str
|
||||
|
||||
|
||||
class Tier(BaseModel):
|
||||
name: str
|
||||
monthlyPriceInDollars: float
|
||||
|
||||
|
||||
class SponsorshipAsMaintainerNode(BaseModel):
|
||||
sponsorEntity: SponsorEntity
|
||||
tier: Tier
|
||||
|
||||
|
||||
class SponsorshipAsMaintainerEdge(BaseModel):
|
||||
cursor: str
|
||||
node: SponsorshipAsMaintainerNode
|
||||
|
||||
|
||||
class SponsorshipAsMaintainer(BaseModel):
|
||||
edges: List[SponsorshipAsMaintainerEdge]
|
||||
|
||||
|
||||
class SponsorsUser(BaseModel):
|
||||
sponsorshipsAsMaintainer: SponsorshipAsMaintainer
|
||||
|
||||
|
||||
class SponsorsResponseData(BaseModel):
|
||||
user: SponsorsUser
|
||||
|
||||
|
||||
class SponsorsResponse(BaseModel):
|
||||
data: SponsorsResponseData
|
||||
|
||||
|
||||
class Settings(BaseSettings):
|
||||
input_token: SecretStr
|
||||
input_standard_token: SecretStr
|
||||
github_repository: str
|
||||
|
||||
|
||||
def get_graphql_response(
|
||||
*, settings: Settings, query: str, after: Optional[str] = None
|
||||
):
|
||||
headers = {"Authorization": f"token {settings.input_token.get_secret_value()}"}
|
||||
variables = {"after": after}
|
||||
response = httpx.post(
|
||||
github_graphql_url,
|
||||
headers=headers,
|
||||
json={"query": query, "variables": variables, "operationName": "Q"},
|
||||
)
|
||||
if not response.status_code == 200:
|
||||
logging.error(f"Response was not 200, after: {after}")
|
||||
logging.error(response.text)
|
||||
raise RuntimeError(response.text)
|
||||
data = response.json()
|
||||
return data
|
||||
|
||||
|
||||
def get_graphql_issue_edges(*, settings: Settings, after: Optional[str] = None):
|
||||
data = get_graphql_response(settings=settings, query=issues_query, after=after)
|
||||
graphql_response = IssuesResponse.parse_obj(data)
|
||||
return graphql_response.data.repository.issues.edges
|
||||
|
||||
|
||||
def get_graphql_pr_edges(*, settings: Settings, after: Optional[str] = None):
|
||||
data = get_graphql_response(settings=settings, query=prs_query, after=after)
|
||||
graphql_response = PRsResponse.parse_obj(data)
|
||||
return graphql_response.data.repository.pullRequests.edges
|
||||
|
||||
|
||||
def get_graphql_sponsor_edges(*, settings: Settings, after: Optional[str] = None):
|
||||
data = get_graphql_response(settings=settings, query=sponsors_query, after=after)
|
||||
graphql_response = SponsorsResponse.parse_obj(data)
|
||||
return graphql_response.data.user.sponsorshipsAsMaintainer.edges
|
||||
|
||||
|
||||
def get_experts(settings: Settings):
|
||||
issue_nodes: List[IssuesNode] = []
|
||||
issue_edges = get_graphql_issue_edges(settings=settings)
|
||||
|
||||
while issue_edges:
|
||||
for edge in issue_edges:
|
||||
issue_nodes.append(edge.node)
|
||||
last_edge = issue_edges[-1]
|
||||
issue_edges = get_graphql_issue_edges(settings=settings, after=last_edge.cursor)
|
||||
|
||||
commentors = Counter()
|
||||
last_month_commentors = Counter()
|
||||
authors: Dict[str, Author] = {}
|
||||
|
||||
now = datetime.now(tz=timezone.utc)
|
||||
one_month_ago = now - timedelta(days=30)
|
||||
|
||||
for issue in issue_nodes:
|
||||
issue_author_name = None
|
||||
if issue.author:
|
||||
authors[issue.author.login] = issue.author
|
||||
issue_author_name = issue.author.login
|
||||
issue_commentors = set()
|
||||
for comment in issue.comments.nodes:
|
||||
if comment.author:
|
||||
authors[comment.author.login] = comment.author
|
||||
if comment.author.login == issue_author_name:
|
||||
continue
|
||||
issue_commentors.add(comment.author.login)
|
||||
for author_name in issue_commentors:
|
||||
commentors[author_name] += 1
|
||||
if issue.createdAt > one_month_ago:
|
||||
last_month_commentors[author_name] += 1
|
||||
return commentors, last_month_commentors, authors
|
||||
|
||||
|
||||
def get_contributors(settings: Settings):
|
||||
pr_nodes: List[PullRequestNode] = []
|
||||
pr_edges = get_graphql_pr_edges(settings=settings)
|
||||
|
||||
while pr_edges:
|
||||
for edge in pr_edges:
|
||||
pr_nodes.append(edge.node)
|
||||
last_edge = pr_edges[-1]
|
||||
pr_edges = get_graphql_pr_edges(settings=settings, after=last_edge.cursor)
|
||||
|
||||
contributors = Counter()
|
||||
commentors = Counter()
|
||||
reviewers = Counter()
|
||||
authors: Dict[str, Author] = {}
|
||||
|
||||
for pr in pr_nodes:
|
||||
author_name = None
|
||||
if pr.author:
|
||||
authors[pr.author.login] = pr.author
|
||||
author_name = pr.author.login
|
||||
pr_commentors: Set[str] = set()
|
||||
pr_reviewers: Set[str] = set()
|
||||
for comment in pr.comments.nodes:
|
||||
if comment.author:
|
||||
authors[comment.author.login] = comment.author
|
||||
if comment.author.login == author_name:
|
||||
continue
|
||||
pr_commentors.add(comment.author.login)
|
||||
for author_name in pr_commentors:
|
||||
commentors[author_name] += 1
|
||||
for review in pr.reviews.nodes:
|
||||
if review.author:
|
||||
authors[review.author.login] = review.author
|
||||
pr_reviewers.add(review.author.login)
|
||||
for reviewer in pr_reviewers:
|
||||
reviewers[reviewer] += 1
|
||||
if pr.state == "MERGED" and pr.author:
|
||||
contributors[pr.author.login] += 1
|
||||
return contributors, commentors, reviewers, authors
|
||||
|
||||
|
||||
def get_individual_sponsors(settings: Settings):
|
||||
nodes: List[SponsorshipAsMaintainerNode] = []
|
||||
edges = get_graphql_sponsor_edges(settings=settings)
|
||||
|
||||
while edges:
|
||||
for edge in edges:
|
||||
nodes.append(edge.node)
|
||||
last_edge = edges[-1]
|
||||
edges = get_graphql_sponsor_edges(settings=settings, after=last_edge.cursor)
|
||||
|
||||
tiers: DefaultDict[float, Dict[str, SponsorEntity]] = defaultdict(dict)
|
||||
for node in nodes:
|
||||
tiers[node.tier.monthlyPriceInDollars][
|
||||
node.sponsorEntity.login
|
||||
] = node.sponsorEntity
|
||||
return tiers
|
||||
|
||||
|
||||
def get_top_users(
|
||||
*,
|
||||
counter: Counter,
|
||||
min_count: int,
|
||||
authors: Dict[str, Author],
|
||||
skip_users: Container[str],
|
||||
):
|
||||
users = []
|
||||
for commentor, count in counter.most_common(50):
|
||||
if commentor in skip_users:
|
||||
continue
|
||||
if count >= min_count:
|
||||
author = authors[commentor]
|
||||
users.append(
|
||||
{
|
||||
"login": commentor,
|
||||
"count": count,
|
||||
"avatarUrl": author.avatarUrl,
|
||||
"url": author.url,
|
||||
}
|
||||
)
|
||||
return users
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
settings = Settings()
|
||||
logging.info(f"Using config: {settings.json()}")
|
||||
g = Github(settings.input_standard_token.get_secret_value())
|
||||
repo = g.get_repo(settings.github_repository)
|
||||
issue_commentors, issue_last_month_commentors, issue_authors = get_experts(
|
||||
settings=settings
|
||||
)
|
||||
contributors, pr_commentors, reviewers, pr_authors = get_contributors(
|
||||
settings=settings
|
||||
)
|
||||
authors = {**issue_authors, **pr_authors}
|
||||
maintainers_logins = {"tiangolo"}
|
||||
bot_names = {"codecov", "github-actions"}
|
||||
maintainers = []
|
||||
for login in maintainers_logins:
|
||||
user = authors[login]
|
||||
maintainers.append(
|
||||
{
|
||||
"login": login,
|
||||
"answers": issue_commentors[login],
|
||||
"prs": contributors[login],
|
||||
"avatarUrl": user.avatarUrl,
|
||||
"url": user.url,
|
||||
}
|
||||
)
|
||||
|
||||
min_count_expert = 10
|
||||
min_count_last_month = 3
|
||||
min_count_contributor = 4
|
||||
min_count_reviewer = 4
|
||||
skip_users = maintainers_logins | bot_names
|
||||
experts = get_top_users(
|
||||
counter=issue_commentors,
|
||||
min_count=min_count_expert,
|
||||
authors=authors,
|
||||
skip_users=skip_users,
|
||||
)
|
||||
last_month_active = get_top_users(
|
||||
counter=issue_last_month_commentors,
|
||||
min_count=min_count_last_month,
|
||||
authors=authors,
|
||||
skip_users=skip_users,
|
||||
)
|
||||
top_contributors = get_top_users(
|
||||
counter=contributors,
|
||||
min_count=min_count_contributor,
|
||||
authors=authors,
|
||||
skip_users=skip_users,
|
||||
)
|
||||
top_reviewers = get_top_users(
|
||||
counter=reviewers,
|
||||
min_count=min_count_reviewer,
|
||||
authors=authors,
|
||||
skip_users=skip_users,
|
||||
)
|
||||
|
||||
tiers = get_individual_sponsors(settings=settings)
|
||||
sponsors_50 = []
|
||||
for login, sponsor in tiers[50].items():
|
||||
sponsors_50.append(
|
||||
{"login": login, "avatarUrl": sponsor.avatarUrl, "url": sponsor.url}
|
||||
)
|
||||
keys = list(tiers.keys())
|
||||
keys.sort(reverse=True)
|
||||
sponsors = []
|
||||
for key in keys:
|
||||
if key >= 50:
|
||||
continue
|
||||
for login, sponsor in tiers[key].items():
|
||||
sponsors.append(
|
||||
{"login": login, "avatarUrl": sponsor.avatarUrl, "url": sponsor.url}
|
||||
)
|
||||
|
||||
people = {
|
||||
"maintainers": maintainers,
|
||||
"experts": experts,
|
||||
"last_month_active": last_month_active,
|
||||
"top_contributors": top_contributors,
|
||||
"top_reviewers": top_reviewers,
|
||||
"sponsors_50": sponsors_50,
|
||||
"sponsors": sponsors,
|
||||
}
|
||||
people_path = Path("./docs/en/data/people.yml")
|
||||
people_old_content = people_path.read_text(encoding="utf-8")
|
||||
new_content = yaml.dump(people, sort_keys=False, width=200, allow_unicode=True)
|
||||
if people_old_content == new_content:
|
||||
logging.info("The FastAPI People data hasn't changed, finishing.")
|
||||
sys.exit(0)
|
||||
people_path.write_text(new_content, encoding="utf-8")
|
||||
logging.info("Setting up GitHub Actions git user")
|
||||
subprocess.run(["git", "config", "user.name", "github-actions"], check=True)
|
||||
subprocess.run(
|
||||
["git", "config", "user.email", "github-actions@github.com"], check=True
|
||||
)
|
||||
branch_name = "fastapi-people"
|
||||
logging.info(f"Creating a new branch {branch_name}")
|
||||
subprocess.run(["git", "checkout", "-b", branch_name], check=True)
|
||||
logging.info("Adding updated file")
|
||||
subprocess.run(["git", "add", str(people_path)], check=True)
|
||||
logging.info("Committing updated file")
|
||||
message = "👥 Update FastAPI People"
|
||||
result = subprocess.run(["git", "commit", "-m", message], check=True)
|
||||
logging.info("Pushing branch")
|
||||
subprocess.run(["git", "push", "origin", branch_name], check=True)
|
||||
logging.info("Creating PR")
|
||||
pr = repo.create_pull(title=message, body=message, base="master", head=branch_name)
|
||||
logging.info(f"Created PR: {pr.number}")
|
||||
logging.info("Finished")
|
||||
18
.github/workflows/build-docs.yml
vendored
@@ -13,22 +13,30 @@ jobs:
|
||||
run: echo "$GITHUB_CONTEXT"
|
||||
- uses: actions/checkout@v2
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v1
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: "3.7"
|
||||
- uses: actions/cache@v2
|
||||
id: cache
|
||||
with:
|
||||
path: ${{ env.pythonLocation }}
|
||||
key: ${{ runner.os }}-python-${{ env.pythonLocation }}-${{ hashFiles('pyproject.toml') }}-docs
|
||||
- name: Install Flit
|
||||
if: steps.cache.outputs.cache-hit != 'true'
|
||||
run: python3.7 -m pip install flit
|
||||
- name: Install docs extras
|
||||
run: python3.7 -m flit install --extras doc
|
||||
if: steps.cache.outputs.cache-hit != 'true'
|
||||
run: python3.7 -m flit install --deps production --extras doc
|
||||
- name: Install Material for MkDocs Insiders
|
||||
if: github.event.pull_request.head.repo.fork == false && steps.cache.outputs.cache-hit != 'true'
|
||||
run: pip install git+https://${{ secrets.ACTIONS_TOKEN }}@github.com/squidfunk/mkdocs-material-insiders.git
|
||||
- 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 }}
|
||||
name: docs-zip
|
||||
path: ./docs.zip
|
||||
- name: Deploy to Netlify
|
||||
uses: nwtgck/actions-netlify@v1.1.5
|
||||
|
||||
10
.github/workflows/issue-manager.yml
vendored
@@ -6,23 +6,25 @@ on:
|
||||
issue_comment:
|
||||
types:
|
||||
- created
|
||||
- edited
|
||||
issues:
|
||||
types:
|
||||
- labeled
|
||||
pull_request_target:
|
||||
types:
|
||||
- labeled
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
issue-manager:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: tiangolo/issue-manager@0.2.0
|
||||
- uses: tiangolo/issue-manager@0.4.0
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
config: >
|
||||
{
|
||||
"answered": {
|
||||
"users": ["tiangolo", "dmontagu"],
|
||||
"delay": 864000,
|
||||
"message": "Assuming the original issue was solved, it will be automatically closed now. But feel free to add more comments or create new issues."
|
||||
"message": "Assuming the original need was handled, this will be automatically closed now. But feel free to add more comments or create new issues or PRs."
|
||||
}
|
||||
}
|
||||
|
||||
13
.github/workflows/label-approved.yml
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
name: Label Approved
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0 12 * * *"
|
||||
|
||||
jobs:
|
||||
label-approved:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: docker://tiangolo/label-approved:0.0.2
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
25
.github/workflows/latest-changes.yml
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
name: Latest Changes
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
branches:
|
||||
- master
|
||||
types:
|
||||
- closed
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
number:
|
||||
description: PR number
|
||||
required: true
|
||||
|
||||
jobs:
|
||||
latest-changes:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: docker://tiangolo/latest-changes:0.0.3
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
latest_changes_file: docs/en/docs/release-notes.md
|
||||
latest_changes_header: '## Latest Changes\n\n'
|
||||
debug_logs: true
|
||||
29
.github/workflows/people.yml
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
name: FastAPI People
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0 14 1 * *"
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
debug_enabled:
|
||||
description: 'Run the build with tmate debugging enabled (https://github.com/marketplace/actions/debugging-with-tmate)'
|
||||
required: false
|
||||
default: false
|
||||
|
||||
jobs:
|
||||
fastapi-people:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
# Allow debugging with tmate
|
||||
- name: Setup tmate session
|
||||
uses: mxschmitt/action-tmate@v3
|
||||
if: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.debug_enabled }}
|
||||
with:
|
||||
limit-access-to-actor: true
|
||||
token: ${{ secrets.ACTIONS_TOKEN }}
|
||||
standard_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
- uses: ./.github/actions/people
|
||||
with:
|
||||
token: ${{ secrets.ACTIONS_TOKEN }}
|
||||
standard_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
14
.github/workflows/pr-approvals.yml
vendored
@@ -1,14 +0,0 @@
|
||||
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"
|
||||
43
.github/workflows/preview-docs.yml
vendored
@@ -1,29 +1,28 @@
|
||||
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
|
||||
workflow_run:
|
||||
workflows:
|
||||
- Build Docs
|
||||
types:
|
||||
- completed
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
runs-on: ubuntu-18.04
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: ./.github/actions/get-artifact
|
||||
- name: Download Artifact Docs
|
||||
uses: dawidd6/action-download-artifact@v2.9.0
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
name: ${{ github.event.inputs.name }}
|
||||
path: ./archive.zip
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
workflow: build-docs.yml
|
||||
run_id: ${{ github.event.workflow_run.id }}
|
||||
name: docs-zip
|
||||
- name: Unzip docs
|
||||
run: bash ./scripts/unzip-docs.sh
|
||||
run: |
|
||||
rm -rf ./site
|
||||
unzip docs.zip
|
||||
rm -f docs.zip
|
||||
- name: Deploy to Netlify
|
||||
id: netlify
|
||||
uses: nwtgck/actions-netlify@v1.1.5
|
||||
@@ -36,9 +35,7 @@ jobs:
|
||||
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
|
||||
uses: ./.github/actions/comment-docs-preview-in-pr
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
deploy_url: "${{ steps.netlify.outputs.deploy-url }}"
|
||||
|
||||
9
.github/workflows/publish.yml
vendored
@@ -15,12 +15,19 @@ jobs:
|
||||
run: echo "$GITHUB_CONTEXT"
|
||||
- uses: actions/checkout@v2
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v1
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: "3.6"
|
||||
- uses: actions/cache@v2
|
||||
id: cache
|
||||
with:
|
||||
path: ${{ env.pythonLocation }}
|
||||
key: ${{ runner.os }}-python-${{ env.pythonLocation }}-${{ hashFiles('pyproject.toml') }}-publish
|
||||
- name: Install Flit
|
||||
if: steps.cache.outputs.cache-hit != 'true'
|
||||
run: pip install flit
|
||||
- name: Install Dependencies
|
||||
if: steps.cache.outputs.cache-hit != 'true'
|
||||
run: flit install --symlink
|
||||
- name: Publish
|
||||
env:
|
||||
|
||||
9
.github/workflows/test.yml
vendored
@@ -16,12 +16,19 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v1
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
- uses: actions/cache@v2
|
||||
id: cache
|
||||
with:
|
||||
path: ${{ env.pythonLocation }}
|
||||
key: ${{ runner.os }}-python-${{ env.pythonLocation }}-${{ hashFiles('pyproject.toml') }}-test
|
||||
- name: Install Flit
|
||||
if: steps.cache.outputs.cache-hit != 'true'
|
||||
run: pip install flit
|
||||
- name: Install Dependencies
|
||||
if: steps.cache.outputs.cache-hit != 'true'
|
||||
run: flit install --symlink
|
||||
- name: Test
|
||||
run: bash scripts/test.sh
|
||||
|
||||
13
.github/workflows/watch-docs-previews.yml
vendored
@@ -1,13 +0,0 @@
|
||||
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 }}
|
||||
31
README.md
@@ -14,9 +14,6 @@
|
||||
<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>
|
||||
|
||||
---
|
||||
@@ -39,10 +36,24 @@ The key features are:
|
||||
* **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>.
|
||||
* **Standards-based**: Based on (and fully compatible with) the open standards for APIs: <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank">OpenAPI</a> (previously known as Swagger) and <a href="https://json-schema.org/" class="external-link" target="_blank">JSON Schema</a>.
|
||||
|
||||
<small>* estimation based on tests on an internal development team, building production applications.</small>
|
||||
|
||||
## Sponsors
|
||||
|
||||
<!-- sponsors -->
|
||||
|
||||
<a href="https://www.deta.sh/?ref=fastapi" target="_blank" title="The launchpad for all your (team's) ideas"><img src="https://fastapi.tiangolo.com/img/sponsors/deta.svg"></a>
|
||||
<a href="https://bit.ly/2QSouzH" target="_blank" title="Jina: build neural search-as-a-service for any kind of data in just minutes."><img src="https://fastapi.tiangolo.com/img/sponsors/jina.svg"></a>
|
||||
<a href="https://www.investsuite.com/jobs" target="_blank" title="Wealthtech jobs with FastAPI"><img src="https://fastapi.tiangolo.com/img/sponsors/investsuite.svg"></a>
|
||||
<a href="https://www.vim.so/?utm_source=FastAPI" target="_blank" title="We help you master vim with interactive exercises"><img src="https://fastapi.tiangolo.com/img/sponsors/vimso.png"></a>
|
||||
<a href="https://talkpython.fm/fastapi-sponsor" target="_blank" title="FastAPI video courses on demand from people you trust"><img src="https://fastapi.tiangolo.com/img/sponsors/talkpython.png"></a>
|
||||
|
||||
<!-- /sponsors -->
|
||||
|
||||
<a href="https://fastapi.tiangolo.com/fastapi-people/#sponsors" class="external-link" target="_blank">Other sponsors</a>
|
||||
|
||||
## 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._"
|
||||
@@ -71,7 +82,7 @@ The key features are:
|
||||
|
||||
"_Honestly, what you've built looks super solid and polished. In many ways, it's what I wanted **Hug** to be - it's really inspiring to see someone build that._"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Timothy Crosley - <strong><a href="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>
|
||||
<div style="text-align: right; margin-right: 10%;">Timothy Crosley - <strong><a href="https://www.hug.rest/" target="_blank">Hug</a> creator</strong> <a href="https://news.ycombinator.com/item?id=19455465" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
@@ -112,12 +123,12 @@ $ pip install fastapi
|
||||
|
||||
</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>.
|
||||
You will also need an ASGI server, for production such as <a href="https://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
|
||||
$ pip install uvicorn[standard]
|
||||
|
||||
---> 100%
|
||||
```
|
||||
@@ -428,9 +439,9 @@ Used by Pydantic:
|
||||
|
||||
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://requests.readthedocs.io" 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://jinja.palletsprojects.com" 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).
|
||||
@@ -439,7 +450,7 @@ Used by Starlette:
|
||||
|
||||
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://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]`.
|
||||
|
||||
31
SECURITY.md
Normal file
@@ -0,0 +1,31 @@
|
||||
# Security Policy
|
||||
|
||||
Security is very important for FastAPI and its community. 🔒
|
||||
|
||||
Learn more about it below. 👇
|
||||
|
||||
## Versions
|
||||
|
||||
The latest versions of FastAPI are supported.
|
||||
|
||||
You are encouraged to [write tests](https://fastapi.tiangolo.com/tutorial/testing/) for your application and update your FastAPI version frequently after ensuring that your tests are passing. This way you will benefit from the latest features, bug fixes, and **security fixes**.
|
||||
|
||||
You can learn more about [FastAPI versions and how to pin and upgrade them](https://fastapi.tiangolo.com/deployment/versions/) for your project in the docs.
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
If you think you found a vulnerability, and even if you are not sure about it, please report it right away by sending an email to: security@tiangolo.com. Please try to be as explicit as possible, describing all the steps and example code to reproduce the security issue.
|
||||
|
||||
I (the author, [@tiangolo](https://twitter.com/tiangolo)) will review it thoroughly and get back to you.
|
||||
|
||||
## Public Discussions
|
||||
|
||||
Please restrain from publicly discussing a potential security vulnerability. 🙊
|
||||
|
||||
It's better to discuss privately and try to find a solution first, to limit the potential impact as much as possible.
|
||||
|
||||
---
|
||||
|
||||
Thanks for your help!
|
||||
|
||||
The FastAPI community and I thank you for that. 🙇
|
||||
@@ -16,9 +16,9 @@ articles:
|
||||
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
|
||||
- link: https://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_link: https://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"
|
||||
@@ -124,7 +124,7 @@ articles:
|
||||
title: Introducing Dispatch
|
||||
author_link: https://netflixtechblog.com/
|
||||
author: Netflix
|
||||
- link: https://davidefiocco.github.io/2020/06/27/streamlit-fastapi-ml-serving.html
|
||||
- link: https://davidefiocco.github.io/streamlit-fastapi-ml-serving/
|
||||
title: Machine learning model serving in Python using FastAPI and streamlit
|
||||
author_link: https://github.com/davidefiocco
|
||||
author: Davide Fiocco
|
||||
@@ -136,6 +136,30 @@ articles:
|
||||
title: Build And Host Fast Data Science Applications Using FastAPI
|
||||
author_link: https://medium.com/@farhadmalik
|
||||
author: Farhad Malik
|
||||
- link: https://medium.com/@gabbyprecious2000/creating-a-crud-app-with-fastapi-part-one-7c049292ad37
|
||||
title: Creating a CRUD App with FastAPI (Part one)
|
||||
author_link: https://medium.com/@gabbyprecious2000
|
||||
author: Precious Ndubueze
|
||||
- link: https://julienharbulot.com/notification-server.html
|
||||
title: HTTP server to display desktop notifications
|
||||
author_link: https://julienharbulot.com/
|
||||
author: Julien Harbulot
|
||||
- link: https://guitton.co/posts/fastapi-monitoring/
|
||||
title: How to monitor your FastAPI service
|
||||
author_link: https://twitter.com/louis_guitton
|
||||
author: Louis Guitton
|
||||
- link: https://amitness.com/2020/06/fastapi-vs-flask/
|
||||
title: FastAPI for Flask Users
|
||||
author_link: https://twitter.com/amitness
|
||||
author: Amit Chaudhary
|
||||
- link: https://valonjanuzaj.medium.com/deploy-a-dockerized-fastapi-application-to-aws-cc757830ba1b
|
||||
title: Deploy a dockerized FastAPI application to AWS
|
||||
author_link: https://www.linkedin.com/in/valon-januzaj-b02692187/
|
||||
author: Valon Januzaj
|
||||
- link: https://dompatmore.com/blog/authenticate-your-fastapi-app-with-auth0
|
||||
title: Authenticate Your FastAPI App with auth0
|
||||
author_link: https://twitter.com/dompatmore
|
||||
author: Dom Patmore
|
||||
japanese:
|
||||
- link: https://qiita.com/mtitg/items/47770e9a562dd150631d
|
||||
title: FastAPI|DB接続してCRUDするPython製APIサーバーを構築
|
||||
@@ -199,6 +223,10 @@ articles:
|
||||
title: Почему Вы должны попробовать FastAPI?
|
||||
author_link: https://github.com/prostomarkeloff
|
||||
author: prostomarkeloff
|
||||
- link: https://trkohler.com/fast-api-introduction-to-framework
|
||||
title: "FastAPI: знакомимся с фреймворком"
|
||||
author_link: https://www.linkedin.com/in/trkohler/
|
||||
author: Troy Köhler
|
||||
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
|
||||
|
||||
752
docs/en/data/people.yml
Normal file
@@ -0,0 +1,752 @@
|
||||
maintainers:
|
||||
- login: tiangolo
|
||||
answers: 1225
|
||||
prs: 232
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=05f95ca7fdead36edd9c86be46b4ef6c3c71f876&v=4
|
||||
url: https://github.com/tiangolo
|
||||
experts:
|
||||
- login: Kludex
|
||||
count: 267
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=cf8455cb899806b774a3a71073f88583adec99f6&v=4
|
||||
url: https://github.com/Kludex
|
||||
- login: dmontagu
|
||||
count: 262
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/35119617?u=58ed2a45798a4339700e2f62b2e12e6e54bf0396&v=4
|
||||
url: https://github.com/dmontagu
|
||||
- login: ycd
|
||||
count: 216
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/62724709?u=826f228edf0bab0d19ad1d5c4ba4df1047ccffef&v=4
|
||||
url: https://github.com/ycd
|
||||
- login: Mause
|
||||
count: 182
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1405026?v=4
|
||||
url: https://github.com/Mause
|
||||
- login: euri10
|
||||
count: 166
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1104190?u=321a2e953e6645a7d09b732786c7a8061e0f8a8b&v=4
|
||||
url: https://github.com/euri10
|
||||
- login: phy25
|
||||
count: 130
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/331403?v=4
|
||||
url: https://github.com/phy25
|
||||
- login: ArcLightSlavik
|
||||
count: 64
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/31127044?u=81a84af39c89b898b0fbc5a04e8834f60f23e55a&v=4
|
||||
url: https://github.com/ArcLightSlavik
|
||||
- login: falkben
|
||||
count: 56
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/653031?u=0c8d8f33d87f1aa1a6488d3f02105e9abc838105&v=4
|
||||
url: https://github.com/falkben
|
||||
- login: raphaelauv
|
||||
count: 47
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/10202690?u=e6f86f5c0c3026a15d6b51792fa3e532b12f1371&v=4
|
||||
url: https://github.com/raphaelauv
|
||||
- login: sm-Fifteen
|
||||
count: 46
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/516999?u=437c0c5038558c67e887ccd863c1ba0f846c03da&v=4
|
||||
url: https://github.com/sm-Fifteen
|
||||
- login: includeamin
|
||||
count: 38
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/11836741?u=8bd5ef7e62fe6a82055e33c4c0e0a7879ff8cfb6&v=4
|
||||
url: https://github.com/includeamin
|
||||
- login: prostomarkeloff
|
||||
count: 33
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/28061158?u=72309cc1f2e04e40fa38b29969cb4e9d3f722e7b&v=4
|
||||
url: https://github.com/prostomarkeloff
|
||||
- login: Dustyposa
|
||||
count: 32
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/27180793?u=5cf2877f50b3eb2bc55086089a78a36f07042889&v=4
|
||||
url: https://github.com/Dustyposa
|
||||
- login: krishnardt
|
||||
count: 30
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/31960541?u=47f4829c77f4962ab437ffb7995951e41eeebe9b&v=4
|
||||
url: https://github.com/krishnardt
|
||||
- login: insomnes
|
||||
count: 30
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/16958893?u=f8be7088d5076d963984a21f95f44e559192d912&v=4
|
||||
url: https://github.com/insomnes
|
||||
- login: wshayes
|
||||
count: 29
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/365303?u=07ca03c5ee811eb0920e633cc3c3db73dbec1aa5&v=4
|
||||
url: https://github.com/wshayes
|
||||
- login: dbanty
|
||||
count: 25
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/43723790?u=0cf33e4f40efc2ea206a1189fd63a11344eb88ed&v=4
|
||||
url: https://github.com/dbanty
|
||||
- login: SirTelemak
|
||||
count: 24
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/9435877?u=719327b7d2c4c62212456d771bfa7c6b8dbb9eac&v=4
|
||||
url: https://github.com/SirTelemak
|
||||
- login: chbndrhnns
|
||||
count: 22
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/7534547?v=4
|
||||
url: https://github.com/chbndrhnns
|
||||
- login: acnebs
|
||||
count: 22
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/9054108?u=bfd127b3e6200f4d00afd714f0fc95c2512df19b&v=4
|
||||
url: https://github.com/acnebs
|
||||
- login: nsidnev
|
||||
count: 22
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/22559461?u=a9cc3238217e21dc8796a1a500f01b722adb082c&v=4
|
||||
url: https://github.com/nsidnev
|
||||
- login: frankie567
|
||||
count: 21
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1144727?u=72adf1cb1d29787305c99700d669561952cea0af&v=4
|
||||
url: https://github.com/frankie567
|
||||
- login: chris-allnutt
|
||||
count: 21
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/565544?v=4
|
||||
url: https://github.com/chris-allnutt
|
||||
- login: retnikt
|
||||
count: 19
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/24581770?v=4
|
||||
url: https://github.com/retnikt
|
||||
- login: Hultner
|
||||
count: 18
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/2669034?u=115e53df959309898ad8dc9443fbb35fee71df07&v=4
|
||||
url: https://github.com/Hultner
|
||||
- login: jorgerpo
|
||||
count: 17
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/12537771?u=7444d20019198e34911082780cc7ad73f2b97cb3&v=4
|
||||
url: https://github.com/jorgerpo
|
||||
- login: nkhitrov
|
||||
count: 17
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/28262306?u=66ee21316275ef356081c2efc4ed7a4572e690dc&v=4
|
||||
url: https://github.com/nkhitrov
|
||||
- login: waynerv
|
||||
count: 15
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/39515546?u=ec35139777597cdbbbddda29bf8b9d4396b429a9&v=4
|
||||
url: https://github.com/waynerv
|
||||
- login: haizaar
|
||||
count: 13
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/58201?u=4f1f9843d69433ca0d380d95146cfe119e5fdac4&v=4
|
||||
url: https://github.com/haizaar
|
||||
- login: acidjunk
|
||||
count: 11
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/685002?u=b5094ab4527fc84b006c0ac9ff54367bdebb2267&v=4
|
||||
url: https://github.com/acidjunk
|
||||
- login: zamiramir
|
||||
count: 11
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/40475662?u=e58ef61034e8d0d6a312cc956fb09b9c3332b449&v=4
|
||||
url: https://github.com/zamiramir
|
||||
- login: juntatalor
|
||||
count: 11
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/8134632?v=4
|
||||
url: https://github.com/juntatalor
|
||||
- login: valentin994
|
||||
count: 11
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/42819267?u=fdeeaa9242a59b243f8603496b00994f6951d5a2&v=4
|
||||
url: https://github.com/valentin994
|
||||
- login: aalifadv
|
||||
count: 11
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/78442260?v=4
|
||||
url: https://github.com/aalifadv
|
||||
- login: stefanondisponibile
|
||||
count: 10
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/20441825?u=ee1e59446b98f8ec2363caeda4c17164d0d9cc7d&v=4
|
||||
url: https://github.com/stefanondisponibile
|
||||
last_month_active:
|
||||
- login: Kludex
|
||||
count: 12
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=cf8455cb899806b774a3a71073f88583adec99f6&v=4
|
||||
url: https://github.com/Kludex
|
||||
- login: frankie567
|
||||
count: 9
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1144727?u=72adf1cb1d29787305c99700d669561952cea0af&v=4
|
||||
url: https://github.com/frankie567
|
||||
- login: Mause
|
||||
count: 6
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1405026?v=4
|
||||
url: https://github.com/Mause
|
||||
- login: ArcLightSlavik
|
||||
count: 6
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/31127044?u=81a84af39c89b898b0fbc5a04e8834f60f23e55a&v=4
|
||||
url: https://github.com/ArcLightSlavik
|
||||
- login: gyKa
|
||||
count: 4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1000842?v=4
|
||||
url: https://github.com/gyKa
|
||||
- login: ricky-sb
|
||||
count: 3
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/10700079?v=4
|
||||
url: https://github.com/ricky-sb
|
||||
- login: captainCapitalism
|
||||
count: 3
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/32553875?v=4
|
||||
url: https://github.com/captainCapitalism
|
||||
- login: acidjunk
|
||||
count: 3
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/685002?u=b5094ab4527fc84b006c0ac9ff54367bdebb2267&v=4
|
||||
url: https://github.com/acidjunk
|
||||
top_contributors:
|
||||
- login: waynerv
|
||||
count: 25
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/39515546?u=ec35139777597cdbbbddda29bf8b9d4396b429a9&v=4
|
||||
url: https://github.com/waynerv
|
||||
- login: tokusumi
|
||||
count: 22
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/41147016?u=55010621aece725aa702270b54fed829b6a1fe60&v=4
|
||||
url: https://github.com/tokusumi
|
||||
- login: dmontagu
|
||||
count: 16
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/35119617?u=58ed2a45798a4339700e2f62b2e12e6e54bf0396&v=4
|
||||
url: https://github.com/dmontagu
|
||||
- login: euri10
|
||||
count: 13
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1104190?u=321a2e953e6645a7d09b732786c7a8061e0f8a8b&v=4
|
||||
url: https://github.com/euri10
|
||||
- login: mariacamilagl
|
||||
count: 9
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/11489395?u=4adb6986bf3debfc2b8216ae701f2bd47d73da7d&v=4
|
||||
url: https://github.com/mariacamilagl
|
||||
- login: RunningIkkyu
|
||||
count: 7
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/31848542?u=706e1ee3f248245f2d68b976d149d06fd5a2010d&v=4
|
||||
url: https://github.com/RunningIkkyu
|
||||
- login: Serrones
|
||||
count: 7
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/22691749?u=4795b880e13ca33a73e52fc0ef7dc9c60c8fce47&v=4
|
||||
url: https://github.com/Serrones
|
||||
- login: hard-coders
|
||||
count: 6
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/9651103?u=f2d3d2038c55d86d7f9348f4e6c5e30191e4ee8b&v=4
|
||||
url: https://github.com/hard-coders
|
||||
- login: wshayes
|
||||
count: 5
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/365303?u=07ca03c5ee811eb0920e633cc3c3db73dbec1aa5&v=4
|
||||
url: https://github.com/wshayes
|
||||
- login: SwftAlpc
|
||||
count: 5
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/52768429?u=6a3aa15277406520ad37f6236e89466ed44bc5b8&v=4
|
||||
url: https://github.com/SwftAlpc
|
||||
- login: Attsun1031
|
||||
count: 5
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1175560?v=4
|
||||
url: https://github.com/Attsun1031
|
||||
- login: jekirl
|
||||
count: 4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/2546697?v=4
|
||||
url: https://github.com/jekirl
|
||||
- login: komtaki
|
||||
count: 4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/39375566?u=5a44657c0544111ee3c132d9bb9951c2804f7969&v=4
|
||||
url: https://github.com/komtaki
|
||||
- login: Smlep
|
||||
count: 4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/16785985?v=4
|
||||
url: https://github.com/Smlep
|
||||
top_reviewers:
|
||||
- login: Kludex
|
||||
count: 80
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=cf8455cb899806b774a3a71073f88583adec99f6&v=4
|
||||
url: https://github.com/Kludex
|
||||
- login: tokusumi
|
||||
count: 44
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/41147016?u=55010621aece725aa702270b54fed829b6a1fe60&v=4
|
||||
url: https://github.com/tokusumi
|
||||
- login: Laineyzhang55
|
||||
count: 42
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/59285379?v=4
|
||||
url: https://github.com/Laineyzhang55
|
||||
- login: ycd
|
||||
count: 41
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/62724709?u=826f228edf0bab0d19ad1d5c4ba4df1047ccffef&v=4
|
||||
url: https://github.com/ycd
|
||||
- login: waynerv
|
||||
count: 38
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/39515546?u=ec35139777597cdbbbddda29bf8b9d4396b429a9&v=4
|
||||
url: https://github.com/waynerv
|
||||
- login: AdrianDeAnda
|
||||
count: 28
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1024932?u=bb7f8a0d6c9de4e9d0320a9f271210206e202250&v=4
|
||||
url: https://github.com/AdrianDeAnda
|
||||
- login: dmontagu
|
||||
count: 23
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/35119617?u=58ed2a45798a4339700e2f62b2e12e6e54bf0396&v=4
|
||||
url: https://github.com/dmontagu
|
||||
- login: komtaki
|
||||
count: 21
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/39375566?u=5a44657c0544111ee3c132d9bb9951c2804f7969&v=4
|
||||
url: https://github.com/komtaki
|
||||
- login: ArcLightSlavik
|
||||
count: 20
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/31127044?u=81a84af39c89b898b0fbc5a04e8834f60f23e55a&v=4
|
||||
url: https://github.com/ArcLightSlavik
|
||||
- login: cassiobotaro
|
||||
count: 16
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/3127847?u=b0a652331da17efeb85cd6e3a4969182e5004804&v=4
|
||||
url: https://github.com/cassiobotaro
|
||||
- login: yanever
|
||||
count: 16
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/21978760?v=4
|
||||
url: https://github.com/yanever
|
||||
- login: SwftAlpc
|
||||
count: 16
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/52768429?u=6a3aa15277406520ad37f6236e89466ed44bc5b8&v=4
|
||||
url: https://github.com/SwftAlpc
|
||||
- login: pedabraham
|
||||
count: 15
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/16860088?u=abf922a7b920bf8fdb7867d8b43e091f1e796178&v=4
|
||||
url: https://github.com/pedabraham
|
||||
- login: delhi09
|
||||
count: 15
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/63476957?u=6c86e59b48e0394d4db230f37fc9ad4d7e2c27c7&v=4
|
||||
url: https://github.com/delhi09
|
||||
- login: RunningIkkyu
|
||||
count: 12
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/31848542?u=706e1ee3f248245f2d68b976d149d06fd5a2010d&v=4
|
||||
url: https://github.com/RunningIkkyu
|
||||
- login: hard-coders
|
||||
count: 12
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/9651103?u=f2d3d2038c55d86d7f9348f4e6c5e30191e4ee8b&v=4
|
||||
url: https://github.com/hard-coders
|
||||
- login: sh0nk
|
||||
count: 11
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/6478810?u=af15d724875cec682ed8088a86d36b2798f981c0&v=4
|
||||
url: https://github.com/sh0nk
|
||||
- login: mariacamilagl
|
||||
count: 10
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/11489395?u=4adb6986bf3debfc2b8216ae701f2bd47d73da7d&v=4
|
||||
url: https://github.com/mariacamilagl
|
||||
- login: Attsun1031
|
||||
count: 10
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1175560?v=4
|
||||
url: https://github.com/Attsun1031
|
||||
- login: maoyibo
|
||||
count: 10
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/7887703?v=4
|
||||
url: https://github.com/maoyibo
|
||||
- login: PandaHun
|
||||
count: 9
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/13096845?u=646eba44db720e37d0dbe8e98e77ab534ea78a20&v=4
|
||||
url: https://github.com/PandaHun
|
||||
- login: bezaca
|
||||
count: 9
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/69092910?u=4ac58eab99bd37d663f3d23551df96d4fbdbf760&v=4
|
||||
url: https://github.com/bezaca
|
||||
- login: lsglucas
|
||||
count: 8
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/61513630?u=320e43fe4dc7bc6efc64e9b8f325f8075634fd20&v=4
|
||||
url: https://github.com/lsglucas
|
||||
- login: rjNemo
|
||||
count: 8
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/56785022?u=d5c3a02567c8649e146fcfc51b6060ccaf8adef8&v=4
|
||||
url: https://github.com/rjNemo
|
||||
- login: blt232018
|
||||
count: 8
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/43393471?u=172b0e0391db1aa6c1706498d6dfcb003c8a4857&v=4
|
||||
url: https://github.com/blt232018
|
||||
- login: Serrones
|
||||
count: 7
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/22691749?u=4795b880e13ca33a73e52fc0ef7dc9c60c8fce47&v=4
|
||||
url: https://github.com/Serrones
|
||||
- login: ryuckel
|
||||
count: 7
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/36391432?u=094eec0cfddd5013f76f31e55e56147d78b19553&v=4
|
||||
url: https://github.com/ryuckel
|
||||
- login: raphaelauv
|
||||
count: 7
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/10202690?u=e6f86f5c0c3026a15d6b51792fa3e532b12f1371&v=4
|
||||
url: https://github.com/raphaelauv
|
||||
- login: NastasiaSaby
|
||||
count: 7
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/8245071?u=b3afd005f9e4bf080c219ef61a592b3a8004b764&v=4
|
||||
url: https://github.com/NastasiaSaby
|
||||
- login: Smlep
|
||||
count: 7
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/16785985?v=4
|
||||
url: https://github.com/Smlep
|
||||
- login: jovicon
|
||||
count: 6
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/21287303?u=b049eac3e51a4c0473c2efe66b4d28a7d8f2b572&v=4
|
||||
url: https://github.com/jovicon
|
||||
- login: Mause
|
||||
count: 6
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1405026?v=4
|
||||
url: https://github.com/Mause
|
||||
- login: nimctl
|
||||
count: 5
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/49960770?u=e39b11d47188744ee07b2a1c7ce1a1bdf3c80760&v=4
|
||||
url: https://github.com/nimctl
|
||||
- login: juntatalor
|
||||
count: 5
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/8134632?v=4
|
||||
url: https://github.com/juntatalor
|
||||
- login: SnkSynthesis
|
||||
count: 5
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/63564282?u=0078826509dbecb2fdb543f4e881c9cd06157893&v=4
|
||||
url: https://github.com/SnkSynthesis
|
||||
- login: anthonycepeda
|
||||
count: 5
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/72019805?u=892f700c79f9732211bd5221bf16eec32356a732&v=4
|
||||
url: https://github.com/anthonycepeda
|
||||
- login: euri10
|
||||
count: 4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1104190?u=321a2e953e6645a7d09b732786c7a8061e0f8a8b&v=4
|
||||
url: https://github.com/euri10
|
||||
- login: rkbeatss
|
||||
count: 4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/23391143?u=56ab6bff50be950fa8cae5cf736f2ae66e319ff3&v=4
|
||||
url: https://github.com/rkbeatss
|
||||
- login: aviramha
|
||||
count: 4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/41201924?u=6883cc4fc13a7b2e60d4deddd4be06f9c5287880&v=4
|
||||
url: https://github.com/aviramha
|
||||
- login: Zxilly
|
||||
count: 4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/31370133?v=4
|
||||
url: https://github.com/Zxilly
|
||||
- login: Bluenix2
|
||||
count: 4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/38372706?u=c9d28aff15958d6ebf1971148bfb3154ff943c4f&v=4
|
||||
url: https://github.com/Bluenix2
|
||||
sponsors_50:
|
||||
- login: johnadjei
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/767860?v=4
|
||||
url: https://github.com/johnadjei
|
||||
- login: wdwinslow
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/11562137?u=dc01daafb354135603a263729e3d26d939c0c452&v=4
|
||||
url: https://github.com/wdwinslow
|
||||
- login: bingwu-chime
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/67026650?u=603a6b345f25c20c6706a8a6c7f71ae688d649a5&v=4
|
||||
url: https://github.com/bingwu-chime
|
||||
sponsors:
|
||||
- login: kamalgill
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/133923?u=0df9181d97436ce330e9acf90ab8a54b7022efe7&v=4
|
||||
url: https://github.com/kamalgill
|
||||
- login: grillazz
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/3415861?u=16d7d0ffa5dfb99f8834f8f76d90e138ba09b94a&v=4
|
||||
url: https://github.com/grillazz
|
||||
- login: tizz98
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/5739698?u=f095a3659e3a8e7c69ccd822696990b521ea25f9&v=4
|
||||
url: https://github.com/tizz98
|
||||
- login: jmaralc
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/21101214?u=b15a9f07b7cbf6c9dcdbcb6550bbd2c52f55aa50&v=4
|
||||
url: https://github.com/jmaralc
|
||||
- login: psgandalf
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/8134158?v=4
|
||||
url: https://github.com/psgandalf
|
||||
- login: samuelcolvin
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/4039449?u=807390ba9cfe23906c3bf8a0d56aaca3cf2bfa0d&v=4
|
||||
url: https://github.com/samuelcolvin
|
||||
- login: jokull
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/701?u=0532b62166893d5160ef795c4c8b7512d971af05&v=4
|
||||
url: https://github.com/jokull
|
||||
- login: wshayes
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/365303?u=07ca03c5ee811eb0920e633cc3c3db73dbec1aa5&v=4
|
||||
url: https://github.com/wshayes
|
||||
- login: koxudaxi
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/630670?u=507d8577b4b3670546b449c4c2ccbc5af40d72f7&v=4
|
||||
url: https://github.com/koxudaxi
|
||||
- login: falkben
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/653031?u=0c8d8f33d87f1aa1a6488d3f02105e9abc838105&v=4
|
||||
url: https://github.com/falkben
|
||||
- login: jqueguiner
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/690878?u=e4835b2a985a0f2d52018e4926cb5a58c26a62e8&v=4
|
||||
url: https://github.com/jqueguiner
|
||||
- login: Mazyod
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/860511?v=4
|
||||
url: https://github.com/Mazyod
|
||||
- login: ltieman
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1084689?u=e69b17de17cb3ca141a17daa7ccbe173ceb1eb17&v=4
|
||||
url: https://github.com/ltieman
|
||||
- login: mrmattwright
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1277725?v=4
|
||||
url: https://github.com/mrmattwright
|
||||
- login: westonsteimel
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1593939?u=0f2c0e3647f916fe295d62fa70da7a4c177115e3&v=4
|
||||
url: https://github.com/westonsteimel
|
||||
- login: timdrijvers
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1694939?v=4
|
||||
url: https://github.com/timdrijvers
|
||||
- login: mrgnw
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/2504532?u=7ec43837a6d0afa80f96f0788744ea6341b89f97&v=4
|
||||
url: https://github.com/mrgnw
|
||||
- login: madisonmay
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/2645393?u=f22b93c6ea345a4d26a90a3834dfc7f0789fcb63&v=4
|
||||
url: https://github.com/madisonmay
|
||||
- login: saivarunk
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/2976867?u=71f4385e781e9a9e871a52f2d4686f9a8d69ba2f&v=4
|
||||
url: https://github.com/saivarunk
|
||||
- login: andre1sk
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/3148093?v=4
|
||||
url: https://github.com/andre1sk
|
||||
- login: Shark009
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/3163309?v=4
|
||||
url: https://github.com/Shark009
|
||||
- login: peterHoburg
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/3860655?u=f55f47eb2d6a9b495e806ac5a044e3ae01ccc1fa&v=4
|
||||
url: https://github.com/peterHoburg
|
||||
- login: dudil
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/4785835?u=58b7ea39123e0507f3b2996448a27256b16fd697&v=4
|
||||
url: https://github.com/dudil
|
||||
- login: ennui93
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/5300907?u=5b5452725ddb391b2caaebf34e05aba873591c3a&v=4
|
||||
url: https://github.com/ennui93
|
||||
- login: sco1
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/5323929?u=2b8434060d0c9d93de80a2a945baed94a412c31e&v=4
|
||||
url: https://github.com/sco1
|
||||
- login: MacroPower
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/5648814?u=b2730000c9f9a471282b9849d2cc85711d7973d4&v=4
|
||||
url: https://github.com/MacroPower
|
||||
- login: ginomempin
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/6091865?v=4
|
||||
url: https://github.com/ginomempin
|
||||
- login: iwpnd
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/6152183?u=b2286006daafff5f991557344fee20b5da59639a&v=4
|
||||
url: https://github.com/iwpnd
|
||||
- login: s3ich4n
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/6926298?u=ba3025d698e1c986655e776ae383a3d60d9d578e&v=4
|
||||
url: https://github.com/s3ich4n
|
||||
- login: Rehket
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/7015688?u=3afb0ba200feebbc7f958950e92db34df2a3c172&v=4
|
||||
url: https://github.com/Rehket
|
||||
- login: christippett
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/7218120?u=434b9d29287d7de25772d94ddc74a9bd6d969284&v=4
|
||||
url: https://github.com/christippett
|
||||
- login: Kludex
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=cf8455cb899806b774a3a71073f88583adec99f6&v=4
|
||||
url: https://github.com/Kludex
|
||||
- login: Shackelford-Arden
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/7362263?v=4
|
||||
url: https://github.com/Shackelford-Arden
|
||||
- login: macleodmac
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/8996312?u=e39c68c3e0b1d264dcba4850134a291680f46355&v=4
|
||||
url: https://github.com/macleodmac
|
||||
- login: cristeaadrian
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/9112724?v=4
|
||||
url: https://github.com/cristeaadrian
|
||||
- login: otivvormes
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/11317418?u=6de1edefb6afd0108c0ad2816bd6efc4464a9c44&v=4
|
||||
url: https://github.com/otivvormes
|
||||
- login: iambobmae
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/12390270?u=c9a35c2ee5092a9b4135ebb1f91b7f521c467031&v=4
|
||||
url: https://github.com/iambobmae
|
||||
- login: ronaldnwilliams
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/13632749?u=ac41a086d0728bf66a9d2bee9e5e377041ff44a4&v=4
|
||||
url: https://github.com/ronaldnwilliams
|
||||
- login: uselessscat
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/15332878?u=8485a1b7383c274b28f383370ee2d5f9a6cd423b&v=4
|
||||
url: https://github.com/uselessscat
|
||||
- login: natenka
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/15850513?u=00d1083c980d0b4ce32835dc07eee7f43f34fd2f&v=4
|
||||
url: https://github.com/natenka
|
||||
- login: la-mar
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/16618300?u=7755c0521d2bb0d704f35a51464b15c1e2e6c4da&v=4
|
||||
url: https://github.com/la-mar
|
||||
- login: robintully
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/17059673?u=862b9bb01513f5acd30df97433cb97a24dbfb772&v=4
|
||||
url: https://github.com/robintully
|
||||
- login: ShaulAb
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/18129076?u=2c8d48e47f2dbee15c3f89c3d17d4c356504386c&v=4
|
||||
url: https://github.com/ShaulAb
|
||||
- login: wedwardbeck
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/19333237?u=1de4ae2bf8d59eb4c013f21d863cbe0f2010575f&v=4
|
||||
url: https://github.com/wedwardbeck
|
||||
- login: linusg
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/19366641?u=125e390abef8fff3b3b0d370c369cba5d7fd4c67&v=4
|
||||
url: https://github.com/linusg
|
||||
- login: RedCarpetUp
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/20360440?v=4
|
||||
url: https://github.com/RedCarpetUp
|
||||
- login: daddycocoaman
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/21189155?u=756f6a17c71c538b11470f70839baacab43807ef&v=4
|
||||
url: https://github.com/daddycocoaman
|
||||
- login: Filimoa
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/21352040?u=75e02d102d2ee3e3d793e555fa5c63045913ccb0&v=4
|
||||
url: https://github.com/Filimoa
|
||||
- login: raminsj13
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/24259406?u=d51f2a526312ebba150a06936ed187ca0727d329&v=4
|
||||
url: https://github.com/raminsj13
|
||||
- login: comoelcometa
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/25950317?u=c6751efa038561b9bc5fa56d1033d5174e10cd65&v=4
|
||||
url: https://github.com/comoelcometa
|
||||
- login: veprimk
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/29689749?u=f8cb5a15a286e522e5b189bc572d5a1a90217fb2&v=4
|
||||
url: https://github.com/veprimk
|
||||
- login: orihomie
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/29889683?u=6bc2135a52fcb3a49e69e7d50190796618185fda&v=4
|
||||
url: https://github.com/orihomie
|
||||
- login: SaltyCoco
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/31451104?u=6ee4e17c07d21b7054f54a12fa9cc377a1b24ff9&v=4
|
||||
url: https://github.com/SaltyCoco
|
||||
- login: mauroalejandrojm
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/31569442?u=cdada990a1527926a36e95f62c30a8b48bbc49a1&v=4
|
||||
url: https://github.com/mauroalejandrojm
|
||||
- login: public-daniel
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/32238294?u=0377e38dd023395c9643d5388b4e9489a24b4d34&v=4
|
||||
url: https://github.com/public-daniel
|
||||
- login: ybressler
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/40807730?u=6621dc9ab53b697912ab2a32211bb29ae90a9112&v=4
|
||||
url: https://github.com/ybressler
|
||||
- login: dbanty
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/43723790?u=0cf33e4f40efc2ea206a1189fd63a11344eb88ed&v=4
|
||||
url: https://github.com/dbanty
|
||||
- login: dudikbender
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/53487583?u=494f85229115076121b3639a3806bbac1c6ae7f6&v=4
|
||||
url: https://github.com/dudikbender
|
||||
- login: primer-io
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/62146168?v=4
|
||||
url: https://github.com/primer-io
|
||||
- login: tkrestiankova
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/67013045?v=4
|
||||
url: https://github.com/tkrestiankova
|
||||
- login: daverin
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/70378377?u=6d1814195c0de7162820eaad95a25b423a3869c0&v=4
|
||||
url: https://github.com/daverin
|
||||
- login: anthonycepeda
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/72019805?u=892f700c79f9732211bd5221bf16eec32356a732&v=4
|
||||
url: https://github.com/anthonycepeda
|
||||
- login: linux-china
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/46711?v=4
|
||||
url: https://github.com/linux-china
|
||||
- login: jhb
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/142217?v=4
|
||||
url: https://github.com/jhb
|
||||
- login: yourkin
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/178984?v=4
|
||||
url: https://github.com/yourkin
|
||||
- login: jmagnusson
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/190835?v=4
|
||||
url: https://github.com/jmagnusson
|
||||
- login: slafs
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/210173?v=4
|
||||
url: https://github.com/slafs
|
||||
- login: adamghill
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/317045?u=f1349d5ffe84a19f324e204777859fbf69ddf633&v=4
|
||||
url: https://github.com/adamghill
|
||||
- login: eteq
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/346587?v=4
|
||||
url: https://github.com/eteq
|
||||
- login: dmig
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/388564?v=4
|
||||
url: https://github.com/dmig
|
||||
- login: hongqn
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/405587?u=470b4c04832e45141fd5264d3354845cc9fc6466&v=4
|
||||
url: https://github.com/hongqn
|
||||
- login: rinckd
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/546002?u=1fcc7e664dc86524a0af6837a0c222829c3fd4e5&v=4
|
||||
url: https://github.com/rinckd
|
||||
- login: Pytlicek
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1430522?u=169dba3bfbc04ed214a914640ff435969f19ddb3&v=4
|
||||
url: https://github.com/Pytlicek
|
||||
- login: okken
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1568356?u=0a991a21bdc62e2bea9ad311652f2c45f453dc84&v=4
|
||||
url: https://github.com/okken
|
||||
- login: leogregianin
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1684053?u=94ddd387601bd1805034dbe83e6eba0491c15323&v=4
|
||||
url: https://github.com/leogregianin
|
||||
- login: cbonoz
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/2351087?u=fd3e8030b2cc9fbfbb54a65e9890c548a016f58b&v=4
|
||||
url: https://github.com/cbonoz
|
||||
- login: rglsk
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/2768101?u=e349c88673f2155fe021331377c656a9d74bcc25&v=4
|
||||
url: https://github.com/rglsk
|
||||
- login: Atem18
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/2875254?v=4
|
||||
url: https://github.com/Atem18
|
||||
- login: paul121
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/3116995?u=6e2d8691cc345e63ee02e4eb4d7cef82b1fcbedc&v=4
|
||||
url: https://github.com/paul121
|
||||
- login: igorcorrea
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/3438238?u=c57605077c31a8f7b2341fc4912507f91b4a5621&v=4
|
||||
url: https://github.com/igorcorrea
|
||||
- login: zsinx6
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/3532625?u=ba75a5dc744d1116ccfeaaf30d41cb2fe81fe8dd&v=4
|
||||
url: https://github.com/zsinx6
|
||||
- login: pawamoy
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/3999221?u=b030e4c89df2f3a36bc4710b925bdeb6745c9856&v=4
|
||||
url: https://github.com/pawamoy
|
||||
- login: spyker77
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/4953435?u=568baae6469628e020fe0bab16e395b7ae10c7d3&v=4
|
||||
url: https://github.com/spyker77
|
||||
- login: serfer2
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/5196592?u=e8798d87120952ed41876778f0cc8a1ddb47f901&v=4
|
||||
url: https://github.com/serfer2
|
||||
- login: JonasKs
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/5310116?u=98a049f3e1491bffb91e1feb7e93def6881a9389&v=4
|
||||
url: https://github.com/JonasKs
|
||||
- login: holec
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/6438041?u=f5af71ec85b3a9d7b8139cb5af0512b02fa9ab1e&v=4
|
||||
url: https://github.com/holec
|
||||
- login: BartlomiejRasztabiga
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/8852711?u=ed213d60f7a423df31ceb1004aa3ec60e612cb98&v=4
|
||||
url: https://github.com/BartlomiejRasztabiga
|
||||
- login: davanstrien
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/8995957?u=fb2aad2b52bb4e7b56db6d7c8ecc9ae1eac1b984&v=4
|
||||
url: https://github.com/davanstrien
|
||||
- login: and-semakin
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/9129071?u=ea77ddf7de4bc375d546bf2825ed420eaddb7666&v=4
|
||||
url: https://github.com/and-semakin
|
||||
- login: VivianSolide
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/9358572?u=ffb2e2ec522a15dcd3f0af1f9fd1df4afe418afa&v=4
|
||||
url: https://github.com/VivianSolide
|
||||
- login: hard-coders
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/9651103?u=f2d3d2038c55d86d7f9348f4e6c5e30191e4ee8b&v=4
|
||||
url: https://github.com/hard-coders
|
||||
- login: satwikkansal
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/10217535?u=b12d6ef74ea297de9e46da6933b1a5b7ba9e6a61&v=4
|
||||
url: https://github.com/satwikkansal
|
||||
- login: pheanex
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/10408624?u=5b6bab6ee174aa6e991333e06eb29f628741013d&v=4
|
||||
url: https://github.com/pheanex
|
||||
- login: wotori
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/10486621?u=0044c295b91694b8c9bccc0a805681f794250f7b&v=4
|
||||
url: https://github.com/wotori
|
||||
- login: JimFawkes
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/12075115?u=dc58ecfd064d72887c34bf500ddfd52592509acd&v=4
|
||||
url: https://github.com/JimFawkes
|
||||
- login: logan-connolly
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/16244943?u=8ae66dfbba936463cc8aa0dd7a6d2b4c0cc757eb&v=4
|
||||
url: https://github.com/logan-connolly
|
||||
- login: iPr0ger
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/19322290?v=4
|
||||
url: https://github.com/iPr0ger
|
||||
- login: sadikkuzu
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/23168063?u=765ed469c44c004560079210ccdad5b29938eaa9&v=4
|
||||
url: https://github.com/sadikkuzu
|
||||
- login: ghandic
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/23500353?u=e2e1d736f924d9be81e8bfc565b6d8836ba99773&v=4
|
||||
url: https://github.com/ghandic
|
||||
- login: MoronVV
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/24293616?v=4
|
||||
url: https://github.com/MoronVV
|
||||
- login: AngusWG
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/26385612?u=f4d4c8bd2097cdd58eb9e385932b83c78777f3c0&v=4
|
||||
url: https://github.com/AngusWG
|
||||
- login: mertguvencli
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/29762151?u=16a906d90df96c8cff9ea131a575c4bc171b1523&v=4
|
||||
url: https://github.com/mertguvencli
|
||||
- login: rgreen32
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/35779241?u=c9d64ad1ab364b6a1ec8e3d859da9ca802d681d8&v=4
|
||||
url: https://github.com/rgreen32
|
||||
- login: askurihin
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/37978981?v=4
|
||||
url: https://github.com/askurihin
|
||||
- login: berrysauce
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/38889179?u=758ed15a5be8bbd03855f5a74f42c19f7946ee32&v=4
|
||||
url: https://github.com/berrysauce
|
||||
- login: JitPackJoyride
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/40203625?u=9638bfeacfa5940358188f8205ce662bba022b53&v=4
|
||||
url: https://github.com/JitPackJoyride
|
||||
- login: es3n1n
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/40367813?u=e881a3880f1e342d19a1ea7c8e1b6d76c52dc294&v=4
|
||||
url: https://github.com/es3n1n
|
||||
- login: ilias-ant
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/42189572?u=a2d6121bac4d125d92ec207460fa3f1842d37e66&v=4
|
||||
url: https://github.com/ilias-ant
|
||||
- login: kbhatiya999
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/47816034?v=4
|
||||
url: https://github.com/kbhatiya999
|
||||
- login: akanz1
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/51492342?u=2280f57134118714645e16b535c1a37adf6b369b&v=4
|
||||
url: https://github.com/akanz1
|
||||
- login: rychardvale
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/54805553?u=3d20ab05301d05f9ac3500fb79a2bfee3842b753&v=4
|
||||
url: https://github.com/rychardvale
|
||||
- login: athemeart
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/61623624?v=4
|
||||
url: https://github.com/athemeart
|
||||
- login: Rhythmicc
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/29839231?u=2100781089a259707c475c4547bd7995b0fc18ee&v=4
|
||||
url: https://github.com/Rhythmicc
|
||||
21
docs/en/data/sponsors.yml
Normal file
@@ -0,0 +1,21 @@
|
||||
gold:
|
||||
- url: https://www.deta.sh/?ref=fastapi
|
||||
title: The launchpad for all your (team's) ideas
|
||||
img: https://fastapi.tiangolo.com/img/sponsors/deta.svg
|
||||
- url: https://bit.ly/2QSouzH
|
||||
title: "Jina: build neural search-as-a-service for any kind of data in just minutes."
|
||||
img: https://fastapi.tiangolo.com/img/sponsors/jina.svg
|
||||
silver:
|
||||
- url: https://www.investsuite.com/jobs
|
||||
title: Wealthtech jobs with FastAPI
|
||||
img: https://fastapi.tiangolo.com/img/sponsors/investsuite.svg
|
||||
- url: https://www.vim.so/?utm_source=FastAPI
|
||||
title: We help you master vim with interactive exercises
|
||||
img: https://fastapi.tiangolo.com/img/sponsors/vimso.png
|
||||
- url: https://talkpython.fm/fastapi-sponsor
|
||||
title: FastAPI video courses on demand from people you trust
|
||||
img: https://fastapi.tiangolo.com/img/sponsors/talkpython.png
|
||||
bronze:
|
||||
- url: https://testdriven.io/courses/tdd-fastapi/
|
||||
title: Learn to build high-quality web apps with best practices
|
||||
img: https://fastapi.tiangolo.com/img/sponsors/testdriven.svg
|
||||
@@ -40,7 +40,7 @@ Import the `Response` class (sub-class) you want to use and declare it in the *p
|
||||
To return a response with HTML directly from **FastAPI**, use `HTMLResponse`.
|
||||
|
||||
* Import `HTMLResponse`.
|
||||
* Pass `HTMLResponse` as the parameter `content_type` of your *path operation*.
|
||||
* Pass `HTMLResponse` as the parameter `response_class` of your *path operation decorator*.
|
||||
|
||||
```Python hl_lines="2 7"
|
||||
{!../../../docs_src/custom_response/tutorial002.py!}
|
||||
|
||||
@@ -83,15 +83,6 @@ So we are going to use that same knowledge to document how the *external API* sh
|
||||
|
||||
First create a new `APIRouter` that will contain one or more callbacks.
|
||||
|
||||
This router will never be added to an actual `FastAPI` app (i.e. it will never be passed to `app.include_router(...)`).
|
||||
|
||||
Because of that, you need to declare what will be the `default_response_class`, and set it to `JSONResponse`.
|
||||
|
||||
!!! Note "Technical Details"
|
||||
The `response_class` is normally set by the `FastAPI` app during the call to `app.include_router(some_router)`.
|
||||
|
||||
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="5 26"
|
||||
{!../../../docs_src/openapi_callbacks/tutorial001.py!}
|
||||
```
|
||||
|
||||
@@ -157,7 +157,7 @@ The `security_scopes` object (of class `SecurityScopes`) also provides a `scope_
|
||||
|
||||
We create an `HTTPException` that we can re-use (`raise`) later at several points.
|
||||
|
||||
In this exception, we include the scopes required (if any) as a string separated by spaces (using `scope_str`). We put that string containing the scopes in in the `WWW-Authenticate` header (this is part of the spec).
|
||||
In this exception, we include the scopes required (if any) as a string separated by spaces (using `scope_str`). We put that string containing the scopes in the `WWW-Authenticate` header (this is part of the spec).
|
||||
|
||||
```Python hl_lines="105 107-115"
|
||||
{!../../../docs_src/security/tutorial005.py!}
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
If you are starting a project from scratch, you are probably better off with SQLAlchemy ORM ([SQL (Relational) Databases](../tutorial/sql-databases.md){.internal-link target=_blank}), or any other async ORM.
|
||||
|
||||
If you already have a code base that uses <a href="http://docs.peewee-orm.com/en/latest/" class="external-link" target="_blank">Peewee ORM</a>, you can check here how to use it with **FastAPI**.
|
||||
If you already have a code base that uses <a href="https://docs.peewee-orm.com/en/latest/" class="external-link" target="_blank">Peewee ORM</a>, you can check here how to use it with **FastAPI**.
|
||||
|
||||
!!! warning "Python 3.7+ required"
|
||||
You will need Python 3.7 or above to safely use Peewee with FastAPI.
|
||||
@@ -25,7 +25,7 @@ But if you need to change some of the defaults, support more than one predefined
|
||||
Nevertheless, it's possible to do it, and here you'll see exactly what code you have to add to be able to use Peewee with FastAPI.
|
||||
|
||||
!!! note "Technical Details"
|
||||
You can read more about Peewee's stand about async in Python <a href="http://docs.peewee-orm.com/en/latest/peewee/database.html#async-with-gevent" class="external-link" target="_blank">in the docs</a>, <a href="https://github.com/coleifer/peewee/issues/263#issuecomment-517347032" class="external-link" target="_blank">an issue</a>, <a href="https://github.com/coleifer/peewee/pull/2072#issuecomment-563215132" class="external-link" target="_blank">a PR</a>.
|
||||
You can read more about Peewee's stand about async in Python <a href="https://docs.peewee-orm.com/en/latest/peewee/database.html#async-with-gevent" class="external-link" target="_blank">in the docs</a>, <a href="https://github.com/coleifer/peewee/issues/263#issuecomment-517347032" class="external-link" target="_blank">an issue</a>, <a href="https://github.com/coleifer/peewee/pull/2072#issuecomment-563215132" class="external-link" target="_blank">a PR</a>.
|
||||
|
||||
## The same app
|
||||
|
||||
@@ -306,7 +306,7 @@ For the **next request**, as we will reset that context variable again in the `a
|
||||
|
||||
#### Peewee Proxy
|
||||
|
||||
If you are using a <a href="http://docs.peewee-orm.com/en/latest/peewee/database.html#dynamically-defining-a-database" class="external-link" target="_blank">Peewee Proxy</a>, the actual database is at `db.obj`.
|
||||
If you are using a <a href="https://docs.peewee-orm.com/en/latest/peewee/database.html#dynamically-defining-a-database" class="external-link" target="_blank">Peewee Proxy</a>, the actual database is at `db.obj`.
|
||||
|
||||
So, you would reset it with:
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ It was one of the first examples of **automatic API documentation**, and this wa
|
||||
!!! check "Inspired **FastAPI** to"
|
||||
Have an automatic API documentation web user interface.
|
||||
|
||||
### <a href="http://flask.pocoo.org/" class="external-link" target="_blank">Flask</a>
|
||||
### <a href="https://flask.palletsprojects.com" class="external-link" target="_blank">Flask</a>
|
||||
|
||||
Flask is a "microframework", it doesn't include database integrations nor many of the things that come by default in Django.
|
||||
|
||||
@@ -57,7 +57,7 @@ Given the simplicity of Flask, it seemed like a good match for building APIs. Th
|
||||
Have a simple and easy to use routing system.
|
||||
|
||||
|
||||
### <a href="http://docs.python-requests.org" class="external-link" target="_blank">Requests</a>
|
||||
### <a href="https://requests.readthedocs.io" class="external-link" target="_blank">Requests</a>
|
||||
|
||||
**FastAPI** is not actually an alternative to **Requests**. Their scope is very different.
|
||||
|
||||
@@ -276,7 +276,7 @@ Routes are declared in a single place, using functions declared in other places
|
||||
|
||||
This actually inspired updating parts of Pydantic, to support the same validation declaration style (all this functionality is now already available in Pydantic).
|
||||
|
||||
### <a href="http://www.hug.rest/" class="external-link" target="_blank">Hug</a>
|
||||
### <a href="https://www.hug.rest/" class="external-link" target="_blank">Hug</a>
|
||||
|
||||
Hug was one of the first frameworks to implement the declaration of API parameter types using Python type hints. This was a great idea that inspired other tools to do the same.
|
||||
|
||||
@@ -410,7 +410,7 @@ It is the recommended server for Starlette and **FastAPI**.
|
||||
|
||||
You can combine it with Gunicorn, to have an asynchronous multi-process server.
|
||||
|
||||
Check more details in the [Deployment](deployment.md){.internal-link target=_blank} section.
|
||||
Check more details in the [Deployment](deployment/index.md){.internal-link target=_blank} section.
|
||||
|
||||
## Benchmarks and speed
|
||||
|
||||
|
||||
@@ -210,7 +210,7 @@ Most of the existing popular Python frameworks (including Flask and Django) were
|
||||
|
||||
Even though the main specification for asynchronous web Python (ASGI) was developed at Django, to add support for WebSockets.
|
||||
|
||||
That kind of asynchronicity is what made NodeJS popular (even though NodeJS is not parallel) and that's the strength of Go as a programing language.
|
||||
That kind of asynchronicity is what made NodeJS popular (even though NodeJS is not parallel) and that's the strength of Go as a programming language.
|
||||
|
||||
And that's the same level of performance you get with **FastAPI**.
|
||||
|
||||
@@ -261,7 +261,7 @@ But you can also exploit the benefits of parallelism and multiprocessing (having
|
||||
|
||||
That, plus the simple fact that Python is the main language for **Data Science**, Machine Learning and especially Deep Learning, make FastAPI a very good match for Data Science / Machine Learning web APIs and applications (among many others).
|
||||
|
||||
To see how to achieve this parallelism in production see the section about [Deployment](deployment.md){.internal-link target=_blank}.
|
||||
To see how to achieve this parallelism in production see the section about [Deployment](deployment/index.md){.internal-link target=_blank}.
|
||||
|
||||
## `async` and `await`
|
||||
|
||||
@@ -334,7 +334,7 @@ This same syntax (or almost identical) was also included recently in modern vers
|
||||
|
||||
But before that, handling asynchronous code was quite more complex and difficult.
|
||||
|
||||
In previous versions of Python, you could have used threads or <a href="http://www.gevent.org/" class="external-link" target="_blank">Gevent</a>. But the code is way more complex to understand, debug, and think about.
|
||||
In previous versions of Python, you could have used threads or <a href="https://www.gevent.org/" class="external-link" target="_blank">Gevent</a>. But the code is way more complex to understand, debug, and think about.
|
||||
|
||||
In previous versions of NodeJS / Browser JavaScript, you would have used "callbacks". Which leads to <a href="http://callbackhell.com/" class="external-link" target="_blank">callback hell</a>.
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ When you check the benchmarks, it is common to see several tools of different ty
|
||||
|
||||
Specifically, to see Uvicorn, Starlette and FastAPI compared together (among many other tools).
|
||||
|
||||
The simplest the problem solved by the tool, the better performance it will get. And most of the benchmarks don't test the additional features provided by the tool.
|
||||
The simpler the problem solved by the tool, the better performance it will get. And most of the benchmarks don't test the additional features provided by the tool.
|
||||
|
||||
The hierarchy is like:
|
||||
|
||||
|
||||
@@ -1,18 +1,101 @@
|
||||
a.external-link::after {
|
||||
/* \00A0 is a non-breaking space
|
||||
/* \00A0 is a non-breaking space
|
||||
to make the mark be on the same line as the link
|
||||
*/
|
||||
content: "\00A0[↪]";
|
||||
content: "\00A0[↪]";
|
||||
}
|
||||
|
||||
a.internal-link::after {
|
||||
/* \00A0 is a non-breaking space
|
||||
/* \00A0 is a non-breaking space
|
||||
to make the mark be on the same line as the link
|
||||
*/
|
||||
content: "\00A0↪";
|
||||
content: "\00A0↪";
|
||||
}
|
||||
|
||||
/* Give space to lower icons so Gitter chat doesn't get on top of them */
|
||||
.md-footer-meta {
|
||||
padding-bottom: 2em;
|
||||
padding-bottom: 2em;
|
||||
}
|
||||
|
||||
.user-list {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.user-list-center {
|
||||
justify-content: space-evenly;
|
||||
}
|
||||
|
||||
.user {
|
||||
margin: 1em;
|
||||
min-width: 7em;
|
||||
}
|
||||
|
||||
.user .avatar-wrapper {
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
margin: 10px auto;
|
||||
overflow: hidden;
|
||||
border-radius: 50%;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.user .avatar-wrapper img {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
|
||||
.user .title {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.user .count {
|
||||
font-size: 80%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
a.announce-link:link,
|
||||
a.announce-link:visited {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
a.announce-link:hover {
|
||||
color: var(--md-accent-fg-color);
|
||||
}
|
||||
|
||||
.announce-wrapper {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.announce-wrapper div.item {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.announce-wrapper .sponsor-badge {
|
||||
display: block;
|
||||
position: absolute;
|
||||
top: -5px;
|
||||
right: 0;
|
||||
font-size: 0.5rem;
|
||||
color: #999;
|
||||
background-color: #666;
|
||||
border-radius: 10px;
|
||||
padding: 0 10px;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.announce-wrapper .sponsor-image {
|
||||
display: block;
|
||||
border-radius: 20px;
|
||||
}
|
||||
|
||||
.announce-wrapper>div {
|
||||
min-height: 40px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
@@ -1,396 +0,0 @@
|
||||
# Deployment
|
||||
|
||||
Deploying a **FastAPI** application is relatively easy.
|
||||
|
||||
There are several ways to do it depending on your specific use case and the tools that you use.
|
||||
|
||||
You will see more about some of the ways to do it in the next sections.
|
||||
|
||||
## FastAPI versions
|
||||
|
||||
**FastAPI** is already being used in production in many applications and systems. And the test coverage is kept at 100%. But its development is still moving quickly.
|
||||
|
||||
New features are added frequently, bugs are fixed regularly, and the code is still continuously improving.
|
||||
|
||||
That's why the current versions are still `0.x.x`, this reflects that each version could potentially have breaking changes. This follows the <a href="https://semver.org/" class="external-link" target="_blank">Semantic Versioning</a> conventions.
|
||||
|
||||
You can create production applications with **FastAPI** right now (and you have probably been doing it for some time), you just have to make sure that you use a version that works correctly with the rest of your code.
|
||||
|
||||
### Pin your `fastapi` version
|
||||
|
||||
The first thing you should do is to "pin" the version of **FastAPI** you are using to the specific latest version that you know works correctly for your application.
|
||||
|
||||
For example, let's say you are using version `0.45.0` in your app.
|
||||
|
||||
If you use a `requirements.txt` file you could specify the version with:
|
||||
|
||||
```txt
|
||||
fastapi==0.45.0
|
||||
```
|
||||
|
||||
that would mean that you would use exactly the version `0.45.0`.
|
||||
|
||||
Or you could also pin it with:
|
||||
|
||||
```txt
|
||||
fastapi>=0.45.0,<0.46.0
|
||||
```
|
||||
|
||||
that would mean that you would use the versions `0.45.0` or above, but less than `0.46.0`, for example, a version `0.45.2` would still be accepted.
|
||||
|
||||
If you use any other tool to manage your installations, like Poetry, Pipenv, or others, they all have a way that you can use to define specific versions for your packages.
|
||||
|
||||
### Available versions
|
||||
|
||||
You can see the available versions (e.g. to check what is the current latest) in the [Release Notes](release-notes.md){.internal-link target=_blank}.
|
||||
|
||||
### About versions
|
||||
|
||||
Following the Semantic Versioning conventions, any version below `1.0.0` could potentially add breaking changes.
|
||||
|
||||
FastAPI also follows the convention that any "PATCH" version change is for bug fixes and non-breaking changes.
|
||||
|
||||
!!! tip
|
||||
The "PATCH" is the last number, for example, in `0.2.3`, the PATCH version is `3`.
|
||||
|
||||
So, you should be able to pin to a version like:
|
||||
|
||||
```txt
|
||||
fastapi>=0.45.0,<0.46.0
|
||||
```
|
||||
|
||||
Breaking changes and new features are added in "MINOR" versions.
|
||||
|
||||
!!! tip
|
||||
The "MINOR" is the number in the middle, for example, in `0.2.3`, the MINOR version is `2`.
|
||||
|
||||
### Upgrading the FastAPI versions
|
||||
|
||||
You should add tests for your app.
|
||||
|
||||
With **FastAPI** it's very easy (thanks to Starlette), check the docs: [Testing](tutorial/testing.md){.internal-link target=_blank}
|
||||
|
||||
After you have tests, then you can upgrade the **FastAPI** version to a more recent one, and make sure that all your code is working correctly by running your tests.
|
||||
|
||||
If everything is working, or after you make the necessary changes, and all your tests are passing, then you can pin your `fastapi` to that new recent version.
|
||||
|
||||
### About Starlette
|
||||
|
||||
You shouldn't pin the version of `starlette`.
|
||||
|
||||
Different versions of **FastAPI** will use a specific newer version of Starlette.
|
||||
|
||||
So, you can just let **FastAPI** use the correct Starlette version.
|
||||
|
||||
### About Pydantic
|
||||
|
||||
Pydantic includes the tests for **FastAPI** with its own tests, so new versions of Pydantic (above `1.0.0`) are always compatible with FastAPI.
|
||||
|
||||
You can pin Pydantic to any version above `1.0.0` that works for you and below `2.0.0`.
|
||||
|
||||
For example:
|
||||
|
||||
```txt
|
||||
pydantic>=1.2.0,<2.0.0
|
||||
```
|
||||
|
||||
## Docker
|
||||
|
||||
In this section you'll see instructions and links to guides to know how to:
|
||||
|
||||
* Make your **FastAPI** application a Docker image/container with maximum performance. In about **5 min**.
|
||||
* (Optionally) understand what you, as a developer, need to know about HTTPS.
|
||||
* Set up a Docker Swarm mode cluster with automatic HTTPS, even on a simple $5 USD/month server. In about **20 min**.
|
||||
* Generate and deploy a full **FastAPI** application, using your Docker Swarm cluster, with HTTPS, etc. In about **10 min**.
|
||||
|
||||
You can use <a href="https://www.docker.com/" class="external-link" target="_blank">**Docker**</a> for deployment. It has several advantages like security, replicability, development simplicity, etc.
|
||||
|
||||
If you are using Docker, you can use the official Docker image:
|
||||
|
||||
### <a href="https://github.com/tiangolo/uvicorn-gunicorn-fastapi-docker" class="external-link" target="_blank">tiangolo/uvicorn-gunicorn-fastapi</a>
|
||||
|
||||
This image has an "auto-tuning" mechanism included, so that you can just add your code and get very high performance automatically. And without making sacrifices.
|
||||
|
||||
But you can still change and update all the configurations with environment variables or configuration files.
|
||||
|
||||
!!! tip
|
||||
To see all the configurations and options, go to the Docker image page: <a href="https://github.com/tiangolo/uvicorn-gunicorn-fastapi-docker" class="external-link" target="_blank">tiangolo/uvicorn-gunicorn-fastapi</a>.
|
||||
|
||||
### Create a `Dockerfile`
|
||||
|
||||
* Go to your project directory.
|
||||
* Create a `Dockerfile` with:
|
||||
|
||||
```Dockerfile
|
||||
FROM tiangolo/uvicorn-gunicorn-fastapi:python3.7
|
||||
|
||||
COPY ./app /app
|
||||
```
|
||||
|
||||
#### Bigger Applications
|
||||
|
||||
If you followed the section about creating [Bigger Applications with Multiple Files](tutorial/bigger-applications.md){.internal-link target=_blank}, your `Dockerfile` might instead look like:
|
||||
|
||||
```Dockerfile
|
||||
FROM tiangolo/uvicorn-gunicorn-fastapi:python3.7
|
||||
|
||||
COPY ./app /app/app
|
||||
```
|
||||
|
||||
#### Raspberry Pi and other architectures
|
||||
|
||||
If you are running Docker in a Raspberry Pi (that has an ARM processor) or any other architecture, you can create a `Dockerfile` from scratch, based on a Python base image (that is multi-architecture) and use Uvicorn alone.
|
||||
|
||||
In this case, your `Dockerfile` could look like:
|
||||
|
||||
```Dockerfile
|
||||
FROM python:3.7
|
||||
|
||||
RUN pip install fastapi uvicorn
|
||||
|
||||
EXPOSE 80
|
||||
|
||||
COPY ./app /app
|
||||
|
||||
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80"]
|
||||
```
|
||||
|
||||
### Create the **FastAPI** Code
|
||||
|
||||
* Create an `app` directory and enter in it.
|
||||
* Create a `main.py` file with:
|
||||
|
||||
```Python
|
||||
from 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}
|
||||
```
|
||||
|
||||
* You should now have a directory structure like:
|
||||
|
||||
```
|
||||
.
|
||||
├── app
|
||||
│ └── main.py
|
||||
└── Dockerfile
|
||||
```
|
||||
|
||||
### Build the Docker image
|
||||
|
||||
* Go to the project directory (in where your `Dockerfile` is, containing your `app` directory).
|
||||
* Build your FastAPI image:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ docker build -t myimage .
|
||||
|
||||
---> 100%
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
### Start the Docker container
|
||||
|
||||
* Run a container based on your image:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ docker run -d --name mycontainer -p 80:80 myimage
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
Now you have an optimized FastAPI server in a Docker container. Auto-tuned for your current server (and number of CPU cores).
|
||||
|
||||
### Check it
|
||||
|
||||
You should be able to check it in your Docker container's URL, for example: <a href="http://192.168.99.100/items/5?q=somequery" class="external-link" target="_blank">http://192.168.99.100/items/5?q=somequery</a> or <a href="http://127.0.0.1/items/5?q=somequery" class="external-link" target="_blank">http://127.0.0.1/items/5?q=somequery</a> (or equivalent, using your Docker host).
|
||||
|
||||
You will see something like:
|
||||
|
||||
```JSON
|
||||
{"item_id": 5, "q": "somequery"}
|
||||
```
|
||||
|
||||
### Interactive API docs
|
||||
|
||||
Now you can go to <a href="http://192.168.99.100/docs" class="external-link" target="_blank">http://192.168.99.100/docs</a> or <a href="http://127.0.0.1/docs" class="external-link" target="_blank">http://127.0.0.1/docs</a> (or equivalent, using your Docker host).
|
||||
|
||||
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 you can also go to <a href="http://192.168.99.100/redoc" class="external-link" target="_blank">http://192.168.99.100/redoc</a> or <a href="http://127.0.0.1/redoc" class="external-link" target="_blank">http://127.0.0.1/redoc</a> (or equivalent, using your Docker host).
|
||||
|
||||
You will see the alternative automatic documentation (provided by <a href="https://github.com/Rebilly/ReDoc" class="external-link" target="_blank">ReDoc</a>):
|
||||
|
||||

|
||||
|
||||
## HTTPS
|
||||
|
||||
### About HTTPS
|
||||
|
||||
It is easy to assume that HTTPS is something that is just "enabled" or not.
|
||||
|
||||
But it is way more complex than that.
|
||||
|
||||
!!! tip
|
||||
If you are in a hurry or don't care, continue with the next section for step by step instructions to set everything up.
|
||||
|
||||
To learn the basics of HTTPS, from a consumer perspective, check <a href="https://howhttps.works/" class="external-link" target="_blank">https://howhttps.works/</a>.
|
||||
|
||||
Now, from a developer's perspective, here are several things to have in mind while thinking about HTTPS:
|
||||
|
||||
* For HTTPS, the server needs to have "certificates" generated by a third party.
|
||||
* Those certificates are actually acquired from the third-party, not "generated".
|
||||
* Certificates have a lifetime.
|
||||
* They expire.
|
||||
* And then they need to be renewed, acquired again from the third party.
|
||||
* The encryption of the connection happens at the TCP level.
|
||||
* That's one layer below HTTP.
|
||||
* So, the certificate and encryption handling is done before HTTP.
|
||||
* TCP doesn't know about "domains". Only about IP addresses.
|
||||
* The information about the specific domain requested goes in the HTTP data.
|
||||
* The HTTPS certificates "certify" a certain domain, but the protocol and encryption happen at the TCP level, before knowing which domain is being dealt with.
|
||||
* By default, that would mean that you can only have one HTTPS certificate per IP address.
|
||||
* No matter how big your server is or how small each application you have on it might be.
|
||||
* There is a solution to this, however.
|
||||
* There's an extension to the TLS protocol (the one handling the encryption at the TCP level, before HTTP) called <a href="https://en.wikipedia.org/wiki/Server_Name_Indication" class="external-link" target="_blank"><abbr title="Server Name Indication">SNI</abbr></a>.
|
||||
* This SNI extension allows one single server (with a single IP address) to have several HTTPS certificates and serve multiple HTTPS domains/applications.
|
||||
* For this to work, a single component (program) running on the server, listening on the public IP address, must have all the HTTPS certificates in the server.
|
||||
* After obtaining a secure connection, the communication protocol is still HTTP.
|
||||
* The contents are encrypted, even though they are being sent with the HTTP protocol.
|
||||
|
||||
It is a common practice to have one program/HTTP server running on the server (the machine, host, etc.) and managing all the HTTPS parts : sending the decrypted HTTP requests to the actual HTTP application running in the same server (the **FastAPI** application, in this case), take the HTTP response from the application, encrypt it using the appropriate certificate and sending it back to the client using HTTPS. This server is often called a <a href="https://en.wikipedia.org/wiki/TLS_termination_proxy" class="external-link" target="_blank">TLS Termination Proxy</a>.
|
||||
|
||||
### Let's Encrypt
|
||||
|
||||
Before Let's Encrypt, these HTTPS certificates were sold by trusted third-parties.
|
||||
|
||||
The process to acquire one of these certificates used to be cumbersome, require quite some paperwork and the certificates were quite expensive.
|
||||
|
||||
But then <a href="https://letsencrypt.org/" class="external-link" target="_blank">Let's Encrypt</a> was created.
|
||||
|
||||
It is a project from the Linux Foundation. It provides HTTPS certificates for free. In an automated way. These certificates use all the standard cryptographic security, and are short lived (about 3 months), so the security is actually better because of their reduced lifespan.
|
||||
|
||||
The domains are securely verified and the certificates are generated automatically. This also allows automating the renewal of these certificates.
|
||||
|
||||
The idea is to automate the acquisition and renewal of these certificates, so that you can have secure HTTPS, for free, forever.
|
||||
|
||||
### Traefik
|
||||
|
||||
<a href="https://traefik.io/" class="external-link" target="_blank">Traefik</a> is a high performance reverse proxy / load balancer. It can do the "TLS Termination Proxy" job (apart from other features).
|
||||
|
||||
It has integration with Let's Encrypt. So, it can handle all the HTTPS parts, including certificate acquisition and renewal.
|
||||
|
||||
It also has integrations with Docker. So, you can declare your domains in each application configurations and have it read those configurations, generate the HTTPS certificates and serve HTTPS to your application automatically, without requiring any change in its configuration.
|
||||
|
||||
---
|
||||
|
||||
With this information and tools, continue with the next section to combine everything.
|
||||
|
||||
## Docker Swarm mode cluster with Traefik and HTTPS
|
||||
|
||||
You can have a Docker Swarm mode cluster set up in minutes (about 20 min) with a main Traefik handling HTTPS (including certificate acquisition and renewal).
|
||||
|
||||
By using Docker Swarm mode, you can start with a "cluster" of a single machine (it can even be a $5 USD / month server) and then you can grow as much as you need adding more servers.
|
||||
|
||||
To set up a Docker Swarm Mode cluster with Traefik and HTTPS handling, follow this guide:
|
||||
|
||||
### <a href="https://medium.com/@tiangolo/docker-swarm-mode-and-traefik-for-a-https-cluster-20328dba6232" class="external-link" target="_blank">Docker Swarm Mode and Traefik for an HTTPS cluster</a>
|
||||
|
||||
### Deploy a FastAPI application
|
||||
|
||||
The easiest way to set everything up, would be using the [**FastAPI** Project Generators](project-generation.md){.internal-link target=_blank}.
|
||||
|
||||
It is designed to be integrated with this Docker Swarm cluster with Traefik and HTTPS described above.
|
||||
|
||||
You can generate a project in about 2 min.
|
||||
|
||||
The generated project has instructions to deploy it, doing it takes another 2 min.
|
||||
|
||||
## Alternatively, deploy **FastAPI** without Docker
|
||||
|
||||
You can deploy **FastAPI** directly without Docker too.
|
||||
|
||||
You just need to install an ASGI compatible server like:
|
||||
|
||||
=== "Uvicorn"
|
||||
|
||||
* <a href="https://www.uvicorn.org/" class="external-link" target="_blank">Uvicorn</a>, a lightning-fast ASGI server, built on uvloop and httptools.
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ pip install uvicorn
|
||||
|
||||
---> 100%
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
=== "Hypercorn"
|
||||
|
||||
* <a href="https://gitlab.com/pgjones/hypercorn" class="external-link" target="_blank">Hypercorn</a>, an ASGI server also compatible with HTTP/2.
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ pip install hypercorn
|
||||
|
||||
---> 100%
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
...or any other ASGI server.
|
||||
|
||||
And run your application the same way you have done in the tutorials, but without the `--reload` option, e.g.:
|
||||
|
||||
=== "Uvicorn"
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ uvicorn main:app --host 0.0.0.0 --port 80
|
||||
|
||||
<span style="color: green;">INFO</span>: Uvicorn running on http://0.0.0.0:80 (Press CTRL+C to quit)
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
=== "Hypercorn"
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ hypercorn main:app --bind 0.0.0.0:80
|
||||
|
||||
Running on 0.0.0.0:8080 over http (CTRL + C to quit)
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
You might want to set up some tooling to make sure it is restarted automatically if it stops.
|
||||
|
||||
You might also want to install <a href="https://gunicorn.org/" class="external-link" target="_blank">Gunicorn</a> and <a href="https://www.uvicorn.org/#running-with-gunicorn" class="external-link" target="_blank">use it as a manager for Uvicorn</a>, or use Hypercorn with multiple workers.
|
||||
|
||||
Making sure to fine-tune the number of workers, etc.
|
||||
|
||||
But if you are doing all that, you might just use the Docker image that does it automatically.
|
||||
240
docs/en/docs/deployment/deta.md
Normal file
@@ -0,0 +1,240 @@
|
||||
# Deploy FastAPI on Deta
|
||||
|
||||
In this section you will learn how to easily deploy a **FastAPI** application on <a href="https://www.deta.sh/?ref=fastapi" class="external-link" target="_blank">Deta</a> using the free plan. 🎁
|
||||
|
||||
It will take you about **10 minutes**.
|
||||
|
||||
!!! info
|
||||
<a href="https://www.deta.sh/?ref=fastapi" class="external-link" target="_blank">Deta</a> is a **FastAPI** sponsor. 🎉
|
||||
|
||||
## A basic **FastAPI** app
|
||||
|
||||
* Create a directory for your app, for example `./fastapideta/` and enter in it.
|
||||
|
||||
### FastAPI code
|
||||
|
||||
* Create a `main.py` file with:
|
||||
|
||||
```Python
|
||||
from fastapi import FastAPI
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
|
||||
@app.get("/")
|
||||
def read_root():
|
||||
return {"Hello": "World"}
|
||||
|
||||
|
||||
@app.get("/items/{item_id}")
|
||||
def read_item(item_id: int):
|
||||
return {"item_id": item_id}
|
||||
```
|
||||
|
||||
### Requirements
|
||||
|
||||
Now, in the same directory create a file `requirements.txt` with:
|
||||
|
||||
```text
|
||||
fastapi
|
||||
```
|
||||
|
||||
!!! tip
|
||||
You don't need to install Uvicorn to deploy on Deta, although you would probably want to install it locally to test your app.
|
||||
|
||||
### Directory structure
|
||||
|
||||
You will now have one directory `./fastapideta/` with two files:
|
||||
|
||||
```
|
||||
.
|
||||
└── main.py
|
||||
└── requirements.txt
|
||||
```
|
||||
|
||||
## Create a free Deta account
|
||||
|
||||
Now create a <a href="https://www.deta.sh/?ref=fastapi" class="external-link" target="_blank">free account on Deta</a>, you just need an email and password.
|
||||
|
||||
You don't even need a credit card.
|
||||
|
||||
## Install the CLI
|
||||
|
||||
Once you have your account, install the Deta <abbr title="Command Line Interface application">CLI</abbr>:
|
||||
|
||||
=== "Linux, macOS"
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ curl -fsSL https://get.deta.dev/cli.sh | sh
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
=== "Windows PowerShell"
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ iwr https://get.deta.dev/cli.ps1 -useb | iex
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
After installing it, open a new terminal so that the installed CLI is detected.
|
||||
|
||||
In a new terminal, confirm that it was correctly installed with:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ deta --help
|
||||
|
||||
Deta command line interface for managing deta micros.
|
||||
Complete documentation available at https://docs.deta.sh
|
||||
|
||||
Usage:
|
||||
deta [flags]
|
||||
deta [command]
|
||||
|
||||
Available Commands:
|
||||
auth Change auth settings for a deta micro
|
||||
|
||||
...
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
!!! tip
|
||||
If you have problems installing the CLI, check the <a href="https://docs.deta.sh/docs/micros/getting_started?ref=fastapi" class="external-link" target="_blank">official Deta docs</a>.
|
||||
|
||||
## Login with the CLI
|
||||
|
||||
Now login to Deta from the CLI with:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ deta login
|
||||
|
||||
Please, log in from the web page. Waiting..
|
||||
Logged in successfully.
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
This will open a web browser and authenticate automatically.
|
||||
|
||||
## Deploy with Deta
|
||||
|
||||
Next, deploy your application with the Deta CLI:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ deta new
|
||||
|
||||
Successfully created a new micro
|
||||
|
||||
// Notice the "endpoint" 🔍
|
||||
|
||||
{
|
||||
"name": "fastapideta",
|
||||
"runtime": "python3.7",
|
||||
"endpoint": "https://qltnci.deta.dev",
|
||||
"visor": "enabled",
|
||||
"http_auth": "enabled"
|
||||
}
|
||||
|
||||
Adding dependencies...
|
||||
|
||||
|
||||
---> 100%
|
||||
|
||||
|
||||
Successfully installed fastapi-0.61.1 pydantic-1.7.2 starlette-0.13.6
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
You will see a JSON message similar to:
|
||||
|
||||
```JSON hl_lines="4"
|
||||
{
|
||||
"name": "fastapideta",
|
||||
"runtime": "python3.7",
|
||||
"endpoint": "https://qltnci.deta.dev",
|
||||
"visor": "enabled",
|
||||
"http_auth": "enabled"
|
||||
}
|
||||
```
|
||||
|
||||
!!! tip
|
||||
Your deployment will have a different `"endpoint"` URL.
|
||||
|
||||
## Check it
|
||||
|
||||
Now open your browser in your `endpoint` URL. In the example above it was `https://qltnci.deta.dev`, but yours will be different.
|
||||
|
||||
You will see the JSON response from your FastAPI app:
|
||||
|
||||
```JSON
|
||||
{
|
||||
"Hello": "World"
|
||||
}
|
||||
```
|
||||
|
||||
And now go to the `/docs` for your API, in the example above it would be `https://qltnci.deta.dev/docs`.
|
||||
|
||||
It will show your docs like:
|
||||
|
||||
<img src="/img/deployment/deta/image01.png">
|
||||
|
||||
## Enable public access
|
||||
|
||||
By default, Deta will handle authentication using cookies for your account.
|
||||
|
||||
But once you are ready, you can make it public with:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ deta auth disable
|
||||
|
||||
Successfully disabled http auth
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
Now you can share that URL with anyone and they will be able to access your API. 🚀
|
||||
|
||||
## HTTPS
|
||||
|
||||
Congrats! You deployed your FastAPI app to Deta! 🎉 🍰
|
||||
|
||||
Also notice that Deta correctly handles HTTPS for you, so you don't have to take care of that and can be sure that your clients will have a secure encrypted connection. ✅ 🔒
|
||||
|
||||
## Check the Visor
|
||||
|
||||
From your docs UI (they will be in a URL like `https://qltnci.deta.dev/docs`) send a request to your *path operation* `/items/{item_id}`.
|
||||
|
||||
For example with ID `5`.
|
||||
|
||||
Now go to <a href="https://web.deta.sh/" class="external-link" target="_blank">https://web.deta.sh</a>.
|
||||
|
||||
You will see there's a section to the left called <abbr title="it comes from Micro(server)">"Micros"</abbr> with each of your apps.
|
||||
|
||||
You will see a tab with "Details", and also a tab "Visor", go to the tab "Visor".
|
||||
|
||||
In there you can inspect the recent requests sent to your app.
|
||||
|
||||
You can also edit them and re-play them.
|
||||
|
||||
<img src="/img/deployment/deta/image02.png">
|
||||
|
||||
## Learn more
|
||||
|
||||
At some point you will probably want to store some data for your app in a way that persists through time. For that you can use <a href="https://docs.deta.sh/docs/base/py_tutorial?ref=fastapi" class="external-link" target="_blank">Deta Base</a>, it also has a generous **free tier**.
|
||||
|
||||
You can also read more in the <a href="https://docs.deta.sh?ref=fastapi" class="external-link" target="_blank">Deta Docs</a>.
|
||||
179
docs/en/docs/deployment/docker.md
Normal file
@@ -0,0 +1,179 @@
|
||||
# Deploy with Docker
|
||||
|
||||
In this section you'll see instructions and links to guides to know how to:
|
||||
|
||||
* Make your **FastAPI** application a Docker image/container with maximum performance. In about **5 min**.
|
||||
* (Optionally) understand what you, as a developer, need to know about HTTPS.
|
||||
* Set up a Docker Swarm mode cluster with automatic HTTPS, even on a simple $5 USD/month server. In about **20 min**.
|
||||
* Generate and deploy a full **FastAPI** application, using your Docker Swarm cluster, with HTTPS, etc. In about **10 min**.
|
||||
|
||||
You can use <a href="https://www.docker.com/" class="external-link" target="_blank">**Docker**</a> for deployment. It has several advantages like security, replicability, development simplicity, etc.
|
||||
|
||||
If you are using Docker, you can use the official Docker image:
|
||||
|
||||
## <a href="https://github.com/tiangolo/uvicorn-gunicorn-fastapi-docker" class="external-link" target="_blank">tiangolo/uvicorn-gunicorn-fastapi</a>
|
||||
|
||||
This image has an "auto-tuning" mechanism included, so that you can just add your code and get very high performance automatically. And without making sacrifices.
|
||||
|
||||
But you can still change and update all the configurations with environment variables or configuration files.
|
||||
|
||||
!!! tip
|
||||
To see all the configurations and options, go to the Docker image page: <a href="https://github.com/tiangolo/uvicorn-gunicorn-fastapi-docker" class="external-link" target="_blank">tiangolo/uvicorn-gunicorn-fastapi</a>.
|
||||
|
||||
## Create a `Dockerfile`
|
||||
|
||||
* Go to your project directory.
|
||||
* Create a `Dockerfile` with:
|
||||
|
||||
```Dockerfile
|
||||
FROM tiangolo/uvicorn-gunicorn-fastapi:python3.7
|
||||
|
||||
COPY ./app /app
|
||||
```
|
||||
|
||||
### Bigger Applications
|
||||
|
||||
If you followed the section about creating [Bigger Applications with Multiple Files](../tutorial/bigger-applications.md){.internal-link target=_blank}, your `Dockerfile` might instead look like:
|
||||
|
||||
```Dockerfile
|
||||
FROM tiangolo/uvicorn-gunicorn-fastapi:python3.7
|
||||
|
||||
COPY ./app /app/app
|
||||
```
|
||||
|
||||
### Raspberry Pi and other architectures
|
||||
|
||||
If you are running Docker in a Raspberry Pi (that has an ARM processor) or any other architecture, you can create a `Dockerfile` from scratch, based on a Python base image (that is multi-architecture) and use Uvicorn alone.
|
||||
|
||||
In this case, your `Dockerfile` could look like:
|
||||
|
||||
```Dockerfile
|
||||
FROM python:3.7
|
||||
|
||||
RUN pip install fastapi uvicorn
|
||||
|
||||
EXPOSE 80
|
||||
|
||||
COPY ./app /app
|
||||
|
||||
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80"]
|
||||
```
|
||||
|
||||
## Create the **FastAPI** Code
|
||||
|
||||
* Create an `app` directory and enter in it.
|
||||
* Create a `main.py` file with:
|
||||
|
||||
```Python
|
||||
from 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}
|
||||
```
|
||||
|
||||
* You should now have a directory structure like:
|
||||
|
||||
```
|
||||
.
|
||||
├── app
|
||||
│ └── main.py
|
||||
└── Dockerfile
|
||||
```
|
||||
|
||||
## Build the Docker image
|
||||
|
||||
* Go to the project directory (in where your `Dockerfile` is, containing your `app` directory).
|
||||
* Build your FastAPI image:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ docker build -t myimage .
|
||||
|
||||
---> 100%
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
## Start the Docker container
|
||||
|
||||
* Run a container based on your image:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ docker run -d --name mycontainer -p 80:80 myimage
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
Now you have an optimized FastAPI server in a Docker container. Auto-tuned for your current server (and number of CPU cores).
|
||||
|
||||
## Check it
|
||||
|
||||
You should be able to check it in your Docker container's URL, for example: <a href="http://192.168.99.100/items/5?q=somequery" class="external-link" target="_blank">http://192.168.99.100/items/5?q=somequery</a> or <a href="http://127.0.0.1/items/5?q=somequery" class="external-link" target="_blank">http://127.0.0.1/items/5?q=somequery</a> (or equivalent, using your Docker host).
|
||||
|
||||
You will see something like:
|
||||
|
||||
```JSON
|
||||
{"item_id": 5, "q": "somequery"}
|
||||
```
|
||||
|
||||
## Interactive API docs
|
||||
|
||||
Now you can go to <a href="http://192.168.99.100/docs" class="external-link" target="_blank">http://192.168.99.100/docs</a> or <a href="http://127.0.0.1/docs" class="external-link" target="_blank">http://127.0.0.1/docs</a> (or equivalent, using your Docker host).
|
||||
|
||||
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 you can also go to <a href="http://192.168.99.100/redoc" class="external-link" target="_blank">http://192.168.99.100/redoc</a> or <a href="http://127.0.0.1/redoc" class="external-link" target="_blank">http://127.0.0.1/redoc</a> (or equivalent, using your Docker host).
|
||||
|
||||
You will see the alternative automatic documentation (provided by <a href="https://github.com/Rebilly/ReDoc" class="external-link" target="_blank">ReDoc</a>):
|
||||
|
||||

|
||||
|
||||
## Traefik
|
||||
|
||||
<a href="https://traefik.io/" class="external-link" target="_blank">Traefik</a> is a high performance reverse proxy / load balancer. It can do the "TLS Termination Proxy" job (apart from other features).
|
||||
|
||||
It has integration with Let's Encrypt. So, it can handle all the HTTPS parts, including certificate acquisition and renewal.
|
||||
|
||||
It also has integrations with Docker. So, you can declare your domains in each application configurations and have it read those configurations, generate the HTTPS certificates and serve HTTPS to your application automatically, without requiring any change in its configuration.
|
||||
|
||||
---
|
||||
|
||||
With this information and tools, continue with the next section to combine everything.
|
||||
|
||||
## Docker Swarm mode cluster with Traefik and HTTPS
|
||||
|
||||
You can have a Docker Swarm mode cluster set up in minutes (about 20 min) with a main Traefik handling HTTPS (including certificate acquisition and renewal).
|
||||
|
||||
By using Docker Swarm mode, you can start with a "cluster" of a single machine (it can even be a $5 USD / month server) and then you can grow as much as you need adding more servers.
|
||||
|
||||
To set up a Docker Swarm Mode cluster with Traefik and HTTPS handling, follow this guide:
|
||||
|
||||
### <a href="https://medium.com/@tiangolo/docker-swarm-mode-and-traefik-for-a-https-cluster-20328dba6232" class="external-link" target="_blank">Docker Swarm Mode and Traefik for an HTTPS cluster</a>
|
||||
|
||||
### Deploy a FastAPI application
|
||||
|
||||
The easiest way to set everything up, would be using the [**FastAPI** Project Generators](../project-generation.md){.internal-link target=_blank}.
|
||||
|
||||
It is designed to be integrated with this Docker Swarm cluster with Traefik and HTTPS described above.
|
||||
|
||||
You can generate a project in about 2 min.
|
||||
|
||||
The generated project has instructions to deploy it, doing it takes another 2 min.
|
||||
48
docs/en/docs/deployment/https.md
Normal file
@@ -0,0 +1,48 @@
|
||||
# About HTTPS
|
||||
|
||||
It is easy to assume that HTTPS is something that is just "enabled" or not.
|
||||
|
||||
But it is way more complex than that.
|
||||
|
||||
!!! tip
|
||||
If you are in a hurry or don't care, continue with the next sections for step by step instructions to set everything up with different techniques.
|
||||
|
||||
To learn the basics of HTTPS, from a consumer perspective, check <a href="https://howhttps.works/" class="external-link" target="_blank">https://howhttps.works/</a>.
|
||||
|
||||
Now, from a developer's perspective, here are several things to have in mind while thinking about HTTPS:
|
||||
|
||||
* For HTTPS, the server needs to have "certificates" generated by a third party.
|
||||
* Those certificates are actually acquired from the third-party, not "generated".
|
||||
* Certificates have a lifetime.
|
||||
* They expire.
|
||||
* And then they need to be renewed, acquired again from the third party.
|
||||
* The encryption of the connection happens at the TCP level.
|
||||
* That's one layer below HTTP.
|
||||
* So, the certificate and encryption handling is done before HTTP.
|
||||
* TCP doesn't know about "domains". Only about IP addresses.
|
||||
* The information about the specific domain requested goes in the HTTP data.
|
||||
* The HTTPS certificates "certify" a certain domain, but the protocol and encryption happen at the TCP level, before knowing which domain is being dealt with.
|
||||
* By default, that would mean that you can only have one HTTPS certificate per IP address.
|
||||
* No matter how big your server is or how small each application you have on it might be.
|
||||
* There is a solution to this, however.
|
||||
* There's an extension to the TLS protocol (the one handling the encryption at the TCP level, before HTTP) called <a href="https://en.wikipedia.org/wiki/Server_Name_Indication" class="external-link" target="_blank"><abbr title="Server Name Indication">SNI</abbr></a>.
|
||||
* This SNI extension allows one single server (with a single IP address) to have several HTTPS certificates and serve multiple HTTPS domains/applications.
|
||||
* For this to work, a single component (program) running on the server, listening on the public IP address, must have all the HTTPS certificates in the server.
|
||||
* After obtaining a secure connection, the communication protocol is still HTTP.
|
||||
* The contents are encrypted, even though they are being sent with the HTTP protocol.
|
||||
|
||||
It is a common practice to have one program/HTTP server running on the server (the machine, host, etc.) and managing all the HTTPS parts : sending the decrypted HTTP requests to the actual HTTP application running in the same server (the **FastAPI** application, in this case), take the HTTP response from the application, encrypt it using the appropriate certificate and sending it back to the client using HTTPS. This server is often called a <a href="https://en.wikipedia.org/wiki/TLS_termination_proxy" class="external-link" target="_blank">TLS Termination Proxy</a>.
|
||||
|
||||
## Let's Encrypt
|
||||
|
||||
Before Let's Encrypt, these HTTPS certificates were sold by trusted third-parties.
|
||||
|
||||
The process to acquire one of these certificates used to be cumbersome, require quite some paperwork and the certificates were quite expensive.
|
||||
|
||||
But then <a href="https://letsencrypt.org/" class="external-link" target="_blank">Let's Encrypt</a> was created.
|
||||
|
||||
It is a project from the Linux Foundation. It provides HTTPS certificates for free. In an automated way. These certificates use all the standard cryptographic security, and are short lived (about 3 months), so the security is actually better because of their reduced lifespan.
|
||||
|
||||
The domains are securely verified and the certificates are generated automatically. This also allows automating the renewal of these certificates.
|
||||
|
||||
The idea is to automate the acquisition and renewal of these certificates, so that you can have secure HTTPS, for free, forever.
|
||||
7
docs/en/docs/deployment/index.md
Normal file
@@ -0,0 +1,7 @@
|
||||
# Deployment - Intro
|
||||
|
||||
Deploying a **FastAPI** application is relatively easy.
|
||||
|
||||
There are several ways to do it depending on your specific use case and the tools that you use.
|
||||
|
||||
You will see more details to have in mind and some of the techniques to do it in the next sections.
|
||||
74
docs/en/docs/deployment/manually.md
Normal file
@@ -0,0 +1,74 @@
|
||||
# Deploy manually
|
||||
|
||||
You can deploy **FastAPI** manually as well.
|
||||
|
||||
You just need to install an ASGI compatible server like:
|
||||
|
||||
=== "Uvicorn"
|
||||
|
||||
* <a href="https://www.uvicorn.org/" class="external-link" target="_blank">Uvicorn</a>, a lightning-fast ASGI server, built on uvloop and httptools.
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ pip install uvicorn[standard]
|
||||
|
||||
---> 100%
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
!!! tip
|
||||
By adding the `standard`, Uvicorn will install and use some recommended extra dependencies.
|
||||
|
||||
That including `uvloop`, the high-performance drop-in replacement for `asyncio`, that provides the big concurrency performance boost.
|
||||
|
||||
=== "Hypercorn"
|
||||
|
||||
* <a href="https://gitlab.com/pgjones/hypercorn" class="external-link" target="_blank">Hypercorn</a>, an ASGI server also compatible with HTTP/2.
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ pip install hypercorn
|
||||
|
||||
---> 100%
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
...or any other ASGI server.
|
||||
|
||||
And run your application the same way you have done in the tutorials, but without the `--reload` option, e.g.:
|
||||
|
||||
=== "Uvicorn"
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ uvicorn main:app --host 0.0.0.0 --port 80
|
||||
|
||||
<span style="color: green;">INFO</span>: Uvicorn running on http://0.0.0.0:80 (Press CTRL+C to quit)
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
=== "Hypercorn"
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ hypercorn main:app --bind 0.0.0.0:80
|
||||
|
||||
Running on 0.0.0.0:8080 over http (CTRL + C to quit)
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
You might want to set up some tooling to make sure it is restarted automatically if it stops.
|
||||
|
||||
You might also want to install <a href="https://gunicorn.org/" class="external-link" target="_blank">Gunicorn</a> and <a href="https://www.uvicorn.org/#running-with-gunicorn" class="external-link" target="_blank">use it as a manager for Uvicorn</a>, or use Hypercorn with multiple workers.
|
||||
|
||||
Making sure to fine-tune the number of workers, etc.
|
||||
|
||||
But if you are doing all that, you might just use the Docker image that does it automatically.
|
||||
87
docs/en/docs/deployment/versions.md
Normal file
@@ -0,0 +1,87 @@
|
||||
# About FastAPI versions
|
||||
|
||||
**FastAPI** is already being used in production in many applications and systems. And the test coverage is kept at 100%. But its development is still moving quickly.
|
||||
|
||||
New features are added frequently, bugs are fixed regularly, and the code is still continuously improving.
|
||||
|
||||
That's why the current versions are still `0.x.x`, this reflects that each version could potentially have breaking changes. This follows the <a href="https://semver.org/" class="external-link" target="_blank">Semantic Versioning</a> conventions.
|
||||
|
||||
You can create production applications with **FastAPI** right now (and you have probably been doing it for some time), you just have to make sure that you use a version that works correctly with the rest of your code.
|
||||
|
||||
## Pin your `fastapi` version
|
||||
|
||||
The first thing you should do is to "pin" the version of **FastAPI** you are using to the specific latest version that you know works correctly for your application.
|
||||
|
||||
For example, let's say you are using version `0.45.0` in your app.
|
||||
|
||||
If you use a `requirements.txt` file you could specify the version with:
|
||||
|
||||
```txt
|
||||
fastapi==0.45.0
|
||||
```
|
||||
|
||||
that would mean that you would use exactly the version `0.45.0`.
|
||||
|
||||
Or you could also pin it with:
|
||||
|
||||
```txt
|
||||
fastapi>=0.45.0,<0.46.0
|
||||
```
|
||||
|
||||
that would mean that you would use the versions `0.45.0` or above, but less than `0.46.0`, for example, a version `0.45.2` would still be accepted.
|
||||
|
||||
If you use any other tool to manage your installations, like Poetry, Pipenv, or others, they all have a way that you can use to define specific versions for your packages.
|
||||
|
||||
## Available versions
|
||||
|
||||
You can see the available versions (e.g. to check what is the current latest) in the [Release Notes](../release-notes.md){.internal-link target=_blank}.
|
||||
|
||||
## About versions
|
||||
|
||||
Following the Semantic Versioning conventions, any version below `1.0.0` could potentially add breaking changes.
|
||||
|
||||
FastAPI also follows the convention that any "PATCH" version change is for bug fixes and non-breaking changes.
|
||||
|
||||
!!! tip
|
||||
The "PATCH" is the last number, for example, in `0.2.3`, the PATCH version is `3`.
|
||||
|
||||
So, you should be able to pin to a version like:
|
||||
|
||||
```txt
|
||||
fastapi>=0.45.0,<0.46.0
|
||||
```
|
||||
|
||||
Breaking changes and new features are added in "MINOR" versions.
|
||||
|
||||
!!! tip
|
||||
The "MINOR" is the number in the middle, for example, in `0.2.3`, the MINOR version is `2`.
|
||||
|
||||
## Upgrading the FastAPI versions
|
||||
|
||||
You should add tests for your app.
|
||||
|
||||
With **FastAPI** it's very easy (thanks to Starlette), check the docs: [Testing](../tutorial/testing.md){.internal-link target=_blank}
|
||||
|
||||
After you have tests, then you can upgrade the **FastAPI** version to a more recent one, and make sure that all your code is working correctly by running your tests.
|
||||
|
||||
If everything is working, or after you make the necessary changes, and all your tests are passing, then you can pin your `fastapi` to that new recent version.
|
||||
|
||||
## About Starlette
|
||||
|
||||
You shouldn't pin the version of `starlette`.
|
||||
|
||||
Different versions of **FastAPI** will use a specific newer version of Starlette.
|
||||
|
||||
So, you can just let **FastAPI** use the correct Starlette version.
|
||||
|
||||
## About Pydantic
|
||||
|
||||
Pydantic includes the tests for **FastAPI** with its own tests, so new versions of Pydantic (above `1.0.0`) are always compatible with FastAPI.
|
||||
|
||||
You can pin Pydantic to any version above `1.0.0` that works for you and below `2.0.0`.
|
||||
|
||||
For example:
|
||||
|
||||
```txt
|
||||
pydantic>=1.2.0,<2.0.0
|
||||
```
|
||||
177
docs/en/docs/fastapi-people.md
Normal file
@@ -0,0 +1,177 @@
|
||||
# FastAPI People
|
||||
|
||||
FastAPI has an amazing community that welcomes people from all backgrounds.
|
||||
|
||||
## Creator - Maintainer
|
||||
|
||||
Hey! 👋
|
||||
|
||||
This is me:
|
||||
|
||||
{% if people %}
|
||||
<div class="user-list user-list-center">
|
||||
{% for user in people.maintainers %}
|
||||
|
||||
<div class="user"><a href="{{ user.url }}" target="_blank"><div class="avatar-wrapper"><img src="{{ user.avatarUrl }}"/></div><div class="title">@{{ user.login }}</div></a> <div class="count">Answers: {{ user.answers }}</div><div class="count">Pull Requests: {{ user.prs }}</div></div>
|
||||
{% endfor %}
|
||||
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
I'm the creator and maintainer of **FastAPI**. You can read more about that in [Help FastAPI - Get Help - Connect with the author](help-fastapi.md#connect-with-the-author){.internal-link target=_blank}.
|
||||
|
||||
...But here I want to show you the community.
|
||||
|
||||
---
|
||||
|
||||
**FastAPI** receives a lot of support from the community. And I want to highlight their contributions.
|
||||
|
||||
These are the people that:
|
||||
|
||||
* [Help others with issues (questions) in GitHub](help-fastapi.md#help-others-with-issues-in-github){.internal-link target=_blank}.
|
||||
* [Create Pull Requests](help-fastapi.md#create-a-pull-request){.internal-link target=_blank}.
|
||||
* Review Pull Requests, [especially important for translations](contributing.md#translations){.internal-link target=_blank}.
|
||||
|
||||
A round of applause to them. 👏 🙇
|
||||
|
||||
## Most active users last month
|
||||
|
||||
These are the users that have been [helping others the most with issues (questions) in GitHub](help-fastapi.md#help-others-with-issues-in-github){.internal-link target=_blank} during the last month. ☕
|
||||
|
||||
{% if people %}
|
||||
<div class="user-list user-list-center">
|
||||
{% for user in people.last_month_active %}
|
||||
|
||||
<div class="user"><a href="{{ user.url }}" target="_blank"><div class="avatar-wrapper"><img src="{{ user.avatarUrl }}"/></div><div class="title">@{{ user.login }}</div></a> <div class="count">Issues replied: {{ user.count }}</div></div>
|
||||
{% endfor %}
|
||||
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
## Experts
|
||||
|
||||
Here are the **FastAPI Experts**. 🤓
|
||||
|
||||
These are the users that have [helped others the most with issues (questions) in GitHub](help-fastapi.md#help-others-with-issues-in-github){.internal-link target=_blank} through *all time*.
|
||||
|
||||
They have proven to be experts by helping many others. ✨
|
||||
|
||||
{% if people %}
|
||||
<div class="user-list user-list-center">
|
||||
{% for user in people.experts %}
|
||||
|
||||
<div class="user"><a href="{{ user.url }}" target="_blank"><div class="avatar-wrapper"><img src="{{ user.avatarUrl }}"/></div><div class="title">@{{ user.login }}</div></a> <div class="count">Issues replied: {{ user.count }}</div></div>
|
||||
{% endfor %}
|
||||
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
## Top Contributors
|
||||
|
||||
Here are the **Top Contributors**. 👷
|
||||
|
||||
These users have [created the most Pull Requests](help-fastapi.md#create-a-pull-request){.internal-link target=_blank} that have been *merged*.
|
||||
|
||||
They have contributed source code, documentation, translations, etc. 📦
|
||||
|
||||
{% if people %}
|
||||
<div class="user-list user-list-center">
|
||||
{% for user in people.top_contributors %}
|
||||
|
||||
<div class="user"><a href="{{ user.url }}" target="_blank"><div class="avatar-wrapper"><img src="{{ user.avatarUrl }}"/></div><div class="title">@{{ user.login }}</div></a> <div class="count">Pull Requests: {{ user.count }}</div></div>
|
||||
{% endfor %}
|
||||
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
There are many other contributors (more than a hundred), you can see them all in the <a href="https://github.com/tiangolo/fastapi/graphs/contributors" class="external-link" target="_blank">FastAPI GitHub Contributors page</a>. 👷
|
||||
|
||||
## Top Reviewers
|
||||
|
||||
These users are the **Top Reviewers**. 🕵️
|
||||
|
||||
### Reviews for Translations
|
||||
|
||||
I only speak a few languages (and not very well 😅). So, the reviewers are the ones that have the [**power to approve translations**](contributing.md#translations){.internal-link target=_blank} of the documentation. Without them, there wouldn't be documentation in several other languages.
|
||||
|
||||
---
|
||||
|
||||
The **Top Reviewers** 🕵️ have reviewed the most Pull Requests from others, ensuring the quality of the code, documentation, and especially, the **translations**.
|
||||
|
||||
{% if people %}
|
||||
<div class="user-list user-list-center">
|
||||
{% for user in people.top_reviewers %}
|
||||
|
||||
<div class="user"><a href="{{ user.url }}" target="_blank"><div class="avatar-wrapper"><img src="{{ user.avatarUrl }}"/></div><div class="title">@{{ user.login }}</div></a> <div class="count">Reviews: {{ user.count }}</div></div>
|
||||
{% endfor %}
|
||||
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
## Sponsors
|
||||
|
||||
These are the **Sponsors**. 😎
|
||||
|
||||
They are supporting my work with **FastAPI** (and others), mainly through <a href="https://github.com/sponsors/tiangolo" class="external-link" target="_blank">GitHub Sponsors</a>.
|
||||
|
||||
### Gold Sponsors
|
||||
|
||||
{% if sponsors %}
|
||||
{% for sponsor in sponsors.gold -%}
|
||||
<a href="{{ sponsor.url }}" target="_blank" title="{{ sponsor.title }}"><img src="{{ sponsor.img }}"></a>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
### Silver Sponsors
|
||||
|
||||
{% if sponsors %}
|
||||
{% for sponsor in sponsors.silver -%}
|
||||
<a href="{{ sponsor.url }}" target="_blank" title="{{ sponsor.title }}"><img src="{{ sponsor.img }}"></a>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
### Bronze Sponsors
|
||||
|
||||
{% if sponsors %}
|
||||
{% for sponsor in sponsors.bronze -%}
|
||||
<a href="{{ sponsor.url }}" target="_blank" title="{{ sponsor.title }}"><img src="{{ sponsor.img }}"></a>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
### Individual Sponsors
|
||||
|
||||
{% if people %}
|
||||
{% if people.sponsors_50 %}
|
||||
|
||||
<div class="user-list user-list-center">
|
||||
{% for user in people.sponsors_50 %}
|
||||
|
||||
<div class="user"><a href="{{ user.url }}" target="_blank"><div class="avatar-wrapper"><img src="{{ user.avatarUrl }}"/></div><div class="title">@{{ user.login }}</div></a></div>
|
||||
{% endfor %}
|
||||
|
||||
</div>
|
||||
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
{% if people %}
|
||||
<div class="user-list user-list-center">
|
||||
{% for user in people.sponsors %}
|
||||
|
||||
<div class="user"><a href="{{ user.url }}" target="_blank"><div class="avatar-wrapper"><img src="{{ user.avatarUrl }}"/></div><div class="title">@{{ user.login }}</div></a></div>
|
||||
{% endfor %}
|
||||
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
## About the data - technical details
|
||||
|
||||
The main intention of this page is to highlight the effort of the community to help others.
|
||||
|
||||
Especially including efforts that are normally less visible, and in many cases more arduous, like helping others with issues and reviewing Pull Requests with translations.
|
||||
|
||||
The data is calculated each month, you can read the <a href="https://github.com/tiangolo/fastapi/blob/master/.github/actions/people/app/main.py" class="external-link" target="_blank">source code here</a>.
|
||||
|
||||
Here I'm also highlighting contributions from sponsors.
|
||||
|
||||
I also reserve the right to update the algorithm, sections, thresholds, etc (just in case 🤷).
|
||||
@@ -7,7 +7,7 @@
|
||||
### Based on open standards
|
||||
|
||||
* <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank"><strong>OpenAPI</strong></a> for API creation, including declarations of <abbr title="also known as: endpoints, routes">path</abbr> <abbr title="also known as HTTP methods, as POST, GET, PUT, DELETE">operations</abbr>, parameters, body requests, security, etc.
|
||||
* Automatic data model documentation with <a href="http://json-schema.org/" class="external-link" target="_blank"><strong>JSON Schema</strong></a> (as OpenAPI itself is based on JSON Schema).
|
||||
* Automatic data model documentation with <a href="https://json-schema.org/" class="external-link" target="_blank"><strong>JSON Schema</strong></a> (as OpenAPI itself is based on JSON Schema).
|
||||
* Designed around these standards, after a meticulous study. Instead of an afterthought layer on top.
|
||||
* This also allows using automatic **client code generation** in many languages.
|
||||
|
||||
|
||||
@@ -10,6 +10,16 @@ There are very simple ways to help (several involve just one or two clicks).
|
||||
|
||||
And there are several ways to get help too.
|
||||
|
||||
## Subscribe to the newsletter
|
||||
|
||||
You can subscribe to the (infrequent) [**FastAPI and friends** newsletter](/newsletter/){.internal-link target=_blank} to stay updated about:
|
||||
|
||||
* News about FastAPI and friends 🚀
|
||||
* Guides 📝
|
||||
* Features ✨
|
||||
* Breaking changes 🚨
|
||||
* Tips and tricks ✅
|
||||
|
||||
## Star **FastAPI** in GitHub
|
||||
|
||||
You can "star" FastAPI in GitHub (clicking the star button at the top right): <a href="https://github.com/tiangolo/fastapi" class="external-link" target="_blank">https://github.com/tiangolo/fastapi</a>. ⭐️
|
||||
@@ -52,12 +62,13 @@ I love to hear about how **FastAPI** is being used, what have you liked in it, i
|
||||
|
||||
* <a href="https://www.slant.co/options/34241/~fastapi-review" class="external-link" target="_blank">Vote for **FastAPI** in Slant</a>.
|
||||
* <a href="https://alternativeto.net/software/fastapi/" class="external-link" target="_blank">Vote for **FastAPI** in AlternativeTo</a>.
|
||||
* <a href="https://github.com/marmelab/awesome-rest/pull/93" class="external-link" target="_blank">Vote for **FastAPI** on awesome-rest</a>.
|
||||
|
||||
## Help others with issues in GitHub
|
||||
|
||||
You can see <a href="https://github.com/tiangolo/fastapi/issues" class="external-link" target="_blank">existing issues</a> and try and help others, most of the times they are questions that you might already know the answer for. 🤓
|
||||
|
||||
If you are helping a lot of people on issues you might become an official [FastAPI Expert](fastapi-people.md#experts){.internal-link target=_blank}. 🎉
|
||||
|
||||
## Watch the GitHub repository
|
||||
|
||||
You can "watch" FastAPI in GitHub (clicking the "watch" button at the top right): <a href="https://github.com/tiangolo/fastapi" class="external-link" target="_blank">https://github.com/tiangolo/fastapi</a>. 👀
|
||||
@@ -70,43 +81,52 @@ Then you can try and help them solving those issues.
|
||||
|
||||
You can <a href="https://github.com/tiangolo/fastapi/issues/new/choose" class="external-link" target="_blank">create a new issue</a> in the GitHub repository, for example to:
|
||||
|
||||
* Ask a question or ask about a problem.
|
||||
* Suggest a new feature.
|
||||
* Ask a **question** or ask about a **problem**.
|
||||
* Suggest a new **feature**.
|
||||
|
||||
**Note**: if you create an issue then I'm going to ask you to also help others. 😉
|
||||
|
||||
## Create a Pull Request
|
||||
|
||||
You can <a href="https://github.com/tiangolo/fastapi" class="external-link" target="_blank">create a Pull Request</a>, for example:
|
||||
You can [contribute](contributing.md){.internal-link target=_blank} to the source code with Pull Requests, for example:
|
||||
|
||||
* To fix a typo you found on the documentation.
|
||||
* To share an article, video, or podcast you created or found about FastAPI by <a href="https://github.com/tiangolo/fastapi/edit/master/docs/en/data/external_links.yml" class="external-link" target="_blank">editing this file</a>.
|
||||
* Make sure you add your link to the end of the corresponding section.
|
||||
* To help [translate the documentation](contributing.md#translations){.internal-link target=_blank} to your language.
|
||||
* You can also help reviewing the translations created by others.
|
||||
* To propose new documentation sections.
|
||||
* To fix an existing issue/bug.
|
||||
* To add a new feature.
|
||||
|
||||
## Join the chat
|
||||
|
||||
<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>
|
||||
Join the 👥 <a href="https://discord.gg/VQjSZaeJmf" class="external-link" target="_blank">Discord chat server</a> 👥 and hang out with others in the FastAPI community.
|
||||
|
||||
Join the chat on Gitter: <a href="https://gitter.im/tiangolo/fastapi" class="external-link" target="_blank">https://gitter.im/tiangolo/fastapi</a>.
|
||||
!!! tip
|
||||
For questions, ask them in <a href="https://github.com/tiangolo/fastapi/issues/new/choose" class="external-link" target="_blank">GitHub issues</a>, there's a much better chance you will receive help by the [FastAPI Experts](fastapi-people.md#experts){.internal-link target=_blank}.
|
||||
|
||||
There you can have quick conversations with others, help others, share ideas, etc.
|
||||
Use the chat only for other general conversations.
|
||||
|
||||
But have in mind that as it allows more "free conversation", it's easy to ask questions that are too general and more difficult to answer, so, you might not receive answers.
|
||||
There is also the previous <a href="https://gitter.im/tiangolo/fastapi" class="external-link" target="_blank">Gitter chat</a>, but as it doesn't have channels and advanced features, conversations are more difficult, so Discord is now the recommended system.
|
||||
|
||||
In GitHub issues the template will guide to to write the right question so that you can more easily get a good answer, or even solve the problem yourself even before asking. And in GitHub I can make sure I always answer everything, even if it takes some time. I can't personally do that with the Gitter chat. 😅
|
||||
### Don't use the chat for questions
|
||||
|
||||
Conversations in Gitter are also not as easily searchable as in GitHub, so questions and answers might get lost in the conversation.
|
||||
Have in mind that as chats allow more "free conversation", it's easy to ask questions that are too general and more difficult to answer, so, you might not receive answers.
|
||||
|
||||
On the other side, there's more than 1000 people in the chat, so there's a high chance you'll find someone to talk to there, almost all the time. 😄
|
||||
In GitHub issues the template will guide you to write the right question so that you can more easily get a good answer, or even solve the problem yourself even before asking. And in GitHub I can make sure I always answer everything, even if it takes some time. I can't personally do that with the chat systems. 😅
|
||||
|
||||
Conversations in the chat systems are also not as easily searchable as in GitHub, so questions and answers might get lost in the conversation. And only the ones in GitHub issues count to become a [FastAPI Expert](fastapi-people.md#experts){.internal-link target=_blank}, so you will most probably receive more attention in GitHub isssues.
|
||||
|
||||
On the other side, there are thousands of users in the chat systems, so there's a high chance you'll find someone to talk to there, almost all the time. 😄
|
||||
|
||||
## Sponsor the author
|
||||
|
||||
You can also financially support the author (me) through <a href="https://github.com/sponsors/tiangolo" class="external-link" target="_blank">GitHub sponsors</a>.
|
||||
|
||||
There you could buy me a coffee ☕️ to say thanks 😄.
|
||||
There you could buy me a coffee ☕️ to say thanks. 😄
|
||||
|
||||
And you can also become a Silver or Gold sponsor for FastAPI. 🏅🎉
|
||||
|
||||
## Sponsor the tools that power FastAPI
|
||||
|
||||
|
||||
BIN
docs/en/docs/img/deployment/deta/image01.png
Normal file
|
After Width: | Height: | Size: 39 KiB |
BIN
docs/en/docs/img/deployment/deta/image02.png
Normal file
|
After Width: | Height: | Size: 47 KiB |
125
docs/en/docs/img/sponsors/deta-banner.svg
Normal file
|
After Width: | Height: | Size: 37 KiB |
65
docs/en/docs/img/sponsors/deta.svg
Normal file
|
After Width: | Height: | Size: 55 KiB |
293
docs/en/docs/img/sponsors/fastapi-course-bundle-banner.svg
Normal file
@@ -0,0 +1,293 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="429.96896"
|
||||
height="40"
|
||||
viewBox="0 0 113.76262 10.583333"
|
||||
version="1.1"
|
||||
id="svg853"
|
||||
inkscape:version="1.0.2 (1.0.2+r75+1)"
|
||||
sodipodi:docname="fastapi-course-bundle-banner.svg">
|
||||
<defs
|
||||
id="defs847" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="2.8"
|
||||
inkscape:cx="222.91167"
|
||||
inkscape:cy="33.521565"
|
||||
inkscape:document-units="mm"
|
||||
inkscape:current-layer="g3355"
|
||||
inkscape:document-rotation="0"
|
||||
showgrid="false"
|
||||
inkscape:snap-object-midpoints="true"
|
||||
inkscape:snap-center="true"
|
||||
inkscape:snap-page="true"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1025"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="27"
|
||||
inkscape:window-maximized="1"
|
||||
units="px" />
|
||||
<metadata
|
||||
id="metadata850">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(-80.634914,-82.650791)">
|
||||
<g
|
||||
id="g3355"
|
||||
transform="matrix(1.4999999,0,0,1.4999999,-40.317455,-41.325393)">
|
||||
<rect
|
||||
style="fill:#ffffff;stroke-width:0.197707;stop-color:#000000"
|
||||
id="rect1784"
|
||||
width="75.841751"
|
||||
height="7.0555558"
|
||||
x="80.634918"
|
||||
y="82.650795" />
|
||||
<g
|
||||
aria-label="FastAPI Course Bundle. Get 3 in-depth courses. Save 10%!"
|
||||
transform="scale(1.0561291,0.94685395)"
|
||||
id="text871"
|
||||
style="font-size:2.43444px;line-height:1.25;font-family:Ubuntu;-inkscape-font-specification:Ubuntu;letter-spacing:0px;word-spacing:0px;stroke-width:0.0608608">
|
||||
<path
|
||||
d="m 84.413426,90.970748 h -0.72629 v 0.764329 h -0.228229 v -1.730735 h 1.0722 v 0.187814 h -0.843971 v 0.591968 h 0.72629 z"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Roboto;-inkscape-font-specification:Roboto;stroke-width:0.0608608"
|
||||
id="path3922" />
|
||||
<path
|
||||
d="m 85.526042,91.735077 q -0.01902,-0.03804 -0.03091,-0.135511 -0.153342,0.159285 -0.366117,0.159285 -0.190191,0 -0.312626,-0.106982 -0.121247,-0.108171 -0.121247,-0.2734 0,-0.200888 0.152153,-0.311437 0.153341,-0.111737 0.430306,-0.111737 h 0.213965 v -0.101038 q 0,-0.115303 -0.06894,-0.183059 -0.06894,-0.06894 -0.203266,-0.06894 -0.11768,0 -0.197323,0.05943 -0.07964,0.05943 -0.07964,0.143831 h -0.221096 q 0,-0.09628 0.06775,-0.185436 0.06894,-0.09034 0.185436,-0.142643 0.11768,-0.0523 0.257946,-0.0523 0.222285,0 0.348286,0.111737 0.126002,0.110548 0.130756,0.305494 v 0.591968 q 0,0.177115 0.04517,0.28172 v 0.01902 z m -0.364929,-0.167606 q 0.103416,0 0.196134,-0.05349 0.09272,-0.05349 0.134323,-0.139077 v -0.263889 h -0.172361 q -0.404155,0 -0.404155,0.23655 0,0.103416 0.06894,0.161662 0.06894,0.05824 0.177115,0.05824 z"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Roboto;-inkscape-font-specification:Roboto;stroke-width:0.0608608"
|
||||
id="path3924" />
|
||||
<path
|
||||
d="m 86.807451,91.393922 q 0,-0.08915 -0.06776,-0.137888 -0.06657,-0.04993 -0.234172,-0.08558 -0.166417,-0.03566 -0.265078,-0.08559 -0.09747,-0.04993 -0.14502,-0.118869 -0.04636,-0.06894 -0.04636,-0.16404 0,-0.158096 0.133133,-0.267455 0.134322,-0.10936 0.342343,-0.10936 0.21872,0 0.35423,0.112926 0.1367,0.112925 0.1367,0.288852 h -0.221097 q 0,-0.09034 -0.07726,-0.155719 -0.07608,-0.06538 -0.192568,-0.06538 -0.120058,0 -0.187813,0.0523 -0.06776,0.0523 -0.06776,0.136699 0,0.07964 0.063,0.120058 0.063,0.04042 0.22704,0.07726 0.165228,0.03685 0.267456,0.08796 0.102227,0.05111 0.150964,0.123624 0.04993,0.07132 0.04993,0.174737 0,0.172361 -0.137888,0.276966 -0.137889,0.103416 -0.357797,0.103416 -0.154529,0 -0.273399,-0.05468 -0.118869,-0.05468 -0.186624,-0.152153 -0.06657,-0.09866 -0.06657,-0.212775 h 0.219908 q 0.0059,0.110548 0.08796,0.175926 0.08321,0.06419 0.218719,0.06419 0.124813,0 0.199701,-0.04993 0.07608,-0.05111 0.07608,-0.135511 z"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Roboto;-inkscape-font-specification:Roboto;stroke-width:0.0608608"
|
||||
id="path3926" />
|
||||
<path
|
||||
d="m 87.612195,90.137476 v 0.311437 h 0.240116 v 0.169983 h -0.240116 v 0.797612 q 0,0.07727 0.03209,0.116491 0.03209,0.03804 0.109359,0.03804 0.03804,0 0.104605,-0.01426 v 0.178304 q -0.08677,0.02377 -0.168794,0.02377 -0.147398,0 -0.222285,-0.08915 -0.07489,-0.08915 -0.07489,-0.253191 v -0.797612 h -0.234172 v -0.169983 h 0.234172 v -0.311437 z"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Roboto;-inkscape-font-specification:Roboto;stroke-width:0.0608608"
|
||||
id="path3928" />
|
||||
<path
|
||||
d="m 89.098059,91.283374 h -0.725102 l -0.16285,0.451703 h -0.235361 l 0.660912,-1.730735 h 0.1997 l 0.662102,1.730735 h -0.234173 z m -0.656157,-0.187813 h 0.588402 l -0.294796,-0.809499 z"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Roboto;-inkscape-font-specification:Roboto;stroke-width:0.0608608"
|
||||
id="path3930" />
|
||||
<path
|
||||
d="m 89.958671,91.057523 v 0.677554 h -0.228228 v -1.730735 h 0.638327 q 0.284097,0 0.444571,0.145021 0.161662,0.14502 0.161662,0.383947 0,0.252003 -0.158096,0.388702 -0.156908,0.135511 -0.450514,0.135511 z m 0,-0.186625 h 0.410099 q 0.183058,0 0.280531,-0.08558 0.09747,-0.08678 0.09747,-0.249626 0,-0.15453 -0.09747,-0.247247 -0.09747,-0.09272 -0.267455,-0.09628 h -0.423175 z"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Roboto;-inkscape-font-specification:Roboto;stroke-width:0.0608608"
|
||||
id="path3932" />
|
||||
<path
|
||||
d="m 91.511103,91.735077 h -0.228229 v -1.730735 h 0.228229 z"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Roboto;-inkscape-font-specification:Roboto;stroke-width:0.0608608"
|
||||
id="path3934" />
|
||||
<path
|
||||
d="m 93.843315,91.158562 q -0.02021,0.279342 -0.206833,0.439815 -0.185436,0.160474 -0.48974,0.160474 -0.332834,0 -0.524213,-0.223474 -0.190191,-0.224663 -0.190191,-0.615742 v -0.105794 q 0,-0.249625 0.08796,-0.439816 0.08796,-0.19019 0.250814,-0.291229 0.164039,-0.102228 0.380381,-0.102228 0.29955,0 0.482609,0.160474 0.183058,0.160473 0.211587,0.450514 h -0.356607 q -0.01308,-0.167606 -0.09391,-0.242493 -0.07964,-0.07608 -0.243682,-0.07608 -0.178303,0 -0.267455,0.128378 -0.08796,0.12719 -0.09034,0.395834 v 0.130756 q 0,0.280532 0.0844,0.410099 0.08559,0.129567 0.268645,0.129567 0.165228,0 0.246059,-0.07489 0.08202,-0.07608 0.09391,-0.234172 z"
|
||||
style="font-weight:bold"
|
||||
id="path3936" />
|
||||
<path
|
||||
d="m 94.001411,91.080108 q 0,-0.191379 0.0737,-0.341154 0.0737,-0.149776 0.211587,-0.231795 0.139077,-0.08202 0.322135,-0.08202 0.260324,0 0.424363,0.159285 0.165228,0.159284 0.184247,0.432683 l 0.0024,0.08796 q 0,0.295985 -0.165228,0.475477 -0.165229,0.178304 -0.443382,0.178304 -0.278154,0 -0.444571,-0.178304 -0.165228,-0.178304 -0.165228,-0.484986 z m 0.343532,0.02496 q 0,0.183059 0.06894,0.280532 0.06894,0.09628 0.197323,0.09628 0.124812,0 0.194945,-0.0951 0.07013,-0.09628 0.07013,-0.306682 0,-0.179492 -0.07013,-0.278154 -0.07013,-0.09866 -0.197323,-0.09866 -0.126001,0 -0.194945,0.09866 -0.06894,0.09747 -0.06894,0.303116 z"
|
||||
style="font-weight:bold"
|
||||
id="path3938" />
|
||||
<path
|
||||
d="m 96.204056,91.604321 q -0.12719,0.15453 -0.351853,0.15453 -0.206832,0 -0.316192,-0.118869 -0.108171,-0.11887 -0.110548,-0.348287 v -0.842782 h 0.343532 v 0.830895 q 0,0.200889 0.183058,0.200889 0.174738,0 0.240116,-0.121247 v -0.910537 h 0.34472 v 1.286164 h -0.323324 z"
|
||||
style="font-weight:bold"
|
||||
id="path3940" />
|
||||
<path
|
||||
d="m 97.521126,90.771048 q -0.07013,-0.0095 -0.123624,-0.0095 -0.194945,0 -0.255568,0.131944 v 0.841594 h -0.343532 v -1.286164 h 0.324513 l 0.0095,0.153341 q 0.103416,-0.177115 0.286475,-0.177115 0.05706,0 0.106982,0.01545 z"
|
||||
style="font-weight:bold"
|
||||
id="path3942" />
|
||||
<path
|
||||
d="m 98.384116,91.379658 q 0,-0.063 -0.063,-0.09866 -0.06181,-0.03685 -0.1997,-0.06538 -0.458835,-0.09628 -0.458835,-0.389891 0,-0.171172 0.141455,-0.285286 0.142643,-0.115303 0.37206,-0.115303 0.244871,0 0.39108,0.115303 0.147397,0.115303 0.147397,0.29955 h -0.343531 q 0,-0.0737 -0.04755,-0.121246 -0.04755,-0.04874 -0.148587,-0.04874 -0.08677,0 -0.134322,0.03923 -0.04755,0.03923 -0.04755,0.09985 0,0.05706 0.05349,0.09272 0.05468,0.03447 0.183058,0.06062 0.128379,0.02496 0.216342,0.05706 0.27221,0.09985 0.27221,0.345909 0,0.175926 -0.150963,0.285286 -0.150964,0.108171 -0.389891,0.108171 -0.161662,0 -0.287663,-0.05706 -0.124813,-0.05825 -0.196135,-0.158096 -0.07132,-0.101039 -0.07132,-0.217531 h 0.325701 q 0.0048,0.09153 0.06776,0.140266 0.063,0.04874 0.168794,0.04874 0.09866,0 0.148586,-0.03685 0.05111,-0.03804 0.05111,-0.09866 z"
|
||||
style="font-weight:bold"
|
||||
id="path3944" />
|
||||
<path
|
||||
d="m 99.530014,91.758851 q -0.282909,0 -0.461212,-0.173549 -0.177115,-0.173549 -0.177115,-0.462401 v -0.03328 q 0,-0.193756 0.07489,-0.345909 0.07489,-0.153341 0.211587,-0.235361 0.137888,-0.08321 0.313815,-0.08321 0.263889,0 0.414853,0.166417 0.152151,0.166417 0.152151,0.47191 v 0.140266 h -0.819007 q 0.01664,0.126001 0.09985,0.202077 0.0844,0.07608 0.212776,0.07608 0.198511,0 0.310248,-0.143832 l 0.168793,0.189002 q -0.07726,0.10936 -0.209208,0.171171 -0.131945,0.06062 -0.292418,0.06062 z m -0.03923,-1.055558 q -0.102227,0 -0.166417,0.06894 -0.063,0.06894 -0.08083,0.197323 h 0.477854 v -0.02734 q -0.0024,-0.114115 -0.06181,-0.175927 -0.05943,-0.063 -0.168794,-0.063 z"
|
||||
style="font-weight:bold"
|
||||
id="path3946" />
|
||||
<path
|
||||
d="m 100.88631,91.735077 v -1.730735 h 0.60623 q 0.31501,0 0.47786,0.121247 0.16285,0.120058 0.16285,0.353041 0,0.12719 -0.0654,0.224663 -0.0654,0.09628 -0.18187,0.141454 0.13313,0.03328 0.20921,0.134322 0.0773,0.101039 0.0773,0.247248 0,0.249625 -0.15928,0.378004 -0.15928,0.128379 -0.45408,0.130756 z m 0.35661,-0.75363 v 0.467155 h 0.30549 q 0.126,0 0.19614,-0.05943 0.0713,-0.06062 0.0713,-0.166417 0,-0.237738 -0.24606,-0.241304 z m 0,-0.252003 h 0.26389 q 0.26983,-0.0048 0.26983,-0.215153 0,-0.117681 -0.0689,-0.168794 -0.0678,-0.0523 -0.21516,-0.0523 h -0.24962 z"
|
||||
style="font-weight:bold"
|
||||
id="path3948" />
|
||||
<path
|
||||
d="m 103.18881,91.604321 q -0.12719,0.15453 -0.35186,0.15453 -0.20683,0 -0.31619,-0.118869 -0.10817,-0.11887 -0.11055,-0.348287 v -0.842782 h 0.34353 v 0.830895 q 0,0.200889 0.18306,0.200889 0.17474,0 0.24012,-0.121247 v -0.910537 h 0.34472 v 1.286164 h -0.32333 z"
|
||||
style="font-weight:bold"
|
||||
id="path3950" />
|
||||
<path
|
||||
d="m 104.09934,90.448913 0.0107,0.148586 q 0.13789,-0.17236 0.36968,-0.17236 0.20446,0 0.30431,0.120058 0.0999,0.120058 0.10223,0.358985 v 0.830895 h -0.34353 v -0.822575 q 0,-0.109359 -0.0476,-0.158095 -0.0476,-0.04993 -0.1581,-0.04993 -0.14502,0 -0.21753,0.123624 v 0.906972 h -0.34353 v -1.286164 z"
|
||||
style="font-weight:bold"
|
||||
id="path3952" />
|
||||
<path
|
||||
d="m 105.09428,91.082485 q 0,-0.300739 0.13432,-0.479042 0.13551,-0.178304 0.36968,-0.178304 0.18782,0 0.31025,0.140266 v -0.656158 h 0.34472 v 1.82583 H 105.943 l -0.0166,-0.1367 q -0.12838,0.160474 -0.33045,0.160474 -0.22704,0 -0.36493,-0.178304 -0.1367,-0.179492 -0.1367,-0.498062 z m 0.34353,0.02496 q 0,0.180681 0.063,0.276965 0.063,0.09628 0.18306,0.09628 0.15928,0 0.22466,-0.134322 v -0.507571 q -0.0642,-0.134323 -0.22228,-0.134323 -0.24844,0 -0.24844,0.402967 z"
|
||||
style="font-weight:bold"
|
||||
id="path3954" />
|
||||
<path
|
||||
d="m 106.88445,91.735077 h -0.34472 v -1.82583 h 0.34472 z"
|
||||
style="font-weight:bold"
|
||||
id="path3956" />
|
||||
<path
|
||||
d="m 107.76051,91.758851 q -0.28291,0 -0.46121,-0.173549 -0.17711,-0.173549 -0.17711,-0.462401 v -0.03328 q 0,-0.193756 0.0749,-0.345909 0.0749,-0.153341 0.21159,-0.235361 0.13789,-0.08321 0.31382,-0.08321 0.26388,0 0.41485,0.166417 0.15215,0.166417 0.15215,0.47191 v 0.140266 h -0.81901 q 0.0166,0.126001 0.0998,0.202077 0.0844,0.07608 0.21278,0.07608 0.19851,0 0.31025,-0.143832 l 0.16879,0.189002 q -0.0773,0.10936 -0.20921,0.171171 -0.13194,0.06062 -0.29242,0.06062 z m -0.0392,-1.055558 q -0.10223,0 -0.16642,0.06894 -0.063,0.06894 -0.0808,0.197323 h 0.47785 v -0.02734 q -0.002,-0.114115 -0.0618,-0.175927 -0.0594,-0.063 -0.16879,-0.063 z"
|
||||
style="font-weight:bold"
|
||||
id="path3958" />
|
||||
<path
|
||||
d="m 108.52484,91.619774 q 0,-0.05706 0.0333,-0.0951 0.0345,-0.03804 0.10222,-0.03804 0.0678,0 0.10223,0.03804 0.0357,0.03804 0.0357,0.0951 0,0.05468 -0.0357,0.09153 -0.0345,0.03685 -0.10223,0.03685 -0.0677,0 -0.10222,-0.03685 -0.0333,-0.03685 -0.0333,-0.09153 z"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Roboto;-inkscape-font-specification:Roboto;stroke-width:0.0608608"
|
||||
id="path3960" />
|
||||
<path
|
||||
d="m 111.07815,91.508037 q -0.088,0.126001 -0.24606,0.189002 -0.15691,0.06181 -0.36612,0.06181 -0.21158,0 -0.37562,-0.09866 -0.16404,-0.09985 -0.25438,-0.282908 -0.0892,-0.183059 -0.0915,-0.424363 v -0.150964 q 0,-0.391079 0.18187,-0.606232 0.18306,-0.215154 0.51351,-0.215154 0.27103,0 0.43625,0.139077 0.16523,0.137889 0.20208,0.392268 h -0.22823 q -0.0642,-0.343531 -0.40891,-0.343531 -0.22942,0 -0.34828,0.161662 -0.11768,0.160473 -0.11887,0.465967 v 0.141454 q 0,0.291229 0.13313,0.46359 0.13313,0.171171 0.36017,0.171171 0.12838,0 0.22467,-0.02853 0.0963,-0.02853 0.15928,-0.09628 v -0.388702 h -0.40059 v -0.185436 h 0.62763 z"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Roboto;-inkscape-font-specification:Roboto;stroke-width:0.0608608"
|
||||
id="path3962" />
|
||||
<path
|
||||
d="m 111.95897,91.758851 q -0.26151,0 -0.42555,-0.171172 -0.16404,-0.17236 -0.16404,-0.460023 v -0.04042 q 0,-0.191379 0.0725,-0.341154 0.0737,-0.150964 0.20445,-0.235361 0.13195,-0.08559 0.28529,-0.08559 0.25081,0 0.38989,0.165228 0.13908,0.165228 0.13908,0.473099 v 0.09153 h -0.87131 q 0.005,0.19019 0.11055,0.307871 0.10698,0.116491 0.27102,0.116491 0.11649,0 0.19732,-0.04755 0.0808,-0.04755 0.14145,-0.126002 l 0.13433,0.104605 q -0.16167,0.248437 -0.48499,0.248437 z m -0.0273,-1.153031 q -0.13313,0 -0.22347,0.09747 -0.0903,0.09628 -0.11174,0.271021 h 0.64427 v -0.01664 q -0.01,-0.167606 -0.0903,-0.259135 -0.0808,-0.09272 -0.21872,-0.09272 z"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Roboto;-inkscape-font-specification:Roboto;stroke-width:0.0608608"
|
||||
id="path3964" />
|
||||
<path
|
||||
d="m 113.01215,90.137476 v 0.311437 h 0.24012 v 0.169983 h -0.24012 v 0.797612 q 0,0.07727 0.0321,0.116491 0.0321,0.03804 0.10936,0.03804 0.038,0 0.1046,-0.01426 v 0.178304 q -0.0868,0.02377 -0.16879,0.02377 -0.1474,0 -0.22229,-0.08915 -0.0749,-0.08915 -0.0749,-0.253191 v -0.797612 h -0.23417 v -0.169983 h 0.23417 v -0.311437 z"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Roboto;-inkscape-font-specification:Roboto;stroke-width:0.0608608"
|
||||
id="path3966" />
|
||||
<path
|
||||
d="m 114.40886,90.762727 h 0.16523 q 0.15572,-0.0024 0.24487,-0.08202 0.0891,-0.07964 0.0891,-0.215153 0,-0.304305 -0.30311,-0.304305 -0.14264,0 -0.22823,0.08202 -0.0844,0.08083 -0.0844,0.215153 h -0.21991 q 0,-0.205643 0.14978,-0.341154 0.15096,-0.1367 0.38276,-0.1367 0.24487,0 0.38395,0.129568 0.13907,0.129567 0.13907,0.360173 0,0.112926 -0.0737,0.21872 -0.0725,0.105793 -0.19851,0.158095 0.14264,0.04517 0.21991,0.149776 0.0784,0.104604 0.0784,0.255568 0,0.232984 -0.15215,0.369683 -0.15215,0.1367 -0.39583,0.1367 -0.24368,0 -0.39703,-0.131945 -0.15215,-0.131945 -0.15215,-0.348287 h 0.2211 q 0,0.1367 0.0892,0.21872 0.0892,0.08202 0.23893,0.08202 0.15928,0 0.24368,-0.08321 0.0844,-0.08321 0.0844,-0.238927 0,-0.150964 -0.0927,-0.231795 -0.0927,-0.08083 -0.26746,-0.08321 h -0.16523 z"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Roboto;-inkscape-font-specification:Roboto;stroke-width:0.0608608"
|
||||
id="path3968" />
|
||||
<path
|
||||
d="m 116.32385,91.735077 h -0.21991 v -1.286164 h 0.21991 z m -0.23774,-1.627319 q 0,-0.05349 0.0321,-0.09034 0.0333,-0.03685 0.0975,-0.03685 0.0642,0 0.0975,0.03685 0.0333,0.03685 0.0333,0.09034 0,0.05349 -0.0333,0.08915 -0.0333,0.03566 -0.0975,0.03566 -0.0642,0 -0.0975,-0.03566 -0.0321,-0.03566 -0.0321,-0.08915 z"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Roboto;-inkscape-font-specification:Roboto;stroke-width:0.0608608"
|
||||
id="path3970" />
|
||||
<path
|
||||
d="m 116.88253,90.448913 0.007,0.161662 q 0.1474,-0.185436 0.38514,-0.185436 0.40772,0 0.41129,0.460024 v 0.849914 h -0.21991 v -0.851103 q -0.001,-0.139077 -0.0642,-0.205644 -0.0618,-0.06657 -0.19376,-0.06657 -0.10698,0 -0.18781,0.05706 -0.0808,0.05706 -0.126,0.149775 v 0.916481 h -0.21991 v -1.286164 z"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Roboto;-inkscape-font-specification:Roboto;stroke-width:0.0608608"
|
||||
id="path3972" />
|
||||
<path
|
||||
d="m 118.47775,91.089617 h -0.58008 v -0.179492 h 0.58008 z"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Roboto;-inkscape-font-specification:Roboto;stroke-width:0.0608608"
|
||||
id="path3974" />
|
||||
<path
|
||||
d="m 118.63704,91.081297 q 0,-0.295984 0.14026,-0.475477 0.14027,-0.180681 0.36731,-0.180681 0.22585,0 0.3578,0.15453 v -0.670422 h 0.2199 v 1.82583 h -0.20207 l -0.0107,-0.137888 q -0.13195,0.161662 -0.36731,0.161662 -0.22347,0 -0.36493,-0.183059 -0.14026,-0.183058 -0.14026,-0.477854 z m 0.21991,0.02496 q 0,0.218719 0.0903,0.342343 0.0903,0.123624 0.24962,0.123624 0.20921,0 0.3055,-0.187813 v -0.59078 q -0.0987,-0.181869 -0.30312,-0.181869 -0.16166,0 -0.252,0.124812 -0.0903,0.124813 -0.0903,0.369683 z"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Roboto;-inkscape-font-specification:Roboto;stroke-width:0.0608608"
|
||||
id="path3976" />
|
||||
<path
|
||||
d="m 120.59838,91.758851 q -0.26151,0 -0.42555,-0.171172 -0.16404,-0.17236 -0.16404,-0.460023 v -0.04042 q 0,-0.191379 0.0725,-0.341154 0.0737,-0.150964 0.20445,-0.235361 0.13195,-0.08559 0.28529,-0.08559 0.25081,0 0.38989,0.165228 0.13908,0.165228 0.13908,0.473099 v 0.09153 h -0.87131 q 0.005,0.19019 0.11054,0.307871 0.10699,0.116491 0.27103,0.116491 0.11649,0 0.19732,-0.04755 0.0808,-0.04755 0.14145,-0.126002 l 0.13432,0.104605 q -0.16166,0.248437 -0.48498,0.248437 z m -0.0273,-1.153031 q -0.13313,0 -0.22348,0.09747 -0.0903,0.09628 -0.11173,0.271021 h 0.64427 v -0.01664 q -0.01,-0.167606 -0.0903,-0.259135 -0.0808,-0.09272 -0.21872,-0.09272 z"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Roboto;-inkscape-font-specification:Roboto;stroke-width:0.0608608"
|
||||
id="path3978" />
|
||||
<path
|
||||
d="m 122.43966,91.106259 q 0,0.293607 -0.13432,0.473099 -0.13432,0.179493 -0.36374,0.179493 -0.23417,0 -0.36849,-0.148587 v 0.619309 h -0.21991 v -1.78066 h 0.20089 l 0.0107,0.142643 q 0.13432,-0.166417 0.37325,-0.166417 0.23179,0 0.36611,0.174738 0.13551,0.174737 0.13551,0.486174 z m -0.2199,-0.02496 q 0,-0.217531 -0.0927,-0.343532 -0.0927,-0.126001 -0.25438,-0.126001 -0.1997,0 -0.29955,0.177115 v 0.614553 q 0.0987,0.175926 0.30193,0.175926 0.15809,0 0.25081,-0.124812 0.0939,-0.126002 0.0939,-0.373249 z"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Roboto;-inkscape-font-specification:Roboto;stroke-width:0.0608608"
|
||||
id="path3980" />
|
||||
<path
|
||||
d="m 123.01618,90.137476 v 0.311437 h 0.24011 v 0.169983 h -0.24011 v 0.797612 q 0,0.07727 0.0321,0.116491 0.0321,0.03804 0.10936,0.03804 0.038,0 0.10461,-0.01426 v 0.178304 q -0.0868,0.02377 -0.1688,0.02377 -0.1474,0 -0.22228,-0.08915 -0.0749,-0.08915 -0.0749,-0.253191 v -0.797612 h -0.23417 v -0.169983 h 0.23417 v -0.311437 z"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Roboto;-inkscape-font-specification:Roboto;stroke-width:0.0608608"
|
||||
id="path3982" />
|
||||
<path
|
||||
d="m 123.73177,90.604631 q 0.14621,-0.179492 0.38038,-0.179492 0.40772,0 0.41129,0.460024 v 0.849914 h -0.21991 v -0.851103 q -0.001,-0.139077 -0.0642,-0.205644 -0.0618,-0.06657 -0.19376,-0.06657 -0.10698,0 -0.18781,0.05706 -0.0808,0.05706 -0.126,0.149775 v 0.916481 h -0.21991 v -1.82583 h 0.21991 z"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Roboto;-inkscape-font-specification:Roboto;stroke-width:0.0608608"
|
||||
id="path3984" />
|
||||
<path
|
||||
d="m 125.97245,91.579358 q 0.11769,0 0.20565,-0.07132 0.088,-0.07132 0.0975,-0.178304 h 0.20802 q -0.006,0.110548 -0.0761,0.210399 -0.0701,0.09985 -0.18782,0.159284 -0.11649,0.05944 -0.24725,0.05944 -0.2627,0 -0.41841,-0.174738 -0.15453,-0.175926 -0.15453,-0.480231 v -0.03685 q 0,-0.187813 0.0689,-0.334022 0.0689,-0.146209 0.19732,-0.22704 0.12957,-0.08083 0.3055,-0.08083 0.21634,0 0.35898,0.129567 0.14383,0.129568 0.15334,0.3364 h -0.20802 q -0.01,-0.124813 -0.0951,-0.204455 -0.0844,-0.08083 -0.20921,-0.08083 -0.16761,0 -0.26033,0.121247 -0.0915,0.120057 -0.0915,0.348286 v 0.0416 q 0,0.222286 0.0915,0.342344 0.0915,0.120057 0.26151,0.120057 z"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Roboto;-inkscape-font-specification:Roboto;stroke-width:0.0608608"
|
||||
id="path3986" />
|
||||
<path
|
||||
d="m 126.67259,91.080108 q 0,-0.189002 0.0737,-0.339966 0.0749,-0.150964 0.20683,-0.232983 0.13314,-0.08202 0.30312,-0.08202 0.2627,0 0.42436,0.18187 0.16285,0.18187 0.16285,0.483797 v 0.01545 q 0,0.187813 -0.0725,0.337589 -0.0713,0.148586 -0.20564,0.231794 -0.13313,0.08321 -0.30668,0.08321 -0.26151,0 -0.42436,-0.18187 -0.16167,-0.18187 -0.16167,-0.48142 z m 0.2211,0.02615 q 0,0.213965 0.0987,0.343532 0.0999,0.129567 0.26627,0.129567 0.1676,0 0.26627,-0.130756 0.0987,-0.131944 0.0987,-0.368494 0,-0.211587 -0.10104,-0.342343 -0.0999,-0.131945 -0.26627,-0.131945 -0.16285,0 -0.2627,0.129567 -0.0998,0.129568 -0.0998,0.370872 z"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Roboto;-inkscape-font-specification:Roboto;stroke-width:0.0608608"
|
||||
id="path3988" />
|
||||
<path
|
||||
d="m 128.91327,91.607887 q -0.12837,0.150964 -0.37681,0.150964 -0.20564,0 -0.31381,-0.118869 -0.10699,-0.120058 -0.10818,-0.35423 v -0.836839 h 0.21991 v 0.830895 q 0,0.292418 0.23774,0.292418 0.252,0 0.33521,-0.187813 v -0.9355 h 0.21991 v 1.286164 h -0.20921 z"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Roboto;-inkscape-font-specification:Roboto;stroke-width:0.0608608"
|
||||
id="path3990" />
|
||||
<path
|
||||
d="m 130.08176,90.646236 q -0.0499,-0.0083 -0.10817,-0.0083 -0.21634,0 -0.29361,0.184247 v 0.912915 h -0.21991 v -1.286164 h 0.21397 l 0.004,0.148586 q 0.10817,-0.17236 0.30669,-0.17236 0.0642,0 0.0975,0.01664 z"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Roboto;-inkscape-font-specification:Roboto;stroke-width:0.0608608"
|
||||
id="path3992" />
|
||||
<path
|
||||
d="m 131.03152,91.393922 q 0,-0.08915 -0.0677,-0.137888 -0.0666,-0.04993 -0.23418,-0.08558 -0.16641,-0.03566 -0.26507,-0.08559 -0.0975,-0.04993 -0.14502,-0.118869 -0.0464,-0.06894 -0.0464,-0.16404 0,-0.158096 0.13313,-0.267455 0.13432,-0.10936 0.34234,-0.10936 0.21872,0 0.35423,0.112926 0.1367,0.112925 0.1367,0.288852 h -0.22109 q 0,-0.09034 -0.0773,-0.155719 -0.0761,-0.06538 -0.19257,-0.06538 -0.12005,0 -0.18781,0.0523 -0.0677,0.0523 -0.0677,0.136699 0,0.07964 0.063,0.120058 0.063,0.04042 0.22704,0.07726 0.16522,0.03685 0.26745,0.08796 0.10223,0.05111 0.15097,0.123624 0.0499,0.07132 0.0499,0.174737 0,0.172361 -0.13789,0.276966 -0.13789,0.103416 -0.35779,0.103416 -0.15453,0 -0.2734,-0.05468 -0.11887,-0.05468 -0.18663,-0.152153 -0.0666,-0.09866 -0.0666,-0.212775 h 0.2199 q 0.006,0.110548 0.088,0.175926 0.0832,0.06419 0.21872,0.06419 0.12481,0 0.1997,-0.04993 0.0761,-0.05111 0.0761,-0.135511 z"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Roboto;-inkscape-font-specification:Roboto;stroke-width:0.0608608"
|
||||
id="path3994" />
|
||||
<path
|
||||
d="m 132.07163,91.758851 q -0.26151,0 -0.42555,-0.171172 -0.16404,-0.17236 -0.16404,-0.460023 v -0.04042 q 0,-0.191379 0.0725,-0.341154 0.0737,-0.150964 0.20445,-0.235361 0.13195,-0.08559 0.28529,-0.08559 0.25081,0 0.38989,0.165228 0.13908,0.165228 0.13908,0.473099 v 0.09153 h -0.87131 q 0.005,0.19019 0.11054,0.307871 0.10699,0.116491 0.27103,0.116491 0.11649,0 0.19732,-0.04755 0.0808,-0.04755 0.14145,-0.126002 l 0.13433,0.104605 q -0.16167,0.248437 -0.48499,0.248437 z m -0.0273,-1.153031 q -0.13313,0 -0.22347,0.09747 -0.0903,0.09628 -0.11174,0.271021 h 0.64427 v -0.01664 q -0.01,-0.167606 -0.0903,-0.259135 -0.0808,-0.09272 -0.21872,-0.09272 z"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Roboto;-inkscape-font-specification:Roboto;stroke-width:0.0608608"
|
||||
id="path3996" />
|
||||
<path
|
||||
d="m 133.57532,91.393922 q 0,-0.08915 -0.0678,-0.137888 -0.0666,-0.04993 -0.23417,-0.08558 -0.16642,-0.03566 -0.26508,-0.08559 -0.0975,-0.04993 -0.14502,-0.118869 -0.0464,-0.06894 -0.0464,-0.16404 0,-0.158096 0.13313,-0.267455 0.13432,-0.10936 0.34234,-0.10936 0.21872,0 0.35423,0.112926 0.1367,0.112925 0.1367,0.288852 h -0.22109 q 0,-0.09034 -0.0773,-0.155719 -0.0761,-0.06538 -0.19257,-0.06538 -0.12005,0 -0.18781,0.0523 -0.0678,0.0523 -0.0678,0.136699 0,0.07964 0.063,0.120058 0.063,0.04042 0.22704,0.07726 0.16522,0.03685 0.26745,0.08796 0.10223,0.05111 0.15097,0.123624 0.0499,0.07132 0.0499,0.174737 0,0.172361 -0.13789,0.276966 -0.13789,0.103416 -0.35779,0.103416 -0.15453,0 -0.2734,-0.05468 -0.11887,-0.05468 -0.18663,-0.152153 -0.0666,-0.09866 -0.0666,-0.212775 h 0.2199 q 0.006,0.110548 0.088,0.175926 0.0832,0.06419 0.21872,0.06419 0.12481,0 0.1997,-0.04993 0.0761,-0.05111 0.0761,-0.135511 z"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Roboto;-inkscape-font-specification:Roboto;stroke-width:0.0608608"
|
||||
id="path3998" />
|
||||
<path
|
||||
d="m 134.08646,91.619774 q 0,-0.05706 0.0333,-0.0951 0.0345,-0.03804 0.10223,-0.03804 0.0677,0 0.10223,0.03804 0.0357,0.03804 0.0357,0.0951 0,0.05468 -0.0357,0.09153 -0.0345,0.03685 -0.10223,0.03685 -0.0678,0 -0.10223,-0.03685 -0.0333,-0.03685 -0.0333,-0.09153 z"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Roboto;-inkscape-font-specification:Roboto;stroke-width:0.0608608"
|
||||
id="path4000" />
|
||||
<path
|
||||
d="m 136.21303,91.280997 q 0,-0.101039 -0.0713,-0.15453 -0.0713,-0.05468 -0.25676,-0.114114 -0.18544,-0.06062 -0.29361,-0.11887 -0.29479,-0.159284 -0.29479,-0.429117 0,-0.140266 0.0785,-0.249625 0.0796,-0.110549 0.22704,-0.172361 0.14859,-0.06181 0.33284,-0.06181 0.18543,0 0.33045,0.06776 0.14502,0.06657 0.22466,0.189002 0.0808,0.122435 0.0808,0.278154 h -0.35661 q 0,-0.11887 -0.0749,-0.184248 -0.0749,-0.06657 -0.2104,-0.06657 -0.13075,0 -0.20326,0.05587 -0.0725,0.05468 -0.0725,0.145021 0,0.0844 0.0844,0.141454 0.0856,0.05706 0.25082,0.106982 0.3043,0.09153 0.44338,0.22704 0.13908,0.135511 0.13908,0.337588 0,0.224663 -0.16999,0.353042 -0.16998,0.12719 -0.45764,0.12719 -0.1997,0 -0.36374,-0.07251 -0.16404,-0.0737 -0.25082,-0.200889 -0.0856,-0.12719 -0.0856,-0.294796 h 0.35779 q 0,0.286475 0.34235,0.286475 0.12719,0 0.19851,-0.05111 0.0713,-0.0523 0.0713,-0.14502 z"
|
||||
style="font-weight:bold"
|
||||
id="path4002" />
|
||||
<path
|
||||
d="m 137.53604,91.735077 q -0.0238,-0.04636 -0.0345,-0.115303 -0.12481,0.139077 -0.32451,0.139077 -0.18901,0 -0.31382,-0.10936 -0.12362,-0.109359 -0.12362,-0.275776 0,-0.204455 0.15096,-0.313815 0.15215,-0.109359 0.43863,-0.110548 h 0.15809 v -0.0737 q 0,-0.08915 -0.0464,-0.142643 -0.0452,-0.05349 -0.14384,-0.05349 -0.0868,0 -0.1367,0.0416 -0.0487,0.0416 -0.0487,0.114115 h -0.34353 q 0,-0.111737 0.0689,-0.206833 0.0689,-0.0951 0.19495,-0.148586 0.126,-0.05468 0.2829,-0.05468 0.23774,0 0.37682,0.120058 0.14027,0.118869 0.14027,0.335211 v 0.557496 q 0.001,0.183059 0.0511,0.276965 v 0.02021 z m -0.2841,-0.238927 q 0.0761,0 0.14027,-0.03328 0.0642,-0.03447 0.0951,-0.09153 v -0.221096 h -0.12837 q -0.25795,0 -0.27459,0.178303 l -0.001,0.02021 q 0,0.06419 0.0452,0.105794 0.0452,0.0416 0.12362,0.0416 z"
|
||||
style="font-weight:bold"
|
||||
id="path4004" />
|
||||
<path
|
||||
d="m 138.5607,91.315469 0.23892,-0.866556 h 0.35899 l -0.43388,1.286164 h -0.32807 l -0.43388,-1.286164 h 0.35899 z"
|
||||
style="font-weight:bold"
|
||||
id="path4006" />
|
||||
<path
|
||||
d="m 139.88846,91.758851 q -0.2829,0 -0.46121,-0.173549 -0.17711,-0.173549 -0.17711,-0.462401 v -0.03328 q 0,-0.193756 0.0749,-0.345909 0.0749,-0.153341 0.21159,-0.235361 0.13789,-0.08321 0.31382,-0.08321 0.26389,0 0.41485,0.166417 0.15215,0.166417 0.15215,0.47191 v 0.140266 h -0.81901 q 0.0166,0.126001 0.0999,0.202077 0.0844,0.07608 0.21278,0.07608 0.19851,0 0.31025,-0.143832 l 0.16879,0.189002 q -0.0773,0.10936 -0.20921,0.171171 -0.13194,0.06062 -0.29242,0.06062 z m -0.0392,-1.055558 q -0.10223,0 -0.16642,0.06894 -0.063,0.06894 -0.0808,0.197323 h 0.47785 v -0.02734 q -0.002,-0.114115 -0.0618,-0.175927 -0.0594,-0.063 -0.16879,-0.063 z"
|
||||
style="font-weight:bold"
|
||||
id="path4008" />
|
||||
<path
|
||||
d="m 142.04237,91.735077 h -0.34353 v -1.324202 l -0.4101,0.12719 v -0.279343 l 0.71678,-0.256757 h 0.0369 z"
|
||||
style="font-weight:bold"
|
||||
id="path4010" />
|
||||
<path
|
||||
d="m 143.77073,91.019485 q 0,0.358984 -0.14859,0.549175 -0.14858,0.190191 -0.43506,0.190191 -0.28291,0 -0.43268,-0.186625 -0.14978,-0.186624 -0.15334,-0.534911 v -0.318569 q 0,-0.362551 0.14977,-0.550364 0.15097,-0.187814 0.43388,-0.187814 0.2829,0 0.43268,0.186625 0.14977,0.185436 0.15334,0.533722 z m -0.34353,-0.349476 q 0,-0.215153 -0.0594,-0.312625 -0.0582,-0.09866 -0.18305,-0.09866 -0.12125,0 -0.1795,0.09391 -0.0571,0.09272 -0.0606,0.291229 v 0.420797 q 0,0.211587 0.0571,0.315003 0.0582,0.102228 0.18543,0.102228 0.126,0 0.18187,-0.09866 0.0559,-0.09866 0.0582,-0.301927 z"
|
||||
style="font-weight:bold"
|
||||
id="path4012" />
|
||||
<path
|
||||
d="m 143.99896,90.337176 q 0,-0.159285 0.10341,-0.257946 0.10342,-0.09985 0.27103,-0.09985 0.16998,0 0.27339,0.09866 0.10342,0.09747 0.10342,0.265078 v 0.08559 q 0,0.160473 -0.10342,0.257946 -0.10341,0.09747 -0.27102,0.09747 -0.16879,0 -0.2734,-0.09747 -0.10341,-0.09866 -0.10341,-0.265078 z m 0.22823,0.09153 q 0,0.07132 0.0404,0.115303 0.0416,0.04279 0.10817,0.04279 0.0666,0 0.1058,-0.04398 0.0392,-0.04398 0.0392,-0.11768 v -0.08796 q 0,-0.07132 -0.0392,-0.115303 -0.0392,-0.04398 -0.10817,-0.04398 -0.0654,0 -0.1058,0.04398 -0.0404,0.04279 -0.0404,0.120058 z m 0.5991,0.882009 q 0,-0.160473 0.1046,-0.257946 0.10461,-0.09866 0.27102,-0.09866 0.1688,0 0.27221,0.09747 0.10461,0.09628 0.10461,0.266267 v 0.08559 q 0,0.159285 -0.10223,0.257946 -0.10223,0.09747 -0.27221,0.09747 -0.17117,0 -0.27459,-0.09866 -0.10341,-0.09866 -0.10341,-0.261512 z m 0.22823,0.09272 q 0,0.06538 0.0428,0.111737 0.0428,0.04636 0.10698,0.04636 0.14502,0 0.14502,-0.160473 v -0.09034 q 0,-0.07132 -0.0404,-0.114114 -0.0404,-0.04398 -0.10699,-0.04398 -0.0666,0 -0.10698,0.04398 -0.0404,0.04279 -0.0404,0.11768 z m -0.61099,0.202078 -0.16761,-0.09034 0.84516,-1.352731 0.16761,0.09034 z"
|
||||
style="font-weight:bold"
|
||||
id="path4014" />
|
||||
<path
|
||||
d="m 146.16475,91.203732 h -0.28528 l -0.0404,-1.19939 h 0.36612 z m -0.14264,0.187813 q 0.0868,0 0.13908,0.05111 0.0535,0.05111 0.0535,0.130756 0,0.07845 -0.0535,0.129567 -0.0523,0.05111 -0.13908,0.05111 -0.0856,0 -0.13908,-0.05111 -0.0523,-0.05111 -0.0523,-0.129567 0,-0.07845 0.0523,-0.129567 0.0535,-0.0523 0.13908,-0.0523 z"
|
||||
style="font-weight:bold"
|
||||
id="path4016" />
|
||||
</g>
|
||||
<g
|
||||
id="g896"
|
||||
transform="matrix(0.11457918,0,0,0.11457918,82.917314,84.127369)">
|
||||
<path
|
||||
fill="#fdd888"
|
||||
d="m 33,31 c 0,2.2 -1.8,4 -4,4 H 7 C 4.8,35 3,33.2 3,31 V 14 c 0,-2.2 1.8,-4 4,-4 h 22 c 2.2,0 4,1.8 4,4 z"
|
||||
id="path873" />
|
||||
<path
|
||||
fill="#fdd888"
|
||||
d="m 36,11 c 0,2.2 -1.8,4 -4,4 H 4 C 1.8,15 0,13.2 0,11 0,8.8 1.8,7 4,7 h 28 c 2.2,0 4,1.8 4,4 z"
|
||||
id="path875" />
|
||||
<path
|
||||
fill="#fcab40"
|
||||
d="m 3,15 h 30 v 2 H 3 Z"
|
||||
id="path877" />
|
||||
<path
|
||||
fill="#da2f47"
|
||||
d="m 19,3 h -2 c -1.657,0 -3,1.343 -3,3 v 29 h 8 V 6 C 22,4.344 20.657,3 19,3 Z"
|
||||
id="path879" />
|
||||
<path
|
||||
fill="#da2f47"
|
||||
d="m 16,7 c 1.1,0 1.263,-0.516 0.361,-1.147 L 9.639,1.147 C 8.737,0.516 7.554,0.781 7.008,1.736 L 4.992,5.264 C 4.446,6.219 4.9,7 6,7 Z m 4,0 C 18.9,7 18.737,6.484 19.639,5.853 l 6.723,-4.706 c 0.901,-0.631 2.085,-0.366 2.631,0.589 l 2.016,3.527 C 31.554,6.219 31.1,7 30,7 Z"
|
||||
id="path881" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 34 KiB |
124
docs/en/docs/img/sponsors/investsuite.svg
Normal file
@@ -0,0 +1,124 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="240"
|
||||
height="100"
|
||||
viewBox="0 0 63.5 26.458334"
|
||||
version="1.1"
|
||||
id="svg975">
|
||||
<defs
|
||||
id="defs969">
|
||||
<clipPath
|
||||
id="clip0">
|
||||
<rect
|
||||
width="770"
|
||||
height="222.03999"
|
||||
fill="#ffffff"
|
||||
id="rect14"
|
||||
x="0"
|
||||
y="0" />
|
||||
</clipPath>
|
||||
<clipPath
|
||||
id="clip0-7">
|
||||
<rect
|
||||
width="770"
|
||||
height="222.03999"
|
||||
fill="#ffffff"
|
||||
id="rect14-5"
|
||||
x="0"
|
||||
y="0" />
|
||||
</clipPath>
|
||||
<clipPath
|
||||
id="clip0-2">
|
||||
<rect
|
||||
width="770"
|
||||
height="222.03999"
|
||||
fill="#ffffff"
|
||||
id="rect14-0"
|
||||
x="0"
|
||||
y="0" />
|
||||
</clipPath>
|
||||
<clipPath
|
||||
id="clip0-3">
|
||||
<rect
|
||||
width="770"
|
||||
height="222.03999"
|
||||
fill="#ffffff"
|
||||
id="rect14-6"
|
||||
x="0"
|
||||
y="0" />
|
||||
</clipPath>
|
||||
</defs>
|
||||
<metadata
|
||||
id="metadata972">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<rect
|
||||
style="fill:#ffffff;fill-opacity:1;stroke-width:0.342717;stop-color:#000000"
|
||||
id="rect945"
|
||||
width="63.5"
|
||||
height="26.458334"
|
||||
x="4e-07"
|
||||
y="-1.5122477e-07" />
|
||||
<g
|
||||
id="g967"
|
||||
transform="translate(0.17210258,1.0583333)">
|
||||
<g
|
||||
id="g955"
|
||||
transform="matrix(0.65843845,0,0,0.65843845,0.27576501,1.1223943)">
|
||||
<path
|
||||
d="m 8.9812622,1.4378695 1.2474488,0.00173 7.302287,7.3022874 0.0018,1.3131081 -7.022162,7.02216 -1.7676605,-0.0025 -6.8470822,-6.847084 -0.00242,-1.7019627 7.0877822,-7.087706 z"
|
||||
fill="#d10622"
|
||||
fill-rule="evenodd"
|
||||
id="path884"
|
||||
style="fill:#b3b3b3;stroke-width:0.0383523" />
|
||||
<path
|
||||
d="m 12.889758,1.4378695 1.24741,0.00173 7.302287,7.3022874 0.0018,1.3131081 -7.022161,7.022161 -1.76766,-0.0025 -6.8470835,-6.847084 -0.00242,-1.7019627 7.0878215,-7.0877058 z"
|
||||
fill="#f7c0bd"
|
||||
fill-rule="evenodd"
|
||||
id="path895"
|
||||
style="stroke-width:0.0383523" />
|
||||
<path
|
||||
d="m 16.798207,1.4378695 1.24741,0.00173 7.302287,7.3022874 0.0018,1.3131081 -7.022162,7.022161 -1.767659,-0.0025 -6.8470836,-6.847084 -0.0024,-1.7019626 7.0877436,-7.0877059 z"
|
||||
fill="#0000ff"
|
||||
fill-rule="evenodd"
|
||||
opacity="0.8"
|
||||
id="path906"
|
||||
style="stroke-width:0.0383523" />
|
||||
<path
|
||||
d="m 20.706643,1.4378692 1.247449,0.00173 7.302287,7.3022875 0.0018,1.3131083 -7.022161,7.022161 -1.76766,-0.0025 -6.847122,-6.847084 -0.0024,-1.7019627 7.087783,-7.0877061 z"
|
||||
fill="#ffffff"
|
||||
fill-rule="evenodd"
|
||||
id="path917"
|
||||
style="fill:#e7285d;fill-opacity:1;stroke-width:0.0383523" />
|
||||
</g>
|
||||
<path
|
||||
d="m 58.713926,8.3808577 h 2.793359 l 0.084,-0.04316 c 0.04201,-0.09527 0.04201,-0.173052 0.04201,-0.216608 0,-1.168599 -0.713215,-2.120589 -1.761649,-2.120589 -1.21643,0 -2.013255,0.95199 -2.013255,2.129144 0,1.2036 0.964434,2.1991443 2.180866,2.1991443 0.629215,0 1.216431,-0.30333 1.594038,-0.5627163 v -0.909211 l -0.04201,-0.04277 c -0.419605,0.432439 -1.006435,0.692215 -1.55165,0.692215 -0.713214,0 -1.216431,-0.475995 -1.325708,-1.125434 z m -0.04667,-0.757546 c 0.124051,-0.446441 0.565828,-0.811214 1.184543,-0.811214 0.486495,0 0.928657,0.364773 0.972601,0.811214 z M 56.35728,10.328782 c 0.279997,0 0.726048,-0.118994 0.962101,-0.255108 V 9.2671277 l -0.04394,-0.04277 a 1.5905386,1.5905386 0 0 1 -0.917766,0.297497 c -0.349996,0 -0.656048,-0.254721 -0.656048,-0.934492 v -1.529096 h 1.573817 l 0.04395,-0.04277 v -0.764547 l -0.04395,-0.04239 h -1.57382 v -0.968322 l -0.04395,-0.05094 h -0.787101 l -0.04355,0.04239 v 0.976879 h -0.6996 l -0.04355,0.04277 v 0.764158 l 0.04355,0.04239 h 0.699603 v 1.571483 c 0,1.104433 0.56855,1.6994263 1.530262,1.6994263 z m -3.580069,-4.8696143 0.497773,-0.499328 v -0.08322 l -0.497773,-0.49933 h -0.08284 l -0.497769,0.499329 v 0.08322 l 0.497772,0.499328 z m -1.431873,4.7443943 0.04201,-0.04201 V 6.3127617 l -0.04201,-0.04201 h -0.754437 l -0.04238,0.04201 v 2.802693 c -0.20961,0.25122 -0.629216,0.418441 -1.048434,0.418441 -0.713214,0 -1.048434,-0.418441 -1.048434,-1.087712 v -2.133422 l -0.04201,-0.04201 h -0.755214 l -0.04161,0.04201 v 2.175421 c 0,1.128934 0.628827,1.8405923 1.887258,1.8405923 0.377218,0 0.754825,-0.125609 1.048433,-0.292829 v 0.125608 l 0.04201,0.04161 h 0.754826 z M 44.157191,5.6403867 c 0,-0.373329 0.24772,-0.62377 0.581384,-0.636603 v -0.0016 c 0.510994,0.0062 0.811992,0.302941 1.069433,0.851657 h 0.08711 l 0.6506,-0.511772 c -0.303326,-0.766816 -0.953931,-1.235422 -1.82231,-1.235422 v 0.0023 c -0.88238,0.02061 -1.564093,0.692603 -1.564093,1.532206 0,1.661704 2.646748,1.576538 2.646748,2.769636 0,0.59655 -0.390828,1.022768 -0.954711,1.022768 -0.520717,0 -0.824437,-0.298274 -1.08499,-0.852047 h -0.08672 l -0.650608,0.511383 c 0.30333,0.76727 0.954712,1.2358763 1.822315,1.2358763 1.084987,0 1.9522,-0.8524353 1.9522,-1.9179803 0,-1.959979 -2.646361,-1.917589 -2.646361,-2.770025 z m -2.629248,4.6883953 c 0.279218,0 0.725268,-0.118994 0.961323,-0.255108 V 9.2671277 l -0.04355,-0.04277 c -0.34105,0.237998 -0.673548,0.297497 -0.917766,0.297497 -0.349997,0 -0.656438,-0.254721 -0.656438,-0.934492 v -1.529096 h 1.574204 l 0.04355,-0.04277 v -0.764547 l -0.04355,-0.04239 h -1.574212 v -0.968322 l -0.04355,-0.05094 H 40.04085 l -0.04355,0.04239 v 0.976879 h -0.699992 l -0.04355,0.04277 v 0.764158 l 0.04395,0.04239 h 0.699603 v 1.571483 c 0,1.104433 0.568162,1.6994263 1.530263,1.6994263 z M 38.984247,9.0299077 c 0,-1.68776 -2.341086,-1.081878 -2.341086,-1.817648 0,-0.21622 0.21272,-0.389662 0.595772,-0.389662 0.425439,0 0.851268,0.129886 1.277097,0.432828 l 0.04277,-0.04317 v -0.865656 c -0.340654,-0.216609 -0.808872,-0.346108 -1.319865,-0.346108 -0.894436,0 -1.490206,0.51916 -1.490206,1.211764 0,1.601427 2.341085,0.995546 2.341085,1.818037 0,0.302942 -0.169943,0.475995 -0.766103,0.475995 -0.467828,0 -1.0216,-0.173053 -1.489428,-0.475995 l -0.04277,0.04317 v 0.865658 c 0.383051,0.2597753 1.0216,0.3896613 1.532206,0.3896613 1.021989,0 1.660538,-0.5627163 1.660538,-1.2988743 z m -5.63805,1.2988743 c 0.629603,0 1.216431,-0.30333 1.594038,-0.5627163 v -0.909212 l -0.04199,-0.04277 c -0.419218,0.432439 -1.006434,0.692214 -1.551651,0.692214 -0.713213,0 -1.216431,-0.475995 -1.325319,-1.125433 h 2.79297 l 0.084,-0.04316 c 0.04199,-0.09527 0.04199,-0.173053 0.04199,-0.216609 0,-1.168599 -0.712826,-2.120589 -1.761649,-2.120589 -1.21643,0 -2.013257,0.95199 -2.013257,2.129145 0,1.203599 0.964825,2.1991443 2.180868,2.1991443 z M 31.974211,7.6233117 c 0.124051,-0.446441 0.565828,-0.811214 1.184543,-0.811214 0.486106,0 0.928268,0.364773 0.972601,0.811214 z m -2.409531,2.6623043 1.600649,-3.9716793 -0.04201,-0.04277 h -0.842714 l -0.04201,0.04277 -1.095488,2.849359 -1.0951,-2.849359 -0.04238,-0.04277 h -0.842324 l -0.04238,0.04277 1.601039,3.9720693 0.04201,0.04316 h 0.758316 l 0.04238,-0.04277 z m -2.755247,-0.227498 0.04201,-0.04161 V 7.8410877 c 0,-1.129711 -0.629216,-1.840592 -1.887258,-1.840592 -0.377608,0 -0.755215,0.125227 -1.048824,0.29283 v -0.125609 l -0.04161,-0.04201 h -0.755599 l -0.04201,0.04201 v 3.8487913 l 0.04201,0.04161 h 0.755214 l 0.04161,-0.04161 V 7.2134267 c 0.209997,-0.250831 0.629215,-0.418051 1.048821,-0.418051 0.712825,0 1.048433,0.418051 1.048433,1.087322 v 2.1338103 l 0.04201,0.04161 h 0.754824 z M 21.996206,5.9604407 h 0.0019 v -1.583151 h -0.115497 l -0.693381,0.730715 v 5.1780013 l 0.04044,0.04277 h 0.725659 l 0.04045,-0.04277 V 5.9608287 Z m 30.510342,0.310329 -0.04045,0.04317 v 3.9720693 l 0.04045,0.04316 h 0.727992 l 0.04045,-0.04277 V 6.3135577 l -0.04045,-0.04277 h -0.728382 z"
|
||||
fill="#f7c0bd"
|
||||
fill-rule="evenodd"
|
||||
id="path934"
|
||||
style="fill:#e7285d;fill-opacity:1;stroke-width:0.388885" />
|
||||
</g>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.23333px;line-height:1.25;font-family:Roboto, sans-serif;-inkscape-font-specification:'Roboto, sans-serif';text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;stroke-width:0.116313"
|
||||
x="31.874025"
|
||||
y="21.589594"
|
||||
id="text959"><tspan
|
||||
id="tspan957"
|
||||
x="31.874023"
|
||||
y="21.589594"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.23333px;font-family:Roboto, sans-serif;-inkscape-font-specification:'Roboto, sans-serif';text-align:center;text-anchor:middle;stroke-width:0.116313">Wealthtech jobs with FastAPI</tspan></text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 8.8 KiB |
233
docs/en/docs/img/sponsors/jina-banner.svg
Normal file
|
After Width: | Height: | Size: 41 KiB |
1981
docs/en/docs/img/sponsors/jina.svg
Normal file
|
After Width: | Height: | Size: 215 KiB |
BIN
docs/en/docs/img/sponsors/talkpython.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
1
docs/en/docs/img/sponsors/testdriven.svg
Normal file
|
After Width: | Height: | Size: 26 KiB |
BIN
docs/en/docs/img/sponsors/vimso.png
Normal file
|
After Width: | Height: | Size: 15 KiB |
118
docs/en/docs/img/sponsors/wetransfer.svg
Normal file
@@ -0,0 +1,118 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="240"
|
||||
height="100"
|
||||
viewBox="0 0 63.5 26.458334"
|
||||
version="1.1"
|
||||
id="svg975">
|
||||
<defs
|
||||
id="defs969">
|
||||
<clipPath
|
||||
id="clip0">
|
||||
<rect
|
||||
width="770"
|
||||
height="222.03999"
|
||||
fill="#ffffff"
|
||||
id="rect14"
|
||||
x="0"
|
||||
y="0" />
|
||||
</clipPath>
|
||||
<clipPath
|
||||
id="clip0-7">
|
||||
<rect
|
||||
width="770"
|
||||
height="222.03999"
|
||||
fill="#ffffff"
|
||||
id="rect14-5"
|
||||
x="0"
|
||||
y="0" />
|
||||
</clipPath>
|
||||
</defs>
|
||||
<metadata
|
||||
id="metadata972">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
id="layer1"
|
||||
transform="translate(-75.455132,-135.96141)">
|
||||
<rect
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.364576;stop-color:#000000"
|
||||
id="rect901"
|
||||
width="63.5"
|
||||
height="26.458334"
|
||||
x="75.455132"
|
||||
y="135.96141" />
|
||||
<rect
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.404023;stop-color:#000000"
|
||||
id="rect1758"
|
||||
width="60.854168"
|
||||
height="23.8125"
|
||||
x="76.778053"
|
||||
y="137.28433" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:4.23333px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;stroke-width:0.133861"
|
||||
x="107.22684"
|
||||
y="154.45795"
|
||||
id="text1712"><tspan
|
||||
x="107.22684"
|
||||
y="154.45795"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.23333px;font-family:Roboto;-inkscape-font-specification:Roboto;text-align:center;text-anchor:middle;fill:#000000;stroke-width:0.133861"
|
||||
id="tspan2004">We deal in big ideas. You in?</tspan><tspan
|
||||
x="107.22684"
|
||||
y="159.79095"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.23333px;font-family:Roboto;-inkscape-font-specification:Roboto;text-align:center;text-anchor:middle;fill:#000000;stroke-width:0.133861"
|
||||
id="tspan874" /></text>
|
||||
<g
|
||||
id="g1003"
|
||||
transform="matrix(0.02061785,0,0,0.02061785,70.802235,134.33866)">
|
||||
<g
|
||||
id="g1015"
|
||||
transform="translate(4.0510205)">
|
||||
<path
|
||||
d="m 900.5,226.1 c -21.9,23 -28.6,35.3 -44.3,70.1 L 710.9,630 608.2,396.1 506.6,630 360.2,296.2 c -15.2,-34.8 -21.9,-46 -44.3,-70.1 h 185.7 c -14,11.8 -21.3,26.9 -21.3,46 0,13.4 2.3,23 9.5,40.4 l 55.5,132.4 41,-98.7 -23,-53.3 c -13.5,-30.8 -23,-49.9 -36.5,-66.7 h 185.7 c -18,11.8 -26.9,26.9 -26.9,46 0,13.4 2.3,23 9.5,40.4 L 751.8,445 807.9,312.6 c 7.3,-17.4 10.1,-26.9 10.1,-39.8 0,-16.8 -11.8,-37 -25.3,-46.5 z"
|
||||
id="path966" />
|
||||
<path
|
||||
d="m 1093.5,523.4 c -18,78 -61.2,103.8 -124,103.8 -71.8,0 -139.2,-52.2 -139.2,-150.3 0,-94.2 59.5,-161 137.5,-161 51.1,0 122.9,26.4 122.9,137.4 H 921.3 c 11.8,59.4 50.5,90.3 104.4,90.3 27.4,0 46.5,-5 67.8,-20.2 z M 917.9,414.6 v 7.3 H 992 c 0,-56.1 -12.4,-73.5 -35.9,-73.5 -24.2,0 -38.2,24.1 -38.2,66.2 z"
|
||||
id="path968" />
|
||||
<path
|
||||
d="M 1433.6,327.6 C 1387,283.3 1341,260.3 1305.7,260.3 v 247.4 c 0,49.9 12.9,80.2 47.1,111.1 h -212.1 c 34.2,-30.8 47.1,-61.1 47.1,-111.1 V 260.3 c -35.4,0 -83.6,23 -127.9,67.3 l 22.5,-118.4 c 15.2,11.8 43.2,16.8 74.6,16.8 h 179.6 c 31.4,0 59.5,-5.1 74.6,-16.8 z"
|
||||
id="path970" />
|
||||
<path
|
||||
d="m 1562.6,618.8 h -178.4 c 21.9,-25.8 31.4,-42.6 31.4,-83.6 v -90.9 c 0,-32 -4.5,-47.1 -25.8,-66.7 l -12.3,-11.2 134.7,-50.5 V 386 c 12.9,-40.4 33.1,-70.1 66.2,-70.1 26.9,0 44.3,19.1 44.3,47.1 0,29.7 -18.5,50.5 -44.3,50.5 -5.6,-12.9 -19.1,-19.1 -31.4,-19.1 -10.1,0 -19.6,2.8 -24.7,7.9 v 129.6 c -0.1,43.1 7.2,54.9 40.3,86.9 z"
|
||||
id="path972" />
|
||||
<path
|
||||
d="m 1931.3,567.2 c -6.7,35.3 -35.9,60 -75.8,60 -33.7,0 -59.5,-20.2 -67.3,-43.2 -16.8,30.3 -48.3,43.2 -81.9,43.2 -46.6,0 -78,-30.8 -78,-72.9 0,-49.4 35.4,-83.6 116.7,-103.2 l 37.6,-9 v -50.5 c 0,-31.4 -10.7,-44.3 -29.7,-44.3 -17.9,0 -29.7,11.8 -29.7,28 0,14 6.7,23 18.5,34.2 0,17.9 -28.1,36.4 -57.2,36.4 -28.6,0 -48.8,-21.9 -48.8,-48.8 0,-47.7 52.7,-81.3 130.2,-81.3 80.8,0 123.4,34.2 123.4,110.5 v 120.6 c 0,15.1 9,25.2 23,25.2 8.3,0.1 14.5,-1.6 19,-4.9 z m -148.7,-8.4 v -90.3 l -7.3,2.2 c -24.1,7.3 -40.4,23 -40.4,54.4 0,26.9 10.7,43.2 28.1,43.2 8.9,0 16.2,-2.8 19.6,-9.5 z"
|
||||
id="path974" />
|
||||
<path
|
||||
d="m 2083.3,618.8 h -150.9 c 15.7,-15.1 25.8,-37.6 25.8,-83.6 v -90.9 c 0,-30.8 -3.9,-46.5 -22.4,-63.9 l -12.9,-11.8 139.2,-52.7 v 43.7 c 16.3,-26.9 50.5,-43.7 84.7,-43.7 53.9,0 83.6,29.2 83.6,81.3 v 157.1 c 0,32 8.4,51.6 21.9,64.5 h -147 c 14.6,-14 18.5,-33.1 18.5,-48.2 V 410.1 c 0,-23.5 -7.8,-35.3 -29.7,-35.3 -12.3,0 -22.5,4.5 -29.2,11.2 v 184.5 c -0.1,15.2 3.8,33.7 18.4,48.3 z"
|
||||
id="path976" />
|
||||
<path
|
||||
d="m 2279.7,602.5 v -95.9 c 40.4,52.7 82.5,81.9 121.8,81.9 19.1,0 28.1,-10.1 28.1,-24.1 0,-13.5 -7.3,-21.3 -20.2,-26.4 l -65.1,-24.1 c -49.9,-18.5 -72.4,-49.4 -72.4,-95.3 0,-59.4 48.8,-102.6 118.4,-102.6 37.6,0 79.1,10.6 99.9,25.8 v 81.9 c -25.8,-45.4 -67.9,-70.7 -108.9,-70.7 -20.8,0 -31.4,6.7 -31.4,19.6 0,12.9 7.9,17.9 25.2,25.2 l 76.9,31.4 c 38.7,15.7 56.1,48.8 56.1,88.6 0,65.6 -47.7,109.4 -119.5,109.4 -36,0 -73,-7.9 -108.9,-24.7 z"
|
||||
id="path978" />
|
||||
<path
|
||||
d="m 2519.3,352.3 32.5,-49.9 c 41.5,-62.8 74.7,-93.1 130.8,-93.1 43.8,0 71.8,19.1 71.8,47.7 0,24.7 -20.2,42.6 -62.9,42.6 0,-34.8 -19.6,-47.7 -39.3,-47.7 -19.6,0 -34.8,14 -34.8,37 0,15.7 8.4,31.4 34.2,35.3 h 62.3 l -22.5,28 h -38.2 v 166.6 c 0,31.4 5.1,59.4 37.6,88.1 l 13.5,11.8 h -193.6 c 22.5,-22.4 35.9,-49.9 35.9,-90.3 V 352.3 Z"
|
||||
id="path980" />
|
||||
<path
|
||||
d="m 2959.2,523.4 c -18,78 -61.2,103.8 -124,103.8 -71.8,0 -139.2,-52.2 -139.2,-150.3 0,-94.2 59.5,-161 137.5,-161 51.1,0 122.9,26.4 122.9,137.4 H 2787 c 11.8,59.4 50.5,90.3 104.4,90.3 27.4,0 46.5,-5 67.8,-20.2 z M 2783.6,414.6 v 7.3 h 74.1 c 0,-56.1 -12.4,-73.5 -35.9,-73.5 -24.2,0 -38.2,24.1 -38.2,66.2 z"
|
||||
id="path982" />
|
||||
<path
|
||||
d="m 3147.2,618.8 h -178.4 c 21.9,-25.8 31.4,-42.6 31.4,-83.6 v -90.9 c 0,-32 -4.5,-47.1 -25.8,-66.7 L 2962,366.4 3096.7,315.9 V 386 c 12.9,-40.4 33.1,-70.1 66.2,-70.1 26.9,0 44.3,19.1 44.3,47.1 0,29.7 -18.5,50.5 -44.3,50.5 -5.6,-12.9 -19.1,-19.1 -31.4,-19.1 -10.1,0 -19.6,2.8 -24.7,7.9 v 129.6 c 0,43.1 7.3,54.9 40.4,86.9 z"
|
||||
id="path984" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 6.8 KiB |
|
Before Width: | Height: | Size: 76 KiB After Width: | Height: | Size: 73 KiB |
43
docs/en/docs/img/tutorial/bigger-applications/package.drawio
Normal file
@@ -0,0 +1,43 @@
|
||||
<mxfile host="65bd71144e" modified="2020-11-28T18:13:19.199Z" agent="5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Code/1.51.1 Chrome/83.0.4103.122 Electron/9.3.3 Safari/537.36" etag="KPHuXUeExV3PdWouu_3U" version="13.6.5">
|
||||
<diagram id="zB4-QXJZ7ScUzHSLnJ1i" name="Page-1">
|
||||
<mxGraphModel dx="1154" dy="780" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="1920" pageHeight="1200" math="0" shadow="0" extFonts="Roboto^https://fonts.googleapis.com/css?family=Roboto|Roboto Mono, mono^https://fonts.googleapis.com/css?family=Roboto+Mono%2C+mono">
|
||||
<root>
|
||||
<mxCell id="0"/>
|
||||
<mxCell id="1" parent="0"/>
|
||||
<mxCell id="2" value="" style="rounded=0;whiteSpace=wrap;html=1;fontStyle=1;strokeWidth=4;" parent="1" vertex="1">
|
||||
<mxGeometry x="110" y="280" width="1350" height="620" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="3" value="<font style="font-size: 24px" face="Roboto">Package app<br>app/__init__.py</font>" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;strokeWidth=3;fontFamily=Roboto Mono, mono;FType=g;" parent="1" vertex="1">
|
||||
<mxGeometry x="635" y="310" width="300" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="15" value="<span style="font-family: &#34;roboto&#34; ; font-size: 24px">Module app.main</span><br style="font-family: &#34;roboto&#34; ; font-size: 24px"><span style="font-family: &#34;roboto&#34; ; font-size: 24px">app/main.py</span>" style="shape=hexagon;perimeter=hexagonPerimeter2;whiteSpace=wrap;html=1;fixedSize=1;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="140" y="430" width="360" height="100" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="16" value="<span style="font-family: &#34;roboto&#34; ; font-size: 24px">Module app.dependencies</span><br style="font-family: &#34;roboto&#34; ; font-size: 24px"><span style="font-family: &#34;roboto&#34; ; font-size: 24px">app/dependencies.py</span>" style="shape=hexagon;perimeter=hexagonPerimeter2;whiteSpace=wrap;html=1;fixedSize=1;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="130" y="565" width="370" height="100" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="5" value="" style="rounded=0;whiteSpace=wrap;html=1;fontStyle=1;strokeWidth=4;" parent="1" vertex="1">
|
||||
<mxGeometry x="1030" y="430" width="400" height="260" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="8" value="<font style="font-size: 24px" face="Roboto">Subpackage app.internal<br></font><span style="font-family: &#34;roboto&#34; ; font-size: 24px">app/internal/__init__.py</span><font style="font-size: 24px" face="Roboto"><br></font>" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;strokeWidth=3;fontFamily=Roboto Mono, mono;FType=g;" parent="1" vertex="1">
|
||||
<mxGeometry x="1083.8438461538462" y="460" width="292.3076923076923" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="19" value="<span style="font-family: &#34;roboto&#34; ; font-size: 24px">Module app.internal.admin</span><br style="font-family: &#34;roboto&#34; ; font-size: 24px"><span style="font-family: &#34;roboto&#34; ; font-size: 24px">app/internal/admin.py</span>" style="shape=hexagon;perimeter=hexagonPerimeter2;whiteSpace=wrap;html=1;fixedSize=1;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="1050" y="570" width="360" height="100" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="4" value="" style="rounded=0;whiteSpace=wrap;html=1;fontStyle=1;strokeWidth=4;" parent="1" vertex="1">
|
||||
<mxGeometry x="540" y="430" width="440" height="410" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="7" value="<font style="font-size: 24px" face="Roboto">Subpackage app.routers<br>app/routers/__init__.py<br></font>" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;strokeWidth=3;fontFamily=Roboto Mono, mono;FType=g;" parent="1" vertex="1">
|
||||
<mxGeometry x="599.2307692307693" y="460" width="321.53846153846155" height="80" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="17" value="<span style="font-family: &#34;roboto&#34; ; font-size: 24px">Module app.routers.items</span><br style="font-family: &#34;roboto&#34; ; font-size: 24px"><span style="font-family: &#34;roboto&#34; ; font-size: 24px">app/routers/items.py</span>" style="shape=hexagon;perimeter=hexagonPerimeter2;whiteSpace=wrap;html=1;fixedSize=1;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="580" y="570" width="360" height="100" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="18" value="<span style="font-family: &#34;roboto&#34; ; font-size: 24px">Module app.routers.users</span><br style="font-family: &#34;roboto&#34; ; font-size: 24px"><span style="font-family: &#34;roboto&#34; ; font-size: 24px">app/routers/users.py</span>" style="shape=hexagon;perimeter=hexagonPerimeter2;whiteSpace=wrap;html=1;fixedSize=1;strokeWidth=3;" parent="1" vertex="1">
|
||||
<mxGeometry x="580" y="700" width="360" height="100" as="geometry"/>
|
||||
</mxCell>
|
||||
</root>
|
||||
</mxGraphModel>
|
||||
</diagram>
|
||||
</mxfile>
|
||||
|
After Width: | Height: | Size: 14 KiB |
BIN
docs/en/docs/img/tutorial/body-fields/image02.png
Normal file
|
After Width: | Height: | Size: 92 KiB |
|
Before Width: | Height: | Size: 82 KiB After Width: | Height: | Size: 116 KiB |
@@ -14,9 +14,6 @@
|
||||
<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>
|
||||
|
||||
---
|
||||
@@ -39,10 +36,27 @@ The key features are:
|
||||
* **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>.
|
||||
* **Standards-based**: Based on (and fully compatible with) the open standards for APIs: <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank">OpenAPI</a> (previously known as Swagger) and <a href="https://json-schema.org/" class="external-link" target="_blank">JSON Schema</a>.
|
||||
|
||||
<small>* estimation based on tests on an internal development team, building production applications.</small>
|
||||
|
||||
## Sponsors
|
||||
|
||||
<!-- sponsors -->
|
||||
|
||||
{% if sponsors %}
|
||||
{% for sponsor in sponsors.gold -%}
|
||||
<a href="{{ sponsor.url }}" target="_blank" title="{{ sponsor.title }}"><img src="{{ sponsor.img }}"></a>
|
||||
{% endfor -%}
|
||||
{%- for sponsor in sponsors.silver -%}
|
||||
<a href="{{ sponsor.url }}" target="_blank" title="{{ sponsor.title }}"><img src="{{ sponsor.img }}"></a>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
<!-- /sponsors -->
|
||||
|
||||
<a href="https://fastapi.tiangolo.com/fastapi-people/#sponsors" class="external-link" target="_blank">Other sponsors</a>
|
||||
|
||||
## 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._"
|
||||
@@ -71,7 +85,7 @@ The key features are:
|
||||
|
||||
"_Honestly, what you've built looks super solid and polished. In many ways, it's what I wanted **Hug** to be - it's really inspiring to see someone build that._"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Timothy Crosley - <strong><a href="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>
|
||||
<div style="text-align: right; margin-right: 10%;">Timothy Crosley - <strong><a href="https://www.hug.rest/" target="_blank">Hug</a> creator</strong> <a href="https://news.ycombinator.com/item?id=19455465" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
@@ -112,12 +126,12 @@ $ pip install fastapi
|
||||
|
||||
</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>.
|
||||
You will also need an ASGI server, for production such as <a href="https://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
|
||||
$ pip install uvicorn[standard]
|
||||
|
||||
---> 100%
|
||||
```
|
||||
@@ -428,9 +442,9 @@ Used by Pydantic:
|
||||
|
||||
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://requests.readthedocs.io" 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://jinja.palletsprojects.com" 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).
|
||||
@@ -439,7 +453,7 @@ Used by Starlette:
|
||||
|
||||
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://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]`.
|
||||
|
||||
@@ -128,6 +128,35 @@ function setupTermynal() {
|
||||
loadVisibleTermynals();
|
||||
}
|
||||
|
||||
function shuffle(array) {
|
||||
var currentIndex = array.length, temporaryValue, randomIndex;
|
||||
while (0 !== currentIndex) {
|
||||
randomIndex = Math.floor(Math.random() * currentIndex);
|
||||
currentIndex -= 1;
|
||||
temporaryValue = array[currentIndex];
|
||||
array[currentIndex] = array[randomIndex];
|
||||
array[randomIndex] = temporaryValue;
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
async function showRandomAnnouncement(groupId, timeInterval) {
|
||||
const announceFastAPI = document.getElementById(groupId);
|
||||
if (announceFastAPI) {
|
||||
let children = [].slice.call(announceFastAPI.children);
|
||||
children = shuffle(children)
|
||||
let index = 0
|
||||
const announceRandom = () => {
|
||||
children.forEach((el, i) => {el.style.display = "none"});
|
||||
children[index].style.display = "block"
|
||||
index = (index + 1) % children.length
|
||||
}
|
||||
announceRandom()
|
||||
setInterval(announceRandom, timeInterval
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
async function main() {
|
||||
if (div) {
|
||||
data = await getData()
|
||||
@@ -144,6 +173,8 @@ async function main() {
|
||||
}
|
||||
|
||||
setupTermynal();
|
||||
showRandomAnnouncement('announce-left', 5000)
|
||||
showRandomAnnouncement('announce-right', 10000)
|
||||
}
|
||||
|
||||
main()
|
||||
|
||||
5
docs/en/docs/newsletter.md
Normal file
@@ -0,0 +1,5 @@
|
||||
# FastAPI and friends newsletter
|
||||
|
||||
<iframe class="mj-w-res-iframe" frameborder="0" scrolling="no" marginheight="0" marginwidth="0" src="https://app.mailjet.com/widget/iframe/6gQ4/GDo" width="100%"></iframe>
|
||||
|
||||
<script type="text/javascript" src="https://app.mailjet.com/statics/js/iframeResizer.min.js"></script>
|
||||
@@ -20,7 +20,7 @@ GitHub: <a href="https://github.com/tiangolo/full-stack-fastapi-postgresql" clas
|
||||
* **Easy**: Designed to be easy to use and learn. Less time reading docs.
|
||||
* **Short**: Minimize code duplication. Multiple features from each parameter declaration.
|
||||
* **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> and <a href="http://json-schema.org/" class="external-link" target="_blank">JSON Schema</a>.
|
||||
* **Standards-based**: Based on (and fully compatible with) the open standards for APIs: <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank">OpenAPI</a> and <a href="https://json-schema.org/" class="external-link" target="_blank">JSON Schema</a>.
|
||||
* <a href="https://fastapi.tiangolo.com/features/" class="external-link" target="_blank">**Many other features**</a> including automatic validation, serialization, interactive documentation, authentication with OAuth2 JWT tokens, etc.
|
||||
* **Secure password** hashing by default.
|
||||
* **JWT token** authentication.
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# Python Types Intro
|
||||
|
||||
**Python 3.6+** has support for optional "type hints".
|
||||
Python has support for optional "type hints".
|
||||
|
||||
These **"type hints"** are a new syntax (since Python 3.6+) that allow declaring the <abbr title="for example: str, int, float, bool">type</abbr> of a variable.
|
||||
These **"type hints"** are a special syntax that allow declaring the <abbr title="for example: str, int, float, bool">type</abbr> of a variable.
|
||||
|
||||
By declaring types for your variables, editors and tools can give you better support.
|
||||
|
||||
|
||||
@@ -1,6 +1,405 @@
|
||||
# Release Notes
|
||||
|
||||
## Latest changes
|
||||
## Latest Changes
|
||||
|
||||
|
||||
## 0.65.3
|
||||
|
||||
### Fixes
|
||||
|
||||
* ♻ Assume request bodies contain JSON when no Content-Type header is provided. This fixes a breaking change introduced by [0.65.2 with PR #2118](https://github.com/tiangolo/fastapi/pull/2118). It should allow upgrading FastAPI applications with clients that send JSON data without a `Content-Type` header. And there's still protection against CSRFs. PR [#3456](https://github.com/tiangolo/fastapi/pull/3456) by [@tiangolo](https://github.com/tiangolo).
|
||||
|
||||
### Translations
|
||||
|
||||
* 🌐 Initialize Indonesian translations. PR [#3014](https://github.com/tiangolo/fastapi/pull/3014) by [@pace-noge](https://github.com/pace-noge).
|
||||
* 🌐 Add Spanish translation of Tutorial - Path Parameters. PR [#2219](https://github.com/tiangolo/fastapi/pull/2219) by [@mariacamilagl](https://github.com/mariacamilagl).
|
||||
* 🌐 Add Spanish translation of Tutorial - First Steps. PR [#2208](https://github.com/tiangolo/fastapi/pull/2208) by [@mariacamilagl](https://github.com/mariacamilagl).
|
||||
* 🌐 Portuguese translation of Tutorial - Body - Fields. PR [#3420](https://github.com/tiangolo/fastapi/pull/3420) by [@ComicShrimp](https://github.com/ComicShrimp).
|
||||
* 🌐 Add Chinese translation for Tutorial - Request - Forms - and - Files. PR [#3249](https://github.com/tiangolo/fastapi/pull/3249) by [@jaystone776](https://github.com/jaystone776).
|
||||
* 🌐 Add Chinese translation for Tutorial - Handling - Errors. PR [#3299](https://github.com/tiangolo/fastapi/pull/3299) by [@jaystone776](https://github.com/jaystone776).
|
||||
* 🌐 Add Chinese translation for Tutorial - Form - Data. PR [#3248](https://github.com/tiangolo/fastapi/pull/3248) by [@jaystone776](https://github.com/jaystone776).
|
||||
* 🌐 Add Chinese translation for Tutorial - Body - Updates. PR [#3237](https://github.com/tiangolo/fastapi/pull/3237) by [@jaystone776](https://github.com/jaystone776).
|
||||
* 🌐 Add Chinese translation for FastAPI People. PR [#3112](https://github.com/tiangolo/fastapi/pull/3112) by [@hareru](https://github.com/hareru).
|
||||
* 🌐 Add French translation for Project Generation. PR [#3197](https://github.com/tiangolo/fastapi/pull/3197) by [@Smlep](https://github.com/Smlep).
|
||||
* 🌐 Add French translation for Python Types Intro. PR [#3185](https://github.com/tiangolo/fastapi/pull/3185) by [@Smlep](https://github.com/Smlep).
|
||||
* 🌐 Add French translation for External Links. PR [#3103](https://github.com/tiangolo/fastapi/pull/3103) by [@Smlep](https://github.com/Smlep).
|
||||
* 🌐 Add French translation for Alternatives, Inspiration and Comparisons. PR [#3020](https://github.com/tiangolo/fastapi/pull/3020) by [@rjNemo](https://github.com/rjNemo).
|
||||
* 🌐 Fix Chinese translation code snippet mismatch in Tutorial - Python Types Intro. PR [#2573](https://github.com/tiangolo/fastapi/pull/2573) by [@BoYanZh](https://github.com/BoYanZh).
|
||||
* 🌐 Add Portuguese translation for Development Contributing. PR [#1364](https://github.com/tiangolo/fastapi/pull/1364) by [@Serrones](https://github.com/Serrones).
|
||||
* 🌐 Add Chinese translation for Tutorial - Request - Files. PR [#3244](https://github.com/tiangolo/fastapi/pull/3244) by [@jaystone776](https://github.com/jaystone776).
|
||||
|
||||
### Internal
|
||||
|
||||
* 👥 Update FastAPI People. PR [#3450](https://github.com/tiangolo/fastapi/pull/3450) by [@github-actions[bot]](https://github.com/apps/github-actions).
|
||||
* 👥 Update FastAPI People. PR [#3319](https://github.com/tiangolo/fastapi/pull/3319) by [@github-actions[bot]](https://github.com/apps/github-actions).
|
||||
* ⬆ Upgrade docs development dependency on `typer-cli` to >=0.0.12 to fix conflicts. PR [#3429](https://github.com/tiangolo/fastapi/pull/3429) by [@tiangolo](https://github.com/tiangolo).
|
||||
|
||||
## 0.65.2
|
||||
|
||||
### Security fixes
|
||||
|
||||
* 🔒 Check Content-Type request header before assuming JSON. Initial PR [#2118](https://github.com/tiangolo/fastapi/pull/2118) by [@patrickkwang](https://github.com/patrickkwang).
|
||||
|
||||
This change fixes a [CSRF](https://en.wikipedia.org/wiki/Cross-site_request_forgery) security vulnerability when using cookies for authentication in path operations with JSON payloads sent by browsers.
|
||||
|
||||
In versions lower than `0.65.2`, FastAPI would try to read the request payload as JSON even if the `content-type` header sent was not set to `application/json` or a compatible JSON media type (e.g. `application/geo+json`).
|
||||
|
||||
So, a request with a content type of `text/plain` containing JSON data would be accepted and the JSON data would be extracted.
|
||||
|
||||
But requests with content type `text/plain` are exempt from [CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) preflights, for being considered [Simple requests](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#simple_requests). So, the browser would execute them right away including cookies, and the text content could be a JSON string that would be parsed and accepted by the FastAPI application.
|
||||
|
||||
See [CVE-2021-32677](https://github.com/tiangolo/fastapi/security/advisories/GHSA-8h2j-cgx8-6xv7) for more details.
|
||||
|
||||
Thanks to [Dima Boger](https://twitter.com/b0g3r) for the security report! 🙇🔒
|
||||
|
||||
### Internal
|
||||
|
||||
* 🔧 Update sponsors badge, course bundle. PR [#3340](https://github.com/tiangolo/fastapi/pull/3340) by [@tiangolo](https://github.com/tiangolo).
|
||||
* 🔧 Add new gold sponsor Jina 🎉. PR [#3291](https://github.com/tiangolo/fastapi/pull/3291) by [@tiangolo](https://github.com/tiangolo).
|
||||
* 🔧 Add new banner sponsor badge for FastAPI courses bundle. PR [#3288](https://github.com/tiangolo/fastapi/pull/3288) by [@tiangolo](https://github.com/tiangolo).
|
||||
* 👷 Upgrade Issue Manager GitHub Action. PR [#3236](https://github.com/tiangolo/fastapi/pull/3236) by [@tiangolo](https://github.com/tiangolo).
|
||||
|
||||
## 0.65.1
|
||||
|
||||
### Security fixes
|
||||
|
||||
* 📌 Upgrade pydantic pin, to handle security vulnerability [CVE-2021-29510](https://github.com/samuelcolvin/pydantic/security/advisories/GHSA-5jqp-qgf6-3pvh). PR [#3213](https://github.com/tiangolo/fastapi/pull/3213) by [@tiangolo](https://github.com/tiangolo).
|
||||
|
||||
## 0.65.0
|
||||
|
||||
### Breaking Changes - Upgrade
|
||||
|
||||
* ⬆️ Upgrade Starlette to `0.14.2`, including internal `UJSONResponse` migrated from Starlette. This includes several bug fixes and features from Starlette. PR [#2335](https://github.com/tiangolo/fastapi/pull/2335) by [@hanneskuettner](https://github.com/hanneskuettner).
|
||||
|
||||
### Translations
|
||||
|
||||
* 🌐 Initialize new language Polish for translations. PR [#3170](https://github.com/tiangolo/fastapi/pull/3170) by [@neternefer](https://github.com/neternefer).
|
||||
|
||||
### Internal
|
||||
|
||||
* 👷 Add GitHub Action cache to speed up CI installs. PR [#3204](https://github.com/tiangolo/fastapi/pull/3204) by [@tiangolo](https://github.com/tiangolo).
|
||||
* ⬆️ Upgrade setup-python GitHub Action to v2. PR [#3203](https://github.com/tiangolo/fastapi/pull/3203) by [@tiangolo](https://github.com/tiangolo).
|
||||
* 🐛 Fix docs script to generate a new translation language with `overrides` boilerplate. PR [#3202](https://github.com/tiangolo/fastapi/pull/3202) by [@tiangolo](https://github.com/tiangolo).
|
||||
* ✨ Add new Deta banner badge with new sponsorship tier 🙇. PR [#3194](https://github.com/tiangolo/fastapi/pull/3194) by [@tiangolo](https://github.com/tiangolo).
|
||||
* 👥 Update FastAPI People. PR [#3189](https://github.com/tiangolo/fastapi/pull/3189) by [@github-actions[bot]](https://github.com/apps/github-actions).
|
||||
* 🔊 Update FastAPI People to allow better debugging. PR [#3188](https://github.com/tiangolo/fastapi/pull/3188) by [@tiangolo](https://github.com/tiangolo).
|
||||
|
||||
## 0.64.0
|
||||
|
||||
### Features
|
||||
|
||||
* ✨ Add support for adding multiple `examples` in request bodies and path, query, cookie, and header params. New docs: [Declare Request Example Data](https://fastapi.tiangolo.com/tutorial/schema-extra-example/#body-with-multiple-examples). Initial PR [#1267](https://github.com/tiangolo/fastapi/pull/1267) by [@austinorr](https://github.com/austinorr).
|
||||
|
||||
### Fixes
|
||||
|
||||
* 📌 Pin SQLAlchemy range for tests, as it doesn't use SemVer. PR [#3001](https://github.com/tiangolo/fastapi/pull/3001) by [@tiangolo](https://github.com/tiangolo).
|
||||
* 🎨 Add newly required type annotations for mypy. PR [#2882](https://github.com/tiangolo/fastapi/pull/2882) by [@tiangolo](https://github.com/tiangolo).
|
||||
* 🎨 Remove internal "type: ignore", now unnecessary. PR [#2424](https://github.com/tiangolo/fastapi/pull/2424) by [@AsakuraMizu](https://github.com/AsakuraMizu).
|
||||
|
||||
### Docs
|
||||
|
||||
* 📝 Add link to article in Russian "FastAPI: знакомимся с фреймворком". PR [#2564](https://github.com/tiangolo/fastapi/pull/2564) by [@trkohler](https://github.com/trkohler).
|
||||
* 📝 Add external link to blog post "Authenticate Your FastAPI App with Auth0". PR [#2172](https://github.com/tiangolo/fastapi/pull/2172) by [@dompatmore](https://github.com/dompatmore).
|
||||
* 📝 Fix broken link to article: Machine learning model serving in Python using FastAPI and Streamlit. PR [#2557](https://github.com/tiangolo/fastapi/pull/2557) by [@davidefiocco](https://github.com/davidefiocco).
|
||||
* 📝 Add FastAPI Medium Article: Deploy a dockerized FastAPI application to AWS. PR [#2515](https://github.com/tiangolo/fastapi/pull/2515) by [@vjanz](https://github.com/vjanz).
|
||||
* ✏ Fix typo in Tutorial - Handling Errors. PR [#2486](https://github.com/tiangolo/fastapi/pull/2486) by [@johnthagen](https://github.com/johnthagen).
|
||||
* ✏ Fix typo in Security OAuth2 scopes. PR [#2407](https://github.com/tiangolo/fastapi/pull/2407) by [@jugmac00](https://github.com/jugmac00).
|
||||
* ✏ Fix typo/clarify docs for SQL (Relational) Databases. PR [#2393](https://github.com/tiangolo/fastapi/pull/2393) by [@kangni](https://github.com/kangni).
|
||||
* 📝 Add external link to "FastAPI for Flask Users". PR [#2280](https://github.com/tiangolo/fastapi/pull/2280) by [@amitness](https://github.com/amitness).
|
||||
|
||||
### Translations
|
||||
|
||||
* 🌐 Fix Chinese translation of Tutorial - Query Parameters, remove obsolete content. PR [#3051](https://github.com/tiangolo/fastapi/pull/3051) by [@louis70109](https://github.com/louis70109).
|
||||
* 🌐 Add French translation for Tutorial - Background Tasks. PR [#3098](https://github.com/tiangolo/fastapi/pull/3098) by [@Smlep](https://github.com/Smlep).
|
||||
* 🌐 Fix Korean translation for docs/ko/docs/index.md. PR [#3159](https://github.com/tiangolo/fastapi/pull/3159) by [@SueNaEunYang](https://github.com/SueNaEunYang).
|
||||
* 🌐 Add Korean translation for Tutorial - Query Parameters. PR [#2390](https://github.com/tiangolo/fastapi/pull/2390) by [@hard-coders](https://github.com/hard-coders).
|
||||
* 🌐 Add French translation for FastAPI People. PR [#2232](https://github.com/tiangolo/fastapi/pull/2232) by [@JulianMaurin](https://github.com/JulianMaurin).
|
||||
* 🌐 Add Korean translation for Tutorial - Path Parameters. PR [#2355](https://github.com/tiangolo/fastapi/pull/2355) by [@hard-coders](https://github.com/hard-coders).
|
||||
* 🌐 Add French translation for Features. PR [#2157](https://github.com/tiangolo/fastapi/pull/2157) by [@Jefidev](https://github.com/Jefidev).
|
||||
* 👥 Update FastAPI People. PR [#3031](https://github.com/tiangolo/fastapi/pull/3031) by [@github-actions[bot]](https://github.com/apps/github-actions).
|
||||
* 🌐 Add Chinese translation for Tutorial - Debugging. PR [#2737](https://github.com/tiangolo/fastapi/pull/2737) by [@blt232018](https://github.com/blt232018).
|
||||
* 🌐 Add Chinese translation for Tutorial - Security - OAuth2 with Password (and hashing), Bearer with JWT tokens. PR [#2642](https://github.com/tiangolo/fastapi/pull/2642) by [@waynerv](https://github.com/waynerv).
|
||||
* 🌐 Add Korean translation for Tutorial - Header Parameters. PR [#2589](https://github.com/tiangolo/fastapi/pull/2589) by [@mode9](https://github.com/mode9).
|
||||
* 🌐 Add Chinese translation for Tutorial - Metadata and Docs URLs. PR [#2559](https://github.com/tiangolo/fastapi/pull/2559) by [@blt232018](https://github.com/blt232018).
|
||||
* 🌐 Add Korean translation for Tutorial - First Steps. PR [#2323](https://github.com/tiangolo/fastapi/pull/2323) by [@hard-coders](https://github.com/hard-coders).
|
||||
* 🌐 Add Chinese translation for Tutorial - CORS (Cross-Origin Resource Sharing). PR [#2540](https://github.com/tiangolo/fastapi/pull/2540) by [@blt232018](https://github.com/blt232018).
|
||||
* 🌐 Add Chinese translation for Tutorial - Middleware. PR [#2334](https://github.com/tiangolo/fastapi/pull/2334) by [@lpdswing](https://github.com/lpdswing).
|
||||
* 🌐 Add Korean translation for Tutorial - Intro. PR [#2317](https://github.com/tiangolo/fastapi/pull/2317) by [@hard-coders](https://github.com/hard-coders).
|
||||
* 🌐 Add Chinese translation for Tutorial - Bigger Applications - Multiple Files. PR [#2453](https://github.com/tiangolo/fastapi/pull/2453) by [@waynerv](https://github.com/waynerv).
|
||||
* 🌐 Add Chinese translation for Tutorial - Security - Security Intro. PR [#2443](https://github.com/tiangolo/fastapi/pull/2443) by [@waynerv](https://github.com/waynerv).
|
||||
* 🌐 Add Chinese translation for Tutorial - Header Parameters. PR [#2412](https://github.com/tiangolo/fastapi/pull/2412) by [@maoyibo](https://github.com/maoyibo).
|
||||
* 🌐 Add Chinese translation for Tutorial - Extra Data Types. PR [#2410](https://github.com/tiangolo/fastapi/pull/2410) by [@maoyibo](https://github.com/maoyibo).
|
||||
* 🌐 Add Japanese translation for Deployment - Docker. PR [#2312](https://github.com/tiangolo/fastapi/pull/2312) by [@tokusumi](https://github.com/tokusumi).
|
||||
* 🌐 Add Japanese translation for Deployment - Versions. PR [#2310](https://github.com/tiangolo/fastapi/pull/2310) by [@tokusumi](https://github.com/tokusumi).
|
||||
* 🌐 Add Chinese translation for Tutorial - Cookie Parameters. PR [#2261](https://github.com/tiangolo/fastapi/pull/2261) by [@alicrazy1947](https://github.com/alicrazy1947).
|
||||
* 🌐 Add Japanese translation for Tutorial - Static files. PR [#2260](https://github.com/tiangolo/fastapi/pull/2260) by [@tokusumi](https://github.com/tokusumi).
|
||||
* 🌐 Add Japanese translation for Tutorial - Testing. PR [#2259](https://github.com/tiangolo/fastapi/pull/2259) by [@tokusumi](https://github.com/tokusumi).
|
||||
* 🌐 Add Japanese translation for Tutorial - Debugging. PR [#2256](https://github.com/tiangolo/fastapi/pull/2256) by [@tokusumi](https://github.com/tokusumi).
|
||||
* 🌐 Add Japanese translation for Tutorial - Middleware. PR [#2255](https://github.com/tiangolo/fastapi/pull/2255) by [@tokusumi](https://github.com/tokusumi).
|
||||
* 🌐 Add Japanese translation for Concurrency and async / await. PR [#2058](https://github.com/tiangolo/fastapi/pull/2058) by [@tokusumi](https://github.com/tokusumi).
|
||||
* 🌐 Add Chinese translation for Tutorial - Security - Simple OAuth2 with Password and Bearer. PR [#2514](https://github.com/tiangolo/fastapi/pull/2514) by [@waynerv](https://github.com/waynerv).
|
||||
* 🌐 Add Japanese translation for Deployment - Deta. PR [#2314](https://github.com/tiangolo/fastapi/pull/2314) by [@tokusumi](https://github.com/tokusumi).
|
||||
* 🌐 Add Chinese translation for Tutorial - Security - Get Current User. PR [#2474](https://github.com/tiangolo/fastapi/pull/2474) by [@waynerv](https://github.com/waynerv).
|
||||
* 🌐 Add Japanese translation for Deployment - Manually. PR [#2313](https://github.com/tiangolo/fastapi/pull/2313) by [@tokusumi](https://github.com/tokusumi).
|
||||
* 🌐 Add Japanese translation for Deployment - Intro. PR [#2309](https://github.com/tiangolo/fastapi/pull/2309) by [@tokusumi](https://github.com/tokusumi).
|
||||
* 🌐 Add Japanese translation for FastAPI People. PR [#2254](https://github.com/tiangolo/fastapi/pull/2254) by [@tokusumi](https://github.com/tokusumi).
|
||||
* 🌐 Add Japanese translation for Advanced - Path Operation Advanced Configuration. PR [#2124](https://github.com/tiangolo/fastapi/pull/2124) by [@Attsun1031](https://github.com/Attsun1031).
|
||||
* 🌐 Add Japanese translation for External Links. PR [#2070](https://github.com/tiangolo/fastapi/pull/2070) by [@tokusumi](https://github.com/tokusumi).
|
||||
* 🌐 Add Japanese translation for Tutorial - Body - Updates. PR [#1956](https://github.com/tiangolo/fastapi/pull/1956) by [@SwftAlpc](https://github.com/SwftAlpc).
|
||||
* 🌐 Add Japanese translation for Tutorial - Form Data. PR [#1943](https://github.com/tiangolo/fastapi/pull/1943) by [@SwftAlpc](https://github.com/SwftAlpc).
|
||||
* 🌐 Add Japanese translation for Tutorial - Cookie Parameters. PR [#1933](https://github.com/tiangolo/fastapi/pull/1933) by [@SwftAlpc](https://github.com/SwftAlpc).
|
||||
|
||||
### Internal
|
||||
|
||||
* 🔧 Update top banner, point to newsletter. PR [#3003](https://github.com/tiangolo/fastapi/pull/3003) by [@tiangolo](https://github.com/tiangolo).
|
||||
* 🔧 Disable sponsor WeTransfer. PR [#3002](https://github.com/tiangolo/fastapi/pull/3002) by [@tiangolo](https://github.com/tiangolo).
|
||||
* 👥 Update FastAPI People. PR [#2880](https://github.com/tiangolo/fastapi/pull/2880) by [@github-actions[bot]](https://github.com/apps/github-actions).
|
||||
* 👥 Update FastAPI People. PR [#2739](https://github.com/tiangolo/fastapi/pull/2739) by [@github-actions[bot]](https://github.com/apps/github-actions).
|
||||
* 🔧 Add new Gold Sponsor Talk Python 🎉. PR [#2673](https://github.com/tiangolo/fastapi/pull/2673) by [@tiangolo](https://github.com/tiangolo).
|
||||
* 🔧 Add new Gold Sponsor vim.so 🎉. PR [#2669](https://github.com/tiangolo/fastapi/pull/2669) by [@tiangolo](https://github.com/tiangolo).
|
||||
* 🔧 Add FastAPI user survey banner. PR [#2623](https://github.com/tiangolo/fastapi/pull/2623) by [@tiangolo](https://github.com/tiangolo).
|
||||
* 🔧 Add new Bronze Sponsor(s) 🥉🎉. PR [#2622](https://github.com/tiangolo/fastapi/pull/2622) by [@tiangolo](https://github.com/tiangolo).
|
||||
* 📝 Update social links: add Discord, fix GitHub. PR [#2621](https://github.com/tiangolo/fastapi/pull/2621) by [@tiangolo](https://github.com/tiangolo).
|
||||
* 🔧 Update FastAPI People GitHub Sponsors order. PR [#2620](https://github.com/tiangolo/fastapi/pull/2620) by [@tiangolo](https://github.com/tiangolo).
|
||||
* 🔧 Update InvestSuite sponsor data. PR [#2608](https://github.com/tiangolo/fastapi/pull/2608) by [@tiangolo](https://github.com/tiangolo).
|
||||
* 👥 Update FastAPI People. PR [#2590](https://github.com/tiangolo/fastapi/pull/2590) by [@github-actions[bot]](https://github.com/apps/github-actions).
|
||||
|
||||
## 0.63.0
|
||||
|
||||
### Features
|
||||
|
||||
* ✨ Improve type annotations, add support for mypy --strict, internally and for external packages. PR [#2547](https://github.com/tiangolo/fastapi/pull/2547) by [@tiangolo](https://github.com/tiangolo).
|
||||
|
||||
### Breaking changes
|
||||
|
||||
* ⬆️ Upgrade Uvicorn when installing `fastapi[all]` to the latest version including `uvloop`, the new range is `uvicorn[standard] >=0.12.0,<0.14.0`. PR [#2548](https://github.com/tiangolo/fastapi/pull/2548) by [@tiangolo](https://github.com/tiangolo).
|
||||
|
||||
### Fixes
|
||||
|
||||
* 🐛 PR [#2547](https://github.com/tiangolo/fastapi/pull/2547) (read above) also fixes some false-positive mypy errors with `callbacks` parameters and when using the `OAuth2` class.
|
||||
|
||||
### Docs
|
||||
|
||||
* 📝 Update Uvicorn installation instructions to use uvicorn[standard] (includes uvloop). PR [#2543](https://github.com/tiangolo/fastapi/pull/2543) by [@tiangolo](https://github.com/tiangolo).
|
||||
* 📝 Update title for Deta tutorial. PR [#2466](https://github.com/tiangolo/fastapi/pull/2466) by [@tiangolo](https://github.com/tiangolo).
|
||||
* 👥 Update FastAPI People. PR [#2454](https://github.com/tiangolo/fastapi/pull/2454) by [@github-actions[bot]](https://github.com/apps/github-actions).
|
||||
|
||||
### Translations
|
||||
|
||||
* 🌐 Add docs lang selector widget. PR [#2542](https://github.com/tiangolo/fastapi/pull/2542) by [@tiangolo](https://github.com/tiangolo).
|
||||
* 🌐 Add Chinese translation for Tutorial - Response Status Code. PR [#2442](https://github.com/tiangolo/fastapi/pull/2442) by [@waynerv](https://github.com/waynerv).
|
||||
* 🌐 Start translation of the documentation for the Albanian language. PR [#2516](https://github.com/tiangolo/fastapi/pull/2516) by [@vjanz](https://github.com/vjanz).
|
||||
* 🌐 Add Chinese translation for Tutorial - Extra Models. PR [#2416](https://github.com/tiangolo/fastapi/pull/2416) by [@waynerv](https://github.com/waynerv).
|
||||
* 🌐 Add Chinese translation for Tutorial - Response Model. PR [#2414](https://github.com/tiangolo/fastapi/pull/2414) by [@waynerv](https://github.com/waynerv).
|
||||
* 🌐 Add Chinese translation for Tutorial - Schema Extra Example. PR [#2411](https://github.com/tiangolo/fastapi/pull/2411) by [@maoyibo](https://github.com/maoyibo).
|
||||
* 🌐 Add Korean translation for Index. PR [#2192](https://github.com/tiangolo/fastapi/pull/2192) by [@hard-coders](https://github.com/hard-coders).
|
||||
* 🌐 Add Japanese translation for Advanced User Guide - Additional Status Codes. PR [#2145](https://github.com/tiangolo/fastapi/pull/2145) by [@Attsun1031](https://github.com/Attsun1031).
|
||||
|
||||
### Internal
|
||||
|
||||
* 🐛 Fix docs overrides directory for translations. PR [#2541](https://github.com/tiangolo/fastapi/pull/2541) by [@tiangolo](https://github.com/tiangolo).
|
||||
* ➖ Remove Typer as a docs building dependency (covered by typer-cli) to fix pip resolver conflicts. PR [#2539](https://github.com/tiangolo/fastapi/pull/2539) by [@tiangolo](https://github.com/tiangolo).
|
||||
* ✨ Add newsletter: FastAPI and friends. PR [#2509](https://github.com/tiangolo/fastapi/pull/2509) by [@tiangolo](https://github.com/tiangolo).
|
||||
* ✨ Add new Gold Sponsor: InvestSuite 🎉. PR [#2508](https://github.com/tiangolo/fastapi/pull/2508) by [@tiangolo](https://github.com/tiangolo).
|
||||
* 🔧 Add issue template configs. PR [#2476](https://github.com/tiangolo/fastapi/pull/2476) by [@tiangolo](https://github.com/tiangolo).
|
||||
|
||||
## 0.62.0
|
||||
|
||||
### Features
|
||||
|
||||
* ✨ Add support for shared/top-level parameters (dependencies, tags, etc). PR [#2434](https://github.com/tiangolo/fastapi/pull/2434) by [@tiangolo](https://github.com/tiangolo).
|
||||
|
||||
Up to now, for several options, the only way to apply them to a group of *path operations* was in `include_router`. That works well, but the call to `app.include_router()` or `router.include_router()` is normally done in another file.
|
||||
|
||||
That means that, for example, to apply authentication to all the *path operations* in a router it would end up being done in a different file, instead of keeping related logic together.
|
||||
|
||||
Setting options in `include_router` still makes sense in some cases, for example, to override or increase configurations from a third party router included in an app. But in a router that is part of a bigger application, it would probably make more sense to add those settings when creating the `APIRouter`.
|
||||
|
||||
**In `FastAPI`**
|
||||
|
||||
This allows setting the (mostly new) parameters (additionally to the already existing parameters):
|
||||
|
||||
* `default_response_class`: updated to handle defaults in `APIRouter` and `include_router`.
|
||||
* `dependencies`: to include ✨ top-level dependencies ✨ that apply to the whole application. E.g. to add global authentication.
|
||||
* `callbacks`: OpenAPI callbacks that apply to all the *path operations*.
|
||||
* `deprecated`: to mark all the *path operations* as deprecated. 🤷
|
||||
* `include_in_schema`: to allow excluding all the *path operations* from the OpenAPI schema.
|
||||
* `responses`: OpenAPI responses that apply to all the *path operations*.
|
||||
|
||||
For example:
|
||||
|
||||
```Python
|
||||
from fastapi import FastAPI, Depends
|
||||
|
||||
|
||||
async def some_dependency():
|
||||
return
|
||||
|
||||
|
||||
app = FastAPI(dependencies=[Depends(some_dependency)])
|
||||
```
|
||||
|
||||
**In `APIRouter`**
|
||||
|
||||
This allows setting the (mostly new) parameters (additionally to the already existing parameters):
|
||||
|
||||
* `default_response_class`: updated to handle defaults in `APIRouter` and `include_router`. For example, it's not needed to set it explicitly when [creating callbacks](https://fastapi.tiangolo.com/advanced/openapi-callbacks/).
|
||||
* `dependencies`: to include ✨ router-level dependencies ✨ that apply to all the *path operations* in a router. Up to now, this was only possible with `include_router`.
|
||||
* `callbacks`: OpenAPI callbacks that apply to all the *path operations* in this router.
|
||||
* `deprecated`: to mark all the *path operations* in a router as deprecated.
|
||||
* `include_in_schema`: to allow excluding all the *path operations* in a router from the OpenAPI schema.
|
||||
* `responses`: OpenAPI responses that apply to all the *path operations* in a router.
|
||||
* `prefix`: to set the path prefix for a router. Up to now, this was only possible when calling `include_router`.
|
||||
* `tags`: OpenAPI tags to apply to all the *path operations* in this router.
|
||||
|
||||
For example:
|
||||
|
||||
```Python
|
||||
from fastapi import APIRouter, Depends
|
||||
|
||||
|
||||
async def some_dependency():
|
||||
return
|
||||
|
||||
|
||||
router = APIRouter(prefix="/users", dependencies=[Depends(some_dependency)])
|
||||
```
|
||||
|
||||
**In `include_router`**
|
||||
|
||||
Most of these settings are now supported in `APIRouter`, which normally lives closer to the related code, so it is recommended to use `APIRouter` when possible.
|
||||
|
||||
But `include_router` is still useful to, for example, adding options (like `dependencies`, `prefix`, and `tags`) when including a third party router, or a generic router that is shared between several projects.
|
||||
|
||||
This PR allows setting the (mostly new) parameters (additionally to the already existing parameters):
|
||||
|
||||
* `default_response_class`: updated to handle defaults in `APIRouter` and `FastAPI`.
|
||||
* `deprecated`: to mark all the *path operations* in a router as deprecated in OpenAPI.
|
||||
* `include_in_schema`: to allow disabling all the *path operations* from showing in the OpenAPI schema.
|
||||
* `callbacks`: OpenAPI callbacks that apply to all the *path operations* in this router.
|
||||
|
||||
Note: all the previous parameters are still there, so it's still possible to declare `dependencies` in `include_router`.
|
||||
|
||||
### Breaking Changes
|
||||
|
||||
* PR [#2434](https://github.com/tiangolo/fastapi/pull/2434) includes several improvements that shouldn't affect normal use cases, but could affect in advanced scenarios:
|
||||
* If you are testing the generated OpenAPI (you shouldn't, FastAPI already tests it extensively for you): the order for `tags` in `include_router` and *path operations* was updated for consistency, but it's a simple order change.
|
||||
* If you have advanced custom logic to access each route's `route.response_class`, or the `router.default_response_class`, or the `app.default_response_class`: the default value for `response_class` in `APIRoute` and for `default_response_class` in `APIRouter` and `FastAPI` is now a `DefaultPlaceholder` used internally to handle and solve default values and overrides. The actual response class inside the `DefaultPlaceholder` is available at `route.response_class.value`.
|
||||
|
||||
### Docs
|
||||
|
||||
* PR [#2434](https://github.com/tiangolo/fastapi/pull/2434) (above) includes new or updated docs:
|
||||
* <a href="https://fastapi.tiangolo.com/advanced/openapi-callbacks/" class="external-link" target="_blank">Advanced User Guide - OpenAPI Callbacks</a>.
|
||||
* <a href="https://fastapi.tiangolo.com/tutorial/bigger-applications/" class="external-link" target="_blank">Tutorial - Bigger Applications</a>.
|
||||
* <a href="https://fastapi.tiangolo.com/tutorial/dependencies/dependencies-in-path-operation-decorators/" class="external-link" target="_blank">Tutorial - Dependencies - Dependencies in path operation decorators</a>.
|
||||
* <a href="https://fastapi.tiangolo.com/tutorial/dependencies/global-dependencies/" class="external-link" target="_blank">Tutorial - Dependencies - Global Dependencies</a>.
|
||||
|
||||
* 📝 Add FastAPI monitoring blog post to External Links. PR [#2324](https://github.com/tiangolo/fastapi/pull/2324) by [@louisguitton](https://github.com/louisguitton).
|
||||
* ✏️ Fix typo in Deta tutorial. PR [#2320](https://github.com/tiangolo/fastapi/pull/2320) by [@tiangolo](https://github.com/tiangolo).
|
||||
* ✨ Add Discord chat. PR [#2322](https://github.com/tiangolo/fastapi/pull/2322) by [@tiangolo](https://github.com/tiangolo).
|
||||
* 📝 Fix image links for sponsors. PR [#2304](https://github.com/tiangolo/fastapi/pull/2304) by [@tiangolo](https://github.com/tiangolo).
|
||||
|
||||
### Translations
|
||||
|
||||
* 🌐 Add Japanese translation for Advanced - Custom Response. PR [#2193](https://github.com/tiangolo/fastapi/pull/2193) by [@Attsun1031](https://github.com/Attsun1031).
|
||||
* 🌐 Add Chinese translation for Benchmarks. PR [#2119](https://github.com/tiangolo/fastapi/pull/2119) by [@spaceack](https://github.com/spaceack).
|
||||
* 🌐 Add Chinese translation for Tutorial - Body - Nested Models. PR [#1609](https://github.com/tiangolo/fastapi/pull/1609) by [@waynerv](https://github.com/waynerv).
|
||||
* 🌐 Add Chinese translation for Advanced - Custom Response. PR [#1459](https://github.com/tiangolo/fastapi/pull/1459) by [@RunningIkkyu](https://github.com/RunningIkkyu).
|
||||
* 🌐 Add Chinese translation for Advanced - Return a Response Directly. PR [#1452](https://github.com/tiangolo/fastapi/pull/1452) by [@RunningIkkyu](https://github.com/RunningIkkyu).
|
||||
* 🌐 Add Chinese translation for Advanced - Additional Status Codes. PR [#1451](https://github.com/tiangolo/fastapi/pull/1451) by [@RunningIkkyu](https://github.com/RunningIkkyu).
|
||||
* 🌐 Add Chinese translation for Advanced - Path Operation Advanced Configuration. PR [#1447](https://github.com/tiangolo/fastapi/pull/1447) by [@RunningIkkyu](https://github.com/RunningIkkyu).
|
||||
* 🌐 Add Chinese translation for Advanced User Guide - Intro. PR [#1445](https://github.com/tiangolo/fastapi/pull/1445) by [@RunningIkkyu](https://github.com/RunningIkkyu).
|
||||
|
||||
### Internal
|
||||
|
||||
* 🔧 Update TestDriven link to course in sponsors section. PR [#2435](https://github.com/tiangolo/fastapi/pull/2435) by [@tiangolo](https://github.com/tiangolo).
|
||||
* 🍱 Update sponsor logos. PR [#2418](https://github.com/tiangolo/fastapi/pull/2418) by [@tiangolo](https://github.com/tiangolo).
|
||||
* 💚 Fix disabling install of Material for MkDocs Insiders in forks, strike 1 ⚾. PR [#2340](https://github.com/tiangolo/fastapi/pull/2340) by [@tiangolo](https://github.com/tiangolo).
|
||||
* 🐛 Fix disabling Material for MkDocs Insiders install in forks. PR [#2339](https://github.com/tiangolo/fastapi/pull/2339) by [@tiangolo](https://github.com/tiangolo).
|
||||
* ✨ Add silver sponsor WeTransfer. PR [#2338](https://github.com/tiangolo/fastapi/pull/2338) by [@tiangolo](https://github.com/tiangolo).
|
||||
* ✨ Set up and enable Material for MkDocs Insiders for the docs. PR [#2325](https://github.com/tiangolo/fastapi/pull/2325) by [@tiangolo](https://github.com/tiangolo).
|
||||
|
||||
## 0.61.2
|
||||
|
||||
### Fixes
|
||||
|
||||
* 📌 Relax Swagger UI version pin. PR [#2089](https://github.com/tiangolo/fastapi/pull/2089) by [@jmriebold](https://github.com/jmriebold).
|
||||
* 🐛 Fix bug overriding custom HTTPException and RequestValidationError from exception_handlers. PR [#1924](https://github.com/tiangolo/fastapi/pull/1924) by [@uriyyo](https://github.com/uriyyo).
|
||||
* ✏️ Fix typo on dependencies utils and cleanup unused variable. PR [#1912](https://github.com/tiangolo/fastapi/pull/1912) by [@Kludex](https://github.com/Kludex).
|
||||
|
||||
### Docs
|
||||
|
||||
* ✏️ Fix typo in Tutorial - Path Parameters. PR [#2231](https://github.com/tiangolo/fastapi/pull/2231) by [@mariacamilagl](https://github.com/mariacamilagl).
|
||||
* ✏ Fix a stylistic error in docs. PR [#2206](https://github.com/tiangolo/fastapi/pull/2206) by [@ddobrinskiy](https://github.com/ddobrinskiy).
|
||||
* ✏ Fix capitalizaiton typo in docs. PR [#2204](https://github.com/tiangolo/fastapi/pull/2204) by [@imba-tjd](https://github.com/imba-tjd).
|
||||
* ✏ Fix typo in docs. PR [#2179](https://github.com/tiangolo/fastapi/pull/2179) by [@ammarasmro](https://github.com/ammarasmro).
|
||||
* 📝 Update/fix links in docs to use HTTPS. PR [#2165](https://github.com/tiangolo/fastapi/pull/2165) by [@imba-tjd](https://github.com/imba-tjd).
|
||||
* ✏ Fix typos and add rewording in docs. PR [#2159](https://github.com/tiangolo/fastapi/pull/2159) by [@nukopy](https://github.com/nukopy).
|
||||
* 📝 Fix code consistency in examples for Tutorial - User Guide - Path Parameters. PR [#2158](https://github.com/tiangolo/fastapi/pull/2158) by [@nukopy](https://github.com/nukopy).
|
||||
* 📝 Fix renamed parameter `content_type` typo. PR [#2135](https://github.com/tiangolo/fastapi/pull/2135) by [@TeoZosa](https://github.com/TeoZosa).
|
||||
* ✏ Fix minor typos in docs. PR [#2122](https://github.com/tiangolo/fastapi/pull/2122) by [@TeoZosa](https://github.com/TeoZosa).
|
||||
* ✏ Fix typos in docs and source examples. PR [#2102](https://github.com/tiangolo/fastapi/pull/2102) by [@AdrianDeAnda](https://github.com/AdrianDeAnda).
|
||||
* ✏ Fix incorrect Celery URLs in docs. PR [#2100](https://github.com/tiangolo/fastapi/pull/2100) by [@CircleOnCircles](https://github.com/CircleOnCircles).
|
||||
* 📝 Simplify intro to Python Types, all currently supported Python versions include type hints 🎉. PR [#2085](https://github.com/tiangolo/fastapi/pull/2085) by [@ninjaaron](https://github.com/ninjaaron).
|
||||
* 📝 Fix example code with sets in Tutorial - Body - Nested Models 3. PR [#2054](https://github.com/tiangolo/fastapi/pull/2054) by [@hitrust](https://github.com/hitrust).
|
||||
* 📝 Fix example code with sets in Tutorial - Body - Nested Models 2. PR [#2053](https://github.com/tiangolo/fastapi/pull/2053) by [@hitrust](https://github.com/hitrust).
|
||||
* 📝 Fix example code with sets in Tutorial - Body - Nested Models. PR [#2052](https://github.com/tiangolo/fastapi/pull/2052) by [@hitrust](https://github.com/hitrust).
|
||||
* ✏ Fix typo in Benchmarks. PR [#1995](https://github.com/tiangolo/fastapi/pull/1995) by [@AlejoAsd](https://github.com/AlejoAsd).
|
||||
* 📝 Add note in CORS tutorial about allow_origins with ["*"] and allow_credentials. PR [#1895](https://github.com/tiangolo/fastapi/pull/1895) by [@dsmurrell](https://github.com/dsmurrell).
|
||||
* 📝 Add deployment to Deta, the first gold sponsor 🎉. PR [#2303](https://github.com/tiangolo/fastapi/pull/2303) by [@tiangolo](https://github.com/tiangolo).
|
||||
* 👥 Update FastAPI People. PR [#2282](https://github.com/tiangolo/fastapi/pull/2282) by [@github-actions[bot]](https://github.com/apps/github-actions).
|
||||
* ✏️ Fix uppercase in Tutorial - Query parameters. PR [#2245](https://github.com/tiangolo/fastapi/pull/2245) by [@mariacamilagl](https://github.com/mariacamilagl).
|
||||
* 📝 Add articles to External Links. PR [#2247](https://github.com/tiangolo/fastapi/pull/2247) by [@tiangolo](https://github.com/tiangolo).
|
||||
* ✏ Fix typo in Spanish tutorial index. PR [#2020](https://github.com/tiangolo/fastapi/pull/2020) by [@aviloncho](https://github.com/aviloncho).
|
||||
|
||||
### Translations
|
||||
|
||||
* 🌐 Add Japanese translation for Advanced Tutorial - Response Directly. PR [#2191](https://github.com/tiangolo/fastapi/pull/2191) by [@Attsun1031](https://github.com/Attsun1031).
|
||||
* 📝 Add Japanese translation for Tutorial - Security - First Steps. PR [#2153](https://github.com/tiangolo/fastapi/pull/2153) by [@komtaki](https://github.com/komtaki).
|
||||
* 🌐 Add Japanese translation for Tutorial - Query Parameters and String Validations. PR [#1901](https://github.com/tiangolo/fastapi/pull/1901) by [@SwftAlpc](https://github.com/SwftAlpc).
|
||||
* 🌐 Add Portuguese translation for External Links. PR [#1443](https://github.com/tiangolo/fastapi/pull/1443) by [@Serrones](https://github.com/Serrones).
|
||||
* 🌐 Add Japanese translation for Tutorial - CORS. PR [#2125](https://github.com/tiangolo/fastapi/pull/2125) by [@tokusumi](https://github.com/tokusumi).
|
||||
* 🌐 Add Japanese translation for Contributing. PR [#2067](https://github.com/tiangolo/fastapi/pull/2067) by [@komtaki](https://github.com/komtaki).
|
||||
* 🌐 Add Japanese translation for Project Generation. PR [#2050](https://github.com/tiangolo/fastapi/pull/2050) by [@tokusumi](https://github.com/tokusumi).
|
||||
* 🌐 Add Japanese translation for Alternatives. PR [#2043](https://github.com/tiangolo/fastapi/pull/2043) by [@Attsun1031](https://github.com/Attsun1031).
|
||||
* 🌐 Add Japanese translation for History Design and Future. PR [#2002](https://github.com/tiangolo/fastapi/pull/2002) by [@komtaki](https://github.com/komtaki).
|
||||
* 🌐 Add Japanese translation for Benchmarks. PR [#1992](https://github.com/tiangolo/fastapi/pull/1992) by [@komtaki](https://github.com/komtaki).
|
||||
* 🌐 Add Japanese translation for Tutorial - Header Parameters. PR [#1935](https://github.com/tiangolo/fastapi/pull/1935) by [@SwftAlpc](https://github.com/SwftAlpc).
|
||||
* 🌐 Add Portuguese translation for Tutorial - First Steps. PR [#1861](https://github.com/tiangolo/fastapi/pull/1861) by [@jessicapaz](https://github.com/jessicapaz).
|
||||
* 🌐 Add Portuguese translation for Python Types. PR [#1796](https://github.com/tiangolo/fastapi/pull/1796) by [@izaguerreiro](https://github.com/izaguerreiro).
|
||||
* 🌐 Add Japanese translation for Help FastAPI. PR [#1692](https://github.com/tiangolo/fastapi/pull/1692) by [@tokusumi](https://github.com/tokusumi).
|
||||
* 🌐 Add Japanese translation for Tutorial - Body. PR [#1683](https://github.com/tiangolo/fastapi/pull/1683) by [@tokusumi](https://github.com/tokusumi).
|
||||
* 🌐 Add Japanese translation for Tutorial - Query Params. PR [#1674](https://github.com/tiangolo/fastapi/pull/1674) by [@tokusumi](https://github.com/tokusumi).
|
||||
* 🌐 Add Japanese translation for tutorial/path-params.md. PR [#1671](https://github.com/tiangolo/fastapi/pull/1671) by [@tokusumi](https://github.com/tokusumi).
|
||||
* 🌐 Add Japanese translation for tutorial/first-steps.md. PR [#1658](https://github.com/tiangolo/fastapi/pull/1658) by [@tokusumi](https://github.com/tokusumi).
|
||||
* 🌐 Add Japanese translation for tutorial/index.md. PR [#1656](https://github.com/tiangolo/fastapi/pull/1656) by [@tokusumi](https://github.com/tokusumi).
|
||||
* 🌐 Add translation to Portuguese for Project Generation. PR [#1602](https://github.com/tiangolo/fastapi/pull/1602) by [@Serrones](https://github.com/Serrones).
|
||||
* 🌐 Add Japanese translation for Features. PR [#1625](https://github.com/tiangolo/fastapi/pull/1625) by [@tokusumi](https://github.com/tokusumi).
|
||||
* 🌐 Initialize new language Korean for translations. PR [#2018](https://github.com/tiangolo/fastapi/pull/2018) by [@hard-coders](https://github.com/hard-coders).
|
||||
* 🌐 Add Portuguese translation of Deployment. PR [#1374](https://github.com/tiangolo/fastapi/pull/1374) by [@Serrones](https://github.com/Serrones).
|
||||
|
||||
### Internal
|
||||
|
||||
* 🔥 Cleanup after upgrade for Docs Previews GitHub Action. PR [#2248](https://github.com/tiangolo/fastapi/pull/2248) by [@tiangolo](https://github.com/tiangolo).
|
||||
* 🐛 Fix CI docs preview, unzip docs. PR [#2246](https://github.com/tiangolo/fastapi/pull/2246) by [@tiangolo](https://github.com/tiangolo).
|
||||
* ✨ Add instant docs deploy previews for PRs from forks. PR [#2244](https://github.com/tiangolo/fastapi/pull/2244) by [@tiangolo](https://github.com/tiangolo).
|
||||
* ⚡️ Build docs for languages in parallel in subprocesses to speed up CI. PR [#2242](https://github.com/tiangolo/fastapi/pull/2242) by [@tiangolo](https://github.com/tiangolo).
|
||||
* 🐛 Fix docs order generation for partial translations. PR [#2238](https://github.com/tiangolo/fastapi/pull/2238) by [@tiangolo](https://github.com/tiangolo).
|
||||
* 👥 Update FastAPI People. PR [#2202](https://github.com/tiangolo/fastapi/pull/2202) by [@github-actions[bot]](https://github.com/apps/github-actions).
|
||||
* ♻️ Update FastAPI People GitHub Action to send the PR as github-actions. PR [#2201](https://github.com/tiangolo/fastapi/pull/2201) by [@tiangolo](https://github.com/tiangolo).
|
||||
* 🔧 Update FastAPI People GitHub Action config, run monthly. PR [#2199](https://github.com/tiangolo/fastapi/pull/2199) by [@tiangolo](https://github.com/tiangolo).
|
||||
* 🐛 Fix FastAPI People GitHub Action Docker dependency, strike 1 ⚾. PR [#2198](https://github.com/tiangolo/fastapi/pull/2198) by [@tiangolo](https://github.com/tiangolo).
|
||||
* 🐛 Fix FastAPI People GitHub Action Docker dependencies. PR [#2197](https://github.com/tiangolo/fastapi/pull/2197) by [@tiangolo](https://github.com/tiangolo).
|
||||
* 🐛 Fix FastAPI People GitHub Action when there's nothing to change. PR [#2196](https://github.com/tiangolo/fastapi/pull/2196) by [@tiangolo](https://github.com/tiangolo).
|
||||
* 👥 Add new section FastAPI People. PR [#2195](https://github.com/tiangolo/fastapi/pull/2195) by [@tiangolo](https://github.com/tiangolo).
|
||||
* ⬆️ Upgrade GitHub Action Latest Changes. PR [#2190](https://github.com/tiangolo/fastapi/pull/2190) by [@tiangolo](https://github.com/tiangolo).
|
||||
* ⬆️ Upgrade GitHub Action Label Approved. PR [#2189](https://github.com/tiangolo/fastapi/pull/2189) by [@tiangolo](https://github.com/tiangolo).
|
||||
* 🔧 Update GitHub Action Label Approved, run at 12:00. PR [#2185](https://github.com/tiangolo/fastapi/pull/2185) by [@tiangolo](https://github.com/tiangolo).
|
||||
* 👷 Upgrade GitHub Action Latest Changes. PR [#2184](https://github.com/tiangolo/fastapi/pull/2184) by [@tiangolo](https://github.com/tiangolo).
|
||||
* 👷 Set GitHub Action Label Approved to run daily, not every minute. PR [#2163](https://github.com/tiangolo/fastapi/pull/2163) by [@tiangolo](https://github.com/tiangolo).
|
||||
* 🔥 Remove pr-approvals GitHub Action as it's not compatible with forks. Use the new one. PR [#2162](https://github.com/tiangolo/fastapi/pull/2162) by [@tiangolo](https://github.com/tiangolo).
|
||||
* 👷 Add GitHub Action Latest Changes. PR [#2160](https://github.com/tiangolo/fastapi/pull/2160).
|
||||
* 👷 Add GitHub Action Label Approved. PR [#2161](https://github.com/tiangolo/fastapi/pull/2161).
|
||||
|
||||
## 0.61.1
|
||||
|
||||
|
||||
@@ -81,7 +81,7 @@ You can see more details in <a href="https://www.starlette.io/background/" class
|
||||
|
||||
## Caveat
|
||||
|
||||
If you need to perform heavy background computation and you don't necessarily need it to be run by the same process (for example, you don't need to share memory, variables, etc), you might benefit from using other bigger tools like <a href="http://www.celeryproject.org/" class="external-link" target="_blank">Celery</a>.
|
||||
If you need to perform heavy background computation and you don't necessarily need it to be run by the same process (for example, you don't need to share memory, variables, etc), you might benefit from using other bigger tools like <a href="https://docs.celeryproject.org" class="external-link" target="_blank">Celery</a>.
|
||||
|
||||
They tend to require more complex configurations, a message/job queue manager, like RabbitMQ or Redis, but they allow you to run background tasks in multiple processes, and especially, in multiple servers.
|
||||
|
||||
|
||||
@@ -16,14 +16,18 @@ Let's say you have a file structure like this:
|
||||
├── app
|
||||
│ ├── __init__.py
|
||||
│ ├── main.py
|
||||
│ ├── dependencies.py
|
||||
│ └── routers
|
||||
│ │ ├── __init__.py
|
||||
│ │ ├── items.py
|
||||
│ │ └── users.py
|
||||
│ └── internal
|
||||
│ ├── __init__.py
|
||||
│ ├── items.py
|
||||
│ └── users.py
|
||||
│ └── admin.py
|
||||
```
|
||||
|
||||
!!! tip
|
||||
There are two `__init__.py` files: one in each directory or subdirectory.
|
||||
There are several `__init__.py` files: one in each directory or subdirectory.
|
||||
|
||||
This is what allows importing code from one file into another.
|
||||
|
||||
@@ -33,18 +37,33 @@ Let's say you have a file structure like this:
|
||||
from app.routers import items
|
||||
```
|
||||
|
||||
* The `app` directory contains everything.
|
||||
* This `app` directory has an empty file `app/__init__.py`.
|
||||
* So, the `app` directory is a "Python package" (a collection of "Python modules").
|
||||
* The `app` directory also has a `app/main.py` file.
|
||||
* As it is inside a Python package directory (because there's a file `__init__.py`), it is a "module" of that package: `app.main`.
|
||||
* There's a subdirectory `app/routers/`.
|
||||
* The subdirectory `app/routers` also has an empty file `__init__.py`.
|
||||
* So, it is a "Python subpackage".
|
||||
* The file `app/routers/items.py` is beside the `app/routers/__init__.py`.
|
||||
* So, it's a submodule: `app.routers.items`.
|
||||
* The file `app/routers/users.py` is beside the `app/routers/__init__.py`.
|
||||
* So, it's a submodule: `app.routers.users`.
|
||||
* The `app` directory contains everything. And it has an empty file `app/__init__.py`, so it is a "Python package" (a collection of "Python modules"): `app`.
|
||||
* It contains an `app/main.py` file. As it is inside a Python package (a directory with a file `__init__.py`), it is a "module" of that package: `app.main`.
|
||||
* There's also an `app/dependencies.py` file, just like `app/main.py`, it is a "module": `app.dependencies`.
|
||||
* There's a subdirectory `app/routers/` with another file `__init__.py`, so it's a "Python subpackage": `app.routers`.
|
||||
* The file `app/routers/items.py` is inside a package, `app/routers/`, so, it's a submodule: `app.routers.items`.
|
||||
* The same with `app/routers/users.py`, it's another submodule: `app.routers.users`.
|
||||
* There's also a subdirectory `app/internal/` with another file `__init__.py`, so it's another "Python subpackage": `app.internal`.
|
||||
* And the file `app/internal/admin.py` is another submodule: `app.internal.admin`.
|
||||
|
||||
<img src="/img/tutorial/bigger-applications/package.svg">
|
||||
|
||||
The same file structure with comments:
|
||||
|
||||
```
|
||||
.
|
||||
├── app # "app" is a Python package
|
||||
│ ├── __init__.py # this file makes "app" a "Python package"
|
||||
│ ├── main.py # "main" module, e.g. import app.main
|
||||
│ ├── dependencies.py # "dependencies" module, e.g. import app.dependencies
|
||||
│ └── routers # "routers" is a "Python subpackage"
|
||||
│ │ ├── __init__.py # makes "routers" a "Python subpackage"
|
||||
│ │ ├── items.py # "items" submodule, e.g. import app.routers.items
|
||||
│ │ └── users.py # "users" submodule, e.g. import app.routers.users
|
||||
│ └── internal # "internal" is a "Python subpackage"
|
||||
│ ├── __init__.py # makes "internal" a "Python subpackage"
|
||||
│ └── admin.py # "admin" submodule, e.g. import app.internal.admin
|
||||
```
|
||||
|
||||
## `APIRouter`
|
||||
|
||||
@@ -78,16 +97,33 @@ You can think of `APIRouter` as a "mini `FastAPI`" class.
|
||||
|
||||
All the same options are supported.
|
||||
|
||||
All the same parameters, responses, dependencies, tags, etc.
|
||||
All the same `parameters`, `responses`, `dependencies`, `tags`, etc.
|
||||
|
||||
!!! tip
|
||||
In this example, the variable is called `router`, but you can name it however you want.
|
||||
|
||||
We are going to include this `APIrouter` in the main `FastAPI` app, but first, let's add another `APIRouter`.
|
||||
We are going to include this `APIRouter` in the main `FastAPI` app, but first, let's check the dependencies and another `APIRouter`.
|
||||
|
||||
## Dependencies
|
||||
|
||||
We see that we are going to need some dependencies used in several places of the application.
|
||||
|
||||
So we put them in their own `dependencies` module (`app/dependencies.py`).
|
||||
|
||||
We will now use a simple dependency to read a custom `X-Token` header:
|
||||
|
||||
```Python hl_lines="1 4-6"
|
||||
{!../../../docs_src/bigger_applications/app/dependencies.py!}
|
||||
```
|
||||
|
||||
!!! tip
|
||||
We are using an invented header to simplify this example.
|
||||
|
||||
But in real cases you will get better results using the integrated [Security utilities](./security/index.md){.internal-link target=_blank}.
|
||||
|
||||
## Another module with `APIRouter`
|
||||
|
||||
Let's say you also have the endpoints dedicated to handling "Items" from your application in the module at `app/routers/items.py`.
|
||||
Let's say you also have the endpoints dedicated to handling "items" from your application in the module at `app/routers/items.py`.
|
||||
|
||||
You have *path operations* for:
|
||||
|
||||
@@ -96,24 +132,148 @@ You have *path operations* for:
|
||||
|
||||
It's all the same structure as with `app/routers/users.py`.
|
||||
|
||||
But let's say that this time we are more lazy.
|
||||
But we want to be smarter and simplify the code a bit.
|
||||
|
||||
And we don't want to have to explicitly type `/items/` and `tags=["items"]` in every *path operation* (we will be able to do it later):
|
||||
We know all the *path operations* in this module have the same:
|
||||
|
||||
```Python hl_lines="6 11"
|
||||
* Path `prefix`: `/items`.
|
||||
* `tags`: (just one tag: `items`).
|
||||
* Extra `responses`.
|
||||
* `dependencies`: they all need that `X-Token` dependency we created.
|
||||
|
||||
So, instead of adding all that to each *path operation*, we can add it to the `APIRouter`.
|
||||
|
||||
```Python hl_lines="5-10 16 21"
|
||||
{!../../../docs_src/bigger_applications/app/routers/items.py!}
|
||||
```
|
||||
|
||||
As the path of each *path operation* has to start with `/`, like in:
|
||||
|
||||
```Python hl_lines="1"
|
||||
@router.get("/{item_id}")
|
||||
async def read_item(item_id: str):
|
||||
...
|
||||
```
|
||||
|
||||
...the prefix must not include a final `/`.
|
||||
|
||||
So, the prefix in this case is `/items`.
|
||||
|
||||
We can also add a list of `tags` and extra `responses` that will be applied to all the *path operations* included in this router.
|
||||
|
||||
And we can add a list of `dependencies` that will be added to all the *path operations* in the router and will be executed/solved for each request made to them.
|
||||
|
||||
!!! tip
|
||||
Note that, much like [dependencies in *path operation decorators*](dependencies/dependencies-in-path-operation-decorators.md){.internal-link target=_blank}, no value will be passed to your *path operation function*.
|
||||
|
||||
The end result is that the item paths are now:
|
||||
|
||||
* `/items/`
|
||||
* `/items/{item_id}`
|
||||
|
||||
...as we intended.
|
||||
|
||||
* They will be marked with a list of tags that contain a single string `"items"`.
|
||||
* These "tags" are especially useful for the automatic interactive documentation systems (using OpenAPI).
|
||||
* All of them will include the predefined `responses`.
|
||||
* All these *path operations* will have the list of `dependencies` evaluated/executed before them.
|
||||
* If you also declare dependencies in a specific *path operation*, **they will be executed too**.
|
||||
* The router dependencies are executed first, then the [`dependencies` in the decorator](dependencies/dependencies-in-path-operation-decorators.md){.internal-link target=_blank}, and then the normal parameter dependencies.
|
||||
* You can also add [`Security` dependencies with `scopes`](../advanced/security/oauth2-scopes.md){.internal-link target=_blank}.
|
||||
|
||||
!!! tip
|
||||
Having `dependencies` in the `APIRouter` can be used, for example, to require authentication for a whole group of *path operations*. Even if the dependencies are not added individually to each one of them.
|
||||
|
||||
!!! check
|
||||
The `prefix`, `tags`, `responses`, and `dependencies` parameters are (as in many other cases) just a feature from **FastAPI** to help you avoid code duplication.
|
||||
|
||||
### Import the dependencies
|
||||
|
||||
This codes lives in the module `app.routers.items`, the file `app/routers/items.py`.
|
||||
|
||||
And we need to get the dependency function from the module `app.dependencies`, the file `app/dependencies.py`.
|
||||
|
||||
So we use a relative import with `..` for the dependencies:
|
||||
|
||||
```Python hl_lines="3"
|
||||
{!../../../docs_src/bigger_applications/app/routers/items.py!}
|
||||
```
|
||||
|
||||
#### How relative imports work
|
||||
|
||||
!!! tip
|
||||
If you know perfectly how imports work, continue to the next section below.
|
||||
|
||||
A single dot `.`, like in:
|
||||
|
||||
```Python
|
||||
from .dependencies import get_token_header
|
||||
```
|
||||
|
||||
would mean:
|
||||
|
||||
* Starting in the same package that this module (the file `app/routers/items.py`) lives in (the directory `app/routers/`)...
|
||||
* find the module `dependencies` (an imaginary file at `app/routers/dependencies.py`)...
|
||||
* and from it, import the function `get_token_header`.
|
||||
|
||||
But that file doesn't exist, our dependencies are in a file at `app/dependencies.py`.
|
||||
|
||||
Remember how our app/file structure looks like:
|
||||
|
||||
<img src="/img/tutorial/bigger-applications/package.svg">
|
||||
|
||||
---
|
||||
|
||||
The two dots `..`, like in:
|
||||
|
||||
```Python
|
||||
from ..dependencies import get_token_header
|
||||
```
|
||||
|
||||
mean:
|
||||
|
||||
* Starting in the same package that this module (the file `app/routers/items.py`) lives in (the directory `app/routers/`)...
|
||||
* go to the parent package (the directory `app/`)...
|
||||
* and in there, find the module `dependencies` (the file at `app/routers/dependencies.py`)...
|
||||
* and from it, import the function `get_token_header`.
|
||||
|
||||
That works correctly! 🎉
|
||||
|
||||
---
|
||||
|
||||
The same way, if we had used three dots `...`, like in:
|
||||
|
||||
```Python
|
||||
from ...dependencies import get_token_header
|
||||
```
|
||||
|
||||
that would mean:
|
||||
|
||||
* Starting in the same package that this module (the file `app/routers/items.py`) lives in (the directory `app/routers/`)...
|
||||
* go to the parent package (the directory `app/`)...
|
||||
* then go to the parent of that package (there's no parent package, `app` is the top level 😱)...
|
||||
* and in there, find the module `dependencies` (the file at `app/routers/dependencies.py`)...
|
||||
* and from it, import the function `get_token_header`.
|
||||
|
||||
That would refer to some package above `app/`, with its own file `__init__.py`, etc. But we don't have that. So, that would throw an error in our example. 🚨
|
||||
|
||||
But now you know how it works, so you can use relative imports in your own apps no matter how complex they are. 🤓
|
||||
|
||||
### Add some custom `tags`, `responses`, and `dependencies`
|
||||
|
||||
We are not adding the prefix `/items/` nor the `tags=["items"]` to add them later.
|
||||
We are not adding the prefix `/items` nor the `tags=["items"]` to each *path operation* because we added them to the `APIRouter`.
|
||||
|
||||
But we can add custom `tags` and `responses` that will be applied to a specific *path operation*:
|
||||
But we can still add _more_ `tags` that will be applied to a specific *path operation*, and also some extra `responses` specific to that *path operation*:
|
||||
|
||||
```Python hl_lines="18-19"
|
||||
```Python hl_lines="30-31"
|
||||
{!../../../docs_src/bigger_applications/app/routers/items.py!}
|
||||
```
|
||||
|
||||
!!! tip
|
||||
This last path operation will have the combination of tags: `["items", "custom"]`.
|
||||
|
||||
And it will also have both responses in the documentation, one for `404` and one for `403`.
|
||||
|
||||
## The main `FastAPI`
|
||||
|
||||
Now, let's see the module at `app/main.py`.
|
||||
@@ -122,25 +282,27 @@ Here's where you import and use the class `FastAPI`.
|
||||
|
||||
This will be the main file in your application that ties everything together.
|
||||
|
||||
And as most of your logic will now live in its own specific module, the main file will be quite simple.
|
||||
|
||||
### Import `FastAPI`
|
||||
|
||||
You import and create a `FastAPI` class as normally:
|
||||
You import and create a `FastAPI` class as normally.
|
||||
|
||||
```Python hl_lines="1 5"
|
||||
And we can even declare [global dependencies](dependencies/global-dependencies.md){.internal-link target=_blank} that will be combined with the dependencies for each `APIRouter`:
|
||||
|
||||
```Python hl_lines="1 3 7"
|
||||
{!../../../docs_src/bigger_applications/app/main.py!}
|
||||
```
|
||||
|
||||
### Import the `APIRouter`
|
||||
|
||||
But this time we are not adding *path operations* directly with the `FastAPI` `app`.
|
||||
Now we import the other submodules that have `APIRouter`s:
|
||||
|
||||
We import the other submodules that have `APIRouter`s:
|
||||
|
||||
```Python hl_lines="3"
|
||||
```Python hl_lines="5"
|
||||
{!../../../docs_src/bigger_applications/app/main.py!}
|
||||
```
|
||||
|
||||
As the file `app/routers/items.py` is part of the same Python package, we can import it using "dot notation".
|
||||
As the files `app/routers/users.py` and `app/routers/items.py` are submodules that are part of the same Python package `app`, we can use a single dot `.` to import them using "relative imports".
|
||||
|
||||
### How the importing works
|
||||
|
||||
@@ -156,7 +318,9 @@ Means:
|
||||
* look for the subpackage `routers` (the directory at `app/routers/`)...
|
||||
* and from it, import the submodule `items` (the file at `app/routers/items.py`) and `users` (the file at `app/routers/users.py`)...
|
||||
|
||||
The module `items` will have a variable `router` (`items.router`). This is the same one we created in the file `app/routers/items.py`. It's an `APIRouter`. The same for the module `users`.
|
||||
The module `items` will have a variable `router` (`items.router`). This is the same one we created in the file `app/routers/items.py`, it's an `APIRouter` object.
|
||||
|
||||
And then we do the same for the module `users`.
|
||||
|
||||
We could also import them like:
|
||||
|
||||
@@ -165,9 +329,17 @@ from app.routers import items, users
|
||||
```
|
||||
|
||||
!!! info
|
||||
The first version is a "relative import".
|
||||
The first version is a "relative import":
|
||||
|
||||
The second version is an "absolute import".
|
||||
```Python
|
||||
from .routers import items, users
|
||||
```
|
||||
|
||||
The second version is an "absolute import":
|
||||
|
||||
```Python
|
||||
from app.routers import items, users
|
||||
```
|
||||
|
||||
To learn more about Python Packages and Modules, read <a href="https://docs.python.org/3/tutorial/modules.html" class="external-link" target="_blank">the official Python documentation about Modules</a>.
|
||||
|
||||
@@ -188,22 +360,24 @@ The `router` from `users` would overwrite the one from `items` and we wouldn't b
|
||||
|
||||
So, to be able to use both of them in the same file, we import the submodules directly:
|
||||
|
||||
```Python hl_lines="3"
|
||||
```Python hl_lines="4"
|
||||
{!../../../docs_src/bigger_applications/app/main.py!}
|
||||
```
|
||||
|
||||
### Include an `APIRouter`
|
||||
### Include the `APIRouter`s for `users` and `items`
|
||||
|
||||
Now, let's include the `router` from the submodule `users`:
|
||||
Now, let's include the `router`s from the submodules `users` and `items`:
|
||||
|
||||
```Python hl_lines="13"
|
||||
```Python hl_lines="10-11"
|
||||
{!../../../docs_src/bigger_applications/app/main.py!}
|
||||
```
|
||||
|
||||
!!! info
|
||||
`users.router` contains the `APIRouter` inside of the file `app/routers/users.py`.
|
||||
|
||||
With `app.include_router()` we can add an `APIRouter` to the main `FastAPI` application.
|
||||
And `items.router` contains the `APIRouter` inside of the file `app/routers/items.py`.
|
||||
|
||||
With `app.include_router()` we can add each `APIRouter` to the main `FastAPI` application.
|
||||
|
||||
It will include all the routes from that router as part of it.
|
||||
|
||||
@@ -217,67 +391,52 @@ It will include all the routes from that router as part of it.
|
||||
|
||||
This will take microseconds and will only happen at startup.
|
||||
|
||||
So it won't affect performance.
|
||||
So it won't affect performance. ⚡
|
||||
|
||||
### Include an `APIRouter` with a `prefix`, `tags`, `responses`, and `dependencies`
|
||||
### Include an `APIRouter` with a custom `prefix`, `tags`, `responses`, and `dependencies`
|
||||
|
||||
Now, let's include the router from the `items` submodule.
|
||||
Now, let's imagine your organization gave you the `app/internal/admin.py` file.
|
||||
|
||||
But, remember that we were lazy and didn't add `/items/` nor `tags` to all the *path operations*?
|
||||
It contains an `APIRouter` with some admin *path operations* that your organization shares between several projects.
|
||||
|
||||
We can add a prefix to all the *path operations* using the parameter `prefix` of `app.include_router()`.
|
||||
For this example it will be super simple. But let's say that because it is shared with other projects in the organization, we cannot modify it and add a `prefix`, `dependencies`, `tags`, etc. directly to the `APIRouter`:
|
||||
|
||||
As the path of each *path operation* has to start with `/`, like in:
|
||||
|
||||
```Python hl_lines="1"
|
||||
@router.get("/{item_id}")
|
||||
async def read_item(item_id: str):
|
||||
...
|
||||
```Python hl_lines="3"
|
||||
{!../../../docs_src/bigger_applications/app/internal/admin.py!}
|
||||
```
|
||||
|
||||
...the prefix must not include a final `/`.
|
||||
But we still want to set a custom `prefix` when including the `APIRouter` so that all its *path operations* start with `/admin`, we want to secure it with the `dependencies` we already have for this project, and we want to include `tags` and `responses`.
|
||||
|
||||
So, the prefix in this case would be `/items`.
|
||||
We can declare all that without having to modify the original `APIRouter` by passing those parameters to `app.include_router()`:
|
||||
|
||||
We can also add a list of `tags` that will be applied to all the *path operations* included in this router.
|
||||
|
||||
And we can add predefined `responses` that will be included in all the *path operations* too.
|
||||
|
||||
And we can add a list of `dependencies` that will be added to all the *path operations* in the router and will be executed/solved for each request made to them. Note that, much like dependencies in *path operation decorators*, no value will be passed to your *path operation function*.
|
||||
|
||||
```Python hl_lines="8-10 14-20"
|
||||
```Python hl_lines="14-17"
|
||||
{!../../../docs_src/bigger_applications/app/main.py!}
|
||||
```
|
||||
|
||||
The end result is that the item paths are now:
|
||||
That way, the original `APIRouter` will keep unmodified, so we can still share that same `app/internal/admin.py` file with other projects in the organization.
|
||||
|
||||
* `/items/`
|
||||
* `/items/{item_id}`
|
||||
The result is that in our app, each of the *path operations* from the `admin` module will have:
|
||||
|
||||
...as we intended.
|
||||
* The prefix `/admin`.
|
||||
* The tag `admin`.
|
||||
* The dependency `get_token_header`.
|
||||
* The response `418`. 🍵
|
||||
|
||||
* They will be marked with a list of tags that contain a single string `"items"`.
|
||||
* The *path operation* that declared a `"custom"` tag will have both tags, `items` and `custom`.
|
||||
* These "tags" are especially useful for the automatic interactive documentation systems (using OpenAPI).
|
||||
* All of them will include the predefined `responses`.
|
||||
* The *path operation* that declared a custom `403` response will have both the predefined responses (`404`) and the `403` declared in it directly.
|
||||
* All these *path operations* will have the list of `dependencies` evaluated/executed before them.
|
||||
* If you also declare dependencies in a specific *path operation*, **they will be executed too**.
|
||||
* The router dependencies are executed first, then the [`dependencies` in the decorator](dependencies/dependencies-in-path-operation-decorators.md){.internal-link target=_blank}, and then the normal parameter dependencies.
|
||||
* You can also add [`Security` dependencies with `scopes`](../advanced/security/oauth2-scopes.md){.internal-link target=_blank}.
|
||||
But that will only affect that `APIRouter` in our app, not in any other code that uses it.
|
||||
|
||||
!!! tip
|
||||
Having `dependencies` in a decorator can be used, for example, to require authentication for a whole group of *path operations*. Even if the dependencies are not added individually to each one of them.
|
||||
So, for example, other projects could use the same `APIRouter` with a different authentication method.
|
||||
|
||||
!!! check
|
||||
The `prefix`, `tags`, `responses` and `dependencies` parameters are (as in many other cases) just a feature from **FastAPI** to help you avoid code duplication.
|
||||
### Include a *path operation*
|
||||
|
||||
!!! tip
|
||||
You could also add *path operations* directly, for example with: `@app.get(...)`.
|
||||
We can also add *path operations* directly to the `FastAPI` app.
|
||||
|
||||
Apart from `app.include_router()`, in the same **FastAPI** app.
|
||||
Here we do it... just to show that we can 🤷:
|
||||
|
||||
It would still work the same.
|
||||
```Python hl_lines="21-23"
|
||||
{!../../../docs_src/bigger_applications/app/main.py!}
|
||||
```
|
||||
|
||||
and it will work correctly, together with all the other *path operations* added with `app.include_router()`.
|
||||
|
||||
!!! info "Very Technical Details"
|
||||
**Note**: this is a very technical detail that you probably can **just skip**.
|
||||
@@ -317,3 +476,13 @@ You can also use `.include_router()` multiple times with the *same* router using
|
||||
This could be useful, for example, to expose the same API under different prefixes, e.g. `/api/v1` and `/api/latest`.
|
||||
|
||||
This is an advanced usage that you might not really need, but it's there in case you do.
|
||||
|
||||
## Include an `APIRouter` in another
|
||||
|
||||
The same way you can include an `APIRouter` in a `FastAPI` application, you can include an `APIRouter` in another `APIRouter` using:
|
||||
|
||||
```Python
|
||||
router.include_router(other_router)
|
||||
```
|
||||
|
||||
Make sure you do it before including `router` in the `FastAPI` app, so that the *path operations* from `other_router` are also included.
|
||||
|
||||
@@ -75,7 +75,7 @@ With just that Python type declaration, **FastAPI** will:
|
||||
* If the data is invalid, it will return a nice and clear error, indicating exactly where and what was the incorrect data.
|
||||
* Give you the received data in the parameter `item`.
|
||||
* As you declared it in the function to be of type `Item`, you will also have all the editor support (completion, etc) for all of the attributes and their types.
|
||||
* Generate <a href="http://json-schema.org" class="external-link" target="_blank">JSON Schema</a> definitions for your model, you can also use them anywhere else you like if it makes sense for your project.
|
||||
* Generate <a href="https://json-schema.org" class="external-link" target="_blank">JSON Schema</a> definitions for your model, you can also use them anywhere else you like if it makes sense for your project.
|
||||
* Those schemas will be part of the generated OpenAPI schema, and used by the automatic documentation <abbr title="User Interfaces">UIs</abbr>.
|
||||
|
||||
## Automatic docs
|
||||
@@ -131,7 +131,7 @@ Inside of the function, you can access all the attributes of the model object di
|
||||
|
||||
## Request body + path parameters
|
||||
|
||||
You can declare path parameters and body requests at the same time.
|
||||
You can declare path parameters and request body at the same time.
|
||||
|
||||
**FastAPI** will recognize that the function parameters that match path parameters should be **taken from the path**, and that function parameters that are declared to be Pydantic models should be **taken from the request body**.
|
||||
|
||||
|
||||
@@ -55,10 +55,10 @@ The default parameters used by the `CORSMiddleware` implementation are restricti
|
||||
The following arguments are supported:
|
||||
|
||||
* `allow_origins` - A list of origins that should be permitted to make cross-origin requests. E.g. `['https://example.org', 'https://www.example.org']`. You can use `['*']` to allow any origin.
|
||||
* `allow_origin_regex` - A regex string to match against origins that should be permitted to make cross-origin requests. eg. `'https://.*\.example\.org'`.
|
||||
* `allow_origin_regex` - A regex string to match against origins that should be permitted to make cross-origin requests. e.g. `'https://.*\.example\.org'`.
|
||||
* `allow_methods` - A list of HTTP methods that should be allowed for cross-origin requests. Defaults to `['GET']`. You can use `['*']` to allow all standard methods.
|
||||
* `allow_headers` - A list of HTTP request headers that should be supported for cross-origin requests. Defaults to `[]`. You can use `['*']` to allow all headers. The `Accept`, `Accept-Language`, `Content-Language` and `Content-Type` headers are always allowed for CORS requests.
|
||||
* `allow_credentials` - Indicate that cookies should be supported for cross-origin requests. Defaults to `False`.
|
||||
* `allow_credentials` - Indicate that cookies should be supported for cross-origin requests. Defaults to `False`. Also, `allow_origins` cannot be set to `['*']` for credentials to be allowed, origins must be specified.
|
||||
* `expose_headers` - Indicate any response headers that should be made accessible to the browser. Defaults to `[]`.
|
||||
* `max_age` - Sets a maximum time in seconds for browsers to cache CORS responses. Defaults to `600`.
|
||||
|
||||
|
||||
@@ -27,6 +27,11 @@ These dependencies will be executed/solved the same way normal dependencies. But
|
||||
|
||||
It might also help avoid confusion for new developers that see an unused parameter in your code and could think it's unnecessary.
|
||||
|
||||
!!! info
|
||||
In this example we use invented custom headers `X-Key` and `X-Token`.
|
||||
|
||||
But in real cases, when implementing security, you would get more benefits from using the integrated [Security utilities (the next chapter)](../security/index.md){.internal-link target=_blank}.
|
||||
|
||||
## Dependencies errors and return values
|
||||
|
||||
You can use the same dependency *functions* you use normally.
|
||||
@@ -60,3 +65,7 @@ So, you can re-use a normal dependency (that returns a value) you already use so
|
||||
## Dependencies for a group of *path operations*
|
||||
|
||||
Later, when reading about how to structure bigger applications ([Bigger Applications - Multiple Files](../../tutorial/bigger-applications.md){.internal-link target=_blank}), possibly with multiple files, you will learn how to declare a single `dependencies` parameter for a group of *path operations*.
|
||||
|
||||
## Global Dependencies
|
||||
|
||||
Next we will see how to add dependencies to the whole `FastAPI` application, so that they apply to each *path operation*.
|
||||
|
||||
17
docs/en/docs/tutorial/dependencies/global-dependencies.md
Normal file
@@ -0,0 +1,17 @@
|
||||
# Global Dependencies
|
||||
|
||||
For some types of applications you might want to add dependencies to the whole application.
|
||||
|
||||
Similar to the way you can [add `dependencies` to the *path operation decorators*](dependencies-in-path-operation-decorators.md){.internal-link target=_blank}, you can add them to the `FastAPI` application.
|
||||
|
||||
In that case, they will be applied to all the *path operations* in the application:
|
||||
|
||||
```Python hl_lines="15"
|
||||
{!../../../docs_src/dependencies/tutorial012.py!}
|
||||
```
|
||||
|
||||
And all the ideas in the section about [adding `dependencies` to the *path operation decorators*](dependencies-in-path-operation-decorators.md){.internal-link target=_blank} still apply, but in this case, to all of the *path operations* in the app.
|
||||
|
||||
## Dependencies for groups of *path operations*
|
||||
|
||||
Later, when reading about how to structure bigger applications ([Bigger Applications - Multiple Files](../../tutorial/bigger-applications.md){.internal-link target=_blank}), possibly with multiple files, you will learn how to declare a single `dependencies` parameter for a group of *path operations*.
|
||||
@@ -39,7 +39,7 @@ This also means that if you are inside a utility function that you are calling i
|
||||
|
||||
The benefit of raising an exception over `return`ing a value will be more evident in the section about Dependencies and Security.
|
||||
|
||||
In this example, when the client request an item by an ID that doesn't exist, raise an exception with a status code of `404`:
|
||||
In this example, when the client requests an item by an ID that doesn't exist, raise an exception with a status code of `404`:
|
||||
|
||||
```Python hl_lines="11"
|
||||
{!../../../docs_src/handling_errors/tutorial001.py!}
|
||||
|
||||
@@ -64,7 +64,7 @@ $ pip install fastapi[all]
|
||||
Also install `uvicorn` to work as the server:
|
||||
|
||||
```
|
||||
pip install uvicorn
|
||||
pip install uvicorn[standard]
|
||||
```
|
||||
|
||||
And the same for each of the optional dependencies that you want to use.
|
||||
|
||||
@@ -106,7 +106,7 @@ And you can also declare numeric validations:
|
||||
* `le`: `l`ess than or `e`qual
|
||||
|
||||
!!! info
|
||||
`Query`, `Path` and others you will see later subclasses of a common `Param` class (that you don't need to use).
|
||||
`Query`, `Path`, and others you will see later are subclasses of a common `Param` class (that you don't need to use).
|
||||
|
||||
And all of them share the same all these same parameters of additional validation and metadata you have seen.
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@ But if you go to the browser at <a href="http://127.0.0.1:8000/items/foo" class=
|
||||
|
||||
because the path parameter `item_id` had a value of `"foo"`, which is not an `int`.
|
||||
|
||||
The same error would appear if you provided a `float` instead of an int, as in: <a href="http://127.0.0.1:8000/items/4.2" class="external-link" target="_blank">http://127.0.0.1:8000/items/4.2</a>
|
||||
The same error would appear if you provided a `float` instead of an `int`, as in: <a href="http://127.0.0.1:8000/items/4.2" class="external-link" target="_blank">http://127.0.0.1:8000/items/4.2</a>
|
||||
|
||||
!!! check
|
||||
So, with the same Python type declaration, **FastAPI** gives you data validation.
|
||||
|
||||
@@ -17,7 +17,7 @@ The query parameter `q` is of type `Optional[str]`, that means that it's of type
|
||||
|
||||
## Additional validation
|
||||
|
||||
We are going to enforce that even though `q` is optional, whenever it is provided, it **doesn't exceed a length of 50 characters**.
|
||||
We are going to enforce that even though `q` is optional, whenever it is provided, **its length doesn't exceed 50 characters**.
|
||||
|
||||
### Import `Query`
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ When you declare other function parameters that are not part of the path paramet
|
||||
|
||||
The query is the set of key-value pairs that go after the `?` in a URL, separated by `&` characters.
|
||||
|
||||
For example, in the url:
|
||||
For example, in the URL:
|
||||
|
||||
```
|
||||
http://127.0.0.1:8000/items/?skip=0&limit=10
|
||||
|
||||
@@ -39,7 +39,7 @@ If you declare the type of your *path operation function* parameter as `bytes`,
|
||||
|
||||
Have in mind that this means that the whole contents will be stored in memory. This will work well for small files.
|
||||
|
||||
But there are several cases in where you might benefit from using `UploadFile`.
|
||||
But there are several cases in which you might benefit from using `UploadFile`.
|
||||
|
||||
## `File` parameters with `UploadFile`
|
||||
|
||||
|
||||
@@ -1,58 +1,109 @@
|
||||
# Schema Extra - Example
|
||||
# Declare Request Example Data
|
||||
|
||||
You can define extra information to go in JSON Schema.
|
||||
You can declare examples of the data your app can receive.
|
||||
|
||||
A common use case is to add an `example` that will be shown in the docs.
|
||||
|
||||
There are several ways you can declare extra JSON Schema information.
|
||||
Here are several ways to do it.
|
||||
|
||||
## Pydantic `schema_extra`
|
||||
|
||||
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>:
|
||||
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="15-23"
|
||||
{!../../../docs_src/schema_extra_example/tutorial001.py!}
|
||||
```
|
||||
|
||||
That extra info will be added as-is to the output JSON Schema.
|
||||
That extra info will be added as-is to the output **JSON Schema** for that model, and it will be used in the API docs.
|
||||
|
||||
!!! tip
|
||||
You could use the same technique to extend the JSON Schema and add your own custom extra info.
|
||||
|
||||
For example you could use it to add metadata for a frontend user interface, etc.
|
||||
|
||||
## `Field` additional arguments
|
||||
|
||||
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`:
|
||||
When using `Field()` with Pydantic models, you can also declare extra info for the **JSON Schema** by passing any other arbitrary arguments to the function.
|
||||
|
||||
You can use this to add `example` for each field:
|
||||
|
||||
```Python hl_lines="4 10-13"
|
||||
{!../../../docs_src/schema_extra_example/tutorial002.py!}
|
||||
```
|
||||
|
||||
!!! warning
|
||||
Have in mind that those extra arguments passed won't add any validation, only annotation, for documentation purposes.
|
||||
Keep in mind that those extra arguments passed won't add any validation, only extra information, for documentation purposes.
|
||||
|
||||
## `Body` additional arguments
|
||||
## `example` and `examples` in OpenAPI
|
||||
|
||||
The same way you can pass extra info to `Field`, you can do the same with `Path`, `Query`, `Body`, etc.
|
||||
When using any of:
|
||||
|
||||
For example, you can pass an `example` for a body request to `Body`:
|
||||
* `Path()`
|
||||
* `Query()`
|
||||
* `Header()`
|
||||
* `Cookie()`
|
||||
* `Body()`
|
||||
* `Form()`
|
||||
* `File()`
|
||||
|
||||
you can also declare a data `example` or a group of `examples` with additional information that will be added to **OpenAPI**.
|
||||
|
||||
### `Body` with `example`
|
||||
|
||||
Here we pass an `example` of the data expected in `Body()`:
|
||||
|
||||
```Python hl_lines="21-26"
|
||||
{!../../../docs_src/schema_extra_example/tutorial003.py!}
|
||||
```
|
||||
|
||||
## Example in the docs UI
|
||||
### Example in the docs UI
|
||||
|
||||
With any of the methods above it would look like this in the `/docs`:
|
||||
|
||||
<img src="/img/tutorial/body-fields/image01.png">
|
||||
|
||||
### `Body` with multiple `examples`
|
||||
|
||||
Alternatively to the single `example`, you can pass `examples` using a `dict` with **multiple examples**, each with extra information that will be added to **OpenAPI** too.
|
||||
|
||||
The keys of the `dict` identify each example, and each value is another `dict`.
|
||||
|
||||
Each specific example `dict` in the `examples` can contain:
|
||||
|
||||
* `summary`: Short description for the example.
|
||||
* `description`: A long description that can contain Markdown text.
|
||||
* `value`: This is the actual example shown, e.g. a `dict`.
|
||||
* `externalValue`: alternative to `value`, a URL pointing to the example. Although this might not be supported by as many tools as `value`.
|
||||
|
||||
```Python hl_lines="22-48"
|
||||
{!../../../docs_src/schema_extra_example/tutorial004.py!}
|
||||
```
|
||||
|
||||
### Examples in the docs UI
|
||||
|
||||
With `examples` added to `Body()` the `/docs` would look like:
|
||||
|
||||
<img src="/img/tutorial/body-fields/image02.png">
|
||||
|
||||
## Technical Details
|
||||
|
||||
About `example` vs `examples`...
|
||||
!!! warning
|
||||
These are very technical details about the standards **JSON Schema** and **OpenAPI**.
|
||||
|
||||
JSON Schema defines a field <a href="https://json-schema.org/draft/2019-09/json-schema-validation.html#rfc.section.9.5" class="external-link" target="_blank">`examples`</a> in the most recent versions, but OpenAPI is based on an older version of JSON Schema that didn't have `examples`.
|
||||
If the ideas above already work for you, that might me enough, and you probably don't need these details, feel free to skip them.
|
||||
|
||||
So, OpenAPI defined its own <a href="https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.3.md#fixed-fields-20" class="external-link" target="_blank">`example`</a> for the same purpose (as `example`, not `examples`), and that's what is used by the docs UI (using Swagger UI).
|
||||
When you add an example inside of a Pydantic model, using `schema_extra` or `Field(example="something")` that example is added to the **JSON Schema** for that Pydantic model.
|
||||
|
||||
So, although `example` is not part of JSON Schema, it is part of OpenAPI, and that's what will be used by the docs UI.
|
||||
And that **JSON Schema** of the Pydantic model is included in the **OpenAPI** of your API, and then it's used in the docs UI.
|
||||
|
||||
## Other info
|
||||
**JSON Schema** doesn't really have a field `example` in the standards. Recent versions of JSON Schema define a field <a href="https://json-schema.org/draft/2019-09/json-schema-validation.html#rfc.section.9.5" class="external-link" target="_blank">`examples`</a>, but OpenAPI 3.0.3 is based on an older version of JSON Schema that didn't have `examples`.
|
||||
|
||||
The same way, you could add your own custom extra info that would be added to the JSON Schema for each model, for example to customize a frontend user interface, etc.
|
||||
So, OpenAPI 3.0.3 defined its own <a href="https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.3.md#fixed-fields-20" class="external-link" target="_blank">`example`</a> for the modified version of **JSON Schema** it uses, for the same purpose (but it's a single `example`, not `examples`), and that's what is used by the API docs UI (using Swagger UI).
|
||||
|
||||
So, although `example` is not part of JSON Schema, it is part of OpenAPI's custom version of JSON Schema, and that's what will be used by the docs UI.
|
||||
|
||||
But when you use `example` or `examples` with any of the other utilities (`Query()`, `Body()`, etc.) those examples are not added to the JSON Schema that describes that data (not even to OpenAPI's own version of JSON Schema), they are added directly to the *path operation* declaration in OpenAPI (outside the parts of OpenAPI that use JSON Schema).
|
||||
|
||||
For `Path()`, `Query()`, `Header()`, and `Cookie()`, the `example` or `examples` are added to the <a href="https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#parameter-object" class="external-link" target="_blank">OpenAPI definition, to the `Parameter Object` (in the specification)</a>.
|
||||
|
||||
And for `Body()`, `File()`, and `Form()`, the `example` or `examples` are equivalently added to the <a href="https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#mediaTypeObject" class="external-link" target="_blank">OpenAPI definition, to the `Request Body Object`, in the field `content`, on the `Media Type Object` (in the specification)</a>.
|
||||
|
||||
On the other hand, there's a newer version of OpenAPI: **3.1.0**, recently released. It is based on the latest JSON Schema and most of the modifications from OpenAPI's custom version of JSON Schema are removed, in exchange of the features from the recent versions of JSON Schema, so all these small differences are reduced. Nevertheless, Swagger UI currently doesn't support OpenAPI 3.1.0, so, for now, it's better to continue using the ideas above.
|
||||
|
||||
@@ -42,7 +42,7 @@ $ pip install python-jose[cryptography]
|
||||
|
||||
<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>.
|
||||
Here we are using the recommended one: <a href="https://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>.
|
||||
|
||||
@@ -235,7 +235,7 @@ Now let's check the file `sql_app/schemas.py`.
|
||||
To avoid confusion between the SQLAlchemy *models* and the Pydantic *models*, we will have the file `models.py` with the SQLAlchemy models, and the file `schemas.py` with the Pydantic models.
|
||||
|
||||
These Pydantic models define more or less a "schema" (a valid data shape).
|
||||
|
||||
|
||||
So this will help us avoiding confusion while using both.
|
||||
|
||||
### Create initial Pydantic *models* / schemas
|
||||
@@ -364,7 +364,7 @@ Create utility functions to:
|
||||
|
||||
* Read a single user by ID and by email.
|
||||
* Read multiple users.
|
||||
* Read a single item.
|
||||
* Read multiple items.
|
||||
|
||||
```Python hl_lines="1 3 6-7 10-11 14-15 27-28"
|
||||
{!../../../docs_src/sql_databases/sql_app/crud.py!}
|
||||
@@ -470,7 +470,7 @@ Our dependency will create a new SQLAlchemy `SessionLocal` that will be used in
|
||||
We put the creation of the `SessionLocal()` and handling of the requests in a `try` block.
|
||||
|
||||
And then we close it in the `finally` block.
|
||||
|
||||
|
||||
This way we make sure the database session is always closed after the request. Even if there was an exception while processing the request.
|
||||
|
||||
But you can't raise another exception from the exit code (after `yield`). See more in [Dependencies with `yield` and `HTTPException`](./dependencies/dependencies-with-yield.md#dependencies-with-yield-and-httpexception){.internal-link target=_blank}
|
||||
@@ -553,7 +553,7 @@ And as the code related to SQLAlchemy and the SQLAlchemy models lives in separat
|
||||
|
||||
The same way, you would be able to use the same SQLAlchemy models and utilities in other parts of your code that are not related to **FastAPI**.
|
||||
|
||||
For example, in a background task worker with <a href="http://www.celeryproject.org/" class="external-link" target="_blank">Celery</a>, <a href="https://python-rq.org/" class="external-link" target="_blank">RQ</a>, or <a href="https://arq-docs.helpmanual.io/" class="external-link" target="_blank">ARQ</a>.
|
||||
For example, in a background task worker with <a href="https://docs.celeryproject.org" class="external-link" target="_blank">Celery</a>, <a href="https://python-rq.org/" class="external-link" target="_blank">RQ</a>, or <a href="https://arq-docs.helpmanual.io/" class="external-link" target="_blank">ARQ</a>.
|
||||
|
||||
## Review all the files
|
||||
|
||||
@@ -648,7 +648,7 @@ The middleware we'll add (just a function) will create a new SQLAlchemy `Session
|
||||
We put the creation of the `SessionLocal()` and handling of the requests in a `try` block.
|
||||
|
||||
And then we close it in the `finally` block.
|
||||
|
||||
|
||||
This way we make sure the database session is always closed after the request. Even if there was an exception while processing the request.
|
||||
|
||||
### About `request.state`
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
Thanks to <a href="https://www.starlette.io/testclient/" class="external-link" target="_blank">Starlette</a>, testing **FastAPI** applications is easy and enjoyable.
|
||||
|
||||
It is based on <a href="http://docs.python-requests.org" class="external-link" target="_blank">Requests</a>, so it's very familiar and intuitive.
|
||||
It is based on <a href="https://requests.readthedocs.io" class="external-link" target="_blank">Requests</a>, so it's very familiar and intuitive.
|
||||
|
||||
With it, you can use <a href="https://docs.pytest.org/" class="external-link" target="_blank">pytest</a> directly with **FastAPI**.
|
||||
|
||||
@@ -97,12 +97,12 @@ E.g.:
|
||||
* To pass *headers*, use a `dict` in the `headers` parameter.
|
||||
* For *cookies*, a `dict` in the `cookies` parameter.
|
||||
|
||||
For more information about how to pass data to the backend (using `requests` or the `TestClient`) check the <a href="http://docs.python-requests.org" class="external-link" target="_blank">Requests documentation</a>.
|
||||
For more information about how to pass data to the backend (using `requests` or the `TestClient`) check the <a href="https://requests.readthedocs.io" class="external-link" target="_blank">Requests documentation</a>.
|
||||
|
||||
!!! info
|
||||
Note that the `TestClient` receives data that can be converted to JSON, not Pydantic models.
|
||||
|
||||
If you have a Pydantic model in your test and you want to send its data to the application during testing, you can use the `jsonable_encoder` descibed in [JSON Compatible Encoder](encoder.md){.internal-link target=_blank}.
|
||||
If you have a Pydantic model in your test and you want to send its data to the application during testing, you can use the `jsonable_encoder` described in [JSON Compatible Encoder](encoder.md){.internal-link target=_blank}.
|
||||
|
||||
## Run it
|
||||
|
||||
|
||||
@@ -3,10 +3,23 @@ site_description: FastAPI framework, high performance, easy to learn, fast to co
|
||||
site_url: https://fastapi.tiangolo.com/
|
||||
theme:
|
||||
name: material
|
||||
custom_dir: overrides
|
||||
palette:
|
||||
scheme: preference
|
||||
- scheme: default
|
||||
primary: teal
|
||||
accent: amber
|
||||
toggle:
|
||||
icon: material/lightbulb-outline
|
||||
name: Switch to light mode
|
||||
- scheme: slate
|
||||
primary: teal
|
||||
accent: amber
|
||||
toggle:
|
||||
icon: material/lightbulb
|
||||
name: Switch to dark mode
|
||||
features:
|
||||
- search.suggest
|
||||
- search.highlight
|
||||
icon:
|
||||
repo: fontawesome/brands/github-alt
|
||||
logo: img/icon-white.svg
|
||||
@@ -28,14 +41,19 @@ nav:
|
||||
- en: /
|
||||
- es: /es/
|
||||
- fr: /fr/
|
||||
- ja: /ja/
|
||||
- id: /id/
|
||||
- it: /it/
|
||||
- ja: /ja/
|
||||
- ko: /ko/
|
||||
- pl: /pl/
|
||||
- pt: /pt/
|
||||
- ru: /ru/
|
||||
- sq: /sq/
|
||||
- tr: /tr/
|
||||
- uk: /uk/
|
||||
- zh: /zh/
|
||||
- features.md
|
||||
- fastapi-people.md
|
||||
- python-types.md
|
||||
- Tutorial - User Guide:
|
||||
- tutorial/index.md
|
||||
@@ -67,6 +85,7 @@ nav:
|
||||
- tutorial/dependencies/classes-as-dependencies.md
|
||||
- tutorial/dependencies/sub-dependencies.md
|
||||
- tutorial/dependencies/dependencies-in-path-operation-decorators.md
|
||||
- tutorial/dependencies/global-dependencies.md
|
||||
- tutorial/dependencies/dependencies-with-yield.md
|
||||
- Security:
|
||||
- tutorial/security/index.md
|
||||
@@ -121,7 +140,13 @@ nav:
|
||||
- advanced/openapi-callbacks.md
|
||||
- advanced/wsgi.md
|
||||
- async.md
|
||||
- deployment.md
|
||||
- Deployment:
|
||||
- deployment/index.md
|
||||
- deployment/versions.md
|
||||
- deployment/https.md
|
||||
- deployment/deta.md
|
||||
- deployment/docker.md
|
||||
- deployment/manually.md
|
||||
- project-generation.md
|
||||
- alternatives.md
|
||||
- history-design-future.md
|
||||
@@ -149,7 +174,9 @@ markdown_extensions:
|
||||
extra:
|
||||
social:
|
||||
- icon: fontawesome/brands/github-alt
|
||||
link: https://github.com/tiangolo/typer
|
||||
link: https://github.com/tiangolo/fastapi
|
||||
- icon: fontawesome/brands/discord
|
||||
link: https://discord.gg/VQjSZaeJmf
|
||||
- icon: fontawesome/brands/twitter
|
||||
link: https://twitter.com/tiangolo
|
||||
- icon: fontawesome/brands/linkedin
|
||||
@@ -160,6 +187,35 @@ extra:
|
||||
link: https://medium.com/@tiangolo
|
||||
- icon: fontawesome/solid/globe
|
||||
link: https://tiangolo.com
|
||||
alternate:
|
||||
- link: /
|
||||
name: en - English
|
||||
- link: /es/
|
||||
name: es - español
|
||||
- link: /fr/
|
||||
name: fr - français
|
||||
- link: /id/
|
||||
name: id
|
||||
- link: /it/
|
||||
name: it - italiano
|
||||
- link: /ja/
|
||||
name: ja - 日本語
|
||||
- link: /ko/
|
||||
name: ko - 한국어
|
||||
- link: /pl/
|
||||
name: pl
|
||||
- link: /pt/
|
||||
name: pt - português
|
||||
- link: /ru/
|
||||
name: ru - русский язык
|
||||
- link: /sq/
|
||||
name: sq - shqip
|
||||
- link: /tr/
|
||||
name: tr - Türkçe
|
||||
- link: /uk/
|
||||
name: uk - українська мова
|
||||
- link: /zh/
|
||||
name: zh - 汉语
|
||||
extra_css:
|
||||
- css/termynal.css
|
||||
- css/custom.css
|
||||
@@ -167,5 +223,3 @@ extra_javascript:
|
||||
- https://unpkg.com/mermaid@8.4.6/dist/mermaid.min.js
|
||||
- js/termynal.js
|
||||
- js/custom.js
|
||||
- js/chat.js
|
||||
- https://sidecar.gitter.im/dist/sidecar.v1.js
|
||||
|
||||
38
docs/en/overrides/main.html
Normal file
@@ -0,0 +1,38 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block announce %}
|
||||
<div class="announce-wrapper">
|
||||
<div id="announce-left">
|
||||
<div class="item">
|
||||
<a class="announce-link" href="https://fastapi.tiangolo.com/newsletter/">
|
||||
<span class="twemoji">
|
||||
{% include ".icons/material/email.svg" %}
|
||||
</span> Subscribe to the <strong>FastAPI and friends</strong> newsletter 🎉
|
||||
</a>
|
||||
</div>
|
||||
<div class="item">
|
||||
<iframe style="display: inline-block; vertical-align: middle; border: none; margin-right: 0.5rem;" src="https://github.com/sponsors/tiangolo/button" title="Sponsor tiangolo" height="35" width="116" style="border: 0;"></iframe> <a class="announce-link" target="_blank" href="https://github.com/sponsors/tiangolo">You can now sponsor <strong>FastAPI</strong> 🍰</a>
|
||||
</div>
|
||||
</div>
|
||||
<div id="announce-right" style="position: relative;">
|
||||
<div class="item">
|
||||
<a title="The launchpad for all your (team's) ideas" style="display: block; position: relative;" href="https://www.deta.sh/?ref=fastapi" target="_blank">
|
||||
<span class="sponsor-badge">sponsor</span>
|
||||
<img class="sponsor-image" src="/img/sponsors/deta-banner.svg" />
|
||||
</a>
|
||||
</div>
|
||||
<div class="item">
|
||||
<a title="Get three courses at 10% off their current prices! Plus, we'll be donating 10% of all profits from sales of this bundle to the FastAPI team." style="display: block; position: relative;" href="https://testdriven.io/talkpython/" target="_blank">
|
||||
<span class="sponsor-badge">sponsor</span>
|
||||
<img class="sponsor-image" src="/img/sponsors/fastapi-course-bundle-banner.svg" />
|
||||
</a>
|
||||
</div>
|
||||
<div class="item">
|
||||
<a title="Jina: build neural search-as-a-service for any kind of data in just minutes." style="display: block; position: relative;" href="https://bit.ly/2QSouzH" target="_blank">
|
||||
<span class="sponsor-badge">sponsor</span>
|
||||
<img class="sponsor-image" src="/img/sponsors/jina-banner.svg" />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -261,7 +261,7 @@ Pero también puedes aprovechar los beneficios del paralelismo y el multiprocesa
|
||||
|
||||
Eso, más el simple hecho de que Python es el lenguaje principal para **Data Science**, Machine Learning y especialmente Deep Learning, hacen de FastAPI una muy buena combinación para las API y aplicaciones web de Data Science / Machine Learning (entre muchas otras).
|
||||
|
||||
Para ver cómo lograr este paralelismo en producción, consulta la sección sobre [Despliegue](deployment.md){.internal-link target=_blank}.
|
||||
Para ver cómo lograr este paralelismo en producción, consulta la sección sobre [Despliegue](deployment/index.md){.internal-link target=_blank}.
|
||||
|
||||
## `async` y `await`
|
||||
|
||||
@@ -334,7 +334,7 @@ Esta misma sintaxis (o casi idéntica) también se incluyó recientemente en las
|
||||
|
||||
Pero antes de eso, manejar código asíncrono era bastante más complejo y difícil.
|
||||
|
||||
En versiones anteriores de Python, podrías haber utilizado <abbr title="En español: hilos.">threads</abbr> o <a href="http://www.gevent.org/" class="external-link" target="_blank">Gevent</a>. Pero el código es mucho más complejo de entender, depurar y desarrollar.
|
||||
En versiones anteriores de Python, podrías haber utilizado <abbr title="En español: hilos.">threads</abbr> o <a href="https://www.gevent.org/" class="external-link" target="_blank">Gevent</a>. Pero el código es mucho más complejo de entender, depurar y desarrollar.
|
||||
|
||||
En versiones anteriores de NodeJS / Browser JavaScript, habrías utilizado "callbacks". Lo que conduce a <a href="http://callbackhell.com/" class="external-link" target="_blank">callback hell</a>.
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
### Basado en estándares abiertos
|
||||
|
||||
* <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank"><strong>OpenAPI</strong></a> para la creación de APIs, incluyendo declaraciones de <abbr title="en español: ruta. En inglés también conocido cómo: endpoints, routes">path</abbr> <abbr title="también conocido como HTTP methods, cómo POST, GET, PUT, DELETE">operations</abbr>, parámetros, <abbr title="cuerpo del mensaje HTTP">body</abbr> requests, seguridad, etc.
|
||||
* Documentación automática del modelo de datos con <a href="http://json-schema.org/" class="external-link" target="_blank"><strong>JSON Schema</strong></a> (dado que OpenAPI mismo está basado en JSON Schema).
|
||||
* Documentación automática del modelo de datos con <a href="https://json-schema.org/" class="external-link" target="_blank"><strong>JSON Schema</strong></a> (dado que OpenAPI mismo está basado en JSON Schema).
|
||||
* Diseñado alrededor de estos estándares después de un estudio meticuloso. En vez de ser una capa añadida a último momento.
|
||||
* Esto también permite la **generación automática de código de cliente** para muchos lenguajes.
|
||||
|
||||
|
||||
@@ -14,9 +14,6 @@
|
||||
<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>
|
||||
|
||||
---
|
||||
@@ -38,10 +35,24 @@ Sus características principales son:
|
||||
* **Fácil**: Está diseñado para ser fácil de usar y aprender. Gastando menos tiempo leyendo documentación.
|
||||
* **Corto**: Minimiza la duplicación de código. Múltiples funcionalidades con cada declaración de parámetros. Menos errores.
|
||||
* **Robusto**: Crea código listo para producción con documentación automática interactiva.
|
||||
* **Basado en estándares**: Basado y totalmente compatible con los estándares abiertos para APIs: <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank">OpenAPI</a> (conocido previamente como Swagger) y <a href="http://json-schema.org/" class="external-link" target="_blank">JSON Schema</a>.
|
||||
* **Basado en estándares**: Basado y totalmente compatible con los estándares abiertos para APIs: <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank">OpenAPI</a> (conocido previamente como Swagger) y <a href="https://json-schema.org/" class="external-link" target="_blank">JSON Schema</a>.
|
||||
|
||||
<small>* Esta estimación está basada en pruebas con un equipo de desarrollo interno contruyendo aplicaciones listas para producción.</small>
|
||||
|
||||
## Gold Sponsors
|
||||
|
||||
<!-- sponsors -->
|
||||
|
||||
{% if sponsors %}
|
||||
{% for sponsor in sponsors.gold -%}
|
||||
<a href="{{ sponsor.url }}" target="_blank" title="{{ sponsor.title }}"><img src="{{ sponsor.img }}"></a>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
<!-- /sponsors -->
|
||||
|
||||
<a href="https://fastapi.tiangolo.com/fastapi-people/#sponsors" class="external-link" target="_blank">Otros sponsors</a>
|
||||
|
||||
## Opiniones
|
||||
|
||||
"_[...] 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._"
|
||||
@@ -70,7 +81,7 @@ Sus características principales son:
|
||||
|
||||
"_Honestly, what you've built looks super solid and polished. In many ways, it's what I wanted **Hug** to be - it's really inspiring to see someone build that._"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Timothy Crosley - <strong><a href="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>
|
||||
<div style="text-align: right; margin-right: 10%;">Timothy Crosley - <strong><a href="https://www.hug.rest/" target="_blank">Hug</a> creator</strong> <a href="https://news.ycombinator.com/item?id=19455465" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
@@ -111,12 +122,12 @@ $ pip install fastapi
|
||||
|
||||
</div>
|
||||
|
||||
También vas a necesitar un servidor ASGI para producción cómo <a href="http://www.uvicorn.org" class="external-link" target="_blank">Uvicorn</a> o <a href="https://gitlab.com/pgjones/hypercorn" class="external-link" target="_blank">Hypercorn</a>.
|
||||
También vas a necesitar un servidor ASGI para producción cómo <a href="https://www.uvicorn.org" class="external-link" target="_blank">Uvicorn</a> o <a href="https://gitlab.com/pgjones/hypercorn" class="external-link" target="_blank">Hypercorn</a>.
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ pip install uvicorn
|
||||
$ pip install uvicorn[standard]
|
||||
|
||||
---> 100%
|
||||
```
|
||||
@@ -424,9 +435,9 @@ Usadas por Pydantic:
|
||||
|
||||
Usados por Starlette:
|
||||
|
||||
* <a href="http://docs.python-requests.org" target="_blank"><code>requests</code></a> - Requerido si quieres usar el `TestClient`.
|
||||
* <a href="https://requests.readthedocs.io" target="_blank"><code>requests</code></a> - Requerido si quieres usar el `TestClient`.
|
||||
* <a href="https://github.com/Tinche/aiofiles" target="_blank"><code>aiofiles</code></a> - Requerido si quieres usar `FileResponse` o `StaticFiles`.
|
||||
* <a href="http://jinja.pocoo.org" target="_blank"><code>jinja2</code></a> - Requerido si quieres usar la configuración por defecto de templates.
|
||||
* <a href="https://jinja.palletsprojects.com" target="_blank"><code>jinja2</code></a> - Requerido si quieres usar la configuración por defecto de templates.
|
||||
* <a href="https://andrew-d.github.io/python-multipart/" target="_blank"><code>python-multipart</code></a> - Requerido si quieres dar soporte a <abbr title="convertir el string que viene de un HTTP request a datos de Python">"parsing"</abbr> de formularios, con `request.form()`.
|
||||
* <a href="https://pythonhosted.org/itsdangerous/" target="_blank"><code>itsdangerous</code></a> - Requerido para dar soporte a `SessionMiddleware`.
|
||||
* <a href="https://pyyaml.org/wiki/PyYAMLDocumentation" target="_blank"><code>pyyaml</code></a> - Requerido para dar soporte al `SchemaGenerator` de Starlette (probablemente no lo necesites con FastAPI).
|
||||
@@ -435,7 +446,7 @@ Usados por Starlette:
|
||||
|
||||
Usado por FastAPI / Starlette:
|
||||
|
||||
* <a href="http://www.uvicorn.org" target="_blank"><code>uvicorn</code></a> - para el servidor que carga y sirve tu aplicación.
|
||||
* <a href="https://www.uvicorn.org" target="_blank"><code>uvicorn</code></a> - para el servidor que carga y sirve tu aplicación.
|
||||
* <a href="https://github.com/ijl/orjson" target="_blank"><code>orjson</code></a> - Requerido si quieres usar `ORJSONResponse`.
|
||||
|
||||
Puedes instalarlos con `pip install fastapi[all]`.
|
||||
|
||||
333
docs/es/docs/tutorial/first-steps.md
Normal file
@@ -0,0 +1,333 @@
|
||||
# Primeros pasos
|
||||
|
||||
Un archivo muy simple de FastAPI podría verse así:
|
||||
|
||||
```Python
|
||||
{!../../../docs_src/first_steps/tutorial001.py!}
|
||||
```
|
||||
|
||||
Copia eso a un archivo `main.py`.
|
||||
|
||||
Corre el servidor en vivo:
|
||||
|
||||
<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)
|
||||
<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.
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
!!! note "Nota"
|
||||
El comando `uvicorn main:app` se refiere a:
|
||||
|
||||
* `main`: el archivo `main.py` (el "módulo" de Python).
|
||||
* `app`: el objeto creado dentro de `main.py` con la línea `app = FastAPI()`.
|
||||
* `--reload`: hace que el servidor se reinicie cada vez que cambia el código. Úsalo únicamente para desarrollo.
|
||||
|
||||
En el output, hay una línea que dice más o menos:
|
||||
|
||||
```hl_lines="4"
|
||||
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
|
||||
```
|
||||
|
||||
Esa línea muestra la URL dónde se está sirviendo tu app en tu maquina local.
|
||||
|
||||
### Revísalo
|
||||
|
||||
Abre tu navegador en <a href="http://127.0.0.1:8000" class="external-link" target="_blank">http://127.0.0.1:8000</a>.
|
||||
|
||||
Verás la respuesta en JSON:
|
||||
|
||||
```JSON
|
||||
{"message": "Hello World"}
|
||||
```
|
||||
|
||||
### Documentación interactiva de la API
|
||||
|
||||
Ahora dirígete a <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
|
||||
|
||||
Ahí verás la documentación automática e interactiva de la API (proveída por <a href="https://github.com/swagger-api/swagger-ui" class="external-link" target="_blank">Swagger UI</a>):
|
||||
|
||||

|
||||
|
||||
### Documentación alternativa de la API
|
||||
|
||||
Ahora, dirígete a <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a>.
|
||||
|
||||
Aquí verás la documentación automática alternativa (proveída por <a href="https://github.com/Rebilly/ReDoc" class="external-link" target="_blank">ReDoc</a>):
|
||||
|
||||

|
||||
|
||||
### OpenAPI
|
||||
|
||||
**FastAPI** genera un "schema" con toda tu API usando el estándar para definir APIs, **OpenAPI**.
|
||||
|
||||
#### "Schema"
|
||||
|
||||
Un "schema" es una definición o descripción de algo. No es el código que la implementa, sino solo una descripción abstracta.
|
||||
|
||||
#### "Schema" de la API
|
||||
|
||||
En este caso, <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank">OpenAPI</a> es una especificación que dicta como se debe definir el schema de tu API.
|
||||
|
||||
La definición del schema incluye los paths de tu API, los parámetros que podría recibir, etc.
|
||||
|
||||
#### "Schema" de datos
|
||||
|
||||
El concepto "schema" también se puede referir a la forma de algunos datos, como un contenido en formato JSON.
|
||||
|
||||
En ese caso haría referencia a los atributos del JSON, los tipos de datos que tiene, etc.
|
||||
|
||||
#### OpenAPI y JSON Schema
|
||||
|
||||
OpenAPI define un schema de API para tu API. Ese schema incluye definiciones (o "schemas") de los datos enviados y recibidos por tu API usando **JSON Schema**, el estándar para los schemas de datos en JSON.
|
||||
|
||||
#### Revisa el `openapi.json`
|
||||
|
||||
Si sientes curiosidad por saber cómo se ve el schema de OpenAPI en bruto, FastAPI genera automáticamente un (schema) JSON con la descripción de todo tu API.
|
||||
|
||||
Lo puedes ver directamente en: <a href="http://127.0.0.1:8000/openapi.json" class="external-link" target="_blank">http://127.0.0.1:8000/openapi.json</a>.
|
||||
|
||||
Esto te mostrará un JSON que comienza con algo como:
|
||||
|
||||
```JSON
|
||||
{
|
||||
"openapi": "3.0.2",
|
||||
"info": {
|
||||
"title": "FastAPI",
|
||||
"version": "0.1.0"
|
||||
},
|
||||
"paths": {
|
||||
"/items/": {
|
||||
"get": {
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {
|
||||
"application/json": {
|
||||
|
||||
|
||||
|
||||
...
|
||||
```
|
||||
|
||||
#### ¿Para qué se usa OpenAPI?
|
||||
|
||||
El schema de OpenAPI es lo que alimenta a los dos sistemas de documentación interactiva incluidos.
|
||||
|
||||
También hay docenas de alternativas, todas basadas en OpenAPI. Podrías añadir fácilmente cualquiera de esas alternativas a tu aplicación construida con **FastAPI**.
|
||||
|
||||
También podrías usarlo para generar código automáticamente, para los clientes que se comunican con tu API. Por ejemplo, frontend, móvil o aplicaciones de IoT.
|
||||
|
||||
## Repaso, paso a paso
|
||||
|
||||
### Paso 1: importa `FastAPI`
|
||||
|
||||
```Python hl_lines="1"
|
||||
{!../../../docs_src/first_steps/tutorial001.py!}
|
||||
```
|
||||
|
||||
`FastAPI` es una clase de Python que provee toda la funcionalidad para tu API.
|
||||
|
||||
!!! note "Detalles Técnicos"
|
||||
`FastAPI` es una clase que hereda directamente de `Starlette`.
|
||||
|
||||
También puedes usar toda la funcionalidad de <a href="https://www.starlette.io/" class="external-link" target="_blank">Starlette</a>.
|
||||
|
||||
### Paso 2: crea un "instance" de `FastAPI`
|
||||
|
||||
```Python hl_lines="3"
|
||||
{!../../../docs_src/first_steps/tutorial001.py!}
|
||||
```
|
||||
|
||||
Aquí la variable `app` será un instance de la clase `FastAPI`.
|
||||
|
||||
Este será el punto de interacción principal para crear todo tu API.
|
||||
|
||||
Esta `app` es la misma a la que nos referimos cuando usamos el comando de `uvicorn`:
|
||||
|
||||
<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>
|
||||
|
||||
Si creas un app como:
|
||||
|
||||
```Python hl_lines="3"
|
||||
{!../../../docs_src/first_steps/tutorial002.py!}
|
||||
```
|
||||
|
||||
y lo guardas en un archivo `main.py`, entonces ejecutarías `uvicorn` así:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ uvicorn main:my_awesome_api --reload
|
||||
|
||||
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
### Paso 3: crea un *operación de path*
|
||||
|
||||
#### Path
|
||||
|
||||
"Path" aquí se refiere a la última parte de una URL comenzando desde el primer `/`.
|
||||
|
||||
Entonces, en una URL como:
|
||||
|
||||
```
|
||||
https://example.com/items/foo
|
||||
```
|
||||
|
||||
...el path sería:
|
||||
|
||||
```
|
||||
/items/foo
|
||||
```
|
||||
|
||||
!!! info "Información"
|
||||
Un "path" también se conoce habitualmente como "endpoint", "route" o "ruta".
|
||||
|
||||
Cuando construyes una API, el "path" es la manera principal de separar los <abbr title="en inglés: separation of concerns">"intereses"</abbr> y los "recursos".
|
||||
|
||||
#### Operación
|
||||
|
||||
"Operación" aquí se refiere a uno de los "métodos" de HTTP.
|
||||
|
||||
Uno como:
|
||||
|
||||
* `POST`
|
||||
* `GET`
|
||||
* `PUT`
|
||||
* `DELETE`
|
||||
|
||||
...y los más exóticos:
|
||||
|
||||
* `OPTIONS`
|
||||
* `HEAD`
|
||||
* `PATCH`
|
||||
* `TRACE`
|
||||
|
||||
En el protocolo de HTTP, te puedes comunicar con cada path usando uno (o más) de estos "métodos".
|
||||
|
||||
---
|
||||
|
||||
Cuando construyes APIs, normalmente usas uno de estos métodos específicos de HTTP para realizar una acción específica.
|
||||
|
||||
Normalmente usas:
|
||||
|
||||
* `POST`: para crear datos.
|
||||
* `GET`: para leer datos.
|
||||
* `PUT`: para actualizar datos.
|
||||
* `DELETE`: para borrar datos.
|
||||
|
||||
Así que en OpenAPI, cada uno de estos métodos de HTTP es referido como una "operación".
|
||||
|
||||
Nosotros también los llamaremos "**operación**".
|
||||
|
||||
#### Define un *decorador de operaciones de path*
|
||||
|
||||
```Python hl_lines="6"
|
||||
{!../../../docs_src/first_steps/tutorial001.py!}
|
||||
```
|
||||
|
||||
El `@app.get("/")` le dice a **FastAPI** que la función que tiene justo debajo está a cargo de manejar los requests que van a:
|
||||
|
||||
* el path `/`
|
||||
* usando una <abbr title="an HTTP GET method">operación <code>get</code></abbr>
|
||||
|
||||
!!! info "Información sobre `@decorator`"
|
||||
Esa sintaxis `@algo` se llama un "decorador" en Python.
|
||||
|
||||
Lo pones encima de una función. Es como un lindo sombrero decorado (creo que de ahí salió el concepto).
|
||||
|
||||
Un "decorador" toma la función que tiene debajo y hace algo con ella.
|
||||
|
||||
En nuestro caso, este decorador le dice a **FastAPI** que la función que está debajo corresponde al **path** `/` con una **operación** `get`.
|
||||
|
||||
Es el "**decorador de operaciones de path**".
|
||||
|
||||
También puedes usar las otras operaciones:
|
||||
|
||||
* `@app.post()`
|
||||
* `@app.put()`
|
||||
* `@app.delete()`
|
||||
|
||||
y las más exóticas:
|
||||
|
||||
* `@app.options()`
|
||||
* `@app.head()`
|
||||
* `@app.patch()`
|
||||
* `@app.trace()`
|
||||
|
||||
!!! tip "Consejo"
|
||||
Tienes la libertad de usar cada operación (método de HTTP) como quieras.
|
||||
|
||||
**FastAPI** no impone ningún significado específico.
|
||||
|
||||
La información que está presentada aquí es una guía, no un requerimiento.
|
||||
|
||||
Por ejemplo, cuando usas GraphQL normalmente realizas todas las acciones usando únicamente operaciones `POST`.
|
||||
|
||||
### Paso 4: define la **función de la operación de path**
|
||||
|
||||
Esta es nuestra "**función de la operación de path**":
|
||||
|
||||
* **path**: es `/`.
|
||||
* **operación**: es `get`.
|
||||
* **función**: es la función debajo del "decorador" (debajo de `@app.get("/")`).
|
||||
|
||||
```Python hl_lines="7"
|
||||
{!../../../docs_src/first_steps/tutorial001.py!}
|
||||
```
|
||||
|
||||
Esto es una función de Python.
|
||||
|
||||
Esta función será llamada por **FastAPI** cada vez que reciba un request en la URL "`/`" usando una operación `GET`.
|
||||
|
||||
En este caso es una función `async`.
|
||||
|
||||
---
|
||||
|
||||
También podrías definirla como una función normal, en vez de `async def`:
|
||||
|
||||
```Python hl_lines="7"
|
||||
{!../../../docs_src/first_steps/tutorial003.py!}
|
||||
```
|
||||
|
||||
!!! note "Nota"
|
||||
Si no sabes la diferencia, revisa el [Async: *"¿Tienes prisa?"*](../async.md#in-a-hurry){.internal-link target=_blank}.
|
||||
|
||||
### Paso 5: devuelve el contenido
|
||||
|
||||
```Python hl_lines="8"
|
||||
{!../../../docs_src/first_steps/tutorial001.py!}
|
||||
```
|
||||
|
||||
Puedes devolver `dict`, `list`, valores singulares como un `str`, `int`, etc.
|
||||
|
||||
También puedes devolver modelos de Pydantic (ya verás más sobre esto más adelante).
|
||||
|
||||
Hay muchos objetos y modelos que pueden ser convertidos automáticamente a JSON (incluyendo ORMs, etc.). Intenta usar tus favoritos, es muy probable que ya tengan soporte.
|
||||
|
||||
## Repaso
|
||||
|
||||
* Importa `FastAPI`.
|
||||
* Crea un instance de `app`.
|
||||
* Escribe un **decorador de operación de path** (como `@app.get("/")`).
|
||||
* Escribe una **función de la operación de path** (como `def root(): ...` arriba).
|
||||
* Corre el servidor de desarrollo (como `uvicorn main:app --reload`).
|
||||
@@ -64,7 +64,7 @@ $ pip install fastapi[all]
|
||||
También debes instalar `uvicorn` para que funcione como tu servidor:
|
||||
|
||||
```
|
||||
pip install uvicorn
|
||||
pip install uvicorn[standard]
|
||||
```
|
||||
|
||||
Y lo mismo para cada una de las dependencias opcionales que quieras utilizar.
|
||||
@@ -75,6 +75,6 @@ También hay una **Guía Avanzada de Usuario** que puedes leer luego de este **T
|
||||
|
||||
La **Guía Avanzada de Usuario**, se basa en este tutorial, utiliza los mismos conceptos y enseña algunas características adicionales.
|
||||
|
||||
Pero primero deberías leer el **Tutorial - Guía de Gsuario** (lo que estas leyendo ahora mismo).
|
||||
Pero primero deberías leer el **Tutorial - Guía de Usuario** (lo que estas leyendo ahora mismo).
|
||||
|
||||
La guía esa diseñada para que puedas crear una aplicación completa con solo el **Tutorial - Guía de Usuario**, y luego extenderlo de diferentes maneras, según tus necesidades, utilizando algunas de las ideas adicionales de la **Guía Avanzada de Usuario**.
|
||||
|
||||
244
docs/es/docs/tutorial/path-params.md
Normal file
@@ -0,0 +1,244 @@
|
||||
# Parámetros de path
|
||||
|
||||
Puedes declarar los "parámetros" o "variables" con la misma sintaxis que usan los format strings de Python:
|
||||
|
||||
```Python hl_lines="6-7"
|
||||
{!../../../docs_src/path_params/tutorial001.py!}
|
||||
```
|
||||
|
||||
El valor del parámetro de path `item_id` será pasado a tu función como el argumento `item_id`.
|
||||
|
||||
Entonces, si corres este ejemplo y vas a <a href="http://127.0.0.1:8000/items/foo" class="external-link" target="_blank">http://127.0.0.1:8000/items/foo</a>, verás una respuesta de:
|
||||
|
||||
```JSON
|
||||
{"item_id":"foo"}
|
||||
```
|
||||
|
||||
## Parámetros de path con tipos
|
||||
|
||||
Puedes declarar el tipo de un parámetro de path en la función usando las anotaciones de tipos estándar de Python:
|
||||
|
||||
```Python hl_lines="7"
|
||||
{!../../../docs_src/path_params/tutorial002.py!}
|
||||
```
|
||||
|
||||
En este caso, `item_id` es declarado como un `int`.
|
||||
|
||||
!!! check "Revisa"
|
||||
Esto te dará soporte en el editor dentro de tu función, con chequeos de errores, autocompletado, etc.
|
||||
|
||||
## <abbr title="también conocido en inglés como: serialization, parsing, marshalling">Conversión</abbr> de datos
|
||||
|
||||
Si corres este ejemplo y abres tu navegador en <a href="http://127.0.0.1:8000/items/3" class="external-link" target="_blank">http://127.0.0.1:8000/items/3</a> verás una respuesta de:
|
||||
|
||||
```JSON
|
||||
{"item_id":3}
|
||||
```
|
||||
|
||||
!!! check "Revisa"
|
||||
Observa que el valor que recibió (y devolvió) tu función es `3`, como un Python `int`, y no un string `"3"`.
|
||||
|
||||
Entonces, con esa declaración de tipos **FastAPI** te da <abbr title="convertir el string que viene de un HTTP request a datos de Python">"parsing"</abbr> automático del request.
|
||||
|
||||
## Validación de datos
|
||||
|
||||
Pero si abres tu navegador en <a href="http://127.0.0.1:8000/items/foo" class="external-link" target="_blank">http://127.0.0.1:8000/items/foo</a> verás este lindo error de HTTP:
|
||||
|
||||
```JSON
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"loc": [
|
||||
"path",
|
||||
"item_id"
|
||||
],
|
||||
"msg": "value is not a valid integer",
|
||||
"type": "type_error.integer"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
debido a que el parámetro de path `item_id` tenía el valor `"foo"`, que no es un `int`.
|
||||
|
||||
El mismo error aparecería si pasaras un `float` en vez de un `int` como en: <a href="http://127.0.0.1:8000/items/4.2" class="external-link" target="_blank">http://127.0.0.1:8000/items/4.2</a>
|
||||
|
||||
!!! check "Revisa"
|
||||
Así, con la misma declaración de tipo de Python, **FastAPI** te da validación de datos.
|
||||
|
||||
Observa que el error también muestra claramente el punto exacto en el que no pasó la validación.
|
||||
|
||||
Esto es increíblemente útil cuando estás desarrollando y debugging código que interactúa con tu API.
|
||||
|
||||
## Documentación
|
||||
|
||||
Cuando abras tu navegador en <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a> verás la documentación automática e interactiva del API como:
|
||||
|
||||
<img src="/img/tutorial/path-params/image01.png">
|
||||
|
||||
!!! check "Revisa"
|
||||
Nuevamente, con la misma declaración de tipo de Python, **FastAPI** te da documentación automática e interactiva (integrándose con Swagger UI)
|
||||
|
||||
Observa que el parámetro de path está declarado como un integer.
|
||||
|
||||
## Beneficios basados en estándares, documentación alternativa
|
||||
|
||||
Debido a que el schema generado es del estándar <a href="https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md" class="external-link" target="_blank">OpenAPI</a> hay muchas herramientas compatibles.
|
||||
|
||||
Es por esto que **FastAPI** mismo provee una documentación alternativa de la API (usando ReDoc), a la que puedes acceder en <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">
|
||||
|
||||
De la misma manera hay muchas herramientas compatibles. Incluyendo herramientas de generación de código para muchos lenguajes.
|
||||
|
||||
## Pydantic
|
||||
|
||||
Toda la validación de datos es realizada tras bastidores por <a href="https://pydantic-docs.helpmanual.io/" class="external-link" target="_blank">Pydantic</a>, así que obtienes todos sus beneficios. Así sabes que estás en buenas manos.
|
||||
|
||||
Puedes usar las mismas declaraciones de tipos con `str`, `float`, `bool` y otros tipos de datos más complejos.
|
||||
|
||||
Exploraremos varios de estos tipos en los próximos capítulos del tutorial.
|
||||
|
||||
## El orden importa
|
||||
|
||||
Cuando creas *operaciones de path* puedes encontrarte con situaciones en las que tengas un path fijo.
|
||||
|
||||
Digamos algo como `/users/me` que sea para obtener datos del usuario actual.
|
||||
|
||||
... y luego puedes tener el path `/users/{user_id}` para obtener los datos sobre un usuario específico asociados a un ID de usuario.
|
||||
|
||||
Porque las *operaciones de path* son evaluadas en orden, tienes que asegurarte de que el path para `/users/me` sea declarado antes que el path para `/users/{user_id}`:
|
||||
|
||||
```Python hl_lines="6 11"
|
||||
{!../../../docs_src/path_params/tutorial003.py!}
|
||||
```
|
||||
|
||||
De otra manera el path para `/users/{user_id}` coincidiría también con `/users/me` "pensando" que está recibiendo el parámetro `user_id` con el valor `"me"`.
|
||||
|
||||
## Valores predefinidos
|
||||
|
||||
Si tienes una *operación de path* que recibe un *parámetro de path* pero quieres que los valores posibles del *parámetro de path* sean predefinidos puedes usar un <abbr title="Enumeration">`Enum`</abbr> estándar de Python.
|
||||
|
||||
### Crea una clase `Enum`
|
||||
|
||||
Importa `Enum` y crea una sub-clase que herede desde `str` y desde `Enum`.
|
||||
|
||||
Al heredar desde `str` la documentación de la API podrá saber que los valores deben ser de tipo `string` y podrá mostrarlos correctamente.
|
||||
|
||||
Luego crea atributos de clase con valores fijos, que serán los valores disponibles válidos:
|
||||
|
||||
```Python hl_lines="1 6-9"
|
||||
{!../../../docs_src/path_params/tutorial005.py!}
|
||||
```
|
||||
|
||||
!!! info "Información"
|
||||
Las <a href="https://docs.python.org/3/library/enum.html" class="external-link" target="_blank">Enumerations (o enums) están disponibles en Python</a> desde la versión 3.4.
|
||||
|
||||
!!! tip "Consejo"
|
||||
Si lo estás dudando, "AlexNet", "ResNet", y "LeNet" son solo nombres de <abbr title="Tecnicamente, arquitecturas de modelos de Deep Learning">modelos</abbr> de Machine Learning.
|
||||
|
||||
### Declara un *parámetro de path*
|
||||
|
||||
Luego, crea un *parámetro de path* con anotaciones de tipos usando la clase enum que creaste (`ModelName`):
|
||||
|
||||
```Python hl_lines="16"
|
||||
{!../../../docs_src/path_params/tutorial005.py!}
|
||||
```
|
||||
|
||||
### Revisa la documentación
|
||||
|
||||
Debido a que los valores disponibles para el *parámetro de path* están predefinidos, la documentación interactiva los puede mostrar bien:
|
||||
|
||||
<img src="/img/tutorial/path-params/image03.png">
|
||||
|
||||
### Trabajando con los *enumerations* de Python
|
||||
|
||||
El valor del *parámetro de path* será un *enumeration member*.
|
||||
|
||||
#### Compara *enumeration members*
|
||||
|
||||
Puedes compararlo con el *enumeration member* en el enum (`ModelName`) que creaste:
|
||||
|
||||
```Python hl_lines="17"
|
||||
{!../../../docs_src/path_params/tutorial005.py!}
|
||||
```
|
||||
|
||||
#### Obtén el *enumeration value*
|
||||
|
||||
Puedes obtener el valor exacto (un `str` en este caso) usando `model_name.value`, o en general, `your_enum_member.value`:
|
||||
|
||||
```Python hl_lines="20"
|
||||
{!../../../docs_src/path_params/tutorial005.py!}
|
||||
```
|
||||
|
||||
!!! tip "Consejo"
|
||||
También podrías obtener el valor `"lenet"` con `ModelName.lenet.value`.
|
||||
|
||||
#### Devuelve *enumeration members*
|
||||
|
||||
Puedes devolver *enum members* desde tu *operación de path* inclusive en un body de JSON anidado (por ejemplo, un `dict`).
|
||||
|
||||
Ellos serán convertidos a sus valores correspondientes (strings en este caso) antes de devolverlos al cliente:
|
||||
|
||||
```Python hl_lines="18 21 23"
|
||||
{!../../../docs_src/path_params/tutorial005.py!}
|
||||
```
|
||||
|
||||
En tu cliente obtendrás una respuesta en JSON como:
|
||||
|
||||
```JSON
|
||||
{
|
||||
"model_name": "alexnet",
|
||||
"message": "Deep Learning FTW!"
|
||||
}
|
||||
```
|
||||
|
||||
## Parámetros de path parameters que contienen paths
|
||||
|
||||
Digamos que tienes una *operación de path* con un path `/files/{file_path}`.
|
||||
|
||||
Pero necesitas que el mismo `file_path` contenga un path como `home/johndoe/myfile.txt`.
|
||||
|
||||
Entonces, la URL para ese archivo sería algo como: `/files/home/johndoe/myfile.txt`.
|
||||
|
||||
### Soporte de OpenAPI
|
||||
|
||||
OpenAPI no soporta una manera de declarar un *parámetro de path* que contenga un path, dado que esto podría llevar a escenarios que son difíciles de probar y definir.
|
||||
|
||||
Sin embargo, lo puedes hacer en **FastAPI** usando una de las herramientas internas de Starlette.
|
||||
|
||||
La documentación seguirá funcionando, aunque no añadirá ninguna información diciendo que el parámetro debería contener un path.
|
||||
|
||||
### Convertidor de path
|
||||
|
||||
Usando una opción directamente desde Starlette puedes declarar un *parámetro de path* que contenga un path usando una URL como:
|
||||
|
||||
```
|
||||
/files/{file_path:path}
|
||||
```
|
||||
|
||||
En este caso el nombre del parámetro es `file_path` y la última parte, `:path`, le dice que el parámetro debería coincidir con cualquier path.
|
||||
|
||||
Entonces lo puedes usar con:
|
||||
|
||||
```Python hl_lines="6"
|
||||
{!../../../docs_src/path_params/tutorial004.py!}
|
||||
```
|
||||
|
||||
!!! tip "Consejo"
|
||||
Podrías necesitar que el parámetro contenga `/home/johndoe/myfile.txt` con un slash inicial (`/`).
|
||||
|
||||
En este caso la URL sería `/files//home/johndoe/myfile.txt` con un slash doble (`//`) entre `files` y `home`.
|
||||
|
||||
## Repaso
|
||||
|
||||
Con **FastAPI**, usando declaraciones de tipo de Python intuitivas y estándares, obtienes:
|
||||
|
||||
* Soporte en el editor: chequeos de errores, auto-completado, etc.
|
||||
* "<abbr title="convertir el string que viene de un HTTP request a datos de Python">Parsing</abbr>" de datos
|
||||
* Validación de datos
|
||||
* Anotación de la API y documentación automática
|
||||
|
||||
Solo tienes que declararlos una vez.
|
||||
|
||||
Esa es probablemente la principal ventaja visible de **FastAPI** sobre otros frameworks alternativos (aparte del rendimiento puro).
|
||||
@@ -3,10 +3,23 @@ site_description: FastAPI framework, high performance, easy to learn, fast to co
|
||||
site_url: https://fastapi.tiangolo.com/es/
|
||||
theme:
|
||||
name: material
|
||||
custom_dir: overrides
|
||||
palette:
|
||||
scheme: preference
|
||||
- scheme: default
|
||||
primary: teal
|
||||
accent: amber
|
||||
toggle:
|
||||
icon: material/lightbulb-outline
|
||||
name: Switch to light mode
|
||||
- scheme: slate
|
||||
primary: teal
|
||||
accent: amber
|
||||
toggle:
|
||||
icon: material/lightbulb
|
||||
name: Switch to dark mode
|
||||
features:
|
||||
- search.suggest
|
||||
- search.highlight
|
||||
icon:
|
||||
repo: fontawesome/brands/github-alt
|
||||
logo: https://fastapi.tiangolo.com/img/icon-white.svg
|
||||
@@ -28,10 +41,14 @@ nav:
|
||||
- en: /
|
||||
- es: /es/
|
||||
- fr: /fr/
|
||||
- ja: /ja/
|
||||
- id: /id/
|
||||
- it: /it/
|
||||
- ja: /ja/
|
||||
- ko: /ko/
|
||||
- pl: /pl/
|
||||
- pt: /pt/
|
||||
- ru: /ru/
|
||||
- sq: /sq/
|
||||
- tr: /tr/
|
||||
- uk: /uk/
|
||||
- zh: /zh/
|
||||
@@ -39,6 +56,8 @@ nav:
|
||||
- python-types.md
|
||||
- Tutorial - Guía de Usuario:
|
||||
- tutorial/index.md
|
||||
- tutorial/first-steps.md
|
||||
- tutorial/path-params.md
|
||||
- Guía de Usuario Avanzada:
|
||||
- advanced/index.md
|
||||
- async.md
|
||||
@@ -61,7 +80,9 @@ markdown_extensions:
|
||||
extra:
|
||||
social:
|
||||
- icon: fontawesome/brands/github-alt
|
||||
link: https://github.com/tiangolo/typer
|
||||
link: https://github.com/tiangolo/fastapi
|
||||
- icon: fontawesome/brands/discord
|
||||
link: https://discord.gg/VQjSZaeJmf
|
||||
- icon: fontawesome/brands/twitter
|
||||
link: https://twitter.com/tiangolo
|
||||
- icon: fontawesome/brands/linkedin
|
||||
@@ -72,6 +93,35 @@ extra:
|
||||
link: https://medium.com/@tiangolo
|
||||
- icon: fontawesome/solid/globe
|
||||
link: https://tiangolo.com
|
||||
alternate:
|
||||
- link: /
|
||||
name: en - English
|
||||
- link: /es/
|
||||
name: es - español
|
||||
- link: /fr/
|
||||
name: fr - français
|
||||
- link: /id/
|
||||
name: id
|
||||
- link: /it/
|
||||
name: it - italiano
|
||||
- link: /ja/
|
||||
name: ja - 日本語
|
||||
- link: /ko/
|
||||
name: ko - 한국어
|
||||
- link: /pl/
|
||||
name: pl
|
||||
- link: /pt/
|
||||
name: pt - português
|
||||
- link: /ru/
|
||||
name: ru - русский язык
|
||||
- link: /sq/
|
||||
name: sq - shqip
|
||||
- link: /tr/
|
||||
name: tr - Türkçe
|
||||
- link: /uk/
|
||||
name: uk - українська мова
|
||||
- link: /zh/
|
||||
name: zh - 汉语
|
||||
extra_css:
|
||||
- https://fastapi.tiangolo.com/css/termynal.css
|
||||
- https://fastapi.tiangolo.com/css/custom.css
|
||||
@@ -79,5 +129,3 @@ 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
|
||||
|
||||
0
docs/es/overrides/.gitignore
vendored
Normal file
446
docs/fr/docs/alternatives.md
Normal file
@@ -0,0 +1,446 @@
|
||||
# Alternatives, inspiration et comparaisons
|
||||
|
||||
Ce qui a inspiré **FastAPI**, comment il se compare à d'autres solutions et ce qu'il en a appris.
|
||||
|
||||
## Intro
|
||||
|
||||
**FastAPI** n'existerait pas sans les précédentes contributions d'autres projets.
|
||||
|
||||
De nombreux outils ont été créés auparavant et ont contribué à inspirer sa création.
|
||||
|
||||
J'ai évité la création d'un nouveau framework pendant plusieurs années. J'ai d'abord essayé de combler toutes les
|
||||
fonctionnalités couvertes par **FastAPI** en utilisant de nombreux frameworks, plug-ins et outils différents.
|
||||
|
||||
Mais à un moment donné il n'y avait pas d'autre option que de créer quelque chose qui offrait toutes ces
|
||||
fonctionnalités, en reprenant et en combinant de la meilleure façon possible les meilleures idées des outils
|
||||
précédents, en utilisant des fonctionnalités du langage qui n'étaient même pas disponibles auparavant (type hints depuis Python 3.6+).
|
||||
|
||||
## Outils précédents
|
||||
|
||||
### <a href="https://www.djangoproject.com/" class="external-link" target="_blank">Django</a>
|
||||
|
||||
C'est le framework Python le plus populaire et il bénéficie d'une grande confiance. Il est utilisé pour construire
|
||||
des systèmes tel qu'Instagram.
|
||||
|
||||
Il est relativement fortement couplé aux bases de données relationnelles (comme MySQL ou PostgreSQL), de sorte qu'il
|
||||
n'est pas très facile d'utiliser une base de données NoSQL (comme Couchbase, MongoDB, Cassandra, etc.) comme principal moyen de
|
||||
stockage.
|
||||
|
||||
Il a été créé pour générer le HTML en backend, pas pour créer des API consommées par un frontend moderne (comme React, Vue.js et Angular) ou par d'autres systèmes (comme les appareils <abbr title="Internet of Things">IoT</abbr>) communiquant avec lui.
|
||||
|
||||
### <a href="https://www.django-rest-framework.org/" class="external-link" target="_blank">Django REST Framework</a>
|
||||
|
||||
Django REST framework a été conçu comme une boîte à outils flexible permettant de construire des API Web à partir de Django, afin d'améliorer ses capacités en matière d'API.
|
||||
|
||||
Il est utilisé par de nombreuses entreprises, dont Mozilla, Red Hat et Eventbrite.
|
||||
|
||||
Il s'agissait de l'un des premiers exemples de **documentation automatique pour API**, et c'est précisément l'une des
|
||||
premières idées qui a inspiré "la recherche de" **FastAPI**.
|
||||
|
||||
!!! note
|
||||
Django REST framework a été créé par Tom Christie. Le créateur de Starlette et Uvicorn, sur lesquels **FastAPI** est basé.
|
||||
|
||||
!!! check "A inspiré **FastAPI** à"
|
||||
Avoir une interface de documentation automatique de l'API.
|
||||
|
||||
### <a href="https://flask.palletsprojects.com" class="external-link" target="_blank">Flask</a>
|
||||
|
||||
Flask est un "micro-framework", il ne comprend pas d'intégrations de bases de données ni beaucoup de choses qui sont fournies par défaut dans Django.
|
||||
|
||||
Cette simplicité et cette flexibilité permettent d'utiliser des bases de données NoSQL comme principal système de stockage de données.
|
||||
|
||||
Comme il est très simple, son apprentissage est relativement intuitif, bien que la documentation soit quelque peu
|
||||
technique par moments.
|
||||
|
||||
Il est aussi couramment utilisé pour d'autres applications qui n'ont pas nécessairement besoin d'une base de données, de gestion des utilisateurs ou de l'une des nombreuses fonctionnalités préinstallées dans Django. Bien que beaucoup de ces fonctionnalités puissent être ajoutées avec des plug-ins.
|
||||
|
||||
Ce découplage des parties, et le fait d'être un "micro-framework" qui puisse être étendu pour couvrir exactement ce
|
||||
qui est nécessaire, était une caractéristique clé que je voulais conserver.
|
||||
|
||||
Compte tenu de la simplicité de Flask, il semblait bien adapté à la création d'API. La prochaine chose à trouver était un "Django REST Framework" pour Flask.
|
||||
|
||||
!!! check "A inspiré **FastAPI** à"
|
||||
Être un micro-framework. Il est donc facile de combiner les outils et les pièces nécessaires.
|
||||
|
||||
Proposer un système de routage simple et facile à utiliser.
|
||||
|
||||
### <a href="https://requests.readthedocs.io" class="external-link" target="_blank">Requests</a>
|
||||
|
||||
**FastAPI** n'est pas réellement une alternative à **Requests**. Leur cadre est très différent.
|
||||
|
||||
Il serait en fait plus courant d'utiliser Requests _à l'intérieur_ d'une application FastAPI.
|
||||
|
||||
Mais quand même, FastAPI s'est inspiré de Requests.
|
||||
|
||||
**Requests** est une bibliothèque pour _interagir_ avec les API (en tant que client), tandis que **FastAPI** est une bibliothèque pour _créer_ des API (en tant que serveur).
|
||||
|
||||
Ils sont, plus ou moins, aux extrémités opposées, se complétant l'un l'autre.
|
||||
|
||||
Requests a un design très simple et intuitif, il est très facile à utiliser, avec des valeurs par défaut raisonnables, tout en étant très puissant et personnalisable.
|
||||
|
||||
C'est pourquoi, comme le dit le site officiel :
|
||||
|
||||
> Requests est l'un des packages Python les plus téléchargés de tous les temps
|
||||
|
||||
La façon dont vous l'utilisez est très simple. Par exemple, pour faire une requête `GET`, vous devez écrire :
|
||||
|
||||
```Python
|
||||
response = requests.get("http://example.com/some/url")
|
||||
```
|
||||
|
||||
En contrepartie l'API _des opérations de chemin_ de FastAPI pourrait ressembler à ceci :
|
||||
|
||||
```Python hl_lines="1"
|
||||
@app.get("/some/url")
|
||||
def read_url():
|
||||
return {"message": "Hello World"}
|
||||
```
|
||||
|
||||
Notez les similitudes entre `requests.get(...)` et `@app.get(...)`.
|
||||
|
||||
!!! check "A inspiré **FastAPI** à"
|
||||
_ Avoir une API simple et intuitive.
|
||||
_ Utiliser les noms de méthodes HTTP (opérations) directement, de manière simple et intuitive. \* Avoir des valeurs par défaut raisonnables, mais des personnalisations puissantes.
|
||||
|
||||
### <a href="https://swagger.io/" class="external-link" target="_blank">Swagger</a> / <a href="https://github.com/OAI/OpenAPI-Specification/" class="external-link" target="_blank">OpenAPI</a>
|
||||
|
||||
La principale fonctionnalité que j'ai emprunté à Django REST Framework était la documentation automatique des API.
|
||||
|
||||
Puis j'ai découvert qu'il existait une norme pour documenter les API, en utilisant JSON (ou YAML, une extension de JSON) appelée Swagger.
|
||||
|
||||
Il existait déjà une interface utilisateur Web pour les API Swagger. Donc, être capable de générer une documentation
|
||||
Swagger pour une API permettrait d'utiliser cette interface utilisateur web automatiquement.
|
||||
|
||||
À un moment donné, Swagger a été cédé à la Fondation Linux, puis a été rebaptisé OpenAPI.
|
||||
|
||||
C'est pourquoi, lorsqu'on parle de la version 2.0, il est courant de dire "Swagger", et pour la version 3+ "OpenAPI".
|
||||
|
||||
!!! check "A inspiré **FastAPI** à"
|
||||
Adopter et utiliser une norme ouverte pour les spécifications des API, au lieu d'un schéma personnalisé.
|
||||
|
||||
Intégrer des outils d'interface utilisateur basés sur des normes :
|
||||
|
||||
* <a href="https://github.com/swagger-api/swagger-ui" class="external-link" target="_blank">Swagger UI</a>
|
||||
* <a href="https://github.com/Rebilly/ReDoc" class="external-link" target="_blank">ReDoc</a>
|
||||
|
||||
Ces deux-là ont été choisis parce qu'ils sont populaires et stables, mais en faisant une recherche rapide, vous pourriez trouver des dizaines d'alternatives supplémentaires pour OpenAPI (que vous pouvez utiliser avec **FastAPI**).
|
||||
|
||||
### Frameworks REST pour Flask
|
||||
|
||||
Il y a plusieurs frameworks REST pour Flask, mais après avoir investi du temps et du travail pour les étudier, j'ai
|
||||
découvert que le développement de beaucoup d'entre eux sont suspendus ou abandonnés, avec plusieurs problèmes
|
||||
permanents qui les rendent inadaptés.
|
||||
|
||||
### <a href="https://marshmallow.readthedocs.io/en/3.0/" class="external-link" target="_blank">Marshmallow</a>
|
||||
|
||||
L'une des principales fonctionnalités nécessaires aux systèmes API est la "<abbr title="également appelée
|
||||
marshalling, conversion">sérialisation</abbr>" des données, qui consiste à prendre les données du code (Python) et à
|
||||
les convertir en quelque chose qui peut être envoyé sur le réseau. Par exemple, convertir un objet contenant des
|
||||
données provenant d'une base de données en un objet JSON. Convertir des objets `datetime` en strings, etc.
|
||||
|
||||
La validation des données est une autre fonctionnalité importante dont ont besoin les API. Elle permet de s'assurer
|
||||
que les données sont valides, compte tenu de certains paramètres. Par exemple, qu'un champ est un `int`, et non un
|
||||
string.
|
||||
Ceci est particulièrement utile pour les données entrantes.
|
||||
|
||||
Sans un système de validation des données, vous devriez effectuer toutes les vérifications à la main, dans le code.
|
||||
|
||||
Ces fonctionnalités sont ce pourquoi Marshmallow a été construit. C'est une excellente bibliothèque, et je l'ai déjà beaucoup utilisée.
|
||||
|
||||
Mais elle a été créée avant que les type hints n'existent en Python. Ainsi, pour définir chaque <abbr title="la définition de
|
||||
la façon dont les données doivent être formées">schéma</abbr>, vous devez utiliser des utilitaires et des classes spécifiques fournies par Marshmallow.
|
||||
|
||||
!!! check "A inspiré **FastAPI** à"
|
||||
Utilisez du code pour définir des "schémas" qui fournissent automatiquement les types de données et la validation.
|
||||
|
||||
### <a href="https://webargs.readthedocs.io/en/latest/" class="external-link" target="_blank">Webargs</a>
|
||||
|
||||
Une autre grande fonctionnalité requise par les API est le <abbr title="la lecture et la conversion en données
|
||||
Python">parsing</abbr> des données provenant des requêtes entrantes.
|
||||
|
||||
Webargs est un outil qui a été créé pour fournir cela par-dessus plusieurs frameworks, dont Flask.
|
||||
|
||||
Il utilise Marshmallow pour effectuer la validation des données. Et il a été créé par les mêmes développeurs.
|
||||
|
||||
C'est un outil formidable et je l'ai beaucoup utilisé aussi, avant d'avoir **FastAPI**.
|
||||
|
||||
!!! info
|
||||
Webargs a été créé par les développeurs de Marshmallow.
|
||||
|
||||
!!! check "A inspiré **FastAPI** à"
|
||||
Disposer d'une validation automatique des données des requêtes entrantes.
|
||||
|
||||
### <a href="https://apispec.readthedocs.io/en/stable/" class="external-link" target="_blank">APISpec</a>
|
||||
|
||||
Marshmallow et Webargs fournissent la validation, l'analyse et la sérialisation en tant que plug-ins.
|
||||
|
||||
Mais la documentation fait toujours défaut. C'est alors qu'APISpec a été créé.
|
||||
|
||||
Il s'agit d'un plug-in pour de nombreux frameworks (et il existe également un plug-in pour Starlette).
|
||||
|
||||
Le principe est le suivant : vous écrivez la définition du schéma au format YAML dans la docstring de chaque fonction gérant une route.
|
||||
|
||||
Et il génère des schémas OpenAPI.
|
||||
|
||||
C'est ainsi que cela fonctionne dans Flask, Starlette, Responder, etc.
|
||||
|
||||
Mais alors, nous avons à nouveau le problème d'avoir une micro-syntaxe, dans une docstring Python (un gros morceau de YAML).
|
||||
|
||||
L'éditeur ne peut guère aider en la matière. Et si nous modifions les paramètres ou les schémas Marshmallow et que nous oublions de modifier également cette docstring YAML, le schéma généré deviendrait obsolète.
|
||||
|
||||
!!! info
|
||||
APISpec a été créé par les développeurs de Marshmallow.
|
||||
|
||||
!!! check "A inspiré **FastAPI** à"
|
||||
Supporter la norme ouverte pour les API, OpenAPI.
|
||||
|
||||
### <a href="https://flask-apispec.readthedocs.io/en/latest/" class="external-link" target="_blank">Flask-apispec</a>
|
||||
|
||||
C'est un plug-in pour Flask, qui relie Webargs, Marshmallow et APISpec.
|
||||
|
||||
Il utilise les informations de Webargs et Marshmallow pour générer automatiquement des schémas OpenAPI, en utilisant APISpec.
|
||||
|
||||
C'est un excellent outil, très sous-estimé. Il devrait être beaucoup plus populaire que de nombreux plug-ins Flask. C'est peut-être dû au fait que sa documentation est trop concise et abstraite.
|
||||
|
||||
Cela a permis de ne pas avoir à écrire YAML (une autre syntaxe) à l'intérieur des docstrings Python.
|
||||
|
||||
Cette combinaison de Flask, Flask-apispec avec Marshmallow et Webargs était ma stack backend préférée jusqu'à la création de **FastAPI**.
|
||||
|
||||
Son utilisation a conduit à la création de plusieurs générateurs Flask full-stack. Ce sont les principales stacks que
|
||||
j'ai (ainsi que plusieurs équipes externes) utilisées jusqu'à présent :
|
||||
|
||||
- <a href="https://github.com/tiangolo/full-stack" class="external-link" target="_blank">https://github.com/tiangolo/full-stack</a>
|
||||
- <a href="https://github.com/tiangolo/full-stack-flask-couchbase" class="external-link" target="_blank">https://github.com/tiangolo/full-stack-flask-couchbase</a>
|
||||
- <a href="https://github.com/tiangolo/full-stack-flask-couchdb" class="external-link" target="_blank">https://github.com/tiangolo/full-stack-flask-couchdb</a>
|
||||
|
||||
Ces mêmes générateurs full-stack ont servi de base aux [Générateurs de projets pour **FastAPI**](project-generation.md){.internal-link target=\_blank}.
|
||||
|
||||
!!! info
|
||||
Flask-apispec a été créé par les développeurs de Marshmallow.
|
||||
|
||||
!!! check "A inspiré **FastAPI** à"
|
||||
Générer le schéma OpenAPI automatiquement, à partir du même code qui définit la sérialisation et la validation.
|
||||
|
||||
### <a href="https://nestjs.com/" class="external-link" target="_blank">NestJS</a> (et <a href="https://angular.io/" class="external-link" target="_blank">Angular</a>)
|
||||
|
||||
Ce n'est même pas du Python, NestJS est un framework JavaScript (TypeScript) NodeJS inspiré d'Angular.
|
||||
|
||||
Il réalise quelque chose de similaire à ce qui peut être fait avec Flask-apispec.
|
||||
|
||||
Il possède un système d'injection de dépendances intégré, inspiré d'Angular 2. Il nécessite de pré-enregistrer les "injectables" (comme tous les autres systèmes d'injection de dépendances que je connais), donc, cela ajoute à la verbosité et à la répétition du code.
|
||||
|
||||
Comme les paramètres sont décrits avec des types TypeScript (similaires aux type hints de Python), la prise en charge
|
||||
par l'éditeur est assez bonne.
|
||||
|
||||
Mais comme les données TypeScript ne sont pas préservées après la compilation en JavaScript, il ne peut pas compter sur les types pour définir la validation, la sérialisation et la documentation en même temps. En raison de cela et de certaines décisions de conception, pour obtenir la validation, la sérialisation et la génération automatique de schémas, il est nécessaire d'ajouter des décorateurs à de nombreux endroits. Cela devient donc assez verbeux.
|
||||
|
||||
Il ne peut pas très bien gérer les modèles imbriqués. Ainsi, si le corps JSON de la requête est un objet JSON comportant des champs internes qui sont à leur tour des objets JSON imbriqués, il ne peut pas être correctement documenté et validé.
|
||||
|
||||
!!! check "A inspiré **FastAPI** à"
|
||||
Utiliser les types Python pour bénéficier d'un excellent support de l'éditeur.
|
||||
|
||||
Disposer d'un puissant système d'injection de dépendances. Trouver un moyen de minimiser la répétition du code.
|
||||
|
||||
### <a href="https://sanic.readthedocs.io/en/latest/" class="external-link" target="_blank">Sanic</a>
|
||||
|
||||
C'était l'un des premiers frameworks Python extrêmement rapides basés sur `asyncio`. Il a été conçu pour être très similaire à Flask.
|
||||
|
||||
!!! note "Détails techniques"
|
||||
Il utilisait <a href="https://github.com/MagicStack/uvloop" class="external-link" target="_blank">`uvloop`</a> au lieu du système par défaut de Python `asyncio`. C'est ce qui l'a rendu si rapide.
|
||||
|
||||
Il a clairement inspiré Uvicorn et Starlette, qui sont actuellement plus rapides que Sanic dans les benchmarks.
|
||||
|
||||
!!! check "A inspiré **FastAPI** à"
|
||||
Trouvez un moyen d'avoir une performance folle.
|
||||
|
||||
C'est pourquoi **FastAPI** est basé sur Starlette, car il s'agit du framework le plus rapide disponible (testé par des benchmarks tiers).
|
||||
|
||||
### <a href="https://falconframework.org/" class="external-link" target="_blank">Falcon</a>
|
||||
|
||||
Falcon est un autre framework Python haute performance, il est conçu pour être minimal, et est utilisé comme fondation pour d'autres frameworks comme Hug.
|
||||
|
||||
Il utilise le standard précédent pour les frameworks web Python (WSGI) qui est synchrone, donc il ne peut pas gérer les WebSockets et d'autres cas d'utilisation. Néanmoins, il offre de très bonnes performances.
|
||||
|
||||
Il est conçu pour avoir des fonctions qui reçoivent deux paramètres, une "requête" et une "réponse". Ensuite, vous
|
||||
"lisez" des parties de la requête et "écrivez" des parties dans la réponse. En raison de cette conception, il n'est
|
||||
pas possible de déclarer des paramètres de requête et des corps avec des indications de type Python standard comme paramètres de fonction.
|
||||
|
||||
Ainsi, la validation, la sérialisation et la documentation des données doivent être effectuées dans le code, et non pas automatiquement. Ou bien elles doivent être implémentées comme un framework au-dessus de Falcon, comme Hug. Cette même distinction se retrouve dans d'autres frameworks qui s'inspirent de la conception de Falcon, qui consiste à avoir un objet de requête et un objet de réponse comme paramètres.
|
||||
|
||||
!!! check "A inspiré **FastAPI** à"
|
||||
Trouver des moyens d'obtenir de bonnes performances.
|
||||
|
||||
Avec Hug (puisque Hug est basé sur Falcon), **FastAPI** a inspiré la déclaration d'un paramètre `response` dans les fonctions.
|
||||
|
||||
Bien que dans FastAPI, il est facultatif, et est utilisé principalement pour définir les en-têtes, les cookies, et les codes de statut alternatifs.
|
||||
|
||||
### <a href="https://moltenframework.com/" class="external-link" target="_blank">Molten</a>
|
||||
|
||||
J'ai découvert Molten lors des premières étapes de développement de **FastAPI**. Et il a des idées assez similaires :
|
||||
|
||||
- Basé sur les type hints Python.
|
||||
- Validation et documentation via ces types.
|
||||
- Système d'injection de dépendances.
|
||||
|
||||
Il n'utilise pas une librairie tiers de validation, sérialisation et de documentation tel que Pydantic, il utilise son propre système. Ainsi, ces définitions de types de données ne sont pas réutilisables aussi facilement.
|
||||
|
||||
Il nécessite une configuration un peu plus verbeuse. Et comme il est basé sur WSGI (au lieu dASGI), il n'est pas
|
||||
conçu pour profiter des hautes performances fournies par des outils comme Uvicorn, Starlette et Sanic.
|
||||
|
||||
Le système d'injection de dépendances exige le pré-enregistrement des dépendances et les dépendances sont résolues sur la base des types déclarés. Ainsi, il n'est pas possible de déclarer plus d'un "composant" qui fournit un certain type.
|
||||
|
||||
Les routes sont déclarées à un seul endroit, en utilisant des fonctions déclarées à d'autres endroits (au lieu
|
||||
d'utiliser des décorateurs qui peuvent être placés juste au-dessus de la fonction qui gère l'endpoint). Cette
|
||||
méthode est plus proche de celle de Django que de celle de Flask (et Starlette). Il sépare dans le code des choses
|
||||
qui sont relativement fortement couplées.
|
||||
|
||||
!!! check "A inspiré **FastAPI** à"
|
||||
Définir des validations supplémentaires pour les types de données utilisant la valeur "par défaut" des attributs du modèle. Ceci améliore le support de l'éditeur, et n'était pas disponible dans Pydantic auparavant.
|
||||
|
||||
Cela a en fait inspiré la mise à jour de certaines parties de Pydantic, afin de supporter le même style de déclaration de validation (toute cette fonctionnalité est maintenant déjà disponible dans Pydantic).
|
||||
|
||||
### <a href="https://www.hug.rest/" class="external-link" target="_blank">Hug</a>
|
||||
|
||||
Hug a été l'un des premiers frameworks à implémenter la déclaration des types de paramètres d'API en utilisant les type hints Python. C'était une excellente idée qui a inspiré d'autres outils à faire de même.
|
||||
|
||||
Il utilisait des types personnalisés dans ses déclarations au lieu des types Python standard, mais c'était tout de même un énorme pas en avant.
|
||||
|
||||
Il a également été l'un des premiers frameworks à générer un schéma personnalisé déclarant l'ensemble de l'API en JSON.
|
||||
|
||||
Il n'était pas basé sur une norme comme OpenAPI et JSON Schema. Il ne serait donc pas simple de l'intégrer à d'autres outils, comme Swagger UI. Mais encore une fois, c'était une idée très innovante.
|
||||
|
||||
Il présente une caractéristique intéressante et peu commune : à l'aide du même framework, il est possible de créer des
|
||||
API et des CLI.
|
||||
|
||||
Comme il est basé sur l'ancienne norme pour les frameworks web Python synchrones (WSGI), il ne peut pas gérer les Websockets et autres, bien qu'il soit également très performant.
|
||||
|
||||
!!! info
|
||||
Hug a été créé par Timothy Crosley, le créateur de <a href="https://github.com/timothycrosley/isort" class="external-link" target="_blank">`isort`</a>, un excellent outil pour trier automatiquement les imports dans les fichiers Python.
|
||||
|
||||
!!! check "A inspiré **FastAPI** à"
|
||||
Hug a inspiré certaines parties d'APIStar, et était l'un des outils que je trouvais les plus prometteurs, à côté d'APIStar.
|
||||
|
||||
Hug a contribué à inspirer **FastAPI** pour utiliser les type hints Python
|
||||
pour déclarer les paramètres, et pour générer automatiquement un schéma définissant l'API.
|
||||
|
||||
Hug a inspiré **FastAPI** pour déclarer un paramètre `response` dans les fonctions pour définir les en-têtes et les cookies.
|
||||
|
||||
### <a href="https://github.com/encode/apistar" class="external-link" target="_blank">APIStar</a> (<= 0.5)
|
||||
|
||||
Juste avant de décider de développer **FastAPI**, j'ai trouvé le serveur **APIStar**. Il contenait presque tout ce
|
||||
que je recherchais et avait un beau design.
|
||||
|
||||
C'était l'une des premières implémentations d'un framework utilisant les type hints Python pour déclarer les paramètres
|
||||
et les requêtes que j'ai vues (avant NestJS et Molten). Je l'ai trouvé plus ou moins en même temps que Hug. Mais APIStar utilisait le standard OpenAPI.
|
||||
|
||||
Il disposait de la validation automatique, sérialisation des données et d'une génération de schéma OpenAPI basée sur les mêmes type hints à plusieurs endroits.
|
||||
|
||||
La définition du schéma de corps de requête n'utilisait pas les mêmes type hints Python que Pydantic, il était un peu plus proche de Marshmallow, donc le support de l'éditeur n'était pas aussi bon, mais APIStar était quand même la meilleure option disponible.
|
||||
|
||||
Il avait les meilleures performances d'après les benchmarks de l'époque (seulement surpassé par Starlette).
|
||||
|
||||
Au départ, il ne disposait pas d'une interface web de documentation automatique de l'API, mais je savais que je pouvais lui ajouter une interface Swagger.
|
||||
|
||||
Il avait un système d'injection de dépendances. Il nécessitait un pré-enregistrement des composants, comme d'autres outils discutés ci-dessus. Mais c'était quand même une excellente fonctionnalité.
|
||||
|
||||
Je n'ai jamais pu l'utiliser dans un projet complet, car il n'avait pas d'intégration de sécurité, et je ne pouvais donc pas remplacer toutes les fonctionnalités que j'avais avec les générateurs complets basés sur Flask-apispec. J'avais dans mon backlog de projets de créer une pull request pour ajouter cette fonctionnalité.
|
||||
|
||||
Mais ensuite, le projet a changé d'orientation.
|
||||
|
||||
Il ne s'agissait plus d'un framework web API, le créateur devant se concentrer sur Starlette.
|
||||
|
||||
Maintenant, APIStar est un ensemble d'outils pour valider les spécifications OpenAPI, et non un framework web.
|
||||
|
||||
!!! info
|
||||
APIStar a été créé par Tom Christie. Le même gars qui a créé :
|
||||
|
||||
* Django REST Framework
|
||||
* Starlette (sur lequel **FastAPI** est basé)
|
||||
* Uvicorn (utilisé par Starlette et **FastAPI**)
|
||||
|
||||
!!! check "A inspiré **FastAPI** à"
|
||||
Exister.
|
||||
|
||||
L'idée de déclarer plusieurs choses (validation des données, sérialisation et documentation) avec les mêmes types Python, tout en offrant un excellent support pour les éditeurs, était pour moi une idée brillante.
|
||||
|
||||
Et après avoir longtemps cherché un framework similaire et testé de nombreuses alternatives, APIStar était la meilleure option disponible.
|
||||
|
||||
Puis APIStar a cessé d'exister en tant que serveur et Starlette a été créé, et a constitué une meilleure base pour un tel système. Ce fut l'inspiration finale pour construire **FastAPI**.
|
||||
|
||||
Je considère **FastAPI** comme un "successeur spirituel" d'APIStar, tout en améliorant et en augmentant les fonctionnalités, le système de typage et d'autres parties, sur la base des enseignements tirés de tous ces outils précédents.
|
||||
|
||||
## Utilisés par **FastAPI**
|
||||
|
||||
### <a href="https://pydantic-docs.helpmanual.io/" class="external-link" target="_blank">Pydantic</a>
|
||||
|
||||
Pydantic est une bibliothèque permettant de définir la validation, la sérialisation et la documentation des données (à l'aide de JSON Schema) en se basant sur les Python type hints.
|
||||
|
||||
Cela le rend extrêmement intuitif.
|
||||
|
||||
Il est comparable à Marshmallow. Bien qu'il soit plus rapide que Marshmallow dans les benchmarks. Et comme il est
|
||||
basé sur les mêmes type hints Python, le support de l'éditeur est grand.
|
||||
|
||||
!!! check "**FastAPI** l'utilise pour"
|
||||
Gérer toute la validation des données, leur sérialisation et la documentation automatique du modèle (basée sur le schéma JSON).
|
||||
|
||||
**FastAPI** prend ensuite ces données JSON Schema et les place dans OpenAPI, en plus de toutes les autres choses qu'il fait.
|
||||
|
||||
### <a href="https://www.starlette.io/" class="external-link" target="_blank">Starlette</a>
|
||||
|
||||
Starlette est un framework/toolkit léger <abbr title="Le nouveau standard pour construire des applications web assynchrones en Python">ASGI</abbr>, qui est idéal pour construire des services asyncio performants.
|
||||
|
||||
Il est très simple et intuitif. Il est conçu pour être facilement extensible et avoir des composants modulaires.
|
||||
|
||||
Il offre :
|
||||
|
||||
- Des performances vraiment impressionnantes.
|
||||
- Le support des WebSockets.
|
||||
- Le support de GraphQL.
|
||||
- Les tâches d'arrière-plan.
|
||||
- Les événements de démarrage et d'arrêt.
|
||||
- Un client de test basé sur request.
|
||||
- CORS, GZip, fichiers statiques, streaming des réponses.
|
||||
- Le support des sessions et des cookies.
|
||||
- Une couverture de test à 100 %.
|
||||
- 100 % de la base de code avec des annotations de type.
|
||||
- Zéro forte dépendance à d'autres packages.
|
||||
|
||||
Starlette est actuellement le framework Python le plus rapide testé. Seulement dépassé par Uvicorn, qui n'est pas un framework, mais un serveur.
|
||||
|
||||
Starlette fournit toutes les fonctionnalités de base d'un micro-framework web.
|
||||
|
||||
Mais il ne fournit pas de validation automatique des données, de sérialisation ou de documentation.
|
||||
|
||||
C'est l'une des principales choses que **FastAPI** ajoute par-dessus, le tout basé sur les type hints Python (en utilisant Pydantic). Cela, plus le système d'injection de dépendances, les utilitaires de sécurité, la génération de schémas OpenAPI, etc.
|
||||
|
||||
!!! note "Détails techniques"
|
||||
ASGI est une nouvelle "norme" développée par les membres de l'équipe principale de Django. Il ne s'agit pas encore d'une "norme Python" (un PEP), bien qu'ils soient en train de le faire.
|
||||
|
||||
Néanmoins, il est déjà utilisé comme "standard" par plusieurs outils. Cela améliore grandement l'interopérabilité, puisque vous pouvez remplacer Uvicorn par n'importe quel autre serveur ASGI (comme Daphne ou Hypercorn), ou vous pouvez ajouter des outils compatibles ASGI, comme `python-socketio`.
|
||||
|
||||
!!! check "**FastAPI** l'utilise pour"
|
||||
Gérer toutes les parties web de base. Ajouter des fonctionnalités par-dessus.
|
||||
|
||||
La classe `FastAPI` elle-même hérite directement de la classe `Starlette`.
|
||||
|
||||
Ainsi, tout ce que vous pouvez faire avec Starlette, vous pouvez le faire directement avec **FastAPI**, car il s'agit en fait de Starlette sous stéroïdes.
|
||||
|
||||
### <a href="https://www.uvicorn.org/" class="external-link" target="_blank">Uvicorn</a>
|
||||
|
||||
Uvicorn est un serveur ASGI rapide comme l'éclair, basé sur uvloop et httptools.
|
||||
|
||||
Il ne s'agit pas d'un framework web, mais d'un serveur. Par exemple, il ne fournit pas d'outils pour le routing. C'est
|
||||
quelque chose qu'un framework comme Starlette (ou **FastAPI**) fournirait par-dessus.
|
||||
|
||||
C'est le serveur recommandé pour Starlette et **FastAPI**.
|
||||
|
||||
!!! check "**FastAPI** le recommande comme"
|
||||
Le serveur web principal pour exécuter les applications **FastAPI**.
|
||||
|
||||
Vous pouvez le combiner avec Gunicorn, pour avoir un serveur multi-processus asynchrone.
|
||||
|
||||
Pour plus de détails, consultez la section [Déploiement](deployment/index.md){.internal-link target=_blank}.
|
||||
|
||||
## Benchmarks et vitesse
|
||||
|
||||
Pour comprendre, comparer et voir la différence entre Uvicorn, Starlette et FastAPI, consultez la section sur les [Benchmarks](benchmarks.md){.internal-link target=\_blank}.
|
||||
82
docs/fr/docs/external-links.md
Normal file
@@ -0,0 +1,82 @@
|
||||
# Articles et liens externes
|
||||
|
||||
**FastAPI** possède une grande communauté en constante extension.
|
||||
|
||||
Il existe de nombreux articles, outils et projets liés à **FastAPI**.
|
||||
|
||||
Voici une liste incomplète de certains d'entre eux.
|
||||
|
||||
!!! tip "Astuce"
|
||||
Si vous avez un article, projet, outil, ou quoi que ce soit lié à **FastAPI** qui n'est actuellement pas listé ici, créez une <a href="https://github.com/tiangolo/fastapi/edit/master/docs/en/data/external_links.yml" class="external-link" target="_blank">Pull Request l'ajoutant</a>.
|
||||
|
||||
## Articles
|
||||
|
||||
### Anglais
|
||||
|
||||
{% if external_links %}
|
||||
{% for article in external_links.articles.english %}
|
||||
|
||||
* <a href="{{ article.link }}" class="external-link" target="_blank">{{ article.title }}</a> par <a href="{{ article.author_link }}" class="external-link" target="_blank">{{ article.author }}</a>.
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
### Japonais
|
||||
|
||||
{% if external_links %}
|
||||
{% for article in external_links.articles.japanese %}
|
||||
|
||||
* <a href="{{ article.link }}" class="external-link" target="_blank">{{ article.title }}</a> par <a href="{{ article.author_link }}" class="external-link" target="_blank">{{ article.author }}</a>.
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
### Vietnamien
|
||||
|
||||
{% if external_links %}
|
||||
{% for article in external_links.articles.vietnamese %}
|
||||
|
||||
* <a href="{{ article.link }}" class="external-link" target="_blank">{{ article.title }}</a> par <a href="{{ article.author_link }}" class="external-link" target="_blank">{{ article.author }}</a>.
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
### Russe
|
||||
|
||||
{% if external_links %}
|
||||
{% for article in external_links.articles.russian %}
|
||||
|
||||
* <a href="{{ article.link }}" class="external-link" target="_blank">{{ article.title }}</a> par <a href="{{ article.author_link }}" class="external-link" target="_blank">{{ article.author }}</a>.
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
### Allemand
|
||||
|
||||
{% if external_links %}
|
||||
{% for article in external_links.articles.german %}
|
||||
|
||||
* <a href="{{ article.link }}" class="external-link" target="_blank">{{ article.title }}</a> par <a href="{{ article.author_link }}" class="external-link" target="_blank">{{ article.author }}</a>.
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
## Podcasts
|
||||
|
||||
{% if external_links %}
|
||||
{% for article in external_links.podcasts.english %}
|
||||
|
||||
* <a href="{{ article.link }}" class="external-link" target="_blank">{{ article.title }}</a> par <a href="{{ article.author_link }}" class="external-link" target="_blank">{{ article.author }}</a>.
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
## Conférences
|
||||
|
||||
{% if external_links %}
|
||||
{% for article in external_links.talks.english %}
|
||||
|
||||
* <a href="{{ article.link }}" class="external-link" target="_blank">{{ article.title }}</a> par <a href="{{ article.author_link }}" class="external-link" target="_blank">{{ article.author }}</a>.
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
## Projets
|
||||
|
||||
Les projets Github avec le topic `fastapi` les plus récents :
|
||||
|
||||
<div class="github-topic-projects">
|
||||
</div>
|
||||
135
docs/fr/docs/fastapi-people.md
Normal file
@@ -0,0 +1,135 @@
|
||||
# La communauté FastAPI
|
||||
|
||||
FastAPI a une communauté extraordinaire qui accueille des personnes de tous horizons.
|
||||
|
||||
## Créateur - Mainteneur
|
||||
|
||||
Salut! 👋
|
||||
|
||||
C'est moi :
|
||||
|
||||
{% if people %}
|
||||
<div class="user-list user-list-center">
|
||||
{% for user in people.maintainers %}
|
||||
|
||||
<div class="user"><a href="{{ user.url }}" target="_blank"><div class="avatar-wrapper"><img src="{{ user.avatarUrl }}"/></div><div class="title">@{{ user.login }}</div></a> <div class="count">Réponses: {{ user.answers }}</div><div class="count">Pull Requests: {{ user.prs }}</div></div>
|
||||
{% endfor %}
|
||||
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
Je suis le créateur et le responsable de **FastAPI**. Vous pouvez en lire plus à ce sujet dans [Aide FastAPI - Obtenir de l'aide - Se rapprocher de l'auteur](help-fastapi.md#connect-with-the-author){.internal-link target=_blank}.
|
||||
|
||||
...Mais ici, je veux vous montrer la communauté.
|
||||
|
||||
---
|
||||
|
||||
**FastAPI** reçoit beaucoup de soutien de la part de la communauté. Et je tiens à souligner leurs contributions.
|
||||
|
||||
Ce sont ces personnes qui :
|
||||
|
||||
* [Aident les autres à résoudre des problèmes (questions) dans GitHub](help-fastapi.md#help-others-with-issues-in-github){.internal-link target=_blank}.
|
||||
* [Créent des Pull Requests](help-fastapi.md#create-a-pull-request){.internal-link target=_blank}.
|
||||
* Review les Pull Requests, [particulièrement important pour les traductions](contributing.md#translations){.internal-link target=_blank}.
|
||||
|
||||
Une salve d'applaudissements pour eux. 👏 🙇
|
||||
|
||||
## Utilisateurs les plus actifs le mois dernier
|
||||
|
||||
Ce sont les utilisateurs qui ont [aidé le plus les autres avec des problèmes (questions) dans GitHub](help-fastapi.md#help-others-with-issues-in-github){.internal-link target=_blank} au cours du dernier mois. ☕
|
||||
|
||||
{% if people %}
|
||||
<div class="user-list user-list-center">
|
||||
{% for user in people.last_month_active %}
|
||||
|
||||
<div class="user"><a href="{{ user.url }}" target="_blank"><div class="avatar-wrapper"><img src="{{ user.avatarUrl }}"/></div><div class="title">@{{ user.login }}</div></a> <div class="count">Questions répondues: {{ user.count }}</div></div>
|
||||
{% endfor %}
|
||||
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
## Experts
|
||||
|
||||
Voici les **Experts FastAPI**. 🤓
|
||||
|
||||
Ce sont les utilisateurs qui ont [aidé le plus les autres avec des problèmes (questions) dans GitHub](help-fastapi.md#help-others-with-issues-in-github){.internal-link target=_blank} depuis *toujours*.
|
||||
|
||||
Ils ont prouvé qu'ils étaient des experts en aidant beaucoup d'autres personnes. ✨
|
||||
|
||||
{% if people %}
|
||||
<div class="user-list user-list-center">
|
||||
{% for user in people.experts %}
|
||||
|
||||
<div class="user"><a href="{{ user.url }}" target="_blank"><div class="avatar-wrapper"><img src="{{ user.avatarUrl }}"/></div><div class="title">@{{ user.login }}</div></a> <div class="count">Questions répondues: {{ user.count }}</div></div>
|
||||
{% endfor %}
|
||||
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
## Principaux contributeurs
|
||||
|
||||
Ces utilisateurs sont les **Principaux contributeurs**. 👷
|
||||
|
||||
Ces utilisateurs ont [créé le plus grand nombre de demandes Pull Request](help-fastapi.md#create-a-pull-request){.internal-link target=_blank} qui ont été *merged*.
|
||||
|
||||
Ils ont contribué au code source, à la documentation, aux traductions, etc. 📦
|
||||
|
||||
{% if people %}
|
||||
<div class="user-list user-list-center">
|
||||
{% for user in people.top_contributors %}
|
||||
|
||||
<div class="user"><a href="{{ user.url }}" target="_blank"><div class="avatar-wrapper"><img src="{{ user.avatarUrl }}"/></div><div class="title">@{{ user.login }}</div></a> <div class="count">Pull Requests: {{ user.count }}</div></div>
|
||||
{% endfor %}
|
||||
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
Il existe de nombreux autres contributeurs (plus d'une centaine), vous pouvez les voir tous dans la <a href="https://github.com/tiangolo/fastapi/graphs/contributors" class="external-link" target="_blank">Page des contributeurs de FastAPI GitHub</a>. 👷
|
||||
|
||||
## Principaux Reviewers
|
||||
|
||||
Ces utilisateurs sont les **Principaux Reviewers**. 🕵️
|
||||
|
||||
### Reviewers des traductions
|
||||
|
||||
Je ne parle que quelques langues (et pas très bien 😅). Ainsi, les reviewers sont ceux qui ont le [**pouvoir d'approuver les traductions**](contributing.md#translations){.internal-link target=_blank} de la documentation. Sans eux, il n'y aurait pas de documentation dans plusieurs autres langues.
|
||||
|
||||
---
|
||||
|
||||
Les **Principaux Reviewers** 🕵️ ont examiné le plus grand nombre de demandes Pull Request des autres, assurant la qualité du code, de la documentation, et surtout, des **traductions**.
|
||||
|
||||
{% if people %}
|
||||
<div class="user-list user-list-center">
|
||||
{% for user in people.top_reviewers %}
|
||||
|
||||
<div class="user"><a href="{{ user.url }}" target="_blank"><div class="avatar-wrapper"><img src="{{ user.avatarUrl }}"/></div><div class="title">@{{ user.login }}</div></a> <div class="count">Reviews: {{ user.count }}</div></div>
|
||||
{% endfor %}
|
||||
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
## Sponsors
|
||||
|
||||
Ce sont les **Sponsors**. 😎
|
||||
|
||||
Ils soutiennent mon travail avec **FastAPI** (et d'autres) avec <a href="https://github.com/sponsors/tiangolo" class="external-link" target="_blank">GitHub Sponsors</a>.
|
||||
|
||||
{% if people %}
|
||||
<div class="user-list user-list-center">
|
||||
{% for user in people.sponsors %}
|
||||
|
||||
<div class="user"><a href="{{ user.url }}" target="_blank"><div class="avatar-wrapper"><img src="{{ user.avatarUrl }}"/></div><div class="title">@{{ user.login }}</div></a></div>
|
||||
{% endfor %}
|
||||
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
## À propos des données - détails techniques
|
||||
|
||||
L'intention de cette page est de souligner l'effort de la communauté pour aider les autres.
|
||||
|
||||
Notamment en incluant des efforts qui sont normalement moins visibles, et, dans de nombreux cas, plus difficile, comme aider d'autres personnes à résoudre des problèmes et examiner les Pull Requests de traduction.
|
||||
|
||||
Les données sont calculées chaque mois, vous pouvez lire le <a href="https://github.com/tiangolo/fastapi/blob/master/.github/actions/people/app/main.py" class="external-link" target="_blank">code source ici</a>.
|
||||
|
||||
Je me réserve également le droit de mettre à jour l'algorithme, les sections, les seuils, etc. (juste au cas où 🤷).
|
||||
201
docs/fr/docs/features.md
Normal file
@@ -0,0 +1,201 @@
|
||||
# Fonctionnalités
|
||||
|
||||
## Fonctionnalités de FastAPI
|
||||
|
||||
**FastAPI** vous offre ceci:
|
||||
|
||||
### Basé sur des standards ouverts
|
||||
|
||||
* <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank"><strong>OpenAPI</strong></a> pour la création d'API, incluant la déclaration de <abbr title="en français: routes. Aussi connu sous le nom anglais endpoints ou routes">path</abbr> <abbr title="Aussi connu sous le nom de méthodes HTTP. À savoir POST, GET, PUT, DELETE">operations</abbr>, paramètres, corps de requêtes, sécurité, etc.
|
||||
* Documentation automatique des modèles de données avec <a href="http://json-schema.org/" class="external-link" target="_blank"><strong>JSON Schema</strong></a> (comme OpenAPI est aussi basée sur JSON Schema).
|
||||
* Conçue avec ces standards après une analyse méticuleuse. Plutôt qu'en rajoutant des surcouches après coup.
|
||||
* Cela permet d'utiliser de la **génération automatique de code client** dans beaucoup de langages.
|
||||
|
||||
### Documentation automatique
|
||||
|
||||
Documentation d'API interactive et interface web d'exploration. Comme le framework est basé sur OpenAPI, de nombreuses options sont disponibles. Deux d'entre-elles sont incluses par défaut.
|
||||
|
||||
* <a href="https://github.com/swagger-api/swagger-ui" class="external-link" target="_blank"><strong>Swagger UI</strong></a>, propose une documentation interactive. Vous permet de directement tester l'API depuis votre navigateur.
|
||||
|
||||

|
||||
|
||||
* Une autre documentation d'API est fournie par <a href="https://github.com/Rebilly/ReDoc" class="external-link" target="_blank"><strong>ReDoc</strong></a>.
|
||||
|
||||

|
||||
|
||||
### Faite en python moderne
|
||||
|
||||
Tout est basé sur la déclaration de type standard de **Python 3.6** (grâce à Pydantic). Pas de nouvelles syntaxes à apprendre. Juste du Python standard et moderne.
|
||||
|
||||
Si vous souhaitez un rappel de 2 minutes sur l'utilisation des types en Python (même si vous ne comptez pas utiliser FastAPI), jetez un oeil au tutoriel suivant: [Python Types](python-types.md){.internal-link target=_blank}.
|
||||
|
||||
Vous écrivez du python standard avec des annotations de types:
|
||||
|
||||
```Python
|
||||
from typing import List, Dict
|
||||
from datetime import date
|
||||
|
||||
from pydantic import BaseModel
|
||||
|
||||
# Déclare une variable comme étant une str
|
||||
# et profitez de l'aide de votre IDE dans cette fonction
|
||||
def main(user_id: str):
|
||||
return user_id
|
||||
|
||||
|
||||
# Un modèle Pydantic
|
||||
class User(BaseModel):
|
||||
id: int
|
||||
name: str
|
||||
joined: date
|
||||
```
|
||||
Qui peuvent ensuite être utilisés comme cela:
|
||||
|
||||
```Python
|
||||
my_user: User = User(id=3, name="John Doe", joined="2018-07-19")
|
||||
|
||||
second_user_data = {
|
||||
"id": 4,
|
||||
"name": "Mary",
|
||||
"joined": "2018-11-30",
|
||||
}
|
||||
|
||||
my_second_user: User = User(**second_user_data)
|
||||
```
|
||||
|
||||
!!! info
|
||||
`**second_user_data` signifie:
|
||||
|
||||
Utilise les clés et valeurs du dictionnaire `second_user_data` directement comme des arguments clé-valeur. C'est équivalent à: `User(id=4, name="Mary", joined="2018-11-30")`
|
||||
|
||||
### Support d'éditeurs
|
||||
|
||||
Tout le framework a été conçu pour être facile et intuitif d'utilisation, toutes les décisions de design ont été testées sur de nombreux éditeurs avant même de commencer le développement final afin d'assurer la meilleure expérience de développement possible.
|
||||
|
||||
Dans le dernier sondage effectué auprès de développeurs python il était clair que <a href="https://www.jetbrains.com/research/python-developers-survey-2017/#tools-and-features" class="external-link" target="_blank">la fonctionnalité la plus utilisée est "l'autocomplètion"</a>.
|
||||
|
||||
Tout le framwork **FastAPI** a été conçu avec cela en tête. L'autocomplétion fonctionne partout.
|
||||
|
||||
Vous devrez rarement revenir à la documentation.
|
||||
|
||||
Voici comment votre éditeur peut vous aider:
|
||||
|
||||
* dans <a href="https://code.visualstudio.com/" class="external-link" target="_blank">Visual Studio Code</a>:
|
||||
|
||||

|
||||
|
||||
* dans <a href="https://www.jetbrains.com/pycharm/" class="external-link" target="_blank">PyCharm</a>:
|
||||
|
||||

|
||||
|
||||
Vous aurez des propositions de complétion que vous n'auriez jamais imaginées. Par exemple la clé `prix` dans le corps d'un document JSON (qui est peut-être imbriqué) venant d'une requête.
|
||||
|
||||
Plus jamais vous ne vous tromperez en tapant le nom d'une clé, vous ne ferez des aller-retour entre votre code et la documentation ou vous ne scrollerez de haut en bas afin d'enfin savoir si vous devez taper `username` ou `user_name`.
|
||||
|
||||
### Court
|
||||
|
||||
Des **valeurs par défaut** sont définies pour tout, des configurations optionnelles sont présentent partout. Tous ces paramètres peuvent être ajustés afin de faire ce que vous voulez et définir l'API dont vous avez besoin.
|
||||
|
||||
Mais, **tout fonctionne** par défaut.
|
||||
|
||||
### Validation
|
||||
|
||||
* Validation pour la plupart (ou tous?) les **types de données** Python incluant:
|
||||
* objets JSON (`dict`).
|
||||
* listes JSON (`list`) définissant des types d'éléments.
|
||||
* Champs String (`str`), définition de longueur minimum ou maximale.
|
||||
* Nombres (`int`, `float`) avec valeur minimale and maximale, etc.
|
||||
|
||||
* Validation pour des types plus exotiques, tel que:
|
||||
* URL.
|
||||
* Email.
|
||||
* UUID.
|
||||
* ...et autres.
|
||||
|
||||
Toutes les validations sont gérées par le bien établi et robuste **Pydantic**.
|
||||
|
||||
### Sécurité et authentification
|
||||
|
||||
La sécurité et l'authentification sont intégrées. Sans aucun compromis avec les bases de données ou les modèles de données.
|
||||
|
||||
Tous les protocoles de sécurités sont définis dans OpenAPI, incluant:
|
||||
|
||||
* HTTP Basic.
|
||||
* **OAuth2** (aussi avec **JWT tokens**). Jetez un oeil au tutoriel [OAuth2 avec JWT](tutorial/security/oauth2-jwt.md){.internal-link target=_blank}.
|
||||
* Clés d'API dans:
|
||||
* Le header.
|
||||
* Les paramètres de requêtes.
|
||||
* Les cookies, etc.
|
||||
|
||||
Plus toutes les fonctionnalités de sécurités venant de Starlette (incluant les **cookies de sessions**).
|
||||
|
||||
Le tout conçu en composant réutilisable facilement intégrable à vos systèmes, data stores, base de données relationnelle ou NoSQL, etc.
|
||||
|
||||
### Injection de dépendances
|
||||
|
||||
FastAPI contient un système simple mais extrêmement puissant d'<abbr title='aussi connus sous le nom de "composants", "ressources", "services", "providers"'><strong>Injection de Dépendances</strong></abbr>.
|
||||
|
||||
* Même les dépendances peuvent avoir des dépendances, créant une hiérarchie ou un **"graph" de dépendances**
|
||||
* Tout est **automatiquement géré** par le framework
|
||||
* Toutes les dépendances peuvent éxiger des données d'une requêtes et **Augmenter les contraintes d'un path operation** et de la documentation automatique.
|
||||
* **Validation automatique** même pour les paramètres de *path operation* définis dans les dépendances.
|
||||
* Supporte les systèmes d'authentification d'utilisateurs complexes, les **connexions de base de données**, etc.
|
||||
* **Aucun compromis** avec les bases de données, les frontends, etc. Mais une intégration facile avec n'importe lequel d'entre eux.
|
||||
|
||||
### "Plug-ins" illimités
|
||||
|
||||
Ou, en d'autres termes, pas besoin d'eux, importez le code que vous voulez et utilisez le.
|
||||
|
||||
Tout intégration est conçue pour être si simple à utiliser (avec des dépendances) que vous pouvez créer un "plug-in" pour votre application en deux lignes de code utilisant la même syntaxe que celle de vos *path operations*
|
||||
|
||||
### Testé
|
||||
|
||||
* 100% <abbr title="La quantité de code qui est testé automatiquement">de couverture de test</abbr>.
|
||||
* 100% <abbr title="Annotation de types Python, avec cela votre éditeur et autres outils externes peuvent vous fournir un meilleur support">d'annotations de type</abbr> dans le code.
|
||||
* Utilisé dans des applications mises en production.
|
||||
|
||||
## Fonctionnalités de Starlette
|
||||
|
||||
**FastAPI** est complètement compatible (et basé sur) <a href="https://www.starlette.io/" class="external-link" target="_blank"><strong>Starlette</strong></a>. Le code utilisant Starlette que vous ajouterez fonctionnera donc aussi.
|
||||
|
||||
En fait, `FastAPI` est un sous compposant de `Starlette`. Donc, si vous savez déjà comment utiliser Starlette, la plupart des fonctionnalités fonctionneront de la même manière.
|
||||
|
||||
Avec **FastAPI** vous aurez toutes les fonctionnalités de **Starlette** (FastAPI est juste Starlette sous stéroïdes):
|
||||
|
||||
* Des performances vraiments impressionnantes. C'est l'<a href="https://github.com/encode/starlette#performance" class="external-link" target="_blank">un des framework Python les plus rapide, à égalité avec **NodeJS** et **GO**</a>.
|
||||
* Le support des **WebSockets**.
|
||||
* Le support de **GraphQL**.
|
||||
* Les <abbr title="En anglais: In-process background tasks">tâches d'arrière-plan.</abbr>
|
||||
* Des évènements de démarrages et d'arrêt.
|
||||
* Un client de test basé sur `request`
|
||||
* **CORS**, GZip, Static Files, Streaming responses.
|
||||
* Le support des **Sessions et Cookies**.
|
||||
* Une couverture de test à 100 %.
|
||||
* 100 % de la base de code avec des annotations de type.
|
||||
|
||||
## Fonctionnalités de Pydantic
|
||||
|
||||
**FastAPI** est totalement compatible avec (et basé sur) <a href="https://pydantic-docs.helpmanual.io" class="external-link" target="_blank"><strong>Pydantic</strong></a>. Le code utilisant Pydantic que vous ajouterez fonctionnera donc aussi.
|
||||
|
||||
Inclus des librairies externes basées, aussi, sur Pydantic, servent d'<abbr title="Object-Relational Mapper">ORM</abbr>s, <abbr title="Object-Document Mapper">ODM</abbr>s pour les bases de données.
|
||||
|
||||
Cela signifie aussi que, dans la plupart des cas, vous pouvez fournir l'objet reçu d'une requête **directement à la base de données**, comme tout est validé automatiquement.
|
||||
|
||||
Inversément, dans la plupart des cas vous pourrez juste envoyer l'objet récupéré de la base de données **directement au client**
|
||||
|
||||
Avec **FastAPI** vous aurez toutes les fonctionnalités de **Pydantic** (comme FastAPI est basé sur Pydantic pour toutes les manipulations de données):
|
||||
|
||||
* **Pas de prise de tête**:
|
||||
* Pas de nouveau langage de définition de schéma à apprendre.
|
||||
* Si vous connaissez le typage en python vous savez comment utiliser Pydantic.
|
||||
* Aide votre **<abbr title="Integrated Development Environment, il s'agit de votre éditeur de code">IDE</abbr>/<abbr title="Programme qui analyse le code à la recherche d'erreurs">linter</abbr>/cerveau**:
|
||||
* Parce que les structures de données de pydantic consistent seulement en une instance de classe que vous définissez; l'auto-complétion, le linting, mypy et votre intuition devrait être largement suffisante pour valider vos données.
|
||||
* **Rapide**:
|
||||
* Dans les <a href="https://pydantic-docs.helpmanual.io/#benchmarks-tag" class="external-link" target="_blank">benchmarks</a> Pydantic est plus rapide que toutes les autres librairies testées.
|
||||
* Valide les **structures complexes**:
|
||||
* Utilise les modèles hiérarchique de Pydantic, le `typage` Python pour les `Lists`, `Dict`, etc.
|
||||
* Et les validateurs permettent aux schémas de données complexes d'être clairement et facilement définis, validés et documentés sous forme d'un schéma JSON.
|
||||
* Vous pouvez avoir des objets **JSON fortements imbriqués** tout en ayant, pour chacun, de la validation et des annotations.
|
||||
* **Renouvelable**:
|
||||
* Pydantic permet de définir de nouveaux types de données ou vous pouvez étendre la validation avec des méthodes sur un modèle décoré avec le<abbr title="en anglais: validator decorator"> décorateur de validation</abbr>
|
||||
* 100% de couverture de test.
|
||||
@@ -18,9 +18,6 @@
|
||||
<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>
|
||||
|
||||
---
|
||||
@@ -43,10 +40,24 @@ The key features are:
|
||||
* **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>.
|
||||
* **Standards-based**: Based on (and fully compatible with) the open standards for APIs: <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank">OpenAPI</a> (previously known as Swagger) and <a href="https://json-schema.org/" class="external-link" target="_blank">JSON Schema</a>.
|
||||
|
||||
<small>* estimation based on tests on an internal development team, building production applications.</small>
|
||||
|
||||
## Gold Sponsors
|
||||
|
||||
<!-- sponsors -->
|
||||
|
||||
{% if sponsors %}
|
||||
{% for sponsor in sponsors.gold -%}
|
||||
<a href="{{ sponsor.url }}" target="_blank" title="{{ sponsor.title }}"><img src="{{ sponsor.img }}"></a>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
<!-- /sponsors -->
|
||||
|
||||
<a href="https://fastapi.tiangolo.com/fastapi-people/#sponsors" class="external-link" target="_blank">Other sponsors</a>
|
||||
|
||||
## 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._"
|
||||
@@ -75,7 +86,7 @@ The key features are:
|
||||
|
||||
"_Honestly, what you've built looks super solid and polished. In many ways, it's what I wanted **Hug** to be - it's really inspiring to see someone build that._"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Timothy Crosley - <strong><a href="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>
|
||||
<div style="text-align: right; margin-right: 10%;">Timothy Crosley - <strong><a href="https://www.hug.rest/" target="_blank">Hug</a> creator</strong> <a href="https://news.ycombinator.com/item?id=19455465" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
@@ -116,12 +127,12 @@ $ pip install fastapi
|
||||
|
||||
</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>.
|
||||
You will also need an ASGI server, for production such as <a href="https://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
|
||||
$ pip install uvicorn[standard]
|
||||
|
||||
---> 100%
|
||||
```
|
||||
@@ -432,9 +443,9 @@ Used by Pydantic:
|
||||
|
||||
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://requests.readthedocs.io" 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://jinja.palletsprojects.com" 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).
|
||||
@@ -443,7 +454,7 @@ Used by Starlette:
|
||||
|
||||
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://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]`.
|
||||
|
||||
84
docs/fr/docs/project-generation.md
Normal file
@@ -0,0 +1,84 @@
|
||||
# Génération de projets - Modèle
|
||||
|
||||
Vous pouvez utiliser un générateur de projet pour commencer, qui réalisera pour vous la mise en place de bases côté architecture globale, sécurité, base de données et premières routes d'API.
|
||||
|
||||
Un générateur de projet fera toujours une mise en place très subjective que vous devriez modifier et adapter suivant vos besoins, mais cela reste un bon point de départ pour vos projets.
|
||||
|
||||
## Full Stack FastAPI PostgreSQL
|
||||
|
||||
GitHub : <a href="https://github.com/tiangolo/full-stack-fastapi-postgresql" class="external-link" target="_blank">https://github.com/tiangolo/full-stack-fastapi-postgresql</a>
|
||||
|
||||
### Full Stack FastAPI PostgreSQL - Fonctionnalités
|
||||
|
||||
* Intégration **Docker** complète (basée sur Docker).
|
||||
* Déploiement Docker en mode <a href="https://docs.docker.com/engine/swarm/" class="external-link" target="_blank">Swarm</a>
|
||||
* Intégration **Docker Compose** et optimisation pour développement local.
|
||||
* Serveur web Python **prêt au déploiement** utilisant Uvicorn et Gunicorn.
|
||||
* Backend Python <a href="https://github.com/tiangolo/fastapi" class="external-link" target="_blank">**FastAPI**</a> :
|
||||
* **Rapide** : Très hautes performances, comparables à **NodeJS** ou **Go** (grâce à Starlette et Pydantic).
|
||||
* **Intuitif** : Excellent support des éditeurs. <abbr title="aussi appelée auto-complétion, autocomplétion, IntelliSense...">Complétion</abbr> partout. Moins de temps passé à déboguer.
|
||||
* **Facile** : Fait pour être facile à utiliser et apprendre. Moins de temps passé à lire de la documentation.
|
||||
* **Concis** : Minimise la duplication de code. Plusieurs fonctionnalités à chaque déclaration de paramètre.
|
||||
* **Robuste** : Obtenez du code prêt pour être utilisé en production. Avec de la documentation automatique interactive.
|
||||
* **Basé sur des normes** : Basé sur (et totalement compatible avec) les normes ouvertes pour les APIs : <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank">OpenAPI</a> et <a href="https://json-schema.org/" class="external-link" target="_blank">JSON Schema</a>.
|
||||
* <a href="https://fastapi.tiangolo.com/features/" class="external-link" target="_blank">**Et bien d'autres fonctionnalités**</a> comme la validation automatique, la sérialisation, l'authentification avec OAuth2 JWT tokens, etc.
|
||||
* Hashage de **mots de passe sécurisé** par défaut.
|
||||
* Authentification par **jetons JWT**.
|
||||
* Modèles **SQLAlchemy** (indépendants des extensions Flask, afin qu'ils puissent être utilisés directement avec des *workers* Celery).
|
||||
* Modèle de démarrages basiques pour les utilisateurs (à modifier et supprimer au besoin).
|
||||
* Migrations **Alembic**.
|
||||
* **CORS** (partage des ressources entre origines multiples, ou *Cross Origin Resource Sharing*).
|
||||
* *Worker* **Celery** pouvant importer et utiliser les modèles et le code du reste du backend.
|
||||
* Tests du backend REST basés sur **Pytest**, intégrés dans Docker, pour que vous puissiez tester toutes les interactions de l'API indépendamment de la base de données. Étant exécutés dans Docker, les tests peuvent utiliser un nouvel entrepôt de données créé de zéro à chaque fois (vous pouvez donc utiliser ElasticSearch, MongoDB, CouchDB, etc. et juste tester que l'API fonctionne).
|
||||
* Intégration Python facile avec **Jupyter Kernels** pour le développement à distance ou intra-Docker avec des extensions comme Atom Hydrogen ou Visual Studio Code Jupyter.
|
||||
* Frontend **Vue** :
|
||||
* Généré avec Vue CLI.
|
||||
* Gestion de l'**Authentification JWT**.
|
||||
* Page de connexion.
|
||||
* Après la connexion, page de tableau de bord principal.
|
||||
* Tableau de bord principal avec création et modification d'utilisateurs.
|
||||
* Modification de ses propres caractéristiques utilisateur.
|
||||
* **Vuex**.
|
||||
* **Vue-router**.
|
||||
* **Vuetify** pour de magnifiques composants *material design*.
|
||||
* **TypeScript**.
|
||||
* Serveur Docker basé sur **Nginx** (configuré pour être facilement manipulé avec Vue-router).
|
||||
* Utilisation de *Docker multi-stage building*, pour ne pas avoir besoin de sauvegarder ou *commit* du code compilé.
|
||||
* Tests frontend exécutés à la compilation (pouvant être désactivés).
|
||||
* Fait aussi modulable que possible, pour pouvoir fonctionner comme tel, tout en pouvant être utilisé qu'en partie grâce à Vue CLI.
|
||||
* **PGAdmin** pour les bases de données PostgreSQL, facilement modifiable pour utiliser PHPMYAdmin ou MySQL.
|
||||
* **Flower** pour la surveillance de tâches Celery.
|
||||
* Équilibrage de charge entre le frontend et le backend avec **Traefik**, afin de pouvoir avoir les deux sur le même domaine, séparés par chemins, mais servis par différents conteneurs.
|
||||
* Intégration Traefik, comprenant la génération automatique de certificat **HTTPS** Let's Encrypt.
|
||||
* GitLab **CI** (intégration continue), comprenant des tests pour le frontend et le backend.
|
||||
|
||||
## Full Stack FastAPI Couchbase
|
||||
|
||||
GitHub : <a href="https://github.com/tiangolo/full-stack-fastapi-couchbase" class="external-link" target="_blank">https://github.com/tiangolo/full-stack-fastapi-couchbase</a>
|
||||
|
||||
⚠️ **ATTENTION** ⚠️
|
||||
|
||||
Si vous démarrez un nouveau projet de zéro, allez voir les alternatives au début de cette page.
|
||||
|
||||
Par exemple, le générateur de projet <a href="https://github.com/tiangolo/full-stack-fastapi-postgresql" class="external-link" target="_blank">Full Stack FastAPI PostgreSQL</a> peut être une meilleure alternative, étant activement maintenu et utilisé et comprenant toutes les nouvelles fonctionnalités et améliorations.
|
||||
|
||||
Vous êtes toujours libre d'utiliser le générateur basé sur Couchbase si vous le voulez, cela devrait probablement fonctionner correctement, et si vous avez déjà un projet généré en utilisant ce dernier, cela devrait fonctionner aussi (et vous l'avez déjà probablement mis à jour suivant vos besoins).
|
||||
|
||||
Vous pouvez en apprendre plus dans la documentation du dépôt GithHub.
|
||||
|
||||
## Full Stack FastAPI MongoDB
|
||||
|
||||
...viendra surement plus tard, suivant le temps que j'ai. 😅 🎉
|
||||
|
||||
## Modèles d'apprentissage automatique avec spaCy et FastAPI
|
||||
|
||||
GitHub : <a href="https://github.com/microsoft/cookiecutter-spacy-fastapi" class="external-link" target="_blank">https://github.com/microsoft/cookiecutter-spacy-fastapi</a>
|
||||
|
||||
## Modèles d'apprentissage automatique avec spaCy et FastAPI - Fonctionnalités
|
||||
|
||||
* Intégration d'un modèle NER **spaCy**.
|
||||
* Formatage de requête pour **Azure Cognitive Search**.
|
||||
* Serveur Python web **prêt à utiliser en production** utilisant Uvicorn et Gunicorn.
|
||||
* Déploiement CI/CD Kubernetes pour **Azure DevOps** (AKS).
|
||||
* **Multilangues**. Choisissez facilement l'une des langues intégrées à spaCy durant la mise en place du projet.
|
||||
* **Facilement généralisable** à d'autres bibliothèques similaires (Pytorch, Tensorflow), et non juste spaCy.
|
||||
314
docs/fr/docs/python-types.md
Normal file
@@ -0,0 +1,314 @@
|
||||
# Introduction aux Types Python
|
||||
|
||||
Python supporte des annotations de type (ou *type hints*) optionnelles.
|
||||
|
||||
Ces annotations de type constituent une syntaxe spéciale qui permet de déclarer le <abbr title="par exemple : str, int, float, bool">type</abbr> d'une variable.
|
||||
|
||||
En déclarant les types de vos variables, cela permet aux différents outils comme les éditeurs de texte d'offrir un meilleur support.
|
||||
|
||||
Ce chapitre n'est qu'un **tutoriel rapide / rappel** sur les annotations de type Python.
|
||||
Seulement le minimum nécessaire pour les utiliser avec **FastAPI** sera couvert... ce qui est en réalité très peu.
|
||||
|
||||
**FastAPI** est totalement basé sur ces annotations de type, qui lui donnent de nombreux avantages.
|
||||
|
||||
Mais même si vous n'utilisez pas ou n'utiliserez jamais **FastAPI**, vous pourriez bénéficier d'apprendre quelques choses sur ces dernières.
|
||||
|
||||
!!! note
|
||||
Si vous êtes un expert Python, et que vous savez déjà **tout** sur les annotations de type, passez au chapitre suivant.
|
||||
|
||||
## Motivations
|
||||
|
||||
Prenons un exemple simple :
|
||||
|
||||
```Python
|
||||
{!../../../docs_src/python_types/tutorial001.py!}
|
||||
```
|
||||
|
||||
Exécuter ce programe affiche :
|
||||
|
||||
```
|
||||
John Doe
|
||||
```
|
||||
|
||||
La fonction :
|
||||
|
||||
* Prend un `first_name` et un `last_name`.
|
||||
* Convertit la première lettre de chaque paramètre en majuscules grâce à `title()`.
|
||||
* Concatène les résultats avec un espace entre les deux.
|
||||
|
||||
```Python hl_lines="2"
|
||||
{!../../../docs_src/python_types/tutorial001.py!}
|
||||
```
|
||||
|
||||
### Limitations
|
||||
|
||||
C'est un programme très simple.
|
||||
|
||||
Mais maintenant imaginez que vous l'écriviez de zéro.
|
||||
|
||||
À un certain point vous auriez commencé la définition de la fonction, vous aviez les paramètres prêts.
|
||||
|
||||
Mais vous aviez besoin de "cette méthode qui convertit la première lettre en majuscule".
|
||||
|
||||
Était-ce `upper` ? `uppercase` ? `first_uppercase` ? `capitalize` ?
|
||||
|
||||
Vous essayez donc d'utiliser le vieil ami du programmeur, l'auto-complétion de l'éditeur.
|
||||
|
||||
Vous écrivez le premier paramètre, `first_name`, puis un point (`.`) et appuyez sur `Ctrl+Espace` pour déclencher l'auto-complétion.
|
||||
|
||||
Mais malheureusement, rien d'utile n'en résulte :
|
||||
|
||||
<img src="/img/python-types/image01.png">
|
||||
|
||||
### Ajouter des types
|
||||
|
||||
Modifions une seule ligne de la version précédente.
|
||||
|
||||
Nous allons changer seulement cet extrait, les paramètres de la fonction, de :
|
||||
|
||||
|
||||
```Python
|
||||
first_name, last_name
|
||||
```
|
||||
|
||||
à :
|
||||
|
||||
```Python
|
||||
first_name: str, last_name: str
|
||||
```
|
||||
|
||||
C'est tout.
|
||||
|
||||
Ce sont des annotations de types :
|
||||
|
||||
```Python hl_lines="1"
|
||||
{!../../../docs_src/python_types/tutorial002.py!}
|
||||
```
|
||||
|
||||
À ne pas confondre avec la déclaration de valeurs par défaut comme ici :
|
||||
|
||||
```Python
|
||||
first_name="john", last_name="doe"
|
||||
```
|
||||
|
||||
C'est une chose différente.
|
||||
|
||||
On utilise un deux-points (`:`), et pas un égal (`=`).
|
||||
|
||||
Et ajouter des annotations de types ne crée normalement pas de différence avec le comportement qui aurait eu lieu si elles n'étaient pas là.
|
||||
|
||||
Maintenant, imaginez que vous êtes en train de créer cette fonction, mais avec des annotations de type cette fois.
|
||||
|
||||
Au même moment que durant l'exemple précédent, vous essayez de déclencher l'auto-complétion et vous voyez :
|
||||
|
||||
<img src="/img/python-types/image02.png">
|
||||
|
||||
Vous pouvez donc dérouler les options jusqu'à trouver la méthode à laquelle vous pensiez.
|
||||
|
||||
<img src="/img/python-types/image03.png">
|
||||
|
||||
## Plus de motivations
|
||||
|
||||
Cette fonction possède déjà des annotations de type :
|
||||
|
||||
```Python hl_lines="1"
|
||||
{!../../../docs_src/python_types/tutorial003.py!}
|
||||
```
|
||||
|
||||
Comme l'éditeur connaît le type des variables, vous n'avez pas seulement l'auto-complétion, mais aussi de la détection d'erreurs :
|
||||
|
||||
<img src="/img/python-types/image04.png">
|
||||
|
||||
Maintenant que vous avez connaissance du problème, convertissez `age` en <abbr title="string">chaine de caractères</abbr> grâce à `str(age)` :
|
||||
|
||||
```Python hl_lines="2"
|
||||
{!../../../docs_src/python_types/tutorial004.py!}
|
||||
```
|
||||
|
||||
## Déclarer des types
|
||||
|
||||
Vous venez de voir là où les types sont généralement déclarés : dans les paramètres de fonctions.
|
||||
|
||||
C'est aussi ici que vous les utiliseriez avec **FastAPI**.
|
||||
|
||||
### Types simples
|
||||
|
||||
Vous pouvez déclarer tous les types de Python, pas seulement `str`.
|
||||
|
||||
Comme par exemple :
|
||||
|
||||
* `int`
|
||||
* `float`
|
||||
* `bool`
|
||||
* `bytes`
|
||||
|
||||
```Python hl_lines="1"
|
||||
{!../../../docs_src/python_types/tutorial005.py!}
|
||||
```
|
||||
|
||||
### Types génériques avec des paramètres de types
|
||||
|
||||
Il existe certaines structures de données qui contiennent d'autres valeurs, comme `dict`, `list`, `set` et `tuple`. Et les valeurs internes peuvent elles aussi avoir leurs propres types.
|
||||
|
||||
Pour déclarer ces types et les types internes, on utilise le module standard de Python `typing`.
|
||||
|
||||
Il existe spécialement pour supporter ces annotations de types.
|
||||
|
||||
#### `List`
|
||||
|
||||
Par exemple, définissons une variable comme `list` de `str`.
|
||||
|
||||
Importez `List` (avec un `L` majuscule) depuis `typing`.
|
||||
|
||||
```Python hl_lines="1"
|
||||
{!../../../docs_src/python_types/tutorial006.py!}
|
||||
```
|
||||
|
||||
Déclarez la variable, en utilisant la syntaxe des deux-points (`:`).
|
||||
|
||||
Et comme type, mettez `List`.
|
||||
|
||||
Les listes étant un type contenant des types internes, mettez ces derniers entre crochets (`[`, `]`) :
|
||||
|
||||
```Python hl_lines="4"
|
||||
{!../../../docs_src/python_types/tutorial006.py!}
|
||||
```
|
||||
|
||||
!!! tip "Astuce"
|
||||
Ces types internes entre crochets sont appelés des "paramètres de type".
|
||||
|
||||
Ici, `str` est un paramètre de type passé à `List`.
|
||||
|
||||
Ce qui signifie : "la variable `items` est une `list`, et chacun de ses éléments a pour type `str`.
|
||||
|
||||
En faisant cela, votre éditeur pourra vous aider, même pendant que vous traitez des éléments de la liste.
|
||||
|
||||
<img src="/img/python-types/image05.png">
|
||||
|
||||
Sans types, c'est presque impossible à réaliser.
|
||||
|
||||
Vous remarquerez que la variable `item` n'est qu'un des éléments de la list `items`.
|
||||
|
||||
Et pourtant, l'éditeur sait qu'elle est de type `str` et pourra donc vous aider à l'utiliser.
|
||||
|
||||
#### `Tuple` et `Set`
|
||||
|
||||
C'est le même fonctionnement pour déclarer un `tuple` ou un `set` :
|
||||
|
||||
```Python hl_lines="1 4"
|
||||
{!../../../docs_src/python_types/tutorial007.py!}
|
||||
```
|
||||
|
||||
Dans cet exemple :
|
||||
|
||||
* La variable `items_t` est un `tuple` avec 3 éléments, un `int`, un deuxième `int`, et un `str`.
|
||||
* La variable `items_s` est un `set`, et chacun de ses éléments est de type `bytes`.
|
||||
|
||||
#### `Dict`
|
||||
|
||||
Pour définir un `dict`, il faut lui passer 2 paramètres, séparés par une virgule (`,`).
|
||||
|
||||
Le premier paramètre de type est pour les clés et le second pour les valeurs du dictionnaire (`dict`).
|
||||
|
||||
```Python hl_lines="1 4"
|
||||
{!../../../docs_src/python_types/tutorial008.py!}
|
||||
```
|
||||
|
||||
Dans cet exemple :
|
||||
|
||||
* La variable `prices` est de type `dict` :
|
||||
* Les clés de ce dictionnaire sont de type `str`.
|
||||
* Les valeurs de ce dictionnaire sont de type `float`.
|
||||
|
||||
#### `Optional`
|
||||
|
||||
Vous pouvez aussi utiliser `Optional` pour déclarer qu'une variable a un type, comme `str` mais qu'il est "optionnel" signifiant qu'il pourrait aussi être `None`.
|
||||
|
||||
```Python hl_lines="1 4"
|
||||
{!../../../docs_src/python_types/tutorial009.py!}
|
||||
```
|
||||
|
||||
Utiliser `Optional[str]` plutôt que `str` permettra à l'éditeur de vous aider à détecter les erreurs où vous supposeriez qu'une valeur est toujours de type `str`, alors qu'elle pourrait aussi être `None`.
|
||||
|
||||
#### Types génériques
|
||||
|
||||
Les types qui peuvent contenir des paramètres de types entre crochets, comme :
|
||||
|
||||
* `List`
|
||||
* `Tuple`
|
||||
* `Set`
|
||||
* `Dict`
|
||||
* `Optional`
|
||||
* ...et d'autres.
|
||||
|
||||
sont appelés des **types génériques** ou **Generics**.
|
||||
|
||||
### Classes en tant que types
|
||||
|
||||
Vous pouvez aussi déclarer une classe comme type d'une variable.
|
||||
|
||||
Disons que vous avez une classe `Person`, avec une variable `name` :
|
||||
|
||||
```Python hl_lines="1-3"
|
||||
{!../../../docs_src/python_types/tutorial010.py!}
|
||||
```
|
||||
|
||||
Vous pouvez ensuite déclarer une variable de type `Person` :
|
||||
|
||||
```Python hl_lines="6"
|
||||
{!../../../docs_src/python_types/tutorial010.py!}
|
||||
```
|
||||
|
||||
Et vous aurez accès, encore une fois, au support complet offert par l'éditeur :
|
||||
|
||||
<img src="/img/python-types/image06.png">
|
||||
|
||||
## Les modèles Pydantic
|
||||
|
||||
<a href="https://pydantic-docs.helpmanual.io/" class="external-link" target="_blank">Pydantic</a> est une bibliothèque Python pour effectuer de la validation de données.
|
||||
|
||||
Vous déclarez la forme de la donnée avec des classes et des attributs.
|
||||
|
||||
Chaque attribut possède un type.
|
||||
|
||||
Puis vous créez une instance de cette classe avec certaines valeurs et **Pydantic** validera les valeurs, les convertira dans le type adéquat (si c'est nécessaire et possible) et vous donnera un objet avec toute la donnée.
|
||||
|
||||
Ainsi, votre éditeur vous offrira un support adapté pour l'objet résultant.
|
||||
|
||||
Extrait de la documentation officielle de **Pydantic** :
|
||||
|
||||
```Python
|
||||
{!../../../docs_src/python_types/tutorial011.py!}
|
||||
```
|
||||
|
||||
!!! info
|
||||
Pour en savoir plus à propos de <a href="https://pydantic-docs.helpmanual.io/" class="external-link" target="_blank">Pydantic, allez jeter un coup d'oeil à sa documentation</a>.
|
||||
|
||||
**FastAPI** est basé entièrement sur **Pydantic**.
|
||||
|
||||
Vous verrez bien plus d'exemples de son utilisation dans [Tutoriel - Guide utilisateur](tutorial/index.md){.internal-link target=_blank}.
|
||||
|
||||
## Les annotations de type dans **FastAPI**
|
||||
|
||||
**FastAPI** utilise ces annotations pour faire différentes choses.
|
||||
|
||||
Avec **FastAPI**, vous déclarez des paramètres grâce aux annotations de types et vous obtenez :
|
||||
|
||||
* **du support de l'éditeur**
|
||||
* **de la vérification de types**
|
||||
|
||||
...et **FastAPI** utilise ces mêmes déclarations pour :
|
||||
|
||||
* **Définir les prérequis** : depuis les paramètres de chemins des requêtes, les entêtes, les corps, les dépendances, etc.
|
||||
* **Convertir des données** : depuis la requête vers les types requis.
|
||||
* **Valider des données** : venant de chaque requête :
|
||||
* Générant automatiquement des **erreurs** renvoyées au client quand la donnée est invalide.
|
||||
* **Documenter** l'API avec OpenAPI :
|
||||
* ce qui ensuite utilisé par les interfaces utilisateur automatiques de documentation interactive.
|
||||
|
||||
Tout cela peut paraître bien abstrait, mais ne vous inquiétez pas, vous verrez tout ça en pratique dans [Tutoriel - Guide utilisateur](tutorial/index.md){.internal-link target=_blank}.
|
||||
|
||||
Ce qu'il faut retenir c'est qu'en utilisant les types standard de Python, à un seul endroit (plutôt que d'ajouter plus de classes, de décorateurs, etc.), **FastAPI** fera une grande partie du travail pour vous.
|
||||
|
||||
!!! info
|
||||
Si vous avez déjà lu le tutoriel et êtes revenus ici pour voir plus sur les types, une bonne ressource est la <a href="https://mypy.readthedocs.io/en/latest/cheat_sheet_py3.html" class="external-link" target="_blank">"cheat sheet" de `mypy`</a>.
|
||||
94
docs/fr/docs/tutorial/background-tasks.md
Normal file
@@ -0,0 +1,94 @@
|
||||
# Tâches d'arrière-plan
|
||||
|
||||
Vous pouvez définir des tâches d'arrière-plan qui seront exécutées après avoir retourné une réponse.
|
||||
|
||||
Ceci est utile pour les opérations qui doivent avoir lieu après une requête, mais où le client n'a pas réellement besoin d'attendre que l'opération soit terminée pour recevoir une réponse.
|
||||
|
||||
Cela comprend, par exemple :
|
||||
|
||||
* Les notifications par email envoyées après l'exécution d'une action :
|
||||
* Étant donné que se connecter à un serveur et envoyer un email a tendance à être «lent» (plusieurs secondes), vous pouvez retourner la réponse directement et envoyer la notification en arrière-plan.
|
||||
* Traiter des données :
|
||||
* Par exemple, si vous recevez un fichier qui doit passer par un traitement lent, vous pouvez retourner une réponse «Accepted» (HTTP 202) puis faire le traitement en arrière-plan.
|
||||
|
||||
|
||||
## Utiliser `BackgroundTasks`
|
||||
|
||||
Pour commencer, importez `BackgroundTasks` et définissez un paramètre dans votre *fonction de chemin* avec `BackgroundTasks` comme type déclaré.
|
||||
|
||||
```Python hl_lines="1 13"
|
||||
{!../../../docs_src/background_tasks/tutorial001.py!}
|
||||
```
|
||||
|
||||
**FastAPI** créera l'objet de type `BackgroundTasks` pour vous et le passera comme paramètre.
|
||||
|
||||
## Créer une fonction de tâche
|
||||
|
||||
Une fonction à exécuter comme tâche d'arrière-plan est juste une fonction standard qui peut recevoir des paramètres.
|
||||
|
||||
Elle peut être une fonction asynchrone (`async def`) ou une fonction normale (`def`), **FastAPI** saura la gérer correctement.
|
||||
|
||||
Dans cet exemple, la fonction de tâche écrira dans un fichier (afin de simuler un envoi d'email).
|
||||
|
||||
L'opération d'écriture n'utilisant ni `async` ni `await`, on définit la fonction avec un `def` normal.
|
||||
|
||||
```Python hl_lines="6-9"
|
||||
{!../../../docs_src/background_tasks/tutorial001.py!}
|
||||
```
|
||||
|
||||
## Ajouter une tâche d'arrière-plan
|
||||
|
||||
Dans votre *fonction de chemin*, passez votre fonction de tâche à l'objet de type `BackgroundTasks` (`background_tasks` ici) grâce à la méthode `.add_task()` :
|
||||
|
||||
|
||||
```Python hl_lines="14"
|
||||
{!../../../docs_src/background_tasks/tutorial001.py!}
|
||||
```
|
||||
|
||||
`.add_task()` reçoit comme arguments :
|
||||
|
||||
* Une fonction de tâche à exécuter en arrière-plan (`write_notification`).
|
||||
* Les arguments positionnels à passer à la fonction de tâche dans l'ordre (`email`).
|
||||
* Les arguments nommés à passer à la fonction de tâche (`message="some notification"`).
|
||||
|
||||
## Injection de dépendances
|
||||
|
||||
Utiliser `BackgroundTasks` fonctionne aussi avec le système d'injection de dépendances. Vous pouvez déclarer un paramètre de type `BackgroundTasks` à différents niveaux : dans une *fonction de chemin*, dans une dépendance, dans une sous-dépendance...
|
||||
|
||||
**FastAPI** sait quoi faire dans chaque cas et comment réutiliser le même objet, afin que tous les paramètres de type `BackgroundTasks` soient fusionnés et que les tâches soient exécutées en arrière-plan :
|
||||
|
||||
```Python hl_lines="13 15 22 25"
|
||||
{!../../../docs_src/background_tasks/tutorial002.py!}
|
||||
```
|
||||
|
||||
Dans cet exemple, les messages seront écrits dans le fichier `log.txt` après que la réponse soit envoyée.
|
||||
|
||||
S'il y avait une `query` (paramètre nommé `q`) dans la requête, alors elle sera écrite dans `log.txt` via une tâche d'arrière-plan.
|
||||
|
||||
Et ensuite une autre tâche d'arrière-plan (générée dans les paramètres de la *la fonction de chemin*) écrira un message dans `log.txt` comprenant le paramètre de chemin `email`.
|
||||
|
||||
## Détails techniques
|
||||
|
||||
La classe `BackgroundTasks` provient directement de <a href="https://www.starlette.io/background/" class="external-link" target="_blank">`starlette.background`</a>.
|
||||
|
||||
Elle est importée/incluse directement dans **FastAPI** pour que vous puissiez l'importer depuis `fastapi` et éviter d'importer accidentellement `BackgroundTask` (sans `s` à la fin) depuis `starlette.background`.
|
||||
|
||||
En utilisant seulement `BackgroundTasks` (et non `BackgroundTask`), il est possible de l'utiliser en tant que paramètre de *fonction de chemin* et de laisser **FastAPI** gérer le reste pour vous, comme en utilisant l'objet `Request` directement.
|
||||
|
||||
Il est tout de même possible d'utiliser `BackgroundTask` seul dans **FastAPI**, mais dans ce cas il faut créer l'objet dans le code et renvoyer une `Response` Starlette l'incluant.
|
||||
|
||||
Plus de détails sont disponibles dans <a href="https://www.starlette.io/background/" class="external-link" target="_blank">la documentation officielle de Starlette sur les tâches d'arrière-plan</a> (via leurs classes `BackgroundTasks`et `BackgroundTask`).
|
||||
|
||||
## Avertissement
|
||||
|
||||
Si vous avez besoin de réaliser des traitements lourds en tâche d'arrière-plan et que vous n'avez pas besoin que ces traitements aient lieu dans le même process (par exemple, pas besoin de partager la mémoire, les variables, etc.), il peut s'avérer profitable d'utiliser des outils plus importants tels que <a href="https://docs.celeryproject.org" class="external-link" target="_blank">Celery</a>.
|
||||
|
||||
Ces outils nécessitent généralement des configurations plus complexes ainsi qu'un gestionnaire de queue de message, comme RabbitMQ ou Redis, mais ils permettent d'exécuter des tâches d'arrière-plan dans différents process, et potentiellement, sur plusieurs serveurs.
|
||||
|
||||
Pour voir un exemple, allez voir les [Générateurs de projets](../project-generation.md){.internal-link target=_blank}, ils incluent tous Celery déjà configuré.
|
||||
|
||||
Mais si vous avez besoin d'accéder aux variables et objets de la même application **FastAPI**, ou si vous avez besoin d'effectuer de petites tâches d'arrière-plan (comme envoyer des notifications par email), vous pouvez simplement vous contenter d'utiliser `BackgroundTasks`.
|
||||
|
||||
## Résumé
|
||||
|
||||
Importez et utilisez `BackgroundTasks` grâce aux paramètres de *fonction de chemin* et les dépendances pour ajouter des tâches d'arrière-plan.
|
||||