Compare commits

...

495 Commits

Author SHA1 Message Date
Sebastián Ramírez
d666ccb622 🔖 Release version 0.95.0 2023-03-18 20:37:42 +01:00
Sebastián Ramírez
38f0cad517 📝 Tweak release notes 2023-03-18 20:37:20 +01:00
Sebastián Ramírez
bd90bed02a 📝 Update release notes 2023-03-18 20:24:12 +01:00
github-actions
546392db98 📝 Update release notes 2023-03-18 19:08:30 +00:00
Sebastián Ramírez
0bc87ec77c 📝 Tweak tip recommending Annotated in docs (#9270)
📝 Tweak tip recommending Annotated
2023-03-18 19:07:53 +00:00
Sebastián Ramírez
fbfd53542e 📝 Update release notes 2023-03-18 19:46:47 +01:00
github-actions
994ea1ad33 📝 Update release notes 2023-03-18 16:16:37 +00:00
Sebastián Ramírez
69673548bc 📝 Update order of examples, latest Python version first, and simplify version tab names (#9269)
* 📝 Simplify names in Python versions in tabs in docs

* 📝 Update docs for Types Intro, explain Python 3.6+, Python 3.9+, Python 3.10+

* 📝 Re-order all Python examples, show latest Python versions first
2023-03-18 17:16:02 +01:00
github-actions
166d348ea6 📝 Update release notes 2023-03-18 12:30:38 +00:00
Sebastián Ramírez
9eaed2eb37 📝 Update all docs to use Annotated as the main recommendation, with new examples and tests (#9268)
* 🍱 Add new source examples with Annotated for Query Params and String Validations

* 📝 Add new docs with Annotated for Query Params and String Validations

* 🚚 Rename incorrectly named tests for Query Params and str validations

*  Add new tests with Annotated for Query Params and Sring Validations examples

* 🍱 Add new examples with Annotated for Intro to Python Types

* 📝 Update Python Types Intro, include Annotated

* 🎨 Fix formatting in Query params and string validation, and highlight

* 🍱 Add new Annotated source examples for Path Params and Numeric Validations

* 📝 Update docs for Path Params and Numeric Validations with Annotated

* 🍱 Add new source examples with Annotated for Body - Multiple Params

* 📝 Update docs with Annotated for Body - Multiple Parameters

*  Add test for new Annotated examples in Body - Multiple Parameters

* 🍱 Add new Annotated source examples for Body Fields

* 📝 Update docs for Body Fields with new Annotated examples

*  Add new tests for new Annotated examples for Body Fields

* 🍱 Add new Annotated source examples for Schema Extra (Example Data)

* 📝 Update docs for Schema Extra with Annotated

*  Add tests for new Annotated examples for Schema Extra

* 🍱 Add new Annnotated source examples for Extra Data Types

* 📝 Update docs with Annotated for Extra Data Types

*  Add tests for new Annotated examples for Extra Data Types

* 🍱 Add new Annotated source examples for Cookie Parameters

* 📝 Update docs for Cookie Parameters with Annotated examples

*  Add tests for new Annotated source examples in Cookie Parameters

* 🍱 Add new Annotated examples for Header Params

* 📝 Update docs with Annotated examples for Header Parameters

*  Add tests for new Annotated examples for Header Params

* 🍱 Add new Annotated examples for Form Data

* 📝 Update Annotated docs for Form Data

*  Add tests for new Annotated examples in Form Data

* 🍱 Add new Annotated source examples for Request Files

* 📝 Update Annotated docs for Request Files

*  Test new Annotated examples for Request Files

* 🍱 Add new Annotated source examples for Request Forms and Files

*  Add tests for new Anotated examples for Request Forms and Files

* 🍱 Add new Annotated source examples for Dependencies and Advanced Dependencies

*  Add tests for new Annotated dependencies

* 📝 Add new docs for using Annotated with dependencies including type aliases

* 📝 Update docs for Classes as Dependencies with Annotated

* 📝 Update docs for Sub-dependencies with Annotated

* 📝 Update docs for Dependencies in path operation decorators with Annotated

* 📝 Update docs for Global Dependencies with Annotated

* 📝 Update docs for Dependencies with yield with Annotated

* 🎨 Update format in example for dependencies with Annotated

* 🍱 Add source examples with Annotated for Security

*  Add tests for new Annotated examples for security

* 📝 Update docs for Security - First Steps with Annotated

* 📝 Update docs for Security: Get Current User with Annotated

* 📝 Update docs for Simple OAuth2 with Password and Bearer with Annotated

* 📝 Update docs for OAuth2 with Password (and hashing), Bearer with JWT tokens with Annotated

* 📝 Update docs for Request Forms and Files with Annotated

* 🍱 Add new source examples for Bigger Applications with Annotated

*  Add new tests for Bigger Applications with Annotated

* 📝 Update docs for Bigger Applications - Multiple Files with Annotated

* 🍱 Add source examples for background tasks with Annotated

* 📝 Update docs for Background Tasks with Annotated

*  Add test for Background Tasks with Anotated

* 🍱 Add new source examples for docs for Testing with Annotated

* 📝 Update docs for Testing with Annotated

*  Add tests for Annotated examples for Testing

* 🍱 Add new source examples for Additional Status Codes with Annotated

*  Add tests for new Annotated examples for Additional Status Codes

* 📝 Update docs for Additional Status Codes with Annotated

* 📝 Update docs for Advanced Dependencies with Annotated

* 📝 Update docs for OAuth2 scopes with Annotated

* 📝 Update docs for HTTP Basic Auth with Annotated

* 🍱 Add source examples with Annotated for WebSockets

*  Add tests for new Annotated examples for WebSockets

* 📝 Update docs for WebSockets with new Annotated examples

* 🍱 Add source examples with Annotated for Settings and Environment Variables

* 📝 Update docs for Settings and Environment Variables with Annotated

* 🍱 Add new source examples for testing dependencies with Annotated

*  Add tests for new examples for testing dependencies

* 📝 Update docs for testing dependencies with new Annotated examples

*  Update and fix marker for Python 3.9 test

* 🔧 Update Ruff ignores for source examples in docs

*  Fix some tests in the grid for Python 3.9 (incorrectly testing 3.10)

* 🔥 Remove source examples and tests for (non existent) docs section about Annotated, as it's covered in all the rest of the docs
2023-03-18 13:29:59 +01:00
github-actions
f63b3ad53e 📝 Update release notes 2023-03-17 20:36:26 +00:00
Nadav Zingerman
375513f114 Add support for PEP-593 Annotated for specifying dependencies and parameters (#4871)
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2023-03-17 21:35:45 +01:00
Sebastián Ramírez
ef176c6631 🔖 Release version 0.94.1 2023-03-14 03:27:11 +01:00
github-actions
7b7e86a307 📝 Update release notes 2023-03-14 02:19:50 +00:00
Sebastián Ramírez
25aabe05ce 🎨 Fix types for lifespan, upgrade Starlette to 0.26.1 (#9245) 2023-03-14 03:19:04 +01:00
Sebastián Ramírez
392ffaae43 🔖 Release version 0.94.0 2023-03-10 20:00:49 +01:00
Sebastián Ramírez
202ee0497a 📝 Update release notes 2023-03-10 20:00:09 +01:00
github-actions
321e873c95 📝 Update release notes 2023-03-10 18:57:58 +00:00
github-actions
4860631468 📝 Update release notes 2023-03-10 18:57:42 +00:00
dependabot[bot]
8e4c96c703 ⬆ Bump black from 22.10.0 to 23.1.0 (#5953)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2023-03-10 19:57:21 +01:00
dependabot[bot]
39813aa9b0 ⬆ Bump types-ujson from 5.6.0.0 to 5.7.0.1 (#6027)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2023-03-10 19:57:07 +01:00
github-actions
3e3278ed3f 📝 Update release notes 2023-03-10 18:51:19 +00:00
dependabot[bot]
c8a07078cf ⬆ Bump dawidd6/action-download-artifact from 2.24.3 to 2.26.0 (#6034)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2023-03-10 19:50:08 +01:00
github-actions
59f91db1d2 📝 Update release notes 2023-03-10 18:49:54 +00:00
pre-commit-ci[bot]
f04b61bd16 ⬆ [pre-commit.ci] pre-commit autoupdate (#5709)
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2023-03-10 19:49:18 +01:00
github-actions
253d58bc5c 📝 Update release notes 2023-03-10 18:48:20 +00:00
Yasser Tahiri
78b8a9b6ec Add pydantic to PyPI classifiers (#5914) 2023-03-10 19:47:38 +01:00
github-actions
c26db94a90 📝 Update release notes 2023-03-10 18:43:10 +00:00
Vladislav Kramorenko
d1f3753e5e 🌐 Add Russian translation for docs/ru/docs/history-design-future.md (#5986) 2023-03-10 19:42:25 +01:00
github-actions
d5b0cc9f58 📝 Update release notes 2023-03-10 18:32:12 +00:00
Ben Beasley
42daed222e ⬆ Upgrade python-multipart to support 0.0.6 (#9212) 2023-03-10 19:31:36 +01:00
github-actions
fd3bfe9f50 📝 Update release notes 2023-03-10 18:27:50 +00:00
Steven Eubank
1fea9c5626 📝 Update Sentry link in docs (#9218) 2023-03-10 19:27:10 +01:00
github-actions
d783463ebd 📝 Update release notes 2023-03-10 18:24:42 +00:00
Sebastián Ramírez
8a4cfa52af ⬆️ Upgrade Starlette version, support new lifespan with state (#9239) 2023-03-10 19:24:04 +01:00
Sebastián Ramírez
25382d2d19 🔖 Release version 0.93.0 2023-03-07 17:06:47 +01:00
Sebastián Ramírez
b9bb441b23 📝 Update release notes 2023-03-07 17:04:40 +01:00
github-actions
e33f30a607 📝 Update release notes 2023-03-07 15:46:37 +00:00
Jordan Speicher
cc9a73c3f8 Add support for lifespan async context managers (superseding startup and shutdown events) (#2944)
Co-authored-by: Mike Shantz <mshantz@coldstorage.com>
Co-authored-by: Jonathan Plasse <13716151+JonathanPlasse@users.noreply.github.com>
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2023-03-07 16:46:00 +01:00
github-actions
66e03c816b 📝 Update release notes 2023-03-06 19:32:19 +00:00
gusty1g
639cf3440a 🌐 Tamil translations - initial setup (#5564)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2023-03-06 20:31:37 +01:00
github-actions
2f1b856fe6 📝 Update release notes 2023-03-06 16:29:17 +00:00
Axel
31e148ba8e 🌐 Add French translation for docs/fr/docs/advanced/path-operation-advanced-configuration.md (#9221)
Co-authored-by: Julian Maurin <julian.maurin.perso@pm.me>
Co-authored-by: Cedric Fraboulet <62244267+frabc@users.noreply.github.com>
2023-03-06 17:28:40 +01:00
github-actions
40c2c44ff9 📝 Update release notes 2023-03-06 16:27:29 +00:00
Cedric Fraboulet
c5f72f02cd 🌐 Add French translation for docs/tutorial/debugging.md (#9175) 2023-03-06 17:26:49 +01:00
github-actions
9b83a00c40 📝 Update release notes 2023-03-04 12:52:10 +00:00
har8
83012a9cf6 🌐 Initiate Armenian translation setup (#5844)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2023-03-04 12:51:37 +00:00
github-actions
8625189351 📝 Update release notes 2023-03-04 12:43:32 +00:00
eykamp
e570371003 ✏ Fix formatting in docs/en/docs/tutorial/metadata.md for ReDoc (#6005) 2023-03-04 13:42:55 +01:00
Aayush Chhabra
4d099250f6 ✏ Fix typo in docs/en/docs/tutorial/bigger-applications.md, "codes" to "code" (#5990)
Typo in docs: it should be code instead of codes
2023-03-04 13:17:21 +01:00
github-actions
9ef46a2299 📝 Update release notes 2023-03-04 12:02:42 +00:00
Ruidy
30a9d68232 🌐 Add French translation for deployment/manually.md (#3693)
Co-authored-by: Sam Courtemanche <smlep.pro@gmail.com>
Co-authored-by: Ruidy <r.nemausat@empfohlen.de>
Co-authored-by: Ruidy <rnemausat@newstore.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2023-03-04 12:02:09 +00:00
github-actions
03bb7c166c 📝 Update release notes 2023-03-04 11:45:13 +00:00
Sebastián Ramírez
c5f343a4fd 👷 Update translation bot messages (#9206) 2023-03-04 11:44:30 +00:00
github-actions
83050bead6 📝 Update release notes 2023-03-04 10:40:08 +00:00
Sebastián Ramírez
bd219c2bbf 👷 Update translations bot to use Discussions, and notify when a PR is done (#9183) 2023-03-04 11:39:28 +01:00
github-actions
4b95025d44 📝 Update release notes 2023-03-04 07:35:11 +00:00
Sebastián Ramírez
ff64772dd1 🔧 Update sponsors-badges (#9182) 2023-03-04 07:34:39 +00:00
github-actions
e8fd74e737 📝 Update release notes 2023-03-04 07:30:07 +00:00
github-actions[bot]
87842ac0db 👥 Update FastAPI People (#9181)
Co-authored-by: github-actions <github-actions@github.com>
2023-03-04 08:29:30 +01:00
github-actions
7674da89d3 📝 Update release notes 2023-03-02 15:11:54 +00:00
Sebastián Ramírez
e9326de161 🔊 Log GraphQL errors in FastAPI People, because it returns 200, with a payload with an error (#9171) 2023-03-02 15:11:17 +00:00
github-actions
97effae92d 📝 Update release notes 2023-03-02 13:07:40 +00:00
Sebastián Ramírez
a8bde44029 💚 Fix/workaround GitHub Actions in Docker with git for FastAPI People (#9169) 2023-03-02 13:06:57 +00:00
github-actions
be54d44b0c 📝 Update release notes 2023-03-01 13:22:41 +00:00
Sebastián Ramírez
35d93d59d8 ♻️ Refactor FastAPI Experts to use only discussions now that questions are migrated (#9165) 2023-03-01 13:22:00 +00:00
github-actions
7b3727e03e 📝 Update release notes 2023-02-21 10:24:13 +00:00
Sebastián Ramírez
a270ab0c3f ⬆️ Upgrade analytics (#6025) 2023-02-21 11:23:37 +01:00
github-actions
f6f39d8714 📝 Update release notes 2023-02-16 18:51:02 +00:00
Sebastián Ramírez
4f4035262c ⬆️ Upgrade and re-enable installing Typer-CLI (#6008) 2023-02-16 18:50:21 +00:00
Sebastián Ramírez
6879082b36 🔖 Release version 0.92.0 2023-02-14 10:17:53 +01:00
Sebastián Ramírez
52ca6cb95b 📝 Update release notes 2023-02-14 10:17:08 +01:00
github-actions
9e283ef66b 📝 Update release notes 2023-02-14 09:13:56 +00:00
Sebastián Ramírez
75e7e9e0a2 ⬆️ Upgrade Starlette to 0.25.0 (#5996) 2023-02-14 09:13:22 +00:00
Sebastián Ramírez
2ca77f9a4d 🔖 Release version 0.91.0 2023-02-10 15:33:25 +01:00
Sebastián Ramírez
3c05189b06 📝 Update release notes 2023-02-10 15:32:23 +01:00
github-actions
a04acf6900 📝 Update release notes 2023-02-10 14:13:57 +00:00
Sebastián Ramírez
d566c6cbca ⬆️ Upgrade Starlette version to 0.24.0 and refactor internals for compatibility (#5985) 2023-02-10 15:13:04 +01:00
Sebastián Ramírez
6e94ec2bf0 🔖 Release version 0.90.1 2023-02-09 20:41:40 +01:00
Sebastián Ramírez
e85c109bcd 📝 Update release notes 2023-02-09 20:40:53 +01:00
github-actions
445e611a29 📝 Update release notes 2023-02-09 19:37:21 +00:00
Jakepys
392766bcfa ✏ Update zip-docs.sh internal script, remove extra space (#5931) 2023-02-09 20:36:46 +01:00
github-actions
5ed70f285b 📝 Update release notes 2023-02-09 19:35:40 +00:00
Chandra Deb
d6fb9429d2 ✏ Tweak wording to clarify docs/en/docs/project-generation.md (#5930) 2023-02-09 20:35:01 +01:00
github-actions
9a5147382e 📝 Update release notes 2023-02-09 19:29:30 +00:00
Yasser Tahiri
99deead7fc ✏ Update Pydantic GitHub URLs (#5952) 2023-02-09 20:28:54 +01:00
github-actions
18e6c3ff6a 📝 Update release notes 2023-02-09 19:27:57 +00:00
Igor Shevchenko
3c5536a780 🌐 Add Russian translation for docs/ru/docs/tutorial/cookie-params.md (#5890) 2023-02-09 20:27:16 +01:00
github-actions
79eed9d7d9 📝 Update release notes 2023-02-09 18:58:23 +00:00
Sebastián Ramírez
e37d504e27 📝 Add opinion from Cisco (#5981) 2023-02-09 18:57:49 +00:00
github-actions
70688eb7b2 📝 Update release notes 2023-02-09 18:47:16 +00:00
Sebastián Ramírez
16599b7356 ⬆️ Upgrade Starlette range to allow 0.23.1 (#5980) 2023-02-09 18:46:38 +00:00
Sebastián Ramírez
148bcf5ce4 🔖 Release version 0.90.0 2023-02-08 11:30:01 +01:00
Sebastián Ramírez
e4c8df062b 📝 Update release notes 2023-02-08 11:28:55 +01:00
github-actions
b313f86338 📝 Update release notes 2023-02-08 10:23:46 +00:00
Marcelo Trylesinski
9293795e99 ⬆️ Bump Starlette from 0.22.0 to 0.23.0 (#5739)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2023-02-08 11:23:07 +01:00
github-actions
58757f63af 📝 Update release notes 2023-02-07 16:51:06 +00:00
Leon
88dc4ce3d7 📝 Add article "Tortoise ORM / FastAPI 整合快速筆記" to External Links (#5496)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2023-02-07 16:50:02 +00:00
github-actions
c9d3656a6e 📝 Update release notes 2023-02-07 16:46:40 +00:00
Sebastián Ramírez
3e4840f21b ⬆️ Upgrade Ubuntu version for docs workflow (#5971) 2023-02-07 16:46:03 +00:00
github-actions
9cb2586499 📝 Update release notes 2023-02-07 13:33:51 +00:00
Alexander Sviridov
8b62319d6c 🌐 Add Russian translation for docs/ru/docs/tutorial/body-fields.md (#5898) 2023-02-07 14:33:16 +01:00
github-actions
6e3c707c60 📝 Update release notes 2023-02-07 13:28:45 +00:00
Sebastián Ramírez
94fa151881 🌐 Add Russian translation for docs/ru/docs/help-fastapi.md (#5970)
Co-authored-by: Xewus <xewuss@yandex.ru>
Co-authored-by: Vladislav Kramorenko <85196001+Xewus@users.noreply.github.com>
2023-02-07 13:28:10 +00:00
github-actions
a4f3bc5a69 📝 Update release notes 2023-02-07 13:10:13 +00:00
github-actions
05342cc264 📝 Update release notes 2023-02-07 13:09:45 +00:00
Bruno Artur Torres Lopes Pereira
8115282ed3 🌐 Add Portuguese translation for docs/pt/docs/tutorial/static-files.md (#5858)
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2023-02-07 14:09:32 +01:00
felipebpl
9ad2cb29f9 🌐 Add Portuguese translation for docs/pt/docs/tutorial/encoder.md (#5525)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2023-02-07 13:09:00 +00:00
github-actions
23d0efa894 📝 Update release notes 2023-02-07 13:05:18 +00:00
Vladislav Kramorenko
e1129af819 🌐 Add Russian translation for docs/ru/docs/contributing.md (#5870)
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2023-02-07 14:04:38 +01:00
github-actions
c59539913d 📝 Update release notes 2023-02-03 17:56:25 +00:00
github-actions[bot]
7a64587d7f 👥 Update FastAPI People (#5954)
Co-authored-by: github-actions <github-actions@github.com>
2023-02-03 18:55:25 +01:00
github-actions
62fc0b4923 📝 Update release notes 2023-02-03 17:55:03 +00:00
Sebastián Ramírez
fc7da62005 📝 Micro-tweak help docs (#5960) 2023-02-03 17:54:22 +00:00
github-actions
40df42f5c7 📝 Update release notes 2023-01-31 14:03:27 +00:00
Sebastián Ramírez
0b0af37b0e 🔧 Update new issue chooser to direct to GitHub Discussions (#5948) 2023-01-31 14:02:52 +00:00
github-actions
73920366e5 📝 Update release notes 2023-01-30 16:50:10 +00:00
Sebastián Ramírez
682067cab2 📝 Recommend GitHub Discussions for questions (#5944) 2023-01-30 16:49:32 +00:00
github-actions
ca30b92dd7 📝 Update release notes 2023-01-30 16:24:22 +00:00
Sebastián Ramírez
72b542d90a 🔧 Update sponsors badges (#5943) 2023-01-30 16:23:43 +00:00
github-actions
9012ab8bcd 📝 Update release notes 2023-01-30 15:16:30 +00:00
Sebastián Ramírez
9530defba8 Compute FastAPI Experts including GitHub Discussions (#5941) 2023-01-30 15:15:56 +00:00
github-actions
7c23bbd96f 📝 Update release notes 2023-01-30 15:10:29 +00:00
Sebastián Ramírez
11b6c0146d ⬆️ Upgrade isort and update pre-commit (#5940) 2023-01-30 16:09:51 +01:00
github-actions
4e29835609 📝 Update release notes 2023-01-24 14:30:38 +00:00
Sebastián Ramírez
9858577cd6 🔧 Add template for questions in Discussions (#5920) 2023-01-24 18:30:03 +04:00
github-actions
cd1ee83435 📝 Update release notes 2023-01-23 14:24:31 +00:00
Sebastián Ramírez
fe74890b4b 🔧 Update Sponsor Budget Insight to Powens (#5916) 2023-01-23 14:23:53 +00:00
github-actions
97a2ebc219 📝 Update release notes 2023-01-23 14:13:39 +00:00
Sebastián Ramírez
805226c2b0 🔧 Update GitHub Sponsors badge data (#5915) 2023-01-23 14:13:03 +00:00
Sebastián Ramírez
5905c3f740 🔖 Release version 0.89.1 2023-01-10 20:31:23 +04:00
Sebastián Ramírez
00f3c831f3 📝 Update release notes 2023-01-10 20:30:10 +04:00
github-actions
e84cb6663e 📝 Update release notes 2023-01-10 16:23:24 +00:00
Sebastián Ramírez
fb8e9083f4 📝 Update docs and examples for Response Model with Return Type Annotations, and update runtime error (#5873) 2023-01-10 16:22:47 +00:00
github-actions
6b83525ff4 📝 Update release notes 2023-01-10 12:46:04 +00:00
Marcelo Trylesinski
fba7493042 🐛 Ignore Response classes on return annotation (#5855)
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2023-01-10 12:45:18 +00:00
github-actions
53973f7f94 📝 Update release notes 2023-01-10 12:38:39 +00:00
Kader M
1562592bde 🌐 Add Turkish translation for docs/tr/docs/tutorial/first_steps.md (#5691)
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2023-01-10 12:38:01 +00:00
github-actions
52a84175c1 📝 Update release notes 2023-01-10 12:34:24 +00:00
Raf Rasenberg
929289b630 📝 Add External Link: FastAPI lambda container: serverless simplified (#5784)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2023-01-10 16:33:36 +04:00
Sebastián Ramírez
69bd7d8501 🔖 Release version 0.89.0 2023-01-07 21:17:10 +04:00
Sebastián Ramírez
a6af7c27f8 📝 Update release notes 2023-01-07 21:15:11 +04:00
github-actions
aa6a8e5d49 📝 Update release notes 2023-01-07 17:05:20 +00:00
dependabot[bot]
c482dd3d42 ⬆ Update coverage[toml] requirement from <7.0,>=6.5.0 to >=6.5.0,<8.0 (#5801)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2023-01-07 17:04:43 +00:00
github-actions
681e5c0199 📝 Update release notes 2023-01-07 17:02:15 +00:00
github-actions
eb39b0f8f8 📝 Update release notes 2023-01-07 17:01:58 +00:00
Xhy-5000
27ce2e2108 📝 Add External Link: Authorization on FastAPI with Casbin (#5712)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2023-01-07 21:01:38 +04:00
dependabot[bot]
f56b0d571d ⬆ Update uvicorn[standard] requirement from <0.19.0,>=0.12.0 to >=0.12.0,<0.21.0 for development (#5795)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2023-01-07 17:01:21 +00:00
github-actions
5c6d7b2ff3 📝 Update release notes 2023-01-07 16:57:45 +00:00
Nonso Mgbechi
78813a543d ✏ Fix typo in docs/en/docs/async.md (#5785)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2023-01-07 20:56:58 +04:00
github-actions
903e3be3b8 📝 Update release notes 2023-01-07 16:56:07 +00:00
dependabot[bot]
a17da3d0f4 ⬆ Bump dawidd6/action-download-artifact from 2.24.2 to 2.24.3 (#5842)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2023-01-07 20:55:29 +04:00
github-actions
d202598c71 📝 Update release notes 2023-01-07 15:35:51 +00:00
github-actions[bot]
2dfdcea69a 👥 Update FastAPI People (#5825)
Co-authored-by: github-actions <github-actions@github.com>
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2023-01-07 15:35:14 +00:00
github-actions
789d649fba 📝 Update release notes 2023-01-07 15:31:38 +00:00
Kelby Faessler
bea1fdd2eb ✏ Fix typo in docs/en/docs/deployment/concepts.md (#5824) 2023-01-07 19:31:03 +04:00
github-actions
929c700117 📝 Update release notes 2023-01-07 15:13:27 +00:00
dependabot[bot]
f4e895bc8a ⬆ Bump types-ujson from 5.5.0 to 5.6.0.0 (#5735)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2023-01-07 15:12:49 +00:00
github-actions
adef9f4c02 📝 Update release notes 2023-01-07 15:08:57 +00:00
dependabot[bot]
6e1152d31f ⬆ Bump pypa/gh-action-pypi-publish from 1.5.2 to 1.6.4 (#5750)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2023-01-07 15:08:12 +00:00
github-actions
9812116dc7 📝 Update release notes 2023-01-07 14:55:35 +00:00
Sviatoslav Sydorenko
2583a83f9d 👷 Add GitHub Action gate/check (#5492) 2023-01-07 18:54:59 +04:00
github-actions
59d654672f 📝 Update release notes 2023-01-07 14:46:09 +00:00
Vladislav Kramorenko
d0027de64f 🌐 Add Russian translation for docs/ru/docs/fastapi-people.md (#5577)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2023-01-07 18:45:32 +04:00
github-actions
3c20b6e42b 📝 Update release notes 2023-01-07 14:34:13 +00:00
Ben Ho
3178c17776 🌐 Fix typo in Chinese translation for docs/zh/docs/benchmarks.md (#4269)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2023-01-07 14:33:29 +00:00
github-actions
1be95ba02d 📝 Update release notes 2023-01-07 14:21:59 +00:00
Nina Hwang
2a3a786dd7 🌐 Add Korean translation for docs/tutorial/cors.md (#3764)
Co-authored-by: weekwith.me <63915557+0417taehyun@users.noreply.github.com>
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2023-01-07 18:21:23 +04:00
github-actions
a3edc76051 📝 Update release notes 2023-01-07 14:14:07 +00:00
Sebastián Ramírez
d70eef825e 🔧 Update sponsors, add Svix (#5848) 2023-01-07 14:13:34 +00:00
github-actions
679aee85ce 📝 Update release notes 2023-01-07 13:59:26 +00:00
Sebastián Ramírez
cb35e275e3 🔧 Remove Doist sponsor (#5847) 2023-01-07 13:58:46 +00:00
github-actions
18d087f9c6 📝 Update release notes 2023-01-07 13:46:24 +00:00
Yurii Karabas
d0573f5713 Add support for function return type annotations to declare the response_model (#1436)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2023-01-07 17:45:48 +04:00
github-actions
efc12c5cdb 📝 Update release notes 2022-12-16 20:25:51 +00:00
dependabot[bot]
4d5cbc71ac ⬆ Update sqlalchemy requirement from <=1.4.41,>=1.3.18 to >=1.3.18,<1.4.43 (#5540)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2022-12-16 23:41:48 +04:00
github-actions
10500dbc03 📝 Update release notes 2022-12-16 19:11:14 +00:00
dependabot[bot]
63ad0ed4a6 ⬆ Bump nwtgck/actions-netlify from 1.2.4 to 2.0.0 (#5757)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-16 23:10:29 +04:00
github-actions
dc9fb1305a 📝 Update release notes 2022-12-16 18:11:45 +00:00
Sebastián Ramírez
9efab1bd96 👷 Refactor CI artifact upload/download for docs previews (#5793) 2022-12-16 22:11:03 +04:00
github-actions
97f04ab58c 📝 Update release notes 2022-12-03 22:26:17 +00:00
dependabot[bot]
1ba515a18d ⬆ Bump pypa/gh-action-pypi-publish from 1.5.1 to 1.5.2 (#5714)
Bumps [pypa/gh-action-pypi-publish](https://github.com/pypa/gh-action-pypi-publish) from 1.5.1 to 1.5.2.
- [Release notes](https://github.com/pypa/gh-action-pypi-publish/releases)
- [Commits](https://github.com/pypa/gh-action-pypi-publish/compare/v1.5.1...v1.5.2)

---
updated-dependencies:
- dependency-name: pypa/gh-action-pypi-publish
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-03 23:25:39 +01:00
github-actions
5f1cc3a5ff 📝 Update release notes 2022-12-02 17:23:12 +00:00
github-actions[bot]
41db4cba4c 👥 Update FastAPI People (#5722)
Co-authored-by: github-actions <github-actions@github.com>
2022-12-02 18:22:33 +01:00
github-actions
83bcdc40d8 📝 Update release notes 2022-11-29 18:06:22 +00:00
Sebastián Ramírez
8bdab084f9 🔧 Update sponsors, disable course bundle (#5713) 2022-11-29 19:05:40 +01:00
github-actions
5c4054ab8a 📝 Update release notes 2022-11-28 07:13:14 +00:00
dependabot[bot]
7e4e0d22ae ⬆ Update typer[all] requirement from <0.7.0,>=0.6.1 to >=0.6.1,<0.8.0 (#5639)
Updates the requirements on [typer[all]](https://github.com/tiangolo/typer) to permit the latest version.
- [Release notes](https://github.com/tiangolo/typer/releases)
- [Changelog](https://github.com/tiangolo/typer/blob/master/docs/release-notes.md)
- [Commits](https://github.com/tiangolo/typer/compare/0.6.1...0.7.0)

---
updated-dependencies:
- dependency-name: typer[all]
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2022-11-28 08:12:37 +01:00
Sebastián Ramírez
612b8ff168 🔖 Release version 0.88.0 2022-11-27 15:50:32 +01:00
Sebastián Ramírez
46bb5d2c4b 📝 Update release notes 2022-11-27 15:49:33 +01:00
github-actions
c458ca6f07 📝 Update release notes 2022-11-27 14:46:48 +00:00
Eugenio Panadero
46974c510e ⬆ Bump Starlette to version 0.22.0 to fix bad encoding for query parameters in TestClient (#5659)
closes https://github.com/tiangolo/fastapi/issues/5646
2022-11-27 15:46:06 +01:00
github-actions
89ec1f2d36 📝 Update release notes 2022-11-27 14:23:13 +00:00
github-actions
128c925c35 📝 Update release notes 2022-11-27 14:22:41 +00:00
Sebastián Ramírez
884203676d 👷 Tweak build-docs to improve CI performance (#5699) 2022-11-27 14:22:30 +00:00
pre-commit-ci[bot]
9b4e85f088 ⬆ [pre-commit.ci] pre-commit autoupdate (#5566)
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2022-11-27 15:22:03 +01:00
github-actions
991db7b05a 📝 Update release notes 2022-11-27 14:14:28 +00:00
Ayrton Freeman
ebd917a530 🌐 Add Portuguese translation for docs/pt/docs/deployment/docker.md (#5663)
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2022-11-27 14:13:50 +00:00
github-actions
99d8470a8e 📝 Update release notes 2022-11-27 14:00:09 +00:00
Sebastián Ramírez
7c5626bef7 ⬆️ Upgrade Ruff (#5698) 2022-11-27 14:59:32 +01:00
github-actions
91e5a5d1cf 📝 Update release notes 2022-11-27 13:53:52 +00:00
Sebastián Ramírez
fcc4dd61f1 👷 Remove pip cache for Smokeshow as it depends on a requirements.txt (#5700) 2022-11-27 14:53:13 +01:00
github-actions
0b53ee505b 📝 Update release notes 2022-11-27 13:40:03 +00:00
Sebastián Ramírez
c942a9b8d0 💚 Fix pip cache for Smokeshow (#5697) 2022-11-27 14:39:17 +01:00
github-actions
c77384fc8f 📝 Update release notes 2022-11-27 13:12:12 +00:00
Sebastián Ramírez
0c07e542a7 👷 Fix and tweak CI cache handling (#5696) 2022-11-27 13:11:22 +00:00
github-actions
ec30c3001d 📝 Update release notes 2022-11-25 11:39:33 +00:00
Michael Adkins
22837ee202 👷 Update setup-python action in tests to use new caching feature (#5680) 2022-11-25 12:38:55 +01:00
github-actions
0eb05cabbf 📝 Update release notes 2022-11-22 13:30:37 +00:00
Muhammad Abdur Rakib
6883f362a5 ✏️ Fix typo in docs for docs/en/docs/advanced/middleware.md (#5376)
Fix typo in documentation

A full-stop was missing in `TrustedHostMiddleware` section

Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2022-11-22 13:29:57 +00:00
github-actions
4638b2c64e 📝 Update release notes 2022-11-13 22:07:03 +00:00
dependabot[bot]
3c01b2469f ⬆ Bump black from 22.8.0 to 22.10.0 (#5569)
Bumps [black](https://github.com/psf/black) from 22.8.0 to 22.10.0.
- [Release notes](https://github.com/psf/black/releases)
- [Changelog](https://github.com/psf/black/blob/main/CHANGES.md)
- [Commits](https://github.com/psf/black/compare/22.8.0...22.10.0)

---
updated-dependencies:
- dependency-name: black
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2022-11-13 23:06:28 +01:00
Sebastián Ramírez
63a5ffcf57 🔖 Release version 0.87.0 2022-11-13 22:36:53 +01:00
Sebastián Ramírez
da1c67338f 🔖 Release version 0.87.0 2022-11-13 22:27:53 +01:00
Sebastián Ramírez
46a509649d 📝 Update release notes 2022-11-13 22:26:43 +01:00
github-actions
1d416c4c53 📝 Update release notes 2022-11-13 20:51:19 +00:00
Sebastián Ramírez
89095eba4f ⬆️ Upgrade and relax dependencies for extras "all" (#5634) 2022-11-13 21:50:43 +01:00
github-actions
5a63f660de 📝 Update release notes 2022-11-13 20:30:05 +00:00
Sebastián Ramírez
9c483505e3 ✏️ Tweak Help FastAPI from PR review after merging (#5633) 2022-11-13 20:29:23 +00:00
github-actions
ad0e923fed 📝 Update release notes 2022-11-13 20:29:15 +00:00
Pax
fc717f84ff ✏️ Clarify docs on CORS (#5627) 2022-11-13 21:28:37 +01:00
Sebastián Ramírez
b1204a9b62 📝 Update release notes 2022-11-13 21:23:22 +01:00
github-actions
16630bf54d 📝 Update release notes 2022-11-13 19:34:43 +00:00
Sebastián Ramírez
50ea75ae98 📝 Update Help FastAPI: Help Maintain FastAPI (#5632) 2022-11-13 20:34:09 +01:00
github-actions
a0852e2f53 📝 Update release notes 2022-11-13 18:19:43 +00:00
Sebastián Ramírez
fa74093440 Use Ruff for linting (#5630) 2022-11-13 19:19:04 +01:00
github-actions
bcd9ab95e1 📝 Update release notes 2022-11-13 16:11:29 +00:00
Sebastián Ramírez
d537ee93d7 Re-export Starlette's WebSocketException and add it to docs (#5629) 2022-11-13 17:10:54 +01:00
github-actions
1c93d5523a 📝 Update release notes 2022-11-13 15:20:44 +00:00
Sebastián Ramírez
f92f87d379 📝 Update references to Requests for tests to HTTPX, and add HTTPX to extras (#5628) 2022-11-13 16:20:05 +01:00
github-actions
57141ccac4 📝 Update release notes 2022-11-13 14:35:13 +00:00
github-actions
46b903f70b 📝 Update release notes 2022-11-13 14:26:43 +00:00
Paweł Rubin
fdbd48be5f ⬆ Upgrade Starlette to 0.21.0, including the new [TestClient based on HTTPX](https://github.com/encode/starlette/releases/tag/0.21.0) (#5471)
Co-authored-by: Paweł Rubin <pawel.rubin@ocado.com>
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2022-11-13 15:26:09 +01:00
github-actions
5f67ac6fd6 📝 Update release notes 2022-11-13 14:04:27 +00:00
axel584
ba5310f731 🌐 Add French translation for docs/fr/docs/advanced/additional-status-code.md (#5477)
Co-authored-by: Julian Maurin <julian.maurin.perso@pm.me>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2022-11-13 14:03:48 +00:00
github-actions
f57ccd8ef3 📝 Update release notes 2022-11-13 13:59:55 +00:00
Bruno Artur Torres Lopes Pereira
c040e3602a 🌐 Add Portuguese translation for docs/pt/docs/tutorial/request-forms-and-files.md (#5579)
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2022-11-13 14:59:16 +01:00
github-actions
86d4073632 📝 Update release notes 2022-11-13 13:59:09 +00:00
Ryusei Ishikawa
59208e4ddc 🌐 Add Japanese translation for docs/ja/docs/advanced/websockets.md (#4983)
Co-authored-by: tokusumi <41147016+tokusumi@users.noreply.github.com>
Co-authored-by: komtaki <39375566+komtaki@users.noreply.github.com>
2022-11-13 14:58:31 +01:00
nikkie
0781a91d19 🌐 Fix highlight lines for Japanese translation for docs/tutorial/query-params.md (#2969)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
Fix https://github.com/tiangolo/fastapi/issues/2966
2022-11-13 14:57:52 +01:00
github-actions
41735d2de9 📝 Update release notes 2022-11-10 12:22:58 +00:00
Sebastián Ramírez
a0c717d784 🛠 Add Arabic issue number to Notify Translations GitHub Action (#5610) 2022-11-10 12:22:25 +00:00
github-actions
0ed9ca78bc 📝 Update release notes 2022-11-10 11:16:30 +00:00
dependabot[bot]
678d35994a ⬆ Bump dawidd6/action-download-artifact from 2.24.1 to 2.24.2 (#5609)
Bumps [dawidd6/action-download-artifact](https://github.com/dawidd6/action-download-artifact) from 2.24.1 to 2.24.2.
- [Release notes](https://github.com/dawidd6/action-download-artifact/releases)
- [Commits](https://github.com/dawidd6/action-download-artifact/compare/v2.24.1...v2.24.2)

---
updated-dependencies:
- dependency-name: dawidd6/action-download-artifact
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-10 12:15:55 +01:00
github-actions
a7edd0b80d 📝 Update release notes 2022-11-09 11:46:50 +00:00
dependabot[bot]
f36d2e2b2b ⬆ Bump dawidd6/action-download-artifact from 2.24.0 to 2.24.1 (#5603)
Bumps [dawidd6/action-download-artifact](https://github.com/dawidd6/action-download-artifact) from 2.24.0 to 2.24.1.
- [Release notes](https://github.com/dawidd6/action-download-artifact/releases)
- [Commits](https://github.com/dawidd6/action-download-artifact/compare/v2.24.0...v2.24.1)

---
updated-dependencies:
- dependency-name: dawidd6/action-download-artifact
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-09 12:46:14 +01:00
github-actions
5f0e095689 📝 Update release notes 2022-11-04 19:20:29 +00:00
Sebastián Ramírez
ccd242348f 🔖 Release version 0.86.0 2022-11-03 22:17:44 +01:00
Sebastián Ramírez
066cfae56e 📝 Update release notes 2022-11-03 22:16:37 +01:00
github-actions
51e768e85a 📝 Update release notes 2022-11-03 21:13:25 +00:00
Sebastián Ramírez
10fbfd6dc7 ⬆ Add Python 3.11 to the officially supported versions (#5587) 2022-11-03 21:12:43 +00:00
Sebastián Ramírez
85e602d7cc 📝 Update release notes 2022-11-03 22:05:26 +01:00
github-actions
fbc13d1f5b 📝 Update release notes 2022-11-03 21:01:09 +00:00
Vivek Ashokkumar
d4e2bdb33a ✏ Fix typo in docs/en/docs/tutorial/security/oauth2-jwt.md (#5584)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2022-11-03 21:00:28 +00:00
github-actions
8a5befd099 📝 Update release notes 2022-11-03 20:56:13 +00:00
Sebastián Ramírez
9a442c9730 👷 Update FastAPI People to exclude bots: pre-commit-ci, dependabot (#5586) 2022-11-03 20:55:32 +00:00
Sebastián Ramírez
4fa4965beb 📝 Update coverage badge to use Samuel Colvin's Smokeshow (#5585) 2022-11-03 21:55:00 +01:00
github-actions
5f4680201c 📝 Update release notes 2022-11-03 20:06:36 +00:00
Irfanuddin Shafi Ahmed
5cd99a9517 🎨 Format OpenAPI JSON in test_starlette_exception.py (#5379) 2022-11-03 21:06:00 +01:00
github-actions
b6ea8414a9 📝 Update release notes 2022-11-03 20:01:17 +00:00
Sebastián Ramírez
be3e29fb3c 👷 Switch from Codecov to Smokeshow plus pytest-cov to pure coverage for internal tests (#5583) 2022-11-03 21:00:29 +01:00
github-actions
cf730518bc 📝 Update release notes 2022-11-03 12:27:24 +00:00
Sebastián Ramírez
d62f5c1b28 Enable tests for Python 3.11 (#4881) 2022-11-03 13:26:48 +01:00
github-actions
4cf9075809 📝 Update release notes 2022-11-03 12:08:23 +00:00
ZHCai
a0c677ef0d 🌐 Update wording in Chinese translation for docs/zh/docs/python-types.md (#5416) 2022-11-03 13:07:49 +01:00
github-actions
54aa27ca07 📝 Update release notes 2022-11-03 12:07:29 +00:00
Adrian Garcia Badaracco
ac9f56ea5e 🐛 Close FormData (uploaded files) after the request is done (#5465)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2022-11-03 13:06:52 +01:00
github-actions
ed9425ef50 📝 Update release notes 2022-11-03 11:52:17 +00:00
Vladislav Kramorenko
9a85535e7f 🌐 Add Russian translation for docs/ru/docs/deployment/index.md (#5336)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2022-11-03 11:51:44 +00:00
github-actions
c9308cf070 📝 Update release notes 2022-11-03 11:51:26 +00:00
jaystone776
058cb6e88e 🌐 Update Chinese translation for docs/tutorial/security/oauth2-jwt.md (#3846)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2022-11-03 11:50:48 +00:00
github-actions
876ea7978f 📝 Update release notes 2022-11-03 11:45:26 +00:00
github-actions[bot]
da0bfd22aa 👥 Update FastAPI People (#5571)
Co-authored-by: github-actions <github-actions@github.com>
2022-11-03 12:44:51 +01:00
Sebastián Ramírez
d0917ce015 🔖 Release version 0.85.2 2022-10-31 19:57:16 +01:00
Sebastián Ramírez
6002290659 📝 Update release notes 2022-10-31 19:56:21 +01:00
github-actions
e92a8649f9 📝 Update release notes 2022-10-31 18:12:19 +00:00
Bruno Artur Torres Lopes Pereira
c28337e61d 🌐 Add Portuguese translation for docs/pt/docs/tutorial/request-forms.md (#4934)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2022-10-31 19:11:41 +01:00
github-actions
f4aea58528 📝 Update release notes 2022-10-31 18:08:49 +00:00
Zssaer
fcab59be88 🌐 Add Chinese translation for docs/zh/docs/tutorial/dependencies/classes-as-dependencies.md (#4971)
Co-authored-by: Jeodre <jedore_fight@189.cn>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2022-10-31 19:08:15 +01:00
github-actions
6aa9ef0c96 📝 Update release notes 2022-10-31 18:08:01 +00:00
Ruidy
c7fe6fea33 🌐 Add French translation for deployment/deta.md (#3692)
Co-authored-by: Sam Courtemanche <smlep.pro@gmail.com>
Co-authored-by: Ruidy <r.nemausat@empfohlen.de>
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2022-10-31 18:07:22 +00:00
github-actions
c53e5bd4b1 📝 Update release notes 2022-10-31 17:58:24 +00:00
非法操作
db4452d47e 🌐 Update Chinese translation for docs/zh/docs/tutorial/query-params-str-validations.md (#5255)
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2022-10-31 18:57:38 +01:00
github-actions
53127efde5 📝 Update release notes 2022-10-31 17:57:25 +00:00
Zssaer
9974c4b6ac 🌐 Add Chinese translation for docs/zh/docs/tutorial/sql-databases.md (#4999)
Co-authored-by: mkdir700 <56359329+mkdir700@users.noreply.github.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2022-10-31 18:56:49 +01:00
Ruidy
7ff62468a0 🌐 Add French translation for deployment/https.md (#3691)
Co-authored-by: Sam Courtemanche <smlep.pro@gmail.com>
Co-authored-by: Ruidy <r.nemausat@empfohlen.de>
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2022-10-31 17:45:30 +00:00
github-actions
38493f8ae1 📝 Update release notes 2022-10-31 17:44:58 +00:00
github-actions
e0945eb1c8 📝 Update release notes 2022-10-31 17:44:40 +00:00
ASpathfinder
a26a3c1cbf 🌐 Add Chinese translation for docs/zh/docs/advanced/wsgi.md (#4505)
Co-authored-by: Jeodre <jedore_fight@189.cn>
Co-authored-by: KellyAlsa-massive-win <lhz928441818@gmail.com>
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2022-10-31 18:43:39 +01:00
Lucas Mendes
2889b4a3df 🌐 Add Portuguese translation for docs/pt/docs/tutorial/body-multiple-params.md (#4111)
Co-authored-by: Lorhan Sohaky <contato+gi74@lorhan.me>
Co-authored-by: Wuerike <35462243+Wuerike@users.noreply.github.com>
Co-authored-by: Lorhan Sohaky <16273730+LorhanSohaky@users.noreply.github.com>
2022-10-31 18:42:57 +01:00
github-actions
8b20eece4c 📝 Update release notes 2022-10-31 17:42:41 +00:00
Lucas Mendes
330e8112ac 🌐 Add Portuguese translation for docs/pt/docs/tutorial/path-params-numeric-validations.md (#4099)
Co-authored-by: Pedro Victor <32584628+peidrao@users.noreply.github.com>
Co-authored-by: Lucas <61513630+lsglucas@users.noreply.github.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2022-10-31 18:41:58 +01:00
github-actions
7a2e9c7aaa 📝 Update release notes 2022-10-31 17:41:03 +00:00
Ruidy
1613749cc3 🌐 Add French translation for deployment/versions.md (#3690)
Co-authored-by: Sam Courtemanche <smlep.pro@gmail.com>
Co-authored-by: Ruidy <r.nemausat@empfohlen.de>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2022-10-31 18:39:54 +01:00
github-actions
669b3a4cb8 📝 Update release notes 2022-10-31 17:38:37 +00:00
dependabot[bot]
5f089435e5 ⬆ Bump nwtgck/actions-netlify from 1.2.3 to 1.2.4 (#5507)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2022-10-31 17:37:23 +00:00
github-actions
f1c61dec0c 📝 Update release notes 2022-10-31 17:36:43 +00:00
github-actions
a96effa86e 📝 Update release notes 2022-10-31 17:36:24 +00:00
dependabot[bot]
29c36f9d3f ⬆ Bump internal dependency types-ujson from 5.4.0 to 5.5.0 (#5537)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2022-10-31 17:36:09 +00:00
dependabot[bot]
fcf49a04eb ⬆ Bump dawidd6/action-download-artifact from 2.23.0 to 2.24.0 (#5508)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2022-10-31 17:35:48 +00:00
github-actions
558d929568 📝 Update release notes 2022-10-31 17:34:47 +00:00
Julian Maurin
f3086a7b15 🌐 Add French translation for docs/fr/docs/help-fastapi.md (#2233)
Co-authored-by: Ruidy <ruidy.nemausat@gmail.com>
2022-10-31 18:34:09 +01:00
github-actions
64d512e349 📝 Update release notes 2022-10-31 17:21:40 +00:00
Pamela Fox
88556dafb6 ✏ Fix grammar and add helpful links to dependencies in docs/en/docs/async.md (#5432) 2022-10-31 18:21:05 +01:00
github-actions
6a46532cc4 📝 Update release notes 2022-10-31 17:17:35 +00:00
Shubham
c75de8cba2 ✏ Fix broken link in alternatives.md (#5455)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2022-10-31 17:16:57 +00:00
github-actions
85443e64ee 📝 Update release notes 2022-10-31 17:10:20 +00:00
dependabot[bot]
2623a06105 ⬆ Update internal dependency pytest-cov requirement from <4.0.0,>=2.12.0 to >=2.12.0,<5.0.0 (#5539)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2022-10-31 17:09:45 +00:00
github-actions
d72599b4dc 📝 Update release notes 2022-10-31 16:51:55 +00:00
pre-commit-ci[bot]
16e058697d ⬆ [pre-commit.ci] pre-commit autoupdate (#5536)
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2022-10-31 17:48:43 +01:00
github-actions
bbfa450991 📝 Update release notes 2022-10-31 16:47:12 +00:00
zhangbo
22524a1610 ✏ Fix typo in docs about contributing, for compatibility with pip in Zsh (#5523)
Co-authored-by: zhangbo <zhangbo@zjptmc.com>
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2022-10-31 16:46:37 +00:00
github-actions
959f6bf209 📝 Update release notes 2022-10-31 16:46:16 +00:00
dependabot[bot]
80eac96c70 ⬆ Bump internal dependency mypy from 0.971 to 0.982 (#5541)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2022-10-31 17:45:41 +01:00
github-actions
bbb8fe1e60 📝 Update release notes 2022-10-31 16:40:30 +00:00
yuk115nt5now
bfb1422555 🌐 Fix typo in Chinese translation for docs/zh/docs/tutorial/security/first-steps.md (#5530) 2022-10-31 17:39:44 +01:00
github-actions
0cc40ed664 📝 Update release notes 2022-10-31 16:39:02 +00:00
feliciss
4a1c69e6c2 📝 Fix typo in docs with examples for Python 3.10 instead of 3.9 (#5545)
Co-authored-by: Feliciss <system@Felicisss-MacBook-Air.local>
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2022-10-31 16:38:10 +00:00
github-actions
42a4ed7a18 📝 Update release notes 2022-10-31 16:22:46 +00:00
Bruno Artur Torres Lopes Pereira
146b9d6e04 🌐 Add Portuguese translation for docs/pt/docs/tutorial/response-status-code.md (#4922)
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2022-10-31 17:22:07 +01:00
github-actions
e0d1619362 📝 Update release notes 2022-10-31 16:07:36 +00:00
Sebastián Ramírez
fdfcb9412e 🔧 Add config for Tamil translations (#5563) 2022-10-31 16:07:02 +00:00
github-actions
866a24f879 📝 Update release notes 2022-10-31 13:36:59 +00:00
Samuel Colvin
ee4b2bb8ae 🐛 Fix internal Trio test warnings (#5547) 2022-10-31 14:36:30 +01:00
github-actions
f67b19f0f7 📝 Update release notes 2022-10-20 11:15:56 +00:00
pre-commit-ci[bot]
9dc1a3026d ⬆ [pre-commit.ci] pre-commit autoupdate (#5408)
updates:
- [github.com/asottile/pyupgrade: v2.37.3 → v3.1.0](https://github.com/asottile/pyupgrade/compare/v2.37.3...v3.1.0)
- https://github.com/myint/autoflakehttps://github.com/PyCQA/autoflake
- [github.com/PyCQA/autoflake: v1.5.3 → v1.7.6](https://github.com/PyCQA/autoflake/compare/v1.5.3...v1.7.6)
- [github.com/psf/black: 22.8.0 → 22.10.0](https://github.com/psf/black/compare/22.8.0...22.10.0)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2022-10-20 13:15:19 +02:00
github-actions
e13df8ee79 📝 Update release notes 2022-10-16 15:16:24 +00:00
Sebastián Ramírez
e04878edfe ⬆️ Upgrade Typer to include Rich in scripts for docs (#5502) 2022-10-16 15:15:47 +00:00
github-actions
0e3ff851c2 📝 Update release notes 2022-10-16 15:02:15 +00:00
Sebastián Ramírez
e866a2c7e1 🐛 Fix calling mkdocs for languages as a subprocess to fix/enable MkDocs Material search plugin (#5501)
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2022-10-16 17:01:38 +02:00
Sebastián Ramírez
90fc4299d1 🔖 Release version 0.85.1 2022-10-14 22:52:36 +02:00
github-actions
a3a37a4213 📝 Update release notes 2022-10-14 20:50:44 +00:00
github-actions[bot]
3c6528460c 👥 Update FastAPI People (#5447)
Co-authored-by: github-actions <github-actions@github.com>
2022-10-14 22:50:07 +02:00
github-actions
5ba0c8c002 📝 Update release notes 2022-10-14 20:44:57 +00:00
Jarro van Ginkel
0ae8db447a 🐛 Fix support for strings in OpenAPI status codes: default, 1XX, 2XX, 3XX, 4XX, 5XX (#5187)
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2022-10-14 22:44:22 +02:00
github-actions
9c6086eee6 📝 Update release notes 2022-10-14 20:22:46 +00:00
Sebastián Ramírez
ebe69913ae 🔧 Disable Material for MkDocs search plugin (#5495) 2022-10-14 20:22:09 +00:00
github-actions
81115dba53 📝 Update release notes 2022-10-11 20:50:43 +00:00
Samuel Colvin
1d1859675f 🔇 Ignore Trio warning in tests for CI (#5483) 2022-10-12 00:50:01 +04:00
github-actions
c6aa28bea2 📝 Update release notes 2022-09-20 14:30:02 +00:00
moneeka
20f689ded2 📝 Add WayScript x FastAPI Tutorial to External Links section (#5407) 2022-09-20 16:29:23 +02:00
Sebastián Ramírez
1213227667 🔖 Release version 0.85.0 2022-09-15 15:57:23 +02:00
Sebastián Ramírez
e782ba43ce 📝 Update release notes 2022-09-15 15:56:35 +02:00
github-actions
6ddd0c64b0 📝 Update release notes 2022-09-15 13:49:32 +00:00
Sebastián Ramírez
a05e8b4e6f ⬆️ Upgrade Uvicorn in public extras: all (#5401) 2022-09-15 13:48:53 +00:00
github-actions
e83aa43296 📝 Update release notes 2022-09-15 13:43:34 +00:00
Sebastián Ramírez
95cbb43b06 ⬆️ Upgrade dependencies for doc and dev internal extras: Typer, Uvicorn (#5400) 2022-09-15 13:42:53 +00:00
github-actions
babe2f9b03 📝 Update release notes 2022-09-15 13:33:12 +00:00
Sebastián Ramírez
add7c4800c ⬆️ Upgrade test dependencies: Black, HTTPX, databases, types-ujson (#5399) 2022-09-15 13:32:22 +00:00
github-actions
b741ea7619 📝 Update release notes 2022-09-15 13:27:00 +00:00
Sebastián Ramírez
74ce2204ae ⬆️ Upgrade mypy and tweak internal type annotations (#5398) 2022-09-15 13:26:21 +00:00
github-actions
823df88c34 📝 Update release notes 2022-09-15 13:02:23 +00:00
Sebastián Ramírez
3658733b5e 🔧 Update test dependencies, upgrade Pytest, move dependencies from dev to test (#5396) 2022-09-15 13:01:46 +00:00
github-actions
715c0341a9 📝 Update release notes 2022-09-15 12:32:54 +00:00
Marcelo Trylesinski
adcf03f2bc ⬆ Upgrade version required of Starlette from 0.19.1 to 0.20.4 (#4820)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2022-09-15 14:32:05 +02:00
Sebastián Ramírez
1073062c7f 🔖 Release version 0.84.0 2022-09-14 20:41:29 +02:00
github-actions
7291cead65 📝 Update release notes 2022-09-14 18:32:03 +00:00
Ofek Lev
4267bd1f4f 🔧 Update package metadata, drop support for Python 3.6, move build internals from Flit to Hatch (#5240)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2022-09-14 20:31:19 +02:00
Sebastián Ramírez
b2aa3593be 📝 Update release notes 2022-09-11 18:26:30 +02:00
Sebastián Ramírez
ed0fcba7cb 🔖 Release version 0.83.0 2022-09-11 18:25:29 +02:00
Sebastián Ramírez
22a155efc1 📝 Update release notes 2022-09-11 18:24:46 +02:00
github-actions
306326a213 📝 Update release notes 2022-09-11 16:16:31 +00:00
Marcelo Trylesinski
4fec12b354 📝 Update SECURITY.md (#5377) 2022-09-11 18:15:49 +02:00
github-actions
275306c369 📝 Update release notes 2022-09-11 16:14:21 +00:00
Irfanuddin Shafi Ahmed
4d270463af 🐛Fix RuntimeError raised when HTTPException has a status code with no content (#5365)
Co-authored-by: Marcelo Trylesinski <marcelotryle@gmail.com>
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2022-09-11 16:13:36 +00:00
github-actions
6620273083 📝 Update release notes 2022-09-08 15:03:37 +00:00
Thomas Meckel
0b4fe10c8f 🐛 Fix empty reponse body when default status_code is empty but the a Response parameter with response.status_code is set (#5360)
Co-authored-by: Thomas Meckel <tmeckel@users.noreply.github.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2022-09-08 15:02:59 +00:00
github-actions
c4007cb9ec 📝 Update release notes 2022-09-08 14:30:00 +00:00
DCsunset
3ec498af63 Add support in jsonable_encoder for include and exclude with dataclasses (#4923)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2022-09-08 16:29:23 +02:00
github-actions
895789bed0 📝 Update release notes 2022-09-08 14:09:15 +00:00
pre-commit-ci[bot]
ef5d6181b6 ⬆ [pre-commit.ci] pre-commit autoupdate (#5352)
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2022-09-08 16:08:33 +02:00
Sebastián Ramírez
3079ba925e 🔖 Release version 0.82.0 2022-09-04 21:26:31 +02:00
Sebastián Ramírez
ddf6daeb07 📝 Update release notes 2022-09-04 21:25:29 +02:00
github-actions
f3efaf69da 📝 Update release notes 2022-09-04 19:10:05 +00:00
Adrian Garcia Badaracco
f8460a8b54 🐛 Allow exit code for dependencies with yield to always execute, by removing capacity limiter for them, to e.g. allow closing DB connections without deadlocks (#5122)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2022-09-04 21:09:24 +02:00
github-actions
d0cc996dc7 📝 Update release notes 2022-09-04 15:17:43 +00:00
github-actions[bot]
c70fab38e7 👥 Update FastAPI People (#5347)
Co-authored-by: github-actions <github-actions@github.com>
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2022-09-04 15:16:00 +00:00
github-actions
80d68a6eda 📝 Update release notes 2022-09-04 15:12:59 +00:00
Mateusz Nowak
dacb689290 Export WebSocketState in fastapi.websockets (#4376) 2022-09-04 17:12:10 +02:00
github-actions
dd2f759bac 📝 Update release notes 2022-09-04 15:07:46 +00:00
Irfanuddin Shafi Ahmed
4cff206ebb 🐛 Fix FastAPI People GitHub Action: set HTTPX timeout for GraphQL query request (#5222)
Co-authored-by: Irfanuddin <irfanuddin@knowledgelens.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2022-09-04 15:07:12 +00:00
github-actions
0195bb5706 📝 Update release notes 2022-09-04 14:57:04 +00:00
baconfield
0ae8d09189 ✏ Update Hypercorn link, now pointing to GitHub (#5346)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2022-09-04 14:56:29 +00:00
github-actions
9df22ab864 📝 Update release notes 2022-09-04 14:28:31 +00:00
Vladislav Kramorenko
81967f8f93 🌐 Add Russian translation for docs/ru/docs/features.md (#5315)
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2022-09-04 16:27:48 +02:00
github-actions
7dd4a4f435 📝 Update release notes 2022-09-04 14:00:36 +00:00
github-actions
94b7527dfd 📝 Update release notes 2022-09-04 14:00:22 +00:00
dependabot[bot]
a3a8d68715 ⬆ Bump dawidd6/action-download-artifact from 2.22.0 to 2.23.0 (#5321)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-09-04 15:59:59 +02:00
pre-commit-ci[bot]
ee035dfa9a ⬆ [pre-commit.ci] pre-commit autoupdate (#5318)
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2022-09-04 15:59:46 +02:00
github-actions
5a79564dab 📝 Update release notes 2022-09-04 13:40:56 +00:00
ASpathfinder
dc1534736d 🌐 Update Chinese translation for docs/zh/docs/tutorial/request-files.md (#4529)
Co-authored-by: KellyAlsa-massive-win <lhz928441818@gmail.com>
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2022-09-04 15:40:14 +02:00
github-actions
fc559b5fcd 📝 Update release notes 2022-09-04 13:39:50 +00:00
Zssaer
0d43b6552b 🌐 Add Chinese translation for docs/zh/docs/tutorial/encoder.md (#4969) 2022-09-04 15:39:06 +02:00
github-actions
89839eb834 📝 Update release notes 2022-09-04 13:38:49 +00:00
Peter Fackeldey
f266dc17d7 ✏ Tweak wording in docs/en/docs/advanced/dataclasses.md (#3698) 2022-09-04 15:37:47 +02:00
github-actions
697ec94a7e 📝 Update release notes 2022-09-04 13:29:46 +00:00
MendyLanda
ae369d879a 📝 Add note about Python 3.10 X | Y operator in explanation about Response Models (#5307) 2022-09-04 15:29:06 +02:00
github-actions
198b7ef2cb 📝 Update release notes 2022-09-04 13:24:23 +00:00
Mário Victor Ribeiro Silva
68e04f6531 🌐 Fix MkDocs file line for Portuguese translation of background-task.md (#5242)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2022-09-04 13:23:34 +00:00
github-actions
c00e1ec6bf 📝 Update release notes 2022-09-04 13:18:44 +00:00
非法操作
d3ff7c620a ✏ Fix a small code highlight line error (#5256) 2022-09-04 15:18:08 +02:00
github-actions
fae28a9bd7 📝 Update release notes 2022-09-04 13:01:40 +00:00
sjyothi54
0e7478d39c 📝 Add link to New Relic article: "How to monitor FastAPI application performance using Python agent" (#5260)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2022-09-04 15:01:08 +02:00
github-actions
dbb43da9c0 📝 Update release notes 2022-09-03 17:13:24 +00:00
Charlie DiGiovanna
56f887de15 🐛 Make sure a parameter defined as required is kept required in OpenAPI even if defined as optional in another dependency (#4319)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2022-09-03 17:12:41 +00:00
github-actions
fbe1a803fc 📝 Update release notes 2022-09-02 13:36:48 +00:00
Junghoon Yang
52b5b08910 ♻ Internal small refactor, move operation_id parameter position in delete method for consistency with the code (#4474)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2022-09-02 13:36:00 +00:00
github-actions
e7e6404faf 📝 Update release notes 2022-09-02 12:44:09 +00:00
Marcelo Trylesinski
30b3905ef3 Support Python internal description on Pydantic model's docstring (#3032)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2022-09-02 14:43:21 +02:00
github-actions
b1d0f1e970 📝 Update release notes 2022-09-02 10:18:09 +00:00
abc.zxy
7250c194da Update ORJSONResponse to support non str keys and serializing Numpy arrays (#3892)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2022-09-02 10:17:31 +00:00
github-actions
173b891603 📝 Update release notes 2022-09-02 09:53:06 +00:00
Sebastián Ramírez
6ae8f07d24 🔧 Update sponsors, disable ImgWhale (#5338) 2022-09-02 09:52:19 +00:00
github-actions
b83709add4 📝 Update release notes 2022-09-01 09:59:45 +00:00
Ben Falk
a71077c530 📝 Update docs for ORJSONResponse with details about improving performance (#2615)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2022-09-01 09:59:05 +00:00
github-actions
278adc012a 📝 Update release notes 2022-09-01 09:33:10 +00:00
Sebastián Ramírez
356a57daa8 📝 Add docs for creating a custom Response class (#5331) 2022-09-01 09:32:30 +00:00
github-actions
b9d7f86743 📝 Update release notes 2022-09-01 09:06:24 +00:00
Sebastián Ramírez
adf4e77dd6 📝 Add tip about using alias for form data fields (#5329) 2022-09-01 09:05:41 +00:00
github-actions
0e1a9d1c0f 📝 Update release notes 2022-09-01 08:51:37 +00:00
David Brochart
d8b6aa630c 🐛 Fix support for path parameters in WebSockets (#3879)
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2022-09-01 10:50:47 +02:00
Sebastián Ramírez
0bb8920ae1 🔖 Release version 0.81.0 2022-08-26 17:18:44 +02:00
Sebastián Ramírez
95c182a42c 📝 Update release notes 2022-08-26 17:17:42 +02:00
github-actions
165d57db24 📝 Update release notes 2022-08-26 14:53:08 +00:00
Ihor Tymkiv
ae5280e501 ✏ Fix a simple typo in docs/en/docs/python-types.md (#5193)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2022-08-26 14:52:23 +00:00
github-actions
d4b2ef8137 📝 Update release notes 2022-08-26 14:46:06 +00:00
impocode
fd2080aece 🌐 Add Russian translation for docs/ru/docs/index.md (#5289) 2022-08-26 16:45:24 +02:00
github-actions
3c8d8c38a7 📝 Update release notes 2022-08-26 14:44:37 +00:00
Artyom Kropp
fa92dbf557 🌐 Add Russian translation for docs/ru/docs/deployment/versions.md (#4985) 2022-08-26 16:43:58 +02:00
github-actions
cd8854c4c7 📝 Update release notes 2022-08-26 14:43:25 +00:00
Bruno Artur Torres Lopes Pereira
b63398f4b5 🌐 Add Portuguese translation for docs/pt/docs/tutorial/header-params.md (#4921)
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2022-08-26 14:42:45 +00:00
github-actions
728b961d35 📝 Update release notes 2022-08-26 14:37:17 +00:00
supraaxdd
5e34cb1868 ✏ Fix typos in tests/test_schema_extra_examples.py (#5126) 2022-08-26 16:36:41 +02:00
github-actions
bbd34c55d5 📝 Update release notes 2022-08-26 14:35:47 +00:00
Roy Hyunjin Han
8a72d363c8 ✏ Fix typos in docs/en/docs/tutorial/path-params-numeric-validations.md (#5142) 2022-08-26 16:35:10 +02:00
github-actions
ee93ad952c 📝 Update release notes 2022-08-26 14:29:03 +00:00
dependabot[bot]
d26674616c ⬆ Bump dawidd6/action-download-artifact from 2.21.1 to 2.22.0 (#5258)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-08-26 16:28:08 +02:00
github-actions
40a19fe261 📝 Update release notes 2022-08-26 14:27:09 +00:00
github-actions
8b4546352f 📝 Update release notes 2022-08-26 14:26:53 +00:00
Edwuin Gutierrez
b3f2f08251 📝 Add step about upgrading pip in the venv to avoid errors when installing dependencies docs/en/docs/contributing.md (#5181)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2022-08-26 14:26:28 +00:00
pre-commit-ci[bot]
3d3a7dbe7e ⬆ [pre-commit.ci] pre-commit autoupdate (#5196)
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2022-08-26 16:26:10 +02:00
github-actions
d69b5f39b4 📝 Update release notes 2022-08-26 14:23:22 +00:00
Pedro Augusto de Paula Barbosa
70213467a6 ✏ Reword and clarify text in tutorial docs/en/docs/tutorial/body-nested-models.md (#5169) 2022-08-26 16:22:36 +02:00
github-actions
8d1d1703f4 📝 Update release notes 2022-08-26 14:21:42 +00:00
Charlie Wilson
1285ba4b2e ✏ Fix minor typo in docs/en/docs/features.md (#5206) 2022-08-26 16:20:57 +02:00
github-actions
6bbfd27c19 📝 Update release notes 2022-08-26 14:11:39 +00:00
github-actions
4c0b9b831c 📝 Update release notes 2022-08-26 14:11:05 +00:00
Burak Kadir Er
9e6dcba766 ✏ Fix minor typos in docs/en/docs/async.md (#5125)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2022-08-26 14:10:53 +00:00
KrishNa
e1825589ba 📝 Add external link to docs: "Fastapi, Docker(Docker compose) and Postgres" (#5033) 2022-08-26 16:10:17 +02:00
github-actions
acc59df815 📝 Update release notes 2022-08-26 14:09:23 +00:00
Seungho Kim
d86b54e79b 🔥 Delete duplicated tests in tests/test_tutorial/test_sql_databases/test_sql_databases.py (#5040) 2022-08-26 16:08:45 +02:00
github-actions
6b77179e3b 📝 Update release notes 2022-08-26 13:57:25 +00:00
github-actions
8dab25df71 📝 Update release notes 2022-08-26 13:56:54 +00:00
Luis R
22bed0008c 🐛 Fix jsonable_encoder for dataclasses with pydantic-compatible fields (#3607)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2022-08-26 15:56:47 +02:00
Erik Vroon
de6ccd7754 Add ReDoc <noscript> warning when JS is disabled (#5074)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2022-08-26 13:56:07 +00:00
github-actions
26c68c6e0d 📝 Update release notes 2022-08-26 13:47:11 +00:00
pylounge
dc10b81d05 ♻ Simplify internal RegEx in fastapi/utils.py (#5057)
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2022-08-26 15:46:22 +02:00
github-actions
1f2070af20 📝 Update release notes 2022-08-26 13:44:50 +00:00
LYK
a95212565a 🌐 Update ko/mkdocs.yml for a missing link (#5020)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2022-08-26 13:44:02 +00:00
github-actions
d80b065b5e 📝 Update release notes 2022-08-26 13:33:08 +00:00
Adrian Garcia Badaracco
dde140d8e3 📝 Simplify example for docs for Additional Responses, remove unnecessary else (#4693) 2022-08-26 15:32:30 +02:00
github-actions
96c3f44a0e 📝 Update release notes 2022-08-26 13:30:28 +00:00
David Kim
0539dd9cd3 🔧 Fix Type hint of auto_error which does not need to be Optional[bool] (#4933) 2022-08-26 15:29:50 +02:00
github-actions
aaf5a380df 📝 Update release notes 2022-08-26 13:27:07 +00:00
Micael Jarniac
e3c055ba8f 📝 Update docs, compare enums with identity instead of equality (#4905) 2022-08-26 15:26:03 +02:00
github-actions
afe44f0b25 📝 Update release notes 2022-08-26 13:25:48 +00:00
Michael Oliver
8cd8aa4b67 🔧 Update mypy config, use strict = true instead of manual configs (#4605)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2022-08-26 15:25:02 +02:00
github-actions
26097421d3 📝 Update release notes 2022-08-26 13:24:42 +00:00
github-actions
3df68694c0 📝 Update release notes 2022-08-26 13:24:10 +00:00
Micael Jarniac
f3e9dcd891 ✏ Fix typo in docs/en/docs/python-types.md (#4886)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2022-08-26 13:24:04 +00:00
Shahriyar Rzayev
00bdf533ef ♻ Change a dict() for {} in fastapi/utils.py (#3138) 2022-08-26 15:23:25 +02:00
github-actions
ae56590c51 📝 Update release notes 2022-08-26 13:17:25 +00:00
github-actions
923e0ac0c1 📝 Update release notes 2022-08-26 13:17:04 +00:00
Guillermo Quintana Pelayo
a64387c3fc ♻ Move internal variable for errors in jsonable_encoder to put related code closer (#4560)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2022-08-26 13:16:44 +00:00
Muzaffer Cikay
c8124496fc ♻ Simplify conditional assignment in fastapi/dependencies/utils.py (#4597)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2022-08-26 13:16:17 +00:00
github-actions
75792eb82b 📝 Update release notes 2022-08-26 13:05:26 +00:00
Joon Hwan 김준환
bb53d0b0ea 🎨 Fix syntax highlighting in docs for OpenAPI Callbacks (#4368)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2022-08-26 15:04:48 +02:00
github-actions
f928f3390c 📝 Update release notes 2022-08-26 09:42:03 +00:00
James Curtin
d5c84594cb ⬆ Upgrade version pin accepted for Flake8, for internal code, to flake8 >=3.8.3,<6.0.0 (#4097)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2022-08-26 11:41:23 +02:00
github-actions
0968329ed7 📝 Update release notes 2022-08-26 09:26:59 +00:00
Ori Levari
880c8b37cf 🐛 Fix support for extending openapi_extras with parameter lists (#4267)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2022-08-26 09:26:20 +00:00
github-actions
92181ef182 📝 Update release notes 2022-08-25 21:53:36 +00:00
juntatalor
ca2fae0588 Add support for FrozenSet in parameters (e.g. query) (#2938)
Co-authored-by: saborisov <borisov_s@tass.ru>
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2022-08-25 23:52:53 +02:00
github-actions
af3a6ef78b 📝 Update release notes 2022-08-25 21:45:33 +00:00
Andy Challis
eb3ab337ab Allow custom middlewares to raise HTTPExceptions and propagate them (#2036)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2022-08-25 23:44:40 +02:00
github-actions
5215b39d50 📝 Update release notes 2022-08-25 09:56:40 +00:00
Sidharth Ajithkumar
9359a8d65f Preserve json.JSONDecodeError information when handling invalid JSON in request body, to support custom exception handlers that use its information (#4057)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2022-08-25 11:55:53 +02:00
github-actions
afaa0391a5 📝 Update release notes 2022-08-24 21:36:15 +00:00
Caleb Renfroe
438656395a ✏ Reword confusing sentence in docs file typo-fix-path-params-numeric-validations.md (#3219)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2022-08-24 21:35:30 +00:00
github-actions
39319a7ede 📝 Update release notes 2022-08-24 14:54:27 +00:00
Kevin Tewouda
8c6ad35615 📝 Update docs for handling HTTP Basic Auth with secrets.compare_digest() to account for non-ASCII characters (#3536)
Co-authored-by: le_woudar <kevin.tewouda@gandi.net>
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2022-08-24 16:53:43 +02:00
github-actions
f90465f5b4 📝 Update release notes 2022-08-24 14:18:57 +00:00
Sebastián Ramírez
1835b3f76d 📝 Update docs for testing, fix examples with relative imports (#5302) 2022-08-24 16:18:11 +02:00
github-actions
2201f29be3 📝 Update release notes 2022-08-24 08:44:22 +00:00
Sebastián Ramírez
68f25120c5 🍱 Update Jina banner, fix typo (#5301) 2022-08-24 08:43:44 +00:00
618 changed files with 37263 additions and 2981 deletions

View File

@@ -1,5 +0,0 @@
[flake8]
max-line-length = 88
select = C,E,F,W,B,B9
ignore = E203, E501, W503
exclude = __init__.py

View File

@@ -1,5 +1,3 @@
name: Question or Problem
description: Ask a question or ask about a problem
labels: [question]
body:
- type: markdown
@@ -9,9 +7,9 @@ body:
Please follow these instructions, fill every question, and do every step. 🙏
I'm asking this because answering questions and solving problems in GitHub issues is what consumes most of the time.
I'm asking this because answering questions and solving problems in GitHub is what consumes most of the time.
I end up not being able to add new features, fix bugs, review pull requests, etc. as fast as I wish because I have to spend too much time handling issues.
I end up not being able to add new features, fix bugs, review pull requests, etc. as fast as I wish because I have to spend too much time handling questions.
All that, on top of all the incredible help provided by a bunch of community members, the [FastAPI Experts](https://fastapi.tiangolo.com/fastapi-people/#experts), that give a lot of their time to come here and help others.
@@ -21,16 +19,16 @@ body:
And there's a high chance that you will find the solution along the way and you won't even have to submit it and wait for an answer. 😎
As there are too many issues with questions, I'll have to close the incomplete ones. That will allow me (and others) to focus on helping people like you that follow the whole process and help us help you. 🤓
As there are too many questions, I'll have to discard and close the incomplete ones. That will allow me (and others) to focus on helping people like you that follow the whole process and help us help you. 🤓
- type: checkboxes
id: checks
attributes:
label: First Check
description: Please confirm and check all the following options.
options:
- label: I added a very descriptive title to this issue.
- label: I added a very descriptive title here.
required: true
- label: I used the GitHub search to find a similar issue and didn't find it.
- label: I used the GitHub search to find a similar question and didn't find it.
required: true
- label: I searched the FastAPI documentation, with the integrated search.
required: true
@@ -38,7 +36,7 @@ body:
required: true
- label: I already read and followed all the tutorial in the docs and didn't find an answer.
required: true
- label: I already checked if it is not related to FastAPI but to [Pydantic](https://github.com/samuelcolvin/pydantic).
- label: I already checked if it is not related to FastAPI but to [Pydantic](https://github.com/pydantic/pydantic).
required: true
- label: I already checked if it is not related to FastAPI but to [Swagger UI](https://github.com/swagger-api/swagger-ui).
required: true
@@ -51,9 +49,9 @@ body:
description: |
After submitting this, I commit to one of:
* Read open issues with questions until I find 2 issues where I can help someone and add a comment to help there.
* Read open questions until I find 2 where I can help someone and add a comment to help there.
* I already hit the "watch" button in this repository to receive notifications and I commit to help at least 2 people that ask questions in the future.
* Implement a Pull Request for a confirmed bug.
* Review one Pull Request by downloading the code and following [all the review process](https://fastapi.tiangolo.com/help-fastapi/#review-pull-requests).
options:
- label: I commit to help with one of those options 👆

View File

@@ -2,3 +2,15 @@ blank_issues_enabled: false
contact_links:
- name: Security Contact
about: Please report security vulnerabilities to security@tiangolo.com
- name: Question or Problem
about: Ask a question or ask about a problem in GitHub Discussions.
url: https://github.com/tiangolo/fastapi/discussions/categories/questions
- name: Feature Request
about: To suggest an idea or ask about a feature, please start with a question saying what you would like to achieve. There might be a way to do it already.
url: https://github.com/tiangolo/fastapi/discussions/categories/questions
- name: Show and tell
about: Show what you built with FastAPI or to be used with FastAPI.
url: https://github.com/tiangolo/fastapi/discussions/categories/show-and-tell
- name: Translations
about: Coordinate translations in GitHub Discussions.
url: https://github.com/tiangolo/fastapi/discussions/categories/translations

View File

@@ -1,181 +0,0 @@
name: Feature Request
description: Suggest an idea or ask for a feature that you would like to have in FastAPI
labels: [enhancement]
body:
- type: markdown
attributes:
value: |
Thanks for your interest in FastAPI! 🚀
Please follow these instructions, fill every question, and do every step. 🙏
I'm asking this because answering questions and solving problems in GitHub issues is what consumes most of the time.
I end up not being able to add new features, fix bugs, review pull requests, etc. as fast as I wish because I have to spend too much time handling issues.
All that, on top of all the incredible help provided by a bunch of community members, the [FastAPI Experts](https://fastapi.tiangolo.com/fastapi-people/#experts), that give a lot of their time to come here and help others.
That's a lot of work they are doing, but if more FastAPI users came to help others like them just a little bit more, it would be much less effort for them (and you and me 😅).
By asking questions in a structured way (following this) it will be much easier to help you.
And there's a high chance that you will find the solution along the way and you won't even have to submit it and wait for an answer. 😎
As there are too many issues with questions, I'll have to close the incomplete ones. That will allow me (and others) to focus on helping people like you that follow the whole process and help us help you. 🤓
- type: checkboxes
id: checks
attributes:
label: First Check
description: Please confirm and check all the following options.
options:
- label: I added a very descriptive title to this issue.
required: true
- label: I used the GitHub search to find a similar issue and didn't find it.
required: true
- label: I searched the FastAPI documentation, with the integrated search.
required: true
- label: I already searched in Google "How to X in FastAPI" and didn't find any information.
required: true
- label: I already read and followed all the tutorial in the docs and didn't find an answer.
required: true
- label: I already checked if it is not related to FastAPI but to [Pydantic](https://github.com/samuelcolvin/pydantic).
required: true
- label: I already checked if it is not related to FastAPI but to [Swagger UI](https://github.com/swagger-api/swagger-ui).
required: true
- label: I already checked if it is not related to FastAPI but to [ReDoc](https://github.com/Redocly/redoc).
required: true
- type: checkboxes
id: help
attributes:
label: Commit to Help
description: |
After submitting this, I commit to one of:
* Read open issues with questions until I find 2 issues where I can help someone and add a comment to help there.
* I already hit the "watch" button in this repository to receive notifications and I commit to help at least 2 people that ask questions in the future.
* Implement a Pull Request for a confirmed bug.
options:
- label: I commit to help with one of those options 👆
required: true
- type: textarea
id: example
attributes:
label: Example Code
description: |
Please add a self-contained, [minimal, reproducible, example](https://stackoverflow.com/help/minimal-reproducible-example) with your use case.
If I (or someone) can copy it, run it, and see it right away, there's a much higher chance I (or someone) will be able to help you.
placeholder: |
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def read_root():
return {"Hello": "World"}
render: python
validations:
required: true
- type: textarea
id: description
attributes:
label: Description
description: |
What is your feature request?
Write a short description telling me what you are trying to solve and what you are currently doing.
placeholder: |
* Open the browser and call the endpoint `/`.
* It returns a JSON with `{"Hello": "World"}`.
* I would like it to have an extra parameter to teleport me to the moon and back.
validations:
required: true
- type: textarea
id: wanted-solution
attributes:
label: Wanted Solution
description: |
Tell me what's the solution you would like.
placeholder: |
I would like it to have a `teleport_to_moon` parameter that defaults to `False`, and can be set to `True` to teleport me.
validations:
required: true
- type: textarea
id: wanted-code
attributes:
label: Wanted Code
description: Show me an example of how you would want the code to look like.
placeholder: |
from fastapi import FastAPI
app = FastAPI()
@app.get("/", teleport_to_moon=True)
def read_root():
return {"Hello": "World"}
render: python
validations:
required: true
- type: textarea
id: alternatives
attributes:
label: Alternatives
description: |
Tell me about alternatives you've considered.
placeholder: |
To wait for Space X moon travel plans to drop down long after they release them. But I would rather teleport.
- type: dropdown
id: os
attributes:
label: Operating System
description: What operating system are you on?
multiple: true
options:
- Linux
- Windows
- macOS
- Other
validations:
required: true
- type: textarea
id: os-details
attributes:
label: Operating System Details
description: You can add more details about your operating system here, in particular if you chose "Other".
- type: input
id: fastapi-version
attributes:
label: FastAPI Version
description: |
What FastAPI version are you using?
You can find the FastAPI version with:
```bash
python -c "import fastapi; print(fastapi.__version__)"
```
validations:
required: true
- type: input
id: python-version
attributes:
label: Python Version
description: |
What Python version are you using?
You can find the Python version with:
```bash
python --version
```
validations:
required: true
- type: textarea
id: context
attributes:
label: Additional Context
description: Add any additional context information or screenshots you think are useful.

22
.github/ISSUE_TEMPLATE/privileged.yml vendored Normal file
View File

@@ -0,0 +1,22 @@
name: Privileged
description: You are @tiangolo or he asked you directly to create an issue here. If not, check the other options. 👇
body:
- type: markdown
attributes:
value: |
Thanks for your interest in FastAPI! 🚀
If you are not @tiangolo or he didn't ask you directly to create an issue here, please start the conversation in a [Question in GitHub Discussions](https://github.com/tiangolo/fastapi/discussions/categories/questions) instead.
- type: checkboxes
id: privileged
attributes:
label: Privileged issue
description: Confirm that you are allowed to create an issue here.
options:
- label: I'm @tiangolo or he asked me directly to create an issue here.
required: true
- type: textarea
id: content
attributes:
label: Issue Content
description: Add the content of the issue here.

View File

@@ -1,10 +1,11 @@
import logging
import random
import sys
import time
from pathlib import Path
from typing import Dict, Union
from typing import Any, Dict, List, Union, cast
import yaml
import httpx
from github import Github
from pydantic import BaseModel, BaseSettings, SecretStr
@@ -13,12 +14,172 @@ lang_all_label = "lang-all"
approved_label = "approved-2"
translations_path = Path(__file__).parent / "translations.yml"
github_graphql_url = "https://api.github.com/graphql"
questions_translations_category_id = "DIC_kwDOCZduT84CT5P9"
all_discussions_query = """
query Q($category_id: ID) {
repository(name: "fastapi", owner: "tiangolo") {
discussions(categoryId: $category_id, first: 100) {
nodes {
title
id
number
labels(first: 10) {
edges {
node {
id
name
}
}
}
}
}
}
}
"""
translation_discussion_query = """
query Q($after: String, $discussion_number: Int!) {
repository(name: "fastapi", owner: "tiangolo") {
discussion(number: $discussion_number) {
comments(first: 100, after: $after) {
edges {
cursor
node {
id
url
body
}
}
}
}
}
}
"""
add_comment_mutation = """
mutation Q($discussion_id: ID!, $body: String!) {
addDiscussionComment(input: {discussionId: $discussion_id, body: $body}) {
comment {
id
url
body
}
}
}
"""
update_comment_mutation = """
mutation Q($comment_id: ID!, $body: String!) {
updateDiscussionComment(input: {commentId: $comment_id, body: $body}) {
comment {
id
url
body
}
}
}
"""
class Comment(BaseModel):
id: str
url: str
body: str
class UpdateDiscussionComment(BaseModel):
comment: Comment
class UpdateCommentData(BaseModel):
updateDiscussionComment: UpdateDiscussionComment
class UpdateCommentResponse(BaseModel):
data: UpdateCommentData
class AddDiscussionComment(BaseModel):
comment: Comment
class AddCommentData(BaseModel):
addDiscussionComment: AddDiscussionComment
class AddCommentResponse(BaseModel):
data: AddCommentData
class CommentsEdge(BaseModel):
node: Comment
cursor: str
class Comments(BaseModel):
edges: List[CommentsEdge]
class CommentsDiscussion(BaseModel):
comments: Comments
class CommentsRepository(BaseModel):
discussion: CommentsDiscussion
class CommentsData(BaseModel):
repository: CommentsRepository
class CommentsResponse(BaseModel):
data: CommentsData
class AllDiscussionsLabelNode(BaseModel):
id: str
name: str
class AllDiscussionsLabelsEdge(BaseModel):
node: AllDiscussionsLabelNode
class AllDiscussionsDiscussionLabels(BaseModel):
edges: List[AllDiscussionsLabelsEdge]
class AllDiscussionsDiscussionNode(BaseModel):
title: str
id: str
number: int
labels: AllDiscussionsDiscussionLabels
class AllDiscussionsDiscussions(BaseModel):
nodes: List[AllDiscussionsDiscussionNode]
class AllDiscussionsRepository(BaseModel):
discussions: AllDiscussionsDiscussions
class AllDiscussionsData(BaseModel):
repository: AllDiscussionsRepository
class AllDiscussionsResponse(BaseModel):
data: AllDiscussionsData
class Settings(BaseSettings):
github_repository: str
input_token: SecretStr
github_event_path: Path
github_event_name: Union[str, None] = None
httpx_timeout: int = 30
input_debug: Union[bool, None] = False
@@ -30,6 +191,113 @@ class PartialGitHubEvent(BaseModel):
pull_request: PartialGitHubEventIssue
def get_graphql_response(
*,
settings: Settings,
query: str,
after: Union[str, None] = None,
category_id: Union[str, None] = None,
discussion_number: Union[int, None] = None,
discussion_id: Union[str, None] = None,
comment_id: Union[str, None] = None,
body: Union[str, None] = None,
) -> Dict[str, Any]:
headers = {"Authorization": f"token {settings.input_token.get_secret_value()}"}
# some fields are only used by one query, but GraphQL allows unused variables, so
# keep them here for simplicity
variables = {
"after": after,
"category_id": category_id,
"discussion_number": discussion_number,
"discussion_id": discussion_id,
"comment_id": comment_id,
"body": body,
}
response = httpx.post(
github_graphql_url,
headers=headers,
timeout=settings.httpx_timeout,
json={"query": query, "variables": variables, "operationName": "Q"},
)
if response.status_code != 200:
logging.error(
f"Response was not 200, after: {after}, category_id: {category_id}"
)
logging.error(response.text)
raise RuntimeError(response.text)
data = response.json()
if "errors" in data:
logging.error(f"Errors in response, after: {after}, category_id: {category_id}")
logging.error(response.text)
raise RuntimeError(response.text)
return cast(Dict[str, Any], data)
def get_graphql_translation_discussions(*, settings: Settings):
data = get_graphql_response(
settings=settings,
query=all_discussions_query,
category_id=questions_translations_category_id,
)
graphql_response = AllDiscussionsResponse.parse_obj(data)
return graphql_response.data.repository.discussions.nodes
def get_graphql_translation_discussion_comments_edges(
*, settings: Settings, discussion_number: int, after: Union[str, None] = None
):
data = get_graphql_response(
settings=settings,
query=translation_discussion_query,
discussion_number=discussion_number,
after=after,
)
graphql_response = CommentsResponse.parse_obj(data)
return graphql_response.data.repository.discussion.comments.edges
def get_graphql_translation_discussion_comments(
*, settings: Settings, discussion_number: int
):
comment_nodes: List[Comment] = []
discussion_edges = get_graphql_translation_discussion_comments_edges(
settings=settings, discussion_number=discussion_number
)
while discussion_edges:
for discussion_edge in discussion_edges:
comment_nodes.append(discussion_edge.node)
last_edge = discussion_edges[-1]
discussion_edges = get_graphql_translation_discussion_comments_edges(
settings=settings,
discussion_number=discussion_number,
after=last_edge.cursor,
)
return comment_nodes
def create_comment(*, settings: Settings, discussion_id: str, body: str):
data = get_graphql_response(
settings=settings,
query=add_comment_mutation,
discussion_id=discussion_id,
body=body,
)
response = AddCommentResponse.parse_obj(data)
return response.data.addDiscussionComment.comment
def update_comment(*, settings: Settings, comment_id: str, body: str):
data = get_graphql_response(
settings=settings,
query=update_comment_mutation,
comment_id=comment_id,
body=body,
)
response = UpdateCommentResponse.parse_obj(data)
return response.data.updateDiscussionComment.comment
if __name__ == "__main__":
settings = Settings()
if settings.input_debug:
@@ -45,60 +313,105 @@ if __name__ == "__main__":
)
contents = settings.github_event_path.read_text()
github_event = PartialGitHubEvent.parse_raw(contents)
translations_map: Dict[str, int] = yaml.safe_load(translations_path.read_text())
logging.debug(f"Using translations map: {translations_map}")
# Avoid race conditions with multiple labels
sleep_time = random.random() * 10 # random number between 0 and 10 seconds
pr = repo.get_pull(github_event.pull_request.number)
logging.debug(
f"Processing PR: {pr.number}, with anti-race condition sleep time: {sleep_time}"
logging.info(
f"Sleeping for {sleep_time} seconds to avoid "
"race conditions and multiple comments"
)
if pr.state == "open":
logging.debug(f"PR is open: {pr.number}")
label_strs = {label.name for label in pr.get_labels()}
if lang_all_label in label_strs and awaiting_label in label_strs:
logging.info(
f"This PR seems to be a language translation and awaiting reviews: {pr.number}"
)
if approved_label in label_strs:
message = (
f"It seems this PR already has the approved label: {pr.number}"
)
logging.error(message)
raise RuntimeError(message)
langs = []
for label in label_strs:
if label.startswith("lang-") and not label == lang_all_label:
langs.append(label[5:])
for lang in langs:
if lang in translations_map:
num = translations_map[lang]
logging.info(
f"Found a translation issue for language: {lang} in issue: {num}"
)
issue = repo.get_issue(num)
message = f"Good news everyone! 😉 There's a new translation PR to be reviewed: #{pr.number} 🎉"
already_notified = False
time.sleep(sleep_time)
logging.info(
f"Sleeping for {sleep_time} seconds to avoid race conditions and multiple comments"
)
logging.info(
f"Checking current comments in issue: {num} to see if already notified about this PR: {pr.number}"
)
for comment in issue.get_comments():
if message in comment.body:
already_notified = True
if not already_notified:
logging.info(
f"Writing comment in issue: {num} about PR: {pr.number}"
)
issue.create_comment(message)
else:
logging.info(
f"Issue: {num} was already notified of PR: {pr.number}"
)
else:
time.sleep(sleep_time)
# Get PR
logging.debug(f"Processing PR: #{github_event.pull_request.number}")
pr = repo.get_pull(github_event.pull_request.number)
label_strs = {label.name for label in pr.get_labels()}
langs = []
for label in label_strs:
if label.startswith("lang-") and not label == lang_all_label:
langs.append(label[5:])
logging.info(f"PR #{pr.number} has labels: {label_strs}")
if not langs or lang_all_label not in label_strs:
logging.info(f"PR #{pr.number} doesn't seem to be a translation PR, skipping")
sys.exit(0)
# Generate translation map, lang ID to discussion
discussions = get_graphql_translation_discussions(settings=settings)
lang_to_discussion_map: Dict[str, AllDiscussionsDiscussionNode] = {}
for discussion in discussions:
for edge in discussion.labels.edges:
label = edge.node.name
if label.startswith("lang-") and not label == lang_all_label:
lang = label[5:]
lang_to_discussion_map[lang] = discussion
logging.debug(f"Using translations map: {lang_to_discussion_map}")
# Messages to create or check
new_translation_message = f"Good news everyone! 😉 There's a new translation PR to be reviewed: #{pr.number} by @{pr.user.login}. 🎉 This requires 2 approvals from native speakers to be merged. 🤓"
done_translation_message = f"~There's a new translation PR to be reviewed: #{pr.number} by @{pr.user.login}~ Good job! This is done. 🍰☕"
# Normally only one language, but still
for lang in langs:
if lang not in lang_to_discussion_map:
log_message = f"Could not find discussion for language: {lang}"
logging.error(log_message)
raise RuntimeError(log_message)
discussion = lang_to_discussion_map[lang]
logging.info(
f"Changing labels in a closed PR doesn't trigger comments, PR: {pr.number}"
f"Found a translation discussion for language: {lang} in discussion: #{discussion.number}"
)
already_notified_comment: Union[Comment, None] = None
already_done_comment: Union[Comment, None] = None
logging.info(
f"Checking current comments in discussion: #{discussion.number} to see if already notified about this PR: #{pr.number}"
)
comments = get_graphql_translation_discussion_comments(
settings=settings, discussion_number=discussion.number
)
for comment in comments:
if new_translation_message in comment.body:
already_notified_comment = comment
elif done_translation_message in comment.body:
already_done_comment = comment
logging.info(
f"Already notified comment: {already_notified_comment}, already done comment: {already_done_comment}"
)
if pr.state == "open" and awaiting_label in label_strs:
logging.info(
f"This PR seems to be a language translation and awaiting reviews: #{pr.number}"
)
if already_notified_comment:
logging.info(
f"This PR #{pr.number} was already notified in comment: {already_notified_comment.url}"
)
else:
logging.info(
f"Writing notification comment about PR #{pr.number} in Discussion: #{discussion.number}"
)
comment = create_comment(
settings=settings,
discussion_id=discussion.id,
body=new_translation_message,
)
logging.info(f"Notified in comment: {comment.url}")
elif pr.state == "closed" or approved_label in label_strs:
logging.info(f"Already approved or closed PR #{pr.number}")
if already_done_comment:
logging.info(
f"This PR #{pr.number} was already marked as done in comment: {already_done_comment.url}"
)
elif already_notified_comment:
updated_comment = update_comment(
settings=settings,
comment_id=already_notified_comment.id,
body=done_translation_message,
)
logging.info(f"Marked as done in comment: {updated_comment.url}")
else:
logging.info(
f"There doesn't seem to be anything to be done about PR #{pr.number}"
)
logging.info("Finished")

View File

@@ -1,19 +0,0 @@
pt: 1211
es: 1218
zh: 1228
ru: 1362
it: 1556
ja: 1572
uk: 1748
tr: 1892
fr: 1972
ko: 2017
fa: 2041
pl: 3169
de: 3716
id: 3717
az: 3994
nl: 4701
uz: 4883
sv: 5146
he: 5157

View File

@@ -4,7 +4,7 @@ import sys
from collections import Counter, defaultdict
from datetime import datetime, timedelta, timezone
from pathlib import Path
from typing import Container, DefaultDict, Dict, List, Set, Union
from typing import Any, Container, DefaultDict, Dict, List, Set, Union
import httpx
import yaml
@@ -12,6 +12,50 @@ from github import Github
from pydantic import BaseModel, BaseSettings, SecretStr
github_graphql_url = "https://api.github.com/graphql"
questions_category_id = "MDE4OkRpc2N1c3Npb25DYXRlZ29yeTMyMDAxNDM0"
discussions_query = """
query Q($after: String, $category_id: ID) {
repository(name: "fastapi", owner: "tiangolo") {
discussions(first: 100, after: $after, categoryId: $category_id) {
edges {
cursor
node {
number
author {
login
avatarUrl
url
}
title
createdAt
comments(first: 100) {
nodes {
createdAt
author {
login
avatarUrl
url
}
isAnswer
replies(first: 10) {
nodes {
createdAt
author {
login
avatarUrl
url
}
}
}
}
}
}
}
}
}
}
"""
issues_query = """
query Q($after: String) {
@@ -131,15 +175,30 @@ class Author(BaseModel):
url: str
# Issues and Discussions
class CommentsNode(BaseModel):
createdAt: datetime
author: Union[Author, None] = None
class Replies(BaseModel):
nodes: List[CommentsNode]
class DiscussionsCommentsNode(CommentsNode):
replies: Replies
class Comments(BaseModel):
nodes: List[CommentsNode]
class DiscussionsComments(BaseModel):
nodes: List[DiscussionsCommentsNode]
class IssuesNode(BaseModel):
number: int
author: Union[Author, None] = None
@@ -149,27 +208,59 @@ class IssuesNode(BaseModel):
comments: Comments
class DiscussionsNode(BaseModel):
number: int
author: Union[Author, None] = None
title: str
createdAt: datetime
comments: DiscussionsComments
class IssuesEdge(BaseModel):
cursor: str
node: IssuesNode
class DiscussionsEdge(BaseModel):
cursor: str
node: DiscussionsNode
class Issues(BaseModel):
edges: List[IssuesEdge]
class Discussions(BaseModel):
edges: List[DiscussionsEdge]
class IssuesRepository(BaseModel):
issues: Issues
class DiscussionsRepository(BaseModel):
discussions: Discussions
class IssuesResponseData(BaseModel):
repository: IssuesRepository
class DiscussionsResponseData(BaseModel):
repository: DiscussionsRepository
class IssuesResponse(BaseModel):
data: IssuesResponseData
class DiscussionsResponse(BaseModel):
data: DiscussionsResponseData
# PRs
class LabelNode(BaseModel):
name: str
@@ -219,6 +310,9 @@ class PRsResponse(BaseModel):
data: PRsResponseData
# Sponsors
class SponsorEntity(BaseModel):
login: str
avatarUrl: str
@@ -260,23 +354,37 @@ class Settings(BaseSettings):
input_token: SecretStr
input_standard_token: SecretStr
github_repository: str
httpx_timeout: int = 30
def get_graphql_response(
*, settings: Settings, query: str, after: Union[str, None] = None
):
*,
settings: Settings,
query: str,
after: Union[str, None] = None,
category_id: Union[str, None] = None,
) -> Dict[str, Any]:
headers = {"Authorization": f"token {settings.input_token.get_secret_value()}"}
variables = {"after": after}
# category_id is only used by one query, but GraphQL allows unused variables, so
# keep it here for simplicity
variables = {"after": after, "category_id": category_id}
response = httpx.post(
github_graphql_url,
headers=headers,
timeout=settings.httpx_timeout,
json={"query": query, "variables": variables, "operationName": "Q"},
)
if not response.status_code == 200:
logging.error(f"Response was not 200, after: {after}")
if response.status_code != 200:
logging.error(
f"Response was not 200, after: {after}, category_id: {category_id}"
)
logging.error(response.text)
raise RuntimeError(response.text)
data = response.json()
if "errors" in data:
logging.error(f"Errors in response, after: {after}, category_id: {category_id}")
logging.error(response.text)
raise RuntimeError(response.text)
return data
@@ -286,6 +394,21 @@ def get_graphql_issue_edges(*, settings: Settings, after: Union[str, None] = Non
return graphql_response.data.repository.issues.edges
def get_graphql_question_discussion_edges(
*,
settings: Settings,
after: Union[str, None] = None,
):
data = get_graphql_response(
settings=settings,
query=discussions_query,
after=after,
category_id=questions_category_id,
)
graphql_response = DiscussionsResponse.parse_obj(data)
return graphql_response.data.repository.discussions.edges
def get_graphql_pr_edges(*, settings: Settings, after: Union[str, None] = None):
data = get_graphql_response(settings=settings, query=prs_query, after=after)
graphql_response = PRsResponse.parse_obj(data)
@@ -298,7 +421,7 @@ def get_graphql_sponsor_edges(*, settings: Settings, after: Union[str, None] = N
return graphql_response.data.user.sponsorshipsAsMaintainer.edges
def get_experts(settings: Settings):
def get_issues_experts(settings: Settings):
issue_nodes: List[IssuesNode] = []
issue_edges = get_graphql_issue_edges(settings=settings)
@@ -324,13 +447,78 @@ def get_experts(settings: Settings):
for comment in issue.comments.nodes:
if comment.author:
authors[comment.author.login] = comment.author
if comment.author.login == issue_author_name:
continue
issue_commentors.add(comment.author.login)
if comment.author.login != issue_author_name:
issue_commentors.add(comment.author.login)
for author_name in issue_commentors:
commentors[author_name] += 1
if issue.createdAt > one_month_ago:
last_month_commentors[author_name] += 1
return commentors, last_month_commentors, authors
def get_discussions_experts(settings: Settings):
discussion_nodes: List[DiscussionsNode] = []
discussion_edges = get_graphql_question_discussion_edges(settings=settings)
while discussion_edges:
for discussion_edge in discussion_edges:
discussion_nodes.append(discussion_edge.node)
last_edge = discussion_edges[-1]
discussion_edges = get_graphql_question_discussion_edges(
settings=settings, after=last_edge.cursor
)
commentors = Counter()
last_month_commentors = Counter()
authors: Dict[str, Author] = {}
now = datetime.now(tz=timezone.utc)
one_month_ago = now - timedelta(days=30)
for discussion in discussion_nodes:
discussion_author_name = None
if discussion.author:
authors[discussion.author.login] = discussion.author
discussion_author_name = discussion.author.login
discussion_commentors = set()
for comment in discussion.comments.nodes:
if comment.author:
authors[comment.author.login] = comment.author
if comment.author.login != discussion_author_name:
discussion_commentors.add(comment.author.login)
for reply in comment.replies.nodes:
if reply.author:
authors[reply.author.login] = reply.author
if reply.author.login != discussion_author_name:
discussion_commentors.add(reply.author.login)
for author_name in discussion_commentors:
commentors[author_name] += 1
if discussion.createdAt > one_month_ago:
last_month_commentors[author_name] += 1
return commentors, last_month_commentors, authors
def get_experts(settings: Settings):
# Migrated to only use GitHub Discussions
# (
# issues_commentors,
# issues_last_month_commentors,
# issues_authors,
# ) = get_issues_experts(settings=settings)
(
discussions_commentors,
discussions_last_month_commentors,
discussions_authors,
) = get_discussions_experts(settings=settings)
# commentors = issues_commentors + discussions_commentors
commentors = discussions_commentors
# last_month_commentors = (
# issues_last_month_commentors + discussions_last_month_commentors
# )
last_month_commentors = discussions_last_month_commentors
# authors = {**issues_authors, **discussions_authors}
authors = {**discussions_authors}
return commentors, last_month_commentors, authors
@@ -423,22 +611,22 @@ if __name__ == "__main__":
logging.info(f"Using config: {settings.json()}")
g = Github(settings.input_standard_token.get_secret_value())
repo = g.get_repo(settings.github_repository)
issue_commentors, issue_last_month_commentors, issue_authors = get_experts(
question_commentors, question_last_month_commentors, question_authors = get_experts(
settings=settings
)
contributors, pr_commentors, reviewers, pr_authors = get_contributors(
settings=settings
)
authors = {**issue_authors, **pr_authors}
authors = {**question_authors, **pr_authors}
maintainers_logins = {"tiangolo"}
bot_names = {"codecov", "github-actions"}
bot_names = {"codecov", "github-actions", "pre-commit-ci", "dependabot"}
maintainers = []
for login in maintainers_logins:
user = authors[login]
maintainers.append(
{
"login": login,
"answers": issue_commentors[login],
"answers": question_commentors[login],
"prs": contributors[login],
"avatarUrl": user.avatarUrl,
"url": user.url,
@@ -451,13 +639,13 @@ if __name__ == "__main__":
min_count_reviewer = 4
skip_users = maintainers_logins | bot_names
experts = get_top_users(
counter=issue_commentors,
counter=question_commentors,
min_count=min_count_expert,
authors=authors,
skip_users=skip_users,
)
last_month_active = get_top_users(
counter=issue_last_month_commentors,
counter=question_last_month_commentors,
min_count=min_count_last_month,
authors=authors,
skip_users=skip_users,

View File

@@ -7,7 +7,7 @@ on:
types: [opened, synchronize]
jobs:
build-docs:
runs-on: ubuntu-18.04
runs-on: ubuntu-latest
steps:
- name: Dump GitHub context
env:
@@ -17,31 +17,28 @@ jobs:
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: "3.7"
python-version: "3.11"
- uses: actions/cache@v3
id: cache
with:
path: ${{ env.pythonLocation }}
key: ${{ runner.os }}-python-docs-${{ env.pythonLocation }}-${{ hashFiles('pyproject.toml') }}-v03
- name: Install Flit
if: steps.cache.outputs.cache-hit != 'true'
run: python3.7 -m pip install flit
- name: Install docs extras
if: steps.cache.outputs.cache-hit != 'true'
run: python3.7 -m flit install --deps production --extras doc
run: pip install .[doc]
- name: Install Material for MkDocs Insiders
if: ( github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork == false ) && steps.cache.outputs.cache-hit != 'true'
run: pip install git+https://${{ secrets.ACTIONS_TOKEN }}@github.com/squidfunk/mkdocs-material-insiders.git
- name: Build Docs
run: python3.7 ./scripts/docs.py build-all
run: python ./scripts/docs.py build-all
- name: Zip docs
run: bash ./scripts/zip-docs.sh
- uses: actions/upload-artifact@v3
with:
name: docs-zip
path: ./docs.zip
path: ./site/docs.zip
- name: Deploy to Netlify
uses: nwtgck/actions-netlify@v1.2.3
uses: nwtgck/actions-netlify@v2.0.0
with:
publish-dir: './site'
production-branch: master

View File

@@ -4,6 +4,7 @@ on:
pull_request_target:
types:
- labeled
- closed
jobs:
notify-translations:

View File

@@ -15,6 +15,9 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
# Ref: https://github.com/actions/runner/issues/2033
- name: Fix git safe.directory in container
run: mkdir -p /home/runner/work/_temp/_github_home && printf "[safe]\n\tdirectory = /github/workspace" > /home/runner/work/_temp/_github_home/.gitconfig
# Allow debugging with tmate
- name: Setup tmate session
uses: mxschmitt/action-tmate@v3

View File

@@ -11,21 +11,26 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Clean site
run: |
rm -rf ./site
mkdir ./site
- name: Download Artifact Docs
uses: dawidd6/action-download-artifact@v2.21.1
uses: dawidd6/action-download-artifact@v2.26.0
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
workflow: build-docs.yml
run_id: ${{ github.event.workflow_run.id }}
name: docs-zip
path: ./site/
- name: Unzip docs
run: |
rm -rf ./site
cd ./site
unzip docs.zip
rm -f docs.zip
- name: Deploy to Netlify
id: netlify
uses: nwtgck/actions-netlify@v1.2.3
uses: nwtgck/actions-netlify@v2.0.0
with:
publish-dir: './site'
production-deploy: false

View File

@@ -17,23 +17,23 @@ jobs:
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: "3.6"
python-version: "3.7"
cache: "pip"
cache-dependency-path: pyproject.toml
- uses: actions/cache@v3
id: cache
with:
path: ${{ env.pythonLocation }}
key: ${{ runner.os }}-python-${{ env.pythonLocation }}-${{ hashFiles('pyproject.toml') }}-publish
- name: Install Flit
- name: Install build dependencies
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
run: pip install build
- name: Build distribution
run: python -m build
- name: Publish
env:
FLIT_USERNAME: ${{ secrets.FLIT_USERNAME }}
FLIT_PASSWORD: ${{ secrets.FLIT_PASSWORD }}
run: bash scripts/publish.sh
uses: pypa/gh-action-pypi-publish@v1.6.4
with:
password: ${{ secrets.PYPI_API_TOKEN }}
- name: Dump GitHub context
env:
GITHUB_CONTEXT: ${{ toJson(github) }}

35
.github/workflows/smokeshow.yml vendored Normal file
View File

@@ -0,0 +1,35 @@
name: Smokeshow
on:
workflow_run:
workflows: [Test]
types: [completed]
permissions:
statuses: write
jobs:
smokeshow:
if: ${{ github.event.workflow_run.conclusion == 'success' }}
runs-on: ubuntu-latest
steps:
- uses: actions/setup-python@v4
with:
python-version: '3.9'
- run: pip install smokeshow
- uses: dawidd6/action-download-artifact@v2.26.0
with:
workflow: test.yml
commit: ${{ github.event.workflow_run.head_sha }}
- run: smokeshow upload coverage-html
env:
SMOKESHOW_GITHUB_STATUS_DESCRIPTION: Coverage {coverage-percentage}
SMOKESHOW_GITHUB_COVERAGE_THRESHOLD: 100
SMOKESHOW_GITHUB_CONTEXT: coverage
SMOKESHOW_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SMOKESHOW_GITHUB_PR_HEAD_SHA: ${{ github.event.workflow_run.head_sha }}
SMOKESHOW_AUTH_KEY: ${{ secrets.SMOKESHOW_AUTH_KEY }}

View File

@@ -12,7 +12,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.6", "3.7", "3.8", "3.9", "3.10"]
python-version: ["3.7", "3.8", "3.9", "3.10", "3.11"]
fail-fast: false
steps:
@@ -21,21 +21,73 @@ jobs:
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
cache: "pip"
cache-dependency-path: pyproject.toml
- uses: actions/cache@v3
id: cache
with:
path: ${{ env.pythonLocation }}
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
key: ${{ runner.os }}-python-${{ env.pythonLocation }}-${{ hashFiles('pyproject.toml') }}-test-v03
- name: Install Dependencies
if: steps.cache.outputs.cache-hit != 'true'
run: flit install --symlink
run: pip install -e .[all,dev,doc,test]
- name: Lint
if: ${{ matrix.python-version != '3.6' }}
run: bash scripts/lint.sh
- run: mkdir coverage
- name: Test
run: bash scripts/test.sh
- name: Upload coverage
uses: codecov/codecov-action@v3
env:
COVERAGE_FILE: coverage/.coverage.${{ runner.os }}-py${{ matrix.python-version }}
CONTEXT: ${{ runner.os }}-py${{ matrix.python-version }}
- name: Store coverage files
uses: actions/upload-artifact@v3
with:
name: coverage
path: coverage
coverage-combine:
needs: [test]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
with:
python-version: '3.8'
cache: "pip"
cache-dependency-path: pyproject.toml
- name: Get coverage files
uses: actions/download-artifact@v3
with:
name: coverage
path: coverage
- run: pip install coverage[toml]
- run: ls -la coverage
- run: coverage combine coverage
- run: coverage report
- run: coverage html --show-contexts --title "Coverage for ${{ github.sha }}"
- name: Store coverage HTML
uses: actions/upload-artifact@v3
with:
name: coverage-html
path: htmlcov
# https://github.com/marketplace/actions/alls-green#why
check: # This job does nothing and is only used for the branch protection
if: always()
needs:
- coverage-combine
runs-on: ubuntu-latest
steps:
- name: Decide whether the needed jobs succeeded or failed
uses: re-actors/alls-green@release/v1
with:
jobs: ${{ toJSON(needs) }}

View File

@@ -1,8 +1,10 @@
# See https://pre-commit.com for more information
# See https://pre-commit.com/hooks.html for more hooks
default_language_version:
python: python3.10
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.3.0
rev: v4.4.0
hooks:
- id: check-added-large-files
- id: check-toml
@@ -12,27 +14,20 @@ repos:
- id: end-of-file-fixer
- id: trailing-whitespace
- repo: https://github.com/asottile/pyupgrade
rev: v2.37.1
rev: v3.3.1
hooks:
- id: pyupgrade
args:
- --py3-plus
- --keep-runtime-typing
- repo: https://github.com/myint/autoflake
rev: v1.4
- repo: https://github.com/charliermarsh/ruff-pre-commit
rev: v0.0.254
hooks:
- id: autoflake
- id: ruff
args:
- --recursive
- --in-place
- --remove-all-unused-imports
- --remove-unused-variables
- --expand-star-imports
- --exclude
- __init__.py
- --remove-duplicate-keys
- --fix
- repo: https://github.com/pycqa/isort
rev: 5.10.1
rev: 5.12.0
hooks:
- id: isort
name: isort (python)
@@ -43,7 +38,7 @@ repos:
name: isort (pyi)
types: [pyi]
- repo: https://github.com/psf/black
rev: 22.6.0
rev: 23.1.0
hooks:
- id: black
ci:

View File

@@ -8,8 +8,8 @@
<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 href="https://coverage-badge.samuelcolvin.workers.dev/redirect/tiangolo/fastapi" target="_blank">
<img src="https://coverage-badge.samuelcolvin.workers.dev/tiangolo/fastapi.svg" 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">
@@ -27,12 +27,11 @@
---
FastAPI is a modern, fast (high-performance), web framework for building APIs with Python 3.6+ based on standard Python type hints.
FastAPI is a modern, fast (high-performance), web framework for building APIs with Python 3.7+ 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.
@@ -50,15 +49,14 @@ The key features are:
<a href="https://bit.ly/3dmXC5S" target="_blank" title="The data structure for unstructured multimodal data"><img src="https://fastapi.tiangolo.com/img/sponsors/docarray.svg"></a>
<a href="https://bit.ly/3JJ7y5C" target="_blank" title="Build cross-modal and multimodal applications on the cloud"><img src="https://fastapi.tiangolo.com/img/sponsors/jina2.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://app.imgwhale.xyz/" target="_blank" title="The ultimate solution to unlimited and forever cloud storage."><img src="https://fastapi.tiangolo.com/img/sponsors/imgwhale.svg"></a>
<a href="https://doist.com/careers/9B437B1615-wa-senior-backend-engineer-python" target="_blank" title="Help us migrate doist to FastAPI"><img src="https://fastapi.tiangolo.com/img/sponsors/doist.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://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>
<a href="https://careers.powens.com/" target="_blank" title="Powens is hiring!"><img src="https://fastapi.tiangolo.com/img/sponsors/powens.png"></a>
<a href="https://www.svix.com/" target="_blank" title="Svix - Webhooks as a service"><img src="https://fastapi.tiangolo.com/img/sponsors/svix.svg"></a>
<!-- /sponsors -->
@@ -104,6 +102,12 @@ The key features are:
---
"_If anyone is looking to build a production Python API, I would highly recommend **FastAPI**. It is **beautifully designed**, **simple to use** and **highly scalable**, it has become a **key component** in our API first development strategy and is driving many automations and services such as our Virtual TAC Engineer._"
<div style="text-align: right; margin-right: 10%;">Deon Pillsbury - <strong>Cisco</strong> <a href="https://www.linkedin.com/posts/deonpillsbury_cisco-cx-python-activity-6963242628536487936-trAp/" 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>
@@ -114,7 +118,7 @@ If you are building a <abbr title="Command Line Interface">CLI</abbr> app to be
## Requirements
Python 3.6+
Python 3.7+
FastAPI stands on the shoulders of giants:
@@ -133,7 +137,7 @@ $ pip install fastapi
</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>.
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://github.com/pgjones/hypercorn" class="external-link" target="_blank">Hypercorn</a>.
<div class="termy">
@@ -330,7 +334,7 @@ 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+**.
Just standard **Python 3.7+**.
For example, for an `int`:
@@ -429,7 +433,7 @@ For a more complete example including more features, see the <a href="https://fa
* **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`
* extremely easy tests based on HTTPX and `pytest`
* **CORS**
* **Cookie Sessions**
* ...and more.
@@ -449,7 +453,7 @@ 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://www.python-httpx.org" target="_blank"><code>httpx</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.

View File

@@ -6,7 +6,7 @@ Learn more about it below. 👇
## Versions
The latest versions of FastAPI are supported.
The latest version of FastAPI is supported.
You are encouraged to [write tests](https://fastapi.tiangolo.com/tutorial/testing/) for your application and update your FastAPI version frequently after ensuring that your tests are passing. This way you will benefit from the latest features, bug fixes, and **security fixes**.

466
docs/az/docs/index.md Normal file
View File

@@ -0,0 +1,466 @@
{!../../../docs/missing-translation.md!}
<p align="center">
<a href="https://fastapi.tiangolo.com"><img src="https://fastapi.tiangolo.com/img/logo-margin/logo-teal.png" alt="FastAPI"></a>
</p>
<p align="center">
<em>FastAPI framework, high performance, easy to learn, fast to code, ready for production</em>
</p>
<p align="center">
<a href="https://github.com/tiangolo/fastapi/actions?query=workflow%3ATest" target="_blank">
<img src="https://github.com/tiangolo/fastapi/workflows/Test/badge.svg" alt="Test">
</a>
<a href="https://codecov.io/gh/tiangolo/fastapi" target="_blank">
<img src="https://img.shields.io/codecov/c/github/tiangolo/fastapi?color=%2334D058" alt="Coverage">
</a>
<a href="https://pypi.org/project/fastapi" target="_blank">
<img src="https://img.shields.io/pypi/v/fastapi?color=%2334D058&label=pypi%20package" alt="Package version">
</a>
</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.7+
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).
* Many extra features (thanks to Starlette) as:
* **WebSockets**
* **GraphQL**
* extremely easy tests based on `requests` and `pytest`
* **CORS**
* **Cookie Sessions**
* ...and more.
## Performance
Independent TechEmpower benchmarks show **FastAPI** applications running under Uvicorn as <a href="https://www.techempower.com/benchmarks/#section=test&runid=7464e520-0dc2-473d-bd34-dbdfd7e85911&hw=ph&test=query&l=zijzen-7" class="external-link" target="_blank">one of the fastest Python frameworks available</a>, only below Starlette and Uvicorn themselves (used internally by FastAPI). (*)
To understand more about it, see the section <a href="https://fastapi.tiangolo.com/benchmarks/" class="internal-link" target="_blank">Benchmarks</a>.
## Optional Dependencies
Used by Pydantic:
* <a href="https://github.com/esnme/ultrajson" target="_blank"><code>ujson</code></a> - for faster JSON <abbr title="converting the string that comes from an HTTP request into Python data">"parsing"</abbr>.
* <a href="https://github.com/JoshData/python-email-validator" target="_blank"><code>email_validator</code></a> - for email validation.
Used by Starlette:
* <a href="https://www.python-httpx.org" target="_blank"><code>httpx</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://graphene-python.org/" target="_blank"><code>graphene</code></a> - Required for `GraphQLApp` support.
* <a href="https://github.com/esnme/ultrajson" target="_blank"><code>ujson</code></a> - Required if you want to use `UJSONResponse`.
Used by FastAPI / Starlette:
* <a href="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.

View File

@@ -45,6 +45,7 @@ nav:
- fa: /fa/
- fr: /fr/
- he: /he/
- hy: /hy/
- id: /id/
- it: /it/
- ja: /ja/
@@ -55,6 +56,7 @@ nav:
- ru: /ru/
- sq: /sq/
- sv: /sv/
- ta: /ta/
- tr: /tr/
- uk: /uk/
- zh: /zh/
@@ -80,7 +82,7 @@ markdown_extensions:
extra:
analytics:
provider: google
property: UA-133183413-1
property: G-YNEVN69SC3
social:
- icon: fontawesome/brands/github-alt
link: https://github.com/tiangolo/fastapi
@@ -111,6 +113,8 @@ extra:
name: fr - français
- link: /he/
name: he
- link: /hy/
name: hy
- link: /id/
name: id
- link: /it/
@@ -131,6 +135,8 @@ extra:
name: sq - shqip
- link: /sv/
name: sv - svenska
- link: /ta/
name: ta - தமிழ்
- link: /tr/
name: tr - Türkçe
- link: /uk/

View File

@@ -169,7 +169,7 @@ Mit **FastAPI** bekommen Sie viele von **Starlette**'s Funktionen (da FastAPI nu
* **WebSocket**-Unterstützung.
* Hintergrundaufgaben im selben Prozess.
* Ereignisse für das Starten und Herunterfahren.
* Testclient basierend auf `requests`.
* Testclient basierend auf HTTPX.
* **CORS**, GZip, statische Dateien, Antwortfluss.
* **Sitzungs und Cookie** Unterstützung.
* 100% Testabdeckung.

View File

@@ -111,7 +111,7 @@ If you are building a <abbr title="Command Line Interface">CLI</abbr> app to be
## Requirements
Python 3.6+
Python 3.7+
FastAPI stands on the shoulders of giants:
@@ -445,7 +445,7 @@ 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://www.python-httpx.org" target="_blank"><code>httpx</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.

View File

@@ -45,6 +45,7 @@ nav:
- fa: /fa/
- fr: /fr/
- he: /he/
- hy: /hy/
- id: /id/
- it: /it/
- ja: /ja/
@@ -55,6 +56,7 @@ nav:
- ru: /ru/
- sq: /sq/
- sv: /sv/
- ta: /ta/
- tr: /tr/
- uk: /uk/
- zh: /zh/
@@ -81,7 +83,7 @@ markdown_extensions:
extra:
analytics:
provider: google
property: UA-133183413-1
property: G-YNEVN69SC3
social:
- icon: fontawesome/brands/github-alt
link: https://github.com/tiangolo/fastapi
@@ -112,6 +114,8 @@ extra:
name: fr - français
- link: /he/
name: he
- link: /hy/
name: hy
- link: /id/
name: id
- link: /it/
@@ -132,6 +136,8 @@ extra:
name: sq - shqip
- link: /sv/
name: sv - svenska
- link: /ta/
name: ta - தமிழ்
- link: /tr/
name: tr - Türkçe
- link: /uk/

View File

@@ -1,5 +1,21 @@
articles:
english:
- author: Raf Rasenberg
author_link: https://rafrasenberg.com/about/
link: https://rafrasenberg.com/fastapi-lambda/
title: 'FastAPI lambda container: serverless simplified'
- author: Teresa N. Fontanella De Santis
author_link: https://dev.to/
link: https://dev.to/teresafds/authorization-on-fastapi-with-casbin-41og
title: Authorization on FastAPI with Casbin
- author: WayScript
author_link: https://www.wayscript.com
link: https://blog.wayscript.com/fast-api-quickstart/
title: Quickstart Guide to Build and Host Responsive APIs with Fast API and WayScript
- author: New Relic
author_link: https://newrelic.com
link: https://newrelic.com/instant-observability/fastapi/e559ec64-f765-4470-a15f-1901fcebb468
title: How to monitor FastAPI application performance using Python agent
- author: Jean-Baptiste Rocher
author_link: https://hashnode.com/@jibrocher
link: https://dev.indooroutdoor.io/series/fastapi-react-poll-app
@@ -212,6 +228,10 @@ articles:
author_link: https://twitter.com/MantoshMukul
link: https://www.jetbrains.com/pycharm/guide/tutorials/fastapi-aws-kubernetes/
title: Developing FastAPI Application using K8s & AWS
- author: KrishNa
author_link: https://medium.com/@krishnardt365
link: https://medium.com/@krishnardt365/fastapi-docker-and-postgres-91943e71be92
title: Fastapi, Docker(Docker compose) and Postgres
german:
- author: Nico Axtmann
author_link: https://twitter.com/_nicoax
@@ -288,6 +308,11 @@ articles:
author_link: https://fullstackstation.com/author/figonking/
link: https://fullstackstation.com/fastapi-trien-khai-bang-docker/
title: 'FASTAPI: TRIỂN KHAI BẰNG DOCKER'
taiwanese:
- author: Leon
author_link: http://editor.leonh.space/
link: https://editor.leonh.space/2022/tortoise/
title: 'Tortoise ORM / FastAPI 整合快速筆記'
podcasts:
english:
- author: Podcast.`__init__`

View File

@@ -1,23 +1,17 @@
sponsors:
- - login: github
avatarUrl: https://avatars.githubusercontent.com/u/9919?v=4
url: https://github.com/github
- - login: Doist
avatarUrl: https://avatars.githubusercontent.com/u/2565372?v=4
url: https://github.com/Doist
- login: cryptapi
avatarUrl: https://avatars.githubusercontent.com/u/44925437?u=61369138589bc7fee6c417f3fbd50fbd38286cc4&v=4
url: https://github.com/cryptapi
- login: BLUE-DEVIL1134
avatarUrl: https://avatars.githubusercontent.com/u/55914808?u=f283d674fce31be7fb3ed2665b0f20d89958e541&v=4
url: https://github.com/BLUE-DEVIL1134
- login: jina-ai
- - 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: ObliviousAI
- - login: armand-sauzay
avatarUrl: https://avatars.githubusercontent.com/u/35524799?u=56e3e944bfe62770d1709c09552d2efc6d285ca6&v=4
url: https://github.com/armand-sauzay
- - login: cryptapi
avatarUrl: https://avatars.githubusercontent.com/u/44925437?u=61369138589bc7fee6c417f3fbd50fbd38286cc4&v=4
url: https://github.com/cryptapi
- - login: nihpo
avatarUrl: https://avatars.githubusercontent.com/u/1841030?u=0264956d7580f7e46687a762a7baa629f84cf97c&v=4
url: https://github.com/nihpo
- login: ObliviousAI
avatarUrl: https://avatars.githubusercontent.com/u/65656077?v=4
url: https://github.com/ObliviousAI
- login: chaserowbotham
@@ -26,9 +20,6 @@ sponsors:
- - login: mikeckennedy
avatarUrl: https://avatars.githubusercontent.com/u/2035561?u=1bb18268bcd4d9249e1f783a063c27df9a84c05b&v=4
url: https://github.com/mikeckennedy
- 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
@@ -38,69 +29,78 @@ sponsors:
- login: investsuite
avatarUrl: https://avatars.githubusercontent.com/u/73833632?v=4
url: https://github.com/investsuite
- login: svix
avatarUrl: https://avatars.githubusercontent.com/u/80175132?v=4
url: https://github.com/svix
- login: VincentParedes
avatarUrl: https://avatars.githubusercontent.com/u/103889729?v=4
url: https://github.com/VincentParedes
- - login: getsentry
avatarUrl: https://avatars.githubusercontent.com/u/1396951?v=4
url: https://github.com/getsentry
- - 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: vyos
avatarUrl: https://avatars.githubusercontent.com/u/5647000?v=4
url: https://github.com/vyos
- login: takashi-yoneya
avatarUrl: https://avatars.githubusercontent.com/u/33813153?u=2d0522bceba0b8b69adf1f2db866503bd96f944e&v=4
url: https://github.com/takashi-yoneya
- 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: nnfuzzy
avatarUrl: https://avatars.githubusercontent.com/u/687670?v=4
url: https://github.com/nnfuzzy
- login: johnadjei
- - 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: ianshan0915
avatarUrl: https://avatars.githubusercontent.com/u/5893101?u=a178d247d882578b1d1ef214b2494e52eb28634c&v=4
url: https://github.com/ianshan0915
- login: Trivie
avatarUrl: https://avatars.githubusercontent.com/u/8161763?v=4
url: https://github.com/Trivie
- login: Lovage-Labs
avatarUrl: https://avatars.githubusercontent.com/u/71685552?v=4
url: https://github.com/Lovage-Labs
- - login: moellenbeck
avatarUrl: https://avatars.githubusercontent.com/u/169372?v=4
url: https://github.com/moellenbeck
- login: birkjernstrom
avatarUrl: https://avatars.githubusercontent.com/u/281715?u=4be14b43f76b4bd497b1941309bb390250b405e6&v=4
url: https://github.com/birkjernstrom
- login: AccentDesign
avatarUrl: https://avatars.githubusercontent.com/u/2429332?v=4
url: https://github.com/AccentDesign
- login: RodneyU215
avatarUrl: https://avatars.githubusercontent.com/u/3329665?u=ec6a9adf8e7e8e306eed7d49687c398608d1604f&v=4
url: https://github.com/RodneyU215
- login: tizz98
avatarUrl: https://avatars.githubusercontent.com/u/5739698?u=f095a3659e3a8e7c69ccd822696990b521ea25f9&v=4
url: https://github.com/tizz98
- login: dorianturba
avatarUrl: https://avatars.githubusercontent.com/u/9381120?u=4bfc7032a824d1ed1994aa8256dfa597c8f187ad&v=4
url: https://github.com/dorianturba
- login: jmaralc
avatarUrl: https://avatars.githubusercontent.com/u/21101214?u=b15a9f07b7cbf6c9dcdbcb6550bbd2c52f55aa50&v=4
url: https://github.com/jmaralc
- login: marutoraman
avatarUrl: https://avatars.githubusercontent.com/u/33813153?u=2d0522bceba0b8b69adf1f2db866503bd96f944e&v=4
url: https://github.com/marutoraman
- login: leynier
avatarUrl: https://avatars.githubusercontent.com/u/36774373?u=2284831c821307de562ebde5b59014d5416c7e0d&v=4
url: https://github.com/leynier
- 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: DelfinaCare
avatarUrl: https://avatars.githubusercontent.com/u/83734439?v=4
url: https://github.com/DelfinaCare
- - login: povilasb
avatarUrl: https://avatars.githubusercontent.com/u/1213442?u=b11f58ed6ceea6e8297c9b310030478ebdac894d&v=4
url: https://github.com/povilasb
- login: primer-io
avatarUrl: https://avatars.githubusercontent.com/u/62146168?v=4
url: https://github.com/primer-io
- - login: indeedeng
avatarUrl: https://avatars.githubusercontent.com/u/2905043?v=4
url: https://github.com/indeedeng
- - login: Kludex
avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=62adc405ef418f4b6c8caa93d3eb8ab107bc4927&v=4
url: https://github.com/Kludex
@@ -116,9 +116,12 @@ sponsors:
- login: kamalgill
avatarUrl: https://avatars.githubusercontent.com/u/133923?u=0df9181d97436ce330e9acf90ab8a54b7022efe7&v=4
url: https://github.com/kamalgill
- login: deserat
avatarUrl: https://avatars.githubusercontent.com/u/299332?v=4
url: https://github.com/deserat
- login: dekoza
avatarUrl: https://avatars.githubusercontent.com/u/210980?u=c03c78a8ae1039b500dfe343665536ebc51979b2&v=4
url: https://github.com/dekoza
- login: pamelafox
avatarUrl: https://avatars.githubusercontent.com/u/297042?v=4
url: https://github.com/pamelafox
- login: ericof
avatarUrl: https://avatars.githubusercontent.com/u/306014?u=cf7c8733620397e6584a451505581c01c5d842d7&v=4
url: https://github.com/ericof
@@ -128,74 +131,74 @@ sponsors:
- 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=bd65cc1f228ce6455e56dfaca3ef47c33bc7c3b0&v=4
url: https://github.com/jqueguiner
- login: alexsantos
avatarUrl: https://avatars.githubusercontent.com/u/932219?v=4
url: https://github.com/alexsantos
- login: iobruno
avatarUrl: https://avatars.githubusercontent.com/u/901651?u=460bc34ac298dca9870aafe3a1560a2ae789bc4a&v=4
url: https://github.com/iobruno
- login: tcsmith
avatarUrl: https://avatars.githubusercontent.com/u/989034?u=7d8d741552b3279e8f4d3878679823a705a46f8f&v=4
url: https://github.com/tcsmith
- login: ltieman
avatarUrl: https://avatars.githubusercontent.com/u/1084689?u=e69b17de17cb3ca141a17daa7ccbe173ceb1eb17&v=4
url: https://github.com/ltieman
- login: mrkmcknz
avatarUrl: https://avatars.githubusercontent.com/u/1089376?u=2b9b8a8c25c33a4f6c220095638bd821cdfd13a3&v=4
url: https://github.com/mrkmcknz
- login: coffeewasmyidea
avatarUrl: https://avatars.githubusercontent.com/u/1636488?u=8e32a4f200eff54dd79cd79d55d254bfce5e946d&v=4
url: https://github.com/coffeewasmyidea
- login: jonakoudijs
avatarUrl: https://avatars.githubusercontent.com/u/1906344?u=5ca0c9a1a89b6a2ba31abe35c66bdc07af60a632&v=4
url: https://github.com/jonakoudijs
- login: corleyma
avatarUrl: https://avatars.githubusercontent.com/u/2080732?u=aed2ff652294a87d666b1c3f6dbe98104db76d26&v=4
avatarUrl: https://avatars.githubusercontent.com/u/2080732?u=c61f9a4bbc45a45f5d855f93e5f6e0fc8b32c468&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
- login: saivarunk
avatarUrl: https://avatars.githubusercontent.com/u/2976867?u=71f4385e781e9a9e871a52f2d4686f9a8d69ba2f&v=4
url: https://github.com/saivarunk
- login: andre1sk
avatarUrl: https://avatars.githubusercontent.com/u/3148093?v=4
url: https://github.com/andre1sk
- login: Shark009
avatarUrl: https://avatars.githubusercontent.com/u/3163309?u=0c6f4091b0eda05c44c390466199826e6dc6e431&v=4
url: https://github.com/Shark009
- login: grillazz
avatarUrl: https://avatars.githubusercontent.com/u/3415861?u=0b32b7073ae1ab8b7f6d2db0188c2e1e357ff451&v=4
url: https://github.com/grillazz
- login: ColliotL
avatarUrl: https://avatars.githubusercontent.com/u/3412402?u=ca64b07ecbef2f9da1cc2cac3f37522aa4814902&v=4
url: https://github.com/ColliotL
- 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: aacayaco
avatarUrl: https://avatars.githubusercontent.com/u/3634801?u=eaadda178c964178fcb64886f6c732172c8f8219&v=4
url: https://github.com/aacayaco
- 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: gorhack
avatarUrl: https://avatars.githubusercontent.com/u/4141690?u=ec119ebc4bdf00a7bc84657a71aa17834f4f27f3&v=4
url: https://github.com/gorhack
- login: jgreys
avatarUrl: https://avatars.githubusercontent.com/u/4136890?u=c66ae617d614f6c886f1f1c1799d22100b3c848d&v=4
url: https://github.com/jgreys
- 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=76ef23f06ae7c604e009873bc27cf0ea9ba738c9&v=4
url: https://github.com/CINOAdam
- 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: ternaus
avatarUrl: https://avatars.githubusercontent.com/u/5481618?u=fabc8d75c921b3380126adb5a931c5da6e7db04f&v=4
url: https://github.com/ternaus
- login: eseglem
avatarUrl: https://avatars.githubusercontent.com/u/5920492?u=208d419cf667b8ac594c82a8db01932c7e50d057&v=4
url: https://github.com/eseglem
- 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
avatarUrl: https://avatars.githubusercontent.com/u/6152183?u=c485eefca5c6329600cae63dd35e4f5682ce6924&v=4
url: https://github.com/iwpnd
- login: simw
avatarUrl: https://avatars.githubusercontent.com/u/6322526?v=4
@@ -203,57 +206,54 @@ sponsors:
- login: pkucmus
avatarUrl: https://avatars.githubusercontent.com/u/6347418?u=98f5918b32e214a168a2f5d59b0b8ebdf57dca0d&v=4
url: https://github.com/pkucmus
- login: ioalloc
avatarUrl: https://avatars.githubusercontent.com/u/6737824?u=6c3a31449f1c92064287171aa9ebe6363a0c9b7b&v=4
url: https://github.com/ioalloc
- login: s3ich4n
avatarUrl: https://avatars.githubusercontent.com/u/6926298?u=ba3025d698e1c986655e776ae383a3d60d9d578e&v=4
avatarUrl: https://avatars.githubusercontent.com/u/6926298?u=6690c5403bc1d9a1837886defdc5256e9a43b1db&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: ValentinCalomme
avatarUrl: https://avatars.githubusercontent.com/u/7288672?u=e09758c7a36c49f0fb3574abe919cbd344fdc2d6&v=4
url: https://github.com/ValentinCalomme
- 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: 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: wdwinslow
avatarUrl: https://avatars.githubusercontent.com/u/11562137?u=dc01daafb354135603a263729e3d26d939c0c452&v=4
url: https://github.com/wdwinslow
- login: svats2k
avatarUrl: https://avatars.githubusercontent.com/u/12378398?u=ecf28c19f61052e664bdfeb2391f8107d137915c&v=4
url: https://github.com/svats2k
- 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: khadrawy
avatarUrl: https://avatars.githubusercontent.com/u/13686061?u=59f25ef42ecf04c22657aac4238ce0e2d3d30304&v=4
url: https://github.com/khadrawy
- login: pablonnaoji
avatarUrl: https://avatars.githubusercontent.com/u/15187159?u=afc15bd5a4ba9c5c7206bbb1bcaeef606a0932e0&v=4
avatarUrl: https://avatars.githubusercontent.com/u/15187159?u=7480e0eaf959e9c5dfe3a05286f2ea4588c0a3c6&v=4
url: https://github.com/pablonnaoji
- login: robintully
avatarUrl: https://avatars.githubusercontent.com/u/17059673?u=862b9bb01513f5acd30df97433cb97a24dbfb772&v=4
url: https://github.com/robintully
- login: mjohnsey
avatarUrl: https://avatars.githubusercontent.com/u/16784016?u=38fad2e6b411244560b3af99c5f5a4751bc81865&v=4
url: https://github.com/mjohnsey
- login: abdalla19977
avatarUrl: https://avatars.githubusercontent.com/u/17257234?v=4
url: https://github.com/abdalla19977
- login: wedwardbeck
avatarUrl: https://avatars.githubusercontent.com/u/19333237?u=1de4ae2bf8d59eb4c013f21d863cbe0f2010575f&v=4
url: https://github.com/wedwardbeck
- 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
avatarUrl: https://avatars.githubusercontent.com/u/21352040?u=0be845711495bbd7b756e13fcaeb8efc1ebd78ba&v=4
url: https://github.com/Filimoa
- login: shuheng-liu
avatarUrl: https://avatars.githubusercontent.com/u/22414322?u=813c45f30786c6b511b21a661def025d8f7b609e&v=4
url: https://github.com/shuheng-liu
- login: Pablongo24
avatarUrl: https://avatars.githubusercontent.com/u/24843427?u=78a6798469889d7a0690449fc667c39e13d5c6a9&v=4
url: https://github.com/Pablongo24
- login: Joeriksson
avatarUrl: https://avatars.githubusercontent.com/u/25037079?v=4
url: https://github.com/Joeriksson
@@ -266,60 +266,60 @@ sponsors:
- login: veprimk
avatarUrl: https://avatars.githubusercontent.com/u/29689749?u=f8cb5a15a286e522e5b189bc572d5a1a90217fb2&v=4
url: https://github.com/veprimk
- login: meysam81
avatarUrl: https://avatars.githubusercontent.com/u/30233243?u=64dc9fc62d039892c6fb44d804251cad5537132b&v=4
url: https://github.com/meysam81
- login: BrettskiPy
avatarUrl: https://avatars.githubusercontent.com/u/30988215?u=d8a94a67e140d5ee5427724b292cc52d8827087a&v=4
url: https://github.com/BrettskiPy
- login: mauroalejandrojm
avatarUrl: https://avatars.githubusercontent.com/u/31569442?u=cdada990a1527926a36e95f62c30a8b48bbc49a1&v=4
url: https://github.com/mauroalejandrojm
- login: Leay15
avatarUrl: https://avatars.githubusercontent.com/u/32212558?u=c4aa9c1737e515959382a5515381757b1fd86c53&v=4
url: https://github.com/Leay15
- login: ygorpontelo
avatarUrl: https://avatars.githubusercontent.com/u/32963605?u=35f7103f9c4c4c2589ae5737ee882e9375ef072e&v=4
url: https://github.com/ygorpontelo
- 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: askurihin
avatarUrl: https://avatars.githubusercontent.com/u/37978981?v=4
url: https://github.com/askurihin
- login: arleybri18
avatarUrl: https://avatars.githubusercontent.com/u/39681546?u=5c028f81324b0e8c73b3c15bc4e7b0218d2ba0c3&v=4
url: https://github.com/arleybri18
- login: ybressler
avatarUrl: https://avatars.githubusercontent.com/u/40807730?u=41e2c00f1eebe3c402635f0325e41b4e6511462c&v=4
url: https://github.com/ybressler
- login: ddilidili
avatarUrl: https://avatars.githubusercontent.com/u/42176885?u=c0a849dde06987434653197b5f638d3deb55fc6c&v=4
url: https://github.com/ddilidili
- login: dbanty
avatarUrl: https://avatars.githubusercontent.com/u/43723790?u=9bcce836bbce55835291c5b2ac93a4e311f4b3c3&v=4
url: https://github.com/dbanty
- login: VictorCalderon
avatarUrl: https://avatars.githubusercontent.com/u/44529243?u=cea69884f826a29aff1415493405209e0706d07a&v=4
url: https://github.com/VictorCalderon
- login: arthuRHD
avatarUrl: https://avatars.githubusercontent.com/u/48015496?u=05a0d5b8b9320eeb7990d35c9337b823f269d2ff&v=4
url: https://github.com/arthuRHD
- login: rafsaf
avatarUrl: https://avatars.githubusercontent.com/u/51059348?u=f8f0d6d6e90fac39fa786228158ba7f013c74271&v=4
url: https://github.com/rafsaf
- login: dudikbender
avatarUrl: https://avatars.githubusercontent.com/u/53487583?u=494f85229115076121b3639a3806bbac1c6ae7f6&v=4
avatarUrl: https://avatars.githubusercontent.com/u/53487583?u=3a57542938ebfd57579a0111db2b297e606d9681&v=4
url: https://github.com/dudikbender
- login: daisuke8000
avatarUrl: https://avatars.githubusercontent.com/u/55035595?u=23a3f2f2925ad3efc27c7420041622b7f5fd2b79&v=4
url: https://github.com/daisuke8000
- login: dazeddd
avatarUrl: https://avatars.githubusercontent.com/u/59472056?u=7a1b668449bf8b448db13e4c575576d24d7d658b&v=4
url: https://github.com/dazeddd
- login: thisistheplace
avatarUrl: https://avatars.githubusercontent.com/u/57633545?u=a3f3a7f8ace8511c6c067753f6eb6aee0db11ac6&v=4
url: https://github.com/thisistheplace
- login: kyjoconn
avatarUrl: https://avatars.githubusercontent.com/u/58443406?u=a3e9c2acfb7ba62edda9334aba61cf027f41f789&v=4
url: https://github.com/kyjoconn
- login: A-Edge
avatarUrl: https://avatars.githubusercontent.com/u/59514131?v=4
url: https://github.com/A-Edge
- 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: around
avatarUrl: https://avatars.githubusercontent.com/u/62425723?v=4
url: https://github.com/around
- login: patsatsia
avatarUrl: https://avatars.githubusercontent.com/u/61111267?u=3271b85f7a37b479c8d0ae0a235182e83c166edf&v=4
url: https://github.com/patsatsia
- login: predictionmachine
avatarUrl: https://avatars.githubusercontent.com/u/63719559?v=4
url: https://github.com/predictionmachine
@@ -329,17 +329,26 @@ sponsors:
- login: anthonycepeda
avatarUrl: https://avatars.githubusercontent.com/u/72019805?u=4252c6b6dc5024af502a823a3ac5e7a03a69963f&v=4
url: https://github.com/anthonycepeda
- login: dotlas
avatarUrl: https://avatars.githubusercontent.com/u/88832003?v=4
url: https://github.com/dotlas
- login: DelfinaCare
avatarUrl: https://avatars.githubusercontent.com/u/83734439?v=4
url: https://github.com/DelfinaCare
- login: osawa-koki
avatarUrl: https://avatars.githubusercontent.com/u/94336223?u=59c6fe6945bcbbaff87b2a794238671b060620d2&v=4
url: https://github.com/osawa-koki
- 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
- login: Dagmaara
avatarUrl: https://avatars.githubusercontent.com/u/115501964?v=4
url: https://github.com/Dagmaara
- - login: pawamoy
avatarUrl: https://avatars.githubusercontent.com/u/3999221?u=b030e4c89df2f3a36bc4710b925bdeb6745c9856&v=4
url: https://github.com/pawamoy
- login: linux-china
avatarUrl: https://avatars.githubusercontent.com/u/46711?u=cd77c65338b158750eb84dc7ff1acf3209ccfc4f&v=4
url: https://github.com/linux-china
- login: ddanier
avatarUrl: https://avatars.githubusercontent.com/u/113563?v=4
avatarUrl: https://avatars.githubusercontent.com/u/113563?u=ed1dc79de72f93bd78581f88ebc6952b62f472da&v=4
url: https://github.com/ddanier
- login: jhb
avatarUrl: https://avatars.githubusercontent.com/u/142217?v=4
@@ -350,15 +359,6 @@ sponsors:
- 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?u=fa7c3503b47bf16405b96d21554bc59f07a65523&v=4
url: https://github.com/yourkin
- 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
@@ -368,15 +368,9 @@ sponsors:
- login: dmig
avatarUrl: https://avatars.githubusercontent.com/u/388564?v=4
url: https://github.com/dmig
- 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
@@ -384,38 +378,32 @@ sponsors:
avatarUrl: https://avatars.githubusercontent.com/u/861044?u=5abfca5588f3e906b31583d7ee62f6de4b68aa24&v=4
url: https://github.com/browniebroke
- login: janfilips
avatarUrl: https://avatars.githubusercontent.com/u/870699?u=6034d81731ecb41ae5c717e56a901ed46fc039a8&v=4
avatarUrl: https://avatars.githubusercontent.com/u/870699?u=50de77b93d3a0b06887e672d4e8c7b9d643085aa&v=4
url: https://github.com/janfilips
- login: woodrad
avatarUrl: https://avatars.githubusercontent.com/u/1410765?u=86707076bb03d143b3b11afc1743d2aa496bd8bf&v=4
url: https://github.com/woodrad
- login: Pytlicek
avatarUrl: https://avatars.githubusercontent.com/u/1430522?u=169dba3bfbc04ed214a914640ff435969f19ddb3&v=4
url: https://github.com/Pytlicek
- login: allen0125
avatarUrl: https://avatars.githubusercontent.com/u/1448456?u=d4feb3d06a61baa4a69857ce371cc53fb4dffd2c&v=4
avatarUrl: https://avatars.githubusercontent.com/u/1448456?u=dc2ad819497eef494b88688a1796e0adb87e7cae&v=4
url: https://github.com/allen0125
- login: WillHogan
avatarUrl: https://avatars.githubusercontent.com/u/1661551?u=7036c064cf29781470573865264ec8e60b6b809f&v=4
url: https://github.com/WillHogan
- login: my3
avatarUrl: https://avatars.githubusercontent.com/u/1825270?v=4
url: https://github.com/my3
- login: cbonoz
avatarUrl: https://avatars.githubusercontent.com/u/2351087?u=fd3e8030b2cc9fbfbb54a65e9890c548a016f58b&v=4
url: https://github.com/cbonoz
- login: rglsk
avatarUrl: https://avatars.githubusercontent.com/u/2768101?u=e349c88673f2155fe021331377c656a9d74bcc25&v=4
url: https://github.com/rglsk
- login: 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: larsvik
avatarUrl: https://avatars.githubusercontent.com/u/3442226?v=4
url: https://github.com/larsvik
- login: anthonycorletti
avatarUrl: https://avatars.githubusercontent.com/u/3477132?v=4
url: https://github.com/anthonycorletti
- login: pawamoy
avatarUrl: https://avatars.githubusercontent.com/u/3999221?u=b030e4c89df2f3a36bc4710b925bdeb6745c9856&v=4
url: https://github.com/pawamoy
- login: nikeee
avatarUrl: https://avatars.githubusercontent.com/u/4068864?u=63f8eee593f25138e0f1032ef442e9ad24907d4c&v=4
url: https://github.com/nikeee
- login: Alisa-lisa
avatarUrl: https://avatars.githubusercontent.com/u/4137964?u=e7e393504f554f4ff15863a1e01a5746863ef9ce&v=4
url: https://github.com/Alisa-lisa
@@ -423,20 +411,26 @@ sponsors:
avatarUrl: https://avatars.githubusercontent.com/u/4472301?v=4
url: https://github.com/danielunderwood
- login: unredundant
avatarUrl: https://avatars.githubusercontent.com/u/5607577?u=57dd0023365bec03f4fc566df6b81bc0a264a47d&v=4
avatarUrl: https://avatars.githubusercontent.com/u/5607577?u=1ffbf39f5bb8736b75c0d235707d6e8f803725c5&v=4
url: https://github.com/unredundant
- login: Baghdady92
avatarUrl: https://avatars.githubusercontent.com/u/5708590?v=4
url: https://github.com/Baghdady92
- login: KentShikama
avatarUrl: https://avatars.githubusercontent.com/u/6329898?u=8b236810db9b96333230430837e1f021f9246da1&v=4
url: https://github.com/KentShikama
- login: holec
avatarUrl: https://avatars.githubusercontent.com/u/6438041?u=f5af71ec85b3a9d7b8139cb5af0512b02fa9ab1e&v=4
url: https://github.com/holec
- login: mattwelke
avatarUrl: https://avatars.githubusercontent.com/u/7719209?v=4
url: https://github.com/mattwelke
- login: hcristea
avatarUrl: https://avatars.githubusercontent.com/u/7814406?u=61d7a4fcf846983a4606788eac25e1c6c1209ba8&v=4
url: https://github.com/hcristea
- 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: yenchenLiu
avatarUrl: https://avatars.githubusercontent.com/u/9199638?u=8cdf5ae507448430d90f6f3518d1665a23afe99b&v=4
url: https://github.com/yenchenLiu
- login: xncbf
avatarUrl: https://avatars.githubusercontent.com/u/9462045?u=866a1311e4bd3ec5ae84185c4fcc99f397c883d7&v=4
url: https://github.com/xncbf
@@ -449,59 +443,65 @@ sponsors:
- login: satwikkansal
avatarUrl: https://avatars.githubusercontent.com/u/10217535?u=b12d6ef74ea297de9e46da6933b1a5b7ba9e6a61&v=4
url: https://github.com/satwikkansal
- login: mntolia
avatarUrl: https://avatars.githubusercontent.com/u/10390224?v=4
url: https://github.com/mntolia
- login: pheanex
avatarUrl: https://avatars.githubusercontent.com/u/10408624?u=5b6bab6ee174aa6e991333e06eb29f628741013d&v=4
url: https://github.com/pheanex
- 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: sanghunka
avatarUrl: https://avatars.githubusercontent.com/u/16280020?u=960f5426ae08303229f045b9cc2ed463dcd41c15&v=4
url: https://github.com/sanghunka
- login: stevenayers
avatarUrl: https://avatars.githubusercontent.com/u/16361214?u=098b797d8d48afb8cd964b717847943b61d24a6d&v=4
url: https://github.com/stevenayers
- login: giuliano-oliveira
avatarUrl: https://avatars.githubusercontent.com/u/13181797?u=0ef2dfbf7fc9a9726d45c21d32b5d1038a174870&v=4
url: https://github.com/giuliano-oliveira
- login: TheR1D
avatarUrl: https://avatars.githubusercontent.com/u/16740832?u=b2923ac17fe6e2a7c9ea14800351ddb92f79b100&v=4
url: https://github.com/TheR1D
- login: cdsre
avatarUrl: https://avatars.githubusercontent.com/u/16945936?v=4
url: https://github.com/cdsre
- login: aprilcoskun
avatarUrl: https://avatars.githubusercontent.com/u/17393603?u=29145243b4c7fadc80c7099471309cc2c04b6bcc&v=4
url: https://github.com/aprilcoskun
- login: jangia
avatarUrl: https://avatars.githubusercontent.com/u/17927101?u=9261b9bb0c3e3bb1ecba43e8915dc58d8c9a077e&v=4
url: https://github.com/jangia
- login: yannicschroeer
avatarUrl: https://avatars.githubusercontent.com/u/22749683?u=4df05a7296c207b91c5d7c7a11c29df5ab313e2b&v=4
url: https://github.com/yannicschroeer
- login: paulowiz
avatarUrl: https://avatars.githubusercontent.com/u/18649504?u=d8a6ac40321f2bded0eba78b637751c7f86c6823&v=4
url: https://github.com/paulowiz
- login: ghandic
avatarUrl: https://avatars.githubusercontent.com/u/23500353?u=e2e1d736f924d9be81e8bfc565b6d8836ba99773&v=4
url: https://github.com/ghandic
- login: fstau
avatarUrl: https://avatars.githubusercontent.com/u/24669867?u=60e7c8c09f8dafabee8fc3edcd6f9e19abbff918&v=4
url: https://github.com/fstau
- login: pers0n4
avatarUrl: https://avatars.githubusercontent.com/u/24864600?u=f211a13a7b572cbbd7779b9c8d8cb428cc7ba07e&v=4
url: https://github.com/pers0n4
- login: SebTota
avatarUrl: https://avatars.githubusercontent.com/u/25122511?v=4
url: https://github.com/SebTota
- login: hoenie-ams
avatarUrl: https://avatars.githubusercontent.com/u/25708487?u=cda07434f0509ac728d9edf5e681117c0f6b818b&v=4
url: https://github.com/hoenie-ams
- login: joerambo
avatarUrl: https://avatars.githubusercontent.com/u/26282974?v=4
url: https://github.com/joerambo
- login: mertguvencli
avatarUrl: https://avatars.githubusercontent.com/u/29762151?u=16a906d90df96c8cff9ea131a575c4bc171b1523&v=4
url: https://github.com/mertguvencli
- login: elisoncrum
avatarUrl: https://avatars.githubusercontent.com/u/30413278?u=531190845bb0935dbc1e4f017cda3cb7b4dd0e54&v=4
url: https://github.com/elisoncrum
- login: ruizdiazever
avatarUrl: https://avatars.githubusercontent.com/u/29817086?u=2df54af55663d246e3a4dc8273711c37f1adb117&v=4
url: https://github.com/ruizdiazever
- login: HosamAlmoghraby
avatarUrl: https://avatars.githubusercontent.com/u/32025281?u=aa1b09feabccbf9dc506b81c71155f32d126cefa&v=4
url: https://github.com/HosamAlmoghraby
- 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: bnkc
avatarUrl: https://avatars.githubusercontent.com/u/34930566?u=76cdc0a8b4e88c7d3e58dccb4b2670839e1247b4&v=4
url: https://github.com/bnkc
- login: declon
avatarUrl: https://avatars.githubusercontent.com/u/36180226?v=4
url: https://github.com/declon
- login: alvarobartt
avatarUrl: https://avatars.githubusercontent.com/u/36760800?u=ac9ccb8b9164eb5fe7d5276142591aa1b8080daf&v=4
avatarUrl: https://avatars.githubusercontent.com/u/36760800?u=9b38695807eb981d452989699ff72ec2d8f6508e&v=4
url: https://github.com/alvarobartt
- login: d-e-h-i-o
avatarUrl: https://avatars.githubusercontent.com/u/36816716?v=4
@@ -510,23 +510,14 @@ sponsors:
avatarUrl: https://avatars.githubusercontent.com/u/38921751?u=ae14bc1e40f2dd5a9c5741fc0b0dffbd416a5fa9&v=4
url: https://github.com/ww-daniel-mora
- login: rwxd
avatarUrl: https://avatars.githubusercontent.com/u/40308458?u=9ddf8023ca3326381ba8fb77285ae36598a15de3&v=4
avatarUrl: https://avatars.githubusercontent.com/u/40308458?u=cd04a39e3655923be4f25c2ba8a5a07b3da3230a&v=4
url: https://github.com/rwxd
- 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=fee5739394fea074cb0b66929d070114a5067aae&v=4
avatarUrl: https://avatars.githubusercontent.com/u/43553423?u=5265858add14a6822bd145f7547323cf078563e6&v=4
url: https://github.com/arrrrrmin
- login: BomGard
avatarUrl: https://avatars.githubusercontent.com/u/47395385?u=8e9052f54e0b8dc7285099c438fa29c55a7d6407&v=4
url: https://github.com/BomGard
- login: akanz1
avatarUrl: https://avatars.githubusercontent.com/u/51492342?u=2280f57134118714645e16b535c1a37adf6b369b&v=4
url: https://github.com/akanz1
- login: shidenko97
avatarUrl: https://avatars.githubusercontent.com/u/54946990?u=3fdc0caea36af9217dacf1cc7760c7ed9d67dcfe&v=4
url: https://github.com/shidenko97
- login: hgalytoby
avatarUrl: https://avatars.githubusercontent.com/u/50397689?u=f4888c2c54929bd86eed0d3971d09fcb306e5088&v=4
url: https://github.com/hgalytoby
- login: data-djinn
avatarUrl: https://avatars.githubusercontent.com/u/56449985?u=42146e140806908d49bd59ccc96f222abf587886&v=4
url: https://github.com/data-djinn
@@ -545,27 +536,12 @@ sponsors:
- login: realabja
avatarUrl: https://avatars.githubusercontent.com/u/66185192?u=001e2dd9297784f4218997981b4e6fa8357bb70b&v=4
url: https://github.com/realabja
- login: alessio-proietti
avatarUrl: https://avatars.githubusercontent.com/u/67370599?u=8ac73db1e18e946a7681f173abdb640516f88515&v=4
url: https://github.com/alessio-proietti
- login: Mr-Sunglasses
avatarUrl: https://avatars.githubusercontent.com/u/81439109?u=a5d0762fdcec26e18a028aef05323de3c6fb195c&v=4
url: https://github.com/Mr-Sunglasses
- - login: backbord
avatarUrl: https://avatars.githubusercontent.com/u/6814946?v=4
url: https://github.com/backbord
- login: gabrielmbmb
avatarUrl: https://avatars.githubusercontent.com/u/29572918?u=6d1e00b5d558e96718312ff910a2318f47cc3145&v=4
url: https://github.com/gabrielmbmb
- login: garydsong
avatarUrl: https://avatars.githubusercontent.com/u/105745865?u=03cc1aa9c978be0020e5a1ce1ecca323dd6c8d65&v=4
url: https://github.com/garydsong
- - login: Leon0824
avatarUrl: https://avatars.githubusercontent.com/u/1922026?v=4
url: https://github.com/Leon0824
- login: danburonline
avatarUrl: https://avatars.githubusercontent.com/u/34251194?u=2cad4388c1544e539ecb732d656e42fb07b4ff2d&v=4
url: https://github.com/danburonline
- login: zachspar
avatarUrl: https://avatars.githubusercontent.com/u/41600414?u=edf29c197137f51bace3f19a2ba759662640771f&v=4
url: https://github.com/zachspar
- login: sownt
avatarUrl: https://avatars.githubusercontent.com/u/44340502?u=c06e3c45fb00a403075172770805fe57ff17b1cf&v=4
url: https://github.com/sownt
- login: aahouzi
avatarUrl: https://avatars.githubusercontent.com/u/75032370?u=82677ee9cd86b3ccf4e13d9cb6765d8de5713e1e&v=4
url: https://github.com/aahouzi

View File

@@ -1,150 +1,158 @@
maintainers:
- login: tiangolo
answers: 1248
prs: 318
answers: 1827
prs: 384
avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=740f11212a731f56798f558ceddb0bd07642afa7&v=4
url: https://github.com/tiangolo
experts:
- login: Kludex
count: 352
count: 376
avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=62adc405ef418f4b6c8caa93d3eb8ab107bc4927&v=4
url: https://github.com/Kludex
- login: dmontagu
count: 262
count: 237
avatarUrl: https://avatars.githubusercontent.com/u/35119617?u=58ed2a45798a4339700e2f62b2e12e6e54bf0396&v=4
url: https://github.com/dmontagu
- login: ycd
count: 221
avatarUrl: https://avatars.githubusercontent.com/u/62724709?u=826f228edf0bab0d19ad1d5c4ba4df1047ccffef&v=4
url: https://github.com/ycd
- login: Mause
count: 207
count: 220
avatarUrl: https://avatars.githubusercontent.com/u/1405026?v=4
url: https://github.com/Mause
- login: ycd
count: 217
avatarUrl: https://avatars.githubusercontent.com/u/62724709?u=bba5af018423a2858d49309bed2a899bb5c34ac5&v=4
url: https://github.com/ycd
- login: JarroVGIT
count: 192
avatarUrl: https://avatars.githubusercontent.com/u/13659033?u=e8bea32d07a5ef72f7dde3b2079ceb714923ca05&v=4
url: https://github.com/JarroVGIT
- login: euri10
count: 166
count: 151
avatarUrl: https://avatars.githubusercontent.com/u/1104190?u=321a2e953e6645a7d09b732786c7a8061e0f8a8b&v=4
url: https://github.com/euri10
- login: phy25
count: 130
count: 126
avatarUrl: https://avatars.githubusercontent.com/u/331403?v=4
url: https://github.com/phy25
- login: iudeen
count: 116
avatarUrl: https://avatars.githubusercontent.com/u/10519440?u=2843b3303282bff8b212dcd4d9d6689452e4470c&v=4
url: https://github.com/iudeen
- login: jgould22
count: 101
avatarUrl: https://avatars.githubusercontent.com/u/4335847?u=ed77f67e0bb069084639b24d812dbb2a2b1dc554&v=4
url: https://github.com/jgould22
- login: raphaelauv
count: 77
count: 83
avatarUrl: https://avatars.githubusercontent.com/u/10202690?u=e6f86f5c0c3026a15d6b51792fa3e532b12f1371&v=4
url: https://github.com/raphaelauv
- login: ArcLightSlavik
count: 71
avatarUrl: https://avatars.githubusercontent.com/u/31127044?u=b0f2c37142f4b762e41ad65dc49581813422bd71&v=4
url: https://github.com/ArcLightSlavik
- login: JarroVGIT
count: 68
avatarUrl: https://avatars.githubusercontent.com/u/13659033?u=e8bea32d07a5ef72f7dde3b2079ceb714923ca05&v=4
url: https://github.com/JarroVGIT
- login: ghandic
count: 71
avatarUrl: https://avatars.githubusercontent.com/u/23500353?u=e2e1d736f924d9be81e8bfc565b6d8836ba99773&v=4
url: https://github.com/ghandic
- login: falkben
count: 58
count: 57
avatarUrl: https://avatars.githubusercontent.com/u/653031?u=0c8d8f33d87f1aa1a6488d3f02105e9abc838105&v=4
url: https://github.com/falkben
- login: sm-Fifteen
count: 49
avatarUrl: https://avatars.githubusercontent.com/u/516999?u=437c0c5038558c67e887ccd863c1ba0f846c03da&v=4
url: https://github.com/sm-Fifteen
- login: insomnes
count: 46
avatarUrl: https://avatars.githubusercontent.com/u/16958893?u=f8be7088d5076d963984a21f95f44e559192d912&v=4
url: https://github.com/insomnes
- login: Dustyposa
count: 43
count: 45
avatarUrl: https://avatars.githubusercontent.com/u/27180793?u=5cf2877f50b3eb2bc55086089a78a36f07042889&v=4
url: https://github.com/Dustyposa
- login: insomnes
count: 45
avatarUrl: https://avatars.githubusercontent.com/u/16958893?u=f8be7088d5076d963984a21f95f44e559192d912&v=4
url: https://github.com/insomnes
- login: frankie567
count: 43
avatarUrl: https://avatars.githubusercontent.com/u/1144727?u=85c025e3fcc7bd79a5665c63ee87cdf8aae13374&v=4
url: https://github.com/frankie567
- login: acidjunk
count: 43
avatarUrl: https://avatars.githubusercontent.com/u/685002?u=b5094ab4527fc84b006c0ac9ff54367bdebb2267&v=4
url: https://github.com/acidjunk
- login: odiseo0
count: 42
avatarUrl: https://avatars.githubusercontent.com/u/87550035?u=16f9255804161c6ff3c8b7ef69848f0126bcd405&v=4
url: https://github.com/odiseo0
- login: adriangb
count: 40
avatarUrl: https://avatars.githubusercontent.com/u/1755071?u=81f0262df34e1460ca546fbd0c211169c2478532&v=4
avatarUrl: https://avatars.githubusercontent.com/u/1755071?u=1e2c2c9b39f5c9b780fb933d8995cf08ec235a47&v=4
url: https://github.com/adriangb
- login: jgould22
count: 40
avatarUrl: https://avatars.githubusercontent.com/u/4335847?u=ed77f67e0bb069084639b24d812dbb2a2b1dc554&v=4
url: https://github.com/jgould22
- login: includeamin
count: 39
count: 40
avatarUrl: https://avatars.githubusercontent.com/u/11836741?u=8bd5ef7e62fe6a82055e33c4c0e0a7879ff8cfb6&v=4
url: https://github.com/includeamin
- login: STeveShary
count: 37
avatarUrl: https://avatars.githubusercontent.com/u/5167622?u=de8f597c81d6336fcebc37b32dfd61a3f877160c&v=4
url: https://github.com/STeveShary
- 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
count: 35
avatarUrl: https://avatars.githubusercontent.com/u/31960541?u=47f4829c77f4962ab437ffb7995951e41eeebe9b&v=4
url: https://github.com/krishnardt
- login: yinziyan1206
count: 34
avatarUrl: https://avatars.githubusercontent.com/u/37829370?u=da44ca53aefd5c23f346fab8e9fd2e108294c179&v=4
url: https://github.com/yinziyan1206
- login: chbndrhnns
count: 30
count: 34
avatarUrl: https://avatars.githubusercontent.com/u/7534547?v=4
url: https://github.com/chbndrhnns
- login: wshayes
count: 29
avatarUrl: https://avatars.githubusercontent.com/u/365303?u=07ca03c5ee811eb0920e633cc3c3db73dbec1aa5&v=4
url: https://github.com/wshayes
- login: panla
count: 27
count: 32
avatarUrl: https://avatars.githubusercontent.com/u/41326348?u=ba2fda6b30110411ecbf406d187907e2b420ac19&v=4
url: https://github.com/panla
- login: acidjunk
count: 25
avatarUrl: https://avatars.githubusercontent.com/u/685002?u=b5094ab4527fc84b006c0ac9ff54367bdebb2267&v=4
url: https://github.com/acidjunk
- login: ghandic
count: 25
avatarUrl: https://avatars.githubusercontent.com/u/23500353?u=e2e1d736f924d9be81e8bfc565b6d8836ba99773&v=4
url: https://github.com/ghandic
- login: prostomarkeloff
count: 28
avatarUrl: https://avatars.githubusercontent.com/u/28061158?u=72309cc1f2e04e40fa38b29969cb4e9d3f722e7b&v=4
url: https://github.com/prostomarkeloff
- login: dbanty
count: 25
count: 26
avatarUrl: https://avatars.githubusercontent.com/u/43723790?u=9bcce836bbce55835291c5b2ac93a4e311f4b3c3&v=4
url: https://github.com/dbanty
- login: wshayes
count: 25
avatarUrl: https://avatars.githubusercontent.com/u/365303?u=07ca03c5ee811eb0920e633cc3c3db73dbec1aa5&v=4
url: https://github.com/wshayes
- login: SirTelemak
count: 24
count: 23
avatarUrl: https://avatars.githubusercontent.com/u/9435877?u=719327b7d2c4c62212456d771bfa7c6b8dbb9eac&v=4
url: https://github.com/SirTelemak
- login: acnebs
count: 22
avatarUrl: https://avatars.githubusercontent.com/u/9054108?u=c27e50269f1ef8ea950cc6f0268c8ec5cebbe9c9&v=4
url: https://github.com/acnebs
- login: caeser1996
count: 21
avatarUrl: https://avatars.githubusercontent.com/u/16540232?u=05d2beb8e034d584d0a374b99d8826327bd7f614&v=4
url: https://github.com/caeser1996
- login: rafsaf
count: 21
avatarUrl: https://avatars.githubusercontent.com/u/51059348?u=f8f0d6d6e90fac39fa786228158ba7f013c74271&v=4
url: https://github.com/rafsaf
- login: nsidnev
count: 22
count: 20
avatarUrl: https://avatars.githubusercontent.com/u/22559461?u=a9cc3238217e21dc8796a1a500f01b722adb082c&v=4
url: https://github.com/nsidnev
- login: acnebs
count: 20
avatarUrl: https://avatars.githubusercontent.com/u/9054108?u=c27e50269f1ef8ea950cc6f0268c8ec5cebbe9c9&v=4
url: https://github.com/acnebs
- login: chris-allnutt
count: 21
count: 20
avatarUrl: https://avatars.githubusercontent.com/u/565544?v=4
url: https://github.com/chris-allnutt
- login: retnikt
count: 19
count: 18
avatarUrl: https://avatars.githubusercontent.com/u/24581770?v=4
url: https://github.com/retnikt
- login: odiseo0
count: 19
avatarUrl: https://avatars.githubusercontent.com/u/87550035?u=ab724eae71c3fe1cf81e8dc76e73415da926ef7d&v=4
url: https://github.com/odiseo0
- login: Hultner
- login: zoliknemet
count: 18
avatarUrl: https://avatars.githubusercontent.com/u/2669034?u=115e53df959309898ad8dc9443fbb35fee71df07&v=4
url: https://github.com/Hultner
- login: rafsaf
count: 18
avatarUrl: https://avatars.githubusercontent.com/u/51059348?u=f8f0d6d6e90fac39fa786228158ba7f013c74271&v=4
url: https://github.com/rafsaf
- login: jorgerpo
count: 17
avatarUrl: https://avatars.githubusercontent.com/u/12537771?u=7444d20019198e34911082780cc7ad73f2b97cb3&v=4
url: https://github.com/jorgerpo
avatarUrl: https://avatars.githubusercontent.com/u/22326718?u=31ba446ac290e23e56eea8e4f0c558aaf0b40779&v=4
url: https://github.com/zoliknemet
- login: nkhitrov
count: 17
avatarUrl: https://avatars.githubusercontent.com/u/28262306?u=66ee21316275ef356081c2efc4ed7a4572e690dc&v=4
@@ -153,75 +161,79 @@ experts:
count: 17
avatarUrl: https://avatars.githubusercontent.com/u/1765494?u=5b1ab7c582db4b4016fa31affe977d10af108ad4&v=4
url: https://github.com/harunyasar
- login: waynerv
- login: Hultner
count: 17
avatarUrl: https://avatars.githubusercontent.com/u/2669034?u=115e53df959309898ad8dc9443fbb35fee71df07&v=4
url: https://github.com/Hultner
- login: jonatasoli
count: 16
avatarUrl: https://avatars.githubusercontent.com/u/39515546?u=ec35139777597cdbbbddda29bf8b9d4396b429a9&v=4
url: https://github.com/waynerv
avatarUrl: https://avatars.githubusercontent.com/u/26334101?u=071c062d2861d3dd127f6b4a5258cd8ef55d4c50&v=4
url: https://github.com/jonatasoli
- login: dstlny
count: 16
avatarUrl: https://avatars.githubusercontent.com/u/41964673?u=9f2174f9d61c15c6e3a4c9e3aeee66f711ce311f&v=4
url: https://github.com/dstlny
- login: jonatasoli
- login: jorgerpo
count: 15
avatarUrl: https://avatars.githubusercontent.com/u/26334101?u=071c062d2861d3dd127f6b4a5258cd8ef55d4c50&v=4
url: https://github.com/jonatasoli
avatarUrl: https://avatars.githubusercontent.com/u/12537771?u=7444d20019198e34911082780cc7ad73f2b97cb3&v=4
url: https://github.com/jorgerpo
- login: ghost
count: 15
avatarUrl: https://avatars.githubusercontent.com/u/10137?u=b1951d34a583cf12ec0d3b0781ba19be97726318&v=4
url: https://github.com/ghost
- login: simondale00
count: 15
avatarUrl: https://avatars.githubusercontent.com/u/33907262?v=4
url: https://github.com/simondale00
- login: hellocoldworld
count: 14
avatarUrl: https://avatars.githubusercontent.com/u/47581948?u=3d2186796434c507a6cb6de35189ab0ad27c356f&v=4
url: https://github.com/hellocoldworld
- login: haizaar
- login: waynerv
count: 14
avatarUrl: https://avatars.githubusercontent.com/u/39515546?u=ec35139777597cdbbbddda29bf8b9d4396b429a9&v=4
url: https://github.com/waynerv
- login: mbroton
count: 13
avatarUrl: https://avatars.githubusercontent.com/u/58201?u=4f1f9843d69433ca0d380d95146cfe119e5fdac4&v=4
url: https://github.com/haizaar
- login: valentin994
count: 13
avatarUrl: https://avatars.githubusercontent.com/u/42819267?u=fdeeaa9242a59b243f8603496b00994f6951d5a2&v=4
url: https://github.com/valentin994
- 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: n8sty
count: 12
avatarUrl: https://avatars.githubusercontent.com/u/2964996?v=4
url: https://github.com/n8sty
- 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
url: https://github.com/zamiramir
avatarUrl: https://avatars.githubusercontent.com/u/50829834?u=a48610bf1bffaa9c75d03228926e2eb08a2e24ee&v=4
url: https://github.com/mbroton
last_month_active:
- login: JarroVGIT
count: 30
avatarUrl: https://avatars.githubusercontent.com/u/13659033?u=e8bea32d07a5ef72f7dde3b2079ceb714923ca05&v=4
url: https://github.com/JarroVGIT
- login: zoliknemet
count: 9
avatarUrl: https://avatars.githubusercontent.com/u/22326718?u=31ba446ac290e23e56eea8e4f0c558aaf0b40779&v=4
url: https://github.com/zoliknemet
- login: iudeen
count: 5
avatarUrl: https://avatars.githubusercontent.com/u/10519440?u=2843b3303282bff8b212dcd4d9d6689452e4470c&v=4
url: https://github.com/iudeen
- login: mr-st0rm
count: 7
avatarUrl: https://avatars.githubusercontent.com/u/48455163?u=6b83550e4e70bea57cd2fdb41e717aeab7f64a91&v=4
url: https://github.com/mr-st0rm
- login: caeser1996
count: 7
avatarUrl: https://avatars.githubusercontent.com/u/16540232?u=05d2beb8e034d584d0a374b99d8826327bd7f614&v=4
url: https://github.com/caeser1996
- login: ebottos94
count: 6
avatarUrl: https://avatars.githubusercontent.com/u/100039558?u=e2c672da5a7977fd24d87ce6ab35f8bf5b1ed9fa&v=4
url: https://github.com/ebottos94
- login: jgould22
count: 6
avatarUrl: https://avatars.githubusercontent.com/u/4335847?u=ed77f67e0bb069084639b24d812dbb2a2b1dc554&v=4
url: https://github.com/jgould22
- login: Kludex
count: 5
avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=62adc405ef418f4b6c8caa93d3eb8ab107bc4927&v=4
url: https://github.com/Kludex
- login: odiseo0
- login: clemens-tolboom
count: 4
avatarUrl: https://avatars.githubusercontent.com/u/87550035?u=ab724eae71c3fe1cf81e8dc76e73415da926ef7d&v=4
url: https://github.com/odiseo0
- login: jonatasoli
avatarUrl: https://avatars.githubusercontent.com/u/371014?v=4
url: https://github.com/clemens-tolboom
- login: williamjamir
count: 4
avatarUrl: https://avatars.githubusercontent.com/u/5083518?u=b76ca8e08b906a86fa195fb817dd94e8d9d3d8f6&v=4
url: https://github.com/williamjamir
- login: nymous
count: 3
avatarUrl: https://avatars.githubusercontent.com/u/26334101?u=071c062d2861d3dd127f6b4a5258cd8ef55d4c50&v=4
url: https://github.com/jonatasoli
avatarUrl: https://avatars.githubusercontent.com/u/4216559?u=360a36fb602cded27273cbfc0afc296eece90662&v=4
url: https://github.com/nymous
- login: frankie567
count: 3
avatarUrl: https://avatars.githubusercontent.com/u/1144727?u=85c025e3fcc7bd79a5665c63ee87cdf8aae13374&v=4
url: https://github.com/frankie567
top_contributors:
- login: waynerv
count: 25
@@ -231,14 +243,18 @@ top_contributors:
count: 22
avatarUrl: https://avatars.githubusercontent.com/u/41147016?u=55010621aece725aa702270b54fed829b6a1fe60&v=4
url: https://github.com/tokusumi
- login: Kludex
count: 17
avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=62adc405ef418f4b6c8caa93d3eb8ab107bc4927&v=4
url: https://github.com/Kludex
- login: jaystone776
count: 17
avatarUrl: https://avatars.githubusercontent.com/u/11191137?u=299205a95e9b6817a43144a48b643346a5aac5cc&v=4
url: https://github.com/jaystone776
- login: dmontagu
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
@@ -247,10 +263,6 @@ top_contributors:
count: 12
avatarUrl: https://avatars.githubusercontent.com/u/11489395?u=4adb6986bf3debfc2b8216ae701f2bd47d73da7d&v=4
url: https://github.com/mariacamilagl
- login: Kludex
count: 11
avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=62adc405ef418f4b6c8caa93d3eb8ab107bc4927&v=4
url: https://github.com/Kludex
- login: Smlep
count: 10
avatarUrl: https://avatars.githubusercontent.com/u/16785985?v=4
@@ -261,12 +273,20 @@ top_contributors:
url: https://github.com/Serrones
- login: RunningIkkyu
count: 7
avatarUrl: https://avatars.githubusercontent.com/u/31848542?u=efb5b45b55584450507834f279ce48d4d64dea2f&v=4
avatarUrl: https://avatars.githubusercontent.com/u/31848542?u=494ecc298e3f26197495bb357ad0f57cfd5f7a32&v=4
url: https://github.com/RunningIkkyu
- login: hard-coders
count: 7
avatarUrl: https://avatars.githubusercontent.com/u/9651103?u=95db33927bbff1ed1c07efddeb97ac2ff33068ed&v=4
url: https://github.com/hard-coders
- login: rjNemo
count: 7
avatarUrl: https://avatars.githubusercontent.com/u/56785022?u=d5c3a02567c8649e146fcfc51b6060ccaf8adef8&v=4
url: https://github.com/rjNemo
- login: batlopes
count: 6
avatarUrl: https://avatars.githubusercontent.com/u/33462923?u=0fb3d7acb316764616f11e4947faf080e49ad8d9&v=4
url: https://github.com/batlopes
- login: wshayes
count: 5
avatarUrl: https://avatars.githubusercontent.com/u/365303?u=07ca03c5ee811eb0920e633cc3c3db73dbec1aa5&v=4
@@ -279,21 +299,33 @@ top_contributors:
count: 5
avatarUrl: https://avatars.githubusercontent.com/u/1175560?v=4
url: https://github.com/Attsun1031
- login: dependabot
- login: ComicShrimp
count: 5
avatarUrl: https://avatars.githubusercontent.com/in/29110?v=4
url: https://github.com/apps/dependabot
avatarUrl: https://avatars.githubusercontent.com/u/43503750?u=f440bc9062afb3c43b9b9c6cdfdcfe31d58699ef&v=4
url: https://github.com/ComicShrimp
- login: NinaHwang
count: 5
avatarUrl: https://avatars.githubusercontent.com/u/79563565?u=eee6bfe9224c71193025ab7477f4f96ceaa05c62&v=4
url: https://github.com/NinaHwang
- login: Xewus
count: 5
avatarUrl: https://avatars.githubusercontent.com/u/85196001?u=f8e2dc7e5104f109cef944af79050ea8d1b8f914&v=4
url: https://github.com/Xewus
- login: jekirl
count: 4
avatarUrl: https://avatars.githubusercontent.com/u/2546697?u=a027452387d85bd4a14834e19d716c99255fb3b7&v=4
url: https://github.com/jekirl
- login: samuelcolvin
count: 4
avatarUrl: https://avatars.githubusercontent.com/u/4039449?u=807390ba9cfe23906c3bf8a0d56aaca3cf2bfa0d&v=4
url: https://github.com/samuelcolvin
- login: jfunez
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
avatarUrl: https://avatars.githubusercontent.com/u/62724709?u=bba5af018423a2858d49309bed2a899bb5c34ac5&v=4
url: https://github.com/ycd
- login: komtaki
count: 4
@@ -307,21 +339,21 @@ top_contributors:
count: 4
avatarUrl: https://avatars.githubusercontent.com/u/61513630?u=320e43fe4dc7bc6efc64e9b8f325f8075634fd20&v=4
url: https://github.com/lsglucas
- login: ComicShrimp
count: 4
avatarUrl: https://avatars.githubusercontent.com/u/43503750?u=b3e4d9a14d9a65d429ce62c566aef73178b7111d&v=4
url: https://github.com/ComicShrimp
- 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: 95
count: 111
avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=62adc405ef418f4b6c8caa93d3eb8ab107bc4927&v=4
url: https://github.com/Kludex
- login: BilalAlpaslan
count: 75
avatarUrl: https://avatars.githubusercontent.com/u/47563997?u=63ed66e304fe8d765762c70587d61d9196e5c82d&v=4
url: https://github.com/BilalAlpaslan
- login: yezz123
count: 71
avatarUrl: https://avatars.githubusercontent.com/u/52716203?u=636b4f79645176df4527dd45c12d5dbb5a4193cf&v=4
url: https://github.com/yezz123
- login: tokusumi
count: 49
count: 51
avatarUrl: https://avatars.githubusercontent.com/u/41147016?u=55010621aece725aa702270b54fed829b6a1fe60&v=4
url: https://github.com/tokusumi
- login: waynerv
@@ -332,22 +364,22 @@ top_reviewers:
count: 47
avatarUrl: https://avatars.githubusercontent.com/u/59285379?v=4
url: https://github.com/Laineyzhang55
- login: BilalAlpaslan
count: 45
avatarUrl: https://avatars.githubusercontent.com/u/47563997?u=63ed66e304fe8d765762c70587d61d9196e5c82d&v=4
url: https://github.com/BilalAlpaslan
- login: ycd
count: 45
avatarUrl: https://avatars.githubusercontent.com/u/62724709?u=826f228edf0bab0d19ad1d5c4ba4df1047ccffef&v=4
avatarUrl: https://avatars.githubusercontent.com/u/62724709?u=bba5af018423a2858d49309bed2a899bb5c34ac5&v=4
url: https://github.com/ycd
- login: iudeen
count: 44
avatarUrl: https://avatars.githubusercontent.com/u/10519440?u=2843b3303282bff8b212dcd4d9d6689452e4470c&v=4
url: https://github.com/iudeen
- login: cikay
count: 41
avatarUrl: https://avatars.githubusercontent.com/u/24587499?u=e772190a051ab0eaa9c8542fcff1892471638f2b&v=4
url: https://github.com/cikay
- login: yezz123
- login: JarroVGIT
count: 34
avatarUrl: https://avatars.githubusercontent.com/u/52716203?u=636b4f79645176df4527dd45c12d5dbb5a4193cf&v=4
url: https://github.com/yezz123
avatarUrl: https://avatars.githubusercontent.com/u/13659033?u=e8bea32d07a5ef72f7dde3b2079ceb714923ca05&v=4
url: https://github.com/JarroVGIT
- login: AdrianDeAnda
count: 33
avatarUrl: https://avatars.githubusercontent.com/u/1024932?u=b2ea249c6b41ddf98679c8d110d0f67d4a3ebf93&v=4
@@ -357,33 +389,45 @@ top_reviewers:
avatarUrl: https://avatars.githubusercontent.com/u/31127044?u=b0f2c37142f4b762e41ad65dc49581813422bd71&v=4
url: https://github.com/ArcLightSlavik
- login: cassiobotaro
count: 25
count: 28
avatarUrl: https://avatars.githubusercontent.com/u/3127847?u=b0a652331da17efeb85cd6e3a4969182e5004804&v=4
url: https://github.com/cassiobotaro
- login: komtaki
count: 27
avatarUrl: https://avatars.githubusercontent.com/u/39375566?u=260ad6b1a4b34c07dbfa728da5e586f16f6d1824&v=4
url: https://github.com/komtaki
- login: lsglucas
count: 26
avatarUrl: https://avatars.githubusercontent.com/u/61513630?u=320e43fe4dc7bc6efc64e9b8f325f8075634fd20&v=4
url: https://github.com/lsglucas
- login: dmontagu
count: 23
avatarUrl: https://avatars.githubusercontent.com/u/35119617?u=58ed2a45798a4339700e2f62b2e12e6e54bf0396&v=4
url: https://github.com/dmontagu
- login: komtaki
count: 21
avatarUrl: https://avatars.githubusercontent.com/u/39375566?u=260ad6b1a4b34c07dbfa728da5e586f16f6d1824&v=4
url: https://github.com/komtaki
- login: LorhanSohaky
count: 22
avatarUrl: https://avatars.githubusercontent.com/u/16273730?u=095b66f243a2cd6a0aadba9a095009f8aaf18393&v=4
url: https://github.com/LorhanSohaky
- login: rjNemo
count: 20
avatarUrl: https://avatars.githubusercontent.com/u/56785022?u=d5c3a02567c8649e146fcfc51b6060ccaf8adef8&v=4
url: https://github.com/rjNemo
- login: hard-coders
count: 19
count: 20
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: lsglucas
count: 18
avatarUrl: https://avatars.githubusercontent.com/u/61513630?u=320e43fe4dc7bc6efc64e9b8f325f8075634fd20&v=4
url: https://github.com/lsglucas
- login: JarroVGIT
count: 18
avatarUrl: https://avatars.githubusercontent.com/u/13659033?u=e8bea32d07a5ef72f7dde3b2079ceb714923ca05&v=4
url: https://github.com/JarroVGIT
- login: odiseo0
count: 19
avatarUrl: https://avatars.githubusercontent.com/u/87550035?u=16f9255804161c6ff3c8b7ef69848f0126bcd405&v=4
url: https://github.com/odiseo0
- login: Smlep
count: 17
avatarUrl: https://avatars.githubusercontent.com/u/16785985?v=4
url: https://github.com/Smlep
- login: zy7y
count: 17
avatarUrl: https://avatars.githubusercontent.com/u/67154681?u=5d634834cc514028ea3f9115f7030b99a1f4d5a4&v=4
@@ -396,14 +440,6 @@ top_reviewers:
count: 16
avatarUrl: https://avatars.githubusercontent.com/u/52768429?u=6a3aa15277406520ad37f6236e89466ed44bc5b8&v=4
url: https://github.com/SwftAlpc
- login: rjNemo
count: 16
avatarUrl: https://avatars.githubusercontent.com/u/56785022?u=d5c3a02567c8649e146fcfc51b6060ccaf8adef8&v=4
url: https://github.com/rjNemo
- login: Smlep
count: 16
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
@@ -416,13 +452,25 @@ top_reviewers:
count: 15
avatarUrl: https://avatars.githubusercontent.com/u/63476957?u=6c86e59b48e0394d4db230f37fc9ad4d7e2c27c7&v=4
url: https://github.com/delhi09
- login: Ryandaydev
count: 15
avatarUrl: https://avatars.githubusercontent.com/u/4292423?u=809f3d1074d04bbc28012a7f17f06ea56f5bd71a&v=4
url: https://github.com/Ryandaydev
- login: Xewus
count: 14
avatarUrl: https://avatars.githubusercontent.com/u/85196001?u=f8e2dc7e5104f109cef944af79050ea8d1b8f914&v=4
url: https://github.com/Xewus
- login: sh0nk
count: 13
avatarUrl: https://avatars.githubusercontent.com/u/6478810?u=af15d724875cec682ed8088a86d36b2798f981c0&v=4
url: https://github.com/sh0nk
- login: peidrao
count: 13
avatarUrl: https://avatars.githubusercontent.com/u/32584628?u=5401640e0b961cc199dee39ec79e162c7833cd6b&v=4
url: https://github.com/peidrao
- login: RunningIkkyu
count: 12
avatarUrl: https://avatars.githubusercontent.com/u/31848542?u=efb5b45b55584450507834f279ce48d4d64dea2f&v=4
avatarUrl: https://avatars.githubusercontent.com/u/31848542?u=494ecc298e3f26197495bb357ad0f57cfd5f7a32&v=4
url: https://github.com/RunningIkkyu
- login: solomein-sv
count: 11
@@ -440,13 +488,21 @@ top_reviewers:
count: 10
avatarUrl: https://avatars.githubusercontent.com/u/7887703?v=4
url: https://github.com/maoyibo
- login: odiseo0
- login: ComicShrimp
count: 10
avatarUrl: https://avatars.githubusercontent.com/u/87550035?u=ab724eae71c3fe1cf81e8dc76e73415da926ef7d&v=4
url: https://github.com/odiseo0
avatarUrl: https://avatars.githubusercontent.com/u/43503750?u=f440bc9062afb3c43b9b9c6cdfdcfe31d58699ef&v=4
url: https://github.com/ComicShrimp
- login: r0b2g1t
count: 10
avatarUrl: https://avatars.githubusercontent.com/u/5357541?u=6428442d875d5d71aaa1bb38bb11c4be1a526bc2&v=4
url: https://github.com/r0b2g1t
- login: izaguerreiro
count: 9
avatarUrl: https://avatars.githubusercontent.com/u/2241504?v=4
url: https://github.com/izaguerreiro
- login: graingert
count: 9
avatarUrl: https://avatars.githubusercontent.com/u/413772?v=4
avatarUrl: https://avatars.githubusercontent.com/u/413772?u=64b77b6aa405c68a9c6bcf45f84257c66eea5f32&v=4
url: https://github.com/graingert
- login: PandaHun
count: 9
@@ -460,10 +516,18 @@ top_reviewers:
count: 9
avatarUrl: https://avatars.githubusercontent.com/u/69092910?u=4ac58eab99bd37d663f3d23551df96d4fbdbf760&v=4
url: https://github.com/bezaca
- login: dimaqq
count: 9
avatarUrl: https://avatars.githubusercontent.com/u/662249?v=4
url: https://github.com/dimaqq
- login: raphaelauv
count: 8
avatarUrl: https://avatars.githubusercontent.com/u/10202690?u=e6f86f5c0c3026a15d6b51792fa3e532b12f1371&v=4
url: https://github.com/raphaelauv
- login: axel584
count: 8
avatarUrl: https://avatars.githubusercontent.com/u/1334088?v=4
url: https://github.com/axel584
- login: blt232018
count: 8
avatarUrl: https://avatars.githubusercontent.com/u/43393471?u=172b0e0391db1aa6c1706498d6dfcb003c8a4857&v=4
@@ -472,43 +536,3 @@ top_reviewers:
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
url: https://github.com/Serrones
- login: ryuckel
count: 7
avatarUrl: https://avatars.githubusercontent.com/u/36391432?u=094eec0cfddd5013f76f31e55e56147d78b19553&v=4
url: https://github.com/ryuckel
- login: NastasiaSaby
count: 7
avatarUrl: https://avatars.githubusercontent.com/u/8245071?u=b3afd005f9e4bf080c219ef61a592b3a8004b764&v=4
url: https://github.com/NastasiaSaby
- login: Mause
count: 7
avatarUrl: https://avatars.githubusercontent.com/u/1405026?v=4
url: https://github.com/Mause
- login: wakabame
count: 7
avatarUrl: https://avatars.githubusercontent.com/u/35513518?v=4
url: https://github.com/wakabame
- login: AlexandreBiguet
count: 7
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/34248814?v=4
url: https://github.com/krocdort

View File

@@ -8,12 +8,6 @@ gold:
- 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://app.imgwhale.xyz/
title: The ultimate solution to unlimited and forever cloud storage.
img: https://fastapi.tiangolo.com/img/sponsors/imgwhale.svg
- url: https://doist.com/careers/9B437B1615-wa-senior-backend-engineer-python
title: Help us migrate doist to FastAPI
img: https://fastapi.tiangolo.com/img/sponsors/doist.svg
silver:
- url: https://www.deta.sh/?ref=fastapi
title: The launchpad for all your (team's) ideas
@@ -33,9 +27,12 @@ silver:
- 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
- url: https://careers.powens.com/
title: Powens is hiring!
img: https://fastapi.tiangolo.com/img/sponsors/powens.png
- url: https://www.svix.com/
title: Svix - Webhooks as a service
img: https://fastapi.tiangolo.com/img/sponsors/svix.svg
bronze:
- url: https://www.exoflare.com/open-source/?utm_source=FastAPI&utm_campaign=open_source
title: Biosecurity risk assessments made easy.

View File

@@ -13,3 +13,6 @@ logins:
- BLUE-DEVIL1134
- ObliviousAI
- Doist
- nihpo
- svix
- armand-sauzay

View File

@@ -23,7 +23,7 @@ Each of those response `dict`s can have a key `model`, containing a Pydantic mod
For example, to declare another response with a status code `404` and a Pydantic model `Message`, you can write:
```Python hl_lines="18 23"
```Python hl_lines="18 22"
{!../../../docs_src/additional_responses/tutorial001.py!}
```

View File

@@ -14,9 +14,41 @@ But you also want it to accept new items. And when the items didn't exist before
To achieve that, import `JSONResponse`, and return your content there directly, setting the `status_code` that you want:
```Python hl_lines="4 25"
{!../../../docs_src/additional_status_codes/tutorial001.py!}
```
=== "Python 3.10+"
```Python hl_lines="4 25"
{!> ../../../docs_src/additional_status_codes/tutorial001_an_py310.py!}
```
=== "Python 3.9+"
```Python hl_lines="4 25"
{!> ../../../docs_src/additional_status_codes/tutorial001_an_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="4 26"
{!> ../../../docs_src/additional_status_codes/tutorial001_an.py!}
```
=== "Python 3.10+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="2 23"
{!> ../../../docs_src/additional_status_codes/tutorial001_py310.py!}
```
=== "Python 3.6+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="4 25"
{!> ../../../docs_src/additional_status_codes/tutorial001.py!}
```
!!! warning
When you return a `Response` directly, like in the example above, it will be returned directly.

View File

@@ -18,9 +18,26 @@ Not the class itself (which is already a callable), but an instance of that clas
To do that, we declare a method `__call__`:
```Python hl_lines="10"
{!../../../docs_src/dependencies/tutorial011.py!}
```
=== "Python 3.9+"
```Python hl_lines="12"
{!> ../../../docs_src/dependencies/tutorial011_an_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="11"
{!> ../../../docs_src/dependencies/tutorial011_an.py!}
```
=== "Python 3.6+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="10"
{!> ../../../docs_src/dependencies/tutorial011.py!}
```
In this case, this `__call__` is what **FastAPI** will use to check for additional parameters and sub-dependencies, and this is what will be called to pass a value to the parameter in your *path operation function* later.
@@ -28,9 +45,26 @@ In this case, this `__call__` is what **FastAPI** will use to check for addition
And now, we can use `__init__` to declare the parameters of the instance that we can use to "parameterize" the dependency:
```Python hl_lines="7"
{!../../../docs_src/dependencies/tutorial011.py!}
```
=== "Python 3.9+"
```Python hl_lines="9"
{!> ../../../docs_src/dependencies/tutorial011_an_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="8"
{!> ../../../docs_src/dependencies/tutorial011_an.py!}
```
=== "Python 3.6+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="7"
{!> ../../../docs_src/dependencies/tutorial011.py!}
```
In this case, **FastAPI** won't ever touch or care about `__init__`, we will use it directly in our code.
@@ -38,9 +72,26 @@ In this case, **FastAPI** won't ever touch or care about `__init__`, we will use
We could create an instance of this class with:
```Python hl_lines="16"
{!../../../docs_src/dependencies/tutorial011.py!}
```
=== "Python 3.9+"
```Python hl_lines="18"
{!> ../../../docs_src/dependencies/tutorial011_an_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="17"
{!> ../../../docs_src/dependencies/tutorial011_an.py!}
```
=== "Python 3.6+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="16"
{!> ../../../docs_src/dependencies/tutorial011.py!}
```
And that way we are able to "parameterize" our dependency, that now has `"bar"` inside of it, as the attribute `checker.fixed_content`.
@@ -56,9 +107,26 @@ checker(q="somequery")
...and pass whatever that returns as the value of the dependency in our *path operation function* as the parameter `fixed_content_included`:
```Python hl_lines="20"
{!../../../docs_src/dependencies/tutorial011.py!}
```
=== "Python 3.9+"
```Python hl_lines="22"
{!> ../../../docs_src/dependencies/tutorial011_an_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="21"
{!> ../../../docs_src/dependencies/tutorial011_an.py!}
```
=== "Python 3.6+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="20"
{!> ../../../docs_src/dependencies/tutorial011.py!}
```
!!! tip
All this might seem contrived. And it might not be very clear how is it useful yet.

View File

@@ -1,6 +1,6 @@
# Async Tests
You have already seen how to test your **FastAPI** applications using the provided `TestClient`, but with it, you can't test or run any other `async` function in your (synchronous) pytest functions.
You have already seen how to test your **FastAPI** applications using the provided `TestClient`. Up to now, you have only seen how to write synchronous tests, without using `async` functions.
Being able to use asynchronous functions in your tests could be useful, for example, when you're querying your database asynchronously. Imagine you want to test sending requests to your FastAPI application and then verify that your backend successfully wrote the correct data in the database, while using an async database library.
@@ -8,7 +8,7 @@ Let's look at how we can make that work.
## pytest.mark.anyio
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.
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
@@ -16,23 +16,27 @@ Even if your **FastAPI** application uses normal `def` functions instead of `asy
The `TestClient` does some magic inside to call the asynchronous FastAPI application in your normal `def` test functions, using standard pytest. But that magic doesn't work anymore when we're using it inside asynchronous functions. By running our tests asynchronously, we can no longer use the `TestClient` inside our test functions.
Luckily there's a nice alternative, called <a href="https://www.python-httpx.org/" class="external-link" target="_blank">HTTPX</a>.
HTTPX is an HTTP client for Python 3 that allows us to query our FastAPI application similarly to how we did it with the `TestClient`.
If you're familiar with the <a href="https://requests.readthedocs.io/en/master/" class="external-link" target="_blank">Requests</a> library, you'll find that the API of HTTPX is almost identical.
The important difference for us is that with HTTPX we are not limited to synchronous, but can also make asynchronous requests.
The `TestClient` is based on <a href="https://www.python-httpx.org" class="external-link" target="_blank">HTTPX</a>, and luckily, we can use it directly to test the API.
## Example
For a simple example, let's consider the following `main.py` module:
For a simple example, let's consider a file structure similar to the one described in [Bigger Applications](../tutorial/bigger-applications.md){.internal-link target=_blank} and [Testing](../tutorial/testing.md){.internal-link target=_blank}:
```
.
├── app
│   ├── __init__.py
│   ├── main.py
│   └── test_main.py
```
The file `main.py` would have:
```Python
{!../../../docs_src/async_tests/main.py!}
```
The `test_main.py` module that contains the tests for `main.py` could look like this now:
The file `test_main.py` would have the tests for `main.py`, it could look like this now:
```Python
{!../../../docs_src/async_tests/test_main.py!}
@@ -75,7 +79,7 @@ This is the equivalent to:
response = client.get('/')
```
that we used to make our requests with the `TestClient`.
...that we used to make our requests with the `TestClient`.
!!! tip
Note that we're using async/await with the new `AsyncClient` - the request is asynchronous.

View File

@@ -21,6 +21,12 @@ For example, if you are squeezing performance, you can install and use <a href="
Import the `Response` class (sub-class) you want to use and declare it in the *path operation decorator*.
For large responses, returning a `Response` directly is much faster than returning a dictionary.
This is because by default, FastAPI will inspect every item inside and make sure it is serializable with JSON, using the same [JSON Compatible Encoder](../tutorial/encoder.md){.internal-link target=_blank} explained in the tutorial. This is what allows you to return **arbitrary objects**, for example database models.
But if you are certain that the content that you are returning is **serializable with JSON**, you can pass it directly to the response class and avoid the extra overhead that FastAPI would have by passing your return content through the `jsonable_encoder` before passing it to the response class.
```Python hl_lines="2 7"
{!../../../docs_src/custom_response/tutorial001b.py!}
```
@@ -244,6 +250,36 @@ You can also use the `response_class` parameter:
In this case, you can return the file path directly from your *path operation* function.
## Custom response class
You can create your own custom response class, inheriting from `Response` and using it.
For example, let's say that you want to use <a href="https://github.com/ijl/orjson" class="external-link" target="_blank">`orjson`</a>, but with some custom settings not used in the included `ORJSONResponse` class.
Let's say you want it to return indented and formatted JSON, so you want to use the orjson option `orjson.OPT_INDENT_2`.
You could create a `CustomORJSONResponse`. The main thing you have to do is create a `Response.render(content)` method that returns the content as `bytes`:
```Python hl_lines="9-14 17"
{!../../../docs_src/custom_response/tutorial009c.py!}
```
Now instead of returning:
```json
{"message": "Hello World"}
```
...this response will return:
```json
{
"message": "Hello World"
}
```
Of course, you will probably find much better ways to take advantage of this than formatting JSON. 😉
## Default response class
When creating a **FastAPI** class instance or an `APIRouter` you can specify which response class to use by default.

View File

@@ -8,7 +8,7 @@ But FastAPI also supports using <a href="https://docs.python.org/3/library/datac
{!../../../docs_src/dataclasses/tutorial001.py!}
```
This is still thanks to **Pydantic**, as it has <a href="https://pydantic-docs.helpmanual.io/usage/dataclasses/#use-of-stdlib-dataclasses-with-basemodel" class="external-link" target="_blank">internal support for `dataclasses`</a>.
This is still supported thanks to **Pydantic**, as it has <a href="https://pydantic-docs.helpmanual.io/usage/dataclasses/#use-of-stdlib-dataclasses-with-basemodel" class="external-link" target="_blank">internal support for `dataclasses`</a>.
So, even with the code above that doesn't use Pydantic explicitly, FastAPI is using Pydantic to convert those standard dataclasses to Pydantic's own flavor of dataclasses.

View File

@@ -1,13 +1,108 @@
# Events: startup - shutdown
# Lifespan Events
You can define logic (code) that should be executed before the application **starts up**. This means that this code will be executed **once**, **before** the application **starts receiving requests**.
The same way, you can define logic (code) that should be executed when the application is **shutting down**. In this case, this code will be executed **once**, **after** having handled possibly **many requests**.
Because this code is executed before the application **starts** taking requests, and right after it **finishes** handling requests, it covers the whole application **lifespan** (the word "lifespan" will be important in a second 😉).
This can be very useful for setting up **resources** that you need to use for the whole app, and that are **shared** among requests, and/or that you need to **clean up** afterwards. For example, a database connection pool, or loading a shared machine learning model.
## Use Case
Let's start with an example **use case** and then see how to solve it with this.
Let's imagine that you have some **machine learning models** that you want to use to handle requests. 🤖
The same models are shared among requests, so, it's not one model per request, or one per user or something similar.
Let's imagine that loading the model can **take quite some time**, because it has to read a lot of **data from disk**. So you don't want to do it for every request.
You could load it at the top level of the module/file, but that would also mean that it would **load the model** even if you are just running a simple automated test, then that test would be **slow** because it would have to wait for the model to load before being able to run an independent part of the code.
That's what we'll solve, let's load the model before the requests are handled, but only right before the application starts receiving requests, not while the code is being loaded.
## Lifespan
You can define this *startup* and *shutdown* logic using the `lifespan` parameter of the `FastAPI` app, and a "context manager" (I'll show you what that is in a second).
Let's start with an example and then see it in detail.
We create an async function `lifespan()` with `yield` like this:
```Python hl_lines="16 19"
{!../../../docs_src/events/tutorial003.py!}
```
Here we are simulating the expensive *startup* operation of loading the model by putting the (fake) model function in the dictionary with machine learning models before the `yield`. This code will be executed **before** the application **starts taking requests**, during the *startup*.
And then, right after the `yield`, we unload the model. This code will be executed **after** the application **finishes handling requests**, right before the *shutdown*. This could, for example, release resources like memory or a GPU.
!!! tip
The `shutdown` would happen when you are **stopping** the application.
Maybe you need to start a new version, or you just got tired of running it. 🤷
### Lifespan function
The first thing to notice, is that we are defining an async function with `yield`. This is very similar to Dependencies with `yield`.
```Python hl_lines="14-19"
{!../../../docs_src/events/tutorial003.py!}
```
The first part of the function, before the `yield`, will be executed **before** the application starts.
And the part after the `yield` will be executed **after** the application has finished.
### Async Context Manager
If you check, the function is decorated with an `@asynccontextmanager`.
That converts the function into something called an "**async context manager**".
```Python hl_lines="1 13"
{!../../../docs_src/events/tutorial003.py!}
```
A **context manager** in Python is something that you can use in a `with` statement, for example, `open()` can be used as a context manager:
```Python
with open("file.txt") as file:
file.read()
```
In recent versions of Python, there's also an **async context manager**. You would use it with `async with`:
```Python
async with lifespan(app):
await do_stuff()
```
When you create a context manager or an async context manager like above, what it does is that, before entering the `with` block, it will execute the code before the `yield`, and after exiting the `with` block, it will execute the code after the `yield`.
In our code example above, we don't use it directly, but we pass it to FastAPI for it to use it.
The `lifespan` parameter of the `FastAPI` app takes an **async context manager**, so we can pass our new `lifespan` async context manager to it.
```Python hl_lines="22"
{!../../../docs_src/events/tutorial003.py!}
```
## Alternative Events (deprecated)
!!! warning
The recommended way to handle the *startup* and *shutdown* is using the `lifespan` parameter of the `FastAPI` app as described above.
You can probably skip this part.
There's an alternative way to define this logic to be executed during *startup* and during *shutdown*.
You can define event handlers (functions) that need to be executed before the application starts up, or when the application is shutting down.
These functions can be declared with `async def` or normal `def`.
!!! warning
Only event handlers for the main application will be executed, not for [Sub Applications - Mounts](./sub-applications.md){.internal-link target=_blank}.
## `startup` event
### `startup` event
To add a function that should be run before the application starts, declare it with the event `"startup"`:
@@ -21,7 +116,7 @@ You can add more than one event handler function.
And your application won't start receiving requests until all the `startup` event handlers have completed.
## `shutdown` event
### `shutdown` event
To add a function that should be run when the application is shutting down, declare it with the event `"shutdown"`:
@@ -43,5 +138,25 @@ Here, the `shutdown` event handler function will write a text line `"Application
So, we declare the event handler function with standard `def` instead of `async def`.
### `startup` and `shutdown` together
There's a high chance that the logic for your *startup* and *shutdown* is connected, you might want to start something and then finish it, acquire a resource and then release it, etc.
Doing that in separated functions that don't share logic or variables together is more difficult as you would need to store values in global variables or similar tricks.
Because of that, it's now recommended to instead use the `lifespan` as explained above.
## Technical Details
Just a technical detail for the curious nerds. 🤓
Underneath, in the ASGI technical specification, this is part of the <a href="https://asgi.readthedocs.io/en/latest/specs/lifespan.html" class="external-link" target="_blank">Lifespan Protocol</a>, and it defines events called `startup` and `shutdown`.
!!! info
You can read more about these event handlers in <a href="https://www.starlette.io/events/" class="external-link" target="_blank">Starlette's Events' docs</a>.
You can read more about the Starlette `lifespan` handlers in <a href="https://www.starlette.io/lifespan/" class="external-link" target="_blank">Starlette's Lifespan' docs</a>.
Including how to handle lifespan state that can be used in other areas of your code.
## Sub Applications
🚨 Have in mind that these lifespan events (startup and shutdown) will only be executed for the main application, not for [Sub Applications - Mounts](./sub-applications.md){.internal-link target=_blank}.

View File

@@ -16,18 +16,18 @@ If you are building a **frontend**, a very interesting alternative is <a href="h
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 3.9+"
```Python hl_lines="7-9 12-13 16-17 21"
{!> ../../../docs_src/generate_clients/tutorial001_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="9-11 14-15 18 19 23"
{!> ../../../docs_src/generate_clients/tutorial001.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
@@ -128,19 +128,18 @@ In many cases your FastAPI app will be bigger, and you will probably use tags to
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 3.9+"
```Python hl_lines="21 26 34"
{!> ../../../docs_src/generate_clients/tutorial002_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="23 28 36"
{!> ../../../docs_src/generate_clients/tutorial002.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.
@@ -186,18 +185,18 @@ For example, here it is using the first tag (you will probably have only one tag
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 3.9+"
```Python hl_lines="6-7 10"
{!> ../../../docs_src/generate_clients/tutorial003_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="8-9 12"
{!> ../../../docs_src/generate_clients/tutorial003.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:

View File

@@ -68,7 +68,7 @@ Enforces that all incoming requests have a correctly set `Host` header, in order
The following arguments are supported:
* `allowed_hosts` - A list of domain names that should be allowed as hostnames. Wildcard domains such as `*.example.com` are supported for matching subdomains to allow any hostname either use `allowed_hosts=["*"]` or omit the middleware.
* `allowed_hosts` - A list of domain names that should be allowed as hostnames. Wildcard domains such as `*.example.com` are supported for matching subdomains. To allow any hostname either use `allowed_hosts=["*"]` or omit the middleware.
If an incoming request does not validate correctly then a `400` response will be sent.
@@ -92,7 +92,7 @@ There are many other ASGI middlewares.
For example:
* <a href="https://docs.sentry.io/platforms/python/asgi/" class="external-link" target="_blank">Sentry</a>
* <a href="https://docs.sentry.io/platforms/python/guides/fastapi/" class="external-link" target="_blank">Sentry</a>
* <a href="https://github.com/encode/uvicorn/blob/master/uvicorn/middleware/proxy_headers.py" class="external-link" target="_blank">Uvicorn's `ProxyHeadersMiddleware`</a>
* <a href="https://github.com/florimondmanca/msgpack-asgi" class="external-link" target="_blank">MessagePack</a>

View File

@@ -31,7 +31,7 @@ It will have a *path operation* that will receive an `Invoice` body, and a query
This part is pretty normal, most of the code is probably already familiar to you:
```Python hl_lines="10-14 37-54"
```Python hl_lines="9-13 36-53"
{!../../../docs_src/openapi_callbacks/tutorial001.py!}
```
@@ -50,7 +50,7 @@ It could be just one or two lines of code, like:
```Python
callback_url = "https://example.com/api/v1/invoices/events/"
requests.post(callback_url, json={"description": "Invoice paid", "paid": True})
httpx.post(callback_url, json={"description": "Invoice paid", "paid": True})
```
But possibly the most important part of the callback is making sure that your API user (the external developer) implements the *external API* correctly, according to the data that *your API* is going to send in the request body of the callback, etc.
@@ -64,7 +64,7 @@ This example doesn't implement the callback itself (that could be just a line of
!!! tip
The actual callback is just an HTTP request.
When implementing the callback yourself, you could use something like <a href="https://www.encode.io/httpx/" class="external-link" target="_blank">HTTPX</a> or <a href="https://requests.readthedocs.io/" class="external-link" target="_blank">Requests</a>.
When implementing the callback yourself, you could use something like <a href="https://www.python-httpx.org" class="external-link" target="_blank">HTTPX</a> or <a href="https://requests.readthedocs.io/" class="external-link" target="_blank">Requests</a>.
## Write the callback documentation code
@@ -83,7 +83,7 @@ So we are going to use that same knowledge to document how the *external API* sh
First create a new `APIRouter` that will contain one or more callbacks.
```Python hl_lines="5 26"
```Python hl_lines="3 25"
{!../../../docs_src/openapi_callbacks/tutorial001.py!}
```
@@ -96,7 +96,7 @@ It should look just like a normal FastAPI *path operation*:
* It should probably have a declaration of the body it should receive, e.g. `body: InvoiceEvent`.
* And it could also have a declaration of the response it should return, e.g. `response_model=InvoiceEventReceived`.
```Python hl_lines="17-19 22-23 29-33"
```Python hl_lines="16-18 21-22 28-32"
{!../../../docs_src/openapi_callbacks/tutorial001.py!}
```
@@ -163,7 +163,7 @@ At this point you have the *callback path operation(s)* needed (the one(s) that
Now use the parameter `callbacks` in *your API's path operation decorator* to pass the attribute `.routes` (that's actually just a `list` of routes/*path operations*) from that callback router:
```Python hl_lines="36"
```Python hl_lines="35"
{!../../../docs_src/openapi_callbacks/tutorial001.py!}
```

View File

@@ -20,9 +20,26 @@ Then, when you type that username and password, the browser sends them in the he
* It returns an object of type `HTTPBasicCredentials`:
* It contains the `username` and `password` sent.
```Python hl_lines="2 6 10"
{!../../../docs_src/security/tutorial006.py!}
```
=== "Python 3.9+"
```Python hl_lines="4 8 12"
{!> ../../../docs_src/security/tutorial006_an_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="2 7 11"
{!> ../../../docs_src/security/tutorial006_an.py!}
```
=== "Python 3.6+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="2 6 10"
{!> ../../../docs_src/security/tutorial006.py!}
```
When you try to open the URL for the first time (or click the "Execute" button in the docs) the browser will ask you for your username and password:
@@ -34,13 +51,36 @@ Here's a more complete example.
Use a dependency to check if the username and password are correct.
For this, use the Python standard module <a href="https://docs.python.org/3/library/secrets.html" class="external-link" target="_blank">`secrets`</a> to check the username and password:
For this, use the Python standard module <a href="https://docs.python.org/3/library/secrets.html" class="external-link" target="_blank">`secrets`</a> to check the username and password.
```Python hl_lines="1 11-13"
{!../../../docs_src/security/tutorial007.py!}
```
`secrets.compare_digest()` needs to take `bytes` or a `str` that only contains ASCII characters (the ones in English), this means it wouldn't work with characters like `á`, as in `Sebastián`.
This will ensure that `credentials.username` is `"stanleyjobson"`, and that `credentials.password` is `"swordfish"`. This would be similar to:
To handle that, we first convert the `username` and `password` to `bytes` encoding them with UTF-8.
Then we can use `secrets.compare_digest()` to ensure that `credentials.username` is `"stanleyjobson"`, and that `credentials.password` is `"swordfish"`.
=== "Python 3.9+"
```Python hl_lines="1 12-24"
{!> ../../../docs_src/security/tutorial007_an_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="1 12-24"
{!> ../../../docs_src/security/tutorial007_an.py!}
```
=== "Python 3.6+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="1 11-21"
{!> ../../../docs_src/security/tutorial007.py!}
```
This would be similar to:
```Python
if not (credentials.username == "stanleyjobson") or not (credentials.password == "swordfish"):
@@ -102,6 +142,23 @@ That way, using `secrets.compare_digest()` in your application code, it will be
After detecting that the credentials are incorrect, return an `HTTPException` with a status code 401 (the same returned when no credentials are provided) and add the header `WWW-Authenticate` to make the browser show the login prompt again:
```Python hl_lines="15-19"
{!../../../docs_src/security/tutorial007.py!}
```
=== "Python 3.9+"
```Python hl_lines="26-30"
{!> ../../../docs_src/security/tutorial007_an_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="26-30"
{!> ../../../docs_src/security/tutorial007_an.py!}
```
=== "Python 3.6+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="23-27"
{!> ../../../docs_src/security/tutorial007.py!}
```

View File

@@ -56,9 +56,50 @@ They are normally used to declare specific security permissions, for example:
First, let's quickly see the parts that change from the examples in the main **Tutorial - User Guide** for [OAuth2 with Password (and hashing), Bearer with JWT tokens](../../tutorial/security/oauth2-jwt.md){.internal-link target=_blank}. Now using OAuth2 scopes:
```Python hl_lines="2 4 8 12 46 64 105 107-115 121-124 128-134 139 153"
{!../../../docs_src/security/tutorial005.py!}
```
=== "Python 3.10+"
```Python hl_lines="4 8 12 46 64 105 107-115 121-124 128-134 139 155"
{!> ../../../docs_src/security/tutorial005_an_py310.py!}
```
=== "Python 3.9+"
```Python hl_lines="2 4 8 12 46 64 105 107-115 121-124 128-134 139 155"
{!> ../../../docs_src/security/tutorial005_an_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="2 4 8 12 47 65 106 108-116 122-125 129-135 140 156"
{!> ../../../docs_src/security/tutorial005_an.py!}
```
=== "Python 3.10+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="3 7 11 45 63 104 106-114 120-123 127-133 138 152"
{!> ../../../docs_src/security/tutorial005_py310.py!}
```
=== "Python 3.9+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="2 4 8 12 46 64 105 107-115 121-124 128-134 139 153"
{!> ../../../docs_src/security/tutorial005_py39.py!}
```
=== "Python 3.6+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="2 4 8 12 46 64 105 107-115 121-124 128-134 139 153"
{!> ../../../docs_src/security/tutorial005.py!}
```
Now let's review those changes step by step.
@@ -68,9 +109,51 @@ The first change is that now we are declaring the OAuth2 security scheme with tw
The `scopes` parameter receives a `dict` with each scope as a key and the description as the value:
```Python hl_lines="62-65"
{!../../../docs_src/security/tutorial005.py!}
```
=== "Python 3.10+"
```Python hl_lines="62-65"
{!> ../../../docs_src/security/tutorial005_an_py310.py!}
```
=== "Python 3.9+"
```Python hl_lines="62-65"
{!> ../../../docs_src/security/tutorial005_an_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="63-66"
{!> ../../../docs_src/security/tutorial005_an.py!}
```
=== "Python 3.10+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="61-64"
{!> ../../../docs_src/security/tutorial005_py310.py!}
```
=== "Python 3.9+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="62-65"
{!> ../../../docs_src/security/tutorial005_py39.py!}
```
=== "Python 3.6+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="62-65"
{!> ../../../docs_src/security/tutorial005.py!}
```
Because we are now declaring those scopes, they will show up in the API docs when you log-in/authorize.
@@ -93,9 +176,50 @@ And we return the scopes as part of the JWT token.
But in your application, for security, you should make sure you only add the scopes that the user is actually able to have, or the ones you have predefined.
```Python hl_lines="153"
{!../../../docs_src/security/tutorial005.py!}
```
=== "Python 3.10+"
```Python hl_lines="155"
{!> ../../../docs_src/security/tutorial005_an_py310.py!}
```
=== "Python 3.9+"
```Python hl_lines="155"
{!> ../../../docs_src/security/tutorial005_an_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="156"
{!> ../../../docs_src/security/tutorial005_an.py!}
```
=== "Python 3.10+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="152"
{!> ../../../docs_src/security/tutorial005_py310.py!}
```
=== "Python 3.9+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="153"
{!> ../../../docs_src/security/tutorial005_py39.py!}
```
=== "Python 3.6+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="153"
{!> ../../../docs_src/security/tutorial005.py!}
```
## Declare scopes in *path operations* and dependencies
@@ -118,9 +242,50 @@ In this case, it requires the scope `me` (it could require more than one scope).
We are doing it here to demonstrate how **FastAPI** handles scopes declared at different levels.
```Python hl_lines="4 139 166"
{!../../../docs_src/security/tutorial005.py!}
```
=== "Python 3.10+"
```Python hl_lines="4 139 170"
{!> ../../../docs_src/security/tutorial005_an_py310.py!}
```
=== "Python 3.9+"
```Python hl_lines="4 139 170"
{!> ../../../docs_src/security/tutorial005_an_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="4 140 171"
{!> ../../../docs_src/security/tutorial005_an.py!}
```
=== "Python 3.10+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="3 138 165"
{!> ../../../docs_src/security/tutorial005_py310.py!}
```
=== "Python 3.9+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="4 139 166"
{!> ../../../docs_src/security/tutorial005_py39.py!}
```
=== "Python 3.6+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="4 139 166"
{!> ../../../docs_src/security/tutorial005.py!}
```
!!! info "Technical Details"
`Security` is actually a subclass of `Depends`, and it has just one extra parameter that we'll see later.
@@ -143,9 +308,50 @@ We also declare a special parameter of type `SecurityScopes`, imported from `fas
This `SecurityScopes` class is similar to `Request` (`Request` was used to get the request object directly).
```Python hl_lines="8 105"
{!../../../docs_src/security/tutorial005.py!}
```
=== "Python 3.10+"
```Python hl_lines="8 105"
{!> ../../../docs_src/security/tutorial005_an_py310.py!}
```
=== "Python 3.9+"
```Python hl_lines="8 105"
{!> ../../../docs_src/security/tutorial005_an_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="8 106"
{!> ../../../docs_src/security/tutorial005_an.py!}
```
=== "Python 3.10+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="7 104"
{!> ../../../docs_src/security/tutorial005_py310.py!}
```
=== "Python 3.9+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="8 105"
{!> ../../../docs_src/security/tutorial005_py39.py!}
```
=== "Python 3.6+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="8 105"
{!> ../../../docs_src/security/tutorial005.py!}
```
## Use the `scopes`
@@ -159,9 +365,50 @@ We create an `HTTPException` that we can re-use (`raise`) later at several point
In this exception, we include the scopes required (if any) as a string separated by spaces (using `scope_str`). We put that string containing the scopes in the `WWW-Authenticate` header (this is part of the spec).
```Python hl_lines="105 107-115"
{!../../../docs_src/security/tutorial005.py!}
```
=== "Python 3.10+"
```Python hl_lines="105 107-115"
{!> ../../../docs_src/security/tutorial005_an_py310.py!}
```
=== "Python 3.9+"
```Python hl_lines="105 107-115"
{!> ../../../docs_src/security/tutorial005_an_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="106 108-116"
{!> ../../../docs_src/security/tutorial005_an.py!}
```
=== "Python 3.10+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="104 106-114"
{!> ../../../docs_src/security/tutorial005_py310.py!}
```
=== "Python 3.9+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="105 107-115"
{!> ../../../docs_src/security/tutorial005_py39.py!}
```
=== "Python 3.6+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="105 107-115"
{!> ../../../docs_src/security/tutorial005.py!}
```
## Verify the `username` and data shape
@@ -177,9 +424,50 @@ Instead of, for example, a `dict`, or something else, as it could break the appl
We also verify that we have a user with that username, and if not, we raise that same exception we created before.
```Python hl_lines="46 116-127"
{!../../../docs_src/security/tutorial005.py!}
```
=== "Python 3.10+"
```Python hl_lines="46 116-127"
{!> ../../../docs_src/security/tutorial005_an_py310.py!}
```
=== "Python 3.9+"
```Python hl_lines="46 116-127"
{!> ../../../docs_src/security/tutorial005_an_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="47 117-128"
{!> ../../../docs_src/security/tutorial005_an.py!}
```
=== "Python 3.10+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="45 115-126"
{!> ../../../docs_src/security/tutorial005_py310.py!}
```
=== "Python 3.9+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="46 116-127"
{!> ../../../docs_src/security/tutorial005_py39.py!}
```
=== "Python 3.6+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="46 116-127"
{!> ../../../docs_src/security/tutorial005.py!}
```
## Verify the `scopes`
@@ -187,9 +475,50 @@ We now verify that all the scopes required, by this dependency and all the depen
For this, we use `security_scopes.scopes`, that contains a `list` with all these scopes as `str`.
```Python hl_lines="128-134"
{!../../../docs_src/security/tutorial005.py!}
```
=== "Python 3.10+"
```Python hl_lines="128-134"
{!> ../../../docs_src/security/tutorial005_an_py310.py!}
```
=== "Python 3.9+"
```Python hl_lines="128-134"
{!> ../../../docs_src/security/tutorial005_an_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="129-135"
{!> ../../../docs_src/security/tutorial005_an.py!}
```
=== "Python 3.10+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="127-133"
{!> ../../../docs_src/security/tutorial005_py310.py!}
```
=== "Python 3.9+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="128-134"
{!> ../../../docs_src/security/tutorial005_py39.py!}
```
=== "Python 3.6+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="128-134"
{!> ../../../docs_src/security/tutorial005.py!}
```
## Dependency tree and scopes

View File

@@ -216,9 +216,26 @@ Notice that now we don't create a default instance `settings = Settings()`.
Now we create a dependency that returns a new `config.Settings()`.
```Python hl_lines="5 11-12"
{!../../../docs_src/settings/app02/main.py!}
```
=== "Python 3.9+"
```Python hl_lines="6 12-13"
{!> ../../../docs_src/settings/app02_an_py39/main.py!}
```
=== "Python 3.6+"
```Python hl_lines="6 12-13"
{!> ../../../docs_src/settings/app02_an/main.py!}
```
=== "Python 3.6+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="5 11-12"
{!> ../../../docs_src/settings/app02/main.py!}
```
!!! tip
We'll discuss the `@lru_cache()` in a bit.
@@ -227,9 +244,26 @@ Now we create a dependency that returns a new `config.Settings()`.
And then we can require it from the *path operation function* as a dependency and use it anywhere we need it.
```Python hl_lines="16 18-20"
{!../../../docs_src/settings/app02/main.py!}
```
=== "Python 3.9+"
```Python hl_lines="17 19-21"
{!> ../../../docs_src/settings/app02_an_py39/main.py!}
```
=== "Python 3.6+"
```Python hl_lines="17 19-21"
{!> ../../../docs_src/settings/app02_an/main.py!}
```
=== "Python 3.6+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="16 18-20"
{!> ../../../docs_src/settings/app02/main.py!}
```
### Settings and testing
@@ -304,9 +338,26 @@ we would create that object for each request, and we would be reading the `.env`
But as we are using the `@lru_cache()` decorator on top, the `Settings` object will be created only once, the first time it's called. ✔️
```Python hl_lines="1 10"
{!../../../docs_src/settings/app03/main.py!}
```
=== "Python 3.9+"
```Python hl_lines="1 11"
{!> ../../../docs_src/settings/app03_an_py39/main.py!}
```
=== "Python 3.6+"
```Python hl_lines="1 11"
{!> ../../../docs_src/settings/app03_an/main.py!}
```
=== "Python 3.6+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="1 10"
{!> ../../../docs_src/settings/app03/main.py!}
```
Then for any subsequent calls of `get_settings()` in the dependencies for the next requests, instead of executing the internal code of `get_settings()` and creating a new `Settings` object, it will return the same object that was returned on the first call, again and again.

View File

@@ -28,9 +28,41 @@ To override a dependency for testing, you put as a key the original dependency (
And then **FastAPI** will call that override instead of the original dependency.
```Python hl_lines="28-29 32"
{!../../../docs_src/dependency_testing/tutorial001.py!}
```
=== "Python 3.10+"
```Python hl_lines="26-27 30"
{!> ../../../docs_src/dependency_testing/tutorial001_an_py310.py!}
```
=== "Python 3.9+"
```Python hl_lines="28-29 32"
{!> ../../../docs_src/dependency_testing/tutorial001_an_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="29-30 33"
{!> ../../../docs_src/dependency_testing/tutorial001_an.py!}
```
=== "Python 3.10+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="24-25 28"
{!> ../../../docs_src/dependency_testing/tutorial001_py310.py!}
```
=== "Python 3.6+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="28-29 32"
{!> ../../../docs_src/dependency_testing/tutorial001.py!}
```
!!! tip
You can set a dependency override for a dependency used anywhere in your **FastAPI** application.

View File

@@ -112,17 +112,47 @@ In WebSocket endpoints you can import from `fastapi` and use:
They work the same way as for other FastAPI endpoints/*path operations*:
```Python hl_lines="58-65 68-83"
{!../../../docs_src/websockets/tutorial002.py!}
```
=== "Python 3.10+"
```Python hl_lines="68-69 82"
{!> ../../../docs_src/websockets/tutorial002_an_py310.py!}
```
=== "Python 3.9+"
```Python hl_lines="68-69 82"
{!> ../../../docs_src/websockets/tutorial002_an_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="69-70 83"
{!> ../../../docs_src/websockets/tutorial002_an.py!}
```
=== "Python 3.10+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="66-67 79"
{!> ../../../docs_src/websockets/tutorial002_py310.py!}
```
=== "Python 3.6+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="68-69 81"
{!> ../../../docs_src/websockets/tutorial002.py!}
```
!!! info
In a WebSocket it doesn't really make sense to raise an `HTTPException`. So it's better to close the WebSocket connection directly.
As this is a WebSocket it doesn't really make sense to raise an `HTTPException`, instead we raise a `WebSocketException`.
You can use a closing code from the <a href="https://tools.ietf.org/html/rfc6455#section-7.4.1" class="external-link" target="_blank">valid codes defined in the specification</a>.
In the future, there will be a `WebSocketException` that you will be able to `raise` from anywhere, and add exception handlers for it. It depends on the <a href="https://github.com/encode/starlette/pull/527" class="external-link" target="_blank">PR #527</a> in Starlette.
### Try the WebSockets with dependencies
If your file is named `main.py`, run your application with:
@@ -155,9 +185,17 @@ With that you can connect the WebSocket and then send and receive messages:
When a WebSocket connection is closed, the `await websocket.receive_text()` will raise a `WebSocketDisconnect` exception, which you can then catch and handle like in this example.
```Python hl_lines="81-83"
{!../../../docs_src/websockets/tutorial003.py!}
```
=== "Python 3.9+"
```Python hl_lines="79-81"
{!> ../../../docs_src/websockets/tutorial003_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="81-83"
{!> ../../../docs_src/websockets/tutorial003.py!}
```
To try it out:

View File

@@ -123,7 +123,7 @@ That's why when talking about version 2.0 it's common to say "Swagger", and for
There are several Flask REST frameworks, but after investing the time and work into investigating them, I found that many are discontinued or abandoned, with several standing issues that made them unfit.
### <a href="https://marshmallow.readthedocs.io/en/3.0/" class="external-link" target="_blank">Marshmallow</a>
### <a href="https://marshmallow.readthedocs.io/en/stable/" class="external-link" target="_blank">Marshmallow</a>
One of the main features needed by API systems is data "<abbr title="also called marshalling, conversion">serialization</abbr>" which is taking data from the code (Python) and converting it into something that can be sent through the network. For example, converting an object containing data from a database into a JSON object. Converting `datetime` objects into strings, etc.
@@ -367,7 +367,7 @@ It has:
* WebSocket support.
* In-process background tasks.
* Startup and shutdown events.
* Test client built on requests.
* Test client built on HTTPX.
* CORS, GZip, Static Files, Streaming responses.
* Session and Cookie support.
* 100% test coverage.

View File

@@ -26,7 +26,7 @@ async def read_results():
---
If you are using a third party library that communicates with something (a database, an API, the file system, etc) and doesn't have support for using `await`, (this is currently the case for most database libraries), then declare your *path operation functions* as normally, with just `def`, like:
If you are using a third party library that communicates with something (a database, an API, the file system, etc.) and doesn't have support for using `await`, (this is currently the case for most database libraries), then declare your *path operation functions* as normally, with just `def`, like:
```Python hl_lines="2"
@app.get('/')
@@ -45,7 +45,7 @@ If you just don't know, use normal `def`.
---
**Note**: you can mix `def` and `async def` in your *path operation functions* as much as you need and define each one using the best option for you. FastAPI will do the right thing with them.
**Note**: You can mix `def` and `async def` in your *path operation functions* as much as you need and define each one using the best option for you. FastAPI will do the right thing with them.
Anyway, in any of the cases above, FastAPI will still work asynchronously and be extremely fast.
@@ -283,7 +283,7 @@ For example:
### Concurrency + Parallelism: Web + Machine Learning
With **FastAPI** you can take the advantage of concurrency that is very common for web development (the same main attractive of NodeJS).
With **FastAPI** you can take the advantage of concurrency that is very common for web development (the same main attraction of NodeJS).
But you can also exploit the benefits of parallelism and multiprocessing (having multiple processes running in parallel) for **CPU bound** workloads like those in Machine Learning systems.
@@ -397,23 +397,23 @@ All that is what powers FastAPI (through Starlette) and what makes it have such
These are very technical details of how **FastAPI** works underneath.
If you have quite some technical knowledge (co-routines, threads, blocking, etc) and are curious about how FastAPI handles `async def` vs normal `def`, go ahead.
If you have quite some technical knowledge (co-routines, threads, blocking, etc.) and are curious about how FastAPI handles `async def` vs normal `def`, go ahead.
### Path operation functions
When you declare a *path operation function* with normal `def` instead of `async def`, it is run in an external threadpool that is then awaited, instead of being called directly (as it would block the server).
If you are coming from another async framework that does not work in the way described above and you are used to define trivial compute-only *path operation functions* with plain `def` for a tiny performance gain (about 100 nanoseconds), please note that in **FastAPI** the effect would be quite opposite. In these cases, it's better to use `async def` unless your *path operation functions* use code that performs blocking <abbr title="Input/Output: disk reading or writing, network communications.">I/O</abbr>.
If you are coming from another async framework that does not work in the way described above and you are used to defining trivial compute-only *path operation functions* with plain `def` for a tiny performance gain (about 100 nanoseconds), please note that in **FastAPI** the effect would be quite opposite. In these cases, it's better to use `async def` unless your *path operation functions* use code that performs blocking <abbr title="Input/Output: disk reading or writing, network communications.">I/O</abbr>.
Still, in both situations, chances are that **FastAPI** will [still be faster](/#performance){.internal-link target=_blank} than (or at least comparable to) your previous framework.
### Dependencies
The same applies for dependencies. If a dependency is a standard `def` function instead of `async def`, it is run in the external threadpool.
The same applies for [dependencies](/tutorial/dependencies/index.md){.internal-link target=_blank}. If a dependency is a standard `def` function instead of `async def`, it is run in the external threadpool.
### Sub-dependencies
You can have multiple dependencies and sub-dependencies requiring each other (as parameters of the function definitions), some of them might be created with `async def` and some with normal `def`. It would still work, and the ones created with normal `def` would be called on an external thread (from the threadpool) instead of being "awaited".
You can have multiple dependencies and [sub-dependencies](/tutorial/dependencies/sub-dependencies.md){.internal-link target=_blank} requiring each other (as parameters of the function definitions), some of them might be created with `async def` and some with normal `def`. It would still work, and the ones created with normal `def` would be called on an external thread (from the threadpool) instead of being "awaited".
### Other utility functions

View File

@@ -84,58 +84,36 @@ To check it worked, use:
If it shows the `pip` binary at `env/bin/pip` then it worked. 🎉
!!! tip
Every time you install a new package with `pip` under that environment, activate the environment again.
This makes sure that if you use a terminal program installed by that package (like `flit`), you use the one from your local environment and not any other that could be installed globally.
### Flit
**FastAPI** uses <a href="https://flit.readthedocs.io/en/latest/index.html" class="external-link" target="_blank">Flit</a> to build, package and publish the project.
After activating the environment as described above, install `flit`:
Make sure you have the latest pip version on your virtual environment to avoid errors on the next steps:
<div class="termy">
```console
$ pip install flit
$ python -m pip install --upgrade pip
---> 100%
```
</div>
Now re-activate the environment to make sure you are using the `flit` you just installed (and not a global one).
!!! tip
Every time you install a new package with `pip` under that environment, activate the environment again.
And now use `flit` to install the development dependencies:
This makes sure that if you use a terminal program installed by that package, you use the one from your local environment and not any other that could be installed globally.
=== "Linux, macOS"
### pip
<div class="termy">
After activating the environment as described above:
```console
$ flit install --deps develop --symlink
<div class="termy">
---> 100%
```
```console
$ pip install -e ."[dev,doc,test]"
</div>
---> 100%
```
=== "Windows"
If you are on Windows, use `--pth-file` instead of `--symlink`:
<div class="termy">
```console
$ flit install --deps develop --pth-file
---> 100%
```
</div>
</div>
It will install all the dependencies and your local FastAPI in your local environment.
@@ -143,7 +121,7 @@ It will install all the dependencies and your local FastAPI in your local enviro
If you create a Python file that imports and uses FastAPI, and run it with the Python from your local environment, it will use your local FastAPI source code.
And if you update that local FastAPI source code, as it is installed with `--symlink` (or `--pth-file` on Windows), when you run that Python file again, it will use the fresh version of FastAPI you just edited.
And if you update that local FastAPI source code, as it is installed with `-e`, when you run that Python file again, it will use the fresh version of FastAPI you just edited.
That way, you don't have to "install" your local version to be able to test every change.
@@ -161,7 +139,7 @@ $ bash scripts/format.sh
It will also auto-sort all your imports.
For it to sort them correctly, you need to have FastAPI installed locally in your environment, with the command in the section above using `--symlink` (or `--pth-file` on Windows).
For it to sort them correctly, you need to have FastAPI installed locally in your environment, with the command in the section above using `-e`.
## Docs

View File

@@ -235,7 +235,7 @@ Here are some possible combinations and strategies:
* One Uvicorn **process manager** would listen on the **IP** and **port**, and it would start **multiple Uvicorn worker processes**
* **Kubernetes** and other distributed **container systems**
* Something in the **Kubernetes** layer would listen on the **IP** and **port**. The replication would be by having **multiple containers**, each with **one Uvicorn process** running
* **Cloud services** that handle this for your
* **Cloud services** that handle this for you
* The cloud service will probably **handle replication for you**. It would possibly let you define **a process to run**, or a **container image** to use, in any case, it would most probably be **a single Uvicorn process**, and the cloud service would be in charge of replicating it.
!!! tip

View File

@@ -56,6 +56,15 @@ Here's an incomplete list of some of them.
{% endfor %}
{% endif %}
### Taiwanese
{% if external_links %}
{% for article in external_links.articles.taiwanese %}
* <a href="{{ article.link }}" class="external-link" target="_blank">{{ article.title }}</a> by <a href="{{ article.author_link }}" class="external-link" target="_blank">{{ article.author }}</a>.
{% endfor %}
{% endif %}
## Podcasts
{% if external_links %}

View File

@@ -28,7 +28,7 @@ I'm the creator and maintainer of **FastAPI**. You can read more about that in [
These are the people that:
* [Help others with issues (questions) in GitHub](help-fastapi.md#help-others-with-issues-in-github){.internal-link target=_blank}.
* [Help others with questions in GitHub](help-fastapi.md#help-others-with-questions-in-github){.internal-link target=_blank}.
* [Create Pull Requests](help-fastapi.md#create-a-pull-request){.internal-link target=_blank}.
* Review Pull Requests, [especially important for translations](contributing.md#translations){.internal-link target=_blank}.
@@ -36,13 +36,13 @@ A round of applause to them. 👏 🙇
## Most active users last month
These are the users that have been [helping others the most with issues (questions) in GitHub](help-fastapi.md#help-others-with-issues-in-github){.internal-link target=_blank} during the last month. ☕
These are the users that have been [helping others the most with questions in GitHub](help-fastapi.md#help-others-with-questions-in-github){.internal-link target=_blank} during the last month. ☕
{% if people %}
<div class="user-list user-list-center">
{% for user in people.last_month_active %}
<div class="user"><a href="{{ user.url }}" target="_blank"><div class="avatar-wrapper"><img src="{{ user.avatarUrl }}"/></div><div class="title">@{{ user.login }}</div></a> <div class="count">Issues replied: {{ user.count }}</div></div>
<div class="user"><a href="{{ user.url }}" target="_blank"><div class="avatar-wrapper"><img src="{{ user.avatarUrl }}"/></div><div class="title">@{{ user.login }}</div></a> <div class="count">Questions replied: {{ user.count }}</div></div>
{% endfor %}
</div>
@@ -52,7 +52,7 @@ These are the users that have been [helping others the most with issues (questio
Here are the **FastAPI Experts**. 🤓
These are the users that have [helped others the most with issues (questions) in GitHub](help-fastapi.md#help-others-with-issues-in-github){.internal-link target=_blank} through *all time*.
These are the users that have [helped others the most with questions in GitHub](help-fastapi.md#help-others-with-questions-in-github){.internal-link target=_blank} through *all time*.
They have proven to be experts by helping many others. ✨
@@ -60,7 +60,7 @@ They have proven to be experts by helping many others. ✨
<div class="user-list user-list-center">
{% for user in people.experts %}
<div class="user"><a href="{{ user.url }}" target="_blank"><div class="avatar-wrapper"><img src="{{ user.avatarUrl }}"/></div><div class="title">@{{ user.login }}</div></a> <div class="count">Issues replied: {{ user.count }}</div></div>
<div class="user"><a href="{{ user.url }}" target="_blank"><div class="avatar-wrapper"><img src="{{ user.avatarUrl }}"/></div><div class="title">@{{ user.login }}</div></a> <div class="count">Questions replied: {{ user.count }}</div></div>
{% endfor %}
</div>
@@ -169,7 +169,7 @@ They are supporting my work with **FastAPI** (and others), mainly through <a hre
The main intention of this page is to highlight the effort of the community to help others.
Especially including efforts that are normally less visible, and in many cases more arduous, like helping others with issues and reviewing Pull Requests with translations.
Especially including efforts that are normally less visible, and in many cases more arduous, like helping others with questions and reviewing Pull Requests with translations.
The data is calculated each month, you can read the <a href="https://github.com/tiangolo/fastapi/blob/master/.github/actions/people/app/main.py" class="external-link" target="_blank">source code here</a>.

View File

@@ -166,7 +166,7 @@ With **FastAPI** you get all of **Starlette**'s features (as FastAPI is just Sta
* **WebSocket** support.
* In-process background tasks.
* Startup and shutdown events.
* Test client built on `requests`.
* Test client built on HTTPX.
* **CORS**, GZip, Static Files, Streaming responses.
* **Session and Cookie** support.
* 100% test coverage.
@@ -195,6 +195,6 @@ With **FastAPI** you get all of **Pydantic**'s features (as FastAPI is based on
* Use of hierarchical Pydantic models, Python `typing`s `List` and `Dict`, etc.
* And validators allow complex data schemas to be clearly and easily defined, checked and documented as JSON Schema.
* You can have deeply **nested JSON** objects and have them all validated and annotated.
* **Extendible**:
* **Extensible**:
* Pydantic allows custom data types to be defined or you can extend validation with methods on a model decorated with the validator decorator.
* 100% test coverage.

View File

@@ -47,7 +47,7 @@ You can:
* <a href="https://github.com/tiangolo" class="external-link" target="_blank">Follow me on **GitHub**</a>.
* See other Open Source projects I have created that could help you.
* Follow me to see when I create a new Open Source project.
* <a href="https://twitter.com/tiangolo" class="external-link" target="_blank">Follow me on **Twitter**</a>.
* <a href="https://twitter.com/tiangolo" class="external-link" target="_blank">Follow me on **Twitter**</a> or <a href="https://fosstodon.org/@tiangolo" class="external-link" target="_blank">Mastodon</a>.
* Tell me how you use FastAPI (I love to hear that).
* Hear when I make announcements or release new tools.
* You can also <a href="https://twitter.com/fastapi" class="external-link" target="_blank">follow @fastapi on Twitter</a> (a separate account).
@@ -67,29 +67,129 @@ I love to hear about how **FastAPI** is being used, what you have liked in it, i
* <a href="https://www.slant.co/options/34241/~fastapi-review" class="external-link" target="_blank">Vote for **FastAPI** in Slant</a>.
* <a href="https://alternativeto.net/software/fastapi/" class="external-link" target="_blank">Vote for **FastAPI** in AlternativeTo</a>.
* <a href="https://stackshare.io/pypi-fastapi" class="external-link" target="_blank">Say you use **FastAPI** on StackShare</a>.
## Help others with issues in GitHub
## Help others with questions in GitHub
You can see <a href="https://github.com/tiangolo/fastapi/issues" class="external-link" target="_blank">existing issues</a> and try and help others, most of the times they are questions that you might already know the answer for. 🤓
You can try and help others with their questions in:
If you are helping a lot of people with issues, you might become an official [FastAPI Expert](fastapi-people.md#experts){.internal-link target=_blank}. 🎉
* <a href="https://github.com/tiangolo/fastapi/discussions/categories/questions?discussions_q=category%3AQuestions+is%3Aunanswered" class="external-link" target="_blank">GitHub Discussions</a>
* <a href="https://github.com/tiangolo/fastapi/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc+label%3Aquestion+-label%3Aanswered+" class="external-link" target="_blank">GitHub Issues</a>
In many cases you might already know the answer for those questions. 🤓
If you are helping a lot of people with their questions, you will become an official [FastAPI Expert](fastapi-people.md#experts){.internal-link target=_blank}. 🎉
Just remember, the most important point is: try to be kind. People come with their frustrations and in many cases don't ask in the best way, but try as best as you can to be kind. 🤗
The idea is for the **FastAPI** community to be kind and welcoming. At the same time, don't accept bullying or disrespectful behavior towards others. We have to take care of each other.
---
Here's how to help others with questions (in discussions or issues):
### Understand the question
* Check if you can understand what is the **purpose** and use case of the person asking.
* Then check if the question (the vast majority are questions) is **clear**.
* In many cases the question asked is about an imaginary solution from the user, but there might be a **better** one. If you can understand the problem and use case better, you might be able to suggest a better **alternative solution**.
* If you can't understand the question, ask for more **details**.
### Reproduce the problem
For most of the cases and most of the questions there's something related to the person's **original code**.
In many cases they will only copy a fragment of the code, but that's not enough to **reproduce the problem**.
* You can ask them to provide a <a href="https://stackoverflow.com/help/minimal-reproducible-example" class="external-link" target="_blank">minimal, reproducible, example</a>, that you can **copy-paste** and run locally to see the same error or behavior they are seeing, or to understand their use case better.
* If you are feeling too generous, you can try to **create an example** like that yourself, just based on the description of the problem. Just have in mind that this might take a lot of time and it might be better to ask them to clarify the problem first.
### Suggest solutions
* After being able to understand the question, you can give them a possible **answer**.
* In many cases, it's better to understand their **underlying problem or use case**, because there might be a better way to solve it than what they are trying to do.
### Ask to close
If they reply, there's a high chance you would have solved their problem, congrats, **you're a hero**! 🦸
* Now, if that solved their problem, you can ask them to:
* In GitHub Discussions: mark the comment as the **answer**.
* In GitHub Issues: **close** the issue**.
## Watch the GitHub repository
You can "watch" FastAPI in GitHub (clicking the "watch" button at the top right): <a href="https://github.com/tiangolo/fastapi" class="external-link" target="_blank">https://github.com/tiangolo/fastapi</a>. 👀
If you select "Watching" instead of "Releases only" you will receive notifications when someone creates a new issue.
If you select "Watching" instead of "Releases only" you will receive notifications when someone creates a new issue or question. You can also specify that you only want to be notified about new issues, or discussions, or PRs, etc.
Then you can try and help them solve those issues.
Then you can try and help them solve those questions.
## Create issues
## Ask Questions
You can <a href="https://github.com/tiangolo/fastapi/issues/new/choose" class="external-link" target="_blank">create a new issue</a> in the GitHub repository, for example to:
You can <a href="https://github.com/tiangolo/fastapi/discussions/new?category=questions" class="external-link" target="_blank">create a new question</a> in the GitHub repository, for example to:
* Ask a **question** or ask about a **problem**.
* Suggest a new **feature**.
**Note**: if you create an issue, then I'm going to ask you to also help others. 😉
**Note**: if you do it, then I'm going to ask you to also help others. 😉
## Review Pull Requests
You can help me review pull requests from others.
Again, please try your best to be kind. 🤗
---
Here's what to have in mind and how to review a pull request:
### Understand the problem
* First, make sure you **understand the problem** that the pull request is trying to solve. It might have a longer discussion in a GitHub Discussion or issue.
* There's also a good chance that the pull request is not actually needed because the problem can be solved in a **different way**. Then you can suggest or ask about that.
### Don't worry about style
* Don't worry too much about things like commit message styles, I will squash and merge customizing the commit manually.
* Also don't worry about style rules, there are already automatized tools checking that.
And if there's any other style or consistency need, I'll ask directly for that, or I'll add commits on top with the needed changes.
### Check the code
* Check and read the code, see if it makes sense, **run it locally** and see if it actually solves the problem.
* Then **comment** saying that you did that, that's how I will know you really checked it.
!!! info
Unfortunately, I can't simply trust PRs that just have several approvals.
Several times it has happened that there are PRs with 3, 5 or more approvals, probably because the description is appealing, but when I check the PRs, they are actually broken, have a bug, or don't solve the problem they claim to solve. 😅
So, it's really important that you actually read and run the code, and let me know in the comments that you did. 🤓
* If the PR can be simplified in a way, you can ask for that, but there's no need to be too picky, there might be a lot of subjective points of view (and I will have my own as well 🙈), so it's better if you can focus on the fundamental things.
### Tests
* Help me check that the PR has **tests**.
* Check that the tests **fail** before the PR. 🚨
* Then check that the tests **pass** after the PR. ✅
* Many PRs don't have tests, you can **remind** them to add tests, or you can even **suggest** some tests yourself. That's one of the things that consume most time and you can help a lot with that.
* Then also comment what you tried, that way I'll know that you checked it. 🤓
## Create a Pull Request
@@ -102,14 +202,32 @@ You can [contribute](contributing.md){.internal-link target=_blank} to the sourc
* You can also help to review the translations created by others.
* To propose new documentation sections.
* To fix an existing issue/bug.
* Make sure to add tests.
* To add a new feature.
* Make sure to add tests.
* Make sure to add documentation if it's relevant.
## Help Maintain FastAPI
Help me maintain **FastAPI**! 🤓
There's a lot of work to do, and for most of it, **YOU** can do it.
The main tasks that you can do right now are:
* [Help others with questions in GitHub](#help-others-with-questions-in-github){.internal-link target=_blank} (see the section above).
* [Review Pull Requests](#review-pull-requests){.internal-link target=_blank} (see the section above).
Those two tasks are what **consume time the most**. That's the main work of maintaining FastAPI.
If you can help me with that, **you are helping me maintain FastAPI** and making sure it keeps **advancing faster and better**. 🚀
## Join the chat
Join the 👥 <a href="https://discord.gg/VQjSZaeJmf" class="external-link" target="_blank">Discord chat server</a> 👥 and hang out with others in the FastAPI community.
!!! tip
For questions, ask them in <a href="https://github.com/tiangolo/fastapi/issues/new/choose" class="external-link" target="_blank">GitHub issues</a>, there's a much better chance you will receive help by the [FastAPI Experts](fastapi-people.md#experts){.internal-link target=_blank}.
For questions, ask them in <a href="https://github.com/tiangolo/fastapi/discussions/new?category=questions" class="external-link" target="_blank">GitHub Discussions</a>, there's a much better chance you will receive help by the [FastAPI Experts](fastapi-people.md#experts){.internal-link target=_blank}.
Use the chat only for other general conversations.
@@ -119,9 +237,9 @@ There is also the previous <a href="https://gitter.im/tiangolo/fastapi" class="e
Have in mind that as chats allow more "free conversation", it's easy to ask questions that are too general and more difficult to answer, so, you might not receive answers.
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. 😅
In GitHub, 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 issues.
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 count to become a [FastAPI Expert](fastapi-people.md#experts){.internal-link target=_blank}, so you will most probably receive more attention in GitHub.
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

Before

Width:  |  Height:  |  Size: 107 KiB

After

Width:  |  Height:  |  Size: 107 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@@ -0,0 +1,178 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
id="svg2"
width="240"
height="100"
viewBox="0 0 240 100"
sodipodi:docname="svix-vector.svg"
inkscape:version="1.0.2 (1.0.2+r75+1)"
inkscape:export-filename="../../../../../tmp/banner.png"
inkscape:export-xdpi="96"
inkscape:export-ydpi="96">
<metadata
id="metadata15">
<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>
<defs
id="defs6" />
<sodipodi:namedview
id="namedview4"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:showpageshadow="2"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
showgrid="false"
inkscape:zoom="2.364373"
inkscape:cx="9.516265"
inkscape:cy="64.499129"
inkscape:window-width="1920"
inkscape:window-height="1025"
inkscape:window-x="0"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:current-layer="text1936"
inkscape:document-rotation="0" />
<g
inkscape:groupmode="layer"
inkscape:label="Image"
id="g8">
<rect
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.986808;stroke-opacity:1;paint-order:fill markers stroke"
id="rect3346"
width="240"
height="100"
x="-240"
y="0"
rx="0"
transform="scale(-1,1)" />
<g
id="g6454"
transform="matrix(0.87971356,0,0,0.87971356,13.956407,4.3914173)">
<g
id="g8-7"
transform="matrix(0.10637635,0,0,0.10637635,14.16696,-68.565829)">
<path
fill-rule="evenodd"
clip-rule="evenodd"
fill="#ffffff"
d="m 356.996,807.521 c -24.779,24.776 -40.104,59.008 -40.104,96.812 0,37.809 15.325,72.034 40.104,96.808 55.364,55.372 104.225,24.98 135.285,56.04 9.84,9.842 15.933,23.447 15.933,38.474 0,15.023 -6.093,28.632 -15.933,38.473 -9.843,9.845 -23.45,15.936 -38.475,15.936 -10.021,0 -19.375,-2.686 -27.377,-7.354 -25.975,-15.161 -30.519,-48.084 -70.353,-71.339 -20.285,-11.842 -43.846,-18.637 -68.954,-18.637 -35.289,0 -67.459,13.355 -91.735,35.282 9.772,28.697 24.19,55.246 42.359,78.749 2.707,-5.83 6.413,-11.102 10.901,-15.589 9.841,-9.842 23.45,-15.936 38.475,-15.936 10.021,0 19.375,2.686 27.376,7.354 8.556,4.994 15.55,11.989 20.191,20.202 12.059,21.337 29.423,39.029 50.162,51.137 20.285,11.842 43.846,18.637 68.955,18.637 37.804,0 72.036,-15.326 96.812,-40.105 24.775,-24.775 40.104,-59.001 40.104,-96.81 0,-37.802 -15.328,-72.034 -40.104,-96.81 -55.367,-55.367 -104.229,-24.983 -135.285,-56.038 -9.843,-9.845 -15.935,-23.448 -15.935,-38.473 0,-15.025 6.092,-28.632 15.935,-38.475 9.839,-9.839 23.448,-15.933 38.473,-15.933 10.021,0 19.376,2.682 27.378,7.354 25.973,15.162 30.517,48.083 70.351,71.339 20.284,11.842 43.846,18.635 68.956,18.635 35.284,0 67.459,-13.352 91.733,-35.28 -9.772,-28.7 -24.19,-55.247 -42.359,-78.751 -2.705,5.831 -6.413,11.102 -10.901,15.589 -9.843,9.843 -23.448,15.935 -38.473,15.935 -10.021,0 -19.375,-2.684 -27.378,-7.354 -8.556,-4.995 -15.548,-11.99 -20.19,-20.202 -12.059,-21.336 -29.422,-39.029 -50.16,-51.138 -20.285,-11.841 -43.847,-18.634 -68.956,-18.634 -37.81,-10e-4 -72.037,15.327 -96.811,40.102 z"
id="path2-0" />
<path
fill-rule="evenodd"
clip-rule="evenodd"
fill="#018ffa"
d="m 453.806,727.069 c -150.731,0 -272.922,122.192 -272.922,272.924 0,30.797 5.1,60.402 14.503,88.021 24.276,-21.927 56.446,-35.282 91.735,-35.282 25.108,0 48.669,6.795 68.954,18.637 39.833,23.255 44.377,56.178 70.353,71.339 8.002,4.669 17.356,7.354 27.377,7.354 15.025,0 28.632,-6.091 38.475,-15.936 9.84,-9.841 15.933,-23.449 15.933,-38.473 0,-15.026 -6.093,-28.632 -15.933,-38.474 -31.06,-31.06 -79.921,-0.668 -135.285,-56.04 -24.779,-24.773 -40.104,-58.999 -40.104,-96.808 0,-37.804 15.325,-72.036 40.104,-96.812 24.774,-24.776 59.001,-40.104 96.81,-40.104 25.109,0 48.671,6.793 68.956,18.634 20.738,12.108 38.101,29.802 50.16,51.138 4.643,8.212 11.634,15.208 20.19,20.202 8.004,4.67 17.358,7.354 27.378,7.354 15.025,0 28.63,-6.092 38.473,-15.935 4.488,-4.488 8.196,-9.759 10.901,-15.589 C 619.951,768.65 541.735,727.069 453.806,727.069 Z"
id="path4-9" />
<path
fill-rule="evenodd"
clip-rule="evenodd"
fill="#018ffa"
d="m 550.617,998.844 c 24.775,24.776 40.104,59.008 40.104,96.81 0,37.809 -15.328,72.034 -40.104,96.81 -24.776,24.779 -59.008,40.105 -96.812,40.105 -25.108,0 -48.67,-6.795 -68.955,-18.637 -20.738,-12.107 -38.103,-29.8 -50.162,-51.137 -4.641,-8.213 -11.635,-15.208 -20.191,-20.202 -8.002,-4.669 -17.356,-7.354 -27.376,-7.354 -15.025,0 -28.634,6.094 -38.475,15.936 -4.488,4.487 -8.194,9.759 -10.901,15.589 49.916,64.571 128.132,106.15 216.06,106.15 150.732,0 272.923,-122.19 272.923,-272.921 0,-30.797 -5.102,-60.403 -14.505,-88.02 -24.274,21.928 -56.449,35.28 -91.733,35.28 -25.109,0 -48.671,-6.793 -68.956,-18.635 -39.834,-23.257 -44.378,-56.178 -70.351,-71.339 -8.002,-4.672 -17.358,-7.354 -27.378,-7.354 -15.025,0 -28.634,6.094 -38.473,15.933 -9.843,9.843 -15.935,23.45 -15.935,38.475 0,15.025 6.092,28.628 15.935,38.473 31.056,31.055 79.918,0.672 135.285,56.038 z"
id="path6-3" />
</g>
<path
fill-rule="evenodd"
clip-rule="evenodd"
fill="#1a283f"
d="m 130.33984,26.880256 c -3.16236,-2.773976 -6.38003,-3.606158 -10.65199,-3.606158 -4.9932,0 -11.53972,2.219223 -11.53972,8.543723 0,6.213868 6.15824,8.100027 11.31771,8.488514 3.88359,0.221902 5.43699,0.998661 5.43699,2.884821 0,1.997109 -2.3857,3.328942 -4.93756,3.273306 -3.0514,-0.05542 -7.48974,-1.664365 -9.43143,-3.828059 l -3.32873,4.826615 c 3.99444,4.16091 8.32193,4.882248 12.64922,4.882248 7.8227,0 11.7616,-4.160911 11.7616,-8.987525 0,-7.267846 -6.5465,-8.432879 -11.70619,-8.765837 -3.49509,-0.221902 -5.10415,-1.220563 -5.10415,-2.995878 0,-1.719787 1.77542,-2.71834 4.9932,-2.71834 2.60739,0 4.82683,0.61028 6.7683,2.441125 z m 26.57462,-2.884929 -3.77274,9.154112 -4.16091,11.428864 -4.21655,-11.539709 -3.77243,-9.043159 h -7.37879 l 11.70597,27.517648 h 7.32359 l 11.65045,-27.517648 h -7.37859 z m 17.4203,-0.05552 v 27.462122 h -6.76852 V 23.939802 Z m -7.37847,-7.600591 c 0,5.270417 7.98896,5.270417 7.98896,0 -10e-5,-5.270523 -7.98896,-5.270523 -7.98896,0 z m 26.68514,16.976603 -5.38137,-9.26485 h -8.09992 v 0.22169 l 8.98753,13.259494 -9.54228,13.703403 v 0.166266 h 8.09993 l 5.93611,-9.154112 5.93655,9.154111 h 8.09992 v -0.166266 l -9.54218,-13.703403 8.98743,-13.259494 v -0.22169 h -8.09992 z"
id="path10-6"
style="stroke-width:0.106376" />
</g>
<g
aria-label="Webhooks as a Service"
id="text1936"
style="font-style:normal;font-weight:normal;font-size:16px;line-height:1.25;font-family:sans-serif;fill:#000000;fill-opacity:1;stroke:none">
<path
d="M 43.474213,86.844101 H 40.739838 L 39.24765,80.476913 q -0.273437,-1.125 -0.460937,-2.351562 -0.1875,1.023437 -0.304688,1.5625 -0.117187,0.53125 -1.664062,7.15625 H 34.083588 L 31.24765,75.836288 h 2.335938 l 1.59375,7.109375 0.359375,1.71875 q 0.21875,-1.085937 0.421875,-2.070312 0.210937,-0.992188 1.5625,-6.757813 h 2.578125 l 1.390625,5.859375 q 0.164062,0.65625 0.554687,2.96875 l 0.195313,-0.90625 0.414062,-1.796875 1.328125,-6.125 h 2.335938 z"
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:16px;font-family:'Nimbus Sans';-inkscape-font-specification:'Nimbus Sans Bold'"
id="path840" />
<path
d="m 50.62265,87.000351 q -1.90625,0 -2.929687,-1.125 -1.023438,-1.132813 -1.023438,-3.296875 0,-2.09375 1.039063,-3.21875 1.039062,-1.125 2.945312,-1.125 1.820313,0 2.78125,1.210937 0.960938,1.203125 0.960938,3.53125 v 0.0625 h -5.421875 q 0,1.234375 0.453125,1.867188 0.460937,0.625 1.304687,0.625 1.164063,0 1.46875,-1.007813 l 2.070313,0.179688 q -0.898438,2.296875 -3.648438,2.296875 z m 0,-7.382813 q -0.773437,0 -1.195312,0.539063 -0.414063,0.539062 -0.4375,1.507812 h 3.28125 q -0.0625,-1.023437 -0.492188,-1.53125 -0.429687,-0.515625 -1.15625,-0.515625 z"
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:16px;font-family:'Nimbus Sans';-inkscape-font-specification:'Nimbus Sans Bold'"
id="path842" />
<path
d="m 64.067963,82.586288 q 0,2.09375 -0.84375,3.257813 -0.835938,1.15625 -2.398438,1.15625 -0.898437,0 -1.554687,-0.390625 -0.65625,-0.390625 -1.007813,-1.125 h -0.01563 q 0,0.273437 -0.03906,0.75 -0.03125,0.476562 -0.07031,0.609375 h -2.132812 q 0.0625,-0.726563 0.0625,-1.929688 v -9.664062 h 2.195312 v 3.234375 l -0.03125,1.375 h 0.03125 q 0.742188,-1.625 2.703125,-1.625 1.5,0 2.296875,1.140625 0.804688,1.132812 0.804688,3.210937 z m -2.289063,0 q 0,-1.4375 -0.421875,-2.132812 -0.421875,-0.695313 -1.304687,-0.695313 -0.890625,0 -1.359375,0.75 -0.460938,0.742188 -0.460938,2.148438 0,1.34375 0.453125,2.09375 0.460938,0.75 1.351563,0.75 1.742187,0 1.742187,-2.914063 z"
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:16px;font-family:'Nimbus Sans';-inkscape-font-specification:'Nimbus Sans Bold'"
id="path844" />
<path
d="m 68.013275,80.078476 q 0.445313,-0.96875 1.117188,-1.40625 0.671875,-0.4375 1.601562,-0.4375 1.34375,0 2.0625,0.828125 0.71875,0.828125 0.71875,2.421875 v 5.359375 h -2.1875 v -4.734375 q 0,-2.226563 -1.507812,-2.226563 -0.796875,0 -1.289063,0.6875 -0.484375,0.679688 -0.484375,1.75 v 4.523438 h -2.195312 v -11.59375 h 2.195312 v 3.164062 q 0,0.851563 -0.0625,1.664063 z"
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:16px;font-family:'Nimbus Sans';-inkscape-font-specification:'Nimbus Sans Bold'"
id="path846" />
<path
d="m 83.661713,82.609726 q 0,2.054687 -1.140625,3.226562 -1.140625,1.164063 -3.15625,1.164063 -1.976563,0 -3.101563,-1.171875 -1.125,-1.171875 -1.125,-3.21875 0,-2.039063 1.125,-3.203125 1.125,-1.171875 3.148438,-1.171875 2.070312,0 3.15625,1.132812 1.09375,1.125 1.09375,3.242188 z m -2.296875,0 q 0,-1.507813 -0.492188,-2.1875 -0.492187,-0.679688 -1.429687,-0.679688 -2,0 -2,2.867188 0,1.414062 0.484375,2.15625 0.492187,0.734375 1.414062,0.734375 2.023438,0 2.023438,-2.890625 z"
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:16px;font-family:'Nimbus Sans';-inkscape-font-specification:'Nimbus Sans Bold'"
id="path848" />
<path
d="m 93.442963,82.609726 q 0,2.054687 -1.140625,3.226562 -1.140625,1.164063 -3.15625,1.164063 -1.976563,0 -3.101563,-1.171875 -1.125,-1.171875 -1.125,-3.21875 0,-2.039063 1.125,-3.203125 1.125,-1.171875 3.148438,-1.171875 2.070312,0 3.15625,1.132812 1.09375,1.125 1.09375,3.242188 z m -2.296875,0 q 0,-1.507813 -0.492188,-2.1875 -0.492187,-0.679688 -1.429687,-0.679688 -2,0 -2,2.867188 0,1.414062 0.484375,2.15625 0.492187,0.734375 1.414062,0.734375 2.023438,0 2.023438,-2.890625 z"
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:16px;font-family:'Nimbus Sans';-inkscape-font-specification:'Nimbus Sans Bold'"
id="path850" />
<path
d="m 100.5914,86.844101 -2.257812,-3.828125 -0.945313,0.65625 v 3.171875 h -2.195312 v -11.59375 h 2.195312 v 6.640625 l 3.015625,-3.5 h 2.35938 l -2.968755,3.296875 3.195315,5.15625 z"
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:16px;font-family:'Nimbus Sans';-inkscape-font-specification:'Nimbus Sans Bold'"
id="path852" />
<path
d="m 111.22421,84.375351 q 0,1.226562 -1.00781,1.929687 -1,0.695313 -2.77344,0.695313 -1.74218,0 -2.67187,-0.546875 -0.92188,-0.554688 -1.22656,-1.71875 l 1.92968,-0.289063 q 0.16407,0.601563 0.5625,0.851563 0.40625,0.25 1.40625,0.25 0.92188,0 1.34375,-0.234375 0.42188,-0.234375 0.42188,-0.734375 0,-0.40625 -0.34375,-0.640625 -0.33594,-0.242188 -1.14844,-0.40625 -1.85937,-0.367188 -2.50781,-0.679688 -0.64844,-0.320312 -0.99219,-0.820312 -0.33594,-0.507813 -0.33594,-1.242188 0,-1.210937 0.92969,-1.882812 0.9375,-0.679688 2.64844,-0.679688 1.50781,0 2.42187,0.585938 0.92188,0.585937 1.14844,1.695312 l -1.94531,0.203125 q -0.0937,-0.515625 -0.46094,-0.765625 -0.36719,-0.257812 -1.16406,-0.257812 -0.78125,0 -1.17188,0.203125 -0.39062,0.195312 -0.39062,0.664062 0,0.367188 0.29687,0.585938 0.30469,0.210937 1.01563,0.351562 0.99219,0.203125 1.75781,0.421875 0.77344,0.210938 1.23438,0.507813 0.46875,0.296875 0.74218,0.765625 0.28125,0.460937 0.28125,1.1875 z"
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:16px;font-family:'Nimbus Sans';-inkscape-font-specification:'Nimbus Sans Bold'"
id="path854" />
<path
d="m 119.39609,87.000351 q -1.22656,0 -1.91406,-0.664063 -0.6875,-0.671875 -0.6875,-1.882812 0,-1.3125 0.85156,-2 0.85937,-0.6875 2.48437,-0.703125 l 1.82032,-0.03125 v -0.429688 q 0,-0.828125 -0.28907,-1.226562 -0.28906,-0.40625 -0.94531,-0.40625 -0.60937,0 -0.89844,0.28125 -0.28125,0.273437 -0.35156,0.914062 l -2.28906,-0.109375 q 0.21094,-1.234375 1.125,-1.867187 0.92187,-0.640625 2.50781,-0.640625 1.60156,0 2.46875,0.789062 0.86719,0.789063 0.86719,2.242188 v 3.078125 q 0,0.710937 0.15625,0.984375 0.16406,0.265625 0.53906,0.265625 0.25,0 0.48438,-0.04687 v 1.1875 q -0.19532,0.04687 -0.35157,0.08594 -0.15625,0.03906 -0.3125,0.0625 -0.15625,0.02344 -0.33593,0.03906 -0.17188,0.01563 -0.40625,0.01563 -0.82813,0 -1.22657,-0.40625 -0.39062,-0.40625 -0.46875,-1.195313 h -0.0469 q -0.92188,1.664063 -2.78125,1.664063 z m 2.55469,-4.070313 -1.125,0.01563 q -0.76563,0.03125 -1.08594,0.171875 -0.32031,0.132813 -0.49219,0.414063 -0.16406,0.28125 -0.16406,0.75 0,0.601562 0.27344,0.898437 0.28125,0.289063 0.74218,0.289063 0.51563,0 0.9375,-0.28125 0.42969,-0.28125 0.67188,-0.773438 0.24219,-0.5 0.24219,-1.054687 z"
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:16px;font-family:'Nimbus Sans';-inkscape-font-specification:'Nimbus Sans Bold'"
id="path856" />
<path
d="m 133.47421,84.375351 q 0,1.226562 -1.00781,1.929687 -1,0.695313 -2.77344,0.695313 -1.74218,0 -2.67187,-0.546875 -0.92188,-0.554688 -1.22656,-1.71875 l 1.92968,-0.289063 q 0.16407,0.601563 0.5625,0.851563 0.40625,0.25 1.40625,0.25 0.92188,0 1.34375,-0.234375 0.42188,-0.234375 0.42188,-0.734375 0,-0.40625 -0.34375,-0.640625 -0.33594,-0.242188 -1.14844,-0.40625 -1.85937,-0.367188 -2.50781,-0.679688 -0.64844,-0.320312 -0.99219,-0.820312 -0.33594,-0.507813 -0.33594,-1.242188 0,-1.210937 0.92969,-1.882812 0.9375,-0.679688 2.64844,-0.679688 1.50781,0 2.42187,0.585938 0.92188,0.585937 1.14844,1.695312 l -1.94531,0.203125 q -0.0937,-0.515625 -0.46094,-0.765625 -0.36719,-0.257812 -1.16406,-0.257812 -0.78125,0 -1.17188,0.203125 -0.39062,0.195312 -0.39062,0.664062 0,0.367188 0.29687,0.585938 0.30469,0.210937 1.01563,0.351562 0.99219,0.203125 1.75781,0.421875 0.77344,0.210938 1.23438,0.507813 0.46875,0.296875 0.74218,0.765625 0.28125,0.460937 0.28125,1.1875 z"
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:16px;font-family:'Nimbus Sans';-inkscape-font-specification:'Nimbus Sans Bold'"
id="path858" />
<path
d="m 141.64609,87.000351 q -1.22656,0 -1.91406,-0.664063 -0.6875,-0.671875 -0.6875,-1.882812 0,-1.3125 0.85156,-2 0.85937,-0.6875 2.48437,-0.703125 l 1.82032,-0.03125 v -0.429688 q 0,-0.828125 -0.28907,-1.226562 -0.28906,-0.40625 -0.94531,-0.40625 -0.60937,0 -0.89844,0.28125 -0.28125,0.273437 -0.35156,0.914062 l -2.28906,-0.109375 q 0.21094,-1.234375 1.125,-1.867187 0.92187,-0.640625 2.50781,-0.640625 1.60156,0 2.46875,0.789062 0.86719,0.789063 0.86719,2.242188 v 3.078125 q 0,0.710937 0.15625,0.984375 0.16406,0.265625 0.53906,0.265625 0.25,0 0.48438,-0.04687 v 1.1875 q -0.19532,0.04687 -0.35157,0.08594 -0.15625,0.03906 -0.3125,0.0625 -0.15625,0.02344 -0.33593,0.03906 -0.17188,0.01563 -0.40625,0.01563 -0.82813,0 -1.22657,-0.40625 -0.39062,-0.40625 -0.46875,-1.195313 h -0.0469 q -0.92188,1.664063 -2.78125,1.664063 z m 2.55469,-4.070313 -1.125,0.01563 q -0.76563,0.03125 -1.08594,0.171875 -0.32031,0.132813 -0.49219,0.414063 -0.16406,0.28125 -0.16406,0.75 0,0.601562 0.27344,0.898437 0.28125,0.289063 0.74218,0.289063 0.51563,0 0.9375,-0.28125 0.42969,-0.28125 0.67188,-0.773438 0.24219,-0.5 0.24219,-1.054687 z"
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:16px;font-family:'Nimbus Sans';-inkscape-font-specification:'Nimbus Sans Bold'"
id="path860" />
<path
d="m 161.9664,83.672226 q 0,1.617187 -1.20312,2.476562 -1.19532,0.851563 -3.51563,0.851563 -2.11719,0 -3.32031,-0.75 -1.20313,-0.75 -1.54688,-2.273438 l 2.22657,-0.367187 q 0.22656,0.875 0.88281,1.273437 0.65625,0.390625 1.82031,0.390625 2.41406,0 2.41406,-1.46875 0,-0.46875 -0.28125,-0.773437 -0.27343,-0.304688 -0.78125,-0.507813 -0.5,-0.203125 -1.92968,-0.492187 -1.23438,-0.289063 -1.71875,-0.460938 -0.48438,-0.179687 -0.875,-0.414062 -0.39063,-0.242188 -0.66407,-0.578125 -0.27343,-0.335938 -0.42968,-0.789063 -0.14844,-0.453125 -0.14844,-1.039062 0,-1.492188 1.11719,-2.28125 1.125,-0.796875 3.26562,-0.796875 2.04688,0 3.07031,0.640625 1.03125,0.640625 1.32813,2.117187 l -2.23438,0.304688 q -0.17187,-0.710938 -0.70312,-1.070313 -0.52344,-0.359375 -1.50781,-0.359375 -2.09375,0 -2.09375,1.3125 0,0.429688 0.21875,0.703125 0.22656,0.273438 0.66406,0.46875 0.4375,0.1875 1.77344,0.476563 1.58593,0.335937 2.26562,0.625 0.6875,0.28125 1.08594,0.664062 0.39844,0.375 0.60937,0.90625 0.21094,0.523438 0.21094,1.210938 z"
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:16px;font-family:'Nimbus Sans';-inkscape-font-specification:'Nimbus Sans Bold'"
id="path862" />
<path
d="m 167.18515,87.000351 q -1.90625,0 -2.92969,-1.125 -1.02343,-1.132813 -1.02343,-3.296875 0,-2.09375 1.03906,-3.21875 1.03906,-1.125 2.94531,-1.125 1.82031,0 2.78125,1.210937 0.96094,1.203125 0.96094,3.53125 v 0.0625 h -5.42188 q 0,1.234375 0.45313,1.867188 0.46094,0.625 1.30469,0.625 1.16406,0 1.46875,-1.007813 l 2.07031,0.179688 q -0.89844,2.296875 -3.64844,2.296875 z m 0,-7.382813 q -0.77344,0 -1.19531,0.539063 -0.41406,0.539062 -0.4375,1.507812 h 3.28125 q -0.0625,-1.023437 -0.49219,-1.53125 -0.42969,-0.515625 -1.15625,-0.515625 z"
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:16px;font-family:'Nimbus Sans';-inkscape-font-specification:'Nimbus Sans Bold'"
id="path864" />
<path
d="m 172.63046,86.844101 v -6.46875 q 0,-0.695313 -0.0234,-1.15625 -0.0156,-0.46875 -0.0391,-0.828125 h 2.09375 q 0.0234,0.140625 0.0625,0.859375 0.0391,0.710937 0.0391,0.945312 h 0.0312 q 0.32031,-0.890625 0.57031,-1.25 0.25,-0.367187 0.59375,-0.539062 0.34375,-0.179688 0.85937,-0.179688 0.42188,0 0.67969,0.117188 v 1.835937 q -0.53125,-0.117187 -0.9375,-0.117187 -0.82031,0 -1.28125,0.664062 -0.45312,0.664063 -0.45312,1.96875 v 4.148438 z"
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:16px;font-family:'Nimbus Sans';-inkscape-font-specification:'Nimbus Sans Bold'"
id="path866" />
<path
d="m 183.44296,86.844101 h -2.625 l -3.02343,-8.453125 h 2.32031 l 1.47656,4.726562 q 0.11719,0.390625 0.55469,1.953125 0.0781,-0.320312 0.32031,-1.125 0.24219,-0.804687 1.79688,-5.554687 h 2.29687 z"
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:16px;font-family:'Nimbus Sans';-inkscape-font-specification:'Nimbus Sans Bold'"
id="path868" />
<path
d="m 187.75546,76.867538 v -1.617187 h 2.19532 v 1.617187 z m 0,9.976563 v -8.453125 h 2.19532 v 8.453125 z"
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:16px;font-family:'Nimbus Sans';-inkscape-font-specification:'Nimbus Sans Bold'"
id="path870" />
<path
d="m 195.7164,87.000351 q -1.92187,0 -2.96875,-1.140625 -1.04687,-1.148438 -1.04687,-3.195313 0,-2.09375 1.05468,-3.257812 1.05469,-1.171875 2.99219,-1.171875 1.49219,0 2.46875,0.75 0.97656,0.75 1.22656,2.070312 l -2.21093,0.109375 q -0.0937,-0.648437 -0.46875,-1.03125 -0.375,-0.390625 -1.0625,-0.390625 -1.69532,0 -1.69532,2.835938 0,2.921875 1.72657,2.921875 0.625,0 1.04687,-0.390625 0.42188,-0.398438 0.52344,-1.179688 l 2.20312,0.101563 q -0.11718,0.867187 -0.625,1.546875 -0.5,0.679687 -1.32031,1.054687 -0.82031,0.367188 -1.84375,0.367188 z"
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:16px;font-family:'Nimbus Sans';-inkscape-font-specification:'Nimbus Sans Bold'"
id="path872" />
<path
d="m 204.56015,87.000351 q -1.90625,0 -2.92969,-1.125 -1.02343,-1.132813 -1.02343,-3.296875 0,-2.09375 1.03906,-3.21875 1.03906,-1.125 2.94531,-1.125 1.82031,0 2.78125,1.210937 0.96094,1.203125 0.96094,3.53125 v 0.0625 h -5.42188 q 0,1.234375 0.45313,1.867188 0.46094,0.625 1.30469,0.625 1.16406,0 1.46875,-1.007813 l 2.07031,0.179688 q -0.89844,2.296875 -3.64844,2.296875 z m 0,-7.382813 q -0.77344,0 -1.19531,0.539063 -0.41406,0.539062 -0.4375,1.507812 h 3.28125 q -0.0625,-1.023437 -0.49219,-1.53125 -0.42969,-0.515625 -1.15625,-0.515625 z"
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:16px;font-family:'Nimbus Sans';-inkscape-font-specification:'Nimbus Sans Bold'"
id="path874" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 22 KiB

View File

@@ -8,8 +8,8 @@
<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 href="https://coverage-badge.samuelcolvin.workers.dev/redirect/tiangolo/fastapi" target="_blank">
<img src="https://coverage-badge.samuelcolvin.workers.dev/tiangolo/fastapi.svg" 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">
@@ -27,12 +27,11 @@
---
FastAPI is a modern, fast (high-performance), web framework for building APIs with Python 3.6+ based on standard Python type hints.
FastAPI is a modern, fast (high-performance), web framework for building APIs with Python 3.7+ 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.
@@ -100,6 +99,12 @@ The key features are:
---
"_If anyone is looking to build a production Python API, I would highly recommend **FastAPI**. It is **beautifully designed**, **simple to use** and **highly scalable**, it has become a **key component** in our API first development strategy and is driving many automations and services such as our Virtual TAC Engineer._"
<div style="text-align: right; margin-right: 10%;">Deon Pillsbury - <strong>Cisco</strong> <a href="https://www.linkedin.com/posts/deonpillsbury_cisco-cx-python-activity-6963242628536487936-trAp/" 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>
@@ -110,7 +115,7 @@ If you are building a <abbr title="Command Line Interface">CLI</abbr> app to be
## Requirements
Python 3.6+
Python 3.7+
FastAPI stands on the shoulders of giants:
@@ -129,7 +134,7 @@ $ pip install fastapi
</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>.
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://github.com/pgjones/hypercorn" class="external-link" target="_blank">Hypercorn</a>.
<div class="termy">
@@ -326,7 +331,7 @@ 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+**.
Just standard **Python 3.7+**.
For example, for an `int`:
@@ -425,7 +430,7 @@ For a more complete example including more features, see the <a href="https://fa
* **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`
* extremely easy tests based on HTTPX and `pytest`
* **CORS**
* **Cookie Sessions**
* ...and more.
@@ -445,7 +450,7 @@ 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://www.python-httpx.org" target="_blank"><code>httpx</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.

View File

@@ -1,6 +1,6 @@
# Project Generation - Template
You can use a project generator to get started, as it includes a lot of the initial set up, security, database and first API endpoints already done for you.
You can use a project generator to get started, as it includes a lot of the initial set up, security, database and some API endpoints already done for you.
A project generator will always have a very opinionated setup that you should update and adapt for your own needs, but it might be a good starting point for your project.

View File

@@ -1,8 +1,8 @@
# Python Types Intro
Python has support for optional "type hints".
Python has support for optional "type hints" (also called "type annotations").
These **"type hints"** are a special syntax that allow declaring the <abbr title="for example: str, int, float, bool">type</abbr> of a variable.
These **"type hints"** or annotations are a special syntax that allow declaring the <abbr title="for example: str, int, float, bool">type</abbr> of a variable.
By declaring types for your variables, editors and tools can give you better support.
@@ -158,13 +158,31 @@ The syntax using `typing` is **compatible** with all versions, from Python 3.6 t
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.
If you can choose a more recent version of Python for your project, you will be able to take advantage of that extra simplicity.
In all the docs there are examples compatible with each version of Python (when there's a difference).
For example "**Python 3.6+**" means it's compatible with Python 3.6 or above (including 3.7, 3.8, 3.9, 3.10, etc). And "**Python 3.9+**" means it's compatible with Python 3.9 or above (including 3.10, etc).
If you can use the **latest versions of Python**, use the examples for the latest version, those will have the **best and simplest syntax**, for example, "**Python 3.10+**".
#### List
For example, let's define a variable to be a `list` of `str`.
=== "Python 3.6 and above"
=== "Python 3.9+"
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!}
```
=== "Python 3.6+"
From `typing`, import `List` (with a capital `L`):
@@ -182,18 +200,6 @@ For example, let's define a variable to be a `list` of `str`.
{!> ../../../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".
@@ -218,18 +224,18 @@ And still, the editor knows it is a `str`, and provides support for that.
You would do the same to declare `tuple`s and `set`s:
=== "Python 3.6 and above"
```Python hl_lines="1 4"
{!> ../../../docs_src/python_types/tutorial007.py!}
```
=== "Python 3.9 and above"
=== "Python 3.9+"
```Python hl_lines="1"
{!> ../../../docs_src/python_types/tutorial007_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="1 4"
{!> ../../../docs_src/python_types/tutorial007.py!}
```
This means:
* The variable `items_t` is a `tuple` with 3 items, an `int`, another `int`, and a `str`.
@@ -243,18 +249,18 @@ The first type parameter is for the keys of the `dict`.
The second type parameter is for the values of the `dict`:
=== "Python 3.6 and above"
```Python hl_lines="1 4"
{!> ../../../docs_src/python_types/tutorial008.py!}
```
=== "Python 3.9 and above"
=== "Python 3.9+"
```Python hl_lines="1"
{!> ../../../docs_src/python_types/tutorial008_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="1 4"
{!> ../../../docs_src/python_types/tutorial008.py!}
```
This means:
* The variable `prices` is a `dict`:
@@ -267,20 +273,20 @@ You can declare that a variable can be any of **several types**, for example, an
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** where 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>.
In Python 3.10 there's also a **new syntax** where 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 3.10+"
```Python hl_lines="1"
{!> ../../../docs_src/python_types/tutorial008b_py310.py!}
```
=== "Python 3.6+"
```Python hl_lines="1 4"
{!> ../../../docs_src/python_types/tutorial008b.py!}
```
In both cases this means that `item` could be an `int` or a `str`.
#### Possibly `None`
@@ -299,24 +305,24 @@ Using `Optional[str]` instead of just `str` will let the editor help you detecti
This also means that in Python 3.10, you can use `Something | None`:
=== "Python 3.6 and above"
=== "Python 3.10+"
```Python hl_lines="1"
{!> ../../../docs_src/python_types/tutorial009_py310.py!}
```
=== "Python 3.6+"
```Python hl_lines="1 4"
{!> ../../../docs_src/python_types/tutorial009.py!}
```
=== "Python 3.6 and above - alternative"
=== "Python 3.6+ 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!}
```
#### Using `Union` or `Optional`
If you are using a Python version below 3.10, here's a tip from my very **subjective** point of view:
@@ -360,34 +366,9 @@ And then you won't have to worry about names like `Optional` and `Union`. 😎
These types that take type parameters in square brackets are called **Generic types** or **Generics**, for example:
=== "Python 3.6 and above"
=== "Python 3.10+"
* `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):
You can use the same builtin types as generics (with square brackets and types inside):
* `list`
* `tuple`
@@ -400,7 +381,32 @@ These types that take type parameters in square brackets are called **Generic ty
* `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.
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, that's a lot better and simpler.
=== "Python 3.9+"
You can use the same builtin types as generics (with square brackets 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.6+"
* `List`
* `Tuple`
* `Set`
* `Dict`
* `Union`
* `Optional`
* ...and others.
### Classes as types
@@ -422,6 +428,10 @@ And then, again, you get all the editor support:
<img src="/img/python-types/image06.png">
Notice that this means "`one_person` is an **instance** of the class `Person`".
It doesn't mean "`one_person` is the **class** called `Person`".
## Pydantic models
<a href="https://pydantic-docs.helpmanual.io/" class="external-link" target="_blank">Pydantic</a> is a Python library to perform data validation.
@@ -436,22 +446,22 @@ And you get all the editor support with that resulting object.
An example from the official Pydantic docs:
=== "Python 3.6 and above"
=== "Python 3.10+"
```Python
{!> ../../../docs_src/python_types/tutorial011.py!}
{!> ../../../docs_src/python_types/tutorial011_py310.py!}
```
=== "Python 3.9 and above"
=== "Python 3.9+"
```Python
{!> ../../../docs_src/python_types/tutorial011_py39.py!}
```
=== "Python 3.10 and above"
=== "Python 3.6+"
```Python
{!> ../../../docs_src/python_types/tutorial011_py310.py!}
{!> ../../../docs_src/python_types/tutorial011.py!}
```
!!! info
@@ -464,6 +474,43 @@ You will see a lot more of all this in practice in the [Tutorial - User Guide](t
!!! tip
Pydantic has a special behavior when you use `Optional` or `Union[Something, None]` without a default value, you can read more about it in the Pydantic docs about <a href="https://pydantic-docs.helpmanual.io/usage/models/#required-optional-fields" class="external-link" target="_blank">Required Optional fields</a>.
## Type Hints with Metadata Annotations
Python also has a feature that allows putting **additional metadata** in these type hints using `Annotated`.
=== "Python 3.9+"
In Python 3.9, `Annotated` is part of the standard library, so you can import it from `typing`.
```Python hl_lines="1 4"
{!> ../../../docs_src/python_types/tutorial013_py39.py!}
```
=== "Python 3.6+"
In versions below Python 3.9, you import `Annotated` from `typing_extensions`.
It will already be installed with **FastAPI**.
```Python hl_lines="1 4"
{!> ../../../docs_src/python_types/tutorial013.py!}
```
Python itself doesn't do anything with this `Annotated`. And for editors and other tools, the type is still `str`.
But you can use this space in `Annotated` to provide **FastAPI** with additional metadata about how you want your application to behave.
The important thing to remember is that **the first *type parameter*** you pass to `Annotated` is the **actual type**. The rest, is just metadata for other tools.
For now, you just need to know that `Annotated` exists, and that it's standard Python. 😎
Later you will see how **powerful** it can be.
!!! tip
The fact that this is **standard Python** means that you will still get the **best possible developer experience** in your editor, with the tools you use to analyze and refactor your code, etc. ✨
And also that your code will be very compatible with many other Python tools and libraries. 🚀
## Type hints in **FastAPI**
**FastAPI** takes advantage of these type hints to do several things.

View File

@@ -3,6 +3,663 @@
## Latest Changes
## 0.95.0
### Highlights
This release adds support for dependencies and parameters using `Annotated` and recommends its usage. ✨
This has **several benefits**, one of the main ones is that now the parameters of your functions with `Annotated` would **not be affected** at all.
If you call those functions in **other places in your code**, the actual **default values** will be kept, your editor will help you notice missing **required arguments**, Python will require you to pass required arguments at **runtime**, you will be able to **use the same functions** for different things and with different libraries (e.g. **Typer** will soon support `Annotated` too, then you could use the same function for an API and a CLI), etc.
Because `Annotated` is **standard Python**, you still get all the **benefits** from editors and tools, like **autocompletion**, **inline errors**, etc.
One of the **biggest benefits** is that now you can create `Annotated` dependencies that are then shared by multiple *path operation functions*, this will allow you to **reduce** a lot of **code duplication** in your codebase, while keeping all the support from editors and tools.
For example, you could have code like this:
```Python
def get_current_user(token: str):
# authenticate user
return User()
@app.get("/items/")
def read_items(user: User = Depends(get_current_user)):
...
@app.post("/items/")
def create_item(*, user: User = Depends(get_current_user), item: Item):
...
@app.get("/items/{item_id}")
def read_item(*, user: User = Depends(get_current_user), item_id: int):
...
@app.delete("/items/{item_id}")
def delete_item(*, user: User = Depends(get_current_user), item_id: int):
...
```
There's a bit of code duplication for the dependency:
```Python
user: User = Depends(get_current_user)
```
...the bigger the codebase, the more noticeable it is.
Now you can create an annotated dependency once, like this:
```Python
CurrentUser = Annotated[User, Depends(get_current_user)]
```
And then you can reuse this `Annotated` dependency:
```Python
CurrentUser = Annotated[User, Depends(get_current_user)]
@app.get("/items/")
def read_items(user: CurrentUser):
...
@app.post("/items/")
def create_item(user: CurrentUser, item: Item):
...
@app.get("/items/{item_id}")
def read_item(user: CurrentUser, item_id: int):
...
@app.delete("/items/{item_id}")
def delete_item(user: CurrentUser, item_id: int):
...
```
...and `CurrentUser` has all the typing information as `User`, so your editor will work as expected (autocompletion and everything), and **FastAPI** will be able to understand the dependency defined in `Annotated`. 😎
Roughly **all the docs** have been rewritten to use `Annotated` as the main way to declare **parameters** and **dependencies**. All the **examples** in the docs now include a version with `Annotated` and a version without it, for each of the specific Python versions (when there are small differences/improvements in more recent versions). There were around 23K new lines added between docs, examples, and tests. 🚀
The key updated docs are:
* Python Types Intro:
* [Type Hints with Metadata Annotations](https://fastapi.tiangolo.com/python-types/#type-hints-with-metadata-annotations).
* Tutorial:
* [Query Parameters and String Validations - Additional validation](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#additional-validation)
* [Advantages of `Annotated`](https://fastapi.tiangolo.com/tutorial/query-params-str-validations/#advantages-of-annotated)
* [Path Parameters and Numeric Validations - Order the parameters as you need, tricks](https://fastapi.tiangolo.com/tutorial/path-params-numeric-validations/#order-the-parameters-as-you-need-tricks)
* [Better with `Annotated`](https://fastapi.tiangolo.com/tutorial/path-params-numeric-validations/#better-with-annotated)
* [Dependencies - First Steps - Share `Annotated` dependencies](https://fastapi.tiangolo.com/tutorial/dependencies/#share-annotated-dependencies)
Special thanks to [@nzig](https://github.com/nzig) for the core implementation and to [@adriangb](https://github.com/adriangb) for the inspiration and idea with [Xpresso](https://github.com/adriangb/xpresso)! 🚀
### Features
* ✨Add support for PEP-593 `Annotated` for specifying dependencies and parameters. PR [#4871](https://github.com/tiangolo/fastapi/pull/4871) by [@nzig](https://github.com/nzig).
### Docs
* 📝 Tweak tip recommending `Annotated` in docs. PR [#9270](https://github.com/tiangolo/fastapi/pull/9270) by [@tiangolo](https://github.com/tiangolo).
* 📝 Update order of examples, latest Python version first, and simplify version tab names. PR [#9269](https://github.com/tiangolo/fastapi/pull/9269) by [@tiangolo](https://github.com/tiangolo).
* 📝 Update all docs to use `Annotated` as the main recommendation, with new examples and tests. PR [#9268](https://github.com/tiangolo/fastapi/pull/9268) by [@tiangolo](https://github.com/tiangolo).
## 0.94.1
### Fixes
* 🎨 Fix types for lifespan, upgrade Starlette to 0.26.1. PR [#9245](https://github.com/tiangolo/fastapi/pull/9245) by [@tiangolo](https://github.com/tiangolo).
## 0.94.0
### Upgrades
* ⬆ Upgrade python-multipart to support 0.0.6. PR [#9212](https://github.com/tiangolo/fastapi/pull/9212) by [@musicinmybrain](https://github.com/musicinmybrain).
* ⬆️ Upgrade Starlette version, support new `lifespan` with state. PR [#9239](https://github.com/tiangolo/fastapi/pull/9239) by [@tiangolo](https://github.com/tiangolo).
### Docs
* 📝 Update Sentry link in docs. PR [#9218](https://github.com/tiangolo/fastapi/pull/9218) by [@smeubank](https://github.com/smeubank).
### Translations
* 🌐 Add Russian translation for `docs/ru/docs/history-design-future.md`. PR [#5986](https://github.com/tiangolo/fastapi/pull/5986) by [@Xewus](https://github.com/Xewus).
### Internal
* Add `pydantic` to PyPI classifiers. PR [#5914](https://github.com/tiangolo/fastapi/pull/5914) by [@yezz123](https://github.com/yezz123).
* ⬆ Bump black from 22.10.0 to 23.1.0. PR [#5953](https://github.com/tiangolo/fastapi/pull/5953) by [@dependabot[bot]](https://github.com/apps/dependabot).
* ⬆ Bump types-ujson from 5.6.0.0 to 5.7.0.1. PR [#6027](https://github.com/tiangolo/fastapi/pull/6027) by [@dependabot[bot]](https://github.com/apps/dependabot).
* ⬆ Bump dawidd6/action-download-artifact from 2.24.3 to 2.26.0. PR [#6034](https://github.com/tiangolo/fastapi/pull/6034) by [@dependabot[bot]](https://github.com/apps/dependabot).
* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#5709](https://github.com/tiangolo/fastapi/pull/5709) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci).
## 0.93.0
### Features
* ✨ Add support for `lifespan` async context managers (superseding `startup` and `shutdown` events). Initial PR [#2944](https://github.com/tiangolo/fastapi/pull/2944) by [@uSpike](https://github.com/uSpike).
Now, instead of using independent `startup` and `shutdown` events, you can define that logic in a single function with `yield` decorated with `@asynccontextmanager` (an async context manager).
For example:
```Python
from contextlib import asynccontextmanager
from fastapi import FastAPI
def fake_answer_to_everything_ml_model(x: float):
return x * 42
ml_models = {}
@asynccontextmanager
async def lifespan(app: FastAPI):
# Load the ML model
ml_models["answer_to_everything"] = fake_answer_to_everything_ml_model
yield
# Clean up the ML models and release the resources
ml_models.clear()
app = FastAPI(lifespan=lifespan)
@app.get("/predict")
async def predict(x: float):
result = ml_models["answer_to_everything"](x)
return {"result": result}
```
**Note**: This is the recommended way going forward, instead of using `startup` and `shutdown` events.
Read more about it in the new docs: [Advanced User Guide: Lifespan Events](https://fastapi.tiangolo.com/advanced/events/).
### Docs
* ✏ Fix formatting in `docs/en/docs/tutorial/metadata.md` for `ReDoc`. PR [#6005](https://github.com/tiangolo/fastapi/pull/6005) by [@eykamp](https://github.com/eykamp).
### Translations
* 🌐 Tamil translations - initial setup. PR [#5564](https://github.com/tiangolo/fastapi/pull/5564) by [@gusty1g](https://github.com/gusty1g).
* 🌐 Add French translation for `docs/fr/docs/advanced/path-operation-advanced-configuration.md`. PR [#9221](https://github.com/tiangolo/fastapi/pull/9221) by [@axel584](https://github.com/axel584).
* 🌐 Add French translation for `docs/tutorial/debugging.md`. PR [#9175](https://github.com/tiangolo/fastapi/pull/9175) by [@frabc](https://github.com/frabc).
* 🌐 Initiate Armenian translation setup. PR [#5844](https://github.com/tiangolo/fastapi/pull/5844) by [@har8](https://github.com/har8).
* 🌐 Add French translation for `deployment/manually.md`. PR [#3693](https://github.com/tiangolo/fastapi/pull/3693) by [@rjNemo](https://github.com/rjNemo).
### Internal
* 👷 Update translation bot messages. PR [#9206](https://github.com/tiangolo/fastapi/pull/9206) by [@tiangolo](https://github.com/tiangolo).
* 👷 Update translations bot to use Discussions, and notify when a PR is done. PR [#9183](https://github.com/tiangolo/fastapi/pull/9183) by [@tiangolo](https://github.com/tiangolo).
* 🔧 Update sponsors-badges. PR [#9182](https://github.com/tiangolo/fastapi/pull/9182) by [@tiangolo](https://github.com/tiangolo).
* 👥 Update FastAPI People. PR [#9181](https://github.com/tiangolo/fastapi/pull/9181) by [@github-actions[bot]](https://github.com/apps/github-actions).
* 🔊 Log GraphQL errors in FastAPI People, because it returns 200, with a payload with an error. PR [#9171](https://github.com/tiangolo/fastapi/pull/9171) by [@tiangolo](https://github.com/tiangolo).
* 💚 Fix/workaround GitHub Actions in Docker with git for FastAPI People. PR [#9169](https://github.com/tiangolo/fastapi/pull/9169) by [@tiangolo](https://github.com/tiangolo).
* ♻️ Refactor FastAPI Experts to use only discussions now that questions are migrated. PR [#9165](https://github.com/tiangolo/fastapi/pull/9165) by [@tiangolo](https://github.com/tiangolo).
* ⬆️ Upgrade analytics. PR [#6025](https://github.com/tiangolo/fastapi/pull/6025) by [@tiangolo](https://github.com/tiangolo).
* ⬆️ Upgrade and re-enable installing Typer-CLI. PR [#6008](https://github.com/tiangolo/fastapi/pull/6008) by [@tiangolo](https://github.com/tiangolo).
## 0.92.0
🚨 This is a security fix. Please upgrade as soon as possible.
### Upgrades
* ⬆️ Upgrade Starlette to 0.25.0. PR [#5996](https://github.com/tiangolo/fastapi/pull/5996) by [@tiangolo](https://github.com/tiangolo).
* This solves a vulnerability that could allow denial of service attacks by using many small multipart fields/files (parts), consuming high CPU and memory.
* Only applications using forms (e.g. file uploads) could be affected.
* For most cases, upgrading won't have any breaking changes.
## 0.91.0
### Upgrades
* ⬆️ Upgrade Starlette version to `0.24.0` and refactor internals for compatibility. PR [#5985](https://github.com/tiangolo/fastapi/pull/5985) by [@tiangolo](https://github.com/tiangolo).
* This can solve nuanced errors when using middlewares. Before Starlette `0.24.0`, a new instance of each middleware class would be created when a new middleware was added. That normally was not a problem, unless the middleware class expected to be created only once, with only one instance, that happened in some cases. This upgrade would solve those cases (thanks [@adriangb](https://github.com/adriangb)! Starlette PR [#2017](https://github.com/encode/starlette/pull/2017)). Now the middleware class instances are created once, right before the first request (the first time the app is called).
* If you depended on that previous behavior, you might need to update your code. As always, make sure your tests pass before merging the upgrade.
## 0.90.1
### Upgrades
* ⬆️ Upgrade Starlette range to allow 0.23.1. PR [#5980](https://github.com/tiangolo/fastapi/pull/5980) by [@tiangolo](https://github.com/tiangolo).
### Docs
* ✏ Tweak wording to clarify `docs/en/docs/project-generation.md`. PR [#5930](https://github.com/tiangolo/fastapi/pull/5930) by [@chandra-deb](https://github.com/chandra-deb).
* ✏ Update Pydantic GitHub URLs. PR [#5952](https://github.com/tiangolo/fastapi/pull/5952) by [@yezz123](https://github.com/yezz123).
* 📝 Add opinion from Cisco. PR [#5981](https://github.com/tiangolo/fastapi/pull/5981) by [@tiangolo](https://github.com/tiangolo).
### Translations
* 🌐 Add Russian translation for `docs/ru/docs/tutorial/cookie-params.md`. PR [#5890](https://github.com/tiangolo/fastapi/pull/5890) by [@bnzone](https://github.com/bnzone).
### Internal
* ✏ Update `zip-docs.sh` internal script, remove extra space. PR [#5931](https://github.com/tiangolo/fastapi/pull/5931) by [@JuanPerdomo00](https://github.com/JuanPerdomo00).
## 0.90.0
### Upgrades
* ⬆️ Bump Starlette from 0.22.0 to 0.23.0. Initial PR [#5739](https://github.com/tiangolo/fastapi/pull/5739) by [@Kludex](https://github.com/Kludex).
### Docs
* 📝 Add article "Tortoise ORM / FastAPI 整合快速筆記" to External Links. PR [#5496](https://github.com/tiangolo/fastapi/pull/5496) by [@Leon0824](https://github.com/Leon0824).
* 👥 Update FastAPI People. PR [#5954](https://github.com/tiangolo/fastapi/pull/5954) by [@github-actions[bot]](https://github.com/apps/github-actions).
* 📝 Micro-tweak help docs. PR [#5960](https://github.com/tiangolo/fastapi/pull/5960) by [@tiangolo](https://github.com/tiangolo).
* 🔧 Update new issue chooser to direct to GitHub Discussions. PR [#5948](https://github.com/tiangolo/fastapi/pull/5948) by [@tiangolo](https://github.com/tiangolo).
* 📝 Recommend GitHub Discussions for questions. PR [#5944](https://github.com/tiangolo/fastapi/pull/5944) by [@tiangolo](https://github.com/tiangolo).
### Translations
* 🌐 Add Russian translation for `docs/ru/docs/tutorial/body-fields.md`. PR [#5898](https://github.com/tiangolo/fastapi/pull/5898) by [@simatheone](https://github.com/simatheone).
* 🌐 Add Russian translation for `docs/ru/docs/help-fastapi.md`. PR [#5970](https://github.com/tiangolo/fastapi/pull/5970) by [@tiangolo](https://github.com/tiangolo).
* 🌐 Add Portuguese translation for `docs/pt/docs/tutorial/static-files.md`. PR [#5858](https://github.com/tiangolo/fastapi/pull/5858) by [@batlopes](https://github.com/batlopes).
* 🌐 Add Portuguese translation for `docs/pt/docs/tutorial/encoder.md`. PR [#5525](https://github.com/tiangolo/fastapi/pull/5525) by [@felipebpl](https://github.com/felipebpl).
* 🌐 Add Russian translation for `docs/ru/docs/contributing.md`. PR [#5870](https://github.com/tiangolo/fastapi/pull/5870) by [@Xewus](https://github.com/Xewus).
### Internal
* ⬆️ Upgrade Ubuntu version for docs workflow. PR [#5971](https://github.com/tiangolo/fastapi/pull/5971) by [@tiangolo](https://github.com/tiangolo).
* 🔧 Update sponsors badges. PR [#5943](https://github.com/tiangolo/fastapi/pull/5943) by [@tiangolo](https://github.com/tiangolo).
* ✨ Compute FastAPI Experts including GitHub Discussions. PR [#5941](https://github.com/tiangolo/fastapi/pull/5941) by [@tiangolo](https://github.com/tiangolo).
* ⬆️ Upgrade isort and update pre-commit. PR [#5940](https://github.com/tiangolo/fastapi/pull/5940) by [@tiangolo](https://github.com/tiangolo).
* 🔧 Add template for questions in Discussions. PR [#5920](https://github.com/tiangolo/fastapi/pull/5920) by [@tiangolo](https://github.com/tiangolo).
* 🔧 Update Sponsor Budget Insight to Powens. PR [#5916](https://github.com/tiangolo/fastapi/pull/5916) by [@tiangolo](https://github.com/tiangolo).
* 🔧 Update GitHub Sponsors badge data. PR [#5915](https://github.com/tiangolo/fastapi/pull/5915) by [@tiangolo](https://github.com/tiangolo).
## 0.89.1
### Fixes
* 🐛 Ignore Response classes on return annotation. PR [#5855](https://github.com/tiangolo/fastapi/pull/5855) by [@Kludex](https://github.com/Kludex). See the new docs in the PR below.
### Docs
* 📝 Update docs and examples for Response Model with Return Type Annotations, and update runtime error. PR [#5873](https://github.com/tiangolo/fastapi/pull/5873) by [@tiangolo](https://github.com/tiangolo). New docs at [Response Model - Return Type: Other Return Type Annotations](https://fastapi.tiangolo.com/tutorial/response-model/#other-return-type-annotations).
* 📝 Add External Link: FastAPI lambda container: serverless simplified. PR [#5784](https://github.com/tiangolo/fastapi/pull/5784) by [@rafrasenberg](https://github.com/rafrasenberg).
### Translations
* 🌐 Add Turkish translation for `docs/tr/docs/tutorial/first_steps.md`. PR [#5691](https://github.com/tiangolo/fastapi/pull/5691) by [@Kadermiyanyedi](https://github.com/Kadermiyanyedi).
## 0.89.0
### Features
* ✨ Add support for function return type annotations to declare the `response_model`. Initial PR [#1436](https://github.com/tiangolo/fastapi/pull/1436) by [@uriyyo](https://github.com/uriyyo).
Now you can declare the return type / `response_model` in the function return type annotation:
```python
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
price: float
@app.get("/items/")
async def read_items() -> list[Item]:
return [
Item(name="Portal Gun", price=42.0),
Item(name="Plumbus", price=32.0),
]
```
FastAPI will use the return type annotation to perform:
* Data validation
* Automatic documentation
* It could power automatic client generators
* **Data filtering**
Before this version it was only supported via the `response_model` parameter.
Read more about it in the new docs: [Response Model - Return Type](https://fastapi.tiangolo.com/tutorial/response-model/).
### Docs
* 📝 Add External Link: Authorization on FastAPI with Casbin. PR [#5712](https://github.com/tiangolo/fastapi/pull/5712) by [@Xhy-5000](https://github.com/Xhy-5000).
* ✏ Fix typo in `docs/en/docs/async.md`. PR [#5785](https://github.com/tiangolo/fastapi/pull/5785) by [@Kingdageek](https://github.com/Kingdageek).
* ✏ Fix typo in `docs/en/docs/deployment/concepts.md`. PR [#5824](https://github.com/tiangolo/fastapi/pull/5824) by [@kelbyfaessler](https://github.com/kelbyfaessler).
### Translations
* 🌐 Add Russian translation for `docs/ru/docs/fastapi-people.md`. PR [#5577](https://github.com/tiangolo/fastapi/pull/5577) by [@Xewus](https://github.com/Xewus).
* 🌐 Fix typo in Chinese translation for `docs/zh/docs/benchmarks.md`. PR [#4269](https://github.com/tiangolo/fastapi/pull/4269) by [@15027668g](https://github.com/15027668g).
* 🌐 Add Korean translation for `docs/tutorial/cors.md`. PR [#3764](https://github.com/tiangolo/fastapi/pull/3764) by [@NinaHwang](https://github.com/NinaHwang).
### Internal
* ⬆ Update coverage[toml] requirement from <7.0,>=6.5.0 to >=6.5.0,<8.0. PR [#5801](https://github.com/tiangolo/fastapi/pull/5801) by [@dependabot[bot]](https://github.com/apps/dependabot).
* ⬆ Update uvicorn[standard] requirement from <0.19.0,>=0.12.0 to >=0.12.0,<0.21.0 for development. PR [#5795](https://github.com/tiangolo/fastapi/pull/5795) by [@dependabot[bot]](https://github.com/apps/dependabot).
* ⬆ Bump dawidd6/action-download-artifact from 2.24.2 to 2.24.3. PR [#5842](https://github.com/tiangolo/fastapi/pull/5842) by [@dependabot[bot]](https://github.com/apps/dependabot).
* 👥 Update FastAPI People. PR [#5825](https://github.com/tiangolo/fastapi/pull/5825) by [@github-actions[bot]](https://github.com/apps/github-actions).
* ⬆ Bump types-ujson from 5.5.0 to 5.6.0.0. PR [#5735](https://github.com/tiangolo/fastapi/pull/5735) by [@dependabot[bot]](https://github.com/apps/dependabot).
* ⬆ Bump pypa/gh-action-pypi-publish from 1.5.2 to 1.6.4. PR [#5750](https://github.com/tiangolo/fastapi/pull/5750) by [@dependabot[bot]](https://github.com/apps/dependabot).
* 👷 Add GitHub Action gate/check. PR [#5492](https://github.com/tiangolo/fastapi/pull/5492) by [@webknjaz](https://github.com/webknjaz).
* 🔧 Update sponsors, add Svix. PR [#5848](https://github.com/tiangolo/fastapi/pull/5848) by [@tiangolo](https://github.com/tiangolo).
* 🔧 Remove Doist sponsor. PR [#5847](https://github.com/tiangolo/fastapi/pull/5847) by [@tiangolo](https://github.com/tiangolo).
* ⬆ Update sqlalchemy requirement from <=1.4.41,>=1.3.18 to >=1.3.18,<1.4.43. PR [#5540](https://github.com/tiangolo/fastapi/pull/5540) by [@dependabot[bot]](https://github.com/apps/dependabot).
* ⬆ Bump nwtgck/actions-netlify from 1.2.4 to 2.0.0. PR [#5757](https://github.com/tiangolo/fastapi/pull/5757) by [@dependabot[bot]](https://github.com/apps/dependabot).
* 👷 Refactor CI artifact upload/download for docs previews. PR [#5793](https://github.com/tiangolo/fastapi/pull/5793) by [@tiangolo](https://github.com/tiangolo).
* ⬆ Bump pypa/gh-action-pypi-publish from 1.5.1 to 1.5.2. PR [#5714](https://github.com/tiangolo/fastapi/pull/5714) by [@dependabot[bot]](https://github.com/apps/dependabot).
* 👥 Update FastAPI People. PR [#5722](https://github.com/tiangolo/fastapi/pull/5722) by [@github-actions[bot]](https://github.com/apps/github-actions).
* 🔧 Update sponsors, disable course bundle. PR [#5713](https://github.com/tiangolo/fastapi/pull/5713) by [@tiangolo](https://github.com/tiangolo).
* ⬆ Update typer[all] requirement from <0.7.0,>=0.6.1 to >=0.6.1,<0.8.0. PR [#5639](https://github.com/tiangolo/fastapi/pull/5639) by [@dependabot[bot]](https://github.com/apps/dependabot).
## 0.88.0
### Upgrades
* ⬆ Bump Starlette to version `0.22.0` to fix bad encoding for query parameters in new `TestClient`. PR [#5659](https://github.com/tiangolo/fastapi/pull/5659) by [@azogue](https://github.com/azogue).
### Docs
* ✏️ Fix typo in docs for `docs/en/docs/advanced/middleware.md`. PR [#5376](https://github.com/tiangolo/fastapi/pull/5376) by [@rifatrakib](https://github.com/rifatrakib).
### Translations
* 🌐 Add Portuguese translation for `docs/pt/docs/deployment/docker.md`. PR [#5663](https://github.com/tiangolo/fastapi/pull/5663) by [@ayr-ton](https://github.com/ayr-ton).
### Internal
* 👷 Tweak build-docs to improve CI performance. PR [#5699](https://github.com/tiangolo/fastapi/pull/5699) by [@tiangolo](https://github.com/tiangolo).
* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#5566](https://github.com/tiangolo/fastapi/pull/5566) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci).
* ⬆️ Upgrade Ruff. PR [#5698](https://github.com/tiangolo/fastapi/pull/5698) by [@tiangolo](https://github.com/tiangolo).
* 👷 Remove pip cache for Smokeshow as it depends on a requirements.txt. PR [#5700](https://github.com/tiangolo/fastapi/pull/5700) by [@tiangolo](https://github.com/tiangolo).
* 💚 Fix pip cache for Smokeshow. PR [#5697](https://github.com/tiangolo/fastapi/pull/5697) by [@tiangolo](https://github.com/tiangolo).
* 👷 Fix and tweak CI cache handling. PR [#5696](https://github.com/tiangolo/fastapi/pull/5696) by [@tiangolo](https://github.com/tiangolo).
* 👷 Update `setup-python` action in tests to use new caching feature. PR [#5680](https://github.com/tiangolo/fastapi/pull/5680) by [@madkinsz](https://github.com/madkinsz).
* ⬆ Bump black from 22.8.0 to 22.10.0. PR [#5569](https://github.com/tiangolo/fastapi/pull/5569) by [@dependabot[bot]](https://github.com/apps/dependabot).
## 0.87.0
Highlights of this release:
* [Upgraded Starlette](https://github.com/encode/starlette/releases/tag/0.21.0)
* Now the `TestClient` is based on HTTPX instead of Requests. 🚀
* There are some possible **breaking changes** in the `TestClient` usage, but [@Kludex](https://github.com/Kludex) built [bump-testclient](https://github.com/Kludex/bump-testclient) to help you automatize migrating your tests. Make sure you are using Git and that you can undo any unnecessary changes (false positive changes, etc) before using `bump-testclient`.
* New [WebSocketException (and docs)](https://fastapi.tiangolo.com/advanced/websockets/#using-depends-and-others), re-exported from Starlette.
* Upgraded and relaxed dependencies for package extras `all` (including new Uvicorn version), when you install `"fastapi[all]"`.
* New docs about how to [**Help Maintain FastAPI**](https://fastapi.tiangolo.com/help-fastapi/#help-maintain-fastapi).
### Features
* ⬆️ Upgrade and relax dependencies for extras "all". PR [#5634](https://github.com/tiangolo/fastapi/pull/5634) by [@tiangolo](https://github.com/tiangolo).
* ✨ Re-export Starlette's `WebSocketException` and add it to docs. PR [#5629](https://github.com/tiangolo/fastapi/pull/5629) by [@tiangolo](https://github.com/tiangolo).
* 📝 Update references to Requests for tests to HTTPX, and add HTTPX to extras. PR [#5628](https://github.com/tiangolo/fastapi/pull/5628) by [@tiangolo](https://github.com/tiangolo).
* ⬆ Upgrade Starlette to `0.21.0`, including the new [`TestClient` based on HTTPX](https://github.com/encode/starlette/releases/tag/0.21.0). PR [#5471](https://github.com/tiangolo/fastapi/pull/5471) by [@pawelrubin](https://github.com/pawelrubin).
### Docs
* ✏️ Tweak Help FastAPI from PR review after merging. PR [#5633](https://github.com/tiangolo/fastapi/pull/5633) by [@tiangolo](https://github.com/tiangolo).
* ✏️ Clarify docs on CORS. PR [#5627](https://github.com/tiangolo/fastapi/pull/5627) by [@paxcodes](https://github.com/paxcodes).
* 📝 Update Help FastAPI: Help Maintain FastAPI. PR [#5632](https://github.com/tiangolo/fastapi/pull/5632) by [@tiangolo](https://github.com/tiangolo).
### Translations
* 🌐 Fix highlight lines for Japanese translation for `docs/tutorial/query-params.md`. PR [#2969](https://github.com/tiangolo/fastapi/pull/2969) by [@ftnext](https://github.com/ftnext).
* 🌐 Add French translation for `docs/fr/docs/advanced/additional-status-code.md`. PR [#5477](https://github.com/tiangolo/fastapi/pull/5477) by [@axel584](https://github.com/axel584).
* 🌐 Add Portuguese translation for `docs/pt/docs/tutorial/request-forms-and-files.md`. PR [#5579](https://github.com/tiangolo/fastapi/pull/5579) by [@batlopes](https://github.com/batlopes).
* 🌐 Add Japanese translation for `docs/ja/docs/advanced/websockets.md`. PR [#4983](https://github.com/tiangolo/fastapi/pull/4983) by [@xryuseix](https://github.com/xryuseix).
### Internal
* ✨ Use Ruff for linting. PR [#5630](https://github.com/tiangolo/fastapi/pull/5630) by [@tiangolo](https://github.com/tiangolo).
* 🛠 Add Arabic issue number to Notify Translations GitHub Action. PR [#5610](https://github.com/tiangolo/fastapi/pull/5610) by [@tiangolo](https://github.com/tiangolo).
* ⬆ Bump dawidd6/action-download-artifact from 2.24.1 to 2.24.2. PR [#5609](https://github.com/tiangolo/fastapi/pull/5609) by [@dependabot[bot]](https://github.com/apps/dependabot).
* ⬆ Bump dawidd6/action-download-artifact from 2.24.0 to 2.24.1. PR [#5603](https://github.com/tiangolo/fastapi/pull/5603) by [@dependabot[bot]](https://github.com/apps/dependabot).
* 📝 Update coverage badge to use Samuel Colvin's Smokeshow. PR [#5585](https://github.com/tiangolo/fastapi/pull/5585) by [@tiangolo](https://github.com/tiangolo).
## 0.86.0
### Features
* ⬆ Add Python 3.11 to the officially supported versions. PR [#5587](https://github.com/tiangolo/fastapi/pull/5587) by [@tiangolo](https://github.com/tiangolo).
* ✅ Enable tests for Python 3.11. PR [#4881](https://github.com/tiangolo/fastapi/pull/4881) by [@tiangolo](https://github.com/tiangolo).
### Fixes
* 🐛 Close FormData (uploaded files) after the request is done. PR [#5465](https://github.com/tiangolo/fastapi/pull/5465) by [@adriangb](https://github.com/adriangb).
### Docs
* ✏ Fix typo in `docs/en/docs/tutorial/security/oauth2-jwt.md`. PR [#5584](https://github.com/tiangolo/fastapi/pull/5584) by [@vivekashok1221](https://github.com/vivekashok1221).
### Translations
* 🌐 Update wording in Chinese translation for `docs/zh/docs/python-types.md`. PR [#5416](https://github.com/tiangolo/fastapi/pull/5416) by [@supercaizehua](https://github.com/supercaizehua).
* 🌐 Add Russian translation for `docs/ru/docs/deployment/index.md`. PR [#5336](https://github.com/tiangolo/fastapi/pull/5336) by [@Xewus](https://github.com/Xewus).
* 🌐 Update Chinese translation for `docs/tutorial/security/oauth2-jwt.md`. PR [#3846](https://github.com/tiangolo/fastapi/pull/3846) by [@jaystone776](https://github.com/jaystone776).
### Internal
* 👷 Update FastAPI People to exclude bots: pre-commit-ci, dependabot. PR [#5586](https://github.com/tiangolo/fastapi/pull/5586) by [@tiangolo](https://github.com/tiangolo).
* 🎨 Format OpenAPI JSON in `test_starlette_exception.py`. PR [#5379](https://github.com/tiangolo/fastapi/pull/5379) by [@iudeen](https://github.com/iudeen).
* 👷 Switch from Codecov to Smokeshow plus pytest-cov to pure coverage for internal tests. PR [#5583](https://github.com/tiangolo/fastapi/pull/5583) by [@tiangolo](https://github.com/tiangolo).
* 👥 Update FastAPI People. PR [#5571](https://github.com/tiangolo/fastapi/pull/5571) by [@github-actions[bot]](https://github.com/apps/github-actions).
## 0.85.2
### Docs
* ✏ Fix grammar and add helpful links to dependencies in `docs/en/docs/async.md`. PR [#5432](https://github.com/tiangolo/fastapi/pull/5432) by [@pamelafox](https://github.com/pamelafox).
* ✏ Fix broken link in `alternatives.md`. PR [#5455](https://github.com/tiangolo/fastapi/pull/5455) by [@su-shubham](https://github.com/su-shubham).
* ✏ Fix typo in docs about contributing, for compatibility with `pip` in Zsh. PR [#5523](https://github.com/tiangolo/fastapi/pull/5523) by [@zhangbo2012](https://github.com/zhangbo2012).
* 📝 Fix typo in docs with examples for Python 3.10 instead of 3.9. PR [#5545](https://github.com/tiangolo/fastapi/pull/5545) by [@feliciss](https://github.com/feliciss).
### Translations
* 🌐 Add Portuguese translation for `docs/pt/docs/tutorial/request-forms.md`. PR [#4934](https://github.com/tiangolo/fastapi/pull/4934) by [@batlopes](https://github.com/batlopes).
* 🌐 Add Chinese translation for `docs/zh/docs/tutorial/dependencies/classes-as-dependencies.md`. PR [#4971](https://github.com/tiangolo/fastapi/pull/4971) by [@Zssaer](https://github.com/Zssaer).
* 🌐 Add French translation for `deployment/deta.md`. PR [#3692](https://github.com/tiangolo/fastapi/pull/3692) by [@rjNemo](https://github.com/rjNemo).
* 🌐 Update Chinese translation for `docs/zh/docs/tutorial/query-params-str-validations.md`. PR [#5255](https://github.com/tiangolo/fastapi/pull/5255) by [@hjlarry](https://github.com/hjlarry).
* 🌐 Add Chinese translation for `docs/zh/docs/tutorial/sql-databases.md`. PR [#4999](https://github.com/tiangolo/fastapi/pull/4999) by [@Zssaer](https://github.com/Zssaer).
* 🌐 Add Chinese translation for `docs/zh/docs/advanced/wsgi.md`. PR [#4505](https://github.com/tiangolo/fastapi/pull/4505) by [@ASpathfinder](https://github.com/ASpathfinder).
* 🌐 Add Portuguese translation for `docs/pt/docs/tutorial/body-multiple-params.md`. PR [#4111](https://github.com/tiangolo/fastapi/pull/4111) by [@lbmendes](https://github.com/lbmendes).
* 🌐 Add Portuguese translation for `docs/pt/docs/tutorial/path-params-numeric-validations.md`. PR [#4099](https://github.com/tiangolo/fastapi/pull/4099) by [@lbmendes](https://github.com/lbmendes).
* 🌐 Add French translation for `deployment/versions.md`. PR [#3690](https://github.com/tiangolo/fastapi/pull/3690) by [@rjNemo](https://github.com/rjNemo).
* 🌐 Add French translation for `docs/fr/docs/help-fastapi.md`. PR [#2233](https://github.com/tiangolo/fastapi/pull/2233) by [@JulianMaurin](https://github.com/JulianMaurin).
* 🌐 Fix typo in Chinese translation for `docs/zh/docs/tutorial/security/first-steps.md`. PR [#5530](https://github.com/tiangolo/fastapi/pull/5530) by [@yuki1sntSnow](https://github.com/yuki1sntSnow).
* 🌐 Add Portuguese translation for `docs/pt/docs/tutorial/response-status-code.md`. PR [#4922](https://github.com/tiangolo/fastapi/pull/4922) by [@batlopes](https://github.com/batlopes).
* 🔧 Add config for Tamil translations. PR [#5563](https://github.com/tiangolo/fastapi/pull/5563) by [@tiangolo](https://github.com/tiangolo).
### Internal
* ⬆ Bump internal dependency mypy from 0.971 to 0.982. PR [#5541](https://github.com/tiangolo/fastapi/pull/5541) by [@dependabot[bot]](https://github.com/apps/dependabot).
* ⬆ Bump nwtgck/actions-netlify from 1.2.3 to 1.2.4. PR [#5507](https://github.com/tiangolo/fastapi/pull/5507) by [@dependabot[bot]](https://github.com/apps/dependabot).
* ⬆ Bump internal dependency types-ujson from 5.4.0 to 5.5.0. PR [#5537](https://github.com/tiangolo/fastapi/pull/5537) by [@dependabot[bot]](https://github.com/apps/dependabot).
* ⬆ Bump dawidd6/action-download-artifact from 2.23.0 to 2.24.0. PR [#5508](https://github.com/tiangolo/fastapi/pull/5508) by [@dependabot[bot]](https://github.com/apps/dependabot).
* ⬆ Update internal dependency pytest-cov requirement from <4.0.0,>=2.12.0 to >=2.12.0,<5.0.0. PR [#5539](https://github.com/tiangolo/fastapi/pull/5539) by [@dependabot[bot]](https://github.com/apps/dependabot).
* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#5536](https://github.com/tiangolo/fastapi/pull/5536) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci).
* 🐛 Fix internal Trio test warnings. PR [#5547](https://github.com/tiangolo/fastapi/pull/5547) by [@samuelcolvin](https://github.com/samuelcolvin).
* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#5408](https://github.com/tiangolo/fastapi/pull/5408) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci).
* ⬆️ Upgrade Typer to include Rich in scripts for docs. PR [#5502](https://github.com/tiangolo/fastapi/pull/5502) by [@tiangolo](https://github.com/tiangolo).
* 🐛 Fix calling `mkdocs` for languages as a subprocess to fix/enable MkDocs Material search plugin. PR [#5501](https://github.com/tiangolo/fastapi/pull/5501) by [@tiangolo](https://github.com/tiangolo).
## 0.85.1
### Fixes
* 🐛 Fix support for strings in OpenAPI status codes: `default`, `1XX`, `2XX`, `3XX`, `4XX`, `5XX`. PR [#5187](https://github.com/tiangolo/fastapi/pull/5187) by [@JarroVGIT](https://github.com/JarroVGIT).
### Docs
* 📝 Add WayScript x FastAPI Tutorial to External Links section. PR [#5407](https://github.com/tiangolo/fastapi/pull/5407) by [@moneeka](https://github.com/moneeka).
### Internal
* 👥 Update FastAPI People. PR [#5447](https://github.com/tiangolo/fastapi/pull/5447) by [@github-actions[bot]](https://github.com/apps/github-actions).
* 🔧 Disable Material for MkDocs search plugin. PR [#5495](https://github.com/tiangolo/fastapi/pull/5495) by [@tiangolo](https://github.com/tiangolo).
* 🔇 Ignore Trio warning in tests for CI. PR [#5483](https://github.com/tiangolo/fastapi/pull/5483) by [@samuelcolvin](https://github.com/samuelcolvin).
## 0.85.0
### Features
* ⬆ Upgrade version required of Starlette from `0.19.1` to `0.20.4`. Initial PR [#4820](https://github.com/tiangolo/fastapi/pull/4820) by [@Kludex](https://github.com/Kludex).
* This includes several bug fixes in Starlette.
* ⬆️ Upgrade Uvicorn max version in public extras: all. From `>=0.12.0,<0.18.0` to `>=0.12.0,<0.19.0`. PR [#5401](https://github.com/tiangolo/fastapi/pull/5401) by [@tiangolo](https://github.com/tiangolo).
### Internal
* ⬆️ Upgrade dependencies for doc and dev internal extras: Typer, Uvicorn. PR [#5400](https://github.com/tiangolo/fastapi/pull/5400) by [@tiangolo](https://github.com/tiangolo).
* ⬆️ Upgrade test dependencies: Black, HTTPX, databases, types-ujson. PR [#5399](https://github.com/tiangolo/fastapi/pull/5399) by [@tiangolo](https://github.com/tiangolo).
* ⬆️ Upgrade mypy and tweak internal type annotations. PR [#5398](https://github.com/tiangolo/fastapi/pull/5398) by [@tiangolo](https://github.com/tiangolo).
* 🔧 Update test dependencies, upgrade Pytest, move dependencies from dev to test. PR [#5396](https://github.com/tiangolo/fastapi/pull/5396) by [@tiangolo](https://github.com/tiangolo).
## 0.84.0
### Breaking Changes
This version of FastAPI drops support for Python 3.6. 🔥 Please upgrade to a supported version of Python (3.7 or above), Python 3.6 reached the end-of-life a long time ago. 😅☠
* 🔧 Update package metadata, drop support for Python 3.6, move build internals from Flit to Hatch. PR [#5240](https://github.com/tiangolo/fastapi/pull/5240) by [@ofek](https://github.com/ofek).
## 0.83.0
🚨 This is probably the last release (or one of the last releases) to support Python 3.6. 🔥
Python 3.6 reached the [end-of-life and is no longer supported by Python](https://www.python.org/downloads/release/python-3615/) since around a year ago.
You hopefully updated to a supported version of Python a while ago. If you haven't, you really should.
### Features
* ✨ Add support in `jsonable_encoder` for include and exclude with dataclasses. PR [#4923](https://github.com/tiangolo/fastapi/pull/4923) by [@DCsunset](https://github.com/DCsunset).
### Fixes
* 🐛 Fix `RuntimeError` raised when `HTTPException` has a status code with no content. PR [#5365](https://github.com/tiangolo/fastapi/pull/5365) by [@iudeen](https://github.com/iudeen).
* 🐛 Fix empty reponse body when default `status_code` is empty but the a `Response` parameter with `response.status_code` is set. PR [#5360](https://github.com/tiangolo/fastapi/pull/5360) by [@tmeckel](https://github.com/tmeckel).
### Docs
* 📝 Update `SECURITY.md`. PR [#5377](https://github.com/tiangolo/fastapi/pull/5377) by [@Kludex](https://github.com/Kludex).
### Internal
* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#5352](https://github.com/tiangolo/fastapi/pull/5352) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci).
## 0.82.0
🚨 This is probably the last release (or one of the last releases) to support Python 3.6. 🔥
Python 3.6 reached the [end-of-life and is no longer supported by Python](https://www.python.org/downloads/release/python-3615/) since around a year ago.
You hopefully updated to a supported version of Python a while ago. If you haven't, you really should.
### Features
* ✨ Export `WebSocketState` in `fastapi.websockets`. PR [#4376](https://github.com/tiangolo/fastapi/pull/4376) by [@matiuszka](https://github.com/matiuszka).
* ✨ Support Python internal description on Pydantic model's docstring. PR [#3032](https://github.com/tiangolo/fastapi/pull/3032) by [@Kludex](https://github.com/Kludex).
* ✨ Update `ORJSONResponse` to support non `str` keys and serializing Numpy arrays. PR [#3892](https://github.com/tiangolo/fastapi/pull/3892) by [@baby5](https://github.com/baby5).
### Fixes
* 🐛 Allow exit code for dependencies with `yield` to always execute, by removing capacity limiter for them, to e.g. allow closing DB connections without deadlocks. PR [#5122](https://github.com/tiangolo/fastapi/pull/5122) by [@adriangb](https://github.com/adriangb).
* 🐛 Fix FastAPI People GitHub Action: set HTTPX timeout for GraphQL query request. PR [#5222](https://github.com/tiangolo/fastapi/pull/5222) by [@iudeen](https://github.com/iudeen).
* 🐛 Make sure a parameter defined as required is kept required in OpenAPI even if defined as optional in another dependency. PR [#4319](https://github.com/tiangolo/fastapi/pull/4319) by [@cd17822](https://github.com/cd17822).
* 🐛 Fix support for path parameters in WebSockets. PR [#3879](https://github.com/tiangolo/fastapi/pull/3879) by [@davidbrochart](https://github.com/davidbrochart).
### Docs
* ✏ Update Hypercorn link, now pointing to GitHub. PR [#5346](https://github.com/tiangolo/fastapi/pull/5346) by [@baconfield](https://github.com/baconfield).
* ✏ Tweak wording in `docs/en/docs/advanced/dataclasses.md`. PR [#3698](https://github.com/tiangolo/fastapi/pull/3698) by [@pfackeldey](https://github.com/pfackeldey).
* 📝 Add note about Python 3.10 `X | Y` operator in explanation about Response Models. PR [#5307](https://github.com/tiangolo/fastapi/pull/5307) by [@MendyLanda](https://github.com/MendyLanda).
* 📝 Add link to New Relic article: "How to monitor FastAPI application performance using Python agent". PR [#5260](https://github.com/tiangolo/fastapi/pull/5260) by [@sjyothi54](https://github.com/sjyothi54).
* 📝 Update docs for `ORJSONResponse` with details about improving performance. PR [#2615](https://github.com/tiangolo/fastapi/pull/2615) by [@falkben](https://github.com/falkben).
* 📝 Add docs for creating a custom Response class. PR [#5331](https://github.com/tiangolo/fastapi/pull/5331) by [@tiangolo](https://github.com/tiangolo).
* 📝 Add tip about using alias for form data fields. PR [#5329](https://github.com/tiangolo/fastapi/pull/5329) by [@tiangolo](https://github.com/tiangolo).
### Translations
* 🌐 Add Russian translation for `docs/ru/docs/features.md`. PR [#5315](https://github.com/tiangolo/fastapi/pull/5315) by [@Xewus](https://github.com/Xewus).
* 🌐 Update Chinese translation for `docs/zh/docs/tutorial/request-files.md`. PR [#4529](https://github.com/tiangolo/fastapi/pull/4529) by [@ASpathfinder](https://github.com/ASpathfinder).
* 🌐 Add Chinese translation for `docs/zh/docs/tutorial/encoder.md`. PR [#4969](https://github.com/tiangolo/fastapi/pull/4969) by [@Zssaer](https://github.com/Zssaer).
* 🌐 Fix MkDocs file line for Portuguese translation of `background-task.md`. PR [#5242](https://github.com/tiangolo/fastapi/pull/5242) by [@ComicShrimp](https://github.com/ComicShrimp).
### Internal
* 👥 Update FastAPI People. PR [#5347](https://github.com/tiangolo/fastapi/pull/5347) by [@github-actions[bot]](https://github.com/apps/github-actions).
* ⬆ Bump dawidd6/action-download-artifact from 2.22.0 to 2.23.0. PR [#5321](https://github.com/tiangolo/fastapi/pull/5321) by [@dependabot[bot]](https://github.com/apps/dependabot).
* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#5318](https://github.com/tiangolo/fastapi/pull/5318) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci).
* ✏ Fix a small code highlight line error. PR [#5256](https://github.com/tiangolo/fastapi/pull/5256) by [@hjlarry](https://github.com/hjlarry).
* ♻ Internal small refactor, move `operation_id` parameter position in delete method for consistency with the code. PR [#4474](https://github.com/tiangolo/fastapi/pull/4474) by [@hiel](https://github.com/hiel).
* 🔧 Update sponsors, disable ImgWhale. PR [#5338](https://github.com/tiangolo/fastapi/pull/5338) by [@tiangolo](https://github.com/tiangolo).
## 0.81.0
### Features
* ✨ Add ReDoc `<noscript>` warning when JS is disabled. PR [#5074](https://github.com/tiangolo/fastapi/pull/5074) by [@evroon](https://github.com/evroon).
* ✨ Add support for `FrozenSet` in parameters (e.g. query). PR [#2938](https://github.com/tiangolo/fastapi/pull/2938) by [@juntatalor](https://github.com/juntatalor).
* ✨ Allow custom middlewares to raise `HTTPException`s and propagate them. PR [#2036](https://github.com/tiangolo/fastapi/pull/2036) by [@ghandic](https://github.com/ghandic).
* ✨ Preserve `json.JSONDecodeError` information when handling invalid JSON in request body, to support custom exception handlers that use its information. PR [#4057](https://github.com/tiangolo/fastapi/pull/4057) by [@UKnowWhoIm](https://github.com/UKnowWhoIm).
### Fixes
* 🐛 Fix `jsonable_encoder` for dataclasses with pydantic-compatible fields. PR [#3607](https://github.com/tiangolo/fastapi/pull/3607) by [@himbeles](https://github.com/himbeles).
* 🐛 Fix support for extending `openapi_extras` with parameter lists. PR [#4267](https://github.com/tiangolo/fastapi/pull/4267) by [@orilevari](https://github.com/orilevari).
### Docs
* ✏ Fix a simple typo in `docs/en/docs/python-types.md`. PR [#5193](https://github.com/tiangolo/fastapi/pull/5193) by [@GlitchingCore](https://github.com/GlitchingCore).
* ✏ Fix typos in `tests/test_schema_extra_examples.py`. PR [#5126](https://github.com/tiangolo/fastapi/pull/5126) by [@supraaxdd](https://github.com/supraaxdd).
* ✏ Fix typos in `docs/en/docs/tutorial/path-params-numeric-validations.md`. PR [#5142](https://github.com/tiangolo/fastapi/pull/5142) by [@invisibleroads](https://github.com/invisibleroads).
* 📝 Add step about upgrading pip in the venv to avoid errors when installing dependencies `docs/en/docs/contributing.md`. PR [#5181](https://github.com/tiangolo/fastapi/pull/5181) by [@edisnake](https://github.com/edisnake).
* ✏ Reword and clarify text in tutorial `docs/en/docs/tutorial/body-nested-models.md`. PR [#5169](https://github.com/tiangolo/fastapi/pull/5169) by [@papb](https://github.com/papb).
* ✏ Fix minor typo in `docs/en/docs/features.md`. PR [#5206](https://github.com/tiangolo/fastapi/pull/5206) by [@OtherBarry](https://github.com/OtherBarry).
* ✏ Fix minor typos in `docs/en/docs/async.md`. PR [#5125](https://github.com/tiangolo/fastapi/pull/5125) by [@Ksenofanex](https://github.com/Ksenofanex).
* 📝 Add external link to docs: "Fastapi, Docker(Docker compose) and Postgres". PR [#5033](https://github.com/tiangolo/fastapi/pull/5033) by [@krishnardt](https://github.com/krishnardt).
* 📝 Simplify example for docs for Additional Responses, remove unnecessary `else`. PR [#4693](https://github.com/tiangolo/fastapi/pull/4693) by [@adriangb](https://github.com/adriangb).
* 📝 Update docs, compare enums with identity instead of equality. PR [#4905](https://github.com/tiangolo/fastapi/pull/4905) by [@MicaelJarniac](https://github.com/MicaelJarniac).
* ✏ Fix typo in `docs/en/docs/python-types.md`. PR [#4886](https://github.com/tiangolo/fastapi/pull/4886) by [@MicaelJarniac](https://github.com/MicaelJarniac).
* 🎨 Fix syntax highlighting in docs for OpenAPI Callbacks. PR [#4368](https://github.com/tiangolo/fastapi/pull/4368) by [@xncbf](https://github.com/xncbf).
* ✏ Reword confusing sentence in docs file `typo-fix-path-params-numeric-validations.md`. PR [#3219](https://github.com/tiangolo/fastapi/pull/3219) by [@ccrenfroe](https://github.com/ccrenfroe).
* 📝 Update docs for handling HTTP Basic Auth with `secrets.compare_digest()` to account for non-ASCII characters. PR [#3536](https://github.com/tiangolo/fastapi/pull/3536) by [@lewoudar](https://github.com/lewoudar).
* 📝 Update docs for testing, fix examples with relative imports. PR [#5302](https://github.com/tiangolo/fastapi/pull/5302) by [@tiangolo](https://github.com/tiangolo).
### Translations
* 🌐 Add Russian translation for `docs/ru/docs/index.md`. PR [#5289](https://github.com/tiangolo/fastapi/pull/5289) by [@impocode](https://github.com/impocode).
* 🌐 Add Russian translation for `docs/ru/docs/deployment/versions.md`. PR [#4985](https://github.com/tiangolo/fastapi/pull/4985) by [@emp7yhead](https://github.com/emp7yhead).
* 🌐 Add Portuguese translation for `docs/pt/docs/tutorial/header-params.md`. PR [#4921](https://github.com/tiangolo/fastapi/pull/4921) by [@batlopes](https://github.com/batlopes).
* 🌐 Update `ko/mkdocs.yml` for a missing link. PR [#5020](https://github.com/tiangolo/fastapi/pull/5020) by [@dalinaum](https://github.com/dalinaum).
### Internal
* ⬆ Bump dawidd6/action-download-artifact from 2.21.1 to 2.22.0. PR [#5258](https://github.com/tiangolo/fastapi/pull/5258) by [@dependabot[bot]](https://github.com/apps/dependabot).
* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#5196](https://github.com/tiangolo/fastapi/pull/5196) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci).
* 🔥 Delete duplicated tests in `tests/test_tutorial/test_sql_databases/test_sql_databases.py`. PR [#5040](https://github.com/tiangolo/fastapi/pull/5040) by [@raccoonyy](https://github.com/raccoonyy).
* ♻ Simplify internal RegEx in `fastapi/utils.py`. PR [#5057](https://github.com/tiangolo/fastapi/pull/5057) by [@pylounge](https://github.com/pylounge).
* 🔧 Fix Type hint of `auto_error` which does not need to be `Optional[bool]`. PR [#4933](https://github.com/tiangolo/fastapi/pull/4933) by [@DavidKimDY](https://github.com/DavidKimDY).
* 🔧 Update mypy config, use `strict = true` instead of manual configs. PR [#4605](https://github.com/tiangolo/fastapi/pull/4605) by [@michaeloliverx](https://github.com/michaeloliverx).
* ♻ Change a `dict()` for `{}` in `fastapi/utils.py`. PR [#3138](https://github.com/tiangolo/fastapi/pull/3138) by [@ShahriyarR](https://github.com/ShahriyarR).
* ♻ Move internal variable for errors in `jsonable_encoder` to put related code closer. PR [#4560](https://github.com/tiangolo/fastapi/pull/4560) by [@GuilleQP](https://github.com/GuilleQP).
* ♻ Simplify conditional assignment in `fastapi/dependencies/utils.py`. PR [#4597](https://github.com/tiangolo/fastapi/pull/4597) by [@cikay](https://github.com/cikay).
* ⬆ Upgrade version pin accepted for Flake8, for internal code, to `flake8 >=3.8.3,<6.0.0`. PR [#4097](https://github.com/tiangolo/fastapi/pull/4097) by [@jamescurtin](https://github.com/jamescurtin).
* 🍱 Update Jina banner, fix typo. PR [#5301](https://github.com/tiangolo/fastapi/pull/5301) by [@tiangolo](https://github.com/tiangolo).
## 0.80.0
### Breaking Changes - Fixes
@@ -830,7 +1487,7 @@ Thanks to [Dima Boger](https://twitter.com/b0g3r) for the security report! 🙇
### Security fixes
* 📌 Upgrade pydantic pin, to handle security vulnerability [CVE-2021-29510](https://github.com/samuelcolvin/pydantic/security/advisories/GHSA-5jqp-qgf6-3pvh). PR [#3213](https://github.com/tiangolo/fastapi/pull/3213) by [@tiangolo](https://github.com/tiangolo).
* 📌 Upgrade pydantic pin, to handle security vulnerability [CVE-2021-29510](https://github.com/pydantic/pydantic/security/advisories/GHSA-5jqp-qgf6-3pvh). PR [#3213](https://github.com/tiangolo/fastapi/pull/3213) by [@tiangolo](https://github.com/tiangolo).
## 0.65.0
@@ -1385,11 +2042,11 @@ Note: all the previous parameters are still there, so it's still possible to dec
## 0.55.1
* Fix handling of enums with their own schema in path parameters. To support [samuelcolvin/pydantic#1432](https://github.com/samuelcolvin/pydantic/pull/1432) in FastAPI. PR [#1463](https://github.com/tiangolo/fastapi/pull/1463).
* Fix handling of enums with their own schema in path parameters. To support [pydantic/pydantic#1432](https://github.com/pydantic/pydantic/pull/1432) in FastAPI. PR [#1463](https://github.com/tiangolo/fastapi/pull/1463).
## 0.55.0
* Allow enums to allow them to have their own schemas in OpenAPI. To support [samuelcolvin/pydantic#1432](https://github.com/samuelcolvin/pydantic/pull/1432) in FastAPI. PR [#1461](https://github.com/tiangolo/fastapi/pull/1461).
* Allow enums to allow them to have their own schemas in OpenAPI. To support [pydantic/pydantic#1432](https://github.com/pydantic/pydantic/pull/1432) in FastAPI. PR [#1461](https://github.com/tiangolo/fastapi/pull/1461).
* Add links for funding through [GitHub sponsors](https://github.com/sponsors/tiangolo). PR [#1425](https://github.com/tiangolo/fastapi/pull/1425).
* Update issue template for for questions. PR [#1344](https://github.com/tiangolo/fastapi/pull/1344) by [@retnikt](https://github.com/retnikt).
* Update warning about storing passwords in docs. PR [#1336](https://github.com/tiangolo/fastapi/pull/1336) by [@skorokithakis](https://github.com/skorokithakis).

View File

@@ -57,18 +57,42 @@ 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 3.6 and above"
=== "Python 3.10+"
```Python hl_lines="13 15 22 25"
{!> ../../../docs_src/background_tasks/tutorial002.py!}
{!> ../../../docs_src/background_tasks/tutorial002_an_py310.py!}
```
=== "Python 3.10 and above"
=== "Python 3.9+"
```Python hl_lines="13 15 22 25"
{!> ../../../docs_src/background_tasks/tutorial002_an_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="14 16 23 26"
{!> ../../../docs_src/background_tasks/tutorial002_an.py!}
```
=== "Python 3.10+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="11 13 20 23"
{!> ../../../docs_src/background_tasks/tutorial002_py310.py!}
```
=== "Python 3.6+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="13 15 22 25"
{!> ../../../docs_src/background_tasks/tutorial002.py!}
```
In this example, the messages will be written to the `log.txt` file *after* the response is sent.
If there was a query in the request, it will be written to the log in a background task.

View File

@@ -112,9 +112,26 @@ So we put them in their own `dependencies` module (`app/dependencies.py`).
We will now use a simple dependency to read a custom `X-Token` header:
```Python hl_lines="1 4-6"
{!../../../docs_src/bigger_applications/app/dependencies.py!}
```
=== "Python 3.9+"
```Python hl_lines="3 6-8"
{!> ../../../docs_src/bigger_applications/app_an_py39/dependencies.py!}
```
=== "Python 3.6+"
```Python hl_lines="1 5-7"
{!> ../../../docs_src/bigger_applications/app_an/dependencies.py!}
```
=== "Python 3.6+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="1 4-6"
{!> ../../../docs_src/bigger_applications/app/dependencies.py!}
```
!!! tip
We are using an invented header to simplify this example.
@@ -189,7 +206,7 @@ The end result is that the item paths are now:
### Import the dependencies
This codes lives in the module `app.routers.items`, the file `app/routers/items.py`.
This code lives in the module `app.routers.items`, the file `app/routers/items.py`.
And we need to get the dependency function from the module `app.dependencies`, the file `app/dependencies.py`.

View File

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

View File

@@ -8,18 +8,42 @@ 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 3.6 and above"
=== "Python 3.10+"
```Python hl_lines="19-21"
{!> ../../../docs_src/body_multiple_params/tutorial001.py!}
```Python hl_lines="18-20"
{!> ../../../docs_src/body_multiple_params/tutorial001_an_py310.py!}
```
=== "Python 3.10 and above"
=== "Python 3.9+"
```Python hl_lines="18-20"
{!> ../../../docs_src/body_multiple_params/tutorial001_an_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="19-21"
{!> ../../../docs_src/body_multiple_params/tutorial001_an.py!}
```
=== "Python 3.10+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="17-19"
{!> ../../../docs_src/body_multiple_params/tutorial001_py310.py!}
```
=== "Python 3.6+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="19-21"
{!> ../../../docs_src/body_multiple_params/tutorial001.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.
@@ -38,18 +62,18 @@ 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 3.6 and above"
```Python hl_lines="22"
{!> ../../../docs_src/body_multiple_params/tutorial002.py!}
```
=== "Python 3.10 and above"
=== "Python 3.10+"
```Python hl_lines="20"
{!> ../../../docs_src/body_multiple_params/tutorial002_py310.py!}
```
=== "Python 3.6+"
```Python hl_lines="22"
{!> ../../../docs_src/body_multiple_params/tutorial002.py!}
```
In this case, **FastAPI** will notice that there are more than one body parameters in the function (two parameters that are Pydantic models).
So, it will then use the parameter names as keys (field names) in the body, and expect a body like:
@@ -87,18 +111,42 @@ 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 3.10+"
```Python hl_lines="22"
{!> ../../../docs_src/body_multiple_params/tutorial003.py!}
```Python hl_lines="23"
{!> ../../../docs_src/body_multiple_params/tutorial003_an_py310.py!}
```
=== "Python 3.10 and above"
=== "Python 3.9+"
```Python hl_lines="23"
{!> ../../../docs_src/body_multiple_params/tutorial003_an_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="24"
{!> ../../../docs_src/body_multiple_params/tutorial003_an.py!}
```
=== "Python 3.10+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="20"
{!> ../../../docs_src/body_multiple_params/tutorial003_py310.py!}
```
=== "Python 3.6+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="22"
{!> ../../../docs_src/body_multiple_params/tutorial003.py!}
```
In this case, **FastAPI** will expect a body like:
```JSON
@@ -137,18 +185,42 @@ q: str | None = None
For example:
=== "Python 3.6 and above"
=== "Python 3.10+"
```Python hl_lines="27"
{!> ../../../docs_src/body_multiple_params/tutorial004_an_py310.py!}
```
=== "Python 3.9+"
```Python hl_lines="27"
{!> ../../../docs_src/body_multiple_params/tutorial004_an_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="28"
{!> ../../../docs_src/body_multiple_params/tutorial004_an.py!}
```
=== "Python 3.10+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="25"
{!> ../../../docs_src/body_multiple_params/tutorial004_py310.py!}
```
=== "Python 3.6+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="27"
{!> ../../../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.
@@ -166,18 +238,42 @@ item: Item = Body(embed=True)
as in:
=== "Python 3.6 and above"
=== "Python 3.10+"
```Python hl_lines="17"
{!> ../../../docs_src/body_multiple_params/tutorial005.py!}
{!> ../../../docs_src/body_multiple_params/tutorial005_an_py310.py!}
```
=== "Python 3.10 and above"
=== "Python 3.9+"
```Python hl_lines="17"
{!> ../../../docs_src/body_multiple_params/tutorial005_an_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="18"
{!> ../../../docs_src/body_multiple_params/tutorial005_an.py!}
```
=== "Python 3.10+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="15"
{!> ../../../docs_src/body_multiple_params/tutorial005_py310.py!}
```
=== "Python 3.6+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="17"
{!> ../../../docs_src/body_multiple_params/tutorial005.py!}
```
In this case **FastAPI** will expect a body like:
```JSON hl_lines="2"

View File

@@ -6,19 +6,19 @@ 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 3.6 and above"
```Python hl_lines="14"
{!> ../../../docs_src/body_nested_models/tutorial001.py!}
```
=== "Python 3.10 and above"
=== "Python 3.10+"
```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.
=== "Python 3.6+"
```Python hl_lines="14"
{!> ../../../docs_src/body_nested_models/tutorial001.py!}
```
This will make `tags` be a list, although it doesn't declare the type of the elements of the list.
## List fields with type parameter
@@ -61,22 +61,22 @@ 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 3.6 and above"
=== "Python 3.10+"
```Python hl_lines="14"
{!> ../../../docs_src/body_nested_models/tutorial002.py!}
```Python hl_lines="12"
{!> ../../../docs_src/body_nested_models/tutorial002_py310.py!}
```
=== "Python 3.9 and above"
=== "Python 3.9+"
```Python hl_lines="14"
{!> ../../../docs_src/body_nested_models/tutorial002_py39.py!}
```
=== "Python 3.10 and above"
=== "Python 3.6+"
```Python hl_lines="12"
{!> ../../../docs_src/body_nested_models/tutorial002_py310.py!}
```Python hl_lines="14"
{!> ../../../docs_src/body_nested_models/tutorial002.py!}
```
## Set types
@@ -87,22 +87,22 @@ And Python has a special data type for sets of unique items, the `set`.
Then we can declare `tags` as a set of strings:
=== "Python 3.6 and above"
=== "Python 3.10+"
```Python hl_lines="1 14"
{!> ../../../docs_src/body_nested_models/tutorial003.py!}
```Python hl_lines="12"
{!> ../../../docs_src/body_nested_models/tutorial003_py310.py!}
```
=== "Python 3.9 and above"
=== "Python 3.9+"
```Python hl_lines="14"
{!> ../../../docs_src/body_nested_models/tutorial003_py39.py!}
```
=== "Python 3.10 and above"
=== "Python 3.6+"
```Python hl_lines="12"
{!> ../../../docs_src/body_nested_models/tutorial003_py310.py!}
```Python hl_lines="1 14"
{!> ../../../docs_src/body_nested_models/tutorial003.py!}
```
With this, even if you receive a request with duplicate data, it will be converted to a set of unique items.
@@ -125,44 +125,44 @@ All that, arbitrarily nested.
For example, we can define an `Image` model:
=== "Python 3.6 and above"
=== "Python 3.10+"
```Python hl_lines="9-11"
{!> ../../../docs_src/body_nested_models/tutorial004.py!}
```Python hl_lines="7-9"
{!> ../../../docs_src/body_nested_models/tutorial004_py310.py!}
```
=== "Python 3.9 and above"
=== "Python 3.9+"
```Python hl_lines="9-11"
{!> ../../../docs_src/body_nested_models/tutorial004_py39.py!}
```
=== "Python 3.10 and above"
=== "Python 3.6+"
```Python hl_lines="7-9"
{!> ../../../docs_src/body_nested_models/tutorial004_py310.py!}
```Python hl_lines="9-11"
{!> ../../../docs_src/body_nested_models/tutorial004.py!}
```
### Use the submodel as a type
And then we can use it as the type of an attribute:
=== "Python 3.6 and above"
=== "Python 3.10+"
```Python hl_lines="20"
{!> ../../../docs_src/body_nested_models/tutorial004.py!}
```Python hl_lines="18"
{!> ../../../docs_src/body_nested_models/tutorial004_py310.py!}
```
=== "Python 3.9 and above"
=== "Python 3.9+"
```Python hl_lines="20"
{!> ../../../docs_src/body_nested_models/tutorial004_py39.py!}
```
=== "Python 3.10 and above"
=== "Python 3.6+"
```Python hl_lines="18"
{!> ../../../docs_src/body_nested_models/tutorial004_py310.py!}
```Python hl_lines="20"
{!> ../../../docs_src/body_nested_models/tutorial004.py!}
```
This would mean that **FastAPI** would expect a body similar to:
@@ -196,22 +196,22 @@ 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 3.6 and above"
=== "Python 3.10+"
```Python hl_lines="4 10"
{!> ../../../docs_src/body_nested_models/tutorial005.py!}
```Python hl_lines="2 8"
{!> ../../../docs_src/body_nested_models/tutorial005_py310.py!}
```
=== "Python 3.9 and above"
=== "Python 3.9+"
```Python hl_lines="4 10"
{!> ../../../docs_src/body_nested_models/tutorial005_py39.py!}
```
=== "Python 3.10 and above"
=== "Python 3.6+"
```Python hl_lines="2 8"
{!> ../../../docs_src/body_nested_models/tutorial005_py310.py!}
```Python hl_lines="4 10"
{!> ../../../docs_src/body_nested_models/tutorial005.py!}
```
The string will be checked to be a valid URL, and documented in JSON Schema / OpenAPI as such.
@@ -220,22 +220,22 @@ 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 3.6 and above"
=== "Python 3.10+"
```Python hl_lines="20"
{!> ../../../docs_src/body_nested_models/tutorial006.py!}
```Python hl_lines="18"
{!> ../../../docs_src/body_nested_models/tutorial006_py310.py!}
```
=== "Python 3.9 and above"
=== "Python 3.9+"
```Python hl_lines="20"
{!> ../../../docs_src/body_nested_models/tutorial006_py39.py!}
```
=== "Python 3.10 and above"
=== "Python 3.6+"
```Python hl_lines="18"
{!> ../../../docs_src/body_nested_models/tutorial006_py310.py!}
```Python hl_lines="20"
{!> ../../../docs_src/body_nested_models/tutorial006.py!}
```
This will expect (convert, validate, document, etc) a JSON body like:
@@ -271,22 +271,22 @@ This will expect (convert, validate, document, etc) a JSON body like:
You can define arbitrarily deeply nested models:
=== "Python 3.6 and above"
=== "Python 3.10+"
```Python hl_lines="9 14 20 23 27"
{!> ../../../docs_src/body_nested_models/tutorial007.py!}
```Python hl_lines="7 12 18 21 25"
{!> ../../../docs_src/body_nested_models/tutorial007_py310.py!}
```
=== "Python 3.9 and above"
=== "Python 3.9+"
```Python hl_lines="9 14 20 23 27"
{!> ../../../docs_src/body_nested_models/tutorial007_py39.py!}
```
=== "Python 3.10 and above"
=== "Python 3.6+"
```Python hl_lines="7 12 18 21 25"
{!> ../../../docs_src/body_nested_models/tutorial007_py310.py!}
```Python hl_lines="9 14 20 23 27"
{!> ../../../docs_src/body_nested_models/tutorial007.py!}
```
!!! info
@@ -308,18 +308,18 @@ images: list[Image]
as in:
=== "Python 3.6 and above"
```Python hl_lines="15"
{!> ../../../docs_src/body_nested_models/tutorial008.py!}
```
=== "Python 3.9 and above"
=== "Python 3.9+"
```Python hl_lines="13"
{!> ../../../docs_src/body_nested_models/tutorial008_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="15"
{!> ../../../docs_src/body_nested_models/tutorial008.py!}
```
## Editor support everywhere
And you get editor support everywhere.
@@ -348,18 +348,18 @@ 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 3.6 and above"
```Python hl_lines="9"
{!> ../../../docs_src/body_nested_models/tutorial009.py!}
```
=== "Python 3.9 and above"
=== "Python 3.9+"
```Python hl_lines="7"
{!> ../../../docs_src/body_nested_models/tutorial009_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="9"
{!> ../../../docs_src/body_nested_models/tutorial009.py!}
```
!!! tip
Have in mind that JSON only supports `str` as keys.

View File

@@ -6,22 +6,22 @@ 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 3.6 and above"
=== "Python 3.10+"
```Python hl_lines="30-35"
{!> ../../../docs_src/body_updates/tutorial001.py!}
```Python hl_lines="28-33"
{!> ../../../docs_src/body_updates/tutorial001_py310.py!}
```
=== "Python 3.9 and above"
=== "Python 3.9+"
```Python hl_lines="30-35"
{!> ../../../docs_src/body_updates/tutorial001_py39.py!}
```
=== "Python 3.10 and above"
=== "Python 3.6+"
```Python hl_lines="28-33"
{!> ../../../docs_src/body_updates/tutorial001_py310.py!}
```Python hl_lines="30-35"
{!> ../../../docs_src/body_updates/tutorial001.py!}
```
`PUT` is used to receive data that should replace the existing data.
@@ -67,22 +67,22 @@ 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 3.6 and above"
=== "Python 3.10+"
```Python hl_lines="34"
{!> ../../../docs_src/body_updates/tutorial002.py!}
```Python hl_lines="32"
{!> ../../../docs_src/body_updates/tutorial002_py310.py!}
```
=== "Python 3.9 and above"
=== "Python 3.9+"
```Python hl_lines="34"
{!> ../../../docs_src/body_updates/tutorial002_py39.py!}
```
=== "Python 3.10 and above"
=== "Python 3.6+"
```Python hl_lines="32"
{!> ../../../docs_src/body_updates/tutorial002_py310.py!}
```Python hl_lines="34"
{!> ../../../docs_src/body_updates/tutorial002.py!}
```
### Using Pydantic's `update` parameter
@@ -91,22 +91,22 @@ Now, you can create a copy of the existing model using `.copy()`, and pass the `
Like `stored_item_model.copy(update=update_data)`:
=== "Python 3.6 and above"
=== "Python 3.10+"
```Python hl_lines="35"
{!> ../../../docs_src/body_updates/tutorial002.py!}
```Python hl_lines="33"
{!> ../../../docs_src/body_updates/tutorial002_py310.py!}
```
=== "Python 3.9 and above"
=== "Python 3.9+"
```Python hl_lines="35"
{!> ../../../docs_src/body_updates/tutorial002_py39.py!}
```
=== "Python 3.10 and above"
=== "Python 3.6+"
```Python hl_lines="33"
{!> ../../../docs_src/body_updates/tutorial002_py310.py!}
```Python hl_lines="35"
{!> ../../../docs_src/body_updates/tutorial002.py!}
```
### Partial updates recap
@@ -124,22 +124,22 @@ In summary, to apply partial updates you would:
* Save the data to your DB.
* Return the updated model.
=== "Python 3.6 and above"
=== "Python 3.10+"
```Python hl_lines="30-37"
{!> ../../../docs_src/body_updates/tutorial002.py!}
```Python hl_lines="28-35"
{!> ../../../docs_src/body_updates/tutorial002_py310.py!}
```
=== "Python 3.9 and above"
=== "Python 3.9+"
```Python hl_lines="30-37"
{!> ../../../docs_src/body_updates/tutorial002_py39.py!}
```
=== "Python 3.10 and above"
=== "Python 3.6+"
```Python hl_lines="28-35"
{!> ../../../docs_src/body_updates/tutorial002_py310.py!}
```Python hl_lines="30-37"
{!> ../../../docs_src/body_updates/tutorial002.py!}
```
!!! tip

View File

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

View File

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

View File

@@ -57,7 +57,7 @@ The following arguments are supported:
* `allow_origins` - A list of origins that should be permitted to make cross-origin requests. E.g. `['https://example.org', 'https://www.example.org']`. You can use `['*']` to allow any origin.
* `allow_origin_regex` - A regex string to match against origins that should be permitted to make cross-origin requests. e.g. `'https://.*\.example\.org'`.
* `allow_methods` - A list of HTTP methods that should be allowed for cross-origin requests. Defaults to `['GET']`. You can use `['*']` to allow all standard methods.
* `allow_headers` - A list of HTTP request headers that should be supported for cross-origin requests. Defaults to `[]`. You can use `['*']` to allow all headers. The `Accept`, `Accept-Language`, `Content-Language` and `Content-Type` headers are always allowed for CORS requests.
* `allow_headers` - A list of HTTP request headers that should be supported for cross-origin requests. Defaults to `[]`. You can use `['*']` to allow all headers. The `Accept`, `Accept-Language`, `Content-Language` and `Content-Type` headers are always allowed for <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#simple_requests" class="external-link" rel="noopener" target="_blank">simple CORS requests</a>.
* `allow_credentials` - Indicate that cookies should be supported for cross-origin requests. Defaults to `False`. Also, `allow_origins` cannot be set to `['*']` for credentials to be allowed, origins must be specified.
* `expose_headers` - Indicate any response headers that should be made accessible to the browser. Defaults to `[]`.
* `max_age` - Sets a maximum time in seconds for browsers to cache CORS responses. Defaults to `600`.

View File

@@ -6,18 +6,42 @@ 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 3.6 and above"
=== "Python 3.10+"
```Python hl_lines="9"
{!> ../../../docs_src/dependencies/tutorial001.py!}
{!> ../../../docs_src/dependencies/tutorial001_an_py310.py!}
```
=== "Python 3.10 and above"
=== "Python 3.9+"
```Python hl_lines="11"
{!> ../../../docs_src/dependencies/tutorial001_an_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="12"
{!> ../../../docs_src/dependencies/tutorial001_an.py!}
```
=== "Python 3.10+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="7"
{!> ../../../docs_src/dependencies/tutorial001_py310.py!}
```
=== "Python 3.6+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="11"
{!> ../../../docs_src/dependencies/tutorial001.py!}
```
But then we get a `dict` in the parameter `commons` of the *path operation function*.
And we know that editors can't provide a lot of support (like completion) for `dict`s, because they can't know their keys and value types.
@@ -79,46 +103,118 @@ 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 3.6 and above"
=== "Python 3.10+"
```Python hl_lines="11-15"
{!> ../../../docs_src/dependencies/tutorial002.py!}
{!> ../../../docs_src/dependencies/tutorial002_an_py310.py!}
```
=== "Python 3.10 and above"
=== "Python 3.9+"
```Python hl_lines="11-15"
{!> ../../../docs_src/dependencies/tutorial002_an_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="12-16"
{!> ../../../docs_src/dependencies/tutorial002_an.py!}
```
=== "Python 3.10+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```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 3.6+ non-Annotated"
=== "Python 3.6 and above"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="12"
```Python hl_lines="11-15"
{!> ../../../docs_src/dependencies/tutorial002.py!}
```
=== "Python 3.10 and above"
Pay attention to the `__init__` method used to create the instance of the class:
=== "Python 3.10+"
```Python hl_lines="12"
{!> ../../../docs_src/dependencies/tutorial002_an_py310.py!}
```
=== "Python 3.9+"
```Python hl_lines="12"
{!> ../../../docs_src/dependencies/tutorial002_an_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="13"
{!> ../../../docs_src/dependencies/tutorial002_an.py!}
```
=== "Python 3.10+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="10"
{!> ../../../docs_src/dependencies/tutorial002_py310.py!}
```
...it has the same parameters as our previous `common_parameters`:
=== "Python 3.6+ non-Annotated"
=== "Python 3.6 and above"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="9"
{!> ../../../docs_src/dependencies/tutorial001.py!}
```Python hl_lines="12"
{!> ../../../docs_src/dependencies/tutorial002.py!}
```
=== "Python 3.10 and above"
...it has the same parameters as our previous `common_parameters`:
=== "Python 3.10+"
```Python hl_lines="8"
{!> ../../../docs_src/dependencies/tutorial001_an_py310.py!}
```
=== "Python 3.9+"
```Python hl_lines="9"
{!> ../../../docs_src/dependencies/tutorial001_an_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="10"
{!> ../../../docs_src/dependencies/tutorial001_an.py!}
```
=== "Python 3.10+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="6"
{!> ../../../docs_src/dependencies/tutorial001_py310.py!}
```
=== "Python 3.6+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="9"
{!> ../../../docs_src/dependencies/tutorial001.py!}
```
Those parameters are what **FastAPI** will use to "solve" the dependency.
In both cases, it will have:
@@ -133,32 +229,67 @@ In both cases the data will be converted, validated, documented on the OpenAPI s
Now you can declare your dependency using this class.
=== "Python 3.6 and above"
=== "Python 3.10+"
```Python hl_lines="19"
{!> ../../../docs_src/dependencies/tutorial002.py!}
{!> ../../../docs_src/dependencies/tutorial002_an_py310.py!}
```
=== "Python 3.10 and above"
=== "Python 3.9+"
```Python hl_lines="19"
{!> ../../../docs_src/dependencies/tutorial002_an_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="20"
{!> ../../../docs_src/dependencies/tutorial002_an.py!}
```
=== "Python 3.10+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="17"
{!> ../../../docs_src/dependencies/tutorial002_py310.py!}
```
=== "Python 3.6+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="19"
{!> ../../../docs_src/dependencies/tutorial002.py!}
```
**FastAPI** calls the `CommonQueryParams` class. This creates an "instance" of that class and the instance will be passed as the parameter `commons` to your function.
## Type annotation vs `Depends`
Notice how we write `CommonQueryParams` twice in the above code:
```Python
commons: CommonQueryParams = Depends(CommonQueryParams)
```
=== "Python 3.6+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python
commons: CommonQueryParams = Depends(CommonQueryParams)
```
=== "Python 3.6+"
```Python
commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)]
```
The last `CommonQueryParams`, in:
```Python
... = Depends(CommonQueryParams)
... Depends(CommonQueryParams)
```
...is what **FastAPI** will actually use to know what is the dependency.
@@ -169,32 +300,78 @@ From it is that FastAPI will extract the declared parameters and that is what Fa
In this case, the first `CommonQueryParams`, in:
```Python
commons: CommonQueryParams ...
```
=== "Python 3.6+"
...doesn't have any special meaning for **FastAPI**. FastAPI won't use it for data conversion, validation, etc. (as it is using the `= Depends(CommonQueryParams)` for that).
```Python
commons: Annotated[CommonQueryParams, ...
```
=== "Python 3.6+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python
commons: CommonQueryParams ...
```
...doesn't have any special meaning for **FastAPI**. FastAPI won't use it for data conversion, validation, etc. (as it is using the `Depends(CommonQueryParams)` for that).
You could actually write just:
```Python
commons = Depends(CommonQueryParams)
```
=== "Python 3.6+"
```Python
commons: Annotated[Any, Depends(CommonQueryParams)]
```
=== "Python 3.6+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python
commons = Depends(CommonQueryParams)
```
..as in:
=== "Python 3.6 and above"
=== "Python 3.10+"
```Python hl_lines="19"
{!> ../../../docs_src/dependencies/tutorial003.py!}
{!> ../../../docs_src/dependencies/tutorial003_an_py310.py!}
```
=== "Python 3.10 and above"
=== "Python 3.9+"
```Python hl_lines="19"
{!> ../../../docs_src/dependencies/tutorial003_an_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="20"
{!> ../../../docs_src/dependencies/tutorial003_an.py!}
```
=== "Python 3.10+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="17"
{!> ../../../docs_src/dependencies/tutorial003_py310.py!}
```
=== "Python 3.6+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="19"
{!> ../../../docs_src/dependencies/tutorial003.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:
<img src="/img/tutorial/dependencies/image02.png">
@@ -203,9 +380,20 @@ But declaring the type is encouraged as that way your editor will know what will
But you see that we are having some code repetition here, writing `CommonQueryParams` twice:
```Python
commons: CommonQueryParams = Depends(CommonQueryParams)
```
=== "Python 3.6+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python
commons: CommonQueryParams = Depends(CommonQueryParams)
```
=== "Python 3.6+"
```Python
commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)]
```
**FastAPI** provides a shortcut for these cases, in where the dependency is *specifically* a class that **FastAPI** will "call" to create an instance of the class itself.
@@ -213,32 +401,78 @@ For those specific cases, you can do the following:
Instead of writing:
```Python
commons: CommonQueryParams = Depends(CommonQueryParams)
```
=== "Python 3.6+"
```Python
commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)]
```
=== "Python 3.6+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python
commons: CommonQueryParams = Depends(CommonQueryParams)
```
...you write:
```Python
commons: CommonQueryParams = Depends()
```
=== "Python 3.6+"
You declare the dependency as the type of the parameter, and you use `Depends()` as its "default" value (that after the `=`) for that function's parameter, without any parameter in `Depends()`, instead of having to write the full class *again* inside of `Depends(CommonQueryParams)`.
```Python
commons: Annotated[CommonQueryParams, Depends()]
```
=== "Python 3.6 non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python
commons: CommonQueryParams = Depends()
```
You declare the dependency as the type of the parameter, and you use `Depends()` without any parameter, instead of having to write the full class *again* inside of `Depends(CommonQueryParams)`.
The same example would then look like:
=== "Python 3.6 and above"
=== "Python 3.10+"
```Python hl_lines="19"
{!> ../../../docs_src/dependencies/tutorial004.py!}
{!> ../../../docs_src/dependencies/tutorial004_an_py310.py!}
```
=== "Python 3.10 and above"
=== "Python 3.9+"
```Python hl_lines="19"
{!> ../../../docs_src/dependencies/tutorial004_an_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="20"
{!> ../../../docs_src/dependencies/tutorial004_an.py!}
```
=== "Python 3.10+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="17"
{!> ../../../docs_src/dependencies/tutorial004_py310.py!}
```
=== "Python 3.6+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="19"
{!> ../../../docs_src/dependencies/tutorial004.py!}
```
...and **FastAPI** will know what to do.
!!! tip

View File

@@ -14,9 +14,26 @@ The *path operation decorator* receives an optional argument `dependencies`.
It should be a `list` of `Depends()`:
```Python hl_lines="17"
{!../../../docs_src/dependencies/tutorial006.py!}
```
=== "Python 3.9+"
```Python hl_lines="19"
{!> ../../../docs_src/dependencies/tutorial006_an_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="18"
{!> ../../../docs_src/dependencies/tutorial006_an.py!}
```
=== "Python 3.6 non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="17"
{!> ../../../docs_src/dependencies/tutorial006.py!}
```
These dependencies will be executed/solved the same way normal dependencies. But their value (if they return any) won't be passed to your *path operation function*.
@@ -40,17 +57,51 @@ You can use the same dependency *functions* you use normally.
They can declare request requirements (like headers) or other sub-dependencies:
```Python hl_lines="6 11"
{!../../../docs_src/dependencies/tutorial006.py!}
```
=== "Python 3.9+"
```Python hl_lines="8 13"
{!> ../../../docs_src/dependencies/tutorial006_an_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="7 12"
{!> ../../../docs_src/dependencies/tutorial006_an.py!}
```
=== "Python 3.6 non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="6 11"
{!> ../../../docs_src/dependencies/tutorial006.py!}
```
### Raise exceptions
These dependencies can `raise` exceptions, the same as normal dependencies:
```Python hl_lines="8 13"
{!../../../docs_src/dependencies/tutorial006.py!}
```
=== "Python 3.9+"
```Python hl_lines="10 15"
{!> ../../../docs_src/dependencies/tutorial006_an_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="9 14"
{!> ../../../docs_src/dependencies/tutorial006_an.py!}
```
=== "Python 3.6 non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="8 13"
{!> ../../../docs_src/dependencies/tutorial006.py!}
```
### Return values
@@ -58,9 +109,26 @@ And they can return values or not, the values won't be used.
So, you can re-use a normal dependency (that returns a value) you already use somewhere else, and even though the value won't be used, the dependency will be executed:
```Python hl_lines="9 14"
{!../../../docs_src/dependencies/tutorial006.py!}
```
=== "Python 3.9+"
```Python hl_lines="11 16"
{!> ../../../docs_src/dependencies/tutorial006_an_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="10 15"
{!> ../../../docs_src/dependencies/tutorial006_an.py!}
```
=== "Python 3.6 non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="9 14"
{!> ../../../docs_src/dependencies/tutorial006.py!}
```
## Dependencies for a group of *path operations*

View File

@@ -66,9 +66,26 @@ You can have sub-dependencies and "trees" of sub-dependencies of any size and sh
For example, `dependency_c` can have a dependency on `dependency_b`, and `dependency_b` on `dependency_a`:
```Python hl_lines="4 12 20"
{!../../../docs_src/dependencies/tutorial008.py!}
```
=== "Python 3.9+"
```Python hl_lines="6 14 22"
{!> ../../../docs_src/dependencies/tutorial008_an_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="5 13 21"
{!> ../../../docs_src/dependencies/tutorial008_an.py!}
```
=== "Python 3.6+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="4 12 20"
{!> ../../../docs_src/dependencies/tutorial008.py!}
```
And all of them can use `yield`.
@@ -76,9 +93,26 @@ In this case `dependency_c`, to execute its exit code, needs the value from `dep
And, in turn, `dependency_b` needs the value from `dependency_a` (here named `dep_a`) to be available for its exit code.
```Python hl_lines="16-17 24-25"
{!../../../docs_src/dependencies/tutorial008.py!}
```
=== "Python 3.9+"
```Python hl_lines="18-19 26-27"
{!> ../../../docs_src/dependencies/tutorial008_an_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="17-18 25-26"
{!> ../../../docs_src/dependencies/tutorial008_an.py!}
```
=== "Python 3.6+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="16-17 24-25"
{!> ../../../docs_src/dependencies/tutorial008.py!}
```
The same way, you could have dependencies with `yield` and `return` mixed.

View File

@@ -6,9 +6,26 @@ Similar to the way you can [add `dependencies` to the *path operation decorators
In that case, they will be applied to all the *path operations* in the application:
```Python hl_lines="15"
{!../../../docs_src/dependencies/tutorial012.py!}
```
=== "Python 3.9+"
```Python hl_lines="16"
{!> ../../../docs_src/dependencies/tutorial012_an_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="16"
{!> ../../../docs_src/dependencies/tutorial012_an.py!}
```
=== "Python 3.6 non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="15"
{!> ../../../docs_src/dependencies/tutorial012.py!}
```
And all the ideas in the section about [adding `dependencies` to the *path operation decorators*](dependencies-in-path-operation-decorators.md){.internal-link target=_blank} still apply, but in this case, to all of the *path operations* in the app.

View File

@@ -31,18 +31,42 @@ 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 3.6 and above"
=== "Python 3.10+"
```Python hl_lines="8-11"
{!> ../../../docs_src/dependencies/tutorial001.py!}
```Python hl_lines="8-9"
{!> ../../../docs_src/dependencies/tutorial001_an_py310.py!}
```
=== "Python 3.10 and above"
=== "Python 3.9+"
```Python hl_lines="8-11"
{!> ../../../docs_src/dependencies/tutorial001_an_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="9-12"
{!> ../../../docs_src/dependencies/tutorial001_an.py!}
```
=== "Python 3.10+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="6-7"
{!> ../../../docs_src/dependencies/tutorial001_py310.py!}
```
=== "Python 3.6+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="8-11"
{!> ../../../docs_src/dependencies/tutorial001.py!}
```
That's it.
**2 lines**.
@@ -63,40 +87,90 @@ And then it just returns a `dict` containing those values.
### Import `Depends`
=== "Python 3.6 and above"
=== "Python 3.10+"
```Python hl_lines="3"
{!> ../../../docs_src/dependencies/tutorial001.py!}
{!> ../../../docs_src/dependencies/tutorial001_an_py310.py!}
```
=== "Python 3.10 and above"
=== "Python 3.9+"
```Python hl_lines="3"
{!> ../../../docs_src/dependencies/tutorial001_an_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="3"
{!> ../../../docs_src/dependencies/tutorial001_an.py!}
```
=== "Python 3.10+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="1"
{!> ../../../docs_src/dependencies/tutorial001_py310.py!}
```
=== "Python 3.6+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="3"
{!> ../../../docs_src/dependencies/tutorial001.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 3.6 and above"
=== "Python 3.10+"
```Python hl_lines="15 20"
{!> ../../../docs_src/dependencies/tutorial001.py!}
```Python hl_lines="13 18"
{!> ../../../docs_src/dependencies/tutorial001_an_py310.py!}
```
=== "Python 3.10 and above"
=== "Python 3.9+"
```Python hl_lines="15 20"
{!> ../../../docs_src/dependencies/tutorial001_an_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="16 21"
{!> ../../../docs_src/dependencies/tutorial001_an.py!}
```
=== "Python 3.10+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="11 16"
{!> ../../../docs_src/dependencies/tutorial001_py310.py!}
```
=== "Python 3.6+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="15 20"
{!> ../../../docs_src/dependencies/tutorial001.py!}
```
Although you use `Depends` in the parameters of your function the same way you use `Body`, `Query`, etc, `Depends` works a bit differently.
You only give `Depends` a single parameter.
This parameter must be something like a function.
You **don't call it** directly (don't add the parenthesis at the end), you just pass it as a parameter to `Depends()`.
And that function takes parameters in the same way that *path operation functions* do.
!!! tip
@@ -126,6 +200,45 @@ This way you write shared code once and **FastAPI** takes care of calling it for
You just pass it to `Depends` and **FastAPI** knows how to do the rest.
## Share `Annotated` dependencies
In the examples above, you see that there's a tiny bit of **code duplication**.
When you need to use the `common_parameters()` dependency, you have to write the whole parameter with the type annotation and `Depends()`:
```Python
commons: Annotated[dict, Depends(common_parameters)]
```
But because we are using `Annotated`, we can store that `Annotated` value in a variable and use it in multiple places:
=== "Python 3.10+"
```Python hl_lines="12 16 21"
{!> ../../../docs_src/dependencies/tutorial001_02_an_py310.py!}
```
=== "Python 3.9+"
```Python hl_lines="14 18 23"
{!> ../../../docs_src/dependencies/tutorial001_02_an_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="15 19 24"
{!> ../../../docs_src/dependencies/tutorial001_02_an.py!}
```
!!! tip
This is just standard Python, it's called a "type alias", it's actually not specific to **FastAPI**.
But because **FastAPI** is based on the Python standards, including `Annotated`, you can use this trick in your code. 😎
The dependencies will keep working as expected, and the **best part** is that the **type information will be preserved**, which means that your editor will be able to keep providing you with **autocompletion**, **inline errors**, etc. The same for other tools like `mypy`.
This will be especially useful when you use it in a **large code base** where you use **the same dependencies** over and over again in **many *path operations***.
## To `async` or not to `async`
As dependencies will also be called by **FastAPI** (the same as your *path operation functions*), the same rules apply while defining your functions.

View File

@@ -10,18 +10,42 @@ They can be as **deep** as you need them to be.
You could create a first dependency ("dependable") like:
=== "Python 3.6 and above"
=== "Python 3.10+"
```Python hl_lines="8-9"
{!> ../../../docs_src/dependencies/tutorial005.py!}
{!> ../../../docs_src/dependencies/tutorial005_an_py310.py!}
```
=== "Python 3.10 and above"
=== "Python 3.9+"
```Python hl_lines="8-9"
{!> ../../../docs_src/dependencies/tutorial005_an_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="9-10"
{!> ../../../docs_src/dependencies/tutorial005_an.py!}
```
=== "Python 3.10 non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="6-7"
{!> ../../../docs_src/dependencies/tutorial005_py310.py!}
```
=== "Python 3.6 non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="8-9"
{!> ../../../docs_src/dependencies/tutorial005.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.
@@ -30,18 +54,42 @@ This is quite simple (not very useful), but will help us focus on how the sub-de
Then you can create another dependency function (a "dependable") that at the same time declares a dependency of its own (so it is a "dependant" too):
=== "Python 3.6 and above"
=== "Python 3.10+"
```Python hl_lines="13"
{!> ../../../docs_src/dependencies/tutorial005.py!}
{!> ../../../docs_src/dependencies/tutorial005_an_py310.py!}
```
=== "Python 3.10 and above"
=== "Python 3.9+"
```Python hl_lines="13"
{!> ../../../docs_src/dependencies/tutorial005_an_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="14"
{!> ../../../docs_src/dependencies/tutorial005_an.py!}
```
=== "Python 3.10 non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="11"
{!> ../../../docs_src/dependencies/tutorial005_py310.py!}
```
=== "Python 3.6 non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="13"
{!> ../../../docs_src/dependencies/tutorial005.py!}
```
Let's focus on the parameters declared:
* Even though this function is a dependency ("dependable") itself, it also declares another dependency (it "depends" on something else).
@@ -53,18 +101,42 @@ Let's focus on the parameters declared:
Then we can use the dependency with:
=== "Python 3.6 and above"
=== "Python 3.10+"
```Python hl_lines="22"
{!> ../../../docs_src/dependencies/tutorial005.py!}
```Python hl_lines="23"
{!> ../../../docs_src/dependencies/tutorial005_an_py310.py!}
```
=== "Python 3.10 and above"
=== "Python 3.9+"
```Python hl_lines="23"
{!> ../../../docs_src/dependencies/tutorial005_an_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="24"
{!> ../../../docs_src/dependencies/tutorial005_an.py!}
```
=== "Python 3.10 non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="19"
{!> ../../../docs_src/dependencies/tutorial005_py310.py!}
```
=== "Python 3.6 non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="22"
{!> ../../../docs_src/dependencies/tutorial005.py!}
```
!!! info
Notice that we are only declaring one dependency in the *path operation function*, the `query_or_cookie_extractor`.
@@ -89,10 +161,22 @@ And it will save the returned value in a <abbr title="A utility/system to store
In an advanced scenario where you know you need the dependency to be called at every step (possibly multiple times) in the same request instead of using the "cached" value, you can set the parameter `use_cache=False` when using `Depends`:
```Python hl_lines="1"
async def needy_dependency(fresh_value: str = Depends(get_value, use_cache=False)):
return {"fresh_value": fresh_value}
```
=== "Python 3.6+"
```Python hl_lines="1"
async def needy_dependency(fresh_value: Annotated[str, Depends(get_value, use_cache=False)]):
return {"fresh_value": fresh_value}
```
=== "Python 3.6+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="1"
async def needy_dependency(fresh_value: str = Depends(get_value, use_cache=False)):
return {"fresh_value": fresh_value}
```
## Recap

View File

@@ -20,18 +20,18 @@ You can use `jsonable_encoder` for that.
It receives an object, like a Pydantic model, and returns a JSON compatible version:
=== "Python 3.6 and above"
```Python hl_lines="5 22"
{!> ../../../docs_src/encoder/tutorial001.py!}
```
=== "Python 3.10 and above"
=== "Python 3.10+"
```Python hl_lines="4 21"
{!> ../../../docs_src/encoder/tutorial001_py310.py!}
```
=== "Python 3.6+"
```Python hl_lines="5 22"
{!> ../../../docs_src/encoder/tutorial001.py!}
```
In this example, it would convert the Pydantic model to a `dict`, and the `datetime` to a `str`.
The result of calling it is something that can be encoded with the Python standard <a href="https://docs.python.org/3/library/json.html#json.dumps" class="external-link" target="_blank">`json.dumps()`</a>.

View File

@@ -55,28 +55,76 @@ 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 3.6 and above"
=== "Python 3.10+"
```Python hl_lines="1 3 12-16"
{!> ../../../docs_src/extra_data_types/tutorial001.py!}
{!> ../../../docs_src/extra_data_types/tutorial001_an_py310.py!}
```
=== "Python 3.10 and above"
=== "Python 3.9+"
```Python hl_lines="1 3 12-16"
{!> ../../../docs_src/extra_data_types/tutorial001_an_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="1 3 13-17"
{!> ../../../docs_src/extra_data_types/tutorial001_an.py!}
```
=== "Python 3.10+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```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 3.6+ non-Annotated"
=== "Python 3.6 and above"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="18-19"
```Python hl_lines="1 2 12-16"
{!> ../../../docs_src/extra_data_types/tutorial001.py!}
```
=== "Python 3.10 and above"
Note that the parameters inside the function have their natural data type, and you can, for example, perform normal date manipulations, like:
=== "Python 3.10+"
```Python hl_lines="18-19"
{!> ../../../docs_src/extra_data_types/tutorial001_an_py310.py!}
```
=== "Python 3.9+"
```Python hl_lines="18-19"
{!> ../../../docs_src/extra_data_types/tutorial001_an_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="19-20"
{!> ../../../docs_src/extra_data_types/tutorial001_an.py!}
```
=== "Python 3.10+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="17-18"
{!> ../../../docs_src/extra_data_types/tutorial001_py310.py!}
```
=== "Python 3.6+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="18-19"
{!> ../../../docs_src/extra_data_types/tutorial001.py!}
```

View File

@@ -17,18 +17,18 @@ 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 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 3.10+"
```Python hl_lines="7 9 14 20 22 27-28 31-33 38-39"
{!> ../../../docs_src/extra_models/tutorial001_py310.py!}
```
=== "Python 3.6+"
```Python hl_lines="9 11 16 22 24 29-30 33-35 40-41"
{!> ../../../docs_src/extra_models/tutorial001.py!}
```
### About `**user_in.dict()`
#### Pydantic's `.dict()`
@@ -158,18 +158,18 @@ 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 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 3.10+"
```Python hl_lines="7 13-14 17-18 21-22"
{!> ../../../docs_src/extra_models/tutorial002_py310.py!}
```
=== "Python 3.6+"
```Python hl_lines="9 15-16 19-20 23-24"
{!> ../../../docs_src/extra_models/tutorial002.py!}
```
## `Union` or `anyOf`
You can declare a response to be the `Union` of two types, that means, that the response would be any of the two.
@@ -181,18 +181,18 @@ 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 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 3.10+"
```Python hl_lines="1 14-15 18-20 33"
{!> ../../../docs_src/extra_models/tutorial003_py310.py!}
```
=== "Python 3.6+"
```Python hl_lines="1 14-15 18-20 33"
{!> ../../../docs_src/extra_models/tutorial003.py!}
```
### `Union` in Python 3.10
In this example we pass `Union[PlaneItem, CarItem]` as the value of the argument `response_model`.
@@ -213,18 +213,18 @@ The same way, you can declare responses of lists of objects.
For that, use the standard Python `typing.List` (or just `list` in Python 3.9 and above):
=== "Python 3.6 and above"
```Python hl_lines="1 20"
{!> ../../../docs_src/extra_models/tutorial004.py!}
```
=== "Python 3.9 and above"
=== "Python 3.9+"
```Python hl_lines="18"
{!> ../../../docs_src/extra_models/tutorial004_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="1 20"
{!> ../../../docs_src/extra_models/tutorial004.py!}
```
## Response with arbitrary `dict`
You can also declare a response using a plain arbitrary `dict`, declaring just the type of the keys and values, without using a Pydantic model.
@@ -233,18 +233,18 @@ This is useful if you don't know the valid field/attribute names (that would be
In this case, you can use `typing.Dict` (or just `dict` in Python 3.9 and above):
=== "Python 3.6 and above"
```Python hl_lines="1 8"
{!> ../../../docs_src/extra_models/tutorial005.py!}
```
=== "Python 3.9 and above"
=== "Python 3.9+"
```Python hl_lines="6"
{!> ../../../docs_src/extra_models/tutorial005_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="1 8"
{!> ../../../docs_src/extra_models/tutorial005.py!}
```
## Recap
Use multiple Pydantic models and inherit freely for each case.

View File

@@ -6,36 +6,84 @@ You can define Header parameters the same way you define `Query`, `Path` and `Co
First import `Header`:
=== "Python 3.6 and above"
=== "Python 3.10+"
```Python hl_lines="3"
{!> ../../../docs_src/header_params/tutorial001.py!}
{!> ../../../docs_src/header_params/tutorial001_an_py310.py!}
```
=== "Python 3.10 and above"
=== "Python 3.9+"
```Python hl_lines="3"
{!> ../../../docs_src/header_params/tutorial001_an_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="3"
{!> ../../../docs_src/header_params/tutorial001_an.py!}
```
=== "Python 3.10+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="1"
{!> ../../../docs_src/header_params/tutorial001_py310.py!}
```
=== "Python 3.6+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="3"
{!> ../../../docs_src/header_params/tutorial001.py!}
```
## Declare `Header` parameters
Then declare the header parameters using the same structure as with `Path`, `Query` and `Cookie`.
The first value is the default value, you can pass all the extra validation or annotation parameters:
=== "Python 3.6 and above"
=== "Python 3.10+"
```Python hl_lines="9"
{!> ../../../docs_src/header_params/tutorial001.py!}
{!> ../../../docs_src/header_params/tutorial001_an_py310.py!}
```
=== "Python 3.10 and above"
=== "Python 3.9+"
```Python hl_lines="9"
{!> ../../../docs_src/header_params/tutorial001_an_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="10"
{!> ../../../docs_src/header_params/tutorial001_an.py!}
```
=== "Python 3.10+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="7"
{!> ../../../docs_src/header_params/tutorial001_py310.py!}
```
=== "Python 3.6+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="9"
{!> ../../../docs_src/header_params/tutorial001.py!}
```
!!! note "Technical Details"
`Header` is a "sister" class of `Path`, `Query` and `Cookie`. It also inherits from the same common `Param` class.
@@ -60,18 +108,42 @@ 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 3.6 and above"
=== "Python 3.10+"
```Python hl_lines="10"
{!> ../../../docs_src/header_params/tutorial002.py!}
{!> ../../../docs_src/header_params/tutorial002_an_py310.py!}
```
=== "Python 3.10 and above"
=== "Python 3.9+"
```Python hl_lines="11"
{!> ../../../docs_src/header_params/tutorial002_an_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="12"
{!> ../../../docs_src/header_params/tutorial002_an.py!}
```
=== "Python 3.10+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="8"
{!> ../../../docs_src/header_params/tutorial002_py310.py!}
```
=== "Python 3.6+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="10"
{!> ../../../docs_src/header_params/tutorial002.py!}
```
!!! warning
Before setting `convert_underscores` to `False`, bear in mind that some HTTP proxies and servers disallow the usage of headers with underscores.
@@ -85,22 +157,49 @@ 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 3.6 and above"
=== "Python 3.10+"
```Python hl_lines="9"
{!> ../../../docs_src/header_params/tutorial003.py!}
{!> ../../../docs_src/header_params/tutorial003_an_py310.py!}
```
=== "Python 3.9 and above"
=== "Python 3.9+"
```Python hl_lines="9"
{!> ../../../docs_src/header_params/tutorial003_an_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="10"
{!> ../../../docs_src/header_params/tutorial003_an.py!}
```
=== "Python 3.10+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="7"
{!> ../../../docs_src/header_params/tutorial003_py310.py!}
```
=== "Python 3.9+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="9"
{!> ../../../docs_src/header_params/tutorial003_py39.py!}
```
=== "Python 3.10 and above"
=== "Python 3.6+ non-Annotated"
```Python hl_lines="7"
{!> ../../../docs_src/header_params/tutorial003_py310.py!}
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="9"
{!> ../../../docs_src/header_params/tutorial003.py!}
```
If you communicate with that *path operation* sending two HTTP headers like:

View File

@@ -101,7 +101,7 @@ You can configure the two documentation user interfaces included:
* **Swagger UI**: served at `/docs`.
* You can set its URL with the parameter `docs_url`.
* You can disable it by setting `docs_url=None`.
* ReDoc: served at `/redoc`.
* **ReDoc**: served at `/redoc`.
* You can set its URL with the parameter `redoc_url`.
* You can disable it by setting `redoc_url=None`.

View File

@@ -13,22 +13,22 @@ 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 3.6 and above"
=== "Python 3.10+"
```Python hl_lines="3 17"
{!> ../../../docs_src/path_operation_configuration/tutorial001.py!}
```Python hl_lines="1 15"
{!> ../../../docs_src/path_operation_configuration/tutorial001_py310.py!}
```
=== "Python 3.9 and above"
=== "Python 3.9+"
```Python hl_lines="3 17"
{!> ../../../docs_src/path_operation_configuration/tutorial001_py39.py!}
```
=== "Python 3.10 and above"
=== "Python 3.6+"
```Python hl_lines="1 15"
{!> ../../../docs_src/path_operation_configuration/tutorial001_py310.py!}
```Python hl_lines="3 17"
{!> ../../../docs_src/path_operation_configuration/tutorial001.py!}
```
That status code will be used in the response and will be added to the OpenAPI schema.
@@ -42,22 +42,22 @@ 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 3.6 and above"
=== "Python 3.10+"
```Python hl_lines="17 22 27"
{!> ../../../docs_src/path_operation_configuration/tutorial002.py!}
```Python hl_lines="15 20 25"
{!> ../../../docs_src/path_operation_configuration/tutorial002_py310.py!}
```
=== "Python 3.9 and above"
=== "Python 3.9+"
```Python hl_lines="17 22 27"
{!> ../../../docs_src/path_operation_configuration/tutorial002_py39.py!}
```
=== "Python 3.10 and above"
=== "Python 3.6+"
```Python hl_lines="15 20 25"
{!> ../../../docs_src/path_operation_configuration/tutorial002_py310.py!}
```Python hl_lines="17 22 27"
{!> ../../../docs_src/path_operation_configuration/tutorial002.py!}
```
They will be added to the OpenAPI schema and used by the automatic documentation interfaces:
@@ -80,22 +80,22 @@ In these cases, it could make sense to store the tags in an `Enum`.
You can add a `summary` and `description`:
=== "Python 3.6 and above"
=== "Python 3.10+"
```Python hl_lines="20-21"
{!> ../../../docs_src/path_operation_configuration/tutorial003.py!}
```Python hl_lines="18-19"
{!> ../../../docs_src/path_operation_configuration/tutorial003_py310.py!}
```
=== "Python 3.9 and above"
=== "Python 3.9+"
```Python hl_lines="20-21"
{!> ../../../docs_src/path_operation_configuration/tutorial003_py39.py!}
```
=== "Python 3.10 and above"
=== "Python 3.6+"
```Python hl_lines="18-19"
{!> ../../../docs_src/path_operation_configuration/tutorial003_py310.py!}
```Python hl_lines="20-21"
{!> ../../../docs_src/path_operation_configuration/tutorial003.py!}
```
## Description from docstring
@@ -104,22 +104,22 @@ 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 3.6 and above"
=== "Python 3.10+"
```Python hl_lines="19-27"
{!> ../../../docs_src/path_operation_configuration/tutorial004.py!}
```Python hl_lines="17-25"
{!> ../../../docs_src/path_operation_configuration/tutorial004_py310.py!}
```
=== "Python 3.9 and above"
=== "Python 3.9+"
```Python hl_lines="19-27"
{!> ../../../docs_src/path_operation_configuration/tutorial004_py39.py!}
```
=== "Python 3.10 and above"
=== "Python 3.6+"
```Python hl_lines="17-25"
{!> ../../../docs_src/path_operation_configuration/tutorial004_py310.py!}
```Python hl_lines="19-27"
{!> ../../../docs_src/path_operation_configuration/tutorial004.py!}
```
It will be used in the interactive docs:
@@ -130,22 +130,22 @@ It will be used in the interactive docs:
You can specify the response description with the parameter `response_description`:
=== "Python 3.6 and above"
=== "Python 3.10+"
```Python hl_lines="21"
{!> ../../../docs_src/path_operation_configuration/tutorial005.py!}
```Python hl_lines="19"
{!> ../../../docs_src/path_operation_configuration/tutorial005_py310.py!}
```
=== "Python 3.9 and above"
=== "Python 3.9+"
```Python hl_lines="21"
{!> ../../../docs_src/path_operation_configuration/tutorial005_py39.py!}
```
=== "Python 3.10 and above"
=== "Python 3.6+"
```Python hl_lines="19"
{!> ../../../docs_src/path_operation_configuration/tutorial005_py310.py!}
```Python hl_lines="21"
{!> ../../../docs_src/path_operation_configuration/tutorial005.py!}
```
!!! info

View File

@@ -1,41 +1,89 @@
# Path Parameters and Numeric Validations
The same way you can declare more validations and metadata for query parameters with `Query`, you can declare the same type of validations and metadata for path parameters with `Path`.
In the same way that you can declare more validations and metadata for query parameters with `Query`, you can declare the same type of validations and metadata for path parameters with `Path`.
## Import Path
First, import `Path` from `fastapi`:
First, import `Path` from `fastapi`, and import `Annotated`:
=== "Python 3.6 and above"
=== "Python 3.10+"
```Python hl_lines="3"
{!> ../../../docs_src/path_params_numeric_validations/tutorial001.py!}
```Python hl_lines="1 3"
{!> ../../../docs_src/path_params_numeric_validations/tutorial001_an_py310.py!}
```
=== "Python 3.10 and above"
=== "Python 3.9+"
```Python hl_lines="1 3"
{!> ../../../docs_src/path_params_numeric_validations/tutorial001_an_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="3-4"
{!> ../../../docs_src/path_params_numeric_validations/tutorial001_an.py!}
```
=== "Python 3.10+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="1"
{!> ../../../docs_src/path_params_numeric_validations/tutorial001_py310.py!}
```
=== "Python 3.6+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="3"
{!> ../../../docs_src/path_params_numeric_validations/tutorial001.py!}
```
## Declare metadata
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 3.6 and above"
=== "Python 3.10+"
```Python hl_lines="10"
{!> ../../../docs_src/path_params_numeric_validations/tutorial001.py!}
{!> ../../../docs_src/path_params_numeric_validations/tutorial001_an_py310.py!}
```
=== "Python 3.10 and above"
=== "Python 3.9+"
```Python hl_lines="10"
{!> ../../../docs_src/path_params_numeric_validations/tutorial001_an_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="11"
{!> ../../../docs_src/path_params_numeric_validations/tutorial001_an.py!}
```
=== "Python 3.10+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="8"
{!> ../../../docs_src/path_params_numeric_validations/tutorial001_py310.py!}
```
=== "Python 3.6+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="10"
{!> ../../../docs_src/path_params_numeric_validations/tutorial001.py!}
```
!!! note
A path parameter is always required as it has to be part of the path.
@@ -45,11 +93,14 @@ For example, to declare a `title` metadata value for the path parameter `item_id
## Order the parameters as you need
!!! tip
This is probably not as important or necessary if you use `Annotated`.
Let's say that you want to declare the query parameter `q` as a required `str`.
And you don't need to declare anything else for that parameter, so you don't really need to use `Query`.
But you still need to use `Path` for the `item_id` path parameter.
But you still need to use `Path` for the `item_id` path parameter. And you don't want to use `Annotated` for some reason.
Python will complain if you put a value with a "default" before a value that doesn't have a "default".
@@ -59,13 +110,44 @@ It doesn't matter for **FastAPI**. It will detect the parameters by their names,
So, you can declare your function as:
```Python hl_lines="7"
{!../../../docs_src/path_params_numeric_validations/tutorial002.py!}
```
=== "Python 3.6 non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="7"
{!> ../../../docs_src/path_params_numeric_validations/tutorial002.py!}
```
But have in mind that if you use `Annotated`, you won't have this problem, it won't matter as you're not using the function parameter default values for `Query()` or `Path()`.
=== "Python 3.9+"
```Python hl_lines="10"
{!> ../../../docs_src/path_params_numeric_validations/tutorial002_an_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="9"
{!> ../../../docs_src/path_params_numeric_validations/tutorial002_an.py!}
```
## Order the parameters as you need, tricks
If you want to declare the `q` query parameter without a `Query` nor any default value, and the path parameter `item_id` using `Path`, and have them in a different order, Python has a little special syntax for that.
!!! tip
This is probably not as important or necessary if you use `Annotated`.
Here's a **small trick** that can be handy, but you won't need it often.
If you want to:
* declare the `q` query parameter without a `Query` nor any default value
* declare the path parameter `item_id` using `Path`
* have them in a different order
* not use `Annotated`
...Python has a little special syntax for that.
Pass `*`, as the first parameter of the function.
@@ -75,15 +157,48 @@ Python won't do anything with that `*`, but it will know that all the following
{!../../../docs_src/path_params_numeric_validations/tutorial003.py!}
```
### Better with `Annotated`
Have in mind that if you use `Annotated`, as you are not using function parameter default values, you won't have this problem, and yo probably won't need to use `*`.
=== "Python 3.9+"
```Python hl_lines="10"
{!> ../../../docs_src/path_params_numeric_validations/tutorial003_an_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="9"
{!> ../../../docs_src/path_params_numeric_validations/tutorial003_an.py!}
```
## Number validations: greater than or equal
With `Query` and `Path` (and other's you'll see later) you can declare string constraints, but also number constraints.
With `Query` and `Path` (and others you'll see later) you can declare number constraints.
Here, with `ge=1`, `item_id` will need to be an integer number "`g`reater than or `e`qual" to `1`.
```Python hl_lines="8"
{!../../../docs_src/path_params_numeric_validations/tutorial004.py!}
```
=== "Python 3.9+"
```Python hl_lines="10"
{!> ../../../docs_src/path_params_numeric_validations/tutorial004_an_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="9"
{!> ../../../docs_src/path_params_numeric_validations/tutorial004_an.py!}
```
=== "Python 3.6+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="8"
{!> ../../../docs_src/path_params_numeric_validations/tutorial004.py!}
```
## Number validations: greater than and less than or equal
@@ -92,9 +207,26 @@ The same applies for:
* `gt`: `g`reater `t`han
* `le`: `l`ess than or `e`qual
```Python hl_lines="9"
{!../../../docs_src/path_params_numeric_validations/tutorial005.py!}
```
=== "Python 3.9+"
```Python hl_lines="10"
{!> ../../../docs_src/path_params_numeric_validations/tutorial005_an_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="9"
{!> ../../../docs_src/path_params_numeric_validations/tutorial005_an.py!}
```
=== "Python 3.6+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="9"
{!> ../../../docs_src/path_params_numeric_validations/tutorial005.py!}
```
## Number validations: floats, greater than and less than
@@ -106,9 +238,26 @@ So, `0.5` would be a valid value. But `0.0` or `0` would not.
And the same for <abbr title="less than"><code>lt</code></abbr>.
```Python hl_lines="11"
{!../../../docs_src/path_params_numeric_validations/tutorial006.py!}
```
=== "Python 3.9+"
```Python hl_lines="13"
{!> ../../../docs_src/path_params_numeric_validations/tutorial006_an_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="12"
{!> ../../../docs_src/path_params_numeric_validations/tutorial006_an.py!}
```
=== "Python 3.6+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="11"
{!> ../../../docs_src/path_params_numeric_validations/tutorial006.py!}
```
## Recap
@@ -122,9 +271,9 @@ And you can also declare numeric validations:
* `le`: `l`ess than or `e`qual
!!! info
`Query`, `Path`, and others you will see later are subclasses of a common `Param` class (that you don't need to use).
`Query`, `Path`, and other classes you will see later are subclasses of a common `Param` class.
And all of them share the same all these same parameters of additional validation and metadata you have seen.
All of them share the same parameters for additional validation and metadata you have seen.
!!! note "Technical Details"
When you import `Query`, `Path` and others from `fastapi`, they are actually functions.

View File

@@ -4,18 +4,18 @@
Let's take this application as example:
=== "Python 3.6 and above"
```Python hl_lines="9"
{!> ../../../docs_src/query_params_str_validations/tutorial001.py!}
```
=== "Python 3.10 and above"
=== "Python 3.10+"
```Python hl_lines="7"
{!> ../../../docs_src/query_params_str_validations/tutorial001_py310.py!}
```
=== "Python 3.6+"
```Python hl_lines="9"
{!> ../../../docs_src/query_params_str_validations/tutorial001.py!}
```
The query parameter `q` is of type `Union[str, None]` (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
@@ -27,39 +27,117 @@ The query parameter `q` is of type `Union[str, None]` (or `str | None` in Python
We are going to enforce that even though `q` is optional, whenever it is provided, **its length doesn't exceed 50 characters**.
### Import `Query`
### Import `Query` and `Annotated`
To achieve that, first import `Query` from `fastapi`:
To achieve that, first import:
=== "Python 3.6 and above"
* `Query` from `fastapi`
* `Annotated` from `typing` (or from `typing_extensions` in Python below 3.9)
```Python hl_lines="3"
{!> ../../../docs_src/query_params_str_validations/tutorial002.py!}
=== "Python 3.10+"
In Python 3.9 or above, `Annotated` is part of the standard library, so you can import it from `typing`.
```Python hl_lines="1 3"
{!> ../../../docs_src/query_params_str_validations/tutorial002_an_py310.py!}
```
=== "Python 3.10 and above"
=== "Python 3.6+"
```Python hl_lines="1"
{!> ../../../docs_src/query_params_str_validations/tutorial002_py310.py!}
In versions of Python below Python 3.9 you import `Annotation` from `typing_extensions`.
It will already be installed with FastAPI.
```Python hl_lines="3-4"
{!> ../../../docs_src/query_params_str_validations/tutorial002_an.py!}
```
## Use `Query` as the default value
## Use `Annotated` in the type for the `q` parameter
And now use it as the default value of your parameter, setting the parameter `max_length` to 50:
Remember I told you before that `Annotated` can be used to add metadata to your parameters in the [Python Types Intro](../python-types.md#type-hints-with-metadata-annotations){.internal-link target=_blank}?
=== "Python 3.6 and above"
Now it's the time to use it with FastAPI. 🚀
We had this type annotation:
=== "Python 3.10+"
```Python
q: str | None = None
```
=== "Python 3.6+"
```Python
q: Union[str, None] = None
```
What we will do is wrap that with `Annotated`, so it becomes:
=== "Python 3.10+"
```Python
q: Annotated[str | None] = None
```
=== "Python 3.6+"
```Python
q: Annotated[Union[str, None]] = None
```
Both of those versions mean the same thing, `q` is a parameter that can be a `str` or `None`, and by default, it is `None`.
Now let's jump to the fun stuff. 🎉
## Add `Query` to `Annotated` in the `q` parameter
Now that we have this `Annotated` where we can put more metadata, add `Query` to it, and set the parameter `max_length` to 50:
=== "Python 3.10+"
```Python hl_lines="9"
{!> ../../../docs_src/query_params_str_validations/tutorial002.py!}
{!> ../../../docs_src/query_params_str_validations/tutorial002_an_py310.py!}
```
=== "Python 3.10 and above"
=== "Python 3.6+"
```Python hl_lines="10"
{!> ../../../docs_src/query_params_str_validations/tutorial002_an.py!}
```
Notice that the default value is still `None`, so the parameter is still optional.
But now, having `Query(max_length=50)` inside of `Annotated`, we are telling FastAPI that we want it to extract this value from the query parameters (this would have been the default anyway 🤷) and that we want to have **additional validation** for this value (that's why we do this, to get the additional validation). 😎
FastAPI wll now:
* **Validate** the data making sure that the max length is 50 characters
* Show a **clear error** for the client when the data is not valid
* **Document** the parameter in the OpenAPI schema *path operation* (so it will show up in the **automatic docs UI**)
## Alternative (old) `Query` as the default value
Previous versions of FastAPI (before <abbr title="before 2023-03">0.95.0</abbr>) required you to use `Query` as the default value of your parameter, instead of putting it in `Annotated`, there's a high chance that you will see code using it around, so I'll explain it to you.
!!! tip
For new code and whenever possible, use `Annotated` as explained above. There are multiple advantages (explained below) and no disadvantages. 🍰
This is how you would use `Query()` as the default value of your function parameter, setting the parameter `max_length` to 50:
=== "Python 3.10+"
```Python hl_lines="7"
{!> ../../../docs_src/query_params_str_validations/tutorial002_py310.py!}
```
As we have to replace the default value `None` in the function with `Query()`, we can now set the default value with the parameter `Query(default=None)`, it serves the same purpose of defining that default value.
=== "Python 3.6+"
```Python hl_lines="9"
{!> ../../../docs_src/query_params_str_validations/tutorial002.py!}
```
As in this case (without using `Annotated`) we have to replace the default value `None` in the function with `Query()`, we now need to set the default value with the parameter `Query(default=None)`, it serves the same purpose of defining that default value (at least for FastAPI).
So:
@@ -67,7 +145,7 @@ So:
q: Union[str, None] = Query(default=None)
```
...makes the parameter optional, the same as:
...makes the parameter optional, with a default value of `None`, the same as:
```Python
q: Union[str, None] = None
@@ -79,7 +157,7 @@ And in Python 3.10 and above:
q: str | None = Query(default=None)
```
...makes the parameter optional, the same as:
...makes the parameter optional, with a default value of `None`, the same as:
```Python
q: str | None = None
@@ -112,38 +190,124 @@ q: Union[str, None] = Query(default=None, max_length=50)
This will validate the data, show a clear error when the data is not valid, and document the parameter in the OpenAPI schema *path operation*.
### `Query` as the default value or in `Annotated`
Have in mind that when using `Query` inside of `Annotated` you cannot use the `default` parameter for `Query`.
Instead use the actual default value of the function parameter. Otherwise, it would be inconsistent.
For example, this is not allowed:
```Python
q: Annotated[str Query(default="rick")] = "morty"
```
...because it's not clear if the default value should be `"rick"` or `"morty"`.
So, you would use (preferably):
```Python
q: Annotated[str, Query()] = "rick"
```
...or in older code bases you will find:
```Python
q: str = Query(default="rick")
```
### Advantages of `Annotated`
**Using `Annotated` is recommended** instead of the default value in function parameters, it is **better** for multiple reasons. 🤓
The **default** value of the **function parameter** is the **actual default** value, that's more intuitive with Python in general. 😌
You could **call** that same function in **other places** without FastAPI, and it would **work as expected**. If there's a **required** parameter (without a default value), your **editor** will let you know with an error, **Python** will also complain if you run it without passing the required parameter.
When you don't use `Annotated` and instead use the **(old) default value style**, if you call that function without FastAPI in **other place**, you have to **remember** to pass the arguments to the function for it to work correctly, otherwise the values will be different from what you expect (e.g. `QueryInfo` or something similar instead of `str`). And your editor won't complain, and Python won't complain running that function, only when the operations inside error out.
Because `Annotated` can have more than one metadata annotation, you could now even use the same function with other tools, like <a href="https://typer.tiangolo.com/" class="external-link" target="_blank">Typer</a>. 🚀
## Add more validations
You can also add a parameter `min_length`:
=== "Python 3.6 and above"
=== "Python 3.10+"
```Python hl_lines="10"
{!> ../../../docs_src/query_params_str_validations/tutorial003.py!}
{!> ../../../docs_src/query_params_str_validations/tutorial003_an_py310.py!}
```
=== "Python 3.10 and above"
=== "Python 3.9+"
```Python hl_lines="10"
{!> ../../../docs_src/query_params_str_validations/tutorial003_an_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="11"
{!> ../../../docs_src/query_params_str_validations/tutorial003_an.py!}
```
=== "Python 3.10+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="7"
{!> ../../../docs_src/query_params_str_validations/tutorial003_py310.py!}
```
=== "Python 3.6+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="10"
{!> ../../../docs_src/query_params_str_validations/tutorial003.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 3.6 and above"
=== "Python 3.10+"
```Python hl_lines="11"
{!> ../../../docs_src/query_params_str_validations/tutorial004.py!}
{!> ../../../docs_src/query_params_str_validations/tutorial004_an_py310.py!}
```
=== "Python 3.10 and above"
=== "Python 3.9+"
```Python hl_lines="11"
{!> ../../../docs_src/query_params_str_validations/tutorial004_an_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="12"
{!> ../../../docs_src/query_params_str_validations/tutorial004_an.py!}
```
=== "Python 3.10+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="9"
{!> ../../../docs_src/query_params_str_validations/tutorial004_py310.py!}
```
=== "Python 3.6+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="11"
{!> ../../../docs_src/query_params_str_validations/tutorial004.py!}
```
This specific regular expression checks that the received parameter value:
* `^`: starts with the following characters, doesn't have characters before.
@@ -156,16 +320,33 @@ But whenever you need them and go and learn them, know that you can already use
## Default values
The same way that you can pass `None` as the value for the `default` parameter, you can pass other values.
You can, of course, use default values other than `None`.
Let's say that you want to declare the `q` query parameter to have a `min_length` of `3`, and to have a default value of `"fixedquery"`:
```Python hl_lines="7"
{!../../../docs_src/query_params_str_validations/tutorial005.py!}
```
=== "Python 3.9+"
```Python hl_lines="9"
{!> ../../../docs_src/query_params_str_validations/tutorial005_an_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="8"
{!> ../../../docs_src/query_params_str_validations/tutorial005_an.py!}
```
=== "Python 3.6+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="7"
{!> ../../../docs_src/query_params_str_validations/tutorial005.py!}
```
!!! note
Having a default value also makes the parameter optional.
Having a default value of any type, including `None`, makes the parameter optional (not required).
## Make it required
@@ -183,23 +364,70 @@ q: Union[str, None] = None
But we are now declaring it with `Query`, for example like:
```Python
q: Union[str, None] = Query(default=None, min_length=3)
```
=== "Annotated"
```Python
q: Annotated[Union[str, None], Query(min_length=3)] = None
```
=== "non-Annotated"
```Python
q: Union[str, None] = Query(default=None, min_length=3)
```
So, when you need to declare a value as required while using `Query`, you can simply not declare a default value:
```Python hl_lines="7"
{!../../../docs_src/query_params_str_validations/tutorial006.py!}
```
=== "Python 3.9+"
```Python hl_lines="9"
{!> ../../../docs_src/query_params_str_validations/tutorial006_an_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="8"
{!> ../../../docs_src/query_params_str_validations/tutorial006_an.py!}
```
=== "Python 3.6+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="7"
{!> ../../../docs_src/query_params_str_validations/tutorial006.py!}
```
!!! tip
Notice that, even though in this case the `Query()` is used as the function parameter default value, we don't pass the `default=None` to `Query()`.
Still, probably better to use the `Annotated` version. 😉
### Required with Ellipsis (`...`)
There's an alternative way to explicitly declare that a value is required. You can set the `default` parameter to the literal value `...`:
There's an alternative way to explicitly declare that a value is required. You can set the default to the literal value `...`:
```Python hl_lines="7"
{!../../../docs_src/query_params_str_validations/tutorial006b.py!}
```
=== "Python 3.9+"
```Python hl_lines="9"
{!> ../../../docs_src/query_params_str_validations/tutorial006b_an_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="8"
{!> ../../../docs_src/query_params_str_validations/tutorial006b_an.py!}
```
=== "Python 3.6+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="7"
{!> ../../../docs_src/query_params_str_validations/tutorial006b.py!}
```
!!! info
If you hadn't seen that `...` before: it is a special single value, it is <a href="https://docs.python.org/3/library/constants.html#Ellipsis" class="external-link" target="_blank">part of Python and is called "Ellipsis"</a>.
@@ -212,20 +440,44 @@ This will let **FastAPI** know that this parameter is required.
You can declare that a parameter can accept `None`, but that it's still required. This would force clients to send a value, even if the value is `None`.
To do that, you can declare that `None` is a valid type but still use `default=...`:
To do that, you can declare that `None` is a valid type but still use `...` as the default:
=== "Python 3.6 and above"
=== "Python 3.10+"
```Python hl_lines="8"
{!> ../../../docs_src/query_params_str_validations/tutorial006c.py!}
```Python hl_lines="9"
{!> ../../../docs_src/query_params_str_validations/tutorial006c_an_py310.py!}
```
=== "Python 3.10 and above"
=== "Python 3.9+"
```Python hl_lines="9"
{!> ../../../docs_src/query_params_str_validations/tutorial006c_an_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="10"
{!> ../../../docs_src/query_params_str_validations/tutorial006c_an.py!}
```
=== "Python 3.10+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="7"
{!> ../../../docs_src/query_params_str_validations/tutorial006c_py310.py!}
```
=== "Python 3.6+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="9"
{!> ../../../docs_src/query_params_str_validations/tutorial006c.py!}
```
!!! tip
Pydantic, which is what powers all the data validation and serialization in FastAPI, has a special behavior when you use `Optional` or `Union[Something, None]` without a default value, you can read more about it in the Pydantic docs about <a href="https://pydantic-docs.helpmanual.io/usage/models/#required-optional-fields" class="external-link" target="_blank">Required Optional fields</a>.
@@ -233,12 +485,29 @@ To do that, you can declare that `None` is a valid type but still use `default=.
If you feel uncomfortable using `...`, you can also import and use `Required` from Pydantic:
```Python hl_lines="2 8"
{!../../../docs_src/query_params_str_validations/tutorial006d.py!}
```
=== "Python 3.9+"
```Python hl_lines="4 10"
{!> ../../../docs_src/query_params_str_validations/tutorial006d_an_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="2 9"
{!> ../../../docs_src/query_params_str_validations/tutorial006d_an.py!}
```
=== "Python 3.6+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="2 8"
{!> ../../../docs_src/query_params_str_validations/tutorial006d.py!}
```
!!! tip
Remember that in most of the cases, when something is required, you can simply omit the `default` parameter, so you normally don't have to use `...` nor `Required`.
Remember that in most of the cases, when something is required, you can simply omit the default, so you normally don't have to use `...` nor `Required`.
## Query parameter list / multiple values
@@ -246,22 +515,49 @@ 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 3.6 and above"
=== "Python 3.10+"
```Python hl_lines="9"
{!> ../../../docs_src/query_params_str_validations/tutorial011.py!}
{!> ../../../docs_src/query_params_str_validations/tutorial011_an_py310.py!}
```
=== "Python 3.9 and above"
=== "Python 3.9+"
```Python hl_lines="9"
{!> ../../../docs_src/query_params_str_validations/tutorial011_an_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="10"
{!> ../../../docs_src/query_params_str_validations/tutorial011_an.py!}
```
=== "Python 3.10+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="7"
{!> ../../../docs_src/query_params_str_validations/tutorial011_py310.py!}
```
=== "Python 3.9+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="9"
{!> ../../../docs_src/query_params_str_validations/tutorial011_py39.py!}
```
=== "Python 3.10 and above"
=== "Python 3.6+ non-Annotated"
```Python hl_lines="7"
{!> ../../../docs_src/query_params_str_validations/tutorial011_py310.py!}
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="9"
{!> ../../../docs_src/query_params_str_validations/tutorial011.py!}
```
Then, with a URL like:
@@ -294,18 +590,36 @@ 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 3.6 and above"
=== "Python 3.9+"
```Python hl_lines="9"
{!> ../../../docs_src/query_params_str_validations/tutorial012.py!}
{!> ../../../docs_src/query_params_str_validations/tutorial012_an_py39.py!}
```
=== "Python 3.9 and above"
=== "Python 3.6+"
```Python hl_lines="10"
{!> ../../../docs_src/query_params_str_validations/tutorial012_an.py!}
```
=== "Python 3.9+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="7"
{!> ../../../docs_src/query_params_str_validations/tutorial012_py39.py!}
```
=== "Python 3.6+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="9"
{!> ../../../docs_src/query_params_str_validations/tutorial012.py!}
```
If you go to:
```
@@ -327,9 +641,26 @@ the default of `q` will be: `["foo", "bar"]` and your response will be:
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!}
```
=== "Python 3.9+"
```Python hl_lines="9"
{!> ../../../docs_src/query_params_str_validations/tutorial013_an_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="8"
{!> ../../../docs_src/query_params_str_validations/tutorial013_an.py!}
```
=== "Python 3.6+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="7"
{!> ../../../docs_src/query_params_str_validations/tutorial013.py!}
```
!!! note
Have in mind that in this case, FastAPI won't check the contents of the list.
@@ -349,32 +680,80 @@ That information will be included in the generated OpenAPI and used by the docum
You can add a `title`:
=== "Python 3.6 and above"
=== "Python 3.10+"
```Python hl_lines="10"
{!> ../../../docs_src/query_params_str_validations/tutorial007.py!}
{!> ../../../docs_src/query_params_str_validations/tutorial007_an_py310.py!}
```
=== "Python 3.10 and above"
=== "Python 3.9+"
```Python hl_lines="10"
{!> ../../../docs_src/query_params_str_validations/tutorial007_an_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="11"
{!> ../../../docs_src/query_params_str_validations/tutorial007_an.py!}
```
=== "Python 3.10+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="8"
{!> ../../../docs_src/query_params_str_validations/tutorial007_py310.py!}
```
And a `description`:
=== "Python 3.6+ non-Annotated"
=== "Python 3.6 and above"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="13"
{!> ../../../docs_src/query_params_str_validations/tutorial008.py!}
```Python hl_lines="10"
{!> ../../../docs_src/query_params_str_validations/tutorial007.py!}
```
=== "Python 3.10 and above"
And a `description`:
=== "Python 3.10+"
```Python hl_lines="14"
{!> ../../../docs_src/query_params_str_validations/tutorial008_an_py310.py!}
```
=== "Python 3.9+"
```Python hl_lines="14"
{!> ../../../docs_src/query_params_str_validations/tutorial008_an_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="15"
{!> ../../../docs_src/query_params_str_validations/tutorial008_an.py!}
```
=== "Python 3.10+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="12"
{!> ../../../docs_src/query_params_str_validations/tutorial008_py310.py!}
```
=== "Python 3.6+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="13"
{!> ../../../docs_src/query_params_str_validations/tutorial008.py!}
```
## Alias parameters
Imagine that you want the parameter to be `item-query`.
@@ -393,18 +772,42 @@ 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 3.6 and above"
=== "Python 3.10+"
```Python hl_lines="9"
{!> ../../../docs_src/query_params_str_validations/tutorial009.py!}
{!> ../../../docs_src/query_params_str_validations/tutorial009_an_py310.py!}
```
=== "Python 3.10 and above"
=== "Python 3.9+"
```Python hl_lines="9"
{!> ../../../docs_src/query_params_str_validations/tutorial009_an_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="10"
{!> ../../../docs_src/query_params_str_validations/tutorial009_an.py!}
```
=== "Python 3.10+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="7"
{!> ../../../docs_src/query_params_str_validations/tutorial009_py310.py!}
```
=== "Python 3.6+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="9"
{!> ../../../docs_src/query_params_str_validations/tutorial009.py!}
```
## Deprecating parameters
Now let's say you don't like this parameter anymore.
@@ -413,18 +816,42 @@ 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 3.6 and above"
=== "Python 3.10+"
```Python hl_lines="18"
{!> ../../../docs_src/query_params_str_validations/tutorial010.py!}
```Python hl_lines="19"
{!> ../../../docs_src/query_params_str_validations/tutorial010_an_py310.py!}
```
=== "Python 3.10 and above"
=== "Python 3.9+"
```Python hl_lines="19"
{!> ../../../docs_src/query_params_str_validations/tutorial010_an_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="20"
{!> ../../../docs_src/query_params_str_validations/tutorial010_an.py!}
```
=== "Python 3.10+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="17"
{!> ../../../docs_src/query_params_str_validations/tutorial010_py310.py!}
```
=== "Python 3.6+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="18"
{!> ../../../docs_src/query_params_str_validations/tutorial010.py!}
```
The docs will show it like this:
<img src="/img/tutorial/query-params-str-validations/image01.png">
@@ -433,18 +860,42 @@ The docs will show it like this:
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 3.10+"
```Python hl_lines="10"
{!> ../../../docs_src/query_params_str_validations/tutorial014.py!}
{!> ../../../docs_src/query_params_str_validations/tutorial014_an_py310.py!}
```
=== "Python 3.10 and above"
=== "Python 3.9+"
```Python hl_lines="10"
{!> ../../../docs_src/query_params_str_validations/tutorial014_an_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="11"
{!> ../../../docs_src/query_params_str_validations/tutorial014_an.py!}
```
=== "Python 3.10+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="8"
{!> ../../../docs_src/query_params_str_validations/tutorial014_py310.py!}
```
=== "Python 3.6+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="10"
{!> ../../../docs_src/query_params_str_validations/tutorial014.py!}
```
## Recap
You can declare additional validations and metadata for your parameters.

View File

@@ -63,18 +63,18 @@ The parameter values in your function will be:
The same way, you can declare optional query parameters, by setting their default to `None`:
=== "Python 3.6 and above"
```Python hl_lines="9"
{!> ../../../docs_src/query_params/tutorial002.py!}
```
=== "Python 3.10 and above"
=== "Python 3.10+"
```Python hl_lines="7"
{!> ../../../docs_src/query_params/tutorial002_py310.py!}
```
=== "Python 3.6+"
```Python hl_lines="9"
{!> ../../../docs_src/query_params/tutorial002.py!}
```
In this case, the function parameter `q` will be optional, and will be `None` by default.
!!! check
@@ -84,18 +84,18 @@ In this case, the function parameter `q` will be optional, and will be `None` by
You can also declare `bool` types, and they will be converted:
=== "Python 3.6 and above"
```Python hl_lines="9"
{!> ../../../docs_src/query_params/tutorial003.py!}
```
=== "Python 3.10 and above"
=== "Python 3.10+"
```Python hl_lines="7"
{!> ../../../docs_src/query_params/tutorial003_py310.py!}
```
=== "Python 3.6+"
```Python hl_lines="9"
{!> ../../../docs_src/query_params/tutorial003.py!}
```
In this case, if you go to:
```
@@ -137,18 +137,18 @@ And you don't have to declare them in any specific order.
They will be detected by name:
=== "Python 3.6 and above"
```Python hl_lines="8 10"
{!> ../../../docs_src/query_params/tutorial004.py!}
```
=== "Python 3.10 and above"
=== "Python 3.10+"
```Python hl_lines="6 8"
{!> ../../../docs_src/query_params/tutorial004_py310.py!}
```
=== "Python 3.6+"
```Python hl_lines="8 10"
{!> ../../../docs_src/query_params/tutorial004.py!}
```
## Required query parameters
When you declare a default value for non-path parameters (for now, we have only seen query parameters), then it is not required.
@@ -203,18 +203,18 @@ 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 3.6 and above"
```Python hl_lines="10"
{!> ../../../docs_src/query_params/tutorial006.py!}
```
=== "Python 3.10 and above"
=== "Python 3.10+"
```Python hl_lines="8"
{!> ../../../docs_src/query_params/tutorial006_py310.py!}
```
=== "Python 3.6+"
```Python hl_lines="10"
{!> ../../../docs_src/query_params/tutorial006.py!}
```
In this case, there are 3 query parameters:
* `needy`, a required `str`.

View File

@@ -13,17 +13,51 @@ You can define files to be uploaded by the client using `File`.
Import `File` and `UploadFile` from `fastapi`:
```Python hl_lines="1"
{!../../../docs_src/request_files/tutorial001.py!}
```
=== "Python 3.9+"
```Python hl_lines="3"
{!> ../../../docs_src/request_files/tutorial001_an_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="1"
{!> ../../../docs_src/request_files/tutorial001_an.py!}
```
=== "Python 3.6+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="1"
{!> ../../../docs_src/request_files/tutorial001.py!}
```
## Define `File` Parameters
Create file parameters the same way you would for `Body` or `Form`:
```Python hl_lines="7"
{!../../../docs_src/request_files/tutorial001.py!}
```
=== "Python 3.9+"
```Python hl_lines="9"
{!> ../../../docs_src/request_files/tutorial001_an_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="8"
{!> ../../../docs_src/request_files/tutorial001_an.py!}
```
=== "Python 3.6+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="7"
{!> ../../../docs_src/request_files/tutorial001.py!}
```
!!! info
`File` is a class that inherits directly from `Form`.
@@ -45,9 +79,26 @@ But there are several cases in which you might benefit from using `UploadFile`.
Define a file parameter with a type of `UploadFile`:
```Python hl_lines="12"
{!../../../docs_src/request_files/tutorial001.py!}
```
=== "Python 3.9+"
```Python hl_lines="14"
{!> ../../../docs_src/request_files/tutorial001_an_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="13"
{!> ../../../docs_src/request_files/tutorial001_an.py!}
```
=== "Python 3.6+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="12"
{!> ../../../docs_src/request_files/tutorial001.py!}
```
Using `UploadFile` has several advantages over `bytes`:
@@ -118,25 +169,66 @@ The way HTML forms (`<form></form>`) sends the data to the server normally uses
You can make a file optional by using standard type annotations and setting a default value of `None`:
=== "Python 3.6 and above"
=== "Python 3.10+"
```Python hl_lines="9 17"
{!> ../../../docs_src/request_files/tutorial001_02_an_py310.py!}
```
=== "Python 3.9+"
```Python hl_lines="9 17"
{!> ../../../docs_src/request_files/tutorial001_02_an_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="10 18"
{!> ../../../docs_src/request_files/tutorial001_02_an.py!}
```
=== "Python 3.10+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="7 15"
{!> ../../../docs_src/request_files/tutorial001_02_py310.py!}
```
=== "Python 3.6+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```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!}
```
=== "Python 3.9+"
```Python hl_lines="9 15"
{!> ../../../docs_src/request_files/tutorial001_03_an_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="8 14"
{!> ../../../docs_src/request_files/tutorial001_03_an.py!}
```
=== "Python 3.6+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="7 13"
{!> ../../../docs_src/request_files/tutorial001_03.py!}
```
## Multiple File Uploads
@@ -146,18 +238,36 @@ They would be associated to the same "form field" sent using "form data".
To use that, declare a list of `bytes` or `UploadFile`:
=== "Python 3.6 and above"
=== "Python 3.9+"
```Python hl_lines="10 15"
{!> ../../../docs_src/request_files/tutorial002.py!}
{!> ../../../docs_src/request_files/tutorial002_an_py39.py!}
```
=== "Python 3.9 and above"
=== "Python 3.6+"
```Python hl_lines="11 16"
{!> ../../../docs_src/request_files/tutorial002_an.py!}
```
=== "Python 3.9+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="8 13"
{!> ../../../docs_src/request_files/tutorial002_py39.py!}
```
=== "Python 3.6+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="10 15"
{!> ../../../docs_src/request_files/tutorial002.py!}
```
You will receive, as declared, a `list` of `bytes` or `UploadFile`s.
!!! note "Technical Details"
@@ -169,18 +279,36 @@ You will receive, as declared, a `list` of `bytes` or `UploadFile`s.
And the same way as before, you can use `File()` to set additional parameters, even for `UploadFile`:
=== "Python 3.6 and above"
=== "Python 3.9+"
```Python hl_lines="18"
{!> ../../../docs_src/request_files/tutorial003.py!}
```Python hl_lines="11 18-20"
{!> ../../../docs_src/request_files/tutorial003_an_py39.py!}
```
=== "Python 3.9 and above"
=== "Python 3.6+"
```Python hl_lines="16"
```Python hl_lines="12 19-21"
{!> ../../../docs_src/request_files/tutorial003_an.py!}
```
=== "Python 3.9+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="9 16"
{!> ../../../docs_src/request_files/tutorial003_py39.py!}
```
=== "Python 3.6+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="11 18"
{!> ../../../docs_src/request_files/tutorial003.py!}
```
## Recap
Use `File`, `bytes`, and `UploadFile` to declare files to be uploaded in the request, sent as form data.

View File

@@ -9,17 +9,51 @@ You can define files and form fields at the same time using `File` and `Form`.
## Import `File` and `Form`
```Python hl_lines="1"
{!../../../docs_src/request_forms_and_files/tutorial001.py!}
```
=== "Python 3.9+"
```Python hl_lines="3"
{!> ../../../docs_src/request_forms_and_files/tutorial001_an_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="1"
{!> ../../../docs_src/request_forms_and_files/tutorial001_an.py!}
```
=== "Python 3.6+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="1"
{!> ../../../docs_src/request_forms_and_files/tutorial001.py!}
```
## Define `File` and `Form` parameters
Create file and form parameters the same way you would for `Body` or `Query`:
```Python hl_lines="8"
{!../../../docs_src/request_forms_and_files/tutorial001.py!}
```
=== "Python 3.9+"
```Python hl_lines="10-12"
{!> ../../../docs_src/request_forms_and_files/tutorial001_an_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="9-11"
{!> ../../../docs_src/request_forms_and_files/tutorial001_an.py!}
```
=== "Python 3.6+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="8"
{!> ../../../docs_src/request_forms_and_files/tutorial001.py!}
```
The files and form fields will be uploaded as form data and you will receive the files and form fields.

View File

@@ -11,23 +11,57 @@ When you need to receive form fields instead of JSON, you can use `Form`.
Import `Form` from `fastapi`:
```Python hl_lines="1"
{!../../../docs_src/request_forms/tutorial001.py!}
```
=== "Python 3.9+"
```Python hl_lines="3"
{!> ../../../docs_src/request_forms/tutorial001_an_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="1"
{!> ../../../docs_src/request_forms/tutorial001_an.py!}
```
=== "Python 3.6+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="1"
{!> ../../../docs_src/request_forms/tutorial001.py!}
```
## Define `Form` parameters
Create form parameters the same way you would for `Body` or `Query`:
```Python hl_lines="7"
{!../../../docs_src/request_forms/tutorial001.py!}
```
=== "Python 3.9+"
```Python hl_lines="9"
{!> ../../../docs_src/request_forms/tutorial001_an_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="8"
{!> ../../../docs_src/request_forms/tutorial001_an.py!}
```
=== "Python 3.6+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="7"
{!> ../../../docs_src/request_forms/tutorial001.py!}
```
For example, in one of the ways the OAuth2 specification can be used (called "password flow") it is required to send a `username` and `password` as form fields.
The <abbr title="specification">spec</abbr> requires the fields to be exactly named `username` and `password`, and to be sent as form fields, not JSON.
With `Form` you can declare the same metadata and validation as with `Body` (and `Query`, `Path`, `Cookie`).
With `Form` you can declare the same configurations as with `Body` (and `Query`, `Path`, `Cookie`), including validation, examples, an alias (e.g. `user-name` instead of `username`), etc.
!!! info
`Form` is a class that inherits directly from `Body`.

View File

@@ -1,6 +1,51 @@
# Response Model
# Response Model - Return Type
You can declare the model used for the response with the parameter `response_model` in any of the *path operations*:
You can declare the type used for the response by annotating the *path operation function* **return type**.
You can use **type annotations** the same way you would for input data in function **parameters**, you can use Pydantic models, lists, dictionaries, scalar values like integers, booleans, etc.
=== "Python 3.10+"
```Python hl_lines="16 21"
{!> ../../../docs_src/response_model/tutorial001_01_py310.py!}
```
=== "Python 3.9+"
```Python hl_lines="18 23"
{!> ../../../docs_src/response_model/tutorial001_01_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="18 23"
{!> ../../../docs_src/response_model/tutorial001_01.py!}
```
FastAPI will use this return type to:
* **Validate** the returned data.
* If the data is invalid (e.g. you are missing a field), it means that *your* app code is broken, not returning what it should, and it will return a server error instead of returning incorrect data. This way you and your clients can be certain that they will receive the data and the data shape expected.
* Add a **JSON Schema** for the response, in the OpenAPI *path operation*.
* This will be used by the **automatic docs**.
* It will also be used by automatic client code generation tools.
But most importantly:
* It will **limit and filter** the output data to what is defined in the return type.
* This is particularly important for **security**, we'll see more of that below.
## `response_model` Parameter
There are some cases where you need or want to return some data that is not exactly what the type declares.
For example, you could want to **return a dictionary** or a database object, but **declare it as a Pydantic model**. This way the Pydantic model would do all the data documentation, validation, etc. for the object that you returned (e.g. a dictionary or database object).
If you added the return type annotation, tools and editors would complain with a (correct) error telling you that your function is returning a type (e.g. a dict) that is different from what you declared (e.g. a Pydantic model).
In those cases, you can use the *path operation decorator* parameter `response_model` instead of the return type.
You can use the `response_model` parameter in any of the *path operations*:
* `@app.get()`
* `@app.post()`
@@ -8,59 +53,60 @@ You can declare the model used for the response with the parameter `response_mod
* `@app.delete()`
* etc.
=== "Python 3.6 and above"
=== "Python 3.10+"
```Python hl_lines="17"
{!> ../../../docs_src/response_model/tutorial001.py!}
```Python hl_lines="17 22 24-27"
{!> ../../../docs_src/response_model/tutorial001_py310.py!}
```
=== "Python 3.9 and above"
=== "Python 3.9+"
```Python hl_lines="17"
```Python hl_lines="17 22 24-27"
{!> ../../../docs_src/response_model/tutorial001_py39.py!}
```
=== "Python 3.10 and above"
=== "Python 3.6+"
```Python hl_lines="15"
{!> ../../../docs_src/response_model/tutorial001_py310.py!}
```Python hl_lines="17 22 24-27"
{!> ../../../docs_src/response_model/tutorial001.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.
It receives the same type you would declare for a Pydantic model attribute, so, it can be a Pydantic model, but it can also be, e.g. a `list` of Pydantic models, like `List[Item]`.
`response_model` receives the same type you would declare for a Pydantic model field, so, it can be a Pydantic model, but it can also be, e.g. a `list` of Pydantic models, like `List[Item]`.
FastAPI will use this `response_model` to:
FastAPI will use this `response_model` to do all the data documentation, validation, etc. and also to **convert and filter the output data** to its type declaration.
* Convert the output data to its type declaration.
* Validate the data.
* Add a JSON Schema for the response, in the OpenAPI *path operation*.
* Will be used by the automatic documentation systems.
!!! tip
If you have strict type checks in your editor, mypy, etc, you can declare the function return type as `Any`.
But most importantly:
That way you tell the editor that you are intentionally returning anything. But FastAPI will still do the data documentation, validation, filtering, etc. with the `response_model`.
* Will limit the output data to that of the model. We'll see how that's important below.
### `response_model` Priority
!!! note "Technical Details"
The response model is declared in this parameter instead of as a function return type annotation, because the path function may not actually return that response model but rather return a `dict`, database object or some other model, and then use the `response_model` to perform the field limiting and serialization.
If you declare both a return type and a `response_model`, the `response_model` will take priority and be used by FastAPI.
This way you can add correct type annotations to your functions even when you are returning a type different than the response model, to be used by the editor and tools like mypy. And still you can have FastAPI do the data validation, documentation, etc. using the `response_model`.
You can also use `response_model=None` to disable creating a response model for that *path operation*, you might need to do it if you are adding type annotations for things that are not valid Pydantic fields, you will see an example of that in one of the sections below.
## Return the same input data
Here we are declaring a `UserIn` model, it will contain a plaintext password:
=== "Python 3.6 and above"
```Python hl_lines="9 11"
{!> ../../../docs_src/response_model/tutorial002.py!}
```
=== "Python 3.10 and above"
=== "Python 3.10+"
```Python hl_lines="7 9"
{!> ../../../docs_src/response_model/tutorial002_py310.py!}
```
=== "Python 3.6+"
```Python hl_lines="9 11"
{!> ../../../docs_src/response_model/tutorial002.py!}
```
!!! info
To use `EmailStr`, first install <a href="https://github.com/JoshData/python-email-validator" class="external-link" target="_blank">`email_validator`</a>.
@@ -69,72 +115,126 @@ Here we are declaring a `UserIn` model, it will contain a plaintext password:
And we are using this model to declare our input and the same model to declare our output:
=== "Python 3.6 and above"
=== "Python 3.10+"
```Python hl_lines="17-18"
{!> ../../../docs_src/response_model/tutorial002.py!}
```Python hl_lines="16"
{!> ../../../docs_src/response_model/tutorial002_py310.py!}
```
=== "Python 3.10 and above"
=== "Python 3.6+"
```Python hl_lines="15-16"
{!> ../../../docs_src/response_model/tutorial002_py310.py!}
```Python hl_lines="18"
{!> ../../../docs_src/response_model/tutorial002.py!}
```
Now, whenever a browser is creating a user with a password, the API will return the same password in the response.
In this case, it might not be a problem, because the user themself is sending the password.
In this case, it might not be a problem, because it's the same user sending the password.
But if we use the same model for another *path operation*, we could be sending our user's passwords to every client.
!!! danger
Never store the plain password of a user or send it in a response.
Never store the plain password of a user or send it in a response like this, unless you know all the caveats and you know what you are doing.
## Add an output model
We can instead create an input model with the plaintext password and an output model without it:
=== "Python 3.6 and above"
=== "Python 3.10+"
```Python hl_lines="9 11 16"
{!> ../../../docs_src/response_model/tutorial003_py310.py!}
```
=== "Python 3.6+"
```Python hl_lines="9 11 16"
{!> ../../../docs_src/response_model/tutorial003.py!}
```
=== "Python 3.10 and above"
Here, even though our *path operation function* is returning the same input user that contains the password:
```Python hl_lines="7 9 14"
=== "Python 3.10+"
```Python hl_lines="24"
{!> ../../../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 3.6 and above"
=== "Python 3.6+"
```Python hl_lines="24"
{!> ../../../docs_src/response_model/tutorial003.py!}
```
=== "Python 3.10 and above"
...we declared the `response_model` to be our model `UserOut`, that doesn't include the password:
=== "Python 3.10+"
```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 3.6 and above"
=== "Python 3.6+"
```Python hl_lines="22"
{!> ../../../docs_src/response_model/tutorial003.py!}
```
=== "Python 3.10 and above"
So, **FastAPI** will take care of filtering out all the data that is not declared in the output model (using Pydantic).
```Python hl_lines="20"
{!> ../../../docs_src/response_model/tutorial003_py310.py!}
### `response_model` or Return Type
In this case, because the two models are different, if we annotated the function return type as `UserOut`, the editor and tools would complain that we are returning an invalid type, as those are different classes.
That's why in this example we have to declare it in the `response_model` parameter.
...but continue reading below to see how to overcome that.
## Return Type and Data Filtering
Let's continue from the previous example. We wanted to **annotate the function with one type** but return something that includes **more data**.
We want FastAPI to keep **filtering** the data using the response model.
In the previous example, because the classes were different, we had to use the `response_model` parameter. But that also means that we don't get the support from the editor and tools checking the function return type.
But in most of the cases where we need to do something like this, we want the model just to **filter/remove** some of the data as in this example.
And in those cases, we can use classes and inheritance to take advantage of function **type annotations** to get better support in the editor and tools, and still get the FastAPI **data filtering**.
=== "Python 3.10+"
```Python hl_lines="7-10 13-14 18"
{!> ../../../docs_src/response_model/tutorial003_01_py310.py!}
```
So, **FastAPI** will take care of filtering out all the data that is not declared in the output model (using Pydantic).
=== "Python 3.6+"
```Python hl_lines="9-13 15-16 20"
{!> ../../../docs_src/response_model/tutorial003_01.py!}
```
With this, we get tooling support, from editors and mypy as this code is correct in terms of types, but we also get the data filtering from FastAPI.
How does this work? Let's check that out. 🤓
### Type Annotations and Tooling
First let's see how editors, mypy and other tools would see this.
`BaseUser` has the base fields. Then `UserIn` inherits from `BaseUser` and adds the `password` field, so, it will include all the fields from both models.
We annotate the function return type as `BaseUser`, but we are actually returning a `UserIn` instance.
The editor, mypy, and other tools won't complain about this because, in typing terms, `UserIn` is a subclass of `BaseUser`, which means it's a *valid* type when what is expected is anything that is a `BaseUser`.
### FastAPI Data Filtering
Now, for FastAPI, it will see the return type and make sure that what you return includes **only** the fields that are declared in the type.
FastAPI does several things internally with Pydantic to make sure that those same rules of class inheritance are not used for the returned data filtering, otherwise you could end up returning much more data than what you expected.
This way, you can get the best of both worlds: type annotations with **tooling support** and **data filtering**.
## See it in the docs
@@ -146,29 +246,97 @@ And both models will be used for the interactive API documentation:
<img src="/img/tutorial/response-model/image02.png">
## Other Return Type Annotations
There might be cases where you return something that is not a valid Pydantic field and you annotate it in the function, only to get the support provided by tooling (the editor, mypy, etc).
### Return a Response Directly
The most common case would be [returning a Response directly as explained later in the advanced docs](../advanced/response-directly.md){.internal-link target=_blank}.
```Python hl_lines="8 10-11"
{!> ../../../docs_src/response_model/tutorial003_02.py!}
```
This simple case is handled automatically by FastAPI because the return type annotation is the class (or a subclass) of `Response`.
And tools will also be happy because both `RedirectResponse` and `JSONResponse` are subclasses of `Response`, so the type annotation is correct.
### Annotate a Response Subclass
You can also use a subclass of `Response` in the type annotation:
```Python hl_lines="8-9"
{!> ../../../docs_src/response_model/tutorial003_03.py!}
```
This will also work because `RedirectResponse` is a subclass of `Response`, and FastAPI will automatically handle this simple case.
### Invalid Return Type Annotations
But when you return some other arbitrary object that is not a valid Pydantic type (e.g. a database object) and you annotate it like that in the function, FastAPI will try to create a Pydantic response model from that type annotation, and will fail.
The same would happen if you had something like a <abbr title='A union between multiple types means "any of these types".'>union</abbr> between different types where one or more of them are not valid Pydantic types, for example this would fail 💥:
=== "Python 3.10+"
```Python hl_lines="8"
{!> ../../../docs_src/response_model/tutorial003_04_py310.py!}
```
=== "Python 3.6+"
```Python hl_lines="10"
{!> ../../../docs_src/response_model/tutorial003_04.py!}
```
...this fails because the type annotation is not a Pydantic type and is not just a single `Response` class or subclass, it's a union (any of the two) between a `Response` and a `dict`.
### Disable Response Model
Continuing from the example above, you might not want to have the default data validation, documentation, filtering, etc. that is performed by FastAPI.
But you might want to still keep the return type annotation in the function to get the support from tools like editors and type checkers (e.g. mypy).
In this case, you can disable the response model generation by setting `response_model=None`:
=== "Python 3.10+"
```Python hl_lines="7"
{!> ../../../docs_src/response_model/tutorial003_05_py310.py!}
```
=== "Python 3.6+"
```Python hl_lines="9"
{!> ../../../docs_src/response_model/tutorial003_05.py!}
```
This will make FastAPI skip the response model generation and that way you can have any return type annotations you need without it affecting your FastAPI application. 🤓
## Response Model encoding parameters
Your response model could have default values, like:
=== "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 3.10+"
```Python hl_lines="9 11-12"
{!> ../../../docs_src/response_model/tutorial004_py310.py!}
```
* `description: Union[str, None] = None` has a default of `None`.
=== "Python 3.9+"
```Python hl_lines="11 13-14"
{!> ../../../docs_src/response_model/tutorial004_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="11 13-14"
{!> ../../../docs_src/response_model/tutorial004.py!}
```
* `description: Union[str, None] = None` (or `str | None = None` in Python 3.10) has a default of `None`.
* `tax: float = 10.5` has a default of `10.5`.
* `tags: List[str] = []` as a default of an empty list: `[]`.
@@ -180,22 +348,22 @@ 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 3.6 and above"
=== "Python 3.10+"
```Python hl_lines="24"
{!> ../../../docs_src/response_model/tutorial004.py!}
```Python hl_lines="22"
{!> ../../../docs_src/response_model/tutorial004_py310.py!}
```
=== "Python 3.9 and above"
=== "Python 3.9+"
```Python hl_lines="24"
{!> ../../../docs_src/response_model/tutorial004_py39.py!}
```
=== "Python 3.10 and above"
=== "Python 3.6+"
```Python hl_lines="22"
{!> ../../../docs_src/response_model/tutorial004_py310.py!}
```Python hl_lines="24"
{!> ../../../docs_src/response_model/tutorial004.py!}
```
and those default values won't be included in the response, only the values actually set.
@@ -273,18 +441,18 @@ 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 3.6 and above"
```Python hl_lines="31 37"
{!> ../../../docs_src/response_model/tutorial005.py!}
```
=== "Python 3.10 and above"
=== "Python 3.10+"
```Python hl_lines="29 35"
{!> ../../../docs_src/response_model/tutorial005_py310.py!}
```
=== "Python 3.6+"
```Python hl_lines="31 37"
{!> ../../../docs_src/response_model/tutorial005.py!}
```
!!! tip
The syntax `{"name", "description"}` creates a `set` with those two values.
@@ -294,18 +462,18 @@ 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 3.6 and above"
```Python hl_lines="31 37"
{!> ../../../docs_src/response_model/tutorial006.py!}
```
=== "Python 3.10 and above"
=== "Python 3.10+"
```Python hl_lines="29 35"
{!> ../../../docs_src/response_model/tutorial006_py310.py!}
```
=== "Python 3.6+"
```Python hl_lines="31 37"
{!> ../../../docs_src/response_model/tutorial006.py!}
```
## Recap
Use the *path operation decorator's* parameter `response_model` to define response models and especially to ensure private data is filtered out.

View File

@@ -8,18 +8,18 @@ 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 3.6 and above"
```Python hl_lines="15-23"
{!> ../../../docs_src/schema_extra_example/tutorial001.py!}
```
=== "Python 3.10 and above"
=== "Python 3.10+"
```Python hl_lines="13-21"
{!> ../../../docs_src/schema_extra_example/tutorial001_py310.py!}
```
=== "Python 3.6+"
```Python hl_lines="15-23"
{!> ../../../docs_src/schema_extra_example/tutorial001.py!}
```
That extra info will be added as-is to the output **JSON Schema** for that model, and it will be used in the API docs.
!!! tip
@@ -33,18 +33,18 @@ 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 3.6 and above"
```Python hl_lines="4 10-13"
{!> ../../../docs_src/schema_extra_example/tutorial002.py!}
```
=== "Python 3.10 and above"
=== "Python 3.10+"
```Python hl_lines="2 8-11"
{!> ../../../docs_src/schema_extra_example/tutorial002_py310.py!}
```
=== "Python 3.6+"
```Python hl_lines="4 10-13"
{!> ../../../docs_src/schema_extra_example/tutorial002.py!}
```
!!! warning
Keep in mind that those extra arguments passed won't add any validation, only extra information, for documentation purposes.
@@ -66,18 +66,39 @@ 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 3.6 and above"
=== "Python 3.10+"
```Python hl_lines="20-25"
{!> ../../../docs_src/schema_extra_example/tutorial003.py!}
```Python hl_lines="22-27"
{!> ../../../docs_src/schema_extra_example/tutorial003_an_py310.py!}
```
=== "Python 3.10 and above"
=== "Python 3.9+"
```Python hl_lines="22-27"
{!> ../../../docs_src/schema_extra_example/tutorial003_an_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="23-28"
{!> ../../../docs_src/schema_extra_example/tutorial003_an.py!}
```
=== "Python 3.10+ non-Annotated"
```Python hl_lines="18-23"
{!> ../../../docs_src/schema_extra_example/tutorial003_py310.py!}
```
=== "Python 3.6+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="20-25"
{!> ../../../docs_src/schema_extra_example/tutorial003.py!}
```
### Example in the docs UI
With any of the methods above it would look like this in the `/docs`:
@@ -97,18 +118,39 @@ 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 3.6 and above"
=== "Python 3.10+"
```Python hl_lines="21-47"
{!> ../../../docs_src/schema_extra_example/tutorial004.py!}
```Python hl_lines="23-49"
{!> ../../../docs_src/schema_extra_example/tutorial004_an_py310.py!}
```
=== "Python 3.10 and above"
=== "Python 3.9+"
```Python hl_lines="23-49"
{!> ../../../docs_src/schema_extra_example/tutorial004_an_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="24-50"
{!> ../../../docs_src/schema_extra_example/tutorial004_an.py!}
```
=== "Python 3.10+ non-Annotated"
```Python hl_lines="19-45"
{!> ../../../docs_src/schema_extra_example/tutorial004_py310.py!}
```
=== "Python 3.6+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="21-47"
{!> ../../../docs_src/schema_extra_example/tutorial004.py!}
```
### Examples in the docs UI
With `examples` added to `Body()` the `/docs` would look like:

View File

@@ -20,9 +20,27 @@ Let's first just use the code and see how it works, and then we'll come back to
Copy the example in a file `main.py`:
```Python
{!../../../docs_src/security/tutorial001.py!}
```
=== "Python 3.9+"
```Python
{!> ../../../docs_src/security/tutorial001_an_py39.py!}
```
=== "Python 3.6+"
```Python
{!> ../../../docs_src/security/tutorial001_an.py!}
```
=== "Python 3.6+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python
{!> ../../../docs_src/security/tutorial001.py!}
```
## Run it
@@ -116,9 +134,26 @@ In this example we are going to use **OAuth2**, with the **Password** flow, usin
When we create an instance of the `OAuth2PasswordBearer` class we pass in the `tokenUrl` parameter. This parameter contains the URL that the client (the frontend running in the user's browser) will use to send the `username` and `password` in order to get a token.
```Python hl_lines="6"
{!../../../docs_src/security/tutorial001.py!}
```
=== "Python 3.9+"
```Python hl_lines="8"
{!> ../../../docs_src/security/tutorial001_an_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="7"
{!> ../../../docs_src/security/tutorial001_an.py!}
```
=== "Python 3.6+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="6"
{!> ../../../docs_src/security/tutorial001.py!}
```
!!! tip
Here `tokenUrl="token"` refers to a relative URL `token` that we haven't created yet. As it's a relative URL, it's equivalent to `./token`.
@@ -150,9 +185,26 @@ So, it can be used with `Depends`.
Now you can pass that `oauth2_scheme` in a dependency with `Depends`.
```Python hl_lines="10"
{!../../../docs_src/security/tutorial001.py!}
```
=== "Python 3.9+"
```Python hl_lines="12"
{!> ../../../docs_src/security/tutorial001_an_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="11"
{!> ../../../docs_src/security/tutorial001_an.py!}
```
=== "Python 3.6+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="10"
{!> ../../../docs_src/security/tutorial001.py!}
```
This dependency will provide a `str` that is assigned to the parameter `token` of the *path operation function*.

View File

@@ -2,9 +2,26 @@
In the previous chapter the security system (which is based on the dependency injection system) was giving the *path operation function* a `token` as a `str`:
```Python hl_lines="10"
{!../../../docs_src/security/tutorial001.py!}
```
=== "Python 3.9+"
```Python hl_lines="12"
{!> ../../../docs_src/security/tutorial001_an_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="11"
{!> ../../../docs_src/security/tutorial001_an.py!}
```
=== "Python 3.6+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="10"
{!> ../../../docs_src/security/tutorial001.py!}
```
But that is still not that useful.
@@ -16,18 +33,42 @@ First, let's create a Pydantic user model.
The same way we use Pydantic to declare bodies, we can use it anywhere else:
=== "Python 3.6 and above"
=== "Python 3.10+"
```Python hl_lines="5 12-16"
{!> ../../../docs_src/security/tutorial002.py!}
{!> ../../../docs_src/security/tutorial002_an_py310.py!}
```
=== "Python 3.10 and above"
=== "Python 3.9+"
```Python hl_lines="5 12-16"
{!> ../../../docs_src/security/tutorial002_an_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="5 13-17"
{!> ../../../docs_src/security/tutorial002_an.py!}
```
=== "Python 3.10+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="3 10-14"
{!> ../../../docs_src/security/tutorial002_py310.py!}
```
=== "Python 3.6+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="5 12-16"
{!> ../../../docs_src/security/tutorial002.py!}
```
## Create a `get_current_user` dependency
Let's create a dependency `get_current_user`.
@@ -38,50 +79,122 @@ 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 3.6 and above"
=== "Python 3.10+"
```Python hl_lines="25"
{!> ../../../docs_src/security/tutorial002.py!}
{!> ../../../docs_src/security/tutorial002_an_py310.py!}
```
=== "Python 3.10 and above"
=== "Python 3.9+"
```Python hl_lines="25"
{!> ../../../docs_src/security/tutorial002_an_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="26"
{!> ../../../docs_src/security/tutorial002_an.py!}
```
=== "Python 3.10+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="23"
{!> ../../../docs_src/security/tutorial002_py310.py!}
```
=== "Python 3.6+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="25"
{!> ../../../docs_src/security/tutorial002.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 3.6 and above"
=== "Python 3.10+"
```Python hl_lines="19-22 26-27"
{!> ../../../docs_src/security/tutorial002.py!}
{!> ../../../docs_src/security/tutorial002_an_py310.py!}
```
=== "Python 3.10 and above"
=== "Python 3.9+"
```Python hl_lines="19-22 26-27"
{!> ../../../docs_src/security/tutorial002_an_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="20-23 27-28"
{!> ../../../docs_src/security/tutorial002_an.py!}
```
=== "Python 3.10+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="17-20 24-25"
{!> ../../../docs_src/security/tutorial002_py310.py!}
```
=== "Python 3.6+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="19-22 26-27"
{!> ../../../docs_src/security/tutorial002.py!}
```
## Inject the current user
So now we can use the same `Depends` with our `get_current_user` in the *path operation*:
=== "Python 3.6 and above"
=== "Python 3.10+"
```Python hl_lines="31"
{!> ../../../docs_src/security/tutorial002.py!}
{!> ../../../docs_src/security/tutorial002_an_py310.py!}
```
=== "Python 3.10 and above"
=== "Python 3.9+"
```Python hl_lines="31"
{!> ../../../docs_src/security/tutorial002_an_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="32"
{!> ../../../docs_src/security/tutorial002_an.py!}
```
=== "Python 3.10+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="29"
{!> ../../../docs_src/security/tutorial002_py310.py!}
```
=== "Python 3.6+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="31"
{!> ../../../docs_src/security/tutorial002.py!}
```
Notice that we declare the type of `current_user` as the Pydantic model `User`.
This will help us inside of the function with all the completion and type checks.
@@ -128,18 +241,42 @@ 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 3.6 and above"
=== "Python 3.10+"
```Python hl_lines="30-32"
{!> ../../../docs_src/security/tutorial002.py!}
{!> ../../../docs_src/security/tutorial002_an_py310.py!}
```
=== "Python 3.10 and above"
=== "Python 3.9+"
```Python hl_lines="30-32"
{!> ../../../docs_src/security/tutorial002_an_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="31-33"
{!> ../../../docs_src/security/tutorial002_an.py!}
```
=== "Python 3.10+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="28-30"
{!> ../../../docs_src/security/tutorial002_py310.py!}
```
=== "Python 3.6+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="30-32"
{!> ../../../docs_src/security/tutorial002.py!}
```
## Recap
You can now get the current user directly in your *path operation function*.

View File

@@ -109,18 +109,42 @@ And another utility to verify if a received password matches the hash stored.
And another one to authenticate and return a user.
=== "Python 3.6 and above"
=== "Python 3.10+"
```Python hl_lines="7 48 55-56 59-60 69-75"
{!> ../../../docs_src/security/tutorial004.py!}
{!> ../../../docs_src/security/tutorial004_an_py310.py!}
```
=== "Python 3.10 and above"
=== "Python 3.9+"
```Python hl_lines="7 48 55-56 59-60 69-75"
{!> ../../../docs_src/security/tutorial004_an_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="7 49 56-57 60-61 70-76"
{!> ../../../docs_src/security/tutorial004_an.py!}
```
=== "Python 3.10+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="6 47 54-55 58-59 68-74"
{!> ../../../docs_src/security/tutorial004_py310.py!}
```
=== "Python 3.6+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="7 48 55-56 59-60 69-75"
{!> ../../../docs_src/security/tutorial004.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"`.
@@ -152,18 +176,42 @@ 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 3.6 and above"
=== "Python 3.10+"
```Python hl_lines="6 12-14 28-30 78-86"
{!> ../../../docs_src/security/tutorial004.py!}
{!> ../../../docs_src/security/tutorial004_an_py310.py!}
```
=== "Python 3.10 and above"
=== "Python 3.9+"
```Python hl_lines="6 12-14 28-30 78-86"
{!> ../../../docs_src/security/tutorial004_an_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="6 13-15 29-31 79-87"
{!> ../../../docs_src/security/tutorial004_an.py!}
```
=== "Python 3.10+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="5 11-13 27-29 77-85"
{!> ../../../docs_src/security/tutorial004_py310.py!}
```
=== "Python 3.6+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="6 12-14 28-30 78-86"
{!> ../../../docs_src/security/tutorial004.py!}
```
## Update the dependencies
Update `get_current_user` to receive the same token as before, but this time, using JWT tokens.
@@ -172,36 +220,84 @@ Decode the received token, verify it, and return the current user.
If the token is invalid, return an HTTP error right away.
=== "Python 3.6 and above"
=== "Python 3.10+"
```Python hl_lines="89-106"
{!> ../../../docs_src/security/tutorial004.py!}
{!> ../../../docs_src/security/tutorial004_an_py310.py!}
```
=== "Python 3.10 and above"
=== "Python 3.9+"
```Python hl_lines="89-106"
{!> ../../../docs_src/security/tutorial004_an_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="90-107"
{!> ../../../docs_src/security/tutorial004_an.py!}
```
=== "Python 3.10+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="88-105"
{!> ../../../docs_src/security/tutorial004_py310.py!}
```
=== "Python 3.6+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="89-106"
{!> ../../../docs_src/security/tutorial004.py!}
```
## Update the `/token` *path operation*
Create a `timedelta` with the expiration time of the token.
Create a real JWT access token and return it.
Create a real JWT access token and return it
=== "Python 3.6 and above"
=== "Python 3.10+"
```Python hl_lines="115-128"
{!> ../../../docs_src/security/tutorial004.py!}
```Python hl_lines="117-132"
{!> ../../../docs_src/security/tutorial004_an_py310.py!}
```
=== "Python 3.10 and above"
=== "Python 3.9+"
```Python hl_lines="117-132"
{!> ../../../docs_src/security/tutorial004_an_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="118-133"
{!> ../../../docs_src/security/tutorial004_an.py!}
```
=== "Python 3.10+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="114-127"
{!> ../../../docs_src/security/tutorial004_py310.py!}
```
=== "Python 3.6+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="115-128"
{!> ../../../docs_src/security/tutorial004.py!}
```
### Technical details about the JWT "subject" `sub`
The JWT specification says that there's a key `sub`, with the subject of the token.
@@ -257,7 +353,7 @@ Call the endpoint `/users/me/`, you will get the response as:
<img src="/img/tutorial/security/image09.png">
If you open the developer tools, you could see how the data sent and only includes the token, the password is only sent in the first request to authenticate the user and get that access token, but not afterwards:
If you open the developer tools, you could see how the data sent only includes the token, the password is only sent in the first request to authenticate the user and get that access token, but not afterwards:
<img src="/img/tutorial/security/image10.png">

View File

@@ -49,18 +49,42 @@ 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 3.6 and above"
=== "Python 3.10+"
```Python hl_lines="4 76"
{!> ../../../docs_src/security/tutorial003.py!}
```Python hl_lines="4 78"
{!> ../../../docs_src/security/tutorial003_an_py310.py!}
```
=== "Python 3.10 and above"
=== "Python 3.9+"
```Python hl_lines="4 78"
{!> ../../../docs_src/security/tutorial003_an_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="4 79"
{!> ../../../docs_src/security/tutorial003_an.py!}
```
=== "Python 3.10+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="2 74"
{!> ../../../docs_src/security/tutorial003_py310.py!}
```
=== "Python 3.6+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="4 76"
{!> ../../../docs_src/security/tutorial003.py!}
```
`OAuth2PasswordRequestForm` is a class dependency that declares a form body with:
* The `username`.
@@ -98,18 +122,42 @@ If there is no such user, we return an error saying "incorrect username or passw
For the error, we use the exception `HTTPException`:
=== "Python 3.6 and above"
=== "Python 3.10+"
```Python hl_lines="3 77-79"
{!> ../../../docs_src/security/tutorial003.py!}
```Python hl_lines="3 79-81"
{!> ../../../docs_src/security/tutorial003_an_py310.py!}
```
=== "Python 3.10 and above"
=== "Python 3.9+"
```Python hl_lines="3 79-81"
{!> ../../../docs_src/security/tutorial003_an_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="3 80-82"
{!> ../../../docs_src/security/tutorial003_an.py!}
```
=== "Python 3.10+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="1 75-77"
{!> ../../../docs_src/security/tutorial003_py310.py!}
```
=== "Python 3.6+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="3 77-79"
{!> ../../../docs_src/security/tutorial003.py!}
```
### Check the password
At this point we have the user data from our database, but we haven't checked the password.
@@ -134,18 +182,42 @@ 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 3.6 and above"
=== "Python 3.10+"
```Python hl_lines="80-83"
{!> ../../../docs_src/security/tutorial003.py!}
```Python hl_lines="82-85"
{!> ../../../docs_src/security/tutorial003_an_py310.py!}
```
=== "Python 3.10 and above"
=== "Python 3.9+"
```Python hl_lines="82-85"
{!> ../../../docs_src/security/tutorial003_an_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="83-86"
{!> ../../../docs_src/security/tutorial003_an.py!}
```
=== "Python 3.10+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="78-81"
{!> ../../../docs_src/security/tutorial003_py310.py!}
```
=== "Python 3.6+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="80-83"
{!> ../../../docs_src/security/tutorial003.py!}
```
#### About `**user_dict`
`UserInDB(**user_dict)` means:
@@ -180,18 +252,42 @@ 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 3.6 and above"
=== "Python 3.10+"
```Python hl_lines="85"
{!> ../../../docs_src/security/tutorial003.py!}
```Python hl_lines="87"
{!> ../../../docs_src/security/tutorial003_an_py310.py!}
```
=== "Python 3.10 and above"
=== "Python 3.9+"
```Python hl_lines="87"
{!> ../../../docs_src/security/tutorial003_an_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="88"
{!> ../../../docs_src/security/tutorial003_an.py!}
```
=== "Python 3.10+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="83"
{!> ../../../docs_src/security/tutorial003_py310.py!}
```
=== "Python 3.6+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="85"
{!> ../../../docs_src/security/tutorial003.py!}
```
!!! tip
By the spec, you should return a JSON with an `access_token` and a `token_type`, the same as in this example.
@@ -213,18 +309,42 @@ 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 3.6 and above"
=== "Python 3.10+"
```Python hl_lines="58-66 69-74 94"
{!> ../../../docs_src/security/tutorial003_an_py310.py!}
```
=== "Python 3.9+"
```Python hl_lines="58-66 69-74 94"
{!> ../../../docs_src/security/tutorial003_an_py39.py!}
```
=== "Python 3.6+"
```Python hl_lines="59-67 70-75 95"
{!> ../../../docs_src/security/tutorial003_an.py!}
```
=== "Python 3.10+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="56-64 67-70 88"
{!> ../../../docs_src/security/tutorial003_py310.py!}
```
=== "Python 3.6+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```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

@@ -262,22 +262,22 @@ 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 3.6 and above"
=== "Python 3.10+"
```Python hl_lines="3 6-8 11-12 23-24 27-28"
{!> ../../../docs_src/sql_databases/sql_app/schemas.py!}
```Python hl_lines="1 4-6 9-10 21-22 25-26"
{!> ../../../docs_src/sql_databases/sql_app_py310/schemas.py!}
```
=== "Python 3.9 and above"
=== "Python 3.9+"
```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 3.6+"
```Python hl_lines="1 4-6 9-10 21-22 25-26"
{!> ../../../docs_src/sql_databases/sql_app_py310/schemas.py!}
```Python hl_lines="3 6-8 11-12 23-24 27-28"
{!> ../../../docs_src/sql_databases/sql_app/schemas.py!}
```
#### SQLAlchemy style and Pydantic style
@@ -306,22 +306,22 @@ 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 3.6 and above"
=== "Python 3.10+"
```Python hl_lines="15-17 31-34"
{!> ../../../docs_src/sql_databases/sql_app/schemas.py!}
```Python hl_lines="13-15 29-32"
{!> ../../../docs_src/sql_databases/sql_app_py310/schemas.py!}
```
=== "Python 3.9 and above"
=== "Python 3.9+"
```Python hl_lines="15-17 31-34"
{!> ../../../docs_src/sql_databases/sql_app_py39/schemas.py!}
```
=== "Python 3.10 and above"
=== "Python 3.6+"
```Python hl_lines="13-15 29-32"
{!> ../../../docs_src/sql_databases/sql_app_py310/schemas.py!}
```Python hl_lines="15-17 31-34"
{!> ../../../docs_src/sql_databases/sql_app/schemas.py!}
```
!!! tip
@@ -335,22 +335,22 @@ This <a href="https://pydantic-docs.helpmanual.io/usage/model_config/" class="ex
In the `Config` class, set the attribute `orm_mode = True`.
=== "Python 3.6 and above"
=== "Python 3.10+"
```Python hl_lines="15 19-20 31 36-37"
{!> ../../../docs_src/sql_databases/sql_app/schemas.py!}
```Python hl_lines="13 17-18 29 34-35"
{!> ../../../docs_src/sql_databases/sql_app_py310/schemas.py!}
```
=== "Python 3.9 and above"
=== "Python 3.9+"
```Python hl_lines="15 19-20 31 36-37"
{!> ../../../docs_src/sql_databases/sql_app_py39/schemas.py!}
```
=== "Python 3.10 and above"
=== "Python 3.6+"
```Python hl_lines="13 17-18 29 34-35"
{!> ../../../docs_src/sql_databases/sql_app_py310/schemas.py!}
```Python hl_lines="15 19-20 31 36-37"
{!> ../../../docs_src/sql_databases/sql_app/schemas.py!}
```
!!! tip
@@ -481,18 +481,18 @@ 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 3.6 and above"
```Python hl_lines="9"
{!> ../../../docs_src/sql_databases/sql_app/main.py!}
```
=== "Python 3.9 and above"
=== "Python 3.9+"
```Python hl_lines="7"
{!> ../../../docs_src/sql_databases/sql_app_py39/main.py!}
```
=== "Python 3.6+"
```Python hl_lines="9"
{!> ../../../docs_src/sql_databases/sql_app/main.py!}
```
#### Alembic Note
Normally you would probably initialize your database (create tables, etc) with <a href="https://alembic.sqlalchemy.org/en/latest/" class="external-link" target="_blank">Alembic</a>.
@@ -515,18 +515,18 @@ 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 3.6 and above"
```Python hl_lines="15-20"
{!> ../../../docs_src/sql_databases/sql_app/main.py!}
```
=== "Python 3.9 and above"
=== "Python 3.9+"
```Python hl_lines="13-18"
{!> ../../../docs_src/sql_databases/sql_app_py39/main.py!}
```
=== "Python 3.6+"
```Python hl_lines="15-20"
{!> ../../../docs_src/sql_databases/sql_app/main.py!}
```
!!! info
We put the creation of the `SessionLocal()` and handling of the requests in a `try` block.
@@ -540,18 +540,18 @@ 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 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 3.9+"
```Python hl_lines="22 30 36 45 51"
{!> ../../../docs_src/sql_databases/sql_app_py39/main.py!}
```
=== "Python 3.6+"
```Python hl_lines="24 32 38 47 53"
{!> ../../../docs_src/sql_databases/sql_app/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.
@@ -561,18 +561,18 @@ This will then give us better editor support inside the *path operation function
Now, finally, here's the standard **FastAPI** *path operations* code.
=== "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 3.9+"
```Python hl_lines="21-26 29-32 35-40 43-47 50-53"
{!> ../../../docs_src/sql_databases/sql_app_py39/main.py!}
```
=== "Python 3.6+"
```Python hl_lines="23-28 31-34 37-42 45-49 52-55"
{!> ../../../docs_src/sql_databases/sql_app/main.py!}
```
We are creating the database session before each request in the dependency with `yield`, and then closing it afterwards.
And then we can create the required dependency in the *path operation function*, to get that session directly.
@@ -654,22 +654,22 @@ For example, in a background task worker with <a href="https://docs.celeryq.dev"
* `sql_app/schemas.py`:
=== "Python 3.6 and above"
=== "Python 3.10+"
```Python
{!> ../../../docs_src/sql_databases/sql_app/schemas.py!}
{!> ../../../docs_src/sql_databases/sql_app_py310/schemas.py!}
```
=== "Python 3.9 and above"
=== "Python 3.9+"
```Python
{!> ../../../docs_src/sql_databases/sql_app_py39/schemas.py!}
```
=== "Python 3.10 and above"
=== "Python 3.6+"
```Python
{!> ../../../docs_src/sql_databases/sql_app_py310/schemas.py!}
{!> ../../../docs_src/sql_databases/sql_app/schemas.py!}
```
* `sql_app/crud.py`:
@@ -680,18 +680,18 @@ For example, in a background task worker with <a href="https://docs.celeryq.dev"
* `sql_app/main.py`:
=== "Python 3.6 and above"
```Python
{!> ../../../docs_src/sql_databases/sql_app/main.py!}
```
=== "Python 3.9 and above"
=== "Python 3.9+"
```Python
{!> ../../../docs_src/sql_databases/sql_app_py39/main.py!}
```
=== "Python 3.6+"
```Python
{!> ../../../docs_src/sql_databases/sql_app/main.py!}
```
## Check it
You can copy this code and use it as is.
@@ -739,18 +739,18 @@ 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 3.6 and above"
```Python hl_lines="14-22"
{!> ../../../docs_src/sql_databases/sql_app/alt_main.py!}
```
=== "Python 3.9 and above"
=== "Python 3.9+"
```Python hl_lines="12-20"
{!> ../../../docs_src/sql_databases/sql_app_py39/alt_main.py!}
```
=== "Python 3.6+"
```Python hl_lines="14-22"
{!> ../../../docs_src/sql_databases/sql_app/alt_main.py!}
```
!!! info
We put the creation of the `SessionLocal()` and handling of the requests in a `try` block.

View File

@@ -2,16 +2,16 @@
Thanks to <a href="https://www.starlette.io/testclient/" class="external-link" target="_blank">Starlette</a>, testing **FastAPI** applications is easy and enjoyable.
It is based on <a href="https://requests.readthedocs.io" class="external-link" target="_blank">Requests</a>, so it's very familiar and intuitive.
It is based on <a href="https://www.python-httpx.org" class="external-link" target="_blank">HTTPX</a>, which in turn is designed based on Requests, so it's very familiar and intuitive.
With it, you can use <a href="https://docs.pytest.org/" class="external-link" target="_blank">pytest</a> directly with **FastAPI**.
## Using `TestClient`
!!! info
To use `TestClient`, first install <a href="https://github.com/psf/requests" class="external-link" target="_blank">`requests`</a>.
To use `TestClient`, first install <a href="https://www.python-httpx.org" class="external-link" target="_blank">`httpx`</a>.
E.g. `pip install requests`.
E.g. `pip install httpx`.
Import `TestClient`.
@@ -19,7 +19,7 @@ Create a `TestClient` by passing your **FastAPI** application to it.
Create functions with a name that starts with `test_` (this is standard `pytest` conventions).
Use the `TestClient` object the same way as you do with `requests`.
Use the `TestClient` object the same way as you do with `httpx`.
Write simple `assert` statements with the standard Python expressions that you need to check (again, standard `pytest`).
@@ -50,7 +50,17 @@ And your **FastAPI** application might also be composed of several files/modules
### **FastAPI** app file
Let's say you have a file `main.py` with your **FastAPI** app:
Let's say you have a file structure as described in [Bigger Applications](./bigger-applications.md){.internal-link target=_blank}:
```
.
├── app
│   ├── __init__.py
│   └── main.py
```
In the file `main.py` you have your **FastAPI** app:
```Python
{!../../../docs_src/app_testing/main.py!}
@@ -58,18 +68,40 @@ Let's say you have a file `main.py` with your **FastAPI** app:
### Testing file
Then you could have a file `test_main.py` with your tests, and import your `app` from the `main` module (`main.py`):
Then you could have a file `test_main.py` with your tests. It could live on the same Python package (the same directory with a `__init__.py` file):
```Python
``` hl_lines="5"
.
├── app
│   ├── __init__.py
│   ├── main.py
│   └── test_main.py
```
Because this file is in the same package, you can use relative imports to import the object `app` from the `main` module (`main.py`):
```Python hl_lines="3"
{!../../../docs_src/app_testing/test_main.py!}
```
...and have the code for the tests just like before.
## Testing: extended example
Now let's extend this example and add more details to see how to test different parts.
### Extended **FastAPI** app file
Let's continue with the same file structure as before:
```
.
├── app
│   ├── __init__.py
│   ├── main.py
│   └── test_main.py
```
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.
@@ -78,18 +110,42 @@ It has a `POST` operation that could return several errors.
Both *path operations* require an `X-Token` header.
=== "Python 3.6 and above"
=== "Python 3.10+"
```Python
{!> ../../../docs_src/app_testing/app_b/main.py!}
{!> ../../../docs_src/app_testing/app_b_an_py310/main.py!}
```
=== "Python 3.10 and above"
=== "Python 3.9+"
```Python
{!> ../../../docs_src/app_testing/app_b_an_py39/main.py!}
```
=== "Python 3.6+"
```Python
{!> ../../../docs_src/app_testing/app_b_an/main.py!}
```
=== "Python 3.10+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python
{!> ../../../docs_src/app_testing/app_b_py310/main.py!}
```
=== "Python 3.6+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python
{!> ../../../docs_src/app_testing/app_b/main.py!}
```
### Extended testing file
You could then update `test_main.py` with the extended tests:
@@ -98,7 +154,7 @@ You could then update `test_main.py` with the extended tests:
{!> ../../../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`.
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 `httpx`, or even how to do it with `requests`, as HTTPX's design is based on Requests' design.
Then you just do the same in your tests.
@@ -110,7 +166,7 @@ E.g.:
* To pass *headers*, use a `dict` in the `headers` parameter.
* For *cookies*, a `dict` in the `cookies` parameter.
For more information about how to pass data to the backend (using `requests` or the `TestClient`) check the <a href="https://requests.readthedocs.io" class="external-link" target="_blank">Requests documentation</a>.
For more information about how to pass data to the backend (using `httpx` or the `TestClient`) check the <a href="https://www.python-httpx.org" class="external-link" target="_blank">HTTPX documentation</a>.
!!! info
Note that the `TestClient` receives data that can be converted to JSON, not Pydantic models.

View File

@@ -45,6 +45,7 @@ nav:
- fa: /fa/
- fr: /fr/
- he: /he/
- hy: /hy/
- id: /id/
- it: /it/
- ja: /ja/
@@ -55,6 +56,7 @@ nav:
- ru: /ru/
- sq: /sq/
- sv: /sv/
- ta: /ta/
- tr: /tr/
- uk: /uk/
- zh: /zh/
@@ -187,7 +189,7 @@ markdown_extensions:
extra:
analytics:
provider: google
property: UA-133183413-1
property: G-YNEVN69SC3
social:
- icon: fontawesome/brands/github-alt
link: https://github.com/tiangolo/fastapi
@@ -218,6 +220,8 @@ extra:
name: fr - français
- link: /he/
name: he
- link: /hy/
name: hy
- link: /id/
name: id
- link: /it/
@@ -238,6 +242,8 @@ extra:
name: sq - shqip
- link: /sv/
name: sv - svenska
- link: /ta/
name: ta - தமிழ்
- link: /tr/
name: tr - Türkçe
- link: /uk/

View File

@@ -22,12 +22,6 @@
</div>
</div>
<div id="announce-right" style="position: relative;">
<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.png" />
</a>
</div>
<div class="item">
<a title="The data structure for unstructured multimodal data" style="display: block; position: relative;" href="https://bit.ly/3AcNTYL" target="_blank">
<span class="sponsor-badge">sponsor</span>
@@ -40,18 +34,6 @@
<img class="sponsor-image" src="/img/sponsors/cryptapi-banner.svg" />
</a>
</div>
<div class="item">
<a title="The ultimate solution to unlimited and forever cloud storage." style="display: block; position: relative;" href="https://app.imgwhale.xyz/" target="_blank">
<span class="sponsor-badge">sponsor</span>
<img class="sponsor-image" src="/img/sponsors/imgwhale-banner.svg" />
</a>
</div>
<div class="item">
<a title="Help us migrate doist to FastAPI" style="display: block; position: relative;" href="https://doist.com/careers/9B437B1615-wa-senior-backend-engineer-python" target="_blank">
<span class="sponsor-badge">sponsor</span>
<img class="sponsor-image" src="/img/sponsors/doist-banner.svg" />
</a>
</div>
<div class="item">
<a title="Build cross-modal and multimodal applications on the cloud" style="display: block; position: relative;" href="https://bit.ly/3dphxRq" target="_blank">
<span class="sponsor-badge">sponsor</span>

View File

@@ -167,7 +167,7 @@ Con **FastAPI** obtienes todas las características de **Starlette** (porque Fas
* Soporte para **GraphQL**.
* <abbr title="En español: tareas que se ejecutan en el fondo, sin frenar requests, en el mismo proceso. En ingles: In-process background tasks">Tareas en background</abbr>.
* Eventos de startup y shutdown.
* Cliente de pruebas construido con `requests`.
* Cliente de pruebas construido con HTTPX.
* **CORS**, GZip, Static Files, Streaming responses.
* Soporte para **Session and Cookie**.
* Cobertura de pruebas al 100%.

View File

@@ -106,7 +106,7 @@ Si estás construyendo un app de <abbr title="Interfaz de línea de comandos en
## Requisitos
Python 3.6+
Python 3.7+
FastAPI está sobre los hombros de gigantes:
@@ -418,7 +418,7 @@ Para un ejemplo más completo que incluye más características ve el <a href="h
* Muchas características extra (gracias a Starlette) como:
* **WebSockets**
* **GraphQL**
* pruebas extremadamente fáciles con `requests` y `pytest`
* pruebas extremadamente fáciles con HTTPX y `pytest`
* **CORS**
* **Cookie Sessions**
* ...y mucho más.
@@ -438,7 +438,7 @@ Usadas por Pydantic:
Usados por Starlette:
* <a href="https://requests.readthedocs.io" target="_blank"><code>requests</code></a> - Requerido si quieres usar el `TestClient`.
* <a href="https://www.python-httpx.org" target="_blank"><code>httpx</code></a> - Requerido si quieres usar el `TestClient`.
* <a href="https://jinja.palletsprojects.com" target="_blank"><code>jinja2</code></a> - Requerido si quieres usar la configuración por defecto de templates.
* <a href="https://andrew-d.github.io/python-multipart/" target="_blank"><code>python-multipart</code></a> - Requerido si quieres dar soporte a <abbr title="convertir el string que viene de un HTTP request a datos de Python">"parsing"</abbr> de formularios, con `request.form()`.
* <a href="https://pythonhosted.org/itsdangerous/" target="_blank"><code>itsdangerous</code></a> - Requerido para dar soporte a `SessionMiddleware`.

View File

@@ -45,6 +45,7 @@ nav:
- fa: /fa/
- fr: /fr/
- he: /he/
- hy: /hy/
- id: /id/
- it: /it/
- ja: /ja/
@@ -55,6 +56,7 @@ nav:
- ru: /ru/
- sq: /sq/
- sv: /sv/
- ta: /ta/
- tr: /tr/
- uk: /uk/
- zh: /zh/
@@ -90,7 +92,7 @@ markdown_extensions:
extra:
analytics:
provider: google
property: UA-133183413-1
property: G-YNEVN69SC3
social:
- icon: fontawesome/brands/github-alt
link: https://github.com/tiangolo/fastapi
@@ -121,6 +123,8 @@ extra:
name: fr - français
- link: /he/
name: he
- link: /hy/
name: hy
- link: /id/
name: id
- link: /it/
@@ -141,6 +145,8 @@ extra:
name: sq - shqip
- link: /sv/
name: sv - svenska
- link: /ta/
name: ta - தமிழ்
- link: /tr/
name: tr - Türkçe
- link: /uk/

View File

@@ -421,7 +421,7 @@ item: Item
* قابلیت‌های اضافی دیگر (بر اساس Starlette) شامل:
* **<abbr title="WebSocket">وب‌سوکت</abbr>**
* **GraphQL**
* تست‌های خودکار آسان مبتنی بر `requests` و `pytest`
* تست‌های خودکار آسان مبتنی بر HTTPX و `pytest`
* **CORS**
* **Cookie Sessions**
* و موارد بیشمار دیگر.
@@ -441,7 +441,7 @@ item: Item
استفاده شده توسط Starlette:
* <a href="https://requests.readthedocs.io" target="_blank"><code>requests</code></a> - در صورتی که می‌خواهید از `TestClient` استفاده کنید.
* <a href="https://www.python-httpx.org" target="_blank"><code>HTTPX</code></a> - در صورتی که می‌خواهید از `TestClient` استفاده کنید.
* <a href="https://github.com/Tinche/aiofiles" target="_blank"><code>aiofiles</code></a> - در صورتی که می‌خواهید از `FileResponse` و `StaticFiles` استفاده کنید.
* <a href="https://jinja.palletsprojects.com" target="_blank"><code>jinja2</code></a> - در صورتی که بخواهید از پیکربندی پیش‌فرض برای قالب‌ها استفاده کنید.
* <a href="https://andrew-d.github.io/python-multipart/" target="_blank"><code>python-multipart</code></a> - در صورتی که بخواهید با استفاده از `request.form()` از قابلیت <abbr title="تبدیل رشته متنی موجود در درخواست HTTP به انواع داده پایتون">"تجزیه (parse)"</abbr> فرم استفاده کنید.

View File

@@ -45,6 +45,7 @@ nav:
- fa: /fa/
- fr: /fr/
- he: /he/
- hy: /hy/
- id: /id/
- it: /it/
- ja: /ja/
@@ -55,6 +56,7 @@ nav:
- ru: /ru/
- sq: /sq/
- sv: /sv/
- ta: /ta/
- tr: /tr/
- uk: /uk/
- zh: /zh/
@@ -80,7 +82,7 @@ markdown_extensions:
extra:
analytics:
provider: google
property: UA-133183413-1
property: G-YNEVN69SC3
social:
- icon: fontawesome/brands/github-alt
link: https://github.com/tiangolo/fastapi
@@ -111,6 +113,8 @@ extra:
name: fr - français
- link: /he/
name: he
- link: /hy/
name: hy
- link: /id/
name: id
- link: /it/
@@ -131,6 +135,8 @@ extra:
name: sq - shqip
- link: /sv/
name: sv - svenska
- link: /ta/
name: ta - தமிழ்
- link: /tr/
name: tr - Türkçe
- link: /uk/

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