Compare commits

..

216 Commits

Author SHA1 Message Date
Sebastián Ramírez
9090c771ee 🔖 Release version 0.76.0 2022-05-05 17:26:05 -05:00
Sebastián Ramírez
8df8b037f2 📝 Update release notes 2022-05-05 17:25:14 -05:00
github-actions
792285a047 📝 Update release notes 2022-05-05 22:22:57 +00:00
github-actions[bot]
66f6344820 👥 Update FastAPI People (#4847)
Co-authored-by: github-actions <github-actions@github.com>
2022-05-05 17:22:25 -05:00
github-actions
b44e85ca8a 📝 Update release notes 2022-05-05 22:20:33 +00:00
Marcelo Trylesinski
33d61430cf ⬆ Upgrade Starlette from 0.17.1 to 0.18.0 (#4483)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2022-05-05 17:19:59 -05:00
github-actions
146f57b8f7 📝 Update release notes 2022-04-25 10:02:17 +00:00
Sebastián Ramírez
1920c3dd16 🔧 Add Budget Insight sponsor (#4824) 2022-04-25 10:01:39 +00:00
github-actions
07b12c8e41 📝 Update release notes 2022-04-24 15:53:04 +00:00
Sebastián Ramírez
4642d5bb86 🍱 Update sponsor, ExoFlare badge (#4822) 2022-04-24 15:52:31 +00:00
github-actions
0fd99ec337 📝 Update release notes 2022-04-24 15:31:48 +00:00
Sebastián Ramírez
7c8383c96b 🔧 Update sponsors, enable Dropbase again, update TalkPython link (#4821) 2022-04-24 17:31:12 +02:00
Sebastián Ramírez
2b54432a9c 🔖 Release version 0.75.2 2022-04-17 23:08:37 +02:00
Sebastián Ramírez
acd2287b57 📝 Update release notes 2022-04-17 23:07:27 +02:00
github-actions
1d106bd959 📝 Update release notes 2022-04-17 21:01:21 +00:00
Sebastián Ramírez
77fc14eb69 🔧 Update sponsors, add: ExoFlare, Ines Course; remove: Dropbase, Vim.so, Calmcode; update: Striveworks, TalkPython and TestDriven.io (#4805) 2022-04-17 23:00:49 +02:00
github-actions
41d75b6d1c 📝 Update release notes 2022-04-17 20:56:09 +00:00
Sebastián Ramírez
ddd9da3db4 Fix new/recent tests with new fixed ValidationError JSON Schema (#4806) 2022-04-17 20:55:36 +00:00
Sebastián Ramírez
197c1d6dd7 📝 Update release notes 2022-04-17 21:02:49 +02:00
github-actions
d9e7a541fd 📝 Update release notes 2022-04-17 17:42:18 +00:00
dconathan
c449ae5c74 🐛 Fix JSON Schema for ValidationError at field loc (#3810)
Co-authored-by: Devin Conathan <dconatha@amfam.com>
2022-04-17 19:41:46 +02:00
github-actions
1d8d81a6d5 📝 Update release notes 2022-04-17 17:22:26 +00:00
Marcelo Trylesinski
d81c908132 🐛 Fix support for prefix on APIRouter WebSockets (#2640)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2022-04-17 19:21:53 +02:00
github-actions
cb4da93643 📝 Update release notes 2022-04-17 16:18:35 +00:00
Sebastián Ramírez
3cbfae16cf ⬆️ Update ujson ranges for CVE-2021-45958 (#4804) 2022-04-17 16:17:59 +00:00
github-actions
0def8382b8 📝 Update release notes 2022-04-17 15:52:12 +00:00
Sebastián Ramírez
02fae6a38e ⬆️ Upgrade dependencies upper range for extras "all" (#4803) 2022-04-17 15:51:42 +00:00
Sebastián Ramírez
75af472029 📝 Update release notes 2022-04-17 16:55:37 +02:00
github-actions
e1135eddb5 📝 Update release notes 2022-04-17 14:47:55 +00:00
Alan Wright
acf8a91c25 ⬆ Upgrade Swagger UI - swagger-ui-dist@4 (#4347)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2022-04-17 14:47:14 +00:00
github-actions
c4f361c0c4 📝 Update release notes 2022-04-16 08:18:43 +00:00
Sebastián Ramírez
cc57bfcf60 ⬆️ Upgrade Codecov GitHub Action (#4801) 2022-04-16 08:18:08 +00:00
Sebastián Ramírez
26f725d259 🔖 Release version 0.75.1 2022-04-01 18:05:52 -05:00
Sebastián Ramírez
9e018c322c 📝 Update release notes 2022-04-01 18:05:06 -05:00
github-actions
3fefc83d42 📝 Update release notes 2022-04-01 23:02:53 +00:00
github-actions
2c31667407 📝 Update release notes 2022-04-01 23:02:28 +00:00
github-actions[bot]
233214795a 👥 Update FastAPI People (#4752)
Co-authored-by: github-actions <github-actions@github.com>
2022-04-01 18:02:17 -05:00
Sebastián Ramírez
e1d0e3874b Temporarily remove typer-cli from dependencies and upgrade Black (#4754) 2022-04-01 23:01:51 +00:00
github-actions
eddbae948f 📝 Update release notes 2022-03-18 16:48:49 +00:00
Sebastián Ramírez
5c842586c2 🌐 Start Dutch translations (#4703) 2022-03-18 16:47:54 +00:00
github-actions
fc96370ce3 📝 Update release notes 2022-03-18 16:37:49 +00:00
Sebastián Ramírez
d820267cde 🔧 Add configuration to notify Dutch translations (#4702) 2022-03-18 16:37:14 +00:00
github-actions
bd94d313c9 📝 Update release notes 2022-03-18 16:24:54 +00:00
Amin Alaee
2b6f1585ec 🌐 Start Persian/Farsi translations (#4243)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2022-03-18 16:24:19 +00:00
github-actions
bab5c201da 📝 Update release notes 2022-03-17 20:25:09 +00:00
Sarmast Bilawal Khuhro
aec2d26bac ✏ Reword sentence about handling errors (#1993)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2022-03-17 20:24:34 +00:00
github-actions
d5d6eebd40 📝 Update release notes 2022-03-17 20:20:21 +00:00
github-actions[bot]
7982aa5143 👥 Update FastAPI People (#4699)
Co-authored-by: github-actions <github-actions@github.com>
2022-03-17 15:19:43 -05:00
github-actions
fd6ce67392 📝 Update release notes 2022-03-17 18:36:57 +00:00
Sebastián Ramírez
d3eb787090 🐛 Fix FastAPI People generation to include missing file in commit (#4695) 2022-03-17 18:36:21 +00:00
github-actions
6125dc72cd 📝 Update release notes 2022-03-15 15:48:22 +00:00
Sebastián Ramírez
cf8b40e660 🔧 Update Classiq sponsor links (#4688) 2022-03-15 15:47:36 +00:00
github-actions
fab2a765de 📝 Update release notes 2022-03-10 02:30:13 +00:00
Sebastián Ramírez
9aa698aa67 🔧 Add Classiq sponsor (#4671) 2022-03-09 21:29:40 -05:00
Sebastián Ramírez
87e29ec2c5 📝 Update release notes 2022-03-05 19:52:18 +01:00
github-actions
abd148f63a 📝 Update release notes 2022-03-05 18:49:46 +00:00
Sebastián Ramírez
9f38a05954 📝 Add Jina's QA Bot to the docs to help people that want to ask quick questions (#4655)
Co-authored-by: yanlong.wang <yanlong.wang@naiver.org>
2022-03-05 19:49:15 +01:00
Sebastián Ramírez
c89dc736bd 📝 Update release notes 2022-03-04 23:11:21 +01:00
Sebastián Ramírez
19769d0483 🔖 Release version 0.75.0 2022-03-04 23:09:11 +01:00
Sebastián Ramírez
586d17bfb5 📝 Update release notes 2022-03-04 23:08:06 +01:00
github-actions
786b5858e5 📝 Update release notes 2022-03-04 22:02:55 +00:00
Sebastián Ramírez
8a0d4c79c1 Add support for custom generate_unique_id_function and docs for generating clients (#4650) 2022-03-04 23:02:18 +01:00
Sebastián Ramírez
440d2d2d1a 🔖 Release version 0.74.1 2022-02-21 16:54:18 +01:00
github-actions
e953059054 📝 Update release notes 2022-02-21 15:52:03 +00:00
Sebastián Ramírez
f5d7df3c6c Include route in scope to allow middleware and other tools to extract its information (#4603) 2022-02-21 16:51:26 +01:00
Sebastián Ramírez
1ce16c2f40 🔖 Release version 0.74.0 2022-02-17 17:08:23 +01:00
Sebastián Ramírez
03d4d4c38e 📝 Update release notes 2022-02-17 17:05:38 +01:00
github-actions
2d2f1dee5d 📝 Update release notes 2022-02-17 14:18:35 +00:00
Sebastián Ramírez
59e36481dc 🔧 Add Striveworks sponsor (#4596) 2022-02-17 14:18:01 +00:00
github-actions
4fcb00328c 📝 Update release notes 2022-02-17 12:40:46 +00:00
Sebastián Ramírez
9d56a3cb59 Update internal AsyncExitStack to fix context for dependencies with yield (#4575) 2022-02-17 13:40:12 +01:00
github-actions
78b07cb809 📝 Update release notes 2022-02-13 17:19:09 +00:00
Sebastián Ramírez
6034f80687 💚 Only build docs on push when on master to avoid duplicate runs from PRs (#4564) 2022-02-13 18:18:38 +01:00
github-actions
b93f8a709a 📝 Update release notes 2022-02-01 14:28:16 +00:00
github-actions[bot]
618c99d774 👥 Update FastAPI People (#4502)
Co-authored-by: github-actions <github-actions@github.com>
2022-02-01 15:27:34 +01:00
Sebastián Ramírez
291180bf2d 🔖 Release version 0.73.0 2022-01-23 23:38:51 +01:00
Sebastián Ramírez
cbe8d552c1 📝 Update release notes 2022-01-23 23:37:48 +01:00
github-actions
af18d5c49f 📝 Update release notes 2022-01-23 22:14:28 +00:00
Victor Benichoux
a698908ed6 🐛 Fix bug preventing to use OpenAPI when using tuples (#3874)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2022-01-23 23:13:55 +01:00
github-actions
dba9ea8120 📝 Update release notes 2022-01-23 21:31:08 +00:00
Sebastián Ramírez
f8d4d04015 📝 Tweak and improve docs for Request Files (#4470) 2022-01-23 21:30:35 +00:00
github-actions
5a864d8261 📝 Update release notes 2022-01-23 19:14:47 +00:00
Sebastián Ramírez
1bf55200a9 Add support for declaring UploadFile parameters without explicit File() (#4469) 2022-01-23 19:14:13 +00:00
github-actions
59b1f353b3 📝 Update release notes 2022-01-23 17:43:36 +00:00
Sebastián Ramírez
569afb4378 Add support for tags with Enums (#4468) 2022-01-23 18:43:04 +01:00
Sebastián Ramírez
0f8349fcb7 📝 Update release notes 2022-01-23 18:03:42 +01:00
github-actions
6215fdd39e 📝 Update release notes 2022-01-23 16:34:52 +00:00
Vivek Sunder
94ca8c1e29 🐛 Prefer custom encoder over defaults if specified in jsonable_encoder (#2061)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2022-01-23 17:34:18 +01:00
github-actions
f4963f05bf 📝 Update release notes 2022-01-23 16:32:35 +00:00
Sebastián Ramírez
d4608a00cf 🐛 Prefer custom encoder over defaults if specified in jsonable_encoder (#4467)
Co-authored-by: Vivek Sunder <sviveksunder@gmail.com>
2022-01-23 17:32:04 +01:00
github-actions
699b5ef841 📝 Update release notes 2022-01-23 16:14:28 +00:00
Sebastián Ramírez
3de0fb82bf 🐛 Fix docs dependencies cache, to get the latest Material for MkDocs (#4466) 2022-01-23 17:13:49 +01:00
github-actions
85518bc58b 📝 Update release notes 2022-01-23 15:55:36 +00:00
Mark
ca5d57ea79 Allow hiding from OpenAPI (and Swagger UI) Query, Cookie, Header, and Path parameters (#3144)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2022-01-23 16:54:59 +01:00
github-actions
347e391271 📝 Update release notes 2022-01-23 14:56:44 +00:00
Sebastián Ramírez
a75d080124 🔧 Add sponsor Dropbase (#4465) 2022-01-23 15:56:14 +01:00
Sebastián Ramírez
f0388915a8 🔖 Release version 0.72.0 2022-01-16 21:09:10 +01:00
Sebastián Ramírez
9e2f5c67b6 📝 Update release notes 2022-01-16 21:08:04 +01:00
github-actions
93e4a19e35 📝 Update release notes 2022-01-16 19:42:33 +00:00
jaystone776
e1c6d7d310 🌐 Update Chinese translation for docs/help-fastapi.md (#3847) 2022-01-16 20:41:59 +01:00
github-actions
d23b295b96 📝 Update release notes 2022-01-16 19:41:49 +00:00
kty4119
26e94116c1 🌐 Fix Korean translation for docs/ko/docs/index.md (#4195)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2022-01-16 19:41:13 +00:00
github-actions
24968937e5 📝 Update release notes 2022-01-16 19:37:21 +00:00
MicroPanda123
5c5b889288 🌐 Add Polish translation for docs/pl/docs/index.md (#4245)
Co-authored-by: Dawid Dutkiewicz <dutkiewicz@users.noreply.github.com>
Co-authored-by: Dima Tisnek <dimaqq@gmail.com>
Co-authored-by: Bart Skowron <bxsx@bartskowron.com>
Co-authored-by: Bart Skowron <bart.skowron@rollbar.com>
2022-01-16 19:36:42 +00:00
github-actions
436261b3ea 📝 Update release notes 2022-01-16 19:35:00 +00:00
jaystone776
5c62a59e7b 🌐 Add Chinese translation for docs\tutorial\path-operation-configuration.md (#3312)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2022-01-16 19:34:28 +00:00
github-actions
acbe79da37 📝 Update release notes 2022-01-16 19:27:03 +00:00
John Riebold
a85aa125d2 Enable configuring Swagger UI parameters (#2568)
Co-authored-by: Artem Ivanov <artem@worklife.io>
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2022-01-16 20:26:24 +01:00
github-actions
9af8cc69d5 📝 Update release notes 2022-01-16 14:44:43 +00:00
Sebastián Ramírez
7fe79441c1 📝 Update Python Types docs, add missing 3.6 / 3.9 example (#4434) 2022-01-16 15:44:08 +01:00
github-actions
b8ae84d460 📝 Update release notes 2022-01-16 14:35:21 +00:00
Sebastián Ramírez
ca2b1dbb64 🔧 Enable MkDocs Material Insiders' content.tabs.link (#4399) 2022-01-16 14:34:45 +00:00
Sebastián Ramírez
672c55ac62 🔖 Release version 0.71.0 2022-01-07 18:07:59 +01:00
github-actions
66c27c3e07 📝 Update release notes 2022-01-07 14:19:23 +00:00
github-actions[bot]
44f4885c66 👥 Update FastAPI People (#4354)
Co-authored-by: github-actions <github-actions@github.com>
2022-01-07 15:18:45 +01:00
github-actions
4da33e3031 📝 Update release notes 2022-01-07 14:17:49 +00:00
Sebastián Ramírez
a1ede32f29 🔧 Add FastAPI Trove Classifier for PyPI (#4386) 2022-01-07 14:17:13 +00:00
github-actions
0a82b3a900 📝 Update release notes 2022-01-07 14:12:16 +00:00
Sebastián Ramírez
d08a062ee2 Add docs and tests for Python 3.9 and Python 3.10 (#3712)
Co-authored-by: Thomas Grainger <tagrain@gmail.com>
2022-01-07 15:11:31 +01:00
github-actions
83f6781037 📝 Update release notes 2022-01-07 10:24:43 +00:00
Sebastián Ramírez
764ecae2d4 ⬆ Upgrade MkDocs Material and configs (#4385) 2022-01-07 11:24:00 +01:00
github-actions
4e9f75912f 📝 Update release notes 2022-01-07 09:35:10 +00:00
simondale00
2b10ca1cc4 ⬆️ Upgrade Starlette to 0.17.1 (#4145)
Co-authored-by: Dima Tisnek <dimaqq@gmail.com>
Co-authored-by: simond <simond@surveymonkey.com>
Co-authored-by: Samuel Colvin <s@muelcolvin.com>
Co-authored-by: Samuel Colvin <samcolvin@gmail.com>
2022-01-07 10:34:28 +01:00
Sebastián Ramírez
3efb4f7edf 🔖 Release version 0.70.1 2021-12-12 12:39:32 +01:00
github-actions
9c25f9615c 📝 Update release notes 2021-12-12 11:34:58 +00:00
github-actions[bot]
e7158bc592 👥 Update FastAPI People (#4274)
Co-authored-by: github-actions <github-actions@github.com>
2021-12-12 12:34:18 +01:00
github-actions
6d642ef5fb 📝 Update release notes 2021-12-12 11:29:36 +00:00
Eric Jolibois
b0cd4d7e7e 🐛 Fix JSON Schema for dataclasses, supporting the fixes in Pydantic 1.9 (#4272)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2021-12-12 12:28:35 +01:00
github-actions
0a87bc88b8 📝 Update release notes 2021-12-09 10:48:10 +00:00
Nina Hwang
062efcbb5d 🌐 Add Korean translation for docs/tutorial/request-forms-and-files.md (#3744)
Co-authored-by: weekwith.me <63915557+0417taehyun@users.noreply.github.com>
2021-12-09 11:47:26 +01:00
github-actions
aa4a69f790 📝 Update release notes 2021-12-09 10:45:00 +00:00
github-actions
eb79441a7f 📝 Update release notes 2021-12-09 10:40:14 +00:00
Nina Hwang
fa5639cb35 🌐 Add Korean translation for docs/tutorial/request-files.md (#3743)
Co-authored-by: Spike <rurouni24@gmail.com>
Co-authored-by: weekwith.me <63915557+0417taehyun@users.noreply.github.com>
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2021-12-08 15:52:01 +00:00
Leandro de Souza
10e3a02582 🌐 Add portuguese translation for docs/tutorial/query-params-str-validations.md (#3965)
Co-authored-by: Mário Victor Ribeiro Silva <mariovictorrs@gmail.com>
Co-authored-by: Leandro de Souza <leandro.souza@fontes.corp>
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2021-12-08 16:50:35 +01:00
github-actions
fb9c4b31b9 📝 Update release notes 2021-12-08 15:46:19 +00:00
Nina Hwang
39dbee9d56 🌐 Add Korean translation for docs/tutorial/response-status-code.md (#3742)
Co-authored-by: weekwith.me <63915557+0417taehyun@users.noreply.github.com>
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2021-12-08 16:45:37 +01:00
github-actions
dd463d0dc2 📝 Update release notes 2021-12-08 15:44:10 +00:00
Kwang Soo Jeong
461e0d4cce 🌐 Add Korean translation for Tutorial - JSON Compatible Encoder (#3152) 2021-12-08 16:43:31 +01:00
github-actions
da69a1c4c0 📝 Update release notes 2021-12-08 15:42:12 +00:00
Spike
a5d697b9b5 🌐 Add Korean translation for Tutorial - Path Parameters and Numeric Validations (#2432) 2021-12-08 16:41:26 +01:00
github-actions
8e416875ce 📝 Update release notes 2021-12-08 15:38:10 +00:00
daehyeon kim
446d194c46 🌐 Add Korean translation for docs/ko/docs/deployment/versions.md (#4121)
Co-authored-by: weekwith.me <63915557+0417taehyun@users.noreply.github.com>
2021-12-08 16:37:30 +01:00
github-actions
cace5a79f7 📝 Update release notes 2021-12-08 15:33:09 +00:00
kimjaeyoonn
dabb4898f1 🌐 Fix Korean translation for docs/ko/docs/tutorial/index.md (#4193) 2021-12-08 15:32:24 +00:00
github-actions
f282c0e207 📝 Update release notes 2021-12-08 15:04:50 +00:00
Sebastián Ramírez
146ff28d9c 🔧 Add CryptAPI sponsor (#4264) 2021-12-08 15:04:04 +00:00
github-actions
58ab733f19 📝 Update release notes 2021-10-26 18:54:22 +00:00
weekwith.me
0a61a6c865 📝 Update docs/tutorial/dependencies/classes-as-dependencies: Add type of query parameters in a description of Classes as dependencies (#4015) 2021-10-26 18:53:40 +00:00
github-actions
fb1f341231 📝 Update release notes 2021-10-26 18:47:42 +00:00
Sam Courtemanche
652cf4bb6b 🌐 Add French translation for Tutorial - First steps (#3455)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2021-10-26 18:47:01 +00:00
github-actions
08410ca568 📝 Update release notes 2021-10-26 18:34:11 +00:00
Sam Courtemanche
0d5e0ba5d5 🌐 Add French translation for docs/tutorial/path-params.md (#3548)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2021-10-26 18:33:34 +00:00
github-actions
b2c9574fc6 📝 Update release notes 2021-10-26 18:16:12 +00:00
Sam Courtemanche
a859497a72 🌐 Add French translation for docs/tutorial/query-params.md (#3556)
Co-authored-by: Ruidy <ruidy.nemausat@gmail.com>
2021-10-26 20:15:30 +02:00
github-actions
3c93e803d5 📝 Update release notes 2021-10-26 18:14:17 +00:00
bilal alpaslan
0bd8f901df 🌐 Add Turkish translation for docs/python-types.md (#3926) 2021-10-26 20:13:34 +02:00
Sebastián Ramírez
864643ef76 📝 Update release notes 2021-10-07 19:38:36 +02:00
Sebastián Ramírez
5d80e02ae8 🔖 Release version 0.70.0 2021-10-07 19:34:27 +02:00
Sebastián Ramírez
affe542753 📝 Update release notes 2021-10-07 19:33:35 +02:00
github-actions
8e887d7145 📝 Update release notes 2021-10-07 17:21:11 +00:00
Sebastián Ramírez
46cf92c55a ⬆️ Upgrade Starlette to 0.16.0 (#4016) 2021-10-07 19:20:30 +02:00
Sebastián Ramírez
921b6f742a 🔖 Release version 0.69.0 2021-10-07 18:45:43 +02:00
Sebastián Ramírez
c1fee263e1 📝 Update release notes 2021-10-07 18:43:50 +02:00
github-actions
42d10ef4bf 📝 Update release notes 2021-10-07 16:22:27 +00:00
Thomas Grainger
637cf89dbd 🔧 Correct DeprecationWarning config and comment in pytest settings (#4008)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2021-10-07 18:21:46 +02:00
github-actions
a81e2f20a5 📝 Update release notes 2021-10-07 16:15:21 +00:00
Andy Challis
53076170c0 ✏ Fix typos in Deployment Guide (#3975)
Co-authored-by: Anthony Lukach <anthonylukach@gmail.com>
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2021-10-07 18:14:39 +02:00
github-actions
eb89968b36 📝 Update release notes 2021-10-07 15:58:17 +00:00
tomwei7
c54fb7e208 📝 Update docs with pip install calls when using extras with brackets, use quotes for compatibility with Zsh (#3131)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2021-10-07 17:57:38 +02:00
github-actions
077e5baf2c 📝 Update release notes 2021-10-07 15:56:18 +00:00
Kaustubh Gupta
9c6e0d02bb 📝 Add external link to article: Deploying ML Models as API Using FastAPI and Heroku (#3904)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2021-10-07 17:55:40 +02:00
github-actions
d198f38b45 📝 Update release notes 2021-10-07 15:45:28 +00:00
Nina Hwang
4ba1e81f16 ✏ Fix typo in file paths in docs/en/docs/contributing.md (#3752)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2021-10-07 17:44:46 +02:00
Jorge Alvarado
b1508dcacc ✏ Re-word and combine 2 paragraphs into 1 for readability (#3346) 2021-10-07 17:39:19 +02:00
github-actions
bb20f5e60d 📝 Update release notes 2021-10-07 15:30:34 +00:00
SaintMalik
7e4887ea55 ✏ Fix a typo in docs/en/docs/advanced/path-operation-advanced-configuration.md and docs/en/docs/release-notes.md (#3750)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2021-10-07 15:29:50 +00:00
github-actions
ffaecddbf6 📝 Update release notes 2021-10-07 14:37:59 +00:00
Jorge Alvarado
e43f434448 ✏️ Add a missing comma in the security tutorial (#3564)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2021-10-07 14:36:43 +00:00
github-actions
eb453a50b8 📝 Update release notes 2021-10-07 14:23:26 +00:00
jaystone776
5a28f95a93 ✏ Fix typo in docs/en/docs/help-fastapi.md (#3760)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2021-10-07 14:22:16 +00:00
github-actions
4093c35058 📝 Update release notes 2021-10-07 14:09:05 +00:00
Denys Marichev
7efdc11075 ✏ Fix typo about file path in docs/en/docs/tutorial/bigger-applications.md (#3285)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2021-10-07 14:07:46 +00:00
github-actions
24cda290e8 📝 Update release notes 2021-10-07 13:59:14 +00:00
Bharat Raghunathan
d06b4d7bb8 ✏ Re-word to clarify test client in docs/en/docs/tutorial/testing.md (#3382)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2021-10-07 13:57:51 +00:00
github-actions
1a8284725a 📝 Update release notes 2021-10-07 13:32:54 +00:00
Pax
4f168c5ada 📝 Fix incorrect highlighted code (#3325)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2021-10-07 13:32:14 +00:00
github-actions
b67532ee5c 📝 Update release notes 2021-10-07 13:27:16 +00:00
Edd Salkield
c29aa0bc87 🔧 Swap light/dark theme button icon (#3246)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2021-10-07 15:26:36 +02:00
github-actions
5551e7282c 📝 Update release notes 2021-10-07 13:14:08 +00:00
Somraj Saha
8e68ddbddf 📝 Add external link to article: How-to deploy FastAPI app to Heroku (#3241)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2021-10-07 13:13:10 +00:00
github-actions
46882b9ae1 📝 Update release notes 2021-10-07 13:07:24 +00:00
mori yuta
e423c8241a ✏ Fix link in Japanese docs for docs/ja/docs/deployment/docker.md (#3245)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2021-10-07 15:06:17 +02:00
github-actions
3581034eff 📝 Update release notes 2021-10-07 13:01:11 +00:00
Abraham Hinteregger
b69781b161 ✏ Fix typo (mistranslation) in docs/en/docs/advanced/templates.md (#3211)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2021-10-07 13:00:33 +00:00
github-actions
12db3926b5 📝 Update release notes 2021-10-07 12:57:15 +00:00
Greg Gandenberger
afe1f69e79 📝 Remove note about (now supported) feature from Swagger UI in docs/en/docs/tutorial/request-files.md (#2803)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2021-10-07 12:55:51 +00:00
raphaelauv
426bd096ad 📝 Update note about Falcon and ASGI, as now Falcon is also ASGI 🎉 (#3073)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2021-10-07 12:44:39 +00:00
Vijay Yarramsetty
0ceacef413 ✏ Fix typo in docs/en/docs/tutorial/body-nested-models.md (#2808)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2021-10-07 12:30:25 +00:00
github-actions
fee3126d3a 📝 Update release notes 2021-10-07 12:27:41 +00:00
Hasan Ramezani
8f4e3a4377 📝 Add supported Python versions badge (#2794)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2021-10-07 12:26:57 +00:00
github-actions
3b686c3774 📝 Update release notes 2021-10-07 12:22:16 +00:00
graue70
17f0ec8927 ✏ Fix typo re-word in docs/tutorial/handling-errors.md (#2700)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2021-10-07 12:21:34 +00:00
github-actions
a6ef62ce7b 📝 Update release notes 2021-10-07 10:36:53 +00:00
Sebastián Ramírez
d9fa2311b3 📝 Add docs for using Trio with Hypercorn (#4014) 2021-10-07 10:36:09 +00:00
github-actions
c15f042318 📝 Update release notes 2021-10-06 15:43:37 +00:00
Sebastián Ramírez
a8bde38f7c Remove graphene as an optional dependency (#4007) 2021-10-06 15:42:55 +00:00
github-actions
496ccc0f70 📝 Update release notes 2021-10-06 15:32:53 +00:00
Thomas Grainger
11d0a08acd Add support for Trio via AnyIO (#3372)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2021-10-06 17:32:11 +02:00
github-actions
4d26fa5c54 📝 Update release notes 2021-10-06 15:09:36 +00:00
Sebastián Ramírez
eb1d68c789 🔧 Lint only in Python 3.7 and above (#4006) 2021-10-06 15:08:57 +00:00
github-actions
292b8c8ce9 📝 Update release notes 2021-10-05 16:10:28 +00:00
Sebastián Ramírez
cce8d9e32c 🔧 Add GitHub Action notify-translations config for Azerbaijani (#3995) 2021-10-05 16:09:45 +00:00
github-actions
ac0f594305 📝 Update release notes 2021-10-05 16:08:13 +00:00
Madat Bay
cc0d0f3899 🌐 Initialize Azerbaijani translations (#3941)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2021-10-05 16:07:25 +00:00
github-actions
67d5ba1efd 📝 Update release notes 2021-10-05 15:53:54 +00:00
bilal alpaslan
2210c84efd 🌐 Add Turkish translation for docs/fastapi-people.md (#3848)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2021-10-05 15:47:51 +00:00
440 changed files with 24776 additions and 1658 deletions

View File

@@ -12,3 +12,5 @@ sq: 2041
pl: 3169
de: 3716
id: 3717
az: 3994
nl: 4701

View File

@@ -501,9 +501,16 @@ if __name__ == "__main__":
github_sponsors_path = Path("./docs/en/data/github_sponsors.yml")
people_old_content = people_path.read_text(encoding="utf-8")
github_sponsors_old_content = github_sponsors_path.read_text(encoding="utf-8")
new_people_content = yaml.dump(people, sort_keys=False, width=200, allow_unicode=True)
new_github_sponsors_content = yaml.dump(github_sponsors, sort_keys=False, width=200, allow_unicode=True)
if people_old_content == new_people_content and github_sponsors_old_content == new_github_sponsors_content:
new_people_content = yaml.dump(
people, sort_keys=False, width=200, allow_unicode=True
)
new_github_sponsors_content = yaml.dump(
github_sponsors, sort_keys=False, width=200, allow_unicode=True
)
if (
people_old_content == new_people_content
and github_sponsors_old_content == new_github_sponsors_content
):
logging.info("The FastAPI People data hasn't changed, finishing.")
sys.exit(0)
people_path.write_text(new_people_content, encoding="utf-8")
@@ -517,7 +524,9 @@ if __name__ == "__main__":
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)
subprocess.run(
["git", "add", str(people_path), str(github_sponsors_path)], check=True
)
logging.info("Committing updated file")
message = "👥 Update FastAPI People"
result = subprocess.run(["git", "commit", "-m", message], check=True)

View File

@@ -1,6 +1,8 @@
name: Build Docs
on:
push:
branches:
- master
pull_request:
types: [opened, synchronize]
jobs:
@@ -20,7 +22,7 @@ jobs:
id: cache
with:
path: ${{ env.pythonLocation }}
key: ${{ runner.os }}-python-${{ env.pythonLocation }}-${{ hashFiles('pyproject.toml') }}-docs
key: ${{ runner.os }}-python-${{ env.pythonLocation }}-${{ hashFiles('pyproject.toml') }}-docs-v2
- name: Install Flit
if: steps.cache.outputs.cache-hit != 'true'
run: python3.7 -m pip install flit

View File

@@ -12,7 +12,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: [3.6, 3.7, 3.8, 3.9]
python-version: ["3.6", "3.7", "3.8", "3.9", "3.10"]
fail-fast: false
steps:
@@ -25,14 +25,17 @@ jobs:
id: cache
with:
path: ${{ env.pythonLocation }}
key: ${{ runner.os }}-python-${{ env.pythonLocation }}-${{ hashFiles('pyproject.toml') }}-test
key: ${{ runner.os }}-python-${{ env.pythonLocation }}-${{ hashFiles('pyproject.toml') }}-test-v02
- 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: Lint
if: ${{ matrix.python-version != '3.6' }}
run: bash scripts/lint.sh
- name: Test
run: bash scripts/test.sh
- name: Upload coverage
uses: codecov/codecov-action@v1
uses: codecov/codecov-action@v2

View File

@@ -14,6 +14,9 @@
<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://pypi.org/project/fastapi" target="_blank">
<img src="https://img.shields.io/pypi/pyversions/fastapi.svg?color=%2334D058" alt="Supported Python versions">
</a>
</p>
---
@@ -45,12 +48,16 @@ The key features are:
<!-- sponsors -->
<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://cryptapi.io/" target="_blank" title="CryptAPI: Your easy to use, secure and privacy oriented payment gateway."><img src="https://fastapi.tiangolo.com/img/sponsors/cryptapi.svg"></a>
<a href="https://classiq.link/n4s" target="_blank" title="Join the team building a new SaaS platform that will change the computing world"><img src="https://fastapi.tiangolo.com/img/sponsors/classiq.png"></a>
<a href="https://www.dropbase.io/careers" target="_blank" title="Dropbase - seamlessly collect, clean, and centralize data."><img src="https://fastapi.tiangolo.com/img/sponsors/dropbase.svg"></a>
<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://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>
<a href="https://training.talkpython.fm/fastapi-courses" target="_blank" title="FastAPI video courses on demand from people you trust"><img src="https://fastapi.tiangolo.com/img/sponsors/talkpython.png"></a>
<a href="https://testdriven.io/courses/tdd-fastapi/" target="_blank" title="Learn to build high-quality web apps with best practices"><img src="https://fastapi.tiangolo.com/img/sponsors/testdriven.svg"></a>
<a href="https://github.com/deepset-ai/haystack/" target="_blank" title="Build powerful search from composable, open source building blocks"><img src="https://fastapi.tiangolo.com/img/sponsors/haystack-fastapi.svg"></a>
<a href="https://www.udemy.com/course/fastapi-rest/" target="_blank" title="Learn FastAPI by building a complete project. Extend your knowledge on advanced web development-AWS, Payments, Emails."><img src="https://fastapi.tiangolo.com/img/sponsors/ines-course.jpg"></a>
<a href="https://careers.budget-insight.com/" target="_blank" title="Budget Insight is hiring!"><img src="https://fastapi.tiangolo.com/img/sponsors/budget-insight.svg"></a>
<!-- /sponsors -->
@@ -130,7 +137,7 @@ You will also need an ASGI server, for production such as <a href="https://www.u
<div class="termy">
```console
$ pip install uvicorn[standard]
$ pip install "uvicorn[standard]"
---> 100%
```
@@ -442,7 +449,6 @@ Used by Pydantic:
Used by Starlette:
* <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="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.
@@ -454,7 +460,7 @@ Used by FastAPI / Starlette:
* <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]`.
You can install all of these with `pip install "fastapi[all]"`.
## License

135
docs/az/mkdocs.yml Normal file
View File

@@ -0,0 +1,135 @@
site_name: FastAPI
site_description: FastAPI framework, high performance, easy to learn, fast to code, ready for production
site_url: https://fastapi.tiangolo.com/az/
theme:
name: material
custom_dir: overrides
palette:
- scheme: default
primary: teal
accent: amber
toggle:
icon: material/lightbulb
name: Switch to light mode
- scheme: slate
primary: teal
accent: amber
toggle:
icon: material/lightbulb-outline
name: Switch to dark mode
features:
- search.suggest
- search.highlight
- content.tabs.link
icon:
repo: fontawesome/brands/github-alt
logo: https://fastapi.tiangolo.com/img/icon-white.svg
favicon: https://fastapi.tiangolo.com/img/favicon.png
language: en
repo_name: tiangolo/fastapi
repo_url: https://github.com/tiangolo/fastapi
edit_uri: ''
plugins:
- search
- markdownextradata:
data: data
nav:
- FastAPI: index.md
- Languages:
- en: /
- az: /az/
- de: /de/
- es: /es/
- fa: /fa/
- fr: /fr/
- id: /id/
- it: /it/
- ja: /ja/
- ko: /ko/
- nl: /nl/
- pl: /pl/
- pt: /pt/
- ru: /ru/
- sq: /sq/
- tr: /tr/
- uk: /uk/
- zh: /zh/
markdown_extensions:
- toc:
permalink: true
- markdown.extensions.codehilite:
guess_lang: false
- mdx_include:
base_path: docs
- admonition
- codehilite
- extra
- pymdownx.superfences:
custom_fences:
- name: mermaid
class: mermaid
format: !!python/name:pymdownx.superfences.fence_code_format ''
- pymdownx.tabbed:
alternate_style: true
extra:
analytics:
provider: google
property: UA-133183413-1
social:
- icon: fontawesome/brands/github-alt
link: https://github.com/tiangolo/fastapi
- icon: fontawesome/brands/discord
link: https://discord.gg/VQjSZaeJmf
- icon: fontawesome/brands/twitter
link: https://twitter.com/fastapi
- icon: fontawesome/brands/linkedin
link: https://www.linkedin.com/in/tiangolo
- icon: fontawesome/brands/dev
link: https://dev.to/tiangolo
- icon: fontawesome/brands/medium
link: https://medium.com/@tiangolo
- icon: fontawesome/solid/globe
link: https://tiangolo.com
alternate:
- link: /
name: en - English
- link: /az/
name: az
- link: /de/
name: de
- link: /es/
name: es - español
- link: /fa/
name: fa
- link: /fr/
name: fr - français
- link: /id/
name: id
- link: /it/
name: it - italiano
- link: /ja/
name: ja - 日本語
- link: /ko/
name: ko - 한국어
- link: /nl/
name: nl
- 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
extra_javascript:
- https://fastapi.tiangolo.com/js/termynal.js
- https://fastapi.tiangolo.com/js/custom.js

0
docs/az/overrides/.gitignore vendored Normal file
View File

View File

@@ -9,13 +9,13 @@ theme:
primary: teal
accent: amber
toggle:
icon: material/lightbulb-outline
icon: material/lightbulb
name: Switch to light mode
- scheme: slate
primary: teal
accent: amber
toggle:
icon: material/lightbulb
icon: material/lightbulb-outline
name: Switch to dark mode
features:
- search.suggest
@@ -29,9 +29,6 @@ theme:
repo_name: tiangolo/fastapi
repo_url: https://github.com/tiangolo/fastapi
edit_uri: ''
google_analytics:
- UA-133183413-1
- auto
plugins:
- search
- markdownextradata:
@@ -40,13 +37,16 @@ nav:
- FastAPI: index.md
- Languages:
- en: /
- az: /az/
- de: /de/
- es: /es/
- fa: /fa/
- fr: /fr/
- id: /id/
- it: /it/
- ja: /ja/
- ko: /ko/
- nl: /nl/
- pl: /pl/
- pt: /pt/
- ru: /ru/
@@ -70,8 +70,12 @@ markdown_extensions:
- name: mermaid
class: mermaid
format: !!python/name:pymdownx.superfences.fence_code_format ''
- pymdownx.tabbed
- pymdownx.tabbed:
alternate_style: true
extra:
analytics:
provider: google
property: UA-133183413-1
social:
- icon: fontawesome/brands/github-alt
link: https://github.com/tiangolo/fastapi
@@ -90,10 +94,14 @@ extra:
alternate:
- link: /
name: en - English
- link: /az/
name: az
- link: /de/
name: de
- link: /es/
name: es - español
- link: /fa/
name: fa
- link: /fr/
name: fr - français
- link: /id/
@@ -104,6 +112,8 @@ extra:
name: ja - 日本語
- link: /ko/
name: ko - 한국어
- link: /nl/
name: nl
- link: /pl/
name: pl
- link: /pt/

View File

@@ -1,5 +1,13 @@
articles:
english:
- author: Kaustubh Gupta
author_link: https://medium.com/@kaustubhgupta1828/
link: https://www.analyticsvidhya.com/blog/2021/06/deploying-ml-models-as-api-using-fastapi-and-heroku/
title: Deploying ML Models as API Using FastAPI and Heroku
- link: https://jarmos.netlify.app/posts/using-github-actions-to-deploy-a-fastapi-project-to-heroku/
title: Using GitHub Actions to Deploy a FastAPI Project to Heroku
author_link: https://jarmos.netlify.app/
author: Somraj Saha
- author: "@pystar"
author_link: https://pystar.substack.com/
link: https://pystar.substack.com/p/how-to-create-a-fake-certificate

View File

@@ -1,42 +1,75 @@
sponsors:
- - login: jina-ai
- - login: cryptapi
avatarUrl: https://avatars.githubusercontent.com/u/44925437?u=61369138589bc7fee6c417f3fbd50fbd38286cc4&v=4
url: https://github.com/cryptapi
- login: jina-ai
avatarUrl: https://avatars.githubusercontent.com/u/60539444?v=4
url: https://github.com/jina-ai
- login: DropbaseHQ
avatarUrl: https://avatars.githubusercontent.com/u/85367855?v=4
url: https://github.com/DropbaseHQ
- - login: sushi2all
avatarUrl: https://avatars.githubusercontent.com/u/1043732?v=4
url: https://github.com/sushi2all
- login: chaserowbotham
avatarUrl: https://avatars.githubusercontent.com/u/97751084?v=4
url: https://github.com/chaserowbotham
- - login: mikeckennedy
avatarUrl: https://avatars.githubusercontent.com/u/2035561?v=4
avatarUrl: https://avatars.githubusercontent.com/u/2035561?u=1bb18268bcd4d9249e1f783a063c27df9a84c05b&v=4
url: https://github.com/mikeckennedy
- login: RodneyU215
avatarUrl: https://avatars.githubusercontent.com/u/3329665?u=ec6a9adf8e7e8e306eed7d49687c398608d1604f&v=4
url: https://github.com/RodneyU215
- login: Trivie
avatarUrl: https://avatars.githubusercontent.com/u/8161763?v=4
url: https://github.com/Trivie
- login: deta
avatarUrl: https://avatars.githubusercontent.com/u/47275976?v=4
url: https://github.com/deta
- login: deepset-ai
avatarUrl: https://avatars.githubusercontent.com/u/51827949?v=4
url: https://github.com/deepset-ai
- login: investsuite
avatarUrl: https://avatars.githubusercontent.com/u/73833632?v=4
url: https://github.com/investsuite
- login: vimsoHQ
avatarUrl: https://avatars.githubusercontent.com/u/77627231?v=4
url: https://github.com/vimsoHQ
- - login: newrelic
avatarUrl: https://avatars.githubusercontent.com/u/31739?v=4
url: https://github.com/newrelic
- login: VincentParedes
avatarUrl: https://avatars.githubusercontent.com/u/103889729?v=4
url: https://github.com/VincentParedes
- - login: plocher
avatarUrl: https://avatars.githubusercontent.com/u/1082871?v=4
url: https://github.com/plocher
- - login: InesIvanova
avatarUrl: https://avatars.githubusercontent.com/u/22920417?u=409882ec1df6dbd77455788bb383a8de223dbf6f&v=4
url: https://github.com/InesIvanova
- - login: SendCloud
avatarUrl: https://avatars.githubusercontent.com/u/7831959?v=4
url: https://github.com/SendCloud
- login: qaas
avatarUrl: https://avatars.githubusercontent.com/u/8503759?u=10a6b4391ad6ab4cf9487ce54e3fcb61322d1efc&v=4
url: https://github.com/qaas
- login: xoflare
avatarUrl: https://avatars.githubusercontent.com/u/74335107?v=4
url: https://github.com/xoflare
- login: Striveworks
avatarUrl: https://avatars.githubusercontent.com/u/45523576?v=4
url: https://github.com/Striveworks
- login: BoostryJP
avatarUrl: https://avatars.githubusercontent.com/u/57932412?v=4
url: https://github.com/BoostryJP
- - login: johnadjei
avatarUrl: https://avatars.githubusercontent.com/u/767860?v=4
url: https://github.com/johnadjei
- login: HiredScore
avatarUrl: https://avatars.githubusercontent.com/u/3908850?v=4
url: https://github.com/HiredScore
- login: wdwinslow
avatarUrl: https://avatars.githubusercontent.com/u/11562137?u=dc01daafb354135603a263729e3d26d939c0c452&v=4
url: https://github.com/wdwinslow
- - login: kamalgill
avatarUrl: https://avatars.githubusercontent.com/u/133923?u=0df9181d97436ce330e9acf90ab8a54b7022efe7&v=4
url: https://github.com/kamalgill
- - login: moellenbeck
avatarUrl: https://avatars.githubusercontent.com/u/169372?v=4
url: https://github.com/moellenbeck
- login: RodneyU215
avatarUrl: https://avatars.githubusercontent.com/u/3329665?u=ec6a9adf8e7e8e306eed7d49687c398608d1604f&v=4
url: https://github.com/RodneyU215
- login: grillazz
avatarUrl: https://avatars.githubusercontent.com/u/3415861?u=16d7d0ffa5dfb99f8834f8f76d90e138ba09b94a&v=4
avatarUrl: https://avatars.githubusercontent.com/u/3415861?u=0b32b7073ae1ab8b7f6d2db0188c2e1e357ff451&v=4
url: https://github.com/grillazz
- login: tizz98
avatarUrl: https://avatars.githubusercontent.com/u/5739698?u=f095a3659e3a8e7c69ccd822696990b521ea25f9&v=4
@@ -44,45 +77,57 @@ sponsors:
- login: jmaralc
avatarUrl: https://avatars.githubusercontent.com/u/21101214?u=b15a9f07b7cbf6c9dcdbcb6550bbd2c52f55aa50&v=4
url: https://github.com/jmaralc
- login: AlexandruSimion
avatarUrl: https://avatars.githubusercontent.com/u/71321732?v=4
url: https://github.com/AlexandruSimion
- - login: samuelcolvin
- login: marutoraman
avatarUrl: https://avatars.githubusercontent.com/u/33813153?u=2d0522bceba0b8b69adf1f2db866503bd96f944e&v=4
url: https://github.com/marutoraman
- login: mainframeindustries
avatarUrl: https://avatars.githubusercontent.com/u/55092103?v=4
url: https://github.com/mainframeindustries
- login: A-Edge
avatarUrl: https://avatars.githubusercontent.com/u/59514131?v=4
url: https://github.com/A-Edge
- - login: Kludex
avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=62adc405ef418f4b6c8caa93d3eb8ab107bc4927&v=4
url: https://github.com/Kludex
- 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: jefftriplett
avatarUrl: https://avatars.githubusercontent.com/u/50527?u=af1ddfd50f6afd6d99f333ba2ac8d0a5b245ea74&v=4
url: https://github.com/jefftriplett
- login: kamalgill
avatarUrl: https://avatars.githubusercontent.com/u/133923?u=0df9181d97436ce330e9acf90ab8a54b7022efe7&v=4
url: https://github.com/kamalgill
- login: jsutton
avatarUrl: https://avatars.githubusercontent.com/u/280777?v=4
url: https://github.com/jsutton
- login: deserat
avatarUrl: https://avatars.githubusercontent.com/u/299332?v=4
url: https://github.com/deserat
- login: ericof
avatarUrl: https://avatars.githubusercontent.com/u/306014?u=cf7c8733620397e6584a451505581c01c5d842d7&v=4
url: https://github.com/ericof
- 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: corleyma
avatarUrl: https://avatars.githubusercontent.com/u/2080732?u=aed2ff652294a87d666b1c3f6dbe98104db76d26&v=4
url: https://github.com/corleyma
- login: madisonmay
avatarUrl: https://avatars.githubusercontent.com/u/2645393?u=f22b93c6ea345a4d26a90a3834dfc7f0789fcb63&v=4
url: https://github.com/madisonmay
@@ -93,149 +138,194 @@ sponsors:
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
avatarUrl: https://avatars.githubusercontent.com/u/3163309?u=0c6f4091b0eda05c44c390466199826e6dc6e431&v=4
url: https://github.com/Shark009
- login: dblackrun
avatarUrl: https://avatars.githubusercontent.com/u/3528486?v=4
url: https://github.com/dblackrun
- login: zsinx6
avatarUrl: https://avatars.githubusercontent.com/u/3532625?u=ba75a5dc744d1116ccfeaaf30d41cb2fe81fe8dd&v=4
url: https://github.com/zsinx6
- login: anomaly
avatarUrl: https://avatars.githubusercontent.com/u/3654837?v=4
url: https://github.com/anomaly
- login: peterHoburg
avatarUrl: https://avatars.githubusercontent.com/u/3860655?u=f55f47eb2d6a9b495e806ac5a044e3ae01ccc1fa&v=4
url: https://github.com/peterHoburg
- login: jaredtrog
avatarUrl: https://avatars.githubusercontent.com/u/4381365?v=4
url: https://github.com/jaredtrog
- login: oliverxchen
avatarUrl: https://avatars.githubusercontent.com/u/4471774?u=534191f25e32eeaadda22dfab4b0a428733d5489&v=4
url: https://github.com/oliverxchen
- login: CINOAdam
avatarUrl: https://avatars.githubusercontent.com/u/4728508?u=34c3d58cb900fed475d0172b436c66a94ad739ed&v=4
avatarUrl: https://avatars.githubusercontent.com/u/4728508?u=76ef23f06ae7c604e009873bc27cf0ea9ba738c9&v=4
url: https://github.com/CINOAdam
- login: dudil
avatarUrl: https://avatars.githubusercontent.com/u/4785835?u=58b7ea39123e0507f3b2996448a27256b16fd697&v=4
url: https://github.com/dudil
- login: ScrimForever
avatarUrl: https://avatars.githubusercontent.com/u/5040124?u=091ec38bfe16d6e762099e91309b59f248616a65&v=4
url: https://github.com/ScrimForever
- login: ennui93
avatarUrl: https://avatars.githubusercontent.com/u/5300907?u=5b5452725ddb391b2caaebf34e05aba873591c3a&v=4
url: https://github.com/ennui93
- login: MacroPower
avatarUrl: https://avatars.githubusercontent.com/u/5648814?u=e13991efd1e03c44c911f919872e750530ded633&v=4
url: https://github.com/MacroPower
- login: ginomempin
avatarUrl: https://avatars.githubusercontent.com/u/6091865?v=4
url: https://github.com/ginomempin
- login: Yaleesa
avatarUrl: https://avatars.githubusercontent.com/u/6135475?v=4
url: https://github.com/Yaleesa
- login: iwpnd
avatarUrl: https://avatars.githubusercontent.com/u/6152183?u=b2286006daafff5f991557344fee20b5da59639a&v=4
url: https://github.com/iwpnd
- login: simw
avatarUrl: https://avatars.githubusercontent.com/u/6322526?v=4
url: https://github.com/simw
- login: pkucmus
avatarUrl: https://avatars.githubusercontent.com/u/6347418?u=98f5918b32e214a168a2f5d59b0b8ebdf57dca0d&v=4
url: https://github.com/pkucmus
- 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: hiancdtrsnm
avatarUrl: https://avatars.githubusercontent.com/u/7343177?v=4
url: https://github.com/hiancdtrsnm
- login: Shackelford-Arden
avatarUrl: https://avatars.githubusercontent.com/u/7362263?v=4
url: https://github.com/Shackelford-Arden
- 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: Vikka
avatarUrl: https://avatars.githubusercontent.com/u/9381120?u=4bfc7032a824d1ed1994aa8256dfa597c8f187ad&v=4
url: https://github.com/Vikka
- login: Ge0f3
avatarUrl: https://avatars.githubusercontent.com/u/11887760?u=ccd80f1ac36dcb8517ef5c4e702e8cc5a80cad2f&v=4
url: https://github.com/Ge0f3
- login: gokulyc
avatarUrl: https://avatars.githubusercontent.com/u/13468848?u=269f269d3e70407b5fb80138c52daba7af783997&v=4
url: https://github.com/gokulyc
- login: dannywade
avatarUrl: https://avatars.githubusercontent.com/u/13680237?u=418ee985bd41577b20fde81417fb2d901e875e8a&v=4
url: https://github.com/dannywade
- login: pablonnaoji
avatarUrl: https://avatars.githubusercontent.com/u/15187159?u=afc15bd5a4ba9c5c7206bbb1bcaeef606a0932e0&v=4
url: https://github.com/pablonnaoji
- 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: stradivari96
avatarUrl: https://avatars.githubusercontent.com/u/19752586?u=255f5f06a768f518b20cebd6963e840ac49294fd&v=4
url: https://github.com/stradivari96
- login: RedCarpetUp
avatarUrl: https://avatars.githubusercontent.com/u/20360440?v=4
url: https://github.com/RedCarpetUp
- 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: shuheng-liu
avatarUrl: https://avatars.githubusercontent.com/u/22414322?u=813c45f30786c6b511b21a661def025d8f7b609e&v=4
url: https://github.com/shuheng-liu
- login: cometa-haley
avatarUrl: https://avatars.githubusercontent.com/u/25950317?u=cec1a3e0643b785288ae8260cc295a85ab344995&v=4
url: https://github.com/cometa-haley
- login: LarryGF
avatarUrl: https://avatars.githubusercontent.com/u/26148349?u=431bb34d36d41c172466252242175281ae132152&v=4
url: https://github.com/LarryGF
- 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: meysam81
avatarUrl: https://avatars.githubusercontent.com/u/30233243?u=64dc9fc62d039892c6fb44d804251cad5537132b&v=4
url: https://github.com/meysam81
- login: mauroalejandrojm
avatarUrl: https://avatars.githubusercontent.com/u/31569442?u=cdada990a1527926a36e95f62c30a8b48bbc49a1&v=4
url: https://github.com/mauroalejandrojm
- login: bulkw4r3
avatarUrl: https://avatars.githubusercontent.com/u/35562532?u=0b812a14a02de14bf73d05fb2b2760a67bacffc2&v=4
url: https://github.com/bulkw4r3
- login: Leay15
avatarUrl: https://avatars.githubusercontent.com/u/32212558?u=c4aa9c1737e515959382a5515381757b1fd86c53&v=4
url: https://github.com/Leay15
- login: AlrasheedA
avatarUrl: https://avatars.githubusercontent.com/u/33544979?u=7fe66bf62b47682612b222e3e8f4795ef3be769b&v=4
url: https://github.com/AlrasheedA
- login: ProteinQure
avatarUrl: https://avatars.githubusercontent.com/u/33707203?v=4
url: https://github.com/ProteinQure
- login: guligon90
avatarUrl: https://avatars.githubusercontent.com/u/35070513?u=b48c05f669d1ea1d329f90dc70e45f10b569ef55&v=4
url: https://github.com/guligon90
- login: ybressler
avatarUrl: https://avatars.githubusercontent.com/u/40807730?u=6621dc9ab53b697912ab2a32211bb29ae90a9112&v=4
url: https://github.com/ybressler
- login: iamkarshe
avatarUrl: https://avatars.githubusercontent.com/u/43641892?u=d08c901b359c931784501740610d416558ff3e24&v=4
url: https://github.com/iamkarshe
- login: dbanty
avatarUrl: https://avatars.githubusercontent.com/u/43723790?u=0cf33e4f40efc2ea206a1189fd63a11344eb88ed&v=4
avatarUrl: https://avatars.githubusercontent.com/u/43723790?u=9bcce836bbce55835291c5b2ac93a4e311f4b3c3&v=4
url: https://github.com/dbanty
- login: rafsaf
avatarUrl: https://avatars.githubusercontent.com/u/51059348?u=be9f06b8ced2d2b677297decc781fa8ce4f7ddbd&v=4
url: https://github.com/rafsaf
- login: dudikbender
avatarUrl: https://avatars.githubusercontent.com/u/53487583?u=494f85229115076121b3639a3806bbac1c6ae7f6&v=4
url: https://github.com/dudikbender
- login: daisuke8000
avatarUrl: https://avatars.githubusercontent.com/u/55035595?u=5025e379cd3655ae1a96039efc85223a873d2e38&v=4
url: https://github.com/daisuke8000
- login: yakkonaut
avatarUrl: https://avatars.githubusercontent.com/u/60633704?u=90a71fd631aa998ba4a96480788f017c9904e07b&v=4
url: https://github.com/yakkonaut
- 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: around
avatarUrl: https://avatars.githubusercontent.com/u/62425723?v=4
url: https://github.com/around
- login: predictionmachine
avatarUrl: https://avatars.githubusercontent.com/u/63719559?v=4
url: https://github.com/predictionmachine
- 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: an-tho-ny
avatarUrl: https://avatars.githubusercontent.com/u/74874159?v=4
url: https://github.com/an-tho-ny
- login: NinaHwang
avatarUrl: https://avatars.githubusercontent.com/u/79563565?u=1741703bd6c8f491503354b363a86e879b4c1cab&v=4
url: https://github.com/NinaHwang
- login: dotlas
avatarUrl: https://avatars.githubusercontent.com/u/88832003?v=4
url: https://github.com/dotlas
- login: pyt3h
avatarUrl: https://avatars.githubusercontent.com/u/99658549?v=4
url: https://github.com/pyt3h
- - login: linux-china
avatarUrl: https://avatars.githubusercontent.com/u/46711?v=4
url: https://github.com/linux-china
- login: ddanier
avatarUrl: https://avatars.githubusercontent.com/u/113563?v=4
url: https://github.com/ddanier
- login: jhb
avatarUrl: https://avatars.githubusercontent.com/u/142217?v=4
url: https://github.com/jhb
- login: justinrmiller
avatarUrl: https://avatars.githubusercontent.com/u/143998?u=b507a940394d4fc2bc1c27cea2ca9c22538874bd&v=4
url: https://github.com/justinrmiller
- login: bryanculbertson
avatarUrl: https://avatars.githubusercontent.com/u/144028?u=defda4f90e93429221cc667500944abde60ebe4a&v=4
url: https://github.com/bryanculbertson
- login: yourkin
avatarUrl: https://avatars.githubusercontent.com/u/178984?v=4
avatarUrl: https://avatars.githubusercontent.com/u/178984?u=fa7c3503b47bf16405b96d21554bc59f07a65523&v=4
url: https://github.com/yourkin
- login: jmagnusson
avatarUrl: https://avatars.githubusercontent.com/u/190835?v=4
url: https://github.com/jmagnusson
- login: sakti
avatarUrl: https://avatars.githubusercontent.com/u/196178?u=0110be74c4270244546f1b610334042cd16bb8ad&v=4
url: https://github.com/sakti
- login: slafs
avatarUrl: https://avatars.githubusercontent.com/u/210173?v=4
url: https://github.com/slafs
- login: assem-ch
avatarUrl: https://avatars.githubusercontent.com/u/315228?u=e0c5ab30726d3243a40974bb9bae327866e42d9b&v=4
url: https://github.com/assem-ch
- login: adamghill
avatarUrl: https://avatars.githubusercontent.com/u/317045?u=f1349d5ffe84a19f324e204777859fbf69ddf633&v=4
url: https://github.com/adamghill
@@ -245,21 +335,33 @@ sponsors:
- 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: securancy
avatarUrl: https://avatars.githubusercontent.com/u/606673?v=4
url: https://github.com/securancy
- login: falkben
avatarUrl: https://avatars.githubusercontent.com/u/653031?u=0c8d8f33d87f1aa1a6488d3f02105e9abc838105&v=4
url: https://github.com/falkben
- login: hardbyte
avatarUrl: https://avatars.githubusercontent.com/u/855189?u=aa29e92f34708814d6b67fcd47ca4cf2ce1c04ed&v=4
url: https://github.com/hardbyte
- login: janfilips
avatarUrl: https://avatars.githubusercontent.com/u/870699?u=6034d81731ecb41ae5c717e56a901ed46fc039a8&v=4
url: https://github.com/janfilips
- login: scari
avatarUrl: https://avatars.githubusercontent.com/u/964251?v=4
url: https://github.com/scari
- 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: Celeborn2BeAlive
avatarUrl: https://avatars.githubusercontent.com/u/1659465?u=944517e4db0f6df65070074e81cabdad9c8a434b&v=4
url: https://github.com/Celeborn2BeAlive
- login: WillHogan
avatarUrl: https://avatars.githubusercontent.com/u/1661551?u=7036c064cf29781470573865264ec8e60b6b809f&v=4
url: https://github.com/WillHogan
- login: cbonoz
avatarUrl: https://avatars.githubusercontent.com/u/2351087?u=fd3e8030b2cc9fbfbb54a65e9890c548a016f58b&v=4
url: https://github.com/cbonoz
@@ -269,47 +371,47 @@ sponsors:
- 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: anthcor
- login: anthonycorletti
avatarUrl: https://avatars.githubusercontent.com/u/3477132?v=4
url: https://github.com/anthcor
- login: zsinx6
avatarUrl: https://avatars.githubusercontent.com/u/3532625?u=ba75a5dc744d1116ccfeaaf30d41cb2fe81fe8dd&v=4
url: https://github.com/zsinx6
url: https://github.com/anthonycorletti
- 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=03c724c6f8fbab5cd6575b810c0c91c652fa4f79&v=4
url: https://github.com/spyker77
- login: JonasKs
avatarUrl: https://avatars.githubusercontent.com/u/5310116?u=98a049f3e1491bffb91e1feb7e93def6881a9389&v=4
url: https://github.com/JonasKs
- login: Alisa-lisa
avatarUrl: https://avatars.githubusercontent.com/u/4137964?u=e7e393504f554f4ff15863a1e01a5746863ef9ce&v=4
url: https://github.com/Alisa-lisa
- login: unredundant
avatarUrl: https://avatars.githubusercontent.com/u/5607577?u=57dd0023365bec03f4fc566df6b81bc0a264a47d&v=4
url: https://github.com/unredundant
- 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: moonape1226
avatarUrl: https://avatars.githubusercontent.com/u/8532038?u=d9f8b855a429fff9397c3833c2ff83849ebf989d&v=4
url: https://github.com/moonape1226
- 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: yenchenLiu
avatarUrl: https://avatars.githubusercontent.com/u/9199638?u=8cdf5ae507448430d90f6f3518d1665a23afe99b&v=4
url: https://github.com/yenchenLiu
- login: VivianSolide
avatarUrl: https://avatars.githubusercontent.com/u/9358572?u=ffb2e2ec522a15dcd3f0af1f9fd1df4afe418afa&v=4
avatarUrl: https://avatars.githubusercontent.com/u/9358572?u=4a38ef72dd39e8b262bd5ab819992128b55c52b4&v=4
url: https://github.com/VivianSolide
- login: xncbf
avatarUrl: https://avatars.githubusercontent.com/u/9462045?u=866a1311e4bd3ec5ae84185c4fcc99f397c883d7&v=4
url: https://github.com/xncbf
- login: DMantis
avatarUrl: https://avatars.githubusercontent.com/u/9536869?v=4
url: https://github.com/DMantis
- login: hard-coders
avatarUrl: https://avatars.githubusercontent.com/u/9651103?u=f2d3d2038c55d86d7f9348f4e6c5e30191e4ee8b&v=4
avatarUrl: https://avatars.githubusercontent.com/u/9651103?u=95db33927bbff1ed1c07efddeb97ac2ff33068ed&v=4
url: https://github.com/hard-coders
- login: satwikkansal
avatarUrl: https://avatars.githubusercontent.com/u/10217535?u=b12d6ef74ea297de9e46da6933b1a5b7ba9e6a61&v=4
@@ -317,63 +419,78 @@ sponsors:
- 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: cdsre
avatarUrl: https://avatars.githubusercontent.com/u/16945936?v=4
url: https://github.com/cdsre
- login: jangia
avatarUrl: https://avatars.githubusercontent.com/u/17927101?u=9261b9bb0c3e3bb1ecba43e8915dc58d8c9a077e&v=4
url: https://github.com/jangia
- 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: fstau
avatarUrl: https://avatars.githubusercontent.com/u/24669867?u=60e7c8c09f8dafabee8fc3edcd6f9e19abbff918&v=4
url: https://github.com/fstau
- 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: 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: dwreeves
avatarUrl: https://avatars.githubusercontent.com/u/31971762?u=69732aba05aa5cf0780866349ebe109cf632b047&v=4
url: https://github.com/dwreeves
- login: kitaramu0401
avatarUrl: https://avatars.githubusercontent.com/u/33246506?u=929e6efa2c518033b8097ba524eb5347a069bb3b&v=4
url: https://github.com/kitaramu0401
- login: engineerjoe440
avatarUrl: https://avatars.githubusercontent.com/u/33275230?u=eb223cad27017bb1e936ee9b429b450d092d0236&v=4
url: https://github.com/engineerjoe440
- login: declon
avatarUrl: https://avatars.githubusercontent.com/u/36180226?v=4
url: https://github.com/declon
- login: d-e-h-i-o
avatarUrl: https://avatars.githubusercontent.com/u/36816716?v=4
url: https://github.com/d-e-h-i-o
- login: ilias-ant
avatarUrl: https://avatars.githubusercontent.com/u/42189572?u=a2d6121bac4d125d92ec207460fa3f1842d37e66&v=4
url: https://github.com/ilias-ant
- login: arrrrrmin
avatarUrl: https://avatars.githubusercontent.com/u/43553423?u=05600727f1cfe75f440bb3fddd49bfea84b1e894&v=4
avatarUrl: https://avatars.githubusercontent.com/u/43553423?u=fee5739394fea074cb0b66929d070114a5067aae&v=4
url: https://github.com/arrrrrmin
- login: Nephilim-Jack
avatarUrl: https://avatars.githubusercontent.com/u/48372168?u=6f2bb405238d7efc467536fe01f58df6779c58a9&v=4
url: https://github.com/Nephilim-Jack
- login: akanz1
avatarUrl: https://avatars.githubusercontent.com/u/51492342?u=2280f57134118714645e16b535c1a37adf6b369b&v=4
url: https://github.com/akanz1
- - login: leogregianin
avatarUrl: https://avatars.githubusercontent.com/u/1684053?u=94ddd387601bd1805034dbe83e6eba0491c15323&v=4
url: https://github.com/leogregianin
- login: rooflexx
avatarUrl: https://avatars.githubusercontent.com/u/58993673?u=f8ba450460f1aea18430ed1e4a3889049a3b4dfa&v=4
url: https://github.com/rooflexx
- login: denisyao1
avatarUrl: https://avatars.githubusercontent.com/u/60019356?v=4
url: https://github.com/denisyao1
- login: apar-tiwari
avatarUrl: https://avatars.githubusercontent.com/u/61064197?v=4
url: https://github.com/apar-tiwari
- login: 0417taehyun
avatarUrl: https://avatars.githubusercontent.com/u/63915557?u=47debaa860fd52c9b98c97ef357ddcec3b3fb399&v=4
url: https://github.com/0417taehyun
- login: alessio-proietti
avatarUrl: https://avatars.githubusercontent.com/u/67370599?u=8ac73db1e18e946a7681f173abdb640516f88515&v=4
url: https://github.com/alessio-proietti
- - login: backbord
avatarUrl: https://avatars.githubusercontent.com/u/6814946?v=4
url: https://github.com/backbord
- login: sadikkuzu
avatarUrl: https://avatars.githubusercontent.com/u/23168063?u=765ed469c44c004560079210ccdad5b29938eaa9&v=4
url: https://github.com/sadikkuzu
- login: gabrielmbmb
avatarUrl: https://avatars.githubusercontent.com/u/29572918?u=92084ed7242160dee4d20aece923a10c59758ee5&v=4
avatarUrl: https://avatars.githubusercontent.com/u/29572918?u=6d1e00b5d558e96718312ff910a2318f47cc3145&v=4
url: https://github.com/gabrielmbmb
- login: starhype
avatarUrl: https://avatars.githubusercontent.com/u/36908028?u=6df41f7b62f0f673f1ecbc87e9cbadaa4fcb0767&v=4
url: https://github.com/starhype
- login: pixel365
avatarUrl: https://avatars.githubusercontent.com/u/53819609?u=9e0309c5420ec4624aececd3ca2d7105f7f68133&v=4
url: https://github.com/pixel365
- login: danburonline
avatarUrl: https://avatars.githubusercontent.com/u/34251194?u=2cad4388c1544e539ecb732d656e42fb07b4ff2d&v=4
url: https://github.com/danburonline

View File

@@ -1,20 +1,20 @@
maintainers:
- login: tiangolo
answers: 1230
prs: 260
answers: 1243
prs: 300
avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=5cad72c846b7aba2e960546af490edc7375dafc4&v=4
url: https://github.com/tiangolo
experts:
- login: Kludex
count: 299
avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=cf8455cb899806b774a3a71073f88583adec99f6&v=4
count: 335
avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=62adc405ef418f4b6c8caa93d3eb8ab107bc4927&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: 219
count: 221
avatarUrl: https://avatars.githubusercontent.com/u/62724709?u=826f228edf0bab0d19ad1d5c4ba4df1047ccffef&v=4
url: https://github.com/ycd
- login: Mause
@@ -29,69 +29,85 @@ experts:
count: 130
avatarUrl: https://avatars.githubusercontent.com/u/331403?v=4
url: https://github.com/phy25
- login: raphaelauv
count: 71
avatarUrl: https://avatars.githubusercontent.com/u/10202690?u=e6f86f5c0c3026a15d6b51792fa3e532b12f1371&v=4
url: https://github.com/raphaelauv
- login: ArcLightSlavik
count: 68
avatarUrl: https://avatars.githubusercontent.com/u/31127044?u=81a84af39c89b898b0fbc5a04e8834f60f23e55a&v=4
count: 71
avatarUrl: https://avatars.githubusercontent.com/u/31127044?u=b0f2c37142f4b762e41ad65dc49581813422bd71&v=4
url: https://github.com/ArcLightSlavik
- login: falkben
count: 57
count: 58
avatarUrl: https://avatars.githubusercontent.com/u/653031?u=0c8d8f33d87f1aa1a6488d3f02105e9abc838105&v=4
url: https://github.com/falkben
- login: sm-Fifteen
count: 48
avatarUrl: https://avatars.githubusercontent.com/u/516999?u=437c0c5038558c67e887ccd863c1ba0f846c03da&v=4
url: https://github.com/sm-Fifteen
- login: raphaelauv
count: 48
avatarUrl: https://avatars.githubusercontent.com/u/10202690?u=e6f86f5c0c3026a15d6b51792fa3e532b12f1371&v=4
url: https://github.com/raphaelauv
- login: includeamin
count: 38
avatarUrl: https://avatars.githubusercontent.com/u/11836741?u=8bd5ef7e62fe6a82055e33c4c0e0a7879ff8cfb6&v=4
url: https://github.com/includeamin
- login: insomnes
count: 46
avatarUrl: https://avatars.githubusercontent.com/u/16958893?u=f8be7088d5076d963984a21f95f44e559192d912&v=4
url: https://github.com/insomnes
- login: Dustyposa
count: 38
count: 43
avatarUrl: https://avatars.githubusercontent.com/u/27180793?u=5cf2877f50b3eb2bc55086089a78a36f07042889&v=4
url: https://github.com/Dustyposa
- login: includeamin
count: 39
avatarUrl: https://avatars.githubusercontent.com/u/11836741?u=8bd5ef7e62fe6a82055e33c4c0e0a7879ff8cfb6&v=4
url: https://github.com/includeamin
- login: jgould22
count: 38
avatarUrl: https://avatars.githubusercontent.com/u/4335847?u=ed77f67e0bb069084639b24d812dbb2a2b1dc554&v=4
url: https://github.com/jgould22
- login: STeveShary
count: 37
avatarUrl: https://avatars.githubusercontent.com/u/5167622?u=de8f597c81d6336fcebc37b32dfd61a3f877160c&v=4
url: https://github.com/STeveShary
- login: adriangb
count: 36
avatarUrl: https://avatars.githubusercontent.com/u/1755071?u=81f0262df34e1460ca546fbd0c211169c2478532&v=4
url: https://github.com/adriangb
- login: prostomarkeloff
count: 33
avatarUrl: https://avatars.githubusercontent.com/u/28061158?u=72309cc1f2e04e40fa38b29969cb4e9d3f722e7b&v=4
url: https://github.com/prostomarkeloff
- login: frankie567
count: 31
avatarUrl: https://avatars.githubusercontent.com/u/1144727?u=85c025e3fcc7bd79a5665c63ee87cdf8aae13374&v=4
url: https://github.com/frankie567
- login: krishnardt
count: 31
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: frankie567
count: 29
avatarUrl: https://avatars.githubusercontent.com/u/1144727?u=85c025e3fcc7bd79a5665c63ee87cdf8aae13374&v=4
url: https://github.com/frankie567
- login: chbndrhnns
count: 28
avatarUrl: https://avatars.githubusercontent.com/u/7534547?v=4
url: https://github.com/chbndrhnns
- login: panla
count: 26
avatarUrl: https://avatars.githubusercontent.com/u/41326348?u=ba2fda6b30110411ecbf406d187907e2b420ac19&v=4
url: https://github.com/panla
- login: ghandic
count: 25
avatarUrl: https://avatars.githubusercontent.com/u/23500353?u=e2e1d736f924d9be81e8bfc565b6d8836ba99773&v=4
url: https://github.com/ghandic
- login: dbanty
count: 25
avatarUrl: https://avatars.githubusercontent.com/u/43723790?u=9bcce836bbce55835291c5b2ac93a4e311f4b3c3&v=4
url: https://github.com/dbanty
- login: chbndrhnns
count: 24
avatarUrl: https://avatars.githubusercontent.com/u/7534547?v=4
url: https://github.com/chbndrhnns
- login: SirTelemak
count: 24
avatarUrl: https://avatars.githubusercontent.com/u/9435877?u=719327b7d2c4c62212456d771bfa7c6b8dbb9eac&v=4
url: https://github.com/SirTelemak
- login: STeveShary
count: 24
avatarUrl: https://avatars.githubusercontent.com/u/5167622?u=de8f597c81d6336fcebc37b32dfd61a3f877160c&v=4
url: https://github.com/STeveShary
- login: acnebs
count: 22
avatarUrl: https://avatars.githubusercontent.com/u/9054108?u=bfd127b3e6200f4d00afd714f0fc95c2512df19b&v=4
avatarUrl: https://avatars.githubusercontent.com/u/9054108?u=c27e50269f1ef8ea950cc6f0268c8ec5cebbe9c9&v=4
url: https://github.com/acnebs
- login: nsidnev
count: 22
@@ -105,18 +121,14 @@ experts:
count: 19
avatarUrl: https://avatars.githubusercontent.com/u/24581770?v=4
url: https://github.com/retnikt
- login: ghandic
- login: acidjunk
count: 18
avatarUrl: https://avatars.githubusercontent.com/u/23500353?u=e2e1d736f924d9be81e8bfc565b6d8836ba99773&v=4
url: https://github.com/ghandic
avatarUrl: https://avatars.githubusercontent.com/u/685002?u=b5094ab4527fc84b006c0ac9ff54367bdebb2267&v=4
url: https://github.com/acidjunk
- login: Hultner
count: 18
avatarUrl: https://avatars.githubusercontent.com/u/2669034?u=115e53df959309898ad8dc9443fbb35fee71df07&v=4
url: https://github.com/Hultner
- login: panla
count: 18
avatarUrl: https://avatars.githubusercontent.com/u/41326348?u=ba2fda6b30110411ecbf406d187907e2b420ac19&v=4
url: https://github.com/panla
- login: jorgerpo
count: 17
avatarUrl: https://avatars.githubusercontent.com/u/12537771?u=7444d20019198e34911082780cc7ad73f2b97cb3&v=4
@@ -125,26 +137,50 @@ experts:
count: 17
avatarUrl: https://avatars.githubusercontent.com/u/28262306?u=66ee21316275ef356081c2efc4ed7a4572e690dc&v=4
url: https://github.com/nkhitrov
- login: adriangb
- login: harunyasar
count: 17
avatarUrl: https://avatars.githubusercontent.com/u/1755071?u=81f0262df34e1460ca546fbd0c211169c2478532&v=4
url: https://github.com/adriangb
avatarUrl: https://avatars.githubusercontent.com/u/1765494?u=5b1ab7c582db4b4016fa31affe977d10af108ad4&v=4
url: https://github.com/harunyasar
- login: rafsaf
count: 17
avatarUrl: https://avatars.githubusercontent.com/u/51059348?u=be9f06b8ced2d2b677297decc781fa8ce4f7ddbd&v=4
url: https://github.com/rafsaf
- login: waynerv
count: 16
avatarUrl: https://avatars.githubusercontent.com/u/39515546?u=ec35139777597cdbbbddda29bf8b9d4396b429a9&v=4
url: https://github.com/waynerv
- login: dstlny
count: 16
avatarUrl: https://avatars.githubusercontent.com/u/41964673?u=9f2174f9d61c15c6e3a4c9e3aeee66f711ce311f&v=4
url: https://github.com/dstlny
- login: haizaar
count: 13
avatarUrl: https://avatars.githubusercontent.com/u/58201?u=4f1f9843d69433ca0d380d95146cfe119e5fdac4&v=4
url: https://github.com/haizaar
- login: acidjunk
- login: valentin994
count: 13
avatarUrl: https://avatars.githubusercontent.com/u/685002?u=b5094ab4527fc84b006c0ac9ff54367bdebb2267&v=4
url: https://github.com/acidjunk
avatarUrl: https://avatars.githubusercontent.com/u/42819267?u=fdeeaa9242a59b243f8603496b00994f6951d5a2&v=4
url: https://github.com/valentin994
- login: hellocoldworld
count: 12
avatarUrl: https://avatars.githubusercontent.com/u/47581948?v=4
url: https://github.com/hellocoldworld
- login: David-Lor
count: 12
avatarUrl: https://avatars.githubusercontent.com/u/17401854?u=474680c02b94cba810cb9032fb7eb787d9cc9d22&v=4
url: https://github.com/David-Lor
- login: yinziyan1206
count: 12
avatarUrl: https://avatars.githubusercontent.com/u/37829370?v=4
url: https://github.com/yinziyan1206
- login: jonatasoli
count: 12
avatarUrl: https://avatars.githubusercontent.com/u/26334101?u=071c062d2861d3dd127f6b4a5258cd8ef55d4c50&v=4
url: https://github.com/jonatasoli
- login: lowercase00
count: 11
avatarUrl: https://avatars.githubusercontent.com/u/21188280?v=4
url: https://github.com/lowercase00
- login: zamiramir
count: 11
avatarUrl: https://avatars.githubusercontent.com/u/40475662?u=e58ef61034e8d0d6a312cc956fb09b9c3332b449&v=4
@@ -153,63 +189,35 @@ experts:
count: 11
avatarUrl: https://avatars.githubusercontent.com/u/8134632?v=4
url: https://github.com/juntatalor
- login: dstlny
- login: n8sty
count: 11
avatarUrl: https://avatars.githubusercontent.com/u/41964673?u=9f2174f9d61c15c6e3a4c9e3aeee66f711ce311f&v=4
url: https://github.com/dstlny
- login: valentin994
count: 11
avatarUrl: https://avatars.githubusercontent.com/u/42819267?u=fdeeaa9242a59b243f8603496b00994f6951d5a2&v=4
url: https://github.com/valentin994
avatarUrl: https://avatars.githubusercontent.com/u/2964996?v=4
url: https://github.com/n8sty
- 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
- login: hellocoldworld
count: 10
avatarUrl: https://avatars.githubusercontent.com/u/47581948?v=4
url: https://github.com/hellocoldworld
last_month_active:
- login: jgould22
count: 15
avatarUrl: https://avatars.githubusercontent.com/u/4335847?u=ed77f67e0bb069084639b24d812dbb2a2b1dc554&v=4
url: https://github.com/jgould22
- login: accelleon
count: 5
avatarUrl: https://avatars.githubusercontent.com/u/5001614?v=4
url: https://github.com/accelleon
- login: jonatasoli
count: 4
avatarUrl: https://avatars.githubusercontent.com/u/26334101?u=071c062d2861d3dd127f6b4a5258cd8ef55d4c50&v=4
url: https://github.com/jonatasoli
- login: Kludex
count: 13
avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=cf8455cb899806b774a3a71073f88583adec99f6&v=4
count: 4
avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=62adc405ef418f4b6c8caa93d3eb8ab107bc4927&v=4
url: https://github.com/Kludex
- login: ghandic
count: 12
avatarUrl: https://avatars.githubusercontent.com/u/23500353?u=e2e1d736f924d9be81e8bfc565b6d8836ba99773&v=4
url: https://github.com/ghandic
- login: STeveShary
count: 8
avatarUrl: https://avatars.githubusercontent.com/u/5167622?u=de8f597c81d6336fcebc37b32dfd61a3f877160c&v=4
url: https://github.com/STeveShary
- login: Honda-a
- login: yinziyan1206
count: 3
avatarUrl: https://avatars.githubusercontent.com/u/22759187?u=f45bd5fb17b4dca331529b8e9e5eab6122b84b8b&v=4
url: https://github.com/Honda-a
- login: frankie567
count: 3
avatarUrl: https://avatars.githubusercontent.com/u/1144727?u=85c025e3fcc7bd79a5665c63ee87cdf8aae13374&v=4
url: https://github.com/frankie567
- login: panla
count: 3
avatarUrl: https://avatars.githubusercontent.com/u/41326348?u=ba2fda6b30110411ecbf406d187907e2b420ac19&v=4
url: https://github.com/panla
- login: dstlny
count: 3
avatarUrl: https://avatars.githubusercontent.com/u/41964673?u=9f2174f9d61c15c6e3a4c9e3aeee66f711ce311f&v=4
url: https://github.com/dstlny
- login: trevorwang
count: 3
avatarUrl: https://avatars.githubusercontent.com/u/121966?v=4
url: https://github.com/trevorwang
- login: klaa97
count: 3
avatarUrl: https://avatars.githubusercontent.com/u/39653693?v=4
url: https://github.com/klaa97
avatarUrl: https://avatars.githubusercontent.com/u/37829370?v=4
url: https://github.com/yinziyan1206
top_contributors:
- login: waynerv
count: 25
@@ -223,6 +231,10 @@ top_contributors:
count: 16
avatarUrl: https://avatars.githubusercontent.com/u/35119617?u=58ed2a45798a4339700e2f62b2e12e6e54bf0396&v=4
url: https://github.com/dmontagu
- login: jaystone776
count: 15
avatarUrl: https://avatars.githubusercontent.com/u/11191137?u=299205a95e9b6817a43144a48b643346a5aac5cc&v=4
url: https://github.com/jaystone776
- login: euri10
count: 13
avatarUrl: https://avatars.githubusercontent.com/u/1104190?u=321a2e953e6645a7d09b732786c7a8061e0f8a8b&v=4
@@ -231,25 +243,25 @@ top_contributors:
count: 12
avatarUrl: https://avatars.githubusercontent.com/u/11489395?u=4adb6986bf3debfc2b8216ae701f2bd47d73da7d&v=4
url: https://github.com/mariacamilagl
- login: jaystone776
count: 11
avatarUrl: https://avatars.githubusercontent.com/u/11191137?u=299205a95e9b6817a43144a48b643346a5aac5cc&v=4
url: https://github.com/jaystone776
- login: Smlep
count: 9
avatarUrl: https://avatars.githubusercontent.com/u/16785985?v=4
url: https://github.com/Smlep
- login: Serrones
count: 8
avatarUrl: https://avatars.githubusercontent.com/u/22691749?u=4795b880e13ca33a73e52fc0ef7dc9c60c8fce47&v=4
url: https://github.com/Serrones
- login: Kludex
count: 8
avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=62adc405ef418f4b6c8caa93d3eb8ab107bc4927&v=4
url: https://github.com/Kludex
- login: RunningIkkyu
count: 7
avatarUrl: https://avatars.githubusercontent.com/u/31848542?u=706e1ee3f248245f2d68b976d149d06fd5a2010d&v=4
url: https://github.com/RunningIkkyu
- login: Kludex
count: 7
avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=cf8455cb899806b774a3a71073f88583adec99f6&v=4
url: https://github.com/Kludex
- login: hard-coders
count: 6
avatarUrl: https://avatars.githubusercontent.com/u/9651103?u=f2d3d2038c55d86d7f9348f4e6c5e30191e4ee8b&v=4
count: 7
avatarUrl: https://avatars.githubusercontent.com/u/9651103?u=95db33927bbff1ed1c07efddeb97ac2ff33068ed&v=4
url: https://github.com/hard-coders
- login: wshayes
count: 5
@@ -263,10 +275,6 @@ top_contributors:
count: 5
avatarUrl: https://avatars.githubusercontent.com/u/1175560?v=4
url: https://github.com/Attsun1031
- login: Smlep
count: 5
avatarUrl: https://avatars.githubusercontent.com/u/16785985?v=4
url: https://github.com/Smlep
- login: jekirl
count: 4
avatarUrl: https://avatars.githubusercontent.com/u/2546697?u=a027452387d85bd4a14834e19d716c99255fb3b7&v=4
@@ -275,14 +283,22 @@ top_contributors:
count: 4
avatarUrl: https://avatars.githubusercontent.com/u/805749?v=4
url: https://github.com/jfunez
- login: ycd
count: 4
avatarUrl: https://avatars.githubusercontent.com/u/62724709?u=826f228edf0bab0d19ad1d5c4ba4df1047ccffef&v=4
url: https://github.com/ycd
- login: komtaki
count: 4
avatarUrl: https://avatars.githubusercontent.com/u/39375566?u=260ad6b1a4b34c07dbfa728da5e586f16f6d1824&v=4
url: https://github.com/komtaki
- login: NinaHwang
count: 4
avatarUrl: https://avatars.githubusercontent.com/u/79563565?u=1741703bd6c8f491503354b363a86e879b4c1cab&v=4
url: https://github.com/NinaHwang
top_reviewers:
- login: Kludex
count: 90
avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=cf8455cb899806b774a3a71073f88583adec99f6&v=4
count: 93
avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=62adc405ef418f4b6c8caa93d3eb8ab107bc4927&v=4
url: https://github.com/Kludex
- login: waynerv
count: 47
@@ -297,17 +313,29 @@ top_reviewers:
avatarUrl: https://avatars.githubusercontent.com/u/41147016?u=55010621aece725aa702270b54fed829b6a1fe60&v=4
url: https://github.com/tokusumi
- login: ycd
count: 43
count: 45
avatarUrl: https://avatars.githubusercontent.com/u/62724709?u=826f228edf0bab0d19ad1d5c4ba4df1047ccffef&v=4
url: https://github.com/ycd
- login: cikay
count: 41
avatarUrl: https://avatars.githubusercontent.com/u/24587499?u=e772190a051ab0eaa9c8542fcff1892471638f2b&v=4
url: https://github.com/cikay
- login: BilalAlpaslan
count: 40
avatarUrl: https://avatars.githubusercontent.com/u/47563997?u=63ed66e304fe8d765762c70587d61d9196e5c82d&v=4
url: https://github.com/BilalAlpaslan
- login: AdrianDeAnda
count: 32
count: 33
avatarUrl: https://avatars.githubusercontent.com/u/1024932?u=bb7f8a0d6c9de4e9d0320a9f271210206e202250&v=4
url: https://github.com/AdrianDeAnda
- login: ArcLightSlavik
count: 27
avatarUrl: https://avatars.githubusercontent.com/u/31127044?u=81a84af39c89b898b0fbc5a04e8834f60f23e55a&v=4
count: 31
avatarUrl: https://avatars.githubusercontent.com/u/31127044?u=b0f2c37142f4b762e41ad65dc49581813422bd71&v=4
url: https://github.com/ArcLightSlavik
- login: cassiobotaro
count: 25
avatarUrl: https://avatars.githubusercontent.com/u/3127847?u=b0a652331da17efeb85cd6e3a4969182e5004804&v=4
url: https://github.com/cassiobotaro
- login: dmontagu
count: 23
avatarUrl: https://avatars.githubusercontent.com/u/35119617?u=58ed2a45798a4339700e2f62b2e12e6e54bf0396&v=4
@@ -316,22 +344,42 @@ top_reviewers:
count: 21
avatarUrl: https://avatars.githubusercontent.com/u/39375566?u=260ad6b1a4b34c07dbfa728da5e586f16f6d1824&v=4
url: https://github.com/komtaki
- login: cassiobotaro
- login: yezz123
count: 19
avatarUrl: https://avatars.githubusercontent.com/u/3127847?u=b0a652331da17efeb85cd6e3a4969182e5004804&v=4
url: https://github.com/cassiobotaro
avatarUrl: https://avatars.githubusercontent.com/u/52716203?u=636b4f79645176df4527dd45c12d5dbb5a4193cf&v=4
url: https://github.com/yezz123
- login: hard-coders
count: 19
avatarUrl: https://avatars.githubusercontent.com/u/9651103?u=95db33927bbff1ed1c07efddeb97ac2ff33068ed&v=4
url: https://github.com/hard-coders
- login: 0417taehyun
count: 19
avatarUrl: https://avatars.githubusercontent.com/u/63915557?u=47debaa860fd52c9b98c97ef357ddcec3b3fb399&v=4
url: https://github.com/0417taehyun
- login: zy7y
count: 17
avatarUrl: https://avatars.githubusercontent.com/u/67154681?u=5d634834cc514028ea3f9115f7030b99a1f4d5a4&v=4
url: https://github.com/zy7y
- login: yanever
count: 16
avatarUrl: https://avatars.githubusercontent.com/u/21978760?v=4
url: https://github.com/yanever
- login: lsglucas
count: 16
avatarUrl: https://avatars.githubusercontent.com/u/61513630?u=320e43fe4dc7bc6efc64e9b8f325f8075634fd20&v=4
url: https://github.com/lsglucas
- login: SwftAlpc
count: 16
avatarUrl: https://avatars.githubusercontent.com/u/52768429?u=6a3aa15277406520ad37f6236e89466ed44bc5b8&v=4
url: https://github.com/SwftAlpc
- login: hard-coders
- login: Smlep
count: 16
avatarUrl: https://avatars.githubusercontent.com/u/9651103?u=f2d3d2038c55d86d7f9348f4e6c5e30191e4ee8b&v=4
url: https://github.com/hard-coders
avatarUrl: https://avatars.githubusercontent.com/u/16785985?v=4
url: https://github.com/Smlep
- login: DevDae
count: 16
avatarUrl: https://avatars.githubusercontent.com/u/87962045?u=08e10fa516e844934f4b3fc7c38b33c61697e4a1&v=4
url: https://github.com/DevDae
- login: pedabraham
count: 15
avatarUrl: https://avatars.githubusercontent.com/u/16860088?u=abf922a7b920bf8fdb7867d8b43e091f1e796178&v=4
@@ -340,16 +388,8 @@ top_reviewers:
count: 15
avatarUrl: https://avatars.githubusercontent.com/u/63476957?u=6c86e59b48e0394d4db230f37fc9ad4d7e2c27c7&v=4
url: https://github.com/delhi09
- login: Smlep
count: 15
avatarUrl: https://avatars.githubusercontent.com/u/16785985?v=4
url: https://github.com/Smlep
- login: lsglucas
count: 14
avatarUrl: https://avatars.githubusercontent.com/u/61513630?u=320e43fe4dc7bc6efc64e9b8f325f8075634fd20&v=4
url: https://github.com/lsglucas
- login: rjNemo
count: 13
count: 14
avatarUrl: https://avatars.githubusercontent.com/u/56785022?u=d5c3a02567c8649e146fcfc51b6060ccaf8adef8&v=4
url: https://github.com/rjNemo
- login: RunningIkkyu
@@ -372,10 +412,22 @@ top_reviewers:
count: 10
avatarUrl: https://avatars.githubusercontent.com/u/7887703?v=4
url: https://github.com/maoyibo
- login: solomein-sv
count: 10
avatarUrl: https://avatars.githubusercontent.com/u/46193920?u=46acfb4aeefb1d7b9fdc5a8cbd9eb8744683c47a&v=4
url: https://github.com/solomein-sv
- login: graingert
count: 9
avatarUrl: https://avatars.githubusercontent.com/u/413772?v=4
url: https://github.com/graingert
- login: PandaHun
count: 9
avatarUrl: https://avatars.githubusercontent.com/u/13096845?u=646eba44db720e37d0dbe8e98e77ab534ea78a20&v=4
url: https://github.com/PandaHun
- login: kty4119
count: 9
avatarUrl: https://avatars.githubusercontent.com/u/49435654?v=4
url: https://github.com/kty4119
- login: bezaca
count: 9
avatarUrl: https://avatars.githubusercontent.com/u/69092910?u=4ac58eab99bd37d663f3d23551df96d4fbdbf760&v=4
@@ -384,6 +436,22 @@ top_reviewers:
count: 8
avatarUrl: https://avatars.githubusercontent.com/u/43393471?u=172b0e0391db1aa6c1706498d6dfcb003c8a4857&v=4
url: https://github.com/blt232018
- login: rogerbrinkmann
count: 8
avatarUrl: https://avatars.githubusercontent.com/u/5690226?v=4
url: https://github.com/rogerbrinkmann
- login: ComicShrimp
count: 8
avatarUrl: https://avatars.githubusercontent.com/u/43503750?u=b3e4d9a14d9a65d429ce62c566aef73178b7111d&v=4
url: https://github.com/ComicShrimp
- login: NinaHwang
count: 8
avatarUrl: https://avatars.githubusercontent.com/u/79563565?u=1741703bd6c8f491503354b363a86e879b4c1cab&v=4
url: https://github.com/NinaHwang
- login: dimaqq
count: 8
avatarUrl: https://avatars.githubusercontent.com/u/662249?v=4
url: https://github.com/dimaqq
- login: Serrones
count: 7
avatarUrl: https://avatars.githubusercontent.com/u/22691749?u=4795b880e13ca33a73e52fc0ef7dc9c60c8fce47&v=4
@@ -396,10 +464,6 @@ top_reviewers:
count: 7
avatarUrl: https://avatars.githubusercontent.com/u/10202690?u=e6f86f5c0c3026a15d6b51792fa3e532b12f1371&v=4
url: https://github.com/raphaelauv
- login: graingert
count: 7
avatarUrl: https://avatars.githubusercontent.com/u/413772?v=4
url: https://github.com/graingert
- login: NastasiaSaby
count: 7
avatarUrl: https://avatars.githubusercontent.com/u/8245071?u=b3afd005f9e4bf080c219ef61a592b3a8004b764&v=4
@@ -408,71 +472,23 @@ top_reviewers:
count: 7
avatarUrl: https://avatars.githubusercontent.com/u/1405026?v=4
url: https://github.com/Mause
- login: solomein-sv
- login: AlexandreBiguet
count: 7
avatarUrl: https://avatars.githubusercontent.com/u/46193920?u=46acfb4aeefb1d7b9fdc5a8cbd9eb8744683c47a&v=4
url: https://github.com/solomein-sv
- login: ComicShrimp
avatarUrl: https://avatars.githubusercontent.com/u/1483079?u=ff926455cd4cab03c6c49441aa5dc2b21df3e266&v=4
url: https://github.com/AlexandreBiguet
- login: krocdort
count: 7
avatarUrl: https://avatars.githubusercontent.com/u/43503750?u=b3e4d9a14d9a65d429ce62c566aef73178b7111d&v=4
url: https://github.com/ComicShrimp
avatarUrl: https://avatars.githubusercontent.com/u/34248814?v=4
url: https://github.com/krocdort
- login: jovicon
count: 6
avatarUrl: https://avatars.githubusercontent.com/u/21287303?u=b049eac3e51a4c0473c2efe66b4d28a7d8f2b572&v=4
url: https://github.com/jovicon
- login: BilalAlpaslan
- login: LorhanSohaky
count: 6
avatarUrl: https://avatars.githubusercontent.com/u/47563997?u=63ed66e304fe8d765762c70587d61d9196e5c82d&v=4
url: https://github.com/BilalAlpaslan
- 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: oandersonmagalhaes
count: 5
avatarUrl: https://avatars.githubusercontent.com/u/83456692?v=4
url: https://github.com/oandersonmagalhaes
- 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: izaguerreiro
count: 4
avatarUrl: https://avatars.githubusercontent.com/u/2241504?v=4
url: https://github.com/izaguerreiro
- login: aviramha
count: 4
avatarUrl: https://avatars.githubusercontent.com/u/41201924?u=6883cc4fc13a7b2e60d4deddd4be06f9c5287880&v=4
url: https://github.com/aviramha
- login: Cajuteq
count: 4
avatarUrl: https://avatars.githubusercontent.com/u/26676532?u=8ee0422981810e51480855de1c0d67b6b79cd3f2&v=4
url: https://github.com/Cajuteq
- login: Zxilly
count: 4
avatarUrl: https://avatars.githubusercontent.com/u/31370133?v=4
url: https://github.com/Zxilly
- login: dukkee
count: 4
avatarUrl: https://avatars.githubusercontent.com/u/36825394?u=ccfd86e6a4f2d093dad6f7544cc875af67fa2df8&v=4
url: https://github.com/dukkee
- login: Bluenix2
count: 4
avatarUrl: https://avatars.githubusercontent.com/u/38372706?u=c9d28aff15958d6ebf1971148bfb3154ff943c4f&v=4
url: https://github.com/Bluenix2
avatarUrl: https://avatars.githubusercontent.com/u/16273730?u=095b66f243a2cd6a0aadba9a095009f8aaf18393&v=4
url: https://github.com/LorhanSohaky
- login: peidrao
count: 6
avatarUrl: https://avatars.githubusercontent.com/u/32584628?u=88c2cb42a99e0f50cdeae3606992568184783ee5&v=4
url: https://github.com/peidrao

View File

@@ -2,6 +2,15 @@ gold:
- 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
- url: https://cryptapi.io/
title: "CryptAPI: Your easy to use, secure and privacy oriented payment gateway."
img: https://fastapi.tiangolo.com/img/sponsors/cryptapi.svg
- url: https://classiq.link/n4s
title: Join the team building a new SaaS platform that will change the computing world
img: https://fastapi.tiangolo.com/img/sponsors/classiq.png
- url: https://www.dropbase.io/careers
title: Dropbase - seamlessly collect, clean, and centralize data.
img: https://fastapi.tiangolo.com/img/sponsors/dropbase.svg
silver:
- url: https://www.deta.sh/?ref=fastapi
title: The launchpad for all your (team's) ideas
@@ -9,10 +18,7 @@ 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
- url: https://training.talkpython.fm/fastapi-courses
title: FastAPI video courses on demand from people you trust
img: https://fastapi.tiangolo.com/img/sponsors/talkpython.png
- url: https://testdriven.io/courses/tdd-fastapi/
@@ -21,7 +27,16 @@ silver:
- url: https://github.com/deepset-ai/haystack/
title: Build powerful search from composable, open source building blocks
img: https://fastapi.tiangolo.com/img/sponsors/haystack-fastapi.svg
- url: https://www.udemy.com/course/fastapi-rest/
title: Learn FastAPI by building a complete project. Extend your knowledge on advanced web development-AWS, Payments, Emails.
img: https://fastapi.tiangolo.com/img/sponsors/ines-course.jpg
- url: https://careers.budget-insight.com/
title: Budget Insight is hiring!
img: https://fastapi.tiangolo.com/img/sponsors/budget-insight.svg
bronze:
- url: https://calmcode.io
title: Code. Simply. Clearly. Calmly.
img: https://fastapi.tiangolo.com/img/sponsors/calmcode.jpg
- url: https://www.exoflare.com/open-source/?utm_source=FastAPI&utm_campaign=open_source
title: Biosecurity risk assessments made easy.
img: https://fastapi.tiangolo.com/img/sponsors/exoflare.png
- url: https://striveworks.us/careers?utm_source=fastapi&utm_medium=sponsor_banner&utm_campaign=feb_march#openings
title: https://striveworks.us/careers
img: https://fastapi.tiangolo.com/img/sponsors/striveworks.png

View File

@@ -2,7 +2,11 @@ logins:
- jina-ai
- deta
- investsuite
- vimsoHQ
- mikeckennedy
- koaning
- deepset-ai
- cryptapi
- Striveworks
- xoflare
- InesIvanova
- DropbaseHQ
- VincentParedes

View File

@@ -6,21 +6,9 @@ Being able to use asynchronous functions in your tests could be useful, for exam
Let's look at how we can make that work.
## pytest-asyncio
## pytest.mark.anyio
If we want to call asynchronous functions in our tests, our test functions have to be asynchronous. Pytest provides a neat library for this, called `pytest-asyncio`, that allows us to specify that some test functions are to be called asynchronously.
You can install it via:
<div class="termy">
```console
$ pip install pytest-asyncio
---> 100%
```
</div>
If we want to call asynchronous functions in our tests, our test functions have to be asynchronous. Anyio provides a neat plugin for this, that allows us to specify that some test functions are to be called asynchronously.
## HTTPX
@@ -66,7 +54,7 @@ $ pytest
## In Detail
The marker `@pytest.mark.asyncio` tells pytest that this test function should be called asynchronously:
The marker `@pytest.mark.anyio` tells pytest that this test function should be called asynchronously:
```Python hl_lines="7"
{!../../../docs_src/async_tests/test_main.py!}
@@ -97,4 +85,4 @@ that we used to make our requests with the `TestClient`.
As the testing function is now asynchronous, you can now also call (and `await`) other `async` functions apart from sending requests to your FastAPI application in your tests, exactly as you would call them anywhere else in your code.
!!! tip
If you encounter a `RuntimeError: Task attached to a different loop` when integrating asynchronous function calls in your tests (e.g. when using <a href="https://stackoverflow.com/questions/41584243/runtimeerror-task-attached-to-a-different-loop" class="external-link" target="_blank">MongoDB's MotorClient</a>) check out <a href="https://github.com/pytest-dev/pytest-asyncio/issues/38#issuecomment-264418154" class="external-link" target="_blank">this issue</a> in the pytest-asyncio repository.
If you encounter a `RuntimeError: Task attached to a different loop` when integrating asynchronous function calls in your tests (e.g. when using <a href="https://stackoverflow.com/questions/41584243/runtimeerror-task-attached-to-a-different-loop" class="external-link" target="_blank">MongoDB's MotorClient</a>) Remember to instantiate objects that need an event loop only within async functions, e.g. an `'@app.on_event("startup")` callback.

View File

@@ -152,21 +152,6 @@ After that, your file structure could look like:
└── swagger-ui.css
```
### Install `aiofiles`
Now you need to install `aiofiles`:
<div class="termy">
```console
$ pip install aiofiles
---> 100%
```
</div>
### Serve the static files
* Import `StaticFiles`.
@@ -248,3 +233,82 @@ Now, to be able to test that everything works, create a *path operation*:
Now, you should be able to disconnect your WiFi, go to your docs at <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>, and reload the page.
And even without Internet, you would be able to see the docs for your API and interact with it.
## Configuring Swagger UI
You can configure some extra <a href="https://swagger.io/docs/open-source-tools/swagger-ui/usage/configuration" class="external-link" target="_blank">Swagger UI parameters</a>.
To configure them, pass the `swagger_ui_parameters` argument when creating the `FastAPI()` app object or to the `get_swagger_ui_html()` function.
`swagger_ui_parameters` receives a dictionary with the configurations passed to Swagger UI directly.
FastAPI converts the configurations to **JSON** to make them compatible with JavaScript, as that's what Swagger UI needs.
### Disable Syntax Highlighting
For example, you could disable syntax highlighting in Swagger UI.
Without changing the settings, syntax highlighting is enabled by default:
<img src="/img/tutorial/extending-openapi/image02.png">
But you can disable it by setting `syntaxHighlight` to `False`:
```Python hl_lines="3"
{!../../../docs_src/extending_openapi/tutorial003.py!}
```
...and then Swagger UI won't show the syntax highlighting anymore:
<img src="/img/tutorial/extending-openapi/image03.png">
### Change the Theme
The same way you could set the syntax highlighting theme with the key `"syntaxHighlight.theme"` (notice that it has a dot in the middle):
```Python hl_lines="3"
{!../../../docs_src/extending_openapi/tutorial004.py!}
```
That configuration would change the syntax highlighting color theme:
<img src="/img/tutorial/extending-openapi/image04.png">
### Change Default Swagger UI Parameters
FastAPI includes some default configuration parameters appropriate for most of the use cases.
It includes these default configurations:
```Python
{!../../../fastapi/openapi/docs.py[ln:7-13]!}
```
You can override any of them by setting a different value in the argument `swagger_ui_parameters`.
For example, to disable `deepLinking` you could pass these settings to `swagger_ui_parameters`:
```Python hl_lines="3"
{!../../../docs_src/extending_openapi/tutorial005.py!}
```
### Other Swagger UI Parameters
To see all the other possible configurations you can use, read the official <a href="https://swagger.io/docs/open-source-tools/swagger-ui/usage/configuration" class="external-link" target="_blank">docs for Swagger UI parameters</a>.
### JavaScript-only settings
Swagger UI also allows other configurations to be **JavaScript-only** objects (for example, JavaScript functions).
FastAPI also includes these JavaScript-only `presets` settings:
```JavaScript
presets: [
SwaggerUIBundle.presets.apis,
SwaggerUIBundle.SwaggerUIStandalonePreset
]
```
These are **JavaScript** objects, not strings, so you can't pass them from Python code directly.
If you need to use JavaScript-only configurations like those, you can use one of the methods above. Override all the Swagger UI *path operation* and manually write any JavaScript you need.

View File

@@ -0,0 +1,267 @@
# Generate Clients
As **FastAPI** is based on the OpenAPI specification, you get automatic compatibility with many tools, including the automatic API docs (provided by Swagger UI).
One particular advantage that is not necessarily obvious is that you can **generate clients** (sometimes called <abbr title="Software Development Kits">**SDKs**</abbr> ) for your API, for many different **programming languages**.
## OpenAPI Client Generators
There are many tools to generate clients from **OpenAPI**.
A common tool is <a href="https://openapi-generator.tech/" class="external-link" target="_blank">OpenAPI Generator</a>.
If you are building a **frontend**, a very interesting alternative is <a href="https://github.com/ferdikoomen/openapi-typescript-codegen" class="external-link" target="_blank">openapi-typescript-codegen</a>.
## Generate a TypeScript Frontend Client
Let's start with a simple FastAPI application:
=== "Python 3.6 and above"
```Python hl_lines="9-11 14-15 18 19 23"
{!> ../../../docs_src/generate_clients/tutorial001.py!}
```
=== "Python 3.9 and above"
```Python hl_lines="7-9 12-13 16-17 21"
{!> ../../../docs_src/generate_clients/tutorial001_py39.py!}
```
Notice that the *path operations* define the models they use for request payload and response payload, using the models `Item` and `ResponseMessage`.
### API Docs
If you go to the API docs, you will see that it has the **schemas** for the data to be sent in requests and received in responses:
<img src="/img/tutorial/generate-clients/image01.png">
You can see those schemas because they were declared with the models in the app.
That information is available in the app's **OpenAPI schema**, and then shown in the API docs (by Swagger UI).
And that same information from the models that is included in OpenAPI is what can be used to **generate the client code**.
### Generate a TypeScript Client
Now that we have the app with the models, we can generate the client code for the frontend.
#### Install `openapi-typescript-codegen`
You can install `openapi-typescript-codegen` in your frontend code with:
<div class="termy">
```console
$ npm install openapi-typescript-codegen --save-dev
---> 100%
```
</div>
#### Generate Client Code
To generate the client code you can use the command line application `openapi` that would now be installed.
Because it is installed in the local project, you probably wouldn't be able to call that command directly, but you would put it on your `package.json` file.
It could look like this:
```JSON hl_lines="7"
{
"name": "frontend-app",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"generate-client": "openapi --input http://localhost:8000/openapi.json --output ./src/client --client axios"
},
"author": "",
"license": "",
"devDependencies": {
"openapi-typescript-codegen": "^0.20.1",
"typescript": "^4.6.2"
}
}
```
After having that NPM `generate-client` script there, you can run it with:
<div class="termy">
```console
$ npm run generate-client
frontend-app@1.0.0 generate-client /home/user/code/frontend-app
> openapi --input http://localhost:8000/openapi.json --output ./src/client --client axios
```
</div>
That command will generate code in `./src/client` and will use `axios` (the frontend HTTP library) internally.
### Try Out the Client Code
Now you can import and use the client code, it could look like this, notice that you get autocompletion for the methods:
<img src="/img/tutorial/generate-clients/image02.png">
You will also get autocompletion for the payload to send:
<img src="/img/tutorial/generate-clients/image03.png">
!!! tip
Notice the autocompletion for `name` and `price`, that was defined in the FastAPI application, in the `Item` model.
You will have inline errors for the data that you send:
<img src="/img/tutorial/generate-clients/image04.png">
The response object will also have autocompletion:
<img src="/img/tutorial/generate-clients/image05.png">
## FastAPI App with Tags
In many cases your FastAPI app will be bigger, and you will probably use tags to separate different groups of *path operations*.
For example, you could have a section for **items** and another section for **users**, and they could be separated by tags:
=== "Python 3.6 and above"
```Python hl_lines="23 28 36"
{!> ../../../docs_src/generate_clients/tutorial002.py!}
```
=== "Python 3.9 and above"
```Python hl_lines="21 26 34"
{!> ../../../docs_src/generate_clients/tutorial002_py39.py!}
```
### Generate a TypeScript Client with Tags
If you generate a client for a FastAPI app using tags, it will normally also separate the client code based on the tags.
This way you will be able to have things ordered and grouped correctly for the client code:
<img src="/img/tutorial/generate-clients/image06.png">
In this case you have:
* `ItemsService`
* `UsersService`
### Client Method Names
Right now the generated method names like `createItemItemsPost` don't look very clean:
```TypeScript
ItemsService.createItemItemsPost({name: "Plumbus", price: 5})
```
...that's because the client generator uses the OpenAPI internal **operation ID** for each *path operation*.
OpenAPI requires that each operation ID is unique across all the *path operations*, so FastAPI uses the **function name**, the **path**, and the **HTTP method/operation** to generate that operation ID, because that way it can make sure that the operation IDs are unique.
But I'll show you how to improve that next. 🤓
## Custom Operation IDs and Better Method Names
You can **modify** the way these operation IDs are **generated** to make them simpler and have **simpler method names** in the clients.
In this case you will have to ensure that each operation ID is **unique** in some other way.
For example, you could make sure that each *path operation* has a tag, and then generate the operation ID based on the **tag** and the *path operation* **name** (the function name).
### Custom Generate Unique ID Function
FastAPI uses a **unique ID** for each *path operation*, it is used for the **operation ID** and also for the names of any needed custom models, for requests or responses.
You can customize that function. It takes an `APIRoute` and outputs a string.
For example, here it is using the first tag (you will probably have only one tag) and the *path operation* name (the function name).
You can then pass that custom function to **FastAPI** as the `generate_unique_id_function` parameter:
=== "Python 3.6 and above"
```Python hl_lines="8-9 12"
{!> ../../../docs_src/generate_clients/tutorial003.py!}
```
=== "Python 3.9 and above"
```Python hl_lines="6-7 10"
{!> ../../../docs_src/generate_clients/tutorial003_py39.py!}
```
### Generate a TypeScript Client with Custom Operation IDs
Now if you generate the client again, you will see that it has the improved method names:
<img src="/img/tutorial/generate-clients/image07.png">
As you see, the method names now have the tag and then the function name, now they don't include information from the URL path and the HTTP operation.
### Preprocess the OpenAPI Specification for the Client Generator
The generated code still has some **duplicated information**.
We already know that this method is related to the **items** because that word is in the `ItemsService` (taken from the tag), but we still have the tag name prefixed in the method name too. 😕
We will probably still want to keep it for OpenAPI in general, as that will ensure that the operation IDs are **unique**.
But for the generated client we could **modify** the OpenAPI operation IDs right before generating the clients, just to make those method names nicer and **cleaner**.
We could download the OpenAPI JSON to a file `openapi.json` and then we could **remove that prefixed tag** with a script like this:
```Python
{!../../../docs_src/generate_clients/tutorial004.py!}
```
With that, the operation IDs would be renamed from things like `items-get_items` to just `get_items`, that way the client generator can generate simpler method names.
### Generate a TypeScript Client with the Preprocessed OpenAPI
Now as the end result is in a file `openapi.json`, you would modify the `package.json` to use that local file, for example:
```JSON hl_lines="7"
{
"name": "frontend-app",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"generate-client": "openapi --input ./openapi.json --output ./src/client --client axios"
},
"author": "",
"license": "",
"devDependencies": {
"openapi-typescript-codegen": "^0.20.1",
"typescript": "^4.6.2"
}
}
```
After generating the new client, you would now have **clean method names**, with all the **autocompletion**, **inline errors**, etc:
<img src="/img/tutorial/generate-clients/image08.png">
## Benefits
When using the automatically generated clients you would **autocompletion** for:
* Methods.
* Request payloads in the body, query parameters, etc.
* Response payloads.
You would also have **inline errors** for everything.
And whenever you update the backend code, and **regenerate** the frontend, it would have any new *path operations* available as methods, the old ones removed, and any other change would be reflected on the generated code. 🤓
This also means that if something changed it will be **reflected** on the client code automatically. And if you **build** the client it will error out if you have any **mismatch** in the data used.
So, you would **detect many errors** very early in the development cycle instead of having to wait for the errors to show up to your final users in production and then trying to debug where the problem is. ✨

View File

@@ -77,7 +77,7 @@ This *path operation*-specific OpenAPI schema is normally generated automaticall
!!! tip
This is a low level extension point.
If you only need to declare additonal responses, a more convenient way to do it is with [Additional Responses in OpenAPI](./additional-responses.md){.internal-link target=_blank}.
If you only need to declare additional responses, a more convenient way to do it is with [Additional Responses in OpenAPI](./additional-responses.md){.internal-link target=_blank}.
You can extend the OpenAPI schema for a *path operation* using the parameter `openapi_extra`.

View File

@@ -2,7 +2,7 @@
You can use any template engine you want with **FastAPI**.
A common election is Jinja2, the same one used by Flask and other tools.
A common choice is Jinja2, the same one used by Flask and other tools.
There are utilities to configure it easily that you can use directly in your **FastAPI** application (provided by Starlette).
@@ -20,18 +20,6 @@ $ pip install jinja2
</div>
If you need to also serve static files (as in this example), install `aiofiles`:
<div class="termy">
```console
$ pip install aiofiles
---> 100%
```
</div>
## Using `Jinja2Templates`
* Import `Jinja2Templates`.

View File

@@ -242,8 +242,6 @@ It was one of the first extremely fast Python frameworks based on `asyncio`. It
Falcon is another high performance Python framework, it is designed to be minimal, and work as the foundation of other frameworks like Hug.
It uses the previous standard for Python web frameworks (WSGI) which is synchronous, so it can't handle WebSockets and other use cases. Nevertheless, it also has a very good performance.
It is designed to have functions that receive two parameters, one "request" and one "response". Then you "read" parts from the request, and "write" parts to the response. Because of this design, it is not possible to declare request parameters and bodies with standard Python type hints as function parameters.
So, data validation, serialization, and documentation, have to be done in code, not automatically. Or they have to be implemented as a framework on top of Falcon, like Hug. This same distinction happens in other frameworks that are inspired by Falcon's design, of having one request object and one response object as parameters.

View File

@@ -324,7 +324,15 @@ So, about the egg and the chicken, how do you call the first `async` function?
If you are working with **FastAPI** you don't have to worry about that, because that "first" function will be your *path operation function*, and FastAPI will know how to do the right thing.
But if you want to use `async` / `await` without FastAPI, <a href="https://docs.python.org/3/library/asyncio-task.html#coroutine" class="external-link" target="_blank">check the official Python docs</a>.
But if you want to use `async` / `await` without FastAPI, you can do it as well.
### Write your own async code
Starlette (and **FastAPI**) are based on <a href="https://anyio.readthedocs.io/en/stable/" class="external-link" target="_blank">AnyIO</a>, which makes it compatible with both Python's standard library <a href="https://docs.python.org/3/library/asyncio-task.html" class="external-link" target="_blank">asyncio</a> and <a href="https://trio.readthedocs.io/en/stable/" class="external-link" target="_blank">Trio</a>.
In particular, you can directly use <a href="https://anyio.readthedocs.io/en/stable/" class="external-link" target="_blank">AnyIO</a> for your advanced concurrency use cases that require more advanced patterns in your own code.
And even if you were not using FastAPI, you could also write your own async applications with <a href="https://anyio.readthedocs.io/en/stable/" class="external-link" target="_blank">AnyIO</a> to be highly compatible and get its benefits (e.g. *structured concurrency*).
### Other forms of asynchronous code

View File

@@ -326,7 +326,7 @@ docs/es/docs/features.md
* Now open the MkDocs config file for English at:
```
docs/en/docs/mkdocs.yml
docs/en/mkdocs.yml
```
* Find the place where that `docs/features.md` is located in the config file. Somewhere like:
@@ -345,7 +345,7 @@ nav:
* Open the MkDocs config file for the language you are editing, e.g.:
```
docs/es/docs/mkdocs.yml
docs/es/mkdocs.yml
```
* Add it there at the exact same location it was for English, e.g.:

View File

@@ -21,7 +21,7 @@ By considering these concepts, you will be able to **evaluate and design** the b
In the next chapters, I'll give you more **concrete recipes** to deploy FastAPI applications.
But for now, let's check these important **conceptual ideas**. These concepts also apply for any other type of web API. 💡
But for now, let's check these important **conceptual ideas**. These concepts also apply to any other type of web API. 💡
## Security - HTTPS
@@ -47,7 +47,7 @@ Some of the tools you could use as a TLS Termination Proxy are:
* With an external component like cert-manager for certificate renewals
* Handled internally by a cloud provider as part of their services (read below 👇)
Another option is that you could use a **cloud service** that does more of the work including setting up HTTPS. It could have some restrictions or charge you more, etc. But in that case you wouldn't have to set up a TLS Termination Proxy yourself.
Another option is that you could use a **cloud service** that does more of the work including setting up HTTPS. It could have some restrictions or charge you more, etc. But in that case, you wouldn't have to set up a TLS Termination Proxy yourself.
I'll show you some concrete examples in the next chapters.
@@ -64,7 +64,7 @@ We will talk a lot about the running "**process**", so it's useful to have clari
The word **program** is commonly used to describe many things:
* The **code** that you write, the **Python files**.
* The **file** that can be **executed** by the operating system, for example `python`, `python.exe` or `uvicorn`.
* The **file** that can be **executed** by the operating system, for example: `python`, `python.exe` or `uvicorn`.
* A particular program while it is **running** on the operating system, using the CPU, and storing things on memory. This is also called a **process**.
### What is a Process
@@ -75,7 +75,7 @@ The word **process** is normally used in a more specific way, only referring to
* This doesn't refer to the file, nor to the code, it refers **specifically** to the thing that is being **executed** and managed by the operating system.
* Any program, any code, **can only do things** when it is being **executed**. So, when there's a **process running**.
* The process can be **terminated** (or "killed") by you, or by the operating system. At that point, it stops running/being executed, and it can **no longer do things**.
* Each application that you have running in your computer has some process behind it, each running program, each window, etc. And there are normally many processes running **at the same time** while a computer is on.
* Each application that you have running on your computer has some process behind it, each running program, each window, etc. And there are normally many processes running **at the same time** while a computer is on.
* There can be **multiple processes** of the **same program** running at the same time.
If you check out the "task manager" or "system monitor" (or similar tools) in your operating system, you will be able to see many of those processes running.
@@ -90,13 +90,13 @@ Now that we know the difference between the terms **process** and **program**, l
## Running on Startup
In most cases, when you create a web API, you want it to be **always running**, uninterrupted, so that your clients can always access it. This is of course, unless you have a specific reason why you want it to run only on certain situations, but most of the time you want it constantly running and **available**.
In most cases, when you create a web API, you want it to be **always running**, uninterrupted, so that your clients can always access it. This is of course, unless you have a specific reason why you want it to run only in certain situations, but most of the time you want it constantly running and **available**.
### In a Remote Server
When you set up a remote server (a cloud server, a virtual machine, etc.) the simplest thing you can do is to run Uvicorn (or similar) manually, the same way you do when developing locally.
And it will work, and will be useful **during development**.
And it will work and will be useful **during development**.
But if your connection to the server is lost, the **running process** will probably die.
@@ -108,7 +108,7 @@ In general, you will probably want the server program (e.g. Uvicorn) to be start
### Separate Program
To achieve this, you will normally have a **separate program** that would make sure your application is run on startup. And in many cases it would also make sure other components or applications are also run, for example a database.
To achieve this, you will normally have a **separate program** that would make sure your application is run on startup. And in many cases, it would also make sure other components or applications are also run, for example, a database.
### Example Tools to Run at Startup
@@ -177,7 +177,7 @@ For example, this could be handled by:
With a FastAPI application, using a server program like Uvicorn, running it once in **one process** can serve multiple clients concurrently.
But in many cases you will want to run several worker processes at the same time.
But in many cases, you will want to run several worker processes at the same time.
### Multiple Processes - Workers
@@ -197,11 +197,11 @@ So, to be able to have **multiple processes** at the same time, there has to be
Now, when the program loads things in memory, for example, a machine learning model in a variable, or the contents of a large file in a variable, all that **consumes a bit of the memory (RAM)** of the server.
And multiple processes normally **don't share any memory**. This means that each running process has its own things, its own variables, its own memory. And if you are consuming a large amount of memory in your code, **each process** will consume an equivalent amount of memory.
And multiple processes normally **don't share any memory**. This means that each running process has its own things, variables, and memory. And if you are consuming a large amount of memory in your code, **each process** will consume an equivalent amount of memory.
### Server Memory
For example, if your code loads a Machine Learning model with **1 GB in size**, when you run one process with your API, it will consume at least 1 GB or RAM. And if you start **4 processes** (4 workers), each will consume 1 GB of RAM. So, in total your API will consume **4 GB of RAM**.
For example, if your code loads a Machine Learning model with **1 GB in size**, when you run one process with your API, it will consume at least 1 GB of RAM. And if you start **4 processes** (4 workers), each will consume 1 GB of RAM. So in total, your API will consume **4 GB of RAM**.
And if your remote server or virtual machine only has 3 GB of RAM, trying to load more than 4 GB of RAM will cause problems. 🚨
@@ -253,12 +253,12 @@ But in most cases, you will want to perform these steps only **once**.
So, you will want to have a **single process** to perform those **previous steps**, before starting the application.
And you will have to make sure that it's a single process running those previous steps *even* if afterwards you start **multiple processes** (multiple workers) for the application itself. If those steps were run by **multiple processes**, they would **duplicate** the work by running it on **parallel**, and if the steps were something delicate like a database migration, they could cause conflicts with each other.
And you will have to make sure that it's a single process running those previous steps *even* if afterwards, you start **multiple processes** (multiple workers) for the application itself. If those steps were run by **multiple processes**, they would **duplicate** the work by running it on **parallel**, and if the steps were something delicate like a database migration, they could cause conflicts with each other.
Of course, there are some cases where there's no problem in running the previous steps multiple times, in that case it's a lot easier to handle.
Of course, there are some cases where there's no problem in running the previous steps multiple times, in that case, it's a lot easier to handle.
!!! tip
Also have in mind that depending on your setup, in some cases you **might not even need any previous steps** before starting your application.
Also, have in mind that depending on your setup, in some cases you **might not even need any previous steps** before starting your application.
In that case, you wouldn't have to worry about any of this. 🤷
@@ -279,7 +279,7 @@ Here are some possible ideas:
Your server(s) is (are) a **resource**, you can consume or **utilize**, with your programs, the computation time on the CPUs, and the RAM memory available.
How much resources do you want to be consuming/utilizing? It might be easy to think "not much", but in reality, you will probably want to consume **as much as possible without crashing**.
How much of the system resources do you want to be consuming/utilizing? It might be easy to think "not much", but in reality, you will probably want to consume **as much as possible without crashing**.
If you are paying for 3 servers but you are using only a little bit of their RAM and CPU, you are probably **wasting money** 💸, and probably **wasting server electric power** 🌎, etc.
@@ -291,9 +291,9 @@ In this case, it would be better to get **one extra server** and run some proces
There's also the chance that for some reason you have a **spike** of usage of your API. Maybe it went viral, or maybe some other services or bots start using it. And you might want to have extra resources to be safe in those cases.
You could put an **arbitrary number** to target, for example something **between 50% to 90%** of resource utilization. The point is that those are probably the main things you will want to measure and use to tweak your deployments.
You could put an **arbitrary number** to target, for example, something **between 50% to 90%** of resource utilization. The point is that those are probably the main things you will want to measure and use to tweak your deployments.
You can use simple tools like `htop` to see the CPU and RAM used in your server, or the amount used by each process. Or you can use more complex monitoring tools, maybe distributed across servers, etc.
You can use simple tools like `htop` to see the CPU and RAM used in your server or the amount used by each process. Or you can use more complex monitoring tools, which may be distributed across servers, etc.
## Recap
@@ -308,4 +308,4 @@ You have been reading here some of the main concepts that you would probably nee
Understanding these ideas and how to apply them should give you the intuition necessary to take any decisions when configuring and tweaking your deployments. 🤓
In the next sections I'll give you more concrete examples of possible strategies you can follow. 🚀
In the next sections, I'll give you more concrete examples of possible strategies you can follow. 🚀

View File

@@ -9,7 +9,7 @@ It will take you about **10 minutes**.
## A basic **FastAPI** app
* Create a directory for your app, for example `./fastapideta/` and enter in it.
* Create a directory for your app, for example, `./fastapideta/` and enter into it.
### FastAPI code
@@ -213,7 +213,7 @@ Now you can share that URL with anyone and they will be able to access your API.
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. ✅ 🔒
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
@@ -235,7 +235,7 @@ You can also edit them and re-play them.
## 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**.
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>.
@@ -253,6 +253,6 @@ Coming back to the concepts we discussed in [Deployments Concepts](./concepts.md
!!! note
Deta is designed to make it easy (and free) to deploy simple applications quickly.
It can simplify a lot several use cases, but at the same time it doesn't support others, like using external databases (apart from Deta's own NoSQL database system), custom virtual machines, etc.
It can simplify several use cases, but at the same time, it doesn't support others, like using external databases (apart from Deta's own NoSQL database system), custom virtual machines, etc.
You can read more details in the <a href="https://docs.deta.sh/docs/micros/about/" class="external-link" target="_blank">Deta docs</a> to see if it's the right choice for you.

View File

@@ -1,6 +1,6 @@
# FastAPI in Containers - Docker
When deploying FastAPI applications a common approach is to build a **Linux container image**. It's normally done using <a href="https://www.docker.com/" class="external-link" target="_blank">**Docker**</a>. And then you can deploy that container image in one of different possible ways.
When deploying FastAPI applications a common approach is to build a **Linux container image**. It's normally done using <a href="https://www.docker.com/" class="external-link" target="_blank">**Docker**</a>. You can then deploy that container image in one of a few possible ways.
Using Linux containers has several advantages including **security**, **replicability**, **simplicity**, and others.
@@ -68,13 +68,13 @@ And there are many other images for different things like databases, for example
* <a href="https://hub.docker.com/_/mongo" class="external-link" target="_blank">MongoDB</a>
* <a href="https://hub.docker.com/_/redis" class="external-link" target="_blank">Redis</a>, etc.
By using a pre-made container image it's very easy to **combine** and use different tools. For example, to try out a new database. In most cases you can use the **official images**, and just configure them with environment variables.
By using a pre-made container image it's very easy to **combine** and use different tools. For example, to try out a new database. In most cases, you can use the **official images**, and just configure them with environment variables.
That way, in many cases you can learn about containers and Docker and re-use that knowledge with many different tools and components.
So, you would run **multiple containers** with different things, like a database, a Python application, a web server with a React frontend application, and connect them together via their internal network.
All the container management systems (like Docker or Kubernetes) have these networking features integrated in them.
All the container management systems (like Docker or Kubernetes) have these networking features integrated into them.
## Containers and Processes
@@ -84,7 +84,7 @@ When a **container** is started, it will run that command/program (although you
A container is running as long as the **main process** (command or program) is running.
A container normally has a **single process**, but it's also possible to start subprocesses from the main process, and that way have **multiple processes** in the same container.
A container normally has a **single process**, but it's also possible to start subprocesses from the main process, and that way you will have **multiple processes** in the same container.
But it's not possible to have a running container without **at least one running process**. If the main process stops, the container stops.
@@ -137,7 +137,7 @@ Successfully installed fastapi pydantic uvicorn
### Create the **FastAPI** Code
* Create an `app` directory and enter in it.
* Create an `app` directory and enter it.
* Create an empty file `__init__.py`.
* Create a `main.py` file with:
@@ -216,7 +216,7 @@ CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80"]
6. Set the **command** to run the `uvicorn` server.
`CMD` takes a list of strings, each of this strings is what you would type in the command line separated by spaces.
`CMD` takes a list of strings, each of these strings is what you would type in the command line separated by spaces.
This command will be run from the **current working directory**, the same `/code` directory you set above with `WORKDIR /code`.
@@ -338,7 +338,7 @@ You will see the alternative automatic documentation (provided by <a href="https
## Build a Docker Image with a Single-File FastAPI
If your FastAPI is a single file, for example `main.py` without an `./app` directory, your file structure could look like:
If your FastAPI is a single file, for example, `main.py` without an `./app` directory, your file structure could look like this:
```
.
@@ -411,7 +411,7 @@ Without using containers, making applications run on startup and with restarts c
## Replication - Number of Processes
If you have a <abbr title="A group of machines that are configured to be connected and work together in some way.">cluster</abbr> of machines with **Kubernetes**, Docker Swarm Mode, Nomad, or other similar complex system to manage distributed containers on multiple machines, then you will probably want to **handle replication** at the **cluster level** instead of using a **process manager** (like Gunicorn with workers) in each container.
If you have a <abbr title="A group of machines that are configured to be connected and work together in some way.">cluster</abbr> of machines with **Kubernetes**, Docker Swarm Mode, Nomad, or another similar complex system to manage distributed containers on multiple machines, then you will probably want to **handle replication** at the **cluster level** instead of using a **process manager** (like Gunicorn with workers) in each container.
One of those distributed container management systems like Kubernetes normally has some integrated way of handling **replication of containers** while still supporting **load balancing** for the incoming requests. All at the **cluster level**.
@@ -487,7 +487,7 @@ The main point is, **none** of these are **rules written in stone** that you hav
## Memory
If you run **a single process per container** you will have a more or less well defined, stable, and limited amount of memory consumed by each of of those containers (more than one if they are replicated).
If you run **a single process per container** you will have a more or less well-defined, stable, and limited amount of memory consumed by each of those containers (more than one if they are replicated).
And then you can set those same memory limits and requirements in your configurations for your container management system (for example in **Kubernetes**). That way it will be able to **replicate the containers** in the **available machines** taking into account the amount of memory needed by them, and the amount available in the machines in the cluster.

View File

@@ -187,4 +187,4 @@ Having **HTTPS** is very important, and quite **critical** in most cases. Most o
But once you know the basic information of **HTTPS for developers** you can easily combine and configure different tools to help you manage everything in a simple way.
In some of the next chapters I'll show you several concrete examples of how to set up **HTTPS** for **FastAPI** applications. 🔒
In some of the next chapters, I'll show you several concrete examples of how to set up **HTTPS** for **FastAPI** applications. 🔒

View File

@@ -8,7 +8,7 @@ To **deploy** an application means to perform the necessary steps to make it **a
For a **web API**, it normally involves putting it in a **remote machine**, with a **server program** that provides good performance, stability, etc, so that your **users** can **access** the application efficiently and without interruptions or problems.
This is in contrast to the the **development** stages, where you are constantly changing the code, breaking it and fixing it, stopping and restarting the development server, etc.
This is in contrast to the **development** stages, where you are constantly changing the code, breaking it and fixing it, stopping and restarting the development server, etc.
## Deployment Strategies

View File

@@ -29,7 +29,7 @@ You can install an ASGI compatible server with:
<div class="termy">
```console
$ pip install uvicorn[standard]
$ pip install "uvicorn[standard]"
---> 100%
```
@@ -92,6 +92,43 @@ You can then your application the same way you have done in the tutorials, but w
It helps a lot during **development**, but you **shouldn't** use it in **production**.
## Hypercorn with Trio
Starlette and **FastAPI** are based on <a href="https://anyio.readthedocs.io/en/stable/" class="external-link" target="_blank">AnyIO</a>, which makes them compatible with both Python's standard library <a href="https://docs.python.org/3/library/asyncio-task.html" class="external-link" target="_blank">asyncio</a> and <a href="https://trio.readthedocs.io/en/stable/" class="external-link" target="_blank">Trio</a>.
Nevertheless, Uvicorn is currently only compatible with asyncio, and it normally uses <a href="https://github.com/MagicStack/uvloop" class="external-link" target="_blank">`uvloop`</a>, the high-performance drop-in replacement for `asyncio`.
But if you want to directly use **Trio**, then you can use **Hypercorn** as it supports it. ✨
### Install Hypercorn with Trio
First you need to install Hypercorn with Trio support:
<div class="termy">
```console
$ pip install "hypercorn[trio]"
---> 100%
```
</div>
### Run with Trio
Then you can pass the command line option `--worker-class` with the value `trio`:
<div class="termy">
```console
$ hypercorn main:app --worker-class trio
```
</div>
And that will start Hypercorn with your app using Trio as the backend.
Now you can use Trio internally in your app. Or even better, you can use AnyIO, to keep your code compatible with both Trio and asyncio. 🎉
## Deployment Concepts
These examples run the server program (e.g Uvicorn), starting **a single process**, listening on all the IPs (`0.0.0.0`) on a predefined port (e.g. `80`).

View File

@@ -20,7 +20,7 @@ Here I'll show you how to use <a href="https://gunicorn.org/" class="external-li
!!! info
If you are using containers, for example with Docker or Kubernetes, I'll tell you more about that in the next chapter: [FastAPI in Containers - Docker](./docker.md){.internal-link target=_blank}.
In particular, when running on **Kubernetes** you will probably **not** want to use Gunicorn, and instead run **a single Uvicorn process per container**, but I'll tell you about it later in that chapter.
In particular, when running on **Kubernetes** you will probably **not** want to use Gunicorn and instead run **a single Uvicorn process per container**, but I'll tell you about it later in that chapter.
## Gunicorn with Uvicorn Workers
@@ -39,7 +39,7 @@ And then the Gunicorn-compatible **Uvicorn worker** class would be in charge of
<div class="termy">
```console
$ pip install uvicorn[standard] gunicorn
$ pip install "uvicorn[standard]" gunicorn
---> 100%
```
@@ -90,7 +90,7 @@ Let's see what each of those options mean:
```
* So, the colon in `main:app` would be equivalent to the Python `import` part in `from main import app`.
* `--workers`: The number of worker processes to use, each will run a Uvicorn worker, in this case 4 workers.
* `--workers`: The number of worker processes to use, each will run a Uvicorn worker, in this case, 4 workers.
* `--worker-class`: The Gunicorn-compatible worker class to use in the worker processes.
* Here we pass the class that Gunicorn can import and use with:
@@ -101,7 +101,7 @@ Let's see what each of those options mean:
* `--bind`: This tells Gunicorn the IP and the port to listen to, using a colon (`:`) to separate the IP and the port.
* If you were running Uvicorn directly, instead of `--bind 0.0.0.0:80` (the Gunicorn option) you would use `--host 0.0.0.0` and `--port 80`.
In the output you can see that it shows the **PID** (process ID) of each process (it's just a number).
In the output, you can see that it shows the **PID** (process ID) of each process (it's just a number).
You can see that:

View File

@@ -121,7 +121,7 @@ Have in mind that as chats allow more "free conversation", it's easy to ask ques
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.
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 issues.
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. 😄

View File

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 36 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

View File

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 131 KiB

View File

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 108 KiB

View File

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 21 KiB

View 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.00002"
height="100"
viewBox="0 0 240.00002 100"
fill="none"
version="1.1"
id="svg35">
<metadata
id="metadata39">
<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>
<path
d="M 0,0 H 240.00002 V 100 H 0 Z"
fill="#ffffff"
id="path2"
style="stroke-width:0.0406002" />
<g
id="g908"
transform="translate(0,8.4984581)">
<path
d="m 89.098346,53.723081 c 6.816739,0 10.858339,-4.216615 10.858339,-11.208001 0,-6.969268 -4.0416,-11.164025 -10.705478,-11.164025 h -7.733908 v 22.372026 z m -3.52837,-3.506585 V 34.857603 h 3.451939 c 4.544493,0 6.914955,2.5344 6.914955,7.657477 0,5.145232 -2.370462,7.701416 -7.034955,7.701416 z m 18.062774,3.506585 h 3.95446 v -9.86437 c 0,-2.130092 1.60578,-3.637661 3.77945,-3.637661 0.66646,0 1.49649,0.120369 1.83507,0.229661 v -3.637736 c -0.36037,-0.06554 -0.98289,-0.109255 -1.42006,-0.109255 -1.92258,0 -3.52837,1.092222 -4.14018,3.03696 h -0.17465 v -2.796554 h -3.83409 z m 18.82449,0.327877 c 4.91557,0 8.04,-3.463015 8.04,-8.651816 0,-5.199877 -3.12443,-8.673564 -8.04,-8.673564 -4.91594,0 -8.04,3.473687 -8.04,8.673564 0,5.188801 3.12406,8.651816 8.04,8.651816 z m 0.0218,-3.168 c -2.72013,0 -4.05268,-2.425108 -4.05268,-5.494893 0,-3.069415 1.33255,-5.527385 4.05268,-5.527385 2.67618,0 4.0091,2.45797 4.0091,5.527385 0,3.069785 -1.33292,5.494893 -4.0091,5.494893 z m 11.37452,9.132185 h 3.95446 v -8.935754 h 0.16357 c 0.62289,1.223631 1.92259,2.938708 4.80665,2.938708 3.95446,0 6.91458,-3.135139 6.91458,-8.662524 0,-5.593108 -3.04763,-8.629995 -6.92566,-8.629995 -2.96012,0 -4.19446,1.780764 -4.79557,2.993318 h -0.22929 v -2.77477 h -3.88874 z m 3.87766,-14.681724 c 0,-3.255139 1.39828,-5.363446 3.94376,-5.363446 2.63261,0 3.98695,2.239384 3.98695,5.363446 0,3.146216 -1.37612,5.440247 -3.98695,5.440247 -2.52333,0 -3.94376,-2.184739 -3.94376,-5.440247 z m 15.52283,8.389662 h 3.88911 v -2.643692 h 0.22929 c 0.62253,1.223631 1.92259,2.938708 4.80665,2.938708 3.95446,0 6.91459,-3.135139 6.91459,-8.662524 0,-5.593108 -3.04764,-8.629995 -6.92567,-8.629995 -2.96049,0 -4.19483,1.780764 -4.79557,2.993318 h -0.16393 v -8.367841 h -3.95447 z m 3.87803,-8.389662 c 0,-3.255139 1.39828,-5.363446 3.94339,-5.363446 2.63298,0 3.98732,2.239384 3.98732,5.363446 0,3.146216 -1.37649,5.440247 -3.98732,5.440247 -2.52332,0 -3.94339,-2.184739 -3.94339,-5.440247 z m 20.15188,8.728247 c 2.63262,0 4.20554,-1.234339 4.92665,-2.643692 h 0.13108 v 2.305107 h 3.8016 V 42.493296 c 0,-4.434831 -3.61588,-5.767718 -6.81674,-5.767718 -3.52837,0 -6.23742,1.572887 -7.11139,4.631595 l 3.69231,0.524307 c 0.39323,-1.14683 1.50757,-2.130092 3.44086,-2.130092 1.83545,0 2.8405,0.939692 2.8405,2.589046 v 0.06572 c 0,1.135754 -1.19077,1.1904 -4.15127,1.507201 -3.25514,0.349661 -6.36849,1.321846 -6.36849,5.101661 0,3.298708 2.41403,5.046647 5.61489,5.046647 z m 1.02683,-2.905846 c -1.64972,0 -2.82941,-0.7536 -2.82941,-2.206524 0,-1.518277 1.32184,-2.151877 3.09157,-2.403323 1.03754,-0.141785 3.11335,-0.403938 3.62658,-0.819323 v 1.977231 c 0,1.868308 -1.50757,3.451939 -3.88874,3.451939 z m 25.07004,-9.776863 c -0.5461,-2.840123 -2.81834,-4.653379 -6.75065,-4.653379 -4.04197,0 -6.79495,1.988271 -6.78388,5.090549 -0.0111,2.446892 1.4965,4.063754 4.71914,4.729846 l 2.86191,0.601108 c 1.54043,0.338584 2.26117,0.961108 2.26117,1.911508 0,1.146831 -1.24505,2.010092 -3.12406,2.010092 -1.8133,0 -2.99299,-0.786461 -3.33194,-2.294031 l -3.85588,0.371446 c 0.49145,3.080493 3.08049,4.904862 7.19889,4.904862 4.19447,0 7.15496,-2.174031 7.16604,-5.352739 -0.0111,-2.392246 -1.55114,-3.856246 -4.71914,-4.544492 l -2.86228,-0.611816 c -1.704,-0.382154 -2.38117,-0.972184 -2.37046,-1.944369 -0.0107,-1.136123 1.24541,-1.922585 2.89477,-1.922585 1.82437,0 2.78584,0.993969 3.09157,2.0976 z m 11.0496,12.672001 c 3.91089,0 6.59815,-1.911877 7.29711,-4.828431 l -3.69231,-0.415015 c -0.53539,1.420061 -1.84616,2.162585 -3.55016,2.162585 -2.55618,0 -4.24947,-1.682216 -4.28233,-4.555201 h 11.68873 v -1.212554 c 0,-5.887754 -3.53944,-8.476764 -7.66855,-8.476764 -4.80665,0 -7.94179,3.528333 -7.94179,8.706426 0,5.265231 3.09157,8.618954 8.1493,8.618954 z m -4.21662,-10.30117 c 0.12,-2.141169 1.704,-3.943754 4.06376,-3.943754 2.27224,0 3.8016,1.660431 3.82338,3.943754 z"
fill="#161616"
id="path4"
style="stroke-width:0.0369231" />
<g
id="g898">
<g
filter="url(#filter0_d_2_165)"
id="g8"
transform="scale(0.03692308)">
<rect
x="454"
y="401"
width="1438"
height="1438"
rx="100"
fill="#ffffff"
id="rect6" />
</g>
<rect
x="21.821541"
y="19.864616"
width="42.978466"
height="42.978466"
rx="2.9887683"
fill="#161616"
id="rect10"
style="stroke-width:0.0369231" />
<path
d="m 41.202465,54.873605 h -7.07077 c -2.332837,0 -4.224,-1.891201 -4.224,-4.224001 V 32.064003 c 0,-2.332837 1.891163,-4.224001 4.224,-4.224001 h 7.07077 z"
fill="#ffffff"
id="path12"
style="stroke-width:0.0369231" />
<path
d="m 45.437542,29.205086 c 0,-0.583201 0.472616,-1.056001 1.056,-1.056001 h 7.07077 c 1.749785,0 3.168,1.418364 3.168,3.168001 v 7.919963 c 0,0.583385 -0.472615,1.056001 -1.056,1.056001 h -7.070769 c -1.749785,0 -3.168001,-1.418216 -3.168001,-3.168001 z"
fill="#ffffff"
id="path14"
style="stroke-width:0.0369231" />
<path
d="m 45.437542,43.77785 c 0,-0.583016 0.472616,-1.056 1.056,-1.056 h 7.07077 c 1.749785,0 3.168,1.418215 3.168,3.168 v 7.920001 c 0,0.583384 -0.472615,1.056 -1.056,1.056 h -7.070769 c -1.749785,0 -3.168001,-1.418216 -3.168001,-3.168001 z"
fill="#ffffff"
id="path16"
style="stroke-width:0.0369231" />
</g>
</g>
<defs
id="defs33">
<filter
id="filter0_d_2_165"
x="408"
y="355"
width="1538"
height="1538"
filterUnits="userSpaceOnUse"
color-interpolation-filters="sRGB">
<feFlood
flood-opacity="0"
result="BackgroundImageFix"
id="feFlood18" />
<feColorMatrix
in="SourceAlpha"
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
result="hardAlpha"
id="feColorMatrix20" />
<feOffset
dx="4"
dy="4"
id="feOffset22" />
<feGaussianBlur
stdDeviation="25"
id="feGaussianBlur24" />
<feColorMatrix
type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.5 0"
id="feColorMatrix26" />
<feBlend
mode="normal"
in2="BackgroundImageFix"
result="effect1_dropShadow_2_165"
id="feBlend28" />
<feBlend
mode="normal"
in="SourceGraphic"
in2="effect1_dropShadow_2_165"
result="shape"
id="feBlend30" />
</filter>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 7.3 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

View File

@@ -14,6 +14,9 @@
<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://pypi.org/project/fastapi" target="_blank">
<img src="https://img.shields.io/pypi/pyversions/fastapi.svg?color=%2334D058" alt="Supported Python versions">
</a>
</p>
---
@@ -131,7 +134,7 @@ You will also need an ASGI server, for production such as <a href="https://www.u
<div class="termy">
```console
$ pip install uvicorn[standard]
$ pip install "uvicorn[standard]"
---> 100%
```
@@ -443,7 +446,6 @@ Used by Pydantic:
Used by Starlette:
* <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="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.
@@ -455,7 +457,7 @@ Used by FastAPI / Starlette:
* <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]`.
You can install all of these with `pip install "fastapi[all]"`.
## License

View File

@@ -148,37 +148,62 @@ You can use, for example:
There are some data structures that can contain other values, like `dict`, `list`, `set` and `tuple`. And the internal values can have their own type too.
To declare those types and the internal types, you can use the standard Python module `typing`.
These types that have internal types are called "**generic**" types. And it's possible to declare them, even with their internal types.
It exists specifically to support these type hints.
To declare those types and the internal types, you can use the standard Python module `typing`. It exists specifically to support these type hints.
#### `List`
#### Newer versions of Python
The syntax using `typing` is **compatible** with all versions, from Python 3.6 to the latest ones, including Python 3.9, Python 3.10, etc.
As Python advances, **newer versions** come with improved support for these type annotations and in many cases you won't even need to import and use the `typing` module to declare the type annotations.
If you can chose a more recent version of Python for your project, you will be able to take advantage of that extra simplicity. See some examples below.
#### List
For example, let's define a variable to be a `list` of `str`.
From `typing`, import `List` (with a capital `L`):
=== "Python 3.6 and above"
```Python hl_lines="1"
{!../../../docs_src/python_types/tutorial006.py!}
```
From `typing`, import `List` (with a capital `L`):
Declare the variable, with the same colon (`:`) syntax.
``` Python hl_lines="1"
{!> ../../../docs_src/python_types/tutorial006.py!}
```
As the type, put the `List`.
Declare the variable, with the same colon (`:`) syntax.
As the list is a type that contains some internal types, you put them in square brackets:
As the type, put the `List` that you imported from `typing`.
```Python hl_lines="4"
{!../../../docs_src/python_types/tutorial006.py!}
```
As the list is a type that contains some internal types, you put them in square brackets:
!!! tip
```Python hl_lines="4"
{!> ../../../docs_src/python_types/tutorial006.py!}
```
=== "Python 3.9 and above"
Declare the variable, with the same colon (`:`) syntax.
As the type, put `list`.
As the list is a type that contains some internal types, you put them in square brackets:
```Python hl_lines="1"
{!> ../../../docs_src/python_types/tutorial006_py39.py!}
```
!!! info
Those internal types in the square brackets are called "type parameters".
In this case, `str` is the type parameter passed to `List`.
In this case, `str` is the type parameter passed to `List` (or `list` in Python 3.9 and above).
That means: "the variable `items` is a `list`, and each of the items in this list is a `str`".
!!! tip
If you use Python 3.9 or above, you don't have to import `List` from `typing`, you can use the same regular `list` type instead.
By doing that, your editor can provide support even while processing items from the list:
<img src="/img/python-types/image05.png">
@@ -189,20 +214,28 @@ Notice that the variable `item` is one of the elements in the list `items`.
And still, the editor knows it is a `str`, and provides support for that.
#### `Tuple` and `Set`
#### Tuple and Set
You would do the same to declare `tuple`s and `set`s:
```Python hl_lines="1 4"
{!../../../docs_src/python_types/tutorial007.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="1 4"
{!> ../../../docs_src/python_types/tutorial007.py!}
```
=== "Python 3.9 and above"
```Python hl_lines="1"
{!> ../../../docs_src/python_types/tutorial007_py39.py!}
```
This means:
* The variable `items_t` is a `tuple` with 3 items, an `int`, another `int`, and a `str`.
* The variable `items_s` is a `set`, and each of its items is of type `bytes`.
#### `Dict`
#### Dict
To define a `dict`, you pass 2 type parameters, separated by commas.
@@ -210,9 +243,17 @@ The first type parameter is for the keys of the `dict`.
The second type parameter is for the values of the `dict`:
```Python hl_lines="1 4"
{!../../../docs_src/python_types/tutorial008.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="1 4"
{!> ../../../docs_src/python_types/tutorial008.py!}
```
=== "Python 3.9 and above"
```Python hl_lines="1"
{!> ../../../docs_src/python_types/tutorial008_py39.py!}
```
This means:
@@ -220,9 +261,33 @@ This means:
* The keys of this `dict` are of type `str` (let's say, the name of each item).
* The values of this `dict` are of type `float` (let's say, the price of each item).
#### `Optional`
#### Union
You can also use `Optional` to declare that a variable has a type, like `str`, but that it is "optional", which means that it could also be `None`:
You can declare that a variable can be any of **several types**, for example, an `int` or a `str`.
In Python 3.6 and above (including Python 3.10) you can use the `Union` type from `typing` and put inside the square brackets the possible types to accept.
In Python 3.10 there's also an **alternative syntax** were you can put the possible types separated by a <abbr title='also called "bitwise or operator", but that meaning is not relevant here'>vertical bar (`|`)</abbr>.
=== "Python 3.6 and above"
```Python hl_lines="1 4"
{!> ../../../docs_src/python_types/tutorial008b.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="1"
{!> ../../../docs_src/python_types/tutorial008b_py310.py!}
```
In both cases this means that `item` could be an `int` or a `str`.
#### Possibly `None`
You can declare that a value could have a type, like `str`, but that it could also be `None`.
In Python 3.6 and above (including Python 3.10) you can declare it by importing and using `Optional` from the `typing` module.
```Python hl_lines="1 4"
{!../../../docs_src/python_types/tutorial009.py!}
@@ -230,18 +295,73 @@ You can also use `Optional` to declare that a variable has a type, like `str`, b
Using `Optional[str]` instead of just `str` will let the editor help you detecting errors where you could be assuming that a value is always a `str`, when it could actually be `None` too.
`Optional[Something]` is actually a shortcut for `Union[Something, None]`, they are equivalent.
This also means that in Python 3.10, you can use `Something | None`:
=== "Python 3.6 and above"
```Python hl_lines="1 4"
{!> ../../../docs_src/python_types/tutorial009.py!}
```
=== "Python 3.6 and above - alternative"
```Python hl_lines="1 4"
{!> ../../../docs_src/python_types/tutorial009b.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="1"
{!> ../../../docs_src/python_types/tutorial009_py310.py!}
```
#### Generic types
These types that take type parameters in square brackets, like:
These types that take type parameters in square brackets are called **Generic types** or **Generics**, for example:
* `List`
* `Tuple`
* `Set`
* `Dict`
* `Optional`
* ...and others.
=== "Python 3.6 and above"
are called **Generic types** or **Generics**.
* `List`
* `Tuple`
* `Set`
* `Dict`
* `Union`
* `Optional`
* ...and others.
=== "Python 3.9 and above"
You can use the same builtin types as generics (with square brakets and types inside):
* `list`
* `tuple`
* `set`
* `dict`
And the same as with Python 3.6, from the `typing` module:
* `Union`
* `Optional`
* ...and others.
=== "Python 3.10 and above"
You can use the same builtin types as generics (with square brakets and types inside):
* `list`
* `tuple`
* `set`
* `dict`
And the same as with Python 3.6, from the `typing` module:
* `Union`
* `Optional` (the same as with Python 3.6)
* ...and others.
In Python 3.10, as an alternative to using the generics `Union` and `Optional`, you can use the <abbr title='also called "bitwise or operator", but that meaning is not relevant here'>vertical bar (`|`)</abbr> to declare unions of types.
### Classes as types
@@ -275,11 +395,25 @@ Then you create an instance of that class with some values and it will validate
And you get all the editor support with that resulting object.
Taken from the official Pydantic docs:
An example from the official Pydantic docs:
```Python
{!../../../docs_src/python_types/tutorial011.py!}
```
=== "Python 3.6 and above"
```Python
{!> ../../../docs_src/python_types/tutorial011.py!}
```
=== "Python 3.9 and above"
```Python
{!> ../../../docs_src/python_types/tutorial011_py39.py!}
```
=== "Python 3.10 and above"
```Python
{!> ../../../docs_src/python_types/tutorial011_py310.py!}
```
!!! info
To learn more about <a href="https://pydantic-docs.helpmanual.io/" class="external-link" target="_blank">Pydantic, check its docs</a>.

View File

@@ -2,6 +2,300 @@
## Latest Changes
## 0.76.0
### Upgrades
* ⬆ Upgrade Starlette from 0.17.1 to 0.18.0. PR [#4483](https://github.com/tiangolo/fastapi/pull/4483) by [@Kludex](https://github.com/Kludex).
### Internal
* 👥 Update FastAPI People. PR [#4847](https://github.com/tiangolo/fastapi/pull/4847) by [@github-actions[bot]](https://github.com/apps/github-actions).
* 🔧 Add Budget Insight sponsor. PR [#4824](https://github.com/tiangolo/fastapi/pull/4824) by [@tiangolo](https://github.com/tiangolo).
* 🍱 Update sponsor, ExoFlare badge. PR [#4822](https://github.com/tiangolo/fastapi/pull/4822) by [@tiangolo](https://github.com/tiangolo).
* 🔧 Update sponsors, enable Dropbase again, update TalkPython link. PR [#4821](https://github.com/tiangolo/fastapi/pull/4821) by [@tiangolo](https://github.com/tiangolo).
## 0.75.2
This release includes upgrades to third-party packages that handle security issues. Although there's a chance these issues don't affect you in particular, please upgrade as soon as possible.
### Fixes
* ✅ Fix new/recent tests with new fixed `ValidationError` JSON Schema. PR [#4806](https://github.com/tiangolo/fastapi/pull/4806) by [@tiangolo](https://github.com/tiangolo).
* 🐛 Fix JSON Schema for `ValidationError` at field `loc`. PR [#3810](https://github.com/tiangolo/fastapi/pull/3810) by [@dconathan](https://github.com/dconathan).
* 🐛 Fix support for prefix on APIRouter WebSockets. PR [#2640](https://github.com/tiangolo/fastapi/pull/2640) by [@Kludex](https://github.com/Kludex).
### Upgrades
* ⬆️ Update ujson ranges for CVE-2021-45958. PR [#4804](https://github.com/tiangolo/fastapi/pull/4804) by [@tiangolo](https://github.com/tiangolo).
* ⬆️ Upgrade dependencies upper range for extras "all". PR [#4803](https://github.com/tiangolo/fastapi/pull/4803) by [@tiangolo](https://github.com/tiangolo).
* ⬆ Upgrade Swagger UI - swagger-ui-dist@4. This handles a security issue in Swagger UI itself where it could be possible to inject HTML into Swagger UI. Please upgrade as soon as you can, in particular if you expose your Swagger UI (`/docs`) publicly to non-expert users. PR [#4347](https://github.com/tiangolo/fastapi/pull/4347) by [@RAlanWright](https://github.com/RAlanWright).
### Internal
* 🔧 Update sponsors, add: ExoFlare, Ines Course; remove: Dropbase, Vim.so, Calmcode; update: Striveworks, TalkPython and TestDriven.io. PR [#4805](https://github.com/tiangolo/fastapi/pull/4805) by [@tiangolo](https://github.com/tiangolo).
* ⬆️ Upgrade Codecov GitHub Action. PR [#4801](https://github.com/tiangolo/fastapi/pull/4801) by [@tiangolo](https://github.com/tiangolo).
## 0.75.1
### Translations
* 🌐 Start Dutch translations. PR [#4703](https://github.com/tiangolo/fastapi/pull/4703) by [@tiangolo](https://github.com/tiangolo).
* 🌐 Start Persian/Farsi translations. PR [#4243](https://github.com/tiangolo/fastapi/pull/4243) by [@aminalaee](https://github.com/aminalaee).
* ✏ Reword sentence about handling errors. PR [#1993](https://github.com/tiangolo/fastapi/pull/1993) by [@khuhroproeza](https://github.com/khuhroproeza).
### Internal
* 👥 Update FastAPI People. PR [#4752](https://github.com/tiangolo/fastapi/pull/4752) by [@github-actions[bot]](https://github.com/apps/github-actions).
* Temporarily remove typer-cli from dependencies and upgrade Black to unblock Pydantic CI. PR [#4754](https://github.com/tiangolo/fastapi/pull/4754) by [@tiangolo](https://github.com/tiangolo).
* 🔧 Add configuration to notify Dutch translations. PR [#4702](https://github.com/tiangolo/fastapi/pull/4702) by [@tiangolo](https://github.com/tiangolo).
* 👥 Update FastAPI People. PR [#4699](https://github.com/tiangolo/fastapi/pull/4699) by [@github-actions[bot]](https://github.com/apps/github-actions).
* 🐛 Fix FastAPI People generation to include missing file in commit. PR [#4695](https://github.com/tiangolo/fastapi/pull/4695) by [@tiangolo](https://github.com/tiangolo).
* 🔧 Update Classiq sponsor links. PR [#4688](https://github.com/tiangolo/fastapi/pull/4688) by [@tiangolo](https://github.com/tiangolo).
* 🔧 Add Classiq sponsor. PR [#4671](https://github.com/tiangolo/fastapi/pull/4671) by [@tiangolo](https://github.com/tiangolo).
* 📝 Add Jina's QA Bot to the docs to help people that want to ask quick questions. PR [#4655](https://github.com/tiangolo/fastapi/pull/4655) by [@tiangolo](https://github.com/tiangolo) based on original PR [#4626](https://github.com/tiangolo/fastapi/pull/4626) by [@hanxiao](https://github.com/hanxiao).
## 0.75.0
### Features
* ✨ Add support for custom `generate_unique_id_function` and docs for generating clients. New docs: [Advanced - Generate Clients](https://fastapi.tiangolo.com/advanced/generate-clients/). PR [#4650](https://github.com/tiangolo/fastapi/pull/4650) by [@tiangolo](https://github.com/tiangolo).
## 0.74.1
### Features
* ✨ Include route in scope to allow middleware and other tools to extract its information. PR [#4603](https://github.com/tiangolo/fastapi/pull/4603) by [@tiangolo](https://github.com/tiangolo).
## 0.74.0
### Breaking Changes
* ✨ Update internal `AsyncExitStack` to fix context for dependencies with `yield`. PR [#4575](https://github.com/tiangolo/fastapi/pull/4575) by [@tiangolo](https://github.com/tiangolo).
Dependencies with `yield` can now catch `HTTPException` and custom exceptions. For example:
```Python
async def get_database():
with Session() as session:
try:
yield session
except HTTPException:
session.rollback()
raise
finally:
session.close()
```
After the dependency with `yield` handles the exception (or not) the exception is raised again. So that any exception handlers can catch it, or ultimately the default internal `ServerErrorMiddleware`.
If you depended on exceptions not being received by dependencies with `yield`, and receiving an exception breaks the code after `yield`, you can use a block with `try` and `finally`:
```Python
async def do_something():
try:
yield something
finally:
some_cleanup()
```
...that way the `finally` block is run regardless of any exception that might happen.
### Features
* The same PR [#4575](https://github.com/tiangolo/fastapi/pull/4575) from above also fixes the `contextvars` context for the code before and after `yield`. This was the main objective of that PR.
This means that now, if you set a value in a context variable before `yield`, the value would still be available after `yield` (as you would intuitively expect). And it also means that you can reset the context variable with a token afterwards.
For example, this works correctly now:
```Python
from contextvars import ContextVar
from typing import Any, Dict, Optional
legacy_request_state_context_var: ContextVar[Optional[Dict[str, Any]]] = ContextVar(
"legacy_request_state_context_var", default=None
)
async def set_up_request_state_dependency():
request_state = {"user": "deadpond"}
contextvar_token = legacy_request_state_context_var.set(request_state)
yield request_state
legacy_request_state_context_var.reset(contextvar_token)
```
...before this change it would raise an error when resetting the context variable, because the `contextvars` context was different, because of the way it was implemented.
**Note**: You probably don't need `contextvars`, and you should probably avoid using them. But they are powerful and useful in some advanced scenarios, for example, migrating from code that used Flask's `g` semi-global variable.
**Technical Details**: If you want to know more of the technical details you can check out the PR description [#4575](https://github.com/tiangolo/fastapi/pull/4575).
### Internal
* 🔧 Add Striveworks sponsor. PR [#4596](https://github.com/tiangolo/fastapi/pull/4596) by [@tiangolo](https://github.com/tiangolo).
* 💚 Only build docs on push when on master to avoid duplicate runs from PRs. PR [#4564](https://github.com/tiangolo/fastapi/pull/4564) by [@tiangolo](https://github.com/tiangolo).
* 👥 Update FastAPI People. PR [#4502](https://github.com/tiangolo/fastapi/pull/4502) by [@github-actions[bot]](https://github.com/apps/github-actions).
## 0.73.0
### Features
* ✨ Add support for declaring `UploadFile` parameters without explicit `File()`. PR [#4469](https://github.com/tiangolo/fastapi/pull/4469) by [@tiangolo](https://github.com/tiangolo). New docs: [Request Files - File Parameters with UploadFile](https://fastapi.tiangolo.com/tutorial/request-files/#file-parameters-with-uploadfile).
* ✨ Add support for tags with Enums. PR [#4468](https://github.com/tiangolo/fastapi/pull/4468) by [@tiangolo](https://github.com/tiangolo). New docs: [Path Operation Configuration - Tags with Enums](https://fastapi.tiangolo.com/tutorial/path-operation-configuration/#tags-with-enums).
* ✨ Allow hiding from OpenAPI (and Swagger UI) `Query`, `Cookie`, `Header`, and `Path` parameters. PR [#3144](https://github.com/tiangolo/fastapi/pull/3144) by [@astraldawn](https://github.com/astraldawn). New docs: [Query Parameters and String Validations - Exclude from OpenAPI](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#exclude-from-openapi).
### Docs
* 📝 Tweak and improve docs for Request Files. PR [#4470](https://github.com/tiangolo/fastapi/pull/4470) by [@tiangolo](https://github.com/tiangolo).
### Fixes
* 🐛 Fix bug preventing to use OpenAPI when using tuples. PR [#3874](https://github.com/tiangolo/fastapi/pull/3874) by [@victorbenichoux](https://github.com/victorbenichoux).
* 🐛 Prefer custom encoder over defaults if specified in `jsonable_encoder`. PR [#2061](https://github.com/tiangolo/fastapi/pull/2061) by [@viveksunder](https://github.com/viveksunder).
* 💚 Duplicate PR to trigger CI. PR [#4467](https://github.com/tiangolo/fastapi/pull/4467) by [@tiangolo](https://github.com/tiangolo).
### Internal
* 🐛 Fix docs dependencies cache, to get the latest Material for MkDocs. PR [#4466](https://github.com/tiangolo/fastapi/pull/4466) by [@tiangolo](https://github.com/tiangolo).
* 🔧 Add sponsor Dropbase. PR [#4465](https://github.com/tiangolo/fastapi/pull/4465) by [@tiangolo](https://github.com/tiangolo).
## 0.72.0
### Features
* ✨ Enable configuring Swagger UI parameters. Original PR [#2568](https://github.com/tiangolo/fastapi/pull/2568) by [@jmriebold](https://github.com/jmriebold). Here are the new docs: [Configuring Swagger UI](https://fastapi.tiangolo.com/advanced/extending-openapi/#configuring-swagger-ui).
### Docs
* 📝 Update Python Types docs, add missing 3.6 / 3.9 example. PR [#4434](https://github.com/tiangolo/fastapi/pull/4434) by [@tiangolo](https://github.com/tiangolo).
### Translations
* 🌐 Update Chinese translation for `docs/help-fastapi.md`. PR [#3847](https://github.com/tiangolo/fastapi/pull/3847) by [@jaystone776](https://github.com/jaystone776).
* 🌐 Fix Korean translation for `docs/ko/docs/index.md`. PR [#4195](https://github.com/tiangolo/fastapi/pull/4195) by [@kty4119](https://github.com/kty4119).
* 🌐 Add Polish translation for `docs/pl/docs/index.md`. PR [#4245](https://github.com/tiangolo/fastapi/pull/4245) by [@MicroPanda123](https://github.com/MicroPanda123).
* 🌐 Add Chinese translation for `docs\tutorial\path-operation-configuration.md`. PR [#3312](https://github.com/tiangolo/fastapi/pull/3312) by [@jaystone776](https://github.com/jaystone776).
### Internal
* 🔧 Enable MkDocs Material Insiders' `content.tabs.link`. PR [#4399](https://github.com/tiangolo/fastapi/pull/4399) by [@tiangolo](https://github.com/tiangolo).
## 0.71.0
### Features
* ✨ Add docs and tests for Python 3.9 and Python 3.10. PR [#3712](https://github.com/tiangolo/fastapi/pull/3712) by [@tiangolo](https://github.com/tiangolo).
* You can start with [Python Types Intro](https://fastapi.tiangolo.com/python-types/), it explains what changes between different Python versions, in Python 3.9 and in Python 3.10.
* All the FastAPI docs are updated. Each code example in the docs that could use different syntax in Python 3.9 or Python 3.10 now has all the alternatives in tabs.
* ⬆️ Upgrade Starlette to 0.17.1. PR [#4145](https://github.com/tiangolo/fastapi/pull/4145) by [@simondale00](https://github.com/simondale00).
### Internal
* 👥 Update FastAPI People. PR [#4354](https://github.com/tiangolo/fastapi/pull/4354) by [@github-actions[bot]](https://github.com/apps/github-actions).
* 🔧 Add FastAPI Trove Classifier for PyPI as now there's one 🤷😁. PR [#4386](https://github.com/tiangolo/fastapi/pull/4386) by [@tiangolo](https://github.com/tiangolo).
* ⬆ Upgrade MkDocs Material and configs. PR [#4385](https://github.com/tiangolo/fastapi/pull/4385) by [@tiangolo](https://github.com/tiangolo).
## 0.70.1
There's nothing interesting in this particular FastAPI release. It is mainly to enable/unblock the release of the next version of Pydantic that comes packed with features and improvements. 🤩
### Fixes
* 🐛 Fix JSON Schema for dataclasses, supporting the fixes in Pydantic 1.9. PR [#4272](https://github.com/tiangolo/fastapi/pull/4272) by [@PrettyWood](https://github.com/PrettyWood).
### Translations
* 🌐 Add Korean translation for `docs/tutorial/request-forms-and-files.md`. PR [#3744](https://github.com/tiangolo/fastapi/pull/3744) by [@NinaHwang](https://github.com/NinaHwang).
* 🌐 Add Korean translation for `docs/tutorial/request-files.md`. PR [#3743](https://github.com/tiangolo/fastapi/pull/3743) by [@NinaHwang](https://github.com/NinaHwang).
* 🌐 Add portuguese translation for `docs/tutorial/query-params-str-validations.md`. PR [#3965](https://github.com/tiangolo/fastapi/pull/3965) by [@leandrodesouzadev](https://github.com/leandrodesouzadev).
* 🌐 Add Korean translation for `docs/tutorial/response-status-code.md`. PR [#3742](https://github.com/tiangolo/fastapi/pull/3742) by [@NinaHwang](https://github.com/NinaHwang).
* 🌐 Add Korean translation for Tutorial - JSON Compatible Encoder. PR [#3152](https://github.com/tiangolo/fastapi/pull/3152) by [@NEONKID](https://github.com/NEONKID).
* 🌐 Add Korean translation for Tutorial - Path Parameters and Numeric Validations. PR [#2432](https://github.com/tiangolo/fastapi/pull/2432) by [@hard-coders](https://github.com/hard-coders).
* 🌐 Add Korean translation for `docs/ko/docs/deployment/versions.md`. PR [#4121](https://github.com/tiangolo/fastapi/pull/4121) by [@DevDae](https://github.com/DevDae).
* 🌐 Fix Korean translation for `docs/ko/docs/tutorial/index.md`. PR [#4193](https://github.com/tiangolo/fastapi/pull/4193) by [@kimjaeyoonn](https://github.com/kimjaeyoonn).
* 🔧 Add CryptAPI sponsor. PR [#4264](https://github.com/tiangolo/fastapi/pull/4264) by [@tiangolo](https://github.com/tiangolo).
* 📝 Update `docs/tutorial/dependencies/classes-as-dependencies`: Add type of query parameters in a description of `Classes as dependencies`. PR [#4015](https://github.com/tiangolo/fastapi/pull/4015) by [@0417taehyun](https://github.com/0417taehyun).
* 🌐 Add French translation for Tutorial - First steps. PR [#3455](https://github.com/tiangolo/fastapi/pull/3455) by [@Smlep](https://github.com/Smlep).
* 🌐 Add French translation for `docs/tutorial/path-params.md`. PR [#3548](https://github.com/tiangolo/fastapi/pull/3548) by [@Smlep](https://github.com/Smlep).
* 🌐 Add French translation for `docs/tutorial/query-params.md`. PR [#3556](https://github.com/tiangolo/fastapi/pull/3556) by [@Smlep](https://github.com/Smlep).
* 🌐 Add Turkish translation for `docs/python-types.md`. PR [#3926](https://github.com/tiangolo/fastapi/pull/3926) by [@BilalAlpaslan](https://github.com/BilalAlpaslan).
### Internal
* 👥 Update FastAPI People. PR [#4274](https://github.com/tiangolo/fastapi/pull/4274) by [@github-actions[bot]](https://github.com/apps/github-actions).
## 0.70.0
This release just upgrades Starlette to the latest version, `0.16.0`, which includes several bug fixes and some small breaking changes.
These last **three consecutive releases** are independent so that you can **migrate gradually**:
* First to FastAPI `0.68.2`, with no breaking changes, but upgrading all the sub-dependencies.
* Next to FastAPI `0.69.0`, which upgrades Starlette to `0.15.0`, with AnyIO support, and a higher chance of having breaking changes in your code.
* Finally to FastAPI `0.70.0`, just upgrading Starlette to the latest version `0.16.0` with additional bug fixes.
This way, in case there was a breaking change for your code in one of the releases, you can still benefit from the previous upgrades. ✨
### Breaking Changes - Upgrade
* ⬆️ Upgrade Starlette to 0.16.0. PR [#4016](https://github.com/tiangolo/fastapi/pull/4016) by [@tiangolo](https://github.com/tiangolo).
Also upgrades the ranges of optional dependencies:
* `"jinja2 >=2.11.2,<4.0.0"`
* `"itsdangerous >=1.1.0,<3.0.0"`
## 0.69.0
### Breaking Changes - Upgrade
This release adds support for [Trio](https://trio.readthedocs.io/en/stable/). ✨
It upgrades the version of Starlette to `0.15.0`, now based on [AnyIO](https://anyio.readthedocs.io/en/stable/), and the internal async components in **FastAPI** are now based on AnyIO as well, making it compatible with both **asyncio** and **Trio**.
You can read the docs about running [FastAPI with Trio using Hypercorn](https://fastapi.tiangolo.com/deployment/manually/#hypercorn-with-trio).
This release also removes `graphene` as an optional dependency for GraphQL. If you need to work with GraphQL, the recommended library now is [Strawberry](https://strawberry.rocks/). You can read the new [FastAPI with GraphQL docs](https://fastapi.tiangolo.com/advanced/graphql/).
### Features
* ✨ Add support for Trio via AnyIO, upgrading Starlette to `0.15.0`. PR [#3372](https://github.com/tiangolo/fastapi/pull/3372) by [@graingert](https://github.com/graingert).
* Remove `graphene` as an optional dependency. PR [#4007](https://github.com/tiangolo/fastapi/pull/4007) by [@tiangolo](https://github.com/tiangolo).
### Docs
* 📝 Add docs for using Trio with Hypercorn. PR [#4014](https://github.com/tiangolo/fastapi/pull/4014) by [@tiangolo](https://github.com/tiangolo).
* ✏ Fix typos in Deployment Guide. PR [#3975](https://github.com/tiangolo/fastapi/pull/3975) by [@ghandic](https://github.com/ghandic).
* 📝 Update docs with pip install calls when using extras with brackets, use quotes for compatibility with Zsh. PR [#3131](https://github.com/tiangolo/fastapi/pull/3131) by [@tomwei7](https://github.com/tomwei7).
* 📝 Add external link to article: Deploying ML Models as API Using FastAPI and Heroku. PR [#3904](https://github.com/tiangolo/fastapi/pull/3904) by [@kaustubhgupta](https://github.com/kaustubhgupta).
* ✏ Fix typo in file paths in `docs/en/docs/contributing.md`. PR [#3752](https://github.com/tiangolo/fastapi/pull/3752) by [@NinaHwang](https://github.com/NinaHwang).
* ✏ Fix a typo in `docs/en/docs/advanced/path-operation-advanced-configuration.md` and `docs/en/docs/release-notes.md`. PR [#3750](https://github.com/tiangolo/fastapi/pull/3750) by [@saintmalik](https://github.com/saintmalik).
* ✏️ Add a missing comma in the security tutorial. PR [#3564](https://github.com/tiangolo/fastapi/pull/3564) by [@jalvaradosegura](https://github.com/jalvaradosegura).
* ✏ Fix typo in `docs/en/docs/help-fastapi.md`. PR [#3760](https://github.com/tiangolo/fastapi/pull/3760) by [@jaystone776](https://github.com/jaystone776).
* ✏ Fix typo about file path in `docs/en/docs/tutorial/bigger-applications.md`. PR [#3285](https://github.com/tiangolo/fastapi/pull/3285) by [@HolyDorus](https://github.com/HolyDorus).
* ✏ Re-word to clarify test client in `docs/en/docs/tutorial/testing.md`. PR [#3382](https://github.com/tiangolo/fastapi/pull/3382) by [@Bharat123rox](https://github.com/Bharat123rox).
* 📝 Fix incorrect highlighted code. PR [#3325](https://github.com/tiangolo/fastapi/pull/3325) by [@paxcodes](https://github.com/paxcodes).
* 📝 Add external link to article: How-to deploy FastAPI app to Heroku. PR [#3241](https://github.com/tiangolo/fastapi/pull/3241) by [@Jarmos-san](https://github.com/Jarmos-san).
* ✏ Fix typo (mistranslation) in `docs/en/docs/advanced/templates.md`. PR [#3211](https://github.com/tiangolo/fastapi/pull/3211) by [@oerpli](https://github.com/oerpli).
* 📝 Remove note about (now supported) feature from Swagger UI in `docs/en/docs/tutorial/request-files.md`. PR [#2803](https://github.com/tiangolo/fastapi/pull/2803) by [@gsganden](https://github.com/gsganden).
* ✏ Fix typo re-word in `docs/tutorial/handling-errors.md`. PR [#2700](https://github.com/tiangolo/fastapi/pull/2700) by [@graue70](https://github.com/graue70).
### Translations
* 🌐 Initialize Azerbaijani translations. PR [#3941](https://github.com/tiangolo/fastapi/pull/3941) by [@madatbay](https://github.com/madatbay).
* 🌐 Add Turkish translation for `docs/fastapi-people.md`. PR [#3848](https://github.com/tiangolo/fastapi/pull/3848) by [@BilalAlpaslan](https://github.com/BilalAlpaslan).
### Internal
* 📝 Add supported Python versions badge. PR [#2794](https://github.com/tiangolo/fastapi/pull/2794) by [@hramezani](https://github.com/hramezani).
* ✏ Fix link in Japanese docs for `docs/ja/docs/deployment/docker.md`. PR [#3245](https://github.com/tiangolo/fastapi/pull/3245) by [@utamori](https://github.com/utamori).
* 🔧 Correct DeprecationWarning config and comment in pytest settings. PR [#4008](https://github.com/tiangolo/fastapi/pull/4008) by [@graingert](https://github.com/graingert).
* 🔧 Swap light/dark theme button icon. PR [#3246](https://github.com/tiangolo/fastapi/pull/3246) by [@eddsalkield](https://github.com/eddsalkield).
* 🔧 Lint only in Python 3.7 and above. PR [#4006](https://github.com/tiangolo/fastapi/pull/4006) by [@tiangolo](https://github.com/tiangolo).
* 🔧 Add GitHub Action notify-translations config for Azerbaijani. PR [#3995](https://github.com/tiangolo/fastapi/pull/3995) by [@tiangolo](https://github.com/tiangolo).
## 0.68.2
This release has **no breaking changes**. 🎉
@@ -75,7 +369,7 @@ Soon there will be a new FastAPI release upgrading Starlette to take advantage o
### Features
* ✨ Add support for extensions and updates to the OpenAPI schema in each *path operation*. New docs: [FastAPI Path Operation Advanced Configuration - OpenAPI Extra](https://fastapi.tiangolo.com/advanced/path-operation-advanced-configuration/#openapi-extra). Initial PR [#1922](https://github.com/tiangolo/fastapi/pull/1922) by [@edouardlp](https://github.com/edouardlp).
* ✨ Add additonal OpenAPI metadata parameters to `FastAPI` class, shown on the automatic API docs UI. New docs: [Metadata and Docs URLs](https://fastapi.tiangolo.com/tutorial/metadata/). Initial PR [#1812](https://github.com/tiangolo/fastapi/pull/1812) by [@dkreeft](https://github.com/dkreeft).
* ✨ Add additional OpenAPI metadata parameters to `FastAPI` class, shown on the automatic API docs UI. New docs: [Metadata and Docs URLs](https://fastapi.tiangolo.com/tutorial/metadata/). Initial PR [#1812](https://github.com/tiangolo/fastapi/pull/1812) by [@dkreeft](https://github.com/dkreeft).
* ✨ Add `description` parameter to all the security scheme classes, e.g. `APIKeyQuery(name="key", description="A very cool API key")`. PR [#1757](https://github.com/tiangolo/fastapi/pull/1757) by [@hylkepostma](https://github.com/hylkepostma).
* ✨ Update OpenAPI models, supporting recursive models and extensions. PR [#3628](https://github.com/tiangolo/fastapi/pull/3628) by [@tiangolo](https://github.com/tiangolo).
* ✨ Import and re-export data structures from Starlette, used by Request properties, on `fastapi.datastructures`. Initial PR [#1872](https://github.com/tiangolo/fastapi/pull/1872) by [@jamescurtin](https://github.com/jamescurtin).

View File

@@ -57,9 +57,17 @@ Using `BackgroundTasks` also works with the dependency injection system, you can
**FastAPI** knows what to do in each case and how to re-use the same object, so that all the background tasks are merged together and are run in the background afterwards:
```Python hl_lines="13 15 22 25"
{!../../../docs_src/background_tasks/tutorial002.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="13 15 22 25"
{!> ../../../docs_src/background_tasks/tutorial002.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="11 13 20 23"
{!> ../../../docs_src/background_tasks/tutorial002_py310.py!}
```
In this example, the messages will be written to the `log.txt` file *after* the response is sent.

View File

@@ -234,7 +234,7 @@ 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 in there, find the module `dependencies` (the file at `app/dependencies.py`)...
* and from it, import the function `get_token_header`.
That works correctly! 🎉
@@ -252,7 +252,7 @@ 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 in there, find the module `dependencies` (the file at `app/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. 🚨

View File

@@ -6,9 +6,17 @@ The same way you can declare additional validation and metadata in *path operati
First, you have to import it:
```Python hl_lines="4"
{!../../../docs_src/body_fields/tutorial001.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="4"
{!> ../../../docs_src/body_fields/tutorial001.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="2"
{!> ../../../docs_src/body_fields/tutorial001_py310.py!}
```
!!! warning
Notice that `Field` is imported directly from `pydantic`, not from `fastapi` as are all the rest (`Query`, `Path`, `Body`, etc).
@@ -17,9 +25,17 @@ First, you have to import it:
You can then use `Field` with model attributes:
```Python hl_lines="11-14"
{!../../../docs_src/body_fields/tutorial001.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="11-14"
{!> ../../../docs_src/body_fields/tutorial001.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="9-12"
{!> ../../../docs_src/body_fields/tutorial001_py310.py!}
```
`Field` works the same way as `Query`, `Path` and `Body`, it has all the same parameters, etc.

View File

@@ -8,9 +8,17 @@ First, of course, you can mix `Path`, `Query` and request body parameter declara
And you can also declare body parameters as optional, by setting the default to `None`:
```Python hl_lines="19-21"
{!../../../docs_src/body_multiple_params/tutorial001.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="19-21"
{!> ../../../docs_src/body_multiple_params/tutorial001.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="17-19"
{!> ../../../docs_src/body_multiple_params/tutorial001_py310.py!}
```
!!! note
Notice that, in this case, the `item` that would be taken from the body is optional. As it has a `None` default value.
@@ -30,9 +38,17 @@ In the previous example, the *path operations* would expect a JSON body with the
But you can also declare multiple body parameters, e.g. `item` and `user`:
```Python hl_lines="22"
{!../../../docs_src/body_multiple_params/tutorial002.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="22"
{!> ../../../docs_src/body_multiple_params/tutorial002.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="20"
{!> ../../../docs_src/body_multiple_params/tutorial002_py310.py!}
```
In this case, **FastAPI** will notice that there are more than one body parameters in the function (two parameters that are Pydantic models).
@@ -71,14 +87,20 @@ If you declare it as is, because it is a singular value, **FastAPI** will assume
But you can instruct **FastAPI** to treat it as another body key using `Body`:
=== "Python 3.6 and above"
```Python hl_lines="23"
{!../../../docs_src/body_multiple_params/tutorial003.py!}
```
```Python hl_lines="23"
{!> ../../../docs_src/body_multiple_params/tutorial003.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="21"
{!> ../../../docs_src/body_multiple_params/tutorial003_py310.py!}
```
In this case, **FastAPI** will expect a body like:
```JSON
{
"item": {
@@ -107,12 +129,26 @@ As, by default, singular values are interpreted as query parameters, you don't h
q: Optional[str] = None
```
as in:
Or in Python 3.10 and above:
```Python hl_lines="27"
{!../../../docs_src/body_multiple_params/tutorial004.py!}
```Python
q: str | None = None
```
For example:
=== "Python 3.6 and above"
```Python hl_lines="28"
{!> ../../../docs_src/body_multiple_params/tutorial004.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="26"
{!> ../../../docs_src/body_multiple_params/tutorial004_py310.py!}
```
!!! info
`Body` also has all the same extra validation and metadata parameters as `Query`,`Path` and others you will see later.
@@ -131,9 +167,17 @@ item: Item = Body(..., embed=True)
as in:
```Python hl_lines="17"
{!../../../docs_src/body_multiple_params/tutorial005.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="17"
{!> ../../../docs_src/body_multiple_params/tutorial005.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="15"
{!> ../../../docs_src/body_multiple_params/tutorial005_py310.py!}
```
In this case **FastAPI** will expect a body like:

View File

@@ -6,9 +6,17 @@ With **FastAPI**, you can define, validate, document, and use arbitrarily deeply
You can define an attribute to be a subtype. For example, a Python `list`:
```Python hl_lines="14"
{!../../../docs_src/body_nested_models/tutorial001.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="14"
{!> ../../../docs_src/body_nested_models/tutorial001.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="12"
{!> ../../../docs_src/body_nested_models/tutorial001_py310.py!}
```
This will make `tags` be a list of items. Although it doesn't declare the type of each of the items.
@@ -18,19 +26,29 @@ But Python has a specific way to declare lists with internal types, or "type par
### Import typing's `List`
First, import `List` from standard Python's `typing` module:
In Python 3.9 and above you can use the standard `list` to declare these type annotations as we'll see below. 💡
But in Python versions before 3.9 (3.6 and above), you first need to import `List` from standard Python's `typing` module:
```Python hl_lines="1"
{!../../../docs_src/body_nested_models/tutorial002.py!}
{!> ../../../docs_src/body_nested_models/tutorial002.py!}
```
### Declare a `List` with a type parameter
### Declare a `list` with a type parameter
To declare types that have type parameters (internal types), like `list`, `dict`, `tuple`:
* Import them from the `typing` module
* If you are in a Python version lower than 3.9, import their equivalent version from the `typing` module
* Pass the internal type(s) as "type parameters" using square brackets: `[` and `]`
In Python 3.9 it would be:
```Python
my_list: list[str]
```
In versions of Python before 3.9, it would be:
```Python
from typing import List
@@ -43,9 +61,23 @@ Use that same standard syntax for model attributes with internal types.
So, in our example, we can make `tags` be specifically a "list of strings":
```Python hl_lines="14"
{!../../../docs_src/body_nested_models/tutorial002.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="14"
{!> ../../../docs_src/body_nested_models/tutorial002.py!}
```
=== "Python 3.9 and above"
```Python hl_lines="14"
{!> ../../../docs_src/body_nested_models/tutorial002_py39.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="12"
{!> ../../../docs_src/body_nested_models/tutorial002_py310.py!}
```
## Set types
@@ -53,11 +85,25 @@ But then we think about it, and realize that tags shouldn't repeat, they would p
And Python has a special data type for sets of unique items, the `set`.
Then we can import `Set` and declare `tags` as a `set` of `str`:
Then we can declare `tags` as a set of strings:
```Python hl_lines="1 14"
{!../../../docs_src/body_nested_models/tutorial003.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="1 14"
{!> ../../../docs_src/body_nested_models/tutorial003.py!}
```
=== "Python 3.9 and above"
```Python hl_lines="14"
{!> ../../../docs_src/body_nested_models/tutorial003_py39.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="12"
{!> ../../../docs_src/body_nested_models/tutorial003_py310.py!}
```
With this, even if you receive a request with duplicate data, it will be converted to a set of unique items.
@@ -79,17 +125,45 @@ All that, arbitrarily nested.
For example, we can define an `Image` model:
```Python hl_lines="9-11"
{!../../../docs_src/body_nested_models/tutorial004.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="9-11"
{!> ../../../docs_src/body_nested_models/tutorial004.py!}
```
=== "Python 3.9 and above"
```Python hl_lines="9-11"
{!> ../../../docs_src/body_nested_models/tutorial004_py39.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="7-9"
{!> ../../../docs_src/body_nested_models/tutorial004_py310.py!}
```
### Use the submodel as a type
And then we can use it as the type of an attribute:
```Python hl_lines="20"
{!../../../docs_src/body_nested_models/tutorial004.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="20"
{!> ../../../docs_src/body_nested_models/tutorial004.py!}
```
=== "Python 3.9 and above"
```Python hl_lines="20"
{!> ../../../docs_src/body_nested_models/tutorial004_py39.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="18"
{!> ../../../docs_src/body_nested_models/tutorial004_py310.py!}
```
This would mean that **FastAPI** would expect a body similar to:
@@ -122,9 +196,23 @@ To see all the options you have, checkout the docs for <a href="https://pydantic
For example, as in the `Image` model we have a `url` field, we can declare it to be instead of a `str`, a Pydantic's `HttpUrl`:
```Python hl_lines="4 10"
{!../../../docs_src/body_nested_models/tutorial005.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="4 10"
{!> ../../../docs_src/body_nested_models/tutorial005.py!}
```
=== "Python 3.9 and above"
```Python hl_lines="4 10"
{!> ../../../docs_src/body_nested_models/tutorial005_py39.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="2 8"
{!> ../../../docs_src/body_nested_models/tutorial005_py310.py!}
```
The string will be checked to be a valid URL, and documented in JSON Schema / OpenAPI as such.
@@ -132,9 +220,23 @@ The string will be checked to be a valid URL, and documented in JSON Schema / Op
You can also use Pydantic models as subtypes of `list`, `set`, etc:
```Python hl_lines="20"
{!../../../docs_src/body_nested_models/tutorial006.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="20"
{!> ../../../docs_src/body_nested_models/tutorial006.py!}
```
=== "Python 3.9 and above"
```Python hl_lines="20"
{!> ../../../docs_src/body_nested_models/tutorial006_py39.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="18"
{!> ../../../docs_src/body_nested_models/tutorial006_py310.py!}
```
This will expect (convert, validate, document, etc) a JSON body like:
@@ -169,9 +271,23 @@ This will expect (convert, validate, document, etc) a JSON body like:
You can define arbitrarily deeply nested models:
```Python hl_lines="9 14 20 23 27"
{!../../../docs_src/body_nested_models/tutorial007.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="9 14 20 23 27"
{!> ../../../docs_src/body_nested_models/tutorial007.py!}
```
=== "Python 3.9 and above"
```Python hl_lines="9 14 20 23 27"
{!> ../../../docs_src/body_nested_models/tutorial007_py39.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="7 12 18 21 25"
{!> ../../../docs_src/body_nested_models/tutorial007_py310.py!}
```
!!! info
Notice how `Offer` has a list of `Item`s, which in turn have an optional list of `Image`s
@@ -184,11 +300,25 @@ If the top level value of the JSON body you expect is a JSON `array` (a Python `
images: List[Image]
```
or in Python 3.9 and above:
```Python
images: list[Image]
```
as in:
```Python hl_lines="15"
{!../../../docs_src/body_nested_models/tutorial008.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="15"
{!> ../../../docs_src/body_nested_models/tutorial008.py!}
```
=== "Python 3.9 and above"
```Python hl_lines="13"
{!> ../../../docs_src/body_nested_models/tutorial008_py39.py!}
```
## Editor support everywhere
@@ -218,9 +348,17 @@ That's what we are going to see here.
In this case, you would accept any `dict` as long as it has `int` keys with `float` values:
```Python hl_lines="9"
{!../../../docs_src/body_nested_models/tutorial009.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="9"
{!> ../../../docs_src/body_nested_models/tutorial009.py!}
```
=== "Python 3.9 and above"
```Python hl_lines="7"
{!> ../../../docs_src/body_nested_models/tutorial009_py39.py!}
```
!!! tip
Have in mind that JSON only supports `str` as keys.

View File

@@ -6,9 +6,23 @@ To update an item you can use the <a href="https://developer.mozilla.org/en-US/d
You can use the `jsonable_encoder` to convert the input data to data that can be stored as JSON (e.g. with a NoSQL database). For example, converting `datetime` to `str`.
```Python hl_lines="30-35"
{!../../../docs_src/body_updates/tutorial001.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="30-35"
{!> ../../../docs_src/body_updates/tutorial001.py!}
```
=== "Python 3.9 and above"
```Python hl_lines="30-35"
{!> ../../../docs_src/body_updates/tutorial001_py39.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="28-33"
{!> ../../../docs_src/body_updates/tutorial001_py310.py!}
```
`PUT` is used to receive data that should replace the existing data.
@@ -53,9 +67,23 @@ That would generate a `dict` with only the data that was set when creating the `
Then you can use this to generate a `dict` with only the data that was set (sent in the request), omitting default values:
```Python hl_lines="34"
{!../../../docs_src/body_updates/tutorial002.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="34"
{!> ../../../docs_src/body_updates/tutorial002.py!}
```
=== "Python 3.9 and above"
```Python hl_lines="34"
{!> ../../../docs_src/body_updates/tutorial002_py39.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="32"
{!> ../../../docs_src/body_updates/tutorial002_py310.py!}
```
### Using Pydantic's `update` parameter
@@ -63,9 +91,23 @@ Now, you can create a copy of the existing model using `.copy()`, and pass the `
Like `stored_item_model.copy(update=update_data)`:
```Python hl_lines="35"
{!../../../docs_src/body_updates/tutorial002.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="35"
{!> ../../../docs_src/body_updates/tutorial002.py!}
```
=== "Python 3.9 and above"
```Python hl_lines="35"
{!> ../../../docs_src/body_updates/tutorial002_py39.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="33"
{!> ../../../docs_src/body_updates/tutorial002_py310.py!}
```
### Partial updates recap
@@ -82,9 +124,23 @@ In summary, to apply partial updates you would:
* Save the data to your DB.
* Return the updated model.
```Python hl_lines="30-37"
{!../../../docs_src/body_updates/tutorial002.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="30-37"
{!> ../../../docs_src/body_updates/tutorial002.py!}
```
=== "Python 3.9 and above"
```Python hl_lines="30-37"
{!> ../../../docs_src/body_updates/tutorial002_py39.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="28-35"
{!> ../../../docs_src/body_updates/tutorial002_py310.py!}
```
!!! tip
You can actually use this same technique with an HTTP `PUT` operation.

View File

@@ -19,9 +19,17 @@ To declare a **request** body, you use <a href="https://pydantic-docs.helpmanual
First, you need to import `BaseModel` from `pydantic`:
```Python hl_lines="4"
{!../../../docs_src/body/tutorial001.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="4"
{!> ../../../docs_src/body/tutorial001.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="2"
{!> ../../../docs_src/body/tutorial001_py310.py!}
```
## Create your data model
@@ -29,9 +37,17 @@ Then you declare your data model as a class that inherits from `BaseModel`.
Use standard Python types for all the attributes:
```Python hl_lines="7-11"
{!../../../docs_src/body/tutorial001.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="7-11"
{!> ../../../docs_src/body/tutorial001.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="5-9"
{!> ../../../docs_src/body/tutorial001_py310.py!}
```
The same as when declaring query parameters, when a model attribute has a default value, it is not required. Otherwise, it is required. Use `None` to make it just optional.
@@ -59,9 +75,17 @@ For example, this model above declares a JSON "`object`" (or Python `dict`) like
To add it to your *path operation*, declare it the same way you declared path and query parameters:
```Python hl_lines="18"
{!../../../docs_src/body/tutorial001.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="18"
{!> ../../../docs_src/body/tutorial001.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="16"
{!> ../../../docs_src/body/tutorial001_py310.py!}
```
...and declare its type as the model you created, `Item`.
@@ -125,9 +149,17 @@ But you would get the same editor support with <a href="https://www.jetbrains.co
Inside of the function, you can access all the attributes of the model object directly:
```Python hl_lines="21"
{!../../../docs_src/body/tutorial002.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="21"
{!> ../../../docs_src/body/tutorial002.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="19"
{!> ../../../docs_src/body/tutorial002_py310.py!}
```
## Request body + path parameters
@@ -135,9 +167,17 @@ 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**.
```Python hl_lines="17-18"
{!../../../docs_src/body/tutorial003.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="17-18"
{!> ../../../docs_src/body/tutorial003.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="15-16"
{!> ../../../docs_src/body/tutorial003_py310.py!}
```
## Request body + path + query parameters
@@ -145,9 +185,17 @@ You can also declare **body**, **path** and **query** parameters, all at the sam
**FastAPI** will recognize each of them and take the data from the correct place.
```Python hl_lines="18"
{!../../../docs_src/body/tutorial004.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="18"
{!> ../../../docs_src/body/tutorial004.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="16"
{!> ../../../docs_src/body/tutorial004_py310.py!}
```
The function parameters will be recognized as follows:

View File

@@ -6,9 +6,17 @@ You can define Cookie parameters the same way you define `Query` and `Path` para
First import `Cookie`:
```Python hl_lines="3"
{!../../../docs_src/cookie_params/tutorial001.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="3"
{!> ../../../docs_src/cookie_params/tutorial001.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="1"
{!> ../../../docs_src/cookie_params/tutorial001_py310.py!}
```
## Declare `Cookie` parameters
@@ -16,9 +24,17 @@ Then declare the cookie parameters using the same structure as with `Path` and `
The first value is the default value, you can pass all the extra validation or annotation parameters:
```Python hl_lines="9"
{!../../../docs_src/cookie_params/tutorial001.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="9"
{!> ../../../docs_src/cookie_params/tutorial001.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="7"
{!> ../../../docs_src/cookie_params/tutorial001_py310.py!}
```
!!! note "Technical Details"
`Cookie` is a "sister" class of `Path` and `Query`. It also inherits from the same common `Param` class.

View File

@@ -6,9 +6,17 @@ Before diving deeper into the **Dependency Injection** system, let's upgrade the
In the previous example, we were returning a `dict` from our dependency ("dependable"):
```Python hl_lines="9"
{!../../../docs_src/dependencies/tutorial001.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="9"
{!> ../../../docs_src/dependencies/tutorial001.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="7"
{!> ../../../docs_src/dependencies/tutorial001_py310.py!}
```
But then we get a `dict` in the parameter `commons` of the *path operation function*.
@@ -71,29 +79,53 @@ That also applies to callables with no parameters at all. The same as it would b
Then, we can change the dependency "dependable" `common_parameters` from above to the class `CommonQueryParams`:
```Python hl_lines="11-15"
{!../../../docs_src/dependencies/tutorial002.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="11-15"
{!> ../../../docs_src/dependencies/tutorial002.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="9-13"
{!> ../../../docs_src/dependencies/tutorial002_py310.py!}
```
Pay attention to the `__init__` method used to create the instance of the class:
```Python hl_lines="12"
{!../../../docs_src/dependencies/tutorial002.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="12"
{!> ../../../docs_src/dependencies/tutorial002.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="10"
{!> ../../../docs_src/dependencies/tutorial002_py310.py!}
```
...it has the same parameters as our previous `common_parameters`:
```Python hl_lines="8"
{!../../../docs_src/dependencies/tutorial001.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="8"
{!> ../../../docs_src/dependencies/tutorial001.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="6"
{!> ../../../docs_src/dependencies/tutorial001_py310.py!}
```
Those parameters are what **FastAPI** will use to "solve" the dependency.
In both cases, it will have:
* an optional `q` query parameter.
* a `skip` query parameter, with a default of `0`.
* a `limit` query parameter, with a default of `100`.
* An optional `q` query parameter that is a `str`.
* A `skip` query parameter that is an `int`, with a default of `0`.
* A `limit` query parameter that is an `int`, with a default of `100`.
In both cases the data will be converted, validated, documented on the OpenAPI schema, etc.
@@ -101,9 +133,17 @@ In both cases the data will be converted, validated, documented on the OpenAPI s
Now you can declare your dependency using this class.
```Python hl_lines="19"
{!../../../docs_src/dependencies/tutorial002.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="19"
{!> ../../../docs_src/dependencies/tutorial002.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="17"
{!> ../../../docs_src/dependencies/tutorial002_py310.py!}
```
**FastAPI** calls the `CommonQueryParams` class. This creates an "instance" of that class and the instance will be passed as the parameter `commons` to your function.
@@ -143,9 +183,17 @@ commons = Depends(CommonQueryParams)
..as in:
```Python hl_lines="19"
{!../../../docs_src/dependencies/tutorial003.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="19"
{!> ../../../docs_src/dependencies/tutorial003.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="17"
{!> ../../../docs_src/dependencies/tutorial003_py310.py!}
```
But declaring the type is encouraged as that way your editor will know what will be passed as the parameter `commons`, and then it can help you with code completion, type checks, etc:
@@ -179,9 +227,17 @@ You declare the dependency as the type of the parameter, and you use `Depends()`
The same example would then look like:
```Python hl_lines="19"
{!../../../docs_src/dependencies/tutorial004.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="19"
{!> ../../../docs_src/dependencies/tutorial004.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="17"
{!> ../../../docs_src/dependencies/tutorial004_py310.py!}
```
...and **FastAPI** will know what to do.

View File

@@ -7,15 +7,6 @@ To do this, use `yield` instead of `return`, and write the extra steps after.
!!! tip
Make sure to use `yield` one single time.
!!! info
For this to work, you need to use **Python 3.7** or above, or in **Python 3.6**, install the "backports":
```
pip install async-exit-stack async-generator
```
This installs <a href="https://github.com/sorcio/async_exit_stack" class="external-link" target="_blank">async-exit-stack</a> and <a href="https://github.com/python-trio/async_generator" class="external-link" target="_blank">async-generator</a>.
!!! note "Technical Details"
Any function that is valid to use with:
@@ -108,7 +99,7 @@ You saw that you can use dependencies with `yield` and have `try` blocks that ca
It might be tempting to raise an `HTTPException` or similar in the exit code, after the `yield`. But **it won't work**.
The exit code in dependencies with `yield` is executed *after* [Exception Handlers](../handling-errors.md#install-custom-exception-handlers){.internal-link target=_blank}. There's nothing catching exceptions thrown by your dependencies in the exit code (after the `yield`).
The exit code in dependencies with `yield` is executed *after* the response is sent, so [Exception Handlers](../handling-errors.md#install-custom-exception-handlers){.internal-link target=_blank} will have already run. There's nothing catching exceptions thrown by your dependencies in the exit code (after the `yield`).
So, if you raise an `HTTPException` after the `yield`, the default (or any custom) exception handler that catches `HTTPException`s and returns an HTTP 400 response won't be there to catch that exception anymore.
@@ -147,9 +138,11 @@ participant tasks as Background tasks
end
dep ->> operation: Run dependency, e.g. DB session
opt raise
operation -->> handler: Raise HTTPException
operation -->> dep: Raise HTTPException
dep -->> handler: Auto forward exception
handler -->> client: HTTP error response
operation -->> dep: Raise other exception
dep -->> handler: Auto forward exception
end
operation ->> client: Return response to client
Note over client,operation: Response is already sent, can't change it anymore
@@ -171,9 +164,9 @@ participant tasks as Background tasks
After one of those responses is sent, no other response can be sent.
!!! tip
This diagram shows `HTTPException`, but you could also raise any other exception for which you create a [Custom Exception Handler](../handling-errors.md#install-custom-exception-handlers){.internal-link target=_blank}. And that exception would be handled by that custom exception handler instead of the dependency exit code.
This diagram shows `HTTPException`, but you could also raise any other exception for which you create a [Custom Exception Handler](../handling-errors.md#install-custom-exception-handlers){.internal-link target=_blank}.
But if you raise an exception that is not handled by the exception handlers, it will be handled by the exit code of the dependency.
If you raise any exception, it will be passed to the dependencies with yield, including `HTTPException`, and then **again** to the exception handlers. If there's no exception handler for that exception, it will then be handled by the default internal `ServerErrorMiddleware`, returning a 500 HTTP status code, to let the client know that there was an error in the server.
## Context Managers

View File

@@ -31,9 +31,17 @@ Let's first focus on the dependency.
It is just a function that can take all the same parameters that a *path operation function* can take:
```Python hl_lines="8-9"
{!../../../docs_src/dependencies/tutorial001.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="8-9"
{!> ../../../docs_src/dependencies/tutorial001.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="6-7"
{!> ../../../docs_src/dependencies/tutorial001_py310.py!}
```
That's it.
@@ -55,17 +63,33 @@ And then it just returns a `dict` containing those values.
### Import `Depends`
```Python hl_lines="3"
{!../../../docs_src/dependencies/tutorial001.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="3"
{!> ../../../docs_src/dependencies/tutorial001.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="1"
{!> ../../../docs_src/dependencies/tutorial001_py310.py!}
```
### Declare the dependency, in the "dependant"
The same way you use `Body`, `Query`, etc. with your *path operation function* parameters, use `Depends` with a new parameter:
```Python hl_lines="13 18"
{!../../../docs_src/dependencies/tutorial001.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="13 18"
{!> ../../../docs_src/dependencies/tutorial001.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="11 16"
{!> ../../../docs_src/dependencies/tutorial001_py310.py!}
```
Although you use `Depends` in the parameters of your function the same way you use `Body`, `Query`, etc, `Depends` works a bit differently.

View File

@@ -6,25 +6,41 @@ They can be as **deep** as you need them to be.
**FastAPI** will take care of solving them.
### First dependency "dependable"
## First dependency "dependable"
You could create a first dependency ("dependable") like:
```Python hl_lines="8-9"
{!../../../docs_src/dependencies/tutorial005.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="8-9"
{!> ../../../docs_src/dependencies/tutorial005.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="6-7"
{!> ../../../docs_src/dependencies/tutorial005_py310.py!}
```
It declares an optional query parameter `q` as a `str`, and then it just returns it.
This is quite simple (not very useful), but will help us focus on how the sub-dependencies work.
### Second dependency, "dependable" and "dependant"
## Second dependency, "dependable" and "dependant"
Then you can create another dependency function (a "dependable") that at the same time declares a dependency of its own (so it is a "dependant" too):
```Python hl_lines="13"
{!../../../docs_src/dependencies/tutorial005.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="13"
{!> ../../../docs_src/dependencies/tutorial005.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="11"
{!> ../../../docs_src/dependencies/tutorial005_py310.py!}
```
Let's focus on the parameters declared:
@@ -33,13 +49,21 @@ Let's focus on the parameters declared:
* It also declares an optional `last_query` cookie, as a `str`.
* If the user didn't provide any query `q`, we use the last query used, which we saved to a cookie before.
### Use the dependency
## Use the dependency
Then we can use the dependency with:
```Python hl_lines="21"
{!../../../docs_src/dependencies/tutorial005.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="21"
{!> ../../../docs_src/dependencies/tutorial005.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="19"
{!> ../../../docs_src/dependencies/tutorial005_py310.py!}
```
!!! info
Notice that we are only declaring one dependency in the *path operation function*, the `query_or_cookie_extractor`.

View File

@@ -20,9 +20,17 @@ You can use `jsonable_encoder` for that.
It receives an object, like a Pydantic model, and returns a JSON compatible version:
```Python hl_lines="5 22"
{!../../../docs_src/encoder/tutorial001.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="5 22"
{!> ../../../docs_src/encoder/tutorial001.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="4 21"
{!> ../../../docs_src/encoder/tutorial001_py310.py!}
```
In this example, it would convert the Pydantic model to a `dict`, and the `datetime` to a `str`.

View File

@@ -55,12 +55,28 @@ Here are some of the additional data types you can use:
Here's an example *path operation* with parameters using some of the above types.
```Python hl_lines="1 3 12-16"
{!../../../docs_src/extra_data_types/tutorial001.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="1 3 12-16"
{!> ../../../docs_src/extra_data_types/tutorial001.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="1 2 11-15"
{!> ../../../docs_src/extra_data_types/tutorial001_py310.py!}
```
Note that the parameters inside the function have their natural data type, and you can, for example, perform normal date manipulations, like:
```Python hl_lines="18-19"
{!../../../docs_src/extra_data_types/tutorial001.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="18-19"
{!> ../../../docs_src/extra_data_types/tutorial001.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="17-18"
{!> ../../../docs_src/extra_data_types/tutorial001_py310.py!}
```

View File

@@ -17,9 +17,17 @@ This is especially the case for user models, because:
Here's a general idea of how the models could look like with their password fields and the places where they are used:
```Python hl_lines="9 11 16 22 24 29-30 33-35 40-41"
{!../../../docs_src/extra_models/tutorial001.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="9 11 16 22 24 29-30 33-35 40-41"
{!> ../../../docs_src/extra_models/tutorial001.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="7 9 14 20 22 27-28 31-33 38-39"
{!> ../../../docs_src/extra_models/tutorial001_py310.py!}
```
### About `**user_in.dict()`
@@ -150,9 +158,17 @@ All the data conversion, validation, documentation, etc. will still work as norm
That way, we can declare just the differences between the models (with plaintext `password`, with `hashed_password` and without password):
```Python hl_lines="9 15-16 19-20 23-24"
{!../../../docs_src/extra_models/tutorial002.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="9 15-16 19-20 23-24"
{!> ../../../docs_src/extra_models/tutorial002.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="7 13-14 17-18 21-22"
{!> ../../../docs_src/extra_models/tutorial002_py310.py!}
```
## `Union` or `anyOf`
@@ -165,19 +181,49 @@ To do that, use the standard Python type hint <a href="https://docs.python.org/3
!!! note
When defining a <a href="https://pydantic-docs.helpmanual.io/usage/types/#unions" class="external-link" target="_blank">`Union`</a>, include the most specific type first, followed by the less specific type. In the example below, the more specific `PlaneItem` comes before `CarItem` in `Union[PlaneItem, CarItem]`.
```Python hl_lines="1 14-15 18-20 33"
{!../../../docs_src/extra_models/tutorial003.py!}
=== "Python 3.6 and above"
```Python hl_lines="1 14-15 18-20 33"
{!> ../../../docs_src/extra_models/tutorial003.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="1 14-15 18-20 33"
{!> ../../../docs_src/extra_models/tutorial003_py310.py!}
```
### `Union` in Python 3.10
In this example we pass `Union[PlaneItem, CarItem]` as the value of the argument `response_model`.
Because we are passing it as a **value to an argument** instead of putting it in a **type annotation**, we have to use `Union` even in Python 3.10.
If it was in a type annotation we could have used the vertical bar, as:
```Python
some_variable: PlaneItem | CarItem
```
But if we put that in `response_model=PlaneItem | CarItem` we would get an error, because Python would try to perform an **invalid operation** between `PlaneItem` and `CarItem` instead of interpreting that as a type annotation.
## List of models
The same way, you can declare responses of lists of objects.
For that, use the standard Python `typing.List`:
For that, use the standard Python `typing.List` (or just `list` in Python 3.9 and above):
```Python hl_lines="1 20"
{!../../../docs_src/extra_models/tutorial004.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="1 20"
{!> ../../../docs_src/extra_models/tutorial004.py!}
```
=== "Python 3.9 and above"
```Python hl_lines="18"
{!> ../../../docs_src/extra_models/tutorial004_py39.py!}
```
## Response with arbitrary `dict`
@@ -185,11 +231,19 @@ You can also declare a response using a plain arbitrary `dict`, declaring just t
This is useful if you don't know the valid field/attribute names (that would be needed for a Pydantic model) beforehand.
In this case, you can use `typing.Dict`:
In this case, you can use `typing.Dict` (or just `dict` in Python 3.9 and above):
```Python hl_lines="1 8"
{!../../../docs_src/extra_models/tutorial005.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="1 8"
{!> ../../../docs_src/extra_models/tutorial005.py!}
```
=== "Python 3.9 and above"
```Python hl_lines="6"
{!> ../../../docs_src/extra_models/tutorial005_py39.py!}
```
## Recap

View File

@@ -252,14 +252,10 @@ from starlette.exceptions import HTTPException as StarletteHTTPException
### Re-use **FastAPI**'s exception handlers
You could also just want to use the exception somehow, but then use the same default exception handlers from **FastAPI**.
You can import and re-use the default exception handlers from `fastapi.exception_handlers`:
If you want to use the exception along with the same default exception handlers from **FastAPI**, You can import and re-use the default exception handlers from `fastapi.exception_handlers`:
```Python hl_lines="2-5 15 21"
{!../../../docs_src/handling_errors/tutorial006.py!}
```
In this example, you are just `print`ing the error with a very expressive message.
But you get the idea, you can use the exception and then just re-use the default exception handlers.
In this example you are just `print`ing the error with a very expressive message, but you get the idea. You can use the exception and then just re-use the default exception handlers.

View File

@@ -6,9 +6,17 @@ You can define Header parameters the same way you define `Query`, `Path` and `Co
First import `Header`:
```Python hl_lines="3"
{!../../../docs_src/header_params/tutorial001.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="3"
{!> ../../../docs_src/header_params/tutorial001.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="1"
{!> ../../../docs_src/header_params/tutorial001_py310.py!}
```
## Declare `Header` parameters
@@ -16,9 +24,17 @@ Then declare the header parameters using the same structure as with `Path`, `Que
The first value is the default value, you can pass all the extra validation or annotation parameters:
```Python hl_lines="9"
{!../../../docs_src/header_params/tutorial001.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="9"
{!> ../../../docs_src/header_params/tutorial001.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="7"
{!> ../../../docs_src/header_params/tutorial001_py310.py!}
```
!!! note "Technical Details"
`Header` is a "sister" class of `Path`, `Query` and `Cookie`. It also inherits from the same common `Param` class.
@@ -44,14 +60,21 @@ So, you can use `user_agent` as you normally would in Python code, instead of ne
If for some reason you need to disable automatic conversion of underscores to hyphens, set the parameter `convert_underscores` of `Header` to `False`:
```Python hl_lines="10"
{!../../../docs_src/header_params/tutorial002.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="10"
{!> ../../../docs_src/header_params/tutorial002.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="8"
{!> ../../../docs_src/header_params/tutorial002_py310.py!}
```
!!! warning
Before setting `convert_underscores` to `False`, bear in mind that some HTTP proxies and servers disallow the usage of headers with underscores.
## Duplicate headers
It is possible to receive duplicate headers. That means, the same header with multiple values.
@@ -62,9 +85,23 @@ You will receive all the values from the duplicate header as a Python `list`.
For example, to declare a header of `X-Token` that can appear more than once, you can write:
```Python hl_lines="9"
{!../../../docs_src/header_params/tutorial003.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="9"
{!> ../../../docs_src/header_params/tutorial003.py!}
```
=== "Python 3.9 and above"
```Python hl_lines="9"
{!> ../../../docs_src/header_params/tutorial003_py39.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="7"
{!> ../../../docs_src/header_params/tutorial003_py310.py!}
```
If you communicate with that *path operation* sending two HTTP headers like:

View File

@@ -43,7 +43,7 @@ For the tutorial, you might want to install it with all the optional dependencie
<div class="termy">
```console
$ pip install fastapi[all]
$ pip install "fastapi[all]"
---> 100%
```
@@ -64,7 +64,7 @@ $ pip install fastapi[all]
Also install `uvicorn` to work as the server:
```
pip install uvicorn[standard]
pip install "uvicorn[standard]"
```
And the same for each of the optional dependencies that you want to use.

View File

@@ -13,9 +13,23 @@ You can pass directly the `int` code, like `404`.
But if you don't remember what each number code is for, you can use the shortcut constants in `status`:
```Python hl_lines="3 17"
{!../../../docs_src/path_operation_configuration/tutorial001.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="3 17"
{!> ../../../docs_src/path_operation_configuration/tutorial001.py!}
```
=== "Python 3.9 and above"
```Python hl_lines="3 17"
{!> ../../../docs_src/path_operation_configuration/tutorial001_py39.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="1 15"
{!> ../../../docs_src/path_operation_configuration/tutorial001_py310.py!}
```
That status code will be used in the response and will be added to the OpenAPI schema.
@@ -28,21 +42,61 @@ That status code will be used in the response and will be added to the OpenAPI s
You can add tags to your *path operation*, pass the parameter `tags` with a `list` of `str` (commonly just one `str`):
```Python hl_lines="17 22 27"
{!../../../docs_src/path_operation_configuration/tutorial002.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="17 22 27"
{!> ../../../docs_src/path_operation_configuration/tutorial002.py!}
```
=== "Python 3.9 and above"
```Python hl_lines="17 22 27"
{!> ../../../docs_src/path_operation_configuration/tutorial002_py39.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="15 20 25"
{!> ../../../docs_src/path_operation_configuration/tutorial002_py310.py!}
```
They will be added to the OpenAPI schema and used by the automatic documentation interfaces:
<img src="/img/tutorial/path-operation-configuration/image01.png">
### Tags with Enums
If you have a big application, you might end up accumulating **several tags**, and you would want to make sure you always use the **same tag** for related *path operations*.
In these cases, it could make sense to store the tags in an `Enum`.
**FastAPI** supports that the same way as with plain strings:
```Python hl_lines="1 8-10 13 18"
{!../../../docs_src/path_operation_configuration/tutorial002b.py!}
```
## Summary and description
You can add a `summary` and `description`:
```Python hl_lines="20-21"
{!../../../docs_src/path_operation_configuration/tutorial003.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="20-21"
{!> ../../../docs_src/path_operation_configuration/tutorial003.py!}
```
=== "Python 3.9 and above"
```Python hl_lines="20-21"
{!> ../../../docs_src/path_operation_configuration/tutorial003_py39.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="18-19"
{!> ../../../docs_src/path_operation_configuration/tutorial003_py310.py!}
```
## Description from docstring
@@ -50,9 +104,23 @@ As descriptions tend to be long and cover multiple lines, you can declare the *p
You can write <a href="https://en.wikipedia.org/wiki/Markdown" class="external-link" target="_blank">Markdown</a> in the docstring, it will be interpreted and displayed correctly (taking into account docstring indentation).
```Python hl_lines="19-27"
{!../../../docs_src/path_operation_configuration/tutorial004.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="19-27"
{!> ../../../docs_src/path_operation_configuration/tutorial004.py!}
```
=== "Python 3.9 and above"
```Python hl_lines="19-27"
{!> ../../../docs_src/path_operation_configuration/tutorial004_py39.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="17-25"
{!> ../../../docs_src/path_operation_configuration/tutorial004_py310.py!}
```
It will be used in the interactive docs:
@@ -62,9 +130,23 @@ It will be used in the interactive docs:
You can specify the response description with the parameter `response_description`:
```Python hl_lines="21"
{!../../../docs_src/path_operation_configuration/tutorial005.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="21"
{!> ../../../docs_src/path_operation_configuration/tutorial005.py!}
```
=== "Python 3.9 and above"
```Python hl_lines="21"
{!> ../../../docs_src/path_operation_configuration/tutorial005_py39.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="19"
{!> ../../../docs_src/path_operation_configuration/tutorial005_py310.py!}
```
!!! info
Notice that `response_description` refers specifically to the response, the `description` refers to the *path operation* in general.

View File

@@ -6,9 +6,17 @@ The same way you can declare more validations and metadata for query parameters
First, import `Path` from `fastapi`:
```Python hl_lines="3"
{!../../../docs_src/path_params_numeric_validations/tutorial001.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="3"
{!> ../../../docs_src/path_params_numeric_validations/tutorial001.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="1"
{!> ../../../docs_src/path_params_numeric_validations/tutorial001_py310.py!}
```
## Declare metadata
@@ -16,13 +24,21 @@ You can declare all the same parameters as for `Query`.
For example, to declare a `title` metadata value for the path parameter `item_id` you can type:
```Python hl_lines="10"
{!../../../docs_src/path_params_numeric_validations/tutorial001.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="10"
{!> ../../../docs_src/path_params_numeric_validations/tutorial001.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="8"
{!> ../../../docs_src/path_params_numeric_validations/tutorial001_py310.py!}
```
!!! note
A path parameter is always required as it has to be part of the path.
So, you should declare it with `...` to mark it as required.
Nevertheless, even if you declared it with `None` or set a default value, it would not affect anything, it would still be always required.

View File

@@ -4,11 +4,19 @@
Let's take this application as example:
```Python hl_lines="9"
{!../../../docs_src/query_params_str_validations/tutorial001.py!}
```
=== "Python 3.6 and above"
The query parameter `q` is of type `Optional[str]`, that means that it's of type `str` but could also be `None`, and indeed, the default value is `None`, so FastAPI will know it's not required.
```Python hl_lines="9"
{!> ../../../docs_src/query_params_str_validations/tutorial001.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="7"
{!> ../../../docs_src/query_params_str_validations/tutorial001_py310.py!}
```
The query parameter `q` is of type `Optional[str]` (or `str | None` in Python 3.10), that means that it's of type `str` but could also be `None`, and indeed, the default value is `None`, so FastAPI will know it's not required.
!!! note
FastAPI will know that the value of `q` is not required because of the default value `= None`.
@@ -23,17 +31,33 @@ We are going to enforce that even though `q` is optional, whenever it is provide
To achieve that, first import `Query` from `fastapi`:
```Python hl_lines="3"
{!../../../docs_src/query_params_str_validations/tutorial002.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="3"
{!> ../../../docs_src/query_params_str_validations/tutorial002.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="1"
{!> ../../../docs_src/query_params_str_validations/tutorial002_py310.py!}
```
## Use `Query` as the default value
And now use it as the default value of your parameter, setting the parameter `max_length` to 50:
```Python hl_lines="9"
{!../../../docs_src/query_params_str_validations/tutorial002.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="9"
{!> ../../../docs_src/query_params_str_validations/tutorial002.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="7"
{!> ../../../docs_src/query_params_str_validations/tutorial002_py310.py!}
```
As we have to replace the default value `None` with `Query(None)`, the first parameter to `Query` serves the same purpose of defining that default value.
@@ -49,10 +73,22 @@ q: Optional[str] = Query(None)
q: Optional[str] = None
```
And in Python 3.10 and above:
```Python
q: str | None = Query(None)
```
...makes the parameter optional, the same as:
```Python
q: str | None = None
```
But it declares it explicitly as being a query parameter.
!!! info
Have in mind that FastAPI cares about the part:
Have in mind that the most important part to make a parameter optional is the part:
```Python
= None
@@ -64,9 +100,9 @@ But it declares it explicitly as being a query parameter.
= Query(None)
```
and will use that `None` to detect that the query parameter is not required.
as it will use that `None` as the default value, and that way make the parameter **not required**.
The `Optional` part is only to allow your editor to provide better support.
The `Optional` part allows your editor to provide better support, but it is not what tells FastAPI that this parameter is not required.
Then, we can pass more parameters to `Query`. In this case, the `max_length` parameter that applies to strings:
@@ -80,17 +116,33 @@ This will validate the data, show a clear error when the data is not valid, and
You can also add a parameter `min_length`:
```Python hl_lines="9"
{!../../../docs_src/query_params_str_validations/tutorial003.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="9"
{!> ../../../docs_src/query_params_str_validations/tutorial003.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="7"
{!> ../../../docs_src/query_params_str_validations/tutorial003_py310.py!}
```
## Add regular expressions
You can define a <abbr title="A regular expression, regex or regexp is a sequence of characters that define a search pattern for strings.">regular expression</abbr> that the parameter should match:
```Python hl_lines="10"
{!../../../docs_src/query_params_str_validations/tutorial004.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="10"
{!> ../../../docs_src/query_params_str_validations/tutorial004.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="8"
{!> ../../../docs_src/query_params_str_validations/tutorial004_py310.py!}
```
This specific regular expression checks that the received parameter value:
@@ -152,9 +204,23 @@ When you define a query parameter explicitly with `Query` you can also declare i
For example, to declare a query parameter `q` that can appear multiple times in the URL, you can write:
```Python hl_lines="9"
{!../../../docs_src/query_params_str_validations/tutorial011.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="9"
{!> ../../../docs_src/query_params_str_validations/tutorial011.py!}
```
=== "Python 3.9 and above"
```Python hl_lines="9"
{!> ../../../docs_src/query_params_str_validations/tutorial011_py39.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="7"
{!> ../../../docs_src/query_params_str_validations/tutorial011_py310.py!}
```
Then, with a URL like:
@@ -186,9 +252,17 @@ The interactive API docs will update accordingly, to allow multiple values:
And you can also define a default `list` of values if none are provided:
```Python hl_lines="9"
{!../../../docs_src/query_params_str_validations/tutorial012.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="9"
{!> ../../../docs_src/query_params_str_validations/tutorial012.py!}
```
=== "Python 3.9 and above"
```Python hl_lines="7"
{!> ../../../docs_src/query_params_str_validations/tutorial012_py39.py!}
```
If you go to:
@@ -209,7 +283,7 @@ the default of `q` will be: `["foo", "bar"]` and your response will be:
#### Using `list`
You can also use `list` directly instead of `List[str]`:
You can also use `list` directly instead of `List[str]` (or `list[str]` in Python 3.9+):
```Python hl_lines="7"
{!../../../docs_src/query_params_str_validations/tutorial013.py!}
@@ -233,15 +307,31 @@ That information will be included in the generated OpenAPI and used by the docum
You can add a `title`:
```Python hl_lines="10"
{!../../../docs_src/query_params_str_validations/tutorial007.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="10"
{!> ../../../docs_src/query_params_str_validations/tutorial007.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="7"
{!> ../../../docs_src/query_params_str_validations/tutorial007_py310.py!}
```
And a `description`:
```Python hl_lines="13"
{!../../../docs_src/query_params_str_validations/tutorial008.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="13"
{!> ../../../docs_src/query_params_str_validations/tutorial008.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="12"
{!> ../../../docs_src/query_params_str_validations/tutorial008_py310.py!}
```
## Alias parameters
@@ -261,9 +351,17 @@ But you still need it to be exactly `item-query`...
Then you can declare an `alias`, and that alias is what will be used to find the parameter value:
```Python hl_lines="9"
{!../../../docs_src/query_params_str_validations/tutorial009.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="9"
{!> ../../../docs_src/query_params_str_validations/tutorial009.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="7"
{!> ../../../docs_src/query_params_str_validations/tutorial009_py310.py!}
```
## Deprecating parameters
@@ -273,14 +371,38 @@ You have to leave it there a while because there are clients using it, but you w
Then pass the parameter `deprecated=True` to `Query`:
```Python hl_lines="18"
{!../../../docs_src/query_params_str_validations/tutorial010.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="18"
{!> ../../../docs_src/query_params_str_validations/tutorial010.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="17"
{!> ../../../docs_src/query_params_str_validations/tutorial010_py310.py!}
```
The docs will show it like this:
<img src="/img/tutorial/query-params-str-validations/image01.png">
## Exclude from OpenAPI
To exclude a query parameter from the generated OpenAPI schema (and thus, from the automatic documentation systems), set the parameter `include_in_schema` of `Query` to `False`:
=== "Python 3.6 and above"
```Python hl_lines="10"
{!> ../../../docs_src/query_params_str_validations/tutorial014.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="7"
{!> ../../../docs_src/query_params_str_validations/tutorial014_py310.py!}
```
## Recap
You can declare additional validations and metadata for your parameters.

View File

@@ -63,27 +63,38 @@ The parameter values in your function will be:
The same way, you can declare optional query parameters, by setting their default to `None`:
```Python hl_lines="9"
{!../../../docs_src/query_params/tutorial002.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="9"
{!> ../../../docs_src/query_params/tutorial002.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="7"
{!> ../../../docs_src/query_params/tutorial002_py310.py!}
```
In this case, the function parameter `q` will be optional, and will be `None` by default.
!!! check
Also notice that **FastAPI** is smart enough to notice that the path parameter `item_id` is a path parameter and `q` is not, so, it's a query parameter.
!!! note
FastAPI will know that `q` is optional because of the `= None`.
The `Optional` in `Optional[str]` is not used by FastAPI (FastAPI will only use the `str` part), but the `Optional[str]` will let your editor help you finding errors in your code.
## Query parameter type conversion
You can also declare `bool` types, and they will be converted:
```Python hl_lines="9"
{!../../../docs_src/query_params/tutorial003.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="9"
{!> ../../../docs_src/query_params/tutorial003.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="7"
{!> ../../../docs_src/query_params/tutorial003_py310.py!}
```
In this case, if you go to:
@@ -126,9 +137,17 @@ And you don't have to declare them in any specific order.
They will be detected by name:
```Python hl_lines="8 10"
{!../../../docs_src/query_params/tutorial004.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="8 10"
{!> ../../../docs_src/query_params/tutorial004.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="6 8"
{!> ../../../docs_src/query_params/tutorial004_py310.py!}
```
## Required query parameters
@@ -184,9 +203,17 @@ http://127.0.0.1:8000/items/foo-item?needy=sooooneedy
And of course, you can define some parameters as required, some as having a default value, and some entirely optional:
```Python hl_lines="10"
{!../../../docs_src/query_params/tutorial006.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="10"
{!> ../../../docs_src/query_params/tutorial006.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="8"
{!> ../../../docs_src/query_params/tutorial006_py310.py!}
```
In this case, there are 3 query parameters:

View File

@@ -17,7 +17,7 @@ Import `File` and `UploadFile` from `fastapi`:
{!../../../docs_src/request_files/tutorial001.py!}
```
## Define `File` parameters
## Define `File` Parameters
Create file parameters the same way you would for `Body` or `Form`:
@@ -41,9 +41,9 @@ Have in mind that this means that the whole contents will be stored in memory. T
But there are several cases in which you might benefit from using `UploadFile`.
## `File` parameters with `UploadFile`
## File Parameters with `UploadFile`
Define a `File` parameter with a type of `UploadFile`:
Define a file parameter with a type of `UploadFile`:
```Python hl_lines="12"
{!../../../docs_src/request_files/tutorial001.py!}
@@ -51,6 +51,7 @@ Define a `File` parameter with a type of `UploadFile`:
Using `UploadFile` has several advantages over `bytes`:
* You don't have to use `File()` in the default value of the parameter.
* It uses a "spooled" file:
* A file stored in memory up to a maximum size limit, and after passing this limit it will be stored in disk.
* This means that it will work well for large files like images, videos, large binaries, etc. without consuming all the memory.
@@ -113,32 +114,73 @@ The way HTML forms (`<form></form>`) sends the data to the server normally uses
This is not a limitation of **FastAPI**, it's part of the HTTP protocol.
## Multiple file uploads
## Optional File Upload
You can make a file optional by using standard type annotations and setting a default value of `None`:
=== "Python 3.6 and above"
```Python hl_lines="9 17"
{!> ../../../docs_src/request_files/tutorial001_02.py!}
```
=== "Python 3.9 and above"
```Python hl_lines="7 14"
{!> ../../../docs_src/request_files/tutorial001_02_py310.py!}
```
## `UploadFile` with Additional Metadata
You can also use `File()` with `UploadFile`, for example, to set additional metadata:
```Python hl_lines="13"
{!../../../docs_src/request_files/tutorial001_03.py!}
```
## Multiple File Uploads
It's possible to upload several files at the same time.
They would be associated to the same "form field" sent using "form data".
To use that, declare a `List` of `bytes` or `UploadFile`:
To use that, declare a list of `bytes` or `UploadFile`:
```Python hl_lines="10 15"
{!../../../docs_src/request_files/tutorial002.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="10 15"
{!> ../../../docs_src/request_files/tutorial002.py!}
```
=== "Python 3.9 and above"
```Python hl_lines="8 13"
{!> ../../../docs_src/request_files/tutorial002_py39.py!}
```
You will receive, as declared, a `list` of `bytes` or `UploadFile`s.
!!! note
Notice that, as of 2019-04-14, Swagger UI doesn't support multiple file uploads in the same form field. For more information, check <a href="https://github.com/swagger-api/swagger-ui/issues/4276" class="external-link" target="_blank">#4276</a> and <a href="https://github.com/swagger-api/swagger-ui/issues/3641" class="external-link" target="_blank">#3641</a>.
Nevertheless, **FastAPI** is already compatible with it, using the standard OpenAPI.
So, whenever Swagger UI supports multi-file uploads, or any other tools that supports OpenAPI, they will be compatible with **FastAPI**.
!!! note "Technical Details"
You could also use `from starlette.responses import HTMLResponse`.
**FastAPI** provides the same `starlette.responses` as `fastapi.responses` just as a convenience for you, the developer. But most of the available responses come directly from Starlette.
### Multiple File Uploads with Additional Metadata
And the same way as before, you can use `File()` to set additional parameters, even for `UploadFile`:
=== "Python 3.6 and above"
```Python hl_lines="18"
{!> ../../../docs_src/request_files/tutorial003.py!}
```
=== "Python 3.9 and above"
```Python hl_lines="16"
{!> ../../../docs_src/request_files/tutorial003_py39.py!}
```
## Recap
Use `File` to declare files to be uploaded as input parameters (as form data).
Use `File`, `bytes`, and `UploadFile` to declare files to be uploaded in the request, sent as form data.

View File

@@ -8,9 +8,23 @@ You can declare the model used for the response with the parameter `response_mod
* `@app.delete()`
* etc.
```Python hl_lines="17"
{!../../../docs_src/response_model/tutorial001.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="17"
{!> ../../../docs_src/response_model/tutorial001.py!}
```
=== "Python 3.9 and above"
```Python hl_lines="17"
{!> ../../../docs_src/response_model/tutorial001_py39.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="15"
{!> ../../../docs_src/response_model/tutorial001_py310.py!}
```
!!! note
Notice that `response_model` is a parameter of the "decorator" method (`get`, `post`, etc). Not of your *path operation function*, like all the parameters and body.
@@ -35,15 +49,31 @@ But most importantly:
Here we are declaring a `UserIn` model, it will contain a plaintext password:
```Python hl_lines="9 11"
{!../../../docs_src/response_model/tutorial002.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="9 11"
{!> ../../../docs_src/response_model/tutorial002.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="7 9"
{!> ../../../docs_src/response_model/tutorial002_py310.py!}
```
And we are using this model to declare our input and the same model to declare our output:
```Python hl_lines="17-18"
{!../../../docs_src/response_model/tutorial002.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="17-18"
{!> ../../../docs_src/response_model/tutorial002.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="15-16"
{!> ../../../docs_src/response_model/tutorial002_py310.py!}
```
Now, whenever a browser is creating a user with a password, the API will return the same password in the response.
@@ -58,21 +88,45 @@ But if we use the same model for another *path operation*, we could be sending o
We can instead create an input model with the plaintext password and an output model without it:
```Python hl_lines="9 11 16"
{!../../../docs_src/response_model/tutorial003.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="9 11 16"
{!> ../../../docs_src/response_model/tutorial003.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="7 9 14"
{!> ../../../docs_src/response_model/tutorial003_py310.py!}
```
Here, even though our *path operation function* is returning the same input user that contains the password:
```Python hl_lines="24"
{!../../../docs_src/response_model/tutorial003.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="24"
{!> ../../../docs_src/response_model/tutorial003.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="22"
{!> ../../../docs_src/response_model/tutorial003_py310.py!}
```
...we declared the `response_model` to be our model `UserOut`, that doesn't include the password:
```Python hl_lines="22"
{!../../../docs_src/response_model/tutorial003.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="22"
{!> ../../../docs_src/response_model/tutorial003.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="20"
{!> ../../../docs_src/response_model/tutorial003_py310.py!}
```
So, **FastAPI** will take care of filtering out all the data that is not declared in the output model (using Pydantic).
@@ -90,9 +144,23 @@ And both models will be used for the interactive API documentation:
Your response model could have default values, like:
```Python hl_lines="11 13-14"
{!../../../docs_src/response_model/tutorial004.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="11 13-14"
{!> ../../../docs_src/response_model/tutorial004.py!}
```
=== "Python 3.9 and above"
```Python hl_lines="11 13-14"
{!> ../../../docs_src/response_model/tutorial004_py39.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="9 11-12"
{!> ../../../docs_src/response_model/tutorial004_py310.py!}
```
* `description: Optional[str] = None` has a default of `None`.
* `tax: float = 10.5` has a default of `10.5`.
@@ -106,9 +174,23 @@ For example, if you have models with many optional attributes in a NoSQL databas
You can set the *path operation decorator* parameter `response_model_exclude_unset=True`:
```Python hl_lines="24"
{!../../../docs_src/response_model/tutorial004.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="24"
{!> ../../../docs_src/response_model/tutorial004.py!}
```
=== "Python 3.9 and above"
```Python hl_lines="24"
{!> ../../../docs_src/response_model/tutorial004_py39.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="22"
{!> ../../../docs_src/response_model/tutorial004_py310.py!}
```
and those default values won't be included in the response, only the values actually set.
@@ -185,9 +267,17 @@ This can be used as a quick shortcut if you have only one Pydantic model and wan
This also applies to `response_model_by_alias` that works similarly.
```Python hl_lines="31 37"
{!../../../docs_src/response_model/tutorial005.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="31 37"
{!> ../../../docs_src/response_model/tutorial005.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="29 35"
{!> ../../../docs_src/response_model/tutorial005_py310.py!}
```
!!! tip
The syntax `{"name", "description"}` creates a `set` with those two values.
@@ -198,9 +288,17 @@ This can be used as a quick shortcut if you have only one Pydantic model and wan
If you forget to use a `set` and use a `list` or `tuple` instead, FastAPI will still convert it to a `set` and it will work correctly:
```Python hl_lines="31 37"
{!../../../docs_src/response_model/tutorial006.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="31 37"
{!> ../../../docs_src/response_model/tutorial006.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="29 35"
{!> ../../../docs_src/response_model/tutorial006_py310.py!}
```
## Recap

View File

@@ -8,9 +8,17 @@ Here are several ways to do it.
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!}
```
=== "Python 3.6 and above"
```Python hl_lines="15-23"
{!> ../../../docs_src/schema_extra_example/tutorial001.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="13-21"
{!> ../../../docs_src/schema_extra_example/tutorial001_py310.py!}
```
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.
@@ -25,9 +33,17 @@ When using `Field()` with Pydantic models, you can also declare extra info for t
You can use this to add `example` for each field:
```Python hl_lines="4 10-13"
{!../../../docs_src/schema_extra_example/tutorial002.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="4 10-13"
{!> ../../../docs_src/schema_extra_example/tutorial002.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="2 8-11"
{!> ../../../docs_src/schema_extra_example/tutorial002_py310.py!}
```
!!! warning
Keep in mind that those extra arguments passed won't add any validation, only extra information, for documentation purposes.
@@ -50,9 +66,17 @@ you can also declare a data `example` or a group of `examples` with additional i
Here we pass an `example` of the data expected in `Body()`:
```Python hl_lines="21-26"
{!../../../docs_src/schema_extra_example/tutorial003.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="21-26"
{!> ../../../docs_src/schema_extra_example/tutorial003.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="19-24"
{!> ../../../docs_src/schema_extra_example/tutorial003_py310.py!}
```
### Example in the docs UI
@@ -73,9 +97,17 @@ Each specific example `dict` in the `examples` can contain:
* `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!}
```
=== "Python 3.6 and above"
```Python hl_lines="22-48"
{!> ../../../docs_src/schema_extra_example/tutorial004.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="20-46"
{!> ../../../docs_src/schema_extra_example/tutorial004_py310.py!}
```
### Examples in the docs UI

View File

@@ -16,9 +16,17 @@ First, let's create a Pydantic user model.
The same way we use Pydantic to declare bodies, we can use it anywhere else:
```Python hl_lines="5 12-16"
{!../../../docs_src/security/tutorial002.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="5 12-16"
{!> ../../../docs_src/security/tutorial002.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="3 10-14"
{!> ../../../docs_src/security/tutorial002_py310.py!}
```
## Create a `get_current_user` dependency
@@ -30,25 +38,49 @@ Remember that dependencies can have sub-dependencies?
The same as we were doing before in the *path operation* directly, our new dependency `get_current_user` will receive a `token` as a `str` from the sub-dependency `oauth2_scheme`:
```Python hl_lines="25"
{!../../../docs_src/security/tutorial002.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="25"
{!> ../../../docs_src/security/tutorial002.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="23"
{!> ../../../docs_src/security/tutorial002_py310.py!}
```
## Get the user
`get_current_user` will use a (fake) utility function we created, that takes a token as a `str` and returns our Pydantic `User` model:
```Python hl_lines="19-22 26-27"
{!../../../docs_src/security/tutorial002.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="19-22 26-27"
{!> ../../../docs_src/security/tutorial002.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="17-20 24-25"
{!> ../../../docs_src/security/tutorial002_py310.py!}
```
## Inject the current user
So now we can use the same `Depends` with our `get_current_user` in the *path operation*:
```Python hl_lines="31"
{!../../../docs_src/security/tutorial002.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="31"
{!> ../../../docs_src/security/tutorial002.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="29"
{!> ../../../docs_src/security/tutorial002_py310.py!}
```
Notice that we declare the type of `current_user` as the Pydantic model `User`.
@@ -64,7 +96,6 @@ This will help us inside of the function with all the completion and type checks
We are not restricted to having only one dependency that can return that type of data.
## Other models
You can now get the current user directly in the *path operation functions* and deal with the security mechanisms at the **Dependency Injection** level, using `Depends`.
@@ -81,10 +112,9 @@ You actually don't have users that log in to your application but robots, bots,
Just use any kind of model, any kind of class, any kind of database that you need for your application. **FastAPI** has you covered with the dependency injection system.
## Code size
This example might seem verbose. Have in mind that we are mixing security, data models utility functions and *path operations* in the same file.
This example might seem verbose. Have in mind that we are mixing security, data models, utility functions and *path operations* in the same file.
But here's the key point.
@@ -98,9 +128,17 @@ And all of them (or any portion of them that you want) can take the advantage of
And all these thousands of *path operations* can be as small as 3 lines:
```Python hl_lines="30-32"
{!../../../docs_src/security/tutorial002.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="30-32"
{!> ../../../docs_src/security/tutorial002.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="28-30"
{!> ../../../docs_src/security/tutorial002_py310.py!}
```
## Recap

View File

@@ -33,7 +33,7 @@ We need to install `python-jose` to generate and verify the JWT tokens in Python
<div class="termy">
```console
$ pip install python-jose[cryptography]
$ pip install "python-jose[cryptography]"
---> 100%
```
@@ -76,7 +76,7 @@ So, install PassLib with Bcrypt:
<div class="termy">
```console
$ pip install passlib[bcrypt]
$ pip install "passlib[bcrypt]"
---> 100%
```
@@ -109,9 +109,17 @@ And another utility to verify if a received password matches the hash stored.
And another one to authenticate and return a user.
```Python hl_lines="7 48 55-56 59-60 69-75"
{!../../../docs_src/security/tutorial004.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="7 48 55-56 59-60 69-75"
{!> ../../../docs_src/security/tutorial004.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="6 47 54-55 58-59 68-74"
{!> ../../../docs_src/security/tutorial004_py310.py!}
```
!!! note
If you check the new (fake) database `fake_users_db`, you will see how the hashed password looks like now: `"$2b$12$EixZaYVK1fsbw1ZfbX3OXePaWxn96p36WQoeG6Lruj3vjPGga31lW"`.
@@ -144,9 +152,17 @@ Define a Pydantic Model that will be used in the token endpoint for the response
Create a utility function to generate a new access token.
```Python hl_lines="6 12-14 28-30 78-86"
{!../../../docs_src/security/tutorial004.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="6 12-14 28-30 78-86"
{!> ../../../docs_src/security/tutorial004.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="5 11-13 27-29 77-85"
{!> ../../../docs_src/security/tutorial004_py310.py!}
```
## Update the dependencies
@@ -156,9 +172,17 @@ Decode the received token, verify it, and return the current user.
If the token is invalid, return an HTTP error right away.
```Python hl_lines="89-106"
{!../../../docs_src/security/tutorial004.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="89-106"
{!> ../../../docs_src/security/tutorial004.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="88-105"
{!> ../../../docs_src/security/tutorial004_py310.py!}
```
## Update the `/token` *path operation*
@@ -166,9 +190,17 @@ Create a `timedelta` with the expiration time of the token.
Create a real JWT access token and return it.
```Python hl_lines="115-128"
{!../../../docs_src/security/tutorial004.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="115-128"
{!> ../../../docs_src/security/tutorial004.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="114-127"
{!> ../../../docs_src/security/tutorial004_py310.py!}
```
### Technical details about the JWT "subject" `sub`

View File

@@ -49,9 +49,17 @@ Now let's use the utilities provided by **FastAPI** to handle this.
First, import `OAuth2PasswordRequestForm`, and use it as a dependency with `Depends` in the *path operation* for `/token`:
```Python hl_lines="4 76"
{!../../../docs_src/security/tutorial003.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="4 76"
{!> ../../../docs_src/security/tutorial003.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="2 74"
{!> ../../../docs_src/security/tutorial003_py310.py!}
```
`OAuth2PasswordRequestForm` is a class dependency that declares a form body with:
@@ -90,9 +98,17 @@ If there is no such user, we return an error saying "incorrect username or passw
For the error, we use the exception `HTTPException`:
```Python hl_lines="3 77-79"
{!../../../docs_src/security/tutorial003.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="3 77-79"
{!> ../../../docs_src/security/tutorial003.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="1 75-77"
{!> ../../../docs_src/security/tutorial003_py310.py!}
```
### Check the password
@@ -118,9 +134,17 @@ If your database is stolen, the thief won't have your users' plaintext passwords
So, the thief won't be able to try to use those same passwords in another system (as many users use the same password everywhere, this would be dangerous).
```Python hl_lines="80-83"
{!../../../docs_src/security/tutorial003.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="80-83"
{!> ../../../docs_src/security/tutorial003.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="78-81"
{!> ../../../docs_src/security/tutorial003_py310.py!}
```
#### About `**user_dict`
@@ -156,9 +180,17 @@ For this simple example, we are going to just be completely insecure and return
But for now, let's focus on the specific details we need.
```Python hl_lines="85"
{!../../../docs_src/security/tutorial003.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="85"
{!> ../../../docs_src/security/tutorial003.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="83"
{!> ../../../docs_src/security/tutorial003_py310.py!}
```
!!! tip
By the spec, you should return a JSON with an `access_token` and a `token_type`, the same as in this example.
@@ -181,9 +213,17 @@ Both of these dependencies will just return an HTTP error if the user doesn't ex
So, in our endpoint, we will only get a user if the user exists, was correctly authenticated, and is active:
```Python hl_lines="58-67 69-72 90"
{!../../../docs_src/security/tutorial003.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="58-66 69-72 90"
{!> ../../../docs_src/security/tutorial003.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="55-64 67-70 88"
{!> ../../../docs_src/security/tutorial003_py310.py!}
```
!!! info
The additional header `WWW-Authenticate` with value `Bearer` we are returning here is also part of the spec.

View File

@@ -248,9 +248,23 @@ So, the user will also have a `password` when creating it.
But for security, the `password` won't be in other Pydantic *models*, for example, it won't be sent from the API when reading a user.
```Python hl_lines="3 6-8 11-12 23-24 27-28"
{!../../../docs_src/sql_databases/sql_app/schemas.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="3 6-8 11-12 23-24 27-28"
{!> ../../../docs_src/sql_databases/sql_app/schemas.py!}
```
=== "Python 3.9 and above"
```Python hl_lines="3 6-8 11-12 23-24 27-28"
{!> ../../../docs_src/sql_databases/sql_app_py39/schemas.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="1 4-6 9-10 21-22 25-26"
{!> ../../../docs_src/sql_databases/sql_app_py310/schemas.py!}
```
#### SQLAlchemy style and Pydantic style
@@ -278,9 +292,23 @@ The same way, when reading a user, we can now declare that `items` will contain
Not only the IDs of those items, but all the data that we defined in the Pydantic *model* for reading items: `Item`.
```Python hl_lines="15-17 31-34"
{!../../../docs_src/sql_databases/sql_app/schemas.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="15-17 31-34"
{!> ../../../docs_src/sql_databases/sql_app/schemas.py!}
```
=== "Python 3.9 and above"
```Python hl_lines="15-17 31-34"
{!> ../../../docs_src/sql_databases/sql_app_py39/schemas.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="13-15 29-32"
{!> ../../../docs_src/sql_databases/sql_app_py310/schemas.py!}
```
!!! tip
Notice that the `User`, the Pydantic *model* that will be used when reading a user (returning it from the API) doesn't include the `password`.
@@ -293,9 +321,23 @@ This <a href="https://pydantic-docs.helpmanual.io/#config" class="external-link"
In the `Config` class, set the attribute `orm_mode = True`.
```Python hl_lines="15 19-20 31 36-37"
{!../../../docs_src/sql_databases/sql_app/schemas.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="15 19-20 31 36-37"
{!> ../../../docs_src/sql_databases/sql_app/schemas.py!}
```
=== "Python 3.9 and above"
```Python hl_lines="15 19-20 31 36-37"
{!> ../../../docs_src/sql_databases/sql_app_py39/schemas.py!}
```
=== "Python 3.10 and above"
```Python hl_lines="13 17-18 29 34-35"
{!> ../../../docs_src/sql_databases/sql_app_py310/schemas.py!}
```
!!! tip
Notice it's assigning a value with `=`, like:
@@ -425,9 +467,17 @@ And now in the file `sql_app/main.py` let's integrate and use all the other part
In a very simplistic way create the database tables:
```Python hl_lines="9"
{!../../../docs_src/sql_databases/sql_app/main.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="9"
{!> ../../../docs_src/sql_databases/sql_app/main.py!}
```
=== "Python 3.9 and above"
```Python hl_lines="7"
{!> ../../../docs_src/sql_databases/sql_app_py39/main.py!}
```
#### Alembic Note
@@ -441,17 +491,6 @@ You can find an example of Alembic in a FastAPI project in the templates from [P
### Create a dependency
!!! info
For this to work, you need to use **Python 3.7** or above, or in **Python 3.6**, install the "backports":
```console
$ pip install async-exit-stack async-generator
```
This installs <a href="https://github.com/sorcio/async_exit_stack" class="external-link" target="_blank">async-exit-stack</a> and <a href="https://github.com/python-trio/async_generator" class="external-link" target="_blank">async-generator</a>.
You can also use the alternative method with a "middleware" explained at the end.
Now use the `SessionLocal` class we created in the `sql_app/databases.py` file to create a dependency.
We need to have an independent database session/connection (`SessionLocal`) per request, use the same session through all the request and then close it after the request is finished.
@@ -462,9 +501,17 @@ For that, we will create a new dependency with `yield`, as explained before in t
Our dependency will create a new SQLAlchemy `SessionLocal` that will be used in a single request, and then close it once the request is finished.
```Python hl_lines="15-20"
{!../../../docs_src/sql_databases/sql_app/main.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="15-20"
{!> ../../../docs_src/sql_databases/sql_app/main.py!}
```
=== "Python 3.9 and above"
```Python hl_lines="13-18"
{!> ../../../docs_src/sql_databases/sql_app_py39/main.py!}
```
!!! info
We put the creation of the `SessionLocal()` and handling of the requests in a `try` block.
@@ -479,9 +526,17 @@ And then, when using the dependency in a *path operation function*, we declare i
This will then give us better editor support inside the *path operation function*, because the editor will know that the `db` parameter is of type `Session`:
```Python hl_lines="24 32 38 47 53"
{!../../../docs_src/sql_databases/sql_app/main.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="24 32 38 47 53"
{!> ../../../docs_src/sql_databases/sql_app/main.py!}
```
=== "Python 3.9 and above"
```Python hl_lines="22 30 36 45 51"
{!> ../../../docs_src/sql_databases/sql_app_py39/main.py!}
```
!!! info "Technical Details"
The parameter `db` is actually of type `SessionLocal`, but this class (created with `sessionmaker()`) is a "proxy" of a SQLAlchemy `Session`, so, the editor doesn't really know what methods are provided.
@@ -492,9 +547,17 @@ This will then give us better editor support inside the *path operation function
Now, finally, here's the standard **FastAPI** *path operations* code.
```Python hl_lines="23-28 31-34 37-42 45-49 52-55"
{!../../../docs_src/sql_databases/sql_app/main.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="23-28 31-34 37-42 45-49 52-55"
{!> ../../../docs_src/sql_databases/sql_app/main.py!}
```
=== "Python 3.9 and above"
```Python hl_lines="21-26 29-32 35-40 43-47 50-53"
{!> ../../../docs_src/sql_databases/sql_app_py39/main.py!}
```
We are creating the database session before each request in the dependency with `yield`, and then closing it afterwards.
@@ -577,9 +640,23 @@ For example, in a background task worker with <a href="https://docs.celeryprojec
* `sql_app/schemas.py`:
```Python
{!../../../docs_src/sql_databases/sql_app/schemas.py!}
```
=== "Python 3.6 and above"
```Python
{!> ../../../docs_src/sql_databases/sql_app/schemas.py!}
```
=== "Python 3.9 and above"
```Python
{!> ../../../docs_src/sql_databases/sql_app_py39/schemas.py!}
```
=== "Python 3.10 and above"
```Python
{!> ../../../docs_src/sql_databases/sql_app_py310/schemas.py!}
```
* `sql_app/crud.py`:
@@ -589,9 +666,17 @@ For example, in a background task worker with <a href="https://docs.celeryprojec
* `sql_app/main.py`:
```Python
{!../../../docs_src/sql_databases/sql_app/main.py!}
```
=== "Python 3.6 and above"
```Python
{!> ../../../docs_src/sql_databases/sql_app/main.py!}
```
=== "Python 3.9 and above"
```Python
{!> ../../../docs_src/sql_databases/sql_app_py39/main.py!}
```
## Check it
@@ -640,9 +725,17 @@ A "middleware" is basically a function that is always executed for each request,
The middleware we'll add (just a function) will create a new SQLAlchemy `SessionLocal` for each request, add it to the request and then close it once the request is finished.
```Python hl_lines="14-22"
{!../../../docs_src/sql_databases/sql_app/alt_main.py!}
```
=== "Python 3.6 and above"
```Python hl_lines="14-22"
{!> ../../../docs_src/sql_databases/sql_app/alt_main.py!}
```
=== "Python 3.9 and above"
```Python hl_lines="12-20"
{!> ../../../docs_src/sql_databases/sql_app_py39/alt_main.py!}
```
!!! info
We put the creation of the `SessionLocal()` and handling of the requests in a `try` block.

View File

@@ -2,20 +2,6 @@
You can serve static files automatically from a directory using `StaticFiles`.
## Install `aiofiles`
First you need to install `aiofiles`:
<div class="termy">
```console
$ pip install aiofiles
---> 100%
```
</div>
## Use `StaticFiles`
* Import `StaticFiles`.

View File

@@ -10,7 +10,7 @@ With it, you can use <a href="https://docs.pytest.org/" class="external-link" ta
Import `TestClient`.
Create a `TestClient` passing to it your **FastAPI**.
Create a `TestClient` passing to it your **FastAPI** application.
Create functions with a name that starts with `test_` (this is standard `pytest` conventions).
@@ -65,7 +65,7 @@ Now let's extend this example and add more details to see how to test different
### Extended **FastAPI** app file
Let's say you have a file `main_b.py` with your **FastAPI** app.
Let's say that now the file `main.py` with your **FastAPI** app has some other **path operations**.
It has a `GET` operation that could return an error.
@@ -73,16 +73,24 @@ It has a `POST` operation that could return several errors.
Both *path operations* require an `X-Token` header.
```Python
{!../../../docs_src/app_testing/main_b.py!}
```
=== "Python 3.6 and above"
```Python
{!> ../../../docs_src/app_testing/app_b/main.py!}
```
=== "Python 3.10 and above"
```Python
{!> ../../../docs_src/app_testing/app_b_py310/main.py!}
```
### Extended testing file
You could then have a `test_main_b.py`, the same as before, with the extended tests:
You could then update `test_main.py` with the extended tests:
```Python
{!../../../docs_src/app_testing/test_main_b.py!}
{!> ../../../docs_src/app_testing/app_b/test_main.py!}
```
Whenever you need the client to pass information in the request and you don't know how to, you can search (Google) how to do it in `requests`.

View File

@@ -9,13 +9,13 @@ theme:
primary: teal
accent: amber
toggle:
icon: material/lightbulb-outline
icon: material/lightbulb
name: Switch to light mode
- scheme: slate
primary: teal
accent: amber
toggle:
icon: material/lightbulb
icon: material/lightbulb-outline
name: Switch to dark mode
features:
- search.suggest
@@ -29,9 +29,6 @@ theme:
repo_name: tiangolo/fastapi
repo_url: https://github.com/tiangolo/fastapi
edit_uri: ''
google_analytics:
- UA-133183413-1
- auto
plugins:
- search
- markdownextradata:
@@ -40,13 +37,16 @@ nav:
- FastAPI: index.md
- Languages:
- en: /
- az: /az/
- de: /de/
- es: /es/
- fa: /fa/
- fr: /fr/
- id: /id/
- it: /it/
- ja: /ja/
- ko: /ko/
- nl: /nl/
- pl: /pl/
- pt: /pt/
- ru: /ru/
@@ -142,6 +142,7 @@ nav:
- advanced/extending-openapi.md
- advanced/openapi-callbacks.md
- advanced/wsgi.md
- advanced/generate-clients.md
- async.md
- Deployment:
- deployment/index.md
@@ -165,9 +166,6 @@ markdown_extensions:
permalink: true
- markdown.extensions.codehilite:
guess_lang: false
# Uncomment these 2 lines during development to more easily add highlights
# - pymdownx.highlight:
# linenums: true
- mdx_include:
base_path: docs
- admonition
@@ -178,8 +176,12 @@ markdown_extensions:
- name: mermaid
class: mermaid
format: !!python/name:pymdownx.superfences.fence_code_format ''
- pymdownx.tabbed
- pymdownx.tabbed:
alternate_style: true
extra:
analytics:
provider: google
property: UA-133183413-1
social:
- icon: fontawesome/brands/github-alt
link: https://github.com/tiangolo/fastapi
@@ -198,10 +200,14 @@ extra:
alternate:
- link: /
name: en - English
- link: /az/
name: az
- link: /de/
name: de
- link: /es/
name: es - español
- link: /fa/
name: fa
- link: /fr/
name: fr - français
- link: /id/
@@ -212,6 +218,8 @@ extra:
name: ja - 日本語
- link: /ko/
name: ko - 한국어
- link: /nl/
name: nl
- link: /pl/
name: pl
- link: /pt/

View File

@@ -22,16 +22,10 @@
</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" />
<img class="sponsor-image" src="/img/sponsors/fastapi-course-bundle-banner.png" />
</a>
</div>
<div class="item">
@@ -40,6 +34,56 @@
<img class="sponsor-image" src="/img/sponsors/jina-banner.svg" />
</a>
</div>
<div class="item">
<a title="CryptAPI: Your easy to use, secure and privacy oriented payment gateway." style="display: block; position: relative;" href="https://cryptapi.io/" target="_blank">
<span class="sponsor-badge">sponsor</span>
<img class="sponsor-image" src="/img/sponsors/cryptapi-banner.svg" />
</a>
</div>
<div class="item">
<a title="Join the team building a new SaaS platform that will change the computing world" style="display: block; position: relative;" href="https://classiq.link/mzg" target="_blank">
<span class="sponsor-badge">sponsor</span>
<img class="sponsor-image" src="/img/sponsors/classiq-banner.png" />
</a>
</div>
<div class="item">
<a title="Dropbase - seamlessly collect, clean, and centralize data." style="display: block; position: relative;" href="https://www.dropbase.io/careers" target="_blank">
<span class="sponsor-badge">sponsor</span>
<img class="sponsor-image" src="/img/sponsors/dropbase-banner.svg" />
</a>
</div>
</div>
</div>
{% endblock %}
{%- block scripts %}
{{ super() }}
<!-- DocsQA integration start -->
<script src="https://cdn.jsdelivr.net/npm/qabot@0.4"></script>
<script>
// This prevents the global search from interfering with qa-bot's internal text input.
document.addEventListener('DOMContentLoaded', () => {
document.querySelectorAll('qa-bot').forEach((x) => {
x.addEventListener('keydown', (event) => {
event.stopPropagation();
});
});
});
</script>
<qa-bot
server="https://tiangolo-fastapi.docsqa.jina.ai"
theme="infer"
title="FastAPI Bot"
description="FastAPI framework, high performance, easy to learn, fast to code, ready for production"
style="font-size: 0.8rem"
>
<template>
<dl>
<dt>You can ask questions about FastAPI. Try:</dt>
<dd>How do you deploy FastAPI?</dd>
<dd>What are type hints?</dd>
<dd>What is OpenAPI?</dd>
</dl>
</template>
</qa-bot>
<!-- DocsQA integration end -->
{%- endblock %}

View File

@@ -4,9 +4,7 @@ Este tutorial te muestra cómo usar **FastAPI** con la mayoría de sus caracter
Cada sección se basa gradualmente en las anteriores, pero está estructurada en temas separados, así puedes ir directamente a cualquier tema en concreto para resolver tus necesidades específicas sobre la API.
También está diseñado para funcionar como una referencia futura.
Para que puedas volver y ver exactamente lo que necesitas.
Funciona también como una referencia futura, para que puedas volver y ver exactamente lo que necesitas.
## Ejecuta el código

View File

@@ -9,13 +9,13 @@ theme:
primary: teal
accent: amber
toggle:
icon: material/lightbulb-outline
icon: material/lightbulb
name: Switch to light mode
- scheme: slate
primary: teal
accent: amber
toggle:
icon: material/lightbulb
icon: material/lightbulb-outline
name: Switch to dark mode
features:
- search.suggest
@@ -29,9 +29,6 @@ theme:
repo_name: tiangolo/fastapi
repo_url: https://github.com/tiangolo/fastapi
edit_uri: ''
google_analytics:
- UA-133183413-1
- auto
plugins:
- search
- markdownextradata:
@@ -40,13 +37,16 @@ nav:
- FastAPI: index.md
- Languages:
- en: /
- az: /az/
- de: /de/
- es: /es/
- fa: /fa/
- fr: /fr/
- id: /id/
- it: /it/
- ja: /ja/
- ko: /ko/
- nl: /nl/
- pl: /pl/
- pt: /pt/
- ru: /ru/
@@ -79,8 +79,12 @@ markdown_extensions:
- name: mermaid
class: mermaid
format: !!python/name:pymdownx.superfences.fence_code_format ''
- pymdownx.tabbed
- pymdownx.tabbed:
alternate_style: true
extra:
analytics:
provider: google
property: UA-133183413-1
social:
- icon: fontawesome/brands/github-alt
link: https://github.com/tiangolo/fastapi
@@ -99,10 +103,14 @@ extra:
alternate:
- link: /
name: en - English
- link: /az/
name: az
- link: /de/
name: de
- link: /es/
name: es - español
- link: /fa/
name: fa
- link: /fr/
name: fr - français
- link: /id/
@@ -113,6 +121,8 @@ extra:
name: ja - 日本語
- link: /ko/
name: ko - 한국어
- link: /nl/
name: nl
- link: /pl/
name: pl
- link: /pt/

468
docs/fa/docs/index.md Normal file
View File

@@ -0,0 +1,468 @@
{!../../../docs/missing-translation.md!}
<p align="center">
<a href="https://fastapi.tiangolo.com"><img src="https://fastapi.tiangolo.com/img/logo-margin/logo-teal.png" alt="FastAPI"></a>
</p>
<p align="center">
<em>FastAPI framework, high performance, easy to learn, fast to code, ready for production</em>
</p>
<p align="center">
<a href="https://github.com/tiangolo/fastapi/actions?query=workflow%3ATest+event%3Apush+branch%3Amaster" target="_blank">
<img src="https://github.com/tiangolo/fastapi/workflows/Test/badge.svg?event=push&branch=master" alt="Test">
</a>
<a href="https://codecov.io/gh/tiangolo/fastapi" target="_blank">
<img src="https://img.shields.io/codecov/c/github/tiangolo/fastapi?color=%2334D058" alt="Coverage">
</a>
<a href="https://pypi.org/project/fastapi" target="_blank">
<img src="https://img.shields.io/pypi/v/fastapi?color=%2334D058&label=pypi%20package" alt="Package version">
</a>
<a href="https://pypi.org/project/fastapi" target="_blank">
<img src="https://img.shields.io/pypi/pyversions/fastapi.svg?color=%2334D058" alt="Supported Python versions">
</a>
</p>
---
**Documentation**: <a href="https://fastapi.tiangolo.com" target="_blank">https://fastapi.tiangolo.com</a>
**Source Code**: <a href="https://github.com/tiangolo/fastapi" target="_blank">https://github.com/tiangolo/fastapi</a>
---
FastAPI is a modern, fast (high-performance), web framework for building APIs with Python 3.6+ based on standard Python type hints.
The key features are:
* **Fast**: Very high performance, on par with **NodeJS** and **Go** (thanks to Starlette and Pydantic). [One of the fastest Python frameworks available](#performance).
* **Fast to code**: Increase the speed to develop features by about 200% to 300%. *
* **Fewer bugs**: Reduce about 40% of human (developer) induced errors. *
* **Intuitive**: Great editor support. <abbr title="also known as auto-complete, autocompletion, IntelliSense">Completion</abbr> everywhere. Less time debugging.
* **Easy**: Designed to be easy to use and learn. Less time reading docs.
* **Short**: Minimize code duplication. Multiple features from each parameter declaration. Fewer bugs.
* **Robust**: Get production-ready code. With automatic interactive documentation.
* **Standards-based**: Based on (and fully compatible with) the open standards for APIs: <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank">OpenAPI</a> (previously known as Swagger) and <a href="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 }}" style="border-radius:15px"></a>
{% endfor -%}
{%- for sponsor in sponsors.silver -%}
<a href="{{ sponsor.url }}" target="_blank" title="{{ sponsor.title }}"><img src="{{ sponsor.img }}" style="border-radius:15px"></a>
{% endfor %}
{% endif %}
<!-- /sponsors -->
<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._"
<div style="text-align: right; margin-right: 10%;">Kabir Khan - <strong>Microsoft</strong> <a href="https://github.com/tiangolo/fastapi/pull/26" target="_blank"><small>(ref)</small></a></div>
---
"_We adopted the **FastAPI** library to spawn a **REST** server that can be queried to obtain **predictions**. [for Ludwig]_"
<div style="text-align: right; margin-right: 10%;">Piero Molino, Yaroslav Dudin, and Sai Sumanth Miryala - <strong>Uber</strong> <a href="https://eng.uber.com/ludwig-v0-2/" target="_blank"><small>(ref)</small></a></div>
---
"_**Netflix** is pleased to announce the open-source release of our **crisis management** orchestration framework: **Dispatch**! [built with **FastAPI**]_"
<div style="text-align: right; margin-right: 10%;">Kevin Glisson, Marc Vilanova, Forest Monsen - <strong>Netflix</strong> <a href="https://netflixtechblog.com/introducing-dispatch-da4b8a2a8072" target="_blank"><small>(ref)</small></a></div>
---
"_Im over the moon excited about **FastAPI**. Its so fun!_"
<div style="text-align: right; margin-right: 10%;">Brian Okken - <strong><a href="https://pythonbytes.fm/episodes/show/123/time-to-right-the-py-wrongs?time_in_sec=855" target="_blank">Python Bytes</a> podcast host</strong> <a href="https://twitter.com/brianokken/status/1112220079972728832" target="_blank"><small>(ref)</small></a></div>
---
"_Honestly, what you've built looks super solid and polished. In many ways, it's what I wanted **Hug** to be - it's really inspiring to see someone build that._"
<div style="text-align: right; margin-right: 10%;">Timothy Crosley - <strong><a href="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>
---
"_If you're looking to learn one **modern framework** for building REST APIs, check out **FastAPI** [...] It's fast, easy to use and easy to learn [...]_"
"_We've switched over to **FastAPI** for our **APIs** [...] I think you'll like it [...]_"
<div style="text-align: right; margin-right: 10%;">Ines Montani - Matthew Honnibal - <strong><a href="https://explosion.ai" target="_blank">Explosion AI</a> founders - <a href="https://spacy.io" target="_blank">spaCy</a> creators</strong> <a href="https://twitter.com/_inesmontani/status/1144173225322143744" target="_blank"><small>(ref)</small></a> - <a href="https://twitter.com/honnibal/status/1144031421859655680" target="_blank"><small>(ref)</small></a></div>
---
## **Typer**, the FastAPI of CLIs
<a href="https://typer.tiangolo.com" target="_blank"><img src="https://typer.tiangolo.com/img/logo-margin/logo-margin-vector.svg" style="width: 20%;"></a>
If you are building a <abbr title="Command Line Interface">CLI</abbr> app to be used in the terminal instead of a web API, check out <a href="https://typer.tiangolo.com/" class="external-link" target="_blank">**Typer**</a>.
**Typer** is FastAPI's little sibling. And it's intended to be the **FastAPI of CLIs**. ⌨️ 🚀
## Requirements
Python 3.6+
FastAPI stands on the shoulders of giants:
* <a href="https://www.starlette.io/" class="external-link" target="_blank">Starlette</a> for the web parts.
* <a href="https://pydantic-docs.helpmanual.io/" class="external-link" target="_blank">Pydantic</a> for the data parts.
## Installation
<div class="termy">
```console
$ pip install fastapi
---> 100%
```
</div>
You will also need an ASGI server, for production such as <a href="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[standard]"
---> 100%
```
</div>
## Example
### Create it
* Create a file `main.py` with:
```Python
from typing import Optional
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def read_root():
return {"Hello": "World"}
@app.get("/items/{item_id}")
def read_item(item_id: int, q: Optional[str] = None):
return {"item_id": item_id, "q": q}
```
<details markdown="1">
<summary>Or use <code>async def</code>...</summary>
If your code uses `async` / `await`, use `async def`:
```Python hl_lines="9 14"
from typing import Optional
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
async def read_root():
return {"Hello": "World"}
@app.get("/items/{item_id}")
async def read_item(item_id: int, q: Optional[str] = None):
return {"item_id": item_id, "q": q}
```
**Note**:
If you don't know, check the _"In a hurry?"_ section about <a href="https://fastapi.tiangolo.com/async/#in-a-hurry" target="_blank">`async` and `await` in the docs</a>.
</details>
### Run it
Run the server with:
<div class="termy">
```console
$ uvicorn main:app --reload
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
INFO: Started reloader process [28720]
INFO: Started server process [28722]
INFO: Waiting for application startup.
INFO: Application startup complete.
```
</div>
<details markdown="1">
<summary>About the command <code>uvicorn main:app --reload</code>...</summary>
The command `uvicorn main:app` refers to:
* `main`: the file `main.py` (the Python "module").
* `app`: the object created inside of `main.py` with the line `app = FastAPI()`.
* `--reload`: make the server restart after code changes. Only do this for development.
</details>
### Check it
Open your browser at <a href="http://127.0.0.1:8000/items/5?q=somequery" class="external-link" target="_blank">http://127.0.0.1:8000/items/5?q=somequery</a>.
You will see the JSON response as:
```JSON
{"item_id": 5, "q": "somequery"}
```
You already created an API that:
* Receives HTTP requests in the _paths_ `/` and `/items/{item_id}`.
* Both _paths_ take `GET` <em>operations</em> (also known as HTTP _methods_).
* The _path_ `/items/{item_id}` has a _path parameter_ `item_id` that should be an `int`.
* The _path_ `/items/{item_id}` has an optional `str` _query parameter_ `q`.
### Interactive API docs
Now go to <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
You will see the automatic interactive API documentation (provided by <a href="https://github.com/swagger-api/swagger-ui" class="external-link" target="_blank">Swagger UI</a>):
![Swagger UI](https://fastapi.tiangolo.com/img/index/index-01-swagger-ui-simple.png)
### Alternative API docs
And now, go to <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a>.
You will see the alternative automatic documentation (provided by <a href="https://github.com/Rebilly/ReDoc" class="external-link" target="_blank">ReDoc</a>):
![ReDoc](https://fastapi.tiangolo.com/img/index/index-02-redoc-simple.png)
## Example upgrade
Now modify the file `main.py` to receive a body from a `PUT` request.
Declare the body using standard Python types, thanks to Pydantic.
```Python hl_lines="4 9-12 25-27"
from typing import Optional
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
price: float
is_offer: Optional[bool] = None
@app.get("/")
def read_root():
return {"Hello": "World"}
@app.get("/items/{item_id}")
def read_item(item_id: int, q: Optional[str] = None):
return {"item_id": item_id, "q": q}
@app.put("/items/{item_id}")
def update_item(item_id: int, item: Item):
return {"item_name": item.name, "item_id": item_id}
```
The server should reload automatically (because you added `--reload` to the `uvicorn` command above).
### Interactive API docs upgrade
Now go to <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
* The interactive API documentation will be automatically updated, including the new body:
![Swagger UI](https://fastapi.tiangolo.com/img/index/index-03-swagger-02.png)
* Click on the button "Try it out", it allows you to fill the parameters and directly interact with the API:
![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-04-swagger-03.png)
* Then click on the "Execute" button, the user interface will communicate with your API, send the parameters, get the results and show them on the screen:
![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-05-swagger-04.png)
### Alternative API docs upgrade
And now, go to <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a>.
* The alternative documentation will also reflect the new query parameter and body:
![ReDoc](https://fastapi.tiangolo.com/img/index/index-06-redoc-02.png)
### Recap
In summary, you declare **once** the types of parameters, body, etc. as function parameters.
You do that with standard modern Python types.
You don't have to learn a new syntax, the methods or classes of a specific library, etc.
Just standard **Python 3.6+**.
For example, for an `int`:
```Python
item_id: int
```
or for a more complex `Item` model:
```Python
item: Item
```
...and with that single declaration you get:
* Editor support, including:
* Completion.
* Type checks.
* Validation of data:
* Automatic and clear errors when the data is invalid.
* Validation even for deeply nested JSON objects.
* <abbr title="also known as: serialization, parsing, marshalling">Conversion</abbr> of input data: coming from the network to Python data and types. Reading from:
* JSON.
* Path parameters.
* Query parameters.
* Cookies.
* Headers.
* Forms.
* Files.
* <abbr title="also known as: serialization, parsing, marshalling">Conversion</abbr> of output data: converting from Python data and types to network data (as JSON):
* Convert Python types (`str`, `int`, `float`, `bool`, `list`, etc).
* `datetime` objects.
* `UUID` objects.
* Database models.
* ...and many more.
* Automatic interactive API documentation, including 2 alternative user interfaces:
* Swagger UI.
* ReDoc.
---
Coming back to the previous code example, **FastAPI** will:
* Validate that there is an `item_id` in the path for `GET` and `PUT` requests.
* Validate that the `item_id` is of type `int` for `GET` and `PUT` requests.
* If it is not, the client will see a useful, clear error.
* Check if there is an optional query parameter named `q` (as in `http://127.0.0.1:8000/items/foo?q=somequery`) for `GET` requests.
* As the `q` parameter is declared with `= None`, it is optional.
* Without the `None` it would be required (as is the body in the case with `PUT`).
* For `PUT` requests to `/items/{item_id}`, Read the body as JSON:
* Check that it has a required attribute `name` that should be a `str`.
* Check that it has a required attribute `price` that has to be a `float`.
* Check that it has an optional attribute `is_offer`, that should be a `bool`, if present.
* All this would also work for deeply nested JSON objects.
* Convert from and to JSON automatically.
* Document everything with OpenAPI, that can be used by:
* Interactive documentation systems.
* Automatic client code generation systems, for many languages.
* Provide 2 interactive documentation web interfaces directly.
---
We just scratched the surface, but you already get the idea of how it all works.
Try changing the line with:
```Python
return {"item_name": item.name, "item_id": item_id}
```
...from:
```Python
... "item_name": item.name ...
```
...to:
```Python
... "item_price": item.price ...
```
...and see how your editor will auto-complete the attributes and know their types:
![editor support](https://fastapi.tiangolo.com/img/vscode-completion.png)
For a more complete example including more features, see the <a href="https://fastapi.tiangolo.com/tutorial/">Tutorial - User Guide</a>.
**Spoiler alert**: the tutorial - user guide includes:
* Declaration of **parameters** from other different places as: **headers**, **cookies**, **form fields** and **files**.
* How to set **validation constraints** as `maximum_length` or `regex`.
* A very powerful and easy to use **<abbr title="also known as components, resources, providers, services, injectables">Dependency Injection</abbr>** system.
* Security and authentication, including support for **OAuth2** with **JWT tokens** and **HTTP Basic** auth.
* More advanced (but equally easy) techniques for declaring **deeply nested JSON models** (thanks to Pydantic).
* **GraphQL** integration with <a href="https://strawberry.rocks" class="external-link" target="_blank">Strawberry</a> and other libraries.
* Many extra features (thanks to Starlette) as:
* **WebSockets**
* extremely easy tests based on `requests` and `pytest`
* **CORS**
* **Cookie Sessions**
* ...and more.
## Performance
Independent TechEmpower benchmarks show **FastAPI** applications running under Uvicorn as <a href="https://www.techempower.com/benchmarks/#section=test&runid=7464e520-0dc2-473d-bd34-dbdfd7e85911&hw=ph&test=query&l=zijzen-7" class="external-link" target="_blank">one of the fastest Python frameworks available</a>, only below Starlette and Uvicorn themselves (used internally by FastAPI). (*)
To understand more about it, see the section <a href="https://fastapi.tiangolo.com/benchmarks/" class="internal-link" target="_blank">Benchmarks</a>.
## Optional Dependencies
Used by Pydantic:
* <a href="https://github.com/esnme/ultrajson" target="_blank"><code>ujson</code></a> - for faster JSON <abbr title="converting the string that comes from an HTTP request into Python data">"parsing"</abbr>.
* <a href="https://github.com/JoshData/python-email-validator" target="_blank"><code>email_validator</code></a> - for email validation.
Used by Starlette:
* <a href="https://requests.readthedocs.io" target="_blank"><code>requests</code></a> - Required if you want to use the `TestClient`.
* <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).
* <a href="https://github.com/esnme/ultrajson" target="_blank"><code>ujson</code></a> - Required if you want to use `UJSONResponse`.
Used by FastAPI / Starlette:
* <a href="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]"`.
## License
This project is licensed under the terms of the MIT license.

135
docs/fa/mkdocs.yml Normal file
View File

@@ -0,0 +1,135 @@
site_name: FastAPI
site_description: FastAPI framework, high performance, easy to learn, fast to code, ready for production
site_url: https://fastapi.tiangolo.com/fa/
theme:
name: material
custom_dir: overrides
palette:
- scheme: default
primary: teal
accent: amber
toggle:
icon: material/lightbulb
name: Switch to light mode
- scheme: slate
primary: teal
accent: amber
toggle:
icon: material/lightbulb-outline
name: Switch to dark mode
features:
- search.suggest
- search.highlight
- content.tabs.link
icon:
repo: fontawesome/brands/github-alt
logo: https://fastapi.tiangolo.com/img/icon-white.svg
favicon: https://fastapi.tiangolo.com/img/favicon.png
language: fa
repo_name: tiangolo/fastapi
repo_url: https://github.com/tiangolo/fastapi
edit_uri: ''
plugins:
- search
- markdownextradata:
data: data
nav:
- FastAPI: index.md
- Languages:
- en: /
- az: /az/
- de: /de/
- es: /es/
- fa: /fa/
- fr: /fr/
- id: /id/
- it: /it/
- ja: /ja/
- ko: /ko/
- nl: /nl/
- pl: /pl/
- pt: /pt/
- ru: /ru/
- sq: /sq/
- tr: /tr/
- uk: /uk/
- zh: /zh/
markdown_extensions:
- toc:
permalink: true
- markdown.extensions.codehilite:
guess_lang: false
- mdx_include:
base_path: docs
- admonition
- codehilite
- extra
- pymdownx.superfences:
custom_fences:
- name: mermaid
class: mermaid
format: !!python/name:pymdownx.superfences.fence_code_format ''
- pymdownx.tabbed:
alternate_style: true
extra:
analytics:
provider: google
property: UA-133183413-1
social:
- icon: fontawesome/brands/github-alt
link: https://github.com/tiangolo/fastapi
- icon: fontawesome/brands/discord
link: https://discord.gg/VQjSZaeJmf
- icon: fontawesome/brands/twitter
link: https://twitter.com/fastapi
- icon: fontawesome/brands/linkedin
link: https://www.linkedin.com/in/tiangolo
- icon: fontawesome/brands/dev
link: https://dev.to/tiangolo
- icon: fontawesome/brands/medium
link: https://medium.com/@tiangolo
- icon: fontawesome/solid/globe
link: https://tiangolo.com
alternate:
- link: /
name: en - English
- link: /az/
name: az
- link: /de/
name: de
- link: /es/
name: es - español
- link: /fa/
name: fa
- link: /fr/
name: fr - français
- link: /id/
name: id
- link: /it/
name: it - italiano
- link: /ja/
name: ja - 日本語
- link: /ko/
name: ko - 한국어
- link: /nl/
name: nl
- 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
extra_javascript:
- https://fastapi.tiangolo.com/js/termynal.js
- https://fastapi.tiangolo.com/js/custom.js

0
docs/fa/overrides/.gitignore vendored Normal file
View File

View File

@@ -0,0 +1,334 @@
# Démarrage
Le fichier **FastAPI** le plus simple possible pourrait ressembler à cela :
```Python
{!../../../docs_src/first_steps/tutorial001.py!}
```
Copiez ce code dans un fichier nommé `main.py`.
Démarrez le serveur :
<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
La commande `uvicorn main:app` fait référence à :
* `main` : le fichier `main.py` (le module Python).
* `app` : l'objet créé dans `main.py` via la ligne `app = FastAPI()`.
* `--reload` : l'option disant à uvicorn de redémarrer le serveur à chaque changement du code. À ne pas utiliser en production !
Vous devriez voir dans la console, une ligne semblable à la suivante :
```hl_lines="4"
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
```
Cette ligne montre l'URL par laquelle l'app est actuellement accessible, sur votre machine locale.
### Allez voir le résultat
Ouvrez votre navigateur à l'adresse <a href="http://127.0.0.1:8000" class="external-link" target="_blank">http://127.0.0.1:8000</a>.
Vous obtiendrez cette réponse JSON :
```JSON
{"message": "Hello World"}
```
### Documentation interactive de l'API
Rendez-vous sur <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
Vous verrez la documentation interactive de l'API générée automatiquement (via <a href="https://github.com/swagger-api/swagger-ui" class="external-link" target="_blank">Swagger UI</a>) :
![Swagger UI](https://fastapi.tiangolo.com/img/index/index-01-swagger-ui-simple.png)
### Documentation alternative
Ensuite, rendez-vous sur <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a>.
Vous y verrez la documentation alternative (via <a href="https://github.com/Rebilly/ReDoc" class="external-link" target="_blank">ReDoc</a>) :
![ReDoc](https://fastapi.tiangolo.com/img/index/index-02-redoc-simple.png)
### OpenAPI
**FastAPI** génère un "schéma" contenant toute votre API dans le standard de définition d'API **OpenAPI**.
#### "Schéma"
Un "schéma" est une définition ou une description de quelque chose. Pas le code qui l'implémente, uniquement une description abstraite.
#### "Schéma" d'API
Ici, <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank">OpenAPI</a> est une spécification qui dicte comment définir le schéma de votre API.
Le schéma inclut les chemins de votre API, les paramètres potentiels de chaque chemin, etc.
#### "Schéma" de données
Le terme "schéma" peut aussi faire référence à la forme de la donnée, comme un contenu JSON.
Dans ce cas, cela signifierait les attributs JSON, ainsi que les types de ces attributs, etc.
#### OpenAPI et JSON Schema
**OpenAPI** définit un schéma d'API pour votre API. Il inclut des définitions (ou "schémas") de la donnée envoyée et reçue par votre API en utilisant **JSON Schema**, le standard des schémas de données JSON.
#### Allez voir `openapi.json`
Si vous êtes curieux d'à quoi ressemble le schéma brut **OpenAPI**, **FastAPI** génère automatiquement un (schéma) JSON avec les descriptions de toute votre API.
Vous pouvez le voir directement à cette adresse : <a href="http://127.0.0.1:8000/openapi.json" class="external-link" target="_blank">http://127.0.0.1:8000/openapi.json</a>.
Le schéma devrait ressembler à ceci :
```JSON
{
"openapi": "3.0.2",
"info": {
"title": "FastAPI",
"version": "0.1.0"
},
"paths": {
"/items/": {
"get": {
"responses": {
"200": {
"description": "Successful Response",
"content": {
"application/json": {
...
```
#### À quoi sert OpenAPI
Le schéma **OpenAPI** est ce qui alimente les deux systèmes de documentation interactive.
Et il existe des dizaines d'alternatives, toutes basées sur **OpenAPI**. Vous pourriez facilement ajouter n'importe laquelle de ces alternatives à votre application **FastAPI**.
Vous pourriez aussi l'utiliser pour générer du code automatiquement, pour les clients qui communiquent avec votre API. Comme par exemple, des applications frontend, mobiles ou IOT.
## Récapitulatif, étape par étape
### Étape 1 : import `FastAPI`
```Python hl_lines="1"
{!../../../docs_src/first_steps/tutorial001.py!}
```
`FastAPI` est une classe Python qui fournit toutes les fonctionnalités nécessaires au lancement de votre API.
!!! note "Détails techniques"
`FastAPI` est une classe héritant directement de `Starlette`.
Vous pouvez donc aussi utiliser toutes les fonctionnalités de <a href="https://www.starlette.io/" class="external-link" target="_blank">Starlette</a> depuis `FastAPI`.
### Étape 2 : créer une "instance" `FastAPI`
```Python hl_lines="3"
{!../../../docs_src/first_steps/tutorial001.py!}
```
Ici la variable `app` sera une "instance" de la classe `FastAPI`.
Ce sera le point principal d'interaction pour créer toute votre API.
Cette `app` est la même que celle à laquelle fait référence `uvicorn` dans la commande :
<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 vous créez votre app avec :
```Python hl_lines="3"
{!../../../docs_src/first_steps/tutorial002.py!}
```
Et la mettez dans un fichier `main.py`, alors vous appeleriez `uvicorn` avec :
<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>
### Étape 3: créer une *opération de chemin*
#### Chemin
Chemin, ou "path" fait référence ici à la dernière partie de l'URL démarrant au premier `/`.
Donc, dans un URL tel que :
```
https://example.com/items/foo
```
...le "path" serait :
```
/items/foo
```
!!! info
Un chemin, ou "path" est aussi souvent appelé route ou "endpoint".
#### Opération
"Opération" fait référence à une des "méthodes" HTTP.
Une de :
* `POST`
* `GET`
* `PUT`
* `DELETE`
...ou une des plus exotiques :
* `OPTIONS`
* `HEAD`
* `PATCH`
* `TRACE`
Dans le protocol HTTP, vous pouvez communiquer avec chaque chemin en utilisant une (ou plus) de ces "méthodes".
---
En construisant des APIs, vous utilisez généralement ces méthodes HTTP spécifiques pour effectuer une action précise.
Généralement vous utilisez :
* `POST` : pour créer de la donnée.
* `GET` : pour lire de la donnée.
* `PUT` : pour mettre à jour de la donnée.
* `DELETE` : pour supprimer de la donnée.
Donc, dans **OpenAPI**, chaque méthode HTTP est appelée une "opération".
Nous allons donc aussi appeler ces dernières des "**opérations**".
#### Définir un *décorateur d'opération de chemin*
```Python hl_lines="6"
{!../../../docs_src/first_steps/tutorial001.py!}
```
Le `@app.get("/")` dit à **FastAPI** que la fonction en dessous est chargée de gérer les requêtes qui vont sur :
* le chemin `/`
* en utilisant une <abbr title="une méthode GET HTTP">opération <code>get</code></abbr>
!!! info "`@décorateur` Info"
Cette syntaxe `@something` en Python est appelée un "décorateur".
Vous la mettez au dessus d'une fonction. Comme un joli chapeau décoratif (j'imagine que ce terme vient de là 🤷🏻‍♂).
Un "décorateur" prend la fonction en dessous et en fait quelque chose.
Dans notre cas, ce décorateur dit à **FastAPI** que la fonction en dessous correspond au **chemin** `/` avec l'**opération** `get`.
C'est le "**décorateur d'opération de chemin**".
Vous pouvez aussi utiliser les autres opérations :
* `@app.post()`
* `@app.put()`
* `@app.delete()`
Tout comme celles les plus exotiques :
* `@app.options()`
* `@app.head()`
* `@app.patch()`
* `@app.trace()`
!!! tip "Astuce"
Vous êtes libres d'utiliser chaque opération (méthode HTTP) comme vous le désirez.
**FastAPI** n'impose pas de sens spécifique à chacune d'elle.
Les informations qui sont présentées ici forment une directive générale, pas des obligations.
Par exemple, quand l'on utilise **GraphQL**, toutes les actions sont effectuées en utilisant uniquement des opérations `POST`.
### Étape 4 : définir la **fonction de chemin**.
Voici notre "**fonction de chemin**" (ou fonction d'opération de chemin) :
* **chemin** : `/`.
* **opération** : `get`.
* **fonction** : la fonction sous le "décorateur" (sous `@app.get("/")`).
```Python hl_lines="7"
{!../../../docs_src/first_steps/tutorial001.py!}
```
C'est une fonction Python.
Elle sera appelée par **FastAPI** quand une requête sur l'URL `/` sera reçue via une opération `GET`.
Ici, c'est une fonction asynchrone (définie avec `async def`).
---
Vous pourriez aussi la définir comme une fonction classique plutôt qu'avec `async def` :
```Python hl_lines="7"
{!../../../docs_src/first_steps/tutorial003.py!}
```
!!! note
Si vous ne connaissez pas la différence, allez voir la section [Concurrence : *"Vous êtes pressés ?"*](../async.md#vous-etes-presses){.internal-link target=_blank}.
### Étape 5 : retourner le contenu
```Python hl_lines="8"
{!../../../docs_src/first_steps/tutorial001.py!}
```
Vous pouvez retourner un dictionnaire (`dict`), une liste (`list`), des valeurs seules comme des chaines de caractères (`str`) et des entiers (`int`), etc.
Vous pouvez aussi retourner des models **Pydantic** (qui seront détaillés plus tard).
Il y a de nombreux autres objets et modèles qui seront automatiquement convertis en JSON. Essayez d'utiliser vos favoris, il est fort probable qu'ils soient déjà supportés.
## Récapitulatif
* Importez `FastAPI`.
* Créez une instance d'`app`.
* Ajoutez une **décorateur d'opération de chemin** (tel que `@app.get("/")`).
* Ajoutez une **fonction de chemin** (telle que `def root(): ...` comme ci-dessus).
* Lancez le serveur de développement (avec `uvicorn main:app --reload`).

View File

@@ -0,0 +1,254 @@
# Paramètres de chemin
Vous pouvez déclarer des "paramètres" ou "variables" de chemin avec la même syntaxe que celle utilisée par le
<a href="https://docs.python.org/fr/3/library/string.html#format-string-syntax" class="external-link" target="_blank">formatage de chaîne Python</a> :
```Python hl_lines="6-7"
{!../../../docs_src/path_params/tutorial001.py!}
```
La valeur du paramètre `item_id` sera transmise à la fonction dans l'argument `item_id`.
Donc, si vous exécutez cet exemple et allez sur <a href="http://127.0.0.1:8000/items/foo" class="external-link" target="_blank">http://127.0.0.1:8000/items/foo</a>,
vous verrez comme réponse :
```JSON
{"item_id":"foo"}
```
## Paramètres de chemin typés
Vous pouvez déclarer le type d'un paramètre de chemin dans la fonction, en utilisant les annotations de type Python :
```Python hl_lines="7"
{!../../../docs_src/path_params/tutorial002.py!}
```
Ici, `item_id` est déclaré comme `int`.
!!! hint "Astuce"
Ceci vous permettra d'obtenir des fonctionnalités de l'éditeur dans votre fonction, telles
que des vérifications d'erreur, de l'auto-complétion, etc.
## <abbr title="aussi appelé sérialisation, ou parfois parsing ou marshalling en anglais">Conversion</abbr> de données
Si vous exécutez cet exemple et allez sur <a href="http://127.0.0.1:8000/items/3" class="external-link" target="_blank">http://127.0.0.1:8000/items/3</a>, vous aurez comme réponse :
```JSON
{"item_id":3}
```
!!! hint "Astuce"
Comme vous l'avez remarqué, la valeur reçue par la fonction (et renvoyée ensuite) est `3`,
en tant qu'entier (`int`) Python, pas la chaîne de caractères (`string`) `"3"`.
Grâce aux déclarations de types, **FastAPI** fournit du
<abbr title="conversion de la chaîne de caractères venant de la requête HTTP en données Python">"parsing"</abbr> automatique.
## Validation de données
Si vous allez sur <a href="http://127.0.0.1:8000/items/foo" class="external-link" target="_blank">http://127.0.0.1:8000/items/foo</a>, vous aurez une belle erreur HTTP :
```JSON
{
"detail": [
{
"loc": [
"path",
"item_id"
],
"msg": "value is not a valid integer",
"type": "type_error.integer"
}
]
}
```
car le paramètre de chemin `item_id` possède comme valeur `"foo"`, qui ne peut pas être convertie en entier (`int`).
La même erreur se produira si vous passez un nombre flottant (`float`) et non un entier, comme ici
<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>.
!!! hint "Astuce"
Donc, avec ces mêmes déclarations de type Python, **FastAPI** vous fournit de la validation de données.
Notez que l'erreur mentionne le point exact où la validation n'a pas réussi.
Ce qui est incroyablement utile au moment de développer et débugger du code qui interagit avec votre API.
## Documentation
Et quand vous vous rendez sur <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>, vous verrez la
documentation générée automatiquement et interactive :
<img src="/img/tutorial/path-params/image01.png">
!!! info
À nouveau, en utilisant uniquement les déclarations de type Python, **FastAPI** vous fournit automatiquement une documentation interactive (via Swagger UI).
On voit bien dans la documentation que `item_id` est déclaré comme entier.
## Les avantages d'avoir une documentation basée sur une norme, et la documentation alternative.
Le schéma généré suivant la norme <a href="https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md" class="external-link" target="_blank">OpenAPI</a>,
il existe de nombreux outils compatibles.
Grâce à cela, **FastAPI** lui-même fournit une documentation alternative (utilisant ReDoc), qui peut être lue
sur <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 même façon, il existe bien d'autres outils compatibles, y compris des outils de génération de code
pour de nombreux langages.
## Pydantic
Toute la validation de données est effectué en arrière-plan avec <a href="https://pydantic-docs.helpmanual.io/" class="external-link" target="_blank">Pydantic</a>,
dont vous bénéficierez de tous les avantages. Vous savez donc que vous êtes entre de bonnes mains.
## L'ordre importe
Quand vous créez des *fonctions de chemins*, vous pouvez vous retrouver dans une situation où vous avez un chemin fixe.
Tel que `/users/me`, disons pour récupérer les données sur l'utilisateur actuel.
Et vous avez un second chemin : `/users/{user_id}` pour récupérer de la donnée sur un utilisateur spécifique grâce à son identifiant d'utilisateur
Les *fonctions de chemin* étant évaluées dans l'ordre, il faut s'assurer que la fonction correspondant à `/users/me` est déclarée avant celle de `/users/{user_id}` :
```Python hl_lines="6 11"
{!../../../docs_src/path_params/tutorial003.py!}
```
Sinon, le chemin `/users/{user_id}` correspondrait aussi à `/users/me`, la fonction "croyant" qu'elle a reçu un paramètre `user_id` avec pour valeur `"me"`.
## Valeurs prédéfinies
Si vous avez une *fonction de chemin* qui reçoit un *paramètre de chemin*, mais que vous voulez que les valeurs possibles des paramètres soient prédéfinies, vous pouvez utiliser les <abbr title="Enumeration">`Enum`</abbr> de Python.
### Création d'un `Enum`
Importez `Enum` et créez une sous-classe qui hérite de `str` et `Enum`.
En héritant de `str` la documentation sera capable de savoir que les valeurs doivent être de type `string` et pourra donc afficher cette `Enum` correctement.
Créez ensuite des attributs de classe avec des valeurs fixes, qui seront les valeurs autorisées pour cette énumération.
```Python hl_lines="1 6-9"
{!../../../docs_src/path_params/tutorial005.py!}
```
!!! info
<a href="https://docs.python.org/3/library/enum.html" class="external-link" target="_blank">Les énumérations (ou enums) sont disponibles en Python</a> depuis la version 3.4.
!!! tip "Astuce"
Pour ceux qui se demandent, "AlexNet", "ResNet", et "LeNet" sont juste des noms de <abbr title="Techniquement, des architectures de modèles">modèles</abbr> de Machine Learning.
### Déclarer un paramètre de chemin
Créez ensuite un *paramètre de chemin* avec une annotation de type désignant l'énumération créée précédemment (`ModelName`) :
```Python hl_lines="16"
{!../../../docs_src/path_params/tutorial005.py!}
```
### Documentation
Les valeurs disponibles pour le *paramètre de chemin* sont bien prédéfinies, la documentation les affiche correctement :
<img src="/img/tutorial/path-params/image03.png">
### Manipuler les *énumérations* Python
La valeur du *paramètre de chemin* sera un des "membres" de l'énumération.
#### Comparer les *membres d'énumération*
Vous pouvez comparer ce paramètre avec les membres de votre énumération `ModelName` :
```Python hl_lines="17"
{!../../../docs_src/path_params/tutorial005.py!}
```
#### Récupérer la *valeur de l'énumération*
Vous pouvez obtenir la valeur réel d'un membre (une chaîne de caractères ici), avec `model_name.value`, ou en général, `votre_membre_d'enum.value` :
```Python hl_lines="20"
{!../../../docs_src/path_params/tutorial005.py!}
```
!!! tip "Astuce"
Vous pouvez aussi accéder la valeur `"lenet"` avec `ModelName.lenet.value`.
#### Retourner des *membres d'énumération*
Vous pouvez retourner des *membres d'énumération* dans vos *fonctions de chemin*, même imbriquée dans un JSON (e.g. un `dict`).
Ils seront convertis vers leurs valeurs correspondantes (chaînes de caractères ici) avant d'être transmis au client :
```Python hl_lines="18 21 23"
{!../../../docs_src/path_params/tutorial005.py!}
```
Le client recevra une réponse JSON comme celle-ci :
```JSON
{
"model_name": "alexnet",
"message": "Deep Learning FTW!"
}
```
## Paramètres de chemin contenant des chemins
Disons que vous avez une *fonction de chemin* liée au chemin `/files/{file_path}`.
Mais que `file_path` lui-même doit contenir un *chemin*, comme `home/johndoe/myfile.txt` par exemple.
Donc, l'URL pour ce fichier pourrait être : `/files/home/johndoe/myfile.txt`.
### Support d'OpenAPI
OpenAPI ne supporte pas de manière de déclarer un paramètre de chemin contenant un *chemin*, cela pouvant causer des scénarios difficiles à tester et définir.
Néanmoins, cela reste faisable dans **FastAPI**, via les outils internes de Starlette.
Et la documentation fonctionne quand même, bien qu'aucune section ne soit ajoutée pour dire que la paramètre devrait contenir un *chemin*.
### Convertisseur de *chemin*
En utilisant une option de Starlette directement, vous pouvez déclarer un *paramètre de chemin* contenant un *chemin* avec une URL comme :
```
/files/{file_path:path}
```
Dans ce cas, le nom du paramètre est `file_path`, et la dernière partie, `:path`, indique à Starlette que le paramètre devrait correspondre à un *chemin*.
Vous pouvez donc l'utilisez comme tel :
```Python hl_lines="6"
{!../../../docs_src/path_params/tutorial004.py!}
```
!!! tip "Astuce"
Vous pourriez avoir besoin que le paramètre contienne `/home/johndoe/myfile.txt`, avec un slash au début (`/`).
Dans ce cas, l'URL serait : `/files//home/johndoe/myfile.txt`, avec un double slash (`//`) entre `files` et `home`.
## Récapitulatif
Avec **FastAPI**, en utilisant les déclarations de type rapides, intuitives et standards de Python, vous bénéficiez de :
* Support de l'éditeur : vérification d'erreurs, auto-complétion, etc.
* <abbr title="conversion de la chaîne de caractères venant de la requête HTTP en données Python">"Parsing"</abbr> de données.
* Validation de données.
* Annotations d'API et documentation automatique.
Et vous n'avez besoin de le déclarer qu'une fois.
C'est probablement l'avantage visible principal de **FastAPI** comparé aux autres *frameworks* (outre les performances pures).

View File

@@ -0,0 +1,198 @@
# Paramètres de requête
Quand vous déclarez des paramètres dans votre fonction de chemin qui ne font pas partie des paramètres indiqués dans le chemin associé, ces paramètres sont automatiquement considérés comme des paramètres de "requête".
```Python hl_lines="9"
{!../../../docs_src/query_params/tutorial001.py!}
```
La partie appelée requête (ou **query**) dans une URL est l'ensemble des paires clés-valeurs placées après le `?` , séparées par des `&`.
Par exemple, dans l'URL :
```
http://127.0.0.1:8000/items/?skip=0&limit=10
```
...les paramètres de requête sont :
* `skip` : avec une valeur de`0`
* `limit` : avec une valeur de `10`
Faisant partie de l'URL, ces valeurs sont des chaînes de caractères (`str`).
Mais quand on les déclare avec des types Python (dans l'exemple précédent, en tant qu'`int`), elles sont converties dans les types renseignés.
Toutes les fonctionnalités qui s'appliquent aux paramètres de chemin s'appliquent aussi aux paramètres de requête :
* Support de l'éditeur : vérification d'erreurs, auto-complétion, etc.
* <abbr title="conversion de la chaîne de caractères venant de la requête HTTP en données Python">"Parsing"</abbr> de données.
* Validation de données.
* Annotations d'API et documentation automatique.
## Valeurs par défaut
Les paramètres de requête ne sont pas une partie fixe d'un chemin, ils peuvent être optionnels et avoir des valeurs par défaut.
Dans l'exemple ci-dessus, ils ont des valeurs par défaut qui sont `skip=0` et `limit=10`.
Donc, accéder à l'URL :
```
http://127.0.0.1:8000/items/
```
serait équivalent à accéder à l'URL :
```
http://127.0.0.1:8000/items/?skip=0&limit=10
```
Mais si vous accédez à, par exemple :
```
http://127.0.0.1:8000/items/?skip=20
```
Les valeurs des paramètres de votre fonction seront :
* `skip=20` : car c'est la valeur déclarée dans l'URL.
* `limit=10` : car `limit` n'a pas été déclaré dans l'URL, et que la valeur par défaut était `10`.
## Paramètres optionnels
De la même façon, vous pouvez définir des paramètres de requête comme optionnels, en leur donnant comme valeur par défaut `None` :
```Python hl_lines="9"
{!../../../docs_src/query_params/tutorial002.py!}
```
Ici, le paramètre `q` sera optionnel, et aura `None` comme valeur par défaut.
!!! check "Remarque"
On peut voir que **FastAPI** est capable de détecter que le paramètre de chemin `item_id` est un paramètre de chemin et que `q` n'en est pas un, c'est donc un paramètre de requête.
!!! note
**FastAPI** saura que `q` est optionnel grâce au `=None`.
Le `Optional` dans `Optional[str]` n'est pas utilisé par **FastAPI** (**FastAPI** n'en utilisera que la partie `str`), mais il servira tout de même à votre editeur de texte pour détecter des erreurs dans votre code.
## Conversion des types des paramètres de requête
Vous pouvez aussi déclarer des paramètres de requête comme booléens (`bool`), **FastAPI** les convertira :
```Python hl_lines="9"
{!../../../docs_src/query_params/tutorial003.py!}
```
Avec ce code, en allant sur :
```
http://127.0.0.1:8000/items/foo?short=1
```
ou
```
http://127.0.0.1:8000/items/foo?short=True
```
ou
```
http://127.0.0.1:8000/items/foo?short=true
```
ou
```
http://127.0.0.1:8000/items/foo?short=on
```
ou
```
http://127.0.0.1:8000/items/foo?short=yes
```
ou n'importe quelle autre variation de casse (tout en majuscules, uniquement la première lettre en majuscule, etc.), votre fonction considérera le paramètre `short` comme ayant une valeur booléenne à `True`. Sinon la valeur sera à `False`.
## Multiples paramètres de chemin et de requête
Vous pouvez déclarer plusieurs paramètres de chemin et paramètres de requête dans la même fonction, **FastAPI** saura comment les gérer.
Et vous n'avez pas besoin de les déclarer dans un ordre spécifique.
Ils seront détectés par leurs noms :
```Python hl_lines="8 10"
{!../../../docs_src/query_params/tutorial004.py!}
```
## Paramètres de requête requis
Quand vous déclarez une valeur par défaut pour un paramètre qui n'est pas un paramètre de chemin (actuellement, nous n'avons vu que les paramètres de requête), alors ce paramètre n'est pas requis.
Si vous ne voulez pas leur donner de valeur par défaut mais juste les rendre optionnels, utilisez `None` comme valeur par défaut.
Mais si vous voulez rendre un paramètre de requête obligatoire, vous pouvez juste ne pas y affecter de valeur par défaut :
```Python hl_lines="6-7"
{!../../../docs_src/query_params/tutorial005.py!}
```
Ici le paramètre `needy` est un paramètre requis (ou obligatoire) de type `str`.
Si vous ouvrez une URL comme :
```
http://127.0.0.1:8000/items/foo-item
```
...sans ajouter le paramètre requis `needy`, vous aurez une erreur :
```JSON
{
"detail": [
{
"loc": [
"query",
"needy"
],
"msg": "field required",
"type": "value_error.missing"
}
]
}
```
La présence de `needy` étant nécessaire, vous auriez besoin de l'insérer dans l'URL :
```
http://127.0.0.1:8000/items/foo-item?needy=sooooneedy
```
...ce qui fonctionnerait :
```JSON
{
"item_id": "foo-item",
"needy": "sooooneedy"
}
```
Et bien sur, vous pouvez définir certains paramètres comme requis, certains avec des valeurs par défaut et certains entièrement optionnels :
```Python hl_lines="10"
{!../../../docs_src/query_params/tutorial006.py!}
```
Ici, on a donc 3 paramètres de requête :
* `needy`, requis et de type `str`.
* `skip`, un `int` avec comme valeur par défaut `0`.
* `limit`, un `int` optionnel.
!!! tip "Astuce"
Vous pouvez utiliser les `Enum`s de la même façon qu'avec les [Paramètres de chemin](path-params.md#valeurs-predefinies){.internal-link target=_blank}.

View File

@@ -9,13 +9,13 @@ theme:
primary: teal
accent: amber
toggle:
icon: material/lightbulb-outline
icon: material/lightbulb
name: Switch to light mode
- scheme: slate
primary: teal
accent: amber
toggle:
icon: material/lightbulb
icon: material/lightbulb-outline
name: Switch to dark mode
features:
- search.suggest
@@ -29,9 +29,6 @@ theme:
repo_name: tiangolo/fastapi
repo_url: https://github.com/tiangolo/fastapi
edit_uri: ''
google_analytics:
- UA-133183413-1
- auto
plugins:
- search
- markdownextradata:
@@ -40,13 +37,16 @@ nav:
- FastAPI: index.md
- Languages:
- en: /
- az: /az/
- de: /de/
- es: /es/
- fa: /fa/
- fr: /fr/
- id: /id/
- it: /it/
- ja: /ja/
- ko: /ko/
- nl: /nl/
- pl: /pl/
- pt: /pt/
- ru: /ru/
@@ -58,6 +58,9 @@ nav:
- fastapi-people.md
- python-types.md
- Tutoriel - Guide utilisateur:
- tutorial/first-steps.md
- tutorial/path-params.md
- tutorial/query-params.md
- tutorial/body.md
- tutorial/background-tasks.md
- async.md
@@ -81,8 +84,12 @@ markdown_extensions:
- name: mermaid
class: mermaid
format: !!python/name:pymdownx.superfences.fence_code_format ''
- pymdownx.tabbed
- pymdownx.tabbed:
alternate_style: true
extra:
analytics:
provider: google
property: UA-133183413-1
social:
- icon: fontawesome/brands/github-alt
link: https://github.com/tiangolo/fastapi
@@ -101,10 +108,14 @@ extra:
alternate:
- link: /
name: en - English
- link: /az/
name: az
- link: /de/
name: de
- link: /es/
name: es - español
- link: /fa/
name: fa
- link: /fr/
name: fr - français
- link: /id/
@@ -115,6 +126,8 @@ extra:
name: ja - 日本語
- link: /ko/
name: ko - 한국어
- link: /nl/
name: nl
- link: /pl/
name: pl
- link: /pt/

View File

@@ -9,13 +9,13 @@ theme:
primary: teal
accent: amber
toggle:
icon: material/lightbulb-outline
icon: material/lightbulb
name: Switch to light mode
- scheme: slate
primary: teal
accent: amber
toggle:
icon: material/lightbulb
icon: material/lightbulb-outline
name: Switch to dark mode
features:
- search.suggest
@@ -29,9 +29,6 @@ theme:
repo_name: tiangolo/fastapi
repo_url: https://github.com/tiangolo/fastapi
edit_uri: ''
google_analytics:
- UA-133183413-1
- auto
plugins:
- search
- markdownextradata:
@@ -40,13 +37,16 @@ nav:
- FastAPI: index.md
- Languages:
- en: /
- az: /az/
- de: /de/
- es: /es/
- fa: /fa/
- fr: /fr/
- id: /id/
- it: /it/
- ja: /ja/
- ko: /ko/
- nl: /nl/
- pl: /pl/
- pt: /pt/
- ru: /ru/
@@ -69,8 +69,12 @@ markdown_extensions:
- name: mermaid
class: mermaid
format: !!python/name:pymdownx.superfences.fence_code_format ''
- pymdownx.tabbed
- pymdownx.tabbed:
alternate_style: true
extra:
analytics:
provider: google
property: UA-133183413-1
social:
- icon: fontawesome/brands/github-alt
link: https://github.com/tiangolo/fastapi
@@ -89,10 +93,14 @@ extra:
alternate:
- link: /
name: en - English
- link: /az/
name: az
- link: /de/
name: de
- link: /es/
name: es - español
- link: /fa/
name: fa
- link: /fr/
name: fr - français
- link: /id/
@@ -103,6 +111,8 @@ extra:
name: ja - 日本語
- link: /ko/
name: ko - 한국어
- link: /nl/
name: nl
- link: /pl/
name: pl
- link: /pt/

View File

@@ -9,13 +9,13 @@ theme:
primary: teal
accent: amber
toggle:
icon: material/lightbulb-outline
icon: material/lightbulb
name: Switch to light mode
- scheme: slate
primary: teal
accent: amber
toggle:
icon: material/lightbulb
icon: material/lightbulb-outline
name: Switch to dark mode
features:
- search.suggest
@@ -29,9 +29,6 @@ theme:
repo_name: tiangolo/fastapi
repo_url: https://github.com/tiangolo/fastapi
edit_uri: ''
google_analytics:
- UA-133183413-1
- auto
plugins:
- search
- markdownextradata:
@@ -40,13 +37,16 @@ nav:
- FastAPI: index.md
- Languages:
- en: /
- az: /az/
- de: /de/
- es: /es/
- fa: /fa/
- fr: /fr/
- id: /id/
- it: /it/
- ja: /ja/
- ko: /ko/
- nl: /nl/
- pl: /pl/
- pt: /pt/
- ru: /ru/
@@ -69,8 +69,12 @@ markdown_extensions:
- name: mermaid
class: mermaid
format: !!python/name:pymdownx.superfences.fence_code_format ''
- pymdownx.tabbed
- pymdownx.tabbed:
alternate_style: true
extra:
analytics:
provider: google
property: UA-133183413-1
social:
- icon: fontawesome/brands/github-alt
link: https://github.com/tiangolo/fastapi
@@ -89,10 +93,14 @@ extra:
alternate:
- link: /
name: en - English
- link: /az/
name: az
- link: /de/
name: de
- link: /es/
name: es - español
- link: /fa/
name: fa
- link: /fr/
name: fr - français
- link: /id/
@@ -103,6 +111,8 @@ extra:
name: ja - 日本語
- link: /ko/
name: ko - 한국어
- link: /nl/
name: nl
- link: /pl/
name: pl
- link: /pt/

View File

@@ -170,7 +170,7 @@ TraefikおよびHTTPS処理を備えたDocker Swarm Modeクラスターをセッ
### FastAPIアプリケーションのデプロイ
すべてを設定するための最も簡単な方法は、[**FastAPI** Project Generators](project-generation.md){.internal-link target=_blank}を使用することでしょう。
すべてを設定するための最も簡単な方法は、[**FastAPI** Project Generators](../project-generation.md){.internal-link target=_blank}を使用することでしょう。
上述したTraefikとHTTPSを備えたDocker Swarm クラスタが統合されるように設計されています。

Some files were not shown because too many files have changed in this diff Show More